-
-
Save sholtomaud/bafa2344b99fad117451 to your computer and use it in GitHub Desktop.
requirebin sketch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var fastn = require('fastn')({ | |
list: require('fastn/listComponent'), | |
text: require('fastn/textComponent'), | |
templater: require('fastn/templaterComponent'), | |
_generic: require('fastn/genericComponent'), | |
leaflet: require('leaflet-component/leafletComponent'), | |
marker: require('leaflet-component/leafletMarkerComponent') | |
}, true); | |
let markerModel = new fastn.Model({ | |
markers : [ | |
{ | |
gis_lat:-35.2834600 , | |
gis_lng: 149.9, | |
title: 'Hello fastn 1' | |
}, | |
{ | |
gis_lat:-35.5 , | |
gis_lng: 144.12, | |
title: 'Hello fastn 2' | |
}, | |
{ | |
gis_lat:-35.1 , | |
gis_lng: 149.125, | |
title: 'Hello fastn 3' | |
}, | |
{ | |
gis_lat:-35.9 , | |
gis_lng: 149.131, | |
title: 'Hello fastn 4' | |
} | |
] | |
}) | |
const app = fastn('div', {class:'map'}, | |
fastn('list:leaflet',{ | |
items: fastn.binding('markers').attach(markerModel), | |
template: function(){ | |
return fastn('base:marker', { | |
gis_lat: fastn.binding('gis_lat'), | |
gis_lng: fastn.binding('gis_lng'), | |
title: fastn.binding('title') | |
}).binding('item') | |
} | |
}) | |
) | |
app.render(); | |
document.body.appendChild(app.element); |
This file has been truncated, but you can view the full file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
setTimeout(function(){ | |
;require=(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 (global){ | |
/*! | |
* The buffer module from node.js, for the browser. | |
* | |
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> | |
* @license MIT | |
*/ | |
/* eslint-disable no-proto */ | |
'use strict' | |
var base64 = require('base64-js') | |
var ieee754 = require('ieee754') | |
var isArray = require('isarray') | |
exports.Buffer = Buffer | |
exports.SlowBuffer = SlowBuffer | |
exports.INSPECT_MAX_BYTES = 50 | |
Buffer.poolSize = 8192 // not used by this implementation | |
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+. | |
* | |
* Due to various browser bugs, sometimes the Object implementation will be used even | |
* when the browser supports typed arrays. | |
* | |
* Note: | |
* | |
* - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, | |
* See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. | |
* | |
* - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property | |
* on objects. | |
* | |
* - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. | |
* | |
* - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of | |
* incorrect length in some situations. | |
* We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they | |
* get the Object implementation, which is slower but behaves correctly. | |
*/ | |
Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined | |
? global.TYPED_ARRAY_SUPPORT | |
: typedArraySupport() | |
function typedArraySupport () { | |
function Bar () {} | |
try { | |
var arr = new Uint8Array(1) | |
arr.foo = function () { return 42 } | |
arr.constructor = Bar | |
return arr.foo() === 42 && // typed array instances can be augmented | |
arr.constructor === Bar && // constructor can be set | |
typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` | |
arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` | |
} catch (e) { | |
return false | |
} | |
} | |
function kMaxLength () { | |
return Buffer.TYPED_ARRAY_SUPPORT | |
? 0x7fffffff | |
: 0x3fffffff | |
} | |
/** | |
* 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 (arg) { | |
if (!(this instanceof Buffer)) { | |
// Avoid going through an ArgumentsAdaptorTrampoline in the common case. | |
if (arguments.length > 1) return new Buffer(arg, arguments[1]) | |
return new Buffer(arg) | |
} | |
if (!Buffer.TYPED_ARRAY_SUPPORT) { | |
this.length = 0 | |
this.parent = undefined | |
} | |
// Common case. | |
if (typeof arg === 'number') { | |
return fromNumber(this, arg) | |
} | |
// Slightly less common case. | |
if (typeof arg === 'string') { | |
return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8') | |
} | |
// Unusual. | |
return fromObject(this, arg) | |
} | |
function fromNumber (that, length) { | |
that = allocate(that, length < 0 ? 0 : checked(length) | 0) | |
if (!Buffer.TYPED_ARRAY_SUPPORT) { | |
for (var i = 0; i < length; i++) { | |
that[i] = 0 | |
} | |
} | |
return that | |
} | |
function fromString (that, string, encoding) { | |
if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8' | |
// Assumption: byteLength() return value is always < kMaxLength. | |
var length = byteLength(string, encoding) | 0 | |
that = allocate(that, length) | |
that.write(string, encoding) | |
return that | |
} | |
function fromObject (that, object) { | |
if (Buffer.isBuffer(object)) return fromBuffer(that, object) | |
if (isArray(object)) return fromArray(that, object) | |
if (object == null) { | |
throw new TypeError('must start with number, buffer, array or string') | |
} | |
if (typeof ArrayBuffer !== 'undefined') { | |
if (object.buffer instanceof ArrayBuffer) { | |
return fromTypedArray(that, object) | |
} | |
if (object instanceof ArrayBuffer) { | |
return fromArrayBuffer(that, object) | |
} | |
} | |
if (object.length) return fromArrayLike(that, object) | |
return fromJsonObject(that, object) | |
} | |
function fromBuffer (that, buffer) { | |
var length = checked(buffer.length) | 0 | |
that = allocate(that, length) | |
buffer.copy(that, 0, 0, length) | |
return that | |
} | |
function fromArray (that, array) { | |
var length = checked(array.length) | 0 | |
that = allocate(that, length) | |
for (var i = 0; i < length; i += 1) { | |
that[i] = array[i] & 255 | |
} | |
return that | |
} | |
// Duplicate of fromArray() to keep fromArray() monomorphic. | |
function fromTypedArray (that, array) { | |
var length = checked(array.length) | 0 | |
that = allocate(that, length) | |
// Truncating the elements is probably not what people expect from typed | |
// arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior | |
// of the old Buffer constructor. | |
for (var i = 0; i < length; i += 1) { | |
that[i] = array[i] & 255 | |
} | |
return that | |
} | |
function fromArrayBuffer (that, array) { | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
// Return an augmented `Uint8Array` instance, for best performance | |
array.byteLength | |
that = Buffer._augment(new Uint8Array(array)) | |
} else { | |
// Fallback: Return an object instance of the Buffer class | |
that = fromTypedArray(that, new Uint8Array(array)) | |
} | |
return that | |
} | |
function fromArrayLike (that, array) { | |
var length = checked(array.length) | 0 | |
that = allocate(that, length) | |
for (var i = 0; i < length; i += 1) { | |
that[i] = array[i] & 255 | |
} | |
return that | |
} | |
// Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object. | |
// Returns a zero-length buffer for inputs that don't conform to the spec. | |
function fromJsonObject (that, object) { | |
var array | |
var length = 0 | |
if (object.type === 'Buffer' && isArray(object.data)) { | |
array = object.data | |
length = checked(array.length) | 0 | |
} | |
that = allocate(that, length) | |
for (var i = 0; i < length; i += 1) { | |
that[i] = array[i] & 255 | |
} | |
return that | |
} | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
Buffer.prototype.__proto__ = Uint8Array.prototype | |
Buffer.__proto__ = Uint8Array | |
} else { | |
// pre-set for values that may exist in the future | |
Buffer.prototype.length = undefined | |
Buffer.prototype.parent = undefined | |
} | |
function allocate (that, length) { | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
// Return an augmented `Uint8Array` instance, for best performance | |
that = Buffer._augment(new Uint8Array(length)) | |
that.__proto__ = Buffer.prototype | |
} else { | |
// Fallback: Return an object instance of the Buffer class | |
that.length = length | |
that._isBuffer = true | |
} | |
var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1 | |
if (fromPool) that.parent = rootParent | |
return that | |
} | |
function checked (length) { | |
// Note: cannot use `length < kMaxLength` here because that fails when | |
// length is NaN (which is otherwise coerced to zero.) | |
if (length >= kMaxLength()) { | |
throw new RangeError('Attempt to allocate Buffer larger than maximum ' + | |
'size: 0x' + kMaxLength().toString(16) + ' bytes') | |
} | |
return length | 0 | |
} | |
function SlowBuffer (subject, encoding) { | |
if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding) | |
var buf = new Buffer(subject, encoding) | |
delete buf.parent | |
return buf | |
} | |
Buffer.isBuffer = function isBuffer (b) { | |
return !!(b != null && b._isBuffer) | |
} | |
Buffer.compare = function compare (a, b) { | |
if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { | |
throw new TypeError('Arguments must be Buffers') | |
} | |
if (a === b) return 0 | |
var x = a.length | |
var y = b.length | |
var i = 0 | |
var len = Math.min(x, y) | |
while (i < len) { | |
if (a[i] !== b[i]) break | |
++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 isEncoding (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 concat (list, length) { | |
if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.') | |
if (list.length === 0) { | |
return new Buffer(0) | |
} | |
var i | |
if (length === undefined) { | |
length = 0 | |
for (i = 0; i < list.length; i++) { | |
length += list[i].length | |
} | |
} | |
var buf = new Buffer(length) | |
var pos = 0 | |
for (i = 0; i < list.length; i++) { | |
var item = list[i] | |
item.copy(buf, pos) | |
pos += item.length | |
} | |
return buf | |
} | |
function byteLength (string, encoding) { | |
if (typeof string !== 'string') string = '' + string | |
var len = string.length | |
if (len === 0) return 0 | |
// Use a for loop to avoid recursion | |
var loweredCase = false | |
for (;;) { | |
switch (encoding) { | |
case 'ascii': | |
case 'binary': | |
// Deprecated | |
case 'raw': | |
case 'raws': | |
return len | |
case 'utf8': | |
case 'utf-8': | |
return utf8ToBytes(string).length | |
case 'ucs2': | |
case 'ucs-2': | |
case 'utf16le': | |
case 'utf-16le': | |
return len * 2 | |
case 'hex': | |
return len >>> 1 | |
case 'base64': | |
return base64ToBytes(string).length | |
default: | |
if (loweredCase) return utf8ToBytes(string).length // assume utf8 | |
encoding = ('' + encoding).toLowerCase() | |
loweredCase = true | |
} | |
} | |
} | |
Buffer.byteLength = byteLength | |
function slowToString (encoding, start, end) { | |
var loweredCase = false | |
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.toString = function toString () { | |
var length = this.length | 0 | |
if (length === 0) return '' | |
if (arguments.length === 0) return utf8Slice(this, 0, length) | |
return slowToString.apply(this, arguments) | |
} | |
Buffer.prototype.equals = function equals (b) { | |
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') | |
if (this === b) return true | |
return Buffer.compare(this, b) === 0 | |
} | |
Buffer.prototype.inspect = function inspect () { | |
var str = '' | |
var max = exports.INSPECT_MAX_BYTES | |
if (this.length > 0) { | |
str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') | |
if (this.length > max) str += ' ... ' | |
} | |
return '<Buffer ' + str + '>' | |
} | |
Buffer.prototype.compare = function compare (b) { | |
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') | |
if (this === b) return 0 | |
return Buffer.compare(this, b) | |
} | |
Buffer.prototype.indexOf = function indexOf (val, byteOffset) { | |
if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff | |
else if (byteOffset < -0x80000000) byteOffset = -0x80000000 | |
byteOffset >>= 0 | |
if (this.length === 0) return -1 | |
if (byteOffset >= this.length) return -1 | |
// Negative offsets start from the end of the buffer | |
if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0) | |
if (typeof val === 'string') { | |
if (val.length === 0) return -1 // special case: looking for empty string always fails | |
return String.prototype.indexOf.call(this, val, byteOffset) | |
} | |
if (Buffer.isBuffer(val)) { | |
return arrayIndexOf(this, val, byteOffset) | |
} | |
if (typeof val === 'number') { | |
if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') { | |
return Uint8Array.prototype.indexOf.call(this, val, byteOffset) | |
} | |
return arrayIndexOf(this, [ val ], byteOffset) | |
} | |
function arrayIndexOf (arr, val, byteOffset) { | |
var foundIndex = -1 | |
for (var i = 0; byteOffset + i < arr.length; i++) { | |
if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) { | |
if (foundIndex === -1) foundIndex = i | |
if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex | |
} else { | |
foundIndex = -1 | |
} | |
} | |
return -1 | |
} | |
throw new TypeError('val must be string, number or Buffer') | |
} | |
// `get` is deprecated | |
Buffer.prototype.get = function get (offset) { | |
console.log('.get() is deprecated. Access using array indexes instead.') | |
return this.readUInt8(offset) | |
} | |
// `set` is deprecated | |
Buffer.prototype.set = function set (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 parsed = parseInt(string.substr(i * 2, 2), 16) | |
if (isNaN(parsed)) throw new Error('Invalid hex string') | |
buf[offset + i] = parsed | |
} | |
return i | |
} | |
function utf8Write (buf, string, offset, length) { | |
return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) | |
} | |
function asciiWrite (buf, string, offset, length) { | |
return blitBuffer(asciiToBytes(string), buf, offset, length) | |
} | |
function binaryWrite (buf, string, offset, length) { | |
return asciiWrite(buf, string, offset, length) | |
} | |
function base64Write (buf, string, offset, length) { | |
return blitBuffer(base64ToBytes(string), buf, offset, length) | |
} | |
function ucs2Write (buf, string, offset, length) { | |
return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) | |
} | |
Buffer.prototype.write = function write (string, offset, length, encoding) { | |
// Buffer#write(string) | |
if (offset === undefined) { | |
encoding = 'utf8' | |
length = this.length | |
offset = 0 | |
// Buffer#write(string, encoding) | |
} else if (length === undefined && typeof offset === 'string') { | |
encoding = offset | |
length = this.length | |
offset = 0 | |
// Buffer#write(string, offset[, length][, encoding]) | |
} else if (isFinite(offset)) { | |
offset = offset | 0 | |
if (isFinite(length)) { | |
length = length | 0 | |
if (encoding === undefined) encoding = 'utf8' | |
} else { | |
encoding = length | |
length = undefined | |
} | |
// legacy write(string, encoding, offset, length) - remove in v0.13 | |
} else { | |
var swap = encoding | |
encoding = offset | |
offset = length | 0 | |
length = swap | |
} | |
var remaining = this.length - offset | |
if (length === undefined || length > remaining) length = remaining | |
if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { | |
throw new RangeError('attempt to write outside buffer bounds') | |
} | |
if (!encoding) encoding = 'utf8' | |
var loweredCase = false | |
for (;;) { | |
switch (encoding) { | |
case 'hex': | |
return hexWrite(this, string, offset, length) | |
case 'utf8': | |
case 'utf-8': | |
return utf8Write(this, string, offset, length) | |
case 'ascii': | |
return asciiWrite(this, string, offset, length) | |
case 'binary': | |
return binaryWrite(this, string, offset, length) | |
case 'base64': | |
// Warning: maxLength not taken into account in base64Write | |
return base64Write(this, string, offset, length) | |
case 'ucs2': | |
case 'ucs-2': | |
case 'utf16le': | |
case 'utf-16le': | |
return ucs2Write(this, string, offset, length) | |
default: | |
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) | |
encoding = ('' + encoding).toLowerCase() | |
loweredCase = true | |
} | |
} | |
} | |
Buffer.prototype.toJSON = function toJSON () { | |
return { | |
type: 'Buffer', | |
data: Array.prototype.slice.call(this._arr || this, 0) | |
} | |
} | |
function base64Slice (buf, start, end) { | |
if (start === 0 && end === buf.length) { | |
return base64.fromByteArray(buf) | |
} else { | |
return base64.fromByteArray(buf.slice(start, end)) | |
} | |
} | |
function utf8Slice (buf, start, end) { | |
end = Math.min(buf.length, end) | |
var res = [] | |
var i = start | |
while (i < end) { | |
var firstByte = buf[i] | |
var codePoint = null | |
var bytesPerSequence = (firstByte > 0xEF) ? 4 | |
: (firstByte > 0xDF) ? 3 | |
: (firstByte > 0xBF) ? 2 | |
: 1 | |
if (i + bytesPerSequence <= end) { | |
var secondByte, thirdByte, fourthByte, tempCodePoint | |
switch (bytesPerSequence) { | |
case 1: | |
if (firstByte < 0x80) { | |
codePoint = firstByte | |
} | |
break | |
case 2: | |
secondByte = buf[i + 1] | |
if ((secondByte & 0xC0) === 0x80) { | |
tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) | |
if (tempCodePoint > 0x7F) { | |
codePoint = tempCodePoint | |
} | |
} | |
break | |
case 3: | |
secondByte = buf[i + 1] | |
thirdByte = buf[i + 2] | |
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { | |
tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) | |
if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { | |
codePoint = tempCodePoint | |
} | |
} | |
break | |
case 4: | |
secondByte = buf[i + 1] | |
thirdByte = buf[i + 2] | |
fourthByte = buf[i + 3] | |
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { | |
tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) | |
if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { | |
codePoint = tempCodePoint | |
} | |
} | |
} | |
} | |
if (codePoint === null) { | |
// we did not generate a valid codePoint so insert a | |
// replacement char (U+FFFD) and advance only 1 byte | |
codePoint = 0xFFFD | |
bytesPerSequence = 1 | |
} else if (codePoint > 0xFFFF) { | |
// encode to utf16 (surrogate pair dance) | |
codePoint -= 0x10000 | |
res.push(codePoint >>> 10 & 0x3FF | 0xD800) | |
codePoint = 0xDC00 | codePoint & 0x3FF | |
} | |
res.push(codePoint) | |
i += bytesPerSequence | |
} | |
return decodeCodePointsArray(res) | |
} | |
// Based on http://stackoverflow.com/a/22747272/680742, the browser with | |
// the lowest limit is Chrome, with 0x10000 args. | |
// We go 1 magnitude less, for safety | |
var MAX_ARGUMENTS_LENGTH = 0x1000 | |
function decodeCodePointsArray (codePoints) { | |
var len = codePoints.length | |
if (len <= MAX_ARGUMENTS_LENGTH) { | |
return String.fromCharCode.apply(String, codePoints) // avoid extra slice() | |
} | |
// Decode in chunks to avoid "call stack size exceeded". | |
var res = '' | |
var i = 0 | |
while (i < len) { | |
res += String.fromCharCode.apply( | |
String, | |
codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) | |
) | |
} | |
return res | |
} | |
function asciiSlice (buf, start, end) { | |
var ret = '' | |
end = Math.min(buf.length, end) | |
for (var i = start; i < end; i++) { | |
ret += String.fromCharCode(buf[i] & 0x7F) | |
} | |
return ret | |
} | |
function 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 slice (start, end) { | |
var len = this.length | |
start = ~~start | |
end = end === undefined ? len : ~~end | |
if (start < 0) { | |
start += len | |
if (start < 0) start = 0 | |
} else if (start > len) { | |
start = len | |
} | |
if (end < 0) { | |
end += len | |
if (end < 0) end = 0 | |
} else if (end > len) { | |
end = len | |
} | |
if (end < start) end = start | |
var newBuf | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
newBuf = Buffer._augment(this.subarray(start, end)) | |
} else { | |
var sliceLen = end - start | |
newBuf = new Buffer(sliceLen, undefined) | |
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 readUIntLE (offset, byteLength, noAssert) { | |
offset = offset | 0 | |
byteLength = byteLength | 0 | |
if (!noAssert) checkOffset(offset, byteLength, this.length) | |
var val = this[offset] | |
var mul = 1 | |
var i = 0 | |
while (++i < byteLength && (mul *= 0x100)) { | |
val += this[offset + i] * mul | |
} | |
return val | |
} | |
Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { | |
offset = offset | 0 | |
byteLength = byteLength | 0 | |
if (!noAssert) { | |
checkOffset(offset, byteLength, this.length) | |
} | |
var val = this[offset + --byteLength] | |
var mul = 1 | |
while (byteLength > 0 && (mul *= 0x100)) { | |
val += this[offset + --byteLength] * mul | |
} | |
return val | |
} | |
Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { | |
if (!noAssert) checkOffset(offset, 1, this.length) | |
return this[offset] | |
} | |
Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { | |
if (!noAssert) checkOffset(offset, 2, this.length) | |
return this[offset] | (this[offset + 1] << 8) | |
} | |
Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { | |
if (!noAssert) checkOffset(offset, 2, this.length) | |
return (this[offset] << 8) | this[offset + 1] | |
} | |
Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return ((this[offset]) | | |
(this[offset + 1] << 8) | | |
(this[offset + 2] << 16)) + | |
(this[offset + 3] * 0x1000000) | |
} | |
Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return (this[offset] * 0x1000000) + | |
((this[offset + 1] << 16) | | |
(this[offset + 2] << 8) | | |
this[offset + 3]) | |
} | |
Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { | |
offset = offset | 0 | |
byteLength = byteLength | 0 | |
if (!noAssert) checkOffset(offset, byteLength, this.length) | |
var val = this[offset] | |
var mul = 1 | |
var i = 0 | |
while (++i < byteLength && (mul *= 0x100)) { | |
val += this[offset + i] * mul | |
} | |
mul *= 0x80 | |
if (val >= mul) val -= Math.pow(2, 8 * byteLength) | |
return val | |
} | |
Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { | |
offset = offset | 0 | |
byteLength = byteLength | 0 | |
if (!noAssert) checkOffset(offset, byteLength, this.length) | |
var i = byteLength | |
var mul = 1 | |
var val = this[offset + --i] | |
while (i > 0 && (mul *= 0x100)) { | |
val += this[offset + --i] * mul | |
} | |
mul *= 0x80 | |
if (val >= mul) val -= Math.pow(2, 8 * byteLength) | |
return val | |
} | |
Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { | |
if (!noAssert) checkOffset(offset, 1, this.length) | |
if (!(this[offset] & 0x80)) return (this[offset]) | |
return ((0xff - this[offset] + 1) * -1) | |
} | |
Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { | |
if (!noAssert) checkOffset(offset, 2, this.length) | |
var val = this[offset] | (this[offset + 1] << 8) | |
return (val & 0x8000) ? val | 0xFFFF0000 : val | |
} | |
Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { | |
if (!noAssert) checkOffset(offset, 2, this.length) | |
var val = this[offset + 1] | (this[offset] << 8) | |
return (val & 0x8000) ? val | 0xFFFF0000 : val | |
} | |
Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return (this[offset]) | | |
(this[offset + 1] << 8) | | |
(this[offset + 2] << 16) | | |
(this[offset + 3] << 24) | |
} | |
Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return (this[offset] << 24) | | |
(this[offset + 1] << 16) | | |
(this[offset + 2] << 8) | | |
(this[offset + 3]) | |
} | |
Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return ieee754.read(this, offset, true, 23, 4) | |
} | |
Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return ieee754.read(this, offset, false, 23, 4) | |
} | |
Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { | |
if (!noAssert) checkOffset(offset, 8, this.length) | |
return ieee754.read(this, offset, true, 52, 8) | |
} | |
Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { | |
if (!noAssert) checkOffset(offset, 8, this.length) | |
return ieee754.read(this, offset, false, 52, 8) | |
} | |
function checkInt (buf, value, offset, ext, max, min) { | |
if (!Buffer.isBuffer(buf)) throw new TypeError('buffer 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 writeUIntLE (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) & 0xFF | |
} | |
return offset + byteLength | |
} | |
Buffer.prototype.writeUIntBE = function writeUIntBE (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) & 0xFF | |
} | |
return offset + byteLength | |
} | |
Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { | |
value = +value | |
offset = offset | 0 | |
if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) | |
if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) | |
this[offset] = (value & 0xff) | |
return offset + 1 | |
} | |
function objectWriteUInt16 (buf, value, offset, littleEndian) { | |
if (value < 0) value = 0xffff + value + 1 | |
for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { | |
buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> | |
(littleEndian ? i : 1 - i) * 8 | |
} | |
} | |
Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { | |
value = +value | |
offset = offset | 0 | |
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
this[offset] = (value & 0xff) | |
this[offset + 1] = (value >>> 8) | |
} else { | |
objectWriteUInt16(this, value, offset, true) | |
} | |
return offset + 2 | |
} | |
Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { | |
value = +value | |
offset = offset | 0 | |
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
this[offset] = (value >>> 8) | |
this[offset + 1] = (value & 0xff) | |
} else { | |
objectWriteUInt16(this, value, offset, false) | |
} | |
return offset + 2 | |
} | |
function objectWriteUInt32 (buf, value, offset, littleEndian) { | |
if (value < 0) value = 0xffffffff + value + 1 | |
for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { | |
buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff | |
} | |
} | |
Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { | |
value = +value | |
offset = offset | 0 | |
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
this[offset + 3] = (value >>> 24) | |
this[offset + 2] = (value >>> 16) | |
this[offset + 1] = (value >>> 8) | |
this[offset] = (value & 0xff) | |
} else { | |
objectWriteUInt32(this, value, offset, true) | |
} | |
return offset + 4 | |
} | |
Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { | |
value = +value | |
offset = offset | 0 | |
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
this[offset] = (value >>> 24) | |
this[offset + 1] = (value >>> 16) | |
this[offset + 2] = (value >>> 8) | |
this[offset + 3] = (value & 0xff) | |
} else { | |
objectWriteUInt32(this, value, offset, false) | |
} | |
return offset + 4 | |
} | |
Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { | |
value = +value | |
offset = offset | 0 | |
if (!noAssert) { | |
var limit = Math.pow(2, 8 * byteLength - 1) | |
checkInt(this, value, offset, byteLength, limit - 1, -limit) | |
} | |
var i = 0 | |
var mul = 1 | |
var sub = 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 writeIntBE (value, offset, byteLength, noAssert) { | |
value = +value | |
offset = offset | 0 | |
if (!noAssert) { | |
var limit = Math.pow(2, 8 * byteLength - 1) | |
checkInt(this, value, offset, byteLength, limit - 1, -limit) | |
} | |
var i = byteLength - 1 | |
var mul = 1 | |
var sub = 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 writeInt8 (value, offset, noAssert) { | |
value = +value | |
offset = offset | 0 | |
if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) | |
if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) | |
if (value < 0) value = 0xff + value + 1 | |
this[offset] = (value & 0xff) | |
return offset + 1 | |
} | |
Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { | |
value = +value | |
offset = offset | 0 | |
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
this[offset] = (value & 0xff) | |
this[offset + 1] = (value >>> 8) | |
} else { | |
objectWriteUInt16(this, value, offset, true) | |
} | |
return offset + 2 | |
} | |
Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { | |
value = +value | |
offset = offset | 0 | |
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
this[offset] = (value >>> 8) | |
this[offset + 1] = (value & 0xff) | |
} else { | |
objectWriteUInt16(this, value, offset, false) | |
} | |
return offset + 2 | |
} | |
Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { | |
value = +value | |
offset = offset | 0 | |
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
this[offset] = (value & 0xff) | |
this[offset + 1] = (value >>> 8) | |
this[offset + 2] = (value >>> 16) | |
this[offset + 3] = (value >>> 24) | |
} else { | |
objectWriteUInt32(this, value, offset, true) | |
} | |
return offset + 4 | |
} | |
Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { | |
value = +value | |
offset = offset | 0 | |
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) | |
if (value < 0) value = 0xffffffff + value + 1 | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
this[offset] = (value >>> 24) | |
this[offset + 1] = (value >>> 16) | |
this[offset + 2] = (value >>> 8) | |
this[offset + 3] = (value & 0xff) | |
} else { | |
objectWriteUInt32(this, value, offset, false) | |
} | |
return offset + 4 | |
} | |
function checkIEEE754 (buf, value, offset, ext, max, min) { | |
if (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 writeFloatLE (value, offset, noAssert) { | |
return writeFloat(this, value, offset, true, noAssert) | |
} | |
Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { | |
return writeFloat(this, value, offset, false, noAssert) | |
} | |
function writeDouble (buf, value, offset, littleEndian, noAssert) { | |
if (!noAssert) { | |
checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) | |
} | |
ieee754.write(buf, value, offset, littleEndian, 52, 8) | |
return offset + 8 | |
} | |
Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { | |
return writeDouble(this, value, offset, true, noAssert) | |
} | |
Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { | |
return writeDouble(this, value, offset, false, noAssert) | |
} | |
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) | |
Buffer.prototype.copy = function copy (target, targetStart, start, end) { | |
if (!start) start = 0 | |
if (!end && end !== 0) end = this.length | |
if (targetStart >= target.length) targetStart = target.length | |
if (!targetStart) targetStart = 0 | |
if (end > 0 && end < start) end = start | |
// Copy 0 bytes; we're done | |
if (end === start) return 0 | |
if (target.length === 0 || this.length === 0) return 0 | |
// Fatal error conditions | |
if (targetStart < 0) { | |
throw new RangeError('targetStart out of bounds') | |
} | |
if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') | |
if (end < 0) throw new RangeError('sourceEnd out of bounds') | |
// Are we oob? | |
if (end > this.length) end = this.length | |
if (target.length - targetStart < end - start) { | |
end = target.length - targetStart + start | |
} | |
var len = end - start | |
var i | |
if (this === target && start < targetStart && targetStart < end) { | |
// descending copy from end | |
for (i = len - 1; i >= 0; i--) { | |
target[i + targetStart] = this[i + start] | |
} | |
} else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { | |
// ascending copy from start | |
for (i = 0; i < len; i++) { | |
target[i + targetStart] = this[i + start] | |
} | |
} else { | |
target._set(this.subarray(start, start + len), targetStart) | |
} | |
return len | |
} | |
// fill(value, start=0, end=buffer.length) | |
Buffer.prototype.fill = function fill (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 toArrayBuffer () { | |
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 _augment (arr) { | |
arr.constructor = Buffer | |
arr._isBuffer = true | |
// save reference to original Uint8Array set method before overwriting | |
arr._set = arr.set | |
// deprecated | |
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.indexOf = BP.indexOf | |
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-Za-z-_]/g | |
function base64clean (str) { | |
// Node strips out invalid characters like \n and \t from the string, base64-js does not | |
str = stringtrim(str).replace(INVALID_BASE64_RE, '') | |
// Node converts strings with length < 2 to '' | |
if (str.length < 2) return '' | |
// Node allows for non-padded base64 strings (missing trailing ===), base64-js does not | |
while (str.length % 4 !== 0) { | |
str = str + '=' | |
} | |
return str | |
} | |
function stringtrim (str) { | |
if (str.trim) return str.trim() | |
return str.replace(/^\s+|\s+$/g, '') | |
} | |
function toHex (n) { | |
if (n < 16) return '0' + n.toString(16) | |
return n.toString(16) | |
} | |
function utf8ToBytes (string, units) { | |
units = units || Infinity | |
var codePoint | |
var length = string.length | |
var leadSurrogate = null | |
var bytes = [] | |
for (var i = 0; i < length; i++) { | |
codePoint = string.charCodeAt(i) | |
// is surrogate component | |
if (codePoint > 0xD7FF && codePoint < 0xE000) { | |
// last char was a lead | |
if (!leadSurrogate) { | |
// no lead yet | |
if (codePoint > 0xDBFF) { | |
// unexpected trail | |
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) | |
continue | |
} else if (i + 1 === length) { | |
// unpaired lead | |
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) | |
continue | |
} | |
// valid lead | |
leadSurrogate = codePoint | |
continue | |
} | |
// 2 leads in a row | |
if (codePoint < 0xDC00) { | |
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) | |
leadSurrogate = codePoint | |
continue | |
} | |
// valid surrogate pair | |
codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 | |
} else if (leadSurrogate) { | |
// valid bmp char, but last char was a lead | |
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) | |
} | |
leadSurrogate = null | |
// encode utf8 | |
if (codePoint < 0x80) { | |
if ((units -= 1) < 0) break | |
bytes.push(codePoint) | |
} else if (codePoint < 0x800) { | |
if ((units -= 2) < 0) break | |
bytes.push( | |
codePoint >> 0x6 | 0xC0, | |
codePoint & 0x3F | 0x80 | |
) | |
} else if (codePoint < 0x10000) { | |
if ((units -= 3) < 0) break | |
bytes.push( | |
codePoint >> 0xC | 0xE0, | |
codePoint >> 0x6 & 0x3F | 0x80, | |
codePoint & 0x3F | 0x80 | |
) | |
} else if (codePoint < 0x110000) { | |
if ((units -= 4) < 0) break | |
bytes.push( | |
codePoint >> 0x12 | 0xF0, | |
codePoint >> 0xC & 0x3F | 0x80, | |
codePoint >> 0x6 & 0x3F | 0x80, | |
codePoint & 0x3F | 0x80 | |
) | |
} else { | |
throw new Error('Invalid code point') | |
} | |
} | |
return bytes | |
} | |
function asciiToBytes (str) { | |
var byteArray = [] | |
for (var i = 0; i < str.length; i++) { | |
// Node's code seems to be doing this and not & 0x7F.. | |
byteArray.push(str.charCodeAt(i) & 0xFF) | |
} | |
return byteArray | |
} | |
function utf16leToBytes (str, units) { | |
var c, hi, lo | |
var byteArray = [] | |
for (var i = 0; i < str.length; i++) { | |
if ((units -= 2) < 0) break | |
c = str.charCodeAt(i) | |
hi = c >> 8 | |
lo = c % 256 | |
byteArray.push(lo) | |
byteArray.push(hi) | |
} | |
return byteArray | |
} | |
function base64ToBytes (str) { | |
return base64.toByteArray(base64clean(str)) | |
} | |
function blitBuffer (src, dst, offset, length) { | |
for (var i = 0; i < length; i++) { | |
if ((i + offset >= dst.length) || (i >= src.length)) break | |
dst[i + offset] = src[i] | |
} | |
return i | |
} | |
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2J1ZmZlci9pbmRleC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIi8qIVxuICogVGhlIGJ1ZmZlciBtb2R1bGUgZnJvbSBub2RlLmpzLCBmb3IgdGhlIGJyb3dzZXIuXG4gKlxuICogQGF1dGhvciAgIEZlcm9zcyBBYm91a2hhZGlqZWggPGZlcm9zc0BmZXJvc3Mub3JnPiA8aHR0cDovL2Zlcm9zcy5vcmc+XG4gKiBAbGljZW5zZSAgTUlUXG4gKi9cbi8qIGVzbGludC1kaXNhYmxlIG5vLXByb3RvICovXG5cbid1c2Ugc3RyaWN0J1xuXG52YXIgYmFzZTY0ID0gcmVxdWlyZSgnYmFzZTY0LWpzJylcbnZhciBpZWVlNzU0ID0gcmVxdWlyZSgnaWVlZTc1NCcpXG52YXIgaXNBcnJheSA9IHJlcXVpcmUoJ2lzYXJyYXknKVxuXG5leHBvcnRzLkJ1ZmZlciA9IEJ1ZmZlclxuZXhwb3J0cy5TbG93QnVmZmVyID0gU2xvd0J1ZmZlclxuZXhwb3J0cy5JTlNQRUNUX01BWF9CWVRFUyA9IDUwXG5CdWZmZXIucG9vbFNpemUgPSA4MTkyIC8vIG5vdCB1c2VkIGJ5IHRoaXMgaW1wbGVtZW50YXRpb25cblxudmFyIHJvb3RQYXJlbnQgPSB7fVxuXG4vKipcbiAqIElmIGBCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVGA6XG4gKiAgID09PSB0cnVlICAgIFVzZSBVaW50OEFycmF5IGltcGxlbWVudGF0aW9uIChmYXN0ZXN0KVxuICogICA9PT0gZmFsc2UgICBVc2UgT2JqZWN0IGltcGxlbWVudGF0aW9uIChtb3N0IGNvbXBhdGlibGUsIGV2ZW4gSUU2KVxuICpcbiAqIEJyb3dzZXJzIHRoYXQgc3VwcG9ydCB0eXBlZCBhcnJheXMgYXJlIElFIDEwKywgRmlyZWZveCA0KywgQ2hyb21lIDcrLCBTYWZhcmkgNS4xKyxcbiAqIE9wZXJhIDExLjYrLCBpT1MgNC4yKy5cbiAqXG4gKiBEdWUgdG8gdmFyaW91cyBicm93c2VyIGJ1Z3MsIHNvbWV0aW1lcyB0aGUgT2JqZWN0IGltcGxlbWVudGF0aW9uIHdpbGwgYmUgdXNlZCBldmVuXG4gKiB3aGVuIHRoZSBicm93c2VyIHN1cHBvcnRzIHR5cGVkIGFycmF5cy5cbiAqXG4gKiBOb3RlOlxuICpcbiAqICAgLSBGaXJlZm94IDQtMjkgbGFja3Mgc3VwcG9ydCBmb3IgYWRkaW5nIG5ldyBwcm9wZXJ0aWVzIHRvIGBVaW50OEFycmF5YCBpbnN0YW5jZXMsXG4gKiAgICAgU2VlOiBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD02OTU0MzguXG4gKlxuICogICAtIFNhZmFyaSA1LTcgbGFja3Mgc3VwcG9ydCBmb3IgY2hhbmdpbmcgdGhlIGBPYmplY3QucHJvdG90eXBlLmNvbnN0cnVjdG9yYCBwcm9wZXJ0eVxuICogICAgIG9uIG9iamVjdHMuXG4gKlxuICogICAtIENocm9tZSA5LTEwIGlzIG1pc3NpbmcgdGhlIGBUeXBlZEFycmF5LnByb3RvdHlwZS5zdWJhcnJheWAgZnVuY3Rpb24uXG4gKlxuICogICAtIElFMTAgaGFzIGEgYnJva2VuIGBUeXBlZEFycmF5LnByb3RvdHlwZS5zdWJhcnJheWAgZnVuY3Rpb24gd2hpY2ggcmV0dXJucyBhcnJheXMgb2ZcbiAqICAgICBpbmNvcnJlY3QgbGVuZ3RoIGluIHNvbWUgc2l0dWF0aW9ucy5cblxuICogV2UgZGV0ZWN0IHRoZXNlIGJ1Z2d5IGJyb3dzZXJzIGFuZCBzZXQgYEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUYCB0byBgZmFsc2VgIHNvIHRoZXlcbiAqIGdldCB0aGUgT2JqZWN0IGltcGxlbWVudGF0aW9uLCB3aGljaCBpcyBzbG93ZXIgYnV0IGJlaGF2ZXMgY29ycmVjdGx5LlxuICovXG5CdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCA9IGdsb2JhbC5UWVBFRF9BUlJBWV9TVVBQT1JUICE9PSB1bmRlZmluZWRcbiAgPyBnbG9iYWwuVFlQRURfQVJSQVlfU1VQUE9SVFxuICA6IHR5cGVkQXJyYXlTdXBwb3J0KClcblxuZnVuY3Rpb24gdHlwZWRBcnJheVN1cHBvcnQgKCkge1xuICBmdW5jdGlvbiBCYXIgKCkge31cbiAgdHJ5IHtcbiAgICB2YXIgYXJyID0gbmV3IFVpbnQ4QXJyYXkoMSlcbiAgICBhcnIuZm9vID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gNDIgfVxuICAgIGFyci5jb25zdHJ1Y3RvciA9IEJhclxuICAgIHJldHVybiBhcnIuZm9vKCkgPT09IDQyICYmIC8vIHR5cGVkIGFycmF5IGluc3RhbmNlcyBjYW4gYmUgYXVnbWVudGVkXG4gICAgICAgIGFyci5jb25zdHJ1Y3RvciA9PT0gQmFyICYmIC8vIGNvbnN0cnVjdG9yIGNhbiBiZSBzZXRcbiAgICAgICAgdHlwZW9mIGFyci5zdWJhcnJheSA9PT0gJ2Z1bmN0aW9uJyAmJiAvLyBjaHJvbWUgOS0xMCBsYWNrIGBzdWJhcnJheWBcbiAgICAgICAgYXJyLnN1YmFycmF5KDEsIDEpLmJ5dGVMZW5ndGggPT09IDAgLy8gaWUxMCBoYXMgYnJva2VuIGBzdWJhcnJheWBcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbmZ1bmN0aW9uIGtNYXhMZW5ndGggKCkge1xuICByZXR1cm4gQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlRcbiAgICA/IDB4N2ZmZmZmZmZcbiAgICA6IDB4M2ZmZmZmZmZcbn1cblxuLyoqXG4gKiBDbGFzczogQnVmZmVyXG4gKiA9PT09PT09PT09PT09XG4gKlxuICogVGhlIEJ1ZmZlciBjb25zdHJ1Y3RvciByZXR1cm5zIGluc3RhbmNlcyBvZiBgVWludDhBcnJheWAgdGhhdCBhcmUgYXVnbWVudGVkXG4gKiB3aXRoIGZ1bmN0aW9uIHByb3BlcnRpZXMgZm9yIGFsbCB0aGUgbm9kZSBgQnVmZmVyYCBBUEkgZnVuY3Rpb25zLiBXZSB1c2VcbiAqIGBVaW50OEFycmF5YCBzbyB0aGF0IHNxdWFyZSBicmFja2V0IG5vdGF0aW9uIHdvcmtzIGFzIGV4cGVjdGVkIC0tIGl0IHJldHVybnNcbiAqIGEgc2luZ2xlIG9jdGV0LlxuICpcbiAqIEJ5IGF1Z21lbnRpbmcgdGhlIGluc3RhbmNlcywgd2UgY2FuIGF2b2lkIG1vZGlmeWluZyB0aGUgYFVpbnQ4QXJyYXlgXG4gKiBwcm90b3R5cGUuXG4gKi9cbmZ1bmN0aW9uIEJ1ZmZlciAoYXJnKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBCdWZmZXIpKSB7XG4gICAgLy8gQXZvaWQgZ29pbmcgdGhyb3VnaCBhbiBBcmd1bWVudHNBZGFwdG9yVHJhbXBvbGluZSBpbiB0aGUgY29tbW9uIGNhc2UuXG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSByZXR1cm4gbmV3IEJ1ZmZlcihhcmcsIGFyZ3VtZW50c1sxXSlcbiAgICByZXR1cm4gbmV3IEJ1ZmZlcihhcmcpXG4gIH1cblxuICBpZiAoIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpcy5sZW5ndGggPSAwXG4gICAgdGhpcy5wYXJlbnQgPSB1bmRlZmluZWRcbiAgfVxuXG4gIC8vIENvbW1vbiBjYXNlLlxuICBpZiAodHlwZW9mIGFyZyA9PT0gJ251bWJlcicpIHtcbiAgICByZXR1cm4gZnJvbU51bWJlcih0aGlzLCBhcmcpXG4gIH1cblxuICAvLyBTbGlnaHRseSBsZXNzIGNvbW1vbiBjYXNlLlxuICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gZnJvbVN0cmluZyh0aGlzLCBhcmcsIGFyZ3VtZW50cy5sZW5ndGggPiAxID8gYXJndW1lbnRzWzFdIDogJ3V0ZjgnKVxuICB9XG5cbiAgLy8gVW51c3VhbC5cbiAgcmV0dXJuIGZyb21PYmplY3QodGhpcywgYXJnKVxufVxuXG5mdW5jdGlvbiBmcm9tTnVtYmVyICh0aGF0LCBsZW5ndGgpIHtcbiAgdGhhdCA9IGFsbG9jYXRlKHRoYXQsIGxlbmd0aCA8IDAgPyAwIDogY2hlY2tlZChsZW5ndGgpIHwgMClcbiAgaWYgKCFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoYXRbaV0gPSAwXG4gICAgfVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGZyb21TdHJpbmcgKHRoYXQsIHN0cmluZywgZW5jb2RpbmcpIHtcbiAgaWYgKHR5cGVvZiBlbmNvZGluZyAhPT0gJ3N0cmluZycgfHwgZW5jb2RpbmcgPT09ICcnKSBlbmNvZGluZyA9ICd1dGY4J1xuXG4gIC8vIEFzc3VtcHRpb246IGJ5dGVMZW5ndGgoKSByZXR1cm4gdmFsdWUgaXMgYWx3YXlzIDwga01heExlbmd0aC5cbiAgdmFyIGxlbmd0aCA9IGJ5dGVMZW5ndGgoc3RyaW5nLCBlbmNvZGluZykgfCAwXG4gIHRoYXQgPSBhbGxvY2F0ZSh0aGF0LCBsZW5ndGgpXG5cbiAgdGhhdC53cml0ZShzdHJpbmcsIGVuY29kaW5nKVxuICByZXR1cm4gdGhhdFxufVxuXG5mdW5jdGlvbiBmcm9tT2JqZWN0ICh0aGF0LCBvYmplY3QpIHtcbiAgaWYgKEJ1ZmZlci5pc0J1ZmZlcihvYmplY3QpKSByZXR1cm4gZnJvbUJ1ZmZlcih0aGF0LCBvYmplY3QpXG5cbiAgaWYgKGlzQXJyYXkob2JqZWN0KSkgcmV0dXJuIGZyb21BcnJheSh0aGF0LCBvYmplY3QpXG5cbiAgaWYgKG9iamVjdCA9PSBudWxsKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbXVzdCBzdGFydCB3aXRoIG51bWJlciwgYnVmZmVyLCBhcnJheSBvciBzdHJpbmcnKVxuICB9XG5cbiAgaWYgKHR5cGVvZiBBcnJheUJ1ZmZlciAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBpZiAob2JqZWN0LmJ1ZmZlciBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB7XG4gICAgICByZXR1cm4gZnJvbVR5cGVkQXJyYXkodGhhdCwgb2JqZWN0KVxuICAgIH1cbiAgICBpZiAob2JqZWN0IGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHtcbiAgICAgIHJldHVybiBmcm9tQXJyYXlCdWZmZXIodGhhdCwgb2JqZWN0KVxuICAgIH1cbiAgfVxuXG4gIGlmIChvYmplY3QubGVuZ3RoKSByZXR1cm4gZnJvbUFycmF5TGlrZSh0aGF0LCBvYmplY3QpXG5cbiAgcmV0dXJuIGZyb21Kc29uT2JqZWN0KHRoYXQsIG9iamVjdClcbn1cblxuZnVuY3Rpb24gZnJvbUJ1ZmZlciAodGhhdCwgYnVmZmVyKSB7XG4gIHZhciBsZW5ndGggPSBjaGVja2VkKGJ1ZmZlci5sZW5ndGgpIHwgMFxuICB0aGF0ID0gYWxsb2NhdGUodGhhdCwgbGVuZ3RoKVxuICBidWZmZXIuY29weSh0aGF0LCAwLCAwLCBsZW5ndGgpXG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheSAodGhhdCwgYXJyYXkpIHtcbiAgdmFyIGxlbmd0aCA9IGNoZWNrZWQoYXJyYXkubGVuZ3RoKSB8IDBcbiAgdGhhdCA9IGFsbG9jYXRlKHRoYXQsIGxlbmd0aClcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgIHRoYXRbaV0gPSBhcnJheVtpXSAmIDI1NVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbi8vIER1cGxpY2F0ZSBvZiBmcm9tQXJyYXkoKSB0byBrZWVwIGZyb21BcnJheSgpIG1vbm9tb3JwaGljLlxuZnVuY3Rpb24gZnJvbVR5cGVkQXJyYXkgKHRoYXQsIGFycmF5KSB7XG4gIHZhciBsZW5ndGggPSBjaGVja2VkKGFycmF5Lmxlbmd0aCkgfCAwXG4gIHRoYXQgPSBhbGxvY2F0ZSh0aGF0LCBsZW5ndGgpXG4gIC8vIFRydW5jYXRpbmcgdGhlIGVsZW1lbnRzIGlzIHByb2JhYmx5IG5vdCB3aGF0IHBlb3BsZSBleHBlY3QgZnJvbSB0eXBlZFxuICAvLyBhcnJheXMgd2l0aCBCWVRFU19QRVJfRUxFTUVOVCA+IDEgYnV0IGl0J3MgY29tcGF0aWJsZSB3aXRoIHRoZSBiZWhhdmlvclxuICAvLyBvZiB0aGUgb2xkIEJ1ZmZlciBjb25zdHJ1Y3Rvci5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgIHRoYXRbaV0gPSBhcnJheVtpXSAmIDI1NVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheUJ1ZmZlciAodGhhdCwgYXJyYXkpIHtcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgLy8gUmV0dXJuIGFuIGF1Z21lbnRlZCBgVWludDhBcnJheWAgaW5zdGFuY2UsIGZvciBiZXN0IHBlcmZvcm1hbmNlXG4gICAgYXJyYXkuYnl0ZUxlbmd0aFxuICAgIHRoYXQgPSBCdWZmZXIuX2F1Z21lbnQobmV3IFVpbnQ4QXJyYXkoYXJyYXkpKVxuICB9IGVsc2Uge1xuICAgIC8vIEZhbGxiYWNrOiBSZXR1cm4gYW4gb2JqZWN0IGluc3RhbmNlIG9mIHRoZSBCdWZmZXIgY2xhc3NcbiAgICB0aGF0ID0gZnJvbVR5cGVkQXJyYXkodGhhdCwgbmV3IFVpbnQ4QXJyYXkoYXJyYXkpKVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheUxpa2UgKHRoYXQsIGFycmF5KSB7XG4gIHZhciBsZW5ndGggPSBjaGVja2VkKGFycmF5Lmxlbmd0aCkgfCAwXG4gIHRoYXQgPSBhbGxvY2F0ZSh0aGF0LCBsZW5ndGgpXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDEpIHtcbiAgICB0aGF0W2ldID0gYXJyYXlbaV0gJiAyNTVcbiAgfVxuICByZXR1cm4gdGhhdFxufVxuXG4vLyBEZXNlcmlhbGl6ZSB7IHR5cGU6ICdCdWZmZXInLCBkYXRhOiBbMSwyLDMsLi4uXSB9IGludG8gYSBCdWZmZXIgb2JqZWN0LlxuLy8gUmV0dXJucyBhIHplcm8tbGVuZ3RoIGJ1ZmZlciBmb3IgaW5wdXRzIHRoYXQgZG9uJ3QgY29uZm9ybSB0byB0aGUgc3BlYy5cbmZ1bmN0aW9uIGZyb21Kc29uT2JqZWN0ICh0aGF0LCBvYmplY3QpIHtcbiAgdmFyIGFycmF5XG4gIHZhciBsZW5ndGggPSAwXG5cbiAgaWYgKG9iamVjdC50eXBlID09PSAnQnVmZmVyJyAmJiBpc0FycmF5KG9iamVjdC5kYXRhKSkge1xuICAgIGFycmF5ID0gb2JqZWN0LmRhdGFcbiAgICBsZW5ndGggPSBjaGVja2VkKGFycmF5Lmxlbmd0aCkgfCAwXG4gIH1cbiAgdGhhdCA9IGFsbG9jYXRlKHRoYXQsIGxlbmd0aClcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgdGhhdFtpXSA9IGFycmF5W2ldICYgMjU1XG4gIH1cbiAgcmV0dXJuIHRoYXRcbn1cblxuaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gIEJ1ZmZlci5wcm90b3R5cGUuX19wcm90b19fID0gVWludDhBcnJheS5wcm90b3R5cGVcbiAgQnVmZmVyLl9fcHJvdG9fXyA9IFVpbnQ4QXJyYXlcbn0gZWxzZSB7XG4gIC8vIHByZS1zZXQgZm9yIHZhbHVlcyB0aGF0IG1heSBleGlzdCBpbiB0aGUgZnV0dXJlXG4gIEJ1ZmZlci5wcm90b3R5cGUubGVuZ3RoID0gdW5kZWZpbmVkXG4gIEJ1ZmZlci5wcm90b3R5cGUucGFyZW50ID0gdW5kZWZpbmVkXG59XG5cbmZ1bmN0aW9uIGFsbG9jYXRlICh0aGF0LCBsZW5ndGgpIHtcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgLy8gUmV0dXJuIGFuIGF1Z21lbnRlZCBgVWludDhBcnJheWAgaW5zdGFuY2UsIGZvciBiZXN0IHBlcmZvcm1hbmNlXG4gICAgdGhhdCA9IEJ1ZmZlci5fYXVnbWVudChuZXcgVWludDhBcnJheShsZW5ndGgpKVxuICAgIHRoYXQuX19wcm90b19fID0gQnVmZmVyLnByb3RvdHlwZVxuICB9IGVsc2Uge1xuICAgIC8vIEZhbGxiYWNrOiBSZXR1cm4gYW4gb2JqZWN0IGluc3RhbmNlIG9mIHRoZSBCdWZmZXIgY2xhc3NcbiAgICB0aGF0Lmxlbmd0aCA9IGxlbmd0aFxuICAgIHRoYXQuX2lzQnVmZmVyID0gdHJ1ZVxuICB9XG5cbiAgdmFyIGZyb21Qb29sID0gbGVuZ3RoICE9PSAwICYmIGxlbmd0aCA8PSBCdWZmZXIucG9vbFNpemUgPj4+IDFcbiAgaWYgKGZyb21Qb29sKSB0aGF0LnBhcmVudCA9IHJvb3RQYXJlbnRcblxuICByZXR1cm4gdGhhdFxufVxuXG5mdW5jdGlvbiBjaGVja2VkIChsZW5ndGgpIHtcbiAgLy8gTm90ZTogY2Fubm90IHVzZSBgbGVuZ3RoIDwga01heExlbmd0aGAgaGVyZSBiZWNhdXNlIHRoYXQgZmFpbHMgd2hlblxuICAvLyBsZW5ndGggaXMgTmFOICh3aGljaCBpcyBvdGhlcndpc2UgY29lcmNlZCB0byB6ZXJvLilcbiAgaWYgKGxlbmd0aCA+PSBrTWF4TGVuZ3RoKCkpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignQXR0ZW1wdCB0byBhbGxvY2F0ZSBCdWZmZXIgbGFyZ2VyIHRoYW4gbWF4aW11bSAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAnc2l6ZTogMHgnICsga01heExlbmd0aCgpLnRvU3RyaW5nKDE2KSArICcgYnl0ZXMnKVxuICB9XG4gIHJldHVybiBsZW5ndGggfCAwXG59XG5cbmZ1bmN0aW9uIFNsb3dCdWZmZXIgKHN1YmplY3QsIGVuY29kaW5nKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTbG93QnVmZmVyKSkgcmV0dXJuIG5ldyBTbG93QnVmZmVyKHN1YmplY3QsIGVuY29kaW5nKVxuXG4gIHZhciBidWYgPSBuZXcgQnVmZmVyKHN1YmplY3QsIGVuY29kaW5nKVxuICBkZWxldGUgYnVmLnBhcmVudFxuICByZXR1cm4gYnVmXG59XG5cbkJ1ZmZlci5pc0J1ZmZlciA9IGZ1bmN0aW9uIGlzQnVmZmVyIChiKSB7XG4gIHJldHVybiAhIShiICE9IG51bGwgJiYgYi5faXNCdWZmZXIpXG59XG5cbkJ1ZmZlci5jb21wYXJlID0gZnVuY3Rpb24gY29tcGFyZSAoYSwgYikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihhKSB8fCAhQnVmZmVyLmlzQnVmZmVyKGIpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJndW1lbnRzIG11c3QgYmUgQnVmZmVycycpXG4gIH1cblxuICBpZiAoYSA9PT0gYikgcmV0dXJuIDBcblxuICB2YXIgeCA9IGEubGVuZ3RoXG4gIHZhciB5ID0gYi5sZW5ndGhcblxuICB2YXIgaSA9IDBcbiAgdmFyIGxlbiA9IE1hdGgubWluKHgsIHkpXG4gIHdoaWxlIChpIDwgbGVuKSB7XG4gICAgaWYgKGFbaV0gIT09IGJbaV0pIGJyZWFrXG5cbiAgICArK2lcbiAgfVxuXG4gIGlmIChpICE9PSBsZW4pIHtcbiAgICB4ID0gYVtpXVxuICAgIHkgPSBiW2ldXG4gIH1cblxuICBpZiAoeCA8IHkpIHJldHVybiAtMVxuICBpZiAoeSA8IHgpIHJldHVybiAxXG4gIHJldHVybiAwXG59XG5cbkJ1ZmZlci5pc0VuY29kaW5nID0gZnVuY3Rpb24gaXNFbmNvZGluZyAoZW5jb2RpbmcpIHtcbiAgc3dpdGNoIChTdHJpbmcoZW5jb2RpbmcpLnRvTG93ZXJDYXNlKCkpIHtcbiAgICBjYXNlICdoZXgnOlxuICAgIGNhc2UgJ3V0ZjgnOlxuICAgIGNhc2UgJ3V0Zi04JzpcbiAgICBjYXNlICdhc2NpaSc6XG4gICAgY2FzZSAnYmluYXJ5JzpcbiAgICBjYXNlICdiYXNlNjQnOlxuICAgIGNhc2UgJ3Jhdyc6XG4gICAgY2FzZSAndWNzMic6XG4gICAgY2FzZSAndWNzLTInOlxuICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgIHJldHVybiB0cnVlXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbkJ1ZmZlci5jb25jYXQgPSBmdW5jdGlvbiBjb25jYXQgKGxpc3QsIGxlbmd0aCkge1xuICBpZiAoIWlzQXJyYXkobGlzdCkpIHRocm93IG5ldyBUeXBlRXJyb3IoJ2xpc3QgYXJndW1lbnQgbXVzdCBiZSBhbiBBcnJheSBvZiBCdWZmZXJzLicpXG5cbiAgaWYgKGxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIG5ldyBCdWZmZXIoMClcbiAgfVxuXG4gIHZhciBpXG4gIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCkge1xuICAgIGxlbmd0aCA9IDBcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgbGVuZ3RoICs9IGxpc3RbaV0ubGVuZ3RoXG4gICAgfVxuICB9XG5cbiAgdmFyIGJ1ZiA9IG5ldyBCdWZmZXIobGVuZ3RoKVxuICB2YXIgcG9zID0gMFxuICBmb3IgKGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIHZhciBpdGVtID0gbGlzdFtpXVxuICAgIGl0ZW0uY29weShidWYsIHBvcylcbiAgICBwb3MgKz0gaXRlbS5sZW5ndGhcbiAgfVxuICByZXR1cm4gYnVmXG59XG5cbmZ1bmN0aW9uIGJ5dGVMZW5ndGggKHN0cmluZywgZW5jb2RpbmcpIHtcbiAgaWYgKHR5cGVvZiBzdHJpbmcgIT09ICdzdHJpbmcnKSBzdHJpbmcgPSAnJyArIHN0cmluZ1xuXG4gIHZhciBsZW4gPSBzdHJpbmcubGVuZ3RoXG4gIGlmIChsZW4gPT09IDApIHJldHVybiAwXG5cbiAgLy8gVXNlIGEgZm9yIGxvb3AgdG8gYXZvaWQgcmVjdXJzaW9uXG4gIHZhciBsb3dlcmVkQ2FzZSA9IGZhbHNlXG4gIGZvciAoOzspIHtcbiAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgICBjYXNlICdhc2NpaSc6XG4gICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgLy8gRGVwcmVjYXRlZFxuICAgICAgY2FzZSAncmF3JzpcbiAgICAgIGNhc2UgJ3Jhd3MnOlxuICAgICAgICByZXR1cm4gbGVuXG4gICAgICBjYXNlICd1dGY4JzpcbiAgICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgICAgcmV0dXJuIHV0ZjhUb0J5dGVzKHN0cmluZykubGVuZ3RoXG4gICAgICBjYXNlICd1Y3MyJzpcbiAgICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgICByZXR1cm4gbGVuICogMlxuICAgICAgY2FzZSAnaGV4JzpcbiAgICAgICAgcmV0dXJuIGxlbiA+Pj4gMVxuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgICAgcmV0dXJuIGJhc2U2NFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGhcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChsb3dlcmVkQ2FzZSkgcmV0dXJuIHV0ZjhUb0J5dGVzKHN0cmluZykubGVuZ3RoIC8vIGFzc3VtZSB1dGY4XG4gICAgICAgIGVuY29kaW5nID0gKCcnICsgZW5jb2RpbmcpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgbG93ZXJlZENhc2UgPSB0cnVlXG4gICAgfVxuICB9XG59XG5CdWZmZXIuYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGhcblxuZnVuY3Rpb24gc2xvd1RvU3RyaW5nIChlbmNvZGluZywgc3RhcnQsIGVuZCkge1xuICB2YXIgbG93ZXJlZENhc2UgPSBmYWxzZVxuXG4gIHN0YXJ0ID0gc3RhcnQgfCAwXG4gIGVuZCA9IGVuZCA9PT0gdW5kZWZpbmVkIHx8IGVuZCA9PT0gSW5maW5pdHkgPyB0aGlzLmxlbmd0aCA6IGVuZCB8IDBcblxuICBpZiAoIWVuY29kaW5nKSBlbmNvZGluZyA9ICd1dGY4J1xuICBpZiAoc3RhcnQgPCAwKSBzdGFydCA9IDBcbiAgaWYgKGVuZCA+IHRoaXMubGVuZ3RoKSBlbmQgPSB0aGlzLmxlbmd0aFxuICBpZiAoZW5kIDw9IHN0YXJ0KSByZXR1cm4gJydcblxuICB3aGlsZSAodHJ1ZSkge1xuICAgIHN3aXRjaCAoZW5jb2RpbmcpIHtcbiAgICAgIGNhc2UgJ2hleCc6XG4gICAgICAgIHJldHVybiBoZXhTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICd1dGY4JzpcbiAgICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgICAgcmV0dXJuIHV0ZjhTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICdhc2NpaSc6XG4gICAgICAgIHJldHVybiBhc2NpaVNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICAgIHJldHVybiBiaW5hcnlTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgICByZXR1cm4gYmFzZTY0U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAndWNzMic6XG4gICAgICBjYXNlICd1Y3MtMic6XG4gICAgICBjYXNlICd1dGYxNmxlJzpcbiAgICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgICAgcmV0dXJuIHV0ZjE2bGVTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBpZiAobG93ZXJlZENhc2UpIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyBlbmNvZGluZylcbiAgICAgICAgZW5jb2RpbmcgPSAoZW5jb2RpbmcgKyAnJykudG9Mb3dlckNhc2UoKVxuICAgICAgICBsb3dlcmVkQ2FzZSA9IHRydWVcbiAgICB9XG4gIH1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nICgpIHtcbiAgdmFyIGxlbmd0aCA9IHRoaXMubGVuZ3RoIHwgMFxuICBpZiAobGVuZ3RoID09PSAwKSByZXR1cm4gJydcbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHJldHVybiB1dGY4U2xpY2UodGhpcywgMCwgbGVuZ3RoKVxuICByZXR1cm4gc2xvd1RvU3RyaW5nLmFwcGx5KHRoaXMsIGFyZ3VtZW50cylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbiBlcXVhbHMgKGIpIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYikpIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXInKVxuICBpZiAodGhpcyA9PT0gYikgcmV0dXJuIHRydWVcbiAgcmV0dXJuIEJ1ZmZlci5jb21wYXJlKHRoaXMsIGIpID09PSAwXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuaW5zcGVjdCA9IGZ1bmN0aW9uIGluc3BlY3QgKCkge1xuICB2YXIgc3RyID0gJydcbiAgdmFyIG1heCA9IGV4cG9ydHMuSU5TUEVDVF9NQVhfQllURVNcbiAgaWYgKHRoaXMubGVuZ3RoID4gMCkge1xuICAgIHN0ciA9IHRoaXMudG9TdHJpbmcoJ2hleCcsIDAsIG1heCkubWF0Y2goLy57Mn0vZykuam9pbignICcpXG4gICAgaWYgKHRoaXMubGVuZ3RoID4gbWF4KSBzdHIgKz0gJyAuLi4gJ1xuICB9XG4gIHJldHVybiAnPEJ1ZmZlciAnICsgc3RyICsgJz4nXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuY29tcGFyZSA9IGZ1bmN0aW9uIGNvbXBhcmUgKGIpIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYikpIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXInKVxuICBpZiAodGhpcyA9PT0gYikgcmV0dXJuIDBcbiAgcmV0dXJuIEJ1ZmZlci5jb21wYXJlKHRoaXMsIGIpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuaW5kZXhPZiA9IGZ1bmN0aW9uIGluZGV4T2YgKHZhbCwgYnl0ZU9mZnNldCkge1xuICBpZiAoYnl0ZU9mZnNldCA+IDB4N2ZmZmZmZmYpIGJ5dGVPZmZzZXQgPSAweDdmZmZmZmZmXG4gIGVsc2UgaWYgKGJ5dGVPZmZzZXQgPCAtMHg4MDAwMDAwMCkgYnl0ZU9mZnNldCA9IC0weDgwMDAwMDAwXG4gIGJ5dGVPZmZzZXQgPj49IDBcblxuICBpZiAodGhpcy5sZW5ndGggPT09IDApIHJldHVybiAtMVxuICBpZiAoYnl0ZU9mZnNldCA+PSB0aGlzLmxlbmd0aCkgcmV0dXJuIC0xXG5cbiAgLy8gTmVnYXRpdmUgb2Zmc2V0cyBzdGFydCBmcm9tIHRoZSBlbmQgb2YgdGhlIGJ1ZmZlclxuICBpZiAoYnl0ZU9mZnNldCA8IDApIGJ5dGVPZmZzZXQgPSBNYXRoLm1heCh0aGlzLmxlbmd0aCArIGJ5dGVPZmZzZXQsIDApXG5cbiAgaWYgKHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnKSB7XG4gICAgaWYgKHZhbC5sZW5ndGggPT09IDApIHJldHVybiAtMSAvLyBzcGVjaWFsIGNhc2U6IGxvb2tpbmcgZm9yIGVtcHR5IHN0cmluZyBhbHdheXMgZmFpbHNcbiAgICByZXR1cm4gU3RyaW5nLnByb3RvdHlwZS5pbmRleE9mLmNhbGwodGhpcywgdmFsLCBieXRlT2Zmc2V0KVxuICB9XG4gIGlmIChCdWZmZXIuaXNCdWZmZXIodmFsKSkge1xuICAgIHJldHVybiBhcnJheUluZGV4T2YodGhpcywgdmFsLCBieXRlT2Zmc2V0KVxuICB9XG4gIGlmICh0eXBlb2YgdmFsID09PSAnbnVtYmVyJykge1xuICAgIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCAmJiBVaW50OEFycmF5LnByb3RvdHlwZS5pbmRleE9mID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICByZXR1cm4gVWludDhBcnJheS5wcm90b3R5cGUuaW5kZXhPZi5jYWxsKHRoaXMsIHZhbCwgYnl0ZU9mZnNldClcbiAgICB9XG4gICAgcmV0dXJuIGFycmF5SW5kZXhPZih0aGlzLCBbIHZhbCBdLCBieXRlT2Zmc2V0KVxuICB9XG5cbiAgZnVuY3Rpb24gYXJyYXlJbmRleE9mIChhcnIsIHZhbCwgYnl0ZU9mZnNldCkge1xuICAgIHZhciBmb3VuZEluZGV4ID0gLTFcbiAgICBmb3IgKHZhciBpID0gMDsgYnl0ZU9mZnNldCArIGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChhcnJbYnl0ZU9mZnNldCArIGldID09PSB2YWxbZm91bmRJbmRleCA9PT0gLTEgPyAwIDogaSAtIGZvdW5kSW5kZXhdKSB7XG4gICAgICAgIGlmIChmb3VuZEluZGV4ID09PSAtMSkgZm91bmRJbmRleCA9IGlcbiAgICAgICAgaWYgKGkgLSBmb3VuZEluZGV4ICsgMSA9PT0gdmFsLmxlbmd0aCkgcmV0dXJuIGJ5dGVPZmZzZXQgKyBmb3VuZEluZGV4XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmb3VuZEluZGV4ID0gLTFcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIC0xXG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2YWwgbXVzdCBiZSBzdHJpbmcsIG51bWJlciBvciBCdWZmZXInKVxufVxuXG4vLyBgZ2V0YCBpcyBkZXByZWNhdGVkXG5CdWZmZXIucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uIGdldCAob2Zmc2V0KSB7XG4gIGNvbnNvbGUubG9nKCcuZ2V0KCkgaXMgZGVwcmVjYXRlZC4gQWNjZXNzIHVzaW5nIGFycmF5IGluZGV4ZXMgaW5zdGVhZC4nKVxuICByZXR1cm4gdGhpcy5yZWFkVUludDgob2Zmc2V0KVxufVxuXG4vLyBgc2V0YCBpcyBkZXByZWNhdGVkXG5CdWZmZXIucHJvdG90eXBlLnNldCA9IGZ1bmN0aW9uIHNldCAodiwgb2Zmc2V0KSB7XG4gIGNvbnNvbGUubG9nKCcuc2V0KCkgaXMgZGVwcmVjYXRlZC4gQWNjZXNzIHVzaW5nIGFycmF5IGluZGV4ZXMgaW5zdGVhZC4nKVxuICByZXR1cm4gdGhpcy53cml0ZVVJbnQ4KHYsIG9mZnNldClcbn1cblxuZnVuY3Rpb24gaGV4V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICBvZmZzZXQgPSBOdW1iZXIob2Zmc2V0KSB8fCAwXG4gIHZhciByZW1haW5pbmcgPSBidWYubGVuZ3RoIC0gb2Zmc2V0XG4gIGlmICghbGVuZ3RoKSB7XG4gICAgbGVuZ3RoID0gcmVtYWluaW5nXG4gIH0gZWxzZSB7XG4gICAgbGVuZ3RoID0gTnVtYmVyKGxlbmd0aClcbiAgICBpZiAobGVuZ3RoID4gcmVtYWluaW5nKSB7XG4gICAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgICB9XG4gIH1cblxuICAvLyBtdXN0IGJlIGFuIGV2ZW4gbnVtYmVyIG9mIGRpZ2l0c1xuICB2YXIgc3RyTGVuID0gc3RyaW5nLmxlbmd0aFxuICBpZiAoc3RyTGVuICUgMiAhPT0gMCkgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGhleCBzdHJpbmcnKVxuXG4gIGlmIChsZW5ndGggPiBzdHJMZW4gLyAyKSB7XG4gICAgbGVuZ3RoID0gc3RyTGVuIC8gMlxuICB9XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcGFyc2VkID0gcGFyc2VJbnQoc3RyaW5nLnN1YnN0cihpICogMiwgMiksIDE2KVxuICAgIGlmIChpc05hTihwYXJzZWQpKSB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaGV4IHN0cmluZycpXG4gICAgYnVmW29mZnNldCArIGldID0gcGFyc2VkXG4gIH1cbiAgcmV0dXJuIGlcbn1cblxuZnVuY3Rpb24gdXRmOFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIodXRmOFRvQnl0ZXMoc3RyaW5nLCBidWYubGVuZ3RoIC0gb2Zmc2V0KSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gYXNjaWlXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKGFzY2lpVG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiBiaW5hcnlXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBhc2NpaVdyaXRlKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gYmFzZTY0V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcihiYXNlNjRUb0J5dGVzKHN0cmluZyksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIHVjczJXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKHV0ZjE2bGVUb0J5dGVzKHN0cmluZywgYnVmLmxlbmd0aCAtIG9mZnNldCksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGUgPSBmdW5jdGlvbiB3cml0ZSAoc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCwgZW5jb2RpbmcpIHtcbiAgLy8gQnVmZmVyI3dyaXRlKHN0cmluZylcbiAgaWYgKG9mZnNldCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgZW5jb2RpbmcgPSAndXRmOCdcbiAgICBsZW5ndGggPSB0aGlzLmxlbmd0aFxuICAgIG9mZnNldCA9IDBcbiAgLy8gQnVmZmVyI3dyaXRlKHN0cmluZywgZW5jb2RpbmcpXG4gIH0gZWxzZSBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQgJiYgdHlwZW9mIG9mZnNldCA9PT0gJ3N0cmluZycpIHtcbiAgICBlbmNvZGluZyA9IG9mZnNldFxuICAgIGxlbmd0aCA9IHRoaXMubGVuZ3RoXG4gICAgb2Zmc2V0ID0gMFxuICAvLyBCdWZmZXIjd3JpdGUoc3RyaW5nLCBvZmZzZXRbLCBsZW5ndGhdWywgZW5jb2RpbmddKVxuICB9IGVsc2UgaWYgKGlzRmluaXRlKG9mZnNldCkpIHtcbiAgICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gICAgaWYgKGlzRmluaXRlKGxlbmd0aCkpIHtcbiAgICAgIGxlbmd0aCA9IGxlbmd0aCB8IDBcbiAgICAgIGlmIChlbmNvZGluZyA9PT0gdW5kZWZpbmVkKSBlbmNvZGluZyA9ICd1dGY4J1xuICAgIH0gZWxzZSB7XG4gICAgICBlbmNvZGluZyA9IGxlbmd0aFxuICAgICAgbGVuZ3RoID0gdW5kZWZpbmVkXG4gICAgfVxuICAvLyBsZWdhY3kgd3JpdGUoc3RyaW5nLCBlbmNvZGluZywgb2Zmc2V0LCBsZW5ndGgpIC0gcmVtb3ZlIGluIHYwLjEzXG4gIH0gZWxzZSB7XG4gICAgdmFyIHN3YXAgPSBlbmNvZGluZ1xuICAgIGVuY29kaW5nID0gb2Zmc2V0XG4gICAgb2Zmc2V0ID0gbGVuZ3RoIHwgMFxuICAgIGxlbmd0aCA9IHN3YXBcbiAgfVxuXG4gIHZhciByZW1haW5pbmcgPSB0aGlzLmxlbmd0aCAtIG9mZnNldFxuICBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQgfHwgbGVuZ3RoID4gcmVtYWluaW5nKSBsZW5ndGggPSByZW1haW5pbmdcblxuICBpZiAoKHN0cmluZy5sZW5ndGggPiAwICYmIChsZW5ndGggPCAwIHx8IG9mZnNldCA8IDApKSB8fCBvZmZzZXQgPiB0aGlzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdhdHRlbXB0IHRvIHdyaXRlIG91dHNpZGUgYnVmZmVyIGJvdW5kcycpXG4gIH1cblxuICBpZiAoIWVuY29kaW5nKSBlbmNvZGluZyA9ICd1dGY4J1xuXG4gIHZhciBsb3dlcmVkQ2FzZSA9IGZhbHNlXG4gIGZvciAoOzspIHtcbiAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gaGV4V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICAgIHJldHVybiB1dGY4V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAnYXNjaWknOlxuICAgICAgICByZXR1cm4gYXNjaWlXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgICByZXR1cm4gYmluYXJ5V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgICAgLy8gV2FybmluZzogbWF4TGVuZ3RoIG5vdCB0YWtlbiBpbnRvIGFjY291bnQgaW4gYmFzZTY0V3JpdGVcbiAgICAgICAgcmV0dXJuIGJhc2U2NFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiB1Y3MyV3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpXG4gICAgICAgIGVuY29kaW5nID0gKCcnICsgZW5jb2RpbmcpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgbG93ZXJlZENhc2UgPSB0cnVlXG4gICAgfVxuICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OICgpIHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiAnQnVmZmVyJyxcbiAgICBkYXRhOiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCh0aGlzLl9hcnIgfHwgdGhpcywgMClcbiAgfVxufVxuXG5mdW5jdGlvbiBiYXNlNjRTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGlmIChzdGFydCA9PT0gMCAmJiBlbmQgPT09IGJ1Zi5sZW5ndGgpIHtcbiAgICByZXR1cm4gYmFzZTY0LmZyb21CeXRlQXJyYXkoYnVmKVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBiYXNlNjQuZnJvbUJ5dGVBcnJheShidWYuc2xpY2Uoc3RhcnQsIGVuZCkpXG4gIH1cbn1cblxuZnVuY3Rpb24gdXRmOFNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuICB2YXIgcmVzID0gW11cblxuICB2YXIgaSA9IHN0YXJ0XG4gIHdoaWxlIChpIDwgZW5kKSB7XG4gICAgdmFyIGZpcnN0Qnl0ZSA9IGJ1ZltpXVxuICAgIHZhciBjb2RlUG9pbnQgPSBudWxsXG4gICAgdmFyIGJ5dGVzUGVyU2VxdWVuY2UgPSAoZmlyc3RCeXRlID4gMHhFRikgPyA0XG4gICAgICA6IChmaXJzdEJ5dGUgPiAweERGKSA/IDNcbiAgICAgIDogKGZpcnN0Qnl0ZSA+IDB4QkYpID8gMlxuICAgICAgOiAxXG5cbiAgICBpZiAoaSArIGJ5dGVzUGVyU2VxdWVuY2UgPD0gZW5kKSB7XG4gICAgICB2YXIgc2Vjb25kQnl0ZSwgdGhpcmRCeXRlLCBmb3VydGhCeXRlLCB0ZW1wQ29kZVBvaW50XG5cbiAgICAgIHN3aXRjaCAoYnl0ZXNQZXJTZXF1ZW5jZSkge1xuICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgaWYgKGZpcnN0Qnl0ZSA8IDB4ODApIHtcbiAgICAgICAgICAgIGNvZGVQb2ludCA9IGZpcnN0Qnl0ZVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgc2Vjb25kQnl0ZSA9IGJ1ZltpICsgMV1cbiAgICAgICAgICBpZiAoKHNlY29uZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCkge1xuICAgICAgICAgICAgdGVtcENvZGVQb2ludCA9IChmaXJzdEJ5dGUgJiAweDFGKSA8PCAweDYgfCAoc2Vjb25kQnl0ZSAmIDB4M0YpXG4gICAgICAgICAgICBpZiAodGVtcENvZGVQb2ludCA+IDB4N0YpIHtcbiAgICAgICAgICAgICAgY29kZVBvaW50ID0gdGVtcENvZGVQb2ludFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgc2Vjb25kQnl0ZSA9IGJ1ZltpICsgMV1cbiAgICAgICAgICB0aGlyZEJ5dGUgPSBidWZbaSArIDJdXG4gICAgICAgICAgaWYgKChzZWNvbmRCeXRlICYgMHhDMCkgPT09IDB4ODAgJiYgKHRoaXJkQnl0ZSAmIDB4QzApID09PSAweDgwKSB7XG4gICAgICAgICAgICB0ZW1wQ29kZVBvaW50ID0gKGZpcnN0Qnl0ZSAmIDB4RikgPDwgMHhDIHwgKHNlY29uZEJ5dGUgJiAweDNGKSA8PCAweDYgfCAodGhpcmRCeXRlICYgMHgzRilcbiAgICAgICAgICAgIGlmICh0ZW1wQ29kZVBvaW50ID4gMHg3RkYgJiYgKHRlbXBDb2RlUG9pbnQgPCAweEQ4MDAgfHwgdGVtcENvZGVQb2ludCA+IDB4REZGRikpIHtcbiAgICAgICAgICAgICAgY29kZVBvaW50ID0gdGVtcENvZGVQb2ludFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgc2Vjb25kQnl0ZSA9IGJ1ZltpICsgMV1cbiAgICAgICAgICB0aGlyZEJ5dGUgPSBidWZbaSArIDJdXG4gICAgICAgICAgZm91cnRoQnl0ZSA9IGJ1ZltpICsgM11cbiAgICAgICAgICBpZiAoKHNlY29uZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCAmJiAodGhpcmRCeXRlICYgMHhDMCkgPT09IDB4ODAgJiYgKGZvdXJ0aEJ5dGUgJiAweEMwKSA9PT0gMHg4MCkge1xuICAgICAgICAgICAgdGVtcENvZGVQb2ludCA9IChmaXJzdEJ5dGUgJiAweEYpIDw8IDB4MTIgfCAoc2Vjb25kQnl0ZSAmIDB4M0YpIDw8IDB4QyB8ICh0aGlyZEJ5dGUgJiAweDNGKSA8PCAweDYgfCAoZm91cnRoQnl0ZSAmIDB4M0YpXG4gICAgICAgICAgICBpZiAodGVtcENvZGVQb2ludCA+IDB4RkZGRiAmJiB0ZW1wQ29kZVBvaW50IDwgMHgxMTAwMDApIHtcbiAgICAgICAgICAgICAgY29kZVBvaW50ID0gdGVtcENvZGVQb2ludFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY29kZVBvaW50ID09PSBudWxsKSB7XG4gICAgICAvLyB3ZSBkaWQgbm90IGdlbmVyYXRlIGEgdmFsaWQgY29kZVBvaW50IHNvIGluc2VydCBhXG4gICAgICAvLyByZXBsYWNlbWVudCBjaGFyIChVK0ZGRkQpIGFuZCBhZHZhbmNlIG9ubHkgMSBieXRlXG4gICAgICBjb2RlUG9pbnQgPSAweEZGRkRcbiAgICAgIGJ5dGVzUGVyU2VxdWVuY2UgPSAxXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPiAweEZGRkYpIHtcbiAgICAgIC8vIGVuY29kZSB0byB1dGYxNiAoc3Vycm9nYXRlIHBhaXIgZGFuY2UpXG4gICAgICBjb2RlUG9pbnQgLT0gMHgxMDAwMFxuICAgICAgcmVzLnB1c2goY29kZVBvaW50ID4+PiAxMCAmIDB4M0ZGIHwgMHhEODAwKVxuICAgICAgY29kZVBvaW50ID0gMHhEQzAwIHwgY29kZVBvaW50ICYgMHgzRkZcbiAgICB9XG5cbiAgICByZXMucHVzaChjb2RlUG9pbnQpXG4gICAgaSArPSBieXRlc1BlclNlcXVlbmNlXG4gIH1cblxuICByZXR1cm4gZGVjb2RlQ29kZVBvaW50c0FycmF5KHJlcylcbn1cblxuLy8gQmFzZWQgb24gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMjI3NDcyNzIvNjgwNzQyLCB0aGUgYnJvd3NlciB3aXRoXG4vLyB0aGUgbG93ZXN0IGxpbWl0IGlzIENocm9tZSwgd2l0aCAweDEwMDAwIGFyZ3MuXG4vLyBXZSBnbyAxIG1hZ25pdHVkZSBsZXNzLCBmb3Igc2FmZXR5XG52YXIgTUFYX0FSR1VNRU5UU19MRU5HVEggPSAweDEwMDBcblxuZnVuY3Rpb24gZGVjb2RlQ29kZVBvaW50c0FycmF5IChjb2RlUG9pbnRzKSB7XG4gIHZhciBsZW4gPSBjb2RlUG9pbnRzLmxlbmd0aFxuICBpZiAobGVuIDw9IE1BWF9BUkdVTUVOVFNfTEVOR1RIKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLCBjb2RlUG9pbnRzKSAvLyBhdm9pZCBleHRyYSBzbGljZSgpXG4gIH1cblxuICAvLyBEZWNvZGUgaW4gY2h1bmtzIHRvIGF2b2lkIFwiY2FsbCBzdGFjayBzaXplIGV4Y2VlZGVkXCIuXG4gIHZhciByZXMgPSAnJ1xuICB2YXIgaSA9IDBcbiAgd2hpbGUgKGkgPCBsZW4pIHtcbiAgICByZXMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShcbiAgICAgIFN0cmluZyxcbiAgICAgIGNvZGVQb2ludHMuc2xpY2UoaSwgaSArPSBNQVhfQVJHVU1FTlRTX0xFTkdUSClcbiAgICApXG4gIH1cbiAgcmV0dXJuIHJlc1xufVxuXG5mdW5jdGlvbiBhc2NpaVNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHJldCA9ICcnXG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcblxuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgIHJldCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ1ZltpXSAmIDB4N0YpXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5mdW5jdGlvbiBiaW5hcnlTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciByZXQgPSAnJ1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG5cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICByZXQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShidWZbaV0pXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5mdW5jdGlvbiBoZXhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG5cbiAgaWYgKCFzdGFydCB8fCBzdGFydCA8IDApIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCB8fCBlbmQgPCAwIHx8IGVuZCA+IGxlbikgZW5kID0gbGVuXG5cbiAgdmFyIG91dCA9ICcnXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgb3V0ICs9IHRvSGV4KGJ1ZltpXSlcbiAgfVxuICByZXR1cm4gb3V0XG59XG5cbmZ1bmN0aW9uIHV0ZjE2bGVTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciBieXRlcyA9IGJ1Zi5zbGljZShzdGFydCwgZW5kKVxuICB2YXIgcmVzID0gJydcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkgKz0gMikge1xuICAgIHJlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ5dGVzW2ldICsgYnl0ZXNbaSArIDFdICogMjU2KVxuICB9XG4gIHJldHVybiByZXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zbGljZSA9IGZ1bmN0aW9uIHNsaWNlIChzdGFydCwgZW5kKSB7XG4gIHZhciBsZW4gPSB0aGlzLmxlbmd0aFxuICBzdGFydCA9IH5+c3RhcnRcbiAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgPyBsZW4gOiB+fmVuZFxuXG4gIGlmIChzdGFydCA8IDApIHtcbiAgICBzdGFydCArPSBsZW5cbiAgICBpZiAoc3RhcnQgPCAwKSBzdGFydCA9IDBcbiAgfSBlbHNlIGlmIChzdGFydCA+IGxlbikge1xuICAgIHN0YXJ0ID0gbGVuXG4gIH1cblxuICBpZiAoZW5kIDwgMCkge1xuICAgIGVuZCArPSBsZW5cbiAgICBpZiAoZW5kIDwgMCkgZW5kID0gMFxuICB9IGVsc2UgaWYgKGVuZCA+IGxlbikge1xuICAgIGVuZCA9IGxlblxuICB9XG5cbiAgaWYgKGVuZCA8IHN0YXJ0KSBlbmQgPSBzdGFydFxuXG4gIHZhciBuZXdCdWZcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgbmV3QnVmID0gQnVmZmVyLl9hdWdtZW50KHRoaXMuc3ViYXJyYXkoc3RhcnQsIGVuZCkpXG4gIH0gZWxzZSB7XG4gICAgdmFyIHNsaWNlTGVuID0gZW5kIC0gc3RhcnRcbiAgICBuZXdCdWYgPSBuZXcgQnVmZmVyKHNsaWNlTGVuLCB1bmRlZmluZWQpXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzbGljZUxlbjsgaSsrKSB7XG4gICAgICBuZXdCdWZbaV0gPSB0aGlzW2kgKyBzdGFydF1cbiAgICB9XG4gIH1cblxuICBpZiAobmV3QnVmLmxlbmd0aCkgbmV3QnVmLnBhcmVudCA9IHRoaXMucGFyZW50IHx8IHRoaXNcblxuICByZXR1cm4gbmV3QnVmXG59XG5cbi8qXG4gKiBOZWVkIHRvIG1ha2Ugc3VyZSB0aGF0IGJ1ZmZlciBpc24ndCB0cnlpbmcgdG8gd3JpdGUgb3V0IG9mIGJvdW5kcy5cbiAqL1xuZnVuY3Rpb24gY2hlY2tPZmZzZXQgKG9mZnNldCwgZXh0LCBsZW5ndGgpIHtcbiAgaWYgKChvZmZzZXQgJSAxKSAhPT0gMCB8fCBvZmZzZXQgPCAwKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignb2Zmc2V0IGlzIG5vdCB1aW50JylcbiAgaWYgKG9mZnNldCArIGV4dCA+IGxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1RyeWluZyB0byBhY2Nlc3MgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50TEUgPSBmdW5jdGlvbiByZWFkVUludExFIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0XVxuICB2YXIgbXVsID0gMVxuICB2YXIgaSA9IDBcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyBpXSAqIG11bFxuICB9XG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50QkUgPSBmdW5jdGlvbiByZWFkVUludEJFIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggfCAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjaGVja09mZnNldChvZmZzZXQsIGJ5dGVMZW5ndGgsIHRoaXMubGVuZ3RoKVxuICB9XG5cbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0ICsgLS1ieXRlTGVuZ3RoXVxuICB2YXIgbXVsID0gMVxuICB3aGlsZSAoYnl0ZUxlbmd0aCA+IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyAtLWJ5dGVMZW5ndGhdICogbXVsXG4gIH1cblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQ4ID0gZnVuY3Rpb24gcmVhZFVJbnQ4IChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMSwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiB0aGlzW29mZnNldF1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDE2TEUgPSBmdW5jdGlvbiByZWFkVUludDE2TEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIHRoaXNbb2Zmc2V0XSB8ICh0aGlzW29mZnNldCArIDFdIDw8IDgpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQxNkJFID0gZnVuY3Rpb24gcmVhZFVJbnQxNkJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiAodGhpc1tvZmZzZXRdIDw8IDgpIHwgdGhpc1tvZmZzZXQgKyAxXVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MzJMRSA9IGZ1bmN0aW9uIHJlYWRVSW50MzJMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuXG4gIHJldHVybiAoKHRoaXNbb2Zmc2V0XSkgfFxuICAgICAgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOCkgfFxuICAgICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgMTYpKSArXG4gICAgICAodGhpc1tvZmZzZXQgKyAzXSAqIDB4MTAwMDAwMClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDMyQkUgPSBmdW5jdGlvbiByZWFkVUludDMyQkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSAqIDB4MTAwMDAwMCkgK1xuICAgICgodGhpc1tvZmZzZXQgKyAxXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDJdIDw8IDgpIHxcbiAgICB0aGlzW29mZnNldCArIDNdKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnRMRSA9IGZ1bmN0aW9uIHJlYWRJbnRMRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoIHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIGJ5dGVMZW5ndGgsIHRoaXMubGVuZ3RoKVxuXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldF1cbiAgdmFyIG11bCA9IDFcbiAgdmFyIGkgPSAwXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgaV0gKiBtdWxcbiAgfVxuICBtdWwgKj0gMHg4MFxuXG4gIGlmICh2YWwgPj0gbXVsKSB2YWwgLT0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpXG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnRCRSA9IGZ1bmN0aW9uIHJlYWRJbnRCRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoIHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIGJ5dGVMZW5ndGgsIHRoaXMubGVuZ3RoKVxuXG4gIHZhciBpID0gYnl0ZUxlbmd0aFxuICB2YXIgbXVsID0gMVxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXQgKyAtLWldXG4gIHdoaWxlIChpID4gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHZhbCArPSB0aGlzW29mZnNldCArIC0taV0gKiBtdWxcbiAgfVxuICBtdWwgKj0gMHg4MFxuXG4gIGlmICh2YWwgPj0gbXVsKSB2YWwgLT0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpXG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQ4ID0gZnVuY3Rpb24gcmVhZEludDggKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAxLCB0aGlzLmxlbmd0aClcbiAgaWYgKCEodGhpc1tvZmZzZXRdICYgMHg4MCkpIHJldHVybiAodGhpc1tvZmZzZXRdKVxuICByZXR1cm4gKCgweGZmIC0gdGhpc1tvZmZzZXRdICsgMSkgKiAtMSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MTZMRSA9IGZ1bmN0aW9uIHJlYWRJbnQxNkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldF0gfCAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KVxuICByZXR1cm4gKHZhbCAmIDB4ODAwMCkgPyB2YWwgfCAweEZGRkYwMDAwIDogdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDE2QkUgPSBmdW5jdGlvbiByZWFkSW50MTZCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXQgKyAxXSB8ICh0aGlzW29mZnNldF0gPDwgOClcbiAgcmV0dXJuICh2YWwgJiAweDgwMDApID8gdmFsIHwgMHhGRkZGMDAwMCA6IHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQzMkxFID0gZnVuY3Rpb24gcmVhZEludDMyTEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSkgfFxuICAgICh0aGlzW29mZnNldCArIDFdIDw8IDgpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDNdIDw8IDI0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQzMkJFID0gZnVuY3Rpb24gcmVhZEludDMyQkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSA8PCAyNCkgfFxuICAgICh0aGlzW29mZnNldCArIDFdIDw8IDE2KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgOCkgfFxuICAgICh0aGlzW29mZnNldCArIDNdKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRGbG9hdExFID0gZnVuY3Rpb24gcmVhZEZsb2F0TEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIHRydWUsIDIzLCA0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRGbG9hdEJFID0gZnVuY3Rpb24gcmVhZEZsb2F0QkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIGZhbHNlLCAyMywgNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRG91YmxlTEUgPSBmdW5jdGlvbiByZWFkRG91YmxlTEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA4LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIHRydWUsIDUyLCA4KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWREb3VibGVCRSA9IGZ1bmN0aW9uIHJlYWREb3VibGVCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDgsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgZmFsc2UsIDUyLCA4KVxufVxuXG5mdW5jdGlvbiBjaGVja0ludCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBleHQsIG1heCwgbWluKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGJ1ZikpIHRocm93IG5ldyBUeXBlRXJyb3IoJ2J1ZmZlciBtdXN0IGJlIGEgQnVmZmVyIGluc3RhbmNlJylcbiAgaWYgKHZhbHVlID4gbWF4IHx8IHZhbHVlIDwgbWluKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcigndmFsdWUgaXMgb3V0IG9mIGJvdW5kcycpXG4gIGlmIChvZmZzZXQgKyBleHQgPiBidWYubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignaW5kZXggb3V0IG9mIHJhbmdlJylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnRMRSA9IGZ1bmN0aW9uIHdyaXRlVUludExFICh2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoIHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCksIDApXG5cbiAgdmFyIG11bCA9IDFcbiAgdmFyIGkgPSAwXG4gIHRoaXNbb2Zmc2V0XSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAodmFsdWUgLyBtdWwpICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnRCRSA9IGZ1bmN0aW9uIHdyaXRlVUludEJFICh2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoIHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCksIDApXG5cbiAgdmFyIGkgPSBieXRlTGVuZ3RoIC0gMVxuICB2YXIgbXVsID0gMVxuICB0aGlzW29mZnNldCArIGldID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgtLWkgPj0gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAodmFsdWUgLyBtdWwpICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQ4ID0gZnVuY3Rpb24gd3JpdGVVSW50OCAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAxLCAweGZmLCAwKVxuICBpZiAoIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB2YWx1ZSA9IE1hdGguZmxvb3IodmFsdWUpXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyAxXG59XG5cbmZ1bmN0aW9uIG9iamVjdFdyaXRlVUludDE2IChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbikge1xuICBpZiAodmFsdWUgPCAwKSB2YWx1ZSA9IDB4ZmZmZiArIHZhbHVlICsgMVxuICBmb3IgKHZhciBpID0gMCwgaiA9IE1hdGgubWluKGJ1Zi5sZW5ndGggLSBvZmZzZXQsIDIpOyBpIDwgajsgaSsrKSB7XG4gICAgYnVmW29mZnNldCArIGldID0gKHZhbHVlICYgKDB4ZmYgPDwgKDggKiAobGl0dGxlRW5kaWFuID8gaSA6IDEgLSBpKSkpKSA+Pj5cbiAgICAgIChsaXR0bGVFbmRpYW4gPyBpIDogMSAtIGkpICogOFxuICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MTZMRSA9IGZ1bmN0aW9uIHdyaXRlVUludDE2TEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMiwgMHhmZmZmLCAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDE2QkUgPSBmdW5jdGlvbiB3cml0ZVVJbnQxNkJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4ZmZmZiwgMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgJiAweGZmKVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbmZ1bmN0aW9uIG9iamVjdFdyaXRlVUludDMyIChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbikge1xuICBpZiAodmFsdWUgPCAwKSB2YWx1ZSA9IDB4ZmZmZmZmZmYgKyB2YWx1ZSArIDFcbiAgZm9yICh2YXIgaSA9IDAsIGogPSBNYXRoLm1pbihidWYubGVuZ3RoIC0gb2Zmc2V0LCA0KTsgaSA8IGo7IGkrKykge1xuICAgIGJ1ZltvZmZzZXQgKyBpXSA9ICh2YWx1ZSA+Pj4gKGxpdHRsZUVuZGlhbiA/IGkgOiAzIC0gaSkgKiA4KSAmIDB4ZmZcbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDMyTEUgPSBmdW5jdGlvbiB3cml0ZVVJbnQzMkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4ZmZmZmZmZmYsIDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgPj4+IDI0KVxuICAgIHRoaXNbb2Zmc2V0ICsgMl0gPSAodmFsdWUgPj4+IDE2KVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MzJCRSA9IGZ1bmN0aW9uIHdyaXRlVUludDMyQkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgNCwgMHhmZmZmZmZmZiwgMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiAyNClcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiAxNilcbiAgICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgJiAweGZmKVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnRMRSA9IGZ1bmN0aW9uIHdyaXRlSW50TEUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIHZhciBsaW1pdCA9IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoIC0gMSlcblxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIGxpbWl0IC0gMSwgLWxpbWl0KVxuICB9XG5cbiAgdmFyIGkgPSAwXG4gIHZhciBtdWwgPSAxXG4gIHZhciBzdWIgPSB2YWx1ZSA8IDAgPyAxIDogMFxuICB0aGlzW29mZnNldF0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB0aGlzW29mZnNldCArIGldID0gKCh2YWx1ZSAvIG11bCkgPj4gMCkgLSBzdWIgJiAweEZGXG4gIH1cblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50QkUgPSBmdW5jdGlvbiB3cml0ZUludEJFICh2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICB2YXIgbGltaXQgPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCAtIDEpXG5cbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBsaW1pdCAtIDEsIC1saW1pdClcbiAgfVxuXG4gIHZhciBpID0gYnl0ZUxlbmd0aCAtIDFcbiAgdmFyIG11bCA9IDFcbiAgdmFyIHN1YiA9IHZhbHVlIDwgMCA/IDEgOiAwXG4gIHRoaXNbb2Zmc2V0ICsgaV0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKC0taSA+PSAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICgodmFsdWUgLyBtdWwpID4+IDApIC0gc3ViICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDggPSBmdW5jdGlvbiB3cml0ZUludDggKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMSwgMHg3ZiwgLTB4ODApXG4gIGlmICghQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHZhbHVlID0gTWF0aC5mbG9vcih2YWx1ZSlcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmICsgdmFsdWUgKyAxXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyAxXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQxNkxFID0gZnVuY3Rpb24gd3JpdGVJbnQxNkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4N2ZmZiwgLTB4ODAwMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDE2QkUgPSBmdW5jdGlvbiB3cml0ZUludDE2QkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMiwgMHg3ZmZmLCAtMHg4MDAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDMyTEUgPSBmdW5jdGlvbiB3cml0ZUludDMyTEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgNCwgMHg3ZmZmZmZmZiwgLTB4ODAwMDAwMDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiAxNilcbiAgICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlID4+PiAyNClcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQzMkJFID0gZnVuY3Rpb24gd3JpdGVJbnQzMkJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4N2ZmZmZmZmYsIC0weDgwMDAwMDAwKVxuICBpZiAodmFsdWUgPCAwKSB2YWx1ZSA9IDB4ZmZmZmZmZmYgKyB2YWx1ZSArIDFcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiAyNClcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiAxNilcbiAgICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgJiAweGZmKVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbmZ1bmN0aW9uIGNoZWNrSUVFRTc1NCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBleHQsIG1heCwgbWluKSB7XG4gIGlmICh2YWx1ZSA+IG1heCB8fCB2YWx1ZSA8IG1pbikgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3ZhbHVlIGlzIG91dCBvZiBib3VuZHMnKVxuICBpZiAob2Zmc2V0ICsgZXh0ID4gYnVmLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2luZGV4IG91dCBvZiByYW5nZScpXG4gIGlmIChvZmZzZXQgPCAwKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignaW5kZXggb3V0IG9mIHJhbmdlJylcbn1cblxuZnVuY3Rpb24gd3JpdGVGbG9hdCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjaGVja0lFRUU3NTQoYnVmLCB2YWx1ZSwgb2Zmc2V0LCA0LCAzLjQwMjgyMzQ2NjM4NTI4ODZlKzM4LCAtMy40MDI4MjM0NjYzODUyODg2ZSszOClcbiAgfVxuICBpZWVlNzU0LndyaXRlKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCAyMywgNClcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0TEUgPSBmdW5jdGlvbiB3cml0ZUZsb2F0TEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZUZsb2F0KHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRmxvYXRCRSA9IGZ1bmN0aW9uIHdyaXRlRmxvYXRCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRmxvYXQodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5mdW5jdGlvbiB3cml0ZURvdWJsZSAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjaGVja0lFRUU3NTQoYnVmLCB2YWx1ZSwgb2Zmc2V0LCA4LCAxLjc5NzY5MzEzNDg2MjMxNTdFKzMwOCwgLTEuNzk3NjkzMTM0ODYyMzE1N0UrMzA4KVxuICB9XG4gIGllZWU3NTQud3JpdGUoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIDUyLCA4KVxuICByZXR1cm4gb2Zmc2V0ICsgOFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRG91YmxlTEUgPSBmdW5jdGlvbiB3cml0ZURvdWJsZUxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVEb3VibGUodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVEb3VibGVCRSA9IGZ1bmN0aW9uIHdyaXRlRG91YmxlQkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZURvdWJsZSh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbi8vIGNvcHkodGFyZ2V0QnVmZmVyLCB0YXJnZXRTdGFydD0wLCBzb3VyY2VTdGFydD0wLCBzb3VyY2VFbmQ9YnVmZmVyLmxlbmd0aClcbkJ1ZmZlci5wcm90b3R5cGUuY29weSA9IGZ1bmN0aW9uIGNvcHkgKHRhcmdldCwgdGFyZ2V0U3RhcnQsIHN0YXJ0LCBlbmQpIHtcbiAgaWYgKCFzdGFydCkgc3RhcnQgPSAwXG4gIGlmICghZW5kICYmIGVuZCAhPT0gMCkgZW5kID0gdGhpcy5sZW5ndGhcbiAgaWYgKHRhcmdldFN0YXJ0ID49IHRhcmdldC5sZW5ndGgpIHRhcmdldFN0YXJ0ID0gdGFyZ2V0Lmxlbmd0aFxuICBpZiAoIXRhcmdldFN0YXJ0KSB0YXJnZXRTdGFydCA9IDBcbiAgaWYgKGVuZCA+IDAgJiYgZW5kIDwgc3RhcnQpIGVuZCA9IHN0YXJ0XG5cbiAgLy8gQ29weSAwIGJ5dGVzOyB3ZSdyZSBkb25lXG4gIGlmIChlbmQgPT09IHN0YXJ0KSByZXR1cm4gMFxuICBpZiAodGFyZ2V0Lmxlbmd0aCA9PT0gMCB8fCB0aGlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIDBcblxuICAvLyBGYXRhbCBlcnJvciBjb25kaXRpb25zXG4gIGlmICh0YXJnZXRTdGFydCA8IDApIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcigndGFyZ2V0U3RhcnQgb3V0IG9mIGJvdW5kcycpXG4gIH1cbiAgaWYgKHN0YXJ0IDwgMCB8fCBzdGFydCA+PSB0aGlzLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3NvdXJjZVN0YXJ0IG91dCBvZiBib3VuZHMnKVxuICBpZiAoZW5kIDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3NvdXJjZUVuZCBvdXQgb2YgYm91bmRzJylcblxuICAvLyBBcmUgd2Ugb29iP1xuICBpZiAoZW5kID4gdGhpcy5sZW5ndGgpIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmICh0YXJnZXQubGVuZ3RoIC0gdGFyZ2V0U3RhcnQgPCBlbmQgLSBzdGFydCkge1xuICAgIGVuZCA9IHRhcmdldC5sZW5ndGggLSB0YXJnZXRTdGFydCArIHN0YXJ0XG4gIH1cblxuICB2YXIgbGVuID0gZW5kIC0gc3RhcnRcbiAgdmFyIGlcblxuICBpZiAodGhpcyA9PT0gdGFyZ2V0ICYmIHN0YXJ0IDwgdGFyZ2V0U3RhcnQgJiYgdGFyZ2V0U3RhcnQgPCBlbmQpIHtcbiAgICAvLyBkZXNjZW5kaW5nIGNvcHkgZnJvbSBlbmRcbiAgICBmb3IgKGkgPSBsZW4gLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgdGFyZ2V0W2kgKyB0YXJnZXRTdGFydF0gPSB0aGlzW2kgKyBzdGFydF1cbiAgICB9XG4gIH0gZWxzZSBpZiAobGVuIDwgMTAwMCB8fCAhQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICAvLyBhc2NlbmRpbmcgY29weSBmcm9tIHN0YXJ0XG4gICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICB0YXJnZXRbaSArIHRhcmdldFN0YXJ0XSA9IHRoaXNbaSArIHN0YXJ0XVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB0YXJnZXQuX3NldCh0aGlzLnN1YmFycmF5KHN0YXJ0LCBzdGFydCArIGxlbiksIHRhcmdldFN0YXJ0KVxuICB9XG5cbiAgcmV0dXJuIGxlblxufVxuXG4vLyBmaWxsKHZhbHVlLCBzdGFydD0wLCBlbmQ9YnVmZmVyLmxlbmd0aClcbkJ1ZmZlci5wcm90b3R5cGUuZmlsbCA9IGZ1bmN0aW9uIGZpbGwgKHZhbHVlLCBzdGFydCwgZW5kKSB7XG4gIGlmICghdmFsdWUpIHZhbHVlID0gMFxuICBpZiAoIXN0YXJ0KSBzdGFydCA9IDBcbiAgaWYgKCFlbmQpIGVuZCA9IHRoaXMubGVuZ3RoXG5cbiAgaWYgKGVuZCA8IHN0YXJ0KSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignZW5kIDwgc3RhcnQnKVxuXG4gIC8vIEZpbGwgMCBieXRlczsgd2UncmUgZG9uZVxuICBpZiAoZW5kID09PSBzdGFydCkgcmV0dXJuXG4gIGlmICh0aGlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuXG5cbiAgaWYgKHN0YXJ0IDwgMCB8fCBzdGFydCA+PSB0aGlzLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3N0YXJ0IG91dCBvZiBib3VuZHMnKVxuICBpZiAoZW5kIDwgMCB8fCBlbmQgPiB0aGlzLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2VuZCBvdXQgb2YgYm91bmRzJylcblxuICB2YXIgaVxuICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgIGZvciAoaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICAgIHRoaXNbaV0gPSB2YWx1ZVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB2YXIgYnl0ZXMgPSB1dGY4VG9CeXRlcyh2YWx1ZS50b1N0cmluZygpKVxuICAgIHZhciBsZW4gPSBieXRlcy5sZW5ndGhcbiAgICBmb3IgKGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICB0aGlzW2ldID0gYnl0ZXNbaSAlIGxlbl1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGhpc1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgYEFycmF5QnVmZmVyYCB3aXRoIHRoZSAqY29waWVkKiBtZW1vcnkgb2YgdGhlIGJ1ZmZlciBpbnN0YW5jZS5cbiAqIEFkZGVkIGluIE5vZGUgMC4xMi4gT25seSBhdmFpbGFibGUgaW4gYnJvd3NlcnMgdGhhdCBzdXBwb3J0IEFycmF5QnVmZmVyLlxuICovXG5CdWZmZXIucHJvdG90eXBlLnRvQXJyYXlCdWZmZXIgPSBmdW5jdGlvbiB0b0FycmF5QnVmZmVyICgpIHtcbiAgaWYgKHR5cGVvZiBVaW50OEFycmF5ICE9PSAndW5kZWZpbmVkJykge1xuICAgIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgICAgcmV0dXJuIChuZXcgQnVmZmVyKHRoaXMpKS5idWZmZXJcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGJ1ZiA9IG5ldyBVaW50OEFycmF5KHRoaXMubGVuZ3RoKVxuICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGJ1Zi5sZW5ndGg7IGkgPCBsZW47IGkgKz0gMSkge1xuICAgICAgICBidWZbaV0gPSB0aGlzW2ldXG4gICAgICB9XG4gICAgICByZXR1cm4gYnVmLmJ1ZmZlclxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdCdWZmZXIudG9BcnJheUJ1ZmZlciBub3Qgc3VwcG9ydGVkIGluIHRoaXMgYnJvd3NlcicpXG4gIH1cbn1cblxuLy8gSEVMUEVSIEZVTkNUSU9OU1xuLy8gPT09PT09PT09PT09PT09PVxuXG52YXIgQlAgPSBCdWZmZXIucHJvdG90eXBlXG5cbi8qKlxuICogQXVnbWVudCBhIFVpbnQ4QXJyYXkgKmluc3RhbmNlKiAobm90IHRoZSBVaW50OEFycmF5IGNsYXNzISkgd2l0aCBCdWZmZXIgbWV0aG9kc1xuICovXG5CdWZmZXIuX2F1Z21lbnQgPSBmdW5jdGlvbiBfYXVnbWVudCAoYXJyKSB7XG4gIGFyci5jb25zdHJ1Y3RvciA9IEJ1ZmZlclxuICBhcnIuX2lzQnVmZmVyID0gdHJ1ZVxuXG4gIC8vIHNhdmUgcmVmZXJlbmNlIHRvIG9yaWdpbmFsIFVpbnQ4QXJyYXkgc2V0IG1ldGhvZCBiZWZvcmUgb3ZlcndyaXRpbmdcbiAgYXJyLl9zZXQgPSBhcnIuc2V0XG5cbiAgLy8gZGVwcmVjYXRlZFxuICBhcnIuZ2V0ID0gQlAuZ2V0XG4gIGFyci5zZXQgPSBCUC5zZXRcblxuICBhcnIud3JpdGUgPSBCUC53cml0ZVxuICBhcnIudG9TdHJpbmcgPSBCUC50b1N0cmluZ1xuICBhcnIudG9Mb2NhbGVTdHJpbmcgPSBCUC50b1N0cmluZ1xuICBhcnIudG9KU09OID0gQlAudG9KU09OXG4gIGFyci5lcXVhbHMgPSBCUC5lcXVhbHNcbiAgYXJyLmNvbXBhcmUgPSBCUC5jb21wYXJlXG4gIGFyci5pbmRleE9mID0gQlAuaW5kZXhPZlxuICBhcnIuY29weSA9IEJQLmNvcHlcbiAgYXJyLnNsaWNlID0gQlAuc2xpY2VcbiAgYXJyLnJlYWRVSW50TEUgPSBCUC5yZWFkVUludExFXG4gIGFyci5yZWFkVUludEJFID0gQlAucmVhZFVJbnRCRVxuICBhcnIucmVhZFVJbnQ4ID0gQlAucmVhZFVJbnQ4XG4gIGFyci5yZWFkVUludDE2TEUgPSBCUC5yZWFkVUludDE2TEVcbiAgYXJyLnJlYWRVSW50MTZCRSA9IEJQLnJlYWRVSW50MTZCRVxuICBhcnIucmVhZFVJbnQzMkxFID0gQlAucmVhZFVJbnQzMkxFXG4gIGFyci5yZWFkVUludDMyQkUgPSBCUC5yZWFkVUludDMyQkVcbiAgYXJyLnJlYWRJbnRMRSA9IEJQLnJlYWRJbnRMRVxuICBhcnIucmVhZEludEJFID0gQlAucmVhZEludEJFXG4gIGFyci5yZWFkSW50OCA9IEJQLnJlYWRJbnQ4XG4gIGFyci5yZWFkSW50MTZMRSA9IEJQLnJlYWRJbnQxNkxFXG4gIGFyci5yZWFkSW50MTZCRSA9IEJQLnJlYWRJbnQxNkJFXG4gIGFyci5yZWFkSW50MzJMRSA9IEJQLnJlYWRJbnQzMkxFXG4gIGFyci5yZWFkSW50MzJCRSA9IEJQLnJlYWRJbnQzMkJFXG4gIGFyci5yZWFkRmxvYXRMRSA9IEJQLnJlYWRGbG9hdExFXG4gIGFyci5yZWFkRmxvYXRCRSA9IEJQLnJlYWRGbG9hdEJFXG4gIGFyci5yZWFkRG91YmxlTEUgPSBCUC5yZWFkRG91YmxlTEVcbiAgYXJyLnJlYWREb3VibGVCRSA9IEJQLnJlYWREb3VibGVCRVxuICBhcnIud3JpdGVVSW50OCA9IEJQLndyaXRlVUludDhcbiAgYXJyLndyaXRlVUludExFID0gQlAud3JpdGVVSW50TEVcbiAgYXJyLndyaXRlVUludEJFID0gQlAud3JpdGVVSW50QkVcbiAgYXJyLndyaXRlVUludDE2TEUgPSBCUC53cml0ZVVJbnQxNkxFXG4gIGFyci53cml0ZVVJbnQxNkJFID0gQlAud3JpdGVVSW50MTZCRVxuICBhcnIud3JpdGVVSW50MzJMRSA9IEJQLndyaXRlVUludDMyTEVcbiAgYXJyLndyaXRlVUludDMyQkUgPSBCUC53cml0ZVVJbnQzMkJFXG4gIGFyci53cml0ZUludExFID0gQlAud3JpdGVJbnRMRVxuICBhcnIud3JpdGVJbnRCRSA9IEJQLndyaXRlSW50QkVcbiAgYXJyLndyaXRlSW50OCA9IEJQLndyaXRlSW50OFxuICBhcnIud3JpdGVJbnQxNkxFID0gQlAud3JpdGVJbnQxNkxFXG4gIGFyci53cml0ZUludDE2QkUgPSBCUC53cml0ZUludDE2QkVcbiAgYXJyLndyaXRlSW50MzJMRSA9IEJQLndyaXRlSW50MzJMRVxuICBhcnIud3JpdGVJbnQzMkJFID0gQlAud3JpdGVJbnQzMkJFXG4gIGFyci53cml0ZUZsb2F0TEUgPSBCUC53cml0ZUZsb2F0TEVcbiAgYXJyLndyaXRlRmxvYXRCRSA9IEJQLndyaXRlRmxvYXRCRVxuICBhcnIud3JpdGVEb3VibGVMRSA9IEJQLndyaXRlRG91YmxlTEVcbiAgYXJyLndyaXRlRG91YmxlQkUgPSBCUC53cml0ZURvdWJsZUJFXG4gIGFyci5maWxsID0gQlAuZmlsbFxuICBhcnIuaW5zcGVjdCA9IEJQLmluc3BlY3RcbiAgYXJyLnRvQXJyYXlCdWZmZXIgPSBCUC50b0FycmF5QnVmZmVyXG5cbiAgcmV0dXJuIGFyclxufVxuXG52YXIgSU5WQUxJRF9CQVNFNjRfUkUgPSAvW14rXFwvMC05QS1aYS16LV9dL2dcblxuZnVuY3Rpb24gYmFzZTY0Y2xlYW4gKHN0cikge1xuICAvLyBOb2RlIHN0cmlwcyBvdXQgaW52YWxpZCBjaGFyYWN0ZXJzIGxpa2UgXFxuIGFuZCBcXHQgZnJvbSB0aGUgc3RyaW5nLCBiYXNlNjQtanMgZG9lcyBub3RcbiAgc3RyID0gc3RyaW5ndHJpbShzdHIpLnJlcGxhY2UoSU5WQUxJRF9CQVNFNjRfUkUsICcnKVxuICAvLyBOb2RlIGNvbnZlcnRzIHN0cmluZ3Mgd2l0aCBsZW5ndGggPCAyIHRvICcnXG4gIGlmIChzdHIubGVuZ3RoIDwgMikgcmV0dXJuICcnXG4gIC8vIE5vZGUgYWxsb3dzIGZvciBub24tcGFkZGVkIGJhc2U2NCBzdHJpbmdzIChtaXNzaW5nIHRyYWlsaW5nID09PSksIGJhc2U2NC1qcyBkb2VzIG5vdFxuICB3aGlsZSAoc3RyLmxlbmd0aCAlIDQgIT09IDApIHtcbiAgICBzdHIgPSBzdHIgKyAnPSdcbiAgfVxuICByZXR1cm4gc3RyXG59XG5cbmZ1bmN0aW9uIHN0cmluZ3RyaW0gKHN0cikge1xuICBpZiAoc3RyLnRyaW0pIHJldHVybiBzdHIudHJpbSgpXG4gIHJldHVybiBzdHIucmVwbGFjZSgvXlxccyt8XFxzKyQvZywgJycpXG59XG5cbmZ1bmN0aW9uIHRvSGV4IChuKSB7XG4gIGlmIChuIDwgMTYpIHJldHVybiAnMCcgKyBuLnRvU3RyaW5nKDE2KVxuICByZXR1cm4gbi50b1N0cmluZygxNilcbn1cblxuZnVuY3Rpb24gdXRmOFRvQnl0ZXMgKHN0cmluZywgdW5pdHMpIHtcbiAgdW5pdHMgPSB1bml0cyB8fCBJbmZpbml0eVxuICB2YXIgY29kZVBvaW50XG4gIHZhciBsZW5ndGggPSBzdHJpbmcubGVuZ3RoXG4gIHZhciBsZWFkU3Vycm9nYXRlID0gbnVsbFxuICB2YXIgYnl0ZXMgPSBbXVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICBjb2RlUG9pbnQgPSBzdHJpbmcuY2hhckNvZGVBdChpKVxuXG4gICAgLy8gaXMgc3Vycm9nYXRlIGNvbXBvbmVudFxuICAgIGlmIChjb2RlUG9pbnQgPiAweEQ3RkYgJiYgY29kZVBvaW50IDwgMHhFMDAwKSB7XG4gICAgICAvLyBsYXN0IGNoYXIgd2FzIGEgbGVhZFxuICAgICAgaWYgKCFsZWFkU3Vycm9nYXRlKSB7XG4gICAgICAgIC8vIG5vIGxlYWQgeWV0XG4gICAgICAgIGlmIChjb2RlUG9pbnQgPiAweERCRkYpIHtcbiAgICAgICAgICAvLyB1bmV4cGVjdGVkIHRyYWlsXG4gICAgICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfSBlbHNlIGlmIChpICsgMSA9PT0gbGVuZ3RoKSB7XG4gICAgICAgICAgLy8gdW5wYWlyZWQgbGVhZFxuICAgICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cblxuICAgICAgICAvLyB2YWxpZCBsZWFkXG4gICAgICAgIGxlYWRTdXJyb2dhdGUgPSBjb2RlUG9pbnRcblxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICAvLyAyIGxlYWRzIGluIGEgcm93XG4gICAgICBpZiAoY29kZVBvaW50IDwgMHhEQzAwKSB7XG4gICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICBsZWFkU3Vycm9nYXRlID0gY29kZVBvaW50XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIC8vIHZhbGlkIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBjb2RlUG9pbnQgPSAobGVhZFN1cnJvZ2F0ZSAtIDB4RDgwMCA8PCAxMCB8IGNvZGVQb2ludCAtIDB4REMwMCkgKyAweDEwMDAwXG4gICAgfSBlbHNlIGlmIChsZWFkU3Vycm9nYXRlKSB7XG4gICAgICAvLyB2YWxpZCBibXAgY2hhciwgYnV0IGxhc3QgY2hhciB3YXMgYSBsZWFkXG4gICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICB9XG5cbiAgICBsZWFkU3Vycm9nYXRlID0gbnVsbFxuXG4gICAgLy8gZW5jb2RlIHV0ZjhcbiAgICBpZiAoY29kZVBvaW50IDwgMHg4MCkge1xuICAgICAgaWYgKCh1bml0cyAtPSAxKSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKGNvZGVQb2ludClcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA8IDB4ODAwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDIpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDYgfCAweEMwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHgxMDAwMCkge1xuICAgICAgaWYgKCh1bml0cyAtPSAzKSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHhDIHwgMHhFMCxcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiAmIDB4M0YgfCAweDgwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHgxMTAwMDApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gNCkgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChcbiAgICAgICAgY29kZVBvaW50ID4+IDB4MTIgfCAweEYwLFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHhDICYgMHgzRiB8IDB4ODAsXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDYgJiAweDNGIHwgMHg4MCxcbiAgICAgICAgY29kZVBvaW50ICYgMHgzRiB8IDB4ODBcbiAgICAgIClcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNvZGUgcG9pbnQnKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBieXRlc1xufVxuXG5mdW5jdGlvbiBhc2NpaVRvQnl0ZXMgKHN0cikge1xuICB2YXIgYnl0ZUFycmF5ID0gW11cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAvLyBOb2RlJ3MgY29kZSBzZWVtcyB0byBiZSBkb2luZyB0aGlzIGFuZCBub3QgJiAweDdGLi5cbiAgICBieXRlQXJyYXkucHVzaChzdHIuY2hhckNvZGVBdChpKSAmIDB4RkYpXG4gIH1cbiAgcmV0dXJuIGJ5dGVBcnJheVxufVxuXG5mdW5jdGlvbiB1dGYxNmxlVG9CeXRlcyAoc3RyLCB1bml0cykge1xuICB2YXIgYywgaGksIGxvXG4gIHZhciBieXRlQXJyYXkgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgIGlmICgodW5pdHMgLT0gMikgPCAwKSBicmVha1xuXG4gICAgYyA9IHN0ci5jaGFyQ29kZUF0KGkpXG4gICAgaGkgPSBjID4+IDhcbiAgICBsbyA9IGMgJSAyNTZcbiAgICBieXRlQXJyYXkucHVzaChsbylcbiAgICBieXRlQXJyYXkucHVzaChoaSlcbiAgfVxuXG4gIHJldHVybiBieXRlQXJyYXlcbn1cblxuZnVuY3Rpb24gYmFzZTY0VG9CeXRlcyAoc3RyKSB7XG4gIHJldHVybiBiYXNlNjQudG9CeXRlQXJyYXkoYmFzZTY0Y2xlYW4oc3RyKSlcbn1cblxuZnVuY3Rpb24gYmxpdEJ1ZmZlciAoc3JjLCBkc3QsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoKGkgKyBvZmZzZXQgPj0gZHN0Lmxlbmd0aCkgfHwgKGkgPj0gc3JjLmxlbmd0aCkpIGJyZWFrXG4gICAgZHN0W2kgKyBvZmZzZXRdID0gc3JjW2ldXG4gIH1cbiAgcmV0dXJuIGlcbn1cbiJdfQ== | |
},{"base64-js":2,"ieee754":3,"isarray":4}],2:[function(require,module,exports){ | |
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)) | |
},{}],3:[function(require,module,exports){ | |
exports.read = function (buffer, offset, isLE, mLen, nBytes) { | |
var e, m | |
var eLen = nBytes * 8 - mLen - 1 | |
var eMax = (1 << eLen) - 1 | |
var eBias = eMax >> 1 | |
var nBits = -7 | |
var i = isLE ? (nBytes - 1) : 0 | |
var d = isLE ? -1 : 1 | |
var s = buffer[offset + i] | |
i += d | |
e = s & ((1 << (-nBits)) - 1) | |
s >>= (-nBits) | |
nBits += eLen | |
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} | |
m = e & ((1 << (-nBits)) - 1) | |
e >>= (-nBits) | |
nBits += mLen | |
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} | |
if (e === 0) { | |
e = 1 - eBias | |
} else if (e === eMax) { | |
return m ? NaN : ((s ? -1 : 1) * Infinity) | |
} else { | |
m = m + Math.pow(2, mLen) | |
e = e - eBias | |
} | |
return (s ? -1 : 1) * m * Math.pow(2, e - mLen) | |
} | |
exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { | |
var e, m, c | |
var eLen = nBytes * 8 - mLen - 1 | |
var eMax = (1 << eLen) - 1 | |
var eBias = eMax >> 1 | |
var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) | |
var i = isLE ? 0 : (nBytes - 1) | |
var d = isLE ? 1 : -1 | |
var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 | |
value = Math.abs(value) | |
if (isNaN(value) || value === Infinity) { | |
m = isNaN(value) ? 1 : 0 | |
e = eMax | |
} else { | |
e = Math.floor(Math.log(value) / Math.LN2) | |
if (value * (c = Math.pow(2, -e)) < 1) { | |
e-- | |
c *= 2 | |
} | |
if (e + eBias >= 1) { | |
value += rt / c | |
} else { | |
value += rt * Math.pow(2, 1 - eBias) | |
} | |
if (value * c >= 2) { | |
e++ | |
c /= 2 | |
} | |
if (e + eBias >= eMax) { | |
m = 0 | |
e = eMax | |
} else if (e + eBias >= 1) { | |
m = (value * c - 1) * Math.pow(2, mLen) | |
e = e + eBias | |
} else { | |
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) | |
e = 0 | |
} | |
} | |
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} | |
e = (e << mLen) | m | |
eLen += mLen | |
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} | |
buffer[offset + i - d] |= s * 128 | |
} | |
},{}],4:[function(require,module,exports){ | |
var toString = {}.toString; | |
module.exports = Array.isArray || function (arr) { | |
return toString.call(arr) == '[object Array]'; | |
}; | |
},{}],5:[function(require,module,exports){ | |
// Copyright Joyent, Inc. and other Node contributors. | |
// | |
// Permission is hereby granted, free of charge, to any person obtaining a | |
// copy of this software and associated documentation files (the | |
// "Software"), to deal in the Software without restriction, including | |
// without limitation the rights to use, copy, modify, merge, publish, | |
// distribute, sublicense, and/or sell copies of the Software, and to permit | |
// persons to whom the Software is furnished to do so, subject to the | |
// following conditions: | |
// | |
// The above copyright notice and this permission notice shall be included | |
// in all copies or substantial portions of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN | |
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | |
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | |
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | |
// USE OR OTHER DEALINGS IN THE SOFTWARE. | |
function EventEmitter() { | |
this._events = this._events || {}; | |
this._maxListeners = this._maxListeners || undefined; | |
} | |
module.exports = EventEmitter; | |
// Backwards-compat with node 0.10.x | |
EventEmitter.EventEmitter = EventEmitter; | |
EventEmitter.prototype._events = undefined; | |
EventEmitter.prototype._maxListeners = undefined; | |
// By default EventEmitters will print a warning if more than 10 listeners are | |
// added to it. This is a useful default which helps finding memory leaks. | |
EventEmitter.defaultMaxListeners = 10; | |
// Obviously not all Emitters should be limited to 10. This function allows | |
// that to be increased. Set to zero for unlimited. | |
EventEmitter.prototype.setMaxListeners = function(n) { | |
if (!isNumber(n) || n < 0 || isNaN(n)) | |
throw TypeError('n must be a positive number'); | |
this._maxListeners = n; | |
return this; | |
}; | |
EventEmitter.prototype.emit = function(type) { | |
var er, handler, len, args, i, listeners; | |
if (!this._events) | |
this._events = {}; | |
// If there is no 'error' event listener then throw. | |
if (type === 'error') { | |
if (!this._events.error || | |
(isObject(this._events.error) && !this._events.error.length)) { | |
er = arguments[1]; | |
if (er instanceof Error) { | |
throw er; // Unhandled 'error' event | |
} | |
throw TypeError('Uncaught, unspecified "error" event.'); | |
} | |
} | |
handler = this._events[type]; | |
if (isUndefined(handler)) | |
return false; | |
if (isFunction(handler)) { | |
switch (arguments.length) { | |
// fast cases | |
case 1: | |
handler.call(this); | |
break; | |
case 2: | |
handler.call(this, arguments[1]); | |
break; | |
case 3: | |
handler.call(this, arguments[1], arguments[2]); | |
break; | |
// slower | |
default: | |
len = arguments.length; | |
args = new Array(len - 1); | |
for (i = 1; i < len; i++) | |
args[i - 1] = arguments[i]; | |
handler.apply(this, args); | |
} | |
} else if (isObject(handler)) { | |
len = arguments.length; | |
args = new Array(len - 1); | |
for (i = 1; i < len; i++) | |
args[i - 1] = arguments[i]; | |
listeners = handler.slice(); | |
len = listeners.length; | |
for (i = 0; i < len; i++) | |
listeners[i].apply(this, args); | |
} | |
return true; | |
}; | |
EventEmitter.prototype.addListener = function(type, listener) { | |
var m; | |
if (!isFunction(listener)) | |
throw TypeError('listener must be a function'); | |
if (!this._events) | |
this._events = {}; | |
// To avoid recursion in the case that type === "newListener"! Before | |
// adding it to the listeners, first emit "newListener". | |
if (this._events.newListener) | |
this.emit('newListener', type, | |
isFunction(listener.listener) ? | |
listener.listener : listener); | |
if (!this._events[type]) | |
// Optimize the case of one listener. Don't need the extra array object. | |
this._events[type] = listener; | |
else if (isObject(this._events[type])) | |
// If we've already got an array, just append. | |
this._events[type].push(listener); | |
else | |
// Adding the second element, need to change to array. | |
this._events[type] = [this._events[type], listener]; | |
// Check for listener leak | |
if (isObject(this._events[type]) && !this._events[type].warned) { | |
var m; | |
if (!isUndefined(this._maxListeners)) { | |
m = this._maxListeners; | |
} else { | |
m = EventEmitter.defaultMaxListeners; | |
} | |
if (m && m > 0 && this._events[type].length > m) { | |
this._events[type].warned = true; | |
console.error('(node) warning: possible EventEmitter memory ' + | |
'leak detected. %d listeners added. ' + | |
'Use emitter.setMaxListeners() to increase limit.', | |
this._events[type].length); | |
if (typeof console.trace === 'function') { | |
// not supported in IE 10 | |
console.trace(); | |
} | |
} | |
} | |
return this; | |
}; | |
EventEmitter.prototype.on = EventEmitter.prototype.addListener; | |
EventEmitter.prototype.once = function(type, listener) { | |
if (!isFunction(listener)) | |
throw TypeError('listener must be a function'); | |
var fired = false; | |
function g() { | |
this.removeListener(type, g); | |
if (!fired) { | |
fired = true; | |
listener.apply(this, arguments); | |
} | |
} | |
g.listener = listener; | |
this.on(type, g); | |
return this; | |
}; | |
// emits a 'removeListener' event iff the listener was removed | |
EventEmitter.prototype.removeListener = function(type, listener) { | |
var list, position, length, i; | |
if (!isFunction(listener)) | |
throw TypeError('listener must be a function'); | |
if (!this._events || !this._events[type]) | |
return this; | |
list = this._events[type]; | |
length = list.length; | |
position = -1; | |
if (list === listener || | |
(isFunction(list.listener) && list.listener === listener)) { | |
delete this._events[type]; | |
if (this._events.removeListener) | |
this.emit('removeListener', type, listener); | |
} else if (isObject(list)) { | |
for (i = length; i-- > 0;) { | |
if (list[i] === listener || | |
(list[i].listener && list[i].listener === listener)) { | |
position = i; | |
break; | |
} | |
} | |
if (position < 0) | |
return this; | |
if (list.length === 1) { | |
list.length = 0; | |
delete this._events[type]; | |
} else { | |
list.splice(position, 1); | |
} | |
if (this._events.removeListener) | |
this.emit('removeListener', type, listener); | |
} | |
return this; | |
}; | |
EventEmitter.prototype.removeAllListeners = function(type) { | |
var key, listeners; | |
if (!this._events) | |
return this; | |
// not listening for removeListener, no need to emit | |
if (!this._events.removeListener) { | |
if (arguments.length === 0) | |
this._events = {}; | |
else if (this._events[type]) | |
delete this._events[type]; | |
return this; | |
} | |
// emit removeListener for all listeners on all events | |
if (arguments.length === 0) { | |
for (key in this._events) { | |
if (key === 'removeListener') continue; | |
this.removeAllListeners(key); | |
} | |
this.removeAllListeners('removeListener'); | |
this._events = {}; | |
return this; | |
} | |
listeners = this._events[type]; | |
if (isFunction(listeners)) { | |
this.removeListener(type, listeners); | |
} else { | |
// LIFO order | |
while (listeners.length) | |
this.removeListener(type, listeners[listeners.length - 1]); | |
} | |
delete this._events[type]; | |
return this; | |
}; | |
EventEmitter.prototype.listeners = function(type) { | |
var ret; | |
if (!this._events || !this._events[type]) | |
ret = []; | |
else if (isFunction(this._events[type])) | |
ret = [this._events[type]]; | |
else | |
ret = this._events[type].slice(); | |
return ret; | |
}; | |
EventEmitter.listenerCount = function(emitter, type) { | |
var ret; | |
if (!emitter._events || !emitter._events[type]) | |
ret = 0; | |
else if (isFunction(emitter._events[type])) | |
ret = 1; | |
else | |
ret = emitter._events[type].length; | |
return ret; | |
}; | |
function isFunction(arg) { | |
return typeof arg === 'function'; | |
} | |
function isNumber(arg) { | |
return typeof arg === 'number'; | |
} | |
function isObject(arg) { | |
return typeof arg === 'object' && arg !== null; | |
} | |
function isUndefined(arg) { | |
return arg === void 0; | |
} | |
},{}],6:[function(require,module,exports){ | |
var is = require('./is'), | |
GENERIC = '_generic', | |
EventEmitter = require('events').EventEmitter, | |
slice = Array.prototype.slice; | |
function flatten(item){ | |
return Array.isArray(item) ? item.reduce(function(result, element){ | |
if(element == null){ | |
return result; | |
} | |
return result.concat(flatten(element)); | |
},[]) : item; | |
} | |
function attachProperties(object, firm){ | |
for(var key in this._properties){ | |
this._properties[key].attach(object, firm); | |
} | |
} | |
function onRender(){ | |
// Ensure all bindings are somewhat attached just before rendering | |
this.attach(undefined, 0); | |
for(var key in this._properties){ | |
this._properties[key].update(); | |
} | |
} | |
function detachProperties(firm){ | |
for(var key in this._properties){ | |
this._properties[key].detach(firm); | |
} | |
} | |
function destroyProperties(){ | |
for(var key in this._properties){ | |
this._properties[key].destroy(); | |
} | |
} | |
function clone(){ | |
return this.fastn(this.component._type, this.component._settings, this.component._children.filter(function(child){ | |
return !child._templated; | |
}).map(function(child){ | |
return child.clone(); | |
}) | |
); | |
} | |
function getSetBinding(newBinding){ | |
if(!arguments.length){ | |
return this.binding; | |
} | |
if(!is.binding(newBinding)){ | |
newBinding = this.fastn.binding(newBinding); | |
} | |
if(this.binding && this.binding !== newBinding){ | |
this.binding.removeListener('change', this.emitAttach); | |
newBinding.attach(this.binding._model, this.binding._firm); | |
} | |
this.binding = newBinding; | |
this.binding.on('change', this.emitAttach); | |
this.binding.on('detach', this.emitDetach); | |
this.emitAttach(); | |
return this.component; | |
}; | |
function emitAttach(){ | |
var newBound = this.binding(); | |
if(newBound !== this.lastBound){ | |
this.lastBound = newBound; | |
this.scope.attach(this.lastBound); | |
this.component.emit('attach', this.scope, 1); | |
} | |
} | |
function emitDetach(){ | |
this.component.emit('detach', 1); | |
} | |
function getScope(){ | |
return this.scope; | |
} | |
function destroy(){ | |
if(this.destroyed){ | |
return; | |
} | |
this.destroyed = true; | |
this.component | |
.removeAllListeners('render') | |
.removeAllListeners('attach'); | |
this.component.emit('destroy'); | |
this.component.element = null; | |
this.scope.destroy(); | |
this.binding.destroy(); | |
return this.component; | |
} | |
function attachComponent(object, firm){ | |
this.binding.attach(object, firm); | |
return this.component; | |
} | |
function detachComponent(firm){ | |
this.binding.detach(firm); | |
return this.component; | |
} | |
function isDestroyed(){ | |
return this.destroyed; | |
} | |
function setProperty(key, property){ | |
// Add a default property or use the one already there | |
if(!property){ | |
property = this.component[key] || this.fastn.property(); | |
} | |
this.component[key] = property; | |
this.component._properties[key] = property; | |
return this.component; | |
} | |
function extendComponent(type, settings, children){ | |
if(type in this.types){ | |
return this.component; | |
} | |
if(!(type in this.fastn.components)){ | |
if(!(GENERIC in this.fastn.components)){ | |
throw new Error('No component of type "' + type + '" is loaded'); | |
} | |
this.fastn.components._generic(this.fastn, this.component, type, settings, children); | |
this.types._generic = true; | |
}else{ | |
this.fastn.components[type](this.fastn, this.component, type, settings, children); | |
} | |
this.types[type] = true; | |
return this.component; | |
}; | |
function isType(type){ | |
return type in this.types; | |
} | |
function FastnComponent(fastn, type, settings, children){ | |
var component = this; | |
var componentScope = { | |
types: {}, | |
fastn: fastn, | |
component: component, | |
binding: fastn.binding('.'), | |
destroyed: false, | |
scope: new fastn.Model(false), | |
lastBound: null | |
}; | |
componentScope.emitAttach = emitAttach.bind(componentScope); | |
componentScope.emitDetach = emitDetach.bind(componentScope); | |
componentScope.binding._default_binding = true; | |
component._type = type; | |
component._properties = {}; | |
component._settings = settings || {}; | |
component._children = children ? flatten(children) : []; | |
component.attach = attachComponent.bind(componentScope); | |
component.detach = detachComponent.bind(componentScope); | |
component.scope = getScope.bind(componentScope); | |
component.destroy = destroy.bind(componentScope); | |
component.destroyed = isDestroyed.bind(componentScope); | |
component.binding = getSetBinding.bind(componentScope); | |
component.setProperty = setProperty.bind(componentScope); | |
component.clone = clone.bind(componentScope); | |
component.children = slice.bind(component._children); | |
component.extend = extendComponent.bind(componentScope); | |
component.is = isType.bind(componentScope); | |
component.binding(componentScope.binding); | |
component.on('attach', attachProperties.bind(this)); | |
component.on('render', onRender.bind(this)); | |
component.on('detach', detachProperties.bind(this)); | |
component.on('destroy', destroyProperties.bind(this)); | |
if(fastn.debug){ | |
component.on('render', function(){ | |
if(component.element && typeof component.element === 'object'){ | |
component.element._component = component; | |
} | |
}); | |
} | |
} | |
FastnComponent.prototype = Object.create(EventEmitter.prototype); | |
FastnComponent.prototype.constructor = FastnComponent; | |
FastnComponent.prototype._fastn_component = true; | |
module.exports = FastnComponent; | |
},{"./is":10,"events":5}],7:[function(require,module,exports){ | |
var is = require('./is'), | |
firmer = require('./firmer'), | |
functionEmitter = require('function-emitter'), | |
setPrototypeOf = require('setprototypeof'), | |
same = require('same-value'); | |
function fuseBinding(){ | |
var fastn = this, | |
args = Array.prototype.slice.call(arguments); | |
var bindings = args.slice(), | |
transform = bindings.pop(), | |
updateTransform, | |
resultBinding = createBinding.call(fastn, 'result'), | |
selfChanging; | |
resultBinding._arguments = args; | |
if(typeof bindings[bindings.length-1] === 'function' && !is.binding(bindings[bindings.length-1])){ | |
updateTransform = transform; | |
transform = bindings.pop(); | |
} | |
resultBinding._model.removeAllListeners(); | |
resultBinding._set = function(value){ | |
if(updateTransform){ | |
selfChanging = true; | |
var newValue = updateTransform(value); | |
if(!same(newValue, bindings[0]())){ | |
bindings[0](newValue); | |
resultBinding._change(newValue); | |
} | |
selfChanging = false; | |
}else{ | |
resultBinding._change(value); | |
} | |
}; | |
function change(){ | |
if(selfChanging){ | |
return; | |
} | |
resultBinding(transform.apply(null, bindings.map(function(binding){ | |
return binding(); | |
}))); | |
} | |
bindings.forEach(function(binding, index){ | |
if(!is.binding(binding)){ | |
binding = createBinding.call(fastn, binding); | |
bindings.splice(index,1,binding); | |
} | |
binding.on('change', change); | |
resultBinding.on('detach', binding.detach); | |
}); | |
var lastAttached; | |
resultBinding.on('attach', function(object){ | |
selfChanging = true; | |
bindings.forEach(function(binding){ | |
binding.attach(object, 1); | |
}); | |
selfChanging = false; | |
if(lastAttached !== object){ | |
change(); | |
} | |
lastAttached = object; | |
}); | |
return resultBinding; | |
} | |
function createValueBinding(fastn){ | |
var valueBinding = createBinding.call(fastn, 'value'); | |
valueBinding.attach = function(){return valueBinding;}; | |
valueBinding.detach = function(){return valueBinding;}; | |
return valueBinding; | |
} | |
function bindingTemplate(newValue){ | |
if(!arguments.length){ | |
return this.value; | |
} | |
if(this.binding._fastn_binding === '.'){ | |
return; | |
} | |
this.binding._set(newValue); | |
return this.binding; | |
} | |
function createBinding(path, more){ | |
var fastn = this; | |
if(more){ // used instead of arguments.length for performance | |
return fuseBinding.apply(fastn, arguments); | |
} | |
if(path == null){ | |
return createValueBinding(fastn); | |
} | |
var bindingScope = {}, | |
binding = bindingScope.binding = bindingTemplate.bind(bindingScope), | |
destroyed; | |
setPrototypeOf(binding, functionEmitter); | |
binding.setMaxListeners(10000); | |
binding._arguments = [path]; | |
binding._model = new fastn.Model(false); | |
binding._fastn_binding = path; | |
binding._firm = -Infinity; | |
function modelAttachHandler(data){ | |
binding._model.attach(data); | |
binding._change(binding._model.get(path)); | |
binding.emit('attach', data, 1); | |
} | |
function modelDetachHandler(){ | |
binding._model.detach(); | |
} | |
binding.attach = function(object, firm){ | |
// If the binding is being asked to attach loosly to an object, | |
// but it has already been defined as being firmly attached, do not attach. | |
if(firmer(binding, firm)){ | |
return binding; | |
} | |
binding._firm = firm; | |
var isModel = fastn.isModel(object); | |
if(isModel && bindingScope.attachedModel === object){ | |
return binding; | |
} | |
if(bindingScope.attachedModel){ | |
bindingScope.attachedModel.removeListener('attach', modelAttachHandler); | |
bindingScope.attachedModel.removeListener('detach', modelDetachHandler); | |
bindingScope.attachedModel = null; | |
} | |
if(isModel){ | |
bindingScope.attachedModel = object; | |
bindingScope.attachedModel.on('attach', modelAttachHandler); | |
bindingScope.attachedModel.on('detach', modelDetachHandler); | |
object = object._model; | |
} | |
if(!(object instanceof Object)){ | |
object = {}; | |
} | |
if(binding._model._model === object){ | |
return binding; | |
} | |
modelAttachHandler(object); | |
return binding; | |
}; | |
binding.detach = function(firm){ | |
if(firmer(binding, firm)){ | |
return binding; | |
} | |
bindingScope.value = undefined; | |
if(binding._model.isAttached()){ | |
binding._model.detach(); | |
} | |
binding.emit('detach', 1); | |
return binding; | |
}; | |
binding._set = function(newValue){ | |
if(same(binding._model.get(path), newValue)){ | |
return; | |
} | |
if(!binding._model.isAttached()){ | |
binding._model.attach(binding._model.get('.')); | |
} | |
binding._model.set(path, newValue); | |
}; | |
binding._change = function(newValue){ | |
bindingScope.value = newValue; | |
binding.emit('change', binding()); | |
}; | |
binding.clone = function(keepAttachment){ | |
var newBinding = createBinding.apply(fastn, binding._arguments); | |
if(keepAttachment){ | |
newBinding.attach(bindingScope.attachedModel || binding._model._model, binding._firm); | |
} | |
return newBinding; | |
}; | |
binding.destroy = function(soft){ | |
if(destroyed){ | |
return; | |
} | |
if(soft && binding.listeners('change').length){ | |
return; | |
} | |
destroyed = true; | |
binding.emit('destroy'); | |
binding.detach(); | |
binding._model.destroy(); | |
}; | |
binding.destroyed = function(){ | |
return destroyed; | |
}; | |
if(path !== '.'){ | |
binding._model.on(path, binding._change); | |
} | |
return binding; | |
} | |
function from(valueOrBinding){ | |
if(is.binding(valueOrBinding)){ | |
return valueOrBinding; | |
} | |
var result = this(); | |
result(valueOrBinding) | |
return result; | |
} | |
module.exports = function(fastn){ | |
var binding = createBinding.bind(fastn); | |
binding.from = from.bind(binding); | |
return binding; | |
}; | |
},{"./firmer":9,"./is":10,"function-emitter":14,"same-value":16,"setprototypeof":17}],8:[function(require,module,exports){ | |
function insertChild(fastn, container, child, index){ | |
if(child == null || child === false){ | |
return; | |
} | |
var currentIndex = container._children.indexOf(child), | |
newComponent = fastn.toComponent(child); | |
if(newComponent !== child && ~currentIndex){ | |
container._children.splice(currentIndex, 1, newComponent); | |
} | |
if(!~currentIndex || newComponent !== child){ | |
newComponent.attach(container.scope(), 1); | |
} | |
if(currentIndex !== index){ | |
if(~currentIndex){ | |
container._children.splice(currentIndex, 1); | |
} | |
container._children.splice(index, 0, newComponent); | |
} | |
if(container.element){ | |
if(!newComponent.element){ | |
newComponent.render(); | |
} | |
container._insert(newComponent.element, index); | |
newComponent.emit('insert', container); | |
container.emit('childInsert', newComponent); | |
} | |
} | |
function getContainerElement(){ | |
return this.containerElement || this.element; | |
} | |
function insert(child, index){ | |
var childComponent = child, | |
container = this.container, | |
fastn = this.fastn; | |
if(index && typeof index === 'object'){ | |
childComponent = Array.prototype.slice.call(arguments); | |
} | |
if(isNaN(index)){ | |
index = container._children.length; | |
} | |
if(Array.isArray(childComponent)){ | |
for (var i = 0; i < childComponent.length; i++) { | |
container.insert(childComponent[i], i + index); | |
} | |
}else{ | |
insertChild(fastn, container, childComponent, index); | |
} | |
return container; | |
} | |
module.exports = function(fastn, component, type, settings, children){ | |
component.insert = insert.bind({ | |
container: component, | |
fastn: fastn | |
}); | |
component._insert = function(element, index){ | |
var containerElement = component.getContainerElement(); | |
if(!containerElement){ | |
return; | |
} | |
if(containerElement.childNodes[index] === element){ | |
return; | |
} | |
containerElement.insertBefore(element, containerElement.childNodes[index]); | |
}; | |
component.remove = function(childComponent){ | |
var index = component._children.indexOf(childComponent); | |
if(~index){ | |
component._children.splice(index,1); | |
} | |
childComponent.detach(1); | |
if(childComponent.element){ | |
component._remove(childComponent.element); | |
childComponent.emit('remove', component); | |
} | |
component.emit('childRemove', childComponent); | |
}; | |
component._remove = function(element){ | |
var containerElement = component.getContainerElement(); | |
if(!element || !containerElement || element.parentNode !== containerElement){ | |
return; | |
} | |
containerElement.removeChild(element); | |
}; | |
component.empty = function(){ | |
while(component._children.length){ | |
component.remove(component._children.pop()); | |
} | |
}; | |
component.replaceChild = function(oldChild, newChild){ | |
var index = component._children.indexOf(oldChild); | |
if(!~index){ | |
return; | |
} | |
component.remove(oldChild); | |
component.insert(newChild, index); | |
}; | |
component.getContainerElement = getContainerElement.bind(component); | |
component.on('render', component.insert.bind(null, component._children, 0)); | |
component.on('attach', function(model, firm){ | |
for(var i = 0; i < component._children.length; i++){ | |
if(fastn.isComponent(component._children[i])){ | |
component._children[i].attach(model, firm); | |
} | |
} | |
}); | |
component.on('destroy', function(data, firm){ | |
for(var i = 0; i < component._children.length; i++){ | |
if(fastn.isComponent(component._children[i])){ | |
component._children[i].destroy(firm); | |
} | |
} | |
}); | |
return component; | |
}; | |
},{}],9:[function(require,module,exports){ | |
// Is the entity firmer than the new firmness | |
module.exports = function(entity, firm){ | |
if(firm != null && (entity._firm === undefined || firm < entity._firm)){ | |
return true; | |
} | |
}; | |
},{}],10:[function(require,module,exports){ | |
var FUNCTION = 'function', | |
OBJECT = 'object', | |
FASTNBINDING = '_fastn_binding', | |
FASTNPROPERTY = '_fastn_property', | |
FASTNCOMPONENT = '_fastn_component', | |
DEFAULTBINDING = '_default_binding'; | |
function isComponent(thing){ | |
return thing && typeof thing === OBJECT && FASTNCOMPONENT in thing; | |
} | |
function isBindingObject(thing){ | |
return thing && typeof thing === OBJECT && FASTNBINDING in thing; | |
} | |
function isBinding(thing){ | |
return typeof thing === FUNCTION && FASTNBINDING in thing; | |
} | |
function isProperty(thing){ | |
return typeof thing === FUNCTION && FASTNPROPERTY in thing; | |
} | |
function isDefaultBinding(thing){ | |
return typeof thing === FUNCTION && FASTNBINDING in thing && DEFAULTBINDING in thing; | |
} | |
module.exports = { | |
component: isComponent, | |
bindingObject: isBindingObject, | |
binding: isBinding, | |
defaultBinding: isDefaultBinding, | |
property: isProperty | |
}; | |
},{}],11:[function(require,module,exports){ | |
//Copyright (C) 2012 Kory Nunn | |
//Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | |
//The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | |
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
/* | |
This code is not formatted for readability, but rather run-speed and to assist compilers. | |
However, the code's intention should be transparent. | |
*** IE SUPPORT *** | |
If you require this library to work in IE7, add the following after declaring crel. | |
var testDiv = document.createElement('div'), | |
testLabel = document.createElement('label'); | |
testDiv.setAttribute('class', 'a'); | |
testDiv['className'] !== 'a' ? crel.attrMap['class'] = 'className':undefined; | |
testDiv.setAttribute('name','a'); | |
testDiv['name'] !== 'a' ? crel.attrMap['name'] = function(element, value){ | |
element.id = value; | |
}:undefined; | |
testLabel.setAttribute('for', 'a'); | |
testLabel['htmlFor'] !== 'a' ? crel.attrMap['for'] = 'htmlFor':undefined; | |
*/ | |
(function (root, factory) { | |
if (typeof exports === 'object') { | |
module.exports = factory(); | |
} else if (typeof define === 'function' && define.amd) { | |
define(factory); | |
} else { | |
root.crel = factory(); | |
} | |
}(this, function () { | |
var fn = 'function', | |
obj = 'object', | |
nodeType = 'nodeType', | |
textContent = 'textContent', | |
setAttribute = 'setAttribute', | |
attrMapString = 'attrMap', | |
isNodeString = 'isNode', | |
isElementString = 'isElement', | |
d = typeof document === obj ? document : {}, | |
isType = function(a, type){ | |
return typeof a === type; | |
}, | |
isNode = typeof Node === fn ? function (object) { | |
return object instanceof Node; | |
} : | |
// in IE <= 8 Node is an object, obviously.. | |
function(object){ | |
return object && | |
isType(object, obj) && | |
(nodeType in object) && | |
isType(object.ownerDocument,obj); | |
}, | |
isElement = function (object) { | |
return crel[isNodeString](object) && object[nodeType] === 1; | |
}, | |
isArray = function(a){ | |
return a instanceof Array; | |
}, | |
appendChild = function(element, child) { | |
if(!crel[isNodeString](child)){ | |
child = d.createTextNode(child); | |
} | |
element.appendChild(child); | |
}; | |
function crel(){ | |
var args = arguments, //Note: assigned to a variable to assist compilers. Saves about 40 bytes in closure compiler. Has negligable effect on performance. | |
element = args[0], | |
child, | |
settings = args[1], | |
childIndex = 2, | |
argumentsLength = args.length, | |
attributeMap = crel[attrMapString]; | |
element = crel[isElementString](element) ? element : d.createElement(element); | |
// shortcut | |
if(argumentsLength === 1){ | |
return element; | |
} | |
if(!isType(settings,obj) || crel[isNodeString](settings) || isArray(settings)) { | |
--childIndex; | |
settings = null; | |
} | |
// shortcut if there is only one child that is a string | |
if((argumentsLength - childIndex) === 1 && isType(args[childIndex], 'string') && element[textContent] !== undefined){ | |
element[textContent] = args[childIndex]; | |
}else{ | |
for(; childIndex < argumentsLength; ++childIndex){ | |
child = args[childIndex]; | |
if(child == null){ | |
continue; | |
} | |
if (isArray(child)) { | |
for (var i=0; i < child.length; ++i) { | |
appendChild(element, child[i]); | |
} | |
} else { | |
appendChild(element, child); | |
} | |
} | |
} | |
for(var key in settings){ | |
if(!attributeMap[key]){ | |
element[setAttribute](key, settings[key]); | |
}else{ | |
var attr = attributeMap[key]; | |
if(typeof attr === fn){ | |
attr(element, settings[key]); | |
}else{ | |
element[setAttribute](attr, settings[key]); | |
} | |
} | |
} | |
return element; | |
} | |
// Used for mapping one kind of attribute to the supported version of that in bad browsers. | |
crel[attrMapString] = {}; | |
crel[isElementString] = isElement; | |
crel[isNodeString] = isNode; | |
if(typeof Proxy !== 'undefined'){ | |
return new Proxy(crel, { | |
get: function(target, key){ | |
!(key in crel) && (crel[key] = crel.bind(null, key)); | |
return crel[key]; | |
} | |
}); | |
} | |
return crel; | |
})); | |
},{}],12:[function(require,module,exports){ | |
(function (global){ | |
var EventEmitter = require('events').EventEmitter, | |
isInstance = require('is-instance'); | |
function toArray(items){ | |
return Array.prototype.slice.call(items); | |
} | |
var deepRegex = /[|.]/i; | |
function matchDeep(path){ | |
return (path + '').match(deepRegex); | |
} | |
function isWildcardPath(path){ | |
var stringPath = (path + ''); | |
return ~stringPath.indexOf('*'); | |
} | |
function getTargetKey(path){ | |
var stringPath = (path + ''); | |
return stringPath.split('|').shift(); | |
} | |
var eventSystemVersion = 1, | |
globalKey = '_entiEventState' + eventSystemVersion | |
globalState = global[globalKey] = global[globalKey] || { | |
instances: [] | |
}; | |
var modifiedEnties = globalState.modifiedEnties = globalState.modifiedEnties || new Set(), | |
trackedObjects = globalState.trackedObjects = globalState.trackedObjects || new WeakMap(); | |
function leftAndRest(path){ | |
var stringPath = (path + ''); | |
// Special case when you want to filter on self (.) | |
if(stringPath.slice(0,2) === '.|'){ | |
return ['.', stringPath.slice(2)]; | |
} | |
var match = matchDeep(stringPath); | |
if(match){ | |
return [stringPath.slice(0, match.index), stringPath.slice(match.index+1)]; | |
} | |
return stringPath; | |
} | |
function isWildcardKey(key){ | |
return key.charAt(0) === '*'; | |
} | |
function isFeralcardKey(key){ | |
return key === '**'; | |
} | |
function addHandler(object, key, handler){ | |
var trackedKeys = trackedObjects.get(object); | |
if(trackedKeys == null){ | |
trackedKeys = {}; | |
trackedObjects.set(object, trackedKeys); | |
} | |
var handlers = trackedKeys[key]; | |
if(!handlers){ | |
handlers = new Set(); | |
trackedKeys[key] = handlers; | |
} | |
handlers.add(handler); | |
} | |
function removeHandler(object, key, handler){ | |
var trackedKeys = trackedObjects.get(object); | |
if(trackedKeys == null){ | |
return; | |
} | |
var handlers = trackedKeys[key]; | |
if(!handlers){ | |
return; | |
} | |
handlers.delete(handler); | |
} | |
function trackObjects(eventName, tracked, handler, object, key, path){ | |
if(!object || typeof object !== 'object'){ | |
return; | |
} | |
var target = object[key]; | |
if(target && typeof target === 'object' && tracked.has(target)){ | |
return; | |
} | |
trackObject(eventName, tracked, handler, object, key, path); | |
} | |
function trackKeys(eventName, tracked, handler, target, root, rest){ | |
var keys = Object.keys(target); | |
for(var i = 0; i < keys.length; i++){ | |
if(isFeralcardKey(root)){ | |
trackObjects(eventName, tracked, handler, target, keys[i], '**' + (rest ? '.' : '') + (rest || '')); | |
}else{ | |
trackObjects(eventName, tracked, handler, target, keys[i], rest); | |
} | |
} | |
} | |
function trackObject(eventName, tracked, handler, object, key, path){ | |
var eventKey = key === '**' ? '*' : key, | |
target = object[key], | |
targetIsObject = target && typeof target === 'object'; | |
var handle = function(value, event, emitKey){ | |
if(eventKey !== '*' && typeof object[eventKey] === 'object' && object[eventKey] !== target){ | |
if(targetIsObject){ | |
tracked.delete(target); | |
} | |
removeHandler(object, eventKey, handle); | |
trackObjects(eventName, tracked, handler, object, key, path); | |
return; | |
} | |
if(eventKey === '*'){ | |
trackKeys(eventName, tracked, handler, object, key, path); | |
} | |
if(!tracked.has(object)){ | |
return; | |
} | |
if(key !== '**' || !path){ | |
handler(value, event, emitKey); | |
} | |
}; | |
addHandler(object, eventKey, handle); | |
if(!targetIsObject){ | |
return; | |
} | |
tracked.add(target); | |
if(!path){ | |
return; | |
} | |
var rootAndRest = leftAndRest(path), | |
root, | |
rest; | |
if(!Array.isArray(rootAndRest)){ | |
root = rootAndRest; | |
}else{ | |
root = rootAndRest[0]; | |
rest = rootAndRest[1]; | |
// If the root is '.', watch for events on * | |
if(root === '.'){ | |
root = '*'; | |
} | |
} | |
if(targetIsObject && isWildcardKey(root)){ | |
trackKeys(eventName, tracked, handler, target, root, rest); | |
} | |
trackObjects(eventName, tracked, handler, target, root, rest); | |
} | |
var trackedEvents = new WeakMap(); | |
function createHandler(enti, trackedObjectPaths, trackedPaths, eventName){ | |
var oldModel = enti._model; | |
return function(event, emitKey){ | |
trackedPaths.entis.forEach(function(enti){ | |
if(enti._emittedEvents[eventName] === emitKey){ | |
return; | |
} | |
if(enti._model !== oldModel){ | |
trackedPaths.entis.delete(enti); | |
if(trackedPaths.entis.size === 0){ | |
delete trackedObjectPaths[eventName]; | |
if(!Object.keys(trackedObjectPaths).length){ | |
trackedEvents.delete(oldModel); | |
} | |
} | |
return; | |
} | |
enti._emittedEvents[eventName] = emitKey; | |
var targetKey = getTargetKey(eventName), | |
value = isWildcardPath(targetKey) ? undefined : enti.get(targetKey); | |
enti.emit(eventName, value, event); | |
}); | |
}; | |
} | |
function trackPath(enti, eventName){ | |
var object = enti._model, | |
trackedObjectPaths = trackedEvents.get(object); | |
if(!trackedObjectPaths){ | |
trackedObjectPaths = {}; | |
trackedEvents.set(object, trackedObjectPaths); | |
} | |
var trackedPaths = trackedObjectPaths[eventName]; | |
if(!trackedPaths){ | |
trackedPaths = { | |
entis: new Set(), | |
trackedObjects: new WeakSet() | |
}; | |
trackedObjectPaths[eventName] = trackedPaths; | |
}else if(trackedPaths.entis.has(enti)){ | |
return; | |
} | |
trackedPaths.entis.add(enti); | |
var handler = createHandler(enti, trackedObjectPaths, trackedPaths, eventName); | |
trackObjects(eventName, trackedPaths.trackedObjects, handler, {model:object}, 'model', eventName); | |
} | |
function trackPaths(enti){ | |
if(!enti._events || !enti._model){ | |
return; | |
} | |
for(var key in enti._events){ | |
trackPath(enti, key); | |
} | |
modifiedEnties.delete(enti); | |
} | |
function emitEvent(object, key, value, emitKey){ | |
modifiedEnties.forEach(trackPaths); | |
var trackedKeys = trackedObjects.get(object); | |
if(!trackedKeys){ | |
return; | |
} | |
var event = { | |
value: value, | |
key: key, | |
object: object | |
}; | |
function emitForKey(handler){ | |
handler(event, emitKey); | |
} | |
if(trackedKeys[key]){ | |
trackedKeys[key].forEach(emitForKey); | |
} | |
if(trackedKeys['*']){ | |
trackedKeys['*'].forEach(emitForKey); | |
} | |
} | |
function emit(events){ | |
var emitKey = {}; | |
events.forEach(function(event){ | |
emitEvent(event[0], event[1], event[2], emitKey); | |
}); | |
} | |
function Enti(model){ | |
var detached = model === false; | |
if(!model || (typeof model !== 'object' && typeof model !== 'function')){ | |
model = {}; | |
} | |
this._emittedEvents = {}; | |
if(detached){ | |
this._model = {}; | |
}else{ | |
this.attach(model); | |
} | |
this.on('newListener', function(){ | |
modifiedEnties.add(this); | |
}); | |
} | |
Enti.emit = function(model, key, value){ | |
if(!(typeof model === 'object' || typeof model === 'function')){ | |
return; | |
} | |
emit([[model, key, value]]); | |
}; | |
Enti.get = function(model, key){ | |
if(!model || typeof model !== 'object'){ | |
return; | |
} | |
key = getTargetKey(key); | |
if(key === '.'){ | |
return model; | |
} | |
var path = leftAndRest(key); | |
if(Array.isArray(path)){ | |
return Enti.get(model[path[0]], path[1]); | |
} | |
return model[key]; | |
}; | |
Enti.set = function(model, key, value){ | |
if(!model || typeof model !== 'object'){ | |
return; | |
} | |
key = getTargetKey(key); | |
var path = leftAndRest(key); | |
if(Array.isArray(path)){ | |
return Enti.set(model[path[0]], path[1], value); | |
} | |
var original = model[key]; | |
if(typeof value !== 'object' && value === original){ | |
return; | |
} | |
var keysChanged = !(key in model); | |
model[key] = value; | |
var events = [[model, key, value]]; | |
if(keysChanged){ | |
if(Array.isArray(model)){ | |
events.push([model, 'length', model.length]); | |
} | |
} | |
emit(events); | |
}; | |
Enti.push = function(model, key, value){ | |
if(!model || typeof model !== 'object'){ | |
return; | |
} | |
var target; | |
if(arguments.length < 3){ | |
value = key; | |
key = '.'; | |
target = model; | |
}else{ | |
var path = leftAndRest(key); | |
if(Array.isArray(path)){ | |
return Enti.push(model[path[0]], path[1], value); | |
} | |
target = model[key]; | |
} | |
if(!Array.isArray(target)){ | |
throw 'The target is not an array.'; | |
} | |
target.push(value); | |
var events = [ | |
[target, target.length-1, value], | |
[target, 'length', target.length] | |
]; | |
emit(events); | |
}; | |
Enti.insert = function(model, key, value, index){ | |
if(!model || typeof model !== 'object'){ | |
return; | |
} | |
var target; | |
if(arguments.length < 4){ | |
index = value; | |
value = key; | |
key = '.'; | |
target = model; | |
}else{ | |
var path = leftAndRest(key); | |
if(Array.isArray(path)){ | |
return Enti.insert(model[path[0]], path[1], value, index); | |
} | |
target = model[key]; | |
} | |
if(!Array.isArray(target)){ | |
throw 'The target is not an array.'; | |
} | |
target.splice(index, 0, value); | |
var events = [ | |
[target, index, value], | |
[target, 'length', target.length] | |
]; | |
emit(events); | |
}; | |
Enti.remove = function(model, key, subKey){ | |
if(!model || typeof model !== 'object'){ | |
return; | |
} | |
var path = leftAndRest(key); | |
if(Array.isArray(path)){ | |
return Enti.remove(model[path[0]], path[1], subKey); | |
} | |
// Remove a key off of an object at 'key' | |
if(subKey != null){ | |
Enti.remove(model[key], subKey); | |
return; | |
} | |
if(key === '.'){ | |
throw '. (self) is not a valid key to remove'; | |
} | |
var events = []; | |
if(Array.isArray(model)){ | |
model.splice(key, 1); | |
events.push([model, 'length', model.length]); | |
}else{ | |
delete model[key]; | |
events.push([model, key]); | |
} | |
emit(events); | |
}; | |
Enti.move = function(model, key, index){ | |
if(!model || typeof model !== 'object'){ | |
return; | |
} | |
var path = leftAndRest(key); | |
if(Array.isArray(path)){ | |
return Enti.move(model[path[0]], path[1], index); | |
} | |
if(key === index){ | |
return; | |
} | |
if(!Array.isArray(model)){ | |
throw 'The model is not an array.'; | |
} | |
var item = model[key]; | |
model.splice(key, 1); | |
model.splice(index - (index > key ? 0 : 1), 0, item); | |
emit([[model, index, item]]); | |
}; | |
Enti.update = function(model, key, value){ | |
if(!model || typeof model !== 'object'){ | |
return; | |
} | |
var target, | |
isArray = Array.isArray(value); | |
if(arguments.length < 3){ | |
value = key; | |
key = '.'; | |
target = model; | |
}else{ | |
var path = leftAndRest(key); | |
if(Array.isArray(path)){ | |
return Enti.update(model[path[0]], path[1], value); | |
} | |
target = model[key]; | |
if(target == null){ | |
model[key] = isArray ? [] : {}; | |
} | |
} | |
if(typeof value !== 'object'){ | |
throw 'The value is not an object.'; | |
} | |
if(typeof target !== 'object'){ | |
throw 'The target is not an object.'; | |
} | |
var events = [], | |
updatedObjects = new WeakSet(); | |
function updateTarget(target, value){ | |
for(var key in value){ | |
var currentValue = target[key]; | |
if(currentValue instanceof Object && !updatedObjects.has(currentValue) && !(currentValue instanceof Date)){ | |
updatedObjects.add(currentValue); | |
updateTarget(currentValue, value[key]); | |
continue; | |
} | |
target[key] = value[key]; | |
events.push([target, key, value[key]]); | |
} | |
if(Array.isArray(target)){ | |
events.push([target, 'length', target.length]); | |
} | |
} | |
updateTarget(target, value); | |
emit(events); | |
}; | |
Enti.prototype = Object.create(EventEmitter.prototype); | |
Enti.prototype._maxListeners = 100; | |
Enti.prototype.constructor = Enti; | |
Enti.prototype.attach = function(model){ | |
if(this._model !== model){ | |
this.detach(); | |
} | |
if(model && !isInstance(model)){ | |
throw 'Entis may only be attached to an object, or null/undefined'; | |
} | |
modifiedEnties.add(this); | |
this._attached = true; | |
this._model = model; | |
this.emit('attach', model); | |
}; | |
Enti.prototype.detach = function(){ | |
modifiedEnties.delete(this); | |
this._emittedEvents = {}; | |
this._model = {}; | |
this._attached = false; | |
this.emit('detach'); | |
}; | |
Enti.prototype.destroy = function(){ | |
this.detach(); | |
this._events = null; | |
this.emit('destroy'); | |
}; | |
Enti.prototype.get = function(key){ | |
return Enti.get(this._model, key); | |
}; | |
Enti.prototype.set = function(key, value){ | |
return Enti.set(this._model, key, value); | |
}; | |
Enti.prototype.push = function(key, value){ | |
return Enti.push.apply(null, [this._model].concat(toArray(arguments))); | |
}; | |
Enti.prototype.insert = function(key, value, index){ | |
return Enti.insert.apply(null, [this._model].concat(toArray(arguments))); | |
}; | |
Enti.prototype.remove = function(key, subKey){ | |
return Enti.remove.apply(null, [this._model].concat(toArray(arguments))); | |
}; | |
Enti.prototype.move = function(key, index){ | |
return Enti.move.apply(null, [this._model].concat(toArray(arguments))); | |
}; | |
Enti.prototype.update = function(key, index){ | |
return Enti.update.apply(null, [this._model].concat(toArray(arguments))); | |
}; | |
Enti.prototype.isAttached = function(){ | |
return this._attached; | |
}; | |
Enti.prototype.attachedCount = function(){ | |
return modifiedEnties.size; | |
}; | |
Enti.isEnti = function(target){ | |
return target && !!~globalState.instances.indexOf(target.constructor); | |
}; | |
Enti.store = function(target, key, value){ | |
if(arguments.length < 2){ | |
return Enti.get(target, key); | |
} | |
Enti.set(target, key, value); | |
}; | |
globalState.instances.push(Enti); | |
module.exports = Enti; | |
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9lbnRpL2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsidmFyIEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ2V2ZW50cycpLkV2ZW50RW1pdHRlcixcbiAgICBpc0luc3RhbmNlID0gcmVxdWlyZSgnaXMtaW5zdGFuY2UnKTtcblxuZnVuY3Rpb24gdG9BcnJheShpdGVtcyl7XG4gICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGl0ZW1zKTtcbn1cblxudmFyIGRlZXBSZWdleCA9IC9bfC5dL2k7XG5cbmZ1bmN0aW9uIG1hdGNoRGVlcChwYXRoKXtcbiAgICByZXR1cm4gKHBhdGggKyAnJykubWF0Y2goZGVlcFJlZ2V4KTtcbn1cblxuZnVuY3Rpb24gaXNXaWxkY2FyZFBhdGgocGF0aCl7XG4gICAgdmFyIHN0cmluZ1BhdGggPSAocGF0aCArICcnKTtcbiAgICByZXR1cm4gfnN0cmluZ1BhdGguaW5kZXhPZignKicpO1xufVxuXG5mdW5jdGlvbiBnZXRUYXJnZXRLZXkocGF0aCl7XG4gICAgdmFyIHN0cmluZ1BhdGggPSAocGF0aCArICcnKTtcbiAgICByZXR1cm4gc3RyaW5nUGF0aC5zcGxpdCgnfCcpLnNoaWZ0KCk7XG59XG5cbnZhciBldmVudFN5c3RlbVZlcnNpb24gPSAxLFxuICAgIGdsb2JhbEtleSA9ICdfZW50aUV2ZW50U3RhdGUnICsgZXZlbnRTeXN0ZW1WZXJzaW9uXG4gICAgZ2xvYmFsU3RhdGUgPSBnbG9iYWxbZ2xvYmFsS2V5XSA9IGdsb2JhbFtnbG9iYWxLZXldIHx8IHtcbiAgICAgICAgaW5zdGFuY2VzOiBbXVxuICAgIH07XG5cbnZhciBtb2RpZmllZEVudGllcyA9IGdsb2JhbFN0YXRlLm1vZGlmaWVkRW50aWVzID0gZ2xvYmFsU3RhdGUubW9kaWZpZWRFbnRpZXMgfHwgbmV3IFNldCgpLFxuICAgIHRyYWNrZWRPYmplY3RzID0gZ2xvYmFsU3RhdGUudHJhY2tlZE9iamVjdHMgPSBnbG9iYWxTdGF0ZS50cmFja2VkT2JqZWN0cyB8fCBuZXcgV2Vha01hcCgpO1xuXG5mdW5jdGlvbiBsZWZ0QW5kUmVzdChwYXRoKXtcbiAgICB2YXIgc3RyaW5nUGF0aCA9IChwYXRoICsgJycpO1xuXG4gICAgLy8gU3BlY2lhbCBjYXNlIHdoZW4geW91IHdhbnQgdG8gZmlsdGVyIG9uIHNlbGYgKC4pXG4gICAgaWYoc3RyaW5nUGF0aC5zbGljZSgwLDIpID09PSAnLnwnKXtcbiAgICAgICAgcmV0dXJuIFsnLicsIHN0cmluZ1BhdGguc2xpY2UoMildO1xuICAgIH1cblxuICAgIHZhciBtYXRjaCA9IG1hdGNoRGVlcChzdHJpbmdQYXRoKTtcbiAgICBpZihtYXRjaCl7XG4gICAgICAgIHJldHVybiBbc3RyaW5nUGF0aC5zbGljZSgwLCBtYXRjaC5pbmRleCksIHN0cmluZ1BhdGguc2xpY2UobWF0Y2guaW5kZXgrMSldO1xuICAgIH1cbiAgICByZXR1cm4gc3RyaW5nUGF0aDtcbn1cblxuZnVuY3Rpb24gaXNXaWxkY2FyZEtleShrZXkpe1xuICAgIHJldHVybiBrZXkuY2hhckF0KDApID09PSAnKic7XG59XG5cbmZ1bmN0aW9uIGlzRmVyYWxjYXJkS2V5KGtleSl7XG4gICAgcmV0dXJuIGtleSA9PT0gJyoqJztcbn1cblxuZnVuY3Rpb24gYWRkSGFuZGxlcihvYmplY3QsIGtleSwgaGFuZGxlcil7XG4gICAgdmFyIHRyYWNrZWRLZXlzID0gdHJhY2tlZE9iamVjdHMuZ2V0KG9iamVjdCk7XG5cbiAgICBpZih0cmFja2VkS2V5cyA9PSBudWxsKXtcbiAgICAgICAgdHJhY2tlZEtleXMgPSB7fTtcbiAgICAgICAgdHJhY2tlZE9iamVjdHMuc2V0KG9iamVjdCwgdHJhY2tlZEtleXMpO1xuICAgIH1cblxuICAgIHZhciBoYW5kbGVycyA9IHRyYWNrZWRLZXlzW2tleV07XG5cbiAgICBpZighaGFuZGxlcnMpe1xuICAgICAgICBoYW5kbGVycyA9IG5ldyBTZXQoKTtcbiAgICAgICAgdHJhY2tlZEtleXNba2V5XSA9IGhhbmRsZXJzO1xuICAgIH1cblxuICAgIGhhbmRsZXJzLmFkZChoYW5kbGVyKTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlSGFuZGxlcihvYmplY3QsIGtleSwgaGFuZGxlcil7XG4gICAgdmFyIHRyYWNrZWRLZXlzID0gdHJhY2tlZE9iamVjdHMuZ2V0KG9iamVjdCk7XG5cbiAgICBpZih0cmFja2VkS2V5cyA9PSBudWxsKXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBoYW5kbGVycyA9IHRyYWNrZWRLZXlzW2tleV07XG5cbiAgICBpZighaGFuZGxlcnMpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaGFuZGxlcnMuZGVsZXRlKGhhbmRsZXIpO1xufVxuXG5mdW5jdGlvbiB0cmFja09iamVjdHMoZXZlbnROYW1lLCB0cmFja2VkLCBoYW5kbGVyLCBvYmplY3QsIGtleSwgcGF0aCl7XG4gICAgaWYoIW9iamVjdCB8fCB0eXBlb2Ygb2JqZWN0ICE9PSAnb2JqZWN0Jyl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgdGFyZ2V0ID0gb2JqZWN0W2tleV07XG5cbiAgICBpZih0YXJnZXQgJiYgdHlwZW9mIHRhcmdldCA9PT0gJ29iamVjdCcgJiYgdHJhY2tlZC5oYXModGFyZ2V0KSl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cmFja09iamVjdChldmVudE5hbWUsIHRyYWNrZWQsIGhhbmRsZXIsIG9iamVjdCwga2V5LCBwYXRoKTtcbn1cblxuZnVuY3Rpb24gdHJhY2tLZXlzKGV2ZW50TmFtZSwgdHJhY2tlZCwgaGFuZGxlciwgdGFyZ2V0LCByb290LCByZXN0KXtcbiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKHRhcmdldCk7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspe1xuICAgICAgICBpZihpc0ZlcmFsY2FyZEtleShyb290KSl7XG4gICAgICAgICAgICB0cmFja09iamVjdHMoZXZlbnROYW1lLCB0cmFja2VkLCBoYW5kbGVyLCB0YXJnZXQsIGtleXNbaV0sICcqKicgKyAocmVzdCA/ICcuJyA6ICcnKSArIChyZXN0IHx8ICcnKSk7XG4gICAgICAgIH1lbHNle1xuICAgICAgICAgICAgdHJhY2tPYmplY3RzKGV2ZW50TmFtZSwgdHJhY2tlZCwgaGFuZGxlciwgdGFyZ2V0LCBrZXlzW2ldLCByZXN0KTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gdHJhY2tPYmplY3QoZXZlbnROYW1lLCB0cmFja2VkLCBoYW5kbGVyLCBvYmplY3QsIGtleSwgcGF0aCl7XG4gICAgdmFyIGV2ZW50S2V5ID0ga2V5ID09PSAnKionID8gJyonIDoga2V5LFxuICAgICAgICB0YXJnZXQgPSBvYmplY3Rba2V5XSxcbiAgICAgICAgdGFyZ2V0SXNPYmplY3QgPSB0YXJnZXQgJiYgdHlwZW9mIHRhcmdldCA9PT0gJ29iamVjdCc7XG5cbiAgICB2YXIgaGFuZGxlID0gZnVuY3Rpb24odmFsdWUsIGV2ZW50LCBlbWl0S2V5KXtcbiAgICAgICAgaWYoZXZlbnRLZXkgIT09ICcqJyAmJiB0eXBlb2Ygb2JqZWN0W2V2ZW50S2V5XSA9PT0gJ29iamVjdCcgJiYgb2JqZWN0W2V2ZW50S2V5XSAhPT0gdGFyZ2V0KXtcbiAgICAgICAgICAgIGlmKHRhcmdldElzT2JqZWN0KXtcbiAgICAgICAgICAgICAgICB0cmFja2VkLmRlbGV0ZSh0YXJnZXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVtb3ZlSGFuZGxlcihvYmplY3QsIGV2ZW50S2V5LCBoYW5kbGUpO1xuICAgICAgICAgICAgdHJhY2tPYmplY3RzKGV2ZW50TmFtZSwgdHJhY2tlZCwgaGFuZGxlciwgb2JqZWN0LCBrZXksIHBhdGgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoZXZlbnRLZXkgPT09ICcqJyl7XG4gICAgICAgICAgICB0cmFja0tleXMoZXZlbnROYW1lLCB0cmFja2VkLCBoYW5kbGVyLCBvYmplY3QsIGtleSwgcGF0aCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZighdHJhY2tlZC5oYXMob2JqZWN0KSl7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZihrZXkgIT09ICcqKicgfHwgIXBhdGgpe1xuICAgICAgICAgICAgaGFuZGxlcih2YWx1ZSwgZXZlbnQsIGVtaXRLZXkpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGFkZEhhbmRsZXIob2JqZWN0LCBldmVudEtleSwgaGFuZGxlKTtcblxuICAgIGlmKCF0YXJnZXRJc09iamVjdCl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cmFja2VkLmFkZCh0YXJnZXQpO1xuXG4gICAgaWYoIXBhdGgpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHJvb3RBbmRSZXN0ID0gbGVmdEFuZFJlc3QocGF0aCksXG4gICAgICAgIHJvb3QsXG4gICAgICAgIHJlc3Q7XG5cbiAgICBpZighQXJyYXkuaXNBcnJheShyb290QW5kUmVzdCkpe1xuICAgICAgICByb290ID0gcm9vdEFuZFJlc3Q7XG4gICAgfWVsc2V7XG4gICAgICAgIHJvb3QgPSByb290QW5kUmVzdFswXTtcbiAgICAgICAgcmVzdCA9IHJvb3RBbmRSZXN0WzFdO1xuXG4gICAgICAgIC8vIElmIHRoZSByb290IGlzICcuJywgd2F0Y2ggZm9yIGV2ZW50cyBvbiAqXG4gICAgICAgIGlmKHJvb3QgPT09ICcuJyl7XG4gICAgICAgICAgICByb290ID0gJyonO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYodGFyZ2V0SXNPYmplY3QgJiYgaXNXaWxkY2FyZEtleShyb290KSl7XG4gICAgICAgIHRyYWNrS2V5cyhldmVudE5hbWUsIHRyYWNrZWQsIGhhbmRsZXIsIHRhcmdldCwgcm9vdCwgcmVzdCk7XG4gICAgfVxuXG4gICAgdHJhY2tPYmplY3RzKGV2ZW50TmFtZSwgdHJhY2tlZCwgaGFuZGxlciwgdGFyZ2V0LCByb290LCByZXN0KTtcbn1cblxudmFyIHRyYWNrZWRFdmVudHMgPSBuZXcgV2Vha01hcCgpO1xuZnVuY3Rpb24gY3JlYXRlSGFuZGxlcihlbnRpLCB0cmFja2VkT2JqZWN0UGF0aHMsIHRyYWNrZWRQYXRocywgZXZlbnROYW1lKXtcbiAgICB2YXIgb2xkTW9kZWwgPSBlbnRpLl9tb2RlbDtcbiAgICByZXR1cm4gZnVuY3Rpb24oZXZlbnQsIGVtaXRLZXkpe1xuICAgICAgICB0cmFja2VkUGF0aHMuZW50aXMuZm9yRWFjaChmdW5jdGlvbihlbnRpKXtcbiAgICAgICAgICAgIGlmKGVudGkuX2VtaXR0ZWRFdmVudHNbZXZlbnROYW1lXSA9PT0gZW1pdEtleSl7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihlbnRpLl9tb2RlbCAhPT0gb2xkTW9kZWwpe1xuICAgICAgICAgICAgICAgIHRyYWNrZWRQYXRocy5lbnRpcy5kZWxldGUoZW50aSk7XG4gICAgICAgICAgICAgICAgaWYodHJhY2tlZFBhdGhzLmVudGlzLnNpemUgPT09IDApe1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdHJhY2tlZE9iamVjdFBhdGhzW2V2ZW50TmFtZV07XG4gICAgICAgICAgICAgICAgICAgIGlmKCFPYmplY3Qua2V5cyh0cmFja2VkT2JqZWN0UGF0aHMpLmxlbmd0aCl7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFja2VkRXZlbnRzLmRlbGV0ZShvbGRNb2RlbCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBlbnRpLl9lbWl0dGVkRXZlbnRzW2V2ZW50TmFtZV0gPSBlbWl0S2V5O1xuXG4gICAgICAgICAgICB2YXIgdGFyZ2V0S2V5ID0gZ2V0VGFyZ2V0S2V5KGV2ZW50TmFtZSksXG4gICAgICAgICAgICAgICAgdmFsdWUgPSBpc1dpbGRjYXJkUGF0aCh0YXJnZXRLZXkpID8gdW5kZWZpbmVkIDogZW50aS5nZXQodGFyZ2V0S2V5KTtcblxuICAgICAgICAgICAgZW50aS5lbWl0KGV2ZW50TmFtZSwgdmFsdWUsIGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gdHJhY2tQYXRoKGVudGksIGV2ZW50TmFtZSl7XG4gICAgdmFyIG9iamVjdCA9IGVudGkuX21vZGVsLFxuICAgICAgICB0cmFja2VkT2JqZWN0UGF0aHMgPSB0cmFja2VkRXZlbnRzLmdldChvYmplY3QpO1xuXG4gICAgaWYoIXRyYWNrZWRPYmplY3RQYXRocyl7XG4gICAgICAgIHRyYWNrZWRPYmplY3RQYXRocyA9IHt9O1xuICAgICAgICB0cmFja2VkRXZlbnRzLnNldChvYmplY3QsIHRyYWNrZWRPYmplY3RQYXRocyk7XG4gICAgfVxuXG4gICAgdmFyIHRyYWNrZWRQYXRocyA9IHRyYWNrZWRPYmplY3RQYXRoc1tldmVudE5hbWVdO1xuXG4gICAgaWYoIXRyYWNrZWRQYXRocyl7XG4gICAgICAgIHRyYWNrZWRQYXRocyA9IHtcbiAgICAgICAgICAgIGVudGlzOiBuZXcgU2V0KCksXG4gICAgICAgICAgICB0cmFja2VkT2JqZWN0czogbmV3IFdlYWtTZXQoKVxuICAgICAgICB9O1xuICAgICAgICB0cmFja2VkT2JqZWN0UGF0aHNbZXZlbnROYW1lXSA9IHRyYWNrZWRQYXRocztcbiAgICB9ZWxzZSBpZih0cmFja2VkUGF0aHMuZW50aXMuaGFzKGVudGkpKXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRyYWNrZWRQYXRocy5lbnRpcy5hZGQoZW50aSk7XG5cbiAgICB2YXIgaGFuZGxlciA9IGNyZWF0ZUhhbmRsZXIoZW50aSwgdHJhY2tlZE9iamVjdFBhdGhzLCB0cmFja2VkUGF0aHMsIGV2ZW50TmFtZSk7XG5cbiAgICB0cmFja09iamVjdHMoZXZlbnROYW1lLCB0cmFja2VkUGF0aHMudHJhY2tlZE9iamVjdHMsIGhhbmRsZXIsIHttb2RlbDpvYmplY3R9LCAnbW9kZWwnLCBldmVudE5hbWUpO1xufVxuXG5mdW5jdGlvbiB0cmFja1BhdGhzKGVudGkpe1xuICAgIGlmKCFlbnRpLl9ldmVudHMgfHwgIWVudGkuX21vZGVsKXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGZvcih2YXIga2V5IGluIGVudGkuX2V2ZW50cyl7XG4gICAgICAgIHRyYWNrUGF0aChlbnRpLCBrZXkpO1xuICAgIH1cbiAgICBtb2RpZmllZEVudGllcy5kZWxldGUoZW50aSk7XG59XG5cbmZ1bmN0aW9uIGVtaXRFdmVudChvYmplY3QsIGtleSwgdmFsdWUsIGVtaXRLZXkpe1xuXG4gICAgbW9kaWZpZWRFbnRpZXMuZm9yRWFjaCh0cmFja1BhdGhzKTtcblxuICAgIHZhciB0cmFja2VkS2V5cyA9IHRyYWNrZWRPYmplY3RzLmdldChvYmplY3QpO1xuXG4gICAgaWYoIXRyYWNrZWRLZXlzKXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBldmVudCA9IHtcbiAgICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgb2JqZWN0OiBvYmplY3RcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gZW1pdEZvcktleShoYW5kbGVyKXtcbiAgICAgICAgaGFuZGxlcihldmVudCwgZW1pdEtleSk7XG4gICAgfVxuXG4gICAgaWYodHJhY2tlZEtleXNba2V5XSl7XG4gICAgICAgIHRyYWNrZWRLZXlzW2tleV0uZm9yRWFjaChlbWl0Rm9yS2V5KTtcbiAgICB9XG5cbiAgICBpZih0cmFja2VkS2V5c1snKiddKXtcbiAgICAgICAgdHJhY2tlZEtleXNbJyonXS5mb3JFYWNoKGVtaXRGb3JLZXkpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZW1pdChldmVudHMpe1xuICAgIHZhciBlbWl0S2V5ID0ge307XG4gICAgZXZlbnRzLmZvckVhY2goZnVuY3Rpb24oZXZlbnQpe1xuICAgICAgICBlbWl0RXZlbnQoZXZlbnRbMF0sIGV2ZW50WzFdLCBldmVudFsyXSwgZW1pdEtleSk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIEVudGkobW9kZWwpe1xuICAgIHZhciBkZXRhY2hlZCA9IG1vZGVsID09PSBmYWxzZTtcblxuICAgIGlmKCFtb2RlbCB8fCAodHlwZW9mIG1vZGVsICE9PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kZWwgIT09ICdmdW5jdGlvbicpKXtcbiAgICAgICAgbW9kZWwgPSB7fTtcbiAgICB9XG5cbiAgICB0aGlzLl9lbWl0dGVkRXZlbnRzID0ge307XG4gICAgaWYoZGV0YWNoZWQpe1xuICAgICAgICB0aGlzLl9tb2RlbCA9IHt9O1xuICAgIH1lbHNle1xuICAgICAgICB0aGlzLmF0dGFjaChtb2RlbCk7XG4gICAgfVxuXG4gICAgdGhpcy5vbignbmV3TGlzdGVuZXInLCBmdW5jdGlvbigpe1xuICAgICAgICBtb2RpZmllZEVudGllcy5hZGQodGhpcyk7XG4gICAgfSk7XG59XG5FbnRpLmVtaXQgPSBmdW5jdGlvbihtb2RlbCwga2V5LCB2YWx1ZSl7XG4gICAgaWYoISh0eXBlb2YgbW9kZWwgPT09ICdvYmplY3QnIHx8IHR5cGVvZiBtb2RlbCA9PT0gJ2Z1bmN0aW9uJykpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZW1pdChbW21vZGVsLCBrZXksIHZhbHVlXV0pO1xufTtcbkVudGkuZ2V0ID0gZnVuY3Rpb24obW9kZWwsIGtleSl7XG4gICAgaWYoIW1vZGVsIHx8IHR5cGVvZiBtb2RlbCAhPT0gJ29iamVjdCcpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAga2V5ID0gZ2V0VGFyZ2V0S2V5KGtleSk7XG5cbiAgICBpZihrZXkgPT09ICcuJyl7XG4gICAgICAgIHJldHVybiBtb2RlbDtcbiAgICB9XG5cblxuICAgIHZhciBwYXRoID0gbGVmdEFuZFJlc3Qoa2V5KTtcbiAgICBpZihBcnJheS5pc0FycmF5KHBhdGgpKXtcbiAgICAgICAgcmV0dXJuIEVudGkuZ2V0KG1vZGVsW3BhdGhbMF1dLCBwYXRoWzFdKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbW9kZWxba2V5XTtcbn07XG5FbnRpLnNldCA9IGZ1bmN0aW9uKG1vZGVsLCBrZXksIHZhbHVlKXtcbiAgICBpZighbW9kZWwgfHwgdHlwZW9mIG1vZGVsICE9PSAnb2JqZWN0Jyl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBrZXkgPSBnZXRUYXJnZXRLZXkoa2V5KTtcblxuICAgIHZhciBwYXRoID0gbGVmdEFuZFJlc3Qoa2V5KTtcbiAgICBpZihBcnJheS5pc0FycmF5KHBhdGgpKXtcbiAgICAgICAgcmV0dXJuIEVudGkuc2V0KG1vZGVsW3BhdGhbMF1dLCBwYXRoWzFdLCB2YWx1ZSk7XG4gICAgfVxuXG4gICAgdmFyIG9yaWdpbmFsID0gbW9kZWxba2V5XTtcblxuICAgIGlmKHR5cGVvZiB2YWx1ZSAhPT0gJ29iamVjdCcgJiYgdmFsdWUgPT09IG9yaWdpbmFsKXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBrZXlzQ2hhbmdlZCA9ICEoa2V5IGluIG1vZGVsKTtcblxuICAgIG1vZGVsW2tleV0gPSB2YWx1ZTtcblxuICAgIHZhciBldmVudHMgPSBbW21vZGVsLCBrZXksIHZhbHVlXV07XG5cbiAgICBpZihrZXlzQ2hhbmdlZCl7XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkobW9kZWwpKXtcbiAgICAgICAgICAgIGV2ZW50cy5wdXNoKFttb2RlbCwgJ2xlbmd0aCcsIG1vZGVsLmxlbmd0aF0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZW1pdChldmVudHMpO1xufTtcbkVudGkucHVzaCA9IGZ1bmN0aW9uKG1vZGVsLCBrZXksIHZhbHVlKXtcbiAgICBpZighbW9kZWwgfHwgdHlwZW9mIG1vZGVsICE9PSAnb2JqZWN0Jyl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgdGFyZ2V0O1xuICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPCAzKXtcbiAgICAgICAgdmFsdWUgPSBrZXk7XG4gICAgICAgIGtleSA9ICcuJztcbiAgICAgICAgdGFyZ2V0ID0gbW9kZWw7XG4gICAgfWVsc2V7XG4gICAgICAgIHZhciBwYXRoID0gbGVmdEFuZFJlc3Qoa2V5KTtcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheShwYXRoKSl7XG4gICAgICAgICAgICByZXR1cm4gRW50aS5wdXNoKG1vZGVsW3BhdGhbMF1dLCBwYXRoWzFdLCB2YWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0YXJnZXQgPSBtb2RlbFtrZXldO1xuICAgIH1cblxuICAgIGlmKCFBcnJheS5pc0FycmF5KHRhcmdldCkpe1xuICAgICAgICB0aHJvdyAnVGhlIHRhcmdldCBpcyBub3QgYW4gYXJyYXkuJztcbiAgICB9XG5cbiAgICB0YXJnZXQucHVzaCh2YWx1ZSk7XG5cbiAgICB2YXIgZXZlbnRzID0gW1xuICAgICAgICBbdGFyZ2V0LCB0YXJnZXQubGVuZ3RoLTEsIHZhbHVlXSxcbiAgICAgICAgW3RhcmdldCwgJ2xlbmd0aCcsIHRhcmdldC5sZW5ndGhdXG4gICAgXTtcblxuICAgIGVtaXQoZXZlbnRzKTtcbn07XG5FbnRpLmluc2VydCA9IGZ1bmN0aW9uKG1vZGVsLCBrZXksIHZhbHVlLCBpbmRleCl7XG4gICAgaWYoIW1vZGVsIHx8IHR5cGVvZiBtb2RlbCAhPT0gJ29iamVjdCcpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG5cbiAgICB2YXIgdGFyZ2V0O1xuICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPCA0KXtcbiAgICAgICAgaW5kZXggPSB2YWx1ZTtcbiAgICAgICAgdmFsdWUgPSBrZXk7XG4gICAgICAgIGtleSA9ICcuJztcbiAgICAgICAgdGFyZ2V0ID0gbW9kZWw7XG4gICAgfWVsc2V7XG4gICAgICAgIHZhciBwYXRoID0gbGVmdEFuZFJlc3Qoa2V5KTtcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheShwYXRoKSl7XG4gICAgICAgICAgICByZXR1cm4gRW50aS5pbnNlcnQobW9kZWxbcGF0aFswXV0sIHBhdGhbMV0sIHZhbHVlLCBpbmRleCk7XG4gICAgICAgIH1cblxuICAgICAgICB0YXJnZXQgPSBtb2RlbFtrZXldO1xuICAgIH1cblxuICAgIGlmKCFBcnJheS5pc0FycmF5KHRhcmdldCkpe1xuICAgICAgICB0aHJvdyAnVGhlIHRhcmdldCBpcyBub3QgYW4gYXJyYXkuJztcbiAgICB9XG5cbiAgICB0YXJnZXQuc3BsaWNlKGluZGV4LCAwLCB2YWx1ZSk7XG5cbiAgICB2YXIgZXZlbnRzID0gW1xuICAgICAgICBbdGFyZ2V0LCBpbmRleCwgdmFsdWVdLFxuICAgICAgICBbdGFyZ2V0LCAnbGVuZ3RoJywgdGFyZ2V0Lmxlbmd0aF1cbiAgICBdO1xuXG4gICAgZW1pdChldmVudHMpO1xufTtcbkVudGkucmVtb3ZlID0gZnVuY3Rpb24obW9kZWwsIGtleSwgc3ViS2V5KXtcbiAgICBpZighbW9kZWwgfHwgdHlwZW9mIG1vZGVsICE9PSAnb2JqZWN0Jyl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgcGF0aCA9IGxlZnRBbmRSZXN0KGtleSk7XG4gICAgaWYoQXJyYXkuaXNBcnJheShwYXRoKSl7XG4gICAgICAgIHJldHVybiBFbnRpLnJlbW92ZShtb2RlbFtwYXRoWzBdXSwgcGF0aFsxXSwgc3ViS2V5KTtcbiAgICB9XG5cbiAgICAvLyBSZW1vdmUgYSBrZXkgb2ZmIG9mIGFuIG9iamVjdCBhdCAna2V5J1xuICAgIGlmKHN1YktleSAhPSBudWxsKXtcbiAgICAgICAgRW50aS5yZW1vdmUobW9kZWxba2V5XSwgc3ViS2V5KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmKGtleSA9PT0gJy4nKXtcbiAgICAgICAgdGhyb3cgJy4gKHNlbGYpIGlzIG5vdCBhIHZhbGlkIGtleSB0byByZW1vdmUnO1xuICAgIH1cblxuICAgIHZhciBldmVudHMgPSBbXTtcblxuICAgIGlmKEFycmF5LmlzQXJyYXkobW9kZWwpKXtcbiAgICAgICAgbW9kZWwuc3BsaWNlKGtleSwgMSk7XG4gICAgICAgIGV2ZW50cy5wdXNoKFttb2RlbCwgJ2xlbmd0aCcsIG1vZGVsLmxlbmd0aF0pO1xuICAgIH1lbHNle1xuICAgICAgICBkZWxldGUgbW9kZWxba2V5XTtcbiAgICAgICAgZXZlbnRzLnB1c2goW21vZGVsLCBrZXldKTtcbiAgICB9XG5cbiAgICBlbWl0KGV2ZW50cyk7XG59O1xuRW50aS5tb3ZlID0gZnVuY3Rpb24obW9kZWwsIGtleSwgaW5kZXgpe1xuICAgIGlmKCFtb2RlbCB8fCB0eXBlb2YgbW9kZWwgIT09ICdvYmplY3QnKXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBwYXRoID0gbGVmdEFuZFJlc3Qoa2V5KTtcbiAgICBpZihBcnJheS5pc0FycmF5KHBhdGgpKXtcbiAgICAgICAgcmV0dXJuIEVudGkubW92ZShtb2RlbFtwYXRoWzBdXSwgcGF0aFsxXSwgaW5kZXgpO1xuICAgIH1cblxuICAgIGlmKGtleSA9PT0gaW5kZXgpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYoIUFycmF5LmlzQXJyYXkobW9kZWwpKXtcbiAgICAgICAgdGhyb3cgJ1RoZSBtb2RlbCBpcyBub3QgYW4gYXJyYXkuJztcbiAgICB9XG5cbiAgICB2YXIgaXRlbSA9IG1vZGVsW2tleV07XG5cbiAgICBtb2RlbC5zcGxpY2Uoa2V5LCAxKTtcblxuICAgIG1vZGVsLnNwbGljZShpbmRleCAtIChpbmRleCA+IGtleSA/IDAgOiAxKSwgMCwgaXRlbSk7XG5cbiAgICBlbWl0KFtbbW9kZWwsIGluZGV4LCBpdGVtXV0pO1xufTtcbkVudGkudXBkYXRlID0gZnVuY3Rpb24obW9kZWwsIGtleSwgdmFsdWUpe1xuICAgIGlmKCFtb2RlbCB8fCB0eXBlb2YgbW9kZWwgIT09ICdvYmplY3QnKXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciB0YXJnZXQsXG4gICAgICAgIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5KHZhbHVlKTtcblxuICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPCAzKXtcbiAgICAgICAgdmFsdWUgPSBrZXk7XG4gICAgICAgIGtleSA9ICcuJztcbiAgICAgICAgdGFyZ2V0ID0gbW9kZWw7XG4gICAgfWVsc2V7XG4gICAgICAgIHZhciBwYXRoID0gbGVmdEFuZFJlc3Qoa2V5KTtcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheShwYXRoKSl7XG4gICAgICAgICAgICByZXR1cm4gRW50aS51cGRhdGUobW9kZWxbcGF0aFswXV0sIHBhdGhbMV0sIHZhbHVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRhcmdldCA9IG1vZGVsW2tleV07XG5cbiAgICAgICAgaWYodGFyZ2V0ID09IG51bGwpe1xuICAgICAgICAgICAgbW9kZWxba2V5XSA9IGlzQXJyYXkgPyBbXSA6IHt9O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYodHlwZW9mIHZhbHVlICE9PSAnb2JqZWN0Jyl7XG4gICAgICAgIHRocm93ICdUaGUgdmFsdWUgaXMgbm90IGFuIG9iamVjdC4nO1xuICAgIH1cblxuICAgIGlmKHR5cGVvZiB0YXJnZXQgIT09ICdvYmplY3QnKXtcbiAgICAgICAgdGhyb3cgJ1RoZSB0YXJnZXQgaXMgbm90IGFuIG9iamVjdC4nO1xuICAgIH1cblxuICAgIHZhciBldmVudHMgPSBbXSxcbiAgICAgICAgdXBkYXRlZE9iamVjdHMgPSBuZXcgV2Vha1NldCgpO1xuXG4gICAgZnVuY3Rpb24gdXBkYXRlVGFyZ2V0KHRhcmdldCwgdmFsdWUpe1xuICAgICAgICBmb3IodmFyIGtleSBpbiB2YWx1ZSl7XG4gICAgICAgICAgICB2YXIgY3VycmVudFZhbHVlID0gdGFyZ2V0W2tleV07XG4gICAgICAgICAgICBpZihjdXJyZW50VmFsdWUgaW5zdGFuY2VvZiBPYmplY3QgJiYgIXVwZGF0ZWRPYmplY3RzLmhhcyhjdXJyZW50VmFsdWUpICYmICEoY3VycmVudFZhbHVlIGluc3RhbmNlb2YgRGF0ZSkpe1xuICAgICAgICAgICAgICAgIHVwZGF0ZWRPYmplY3RzLmFkZChjdXJyZW50VmFsdWUpO1xuICAgICAgICAgICAgICAgIHVwZGF0ZVRhcmdldChjdXJyZW50VmFsdWUsIHZhbHVlW2tleV0pO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGFyZ2V0W2tleV0gPSB2YWx1ZVtrZXldO1xuICAgICAgICAgICAgZXZlbnRzLnB1c2goW3RhcmdldCwga2V5LCB2YWx1ZVtrZXldXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihBcnJheS5pc0FycmF5KHRhcmdldCkpe1xuICAgICAgICAgICAgZXZlbnRzLnB1c2goW3RhcmdldCwgJ2xlbmd0aCcsIHRhcmdldC5sZW5ndGhdKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHVwZGF0ZVRhcmdldCh0YXJnZXQsIHZhbHVlKTtcblxuICAgIGVtaXQoZXZlbnRzKTtcbn07XG5FbnRpLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRXZlbnRFbWl0dGVyLnByb3RvdHlwZSk7XG5FbnRpLnByb3RvdHlwZS5fbWF4TGlzdGVuZXJzID0gMTAwO1xuRW50aS5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBFbnRpO1xuRW50aS5wcm90b3R5cGUuYXR0YWNoID0gZnVuY3Rpb24obW9kZWwpe1xuICAgIGlmKHRoaXMuX21vZGVsICE9PSBtb2RlbCl7XG4gICAgICAgIHRoaXMuZGV0YWNoKCk7XG4gICAgfVxuXG4gICAgaWYobW9kZWwgJiYgIWlzSW5zdGFuY2UobW9kZWwpKXtcbiAgICAgICAgdGhyb3cgJ0VudGlzIG1heSBvbmx5IGJlIGF0dGFjaGVkIHRvIGFuIG9iamVjdCwgb3IgbnVsbC91bmRlZmluZWQnO1xuICAgIH1cblxuICAgIG1vZGlmaWVkRW50aWVzLmFkZCh0aGlzKTtcbiAgICB0aGlzLl9hdHRhY2hlZCA9IHRydWU7XG4gICAgdGhpcy5fbW9kZWwgPSBtb2RlbDtcbiAgICB0aGlzLmVtaXQoJ2F0dGFjaCcsIG1vZGVsKTtcbn07XG5FbnRpLnByb3RvdHlwZS5kZXRhY2ggPSBmdW5jdGlvbigpe1xuICAgIG1vZGlmaWVkRW50aWVzLmRlbGV0ZSh0aGlzKTtcblxuICAgIHRoaXMuX2VtaXR0ZWRFdmVudHMgPSB7fTtcbiAgICB0aGlzLl9tb2RlbCA9IHt9O1xuICAgIHRoaXMuX2F0dGFjaGVkID0gZmFsc2U7XG4gICAgdGhpcy5lbWl0KCdkZXRhY2gnKTtcbn07XG5FbnRpLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24oKXtcbiAgICB0aGlzLmRldGFjaCgpO1xuICAgIHRoaXMuX2V2ZW50cyA9IG51bGw7XG4gICAgdGhpcy5lbWl0KCdkZXN0cm95Jyk7XG59O1xuRW50aS5wcm90b3R5cGUuZ2V0ID0gZnVuY3Rpb24oa2V5KXtcbiAgICByZXR1cm4gRW50aS5nZXQodGhpcy5fbW9kZWwsIGtleSk7XG59O1xuXG5FbnRpLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbihrZXksIHZhbHVlKXtcbiAgICByZXR1cm4gRW50aS5zZXQodGhpcy5fbW9kZWwsIGtleSwgdmFsdWUpO1xufTtcblxuRW50aS5wcm90b3R5cGUucHVzaCA9IGZ1bmN0aW9uKGtleSwgdmFsdWUpe1xuICAgIHJldHVybiBFbnRpLnB1c2guYXBwbHkobnVsbCwgW3RoaXMuX21vZGVsXS5jb25jYXQodG9BcnJheShhcmd1bWVudHMpKSk7XG59O1xuXG5FbnRpLnByb3RvdHlwZS5pbnNlcnQgPSBmdW5jdGlvbihrZXksIHZhbHVlLCBpbmRleCl7XG4gICAgcmV0dXJuIEVudGkuaW5zZXJ0LmFwcGx5KG51bGwsIFt0aGlzLl9tb2RlbF0uY29uY2F0KHRvQXJyYXkoYXJndW1lbnRzKSkpO1xufTtcblxuRW50aS5wcm90b3R5cGUucmVtb3ZlID0gZnVuY3Rpb24oa2V5LCBzdWJLZXkpe1xuICAgIHJldHVybiBFbnRpLnJlbW92ZS5hcHBseShudWxsLCBbdGhpcy5fbW9kZWxdLmNvbmNhdCh0b0FycmF5KGFyZ3VtZW50cykpKTtcbn07XG5cbkVudGkucHJvdG90eXBlLm1vdmUgPSBmdW5jdGlvbihrZXksIGluZGV4KXtcbiAgICByZXR1cm4gRW50aS5tb3ZlLmFwcGx5KG51bGwsIFt0aGlzLl9tb2RlbF0uY29uY2F0KHRvQXJyYXkoYXJndW1lbnRzKSkpO1xufTtcblxuRW50aS5wcm90b3R5cGUudXBkYXRlID0gZnVuY3Rpb24oa2V5LCBpbmRleCl7XG4gICAgcmV0dXJuIEVudGkudXBkYXRlLmFwcGx5KG51bGwsIFt0aGlzLl9tb2RlbF0uY29uY2F0KHRvQXJyYXkoYXJndW1lbnRzKSkpO1xufTtcbkVudGkucHJvdG90eXBlLmlzQXR0YWNoZWQgPSBmdW5jdGlvbigpe1xuICAgIHJldHVybiB0aGlzLl9hdHRhY2hlZDtcbn07XG5FbnRpLnByb3RvdHlwZS5hdHRhY2hlZENvdW50ID0gZnVuY3Rpb24oKXtcbiAgICByZXR1cm4gbW9kaWZpZWRFbnRpZXMuc2l6ZTtcbn07XG5cbkVudGkuaXNFbnRpID0gZnVuY3Rpb24odGFyZ2V0KXtcbiAgICByZXR1cm4gdGFyZ2V0ICYmICEhfmdsb2JhbFN0YXRlLmluc3RhbmNlcy5pbmRleE9mKHRhcmdldC5jb25zdHJ1Y3Rvcik7XG59O1xuXG5FbnRpLnN0b3JlID0gZnVuY3Rpb24odGFyZ2V0LCBrZXksIHZhbHVlKXtcbiAgICBpZihhcmd1bWVudHMubGVuZ3RoIDwgMil7XG4gICAgICAgIHJldHVybiBFbnRpLmdldCh0YXJnZXQsIGtleSk7XG4gICAgfVxuXG4gICAgRW50aS5zZXQodGFyZ2V0LCBrZXksIHZhbHVlKTtcbn07XG5cbmdsb2JhbFN0YXRlLmluc3RhbmNlcy5wdXNoKEVudGkpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEVudGk7XG4iXX0= | |
},{"events":5,"is-instance":13}],13:[function(require,module,exports){ | |
module.exports = function(value){ | |
return value && typeof value === 'object' || typeof value === 'function'; | |
}; | |
},{}],14:[function(require,module,exports){ | |
var EventEmitter = require('events').EventEmitter, | |
functionEmitterPrototype = function(){}; | |
for(var key in EventEmitter.prototype){ | |
functionEmitterPrototype[key] = EventEmitter.prototype[key]; | |
} | |
module.exports = functionEmitterPrototype; | |
},{"events":5}],15:[function(require,module,exports){ | |
'use strict'; | |
var propIsEnumerable = Object.prototype.propertyIsEnumerable; | |
function ToObject(val) { | |
if (val == null) { | |
throw new TypeError('Object.assign cannot be called with null or undefined'); | |
} | |
return Object(val); | |
} | |
function ownEnumerableKeys(obj) { | |
var keys = Object.getOwnPropertyNames(obj); | |
if (Object.getOwnPropertySymbols) { | |
keys = keys.concat(Object.getOwnPropertySymbols(obj)); | |
} | |
return keys.filter(function (key) { | |
return propIsEnumerable.call(obj, key); | |
}); | |
} | |
module.exports = Object.assign || function (target, source) { | |
var from; | |
var keys; | |
var to = ToObject(target); | |
for (var s = 1; s < arguments.length; s++) { | |
from = arguments[s]; | |
keys = ownEnumerableKeys(Object(from)); | |
for (var i = 0; i < keys.length; i++) { | |
to[keys[i]] = from[keys[i]]; | |
} | |
} | |
return to; | |
}; | |
},{}],16:[function(require,module,exports){ | |
module.exports = function isSame(a, b){ | |
if(a === b){ | |
return true; | |
} | |
if( | |
typeof a !== typeof b || | |
typeof a === 'object' && | |
!(a instanceof Date && b instanceof Date) | |
){ | |
return false; | |
} | |
return String(a) === String(b); | |
}; | |
},{}],17:[function(require,module,exports){ | |
module.exports = Object.setPrototypeOf || ({__proto__:[]} instanceof Array ? setProtoOf : mixinProperties); | |
function setProtoOf(obj, proto) { | |
obj.__proto__ = proto; | |
} | |
function mixinProperties(obj, proto) { | |
for (var prop in proto) { | |
obj[prop] = proto[prop]; | |
} | |
} | |
},{}],18:[function(require,module,exports){ | |
var clone = require('clone'), | |
deepEqual = require('cyclic-deep-equal'); | |
function keysAreDifferent(keys1, keys2){ | |
if(keys1 === keys2){ | |
return; | |
} | |
if(!keys1 || !keys2 || keys1.length !== keys2.length){ | |
return true; | |
} | |
for(var i = 0; i < keys1.length; i++){ | |
if(!~keys2.indexOf(keys1[i])){ | |
return true; | |
} | |
} | |
} | |
function getKeys(value){ | |
if(!value || typeof value !== 'object'){ | |
return; | |
} | |
return Object.keys(value); | |
} | |
function WhatChanged(value, changesToTrack){ | |
this._changesToTrack = {}; | |
if(changesToTrack == null){ | |
changesToTrack = 'value type keys structure reference'; | |
} | |
if(typeof changesToTrack !== 'string'){ | |
throw 'changesToTrack must be of type string'; | |
} | |
changesToTrack = changesToTrack.split(' '); | |
for (var i = 0; i < changesToTrack.length; i++) { | |
this._changesToTrack[changesToTrack[i]] = true; | |
}; | |
this.update(value); | |
} | |
WhatChanged.prototype.update = function(value){ | |
var result = {}, | |
changesToTrack = this._changesToTrack, | |
newKeys = getKeys(value); | |
if('value' in changesToTrack && value+'' !== this._lastReference+''){ | |
result.value = true; | |
} | |
if( | |
'type' in changesToTrack && typeof value !== typeof this._lastValue || | |
(value === null || this._lastValue === null) && this.value !== this._lastValue // typeof null === 'object' | |
){ | |
result.type = true; | |
} | |
if('keys' in changesToTrack && keysAreDifferent(this._lastKeys, getKeys(value))){ | |
result.keys = true; | |
} | |
if(value !== null && typeof value === 'object' || typeof value === 'function'){ | |
var lastValue = this._lastValue; | |
if('shallowStructure' in changesToTrack && (!lastValue || typeof lastValue !== 'object' || Object.keys(value).some(function(key, index){ | |
return value[key] !== lastValue[key]; | |
}))){ | |
result.shallowStructure = true; | |
} | |
if('structure' in changesToTrack && !deepEqual(value, lastValue)){ | |
result.structure = true; | |
} | |
if('reference' in changesToTrack && value !== this._lastReference){ | |
result.reference = true; | |
} | |
} | |
this._lastValue = 'structure' in changesToTrack ? clone(value) : 'shallowStructure' in changesToTrack ? clone(value, true, 1): value; | |
this._lastReference = value; | |
this._lastKeys = newKeys; | |
return result; | |
}; | |
module.exports = WhatChanged; | |
},{"clone":19,"cyclic-deep-equal":20}],19:[function(require,module,exports){ | |
(function (Buffer){ | |
var clone = (function() { | |
'use strict'; | |
/** | |
* Clones (copies) an Object using deep copying. | |
* | |
* This function supports circular references by default, but if you are certain | |
* there are no circular references in your object, you can save some CPU time | |
* by calling clone(obj, false). | |
* | |
* Caution: if `circular` is false and `parent` contains circular references, | |
* your program may enter an infinite loop and crash. | |
* | |
* @param `parent` - the object to be cloned | |
* @param `circular` - set to true if the object to be cloned may contain | |
* circular references. (optional - true by default) | |
* @param `depth` - set to a number if the object is only to be cloned to | |
* a particular depth. (optional - defaults to Infinity) | |
* @param `prototype` - sets the prototype to be used when cloning an object. | |
* (optional - defaults to parent prototype). | |
*/ | |
function clone(parent, circular, depth, prototype) { | |
var filter; | |
if (typeof circular === 'object') { | |
depth = circular.depth; | |
prototype = circular.prototype; | |
filter = circular.filter; | |
circular = circular.circular | |
} | |
// maintain two arrays for circular references, where corresponding parents | |
// and children have the same index | |
var allParents = []; | |
var allChildren = []; | |
var useBuffer = typeof Buffer != 'undefined'; | |
if (typeof circular == 'undefined') | |
circular = true; | |
if (typeof depth == 'undefined') | |
depth = Infinity; | |
// recurse this function so we don't reset allParents and allChildren | |
function _clone(parent, depth) { | |
// cloning null always returns null | |
if (parent === null) | |
return null; | |
if (depth == 0) | |
return parent; | |
var child; | |
var proto; | |
if (typeof parent != 'object') { | |
return parent; | |
} | |
if (clone.__isArray(parent)) { | |
child = []; | |
} else if (clone.__isRegExp(parent)) { | |
child = new RegExp(parent.source, __getRegExpFlags(parent)); | |
if (parent.lastIndex) child.lastIndex = parent.lastIndex; | |
} else if (clone.__isDate(parent)) { | |
child = new Date(parent.getTime()); | |
} else if (useBuffer && Buffer.isBuffer(parent)) { | |
child = new Buffer(parent.length); | |
parent.copy(child); | |
return child; | |
} else { | |
if (typeof prototype == 'undefined') { | |
proto = Object.getPrototypeOf(parent); | |
child = Object.create(proto); | |
} | |
else { | |
child = Object.create(prototype); | |
proto = prototype; | |
} | |
} | |
if (circular) { | |
var index = allParents.indexOf(parent); | |
if (index != -1) { | |
return allChildren[index]; | |
} | |
allParents.push(parent); | |
allChildren.push(child); | |
} | |
for (var i in parent) { | |
var attrs; | |
if (proto) { | |
attrs = Object.getOwnPropertyDescriptor(proto, i); | |
} | |
if (attrs && attrs.set == null) { | |
continue; | |
} | |
child[i] = _clone(parent[i], depth - 1); | |
} | |
return child; | |
} | |
return _clone(parent, depth); | |
} | |
/** | |
* Simple flat clone using prototype, accepts only objects, usefull for property | |
* override on FLAT configuration object (no nested props). | |
* | |
* USE WITH CAUTION! This may not behave as you wish if you do not know how this | |
* works. | |
*/ | |
clone.clonePrototype = function clonePrototype(parent) { | |
if (parent === null) | |
return null; | |
var c = function () {}; | |
c.prototype = parent; | |
return new c(); | |
}; | |
// private utility functions | |
function __objToStr(o) { | |
return Object.prototype.toString.call(o); | |
}; | |
clone.__objToStr = __objToStr; | |
function __isDate(o) { | |
return typeof o === 'object' && __objToStr(o) === '[object Date]'; | |
}; | |
clone.__isDate = __isDate; | |
function __isArray(o) { | |
return typeof o === 'object' && __objToStr(o) === '[object Array]'; | |
}; | |
clone.__isArray = __isArray; | |
function __isRegExp(o) { | |
return typeof o === 'object' && __objToStr(o) === '[object RegExp]'; | |
}; | |
clone.__isRegExp = __isRegExp; | |
function __getRegExpFlags(re) { | |
var flags = ''; | |
if (re.global) flags += 'g'; | |
if (re.ignoreCase) flags += 'i'; | |
if (re.multiline) flags += 'm'; | |
return flags; | |
}; | |
clone.__getRegExpFlags = __getRegExpFlags; | |
return clone; | |
})(); | |
if (typeof module === 'object' && module.exports) { | |
module.exports = clone; | |
} | |
}).call(this,require("buffer").Buffer) | |
//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy93aGF0LWNoYW5nZWQvbm9kZV9tb2R1bGVzL2Nsb25lL2Nsb25lLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgY2xvbmUgPSAoZnVuY3Rpb24oKSB7XG4ndXNlIHN0cmljdCc7XG5cbi8qKlxuICogQ2xvbmVzIChjb3BpZXMpIGFuIE9iamVjdCB1c2luZyBkZWVwIGNvcHlpbmcuXG4gKlxuICogVGhpcyBmdW5jdGlvbiBzdXBwb3J0cyBjaXJjdWxhciByZWZlcmVuY2VzIGJ5IGRlZmF1bHQsIGJ1dCBpZiB5b3UgYXJlIGNlcnRhaW5cbiAqIHRoZXJlIGFyZSBubyBjaXJjdWxhciByZWZlcmVuY2VzIGluIHlvdXIgb2JqZWN0LCB5b3UgY2FuIHNhdmUgc29tZSBDUFUgdGltZVxuICogYnkgY2FsbGluZyBjbG9uZShvYmosIGZhbHNlKS5cbiAqXG4gKiBDYXV0aW9uOiBpZiBgY2lyY3VsYXJgIGlzIGZhbHNlIGFuZCBgcGFyZW50YCBjb250YWlucyBjaXJjdWxhciByZWZlcmVuY2VzLFxuICogeW91ciBwcm9ncmFtIG1heSBlbnRlciBhbiBpbmZpbml0ZSBsb29wIGFuZCBjcmFzaC5cbiAqXG4gKiBAcGFyYW0gYHBhcmVudGAgLSB0aGUgb2JqZWN0IHRvIGJlIGNsb25lZFxuICogQHBhcmFtIGBjaXJjdWxhcmAgLSBzZXQgdG8gdHJ1ZSBpZiB0aGUgb2JqZWN0IHRvIGJlIGNsb25lZCBtYXkgY29udGFpblxuICogICAgY2lyY3VsYXIgcmVmZXJlbmNlcy4gKG9wdGlvbmFsIC0gdHJ1ZSBieSBkZWZhdWx0KVxuICogQHBhcmFtIGBkZXB0aGAgLSBzZXQgdG8gYSBudW1iZXIgaWYgdGhlIG9iamVjdCBpcyBvbmx5IHRvIGJlIGNsb25lZCB0b1xuICogICAgYSBwYXJ0aWN1bGFyIGRlcHRoLiAob3B0aW9uYWwgLSBkZWZhdWx0cyB0byBJbmZpbml0eSlcbiAqIEBwYXJhbSBgcHJvdG90eXBlYCAtIHNldHMgdGhlIHByb3RvdHlwZSB0byBiZSB1c2VkIHdoZW4gY2xvbmluZyBhbiBvYmplY3QuXG4gKiAgICAob3B0aW9uYWwgLSBkZWZhdWx0cyB0byBwYXJlbnQgcHJvdG90eXBlKS5cbiovXG5mdW5jdGlvbiBjbG9uZShwYXJlbnQsIGNpcmN1bGFyLCBkZXB0aCwgcHJvdG90eXBlKSB7XG4gIHZhciBmaWx0ZXI7XG4gIGlmICh0eXBlb2YgY2lyY3VsYXIgPT09ICdvYmplY3QnKSB7XG4gICAgZGVwdGggPSBjaXJjdWxhci5kZXB0aDtcbiAgICBwcm90b3R5cGUgPSBjaXJjdWxhci5wcm90b3R5cGU7XG4gICAgZmlsdGVyID0gY2lyY3VsYXIuZmlsdGVyO1xuICAgIGNpcmN1bGFyID0gY2lyY3VsYXIuY2lyY3VsYXJcbiAgfVxuICAvLyBtYWludGFpbiB0d28gYXJyYXlzIGZvciBjaXJjdWxhciByZWZlcmVuY2VzLCB3aGVyZSBjb3JyZXNwb25kaW5nIHBhcmVudHNcbiAgLy8gYW5kIGNoaWxkcmVuIGhhdmUgdGhlIHNhbWUgaW5kZXhcbiAgdmFyIGFsbFBhcmVudHMgPSBbXTtcbiAgdmFyIGFsbENoaWxkcmVuID0gW107XG5cbiAgdmFyIHVzZUJ1ZmZlciA9IHR5cGVvZiBCdWZmZXIgIT0gJ3VuZGVmaW5lZCc7XG5cbiAgaWYgKHR5cGVvZiBjaXJjdWxhciA9PSAndW5kZWZpbmVkJylcbiAgICBjaXJjdWxhciA9IHRydWU7XG5cbiAgaWYgKHR5cGVvZiBkZXB0aCA9PSAndW5kZWZpbmVkJylcbiAgICBkZXB0aCA9IEluZmluaXR5O1xuXG4gIC8vIHJlY3Vyc2UgdGhpcyBmdW5jdGlvbiBzbyB3ZSBkb24ndCByZXNldCBhbGxQYXJlbnRzIGFuZCBhbGxDaGlsZHJlblxuICBmdW5jdGlvbiBfY2xvbmUocGFyZW50LCBkZXB0aCkge1xuICAgIC8vIGNsb25pbmcgbnVsbCBhbHdheXMgcmV0dXJucyBudWxsXG4gICAgaWYgKHBhcmVudCA9PT0gbnVsbClcbiAgICAgIHJldHVybiBudWxsO1xuXG4gICAgaWYgKGRlcHRoID09IDApXG4gICAgICByZXR1cm4gcGFyZW50O1xuXG4gICAgdmFyIGNoaWxkO1xuICAgIHZhciBwcm90bztcbiAgICBpZiAodHlwZW9mIHBhcmVudCAhPSAnb2JqZWN0Jykge1xuICAgICAgcmV0dXJuIHBhcmVudDtcbiAgICB9XG5cbiAgICBpZiAoY2xvbmUuX19pc0FycmF5KHBhcmVudCkpIHtcbiAgICAgIGNoaWxkID0gW107XG4gICAgfSBlbHNlIGlmIChjbG9uZS5fX2lzUmVnRXhwKHBhcmVudCkpIHtcbiAgICAgIGNoaWxkID0gbmV3IFJlZ0V4cChwYXJlbnQuc291cmNlLCBfX2dldFJlZ0V4cEZsYWdzKHBhcmVudCkpO1xuICAgICAgaWYgKHBhcmVudC5sYXN0SW5kZXgpIGNoaWxkLmxhc3RJbmRleCA9IHBhcmVudC5sYXN0SW5kZXg7XG4gICAgfSBlbHNlIGlmIChjbG9uZS5fX2lzRGF0ZShwYXJlbnQpKSB7XG4gICAgICBjaGlsZCA9IG5ldyBEYXRlKHBhcmVudC5nZXRUaW1lKCkpO1xuICAgIH0gZWxzZSBpZiAodXNlQnVmZmVyICYmIEJ1ZmZlci5pc0J1ZmZlcihwYXJlbnQpKSB7XG4gICAgICBjaGlsZCA9IG5ldyBCdWZmZXIocGFyZW50Lmxlbmd0aCk7XG4gICAgICBwYXJlbnQuY29weShjaGlsZCk7XG4gICAgICByZXR1cm4gY2hpbGQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh0eXBlb2YgcHJvdG90eXBlID09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHBhcmVudCk7XG4gICAgICAgIGNoaWxkID0gT2JqZWN0LmNyZWF0ZShwcm90byk7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgY2hpbGQgPSBPYmplY3QuY3JlYXRlKHByb3RvdHlwZSk7XG4gICAgICAgIHByb3RvID0gcHJvdG90eXBlO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjaXJjdWxhcikge1xuICAgICAgdmFyIGluZGV4ID0gYWxsUGFyZW50cy5pbmRleE9mKHBhcmVudCk7XG5cbiAgICAgIGlmIChpbmRleCAhPSAtMSkge1xuICAgICAgICByZXR1cm4gYWxsQ2hpbGRyZW5baW5kZXhdO1xuICAgICAgfVxuICAgICAgYWxsUGFyZW50cy5wdXNoKHBhcmVudCk7XG4gICAgICBhbGxDaGlsZHJlbi5wdXNoKGNoaWxkKTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpIGluIHBhcmVudCkge1xuICAgICAgdmFyIGF0dHJzO1xuICAgICAgaWYgKHByb3RvKSB7XG4gICAgICAgIGF0dHJzID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihwcm90bywgaSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChhdHRycyAmJiBhdHRycy5zZXQgPT0gbnVsbCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNoaWxkW2ldID0gX2Nsb25lKHBhcmVudFtpXSwgZGVwdGggLSAxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2hpbGQ7XG4gIH1cblxuICByZXR1cm4gX2Nsb25lKHBhcmVudCwgZGVwdGgpO1xufVxuXG4vKipcbiAqIFNpbXBsZSBmbGF0IGNsb25lIHVzaW5nIHByb3RvdHlwZSwgYWNjZXB0cyBvbmx5IG9iamVjdHMsIHVzZWZ1bGwgZm9yIHByb3BlcnR5XG4gKiBvdmVycmlkZSBvbiBGTEFUIGNvbmZpZ3VyYXRpb24gb2JqZWN0IChubyBuZXN0ZWQgcHJvcHMpLlxuICpcbiAqIFVTRSBXSVRIIENBVVRJT04hIFRoaXMgbWF5IG5vdCBiZWhhdmUgYXMgeW91IHdpc2ggaWYgeW91IGRvIG5vdCBrbm93IGhvdyB0aGlzXG4gKiB3b3Jrcy5cbiAqL1xuY2xvbmUuY2xvbmVQcm90b3R5cGUgPSBmdW5jdGlvbiBjbG9uZVByb3RvdHlwZShwYXJlbnQpIHtcbiAgaWYgKHBhcmVudCA9PT0gbnVsbClcbiAgICByZXR1cm4gbnVsbDtcblxuICB2YXIgYyA9IGZ1bmN0aW9uICgpIHt9O1xuICBjLnByb3RvdHlwZSA9IHBhcmVudDtcbiAgcmV0dXJuIG5ldyBjKCk7XG59O1xuXG4vLyBwcml2YXRlIHV0aWxpdHkgZnVuY3Rpb25zXG5cbmZ1bmN0aW9uIF9fb2JqVG9TdHIobykge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG8pO1xufTtcbmNsb25lLl9fb2JqVG9TdHIgPSBfX29ialRvU3RyO1xuXG5mdW5jdGlvbiBfX2lzRGF0ZShvKSB7XG4gIHJldHVybiB0eXBlb2YgbyA9PT0gJ29iamVjdCcgJiYgX19vYmpUb1N0cihvKSA9PT0gJ1tvYmplY3QgRGF0ZV0nO1xufTtcbmNsb25lLl9faXNEYXRlID0gX19pc0RhdGU7XG5cbmZ1bmN0aW9uIF9faXNBcnJheShvKSB7XG4gIHJldHVybiB0eXBlb2YgbyA9PT0gJ29iamVjdCcgJiYgX19vYmpUb1N0cihvKSA9PT0gJ1tvYmplY3QgQXJyYXldJztcbn07XG5jbG9uZS5fX2lzQXJyYXkgPSBfX2lzQXJyYXk7XG5cbmZ1bmN0aW9uIF9faXNSZWdFeHAobykge1xuICByZXR1cm4gdHlwZW9mIG8gPT09ICdvYmplY3QnICYmIF9fb2JqVG9TdHIobykgPT09ICdbb2JqZWN0IFJlZ0V4cF0nO1xufTtcbmNsb25lLl9faXNSZWdFeHAgPSBfX2lzUmVnRXhwO1xuXG5mdW5jdGlvbiBfX2dldFJlZ0V4cEZsYWdzKHJlKSB7XG4gIHZhciBmbGFncyA9ICcnO1xuICBpZiAocmUuZ2xvYmFsKSBmbGFncyArPSAnZyc7XG4gIGlmIChyZS5pZ25vcmVDYXNlKSBmbGFncyArPSAnaSc7XG4gIGlmIChyZS5tdWx0aWxpbmUpIGZsYWdzICs9ICdtJztcbiAgcmV0dXJuIGZsYWdzO1xufTtcbmNsb25lLl9fZ2V0UmVnRXhwRmxhZ3MgPSBfX2dldFJlZ0V4cEZsYWdzO1xuXG5yZXR1cm4gY2xvbmU7XG59KSgpO1xuXG5pZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpIHtcbiAgbW9kdWxlLmV4cG9ydHMgPSBjbG9uZTtcbn1cbiJdfQ== | |
},{"buffer":1}],20:[function(require,module,exports){ | |
function compare(a, b, visited){ | |
var aType = typeof a; | |
if(aType !== typeof b){ | |
return false; | |
} | |
if(a == null || b == null || !(aType === 'object' || aType === 'function')){ | |
if(aType === 'number' && isNaN(a) && isNaN(b)){ | |
return true; | |
} | |
return a === b; | |
} | |
if(Array.isArray(a) !== Array.isArray(b)){ | |
return false; | |
} | |
var aKeys = Object.keys(a), | |
bKeys = Object.keys(b); | |
if(aKeys.length !== bKeys.length){ | |
return false; | |
} | |
var equal = true; | |
if(!visited){ | |
visited = new Set(); | |
} | |
aKeys.forEach(function(key){ | |
if(!(key in b)){ | |
equal = false; | |
return; | |
} | |
if(visited.has(a[key])){ | |
return; | |
} | |
visited.add(a[key]); | |
if(!compare(a[key], b[key], visited)){ | |
equal = false; | |
return; | |
} | |
}); | |
return equal; | |
}; | |
module.exports = function(a, b){ | |
return compare(a, b); | |
} | |
},{}],21:[function(require,module,exports){ | |
var WhatChanged = require('what-changed'), | |
same = require('same-value'), | |
firmer = require('./firmer'), | |
functionEmitter = require('function-emitter'), | |
setPrototypeOf = require('setprototypeof'); | |
var propertyProto = Object.create(functionEmitter); | |
propertyProto._fastn_property = true; | |
propertyProto._firm = 1; | |
function propertyTemplate(value){ | |
if(!arguments.length){ | |
return this.binding && this.binding() || this.property._value; | |
} | |
if(!this.destroyed){ | |
if(this.binding){ | |
this.binding(value); | |
return this.property; | |
} | |
this.valueUpdate(value); | |
} | |
return this.property; | |
} | |
function changeChecker(current, changes){ | |
if(changes){ | |
var changes = new WhatChanged(current, changes); | |
return function(value){ | |
return Object.keys(changes.update(value)).length > 0; | |
}; | |
}else{ | |
var lastValue = current; | |
return function(newValue){ | |
if(!same(lastValue, newValue)){ | |
lastValue = newValue; | |
return true; | |
} | |
}; | |
} | |
} | |
function propertyBinding(newBinding){ | |
if(!arguments.length){ | |
return this.binding; | |
} | |
if(!this.fastn.isBinding(newBinding)){ | |
newBinding = this.fastn.binding(newBinding); | |
} | |
if(newBinding === this.binding){ | |
return this.property; | |
} | |
if(this.binding){ | |
this.binding.removeListener('change', this.valueUpdate); | |
} | |
this.binding = newBinding; | |
if(this.model){ | |
this.property.attach(this.model, this.property._firm); | |
} | |
this.binding.on('change', this.valueUpdate); | |
this.valueUpdate(this.binding()); | |
return this.property; | |
}; | |
function attachProperty(object, firm){ | |
if(firmer(this.property, firm)){ | |
return this.property; | |
} | |
this.property._firm = firm; | |
if(!(object instanceof Object)){ | |
object = {}; | |
} | |
if(this.binding){ | |
this.model = object; | |
this.binding.attach(object, 1); | |
} | |
if(this.property._events && 'attach' in this.property._events){ | |
this.property.emit('attach', object, 1); | |
} | |
return this.property; | |
}; | |
function detachProperty(firm){ | |
if(firmer(this.property, firm)){ | |
return this.property; | |
} | |
if(this.binding){ | |
this.binding.removeListener('change', this.valueUpdate); | |
this.binding.detach(1); | |
this.model = null; | |
} | |
if(this.property._events && 'detach' in this.property._events){ | |
this.property.emit('detach', 1); | |
} | |
return this.property; | |
}; | |
function updateProperty(){ | |
if(!this.destroyed){ | |
if(this.property._update){ | |
this.property._update(this.property._value, this.property); | |
} | |
this.property.emit('update', this.property._value); | |
} | |
return this.property; | |
}; | |
function propertyUpdater(fn){ | |
if(!arguments.length){ | |
return this.property._update; | |
} | |
this.property._update = fn; | |
return this.property; | |
}; | |
function destroyProperty(){ | |
if(!this.destroyed){ | |
this.destroyed = true; | |
this.property | |
.removeAllListeners('change') | |
.removeAllListeners('update') | |
.removeAllListeners('attach'); | |
this.property.emit('destroy'); | |
this.property.detach(); | |
if(this.binding){ | |
this.binding.destroy(true); | |
} | |
} | |
return this.property; | |
}; | |
function propertyDestroyed(){ | |
return this.destroyed; | |
}; | |
function addPropertyTo(component, key){ | |
component.setProperty(key, this.property); | |
return this.property; | |
}; | |
function createProperty(currentValue, changes, updater){ | |
if(typeof changes === 'function'){ | |
updater = changes; | |
changes = null; | |
} | |
var propertyScope = | |
property = propertyTemplate.bind(propertyScope) | |
propertyScope = { | |
fastn: this, | |
hasChanged: changeChecker(currentValue, changes), | |
valueUpdate: function(value){ | |
property._value = value; | |
if(!propertyScope.hasChanged(value)){ | |
return; | |
} | |
property.emit('change', property._value); | |
property.update(); | |
} | |
}; | |
var property = propertyScope.property = propertyTemplate.bind(propertyScope); | |
property._value = currentValue; | |
property._update = updater; | |
setPrototypeOf(property, propertyProto); | |
property.binding = propertyBinding.bind(propertyScope); | |
property.attach = attachProperty.bind(propertyScope); | |
property.detach = detachProperty.bind(propertyScope); | |
property.update = updateProperty.bind(propertyScope); | |
property.updater = propertyUpdater.bind(propertyScope); | |
property.destroy = destroyProperty.bind(propertyScope); | |
property.destroyed = propertyDestroyed.bind(propertyScope); | |
property.addTo = addPropertyTo.bind(propertyScope); | |
return property; | |
}; | |
module.exports = createProperty; | |
},{"./firmer":9,"function-emitter":14,"same-value":16,"setprototypeof":17,"what-changed":18}],"fastn":[function(require,module,exports){ | |
var createProperty = require('./property'), | |
createBinding = require('./binding'), | |
BaseComponent = require('./baseComponent'), | |
crel = require('crel'), | |
Enti = require('enti'), | |
objectAssign = require('object-assign'), | |
is = require('./is'); | |
function inflateProperties(component, settings){ | |
for(var key in settings){ | |
var setting = settings[key], | |
property = component[key]; | |
if(is.property(settings[key])){ | |
if(is.property(property)){ | |
property.destroy(); | |
} | |
setting.addTo(component, key); | |
}else if(is.property(property)){ | |
if(is.binding(setting)){ | |
property.binding(setting); | |
}else{ | |
property(setting); | |
} | |
property.addTo(component, key); | |
} | |
} | |
} | |
function validateExpectedComponents(components, componentName, expectedComponents){ | |
expectedComponents = expectedComponents.filter(function(componentName){ | |
return !(componentName in components); | |
}); | |
if(expectedComponents.length){ | |
console.warn([ | |
'fastn("' + componentName + '") uses some components that have not been registered with fastn', | |
'Expected conponent constructors: ' + expectedComponents.join(', ') | |
].join('\n\n')); | |
} | |
} | |
module.exports = function(components, debug){ | |
if(!components || typeof components !== 'object'){ | |
throw new Error('fastn must be initialised with a components object'); | |
} | |
components._container = components._container || require('./containerComponent'); | |
function fastn(type){ | |
var args = []; | |
for(var i = 0; i < arguments.length; i++){ | |
args[i] = arguments[i]; | |
} | |
var settings = args[1], | |
childrenIndex = 2, | |
settingsChild = fastn.toComponent(args[1]); | |
if(Array.isArray(args[1]) || settingsChild || !args[1]){ | |
args[1] = settingsChild || args[1]; | |
childrenIndex--; | |
settings = null; | |
} | |
settings = objectAssign({}, settings || {}); | |
var types = typeof type === 'string' ? type.split(':') : Array.isArray(type) ? type : [type], | |
baseType, | |
children = args.slice(childrenIndex), | |
component = fastn.base(type, settings, children); | |
while(baseType = types.shift()){ | |
component.extend(baseType, settings, children); | |
} | |
component._properties = {}; | |
inflateProperties(component, settings); | |
return component; | |
} | |
fastn.toComponent = function(component){ | |
if(component == null){ | |
return; | |
} | |
if(is.component(component)){ | |
return component; | |
} | |
if(typeof component !== 'object' || component instanceof Date){ | |
return fastn('text', {auto: true}, component); | |
} | |
if(crel.isElement(component)){ | |
return fastn(component); | |
} | |
if(crel.isNode(component)){ | |
return fastn('text', {auto: true}, component.textContent); | |
} | |
}; | |
fastn.debug = debug; | |
fastn.property = createProperty.bind(fastn); | |
fastn.binding = createBinding(fastn); | |
fastn.isComponent = is.component; | |
fastn.isBinding = is.binding; | |
fastn.isDefaultBinding = is.defaultBinding; | |
fastn.isBindingObject = is.bindingObject; | |
fastn.isProperty = is.property; | |
fastn.components = components; | |
fastn.Model = Enti; | |
fastn.isModel = Enti.isEnti.bind(Enti); | |
fastn.base = function(type, settings, children){ | |
return new BaseComponent(fastn, type, settings, children); | |
}; | |
for(var key in components){ | |
var componentConstructor = components[key]; | |
if(componentConstructor.expectedComponents){ | |
validateExpectedComponents(components, key, componentConstructor.expectedComponents); | |
} | |
} | |
return fastn; | |
}; | |
},{"./baseComponent":6,"./binding":7,"./containerComponent":8,"./is":10,"./property":21,"crel":11,"enti":12,"object-assign":15}]},{},[]) | |
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2J1ZmZlci9pbmRleC5qcyIsIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2J1ZmZlci9ub2RlX21vZHVsZXMvYmFzZTY0LWpzL2xpYi9iNjQuanMiLCIuLi8uLi8uLi8uLi9ob21lL2FkbWluL2Jyb3dzZXJpZnktY2RuL25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9idWZmZXIvbm9kZV9tb2R1bGVzL2llZWU3NTQvaW5kZXguanMiLCIuLi8uLi8uLi8uLi9ob21lL2FkbWluL2Jyb3dzZXJpZnktY2RuL25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9idWZmZXIvbm9kZV9tb2R1bGVzL2lzYXJyYXkvaW5kZXguanMiLCIuLi8uLi8uLi8uLi9ob21lL2FkbWluL2Jyb3dzZXJpZnktY2RuL25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9ldmVudHMvZXZlbnRzLmpzIiwiYmFzZUNvbXBvbmVudC5qcyIsImJpbmRpbmcuanMiLCJjb250YWluZXJDb21wb25lbnQuanMiLCJmaXJtZXIuanMiLCJpcy5qcyIsIm5vZGVfbW9kdWxlcy9jcmVsL2NyZWwuanMiLCJub2RlX21vZHVsZXMvZW50aS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9lbnRpL25vZGVfbW9kdWxlcy9pcy1pbnN0YW5jZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9mdW5jdGlvbi1lbWl0dGVyL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL29iamVjdC1hc3NpZ24vaW5kZXguanMiLCJub2RlX21vZHVsZXMvc2FtZS12YWx1ZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9zZXRwcm90b3R5cGVvZi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy93aGF0LWNoYW5nZWQvaW5kZXguanMiLCJub2RlX21vZHVsZXMvd2hhdC1jaGFuZ2VkL25vZGVfbW9kdWxlcy9jbG9uZS9jbG9uZS5qcyIsIm5vZGVfbW9kdWxlcy93aGF0LWNoYW5nZWQvbm9kZV9tb2R1bGVzL2N5Y2xpYy1kZWVwLWVxdWFsL2luZGV4LmpzIiwicHJvcGVydHkuanMiLCJpbmRleC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9nREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1SEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9PQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0lBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdtQkE7QUFDQTtBQUNBOztBQ0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3TUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIoZnVuY3Rpb24gKGdsb2JhbCl7XG4vKiFcbiAqIFRoZSBidWZmZXIgbW9kdWxlIGZyb20gbm9kZS5qcywgZm9yIHRoZSBicm93c2VyLlxuICpcbiAqIEBhdXRob3IgICBGZXJvc3MgQWJvdWtoYWRpamVoIDxmZXJvc3NAZmVyb3NzLm9yZz4gPGh0dHA6Ly9mZXJvc3Mub3JnPlxuICogQGxpY2Vuc2UgIE1JVFxuICovXG4vKiBlc2xpbnQtZGlzYWJsZSBuby1wcm90byAqL1xuXG4ndXNlIHN0cmljdCdcblxudmFyIGJhc2U2NCA9IHJlcXVpcmUoJ2Jhc2U2NC1qcycpXG52YXIgaWVlZTc1NCA9IHJlcXVpcmUoJ2llZWU3NTQnKVxudmFyIGlzQXJyYXkgPSByZXF1aXJlKCdpc2FycmF5JylcblxuZXhwb3J0cy5CdWZmZXIgPSBCdWZmZXJcbmV4cG9ydHMuU2xvd0J1ZmZlciA9IFNsb3dCdWZmZXJcbmV4cG9ydHMuSU5TUEVDVF9NQVhfQllURVMgPSA1MFxuQnVmZmVyLnBvb2xTaXplID0gODE5MiAvLyBub3QgdXNlZCBieSB0aGlzIGltcGxlbWVudGF0aW9uXG5cbnZhciByb290UGFyZW50ID0ge31cblxuLyoqXG4gKiBJZiBgQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlRgOlxuICogICA9PT0gdHJ1ZSAgICBVc2UgVWludDhBcnJheSBpbXBsZW1lbnRhdGlvbiAoZmFzdGVzdClcbiAqICAgPT09IGZhbHNlICAgVXNlIE9iamVjdCBpbXBsZW1lbnRhdGlvbiAobW9zdCBjb21wYXRpYmxlLCBldmVuIElFNilcbiAqXG4gKiBCcm93c2VycyB0aGF0IHN1cHBvcnQgdHlwZWQgYXJyYXlzIGFyZSBJRSAxMCssIEZpcmVmb3ggNCssIENocm9tZSA3KywgU2FmYXJpIDUuMSssXG4gKiBPcGVyYSAxMS42KywgaU9TIDQuMisuXG4gKlxuICogRHVlIHRvIHZhcmlvdXMgYnJvd3NlciBidWdzLCBzb21ldGltZXMgdGhlIE9iamVjdCBpbXBsZW1lbnRhdGlvbiB3aWxsIGJlIHVzZWQgZXZlblxuICogd2hlbiB0aGUgYnJvd3NlciBzdXBwb3J0cyB0eXBlZCBhcnJheXMuXG4gKlxuICogTm90ZTpcbiAqXG4gKiAgIC0gRmlyZWZveCA0LTI5IGxhY2tzIHN1cHBvcnQgZm9yIGFkZGluZyBuZXcgcHJvcGVydGllcyB0byBgVWludDhBcnJheWAgaW5zdGFuY2VzLFxuICogICAgIFNlZTogaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9Njk1NDM4LlxuICpcbiAqICAgLSBTYWZhcmkgNS03IGxhY2tzIHN1cHBvcnQgZm9yIGNoYW5naW5nIHRoZSBgT2JqZWN0LnByb3RvdHlwZS5jb25zdHJ1Y3RvcmAgcHJvcGVydHlcbiAqICAgICBvbiBvYmplY3RzLlxuICpcbiAqICAgLSBDaHJvbWUgOS0xMCBpcyBtaXNzaW5nIHRoZSBgVHlwZWRBcnJheS5wcm90b3R5cGUuc3ViYXJyYXlgIGZ1bmN0aW9uLlxuICpcbiAqICAgLSBJRTEwIGhhcyBhIGJyb2tlbiBgVHlwZWRBcnJheS5wcm90b3R5cGUuc3ViYXJyYXlgIGZ1bmN0aW9uIHdoaWNoIHJldHVybnMgYXJyYXlzIG9mXG4gKiAgICAgaW5jb3JyZWN0IGxlbmd0aCBpbiBzb21lIHNpdHVhdGlvbnMuXG5cbiAqIFdlIGRldGVjdCB0aGVzZSBidWdneSBicm93c2VycyBhbmQgc2V0IGBCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVGAgdG8gYGZhbHNlYCBzbyB0aGV5XG4gKiBnZXQgdGhlIE9iamVjdCBpbXBsZW1lbnRhdGlvbiwgd2hpY2ggaXMgc2xvd2VyIGJ1dCBiZWhhdmVzIGNvcnJlY3RseS5cbiAqL1xuQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQgPSBnbG9iYWwuVFlQRURfQVJSQVlfU1VQUE9SVCAhPT0gdW5kZWZpbmVkXG4gID8gZ2xvYmFsLlRZUEVEX0FSUkFZX1NVUFBPUlRcbiAgOiB0eXBlZEFycmF5U3VwcG9ydCgpXG5cbmZ1bmN0aW9uIHR5cGVkQXJyYXlTdXBwb3J0ICgpIHtcbiAgZnVuY3Rpb24gQmFyICgpIHt9XG4gIHRyeSB7XG4gICAgdmFyIGFyciA9IG5ldyBVaW50OEFycmF5KDEpXG4gICAgYXJyLmZvbyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIDQyIH1cbiAgICBhcnIuY29uc3RydWN0b3IgPSBCYXJcbiAgICByZXR1cm4gYXJyLmZvbygpID09PSA0MiAmJiAvLyB0eXBlZCBhcnJheSBpbnN0YW5jZXMgY2FuIGJlIGF1Z21lbnRlZFxuICAgICAgICBhcnIuY29uc3RydWN0b3IgPT09IEJhciAmJiAvLyBjb25zdHJ1Y3RvciBjYW4gYmUgc2V0XG4gICAgICAgIHR5cGVvZiBhcnIuc3ViYXJyYXkgPT09ICdmdW5jdGlvbicgJiYgLy8gY2hyb21lIDktMTAgbGFjayBgc3ViYXJyYXlgXG4gICAgICAgIGFyci5zdWJhcnJheSgxLCAxKS5ieXRlTGVuZ3RoID09PSAwIC8vIGllMTAgaGFzIGJyb2tlbiBgc3ViYXJyYXlgXG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuXG5mdW5jdGlvbiBrTWF4TGVuZ3RoICgpIHtcbiAgcmV0dXJuIEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUXG4gICAgPyAweDdmZmZmZmZmXG4gICAgOiAweDNmZmZmZmZmXG59XG5cbi8qKlxuICogQ2xhc3M6IEJ1ZmZlclxuICogPT09PT09PT09PT09PVxuICpcbiAqIFRoZSBCdWZmZXIgY29uc3RydWN0b3IgcmV0dXJucyBpbnN0YW5jZXMgb2YgYFVpbnQ4QXJyYXlgIHRoYXQgYXJlIGF1Z21lbnRlZFxuICogd2l0aCBmdW5jdGlvbiBwcm9wZXJ0aWVzIGZvciBhbGwgdGhlIG5vZGUgYEJ1ZmZlcmAgQVBJIGZ1bmN0aW9ucy4gV2UgdXNlXG4gKiBgVWludDhBcnJheWAgc28gdGhhdCBzcXVhcmUgYnJhY2tldCBub3RhdGlvbiB3b3JrcyBhcyBleHBlY3RlZCAtLSBpdCByZXR1cm5zXG4gKiBhIHNpbmdsZSBvY3RldC5cbiAqXG4gKiBCeSBhdWdtZW50aW5nIHRoZSBpbnN0YW5jZXMsIHdlIGNhbiBhdm9pZCBtb2RpZnlpbmcgdGhlIGBVaW50OEFycmF5YFxuICogcHJvdG90eXBlLlxuICovXG5mdW5jdGlvbiBCdWZmZXIgKGFyZykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgQnVmZmVyKSkge1xuICAgIC8vIEF2b2lkIGdvaW5nIHRocm91Z2ggYW4gQXJndW1lbnRzQWRhcHRvclRyYW1wb2xpbmUgaW4gdGhlIGNvbW1vbiBjYXNlLlxuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkgcmV0dXJuIG5ldyBCdWZmZXIoYXJnLCBhcmd1bWVudHNbMV0pXG4gICAgcmV0dXJuIG5ldyBCdWZmZXIoYXJnKVxuICB9XG5cbiAgaWYgKCFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXMubGVuZ3RoID0gMFxuICAgIHRoaXMucGFyZW50ID0gdW5kZWZpbmVkXG4gIH1cblxuICAvLyBDb21tb24gY2FzZS5cbiAgaWYgKHR5cGVvZiBhcmcgPT09ICdudW1iZXInKSB7XG4gICAgcmV0dXJuIGZyb21OdW1iZXIodGhpcywgYXJnKVxuICB9XG5cbiAgLy8gU2xpZ2h0bHkgbGVzcyBjb21tb24gY2FzZS5cbiAgaWYgKHR5cGVvZiBhcmcgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIGZyb21TdHJpbmcodGhpcywgYXJnLCBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6ICd1dGY4JylcbiAgfVxuXG4gIC8vIFVudXN1YWwuXG4gIHJldHVybiBmcm9tT2JqZWN0KHRoaXMsIGFyZylcbn1cblxuZnVuY3Rpb24gZnJvbU51bWJlciAodGhhdCwgbGVuZ3RoKSB7XG4gIHRoYXQgPSBhbGxvY2F0ZSh0aGF0LCBsZW5ndGggPCAwID8gMCA6IGNoZWNrZWQobGVuZ3RoKSB8IDApXG4gIGlmICghQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICB0aGF0W2ldID0gMFxuICAgIH1cbiAgfVxuICByZXR1cm4gdGhhdFxufVxuXG5mdW5jdGlvbiBmcm9tU3RyaW5nICh0aGF0LCBzdHJpbmcsIGVuY29kaW5nKSB7XG4gIGlmICh0eXBlb2YgZW5jb2RpbmcgIT09ICdzdHJpbmcnIHx8IGVuY29kaW5nID09PSAnJykgZW5jb2RpbmcgPSAndXRmOCdcblxuICAvLyBBc3N1bXB0aW9uOiBieXRlTGVuZ3RoKCkgcmV0dXJuIHZhbHVlIGlzIGFsd2F5cyA8IGtNYXhMZW5ndGguXG4gIHZhciBsZW5ndGggPSBieXRlTGVuZ3RoKHN0cmluZywgZW5jb2RpbmcpIHwgMFxuICB0aGF0ID0gYWxsb2NhdGUodGhhdCwgbGVuZ3RoKVxuXG4gIHRoYXQud3JpdGUoc3RyaW5nLCBlbmNvZGluZylcbiAgcmV0dXJuIHRoYXRcbn1cblxuZnVuY3Rpb24gZnJvbU9iamVjdCAodGhhdCwgb2JqZWN0KSB7XG4gIGlmIChCdWZmZXIuaXNCdWZmZXIob2JqZWN0KSkgcmV0dXJuIGZyb21CdWZmZXIodGhhdCwgb2JqZWN0KVxuXG4gIGlmIChpc0FycmF5KG9iamVjdCkpIHJldHVybiBmcm9tQXJyYXkodGhhdCwgb2JqZWN0KVxuXG4gIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ211c3Qgc3RhcnQgd2l0aCBudW1iZXIsIGJ1ZmZlciwgYXJyYXkgb3Igc3RyaW5nJylcbiAgfVxuXG4gIGlmICh0eXBlb2YgQXJyYXlCdWZmZXIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgaWYgKG9iamVjdC5idWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikge1xuICAgICAgcmV0dXJuIGZyb21UeXBlZEFycmF5KHRoYXQsIG9iamVjdClcbiAgICB9XG4gICAgaWYgKG9iamVjdCBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB7XG4gICAgICByZXR1cm4gZnJvbUFycmF5QnVmZmVyKHRoYXQsIG9iamVjdClcbiAgICB9XG4gIH1cblxuICBpZiAob2JqZWN0Lmxlbmd0aCkgcmV0dXJuIGZyb21BcnJheUxpa2UodGhhdCwgb2JqZWN0KVxuXG4gIHJldHVybiBmcm9tSnNvbk9iamVjdCh0aGF0LCBvYmplY3QpXG59XG5cbmZ1bmN0aW9uIGZyb21CdWZmZXIgKHRoYXQsIGJ1ZmZlcikge1xuICB2YXIgbGVuZ3RoID0gY2hlY2tlZChidWZmZXIubGVuZ3RoKSB8IDBcbiAgdGhhdCA9IGFsbG9jYXRlKHRoYXQsIGxlbmd0aClcbiAgYnVmZmVyLmNvcHkodGhhdCwgMCwgMCwgbGVuZ3RoKVxuICByZXR1cm4gdGhhdFxufVxuXG5mdW5jdGlvbiBmcm9tQXJyYXkgKHRoYXQsIGFycmF5KSB7XG4gIHZhciBsZW5ndGggPSBjaGVja2VkKGFycmF5Lmxlbmd0aCkgfCAwXG4gIHRoYXQgPSBhbGxvY2F0ZSh0aGF0LCBsZW5ndGgpXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDEpIHtcbiAgICB0aGF0W2ldID0gYXJyYXlbaV0gJiAyNTVcbiAgfVxuICByZXR1cm4gdGhhdFxufVxuXG4vLyBEdXBsaWNhdGUgb2YgZnJvbUFycmF5KCkgdG8ga2VlcCBmcm9tQXJyYXkoKSBtb25vbW9ycGhpYy5cbmZ1bmN0aW9uIGZyb21UeXBlZEFycmF5ICh0aGF0LCBhcnJheSkge1xuICB2YXIgbGVuZ3RoID0gY2hlY2tlZChhcnJheS5sZW5ndGgpIHwgMFxuICB0aGF0ID0gYWxsb2NhdGUodGhhdCwgbGVuZ3RoKVxuICAvLyBUcnVuY2F0aW5nIHRoZSBlbGVtZW50cyBpcyBwcm9iYWJseSBub3Qgd2hhdCBwZW9wbGUgZXhwZWN0IGZyb20gdHlwZWRcbiAgLy8gYXJyYXlzIHdpdGggQllURVNfUEVSX0VMRU1FTlQgPiAxIGJ1dCBpdCdzIGNvbXBhdGlibGUgd2l0aCB0aGUgYmVoYXZpb3JcbiAgLy8gb2YgdGhlIG9sZCBCdWZmZXIgY29uc3RydWN0b3IuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDEpIHtcbiAgICB0aGF0W2ldID0gYXJyYXlbaV0gJiAyNTVcbiAgfVxuICByZXR1cm4gdGhhdFxufVxuXG5mdW5jdGlvbiBmcm9tQXJyYXlCdWZmZXIgKHRoYXQsIGFycmF5KSB7XG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIC8vIFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlLCBmb3IgYmVzdCBwZXJmb3JtYW5jZVxuICAgIGFycmF5LmJ5dGVMZW5ndGhcbiAgICB0aGF0ID0gQnVmZmVyLl9hdWdtZW50KG5ldyBVaW50OEFycmF5KGFycmF5KSlcbiAgfSBlbHNlIHtcbiAgICAvLyBGYWxsYmFjazogUmV0dXJuIGFuIG9iamVjdCBpbnN0YW5jZSBvZiB0aGUgQnVmZmVyIGNsYXNzXG4gICAgdGhhdCA9IGZyb21UeXBlZEFycmF5KHRoYXQsIG5ldyBVaW50OEFycmF5KGFycmF5KSlcbiAgfVxuICByZXR1cm4gdGhhdFxufVxuXG5mdW5jdGlvbiBmcm9tQXJyYXlMaWtlICh0aGF0LCBhcnJheSkge1xuICB2YXIgbGVuZ3RoID0gY2hlY2tlZChhcnJheS5sZW5ndGgpIHwgMFxuICB0aGF0ID0gYWxsb2NhdGUodGhhdCwgbGVuZ3RoKVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgdGhhdFtpXSA9IGFycmF5W2ldICYgMjU1XG4gIH1cbiAgcmV0dXJuIHRoYXRcbn1cblxuLy8gRGVzZXJpYWxpemUgeyB0eXBlOiAnQnVmZmVyJywgZGF0YTogWzEsMiwzLC4uLl0gfSBpbnRvIGEgQnVmZmVyIG9iamVjdC5cbi8vIFJldHVybnMgYSB6ZXJvLWxlbmd0aCBidWZmZXIgZm9yIGlucHV0cyB0aGF0IGRvbid0IGNvbmZvcm0gdG8gdGhlIHNwZWMuXG5mdW5jdGlvbiBmcm9tSnNvbk9iamVjdCAodGhhdCwgb2JqZWN0KSB7XG4gIHZhciBhcnJheVxuICB2YXIgbGVuZ3RoID0gMFxuXG4gIGlmIChvYmplY3QudHlwZSA9PT0gJ0J1ZmZlcicgJiYgaXNBcnJheShvYmplY3QuZGF0YSkpIHtcbiAgICBhcnJheSA9IG9iamVjdC5kYXRhXG4gICAgbGVuZ3RoID0gY2hlY2tlZChhcnJheS5sZW5ndGgpIHwgMFxuICB9XG4gIHRoYXQgPSBhbGxvY2F0ZSh0aGF0LCBsZW5ndGgpXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgIHRoYXRbaV0gPSBhcnJheVtpXSAmIDI1NVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbmlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICBCdWZmZXIucHJvdG90eXBlLl9fcHJvdG9fXyA9IFVpbnQ4QXJyYXkucHJvdG90eXBlXG4gIEJ1ZmZlci5fX3Byb3RvX18gPSBVaW50OEFycmF5XG59IGVsc2Uge1xuICAvLyBwcmUtc2V0IGZvciB2YWx1ZXMgdGhhdCBtYXkgZXhpc3QgaW4gdGhlIGZ1dHVyZVxuICBCdWZmZXIucHJvdG90eXBlLmxlbmd0aCA9IHVuZGVmaW5lZFxuICBCdWZmZXIucHJvdG90eXBlLnBhcmVudCA9IHVuZGVmaW5lZFxufVxuXG5mdW5jdGlvbiBhbGxvY2F0ZSAodGhhdCwgbGVuZ3RoKSB7XG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIC8vIFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlLCBmb3IgYmVzdCBwZXJmb3JtYW5jZVxuICAgIHRoYXQgPSBCdWZmZXIuX2F1Z21lbnQobmV3IFVpbnQ4QXJyYXkobGVuZ3RoKSlcbiAgICB0aGF0Ll9fcHJvdG9fXyA9IEJ1ZmZlci5wcm90b3R5cGVcbiAgfSBlbHNlIHtcbiAgICAvLyBGYWxsYmFjazogUmV0dXJuIGFuIG9iamVjdCBpbnN0YW5jZSBvZiB0aGUgQnVmZmVyIGNsYXNzXG4gICAgdGhhdC5sZW5ndGggPSBsZW5ndGhcbiAgICB0aGF0Ll9pc0J1ZmZlciA9IHRydWVcbiAgfVxuXG4gIHZhciBmcm9tUG9vbCA9IGxlbmd0aCAhPT0gMCAmJiBsZW5ndGggPD0gQnVmZmVyLnBvb2xTaXplID4+PiAxXG4gIGlmIChmcm9tUG9vbCkgdGhhdC5wYXJlbnQgPSByb290UGFyZW50XG5cbiAgcmV0dXJuIHRoYXRcbn1cblxuZnVuY3Rpb24gY2hlY2tlZCAobGVuZ3RoKSB7XG4gIC8vIE5vdGU6IGNhbm5vdCB1c2UgYGxlbmd0aCA8IGtNYXhMZW5ndGhgIGhlcmUgYmVjYXVzZSB0aGF0IGZhaWxzIHdoZW5cbiAgLy8gbGVuZ3RoIGlzIE5hTiAod2hpY2ggaXMgb3RoZXJ3aXNlIGNvZXJjZWQgdG8gemVyby4pXG4gIGlmIChsZW5ndGggPj0ga01heExlbmd0aCgpKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0F0dGVtcHQgdG8gYWxsb2NhdGUgQnVmZmVyIGxhcmdlciB0aGFuIG1heGltdW0gJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgJ3NpemU6IDB4JyArIGtNYXhMZW5ndGgoKS50b1N0cmluZygxNikgKyAnIGJ5dGVzJylcbiAgfVxuICByZXR1cm4gbGVuZ3RoIHwgMFxufVxuXG5mdW5jdGlvbiBTbG93QnVmZmVyIChzdWJqZWN0LCBlbmNvZGluZykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU2xvd0J1ZmZlcikpIHJldHVybiBuZXcgU2xvd0J1ZmZlcihzdWJqZWN0LCBlbmNvZGluZylcblxuICB2YXIgYnVmID0gbmV3IEJ1ZmZlcihzdWJqZWN0LCBlbmNvZGluZylcbiAgZGVsZXRlIGJ1Zi5wYXJlbnRcbiAgcmV0dXJuIGJ1ZlxufVxuXG5CdWZmZXIuaXNCdWZmZXIgPSBmdW5jdGlvbiBpc0J1ZmZlciAoYikge1xuICByZXR1cm4gISEoYiAhPSBudWxsICYmIGIuX2lzQnVmZmVyKVxufVxuXG5CdWZmZXIuY29tcGFyZSA9IGZ1bmN0aW9uIGNvbXBhcmUgKGEsIGIpIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYSkgfHwgIUJ1ZmZlci5pc0J1ZmZlcihiKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50cyBtdXN0IGJlIEJ1ZmZlcnMnKVxuICB9XG5cbiAgaWYgKGEgPT09IGIpIHJldHVybiAwXG5cbiAgdmFyIHggPSBhLmxlbmd0aFxuICB2YXIgeSA9IGIubGVuZ3RoXG5cbiAgdmFyIGkgPSAwXG4gIHZhciBsZW4gPSBNYXRoLm1pbih4LCB5KVxuICB3aGlsZSAoaSA8IGxlbikge1xuICAgIGlmIChhW2ldICE9PSBiW2ldKSBicmVha1xuXG4gICAgKytpXG4gIH1cblxuICBpZiAoaSAhPT0gbGVuKSB7XG4gICAgeCA9IGFbaV1cbiAgICB5ID0gYltpXVxuICB9XG5cbiAgaWYgKHggPCB5KSByZXR1cm4gLTFcbiAgaWYgKHkgPCB4KSByZXR1cm4gMVxuICByZXR1cm4gMFxufVxuXG5CdWZmZXIuaXNFbmNvZGluZyA9IGZ1bmN0aW9uIGlzRW5jb2RpbmcgKGVuY29kaW5nKSB7XG4gIHN3aXRjaCAoU3RyaW5nKGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpKSB7XG4gICAgY2FzZSAnaGV4JzpcbiAgICBjYXNlICd1dGY4JzpcbiAgICBjYXNlICd1dGYtOCc6XG4gICAgY2FzZSAnYXNjaWknOlxuICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgY2FzZSAnYmFzZTY0JzpcbiAgICBjYXNlICdyYXcnOlxuICAgIGNhc2UgJ3VjczInOlxuICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICBjYXNlICd1dGYxNmxlJzpcbiAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuXG5CdWZmZXIuY29uY2F0ID0gZnVuY3Rpb24gY29uY2F0IChsaXN0LCBsZW5ndGgpIHtcbiAgaWYgKCFpc0FycmF5KGxpc3QpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdsaXN0IGFyZ3VtZW50IG11c3QgYmUgYW4gQXJyYXkgb2YgQnVmZmVycy4nKVxuXG4gIGlmIChsaXN0Lmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBuZXcgQnVmZmVyKDApXG4gIH1cblxuICB2YXIgaVxuICBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQpIHtcbiAgICBsZW5ndGggPSAwXG4gICAgZm9yIChpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxlbmd0aCArPSBsaXN0W2ldLmxlbmd0aFxuICAgIH1cbiAgfVxuXG4gIHZhciBidWYgPSBuZXcgQnVmZmVyKGxlbmd0aClcbiAgdmFyIHBvcyA9IDBcbiAgZm9yIChpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgaXRlbSA9IGxpc3RbaV1cbiAgICBpdGVtLmNvcHkoYnVmLCBwb3MpXG4gICAgcG9zICs9IGl0ZW0ubGVuZ3RoXG4gIH1cbiAgcmV0dXJuIGJ1ZlxufVxuXG5mdW5jdGlvbiBieXRlTGVuZ3RoIChzdHJpbmcsIGVuY29kaW5nKSB7XG4gIGlmICh0eXBlb2Ygc3RyaW5nICE9PSAnc3RyaW5nJykgc3RyaW5nID0gJycgKyBzdHJpbmdcblxuICB2YXIgbGVuID0gc3RyaW5nLmxlbmd0aFxuICBpZiAobGVuID09PSAwKSByZXR1cm4gMFxuXG4gIC8vIFVzZSBhIGZvciBsb29wIHRvIGF2b2lkIHJlY3Vyc2lvblxuICB2YXIgbG93ZXJlZENhc2UgPSBmYWxzZVxuICBmb3IgKDs7KSB7XG4gICAgc3dpdGNoIChlbmNvZGluZykge1xuICAgICAgY2FzZSAnYXNjaWknOlxuICAgICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgIC8vIERlcHJlY2F0ZWRcbiAgICAgIGNhc2UgJ3Jhdyc6XG4gICAgICBjYXNlICdyYXdzJzpcbiAgICAgICAgcmV0dXJuIGxlblxuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICAgIHJldHVybiB1dGY4VG9CeXRlcyhzdHJpbmcpLmxlbmd0aFxuICAgICAgY2FzZSAndWNzMic6XG4gICAgICBjYXNlICd1Y3MtMic6XG4gICAgICBjYXNlICd1dGYxNmxlJzpcbiAgICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgICAgcmV0dXJuIGxlbiAqIDJcbiAgICAgIGNhc2UgJ2hleCc6XG4gICAgICAgIHJldHVybiBsZW4gPj4+IDFcbiAgICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICAgIHJldHVybiBiYXNlNjRUb0J5dGVzKHN0cmluZykubGVuZ3RoXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBpZiAobG93ZXJlZENhc2UpIHJldHVybiB1dGY4VG9CeXRlcyhzdHJpbmcpLmxlbmd0aCAvLyBhc3N1bWUgdXRmOFxuICAgICAgICBlbmNvZGluZyA9ICgnJyArIGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpXG4gICAgICAgIGxvd2VyZWRDYXNlID0gdHJ1ZVxuICAgIH1cbiAgfVxufVxuQnVmZmVyLmJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoXG5cbmZ1bmN0aW9uIHNsb3dUb1N0cmluZyAoZW5jb2RpbmcsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGxvd2VyZWRDYXNlID0gZmFsc2VcblxuICBzdGFydCA9IHN0YXJ0IHwgMFxuICBlbmQgPSBlbmQgPT09IHVuZGVmaW5lZCB8fCBlbmQgPT09IEluZmluaXR5ID8gdGhpcy5sZW5ndGggOiBlbmQgfCAwXG5cbiAgaWYgKCFlbmNvZGluZykgZW5jb2RpbmcgPSAndXRmOCdcbiAgaWYgKHN0YXJ0IDwgMCkgc3RhcnQgPSAwXG4gIGlmIChlbmQgPiB0aGlzLmxlbmd0aCkgZW5kID0gdGhpcy5sZW5ndGhcbiAgaWYgKGVuZCA8PSBzdGFydCkgcmV0dXJuICcnXG5cbiAgd2hpbGUgKHRydWUpIHtcbiAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gaGV4U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICAgIHJldHVybiB1dGY4U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnYXNjaWknOlxuICAgICAgICByZXR1cm4gYXNjaWlTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgICByZXR1cm4gYmluYXJ5U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgICAgcmV0dXJuIGJhc2U2NFNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiB1dGYxNmxlU2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpXG4gICAgICAgIGVuY29kaW5nID0gKGVuY29kaW5nICsgJycpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgbG93ZXJlZENhc2UgPSB0cnVlXG4gICAgfVxuICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZyAoKSB7XG4gIHZhciBsZW5ndGggPSB0aGlzLmxlbmd0aCB8IDBcbiAgaWYgKGxlbmd0aCA9PT0gMCkgcmV0dXJuICcnXG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSByZXR1cm4gdXRmOFNsaWNlKHRoaXMsIDAsIGxlbmd0aClcbiAgcmV0dXJuIHNsb3dUb1N0cmluZy5hcHBseSh0aGlzLCBhcmd1bWVudHMpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuZXF1YWxzID0gZnVuY3Rpb24gZXF1YWxzIChiKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudCBtdXN0IGJlIGEgQnVmZmVyJylcbiAgaWYgKHRoaXMgPT09IGIpIHJldHVybiB0cnVlXG4gIHJldHVybiBCdWZmZXIuY29tcGFyZSh0aGlzLCBiKSA9PT0gMFxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluc3BlY3QgPSBmdW5jdGlvbiBpbnNwZWN0ICgpIHtcbiAgdmFyIHN0ciA9ICcnXG4gIHZhciBtYXggPSBleHBvcnRzLklOU1BFQ1RfTUFYX0JZVEVTXG4gIGlmICh0aGlzLmxlbmd0aCA+IDApIHtcbiAgICBzdHIgPSB0aGlzLnRvU3RyaW5nKCdoZXgnLCAwLCBtYXgpLm1hdGNoKC8uezJ9L2cpLmpvaW4oJyAnKVxuICAgIGlmICh0aGlzLmxlbmd0aCA+IG1heCkgc3RyICs9ICcgLi4uICdcbiAgfVxuICByZXR1cm4gJzxCdWZmZXIgJyArIHN0ciArICc+J1xufVxuXG5CdWZmZXIucHJvdG90eXBlLmNvbXBhcmUgPSBmdW5jdGlvbiBjb21wYXJlIChiKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudCBtdXN0IGJlIGEgQnVmZmVyJylcbiAgaWYgKHRoaXMgPT09IGIpIHJldHVybiAwXG4gIHJldHVybiBCdWZmZXIuY29tcGFyZSh0aGlzLCBiKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluZGV4T2YgPSBmdW5jdGlvbiBpbmRleE9mICh2YWwsIGJ5dGVPZmZzZXQpIHtcbiAgaWYgKGJ5dGVPZmZzZXQgPiAweDdmZmZmZmZmKSBieXRlT2Zmc2V0ID0gMHg3ZmZmZmZmZlxuICBlbHNlIGlmIChieXRlT2Zmc2V0IDwgLTB4ODAwMDAwMDApIGJ5dGVPZmZzZXQgPSAtMHg4MDAwMDAwMFxuICBieXRlT2Zmc2V0ID4+PSAwXG5cbiAgaWYgKHRoaXMubGVuZ3RoID09PSAwKSByZXR1cm4gLTFcbiAgaWYgKGJ5dGVPZmZzZXQgPj0gdGhpcy5sZW5ndGgpIHJldHVybiAtMVxuXG4gIC8vIE5lZ2F0aXZlIG9mZnNldHMgc3RhcnQgZnJvbSB0aGUgZW5kIG9mIHRoZSBidWZmZXJcbiAgaWYgKGJ5dGVPZmZzZXQgPCAwKSBieXRlT2Zmc2V0ID0gTWF0aC5tYXgodGhpcy5sZW5ndGggKyBieXRlT2Zmc2V0LCAwKVxuXG4gIGlmICh0eXBlb2YgdmFsID09PSAnc3RyaW5nJykge1xuICAgIGlmICh2YWwubGVuZ3RoID09PSAwKSByZXR1cm4gLTEgLy8gc3BlY2lhbCBjYXNlOiBsb29raW5nIGZvciBlbXB0eSBzdHJpbmcgYWx3YXlzIGZhaWxzXG4gICAgcmV0dXJuIFN0cmluZy5wcm90b3R5cGUuaW5kZXhPZi5jYWxsKHRoaXMsIHZhbCwgYnl0ZU9mZnNldClcbiAgfVxuICBpZiAoQnVmZmVyLmlzQnVmZmVyKHZhbCkpIHtcbiAgICByZXR1cm4gYXJyYXlJbmRleE9mKHRoaXMsIHZhbCwgYnl0ZU9mZnNldClcbiAgfVxuICBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpIHtcbiAgICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQgJiYgVWludDhBcnJheS5wcm90b3R5cGUuaW5kZXhPZiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmV0dXJuIFVpbnQ4QXJyYXkucHJvdG90eXBlLmluZGV4T2YuY2FsbCh0aGlzLCB2YWwsIGJ5dGVPZmZzZXQpXG4gICAgfVxuICAgIHJldHVybiBhcnJheUluZGV4T2YodGhpcywgWyB2YWwgXSwgYnl0ZU9mZnNldClcbiAgfVxuXG4gIGZ1bmN0aW9uIGFycmF5SW5kZXhPZiAoYXJyLCB2YWwsIGJ5dGVPZmZzZXQpIHtcbiAgICB2YXIgZm91bmRJbmRleCA9IC0xXG4gICAgZm9yICh2YXIgaSA9IDA7IGJ5dGVPZmZzZXQgKyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoYXJyW2J5dGVPZmZzZXQgKyBpXSA9PT0gdmFsW2ZvdW5kSW5kZXggPT09IC0xID8gMCA6IGkgLSBmb3VuZEluZGV4XSkge1xuICAgICAgICBpZiAoZm91bmRJbmRleCA9PT0gLTEpIGZvdW5kSW5kZXggPSBpXG4gICAgICAgIGlmIChpIC0gZm91bmRJbmRleCArIDEgPT09IHZhbC5sZW5ndGgpIHJldHVybiBieXRlT2Zmc2V0ICsgZm91bmRJbmRleFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZm91bmRJbmRleCA9IC0xXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiAtMVxuICB9XG5cbiAgdGhyb3cgbmV3IFR5cGVFcnJvcigndmFsIG11c3QgYmUgc3RyaW5nLCBudW1iZXIgb3IgQnVmZmVyJylcbn1cblxuLy8gYGdldGAgaXMgZGVwcmVjYXRlZFxuQnVmZmVyLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiBnZXQgKG9mZnNldCkge1xuICBjb25zb2xlLmxvZygnLmdldCgpIGlzIGRlcHJlY2F0ZWQuIEFjY2VzcyB1c2luZyBhcnJheSBpbmRleGVzIGluc3RlYWQuJylcbiAgcmV0dXJuIHRoaXMucmVhZFVJbnQ4KG9mZnNldClcbn1cblxuLy8gYHNldGAgaXMgZGVwcmVjYXRlZFxuQnVmZmVyLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbiBzZXQgKHYsIG9mZnNldCkge1xuICBjb25zb2xlLmxvZygnLnNldCgpIGlzIGRlcHJlY2F0ZWQuIEFjY2VzcyB1c2luZyBhcnJheSBpbmRleGVzIGluc3RlYWQuJylcbiAgcmV0dXJuIHRoaXMud3JpdGVVSW50OCh2LCBvZmZzZXQpXG59XG5cbmZ1bmN0aW9uIGhleFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgb2Zmc2V0ID0gTnVtYmVyKG9mZnNldCkgfHwgMFxuICB2YXIgcmVtYWluaW5nID0gYnVmLmxlbmd0aCAtIG9mZnNldFxuICBpZiAoIWxlbmd0aCkge1xuICAgIGxlbmd0aCA9IHJlbWFpbmluZ1xuICB9IGVsc2Uge1xuICAgIGxlbmd0aCA9IE51bWJlcihsZW5ndGgpXG4gICAgaWYgKGxlbmd0aCA+IHJlbWFpbmluZykge1xuICAgICAgbGVuZ3RoID0gcmVtYWluaW5nXG4gICAgfVxuICB9XG5cbiAgLy8gbXVzdCBiZSBhbiBldmVuIG51bWJlciBvZiBkaWdpdHNcbiAgdmFyIHN0ckxlbiA9IHN0cmluZy5sZW5ndGhcbiAgaWYgKHN0ckxlbiAlIDIgIT09IDApIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBoZXggc3RyaW5nJylcblxuICBpZiAobGVuZ3RoID4gc3RyTGVuIC8gMikge1xuICAgIGxlbmd0aCA9IHN0ckxlbiAvIDJcbiAgfVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHBhcnNlZCA9IHBhcnNlSW50KHN0cmluZy5zdWJzdHIoaSAqIDIsIDIpLCAxNilcbiAgICBpZiAoaXNOYU4ocGFyc2VkKSkgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGhleCBzdHJpbmcnKVxuICAgIGJ1ZltvZmZzZXQgKyBpXSA9IHBhcnNlZFxuICB9XG4gIHJldHVybiBpXG59XG5cbmZ1bmN0aW9uIHV0ZjhXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKHV0ZjhUb0J5dGVzKHN0cmluZywgYnVmLmxlbmd0aCAtIG9mZnNldCksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIGFzY2lpV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcihhc2NpaVRvQnl0ZXMoc3RyaW5nKSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gYmluYXJ5V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYXNjaWlXcml0ZShidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIGJhc2U2NFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIoYmFzZTY0VG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiB1Y3MyV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcih1dGYxNmxlVG9CeXRlcyhzdHJpbmcsIGJ1Zi5sZW5ndGggLSBvZmZzZXQpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlID0gZnVuY3Rpb24gd3JpdGUgKHN0cmluZywgb2Zmc2V0LCBsZW5ndGgsIGVuY29kaW5nKSB7XG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcpXG4gIGlmIChvZmZzZXQgPT09IHVuZGVmaW5lZCkge1xuICAgIGVuY29kaW5nID0gJ3V0ZjgnXG4gICAgbGVuZ3RoID0gdGhpcy5sZW5ndGhcbiAgICBvZmZzZXQgPSAwXG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcsIGVuY29kaW5nKVxuICB9IGVsc2UgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkICYmIHR5cGVvZiBvZmZzZXQgPT09ICdzdHJpbmcnKSB7XG4gICAgZW5jb2RpbmcgPSBvZmZzZXRcbiAgICBsZW5ndGggPSB0aGlzLmxlbmd0aFxuICAgIG9mZnNldCA9IDBcbiAgLy8gQnVmZmVyI3dyaXRlKHN0cmluZywgb2Zmc2V0WywgbGVuZ3RoXVssIGVuY29kaW5nXSlcbiAgfSBlbHNlIGlmIChpc0Zpbml0ZShvZmZzZXQpKSB7XG4gICAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICAgIGlmIChpc0Zpbml0ZShsZW5ndGgpKSB7XG4gICAgICBsZW5ndGggPSBsZW5ndGggfCAwXG4gICAgICBpZiAoZW5jb2RpbmcgPT09IHVuZGVmaW5lZCkgZW5jb2RpbmcgPSAndXRmOCdcbiAgICB9IGVsc2Uge1xuICAgICAgZW5jb2RpbmcgPSBsZW5ndGhcbiAgICAgIGxlbmd0aCA9IHVuZGVmaW5lZFxuICAgIH1cbiAgLy8gbGVnYWN5IHdyaXRlKHN0cmluZywgZW5jb2RpbmcsIG9mZnNldCwgbGVuZ3RoKSAtIHJlbW92ZSBpbiB2MC4xM1xuICB9IGVsc2Uge1xuICAgIHZhciBzd2FwID0gZW5jb2RpbmdcbiAgICBlbmNvZGluZyA9IG9mZnNldFxuICAgIG9mZnNldCA9IGxlbmd0aCB8IDBcbiAgICBsZW5ndGggPSBzd2FwXG4gIH1cblxuICB2YXIgcmVtYWluaW5nID0gdGhpcy5sZW5ndGggLSBvZmZzZXRcbiAgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkIHx8IGxlbmd0aCA+IHJlbWFpbmluZykgbGVuZ3RoID0gcmVtYWluaW5nXG5cbiAgaWYgKChzdHJpbmcubGVuZ3RoID4gMCAmJiAobGVuZ3RoIDwgMCB8fCBvZmZzZXQgPCAwKSkgfHwgb2Zmc2V0ID4gdGhpcy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignYXR0ZW1wdCB0byB3cml0ZSBvdXRzaWRlIGJ1ZmZlciBib3VuZHMnKVxuICB9XG5cbiAgaWYgKCFlbmNvZGluZykgZW5jb2RpbmcgPSAndXRmOCdcblxuICB2YXIgbG93ZXJlZENhc2UgPSBmYWxzZVxuICBmb3IgKDs7KSB7XG4gICAgc3dpdGNoIChlbmNvZGluZykge1xuICAgICAgY2FzZSAnaGV4JzpcbiAgICAgICAgcmV0dXJuIGhleFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgY2FzZSAndXRmLTgnOlxuICAgICAgICByZXR1cm4gdXRmOFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ2FzY2lpJzpcbiAgICAgICAgcmV0dXJuIGFzY2lpV3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgICAgcmV0dXJuIGJpbmFyeVdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICAgIC8vIFdhcm5pbmc6IG1heExlbmd0aCBub3QgdGFrZW4gaW50byBhY2NvdW50IGluIGJhc2U2NFdyaXRlXG4gICAgICAgIHJldHVybiBiYXNlNjRXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICd1Y3MyJzpcbiAgICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgICByZXR1cm4gdWNzMldyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChsb3dlcmVkQ2FzZSkgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBlbmNvZGluZzogJyArIGVuY29kaW5nKVxuICAgICAgICBlbmNvZGluZyA9ICgnJyArIGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpXG4gICAgICAgIGxvd2VyZWRDYXNlID0gdHJ1ZVxuICAgIH1cbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uIHRvSlNPTiAoKSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogJ0J1ZmZlcicsXG4gICAgZGF0YTogQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwodGhpcy5fYXJyIHx8IHRoaXMsIDApXG4gIH1cbn1cblxuZnVuY3Rpb24gYmFzZTY0U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICBpZiAoc3RhcnQgPT09IDAgJiYgZW5kID09PSBidWYubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGJhc2U2NC5mcm9tQnl0ZUFycmF5KGJ1ZilcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYmFzZTY0LmZyb21CeXRlQXJyYXkoYnVmLnNsaWNlKHN0YXJ0LCBlbmQpKVxuICB9XG59XG5cbmZ1bmN0aW9uIHV0ZjhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcbiAgdmFyIHJlcyA9IFtdXG5cbiAgdmFyIGkgPSBzdGFydFxuICB3aGlsZSAoaSA8IGVuZCkge1xuICAgIHZhciBmaXJzdEJ5dGUgPSBidWZbaV1cbiAgICB2YXIgY29kZVBvaW50ID0gbnVsbFxuICAgIHZhciBieXRlc1BlclNlcXVlbmNlID0gKGZpcnN0Qnl0ZSA+IDB4RUYpID8gNFxuICAgICAgOiAoZmlyc3RCeXRlID4gMHhERikgPyAzXG4gICAgICA6IChmaXJzdEJ5dGUgPiAweEJGKSA/IDJcbiAgICAgIDogMVxuXG4gICAgaWYgKGkgKyBieXRlc1BlclNlcXVlbmNlIDw9IGVuZCkge1xuICAgICAgdmFyIHNlY29uZEJ5dGUsIHRoaXJkQnl0ZSwgZm91cnRoQnl0ZSwgdGVtcENvZGVQb2ludFxuXG4gICAgICBzd2l0Y2ggKGJ5dGVzUGVyU2VxdWVuY2UpIHtcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgIGlmIChmaXJzdEJ5dGUgPCAweDgwKSB7XG4gICAgICAgICAgICBjb2RlUG9pbnQgPSBmaXJzdEJ5dGVcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgaWYgKChzZWNvbmRCeXRlICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgICAgIHRlbXBDb2RlUG9pbnQgPSAoZmlyc3RCeXRlICYgMHgxRikgPDwgMHg2IHwgKHNlY29uZEJ5dGUgJiAweDNGKVxuICAgICAgICAgICAgaWYgKHRlbXBDb2RlUG9pbnQgPiAweDdGKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgdGhpcmRCeXRlID0gYnVmW2kgKyAyXVxuICAgICAgICAgIGlmICgoc2Vjb25kQnl0ZSAmIDB4QzApID09PSAweDgwICYmICh0aGlyZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCkge1xuICAgICAgICAgICAgdGVtcENvZGVQb2ludCA9IChmaXJzdEJ5dGUgJiAweEYpIDw8IDB4QyB8IChzZWNvbmRCeXRlICYgMHgzRikgPDwgMHg2IHwgKHRoaXJkQnl0ZSAmIDB4M0YpXG4gICAgICAgICAgICBpZiAodGVtcENvZGVQb2ludCA+IDB4N0ZGICYmICh0ZW1wQ29kZVBvaW50IDwgMHhEODAwIHx8IHRlbXBDb2RlUG9pbnQgPiAweERGRkYpKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgdGhpcmRCeXRlID0gYnVmW2kgKyAyXVxuICAgICAgICAgIGZvdXJ0aEJ5dGUgPSBidWZbaSArIDNdXG4gICAgICAgICAgaWYgKChzZWNvbmRCeXRlICYgMHhDMCkgPT09IDB4ODAgJiYgKHRoaXJkQnl0ZSAmIDB4QzApID09PSAweDgwICYmIChmb3VydGhCeXRlICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgICAgIHRlbXBDb2RlUG9pbnQgPSAoZmlyc3RCeXRlICYgMHhGKSA8PCAweDEyIHwgKHNlY29uZEJ5dGUgJiAweDNGKSA8PCAweEMgfCAodGhpcmRCeXRlICYgMHgzRikgPDwgMHg2IHwgKGZvdXJ0aEJ5dGUgJiAweDNGKVxuICAgICAgICAgICAgaWYgKHRlbXBDb2RlUG9pbnQgPiAweEZGRkYgJiYgdGVtcENvZGVQb2ludCA8IDB4MTEwMDAwKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNvZGVQb2ludCA9PT0gbnVsbCkge1xuICAgICAgLy8gd2UgZGlkIG5vdCBnZW5lcmF0ZSBhIHZhbGlkIGNvZGVQb2ludCBzbyBpbnNlcnQgYVxuICAgICAgLy8gcmVwbGFjZW1lbnQgY2hhciAoVStGRkZEKSBhbmQgYWR2YW5jZSBvbmx5IDEgYnl0ZVxuICAgICAgY29kZVBvaW50ID0gMHhGRkZEXG4gICAgICBieXRlc1BlclNlcXVlbmNlID0gMVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50ID4gMHhGRkZGKSB7XG4gICAgICAvLyBlbmNvZGUgdG8gdXRmMTYgKHN1cnJvZ2F0ZSBwYWlyIGRhbmNlKVxuICAgICAgY29kZVBvaW50IC09IDB4MTAwMDBcbiAgICAgIHJlcy5wdXNoKGNvZGVQb2ludCA+Pj4gMTAgJiAweDNGRiB8IDB4RDgwMClcbiAgICAgIGNvZGVQb2ludCA9IDB4REMwMCB8IGNvZGVQb2ludCAmIDB4M0ZGXG4gICAgfVxuXG4gICAgcmVzLnB1c2goY29kZVBvaW50KVxuICAgIGkgKz0gYnl0ZXNQZXJTZXF1ZW5jZVxuICB9XG5cbiAgcmV0dXJuIGRlY29kZUNvZGVQb2ludHNBcnJheShyZXMpXG59XG5cbi8vIEJhc2VkIG9uIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzIyNzQ3MjcyLzY4MDc0MiwgdGhlIGJyb3dzZXIgd2l0aFxuLy8gdGhlIGxvd2VzdCBsaW1pdCBpcyBDaHJvbWUsIHdpdGggMHgxMDAwMCBhcmdzLlxuLy8gV2UgZ28gMSBtYWduaXR1ZGUgbGVzcywgZm9yIHNhZmV0eVxudmFyIE1BWF9BUkdVTUVOVFNfTEVOR1RIID0gMHgxMDAwXG5cbmZ1bmN0aW9uIGRlY29kZUNvZGVQb2ludHNBcnJheSAoY29kZVBvaW50cykge1xuICB2YXIgbGVuID0gY29kZVBvaW50cy5sZW5ndGhcbiAgaWYgKGxlbiA8PSBNQVhfQVJHVU1FTlRTX0xFTkdUSCkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KFN0cmluZywgY29kZVBvaW50cykgLy8gYXZvaWQgZXh0cmEgc2xpY2UoKVxuICB9XG5cbiAgLy8gRGVjb2RlIGluIGNodW5rcyB0byBhdm9pZCBcImNhbGwgc3RhY2sgc2l6ZSBleGNlZWRlZFwiLlxuICB2YXIgcmVzID0gJydcbiAgdmFyIGkgPSAwXG4gIHdoaWxlIChpIDwgbGVuKSB7XG4gICAgcmVzICs9IFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoXG4gICAgICBTdHJpbmcsXG4gICAgICBjb2RlUG9pbnRzLnNsaWNlKGksIGkgKz0gTUFYX0FSR1VNRU5UU19MRU5HVEgpXG4gICAgKVxuICB9XG4gIHJldHVybiByZXNcbn1cblxuZnVuY3Rpb24gYXNjaWlTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciByZXQgPSAnJ1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG5cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICByZXQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShidWZbaV0gJiAweDdGKVxuICB9XG4gIHJldHVybiByZXRcbn1cblxuZnVuY3Rpb24gYmluYXJ5U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgcmV0ID0gJydcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgcmV0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYnVmW2ldKVxuICB9XG4gIHJldHVybiByZXRcbn1cblxuZnVuY3Rpb24gaGV4U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuXG4gIGlmICghc3RhcnQgfHwgc3RhcnQgPCAwKSBzdGFydCA9IDBcbiAgaWYgKCFlbmQgfHwgZW5kIDwgMCB8fCBlbmQgPiBsZW4pIGVuZCA9IGxlblxuXG4gIHZhciBvdXQgPSAnJ1xuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgIG91dCArPSB0b0hleChidWZbaV0pXG4gIH1cbiAgcmV0dXJuIG91dFxufVxuXG5mdW5jdGlvbiB1dGYxNmxlU2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgYnl0ZXMgPSBidWYuc2xpY2Uoc3RhcnQsIGVuZClcbiAgdmFyIHJlcyA9ICcnXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYnl0ZXMubGVuZ3RoOyBpICs9IDIpIHtcbiAgICByZXMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShieXRlc1tpXSArIGJ5dGVzW2kgKyAxXSAqIDI1NilcbiAgfVxuICByZXR1cm4gcmVzXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuc2xpY2UgPSBmdW5jdGlvbiBzbGljZSAoc3RhcnQsIGVuZCkge1xuICB2YXIgbGVuID0gdGhpcy5sZW5ndGhcbiAgc3RhcnQgPSB+fnN0YXJ0XG4gIGVuZCA9IGVuZCA9PT0gdW5kZWZpbmVkID8gbGVuIDogfn5lbmRcblxuICBpZiAoc3RhcnQgPCAwKSB7XG4gICAgc3RhcnQgKz0gbGVuXG4gICAgaWYgKHN0YXJ0IDwgMCkgc3RhcnQgPSAwXG4gIH0gZWxzZSBpZiAoc3RhcnQgPiBsZW4pIHtcbiAgICBzdGFydCA9IGxlblxuICB9XG5cbiAgaWYgKGVuZCA8IDApIHtcbiAgICBlbmQgKz0gbGVuXG4gICAgaWYgKGVuZCA8IDApIGVuZCA9IDBcbiAgfSBlbHNlIGlmIChlbmQgPiBsZW4pIHtcbiAgICBlbmQgPSBsZW5cbiAgfVxuXG4gIGlmIChlbmQgPCBzdGFydCkgZW5kID0gc3RhcnRcblxuICB2YXIgbmV3QnVmXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIG5ld0J1ZiA9IEJ1ZmZlci5fYXVnbWVudCh0aGlzLnN1YmFycmF5KHN0YXJ0LCBlbmQpKVxuICB9IGVsc2Uge1xuICAgIHZhciBzbGljZUxlbiA9IGVuZCAtIHN0YXJ0XG4gICAgbmV3QnVmID0gbmV3IEJ1ZmZlcihzbGljZUxlbiwgdW5kZWZpbmVkKVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2xpY2VMZW47IGkrKykge1xuICAgICAgbmV3QnVmW2ldID0gdGhpc1tpICsgc3RhcnRdXG4gICAgfVxuICB9XG5cbiAgaWYgKG5ld0J1Zi5sZW5ndGgpIG5ld0J1Zi5wYXJlbnQgPSB0aGlzLnBhcmVudCB8fCB0aGlzXG5cbiAgcmV0dXJuIG5ld0J1ZlxufVxuXG4vKlxuICogTmVlZCB0byBtYWtlIHN1cmUgdGhhdCBidWZmZXIgaXNuJ3QgdHJ5aW5nIHRvIHdyaXRlIG91dCBvZiBib3VuZHMuXG4gKi9cbmZ1bmN0aW9uIGNoZWNrT2Zmc2V0IChvZmZzZXQsIGV4dCwgbGVuZ3RoKSB7XG4gIGlmICgob2Zmc2V0ICUgMSkgIT09IDAgfHwgb2Zmc2V0IDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ29mZnNldCBpcyBub3QgdWludCcpXG4gIGlmIChvZmZzZXQgKyBleHQgPiBsZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdUcnlpbmcgdG8gYWNjZXNzIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludExFID0gZnVuY3Rpb24gcmVhZFVJbnRMRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoIHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIGJ5dGVMZW5ndGgsIHRoaXMubGVuZ3RoKVxuXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldF1cbiAgdmFyIG11bCA9IDFcbiAgdmFyIGkgPSAwXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgaV0gKiBtdWxcbiAgfVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludEJFID0gZnVuY3Rpb24gcmVhZFVJbnRCRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoIHwgMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcbiAgfVxuXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldCArIC0tYnl0ZUxlbmd0aF1cbiAgdmFyIG11bCA9IDFcbiAgd2hpbGUgKGJ5dGVMZW5ndGggPiAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgLS1ieXRlTGVuZ3RoXSAqIG11bFxuICB9XG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50OCA9IGZ1bmN0aW9uIHJlYWRVSW50OCAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDEsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gdGhpc1tvZmZzZXRdXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQxNkxFID0gZnVuY3Rpb24gcmVhZFVJbnQxNkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiB0aGlzW29mZnNldF0gfCAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MTZCRSA9IGZ1bmN0aW9uIHJlYWRVSW50MTZCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSA8PCA4KSB8IHRoaXNbb2Zmc2V0ICsgMV1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDMyTEUgPSBmdW5jdGlvbiByZWFkVUludDMyTEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKCh0aGlzW29mZnNldF0pIHxcbiAgICAgICh0aGlzW29mZnNldCArIDFdIDw8IDgpIHxcbiAgICAgICh0aGlzW29mZnNldCArIDJdIDw8IDE2KSkgK1xuICAgICAgKHRoaXNbb2Zmc2V0ICsgM10gKiAweDEwMDAwMDApXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQzMkJFID0gZnVuY3Rpb24gcmVhZFVJbnQzMkJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICh0aGlzW29mZnNldF0gKiAweDEwMDAwMDApICtcbiAgICAoKHRoaXNbb2Zmc2V0ICsgMV0gPDwgMTYpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCA4KSB8XG4gICAgdGhpc1tvZmZzZXQgKyAzXSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50TEUgPSBmdW5jdGlvbiByZWFkSW50TEUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXRdXG4gIHZhciBtdWwgPSAxXG4gIHZhciBpID0gMFxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHZhbCArPSB0aGlzW29mZnNldCArIGldICogbXVsXG4gIH1cbiAgbXVsICo9IDB4ODBcblxuICBpZiAodmFsID49IG11bCkgdmFsIC09IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50QkUgPSBmdW5jdGlvbiByZWFkSW50QkUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICB2YXIgaSA9IGJ5dGVMZW5ndGhcbiAgdmFyIG11bCA9IDFcbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0ICsgLS1pXVxuICB3aGlsZSAoaSA+IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyAtLWldICogbXVsXG4gIH1cbiAgbXVsICo9IDB4ODBcblxuICBpZiAodmFsID49IG11bCkgdmFsIC09IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50OCA9IGZ1bmN0aW9uIHJlYWRJbnQ4IChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMSwgdGhpcy5sZW5ndGgpXG4gIGlmICghKHRoaXNbb2Zmc2V0XSAmIDB4ODApKSByZXR1cm4gKHRoaXNbb2Zmc2V0XSlcbiAgcmV0dXJuICgoMHhmZiAtIHRoaXNbb2Zmc2V0XSArIDEpICogLTEpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDE2TEUgPSBmdW5jdGlvbiByZWFkSW50MTZMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXRdIHwgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOClcbiAgcmV0dXJuICh2YWwgJiAweDgwMDApID8gdmFsIHwgMHhGRkZGMDAwMCA6IHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQxNkJFID0gZnVuY3Rpb24gcmVhZEludDE2QkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0ICsgMV0gfCAodGhpc1tvZmZzZXRdIDw8IDgpXG4gIHJldHVybiAodmFsICYgMHg4MDAwKSA/IHZhbCB8IDB4RkZGRjAwMDAgOiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MzJMRSA9IGZ1bmN0aW9uIHJlYWRJbnQzMkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICh0aGlzW29mZnNldF0pIHxcbiAgICAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgMTYpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAzXSA8PCAyNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MzJCRSA9IGZ1bmN0aW9uIHJlYWRJbnQzMkJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICh0aGlzW29mZnNldF0gPDwgMjQpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAxXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDJdIDw8IDgpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAzXSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRmxvYXRMRSA9IGZ1bmN0aW9uIHJlYWRGbG9hdExFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCB0cnVlLCAyMywgNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRmxvYXRCRSA9IGZ1bmN0aW9uIHJlYWRGbG9hdEJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCBmYWxzZSwgMjMsIDQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZERvdWJsZUxFID0gZnVuY3Rpb24gcmVhZERvdWJsZUxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgOCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCB0cnVlLCA1MiwgOClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRG91YmxlQkUgPSBmdW5jdGlvbiByZWFkRG91YmxlQkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA4LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIGZhbHNlLCA1MiwgOClcbn1cblxuZnVuY3Rpb24gY2hlY2tJbnQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgZXh0LCBtYXgsIG1pbikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihidWYpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdidWZmZXIgbXVzdCBiZSBhIEJ1ZmZlciBpbnN0YW5jZScpXG4gIGlmICh2YWx1ZSA+IG1heCB8fCB2YWx1ZSA8IG1pbikgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3ZhbHVlIGlzIG91dCBvZiBib3VuZHMnKVxuICBpZiAob2Zmc2V0ICsgZXh0ID4gYnVmLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2luZGV4IG91dCBvZiByYW5nZScpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50TEUgPSBmdW5jdGlvbiB3cml0ZVVJbnRMRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpLCAwKVxuXG4gIHZhciBtdWwgPSAxXG4gIHZhciBpID0gMFxuICB0aGlzW29mZnNldF0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB0aGlzW29mZnNldCArIGldID0gKHZhbHVlIC8gbXVsKSAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50QkUgPSBmdW5jdGlvbiB3cml0ZVVJbnRCRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpLCAwKVxuXG4gIHZhciBpID0gYnl0ZUxlbmd0aCAtIDFcbiAgdmFyIG11bCA9IDFcbiAgdGhpc1tvZmZzZXQgKyBpXSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoLS1pID49IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB0aGlzW29mZnNldCArIGldID0gKHZhbHVlIC8gbXVsKSAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50OCA9IGZ1bmN0aW9uIHdyaXRlVUludDggKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMSwgMHhmZiwgMClcbiAgaWYgKCFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkgdmFsdWUgPSBNYXRoLmZsb29yKHZhbHVlKVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICByZXR1cm4gb2Zmc2V0ICsgMVxufVxuXG5mdW5jdGlvbiBvYmplY3RXcml0ZVVJbnQxNiAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4pIHtcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmZmYgKyB2YWx1ZSArIDFcbiAgZm9yICh2YXIgaSA9IDAsIGogPSBNYXRoLm1pbihidWYubGVuZ3RoIC0gb2Zmc2V0LCAyKTsgaSA8IGo7IGkrKykge1xuICAgIGJ1ZltvZmZzZXQgKyBpXSA9ICh2YWx1ZSAmICgweGZmIDw8ICg4ICogKGxpdHRsZUVuZGlhbiA/IGkgOiAxIC0gaSkpKSkgPj4+XG4gICAgICAobGl0dGxlRW5kaWFuID8gaSA6IDEgLSBpKSAqIDhcbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDE2TEUgPSBmdW5jdGlvbiB3cml0ZVVJbnQxNkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4ZmZmZiwgMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQxNkJFID0gZnVuY3Rpb24gd3JpdGVVSW50MTZCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweGZmZmYsIDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlICYgMHhmZilcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5mdW5jdGlvbiBvYmplY3RXcml0ZVVJbnQzMiAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4pIHtcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmZmZmZmZmICsgdmFsdWUgKyAxXG4gIGZvciAodmFyIGkgPSAwLCBqID0gTWF0aC5taW4oYnVmLmxlbmd0aCAtIG9mZnNldCwgNCk7IGkgPCBqOyBpKyspIHtcbiAgICBidWZbb2Zmc2V0ICsgaV0gPSAodmFsdWUgPj4+IChsaXR0bGVFbmRpYW4gPyBpIDogMyAtIGkpICogOCkgJiAweGZmXG4gIH1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkxFID0gZnVuY3Rpb24gd3JpdGVVSW50MzJMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweGZmZmZmZmZmLCAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlID4+PiAyNClcbiAgICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiAxNilcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MzIodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDMyQkUgPSBmdW5jdGlvbiB3cml0ZVVJbnQzMkJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4ZmZmZmZmZmYsIDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gMjQpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gICAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlICYgMHhmZilcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50TEUgPSBmdW5jdGlvbiB3cml0ZUludExFICh2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICB2YXIgbGltaXQgPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCAtIDEpXG5cbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBsaW1pdCAtIDEsIC1saW1pdClcbiAgfVxuXG4gIHZhciBpID0gMFxuICB2YXIgbXVsID0gMVxuICB2YXIgc3ViID0gdmFsdWUgPCAwID8gMSA6IDBcbiAgdGhpc1tvZmZzZXRdID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICgodmFsdWUgLyBtdWwpID4+IDApIC0gc3ViICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludEJFID0gZnVuY3Rpb24gd3JpdGVJbnRCRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgdmFyIGxpbWl0ID0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGggLSAxKVxuXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbGltaXQgLSAxLCAtbGltaXQpXG4gIH1cblxuICB2YXIgaSA9IGJ5dGVMZW5ndGggLSAxXG4gIHZhciBtdWwgPSAxXG4gIHZhciBzdWIgPSB2YWx1ZSA8IDAgPyAxIDogMFxuICB0aGlzW29mZnNldCArIGldID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgtLWkgPj0gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAoKHZhbHVlIC8gbXVsKSA+PiAwKSAtIHN1YiAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQ4ID0gZnVuY3Rpb24gd3JpdGVJbnQ4ICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDEsIDB4N2YsIC0weDgwKVxuICBpZiAoIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB2YWx1ZSA9IE1hdGguZmxvb3IodmFsdWUpXG4gIGlmICh2YWx1ZSA8IDApIHZhbHVlID0gMHhmZiArIHZhbHVlICsgMVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICByZXR1cm4gb2Zmc2V0ICsgMVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MTZMRSA9IGZ1bmN0aW9uIHdyaXRlSW50MTZMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweDdmZmYsIC0weDgwMDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQxNkJFID0gZnVuY3Rpb24gd3JpdGVJbnQxNkJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4N2ZmZiwgLTB4ODAwMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgJiAweGZmKVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQzMkxFID0gZnVuY3Rpb24gd3JpdGVJbnQzMkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4N2ZmZmZmZmYsIC0weDgwMDAwMDAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gICAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSA+Pj4gMjQpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MzIodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MzJCRSA9IGZ1bmN0aW9uIHdyaXRlSW50MzJCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweDdmZmZmZmZmLCAtMHg4MDAwMDAwMClcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmZmZmZmZmICsgdmFsdWUgKyAxXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gMjQpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gICAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlICYgMHhmZilcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5mdW5jdGlvbiBjaGVja0lFRUU3NTQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgZXh0LCBtYXgsIG1pbikge1xuICBpZiAodmFsdWUgPiBtYXggfHwgdmFsdWUgPCBtaW4pIHRocm93IG5ldyBSYW5nZUVycm9yKCd2YWx1ZSBpcyBvdXQgb2YgYm91bmRzJylcbiAgaWYgKG9mZnNldCArIGV4dCA+IGJ1Zi5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdpbmRleCBvdXQgb2YgcmFuZ2UnKVxuICBpZiAob2Zmc2V0IDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2luZGV4IG91dCBvZiByYW5nZScpXG59XG5cbmZ1bmN0aW9uIHdyaXRlRmxvYXQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tJRUVFNzU0KGJ1ZiwgdmFsdWUsIG9mZnNldCwgNCwgMy40MDI4MjM0NjYzODUyODg2ZSszOCwgLTMuNDAyODIzNDY2Mzg1Mjg4NmUrMzgpXG4gIH1cbiAgaWVlZTc1NC53cml0ZShidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgMjMsIDQpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVGbG9hdExFID0gZnVuY3Rpb24gd3JpdGVGbG9hdExFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVGbG9hdCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0QkUgPSBmdW5jdGlvbiB3cml0ZUZsb2F0QkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZUZsb2F0KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gd3JpdGVEb3VibGUgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tJRUVFNzU0KGJ1ZiwgdmFsdWUsIG9mZnNldCwgOCwgMS43OTc2OTMxMzQ4NjIzMTU3RSszMDgsIC0xLjc5NzY5MzEzNDg2MjMxNTdFKzMwOClcbiAgfVxuICBpZWVlNzU0LndyaXRlKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCA1MiwgOClcbiAgcmV0dXJuIG9mZnNldCArIDhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZURvdWJsZUxFID0gZnVuY3Rpb24gd3JpdGVEb3VibGVMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRG91YmxlKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRG91YmxlQkUgPSBmdW5jdGlvbiB3cml0ZURvdWJsZUJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVEb3VibGUodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG4vLyBjb3B5KHRhcmdldEJ1ZmZlciwgdGFyZ2V0U3RhcnQ9MCwgc291cmNlU3RhcnQ9MCwgc291cmNlRW5kPWJ1ZmZlci5sZW5ndGgpXG5CdWZmZXIucHJvdG90eXBlLmNvcHkgPSBmdW5jdGlvbiBjb3B5ICh0YXJnZXQsIHRhcmdldFN0YXJ0LCBzdGFydCwgZW5kKSB7XG4gIGlmICghc3RhcnQpIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCAmJiBlbmQgIT09IDApIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmICh0YXJnZXRTdGFydCA+PSB0YXJnZXQubGVuZ3RoKSB0YXJnZXRTdGFydCA9IHRhcmdldC5sZW5ndGhcbiAgaWYgKCF0YXJnZXRTdGFydCkgdGFyZ2V0U3RhcnQgPSAwXG4gIGlmIChlbmQgPiAwICYmIGVuZCA8IHN0YXJ0KSBlbmQgPSBzdGFydFxuXG4gIC8vIENvcHkgMCBieXRlczsgd2UncmUgZG9uZVxuICBpZiAoZW5kID09PSBzdGFydCkgcmV0dXJuIDBcbiAgaWYgKHRhcmdldC5sZW5ndGggPT09IDAgfHwgdGhpcy5sZW5ndGggPT09IDApIHJldHVybiAwXG5cbiAgLy8gRmF0YWwgZXJyb3IgY29uZGl0aW9uc1xuICBpZiAodGFyZ2V0U3RhcnQgPCAwKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3RhcmdldFN0YXJ0IG91dCBvZiBib3VuZHMnKVxuICB9XG4gIGlmIChzdGFydCA8IDAgfHwgc3RhcnQgPj0gdGhpcy5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdzb3VyY2VTdGFydCBvdXQgb2YgYm91bmRzJylcbiAgaWYgKGVuZCA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdzb3VyY2VFbmQgb3V0IG9mIGJvdW5kcycpXG5cbiAgLy8gQXJlIHdlIG9vYj9cbiAgaWYgKGVuZCA+IHRoaXMubGVuZ3RoKSBlbmQgPSB0aGlzLmxlbmd0aFxuICBpZiAodGFyZ2V0Lmxlbmd0aCAtIHRhcmdldFN0YXJ0IDwgZW5kIC0gc3RhcnQpIHtcbiAgICBlbmQgPSB0YXJnZXQubGVuZ3RoIC0gdGFyZ2V0U3RhcnQgKyBzdGFydFxuICB9XG5cbiAgdmFyIGxlbiA9IGVuZCAtIHN0YXJ0XG4gIHZhciBpXG5cbiAgaWYgKHRoaXMgPT09IHRhcmdldCAmJiBzdGFydCA8IHRhcmdldFN0YXJ0ICYmIHRhcmdldFN0YXJ0IDwgZW5kKSB7XG4gICAgLy8gZGVzY2VuZGluZyBjb3B5IGZyb20gZW5kXG4gICAgZm9yIChpID0gbGVuIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIHRhcmdldFtpICsgdGFyZ2V0U3RhcnRdID0gdGhpc1tpICsgc3RhcnRdXG4gICAgfVxuICB9IGVsc2UgaWYgKGxlbiA8IDEwMDAgfHwgIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgLy8gYXNjZW5kaW5nIGNvcHkgZnJvbSBzdGFydFxuICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgdGFyZ2V0W2kgKyB0YXJnZXRTdGFydF0gPSB0aGlzW2kgKyBzdGFydF1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGFyZ2V0Ll9zZXQodGhpcy5zdWJhcnJheShzdGFydCwgc3RhcnQgKyBsZW4pLCB0YXJnZXRTdGFydClcbiAgfVxuXG4gIHJldHVybiBsZW5cbn1cblxuLy8gZmlsbCh2YWx1ZSwgc3RhcnQ9MCwgZW5kPWJ1ZmZlci5sZW5ndGgpXG5CdWZmZXIucHJvdG90eXBlLmZpbGwgPSBmdW5jdGlvbiBmaWxsICh2YWx1ZSwgc3RhcnQsIGVuZCkge1xuICBpZiAoIXZhbHVlKSB2YWx1ZSA9IDBcbiAgaWYgKCFzdGFydCkgc3RhcnQgPSAwXG4gIGlmICghZW5kKSBlbmQgPSB0aGlzLmxlbmd0aFxuXG4gIGlmIChlbmQgPCBzdGFydCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2VuZCA8IHN0YXJ0JylcblxuICAvLyBGaWxsIDAgYnl0ZXM7IHdlJ3JlIGRvbmVcbiAgaWYgKGVuZCA9PT0gc3RhcnQpIHJldHVyblxuICBpZiAodGhpcy5sZW5ndGggPT09IDApIHJldHVyblxuXG4gIGlmIChzdGFydCA8IDAgfHwgc3RhcnQgPj0gdGhpcy5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdzdGFydCBvdXQgb2YgYm91bmRzJylcbiAgaWYgKGVuZCA8IDAgfHwgZW5kID4gdGhpcy5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdlbmQgb3V0IG9mIGJvdW5kcycpXG5cbiAgdmFyIGlcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICBmb3IgKGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICB0aGlzW2ldID0gdmFsdWVcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdmFyIGJ5dGVzID0gdXRmOFRvQnl0ZXModmFsdWUudG9TdHJpbmcoKSlcbiAgICB2YXIgbGVuID0gYnl0ZXMubGVuZ3RoXG4gICAgZm9yIChpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgICAgdGhpc1tpXSA9IGJ5dGVzW2kgJSBsZW5dXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoaXNcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGBBcnJheUJ1ZmZlcmAgd2l0aCB0aGUgKmNvcGllZCogbWVtb3J5IG9mIHRoZSBidWZmZXIgaW5zdGFuY2UuXG4gKiBBZGRlZCBpbiBOb2RlIDAuMTIuIE9ubHkgYXZhaWxhYmxlIGluIGJyb3dzZXJzIHRoYXQgc3VwcG9ydCBBcnJheUJ1ZmZlci5cbiAqL1xuQnVmZmVyLnByb3RvdHlwZS50b0FycmF5QnVmZmVyID0gZnVuY3Rpb24gdG9BcnJheUJ1ZmZlciAoKSB7XG4gIGlmICh0eXBlb2YgVWludDhBcnJheSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICAgIHJldHVybiAobmV3IEJ1ZmZlcih0aGlzKSkuYnVmZmVyXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBidWYgPSBuZXcgVWludDhBcnJheSh0aGlzLmxlbmd0aClcbiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBidWYubGVuZ3RoOyBpIDwgbGVuOyBpICs9IDEpIHtcbiAgICAgICAgYnVmW2ldID0gdGhpc1tpXVxuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1Zi5idWZmZXJcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQnVmZmVyLnRvQXJyYXlCdWZmZXIgbm90IHN1cHBvcnRlZCBpbiB0aGlzIGJyb3dzZXInKVxuICB9XG59XG5cbi8vIEhFTFBFUiBGVU5DVElPTlNcbi8vID09PT09PT09PT09PT09PT1cblxudmFyIEJQID0gQnVmZmVyLnByb3RvdHlwZVxuXG4vKipcbiAqIEF1Z21lbnQgYSBVaW50OEFycmF5ICppbnN0YW5jZSogKG5vdCB0aGUgVWludDhBcnJheSBjbGFzcyEpIHdpdGggQnVmZmVyIG1ldGhvZHNcbiAqL1xuQnVmZmVyLl9hdWdtZW50ID0gZnVuY3Rpb24gX2F1Z21lbnQgKGFycikge1xuICBhcnIuY29uc3RydWN0b3IgPSBCdWZmZXJcbiAgYXJyLl9pc0J1ZmZlciA9IHRydWVcblxuICAvLyBzYXZlIHJlZmVyZW5jZSB0byBvcmlnaW5hbCBVaW50OEFycmF5IHNldCBtZXRob2QgYmVmb3JlIG92ZXJ3cml0aW5nXG4gIGFyci5fc2V0ID0gYXJyLnNldFxuXG4gIC8vIGRlcHJlY2F0ZWRcbiAgYXJyLmdldCA9IEJQLmdldFxuICBhcnIuc2V0ID0gQlAuc2V0XG5cbiAgYXJyLndyaXRlID0gQlAud3JpdGVcbiAgYXJyLnRvU3RyaW5nID0gQlAudG9TdHJpbmdcbiAgYXJyLnRvTG9jYWxlU3RyaW5nID0gQlAudG9TdHJpbmdcbiAgYXJyLnRvSlNPTiA9IEJQLnRvSlNPTlxuICBhcnIuZXF1YWxzID0gQlAuZXF1YWxzXG4gIGFyci5jb21wYXJlID0gQlAuY29tcGFyZVxuICBhcnIuaW5kZXhPZiA9IEJQLmluZGV4T2ZcbiAgYXJyLmNvcHkgPSBCUC5jb3B5XG4gIGFyci5zbGljZSA9IEJQLnNsaWNlXG4gIGFyci5yZWFkVUludExFID0gQlAucmVhZFVJbnRMRVxuICBhcnIucmVhZFVJbnRCRSA9IEJQLnJlYWRVSW50QkVcbiAgYXJyLnJlYWRVSW50OCA9IEJQLnJlYWRVSW50OFxuICBhcnIucmVhZFVJbnQxNkxFID0gQlAucmVhZFVJbnQxNkxFXG4gIGFyci5yZWFkVUludDE2QkUgPSBCUC5yZWFkVUludDE2QkVcbiAgYXJyLnJlYWRVSW50MzJMRSA9IEJQLnJlYWRVSW50MzJMRVxuICBhcnIucmVhZFVJbnQzMkJFID0gQlAucmVhZFVJbnQzMkJFXG4gIGFyci5yZWFkSW50TEUgPSBCUC5yZWFkSW50TEVcbiAgYXJyLnJlYWRJbnRCRSA9IEJQLnJlYWRJbnRCRVxuICBhcnIucmVhZEludDggPSBCUC5yZWFkSW50OFxuICBhcnIucmVhZEludDE2TEUgPSBCUC5yZWFkSW50MTZMRVxuICBhcnIucmVhZEludDE2QkUgPSBCUC5yZWFkSW50MTZCRVxuICBhcnIucmVhZEludDMyTEUgPSBCUC5yZWFkSW50MzJMRVxuICBhcnIucmVhZEludDMyQkUgPSBCUC5yZWFkSW50MzJCRVxuICBhcnIucmVhZEZsb2F0TEUgPSBCUC5yZWFkRmxvYXRMRVxuICBhcnIucmVhZEZsb2F0QkUgPSBCUC5yZWFkRmxvYXRCRVxuICBhcnIucmVhZERvdWJsZUxFID0gQlAucmVhZERvdWJsZUxFXG4gIGFyci5yZWFkRG91YmxlQkUgPSBCUC5yZWFkRG91YmxlQkVcbiAgYXJyLndyaXRlVUludDggPSBCUC53cml0ZVVJbnQ4XG4gIGFyci53cml0ZVVJbnRMRSA9IEJQLndyaXRlVUludExFXG4gIGFyci53cml0ZVVJbnRCRSA9IEJQLndyaXRlVUludEJFXG4gIGFyci53cml0ZVVJbnQxNkxFID0gQlAud3JpdGVVSW50MTZMRVxuICBhcnIud3JpdGVVSW50MTZCRSA9IEJQLndyaXRlVUludDE2QkVcbiAgYXJyLndyaXRlVUludDMyTEUgPSBCUC53cml0ZVVJbnQzMkxFXG4gIGFyci53cml0ZVVJbnQzMkJFID0gQlAud3JpdGVVSW50MzJCRVxuICBhcnIud3JpdGVJbnRMRSA9IEJQLndyaXRlSW50TEVcbiAgYXJyLndyaXRlSW50QkUgPSBCUC53cml0ZUludEJFXG4gIGFyci53cml0ZUludDggPSBCUC53cml0ZUludDhcbiAgYXJyLndyaXRlSW50MTZMRSA9IEJQLndyaXRlSW50MTZMRVxuICBhcnIud3JpdGVJbnQxNkJFID0gQlAud3JpdGVJbnQxNkJFXG4gIGFyci53cml0ZUludDMyTEUgPSBCUC53cml0ZUludDMyTEVcbiAgYXJyLndyaXRlSW50MzJCRSA9IEJQLndyaXRlSW50MzJCRVxuICBhcnIud3JpdGVGbG9hdExFID0gQlAud3JpdGVGbG9hdExFXG4gIGFyci53cml0ZUZsb2F0QkUgPSBCUC53cml0ZUZsb2F0QkVcbiAgYXJyLndyaXRlRG91YmxlTEUgPSBCUC53cml0ZURvdWJsZUxFXG4gIGFyci53cml0ZURvdWJsZUJFID0gQlAud3JpdGVEb3VibGVCRVxuICBhcnIuZmlsbCA9IEJQLmZpbGxcbiAgYXJyLmluc3BlY3QgPSBCUC5pbnNwZWN0XG4gIGFyci50b0FycmF5QnVmZmVyID0gQlAudG9BcnJheUJ1ZmZlclxuXG4gIHJldHVybiBhcnJcbn1cblxudmFyIElOVkFMSURfQkFTRTY0X1JFID0gL1teK1xcLzAtOUEtWmEtei1fXS9nXG5cbmZ1bmN0aW9uIGJhc2U2NGNsZWFuIChzdHIpIHtcbiAgLy8gTm9kZSBzdHJpcHMgb3V0IGludmFsaWQgY2hhcmFjdGVycyBsaWtlIFxcbiBhbmQgXFx0IGZyb20gdGhlIHN0cmluZywgYmFzZTY0LWpzIGRvZXMgbm90XG4gIHN0ciA9IHN0cmluZ3RyaW0oc3RyKS5yZXBsYWNlKElOVkFMSURfQkFTRTY0X1JFLCAnJylcbiAgLy8gTm9kZSBjb252ZXJ0cyBzdHJpbmdzIHdpdGggbGVuZ3RoIDwgMiB0byAnJ1xuICBpZiAoc3RyLmxlbmd0aCA8IDIpIHJldHVybiAnJ1xuICAvLyBOb2RlIGFsbG93cyBmb3Igbm9uLXBhZGRlZCBiYXNlNjQgc3RyaW5ncyAobWlzc2luZyB0cmFpbGluZyA9PT0pLCBiYXNlNjQtanMgZG9lcyBub3RcbiAgd2hpbGUgKHN0ci5sZW5ndGggJSA0ICE9PSAwKSB7XG4gICAgc3RyID0gc3RyICsgJz0nXG4gIH1cbiAgcmV0dXJuIHN0clxufVxuXG5mdW5jdGlvbiBzdHJpbmd0cmltIChzdHIpIHtcbiAgaWYgKHN0ci50cmltKSByZXR1cm4gc3RyLnRyaW0oKVxuICByZXR1cm4gc3RyLnJlcGxhY2UoL15cXHMrfFxccyskL2csICcnKVxufVxuXG5mdW5jdGlvbiB0b0hleCAobikge1xuICBpZiAobiA8IDE2KSByZXR1cm4gJzAnICsgbi50b1N0cmluZygxNilcbiAgcmV0dXJuIG4udG9TdHJpbmcoMTYpXG59XG5cbmZ1bmN0aW9uIHV0ZjhUb0J5dGVzIChzdHJpbmcsIHVuaXRzKSB7XG4gIHVuaXRzID0gdW5pdHMgfHwgSW5maW5pdHlcbiAgdmFyIGNvZGVQb2ludFxuICB2YXIgbGVuZ3RoID0gc3RyaW5nLmxlbmd0aFxuICB2YXIgbGVhZFN1cnJvZ2F0ZSA9IG51bGxcbiAgdmFyIGJ5dGVzID0gW11cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgY29kZVBvaW50ID0gc3RyaW5nLmNoYXJDb2RlQXQoaSlcblxuICAgIC8vIGlzIHN1cnJvZ2F0ZSBjb21wb25lbnRcbiAgICBpZiAoY29kZVBvaW50ID4gMHhEN0ZGICYmIGNvZGVQb2ludCA8IDB4RTAwMCkge1xuICAgICAgLy8gbGFzdCBjaGFyIHdhcyBhIGxlYWRcbiAgICAgIGlmICghbGVhZFN1cnJvZ2F0ZSkge1xuICAgICAgICAvLyBubyBsZWFkIHlldFxuICAgICAgICBpZiAoY29kZVBvaW50ID4gMHhEQkZGKSB7XG4gICAgICAgICAgLy8gdW5leHBlY3RlZCB0cmFpbFxuICAgICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH0gZWxzZSBpZiAoaSArIDEgPT09IGxlbmd0aCkge1xuICAgICAgICAgIC8vIHVucGFpcmVkIGxlYWRcbiAgICAgICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gdmFsaWQgbGVhZFxuICAgICAgICBsZWFkU3Vycm9nYXRlID0gY29kZVBvaW50XG5cbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgLy8gMiBsZWFkcyBpbiBhIHJvd1xuICAgICAgaWYgKGNvZGVQb2ludCA8IDB4REMwMCkge1xuICAgICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgICAgbGVhZFN1cnJvZ2F0ZSA9IGNvZGVQb2ludFxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICAvLyB2YWxpZCBzdXJyb2dhdGUgcGFpclxuICAgICAgY29kZVBvaW50ID0gKGxlYWRTdXJyb2dhdGUgLSAweEQ4MDAgPDwgMTAgfCBjb2RlUG9pbnQgLSAweERDMDApICsgMHgxMDAwMFxuICAgIH0gZWxzZSBpZiAobGVhZFN1cnJvZ2F0ZSkge1xuICAgICAgLy8gdmFsaWQgYm1wIGNoYXIsIGJ1dCBsYXN0IGNoYXIgd2FzIGEgbGVhZFxuICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgfVxuXG4gICAgbGVhZFN1cnJvZ2F0ZSA9IG51bGxcblxuICAgIC8vIGVuY29kZSB1dGY4XG4gICAgaWYgKGNvZGVQb2ludCA8IDB4ODApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gMSkgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChjb2RlUG9pbnQpXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDgwMCkge1xuICAgICAgaWYgKCh1bml0cyAtPSAyKSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHg2IHwgMHhDMCxcbiAgICAgICAgY29kZVBvaW50ICYgMHgzRiB8IDB4ODBcbiAgICAgIClcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA8IDB4MTAwMDApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gMykgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChcbiAgICAgICAgY29kZVBvaW50ID4+IDB4QyB8IDB4RTAsXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDYgJiAweDNGIHwgMHg4MCxcbiAgICAgICAgY29kZVBvaW50ICYgMHgzRiB8IDB4ODBcbiAgICAgIClcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA8IDB4MTEwMDAwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDQpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDEyIHwgMHhGMCxcbiAgICAgICAgY29kZVBvaW50ID4+IDB4QyAmIDB4M0YgfCAweDgwLFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHg2ICYgMHgzRiB8IDB4ODAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBjb2RlIHBvaW50JylcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYnl0ZXNcbn1cblxuZnVuY3Rpb24gYXNjaWlUb0J5dGVzIChzdHIpIHtcbiAgdmFyIGJ5dGVBcnJheSA9IFtdXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgLy8gTm9kZSdzIGNvZGUgc2VlbXMgdG8gYmUgZG9pbmcgdGhpcyBhbmQgbm90ICYgMHg3Ri4uXG4gICAgYnl0ZUFycmF5LnB1c2goc3RyLmNoYXJDb2RlQXQoaSkgJiAweEZGKVxuICB9XG4gIHJldHVybiBieXRlQXJyYXlcbn1cblxuZnVuY3Rpb24gdXRmMTZsZVRvQnl0ZXMgKHN0ciwgdW5pdHMpIHtcbiAgdmFyIGMsIGhpLCBsb1xuICB2YXIgYnl0ZUFycmF5ID0gW11cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoKHVuaXRzIC09IDIpIDwgMCkgYnJlYWtcblxuICAgIGMgPSBzdHIuY2hhckNvZGVBdChpKVxuICAgIGhpID0gYyA+PiA4XG4gICAgbG8gPSBjICUgMjU2XG4gICAgYnl0ZUFycmF5LnB1c2gobG8pXG4gICAgYnl0ZUFycmF5LnB1c2goaGkpXG4gIH1cblxuICByZXR1cm4gYnl0ZUFycmF5XG59XG5cbmZ1bmN0aW9uIGJhc2U2NFRvQnl0ZXMgKHN0cikge1xuICByZXR1cm4gYmFzZTY0LnRvQnl0ZUFycmF5KGJhc2U2NGNsZWFuKHN0cikpXG59XG5cbmZ1bmN0aW9uIGJsaXRCdWZmZXIgKHNyYywgZHN0LCBvZmZzZXQsIGxlbmd0aCkge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKChpICsgb2Zmc2V0ID49IGRzdC5sZW5ndGgpIHx8IChpID49IHNyYy5sZW5ndGgpKSBicmVha1xuICAgIGRzdFtpICsgb2Zmc2V0XSA9IHNyY1tpXVxuICB9XG4gIHJldHVybiBpXG59XG5cbn0pLmNhbGwodGhpcyx0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2NoYXJzZXQ6dXRmLTg7YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSWk0dUx5NHVMeTR1THk0dUwyaHZiV1V2WVdSdGFXNHZZbkp2ZDNObGNtbG1lUzFqWkc0dmJtOWtaVjl0YjJSMWJHVnpMMkp5YjNkelpYSnBabmt2Ym05a1pWOXRiMlIxYkdWekwySjFabVpsY2k5cGJtUmxlQzVxY3lKZExDSnVZVzFsY3lJNlcxMHNJbTFoY0hCcGJtZHpJam9pTzBGQlFVRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRWlMQ0ptYVd4bElqb2laMlZ1WlhKaGRHVmtMbXB6SWl3aWMyOTFjbU5sVW05dmRDSTZJaUlzSW5OdmRYSmpaWE5EYjI1MFpXNTBJanBiSWk4cUlWeHVJQ29nVkdobElHSjFabVpsY2lCdGIyUjFiR1VnWm5KdmJTQnViMlJsTG1wekxDQm1iM0lnZEdobElHSnliM2R6WlhJdVhHNGdLbHh1SUNvZ1FHRjFkR2h2Y2lBZ0lFWmxjbTl6Y3lCQlltOTFhMmhoWkdscVpXZ2dQR1psY205emMwQm1aWEp2YzNNdWIzSm5QaUE4YUhSMGNEb3ZMMlpsY205emN5NXZjbWMrWEc0Z0tpQkFiR2xqWlc1elpTQWdUVWxVWEc0Z0tpOWNiaThxSUdWemJHbHVkQzFrYVhOaFlteGxJRzV2TFhCeWIzUnZJQ292WEc1Y2JpZDFjMlVnYzNSeWFXTjBKMXh1WEc1MllYSWdZbUZ6WlRZMElEMGdjbVZ4ZFdseVpTZ25ZbUZ6WlRZMExXcHpKeWxjYm5aaGNpQnBaV1ZsTnpVMElEMGdjbVZ4ZFdseVpTZ25hV1ZsWlRjMU5DY3BYRzUyWVhJZ2FYTkJjbkpoZVNBOUlISmxjWFZwY21Vb0oybHpZWEp5WVhrbktWeHVYRzVsZUhCdmNuUnpMa0oxWm1abGNpQTlJRUoxWm1abGNseHVaWGh3YjNKMGN5NVRiRzkzUW5WbVptVnlJRDBnVTJ4dmQwSjFabVpsY2x4dVpYaHdiM0owY3k1SlRsTlFSVU5VWDAxQldGOUNXVlJGVXlBOUlEVXdYRzVDZFdabVpYSXVjRzl2YkZOcGVtVWdQU0E0TVRreUlDOHZJRzV2ZENCMWMyVmtJR0o1SUhSb2FYTWdhVzF3YkdWdFpXNTBZWFJwYjI1Y2JseHVkbUZ5SUhKdmIzUlFZWEpsYm5RZ1BTQjdmVnh1WEc0dktpcGNiaUFxSUVsbUlHQkNkV1ptWlhJdVZGbFFSVVJmUVZKU1FWbGZVMVZRVUU5U1ZHQTZYRzRnS2lBZ0lEMDlQU0IwY25WbElDQWdJRlZ6WlNCVmFXNTBPRUZ5Y21GNUlHbHRjR3hsYldWdWRHRjBhVzl1SUNobVlYTjBaWE4wS1Z4dUlDb2dJQ0E5UFQwZ1ptRnNjMlVnSUNCVmMyVWdUMkpxWldOMElHbHRjR3hsYldWdWRHRjBhVzl1SUNodGIzTjBJR052YlhCaGRHbGliR1VzSUdWMlpXNGdTVVUyS1Z4dUlDcGNiaUFxSUVKeWIzZHpaWEp6SUhSb1lYUWdjM1Z3Y0c5eWRDQjBlWEJsWkNCaGNuSmhlWE1nWVhKbElFbEZJREV3S3l3Z1JtbHlaV1p2ZUNBMEt5d2dRMmh5YjIxbElEY3JMQ0JUWVdaaGNta2dOUzR4S3l4Y2JpQXFJRTl3WlhKaElERXhMallyTENCcFQxTWdOQzR5S3k1Y2JpQXFYRzRnS2lCRWRXVWdkRzhnZG1GeWFXOTFjeUJpY205M2MyVnlJR0oxWjNNc0lITnZiV1YwYVcxbGN5QjBhR1VnVDJKcVpXTjBJR2x0Y0d4bGJXVnVkR0YwYVc5dUlIZHBiR3dnWW1VZ2RYTmxaQ0JsZG1WdVhHNGdLaUIzYUdWdUlIUm9aU0JpY205M2MyVnlJSE4xY0hCdmNuUnpJSFI1Y0dWa0lHRnljbUY1Y3k1Y2JpQXFYRzRnS2lCT2IzUmxPbHh1SUNwY2JpQXFJQ0FnTFNCR2FYSmxabTk0SURRdE1qa2diR0ZqYTNNZ2MzVndjRzl5ZENCbWIzSWdZV1JrYVc1bklHNWxkeUJ3Y205d1pYSjBhV1Z6SUhSdklHQlZhVzUwT0VGeWNtRjVZQ0JwYm5OMFlXNWpaWE1zWEc0Z0tpQWdJQ0FnVTJWbE9pQm9kSFJ3Y3pvdkwySjFaM3BwYkd4aExtMXZlbWxzYkdFdWIzSm5MM05vYjNkZlluVm5MbU5uYVQ5cFpEMDJPVFUwTXpndVhHNGdLbHh1SUNvZ0lDQXRJRk5oWm1GeWFTQTFMVGNnYkdGamEzTWdjM1Z3Y0c5eWRDQm1iM0lnWTJoaGJtZHBibWNnZEdobElHQlBZbXBsWTNRdWNISnZkRzkwZVhCbExtTnZibk4wY25WamRHOXlZQ0J3Y205d1pYSjBlVnh1SUNvZ0lDQWdJRzl1SUc5aWFtVmpkSE11WEc0Z0tseHVJQ29nSUNBdElFTm9jbTl0WlNBNUxURXdJR2x6SUcxcGMzTnBibWNnZEdobElHQlVlWEJsWkVGeWNtRjVMbkJ5YjNSdmRIbHdaUzV6ZFdKaGNuSmhlV0FnWm5WdVkzUnBiMjR1WEc0Z0tseHVJQ29nSUNBdElFbEZNVEFnYUdGeklHRWdZbkp2YTJWdUlHQlVlWEJsWkVGeWNtRjVMbkJ5YjNSdmRIbHdaUzV6ZFdKaGNuSmhlV0FnWm5WdVkzUnBiMjRnZDJocFkyZ2djbVYwZFhKdWN5QmhjbkpoZVhNZ2IyWmNiaUFxSUNBZ0lDQnBibU52Y25KbFkzUWdiR1Z1WjNSb0lHbHVJSE52YldVZ2MybDBkV0YwYVc5dWN5NWNibHh1SUNvZ1YyVWdaR1YwWldOMElIUm9aWE5sSUdKMVoyZDVJR0p5YjNkelpYSnpJR0Z1WkNCelpYUWdZRUoxWm1abGNpNVVXVkJGUkY5QlVsSkJXVjlUVlZCUVQxSlVZQ0IwYnlCZ1ptRnNjMlZnSUhOdklIUm9aWGxjYmlBcUlHZGxkQ0IwYUdVZ1QySnFaV04wSUdsdGNHeGxiV1Z1ZEdGMGFXOXVMQ0IzYUdsamFDQnBjeUJ6Ykc5M1pYSWdZblYwSUdKbGFHRjJaWE1nWTI5eWNtVmpkR3g1TGx4dUlDb3ZYRzVDZFdabVpYSXVWRmxRUlVSZlFWSlNRVmxmVTFWUVVFOVNWQ0E5SUdkc2IySmhiQzVVV1ZCRlJGOUJVbEpCV1Y5VFZWQlFUMUpVSUNFOVBTQjFibVJsWm1sdVpXUmNiaUFnUHlCbmJHOWlZV3d1VkZsUVJVUmZRVkpTUVZsZlUxVlFVRTlTVkZ4dUlDQTZJSFI1Y0dWa1FYSnlZWGxUZFhCd2IzSjBLQ2xjYmx4dVpuVnVZM1JwYjI0Z2RIbHdaV1JCY25KaGVWTjFjSEJ2Y25RZ0tDa2dlMXh1SUNCbWRXNWpkR2x2YmlCQ1lYSWdLQ2tnZTMxY2JpQWdkSEo1SUh0Y2JpQWdJQ0IyWVhJZ1lYSnlJRDBnYm1WM0lGVnBiblE0UVhKeVlYa29NU2xjYmlBZ0lDQmhjbkl1Wm05dklEMGdablZ1WTNScGIyNGdLQ2tnZXlCeVpYUjFjbTRnTkRJZ2ZWeHVJQ0FnSUdGeWNpNWpiMjV6ZEhKMVkzUnZjaUE5SUVKaGNseHVJQ0FnSUhKbGRIVnliaUJoY25JdVptOXZLQ2tnUFQwOUlEUXlJQ1ltSUM4dklIUjVjR1ZrSUdGeWNtRjVJR2x1YzNSaGJtTmxjeUJqWVc0Z1ltVWdZWFZuYldWdWRHVmtYRzRnSUNBZ0lDQWdJR0Z5Y2k1amIyNXpkSEoxWTNSdmNpQTlQVDBnUW1GeUlDWW1JQzh2SUdOdmJuTjBjblZqZEc5eUlHTmhiaUJpWlNCelpYUmNiaUFnSUNBZ0lDQWdkSGx3Wlc5bUlHRnljaTV6ZFdKaGNuSmhlU0E5UFQwZ0oyWjFibU4wYVc5dUp5QW1KaUF2THlCamFISnZiV1VnT1MweE1DQnNZV05ySUdCemRXSmhjbkpoZVdCY2JpQWdJQ0FnSUNBZ1lYSnlMbk4xWW1GeWNtRjVLREVzSURFcExtSjVkR1ZNWlc1bmRHZ2dQVDA5SURBZ0x5OGdhV1V4TUNCb1lYTWdZbkp2YTJWdUlHQnpkV0poY25KaGVXQmNiaUFnZlNCallYUmphQ0FvWlNrZ2UxeHVJQ0FnSUhKbGRIVnliaUJtWVd4elpWeHVJQ0I5WEc1OVhHNWNibVoxYm1OMGFXOXVJR3ROWVhoTVpXNW5kR2dnS0NrZ2UxeHVJQ0J5WlhSMWNtNGdRblZtWm1WeUxsUlpVRVZFWDBGU1VrRlpYMU5WVUZCUFVsUmNiaUFnSUNBL0lEQjROMlptWm1abVptWmNiaUFnSUNBNklEQjRNMlptWm1abVptWmNibjFjYmx4dUx5b3FYRzRnS2lCRGJHRnpjem9nUW5WbVptVnlYRzRnS2lBOVBUMDlQVDA5UFQwOVBUMDlYRzRnS2x4dUlDb2dWR2hsSUVKMVptWmxjaUJqYjI1emRISjFZM1J2Y2lCeVpYUjFjbTV6SUdsdWMzUmhibU5sY3lCdlppQmdWV2x1ZERoQmNuSmhlV0FnZEdoaGRDQmhjbVVnWVhWbmJXVnVkR1ZrWEc0Z0tpQjNhWFJvSUdaMWJtTjBhVzl1SUhCeWIzQmxjblJwWlhNZ1ptOXlJR0ZzYkNCMGFHVWdibTlrWlNCZ1FuVm1abVZ5WUNCQlVFa2dablZ1WTNScGIyNXpMaUJYWlNCMWMyVmNiaUFxSUdCVmFXNTBPRUZ5Y21GNVlDQnpieUIwYUdGMElITnhkV0Z5WlNCaWNtRmphMlYwSUc1dmRHRjBhVzl1SUhkdmNtdHpJR0Z6SUdWNGNHVmpkR1ZrSUMwdElHbDBJSEpsZEhWeWJuTmNiaUFxSUdFZ2MybHVaMnhsSUc5amRHVjBMbHh1SUNwY2JpQXFJRUo1SUdGMVoyMWxiblJwYm1jZ2RHaGxJR2x1YzNSaGJtTmxjeXdnZDJVZ1kyRnVJR0YyYjJsa0lHMXZaR2xtZVdsdVp5QjBhR1VnWUZWcGJuUTRRWEp5WVhsZ1hHNGdLaUJ3Y205MGIzUjVjR1V1WEc0Z0tpOWNibVoxYm1OMGFXOXVJRUoxWm1abGNpQW9ZWEpuS1NCN1hHNGdJR2xtSUNnaEtIUm9hWE1nYVc1emRHRnVZMlZ2WmlCQ2RXWm1aWElwS1NCN1hHNGdJQ0FnTHk4Z1FYWnZhV1FnWjI5cGJtY2dkR2h5YjNWbmFDQmhiaUJCY21kMWJXVnVkSE5CWkdGd2RHOXlWSEpoYlhCdmJHbHVaU0JwYmlCMGFHVWdZMjl0Ylc5dUlHTmhjMlV1WEc0Z0lDQWdhV1lnS0dGeVozVnRaVzUwY3k1c1pXNW5kR2dnUGlBeEtTQnlaWFIxY200Z2JtVjNJRUoxWm1abGNpaGhjbWNzSUdGeVozVnRaVzUwYzFzeFhTbGNiaUFnSUNCeVpYUjFjbTRnYm1WM0lFSjFabVpsY2loaGNtY3BYRzRnSUgxY2JseHVJQ0JwWmlBb0lVSjFabVpsY2k1VVdWQkZSRjlCVWxKQldWOVRWVkJRVDFKVUtTQjdYRzRnSUNBZ2RHaHBjeTVzWlc1bmRHZ2dQU0F3WEc0Z0lDQWdkR2hwY3k1d1lYSmxiblFnUFNCMWJtUmxabWx1WldSY2JpQWdmVnh1WEc0Z0lDOHZJRU52YlcxdmJpQmpZWE5sTGx4dUlDQnBaaUFvZEhsd1pXOW1JR0Z5WnlBOVBUMGdKMjUxYldKbGNpY3BJSHRjYmlBZ0lDQnlaWFIxY200Z1puSnZiVTUxYldKbGNpaDBhR2x6TENCaGNtY3BYRzRnSUgxY2JseHVJQ0F2THlCVGJHbG5hSFJzZVNCc1pYTnpJR052YlcxdmJpQmpZWE5sTGx4dUlDQnBaaUFvZEhsd1pXOW1JR0Z5WnlBOVBUMGdKM04wY21sdVp5Y3BJSHRjYmlBZ0lDQnlaWFIxY200Z1puSnZiVk4wY21sdVp5aDBhR2x6TENCaGNtY3NJR0Z5WjNWdFpXNTBjeTVzWlc1bmRHZ2dQaUF4SUQ4Z1lYSm5kVzFsYm5Seld6RmRJRG9nSjNWMFpqZ25LVnh1SUNCOVhHNWNiaUFnTHk4Z1ZXNTFjM1ZoYkM1Y2JpQWdjbVYwZFhKdUlHWnliMjFQWW1wbFkzUW9kR2hwY3l3Z1lYSm5LVnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQm1jbTl0VG5WdFltVnlJQ2gwYUdGMExDQnNaVzVuZEdncElIdGNiaUFnZEdoaGRDQTlJR0ZzYkc5allYUmxLSFJvWVhRc0lHeGxibWQwYUNBOElEQWdQeUF3SURvZ1kyaGxZMnRsWkNoc1pXNW5kR2dwSUh3Z01DbGNiaUFnYVdZZ0tDRkNkV1ptWlhJdVZGbFFSVVJmUVZKU1FWbGZVMVZRVUU5U1ZDa2dlMXh1SUNBZ0lHWnZjaUFvZG1GeUlHa2dQU0F3T3lCcElEd2diR1Z1WjNSb095QnBLeXNwSUh0Y2JpQWdJQ0FnSUhSb1lYUmJhVjBnUFNBd1hHNGdJQ0FnZlZ4dUlDQjlYRzRnSUhKbGRIVnliaUIwYUdGMFhHNTlYRzVjYm1aMWJtTjBhVzl1SUdaeWIyMVRkSEpwYm1jZ0tIUm9ZWFFzSUhOMGNtbHVaeXdnWlc1amIyUnBibWNwSUh0Y2JpQWdhV1lnS0hSNWNHVnZaaUJsYm1OdlpHbHVaeUFoUFQwZ0ozTjBjbWx1WnljZ2ZId2daVzVqYjJScGJtY2dQVDA5SUNjbktTQmxibU52WkdsdVp5QTlJQ2QxZEdZNEoxeHVYRzRnSUM4dklFRnpjM1Z0Y0hScGIyNDZJR0o1ZEdWTVpXNW5kR2dvS1NCeVpYUjFjbTRnZG1Gc2RXVWdhWE1nWVd4M1lYbHpJRHdnYTAxaGVFeGxibWQwYUM1Y2JpQWdkbUZ5SUd4bGJtZDBhQ0E5SUdKNWRHVk1aVzVuZEdnb2MzUnlhVzVuTENCbGJtTnZaR2x1WnlrZ2ZDQXdYRzRnSUhSb1lYUWdQU0JoYkd4dlkyRjBaU2gwYUdGMExDQnNaVzVuZEdncFhHNWNiaUFnZEdoaGRDNTNjbWwwWlNoemRISnBibWNzSUdWdVkyOWthVzVuS1Z4dUlDQnlaWFIxY200Z2RHaGhkRnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQm1jbTl0VDJKcVpXTjBJQ2gwYUdGMExDQnZZbXBsWTNRcElIdGNiaUFnYVdZZ0tFSjFabVpsY2k1cGMwSjFabVpsY2lodlltcGxZM1FwS1NCeVpYUjFjbTRnWm5KdmJVSjFabVpsY2loMGFHRjBMQ0J2WW1wbFkzUXBYRzVjYmlBZ2FXWWdLR2x6UVhKeVlYa29iMkpxWldOMEtTa2djbVYwZFhKdUlHWnliMjFCY25KaGVTaDBhR0YwTENCdlltcGxZM1FwWEc1Y2JpQWdhV1lnS0c5aWFtVmpkQ0E5UFNCdWRXeHNLU0I3WEc0Z0lDQWdkR2h5YjNjZ2JtVjNJRlI1Y0dWRmNuSnZjaWduYlhWemRDQnpkR0Z5ZENCM2FYUm9JRzUxYldKbGNpd2dZblZtWm1WeUxDQmhjbkpoZVNCdmNpQnpkSEpwYm1jbktWeHVJQ0I5WEc1Y2JpQWdhV1lnS0hSNWNHVnZaaUJCY25KaGVVSjFabVpsY2lBaFBUMGdKM1Z1WkdWbWFXNWxaQ2NwSUh0Y2JpQWdJQ0JwWmlBb2IySnFaV04wTG1KMVptWmxjaUJwYm5OMFlXNWpaVzltSUVGeWNtRjVRblZtWm1WeUtTQjdYRzRnSUNBZ0lDQnlaWFIxY200Z1puSnZiVlI1Y0dWa1FYSnlZWGtvZEdoaGRDd2diMkpxWldOMEtWeHVJQ0FnSUgxY2JpQWdJQ0JwWmlBb2IySnFaV04wSUdsdWMzUmhibU5sYjJZZ1FYSnlZWGxDZFdabVpYSXBJSHRjYmlBZ0lDQWdJSEpsZEhWeWJpQm1jbTl0UVhKeVlYbENkV1ptWlhJb2RHaGhkQ3dnYjJKcVpXTjBLVnh1SUNBZ0lIMWNiaUFnZlZ4dVhHNGdJR2xtSUNodlltcGxZM1F1YkdWdVozUm9LU0J5WlhSMWNtNGdabkp2YlVGeWNtRjVUR2xyWlNoMGFHRjBMQ0J2WW1wbFkzUXBYRzVjYmlBZ2NtVjBkWEp1SUdaeWIyMUtjMjl1VDJKcVpXTjBLSFJvWVhRc0lHOWlhbVZqZENsY2JuMWNibHh1Wm5WdVkzUnBiMjRnWm5KdmJVSjFabVpsY2lBb2RHaGhkQ3dnWW5WbVptVnlLU0I3WEc0Z0lIWmhjaUJzWlc1bmRHZ2dQU0JqYUdWamEyVmtLR0oxWm1abGNpNXNaVzVuZEdncElId2dNRnh1SUNCMGFHRjBJRDBnWVd4c2IyTmhkR1VvZEdoaGRDd2diR1Z1WjNSb0tWeHVJQ0JpZFdabVpYSXVZMjl3ZVNoMGFHRjBMQ0F3TENBd0xDQnNaVzVuZEdncFhHNGdJSEpsZEhWeWJpQjBhR0YwWEc1OVhHNWNibVoxYm1OMGFXOXVJR1p5YjIxQmNuSmhlU0FvZEdoaGRDd2dZWEp5WVhrcElIdGNiaUFnZG1GeUlHeGxibWQwYUNBOUlHTm9aV05yWldRb1lYSnlZWGt1YkdWdVozUm9LU0I4SURCY2JpQWdkR2hoZENBOUlHRnNiRzlqWVhSbEtIUm9ZWFFzSUd4bGJtZDBhQ2xjYmlBZ1ptOXlJQ2gyWVhJZ2FTQTlJREE3SUdrZ1BDQnNaVzVuZEdnN0lHa2dLejBnTVNrZ2UxeHVJQ0FnSUhSb1lYUmJhVjBnUFNCaGNuSmhlVnRwWFNBbUlESTFOVnh1SUNCOVhHNGdJSEpsZEhWeWJpQjBhR0YwWEc1OVhHNWNiaTh2SUVSMWNHeHBZMkYwWlNCdlppQm1jbTl0UVhKeVlYa29LU0IwYnlCclpXVndJR1p5YjIxQmNuSmhlU2dwSUcxdmJtOXRiM0p3YUdsakxseHVablZ1WTNScGIyNGdabkp2YlZSNWNHVmtRWEp5WVhrZ0tIUm9ZWFFzSUdGeWNtRjVLU0I3WEc0Z0lIWmhjaUJzWlc1bmRHZ2dQU0JqYUdWamEyVmtLR0Z5Y21GNUxteGxibWQwYUNrZ2ZDQXdYRzRnSUhSb1lYUWdQU0JoYkd4dlkyRjBaU2gwYUdGMExDQnNaVzVuZEdncFhHNGdJQzh2SUZSeWRXNWpZWFJwYm1jZ2RHaGxJR1ZzWlcxbGJuUnpJR2x6SUhCeWIySmhZbXg1SUc1dmRDQjNhR0YwSUhCbGIzQnNaU0JsZUhCbFkzUWdabkp2YlNCMGVYQmxaRnh1SUNBdkx5QmhjbkpoZVhNZ2QybDBhQ0JDV1ZSRlUxOVFSVkpmUlV4RlRVVk9WQ0ErSURFZ1luVjBJR2wwSjNNZ1kyOXRjR0YwYVdKc1pTQjNhWFJvSUhSb1pTQmlaV2hoZG1sdmNseHVJQ0F2THlCdlppQjBhR1VnYjJ4a0lFSjFabVpsY2lCamIyNXpkSEoxWTNSdmNpNWNiaUFnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCc1pXNW5kR2c3SUdrZ0t6MGdNU2tnZTF4dUlDQWdJSFJvWVhSYmFWMGdQU0JoY25KaGVWdHBYU0FtSURJMU5WeHVJQ0I5WEc0Z0lISmxkSFZ5YmlCMGFHRjBYRzU5WEc1Y2JtWjFibU4wYVc5dUlHWnliMjFCY25KaGVVSjFabVpsY2lBb2RHaGhkQ3dnWVhKeVlYa3BJSHRjYmlBZ2FXWWdLRUoxWm1abGNpNVVXVkJGUkY5QlVsSkJXVjlUVlZCUVQxSlVLU0I3WEc0Z0lDQWdMeThnVW1WMGRYSnVJR0Z1SUdGMVoyMWxiblJsWkNCZ1ZXbHVkRGhCY25KaGVXQWdhVzV6ZEdGdVkyVXNJR1p2Y2lCaVpYTjBJSEJsY21admNtMWhibU5sWEc0Z0lDQWdZWEp5WVhrdVlubDBaVXhsYm1kMGFGeHVJQ0FnSUhSb1lYUWdQU0JDZFdabVpYSXVYMkYxWjIxbGJuUW9ibVYzSUZWcGJuUTRRWEp5WVhrb1lYSnlZWGtwS1Z4dUlDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUM4dklFWmhiR3hpWVdOck9pQlNaWFIxY200Z1lXNGdiMkpxWldOMElHbHVjM1JoYm1ObElHOW1JSFJvWlNCQ2RXWm1aWElnWTJ4aGMzTmNiaUFnSUNCMGFHRjBJRDBnWm5KdmJWUjVjR1ZrUVhKeVlYa29kR2hoZEN3Z2JtVjNJRlZwYm5RNFFYSnlZWGtvWVhKeVlYa3BLVnh1SUNCOVhHNGdJSEpsZEhWeWJpQjBhR0YwWEc1OVhHNWNibVoxYm1OMGFXOXVJR1p5YjIxQmNuSmhlVXhwYTJVZ0tIUm9ZWFFzSUdGeWNtRjVLU0I3WEc0Z0lIWmhjaUJzWlc1bmRHZ2dQU0JqYUdWamEyVmtLR0Z5Y21GNUxteGxibWQwYUNrZ2ZDQXdYRzRnSUhSb1lYUWdQU0JoYkd4dlkyRjBaU2gwYUdGMExDQnNaVzVuZEdncFhHNGdJR1p2Y2lBb2RtRnlJR2tnUFNBd095QnBJRHdnYkdWdVozUm9PeUJwSUNzOUlERXBJSHRjYmlBZ0lDQjBhR0YwVzJsZElEMGdZWEp5WVhsYmFWMGdKaUF5TlRWY2JpQWdmVnh1SUNCeVpYUjFjbTRnZEdoaGRGeHVmVnh1WEc0dkx5QkVaWE5sY21saGJHbDZaU0I3SUhSNWNHVTZJQ2RDZFdabVpYSW5MQ0JrWVhSaE9pQmJNU3d5TERNc0xpNHVYU0I5SUdsdWRHOGdZU0JDZFdabVpYSWdiMkpxWldOMExseHVMeThnVW1WMGRYSnVjeUJoSUhwbGNtOHRiR1Z1WjNSb0lHSjFabVpsY2lCbWIzSWdhVzV3ZFhSeklIUm9ZWFFnWkc5dUozUWdZMjl1Wm05eWJTQjBieUIwYUdVZ2MzQmxZeTVjYm1aMWJtTjBhVzl1SUdaeWIyMUtjMjl1VDJKcVpXTjBJQ2gwYUdGMExDQnZZbXBsWTNRcElIdGNiaUFnZG1GeUlHRnljbUY1WEc0Z0lIWmhjaUJzWlc1bmRHZ2dQU0F3WEc1Y2JpQWdhV1lnS0c5aWFtVmpkQzUwZVhCbElEMDlQU0FuUW5WbVptVnlKeUFtSmlCcGMwRnljbUY1S0c5aWFtVmpkQzVrWVhSaEtTa2dlMXh1SUNBZ0lHRnljbUY1SUQwZ2IySnFaV04wTG1SaGRHRmNiaUFnSUNCc1pXNW5kR2dnUFNCamFHVmphMlZrS0dGeWNtRjVMbXhsYm1kMGFDa2dmQ0F3WEc0Z0lIMWNiaUFnZEdoaGRDQTlJR0ZzYkc5allYUmxLSFJvWVhRc0lHeGxibWQwYUNsY2JseHVJQ0JtYjNJZ0tIWmhjaUJwSUQwZ01Ec2dhU0E4SUd4bGJtZDBhRHNnYVNBclBTQXhLU0I3WEc0Z0lDQWdkR2hoZEZ0cFhTQTlJR0Z5Y21GNVcybGRJQ1lnTWpVMVhHNGdJSDFjYmlBZ2NtVjBkWEp1SUhSb1lYUmNibjFjYmx4dWFXWWdLRUoxWm1abGNpNVVXVkJGUkY5QlVsSkJXVjlUVlZCUVQxSlVLU0I3WEc0Z0lFSjFabVpsY2k1d2NtOTBiM1I1Y0dVdVgxOXdjbTkwYjE5ZklEMGdWV2x1ZERoQmNuSmhlUzV3Y205MGIzUjVjR1ZjYmlBZ1FuVm1abVZ5TGw5ZmNISnZkRzlmWHlBOUlGVnBiblE0UVhKeVlYbGNibjBnWld4elpTQjdYRzRnSUM4dklIQnlaUzF6WlhRZ1ptOXlJSFpoYkhWbGN5QjBhR0YwSUcxaGVTQmxlR2x6ZENCcGJpQjBhR1VnWm5WMGRYSmxYRzRnSUVKMVptWmxjaTV3Y205MGIzUjVjR1V1YkdWdVozUm9JRDBnZFc1a1pXWnBibVZrWEc0Z0lFSjFabVpsY2k1d2NtOTBiM1I1Y0dVdWNHRnlaVzUwSUQwZ2RXNWtaV1pwYm1Wa1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdGc2JHOWpZWFJsSUNoMGFHRjBMQ0JzWlc1bmRHZ3BJSHRjYmlBZ2FXWWdLRUoxWm1abGNpNVVXVkJGUkY5QlVsSkJXVjlUVlZCUVQxSlVLU0I3WEc0Z0lDQWdMeThnVW1WMGRYSnVJR0Z1SUdGMVoyMWxiblJsWkNCZ1ZXbHVkRGhCY25KaGVXQWdhVzV6ZEdGdVkyVXNJR1p2Y2lCaVpYTjBJSEJsY21admNtMWhibU5sWEc0Z0lDQWdkR2hoZENBOUlFSjFabVpsY2k1ZllYVm5iV1Z1ZENodVpYY2dWV2x1ZERoQmNuSmhlU2hzWlc1bmRHZ3BLVnh1SUNBZ0lIUm9ZWFF1WDE5d2NtOTBiMTlmSUQwZ1FuVm1abVZ5TG5CeWIzUnZkSGx3WlZ4dUlDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUM4dklFWmhiR3hpWVdOck9pQlNaWFIxY200Z1lXNGdiMkpxWldOMElHbHVjM1JoYm1ObElHOW1JSFJvWlNCQ2RXWm1aWElnWTJ4aGMzTmNiaUFnSUNCMGFHRjBMbXhsYm1kMGFDQTlJR3hsYm1kMGFGeHVJQ0FnSUhSb1lYUXVYMmx6UW5WbVptVnlJRDBnZEhKMVpWeHVJQ0I5WEc1Y2JpQWdkbUZ5SUdaeWIyMVFiMjlzSUQwZ2JHVnVaM1JvSUNFOVBTQXdJQ1ltSUd4bGJtZDBhQ0E4UFNCQ2RXWm1aWEl1Y0c5dmJGTnBlbVVnUGo0K0lERmNiaUFnYVdZZ0tHWnliMjFRYjI5c0tTQjBhR0YwTG5CaGNtVnVkQ0E5SUhKdmIzUlFZWEpsYm5SY2JseHVJQ0J5WlhSMWNtNGdkR2hoZEZ4dWZWeHVYRzVtZFc1amRHbHZiaUJqYUdWamEyVmtJQ2hzWlc1bmRHZ3BJSHRjYmlBZ0x5OGdUbTkwWlRvZ1kyRnVibTkwSUhWelpTQmdiR1Z1WjNSb0lEd2dhMDFoZUV4bGJtZDBhR0FnYUdWeVpTQmlaV05oZFhObElIUm9ZWFFnWm1GcGJITWdkMmhsYmx4dUlDQXZMeUJzWlc1bmRHZ2dhWE1nVG1GT0lDaDNhR2xqYUNCcGN5QnZkR2hsY25kcGMyVWdZMjlsY21ObFpDQjBieUI2WlhKdkxpbGNiaUFnYVdZZ0tHeGxibWQwYUNBK1BTQnJUV0Y0VEdWdVozUm9LQ2twSUh0Y2JpQWdJQ0IwYUhKdmR5QnVaWGNnVW1GdVoyVkZjbkp2Y2lnblFYUjBaVzF3ZENCMGJ5QmhiR3h2WTJGMFpTQkNkV1ptWlhJZ2JHRnlaMlZ5SUhSb1lXNGdiV0Y0YVcxMWJTQW5JQ3RjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FuYzJsNlpUb2dNSGduSUNzZ2EwMWhlRXhsYm1kMGFDZ3BMblJ2VTNSeWFXNW5LREUyS1NBcklDY2dZbmwwWlhNbktWeHVJQ0I5WEc0Z0lISmxkSFZ5YmlCc1pXNW5kR2dnZkNBd1hHNTlYRzVjYm1aMWJtTjBhVzl1SUZOc2IzZENkV1ptWlhJZ0tITjFZbXBsWTNRc0lHVnVZMjlrYVc1bktTQjdYRzRnSUdsbUlDZ2hLSFJvYVhNZ2FXNXpkR0Z1WTJWdlppQlRiRzkzUW5WbVptVnlLU2tnY21WMGRYSnVJRzVsZHlCVGJHOTNRblZtWm1WeUtITjFZbXBsWTNRc0lHVnVZMjlrYVc1bktWeHVYRzRnSUhaaGNpQmlkV1lnUFNCdVpYY2dRblZtWm1WeUtITjFZbXBsWTNRc0lHVnVZMjlrYVc1bktWeHVJQ0JrWld4bGRHVWdZblZtTG5CaGNtVnVkRnh1SUNCeVpYUjFjbTRnWW5WbVhHNTlYRzVjYmtKMVptWmxjaTVwYzBKMVptWmxjaUE5SUdaMWJtTjBhVzl1SUdselFuVm1abVZ5SUNoaUtTQjdYRzRnSUhKbGRIVnliaUFoSVNoaUlDRTlJRzUxYkd3Z0ppWWdZaTVmYVhOQ2RXWm1aWElwWEc1OVhHNWNia0oxWm1abGNpNWpiMjF3WVhKbElEMGdablZ1WTNScGIyNGdZMjl0Y0dGeVpTQW9ZU3dnWWlrZ2UxeHVJQ0JwWmlBb0lVSjFabVpsY2k1cGMwSjFabVpsY2loaEtTQjhmQ0FoUW5WbVptVnlMbWx6UW5WbVptVnlLR0lwS1NCN1hHNGdJQ0FnZEdoeWIzY2dibVYzSUZSNWNHVkZjbkp2Y2lnblFYSm5kVzFsYm5SeklHMTFjM1FnWW1VZ1FuVm1abVZ5Y3ljcFhHNGdJSDFjYmx4dUlDQnBaaUFvWVNBOVBUMGdZaWtnY21WMGRYSnVJREJjYmx4dUlDQjJZWElnZUNBOUlHRXViR1Z1WjNSb1hHNGdJSFpoY2lCNUlEMGdZaTVzWlc1bmRHaGNibHh1SUNCMllYSWdhU0E5SURCY2JpQWdkbUZ5SUd4bGJpQTlJRTFoZEdndWJXbHVLSGdzSUhrcFhHNGdJSGRvYVd4bElDaHBJRHdnYkdWdUtTQjdYRzRnSUNBZ2FXWWdLR0ZiYVYwZ0lUMDlJR0piYVYwcElHSnlaV0ZyWEc1Y2JpQWdJQ0FySzJsY2JpQWdmVnh1WEc0Z0lHbG1JQ2hwSUNFOVBTQnNaVzRwSUh0Y2JpQWdJQ0I0SUQwZ1lWdHBYVnh1SUNBZ0lIa2dQU0JpVzJsZFhHNGdJSDFjYmx4dUlDQnBaaUFvZUNBOElIa3BJSEpsZEhWeWJpQXRNVnh1SUNCcFppQW9lU0E4SUhncElISmxkSFZ5YmlBeFhHNGdJSEpsZEhWeWJpQXdYRzU5WEc1Y2JrSjFabVpsY2k1cGMwVnVZMjlrYVc1bklEMGdablZ1WTNScGIyNGdhWE5GYm1OdlpHbHVaeUFvWlc1amIyUnBibWNwSUh0Y2JpQWdjM2RwZEdOb0lDaFRkSEpwYm1jb1pXNWpiMlJwYm1jcExuUnZURzkzWlhKRFlYTmxLQ2twSUh0Y2JpQWdJQ0JqWVhObElDZG9aWGduT2x4dUlDQWdJR05oYzJVZ0ozVjBaamduT2x4dUlDQWdJR05oYzJVZ0ozVjBaaTA0SnpwY2JpQWdJQ0JqWVhObElDZGhjMk5wYVNjNlhHNGdJQ0FnWTJGelpTQW5ZbWx1WVhKNUp6cGNiaUFnSUNCallYTmxJQ2RpWVhObE5qUW5PbHh1SUNBZ0lHTmhjMlVnSjNKaGR5YzZYRzRnSUNBZ1kyRnpaU0FuZFdOek1pYzZYRzRnSUNBZ1kyRnpaU0FuZFdOekxUSW5PbHh1SUNBZ0lHTmhjMlVnSjNWMFpqRTJiR1VuT2x4dUlDQWdJR05oYzJVZ0ozVjBaaTB4Tm14bEp6cGNiaUFnSUNBZ0lISmxkSFZ5YmlCMGNuVmxYRzRnSUNBZ1pHVm1ZWFZzZERwY2JpQWdJQ0FnSUhKbGRIVnliaUJtWVd4elpWeHVJQ0I5WEc1OVhHNWNia0oxWm1abGNpNWpiMjVqWVhRZ1BTQm1kVzVqZEdsdmJpQmpiMjVqWVhRZ0tHeHBjM1FzSUd4bGJtZDBhQ2tnZTF4dUlDQnBaaUFvSVdselFYSnlZWGtvYkdsemRDa3BJSFJvY205M0lHNWxkeUJVZVhCbFJYSnliM0lvSjJ4cGMzUWdZWEpuZFcxbGJuUWdiWFZ6ZENCaVpTQmhiaUJCY25KaGVTQnZaaUJDZFdabVpYSnpMaWNwWEc1Y2JpQWdhV1lnS0d4cGMzUXViR1Z1WjNSb0lEMDlQU0F3S1NCN1hHNGdJQ0FnY21WMGRYSnVJRzVsZHlCQ2RXWm1aWElvTUNsY2JpQWdmVnh1WEc0Z0lIWmhjaUJwWEc0Z0lHbG1JQ2hzWlc1bmRHZ2dQVDA5SUhWdVpHVm1hVzVsWkNrZ2UxeHVJQ0FnSUd4bGJtZDBhQ0E5SURCY2JpQWdJQ0JtYjNJZ0tHa2dQU0F3T3lCcElEd2diR2x6ZEM1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdiR1Z1WjNSb0lDczlJR3hwYzNSYmFWMHViR1Z1WjNSb1hHNGdJQ0FnZlZ4dUlDQjlYRzVjYmlBZ2RtRnlJR0oxWmlBOUlHNWxkeUJDZFdabVpYSW9iR1Z1WjNSb0tWeHVJQ0IyWVhJZ2NHOXpJRDBnTUZ4dUlDQm1iM0lnS0drZ1BTQXdPeUJwSUR3Z2JHbHpkQzVzWlc1bmRHZzdJR2tyS3lrZ2UxeHVJQ0FnSUhaaGNpQnBkR1Z0SUQwZ2JHbHpkRnRwWFZ4dUlDQWdJR2wwWlcwdVkyOXdlU2hpZFdZc0lIQnZjeWxjYmlBZ0lDQndiM01nS3owZ2FYUmxiUzVzWlc1bmRHaGNiaUFnZlZ4dUlDQnlaWFIxY200Z1luVm1YRzU5WEc1Y2JtWjFibU4wYVc5dUlHSjVkR1ZNWlc1bmRHZ2dLSE4wY21sdVp5d2daVzVqYjJScGJtY3BJSHRjYmlBZ2FXWWdLSFI1Y0dWdlppQnpkSEpwYm1jZ0lUMDlJQ2R6ZEhKcGJtY25LU0J6ZEhKcGJtY2dQU0FuSnlBcklITjBjbWx1WjF4dVhHNGdJSFpoY2lCc1pXNGdQU0J6ZEhKcGJtY3ViR1Z1WjNSb1hHNGdJR2xtSUNoc1pXNGdQVDA5SURBcElISmxkSFZ5YmlBd1hHNWNiaUFnTHk4Z1ZYTmxJR0VnWm05eUlHeHZiM0FnZEc4Z1lYWnZhV1FnY21WamRYSnphVzl1WEc0Z0lIWmhjaUJzYjNkbGNtVmtRMkZ6WlNBOUlHWmhiSE5sWEc0Z0lHWnZjaUFvT3pzcElIdGNiaUFnSUNCemQybDBZMmdnS0dWdVkyOWthVzVuS1NCN1hHNGdJQ0FnSUNCallYTmxJQ2RoYzJOcGFTYzZYRzRnSUNBZ0lDQmpZWE5sSUNkaWFXNWhjbmtuT2x4dUlDQWdJQ0FnTHk4Z1JHVndjbVZqWVhSbFpGeHVJQ0FnSUNBZ1kyRnpaU0FuY21GM0p6cGNiaUFnSUNBZ0lHTmhjMlVnSjNKaGQzTW5PbHh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdiR1Z1WEc0Z0lDQWdJQ0JqWVhObElDZDFkR1k0SnpwY2JpQWdJQ0FnSUdOaGMyVWdKM1YwWmkwNEp6cGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlIVjBaamhVYjBKNWRHVnpLSE4wY21sdVp5a3ViR1Z1WjNSb1hHNGdJQ0FnSUNCallYTmxJQ2QxWTNNeUp6cGNiaUFnSUNBZ0lHTmhjMlVnSjNWamN5MHlKenBjYmlBZ0lDQWdJR05oYzJVZ0ozVjBaakUyYkdVbk9seHVJQ0FnSUNBZ1kyRnpaU0FuZFhSbUxURTJiR1VuT2x4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnYkdWdUlDb2dNbHh1SUNBZ0lDQWdZMkZ6WlNBbmFHVjRKenBjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJR3hsYmlBK1BqNGdNVnh1SUNBZ0lDQWdZMkZ6WlNBblltRnpaVFkwSnpwY2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUdKaGMyVTJORlJ2UW5sMFpYTW9jM1J5YVc1bktTNXNaVzVuZEdoY2JpQWdJQ0FnSUdSbFptRjFiSFE2WEc0Z0lDQWdJQ0FnSUdsbUlDaHNiM2RsY21Wa1EyRnpaU2tnY21WMGRYSnVJSFYwWmpoVWIwSjVkR1Z6S0hOMGNtbHVaeWt1YkdWdVozUm9JQzh2SUdGemMzVnRaU0IxZEdZNFhHNGdJQ0FnSUNBZ0lHVnVZMjlrYVc1bklEMGdLQ2NuSUNzZ1pXNWpiMlJwYm1jcExuUnZURzkzWlhKRFlYTmxLQ2xjYmlBZ0lDQWdJQ0FnYkc5M1pYSmxaRU5oYzJVZ1BTQjBjblZsWEc0Z0lDQWdmVnh1SUNCOVhHNTlYRzVDZFdabVpYSXVZbmwwWlV4bGJtZDBhQ0E5SUdKNWRHVk1aVzVuZEdoY2JseHVablZ1WTNScGIyNGdjMnh2ZDFSdlUzUnlhVzVuSUNobGJtTnZaR2x1Wnl3Z2MzUmhjblFzSUdWdVpDa2dlMXh1SUNCMllYSWdiRzkzWlhKbFpFTmhjMlVnUFNCbVlXeHpaVnh1WEc0Z0lITjBZWEowSUQwZ2MzUmhjblFnZkNBd1hHNGdJR1Z1WkNBOUlHVnVaQ0E5UFQwZ2RXNWtaV1pwYm1Wa0lIeDhJR1Z1WkNBOVBUMGdTVzVtYVc1cGRIa2dQeUIwYUdsekxteGxibWQwYUNBNklHVnVaQ0I4SURCY2JseHVJQ0JwWmlBb0lXVnVZMjlrYVc1bktTQmxibU52WkdsdVp5QTlJQ2QxZEdZNEoxeHVJQ0JwWmlBb2MzUmhjblFnUENBd0tTQnpkR0Z5ZENBOUlEQmNiaUFnYVdZZ0tHVnVaQ0ErSUhSb2FYTXViR1Z1WjNSb0tTQmxibVFnUFNCMGFHbHpMbXhsYm1kMGFGeHVJQ0JwWmlBb1pXNWtJRHc5SUhOMFlYSjBLU0J5WlhSMWNtNGdKeWRjYmx4dUlDQjNhR2xzWlNBb2RISjFaU2tnZTF4dUlDQWdJSE4zYVhSamFDQW9aVzVqYjJScGJtY3BJSHRjYmlBZ0lDQWdJR05oYzJVZ0oyaGxlQ2M2WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJvWlhoVGJHbGpaU2gwYUdsekxDQnpkR0Z5ZEN3Z1pXNWtLVnh1WEc0Z0lDQWdJQ0JqWVhObElDZDFkR1k0SnpwY2JpQWdJQ0FnSUdOaGMyVWdKM1YwWmkwNEp6cGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlIVjBaamhUYkdsalpTaDBhR2x6TENCemRHRnlkQ3dnWlc1a0tWeHVYRzRnSUNBZ0lDQmpZWE5sSUNkaGMyTnBhU2M2WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJoYzJOcGFWTnNhV05sS0hSb2FYTXNJSE4wWVhKMExDQmxibVFwWEc1Y2JpQWdJQ0FnSUdOaGMyVWdKMkpwYm1GeWVTYzZYRzRnSUNBZ0lDQWdJSEpsZEhWeWJpQmlhVzVoY25sVGJHbGpaU2gwYUdsekxDQnpkR0Z5ZEN3Z1pXNWtLVnh1WEc0Z0lDQWdJQ0JqWVhObElDZGlZWE5sTmpRbk9seHVJQ0FnSUNBZ0lDQnlaWFIxY200Z1ltRnpaVFkwVTJ4cFkyVW9kR2hwY3l3Z2MzUmhjblFzSUdWdVpDbGNibHh1SUNBZ0lDQWdZMkZ6WlNBbmRXTnpNaWM2WEc0Z0lDQWdJQ0JqWVhObElDZDFZM010TWljNlhHNGdJQ0FnSUNCallYTmxJQ2QxZEdZeE5teGxKenBjYmlBZ0lDQWdJR05oYzJVZ0ozVjBaaTB4Tm14bEp6cGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlIVjBaakUyYkdWVGJHbGpaU2gwYUdsekxDQnpkR0Z5ZEN3Z1pXNWtLVnh1WEc0Z0lDQWdJQ0JrWldaaGRXeDBPbHh1SUNBZ0lDQWdJQ0JwWmlBb2JHOTNaWEpsWkVOaGMyVXBJSFJvY205M0lHNWxkeUJVZVhCbFJYSnliM0lvSjFWdWEyNXZkMjRnWlc1amIyUnBibWM2SUNjZ0t5QmxibU52WkdsdVp5bGNiaUFnSUNBZ0lDQWdaVzVqYjJScGJtY2dQU0FvWlc1amIyUnBibWNnS3lBbkp5a3VkRzlNYjNkbGNrTmhjMlVvS1Z4dUlDQWdJQ0FnSUNCc2IzZGxjbVZrUTJGelpTQTlJSFJ5ZFdWY2JpQWdJQ0I5WEc0Z0lIMWNibjFjYmx4dVFuVm1abVZ5TG5CeWIzUnZkSGx3WlM1MGIxTjBjbWx1WnlBOUlHWjFibU4wYVc5dUlIUnZVM1J5YVc1bklDZ3BJSHRjYmlBZ2RtRnlJR3hsYm1kMGFDQTlJSFJvYVhNdWJHVnVaM1JvSUh3Z01GeHVJQ0JwWmlBb2JHVnVaM1JvSUQwOVBTQXdLU0J5WlhSMWNtNGdKeWRjYmlBZ2FXWWdLR0Z5WjNWdFpXNTBjeTVzWlc1bmRHZ2dQVDA5SURBcElISmxkSFZ5YmlCMWRHWTRVMnhwWTJVb2RHaHBjeXdnTUN3Z2JHVnVaM1JvS1Z4dUlDQnlaWFIxY200Z2MyeHZkMVJ2VTNSeWFXNW5MbUZ3Y0d4NUtIUm9hWE1zSUdGeVozVnRaVzUwY3lsY2JuMWNibHh1UW5WbVptVnlMbkJ5YjNSdmRIbHdaUzVsY1hWaGJITWdQU0JtZFc1amRHbHZiaUJsY1hWaGJITWdLR0lwSUh0Y2JpQWdhV1lnS0NGQ2RXWm1aWEl1YVhOQ2RXWm1aWElvWWlrcElIUm9jbTkzSUc1bGR5QlVlWEJsUlhKeWIzSW9KMEZ5WjNWdFpXNTBJRzExYzNRZ1ltVWdZU0JDZFdabVpYSW5LVnh1SUNCcFppQW9kR2hwY3lBOVBUMGdZaWtnY21WMGRYSnVJSFJ5ZFdWY2JpQWdjbVYwZFhKdUlFSjFabVpsY2k1amIyMXdZWEpsS0hSb2FYTXNJR0lwSUQwOVBTQXdYRzU5WEc1Y2JrSjFabVpsY2k1d2NtOTBiM1I1Y0dVdWFXNXpjR1ZqZENBOUlHWjFibU4wYVc5dUlHbHVjM0JsWTNRZ0tDa2dlMXh1SUNCMllYSWdjM1J5SUQwZ0p5ZGNiaUFnZG1GeUlHMWhlQ0E5SUdWNGNHOXlkSE11U1U1VFVFVkRWRjlOUVZoZlFsbFVSVk5jYmlBZ2FXWWdLSFJvYVhNdWJHVnVaM1JvSUQ0Z01Da2dlMXh1SUNBZ0lITjBjaUE5SUhSb2FYTXVkRzlUZEhKcGJtY29KMmhsZUNjc0lEQXNJRzFoZUNrdWJXRjBZMmdvTHk1N01uMHZaeWt1YW05cGJpZ25JQ2NwWEc0Z0lDQWdhV1lnS0hSb2FYTXViR1Z1WjNSb0lENGdiV0Y0S1NCemRISWdLejBnSnlBdUxpNGdKMXh1SUNCOVhHNGdJSEpsZEhWeWJpQW5QRUoxWm1abGNpQW5JQ3NnYzNSeUlDc2dKejRuWEc1OVhHNWNia0oxWm1abGNpNXdjbTkwYjNSNWNHVXVZMjl0Y0dGeVpTQTlJR1oxYm1OMGFXOXVJR052YlhCaGNtVWdLR0lwSUh0Y2JpQWdhV1lnS0NGQ2RXWm1aWEl1YVhOQ2RXWm1aWElvWWlrcElIUm9jbTkzSUc1bGR5QlVlWEJsUlhKeWIzSW9KMEZ5WjNWdFpXNTBJRzExYzNRZ1ltVWdZU0JDZFdabVpYSW5LVnh1SUNCcFppQW9kR2hwY3lBOVBUMGdZaWtnY21WMGRYSnVJREJjYmlBZ2NtVjBkWEp1SUVKMVptWmxjaTVqYjIxd1lYSmxLSFJvYVhNc0lHSXBYRzU5WEc1Y2JrSjFabVpsY2k1d2NtOTBiM1I1Y0dVdWFXNWtaWGhQWmlBOUlHWjFibU4wYVc5dUlHbHVaR1Y0VDJZZ0tIWmhiQ3dnWW5sMFpVOW1abk5sZENrZ2UxeHVJQ0JwWmlBb1lubDBaVTltWm5ObGRDQStJREI0TjJabVptWm1abVlwSUdKNWRHVlBabVp6WlhRZ1BTQXdlRGRtWm1abVptWm1YRzRnSUdWc2MyVWdhV1lnS0dKNWRHVlBabVp6WlhRZ1BDQXRNSGc0TURBd01EQXdNQ2tnWW5sMFpVOW1abk5sZENBOUlDMHdlRGd3TURBd01EQXdYRzRnSUdKNWRHVlBabVp6WlhRZ1BqNDlJREJjYmx4dUlDQnBaaUFvZEdocGN5NXNaVzVuZEdnZ1BUMDlJREFwSUhKbGRIVnliaUF0TVZ4dUlDQnBaaUFvWW5sMFpVOW1abk5sZENBK1BTQjBhR2x6TG14bGJtZDBhQ2tnY21WMGRYSnVJQzB4WEc1Y2JpQWdMeThnVG1WbllYUnBkbVVnYjJabWMyVjBjeUJ6ZEdGeWRDQm1jbTl0SUhSb1pTQmxibVFnYjJZZ2RHaGxJR0oxWm1abGNseHVJQ0JwWmlBb1lubDBaVTltWm5ObGRDQThJREFwSUdKNWRHVlBabVp6WlhRZ1BTQk5ZWFJvTG0xaGVDaDBhR2x6TG14bGJtZDBhQ0FySUdKNWRHVlBabVp6WlhRc0lEQXBYRzVjYmlBZ2FXWWdLSFI1Y0dWdlppQjJZV3dnUFQwOUlDZHpkSEpwYm1jbktTQjdYRzRnSUNBZ2FXWWdLSFpoYkM1c1pXNW5kR2dnUFQwOUlEQXBJSEpsZEhWeWJpQXRNU0F2THlCemNHVmphV0ZzSUdOaGMyVTZJR3h2YjJ0cGJtY2dabTl5SUdWdGNIUjVJSE4wY21sdVp5QmhiSGRoZVhNZ1ptRnBiSE5jYmlBZ0lDQnlaWFIxY200Z1UzUnlhVzVuTG5CeWIzUnZkSGx3WlM1cGJtUmxlRTltTG1OaGJHd29kR2hwY3l3Z2RtRnNMQ0JpZVhSbFQyWm1jMlYwS1Z4dUlDQjlYRzRnSUdsbUlDaENkV1ptWlhJdWFYTkNkV1ptWlhJb2RtRnNLU2tnZTF4dUlDQWdJSEpsZEhWeWJpQmhjbkpoZVVsdVpHVjRUMllvZEdocGN5d2dkbUZzTENCaWVYUmxUMlptYzJWMEtWeHVJQ0I5WEc0Z0lHbG1JQ2gwZVhCbGIyWWdkbUZzSUQwOVBTQW5iblZ0WW1WeUp5a2dlMXh1SUNBZ0lHbG1JQ2hDZFdabVpYSXVWRmxRUlVSZlFWSlNRVmxmVTFWUVVFOVNWQ0FtSmlCVmFXNTBPRUZ5Y21GNUxuQnliM1J2ZEhsd1pTNXBibVJsZUU5bUlEMDlQU0FuWm5WdVkzUnBiMjRuS1NCN1hHNGdJQ0FnSUNCeVpYUjFjbTRnVldsdWREaEJjbkpoZVM1d2NtOTBiM1I1Y0dVdWFXNWtaWGhQWmk1allXeHNLSFJvYVhNc0lIWmhiQ3dnWW5sMFpVOW1abk5sZENsY2JpQWdJQ0I5WEc0Z0lDQWdjbVYwZFhKdUlHRnljbUY1U1c1a1pYaFBaaWgwYUdsekxDQmJJSFpoYkNCZExDQmllWFJsVDJabWMyVjBLVnh1SUNCOVhHNWNiaUFnWm5WdVkzUnBiMjRnWVhKeVlYbEpibVJsZUU5bUlDaGhjbklzSUhaaGJDd2dZbmwwWlU5bVpuTmxkQ2tnZTF4dUlDQWdJSFpoY2lCbWIzVnVaRWx1WkdWNElEMGdMVEZjYmlBZ0lDQm1iM0lnS0haaGNpQnBJRDBnTURzZ1lubDBaVTltWm5ObGRDQXJJR2tnUENCaGNuSXViR1Z1WjNSb095QnBLeXNwSUh0Y2JpQWdJQ0FnSUdsbUlDaGhjbkpiWW5sMFpVOW1abk5sZENBcklHbGRJRDA5UFNCMllXeGJabTkxYm1SSmJtUmxlQ0E5UFQwZ0xURWdQeUF3SURvZ2FTQXRJR1p2ZFc1a1NXNWtaWGhkS1NCN1hHNGdJQ0FnSUNBZ0lHbG1JQ2htYjNWdVpFbHVaR1Y0SUQwOVBTQXRNU2tnWm05MWJtUkpibVJsZUNBOUlHbGNiaUFnSUNBZ0lDQWdhV1lnS0drZ0xTQm1iM1Z1WkVsdVpHVjRJQ3NnTVNBOVBUMGdkbUZzTG14bGJtZDBhQ2tnY21WMGRYSnVJR0o1ZEdWUFptWnpaWFFnS3lCbWIzVnVaRWx1WkdWNFhHNGdJQ0FnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUNCbWIzVnVaRWx1WkdWNElEMGdMVEZjYmlBZ0lDQWdJSDFjYmlBZ0lDQjlYRzRnSUNBZ2NtVjBkWEp1SUMweFhHNGdJSDFjYmx4dUlDQjBhSEp2ZHlCdVpYY2dWSGx3WlVWeWNtOXlLQ2QyWVd3Z2JYVnpkQ0JpWlNCemRISnBibWNzSUc1MWJXSmxjaUJ2Y2lCQ2RXWm1aWEluS1Z4dWZWeHVYRzR2THlCZ1oyVjBZQ0JwY3lCa1pYQnlaV05oZEdWa1hHNUNkV1ptWlhJdWNISnZkRzkwZVhCbExtZGxkQ0E5SUdaMWJtTjBhVzl1SUdkbGRDQW9iMlptYzJWMEtTQjdYRzRnSUdOdmJuTnZiR1V1Ykc5bktDY3VaMlYwS0NrZ2FYTWdaR1Z3Y21WallYUmxaQzRnUVdOalpYTnpJSFZ6YVc1bklHRnljbUY1SUdsdVpHVjRaWE1nYVc1emRHVmhaQzRuS1Z4dUlDQnlaWFIxY200Z2RHaHBjeTV5WldGa1ZVbHVkRGdvYjJabWMyVjBLVnh1ZlZ4dVhHNHZMeUJnYzJWMFlDQnBjeUJrWlhCeVpXTmhkR1ZrWEc1Q2RXWm1aWEl1Y0hKdmRHOTBlWEJsTG5ObGRDQTlJR1oxYm1OMGFXOXVJSE5sZENBb2Rpd2diMlptYzJWMEtTQjdYRzRnSUdOdmJuTnZiR1V1Ykc5bktDY3VjMlYwS0NrZ2FYTWdaR1Z3Y21WallYUmxaQzRnUVdOalpYTnpJSFZ6YVc1bklHRnljbUY1SUdsdVpHVjRaWE1nYVc1emRHVmhaQzRuS1Z4dUlDQnlaWFIxY200Z2RHaHBjeTUzY21sMFpWVkpiblE0S0hZc0lHOW1abk5sZENsY2JuMWNibHh1Wm5WdVkzUnBiMjRnYUdWNFYzSnBkR1VnS0dKMVppd2djM1J5YVc1bkxDQnZabVp6WlhRc0lHeGxibWQwYUNrZ2UxeHVJQ0J2Wm1aelpYUWdQU0JPZFcxaVpYSW9iMlptYzJWMEtTQjhmQ0F3WEc0Z0lIWmhjaUJ5WlcxaGFXNXBibWNnUFNCaWRXWXViR1Z1WjNSb0lDMGdiMlptYzJWMFhHNGdJR2xtSUNnaGJHVnVaM1JvS1NCN1hHNGdJQ0FnYkdWdVozUm9JRDBnY21WdFlXbHVhVzVuWEc0Z0lIMGdaV3h6WlNCN1hHNGdJQ0FnYkdWdVozUm9JRDBnVG5WdFltVnlLR3hsYm1kMGFDbGNiaUFnSUNCcFppQW9iR1Z1WjNSb0lENGdjbVZ0WVdsdWFXNW5LU0I3WEc0Z0lDQWdJQ0JzWlc1bmRHZ2dQU0J5WlcxaGFXNXBibWRjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0F2THlCdGRYTjBJR0psSUdGdUlHVjJaVzRnYm5WdFltVnlJRzltSUdScFoybDBjMXh1SUNCMllYSWdjM1J5VEdWdUlEMGdjM1J5YVc1bkxteGxibWQwYUZ4dUlDQnBaaUFvYzNSeVRHVnVJQ1VnTWlBaFBUMGdNQ2tnZEdoeWIzY2dibVYzSUVWeWNtOXlLQ2RKYm5aaGJHbGtJR2hsZUNCemRISnBibWNuS1Z4dVhHNGdJR2xtSUNoc1pXNW5kR2dnUGlCemRISk1aVzRnTHlBeUtTQjdYRzRnSUNBZ2JHVnVaM1JvSUQwZ2MzUnlUR1Z1SUM4Z01seHVJQ0I5WEc0Z0lHWnZjaUFvZG1GeUlHa2dQU0F3T3lCcElEd2diR1Z1WjNSb095QnBLeXNwSUh0Y2JpQWdJQ0IyWVhJZ2NHRnljMlZrSUQwZ2NHRnljMlZKYm5Rb2MzUnlhVzVuTG5OMVluTjBjaWhwSUNvZ01pd2dNaWtzSURFMktWeHVJQ0FnSUdsbUlDaHBjMDVoVGlod1lYSnpaV1FwS1NCMGFISnZkeUJ1WlhjZ1JYSnliM0lvSjBsdWRtRnNhV1FnYUdWNElITjBjbWx1WnljcFhHNGdJQ0FnWW5WbVcyOW1abk5sZENBcklHbGRJRDBnY0dGeWMyVmtYRzRnSUgxY2JpQWdjbVYwZFhKdUlHbGNibjFjYmx4dVpuVnVZM1JwYjI0Z2RYUm1PRmR5YVhSbElDaGlkV1lzSUhOMGNtbHVaeXdnYjJabWMyVjBMQ0JzWlc1bmRHZ3BJSHRjYmlBZ2NtVjBkWEp1SUdKc2FYUkNkV1ptWlhJb2RYUm1PRlJ2UW5sMFpYTW9jM1J5YVc1bkxDQmlkV1l1YkdWdVozUm9JQzBnYjJabWMyVjBLU3dnWW5WbUxDQnZabVp6WlhRc0lHeGxibWQwYUNsY2JuMWNibHh1Wm5WdVkzUnBiMjRnWVhOamFXbFhjbWwwWlNBb1luVm1MQ0J6ZEhKcGJtY3NJRzltWm5ObGRDd2diR1Z1WjNSb0tTQjdYRzRnSUhKbGRIVnliaUJpYkdsMFFuVm1abVZ5S0dGelkybHBWRzlDZVhSbGN5aHpkSEpwYm1jcExDQmlkV1lzSUc5bVpuTmxkQ3dnYkdWdVozUm9LVnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQmlhVzVoY25sWGNtbDBaU0FvWW5WbUxDQnpkSEpwYm1jc0lHOW1abk5sZEN3Z2JHVnVaM1JvS1NCN1hHNGdJSEpsZEhWeWJpQmhjMk5wYVZkeWFYUmxLR0oxWml3Z2MzUnlhVzVuTENCdlptWnpaWFFzSUd4bGJtZDBhQ2xjYm4xY2JseHVablZ1WTNScGIyNGdZbUZ6WlRZMFYzSnBkR1VnS0dKMVppd2djM1J5YVc1bkxDQnZabVp6WlhRc0lHeGxibWQwYUNrZ2UxeHVJQ0J5WlhSMWNtNGdZbXhwZEVKMVptWmxjaWhpWVhObE5qUlViMEo1ZEdWektITjBjbWx1Wnlrc0lHSjFaaXdnYjJabWMyVjBMQ0JzWlc1bmRHZ3BYRzU5WEc1Y2JtWjFibU4wYVc5dUlIVmpjekpYY21sMFpTQW9ZblZtTENCemRISnBibWNzSUc5bVpuTmxkQ3dnYkdWdVozUm9LU0I3WEc0Z0lISmxkSFZ5YmlCaWJHbDBRblZtWm1WeUtIVjBaakUyYkdWVWIwSjVkR1Z6S0hOMGNtbHVaeXdnWW5WbUxteGxibWQwYUNBdElHOW1abk5sZENrc0lHSjFaaXdnYjJabWMyVjBMQ0JzWlc1bmRHZ3BYRzU5WEc1Y2JrSjFabVpsY2k1d2NtOTBiM1I1Y0dVdWQzSnBkR1VnUFNCbWRXNWpkR2x2YmlCM2NtbDBaU0FvYzNSeWFXNW5MQ0J2Wm1aelpYUXNJR3hsYm1kMGFDd2daVzVqYjJScGJtY3BJSHRjYmlBZ0x5OGdRblZtWm1WeUkzZHlhWFJsS0hOMGNtbHVaeWxjYmlBZ2FXWWdLRzltWm5ObGRDQTlQVDBnZFc1a1pXWnBibVZrS1NCN1hHNGdJQ0FnWlc1amIyUnBibWNnUFNBbmRYUm1PQ2RjYmlBZ0lDQnNaVzVuZEdnZ1BTQjBhR2x6TG14bGJtZDBhRnh1SUNBZ0lHOW1abk5sZENBOUlEQmNiaUFnTHk4Z1FuVm1abVZ5STNkeWFYUmxLSE4wY21sdVp5d2daVzVqYjJScGJtY3BYRzRnSUgwZ1pXeHpaU0JwWmlBb2JHVnVaM1JvSUQwOVBTQjFibVJsWm1sdVpXUWdKaVlnZEhsd1pXOW1JRzltWm5ObGRDQTlQVDBnSjNOMGNtbHVaeWNwSUh0Y2JpQWdJQ0JsYm1OdlpHbHVaeUE5SUc5bVpuTmxkRnh1SUNBZ0lHeGxibWQwYUNBOUlIUm9hWE11YkdWdVozUm9YRzRnSUNBZ2IyWm1jMlYwSUQwZ01GeHVJQ0F2THlCQ2RXWm1aWElqZDNKcGRHVW9jM1J5YVc1bkxDQnZabVp6WlhSYkxDQnNaVzVuZEdoZFd5d2daVzVqYjJScGJtZGRLVnh1SUNCOUlHVnNjMlVnYVdZZ0tHbHpSbWx1YVhSbEtHOW1abk5sZENrcElIdGNiaUFnSUNCdlptWnpaWFFnUFNCdlptWnpaWFFnZkNBd1hHNGdJQ0FnYVdZZ0tHbHpSbWx1YVhSbEtHeGxibWQwYUNrcElIdGNiaUFnSUNBZ0lHeGxibWQwYUNBOUlHeGxibWQwYUNCOElEQmNiaUFnSUNBZ0lHbG1JQ2hsYm1OdlpHbHVaeUE5UFQwZ2RXNWtaV1pwYm1Wa0tTQmxibU52WkdsdVp5QTlJQ2QxZEdZNEoxeHVJQ0FnSUgwZ1pXeHpaU0I3WEc0Z0lDQWdJQ0JsYm1OdlpHbHVaeUE5SUd4bGJtZDBhRnh1SUNBZ0lDQWdiR1Z1WjNSb0lEMGdkVzVrWldacGJtVmtYRzRnSUNBZ2ZWeHVJQ0F2THlCc1pXZGhZM2tnZDNKcGRHVW9jM1J5YVc1bkxDQmxibU52WkdsdVp5d2diMlptYzJWMExDQnNaVzVuZEdncElDMGdjbVZ0YjNabElHbHVJSFl3TGpFelhHNGdJSDBnWld4elpTQjdYRzRnSUNBZ2RtRnlJSE4zWVhBZ1BTQmxibU52WkdsdVoxeHVJQ0FnSUdWdVkyOWthVzVuSUQwZ2IyWm1jMlYwWEc0Z0lDQWdiMlptYzJWMElEMGdiR1Z1WjNSb0lId2dNRnh1SUNBZ0lHeGxibWQwYUNBOUlITjNZWEJjYmlBZ2ZWeHVYRzRnSUhaaGNpQnlaVzFoYVc1cGJtY2dQU0IwYUdsekxteGxibWQwYUNBdElHOW1abk5sZEZ4dUlDQnBaaUFvYkdWdVozUm9JRDA5UFNCMWJtUmxabWx1WldRZ2ZId2diR1Z1WjNSb0lENGdjbVZ0WVdsdWFXNW5LU0JzWlc1bmRHZ2dQU0J5WlcxaGFXNXBibWRjYmx4dUlDQnBaaUFvS0hOMGNtbHVaeTVzWlc1bmRHZ2dQaUF3SUNZbUlDaHNaVzVuZEdnZ1BDQXdJSHg4SUc5bVpuTmxkQ0E4SURBcEtTQjhmQ0J2Wm1aelpYUWdQaUIwYUdsekxteGxibWQwYUNrZ2UxeHVJQ0FnSUhSb2NtOTNJRzVsZHlCU1lXNW5aVVZ5Y205eUtDZGhkSFJsYlhCMElIUnZJSGR5YVhSbElHOTFkSE5wWkdVZ1luVm1abVZ5SUdKdmRXNWtjeWNwWEc0Z0lIMWNibHh1SUNCcFppQW9JV1Z1WTI5a2FXNW5LU0JsYm1OdlpHbHVaeUE5SUNkMWRHWTRKMXh1WEc0Z0lIWmhjaUJzYjNkbGNtVmtRMkZ6WlNBOUlHWmhiSE5sWEc0Z0lHWnZjaUFvT3pzcElIdGNiaUFnSUNCemQybDBZMmdnS0dWdVkyOWthVzVuS1NCN1hHNGdJQ0FnSUNCallYTmxJQ2RvWlhnbk9seHVJQ0FnSUNBZ0lDQnlaWFIxY200Z2FHVjRWM0pwZEdVb2RHaHBjeXdnYzNSeWFXNW5MQ0J2Wm1aelpYUXNJR3hsYm1kMGFDbGNibHh1SUNBZ0lDQWdZMkZ6WlNBbmRYUm1PQ2M2WEc0Z0lDQWdJQ0JqWVhObElDZDFkR1l0T0NjNlhHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCMWRHWTRWM0pwZEdVb2RHaHBjeXdnYzNSeWFXNW5MQ0J2Wm1aelpYUXNJR3hsYm1kMGFDbGNibHh1SUNBZ0lDQWdZMkZ6WlNBbllYTmphV2tuT2x4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWVhOamFXbFhjbWwwWlNoMGFHbHpMQ0J6ZEhKcGJtY3NJRzltWm5ObGRDd2diR1Z1WjNSb0tWeHVYRzRnSUNBZ0lDQmpZWE5sSUNkaWFXNWhjbmtuT2x4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWW1sdVlYSjVWM0pwZEdVb2RHaHBjeXdnYzNSeWFXNW5MQ0J2Wm1aelpYUXNJR3hsYm1kMGFDbGNibHh1SUNBZ0lDQWdZMkZ6WlNBblltRnpaVFkwSnpwY2JpQWdJQ0FnSUNBZ0x5OGdWMkZ5Ym1sdVp6b2diV0Y0VEdWdVozUm9JRzV2ZENCMFlXdGxiaUJwYm5SdklHRmpZMjkxYm5RZ2FXNGdZbUZ6WlRZMFYzSnBkR1ZjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJR0poYzJVMk5GZHlhWFJsS0hSb2FYTXNJSE4wY21sdVp5d2diMlptYzJWMExDQnNaVzVuZEdncFhHNWNiaUFnSUNBZ0lHTmhjMlVnSjNWamN6SW5PbHh1SUNBZ0lDQWdZMkZ6WlNBbmRXTnpMVEluT2x4dUlDQWdJQ0FnWTJGelpTQW5kWFJtTVRac1pTYzZYRzRnSUNBZ0lDQmpZWE5sSUNkMWRHWXRNVFpzWlNjNlhHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCMVkzTXlWM0pwZEdVb2RHaHBjeXdnYzNSeWFXNW5MQ0J2Wm1aelpYUXNJR3hsYm1kMGFDbGNibHh1SUNBZ0lDQWdaR1ZtWVhWc2REcGNiaUFnSUNBZ0lDQWdhV1lnS0d4dmQyVnlaV1JEWVhObEtTQjBhSEp2ZHlCdVpYY2dWSGx3WlVWeWNtOXlLQ2RWYm10dWIzZHVJR1Z1WTI5a2FXNW5PaUFuSUNzZ1pXNWpiMlJwYm1jcFhHNGdJQ0FnSUNBZ0lHVnVZMjlrYVc1bklEMGdLQ2NuSUNzZ1pXNWpiMlJwYm1jcExuUnZURzkzWlhKRFlYTmxLQ2xjYmlBZ0lDQWdJQ0FnYkc5M1pYSmxaRU5oYzJVZ1BTQjBjblZsWEc0Z0lDQWdmVnh1SUNCOVhHNTlYRzVjYmtKMVptWmxjaTV3Y205MGIzUjVjR1V1ZEc5S1UwOU9JRDBnWm5WdVkzUnBiMjRnZEc5S1UwOU9JQ2dwSUh0Y2JpQWdjbVYwZFhKdUlIdGNiaUFnSUNCMGVYQmxPaUFuUW5WbVptVnlKeXhjYmlBZ0lDQmtZWFJoT2lCQmNuSmhlUzV3Y205MGIzUjVjR1V1YzJ4cFkyVXVZMkZzYkNoMGFHbHpMbDloY25JZ2ZId2dkR2hwY3l3Z01DbGNiaUFnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJpWVhObE5qUlRiR2xqWlNBb1luVm1MQ0J6ZEdGeWRDd2daVzVrS1NCN1hHNGdJR2xtSUNoemRHRnlkQ0E5UFQwZ01DQW1KaUJsYm1RZ1BUMDlJR0oxWmk1c1pXNW5kR2dwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdZbUZ6WlRZMExtWnliMjFDZVhSbFFYSnlZWGtvWW5WbUtWeHVJQ0I5SUdWc2MyVWdlMXh1SUNBZ0lISmxkSFZ5YmlCaVlYTmxOalF1Wm5KdmJVSjVkR1ZCY25KaGVTaGlkV1l1YzJ4cFkyVW9jM1JoY25Rc0lHVnVaQ2twWEc0Z0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z2RYUm1PRk5zYVdObElDaGlkV1lzSUhOMFlYSjBMQ0JsYm1RcElIdGNiaUFnWlc1a0lEMGdUV0YwYUM1dGFXNG9ZblZtTG14bGJtZDBhQ3dnWlc1a0tWeHVJQ0IyWVhJZ2NtVnpJRDBnVzExY2JseHVJQ0IyWVhJZ2FTQTlJSE4wWVhKMFhHNGdJSGRvYVd4bElDaHBJRHdnWlc1a0tTQjdYRzRnSUNBZ2RtRnlJR1pwY25OMFFubDBaU0E5SUdKMVpsdHBYVnh1SUNBZ0lIWmhjaUJqYjJSbFVHOXBiblFnUFNCdWRXeHNYRzRnSUNBZ2RtRnlJR0o1ZEdWelVHVnlVMlZ4ZFdWdVkyVWdQU0FvWm1seWMzUkNlWFJsSUQ0Z01IaEZSaWtnUHlBMFhHNGdJQ0FnSUNBNklDaG1hWEp6ZEVKNWRHVWdQaUF3ZUVSR0tTQS9JRE5jYmlBZ0lDQWdJRG9nS0dacGNuTjBRbmwwWlNBK0lEQjRRa1lwSUQ4Z01seHVJQ0FnSUNBZ09pQXhYRzVjYmlBZ0lDQnBaaUFvYVNBcklHSjVkR1Z6VUdWeVUyVnhkV1Z1WTJVZ1BEMGdaVzVrS1NCN1hHNGdJQ0FnSUNCMllYSWdjMlZqYjI1a1FubDBaU3dnZEdocGNtUkNlWFJsTENCbWIzVnlkR2hDZVhSbExDQjBaVzF3UTI5a1pWQnZhVzUwWEc1Y2JpQWdJQ0FnSUhOM2FYUmphQ0FvWW5sMFpYTlFaWEpUWlhGMVpXNWpaU2tnZTF4dUlDQWdJQ0FnSUNCallYTmxJREU2WEc0Z0lDQWdJQ0FnSUNBZ2FXWWdLR1pwY25OMFFubDBaU0E4SURCNE9EQXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHTnZaR1ZRYjJsdWRDQTlJR1pwY25OMFFubDBaVnh1SUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ0lDQmljbVZoYTF4dUlDQWdJQ0FnSUNCallYTmxJREk2WEc0Z0lDQWdJQ0FnSUNBZ2MyVmpiMjVrUW5sMFpTQTlJR0oxWmx0cElDc2dNVjFjYmlBZ0lDQWdJQ0FnSUNCcFppQW9LSE5sWTI5dVpFSjVkR1VnSmlBd2VFTXdLU0E5UFQwZ01IZzRNQ2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdkR1Z0Y0VOdlpHVlFiMmx1ZENBOUlDaG1hWEp6ZEVKNWRHVWdKaUF3ZURGR0tTQThQQ0F3ZURZZ2ZDQW9jMlZqYjI1a1FubDBaU0FtSURCNE0wWXBYRzRnSUNBZ0lDQWdJQ0FnSUNCcFppQW9kR1Z0Y0VOdlpHVlFiMmx1ZENBK0lEQjROMFlwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnWTI5a1pWQnZhVzUwSUQwZ2RHVnRjRU52WkdWUWIybHVkRnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNCaWNtVmhhMXh1SUNBZ0lDQWdJQ0JqWVhObElETTZYRzRnSUNBZ0lDQWdJQ0FnYzJWamIyNWtRbmwwWlNBOUlHSjFabHRwSUNzZ01WMWNiaUFnSUNBZ0lDQWdJQ0IwYUdseVpFSjVkR1VnUFNCaWRXWmJhU0FySURKZFhHNGdJQ0FnSUNBZ0lDQWdhV1lnS0NoelpXTnZibVJDZVhSbElDWWdNSGhETUNrZ1BUMDlJREI0T0RBZ0ppWWdLSFJvYVhKa1FubDBaU0FtSURCNFF6QXBJRDA5UFNBd2VEZ3dLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQjBaVzF3UTI5a1pWQnZhVzUwSUQwZ0tHWnBjbk4wUW5sMFpTQW1JREI0UmlrZ1BEd2dNSGhESUh3Z0tITmxZMjl1WkVKNWRHVWdKaUF3ZUROR0tTQThQQ0F3ZURZZ2ZDQW9kR2hwY21SQ2VYUmxJQ1lnTUhnelJpbGNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDaDBaVzF3UTI5a1pWQnZhVzUwSUQ0Z01IZzNSa1lnSmlZZ0tIUmxiWEJEYjJSbFVHOXBiblFnUENBd2VFUTRNREFnZkh3Z2RHVnRjRU52WkdWUWIybHVkQ0ErSURCNFJFWkdSaWtwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnWTI5a1pWQnZhVzUwSUQwZ2RHVnRjRU52WkdWUWIybHVkRnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNCaWNtVmhhMXh1SUNBZ0lDQWdJQ0JqWVhObElEUTZYRzRnSUNBZ0lDQWdJQ0FnYzJWamIyNWtRbmwwWlNBOUlHSjFabHRwSUNzZ01WMWNiaUFnSUNBZ0lDQWdJQ0IwYUdseVpFSjVkR1VnUFNCaWRXWmJhU0FySURKZFhHNGdJQ0FnSUNBZ0lDQWdabTkxY25Sb1FubDBaU0E5SUdKMVpsdHBJQ3NnTTExY2JpQWdJQ0FnSUNBZ0lDQnBaaUFvS0hObFkyOXVaRUo1ZEdVZ0ppQXdlRU13S1NBOVBUMGdNSGc0TUNBbUppQW9kR2hwY21SQ2VYUmxJQ1lnTUhoRE1Da2dQVDA5SURCNE9EQWdKaVlnS0dadmRYSjBhRUo1ZEdVZ0ppQXdlRU13S1NBOVBUMGdNSGc0TUNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZEdWdGNFTnZaR1ZRYjJsdWRDQTlJQ2htYVhKemRFSjVkR1VnSmlBd2VFWXBJRHc4SURCNE1USWdmQ0FvYzJWamIyNWtRbmwwWlNBbUlEQjRNMFlwSUR3OElEQjRReUI4SUNoMGFHbHlaRUo1ZEdVZ0ppQXdlRE5HS1NBOFBDQXdlRFlnZkNBb1ptOTFjblJvUW5sMFpTQW1JREI0TTBZcFhHNGdJQ0FnSUNBZ0lDQWdJQ0JwWmlBb2RHVnRjRU52WkdWUWIybHVkQ0ErSURCNFJrWkdSaUFtSmlCMFpXMXdRMjlrWlZCdmFXNTBJRHdnTUhneE1UQXdNREFwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnWTI5a1pWQnZhVzUwSUQwZ2RHVnRjRU52WkdWUWIybHVkRnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQnBaaUFvWTI5a1pWQnZhVzUwSUQwOVBTQnVkV3hzS1NCN1hHNGdJQ0FnSUNBdkx5QjNaU0JrYVdRZ2JtOTBJR2RsYm1WeVlYUmxJR0VnZG1Gc2FXUWdZMjlrWlZCdmFXNTBJSE52SUdsdWMyVnlkQ0JoWEc0Z0lDQWdJQ0F2THlCeVpYQnNZV05sYldWdWRDQmphR0Z5SUNoVkswWkdSa1FwSUdGdVpDQmhaSFpoYm1ObElHOXViSGtnTVNCaWVYUmxYRzRnSUNBZ0lDQmpiMlJsVUc5cGJuUWdQU0F3ZUVaR1JrUmNiaUFnSUNBZ0lHSjVkR1Z6VUdWeVUyVnhkV1Z1WTJVZ1BTQXhYRzRnSUNBZ2ZTQmxiSE5sSUdsbUlDaGpiMlJsVUc5cGJuUWdQaUF3ZUVaR1JrWXBJSHRjYmlBZ0lDQWdJQzh2SUdWdVkyOWtaU0IwYnlCMWRHWXhOaUFvYzNWeWNtOW5ZWFJsSUhCaGFYSWdaR0Z1WTJVcFhHNGdJQ0FnSUNCamIyUmxVRzlwYm5RZ0xUMGdNSGd4TURBd01GeHVJQ0FnSUNBZ2NtVnpMbkIxYzJnb1kyOWtaVkJ2YVc1MElENCtQaUF4TUNBbUlEQjRNMFpHSUh3Z01IaEVPREF3S1Z4dUlDQWdJQ0FnWTI5a1pWQnZhVzUwSUQwZ01IaEVRekF3SUh3Z1kyOWtaVkJ2YVc1MElDWWdNSGd6UmtaY2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhNdWNIVnphQ2hqYjJSbFVHOXBiblFwWEc0Z0lDQWdhU0FyUFNCaWVYUmxjMUJsY2xObGNYVmxibU5sWEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnWkdWamIyUmxRMjlrWlZCdmFXNTBjMEZ5Y21GNUtISmxjeWxjYm4xY2JseHVMeThnUW1GelpXUWdiMjRnYUhSMGNEb3ZMM04wWVdOcmIzWmxjbVpzYjNjdVkyOXRMMkV2TWpJM05EY3lOekl2Tmpnd056UXlMQ0IwYUdVZ1luSnZkM05sY2lCM2FYUm9YRzR2THlCMGFHVWdiRzkzWlhOMElHeHBiV2wwSUdseklFTm9jbTl0WlN3Z2QybDBhQ0F3ZURFd01EQXdJR0Z5WjNNdVhHNHZMeUJYWlNCbmJ5QXhJRzFoWjI1cGRIVmtaU0JzWlhOekxDQm1iM0lnYzJGbVpYUjVYRzUyWVhJZ1RVRllYMEZTUjFWTlJVNVVVMTlNUlU1SFZFZ2dQU0F3ZURFd01EQmNibHh1Wm5WdVkzUnBiMjRnWkdWamIyUmxRMjlrWlZCdmFXNTBjMEZ5Y21GNUlDaGpiMlJsVUc5cGJuUnpLU0I3WEc0Z0lIWmhjaUJzWlc0Z1BTQmpiMlJsVUc5cGJuUnpMbXhsYm1kMGFGeHVJQ0JwWmlBb2JHVnVJRHc5SUUxQldGOUJVa2RWVFVWT1ZGTmZURVZPUjFSSUtTQjdYRzRnSUNBZ2NtVjBkWEp1SUZOMGNtbHVaeTVtY205dFEyaGhja052WkdVdVlYQndiSGtvVTNSeWFXNW5MQ0JqYjJSbFVHOXBiblJ6S1NBdkx5QmhkbTlwWkNCbGVIUnlZU0J6YkdsalpTZ3BYRzRnSUgxY2JseHVJQ0F2THlCRVpXTnZaR1VnYVc0Z1kyaDFibXR6SUhSdklHRjJiMmxrSUZ3aVkyRnNiQ0J6ZEdGamF5QnphWHBsSUdWNFkyVmxaR1ZrWENJdVhHNGdJSFpoY2lCeVpYTWdQU0FuSjF4dUlDQjJZWElnYVNBOUlEQmNiaUFnZDJocGJHVWdLR2tnUENCc1pXNHBJSHRjYmlBZ0lDQnlaWE1nS3owZ1UzUnlhVzVuTG1aeWIyMURhR0Z5UTI5a1pTNWhjSEJzZVNoY2JpQWdJQ0FnSUZOMGNtbHVaeXhjYmlBZ0lDQWdJR052WkdWUWIybHVkSE11YzJ4cFkyVW9hU3dnYVNBclBTQk5RVmhmUVZKSFZVMUZUbFJUWDB4RlRrZFVTQ2xjYmlBZ0lDQXBYRzRnSUgxY2JpQWdjbVYwZFhKdUlISmxjMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQmhjMk5wYVZOc2FXTmxJQ2hpZFdZc0lITjBZWEowTENCbGJtUXBJSHRjYmlBZ2RtRnlJSEpsZENBOUlDY25YRzRnSUdWdVpDQTlJRTFoZEdndWJXbHVLR0oxWmk1c1pXNW5kR2dzSUdWdVpDbGNibHh1SUNCbWIzSWdLSFpoY2lCcElEMGdjM1JoY25RN0lHa2dQQ0JsYm1RN0lHa3JLeWtnZTF4dUlDQWdJSEpsZENBclBTQlRkSEpwYm1jdVpuSnZiVU5vWVhKRGIyUmxLR0oxWmx0cFhTQW1JREI0TjBZcFhHNGdJSDFjYmlBZ2NtVjBkWEp1SUhKbGRGeHVmVnh1WEc1bWRXNWpkR2x2YmlCaWFXNWhjbmxUYkdsalpTQW9ZblZtTENCemRHRnlkQ3dnWlc1a0tTQjdYRzRnSUhaaGNpQnlaWFFnUFNBbkoxeHVJQ0JsYm1RZ1BTQk5ZWFJvTG0xcGJpaGlkV1l1YkdWdVozUm9MQ0JsYm1RcFhHNWNiaUFnWm05eUlDaDJZWElnYVNBOUlITjBZWEowT3lCcElEd2daVzVrT3lCcEt5c3BJSHRjYmlBZ0lDQnlaWFFnS3owZ1UzUnlhVzVuTG1aeWIyMURhR0Z5UTI5a1pTaGlkV1piYVYwcFhHNGdJSDFjYmlBZ2NtVjBkWEp1SUhKbGRGeHVmVnh1WEc1bWRXNWpkR2x2YmlCb1pYaFRiR2xqWlNBb1luVm1MQ0J6ZEdGeWRDd2daVzVrS1NCN1hHNGdJSFpoY2lCc1pXNGdQU0JpZFdZdWJHVnVaM1JvWEc1Y2JpQWdhV1lnS0NGemRHRnlkQ0I4ZkNCemRHRnlkQ0E4SURBcElITjBZWEowSUQwZ01GeHVJQ0JwWmlBb0lXVnVaQ0I4ZkNCbGJtUWdQQ0F3SUh4OElHVnVaQ0ErSUd4bGJpa2daVzVrSUQwZ2JHVnVYRzVjYmlBZ2RtRnlJRzkxZENBOUlDY25YRzRnSUdadmNpQW9kbUZ5SUdrZ1BTQnpkR0Z5ZERzZ2FTQThJR1Z1WkRzZ2FTc3JLU0I3WEc0Z0lDQWdiM1YwSUNzOUlIUnZTR1Y0S0dKMVpsdHBYU2xjYmlBZ2ZWeHVJQ0J5WlhSMWNtNGdiM1YwWEc1OVhHNWNibVoxYm1OMGFXOXVJSFYwWmpFMmJHVlRiR2xqWlNBb1luVm1MQ0J6ZEdGeWRDd2daVzVrS1NCN1hHNGdJSFpoY2lCaWVYUmxjeUE5SUdKMVppNXpiR2xqWlNoemRHRnlkQ3dnWlc1a0tWeHVJQ0IyWVhJZ2NtVnpJRDBnSnlkY2JpQWdabTl5SUNoMllYSWdhU0E5SURBN0lHa2dQQ0JpZVhSbGN5NXNaVzVuZEdnN0lHa2dLejBnTWlrZ2UxeHVJQ0FnSUhKbGN5QXJQU0JUZEhKcGJtY3Vabkp2YlVOb1lYSkRiMlJsS0dKNWRHVnpXMmxkSUNzZ1lubDBaWE5iYVNBcklERmRJQ29nTWpVMktWeHVJQ0I5WEc0Z0lISmxkSFZ5YmlCeVpYTmNibjFjYmx4dVFuVm1abVZ5TG5CeWIzUnZkSGx3WlM1emJHbGpaU0E5SUdaMWJtTjBhVzl1SUhOc2FXTmxJQ2h6ZEdGeWRDd2daVzVrS1NCN1hHNGdJSFpoY2lCc1pXNGdQU0IwYUdsekxteGxibWQwYUZ4dUlDQnpkR0Z5ZENBOUlINStjM1JoY25SY2JpQWdaVzVrSUQwZ1pXNWtJRDA5UFNCMWJtUmxabWx1WldRZ1B5QnNaVzRnT2lCK2ZtVnVaRnh1WEc0Z0lHbG1JQ2h6ZEdGeWRDQThJREFwSUh0Y2JpQWdJQ0J6ZEdGeWRDQXJQU0JzWlc1Y2JpQWdJQ0JwWmlBb2MzUmhjblFnUENBd0tTQnpkR0Z5ZENBOUlEQmNiaUFnZlNCbGJITmxJR2xtSUNoemRHRnlkQ0ErSUd4bGJpa2dlMXh1SUNBZ0lITjBZWEowSUQwZ2JHVnVYRzRnSUgxY2JseHVJQ0JwWmlBb1pXNWtJRHdnTUNrZ2UxeHVJQ0FnSUdWdVpDQXJQU0JzWlc1Y2JpQWdJQ0JwWmlBb1pXNWtJRHdnTUNrZ1pXNWtJRDBnTUZ4dUlDQjlJR1ZzYzJVZ2FXWWdLR1Z1WkNBK0lHeGxiaWtnZTF4dUlDQWdJR1Z1WkNBOUlHeGxibHh1SUNCOVhHNWNiaUFnYVdZZ0tHVnVaQ0E4SUhOMFlYSjBLU0JsYm1RZ1BTQnpkR0Z5ZEZ4dVhHNGdJSFpoY2lCdVpYZENkV1pjYmlBZ2FXWWdLRUoxWm1abGNpNVVXVkJGUkY5QlVsSkJXVjlUVlZCUVQxSlVLU0I3WEc0Z0lDQWdibVYzUW5WbUlEMGdRblZtWm1WeUxsOWhkV2R0Wlc1MEtIUm9hWE11YzNWaVlYSnlZWGtvYzNSaGNuUXNJR1Z1WkNrcFhHNGdJSDBnWld4elpTQjdYRzRnSUNBZ2RtRnlJSE5zYVdObFRHVnVJRDBnWlc1a0lDMGdjM1JoY25SY2JpQWdJQ0J1WlhkQ2RXWWdQU0J1WlhjZ1FuVm1abVZ5S0hOc2FXTmxUR1Z1TENCMWJtUmxabWx1WldRcFhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCemJHbGpaVXhsYmpzZ2FTc3JLU0I3WEc0Z0lDQWdJQ0J1WlhkQ2RXWmJhVjBnUFNCMGFHbHpXMmtnS3lCemRHRnlkRjFjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0JwWmlBb2JtVjNRblZtTG14bGJtZDBhQ2tnYm1WM1FuVm1MbkJoY21WdWRDQTlJSFJvYVhNdWNHRnlaVzUwSUh4OElIUm9hWE5jYmx4dUlDQnlaWFIxY200Z2JtVjNRblZtWEc1OVhHNWNiaThxWEc0Z0tpQk9aV1ZrSUhSdklHMWhhMlVnYzNWeVpTQjBhR0YwSUdKMVptWmxjaUJwYzI0bmRDQjBjbmxwYm1jZ2RHOGdkM0pwZEdVZ2IzVjBJRzltSUdKdmRXNWtjeTVjYmlBcUwxeHVablZ1WTNScGIyNGdZMmhsWTJ0UFptWnpaWFFnS0c5bVpuTmxkQ3dnWlhoMExDQnNaVzVuZEdncElIdGNiaUFnYVdZZ0tDaHZabVp6WlhRZ0pTQXhLU0FoUFQwZ01DQjhmQ0J2Wm1aelpYUWdQQ0F3S1NCMGFISnZkeUJ1WlhjZ1VtRnVaMlZGY25KdmNpZ25iMlptYzJWMElHbHpJRzV2ZENCMWFXNTBKeWxjYmlBZ2FXWWdLRzltWm5ObGRDQXJJR1Y0ZENBK0lHeGxibWQwYUNrZ2RHaHliM2NnYm1WM0lGSmhibWRsUlhKeWIzSW9KMVJ5ZVdsdVp5QjBieUJoWTJObGMzTWdZbVY1YjI1a0lHSjFabVpsY2lCc1pXNW5kR2duS1Z4dWZWeHVYRzVDZFdabVpYSXVjSEp2ZEc5MGVYQmxMbkpsWVdSVlNXNTBURVVnUFNCbWRXNWpkR2x2YmlCeVpXRmtWVWx1ZEV4RklDaHZabVp6WlhRc0lHSjVkR1ZNWlc1bmRHZ3NJRzV2UVhOelpYSjBLU0I3WEc0Z0lHOW1abk5sZENBOUlHOW1abk5sZENCOElEQmNiaUFnWW5sMFpVeGxibWQwYUNBOUlHSjVkR1ZNWlc1bmRHZ2dmQ0F3WEc0Z0lHbG1JQ2doYm05QmMzTmxjblFwSUdOb1pXTnJUMlptYzJWMEtHOW1abk5sZEN3Z1lubDBaVXhsYm1kMGFDd2dkR2hwY3k1c1pXNW5kR2dwWEc1Y2JpQWdkbUZ5SUhaaGJDQTlJSFJvYVhOYmIyWm1jMlYwWFZ4dUlDQjJZWElnYlhWc0lEMGdNVnh1SUNCMllYSWdhU0E5SURCY2JpQWdkMmhwYkdVZ0tDc3JhU0E4SUdKNWRHVk1aVzVuZEdnZ0ppWWdLRzExYkNBcVBTQXdlREV3TUNrcElIdGNiaUFnSUNCMllXd2dLejBnZEdocGMxdHZabVp6WlhRZ0t5QnBYU0FxSUcxMWJGeHVJQ0I5WEc1Y2JpQWdjbVYwZFhKdUlIWmhiRnh1ZlZ4dVhHNUNkV1ptWlhJdWNISnZkRzkwZVhCbExuSmxZV1JWU1c1MFFrVWdQU0JtZFc1amRHbHZiaUJ5WldGa1ZVbHVkRUpGSUNodlptWnpaWFFzSUdKNWRHVk1aVzVuZEdnc0lHNXZRWE56WlhKMEtTQjdYRzRnSUc5bVpuTmxkQ0E5SUc5bVpuTmxkQ0I4SURCY2JpQWdZbmwwWlV4bGJtZDBhQ0E5SUdKNWRHVk1aVzVuZEdnZ2ZDQXdYRzRnSUdsbUlDZ2hibTlCYzNObGNuUXBJSHRjYmlBZ0lDQmphR1ZqYTA5bVpuTmxkQ2h2Wm1aelpYUXNJR0o1ZEdWTVpXNW5kR2dzSUhSb2FYTXViR1Z1WjNSb0tWeHVJQ0I5WEc1Y2JpQWdkbUZ5SUhaaGJDQTlJSFJvYVhOYmIyWm1jMlYwSUNzZ0xTMWllWFJsVEdWdVozUm9YVnh1SUNCMllYSWdiWFZzSUQwZ01WeHVJQ0IzYUdsc1pTQW9ZbmwwWlV4bGJtZDBhQ0ErSURBZ0ppWWdLRzExYkNBcVBTQXdlREV3TUNrcElIdGNiaUFnSUNCMllXd2dLejBnZEdocGMxdHZabVp6WlhRZ0t5QXRMV0o1ZEdWTVpXNW5kR2hkSUNvZ2JYVnNYRzRnSUgxY2JseHVJQ0J5WlhSMWNtNGdkbUZzWEc1OVhHNWNia0oxWm1abGNpNXdjbTkwYjNSNWNHVXVjbVZoWkZWSmJuUTRJRDBnWm5WdVkzUnBiMjRnY21WaFpGVkpiblE0SUNodlptWnpaWFFzSUc1dlFYTnpaWEowS1NCN1hHNGdJR2xtSUNnaGJtOUJjM05sY25RcElHTm9aV05yVDJabWMyVjBLRzltWm5ObGRDd2dNU3dnZEdocGN5NXNaVzVuZEdncFhHNGdJSEpsZEhWeWJpQjBhR2x6VzI5bVpuTmxkRjFjYm4xY2JseHVRblZtWm1WeUxuQnliM1J2ZEhsd1pTNXlaV0ZrVlVsdWRERTJURVVnUFNCbWRXNWpkR2x2YmlCeVpXRmtWVWx1ZERFMlRFVWdLRzltWm5ObGRDd2dibTlCYzNObGNuUXBJSHRjYmlBZ2FXWWdLQ0Z1YjBGemMyVnlkQ2tnWTJobFkydFBabVp6WlhRb2IyWm1jMlYwTENBeUxDQjBhR2x6TG14bGJtZDBhQ2xjYmlBZ2NtVjBkWEp1SUhSb2FYTmJiMlptYzJWMFhTQjhJQ2gwYUdselcyOW1abk5sZENBcklERmRJRHc4SURncFhHNTlYRzVjYmtKMVptWmxjaTV3Y205MGIzUjVjR1V1Y21WaFpGVkpiblF4TmtKRklEMGdablZ1WTNScGIyNGdjbVZoWkZWSmJuUXhOa0pGSUNodlptWnpaWFFzSUc1dlFYTnpaWEowS1NCN1hHNGdJR2xtSUNnaGJtOUJjM05sY25RcElHTm9aV05yVDJabWMyVjBLRzltWm5ObGRDd2dNaXdnZEdocGN5NXNaVzVuZEdncFhHNGdJSEpsZEhWeWJpQW9kR2hwYzF0dlptWnpaWFJkSUR3OElEZ3BJSHdnZEdocGMxdHZabVp6WlhRZ0t5QXhYVnh1ZlZ4dVhHNUNkV1ptWlhJdWNISnZkRzkwZVhCbExuSmxZV1JWU1c1ME16Sk1SU0E5SUdaMWJtTjBhVzl1SUhKbFlXUlZTVzUwTXpKTVJTQW9iMlptYzJWMExDQnViMEZ6YzJWeWRDa2dlMXh1SUNCcFppQW9JVzV2UVhOelpYSjBLU0JqYUdWamEwOW1abk5sZENodlptWnpaWFFzSURRc0lIUm9hWE11YkdWdVozUm9LVnh1WEc0Z0lISmxkSFZ5YmlBb0tIUm9hWE5iYjJabWMyVjBYU2tnZkZ4dUlDQWdJQ0FnS0hSb2FYTmJiMlptYzJWMElDc2dNVjBnUER3Z09Da2dmRnh1SUNBZ0lDQWdLSFJvYVhOYmIyWm1jMlYwSUNzZ01sMGdQRHdnTVRZcEtTQXJYRzRnSUNBZ0lDQW9kR2hwYzF0dlptWnpaWFFnS3lBelhTQXFJREI0TVRBd01EQXdNQ2xjYm4xY2JseHVRblZtWm1WeUxuQnliM1J2ZEhsd1pTNXlaV0ZrVlVsdWRETXlRa1VnUFNCbWRXNWpkR2x2YmlCeVpXRmtWVWx1ZERNeVFrVWdLRzltWm5ObGRDd2dibTlCYzNObGNuUXBJSHRjYmlBZ2FXWWdLQ0Z1YjBGemMyVnlkQ2tnWTJobFkydFBabVp6WlhRb2IyWm1jMlYwTENBMExDQjBhR2x6TG14bGJtZDBhQ2xjYmx4dUlDQnlaWFIxY200Z0tIUm9hWE5iYjJabWMyVjBYU0FxSURCNE1UQXdNREF3TUNrZ0sxeHVJQ0FnSUNnb2RHaHBjMXR2Wm1aelpYUWdLeUF4WFNBOFBDQXhOaWtnZkZ4dUlDQWdJQ2gwYUdselcyOW1abk5sZENBcklESmRJRHc4SURncElIeGNiaUFnSUNCMGFHbHpXMjltWm5ObGRDQXJJRE5kS1Z4dWZWeHVYRzVDZFdabVpYSXVjSEp2ZEc5MGVYQmxMbkpsWVdSSmJuUk1SU0E5SUdaMWJtTjBhVzl1SUhKbFlXUkpiblJNUlNBb2IyWm1jMlYwTENCaWVYUmxUR1Z1WjNSb0xDQnViMEZ6YzJWeWRDa2dlMXh1SUNCdlptWnpaWFFnUFNCdlptWnpaWFFnZkNBd1hHNGdJR0o1ZEdWTVpXNW5kR2dnUFNCaWVYUmxUR1Z1WjNSb0lId2dNRnh1SUNCcFppQW9JVzV2UVhOelpYSjBLU0JqYUdWamEwOW1abk5sZENodlptWnpaWFFzSUdKNWRHVk1aVzVuZEdnc0lIUm9hWE11YkdWdVozUm9LVnh1WEc0Z0lIWmhjaUIyWVd3Z1BTQjBhR2x6VzI5bVpuTmxkRjFjYmlBZ2RtRnlJRzExYkNBOUlERmNiaUFnZG1GeUlHa2dQU0F3WEc0Z0lIZG9hV3hsSUNncksya2dQQ0JpZVhSbFRHVnVaM1JvSUNZbUlDaHRkV3dnS2owZ01IZ3hNREFwS1NCN1hHNGdJQ0FnZG1Gc0lDczlJSFJvYVhOYmIyWm1jMlYwSUNzZ2FWMGdLaUJ0ZFd4Y2JpQWdmVnh1SUNCdGRXd2dLajBnTUhnNE1GeHVYRzRnSUdsbUlDaDJZV3dnUGowZ2JYVnNLU0IyWVd3Z0xUMGdUV0YwYUM1d2IzY29NaXdnT0NBcUlHSjVkR1ZNWlc1bmRHZ3BYRzVjYmlBZ2NtVjBkWEp1SUhaaGJGeHVmVnh1WEc1Q2RXWm1aWEl1Y0hKdmRHOTBlWEJsTG5KbFlXUkpiblJDUlNBOUlHWjFibU4wYVc5dUlISmxZV1JKYm5SQ1JTQW9iMlptYzJWMExDQmllWFJsVEdWdVozUm9MQ0J1YjBGemMyVnlkQ2tnZTF4dUlDQnZabVp6WlhRZ1BTQnZabVp6WlhRZ2ZDQXdYRzRnSUdKNWRHVk1aVzVuZEdnZ1BTQmllWFJsVEdWdVozUm9JSHdnTUZ4dUlDQnBaaUFvSVc1dlFYTnpaWEowS1NCamFHVmphMDltWm5ObGRDaHZabVp6WlhRc0lHSjVkR1ZNWlc1bmRHZ3NJSFJvYVhNdWJHVnVaM1JvS1Z4dVhHNGdJSFpoY2lCcElEMGdZbmwwWlV4bGJtZDBhRnh1SUNCMllYSWdiWFZzSUQwZ01WeHVJQ0IyWVhJZ2RtRnNJRDBnZEdocGMxdHZabVp6WlhRZ0t5QXRMV2xkWEc0Z0lIZG9hV3hsSUNocElENGdNQ0FtSmlBb2JYVnNJQ285SURCNE1UQXdLU2tnZTF4dUlDQWdJSFpoYkNBclBTQjBhR2x6VzI5bVpuTmxkQ0FySUMwdGFWMGdLaUJ0ZFd4Y2JpQWdmVnh1SUNCdGRXd2dLajBnTUhnNE1GeHVYRzRnSUdsbUlDaDJZV3dnUGowZ2JYVnNLU0IyWVd3Z0xUMGdUV0YwYUM1d2IzY29NaXdnT0NBcUlHSjVkR1ZNWlc1bmRHZ3BYRzVjYmlBZ2NtVjBkWEp1SUhaaGJGeHVmVnh1WEc1Q2RXWm1aWEl1Y0hKdmRHOTBlWEJsTG5KbFlXUkpiblE0SUQwZ1puVnVZM1JwYjI0Z2NtVmhaRWx1ZERnZ0tHOW1abk5sZEN3Z2JtOUJjM05sY25RcElIdGNiaUFnYVdZZ0tDRnViMEZ6YzJWeWRDa2dZMmhsWTJ0UFptWnpaWFFvYjJabWMyVjBMQ0F4TENCMGFHbHpMbXhsYm1kMGFDbGNiaUFnYVdZZ0tDRW9kR2hwYzF0dlptWnpaWFJkSUNZZ01IZzRNQ2twSUhKbGRIVnliaUFvZEdocGMxdHZabVp6WlhSZEtWeHVJQ0J5WlhSMWNtNGdLQ2d3ZUdabUlDMGdkR2hwYzF0dlptWnpaWFJkSUNzZ01Ta2dLaUF0TVNsY2JuMWNibHh1UW5WbVptVnlMbkJ5YjNSdmRIbHdaUzV5WldGa1NXNTBNVFpNUlNBOUlHWjFibU4wYVc5dUlISmxZV1JKYm5ReE5reEZJQ2h2Wm1aelpYUXNJRzV2UVhOelpYSjBLU0I3WEc0Z0lHbG1JQ2doYm05QmMzTmxjblFwSUdOb1pXTnJUMlptYzJWMEtHOW1abk5sZEN3Z01pd2dkR2hwY3k1c1pXNW5kR2dwWEc0Z0lIWmhjaUIyWVd3Z1BTQjBhR2x6VzI5bVpuTmxkRjBnZkNBb2RHaHBjMXR2Wm1aelpYUWdLeUF4WFNBOFBDQTRLVnh1SUNCeVpYUjFjbTRnS0haaGJDQW1JREI0T0RBd01Da2dQeUIyWVd3Z2ZDQXdlRVpHUmtZd01EQXdJRG9nZG1Gc1hHNTlYRzVjYmtKMVptWmxjaTV3Y205MGIzUjVjR1V1Y21WaFpFbHVkREUyUWtVZ1BTQm1kVzVqZEdsdmJpQnlaV0ZrU1c1ME1UWkNSU0FvYjJabWMyVjBMQ0J1YjBGemMyVnlkQ2tnZTF4dUlDQnBaaUFvSVc1dlFYTnpaWEowS1NCamFHVmphMDltWm5ObGRDaHZabVp6WlhRc0lESXNJSFJvYVhNdWJHVnVaM1JvS1Z4dUlDQjJZWElnZG1Gc0lEMGdkR2hwYzF0dlptWnpaWFFnS3lBeFhTQjhJQ2gwYUdselcyOW1abk5sZEYwZ1BEd2dPQ2xjYmlBZ2NtVjBkWEp1SUNoMllXd2dKaUF3ZURnd01EQXBJRDhnZG1Gc0lId2dNSGhHUmtaR01EQXdNQ0E2SUhaaGJGeHVmVnh1WEc1Q2RXWm1aWEl1Y0hKdmRHOTBlWEJsTG5KbFlXUkpiblF6TWt4RklEMGdablZ1WTNScGIyNGdjbVZoWkVsdWRETXlURVVnS0c5bVpuTmxkQ3dnYm05QmMzTmxjblFwSUh0Y2JpQWdhV1lnS0NGdWIwRnpjMlZ5ZENrZ1kyaGxZMnRQWm1aelpYUW9iMlptYzJWMExDQTBMQ0IwYUdsekxteGxibWQwYUNsY2JseHVJQ0J5WlhSMWNtNGdLSFJvYVhOYmIyWm1jMlYwWFNrZ2ZGeHVJQ0FnSUNoMGFHbHpXMjltWm5ObGRDQXJJREZkSUR3OElEZ3BJSHhjYmlBZ0lDQW9kR2hwYzF0dlptWnpaWFFnS3lBeVhTQThQQ0F4TmlrZ2ZGeHVJQ0FnSUNoMGFHbHpXMjltWm5ObGRDQXJJRE5kSUR3OElESTBLVnh1ZlZ4dVhHNUNkV1ptWlhJdWNISnZkRzkwZVhCbExuSmxZV1JKYm5Rek1rSkZJRDBnWm5WdVkzUnBiMjRnY21WaFpFbHVkRE15UWtVZ0tHOW1abk5sZEN3Z2JtOUJjM05sY25RcElIdGNiaUFnYVdZZ0tDRnViMEZ6YzJWeWRDa2dZMmhsWTJ0UFptWnpaWFFvYjJabWMyVjBMQ0EwTENCMGFHbHpMbXhsYm1kMGFDbGNibHh1SUNCeVpYUjFjbTRnS0hSb2FYTmJiMlptYzJWMFhTQThQQ0F5TkNrZ2ZGeHVJQ0FnSUNoMGFHbHpXMjltWm5ObGRDQXJJREZkSUR3OElERTJLU0I4WEc0Z0lDQWdLSFJvYVhOYmIyWm1jMlYwSUNzZ01sMGdQRHdnT0NrZ2ZGeHVJQ0FnSUNoMGFHbHpXMjltWm5ObGRDQXJJRE5kS1Z4dWZWeHVYRzVDZFdabVpYSXVjSEp2ZEc5MGVYQmxMbkpsWVdSR2JHOWhkRXhGSUQwZ1puVnVZM1JwYjI0Z2NtVmhaRVpzYjJGMFRFVWdLRzltWm5ObGRDd2dibTlCYzNObGNuUXBJSHRjYmlBZ2FXWWdLQ0Z1YjBGemMyVnlkQ2tnWTJobFkydFBabVp6WlhRb2IyWm1jMlYwTENBMExDQjBhR2x6TG14bGJtZDBhQ2xjYmlBZ2NtVjBkWEp1SUdsbFpXVTNOVFF1Y21WaFpDaDBhR2x6TENCdlptWnpaWFFzSUhSeWRXVXNJREl6TENBMEtWeHVmVnh1WEc1Q2RXWm1aWEl1Y0hKdmRHOTBlWEJsTG5KbFlXUkdiRzloZEVKRklEMGdablZ1WTNScGIyNGdjbVZoWkVac2IyRjBRa1VnS0c5bVpuTmxkQ3dnYm05QmMzTmxjblFwSUh0Y2JpQWdhV1lnS0NGdWIwRnpjMlZ5ZENrZ1kyaGxZMnRQWm1aelpYUW9iMlptYzJWMExDQTBMQ0IwYUdsekxteGxibWQwYUNsY2JpQWdjbVYwZFhKdUlHbGxaV1UzTlRRdWNtVmhaQ2gwYUdsekxDQnZabVp6WlhRc0lHWmhiSE5sTENBeU15d2dOQ2xjYm4xY2JseHVRblZtWm1WeUxuQnliM1J2ZEhsd1pTNXlaV0ZrUkc5MVlteGxURVVnUFNCbWRXNWpkR2x2YmlCeVpXRmtSRzkxWW14bFRFVWdLRzltWm5ObGRDd2dibTlCYzNObGNuUXBJSHRjYmlBZ2FXWWdLQ0Z1YjBGemMyVnlkQ2tnWTJobFkydFBabVp6WlhRb2IyWm1jMlYwTENBNExDQjBhR2x6TG14bGJtZDBhQ2xjYmlBZ2NtVjBkWEp1SUdsbFpXVTNOVFF1Y21WaFpDaDBhR2x6TENCdlptWnpaWFFzSUhSeWRXVXNJRFV5TENBNEtWeHVmVnh1WEc1Q2RXWm1aWEl1Y0hKdmRHOTBlWEJsTG5KbFlXUkViM1ZpYkdWQ1JTQTlJR1oxYm1OMGFXOXVJSEpsWVdSRWIzVmliR1ZDUlNBb2IyWm1jMlYwTENCdWIwRnpjMlZ5ZENrZ2UxeHVJQ0JwWmlBb0lXNXZRWE56WlhKMEtTQmphR1ZqYTA5bVpuTmxkQ2h2Wm1aelpYUXNJRGdzSUhSb2FYTXViR1Z1WjNSb0tWeHVJQ0J5WlhSMWNtNGdhV1ZsWlRjMU5DNXlaV0ZrS0hSb2FYTXNJRzltWm5ObGRDd2dabUZzYzJVc0lEVXlMQ0E0S1Z4dWZWeHVYRzVtZFc1amRHbHZiaUJqYUdWamEwbHVkQ0FvWW5WbUxDQjJZV3gxWlN3Z2IyWm1jMlYwTENCbGVIUXNJRzFoZUN3Z2JXbHVLU0I3WEc0Z0lHbG1JQ2doUW5WbVptVnlMbWx6UW5WbVptVnlLR0oxWmlrcElIUm9jbTkzSUc1bGR5QlVlWEJsUlhKeWIzSW9KMkoxWm1abGNpQnRkWE4wSUdKbElHRWdRblZtWm1WeUlHbHVjM1JoYm1ObEp5bGNiaUFnYVdZZ0tIWmhiSFZsSUQ0Z2JXRjRJSHg4SUhaaGJIVmxJRHdnYldsdUtTQjBhSEp2ZHlCdVpYY2dVbUZ1WjJWRmNuSnZjaWduZG1Gc2RXVWdhWE1nYjNWMElHOW1JR0p2ZFc1a2N5Y3BYRzRnSUdsbUlDaHZabVp6WlhRZ0t5QmxlSFFnUGlCaWRXWXViR1Z1WjNSb0tTQjBhSEp2ZHlCdVpYY2dVbUZ1WjJWRmNuSnZjaWduYVc1a1pYZ2diM1YwSUc5bUlISmhibWRsSnlsY2JuMWNibHh1UW5WbVptVnlMbkJ5YjNSdmRIbHdaUzUzY21sMFpWVkpiblJNUlNBOUlHWjFibU4wYVc5dUlIZHlhWFJsVlVsdWRFeEZJQ2gyWVd4MVpTd2diMlptYzJWMExDQmllWFJsVEdWdVozUm9MQ0J1YjBGemMyVnlkQ2tnZTF4dUlDQjJZV3gxWlNBOUlDdDJZV3gxWlZ4dUlDQnZabVp6WlhRZ1BTQnZabVp6WlhRZ2ZDQXdYRzRnSUdKNWRHVk1aVzVuZEdnZ1BTQmllWFJsVEdWdVozUm9JSHdnTUZ4dUlDQnBaaUFvSVc1dlFYTnpaWEowS1NCamFHVmphMGx1ZENoMGFHbHpMQ0IyWVd4MVpTd2diMlptYzJWMExDQmllWFJsVEdWdVozUm9MQ0JOWVhSb0xuQnZkeWd5TENBNElDb2dZbmwwWlV4bGJtZDBhQ2tzSURBcFhHNWNiaUFnZG1GeUlHMTFiQ0E5SURGY2JpQWdkbUZ5SUdrZ1BTQXdYRzRnSUhSb2FYTmJiMlptYzJWMFhTQTlJSFpoYkhWbElDWWdNSGhHUmx4dUlDQjNhR2xzWlNBb0t5dHBJRHdnWW5sMFpVeGxibWQwYUNBbUppQW9iWFZzSUNvOUlEQjRNVEF3S1NrZ2UxeHVJQ0FnSUhSb2FYTmJiMlptYzJWMElDc2dhVjBnUFNBb2RtRnNkV1VnTHlCdGRXd3BJQ1lnTUhoR1JseHVJQ0I5WEc1Y2JpQWdjbVYwZFhKdUlHOW1abk5sZENBcklHSjVkR1ZNWlc1bmRHaGNibjFjYmx4dVFuVm1abVZ5TG5CeWIzUnZkSGx3WlM1M2NtbDBaVlZKYm5SQ1JTQTlJR1oxYm1OMGFXOXVJSGR5YVhSbFZVbHVkRUpGSUNoMllXeDFaU3dnYjJabWMyVjBMQ0JpZVhSbFRHVnVaM1JvTENCdWIwRnpjMlZ5ZENrZ2UxeHVJQ0IyWVd4MVpTQTlJQ3QyWVd4MVpWeHVJQ0J2Wm1aelpYUWdQU0J2Wm1aelpYUWdmQ0F3WEc0Z0lHSjVkR1ZNWlc1bmRHZ2dQU0JpZVhSbFRHVnVaM1JvSUh3Z01GeHVJQ0JwWmlBb0lXNXZRWE56WlhKMEtTQmphR1ZqYTBsdWRDaDBhR2x6TENCMllXeDFaU3dnYjJabWMyVjBMQ0JpZVhSbFRHVnVaM1JvTENCTllYUm9MbkJ2ZHlneUxDQTRJQ29nWW5sMFpVeGxibWQwYUNrc0lEQXBYRzVjYmlBZ2RtRnlJR2tnUFNCaWVYUmxUR1Z1WjNSb0lDMGdNVnh1SUNCMllYSWdiWFZzSUQwZ01WeHVJQ0IwYUdselcyOW1abk5sZENBcklHbGRJRDBnZG1Gc2RXVWdKaUF3ZUVaR1hHNGdJSGRvYVd4bElDZ3RMV2tnUGowZ01DQW1KaUFvYlhWc0lDbzlJREI0TVRBd0tTa2dlMXh1SUNBZ0lIUm9hWE5iYjJabWMyVjBJQ3NnYVYwZ1BTQW9kbUZzZFdVZ0x5QnRkV3dwSUNZZ01IaEdSbHh1SUNCOVhHNWNiaUFnY21WMGRYSnVJRzltWm5ObGRDQXJJR0o1ZEdWTVpXNW5kR2hjYm4xY2JseHVRblZtWm1WeUxuQnliM1J2ZEhsd1pTNTNjbWwwWlZWSmJuUTRJRDBnWm5WdVkzUnBiMjRnZDNKcGRHVlZTVzUwT0NBb2RtRnNkV1VzSUc5bVpuTmxkQ3dnYm05QmMzTmxjblFwSUh0Y2JpQWdkbUZzZFdVZ1BTQXJkbUZzZFdWY2JpQWdiMlptYzJWMElEMGdiMlptYzJWMElId2dNRnh1SUNCcFppQW9JVzV2UVhOelpYSjBLU0JqYUdWamEwbHVkQ2gwYUdsekxDQjJZV3gxWlN3Z2IyWm1jMlYwTENBeExDQXdlR1ptTENBd0tWeHVJQ0JwWmlBb0lVSjFabVpsY2k1VVdWQkZSRjlCVWxKQldWOVRWVkJRVDFKVUtTQjJZV3gxWlNBOUlFMWhkR2d1Wm14dmIzSW9kbUZzZFdVcFhHNGdJSFJvYVhOYmIyWm1jMlYwWFNBOUlDaDJZV3gxWlNBbUlEQjRabVlwWEc0Z0lISmxkSFZ5YmlCdlptWnpaWFFnS3lBeFhHNTlYRzVjYm1aMWJtTjBhVzl1SUc5aWFtVmpkRmR5YVhSbFZVbHVkREUySUNoaWRXWXNJSFpoYkhWbExDQnZabVp6WlhRc0lHeHBkSFJzWlVWdVpHbGhiaWtnZTF4dUlDQnBaaUFvZG1Gc2RXVWdQQ0F3S1NCMllXeDFaU0E5SURCNFptWm1aaUFySUhaaGJIVmxJQ3NnTVZ4dUlDQm1iM0lnS0haaGNpQnBJRDBnTUN3Z2FpQTlJRTFoZEdndWJXbHVLR0oxWmk1c1pXNW5kR2dnTFNCdlptWnpaWFFzSURJcE95QnBJRHdnYWpzZ2FTc3JLU0I3WEc0Z0lDQWdZblZtVzI5bVpuTmxkQ0FySUdsZElEMGdLSFpoYkhWbElDWWdLREI0Wm1ZZ1BEd2dLRGdnS2lBb2JHbDBkR3hsUlc1a2FXRnVJRDhnYVNBNklERWdMU0JwS1NrcEtTQStQajVjYmlBZ0lDQWdJQ2hzYVhSMGJHVkZibVJwWVc0Z1B5QnBJRG9nTVNBdElHa3BJQ29nT0Z4dUlDQjlYRzU5WEc1Y2JrSjFabVpsY2k1d2NtOTBiM1I1Y0dVdWQzSnBkR1ZWU1c1ME1UWk1SU0E5SUdaMWJtTjBhVzl1SUhkeWFYUmxWVWx1ZERFMlRFVWdLSFpoYkhWbExDQnZabVp6WlhRc0lHNXZRWE56WlhKMEtTQjdYRzRnSUhaaGJIVmxJRDBnSzNaaGJIVmxYRzRnSUc5bVpuTmxkQ0E5SUc5bVpuTmxkQ0I4SURCY2JpQWdhV1lnS0NGdWIwRnpjMlZ5ZENrZ1kyaGxZMnRKYm5Rb2RHaHBjeXdnZG1Gc2RXVXNJRzltWm5ObGRDd2dNaXdnTUhobVptWm1MQ0F3S1Z4dUlDQnBaaUFvUW5WbVptVnlMbFJaVUVWRVgwRlNVa0ZaWDFOVlVGQlBVbFFwSUh0Y2JpQWdJQ0IwYUdselcyOW1abk5sZEYwZ1BTQW9kbUZzZFdVZ0ppQXdlR1ptS1Z4dUlDQWdJSFJvYVhOYmIyWm1jMlYwSUNzZ01WMGdQU0FvZG1Gc2RXVWdQajQrSURncFhHNGdJSDBnWld4elpTQjdYRzRnSUNBZ2IySnFaV04wVjNKcGRHVlZTVzUwTVRZb2RHaHBjeXdnZG1Gc2RXVXNJRzltWm5ObGRDd2dkSEoxWlNsY2JpQWdmVnh1SUNCeVpYUjFjbTRnYjJabWMyVjBJQ3NnTWx4dWZWeHVYRzVDZFdabVpYSXVjSEp2ZEc5MGVYQmxMbmR5YVhSbFZVbHVkREUyUWtVZ1BTQm1kVzVqZEdsdmJpQjNjbWwwWlZWSmJuUXhOa0pGSUNoMllXeDFaU3dnYjJabWMyVjBMQ0J1YjBGemMyVnlkQ2tnZTF4dUlDQjJZV3gxWlNBOUlDdDJZV3gxWlZ4dUlDQnZabVp6WlhRZ1BTQnZabVp6WlhRZ2ZDQXdYRzRnSUdsbUlDZ2hibTlCYzNObGNuUXBJR05vWldOclNXNTBLSFJvYVhNc0lIWmhiSFZsTENCdlptWnpaWFFzSURJc0lEQjRabVptWml3Z01DbGNiaUFnYVdZZ0tFSjFabVpsY2k1VVdWQkZSRjlCVWxKQldWOVRWVkJRVDFKVUtTQjdYRzRnSUNBZ2RHaHBjMXR2Wm1aelpYUmRJRDBnS0haaGJIVmxJRDQrUGlBNEtWeHVJQ0FnSUhSb2FYTmJiMlptYzJWMElDc2dNVjBnUFNBb2RtRnNkV1VnSmlBd2VHWm1LVnh1SUNCOUlHVnNjMlVnZTF4dUlDQWdJRzlpYW1WamRGZHlhWFJsVlVsdWRERTJLSFJvYVhNc0lIWmhiSFZsTENCdlptWnpaWFFzSUdaaGJITmxLVnh1SUNCOVhHNGdJSEpsZEhWeWJpQnZabVp6WlhRZ0t5QXlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHOWlhbVZqZEZkeWFYUmxWVWx1ZERNeUlDaGlkV1lzSUhaaGJIVmxMQ0J2Wm1aelpYUXNJR3hwZEhSc1pVVnVaR2xoYmlrZ2UxeHVJQ0JwWmlBb2RtRnNkV1VnUENBd0tTQjJZV3gxWlNBOUlEQjRabVptWm1abVptWWdLeUIyWVd4MVpTQXJJREZjYmlBZ1ptOXlJQ2gyWVhJZ2FTQTlJREFzSUdvZ1BTQk5ZWFJvTG0xcGJpaGlkV1l1YkdWdVozUm9JQzBnYjJabWMyVjBMQ0EwS1RzZ2FTQThJR283SUdrckt5a2dlMXh1SUNBZ0lHSjFabHR2Wm1aelpYUWdLeUJwWFNBOUlDaDJZV3gxWlNBK1BqNGdLR3hwZEhSc1pVVnVaR2xoYmlBL0lHa2dPaUF6SUMwZ2FTa2dLaUE0S1NBbUlEQjRabVpjYmlBZ2ZWeHVmVnh1WEc1Q2RXWm1aWEl1Y0hKdmRHOTBlWEJsTG5keWFYUmxWVWx1ZERNeVRFVWdQU0JtZFc1amRHbHZiaUIzY21sMFpWVkpiblF6TWt4RklDaDJZV3gxWlN3Z2IyWm1jMlYwTENCdWIwRnpjMlZ5ZENrZ2UxeHVJQ0IyWVd4MVpTQTlJQ3QyWVd4MVpWeHVJQ0J2Wm1aelpYUWdQU0J2Wm1aelpYUWdmQ0F3WEc0Z0lHbG1JQ2doYm05QmMzTmxjblFwSUdOb1pXTnJTVzUwS0hSb2FYTXNJSFpoYkhWbExDQnZabVp6WlhRc0lEUXNJREI0Wm1abVptWm1abVlzSURBcFhHNGdJR2xtSUNoQ2RXWm1aWEl1VkZsUVJVUmZRVkpTUVZsZlUxVlFVRTlTVkNrZ2UxeHVJQ0FnSUhSb2FYTmJiMlptYzJWMElDc2dNMTBnUFNBb2RtRnNkV1VnUGo0K0lESTBLVnh1SUNBZ0lIUm9hWE5iYjJabWMyVjBJQ3NnTWwwZ1BTQW9kbUZzZFdVZ1BqNCtJREUyS1Z4dUlDQWdJSFJvYVhOYmIyWm1jMlYwSUNzZ01WMGdQU0FvZG1Gc2RXVWdQajQrSURncFhHNGdJQ0FnZEdocGMxdHZabVp6WlhSZElEMGdLSFpoYkhWbElDWWdNSGhtWmlsY2JpQWdmU0JsYkhObElIdGNiaUFnSUNCdlltcGxZM1JYY21sMFpWVkpiblF6TWloMGFHbHpMQ0IyWVd4MVpTd2diMlptYzJWMExDQjBjblZsS1Z4dUlDQjlYRzRnSUhKbGRIVnliaUJ2Wm1aelpYUWdLeUEwWEc1OVhHNWNia0oxWm1abGNpNXdjbTkwYjNSNWNHVXVkM0pwZEdWVlNXNTBNekpDUlNBOUlHWjFibU4wYVc5dUlIZHlhWFJsVlVsdWRETXlRa1VnS0haaGJIVmxMQ0J2Wm1aelpYUXNJRzV2UVhOelpYSjBLU0I3WEc0Z0lIWmhiSFZsSUQwZ0szWmhiSFZsWEc0Z0lHOW1abk5sZENBOUlHOW1abk5sZENCOElEQmNiaUFnYVdZZ0tDRnViMEZ6YzJWeWRDa2dZMmhsWTJ0SmJuUW9kR2hwY3l3Z2RtRnNkV1VzSUc5bVpuTmxkQ3dnTkN3Z01IaG1abVptWm1abVppd2dNQ2xjYmlBZ2FXWWdLRUoxWm1abGNpNVVXVkJGUkY5QlVsSkJXVjlUVlZCUVQxSlVLU0I3WEc0Z0lDQWdkR2hwYzF0dlptWnpaWFJkSUQwZ0tIWmhiSFZsSUQ0K1BpQXlOQ2xjYmlBZ0lDQjBhR2x6VzI5bVpuTmxkQ0FySURGZElEMGdLSFpoYkhWbElENCtQaUF4TmlsY2JpQWdJQ0IwYUdselcyOW1abk5sZENBcklESmRJRDBnS0haaGJIVmxJRDQrUGlBNEtWeHVJQ0FnSUhSb2FYTmJiMlptYzJWMElDc2dNMTBnUFNBb2RtRnNkV1VnSmlBd2VHWm1LVnh1SUNCOUlHVnNjMlVnZTF4dUlDQWdJRzlpYW1WamRGZHlhWFJsVlVsdWRETXlLSFJvYVhNc0lIWmhiSFZsTENCdlptWnpaWFFzSUdaaGJITmxLVnh1SUNCOVhHNGdJSEpsZEhWeWJpQnZabVp6WlhRZ0t5QTBYRzU5WEc1Y2JrSjFabVpsY2k1d2NtOTBiM1I1Y0dVdWQzSnBkR1ZKYm5STVJTQTlJR1oxYm1OMGFXOXVJSGR5YVhSbFNXNTBURVVnS0haaGJIVmxMQ0J2Wm1aelpYUXNJR0o1ZEdWTVpXNW5kR2dzSUc1dlFYTnpaWEowS1NCN1hHNGdJSFpoYkhWbElEMGdLM1poYkhWbFhHNGdJRzltWm5ObGRDQTlJRzltWm5ObGRDQjhJREJjYmlBZ2FXWWdLQ0Z1YjBGemMyVnlkQ2tnZTF4dUlDQWdJSFpoY2lCc2FXMXBkQ0E5SUUxaGRHZ3VjRzkzS0RJc0lEZ2dLaUJpZVhSbFRHVnVaM1JvSUMwZ01TbGNibHh1SUNBZ0lHTm9aV05yU1c1MEtIUm9hWE1zSUhaaGJIVmxMQ0J2Wm1aelpYUXNJR0o1ZEdWTVpXNW5kR2dzSUd4cGJXbDBJQzBnTVN3Z0xXeHBiV2wwS1Z4dUlDQjlYRzVjYmlBZ2RtRnlJR2tnUFNBd1hHNGdJSFpoY2lCdGRXd2dQU0F4WEc0Z0lIWmhjaUJ6ZFdJZ1BTQjJZV3gxWlNBOElEQWdQeUF4SURvZ01GeHVJQ0IwYUdselcyOW1abk5sZEYwZ1BTQjJZV3gxWlNBbUlEQjRSa1pjYmlBZ2QyaHBiR1VnS0NzcmFTQThJR0o1ZEdWTVpXNW5kR2dnSmlZZ0tHMTFiQ0FxUFNBd2VERXdNQ2twSUh0Y2JpQWdJQ0IwYUdselcyOW1abk5sZENBcklHbGRJRDBnS0NoMllXeDFaU0F2SUcxMWJDa2dQajRnTUNrZ0xTQnpkV0lnSmlBd2VFWkdYRzRnSUgxY2JseHVJQ0J5WlhSMWNtNGdiMlptYzJWMElDc2dZbmwwWlV4bGJtZDBhRnh1ZlZ4dVhHNUNkV1ptWlhJdWNISnZkRzkwZVhCbExuZHlhWFJsU1c1MFFrVWdQU0JtZFc1amRHbHZiaUIzY21sMFpVbHVkRUpGSUNoMllXeDFaU3dnYjJabWMyVjBMQ0JpZVhSbFRHVnVaM1JvTENCdWIwRnpjMlZ5ZENrZ2UxeHVJQ0IyWVd4MVpTQTlJQ3QyWVd4MVpWeHVJQ0J2Wm1aelpYUWdQU0J2Wm1aelpYUWdmQ0F3WEc0Z0lHbG1JQ2doYm05QmMzTmxjblFwSUh0Y2JpQWdJQ0IyWVhJZ2JHbHRhWFFnUFNCTllYUm9MbkJ2ZHlneUxDQTRJQ29nWW5sMFpVeGxibWQwYUNBdElERXBYRzVjYmlBZ0lDQmphR1ZqYTBsdWRDaDBhR2x6TENCMllXeDFaU3dnYjJabWMyVjBMQ0JpZVhSbFRHVnVaM1JvTENCc2FXMXBkQ0F0SURFc0lDMXNhVzFwZENsY2JpQWdmVnh1WEc0Z0lIWmhjaUJwSUQwZ1lubDBaVXhsYm1kMGFDQXRJREZjYmlBZ2RtRnlJRzExYkNBOUlERmNiaUFnZG1GeUlITjFZaUE5SUhaaGJIVmxJRHdnTUNBL0lERWdPaUF3WEc0Z0lIUm9hWE5iYjJabWMyVjBJQ3NnYVYwZ1BTQjJZV3gxWlNBbUlEQjRSa1pjYmlBZ2QyaHBiR1VnS0MwdGFTQStQU0F3SUNZbUlDaHRkV3dnS2owZ01IZ3hNREFwS1NCN1hHNGdJQ0FnZEdocGMxdHZabVp6WlhRZ0t5QnBYU0E5SUNnb2RtRnNkV1VnTHlCdGRXd3BJRDQrSURBcElDMGdjM1ZpSUNZZ01IaEdSbHh1SUNCOVhHNWNiaUFnY21WMGRYSnVJRzltWm5ObGRDQXJJR0o1ZEdWTVpXNW5kR2hjYm4xY2JseHVRblZtWm1WeUxuQnliM1J2ZEhsd1pTNTNjbWwwWlVsdWREZ2dQU0JtZFc1amRHbHZiaUIzY21sMFpVbHVkRGdnS0haaGJIVmxMQ0J2Wm1aelpYUXNJRzV2UVhOelpYSjBLU0I3WEc0Z0lIWmhiSFZsSUQwZ0szWmhiSFZsWEc0Z0lHOW1abk5sZENBOUlHOW1abk5sZENCOElEQmNiaUFnYVdZZ0tDRnViMEZ6YzJWeWRDa2dZMmhsWTJ0SmJuUW9kR2hwY3l3Z2RtRnNkV1VzSUc5bVpuTmxkQ3dnTVN3Z01IZzNaaXdnTFRCNE9EQXBYRzRnSUdsbUlDZ2hRblZtWm1WeUxsUlpVRVZFWDBGU1VrRlpYMU5WVUZCUFVsUXBJSFpoYkhWbElEMGdUV0YwYUM1bWJHOXZjaWgyWVd4MVpTbGNiaUFnYVdZZ0tIWmhiSFZsSUR3Z01Da2dkbUZzZFdVZ1BTQXdlR1ptSUNzZ2RtRnNkV1VnS3lBeFhHNGdJSFJvYVhOYmIyWm1jMlYwWFNBOUlDaDJZV3gxWlNBbUlEQjRabVlwWEc0Z0lISmxkSFZ5YmlCdlptWnpaWFFnS3lBeFhHNTlYRzVjYmtKMVptWmxjaTV3Y205MGIzUjVjR1V1ZDNKcGRHVkpiblF4Tmt4RklEMGdablZ1WTNScGIyNGdkM0pwZEdWSmJuUXhOa3hGSUNoMllXeDFaU3dnYjJabWMyVjBMQ0J1YjBGemMyVnlkQ2tnZTF4dUlDQjJZV3gxWlNBOUlDdDJZV3gxWlZ4dUlDQnZabVp6WlhRZ1BTQnZabVp6WlhRZ2ZDQXdYRzRnSUdsbUlDZ2hibTlCYzNObGNuUXBJR05vWldOclNXNTBLSFJvYVhNc0lIWmhiSFZsTENCdlptWnpaWFFzSURJc0lEQjROMlptWml3Z0xUQjRPREF3TUNsY2JpQWdhV1lnS0VKMVptWmxjaTVVV1ZCRlJGOUJVbEpCV1Y5VFZWQlFUMUpVS1NCN1hHNGdJQ0FnZEdocGMxdHZabVp6WlhSZElEMGdLSFpoYkhWbElDWWdNSGhtWmlsY2JpQWdJQ0IwYUdselcyOW1abk5sZENBcklERmRJRDBnS0haaGJIVmxJRDQrUGlBNEtWeHVJQ0I5SUdWc2MyVWdlMXh1SUNBZ0lHOWlhbVZqZEZkeWFYUmxWVWx1ZERFMktIUm9hWE1zSUhaaGJIVmxMQ0J2Wm1aelpYUXNJSFJ5ZFdVcFhHNGdJSDFjYmlBZ2NtVjBkWEp1SUc5bVpuTmxkQ0FySURKY2JuMWNibHh1UW5WbVptVnlMbkJ5YjNSdmRIbHdaUzUzY21sMFpVbHVkREUyUWtVZ1BTQm1kVzVqZEdsdmJpQjNjbWwwWlVsdWRERTJRa1VnS0haaGJIVmxMQ0J2Wm1aelpYUXNJRzV2UVhOelpYSjBLU0I3WEc0Z0lIWmhiSFZsSUQwZ0szWmhiSFZsWEc0Z0lHOW1abk5sZENBOUlHOW1abk5sZENCOElEQmNiaUFnYVdZZ0tDRnViMEZ6YzJWeWRDa2dZMmhsWTJ0SmJuUW9kR2hwY3l3Z2RtRnNkV1VzSUc5bVpuTmxkQ3dnTWl3Z01IZzNabVptTENBdE1IZzRNREF3S1Z4dUlDQnBaaUFvUW5WbVptVnlMbFJaVUVWRVgwRlNVa0ZaWDFOVlVGQlBVbFFwSUh0Y2JpQWdJQ0IwYUdselcyOW1abk5sZEYwZ1BTQW9kbUZzZFdVZ1BqNCtJRGdwWEc0Z0lDQWdkR2hwYzF0dlptWnpaWFFnS3lBeFhTQTlJQ2gyWVd4MVpTQW1JREI0Wm1ZcFhHNGdJSDBnWld4elpTQjdYRzRnSUNBZ2IySnFaV04wVjNKcGRHVlZTVzUwTVRZb2RHaHBjeXdnZG1Gc2RXVXNJRzltWm5ObGRDd2dabUZzYzJVcFhHNGdJSDFjYmlBZ2NtVjBkWEp1SUc5bVpuTmxkQ0FySURKY2JuMWNibHh1UW5WbVptVnlMbkJ5YjNSdmRIbHdaUzUzY21sMFpVbHVkRE15VEVVZ1BTQm1kVzVqZEdsdmJpQjNjbWwwWlVsdWRETXlURVVnS0haaGJIVmxMQ0J2Wm1aelpYUXNJRzV2UVhOelpYSjBLU0I3WEc0Z0lIWmhiSFZsSUQwZ0szWmhiSFZsWEc0Z0lHOW1abk5sZENBOUlHOW1abk5sZENCOElEQmNiaUFnYVdZZ0tDRnViMEZ6YzJWeWRDa2dZMmhsWTJ0SmJuUW9kR2hwY3l3Z2RtRnNkV1VzSUc5bVpuTmxkQ3dnTkN3Z01IZzNabVptWm1abVppd2dMVEI0T0RBd01EQXdNREFwWEc0Z0lHbG1JQ2hDZFdabVpYSXVWRmxRUlVSZlFWSlNRVmxmVTFWUVVFOVNWQ2tnZTF4dUlDQWdJSFJvYVhOYmIyWm1jMlYwWFNBOUlDaDJZV3gxWlNBbUlEQjRabVlwWEc0Z0lDQWdkR2hwYzF0dlptWnpaWFFnS3lBeFhTQTlJQ2gyWVd4MVpTQStQajRnT0NsY2JpQWdJQ0IwYUdselcyOW1abk5sZENBcklESmRJRDBnS0haaGJIVmxJRDQrUGlBeE5pbGNiaUFnSUNCMGFHbHpXMjltWm5ObGRDQXJJRE5kSUQwZ0tIWmhiSFZsSUQ0K1BpQXlOQ2xjYmlBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0J2WW1wbFkzUlhjbWwwWlZWSmJuUXpNaWgwYUdsekxDQjJZV3gxWlN3Z2IyWm1jMlYwTENCMGNuVmxLVnh1SUNCOVhHNGdJSEpsZEhWeWJpQnZabVp6WlhRZ0t5QTBYRzU5WEc1Y2JrSjFabVpsY2k1d2NtOTBiM1I1Y0dVdWQzSnBkR1ZKYm5Rek1rSkZJRDBnWm5WdVkzUnBiMjRnZDNKcGRHVkpiblF6TWtKRklDaDJZV3gxWlN3Z2IyWm1jMlYwTENCdWIwRnpjMlZ5ZENrZ2UxeHVJQ0IyWVd4MVpTQTlJQ3QyWVd4MVpWeHVJQ0J2Wm1aelpYUWdQU0J2Wm1aelpYUWdmQ0F3WEc0Z0lHbG1JQ2doYm05QmMzTmxjblFwSUdOb1pXTnJTVzUwS0hSb2FYTXNJSFpoYkhWbExDQnZabVp6WlhRc0lEUXNJREI0TjJabVptWm1abVlzSUMwd2VEZ3dNREF3TURBd0tWeHVJQ0JwWmlBb2RtRnNkV1VnUENBd0tTQjJZV3gxWlNBOUlEQjRabVptWm1abVptWWdLeUIyWVd4MVpTQXJJREZjYmlBZ2FXWWdLRUoxWm1abGNpNVVXVkJGUkY5QlVsSkJXVjlUVlZCUVQxSlVLU0I3WEc0Z0lDQWdkR2hwYzF0dlptWnpaWFJkSUQwZ0tIWmhiSFZsSUQ0K1BpQXlOQ2xjYmlBZ0lDQjBhR2x6VzI5bVpuTmxkQ0FySURGZElEMGdLSFpoYkhWbElENCtQaUF4TmlsY2JpQWdJQ0IwYUdselcyOW1abk5sZENBcklESmRJRDBnS0haaGJIVmxJRDQrUGlBNEtWeHVJQ0FnSUhSb2FYTmJiMlptYzJWMElDc2dNMTBnUFNBb2RtRnNkV1VnSmlBd2VHWm1LVnh1SUNCOUlHVnNjMlVnZTF4dUlDQWdJRzlpYW1WamRGZHlhWFJsVlVsdWRETXlLSFJvYVhNc0lIWmhiSFZsTENCdlptWnpaWFFzSUdaaGJITmxLVnh1SUNCOVhHNGdJSEpsZEhWeWJpQnZabVp6WlhRZ0t5QTBYRzU5WEc1Y2JtWjFibU4wYVc5dUlHTm9aV05yU1VWRlJUYzFOQ0FvWW5WbUxDQjJZV3gxWlN3Z2IyWm1jMlYwTENCbGVIUXNJRzFoZUN3Z2JXbHVLU0I3WEc0Z0lHbG1JQ2gyWVd4MVpTQStJRzFoZUNCOGZDQjJZV3gxWlNBOElHMXBiaWtnZEdoeWIzY2dibVYzSUZKaGJtZGxSWEp5YjNJb0ozWmhiSFZsSUdseklHOTFkQ0J2WmlCaWIzVnVaSE1uS1Z4dUlDQnBaaUFvYjJabWMyVjBJQ3NnWlhoMElENGdZblZtTG14bGJtZDBhQ2tnZEdoeWIzY2dibVYzSUZKaGJtZGxSWEp5YjNJb0oybHVaR1Y0SUc5MWRDQnZaaUJ5WVc1blpTY3BYRzRnSUdsbUlDaHZabVp6WlhRZ1BDQXdLU0IwYUhKdmR5QnVaWGNnVW1GdVoyVkZjbkp2Y2lnbmFXNWtaWGdnYjNWMElHOW1JSEpoYm1kbEp5bGNibjFjYmx4dVpuVnVZM1JwYjI0Z2QzSnBkR1ZHYkc5aGRDQW9ZblZtTENCMllXeDFaU3dnYjJabWMyVjBMQ0JzYVhSMGJHVkZibVJwWVc0c0lHNXZRWE56WlhKMEtTQjdYRzRnSUdsbUlDZ2hibTlCYzNObGNuUXBJSHRjYmlBZ0lDQmphR1ZqYTBsRlJVVTNOVFFvWW5WbUxDQjJZV3gxWlN3Z2IyWm1jMlYwTENBMExDQXpMalF3TWpneU16UTJOak00TlRJNE9EWmxLek00TENBdE15NDBNREk0TWpNME5qWXpPRFV5T0RnMlpTc3pPQ2xjYmlBZ2ZWeHVJQ0JwWldWbE56VTBMbmR5YVhSbEtHSjFaaXdnZG1Gc2RXVXNJRzltWm5ObGRDd2diR2wwZEd4bFJXNWthV0Z1TENBeU15d2dOQ2xjYmlBZ2NtVjBkWEp1SUc5bVpuTmxkQ0FySURSY2JuMWNibHh1UW5WbVptVnlMbkJ5YjNSdmRIbHdaUzUzY21sMFpVWnNiMkYwVEVVZ1BTQm1kVzVqZEdsdmJpQjNjbWwwWlVac2IyRjBURVVnS0haaGJIVmxMQ0J2Wm1aelpYUXNJRzV2UVhOelpYSjBLU0I3WEc0Z0lISmxkSFZ5YmlCM2NtbDBaVVpzYjJGMEtIUm9hWE1zSUhaaGJIVmxMQ0J2Wm1aelpYUXNJSFJ5ZFdVc0lHNXZRWE56WlhKMEtWeHVmVnh1WEc1Q2RXWm1aWEl1Y0hKdmRHOTBlWEJsTG5keWFYUmxSbXh2WVhSQ1JTQTlJR1oxYm1OMGFXOXVJSGR5YVhSbFJteHZZWFJDUlNBb2RtRnNkV1VzSUc5bVpuTmxkQ3dnYm05QmMzTmxjblFwSUh0Y2JpQWdjbVYwZFhKdUlIZHlhWFJsUm14dllYUW9kR2hwY3l3Z2RtRnNkV1VzSUc5bVpuTmxkQ3dnWm1Gc2MyVXNJRzV2UVhOelpYSjBLVnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQjNjbWwwWlVSdmRXSnNaU0FvWW5WbUxDQjJZV3gxWlN3Z2IyWm1jMlYwTENCc2FYUjBiR1ZGYm1ScFlXNHNJRzV2UVhOelpYSjBLU0I3WEc0Z0lHbG1JQ2doYm05QmMzTmxjblFwSUh0Y2JpQWdJQ0JqYUdWamEwbEZSVVUzTlRRb1luVm1MQ0IyWVd4MVpTd2diMlptYzJWMExDQTRMQ0F4TGpjNU56WTVNekV6TkRnMk1qTXhOVGRGS3pNd09Dd2dMVEV1TnprM05qa3pNVE0wT0RZeU16RTFOMFVyTXpBNEtWeHVJQ0I5WEc0Z0lHbGxaV1UzTlRRdWQzSnBkR1VvWW5WbUxDQjJZV3gxWlN3Z2IyWm1jMlYwTENCc2FYUjBiR1ZGYm1ScFlXNHNJRFV5TENBNEtWeHVJQ0J5WlhSMWNtNGdiMlptYzJWMElDc2dPRnh1ZlZ4dVhHNUNkV1ptWlhJdWNISnZkRzkwZVhCbExuZHlhWFJsUkc5MVlteGxURVVnUFNCbWRXNWpkR2x2YmlCM2NtbDBaVVJ2ZFdKc1pVeEZJQ2gyWVd4MVpTd2diMlptYzJWMExDQnViMEZ6YzJWeWRDa2dlMXh1SUNCeVpYUjFjbTRnZDNKcGRHVkViM1ZpYkdVb2RHaHBjeXdnZG1Gc2RXVXNJRzltWm5ObGRDd2dkSEoxWlN3Z2JtOUJjM05sY25RcFhHNTlYRzVjYmtKMVptWmxjaTV3Y205MGIzUjVjR1V1ZDNKcGRHVkViM1ZpYkdWQ1JTQTlJR1oxYm1OMGFXOXVJSGR5YVhSbFJHOTFZbXhsUWtVZ0tIWmhiSFZsTENCdlptWnpaWFFzSUc1dlFYTnpaWEowS1NCN1hHNGdJSEpsZEhWeWJpQjNjbWwwWlVSdmRXSnNaU2gwYUdsekxDQjJZV3gxWlN3Z2IyWm1jMlYwTENCbVlXeHpaU3dnYm05QmMzTmxjblFwWEc1OVhHNWNiaTh2SUdOdmNIa29kR0Z5WjJWMFFuVm1abVZ5TENCMFlYSm5aWFJUZEdGeWREMHdMQ0J6YjNWeVkyVlRkR0Z5ZEQwd0xDQnpiM1Z5WTJWRmJtUTlZblZtWm1WeUxteGxibWQwYUNsY2JrSjFabVpsY2k1d2NtOTBiM1I1Y0dVdVkyOXdlU0E5SUdaMWJtTjBhVzl1SUdOdmNIa2dLSFJoY21kbGRDd2dkR0Z5WjJWMFUzUmhjblFzSUhOMFlYSjBMQ0JsYm1RcElIdGNiaUFnYVdZZ0tDRnpkR0Z5ZENrZ2MzUmhjblFnUFNBd1hHNGdJR2xtSUNnaFpXNWtJQ1ltSUdWdVpDQWhQVDBnTUNrZ1pXNWtJRDBnZEdocGN5NXNaVzVuZEdoY2JpQWdhV1lnS0hSaGNtZGxkRk4wWVhKMElENDlJSFJoY21kbGRDNXNaVzVuZEdncElIUmhjbWRsZEZOMFlYSjBJRDBnZEdGeVoyVjBMbXhsYm1kMGFGeHVJQ0JwWmlBb0lYUmhjbWRsZEZOMFlYSjBLU0IwWVhKblpYUlRkR0Z5ZENBOUlEQmNiaUFnYVdZZ0tHVnVaQ0ErSURBZ0ppWWdaVzVrSUR3Z2MzUmhjblFwSUdWdVpDQTlJSE4wWVhKMFhHNWNiaUFnTHk4Z1EyOXdlU0F3SUdKNWRHVnpPeUIzWlNkeVpTQmtiMjVsWEc0Z0lHbG1JQ2hsYm1RZ1BUMDlJSE4wWVhKMEtTQnlaWFIxY200Z01GeHVJQ0JwWmlBb2RHRnlaMlYwTG14bGJtZDBhQ0E5UFQwZ01DQjhmQ0IwYUdsekxteGxibWQwYUNBOVBUMGdNQ2tnY21WMGRYSnVJREJjYmx4dUlDQXZMeUJHWVhSaGJDQmxjbkp2Y2lCamIyNWthWFJwYjI1elhHNGdJR2xtSUNoMFlYSm5aWFJUZEdGeWRDQThJREFwSUh0Y2JpQWdJQ0IwYUhKdmR5QnVaWGNnVW1GdVoyVkZjbkp2Y2lnbmRHRnlaMlYwVTNSaGNuUWdiM1YwSUc5bUlHSnZkVzVrY3ljcFhHNGdJSDFjYmlBZ2FXWWdLSE4wWVhKMElEd2dNQ0I4ZkNCemRHRnlkQ0ErUFNCMGFHbHpMbXhsYm1kMGFDa2dkR2h5YjNjZ2JtVjNJRkpoYm1kbFJYSnliM0lvSjNOdmRYSmpaVk4wWVhKMElHOTFkQ0J2WmlCaWIzVnVaSE1uS1Z4dUlDQnBaaUFvWlc1a0lEd2dNQ2tnZEdoeWIzY2dibVYzSUZKaGJtZGxSWEp5YjNJb0ozTnZkWEpqWlVWdVpDQnZkWFFnYjJZZ1ltOTFibVJ6SnlsY2JseHVJQ0F2THlCQmNtVWdkMlVnYjI5aVAxeHVJQ0JwWmlBb1pXNWtJRDRnZEdocGN5NXNaVzVuZEdncElHVnVaQ0E5SUhSb2FYTXViR1Z1WjNSb1hHNGdJR2xtSUNoMFlYSm5aWFF1YkdWdVozUm9JQzBnZEdGeVoyVjBVM1JoY25RZ1BDQmxibVFnTFNCemRHRnlkQ2tnZTF4dUlDQWdJR1Z1WkNBOUlIUmhjbWRsZEM1c1pXNW5kR2dnTFNCMFlYSm5aWFJUZEdGeWRDQXJJSE4wWVhKMFhHNGdJSDFjYmx4dUlDQjJZWElnYkdWdUlEMGdaVzVrSUMwZ2MzUmhjblJjYmlBZ2RtRnlJR2xjYmx4dUlDQnBaaUFvZEdocGN5QTlQVDBnZEdGeVoyVjBJQ1ltSUhOMFlYSjBJRHdnZEdGeVoyVjBVM1JoY25RZ0ppWWdkR0Z5WjJWMFUzUmhjblFnUENCbGJtUXBJSHRjYmlBZ0lDQXZMeUJrWlhOalpXNWthVzVuSUdOdmNIa2dabkp2YlNCbGJtUmNiaUFnSUNCbWIzSWdLR2tnUFNCc1pXNGdMU0F4T3lCcElENDlJREE3SUdrdExTa2dlMXh1SUNBZ0lDQWdkR0Z5WjJWMFcya2dLeUIwWVhKblpYUlRkR0Z5ZEYwZ1BTQjBhR2x6VzJrZ0t5QnpkR0Z5ZEYxY2JpQWdJQ0I5WEc0Z0lIMGdaV3h6WlNCcFppQW9iR1Z1SUR3Z01UQXdNQ0I4ZkNBaFFuVm1abVZ5TGxSWlVFVkVYMEZTVWtGWlgxTlZVRkJQVWxRcElIdGNiaUFnSUNBdkx5QmhjMk5sYm1ScGJtY2dZMjl3ZVNCbWNtOXRJSE4wWVhKMFhHNGdJQ0FnWm05eUlDaHBJRDBnTURzZ2FTQThJR3hsYmpzZ2FTc3JLU0I3WEc0Z0lDQWdJQ0IwWVhKblpYUmJhU0FySUhSaGNtZGxkRk4wWVhKMFhTQTlJSFJvYVhOYmFTQXJJSE4wWVhKMFhWeHVJQ0FnSUgxY2JpQWdmU0JsYkhObElIdGNiaUFnSUNCMFlYSm5aWFF1WDNObGRDaDBhR2x6TG5OMVltRnljbUY1S0hOMFlYSjBMQ0J6ZEdGeWRDQXJJR3hsYmlrc0lIUmhjbWRsZEZOMFlYSjBLVnh1SUNCOVhHNWNiaUFnY21WMGRYSnVJR3hsYmx4dWZWeHVYRzR2THlCbWFXeHNLSFpoYkhWbExDQnpkR0Z5ZEQwd0xDQmxibVE5WW5WbVptVnlMbXhsYm1kMGFDbGNia0oxWm1abGNpNXdjbTkwYjNSNWNHVXVabWxzYkNBOUlHWjFibU4wYVc5dUlHWnBiR3dnS0haaGJIVmxMQ0J6ZEdGeWRDd2daVzVrS1NCN1hHNGdJR2xtSUNnaGRtRnNkV1VwSUhaaGJIVmxJRDBnTUZ4dUlDQnBaaUFvSVhOMFlYSjBLU0J6ZEdGeWRDQTlJREJjYmlBZ2FXWWdLQ0ZsYm1RcElHVnVaQ0E5SUhSb2FYTXViR1Z1WjNSb1hHNWNiaUFnYVdZZ0tHVnVaQ0E4SUhOMFlYSjBLU0IwYUhKdmR5QnVaWGNnVW1GdVoyVkZjbkp2Y2lnblpXNWtJRHdnYzNSaGNuUW5LVnh1WEc0Z0lDOHZJRVpwYkd3Z01DQmllWFJsY3pzZ2QyVW5jbVVnWkc5dVpWeHVJQ0JwWmlBb1pXNWtJRDA5UFNCemRHRnlkQ2tnY21WMGRYSnVYRzRnSUdsbUlDaDBhR2x6TG14bGJtZDBhQ0E5UFQwZ01Da2djbVYwZFhKdVhHNWNiaUFnYVdZZ0tITjBZWEowSUR3Z01DQjhmQ0J6ZEdGeWRDQStQU0IwYUdsekxteGxibWQwYUNrZ2RHaHliM2NnYm1WM0lGSmhibWRsUlhKeWIzSW9KM04wWVhKMElHOTFkQ0J2WmlCaWIzVnVaSE1uS1Z4dUlDQnBaaUFvWlc1a0lEd2dNQ0I4ZkNCbGJtUWdQaUIwYUdsekxteGxibWQwYUNrZ2RHaHliM2NnYm1WM0lGSmhibWRsUlhKeWIzSW9KMlZ1WkNCdmRYUWdiMllnWW05MWJtUnpKeWxjYmx4dUlDQjJZWElnYVZ4dUlDQnBaaUFvZEhsd1pXOW1JSFpoYkhWbElEMDlQU0FuYm5WdFltVnlKeWtnZTF4dUlDQWdJR1p2Y2lBb2FTQTlJSE4wWVhKME95QnBJRHdnWlc1a095QnBLeXNwSUh0Y2JpQWdJQ0FnSUhSb2FYTmJhVjBnUFNCMllXeDFaVnh1SUNBZ0lIMWNiaUFnZlNCbGJITmxJSHRjYmlBZ0lDQjJZWElnWW5sMFpYTWdQU0IxZEdZNFZHOUNlWFJsY3loMllXeDFaUzUwYjFOMGNtbHVaeWdwS1Z4dUlDQWdJSFpoY2lCc1pXNGdQU0JpZVhSbGN5NXNaVzVuZEdoY2JpQWdJQ0JtYjNJZ0tHa2dQU0J6ZEdGeWREc2dhU0E4SUdWdVpEc2dhU3NyS1NCN1hHNGdJQ0FnSUNCMGFHbHpXMmxkSUQwZ1lubDBaWE5iYVNBbElHeGxibDFjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0J5WlhSMWNtNGdkR2hwYzF4dWZWeHVYRzR2S2lwY2JpQXFJRU55WldGMFpYTWdZU0J1WlhjZ1lFRnljbUY1UW5WbVptVnlZQ0IzYVhSb0lIUm9aU0FxWTI5d2FXVmtLaUJ0WlcxdmNua2diMllnZEdobElHSjFabVpsY2lCcGJuTjBZVzVqWlM1Y2JpQXFJRUZrWkdWa0lHbHVJRTV2WkdVZ01DNHhNaTRnVDI1c2VTQmhkbUZwYkdGaWJHVWdhVzRnWW5KdmQzTmxjbk1nZEdoaGRDQnpkWEJ3YjNKMElFRnljbUY1UW5WbVptVnlMbHh1SUNvdlhHNUNkV1ptWlhJdWNISnZkRzkwZVhCbExuUnZRWEp5WVhsQ2RXWm1aWElnUFNCbWRXNWpkR2x2YmlCMGIwRnljbUY1UW5WbVptVnlJQ2dwSUh0Y2JpQWdhV1lnS0hSNWNHVnZaaUJWYVc1ME9FRnljbUY1SUNFOVBTQW5kVzVrWldacGJtVmtKeWtnZTF4dUlDQWdJR2xtSUNoQ2RXWm1aWEl1VkZsUVJVUmZRVkpTUVZsZlUxVlFVRTlTVkNrZ2UxeHVJQ0FnSUNBZ2NtVjBkWEp1SUNodVpYY2dRblZtWm1WeUtIUm9hWE1wS1M1aWRXWm1aWEpjYmlBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ2RtRnlJR0oxWmlBOUlHNWxkeUJWYVc1ME9FRnljbUY1S0hSb2FYTXViR1Z1WjNSb0tWeHVJQ0FnSUNBZ1ptOXlJQ2gyWVhJZ2FTQTlJREFzSUd4bGJpQTlJR0oxWmk1c1pXNW5kR2c3SUdrZ1BDQnNaVzQ3SUdrZ0t6MGdNU2tnZTF4dUlDQWdJQ0FnSUNCaWRXWmJhVjBnUFNCMGFHbHpXMmxkWEc0Z0lDQWdJQ0I5WEc0Z0lDQWdJQ0J5WlhSMWNtNGdZblZtTG1KMVptWmxjbHh1SUNBZ0lIMWNiaUFnZlNCbGJITmxJSHRjYmlBZ0lDQjBhSEp2ZHlCdVpYY2dWSGx3WlVWeWNtOXlLQ2RDZFdabVpYSXVkRzlCY25KaGVVSjFabVpsY2lCdWIzUWdjM1Z3Y0c5eWRHVmtJR2x1SUhSb2FYTWdZbkp2ZDNObGNpY3BYRzRnSUgxY2JuMWNibHh1THk4Z1NFVk1VRVZTSUVaVlRrTlVTVTlPVTF4dUx5OGdQVDA5UFQwOVBUMDlQVDA5UFQwOVBWeHVYRzUyWVhJZ1FsQWdQU0JDZFdabVpYSXVjSEp2ZEc5MGVYQmxYRzVjYmk4cUtseHVJQ29nUVhWbmJXVnVkQ0JoSUZWcGJuUTRRWEp5WVhrZ0ttbHVjM1JoYm1ObEtpQW9ibTkwSUhSb1pTQlZhVzUwT0VGeWNtRjVJR05zWVhOeklTa2dkMmwwYUNCQ2RXWm1aWElnYldWMGFHOWtjMXh1SUNvdlhHNUNkV1ptWlhJdVgyRjFaMjFsYm5RZ1BTQm1kVzVqZEdsdmJpQmZZWFZuYldWdWRDQW9ZWEp5S1NCN1hHNGdJR0Z5Y2k1amIyNXpkSEoxWTNSdmNpQTlJRUoxWm1abGNseHVJQ0JoY25JdVgybHpRblZtWm1WeUlEMGdkSEoxWlZ4dVhHNGdJQzh2SUhOaGRtVWdjbVZtWlhKbGJtTmxJSFJ2SUc5eWFXZHBibUZzSUZWcGJuUTRRWEp5WVhrZ2MyVjBJRzFsZEdodlpDQmlaV1p2Y21VZ2IzWmxjbmR5YVhScGJtZGNiaUFnWVhKeUxsOXpaWFFnUFNCaGNuSXVjMlYwWEc1Y2JpQWdMeThnWkdWd2NtVmpZWFJsWkZ4dUlDQmhjbkl1WjJWMElEMGdRbEF1WjJWMFhHNGdJR0Z5Y2k1elpYUWdQU0JDVUM1elpYUmNibHh1SUNCaGNuSXVkM0pwZEdVZ1BTQkNVQzUzY21sMFpWeHVJQ0JoY25JdWRHOVRkSEpwYm1jZ1BTQkNVQzUwYjFOMGNtbHVaMXh1SUNCaGNuSXVkRzlNYjJOaGJHVlRkSEpwYm1jZ1BTQkNVQzUwYjFOMGNtbHVaMXh1SUNCaGNuSXVkRzlLVTA5T0lEMGdRbEF1ZEc5S1UwOU9YRzRnSUdGeWNpNWxjWFZoYkhNZ1BTQkNVQzVsY1hWaGJITmNiaUFnWVhKeUxtTnZiWEJoY21VZ1BTQkNVQzVqYjIxd1lYSmxYRzRnSUdGeWNpNXBibVJsZUU5bUlEMGdRbEF1YVc1a1pYaFBabHh1SUNCaGNuSXVZMjl3ZVNBOUlFSlFMbU52Y0hsY2JpQWdZWEp5TG5Oc2FXTmxJRDBnUWxBdWMyeHBZMlZjYmlBZ1lYSnlMbkpsWVdSVlNXNTBURVVnUFNCQ1VDNXlaV0ZrVlVsdWRFeEZYRzRnSUdGeWNpNXlaV0ZrVlVsdWRFSkZJRDBnUWxBdWNtVmhaRlZKYm5SQ1JWeHVJQ0JoY25JdWNtVmhaRlZKYm5RNElEMGdRbEF1Y21WaFpGVkpiblE0WEc0Z0lHRnljaTV5WldGa1ZVbHVkREUyVEVVZ1BTQkNVQzV5WldGa1ZVbHVkREUyVEVWY2JpQWdZWEp5TG5KbFlXUlZTVzUwTVRaQ1JTQTlJRUpRTG5KbFlXUlZTVzUwTVRaQ1JWeHVJQ0JoY25JdWNtVmhaRlZKYm5Rek1reEZJRDBnUWxBdWNtVmhaRlZKYm5Rek1reEZYRzRnSUdGeWNpNXlaV0ZrVlVsdWRETXlRa1VnUFNCQ1VDNXlaV0ZrVlVsdWRETXlRa1ZjYmlBZ1lYSnlMbkpsWVdSSmJuUk1SU0E5SUVKUUxuSmxZV1JKYm5STVJWeHVJQ0JoY25JdWNtVmhaRWx1ZEVKRklEMGdRbEF1Y21WaFpFbHVkRUpGWEc0Z0lHRnljaTV5WldGa1NXNTBPQ0E5SUVKUUxuSmxZV1JKYm5RNFhHNGdJR0Z5Y2k1eVpXRmtTVzUwTVRaTVJTQTlJRUpRTG5KbFlXUkpiblF4Tmt4RlhHNGdJR0Z5Y2k1eVpXRmtTVzUwTVRaQ1JTQTlJRUpRTG5KbFlXUkpiblF4TmtKRlhHNGdJR0Z5Y2k1eVpXRmtTVzUwTXpKTVJTQTlJRUpRTG5KbFlXUkpiblF6TWt4RlhHNGdJR0Z5Y2k1eVpXRmtTVzUwTXpKQ1JTQTlJRUpRTG5KbFlXUkpiblF6TWtKRlhHNGdJR0Z5Y2k1eVpXRmtSbXh2WVhSTVJTQTlJRUpRTG5KbFlXUkdiRzloZEV4RlhHNGdJR0Z5Y2k1eVpXRmtSbXh2WVhSQ1JTQTlJRUpRTG5KbFlXUkdiRzloZEVKRlhHNGdJR0Z5Y2k1eVpXRmtSRzkxWW14bFRFVWdQU0JDVUM1eVpXRmtSRzkxWW14bFRFVmNiaUFnWVhKeUxuSmxZV1JFYjNWaWJHVkNSU0E5SUVKUUxuSmxZV1JFYjNWaWJHVkNSVnh1SUNCaGNuSXVkM0pwZEdWVlNXNTBPQ0E5SUVKUUxuZHlhWFJsVlVsdWREaGNiaUFnWVhKeUxuZHlhWFJsVlVsdWRFeEZJRDBnUWxBdWQzSnBkR1ZWU1c1MFRFVmNiaUFnWVhKeUxuZHlhWFJsVlVsdWRFSkZJRDBnUWxBdWQzSnBkR1ZWU1c1MFFrVmNiaUFnWVhKeUxuZHlhWFJsVlVsdWRERTJURVVnUFNCQ1VDNTNjbWwwWlZWSmJuUXhOa3hGWEc0Z0lHRnljaTUzY21sMFpWVkpiblF4TmtKRklEMGdRbEF1ZDNKcGRHVlZTVzUwTVRaQ1JWeHVJQ0JoY25JdWQzSnBkR1ZWU1c1ME16Sk1SU0E5SUVKUUxuZHlhWFJsVlVsdWRETXlURVZjYmlBZ1lYSnlMbmR5YVhSbFZVbHVkRE15UWtVZ1BTQkNVQzUzY21sMFpWVkpiblF6TWtKRlhHNGdJR0Z5Y2k1M2NtbDBaVWx1ZEV4RklEMGdRbEF1ZDNKcGRHVkpiblJNUlZ4dUlDQmhjbkl1ZDNKcGRHVkpiblJDUlNBOUlFSlFMbmR5YVhSbFNXNTBRa1ZjYmlBZ1lYSnlMbmR5YVhSbFNXNTBPQ0E5SUVKUUxuZHlhWFJsU1c1ME9GeHVJQ0JoY25JdWQzSnBkR1ZKYm5ReE5reEZJRDBnUWxBdWQzSnBkR1ZKYm5ReE5reEZYRzRnSUdGeWNpNTNjbWwwWlVsdWRERTJRa1VnUFNCQ1VDNTNjbWwwWlVsdWRERTJRa1ZjYmlBZ1lYSnlMbmR5YVhSbFNXNTBNekpNUlNBOUlFSlFMbmR5YVhSbFNXNTBNekpNUlZ4dUlDQmhjbkl1ZDNKcGRHVkpiblF6TWtKRklEMGdRbEF1ZDNKcGRHVkpiblF6TWtKRlhHNGdJR0Z5Y2k1M2NtbDBaVVpzYjJGMFRFVWdQU0JDVUM1M2NtbDBaVVpzYjJGMFRFVmNiaUFnWVhKeUxuZHlhWFJsUm14dllYUkNSU0E5SUVKUUxuZHlhWFJsUm14dllYUkNSVnh1SUNCaGNuSXVkM0pwZEdWRWIzVmliR1ZNUlNBOUlFSlFMbmR5YVhSbFJHOTFZbXhsVEVWY2JpQWdZWEp5TG5keWFYUmxSRzkxWW14bFFrVWdQU0JDVUM1M2NtbDBaVVJ2ZFdKc1pVSkZYRzRnSUdGeWNpNW1hV3hzSUQwZ1FsQXVabWxzYkZ4dUlDQmhjbkl1YVc1emNHVmpkQ0E5SUVKUUxtbHVjM0JsWTNSY2JpQWdZWEp5TG5SdlFYSnlZWGxDZFdabVpYSWdQU0JDVUM1MGIwRnljbUY1UW5WbVptVnlYRzVjYmlBZ2NtVjBkWEp1SUdGeWNseHVmVnh1WEc1MllYSWdTVTVXUVV4SlJGOUNRVk5GTmpSZlVrVWdQU0F2VzE0clhGd3ZNQzA1UVMxYVlTMTZMVjlkTDJkY2JseHVablZ1WTNScGIyNGdZbUZ6WlRZMFkyeGxZVzRnS0hOMGNpa2dlMXh1SUNBdkx5Qk9iMlJsSUhOMGNtbHdjeUJ2ZFhRZ2FXNTJZV3hwWkNCamFHRnlZV04wWlhKeklHeHBhMlVnWEZ4dUlHRnVaQ0JjWEhRZ1puSnZiU0IwYUdVZ2MzUnlhVzVuTENCaVlYTmxOalF0YW5NZ1pHOWxjeUJ1YjNSY2JpQWdjM1J5SUQwZ2MzUnlhVzVuZEhKcGJTaHpkSElwTG5KbGNHeGhZMlVvU1U1V1FVeEpSRjlDUVZORk5qUmZVa1VzSUNjbktWeHVJQ0F2THlCT2IyUmxJR052Ym5abGNuUnpJSE4wY21sdVozTWdkMmwwYUNCc1pXNW5kR2dnUENBeUlIUnZJQ2NuWEc0Z0lHbG1JQ2h6ZEhJdWJHVnVaM1JvSUR3Z01pa2djbVYwZFhKdUlDY25YRzRnSUM4dklFNXZaR1VnWVd4c2IzZHpJR1p2Y2lCdWIyNHRjR0ZrWkdWa0lHSmhjMlUyTkNCemRISnBibWR6SUNodGFYTnphVzVuSUhSeVlXbHNhVzVuSUQwOVBTa3NJR0poYzJVMk5DMXFjeUJrYjJWeklHNXZkRnh1SUNCM2FHbHNaU0FvYzNSeUxteGxibWQwYUNBbElEUWdJVDA5SURBcElIdGNiaUFnSUNCemRISWdQU0J6ZEhJZ0t5QW5QU2RjYmlBZ2ZWeHVJQ0J5WlhSMWNtNGdjM1J5WEc1OVhHNWNibVoxYm1OMGFXOXVJSE4wY21sdVozUnlhVzBnS0hOMGNpa2dlMXh1SUNCcFppQW9jM1J5TG5SeWFXMHBJSEpsZEhWeWJpQnpkSEl1ZEhKcGJTZ3BYRzRnSUhKbGRIVnliaUJ6ZEhJdWNtVndiR0ZqWlNndlhseGNjeXQ4WEZ4ekt5UXZaeXdnSnljcFhHNTlYRzVjYm1aMWJtTjBhVzl1SUhSdlNHVjRJQ2h1S1NCN1hHNGdJR2xtSUNodUlEd2dNVFlwSUhKbGRIVnliaUFuTUNjZ0t5QnVMblJ2VTNSeWFXNW5LREUyS1Z4dUlDQnlaWFIxY200Z2JpNTBiMU4wY21sdVp5Z3hOaWxjYm4xY2JseHVablZ1WTNScGIyNGdkWFJtT0ZSdlFubDBaWE1nS0hOMGNtbHVaeXdnZFc1cGRITXBJSHRjYmlBZ2RXNXBkSE1nUFNCMWJtbDBjeUI4ZkNCSmJtWnBibWwwZVZ4dUlDQjJZWElnWTI5a1pWQnZhVzUwWEc0Z0lIWmhjaUJzWlc1bmRHZ2dQU0J6ZEhKcGJtY3ViR1Z1WjNSb1hHNGdJSFpoY2lCc1pXRmtVM1Z5Y205bllYUmxJRDBnYm5Wc2JGeHVJQ0IyWVhJZ1lubDBaWE1nUFNCYlhWeHVYRzRnSUdadmNpQW9kbUZ5SUdrZ1BTQXdPeUJwSUR3Z2JHVnVaM1JvT3lCcEt5c3BJSHRjYmlBZ0lDQmpiMlJsVUc5cGJuUWdQU0J6ZEhKcGJtY3VZMmhoY2tOdlpHVkJkQ2hwS1Z4dVhHNGdJQ0FnTHk4Z2FYTWdjM1Z5Y205bllYUmxJR052YlhCdmJtVnVkRnh1SUNBZ0lHbG1JQ2hqYjJSbFVHOXBiblFnUGlBd2VFUTNSa1lnSmlZZ1kyOWtaVkJ2YVc1MElEd2dNSGhGTURBd0tTQjdYRzRnSUNBZ0lDQXZMeUJzWVhOMElHTm9ZWElnZDJGeklHRWdiR1ZoWkZ4dUlDQWdJQ0FnYVdZZ0tDRnNaV0ZrVTNWeWNtOW5ZWFJsS1NCN1hHNGdJQ0FnSUNBZ0lDOHZJRzV2SUd4bFlXUWdlV1YwWEc0Z0lDQWdJQ0FnSUdsbUlDaGpiMlJsVUc5cGJuUWdQaUF3ZUVSQ1JrWXBJSHRjYmlBZ0lDQWdJQ0FnSUNBdkx5QjFibVY0Y0dWamRHVmtJSFJ5WVdsc1hHNGdJQ0FnSUNBZ0lDQWdhV1lnS0NoMWJtbDBjeUF0UFNBektTQStJQzB4S1NCaWVYUmxjeTV3ZFhOb0tEQjRSVVlzSURCNFFrWXNJREI0UWtRcFhHNGdJQ0FnSUNBZ0lDQWdZMjl1ZEdsdWRXVmNiaUFnSUNBZ0lDQWdmU0JsYkhObElHbG1JQ2hwSUNzZ01TQTlQVDBnYkdWdVozUm9LU0I3WEc0Z0lDQWdJQ0FnSUNBZ0x5OGdkVzV3WVdseVpXUWdiR1ZoWkZ4dUlDQWdJQ0FnSUNBZ0lHbG1JQ2dvZFc1cGRITWdMVDBnTXlrZ1BpQXRNU2tnWW5sMFpYTXVjSFZ6YUNnd2VFVkdMQ0F3ZUVKR0xDQXdlRUpFS1Z4dUlDQWdJQ0FnSUNBZ0lHTnZiblJwYm5WbFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0F2THlCMllXeHBaQ0JzWldGa1hHNGdJQ0FnSUNBZ0lHeGxZV1JUZFhKeWIyZGhkR1VnUFNCamIyUmxVRzlwYm5SY2JseHVJQ0FnSUNBZ0lDQmpiMjUwYVc1MVpWeHVJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQXZMeUF5SUd4bFlXUnpJR2x1SUdFZ2NtOTNYRzRnSUNBZ0lDQnBaaUFvWTI5a1pWQnZhVzUwSUR3Z01IaEVRekF3S1NCN1hHNGdJQ0FnSUNBZ0lHbG1JQ2dvZFc1cGRITWdMVDBnTXlrZ1BpQXRNU2tnWW5sMFpYTXVjSFZ6YUNnd2VFVkdMQ0F3ZUVKR0xDQXdlRUpFS1Z4dUlDQWdJQ0FnSUNCc1pXRmtVM1Z5Y205bllYUmxJRDBnWTI5a1pWQnZhVzUwWEc0Z0lDQWdJQ0FnSUdOdmJuUnBiblZsWEc0Z0lDQWdJQ0I5WEc1Y2JpQWdJQ0FnSUM4dklIWmhiR2xrSUhOMWNuSnZaMkYwWlNCd1lXbHlYRzRnSUNBZ0lDQmpiMlJsVUc5cGJuUWdQU0FvYkdWaFpGTjFjbkp2WjJGMFpTQXRJREI0UkRnd01DQThQQ0F4TUNCOElHTnZaR1ZRYjJsdWRDQXRJREI0UkVNd01Da2dLeUF3ZURFd01EQXdYRzRnSUNBZ2ZTQmxiSE5sSUdsbUlDaHNaV0ZrVTNWeWNtOW5ZWFJsS1NCN1hHNGdJQ0FnSUNBdkx5QjJZV3hwWkNCaWJYQWdZMmhoY2l3Z1luVjBJR3hoYzNRZ1kyaGhjaUIzWVhNZ1lTQnNaV0ZrWEc0Z0lDQWdJQ0JwWmlBb0tIVnVhWFJ6SUMwOUlETXBJRDRnTFRFcElHSjVkR1Z6TG5CMWMyZ29NSGhGUml3Z01IaENSaXdnTUhoQ1JDbGNiaUFnSUNCOVhHNWNiaUFnSUNCc1pXRmtVM1Z5Y205bllYUmxJRDBnYm5Wc2JGeHVYRzRnSUNBZ0x5OGdaVzVqYjJSbElIVjBaamhjYmlBZ0lDQnBaaUFvWTI5a1pWQnZhVzUwSUR3Z01IZzRNQ2tnZTF4dUlDQWdJQ0FnYVdZZ0tDaDFibWwwY3lBdFBTQXhLU0E4SURBcElHSnlaV0ZyWEc0Z0lDQWdJQ0JpZVhSbGN5NXdkWE5vS0dOdlpHVlFiMmx1ZENsY2JpQWdJQ0I5SUdWc2MyVWdhV1lnS0dOdlpHVlFiMmx1ZENBOElEQjRPREF3S1NCN1hHNGdJQ0FnSUNCcFppQW9LSFZ1YVhSeklDMDlJRElwSUR3Z01Da2dZbkpsWVd0Y2JpQWdJQ0FnSUdKNWRHVnpMbkIxYzJnb1hHNGdJQ0FnSUNBZ0lHTnZaR1ZRYjJsdWRDQStQaUF3ZURZZ2ZDQXdlRU13TEZ4dUlDQWdJQ0FnSUNCamIyUmxVRzlwYm5RZ0ppQXdlRE5HSUh3Z01IZzRNRnh1SUNBZ0lDQWdLVnh1SUNBZ0lIMGdaV3h6WlNCcFppQW9ZMjlrWlZCdmFXNTBJRHdnTUhneE1EQXdNQ2tnZTF4dUlDQWdJQ0FnYVdZZ0tDaDFibWwwY3lBdFBTQXpLU0E4SURBcElHSnlaV0ZyWEc0Z0lDQWdJQ0JpZVhSbGN5NXdkWE5vS0Z4dUlDQWdJQ0FnSUNCamIyUmxVRzlwYm5RZ1BqNGdNSGhESUh3Z01IaEZNQ3hjYmlBZ0lDQWdJQ0FnWTI5a1pWQnZhVzUwSUQ0K0lEQjROaUFtSURCNE0wWWdmQ0F3ZURnd0xGeHVJQ0FnSUNBZ0lDQmpiMlJsVUc5cGJuUWdKaUF3ZUROR0lId2dNSGc0TUZ4dUlDQWdJQ0FnS1Z4dUlDQWdJSDBnWld4elpTQnBaaUFvWTI5a1pWQnZhVzUwSUR3Z01IZ3hNVEF3TURBcElIdGNiaUFnSUNBZ0lHbG1JQ2dvZFc1cGRITWdMVDBnTkNrZ1BDQXdLU0JpY21WaGExeHVJQ0FnSUNBZ1lubDBaWE11Y0hWemFDaGNiaUFnSUNBZ0lDQWdZMjlrWlZCdmFXNTBJRDQrSURCNE1USWdmQ0F3ZUVZd0xGeHVJQ0FnSUNBZ0lDQmpiMlJsVUc5cGJuUWdQajRnTUhoRElDWWdNSGd6UmlCOElEQjRPREFzWEc0Z0lDQWdJQ0FnSUdOdlpHVlFiMmx1ZENBK1BpQXdlRFlnSmlBd2VETkdJSHdnTUhnNE1DeGNiaUFnSUNBZ0lDQWdZMjlrWlZCdmFXNTBJQ1lnTUhnelJpQjhJREI0T0RCY2JpQWdJQ0FnSUNsY2JpQWdJQ0I5SUdWc2MyVWdlMXh1SUNBZ0lDQWdkR2h5YjNjZ2JtVjNJRVZ5Y205eUtDZEpiblpoYkdsa0lHTnZaR1VnY0c5cGJuUW5LVnh1SUNBZ0lIMWNiaUFnZlZ4dVhHNGdJSEpsZEhWeWJpQmllWFJsYzF4dWZWeHVYRzVtZFc1amRHbHZiaUJoYzJOcGFWUnZRbmwwWlhNZ0tITjBjaWtnZTF4dUlDQjJZWElnWW5sMFpVRnljbUY1SUQwZ1cxMWNiaUFnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCemRISXViR1Z1WjNSb095QnBLeXNwSUh0Y2JpQWdJQ0F2THlCT2IyUmxKM01nWTI5a1pTQnpaV1Z0Y3lCMGJ5QmlaU0JrYjJsdVp5QjBhR2x6SUdGdVpDQnViM1FnSmlBd2VEZEdMaTVjYmlBZ0lDQmllWFJsUVhKeVlYa3VjSFZ6YUNoemRISXVZMmhoY2tOdlpHVkJkQ2hwS1NBbUlEQjRSa1lwWEc0Z0lIMWNiaUFnY21WMGRYSnVJR0o1ZEdWQmNuSmhlVnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQjFkR1l4Tm14bFZHOUNlWFJsY3lBb2MzUnlMQ0IxYm1sMGN5a2dlMXh1SUNCMllYSWdZeXdnYUdrc0lHeHZYRzRnSUhaaGNpQmllWFJsUVhKeVlYa2dQU0JiWFZ4dUlDQm1iM0lnS0haaGNpQnBJRDBnTURzZ2FTQThJSE4wY2k1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lHbG1JQ2dvZFc1cGRITWdMVDBnTWlrZ1BDQXdLU0JpY21WaGExeHVYRzRnSUNBZ1l5QTlJSE4wY2k1amFHRnlRMjlrWlVGMEtHa3BYRzRnSUNBZ2FHa2dQU0JqSUQ0K0lEaGNiaUFnSUNCc2J5QTlJR01nSlNBeU5UWmNiaUFnSUNCaWVYUmxRWEp5WVhrdWNIVnphQ2hzYnlsY2JpQWdJQ0JpZVhSbFFYSnlZWGt1Y0hWemFDaG9hU2xjYmlBZ2ZWeHVYRzRnSUhKbGRIVnliaUJpZVhSbFFYSnlZWGxjYm4xY2JseHVablZ1WTNScGIyNGdZbUZ6WlRZMFZHOUNlWFJsY3lBb2MzUnlLU0I3WEc0Z0lISmxkSFZ5YmlCaVlYTmxOalF1ZEc5Q2VYUmxRWEp5WVhrb1ltRnpaVFkwWTJ4bFlXNG9jM1J5S1NsY2JuMWNibHh1Wm5WdVkzUnBiMjRnWW14cGRFSjFabVpsY2lBb2MzSmpMQ0JrYzNRc0lHOW1abk5sZEN3Z2JHVnVaM1JvS1NCN1hHNGdJR1p2Y2lBb2RtRnlJR2tnUFNBd095QnBJRHdnYkdWdVozUm9PeUJwS3lzcElIdGNiaUFnSUNCcFppQW9LR2tnS3lCdlptWnpaWFFnUGowZ1pITjBMbXhsYm1kMGFDa2dmSHdnS0drZ1BqMGdjM0pqTG14bGJtZDBhQ2twSUdKeVpXRnJYRzRnSUNBZ1pITjBXMmtnS3lCdlptWnpaWFJkSUQwZ2MzSmpXMmxkWEc0Z0lIMWNiaUFnY21WMGRYSnVJR2xjYm4xY2JpSmRmUT09IiwidmFyIGxvb2t1cCA9ICdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvJztcblxuOyhmdW5jdGlvbiAoZXhwb3J0cykge1xuXHQndXNlIHN0cmljdCc7XG5cbiAgdmFyIEFyciA9ICh0eXBlb2YgVWludDhBcnJheSAhPT0gJ3VuZGVmaW5lZCcpXG4gICAgPyBVaW50OEFycmF5XG4gICAgOiBBcnJheVxuXG5cdHZhciBQTFVTICAgPSAnKycuY2hhckNvZGVBdCgwKVxuXHR2YXIgU0xBU0ggID0gJy8nLmNoYXJDb2RlQXQoMClcblx0dmFyIE5VTUJFUiA9ICcwJy5jaGFyQ29kZUF0KDApXG5cdHZhciBMT1dFUiAgPSAnYScuY2hhckNvZGVBdCgwKVxuXHR2YXIgVVBQRVIgID0gJ0EnLmNoYXJDb2RlQXQoMClcblx0dmFyIFBMVVNfVVJMX1NBRkUgPSAnLScuY2hhckNvZGVBdCgwKVxuXHR2YXIgU0xBU0hfVVJMX1NBRkUgPSAnXycuY2hhckNvZGVBdCgwKVxuXG5cdGZ1bmN0aW9uIGRlY29kZSAoZWx0KSB7XG5cdFx0dmFyIGNvZGUgPSBlbHQuY2hhckNvZGVBdCgwKVxuXHRcdGlmIChjb2RlID09PSBQTFVTIHx8XG5cdFx0ICAgIGNvZGUgPT09IFBMVVNfVVJMX1NBRkUpXG5cdFx0XHRyZXR1cm4gNjIgLy8gJysnXG5cdFx0aWYgKGNvZGUgPT09IFNMQVNIIHx8XG5cdFx0ICAgIGNvZGUgPT09IFNMQVNIX1VSTF9TQUZFKVxuXHRcdFx0cmV0dXJuIDYzIC8vICcvJ1xuXHRcdGlmIChjb2RlIDwgTlVNQkVSKVxuXHRcdFx0cmV0dXJuIC0xIC8vbm8gbWF0Y2hcblx0XHRpZiAoY29kZSA8IE5VTUJFUiArIDEwKVxuXHRcdFx0cmV0dXJuIGNvZGUgLSBOVU1CRVIgKyAyNiArIDI2XG5cdFx0aWYgKGNvZGUgPCBVUFBFUiArIDI2KVxuXHRcdFx0cmV0dXJuIGNvZGUgLSBVUFBFUlxuXHRcdGlmIChjb2RlIDwgTE9XRVIgKyAyNilcblx0XHRcdHJldHVybiBjb2RlIC0gTE9XRVIgKyAyNlxuXHR9XG5cblx0ZnVuY3Rpb24gYjY0VG9CeXRlQXJyYXkgKGI2NCkge1xuXHRcdHZhciBpLCBqLCBsLCB0bXAsIHBsYWNlSG9sZGVycywgYXJyXG5cblx0XHRpZiAoYjY0Lmxlbmd0aCAlIDQgPiAwKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc3RyaW5nLiBMZW5ndGggbXVzdCBiZSBhIG11bHRpcGxlIG9mIDQnKVxuXHRcdH1cblxuXHRcdC8vIHRoZSBudW1iZXIgb2YgZXF1YWwgc2lnbnMgKHBsYWNlIGhvbGRlcnMpXG5cdFx0Ly8gaWYgdGhlcmUgYXJlIHR3byBwbGFjZWhvbGRlcnMsIHRoYW4gdGhlIHR3byBjaGFyYWN0ZXJzIGJlZm9yZSBpdFxuXHRcdC8vIHJlcHJlc2VudCBvbmUgYnl0ZVxuXHRcdC8vIGlmIHRoZXJlIGlzIG9ubHkgb25lLCB0aGVuIHRoZSB0aHJlZSBjaGFyYWN0ZXJzIGJlZm9yZSBpdCByZXByZXNlbnQgMiBieXRlc1xuXHRcdC8vIHRoaXMgaXMganVzdCBhIGNoZWFwIGhhY2sgdG8gbm90IGRvIGluZGV4T2YgdHdpY2Vcblx0XHR2YXIgbGVuID0gYjY0Lmxlbmd0aFxuXHRcdHBsYWNlSG9sZGVycyA9ICc9JyA9PT0gYjY0LmNoYXJBdChsZW4gLSAyKSA/IDIgOiAnPScgPT09IGI2NC5jaGFyQXQobGVuIC0gMSkgPyAxIDogMFxuXG5cdFx0Ly8gYmFzZTY0IGlzIDQvMyArIHVwIHRvIHR3byBjaGFyYWN0ZXJzIG9mIHRoZSBvcmlnaW5hbCBkYXRhXG5cdFx0YXJyID0gbmV3IEFycihiNjQubGVuZ3RoICogMyAvIDQgLSBwbGFjZUhvbGRlcnMpXG5cblx0XHQvLyBpZiB0aGVyZSBhcmUgcGxhY2Vob2xkZXJzLCBvbmx5IGdldCB1cCB0byB0aGUgbGFzdCBjb21wbGV0ZSA0IGNoYXJzXG5cdFx0bCA9IHBsYWNlSG9sZGVycyA+IDAgPyBiNjQubGVuZ3RoIC0gNCA6IGI2NC5sZW5ndGhcblxuXHRcdHZhciBMID0gMFxuXG5cdFx0ZnVuY3Rpb24gcHVzaCAodikge1xuXHRcdFx0YXJyW0wrK10gPSB2XG5cdFx0fVxuXG5cdFx0Zm9yIChpID0gMCwgaiA9IDA7IGkgPCBsOyBpICs9IDQsIGogKz0gMykge1xuXHRcdFx0dG1wID0gKGRlY29kZShiNjQuY2hhckF0KGkpKSA8PCAxOCkgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDEpKSA8PCAxMikgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDIpKSA8PCA2KSB8IGRlY29kZShiNjQuY2hhckF0KGkgKyAzKSlcblx0XHRcdHB1c2goKHRtcCAmIDB4RkYwMDAwKSA+PiAxNilcblx0XHRcdHB1c2goKHRtcCAmIDB4RkYwMCkgPj4gOClcblx0XHRcdHB1c2godG1wICYgMHhGRilcblx0XHR9XG5cblx0XHRpZiAocGxhY2VIb2xkZXJzID09PSAyKSB7XG5cdFx0XHR0bXAgPSAoZGVjb2RlKGI2NC5jaGFyQXQoaSkpIDw8IDIpIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAxKSkgPj4gNClcblx0XHRcdHB1c2godG1wICYgMHhGRilcblx0XHR9IGVsc2UgaWYgKHBsYWNlSG9sZGVycyA9PT0gMSkge1xuXHRcdFx0dG1wID0gKGRlY29kZShiNjQuY2hhckF0KGkpKSA8PCAxMCkgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDEpKSA8PCA0KSB8IChkZWNvZGUoYjY0LmNoYXJBdChpICsgMikpID4+IDIpXG5cdFx0XHRwdXNoKCh0bXAgPj4gOCkgJiAweEZGKVxuXHRcdFx0cHVzaCh0bXAgJiAweEZGKVxuXHRcdH1cblxuXHRcdHJldHVybiBhcnJcblx0fVxuXG5cdGZ1bmN0aW9uIHVpbnQ4VG9CYXNlNjQgKHVpbnQ4KSB7XG5cdFx0dmFyIGksXG5cdFx0XHRleHRyYUJ5dGVzID0gdWludDgubGVuZ3RoICUgMywgLy8gaWYgd2UgaGF2ZSAxIGJ5dGUgbGVmdCwgcGFkIDIgYnl0ZXNcblx0XHRcdG91dHB1dCA9IFwiXCIsXG5cdFx0XHR0ZW1wLCBsZW5ndGhcblxuXHRcdGZ1bmN0aW9uIGVuY29kZSAobnVtKSB7XG5cdFx0XHRyZXR1cm4gbG9va3VwLmNoYXJBdChudW0pXG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gdHJpcGxldFRvQmFzZTY0IChudW0pIHtcblx0XHRcdHJldHVybiBlbmNvZGUobnVtID4+IDE4ICYgMHgzRikgKyBlbmNvZGUobnVtID4+IDEyICYgMHgzRikgKyBlbmNvZGUobnVtID4+IDYgJiAweDNGKSArIGVuY29kZShudW0gJiAweDNGKVxuXHRcdH1cblxuXHRcdC8vIGdvIHRocm91Z2ggdGhlIGFycmF5IGV2ZXJ5IHRocmVlIGJ5dGVzLCB3ZSdsbCBkZWFsIHdpdGggdHJhaWxpbmcgc3R1ZmYgbGF0ZXJcblx0XHRmb3IgKGkgPSAwLCBsZW5ndGggPSB1aW50OC5sZW5ndGggLSBleHRyYUJ5dGVzOyBpIDwgbGVuZ3RoOyBpICs9IDMpIHtcblx0XHRcdHRlbXAgPSAodWludDhbaV0gPDwgMTYpICsgKHVpbnQ4W2kgKyAxXSA8PCA4KSArICh1aW50OFtpICsgMl0pXG5cdFx0XHRvdXRwdXQgKz0gdHJpcGxldFRvQmFzZTY0KHRlbXApXG5cdFx0fVxuXG5cdFx0Ly8gcGFkIHRoZSBlbmQgd2l0aCB6ZXJvcywgYnV0IG1ha2Ugc3VyZSB0byBub3QgZm9yZ2V0IHRoZSBleHRyYSBieXRlc1xuXHRcdHN3aXRjaCAoZXh0cmFCeXRlcykge1xuXHRcdFx0Y2FzZSAxOlxuXHRcdFx0XHR0ZW1wID0gdWludDhbdWludDgubGVuZ3RoIC0gMV1cblx0XHRcdFx0b3V0cHV0ICs9IGVuY29kZSh0ZW1wID4+IDIpXG5cdFx0XHRcdG91dHB1dCArPSBlbmNvZGUoKHRlbXAgPDwgNCkgJiAweDNGKVxuXHRcdFx0XHRvdXRwdXQgKz0gJz09J1xuXHRcdFx0XHRicmVha1xuXHRcdFx0Y2FzZSAyOlxuXHRcdFx0XHR0ZW1wID0gKHVpbnQ4W3VpbnQ4Lmxlbmd0aCAtIDJdIDw8IDgpICsgKHVpbnQ4W3VpbnQ4Lmxlbmd0aCAtIDFdKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKHRlbXAgPj4gMTApXG5cdFx0XHRcdG91dHB1dCArPSBlbmNvZGUoKHRlbXAgPj4gNCkgJiAweDNGKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKCh0ZW1wIDw8IDIpICYgMHgzRilcblx0XHRcdFx0b3V0cHV0ICs9ICc9J1xuXHRcdFx0XHRicmVha1xuXHRcdH1cblxuXHRcdHJldHVybiBvdXRwdXRcblx0fVxuXG5cdGV4cG9ydHMudG9CeXRlQXJyYXkgPSBiNjRUb0J5dGVBcnJheVxuXHRleHBvcnRzLmZyb21CeXRlQXJyYXkgPSB1aW50OFRvQmFzZTY0XG59KHR5cGVvZiBleHBvcnRzID09PSAndW5kZWZpbmVkJyA/ICh0aGlzLmJhc2U2NGpzID0ge30pIDogZXhwb3J0cykpXG4iLCJleHBvcnRzLnJlYWQgPSBmdW5jdGlvbiAoYnVmZmVyLCBvZmZzZXQsIGlzTEUsIG1MZW4sIG5CeXRlcykge1xuICB2YXIgZSwgbVxuICB2YXIgZUxlbiA9IG5CeXRlcyAqIDggLSBtTGVuIC0gMVxuICB2YXIgZU1heCA9ICgxIDw8IGVMZW4pIC0gMVxuICB2YXIgZUJpYXMgPSBlTWF4ID4+IDFcbiAgdmFyIG5CaXRzID0gLTdcbiAgdmFyIGkgPSBpc0xFID8gKG5CeXRlcyAtIDEpIDogMFxuICB2YXIgZCA9IGlzTEUgPyAtMSA6IDFcbiAgdmFyIHMgPSBidWZmZXJbb2Zmc2V0ICsgaV1cblxuICBpICs9IGRcblxuICBlID0gcyAmICgoMSA8PCAoLW5CaXRzKSkgLSAxKVxuICBzID4+PSAoLW5CaXRzKVxuICBuQml0cyArPSBlTGVuXG4gIGZvciAoOyBuQml0cyA+IDA7IGUgPSBlICogMjU2ICsgYnVmZmVyW29mZnNldCArIGldLCBpICs9IGQsIG5CaXRzIC09IDgpIHt9XG5cbiAgbSA9IGUgJiAoKDEgPDwgKC1uQml0cykpIC0gMSlcbiAgZSA+Pj0gKC1uQml0cylcbiAgbkJpdHMgKz0gbUxlblxuICBmb3IgKDsgbkJpdHMgPiAwOyBtID0gbSAqIDI1NiArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KSB7fVxuXG4gIGlmIChlID09PSAwKSB7XG4gICAgZSA9IDEgLSBlQmlhc1xuICB9IGVsc2UgaWYgKGUgPT09IGVNYXgpIHtcbiAgICByZXR1cm4gbSA/IE5hTiA6ICgocyA/IC0xIDogMSkgKiBJbmZpbml0eSlcbiAgfSBlbHNlIHtcbiAgICBtID0gbSArIE1hdGgucG93KDIsIG1MZW4pXG4gICAgZSA9IGUgLSBlQmlhc1xuICB9XG4gIHJldHVybiAocyA/IC0xIDogMSkgKiBtICogTWF0aC5wb3coMiwgZSAtIG1MZW4pXG59XG5cbmV4cG9ydHMud3JpdGUgPSBmdW5jdGlvbiAoYnVmZmVyLCB2YWx1ZSwgb2Zmc2V0LCBpc0xFLCBtTGVuLCBuQnl0ZXMpIHtcbiAgdmFyIGUsIG0sIGNcbiAgdmFyIGVMZW4gPSBuQnl0ZXMgKiA4IC0gbUxlbiAtIDFcbiAgdmFyIGVNYXggPSAoMSA8PCBlTGVuKSAtIDFcbiAgdmFyIGVCaWFzID0gZU1heCA+PiAxXG4gIHZhciBydCA9IChtTGVuID09PSAyMyA/IE1hdGgucG93KDIsIC0yNCkgLSBNYXRoLnBvdygyLCAtNzcpIDogMClcbiAgdmFyIGkgPSBpc0xFID8gMCA6IChuQnl0ZXMgLSAxKVxuICB2YXIgZCA9IGlzTEUgPyAxIDogLTFcbiAgdmFyIHMgPSB2YWx1ZSA8IDAgfHwgKHZhbHVlID09PSAwICYmIDEgLyB2YWx1ZSA8IDApID8gMSA6IDBcblxuICB2YWx1ZSA9IE1hdGguYWJzKHZhbHVlKVxuXG4gIGlmIChpc05hTih2YWx1ZSkgfHwgdmFsdWUgPT09IEluZmluaXR5KSB7XG4gICAgbSA9IGlzTmFOKHZhbHVlKSA/IDEgOiAwXG4gICAgZSA9IGVNYXhcbiAgfSBlbHNlIHtcbiAgICBlID0gTWF0aC5mbG9vcihNYXRoLmxvZyh2YWx1ZSkgLyBNYXRoLkxOMilcbiAgICBpZiAodmFsdWUgKiAoYyA9IE1hdGgucG93KDIsIC1lKSkgPCAxKSB7XG4gICAgICBlLS1cbiAgICAgIGMgKj0gMlxuICAgIH1cbiAgICBpZiAoZSArIGVCaWFzID49IDEpIHtcbiAgICAgIHZhbHVlICs9IHJ0IC8gY1xuICAgIH0gZWxzZSB7XG4gICAgICB2YWx1ZSArPSBydCAqIE1hdGgucG93KDIsIDEgLSBlQmlhcylcbiAgICB9XG4gICAgaWYgKHZhbHVlICogYyA+PSAyKSB7XG4gICAgICBlKytcbiAgICAgIGMgLz0gMlxuICAgIH1cblxuICAgIGlmIChlICsgZUJpYXMgPj0gZU1heCkge1xuICAgICAgbSA9IDBcbiAgICAgIGUgPSBlTWF4XG4gICAgfSBlbHNlIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgbSA9ICh2YWx1ZSAqIGMgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pXG4gICAgICBlID0gZSArIGVCaWFzXG4gICAgfSBlbHNlIHtcbiAgICAgIG0gPSB2YWx1ZSAqIE1hdGgucG93KDIsIGVCaWFzIC0gMSkgKiBNYXRoLnBvdygyLCBtTGVuKVxuICAgICAgZSA9IDBcbiAgICB9XG4gIH1cblxuICBmb3IgKDsgbUxlbiA+PSA4OyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBtICYgMHhmZiwgaSArPSBkLCBtIC89IDI1NiwgbUxlbiAtPSA4KSB7fVxuXG4gIGUgPSAoZSA8PCBtTGVuKSB8IG1cbiAgZUxlbiArPSBtTGVuXG4gIGZvciAoOyBlTGVuID4gMDsgYnVmZmVyW29mZnNldCArIGldID0gZSAmIDB4ZmYsIGkgKz0gZCwgZSAvPSAyNTYsIGVMZW4gLT0gOCkge31cblxuICBidWZmZXJbb2Zmc2V0ICsgaSAtIGRdIHw9IHMgKiAxMjhcbn1cbiIsInZhciB0b1N0cmluZyA9IHt9LnRvU3RyaW5nO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEFycmF5LmlzQXJyYXkgfHwgZnVuY3Rpb24gKGFycikge1xuICByZXR1cm4gdG9TdHJpbmcuY2FsbChhcnIpID09ICdbb2JqZWN0IEFycmF5XSc7XG59O1xuIiwiLy8gQ29weXJpZ2h0IEpveWVudCwgSW5jLiBhbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGFcbi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbi8vIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuLy8gd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuLy8gZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdFxuLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlXG4vLyBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZFxuLy8gaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTU1xuLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuLy8gTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTlxuLy8gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sXG4vLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1Jcbi8vIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEVcbi8vIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgdGhpcy5fZXZlbnRzID0gdGhpcy5fZXZlbnRzIHx8IHt9O1xuICB0aGlzLl9tYXhMaXN0ZW5lcnMgPSB0aGlzLl9tYXhMaXN0ZW5lcnMgfHwgdW5kZWZpbmVkO1xufVxubW9kdWxlLmV4cG9ydHMgPSBFdmVudEVtaXR0ZXI7XG5cbi8vIEJhY2t3YXJkcy1jb21wYXQgd2l0aCBub2RlIDAuMTAueFxuRXZlbnRFbWl0dGVyLkV2ZW50RW1pdHRlciA9IEV2ZW50RW1pdHRlcjtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fZXZlbnRzID0gdW5kZWZpbmVkO1xuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fbWF4TGlzdGVuZXJzID0gdW5kZWZpbmVkO1xuXG4vLyBCeSBkZWZhdWx0IEV2ZW50RW1pdHRlcnMgd2lsbCBwcmludCBhIHdhcm5pbmcgaWYgbW9yZSB0aGFuIDEwIGxpc3RlbmVycyBhcmVcbi8vIGFkZGVkIHRvIGl0LiBUaGlzIGlzIGEgdXNlZnVsIGRlZmF1bHQgd2hpY2ggaGVscHMgZmluZGluZyBtZW1vcnkgbGVha3MuXG5FdmVudEVtaXR0ZXIuZGVmYXVsdE1heExpc3RlbmVycyA9IDEwO1xuXG4vLyBPYnZpb3VzbHkgbm90IGFsbCBFbWl0dGVycyBzaG91bGQgYmUgbGltaXRlZCB0byAxMC4gVGhpcyBmdW5jdGlvbiBhbGxvd3Ncbi8vIHRoYXQgdG8gYmUgaW5jcmVhc2VkLiBTZXQgdG8gemVybyBmb3IgdW5saW1pdGVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5zZXRNYXhMaXN0ZW5lcnMgPSBmdW5jdGlvbihuKSB7XG4gIGlmICghaXNOdW1iZXIobikgfHwgbiA8IDAgfHwgaXNOYU4obikpXG4gICAgdGhyb3cgVHlwZUVycm9yKCduIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInKTtcbiAgdGhpcy5fbWF4TGlzdGVuZXJzID0gbjtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmVtaXQgPSBmdW5jdGlvbih0eXBlKSB7XG4gIHZhciBlciwgaGFuZGxlciwgbGVuLCBhcmdzLCBpLCBsaXN0ZW5lcnM7XG5cbiAgaWYgKCF0aGlzLl9ldmVudHMpXG4gICAgdGhpcy5fZXZlbnRzID0ge307XG5cbiAgLy8gSWYgdGhlcmUgaXMgbm8gJ2Vycm9yJyBldmVudCBsaXN0ZW5lciB0aGVuIHRocm93LlxuICBpZiAodHlwZSA9PT0gJ2Vycm9yJykge1xuICAgIGlmICghdGhpcy5fZXZlbnRzLmVycm9yIHx8XG4gICAgICAgIChpc09iamVjdCh0aGlzLl9ldmVudHMuZXJyb3IpICYmICF0aGlzLl9ldmVudHMuZXJyb3IubGVuZ3RoKSkge1xuICAgICAgZXIgPSBhcmd1bWVudHNbMV07XG4gICAgICBpZiAoZXIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICB0aHJvdyBlcjsgLy8gVW5oYW5kbGVkICdlcnJvcicgZXZlbnRcbiAgICAgIH1cbiAgICAgIHRocm93IFR5cGVFcnJvcignVW5jYXVnaHQsIHVuc3BlY2lmaWVkIFwiZXJyb3JcIiBldmVudC4nKTtcbiAgICB9XG4gIH1cblxuICBoYW5kbGVyID0gdGhpcy5fZXZlbnRzW3R5cGVdO1xuXG4gIGlmIChpc1VuZGVmaW5lZChoYW5kbGVyKSlcbiAgICByZXR1cm4gZmFsc2U7XG5cbiAgaWYgKGlzRnVuY3Rpb24oaGFuZGxlcikpIHtcbiAgICBzd2l0Y2ggKGFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgIC8vIGZhc3QgY2FzZXNcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgaGFuZGxlci5jYWxsKHRoaXMpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMjpcbiAgICAgICAgaGFuZGxlci5jYWxsKHRoaXMsIGFyZ3VtZW50c1sxXSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzOlxuICAgICAgICBoYW5kbGVyLmNhbGwodGhpcywgYXJndW1lbnRzWzFdLCBhcmd1bWVudHNbMl0pO1xuICAgICAgICBicmVhaztcbiAgICAgIC8vIHNsb3dlclxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgbGVuID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgICAgICAgYXJncyA9IG5ldyBBcnJheShsZW4gLSAxKTtcbiAgICAgICAgZm9yIChpID0gMTsgaSA8IGxlbjsgaSsrKVxuICAgICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgICBoYW5kbGVyLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChpc09iamVjdChoYW5kbGVyKSkge1xuICAgIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgYXJncyA9IG5ldyBBcnJheShsZW4gLSAxKTtcbiAgICBmb3IgKGkgPSAxOyBpIDwgbGVuOyBpKyspXG4gICAgICBhcmdzW2kgLSAxXSA9IGFyZ3VtZW50c1tpXTtcblxuICAgIGxpc3RlbmVycyA9IGhhbmRsZXIuc2xpY2UoKTtcbiAgICBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKylcbiAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBhcmdzKTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBtO1xuXG4gIGlmICghaXNGdW5jdGlvbihsaXN0ZW5lcikpXG4gICAgdGhyb3cgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblxuICBpZiAoIXRoaXMuX2V2ZW50cylcbiAgICB0aGlzLl9ldmVudHMgPSB7fTtcblxuICAvLyBUbyBhdm9pZCByZWN1cnNpb24gaW4gdGhlIGNhc2UgdGhhdCB0eXBlID09PSBcIm5ld0xpc3RlbmVyXCIhIEJlZm9yZVxuICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gIGlmICh0aGlzLl9ldmVudHMubmV3TGlzdGVuZXIpXG4gICAgdGhpcy5lbWl0KCduZXdMaXN0ZW5lcicsIHR5cGUsXG4gICAgICAgICAgICAgIGlzRnVuY3Rpb24obGlzdGVuZXIubGlzdGVuZXIpID9cbiAgICAgICAgICAgICAgbGlzdGVuZXIubGlzdGVuZXIgOiBsaXN0ZW5lcik7XG5cbiAgaWYgKCF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgdGhpcy5fZXZlbnRzW3R5cGVdID0gbGlzdGVuZXI7XG4gIGVsc2UgaWYgKGlzT2JqZWN0KHRoaXMuX2V2ZW50c1t0eXBlXSkpXG4gICAgLy8gSWYgd2UndmUgYWxyZWFkeSBnb3QgYW4gYXJyYXksIGp1c3QgYXBwZW5kLlxuICAgIHRoaXMuX2V2ZW50c1t0eXBlXS5wdXNoKGxpc3RlbmVyKTtcbiAgZWxzZVxuICAgIC8vIEFkZGluZyB0aGUgc2Vjb25kIGVsZW1lbnQsIG5lZWQgdG8gY2hhbmdlIHRvIGFycmF5LlxuICAgIHRoaXMuX2V2ZW50c1t0eXBlXSA9IFt0aGlzLl9ldmVudHNbdHlwZV0sIGxpc3RlbmVyXTtcblxuICAvLyBDaGVjayBmb3IgbGlzdGVuZXIgbGVha1xuICBpZiAoaXNPYmplY3QodGhpcy5fZXZlbnRzW3R5cGVdKSAmJiAhdGhpcy5fZXZlbnRzW3R5cGVdLndhcm5lZCkge1xuICAgIHZhciBtO1xuICAgIGlmICghaXNVbmRlZmluZWQodGhpcy5fbWF4TGlzdGVuZXJzKSkge1xuICAgICAgbSA9IHRoaXMuX21heExpc3RlbmVycztcbiAgICB9IGVsc2Uge1xuICAgICAgbSA9IEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH1cblxuICAgIGlmIChtICYmIG0gPiAwICYmIHRoaXMuX2V2ZW50c1t0eXBlXS5sZW5ndGggPiBtKSB7XG4gICAgICB0aGlzLl9ldmVudHNbdHlwZV0ud2FybmVkID0gdHJ1ZTtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJyhub2RlKSB3YXJuaW5nOiBwb3NzaWJsZSBFdmVudEVtaXR0ZXIgbWVtb3J5ICcgK1xuICAgICAgICAgICAgICAgICAgICAnbGVhayBkZXRlY3RlZC4gJWQgbGlzdGVuZXJzIGFkZGVkLiAnICtcbiAgICAgICAgICAgICAgICAgICAgJ1VzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvIGluY3JlYXNlIGxpbWl0LicsXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2V2ZW50c1t0eXBlXS5sZW5ndGgpO1xuICAgICAgaWYgKHR5cGVvZiBjb25zb2xlLnRyYWNlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIC8vIG5vdCBzdXBwb3J0ZWQgaW4gSUUgMTBcbiAgICAgICAgY29uc29sZS50cmFjZSgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbiA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXI7XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub25jZSA9IGZ1bmN0aW9uKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICghaXNGdW5jdGlvbihsaXN0ZW5lcikpXG4gICAgdGhyb3cgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblxuICB2YXIgZmlyZWQgPSBmYWxzZTtcblxuICBmdW5jdGlvbiBnKCkge1xuICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIodHlwZSwgZyk7XG5cbiAgICBpZiAoIWZpcmVkKSB7XG4gICAgICBmaXJlZCA9IHRydWU7XG4gICAgICBsaXN0ZW5lci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIGcubGlzdGVuZXIgPSBsaXN0ZW5lcjtcbiAgdGhpcy5vbih0eXBlLCBnKTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cbi8vIGVtaXRzIGEgJ3JlbW92ZUxpc3RlbmVyJyBldmVudCBpZmYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUxpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgbGlzdGVuZXIpIHtcbiAgdmFyIGxpc3QsIHBvc2l0aW9uLCBsZW5ndGgsIGk7XG5cbiAgaWYgKCFpc0Z1bmN0aW9uKGxpc3RlbmVyKSlcbiAgICB0aHJvdyBUeXBlRXJyb3IoJ2xpc3RlbmVyIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXG4gIGlmICghdGhpcy5fZXZlbnRzIHx8ICF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgcmV0dXJuIHRoaXM7XG5cbiAgbGlzdCA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgbGVuZ3RoID0gbGlzdC5sZW5ndGg7XG4gIHBvc2l0aW9uID0gLTE7XG5cbiAgaWYgKGxpc3QgPT09IGxpc3RlbmVyIHx8XG4gICAgICAoaXNGdW5jdGlvbihsaXN0Lmxpc3RlbmVyKSAmJiBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikpIHtcbiAgICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgIGlmICh0aGlzLl9ldmVudHMucmVtb3ZlTGlzdGVuZXIpXG4gICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgbGlzdGVuZXIpO1xuXG4gIH0gZWxzZSBpZiAoaXNPYmplY3QobGlzdCkpIHtcbiAgICBmb3IgKGkgPSBsZW5ndGg7IGktLSA+IDA7KSB7XG4gICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHxcbiAgICAgICAgICAobGlzdFtpXS5saXN0ZW5lciAmJiBsaXN0W2ldLmxpc3RlbmVyID09PSBsaXN0ZW5lcikpIHtcbiAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocG9zaXRpb24gPCAwKVxuICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpIHtcbiAgICAgIGxpc3QubGVuZ3RoID0gMDtcbiAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHNbdHlwZV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGxpc3Quc3BsaWNlKHBvc2l0aW9uLCAxKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgdGhpcy5lbWl0KCdyZW1vdmVMaXN0ZW5lcicsIHR5cGUsIGxpc3RlbmVyKTtcbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBmdW5jdGlvbih0eXBlKSB7XG4gIHZhciBrZXksIGxpc3RlbmVycztcblxuICBpZiAoIXRoaXMuX2V2ZW50cylcbiAgICByZXR1cm4gdGhpcztcblxuICAvLyBub3QgbGlzdGVuaW5nIGZvciByZW1vdmVMaXN0ZW5lciwgbm8gbmVlZCB0byBlbWl0XG4gIGlmICghdGhpcy5fZXZlbnRzLnJlbW92ZUxpc3RlbmVyKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApXG4gICAgICB0aGlzLl9ldmVudHMgPSB7fTtcbiAgICBlbHNlIGlmICh0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLy8gZW1pdCByZW1vdmVMaXN0ZW5lciBmb3IgYWxsIGxpc3RlbmVycyBvbiBhbGwgZXZlbnRzXG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgZm9yIChrZXkgaW4gdGhpcy5fZXZlbnRzKSB7XG4gICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKGtleSk7XG4gICAgfVxuICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgIHRoaXMuX2V2ZW50cyA9IHt9O1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgbGlzdGVuZXJzID0gdGhpcy5fZXZlbnRzW3R5cGVdO1xuXG4gIGlmIChpc0Z1bmN0aW9uKGxpc3RlbmVycykpIHtcbiAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVycyk7XG4gIH0gZWxzZSB7XG4gICAgLy8gTElGTyBvcmRlclxuICAgIHdoaWxlIChsaXN0ZW5lcnMubGVuZ3RoKVxuICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnNbbGlzdGVuZXJzLmxlbmd0aCAtIDFdKTtcbiAgfVxuICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lcnMgPSBmdW5jdGlvbih0eXBlKSB7XG4gIHZhciByZXQ7XG4gIGlmICghdGhpcy5fZXZlbnRzIHx8ICF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgcmV0ID0gW107XG4gIGVsc2UgaWYgKGlzRnVuY3Rpb24odGhpcy5fZXZlbnRzW3R5cGVdKSlcbiAgICByZXQgPSBbdGhpcy5fZXZlbnRzW3R5cGVdXTtcbiAgZWxzZVxuICAgIHJldCA9IHRoaXMuX2V2ZW50c1t0eXBlXS5zbGljZSgpO1xuICByZXR1cm4gcmV0O1xufTtcblxuRXZlbnRFbWl0dGVyLmxpc3RlbmVyQ291bnQgPSBmdW5jdGlvbihlbWl0dGVyLCB0eXBlKSB7XG4gIHZhciByZXQ7XG4gIGlmICghZW1pdHRlci5fZXZlbnRzIHx8ICFlbWl0dGVyLl9ldmVudHNbdHlwZV0pXG4gICAgcmV0ID0gMDtcbiAgZWxzZSBpZiAoaXNGdW5jdGlvbihlbWl0dGVyLl9ldmVudHNbdHlwZV0pKVxuICAgIHJldCA9IDE7XG4gIGVsc2VcbiAgICByZXQgPSBlbWl0dGVyLl9ldmVudHNbdHlwZV0ubGVuZ3RoO1xuICByZXR1cm4gcmV0O1xufTtcblxuZnVuY3Rpb24gaXNGdW5jdGlvbihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdmdW5jdGlvbic7XG59XG5cbmZ1bmN0aW9uIGlzTnVtYmVyKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzT2JqZWN0KGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ29iamVjdCcgJiYgYXJnICE9PSBudWxsO1xufVxuXG5mdW5jdGlvbiBpc1VuZGVmaW5lZChhcmcpIHtcbiAgcmV0dXJuIGFyZyA9PT0gdm9pZCAwO1xufVxuIiwidmFyIGlzID0gcmVxdWlyZSgnLi9pcycpLFxuICAgIEdFTkVSSUMgPSAnX2dlbmVyaWMnLFxuICAgIEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ2V2ZW50cycpLkV2ZW50RW1pdHRlcixcbiAgICBzbGljZSA9IEFycmF5LnByb3RvdHlwZS5zbGljZTtcblxuZnVuY3Rpb24gZmxhdHRlbihpdGVtKXtcbiAgICByZXR1cm4gQXJyYXkuaXNBcnJheShpdGVtKSA/IGl0ZW0ucmVkdWNlKGZ1bmN0aW9uKHJlc3VsdCwgZWxlbWVudCl7XG4gICAgICAgIGlmKGVsZW1lbnQgPT0gbnVsbCl7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQuY29uY2F0KGZsYXR0ZW4oZWxlbWVudCkpO1xuICAgIH0sW10pIDogaXRlbTtcbn1cblxuZnVuY3Rpb24gYXR0YWNoUHJvcGVydGllcyhvYmplY3QsIGZpcm0pe1xuICAgIGZvcih2YXIga2V5IGluIHRoaXMuX3Byb3BlcnRpZXMpe1xuICAgICAgICB0aGlzLl9wcm9wZXJ0aWVzW2tleV0uYXR0YWNoKG9iamVjdCwgZmlybSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBvblJlbmRlcigpe1xuXG4gICAgLy8gRW5zdXJlIGFsbCBiaW5kaW5ncyBhcmUgc29tZXdoYXQgYXR0YWNoZWQganVzdCBiZWZvcmUgcmVuZGVyaW5nXG4gICAgdGhpcy5hdHRhY2godW5kZWZpbmVkLCAwKTtcblxuICAgIGZvcih2YXIga2V5IGluIHRoaXMuX3Byb3BlcnRpZXMpe1xuICAgICAgICB0aGlzLl9wcm9wZXJ0aWVzW2tleV0udXBkYXRlKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkZXRhY2hQcm9wZXJ0aWVzKGZpcm0pe1xuICAgIGZvcih2YXIga2V5IGluIHRoaXMuX3Byb3BlcnRpZXMpe1xuICAgICAgICB0aGlzLl9wcm9wZXJ0aWVzW2tleV0uZGV0YWNoKGZpcm0pO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZGVzdHJveVByb3BlcnRpZXMoKXtcbiAgICBmb3IodmFyIGtleSBpbiB0aGlzLl9wcm9wZXJ0aWVzKXtcbiAgICAgICAgdGhpcy5fcHJvcGVydGllc1trZXldLmRlc3Ryb3koKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNsb25lKCl7XG4gICAgcmV0dXJuIHRoaXMuZmFzdG4odGhpcy5jb21wb25lbnQuX3R5cGUsIHRoaXMuY29tcG9uZW50Ll9zZXR0aW5ncywgdGhpcy5jb21wb25lbnQuX2NoaWxkcmVuLmZpbHRlcihmdW5jdGlvbihjaGlsZCl7XG4gICAgICAgICAgICByZXR1cm4gIWNoaWxkLl90ZW1wbGF0ZWQ7XG4gICAgICAgIH0pLm1hcChmdW5jdGlvbihjaGlsZCl7XG4gICAgICAgICAgICByZXR1cm4gY2hpbGQuY2xvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xufVxuXG5mdW5jdGlvbiBnZXRTZXRCaW5kaW5nKG5ld0JpbmRpbmcpe1xuICAgIGlmKCFhcmd1bWVudHMubGVuZ3RoKXtcbiAgICAgICAgcmV0dXJuIHRoaXMuYmluZGluZztcbiAgICB9XG5cbiAgICBpZighaXMuYmluZGluZyhuZXdCaW5kaW5nKSl7XG4gICAgICAgIG5ld0JpbmRpbmcgPSB0aGlzLmZhc3RuLmJpbmRpbmcobmV3QmluZGluZyk7XG4gICAgfVxuXG4gICAgaWYodGhpcy5iaW5kaW5nICYmIHRoaXMuYmluZGluZyAhPT0gbmV3QmluZGluZyl7XG4gICAgICAgIHRoaXMuYmluZGluZy5yZW1vdmVMaXN0ZW5lcignY2hhbmdlJywgdGhpcy5lbWl0QXR0YWNoKTtcbiAgICAgICAgbmV3QmluZGluZy5hdHRhY2godGhpcy5iaW5kaW5nLl9tb2RlbCwgdGhpcy5iaW5kaW5nLl9maXJtKTtcbiAgICB9XG5cbiAgICB0aGlzLmJpbmRpbmcgPSBuZXdCaW5kaW5nO1xuXG4gICAgdGhpcy5iaW5kaW5nLm9uKCdjaGFuZ2UnLCB0aGlzLmVtaXRBdHRhY2gpO1xuICAgIHRoaXMuYmluZGluZy5vbignZGV0YWNoJywgdGhpcy5lbWl0RGV0YWNoKTtcblxuICAgIHRoaXMuZW1pdEF0dGFjaCgpO1xuXG4gICAgcmV0dXJuIHRoaXMuY29tcG9uZW50O1xufTtcblxuZnVuY3Rpb24gZW1pdEF0dGFjaCgpe1xuICAgIHZhciBuZXdCb3VuZCA9IHRoaXMuYmluZGluZygpO1xuICAgIGlmKG5ld0JvdW5kICE9PSB0aGlzLmxhc3RCb3VuZCl7XG4gICAgICAgIHRoaXMubGFzdEJvdW5kID0gbmV3Qm91bmQ7XG4gICAgICAgIHRoaXMuc2NvcGUuYXR0YWNoKHRoaXMubGFzdEJvdW5kKTtcbiAgICAgICAgdGhpcy5jb21wb25lbnQuZW1pdCgnYXR0YWNoJywgdGhpcy5zY29wZSwgMSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBlbWl0RGV0YWNoKCl7XG4gICAgdGhpcy5jb21wb25lbnQuZW1pdCgnZGV0YWNoJywgMSk7XG59XG5cbmZ1bmN0aW9uIGdldFNjb3BlKCl7XG4gICAgcmV0dXJuIHRoaXMuc2NvcGU7XG59XG5cbmZ1bmN0aW9uIGRlc3Ryb3koKXtcbiAgICBpZih0aGlzLmRlc3Ryb3llZCl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5kZXN0cm95ZWQgPSB0cnVlO1xuXG4gICAgdGhpcy5jb21wb25lbnRcbiAgICAgICAgLnJlbW92ZUFsbExpc3RlbmVycygncmVuZGVyJylcbiAgICAgICAgLnJlbW92ZUFsbExpc3RlbmVycygnYXR0YWNoJyk7XG5cbiAgICB0aGlzLmNvbXBvbmVudC5lbWl0KCdkZXN0cm95Jyk7XG4gICAgdGhpcy5jb21wb25lbnQuZWxlbWVudCA9IG51bGw7XG4gICAgdGhpcy5zY29wZS5kZXN0cm95KCk7XG4gICAgdGhpcy5iaW5kaW5nLmRlc3Ryb3koKTtcblxuICAgIHJldHVybiB0aGlzLmNvbXBvbmVudDtcbn1cblxuZnVuY3Rpb24gYXR0YWNoQ29tcG9uZW50KG9iamVjdCwgZmlybSl7XG4gICAgdGhpcy5iaW5kaW5nLmF0dGFjaChvYmplY3QsIGZpcm0pO1xuICAgIHJldHVybiB0aGlzLmNvbXBvbmVudDtcbn1cblxuZnVuY3Rpb24gZGV0YWNoQ29tcG9uZW50KGZpcm0pe1xuICAgIHRoaXMuYmluZGluZy5kZXRhY2goZmlybSk7XG4gICAgcmV0dXJuIHRoaXMuY29tcG9uZW50O1xufVxuXG5mdW5jdGlvbiBpc0Rlc3Ryb3llZCgpe1xuICAgIHJldHVybiB0aGlzLmRlc3Ryb3llZDtcbn1cblxuZnVuY3Rpb24gc2V0UHJvcGVydHkoa2V5LCBwcm9wZXJ0eSl7XG5cbiAgICAvLyBBZGQgYSBkZWZhdWx0IHByb3BlcnR5IG9yIHVzZSB0aGUgb25lIGFscmVhZHkgdGhlcmVcbiAgICBpZighcHJvcGVydHkpe1xuICAgICAgICBwcm9wZXJ0eSA9IHRoaXMuY29tcG9uZW50W2tleV0gfHwgdGhpcy5mYXN0bi5wcm9wZXJ0eSgpO1xuICAgIH1cblxuICAgIHRoaXMuY29tcG9uZW50W2tleV0gPSBwcm9wZXJ0eTtcbiAgICB0aGlzLmNvbXBvbmVudC5fcHJvcGVydGllc1trZXldID0gcHJvcGVydHk7XG5cbiAgICByZXR1cm4gdGhpcy5jb21wb25lbnQ7XG59XG5cbmZ1bmN0aW9uIGV4dGVuZENvbXBvbmVudCh0eXBlLCBzZXR0aW5ncywgY2hpbGRyZW4pe1xuXG4gICAgaWYodHlwZSBpbiB0aGlzLnR5cGVzKXtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29tcG9uZW50O1xuICAgIH1cblxuICAgIGlmKCEodHlwZSBpbiB0aGlzLmZhc3RuLmNvbXBvbmVudHMpKXtcblxuICAgICAgICBpZighKEdFTkVSSUMgaW4gdGhpcy5mYXN0bi5jb21wb25lbnRzKSl7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGNvbXBvbmVudCBvZiB0eXBlIFwiJyArIHR5cGUgKyAnXCIgaXMgbG9hZGVkJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmZhc3RuLmNvbXBvbmVudHMuX2dlbmVyaWModGhpcy5mYXN0biwgdGhpcy5jb21wb25lbnQsIHR5cGUsIHNldHRpbmdzLCBjaGlsZHJlbik7XG5cbiAgICAgICAgdGhpcy50eXBlcy5fZ2VuZXJpYyA9IHRydWU7XG4gICAgfWVsc2V7XG5cbiAgICAgICAgdGhpcy5mYXN0bi5jb21wb25lbnRzW3R5cGVdKHRoaXMuZmFzdG4sIHRoaXMuY29tcG9uZW50LCB0eXBlLCBzZXR0aW5ncywgY2hpbGRyZW4pO1xuICAgIH1cblxuICAgIHRoaXMudHlwZXNbdHlwZV0gPSB0cnVlO1xuXG4gICAgcmV0dXJuIHRoaXMuY29tcG9uZW50O1xufTtcblxuZnVuY3Rpb24gaXNUeXBlKHR5cGUpe1xuICAgIHJldHVybiB0eXBlIGluIHRoaXMudHlwZXM7XG59XG5cbmZ1bmN0aW9uIEZhc3RuQ29tcG9uZW50KGZhc3RuLCB0eXBlLCBzZXR0aW5ncywgY2hpbGRyZW4pe1xuICAgIHZhciBjb21wb25lbnQgPSB0aGlzO1xuXG4gICAgdmFyIGNvbXBvbmVudFNjb3BlID0ge1xuICAgICAgICB0eXBlczoge30sXG4gICAgICAgIGZhc3RuOiBmYXN0bixcbiAgICAgICAgY29tcG9uZW50OiBjb21wb25lbnQsXG4gICAgICAgIGJpbmRpbmc6IGZhc3RuLmJpbmRpbmcoJy4nKSxcbiAgICAgICAgZGVzdHJveWVkOiBmYWxzZSxcbiAgICAgICAgc2NvcGU6IG5ldyBmYXN0bi5Nb2RlbChmYWxzZSksXG4gICAgICAgIGxhc3RCb3VuZDogbnVsbFxuICAgIH07XG5cbiAgICBjb21wb25lbnRTY29wZS5lbWl0QXR0YWNoID0gZW1pdEF0dGFjaC5iaW5kKGNvbXBvbmVudFNjb3BlKTtcbiAgICBjb21wb25lbnRTY29wZS5lbWl0RGV0YWNoID0gZW1pdERldGFjaC5iaW5kKGNvbXBvbmVudFNjb3BlKTtcbiAgICBjb21wb25lbnRTY29wZS5iaW5kaW5nLl9kZWZhdWx0X2JpbmRpbmcgPSB0cnVlO1xuXG4gICAgY29tcG9uZW50Ll90eXBlID0gdHlwZTtcbiAgICBjb21wb25lbnQuX3Byb3BlcnRpZXMgPSB7fTtcbiAgICBjb21wb25lbnQuX3NldHRpbmdzID0gc2V0dGluZ3MgfHwge307XG4gICAgY29tcG9uZW50Ll9jaGlsZHJlbiA9IGNoaWxkcmVuID8gZmxhdHRlbihjaGlsZHJlbikgOiBbXTtcblxuICAgIGNvbXBvbmVudC5hdHRhY2ggPSBhdHRhY2hDb21wb25lbnQuYmluZChjb21wb25lbnRTY29wZSk7XG4gICAgY29tcG9uZW50LmRldGFjaCA9IGRldGFjaENvbXBvbmVudC5iaW5kKGNvbXBvbmVudFNjb3BlKTtcbiAgICBjb21wb25lbnQuc2NvcGUgPSBnZXRTY29wZS5iaW5kKGNvbXBvbmVudFNjb3BlKTtcbiAgICBjb21wb25lbnQuZGVzdHJveSA9IGRlc3Ryb3kuYmluZChjb21wb25lbnRTY29wZSk7XG4gICAgY29tcG9uZW50LmRlc3Ryb3llZCA9IGlzRGVzdHJveWVkLmJpbmQoY29tcG9uZW50U2NvcGUpO1xuICAgIGNvbXBvbmVudC5iaW5kaW5nID0gZ2V0U2V0QmluZGluZy5iaW5kKGNvbXBvbmVudFNjb3BlKTtcbiAgICBjb21wb25lbnQuc2V0UHJvcGVydHkgPSBzZXRQcm9wZXJ0eS5iaW5kKGNvbXBvbmVudFNjb3BlKTtcbiAgICBjb21wb25lbnQuY2xvbmUgPSBjbG9uZS5iaW5kKGNvbXBvbmVudFNjb3BlKTtcbiAgICBjb21wb25lbnQuY2hpbGRyZW4gPSBzbGljZS5iaW5kKGNvbXBvbmVudC5fY2hpbGRyZW4pO1xuICAgIGNvbXBvbmVudC5leHRlbmQgPSBleHRlbmRDb21wb25lbnQuYmluZChjb21wb25lbnRTY29wZSk7XG4gICAgY29tcG9uZW50LmlzID0gaXNUeXBlLmJpbmQoY29tcG9uZW50U2NvcGUpO1xuXG4gICAgY29tcG9uZW50LmJpbmRpbmcoY29tcG9uZW50U2NvcGUuYmluZGluZyk7XG5cbiAgICBjb21wb25lbnQub24oJ2F0dGFjaCcsIGF0dGFjaFByb3BlcnRpZXMuYmluZCh0aGlzKSk7XG4gICAgY29tcG9uZW50Lm9uKCdyZW5kZXInLCBvblJlbmRlci5iaW5kKHRoaXMpKTtcbiAgICBjb21wb25lbnQub24oJ2RldGFjaCcsIGRldGFjaFByb3BlcnRpZXMuYmluZCh0aGlzKSk7XG4gICAgY29tcG9uZW50Lm9uKCdkZXN0cm95JywgZGVzdHJveVByb3BlcnRpZXMuYmluZCh0aGlzKSk7XG5cbiAgICBpZihmYXN0bi5kZWJ1Zyl7XG4gICAgICAgIGNvbXBvbmVudC5vbigncmVuZGVyJywgZnVuY3Rpb24oKXtcbiAgICAgICAgICAgIGlmKGNvbXBvbmVudC5lbGVtZW50ICYmIHR5cGVvZiBjb21wb25lbnQuZWxlbWVudCA9PT0gJ29iamVjdCcpe1xuICAgICAgICAgICAgICAgIGNvbXBvbmVudC5lbGVtZW50Ll9jb21wb25lbnQgPSBjb21wb25lbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbn1cbkZhc3RuQ29tcG9uZW50LnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRXZlbnRFbWl0dGVyLnByb3RvdHlwZSk7XG5GYXN0bkNvbXBvbmVudC5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBGYXN0bkNvbXBvbmVudDtcbkZhc3RuQ29tcG9uZW50LnByb3RvdHlwZS5fZmFzdG5fY29tcG9uZW50ID0gdHJ1ZTtcblxubW9kdWxlLmV4cG9ydHMgPSBGYXN0bkNvbXBvbmVudDsiLCJ2YXIgaXMgPSByZXF1aXJlKCcuL2lzJyksXG4gICAgZmlybWVyID0gcmVxdWlyZSgnLi9maXJtZXInKSxcbiAgICBmdW5jdGlvbkVtaXR0ZXIgPSByZXF1aXJlKCdmdW5jdGlvbi1lbWl0dGVyJyksXG4gICAgc2V0UHJvdG90eXBlT2YgPSByZXF1aXJlKCdzZXRwcm90b3R5cGVvZicpLFxuICAgIHNhbWUgPSByZXF1aXJlKCdzYW1lLXZhbHVlJyk7XG5cbmZ1bmN0aW9uIGZ1c2VCaW5kaW5nKCl7XG4gICAgdmFyIGZhc3RuID0gdGhpcyxcbiAgICAgICAgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cyk7XG5cbiAgICB2YXIgYmluZGluZ3MgPSBhcmdzLnNsaWNlKCksXG4gICAgICAgIHRyYW5zZm9ybSA9IGJpbmRpbmdzLnBvcCgpLFxuICAgICAgICB1cGRhdGVUcmFuc2Zvcm0sXG4gICAgICAgIHJlc3VsdEJpbmRpbmcgPSBjcmVhdGVCaW5kaW5nLmNhbGwoZmFzdG4sICdyZXN1bHQnKSxcbiAgICAgICAgc2VsZkNoYW5naW5nO1xuXG4gICAgcmVzdWx0QmluZGluZy5fYXJndW1lbnRzID0gYXJncztcblxuICAgIGlmKHR5cGVvZiBiaW5kaW5nc1tiaW5kaW5ncy5sZW5ndGgtMV0gPT09ICdmdW5jdGlvbicgJiYgIWlzLmJpbmRpbmcoYmluZGluZ3NbYmluZGluZ3MubGVuZ3RoLTFdKSl7XG4gICAgICAgIHVwZGF0ZVRyYW5zZm9ybSA9IHRyYW5zZm9ybTtcbiAgICAgICAgdHJhbnNmb3JtID0gYmluZGluZ3MucG9wKCk7XG4gICAgfVxuXG4gICAgcmVzdWx0QmluZGluZy5fbW9kZWwucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgcmVzdWx0QmluZGluZy5fc2V0ID0gZnVuY3Rpb24odmFsdWUpe1xuICAgICAgICBpZih1cGRhdGVUcmFuc2Zvcm0pe1xuICAgICAgICAgICAgc2VsZkNoYW5naW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIHZhciBuZXdWYWx1ZSA9IHVwZGF0ZVRyYW5zZm9ybSh2YWx1ZSk7XG4gICAgICAgICAgICBpZighc2FtZShuZXdWYWx1ZSwgYmluZGluZ3NbMF0oKSkpe1xuICAgICAgICAgICAgICAgIGJpbmRpbmdzWzBdKG5ld1ZhbHVlKTtcbiAgICAgICAgICAgICAgICByZXN1bHRCaW5kaW5nLl9jaGFuZ2UobmV3VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZkNoYW5naW5nID0gZmFsc2U7XG4gICAgICAgIH1lbHNle1xuICAgICAgICAgICAgcmVzdWx0QmluZGluZy5fY2hhbmdlKHZhbHVlKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBmdW5jdGlvbiBjaGFuZ2UoKXtcbiAgICAgICAgaWYoc2VsZkNoYW5naW5nKXtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICByZXN1bHRCaW5kaW5nKHRyYW5zZm9ybS5hcHBseShudWxsLCBiaW5kaW5ncy5tYXAoZnVuY3Rpb24oYmluZGluZyl7XG4gICAgICAgICAgICByZXR1cm4gYmluZGluZygpO1xuICAgICAgICB9KSkpO1xuICAgIH1cblxuICAgIGJpbmRpbmdzLmZvckVhY2goZnVuY3Rpb24oYmluZGluZywgaW5kZXgpe1xuICAgICAgICBpZighaXMuYmluZGluZyhiaW5kaW5nKSl7XG4gICAgICAgICAgICBiaW5kaW5nID0gY3JlYXRlQmluZGluZy5jYWxsKGZhc3RuLCBiaW5kaW5nKTtcbiAgICAgICAgICAgIGJpbmRpbmdzLnNwbGljZShpbmRleCwxLGJpbmRpbmcpO1xuICAgICAgICB9XG4gICAgICAgIGJpbmRpbmcub24oJ2NoYW5nZScsIGNoYW5nZSk7XG4gICAgICAgIHJlc3VsdEJpbmRpbmcub24oJ2RldGFjaCcsIGJpbmRpbmcuZGV0YWNoKTtcbiAgICB9KTtcblxuICAgIHZhciBsYXN0QXR0YWNoZWQ7XG4gICAgcmVzdWx0QmluZGluZy5vbignYXR0YWNoJywgZnVuY3Rpb24ob2JqZWN0KXtcbiAgICAgICAgc2VsZkNoYW5naW5nID0gdHJ1ZTtcbiAgICAgICAgYmluZGluZ3MuZm9yRWFjaChmdW5jdGlvbihiaW5kaW5nKXtcbiAgICAgICAgICAgIGJpbmRpbmcuYXR0YWNoKG9iamVjdCwgMSk7XG4gICAgICAgIH0pO1xuICAgICAgICBzZWxmQ2hhbmdpbmcgPSBmYWxzZTtcbiAgICAgICAgaWYobGFzdEF0dGFjaGVkICE9PSBvYmplY3Qpe1xuICAgICAgICAgICAgY2hhbmdlKCk7XG4gICAgICAgIH1cbiAgICAgICAgbGFzdEF0dGFjaGVkID0gb2JqZWN0O1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHJlc3VsdEJpbmRpbmc7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVZhbHVlQmluZGluZyhmYXN0bil7XG4gICAgdmFyIHZhbHVlQmluZGluZyA9IGNyZWF0ZUJpbmRpbmcuY2FsbChmYXN0biwgJ3ZhbHVlJyk7XG4gICAgdmFsdWVCaW5kaW5nLmF0dGFjaCA9IGZ1bmN0aW9uKCl7cmV0dXJuIHZhbHVlQmluZGluZzt9O1xuICAgIHZhbHVlQmluZGluZy5kZXRhY2ggPSBmdW5jdGlvbigpe3JldHVybiB2YWx1ZUJpbmRpbmc7fTtcbiAgICByZXR1cm4gdmFsdWVCaW5kaW5nO1xufVxuXG5mdW5jdGlvbiBiaW5kaW5nVGVtcGxhdGUobmV3VmFsdWUpe1xuICAgIGlmKCFhcmd1bWVudHMubGVuZ3RoKXtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gICAgfVxuXG4gICAgaWYodGhpcy5iaW5kaW5nLl9mYXN0bl9iaW5kaW5nID09PSAnLicpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5iaW5kaW5nLl9zZXQobmV3VmFsdWUpO1xuICAgIHJldHVybiB0aGlzLmJpbmRpbmc7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUJpbmRpbmcocGF0aCwgbW9yZSl7XG4gICAgdmFyIGZhc3RuID0gdGhpcztcblxuICAgIGlmKG1vcmUpeyAvLyB1c2VkIGluc3RlYWQgb2YgYXJndW1lbnRzLmxlbmd0aCBmb3IgcGVyZm9ybWFuY2VcbiAgICAgICAgcmV0dXJuIGZ1c2VCaW5kaW5nLmFwcGx5KGZhc3RuLCBhcmd1bWVudHMpO1xuICAgIH1cblxuICAgIGlmKHBhdGggPT0gbnVsbCl7XG4gICAgICAgIHJldHVybiBjcmVhdGVWYWx1ZUJpbmRpbmcoZmFzdG4pO1xuICAgIH1cblxuICAgIHZhciBiaW5kaW5nU2NvcGUgPSB7fSxcbiAgICAgICAgYmluZGluZyA9IGJpbmRpbmdTY29wZS5iaW5kaW5nID0gYmluZGluZ1RlbXBsYXRlLmJpbmQoYmluZGluZ1Njb3BlKSxcbiAgICAgICAgZGVzdHJveWVkO1xuXG4gICAgc2V0UHJvdG90eXBlT2YoYmluZGluZywgZnVuY3Rpb25FbWl0dGVyKTtcbiAgICBiaW5kaW5nLnNldE1heExpc3RlbmVycygxMDAwMCk7XG4gICAgYmluZGluZy5fYXJndW1lbnRzID0gW3BhdGhdO1xuICAgIGJpbmRpbmcuX21vZGVsID0gbmV3IGZhc3RuLk1vZGVsKGZhbHNlKTtcbiAgICBiaW5kaW5nLl9mYXN0bl9iaW5kaW5nID0gcGF0aDtcbiAgICBiaW5kaW5nLl9maXJtID0gLUluZmluaXR5O1xuXG4gICAgZnVuY3Rpb24gbW9kZWxBdHRhY2hIYW5kbGVyKGRhdGEpe1xuICAgICAgICBiaW5kaW5nLl9tb2RlbC5hdHRhY2goZGF0YSk7XG4gICAgICAgIGJpbmRpbmcuX2NoYW5nZShiaW5kaW5nLl9tb2RlbC5nZXQocGF0aCkpO1xuICAgICAgICBiaW5kaW5nLmVtaXQoJ2F0dGFjaCcsIGRhdGEsIDEpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1vZGVsRGV0YWNoSGFuZGxlcigpe1xuICAgICAgICBiaW5kaW5nLl9tb2RlbC5kZXRhY2goKTtcbiAgICB9XG5cbiAgICBiaW5kaW5nLmF0dGFjaCA9IGZ1bmN0aW9uKG9iamVjdCwgZmlybSl7XG5cbiAgICAgICAgLy8gSWYgdGhlIGJpbmRpbmcgaXMgYmVpbmcgYXNrZWQgdG8gYXR0YWNoIGxvb3NseSB0byBhbiBvYmplY3QsXG4gICAgICAgIC8vIGJ1dCBpdCBoYXMgYWxyZWFkeSBiZWVuIGRlZmluZWQgYXMgYmVpbmcgZmlybWx5IGF0dGFjaGVkLCBkbyBub3QgYXR0YWNoLlxuICAgICAgICBpZihmaXJtZXIoYmluZGluZywgZmlybSkpe1xuICAgICAgICAgICAgcmV0dXJuIGJpbmRpbmc7XG4gICAgICAgIH1cblxuICAgICAgICBiaW5kaW5nLl9maXJtID0gZmlybTtcblxuICAgICAgICB2YXIgaXNNb2RlbCA9IGZhc3RuLmlzTW9kZWwob2JqZWN0KTtcblxuICAgICAgICBpZihpc01vZGVsICYmIGJpbmRpbmdTY29wZS5hdHRhY2hlZE1vZGVsID09PSBvYmplY3Qpe1xuICAgICAgICAgICAgcmV0dXJuIGJpbmRpbmc7XG4gICAgICAgIH1cblxuICAgICAgICBpZihiaW5kaW5nU2NvcGUuYXR0YWNoZWRNb2RlbCl7XG4gICAgICAgICAgICBiaW5kaW5nU2NvcGUuYXR0YWNoZWRNb2RlbC5yZW1vdmVMaXN0ZW5lcignYXR0YWNoJywgbW9kZWxBdHRhY2hIYW5kbGVyKTtcbiAgICAgICAgICAgIGJpbmRpbmdTY29wZS5hdHRhY2hlZE1vZGVsLnJlbW92ZUxpc3RlbmVyKCdkZXRhY2gnLCBtb2RlbERldGFjaEhhbmRsZXIpO1xuICAgICAgICAgICAgYmluZGluZ1Njb3BlLmF0dGFjaGVkTW9kZWwgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoaXNNb2RlbCl7XG4gICAgICAgICAgICBiaW5kaW5nU2NvcGUuYXR0YWNoZWRNb2RlbCA9IG9iamVjdDtcbiAgICAgICAgICAgIGJpbmRpbmdTY29wZS5hdHRhY2hlZE1vZGVsLm9uKCdhdHRhY2gnLCBtb2RlbEF0dGFjaEhhbmRsZXIpO1xuICAgICAgICAgICAgYmluZGluZ1Njb3BlLmF0dGFjaGVkTW9kZWwub24oJ2RldGFjaCcsIG1vZGVsRGV0YWNoSGFuZGxlcik7XG4gICAgICAgICAgICBvYmplY3QgPSBvYmplY3QuX21vZGVsO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIShvYmplY3QgaW5zdGFuY2VvZiBPYmplY3QpKXtcbiAgICAgICAgICAgIG9iamVjdCA9IHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoYmluZGluZy5fbW9kZWwuX21vZGVsID09PSBvYmplY3Qpe1xuICAgICAgICAgICAgcmV0dXJuIGJpbmRpbmc7XG4gICAgICAgIH1cblxuICAgICAgICBtb2RlbEF0dGFjaEhhbmRsZXIob2JqZWN0KTtcblxuICAgICAgICByZXR1cm4gYmluZGluZztcbiAgICB9O1xuXG4gICAgYmluZGluZy5kZXRhY2ggPSBmdW5jdGlvbihmaXJtKXtcbiAgICAgICAgaWYoZmlybWVyKGJpbmRpbmcsIGZpcm0pKXtcbiAgICAgICAgICAgIHJldHVybiBiaW5kaW5nO1xuICAgICAgICB9XG5cbiAgICAgICAgYmluZGluZ1Njb3BlLnZhbHVlID0gdW5kZWZpbmVkO1xuICAgICAgICBpZihiaW5kaW5nLl9tb2RlbC5pc0F0dGFjaGVkKCkpe1xuICAgICAgICAgICAgYmluZGluZy5fbW9kZWwuZGV0YWNoKCk7XG4gICAgICAgIH1cbiAgICAgICAgYmluZGluZy5lbWl0KCdkZXRhY2gnLCAxKTtcbiAgICAgICAgcmV0dXJuIGJpbmRpbmc7XG4gICAgfTtcbiAgICBiaW5kaW5nLl9zZXQgPSBmdW5jdGlvbihuZXdWYWx1ZSl7XG4gICAgICAgIGlmKHNhbWUoYmluZGluZy5fbW9kZWwuZ2V0KHBhdGgpLCBuZXdWYWx1ZSkpe1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmKCFiaW5kaW5nLl9tb2RlbC5pc0F0dGFjaGVkKCkpe1xuICAgICAgICAgICAgYmluZGluZy5fbW9kZWwuYXR0YWNoKGJpbmRpbmcuX21vZGVsLmdldCgnLicpKTtcbiAgICAgICAgfVxuICAgICAgICBiaW5kaW5nLl9tb2RlbC5zZXQocGF0aCwgbmV3VmFsdWUpO1xuICAgIH07XG4gICAgYmluZGluZy5fY2hhbmdlID0gZnVuY3Rpb24obmV3VmFsdWUpe1xuICAgICAgICBiaW5kaW5nU2NvcGUudmFsdWUgPSBuZXdWYWx1ZTtcbiAgICAgICAgYmluZGluZy5lbWl0KCdjaGFuZ2UnLCBiaW5kaW5nKCkpO1xuICAgIH07XG4gICAgYmluZGluZy5jbG9uZSA9IGZ1bmN0aW9uKGtlZXBBdHRhY2htZW50KXtcbiAgICAgICAgdmFyIG5ld0JpbmRpbmcgPSBjcmVhdGVCaW5kaW5nLmFwcGx5KGZhc3RuLCBiaW5kaW5nLl9hcmd1bWVudHMpO1xuXG4gICAgICAgIGlmKGtlZXBBdHRhY2htZW50KXtcbiAgICAgICAgICAgIG5ld0JpbmRpbmcuYXR0YWNoKGJpbmRpbmdTY29wZS5hdHRhY2hlZE1vZGVsIHx8IGJpbmRpbmcuX21vZGVsLl9tb2RlbCwgYmluZGluZy5fZmlybSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbmV3QmluZGluZztcbiAgICB9O1xuICAgIGJpbmRpbmcuZGVzdHJveSA9IGZ1bmN0aW9uKHNvZnQpe1xuICAgICAgICBpZihkZXN0cm95ZWQpe1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmKHNvZnQgJiYgYmluZGluZy5saXN0ZW5lcnMoJ2NoYW5nZScpLmxlbmd0aCl7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZGVzdHJveWVkID0gdHJ1ZTtcbiAgICAgICAgYmluZGluZy5lbWl0KCdkZXN0cm95Jyk7XG4gICAgICAgIGJpbmRpbmcuZGV0YWNoKCk7XG4gICAgICAgIGJpbmRpbmcuX21vZGVsLmRlc3Ryb3koKTtcbiAgICB9O1xuXG4gICAgYmluZGluZy5kZXN0cm95ZWQgPSBmdW5jdGlvbigpe1xuICAgICAgICByZXR1cm4gZGVzdHJveWVkO1xuICAgIH07XG5cbiAgICBpZihwYXRoICE9PSAnLicpe1xuICAgICAgICBiaW5kaW5nLl9tb2RlbC5vbihwYXRoLCBiaW5kaW5nLl9jaGFuZ2UpO1xuICAgIH1cblxuICAgIHJldHVybiBiaW5kaW5nO1xufVxuXG5mdW5jdGlvbiBmcm9tKHZhbHVlT3JCaW5kaW5nKXtcbiAgICBpZihpcy5iaW5kaW5nKHZhbHVlT3JCaW5kaW5nKSl7XG4gICAgICAgIHJldHVybiB2YWx1ZU9yQmluZGluZztcbiAgICB9XG5cbiAgICB2YXIgcmVzdWx0ID0gdGhpcygpO1xuICAgIHJlc3VsdCh2YWx1ZU9yQmluZGluZylcblxuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZmFzdG4pe1xuICAgIHZhciBiaW5kaW5nID0gY3JlYXRlQmluZGluZy5iaW5kKGZhc3RuKTtcbiAgICBiaW5kaW5nLmZyb20gPSBmcm9tLmJpbmQoYmluZGluZyk7XG4gICAgcmV0dXJuIGJpbmRpbmc7XG59OyIsImZ1bmN0aW9uIGluc2VydENoaWxkKGZhc3RuLCBjb250YWluZXIsIGNoaWxkLCBpbmRleCl7XG4gICAgaWYoY2hpbGQgPT0gbnVsbCB8fCBjaGlsZCA9PT0gZmFsc2Upe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGN1cnJlbnRJbmRleCA9IGNvbnRhaW5lci5fY2hpbGRyZW4uaW5kZXhPZihjaGlsZCksXG4gICAgICAgIG5ld0NvbXBvbmVudCA9IGZhc3RuLnRvQ29tcG9uZW50KGNoaWxkKTtcblxuICAgIGlmKG5ld0NvbXBvbmVudCAhPT0gY2hpbGQgJiYgfmN1cnJlbnRJbmRleCl7XG4gICAgICAgIGNvbnRhaW5lci5fY2hpbGRyZW4uc3BsaWNlKGN1cnJlbnRJbmRleCwgMSwgbmV3Q29tcG9uZW50KTtcbiAgICB9XG5cbiAgICBpZighfmN1cnJlbnRJbmRleCB8fCBuZXdDb21wb25lbnQgIT09IGNoaWxkKXtcbiAgICAgICAgbmV3Q29tcG9uZW50LmF0dGFjaChjb250YWluZXIuc2NvcGUoKSwgMSk7XG4gICAgfVxuXG4gICAgaWYoY3VycmVudEluZGV4ICE9PSBpbmRleCl7XG4gICAgICAgIGlmKH5jdXJyZW50SW5kZXgpe1xuICAgICAgICAgICAgY29udGFpbmVyLl9jaGlsZHJlbi5zcGxpY2UoY3VycmVudEluZGV4LCAxKTtcbiAgICAgICAgfVxuICAgICAgICBjb250YWluZXIuX2NoaWxkcmVuLnNwbGljZShpbmRleCwgMCwgbmV3Q29tcG9uZW50KTtcbiAgICB9XG5cbiAgICBpZihjb250YWluZXIuZWxlbWVudCl7XG4gICAgICAgIGlmKCFuZXdDb21wb25lbnQuZWxlbWVudCl7XG4gICAgICAgICAgICBuZXdDb21wb25lbnQucmVuZGVyKCk7XG4gICAgICAgIH1cbiAgICAgICAgY29udGFpbmVyLl9pbnNlcnQobmV3Q29tcG9uZW50LmVsZW1lbnQsIGluZGV4KTtcbiAgICAgICAgbmV3Q29tcG9uZW50LmVtaXQoJ2luc2VydCcsIGNvbnRhaW5lcik7XG4gICAgICAgIGNvbnRhaW5lci5lbWl0KCdjaGlsZEluc2VydCcsIG5ld0NvbXBvbmVudCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBnZXRDb250YWluZXJFbGVtZW50KCl7XG4gICAgcmV0dXJuIHRoaXMuY29udGFpbmVyRWxlbWVudCB8fCB0aGlzLmVsZW1lbnQ7XG59XG5cbmZ1bmN0aW9uIGluc2VydChjaGlsZCwgaW5kZXgpe1xuICAgIHZhciBjaGlsZENvbXBvbmVudCA9IGNoaWxkLFxuICAgICAgICBjb250YWluZXIgPSB0aGlzLmNvbnRhaW5lcixcbiAgICAgICAgZmFzdG4gPSB0aGlzLmZhc3RuO1xuXG4gICAgaWYoaW5kZXggJiYgdHlwZW9mIGluZGV4ID09PSAnb2JqZWN0Jyl7XG4gICAgICAgIGNoaWxkQ29tcG9uZW50ID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcbiAgICB9XG5cbiAgICBpZihpc05hTihpbmRleCkpe1xuICAgICAgICBpbmRleCA9IGNvbnRhaW5lci5fY2hpbGRyZW4ubGVuZ3RoO1xuICAgIH1cblxuICAgIGlmKEFycmF5LmlzQXJyYXkoY2hpbGRDb21wb25lbnQpKXtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZENvbXBvbmVudC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29udGFpbmVyLmluc2VydChjaGlsZENvbXBvbmVudFtpXSwgaSArIGluZGV4KTtcbiAgICAgICAgfVxuICAgIH1lbHNle1xuICAgICAgICBpbnNlcnRDaGlsZChmYXN0biwgY29udGFpbmVyLCBjaGlsZENvbXBvbmVudCwgaW5kZXgpO1xuICAgIH1cblxuICAgIHJldHVybiBjb250YWluZXI7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZmFzdG4sIGNvbXBvbmVudCwgdHlwZSwgc2V0dGluZ3MsIGNoaWxkcmVuKXtcbiAgICBjb21wb25lbnQuaW5zZXJ0ID0gaW5zZXJ0LmJpbmQoe1xuICAgICAgICBjb250YWluZXI6IGNvbXBvbmVudCxcbiAgICAgICAgZmFzdG46IGZhc3RuXG4gICAgfSk7XG5cbiAgICBjb21wb25lbnQuX2luc2VydCA9IGZ1bmN0aW9uKGVsZW1lbnQsIGluZGV4KXtcbiAgICAgICAgdmFyIGNvbnRhaW5lckVsZW1lbnQgPSBjb21wb25lbnQuZ2V0Q29udGFpbmVyRWxlbWVudCgpO1xuICAgICAgICBpZighY29udGFpbmVyRWxlbWVudCl7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZihjb250YWluZXJFbGVtZW50LmNoaWxkTm9kZXNbaW5kZXhdID09PSBlbGVtZW50KXtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnRhaW5lckVsZW1lbnQuaW5zZXJ0QmVmb3JlKGVsZW1lbnQsIGNvbnRhaW5lckVsZW1lbnQuY2hpbGROb2Rlc1tpbmRleF0pO1xuICAgIH07XG5cbiAgICBjb21wb25lbnQucmVtb3ZlID0gZnVuY3Rpb24oY2hpbGRDb21wb25lbnQpe1xuICAgICAgICB2YXIgaW5kZXggPSBjb21wb25lbnQuX2NoaWxkcmVuLmluZGV4T2YoY2hpbGRDb21wb25lbnQpO1xuICAgICAgICBpZih+aW5kZXgpe1xuICAgICAgICAgICAgY29tcG9uZW50Ll9jaGlsZHJlbi5zcGxpY2UoaW5kZXgsMSk7XG4gICAgICAgIH1cblxuICAgICAgICBjaGlsZENvbXBvbmVudC5kZXRhY2goMSk7XG5cbiAgICAgICAgaWYoY2hpbGRDb21wb25lbnQuZWxlbWVudCl7XG4gICAgICAgICAgICBjb21wb25lbnQuX3JlbW92ZShjaGlsZENvbXBvbmVudC5lbGVtZW50KTtcbiAgICAgICAgICAgIGNoaWxkQ29tcG9uZW50LmVtaXQoJ3JlbW92ZScsIGNvbXBvbmVudCk7XG4gICAgICAgIH1cbiAgICAgICAgY29tcG9uZW50LmVtaXQoJ2NoaWxkUmVtb3ZlJywgY2hpbGRDb21wb25lbnQpO1xuICAgIH07XG5cbiAgICBjb21wb25lbnQuX3JlbW92ZSA9IGZ1bmN0aW9uKGVsZW1lbnQpe1xuICAgICAgICB2YXIgY29udGFpbmVyRWxlbWVudCA9IGNvbXBvbmVudC5nZXRDb250YWluZXJFbGVtZW50KCk7XG5cbiAgICAgICAgaWYoIWVsZW1lbnQgfHwgIWNvbnRhaW5lckVsZW1lbnQgfHwgZWxlbWVudC5wYXJlbnROb2RlICE9PSBjb250YWluZXJFbGVtZW50KXtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnRhaW5lckVsZW1lbnQucmVtb3ZlQ2hpbGQoZWxlbWVudCk7XG4gICAgfTtcblxuICAgIGNvbXBvbmVudC5lbXB0eSA9IGZ1bmN0aW9uKCl7XG4gICAgICAgIHdoaWxlKGNvbXBvbmVudC5fY2hpbGRyZW4ubGVuZ3RoKXtcbiAgICAgICAgICAgIGNvbXBvbmVudC5yZW1vdmUoY29tcG9uZW50Ll9jaGlsZHJlbi5wb3AoKSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgY29tcG9uZW50LnJlcGxhY2VDaGlsZCA9IGZ1bmN0aW9uKG9sZENoaWxkLCBuZXdDaGlsZCl7XG4gICAgICAgIHZhciBpbmRleCA9IGNvbXBvbmVudC5fY2hpbGRyZW4uaW5kZXhPZihvbGRDaGlsZCk7XG5cbiAgICAgICAgaWYoIX5pbmRleCl7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb21wb25lbnQucmVtb3ZlKG9sZENoaWxkKTtcbiAgICAgICAgY29tcG9uZW50Lmluc2VydChuZXdDaGlsZCwgaW5kZXgpO1xuICAgIH07XG5cbiAgICBjb21wb25lbnQuZ2V0Q29udGFpbmVyRWxlbWVudCA9IGdldENvbnRhaW5lckVsZW1lbnQuYmluZChjb21wb25lbnQpO1xuXG4gICAgY29tcG9uZW50Lm9uKCdyZW5kZXInLCBjb21wb25lbnQuaW5zZXJ0LmJpbmQobnVsbCwgY29tcG9uZW50Ll9jaGlsZHJlbiwgMCkpO1xuXG4gICAgY29tcG9uZW50Lm9uKCdhdHRhY2gnLCBmdW5jdGlvbihtb2RlbCwgZmlybSl7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjb21wb25lbnQuX2NoaWxkcmVuLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgICAgIGlmKGZhc3RuLmlzQ29tcG9uZW50KGNvbXBvbmVudC5fY2hpbGRyZW5baV0pKXtcbiAgICAgICAgICAgICAgICBjb21wb25lbnQuX2NoaWxkcmVuW2ldLmF0dGFjaChtb2RlbCwgZmlybSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGNvbXBvbmVudC5vbignZGVzdHJveScsIGZ1bmN0aW9uKGRhdGEsIGZpcm0pe1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY29tcG9uZW50Ll9jaGlsZHJlbi5sZW5ndGg7IGkrKyl7XG4gICAgICAgICAgICBpZihmYXN0bi5pc0NvbXBvbmVudChjb21wb25lbnQuX2NoaWxkcmVuW2ldKSl7XG4gICAgICAgICAgICAgICAgY29tcG9uZW50Ll9jaGlsZHJlbltpXS5kZXN0cm95KGZpcm0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gY29tcG9uZW50O1xufTsiLCIvLyBJcyB0aGUgZW50aXR5IGZpcm1lciB0aGFuIHRoZSBuZXcgZmlybW5lc3Ncbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZW50aXR5LCBmaXJtKXtcbiAgICBpZihmaXJtICE9IG51bGwgJiYgKGVudGl0eS5fZmlybSA9PT0gdW5kZWZpbmVkIHx8IGZpcm0gPCBlbnRpdHkuX2Zpcm0pKXtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxufTsiLCJ2YXIgRlVOQ1RJT04gPSAnZnVuY3Rpb24nLFxuICAgIE9CSkVDVCA9ICdvYmplY3QnLFxuICAgIEZBU1ROQklORElORyA9ICdfZmFzdG5fYmluZGluZycsXG4gICAgRkFTVE5QUk9QRVJUWSA9ICdfZmFzdG5fcHJvcGVydHknLFxuICAgIEZBU1ROQ09NUE9ORU5UID0gJ19mYXN0bl9jb21wb25lbnQnLFxuICAgIERFRkFVTFRCSU5ESU5HID0gJ19kZWZhdWx0X2JpbmRpbmcnO1xuXG5mdW5jdGlvbiBpc0NvbXBvbmVudCh0aGluZyl7XG4gICAgcmV0dXJuIHRoaW5nICYmIHR5cGVvZiB0aGluZyA9PT0gT0JKRUNUICYmIEZBU1ROQ09NUE9ORU5UIGluIHRoaW5nO1xufVxuXG5mdW5jdGlvbiBpc0JpbmRpbmdPYmplY3QodGhpbmcpe1xuICAgIHJldHVybiB0aGluZyAmJiB0eXBlb2YgdGhpbmcgPT09IE9CSkVDVCAmJiBGQVNUTkJJTkRJTkcgaW4gdGhpbmc7XG59XG5cbmZ1bmN0aW9uIGlzQmluZGluZyh0aGluZyl7XG4gICAgcmV0dXJuIHR5cGVvZiB0aGluZyA9PT0gRlVOQ1RJT04gJiYgRkFTVE5CSU5ESU5HIGluIHRoaW5nO1xufVxuXG5mdW5jdGlvbiBpc1Byb3BlcnR5KHRoaW5nKXtcbiAgICByZXR1cm4gdHlwZW9mIHRoaW5nID09PSBGVU5DVElPTiAmJiBGQVNUTlBST1BFUlRZIGluIHRoaW5nO1xufVxuXG5mdW5jdGlvbiBpc0RlZmF1bHRCaW5kaW5nKHRoaW5nKXtcbiAgICByZXR1cm4gdHlwZW9mIHRoaW5nID09PSBGVU5DVElPTiAmJiBGQVNUTkJJTkRJTkcgaW4gdGhpbmcgJiYgREVGQVVMVEJJTkRJTkcgaW4gdGhpbmc7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGNvbXBvbmVudDogaXNDb21wb25lbnQsXG4gICAgYmluZGluZ09iamVjdDogaXNCaW5kaW5nT2JqZWN0LFxuICAgIGJpbmRpbmc6IGlzQmluZGluZyxcbiAgICBkZWZhdWx0QmluZGluZzogaXNEZWZhdWx0QmluZGluZyxcbiAgICBwcm9wZXJ0eTogaXNQcm9wZXJ0eVxufTsiLCIvL0NvcHlyaWdodCAoQykgMjAxMiBLb3J5IE51bm5cclxuXHJcbi8vUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcclxuXHJcbi8vVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXHJcblxyXG4vL1RIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxyXG5cclxuLypcclxuXHJcbiAgICBUaGlzIGNvZGUgaXMgbm90IGZvcm1hdHRlZCBmb3IgcmVhZGFiaWxpdHksIGJ1dCByYXRoZXIgcnVuLXNwZWVkIGFuZCB0byBhc3Npc3QgY29tcGlsZXJzLlxyXG5cclxuICAgIEhvd2V2ZXIsIHRoZSBjb2RlJ3MgaW50ZW50aW9uIHNob3VsZCBiZSB0cmFuc3BhcmVudC5cclxuXHJcbiAgICAqKiogSUUgU1VQUE9SVCAqKipcclxuXHJcbiAgICBJZiB5b3UgcmVxdWlyZSB0aGlzIGxpYnJhcnkgdG8gd29yayBpbiBJRTcsIGFkZCB0aGUgZm9sbG93aW5nIGFmdGVyIGRlY2xhcmluZyBjcmVsLlxyXG5cclxuICAgIHZhciB0ZXN0RGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JyksXHJcbiAgICAgICAgdGVzdExhYmVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGFiZWwnKTtcclxuXHJcbiAgICB0ZXN0RGl2LnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnYScpO1xyXG4gICAgdGVzdERpdlsnY2xhc3NOYW1lJ10gIT09ICdhJyA/IGNyZWwuYXR0ck1hcFsnY2xhc3MnXSA9ICdjbGFzc05hbWUnOnVuZGVmaW5lZDtcclxuICAgIHRlc3REaXYuc2V0QXR0cmlidXRlKCduYW1lJywnYScpO1xyXG4gICAgdGVzdERpdlsnbmFtZSddICE9PSAnYScgPyBjcmVsLmF0dHJNYXBbJ25hbWUnXSA9IGZ1bmN0aW9uKGVsZW1lbnQsIHZhbHVlKXtcclxuICAgICAgICBlbGVtZW50LmlkID0gdmFsdWU7XHJcbiAgICB9OnVuZGVmaW5lZDtcclxuXHJcblxyXG4gICAgdGVzdExhYmVsLnNldEF0dHJpYnV0ZSgnZm9yJywgJ2EnKTtcclxuICAgIHRlc3RMYWJlbFsnaHRtbEZvciddICE9PSAnYScgPyBjcmVsLmF0dHJNYXBbJ2ZvciddID0gJ2h0bWxGb3InOnVuZGVmaW5lZDtcclxuXHJcblxyXG5cclxuKi9cclxuXHJcbihmdW5jdGlvbiAocm9vdCwgZmFjdG9yeSkge1xyXG4gICAgaWYgKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0Jykge1xyXG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpO1xyXG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcclxuICAgICAgICBkZWZpbmUoZmFjdG9yeSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJvb3QuY3JlbCA9IGZhY3RvcnkoKTtcclxuICAgIH1cclxufSh0aGlzLCBmdW5jdGlvbiAoKSB7XHJcbiAgICB2YXIgZm4gPSAnZnVuY3Rpb24nLFxyXG4gICAgICAgIG9iaiA9ICdvYmplY3QnLFxyXG4gICAgICAgIG5vZGVUeXBlID0gJ25vZGVUeXBlJyxcclxuICAgICAgICB0ZXh0Q29udGVudCA9ICd0ZXh0Q29udGVudCcsXHJcbiAgICAgICAgc2V0QXR0cmlidXRlID0gJ3NldEF0dHJpYnV0ZScsXHJcbiAgICAgICAgYXR0ck1hcFN0cmluZyA9ICdhdHRyTWFwJyxcclxuICAgICAgICBpc05vZGVTdHJpbmcgPSAnaXNOb2RlJyxcclxuICAgICAgICBpc0VsZW1lbnRTdHJpbmcgPSAnaXNFbGVtZW50JyxcclxuICAgICAgICBkID0gdHlwZW9mIGRvY3VtZW50ID09PSBvYmogPyBkb2N1bWVudCA6IHt9LFxyXG4gICAgICAgIGlzVHlwZSA9IGZ1bmN0aW9uKGEsIHR5cGUpe1xyXG4gICAgICAgICAgICByZXR1cm4gdHlwZW9mIGEgPT09IHR5cGU7XHJcbiAgICAgICAgfSxcclxuICAgICAgICBpc05vZGUgPSB0eXBlb2YgTm9kZSA9PT0gZm4gPyBmdW5jdGlvbiAob2JqZWN0KSB7XHJcbiAgICAgICAgICAgIHJldHVybiBvYmplY3QgaW5zdGFuY2VvZiBOb2RlO1xyXG4gICAgICAgIH0gOlxyXG4gICAgICAgIC8vIGluIElFIDw9IDggTm9kZSBpcyBhbiBvYmplY3QsIG9idmlvdXNseS4uXHJcbiAgICAgICAgZnVuY3Rpb24ob2JqZWN0KXtcclxuICAgICAgICAgICAgcmV0dXJuIG9iamVjdCAmJlxyXG4gICAgICAgICAgICAgICAgaXNUeXBlKG9iamVjdCwgb2JqKSAmJlxyXG4gICAgICAgICAgICAgICAgKG5vZGVUeXBlIGluIG9iamVjdCkgJiZcclxuICAgICAgICAgICAgICAgIGlzVHlwZShvYmplY3Qub3duZXJEb2N1bWVudCxvYmopO1xyXG4gICAgICAgIH0sXHJcbiAgICAgICAgaXNFbGVtZW50ID0gZnVuY3Rpb24gKG9iamVjdCkge1xyXG4gICAgICAgICAgICByZXR1cm4gY3JlbFtpc05vZGVTdHJpbmddKG9iamVjdCkgJiYgb2JqZWN0W25vZGVUeXBlXSA9PT0gMTtcclxuICAgICAgICB9LFxyXG4gICAgICAgIGlzQXJyYXkgPSBmdW5jdGlvbihhKXtcclxuICAgICAgICAgICAgcmV0dXJuIGEgaW5zdGFuY2VvZiBBcnJheTtcclxuICAgICAgICB9LFxyXG4gICAgICAgIGFwcGVuZENoaWxkID0gZnVuY3Rpb24oZWxlbWVudCwgY2hpbGQpIHtcclxuICAgICAgICAgIGlmKCFjcmVsW2lzTm9kZVN0cmluZ10oY2hpbGQpKXtcclxuICAgICAgICAgICAgICBjaGlsZCA9IGQuY3JlYXRlVGV4dE5vZGUoY2hpbGQpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgZWxlbWVudC5hcHBlbmRDaGlsZChjaGlsZCk7XHJcbiAgICAgICAgfTtcclxuXHJcblxyXG4gICAgZnVuY3Rpb24gY3JlbCgpe1xyXG4gICAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzLCAvL05vdGU6IGFzc2lnbmVkIHRvIGEgdmFyaWFibGUgdG8gYXNzaXN0IGNvbXBpbGVycy4gU2F2ZXMgYWJvdXQgNDAgYnl0ZXMgaW4gY2xvc3VyZSBjb21waWxlci4gSGFzIG5lZ2xpZ2FibGUgZWZmZWN0IG9uIHBlcmZvcm1hbmNlLlxyXG4gICAgICAgICAgICBlbGVtZW50ID0gYXJnc1swXSxcclxuICAgICAgICAgICAgY2hpbGQsXHJcbiAgICAgICAgICAgIHNldHRpbmdzID0gYXJnc1sxXSxcclxuICAgICAgICAgICAgY2hpbGRJbmRleCA9IDIsXHJcbiAgICAgICAgICAgIGFyZ3VtZW50c0xlbmd0aCA9IGFyZ3MubGVuZ3RoLFxyXG4gICAgICAgICAgICBhdHRyaWJ1dGVNYXAgPSBjcmVsW2F0dHJNYXBTdHJpbmddO1xyXG5cclxuICAgICAgICBlbGVtZW50ID0gY3JlbFtpc0VsZW1lbnRTdHJpbmddKGVsZW1lbnQpID8gZWxlbWVudCA6IGQuY3JlYXRlRWxlbWVudChlbGVtZW50KTtcclxuICAgICAgICAvLyBzaG9ydGN1dFxyXG4gICAgICAgIGlmKGFyZ3VtZW50c0xlbmd0aCA9PT0gMSl7XHJcbiAgICAgICAgICAgIHJldHVybiBlbGVtZW50O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYoIWlzVHlwZShzZXR0aW5ncyxvYmopIHx8IGNyZWxbaXNOb2RlU3RyaW5nXShzZXR0aW5ncykgfHwgaXNBcnJheShzZXR0aW5ncykpIHtcclxuICAgICAgICAgICAgLS1jaGlsZEluZGV4O1xyXG4gICAgICAgICAgICBzZXR0aW5ncyA9IG51bGw7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBzaG9ydGN1dCBpZiB0aGVyZSBpcyBvbmx5IG9uZSBjaGlsZCB0aGF0IGlzIGEgc3RyaW5nXHJcbiAgICAgICAgaWYoKGFyZ3VtZW50c0xlbmd0aCAtIGNoaWxkSW5kZXgpID09PSAxICYmIGlzVHlwZShhcmdzW2NoaWxkSW5kZXhdLCAnc3RyaW5nJykgJiYgZWxlbWVudFt0ZXh0Q29udGVudF0gIT09IHVuZGVmaW5lZCl7XHJcbiAgICAgICAgICAgIGVsZW1lbnRbdGV4dENvbnRlbnRdID0gYXJnc1tjaGlsZEluZGV4XTtcclxuICAgICAgICB9ZWxzZXtcclxuICAgICAgICAgICAgZm9yKDsgY2hpbGRJbmRleCA8IGFyZ3VtZW50c0xlbmd0aDsgKytjaGlsZEluZGV4KXtcclxuICAgICAgICAgICAgICAgIGNoaWxkID0gYXJnc1tjaGlsZEluZGV4XTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZihjaGlsZCA9PSBudWxsKXtcclxuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShjaGlsZCkpIHtcclxuICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaT0wOyBpIDwgY2hpbGQubGVuZ3RoOyArK2kpIHtcclxuICAgICAgICAgICAgICAgICAgICBhcHBlbmRDaGlsZChlbGVtZW50LCBjaGlsZFtpXSk7XHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgIGFwcGVuZENoaWxkKGVsZW1lbnQsIGNoaWxkKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZm9yKHZhciBrZXkgaW4gc2V0dGluZ3Mpe1xyXG4gICAgICAgICAgICBpZighYXR0cmlidXRlTWFwW2tleV0pe1xyXG4gICAgICAgICAgICAgICAgZWxlbWVudFtzZXRBdHRyaWJ1dGVdKGtleSwgc2V0dGluZ3Nba2V5XSk7XHJcbiAgICAgICAgICAgIH1lbHNle1xyXG4gICAgICAgICAgICAgICAgdmFyIGF0dHIgPSBhdHRyaWJ1dGVNYXBba2V5XTtcclxuICAgICAgICAgICAgICAgIGlmKHR5cGVvZiBhdHRyID09PSBmbil7XHJcbiAgICAgICAgICAgICAgICAgICAgYXR0cihlbGVtZW50LCBzZXR0aW5nc1trZXldKTtcclxuICAgICAgICAgICAgICAgIH1lbHNle1xyXG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnRbc2V0QXR0cmlidXRlXShhdHRyLCBzZXR0aW5nc1trZXldKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGVsZW1lbnQ7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gVXNlZCBmb3IgbWFwcGluZyBvbmUga2luZCBvZiBhdHRyaWJ1dGUgdG8gdGhlIHN1cHBvcnRlZCB2ZXJzaW9uIG9mIHRoYXQgaW4gYmFkIGJyb3dzZXJzLlxyXG4gICAgY3JlbFthdHRyTWFwU3RyaW5nXSA9IHt9O1xyXG5cclxuICAgIGNyZWxbaXNFbGVtZW50U3RyaW5nXSA9IGlzRWxlbWVudDtcclxuXHJcbiAgICBjcmVsW2lzTm9kZVN0cmluZ10gPSBpc05vZGU7XHJcblxyXG4gICAgaWYodHlwZW9mIFByb3h5ICE9PSAndW5kZWZpbmVkJyl7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBQcm94eShjcmVsLCB7XHJcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24odGFyZ2V0LCBrZXkpe1xyXG4gICAgICAgICAgICAgICAgIShrZXkgaW4gY3JlbCkgJiYgKGNyZWxba2V5XSA9IGNyZWwuYmluZChudWxsLCBrZXkpKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBjcmVsW2tleV07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gY3JlbDtcclxufSkpO1xyXG4iLCIoZnVuY3Rpb24gKGdsb2JhbCl7XG52YXIgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyLFxuICAgIGlzSW5zdGFuY2UgPSByZXF1aXJlKCdpcy1pbnN0YW5jZScpO1xuXG5mdW5jdGlvbiB0b0FycmF5KGl0ZW1zKXtcbiAgICByZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoaXRlbXMpO1xufVxuXG52YXIgZGVlcFJlZ2V4ID0gL1t8Ll0vaTtcblxuZnVuY3Rpb24gbWF0Y2hEZWVwKHBhdGgpe1xuICAgIHJldHVybiAocGF0aCArICcnKS5tYXRjaChkZWVwUmVnZXgpO1xufVxuXG5mdW5jdGlvbiBpc1dpbGRjYXJkUGF0aChwYXRoKXtcbiAgICB2YXIgc3RyaW5nUGF0aCA9IChwYXRoICsgJycpO1xuICAgIHJldHVybiB+c3RyaW5nUGF0aC5pbmRleE9mKCcqJyk7XG59XG5cbmZ1bmN0aW9uIGdldFRhcmdldEtleShwYXRoKXtcbiAgICB2YXIgc3RyaW5nUGF0aCA9IChwYXRoICsgJycpO1xuICAgIHJldHVybiBzdHJpbmdQYXRoLnNwbGl0KCd8Jykuc2hpZnQoKTtcbn1cblxudmFyIGV2ZW50U3lzdGVtVmVyc2lvbiA9IDEsXG4gICAgZ2xvYmFsS2V5ID0gJ19lbnRpRXZlbnRTdGF0ZScgKyBldmVudFN5c3RlbVZlcnNpb25cbiAgICBnbG9iYWxTdGF0ZSA9IGdsb2JhbFtnbG9iYWxLZXldID0gZ2xvYmFsW2dsb2JhbEtleV0gfHwge1xuICAgICAgICBpbnN0YW5jZXM6IFtdXG4gICAgfTtcblxudmFyIG1vZGlmaWVkRW50aWVzID0gZ2xvYmFsU3RhdGUubW9kaWZpZWRFbnRpZXMgPSBnbG9iYWxTdGF0ZS5tb2RpZmllZEVudGllcyB8fCBuZXcgU2V0KCksXG4gICAgdHJhY2tlZE9iamVjdHMgPSBnbG9iYWxTdGF0ZS50cmFja2VkT2JqZWN0cyA9IGdsb2JhbFN0YXRlLnRyYWNrZWRPYmplY3RzIHx8IG5ldyBXZWFrTWFwKCk7XG5cbmZ1bmN0aW9uIGxlZnRBbmRSZXN0KHBhdGgpe1xuICAgIHZhciBzdHJpbmdQYXRoID0gKHBhdGggKyAnJyk7XG5cbiAgICAvLyBTcGVjaWFsIGNhc2Ugd2hlbiB5b3Ugd2FudCB0byBmaWx0ZXIgb24gc2VsZiAoLilcbiAgICBpZihzdHJpbmdQYXRoLnNsaWNlKDAsMikgPT09ICcufCcpe1xuICAgICAgICByZXR1cm4gWycuJywgc3RyaW5nUGF0aC5zbGljZSgyKV07XG4gICAgfVxuXG4gICAgdmFyIG1hdGNoID0gbWF0Y2hEZWVwKHN0cmluZ1BhdGgpO1xuICAgIGlmKG1hdGNoKXtcbiAgICAgICAgcmV0dXJuIFtzdHJpbmdQYXRoLnNsaWNlKDAsIG1hdGNoLmluZGV4KSwgc3RyaW5nUGF0aC5zbGljZShtYXRjaC5pbmRleCsxKV07XG4gICAgfVxuICAgIHJldHVybiBzdHJpbmdQYXRoO1xufVxuXG5mdW5jdGlvbiBpc1dpbGRjYXJkS2V5KGtleSl7XG4gICAgcmV0dXJuIGtleS5jaGFyQXQoMCkgPT09ICcqJztcbn1cblxuZnVuY3Rpb24gaXNGZXJhbGNhcmRLZXkoa2V5KXtcbiAgICByZXR1cm4ga2V5ID09PSAnKionO1xufVxuXG5mdW5jdGlvbiBhZGRIYW5kbGVyKG9iamVjdCwga2V5LCBoYW5kbGVyKXtcbiAgICB2YXIgdHJhY2tlZEtleXMgPSB0cmFja2VkT2JqZWN0cy5nZXQob2JqZWN0KTtcblxuICAgIGlmKHRyYWNrZWRLZXlzID09IG51bGwpe1xuICAgICAgICB0cmFja2VkS2V5cyA9IHt9O1xuICAgICAgICB0cmFja2VkT2JqZWN0cy5zZXQob2JqZWN0LCB0cmFja2VkS2V5cyk7XG4gICAgfVxuXG4gICAgdmFyIGhhbmRsZXJzID0gdHJhY2tlZEtleXNba2V5XTtcblxuICAgIGlmKCFoYW5kbGVycyl7XG4gICAgICAgIGhhbmRsZXJzID0gbmV3IFNldCgpO1xuICAgICAgICB0cmFja2VkS2V5c1trZXldID0gaGFuZGxlcnM7XG4gICAgfVxuXG4gICAgaGFuZGxlcnMuYWRkKGhhbmRsZXIpO1xufVxuXG5mdW5jdGlvbiByZW1vdmVIYW5kbGVyKG9iamVjdCwga2V5LCBoYW5kbGVyKXtcbiAgICB2YXIgdHJhY2tlZEtleXMgPSB0cmFja2VkT2JqZWN0cy5nZXQob2JqZWN0KTtcblxuICAgIGlmKHRyYWNrZWRLZXlzID09IG51bGwpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGhhbmRsZXJzID0gdHJhY2tlZEtleXNba2V5XTtcblxuICAgIGlmKCFoYW5kbGVycyl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBoYW5kbGVycy5kZWxldGUoaGFuZGxlcik7XG59XG5cbmZ1bmN0aW9uIHRyYWNrT2JqZWN0cyhldmVudE5hbWUsIHRyYWNrZWQsIGhhbmRsZXIsIG9iamVjdCwga2V5LCBwYXRoKXtcbiAgICBpZighb2JqZWN0IHx8IHR5cGVvZiBvYmplY3QgIT09ICdvYmplY3QnKXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciB0YXJnZXQgPSBvYmplY3Rba2V5XTtcblxuICAgIGlmKHRhcmdldCAmJiB0eXBlb2YgdGFyZ2V0ID09PSAnb2JqZWN0JyAmJiB0cmFja2VkLmhhcyh0YXJnZXQpKXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRyYWNrT2JqZWN0KGV2ZW50TmFtZSwgdHJhY2tlZCwgaGFuZGxlciwgb2JqZWN0LCBrZXksIHBhdGgpO1xufVxuXG5mdW5jdGlvbiB0cmFja0tleXMoZXZlbnROYW1lLCB0cmFja2VkLCBoYW5kbGVyLCB0YXJnZXQsIHJvb3QsIHJlc3Qpe1xuICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXModGFyZ2V0KTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKyl7XG4gICAgICAgIGlmKGlzRmVyYWxjYXJkS2V5KHJvb3QpKXtcbiAgICAgICAgICAgIHRyYWNrT2JqZWN0cyhldmVudE5hbWUsIHRyYWNrZWQsIGhhbmRsZXIsIHRhcmdldCwga2V5c1tpXSwgJyoqJyArIChyZXN0ID8gJy4nIDogJycpICsgKHJlc3QgfHwgJycpKTtcbiAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICB0cmFja09iamVjdHMoZXZlbnROYW1lLCB0cmFja2VkLCBoYW5kbGVyLCB0YXJnZXQsIGtleXNbaV0sIHJlc3QpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiB0cmFja09iamVjdChldmVudE5hbWUsIHRyYWNrZWQsIGhhbmRsZXIsIG9iamVjdCwga2V5LCBwYXRoKXtcbiAgICB2YXIgZXZlbnRLZXkgPSBrZXkgPT09ICcqKicgPyAnKicgOiBrZXksXG4gICAgICAgIHRhcmdldCA9IG9iamVjdFtrZXldLFxuICAgICAgICB0YXJnZXRJc09iamVjdCA9IHRhcmdldCAmJiB0eXBlb2YgdGFyZ2V0ID09PSAnb2JqZWN0JztcblxuICAgIHZhciBoYW5kbGUgPSBmdW5jdGlvbih2YWx1ZSwgZXZlbnQsIGVtaXRLZXkpe1xuICAgICAgICBpZihldmVudEtleSAhPT0gJyonICYmIHR5cGVvZiBvYmplY3RbZXZlbnRLZXldID09PSAnb2JqZWN0JyAmJiBvYmplY3RbZXZlbnRLZXldICE9PSB0YXJnZXQpe1xuICAgICAgICAgICAgaWYodGFyZ2V0SXNPYmplY3Qpe1xuICAgICAgICAgICAgICAgIHRyYWNrZWQuZGVsZXRlKHRhcmdldCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZW1vdmVIYW5kbGVyKG9iamVjdCwgZXZlbnRLZXksIGhhbmRsZSk7XG4gICAgICAgICAgICB0cmFja09iamVjdHMoZXZlbnROYW1lLCB0cmFja2VkLCBoYW5kbGVyLCBvYmplY3QsIGtleSwgcGF0aCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZihldmVudEtleSA9PT0gJyonKXtcbiAgICAgICAgICAgIHRyYWNrS2V5cyhldmVudE5hbWUsIHRyYWNrZWQsIGhhbmRsZXIsIG9iamVjdCwga2V5LCBwYXRoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCF0cmFja2VkLmhhcyhvYmplY3QpKXtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGtleSAhPT0gJyoqJyB8fCAhcGF0aCl7XG4gICAgICAgICAgICBoYW5kbGVyKHZhbHVlLCBldmVudCwgZW1pdEtleSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgYWRkSGFuZGxlcihvYmplY3QsIGV2ZW50S2V5LCBoYW5kbGUpO1xuXG4gICAgaWYoIXRhcmdldElzT2JqZWN0KXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRyYWNrZWQuYWRkKHRhcmdldCk7XG5cbiAgICBpZighcGF0aCl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgcm9vdEFuZFJlc3QgPSBsZWZ0QW5kUmVzdChwYXRoKSxcbiAgICAgICAgcm9vdCxcbiAgICAgICAgcmVzdDtcblxuICAgIGlmKCFBcnJheS5pc0FycmF5KHJvb3RBbmRSZXN0KSl7XG4gICAgICAgIHJvb3QgPSByb290QW5kUmVzdDtcbiAgICB9ZWxzZXtcbiAgICAgICAgcm9vdCA9IHJvb3RBbmRSZXN0WzBdO1xuICAgICAgICByZXN0ID0gcm9vdEFuZFJlc3RbMV07XG5cbiAgICAgICAgLy8gSWYgdGhlIHJvb3QgaXMgJy4nLCB3YXRjaCBmb3IgZXZlbnRzIG9uICpcbiAgICAgICAgaWYocm9vdCA9PT0gJy4nKXtcbiAgICAgICAgICAgIHJvb3QgPSAnKic7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZih0YXJnZXRJc09iamVjdCAmJiBpc1dpbGRjYXJkS2V5KHJvb3QpKXtcbiAgICAgICAgdHJhY2tLZXlzKGV2ZW50TmFtZSwgdHJhY2tlZCwgaGFuZGxlciwgdGFyZ2V0LCByb290LCByZXN0KTtcbiAgICB9XG5cbiAgICB0cmFja09iamVjdHMoZXZlbnROYW1lLCB0cmFja2VkLCBoYW5kbGVyLCB0YXJnZXQsIHJvb3QsIHJlc3QpO1xufVxuXG52YXIgdHJhY2tlZEV2ZW50cyA9IG5ldyBXZWFrTWFwKCk7XG5mdW5jdGlvbiBjcmVhdGVIYW5kbGVyKGVudGksIHRyYWNrZWRPYmplY3RQYXRocywgdHJhY2tlZFBhdGhzLCBldmVudE5hbWUpe1xuICAgIHZhciBvbGRNb2RlbCA9IGVudGkuX21vZGVsO1xuICAgIHJldHVybiBmdW5jdGlvbihldmVudCwgZW1pdEtleSl7XG4gICAgICAgIHRyYWNrZWRQYXRocy5lbnRpcy5mb3JFYWNoKGZ1bmN0aW9uKGVudGkpe1xuICAgICAgICAgICAgaWYoZW50aS5fZW1pdHRlZEV2ZW50c1tldmVudE5hbWVdID09PSBlbWl0S2V5KXtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGVudGkuX21vZGVsICE9PSBvbGRNb2RlbCl7XG4gICAgICAgICAgICAgICAgdHJhY2tlZFBhdGhzLmVudGlzLmRlbGV0ZShlbnRpKTtcbiAgICAgICAgICAgICAgICBpZih0cmFja2VkUGF0aHMuZW50aXMuc2l6ZSA9PT0gMCl7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0cmFja2VkT2JqZWN0UGF0aHNbZXZlbnROYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgaWYoIU9iamVjdC5rZXlzKHRyYWNrZWRPYmplY3RQYXRocykubGVuZ3RoKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrZWRFdmVudHMuZGVsZXRlKG9sZE1vZGVsKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGVudGkuX2VtaXR0ZWRFdmVudHNbZXZlbnROYW1lXSA9IGVtaXRLZXk7XG5cbiAgICAgICAgICAgIHZhciB0YXJnZXRLZXkgPSBnZXRUYXJnZXRLZXkoZXZlbnROYW1lKSxcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IGlzV2lsZGNhcmRQYXRoKHRhcmdldEtleSkgPyB1bmRlZmluZWQgOiBlbnRpLmdldCh0YXJnZXRLZXkpO1xuXG4gICAgICAgICAgICBlbnRpLmVtaXQoZXZlbnROYW1lLCB2YWx1ZSwgZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICB9O1xufVxuXG5mdW5jdGlvbiB0cmFja1BhdGgoZW50aSwgZXZlbnROYW1lKXtcbiAgICB2YXIgb2JqZWN0ID0gZW50aS5fbW9kZWwsXG4gICAgICAgIHRyYWNrZWRPYmplY3RQYXRocyA9IHRyYWNrZWRFdmVudHMuZ2V0KG9iamVjdCk7XG5cbiAgICBpZighdHJhY2tlZE9iamVjdFBhdGhzKXtcbiAgICAgICAgdHJhY2tlZE9iamVjdFBhdGhzID0ge307XG4gICAgICAgIHRyYWNrZWRFdmVudHMuc2V0KG9iamVjdCwgdHJhY2tlZE9iamVjdFBhdGhzKTtcbiAgICB9XG5cbiAgICB2YXIgdHJhY2tlZFBhdGhzID0gdHJhY2tlZE9iamVjdFBhdGhzW2V2ZW50TmFtZV07XG5cbiAgICBpZighdHJhY2tlZFBhdGhzKXtcbiAgICAgICAgdHJhY2tlZFBhdGhzID0ge1xuICAgICAgICAgICAgZW50aXM6IG5ldyBTZXQoKSxcbiAgICAgICAgICAgIHRyYWNrZWRPYmplY3RzOiBuZXcgV2Vha1NldCgpXG4gICAgICAgIH07XG4gICAgICAgIHRyYWNrZWRPYmplY3RQYXRoc1tldmVudE5hbWVdID0gdHJhY2tlZFBhdGhzO1xuICAgIH1lbHNlIGlmKHRyYWNrZWRQYXRocy5lbnRpcy5oYXMoZW50aSkpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJhY2tlZFBhdGhzLmVudGlzLmFkZChlbnRpKTtcblxuICAgIHZhciBoYW5kbGVyID0gY3JlYXRlSGFuZGxlcihlbnRpLCB0cmFja2VkT2JqZWN0UGF0aHMsIHRyYWNrZWRQYXRocywgZXZlbnROYW1lKTtcblxuICAgIHRyYWNrT2JqZWN0cyhldmVudE5hbWUsIHRyYWNrZWRQYXRocy50cmFja2VkT2JqZWN0cywgaGFuZGxlciwge21vZGVsOm9iamVjdH0sICdtb2RlbCcsIGV2ZW50TmFtZSk7XG59XG5cbmZ1bmN0aW9uIHRyYWNrUGF0aHMoZW50aSl7XG4gICAgaWYoIWVudGkuX2V2ZW50cyB8fCAhZW50aS5fbW9kZWwpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZm9yKHZhciBrZXkgaW4gZW50aS5fZXZlbnRzKXtcbiAgICAgICAgdHJhY2tQYXRoKGVudGksIGtleSk7XG4gICAgfVxuICAgIG1vZGlmaWVkRW50aWVzLmRlbGV0ZShlbnRpKTtcbn1cblxuZnVuY3Rpb24gZW1pdEV2ZW50KG9iamVjdCwga2V5LCB2YWx1ZSwgZW1pdEtleSl7XG5cbiAgICBtb2RpZmllZEVudGllcy5mb3JFYWNoKHRyYWNrUGF0aHMpO1xuXG4gICAgdmFyIHRyYWNrZWRLZXlzID0gdHJhY2tlZE9iamVjdHMuZ2V0KG9iamVjdCk7XG5cbiAgICBpZighdHJhY2tlZEtleXMpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGV2ZW50ID0ge1xuICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgIGtleToga2V5LFxuICAgICAgICBvYmplY3Q6IG9iamVjdFxuICAgIH07XG5cbiAgICBmdW5jdGlvbiBlbWl0Rm9yS2V5KGhhbmRsZXIpe1xuICAgICAgICBoYW5kbGVyKGV2ZW50LCBlbWl0S2V5KTtcbiAgICB9XG5cbiAgICBpZih0cmFja2VkS2V5c1trZXldKXtcbiAgICAgICAgdHJhY2tlZEtleXNba2V5XS5mb3JFYWNoKGVtaXRGb3JLZXkpO1xuICAgIH1cblxuICAgIGlmKHRyYWNrZWRLZXlzWycqJ10pe1xuICAgICAgICB0cmFja2VkS2V5c1snKiddLmZvckVhY2goZW1pdEZvcktleSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBlbWl0KGV2ZW50cyl7XG4gICAgdmFyIGVtaXRLZXkgPSB7fTtcbiAgICBldmVudHMuZm9yRWFjaChmdW5jdGlvbihldmVudCl7XG4gICAgICAgIGVtaXRFdmVudChldmVudFswXSwgZXZlbnRbMV0sIGV2ZW50WzJdLCBlbWl0S2V5KTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gRW50aShtb2RlbCl7XG4gICAgdmFyIGRldGFjaGVkID0gbW9kZWwgPT09IGZhbHNlO1xuXG4gICAgaWYoIW1vZGVsIHx8ICh0eXBlb2YgbW9kZWwgIT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2RlbCAhPT0gJ2Z1bmN0aW9uJykpe1xuICAgICAgICBtb2RlbCA9IHt9O1xuICAgIH1cblxuICAgIHRoaXMuX2VtaXR0ZWRFdmVudHMgPSB7fTtcbiAgICBpZihkZXRhY2hlZCl7XG4gICAgICAgIHRoaXMuX21vZGVsID0ge307XG4gICAgfWVsc2V7XG4gICAgICAgIHRoaXMuYXR0YWNoKG1vZGVsKTtcbiAgICB9XG5cbiAgICB0aGlzLm9uKCduZXdMaXN0ZW5lcicsIGZ1bmN0aW9uKCl7XG4gICAgICAgIG1vZGlmaWVkRW50aWVzLmFkZCh0aGlzKTtcbiAgICB9KTtcbn1cbkVudGkuZW1pdCA9IGZ1bmN0aW9uKG1vZGVsLCBrZXksIHZhbHVlKXtcbiAgICBpZighKHR5cGVvZiBtb2RlbCA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIG1vZGVsID09PSAnZnVuY3Rpb24nKSl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBlbWl0KFtbbW9kZWwsIGtleSwgdmFsdWVdXSk7XG59O1xuRW50aS5nZXQgPSBmdW5jdGlvbihtb2RlbCwga2V5KXtcbiAgICBpZighbW9kZWwgfHwgdHlwZW9mIG1vZGVsICE9PSAnb2JqZWN0Jyl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBrZXkgPSBnZXRUYXJnZXRLZXkoa2V5KTtcblxuICAgIGlmKGtleSA9PT0gJy4nKXtcbiAgICAgICAgcmV0dXJuIG1vZGVsO1xuICAgIH1cblxuXG4gICAgdmFyIHBhdGggPSBsZWZ0QW5kUmVzdChrZXkpO1xuICAgIGlmKEFycmF5LmlzQXJyYXkocGF0aCkpe1xuICAgICAgICByZXR1cm4gRW50aS5nZXQobW9kZWxbcGF0aFswXV0sIHBhdGhbMV0pO1xuICAgIH1cblxuICAgIHJldHVybiBtb2RlbFtrZXldO1xufTtcbkVudGkuc2V0ID0gZnVuY3Rpb24obW9kZWwsIGtleSwgdmFsdWUpe1xuICAgIGlmKCFtb2RlbCB8fCB0eXBlb2YgbW9kZWwgIT09ICdvYmplY3QnKXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGtleSA9IGdldFRhcmdldEtleShrZXkpO1xuXG4gICAgdmFyIHBhdGggPSBsZWZ0QW5kUmVzdChrZXkpO1xuICAgIGlmKEFycmF5LmlzQXJyYXkocGF0aCkpe1xuICAgICAgICByZXR1cm4gRW50aS5zZXQobW9kZWxbcGF0aFswXV0sIHBhdGhbMV0sIHZhbHVlKTtcbiAgICB9XG5cbiAgICB2YXIgb3JpZ2luYWwgPSBtb2RlbFtrZXldO1xuXG4gICAgaWYodHlwZW9mIHZhbHVlICE9PSAnb2JqZWN0JyAmJiB2YWx1ZSA9PT0gb3JpZ2luYWwpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGtleXNDaGFuZ2VkID0gIShrZXkgaW4gbW9kZWwpO1xuXG4gICAgbW9kZWxba2V5XSA9IHZhbHVlO1xuXG4gICAgdmFyIGV2ZW50cyA9IFtbbW9kZWwsIGtleSwgdmFsdWVdXTtcblxuICAgIGlmKGtleXNDaGFuZ2VkKXtcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheShtb2RlbCkpe1xuICAgICAgICAgICAgZXZlbnRzLnB1c2goW21vZGVsLCAnbGVuZ3RoJywgbW9kZWwubGVuZ3RoXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBlbWl0KGV2ZW50cyk7XG59O1xuRW50aS5wdXNoID0gZnVuY3Rpb24obW9kZWwsIGtleSwgdmFsdWUpe1xuICAgIGlmKCFtb2RlbCB8fCB0eXBlb2YgbW9kZWwgIT09ICdvYmplY3QnKXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciB0YXJnZXQ7XG4gICAgaWYoYXJndW1lbnRzLmxlbmd0aCA8IDMpe1xuICAgICAgICB2YWx1ZSA9IGtleTtcbiAgICAgICAga2V5ID0gJy4nO1xuICAgICAgICB0YXJnZXQgPSBtb2RlbDtcbiAgICB9ZWxzZXtcbiAgICAgICAgdmFyIHBhdGggPSBsZWZ0QW5kUmVzdChrZXkpO1xuICAgICAgICBpZihBcnJheS5pc0FycmF5KHBhdGgpKXtcbiAgICAgICAgICAgIHJldHVybiBFbnRpLnB1c2gobW9kZWxbcGF0aFswXV0sIHBhdGhbMV0sIHZhbHVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRhcmdldCA9IG1vZGVsW2tleV07XG4gICAgfVxuXG4gICAgaWYoIUFycmF5LmlzQXJyYXkodGFyZ2V0KSl7XG4gICAgICAgIHRocm93ICdUaGUgdGFyZ2V0IGlzIG5vdCBhbiBhcnJheS4nO1xuICAgIH1cblxuICAgIHRhcmdldC5wdXNoKHZhbHVlKTtcblxuICAgIHZhciBldmVudHMgPSBbXG4gICAgICAgIFt0YXJnZXQsIHRhcmdldC5sZW5ndGgtMSwgdmFsdWVdLFxuICAgICAgICBbdGFyZ2V0LCAnbGVuZ3RoJywgdGFyZ2V0Lmxlbmd0aF1cbiAgICBdO1xuXG4gICAgZW1pdChldmVudHMpO1xufTtcbkVudGkuaW5zZXJ0ID0gZnVuY3Rpb24obW9kZWwsIGtleSwgdmFsdWUsIGluZGV4KXtcbiAgICBpZighbW9kZWwgfHwgdHlwZW9mIG1vZGVsICE9PSAnb2JqZWN0Jyl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cblxuICAgIHZhciB0YXJnZXQ7XG4gICAgaWYoYXJndW1lbnRzLmxlbmd0aCA8IDQpe1xuICAgICAgICBpbmRleCA9IHZhbHVlO1xuICAgICAgICB2YWx1ZSA9IGtleTtcbiAgICAgICAga2V5ID0gJy4nO1xuICAgICAgICB0YXJnZXQgPSBtb2RlbDtcbiAgICB9ZWxzZXtcbiAgICAgICAgdmFyIHBhdGggPSBsZWZ0QW5kUmVzdChrZXkpO1xuICAgICAgICBpZihBcnJheS5pc0FycmF5KHBhdGgpKXtcbiAgICAgICAgICAgIHJldHVybiBFbnRpLmluc2VydChtb2RlbFtwYXRoWzBdXSwgcGF0aFsxXSwgdmFsdWUsIGluZGV4KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRhcmdldCA9IG1vZGVsW2tleV07XG4gICAgfVxuXG4gICAgaWYoIUFycmF5LmlzQXJyYXkodGFyZ2V0KSl7XG4gICAgICAgIHRocm93ICdUaGUgdGFyZ2V0IGlzIG5vdCBhbiBhcnJheS4nO1xuICAgIH1cblxuICAgIHRhcmdldC5zcGxpY2UoaW5kZXgsIDAsIHZhbHVlKTtcblxuICAgIHZhciBldmVudHMgPSBbXG4gICAgICAgIFt0YXJnZXQsIGluZGV4LCB2YWx1ZV0sXG4gICAgICAgIFt0YXJnZXQsICdsZW5ndGgnLCB0YXJnZXQubGVuZ3RoXVxuICAgIF07XG5cbiAgICBlbWl0KGV2ZW50cyk7XG59O1xuRW50aS5yZW1vdmUgPSBmdW5jdGlvbihtb2RlbCwga2V5LCBzdWJLZXkpe1xuICAgIGlmKCFtb2RlbCB8fCB0eXBlb2YgbW9kZWwgIT09ICdvYmplY3QnKXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBwYXRoID0gbGVmdEFuZFJlc3Qoa2V5KTtcbiAgICBpZihBcnJheS5pc0FycmF5KHBhdGgpKXtcbiAgICAgICAgcmV0dXJuIEVudGkucmVtb3ZlKG1vZGVsW3BhdGhbMF1dLCBwYXRoWzFdLCBzdWJLZXkpO1xuICAgIH1cblxuICAgIC8vIFJlbW92ZSBhIGtleSBvZmYgb2YgYW4gb2JqZWN0IGF0ICdrZXknXG4gICAgaWYoc3ViS2V5ICE9IG51bGwpe1xuICAgICAgICBFbnRpLnJlbW92ZShtb2RlbFtrZXldLCBzdWJLZXkpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYoa2V5ID09PSAnLicpe1xuICAgICAgICB0aHJvdyAnLiAoc2VsZikgaXMgbm90IGEgdmFsaWQga2V5IHRvIHJlbW92ZSc7XG4gICAgfVxuXG4gICAgdmFyIGV2ZW50cyA9IFtdO1xuXG4gICAgaWYoQXJyYXkuaXNBcnJheShtb2RlbCkpe1xuICAgICAgICBtb2RlbC5zcGxpY2Uoa2V5LCAxKTtcbiAgICAgICAgZXZlbnRzLnB1c2goW21vZGVsLCAnbGVuZ3RoJywgbW9kZWwubGVuZ3RoXSk7XG4gICAgfWVsc2V7XG4gICAgICAgIGRlbGV0ZSBtb2RlbFtrZXldO1xuICAgICAgICBldmVudHMucHVzaChbbW9kZWwsIGtleV0pO1xuICAgIH1cblxuICAgIGVtaXQoZXZlbnRzKTtcbn07XG5FbnRpLm1vdmUgPSBmdW5jdGlvbihtb2RlbCwga2V5LCBpbmRleCl7XG4gICAgaWYoIW1vZGVsIHx8IHR5cGVvZiBtb2RlbCAhPT0gJ29iamVjdCcpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHBhdGggPSBsZWZ0QW5kUmVzdChrZXkpO1xuICAgIGlmKEFycmF5LmlzQXJyYXkocGF0aCkpe1xuICAgICAgICByZXR1cm4gRW50aS5tb3ZlKG1vZGVsW3BhdGhbMF1dLCBwYXRoWzFdLCBpbmRleCk7XG4gICAgfVxuXG4gICAgaWYoa2V5ID09PSBpbmRleCl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZighQXJyYXkuaXNBcnJheShtb2RlbCkpe1xuICAgICAgICB0aHJvdyAnVGhlIG1vZGVsIGlzIG5vdCBhbiBhcnJheS4nO1xuICAgIH1cblxuICAgIHZhciBpdGVtID0gbW9kZWxba2V5XTtcblxuICAgIG1vZGVsLnNwbGljZShrZXksIDEpO1xuXG4gICAgbW9kZWwuc3BsaWNlKGluZGV4IC0gKGluZGV4ID4ga2V5ID8gMCA6IDEpLCAwLCBpdGVtKTtcblxuICAgIGVtaXQoW1ttb2RlbCwgaW5kZXgsIGl0ZW1dXSk7XG59O1xuRW50aS51cGRhdGUgPSBmdW5jdGlvbihtb2RlbCwga2V5LCB2YWx1ZSl7XG4gICAgaWYoIW1vZGVsIHx8IHR5cGVvZiBtb2RlbCAhPT0gJ29iamVjdCcpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHRhcmdldCxcbiAgICAgICAgaXNBcnJheSA9IEFycmF5LmlzQXJyYXkodmFsdWUpO1xuXG4gICAgaWYoYXJndW1lbnRzLmxlbmd0aCA8IDMpe1xuICAgICAgICB2YWx1ZSA9IGtleTtcbiAgICAgICAga2V5ID0gJy4nO1xuICAgICAgICB0YXJnZXQgPSBtb2RlbDtcbiAgICB9ZWxzZXtcbiAgICAgICAgdmFyIHBhdGggPSBsZWZ0QW5kUmVzdChrZXkpO1xuICAgICAgICBpZihBcnJheS5pc0FycmF5KHBhdGgpKXtcbiAgICAgICAgICAgIHJldHVybiBFbnRpLnVwZGF0ZShtb2RlbFtwYXRoWzBdXSwgcGF0aFsxXSwgdmFsdWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGFyZ2V0ID0gbW9kZWxba2V5XTtcblxuICAgICAgICBpZih0YXJnZXQgPT0gbnVsbCl7XG4gICAgICAgICAgICBtb2RlbFtrZXldID0gaXNBcnJheSA/IFtdIDoge307XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZih0eXBlb2YgdmFsdWUgIT09ICdvYmplY3QnKXtcbiAgICAgICAgdGhyb3cgJ1RoZSB2YWx1ZSBpcyBub3QgYW4gb2JqZWN0Lic7XG4gICAgfVxuXG4gICAgaWYodHlwZW9mIHRhcmdldCAhPT0gJ29iamVjdCcpe1xuICAgICAgICB0aHJvdyAnVGhlIHRhcmdldCBpcyBub3QgYW4gb2JqZWN0Lic7XG4gICAgfVxuXG4gICAgdmFyIGV2ZW50cyA9IFtdLFxuICAgICAgICB1cGRhdGVkT2JqZWN0cyA9IG5ldyBXZWFrU2V0KCk7XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVUYXJnZXQodGFyZ2V0LCB2YWx1ZSl7XG4gICAgICAgIGZvcih2YXIga2V5IGluIHZhbHVlKXtcbiAgICAgICAgICAgIHZhciBjdXJyZW50VmFsdWUgPSB0YXJnZXRba2V5XTtcbiAgICAgICAgICAgIGlmKGN1cnJlbnRWYWx1ZSBpbnN0YW5jZW9mIE9iamVjdCAmJiAhdXBkYXRlZE9iamVjdHMuaGFzKGN1cnJlbnRWYWx1ZSkgJiYgIShjdXJyZW50VmFsdWUgaW5zdGFuY2VvZiBEYXRlKSl7XG4gICAgICAgICAgICAgICAgdXBkYXRlZE9iamVjdHMuYWRkKGN1cnJlbnRWYWx1ZSk7XG4gICAgICAgICAgICAgICAgdXBkYXRlVGFyZ2V0KGN1cnJlbnRWYWx1ZSwgdmFsdWVba2V5XSk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0YXJnZXRba2V5XSA9IHZhbHVlW2tleV07XG4gICAgICAgICAgICBldmVudHMucHVzaChbdGFyZ2V0LCBrZXksIHZhbHVlW2tleV1dKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkodGFyZ2V0KSl7XG4gICAgICAgICAgICBldmVudHMucHVzaChbdGFyZ2V0LCAnbGVuZ3RoJywgdGFyZ2V0Lmxlbmd0aF0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdXBkYXRlVGFyZ2V0KHRhcmdldCwgdmFsdWUpO1xuXG4gICAgZW1pdChldmVudHMpO1xufTtcbkVudGkucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShFdmVudEVtaXR0ZXIucHJvdG90eXBlKTtcbkVudGkucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSAxMDA7XG5FbnRpLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IEVudGk7XG5FbnRpLnByb3RvdHlwZS5hdHRhY2ggPSBmdW5jdGlvbihtb2RlbCl7XG4gICAgaWYodGhpcy5fbW9kZWwgIT09IG1vZGVsKXtcbiAgICAgICAgdGhpcy5kZXRhY2goKTtcbiAgICB9XG5cbiAgICBpZihtb2RlbCAmJiAhaXNJbnN0YW5jZShtb2RlbCkpe1xuICAgICAgICB0aHJvdyAnRW50aXMgbWF5IG9ubHkgYmUgYXR0YWNoZWQgdG8gYW4gb2JqZWN0LCBvciBudWxsL3VuZGVmaW5lZCc7XG4gICAgfVxuXG4gICAgbW9kaWZpZWRFbnRpZXMuYWRkKHRoaXMpO1xuICAgIHRoaXMuX2F0dGFjaGVkID0gdHJ1ZTtcbiAgICB0aGlzLl9tb2RlbCA9IG1vZGVsO1xuICAgIHRoaXMuZW1pdCgnYXR0YWNoJywgbW9kZWwpO1xufTtcbkVudGkucHJvdG90eXBlLmRldGFjaCA9IGZ1bmN0aW9uKCl7XG4gICAgbW9kaWZpZWRFbnRpZXMuZGVsZXRlKHRoaXMpO1xuXG4gICAgdGhpcy5fZW1pdHRlZEV2ZW50cyA9IHt9O1xuICAgIHRoaXMuX21vZGVsID0ge307XG4gICAgdGhpcy5fYXR0YWNoZWQgPSBmYWxzZTtcbiAgICB0aGlzLmVtaXQoJ2RldGFjaCcpO1xufTtcbkVudGkucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbigpe1xuICAgIHRoaXMuZGV0YWNoKCk7XG4gICAgdGhpcy5fZXZlbnRzID0gbnVsbDtcbiAgICB0aGlzLmVtaXQoJ2Rlc3Ryb3knKTtcbn07XG5FbnRpLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbihrZXkpe1xuICAgIHJldHVybiBFbnRpLmdldCh0aGlzLl9tb2RlbCwga2V5KTtcbn07XG5cbkVudGkucHJvdG90eXBlLnNldCA9IGZ1bmN0aW9uKGtleSwgdmFsdWUpe1xuICAgIHJldHVybiBFbnRpLnNldCh0aGlzLl9tb2RlbCwga2V5LCB2YWx1ZSk7XG59O1xuXG5FbnRpLnByb3RvdHlwZS5wdXNoID0gZnVuY3Rpb24oa2V5LCB2YWx1ZSl7XG4gICAgcmV0dXJuIEVudGkucHVzaC5hcHBseShudWxsLCBbdGhpcy5fbW9kZWxdLmNvbmNhdCh0b0FycmF5KGFyZ3VtZW50cykpKTtcbn07XG5cbkVudGkucHJvdG90eXBlLmluc2VydCA9IGZ1bmN0aW9uKGtleSwgdmFsdWUsIGluZGV4KXtcbiAgICByZXR1cm4gRW50aS5pbnNlcnQuYXBwbHkobnVsbCwgW3RoaXMuX21vZGVsXS5jb25jYXQodG9BcnJheShhcmd1bWVudHMpKSk7XG59O1xuXG5FbnRpLnByb3RvdHlwZS5yZW1vdmUgPSBmdW5jdGlvbihrZXksIHN1YktleSl7XG4gICAgcmV0dXJuIEVudGkucmVtb3ZlLmFwcGx5KG51bGwsIFt0aGlzLl9tb2RlbF0uY29uY2F0KHRvQXJyYXkoYXJndW1lbnRzKSkpO1xufTtcblxuRW50aS5wcm90b3R5cGUubW92ZSA9IGZ1bmN0aW9uKGtleSwgaW5kZXgpe1xuICAgIHJldHVybiBFbnRpLm1vdmUuYXBwbHkobnVsbCwgW3RoaXMuX21vZGVsXS5jb25jYXQodG9BcnJheShhcmd1bWVudHMpKSk7XG59O1xuXG5FbnRpLnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbihrZXksIGluZGV4KXtcbiAgICByZXR1cm4gRW50aS51cGRhdGUuYXBwbHkobnVsbCwgW3RoaXMuX21vZGVsXS5jb25jYXQodG9BcnJheShhcmd1bWVudHMpKSk7XG59O1xuRW50aS5wcm90b3R5cGUuaXNBdHRhY2hlZCA9IGZ1bmN0aW9uKCl7XG4gICAgcmV0dXJuIHRoaXMuX2F0dGFjaGVkO1xufTtcbkVudGkucHJvdG90eXBlLmF0dGFjaGVkQ291bnQgPSBmdW5jdGlvbigpe1xuICAgIHJldHVybiBtb2RpZmllZEVudGllcy5zaXplO1xufTtcblxuRW50aS5pc0VudGkgPSBmdW5jdGlvbih0YXJnZXQpe1xuICAgIHJldHVybiB0YXJnZXQgJiYgISF+Z2xvYmFsU3RhdGUuaW5zdGFuY2VzLmluZGV4T2YodGFyZ2V0LmNvbnN0cnVjdG9yKTtcbn07XG5cbkVudGkuc3RvcmUgPSBmdW5jdGlvbih0YXJnZXQsIGtleSwgdmFsdWUpe1xuICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPCAyKXtcbiAgICAgICAgcmV0dXJuIEVudGkuZ2V0KHRhcmdldCwga2V5KTtcbiAgICB9XG5cbiAgICBFbnRpLnNldCh0YXJnZXQsIGtleSwgdmFsdWUpO1xufTtcblxuZ2xvYmFsU3RhdGUuaW5zdGFuY2VzLnB1c2goRW50aSk7XG5cbm1vZHVsZS5leHBvcnRzID0gRW50aTtcblxufSkuY2FsbCh0aGlzLHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pXG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247Y2hhcnNldDp1dGYtODtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbTV2WkdWZmJXOWtkV3hsY3k5bGJuUnBMMmx1WkdWNExtcHpJbDBzSW01aGJXVnpJanBiWFN3aWJXRndjR2x1WjNNaU9pSTdRVUZCUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFTSXNJbVpwYkdVaU9pSm5aVzVsY21GMFpXUXVhbk1pTENKemIzVnlZMlZTYjI5MElqb2lJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpZG1GeUlFVjJaVzUwUlcxcGRIUmxjaUE5SUhKbGNYVnBjbVVvSjJWMlpXNTBjeWNwTGtWMlpXNTBSVzFwZEhSbGNpeGNiaUFnSUNCcGMwbHVjM1JoYm1ObElEMGdjbVZ4ZFdseVpTZ25hWE10YVc1emRHRnVZMlVuS1R0Y2JseHVablZ1WTNScGIyNGdkRzlCY25KaGVTaHBkR1Z0Y3lsN1hHNGdJQ0FnY21WMGRYSnVJRUZ5Y21GNUxuQnliM1J2ZEhsd1pTNXpiR2xqWlM1allXeHNLR2wwWlcxektUdGNibjFjYmx4dWRtRnlJR1JsWlhCU1pXZGxlQ0E5SUM5YmZDNWRMMms3WEc1Y2JtWjFibU4wYVc5dUlHMWhkR05vUkdWbGNDaHdZWFJvS1h0Y2JpQWdJQ0J5WlhSMWNtNGdLSEJoZEdnZ0t5QW5KeWt1YldGMFkyZ29aR1ZsY0ZKbFoyVjRLVHRjYm4xY2JseHVablZ1WTNScGIyNGdhWE5YYVd4a1kyRnlaRkJoZEdnb2NHRjBhQ2w3WEc0Z0lDQWdkbUZ5SUhOMGNtbHVaMUJoZEdnZ1BTQW9jR0YwYUNBcklDY25LVHRjYmlBZ0lDQnlaWFIxY200Z2ZuTjBjbWx1WjFCaGRHZ3VhVzVrWlhoUFppZ25LaWNwTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJuWlhSVVlYSm5aWFJMWlhrb2NHRjBhQ2w3WEc0Z0lDQWdkbUZ5SUhOMGNtbHVaMUJoZEdnZ1BTQW9jR0YwYUNBcklDY25LVHRjYmlBZ0lDQnlaWFIxY200Z2MzUnlhVzVuVUdGMGFDNXpjR3hwZENnbmZDY3BMbk5vYVdaMEtDazdYRzU5WEc1Y2JuWmhjaUJsZG1WdWRGTjVjM1JsYlZabGNuTnBiMjRnUFNBeExGeHVJQ0FnSUdkc2IySmhiRXRsZVNBOUlDZGZaVzUwYVVWMlpXNTBVM1JoZEdVbklDc2daWFpsYm5SVGVYTjBaVzFXWlhKemFXOXVYRzRnSUNBZ1oyeHZZbUZzVTNSaGRHVWdQU0JuYkc5aVlXeGJaMnh2WW1Gc1MyVjVYU0E5SUdkc2IySmhiRnRuYkc5aVlXeExaWGxkSUh4OElIdGNiaUFnSUNBZ0lDQWdhVzV6ZEdGdVkyVnpPaUJiWFZ4dUlDQWdJSDA3WEc1Y2JuWmhjaUJ0YjJScFptbGxaRVZ1ZEdsbGN5QTlJR2RzYjJKaGJGTjBZWFJsTG0xdlpHbG1hV1ZrUlc1MGFXVnpJRDBnWjJ4dlltRnNVM1JoZEdVdWJXOWthV1pwWldSRmJuUnBaWE1nZkh3Z2JtVjNJRk5sZENncExGeHVJQ0FnSUhSeVlXTnJaV1JQWW1wbFkzUnpJRDBnWjJ4dlltRnNVM1JoZEdVdWRISmhZMnRsWkU5aWFtVmpkSE1nUFNCbmJHOWlZV3hUZEdGMFpTNTBjbUZqYTJWa1QySnFaV04wY3lCOGZDQnVaWGNnVjJWaGEwMWhjQ2dwTzF4dVhHNW1kVzVqZEdsdmJpQnNaV1owUVc1a1VtVnpkQ2h3WVhSb0tYdGNiaUFnSUNCMllYSWdjM1J5YVc1blVHRjBhQ0E5SUNod1lYUm9JQ3NnSnljcE8xeHVYRzRnSUNBZ0x5OGdVM0JsWTJsaGJDQmpZWE5sSUhkb1pXNGdlVzkxSUhkaGJuUWdkRzhnWm1sc2RHVnlJRzl1SUhObGJHWWdLQzRwWEc0Z0lDQWdhV1lvYzNSeWFXNW5VR0YwYUM1emJHbGpaU2d3TERJcElEMDlQU0FuTG53bktYdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlGc25MaWNzSUhOMGNtbHVaMUJoZEdndWMyeHBZMlVvTWlsZE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhaaGNpQnRZWFJqYUNBOUlHMWhkR05vUkdWbGNDaHpkSEpwYm1kUVlYUm9LVHRjYmlBZ0lDQnBaaWh0WVhSamFDbDdYRzRnSUNBZ0lDQWdJSEpsZEhWeWJpQmJjM1J5YVc1blVHRjBhQzV6YkdsalpTZ3dMQ0J0WVhSamFDNXBibVJsZUNrc0lITjBjbWx1WjFCaGRHZ3VjMnhwWTJVb2JXRjBZMmd1YVc1a1pYZ3JNU2xkTzF4dUlDQWdJSDFjYmlBZ0lDQnlaWFIxY200Z2MzUnlhVzVuVUdGMGFEdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2FYTlhhV3hrWTJGeVpFdGxlU2hyWlhrcGUxeHVJQ0FnSUhKbGRIVnliaUJyWlhrdVkyaGhja0YwS0RBcElEMDlQU0FuS2ljN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdselJtVnlZV3hqWVhKa1MyVjVLR3RsZVNsN1hHNGdJQ0FnY21WMGRYSnVJR3RsZVNBOVBUMGdKeW9xSnp0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWVdSa1NHRnVaR3hsY2lodlltcGxZM1FzSUd0bGVTd2dhR0Z1Wkd4bGNpbDdYRzRnSUNBZ2RtRnlJSFJ5WVdOclpXUkxaWGx6SUQwZ2RISmhZMnRsWkU5aWFtVmpkSE11WjJWMEtHOWlhbVZqZENrN1hHNWNiaUFnSUNCcFppaDBjbUZqYTJWa1MyVjVjeUE5UFNCdWRXeHNLWHRjYmlBZ0lDQWdJQ0FnZEhKaFkydGxaRXRsZVhNZ1BTQjdmVHRjYmlBZ0lDQWdJQ0FnZEhKaFkydGxaRTlpYW1WamRITXVjMlYwS0c5aWFtVmpkQ3dnZEhKaFkydGxaRXRsZVhNcE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhaaGNpQm9ZVzVrYkdWeWN5QTlJSFJ5WVdOclpXUkxaWGx6VzJ0bGVWMDdYRzVjYmlBZ0lDQnBaaWdoYUdGdVpHeGxjbk1wZTF4dUlDQWdJQ0FnSUNCb1lXNWtiR1Z5Y3lBOUlHNWxkeUJUWlhRb0tUdGNiaUFnSUNBZ0lDQWdkSEpoWTJ0bFpFdGxlWE5iYTJWNVhTQTlJR2hoYm1Sc1pYSnpPMXh1SUNBZ0lIMWNibHh1SUNBZ0lHaGhibVJzWlhKekxtRmtaQ2hvWVc1a2JHVnlLVHRjYm4xY2JseHVablZ1WTNScGIyNGdjbVZ0YjNabFNHRnVaR3hsY2lodlltcGxZM1FzSUd0bGVTd2dhR0Z1Wkd4bGNpbDdYRzRnSUNBZ2RtRnlJSFJ5WVdOclpXUkxaWGx6SUQwZ2RISmhZMnRsWkU5aWFtVmpkSE11WjJWMEtHOWlhbVZqZENrN1hHNWNiaUFnSUNCcFppaDBjbUZqYTJWa1MyVjVjeUE5UFNCdWRXeHNLWHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVPMXh1SUNBZ0lIMWNibHh1SUNBZ0lIWmhjaUJvWVc1a2JHVnljeUE5SUhSeVlXTnJaV1JMWlhselcydGxlVjA3WEc1Y2JpQWdJQ0JwWmlnaGFHRnVaR3hsY25NcGUxeHVJQ0FnSUNBZ0lDQnlaWFIxY200N1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnYUdGdVpHeGxjbk11WkdWc1pYUmxLR2hoYm1Sc1pYSXBPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQjBjbUZqYTA5aWFtVmpkSE1vWlhabGJuUk9ZVzFsTENCMGNtRmphMlZrTENCb1lXNWtiR1Z5TENCdlltcGxZM1FzSUd0bGVTd2djR0YwYUNsN1hHNGdJQ0FnYVdZb0lXOWlhbVZqZENCOGZDQjBlWEJsYjJZZ2IySnFaV04wSUNFOVBTQW5iMkpxWldOMEp5bDdYRzRnSUNBZ0lDQWdJSEpsZEhWeWJqdGNiaUFnSUNCOVhHNWNiaUFnSUNCMllYSWdkR0Z5WjJWMElEMGdiMkpxWldOMFcydGxlVjA3WEc1Y2JpQWdJQ0JwWmloMFlYSm5aWFFnSmlZZ2RIbHdaVzltSUhSaGNtZGxkQ0E5UFQwZ0oyOWlhbVZqZENjZ0ppWWdkSEpoWTJ0bFpDNW9ZWE1vZEdGeVoyVjBLU2w3WEc0Z0lDQWdJQ0FnSUhKbGRIVnlianRjYmlBZ0lDQjlYRzVjYmlBZ0lDQjBjbUZqYTA5aWFtVmpkQ2hsZG1WdWRFNWhiV1VzSUhSeVlXTnJaV1FzSUdoaGJtUnNaWElzSUc5aWFtVmpkQ3dnYTJWNUxDQndZWFJvS1R0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnZEhKaFkydExaWGx6S0dWMlpXNTBUbUZ0WlN3Z2RISmhZMnRsWkN3Z2FHRnVaR3hsY2l3Z2RHRnlaMlYwTENCeWIyOTBMQ0J5WlhOMEtYdGNiaUFnSUNCMllYSWdhMlY1Y3lBOUlFOWlhbVZqZEM1clpYbHpLSFJoY21kbGRDazdYRzRnSUNBZ1ptOXlLSFpoY2lCcElEMGdNRHNnYVNBOElHdGxlWE11YkdWdVozUm9PeUJwS3lzcGUxeHVJQ0FnSUNBZ0lDQnBaaWhwYzBabGNtRnNZMkZ5WkV0bGVTaHliMjkwS1NsN1hHNGdJQ0FnSUNBZ0lDQWdJQ0IwY21GamEwOWlhbVZqZEhNb1pYWmxiblJPWVcxbExDQjBjbUZqYTJWa0xDQm9ZVzVrYkdWeUxDQjBZWEpuWlhRc0lHdGxlWE5iYVYwc0lDY3FLaWNnS3lBb2NtVnpkQ0EvSUNjdUp5QTZJQ2NuS1NBcklDaHlaWE4wSUh4OElDY25LU2s3WEc0Z0lDQWdJQ0FnSUgxbGJITmxlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2RISmhZMnRQWW1wbFkzUnpLR1YyWlc1MFRtRnRaU3dnZEhKaFkydGxaQ3dnYUdGdVpHeGxjaXdnZEdGeVoyVjBMQ0JyWlhselcybGRMQ0J5WlhOMEtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z2RISmhZMnRQWW1wbFkzUW9aWFpsYm5ST1lXMWxMQ0IwY21GamEyVmtMQ0JvWVc1a2JHVnlMQ0J2WW1wbFkzUXNJR3RsZVN3Z2NHRjBhQ2w3WEc0Z0lDQWdkbUZ5SUdWMlpXNTBTMlY1SUQwZ2EyVjVJRDA5UFNBbktpb25JRDhnSnlvbklEb2dhMlY1TEZ4dUlDQWdJQ0FnSUNCMFlYSm5aWFFnUFNCdlltcGxZM1JiYTJWNVhTeGNiaUFnSUNBZ0lDQWdkR0Z5WjJWMFNYTlBZbXBsWTNRZ1BTQjBZWEpuWlhRZ0ppWWdkSGx3Wlc5bUlIUmhjbWRsZENBOVBUMGdKMjlpYW1WamRDYzdYRzVjYmlBZ0lDQjJZWElnYUdGdVpHeGxJRDBnWm5WdVkzUnBiMjRvZG1Gc2RXVXNJR1YyWlc1MExDQmxiV2wwUzJWNUtYdGNiaUFnSUNBZ0lDQWdhV1lvWlhabGJuUkxaWGtnSVQwOUlDY3FKeUFtSmlCMGVYQmxiMllnYjJKcVpXTjBXMlYyWlc1MFMyVjVYU0E5UFQwZ0oyOWlhbVZqZENjZ0ppWWdiMkpxWldOMFcyVjJaVzUwUzJWNVhTQWhQVDBnZEdGeVoyVjBLWHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1LSFJoY21kbGRFbHpUMkpxWldOMEtYdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjBjbUZqYTJWa0xtUmxiR1YwWlNoMFlYSm5aWFFwTzF4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ2NtVnRiM1psU0dGdVpHeGxjaWh2WW1wbFkzUXNJR1YyWlc1MFMyVjVMQ0JvWVc1a2JHVXBPMXh1SUNBZ0lDQWdJQ0FnSUNBZ2RISmhZMnRQWW1wbFkzUnpLR1YyWlc1MFRtRnRaU3dnZEhKaFkydGxaQ3dnYUdGdVpHeGxjaXdnYjJKcVpXTjBMQ0JyWlhrc0lIQmhkR2dwTzF4dUlDQWdJQ0FnSUNBZ0lDQWdjbVYwZFhKdU8xeHVJQ0FnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJQ0FnYVdZb1pYWmxiblJMWlhrZ1BUMDlJQ2NxSnlsN1hHNGdJQ0FnSUNBZ0lDQWdJQ0IwY21GamEwdGxlWE1vWlhabGJuUk9ZVzFsTENCMGNtRmphMlZrTENCb1lXNWtiR1Z5TENCdlltcGxZM1FzSUd0bGVTd2djR0YwYUNrN1hHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0JwWmlnaGRISmhZMnRsWkM1b1lYTW9iMkpxWldOMEtTbDdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTQ3WEc0Z0lDQWdJQ0FnSUgxY2JseHVJQ0FnSUNBZ0lDQnBaaWhyWlhrZ0lUMDlJQ2NxS2ljZ2ZId2dJWEJoZEdncGUxeHVJQ0FnSUNBZ0lDQWdJQ0FnYUdGdVpHeGxjaWgyWVd4MVpTd2daWFpsYm5Rc0lHVnRhWFJMWlhrcE8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ2ZUdGNibHh1SUNBZ0lHRmtaRWhoYm1Sc1pYSW9iMkpxWldOMExDQmxkbVZ1ZEV0bGVTd2dhR0Z1Wkd4bEtUdGNibHh1SUNBZ0lHbG1LQ0YwWVhKblpYUkpjMDlpYW1WamRDbDdYRzRnSUNBZ0lDQWdJSEpsZEhWeWJqdGNiaUFnSUNCOVhHNWNiaUFnSUNCMGNtRmphMlZrTG1Ga1pDaDBZWEpuWlhRcE8xeHVYRzRnSUNBZ2FXWW9JWEJoZEdncGUxeHVJQ0FnSUNBZ0lDQnlaWFIxY200N1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnZG1GeUlISnZiM1JCYm1SU1pYTjBJRDBnYkdWbWRFRnVaRkpsYzNRb2NHRjBhQ2tzWEc0Z0lDQWdJQ0FnSUhKdmIzUXNYRzRnSUNBZ0lDQWdJSEpsYzNRN1hHNWNiaUFnSUNCcFppZ2hRWEp5WVhrdWFYTkJjbkpoZVNoeWIyOTBRVzVrVW1WemRDa3BlMXh1SUNBZ0lDQWdJQ0J5YjI5MElEMGdjbTl2ZEVGdVpGSmxjM1E3WEc0Z0lDQWdmV1ZzYzJWN1hHNGdJQ0FnSUNBZ0lISnZiM1FnUFNCeWIyOTBRVzVrVW1WemRGc3dYVHRjYmlBZ0lDQWdJQ0FnY21WemRDQTlJSEp2YjNSQmJtUlNaWE4wV3pGZE8xeHVYRzRnSUNBZ0lDQWdJQzh2SUVsbUlIUm9aU0J5YjI5MElHbHpJQ2N1Snl3Z2QyRjBZMmdnWm05eUlHVjJaVzUwY3lCdmJpQXFYRzRnSUNBZ0lDQWdJR2xtS0hKdmIzUWdQVDA5SUNjdUp5bDdYRzRnSUNBZ0lDQWdJQ0FnSUNCeWIyOTBJRDBnSnlvbk8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2FXWW9kR0Z5WjJWMFNYTlBZbXBsWTNRZ0ppWWdhWE5YYVd4a1kyRnlaRXRsZVNoeWIyOTBLU2w3WEc0Z0lDQWdJQ0FnSUhSeVlXTnJTMlY1Y3lobGRtVnVkRTVoYldVc0lIUnlZV05yWldRc0lHaGhibVJzWlhJc0lIUmhjbWRsZEN3Z2NtOXZkQ3dnY21WemRDazdYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2RISmhZMnRQWW1wbFkzUnpLR1YyWlc1MFRtRnRaU3dnZEhKaFkydGxaQ3dnYUdGdVpHeGxjaXdnZEdGeVoyVjBMQ0J5YjI5MExDQnlaWE4wS1R0Y2JuMWNibHh1ZG1GeUlIUnlZV05yWldSRmRtVnVkSE1nUFNCdVpYY2dWMlZoYTAxaGNDZ3BPMXh1Wm5WdVkzUnBiMjRnWTNKbFlYUmxTR0Z1Wkd4bGNpaGxiblJwTENCMGNtRmphMlZrVDJKcVpXTjBVR0YwYUhNc0lIUnlZV05yWldSUVlYUm9jeXdnWlhabGJuUk9ZVzFsS1h0Y2JpQWdJQ0IyWVhJZ2IyeGtUVzlrWld3Z1BTQmxiblJwTGw5dGIyUmxiRHRjYmlBZ0lDQnlaWFIxY200Z1puVnVZM1JwYjI0b1pYWmxiblFzSUdWdGFYUkxaWGtwZTF4dUlDQWdJQ0FnSUNCMGNtRmphMlZrVUdGMGFITXVaVzUwYVhNdVptOXlSV0ZqYUNobWRXNWpkR2x2YmlobGJuUnBLWHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1LR1Z1ZEdrdVgyVnRhWFIwWldSRmRtVnVkSE5iWlhabGJuUk9ZVzFsWFNBOVBUMGdaVzFwZEV0bGVTbDdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdjbVYwZFhKdU8xeHVJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dVhHNGdJQ0FnSUNBZ0lDQWdJQ0JwWmlobGJuUnBMbDl0YjJSbGJDQWhQVDBnYjJ4a1RXOWtaV3dwZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhSeVlXTnJaV1JRWVhSb2N5NWxiblJwY3k1a1pXeGxkR1VvWlc1MGFTazdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdhV1lvZEhKaFkydGxaRkJoZEdoekxtVnVkR2x6TG5OcGVtVWdQVDA5SURBcGUxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JrWld4bGRHVWdkSEpoWTJ0bFpFOWlhbVZqZEZCaGRHaHpXMlYyWlc1MFRtRnRaVjA3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbG1LQ0ZQWW1wbFkzUXVhMlY1Y3loMGNtRmphMlZrVDJKcVpXTjBVR0YwYUhNcExteGxibWQwYUNsN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCMGNtRmphMlZrUlhabGJuUnpMbVJsYkdWMFpTaHZiR1JOYjJSbGJDazdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCOVhHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2NtVjBkWEp1TzF4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQmxiblJwTGw5bGJXbDBkR1ZrUlhabGJuUnpXMlYyWlc1MFRtRnRaVjBnUFNCbGJXbDBTMlY1TzF4dVhHNGdJQ0FnSUNBZ0lDQWdJQ0IyWVhJZ2RHRnlaMlYwUzJWNUlEMGdaMlYwVkdGeVoyVjBTMlY1S0dWMlpXNTBUbUZ0WlNrc1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2RtRnNkV1VnUFNCcGMxZHBiR1JqWVhKa1VHRjBhQ2gwWVhKblpYUkxaWGtwSUQ4Z2RXNWtaV1pwYm1Wa0lEb2daVzUwYVM1blpYUW9kR0Z5WjJWMFMyVjVLVHRjYmx4dUlDQWdJQ0FnSUNBZ0lDQWdaVzUwYVM1bGJXbDBLR1YyWlc1MFRtRnRaU3dnZG1Gc2RXVXNJR1YyWlc1MEtUdGNiaUFnSUNBZ0lDQWdmU2s3WEc0Z0lDQWdmVHRjYm4xY2JseHVablZ1WTNScGIyNGdkSEpoWTJ0UVlYUm9LR1Z1ZEdrc0lHVjJaVzUwVG1GdFpTbDdYRzRnSUNBZ2RtRnlJRzlpYW1WamRDQTlJR1Z1ZEdrdVgyMXZaR1ZzTEZ4dUlDQWdJQ0FnSUNCMGNtRmphMlZrVDJKcVpXTjBVR0YwYUhNZ1BTQjBjbUZqYTJWa1JYWmxiblJ6TG1kbGRDaHZZbXBsWTNRcE8xeHVYRzRnSUNBZ2FXWW9JWFJ5WVdOclpXUlBZbXBsWTNSUVlYUm9jeWw3WEc0Z0lDQWdJQ0FnSUhSeVlXTnJaV1JQWW1wbFkzUlFZWFJvY3lBOUlIdDlPMXh1SUNBZ0lDQWdJQ0IwY21GamEyVmtSWFpsYm5SekxuTmxkQ2h2WW1wbFkzUXNJSFJ5WVdOclpXUlBZbXBsWTNSUVlYUm9jeWs3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUhSeVlXTnJaV1JRWVhSb2N5QTlJSFJ5WVdOclpXUlBZbXBsWTNSUVlYUm9jMXRsZG1WdWRFNWhiV1ZkTzF4dVhHNGdJQ0FnYVdZb0lYUnlZV05yWldSUVlYUm9jeWw3WEc0Z0lDQWdJQ0FnSUhSeVlXTnJaV1JRWVhSb2N5QTlJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHVnVkR2x6T2lCdVpYY2dVMlYwS0Nrc1hHNGdJQ0FnSUNBZ0lDQWdJQ0IwY21GamEyVmtUMkpxWldOMGN6b2dibVYzSUZkbFlXdFRaWFFvS1Z4dUlDQWdJQ0FnSUNCOU8xeHVJQ0FnSUNBZ0lDQjBjbUZqYTJWa1QySnFaV04wVUdGMGFITmJaWFpsYm5ST1lXMWxYU0E5SUhSeVlXTnJaV1JRWVhSb2N6dGNiaUFnSUNCOVpXeHpaU0JwWmloMGNtRmphMlZrVUdGMGFITXVaVzUwYVhNdWFHRnpLR1Z1ZEdrcEtYdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdU8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhSeVlXTnJaV1JRWVhSb2N5NWxiblJwY3k1aFpHUW9aVzUwYVNrN1hHNWNiaUFnSUNCMllYSWdhR0Z1Wkd4bGNpQTlJR055WldGMFpVaGhibVJzWlhJb1pXNTBhU3dnZEhKaFkydGxaRTlpYW1WamRGQmhkR2h6TENCMGNtRmphMlZrVUdGMGFITXNJR1YyWlc1MFRtRnRaU2s3WEc1Y2JpQWdJQ0IwY21GamEwOWlhbVZqZEhNb1pYWmxiblJPWVcxbExDQjBjbUZqYTJWa1VHRjBhSE11ZEhKaFkydGxaRTlpYW1WamRITXNJR2hoYm1Sc1pYSXNJSHR0YjJSbGJEcHZZbXBsWTNSOUxDQW5iVzlrWld3bkxDQmxkbVZ1ZEU1aGJXVXBPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQjBjbUZqYTFCaGRHaHpLR1Z1ZEdrcGUxeHVJQ0FnSUdsbUtDRmxiblJwTGw5bGRtVnVkSE1nZkh3Z0lXVnVkR2t1WDIxdlpHVnNLWHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVPMXh1SUNBZ0lIMWNibHh1SUNBZ0lHWnZjaWgyWVhJZ2EyVjVJR2x1SUdWdWRHa3VYMlYyWlc1MGN5bDdYRzRnSUNBZ0lDQWdJSFJ5WVdOclVHRjBhQ2hsYm5ScExDQnJaWGtwTzF4dUlDQWdJSDFjYmlBZ0lDQnRiMlJwWm1sbFpFVnVkR2xsY3k1a1pXeGxkR1VvWlc1MGFTazdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHVnRhWFJGZG1WdWRDaHZZbXBsWTNRc0lHdGxlU3dnZG1Gc2RXVXNJR1Z0YVhSTFpYa3BlMXh1WEc0Z0lDQWdiVzlrYVdacFpXUkZiblJwWlhNdVptOXlSV0ZqYUNoMGNtRmphMUJoZEdoektUdGNibHh1SUNBZ0lIWmhjaUIwY21GamEyVmtTMlY1Y3lBOUlIUnlZV05yWldSUFltcGxZM1J6TG1kbGRDaHZZbXBsWTNRcE8xeHVYRzRnSUNBZ2FXWW9JWFJ5WVdOclpXUkxaWGx6S1h0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1TzF4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCbGRtVnVkQ0E5SUh0Y2JpQWdJQ0FnSUNBZ2RtRnNkV1U2SUhaaGJIVmxMRnh1SUNBZ0lDQWdJQ0JyWlhrNklHdGxlU3hjYmlBZ0lDQWdJQ0FnYjJKcVpXTjBPaUJ2WW1wbFkzUmNiaUFnSUNCOU8xeHVYRzRnSUNBZ1puVnVZM1JwYjI0Z1pXMXBkRVp2Y2t0bGVTaG9ZVzVrYkdWeUtYdGNiaUFnSUNBZ0lDQWdhR0Z1Wkd4bGNpaGxkbVZ1ZEN3Z1pXMXBkRXRsZVNrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnYVdZb2RISmhZMnRsWkV0bGVYTmJhMlY1WFNsN1hHNGdJQ0FnSUNBZ0lIUnlZV05yWldSTFpYbHpXMnRsZVYwdVptOXlSV0ZqYUNobGJXbDBSbTl5UzJWNUtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCcFppaDBjbUZqYTJWa1MyVjVjMXNuS2lkZEtYdGNiaUFnSUNBZ0lDQWdkSEpoWTJ0bFpFdGxlWE5iSnlvblhTNW1iM0pGWVdOb0tHVnRhWFJHYjNKTFpYa3BPMXh1SUNBZ0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z1pXMXBkQ2hsZG1WdWRITXBlMXh1SUNBZ0lIWmhjaUJsYldsMFMyVjVJRDBnZTMwN1hHNGdJQ0FnWlhabGJuUnpMbVp2Y2tWaFkyZ29ablZ1WTNScGIyNG9aWFpsYm5RcGUxeHVJQ0FnSUNBZ0lDQmxiV2wwUlhabGJuUW9aWFpsYm5SYk1GMHNJR1YyWlc1MFd6RmRMQ0JsZG1WdWRGc3lYU3dnWlcxcGRFdGxlU2s3WEc0Z0lDQWdmU2s3WEc1OVhHNWNibVoxYm1OMGFXOXVJRVZ1ZEdrb2JXOWtaV3dwZTF4dUlDQWdJSFpoY2lCa1pYUmhZMmhsWkNBOUlHMXZaR1ZzSUQwOVBTQm1ZV3h6WlR0Y2JseHVJQ0FnSUdsbUtDRnRiMlJsYkNCOGZDQW9kSGx3Wlc5bUlHMXZaR1ZzSUNFOVBTQW5iMkpxWldOMEp5QW1KaUIwZVhCbGIyWWdiVzlrWld3Z0lUMDlJQ2RtZFc1amRHbHZiaWNwS1h0Y2JpQWdJQ0FnSUNBZ2JXOWtaV3dnUFNCN2ZUdGNiaUFnSUNCOVhHNWNiaUFnSUNCMGFHbHpMbDlsYldsMGRHVmtSWFpsYm5SeklEMGdlMzA3WEc0Z0lDQWdhV1lvWkdWMFlXTm9aV1FwZTF4dUlDQWdJQ0FnSUNCMGFHbHpMbDl0YjJSbGJDQTlJSHQ5TzF4dUlDQWdJSDFsYkhObGUxeHVJQ0FnSUNBZ0lDQjBhR2x6TG1GMGRHRmphQ2h0YjJSbGJDazdYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2RHaHBjeTV2YmlnbmJtVjNUR2x6ZEdWdVpYSW5MQ0JtZFc1amRHbHZiaWdwZTF4dUlDQWdJQ0FnSUNCdGIyUnBabWxsWkVWdWRHbGxjeTVoWkdRb2RHaHBjeWs3WEc0Z0lDQWdmU2s3WEc1OVhHNUZiblJwTG1WdGFYUWdQU0JtZFc1amRHbHZiaWh0YjJSbGJDd2dhMlY1TENCMllXeDFaU2w3WEc0Z0lDQWdhV1lvSVNoMGVYQmxiMllnYlc5a1pXd2dQVDA5SUNkdlltcGxZM1FuSUh4OElIUjVjR1Z2WmlCdGIyUmxiQ0E5UFQwZ0oyWjFibU4wYVc5dUp5a3BlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNDdYRzRnSUNBZ2ZWeHVYRzRnSUNBZ1pXMXBkQ2hiVzIxdlpHVnNMQ0JyWlhrc0lIWmhiSFZsWFYwcE8xeHVmVHRjYmtWdWRHa3VaMlYwSUQwZ1puVnVZM1JwYjI0b2JXOWtaV3dzSUd0bGVTbDdYRzRnSUNBZ2FXWW9JVzF2WkdWc0lIeDhJSFI1Y0dWdlppQnRiMlJsYkNBaFBUMGdKMjlpYW1WamRDY3BlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNDdYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2EyVjVJRDBnWjJWMFZHRnlaMlYwUzJWNUtHdGxlU2s3WEc1Y2JpQWdJQ0JwWmloclpYa2dQVDA5SUNjdUp5bDdYRzRnSUNBZ0lDQWdJSEpsZEhWeWJpQnRiMlJsYkR0Y2JpQWdJQ0I5WEc1Y2JseHVJQ0FnSUhaaGNpQndZWFJvSUQwZ2JHVm1kRUZ1WkZKbGMzUW9hMlY1S1R0Y2JpQWdJQ0JwWmloQmNuSmhlUzVwYzBGeWNtRjVLSEJoZEdncEtYdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlFVnVkR2t1WjJWMEtHMXZaR1ZzVzNCaGRHaGJNRjFkTENCd1lYUm9XekZkS1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdiVzlrWld4YmEyVjVYVHRjYm4wN1hHNUZiblJwTG5ObGRDQTlJR1oxYm1OMGFXOXVLRzF2WkdWc0xDQnJaWGtzSUhaaGJIVmxLWHRjYmlBZ0lDQnBaaWdoYlc5a1pXd2dmSHdnZEhsd1pXOW1JRzF2WkdWc0lDRTlQU0FuYjJKcVpXTjBKeWw3WEc0Z0lDQWdJQ0FnSUhKbGRIVnlianRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnJaWGtnUFNCblpYUlVZWEpuWlhSTFpYa29hMlY1S1R0Y2JseHVJQ0FnSUhaaGNpQndZWFJvSUQwZ2JHVm1kRUZ1WkZKbGMzUW9hMlY1S1R0Y2JpQWdJQ0JwWmloQmNuSmhlUzVwYzBGeWNtRjVLSEJoZEdncEtYdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlFVnVkR2t1YzJWMEtHMXZaR1ZzVzNCaGRHaGJNRjFkTENCd1lYUm9XekZkTENCMllXeDFaU2s3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUc5eWFXZHBibUZzSUQwZ2JXOWtaV3hiYTJWNVhUdGNibHh1SUNBZ0lHbG1LSFI1Y0dWdlppQjJZV3gxWlNBaFBUMGdKMjlpYW1WamRDY2dKaVlnZG1Gc2RXVWdQVDA5SUc5eWFXZHBibUZzS1h0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1TzF4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCclpYbHpRMmhoYm1kbFpDQTlJQ0VvYTJWNUlHbHVJRzF2WkdWc0tUdGNibHh1SUNBZ0lHMXZaR1ZzVzJ0bGVWMGdQU0IyWVd4MVpUdGNibHh1SUNBZ0lIWmhjaUJsZG1WdWRITWdQU0JiVzIxdlpHVnNMQ0JyWlhrc0lIWmhiSFZsWFYwN1hHNWNiaUFnSUNCcFppaHJaWGx6UTJoaGJtZGxaQ2w3WEc0Z0lDQWdJQ0FnSUdsbUtFRnljbUY1TG1selFYSnlZWGtvYlc5a1pXd3BLWHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHVjJaVzUwY3k1d2RYTm9LRnR0YjJSbGJDd2dKMnhsYm1kMGFDY3NJRzF2WkdWc0xteGxibWQwYUYwcE8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ1pXMXBkQ2hsZG1WdWRITXBPMXh1ZlR0Y2JrVnVkR2t1Y0hWemFDQTlJR1oxYm1OMGFXOXVLRzF2WkdWc0xDQnJaWGtzSUhaaGJIVmxLWHRjYmlBZ0lDQnBaaWdoYlc5a1pXd2dmSHdnZEhsd1pXOW1JRzF2WkdWc0lDRTlQU0FuYjJKcVpXTjBKeWw3WEc0Z0lDQWdJQ0FnSUhKbGRIVnlianRjYmlBZ0lDQjlYRzVjYmlBZ0lDQjJZWElnZEdGeVoyVjBPMXh1SUNBZ0lHbG1LR0Z5WjNWdFpXNTBjeTVzWlc1bmRHZ2dQQ0F6S1h0Y2JpQWdJQ0FnSUNBZ2RtRnNkV1VnUFNCclpYazdYRzRnSUNBZ0lDQWdJR3RsZVNBOUlDY3VKenRjYmlBZ0lDQWdJQ0FnZEdGeVoyVjBJRDBnYlc5a1pXdzdYRzRnSUNBZ2ZXVnNjMlY3WEc0Z0lDQWdJQ0FnSUhaaGNpQndZWFJvSUQwZ2JHVm1kRUZ1WkZKbGMzUW9hMlY1S1R0Y2JpQWdJQ0FnSUNBZ2FXWW9RWEp5WVhrdWFYTkJjbkpoZVNod1lYUm9LU2w3WEc0Z0lDQWdJQ0FnSUNBZ0lDQnlaWFIxY200Z1JXNTBhUzV3ZFhOb0tHMXZaR1ZzVzNCaGRHaGJNRjFkTENCd1lYUm9XekZkTENCMllXeDFaU2s3WEc0Z0lDQWdJQ0FnSUgxY2JseHVJQ0FnSUNBZ0lDQjBZWEpuWlhRZ1BTQnRiMlJsYkZ0clpYbGRPMXh1SUNBZ0lIMWNibHh1SUNBZ0lHbG1LQ0ZCY25KaGVTNXBjMEZ5Y21GNUtIUmhjbWRsZENrcGUxeHVJQ0FnSUNBZ0lDQjBhSEp2ZHlBblZHaGxJSFJoY21kbGRDQnBjeUJ1YjNRZ1lXNGdZWEp5WVhrdUp6dGNiaUFnSUNCOVhHNWNiaUFnSUNCMFlYSm5aWFF1Y0hWemFDaDJZV3gxWlNrN1hHNWNiaUFnSUNCMllYSWdaWFpsYm5SeklEMGdXMXh1SUNBZ0lDQWdJQ0JiZEdGeVoyVjBMQ0IwWVhKblpYUXViR1Z1WjNSb0xURXNJSFpoYkhWbFhTeGNiaUFnSUNBZ0lDQWdXM1JoY21kbGRDd2dKMnhsYm1kMGFDY3NJSFJoY21kbGRDNXNaVzVuZEdoZFhHNGdJQ0FnWFR0Y2JseHVJQ0FnSUdWdGFYUW9aWFpsYm5SektUdGNibjA3WEc1RmJuUnBMbWx1YzJWeWRDQTlJR1oxYm1OMGFXOXVLRzF2WkdWc0xDQnJaWGtzSUhaaGJIVmxMQ0JwYm1SbGVDbDdYRzRnSUNBZ2FXWW9JVzF2WkdWc0lIeDhJSFI1Y0dWdlppQnRiMlJsYkNBaFBUMGdKMjlpYW1WamRDY3BlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNDdYRzRnSUNBZ2ZWeHVYRzVjYmlBZ0lDQjJZWElnZEdGeVoyVjBPMXh1SUNBZ0lHbG1LR0Z5WjNWdFpXNTBjeTVzWlc1bmRHZ2dQQ0EwS1h0Y2JpQWdJQ0FnSUNBZ2FXNWtaWGdnUFNCMllXeDFaVHRjYmlBZ0lDQWdJQ0FnZG1Gc2RXVWdQU0JyWlhrN1hHNGdJQ0FnSUNBZ0lHdGxlU0E5SUNjdUp6dGNiaUFnSUNBZ0lDQWdkR0Z5WjJWMElEMGdiVzlrWld3N1hHNGdJQ0FnZldWc2MyVjdYRzRnSUNBZ0lDQWdJSFpoY2lCd1lYUm9JRDBnYkdWbWRFRnVaRkpsYzNRb2EyVjVLVHRjYmlBZ0lDQWdJQ0FnYVdZb1FYSnlZWGt1YVhOQmNuSmhlU2h3WVhSb0tTbDdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnUlc1MGFTNXBibk5sY25Rb2JXOWtaV3hiY0dGMGFGc3dYVjBzSUhCaGRHaGJNVjBzSUhaaGJIVmxMQ0JwYm1SbGVDazdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCMFlYSm5aWFFnUFNCdGIyUmxiRnRyWlhsZE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUdsbUtDRkJjbkpoZVM1cGMwRnljbUY1S0hSaGNtZGxkQ2twZTF4dUlDQWdJQ0FnSUNCMGFISnZkeUFuVkdobElIUmhjbWRsZENCcGN5QnViM1FnWVc0Z1lYSnlZWGt1Snp0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0IwWVhKblpYUXVjM0JzYVdObEtHbHVaR1Y0TENBd0xDQjJZV3gxWlNrN1hHNWNiaUFnSUNCMllYSWdaWFpsYm5SeklEMGdXMXh1SUNBZ0lDQWdJQ0JiZEdGeVoyVjBMQ0JwYm1SbGVDd2dkbUZzZFdWZExGeHVJQ0FnSUNBZ0lDQmJkR0Z5WjJWMExDQW5iR1Z1WjNSb0p5d2dkR0Z5WjJWMExteGxibWQwYUYxY2JpQWdJQ0JkTzF4dVhHNGdJQ0FnWlcxcGRDaGxkbVZ1ZEhNcE8xeHVmVHRjYmtWdWRHa3VjbVZ0YjNabElEMGdablZ1WTNScGIyNG9iVzlrWld3c0lHdGxlU3dnYzNWaVMyVjVLWHRjYmlBZ0lDQnBaaWdoYlc5a1pXd2dmSHdnZEhsd1pXOW1JRzF2WkdWc0lDRTlQU0FuYjJKcVpXTjBKeWw3WEc0Z0lDQWdJQ0FnSUhKbGRIVnlianRjYmlBZ0lDQjlYRzVjYmlBZ0lDQjJZWElnY0dGMGFDQTlJR3hsWm5SQmJtUlNaWE4wS0d0bGVTazdYRzRnSUNBZ2FXWW9RWEp5WVhrdWFYTkJjbkpoZVNod1lYUm9LU2w3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJGYm5ScExuSmxiVzkyWlNodGIyUmxiRnR3WVhSb1d6QmRYU3dnY0dGMGFGc3hYU3dnYzNWaVMyVjVLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQXZMeUJTWlcxdmRtVWdZU0JyWlhrZ2IyWm1JRzltSUdGdUlHOWlhbVZqZENCaGRDQW5hMlY1SjF4dUlDQWdJR2xtS0hOMVlrdGxlU0FoUFNCdWRXeHNLWHRjYmlBZ0lDQWdJQ0FnUlc1MGFTNXlaVzF2ZG1Vb2JXOWtaV3hiYTJWNVhTd2djM1ZpUzJWNUtUdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdU8xeHVJQ0FnSUgxY2JseHVJQ0FnSUdsbUtHdGxlU0E5UFQwZ0p5NG5LWHRjYmlBZ0lDQWdJQ0FnZEdoeWIzY2dKeTRnS0hObGJHWXBJR2x6SUc1dmRDQmhJSFpoYkdsa0lHdGxlU0IwYnlCeVpXMXZkbVVuTzF4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCbGRtVnVkSE1nUFNCYlhUdGNibHh1SUNBZ0lHbG1LRUZ5Y21GNUxtbHpRWEp5WVhrb2JXOWtaV3dwS1h0Y2JpQWdJQ0FnSUNBZ2JXOWtaV3d1YzNCc2FXTmxLR3RsZVN3Z01TazdYRzRnSUNBZ0lDQWdJR1YyWlc1MGN5NXdkWE5vS0Z0dGIyUmxiQ3dnSjJ4bGJtZDBhQ2NzSUcxdlpHVnNMbXhsYm1kMGFGMHBPMXh1SUNBZ0lIMWxiSE5sZTF4dUlDQWdJQ0FnSUNCa1pXeGxkR1VnYlc5a1pXeGJhMlY1WFR0Y2JpQWdJQ0FnSUNBZ1pYWmxiblJ6TG5CMWMyZ29XMjF2WkdWc0xDQnJaWGxkS1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0JsYldsMEtHVjJaVzUwY3lrN1hHNTlPMXh1Ulc1MGFTNXRiM1psSUQwZ1puVnVZM1JwYjI0b2JXOWtaV3dzSUd0bGVTd2dhVzVrWlhncGUxeHVJQ0FnSUdsbUtDRnRiMlJsYkNCOGZDQjBlWEJsYjJZZ2JXOWtaV3dnSVQwOUlDZHZZbXBsWTNRbktYdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdU8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhaaGNpQndZWFJvSUQwZ2JHVm1kRUZ1WkZKbGMzUW9hMlY1S1R0Y2JpQWdJQ0JwWmloQmNuSmhlUzVwYzBGeWNtRjVLSEJoZEdncEtYdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlFVnVkR2t1Ylc5MlpTaHRiMlJsYkZ0d1lYUm9XekJkWFN3Z2NHRjBhRnN4WFN3Z2FXNWtaWGdwTzF4dUlDQWdJSDFjYmx4dUlDQWdJR2xtS0d0bGVTQTlQVDBnYVc1a1pYZ3BlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNDdYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2FXWW9JVUZ5Y21GNUxtbHpRWEp5WVhrb2JXOWtaV3dwS1h0Y2JpQWdJQ0FnSUNBZ2RHaHliM2NnSjFSb1pTQnRiMlJsYkNCcGN5QnViM1FnWVc0Z1lYSnlZWGt1Snp0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0IyWVhJZ2FYUmxiU0E5SUcxdlpHVnNXMnRsZVYwN1hHNWNiaUFnSUNCdGIyUmxiQzV6Y0d4cFkyVW9hMlY1TENBeEtUdGNibHh1SUNBZ0lHMXZaR1ZzTG5Od2JHbGpaU2hwYm1SbGVDQXRJQ2hwYm1SbGVDQStJR3RsZVNBL0lEQWdPaUF4S1N3Z01Dd2dhWFJsYlNrN1hHNWNiaUFnSUNCbGJXbDBLRnRiYlc5a1pXd3NJR2x1WkdWNExDQnBkR1Z0WFYwcE8xeHVmVHRjYmtWdWRHa3VkWEJrWVhSbElEMGdablZ1WTNScGIyNG9iVzlrWld3c0lHdGxlU3dnZG1Gc2RXVXBlMXh1SUNBZ0lHbG1LQ0Z0YjJSbGJDQjhmQ0IwZVhCbGIyWWdiVzlrWld3Z0lUMDlJQ2R2WW1wbFkzUW5LWHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVPMXh1SUNBZ0lIMWNibHh1SUNBZ0lIWmhjaUIwWVhKblpYUXNYRzRnSUNBZ0lDQWdJR2x6UVhKeVlYa2dQU0JCY25KaGVTNXBjMEZ5Y21GNUtIWmhiSFZsS1R0Y2JseHVJQ0FnSUdsbUtHRnlaM1Z0Wlc1MGN5NXNaVzVuZEdnZ1BDQXpLWHRjYmlBZ0lDQWdJQ0FnZG1Gc2RXVWdQU0JyWlhrN1hHNGdJQ0FnSUNBZ0lHdGxlU0E5SUNjdUp6dGNiaUFnSUNBZ0lDQWdkR0Z5WjJWMElEMGdiVzlrWld3N1hHNGdJQ0FnZldWc2MyVjdYRzRnSUNBZ0lDQWdJSFpoY2lCd1lYUm9JRDBnYkdWbWRFRnVaRkpsYzNRb2EyVjVLVHRjYmlBZ0lDQWdJQ0FnYVdZb1FYSnlZWGt1YVhOQmNuSmhlU2h3WVhSb0tTbDdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnUlc1MGFTNTFjR1JoZEdVb2JXOWtaV3hiY0dGMGFGc3dYVjBzSUhCaGRHaGJNVjBzSUhaaGJIVmxLVHRjYmlBZ0lDQWdJQ0FnZlZ4dVhHNGdJQ0FnSUNBZ0lIUmhjbWRsZENBOUlHMXZaR1ZzVzJ0bGVWMDdYRzVjYmlBZ0lDQWdJQ0FnYVdZb2RHRnlaMlYwSUQwOUlHNTFiR3dwZTF4dUlDQWdJQ0FnSUNBZ0lDQWdiVzlrWld4YmEyVjVYU0E5SUdselFYSnlZWGtnUHlCYlhTQTZJSHQ5TzF4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnYVdZb2RIbHdaVzltSUhaaGJIVmxJQ0U5UFNBbmIySnFaV04wSnlsN1hHNGdJQ0FnSUNBZ0lIUm9jbTkzSUNkVWFHVWdkbUZzZFdVZ2FYTWdibTkwSUdGdUlHOWlhbVZqZEM0bk8xeHVJQ0FnSUgxY2JseHVJQ0FnSUdsbUtIUjVjR1Z2WmlCMFlYSm5aWFFnSVQwOUlDZHZZbXBsWTNRbktYdGNiaUFnSUNBZ0lDQWdkR2h5YjNjZ0oxUm9aU0IwWVhKblpYUWdhWE1nYm05MElHRnVJRzlpYW1WamRDNG5PMXh1SUNBZ0lIMWNibHh1SUNBZ0lIWmhjaUJsZG1WdWRITWdQU0JiWFN4Y2JpQWdJQ0FnSUNBZ2RYQmtZWFJsWkU5aWFtVmpkSE1nUFNCdVpYY2dWMlZoYTFObGRDZ3BPMXh1WEc0Z0lDQWdablZ1WTNScGIyNGdkWEJrWVhSbFZHRnlaMlYwS0hSaGNtZGxkQ3dnZG1Gc2RXVXBlMXh1SUNBZ0lDQWdJQ0JtYjNJb2RtRnlJR3RsZVNCcGJpQjJZV3gxWlNsN1hHNGdJQ0FnSUNBZ0lDQWdJQ0IyWVhJZ1kzVnljbVZ1ZEZaaGJIVmxJRDBnZEdGeVoyVjBXMnRsZVYwN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JwWmloamRYSnlaVzUwVm1Gc2RXVWdhVzV6ZEdGdVkyVnZaaUJQWW1wbFkzUWdKaVlnSVhWd1pHRjBaV1JQWW1wbFkzUnpMbWhoY3loamRYSnlaVzUwVm1Gc2RXVXBJQ1ltSUNFb1kzVnljbVZ1ZEZaaGJIVmxJR2x1YzNSaGJtTmxiMllnUkdGMFpTa3BlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSFZ3WkdGMFpXUlBZbXBsWTNSekxtRmtaQ2hqZFhKeVpXNTBWbUZzZFdVcE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIVndaR0YwWlZSaGNtZGxkQ2hqZFhKeVpXNTBWbUZzZFdVc0lIWmhiSFZsVzJ0bGVWMHBPMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR052Ym5ScGJuVmxPMXh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnZEdGeVoyVjBXMnRsZVYwZ1BTQjJZV3gxWlZ0clpYbGRPMXh1SUNBZ0lDQWdJQ0FnSUNBZ1pYWmxiblJ6TG5CMWMyZ29XM1JoY21kbGRDd2dhMlY1TENCMllXeDFaVnRyWlhsZFhTazdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCcFppaEJjbkpoZVM1cGMwRnljbUY1S0hSaGNtZGxkQ2twZTF4dUlDQWdJQ0FnSUNBZ0lDQWdaWFpsYm5SekxuQjFjMmdvVzNSaGNtZGxkQ3dnSjJ4bGJtZDBhQ2NzSUhSaGNtZGxkQzVzWlc1bmRHaGRLVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFZ3WkdGMFpWUmhjbWRsZENoMFlYSm5aWFFzSUhaaGJIVmxLVHRjYmx4dUlDQWdJR1Z0YVhRb1pYWmxiblJ6S1R0Y2JuMDdYRzVGYm5ScExuQnliM1J2ZEhsd1pTQTlJRTlpYW1WamRDNWpjbVZoZEdVb1JYWmxiblJGYldsMGRHVnlMbkJ5YjNSdmRIbHdaU2s3WEc1RmJuUnBMbkJ5YjNSdmRIbHdaUzVmYldGNFRHbHpkR1Z1WlhKeklEMGdNVEF3TzF4dVJXNTBhUzV3Y205MGIzUjVjR1V1WTI5dWMzUnlkV04wYjNJZ1BTQkZiblJwTzF4dVJXNTBhUzV3Y205MGIzUjVjR1V1WVhSMFlXTm9JRDBnWm5WdVkzUnBiMjRvYlc5a1pXd3BlMXh1SUNBZ0lHbG1LSFJvYVhNdVgyMXZaR1ZzSUNFOVBTQnRiMlJsYkNsN1hHNGdJQ0FnSUNBZ0lIUm9hWE11WkdWMFlXTm9LQ2s3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdhV1lvYlc5a1pXd2dKaVlnSVdselNXNXpkR0Z1WTJVb2JXOWtaV3dwS1h0Y2JpQWdJQ0FnSUNBZ2RHaHliM2NnSjBWdWRHbHpJRzFoZVNCdmJteDVJR0psSUdGMGRHRmphR1ZrSUhSdklHRnVJRzlpYW1WamRDd2diM0lnYm5Wc2JDOTFibVJsWm1sdVpXUW5PMXh1SUNBZ0lIMWNibHh1SUNBZ0lHMXZaR2xtYVdWa1JXNTBhV1Z6TG1Ga1pDaDBhR2x6S1R0Y2JpQWdJQ0IwYUdsekxsOWhkSFJoWTJobFpDQTlJSFJ5ZFdVN1hHNGdJQ0FnZEdocGN5NWZiVzlrWld3Z1BTQnRiMlJsYkR0Y2JpQWdJQ0IwYUdsekxtVnRhWFFvSjJGMGRHRmphQ2NzSUcxdlpHVnNLVHRjYm4wN1hHNUZiblJwTG5CeWIzUnZkSGx3WlM1a1pYUmhZMmdnUFNCbWRXNWpkR2x2YmlncGUxeHVJQ0FnSUcxdlpHbG1hV1ZrUlc1MGFXVnpMbVJsYkdWMFpTaDBhR2x6S1R0Y2JseHVJQ0FnSUhSb2FYTXVYMlZ0YVhSMFpXUkZkbVZ1ZEhNZ1BTQjdmVHRjYmlBZ0lDQjBhR2x6TGw5dGIyUmxiQ0E5SUh0OU8xeHVJQ0FnSUhSb2FYTXVYMkYwZEdGamFHVmtJRDBnWm1Gc2MyVTdYRzRnSUNBZ2RHaHBjeTVsYldsMEtDZGtaWFJoWTJnbktUdGNibjA3WEc1RmJuUnBMbkJ5YjNSdmRIbHdaUzVrWlhOMGNtOTVJRDBnWm5WdVkzUnBiMjRvS1h0Y2JpQWdJQ0IwYUdsekxtUmxkR0ZqYUNncE8xeHVJQ0FnSUhSb2FYTXVYMlYyWlc1MGN5QTlJRzUxYkd3N1hHNGdJQ0FnZEdocGN5NWxiV2wwS0Nka1pYTjBjbTk1SnlrN1hHNTlPMXh1Ulc1MGFTNXdjbTkwYjNSNWNHVXVaMlYwSUQwZ1puVnVZM1JwYjI0b2EyVjVLWHRjYmlBZ0lDQnlaWFIxY200Z1JXNTBhUzVuWlhRb2RHaHBjeTVmYlc5a1pXd3NJR3RsZVNrN1hHNTlPMXh1WEc1RmJuUnBMbkJ5YjNSdmRIbHdaUzV6WlhRZ1BTQm1kVzVqZEdsdmJpaHJaWGtzSUhaaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z1JXNTBhUzV6WlhRb2RHaHBjeTVmYlc5a1pXd3NJR3RsZVN3Z2RtRnNkV1VwTzF4dWZUdGNibHh1Ulc1MGFTNXdjbTkwYjNSNWNHVXVjSFZ6YUNBOUlHWjFibU4wYVc5dUtHdGxlU3dnZG1Gc2RXVXBlMXh1SUNBZ0lISmxkSFZ5YmlCRmJuUnBMbkIxYzJndVlYQndiSGtvYm5Wc2JDd2dXM1JvYVhNdVgyMXZaR1ZzWFM1amIyNWpZWFFvZEc5QmNuSmhlU2hoY21kMWJXVnVkSE1wS1NrN1hHNTlPMXh1WEc1RmJuUnBMbkJ5YjNSdmRIbHdaUzVwYm5ObGNuUWdQU0JtZFc1amRHbHZiaWhyWlhrc0lIWmhiSFZsTENCcGJtUmxlQ2w3WEc0Z0lDQWdjbVYwZFhKdUlFVnVkR2t1YVc1elpYSjBMbUZ3Y0d4NUtHNTFiR3dzSUZ0MGFHbHpMbDl0YjJSbGJGMHVZMjl1WTJGMEtIUnZRWEp5WVhrb1lYSm5kVzFsYm5SektTa3BPMXh1ZlR0Y2JseHVSVzUwYVM1d2NtOTBiM1I1Y0dVdWNtVnRiM1psSUQwZ1puVnVZM1JwYjI0b2EyVjVMQ0J6ZFdKTFpYa3BlMXh1SUNBZ0lISmxkSFZ5YmlCRmJuUnBMbkpsYlc5MlpTNWhjSEJzZVNodWRXeHNMQ0JiZEdocGN5NWZiVzlrWld4ZExtTnZibU5oZENoMGIwRnljbUY1S0dGeVozVnRaVzUwY3lrcEtUdGNibjA3WEc1Y2JrVnVkR2t1Y0hKdmRHOTBlWEJsTG0xdmRtVWdQU0JtZFc1amRHbHZiaWhyWlhrc0lHbHVaR1Y0S1h0Y2JpQWdJQ0J5WlhSMWNtNGdSVzUwYVM1dGIzWmxMbUZ3Y0d4NUtHNTFiR3dzSUZ0MGFHbHpMbDl0YjJSbGJGMHVZMjl1WTJGMEtIUnZRWEp5WVhrb1lYSm5kVzFsYm5SektTa3BPMXh1ZlR0Y2JseHVSVzUwYVM1d2NtOTBiM1I1Y0dVdWRYQmtZWFJsSUQwZ1puVnVZM1JwYjI0b2EyVjVMQ0JwYm1SbGVDbDdYRzRnSUNBZ2NtVjBkWEp1SUVWdWRHa3VkWEJrWVhSbExtRndjR3g1S0c1MWJHd3NJRnQwYUdsekxsOXRiMlJsYkYwdVkyOXVZMkYwS0hSdlFYSnlZWGtvWVhKbmRXMWxiblJ6S1NrcE8xeHVmVHRjYmtWdWRHa3VjSEp2ZEc5MGVYQmxMbWx6UVhSMFlXTm9aV1FnUFNCbWRXNWpkR2x2YmlncGUxeHVJQ0FnSUhKbGRIVnliaUIwYUdsekxsOWhkSFJoWTJobFpEdGNibjA3WEc1RmJuUnBMbkJ5YjNSdmRIbHdaUzVoZEhSaFkyaGxaRU52ZFc1MElEMGdablZ1WTNScGIyNG9LWHRjYmlBZ0lDQnlaWFIxY200Z2JXOWthV1pwWldSRmJuUnBaWE11YzJsNlpUdGNibjA3WEc1Y2JrVnVkR2t1YVhORmJuUnBJRDBnWm5WdVkzUnBiMjRvZEdGeVoyVjBLWHRjYmlBZ0lDQnlaWFIxY200Z2RHRnlaMlYwSUNZbUlDRWhmbWRzYjJKaGJGTjBZWFJsTG1sdWMzUmhibU5sY3k1cGJtUmxlRTltS0hSaGNtZGxkQzVqYjI1emRISjFZM1J2Y2lrN1hHNTlPMXh1WEc1RmJuUnBMbk4wYjNKbElEMGdablZ1WTNScGIyNG9kR0Z5WjJWMExDQnJaWGtzSUhaaGJIVmxLWHRjYmlBZ0lDQnBaaWhoY21kMWJXVnVkSE11YkdWdVozUm9JRHdnTWlsN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCRmJuUnBMbWRsZENoMFlYSm5aWFFzSUd0bGVTazdYRzRnSUNBZ2ZWeHVYRzRnSUNBZ1JXNTBhUzV6WlhRb2RHRnlaMlYwTENCclpYa3NJSFpoYkhWbEtUdGNibjA3WEc1Y2JtZHNiMkpoYkZOMFlYUmxMbWx1YzNSaGJtTmxjeTV3ZFhOb0tFVnVkR2twTzF4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlFVnVkR2s3WEc0aVhYMD0iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHZhbHVlKXtcclxuICAgIHJldHVybiB2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJztcclxufTsiLCJ2YXIgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyLFxuICAgIGZ1bmN0aW9uRW1pdHRlclByb3RvdHlwZSA9IGZ1bmN0aW9uKCl7fTtcblxuZm9yKHZhciBrZXkgaW4gRXZlbnRFbWl0dGVyLnByb3RvdHlwZSl7XG4gICAgZnVuY3Rpb25FbWl0dGVyUHJvdG90eXBlW2tleV0gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlW2tleV07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb25FbWl0dGVyUHJvdG90eXBlOyIsIid1c2Ugc3RyaWN0JztcbnZhciBwcm9wSXNFbnVtZXJhYmxlID0gT2JqZWN0LnByb3RvdHlwZS5wcm9wZXJ0eUlzRW51bWVyYWJsZTtcblxuZnVuY3Rpb24gVG9PYmplY3QodmFsKSB7XG5cdGlmICh2YWwgPT0gbnVsbCkge1xuXHRcdHRocm93IG5ldyBUeXBlRXJyb3IoJ09iamVjdC5hc3NpZ24gY2Fubm90IGJlIGNhbGxlZCB3aXRoIG51bGwgb3IgdW5kZWZpbmVkJyk7XG5cdH1cblxuXHRyZXR1cm4gT2JqZWN0KHZhbCk7XG59XG5cbmZ1bmN0aW9uIG93bkVudW1lcmFibGVLZXlzKG9iaikge1xuXHR2YXIga2V5cyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKG9iaik7XG5cblx0aWYgKE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMpIHtcblx0XHRrZXlzID0ga2V5cy5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhvYmopKTtcblx0fVxuXG5cdHJldHVybiBrZXlzLmZpbHRlcihmdW5jdGlvbiAoa2V5KSB7XG5cdFx0cmV0dXJuIHByb3BJc0VudW1lcmFibGUuY2FsbChvYmosIGtleSk7XG5cdH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gKHRhcmdldCwgc291cmNlKSB7XG5cdHZhciBmcm9tO1xuXHR2YXIga2V5cztcblx0dmFyIHRvID0gVG9PYmplY3QodGFyZ2V0KTtcblxuXHRmb3IgKHZhciBzID0gMTsgcyA8IGFyZ3VtZW50cy5sZW5ndGg7IHMrKykge1xuXHRcdGZyb20gPSBhcmd1bWVudHNbc107XG5cdFx0a2V5cyA9IG93bkVudW1lcmFibGVLZXlzKE9iamVjdChmcm9tKSk7XG5cblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRvW2tleXNbaV1dID0gZnJvbVtrZXlzW2ldXTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gdG87XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc1NhbWUoYSwgYil7XG4gICAgaWYoYSA9PT0gYil7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGlmKFxuICAgICAgICB0eXBlb2YgYSAhPT0gdHlwZW9mIGIgfHxcbiAgICAgICAgdHlwZW9mIGEgPT09ICdvYmplY3QnICYmXG4gICAgICAgICEoYSBpbnN0YW5jZW9mIERhdGUgJiYgYiBpbnN0YW5jZW9mIERhdGUpXG4gICAgKXtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiBTdHJpbmcoYSkgPT09IFN0cmluZyhiKTtcbn07IiwibW9kdWxlLmV4cG9ydHMgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwgKHtfX3Byb3RvX186W119IGluc3RhbmNlb2YgQXJyYXkgPyBzZXRQcm90b09mIDogbWl4aW5Qcm9wZXJ0aWVzKTtcblxuZnVuY3Rpb24gc2V0UHJvdG9PZihvYmosIHByb3RvKSB7XG5cdG9iai5fX3Byb3RvX18gPSBwcm90bztcbn1cblxuZnVuY3Rpb24gbWl4aW5Qcm9wZXJ0aWVzKG9iaiwgcHJvdG8pIHtcblx0Zm9yICh2YXIgcHJvcCBpbiBwcm90bykge1xuXHRcdG9ialtwcm9wXSA9IHByb3RvW3Byb3BdO1xuXHR9XG59XG4iLCJ2YXIgY2xvbmUgPSByZXF1aXJlKCdjbG9uZScpLFxuICAgIGRlZXBFcXVhbCA9IHJlcXVpcmUoJ2N5Y2xpYy1kZWVwLWVxdWFsJyk7XG5cbmZ1bmN0aW9uIGtleXNBcmVEaWZmZXJlbnQoa2V5czEsIGtleXMyKXtcbiAgICBpZihrZXlzMSA9PT0ga2V5czIpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmKCFrZXlzMSB8fCAha2V5czIgfHwga2V5czEubGVuZ3RoICE9PSBrZXlzMi5sZW5ndGgpe1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGtleXMxLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgaWYoIX5rZXlzMi5pbmRleE9mKGtleXMxW2ldKSl7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0S2V5cyh2YWx1ZSl7XG4gICAgaWYoIXZhbHVlIHx8IHR5cGVvZiB2YWx1ZSAhPT0gJ29iamVjdCcpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gV2hhdENoYW5nZWQodmFsdWUsIGNoYW5nZXNUb1RyYWNrKXtcbiAgICB0aGlzLl9jaGFuZ2VzVG9UcmFjayA9IHt9O1xuXG4gICAgaWYoY2hhbmdlc1RvVHJhY2sgPT0gbnVsbCl7XG4gICAgICAgIGNoYW5nZXNUb1RyYWNrID0gJ3ZhbHVlIHR5cGUga2V5cyBzdHJ1Y3R1cmUgcmVmZXJlbmNlJztcbiAgICB9XG5cbiAgICBpZih0eXBlb2YgY2hhbmdlc1RvVHJhY2sgIT09ICdzdHJpbmcnKXtcbiAgICAgICAgdGhyb3cgJ2NoYW5nZXNUb1RyYWNrIG11c3QgYmUgb2YgdHlwZSBzdHJpbmcnO1xuICAgIH1cblxuICAgIGNoYW5nZXNUb1RyYWNrID0gY2hhbmdlc1RvVHJhY2suc3BsaXQoJyAnKTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hhbmdlc1RvVHJhY2subGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGhpcy5fY2hhbmdlc1RvVHJhY2tbY2hhbmdlc1RvVHJhY2tbaV1dID0gdHJ1ZTtcbiAgICB9O1xuXG4gICAgdGhpcy51cGRhdGUodmFsdWUpO1xufVxuV2hhdENoYW5nZWQucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uKHZhbHVlKXtcbiAgICB2YXIgcmVzdWx0ID0ge30sXG4gICAgICAgIGNoYW5nZXNUb1RyYWNrID0gdGhpcy5fY2hhbmdlc1RvVHJhY2ssXG4gICAgICAgIG5ld0tleXMgPSBnZXRLZXlzKHZhbHVlKTtcblxuICAgIGlmKCd2YWx1ZScgaW4gY2hhbmdlc1RvVHJhY2sgJiYgdmFsdWUrJycgIT09IHRoaXMuX2xhc3RSZWZlcmVuY2UrJycpe1xuICAgICAgICByZXN1bHQudmFsdWUgPSB0cnVlO1xuICAgIH1cbiAgICBpZihcbiAgICAgICAgJ3R5cGUnIGluIGNoYW5nZXNUb1RyYWNrICYmIHR5cGVvZiB2YWx1ZSAhPT0gdHlwZW9mIHRoaXMuX2xhc3RWYWx1ZSB8fFxuICAgICAgICAodmFsdWUgPT09IG51bGwgfHwgdGhpcy5fbGFzdFZhbHVlID09PSBudWxsKSAmJiB0aGlzLnZhbHVlICE9PSB0aGlzLl9sYXN0VmFsdWUgLy8gdHlwZW9mIG51bGwgPT09ICdvYmplY3QnXG4gICAgKXtcbiAgICAgICAgcmVzdWx0LnR5cGUgPSB0cnVlO1xuICAgIH1cbiAgICBpZigna2V5cycgaW4gY2hhbmdlc1RvVHJhY2sgJiYga2V5c0FyZURpZmZlcmVudCh0aGlzLl9sYXN0S2V5cywgZ2V0S2V5cyh2YWx1ZSkpKXtcbiAgICAgICAgcmVzdWx0LmtleXMgPSB0cnVlO1xuICAgIH1cblxuICAgIGlmKHZhbHVlICE9PSBudWxsICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKXtcbiAgICAgICAgdmFyIGxhc3RWYWx1ZSA9IHRoaXMuX2xhc3RWYWx1ZTtcblxuICAgICAgICBpZignc2hhbGxvd1N0cnVjdHVyZScgaW4gY2hhbmdlc1RvVHJhY2sgJiYgKCFsYXN0VmFsdWUgfHwgdHlwZW9mIGxhc3RWYWx1ZSAhPT0gJ29iamVjdCcgfHwgT2JqZWN0LmtleXModmFsdWUpLnNvbWUoZnVuY3Rpb24oa2V5LCBpbmRleCl7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWVba2V5XSAhPT0gbGFzdFZhbHVlW2tleV07XG4gICAgICAgIH0pKSl7XG4gICAgICAgICAgICByZXN1bHQuc2hhbGxvd1N0cnVjdHVyZSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYoJ3N0cnVjdHVyZScgaW4gY2hhbmdlc1RvVHJhY2sgJiYgIWRlZXBFcXVhbCh2YWx1ZSwgbGFzdFZhbHVlKSl7XG4gICAgICAgICAgICByZXN1bHQuc3RydWN0dXJlID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZigncmVmZXJlbmNlJyBpbiBjaGFuZ2VzVG9UcmFjayAmJiB2YWx1ZSAhPT0gdGhpcy5fbGFzdFJlZmVyZW5jZSl7XG4gICAgICAgICAgICByZXN1bHQucmVmZXJlbmNlID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuX2xhc3RWYWx1ZSA9ICdzdHJ1Y3R1cmUnIGluIGNoYW5nZXNUb1RyYWNrID8gY2xvbmUodmFsdWUpIDogJ3NoYWxsb3dTdHJ1Y3R1cmUnIGluIGNoYW5nZXNUb1RyYWNrID8gY2xvbmUodmFsdWUsIHRydWUsIDEpOiB2YWx1ZTtcbiAgICB0aGlzLl9sYXN0UmVmZXJlbmNlID0gdmFsdWU7XG4gICAgdGhpcy5fbGFzdEtleXMgPSBuZXdLZXlzO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gV2hhdENoYW5nZWQ7IiwiKGZ1bmN0aW9uIChCdWZmZXIpe1xudmFyIGNsb25lID0gKGZ1bmN0aW9uKCkge1xuJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIENsb25lcyAoY29waWVzKSBhbiBPYmplY3QgdXNpbmcgZGVlcCBjb3B5aW5nLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gc3VwcG9ydHMgY2lyY3VsYXIgcmVmZXJlbmNlcyBieSBkZWZhdWx0LCBidXQgaWYgeW91IGFyZSBjZXJ0YWluXG4gKiB0aGVyZSBhcmUgbm8gY2lyY3VsYXIgcmVmZXJlbmNlcyBpbiB5b3VyIG9iamVjdCwgeW91IGNhbiBzYXZlIHNvbWUgQ1BVIHRpbWVcbiAqIGJ5IGNhbGxpbmcgY2xvbmUob2JqLCBmYWxzZSkuXG4gKlxuICogQ2F1dGlvbjogaWYgYGNpcmN1bGFyYCBpcyBmYWxzZSBhbmQgYHBhcmVudGAgY29udGFpbnMgY2lyY3VsYXIgcmVmZXJlbmNlcyxcbiAqIHlvdXIgcHJvZ3JhbSBtYXkgZW50ZXIgYW4gaW5maW5pdGUgbG9vcCBhbmQgY3Jhc2guXG4gKlxuICogQHBhcmFtIGBwYXJlbnRgIC0gdGhlIG9iamVjdCB0byBiZSBjbG9uZWRcbiAqIEBwYXJhbSBgY2lyY3VsYXJgIC0gc2V0IHRvIHRydWUgaWYgdGhlIG9iamVjdCB0byBiZSBjbG9uZWQgbWF5IGNvbnRhaW5cbiAqICAgIGNpcmN1bGFyIHJlZmVyZW5jZXMuIChvcHRpb25hbCAtIHRydWUgYnkgZGVmYXVsdClcbiAqIEBwYXJhbSBgZGVwdGhgIC0gc2V0IHRvIGEgbnVtYmVyIGlmIHRoZSBvYmplY3QgaXMgb25seSB0byBiZSBjbG9uZWQgdG9cbiAqICAgIGEgcGFydGljdWxhciBkZXB0aC4gKG9wdGlvbmFsIC0gZGVmYXVsdHMgdG8gSW5maW5pdHkpXG4gKiBAcGFyYW0gYHByb3RvdHlwZWAgLSBzZXRzIHRoZSBwcm90b3R5cGUgdG8gYmUgdXNlZCB3aGVuIGNsb25pbmcgYW4gb2JqZWN0LlxuICogICAgKG9wdGlvbmFsIC0gZGVmYXVsdHMgdG8gcGFyZW50IHByb3RvdHlwZSkuXG4qL1xuZnVuY3Rpb24gY2xvbmUocGFyZW50LCBjaXJjdWxhciwgZGVwdGgsIHByb3RvdHlwZSkge1xuICB2YXIgZmlsdGVyO1xuICBpZiAodHlwZW9mIGNpcmN1bGFyID09PSAnb2JqZWN0Jykge1xuICAgIGRlcHRoID0gY2lyY3VsYXIuZGVwdGg7XG4gICAgcHJvdG90eXBlID0gY2lyY3VsYXIucHJvdG90eXBlO1xuICAgIGZpbHRlciA9IGNpcmN1bGFyLmZpbHRlcjtcbiAgICBjaXJjdWxhciA9IGNpcmN1bGFyLmNpcmN1bGFyXG4gIH1cbiAgLy8gbWFpbnRhaW4gdHdvIGFycmF5cyBmb3IgY2lyY3VsYXIgcmVmZXJlbmNlcywgd2hlcmUgY29ycmVzcG9uZGluZyBwYXJlbnRzXG4gIC8vIGFuZCBjaGlsZHJlbiBoYXZlIHRoZSBzYW1lIGluZGV4XG4gIHZhciBhbGxQYXJlbnRzID0gW107XG4gIHZhciBhbGxDaGlsZHJlbiA9IFtdO1xuXG4gIHZhciB1c2VCdWZmZXIgPSB0eXBlb2YgQnVmZmVyICE9ICd1bmRlZmluZWQnO1xuXG4gIGlmICh0eXBlb2YgY2lyY3VsYXIgPT0gJ3VuZGVmaW5lZCcpXG4gICAgY2lyY3VsYXIgPSB0cnVlO1xuXG4gIGlmICh0eXBlb2YgZGVwdGggPT0gJ3VuZGVmaW5lZCcpXG4gICAgZGVwdGggPSBJbmZpbml0eTtcblxuICAvLyByZWN1cnNlIHRoaXMgZnVuY3Rpb24gc28gd2UgZG9uJ3QgcmVzZXQgYWxsUGFyZW50cyBhbmQgYWxsQ2hpbGRyZW5cbiAgZnVuY3Rpb24gX2Nsb25lKHBhcmVudCwgZGVwdGgpIHtcbiAgICAvLyBjbG9uaW5nIG51bGwgYWx3YXlzIHJldHVybnMgbnVsbFxuICAgIGlmIChwYXJlbnQgPT09IG51bGwpXG4gICAgICByZXR1cm4gbnVsbDtcblxuICAgIGlmIChkZXB0aCA9PSAwKVxuICAgICAgcmV0dXJuIHBhcmVudDtcblxuICAgIHZhciBjaGlsZDtcbiAgICB2YXIgcHJvdG87XG4gICAgaWYgKHR5cGVvZiBwYXJlbnQgIT0gJ29iamVjdCcpIHtcbiAgICAgIHJldHVybiBwYXJlbnQ7XG4gICAgfVxuXG4gICAgaWYgKGNsb25lLl9faXNBcnJheShwYXJlbnQpKSB7XG4gICAgICBjaGlsZCA9IFtdO1xuICAgIH0gZWxzZSBpZiAoY2xvbmUuX19pc1JlZ0V4cChwYXJlbnQpKSB7XG4gICAgICBjaGlsZCA9IG5ldyBSZWdFeHAocGFyZW50LnNvdXJjZSwgX19nZXRSZWdFeHBGbGFncyhwYXJlbnQpKTtcbiAgICAgIGlmIChwYXJlbnQubGFzdEluZGV4KSBjaGlsZC5sYXN0SW5kZXggPSBwYXJlbnQubGFzdEluZGV4O1xuICAgIH0gZWxzZSBpZiAoY2xvbmUuX19pc0RhdGUocGFyZW50KSkge1xuICAgICAgY2hpbGQgPSBuZXcgRGF0ZShwYXJlbnQuZ2V0VGltZSgpKTtcbiAgICB9IGVsc2UgaWYgKHVzZUJ1ZmZlciAmJiBCdWZmZXIuaXNCdWZmZXIocGFyZW50KSkge1xuICAgICAgY2hpbGQgPSBuZXcgQnVmZmVyKHBhcmVudC5sZW5ndGgpO1xuICAgICAgcGFyZW50LmNvcHkoY2hpbGQpO1xuICAgICAgcmV0dXJuIGNoaWxkO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodHlwZW9mIHByb3RvdHlwZSA9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihwYXJlbnQpO1xuICAgICAgICBjaGlsZCA9IE9iamVjdC5jcmVhdGUocHJvdG8pO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIGNoaWxkID0gT2JqZWN0LmNyZWF0ZShwcm90b3R5cGUpO1xuICAgICAgICBwcm90byA9IHByb3RvdHlwZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY2lyY3VsYXIpIHtcbiAgICAgIHZhciBpbmRleCA9IGFsbFBhcmVudHMuaW5kZXhPZihwYXJlbnQpO1xuXG4gICAgICBpZiAoaW5kZXggIT0gLTEpIHtcbiAgICAgICAgcmV0dXJuIGFsbENoaWxkcmVuW2luZGV4XTtcbiAgICAgIH1cbiAgICAgIGFsbFBhcmVudHMucHVzaChwYXJlbnQpO1xuICAgICAgYWxsQ2hpbGRyZW4ucHVzaChjaGlsZCk7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSBpbiBwYXJlbnQpIHtcbiAgICAgIHZhciBhdHRycztcbiAgICAgIGlmIChwcm90bykge1xuICAgICAgICBhdHRycyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IocHJvdG8sIGkpO1xuICAgICAgfVxuXG4gICAgICBpZiAoYXR0cnMgJiYgYXR0cnMuc2V0ID09IG51bGwpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBjaGlsZFtpXSA9IF9jbG9uZShwYXJlbnRbaV0sIGRlcHRoIC0gMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNoaWxkO1xuICB9XG5cbiAgcmV0dXJuIF9jbG9uZShwYXJlbnQsIGRlcHRoKTtcbn1cblxuLyoqXG4gKiBTaW1wbGUgZmxhdCBjbG9uZSB1c2luZyBwcm90b3R5cGUsIGFjY2VwdHMgb25seSBvYmplY3RzLCB1c2VmdWxsIGZvciBwcm9wZXJ0eVxuICogb3ZlcnJpZGUgb24gRkxBVCBjb25maWd1cmF0aW9uIG9iamVjdCAobm8gbmVzdGVkIHByb3BzKS5cbiAqXG4gKiBVU0UgV0lUSCBDQVVUSU9OISBUaGlzIG1heSBub3QgYmVoYXZlIGFzIHlvdSB3aXNoIGlmIHlvdSBkbyBub3Qga25vdyBob3cgdGhpc1xuICogd29ya3MuXG4gKi9cbmNsb25lLmNsb25lUHJvdG90eXBlID0gZnVuY3Rpb24gY2xvbmVQcm90b3R5cGUocGFyZW50KSB7XG4gIGlmIChwYXJlbnQgPT09IG51bGwpXG4gICAgcmV0dXJuIG51bGw7XG5cbiAgdmFyIGMgPSBmdW5jdGlvbiAoKSB7fTtcbiAgYy5wcm90b3R5cGUgPSBwYXJlbnQ7XG4gIHJldHVybiBuZXcgYygpO1xufTtcblxuLy8gcHJpdmF0ZSB1dGlsaXR5IGZ1bmN0aW9uc1xuXG5mdW5jdGlvbiBfX29ialRvU3RyKG8pIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKTtcbn07XG5jbG9uZS5fX29ialRvU3RyID0gX19vYmpUb1N0cjtcblxuZnVuY3Rpb24gX19pc0RhdGUobykge1xuICByZXR1cm4gdHlwZW9mIG8gPT09ICdvYmplY3QnICYmIF9fb2JqVG9TdHIobykgPT09ICdbb2JqZWN0IERhdGVdJztcbn07XG5jbG9uZS5fX2lzRGF0ZSA9IF9faXNEYXRlO1xuXG5mdW5jdGlvbiBfX2lzQXJyYXkobykge1xuICByZXR1cm4gdHlwZW9mIG8gPT09ICdvYmplY3QnICYmIF9fb2JqVG9TdHIobykgPT09ICdbb2JqZWN0IEFycmF5XSc7XG59O1xuY2xvbmUuX19pc0FycmF5ID0gX19pc0FycmF5O1xuXG5mdW5jdGlvbiBfX2lzUmVnRXhwKG8pIHtcbiAgcmV0dXJuIHR5cGVvZiBvID09PSAnb2JqZWN0JyAmJiBfX29ialRvU3RyKG8pID09PSAnW29iamVjdCBSZWdFeHBdJztcbn07XG5jbG9uZS5fX2lzUmVnRXhwID0gX19pc1JlZ0V4cDtcblxuZnVuY3Rpb24gX19nZXRSZWdFeHBGbGFncyhyZSkge1xuICB2YXIgZmxhZ3MgPSAnJztcbiAgaWYgKHJlLmdsb2JhbCkgZmxhZ3MgKz0gJ2cnO1xuICBpZiAocmUuaWdub3JlQ2FzZSkgZmxhZ3MgKz0gJ2knO1xuICBpZiAocmUubXVsdGlsaW5lKSBmbGFncyArPSAnbSc7XG4gIHJldHVybiBmbGFncztcbn07XG5jbG9uZS5fX2dldFJlZ0V4cEZsYWdzID0gX19nZXRSZWdFeHBGbGFncztcblxucmV0dXJuIGNsb25lO1xufSkoKTtcblxuaWYgKHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzKSB7XG4gIG1vZHVsZS5leHBvcnRzID0gY2xvbmU7XG59XG5cbn0pLmNhbGwodGhpcyxyZXF1aXJlKFwiYnVmZmVyXCIpLkJ1ZmZlcilcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtjaGFyc2V0OnV0Zi04O2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYkltNXZaR1ZmYlc5a2RXeGxjeTkzYUdGMExXTm9ZVzVuWldRdmJtOWtaVjl0YjJSMWJHVnpMMk5zYjI1bEwyTnNiMjVsTG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lJN1FVRkJRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJJaXdpWm1sc1pTSTZJbWRsYm1WeVlYUmxaQzVxY3lJc0luTnZkWEpqWlZKdmIzUWlPaUlpTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lKMllYSWdZMnh2Ym1VZ1BTQW9ablZ1WTNScGIyNG9LU0I3WEc0bmRYTmxJSE4wY21samRDYzdYRzVjYmk4cUtseHVJQ29nUTJ4dmJtVnpJQ2hqYjNCcFpYTXBJR0Z1SUU5aWFtVmpkQ0IxYzJsdVp5QmtaV1Z3SUdOdmNIbHBibWN1WEc0Z0tseHVJQ29nVkdocGN5Qm1kVzVqZEdsdmJpQnpkWEJ3YjNKMGN5QmphWEpqZFd4aGNpQnlaV1psY21WdVkyVnpJR0o1SUdSbFptRjFiSFFzSUdKMWRDQnBaaUI1YjNVZ1lYSmxJR05sY25SaGFXNWNiaUFxSUhSb1pYSmxJR0Z5WlNCdWJ5QmphWEpqZFd4aGNpQnlaV1psY21WdVkyVnpJR2x1SUhsdmRYSWdiMkpxWldOMExDQjViM1VnWTJGdUlITmhkbVVnYzI5dFpTQkRVRlVnZEdsdFpWeHVJQ29nWW5rZ1kyRnNiR2x1WnlCamJHOXVaU2h2WW1vc0lHWmhiSE5sS1M1Y2JpQXFYRzRnS2lCRFlYVjBhVzl1T2lCcFppQmdZMmx5WTNWc1lYSmdJR2x6SUdaaGJITmxJR0Z1WkNCZ2NHRnlaVzUwWUNCamIyNTBZV2x1Y3lCamFYSmpkV3hoY2lCeVpXWmxjbVZ1WTJWekxGeHVJQ29nZVc5MWNpQndjbTluY21GdElHMWhlU0JsYm5SbGNpQmhiaUJwYm1acGJtbDBaU0JzYjI5d0lHRnVaQ0JqY21GemFDNWNiaUFxWEc0Z0tpQkFjR0Z5WVcwZ1lIQmhjbVZ1ZEdBZ0xTQjBhR1VnYjJKcVpXTjBJSFJ2SUdKbElHTnNiMjVsWkZ4dUlDb2dRSEJoY21GdElHQmphWEpqZFd4aGNtQWdMU0J6WlhRZ2RHOGdkSEoxWlNCcFppQjBhR1VnYjJKcVpXTjBJSFJ2SUdKbElHTnNiMjVsWkNCdFlYa2dZMjl1ZEdGcGJseHVJQ29nSUNBZ1kybHlZM1ZzWVhJZ2NtVm1aWEpsYm1ObGN5NGdLRzl3ZEdsdmJtRnNJQzBnZEhKMVpTQmllU0JrWldaaGRXeDBLVnh1SUNvZ1FIQmhjbUZ0SUdCa1pYQjBhR0FnTFNCelpYUWdkRzhnWVNCdWRXMWlaWElnYVdZZ2RHaGxJRzlpYW1WamRDQnBjeUJ2Ym14NUlIUnZJR0psSUdOc2IyNWxaQ0IwYjF4dUlDb2dJQ0FnWVNCd1lYSjBhV04xYkdGeUlHUmxjSFJvTGlBb2IzQjBhVzl1WVd3Z0xTQmtaV1poZFd4MGN5QjBieUJKYm1acGJtbDBlU2xjYmlBcUlFQndZWEpoYlNCZ2NISnZkRzkwZVhCbFlDQXRJSE5sZEhNZ2RHaGxJSEJ5YjNSdmRIbHdaU0IwYnlCaVpTQjFjMlZrSUhkb1pXNGdZMnh2Ym1sdVp5QmhiaUJ2WW1wbFkzUXVYRzRnS2lBZ0lDQW9iM0IwYVc5dVlXd2dMU0JrWldaaGRXeDBjeUIwYnlCd1lYSmxiblFnY0hKdmRHOTBlWEJsS1M1Y2Jpb3ZYRzVtZFc1amRHbHZiaUJqYkc5dVpTaHdZWEpsYm5Rc0lHTnBjbU4xYkdGeUxDQmtaWEIwYUN3Z2NISnZkRzkwZVhCbEtTQjdYRzRnSUhaaGNpQm1hV3gwWlhJN1hHNGdJR2xtSUNoMGVYQmxiMllnWTJseVkzVnNZWElnUFQwOUlDZHZZbXBsWTNRbktTQjdYRzRnSUNBZ1pHVndkR2dnUFNCamFYSmpkV3hoY2k1a1pYQjBhRHRjYmlBZ0lDQndjbTkwYjNSNWNHVWdQU0JqYVhKamRXeGhjaTV3Y205MGIzUjVjR1U3WEc0Z0lDQWdabWxzZEdWeUlEMGdZMmx5WTNWc1lYSXVabWxzZEdWeU8xeHVJQ0FnSUdOcGNtTjFiR0Z5SUQwZ1kybHlZM1ZzWVhJdVkybHlZM1ZzWVhKY2JpQWdmVnh1SUNBdkx5QnRZV2x1ZEdGcGJpQjBkMjhnWVhKeVlYbHpJR1p2Y2lCamFYSmpkV3hoY2lCeVpXWmxjbVZ1WTJWekxDQjNhR1Z5WlNCamIzSnlaWE53YjI1a2FXNW5JSEJoY21WdWRITmNiaUFnTHk4Z1lXNWtJR05vYVd4a2NtVnVJR2hoZG1VZ2RHaGxJSE5oYldVZ2FXNWtaWGhjYmlBZ2RtRnlJR0ZzYkZCaGNtVnVkSE1nUFNCYlhUdGNiaUFnZG1GeUlHRnNiRU5vYVd4a2NtVnVJRDBnVzEwN1hHNWNiaUFnZG1GeUlIVnpaVUoxWm1abGNpQTlJSFI1Y0dWdlppQkNkV1ptWlhJZ0lUMGdKM1Z1WkdWbWFXNWxaQ2M3WEc1Y2JpQWdhV1lnS0hSNWNHVnZaaUJqYVhKamRXeGhjaUE5UFNBbmRXNWtaV1pwYm1Wa0p5bGNiaUFnSUNCamFYSmpkV3hoY2lBOUlIUnlkV1U3WEc1Y2JpQWdhV1lnS0hSNWNHVnZaaUJrWlhCMGFDQTlQU0FuZFc1a1pXWnBibVZrSnlsY2JpQWdJQ0JrWlhCMGFDQTlJRWx1Wm1sdWFYUjVPMXh1WEc0Z0lDOHZJSEpsWTNWeWMyVWdkR2hwY3lCbWRXNWpkR2x2YmlCemJ5QjNaU0JrYjI0bmRDQnlaWE5sZENCaGJHeFFZWEpsYm5SeklHRnVaQ0JoYkd4RGFHbHNaSEpsYmx4dUlDQm1kVzVqZEdsdmJpQmZZMnh2Ym1Vb2NHRnlaVzUwTENCa1pYQjBhQ2tnZTF4dUlDQWdJQzh2SUdOc2IyNXBibWNnYm5Wc2JDQmhiSGRoZVhNZ2NtVjBkWEp1Y3lCdWRXeHNYRzRnSUNBZ2FXWWdLSEJoY21WdWRDQTlQVDBnYm5Wc2JDbGNiaUFnSUNBZ0lISmxkSFZ5YmlCdWRXeHNPMXh1WEc0Z0lDQWdhV1lnS0dSbGNIUm9JRDA5SURBcFhHNGdJQ0FnSUNCeVpYUjFjbTRnY0dGeVpXNTBPMXh1WEc0Z0lDQWdkbUZ5SUdOb2FXeGtPMXh1SUNBZ0lIWmhjaUJ3Y205MGJ6dGNiaUFnSUNCcFppQW9kSGx3Wlc5bUlIQmhjbVZ1ZENBaFBTQW5iMkpxWldOMEp5a2dlMXh1SUNBZ0lDQWdjbVYwZFhKdUlIQmhjbVZ1ZER0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0JwWmlBb1kyeHZibVV1WDE5cGMwRnljbUY1S0hCaGNtVnVkQ2twSUh0Y2JpQWdJQ0FnSUdOb2FXeGtJRDBnVzEwN1hHNGdJQ0FnZlNCbGJITmxJR2xtSUNoamJHOXVaUzVmWDJselVtVm5SWGh3S0hCaGNtVnVkQ2twSUh0Y2JpQWdJQ0FnSUdOb2FXeGtJRDBnYm1WM0lGSmxaMFY0Y0Nod1lYSmxiblF1YzI5MWNtTmxMQ0JmWDJkbGRGSmxaMFY0Y0Vac1lXZHpLSEJoY21WdWRDa3BPMXh1SUNBZ0lDQWdhV1lnS0hCaGNtVnVkQzVzWVhOMFNXNWtaWGdwSUdOb2FXeGtMbXhoYzNSSmJtUmxlQ0E5SUhCaGNtVnVkQzVzWVhOMFNXNWtaWGc3WEc0Z0lDQWdmU0JsYkhObElHbG1JQ2hqYkc5dVpTNWZYMmx6UkdGMFpTaHdZWEpsYm5RcEtTQjdYRzRnSUNBZ0lDQmphR2xzWkNBOUlHNWxkeUJFWVhSbEtIQmhjbVZ1ZEM1blpYUlVhVzFsS0NrcE8xeHVJQ0FnSUgwZ1pXeHpaU0JwWmlBb2RYTmxRblZtWm1WeUlDWW1JRUoxWm1abGNpNXBjMEoxWm1abGNpaHdZWEpsYm5RcEtTQjdYRzRnSUNBZ0lDQmphR2xzWkNBOUlHNWxkeUJDZFdabVpYSW9jR0Z5Wlc1MExteGxibWQwYUNrN1hHNGdJQ0FnSUNCd1lYSmxiblF1WTI5d2VTaGphR2xzWkNrN1hHNGdJQ0FnSUNCeVpYUjFjbTRnWTJocGJHUTdYRzRnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUdsbUlDaDBlWEJsYjJZZ2NISnZkRzkwZVhCbElEMDlJQ2QxYm1SbFptbHVaV1FuS1NCN1hHNGdJQ0FnSUNBZ0lIQnliM1J2SUQwZ1QySnFaV04wTG1kbGRGQnliM1J2ZEhsd1pVOW1LSEJoY21WdWRDazdYRzRnSUNBZ0lDQWdJR05vYVd4a0lEMGdUMkpxWldOMExtTnlaV0YwWlNod2NtOTBieWs3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdJQ0JsYkhObElIdGNiaUFnSUNBZ0lDQWdZMmhwYkdRZ1BTQlBZbXBsWTNRdVkzSmxZWFJsS0hCeWIzUnZkSGx3WlNrN1hHNGdJQ0FnSUNBZ0lIQnliM1J2SUQwZ2NISnZkRzkwZVhCbE8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUdsbUlDaGphWEpqZFd4aGNpa2dlMXh1SUNBZ0lDQWdkbUZ5SUdsdVpHVjRJRDBnWVd4c1VHRnlaVzUwY3k1cGJtUmxlRTltS0hCaGNtVnVkQ2s3WEc1Y2JpQWdJQ0FnSUdsbUlDaHBibVJsZUNBaFBTQXRNU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWVd4c1EyaHBiR1J5Wlc1YmFXNWtaWGhkTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJQ0FnWVd4c1VHRnlaVzUwY3k1d2RYTm9LSEJoY21WdWRDazdYRzRnSUNBZ0lDQmhiR3hEYUdsc1pISmxiaTV3ZFhOb0tHTm9hV3hrS1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0JtYjNJZ0tIWmhjaUJwSUdsdUlIQmhjbVZ1ZENrZ2UxeHVJQ0FnSUNBZ2RtRnlJR0YwZEhKek8xeHVJQ0FnSUNBZ2FXWWdLSEJ5YjNSdktTQjdYRzRnSUNBZ0lDQWdJR0YwZEhKeklEMGdUMkpxWldOMExtZGxkRTkzYmxCeWIzQmxjblI1UkdWelkzSnBjSFJ2Y2lod2NtOTBieXdnYVNrN1hHNGdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lHbG1JQ2hoZEhSeWN5QW1KaUJoZEhSeWN5NXpaWFFnUFQwZ2JuVnNiQ2tnZTF4dUlDQWdJQ0FnSUNCamIyNTBhVzUxWlR0Y2JpQWdJQ0FnSUgxY2JpQWdJQ0FnSUdOb2FXeGtXMmxkSUQwZ1gyTnNiMjVsS0hCaGNtVnVkRnRwWFN3Z1pHVndkR2dnTFNBeEtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnWTJocGJHUTdYRzRnSUgxY2JseHVJQ0J5WlhSMWNtNGdYMk5zYjI1bEtIQmhjbVZ1ZEN3Z1pHVndkR2dwTzF4dWZWeHVYRzR2S2lwY2JpQXFJRk5wYlhCc1pTQm1iR0YwSUdOc2IyNWxJSFZ6YVc1bklIQnliM1J2ZEhsd1pTd2dZV05qWlhCMGN5QnZibXg1SUc5aWFtVmpkSE1zSUhWelpXWjFiR3dnWm05eUlIQnliM0JsY25SNVhHNGdLaUJ2ZG1WeWNtbGtaU0J2YmlCR1RFRlVJR052Ym1acFozVnlZWFJwYjI0Z2IySnFaV04wSUNodWJ5QnVaWE4wWldRZ2NISnZjSE1wTGx4dUlDcGNiaUFxSUZWVFJTQlhTVlJJSUVOQlZWUkpUMDRoSUZSb2FYTWdiV0Y1SUc1dmRDQmlaV2hoZG1VZ1lYTWdlVzkxSUhkcGMyZ2dhV1lnZVc5MUlHUnZJRzV2ZENCcmJtOTNJR2h2ZHlCMGFHbHpYRzRnS2lCM2IzSnJjeTVjYmlBcUwxeHVZMnh2Ym1VdVkyeHZibVZRY205MGIzUjVjR1VnUFNCbWRXNWpkR2x2YmlCamJHOXVaVkJ5YjNSdmRIbHdaU2h3WVhKbGJuUXBJSHRjYmlBZ2FXWWdLSEJoY21WdWRDQTlQVDBnYm5Wc2JDbGNiaUFnSUNCeVpYUjFjbTRnYm5Wc2JEdGNibHh1SUNCMllYSWdZeUE5SUdaMWJtTjBhVzl1SUNncElIdDlPMXh1SUNCakxuQnliM1J2ZEhsd1pTQTlJSEJoY21WdWREdGNiaUFnY21WMGRYSnVJRzVsZHlCaktDazdYRzU5TzF4dVhHNHZMeUJ3Y21sMllYUmxJSFYwYVd4cGRIa2dablZ1WTNScGIyNXpYRzVjYm1aMWJtTjBhVzl1SUY5ZmIySnFWRzlUZEhJb2J5a2dlMXh1SUNCeVpYUjFjbTRnVDJKcVpXTjBMbkJ5YjNSdmRIbHdaUzUwYjFOMGNtbHVaeTVqWVd4c0tHOHBPMXh1ZlR0Y2JtTnNiMjVsTGw5ZmIySnFWRzlUZEhJZ1BTQmZYMjlpYWxSdlUzUnlPMXh1WEc1bWRXNWpkR2x2YmlCZlgybHpSR0YwWlNodktTQjdYRzRnSUhKbGRIVnliaUIwZVhCbGIyWWdieUE5UFQwZ0oyOWlhbVZqZENjZ0ppWWdYMTl2WW1wVWIxTjBjaWh2S1NBOVBUMGdKMXR2WW1wbFkzUWdSR0YwWlYwbk8xeHVmVHRjYm1Oc2IyNWxMbDlmYVhORVlYUmxJRDBnWDE5cGMwUmhkR1U3WEc1Y2JtWjFibU4wYVc5dUlGOWZhWE5CY25KaGVTaHZLU0I3WEc0Z0lISmxkSFZ5YmlCMGVYQmxiMllnYnlBOVBUMGdKMjlpYW1WamRDY2dKaVlnWDE5dlltcFViMU4wY2lodktTQTlQVDBnSjF0dlltcGxZM1FnUVhKeVlYbGRKenRjYm4wN1hHNWpiRzl1WlM1ZlgybHpRWEp5WVhrZ1BTQmZYMmx6UVhKeVlYazdYRzVjYm1aMWJtTjBhVzl1SUY5ZmFYTlNaV2RGZUhBb2J5a2dlMXh1SUNCeVpYUjFjbTRnZEhsd1pXOW1JRzhnUFQwOUlDZHZZbXBsWTNRbklDWW1JRjlmYjJKcVZHOVRkSElvYnlrZ1BUMDlJQ2RiYjJKcVpXTjBJRkpsWjBWNGNGMG5PMXh1ZlR0Y2JtTnNiMjVsTGw5ZmFYTlNaV2RGZUhBZ1BTQmZYMmx6VW1WblJYaHdPMXh1WEc1bWRXNWpkR2x2YmlCZlgyZGxkRkpsWjBWNGNFWnNZV2R6S0hKbEtTQjdYRzRnSUhaaGNpQm1iR0ZuY3lBOUlDY25PMXh1SUNCcFppQW9jbVV1WjJ4dlltRnNLU0JtYkdGbmN5QXJQU0FuWnljN1hHNGdJR2xtSUNoeVpTNXBaMjV2Y21WRFlYTmxLU0JtYkdGbmN5QXJQU0FuYVNjN1hHNGdJR2xtSUNoeVpTNXRkV3gwYVd4cGJtVXBJR1pzWVdkeklDczlJQ2R0Snp0Y2JpQWdjbVYwZFhKdUlHWnNZV2R6TzF4dWZUdGNibU5zYjI1bExsOWZaMlYwVW1WblJYaHdSbXhoWjNNZ1BTQmZYMmRsZEZKbFowVjRjRVpzWVdkek8xeHVYRzV5WlhSMWNtNGdZMnh2Ym1VN1hHNTlLU2dwTzF4dVhHNXBaaUFvZEhsd1pXOW1JRzF2WkhWc1pTQTlQVDBnSjI5aWFtVmpkQ2NnSmlZZ2JXOWtkV3hsTG1WNGNHOXlkSE1wSUh0Y2JpQWdiVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmpiRzl1WlR0Y2JuMWNiaUpkZlE9PSIsImZ1bmN0aW9uIGNvbXBhcmUoYSwgYiwgdmlzaXRlZCl7XG4gICAgdmFyIGFUeXBlID0gdHlwZW9mIGE7XG5cbiAgICBpZihhVHlwZSAhPT0gdHlwZW9mIGIpe1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYoYSA9PSBudWxsIHx8IGIgPT0gbnVsbCB8fCAhKGFUeXBlID09PSAnb2JqZWN0JyB8fCBhVHlwZSA9PT0gJ2Z1bmN0aW9uJykpe1xuICAgICAgICBpZihhVHlwZSA9PT0gJ251bWJlcicgJiYgaXNOYU4oYSkgJiYgaXNOYU4oYikpe1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYSA9PT0gYjtcbiAgICB9XG5cbiAgICBpZihBcnJheS5pc0FycmF5KGEpICE9PSBBcnJheS5pc0FycmF5KGIpKXtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHZhciBhS2V5cyA9IE9iamVjdC5rZXlzKGEpLFxuICAgICAgICBiS2V5cyA9IE9iamVjdC5rZXlzKGIpO1xuXG4gICAgaWYoYUtleXMubGVuZ3RoICE9PSBiS2V5cy5sZW5ndGgpe1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgdmFyIGVxdWFsID0gdHJ1ZTtcblxuICAgIGlmKCF2aXNpdGVkKXtcbiAgICAgICAgdmlzaXRlZCA9IG5ldyBTZXQoKTtcbiAgICB9XG5cbiAgICBhS2V5cy5mb3JFYWNoKGZ1bmN0aW9uKGtleSl7XG4gICAgICAgIGlmKCEoa2V5IGluIGIpKXtcbiAgICAgICAgICAgIGVxdWFsID0gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYodmlzaXRlZC5oYXMoYVtrZXldKSl7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmlzaXRlZC5hZGQoYVtrZXldKTtcbiAgICAgICAgaWYoIWNvbXBhcmUoYVtrZXldLCBiW2tleV0sIHZpc2l0ZWQpKXtcbiAgICAgICAgICAgIGVxdWFsID0gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiBlcXVhbDtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oYSwgYil7XG4gICAgcmV0dXJuIGNvbXBhcmUoYSwgYik7XG59IiwidmFyIFdoYXRDaGFuZ2VkID0gcmVxdWlyZSgnd2hhdC1jaGFuZ2VkJyksXG4gICAgc2FtZSA9IHJlcXVpcmUoJ3NhbWUtdmFsdWUnKSxcbiAgICBmaXJtZXIgPSByZXF1aXJlKCcuL2Zpcm1lcicpLFxuICAgIGZ1bmN0aW9uRW1pdHRlciA9IHJlcXVpcmUoJ2Z1bmN0aW9uLWVtaXR0ZXInKSxcbiAgICBzZXRQcm90b3R5cGVPZiA9IHJlcXVpcmUoJ3NldHByb3RvdHlwZW9mJyk7XG5cbnZhciBwcm9wZXJ0eVByb3RvID0gT2JqZWN0LmNyZWF0ZShmdW5jdGlvbkVtaXR0ZXIpO1xuXG5wcm9wZXJ0eVByb3RvLl9mYXN0bl9wcm9wZXJ0eSA9IHRydWU7XG5wcm9wZXJ0eVByb3RvLl9maXJtID0gMTtcblxuZnVuY3Rpb24gcHJvcGVydHlUZW1wbGF0ZSh2YWx1ZSl7XG4gICAgaWYoIWFyZ3VtZW50cy5sZW5ndGgpe1xuICAgICAgICByZXR1cm4gdGhpcy5iaW5kaW5nICYmIHRoaXMuYmluZGluZygpIHx8IHRoaXMucHJvcGVydHkuX3ZhbHVlO1xuICAgIH1cblxuICAgIGlmKCF0aGlzLmRlc3Ryb3llZCl7XG4gICAgICAgIGlmKHRoaXMuYmluZGluZyl7XG4gICAgICAgICAgICB0aGlzLmJpbmRpbmcodmFsdWUpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJvcGVydHk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnZhbHVlVXBkYXRlKHZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5wcm9wZXJ0eTtcbn1cblxuZnVuY3Rpb24gY2hhbmdlQ2hlY2tlcihjdXJyZW50LCBjaGFuZ2VzKXtcbiAgICBpZihjaGFuZ2VzKXtcbiAgICAgICAgdmFyIGNoYW5nZXMgPSBuZXcgV2hhdENoYW5nZWQoY3VycmVudCwgY2hhbmdlcyk7XG5cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlKXtcbiAgICAgICAgICAgIHJldHVybiBPYmplY3Qua2V5cyhjaGFuZ2VzLnVwZGF0ZSh2YWx1ZSkpLmxlbmd0aCA+IDA7XG4gICAgICAgIH07XG4gICAgfWVsc2V7XG4gICAgICAgIHZhciBsYXN0VmFsdWUgPSBjdXJyZW50O1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24obmV3VmFsdWUpe1xuICAgICAgICAgICAgaWYoIXNhbWUobGFzdFZhbHVlLCBuZXdWYWx1ZSkpe1xuICAgICAgICAgICAgICAgIGxhc3RWYWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cbn1cblxuXG5mdW5jdGlvbiBwcm9wZXJ0eUJpbmRpbmcobmV3QmluZGluZyl7XG4gICAgaWYoIWFyZ3VtZW50cy5sZW5ndGgpe1xuICAgICAgICByZXR1cm4gdGhpcy5iaW5kaW5nO1xuICAgIH1cblxuICAgIGlmKCF0aGlzLmZhc3RuLmlzQmluZGluZyhuZXdCaW5kaW5nKSl7XG4gICAgICAgIG5ld0JpbmRpbmcgPSB0aGlzLmZhc3RuLmJpbmRpbmcobmV3QmluZGluZyk7XG4gICAgfVxuXG4gICAgaWYobmV3QmluZGluZyA9PT0gdGhpcy5iaW5kaW5nKXtcbiAgICAgICAgcmV0dXJuIHRoaXMucHJvcGVydHk7XG4gICAgfVxuXG4gICAgaWYodGhpcy5iaW5kaW5nKXtcbiAgICAgICAgdGhpcy5iaW5kaW5nLnJlbW92ZUxpc3RlbmVyKCdjaGFuZ2UnLCB0aGlzLnZhbHVlVXBkYXRlKTtcbiAgICB9XG5cbiAgICB0aGlzLmJpbmRpbmcgPSBuZXdCaW5kaW5nO1xuXG4gICAgaWYodGhpcy5tb2RlbCl7XG4gICAgICAgIHRoaXMucHJvcGVydHkuYXR0YWNoKHRoaXMubW9kZWwsIHRoaXMucHJvcGVydHkuX2Zpcm0pO1xuICAgIH1cblxuICAgIHRoaXMuYmluZGluZy5vbignY2hhbmdlJywgdGhpcy52YWx1ZVVwZGF0ZSk7XG4gICAgdGhpcy52YWx1ZVVwZGF0ZSh0aGlzLmJpbmRpbmcoKSk7XG5cbiAgICByZXR1cm4gdGhpcy5wcm9wZXJ0eTtcbn07XG5cbmZ1bmN0aW9uIGF0dGFjaFByb3BlcnR5KG9iamVjdCwgZmlybSl7XG4gICAgaWYoZmlybWVyKHRoaXMucHJvcGVydHksIGZpcm0pKXtcbiAgICAgICAgcmV0dXJuIHRoaXMucHJvcGVydHk7XG4gICAgfVxuXG4gICAgdGhpcy5wcm9wZXJ0eS5fZmlybSA9IGZpcm07XG5cbiAgICBpZighKG9iamVjdCBpbnN0YW5jZW9mIE9iamVjdCkpe1xuICAgICAgICBvYmplY3QgPSB7fTtcbiAgICB9XG5cbiAgICBpZih0aGlzLmJpbmRpbmcpe1xuICAgICAgICB0aGlzLm1vZGVsID0gb2JqZWN0O1xuICAgICAgICB0aGlzLmJpbmRpbmcuYXR0YWNoKG9iamVjdCwgMSk7XG4gICAgfVxuXG4gICAgaWYodGhpcy5wcm9wZXJ0eS5fZXZlbnRzICYmICdhdHRhY2gnIGluIHRoaXMucHJvcGVydHkuX2V2ZW50cyl7XG4gICAgICAgIHRoaXMucHJvcGVydHkuZW1pdCgnYXR0YWNoJywgb2JqZWN0LCAxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5wcm9wZXJ0eTtcbn07XG5cbmZ1bmN0aW9uIGRldGFjaFByb3BlcnR5KGZpcm0pe1xuICAgIGlmKGZpcm1lcih0aGlzLnByb3BlcnR5LCBmaXJtKSl7XG4gICAgICAgIHJldHVybiB0aGlzLnByb3BlcnR5O1xuICAgIH1cblxuICAgIGlmKHRoaXMuYmluZGluZyl7XG4gICAgICAgIHRoaXMuYmluZGluZy5yZW1vdmVMaXN0ZW5lcignY2hhbmdlJywgdGhpcy52YWx1ZVVwZGF0ZSk7XG4gICAgICAgIHRoaXMuYmluZGluZy5kZXRhY2goMSk7XG4gICAgICAgIHRoaXMubW9kZWwgPSBudWxsO1xuICAgIH1cblxuICAgIGlmKHRoaXMucHJvcGVydHkuX2V2ZW50cyAmJiAnZGV0YWNoJyBpbiB0aGlzLnByb3BlcnR5Ll9ldmVudHMpe1xuICAgICAgICB0aGlzLnByb3BlcnR5LmVtaXQoJ2RldGFjaCcsIDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnByb3BlcnR5O1xufTtcblxuZnVuY3Rpb24gdXBkYXRlUHJvcGVydHkoKXtcbiAgICBpZighdGhpcy5kZXN0cm95ZWQpe1xuXG4gICAgICAgIGlmKHRoaXMucHJvcGVydHkuX3VwZGF0ZSl7XG4gICAgICAgICAgICB0aGlzLnByb3BlcnR5Ll91cGRhdGUodGhpcy5wcm9wZXJ0eS5fdmFsdWUsIHRoaXMucHJvcGVydHkpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5wcm9wZXJ0eS5lbWl0KCd1cGRhdGUnLCB0aGlzLnByb3BlcnR5Ll92YWx1ZSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnByb3BlcnR5O1xufTtcblxuZnVuY3Rpb24gcHJvcGVydHlVcGRhdGVyKGZuKXtcbiAgICBpZighYXJndW1lbnRzLmxlbmd0aCl7XG4gICAgICAgIHJldHVybiB0aGlzLnByb3BlcnR5Ll91cGRhdGU7XG4gICAgfVxuICAgIHRoaXMucHJvcGVydHkuX3VwZGF0ZSA9IGZuO1xuICAgIHJldHVybiB0aGlzLnByb3BlcnR5O1xufTtcblxuZnVuY3Rpb24gZGVzdHJveVByb3BlcnR5KCl7XG4gICAgaWYoIXRoaXMuZGVzdHJveWVkKXtcbiAgICAgICAgdGhpcy5kZXN0cm95ZWQgPSB0cnVlO1xuXG4gICAgICAgIHRoaXMucHJvcGVydHlcbiAgICAgICAgICAgIC5yZW1vdmVBbGxMaXN0ZW5lcnMoJ2NoYW5nZScpXG4gICAgICAgICAgICAucmVtb3ZlQWxsTGlzdGVuZXJzKCd1cGRhdGUnKVxuICAgICAgICAgICAgLnJlbW92ZUFsbExpc3RlbmVycygnYXR0YWNoJyk7XG5cbiAgICAgICAgdGhpcy5wcm9wZXJ0eS5lbWl0KCdkZXN0cm95Jyk7XG4gICAgICAgIHRoaXMucHJvcGVydHkuZGV0YWNoKCk7XG4gICAgICAgIGlmKHRoaXMuYmluZGluZyl7XG4gICAgICAgICAgICB0aGlzLmJpbmRpbmcuZGVzdHJveSh0cnVlKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5wcm9wZXJ0eTtcbn07XG5cbmZ1bmN0aW9uIHByb3BlcnR5RGVzdHJveWVkKCl7XG4gICAgcmV0dXJuIHRoaXMuZGVzdHJveWVkO1xufTtcblxuZnVuY3Rpb24gYWRkUHJvcGVydHlUbyhjb21wb25lbnQsIGtleSl7XG4gICAgY29tcG9uZW50LnNldFByb3BlcnR5KGtleSwgdGhpcy5wcm9wZXJ0eSk7XG5cbiAgICByZXR1cm4gdGhpcy5wcm9wZXJ0eTtcbn07XG5cbmZ1bmN0aW9uIGNyZWF0ZVByb3BlcnR5KGN1cnJlbnRWYWx1ZSwgY2hhbmdlcywgdXBkYXRlcil7XG4gICAgaWYodHlwZW9mIGNoYW5nZXMgPT09ICdmdW5jdGlvbicpe1xuICAgICAgICB1cGRhdGVyID0gY2hhbmdlcztcbiAgICAgICAgY2hhbmdlcyA9IG51bGw7XG4gICAgfVxuXG4gICAgdmFyIHByb3BlcnR5U2NvcGUgPVxuICAgICAgICBwcm9wZXJ0eSA9IHByb3BlcnR5VGVtcGxhdGUuYmluZChwcm9wZXJ0eVNjb3BlKVxuICAgICAgICBwcm9wZXJ0eVNjb3BlID0ge1xuICAgICAgICAgICAgZmFzdG46IHRoaXMsXG4gICAgICAgICAgICBoYXNDaGFuZ2VkOiBjaGFuZ2VDaGVja2VyKGN1cnJlbnRWYWx1ZSwgY2hhbmdlcyksXG4gICAgICAgICAgICB2YWx1ZVVwZGF0ZTogZnVuY3Rpb24odmFsdWUpe1xuICAgICAgICAgICAgICAgIHByb3BlcnR5Ll92YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgIGlmKCFwcm9wZXJ0eVNjb3BlLmhhc0NoYW5nZWQodmFsdWUpKXtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwcm9wZXJ0eS5lbWl0KCdjaGFuZ2UnLCBwcm9wZXJ0eS5fdmFsdWUpO1xuICAgICAgICAgICAgICAgIHByb3BlcnR5LnVwZGF0ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydHlTY29wZS5wcm9wZXJ0eSA9IHByb3BlcnR5VGVtcGxhdGUuYmluZChwcm9wZXJ0eVNjb3BlKTtcblxuICAgIHByb3BlcnR5Ll92YWx1ZSA9IGN1cnJlbnRWYWx1ZTtcbiAgICBwcm9wZXJ0eS5fdXBkYXRlID0gdXBkYXRlcjtcblxuICAgIHNldFByb3RvdHlwZU9mKHByb3BlcnR5LCBwcm9wZXJ0eVByb3RvKTtcblxuICAgIHByb3BlcnR5LmJpbmRpbmcgPSBwcm9wZXJ0eUJpbmRpbmcuYmluZChwcm9wZXJ0eVNjb3BlKTtcbiAgICBwcm9wZXJ0eS5hdHRhY2ggPSBhdHRhY2hQcm9wZXJ0eS5iaW5kKHByb3BlcnR5U2NvcGUpO1xuICAgIHByb3BlcnR5LmRldGFjaCA9IGRldGFjaFByb3BlcnR5LmJpbmQocHJvcGVydHlTY29wZSk7XG4gICAgcHJvcGVydHkudXBkYXRlID0gdXBkYXRlUHJvcGVydHkuYmluZChwcm9wZXJ0eVNjb3BlKTtcbiAgICBwcm9wZXJ0eS51cGRhdGVyID0gcHJvcGVydHlVcGRhdGVyLmJpbmQocHJvcGVydHlTY29wZSk7XG4gICAgcHJvcGVydHkuZGVzdHJveSA9IGRlc3Ryb3lQcm9wZXJ0eS5iaW5kKHByb3BlcnR5U2NvcGUpO1xuICAgIHByb3BlcnR5LmRlc3Ryb3llZCA9IHByb3BlcnR5RGVzdHJveWVkLmJpbmQocHJvcGVydHlTY29wZSk7XG4gICAgcHJvcGVydHkuYWRkVG8gPSBhZGRQcm9wZXJ0eVRvLmJpbmQocHJvcGVydHlTY29wZSk7XG5cbiAgICByZXR1cm4gcHJvcGVydHk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVByb3BlcnR5OyIsInZhciBjcmVhdGVQcm9wZXJ0eSA9IHJlcXVpcmUoJy4vcHJvcGVydHknKSxcbiAgICBjcmVhdGVCaW5kaW5nID0gcmVxdWlyZSgnLi9iaW5kaW5nJyksXG4gICAgQmFzZUNvbXBvbmVudCA9IHJlcXVpcmUoJy4vYmFzZUNvbXBvbmVudCcpLFxuICAgIGNyZWwgPSByZXF1aXJlKCdjcmVsJyksXG4gICAgRW50aSA9IHJlcXVpcmUoJ2VudGknKSxcbiAgICBvYmplY3RBc3NpZ24gPSByZXF1aXJlKCdvYmplY3QtYXNzaWduJyksXG4gICAgaXMgPSByZXF1aXJlKCcuL2lzJyk7XG5cbmZ1bmN0aW9uIGluZmxhdGVQcm9wZXJ0aWVzKGNvbXBvbmVudCwgc2V0dGluZ3Mpe1xuICAgIGZvcih2YXIga2V5IGluIHNldHRpbmdzKXtcbiAgICAgICAgdmFyIHNldHRpbmcgPSBzZXR0aW5nc1trZXldLFxuICAgICAgICAgICAgcHJvcGVydHkgPSBjb21wb25lbnRba2V5XTtcblxuICAgICAgICBpZihpcy5wcm9wZXJ0eShzZXR0aW5nc1trZXldKSl7XG5cbiAgICAgICAgICAgIGlmKGlzLnByb3BlcnR5KHByb3BlcnR5KSl7XG4gICAgICAgICAgICAgICAgcHJvcGVydHkuZGVzdHJveSgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzZXR0aW5nLmFkZFRvKGNvbXBvbmVudCwga2V5KTtcblxuICAgICAgICB9ZWxzZSBpZihpcy5wcm9wZXJ0eShwcm9wZXJ0eSkpe1xuXG4gICAgICAgICAgICBpZihpcy5iaW5kaW5nKHNldHRpbmcpKXtcbiAgICAgICAgICAgICAgICBwcm9wZXJ0eS5iaW5kaW5nKHNldHRpbmcpO1xuICAgICAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICAgICAgcHJvcGVydHkoc2V0dGluZyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHByb3BlcnR5LmFkZFRvKGNvbXBvbmVudCwga2V5KTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVFeHBlY3RlZENvbXBvbmVudHMoY29tcG9uZW50cywgY29tcG9uZW50TmFtZSwgZXhwZWN0ZWRDb21wb25lbnRzKXtcbiAgICBleHBlY3RlZENvbXBvbmVudHMgPSBleHBlY3RlZENvbXBvbmVudHMuZmlsdGVyKGZ1bmN0aW9uKGNvbXBvbmVudE5hbWUpe1xuICAgICAgICByZXR1cm4gIShjb21wb25lbnROYW1lIGluIGNvbXBvbmVudHMpO1xuICAgIH0pO1xuXG4gICAgaWYoZXhwZWN0ZWRDb21wb25lbnRzLmxlbmd0aCl7XG4gICAgICAgIGNvbnNvbGUud2FybihbXG4gICAgICAgICAgICAnZmFzdG4oXCInICsgY29tcG9uZW50TmFtZSArICdcIikgdXNlcyBzb21lIGNvbXBvbmVudHMgdGhhdCBoYXZlIG5vdCBiZWVuIHJlZ2lzdGVyZWQgd2l0aCBmYXN0bicsXG4gICAgICAgICAgICAnRXhwZWN0ZWQgY29ucG9uZW50IGNvbnN0cnVjdG9yczogJyArIGV4cGVjdGVkQ29tcG9uZW50cy5qb2luKCcsICcpXG4gICAgICAgIF0uam9pbignXFxuXFxuJykpO1xuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihjb21wb25lbnRzLCBkZWJ1Zyl7XG5cbiAgICBpZighY29tcG9uZW50cyB8fCB0eXBlb2YgY29tcG9uZW50cyAhPT0gJ29iamVjdCcpe1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Zhc3RuIG11c3QgYmUgaW5pdGlhbGlzZWQgd2l0aCBhIGNvbXBvbmVudHMgb2JqZWN0Jyk7XG4gICAgfVxuXG4gICAgY29tcG9uZW50cy5fY29udGFpbmVyID0gY29tcG9uZW50cy5fY29udGFpbmVyIHx8IHJlcXVpcmUoJy4vY29udGFpbmVyQ29tcG9uZW50Jyk7XG5cbiAgICBmdW5jdGlvbiBmYXN0bih0eXBlKXtcblxuICAgICAgICB2YXIgYXJncyA9IFtdO1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgICAgIGFyZ3NbaV0gPSBhcmd1bWVudHNbaV07XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc2V0dGluZ3MgPSBhcmdzWzFdLFxuICAgICAgICAgICAgY2hpbGRyZW5JbmRleCA9IDIsXG4gICAgICAgICAgICBzZXR0aW5nc0NoaWxkID0gZmFzdG4udG9Db21wb25lbnQoYXJnc1sxXSk7XG5cbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheShhcmdzWzFdKSB8fCBzZXR0aW5nc0NoaWxkIHx8ICFhcmdzWzFdKXtcbiAgICAgICAgICAgIGFyZ3NbMV0gPSBzZXR0aW5nc0NoaWxkIHx8IGFyZ3NbMV07XG4gICAgICAgICAgICBjaGlsZHJlbkluZGV4LS07XG4gICAgICAgICAgICBzZXR0aW5ncyA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBzZXR0aW5ncyA9IG9iamVjdEFzc2lnbih7fSwgc2V0dGluZ3MgfHwge30pO1xuXG4gICAgICAgIHZhciB0eXBlcyA9IHR5cGVvZiB0eXBlID09PSAnc3RyaW5nJyA/IHR5cGUuc3BsaXQoJzonKSA6IEFycmF5LmlzQXJyYXkodHlwZSkgPyB0eXBlIDogW3R5cGVdLFxuICAgICAgICAgICAgYmFzZVR5cGUsXG4gICAgICAgICAgICBjaGlsZHJlbiA9IGFyZ3Muc2xpY2UoY2hpbGRyZW5JbmRleCksXG4gICAgICAgICAgICBjb21wb25lbnQgPSBmYXN0bi5iYXNlKHR5cGUsIHNldHRpbmdzLCBjaGlsZHJlbik7XG5cbiAgICAgICAgd2hpbGUoYmFzZVR5cGUgPSB0eXBlcy5zaGlmdCgpKXtcbiAgICAgICAgICAgIGNvbXBvbmVudC5leHRlbmQoYmFzZVR5cGUsIHNldHRpbmdzLCBjaGlsZHJlbik7XG4gICAgICAgIH1cblxuICAgICAgICBjb21wb25lbnQuX3Byb3BlcnRpZXMgPSB7fTtcblxuICAgICAgICBpbmZsYXRlUHJvcGVydGllcyhjb21wb25lbnQsIHNldHRpbmdzKTtcblxuICAgICAgICByZXR1cm4gY29tcG9uZW50O1xuICAgIH1cblxuICAgIGZhc3RuLnRvQ29tcG9uZW50ID0gZnVuY3Rpb24oY29tcG9uZW50KXtcbiAgICAgICAgaWYoY29tcG9uZW50ID09IG51bGwpe1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmKGlzLmNvbXBvbmVudChjb21wb25lbnQpKXtcbiAgICAgICAgICAgIHJldHVybiBjb21wb25lbnQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYodHlwZW9mIGNvbXBvbmVudCAhPT0gJ29iamVjdCcgfHwgY29tcG9uZW50IGluc3RhbmNlb2YgRGF0ZSl7XG4gICAgICAgICAgICByZXR1cm4gZmFzdG4oJ3RleHQnLCB7YXV0bzogdHJ1ZX0sIGNvbXBvbmVudCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoY3JlbC5pc0VsZW1lbnQoY29tcG9uZW50KSl7XG4gICAgICAgICAgICByZXR1cm4gZmFzdG4oY29tcG9uZW50KTtcbiAgICAgICAgfVxuICAgICAgICBpZihjcmVsLmlzTm9kZShjb21wb25lbnQpKXtcbiAgICAgICAgICAgIHJldHVybiBmYXN0bigndGV4dCcsIHthdXRvOiB0cnVlfSwgY29tcG9uZW50LnRleHRDb250ZW50KTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBmYXN0bi5kZWJ1ZyA9IGRlYnVnO1xuICAgIGZhc3RuLnByb3BlcnR5ID0gY3JlYXRlUHJvcGVydHkuYmluZChmYXN0bik7XG4gICAgZmFzdG4uYmluZGluZyA9IGNyZWF0ZUJpbmRpbmcoZmFzdG4pO1xuICAgIGZhc3RuLmlzQ29tcG9uZW50ID0gaXMuY29tcG9uZW50O1xuICAgIGZhc3RuLmlzQmluZGluZyA9IGlzLmJpbmRpbmc7XG4gICAgZmFzdG4uaXNEZWZhdWx0QmluZGluZyA9IGlzLmRlZmF1bHRCaW5kaW5nO1xuICAgIGZhc3RuLmlzQmluZGluZ09iamVjdCA9IGlzLmJpbmRpbmdPYmplY3Q7XG4gICAgZmFzdG4uaXNQcm9wZXJ0eSA9IGlzLnByb3BlcnR5O1xuICAgIGZhc3RuLmNvbXBvbmVudHMgPSBjb21wb25lbnRzO1xuICAgIGZhc3RuLk1vZGVsID0gRW50aTtcbiAgICBmYXN0bi5pc01vZGVsID0gRW50aS5pc0VudGkuYmluZChFbnRpKTtcblxuICAgIGZhc3RuLmJhc2UgPSBmdW5jdGlvbih0eXBlLCBzZXR0aW5ncywgY2hpbGRyZW4pe1xuICAgICAgICByZXR1cm4gbmV3IEJhc2VDb21wb25lbnQoZmFzdG4sIHR5cGUsIHNldHRpbmdzLCBjaGlsZHJlbik7XG4gICAgfTtcblxuICAgIGZvcih2YXIga2V5IGluIGNvbXBvbmVudHMpe1xuICAgICAgICB2YXIgY29tcG9uZW50Q29uc3RydWN0b3IgPSBjb21wb25lbnRzW2tleV07XG5cbiAgICAgICAgaWYoY29tcG9uZW50Q29uc3RydWN0b3IuZXhwZWN0ZWRDb21wb25lbnRzKXtcbiAgICAgICAgICAgIHZhbGlkYXRlRXhwZWN0ZWRDb21wb25lbnRzKGNvbXBvbmVudHMsIGtleSwgY29tcG9uZW50Q29uc3RydWN0b3IuZXhwZWN0ZWRDb21wb25lbnRzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYXN0bjtcbn07Il19 | |
require=(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})({"fastn/textComponent":[function(require,module,exports){ | |
function updateText(){ | |
if(!this.element){ | |
return; | |
} | |
var value = this.text(); | |
this.element.textContent = (value == null ? '' : value); | |
} | |
function autoRender(content){ | |
this.element = document.createTextNode(content); | |
} | |
function autoText(text, fastn, content) { | |
text.render = autoRender.bind(text, content); | |
return text; | |
} | |
function render(){ | |
this.element = this.createTextNode(this.text()); | |
this.emit('render'); | |
}; | |
function textComponent(fastn, component, type, settings, children){ | |
if(settings.auto){ | |
delete settings.auto; | |
if(!fastn.isBinding(children[0])){ | |
return autoText(component, fastn, children[0]); | |
} | |
settings.text = children.pop(); | |
} | |
component.createTextNode = textComponent.createTextNode; | |
component.render = render.bind(component); | |
component.setProperty('text', fastn.property('', updateText.bind(component))); | |
return component; | |
} | |
textComponent.createTextNode = function(text){ | |
return document.createTextNode(text); | |
}; | |
module.exports = textComponent; | |
},{}]},{},[]) | |
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsInRleHRDb21wb25lbnQuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsImZ1bmN0aW9uIHVwZGF0ZVRleHQoKXtcbiAgICBpZighdGhpcy5lbGVtZW50KXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciB2YWx1ZSA9IHRoaXMudGV4dCgpO1xuXG4gICAgdGhpcy5lbGVtZW50LnRleHRDb250ZW50ID0gKHZhbHVlID09IG51bGwgPyAnJyA6IHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gYXV0b1JlbmRlcihjb250ZW50KXtcbiAgICB0aGlzLmVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShjb250ZW50KTtcbn1cblxuZnVuY3Rpb24gYXV0b1RleHQodGV4dCwgZmFzdG4sIGNvbnRlbnQpIHtcbiAgICB0ZXh0LnJlbmRlciA9IGF1dG9SZW5kZXIuYmluZCh0ZXh0LCBjb250ZW50KTtcblxuICAgIHJldHVybiB0ZXh0O1xufVxuXG5mdW5jdGlvbiByZW5kZXIoKXtcbiAgICB0aGlzLmVsZW1lbnQgPSB0aGlzLmNyZWF0ZVRleHROb2RlKHRoaXMudGV4dCgpKTtcbiAgICB0aGlzLmVtaXQoJ3JlbmRlcicpO1xufTtcblxuZnVuY3Rpb24gdGV4dENvbXBvbmVudChmYXN0biwgY29tcG9uZW50LCB0eXBlLCBzZXR0aW5ncywgY2hpbGRyZW4pe1xuICAgIGlmKHNldHRpbmdzLmF1dG8pe1xuICAgICAgICBkZWxldGUgc2V0dGluZ3MuYXV0bztcbiAgICAgICAgaWYoIWZhc3RuLmlzQmluZGluZyhjaGlsZHJlblswXSkpe1xuICAgICAgICAgICAgcmV0dXJuIGF1dG9UZXh0KGNvbXBvbmVudCwgZmFzdG4sIGNoaWxkcmVuWzBdKTtcbiAgICAgICAgfVxuICAgICAgICBzZXR0aW5ncy50ZXh0ID0gY2hpbGRyZW4ucG9wKCk7XG4gICAgfVxuXG4gICAgY29tcG9uZW50LmNyZWF0ZVRleHROb2RlID0gdGV4dENvbXBvbmVudC5jcmVhdGVUZXh0Tm9kZTtcbiAgICBjb21wb25lbnQucmVuZGVyID0gcmVuZGVyLmJpbmQoY29tcG9uZW50KTtcblxuICAgIGNvbXBvbmVudC5zZXRQcm9wZXJ0eSgndGV4dCcsIGZhc3RuLnByb3BlcnR5KCcnLCB1cGRhdGVUZXh0LmJpbmQoY29tcG9uZW50KSkpO1xuXG4gICAgcmV0dXJuIGNvbXBvbmVudDtcbn1cblxudGV4dENvbXBvbmVudC5jcmVhdGVUZXh0Tm9kZSA9IGZ1bmN0aW9uKHRleHQpe1xuICAgIHJldHVybiBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSh0ZXh0KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gdGV4dENvbXBvbmVudDsiXX0= | |
require=(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})({"fastn/templaterComponent":[function(require,module,exports){ | |
module.exports = function(fastn, component, type, settings, children){ | |
var itemModel = new fastn.Model({}); | |
if(!('template' in settings)){ | |
console.warn('No "template" function was set for this templater component'); | |
} | |
function replaceElement(element){ | |
if(component.element && component.element.parentNode){ | |
component.element.parentNode.replaceChild(element, component.element); | |
} | |
component.element = element; | |
} | |
function update(){ | |
var value = component.data(), | |
template = component.template(); | |
itemModel.set('item', value); | |
var newComponent; | |
if(template){ | |
newComponent = fastn.toComponent(template(itemModel, component.scope(), component._currentComponent)); | |
} | |
if(component._currentComponent && component._currentComponent !== newComponent){ | |
if(fastn.isComponent(component._currentComponent)){ | |
component._currentComponent.destroy(); | |
} | |
} | |
component._currentComponent = newComponent; | |
if(!newComponent){ | |
replaceElement(component.emptyElement); | |
return; | |
} | |
if(fastn.isComponent(newComponent)){ | |
if(component._settings.attachTemplates !== false){ | |
newComponent.attach(itemModel, 2); | |
}else{ | |
newComponent.attach(component.scope(), 1); | |
} | |
if(component.element && component.element !== newComponent.element){ | |
if(newComponent.element == null){ | |
newComponent.render(); | |
} | |
replaceElement(component._currentComponent.element); | |
} | |
} | |
} | |
component.render = function(){ | |
var element; | |
component.emptyElement = document.createTextNode(''); | |
if(component._currentComponent){ | |
component._currentComponent.render(); | |
element = component._currentComponent.element; | |
} | |
component.element = element || component.emptyElement; | |
component.emit('render'); | |
}; | |
component.setProperty('data', | |
fastn.property(undefined, settings.dataChanges || 'value structure') | |
.on('change', update) | |
); | |
component.setProperty('template', | |
fastn.property(undefined, 'value reference') | |
.on('change', update) | |
); | |
component.on('destroy', function(){ | |
if(fastn.isComponent(component._currentComponent)){ | |
component._currentComponent.destroy(); | |
} | |
}); | |
component.on('attach', function(data){ | |
if(fastn.isComponent(component._currentComponent)){ | |
component._currentComponent.attach(component.scope(), 1); | |
} | |
}); | |
return component; | |
}; | |
},{}]},{},[]) | |
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsInRlbXBsYXRlckNvbXBvbmVudC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZmFzdG4sIGNvbXBvbmVudCwgdHlwZSwgc2V0dGluZ3MsIGNoaWxkcmVuKXtcbiAgICB2YXIgaXRlbU1vZGVsID0gbmV3IGZhc3RuLk1vZGVsKHt9KTtcblxuICAgIGlmKCEoJ3RlbXBsYXRlJyBpbiBzZXR0aW5ncykpe1xuICAgICAgICBjb25zb2xlLndhcm4oJ05vIFwidGVtcGxhdGVcIiBmdW5jdGlvbiB3YXMgc2V0IGZvciB0aGlzIHRlbXBsYXRlciBjb21wb25lbnQnKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZXBsYWNlRWxlbWVudChlbGVtZW50KXtcbiAgICAgICAgaWYoY29tcG9uZW50LmVsZW1lbnQgJiYgY29tcG9uZW50LmVsZW1lbnQucGFyZW50Tm9kZSl7XG4gICAgICAgICAgICBjb21wb25lbnQuZWxlbWVudC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChlbGVtZW50LCBjb21wb25lbnQuZWxlbWVudCk7XG4gICAgICAgIH1cbiAgICAgICAgY29tcG9uZW50LmVsZW1lbnQgPSBlbGVtZW50O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVwZGF0ZSgpe1xuXG4gICAgICAgIHZhciB2YWx1ZSA9IGNvbXBvbmVudC5kYXRhKCksXG4gICAgICAgICAgICB0ZW1wbGF0ZSA9IGNvbXBvbmVudC50ZW1wbGF0ZSgpO1xuXG4gICAgICAgIGl0ZW1Nb2RlbC5zZXQoJ2l0ZW0nLCB2YWx1ZSk7XG5cbiAgICAgICAgdmFyIG5ld0NvbXBvbmVudDtcblxuICAgICAgICBpZih0ZW1wbGF0ZSl7XG4gICAgICAgICAgIG5ld0NvbXBvbmVudCA9IGZhc3RuLnRvQ29tcG9uZW50KHRlbXBsYXRlKGl0ZW1Nb2RlbCwgY29tcG9uZW50LnNjb3BlKCksIGNvbXBvbmVudC5fY3VycmVudENvbXBvbmVudCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoY29tcG9uZW50Ll9jdXJyZW50Q29tcG9uZW50ICYmIGNvbXBvbmVudC5fY3VycmVudENvbXBvbmVudCAhPT0gbmV3Q29tcG9uZW50KXtcbiAgICAgICAgICAgIGlmKGZhc3RuLmlzQ29tcG9uZW50KGNvbXBvbmVudC5fY3VycmVudENvbXBvbmVudCkpe1xuICAgICAgICAgICAgICAgIGNvbXBvbmVudC5fY3VycmVudENvbXBvbmVudC5kZXN0cm95KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb21wb25lbnQuX2N1cnJlbnRDb21wb25lbnQgPSBuZXdDb21wb25lbnQ7XG5cbiAgICAgICAgaWYoIW5ld0NvbXBvbmVudCl7XG4gICAgICAgICAgICByZXBsYWNlRWxlbWVudChjb21wb25lbnQuZW1wdHlFbGVtZW50KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGZhc3RuLmlzQ29tcG9uZW50KG5ld0NvbXBvbmVudCkpe1xuICAgICAgICAgICAgaWYoY29tcG9uZW50Ll9zZXR0aW5ncy5hdHRhY2hUZW1wbGF0ZXMgIT09IGZhbHNlKXtcbiAgICAgICAgICAgICAgICBuZXdDb21wb25lbnQuYXR0YWNoKGl0ZW1Nb2RlbCwgMik7XG4gICAgICAgICAgICB9ZWxzZXtcbiAgICAgICAgICAgICAgICBuZXdDb21wb25lbnQuYXR0YWNoKGNvbXBvbmVudC5zY29wZSgpLCAxKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoY29tcG9uZW50LmVsZW1lbnQgJiYgY29tcG9uZW50LmVsZW1lbnQgIT09IG5ld0NvbXBvbmVudC5lbGVtZW50KXtcbiAgICAgICAgICAgICAgICBpZihuZXdDb21wb25lbnQuZWxlbWVudCA9PSBudWxsKXtcbiAgICAgICAgICAgICAgICAgICAgbmV3Q29tcG9uZW50LnJlbmRlcigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXBsYWNlRWxlbWVudChjb21wb25lbnQuX2N1cnJlbnRDb21wb25lbnQuZWxlbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjb21wb25lbnQucmVuZGVyID0gZnVuY3Rpb24oKXtcbiAgICAgICAgdmFyIGVsZW1lbnQ7XG4gICAgICAgIGNvbXBvbmVudC5lbXB0eUVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgnJyk7XG4gICAgICAgIGlmKGNvbXBvbmVudC5fY3VycmVudENvbXBvbmVudCl7XG4gICAgICAgICAgICBjb21wb25lbnQuX2N1cnJlbnRDb21wb25lbnQucmVuZGVyKCk7XG4gICAgICAgICAgICBlbGVtZW50ID0gY29tcG9uZW50Ll9jdXJyZW50Q29tcG9uZW50LmVsZW1lbnQ7XG4gICAgICAgIH1cbiAgICAgICAgY29tcG9uZW50LmVsZW1lbnQgPSBlbGVtZW50IHx8IGNvbXBvbmVudC5lbXB0eUVsZW1lbnQ7XG4gICAgICAgIGNvbXBvbmVudC5lbWl0KCdyZW5kZXInKTtcbiAgICB9O1xuXG4gICAgY29tcG9uZW50LnNldFByb3BlcnR5KCdkYXRhJyxcbiAgICAgICAgZmFzdG4ucHJvcGVydHkodW5kZWZpbmVkLCBzZXR0aW5ncy5kYXRhQ2hhbmdlcyB8fCAndmFsdWUgc3RydWN0dXJlJylcbiAgICAgICAgICAgIC5vbignY2hhbmdlJywgdXBkYXRlKVxuICAgICk7XG5cbiAgICBjb21wb25lbnQuc2V0UHJvcGVydHkoJ3RlbXBsYXRlJyxcbiAgICAgICAgZmFzdG4ucHJvcGVydHkodW5kZWZpbmVkLCAndmFsdWUgcmVmZXJlbmNlJylcbiAgICAgICAgICAgIC5vbignY2hhbmdlJywgdXBkYXRlKVxuICAgICk7XG5cbiAgICBjb21wb25lbnQub24oJ2Rlc3Ryb3knLCBmdW5jdGlvbigpe1xuICAgICAgICBpZihmYXN0bi5pc0NvbXBvbmVudChjb21wb25lbnQuX2N1cnJlbnRDb21wb25lbnQpKXtcbiAgICAgICAgICAgIGNvbXBvbmVudC5fY3VycmVudENvbXBvbmVudC5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGNvbXBvbmVudC5vbignYXR0YWNoJywgZnVuY3Rpb24oZGF0YSl7XG4gICAgICAgIGlmKGZhc3RuLmlzQ29tcG9uZW50KGNvbXBvbmVudC5fY3VycmVudENvbXBvbmVudCkpe1xuICAgICAgICAgICAgY29tcG9uZW50Ll9jdXJyZW50Q29tcG9uZW50LmF0dGFjaChjb21wb25lbnQuc2NvcGUoKSwgMSk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiBjb21wb25lbnQ7XG59OyJdfQ== | |
require=(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 insertChild(fastn, container, child, index){ | |
if(child == null || child === false){ | |
return; | |
} | |
var currentIndex = container._children.indexOf(child), | |
newComponent = fastn.toComponent(child); | |
if(newComponent !== child && ~currentIndex){ | |
container._children.splice(currentIndex, 1, newComponent); | |
} | |
if(!~currentIndex || newComponent !== child){ | |
newComponent.attach(container.scope(), 1); | |
} | |
if(currentIndex !== index){ | |
if(~currentIndex){ | |
container._children.splice(currentIndex, 1); | |
} | |
container._children.splice(index, 0, newComponent); | |
} | |
if(container.element){ | |
if(!newComponent.element){ | |
newComponent.render(); | |
} | |
container._insert(newComponent.element, index); | |
newComponent.emit('insert', container); | |
container.emit('childInsert', newComponent); | |
} | |
} | |
function getContainerElement(){ | |
return this.containerElement || this.element; | |
} | |
function insert(child, index){ | |
var childComponent = child, | |
container = this.container, | |
fastn = this.fastn; | |
if(index && typeof index === 'object'){ | |
childComponent = Array.prototype.slice.call(arguments); | |
} | |
if(isNaN(index)){ | |
index = container._children.length; | |
} | |
if(Array.isArray(childComponent)){ | |
for (var i = 0; i < childComponent.length; i++) { | |
container.insert(childComponent[i], i + index); | |
} | |
}else{ | |
insertChild(fastn, container, childComponent, index); | |
} | |
return container; | |
} | |
module.exports = function(fastn, component, type, settings, children){ | |
component.insert = insert.bind({ | |
container: component, | |
fastn: fastn | |
}); | |
component._insert = function(element, index){ | |
var containerElement = component.getContainerElement(); | |
if(!containerElement){ | |
return; | |
} | |
if(containerElement.childNodes[index] === element){ | |
return; | |
} | |
containerElement.insertBefore(element, containerElement.childNodes[index]); | |
}; | |
component.remove = function(childComponent){ | |
var index = component._children.indexOf(childComponent); | |
if(~index){ | |
component._children.splice(index,1); | |
} | |
childComponent.detach(1); | |
if(childComponent.element){ | |
component._remove(childComponent.element); | |
childComponent.emit('remove', component); | |
} | |
component.emit('childRemove', childComponent); | |
}; | |
component._remove = function(element){ | |
var containerElement = component.getContainerElement(); | |
if(!element || !containerElement || element.parentNode !== containerElement){ | |
return; | |
} | |
containerElement.removeChild(element); | |
}; | |
component.empty = function(){ | |
while(component._children.length){ | |
component.remove(component._children.pop()); | |
} | |
}; | |
component.replaceChild = function(oldChild, newChild){ | |
var index = component._children.indexOf(oldChild); | |
if(!~index){ | |
return; | |
} | |
component.remove(oldChild); | |
component.insert(newChild, index); | |
}; | |
component.getContainerElement = getContainerElement.bind(component); | |
component.on('render', component.insert.bind(null, component._children, 0)); | |
component.on('attach', function(model, firm){ | |
for(var i = 0; i < component._children.length; i++){ | |
if(fastn.isComponent(component._children[i])){ | |
component._children[i].attach(model, firm); | |
} | |
} | |
}); | |
component.on('destroy', function(data, firm){ | |
for(var i = 0; i < component._children.length; i++){ | |
if(fastn.isComponent(component._children[i])){ | |
component._children[i].destroy(firm); | |
} | |
} | |
}); | |
return component; | |
}; | |
},{}],2:[function(require,module,exports){ | |
var setify = require('setify'), | |
classist = require('classist'); | |
function updateTextProperty(generic, element, value){ | |
if(arguments.length === 2){ | |
return element.textContent; | |
} | |
element.textContent = (value == null ? '' : value); | |
} | |
module.exports = { | |
class: function(generic, element, value){ | |
if(!generic._classist){ | |
generic._classist = classist(element); | |
} | |
if(arguments.length < 3){ | |
return generic._classist(); | |
} | |
generic._classist(value); | |
}, | |
display: function(generic, element, value){ | |
if(arguments.length === 2){ | |
return element.style.display !== 'none'; | |
} | |
element.style.display = value ? null : 'none'; | |
}, | |
disabled: function(generic, element, value){ | |
if(arguments.length === 2){ | |
return element.hasAttribute('disabled'); | |
} | |
if(value){ | |
element.setAttribute('disabled', 'disabled'); | |
}else{ | |
element.removeAttribute('disabled'); | |
} | |
}, | |
textContent: updateTextProperty, | |
innerText: updateTextProperty, | |
innerHTML: function(generic, element, value){ | |
if(arguments.length === 2){ | |
return element.innerHTML; | |
} | |
element.innerHTML = (value == null ? '' : value); | |
}, | |
value: function(generic, element, value){ | |
var inputType = element.type; | |
if(element.nodeName === 'INPUT' && inputType === 'date'){ | |
if(arguments.length === 2){ | |
return element.value ? new Date(element.value.replace(/-/g,'/').replace('T',' ')) : null; | |
} | |
value = value != null ? new Date(value) : null; | |
if(!value || isNaN(value)){ | |
element.value = null; | |
}else{ | |
element.value = [ | |
value.getFullYear(), | |
('0' + (value.getMonth() + 1)).slice(-2), | |
('0' + value.getDate()).slice(-2) | |
].join('-'); | |
} | |
return; | |
} | |
if(arguments.length === 2){ | |
return element.value; | |
} | |
if(value === undefined){ | |
value = null; | |
} | |
if(element.nodeName === 'PROGRESS'){ | |
value = parseFloat(value) || 0; | |
} | |
setify(element, value); | |
}, | |
max: function(generic, element, value) { | |
if(arguments.length === 2){ | |
return element.value; | |
} | |
if(element.nodeName === 'PROGRESS'){ | |
value = parseFloat(value) || 0; | |
} | |
element.max = value; | |
}, | |
style: function(generic, element, value){ | |
if(arguments.length === 2){ | |
return element.style; | |
} | |
for(var key in value){ | |
element.style[key] = value[key]; | |
} | |
}, | |
type: function(generic, element, value){ | |
if(arguments.length === 2){ | |
return element.type; | |
} | |
element.setAttribute('type', value); | |
} | |
}; | |
},{"classist":3,"setify":4}],3:[function(require,module,exports){ | |
module.exports = function(element){ | |
var lastClasses = []; | |
return function(classes){ | |
if(!arguments.length){ | |
return lastClasses.join(' '); | |
} | |
function cleanClassName(result, className){ | |
if(typeof className === 'string' && className.match(/\s/)){ | |
className = className.split(' '); | |
} | |
if(Array.isArray(className)){ | |
return result.concat(className.reduce(cleanClassName, [])); | |
} | |
if(className != null && className !== '' && typeof className !== 'boolean'){ | |
result.push(String(className).trim()); | |
} | |
return result; | |
} | |
var newClasses = cleanClassName([], classes), | |
currentClasses = element.className ? element.className.split(' ') : []; | |
lastClasses.map(function(className){ | |
if(!className){ | |
return; | |
} | |
var index = currentClasses.indexOf(className); | |
if(~index){ | |
currentClasses.splice(index, 1); | |
} | |
}); | |
currentClasses = currentClasses.concat(newClasses); | |
lastClasses = newClasses; | |
element.className = currentClasses.join(' '); | |
}; | |
}; | |
},{}],4:[function(require,module,exports){ | |
var naturalSelection = require('natural-selection'); | |
module.exports = function(element, value){ | |
var canSet = naturalSelection(element) && element === document.activeElement; | |
if (canSet) { | |
var start = element.selectionStart, | |
end = element.selectionEnd; | |
element.value = value; | |
element.setSelectionRange(start, end); | |
} else { | |
element.value = value; | |
} | |
}; | |
},{"natural-selection":5}],5:[function(require,module,exports){ | |
var supportedTypes = ['text', 'search', 'tel', 'url', 'password']; | |
module.exports = function(element){ | |
return !!(element.setSelectionRange && ~supportedTypes.indexOf(element.type)); | |
}; | |
},{}],6:[function(require,module,exports){ | |
var todo = [], | |
todoKeys = [], | |
scheduled, | |
updates = 0; | |
function run(){ | |
var startTime = Date.now(); | |
while(todo.length && Date.now() - startTime < 16){ | |
todoKeys.shift(); | |
todo.shift()(); | |
} | |
if(todo.length){ | |
requestAnimationFrame(run); | |
}else{ | |
scheduled = false; | |
} | |
} | |
function schedule(key, fn){ | |
if(~todoKeys.indexOf(key)){ | |
return; | |
} | |
todo.push(fn); | |
todoKeys.push(key); | |
if(!scheduled){ | |
scheduled = true; | |
requestAnimationFrame(run); | |
} | |
} | |
module.exports = schedule; | |
},{}],"fastn/genericComponent":[function(require,module,exports){ | |
var containerComponent = require('./containerComponent'), | |
schedule = require('./schedule'), | |
fancyProps = require('./fancyProps'), | |
matchDomHandlerName = /^((?:el\.)?)([^. ]+)(?:\.(capture))?$/, | |
GENERIC = '_generic'; | |
function createProperties(fastn, component, settings){ | |
for(var key in settings){ | |
var setting = settings[key]; | |
if(typeof setting === 'function' && !fastn.isProperty(setting) && !fastn.isBinding(setting)){ | |
continue; | |
} | |
component.addDomProperty(key); | |
} | |
} | |
function trackKeyEvents(component, element, event){ | |
if('_lastStates' in component && 'charCode' in event){ | |
component._lastStates.unshift(element.value); | |
component._lastStates.pop(); | |
} | |
} | |
function addDomHandler(component, element, handlerName, eventName, capture){ | |
var eventParts = handlerName.split('.'); | |
if(eventParts[0] === 'on'){ | |
eventParts.shift(); | |
} | |
var handler = function(event){ | |
trackKeyEvents(component, element, event); | |
component.emit(handlerName, event, component.scope()); | |
}; | |
element.addEventListener(eventName, handler, capture); | |
component.on('destroy', function(){ | |
element.removeEventListener(eventName, handler, capture); | |
}); | |
} | |
function addDomHandlers(component, element, eventNames){ | |
var events = eventNames.split(' '); | |
for(var i = 0; i < events.length; i++){ | |
var eventName = events[i], | |
match = eventName.match(matchDomHandlerName); | |
if(!match){ | |
continue; | |
} | |
if(match[1] || 'on' + match[2] in element){ | |
addDomHandler(component, element, eventNames, match[2], match[3]); | |
} | |
} | |
} | |
function addAutoHandler(component, element, key, settings){ | |
if(!settings[key]){ | |
return; | |
} | |
var autoEvent = settings[key].split(':'), | |
eventName = key.slice(2); | |
delete settings[key]; | |
var handler = function(event){ | |
var fancyProp = fancyProps[autoEvent[1]], | |
value = fancyProp ? fancyProp(component, element) : element[autoEvent[1]]; | |
trackKeyEvents(component, element, event); | |
component[autoEvent[0]](value); | |
}; | |
element.addEventListener(eventName, handler); | |
component.on('destroy', function(){ | |
element.removeEventListener(eventName, handler); | |
}); | |
} | |
function addDomProperty(fastn, key, property){ | |
var component = this, | |
timeout; | |
property = property || component[key] || fastn.property(); | |
component.setProperty(key, property); | |
function update(){ | |
var element = component.getPropertyElement(key), | |
value = property(); | |
if(!element || component.destroyed()){ | |
return; | |
} | |
if( | |
key === 'value' && | |
component._lastStates && | |
~component._lastStates.indexOf(value) | |
){ | |
clearTimeout(timeout); | |
timeout = setTimeout(update, 50); | |
return; | |
} | |
var isProperty = key in element, | |
fancyProp = fancyProps[key], | |
previous = fancyProp ? fancyProp(component, element) : isProperty ? element[key] : element.getAttribute(key); | |
if(!fancyProp && !isProperty && value == null){ | |
value = ''; | |
} | |
if(value !== previous){ | |
if(fancyProp){ | |
fancyProp(component, element, value); | |
return; | |
} | |
if(isProperty){ | |
element[key] = value; | |
return; | |
} | |
if(typeof value !== 'function' && typeof value !== 'object'){ | |
element.setAttribute(key, value); | |
} | |
} | |
} | |
property.updater(update); | |
} | |
function onRender(){ | |
var component = this, | |
element; | |
for(var key in component._settings){ | |
element = component.getEventElement(key); | |
if(key.slice(0,2) === 'on' && key in element){ | |
addAutoHandler(component, element, key, component._settings); | |
} | |
} | |
for(var eventKey in component._events){ | |
element = component.getEventElement(key); | |
addDomHandlers(component, element, eventKey); | |
} | |
} | |
function render(){ | |
this.element = this.createElement(this._settings.tagName || this._tagName); | |
if('value' in this.element){ | |
this._lastStates = new Array(2); | |
} | |
this.emit('render'); | |
return this; | |
}; | |
function genericComponent(fastn, component, type, settings, children){ | |
if(component.is(type)){ | |
return component; | |
} | |
if(type === GENERIC){ | |
component._tagName = component._tagName || 'div'; | |
}else{ | |
component._tagName = type; | |
} | |
if(component.is(GENERIC)){ | |
return component; | |
} | |
component.extend('_container', settings, children); | |
component.addDomProperty = addDomProperty.bind(component, fastn); | |
component.getEventElement = component.getContainerElement; | |
component.getPropertyElement = component.getContainerElement; | |
component.updateProperty = genericComponent.updateProperty; | |
component.createElement = genericComponent.createElement; | |
createProperties(fastn, component, settings); | |
component.render = render.bind(component); | |
component.on('render', onRender); | |
return component; | |
} | |
genericComponent.updateProperty = function(component, property, update){ | |
if(typeof document !== 'undefined' && document.contains(component.element)){ | |
schedule(property, update); | |
}else{ | |
update(); | |
} | |
}; | |
genericComponent.createElement = function(tagName){ | |
if(tagName instanceof Node){ | |
return tagName; | |
} | |
return document.createElement(tagName); | |
}; | |
module.exports = genericComponent; | |
},{"./containerComponent":1,"./fancyProps":2,"./schedule":6}]},{},[]) | |
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsImNvbnRhaW5lckNvbXBvbmVudC5qcyIsImZhbmN5UHJvcHMuanMiLCJub2RlX21vZHVsZXMvY2xhc3Npc3QvaW5kZXguanMiLCJub2RlX21vZHVsZXMvc2V0aWZ5L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3NldGlmeS9ub2RlX21vZHVsZXMvbmF0dXJhbC1zZWxlY3Rpb24vaW5kZXguanMiLCJzY2hlZHVsZS5qcyIsImdlbmVyaWNDb21wb25lbnQuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0lBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiZnVuY3Rpb24gaW5zZXJ0Q2hpbGQoZmFzdG4sIGNvbnRhaW5lciwgY2hpbGQsIGluZGV4KXtcbiAgICBpZihjaGlsZCA9PSBudWxsIHx8IGNoaWxkID09PSBmYWxzZSl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgY3VycmVudEluZGV4ID0gY29udGFpbmVyLl9jaGlsZHJlbi5pbmRleE9mKGNoaWxkKSxcbiAgICAgICAgbmV3Q29tcG9uZW50ID0gZmFzdG4udG9Db21wb25lbnQoY2hpbGQpO1xuXG4gICAgaWYobmV3Q29tcG9uZW50ICE9PSBjaGlsZCAmJiB+Y3VycmVudEluZGV4KXtcbiAgICAgICAgY29udGFpbmVyLl9jaGlsZHJlbi5zcGxpY2UoY3VycmVudEluZGV4LCAxLCBuZXdDb21wb25lbnQpO1xuICAgIH1cblxuICAgIGlmKCF+Y3VycmVudEluZGV4IHx8IG5ld0NvbXBvbmVudCAhPT0gY2hpbGQpe1xuICAgICAgICBuZXdDb21wb25lbnQuYXR0YWNoKGNvbnRhaW5lci5zY29wZSgpLCAxKTtcbiAgICB9XG5cbiAgICBpZihjdXJyZW50SW5kZXggIT09IGluZGV4KXtcbiAgICAgICAgaWYofmN1cnJlbnRJbmRleCl7XG4gICAgICAgICAgICBjb250YWluZXIuX2NoaWxkcmVuLnNwbGljZShjdXJyZW50SW5kZXgsIDEpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnRhaW5lci5fY2hpbGRyZW4uc3BsaWNlKGluZGV4LCAwLCBuZXdDb21wb25lbnQpO1xuICAgIH1cblxuICAgIGlmKGNvbnRhaW5lci5lbGVtZW50KXtcbiAgICAgICAgaWYoIW5ld0NvbXBvbmVudC5lbGVtZW50KXtcbiAgICAgICAgICAgIG5ld0NvbXBvbmVudC5yZW5kZXIoKTtcbiAgICAgICAgfVxuICAgICAgICBjb250YWluZXIuX2luc2VydChuZXdDb21wb25lbnQuZWxlbWVudCwgaW5kZXgpO1xuICAgICAgICBuZXdDb21wb25lbnQuZW1pdCgnaW5zZXJ0JywgY29udGFpbmVyKTtcbiAgICAgICAgY29udGFpbmVyLmVtaXQoJ2NoaWxkSW5zZXJ0JywgbmV3Q29tcG9uZW50KTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldENvbnRhaW5lckVsZW1lbnQoKXtcbiAgICByZXR1cm4gdGhpcy5jb250YWluZXJFbGVtZW50IHx8IHRoaXMuZWxlbWVudDtcbn1cblxuZnVuY3Rpb24gaW5zZXJ0KGNoaWxkLCBpbmRleCl7XG4gICAgdmFyIGNoaWxkQ29tcG9uZW50ID0gY2hpbGQsXG4gICAgICAgIGNvbnRhaW5lciA9IHRoaXMuY29udGFpbmVyLFxuICAgICAgICBmYXN0biA9IHRoaXMuZmFzdG47XG5cbiAgICBpZihpbmRleCAmJiB0eXBlb2YgaW5kZXggPT09ICdvYmplY3QnKXtcbiAgICAgICAgY2hpbGRDb21wb25lbnQgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuICAgIH1cblxuICAgIGlmKGlzTmFOKGluZGV4KSl7XG4gICAgICAgIGluZGV4ID0gY29udGFpbmVyLl9jaGlsZHJlbi5sZW5ndGg7XG4gICAgfVxuXG4gICAgaWYoQXJyYXkuaXNBcnJheShjaGlsZENvbXBvbmVudCkpe1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkQ29tcG9uZW50Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb250YWluZXIuaW5zZXJ0KGNoaWxkQ29tcG9uZW50W2ldLCBpICsgaW5kZXgpO1xuICAgICAgICB9XG4gICAgfWVsc2V7XG4gICAgICAgIGluc2VydENoaWxkKGZhc3RuLCBjb250YWluZXIsIGNoaWxkQ29tcG9uZW50LCBpbmRleCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbnRhaW5lcjtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihmYXN0biwgY29tcG9uZW50LCB0eXBlLCBzZXR0aW5ncywgY2hpbGRyZW4pe1xuICAgIGNvbXBvbmVudC5pbnNlcnQgPSBpbnNlcnQuYmluZCh7XG4gICAgICAgIGNvbnRhaW5lcjogY29tcG9uZW50LFxuICAgICAgICBmYXN0bjogZmFzdG5cbiAgICB9KTtcblxuICAgIGNvbXBvbmVudC5faW5zZXJ0ID0gZnVuY3Rpb24oZWxlbWVudCwgaW5kZXgpe1xuICAgICAgICB2YXIgY29udGFpbmVyRWxlbWVudCA9IGNvbXBvbmVudC5nZXRDb250YWluZXJFbGVtZW50KCk7XG4gICAgICAgIGlmKCFjb250YWluZXJFbGVtZW50KXtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGNvbnRhaW5lckVsZW1lbnQuY2hpbGROb2Rlc1tpbmRleF0gPT09IGVsZW1lbnQpe1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29udGFpbmVyRWxlbWVudC5pbnNlcnRCZWZvcmUoZWxlbWVudCwgY29udGFpbmVyRWxlbWVudC5jaGlsZE5vZGVzW2luZGV4XSk7XG4gICAgfTtcblxuICAgIGNvbXBvbmVudC5yZW1vdmUgPSBmdW5jdGlvbihjaGlsZENvbXBvbmVudCl7XG4gICAgICAgIHZhciBpbmRleCA9IGNvbXBvbmVudC5fY2hpbGRyZW4uaW5kZXhPZihjaGlsZENvbXBvbmVudCk7XG4gICAgICAgIGlmKH5pbmRleCl7XG4gICAgICAgICAgICBjb21wb25lbnQuX2NoaWxkcmVuLnNwbGljZShpbmRleCwxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNoaWxkQ29tcG9uZW50LmRldGFjaCgxKTtcblxuICAgICAgICBpZihjaGlsZENvbXBvbmVudC5lbGVtZW50KXtcbiAgICAgICAgICAgIGNvbXBvbmVudC5fcmVtb3ZlKGNoaWxkQ29tcG9uZW50LmVsZW1lbnQpO1xuICAgICAgICAgICAgY2hpbGRDb21wb25lbnQuZW1pdCgncmVtb3ZlJywgY29tcG9uZW50KTtcbiAgICAgICAgfVxuICAgICAgICBjb21wb25lbnQuZW1pdCgnY2hpbGRSZW1vdmUnLCBjaGlsZENvbXBvbmVudCk7XG4gICAgfTtcblxuICAgIGNvbXBvbmVudC5fcmVtb3ZlID0gZnVuY3Rpb24oZWxlbWVudCl7XG4gICAgICAgIHZhciBjb250YWluZXJFbGVtZW50ID0gY29tcG9uZW50LmdldENvbnRhaW5lckVsZW1lbnQoKTtcblxuICAgICAgICBpZighZWxlbWVudCB8fCAhY29udGFpbmVyRWxlbWVudCB8fCBlbGVtZW50LnBhcmVudE5vZGUgIT09IGNvbnRhaW5lckVsZW1lbnQpe1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29udGFpbmVyRWxlbWVudC5yZW1vdmVDaGlsZChlbGVtZW50KTtcbiAgICB9O1xuXG4gICAgY29tcG9uZW50LmVtcHR5ID0gZnVuY3Rpb24oKXtcbiAgICAgICAgd2hpbGUoY29tcG9uZW50Ll9jaGlsZHJlbi5sZW5ndGgpe1xuICAgICAgICAgICAgY29tcG9uZW50LnJlbW92ZShjb21wb25lbnQuX2NoaWxkcmVuLnBvcCgpKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBjb21wb25lbnQucmVwbGFjZUNoaWxkID0gZnVuY3Rpb24ob2xkQ2hpbGQsIG5ld0NoaWxkKXtcbiAgICAgICAgdmFyIGluZGV4ID0gY29tcG9uZW50Ll9jaGlsZHJlbi5pbmRleE9mKG9sZENoaWxkKTtcblxuICAgICAgICBpZighfmluZGV4KXtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbXBvbmVudC5yZW1vdmUob2xkQ2hpbGQpO1xuICAgICAgICBjb21wb25lbnQuaW5zZXJ0KG5ld0NoaWxkLCBpbmRleCk7XG4gICAgfTtcblxuICAgIGNvbXBvbmVudC5nZXRDb250YWluZXJFbGVtZW50ID0gZ2V0Q29udGFpbmVyRWxlbWVudC5iaW5kKGNvbXBvbmVudCk7XG5cbiAgICBjb21wb25lbnQub24oJ3JlbmRlcicsIGNvbXBvbmVudC5pbnNlcnQuYmluZChudWxsLCBjb21wb25lbnQuX2NoaWxkcmVuLCAwKSk7XG5cbiAgICBjb21wb25lbnQub24oJ2F0dGFjaCcsIGZ1bmN0aW9uKG1vZGVsLCBmaXJtKXtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGNvbXBvbmVudC5fY2hpbGRyZW4ubGVuZ3RoOyBpKyspe1xuICAgICAgICAgICAgaWYoZmFzdG4uaXNDb21wb25lbnQoY29tcG9uZW50Ll9jaGlsZHJlbltpXSkpe1xuICAgICAgICAgICAgICAgIGNvbXBvbmVudC5fY2hpbGRyZW5baV0uYXR0YWNoKG1vZGVsLCBmaXJtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29tcG9uZW50Lm9uKCdkZXN0cm95JywgZnVuY3Rpb24oZGF0YSwgZmlybSl7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjb21wb25lbnQuX2NoaWxkcmVuLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgICAgIGlmKGZhc3RuLmlzQ29tcG9uZW50KGNvbXBvbmVudC5fY2hpbGRyZW5baV0pKXtcbiAgICAgICAgICAgICAgICBjb21wb25lbnQuX2NoaWxkcmVuW2ldLmRlc3Ryb3koZmlybSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiBjb21wb25lbnQ7XG59OyIsInZhciBzZXRpZnkgPSByZXF1aXJlKCdzZXRpZnknKSxcbiAgICBjbGFzc2lzdCA9IHJlcXVpcmUoJ2NsYXNzaXN0Jyk7XG5cbmZ1bmN0aW9uIHVwZGF0ZVRleHRQcm9wZXJ0eShnZW5lcmljLCBlbGVtZW50LCB2YWx1ZSl7XG4gICAgaWYoYXJndW1lbnRzLmxlbmd0aCA9PT0gMil7XG4gICAgICAgIHJldHVybiBlbGVtZW50LnRleHRDb250ZW50O1xuICAgIH1cbiAgICBlbGVtZW50LnRleHRDb250ZW50ID0gKHZhbHVlID09IG51bGwgPyAnJyA6IHZhbHVlKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgY2xhc3M6IGZ1bmN0aW9uKGdlbmVyaWMsIGVsZW1lbnQsIHZhbHVlKXtcbiAgICAgICAgaWYoIWdlbmVyaWMuX2NsYXNzaXN0KXtcbiAgICAgICAgICAgIGdlbmVyaWMuX2NsYXNzaXN0ID0gY2xhc3Npc3QoZWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihhcmd1bWVudHMubGVuZ3RoIDwgMyl7XG4gICAgICAgICAgICByZXR1cm4gZ2VuZXJpYy5fY2xhc3Npc3QoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGdlbmVyaWMuX2NsYXNzaXN0KHZhbHVlKTtcbiAgICB9LFxuICAgIGRpc3BsYXk6IGZ1bmN0aW9uKGdlbmVyaWMsIGVsZW1lbnQsIHZhbHVlKXtcbiAgICAgICAgaWYoYXJndW1lbnRzLmxlbmd0aCA9PT0gMil7XG4gICAgICAgICAgICByZXR1cm4gZWxlbWVudC5zdHlsZS5kaXNwbGF5ICE9PSAnbm9uZSc7XG4gICAgICAgIH1cbiAgICAgICAgZWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gdmFsdWUgPyBudWxsIDogJ25vbmUnO1xuICAgIH0sXG4gICAgZGlzYWJsZWQ6IGZ1bmN0aW9uKGdlbmVyaWMsIGVsZW1lbnQsIHZhbHVlKXtcbiAgICAgICAgaWYoYXJndW1lbnRzLmxlbmd0aCA9PT0gMil7XG4gICAgICAgICAgICByZXR1cm4gZWxlbWVudC5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYodmFsdWUpe1xuICAgICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyk7XG4gICAgICAgIH1lbHNle1xuICAgICAgICAgICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHRleHRDb250ZW50OiB1cGRhdGVUZXh0UHJvcGVydHksXG4gICAgaW5uZXJUZXh0OiB1cGRhdGVUZXh0UHJvcGVydHksXG4gICAgaW5uZXJIVE1MOiBmdW5jdGlvbihnZW5lcmljLCBlbGVtZW50LCB2YWx1ZSl7XG4gICAgICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPT09IDIpe1xuICAgICAgICAgICAgcmV0dXJuIGVsZW1lbnQuaW5uZXJIVE1MO1xuICAgICAgICB9XG4gICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gKHZhbHVlID09IG51bGwgPyAnJyA6IHZhbHVlKTtcbiAgICB9LFxuICAgIHZhbHVlOiBmdW5jdGlvbihnZW5lcmljLCBlbGVtZW50LCB2YWx1ZSl7XG4gICAgICAgIHZhciBpbnB1dFR5cGUgPSBlbGVtZW50LnR5cGU7XG5cbiAgICAgICAgaWYoZWxlbWVudC5ub2RlTmFtZSA9PT0gJ0lOUFVUJyAmJiBpbnB1dFR5cGUgPT09ICdkYXRlJyl7XG4gICAgICAgICAgICBpZihhcmd1bWVudHMubGVuZ3RoID09PSAyKXtcbiAgICAgICAgICAgICAgICByZXR1cm4gZWxlbWVudC52YWx1ZSA/IG5ldyBEYXRlKGVsZW1lbnQudmFsdWUucmVwbGFjZSgvLS9nLCcvJykucmVwbGFjZSgnVCcsJyAnKSkgOiBudWxsO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlICE9IG51bGwgPyBuZXcgRGF0ZSh2YWx1ZSkgOiBudWxsO1xuXG4gICAgICAgICAgICBpZighdmFsdWUgfHwgaXNOYU4odmFsdWUpKXtcbiAgICAgICAgICAgICAgICBlbGVtZW50LnZhbHVlID0gbnVsbDtcbiAgICAgICAgICAgIH1lbHNle1xuICAgICAgICAgICAgICAgIGVsZW1lbnQudmFsdWUgPSBbXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlLmdldEZ1bGxZZWFyKCksXG4gICAgICAgICAgICAgICAgICAgICgnMCcgKyAodmFsdWUuZ2V0TW9udGgoKSArIDEpKS5zbGljZSgtMiksXG4gICAgICAgICAgICAgICAgICAgICgnMCcgKyB2YWx1ZS5nZXREYXRlKCkpLnNsaWNlKC0yKVxuICAgICAgICAgICAgICAgIF0uam9pbignLScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoYXJndW1lbnRzLmxlbmd0aCA9PT0gMil7XG4gICAgICAgICAgICByZXR1cm4gZWxlbWVudC52YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZih2YWx1ZSA9PT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgIHZhbHVlID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGVsZW1lbnQubm9kZU5hbWUgPT09ICdQUk9HUkVTUycpe1xuICAgICAgICAgICAgdmFsdWUgPSBwYXJzZUZsb2F0KHZhbHVlKSB8fCAwO1xuICAgICAgICB9XG5cbiAgICAgICAgc2V0aWZ5KGVsZW1lbnQsIHZhbHVlKTtcbiAgICB9LFxuICAgIG1heDogZnVuY3Rpb24oZ2VuZXJpYywgZWxlbWVudCwgdmFsdWUpIHtcbiAgICAgICAgaWYoYXJndW1lbnRzLmxlbmd0aCA9PT0gMil7XG4gICAgICAgICAgICByZXR1cm4gZWxlbWVudC52YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGVsZW1lbnQubm9kZU5hbWUgPT09ICdQUk9HUkVTUycpe1xuICAgICAgICAgICAgdmFsdWUgPSBwYXJzZUZsb2F0KHZhbHVlKSB8fCAwO1xuICAgICAgICB9XG5cbiAgICAgICAgZWxlbWVudC5tYXggPSB2YWx1ZTtcbiAgICB9LFxuICAgIHN0eWxlOiBmdW5jdGlvbihnZW5lcmljLCBlbGVtZW50LCB2YWx1ZSl7XG4gICAgICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPT09IDIpe1xuICAgICAgICAgICAgcmV0dXJuIGVsZW1lbnQuc3R5bGU7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IodmFyIGtleSBpbiB2YWx1ZSl7XG4gICAgICAgICAgICBlbGVtZW50LnN0eWxlW2tleV0gPSB2YWx1ZVtrZXldO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB0eXBlOiBmdW5jdGlvbihnZW5lcmljLCBlbGVtZW50LCB2YWx1ZSl7XG4gICAgICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPT09IDIpe1xuICAgICAgICAgICAgcmV0dXJuIGVsZW1lbnQudHlwZTtcbiAgICAgICAgfVxuICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgndHlwZScsIHZhbHVlKTtcbiAgICB9XG59OyIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZWxlbWVudCl7XG4gICAgdmFyIGxhc3RDbGFzc2VzID0gW107XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oY2xhc3Nlcyl7XG5cbiAgICAgICAgaWYoIWFyZ3VtZW50cy5sZW5ndGgpe1xuICAgICAgICAgICAgcmV0dXJuIGxhc3RDbGFzc2VzLmpvaW4oJyAnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGNsZWFuQ2xhc3NOYW1lKHJlc3VsdCwgY2xhc3NOYW1lKXtcbiAgICAgICAgICAgIGlmKHR5cGVvZiBjbGFzc05hbWUgPT09ICdzdHJpbmcnICYmIGNsYXNzTmFtZS5tYXRjaCgvXFxzLykpe1xuICAgICAgICAgICAgICAgIGNsYXNzTmFtZSA9IGNsYXNzTmFtZS5zcGxpdCgnICcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KGNsYXNzTmFtZSkpe1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQuY29uY2F0KGNsYXNzTmFtZS5yZWR1Y2UoY2xlYW5DbGFzc05hbWUsIFtdKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGNsYXNzTmFtZSAhPSBudWxsICYmIGNsYXNzTmFtZSAhPT0gJycgJiYgdHlwZW9mIGNsYXNzTmFtZSAhPT0gJ2Jvb2xlYW4nKXtcbiAgICAgICAgICAgICAgICByZXN1bHQucHVzaChTdHJpbmcoY2xhc3NOYW1lKS50cmltKCkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIG5ld0NsYXNzZXMgPSBjbGVhbkNsYXNzTmFtZShbXSwgY2xhc3NlcyksXG4gICAgICAgICAgICBjdXJyZW50Q2xhc3NlcyA9IGVsZW1lbnQuY2xhc3NOYW1lID8gZWxlbWVudC5jbGFzc05hbWUuc3BsaXQoJyAnKSA6IFtdO1xuXG4gICAgICAgIGxhc3RDbGFzc2VzLm1hcChmdW5jdGlvbihjbGFzc05hbWUpe1xuICAgICAgICAgICAgaWYoIWNsYXNzTmFtZSl7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgaW5kZXggPSBjdXJyZW50Q2xhc3Nlcy5pbmRleE9mKGNsYXNzTmFtZSk7XG5cbiAgICAgICAgICAgIGlmKH5pbmRleCl7XG4gICAgICAgICAgICAgICAgY3VycmVudENsYXNzZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgY3VycmVudENsYXNzZXMgPSBjdXJyZW50Q2xhc3Nlcy5jb25jYXQobmV3Q2xhc3Nlcyk7XG4gICAgICAgIGxhc3RDbGFzc2VzID0gbmV3Q2xhc3NlcztcblxuICAgICAgICBlbGVtZW50LmNsYXNzTmFtZSA9IGN1cnJlbnRDbGFzc2VzLmpvaW4oJyAnKTtcbiAgICB9O1xufTtcbiIsInZhciBuYXR1cmFsU2VsZWN0aW9uID0gcmVxdWlyZSgnbmF0dXJhbC1zZWxlY3Rpb24nKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihlbGVtZW50LCB2YWx1ZSl7XG4gICAgdmFyIGNhblNldCA9IG5hdHVyYWxTZWxlY3Rpb24oZWxlbWVudCkgJiYgZWxlbWVudCA9PT0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudDtcblxuICAgIGlmIChjYW5TZXQpIHtcbiAgICAgICAgdmFyIHN0YXJ0ID0gZWxlbWVudC5zZWxlY3Rpb25TdGFydCxcbiAgICAgICAgICAgIGVuZCA9IGVsZW1lbnQuc2VsZWN0aW9uRW5kO1xuXG4gICAgICAgIGVsZW1lbnQudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgZWxlbWVudC5zZXRTZWxlY3Rpb25SYW5nZShzdGFydCwgZW5kKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBlbGVtZW50LnZhbHVlID0gdmFsdWU7XG4gICAgfVxufTtcbiIsInZhciBzdXBwb3J0ZWRUeXBlcyA9IFsndGV4dCcsICdzZWFyY2gnLCAndGVsJywgJ3VybCcsICdwYXNzd29yZCddO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGVsZW1lbnQpe1xuICAgIHJldHVybiAhIShlbGVtZW50LnNldFNlbGVjdGlvblJhbmdlICYmIH5zdXBwb3J0ZWRUeXBlcy5pbmRleE9mKGVsZW1lbnQudHlwZSkpO1xufTtcbiIsInZhciB0b2RvID0gW10sXG4gICAgdG9kb0tleXMgPSBbXSxcbiAgICBzY2hlZHVsZWQsXG4gICAgdXBkYXRlcyA9IDA7XG5cbmZ1bmN0aW9uIHJ1bigpe1xuICAgIHZhciBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgd2hpbGUodG9kby5sZW5ndGggJiYgRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSA8IDE2KXtcbiAgICAgICAgdG9kb0tleXMuc2hpZnQoKTtcbiAgICAgICAgdG9kby5zaGlmdCgpKCk7XG4gICAgfVxuXG4gICAgaWYodG9kby5sZW5ndGgpe1xuICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUocnVuKTtcbiAgICB9ZWxzZXtcbiAgICAgICAgc2NoZWR1bGVkID0gZmFsc2U7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBzY2hlZHVsZShrZXksIGZuKXtcbiAgICBpZih+dG9kb0tleXMuaW5kZXhPZihrZXkpKXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRvZG8ucHVzaChmbik7XG4gICAgdG9kb0tleXMucHVzaChrZXkpO1xuXG4gICAgaWYoIXNjaGVkdWxlZCl7XG4gICAgICAgIHNjaGVkdWxlZCA9IHRydWU7XG4gICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZShydW4pO1xuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBzY2hlZHVsZTsiLCJ2YXIgY29udGFpbmVyQ29tcG9uZW50ID0gcmVxdWlyZSgnLi9jb250YWluZXJDb21wb25lbnQnKSxcbiAgICBzY2hlZHVsZSA9IHJlcXVpcmUoJy4vc2NoZWR1bGUnKSxcbiAgICBmYW5jeVByb3BzID0gcmVxdWlyZSgnLi9mYW5jeVByb3BzJyksXG4gICAgbWF0Y2hEb21IYW5kbGVyTmFtZSA9IC9eKCg/OmVsXFwuKT8pKFteLiBdKykoPzpcXC4oY2FwdHVyZSkpPyQvLFxuICAgIEdFTkVSSUMgPSAnX2dlbmVyaWMnO1xuXG5mdW5jdGlvbiBjcmVhdGVQcm9wZXJ0aWVzKGZhc3RuLCBjb21wb25lbnQsIHNldHRpbmdzKXtcbiAgICBmb3IodmFyIGtleSBpbiBzZXR0aW5ncyl7XG4gICAgICAgIHZhciBzZXR0aW5nID0gc2V0dGluZ3Nba2V5XTtcblxuICAgICAgICBpZih0eXBlb2Ygc2V0dGluZyA9PT0gJ2Z1bmN0aW9uJyAmJiAhZmFzdG4uaXNQcm9wZXJ0eShzZXR0aW5nKSAmJiAhZmFzdG4uaXNCaW5kaW5nKHNldHRpbmcpKXtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29tcG9uZW50LmFkZERvbVByb3BlcnR5KGtleSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiB0cmFja0tleUV2ZW50cyhjb21wb25lbnQsIGVsZW1lbnQsIGV2ZW50KXtcbiAgICBpZignX2xhc3RTdGF0ZXMnIGluIGNvbXBvbmVudCAmJiAnY2hhckNvZGUnIGluIGV2ZW50KXtcbiAgICAgICAgY29tcG9uZW50Ll9sYXN0U3RhdGVzLnVuc2hpZnQoZWxlbWVudC52YWx1ZSk7XG4gICAgICAgIGNvbXBvbmVudC5fbGFzdFN0YXRlcy5wb3AoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGFkZERvbUhhbmRsZXIoY29tcG9uZW50LCBlbGVtZW50LCBoYW5kbGVyTmFtZSwgZXZlbnROYW1lLCBjYXB0dXJlKXtcbiAgICB2YXIgZXZlbnRQYXJ0cyA9IGhhbmRsZXJOYW1lLnNwbGl0KCcuJyk7XG5cbiAgICBpZihldmVudFBhcnRzWzBdID09PSAnb24nKXtcbiAgICAgICAgZXZlbnRQYXJ0cy5zaGlmdCgpO1xuICAgIH1cblxuICAgIHZhciBoYW5kbGVyID0gZnVuY3Rpb24oZXZlbnQpe1xuICAgICAgICAgICAgdHJhY2tLZXlFdmVudHMoY29tcG9uZW50LCBlbGVtZW50LCBldmVudCk7XG4gICAgICAgICAgICBjb21wb25lbnQuZW1pdChoYW5kbGVyTmFtZSwgZXZlbnQsIGNvbXBvbmVudC5zY29wZSgpKTtcbiAgICAgICAgfTtcblxuICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIGhhbmRsZXIsIGNhcHR1cmUpO1xuXG4gICAgY29tcG9uZW50Lm9uKCdkZXN0cm95JywgZnVuY3Rpb24oKXtcbiAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgaGFuZGxlciwgY2FwdHVyZSk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGFkZERvbUhhbmRsZXJzKGNvbXBvbmVudCwgZWxlbWVudCwgZXZlbnROYW1lcyl7XG4gICAgdmFyIGV2ZW50cyA9IGV2ZW50TmFtZXMuc3BsaXQoJyAnKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBldmVudHMubGVuZ3RoOyBpKyspe1xuICAgICAgICB2YXIgZXZlbnROYW1lID0gZXZlbnRzW2ldLFxuICAgICAgICAgICAgbWF0Y2ggPSBldmVudE5hbWUubWF0Y2gobWF0Y2hEb21IYW5kbGVyTmFtZSk7XG5cbiAgICAgICAgaWYoIW1hdGNoKXtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYobWF0Y2hbMV0gfHwgJ29uJyArIG1hdGNoWzJdIGluIGVsZW1lbnQpe1xuICAgICAgICAgICAgYWRkRG9tSGFuZGxlcihjb21wb25lbnQsIGVsZW1lbnQsIGV2ZW50TmFtZXMsIG1hdGNoWzJdLCBtYXRjaFszXSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGFkZEF1dG9IYW5kbGVyKGNvbXBvbmVudCwgZWxlbWVudCwga2V5LCBzZXR0aW5ncyl7XG4gICAgaWYoIXNldHRpbmdzW2tleV0pe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGF1dG9FdmVudCA9IHNldHRpbmdzW2tleV0uc3BsaXQoJzonKSxcbiAgICAgICAgZXZlbnROYW1lID0ga2V5LnNsaWNlKDIpO1xuXG4gICAgZGVsZXRlIHNldHRpbmdzW2tleV07XG5cbiAgICB2YXIgaGFuZGxlciA9IGZ1bmN0aW9uKGV2ZW50KXtcbiAgICAgICAgdmFyIGZhbmN5UHJvcCA9IGZhbmN5UHJvcHNbYXV0b0V2ZW50WzFdXSxcbiAgICAgICAgICAgIHZhbHVlID0gZmFuY3lQcm9wID8gZmFuY3lQcm9wKGNvbXBvbmVudCwgZWxlbWVudCkgOiBlbGVtZW50W2F1dG9FdmVudFsxXV07XG5cbiAgICAgICAgdHJhY2tLZXlFdmVudHMoY29tcG9uZW50LCBlbGVtZW50LCBldmVudCk7XG5cbiAgICAgICAgY29tcG9uZW50W2F1dG9FdmVudFswXV0odmFsdWUpO1xuICAgIH07XG5cbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnROYW1lLCBoYW5kbGVyKTtcblxuICAgIGNvbXBvbmVudC5vbignZGVzdHJveScsIGZ1bmN0aW9uKCl7XG4gICAgICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIGhhbmRsZXIpO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBhZGREb21Qcm9wZXJ0eShmYXN0biwga2V5LCBwcm9wZXJ0eSl7XG4gICAgdmFyIGNvbXBvbmVudCA9IHRoaXMsXG4gICAgICAgIHRpbWVvdXQ7XG5cbiAgICBwcm9wZXJ0eSA9IHByb3BlcnR5IHx8IGNvbXBvbmVudFtrZXldIHx8IGZhc3RuLnByb3BlcnR5KCk7XG4gICAgY29tcG9uZW50LnNldFByb3BlcnR5KGtleSwgcHJvcGVydHkpO1xuXG4gICAgZnVuY3Rpb24gdXBkYXRlKCl7XG5cbiAgICAgICAgdmFyIGVsZW1lbnQgPSBjb21wb25lbnQuZ2V0UHJvcGVydHlFbGVtZW50KGtleSksXG4gICAgICAgICAgICB2YWx1ZSA9IHByb3BlcnR5KCk7XG5cbiAgICAgICAgaWYoIWVsZW1lbnQgfHwgY29tcG9uZW50LmRlc3Ryb3llZCgpKXtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKFxuICAgICAgICAgICAga2V5ID09PSAndmFsdWUnICYmXG4gICAgICAgICAgICBjb21wb25lbnQuX2xhc3RTdGF0ZXMgJiZcbiAgICAgICAgICAgIH5jb21wb25lbnQuX2xhc3RTdGF0ZXMuaW5kZXhPZih2YWx1ZSlcbiAgICAgICAgKXtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KHVwZGF0ZSwgNTApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGlzUHJvcGVydHkgPSBrZXkgaW4gZWxlbWVudCxcbiAgICAgICAgICAgIGZhbmN5UHJvcCA9IGZhbmN5UHJvcHNba2V5XSxcbiAgICAgICAgICAgIHByZXZpb3VzID0gZmFuY3lQcm9wID8gZmFuY3lQcm9wKGNvbXBvbmVudCwgZWxlbWVudCkgOiBpc1Byb3BlcnR5ID8gZWxlbWVudFtrZXldIDogZWxlbWVudC5nZXRBdHRyaWJ1dGUoa2V5KTtcblxuICAgICAgICBpZighZmFuY3lQcm9wICYmICFpc1Byb3BlcnR5ICYmIHZhbHVlID09IG51bGwpe1xuICAgICAgICAgICAgdmFsdWUgPSAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHZhbHVlICE9PSBwcmV2aW91cyl7XG4gICAgICAgICAgICBpZihmYW5jeVByb3Ape1xuICAgICAgICAgICAgICAgIGZhbmN5UHJvcChjb21wb25lbnQsIGVsZW1lbnQsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGlzUHJvcGVydHkpe1xuICAgICAgICAgICAgICAgIGVsZW1lbnRba2V5XSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYodHlwZW9mIHZhbHVlICE9PSAnZnVuY3Rpb24nICYmIHR5cGVvZiB2YWx1ZSAhPT0gJ29iamVjdCcpe1xuICAgICAgICAgICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKGtleSwgdmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJvcGVydHkudXBkYXRlcih1cGRhdGUpO1xufVxuXG5mdW5jdGlvbiBvblJlbmRlcigpe1xuICAgIHZhciBjb21wb25lbnQgPSB0aGlzLFxuICAgICAgICBlbGVtZW50O1xuXG4gICAgZm9yKHZhciBrZXkgaW4gY29tcG9uZW50Ll9zZXR0aW5ncyl7XG4gICAgICAgIGVsZW1lbnQgPSBjb21wb25lbnQuZ2V0RXZlbnRFbGVtZW50KGtleSk7XG4gICAgICAgIGlmKGtleS5zbGljZSgwLDIpID09PSAnb24nICYmIGtleSBpbiBlbGVtZW50KXtcbiAgICAgICAgICAgIGFkZEF1dG9IYW5kbGVyKGNvbXBvbmVudCwgZWxlbWVudCwga2V5LCBjb21wb25lbnQuX3NldHRpbmdzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcih2YXIgZXZlbnRLZXkgaW4gY29tcG9uZW50Ll9ldmVudHMpe1xuICAgICAgICBlbGVtZW50ID0gY29tcG9uZW50LmdldEV2ZW50RWxlbWVudChrZXkpO1xuICAgICAgICBhZGREb21IYW5kbGVycyhjb21wb25lbnQsIGVsZW1lbnQsIGV2ZW50S2V5KTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHJlbmRlcigpe1xuICAgIHRoaXMuZWxlbWVudCA9IHRoaXMuY3JlYXRlRWxlbWVudCh0aGlzLl9zZXR0aW5ncy50YWdOYW1lIHx8IHRoaXMuX3RhZ05hbWUpO1xuXG4gICAgaWYoJ3ZhbHVlJyBpbiB0aGlzLmVsZW1lbnQpe1xuICAgICAgICB0aGlzLl9sYXN0U3RhdGVzID0gbmV3IEFycmF5KDIpO1xuICAgIH1cblxuICAgIHRoaXMuZW1pdCgncmVuZGVyJyk7XG5cbiAgICByZXR1cm4gdGhpcztcbn07XG5cbmZ1bmN0aW9uIGdlbmVyaWNDb21wb25lbnQoZmFzdG4sIGNvbXBvbmVudCwgdHlwZSwgc2V0dGluZ3MsIGNoaWxkcmVuKXtcbiAgICBpZihjb21wb25lbnQuaXModHlwZSkpe1xuICAgICAgICByZXR1cm4gY29tcG9uZW50O1xuICAgIH1cblxuICAgIGlmKHR5cGUgPT09IEdFTkVSSUMpe1xuICAgICAgICBjb21wb25lbnQuX3RhZ05hbWUgPSBjb21wb25lbnQuX3RhZ05hbWUgfHwgJ2Rpdic7XG4gICAgfWVsc2V7XG4gICAgICAgIGNvbXBvbmVudC5fdGFnTmFtZSA9IHR5cGU7XG4gICAgfVxuXG4gICAgaWYoY29tcG9uZW50LmlzKEdFTkVSSUMpKXtcbiAgICAgICAgcmV0dXJuIGNvbXBvbmVudDtcbiAgICB9XG5cbiAgICBjb21wb25lbnQuZXh0ZW5kKCdfY29udGFpbmVyJywgc2V0dGluZ3MsIGNoaWxkcmVuKTtcblxuICAgIGNvbXBvbmVudC5hZGREb21Qcm9wZXJ0eSA9IGFkZERvbVByb3BlcnR5LmJpbmQoY29tcG9uZW50LCBmYXN0bik7XG4gICAgY29tcG9uZW50LmdldEV2ZW50RWxlbWVudCA9IGNvbXBvbmVudC5nZXRDb250YWluZXJFbGVtZW50O1xuICAgIGNvbXBvbmVudC5nZXRQcm9wZXJ0eUVsZW1lbnQgPSBjb21wb25lbnQuZ2V0Q29udGFpbmVyRWxlbWVudDtcbiAgICBjb21wb25lbnQudXBkYXRlUHJvcGVydHkgPSBnZW5lcmljQ29tcG9uZW50LnVwZGF0ZVByb3BlcnR5O1xuICAgIGNvbXBvbmVudC5jcmVhdGVFbGVtZW50ID0gZ2VuZXJpY0NvbXBvbmVudC5jcmVhdGVFbGVtZW50O1xuXG4gICAgY3JlYXRlUHJvcGVydGllcyhmYXN0biwgY29tcG9uZW50LCBzZXR0aW5ncyk7XG5cbiAgICBjb21wb25lbnQucmVuZGVyID0gcmVuZGVyLmJpbmQoY29tcG9uZW50KTtcblxuICAgIGNvbXBvbmVudC5vbigncmVuZGVyJywgb25SZW5kZXIpO1xuXG4gICAgcmV0dXJuIGNvbXBvbmVudDtcbn1cblxuZ2VuZXJpY0NvbXBvbmVudC51cGRhdGVQcm9wZXJ0eSA9IGZ1bmN0aW9uKGNvbXBvbmVudCwgcHJvcGVydHksIHVwZGF0ZSl7XG4gICAgaWYodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyAmJiBkb2N1bWVudC5jb250YWlucyhjb21wb25lbnQuZWxlbWVudCkpe1xuICAgICAgICBzY2hlZHVsZShwcm9wZXJ0eSwgdXBkYXRlKTtcbiAgICB9ZWxzZXtcbiAgICAgICAgdXBkYXRlKCk7XG4gICAgfVxufTtcblxuZ2VuZXJpY0NvbXBvbmVudC5jcmVhdGVFbGVtZW50ID0gZnVuY3Rpb24odGFnTmFtZSl7XG4gICAgaWYodGFnTmFtZSBpbnN0YW5jZW9mIE5vZGUpe1xuICAgICAgICByZXR1cm4gdGFnTmFtZTtcbiAgICB9XG4gICAgcmV0dXJuIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnTmFtZSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGdlbmVyaWNDb21wb25lbnQ7Il19 | |
require=(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 flatMerge(a,b){ | |
if(!b || typeof b !== 'object'){ | |
b = {}; | |
} | |
if(!a || typeof a !== 'object'){ | |
a = new b.constructor(); | |
} | |
var result = new a.constructor(), | |
aKeys = Object.keys(a), | |
bKeys = Object.keys(b); | |
for(var i = 0; i < aKeys.length; i++){ | |
result[aKeys[i]] = a[aKeys[i]]; | |
} | |
for(var i = 0; i < bKeys.length; i++){ | |
result[bKeys[i]] = b[bKeys[i]]; | |
} | |
return result; | |
} | |
module.exports = flatMerge; | |
},{}],2:[function(require,module,exports){ | |
"use strict"; | |
/* global module, define */ | |
function mapEach(map, operation){ | |
var keys = map.keys(); | |
var next; | |
while(!(next = keys.next()).done) { | |
operation(map.get(next.value), next.value, map); | |
} | |
} | |
var Multimap = (function() { | |
var mapCtor; | |
if (typeof Map !== 'undefined') { | |
mapCtor = Map; | |
if (!Map.prototype.keys) { | |
Map.prototype.keys = function() { | |
var keys = []; | |
this.forEach(function(item, key) { | |
keys.push(key); | |
}); | |
return keys; | |
}; | |
} | |
} | |
function Multimap(iterable) { | |
var self = this; | |
self._map = mapCtor; | |
if (Multimap.Map) { | |
self._map = Multimap.Map; | |
} | |
self._ = self._map ? new self._map() : {}; | |
if (iterable) { | |
iterable.forEach(function(i) { | |
self.set(i[0], i[1]); | |
}); | |
} | |
} | |
/** | |
* @param {Object} key | |
* @return {Array} An array of values, undefined if no such a key; | |
*/ | |
Multimap.prototype.get = function(key) { | |
return this._map ? this._.get(key) : this._[key]; | |
}; | |
/** | |
* @param {Object} key | |
* @param {Object} val... | |
*/ | |
Multimap.prototype.set = function(key, val) { | |
var args = Array.prototype.slice.call(arguments); | |
key = args.shift(); | |
var entry = this.get(key); | |
if (!entry) { | |
entry = []; | |
if (this._map) | |
this._.set(key, entry); | |
else | |
this._[key] = entry; | |
} | |
Array.prototype.push.apply(entry, args); | |
return this; | |
}; | |
/** | |
* @param {Object} key | |
* @param {Object=} val | |
* @return {boolean} true if any thing changed | |
*/ | |
Multimap.prototype.delete = function(key, val) { | |
if (!this.has(key)) | |
return false; | |
if (arguments.length == 1) { | |
this._map ? (this._.delete(key)) : (delete this._[key]); | |
return true; | |
} else { | |
var entry = this.get(key); | |
var idx = entry.indexOf(val); | |
if (idx != -1) { | |
entry.splice(idx, 1); | |
return true; | |
} | |
} | |
return false; | |
}; | |
/** | |
* @param {Object} key | |
* @param {Object=} val | |
* @return {boolean} whether the map contains 'key' or 'key=>val' pair | |
*/ | |
Multimap.prototype.has = function(key, val) { | |
var hasKey = this._map ? this._.has(key) : this._.hasOwnProperty(key); | |
if (arguments.length == 1 || !hasKey) | |
return hasKey; | |
var entry = this.get(key) || []; | |
return entry.indexOf(val) != -1; | |
}; | |
/** | |
* @return {Array} all the keys in the map | |
*/ | |
Multimap.prototype.keys = function() { | |
if (this._map) | |
return makeIterator(this._.keys()); | |
return makeIterator(Object.keys(this._)); | |
}; | |
/** | |
* @return {Array} all the values in the map | |
*/ | |
Multimap.prototype.values = function() { | |
var vals = []; | |
this.forEachEntry(function(entry) { | |
Array.prototype.push.apply(vals, entry); | |
}); | |
return makeIterator(vals); | |
}; | |
/** | |
* | |
*/ | |
Multimap.prototype.forEachEntry = function(iter) { | |
mapEach(this, iter); | |
}; | |
Multimap.prototype.forEach = function(iter) { | |
var self = this; | |
self.forEachEntry(function(entry, key) { | |
entry.forEach(function(item) { | |
iter(item, key, self); | |
}); | |
}); | |
}; | |
Multimap.prototype.clear = function() { | |
if (this._map) { | |
this._.clear(); | |
} else { | |
this._ = {}; | |
} | |
}; | |
Object.defineProperty( | |
Multimap.prototype, | |
"size", { | |
configurable: false, | |
enumerable: true, | |
get: function() { | |
var total = 0; | |
mapEach(this, function(value){ | |
total += value.length; | |
}); | |
return total; | |
} | |
}); | |
var safariNext; | |
try{ | |
safariNext = new Function('iterator', 'makeIterator', 'var keysArray = []; for(var key of iterator){keysArray.push(key);} return makeIterator(keysArray).next;'); | |
}catch(error){ | |
// for of not implemented; | |
} | |
function makeIterator(iterator){ | |
if(Array.isArray(iterator)){ | |
var nextIndex = 0; | |
return { | |
next: function(){ | |
return nextIndex < iterator.length ? | |
{value: iterator[nextIndex++], done: false} : | |
{done: true}; | |
} | |
}; | |
} | |
// Only an issue in safari | |
if(!iterator.next && safariNext){ | |
iterator.next = safariNext(iterator, makeIterator); | |
} | |
return iterator; | |
} | |
return Multimap; | |
})(); | |
if(typeof exports === 'object' && module && module.exports) | |
module.exports = Multimap; | |
else if(typeof define === 'function' && define.amd) | |
define(function() { return Multimap; }); | |
},{}],"fastn/listComponent":[function(require,module,exports){ | |
var MultiMap = require('multimap'), | |
merge = require('flat-merge'); | |
MultiMap.Map = Map; | |
function each(value, fn){ | |
if(!value || typeof value !== 'object'){ | |
return; | |
} | |
if(Array.isArray(value)){ | |
for(var i = 0; i < value.length; i++){ | |
fn(value[i], i) | |
} | |
}else{ | |
for(var key in value){ | |
fn(value[key], key); | |
} | |
} | |
} | |
function keyFor(object, value){ | |
if(!object || typeof object !== 'object'){ | |
return false; | |
} | |
if(Array.isArray(object)){ | |
var index = object.indexOf(value); | |
return index >=0 ? index : false; | |
} | |
for(var key in object){ | |
if(object[key] === value){ | |
return key; | |
} | |
} | |
return false; | |
} | |
module.exports = function(fastn, component, type, settings, children){ | |
if(fastn.components._generic){ | |
component.extend('_generic', settings, children); | |
}else{ | |
component.extend('_container', settings, children); | |
} | |
if(!('template' in settings)){ | |
console.warn('No "template" function was set for this templater component'); | |
} | |
var itemsMap = new MultiMap(), | |
dataMap = new WeakMap(), | |
lastTemplate, | |
existingItem = {}; | |
function updateItems(){ | |
var value = component.items(), | |
template = component.template(), | |
emptyTemplate = component.emptyTemplate(), | |
newTemplate = lastTemplate !== template; | |
var currentItems = merge(template ? value : []); | |
itemsMap.forEach(function(childComponent, item){ | |
var currentKey = keyFor(currentItems, item); | |
if(!newTemplate && currentKey !== false){ | |
currentItems[currentKey] = [existingItem, item, childComponent]; | |
}else{ | |
removeComponent(childComponent); | |
itemsMap.delete(item); | |
} | |
}); | |
var index = 0; | |
function updateItem(item, key){ | |
var child, | |
existing; | |
while(index < component._children.length && !component._children[index]._templated){ | |
index++; | |
} | |
if(Array.isArray(item) && item[0] === existingItem){ | |
existing = true; | |
child = item[2]; | |
item = item[1]; | |
} | |
var childModel; | |
if(!existing){ | |
childModel = new fastn.Model({ | |
item: item, | |
key: key | |
}); | |
child = fastn.toComponent(template(childModel, component.scope())); | |
if(!child){ | |
child = fastn('template'); | |
} | |
child._listItem = item; | |
child._templated = true; | |
dataMap.set(child, childModel); | |
itemsMap.set(item, child); | |
}else{ | |
childModel = dataMap.get(child); | |
childModel.set('key', key); | |
} | |
if(fastn.isComponent(child) && component._settings.attachTemplates !== false){ | |
child.attach(childModel, 2); | |
} | |
component.insert(child, index); | |
index++; | |
} | |
each(currentItems, updateItem); | |
lastTemplate = template; | |
if(index === 0 && emptyTemplate){ | |
var child = fastn.toComponent(emptyTemplate(component.scope())); | |
if(!child){ | |
child = fastn('template'); | |
} | |
child._templated = true; | |
itemsMap.set({}, child); | |
component.insert(child); | |
} | |
} | |
function removeComponent(childComponent){ | |
component.remove(childComponent); | |
childComponent.destroy(); | |
} | |
component.setProperty('items', | |
fastn.property([], settings.itemChanges || 'type keys shallowStructure') | |
.on('change', updateItems) | |
); | |
component.setProperty('template', | |
fastn.property().on('change', updateItems) | |
); | |
component.setProperty('emptyTemplate', | |
fastn.property().on('change', updateItems) | |
); | |
return component; | |
}; | |
},{"flat-merge":1,"multimap":2}]},{},[]) | |
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIm5vZGVfbW9kdWxlcy9mbGF0LW1lcmdlL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL211bHRpbWFwL2luZGV4LmpzIiwibGlzdENvbXBvbmVudC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4TkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsImZ1bmN0aW9uIGZsYXRNZXJnZShhLGIpe1xuICAgIGlmKCFiIHx8IHR5cGVvZiBiICE9PSAnb2JqZWN0Jyl7XG4gICAgICAgIGIgPSB7fTtcbiAgICB9XG5cbiAgICBpZighYSB8fCB0eXBlb2YgYSAhPT0gJ29iamVjdCcpe1xuICAgICAgICBhID0gbmV3IGIuY29uc3RydWN0b3IoKTtcbiAgICB9XG5cbiAgICB2YXIgcmVzdWx0ID0gbmV3IGEuY29uc3RydWN0b3IoKSxcbiAgICAgICAgYUtleXMgPSBPYmplY3Qua2V5cyhhKSxcbiAgICAgICAgYktleXMgPSBPYmplY3Qua2V5cyhiKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhS2V5cy5sZW5ndGg7IGkrKyl7XG4gICAgICAgIHJlc3VsdFthS2V5c1tpXV0gPSBhW2FLZXlzW2ldXTtcbiAgICB9XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYktleXMubGVuZ3RoOyBpKyspe1xuICAgICAgICByZXN1bHRbYktleXNbaV1dID0gYltiS2V5c1tpXV07XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmbGF0TWVyZ2U7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbi8qIGdsb2JhbCBtb2R1bGUsIGRlZmluZSAqL1xuXG5mdW5jdGlvbiBtYXBFYWNoKG1hcCwgb3BlcmF0aW9uKXtcbiAgdmFyIGtleXMgPSBtYXAua2V5cygpO1xuICB2YXIgbmV4dDtcbiAgd2hpbGUoIShuZXh0ID0ga2V5cy5uZXh0KCkpLmRvbmUpIHtcbiAgICBvcGVyYXRpb24obWFwLmdldChuZXh0LnZhbHVlKSwgbmV4dC52YWx1ZSwgbWFwKTtcbiAgfVxufVxuXG52YXIgTXVsdGltYXAgPSAoZnVuY3Rpb24oKSB7XG4gIHZhciBtYXBDdG9yO1xuICBpZiAodHlwZW9mIE1hcCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBtYXBDdG9yID0gTWFwO1xuXG4gICAgaWYgKCFNYXAucHJvdG90eXBlLmtleXMpIHtcbiAgICAgIE1hcC5wcm90b3R5cGUua2V5cyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIga2V5cyA9IFtdO1xuICAgICAgICB0aGlzLmZvckVhY2goZnVuY3Rpb24oaXRlbSwga2V5KSB7XG4gICAgICAgICAga2V5cy5wdXNoKGtleSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4ga2V5cztcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gTXVsdGltYXAoaXRlcmFibGUpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICBzZWxmLl9tYXAgPSBtYXBDdG9yO1xuXG4gICAgaWYgKE11bHRpbWFwLk1hcCkge1xuICAgICAgc2VsZi5fbWFwID0gTXVsdGltYXAuTWFwO1xuICAgIH1cblxuICAgIHNlbGYuXyA9IHNlbGYuX21hcCA/IG5ldyBzZWxmLl9tYXAoKSA6IHt9O1xuXG4gICAgaWYgKGl0ZXJhYmxlKSB7XG4gICAgICBpdGVyYWJsZS5mb3JFYWNoKGZ1bmN0aW9uKGkpIHtcbiAgICAgICAgc2VsZi5zZXQoaVswXSwgaVsxXSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGtleVxuICAgKiBAcmV0dXJuIHtBcnJheX0gQW4gYXJyYXkgb2YgdmFsdWVzLCB1bmRlZmluZWQgaWYgbm8gc3VjaCBhIGtleTtcbiAgICovXG4gIE11bHRpbWFwLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbihrZXkpIHtcbiAgICByZXR1cm4gdGhpcy5fbWFwID8gdGhpcy5fLmdldChrZXkpIDogdGhpcy5fW2tleV07XG4gIH07XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBrZXlcbiAgICogQHBhcmFtIHtPYmplY3R9IHZhbC4uLlxuICAgKi9cbiAgTXVsdGltYXAucHJvdG90eXBlLnNldCA9IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuXG4gICAga2V5ID0gYXJncy5zaGlmdCgpO1xuXG4gICAgdmFyIGVudHJ5ID0gdGhpcy5nZXQoa2V5KTtcbiAgICBpZiAoIWVudHJ5KSB7XG4gICAgICBlbnRyeSA9IFtdO1xuICAgICAgaWYgKHRoaXMuX21hcClcbiAgICAgICAgdGhpcy5fLnNldChrZXksIGVudHJ5KTtcbiAgICAgIGVsc2VcbiAgICAgICAgdGhpcy5fW2tleV0gPSBlbnRyeTtcbiAgICB9XG5cbiAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShlbnRyeSwgYXJncyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBrZXlcbiAgICogQHBhcmFtIHtPYmplY3Q9fSB2YWxcbiAgICogQHJldHVybiB7Ym9vbGVhbn0gdHJ1ZSBpZiBhbnkgdGhpbmcgY2hhbmdlZFxuICAgKi9cbiAgTXVsdGltYXAucHJvdG90eXBlLmRlbGV0ZSA9IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgaWYgKCF0aGlzLmhhcyhrZXkpKVxuICAgICAgcmV0dXJuIGZhbHNlO1xuXG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT0gMSkge1xuICAgICAgdGhpcy5fbWFwID8gKHRoaXMuXy5kZWxldGUoa2V5KSkgOiAoZGVsZXRlIHRoaXMuX1trZXldKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgZW50cnkgPSB0aGlzLmdldChrZXkpO1xuICAgICAgdmFyIGlkeCA9IGVudHJ5LmluZGV4T2YodmFsKTtcbiAgICAgIGlmIChpZHggIT0gLTEpIHtcbiAgICAgICAgZW50cnkuc3BsaWNlKGlkeCwgMSk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGtleVxuICAgKiBAcGFyYW0ge09iamVjdD19IHZhbFxuICAgKiBAcmV0dXJuIHtib29sZWFufSB3aGV0aGVyIHRoZSBtYXAgY29udGFpbnMgJ2tleScgb3IgJ2tleT0+dmFsJyBwYWlyXG4gICAqL1xuICBNdWx0aW1hcC5wcm90b3R5cGUuaGFzID0gZnVuY3Rpb24oa2V5LCB2YWwpIHtcbiAgICB2YXIgaGFzS2V5ID0gdGhpcy5fbWFwID8gdGhpcy5fLmhhcyhrZXkpIDogdGhpcy5fLmhhc093blByb3BlcnR5KGtleSk7XG5cbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PSAxIHx8ICFoYXNLZXkpXG4gICAgICByZXR1cm4gaGFzS2V5O1xuXG4gICAgdmFyIGVudHJ5ID0gdGhpcy5nZXQoa2V5KSB8fCBbXTtcbiAgICByZXR1cm4gZW50cnkuaW5kZXhPZih2YWwpICE9IC0xO1xuICB9O1xuXG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0FycmF5fSBhbGwgdGhlIGtleXMgaW4gdGhlIG1hcFxuICAgKi9cbiAgTXVsdGltYXAucHJvdG90eXBlLmtleXMgPSBmdW5jdGlvbigpIHtcbiAgICBpZiAodGhpcy5fbWFwKVxuICAgICAgcmV0dXJuIG1ha2VJdGVyYXRvcih0aGlzLl8ua2V5cygpKTtcblxuICAgIHJldHVybiBtYWtlSXRlcmF0b3IoT2JqZWN0LmtleXModGhpcy5fKSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0FycmF5fSBhbGwgdGhlIHZhbHVlcyBpbiB0aGUgbWFwXG4gICAqL1xuICBNdWx0aW1hcC5wcm90b3R5cGUudmFsdWVzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHZhbHMgPSBbXTtcbiAgICB0aGlzLmZvckVhY2hFbnRyeShmdW5jdGlvbihlbnRyeSkge1xuICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkodmFscywgZW50cnkpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIG1ha2VJdGVyYXRvcih2YWxzKTtcbiAgfTtcblxuICAvKipcbiAgICpcbiAgICovXG4gIE11bHRpbWFwLnByb3RvdHlwZS5mb3JFYWNoRW50cnkgPSBmdW5jdGlvbihpdGVyKSB7XG4gICAgbWFwRWFjaCh0aGlzLCBpdGVyKTtcbiAgfTtcblxuICBNdWx0aW1hcC5wcm90b3R5cGUuZm9yRWFjaCA9IGZ1bmN0aW9uKGl0ZXIpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgc2VsZi5mb3JFYWNoRW50cnkoZnVuY3Rpb24oZW50cnksIGtleSkge1xuICAgICAgZW50cnkuZm9yRWFjaChmdW5jdGlvbihpdGVtKSB7XG4gICAgICAgIGl0ZXIoaXRlbSwga2V5LCBzZWxmKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG5cbiAgTXVsdGltYXAucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24oKSB7XG4gICAgaWYgKHRoaXMuX21hcCkge1xuICAgICAgdGhpcy5fLmNsZWFyKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuXyA9IHt9O1xuICAgIH1cbiAgfTtcblxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoXG4gICAgTXVsdGltYXAucHJvdG90eXBlLFxuICAgIFwic2l6ZVwiLCB7XG4gICAgICBjb25maWd1cmFibGU6IGZhbHNlLFxuICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB0b3RhbCA9IDA7XG5cbiAgICAgICAgbWFwRWFjaCh0aGlzLCBmdW5jdGlvbih2YWx1ZSl7XG4gICAgICAgICAgdG90YWwgKz0gdmFsdWUubGVuZ3RoO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gdG90YWw7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgdmFyIHNhZmFyaU5leHQ7XG5cbiAgdHJ5e1xuICAgIHNhZmFyaU5leHQgPSBuZXcgRnVuY3Rpb24oJ2l0ZXJhdG9yJywgJ21ha2VJdGVyYXRvcicsICd2YXIga2V5c0FycmF5ID0gW107IGZvcih2YXIga2V5IG9mIGl0ZXJhdG9yKXtrZXlzQXJyYXkucHVzaChrZXkpO30gcmV0dXJuIG1ha2VJdGVyYXRvcihrZXlzQXJyYXkpLm5leHQ7Jyk7XG4gIH1jYXRjaChlcnJvcil7XG4gICAgLy8gZm9yIG9mIG5vdCBpbXBsZW1lbnRlZDtcbiAgfVxuXG4gIGZ1bmN0aW9uIG1ha2VJdGVyYXRvcihpdGVyYXRvcil7XG4gICAgaWYoQXJyYXkuaXNBcnJheShpdGVyYXRvcikpe1xuICAgICAgdmFyIG5leHRJbmRleCA9IDA7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIG5leHQ6IGZ1bmN0aW9uKCl7XG4gICAgICAgICAgcmV0dXJuIG5leHRJbmRleCA8IGl0ZXJhdG9yLmxlbmd0aCA/XG4gICAgICAgICAgICB7dmFsdWU6IGl0ZXJhdG9yW25leHRJbmRleCsrXSwgZG9uZTogZmFsc2V9IDpcbiAgICAgICAgICB7ZG9uZTogdHJ1ZX07XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gT25seSBhbiBpc3N1ZSBpbiBzYWZhcmlcbiAgICBpZighaXRlcmF0b3IubmV4dCAmJiBzYWZhcmlOZXh0KXtcbiAgICAgIGl0ZXJhdG9yLm5leHQgPSBzYWZhcmlOZXh0KGl0ZXJhdG9yLCBtYWtlSXRlcmF0b3IpO1xuICAgIH1cblxuICAgIHJldHVybiBpdGVyYXRvcjtcbiAgfVxuXG4gIHJldHVybiBNdWx0aW1hcDtcbn0pKCk7XG5cblxuaWYodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIG1vZHVsZSAmJiBtb2R1bGUuZXhwb3J0cylcbiAgbW9kdWxlLmV4cG9ydHMgPSBNdWx0aW1hcDtcbmVsc2UgaWYodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKVxuICBkZWZpbmUoZnVuY3Rpb24oKSB7IHJldHVybiBNdWx0aW1hcDsgfSk7XG4iLCJ2YXIgTXVsdGlNYXAgPSByZXF1aXJlKCdtdWx0aW1hcCcpLFxuICAgIG1lcmdlID0gcmVxdWlyZSgnZmxhdC1tZXJnZScpO1xuXG5NdWx0aU1hcC5NYXAgPSBNYXA7XG5cbmZ1bmN0aW9uIGVhY2godmFsdWUsIGZuKXtcbiAgICBpZighdmFsdWUgfHwgdHlwZW9mIHZhbHVlICE9PSAnb2JqZWN0Jyl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZihBcnJheS5pc0FycmF5KHZhbHVlKSl7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB2YWx1ZS5sZW5ndGg7IGkrKyl7XG4gICAgICAgICAgICBmbih2YWx1ZVtpXSwgaSlcbiAgICAgICAgfVxuICAgIH1lbHNle1xuICAgICAgICBmb3IodmFyIGtleSBpbiB2YWx1ZSl7XG4gICAgICAgICAgICBmbih2YWx1ZVtrZXldLCBrZXkpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBrZXlGb3Iob2JqZWN0LCB2YWx1ZSl7XG4gICAgaWYoIW9iamVjdCB8fCB0eXBlb2Ygb2JqZWN0ICE9PSAnb2JqZWN0Jyl7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZihBcnJheS5pc0FycmF5KG9iamVjdCkpe1xuICAgICAgICB2YXIgaW5kZXggPSBvYmplY3QuaW5kZXhPZih2YWx1ZSk7XG4gICAgICAgIHJldHVybiBpbmRleCA+PTAgPyBpbmRleCA6IGZhbHNlO1xuICAgIH1cblxuICAgIGZvcih2YXIga2V5IGluIG9iamVjdCl7XG4gICAgICAgIGlmKG9iamVjdFtrZXldID09PSB2YWx1ZSl7XG4gICAgICAgICAgICByZXR1cm4ga2V5O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGZhc3RuLCBjb21wb25lbnQsIHR5cGUsIHNldHRpbmdzLCBjaGlsZHJlbil7XG5cbiAgICBpZihmYXN0bi5jb21wb25lbnRzLl9nZW5lcmljKXtcbiAgICAgICAgY29tcG9uZW50LmV4dGVuZCgnX2dlbmVyaWMnLCBzZXR0aW5ncywgY2hpbGRyZW4pO1xuICAgIH1lbHNle1xuICAgICAgICBjb21wb25lbnQuZXh0ZW5kKCdfY29udGFpbmVyJywgc2V0dGluZ3MsIGNoaWxkcmVuKTtcbiAgICB9XG5cbiAgICBpZighKCd0ZW1wbGF0ZScgaW4gc2V0dGluZ3MpKXtcbiAgICAgICAgY29uc29sZS53YXJuKCdObyBcInRlbXBsYXRlXCIgZnVuY3Rpb24gd2FzIHNldCBmb3IgdGhpcyB0ZW1wbGF0ZXIgY29tcG9uZW50Jyk7XG4gICAgfVxuXG4gICAgdmFyIGl0ZW1zTWFwID0gbmV3IE11bHRpTWFwKCksXG4gICAgICAgIGRhdGFNYXAgPSBuZXcgV2Vha01hcCgpLFxuICAgICAgICBsYXN0VGVtcGxhdGUsXG4gICAgICAgIGV4aXN0aW5nSXRlbSA9IHt9O1xuXG4gICAgZnVuY3Rpb24gdXBkYXRlSXRlbXMoKXtcbiAgICAgICAgdmFyIHZhbHVlID0gY29tcG9uZW50Lml0ZW1zKCksXG4gICAgICAgICAgICB0ZW1wbGF0ZSA9IGNvbXBvbmVudC50ZW1wbGF0ZSgpLFxuICAgICAgICAgICAgZW1wdHlUZW1wbGF0ZSA9IGNvbXBvbmVudC5lbXB0eVRlbXBsYXRlKCksXG4gICAgICAgICAgICBuZXdUZW1wbGF0ZSA9IGxhc3RUZW1wbGF0ZSAhPT0gdGVtcGxhdGU7XG5cbiAgICAgICAgdmFyIGN1cnJlbnRJdGVtcyA9IG1lcmdlKHRlbXBsYXRlID8gdmFsdWUgOiBbXSk7XG5cbiAgICAgICAgaXRlbXNNYXAuZm9yRWFjaChmdW5jdGlvbihjaGlsZENvbXBvbmVudCwgaXRlbSl7XG4gICAgICAgICAgICB2YXIgY3VycmVudEtleSA9IGtleUZvcihjdXJyZW50SXRlbXMsIGl0ZW0pO1xuXG4gICAgICAgICAgICBpZighbmV3VGVtcGxhdGUgJiYgY3VycmVudEtleSAhPT0gZmFsc2Upe1xuICAgICAgICAgICAgICAgIGN1cnJlbnRJdGVtc1tjdXJyZW50S2V5XSA9IFtleGlzdGluZ0l0ZW0sIGl0ZW0sIGNoaWxkQ29tcG9uZW50XTtcbiAgICAgICAgICAgIH1lbHNle1xuICAgICAgICAgICAgICAgIHJlbW92ZUNvbXBvbmVudChjaGlsZENvbXBvbmVudCk7XG4gICAgICAgICAgICAgICAgaXRlbXNNYXAuZGVsZXRlKGl0ZW0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICB2YXIgaW5kZXggPSAwO1xuXG4gICAgICAgIGZ1bmN0aW9uIHVwZGF0ZUl0ZW0oaXRlbSwga2V5KXtcbiAgICAgICAgICAgIHZhciBjaGlsZCxcbiAgICAgICAgICAgICAgICBleGlzdGluZztcblxuICAgICAgICAgICAgd2hpbGUoaW5kZXggPCBjb21wb25lbnQuX2NoaWxkcmVuLmxlbmd0aCAmJiAhY29tcG9uZW50Ll9jaGlsZHJlbltpbmRleF0uX3RlbXBsYXRlZCl7XG4gICAgICAgICAgICAgICAgaW5kZXgrKztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoQXJyYXkuaXNBcnJheShpdGVtKSAmJiBpdGVtWzBdID09PSBleGlzdGluZ0l0ZW0pe1xuICAgICAgICAgICAgICAgIGV4aXN0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBjaGlsZCA9IGl0ZW1bMl07XG4gICAgICAgICAgICAgICAgaXRlbSA9IGl0ZW1bMV07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBjaGlsZE1vZGVsO1xuXG4gICAgICAgICAgICBpZighZXhpc3Rpbmcpe1xuICAgICAgICAgICAgICAgIGNoaWxkTW9kZWwgPSBuZXcgZmFzdG4uTW9kZWwoe1xuICAgICAgICAgICAgICAgICAgICBpdGVtOiBpdGVtLFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgY2hpbGQgPSBmYXN0bi50b0NvbXBvbmVudCh0ZW1wbGF0ZShjaGlsZE1vZGVsLCBjb21wb25lbnQuc2NvcGUoKSkpO1xuICAgICAgICAgICAgICAgIGlmKCFjaGlsZCl7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkID0gZmFzdG4oJ3RlbXBsYXRlJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNoaWxkLl9saXN0SXRlbSA9IGl0ZW07XG4gICAgICAgICAgICAgICAgY2hpbGQuX3RlbXBsYXRlZCA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICBkYXRhTWFwLnNldChjaGlsZCwgY2hpbGRNb2RlbCk7XG4gICAgICAgICAgICAgICAgaXRlbXNNYXAuc2V0KGl0ZW0sIGNoaWxkKTtcbiAgICAgICAgICAgIH1lbHNle1xuICAgICAgICAgICAgICAgIGNoaWxkTW9kZWwgPSBkYXRhTWFwLmdldChjaGlsZCk7XG4gICAgICAgICAgICAgICAgY2hpbGRNb2RlbC5zZXQoJ2tleScsIGtleSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGZhc3RuLmlzQ29tcG9uZW50KGNoaWxkKSAmJiBjb21wb25lbnQuX3NldHRpbmdzLmF0dGFjaFRlbXBsYXRlcyAhPT0gZmFsc2Upe1xuICAgICAgICAgICAgICAgIGNoaWxkLmF0dGFjaChjaGlsZE1vZGVsLCAyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29tcG9uZW50Lmluc2VydChjaGlsZCwgaW5kZXgpO1xuICAgICAgICAgICAgaW5kZXgrKztcbiAgICAgICAgfVxuXG4gICAgICAgIGVhY2goY3VycmVudEl0ZW1zLCB1cGRhdGVJdGVtKTtcblxuICAgICAgICBsYXN0VGVtcGxhdGUgPSB0ZW1wbGF0ZTtcblxuICAgICAgICBpZihpbmRleCA9PT0gMCAmJiBlbXB0eVRlbXBsYXRlKXtcbiAgICAgICAgICAgIHZhciBjaGlsZCA9IGZhc3RuLnRvQ29tcG9uZW50KGVtcHR5VGVtcGxhdGUoY29tcG9uZW50LnNjb3BlKCkpKTtcbiAgICAgICAgICAgIGlmKCFjaGlsZCl7XG4gICAgICAgICAgICAgICAgY2hpbGQgPSBmYXN0bigndGVtcGxhdGUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNoaWxkLl90ZW1wbGF0ZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBpdGVtc01hcC5zZXQoe30sIGNoaWxkKTtcblxuICAgICAgICAgICAgY29tcG9uZW50Lmluc2VydChjaGlsZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZW1vdmVDb21wb25lbnQoY2hpbGRDb21wb25lbnQpe1xuICAgICAgICBjb21wb25lbnQucmVtb3ZlKGNoaWxkQ29tcG9uZW50KTtcbiAgICAgICAgY2hpbGRDb21wb25lbnQuZGVzdHJveSgpO1xuICAgIH1cblxuICAgIGNvbXBvbmVudC5zZXRQcm9wZXJ0eSgnaXRlbXMnLFxuICAgICAgICBmYXN0bi5wcm9wZXJ0eShbXSwgc2V0dGluZ3MuaXRlbUNoYW5nZXMgfHwgJ3R5cGUga2V5cyBzaGFsbG93U3RydWN0dXJlJylcbiAgICAgICAgICAgIC5vbignY2hhbmdlJywgdXBkYXRlSXRlbXMpXG4gICAgKTtcblxuICAgIGNvbXBvbmVudC5zZXRQcm9wZXJ0eSgndGVtcGxhdGUnLFxuICAgICAgICBmYXN0bi5wcm9wZXJ0eSgpLm9uKCdjaGFuZ2UnLCB1cGRhdGVJdGVtcylcbiAgICApO1xuXG4gICAgY29tcG9uZW50LnNldFByb3BlcnR5KCdlbXB0eVRlbXBsYXRlJyxcbiAgICAgICAgZmFzdG4ucHJvcGVydHkoKS5vbignY2hhbmdlJywgdXBkYXRlSXRlbXMpXG4gICAgKTtcblxuICAgIHJldHVybiBjb21wb25lbnQ7XG59OyJdfQ== | |
require=(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){ | |
/* | |
Leaflet, a JavaScript library for mobile-friendly interactive maps. http://leafletjs.com | |
(c) 2010-2013, Vladimir Agafonkin | |
(c) 2010-2011, CloudMade | |
*/ | |
(function (window, document, undefined) { | |
var oldL = window.L, | |
L = {}; | |
L.version = '0.7.7'; | |
// define Leaflet for Node module pattern loaders, including Browserify | |
if (typeof module === 'object' && typeof module.exports === 'object') { | |
module.exports = L; | |
// define Leaflet as an AMD module | |
} else if (typeof define === 'function' && define.amd) { | |
define(L); | |
} | |
// define Leaflet as a global L variable, saving the original L to restore later if needed | |
L.noConflict = function () { | |
window.L = oldL; | |
return this; | |
}; | |
window.L = L; | |
/* | |
* L.Util contains various utility functions used throughout Leaflet code. | |
*/ | |
L.Util = { | |
extend: function (dest) { // (Object[, Object, ...]) -> | |
var sources = Array.prototype.slice.call(arguments, 1), | |
i, j, len, src; | |
for (j = 0, len = sources.length; j < len; j++) { | |
src = sources[j] || {}; | |
for (i in src) { | |
if (src.hasOwnProperty(i)) { | |
dest[i] = src[i]; | |
} | |
} | |
} | |
return dest; | |
}, | |
bind: function (fn, obj) { // (Function, Object) -> Function | |
var args = arguments.length > 2 ? Array.prototype.slice.call(arguments, 2) : null; | |
return function () { | |
return fn.apply(obj, args || arguments); | |
}; | |
}, | |
stamp: (function () { | |
var lastId = 0, | |
key = '_leaflet_id'; | |
return function (obj) { | |
obj[key] = obj[key] || ++lastId; | |
return obj[key]; | |
}; | |
}()), | |
invokeEach: function (obj, method, context) { | |
var i, args; | |
if (typeof obj === 'object') { | |
args = Array.prototype.slice.call(arguments, 3); | |
for (i in obj) { | |
method.apply(context, [i, obj[i]].concat(args)); | |
} | |
return true; | |
} | |
return false; | |
}, | |
limitExecByInterval: function (fn, time, context) { | |
var lock, execOnUnlock; | |
return function wrapperFn() { | |
var args = arguments; | |
if (lock) { | |
execOnUnlock = true; | |
return; | |
} | |
lock = true; | |
setTimeout(function () { | |
lock = false; | |
if (execOnUnlock) { | |
wrapperFn.apply(context, args); | |
execOnUnlock = false; | |
} | |
}, time); | |
fn.apply(context, args); | |
}; | |
}, | |
falseFn: function () { | |
return false; | |
}, | |
formatNum: function (num, digits) { | |
var pow = Math.pow(10, digits || 5); | |
return Math.round(num * pow) / pow; | |
}, | |
trim: function (str) { | |
return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); | |
}, | |
splitWords: function (str) { | |
return L.Util.trim(str).split(/\s+/); | |
}, | |
setOptions: function (obj, options) { | |
obj.options = L.extend({}, obj.options, options); | |
return obj.options; | |
}, | |
getParamString: function (obj, existingUrl, uppercase) { | |
var params = []; | |
for (var i in obj) { | |
params.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i])); | |
} | |
return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&'); | |
}, | |
template: function (str, data) { | |
return str.replace(/\{ *([\w_]+) *\}/g, function (str, key) { | |
var value = data[key]; | |
if (value === undefined) { | |
throw new Error('No value provided for variable ' + str); | |
} else if (typeof value === 'function') { | |
value = value(data); | |
} | |
return value; | |
}); | |
}, | |
isArray: Array.isArray || function (obj) { | |
return (Object.prototype.toString.call(obj) === '[object Array]'); | |
}, | |
emptyImageUrl: 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=' | |
}; | |
(function () { | |
// inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/ | |
function getPrefixed(name) { | |
var i, fn, | |
prefixes = ['webkit', 'moz', 'o', 'ms']; | |
for (i = 0; i < prefixes.length && !fn; i++) { | |
fn = window[prefixes[i] + name]; | |
} | |
return fn; | |
} | |
var lastTime = 0; | |
function timeoutDefer(fn) { | |
var time = +new Date(), | |
timeToCall = Math.max(0, 16 - (time - lastTime)); | |
lastTime = time + timeToCall; | |
return window.setTimeout(fn, timeToCall); | |
} | |
var requestFn = window.requestAnimationFrame || | |
getPrefixed('RequestAnimationFrame') || timeoutDefer; | |
var cancelFn = window.cancelAnimationFrame || | |
getPrefixed('CancelAnimationFrame') || | |
getPrefixed('CancelRequestAnimationFrame') || | |
function (id) { window.clearTimeout(id); }; | |
L.Util.requestAnimFrame = function (fn, context, immediate, element) { | |
fn = L.bind(fn, context); | |
if (immediate && requestFn === timeoutDefer) { | |
fn(); | |
} else { | |
return requestFn.call(window, fn, element); | |
} | |
}; | |
L.Util.cancelAnimFrame = function (id) { | |
if (id) { | |
cancelFn.call(window, id); | |
} | |
}; | |
}()); | |
// shortcuts for most used utility functions | |
L.extend = L.Util.extend; | |
L.bind = L.Util.bind; | |
L.stamp = L.Util.stamp; | |
L.setOptions = L.Util.setOptions; | |
/* | |
* L.Class powers the OOP facilities of the library. | |
* Thanks to John Resig and Dean Edwards for inspiration! | |
*/ | |
L.Class = function () {}; | |
L.Class.extend = function (props) { | |
// extended class with the new prototype | |
var NewClass = function () { | |
// call the constructor | |
if (this.initialize) { | |
this.initialize.apply(this, arguments); | |
} | |
// call all constructor hooks | |
if (this._initHooks) { | |
this.callInitHooks(); | |
} | |
}; | |
// instantiate class without calling constructor | |
var F = function () {}; | |
F.prototype = this.prototype; | |
var proto = new F(); | |
proto.constructor = NewClass; | |
NewClass.prototype = proto; | |
//inherit parent's statics | |
for (var i in this) { | |
if (this.hasOwnProperty(i) && i !== 'prototype') { | |
NewClass[i] = this[i]; | |
} | |
} | |
// mix static properties into the class | |
if (props.statics) { | |
L.extend(NewClass, props.statics); | |
delete props.statics; | |
} | |
// mix includes into the prototype | |
if (props.includes) { | |
L.Util.extend.apply(null, [proto].concat(props.includes)); | |
delete props.includes; | |
} | |
// merge options | |
if (props.options && proto.options) { | |
props.options = L.extend({}, proto.options, props.options); | |
} | |
// mix given properties into the prototype | |
L.extend(proto, props); | |
proto._initHooks = []; | |
var parent = this; | |
// jshint camelcase: false | |
NewClass.__super__ = parent.prototype; | |
// add method for calling all hooks | |
proto.callInitHooks = function () { | |
if (this._initHooksCalled) { return; } | |
if (parent.prototype.callInitHooks) { | |
parent.prototype.callInitHooks.call(this); | |
} | |
this._initHooksCalled = true; | |
for (var i = 0, len = proto._initHooks.length; i < len; i++) { | |
proto._initHooks[i].call(this); | |
} | |
}; | |
return NewClass; | |
}; | |
// method for adding properties to prototype | |
L.Class.include = function (props) { | |
L.extend(this.prototype, props); | |
}; | |
// merge new default options to the Class | |
L.Class.mergeOptions = function (options) { | |
L.extend(this.prototype.options, options); | |
}; | |
// add a constructor hook | |
L.Class.addInitHook = function (fn) { // (Function) || (String, args...) | |
var args = Array.prototype.slice.call(arguments, 1); | |
var init = typeof fn === 'function' ? fn : function () { | |
this[fn].apply(this, args); | |
}; | |
this.prototype._initHooks = this.prototype._initHooks || []; | |
this.prototype._initHooks.push(init); | |
}; | |
/* | |
* L.Mixin.Events is used to add custom events functionality to Leaflet classes. | |
*/ | |
var eventsKey = '_leaflet_events'; | |
L.Mixin = {}; | |
L.Mixin.Events = { | |
addEventListener: function (types, fn, context) { // (String, Function[, Object]) or (Object[, Object]) | |
// types can be a map of types/handlers | |
if (L.Util.invokeEach(types, this.addEventListener, this, fn, context)) { return this; } | |
var events = this[eventsKey] = this[eventsKey] || {}, | |
contextId = context && context !== this && L.stamp(context), | |
i, len, event, type, indexKey, indexLenKey, typeIndex; | |
// types can be a string of space-separated words | |
types = L.Util.splitWords(types); | |
for (i = 0, len = types.length; i < len; i++) { | |
event = { | |
action: fn, | |
context: context || this | |
}; | |
type = types[i]; | |
if (contextId) { | |
// store listeners of a particular context in a separate hash (if it has an id) | |
// gives a major performance boost when removing thousands of map layers | |
indexKey = type + '_idx'; | |
indexLenKey = indexKey + '_len'; | |
typeIndex = events[indexKey] = events[indexKey] || {}; | |
if (!typeIndex[contextId]) { | |
typeIndex[contextId] = []; | |
// keep track of the number of keys in the index to quickly check if it's empty | |
events[indexLenKey] = (events[indexLenKey] || 0) + 1; | |
} | |
typeIndex[contextId].push(event); | |
} else { | |
events[type] = events[type] || []; | |
events[type].push(event); | |
} | |
} | |
return this; | |
}, | |
hasEventListeners: function (type) { // (String) -> Boolean | |
var events = this[eventsKey]; | |
return !!events && ((type in events && events[type].length > 0) || | |
(type + '_idx' in events && events[type + '_idx_len'] > 0)); | |
}, | |
removeEventListener: function (types, fn, context) { // ([String, Function, Object]) or (Object[, Object]) | |
if (!this[eventsKey]) { | |
return this; | |
} | |
if (!types) { | |
return this.clearAllEventListeners(); | |
} | |
if (L.Util.invokeEach(types, this.removeEventListener, this, fn, context)) { return this; } | |
var events = this[eventsKey], | |
contextId = context && context !== this && L.stamp(context), | |
i, len, type, listeners, j, indexKey, indexLenKey, typeIndex, removed; | |
types = L.Util.splitWords(types); | |
for (i = 0, len = types.length; i < len; i++) { | |
type = types[i]; | |
indexKey = type + '_idx'; | |
indexLenKey = indexKey + '_len'; | |
typeIndex = events[indexKey]; | |
if (!fn) { | |
// clear all listeners for a type if function isn't specified | |
delete events[type]; | |
delete events[indexKey]; | |
delete events[indexLenKey]; | |
} else { | |
listeners = contextId && typeIndex ? typeIndex[contextId] : events[type]; | |
if (listeners) { | |
for (j = listeners.length - 1; j >= 0; j--) { | |
if ((listeners[j].action === fn) && (!context || (listeners[j].context === context))) { | |
removed = listeners.splice(j, 1); | |
// set the old action to a no-op, because it is possible | |
// that the listener is being iterated over as part of a dispatch | |
removed[0].action = L.Util.falseFn; | |
} | |
} | |
if (context && typeIndex && (listeners.length === 0)) { | |
delete typeIndex[contextId]; | |
events[indexLenKey]--; | |
} | |
} | |
} | |
} | |
return this; | |
}, | |
clearAllEventListeners: function () { | |
delete this[eventsKey]; | |
return this; | |
}, | |
fireEvent: function (type, data) { // (String[, Object]) | |
if (!this.hasEventListeners(type)) { | |
return this; | |
} | |
var event = L.Util.extend({}, data, { type: type, target: this }); | |
var events = this[eventsKey], | |
listeners, i, len, typeIndex, contextId; | |
if (events[type]) { | |
// make sure adding/removing listeners inside other listeners won't cause infinite loop | |
listeners = events[type].slice(); | |
for (i = 0, len = listeners.length; i < len; i++) { | |
listeners[i].action.call(listeners[i].context, event); | |
} | |
} | |
// fire event for the context-indexed listeners as well | |
typeIndex = events[type + '_idx']; | |
for (contextId in typeIndex) { | |
listeners = typeIndex[contextId].slice(); | |
if (listeners) { | |
for (i = 0, len = listeners.length; i < len; i++) { | |
listeners[i].action.call(listeners[i].context, event); | |
} | |
} | |
} | |
return this; | |
}, | |
addOneTimeEventListener: function (types, fn, context) { | |
if (L.Util.invokeEach(types, this.addOneTimeEventListener, this, fn, context)) { return this; } | |
var handler = L.bind(function () { | |
this | |
.removeEventListener(types, fn, context) | |
.removeEventListener(types, handler, context); | |
}, this); | |
return this | |
.addEventListener(types, fn, context) | |
.addEventListener(types, handler, context); | |
} | |
}; | |
L.Mixin.Events.on = L.Mixin.Events.addEventListener; | |
L.Mixin.Events.off = L.Mixin.Events.removeEventListener; | |
L.Mixin.Events.once = L.Mixin.Events.addOneTimeEventListener; | |
L.Mixin.Events.fire = L.Mixin.Events.fireEvent; | |
/* | |
* L.Browser handles different browser and feature detections for internal Leaflet use. | |
*/ | |
(function () { | |
var ie = 'ActiveXObject' in window, | |
ielt9 = ie && !document.addEventListener, | |
// terrible browser detection to work around Safari / iOS / Android browser bugs | |
ua = navigator.userAgent.toLowerCase(), | |
webkit = ua.indexOf('webkit') !== -1, | |
chrome = ua.indexOf('chrome') !== -1, | |
phantomjs = ua.indexOf('phantom') !== -1, | |
android = ua.indexOf('android') !== -1, | |
android23 = ua.search('android [23]') !== -1, | |
gecko = ua.indexOf('gecko') !== -1, | |
mobile = typeof orientation !== undefined + '', | |
msPointer = !window.PointerEvent && window.MSPointerEvent, | |
pointer = (window.PointerEvent && window.navigator.pointerEnabled) || | |
msPointer, | |
retina = ('devicePixelRatio' in window && window.devicePixelRatio > 1) || | |
('matchMedia' in window && window.matchMedia('(min-resolution:144dpi)') && | |
window.matchMedia('(min-resolution:144dpi)').matches), | |
doc = document.documentElement, | |
ie3d = ie && ('transition' in doc.style), | |
webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23, | |
gecko3d = 'MozPerspective' in doc.style, | |
opera3d = 'OTransition' in doc.style, | |
any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d || opera3d) && !phantomjs; | |
var touch = !window.L_NO_TOUCH && !phantomjs && (pointer || 'ontouchstart' in window || | |
(window.DocumentTouch && document instanceof window.DocumentTouch)); | |
L.Browser = { | |
ie: ie, | |
ielt9: ielt9, | |
webkit: webkit, | |
gecko: gecko && !webkit && !window.opera && !ie, | |
android: android, | |
android23: android23, | |
chrome: chrome, | |
ie3d: ie3d, | |
webkit3d: webkit3d, | |
gecko3d: gecko3d, | |
opera3d: opera3d, | |
any3d: any3d, | |
mobile: mobile, | |
mobileWebkit: mobile && webkit, | |
mobileWebkit3d: mobile && webkit3d, | |
mobileOpera: mobile && window.opera, | |
touch: touch, | |
msPointer: msPointer, | |
pointer: pointer, | |
retina: retina | |
}; | |
}()); | |
/* | |
* L.Point represents a point with x and y coordinates. | |
*/ | |
L.Point = function (/*Number*/ x, /*Number*/ y, /*Boolean*/ round) { | |
this.x = (round ? Math.round(x) : x); | |
this.y = (round ? Math.round(y) : y); | |
}; | |
L.Point.prototype = { | |
clone: function () { | |
return new L.Point(this.x, this.y); | |
}, | |
// non-destructive, returns a new point | |
add: function (point) { | |
return this.clone()._add(L.point(point)); | |
}, | |
// destructive, used directly for performance in situations where it's safe to modify existing point | |
_add: function (point) { | |
this.x += point.x; | |
this.y += point.y; | |
return this; | |
}, | |
subtract: function (point) { | |
return this.clone()._subtract(L.point(point)); | |
}, | |
_subtract: function (point) { | |
this.x -= point.x; | |
this.y -= point.y; | |
return this; | |
}, | |
divideBy: function (num) { | |
return this.clone()._divideBy(num); | |
}, | |
_divideBy: function (num) { | |
this.x /= num; | |
this.y /= num; | |
return this; | |
}, | |
multiplyBy: function (num) { | |
return this.clone()._multiplyBy(num); | |
}, | |
_multiplyBy: function (num) { | |
this.x *= num; | |
this.y *= num; | |
return this; | |
}, | |
round: function () { | |
return this.clone()._round(); | |
}, | |
_round: function () { | |
this.x = Math.round(this.x); | |
this.y = Math.round(this.y); | |
return this; | |
}, | |
floor: function () { | |
return this.clone()._floor(); | |
}, | |
_floor: function () { | |
this.x = Math.floor(this.x); | |
this.y = Math.floor(this.y); | |
return this; | |
}, | |
distanceTo: function (point) { | |
point = L.point(point); | |
var x = point.x - this.x, | |
y = point.y - this.y; | |
return Math.sqrt(x * x + y * y); | |
}, | |
equals: function (point) { | |
point = L.point(point); | |
return point.x === this.x && | |
point.y === this.y; | |
}, | |
contains: function (point) { | |
point = L.point(point); | |
return Math.abs(point.x) <= Math.abs(this.x) && | |
Math.abs(point.y) <= Math.abs(this.y); | |
}, | |
toString: function () { | |
return 'Point(' + | |
L.Util.formatNum(this.x) + ', ' + | |
L.Util.formatNum(this.y) + ')'; | |
} | |
}; | |
L.point = function (x, y, round) { | |
if (x instanceof L.Point) { | |
return x; | |
} | |
if (L.Util.isArray(x)) { | |
return new L.Point(x[0], x[1]); | |
} | |
if (x === undefined || x === null) { | |
return x; | |
} | |
return new L.Point(x, y, round); | |
}; | |
/* | |
* L.Bounds represents a rectangular area on the screen in pixel coordinates. | |
*/ | |
L.Bounds = function (a, b) { //(Point, Point) or Point[] | |
if (!a) { return; } | |
var points = b ? [a, b] : a; | |
for (var i = 0, len = points.length; i < len; i++) { | |
this.extend(points[i]); | |
} | |
}; | |
L.Bounds.prototype = { | |
// extend the bounds to contain the given point | |
extend: function (point) { // (Point) | |
point = L.point(point); | |
if (!this.min && !this.max) { | |
this.min = point.clone(); | |
this.max = point.clone(); | |
} else { | |
this.min.x = Math.min(point.x, this.min.x); | |
this.max.x = Math.max(point.x, this.max.x); | |
this.min.y = Math.min(point.y, this.min.y); | |
this.max.y = Math.max(point.y, this.max.y); | |
} | |
return this; | |
}, | |
getCenter: function (round) { // (Boolean) -> Point | |
return new L.Point( | |
(this.min.x + this.max.x) / 2, | |
(this.min.y + this.max.y) / 2, round); | |
}, | |
getBottomLeft: function () { // -> Point | |
return new L.Point(this.min.x, this.max.y); | |
}, | |
getTopRight: function () { // -> Point | |
return new L.Point(this.max.x, this.min.y); | |
}, | |
getSize: function () { | |
return this.max.subtract(this.min); | |
}, | |
contains: function (obj) { // (Bounds) or (Point) -> Boolean | |
var min, max; | |
if (typeof obj[0] === 'number' || obj instanceof L.Point) { | |
obj = L.point(obj); | |
} else { | |
obj = L.bounds(obj); | |
} | |
if (obj instanceof L.Bounds) { | |
min = obj.min; | |
max = obj.max; | |
} else { | |
min = max = obj; | |
} | |
return (min.x >= this.min.x) && | |
(max.x <= this.max.x) && | |
(min.y >= this.min.y) && | |
(max.y <= this.max.y); | |
}, | |
intersects: function (bounds) { // (Bounds) -> Boolean | |
bounds = L.bounds(bounds); | |
var min = this.min, | |
max = this.max, | |
min2 = bounds.min, | |
max2 = bounds.max, | |
xIntersects = (max2.x >= min.x) && (min2.x <= max.x), | |
yIntersects = (max2.y >= min.y) && (min2.y <= max.y); | |
return xIntersects && yIntersects; | |
}, | |
isValid: function () { | |
return !!(this.min && this.max); | |
} | |
}; | |
L.bounds = function (a, b) { // (Bounds) or (Point, Point) or (Point[]) | |
if (!a || a instanceof L.Bounds) { | |
return a; | |
} | |
return new L.Bounds(a, b); | |
}; | |
/* | |
* L.Transformation is an utility class to perform simple point transformations through a 2d-matrix. | |
*/ | |
L.Transformation = function (a, b, c, d) { | |
this._a = a; | |
this._b = b; | |
this._c = c; | |
this._d = d; | |
}; | |
L.Transformation.prototype = { | |
transform: function (point, scale) { // (Point, Number) -> Point | |
return this._transform(point.clone(), scale); | |
}, | |
// destructive transform (faster) | |
_transform: function (point, scale) { | |
scale = scale || 1; | |
point.x = scale * (this._a * point.x + this._b); | |
point.y = scale * (this._c * point.y + this._d); | |
return point; | |
}, | |
untransform: function (point, scale) { | |
scale = scale || 1; | |
return new L.Point( | |
(point.x / scale - this._b) / this._a, | |
(point.y / scale - this._d) / this._c); | |
} | |
}; | |
/* | |
* L.DomUtil contains various utility functions for working with DOM. | |
*/ | |
L.DomUtil = { | |
get: function (id) { | |
return (typeof id === 'string' ? document.getElementById(id) : id); | |
}, | |
getStyle: function (el, style) { | |
var value = el.style[style]; | |
if (!value && el.currentStyle) { | |
value = el.currentStyle[style]; | |
} | |
if ((!value || value === 'auto') && document.defaultView) { | |
var css = document.defaultView.getComputedStyle(el, null); | |
value = css ? css[style] : null; | |
} | |
return value === 'auto' ? null : value; | |
}, | |
getViewportOffset: function (element) { | |
var top = 0, | |
left = 0, | |
el = element, | |
docBody = document.body, | |
docEl = document.documentElement, | |
pos; | |
do { | |
top += el.offsetTop || 0; | |
left += el.offsetLeft || 0; | |
//add borders | |
top += parseInt(L.DomUtil.getStyle(el, 'borderTopWidth'), 10) || 0; | |
left += parseInt(L.DomUtil.getStyle(el, 'borderLeftWidth'), 10) || 0; | |
pos = L.DomUtil.getStyle(el, 'position'); | |
if (el.offsetParent === docBody && pos === 'absolute') { break; } | |
if (pos === 'fixed') { | |
top += docBody.scrollTop || docEl.scrollTop || 0; | |
left += docBody.scrollLeft || docEl.scrollLeft || 0; | |
break; | |
} | |
if (pos === 'relative' && !el.offsetLeft) { | |
var width = L.DomUtil.getStyle(el, 'width'), | |
maxWidth = L.DomUtil.getStyle(el, 'max-width'), | |
r = el.getBoundingClientRect(); | |
if (width !== 'none' || maxWidth !== 'none') { | |
left += r.left + el.clientLeft; | |
} | |
//calculate full y offset since we're breaking out of the loop | |
top += r.top + (docBody.scrollTop || docEl.scrollTop || 0); | |
break; | |
} | |
el = el.offsetParent; | |
} while (el); | |
el = element; | |
do { | |
if (el === docBody) { break; } | |
top -= el.scrollTop || 0; | |
left -= el.scrollLeft || 0; | |
el = el.parentNode; | |
} while (el); | |
return new L.Point(left, top); | |
}, | |
documentIsLtr: function () { | |
if (!L.DomUtil._docIsLtrCached) { | |
L.DomUtil._docIsLtrCached = true; | |
L.DomUtil._docIsLtr = L.DomUtil.getStyle(document.body, 'direction') === 'ltr'; | |
} | |
return L.DomUtil._docIsLtr; | |
}, | |
create: function (tagName, className, container) { | |
var el = document.createElement(tagName); | |
el.className = className; | |
if (container) { | |
container.appendChild(el); | |
} | |
return el; | |
}, | |
hasClass: function (el, name) { | |
if (el.classList !== undefined) { | |
return el.classList.contains(name); | |
} | |
var className = L.DomUtil._getClass(el); | |
return className.length > 0 && new RegExp('(^|\\s)' + name + '(\\s|$)').test(className); | |
}, | |
addClass: function (el, name) { | |
if (el.classList !== undefined) { | |
var classes = L.Util.splitWords(name); | |
for (var i = 0, len = classes.length; i < len; i++) { | |
el.classList.add(classes[i]); | |
} | |
} else if (!L.DomUtil.hasClass(el, name)) { | |
var className = L.DomUtil._getClass(el); | |
L.DomUtil._setClass(el, (className ? className + ' ' : '') + name); | |
} | |
}, | |
removeClass: function (el, name) { | |
if (el.classList !== undefined) { | |
el.classList.remove(name); | |
} else { | |
L.DomUtil._setClass(el, L.Util.trim((' ' + L.DomUtil._getClass(el) + ' ').replace(' ' + name + ' ', ' '))); | |
} | |
}, | |
_setClass: function (el, name) { | |
if (el.className.baseVal === undefined) { | |
el.className = name; | |
} else { | |
// in case of SVG element | |
el.className.baseVal = name; | |
} | |
}, | |
_getClass: function (el) { | |
return el.className.baseVal === undefined ? el.className : el.className.baseVal; | |
}, | |
setOpacity: function (el, value) { | |
if ('opacity' in el.style) { | |
el.style.opacity = value; | |
} else if ('filter' in el.style) { | |
var filter = false, | |
filterName = 'DXImageTransform.Microsoft.Alpha'; | |
// filters collection throws an error if we try to retrieve a filter that doesn't exist | |
try { | |
filter = el.filters.item(filterName); | |
} catch (e) { | |
// don't set opacity to 1 if we haven't already set an opacity, | |
// it isn't needed and breaks transparent pngs. | |
if (value === 1) { return; } | |
} | |
value = Math.round(value * 100); | |
if (filter) { | |
filter.Enabled = (value !== 100); | |
filter.Opacity = value; | |
} else { | |
el.style.filter += ' progid:' + filterName + '(opacity=' + value + ')'; | |
} | |
} | |
}, | |
testProp: function (props) { | |
var style = document.documentElement.style; | |
for (var i = 0; i < props.length; i++) { | |
if (props[i] in style) { | |
return props[i]; | |
} | |
} | |
return false; | |
}, | |
getTranslateString: function (point) { | |
// on WebKit browsers (Chrome/Safari/iOS Safari/Android) using translate3d instead of translate | |
// makes animation smoother as it ensures HW accel is used. Firefox 13 doesn't care | |
// (same speed either way), Opera 12 doesn't support translate3d | |
var is3d = L.Browser.webkit3d, | |
open = 'translate' + (is3d ? '3d' : '') + '(', | |
close = (is3d ? ',0' : '') + ')'; | |
return open + point.x + 'px,' + point.y + 'px' + close; | |
}, | |
getScaleString: function (scale, origin) { | |
var preTranslateStr = L.DomUtil.getTranslateString(origin.add(origin.multiplyBy(-1 * scale))), | |
scaleStr = ' scale(' + scale + ') '; | |
return preTranslateStr + scaleStr; | |
}, | |
setPosition: function (el, point, disable3D) { // (HTMLElement, Point[, Boolean]) | |
// jshint camelcase: false | |
el._leaflet_pos = point; | |
if (!disable3D && L.Browser.any3d) { | |
el.style[L.DomUtil.TRANSFORM] = L.DomUtil.getTranslateString(point); | |
} else { | |
el.style.left = point.x + 'px'; | |
el.style.top = point.y + 'px'; | |
} | |
}, | |
getPosition: function (el) { | |
// this method is only used for elements previously positioned using setPosition, | |
// so it's safe to cache the position for performance | |
// jshint camelcase: false | |
return el._leaflet_pos; | |
} | |
}; | |
// prefix style property names | |
L.DomUtil.TRANSFORM = L.DomUtil.testProp( | |
['transform', 'WebkitTransform', 'OTransform', 'MozTransform', 'msTransform']); | |
// webkitTransition comes first because some browser versions that drop vendor prefix don't do | |
// the same for the transitionend event, in particular the Android 4.1 stock browser | |
L.DomUtil.TRANSITION = L.DomUtil.testProp( | |
['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']); | |
L.DomUtil.TRANSITION_END = | |
L.DomUtil.TRANSITION === 'webkitTransition' || L.DomUtil.TRANSITION === 'OTransition' ? | |
L.DomUtil.TRANSITION + 'End' : 'transitionend'; | |
(function () { | |
if ('onselectstart' in document) { | |
L.extend(L.DomUtil, { | |
disableTextSelection: function () { | |
L.DomEvent.on(window, 'selectstart', L.DomEvent.preventDefault); | |
}, | |
enableTextSelection: function () { | |
L.DomEvent.off(window, 'selectstart', L.DomEvent.preventDefault); | |
} | |
}); | |
} else { | |
var userSelectProperty = L.DomUtil.testProp( | |
['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']); | |
L.extend(L.DomUtil, { | |
disableTextSelection: function () { | |
if (userSelectProperty) { | |
var style = document.documentElement.style; | |
this._userSelect = style[userSelectProperty]; | |
style[userSelectProperty] = 'none'; | |
} | |
}, | |
enableTextSelection: function () { | |
if (userSelectProperty) { | |
document.documentElement.style[userSelectProperty] = this._userSelect; | |
delete this._userSelect; | |
} | |
} | |
}); | |
} | |
L.extend(L.DomUtil, { | |
disableImageDrag: function () { | |
L.DomEvent.on(window, 'dragstart', L.DomEvent.preventDefault); | |
}, | |
enableImageDrag: function () { | |
L.DomEvent.off(window, 'dragstart', L.DomEvent.preventDefault); | |
} | |
}); | |
})(); | |
/* | |
* L.LatLng represents a geographical point with latitude and longitude coordinates. | |
*/ | |
L.LatLng = function (lat, lng, alt) { // (Number, Number, Number) | |
lat = parseFloat(lat); | |
lng = parseFloat(lng); | |
if (isNaN(lat) || isNaN(lng)) { | |
throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')'); | |
} | |
this.lat = lat; | |
this.lng = lng; | |
if (alt !== undefined) { | |
this.alt = parseFloat(alt); | |
} | |
}; | |
L.extend(L.LatLng, { | |
DEG_TO_RAD: Math.PI / 180, | |
RAD_TO_DEG: 180 / Math.PI, | |
MAX_MARGIN: 1.0E-9 // max margin of error for the "equals" check | |
}); | |
L.LatLng.prototype = { | |
equals: function (obj) { // (LatLng) -> Boolean | |
if (!obj) { return false; } | |
obj = L.latLng(obj); | |
var margin = Math.max( | |
Math.abs(this.lat - obj.lat), | |
Math.abs(this.lng - obj.lng)); | |
return margin <= L.LatLng.MAX_MARGIN; | |
}, | |
toString: function (precision) { // (Number) -> String | |
return 'LatLng(' + | |
L.Util.formatNum(this.lat, precision) + ', ' + | |
L.Util.formatNum(this.lng, precision) + ')'; | |
}, | |
// Haversine distance formula, see http://en.wikipedia.org/wiki/Haversine_formula | |
// TODO move to projection code, LatLng shouldn't know about Earth | |
distanceTo: function (other) { // (LatLng) -> Number | |
other = L.latLng(other); | |
var R = 6378137, // earth radius in meters | |
d2r = L.LatLng.DEG_TO_RAD, | |
dLat = (other.lat - this.lat) * d2r, | |
dLon = (other.lng - this.lng) * d2r, | |
lat1 = this.lat * d2r, | |
lat2 = other.lat * d2r, | |
sin1 = Math.sin(dLat / 2), | |
sin2 = Math.sin(dLon / 2); | |
var a = sin1 * sin1 + sin2 * sin2 * Math.cos(lat1) * Math.cos(lat2); | |
return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); | |
}, | |
wrap: function (a, b) { // (Number, Number) -> LatLng | |
var lng = this.lng; | |
a = a || -180; | |
b = b || 180; | |
lng = (lng + b) % (b - a) + (lng < a || lng === b ? b : a); | |
return new L.LatLng(this.lat, lng); | |
} | |
}; | |
L.latLng = function (a, b) { // (LatLng) or ([Number, Number]) or (Number, Number) | |
if (a instanceof L.LatLng) { | |
return a; | |
} | |
if (L.Util.isArray(a)) { | |
if (typeof a[0] === 'number' || typeof a[0] === 'string') { | |
return new L.LatLng(a[0], a[1], a[2]); | |
} else { | |
return null; | |
} | |
} | |
if (a === undefined || a === null) { | |
return a; | |
} | |
if (typeof a === 'object' && 'lat' in a) { | |
return new L.LatLng(a.lat, 'lng' in a ? a.lng : a.lon); | |
} | |
if (b === undefined) { | |
return null; | |
} | |
return new L.LatLng(a, b); | |
}; | |
/* | |
* L.LatLngBounds represents a rectangular area on the map in geographical coordinates. | |
*/ | |
L.LatLngBounds = function (southWest, northEast) { // (LatLng, LatLng) or (LatLng[]) | |
if (!southWest) { return; } | |
var latlngs = northEast ? [southWest, northEast] : southWest; | |
for (var i = 0, len = latlngs.length; i < len; i++) { | |
this.extend(latlngs[i]); | |
} | |
}; | |
L.LatLngBounds.prototype = { | |
// extend the bounds to contain the given point or bounds | |
extend: function (obj) { // (LatLng) or (LatLngBounds) | |
if (!obj) { return this; } | |
var latLng = L.latLng(obj); | |
if (latLng !== null) { | |
obj = latLng; | |
} else { | |
obj = L.latLngBounds(obj); | |
} | |
if (obj instanceof L.LatLng) { | |
if (!this._southWest && !this._northEast) { | |
this._southWest = new L.LatLng(obj.lat, obj.lng); | |
this._northEast = new L.LatLng(obj.lat, obj.lng); | |
} else { | |
this._southWest.lat = Math.min(obj.lat, this._southWest.lat); | |
this._southWest.lng = Math.min(obj.lng, this._southWest.lng); | |
this._northEast.lat = Math.max(obj.lat, this._northEast.lat); | |
this._northEast.lng = Math.max(obj.lng, this._northEast.lng); | |
} | |
} else if (obj instanceof L.LatLngBounds) { | |
this.extend(obj._southWest); | |
this.extend(obj._northEast); | |
} | |
return this; | |
}, | |
// extend the bounds by a percentage | |
pad: function (bufferRatio) { // (Number) -> LatLngBounds | |
var sw = this._southWest, | |
ne = this._northEast, | |
heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio, | |
widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio; | |
return new L.LatLngBounds( | |
new L.LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer), | |
new L.LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer)); | |
}, | |
getCenter: function () { // -> LatLng | |
return new L.LatLng( | |
(this._southWest.lat + this._northEast.lat) / 2, | |
(this._southWest.lng + this._northEast.lng) / 2); | |
}, | |
getSouthWest: function () { | |
return this._southWest; | |
}, | |
getNorthEast: function () { | |
return this._northEast; | |
}, | |
getNorthWest: function () { | |
return new L.LatLng(this.getNorth(), this.getWest()); | |
}, | |
getSouthEast: function () { | |
return new L.LatLng(this.getSouth(), this.getEast()); | |
}, | |
getWest: function () { | |
return this._southWest.lng; | |
}, | |
getSouth: function () { | |
return this._southWest.lat; | |
}, | |
getEast: function () { | |
return this._northEast.lng; | |
}, | |
getNorth: function () { | |
return this._northEast.lat; | |
}, | |
contains: function (obj) { // (LatLngBounds) or (LatLng) -> Boolean | |
if (typeof obj[0] === 'number' || obj instanceof L.LatLng) { | |
obj = L.latLng(obj); | |
} else { | |
obj = L.latLngBounds(obj); | |
} | |
var sw = this._southWest, | |
ne = this._northEast, | |
sw2, ne2; | |
if (obj instanceof L.LatLngBounds) { | |
sw2 = obj.getSouthWest(); | |
ne2 = obj.getNorthEast(); | |
} else { | |
sw2 = ne2 = obj; | |
} | |
return (sw2.lat >= sw.lat) && (ne2.lat <= ne.lat) && | |
(sw2.lng >= sw.lng) && (ne2.lng <= ne.lng); | |
}, | |
intersects: function (bounds) { // (LatLngBounds) | |
bounds = L.latLngBounds(bounds); | |
var sw = this._southWest, | |
ne = this._northEast, | |
sw2 = bounds.getSouthWest(), | |
ne2 = bounds.getNorthEast(), | |
latIntersects = (ne2.lat >= sw.lat) && (sw2.lat <= ne.lat), | |
lngIntersects = (ne2.lng >= sw.lng) && (sw2.lng <= ne.lng); | |
return latIntersects && lngIntersects; | |
}, | |
toBBoxString: function () { | |
return [this.getWest(), this.getSouth(), this.getEast(), this.getNorth()].join(','); | |
}, | |
equals: function (bounds) { // (LatLngBounds) | |
if (!bounds) { return false; } | |
bounds = L.latLngBounds(bounds); | |
return this._southWest.equals(bounds.getSouthWest()) && | |
this._northEast.equals(bounds.getNorthEast()); | |
}, | |
isValid: function () { | |
return !!(this._southWest && this._northEast); | |
} | |
}; | |
//TODO International date line? | |
L.latLngBounds = function (a, b) { // (LatLngBounds) or (LatLng, LatLng) | |
if (!a || a instanceof L.LatLngBounds) { | |
return a; | |
} | |
return new L.LatLngBounds(a, b); | |
}; | |
/* | |
* L.Projection contains various geographical projections used by CRS classes. | |
*/ | |
L.Projection = {}; | |
/* | |
* Spherical Mercator is the most popular map projection, used by EPSG:3857 CRS used by default. | |
*/ | |
L.Projection.SphericalMercator = { | |
MAX_LATITUDE: 85.0511287798, | |
project: function (latlng) { // (LatLng) -> Point | |
var d = L.LatLng.DEG_TO_RAD, | |
max = this.MAX_LATITUDE, | |
lat = Math.max(Math.min(max, latlng.lat), -max), | |
x = latlng.lng * d, | |
y = lat * d; | |
y = Math.log(Math.tan((Math.PI / 4) + (y / 2))); | |
return new L.Point(x, y); | |
}, | |
unproject: function (point) { // (Point, Boolean) -> LatLng | |
var d = L.LatLng.RAD_TO_DEG, | |
lng = point.x * d, | |
lat = (2 * Math.atan(Math.exp(point.y)) - (Math.PI / 2)) * d; | |
return new L.LatLng(lat, lng); | |
} | |
}; | |
/* | |
* Simple equirectangular (Plate Carree) projection, used by CRS like EPSG:4326 and Simple. | |
*/ | |
L.Projection.LonLat = { | |
project: function (latlng) { | |
return new L.Point(latlng.lng, latlng.lat); | |
}, | |
unproject: function (point) { | |
return new L.LatLng(point.y, point.x); | |
} | |
}; | |
/* | |
* L.CRS is a base object for all defined CRS (Coordinate Reference Systems) in Leaflet. | |
*/ | |
L.CRS = { | |
latLngToPoint: function (latlng, zoom) { // (LatLng, Number) -> Point | |
var projectedPoint = this.projection.project(latlng), | |
scale = this.scale(zoom); | |
return this.transformation._transform(projectedPoint, scale); | |
}, | |
pointToLatLng: function (point, zoom) { // (Point, Number[, Boolean]) -> LatLng | |
var scale = this.scale(zoom), | |
untransformedPoint = this.transformation.untransform(point, scale); | |
return this.projection.unproject(untransformedPoint); | |
}, | |
project: function (latlng) { | |
return this.projection.project(latlng); | |
}, | |
scale: function (zoom) { | |
return 256 * Math.pow(2, zoom); | |
}, | |
getSize: function (zoom) { | |
var s = this.scale(zoom); | |
return L.point(s, s); | |
} | |
}; | |
/* | |
* A simple CRS that can be used for flat non-Earth maps like panoramas or game maps. | |
*/ | |
L.CRS.Simple = L.extend({}, L.CRS, { | |
projection: L.Projection.LonLat, | |
transformation: new L.Transformation(1, 0, -1, 0), | |
scale: function (zoom) { | |
return Math.pow(2, zoom); | |
} | |
}); | |
/* | |
* L.CRS.EPSG3857 (Spherical Mercator) is the most common CRS for web mapping | |
* and is used by Leaflet by default. | |
*/ | |
L.CRS.EPSG3857 = L.extend({}, L.CRS, { | |
code: 'EPSG:3857', | |
projection: L.Projection.SphericalMercator, | |
transformation: new L.Transformation(0.5 / Math.PI, 0.5, -0.5 / Math.PI, 0.5), | |
project: function (latlng) { // (LatLng) -> Point | |
var projectedPoint = this.projection.project(latlng), | |
earthRadius = 6378137; | |
return projectedPoint.multiplyBy(earthRadius); | |
} | |
}); | |
L.CRS.EPSG900913 = L.extend({}, L.CRS.EPSG3857, { | |
code: 'EPSG:900913' | |
}); | |
/* | |
* L.CRS.EPSG4326 is a CRS popular among advanced GIS specialists. | |
*/ | |
L.CRS.EPSG4326 = L.extend({}, L.CRS, { | |
code: 'EPSG:4326', | |
projection: L.Projection.LonLat, | |
transformation: new L.Transformation(1 / 360, 0.5, -1 / 360, 0.5) | |
}); | |
/* | |
* L.Map is the central class of the API - it is used to create a map. | |
*/ | |
L.Map = L.Class.extend({ | |
includes: L.Mixin.Events, | |
options: { | |
crs: L.CRS.EPSG3857, | |
/* | |
center: LatLng, | |
zoom: Number, | |
layers: Array, | |
*/ | |
fadeAnimation: L.DomUtil.TRANSITION && !L.Browser.android23, | |
trackResize: true, | |
markerZoomAnimation: L.DomUtil.TRANSITION && L.Browser.any3d | |
}, | |
initialize: function (id, options) { // (HTMLElement or String, Object) | |
options = L.setOptions(this, options); | |
this._initContainer(id); | |
this._initLayout(); | |
// hack for https://github.com/Leaflet/Leaflet/issues/1980 | |
this._onResize = L.bind(this._onResize, this); | |
this._initEvents(); | |
if (options.maxBounds) { | |
this.setMaxBounds(options.maxBounds); | |
} | |
if (options.center && options.zoom !== undefined) { | |
this.setView(L.latLng(options.center), options.zoom, {reset: true}); | |
} | |
this._handlers = []; | |
this._layers = {}; | |
this._zoomBoundLayers = {}; | |
this._tileLayersNum = 0; | |
this.callInitHooks(); | |
this._addLayers(options.layers); | |
}, | |
// public methods that modify map state | |
// replaced by animation-powered implementation in Map.PanAnimation.js | |
setView: function (center, zoom) { | |
zoom = zoom === undefined ? this.getZoom() : zoom; | |
this._resetView(L.latLng(center), this._limitZoom(zoom)); | |
return this; | |
}, | |
setZoom: function (zoom, options) { | |
if (!this._loaded) { | |
this._zoom = this._limitZoom(zoom); | |
return this; | |
} | |
return this.setView(this.getCenter(), zoom, {zoom: options}); | |
}, | |
zoomIn: function (delta, options) { | |
return this.setZoom(this._zoom + (delta || 1), options); | |
}, | |
zoomOut: function (delta, options) { | |
return this.setZoom(this._zoom - (delta || 1), options); | |
}, | |
setZoomAround: function (latlng, zoom, options) { | |
var scale = this.getZoomScale(zoom), | |
viewHalf = this.getSize().divideBy(2), | |
containerPoint = latlng instanceof L.Point ? latlng : this.latLngToContainerPoint(latlng), | |
centerOffset = containerPoint.subtract(viewHalf).multiplyBy(1 - 1 / scale), | |
newCenter = this.containerPointToLatLng(viewHalf.add(centerOffset)); | |
return this.setView(newCenter, zoom, {zoom: options}); | |
}, | |
fitBounds: function (bounds, options) { | |
options = options || {}; | |
bounds = bounds.getBounds ? bounds.getBounds() : L.latLngBounds(bounds); | |
var paddingTL = L.point(options.paddingTopLeft || options.padding || [0, 0]), | |
paddingBR = L.point(options.paddingBottomRight || options.padding || [0, 0]), | |
zoom = this.getBoundsZoom(bounds, false, paddingTL.add(paddingBR)); | |
zoom = (options.maxZoom) ? Math.min(options.maxZoom, zoom) : zoom; | |
var paddingOffset = paddingBR.subtract(paddingTL).divideBy(2), | |
swPoint = this.project(bounds.getSouthWest(), zoom), | |
nePoint = this.project(bounds.getNorthEast(), zoom), | |
center = this.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom); | |
return this.setView(center, zoom, options); | |
}, | |
fitWorld: function (options) { | |
return this.fitBounds([[-90, -180], [90, 180]], options); | |
}, | |
panTo: function (center, options) { // (LatLng) | |
return this.setView(center, this._zoom, {pan: options}); | |
}, | |
panBy: function (offset) { // (Point) | |
// replaced with animated panBy in Map.PanAnimation.js | |
this.fire('movestart'); | |
this._rawPanBy(L.point(offset)); | |
this.fire('move'); | |
return this.fire('moveend'); | |
}, | |
setMaxBounds: function (bounds) { | |
bounds = L.latLngBounds(bounds); | |
this.options.maxBounds = bounds; | |
if (!bounds) { | |
return this.off('moveend', this._panInsideMaxBounds, this); | |
} | |
if (this._loaded) { | |
this._panInsideMaxBounds(); | |
} | |
return this.on('moveend', this._panInsideMaxBounds, this); | |
}, | |
panInsideBounds: function (bounds, options) { | |
var center = this.getCenter(), | |
newCenter = this._limitCenter(center, this._zoom, bounds); | |
if (center.equals(newCenter)) { return this; } | |
return this.panTo(newCenter, options); | |
}, | |
addLayer: function (layer) { | |
// TODO method is too big, refactor | |
var id = L.stamp(layer); | |
if (this._layers[id]) { return this; } | |
this._layers[id] = layer; | |
// TODO getMaxZoom, getMinZoom in ILayer (instead of options) | |
if (layer.options && (!isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom))) { | |
this._zoomBoundLayers[id] = layer; | |
this._updateZoomLevels(); | |
} | |
// TODO looks ugly, refactor!!! | |
if (this.options.zoomAnimation && L.TileLayer && (layer instanceof L.TileLayer)) { | |
this._tileLayersNum++; | |
this._tileLayersToLoad++; | |
layer.on('load', this._onTileLayerLoad, this); | |
} | |
if (this._loaded) { | |
this._layerAdd(layer); | |
} | |
return this; | |
}, | |
removeLayer: function (layer) { | |
var id = L.stamp(layer); | |
if (!this._layers[id]) { return this; } | |
if (this._loaded) { | |
layer.onRemove(this); | |
} | |
delete this._layers[id]; | |
if (this._loaded) { | |
this.fire('layerremove', {layer: layer}); | |
} | |
if (this._zoomBoundLayers[id]) { | |
delete this._zoomBoundLayers[id]; | |
this._updateZoomLevels(); | |
} | |
// TODO looks ugly, refactor | |
if (this.options.zoomAnimation && L.TileLayer && (layer instanceof L.TileLayer)) { | |
this._tileLayersNum--; | |
this._tileLayersToLoad--; | |
layer.off('load', this._onTileLayerLoad, this); | |
} | |
return this; | |
}, | |
hasLayer: function (layer) { | |
if (!layer) { return false; } | |
return (L.stamp(layer) in this._layers); | |
}, | |
eachLayer: function (method, context) { | |
for (var i in this._layers) { | |
method.call(context, this._layers[i]); | |
} | |
return this; | |
}, | |
invalidateSize: function (options) { | |
if (!this._loaded) { return this; } | |
options = L.extend({ | |
animate: false, | |
pan: true | |
}, options === true ? {animate: true} : options); | |
var oldSize = this.getSize(); | |
this._sizeChanged = true; | |
this._initialCenter = null; | |
var newSize = this.getSize(), | |
oldCenter = oldSize.divideBy(2).round(), | |
newCenter = newSize.divideBy(2).round(), | |
offset = oldCenter.subtract(newCenter); | |
if (!offset.x && !offset.y) { return this; } | |
if (options.animate && options.pan) { | |
this.panBy(offset); | |
} else { | |
if (options.pan) { | |
this._rawPanBy(offset); | |
} | |
this.fire('move'); | |
if (options.debounceMoveend) { | |
clearTimeout(this._sizeTimer); | |
this._sizeTimer = setTimeout(L.bind(this.fire, this, 'moveend'), 200); | |
} else { | |
this.fire('moveend'); | |
} | |
} | |
return this.fire('resize', { | |
oldSize: oldSize, | |
newSize: newSize | |
}); | |
}, | |
// TODO handler.addTo | |
addHandler: function (name, HandlerClass) { | |
if (!HandlerClass) { return this; } | |
var handler = this[name] = new HandlerClass(this); | |
this._handlers.push(handler); | |
if (this.options[name]) { | |
handler.enable(); | |
} | |
return this; | |
}, | |
remove: function () { | |
if (this._loaded) { | |
this.fire('unload'); | |
} | |
this._initEvents('off'); | |
try { | |
// throws error in IE6-8 | |
delete this._container._leaflet; | |
} catch (e) { | |
this._container._leaflet = undefined; | |
} | |
this._clearPanes(); | |
if (this._clearControlPos) { | |
this._clearControlPos(); | |
} | |
this._clearHandlers(); | |
return this; | |
}, | |
// public methods for getting map state | |
getCenter: function () { // (Boolean) -> LatLng | |
this._checkIfLoaded(); | |
if (this._initialCenter && !this._moved()) { | |
return this._initialCenter; | |
} | |
return this.layerPointToLatLng(this._getCenterLayerPoint()); | |
}, | |
getZoom: function () { | |
return this._zoom; | |
}, | |
getBounds: function () { | |
var bounds = this.getPixelBounds(), | |
sw = this.unproject(bounds.getBottomLeft()), | |
ne = this.unproject(bounds.getTopRight()); | |
return new L.LatLngBounds(sw, ne); | |
}, | |
getMinZoom: function () { | |
return this.options.minZoom === undefined ? | |
(this._layersMinZoom === undefined ? 0 : this._layersMinZoom) : | |
this.options.minZoom; | |
}, | |
getMaxZoom: function () { | |
return this.options.maxZoom === undefined ? | |
(this._layersMaxZoom === undefined ? Infinity : this._layersMaxZoom) : | |
this.options.maxZoom; | |
}, | |
getBoundsZoom: function (bounds, inside, padding) { // (LatLngBounds[, Boolean, Point]) -> Number | |
bounds = L.latLngBounds(bounds); | |
var zoom = this.getMinZoom() - (inside ? 1 : 0), | |
maxZoom = this.getMaxZoom(), | |
size = this.getSize(), | |
nw = bounds.getNorthWest(), | |
se = bounds.getSouthEast(), | |
zoomNotFound = true, | |
boundsSize; | |
padding = L.point(padding || [0, 0]); | |
do { | |
zoom++; | |
boundsSize = this.project(se, zoom).subtract(this.project(nw, zoom)).add(padding); | |
zoomNotFound = !inside ? size.contains(boundsSize) : boundsSize.x < size.x || boundsSize.y < size.y; | |
} while (zoomNotFound && zoom <= maxZoom); | |
if (zoomNotFound && inside) { | |
return null; | |
} | |
return inside ? zoom : zoom - 1; | |
}, | |
getSize: function () { | |
if (!this._size || this._sizeChanged) { | |
this._size = new L.Point( | |
this._container.clientWidth, | |
this._container.clientHeight); | |
this._sizeChanged = false; | |
} | |
return this._size.clone(); | |
}, | |
getPixelBounds: function () { | |
var topLeftPoint = this._getTopLeftPoint(); | |
return new L.Bounds(topLeftPoint, topLeftPoint.add(this.getSize())); | |
}, | |
getPixelOrigin: function () { | |
this._checkIfLoaded(); | |
return this._initialTopLeftPoint; | |
}, | |
getPanes: function () { | |
return this._panes; | |
}, | |
getContainer: function () { | |
return this._container; | |
}, | |
// TODO replace with universal implementation after refactoring projections | |
getZoomScale: function (toZoom) { | |
var crs = this.options.crs; | |
return crs.scale(toZoom) / crs.scale(this._zoom); | |
}, | |
getScaleZoom: function (scale) { | |
return this._zoom + (Math.log(scale) / Math.LN2); | |
}, | |
// conversion methods | |
project: function (latlng, zoom) { // (LatLng[, Number]) -> Point | |
zoom = zoom === undefined ? this._zoom : zoom; | |
return this.options.crs.latLngToPoint(L.latLng(latlng), zoom); | |
}, | |
unproject: function (point, zoom) { // (Point[, Number]) -> LatLng | |
zoom = zoom === undefined ? this._zoom : zoom; | |
return this.options.crs.pointToLatLng(L.point(point), zoom); | |
}, | |
layerPointToLatLng: function (point) { // (Point) | |
var projectedPoint = L.point(point).add(this.getPixelOrigin()); | |
return this.unproject(projectedPoint); | |
}, | |
latLngToLayerPoint: function (latlng) { // (LatLng) | |
var projectedPoint = this.project(L.latLng(latlng))._round(); | |
return projectedPoint._subtract(this.getPixelOrigin()); | |
}, | |
containerPointToLayerPoint: function (point) { // (Point) | |
return L.point(point).subtract(this._getMapPanePos()); | |
}, | |
layerPointToContainerPoint: function (point) { // (Point) | |
return L.point(point).add(this._getMapPanePos()); | |
}, | |
containerPointToLatLng: function (point) { | |
var layerPoint = this.containerPointToLayerPoint(L.point(point)); | |
return this.layerPointToLatLng(layerPoint); | |
}, | |
latLngToContainerPoint: function (latlng) { | |
return this.layerPointToContainerPoint(this.latLngToLayerPoint(L.latLng(latlng))); | |
}, | |
mouseEventToContainerPoint: function (e) { // (MouseEvent) | |
return L.DomEvent.getMousePosition(e, this._container); | |
}, | |
mouseEventToLayerPoint: function (e) { // (MouseEvent) | |
return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(e)); | |
}, | |
mouseEventToLatLng: function (e) { // (MouseEvent) | |
return this.layerPointToLatLng(this.mouseEventToLayerPoint(e)); | |
}, | |
// map initialization methods | |
_initContainer: function (id) { | |
var container = this._container = L.DomUtil.get(id); | |
if (!container) { | |
throw new Error('Map container not found.'); | |
} else if (container._leaflet) { | |
throw new Error('Map container is already initialized.'); | |
} | |
container._leaflet = true; | |
}, | |
_initLayout: function () { | |
var container = this._container; | |
L.DomUtil.addClass(container, 'leaflet-container' + | |
(L.Browser.touch ? ' leaflet-touch' : '') + | |
(L.Browser.retina ? ' leaflet-retina' : '') + | |
(L.Browser.ielt9 ? ' leaflet-oldie' : '') + | |
(this.options.fadeAnimation ? ' leaflet-fade-anim' : '')); | |
var position = L.DomUtil.getStyle(container, 'position'); | |
if (position !== 'absolute' && position !== 'relative' && position !== 'fixed') { | |
container.style.position = 'relative'; | |
} | |
this._initPanes(); | |
if (this._initControlPos) { | |
this._initControlPos(); | |
} | |
}, | |
_initPanes: function () { | |
var panes = this._panes = {}; | |
this._mapPane = panes.mapPane = this._createPane('leaflet-map-pane', this._container); | |
this._tilePane = panes.tilePane = this._createPane('leaflet-tile-pane', this._mapPane); | |
panes.objectsPane = this._createPane('leaflet-objects-pane', this._mapPane); | |
panes.shadowPane = this._createPane('leaflet-shadow-pane'); | |
panes.overlayPane = this._createPane('leaflet-overlay-pane'); | |
panes.markerPane = this._createPane('leaflet-marker-pane'); | |
panes.popupPane = this._createPane('leaflet-popup-pane'); | |
var zoomHide = ' leaflet-zoom-hide'; | |
if (!this.options.markerZoomAnimation) { | |
L.DomUtil.addClass(panes.markerPane, zoomHide); | |
L.DomUtil.addClass(panes.shadowPane, zoomHide); | |
L.DomUtil.addClass(panes.popupPane, zoomHide); | |
} | |
}, | |
_createPane: function (className, container) { | |
return L.DomUtil.create('div', className, container || this._panes.objectsPane); | |
}, | |
_clearPanes: function () { | |
this._container.removeChild(this._mapPane); | |
}, | |
_addLayers: function (layers) { | |
layers = layers ? (L.Util.isArray(layers) ? layers : [layers]) : []; | |
for (var i = 0, len = layers.length; i < len; i++) { | |
this.addLayer(layers[i]); | |
} | |
}, | |
// private methods that modify map state | |
_resetView: function (center, zoom, preserveMapOffset, afterZoomAnim) { | |
var zoomChanged = (this._zoom !== zoom); | |
if (!afterZoomAnim) { | |
this.fire('movestart'); | |
if (zoomChanged) { | |
this.fire('zoomstart'); | |
} | |
} | |
this._zoom = zoom; | |
this._initialCenter = center; | |
this._initialTopLeftPoint = this._getNewTopLeftPoint(center); | |
if (!preserveMapOffset) { | |
L.DomUtil.setPosition(this._mapPane, new L.Point(0, 0)); | |
} else { | |
this._initialTopLeftPoint._add(this._getMapPanePos()); | |
} | |
this._tileLayersToLoad = this._tileLayersNum; | |
var loading = !this._loaded; | |
this._loaded = true; | |
this.fire('viewreset', {hard: !preserveMapOffset}); | |
if (loading) { | |
this.fire('load'); | |
this.eachLayer(this._layerAdd, this); | |
} | |
this.fire('move'); | |
if (zoomChanged || afterZoomAnim) { | |
this.fire('zoomend'); | |
} | |
this.fire('moveend', {hard: !preserveMapOffset}); | |
}, | |
_rawPanBy: function (offset) { | |
L.DomUtil.setPosition(this._mapPane, this._getMapPanePos().subtract(offset)); | |
}, | |
_getZoomSpan: function () { | |
return this.getMaxZoom() - this.getMinZoom(); | |
}, | |
_updateZoomLevels: function () { | |
var i, | |
minZoom = Infinity, | |
maxZoom = -Infinity, | |
oldZoomSpan = this._getZoomSpan(); | |
for (i in this._zoomBoundLayers) { | |
var layer = this._zoomBoundLayers[i]; | |
if (!isNaN(layer.options.minZoom)) { | |
minZoom = Math.min(minZoom, layer.options.minZoom); | |
} | |
if (!isNaN(layer.options.maxZoom)) { | |
maxZoom = Math.max(maxZoom, layer.options.maxZoom); | |
} | |
} | |
if (i === undefined) { // we have no tilelayers | |
this._layersMaxZoom = this._layersMinZoom = undefined; | |
} else { | |
this._layersMaxZoom = maxZoom; | |
this._layersMinZoom = minZoom; | |
} | |
if (oldZoomSpan !== this._getZoomSpan()) { | |
this.fire('zoomlevelschange'); | |
} | |
}, | |
_panInsideMaxBounds: function () { | |
this.panInsideBounds(this.options.maxBounds); | |
}, | |
_checkIfLoaded: function () { | |
if (!this._loaded) { | |
throw new Error('Set map center and zoom first.'); | |
} | |
}, | |
// map events | |
_initEvents: function (onOff) { | |
if (!L.DomEvent) { return; } | |
onOff = onOff || 'on'; | |
L.DomEvent[onOff](this._container, 'click', this._onMouseClick, this); | |
var events = ['dblclick', 'mousedown', 'mouseup', 'mouseenter', | |
'mouseleave', 'mousemove', 'contextmenu'], | |
i, len; | |
for (i = 0, len = events.length; i < len; i++) { | |
L.DomEvent[onOff](this._container, events[i], this._fireMouseEvent, this); | |
} | |
if (this.options.trackResize) { | |
L.DomEvent[onOff](window, 'resize', this._onResize, this); | |
} | |
}, | |
_onResize: function () { | |
L.Util.cancelAnimFrame(this._resizeRequest); | |
this._resizeRequest = L.Util.requestAnimFrame( | |
function () { this.invalidateSize({debounceMoveend: true}); }, this, false, this._container); | |
}, | |
_onMouseClick: function (e) { | |
if (!this._loaded || (!e._simulated && | |
((this.dragging && this.dragging.moved()) || | |
(this.boxZoom && this.boxZoom.moved()))) || | |
L.DomEvent._skipped(e)) { return; } | |
this.fire('preclick'); | |
this._fireMouseEvent(e); | |
}, | |
_fireMouseEvent: function (e) { | |
if (!this._loaded || L.DomEvent._skipped(e)) { return; } | |
var type = e.type; | |
type = (type === 'mouseenter' ? 'mouseover' : (type === 'mouseleave' ? 'mouseout' : type)); | |
if (!this.hasEventListeners(type)) { return; } | |
if (type === 'contextmenu') { | |
L.DomEvent.preventDefault(e); | |
} | |
var containerPoint = this.mouseEventToContainerPoint(e), | |
layerPoint = this.containerPointToLayerPoint(containerPoint), | |
latlng = this.layerPointToLatLng(layerPoint); | |
this.fire(type, { | |
latlng: latlng, | |
layerPoint: layerPoint, | |
containerPoint: containerPoint, | |
originalEvent: e | |
}); | |
}, | |
_onTileLayerLoad: function () { | |
this._tileLayersToLoad--; | |
if (this._tileLayersNum && !this._tileLayersToLoad) { | |
this.fire('tilelayersload'); | |
} | |
}, | |
_clearHandlers: function () { | |
for (var i = 0, len = this._handlers.length; i < len; i++) { | |
this._handlers[i].disable(); | |
} | |
}, | |
whenReady: function (callback, context) { | |
if (this._loaded) { | |
callback.call(context || this, this); | |
} else { | |
this.on('load', callback, context); | |
} | |
return this; | |
}, | |
_layerAdd: function (layer) { | |
layer.onAdd(this); | |
this.fire('layeradd', {layer: layer}); | |
}, | |
// private methods for getting map state | |
_getMapPanePos: function () { | |
return L.DomUtil.getPosition(this._mapPane); | |
}, | |
_moved: function () { | |
var pos = this._getMapPanePos(); | |
return pos && !pos.equals([0, 0]); | |
}, | |
_getTopLeftPoint: function () { | |
return this.getPixelOrigin().subtract(this._getMapPanePos()); | |
}, | |
_getNewTopLeftPoint: function (center, zoom) { | |
var viewHalf = this.getSize()._divideBy(2); | |
// TODO round on display, not calculation to increase precision? | |
return this.project(center, zoom)._subtract(viewHalf)._round(); | |
}, | |
_latLngToNewLayerPoint: function (latlng, newZoom, newCenter) { | |
var topLeft = this._getNewTopLeftPoint(newCenter, newZoom).add(this._getMapPanePos()); | |
return this.project(latlng, newZoom)._subtract(topLeft); | |
}, | |
// layer point of the current center | |
_getCenterLayerPoint: function () { | |
return this.containerPointToLayerPoint(this.getSize()._divideBy(2)); | |
}, | |
// offset of the specified place to the current center in pixels | |
_getCenterOffset: function (latlng) { | |
return this.latLngToLayerPoint(latlng).subtract(this._getCenterLayerPoint()); | |
}, | |
// adjust center for view to get inside bounds | |
_limitCenter: function (center, zoom, bounds) { | |
if (!bounds) { return center; } | |
var centerPoint = this.project(center, zoom), | |
viewHalf = this.getSize().divideBy(2), | |
viewBounds = new L.Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)), | |
offset = this._getBoundsOffset(viewBounds, bounds, zoom); | |
return this.unproject(centerPoint.add(offset), zoom); | |
}, | |
// adjust offset for view to get inside bounds | |
_limitOffset: function (offset, bounds) { | |
if (!bounds) { return offset; } | |
var viewBounds = this.getPixelBounds(), | |
newBounds = new L.Bounds(viewBounds.min.add(offset), viewBounds.max.add(offset)); | |
return offset.add(this._getBoundsOffset(newBounds, bounds)); | |
}, | |
// returns offset needed for pxBounds to get inside maxBounds at a specified zoom | |
_getBoundsOffset: function (pxBounds, maxBounds, zoom) { | |
var nwOffset = this.project(maxBounds.getNorthWest(), zoom).subtract(pxBounds.min), | |
seOffset = this.project(maxBounds.getSouthEast(), zoom).subtract(pxBounds.max), | |
dx = this._rebound(nwOffset.x, -seOffset.x), | |
dy = this._rebound(nwOffset.y, -seOffset.y); | |
return new L.Point(dx, dy); | |
}, | |
_rebound: function (left, right) { | |
return left + right > 0 ? | |
Math.round(left - right) / 2 : | |
Math.max(0, Math.ceil(left)) - Math.max(0, Math.floor(right)); | |
}, | |
_limitZoom: function (zoom) { | |
var min = this.getMinZoom(), | |
max = this.getMaxZoom(); | |
return Math.max(min, Math.min(max, zoom)); | |
} | |
}); | |
L.map = function (id, options) { | |
return new L.Map(id, options); | |
}; | |
/* | |
* Mercator projection that takes into account that the Earth is not a perfect sphere. | |
* Less popular than spherical mercator; used by projections like EPSG:3395. | |
*/ | |
L.Projection.Mercator = { | |
MAX_LATITUDE: 85.0840591556, | |
R_MINOR: 6356752.314245179, | |
R_MAJOR: 6378137, | |
project: function (latlng) { // (LatLng) -> Point | |
var d = L.LatLng.DEG_TO_RAD, | |
max = this.MAX_LATITUDE, | |
lat = Math.max(Math.min(max, latlng.lat), -max), | |
r = this.R_MAJOR, | |
r2 = this.R_MINOR, | |
x = latlng.lng * d * r, | |
y = lat * d, | |
tmp = r2 / r, | |
eccent = Math.sqrt(1.0 - tmp * tmp), | |
con = eccent * Math.sin(y); | |
con = Math.pow((1 - con) / (1 + con), eccent * 0.5); | |
var ts = Math.tan(0.5 * ((Math.PI * 0.5) - y)) / con; | |
y = -r * Math.log(ts); | |
return new L.Point(x, y); | |
}, | |
unproject: function (point) { // (Point, Boolean) -> LatLng | |
var d = L.LatLng.RAD_TO_DEG, | |
r = this.R_MAJOR, | |
r2 = this.R_MINOR, | |
lng = point.x * d / r, | |
tmp = r2 / r, | |
eccent = Math.sqrt(1 - (tmp * tmp)), | |
ts = Math.exp(- point.y / r), | |
phi = (Math.PI / 2) - 2 * Math.atan(ts), | |
numIter = 15, | |
tol = 1e-7, | |
i = numIter, | |
dphi = 0.1, | |
con; | |
while ((Math.abs(dphi) > tol) && (--i > 0)) { | |
con = eccent * Math.sin(phi); | |
dphi = (Math.PI / 2) - 2 * Math.atan(ts * | |
Math.pow((1.0 - con) / (1.0 + con), 0.5 * eccent)) - phi; | |
phi += dphi; | |
} | |
return new L.LatLng(phi * d, lng); | |
} | |
}; | |
L.CRS.EPSG3395 = L.extend({}, L.CRS, { | |
code: 'EPSG:3395', | |
projection: L.Projection.Mercator, | |
transformation: (function () { | |
var m = L.Projection.Mercator, | |
r = m.R_MAJOR, | |
scale = 0.5 / (Math.PI * r); | |
return new L.Transformation(scale, 0.5, -scale, 0.5); | |
}()) | |
}); | |
/* | |
* L.TileLayer is used for standard xyz-numbered tile layers. | |
*/ | |
L.TileLayer = L.Class.extend({ | |
includes: L.Mixin.Events, | |
options: { | |
minZoom: 0, | |
maxZoom: 18, | |
tileSize: 256, | |
subdomains: 'abc', | |
errorTileUrl: '', | |
attribution: '', | |
zoomOffset: 0, | |
opacity: 1, | |
/* | |
maxNativeZoom: null, | |
zIndex: null, | |
tms: false, | |
continuousWorld: false, | |
noWrap: false, | |
zoomReverse: false, | |
detectRetina: false, | |
reuseTiles: false, | |
bounds: false, | |
*/ | |
unloadInvisibleTiles: L.Browser.mobile, | |
updateWhenIdle: L.Browser.mobile | |
}, | |
initialize: function (url, options) { | |
options = L.setOptions(this, options); | |
// detecting retina displays, adjusting tileSize and zoom levels | |
if (options.detectRetina && L.Browser.retina && options.maxZoom > 0) { | |
options.tileSize = Math.floor(options.tileSize / 2); | |
options.zoomOffset++; | |
if (options.minZoom > 0) { | |
options.minZoom--; | |
} | |
this.options.maxZoom--; | |
} | |
if (options.bounds) { | |
options.bounds = L.latLngBounds(options.bounds); | |
} | |
this._url = url; | |
var subdomains = this.options.subdomains; | |
if (typeof subdomains === 'string') { | |
this.options.subdomains = subdomains.split(''); | |
} | |
}, | |
onAdd: function (map) { | |
this._map = map; | |
this._animated = map._zoomAnimated; | |
// create a container div for tiles | |
this._initContainer(); | |
// set up events | |
map.on({ | |
'viewreset': this._reset, | |
'moveend': this._update | |
}, this); | |
if (this._animated) { | |
map.on({ | |
'zoomanim': this._animateZoom, | |
'zoomend': this._endZoomAnim | |
}, this); | |
} | |
if (!this.options.updateWhenIdle) { | |
this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this); | |
map.on('move', this._limitedUpdate, this); | |
} | |
this._reset(); | |
this._update(); | |
}, | |
addTo: function (map) { | |
map.addLayer(this); | |
return this; | |
}, | |
onRemove: function (map) { | |
this._container.parentNode.removeChild(this._container); | |
map.off({ | |
'viewreset': this._reset, | |
'moveend': this._update | |
}, this); | |
if (this._animated) { | |
map.off({ | |
'zoomanim': this._animateZoom, | |
'zoomend': this._endZoomAnim | |
}, this); | |
} | |
if (!this.options.updateWhenIdle) { | |
map.off('move', this._limitedUpdate, this); | |
} | |
this._container = null; | |
this._map = null; | |
}, | |
bringToFront: function () { | |
var pane = this._map._panes.tilePane; | |
if (this._container) { | |
pane.appendChild(this._container); | |
this._setAutoZIndex(pane, Math.max); | |
} | |
return this; | |
}, | |
bringToBack: function () { | |
var pane = this._map._panes.tilePane; | |
if (this._container) { | |
pane.insertBefore(this._container, pane.firstChild); | |
this._setAutoZIndex(pane, Math.min); | |
} | |
return this; | |
}, | |
getAttribution: function () { | |
return this.options.attribution; | |
}, | |
getContainer: function () { | |
return this._container; | |
}, | |
setOpacity: function (opacity) { | |
this.options.opacity = opacity; | |
if (this._map) { | |
this._updateOpacity(); | |
} | |
return this; | |
}, | |
setZIndex: function (zIndex) { | |
this.options.zIndex = zIndex; | |
this._updateZIndex(); | |
return this; | |
}, | |
setUrl: function (url, noRedraw) { | |
this._url = url; | |
if (!noRedraw) { | |
this.redraw(); | |
} | |
return this; | |
}, | |
redraw: function () { | |
if (this._map) { | |
this._reset({hard: true}); | |
this._update(); | |
} | |
return this; | |
}, | |
_updateZIndex: function () { | |
if (this._container && this.options.zIndex !== undefined) { | |
this._container.style.zIndex = this.options.zIndex; | |
} | |
}, | |
_setAutoZIndex: function (pane, compare) { | |
var layers = pane.children, | |
edgeZIndex = -compare(Infinity, -Infinity), // -Infinity for max, Infinity for min | |
zIndex, i, len; | |
for (i = 0, len = layers.length; i < len; i++) { | |
if (layers[i] !== this._container) { | |
zIndex = parseInt(layers[i].style.zIndex, 10); | |
if (!isNaN(zIndex)) { | |
edgeZIndex = compare(edgeZIndex, zIndex); | |
} | |
} | |
} | |
this.options.zIndex = this._container.style.zIndex = | |
(isFinite(edgeZIndex) ? edgeZIndex : 0) + compare(1, -1); | |
}, | |
_updateOpacity: function () { | |
var i, | |
tiles = this._tiles; | |
if (L.Browser.ielt9) { | |
for (i in tiles) { | |
L.DomUtil.setOpacity(tiles[i], this.options.opacity); | |
} | |
} else { | |
L.DomUtil.setOpacity(this._container, this.options.opacity); | |
} | |
}, | |
_initContainer: function () { | |
var tilePane = this._map._panes.tilePane; | |
if (!this._container) { | |
this._container = L.DomUtil.create('div', 'leaflet-layer'); | |
this._updateZIndex(); | |
if (this._animated) { | |
var className = 'leaflet-tile-container'; | |
this._bgBuffer = L.DomUtil.create('div', className, this._container); | |
this._tileContainer = L.DomUtil.create('div', className, this._container); | |
} else { | |
this._tileContainer = this._container; | |
} | |
tilePane.appendChild(this._container); | |
if (this.options.opacity < 1) { | |
this._updateOpacity(); | |
} | |
} | |
}, | |
_reset: function (e) { | |
for (var key in this._tiles) { | |
this.fire('tileunload', {tile: this._tiles[key]}); | |
} | |
this._tiles = {}; | |
this._tilesToLoad = 0; | |
if (this.options.reuseTiles) { | |
this._unusedTiles = []; | |
} | |
this._tileContainer.innerHTML = ''; | |
if (this._animated && e && e.hard) { | |
this._clearBgBuffer(); | |
} | |
this._initContainer(); | |
}, | |
_getTileSize: function () { | |
var map = this._map, | |
zoom = map.getZoom() + this.options.zoomOffset, | |
zoomN = this.options.maxNativeZoom, | |
tileSize = this.options.tileSize; | |
if (zoomN && zoom > zoomN) { | |
tileSize = Math.round(map.getZoomScale(zoom) / map.getZoomScale(zoomN) * tileSize); | |
} | |
return tileSize; | |
}, | |
_update: function () { | |
if (!this._map) { return; } | |
var map = this._map, | |
bounds = map.getPixelBounds(), | |
zoom = map.getZoom(), | |
tileSize = this._getTileSize(); | |
if (zoom > this.options.maxZoom || zoom < this.options.minZoom) { | |
return; | |
} | |
var tileBounds = L.bounds( | |
bounds.min.divideBy(tileSize)._floor(), | |
bounds.max.divideBy(tileSize)._floor()); | |
this._addTilesFromCenterOut(tileBounds); | |
if (this.options.unloadInvisibleTiles || this.options.reuseTiles) { | |
this._removeOtherTiles(tileBounds); | |
} | |
}, | |
_addTilesFromCenterOut: function (bounds) { | |
var queue = [], | |
center = bounds.getCenter(); | |
var j, i, point; | |
for (j = bounds.min.y; j <= bounds.max.y; j++) { | |
for (i = bounds.min.x; i <= bounds.max.x; i++) { | |
point = new L.Point(i, j); | |
if (this._tileShouldBeLoaded(point)) { | |
queue.push(point); | |
} | |
} | |
} | |
var tilesToLoad = queue.length; | |
if (tilesToLoad === 0) { return; } | |
// load tiles in order of their distance to center | |
queue.sort(function (a, b) { | |
return a.distanceTo(center) - b.distanceTo(center); | |
}); | |
var fragment = document.createDocumentFragment(); | |
// if its the first batch of tiles to load | |
if (!this._tilesToLoad) { | |
this.fire('loading'); | |
} | |
this._tilesToLoad += tilesToLoad; | |
for (i = 0; i < tilesToLoad; i++) { | |
this._addTile(queue[i], fragment); | |
} | |
this._tileContainer.appendChild(fragment); | |
}, | |
_tileShouldBeLoaded: function (tilePoint) { | |
if ((tilePoint.x + ':' + tilePoint.y) in this._tiles) { | |
return false; // already loaded | |
} | |
var options = this.options; | |
if (!options.continuousWorld) { | |
var limit = this._getWrapTileNum(); | |
// don't load if exceeds world bounds | |
if ((options.noWrap && (tilePoint.x < 0 || tilePoint.x >= limit.x)) || | |
tilePoint.y < 0 || tilePoint.y >= limit.y) { return false; } | |
} | |
if (options.bounds) { | |
var tileSize = this._getTileSize(), | |
nwPoint = tilePoint.multiplyBy(tileSize), | |
sePoint = nwPoint.add([tileSize, tileSize]), | |
nw = this._map.unproject(nwPoint), | |
se = this._map.unproject(sePoint); | |
// TODO temporary hack, will be removed after refactoring projections | |
// https://github.com/Leaflet/Leaflet/issues/1618 | |
if (!options.continuousWorld && !options.noWrap) { | |
nw = nw.wrap(); | |
se = se.wrap(); | |
} | |
if (!options.bounds.intersects([nw, se])) { return false; } | |
} | |
return true; | |
}, | |
_removeOtherTiles: function (bounds) { | |
var kArr, x, y, key; | |
for (key in this._tiles) { | |
kArr = key.split(':'); | |
x = parseInt(kArr[0], 10); | |
y = parseInt(kArr[1], 10); | |
// remove tile if it's out of bounds | |
if (x < bounds.min.x || x > bounds.max.x || y < bounds.min.y || y > bounds.max.y) { | |
this._removeTile(key); | |
} | |
} | |
}, | |
_removeTile: function (key) { | |
var tile = this._tiles[key]; | |
this.fire('tileunload', {tile: tile, url: tile.src}); | |
if (this.options.reuseTiles) { | |
L.DomUtil.removeClass(tile, 'leaflet-tile-loaded'); | |
this._unusedTiles.push(tile); | |
} else if (tile.parentNode === this._tileContainer) { | |
this._tileContainer.removeChild(tile); | |
} | |
// for https://github.com/CloudMade/Leaflet/issues/137 | |
if (!L.Browser.android) { | |
tile.onload = null; | |
tile.src = L.Util.emptyImageUrl; | |
} | |
delete this._tiles[key]; | |
}, | |
_addTile: function (tilePoint, container) { | |
var tilePos = this._getTilePos(tilePoint); | |
// get unused tile - or create a new tile | |
var tile = this._getTile(); | |
/* | |
Chrome 20 layouts much faster with top/left (verify with timeline, frames) | |
Android 4 browser has display issues with top/left and requires transform instead | |
(other browsers don't currently care) - see debug/hacks/jitter.html for an example | |
*/ | |
L.DomUtil.setPosition(tile, tilePos, L.Browser.chrome); | |
this._tiles[tilePoint.x + ':' + tilePoint.y] = tile; | |
this._loadTile(tile, tilePoint); | |
if (tile.parentNode !== this._tileContainer) { | |
container.appendChild(tile); | |
} | |
}, | |
_getZoomForUrl: function () { | |
var options = this.options, | |
zoom = this._map.getZoom(); | |
if (options.zoomReverse) { | |
zoom = options.maxZoom - zoom; | |
} | |
zoom += options.zoomOffset; | |
return options.maxNativeZoom ? Math.min(zoom, options.maxNativeZoom) : zoom; | |
}, | |
_getTilePos: function (tilePoint) { | |
var origin = this._map.getPixelOrigin(), | |
tileSize = this._getTileSize(); | |
return tilePoint.multiplyBy(tileSize).subtract(origin); | |
}, | |
// image-specific code (override to implement e.g. Canvas or SVG tile layer) | |
getTileUrl: function (tilePoint) { | |
return L.Util.template(this._url, L.extend({ | |
s: this._getSubdomain(tilePoint), | |
z: tilePoint.z, | |
x: tilePoint.x, | |
y: tilePoint.y | |
}, this.options)); | |
}, | |
_getWrapTileNum: function () { | |
var crs = this._map.options.crs, | |
size = crs.getSize(this._map.getZoom()); | |
return size.divideBy(this._getTileSize())._floor(); | |
}, | |
_adjustTilePoint: function (tilePoint) { | |
var limit = this._getWrapTileNum(); | |
// wrap tile coordinates | |
if (!this.options.continuousWorld && !this.options.noWrap) { | |
tilePoint.x = ((tilePoint.x % limit.x) + limit.x) % limit.x; | |
} | |
if (this.options.tms) { | |
tilePoint.y = limit.y - tilePoint.y - 1; | |
} | |
tilePoint.z = this._getZoomForUrl(); | |
}, | |
_getSubdomain: function (tilePoint) { | |
var index = Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length; | |
return this.options.subdomains[index]; | |
}, | |
_getTile: function () { | |
if (this.options.reuseTiles && this._unusedTiles.length > 0) { | |
var tile = this._unusedTiles.pop(); | |
this._resetTile(tile); | |
return tile; | |
} | |
return this._createTile(); | |
}, | |
// Override if data stored on a tile needs to be cleaned up before reuse | |
_resetTile: function (/*tile*/) {}, | |
_createTile: function () { | |
var tile = L.DomUtil.create('img', 'leaflet-tile'); | |
tile.style.width = tile.style.height = this._getTileSize() + 'px'; | |
tile.galleryimg = 'no'; | |
tile.onselectstart = tile.onmousemove = L.Util.falseFn; | |
if (L.Browser.ielt9 && this.options.opacity !== undefined) { | |
L.DomUtil.setOpacity(tile, this.options.opacity); | |
} | |
// without this hack, tiles disappear after zoom on Chrome for Android | |
// https://github.com/Leaflet/Leaflet/issues/2078 | |
if (L.Browser.mobileWebkit3d) { | |
tile.style.WebkitBackfaceVisibility = 'hidden'; | |
} | |
return tile; | |
}, | |
_loadTile: function (tile, tilePoint) { | |
tile._layer = this; | |
tile.onload = this._tileOnLoad; | |
tile.onerror = this._tileOnError; | |
this._adjustTilePoint(tilePoint); | |
tile.src = this.getTileUrl(tilePoint); | |
this.fire('tileloadstart', { | |
tile: tile, | |
url: tile.src | |
}); | |
}, | |
_tileLoaded: function () { | |
this._tilesToLoad--; | |
if (this._animated) { | |
L.DomUtil.addClass(this._tileContainer, 'leaflet-zoom-animated'); | |
} | |
if (!this._tilesToLoad) { | |
this.fire('load'); | |
if (this._animated) { | |
// clear scaled tiles after all new tiles are loaded (for performance) | |
clearTimeout(this._clearBgBufferTimer); | |
this._clearBgBufferTimer = setTimeout(L.bind(this._clearBgBuffer, this), 500); | |
} | |
} | |
}, | |
_tileOnLoad: function () { | |
var layer = this._layer; | |
//Only if we are loading an actual image | |
if (this.src !== L.Util.emptyImageUrl) { | |
L.DomUtil.addClass(this, 'leaflet-tile-loaded'); | |
layer.fire('tileload', { | |
tile: this, | |
url: this.src | |
}); | |
} | |
layer._tileLoaded(); | |
}, | |
_tileOnError: function () { | |
var layer = this._layer; | |
layer.fire('tileerror', { | |
tile: this, | |
url: this.src | |
}); | |
var newUrl = layer.options.errorTileUrl; | |
if (newUrl) { | |
this.src = newUrl; | |
} | |
layer._tileLoaded(); | |
} | |
}); | |
L.tileLayer = function (url, options) { | |
return new L.TileLayer(url, options); | |
}; | |
/* | |
* L.TileLayer.WMS is used for putting WMS tile layers on the map. | |
*/ | |
L.TileLayer.WMS = L.TileLayer.extend({ | |
defaultWmsParams: { | |
service: 'WMS', | |
request: 'GetMap', | |
version: '1.1.1', | |
layers: '', | |
styles: '', | |
format: 'image/jpeg', | |
transparent: false | |
}, | |
initialize: function (url, options) { // (String, Object) | |
this._url = url; | |
var wmsParams = L.extend({}, this.defaultWmsParams), | |
tileSize = options.tileSize || this.options.tileSize; | |
if (options.detectRetina && L.Browser.retina) { | |
wmsParams.width = wmsParams.height = tileSize * 2; | |
} else { | |
wmsParams.width = wmsParams.height = tileSize; | |
} | |
for (var i in options) { | |
// all keys that are not TileLayer options go to WMS params | |
if (!this.options.hasOwnProperty(i) && i !== 'crs') { | |
wmsParams[i] = options[i]; | |
} | |
} | |
this.wmsParams = wmsParams; | |
L.setOptions(this, options); | |
}, | |
onAdd: function (map) { | |
this._crs = this.options.crs || map.options.crs; | |
this._wmsVersion = parseFloat(this.wmsParams.version); | |
var projectionKey = this._wmsVersion >= 1.3 ? 'crs' : 'srs'; | |
this.wmsParams[projectionKey] = this._crs.code; | |
L.TileLayer.prototype.onAdd.call(this, map); | |
}, | |
getTileUrl: function (tilePoint) { // (Point, Number) -> String | |
var map = this._map, | |
tileSize = this.options.tileSize, | |
nwPoint = tilePoint.multiplyBy(tileSize), | |
sePoint = nwPoint.add([tileSize, tileSize]), | |
nw = this._crs.project(map.unproject(nwPoint, tilePoint.z)), | |
se = this._crs.project(map.unproject(sePoint, tilePoint.z)), | |
bbox = this._wmsVersion >= 1.3 && this._crs === L.CRS.EPSG4326 ? | |
[se.y, nw.x, nw.y, se.x].join(',') : | |
[nw.x, se.y, se.x, nw.y].join(','), | |
url = L.Util.template(this._url, {s: this._getSubdomain(tilePoint)}); | |
return url + L.Util.getParamString(this.wmsParams, url, true) + '&BBOX=' + bbox; | |
}, | |
setParams: function (params, noRedraw) { | |
L.extend(this.wmsParams, params); | |
if (!noRedraw) { | |
this.redraw(); | |
} | |
return this; | |
} | |
}); | |
L.tileLayer.wms = function (url, options) { | |
return new L.TileLayer.WMS(url, options); | |
}; | |
/* | |
* L.TileLayer.Canvas is a class that you can use as a base for creating | |
* dynamically drawn Canvas-based tile layers. | |
*/ | |
L.TileLayer.Canvas = L.TileLayer.extend({ | |
options: { | |
async: false | |
}, | |
initialize: function (options) { | |
L.setOptions(this, options); | |
}, | |
redraw: function () { | |
if (this._map) { | |
this._reset({hard: true}); | |
this._update(); | |
} | |
for (var i in this._tiles) { | |
this._redrawTile(this._tiles[i]); | |
} | |
return this; | |
}, | |
_redrawTile: function (tile) { | |
this.drawTile(tile, tile._tilePoint, this._map._zoom); | |
}, | |
_createTile: function () { | |
var tile = L.DomUtil.create('canvas', 'leaflet-tile'); | |
tile.width = tile.height = this.options.tileSize; | |
tile.onselectstart = tile.onmousemove = L.Util.falseFn; | |
return tile; | |
}, | |
_loadTile: function (tile, tilePoint) { | |
tile._layer = this; | |
tile._tilePoint = tilePoint; | |
this._redrawTile(tile); | |
if (!this.options.async) { | |
this.tileDrawn(tile); | |
} | |
}, | |
drawTile: function (/*tile, tilePoint*/) { | |
// override with rendering code | |
}, | |
tileDrawn: function (tile) { | |
this._tileOnLoad.call(tile); | |
} | |
}); | |
L.tileLayer.canvas = function (options) { | |
return new L.TileLayer.Canvas(options); | |
}; | |
/* | |
* L.ImageOverlay is used to overlay images over the map (to specific geographical bounds). | |
*/ | |
L.ImageOverlay = L.Class.extend({ | |
includes: L.Mixin.Events, | |
options: { | |
opacity: 1 | |
}, | |
initialize: function (url, bounds, options) { // (String, LatLngBounds, Object) | |
this._url = url; | |
this._bounds = L.latLngBounds(bounds); | |
L.setOptions(this, options); | |
}, | |
onAdd: function (map) { | |
this._map = map; | |
if (!this._image) { | |
this._initImage(); | |
} | |
map._panes.overlayPane.appendChild(this._image); | |
map.on('viewreset', this._reset, this); | |
if (map.options.zoomAnimation && L.Browser.any3d) { | |
map.on('zoomanim', this._animateZoom, this); | |
} | |
this._reset(); | |
}, | |
onRemove: function (map) { | |
map.getPanes().overlayPane.removeChild(this._image); | |
map.off('viewreset', this._reset, this); | |
if (map.options.zoomAnimation) { | |
map.off('zoomanim', this._animateZoom, this); | |
} | |
}, | |
addTo: function (map) { | |
map.addLayer(this); | |
return this; | |
}, | |
setOpacity: function (opacity) { | |
this.options.opacity = opacity; | |
this._updateOpacity(); | |
return this; | |
}, | |
// TODO remove bringToFront/bringToBack duplication from TileLayer/Path | |
bringToFront: function () { | |
if (this._image) { | |
this._map._panes.overlayPane.appendChild(this._image); | |
} | |
return this; | |
}, | |
bringToBack: function () { | |
var pane = this._map._panes.overlayPane; | |
if (this._image) { | |
pane.insertBefore(this._image, pane.firstChild); | |
} | |
return this; | |
}, | |
setUrl: function (url) { | |
this._url = url; | |
this._image.src = this._url; | |
}, | |
getAttribution: function () { | |
return this.options.attribution; | |
}, | |
_initImage: function () { | |
this._image = L.DomUtil.create('img', 'leaflet-image-layer'); | |
if (this._map.options.zoomAnimation && L.Browser.any3d) { | |
L.DomUtil.addClass(this._image, 'leaflet-zoom-animated'); | |
} else { | |
L.DomUtil.addClass(this._image, 'leaflet-zoom-hide'); | |
} | |
this._updateOpacity(); | |
//TODO createImage util method to remove duplication | |
L.extend(this._image, { | |
galleryimg: 'no', | |
onselectstart: L.Util.falseFn, | |
onmousemove: L.Util.falseFn, | |
onload: L.bind(this._onImageLoad, this), | |
src: this._url | |
}); | |
}, | |
_animateZoom: function (e) { | |
var map = this._map, | |
image = this._image, | |
scale = map.getZoomScale(e.zoom), | |
nw = this._bounds.getNorthWest(), | |
se = this._bounds.getSouthEast(), | |
topLeft = map._latLngToNewLayerPoint(nw, e.zoom, e.center), | |
size = map._latLngToNewLayerPoint(se, e.zoom, e.center)._subtract(topLeft), | |
origin = topLeft._add(size._multiplyBy((1 / 2) * (1 - 1 / scale))); | |
image.style[L.DomUtil.TRANSFORM] = | |
L.DomUtil.getTranslateString(origin) + ' scale(' + scale + ') '; | |
}, | |
_reset: function () { | |
var image = this._image, | |
topLeft = this._map.latLngToLayerPoint(this._bounds.getNorthWest()), | |
size = this._map.latLngToLayerPoint(this._bounds.getSouthEast())._subtract(topLeft); | |
L.DomUtil.setPosition(image, topLeft); | |
image.style.width = size.x + 'px'; | |
image.style.height = size.y + 'px'; | |
}, | |
_onImageLoad: function () { | |
this.fire('load'); | |
}, | |
_updateOpacity: function () { | |
L.DomUtil.setOpacity(this._image, this.options.opacity); | |
} | |
}); | |
L.imageOverlay = function (url, bounds, options) { | |
return new L.ImageOverlay(url, bounds, options); | |
}; | |
/* | |
* L.Icon is an image-based icon class that you can use with L.Marker for custom markers. | |
*/ | |
L.Icon = L.Class.extend({ | |
options: { | |
/* | |
iconUrl: (String) (required) | |
iconRetinaUrl: (String) (optional, used for retina devices if detected) | |
iconSize: (Point) (can be set through CSS) | |
iconAnchor: (Point) (centered by default, can be set in CSS with negative margins) | |
popupAnchor: (Point) (if not specified, popup opens in the anchor point) | |
shadowUrl: (String) (no shadow by default) | |
shadowRetinaUrl: (String) (optional, used for retina devices if detected) | |
shadowSize: (Point) | |
shadowAnchor: (Point) | |
*/ | |
className: '' | |
}, | |
initialize: function (options) { | |
L.setOptions(this, options); | |
}, | |
createIcon: function (oldIcon) { | |
return this._createIcon('icon', oldIcon); | |
}, | |
createShadow: function (oldIcon) { | |
return this._createIcon('shadow', oldIcon); | |
}, | |
_createIcon: function (name, oldIcon) { | |
var src = this._getIconUrl(name); | |
if (!src) { | |
if (name === 'icon') { | |
throw new Error('iconUrl not set in Icon options (see the docs).'); | |
} | |
return null; | |
} | |
var img; | |
if (!oldIcon || oldIcon.tagName !== 'IMG') { | |
img = this._createImg(src); | |
} else { | |
img = this._createImg(src, oldIcon); | |
} | |
this._setIconStyles(img, name); | |
return img; | |
}, | |
_setIconStyles: function (img, name) { | |
var options = this.options, | |
size = L.point(options[name + 'Size']), | |
anchor; | |
if (name === 'shadow') { | |
anchor = L.point(options.shadowAnchor || options.iconAnchor); | |
} else { | |
anchor = L.point(options.iconAnchor); | |
} | |
if (!anchor && size) { | |
anchor = size.divideBy(2, true); | |
} | |
img.className = 'leaflet-marker-' + name + ' ' + options.className; | |
if (anchor) { | |
img.style.marginLeft = (-anchor.x) + 'px'; | |
img.style.marginTop = (-anchor.y) + 'px'; | |
} | |
if (size) { | |
img.style.width = size.x + 'px'; | |
img.style.height = size.y + 'px'; | |
} | |
}, | |
_createImg: function (src, el) { | |
el = el || document.createElement('img'); | |
el.src = src; | |
return el; | |
}, | |
_getIconUrl: function (name) { | |
if (L.Browser.retina && this.options[name + 'RetinaUrl']) { | |
return this.options[name + 'RetinaUrl']; | |
} | |
return this.options[name + 'Url']; | |
} | |
}); | |
L.icon = function (options) { | |
return new L.Icon(options); | |
}; | |
/* | |
* L.Icon.Default is the blue marker icon used by default in Leaflet. | |
*/ | |
L.Icon.Default = L.Icon.extend({ | |
options: { | |
iconSize: [25, 41], | |
iconAnchor: [12, 41], | |
popupAnchor: [1, -34], | |
shadowSize: [41, 41] | |
}, | |
_getIconUrl: function (name) { | |
var key = name + 'Url'; | |
if (this.options[key]) { | |
return this.options[key]; | |
} | |
if (L.Browser.retina && name === 'icon') { | |
name += '-2x'; | |
} | |
var path = L.Icon.Default.imagePath; | |
if (!path) { | |
throw new Error('Couldn\'t autodetect L.Icon.Default.imagePath, set it manually.'); | |
} | |
return path + '/marker-' + name + '.png'; | |
} | |
}); | |
L.Icon.Default.imagePath = (function () { | |
var scripts = document.getElementsByTagName('script'), | |
leafletRe = /[\/^]leaflet[\-\._]?([\w\-\._]*)\.js\??/; | |
var i, len, src, matches, path; | |
for (i = 0, len = scripts.length; i < len; i++) { | |
src = scripts[i].src; | |
matches = src.match(leafletRe); | |
if (matches) { | |
path = src.split(leafletRe)[0]; | |
return (path ? path + '/' : '') + 'images'; | |
} | |
} | |
}()); | |
/* | |
* L.Marker is used to display clickable/draggable icons on the map. | |
*/ | |
L.Marker = L.Class.extend({ | |
includes: L.Mixin.Events, | |
options: { | |
icon: new L.Icon.Default(), | |
title: '', | |
alt: '', | |
clickable: true, | |
draggable: false, | |
keyboard: true, | |
zIndexOffset: 0, | |
opacity: 1, | |
riseOnHover: false, | |
riseOffset: 250 | |
}, | |
initialize: function (latlng, options) { | |
L.setOptions(this, options); | |
this._latlng = L.latLng(latlng); | |
}, | |
onAdd: function (map) { | |
this._map = map; | |
map.on('viewreset', this.update, this); | |
this._initIcon(); | |
this.update(); | |
this.fire('add'); | |
if (map.options.zoomAnimation && map.options.markerZoomAnimation) { | |
map.on('zoomanim', this._animateZoom, this); | |
} | |
}, | |
addTo: function (map) { | |
map.addLayer(this); | |
return this; | |
}, | |
onRemove: function (map) { | |
if (this.dragging) { | |
this.dragging.disable(); | |
} | |
this._removeIcon(); | |
this._removeShadow(); | |
this.fire('remove'); | |
map.off({ | |
'viewreset': this.update, | |
'zoomanim': this._animateZoom | |
}, this); | |
this._map = null; | |
}, | |
getLatLng: function () { | |
return this._latlng; | |
}, | |
setLatLng: function (latlng) { | |
this._latlng = L.latLng(latlng); | |
this.update(); | |
return this.fire('move', { latlng: this._latlng }); | |
}, | |
setZIndexOffset: function (offset) { | |
this.options.zIndexOffset = offset; | |
this.update(); | |
return this; | |
}, | |
setIcon: function (icon) { | |
this.options.icon = icon; | |
if (this._map) { | |
this._initIcon(); | |
this.update(); | |
} | |
if (this._popup) { | |
this.bindPopup(this._popup); | |
} | |
return this; | |
}, | |
update: function () { | |
if (this._icon) { | |
this._setPos(this._map.latLngToLayerPoint(this._latlng).round()); | |
} | |
return this; | |
}, | |
_initIcon: function () { | |
var options = this.options, | |
map = this._map, | |
animation = (map.options.zoomAnimation && map.options.markerZoomAnimation), | |
classToAdd = animation ? 'leaflet-zoom-animated' : 'leaflet-zoom-hide'; | |
var icon = options.icon.createIcon(this._icon), | |
addIcon = false; | |
// if we're not reusing the icon, remove the old one and init new one | |
if (icon !== this._icon) { | |
if (this._icon) { | |
this._removeIcon(); | |
} | |
addIcon = true; | |
if (options.title) { | |
icon.title = options.title; | |
} | |
if (options.alt) { | |
icon.alt = options.alt; | |
} | |
} | |
L.DomUtil.addClass(icon, classToAdd); | |
if (options.keyboard) { | |
icon.tabIndex = '0'; | |
} | |
this._icon = icon; | |
this._initInteraction(); | |
if (options.riseOnHover) { | |
L.DomEvent | |
.on(icon, 'mouseover', this._bringToFront, this) | |
.on(icon, 'mouseout', this._resetZIndex, this); | |
} | |
var newShadow = options.icon.createShadow(this._shadow), | |
addShadow = false; | |
if (newShadow !== this._shadow) { | |
this._removeShadow(); | |
addShadow = true; | |
} | |
if (newShadow) { | |
L.DomUtil.addClass(newShadow, classToAdd); | |
} | |
this._shadow = newShadow; | |
if (options.opacity < 1) { | |
this._updateOpacity(); | |
} | |
var panes = this._map._panes; | |
if (addIcon) { | |
panes.markerPane.appendChild(this._icon); | |
} | |
if (newShadow && addShadow) { | |
panes.shadowPane.appendChild(this._shadow); | |
} | |
}, | |
_removeIcon: function () { | |
if (this.options.riseOnHover) { | |
L.DomEvent | |
.off(this._icon, 'mouseover', this._bringToFront) | |
.off(this._icon, 'mouseout', this._resetZIndex); | |
} | |
this._map._panes.markerPane.removeChild(this._icon); | |
this._icon = null; | |
}, | |
_removeShadow: function () { | |
if (this._shadow) { | |
this._map._panes.shadowPane.removeChild(this._shadow); | |
} | |
this._shadow = null; | |
}, | |
_setPos: function (pos) { | |
L.DomUtil.setPosition(this._icon, pos); | |
if (this._shadow) { | |
L.DomUtil.setPosition(this._shadow, pos); | |
} | |
this._zIndex = pos.y + this.options.zIndexOffset; | |
this._resetZIndex(); | |
}, | |
_updateZIndex: function (offset) { | |
this._icon.style.zIndex = this._zIndex + offset; | |
}, | |
_animateZoom: function (opt) { | |
var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round(); | |
this._setPos(pos); | |
}, | |
_initInteraction: function () { | |
if (!this.options.clickable) { return; } | |
// TODO refactor into something shared with Map/Path/etc. to DRY it up | |
var icon = this._icon, | |
events = ['dblclick', 'mousedown', 'mouseover', 'mouseout', 'contextmenu']; | |
L.DomUtil.addClass(icon, 'leaflet-clickable'); | |
L.DomEvent.on(icon, 'click', this._onMouseClick, this); | |
L.DomEvent.on(icon, 'keypress', this._onKeyPress, this); | |
for (var i = 0; i < events.length; i++) { | |
L.DomEvent.on(icon, events[i], this._fireMouseEvent, this); | |
} | |
if (L.Handler.MarkerDrag) { | |
this.dragging = new L.Handler.MarkerDrag(this); | |
if (this.options.draggable) { | |
this.dragging.enable(); | |
} | |
} | |
}, | |
_onMouseClick: function (e) { | |
var wasDragged = this.dragging && this.dragging.moved(); | |
if (this.hasEventListeners(e.type) || wasDragged) { | |
L.DomEvent.stopPropagation(e); | |
} | |
if (wasDragged) { return; } | |
if ((!this.dragging || !this.dragging._enabled) && this._map.dragging && this._map.dragging.moved()) { return; } | |
this.fire(e.type, { | |
originalEvent: e, | |
latlng: this._latlng | |
}); | |
}, | |
_onKeyPress: function (e) { | |
if (e.keyCode === 13) { | |
this.fire('click', { | |
originalEvent: e, | |
latlng: this._latlng | |
}); | |
} | |
}, | |
_fireMouseEvent: function (e) { | |
this.fire(e.type, { | |
originalEvent: e, | |
latlng: this._latlng | |
}); | |
// TODO proper custom event propagation | |
// this line will always be called if marker is in a FeatureGroup | |
if (e.type === 'contextmenu' && this.hasEventListeners(e.type)) { | |
L.DomEvent.preventDefault(e); | |
} | |
if (e.type !== 'mousedown') { | |
L.DomEvent.stopPropagation(e); | |
} else { | |
L.DomEvent.preventDefault(e); | |
} | |
}, | |
setOpacity: function (opacity) { | |
this.options.opacity = opacity; | |
if (this._map) { | |
this._updateOpacity(); | |
} | |
return this; | |
}, | |
_updateOpacity: function () { | |
L.DomUtil.setOpacity(this._icon, this.options.opacity); | |
if (this._shadow) { | |
L.DomUtil.setOpacity(this._shadow, this.options.opacity); | |
} | |
}, | |
_bringToFront: function () { | |
this._updateZIndex(this.options.riseOffset); | |
}, | |
_resetZIndex: function () { | |
this._updateZIndex(0); | |
} | |
}); | |
L.marker = function (latlng, options) { | |
return new L.Marker(latlng, options); | |
}; | |
/* | |
* L.DivIcon is a lightweight HTML-based icon class (as opposed to the image-based L.Icon) | |
* to use with L.Marker. | |
*/ | |
L.DivIcon = L.Icon.extend({ | |
options: { | |
iconSize: [12, 12], // also can be set through CSS | |
/* | |
iconAnchor: (Point) | |
popupAnchor: (Point) | |
html: (String) | |
bgPos: (Point) | |
*/ | |
className: 'leaflet-div-icon', | |
html: false | |
}, | |
createIcon: function (oldIcon) { | |
var div = (oldIcon && oldIcon.tagName === 'DIV') ? oldIcon : document.createElement('div'), | |
options = this.options; | |
if (options.html !== false) { | |
div.innerHTML = options.html; | |
} else { | |
div.innerHTML = ''; | |
} | |
if (options.bgPos) { | |
div.style.backgroundPosition = | |
(-options.bgPos.x) + 'px ' + (-options.bgPos.y) + 'px'; | |
} | |
this._setIconStyles(div, 'icon'); | |
return div; | |
}, | |
createShadow: function () { | |
return null; | |
} | |
}); | |
L.divIcon = function (options) { | |
return new L.DivIcon(options); | |
}; | |
/* | |
* L.Popup is used for displaying popups on the map. | |
*/ | |
L.Map.mergeOptions({ | |
closePopupOnClick: true | |
}); | |
L.Popup = L.Class.extend({ | |
includes: L.Mixin.Events, | |
options: { | |
minWidth: 50, | |
maxWidth: 300, | |
// maxHeight: null, | |
autoPan: true, | |
closeButton: true, | |
offset: [0, 7], | |
autoPanPadding: [5, 5], | |
// autoPanPaddingTopLeft: null, | |
// autoPanPaddingBottomRight: null, | |
keepInView: false, | |
className: '', | |
zoomAnimation: true | |
}, | |
initialize: function (options, source) { | |
L.setOptions(this, options); | |
this._source = source; | |
this._animated = L.Browser.any3d && this.options.zoomAnimation; | |
this._isOpen = false; | |
}, | |
onAdd: function (map) { | |
this._map = map; | |
if (!this._container) { | |
this._initLayout(); | |
} | |
var animFade = map.options.fadeAnimation; | |
if (animFade) { | |
L.DomUtil.setOpacity(this._container, 0); | |
} | |
map._panes.popupPane.appendChild(this._container); | |
map.on(this._getEvents(), this); | |
this.update(); | |
if (animFade) { | |
L.DomUtil.setOpacity(this._container, 1); | |
} | |
this.fire('open'); | |
map.fire('popupopen', {popup: this}); | |
if (this._source) { | |
this._source.fire('popupopen', {popup: this}); | |
} | |
}, | |
addTo: function (map) { | |
map.addLayer(this); | |
return this; | |
}, | |
openOn: function (map) { | |
map.openPopup(this); | |
return this; | |
}, | |
onRemove: function (map) { | |
map._panes.popupPane.removeChild(this._container); | |
L.Util.falseFn(this._container.offsetWidth); // force reflow | |
map.off(this._getEvents(), this); | |
if (map.options.fadeAnimation) { | |
L.DomUtil.setOpacity(this._container, 0); | |
} | |
this._map = null; | |
this.fire('close'); | |
map.fire('popupclose', {popup: this}); | |
if (this._source) { | |
this._source.fire('popupclose', {popup: this}); | |
} | |
}, | |
getLatLng: function () { | |
return this._latlng; | |
}, | |
setLatLng: function (latlng) { | |
this._latlng = L.latLng(latlng); | |
if (this._map) { | |
this._updatePosition(); | |
this._adjustPan(); | |
} | |
return this; | |
}, | |
getContent: function () { | |
return this._content; | |
}, | |
setContent: function (content) { | |
this._content = content; | |
this.update(); | |
return this; | |
}, | |
update: function () { | |
if (!this._map) { return; } | |
this._container.style.visibility = 'hidden'; | |
this._updateContent(); | |
this._updateLayout(); | |
this._updatePosition(); | |
this._container.style.visibility = ''; | |
this._adjustPan(); | |
}, | |
_getEvents: function () { | |
var events = { | |
viewreset: this._updatePosition | |
}; | |
if (this._animated) { | |
events.zoomanim = this._zoomAnimation; | |
} | |
if ('closeOnClick' in this.options ? this.options.closeOnClick : this._map.options.closePopupOnClick) { | |
events.preclick = this._close; | |
} | |
if (this.options.keepInView) { | |
events.moveend = this._adjustPan; | |
} | |
return events; | |
}, | |
_close: function () { | |
if (this._map) { | |
this._map.closePopup(this); | |
} | |
}, | |
_initLayout: function () { | |
var prefix = 'leaflet-popup', | |
containerClass = prefix + ' ' + this.options.className + ' leaflet-zoom-' + | |
(this._animated ? 'animated' : 'hide'), | |
container = this._container = L.DomUtil.create('div', containerClass), | |
closeButton; | |
if (this.options.closeButton) { | |
closeButton = this._closeButton = | |
L.DomUtil.create('a', prefix + '-close-button', container); | |
closeButton.href = '#close'; | |
closeButton.innerHTML = '×'; | |
L.DomEvent.disableClickPropagation(closeButton); | |
L.DomEvent.on(closeButton, 'click', this._onCloseButtonClick, this); | |
} | |
var wrapper = this._wrapper = | |
L.DomUtil.create('div', prefix + '-content-wrapper', container); | |
L.DomEvent.disableClickPropagation(wrapper); | |
this._contentNode = L.DomUtil.create('div', prefix + '-content', wrapper); | |
L.DomEvent.disableScrollPropagation(this._contentNode); | |
L.DomEvent.on(wrapper, 'contextmenu', L.DomEvent.stopPropagation); | |
this._tipContainer = L.DomUtil.create('div', prefix + '-tip-container', container); | |
this._tip = L.DomUtil.create('div', prefix + '-tip', this._tipContainer); | |
}, | |
_updateContent: function () { | |
if (!this._content) { return; } | |
if (typeof this._content === 'string') { | |
this._contentNode.innerHTML = this._content; | |
} else { | |
while (this._contentNode.hasChildNodes()) { | |
this._contentNode.removeChild(this._contentNode.firstChild); | |
} | |
this._contentNode.appendChild(this._content); | |
} | |
this.fire('contentupdate'); | |
}, | |
_updateLayout: function () { | |
var container = this._contentNode, | |
style = container.style; | |
style.width = ''; | |
style.whiteSpace = 'nowrap'; | |
var width = container.offsetWidth; | |
width = Math.min(width, this.options.maxWidth); | |
width = Math.max(width, this.options.minWidth); | |
style.width = (width + 1) + 'px'; | |
style.whiteSpace = ''; | |
style.height = ''; | |
var height = container.offsetHeight, | |
maxHeight = this.options.maxHeight, | |
scrolledClass = 'leaflet-popup-scrolled'; | |
if (maxHeight && height > maxHeight) { | |
style.height = maxHeight + 'px'; | |
L.DomUtil.addClass(container, scrolledClass); | |
} else { | |
L.DomUtil.removeClass(container, scrolledClass); | |
} | |
this._containerWidth = this._container.offsetWidth; | |
}, | |
_updatePosition: function () { | |
if (!this._map) { return; } | |
var pos = this._map.latLngToLayerPoint(this._latlng), | |
animated = this._animated, | |
offset = L.point(this.options.offset); | |
if (animated) { | |
L.DomUtil.setPosition(this._container, pos); | |
} | |
this._containerBottom = -offset.y - (animated ? 0 : pos.y); | |
this._containerLeft = -Math.round(this._containerWidth / 2) + offset.x + (animated ? 0 : pos.x); | |
// bottom position the popup in case the height of the popup changes (images loading etc) | |
this._container.style.bottom = this._containerBottom + 'px'; | |
this._container.style.left = this._containerLeft + 'px'; | |
}, | |
_zoomAnimation: function (opt) { | |
var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center); | |
L.DomUtil.setPosition(this._container, pos); | |
}, | |
_adjustPan: function () { | |
if (!this.options.autoPan) { return; } | |
var map = this._map, | |
containerHeight = this._container.offsetHeight, | |
containerWidth = this._containerWidth, | |
layerPos = new L.Point(this._containerLeft, -containerHeight - this._containerBottom); | |
if (this._animated) { | |
layerPos._add(L.DomUtil.getPosition(this._container)); | |
} | |
var containerPos = map.layerPointToContainerPoint(layerPos), | |
padding = L.point(this.options.autoPanPadding), | |
paddingTL = L.point(this.options.autoPanPaddingTopLeft || padding), | |
paddingBR = L.point(this.options.autoPanPaddingBottomRight || padding), | |
size = map.getSize(), | |
dx = 0, | |
dy = 0; | |
if (containerPos.x + containerWidth + paddingBR.x > size.x) { // right | |
dx = containerPos.x + containerWidth - size.x + paddingBR.x; | |
} | |
if (containerPos.x - dx - paddingTL.x < 0) { // left | |
dx = containerPos.x - paddingTL.x; | |
} | |
if (containerPos.y + containerHeight + paddingBR.y > size.y) { // bottom | |
dy = containerPos.y + containerHeight - size.y + paddingBR.y; | |
} | |
if (containerPos.y - dy - paddingTL.y < 0) { // top | |
dy = containerPos.y - paddingTL.y; | |
} | |
if (dx || dy) { | |
map | |
.fire('autopanstart') | |
.panBy([dx, dy]); | |
} | |
}, | |
_onCloseButtonClick: function (e) { | |
this._close(); | |
L.DomEvent.stop(e); | |
} | |
}); | |
L.popup = function (options, source) { | |
return new L.Popup(options, source); | |
}; | |
L.Map.include({ | |
openPopup: function (popup, latlng, options) { // (Popup) or (String || HTMLElement, LatLng[, Object]) | |
this.closePopup(); | |
if (!(popup instanceof L.Popup)) { | |
var content = popup; | |
popup = new L.Popup(options) | |
.setLatLng(latlng) | |
.setContent(content); | |
} | |
popup._isOpen = true; | |
this._popup = popup; | |
return this.addLayer(popup); | |
}, | |
closePopup: function (popup) { | |
if (!popup || popup === this._popup) { | |
popup = this._popup; | |
this._popup = null; | |
} | |
if (popup) { | |
this.removeLayer(popup); | |
popup._isOpen = false; | |
} | |
return this; | |
} | |
}); | |
/* | |
* Popup extension to L.Marker, adding popup-related methods. | |
*/ | |
L.Marker.include({ | |
openPopup: function () { | |
if (this._popup && this._map && !this._map.hasLayer(this._popup)) { | |
this._popup.setLatLng(this._latlng); | |
this._map.openPopup(this._popup); | |
} | |
return this; | |
}, | |
closePopup: function () { | |
if (this._popup) { | |
this._popup._close(); | |
} | |
return this; | |
}, | |
togglePopup: function () { | |
if (this._popup) { | |
if (this._popup._isOpen) { | |
this.closePopup(); | |
} else { | |
this.openPopup(); | |
} | |
} | |
return this; | |
}, | |
bindPopup: function (content, options) { | |
var anchor = L.point(this.options.icon.options.popupAnchor || [0, 0]); | |
anchor = anchor.add(L.Popup.prototype.options.offset); | |
if (options && options.offset) { | |
anchor = anchor.add(options.offset); | |
} | |
options = L.extend({offset: anchor}, options); | |
if (!this._popupHandlersAdded) { | |
this | |
.on('click', this.togglePopup, this) | |
.on('remove', this.closePopup, this) | |
.on('move', this._movePopup, this); | |
this._popupHandlersAdded = true; | |
} | |
if (content instanceof L.Popup) { | |
L.setOptions(content, options); | |
this._popup = content; | |
content._source = this; | |
} else { | |
this._popup = new L.Popup(options, this) | |
.setContent(content); | |
} | |
return this; | |
}, | |
setPopupContent: function (content) { | |
if (this._popup) { | |
this._popup.setContent(content); | |
} | |
return this; | |
}, | |
unbindPopup: function () { | |
if (this._popup) { | |
this._popup = null; | |
this | |
.off('click', this.togglePopup, this) | |
.off('remove', this.closePopup, this) | |
.off('move', this._movePopup, this); | |
this._popupHandlersAdded = false; | |
} | |
return this; | |
}, | |
getPopup: function () { | |
return this._popup; | |
}, | |
_movePopup: function (e) { | |
this._popup.setLatLng(e.latlng); | |
} | |
}); | |
/* | |
* L.LayerGroup is a class to combine several layers into one so that | |
* you can manipulate the group (e.g. add/remove it) as one layer. | |
*/ | |
L.LayerGroup = L.Class.extend({ | |
initialize: function (layers) { | |
this._layers = {}; | |
var i, len; | |
if (layers) { | |
for (i = 0, len = layers.length; i < len; i++) { | |
this.addLayer(layers[i]); | |
} | |
} | |
}, | |
addLayer: function (layer) { | |
var id = this.getLayerId(layer); | |
this._layers[id] = layer; | |
if (this._map) { | |
this._map.addLayer(layer); | |
} | |
return this; | |
}, | |
removeLayer: function (layer) { | |
var id = layer in this._layers ? layer : this.getLayerId(layer); | |
if (this._map && this._layers[id]) { | |
this._map.removeLayer(this._layers[id]); | |
} | |
delete this._layers[id]; | |
return this; | |
}, | |
hasLayer: function (layer) { | |
if (!layer) { return false; } | |
return (layer in this._layers || this.getLayerId(layer) in this._layers); | |
}, | |
clearLayers: function () { | |
this.eachLayer(this.removeLayer, this); | |
return this; | |
}, | |
invoke: function (methodName) { | |
var args = Array.prototype.slice.call(arguments, 1), | |
i, layer; | |
for (i in this._layers) { | |
layer = this._layers[i]; | |
if (layer[methodName]) { | |
layer[methodName].apply(layer, args); | |
} | |
} | |
return this; | |
}, | |
onAdd: function (map) { | |
this._map = map; | |
this.eachLayer(map.addLayer, map); | |
}, | |
onRemove: function (map) { | |
this.eachLayer(map.removeLayer, map); | |
this._map = null; | |
}, | |
addTo: function (map) { | |
map.addLayer(this); | |
return this; | |
}, | |
eachLayer: function (method, context) { | |
for (var i in this._layers) { | |
method.call(context, this._layers[i]); | |
} | |
return this; | |
}, | |
getLayer: function (id) { | |
return this._layers[id]; | |
}, | |
getLayers: function () { | |
var layers = []; | |
for (var i in this._layers) { | |
layers.push(this._layers[i]); | |
} | |
return layers; | |
}, | |
setZIndex: function (zIndex) { | |
return this.invoke('setZIndex', zIndex); | |
}, | |
getLayerId: function (layer) { | |
return L.stamp(layer); | |
} | |
}); | |
L.layerGroup = function (layers) { | |
return new L.LayerGroup(layers); | |
}; | |
/* | |
* L.FeatureGroup extends L.LayerGroup by introducing mouse events and additional methods | |
* shared between a group of interactive layers (like vectors or markers). | |
*/ | |
L.FeatureGroup = L.LayerGroup.extend({ | |
includes: L.Mixin.Events, | |
statics: { | |
EVENTS: 'click dblclick mouseover mouseout mousemove contextmenu popupopen popupclose' | |
}, | |
addLayer: function (layer) { | |
if (this.hasLayer(layer)) { | |
return this; | |
} | |
if ('on' in layer) { | |
layer.on(L.FeatureGroup.EVENTS, this._propagateEvent, this); | |
} | |
L.LayerGroup.prototype.addLayer.call(this, layer); | |
if (this._popupContent && layer.bindPopup) { | |
layer.bindPopup(this._popupContent, this._popupOptions); | |
} | |
return this.fire('layeradd', {layer: layer}); | |
}, | |
removeLayer: function (layer) { | |
if (!this.hasLayer(layer)) { | |
return this; | |
} | |
if (layer in this._layers) { | |
layer = this._layers[layer]; | |
} | |
if ('off' in layer) { | |
layer.off(L.FeatureGroup.EVENTS, this._propagateEvent, this); | |
} | |
L.LayerGroup.prototype.removeLayer.call(this, layer); | |
if (this._popupContent) { | |
this.invoke('unbindPopup'); | |
} | |
return this.fire('layerremove', {layer: layer}); | |
}, | |
bindPopup: function (content, options) { | |
this._popupContent = content; | |
this._popupOptions = options; | |
return this.invoke('bindPopup', content, options); | |
}, | |
openPopup: function (latlng) { | |
// open popup on the first layer | |
for (var id in this._layers) { | |
this._layers[id].openPopup(latlng); | |
break; | |
} | |
return this; | |
}, | |
setStyle: function (style) { | |
return this.invoke('setStyle', style); | |
}, | |
bringToFront: function () { | |
return this.invoke('bringToFront'); | |
}, | |
bringToBack: function () { | |
return this.invoke('bringToBack'); | |
}, | |
getBounds: function () { | |
var bounds = new L.LatLngBounds(); | |
this.eachLayer(function (layer) { | |
bounds.extend(layer instanceof L.Marker ? layer.getLatLng() : layer.getBounds()); | |
}); | |
return bounds; | |
}, | |
_propagateEvent: function (e) { | |
e = L.extend({ | |
layer: e.target, | |
target: this | |
}, e); | |
this.fire(e.type, e); | |
} | |
}); | |
L.featureGroup = function (layers) { | |
return new L.FeatureGroup(layers); | |
}; | |
/* | |
* L.Path is a base class for rendering vector paths on a map. Inherited by Polyline, Circle, etc. | |
*/ | |
L.Path = L.Class.extend({ | |
includes: [L.Mixin.Events], | |
statics: { | |
// how much to extend the clip area around the map view | |
// (relative to its size, e.g. 0.5 is half the screen in each direction) | |
// set it so that SVG element doesn't exceed 1280px (vectors flicker on dragend if it is) | |
CLIP_PADDING: (function () { | |
var max = L.Browser.mobile ? 1280 : 2000, | |
target = (max / Math.max(window.outerWidth, window.outerHeight) - 1) / 2; | |
return Math.max(0, Math.min(0.5, target)); | |
})() | |
}, | |
options: { | |
stroke: true, | |
color: '#0033ff', | |
dashArray: null, | |
lineCap: null, | |
lineJoin: null, | |
weight: 5, | |
opacity: 0.5, | |
fill: false, | |
fillColor: null, //same as color by default | |
fillOpacity: 0.2, | |
clickable: true | |
}, | |
initialize: function (options) { | |
L.setOptions(this, options); | |
}, | |
onAdd: function (map) { | |
this._map = map; | |
if (!this._container) { | |
this._initElements(); | |
this._initEvents(); | |
} | |
this.projectLatlngs(); | |
this._updatePath(); | |
if (this._container) { | |
this._map._pathRoot.appendChild(this._container); | |
} | |
this.fire('add'); | |
map.on({ | |
'viewreset': this.projectLatlngs, | |
'moveend': this._updatePath | |
}, this); | |
}, | |
addTo: function (map) { | |
map.addLayer(this); | |
return this; | |
}, | |
onRemove: function (map) { | |
map._pathRoot.removeChild(this._container); | |
// Need to fire remove event before we set _map to null as the event hooks might need the object | |
this.fire('remove'); | |
this._map = null; | |
if (L.Browser.vml) { | |
this._container = null; | |
this._stroke = null; | |
this._fill = null; | |
} | |
map.off({ | |
'viewreset': this.projectLatlngs, | |
'moveend': this._updatePath | |
}, this); | |
}, | |
projectLatlngs: function () { | |
// do all projection stuff here | |
}, | |
setStyle: function (style) { | |
L.setOptions(this, style); | |
if (this._container) { | |
this._updateStyle(); | |
} | |
return this; | |
}, | |
redraw: function () { | |
if (this._map) { | |
this.projectLatlngs(); | |
this._updatePath(); | |
} | |
return this; | |
} | |
}); | |
L.Map.include({ | |
_updatePathViewport: function () { | |
var p = L.Path.CLIP_PADDING, | |
size = this.getSize(), | |
panePos = L.DomUtil.getPosition(this._mapPane), | |
min = panePos.multiplyBy(-1)._subtract(size.multiplyBy(p)._round()), | |
max = min.add(size.multiplyBy(1 + p * 2)._round()); | |
this._pathViewport = new L.Bounds(min, max); | |
} | |
}); | |
/* | |
* Extends L.Path with SVG-specific rendering code. | |
*/ | |
L.Path.SVG_NS = 'http://www.w3.org/2000/svg'; | |
L.Browser.svg = !!(document.createElementNS && document.createElementNS(L.Path.SVG_NS, 'svg').createSVGRect); | |
L.Path = L.Path.extend({ | |
statics: { | |
SVG: L.Browser.svg | |
}, | |
bringToFront: function () { | |
var root = this._map._pathRoot, | |
path = this._container; | |
if (path && root.lastChild !== path) { | |
root.appendChild(path); | |
} | |
return this; | |
}, | |
bringToBack: function () { | |
var root = this._map._pathRoot, | |
path = this._container, | |
first = root.firstChild; | |
if (path && first !== path) { | |
root.insertBefore(path, first); | |
} | |
return this; | |
}, | |
getPathString: function () { | |
// form path string here | |
}, | |
_createElement: function (name) { | |
return document.createElementNS(L.Path.SVG_NS, name); | |
}, | |
_initElements: function () { | |
this._map._initPathRoot(); | |
this._initPath(); | |
this._initStyle(); | |
}, | |
_initPath: function () { | |
this._container = this._createElement('g'); | |
this._path = this._createElement('path'); | |
if (this.options.className) { | |
L.DomUtil.addClass(this._path, this.options.className); | |
} | |
this._container.appendChild(this._path); | |
}, | |
_initStyle: function () { | |
if (this.options.stroke) { | |
this._path.setAttribute('stroke-linejoin', 'round'); | |
this._path.setAttribute('stroke-linecap', 'round'); | |
} | |
if (this.options.fill) { | |
this._path.setAttribute('fill-rule', 'evenodd'); | |
} | |
if (this.options.pointerEvents) { | |
this._path.setAttribute('pointer-events', this.options.pointerEvents); | |
} | |
if (!this.options.clickable && !this.options.pointerEvents) { | |
this._path.setAttribute('pointer-events', 'none'); | |
} | |
this._updateStyle(); | |
}, | |
_updateStyle: function () { | |
if (this.options.stroke) { | |
this._path.setAttribute('stroke', this.options.color); | |
this._path.setAttribute('stroke-opacity', this.options.opacity); | |
this._path.setAttribute('stroke-width', this.options.weight); | |
if (this.options.dashArray) { | |
this._path.setAttribute('stroke-dasharray', this.options.dashArray); | |
} else { | |
this._path.removeAttribute('stroke-dasharray'); | |
} | |
if (this.options.lineCap) { | |
this._path.setAttribute('stroke-linecap', this.options.lineCap); | |
} | |
if (this.options.lineJoin) { | |
this._path.setAttribute('stroke-linejoin', this.options.lineJoin); | |
} | |
} else { | |
this._path.setAttribute('stroke', 'none'); | |
} | |
if (this.options.fill) { | |
this._path.setAttribute('fill', this.options.fillColor || this.options.color); | |
this._path.setAttribute('fill-opacity', this.options.fillOpacity); | |
} else { | |
this._path.setAttribute('fill', 'none'); | |
} | |
}, | |
_updatePath: function () { | |
var str = this.getPathString(); | |
if (!str) { | |
// fix webkit empty string parsing bug | |
str = 'M0 0'; | |
} | |
this._path.setAttribute('d', str); | |
}, | |
// TODO remove duplication with L.Map | |
_initEvents: function () { | |
if (this.options.clickable) { | |
if (L.Browser.svg || !L.Browser.vml) { | |
L.DomUtil.addClass(this._path, 'leaflet-clickable'); | |
} | |
L.DomEvent.on(this._container, 'click', this._onMouseClick, this); | |
var events = ['dblclick', 'mousedown', 'mouseover', | |
'mouseout', 'mousemove', 'contextmenu']; | |
for (var i = 0; i < events.length; i++) { | |
L.DomEvent.on(this._container, events[i], this._fireMouseEvent, this); | |
} | |
} | |
}, | |
_onMouseClick: function (e) { | |
if (this._map.dragging && this._map.dragging.moved()) { return; } | |
this._fireMouseEvent(e); | |
}, | |
_fireMouseEvent: function (e) { | |
if (!this._map || !this.hasEventListeners(e.type)) { return; } | |
var map = this._map, | |
containerPoint = map.mouseEventToContainerPoint(e), | |
layerPoint = map.containerPointToLayerPoint(containerPoint), | |
latlng = map.layerPointToLatLng(layerPoint); | |
this.fire(e.type, { | |
latlng: latlng, | |
layerPoint: layerPoint, | |
containerPoint: containerPoint, | |
originalEvent: e | |
}); | |
if (e.type === 'contextmenu') { | |
L.DomEvent.preventDefault(e); | |
} | |
if (e.type !== 'mousemove') { | |
L.DomEvent.stopPropagation(e); | |
} | |
} | |
}); | |
L.Map.include({ | |
_initPathRoot: function () { | |
if (!this._pathRoot) { | |
this._pathRoot = L.Path.prototype._createElement('svg'); | |
this._panes.overlayPane.appendChild(this._pathRoot); | |
if (this.options.zoomAnimation && L.Browser.any3d) { | |
L.DomUtil.addClass(this._pathRoot, 'leaflet-zoom-animated'); | |
this.on({ | |
'zoomanim': this._animatePathZoom, | |
'zoomend': this._endPathZoom | |
}); | |
} else { | |
L.DomUtil.addClass(this._pathRoot, 'leaflet-zoom-hide'); | |
} | |
this.on('moveend', this._updateSvgViewport); | |
this._updateSvgViewport(); | |
} | |
}, | |
_animatePathZoom: function (e) { | |
var scale = this.getZoomScale(e.zoom), | |
offset = this._getCenterOffset(e.center)._multiplyBy(-scale)._add(this._pathViewport.min); | |
this._pathRoot.style[L.DomUtil.TRANSFORM] = | |
L.DomUtil.getTranslateString(offset) + ' scale(' + scale + ') '; | |
this._pathZooming = true; | |
}, | |
_endPathZoom: function () { | |
this._pathZooming = false; | |
}, | |
_updateSvgViewport: function () { | |
if (this._pathZooming) { | |
// Do not update SVGs while a zoom animation is going on otherwise the animation will break. | |
// When the zoom animation ends we will be updated again anyway | |
// This fixes the case where you do a momentum move and zoom while the move is still ongoing. | |
return; | |
} | |
this._updatePathViewport(); | |
var vp = this._pathViewport, | |
min = vp.min, | |
max = vp.max, | |
width = max.x - min.x, | |
height = max.y - min.y, | |
root = this._pathRoot, | |
pane = this._panes.overlayPane; | |
// Hack to make flicker on drag end on mobile webkit less irritating | |
if (L.Browser.mobileWebkit) { | |
pane.removeChild(root); | |
} | |
L.DomUtil.setPosition(root, min); | |
root.setAttribute('width', width); | |
root.setAttribute('height', height); | |
root.setAttribute('viewBox', [min.x, min.y, width, height].join(' ')); | |
if (L.Browser.mobileWebkit) { | |
pane.appendChild(root); | |
} | |
} | |
}); | |
/* | |
* Popup extension to L.Path (polylines, polygons, circles), adding popup-related methods. | |
*/ | |
L.Path.include({ | |
bindPopup: function (content, options) { | |
if (content instanceof L.Popup) { | |
this._popup = content; | |
} else { | |
if (!this._popup || options) { | |
this._popup = new L.Popup(options, this); | |
} | |
this._popup.setContent(content); | |
} | |
if (!this._popupHandlersAdded) { | |
this | |
.on('click', this._openPopup, this) | |
.on('remove', this.closePopup, this); | |
this._popupHandlersAdded = true; | |
} | |
return this; | |
}, | |
unbindPopup: function () { | |
if (this._popup) { | |
this._popup = null; | |
this | |
.off('click', this._openPopup) | |
.off('remove', this.closePopup); | |
this._popupHandlersAdded = false; | |
} | |
return this; | |
}, | |
openPopup: function (latlng) { | |
if (this._popup) { | |
// open the popup from one of the path's points if not specified | |
latlng = latlng || this._latlng || | |
this._latlngs[Math.floor(this._latlngs.length / 2)]; | |
this._openPopup({latlng: latlng}); | |
} | |
return this; | |
}, | |
closePopup: function () { | |
if (this._popup) { | |
this._popup._close(); | |
} | |
return this; | |
}, | |
_openPopup: function (e) { | |
this._popup.setLatLng(e.latlng); | |
this._map.openPopup(this._popup); | |
} | |
}); | |
/* | |
* Vector rendering for IE6-8 through VML. | |
* Thanks to Dmitry Baranovsky and his Raphael library for inspiration! | |
*/ | |
L.Browser.vml = !L.Browser.svg && (function () { | |
try { | |
var div = document.createElement('div'); | |
div.innerHTML = '<v:shape adj="1"/>'; | |
var shape = div.firstChild; | |
shape.style.behavior = 'url(#default#VML)'; | |
return shape && (typeof shape.adj === 'object'); | |
} catch (e) { | |
return false; | |
} | |
}()); | |
L.Path = L.Browser.svg || !L.Browser.vml ? L.Path : L.Path.extend({ | |
statics: { | |
VML: true, | |
CLIP_PADDING: 0.02 | |
}, | |
_createElement: (function () { | |
try { | |
document.namespaces.add('lvml', 'urn:schemas-microsoft-com:vml'); | |
return function (name) { | |
return document.createElement('<lvml:' + name + ' class="lvml">'); | |
}; | |
} catch (e) { | |
return function (name) { | |
return document.createElement( | |
'<' + name + ' xmlns="urn:schemas-microsoft.com:vml" class="lvml">'); | |
}; | |
} | |
}()), | |
_initPath: function () { | |
var container = this._container = this._createElement('shape'); | |
L.DomUtil.addClass(container, 'leaflet-vml-shape' + | |
(this.options.className ? ' ' + this.options.className : '')); | |
if (this.options.clickable) { | |
L.DomUtil.addClass(container, 'leaflet-clickable'); | |
} | |
container.coordsize = '1 1'; | |
this._path = this._createElement('path'); | |
container.appendChild(this._path); | |
this._map._pathRoot.appendChild(container); | |
}, | |
_initStyle: function () { | |
this._updateStyle(); | |
}, | |
_updateStyle: function () { | |
var stroke = this._stroke, | |
fill = this._fill, | |
options = this.options, | |
container = this._container; | |
container.stroked = options.stroke; | |
container.filled = options.fill; | |
if (options.stroke) { | |
if (!stroke) { | |
stroke = this._stroke = this._createElement('stroke'); | |
stroke.endcap = 'round'; | |
container.appendChild(stroke); | |
} | |
stroke.weight = options.weight + 'px'; | |
stroke.color = options.color; | |
stroke.opacity = options.opacity; | |
if (options.dashArray) { | |
stroke.dashStyle = L.Util.isArray(options.dashArray) ? | |
options.dashArray.join(' ') : | |
options.dashArray.replace(/( *, *)/g, ' '); | |
} else { | |
stroke.dashStyle = ''; | |
} | |
if (options.lineCap) { | |
stroke.endcap = options.lineCap.replace('butt', 'flat'); | |
} | |
if (options.lineJoin) { | |
stroke.joinstyle = options.lineJoin; | |
} | |
} else if (stroke) { | |
container.removeChild(stroke); | |
this._stroke = null; | |
} | |
if (options.fill) { | |
if (!fill) { | |
fill = this._fill = this._createElement('fill'); | |
container.appendChild(fill); | |
} | |
fill.color = options.fillColor || options.color; | |
fill.opacity = options.fillOpacity; | |
} else if (fill) { | |
container.removeChild(fill); | |
this._fill = null; | |
} | |
}, | |
_updatePath: function () { | |
var style = this._container.style; | |
style.display = 'none'; | |
this._path.v = this.getPathString() + ' '; // the space fixes IE empty path string bug | |
style.display = ''; | |
} | |
}); | |
L.Map.include(L.Browser.svg || !L.Browser.vml ? {} : { | |
_initPathRoot: function () { | |
if (this._pathRoot) { return; } | |
var root = this._pathRoot = document.createElement('div'); | |
root.className = 'leaflet-vml-container'; | |
this._panes.overlayPane.appendChild(root); | |
this.on('moveend', this._updatePathViewport); | |
this._updatePathViewport(); | |
} | |
}); | |
/* | |
* Vector rendering for all browsers that support canvas. | |
*/ | |
L.Browser.canvas = (function () { | |
return !!document.createElement('canvas').getContext; | |
}()); | |
L.Path = (L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? L.Path : L.Path.extend({ | |
statics: { | |
//CLIP_PADDING: 0.02, // not sure if there's a need to set it to a small value | |
CANVAS: true, | |
SVG: false | |
}, | |
redraw: function () { | |
if (this._map) { | |
this.projectLatlngs(); | |
this._requestUpdate(); | |
} | |
return this; | |
}, | |
setStyle: function (style) { | |
L.setOptions(this, style); | |
if (this._map) { | |
this._updateStyle(); | |
this._requestUpdate(); | |
} | |
return this; | |
}, | |
onRemove: function (map) { | |
map | |
.off('viewreset', this.projectLatlngs, this) | |
.off('moveend', this._updatePath, this); | |
if (this.options.clickable) { | |
this._map.off('click', this._onClick, this); | |
this._map.off('mousemove', this._onMouseMove, this); | |
} | |
this._requestUpdate(); | |
this.fire('remove'); | |
this._map = null; | |
}, | |
_requestUpdate: function () { | |
if (this._map && !L.Path._updateRequest) { | |
L.Path._updateRequest = L.Util.requestAnimFrame(this._fireMapMoveEnd, this._map); | |
} | |
}, | |
_fireMapMoveEnd: function () { | |
L.Path._updateRequest = null; | |
this.fire('moveend'); | |
}, | |
_initElements: function () { | |
this._map._initPathRoot(); | |
this._ctx = this._map._canvasCtx; | |
}, | |
_updateStyle: function () { | |
var options = this.options; | |
if (options.stroke) { | |
this._ctx.lineWidth = options.weight; | |
this._ctx.strokeStyle = options.color; | |
} | |
if (options.fill) { | |
this._ctx.fillStyle = options.fillColor || options.color; | |
} | |
if (options.lineCap) { | |
this._ctx.lineCap = options.lineCap; | |
} | |
if (options.lineJoin) { | |
this._ctx.lineJoin = options.lineJoin; | |
} | |
}, | |
_drawPath: function () { | |
var i, j, len, len2, point, drawMethod; | |
this._ctx.beginPath(); | |
for (i = 0, len = this._parts.length; i < len; i++) { | |
for (j = 0, len2 = this._parts[i].length; j < len2; j++) { | |
point = this._parts[i][j]; | |
drawMethod = (j === 0 ? 'move' : 'line') + 'To'; | |
this._ctx[drawMethod](point.x, point.y); | |
} | |
// TODO refactor ugly hack | |
if (this instanceof L.Polygon) { | |
this._ctx.closePath(); | |
} | |
} | |
}, | |
_checkIfEmpty: function () { | |
return !this._parts.length; | |
}, | |
_updatePath: function () { | |
if (this._checkIfEmpty()) { return; } | |
var ctx = this._ctx, | |
options = this.options; | |
this._drawPath(); | |
ctx.save(); | |
this._updateStyle(); | |
if (options.fill) { | |
ctx.globalAlpha = options.fillOpacity; | |
ctx.fill(options.fillRule || 'evenodd'); | |
} | |
if (options.stroke) { | |
ctx.globalAlpha = options.opacity; | |
ctx.stroke(); | |
} | |
ctx.restore(); | |
// TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature | |
}, | |
_initEvents: function () { | |
if (this.options.clickable) { | |
this._map.on('mousemove', this._onMouseMove, this); | |
this._map.on('click dblclick contextmenu', this._fireMouseEvent, this); | |
} | |
}, | |
_fireMouseEvent: function (e) { | |
if (this._containsPoint(e.layerPoint)) { | |
this.fire(e.type, e); | |
} | |
}, | |
_onMouseMove: function (e) { | |
if (!this._map || this._map._animatingZoom) { return; } | |
// TODO don't do on each move | |
if (this._containsPoint(e.layerPoint)) { | |
this._ctx.canvas.style.cursor = 'pointer'; | |
this._mouseInside = true; | |
this.fire('mouseover', e); | |
} else if (this._mouseInside) { | |
this._ctx.canvas.style.cursor = ''; | |
this._mouseInside = false; | |
this.fire('mouseout', e); | |
} | |
} | |
}); | |
L.Map.include((L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? {} : { | |
_initPathRoot: function () { | |
var root = this._pathRoot, | |
ctx; | |
if (!root) { | |
root = this._pathRoot = document.createElement('canvas'); | |
root.style.position = 'absolute'; | |
ctx = this._canvasCtx = root.getContext('2d'); | |
ctx.lineCap = 'round'; | |
ctx.lineJoin = 'round'; | |
this._panes.overlayPane.appendChild(root); | |
if (this.options.zoomAnimation) { | |
this._pathRoot.className = 'leaflet-zoom-animated'; | |
this.on('zoomanim', this._animatePathZoom); | |
this.on('zoomend', this._endPathZoom); | |
} | |
this.on('moveend', this._updateCanvasViewport); | |
this._updateCanvasViewport(); | |
} | |
}, | |
_updateCanvasViewport: function () { | |
// don't redraw while zooming. See _updateSvgViewport for more details | |
if (this._pathZooming) { return; } | |
this._updatePathViewport(); | |
var vp = this._pathViewport, | |
min = vp.min, | |
size = vp.max.subtract(min), | |
root = this._pathRoot; | |
//TODO check if this works properly on mobile webkit | |
L.DomUtil.setPosition(root, min); | |
root.width = size.x; | |
root.height = size.y; | |
root.getContext('2d').translate(-min.x, -min.y); | |
} | |
}); | |
/* | |
* L.LineUtil contains different utility functions for line segments | |
* and polylines (clipping, simplification, distances, etc.) | |
*/ | |
/*jshint bitwise:false */ // allow bitwise operations for this file | |
L.LineUtil = { | |
// Simplify polyline with vertex reduction and Douglas-Peucker simplification. | |
// Improves rendering performance dramatically by lessening the number of points to draw. | |
simplify: function (/*Point[]*/ points, /*Number*/ tolerance) { | |
if (!tolerance || !points.length) { | |
return points.slice(); | |
} | |
var sqTolerance = tolerance * tolerance; | |
// stage 1: vertex reduction | |
points = this._reducePoints(points, sqTolerance); | |
// stage 2: Douglas-Peucker simplification | |
points = this._simplifyDP(points, sqTolerance); | |
return points; | |
}, | |
// distance from a point to a segment between two points | |
pointToSegmentDistance: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) { | |
return Math.sqrt(this._sqClosestPointOnSegment(p, p1, p2, true)); | |
}, | |
closestPointOnSegment: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) { | |
return this._sqClosestPointOnSegment(p, p1, p2); | |
}, | |
// Douglas-Peucker simplification, see http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm | |
_simplifyDP: function (points, sqTolerance) { | |
var len = points.length, | |
ArrayConstructor = typeof Uint8Array !== undefined + '' ? Uint8Array : Array, | |
markers = new ArrayConstructor(len); | |
markers[0] = markers[len - 1] = 1; | |
this._simplifyDPStep(points, markers, sqTolerance, 0, len - 1); | |
var i, | |
newPoints = []; | |
for (i = 0; i < len; i++) { | |
if (markers[i]) { | |
newPoints.push(points[i]); | |
} | |
} | |
return newPoints; | |
}, | |
_simplifyDPStep: function (points, markers, sqTolerance, first, last) { | |
var maxSqDist = 0, | |
index, i, sqDist; | |
for (i = first + 1; i <= last - 1; i++) { | |
sqDist = this._sqClosestPointOnSegment(points[i], points[first], points[last], true); | |
if (sqDist > maxSqDist) { | |
index = i; | |
maxSqDist = sqDist; | |
} | |
} | |
if (maxSqDist > sqTolerance) { | |
markers[index] = 1; | |
this._simplifyDPStep(points, markers, sqTolerance, first, index); | |
this._simplifyDPStep(points, markers, sqTolerance, index, last); | |
} | |
}, | |
// reduce points that are too close to each other to a single point | |
_reducePoints: function (points, sqTolerance) { | |
var reducedPoints = [points[0]]; | |
for (var i = 1, prev = 0, len = points.length; i < len; i++) { | |
if (this._sqDist(points[i], points[prev]) > sqTolerance) { | |
reducedPoints.push(points[i]); | |
prev = i; | |
} | |
} | |
if (prev < len - 1) { | |
reducedPoints.push(points[len - 1]); | |
} | |
return reducedPoints; | |
}, | |
// Cohen-Sutherland line clipping algorithm. | |
// Used to avoid rendering parts of a polyline that are not currently visible. | |
clipSegment: function (a, b, bounds, useLastCode) { | |
var codeA = useLastCode ? this._lastCode : this._getBitCode(a, bounds), | |
codeB = this._getBitCode(b, bounds), | |
codeOut, p, newCode; | |
// save 2nd code to avoid calculating it on the next segment | |
this._lastCode = codeB; | |
while (true) { | |
// if a,b is inside the clip window (trivial accept) | |
if (!(codeA | codeB)) { | |
return [a, b]; | |
// if a,b is outside the clip window (trivial reject) | |
} else if (codeA & codeB) { | |
return false; | |
// other cases | |
} else { | |
codeOut = codeA || codeB; | |
p = this._getEdgeIntersection(a, b, codeOut, bounds); | |
newCode = this._getBitCode(p, bounds); | |
if (codeOut === codeA) { | |
a = p; | |
codeA = newCode; | |
} else { | |
b = p; | |
codeB = newCode; | |
} | |
} | |
} | |
}, | |
_getEdgeIntersection: function (a, b, code, bounds) { | |
var dx = b.x - a.x, | |
dy = b.y - a.y, | |
min = bounds.min, | |
max = bounds.max; | |
if (code & 8) { // top | |
return new L.Point(a.x + dx * (max.y - a.y) / dy, max.y); | |
} else if (code & 4) { // bottom | |
return new L.Point(a.x + dx * (min.y - a.y) / dy, min.y); | |
} else if (code & 2) { // right | |
return new L.Point(max.x, a.y + dy * (max.x - a.x) / dx); | |
} else if (code & 1) { // left | |
return new L.Point(min.x, a.y + dy * (min.x - a.x) / dx); | |
} | |
}, | |
_getBitCode: function (/*Point*/ p, bounds) { | |
var code = 0; | |
if (p.x < bounds.min.x) { // left | |
code |= 1; | |
} else if (p.x > bounds.max.x) { // right | |
code |= 2; | |
} | |
if (p.y < bounds.min.y) { // bottom | |
code |= 4; | |
} else if (p.y > bounds.max.y) { // top | |
code |= 8; | |
} | |
return code; | |
}, | |
// square distance (to avoid unnecessary Math.sqrt calls) | |
_sqDist: function (p1, p2) { | |
var dx = p2.x - p1.x, | |
dy = p2.y - p1.y; | |
return dx * dx + dy * dy; | |
}, | |
// return closest point on segment or distance to that point | |
_sqClosestPointOnSegment: function (p, p1, p2, sqDist) { | |
var x = p1.x, | |
y = p1.y, | |
dx = p2.x - x, | |
dy = p2.y - y, | |
dot = dx * dx + dy * dy, | |
t; | |
if (dot > 0) { | |
t = ((p.x - x) * dx + (p.y - y) * dy) / dot; | |
if (t > 1) { | |
x = p2.x; | |
y = p2.y; | |
} else if (t > 0) { | |
x += dx * t; | |
y += dy * t; | |
} | |
} | |
dx = p.x - x; | |
dy = p.y - y; | |
return sqDist ? dx * dx + dy * dy : new L.Point(x, y); | |
} | |
}; | |
/* | |
* L.Polyline is used to display polylines on a map. | |
*/ | |
L.Polyline = L.Path.extend({ | |
initialize: function (latlngs, options) { | |
L.Path.prototype.initialize.call(this, options); | |
this._latlngs = this._convertLatLngs(latlngs); | |
}, | |
options: { | |
// how much to simplify the polyline on each zoom level | |
// more = better performance and smoother look, less = more accurate | |
smoothFactor: 1.0, | |
noClip: false | |
}, | |
projectLatlngs: function () { | |
this._originalPoints = []; | |
for (var i = 0, len = this._latlngs.length; i < len; i++) { | |
this._originalPoints[i] = this._map.latLngToLayerPoint(this._latlngs[i]); | |
} | |
}, | |
getPathString: function () { | |
for (var i = 0, len = this._parts.length, str = ''; i < len; i++) { | |
str += this._getPathPartStr(this._parts[i]); | |
} | |
return str; | |
}, | |
getLatLngs: function () { | |
return this._latlngs; | |
}, | |
setLatLngs: function (latlngs) { | |
this._latlngs = this._convertLatLngs(latlngs); | |
return this.redraw(); | |
}, | |
addLatLng: function (latlng) { | |
this._latlngs.push(L.latLng(latlng)); | |
return this.redraw(); | |
}, | |
spliceLatLngs: function () { // (Number index, Number howMany) | |
var removed = [].splice.apply(this._latlngs, arguments); | |
this._convertLatLngs(this._latlngs, true); | |
this.redraw(); | |
return removed; | |
}, | |
closestLayerPoint: function (p) { | |
var minDistance = Infinity, parts = this._parts, p1, p2, minPoint = null; | |
for (var j = 0, jLen = parts.length; j < jLen; j++) { | |
var points = parts[j]; | |
for (var i = 1, len = points.length; i < len; i++) { | |
p1 = points[i - 1]; | |
p2 = points[i]; | |
var sqDist = L.LineUtil._sqClosestPointOnSegment(p, p1, p2, true); | |
if (sqDist < minDistance) { | |
minDistance = sqDist; | |
minPoint = L.LineUtil._sqClosestPointOnSegment(p, p1, p2); | |
} | |
} | |
} | |
if (minPoint) { | |
minPoint.distance = Math.sqrt(minDistance); | |
} | |
return minPoint; | |
}, | |
getBounds: function () { | |
return new L.LatLngBounds(this.getLatLngs()); | |
}, | |
_convertLatLngs: function (latlngs, overwrite) { | |
var i, len, target = overwrite ? latlngs : []; | |
for (i = 0, len = latlngs.length; i < len; i++) { | |
if (L.Util.isArray(latlngs[i]) && typeof latlngs[i][0] !== 'number') { | |
return; | |
} | |
target[i] = L.latLng(latlngs[i]); | |
} | |
return target; | |
}, | |
_initEvents: function () { | |
L.Path.prototype._initEvents.call(this); | |
}, | |
_getPathPartStr: function (points) { | |
var round = L.Path.VML; | |
for (var j = 0, len2 = points.length, str = '', p; j < len2; j++) { | |
p = points[j]; | |
if (round) { | |
p._round(); | |
} | |
str += (j ? 'L' : 'M') + p.x + ' ' + p.y; | |
} | |
return str; | |
}, | |
_clipPoints: function () { | |
var points = this._originalPoints, | |
len = points.length, | |
i, k, segment; | |
if (this.options.noClip) { | |
this._parts = [points]; | |
return; | |
} | |
this._parts = []; | |
var parts = this._parts, | |
vp = this._map._pathViewport, | |
lu = L.LineUtil; | |
for (i = 0, k = 0; i < len - 1; i++) { | |
segment = lu.clipSegment(points[i], points[i + 1], vp, i); | |
if (!segment) { | |
continue; | |
} | |
parts[k] = parts[k] || []; | |
parts[k].push(segment[0]); | |
// if segment goes out of screen, or it's the last one, it's the end of the line part | |
if ((segment[1] !== points[i + 1]) || (i === len - 2)) { | |
parts[k].push(segment[1]); | |
k++; | |
} | |
} | |
}, | |
// simplify each clipped part of the polyline | |
_simplifyPoints: function () { | |
var parts = this._parts, | |
lu = L.LineUtil; | |
for (var i = 0, len = parts.length; i < len; i++) { | |
parts[i] = lu.simplify(parts[i], this.options.smoothFactor); | |
} | |
}, | |
_updatePath: function () { | |
if (!this._map) { return; } | |
this._clipPoints(); | |
this._simplifyPoints(); | |
L.Path.prototype._updatePath.call(this); | |
} | |
}); | |
L.polyline = function (latlngs, options) { | |
return new L.Polyline(latlngs, options); | |
}; | |
/* | |
* L.PolyUtil contains utility functions for polygons (clipping, etc.). | |
*/ | |
/*jshint bitwise:false */ // allow bitwise operations here | |
L.PolyUtil = {}; | |
/* | |
* Sutherland-Hodgeman polygon clipping algorithm. | |
* Used to avoid rendering parts of a polygon that are not currently visible. | |
*/ | |
L.PolyUtil.clipPolygon = function (points, bounds) { | |
var clippedPoints, | |
edges = [1, 4, 2, 8], | |
i, j, k, | |
a, b, | |
len, edge, p, | |
lu = L.LineUtil; | |
for (i = 0, len = points.length; i < len; i++) { | |
points[i]._code = lu._getBitCode(points[i], bounds); | |
} | |
// for each edge (left, bottom, right, top) | |
for (k = 0; k < 4; k++) { | |
edge = edges[k]; | |
clippedPoints = []; | |
for (i = 0, len = points.length, j = len - 1; i < len; j = i++) { | |
a = points[i]; | |
b = points[j]; | |
// if a is inside the clip window | |
if (!(a._code & edge)) { | |
// if b is outside the clip window (a->b goes out of screen) | |
if (b._code & edge) { | |
p = lu._getEdgeIntersection(b, a, edge, bounds); | |
p._code = lu._getBitCode(p, bounds); | |
clippedPoints.push(p); | |
} | |
clippedPoints.push(a); | |
// else if b is inside the clip window (a->b enters the screen) | |
} else if (!(b._code & edge)) { | |
p = lu._getEdgeIntersection(b, a, edge, bounds); | |
p._code = lu._getBitCode(p, bounds); | |
clippedPoints.push(p); | |
} | |
} | |
points = clippedPoints; | |
} | |
return points; | |
}; | |
/* | |
* L.Polygon is used to display polygons on a map. | |
*/ | |
L.Polygon = L.Polyline.extend({ | |
options: { | |
fill: true | |
}, | |
initialize: function (latlngs, options) { | |
L.Polyline.prototype.initialize.call(this, latlngs, options); | |
this._initWithHoles(latlngs); | |
}, | |
_initWithHoles: function (latlngs) { | |
var i, len, hole; | |
if (latlngs && L.Util.isArray(latlngs[0]) && (typeof latlngs[0][0] !== 'number')) { | |
this._latlngs = this._convertLatLngs(latlngs[0]); | |
this._holes = latlngs.slice(1); | |
for (i = 0, len = this._holes.length; i < len; i++) { | |
hole = this._holes[i] = this._convertLatLngs(this._holes[i]); | |
if (hole[0].equals(hole[hole.length - 1])) { | |
hole.pop(); | |
} | |
} | |
} | |
// filter out last point if its equal to the first one | |
latlngs = this._latlngs; | |
if (latlngs.length >= 2 && latlngs[0].equals(latlngs[latlngs.length - 1])) { | |
latlngs.pop(); | |
} | |
}, | |
projectLatlngs: function () { | |
L.Polyline.prototype.projectLatlngs.call(this); | |
// project polygon holes points | |
// TODO move this logic to Polyline to get rid of duplication | |
this._holePoints = []; | |
if (!this._holes) { return; } | |
var i, j, len, len2; | |
for (i = 0, len = this._holes.length; i < len; i++) { | |
this._holePoints[i] = []; | |
for (j = 0, len2 = this._holes[i].length; j < len2; j++) { | |
this._holePoints[i][j] = this._map.latLngToLayerPoint(this._holes[i][j]); | |
} | |
} | |
}, | |
setLatLngs: function (latlngs) { | |
if (latlngs && L.Util.isArray(latlngs[0]) && (typeof latlngs[0][0] !== 'number')) { | |
this._initWithHoles(latlngs); | |
return this.redraw(); | |
} else { | |
return L.Polyline.prototype.setLatLngs.call(this, latlngs); | |
} | |
}, | |
_clipPoints: function () { | |
var points = this._originalPoints, | |
newParts = []; | |
this._parts = [points].concat(this._holePoints); | |
if (this.options.noClip) { return; } | |
for (var i = 0, len = this._parts.length; i < len; i++) { | |
var clipped = L.PolyUtil.clipPolygon(this._parts[i], this._map._pathViewport); | |
if (clipped.length) { | |
newParts.push(clipped); | |
} | |
} | |
this._parts = newParts; | |
}, | |
_getPathPartStr: function (points) { | |
var str = L.Polyline.prototype._getPathPartStr.call(this, points); | |
return str + (L.Browser.svg ? 'z' : 'x'); | |
} | |
}); | |
L.polygon = function (latlngs, options) { | |
return new L.Polygon(latlngs, options); | |
}; | |
/* | |
* Contains L.MultiPolyline and L.MultiPolygon layers. | |
*/ | |
(function () { | |
function createMulti(Klass) { | |
return L.FeatureGroup.extend({ | |
initialize: function (latlngs, options) { | |
this._layers = {}; | |
this._options = options; | |
this.setLatLngs(latlngs); | |
}, | |
setLatLngs: function (latlngs) { | |
var i = 0, | |
len = latlngs.length; | |
this.eachLayer(function (layer) { | |
if (i < len) { | |
layer.setLatLngs(latlngs[i++]); | |
} else { | |
this.removeLayer(layer); | |
} | |
}, this); | |
while (i < len) { | |
this.addLayer(new Klass(latlngs[i++], this._options)); | |
} | |
return this; | |
}, | |
getLatLngs: function () { | |
var latlngs = []; | |
this.eachLayer(function (layer) { | |
latlngs.push(layer.getLatLngs()); | |
}); | |
return latlngs; | |
} | |
}); | |
} | |
L.MultiPolyline = createMulti(L.Polyline); | |
L.MultiPolygon = createMulti(L.Polygon); | |
L.multiPolyline = function (latlngs, options) { | |
return new L.MultiPolyline(latlngs, options); | |
}; | |
L.multiPolygon = function (latlngs, options) { | |
return new L.MultiPolygon(latlngs, options); | |
}; | |
}()); | |
/* | |
* L.Rectangle extends Polygon and creates a rectangle when passed a LatLngBounds object. | |
*/ | |
L.Rectangle = L.Polygon.extend({ | |
initialize: function (latLngBounds, options) { | |
L.Polygon.prototype.initialize.call(this, this._boundsToLatLngs(latLngBounds), options); | |
}, | |
setBounds: function (latLngBounds) { | |
this.setLatLngs(this._boundsToLatLngs(latLngBounds)); | |
}, | |
_boundsToLatLngs: function (latLngBounds) { | |
latLngBounds = L.latLngBounds(latLngBounds); | |
return [ | |
latLngBounds.getSouthWest(), | |
latLngBounds.getNorthWest(), | |
latLngBounds.getNorthEast(), | |
latLngBounds.getSouthEast() | |
]; | |
} | |
}); | |
L.rectangle = function (latLngBounds, options) { | |
return new L.Rectangle(latLngBounds, options); | |
}; | |
/* | |
* L.Circle is a circle overlay (with a certain radius in meters). | |
*/ | |
L.Circle = L.Path.extend({ | |
initialize: function (latlng, radius, options) { | |
L.Path.prototype.initialize.call(this, options); | |
this._latlng = L.latLng(latlng); | |
this._mRadius = radius; | |
}, | |
options: { | |
fill: true | |
}, | |
setLatLng: function (latlng) { | |
this._latlng = L.latLng(latlng); | |
return this.redraw(); | |
}, | |
setRadius: function (radius) { | |
this._mRadius = radius; | |
return this.redraw(); | |
}, | |
projectLatlngs: function () { | |
var lngRadius = this._getLngRadius(), | |
latlng = this._latlng, | |
pointLeft = this._map.latLngToLayerPoint([latlng.lat, latlng.lng - lngRadius]); | |
this._point = this._map.latLngToLayerPoint(latlng); | |
this._radius = Math.max(this._point.x - pointLeft.x, 1); | |
}, | |
getBounds: function () { | |
var lngRadius = this._getLngRadius(), | |
latRadius = (this._mRadius / 40075017) * 360, | |
latlng = this._latlng; | |
return new L.LatLngBounds( | |
[latlng.lat - latRadius, latlng.lng - lngRadius], | |
[latlng.lat + latRadius, latlng.lng + lngRadius]); | |
}, | |
getLatLng: function () { | |
return this._latlng; | |
}, | |
getPathString: function () { | |
var p = this._point, | |
r = this._radius; | |
if (this._checkIfEmpty()) { | |
return ''; | |
} | |
if (L.Browser.svg) { | |
return 'M' + p.x + ',' + (p.y - r) + | |
'A' + r + ',' + r + ',0,1,1,' + | |
(p.x - 0.1) + ',' + (p.y - r) + ' z'; | |
} else { | |
p._round(); | |
r = Math.round(r); | |
return 'AL ' + p.x + ',' + p.y + ' ' + r + ',' + r + ' 0,' + (65535 * 360); | |
} | |
}, | |
getRadius: function () { | |
return this._mRadius; | |
}, | |
// TODO Earth hardcoded, move into projection code! | |
_getLatRadius: function () { | |
return (this._mRadius / 40075017) * 360; | |
}, | |
_getLngRadius: function () { | |
return this._getLatRadius() / Math.cos(L.LatLng.DEG_TO_RAD * this._latlng.lat); | |
}, | |
_checkIfEmpty: function () { | |
if (!this._map) { | |
return false; | |
} | |
var vp = this._map._pathViewport, | |
r = this._radius, | |
p = this._point; | |
return p.x - r > vp.max.x || p.y - r > vp.max.y || | |
p.x + r < vp.min.x || p.y + r < vp.min.y; | |
} | |
}); | |
L.circle = function (latlng, radius, options) { | |
return new L.Circle(latlng, radius, options); | |
}; | |
/* | |
* L.CircleMarker is a circle overlay with a permanent pixel radius. | |
*/ | |
L.CircleMarker = L.Circle.extend({ | |
options: { | |
radius: 10, | |
weight: 2 | |
}, | |
initialize: function (latlng, options) { | |
L.Circle.prototype.initialize.call(this, latlng, null, options); | |
this._radius = this.options.radius; | |
}, | |
projectLatlngs: function () { | |
this._point = this._map.latLngToLayerPoint(this._latlng); | |
}, | |
_updateStyle : function () { | |
L.Circle.prototype._updateStyle.call(this); | |
this.setRadius(this.options.radius); | |
}, | |
setLatLng: function (latlng) { | |
L.Circle.prototype.setLatLng.call(this, latlng); | |
if (this._popup && this._popup._isOpen) { | |
this._popup.setLatLng(latlng); | |
} | |
return this; | |
}, | |
setRadius: function (radius) { | |
this.options.radius = this._radius = radius; | |
return this.redraw(); | |
}, | |
getRadius: function () { | |
return this._radius; | |
} | |
}); | |
L.circleMarker = function (latlng, options) { | |
return new L.CircleMarker(latlng, options); | |
}; | |
/* | |
* Extends L.Polyline to be able to manually detect clicks on Canvas-rendered polylines. | |
*/ | |
L.Polyline.include(!L.Path.CANVAS ? {} : { | |
_containsPoint: function (p, closed) { | |
var i, j, k, len, len2, dist, part, | |
w = this.options.weight / 2; | |
if (L.Browser.touch) { | |
w += 10; // polyline click tolerance on touch devices | |
} | |
for (i = 0, len = this._parts.length; i < len; i++) { | |
part = this._parts[i]; | |
for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) { | |
if (!closed && (j === 0)) { | |
continue; | |
} | |
dist = L.LineUtil.pointToSegmentDistance(p, part[k], part[j]); | |
if (dist <= w) { | |
return true; | |
} | |
} | |
} | |
return false; | |
} | |
}); | |
/* | |
* Extends L.Polygon to be able to manually detect clicks on Canvas-rendered polygons. | |
*/ | |
L.Polygon.include(!L.Path.CANVAS ? {} : { | |
_containsPoint: function (p) { | |
var inside = false, | |
part, p1, p2, | |
i, j, k, | |
len, len2; | |
// TODO optimization: check if within bounds first | |
if (L.Polyline.prototype._containsPoint.call(this, p, true)) { | |
// click on polygon border | |
return true; | |
} | |
// ray casting algorithm for detecting if point is in polygon | |
for (i = 0, len = this._parts.length; i < len; i++) { | |
part = this._parts[i]; | |
for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) { | |
p1 = part[j]; | |
p2 = part[k]; | |
if (((p1.y > p.y) !== (p2.y > p.y)) && | |
(p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) { | |
inside = !inside; | |
} | |
} | |
} | |
return inside; | |
} | |
}); | |
/* | |
* Extends L.Circle with Canvas-specific code. | |
*/ | |
L.Circle.include(!L.Path.CANVAS ? {} : { | |
_drawPath: function () { | |
var p = this._point; | |
this._ctx.beginPath(); | |
this._ctx.arc(p.x, p.y, this._radius, 0, Math.PI * 2, false); | |
}, | |
_containsPoint: function (p) { | |
var center = this._point, | |
w2 = this.options.stroke ? this.options.weight / 2 : 0; | |
return (p.distanceTo(center) <= this._radius + w2); | |
} | |
}); | |
/* | |
* CircleMarker canvas specific drawing parts. | |
*/ | |
L.CircleMarker.include(!L.Path.CANVAS ? {} : { | |
_updateStyle: function () { | |
L.Path.prototype._updateStyle.call(this); | |
} | |
}); | |
/* | |
* L.GeoJSON turns any GeoJSON data into a Leaflet layer. | |
*/ | |
L.GeoJSON = L.FeatureGroup.extend({ | |
initialize: function (geojson, options) { | |
L.setOptions(this, options); | |
this._layers = {}; | |
if (geojson) { | |
this.addData(geojson); | |
} | |
}, | |
addData: function (geojson) { | |
var features = L.Util.isArray(geojson) ? geojson : geojson.features, | |
i, len, feature; | |
if (features) { | |
for (i = 0, len = features.length; i < len; i++) { | |
// Only add this if geometry or geometries are set and not null | |
feature = features[i]; | |
if (feature.geometries || feature.geometry || feature.features || feature.coordinates) { | |
this.addData(features[i]); | |
} | |
} | |
return this; | |
} | |
var options = this.options; | |
if (options.filter && !options.filter(geojson)) { return; } | |
var layer = L.GeoJSON.geometryToLayer(geojson, options.pointToLayer, options.coordsToLatLng, options); | |
layer.feature = L.GeoJSON.asFeature(geojson); | |
layer.defaultOptions = layer.options; | |
this.resetStyle(layer); | |
if (options.onEachFeature) { | |
options.onEachFeature(geojson, layer); | |
} | |
return this.addLayer(layer); | |
}, | |
resetStyle: function (layer) { | |
var style = this.options.style; | |
if (style) { | |
// reset any custom styles | |
L.Util.extend(layer.options, layer.defaultOptions); | |
this._setLayerStyle(layer, style); | |
} | |
}, | |
setStyle: function (style) { | |
this.eachLayer(function (layer) { | |
this._setLayerStyle(layer, style); | |
}, this); | |
}, | |
_setLayerStyle: function (layer, style) { | |
if (typeof style === 'function') { | |
style = style(layer.feature); | |
} | |
if (layer.setStyle) { | |
layer.setStyle(style); | |
} | |
} | |
}); | |
L.extend(L.GeoJSON, { | |
geometryToLayer: function (geojson, pointToLayer, coordsToLatLng, vectorOptions) { | |
var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson, | |
coords = geometry.coordinates, | |
layers = [], | |
latlng, latlngs, i, len; | |
coordsToLatLng = coordsToLatLng || this.coordsToLatLng; | |
switch (geometry.type) { | |
case 'Point': | |
latlng = coordsToLatLng(coords); | |
return pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng); | |
case 'MultiPoint': | |
for (i = 0, len = coords.length; i < len; i++) { | |
latlng = coordsToLatLng(coords[i]); | |
layers.push(pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng)); | |
} | |
return new L.FeatureGroup(layers); | |
case 'LineString': | |
latlngs = this.coordsToLatLngs(coords, 0, coordsToLatLng); | |
return new L.Polyline(latlngs, vectorOptions); | |
case 'Polygon': | |
if (coords.length === 2 && !coords[1].length) { | |
throw new Error('Invalid GeoJSON object.'); | |
} | |
latlngs = this.coordsToLatLngs(coords, 1, coordsToLatLng); | |
return new L.Polygon(latlngs, vectorOptions); | |
case 'MultiLineString': | |
latlngs = this.coordsToLatLngs(coords, 1, coordsToLatLng); | |
return new L.MultiPolyline(latlngs, vectorOptions); | |
case 'MultiPolygon': | |
latlngs = this.coordsToLatLngs(coords, 2, coordsToLatLng); | |
return new L.MultiPolygon(latlngs, vectorOptions); | |
case 'GeometryCollection': | |
for (i = 0, len = geometry.geometries.length; i < len; i++) { | |
layers.push(this.geometryToLayer({ | |
geometry: geometry.geometries[i], | |
type: 'Feature', | |
properties: geojson.properties | |
}, pointToLayer, coordsToLatLng, vectorOptions)); | |
} | |
return new L.FeatureGroup(layers); | |
default: | |
throw new Error('Invalid GeoJSON object.'); | |
} | |
}, | |
coordsToLatLng: function (coords) { // (Array[, Boolean]) -> LatLng | |
return new L.LatLng(coords[1], coords[0], coords[2]); | |
}, | |
coordsToLatLngs: function (coords, levelsDeep, coordsToLatLng) { // (Array[, Number, Function]) -> Array | |
var latlng, i, len, | |
latlngs = []; | |
for (i = 0, len = coords.length; i < len; i++) { | |
latlng = levelsDeep ? | |
this.coordsToLatLngs(coords[i], levelsDeep - 1, coordsToLatLng) : | |
(coordsToLatLng || this.coordsToLatLng)(coords[i]); | |
latlngs.push(latlng); | |
} | |
return latlngs; | |
}, | |
latLngToCoords: function (latlng) { | |
var coords = [latlng.lng, latlng.lat]; | |
if (latlng.alt !== undefined) { | |
coords.push(latlng.alt); | |
} | |
return coords; | |
}, | |
latLngsToCoords: function (latLngs) { | |
var coords = []; | |
for (var i = 0, len = latLngs.length; i < len; i++) { | |
coords.push(L.GeoJSON.latLngToCoords(latLngs[i])); | |
} | |
return coords; | |
}, | |
getFeature: function (layer, newGeometry) { | |
return layer.feature ? L.extend({}, layer.feature, {geometry: newGeometry}) : L.GeoJSON.asFeature(newGeometry); | |
}, | |
asFeature: function (geoJSON) { | |
if (geoJSON.type === 'Feature') { | |
return geoJSON; | |
} | |
return { | |
type: 'Feature', | |
properties: {}, | |
geometry: geoJSON | |
}; | |
} | |
}); | |
var PointToGeoJSON = { | |
toGeoJSON: function () { | |
return L.GeoJSON.getFeature(this, { | |
type: 'Point', | |
coordinates: L.GeoJSON.latLngToCoords(this.getLatLng()) | |
}); | |
} | |
}; | |
L.Marker.include(PointToGeoJSON); | |
L.Circle.include(PointToGeoJSON); | |
L.CircleMarker.include(PointToGeoJSON); | |
L.Polyline.include({ | |
toGeoJSON: function () { | |
return L.GeoJSON.getFeature(this, { | |
type: 'LineString', | |
coordinates: L.GeoJSON.latLngsToCoords(this.getLatLngs()) | |
}); | |
} | |
}); | |
L.Polygon.include({ | |
toGeoJSON: function () { | |
var coords = [L.GeoJSON.latLngsToCoords(this.getLatLngs())], | |
i, len, hole; | |
coords[0].push(coords[0][0]); | |
if (this._holes) { | |
for (i = 0, len = this._holes.length; i < len; i++) { | |
hole = L.GeoJSON.latLngsToCoords(this._holes[i]); | |
hole.push(hole[0]); | |
coords.push(hole); | |
} | |
} | |
return L.GeoJSON.getFeature(this, { | |
type: 'Polygon', | |
coordinates: coords | |
}); | |
} | |
}); | |
(function () { | |
function multiToGeoJSON(type) { | |
return function () { | |
var coords = []; | |
this.eachLayer(function (layer) { | |
coords.push(layer.toGeoJSON().geometry.coordinates); | |
}); | |
return L.GeoJSON.getFeature(this, { | |
type: type, | |
coordinates: coords | |
}); | |
}; | |
} | |
L.MultiPolyline.include({toGeoJSON: multiToGeoJSON('MultiLineString')}); | |
L.MultiPolygon.include({toGeoJSON: multiToGeoJSON('MultiPolygon')}); | |
L.LayerGroup.include({ | |
toGeoJSON: function () { | |
var geometry = this.feature && this.feature.geometry, | |
jsons = [], | |
json; | |
if (geometry && geometry.type === 'MultiPoint') { | |
return multiToGeoJSON('MultiPoint').call(this); | |
} | |
var isGeometryCollection = geometry && geometry.type === 'GeometryCollection'; | |
this.eachLayer(function (layer) { | |
if (layer.toGeoJSON) { | |
json = layer.toGeoJSON(); | |
jsons.push(isGeometryCollection ? json.geometry : L.GeoJSON.asFeature(json)); | |
} | |
}); | |
if (isGeometryCollection) { | |
return L.GeoJSON.getFeature(this, { | |
geometries: jsons, | |
type: 'GeometryCollection' | |
}); | |
} | |
return { | |
type: 'FeatureCollection', | |
features: jsons | |
}; | |
} | |
}); | |
}()); | |
L.geoJson = function (geojson, options) { | |
return new L.GeoJSON(geojson, options); | |
}; | |
/* | |
* L.DomEvent contains functions for working with DOM events. | |
*/ | |
L.DomEvent = { | |
/* inspired by John Resig, Dean Edwards and YUI addEvent implementations */ | |
addListener: function (obj, type, fn, context) { // (HTMLElement, String, Function[, Object]) | |
var id = L.stamp(fn), | |
key = '_leaflet_' + type + id, | |
handler, originalHandler, newType; | |
if (obj[key]) { return this; } | |
handler = function (e) { | |
return fn.call(context || obj, e || L.DomEvent._getEvent()); | |
}; | |
if (L.Browser.pointer && type.indexOf('touch') === 0) { | |
return this.addPointerListener(obj, type, handler, id); | |
} | |
if (L.Browser.touch && (type === 'dblclick') && this.addDoubleTapListener) { | |
this.addDoubleTapListener(obj, handler, id); | |
} | |
if ('addEventListener' in obj) { | |
if (type === 'mousewheel') { | |
obj.addEventListener('DOMMouseScroll', handler, false); | |
obj.addEventListener(type, handler, false); | |
} else if ((type === 'mouseenter') || (type === 'mouseleave')) { | |
originalHandler = handler; | |
newType = (type === 'mouseenter' ? 'mouseover' : 'mouseout'); | |
handler = function (e) { | |
if (!L.DomEvent._checkMouse(obj, e)) { return; } | |
return originalHandler(e); | |
}; | |
obj.addEventListener(newType, handler, false); | |
} else if (type === 'click' && L.Browser.android) { | |
originalHandler = handler; | |
handler = function (e) { | |
return L.DomEvent._filterClick(e, originalHandler); | |
}; | |
obj.addEventListener(type, handler, false); | |
} else { | |
obj.addEventListener(type, handler, false); | |
} | |
} else if ('attachEvent' in obj) { | |
obj.attachEvent('on' + type, handler); | |
} | |
obj[key] = handler; | |
return this; | |
}, | |
removeListener: function (obj, type, fn) { // (HTMLElement, String, Function) | |
var id = L.stamp(fn), | |
key = '_leaflet_' + type + id, | |
handler = obj[key]; | |
if (!handler) { return this; } | |
if (L.Browser.pointer && type.indexOf('touch') === 0) { | |
this.removePointerListener(obj, type, id); | |
} else if (L.Browser.touch && (type === 'dblclick') && this.removeDoubleTapListener) { | |
this.removeDoubleTapListener(obj, id); | |
} else if ('removeEventListener' in obj) { | |
if (type === 'mousewheel') { | |
obj.removeEventListener('DOMMouseScroll', handler, false); | |
obj.removeEventListener(type, handler, false); | |
} else if ((type === 'mouseenter') || (type === 'mouseleave')) { | |
obj.removeEventListener((type === 'mouseenter' ? 'mouseover' : 'mouseout'), handler, false); | |
} else { | |
obj.removeEventListener(type, handler, false); | |
} | |
} else if ('detachEvent' in obj) { | |
obj.detachEvent('on' + type, handler); | |
} | |
obj[key] = null; | |
return this; | |
}, | |
stopPropagation: function (e) { | |
if (e.stopPropagation) { | |
e.stopPropagation(); | |
} else { | |
e.cancelBubble = true; | |
} | |
L.DomEvent._skipped(e); | |
return this; | |
}, | |
disableScrollPropagation: function (el) { | |
var stop = L.DomEvent.stopPropagation; | |
return L.DomEvent | |
.on(el, 'mousewheel', stop) | |
.on(el, 'MozMousePixelScroll', stop); | |
}, | |
disableClickPropagation: function (el) { | |
var stop = L.DomEvent.stopPropagation; | |
for (var i = L.Draggable.START.length - 1; i >= 0; i--) { | |
L.DomEvent.on(el, L.Draggable.START[i], stop); | |
} | |
return L.DomEvent | |
.on(el, 'click', L.DomEvent._fakeStop) | |
.on(el, 'dblclick', stop); | |
}, | |
preventDefault: function (e) { | |
if (e.preventDefault) { | |
e.preventDefault(); | |
} else { | |
e.returnValue = false; | |
} | |
return this; | |
}, | |
stop: function (e) { | |
return L.DomEvent | |
.preventDefault(e) | |
.stopPropagation(e); | |
}, | |
getMousePosition: function (e, container) { | |
if (!container) { | |
return new L.Point(e.clientX, e.clientY); | |
} | |
var rect = container.getBoundingClientRect(); | |
return new L.Point( | |
e.clientX - rect.left - container.clientLeft, | |
e.clientY - rect.top - container.clientTop); | |
}, | |
getWheelDelta: function (e) { | |
var delta = 0; | |
if (e.wheelDelta) { | |
delta = e.wheelDelta / 120; | |
} | |
if (e.detail) { | |
delta = -e.detail / 3; | |
} | |
return delta; | |
}, | |
_skipEvents: {}, | |
_fakeStop: function (e) { | |
// fakes stopPropagation by setting a special event flag, checked/reset with L.DomEvent._skipped(e) | |
L.DomEvent._skipEvents[e.type] = true; | |
}, | |
_skipped: function (e) { | |
var skipped = this._skipEvents[e.type]; | |
// reset when checking, as it's only used in map container and propagates outside of the map | |
this._skipEvents[e.type] = false; | |
return skipped; | |
}, | |
// check if element really left/entered the event target (for mouseenter/mouseleave) | |
_checkMouse: function (el, e) { | |
var related = e.relatedTarget; | |
if (!related) { return true; } | |
try { | |
while (related && (related !== el)) { | |
related = related.parentNode; | |
} | |
} catch (err) { | |
return false; | |
} | |
return (related !== el); | |
}, | |
_getEvent: function () { // evil magic for IE | |
/*jshint noarg:false */ | |
var e = window.event; | |
if (!e) { | |
var caller = arguments.callee.caller; | |
while (caller) { | |
e = caller['arguments'][0]; | |
if (e && window.Event === e.constructor) { | |
break; | |
} | |
caller = caller.caller; | |
} | |
} | |
return e; | |
}, | |
// this is a horrible workaround for a bug in Android where a single touch triggers two click events | |
_filterClick: function (e, handler) { | |
var timeStamp = (e.timeStamp || e.originalEvent.timeStamp), | |
elapsed = L.DomEvent._lastClick && (timeStamp - L.DomEvent._lastClick); | |
// are they closer together than 500ms yet more than 100ms? | |
// Android typically triggers them ~300ms apart while multiple listeners | |
// on the same event should be triggered far faster; | |
// or check if click is simulated on the element, and if it is, reject any non-simulated events | |
if ((elapsed && elapsed > 100 && elapsed < 500) || (e.target._simulatedClick && !e._simulated)) { | |
L.DomEvent.stop(e); | |
return; | |
} | |
L.DomEvent._lastClick = timeStamp; | |
return handler(e); | |
} | |
}; | |
L.DomEvent.on = L.DomEvent.addListener; | |
L.DomEvent.off = L.DomEvent.removeListener; | |
/* | |
* L.Draggable allows you to add dragging capabilities to any element. Supports mobile devices too. | |
*/ | |
L.Draggable = L.Class.extend({ | |
includes: L.Mixin.Events, | |
statics: { | |
START: L.Browser.touch ? ['touchstart', 'mousedown'] : ['mousedown'], | |
END: { | |
mousedown: 'mouseup', | |
touchstart: 'touchend', | |
pointerdown: 'touchend', | |
MSPointerDown: 'touchend' | |
}, | |
MOVE: { | |
mousedown: 'mousemove', | |
touchstart: 'touchmove', | |
pointerdown: 'touchmove', | |
MSPointerDown: 'touchmove' | |
} | |
}, | |
initialize: function (element, dragStartTarget) { | |
this._element = element; | |
this._dragStartTarget = dragStartTarget || element; | |
}, | |
enable: function () { | |
if (this._enabled) { return; } | |
for (var i = L.Draggable.START.length - 1; i >= 0; i--) { | |
L.DomEvent.on(this._dragStartTarget, L.Draggable.START[i], this._onDown, this); | |
} | |
this._enabled = true; | |
}, | |
disable: function () { | |
if (!this._enabled) { return; } | |
for (var i = L.Draggable.START.length - 1; i >= 0; i--) { | |
L.DomEvent.off(this._dragStartTarget, L.Draggable.START[i], this._onDown, this); | |
} | |
this._enabled = false; | |
this._moved = false; | |
}, | |
_onDown: function (e) { | |
this._moved = false; | |
if (e.shiftKey || ((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; } | |
L.DomEvent.stopPropagation(e); | |
if (L.Draggable._disabled) { return; } | |
L.DomUtil.disableImageDrag(); | |
L.DomUtil.disableTextSelection(); | |
if (this._moving) { return; } | |
var first = e.touches ? e.touches[0] : e; | |
this._startPoint = new L.Point(first.clientX, first.clientY); | |
this._startPos = this._newPos = L.DomUtil.getPosition(this._element); | |
L.DomEvent | |
.on(document, L.Draggable.MOVE[e.type], this._onMove, this) | |
.on(document, L.Draggable.END[e.type], this._onUp, this); | |
}, | |
_onMove: function (e) { | |
if (e.touches && e.touches.length > 1) { | |
this._moved = true; | |
return; | |
} | |
var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e), | |
newPoint = new L.Point(first.clientX, first.clientY), | |
offset = newPoint.subtract(this._startPoint); | |
if (!offset.x && !offset.y) { return; } | |
if (L.Browser.touch && Math.abs(offset.x) + Math.abs(offset.y) < 3) { return; } | |
L.DomEvent.preventDefault(e); | |
if (!this._moved) { | |
this.fire('dragstart'); | |
this._moved = true; | |
this._startPos = L.DomUtil.getPosition(this._element).subtract(offset); | |
L.DomUtil.addClass(document.body, 'leaflet-dragging'); | |
this._lastTarget = e.target || e.srcElement; | |
L.DomUtil.addClass(this._lastTarget, 'leaflet-drag-target'); | |
} | |
this._newPos = this._startPos.add(offset); | |
this._moving = true; | |
L.Util.cancelAnimFrame(this._animRequest); | |
this._animRequest = L.Util.requestAnimFrame(this._updatePosition, this, true, this._dragStartTarget); | |
}, | |
_updatePosition: function () { | |
this.fire('predrag'); | |
L.DomUtil.setPosition(this._element, this._newPos); | |
this.fire('drag'); | |
}, | |
_onUp: function () { | |
L.DomUtil.removeClass(document.body, 'leaflet-dragging'); | |
if (this._lastTarget) { | |
L.DomUtil.removeClass(this._lastTarget, 'leaflet-drag-target'); | |
this._lastTarget = null; | |
} | |
for (var i in L.Draggable.MOVE) { | |
L.DomEvent | |
.off(document, L.Draggable.MOVE[i], this._onMove) | |
.off(document, L.Draggable.END[i], this._onUp); | |
} | |
L.DomUtil.enableImageDrag(); | |
L.DomUtil.enableTextSelection(); | |
if (this._moved && this._moving) { | |
// ensure drag is not fired after dragend | |
L.Util.cancelAnimFrame(this._animRequest); | |
this.fire('dragend', { | |
distance: this._newPos.distanceTo(this._startPos) | |
}); | |
} | |
this._moving = false; | |
} | |
}); | |
/* | |
L.Handler is a base class for handler classes that are used internally to inject | |
interaction features like dragging to classes like Map and Marker. | |
*/ | |
L.Handler = L.Class.extend({ | |
initialize: function (map) { | |
this._map = map; | |
}, | |
enable: function () { | |
if (this._enabled) { return; } | |
this._enabled = true; | |
this.addHooks(); | |
}, | |
disable: function () { | |
if (!this._enabled) { return; } | |
this._enabled = false; | |
this.removeHooks(); | |
}, | |
enabled: function () { | |
return !!this._enabled; | |
} | |
}); | |
/* | |
* L.Handler.MapDrag is used to make the map draggable (with panning inertia), enabled by default. | |
*/ | |
L.Map.mergeOptions({ | |
dragging: true, | |
inertia: !L.Browser.android23, | |
inertiaDeceleration: 3400, // px/s^2 | |
inertiaMaxSpeed: Infinity, // px/s | |
inertiaThreshold: L.Browser.touch ? 32 : 18, // ms | |
easeLinearity: 0.25, | |
// TODO refactor, move to CRS | |
worldCopyJump: false | |
}); | |
L.Map.Drag = L.Handler.extend({ | |
addHooks: function () { | |
if (!this._draggable) { | |
var map = this._map; | |
this._draggable = new L.Draggable(map._mapPane, map._container); | |
this._draggable.on({ | |
'dragstart': this._onDragStart, | |
'drag': this._onDrag, | |
'dragend': this._onDragEnd | |
}, this); | |
if (map.options.worldCopyJump) { | |
this._draggable.on('predrag', this._onPreDrag, this); | |
map.on('viewreset', this._onViewReset, this); | |
map.whenReady(this._onViewReset, this); | |
} | |
} | |
this._draggable.enable(); | |
}, | |
removeHooks: function () { | |
this._draggable.disable(); | |
}, | |
moved: function () { | |
return this._draggable && this._draggable._moved; | |
}, | |
_onDragStart: function () { | |
var map = this._map; | |
if (map._panAnim) { | |
map._panAnim.stop(); | |
} | |
map | |
.fire('movestart') | |
.fire('dragstart'); | |
if (map.options.inertia) { | |
this._positions = []; | |
this._times = []; | |
} | |
}, | |
_onDrag: function () { | |
if (this._map.options.inertia) { | |
var time = this._lastTime = +new Date(), | |
pos = this._lastPos = this._draggable._newPos; | |
this._positions.push(pos); | |
this._times.push(time); | |
if (time - this._times[0] > 200) { | |
this._positions.shift(); | |
this._times.shift(); | |
} | |
} | |
this._map | |
.fire('move') | |
.fire('drag'); | |
}, | |
_onViewReset: function () { | |
// TODO fix hardcoded Earth values | |
var pxCenter = this._map.getSize()._divideBy(2), | |
pxWorldCenter = this._map.latLngToLayerPoint([0, 0]); | |
this._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x; | |
this._worldWidth = this._map.project([0, 180]).x; | |
}, | |
_onPreDrag: function () { | |
// TODO refactor to be able to adjust map pane position after zoom | |
var worldWidth = this._worldWidth, | |
halfWidth = Math.round(worldWidth / 2), | |
dx = this._initialWorldOffset, | |
x = this._draggable._newPos.x, | |
newX1 = (x - halfWidth + dx) % worldWidth + halfWidth - dx, | |
newX2 = (x + halfWidth + dx) % worldWidth - halfWidth - dx, | |
newX = Math.abs(newX1 + dx) < Math.abs(newX2 + dx) ? newX1 : newX2; | |
this._draggable._newPos.x = newX; | |
}, | |
_onDragEnd: function (e) { | |
var map = this._map, | |
options = map.options, | |
delay = +new Date() - this._lastTime, | |
noInertia = !options.inertia || delay > options.inertiaThreshold || !this._positions[0]; | |
map.fire('dragend', e); | |
if (noInertia) { | |
map.fire('moveend'); | |
} else { | |
var direction = this._lastPos.subtract(this._positions[0]), | |
duration = (this._lastTime + delay - this._times[0]) / 1000, | |
ease = options.easeLinearity, | |
speedVector = direction.multiplyBy(ease / duration), | |
speed = speedVector.distanceTo([0, 0]), | |
limitedSpeed = Math.min(options.inertiaMaxSpeed, speed), | |
limitedSpeedVector = speedVector.multiplyBy(limitedSpeed / speed), | |
decelerationDuration = limitedSpeed / (options.inertiaDeceleration * ease), | |
offset = limitedSpeedVector.multiplyBy(-decelerationDuration / 2).round(); | |
if (!offset.x || !offset.y) { | |
map.fire('moveend'); | |
} else { | |
offset = map._limitOffset(offset, map.options.maxBounds); | |
L.Util.requestAnimFrame(function () { | |
map.panBy(offset, { | |
duration: decelerationDuration, | |
easeLinearity: ease, | |
noMoveStart: true | |
}); | |
}); | |
} | |
} | |
} | |
}); | |
L.Map.addInitHook('addHandler', 'dragging', L.Map.Drag); | |
/* | |
* L.Handler.DoubleClickZoom is used to handle double-click zoom on the map, enabled by default. | |
*/ | |
L.Map.mergeOptions({ | |
doubleClickZoom: true | |
}); | |
L.Map.DoubleClickZoom = L.Handler.extend({ | |
addHooks: function () { | |
this._map.on('dblclick', this._onDoubleClick, this); | |
}, | |
removeHooks: function () { | |
this._map.off('dblclick', this._onDoubleClick, this); | |
}, | |
_onDoubleClick: function (e) { | |
var map = this._map, | |
zoom = map.getZoom() + (e.originalEvent.shiftKey ? -1 : 1); | |
if (map.options.doubleClickZoom === 'center') { | |
map.setZoom(zoom); | |
} else { | |
map.setZoomAround(e.containerPoint, zoom); | |
} | |
} | |
}); | |
L.Map.addInitHook('addHandler', 'doubleClickZoom', L.Map.DoubleClickZoom); | |
/* | |
* L.Handler.ScrollWheelZoom is used by L.Map to enable mouse scroll wheel zoom on the map. | |
*/ | |
L.Map.mergeOptions({ | |
scrollWheelZoom: true | |
}); | |
L.Map.ScrollWheelZoom = L.Handler.extend({ | |
addHooks: function () { | |
L.DomEvent.on(this._map._container, 'mousewheel', this._onWheelScroll, this); | |
L.DomEvent.on(this._map._container, 'MozMousePixelScroll', L.DomEvent.preventDefault); | |
this._delta = 0; | |
}, | |
removeHooks: function () { | |
L.DomEvent.off(this._map._container, 'mousewheel', this._onWheelScroll); | |
L.DomEvent.off(this._map._container, 'MozMousePixelScroll', L.DomEvent.preventDefault); | |
}, | |
_onWheelScroll: function (e) { | |
var delta = L.DomEvent.getWheelDelta(e); | |
this._delta += delta; | |
this._lastMousePos = this._map.mouseEventToContainerPoint(e); | |
if (!this._startTime) { | |
this._startTime = +new Date(); | |
} | |
var left = Math.max(40 - (+new Date() - this._startTime), 0); | |
clearTimeout(this._timer); | |
this._timer = setTimeout(L.bind(this._performZoom, this), left); | |
L.DomEvent.preventDefault(e); | |
L.DomEvent.stopPropagation(e); | |
}, | |
_performZoom: function () { | |
var map = this._map, | |
delta = this._delta, | |
zoom = map.getZoom(); | |
delta = delta > 0 ? Math.ceil(delta) : Math.floor(delta); | |
delta = Math.max(Math.min(delta, 4), -4); | |
delta = map._limitZoom(zoom + delta) - zoom; | |
this._delta = 0; | |
this._startTime = null; | |
if (!delta) { return; } | |
if (map.options.scrollWheelZoom === 'center') { | |
map.setZoom(zoom + delta); | |
} else { | |
map.setZoomAround(this._lastMousePos, zoom + delta); | |
} | |
} | |
}); | |
L.Map.addInitHook('addHandler', 'scrollWheelZoom', L.Map.ScrollWheelZoom); | |
/* | |
* Extends the event handling code with double tap support for mobile browsers. | |
*/ | |
L.extend(L.DomEvent, { | |
_touchstart: L.Browser.msPointer ? 'MSPointerDown' : L.Browser.pointer ? 'pointerdown' : 'touchstart', | |
_touchend: L.Browser.msPointer ? 'MSPointerUp' : L.Browser.pointer ? 'pointerup' : 'touchend', | |
// inspired by Zepto touch code by Thomas Fuchs | |
addDoubleTapListener: function (obj, handler, id) { | |
var last, | |
doubleTap = false, | |
delay = 250, | |
touch, | |
pre = '_leaflet_', | |
touchstart = this._touchstart, | |
touchend = this._touchend, | |
trackedTouches = []; | |
function onTouchStart(e) { | |
var count; | |
if (L.Browser.pointer) { | |
trackedTouches.push(e.pointerId); | |
count = trackedTouches.length; | |
} else { | |
count = e.touches.length; | |
} | |
if (count > 1) { | |
return; | |
} | |
var now = Date.now(), | |
delta = now - (last || now); | |
touch = e.touches ? e.touches[0] : e; | |
doubleTap = (delta > 0 && delta <= delay); | |
last = now; | |
} | |
function onTouchEnd(e) { | |
if (L.Browser.pointer) { | |
var idx = trackedTouches.indexOf(e.pointerId); | |
if (idx === -1) { | |
return; | |
} | |
trackedTouches.splice(idx, 1); | |
} | |
if (doubleTap) { | |
if (L.Browser.pointer) { | |
// work around .type being readonly with MSPointer* events | |
var newTouch = { }, | |
prop; | |
// jshint forin:false | |
for (var i in touch) { | |
prop = touch[i]; | |
if (typeof prop === 'function') { | |
newTouch[i] = prop.bind(touch); | |
} else { | |
newTouch[i] = prop; | |
} | |
} | |
touch = newTouch; | |
} | |
touch.type = 'dblclick'; | |
handler(touch); | |
last = null; | |
} | |
} | |
obj[pre + touchstart + id] = onTouchStart; | |
obj[pre + touchend + id] = onTouchEnd; | |
// on pointer we need to listen on the document, otherwise a drag starting on the map and moving off screen | |
// will not come through to us, so we will lose track of how many touches are ongoing | |
var endElement = L.Browser.pointer ? document.documentElement : obj; | |
obj.addEventListener(touchstart, onTouchStart, false); | |
endElement.addEventListener(touchend, onTouchEnd, false); | |
if (L.Browser.pointer) { | |
endElement.addEventListener(L.DomEvent.POINTER_CANCEL, onTouchEnd, false); | |
} | |
return this; | |
}, | |
removeDoubleTapListener: function (obj, id) { | |
var pre = '_leaflet_'; | |
obj.removeEventListener(this._touchstart, obj[pre + this._touchstart + id], false); | |
(L.Browser.pointer ? document.documentElement : obj).removeEventListener( | |
this._touchend, obj[pre + this._touchend + id], false); | |
if (L.Browser.pointer) { | |
document.documentElement.removeEventListener(L.DomEvent.POINTER_CANCEL, obj[pre + this._touchend + id], | |
false); | |
} | |
return this; | |
} | |
}); | |
/* | |
* Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices. | |
*/ | |
L.extend(L.DomEvent, { | |
//static | |
POINTER_DOWN: L.Browser.msPointer ? 'MSPointerDown' : 'pointerdown', | |
POINTER_MOVE: L.Browser.msPointer ? 'MSPointerMove' : 'pointermove', | |
POINTER_UP: L.Browser.msPointer ? 'MSPointerUp' : 'pointerup', | |
POINTER_CANCEL: L.Browser.msPointer ? 'MSPointerCancel' : 'pointercancel', | |
_pointers: [], | |
_pointerDocumentListener: false, | |
// Provides a touch events wrapper for (ms)pointer events. | |
// Based on changes by veproza https://github.com/CloudMade/Leaflet/pull/1019 | |
//ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890 | |
addPointerListener: function (obj, type, handler, id) { | |
switch (type) { | |
case 'touchstart': | |
return this.addPointerListenerStart(obj, type, handler, id); | |
case 'touchend': | |
return this.addPointerListenerEnd(obj, type, handler, id); | |
case 'touchmove': | |
return this.addPointerListenerMove(obj, type, handler, id); | |
default: | |
throw 'Unknown touch event type'; | |
} | |
}, | |
addPointerListenerStart: function (obj, type, handler, id) { | |
var pre = '_leaflet_', | |
pointers = this._pointers; | |
var cb = function (e) { | |
if (e.pointerType !== 'mouse' && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) { | |
L.DomEvent.preventDefault(e); | |
} | |
var alreadyInArray = false; | |
for (var i = 0; i < pointers.length; i++) { | |
if (pointers[i].pointerId === e.pointerId) { | |
alreadyInArray = true; | |
break; | |
} | |
} | |
if (!alreadyInArray) { | |
pointers.push(e); | |
} | |
e.touches = pointers.slice(); | |
e.changedTouches = [e]; | |
handler(e); | |
}; | |
obj[pre + 'touchstart' + id] = cb; | |
obj.addEventListener(this.POINTER_DOWN, cb, false); | |
// need to also listen for end events to keep the _pointers list accurate | |
// this needs to be on the body and never go away | |
if (!this._pointerDocumentListener) { | |
var internalCb = function (e) { | |
for (var i = 0; i < pointers.length; i++) { | |
if (pointers[i].pointerId === e.pointerId) { | |
pointers.splice(i, 1); | |
break; | |
} | |
} | |
}; | |
//We listen on the documentElement as any drags that end by moving the touch off the screen get fired there | |
document.documentElement.addEventListener(this.POINTER_UP, internalCb, false); | |
document.documentElement.addEventListener(this.POINTER_CANCEL, internalCb, false); | |
this._pointerDocumentListener = true; | |
} | |
return this; | |
}, | |
addPointerListenerMove: function (obj, type, handler, id) { | |
var pre = '_leaflet_', | |
touches = this._pointers; | |
function cb(e) { | |
// don't fire touch moves when mouse isn't down | |
if ((e.pointerType === e.MSPOINTER_TYPE_MOUSE || e.pointerType === 'mouse') && e.buttons === 0) { return; } | |
for (var i = 0; i < touches.length; i++) { | |
if (touches[i].pointerId === e.pointerId) { | |
touches[i] = e; | |
break; | |
} | |
} | |
e.touches = touches.slice(); | |
e.changedTouches = [e]; | |
handler(e); | |
} | |
obj[pre + 'touchmove' + id] = cb; | |
obj.addEventListener(this.POINTER_MOVE, cb, false); | |
return this; | |
}, | |
addPointerListenerEnd: function (obj, type, handler, id) { | |
var pre = '_leaflet_', | |
touches = this._pointers; | |
var cb = function (e) { | |
for (var i = 0; i < touches.length; i++) { | |
if (touches[i].pointerId === e.pointerId) { | |
touches.splice(i, 1); | |
break; | |
} | |
} | |
e.touches = touches.slice(); | |
e.changedTouches = [e]; | |
handler(e); | |
}; | |
obj[pre + 'touchend' + id] = cb; | |
obj.addEventListener(this.POINTER_UP, cb, false); | |
obj.addEventListener(this.POINTER_CANCEL, cb, false); | |
return this; | |
}, | |
removePointerListener: function (obj, type, id) { | |
var pre = '_leaflet_', | |
cb = obj[pre + type + id]; | |
switch (type) { | |
case 'touchstart': | |
obj.removeEventListener(this.POINTER_DOWN, cb, false); | |
break; | |
case 'touchmove': | |
obj.removeEventListener(this.POINTER_MOVE, cb, false); | |
break; | |
case 'touchend': | |
obj.removeEventListener(this.POINTER_UP, cb, false); | |
obj.removeEventListener(this.POINTER_CANCEL, cb, false); | |
break; | |
} | |
return this; | |
} | |
}); | |
/* | |
* L.Handler.TouchZoom is used by L.Map to add pinch zoom on supported mobile browsers. | |
*/ | |
L.Map.mergeOptions({ | |
touchZoom: L.Browser.touch && !L.Browser.android23, | |
bounceAtZoomLimits: true | |
}); | |
L.Map.TouchZoom = L.Handler.extend({ | |
addHooks: function () { | |
L.DomEvent.on(this._map._container, 'touchstart', this._onTouchStart, this); | |
}, | |
removeHooks: function () { | |
L.DomEvent.off(this._map._container, 'touchstart', this._onTouchStart, this); | |
}, | |
_onTouchStart: function (e) { | |
var map = this._map; | |
if (!e.touches || e.touches.length !== 2 || map._animatingZoom || this._zooming) { return; } | |
var p1 = map.mouseEventToLayerPoint(e.touches[0]), | |
p2 = map.mouseEventToLayerPoint(e.touches[1]), | |
viewCenter = map._getCenterLayerPoint(); | |
this._startCenter = p1.add(p2)._divideBy(2); | |
this._startDist = p1.distanceTo(p2); | |
this._moved = false; | |
this._zooming = true; | |
this._centerOffset = viewCenter.subtract(this._startCenter); | |
if (map._panAnim) { | |
map._panAnim.stop(); | |
} | |
L.DomEvent | |
.on(document, 'touchmove', this._onTouchMove, this) | |
.on(document, 'touchend', this._onTouchEnd, this); | |
L.DomEvent.preventDefault(e); | |
}, | |
_onTouchMove: function (e) { | |
var map = this._map; | |
if (!e.touches || e.touches.length !== 2 || !this._zooming) { return; } | |
var p1 = map.mouseEventToLayerPoint(e.touches[0]), | |
p2 = map.mouseEventToLayerPoint(e.touches[1]); | |
this._scale = p1.distanceTo(p2) / this._startDist; | |
this._delta = p1._add(p2)._divideBy(2)._subtract(this._startCenter); | |
if (this._scale === 1) { return; } | |
if (!map.options.bounceAtZoomLimits) { | |
if ((map.getZoom() === map.getMinZoom() && this._scale < 1) || | |
(map.getZoom() === map.getMaxZoom() && this._scale > 1)) { return; } | |
} | |
if (!this._moved) { | |
L.DomUtil.addClass(map._mapPane, 'leaflet-touching'); | |
map | |
.fire('movestart') | |
.fire('zoomstart'); | |
this._moved = true; | |
} | |
L.Util.cancelAnimFrame(this._animRequest); | |
this._animRequest = L.Util.requestAnimFrame( | |
this._updateOnMove, this, true, this._map._container); | |
L.DomEvent.preventDefault(e); | |
}, | |
_updateOnMove: function () { | |
var map = this._map, | |
origin = this._getScaleOrigin(), | |
center = map.layerPointToLatLng(origin), | |
zoom = map.getScaleZoom(this._scale); | |
map._animateZoom(center, zoom, this._startCenter, this._scale, this._delta, false, true); | |
}, | |
_onTouchEnd: function () { | |
if (!this._moved || !this._zooming) { | |
this._zooming = false; | |
return; | |
} | |
var map = this._map; | |
this._zooming = false; | |
L.DomUtil.removeClass(map._mapPane, 'leaflet-touching'); | |
L.Util.cancelAnimFrame(this._animRequest); | |
L.DomEvent | |
.off(document, 'touchmove', this._onTouchMove) | |
.off(document, 'touchend', this._onTouchEnd); | |
var origin = this._getScaleOrigin(), | |
center = map.layerPointToLatLng(origin), | |
oldZoom = map.getZoom(), | |
floatZoomDelta = map.getScaleZoom(this._scale) - oldZoom, | |
roundZoomDelta = (floatZoomDelta > 0 ? | |
Math.ceil(floatZoomDelta) : Math.floor(floatZoomDelta)), | |
zoom = map._limitZoom(oldZoom + roundZoomDelta), | |
scale = map.getZoomScale(zoom) / this._scale; | |
map._animateZoom(center, zoom, origin, scale); | |
}, | |
_getScaleOrigin: function () { | |
var centerOffset = this._centerOffset.subtract(this._delta).divideBy(this._scale); | |
return this._startCenter.add(centerOffset); | |
} | |
}); | |
L.Map.addInitHook('addHandler', 'touchZoom', L.Map.TouchZoom); | |
/* | |
* L.Map.Tap is used to enable mobile hacks like quick taps and long hold. | |
*/ | |
L.Map.mergeOptions({ | |
tap: true, | |
tapTolerance: 15 | |
}); | |
L.Map.Tap = L.Handler.extend({ | |
addHooks: function () { | |
L.DomEvent.on(this._map._container, 'touchstart', this._onDown, this); | |
}, | |
removeHooks: function () { | |
L.DomEvent.off(this._map._container, 'touchstart', this._onDown, this); | |
}, | |
_onDown: function (e) { | |
if (!e.touches) { return; } | |
L.DomEvent.preventDefault(e); | |
this._fireClick = true; | |
// don't simulate click or track longpress if more than 1 touch | |
if (e.touches.length > 1) { | |
this._fireClick = false; | |
clearTimeout(this._holdTimeout); | |
return; | |
} | |
var first = e.touches[0], | |
el = first.target; | |
this._startPos = this._newPos = new L.Point(first.clientX, first.clientY); | |
// if touching a link, highlight it | |
if (el.tagName && el.tagName.toLowerCase() === 'a') { | |
L.DomUtil.addClass(el, 'leaflet-active'); | |
} | |
// simulate long hold but setting a timeout | |
this._holdTimeout = setTimeout(L.bind(function () { | |
if (this._isTapValid()) { | |
this._fireClick = false; | |
this._onUp(); | |
this._simulateEvent('contextmenu', first); | |
} | |
}, this), 1000); | |
L.DomEvent | |
.on(document, 'touchmove', this._onMove, this) | |
.on(document, 'touchend', this._onUp, this); | |
}, | |
_onUp: function (e) { | |
clearTimeout(this._holdTimeout); | |
L.DomEvent | |
.off(document, 'touchmove', this._onMove, this) | |
.off(document, 'touchend', this._onUp, this); | |
if (this._fireClick && e && e.changedTouches) { | |
var first = e.changedTouches[0], | |
el = first.target; | |
if (el && el.tagName && el.tagName.toLowerCase() === 'a') { | |
L.DomUtil.removeClass(el, 'leaflet-active'); | |
} | |
// simulate click if the touch didn't move too much | |
if (this._isTapValid()) { | |
this._simulateEvent('click', first); | |
} | |
} | |
}, | |
_isTapValid: function () { | |
return this._newPos.distanceTo(this._startPos) <= this._map.options.tapTolerance; | |
}, | |
_onMove: function (e) { | |
var first = e.touches[0]; | |
this._newPos = new L.Point(first.clientX, first.clientY); | |
}, | |
_simulateEvent: function (type, e) { | |
var simulatedEvent = document.createEvent('MouseEvents'); | |
simulatedEvent._simulated = true; | |
e.target._simulatedClick = true; | |
simulatedEvent.initMouseEvent( | |
type, true, true, window, 1, | |
e.screenX, e.screenY, | |
e.clientX, e.clientY, | |
false, false, false, false, 0, null); | |
e.target.dispatchEvent(simulatedEvent); | |
} | |
}); | |
if (L.Browser.touch && !L.Browser.pointer) { | |
L.Map.addInitHook('addHandler', 'tap', L.Map.Tap); | |
} | |
/* | |
* L.Handler.ShiftDragZoom is used to add shift-drag zoom interaction to the map | |
* (zoom to a selected bounding box), enabled by default. | |
*/ | |
L.Map.mergeOptions({ | |
boxZoom: true | |
}); | |
L.Map.BoxZoom = L.Handler.extend({ | |
initialize: function (map) { | |
this._map = map; | |
this._container = map._container; | |
this._pane = map._panes.overlayPane; | |
this._moved = false; | |
}, | |
addHooks: function () { | |
L.DomEvent.on(this._container, 'mousedown', this._onMouseDown, this); | |
}, | |
removeHooks: function () { | |
L.DomEvent.off(this._container, 'mousedown', this._onMouseDown); | |
this._moved = false; | |
}, | |
moved: function () { | |
return this._moved; | |
}, | |
_onMouseDown: function (e) { | |
this._moved = false; | |
if (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; } | |
L.DomUtil.disableTextSelection(); | |
L.DomUtil.disableImageDrag(); | |
this._startLayerPoint = this._map.mouseEventToLayerPoint(e); | |
L.DomEvent | |
.on(document, 'mousemove', this._onMouseMove, this) | |
.on(document, 'mouseup', this._onMouseUp, this) | |
.on(document, 'keydown', this._onKeyDown, this); | |
}, | |
_onMouseMove: function (e) { | |
if (!this._moved) { | |
this._box = L.DomUtil.create('div', 'leaflet-zoom-box', this._pane); | |
L.DomUtil.setPosition(this._box, this._startLayerPoint); | |
//TODO refactor: move cursor to styles | |
this._container.style.cursor = 'crosshair'; | |
this._map.fire('boxzoomstart'); | |
} | |
var startPoint = this._startLayerPoint, | |
box = this._box, | |
layerPoint = this._map.mouseEventToLayerPoint(e), | |
offset = layerPoint.subtract(startPoint), | |
newPos = new L.Point( | |
Math.min(layerPoint.x, startPoint.x), | |
Math.min(layerPoint.y, startPoint.y)); | |
L.DomUtil.setPosition(box, newPos); | |
this._moved = true; | |
// TODO refactor: remove hardcoded 4 pixels | |
box.style.width = (Math.max(0, Math.abs(offset.x) - 4)) + 'px'; | |
box.style.height = (Math.max(0, Math.abs(offset.y) - 4)) + 'px'; | |
}, | |
_finish: function () { | |
if (this._moved) { | |
this._pane.removeChild(this._box); | |
this._container.style.cursor = ''; | |
} | |
L.DomUtil.enableTextSelection(); | |
L.DomUtil.enableImageDrag(); | |
L.DomEvent | |
.off(document, 'mousemove', this._onMouseMove) | |
.off(document, 'mouseup', this._onMouseUp) | |
.off(document, 'keydown', this._onKeyDown); | |
}, | |
_onMouseUp: function (e) { | |
this._finish(); | |
var map = this._map, | |
layerPoint = map.mouseEventToLayerPoint(e); | |
if (this._startLayerPoint.equals(layerPoint)) { return; } | |
var bounds = new L.LatLngBounds( | |
map.layerPointToLatLng(this._startLayerPoint), | |
map.layerPointToLatLng(layerPoint)); | |
map.fitBounds(bounds); | |
map.fire('boxzoomend', { | |
boxZoomBounds: bounds | |
}); | |
}, | |
_onKeyDown: function (e) { | |
if (e.keyCode === 27) { | |
this._finish(); | |
} | |
} | |
}); | |
L.Map.addInitHook('addHandler', 'boxZoom', L.Map.BoxZoom); | |
/* | |
* L.Map.Keyboard is handling keyboard interaction with the map, enabled by default. | |
*/ | |
L.Map.mergeOptions({ | |
keyboard: true, | |
keyboardPanOffset: 80, | |
keyboardZoomOffset: 1 | |
}); | |
L.Map.Keyboard = L.Handler.extend({ | |
keyCodes: { | |
left: [37], | |
right: [39], | |
down: [40], | |
up: [38], | |
zoomIn: [187, 107, 61, 171], | |
zoomOut: [189, 109, 173] | |
}, | |
initialize: function (map) { | |
this._map = map; | |
this._setPanOffset(map.options.keyboardPanOffset); | |
this._setZoomOffset(map.options.keyboardZoomOffset); | |
}, | |
addHooks: function () { | |
var container = this._map._container; | |
// make the container focusable by tabbing | |
if (container.tabIndex === -1) { | |
container.tabIndex = '0'; | |
} | |
L.DomEvent | |
.on(container, 'focus', this._onFocus, this) | |
.on(container, 'blur', this._onBlur, this) | |
.on(container, 'mousedown', this._onMouseDown, this); | |
this._map | |
.on('focus', this._addHooks, this) | |
.on('blur', this._removeHooks, this); | |
}, | |
removeHooks: function () { | |
this._removeHooks(); | |
var container = this._map._container; | |
L.DomEvent | |
.off(container, 'focus', this._onFocus, this) | |
.off(container, 'blur', this._onBlur, this) | |
.off(container, 'mousedown', this._onMouseDown, this); | |
this._map | |
.off('focus', this._addHooks, this) | |
.off('blur', this._removeHooks, this); | |
}, | |
_onMouseDown: function () { | |
if (this._focused) { return; } | |
var body = document.body, | |
docEl = document.documentElement, | |
top = body.scrollTop || docEl.scrollTop, | |
left = body.scrollLeft || docEl.scrollLeft; | |
this._map._container.focus(); | |
window.scrollTo(left, top); | |
}, | |
_onFocus: function () { | |
this._focused = true; | |
this._map.fire('focus'); | |
}, | |
_onBlur: function () { | |
this._focused = false; | |
this._map.fire('blur'); | |
}, | |
_setPanOffset: function (pan) { | |
var keys = this._panKeys = {}, | |
codes = this.keyCodes, | |
i, len; | |
for (i = 0, len = codes.left.length; i < len; i++) { | |
keys[codes.left[i]] = [-1 * pan, 0]; | |
} | |
for (i = 0, len = codes.right.length; i < len; i++) { | |
keys[codes.right[i]] = [pan, 0]; | |
} | |
for (i = 0, len = codes.down.length; i < len; i++) { | |
keys[codes.down[i]] = [0, pan]; | |
} | |
for (i = 0, len = codes.up.length; i < len; i++) { | |
keys[codes.up[i]] = [0, -1 * pan]; | |
} | |
}, | |
_setZoomOffset: function (zoom) { | |
var keys = this._zoomKeys = {}, | |
codes = this.keyCodes, | |
i, len; | |
for (i = 0, len = codes.zoomIn.length; i < len; i++) { | |
keys[codes.zoomIn[i]] = zoom; | |
} | |
for (i = 0, len = codes.zoomOut.length; i < len; i++) { | |
keys[codes.zoomOut[i]] = -zoom; | |
} | |
}, | |
_addHooks: function () { | |
L.DomEvent.on(document, 'keydown', this._onKeyDown, this); | |
}, | |
_removeHooks: function () { | |
L.DomEvent.off(document, 'keydown', this._onKeyDown, this); | |
}, | |
_onKeyDown: function (e) { | |
var key = e.keyCode, | |
map = this._map; | |
if (key in this._panKeys) { | |
if (map._panAnim && map._panAnim._inProgress) { return; } | |
map.panBy(this._panKeys[key]); | |
if (map.options.maxBounds) { | |
map.panInsideBounds(map.options.maxBounds); | |
} | |
} else if (key in this._zoomKeys) { | |
map.setZoom(map.getZoom() + this._zoomKeys[key]); | |
} else { | |
return; | |
} | |
L.DomEvent.stop(e); | |
} | |
}); | |
L.Map.addInitHook('addHandler', 'keyboard', L.Map.Keyboard); | |
/* | |
* L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable. | |
*/ | |
L.Handler.MarkerDrag = L.Handler.extend({ | |
initialize: function (marker) { | |
this._marker = marker; | |
}, | |
addHooks: function () { | |
var icon = this._marker._icon; | |
if (!this._draggable) { | |
this._draggable = new L.Draggable(icon, icon); | |
} | |
this._draggable | |
.on('dragstart', this._onDragStart, this) | |
.on('drag', this._onDrag, this) | |
.on('dragend', this._onDragEnd, this); | |
this._draggable.enable(); | |
L.DomUtil.addClass(this._marker._icon, 'leaflet-marker-draggable'); | |
}, | |
removeHooks: function () { | |
this._draggable | |
.off('dragstart', this._onDragStart, this) | |
.off('drag', this._onDrag, this) | |
.off('dragend', this._onDragEnd, this); | |
this._draggable.disable(); | |
L.DomUtil.removeClass(this._marker._icon, 'leaflet-marker-draggable'); | |
}, | |
moved: function () { | |
return this._draggable && this._draggable._moved; | |
}, | |
_onDragStart: function () { | |
this._marker | |
.closePopup() | |
.fire('movestart') | |
.fire('dragstart'); | |
}, | |
_onDrag: function () { | |
var marker = this._marker, | |
shadow = marker._shadow, | |
iconPos = L.DomUtil.getPosition(marker._icon), | |
latlng = marker._map.layerPointToLatLng(iconPos); | |
// update shadow position | |
if (shadow) { | |
L.DomUtil.setPosition(shadow, iconPos); | |
} | |
marker._latlng = latlng; | |
marker | |
.fire('move', {latlng: latlng}) | |
.fire('drag'); | |
}, | |
_onDragEnd: function (e) { | |
this._marker | |
.fire('moveend') | |
.fire('dragend', e); | |
} | |
}); | |
/* | |
* L.Control is a base class for implementing map controls. Handles positioning. | |
* All other controls extend from this class. | |
*/ | |
L.Control = L.Class.extend({ | |
options: { | |
position: 'topright' | |
}, | |
initialize: function (options) { | |
L.setOptions(this, options); | |
}, | |
getPosition: function () { | |
return this.options.position; | |
}, | |
setPosition: function (position) { | |
var map = this._map; | |
if (map) { | |
map.removeControl(this); | |
} | |
this.options.position = position; | |
if (map) { | |
map.addControl(this); | |
} | |
return this; | |
}, | |
getContainer: function () { | |
return this._container; | |
}, | |
addTo: function (map) { | |
this._map = map; | |
var container = this._container = this.onAdd(map), | |
pos = this.getPosition(), | |
corner = map._controlCorners[pos]; | |
L.DomUtil.addClass(container, 'leaflet-control'); | |
if (pos.indexOf('bottom') !== -1) { | |
corner.insertBefore(container, corner.firstChild); | |
} else { | |
corner.appendChild(container); | |
} | |
return this; | |
}, | |
removeFrom: function (map) { | |
var pos = this.getPosition(), | |
corner = map._controlCorners[pos]; | |
corner.removeChild(this._container); | |
this._map = null; | |
if (this.onRemove) { | |
this.onRemove(map); | |
} | |
return this; | |
}, | |
_refocusOnMap: function () { | |
if (this._map) { | |
this._map.getContainer().focus(); | |
} | |
} | |
}); | |
L.control = function (options) { | |
return new L.Control(options); | |
}; | |
// adds control-related methods to L.Map | |
L.Map.include({ | |
addControl: function (control) { | |
control.addTo(this); | |
return this; | |
}, | |
removeControl: function (control) { | |
control.removeFrom(this); | |
return this; | |
}, | |
_initControlPos: function () { | |
var corners = this._controlCorners = {}, | |
l = 'leaflet-', | |
container = this._controlContainer = | |
L.DomUtil.create('div', l + 'control-container', this._container); | |
function createCorner(vSide, hSide) { | |
var className = l + vSide + ' ' + l + hSide; | |
corners[vSide + hSide] = L.DomUtil.create('div', className, container); | |
} | |
createCorner('top', 'left'); | |
createCorner('top', 'right'); | |
createCorner('bottom', 'left'); | |
createCorner('bottom', 'right'); | |
}, | |
_clearControlPos: function () { | |
this._container.removeChild(this._controlContainer); | |
} | |
}); | |
/* | |
* L.Control.Zoom is used for the default zoom buttons on the map. | |
*/ | |
L.Control.Zoom = L.Control.extend({ | |
options: { | |
position: 'topleft', | |
zoomInText: '+', | |
zoomInTitle: 'Zoom in', | |
zoomOutText: '-', | |
zoomOutTitle: 'Zoom out' | |
}, | |
onAdd: function (map) { | |
var zoomName = 'leaflet-control-zoom', | |
container = L.DomUtil.create('div', zoomName + ' leaflet-bar'); | |
this._map = map; | |
this._zoomInButton = this._createButton( | |
this.options.zoomInText, this.options.zoomInTitle, | |
zoomName + '-in', container, this._zoomIn, this); | |
this._zoomOutButton = this._createButton( | |
this.options.zoomOutText, this.options.zoomOutTitle, | |
zoomName + '-out', container, this._zoomOut, this); | |
this._updateDisabled(); | |
map.on('zoomend zoomlevelschange', this._updateDisabled, this); | |
return container; | |
}, | |
onRemove: function (map) { | |
map.off('zoomend zoomlevelschange', this._updateDisabled, this); | |
}, | |
_zoomIn: function (e) { | |
this._map.zoomIn(e.shiftKey ? 3 : 1); | |
}, | |
_zoomOut: function (e) { | |
this._map.zoomOut(e.shiftKey ? 3 : 1); | |
}, | |
_createButton: function (html, title, className, container, fn, context) { | |
var link = L.DomUtil.create('a', className, container); | |
link.innerHTML = html; | |
link.href = '#'; | |
link.title = title; | |
var stop = L.DomEvent.stopPropagation; | |
L.DomEvent | |
.on(link, 'click', stop) | |
.on(link, 'mousedown', stop) | |
.on(link, 'dblclick', stop) | |
.on(link, 'click', L.DomEvent.preventDefault) | |
.on(link, 'click', fn, context) | |
.on(link, 'click', this._refocusOnMap, context); | |
return link; | |
}, | |
_updateDisabled: function () { | |
var map = this._map, | |
className = 'leaflet-disabled'; | |
L.DomUtil.removeClass(this._zoomInButton, className); | |
L.DomUtil.removeClass(this._zoomOutButton, className); | |
if (map._zoom === map.getMinZoom()) { | |
L.DomUtil.addClass(this._zoomOutButton, className); | |
} | |
if (map._zoom === map.getMaxZoom()) { | |
L.DomUtil.addClass(this._zoomInButton, className); | |
} | |
} | |
}); | |
L.Map.mergeOptions({ | |
zoomControl: true | |
}); | |
L.Map.addInitHook(function () { | |
if (this.options.zoomControl) { | |
this.zoomControl = new L.Control.Zoom(); | |
this.addControl(this.zoomControl); | |
} | |
}); | |
L.control.zoom = function (options) { | |
return new L.Control.Zoom(options); | |
}; | |
/* | |
* L.Control.Attribution is used for displaying attribution on the map (added by default). | |
*/ | |
L.Control.Attribution = L.Control.extend({ | |
options: { | |
position: 'bottomright', | |
prefix: '<a href="http://leafletjs.com" title="A JS library for interactive maps">Leaflet</a>' | |
}, | |
initialize: function (options) { | |
L.setOptions(this, options); | |
this._attributions = {}; | |
}, | |
onAdd: function (map) { | |
this._container = L.DomUtil.create('div', 'leaflet-control-attribution'); | |
L.DomEvent.disableClickPropagation(this._container); | |
for (var i in map._layers) { | |
if (map._layers[i].getAttribution) { | |
this.addAttribution(map._layers[i].getAttribution()); | |
} | |
} | |
map | |
.on('layeradd', this._onLayerAdd, this) | |
.on('layerremove', this._onLayerRemove, this); | |
this._update(); | |
return this._container; | |
}, | |
onRemove: function (map) { | |
map | |
.off('layeradd', this._onLayerAdd) | |
.off('layerremove', this._onLayerRemove); | |
}, | |
setPrefix: function (prefix) { | |
this.options.prefix = prefix; | |
this._update(); | |
return this; | |
}, | |
addAttribution: function (text) { | |
if (!text) { return; } | |
if (!this._attributions[text]) { | |
this._attributions[text] = 0; | |
} | |
this._attributions[text]++; | |
this._update(); | |
return this; | |
}, | |
removeAttribution: function (text) { | |
if (!text) { return; } | |
if (this._attributions[text]) { | |
this._attributions[text]--; | |
this._update(); | |
} | |
return this; | |
}, | |
_update: function () { | |
if (!this._map) { return; } | |
var attribs = []; | |
for (var i in this._attributions) { | |
if (this._attributions[i]) { | |
attribs.push(i); | |
} | |
} | |
var prefixAndAttribs = []; | |
if (this.options.prefix) { | |
prefixAndAttribs.push(this.options.prefix); | |
} | |
if (attribs.length) { | |
prefixAndAttribs.push(attribs.join(', ')); | |
} | |
this._container.innerHTML = prefixAndAttribs.join(' | '); | |
}, | |
_onLayerAdd: function (e) { | |
if (e.layer.getAttribution) { | |
this.addAttribution(e.layer.getAttribution()); | |
} | |
}, | |
_onLayerRemove: function (e) { | |
if (e.layer.getAttribution) { | |
this.removeAttribution(e.layer.getAttribution()); | |
} | |
} | |
}); | |
L.Map.mergeOptions({ | |
attributionControl: true | |
}); | |
L.Map.addInitHook(function () { | |
if (this.options.attributionControl) { | |
this.attributionControl = (new L.Control.Attribution()).addTo(this); | |
} | |
}); | |
L.control.attribution = function (options) { | |
return new L.Control.Attribution(options); | |
}; | |
/* | |
* L.Control.Scale is used for displaying metric/imperial scale on the map. | |
*/ | |
L.Control.Scale = L.Control.extend({ | |
options: { | |
position: 'bottomleft', | |
maxWidth: 100, | |
metric: true, | |
imperial: true, | |
updateWhenIdle: false | |
}, | |
onAdd: function (map) { | |
this._map = map; | |
var className = 'leaflet-control-scale', | |
container = L.DomUtil.create('div', className), | |
options = this.options; | |
this._addScales(options, className, container); | |
map.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this); | |
map.whenReady(this._update, this); | |
return container; | |
}, | |
onRemove: function (map) { | |
map.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this); | |
}, | |
_addScales: function (options, className, container) { | |
if (options.metric) { | |
this._mScale = L.DomUtil.create('div', className + '-line', container); | |
} | |
if (options.imperial) { | |
this._iScale = L.DomUtil.create('div', className + '-line', container); | |
} | |
}, | |
_update: function () { | |
var bounds = this._map.getBounds(), | |
centerLat = bounds.getCenter().lat, | |
halfWorldMeters = 6378137 * Math.PI * Math.cos(centerLat * Math.PI / 180), | |
dist = halfWorldMeters * (bounds.getNorthEast().lng - bounds.getSouthWest().lng) / 180, | |
size = this._map.getSize(), | |
options = this.options, | |
maxMeters = 0; | |
if (size.x > 0) { | |
maxMeters = dist * (options.maxWidth / size.x); | |
} | |
this._updateScales(options, maxMeters); | |
}, | |
_updateScales: function (options, maxMeters) { | |
if (options.metric && maxMeters) { | |
this._updateMetric(maxMeters); | |
} | |
if (options.imperial && maxMeters) { | |
this._updateImperial(maxMeters); | |
} | |
}, | |
_updateMetric: function (maxMeters) { | |
var meters = this._getRoundNum(maxMeters); | |
this._mScale.style.width = this._getScaleWidth(meters / maxMeters) + 'px'; | |
this._mScale.innerHTML = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km'; | |
}, | |
_updateImperial: function (maxMeters) { | |
var maxFeet = maxMeters * 3.2808399, | |
scale = this._iScale, | |
maxMiles, miles, feet; | |
if (maxFeet > 5280) { | |
maxMiles = maxFeet / 5280; | |
miles = this._getRoundNum(maxMiles); | |
scale.style.width = this._getScaleWidth(miles / maxMiles) + 'px'; | |
scale.innerHTML = miles + ' mi'; | |
} else { | |
feet = this._getRoundNum(maxFeet); | |
scale.style.width = this._getScaleWidth(feet / maxFeet) + 'px'; | |
scale.innerHTML = feet + ' ft'; | |
} | |
}, | |
_getScaleWidth: function (ratio) { | |
return Math.round(this.options.maxWidth * ratio) - 10; | |
}, | |
_getRoundNum: function (num) { | |
var pow10 = Math.pow(10, (Math.floor(num) + '').length - 1), | |
d = num / pow10; | |
d = d >= 10 ? 10 : d >= 5 ? 5 : d >= 3 ? 3 : d >= 2 ? 2 : 1; | |
return pow10 * d; | |
} | |
}); | |
L.control.scale = function (options) { | |
return new L.Control.Scale(options); | |
}; | |
/* | |
* L.Control.Layers is a control to allow users to switch between different layers on the map. | |
*/ | |
L.Control.Layers = L.Control.extend({ | |
options: { | |
collapsed: true, | |
position: 'topright', | |
autoZIndex: true | |
}, | |
initialize: function (baseLayers, overlays, options) { | |
L.setOptions(this, options); | |
this._layers = {}; | |
this._lastZIndex = 0; | |
this._handlingClick = false; | |
for (var i in baseLayers) { | |
this._addLayer(baseLayers[i], i); | |
} | |
for (i in overlays) { | |
this._addLayer(overlays[i], i, true); | |
} | |
}, | |
onAdd: function (map) { | |
this._initLayout(); | |
this._update(); | |
map | |
.on('layeradd', this._onLayerChange, this) | |
.on('layerremove', this._onLayerChange, this); | |
return this._container; | |
}, | |
onRemove: function (map) { | |
map | |
.off('layeradd', this._onLayerChange, this) | |
.off('layerremove', this._onLayerChange, this); | |
}, | |
addBaseLayer: function (layer, name) { | |
this._addLayer(layer, name); | |
this._update(); | |
return this; | |
}, | |
addOverlay: function (layer, name) { | |
this._addLayer(layer, name, true); | |
this._update(); | |
return this; | |
}, | |
removeLayer: function (layer) { | |
var id = L.stamp(layer); | |
delete this._layers[id]; | |
this._update(); | |
return this; | |
}, | |
_initLayout: function () { | |
var className = 'leaflet-control-layers', | |
container = this._container = L.DomUtil.create('div', className); | |
//Makes this work on IE10 Touch devices by stopping it from firing a mouseout event when the touch is released | |
container.setAttribute('aria-haspopup', true); | |
if (!L.Browser.touch) { | |
L.DomEvent | |
.disableClickPropagation(container) | |
.disableScrollPropagation(container); | |
} else { | |
L.DomEvent.on(container, 'click', L.DomEvent.stopPropagation); | |
} | |
var form = this._form = L.DomUtil.create('form', className + '-list'); | |
if (this.options.collapsed) { | |
if (!L.Browser.android) { | |
L.DomEvent | |
.on(container, 'mouseover', this._expand, this) | |
.on(container, 'mouseout', this._collapse, this); | |
} | |
var link = this._layersLink = L.DomUtil.create('a', className + '-toggle', container); | |
link.href = '#'; | |
link.title = 'Layers'; | |
if (L.Browser.touch) { | |
L.DomEvent | |
.on(link, 'click', L.DomEvent.stop) | |
.on(link, 'click', this._expand, this); | |
} | |
else { | |
L.DomEvent.on(link, 'focus', this._expand, this); | |
} | |
//Work around for Firefox android issue https://github.com/Leaflet/Leaflet/issues/2033 | |
L.DomEvent.on(form, 'click', function () { | |
setTimeout(L.bind(this._onInputClick, this), 0); | |
}, this); | |
this._map.on('click', this._collapse, this); | |
// TODO keyboard accessibility | |
} else { | |
this._expand(); | |
} | |
this._baseLayersList = L.DomUtil.create('div', className + '-base', form); | |
this._separator = L.DomUtil.create('div', className + '-separator', form); | |
this._overlaysList = L.DomUtil.create('div', className + '-overlays', form); | |
container.appendChild(form); | |
}, | |
_addLayer: function (layer, name, overlay) { | |
var id = L.stamp(layer); | |
this._layers[id] = { | |
layer: layer, | |
name: name, | |
overlay: overlay | |
}; | |
if (this.options.autoZIndex && layer.setZIndex) { | |
this._lastZIndex++; | |
layer.setZIndex(this._lastZIndex); | |
} | |
}, | |
_update: function () { | |
if (!this._container) { | |
return; | |
} | |
this._baseLayersList.innerHTML = ''; | |
this._overlaysList.innerHTML = ''; | |
var baseLayersPresent = false, | |
overlaysPresent = false, | |
i, obj; | |
for (i in this._layers) { | |
obj = this._layers[i]; | |
this._addItem(obj); | |
overlaysPresent = overlaysPresent || obj.overlay; | |
baseLayersPresent = baseLayersPresent || !obj.overlay; | |
} | |
this._separator.style.display = overlaysPresent && baseLayersPresent ? '' : 'none'; | |
}, | |
_onLayerChange: function (e) { | |
var obj = this._layers[L.stamp(e.layer)]; | |
if (!obj) { return; } | |
if (!this._handlingClick) { | |
this._update(); | |
} | |
var type = obj.overlay ? | |
(e.type === 'layeradd' ? 'overlayadd' : 'overlayremove') : | |
(e.type === 'layeradd' ? 'baselayerchange' : null); | |
if (type) { | |
this._map.fire(type, obj); | |
} | |
}, | |
// IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see http://bit.ly/PqYLBe) | |
_createRadioElement: function (name, checked) { | |
var radioHtml = '<input type="radio" class="leaflet-control-layers-selector" name="' + name + '"'; | |
if (checked) { | |
radioHtml += ' checked="checked"'; | |
} | |
radioHtml += '/>'; | |
var radioFragment = document.createElement('div'); | |
radioFragment.innerHTML = radioHtml; | |
return radioFragment.firstChild; | |
}, | |
_addItem: function (obj) { | |
var label = document.createElement('label'), | |
input, | |
checked = this._map.hasLayer(obj.layer); | |
if (obj.overlay) { | |
input = document.createElement('input'); | |
input.type = 'checkbox'; | |
input.className = 'leaflet-control-layers-selector'; | |
input.defaultChecked = checked; | |
} else { | |
input = this._createRadioElement('leaflet-base-layers', checked); | |
} | |
input.layerId = L.stamp(obj.layer); | |
L.DomEvent.on(input, 'click', this._onInputClick, this); | |
var name = document.createElement('span'); | |
name.innerHTML = ' ' + obj.name; | |
label.appendChild(input); | |
label.appendChild(name); | |
var container = obj.overlay ? this._overlaysList : this._baseLayersList; | |
container.appendChild(label); | |
return label; | |
}, | |
_onInputClick: function () { | |
var i, input, obj, | |
inputs = this._form.getElementsByTagName('input'), | |
inputsLen = inputs.length; | |
this._handlingClick = true; | |
for (i = 0; i < inputsLen; i++) { | |
input = inputs[i]; | |
obj = this._layers[input.layerId]; | |
if (input.checked && !this._map.hasLayer(obj.layer)) { | |
this._map.addLayer(obj.layer); | |
} else if (!input.checked && this._map.hasLayer(obj.layer)) { | |
this._map.removeLayer(obj.layer); | |
} | |
} | |
this._handlingClick = false; | |
this._refocusOnMap(); | |
}, | |
_expand: function () { | |
L.DomUtil.addClass(this._container, 'leaflet-control-layers-expanded'); | |
}, | |
_collapse: function () { | |
this._container.className = this._container.className.replace(' leaflet-control-layers-expanded', ''); | |
} | |
}); | |
L.control.layers = function (baseLayers, overlays, options) { | |
return new L.Control.Layers(baseLayers, overlays, options); | |
}; | |
/* | |
* L.PosAnimation is used by Leaflet internally for pan animations. | |
*/ | |
L.PosAnimation = L.Class.extend({ | |
includes: L.Mixin.Events, | |
run: function (el, newPos, duration, easeLinearity) { // (HTMLElement, Point[, Number, Number]) | |
this.stop(); | |
this._el = el; | |
this._inProgress = true; | |
this._newPos = newPos; | |
this.fire('start'); | |
el.style[L.DomUtil.TRANSITION] = 'all ' + (duration || 0.25) + | |
's cubic-bezier(0,0,' + (easeLinearity || 0.5) + ',1)'; | |
L.DomEvent.on(el, L.DomUtil.TRANSITION_END, this._onTransitionEnd, this); | |
L.DomUtil.setPosition(el, newPos); | |
// toggle reflow, Chrome flickers for some reason if you don't do this | |
L.Util.falseFn(el.offsetWidth); | |
// there's no native way to track value updates of transitioned properties, so we imitate this | |
this._stepTimer = setInterval(L.bind(this._onStep, this), 50); | |
}, | |
stop: function () { | |
if (!this._inProgress) { return; } | |
// if we just removed the transition property, the element would jump to its final position, | |
// so we need to make it stay at the current position | |
L.DomUtil.setPosition(this._el, this._getPos()); | |
this._onTransitionEnd(); | |
L.Util.falseFn(this._el.offsetWidth); // force reflow in case we are about to start a new animation | |
}, | |
_onStep: function () { | |
var stepPos = this._getPos(); | |
if (!stepPos) { | |
this._onTransitionEnd(); | |
return; | |
} | |
// jshint camelcase: false | |
// make L.DomUtil.getPosition return intermediate position value during animation | |
this._el._leaflet_pos = stepPos; | |
this.fire('step'); | |
}, | |
// you can't easily get intermediate values of properties animated with CSS3 Transitions, | |
// we need to parse computed style (in case of transform it returns matrix string) | |
_transformRe: /([-+]?(?:\d*\.)?\d+)\D*, ([-+]?(?:\d*\.)?\d+)\D*\)/, | |
_getPos: function () { | |
var left, top, matches, | |
el = this._el, | |
style = window.getComputedStyle(el); | |
if (L.Browser.any3d) { | |
matches = style[L.DomUtil.TRANSFORM].match(this._transformRe); | |
if (!matches) { return; } | |
left = parseFloat(matches[1]); | |
top = parseFloat(matches[2]); | |
} else { | |
left = parseFloat(style.left); | |
top = parseFloat(style.top); | |
} | |
return new L.Point(left, top, true); | |
}, | |
_onTransitionEnd: function () { | |
L.DomEvent.off(this._el, L.DomUtil.TRANSITION_END, this._onTransitionEnd, this); | |
if (!this._inProgress) { return; } | |
this._inProgress = false; | |
this._el.style[L.DomUtil.TRANSITION] = ''; | |
// jshint camelcase: false | |
// make sure L.DomUtil.getPosition returns the final position value after animation | |
this._el._leaflet_pos = this._newPos; | |
clearInterval(this._stepTimer); | |
this.fire('step').fire('end'); | |
} | |
}); | |
/* | |
* Extends L.Map to handle panning animations. | |
*/ | |
L.Map.include({ | |
setView: function (center, zoom, options) { | |
zoom = zoom === undefined ? this._zoom : this._limitZoom(zoom); | |
center = this._limitCenter(L.latLng(center), zoom, this.options.maxBounds); | |
options = options || {}; | |
if (this._panAnim) { | |
this._panAnim.stop(); | |
} | |
if (this._loaded && !options.reset && options !== true) { | |
if (options.animate !== undefined) { | |
options.zoom = L.extend({animate: options.animate}, options.zoom); | |
options.pan = L.extend({animate: options.animate}, options.pan); | |
} | |
// try animating pan or zoom | |
var animated = (this._zoom !== zoom) ? | |
this._tryAnimatedZoom && this._tryAnimatedZoom(center, zoom, options.zoom) : | |
this._tryAnimatedPan(center, options.pan); | |
if (animated) { | |
// prevent resize handler call, the view will refresh after animation anyway | |
clearTimeout(this._sizeTimer); | |
return this; | |
} | |
} | |
// animation didn't start, just reset the map view | |
this._resetView(center, zoom); | |
return this; | |
}, | |
panBy: function (offset, options) { | |
offset = L.point(offset).round(); | |
options = options || {}; | |
if (!offset.x && !offset.y) { | |
return this; | |
} | |
if (!this._panAnim) { | |
this._panAnim = new L.PosAnimation(); | |
this._panAnim.on({ | |
'step': this._onPanTransitionStep, | |
'end': this._onPanTransitionEnd | |
}, this); | |
} | |
// don't fire movestart if animating inertia | |
if (!options.noMoveStart) { | |
this.fire('movestart'); | |
} | |
// animate pan unless animate: false specified | |
if (options.animate !== false) { | |
L.DomUtil.addClass(this._mapPane, 'leaflet-pan-anim'); | |
var newPos = this._getMapPanePos().subtract(offset); | |
this._panAnim.run(this._mapPane, newPos, options.duration || 0.25, options.easeLinearity); | |
} else { | |
this._rawPanBy(offset); | |
this.fire('move').fire('moveend'); | |
} | |
return this; | |
}, | |
_onPanTransitionStep: function () { | |
this.fire('move'); | |
}, | |
_onPanTransitionEnd: function () { | |
L.DomUtil.removeClass(this._mapPane, 'leaflet-pan-anim'); | |
this.fire('moveend'); | |
}, | |
_tryAnimatedPan: function (center, options) { | |
// difference between the new and current centers in pixels | |
var offset = this._getCenterOffset(center)._floor(); | |
// don't animate too far unless animate: true specified in options | |
if ((options && options.animate) !== true && !this.getSize().contains(offset)) { return false; } | |
this.panBy(offset, options); | |
return true; | |
} | |
}); | |
/* | |
* L.PosAnimation fallback implementation that powers Leaflet pan animations | |
* in browsers that don't support CSS3 Transitions. | |
*/ | |
L.PosAnimation = L.DomUtil.TRANSITION ? L.PosAnimation : L.PosAnimation.extend({ | |
run: function (el, newPos, duration, easeLinearity) { // (HTMLElement, Point[, Number, Number]) | |
this.stop(); | |
this._el = el; | |
this._inProgress = true; | |
this._duration = duration || 0.25; | |
this._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2); | |
this._startPos = L.DomUtil.getPosition(el); | |
this._offset = newPos.subtract(this._startPos); | |
this._startTime = +new Date(); | |
this.fire('start'); | |
this._animate(); | |
}, | |
stop: function () { | |
if (!this._inProgress) { return; } | |
this._step(); | |
this._complete(); | |
}, | |
_animate: function () { | |
// animation loop | |
this._animId = L.Util.requestAnimFrame(this._animate, this); | |
this._step(); | |
}, | |
_step: function () { | |
var elapsed = (+new Date()) - this._startTime, | |
duration = this._duration * 1000; | |
if (elapsed < duration) { | |
this._runFrame(this._easeOut(elapsed / duration)); | |
} else { | |
this._runFrame(1); | |
this._complete(); | |
} | |
}, | |
_runFrame: function (progress) { | |
var pos = this._startPos.add(this._offset.multiplyBy(progress)); | |
L.DomUtil.setPosition(this._el, pos); | |
this.fire('step'); | |
}, | |
_complete: function () { | |
L.Util.cancelAnimFrame(this._animId); | |
this._inProgress = false; | |
this.fire('end'); | |
}, | |
_easeOut: function (t) { | |
return 1 - Math.pow(1 - t, this._easeOutPower); | |
} | |
}); | |
/* | |
* Extends L.Map to handle zoom animations. | |
*/ | |
L.Map.mergeOptions({ | |
zoomAnimation: true, | |
zoomAnimationThreshold: 4 | |
}); | |
if (L.DomUtil.TRANSITION) { | |
L.Map.addInitHook(function () { | |
// don't animate on browsers without hardware-accelerated transitions or old Android/Opera | |
this._zoomAnimated = this.options.zoomAnimation && L.DomUtil.TRANSITION && | |
L.Browser.any3d && !L.Browser.android23 && !L.Browser.mobileOpera; | |
// zoom transitions run with the same duration for all layers, so if one of transitionend events | |
// happens after starting zoom animation (propagating to the map pane), we know that it ended globally | |
if (this._zoomAnimated) { | |
L.DomEvent.on(this._mapPane, L.DomUtil.TRANSITION_END, this._catchTransitionEnd, this); | |
} | |
}); | |
} | |
L.Map.include(!L.DomUtil.TRANSITION ? {} : { | |
_catchTransitionEnd: function (e) { | |
if (this._animatingZoom && e.propertyName.indexOf('transform') >= 0) { | |
this._onZoomTransitionEnd(); | |
} | |
}, | |
_nothingToAnimate: function () { | |
return !this._container.getElementsByClassName('leaflet-zoom-animated').length; | |
}, | |
_tryAnimatedZoom: function (center, zoom, options) { | |
if (this._animatingZoom) { return true; } | |
options = options || {}; | |
// don't animate if disabled, not supported or zoom difference is too large | |
if (!this._zoomAnimated || options.animate === false || this._nothingToAnimate() || | |
Math.abs(zoom - this._zoom) > this.options.zoomAnimationThreshold) { return false; } | |
// offset is the pixel coords of the zoom origin relative to the current center | |
var scale = this.getZoomScale(zoom), | |
offset = this._getCenterOffset(center)._divideBy(1 - 1 / scale), | |
origin = this._getCenterLayerPoint()._add(offset); | |
// don't animate if the zoom origin isn't within one screen from the current center, unless forced | |
if (options.animate !== true && !this.getSize().contains(offset)) { return false; } | |
this | |
.fire('movestart') | |
.fire('zoomstart'); | |
this._animateZoom(center, zoom, origin, scale, null, true); | |
return true; | |
}, | |
_animateZoom: function (center, zoom, origin, scale, delta, backwards, forTouchZoom) { | |
if (!forTouchZoom) { | |
this._animatingZoom = true; | |
} | |
// put transform transition on all layers with leaflet-zoom-animated class | |
L.DomUtil.addClass(this._mapPane, 'leaflet-zoom-anim'); | |
// remember what center/zoom to set after animation | |
this._animateToCenter = center; | |
this._animateToZoom = zoom; | |
// disable any dragging during animation | |
if (L.Draggable) { | |
L.Draggable._disabled = true; | |
} | |
L.Util.requestAnimFrame(function () { | |
this.fire('zoomanim', { | |
center: center, | |
zoom: zoom, | |
origin: origin, | |
scale: scale, | |
delta: delta, | |
backwards: backwards | |
}); | |
// horrible hack to work around a Chrome bug https://github.com/Leaflet/Leaflet/issues/3689 | |
setTimeout(L.bind(this._onZoomTransitionEnd, this), 250); | |
}, this); | |
}, | |
_onZoomTransitionEnd: function () { | |
if (!this._animatingZoom) { return; } | |
this._animatingZoom = false; | |
L.DomUtil.removeClass(this._mapPane, 'leaflet-zoom-anim'); | |
L.Util.requestAnimFrame(function () { | |
this._resetView(this._animateToCenter, this._animateToZoom, true, true); | |
if (L.Draggable) { | |
L.Draggable._disabled = false; | |
} | |
}, this); | |
} | |
}); | |
/* | |
Zoom animation logic for L.TileLayer. | |
*/ | |
L.TileLayer.include({ | |
_animateZoom: function (e) { | |
if (!this._animating) { | |
this._animating = true; | |
this._prepareBgBuffer(); | |
} | |
var bg = this._bgBuffer, | |
transform = L.DomUtil.TRANSFORM, | |
initialTransform = e.delta ? L.DomUtil.getTranslateString(e.delta) : bg.style[transform], | |
scaleStr = L.DomUtil.getScaleString(e.scale, e.origin); | |
bg.style[transform] = e.backwards ? | |
scaleStr + ' ' + initialTransform : | |
initialTransform + ' ' + scaleStr; | |
}, | |
_endZoomAnim: function () { | |
var front = this._tileContainer, | |
bg = this._bgBuffer; | |
front.style.visibility = ''; | |
front.parentNode.appendChild(front); // Bring to fore | |
// force reflow | |
L.Util.falseFn(bg.offsetWidth); | |
var zoom = this._map.getZoom(); | |
if (zoom > this.options.maxZoom || zoom < this.options.minZoom) { | |
this._clearBgBuffer(); | |
} | |
this._animating = false; | |
}, | |
_clearBgBuffer: function () { | |
var map = this._map; | |
if (map && !map._animatingZoom && !map.touchZoom._zooming) { | |
this._bgBuffer.innerHTML = ''; | |
this._bgBuffer.style[L.DomUtil.TRANSFORM] = ''; | |
} | |
}, | |
_prepareBgBuffer: function () { | |
var front = this._tileContainer, | |
bg = this._bgBuffer; | |
// if foreground layer doesn't have many tiles but bg layer does, | |
// keep the existing bg layer and just zoom it some more | |
var bgLoaded = this._getLoadedTilesPercentage(bg), | |
frontLoaded = this._getLoadedTilesPercentage(front); | |
if (bg && bgLoaded > 0.5 && frontLoaded < 0.5) { | |
front.style.visibility = 'hidden'; | |
this._stopLoadingImages(front); | |
return; | |
} | |
// prepare the buffer to become the front tile pane | |
bg.style.visibility = 'hidden'; | |
bg.style[L.DomUtil.TRANSFORM] = ''; | |
// switch out the current layer to be the new bg layer (and vice-versa) | |
this._tileContainer = bg; | |
bg = this._bgBuffer = front; | |
this._stopLoadingImages(bg); | |
//prevent bg buffer from clearing right after zoom | |
clearTimeout(this._clearBgBufferTimer); | |
}, | |
_getLoadedTilesPercentage: function (container) { | |
var tiles = container.getElementsByTagName('img'), | |
i, len, count = 0; | |
for (i = 0, len = tiles.length; i < len; i++) { | |
if (tiles[i].complete) { | |
count++; | |
} | |
} | |
return count / len; | |
}, | |
// stops loading all tiles in the background layer | |
_stopLoadingImages: function (container) { | |
var tiles = Array.prototype.slice.call(container.getElementsByTagName('img')), | |
i, len, tile; | |
for (i = 0, len = tiles.length; i < len; i++) { | |
tile = tiles[i]; | |
if (!tile.complete) { | |
tile.onload = L.Util.falseFn; | |
tile.onerror = L.Util.falseFn; | |
tile.src = L.Util.emptyImageUrl; | |
tile.parentNode.removeChild(tile); | |
} | |
} | |
} | |
}); | |
/* | |
* Provides L.Map with convenient shortcuts for using browser geolocation features. | |
*/ | |
L.Map.include({ | |
_defaultLocateOptions: { | |
watch: false, | |
setView: false, | |
maxZoom: Infinity, | |
timeout: 10000, | |
maximumAge: 0, | |
enableHighAccuracy: false | |
}, | |
locate: function (/*Object*/ options) { | |
options = this._locateOptions = L.extend(this._defaultLocateOptions, options); | |
if (!navigator.geolocation) { | |
this._handleGeolocationError({ | |
code: 0, | |
message: 'Geolocation not supported.' | |
}); | |
return this; | |
} | |
var onResponse = L.bind(this._handleGeolocationResponse, this), | |
onError = L.bind(this._handleGeolocationError, this); | |
if (options.watch) { | |
this._locationWatchId = | |
navigator.geolocation.watchPosition(onResponse, onError, options); | |
} else { | |
navigator.geolocation.getCurrentPosition(onResponse, onError, options); | |
} | |
return this; | |
}, | |
stopLocate: function () { | |
if (navigator.geolocation) { | |
navigator.geolocation.clearWatch(this._locationWatchId); | |
} | |
if (this._locateOptions) { | |
this._locateOptions.setView = false; | |
} | |
return this; | |
}, | |
_handleGeolocationError: function (error) { | |
var c = error.code, | |
message = error.message || | |
(c === 1 ? 'permission denied' : | |
(c === 2 ? 'position unavailable' : 'timeout')); | |
if (this._locateOptions.setView && !this._loaded) { | |
this.fitWorld(); | |
} | |
this.fire('locationerror', { | |
code: c, | |
message: 'Geolocation error: ' + message + '.' | |
}); | |
}, | |
_handleGeolocationResponse: function (pos) { | |
var lat = pos.coords.latitude, | |
lng = pos.coords.longitude, | |
latlng = new L.LatLng(lat, lng), | |
latAccuracy = 180 * pos.coords.accuracy / 40075017, | |
lngAccuracy = latAccuracy / Math.cos(L.LatLng.DEG_TO_RAD * lat), | |
bounds = L.latLngBounds( | |
[lat - latAccuracy, lng - lngAccuracy], | |
[lat + latAccuracy, lng + lngAccuracy]), | |
options = this._locateOptions; | |
if (options.setView) { | |
var zoom = Math.min(this.getBoundsZoom(bounds), options.maxZoom); | |
this.setView(latlng, zoom); | |
} | |
var data = { | |
latlng: latlng, | |
bounds: bounds, | |
timestamp: pos.timestamp | |
}; | |
for (var i in pos.coords) { | |
if (typeof pos.coords[i] === 'number') { | |
data[i] = pos.coords[i]; | |
} | |
} | |
this.fire('locationfound', data); | |
} | |
}); | |
}(window, document)); | |
},{}],"leaflet-component/leafletMarkerComponent":[function(require,module,exports){ | |
'use strict' | |
const L = require('leaflet'); | |
module.exports = function(fastn, component, type, settings, children) { | |
component.render = function(){ | |
L.Icon.Default.imagePath = 'markers'; | |
component.element = L.marker([ | |
component.gis_lat(), | |
component.gis_lng() | |
], { | |
clickable: true, | |
title: component.title() | |
}); | |
component.element.on('click', function(event){ | |
component.emit('click', event, component.scope()) | |
}); | |
}; | |
function updatePosition(){ | |
if(!component.element){ | |
return; | |
} | |
component.element.setLatLng([ | |
component.gis_lat(), | |
component.gis_lng() | |
]); | |
} | |
function updateTitle(){ | |
if(!component.element){ | |
return; | |
} | |
component.element.setTitle([ | |
component.title() | |
]); | |
} | |
function updateType(){ | |
if(!component.element){ | |
return; | |
} | |
component.element.setType([ | |
component.type() | |
]); | |
} | |
function updateStatus(){ | |
if(!component.element){ | |
return; | |
} | |
component.element.setStatus([ | |
component.status() | |
]); | |
} | |
fastn.property(0, 'value') | |
.addTo(component, 'gis_lat') | |
.on('change', updatePosition); | |
fastn.property(0, 'value') | |
.addTo(component, 'gis_lng') | |
.on('change', updatePosition); | |
fastn.property(0, 'value') | |
.addTo(component, 'title') | |
.on('change', updateTitle); | |
fastn.property(0, 'value') | |
.addTo(component, 'type') | |
.on('change', updateType); | |
fastn.property(0, 'value') | |
.addTo(component, 'status') | |
.on('change', updateStatus); | |
return component; | |
} | |
},{"leaflet":1}]},{},[]) | |
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIm5vZGVfbW9kdWxlcy9sZWFmbGV0L2Rpc3QvbGVhZmxldC1zcmMuanMiLCJsZWFmbGV0TWFya2VyQ29tcG9uZW50LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy84UkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIvKlxuIExlYWZsZXQsIGEgSmF2YVNjcmlwdCBsaWJyYXJ5IGZvciBtb2JpbGUtZnJpZW5kbHkgaW50ZXJhY3RpdmUgbWFwcy4gaHR0cDovL2xlYWZsZXRqcy5jb21cbiAoYykgMjAxMC0yMDEzLCBWbGFkaW1pciBBZ2Fmb25raW5cbiAoYykgMjAxMC0yMDExLCBDbG91ZE1hZGVcbiovXG4oZnVuY3Rpb24gKHdpbmRvdywgZG9jdW1lbnQsIHVuZGVmaW5lZCkge1xyXG52YXIgb2xkTCA9IHdpbmRvdy5MLFxyXG4gICAgTCA9IHt9O1xyXG5cclxuTC52ZXJzaW9uID0gJzAuNy43JztcclxuXHJcbi8vIGRlZmluZSBMZWFmbGV0IGZvciBOb2RlIG1vZHVsZSBwYXR0ZXJuIGxvYWRlcnMsIGluY2x1ZGluZyBCcm93c2VyaWZ5XHJcbmlmICh0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPT09ICdvYmplY3QnKSB7XHJcblx0bW9kdWxlLmV4cG9ydHMgPSBMO1xyXG5cclxuLy8gZGVmaW5lIExlYWZsZXQgYXMgYW4gQU1EIG1vZHVsZVxyXG59IGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xyXG5cdGRlZmluZShMKTtcclxufVxyXG5cclxuLy8gZGVmaW5lIExlYWZsZXQgYXMgYSBnbG9iYWwgTCB2YXJpYWJsZSwgc2F2aW5nIHRoZSBvcmlnaW5hbCBMIHRvIHJlc3RvcmUgbGF0ZXIgaWYgbmVlZGVkXHJcblxyXG5MLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XHJcblx0d2luZG93LkwgPSBvbGRMO1xyXG5cdHJldHVybiB0aGlzO1xyXG59O1xyXG5cclxud2luZG93LkwgPSBMO1xyXG5cblxuLypcclxuICogTC5VdGlsIGNvbnRhaW5zIHZhcmlvdXMgdXRpbGl0eSBmdW5jdGlvbnMgdXNlZCB0aHJvdWdob3V0IExlYWZsZXQgY29kZS5cclxuICovXHJcblxyXG5MLlV0aWwgPSB7XHJcblx0ZXh0ZW5kOiBmdW5jdGlvbiAoZGVzdCkgeyAvLyAoT2JqZWN0WywgT2JqZWN0LCAuLi5dKSAtPlxyXG5cdFx0dmFyIHNvdXJjZXMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxyXG5cdFx0ICAgIGksIGosIGxlbiwgc3JjO1xyXG5cclxuXHRcdGZvciAoaiA9IDAsIGxlbiA9IHNvdXJjZXMubGVuZ3RoOyBqIDwgbGVuOyBqKyspIHtcclxuXHRcdFx0c3JjID0gc291cmNlc1tqXSB8fCB7fTtcclxuXHRcdFx0Zm9yIChpIGluIHNyYykge1xyXG5cdFx0XHRcdGlmIChzcmMuaGFzT3duUHJvcGVydHkoaSkpIHtcclxuXHRcdFx0XHRcdGRlc3RbaV0gPSBzcmNbaV07XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gZGVzdDtcclxuXHR9LFxyXG5cclxuXHRiaW5kOiBmdW5jdGlvbiAoZm4sIG9iaikgeyAvLyAoRnVuY3Rpb24sIE9iamVjdCkgLT4gRnVuY3Rpb25cclxuXHRcdHZhciBhcmdzID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgPyBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpIDogbnVsbDtcclxuXHRcdHJldHVybiBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdHJldHVybiBmbi5hcHBseShvYmosIGFyZ3MgfHwgYXJndW1lbnRzKTtcclxuXHRcdH07XHJcblx0fSxcclxuXHJcblx0c3RhbXA6IChmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgbGFzdElkID0gMCxcclxuXHRcdCAgICBrZXkgPSAnX2xlYWZsZXRfaWQnO1xyXG5cdFx0cmV0dXJuIGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdFx0b2JqW2tleV0gPSBvYmpba2V5XSB8fCArK2xhc3RJZDtcclxuXHRcdFx0cmV0dXJuIG9ialtrZXldO1xyXG5cdFx0fTtcclxuXHR9KCkpLFxyXG5cclxuXHRpbnZva2VFYWNoOiBmdW5jdGlvbiAob2JqLCBtZXRob2QsIGNvbnRleHQpIHtcclxuXHRcdHZhciBpLCBhcmdzO1xyXG5cclxuXHRcdGlmICh0eXBlb2Ygb2JqID09PSAnb2JqZWN0Jykge1xyXG5cdFx0XHRhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAzKTtcclxuXHJcblx0XHRcdGZvciAoaSBpbiBvYmopIHtcclxuXHRcdFx0XHRtZXRob2QuYXBwbHkoY29udGV4dCwgW2ksIG9ialtpXV0uY29uY2F0KGFyZ3MpKTtcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gZmFsc2U7XHJcblx0fSxcclxuXHJcblx0bGltaXRFeGVjQnlJbnRlcnZhbDogZnVuY3Rpb24gKGZuLCB0aW1lLCBjb250ZXh0KSB7XHJcblx0XHR2YXIgbG9jaywgZXhlY09uVW5sb2NrO1xyXG5cclxuXHRcdHJldHVybiBmdW5jdGlvbiB3cmFwcGVyRm4oKSB7XHJcblx0XHRcdHZhciBhcmdzID0gYXJndW1lbnRzO1xyXG5cclxuXHRcdFx0aWYgKGxvY2spIHtcclxuXHRcdFx0XHRleGVjT25VbmxvY2sgPSB0cnVlO1xyXG5cdFx0XHRcdHJldHVybjtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0bG9jayA9IHRydWU7XHJcblxyXG5cdFx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0XHRsb2NrID0gZmFsc2U7XHJcblxyXG5cdFx0XHRcdGlmIChleGVjT25VbmxvY2spIHtcclxuXHRcdFx0XHRcdHdyYXBwZXJGbi5hcHBseShjb250ZXh0LCBhcmdzKTtcclxuXHRcdFx0XHRcdGV4ZWNPblVubG9jayA9IGZhbHNlO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fSwgdGltZSk7XHJcblxyXG5cdFx0XHRmbi5hcHBseShjb250ZXh0LCBhcmdzKTtcclxuXHRcdH07XHJcblx0fSxcclxuXHJcblx0ZmFsc2VGbjogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIGZhbHNlO1xyXG5cdH0sXHJcblxyXG5cdGZvcm1hdE51bTogZnVuY3Rpb24gKG51bSwgZGlnaXRzKSB7XHJcblx0XHR2YXIgcG93ID0gTWF0aC5wb3coMTAsIGRpZ2l0cyB8fCA1KTtcclxuXHRcdHJldHVybiBNYXRoLnJvdW5kKG51bSAqIHBvdykgLyBwb3c7XHJcblx0fSxcclxuXHJcblx0dHJpbTogZnVuY3Rpb24gKHN0cikge1xyXG5cdFx0cmV0dXJuIHN0ci50cmltID8gc3RyLnRyaW0oKSA6IHN0ci5yZXBsYWNlKC9eXFxzK3xcXHMrJC9nLCAnJyk7XHJcblx0fSxcclxuXHJcblx0c3BsaXRXb3JkczogZnVuY3Rpb24gKHN0cikge1xyXG5cdFx0cmV0dXJuIEwuVXRpbC50cmltKHN0cikuc3BsaXQoL1xccysvKTtcclxuXHR9LFxyXG5cclxuXHRzZXRPcHRpb25zOiBmdW5jdGlvbiAob2JqLCBvcHRpb25zKSB7XHJcblx0XHRvYmoub3B0aW9ucyA9IEwuZXh0ZW5kKHt9LCBvYmoub3B0aW9ucywgb3B0aW9ucyk7XHJcblx0XHRyZXR1cm4gb2JqLm9wdGlvbnM7XHJcblx0fSxcclxuXHJcblx0Z2V0UGFyYW1TdHJpbmc6IGZ1bmN0aW9uIChvYmosIGV4aXN0aW5nVXJsLCB1cHBlcmNhc2UpIHtcclxuXHRcdHZhciBwYXJhbXMgPSBbXTtcclxuXHRcdGZvciAodmFyIGkgaW4gb2JqKSB7XHJcblx0XHRcdHBhcmFtcy5wdXNoKGVuY29kZVVSSUNvbXBvbmVudCh1cHBlcmNhc2UgPyBpLnRvVXBwZXJDYXNlKCkgOiBpKSArICc9JyArIGVuY29kZVVSSUNvbXBvbmVudChvYmpbaV0pKTtcclxuXHRcdH1cclxuXHRcdHJldHVybiAoKCFleGlzdGluZ1VybCB8fCBleGlzdGluZ1VybC5pbmRleE9mKCc/JykgPT09IC0xKSA/ICc/JyA6ICcmJykgKyBwYXJhbXMuam9pbignJicpO1xyXG5cdH0sXHJcblx0dGVtcGxhdGU6IGZ1bmN0aW9uIChzdHIsIGRhdGEpIHtcclxuXHRcdHJldHVybiBzdHIucmVwbGFjZSgvXFx7ICooW1xcd19dKykgKlxcfS9nLCBmdW5jdGlvbiAoc3RyLCBrZXkpIHtcclxuXHRcdFx0dmFyIHZhbHVlID0gZGF0YVtrZXldO1xyXG5cdFx0XHRpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xyXG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcignTm8gdmFsdWUgcHJvdmlkZWQgZm9yIHZhcmlhYmxlICcgKyBzdHIpO1xyXG5cdFx0XHR9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xyXG5cdFx0XHRcdHZhbHVlID0gdmFsdWUoZGF0YSk7XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIHZhbHVlO1xyXG5cdFx0fSk7XHJcblx0fSxcclxuXHJcblx0aXNBcnJheTogQXJyYXkuaXNBcnJheSB8fCBmdW5jdGlvbiAob2JqKSB7XHJcblx0XHRyZXR1cm4gKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmopID09PSAnW29iamVjdCBBcnJheV0nKTtcclxuXHR9LFxyXG5cclxuXHRlbXB0eUltYWdlVXJsOiAnZGF0YTppbWFnZS9naWY7YmFzZTY0LFIwbEdPRGxoQVFBQkFBRC9BQ3dBQUFBQUFRQUJBQUFDQURzPSdcclxufTtcclxuXHJcbihmdW5jdGlvbiAoKSB7XHJcblxyXG5cdC8vIGluc3BpcmVkIGJ5IGh0dHA6Ly9wYXVsaXJpc2guY29tLzIwMTEvcmVxdWVzdGFuaW1hdGlvbmZyYW1lLWZvci1zbWFydC1hbmltYXRpbmcvXHJcblxyXG5cdGZ1bmN0aW9uIGdldFByZWZpeGVkKG5hbWUpIHtcclxuXHRcdHZhciBpLCBmbixcclxuXHRcdCAgICBwcmVmaXhlcyA9IFsnd2Via2l0JywgJ21veicsICdvJywgJ21zJ107XHJcblxyXG5cdFx0Zm9yIChpID0gMDsgaSA8IHByZWZpeGVzLmxlbmd0aCAmJiAhZm47IGkrKykge1xyXG5cdFx0XHRmbiA9IHdpbmRvd1twcmVmaXhlc1tpXSArIG5hbWVdO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBmbjtcclxuXHR9XHJcblxyXG5cdHZhciBsYXN0VGltZSA9IDA7XHJcblxyXG5cdGZ1bmN0aW9uIHRpbWVvdXREZWZlcihmbikge1xyXG5cdFx0dmFyIHRpbWUgPSArbmV3IERhdGUoKSxcclxuXHRcdCAgICB0aW1lVG9DYWxsID0gTWF0aC5tYXgoMCwgMTYgLSAodGltZSAtIGxhc3RUaW1lKSk7XHJcblxyXG5cdFx0bGFzdFRpbWUgPSB0aW1lICsgdGltZVRvQ2FsbDtcclxuXHRcdHJldHVybiB3aW5kb3cuc2V0VGltZW91dChmbiwgdGltZVRvQ2FsbCk7XHJcblx0fVxyXG5cclxuXHR2YXIgcmVxdWVzdEZuID0gd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSB8fFxyXG5cdCAgICAgICAgZ2V0UHJlZml4ZWQoJ1JlcXVlc3RBbmltYXRpb25GcmFtZScpIHx8IHRpbWVvdXREZWZlcjtcclxuXHJcblx0dmFyIGNhbmNlbEZuID0gd2luZG93LmNhbmNlbEFuaW1hdGlvbkZyYW1lIHx8XHJcblx0ICAgICAgICBnZXRQcmVmaXhlZCgnQ2FuY2VsQW5pbWF0aW9uRnJhbWUnKSB8fFxyXG5cdCAgICAgICAgZ2V0UHJlZml4ZWQoJ0NhbmNlbFJlcXVlc3RBbmltYXRpb25GcmFtZScpIHx8XHJcblx0ICAgICAgICBmdW5jdGlvbiAoaWQpIHsgd2luZG93LmNsZWFyVGltZW91dChpZCk7IH07XHJcblxyXG5cclxuXHRMLlV0aWwucmVxdWVzdEFuaW1GcmFtZSA9IGZ1bmN0aW9uIChmbiwgY29udGV4dCwgaW1tZWRpYXRlLCBlbGVtZW50KSB7XHJcblx0XHRmbiA9IEwuYmluZChmbiwgY29udGV4dCk7XHJcblxyXG5cdFx0aWYgKGltbWVkaWF0ZSAmJiByZXF1ZXN0Rm4gPT09IHRpbWVvdXREZWZlcikge1xyXG5cdFx0XHRmbigpO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0cmV0dXJuIHJlcXVlc3RGbi5jYWxsKHdpbmRvdywgZm4sIGVsZW1lbnQpO1xyXG5cdFx0fVxyXG5cdH07XHJcblxyXG5cdEwuVXRpbC5jYW5jZWxBbmltRnJhbWUgPSBmdW5jdGlvbiAoaWQpIHtcclxuXHRcdGlmIChpZCkge1xyXG5cdFx0XHRjYW5jZWxGbi5jYWxsKHdpbmRvdywgaWQpO1xyXG5cdFx0fVxyXG5cdH07XHJcblxyXG59KCkpO1xyXG5cclxuLy8gc2hvcnRjdXRzIGZvciBtb3N0IHVzZWQgdXRpbGl0eSBmdW5jdGlvbnNcclxuTC5leHRlbmQgPSBMLlV0aWwuZXh0ZW5kO1xyXG5MLmJpbmQgPSBMLlV0aWwuYmluZDtcclxuTC5zdGFtcCA9IEwuVXRpbC5zdGFtcDtcclxuTC5zZXRPcHRpb25zID0gTC5VdGlsLnNldE9wdGlvbnM7XHJcblxuXG4vKlxyXG4gKiBMLkNsYXNzIHBvd2VycyB0aGUgT09QIGZhY2lsaXRpZXMgb2YgdGhlIGxpYnJhcnkuXHJcbiAqIFRoYW5rcyB0byBKb2huIFJlc2lnIGFuZCBEZWFuIEVkd2FyZHMgZm9yIGluc3BpcmF0aW9uIVxyXG4gKi9cclxuXHJcbkwuQ2xhc3MgPSBmdW5jdGlvbiAoKSB7fTtcclxuXHJcbkwuQ2xhc3MuZXh0ZW5kID0gZnVuY3Rpb24gKHByb3BzKSB7XHJcblxyXG5cdC8vIGV4dGVuZGVkIGNsYXNzIHdpdGggdGhlIG5ldyBwcm90b3R5cGVcclxuXHR2YXIgTmV3Q2xhc3MgPSBmdW5jdGlvbiAoKSB7XHJcblxyXG5cdFx0Ly8gY2FsbCB0aGUgY29uc3RydWN0b3JcclxuXHRcdGlmICh0aGlzLmluaXRpYWxpemUpIHtcclxuXHRcdFx0dGhpcy5pbml0aWFsaXplLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gY2FsbCBhbGwgY29uc3RydWN0b3IgaG9va3NcclxuXHRcdGlmICh0aGlzLl9pbml0SG9va3MpIHtcclxuXHRcdFx0dGhpcy5jYWxsSW5pdEhvb2tzKCk7XHJcblx0XHR9XHJcblx0fTtcclxuXHJcblx0Ly8gaW5zdGFudGlhdGUgY2xhc3Mgd2l0aG91dCBjYWxsaW5nIGNvbnN0cnVjdG9yXHJcblx0dmFyIEYgPSBmdW5jdGlvbiAoKSB7fTtcclxuXHRGLnByb3RvdHlwZSA9IHRoaXMucHJvdG90eXBlO1xyXG5cclxuXHR2YXIgcHJvdG8gPSBuZXcgRigpO1xyXG5cdHByb3RvLmNvbnN0cnVjdG9yID0gTmV3Q2xhc3M7XHJcblxyXG5cdE5ld0NsYXNzLnByb3RvdHlwZSA9IHByb3RvO1xyXG5cclxuXHQvL2luaGVyaXQgcGFyZW50J3Mgc3RhdGljc1xyXG5cdGZvciAodmFyIGkgaW4gdGhpcykge1xyXG5cdFx0aWYgKHRoaXMuaGFzT3duUHJvcGVydHkoaSkgJiYgaSAhPT0gJ3Byb3RvdHlwZScpIHtcclxuXHRcdFx0TmV3Q2xhc3NbaV0gPSB0aGlzW2ldO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0Ly8gbWl4IHN0YXRpYyBwcm9wZXJ0aWVzIGludG8gdGhlIGNsYXNzXHJcblx0aWYgKHByb3BzLnN0YXRpY3MpIHtcclxuXHRcdEwuZXh0ZW5kKE5ld0NsYXNzLCBwcm9wcy5zdGF0aWNzKTtcclxuXHRcdGRlbGV0ZSBwcm9wcy5zdGF0aWNzO1xyXG5cdH1cclxuXHJcblx0Ly8gbWl4IGluY2x1ZGVzIGludG8gdGhlIHByb3RvdHlwZVxyXG5cdGlmIChwcm9wcy5pbmNsdWRlcykge1xyXG5cdFx0TC5VdGlsLmV4dGVuZC5hcHBseShudWxsLCBbcHJvdG9dLmNvbmNhdChwcm9wcy5pbmNsdWRlcykpO1xyXG5cdFx0ZGVsZXRlIHByb3BzLmluY2x1ZGVzO1xyXG5cdH1cclxuXHJcblx0Ly8gbWVyZ2Ugb3B0aW9uc1xyXG5cdGlmIChwcm9wcy5vcHRpb25zICYmIHByb3RvLm9wdGlvbnMpIHtcclxuXHRcdHByb3BzLm9wdGlvbnMgPSBMLmV4dGVuZCh7fSwgcHJvdG8ub3B0aW9ucywgcHJvcHMub3B0aW9ucyk7XHJcblx0fVxyXG5cclxuXHQvLyBtaXggZ2l2ZW4gcHJvcGVydGllcyBpbnRvIHRoZSBwcm90b3R5cGVcclxuXHRMLmV4dGVuZChwcm90bywgcHJvcHMpO1xyXG5cclxuXHRwcm90by5faW5pdEhvb2tzID0gW107XHJcblxyXG5cdHZhciBwYXJlbnQgPSB0aGlzO1xyXG5cdC8vIGpzaGludCBjYW1lbGNhc2U6IGZhbHNlXHJcblx0TmV3Q2xhc3MuX19zdXBlcl9fID0gcGFyZW50LnByb3RvdHlwZTtcclxuXHJcblx0Ly8gYWRkIG1ldGhvZCBmb3IgY2FsbGluZyBhbGwgaG9va3NcclxuXHRwcm90by5jYWxsSW5pdEhvb2tzID0gZnVuY3Rpb24gKCkge1xyXG5cclxuXHRcdGlmICh0aGlzLl9pbml0SG9va3NDYWxsZWQpIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0aWYgKHBhcmVudC5wcm90b3R5cGUuY2FsbEluaXRIb29rcykge1xyXG5cdFx0XHRwYXJlbnQucHJvdG90eXBlLmNhbGxJbml0SG9va3MuY2FsbCh0aGlzKTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9pbml0SG9va3NDYWxsZWQgPSB0cnVlO1xyXG5cclxuXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBwcm90by5faW5pdEhvb2tzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdHByb3RvLl9pbml0SG9va3NbaV0uY2FsbCh0aGlzKTtcclxuXHRcdH1cclxuXHR9O1xyXG5cclxuXHRyZXR1cm4gTmV3Q2xhc3M7XHJcbn07XHJcblxyXG5cclxuLy8gbWV0aG9kIGZvciBhZGRpbmcgcHJvcGVydGllcyB0byBwcm90b3R5cGVcclxuTC5DbGFzcy5pbmNsdWRlID0gZnVuY3Rpb24gKHByb3BzKSB7XHJcblx0TC5leHRlbmQodGhpcy5wcm90b3R5cGUsIHByb3BzKTtcclxufTtcclxuXHJcbi8vIG1lcmdlIG5ldyBkZWZhdWx0IG9wdGlvbnMgdG8gdGhlIENsYXNzXHJcbkwuQ2xhc3MubWVyZ2VPcHRpb25zID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuXHRMLmV4dGVuZCh0aGlzLnByb3RvdHlwZS5vcHRpb25zLCBvcHRpb25zKTtcclxufTtcclxuXHJcbi8vIGFkZCBhIGNvbnN0cnVjdG9yIGhvb2tcclxuTC5DbGFzcy5hZGRJbml0SG9vayA9IGZ1bmN0aW9uIChmbikgeyAvLyAoRnVuY3Rpb24pIHx8IChTdHJpbmcsIGFyZ3MuLi4pXHJcblx0dmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xyXG5cclxuXHR2YXIgaW5pdCA9IHR5cGVvZiBmbiA9PT0gJ2Z1bmN0aW9uJyA/IGZuIDogZnVuY3Rpb24gKCkge1xyXG5cdFx0dGhpc1tmbl0uYXBwbHkodGhpcywgYXJncyk7XHJcblx0fTtcclxuXHJcblx0dGhpcy5wcm90b3R5cGUuX2luaXRIb29rcyA9IHRoaXMucHJvdG90eXBlLl9pbml0SG9va3MgfHwgW107XHJcblx0dGhpcy5wcm90b3R5cGUuX2luaXRIb29rcy5wdXNoKGluaXQpO1xyXG59O1xyXG5cblxuLypcclxuICogTC5NaXhpbi5FdmVudHMgaXMgdXNlZCB0byBhZGQgY3VzdG9tIGV2ZW50cyBmdW5jdGlvbmFsaXR5IHRvIExlYWZsZXQgY2xhc3Nlcy5cclxuICovXHJcblxyXG52YXIgZXZlbnRzS2V5ID0gJ19sZWFmbGV0X2V2ZW50cyc7XHJcblxyXG5MLk1peGluID0ge307XHJcblxyXG5MLk1peGluLkV2ZW50cyA9IHtcclxuXHJcblx0YWRkRXZlbnRMaXN0ZW5lcjogZnVuY3Rpb24gKHR5cGVzLCBmbiwgY29udGV4dCkgeyAvLyAoU3RyaW5nLCBGdW5jdGlvblssIE9iamVjdF0pIG9yIChPYmplY3RbLCBPYmplY3RdKVxyXG5cclxuXHRcdC8vIHR5cGVzIGNhbiBiZSBhIG1hcCBvZiB0eXBlcy9oYW5kbGVyc1xyXG5cdFx0aWYgKEwuVXRpbC5pbnZva2VFYWNoKHR5cGVzLCB0aGlzLmFkZEV2ZW50TGlzdGVuZXIsIHRoaXMsIGZuLCBjb250ZXh0KSkgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuXHRcdHZhciBldmVudHMgPSB0aGlzW2V2ZW50c0tleV0gPSB0aGlzW2V2ZW50c0tleV0gfHwge30sXHJcblx0XHQgICAgY29udGV4dElkID0gY29udGV4dCAmJiBjb250ZXh0ICE9PSB0aGlzICYmIEwuc3RhbXAoY29udGV4dCksXHJcblx0XHQgICAgaSwgbGVuLCBldmVudCwgdHlwZSwgaW5kZXhLZXksIGluZGV4TGVuS2V5LCB0eXBlSW5kZXg7XHJcblxyXG5cdFx0Ly8gdHlwZXMgY2FuIGJlIGEgc3RyaW5nIG9mIHNwYWNlLXNlcGFyYXRlZCB3b3Jkc1xyXG5cdFx0dHlwZXMgPSBMLlV0aWwuc3BsaXRXb3Jkcyh0eXBlcyk7XHJcblxyXG5cdFx0Zm9yIChpID0gMCwgbGVuID0gdHlwZXMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuXHRcdFx0ZXZlbnQgPSB7XHJcblx0XHRcdFx0YWN0aW9uOiBmbixcclxuXHRcdFx0XHRjb250ZXh0OiBjb250ZXh0IHx8IHRoaXNcclxuXHRcdFx0fTtcclxuXHRcdFx0dHlwZSA9IHR5cGVzW2ldO1xyXG5cclxuXHRcdFx0aWYgKGNvbnRleHRJZCkge1xyXG5cdFx0XHRcdC8vIHN0b3JlIGxpc3RlbmVycyBvZiBhIHBhcnRpY3VsYXIgY29udGV4dCBpbiBhIHNlcGFyYXRlIGhhc2ggKGlmIGl0IGhhcyBhbiBpZClcclxuXHRcdFx0XHQvLyBnaXZlcyBhIG1ham9yIHBlcmZvcm1hbmNlIGJvb3N0IHdoZW4gcmVtb3ZpbmcgdGhvdXNhbmRzIG9mIG1hcCBsYXllcnNcclxuXHJcblx0XHRcdFx0aW5kZXhLZXkgPSB0eXBlICsgJ19pZHgnO1xyXG5cdFx0XHRcdGluZGV4TGVuS2V5ID0gaW5kZXhLZXkgKyAnX2xlbic7XHJcblxyXG5cdFx0XHRcdHR5cGVJbmRleCA9IGV2ZW50c1tpbmRleEtleV0gPSBldmVudHNbaW5kZXhLZXldIHx8IHt9O1xyXG5cclxuXHRcdFx0XHRpZiAoIXR5cGVJbmRleFtjb250ZXh0SWRdKSB7XHJcblx0XHRcdFx0XHR0eXBlSW5kZXhbY29udGV4dElkXSA9IFtdO1xyXG5cclxuXHRcdFx0XHRcdC8vIGtlZXAgdHJhY2sgb2YgdGhlIG51bWJlciBvZiBrZXlzIGluIHRoZSBpbmRleCB0byBxdWlja2x5IGNoZWNrIGlmIGl0J3MgZW1wdHlcclxuXHRcdFx0XHRcdGV2ZW50c1tpbmRleExlbktleV0gPSAoZXZlbnRzW2luZGV4TGVuS2V5XSB8fCAwKSArIDE7XHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHR0eXBlSW5kZXhbY29udGV4dElkXS5wdXNoKGV2ZW50KTtcclxuXHJcblxyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdGV2ZW50c1t0eXBlXSA9IGV2ZW50c1t0eXBlXSB8fCBbXTtcclxuXHRcdFx0XHRldmVudHNbdHlwZV0ucHVzaChldmVudCk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHRoYXNFdmVudExpc3RlbmVyczogZnVuY3Rpb24gKHR5cGUpIHsgLy8gKFN0cmluZykgLT4gQm9vbGVhblxyXG5cdFx0dmFyIGV2ZW50cyA9IHRoaXNbZXZlbnRzS2V5XTtcclxuXHRcdHJldHVybiAhIWV2ZW50cyAmJiAoKHR5cGUgaW4gZXZlbnRzICYmIGV2ZW50c1t0eXBlXS5sZW5ndGggPiAwKSB8fFxyXG5cdFx0ICAgICAgICAgICAgICAgICAgICAodHlwZSArICdfaWR4JyBpbiBldmVudHMgJiYgZXZlbnRzW3R5cGUgKyAnX2lkeF9sZW4nXSA+IDApKTtcclxuXHR9LFxyXG5cclxuXHRyZW1vdmVFdmVudExpc3RlbmVyOiBmdW5jdGlvbiAodHlwZXMsIGZuLCBjb250ZXh0KSB7IC8vIChbU3RyaW5nLCBGdW5jdGlvbiwgT2JqZWN0XSkgb3IgKE9iamVjdFssIE9iamVjdF0pXHJcblxyXG5cdFx0aWYgKCF0aGlzW2V2ZW50c0tleV0pIHtcclxuXHRcdFx0cmV0dXJuIHRoaXM7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKCF0eXBlcykge1xyXG5cdFx0XHRyZXR1cm4gdGhpcy5jbGVhckFsbEV2ZW50TGlzdGVuZXJzKCk7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKEwuVXRpbC5pbnZva2VFYWNoKHR5cGVzLCB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIsIHRoaXMsIGZuLCBjb250ZXh0KSkgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuXHRcdHZhciBldmVudHMgPSB0aGlzW2V2ZW50c0tleV0sXHJcblx0XHQgICAgY29udGV4dElkID0gY29udGV4dCAmJiBjb250ZXh0ICE9PSB0aGlzICYmIEwuc3RhbXAoY29udGV4dCksXHJcblx0XHQgICAgaSwgbGVuLCB0eXBlLCBsaXN0ZW5lcnMsIGosIGluZGV4S2V5LCBpbmRleExlbktleSwgdHlwZUluZGV4LCByZW1vdmVkO1xyXG5cclxuXHRcdHR5cGVzID0gTC5VdGlsLnNwbGl0V29yZHModHlwZXMpO1xyXG5cclxuXHRcdGZvciAoaSA9IDAsIGxlbiA9IHR5cGVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdHR5cGUgPSB0eXBlc1tpXTtcclxuXHRcdFx0aW5kZXhLZXkgPSB0eXBlICsgJ19pZHgnO1xyXG5cdFx0XHRpbmRleExlbktleSA9IGluZGV4S2V5ICsgJ19sZW4nO1xyXG5cclxuXHRcdFx0dHlwZUluZGV4ID0gZXZlbnRzW2luZGV4S2V5XTtcclxuXHJcblx0XHRcdGlmICghZm4pIHtcclxuXHRcdFx0XHQvLyBjbGVhciBhbGwgbGlzdGVuZXJzIGZvciBhIHR5cGUgaWYgZnVuY3Rpb24gaXNuJ3Qgc3BlY2lmaWVkXHJcblx0XHRcdFx0ZGVsZXRlIGV2ZW50c1t0eXBlXTtcclxuXHRcdFx0XHRkZWxldGUgZXZlbnRzW2luZGV4S2V5XTtcclxuXHRcdFx0XHRkZWxldGUgZXZlbnRzW2luZGV4TGVuS2V5XTtcclxuXHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0bGlzdGVuZXJzID0gY29udGV4dElkICYmIHR5cGVJbmRleCA/IHR5cGVJbmRleFtjb250ZXh0SWRdIDogZXZlbnRzW3R5cGVdO1xyXG5cclxuXHRcdFx0XHRpZiAobGlzdGVuZXJzKSB7XHJcblx0XHRcdFx0XHRmb3IgKGogPSBsaXN0ZW5lcnMubGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIHtcclxuXHRcdFx0XHRcdFx0aWYgKChsaXN0ZW5lcnNbal0uYWN0aW9uID09PSBmbikgJiYgKCFjb250ZXh0IHx8IChsaXN0ZW5lcnNbal0uY29udGV4dCA9PT0gY29udGV4dCkpKSB7XHJcblx0XHRcdFx0XHRcdFx0cmVtb3ZlZCA9IGxpc3RlbmVycy5zcGxpY2UoaiwgMSk7XHJcblx0XHRcdFx0XHRcdFx0Ly8gc2V0IHRoZSBvbGQgYWN0aW9uIHRvIGEgbm8tb3AsIGJlY2F1c2UgaXQgaXMgcG9zc2libGVcclxuXHRcdFx0XHRcdFx0XHQvLyB0aGF0IHRoZSBsaXN0ZW5lciBpcyBiZWluZyBpdGVyYXRlZCBvdmVyIGFzIHBhcnQgb2YgYSBkaXNwYXRjaFxyXG5cdFx0XHRcdFx0XHRcdHJlbW92ZWRbMF0uYWN0aW9uID0gTC5VdGlsLmZhbHNlRm47XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHRpZiAoY29udGV4dCAmJiB0eXBlSW5kZXggJiYgKGxpc3RlbmVycy5sZW5ndGggPT09IDApKSB7XHJcblx0XHRcdFx0XHRcdGRlbGV0ZSB0eXBlSW5kZXhbY29udGV4dElkXTtcclxuXHRcdFx0XHRcdFx0ZXZlbnRzW2luZGV4TGVuS2V5XS0tO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdGNsZWFyQWxsRXZlbnRMaXN0ZW5lcnM6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGRlbGV0ZSB0aGlzW2V2ZW50c0tleV07XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHRmaXJlRXZlbnQ6IGZ1bmN0aW9uICh0eXBlLCBkYXRhKSB7IC8vIChTdHJpbmdbLCBPYmplY3RdKVxyXG5cdFx0aWYgKCF0aGlzLmhhc0V2ZW50TGlzdGVuZXJzKHR5cGUpKSB7XHJcblx0XHRcdHJldHVybiB0aGlzO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBldmVudCA9IEwuVXRpbC5leHRlbmQoe30sIGRhdGEsIHsgdHlwZTogdHlwZSwgdGFyZ2V0OiB0aGlzIH0pO1xyXG5cclxuXHRcdHZhciBldmVudHMgPSB0aGlzW2V2ZW50c0tleV0sXHJcblx0XHQgICAgbGlzdGVuZXJzLCBpLCBsZW4sIHR5cGVJbmRleCwgY29udGV4dElkO1xyXG5cclxuXHRcdGlmIChldmVudHNbdHlwZV0pIHtcclxuXHRcdFx0Ly8gbWFrZSBzdXJlIGFkZGluZy9yZW1vdmluZyBsaXN0ZW5lcnMgaW5zaWRlIG90aGVyIGxpc3RlbmVycyB3b24ndCBjYXVzZSBpbmZpbml0ZSBsb29wXHJcblx0XHRcdGxpc3RlbmVycyA9IGV2ZW50c1t0eXBlXS5zbGljZSgpO1xyXG5cclxuXHRcdFx0Zm9yIChpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdFx0bGlzdGVuZXJzW2ldLmFjdGlvbi5jYWxsKGxpc3RlbmVyc1tpXS5jb250ZXh0LCBldmVudCk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHQvLyBmaXJlIGV2ZW50IGZvciB0aGUgY29udGV4dC1pbmRleGVkIGxpc3RlbmVycyBhcyB3ZWxsXHJcblx0XHR0eXBlSW5kZXggPSBldmVudHNbdHlwZSArICdfaWR4J107XHJcblxyXG5cdFx0Zm9yIChjb250ZXh0SWQgaW4gdHlwZUluZGV4KSB7XHJcblx0XHRcdGxpc3RlbmVycyA9IHR5cGVJbmRleFtjb250ZXh0SWRdLnNsaWNlKCk7XHJcblxyXG5cdFx0XHRpZiAobGlzdGVuZXJzKSB7XHJcblx0XHRcdFx0Zm9yIChpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdFx0XHRsaXN0ZW5lcnNbaV0uYWN0aW9uLmNhbGwobGlzdGVuZXJzW2ldLmNvbnRleHQsIGV2ZW50KTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHRhZGRPbmVUaW1lRXZlbnRMaXN0ZW5lcjogZnVuY3Rpb24gKHR5cGVzLCBmbiwgY29udGV4dCkge1xyXG5cclxuXHRcdGlmIChMLlV0aWwuaW52b2tlRWFjaCh0eXBlcywgdGhpcy5hZGRPbmVUaW1lRXZlbnRMaXN0ZW5lciwgdGhpcywgZm4sIGNvbnRleHQpKSB7IHJldHVybiB0aGlzOyB9XHJcblxyXG5cdFx0dmFyIGhhbmRsZXIgPSBMLmJpbmQoZnVuY3Rpb24gKCkge1xyXG5cdFx0XHR0aGlzXHJcblx0XHRcdCAgICAucmVtb3ZlRXZlbnRMaXN0ZW5lcih0eXBlcywgZm4sIGNvbnRleHQpXHJcblx0XHRcdCAgICAucmVtb3ZlRXZlbnRMaXN0ZW5lcih0eXBlcywgaGFuZGxlciwgY29udGV4dCk7XHJcblx0XHR9LCB0aGlzKTtcclxuXHJcblx0XHRyZXR1cm4gdGhpc1xyXG5cdFx0ICAgIC5hZGRFdmVudExpc3RlbmVyKHR5cGVzLCBmbiwgY29udGV4dClcclxuXHRcdCAgICAuYWRkRXZlbnRMaXN0ZW5lcih0eXBlcywgaGFuZGxlciwgY29udGV4dCk7XHJcblx0fVxyXG59O1xyXG5cclxuTC5NaXhpbi5FdmVudHMub24gPSBMLk1peGluLkV2ZW50cy5hZGRFdmVudExpc3RlbmVyO1xyXG5MLk1peGluLkV2ZW50cy5vZmYgPSBMLk1peGluLkV2ZW50cy5yZW1vdmVFdmVudExpc3RlbmVyO1xyXG5MLk1peGluLkV2ZW50cy5vbmNlID0gTC5NaXhpbi5FdmVudHMuYWRkT25lVGltZUV2ZW50TGlzdGVuZXI7XHJcbkwuTWl4aW4uRXZlbnRzLmZpcmUgPSBMLk1peGluLkV2ZW50cy5maXJlRXZlbnQ7XHJcblxuXG4vKlxyXG4gKiBMLkJyb3dzZXIgaGFuZGxlcyBkaWZmZXJlbnQgYnJvd3NlciBhbmQgZmVhdHVyZSBkZXRlY3Rpb25zIGZvciBpbnRlcm5hbCBMZWFmbGV0IHVzZS5cclxuICovXHJcblxyXG4oZnVuY3Rpb24gKCkge1xyXG5cclxuXHR2YXIgaWUgPSAnQWN0aXZlWE9iamVjdCcgaW4gd2luZG93LFxyXG5cdFx0aWVsdDkgPSBpZSAmJiAhZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcixcclxuXHJcblx0ICAgIC8vIHRlcnJpYmxlIGJyb3dzZXIgZGV0ZWN0aW9uIHRvIHdvcmsgYXJvdW5kIFNhZmFyaSAvIGlPUyAvIEFuZHJvaWQgYnJvd3NlciBidWdzXHJcblx0ICAgIHVhID0gbmF2aWdhdG9yLnVzZXJBZ2VudC50b0xvd2VyQ2FzZSgpLFxyXG5cdCAgICB3ZWJraXQgPSB1YS5pbmRleE9mKCd3ZWJraXQnKSAhPT0gLTEsXHJcblx0ICAgIGNocm9tZSA9IHVhLmluZGV4T2YoJ2Nocm9tZScpICE9PSAtMSxcclxuXHQgICAgcGhhbnRvbWpzID0gdWEuaW5kZXhPZigncGhhbnRvbScpICE9PSAtMSxcclxuXHQgICAgYW5kcm9pZCA9IHVhLmluZGV4T2YoJ2FuZHJvaWQnKSAhPT0gLTEsXHJcblx0ICAgIGFuZHJvaWQyMyA9IHVhLnNlYXJjaCgnYW5kcm9pZCBbMjNdJykgIT09IC0xLFxyXG5cdF |
View raw
(Sorry about that, but we can’t show files that are this big right now.)
View raw
(Sorry about that, but we can’t show files that are this big right now.)
View raw
(Sorry about that, but we can’t show files that are this big right now.)
View raw
(Sorry about that, but we can’t show files that are this big right now.)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment