ng-devui
Version:
DevUI components based on Angular
531 lines • 72.9 kB
JavaScript
/**
* 2020.03.23-Modified from https://github.com/Bernardo-Castilho/dragdroptouch, license: MIT,reason:Converting .js file to .ts file
*/
export class DragDropTouch {
static { this.THRESHOLD = 5; } // pixels to move before drag starts
static { this.OPACITY = 0.5; } // drag image opacity
static { this.DBLCLICK = 500; } // max ms between clicks in a double click
static { this.DRAG_OVER_TIME = 300; } // interval ms when drag over
static { this.CTX_MENU = 900; } // ms to hold before raising 'contextmenu' event
static { this.IS_PRESS_HOLD_MODE = true; } // decides of press & hold mode presence
static { this.PRESS_HOLD_AWAIT = 400; } // ms to wait before press & hold is detected
static { this.PRESS_HOLD_MARGIN = 25; } // pixels that finger might shiver while pressing
static { this.PRESS_HOLD_THRESHOLD = 0; } // pixels to move before drag starts
static { this.DRAG_HANDLE_ATTR = 'data-drag-handle-selector'; }
static { this.rmvAttrs = 'id,class,style,draggable'.split(','); }
static { this.kbdProps = 'altKey,ctrlKey,metaKey,shiftKey'.split(','); }
static { this.ptProps = 'pageX,pageY,clientX,clientY,screenX,screenY'.split(','); }
static { this.instance = null; }
constructor() {
this.lastClick = 0;
// ** event handlers
this.touchstart = (e) => {
if (this.shouldHandle(e)) {
// raise double-click and prevent zooming
if (Date.now() - this.lastClick < DragDropTouch.DBLCLICK) {
if (this.dispatchEvent(e, 'dblclick', e.target)) {
e.preventDefault();
this.reset();
return;
}
}
// clear all variables
this.reset();
// get nearest draggable element
const src = this.closestDraggable(e.target);
if (src) {
this.dragSource = src;
this.ptDown = this.getPoint(e);
this.lastTouch = e;
if (DragDropTouch.IS_PRESS_HOLD_MODE) {
this.pressHoldInterval = setTimeout(() => {
this.bindTouchmoveTouchend(e);
this.isDragEnabled = true;
this.touchmove(e);
}, DragDropTouch.PRESS_HOLD_AWAIT);
}
else {
e.preventDefault();
this.bindTouchmoveTouchend(e);
}
}
}
};
this.touchmoveOnDocument = (e) => {
if (this.shouldCancelPressHoldMove(e)) {
this.reset();
return;
}
};
this.touchmove = (e) => {
if (this.shouldCancelPressHoldMove(e)) {
this.reset();
return;
}
if (this.shouldHandleMove(e) || this.shouldHandlePressHoldMove(e)) {
const target = this.getTarget(e);
// start dragging
if (this.dragSource && !this.img && this.shouldStartDragging(e)) {
this.dispatchEvent(e, 'dragstart', this.dragSource);
this.createImage(e);
}
// continue dragging
if (this.img) {
this.clearDragoverInterval();
this.lastTouch = e;
e.preventDefault(); // prevent scrolling
if (target !== this.lastTarget) {
// according to drag drop implementation of the browser, dragenterB is supposed to fired before dragleaveA
this.dispatchEvent(e, 'dragenter', target);
this.dispatchEvent(this.lastTouch, 'dragleave', this.lastTarget);
this.lastTarget = target;
}
this.moveImage(e);
this.isDropZone = this.dispatchEvent(e, 'dragover', target);
// should continue dispatch dragover event when touch position stay still
this.setDragoverInterval(e);
}
}
};
this.touchendOnDocument = (e) => {
if (this.shouldHandle(e)) {
if (!this.img) {
this.dragSource = null;
this.lastClick = Date.now();
}
// finish dragging
this.destroyImage();
if (this.dragSource) {
this.reset();
}
}
};
this.touchend = (e) => {
if (this.shouldHandle(e)) {
// user clicked the element but didn't drag, so clear the source and simulate a click
if (!this.img) {
this.dragSource = null;
// browser will dispatch click event after trigger touchend, since touchstart didn't preventDefault
this.lastClick = Date.now();
}
// finish dragging
this.destroyImage();
if (this.dragSource) {
if (e.type.indexOf('cancel') < 0 && this.isDropZone) {
this.dispatchEvent(this.lastTouch, 'drop', this.lastTarget);
}
this.dispatchEvent(this.lastTouch, 'dragend', this.dragSource);
this.reset();
}
}
};
// enforce singleton pattern
if (DragDropTouch.instance) {
throw new Error('DragDropTouch instance already created.');
}
// detect passive event support
// https://github.com/Modernizr/Modernizr/issues/1894
let supportsPassive = false;
if (typeof document !== 'undefined') {
document.addEventListener('test', () => { }, {
get passive() {
supportsPassive = true;
return true;
},
});
// listen to touch events
if (DragDropTouch.isTouchDevice()) {
// 能响应触摸事件
const d = document;
const ts = this.touchstart;
const tmod = this.touchmoveOnDocument;
const teod = this.touchendOnDocument;
const opt = supportsPassive ? { passive: false, capture: false } : false;
const optPassive = supportsPassive ? { passive: true } : false;
d.addEventListener('touchstart', ts, opt);
d.addEventListener('touchmove', tmod, optPassive);
d.addEventListener('touchend', teod);
d.addEventListener('touchcancel', teod);
this.touchmoveListener = this.touchmove;
this.touchendListener = this.touchend;
this.listenerOpt = opt;
}
}
}
/**
* Gets a reference to the @see:DragDropTouch singleton.
*/
static getInstance() {
if (!DragDropTouch.instance) {
DragDropTouch.instance = new DragDropTouch();
}
return DragDropTouch.instance;
}
static isTouchDevice() {
if (typeof window === 'undefined' || typeof document === 'undefined') {
return false;
}
const d = document;
const w = window;
let bool;
if ('ontouchstart' in d || // normal mobile device
'ontouchstart' in w ||
navigator.maxTouchPoints > 0 ||
navigator.msMaxTouchPoints > 0 ||
(window.DocumentTouch && document instanceof window.DocumentTouch)) {
bool = true;
}
else {
const fakeBody = document.createElement('fakebody');
fakeBody.innerHTML += `
<style>
@media (touch-enabled),(-webkit-touch-enabled),(-moz-touch-enabled),(-o-touch-enabled){
#touch_test {
top: 42px;
position: absolute;
}
}
</style>`;
document.documentElement.appendChild(fakeBody);
const touchTestNode = document.createElement('div');
touchTestNode.id = 'touch_test';
fakeBody.appendChild(touchTestNode);
bool = touchTestNode.offsetTop === 42;
fakeBody.parentElement.removeChild(fakeBody);
}
return bool;
}
// ** event listener binding
bindTouchmoveTouchend(e) {
this.touchTarget = e.target;
e.target.addEventListener('touchmove', this.touchmoveListener, this.listenerOpt);
e.target.addEventListener('touchend', this.touchendListener);
e.target.addEventListener('touchcancel', this.touchendListener);
}
removeTouchmoveTouchend() {
if (this.touchTarget) {
this.touchTarget.removeEventListener('touchmove', this.touchmoveListener);
this.touchTarget.removeEventListener('touchend', this.touchendListener);
this.touchTarget.removeEventListener('touchcancel', this.touchendListener);
this.touchTarget = undefined;
}
}
// ** utilities
// ignore events that have been handled or that involve more than one touch
shouldHandle(e) {
return e && !e.defaultPrevented && e.touches && e.touches.length < 2;
}
// use regular condition outside of press & hold mode
shouldHandleMove(e) {
return !DragDropTouch.IS_PRESS_HOLD_MODE && this.shouldHandle(e);
}
// allow to handle moves that involve many touches for press & hold
shouldHandlePressHoldMove(e) {
return DragDropTouch.IS_PRESS_HOLD_MODE && this.isDragEnabled && e && e.touches && e.touches.length;
}
// reset data if user drags without pressing & holding
shouldCancelPressHoldMove(e) {
return DragDropTouch.IS_PRESS_HOLD_MODE && !this.isDragEnabled && this.getDelta(e) > DragDropTouch.PRESS_HOLD_MARGIN;
}
// start dragging when mouseover element matches drag handler selector and specified delta is detected
shouldStartDragging(e) {
const dragHandleSelector = this.getDragHandle();
// start dragging when mouseover element matches drag handler selector
if (dragHandleSelector && !this.matchSelector(e.target, dragHandleSelector)) {
return false;
}
// start dragging when specified delta is detected
const delta = this.getDelta(e);
return delta > DragDropTouch.THRESHOLD || (DragDropTouch.IS_PRESS_HOLD_MODE && delta >= DragDropTouch.PRESS_HOLD_THRESHOLD);
}
// find drag handler selector for dragstart only with partial element
getDragHandle() {
if (this.dragSource) {
return this.dragSource.getAttribute(DragDropTouch.DRAG_HANDLE_ATTR) || '';
}
return '';
}
// test if element matches selector
matchSelector(element, selector) {
if (selector) {
const proto = Element.prototype;
const func = proto.matches ||
proto.matchesSelector ||
proto.mozMatchesSelector ||
proto.msMatchesSelector ||
proto.oMatchesSelector ||
proto.webkitMatchesSelector ||
function (s) {
const matches = (this.document || this.ownerDocument).querySelectorAll(s);
let i = matches.length;
while (--i >= 0 && matches.item(i) !== this) {
// do nothing
}
return i > -1;
};
return func.call(element, selector);
}
return true;
}
// clear all members
reset() {
this.removeTouchmoveTouchend();
this.destroyImage();
this.dragSource = null;
this.lastTouch = null;
this.lastTarget = null;
this.ptDown = null;
this.isDragEnabled = false;
this.isDropZone = false;
this.dataTransfer = new DragDropTouch.DataTransfer();
clearInterval(this.pressHoldInterval);
this.clearDragoverInterval();
}
// get point for a touch event
getPoint(e, page) {
if (e && e.touches) {
e = e.touches[0];
}
return { x: page ? e.pageX : e.clientX, y: page ? e.pageY : e.clientY };
}
// get distance between the current touch event and the first one
getDelta(e) {
if (DragDropTouch.IS_PRESS_HOLD_MODE && !this.ptDown) {
return 0;
}
const p = this.getPoint(e);
return Math.abs(p.x - this.ptDown.x) + Math.abs(p.y - this.ptDown.y);
}
// get the element at a given touch event
getTarget(e) {
const pt = this.getPoint(e);
let el = document.elementFromPoint(pt.x, pt.y);
while (el && getComputedStyle(el).pointerEvents === 'none') {
el = el.parentElement;
}
return el;
}
// create drag image from source element
createImage(e) {
// just in case...
if (this.img) {
this.destroyImage();
}
// create drag image from custom element or drag source
const src = this.imgCustom || this.dragSource;
this.img = src.cloneNode(true);
this.copyStyle(src, this.img);
this.img.style.top = this.img.style.left = '-9999px';
// if creating from drag source, apply offset and opacity
if (!this.imgCustom) {
const rc = src.getBoundingClientRect();
const pt = this.getPoint(e);
this.imgOffset = { x: pt.x - rc.left, y: pt.y - rc.top };
this.img.style.opacity = DragDropTouch.OPACITY.toString();
}
// add image to document
this.moveImage(e);
document.body.appendChild(this.img);
}
// dispose of drag image element
destroyImage() {
if (this.img && this.img.parentElement) {
this.img.parentElement.removeChild(this.img);
}
this.img = null;
this.imgCustom = null;
}
// move the drag image element
moveImage(e) {
requestAnimationFrame(() => {
if (this.img) {
const pt = this.getPoint(e, true);
const s = this.img.style;
s.position = 'absolute';
s.pointerEvents = 'none';
s.zIndex = '999999';
s.left = Math.round(pt.x - this.imgOffset.x) + 'px';
s.top = Math.round(pt.y - this.imgOffset.y) + 'px';
}
});
}
// copy properties from an object to another
copyProps(dst, src, props) {
for (let i = 0; i < props.length; i++) {
const p = props[i];
dst[p] = src[p];
}
}
// copy styles/attributes from drag source to drag image element
copyStyle(src, dst) {
// remove potentially troublesome attributes
DragDropTouch.rmvAttrs.forEach((att) => dst.removeAttribute(att));
// copy canvas content
if (src instanceof HTMLCanvasElement) {
const canSrc = src;
const canDst = dst;
canDst.width = canSrc.width;
canDst.height = canSrc.height;
canDst.getContext('2d').drawImage(canSrc, 0, 0);
}
// copy canvas content for nested canvas element
const srcCanvases = src.querySelectorAll('canvas');
if (srcCanvases.length > 0) {
const dstCanvases = dst.querySelectorAll('canvas');
for (let i = 0; i < dstCanvases.length; i++) {
const cSrc = srcCanvases[i];
const cDst = dstCanvases[i];
cDst.getContext('2d').drawImage(cSrc, 0, 0);
}
}
// copy style (without transitions)
const cs = getComputedStyle(src);
for (let i = 0; i < cs.length; i++) {
const key = cs[i];
if (key.indexOf('transition') < 0) {
dst.style[key] = cs[key];
}
}
dst.style.pointerEvents = 'none';
// and repeat for all children
for (let i = 0; i < src.children.length; i++) {
this.copyStyle(src.children[i], dst.children[i]);
}
}
// synthesize and dispatch an event
// returns true if the event has been handled (e.preventDefault == true)
dispatchEvent(e, type, target) {
if (e && target) {
const evt = document.createEvent('Event');
const t = e.touches ? e.touches[0] : e;
evt.initEvent(type, true, true);
const obj = {
button: 0,
which: 0,
buttons: 1,
dataTransfer: this.dataTransfer,
};
this.copyProps(evt, e, DragDropTouch.kbdProps);
this.copyProps(evt, t, DragDropTouch.ptProps);
this.copyProps(evt, { fromTouch: true }, ['fromTouch']); // mark as from touch event
this.copyProps(evt, obj, Object.keys(obj));
target.dispatchEvent(evt);
return evt.defaultPrevented;
}
return false;
}
// gets an element's closest draggable ancestor
closestDraggable(e) {
for (; e; e = e.parentElement) {
if (e.hasAttribute('draggable') && e.draggable) {
return e;
}
}
return null;
}
// repeat dispatch dragover event when touch point stay still
setDragoverInterval(e) {
this.dragoverTimer = setInterval(() => {
const target = this.getTarget(e);
if (target !== this.lastTarget) {
this.dispatchEvent(e, 'dragenter', target);
this.dispatchEvent(e, 'dragleave', this.lastTarget);
this.lastTarget = target;
}
this.isDropZone = this.dispatchEvent(e, 'dragover', target);
}, DragDropTouch.DRAG_OVER_TIME);
}
clearDragoverInterval() {
if (this.dragoverTimer) {
clearInterval(this.dragoverTimer);
this.dragoverTimer = undefined;
}
}
}
/* eslint-disable-next-line @typescript-eslint/no-namespace */
(function (DragDropTouch) {
/**
* Object used to hold the data that is being dragged during drag and drop operations.
*
* It may hold one or more data items of different types. For more information about
* drag and drop operations and data transfer objects, see
* <a href="https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer">HTML Drag and Drop API</a>.
*
* This object is created automatically by the @see:DragDropTouch singleton and is
* accessible through the @see:dataTransfer property of all drag events.
*/
class DataTransfer {
get dropEffect() {
return this._dropEffect;
}
set dropEffect(value) {
this._dropEffect = value;
}
get effectAllowed() {
return this._effectAllowed;
}
set effectAllowed(value) {
this._effectAllowed = value;
}
get types() {
return Object.keys(this._data);
}
constructor() {
this._dropEffect = 'move';
this._effectAllowed = 'all';
this._data = {};
}
/**
* Removes the data associated with a given type.
*
* The type argument is optional. If the type is empty or not specified, the data
* associated with all types is removed. If data for the specified type does not exist,
* or the data transfer contains no data, this method will have no effect.
*
* @param type Type of data to remove.
*/
clearData(type) {
if (type !== null) {
delete this._data[type];
}
else {
this._data = null;
}
}
/**
* Retrieves the data for a given type, or an empty string if data for that type does
* not exist or the data transfer contains no data.
*
* @param type Type of data to retrieve.
*/
getData(type) {
return this._data[type] || '';
}
/**
* Set the data for a given type.
*
* For a list of recommended drag types, please see
* https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Recommended_Drag_Types.
*
* @param type Type of data to add.
* @param value Data to add.
*/
setData(type, value) {
this._data[type] = value;
}
/**
* Set the image to be used for dragging if a custom one is desired.
*
* @param img An image element to use as the drag feedback image.
* @param offsetX The horizontal offset within the image.
* @param offsetY The vertical offset within the image.
*/
setDragImage(img, offsetX, offsetY) {
const ddt = DragDropTouch.getInstance();
ddt.imgCustom = img;
ddt.imgOffset = { x: offsetX, y: offsetY };
}
}
DragDropTouch.DataTransfer = DataTransfer;
})(DragDropTouch || (DragDropTouch = {}));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJhZ2Ryb3AtdG91Y2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9kZXZ1aS9kcmFnZHJvcC90b3VjaC1zdXBwb3J0L2RyYWdkcm9wLXRvdWNoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGFBQWE7YUFDUixjQUFTLEdBQUcsQ0FBQyxBQUFKLENBQUssR0FBQyxvQ0FBb0M7YUFDbkQsWUFBTyxHQUFHLEdBQUcsQUFBTixDQUFPLEdBQUMscUJBQXFCO2FBQ3BDLGFBQVEsR0FBRyxHQUFHLEFBQU4sQ0FBTyxHQUFDLDBDQUEwQzthQUMxRCxtQkFBYyxHQUFHLEdBQUcsQUFBTixDQUFPLEdBQUMsNkJBQTZCO2FBQ25ELGFBQVEsR0FBRyxHQUFHLEFBQU4sQ0FBTyxHQUFDLGdEQUFnRDthQUNoRSx1QkFBa0IsR0FBRyxJQUFJLEFBQVAsQ0FBUSxHQUFDLHdDQUF3QzthQUNuRSxxQkFBZ0IsR0FBRyxHQUFHLEFBQU4sQ0FBTyxHQUFDLDZDQUE2QzthQUNyRSxzQkFBaUIsR0FBRyxFQUFFLEFBQUwsQ0FBTSxHQUFDLGlEQUFpRDthQUN6RSx5QkFBb0IsR0FBRyxDQUFDLEFBQUosQ0FBSyxHQUFDLG9DQUFvQzthQUM5RCxxQkFBZ0IsR0FBRywyQkFBMkIsQUFBOUIsQ0FBK0I7YUFDL0MsYUFBUSxHQUFHLDBCQUEwQixDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQUFBeEMsQ0FBeUM7YUFDakQsYUFBUSxHQUFHLGlDQUFpQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQUFBL0MsQ0FBZ0Q7YUFDeEQsWUFBTyxHQUFHLDZDQUE2QyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQUFBM0QsQ0FBNEQ7YUFFcEUsYUFBUSxHQUFrQixJQUFJLEFBQXRCLENBQXVCO0lBeUI5QztRQXRCQSxjQUFTLEdBQUcsQ0FBQyxDQUFDO1FBbUhkLG9CQUFvQjtRQUNwQixlQUFVLEdBQUcsQ0FBQyxDQUFhLEVBQUUsRUFBRTtZQUM3QixJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDekIseUNBQXlDO2dCQUN6QyxJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsU0FBUyxHQUFHLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztvQkFDekQsSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7d0JBQ2hELENBQUMsQ0FBQyxjQUFjLEVBQUUsQ0FBQzt3QkFDbkIsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO3dCQUNiLE9BQU87b0JBQ1QsQ0FBQztnQkFDSCxDQUFDO2dCQUNELHNCQUFzQjtnQkFDdEIsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNiLGdDQUFnQztnQkFDaEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDNUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztvQkFDUixJQUFJLENBQUMsVUFBVSxHQUFHLEdBQUcsQ0FBQztvQkFDdEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUMvQixJQUFJLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQztvQkFDbkIsSUFBSSxhQUFhLENBQUMsa0JBQWtCLEVBQUUsQ0FBQzt3QkFDckMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLFVBQVUsQ0FBQyxHQUFHLEVBQUU7NEJBQ3ZDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsQ0FBQzs0QkFDOUIsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUM7NEJBQzFCLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7d0JBQ3BCLENBQUMsRUFBRSxhQUFhLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztvQkFDckMsQ0FBQzt5QkFBTSxDQUFDO3dCQUNOLENBQUMsQ0FBQyxjQUFjLEVBQUUsQ0FBQzt3QkFDbkIsSUFBSSxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUNoQyxDQUFDO2dCQUNILENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQyxDQUFDO1FBQ0Ysd0JBQW1CLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUMxQixJQUFJLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUN0QyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ2IsT0FBTztZQUNULENBQUM7UUFDSCxDQUFDLENBQUM7UUFDRixjQUFTLEdBQUcsQ0FBQyxDQUFhLEVBQUUsRUFBRTtZQUM1QixJQUFJLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUN0QyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ2IsT0FBTztZQUNULENBQUM7WUFDRCxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMseUJBQXlCLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDbEUsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDakMsaUJBQWlCO2dCQUNqQixJQUFJLElBQUksQ0FBQyxVQUFVLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO29CQUNoRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsRUFBRSxXQUFXLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO29CQUNwRCxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUN0QixDQUFDO2dCQUNELG9CQUFvQjtnQkFDcEIsSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7b0JBQ2IsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7b0JBQzdCLElBQUksQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDO29CQUNuQixDQUFDLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxvQkFBb0I7b0JBQ3hDLElBQUksTUFBTSxLQUFLLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQzt3QkFDL0IsMEdBQTBHO3dCQUMxRyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsRUFBRSxXQUFXLEVBQUUsTUFBTSxDQUFDLENBQUM7d0JBQzNDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxXQUFXLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO3dCQUNqRSxJQUFJLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQztvQkFDM0IsQ0FBQztvQkFDRCxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUNsQixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQztvQkFDNUQseUVBQXlFO29CQUN6RSxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzlCLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQyxDQUFDO1FBQ0YsdUJBQWtCLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUN6QixJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDekIsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztvQkFDZCxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztvQkFDdkIsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7Z0JBQzlCLENBQUM7Z0JBQ0Qsa0JBQWtCO2dCQUNsQixJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ3BCLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO29CQUNwQixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ2YsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDLENBQUM7UUFDRixhQUFRLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUNmLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUN6QixxRkFBcUY7Z0JBQ3JGLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7b0JBQ2QsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7b0JBQ3ZCLG1HQUFtRztvQkFDbkcsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7Z0JBQzlCLENBQUM7Z0JBQ0Qsa0JBQWtCO2dCQUNsQixJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ3BCLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO29CQUNwQixJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7d0JBQ3BELElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO29CQUM5RCxDQUFDO29CQUNELElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO29CQUMvRCxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ2YsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDLENBQUM7UUEvTEEsNEJBQTRCO1FBQzVCLElBQUksYUFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQzNCLE1BQU0sSUFBSSxLQUFLLENBQUMseUNBQXlDLENBQUMsQ0FBQztRQUM3RCxDQUFDO1FBQ0QsK0JBQStCO1FBQy9CLHFEQUFxRDtRQUNyRCxJQUFJLGVBQWUsR0FBRyxLQUFLLENBQUM7UUFDNUIsSUFBSSxPQUFPLFFBQVEsS0FBSyxXQUFXLEVBQUUsQ0FBQztZQUNwQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxHQUFFLENBQUMsRUFBRTtnQkFDMUMsSUFBSSxPQUFPO29CQUNULGVBQWUsR0FBRyxJQUFJLENBQUM7b0JBQ3ZCLE9BQU8sSUFBSSxDQUFDO2dCQUNkLENBQUM7YUFDRixDQUFDLENBQUM7WUFDSCx5QkFBeUI7WUFDekIsSUFBSSxhQUFhLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQztnQkFDbEMsVUFBVTtnQkFDVixNQUFNLENBQUMsR0FBRyxRQUFRLENBQUM7Z0JBQ25CLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7Z0JBQzNCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQztnQkFDdEMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDO2dCQUNyQyxNQUFNLEdBQUcsR0FBRyxlQUFlLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztnQkFDekUsTUFBTSxVQUFVLEdBQUcsZUFBZSxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO2dCQUMvRCxDQUFDLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUMsQ0FBQztnQkFDMUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLFdBQVcsRUFBRSxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7Z0JBQ2xELENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQ3JDLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQ3hDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO2dCQUN4QyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztnQkFDdEMsSUFBSSxDQUFDLFdBQVcsR0FBRyxHQUFHLENBQUM7WUFDekIsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBQ0Q7O09BRUc7SUFDSCxNQUFNLENBQUMsV0FBVztRQUNoQixJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQzVCLGFBQWEsQ0FBQyxRQUFRLEdBQUcsSUFBSSxhQUFhLEVBQUUsQ0FBQztRQUMvQyxDQUFDO1FBQ0QsT0FBTyxhQUFhLENBQUMsUUFBUSxDQUFDO0lBQ2hDLENBQUM7SUFDRCxNQUFNLENBQUMsYUFBYTtRQUNsQixJQUFJLE9BQU8sTUFBTSxLQUFLLFdBQVcsSUFBSSxPQUFPLFFBQVEsS0FBSyxXQUFXLEVBQUUsQ0FBQztZQUNyRSxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7UUFDRCxNQUFNLENBQUMsR0FBYSxRQUFRLENBQUM7UUFDN0IsTUFBTSxDQUFDLEdBQVcsTUFBTSxDQUFDO1FBQ3pCLElBQUksSUFBSSxDQUFDO1FBQ1QsSUFDRSxjQUFjLElBQUksQ0FBQyxJQUFJLHVCQUF1QjtZQUM5QyxjQUFjLElBQUksQ0FBQztZQUNuQixTQUFTLENBQUMsY0FBYyxHQUFHLENBQUM7WUFDM0IsU0FBaUIsQ0FBQyxnQkFBZ0IsR0FBRyxDQUFDO1lBQ3ZDLENBQUUsTUFBYyxDQUFDLGFBQWEsSUFBSSxRQUFRLFlBQWEsTUFBYyxDQUFDLGFBQWEsQ0FBQyxFQUNwRixDQUFDO1lBQ0QsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNkLENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNwRCxRQUFRLENBQUMsU0FBUyxJQUFJOzs7Ozs7OztlQVFiLENBQUM7WUFDVixRQUFRLENBQUMsZUFBZSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUMvQyxNQUFNLGFBQWEsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3BELGFBQWEsQ0FBQyxFQUFFLEdBQUcsWUFBWSxDQUFDO1lBQ2hDLFFBQVEsQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDcEMsSUFBSSxHQUFHLGFBQWEsQ0FBQyxTQUFTLEtBQUssRUFBRSxDQUFDO1lBQ3RDLFFBQVEsQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQy9DLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFDRCw0QkFBNEI7SUFDNUIscUJBQXFCLENBQUMsQ0FBYTtRQUNqQyxJQUFJLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUM7UUFDNUIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNqRixDQUFDLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUM3RCxDQUFDLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUNsRSxDQUFDO0lBQ0QsdUJBQXVCO1FBQ3JCLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3JCLElBQUksQ0FBQyxXQUFXLENBQUMsbUJBQW1CLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1lBQzFFLElBQUksQ0FBQyxXQUFXLENBQUMsbUJBQW1CLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1lBQ3hFLElBQUksQ0FBQyxXQUFXLENBQUMsbUJBQW1CLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1lBQzNFLElBQUksQ0FBQyxXQUFXLEdBQUcsU0FBUyxDQUFDO1FBQy9CLENBQUM7SUFDSCxDQUFDO0lBcUdELGVBQWU7SUFDZiwyRUFBMkU7SUFDM0UsWUFBWSxDQUFDLENBQUM7UUFDWixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsSUFBSSxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUN2RSxDQUFDO0lBQ0QscURBQXFEO0lBQ3JELGdCQUFnQixDQUFDLENBQUM7UUFDaEIsT0FBTyxDQUFDLGFBQWEsQ0FBQyxrQkFBa0IsSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ25FLENBQUM7SUFDRCxtRUFBbUU7SUFDbkUseUJBQXlCLENBQUMsQ0FBQztRQUN6QixPQUFPLGFBQWEsQ0FBQyxrQkFBa0IsSUFBSSxJQUFJLENBQUMsYUFBYSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDO0lBQ3RHLENBQUM7SUFDRCxzREFBc0Q7SUFDdEQseUJBQXlCLENBQUMsQ0FBQztRQUN6QixPQUFPLGFBQWEsQ0FBQyxrQkFBa0IsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsR0FBRyxhQUFhLENBQUMsaUJBQWlCLENBQUM7SUFDdkgsQ0FBQztJQUNELHNHQUFzRztJQUN0RyxtQkFBbUIsQ0FBQyxDQUFDO1FBQ25CLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ2hELHNFQUFzRTtRQUN0RSxJQUFJLGtCQUFrQixJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLGtCQUFrQixDQUFDLEVBQUUsQ0FBQztZQUM1RSxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7UUFDRCxrREFBa0Q7UUFDbEQsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMvQixPQUFPLEtBQUssR0FBRyxhQUFhLENBQUMsU0FBUyxJQUFJLENBQUMsYUFBYSxDQUFDLGtCQUFrQixJQUFJLEtBQUssSUFBSSxhQUFhLENBQUMsb0JBQW9CLENBQUMsQ0FBQztJQUM5SCxDQUFDO0lBQ0QscUVBQXFFO0lBQ3JFLGFBQWE7UUFDWCxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNwQixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUM1RSxDQUFDO1FBQ0QsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBQ0QsbUNBQW1DO0lBQ25DLGFBQWEsQ0FBQyxPQUFPLEVBQUUsUUFBUTtRQUM3QixJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQ2IsTUFBTSxLQUFLLEdBQVEsT0FBTyxDQUFDLFNBQVMsQ0FBQztZQUNyQyxNQUFNLElBQUksR0FDUixLQUFLLENBQUMsT0FBTztnQkFDYixLQUFLLENBQUMsZUFBZTtnQkFDckIsS0FBSyxDQUFDLGtCQUFrQjtnQkFDeEIsS0FBSyxDQUFDLGlCQUFpQjtnQkFDdkIsS0FBSyxDQUFDLGdCQUFnQjtnQkFDdEIsS0FBSyxDQUFDLHFCQUFxQjtnQkFDM0IsVUFBVSxDQUFDO29CQUNULE1BQU0sT0FBTyxHQUFHLENBQUMsSUFBSSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQzFFLElBQUksQ0FBQyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUM7b0JBQ3ZCLE9BQU8sRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7d0JBQzVDLGFBQWE7b0JBQ2YsQ0FBQztvQkFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFDaEIsQ0FBQyxDQUFDO1lBQ0osT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQztRQUN0QyxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBQ0Qsb0JBQW9CO0lBQ3BCLEtBQUs7UUFDSCxJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztRQUMvQixJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDcEIsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7UUFDdkIsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7UUFDdEIsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7UUFDdkIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7UUFDbkIsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUM7UUFDM0IsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7UUFDeEIsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLGFBQWEsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNyRCxhQUFhLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDdEMsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7SUFDL0IsQ0FBQztJQUNELDhCQUE4QjtJQUM5QixRQUFRLENBQUMsQ0FBQyxFQUFFLElBQUs7UUFDZixJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDbkIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkIsQ0FBQztRQUNELE9BQU8sRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUMxRSxDQUFDO0lBQ0QsaUVBQWlFO0lBQ2pFLFFBQVEsQ0FBQyxDQUFDO1FBQ1IsSUFBSSxhQUFhLENBQUMsa0JBQWtCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDckQsT0FBTyxDQUFDLENBQUM7UUFDWCxDQUFDO1FBQ0QsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzQixPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZFLENBQUM7SUFDRCx5Q0FBeUM7SUFDekMsU0FBUyxDQUFDLENBQWE7UUFDckIsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM1QixJQUFJLEVBQUUsR0FBRyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDL0MsT0FBTyxFQUFFLElBQUksZ0JBQWdCLENBQUMsRUFBRSxDQUFDLENBQUMsYUFBYSxLQUFLLE1BQU0sRUFBRSxDQUFDO1lBQzNELEVBQUUsR0FBRyxFQUFFLENBQUMsYUFBYSxDQUFDO1FBQ3hCLENBQUM7UUFDRCxPQUFvQixFQUFFLENBQUM7SUFDekIsQ0FBQztJQUNELHdDQUF3QztJQUN4QyxXQUFXLENBQUMsQ0FBQztRQUNYLGtCQUFrQjtRQUNsQixJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNiLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUN0QixDQUFDO1FBQ0QsdURBQXVEO1FBQ3ZELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQztRQUM5QyxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDL0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzlCLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLEdBQUcsU0FBUyxDQUFDO1FBQ3JELHlEQUF5RDtRQUN6RCxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3BCLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQ3ZDLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDNUIsSUFBSSxDQUFDLFNBQVMsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ3pELElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxhQUFhLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQzVELENBQUM7UUFDRCx3QkFBd0I7UUFDeEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNsQixRQUFRLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUNELGdDQUFnQztJQUNoQyxZQUFZO1FBQ1YsSUFBSSxJQUFJLENBQUMsR0FBRyxJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDdkMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUMvQyxDQUFDO1FBQ0QsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUM7UUFDaEIsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7SUFDeEIsQ0FBQztJQUNELDhCQUE4QjtJQUM5QixTQUFTLENBQUMsQ0FBQztRQUNULHFCQUFxQixDQUFDLEdBQUcsRUFBRTtZQUN6QixJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFDYixNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztnQkFDbEMsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUM7Z0JBQ3pCLENBQUMsQ0FBQyxRQUFRLEdBQUcsVUFBVSxDQUFDO2dCQUN4QixDQUFDLENBQUMsYUFBYSxHQUFHLE1BQU0sQ0FBQztnQkFDekIsQ0FBQyxDQUFDLE1BQU0sR0FBRyxRQUFRLENBQUM7Z0JBQ3BCLENBQUMsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDO2dCQUNwRCxDQUFDLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQztZQUNyRCxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBQ0QsNENBQTRDO0lBQzVDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEtBQUs7UUFDdkIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUN0QyxNQUFNLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDbkIsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNsQixDQUFDO0lBQ0gsQ0FBQztJQUNELGdFQUFnRTtJQUNoRSxTQUFTLENBQUMsR0FBRyxFQUFFLEdBQUc7UUFDaEIsNENBQTRDO1FBQzVDLGFBQWEsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDbEUsc0JBQXNCO1FBQ3RCLElBQUksR0FBRyxZQUFZLGlCQUFpQixFQUFFLENBQUM7WUFDckMsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDO1lBQ25CLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQztZQUNuQixNQUFNLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUM7WUFDNUIsTUFBTSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO1lBQzlCLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDbEQsQ0FBQztRQUNELGdEQUFnRDtRQUNoRCxNQUFNLFdBQVcsR0FBRyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDbkQsSUFBSSxXQUFXLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzNCLE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUNuRCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsV0FBVyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUM1QyxNQUFNLElBQUksR0FBRyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzVCLE1BQU0sSUFBSSxHQUFHLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDNUIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUM5QyxDQUFDO1FBQ0gsQ0FBQztRQUNELG1DQUFtQztRQUNuQyxNQUFNLEVBQUUsR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNqQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ25DLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNsQixJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ2xDLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQzNCLENBQUM7UUFDSCxDQUFDO1FBQ0QsR0FBRyxDQUFDLEtBQUssQ0FBQyxhQUFhLEdBQUcsTUFBTSxDQUFDO1FBQ2pDLDhCQUE4QjtRQUM5QixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUM3QyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ25ELENBQUM7SUFDSCxDQUFDO0lBQ0QsbUNBQW1DO0lBQ25DLHdFQUF3RTtJQUN4RSxhQUFhLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNO1FBQzNCLElBQUksQ0FBQyxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ2hCLE1BQU0sR0FBRyxHQUFHLFFBQVEsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDMUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3ZDLEdBQUcsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNoQyxNQUFNLEdBQUcsR0FBRztnQkFDVixNQUFNLEVBQUUsQ0FBQztnQkFDVCxLQUFLLEVBQUUsQ0FBQztnQkFDUixPQUFPLEVBQUUsQ0FBQztnQkFDVixZQUFZLEVBQUUsSUFBSSxDQUFDLFlBQVk7YUFDaEMsQ0FBQztZQUNGLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDL0MsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUM5QyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQywyQkFBMkI7WUFDcEYsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUUzQyxNQUFNLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQzFCLE9BQU8sR0FBRyxDQUFDLGdCQUFnQixDQUFDO1FBQzlCLENBQUM7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFDRCwrQ0FBK0M7SUFDL0MsZ0JBQWdCLENBQUMsQ0FBQztRQUNoQixPQUFPLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzlCLElBQUksQ0FBQyxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQy9DLE9BQU8sQ0FBQyxDQUFDO1lBQ1gsQ0FBQztRQUNILENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFDRCw2REFBNkQ7SUFDN0QsbUJBQW1CLENBQUMsQ0FBQztRQUNuQixJQUFJLENBQUMsYUFBYSxHQUFHLFdBQVcsQ0FBQyxHQUFHLEVBQUU7WUFDcEMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNqQyxJQUFJLE1BQU0sS0FBSyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7Z0JBQy9CLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxNQUFNLENBQUMsQ0FBQztnQkFDM0MsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFDcEQsSUFBSSxDQUFDLFVBQVUsR0FBRyxNQUFNLENBQUM7WUFDM0IsQ0FBQztZQUNELElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQzlELENBQUMsRUFBRSxhQUFhLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUNELHFCQUFxQjtRQUNuQixJQUFJLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUN2QixhQUFhLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQ2xDLElBQUksQ0FBQyxhQUFhLEdBQUcsU0FBUyxDQUFDO1FBQ2pDLENBQUM7SUFDSCxDQUFDOztBQUVILDhEQUE4RDtBQUM5RCxXQUFpQixhQUFhO0lBQzVCOzs7Ozs7Ozs7T0FTRztJQUNILE1BQWEsWUFBWTtRQVN2QixJQUFJLFVBQVU7WUFDWixPQUFPLElBQUksQ0FBQyxXQUFXLENBQUM7UUFDMUIsQ0FBQztRQUNELElBQUksVUFBVSxDQUFDLEtBQUs7WUFDbEIsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUM7UUFDM0IsQ0FBQztRQU9ELElBQUksYUFBYTtZQUNmLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQztRQUM3QixDQUFDO1FBQ0QsSUFBSSxhQUFhLENBQUMsS0FBSztZQUNyQixJQUFJLENBQUMsY0FBYyxHQUFHLEtBQUssQ0FBQztRQUM5QixDQUFDO1FBS0QsSUFBSSxLQUFLO1lBQ1AsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNqQyxDQUFDO1FBRUQ7WUFDRSxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sQ0FBQztZQUMxQixJQUFJLENBQUMsY0FBYyxHQUFHLEtBQUssQ0FBQztZQUM1QixJQUFJLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztRQUNsQixDQUFDO1FBQ0Q7Ozs7Ozs7O1dBUUc7UUFDSCxTQUFTLENBQUMsSUFBSTtZQUNaLElBQUksSUFBSSxLQUFLLElBQUksRUFBRSxDQUFDO2dCQUNsQixPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDMUIsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1lBQ3BCLENBQUM7UUFDSCxDQUFDO1FBQ0Q7Ozs7O1dBS0c7UUFDSCxPQUFPLENBQUMsSUFBSTtZQUNWLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDaEMsQ0FBQztRQUVEOzs7Ozs7OztXQVFHO1FBQ0gsT0FBTyxDQUFDLElBQUksRUFBRSxLQUFLO1lBQ2pCLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDO1FBQzNCLENBQUM7UUFDRDs7Ozs7O1dBTUc7UUFDSCxZQUFZLENBQUMsR0FBRyxFQUFFLE9BQU8sRUFBRSxPQUFPO1lBQ2hDLE1BQU0sR0FBRyxHQUFHLGFBQWEsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN4QyxHQUFHLENBQUMsU0FBUyxHQUFHLEdBQUcsQ0FBQztZQUNwQixHQUFHLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUM7UUFDN0MsQ0FBQztLQUNGO0lBMUZZLDBCQUFZLGVBMEZ4QixDQUFBO0FBQ0gsQ0FBQyxFQXRHZ0IsYUFBYSxLQUFiLGFBQWEsUUFzRzdCIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXHJcbiAqIDIwMjAuMDMuMjMtTW9kaWZpZWQgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vQmVybmFyZG8tQ2FzdGlsaG8vZHJhZ2Ryb3B0b3VjaCwgbGljZW5zZTogTUlU77yMcmVhc29uOkNvbnZlcnRpbmcgLmpzIGZpbGUgdG8gLnRzIGZpbGVcclxuICovXHJcbmV4cG9ydCBjbGFzcyBEcmFnRHJvcFRvdWNoIHtcclxuICBzdGF0aWMgcmVhZG9ubHkgVEhSRVNIT0xEID0gNTsgLy8gcGl4ZWxzIHRvIG1vdmUgYmVmb3JlIGRyYWcgc3RhcnRzXHJcbiAgc3RhdGljIHJlYWRvbmx5IE9QQUNJVFkgPSAwLjU7IC8vIGRyYWcgaW1hZ2Ugb3BhY2l0eVxyXG4gIHN0YXRpYyByZWFkb25seSBEQkxDTElDSyA9IDUwMDsgLy8gbWF4IG1zIGJldHdlZW4gY2xpY2tzIGluIGEgZG91YmxlIGNsaWNrXHJcbiAgc3RhdGljIHJlYWRvbmx5IERSQUdfT1ZFUl9USU1FID0gMzAwOyAvLyBpbnRlcnZhbCBtcyB3aGVuIGRyYWcgb3ZlclxyXG4gIHN0YXRpYyByZWFkb25seSBDVFhfTUVOVSA9IDkwMDsgLy8gbXMgdG8gaG9sZCBiZWZvcmUgcmFpc2luZyAnY29udGV4dG1lbnUnIGV2ZW50XHJcbiAgc3RhdGljIHJlYWRvbmx5IElTX1BSRVNTX0hPTERfTU9ERSA9IHRydWU7IC8vIGRlY2lkZXMgb2YgcHJlc3MgJiBob2xkIG1vZGUgcHJlc2VuY2VcclxuICBzdGF0aWMgcmVhZG9ubHkgUFJFU1NfSE9MRF9BV0FJVCA9IDQwMDsgLy8gbXMgdG8gd2FpdCBiZWZvcmUgcHJlc3MgJiBob2xkIGlzIGRldGVjdGVkXHJcbiAgc3RhdGljIHJlYWRvbmx5IFBSRVNTX0hPTERfTUFSR0lOID0gMjU7IC8vIHBpeGVscyB0aGF0IGZpbmdlciBtaWdodCBzaGl2ZXIgd2hpbGUgcHJlc3NpbmdcclxuICBzdGF0aWMgcmVhZG9ubHkgUFJFU1NfSE9MRF9USFJFU0hPTEQgPSAwOyAvLyBwaXhlbHMgdG8gbW92ZSBiZWZvcmUgZHJhZyBzdGFydHNcclxuICBzdGF0aWMgcmVhZG9ubHkgRFJBR19IQU5ETEVfQVRUUiA9ICdkYXRhLWRyYWctaGFuZGxlLXNlbGVjdG9yJztcclxuICBzdGF0aWMgcmVhZG9ubHkgcm12QXR0cnMgPSAnaWQsY2xhc3Msc3R5bGUsZHJhZ2dhYmxlJy5zcGxpdCgnLCcpO1xyXG4gIHN0YXRpYyByZWFkb25seSBrYmRQcm9wcyA9ICdhbHRLZXksY3RybEtleSxtZXRhS2V5LHNoaWZ0S2V5Jy5zcGxpdCgnLCcpO1xyXG4gIHN0YXRpYyByZWFkb25seSBwdFByb3BzID0gJ3BhZ2VYLHBhZ2VZLGNsaWVudFgsY2xpZW50WSxzY3JlZW5YLHNjcmVlblknLnNwbGl0KCcsJyk7XHJcblxyXG4gIHByaXZhdGUgc3RhdGljIGluc3RhbmNlOiBEcmFnRHJvcFRvdWNoID0gbnVsbDtcclxuXHJcbiAgZGF0YVRyYW5zZmVyOiBEYXRhVHJhbnNmZXI7XHJcbiAgbGFzdENsaWNrID0gMDtcclxuICBsYXN0VG91Y2g6IFRvdWNoRXZlbnQ7XHJcbiAgLy8gdG91Y2hlZCBlbGVtZW50XHJcbiAgbGFzdFRhcmdldDogSFRNTEVsZW1lbnQ7XHJcbiAgLy8gdG91Y2hlZCBkcmFnZ2JsZSBlbGVtZW50XHJcbiAgZHJhZ1NvdXJjZTogSFRNTEVsZW1lbnQ7XHJcbiAgcHREb3duOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH07XHJcbiAgaXNEcmFnRW5hYmxlZDogYm9vbGVhbjtcclxuICBpc0Ryb3Bab25lOiBib29sZWFuO1xyXG4gIHByZXNzSG9sZEludGVydmFsO1xyXG4gIGltZztcclxuICBpbWdDdXN0b207XHJcbiAgaW1nT2Zmc2V0O1xyXG4gIC8vIGZvciBjb250aW51YWwgZHJhZyBvdmVyIGV2ZW50IGV2ZW4gdG91Y2ggcG9pbnQgc3RvcCBhdCBhIGNlcnRhaW4gcG9pbnQgZm9yIGEgd2hpbGUuXHJcbiAgZHJhZ292ZXJUaW1lcjtcclxuICAvLyBmb3IgYmluZCB0b3VjaCBtb3ZlIGFuZCB0b3VjaCBlbmQgZXZlbnQgdG8gdG91Y2ggdGFyZ2V0IGluY2FzZSB2aXJ0dWFsIHNjcm9sbCBjYXVzZVxyXG4gIC8vIGRvY3VtZW50IG5vIGxvbmdlciBnZXQgY2FwdHVyZS8gYnViYmxlIG9mIHRvdWNobW92ZSBldmVudCBmcm9tIGRvbSByZW1vdmVkIGZyb20gZG9jdW1lbnQgdHJlZVxyXG4gIHRvdWNoVGFyZ2V0OiBFdmVudFRhcmdldDtcclxuICB0b3VjaG1vdmVMaXN0ZW5lcjogRXZlbnRMaXN0ZW5lcjtcclxuICB0b3VjaGVuZExpc3RlbmVyOiBFdmVudExpc3RlbmVyO1xyXG4gIGxpc3RlbmVyT3B0OiBib29sZWFuIHwgRXZlbnRMaXN0ZW5lck9wdGlvbnM7XHJcblxyXG4gIGNvbnN0cnVjdG9yKCkge1xyXG4gICAgLy8gZW5mb3JjZSBzaW5nbGV0b24gcGF0dGVyblxyXG4gICAgaWYgKERyYWdEcm9wVG91Y2guaW5zdGFuY2UpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdEcmFnRHJvcFRvdWNoIGluc3RhbmNlIGFscmVhZHkgY3JlYXRlZC4nKTtcclxuICAgIH1cclxuICAgIC8vIGRldGVjdCBwYXNzaXZlIGV2ZW50IHN1cHBvcnRcclxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9Nb2Rlcm5penIvTW9kZXJuaXpyL2lzc3Vlcy8xODk0XHJcbiAgICBsZXQgc3VwcG9ydHNQYXNzaXZlID0gZmFsc2U7XHJcbiAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJykge1xyXG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0ZXN0JywgKCkgPT4ge30sIHtcclxuICAgICAgICBnZXQgcGFzc2l2ZSgpIHtcclxuICAgICAgICAgIHN1cHBvcnRzUGFzc2l2ZSA9IHRydWU7XHJcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICB9LFxyXG4gICAgICB9KTtcclxuICAgICAgLy8gbGlzdGVuIHRvIHRvdWNoIGV2ZW50c1xyXG4gICAgICBpZiAoRHJhZ0Ryb3BUb3VjaC5pc1RvdWNoRGV2aWNlKCkpIHtcclxuICAgICAgICAvLyDog73lk43lupTop6bmkbjkuovku7ZcclxuICAgICAgICBjb25zdCBkID0gZG9jdW1lbnQ7XHJcbiAgICAgICAgY29uc3QgdHMgPSB0aGlzLnRvdWNoc3RhcnQ7XHJcbiAgICAgICAgY29uc3QgdG1vZCA9IHRoaXMudG91Y2htb3ZlT25Eb2N1bWVudDtcclxuICAgICAgICBjb25zdCB0ZW9kID0gdGhpcy50b3VjaGVuZE9uRG9jdW1lbnQ7XHJcbiAgICAgICAgY29uc3Qgb3B0ID0gc3VwcG9ydHNQYXNzaXZlID8geyBwYXNzaXZlOiBmYWxzZSwgY2FwdHVyZTogZmFsc2UgfSA6IGZhbHNlO1xyXG4gICAgICAgIGNvbnN0IG9wdFBhc3NpdmUgPSBzdXBwb3J0c1Bhc3NpdmUgPyB7IHBhc3NpdmU6IHRydWUgfSA6IGZhbHNlO1xyXG4gICAgICAgIGQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRzLCBvcHQpO1xyXG4gICAgICAgIGQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdG1vZCwgb3B0UGFzc2l2ZSk7XHJcbiAgICAgICAgZC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRlb2QpO1xyXG4gICAgICAgIGQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hjYW5jZWwnLCB0ZW9kKTtcclxuICAgICAgICB0aGlzLnRvdWNobW92ZUxpc3RlbmVyID0gdGhpcy50b3VjaG1vdmU7XHJcbiAgICAgICAgdGhpcy50b3VjaGVuZExpc3RlbmVyID0gdGhpcy50b3VjaGVuZDtcclxuICAgICAgICB0aGlzLmxpc3RlbmVyT3B0ID0gb3B0O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIEdldHMgYSByZWZlcmVuY2UgdG8gdGhlIEBzZWU6RHJhZ0Ryb3BUb3VjaCBzaW5nbGV0b24uXHJcbiAgICovXHJcbiAgc3RhdGljIGdldEluc3RhbmNlKCkge1xyXG4gICAgaWYgKCFEcmFnRHJvcFRvdWNoLmluc3RhbmNlKSB7XHJcbiAgICAgIERyYWdEcm9wVG91Y2guaW5zdGFuY2UgPSBuZXcgRHJhZ0Ryb3BUb3VjaCgpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIERyYWdEcm9wVG91Y2guaW5zdGFuY2U7XHJcbiAgfVxyXG4gIHN0YXRpYyBpc1RvdWNoRGV2aWNlKCkge1xyXG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnIHx8IHR5cGVvZiBkb2N1bWVudCA9PT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gICAgY29uc3QgZDogRG9jdW1lbnQgPSBkb2N1bWVudDtcclxuICAgIGNvbnN0IHc6IFdpbmRvdyA9IHdpbmRvdztcclxuICAgIGxldCBib29sO1xyXG4gICAgaWYgKFxyXG4gICAgICAnb250b3VjaHN0YXJ0JyBpbiBkIHx8IC8vIG5vcm1hbCBtb2JpbGUgZGV2aWNlXHJcbiAgICAgICdvbnRvdWNoc3RhcnQnIGluIHcgfHxcclxuICAgICAgbmF2aWdhdG9yLm1heFRvdWNoUG9pbnRzID4gMCB8fFxyXG4gICAgICAobmF2aWdhdG9yIGFzIGFueSkubXNNYXhUb3VjaFBvaW50cyA+IDAgfHxcclxuICAgICAgKCh3aW5kb3cgYXMgYW55KS5Eb2N1bWVudFRvdWNoICYmIGRvY3VtZW50IGluc3RhbmNlb2YgKHdpbmRvdyBhcyBhbnkpLkRvY3VtZW50VG91Y2gpXHJcbiAgICApIHtcclxuICAgICAgYm9vbCA9IHRydWU7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBjb25zdCBmYWtlQm9keSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2Zha2Vib2R5Jyk7XHJcbiAgICAgIGZha2VCb2R5Lmlu