@katoid/angular-grid-layout
Version:
Grid Layout with draggable and resizable items for Angular
219 lines • 40.6 kB
JavaScript
import { compact, getFirstCollision, moveElement } from './react-grid-layout.utils';
import { ktdPointerClientX, ktdPointerClientY } from './pointer.utils';
/** Tracks items by id. This function is mean to be used in conjunction with the ngFor that renders the 'ktd-grid-items' */
export function ktdTrackById(index, item) {
return item.id;
}
/** Given a layout, the gridHeight and the gap return the resulting rowHeight */
export function ktdGetGridItemRowHeight(layout, gridHeight, gap) {
const numberOfRows = layout.reduce((acc, cur) => Math.max(acc, Math.max(cur.y + cur.h, 0)), 0);
const gapTotalHeight = (numberOfRows - 1) * gap;
const gridHeightMinusGap = gridHeight - gapTotalHeight;
return gridHeightMinusGap / numberOfRows;
}
/**
* Call react-grid-layout utils 'compact()' function and return the compacted layout.
* @param layout to be compacted.
* @param compactType, type of compaction.
* @param cols, number of columns of the grid.
*/
export function ktdGridCompact(layout, compactType, cols) {
return compact(layout, compactType, cols)
// Prune react-grid-layout compact extra properties.
.map(item => ({ id: item.id, x: item.x, y: item.y, w: item.w, h: item.h, minW: item.minW, minH: item.minH, maxW: item.maxW, maxH: item.maxH }));
}
function screenXToGridX(screenXPos, cols, width, gap) {
if (cols <= 1) {
return 0;
}
const totalGapsWidth = gap * (cols - 1);
const totalItemsWidth = width - totalGapsWidth;
const itemPlusGapWidth = totalItemsWidth / cols + gap;
return Math.round(screenXPos / itemPlusGapWidth);
}
function screenYToGridY(screenYPos, rowHeight, height, gap) {
return Math.round(screenYPos / (rowHeight + gap));
}
function screenWidthToGridWidth(gridScreenWidth, cols, width, gap) {
const widthMinusGaps = width - (gap * (cols - 1));
const itemWidth = widthMinusGaps / cols;
const gridScreenWidthMinusFirst = gridScreenWidth - itemWidth;
return Math.round(gridScreenWidthMinusFirst / (itemWidth + gap)) + 1;
}
function screenHeightToGridHeight(gridScreenHeight, rowHeight, height, gap) {
const gridScreenHeightMinusFirst = gridScreenHeight - rowHeight;
return Math.round(gridScreenHeightMinusFirst / (rowHeight + gap)) + 1;
}
/** Returns a Dictionary where the key is the id and the value is the change applied to that item. If no changes Dictionary is empty. */
export function ktdGetGridLayoutDiff(gridLayoutA, gridLayoutB) {
const diff = {};
gridLayoutA.forEach(itemA => {
const itemB = gridLayoutB.find(_itemB => _itemB.id === itemA.id);
if (itemB != null) {
const posChanged = itemA.x !== itemB.x || itemA.y !== itemB.y;
const sizeChanged = itemA.w !== itemB.w || itemA.h !== itemB.h;
const change = posChanged && sizeChanged ? 'moveresize' : posChanged ? 'move' : sizeChanged ? 'resize' : null;
if (change) {
diff[itemB.id] = { change };
}
}
});
return diff;
}
/**
* Given the grid config & layout data and the current drag position & information, returns the corresponding layout and drag item position
* @param gridItem grid item that is been dragged
* @param config current grid configuration
* @param compactionType type of compaction that will be performed
* @param draggingData contains all the information about the drag
*/
export function ktdGridItemDragging(gridItem, config, compactionType, draggingData) {
const { pointerDownEvent, pointerDragEvent, gridElemClientRect, dragElemClientRect, scrollDifference } = draggingData;
const gridItemId = gridItem.id;
const draggingElemPrevItem = config.layout.find(item => item.id === gridItemId);
const clientStartX = ktdPointerClientX(pointerDownEvent);
const clientStartY = ktdPointerClientY(pointerDownEvent);
const clientX = ktdPointerClientX(pointerDragEvent);
const clientY = ktdPointerClientY(pointerDragEvent);
const offsetX = clientStartX - dragElemClientRect.left;
const offsetY = clientStartY - dragElemClientRect.top;
// Grid element positions taking into account the possible scroll total difference from the beginning.
const gridElementLeftPosition = gridElemClientRect.left + scrollDifference.left;
const gridElementTopPosition = gridElemClientRect.top + scrollDifference.top;
// Calculate position relative to the grid element.
const gridRelXPos = clientX - gridElementLeftPosition - offsetX;
const gridRelYPos = clientY - gridElementTopPosition - offsetY;
const rowHeightInPixels = config.rowHeight === 'fit'
? ktdGetGridItemRowHeight(config.layout, config.height ?? gridElemClientRect.height, config.gap)
: config.rowHeight;
// Get layout item position
const layoutItem = {
...draggingElemPrevItem,
x: screenXToGridX(gridRelXPos, config.cols, gridElemClientRect.width, config.gap),
y: screenYToGridY(gridRelYPos, rowHeightInPixels, gridElemClientRect.height, config.gap)
};
// Correct the values if they overflow, since 'moveElement' function doesn't do it
layoutItem.x = Math.max(0, layoutItem.x);
layoutItem.y = Math.max(0, layoutItem.y);
if (layoutItem.x + layoutItem.w > config.cols) {
layoutItem.x = Math.max(0, config.cols - layoutItem.w);
}
// Parse to LayoutItem array data in order to use 'react.grid-layout' utils
const layoutItems = config.layout;
const draggedLayoutItem = layoutItems.find(item => item.id === gridItemId);
let newLayoutItems = moveElement(layoutItems, draggedLayoutItem, layoutItem.x, layoutItem.y, true, config.preventCollision, compactionType, config.cols);
newLayoutItems = compact(newLayoutItems, compactionType, config.cols);
return {
layout: newLayoutItems,
draggedItemPos: {
top: gridRelYPos,
left: gridRelXPos,
width: dragElemClientRect.width,
height: dragElemClientRect.height,
}
};
}
/**
* Given the grid config & layout data and the current drag position & information, returns the corresponding layout and drag item position
* @param gridItem grid item that is been dragged
* @param config current grid configuration
* @param compactionType type of compaction that will be performed
* @param draggingData contains all the information about the drag
*/
export function ktdGridItemResizing(gridItem, config, compactionType, draggingData) {
const { pointerDownEvent, pointerDragEvent, gridElemClientRect, dragElemClientRect, scrollDifference } = draggingData;
const gridItemId = gridItem.id;
const clientStartX = ktdPointerClientX(pointerDownEvent);
const clientStartY = ktdPointerClientY(pointerDownEvent);
const clientX = ktdPointerClientX(pointerDragEvent);
const clientY = ktdPointerClientY(pointerDragEvent);
// Get the difference between the mouseDown and the position 'right' of the resize element.
const resizeElemOffsetX = dragElemClientRect.width - (clientStartX - dragElemClientRect.left);
const resizeElemOffsetY = dragElemClientRect.height - (clientStartY - dragElemClientRect.top);
const draggingElemPrevItem = config.layout.find(item => item.id === gridItemId);
const width = clientX + resizeElemOffsetX - (dragElemClientRect.left + scrollDifference.left);
const height = clientY + resizeElemOffsetY - (dragElemClientRect.top + scrollDifference.top);
const rowHeightInPixels = config.rowHeight === 'fit'
? ktdGetGridItemRowHeight(config.layout, config.height ?? gridElemClientRect.height, config.gap)
: config.rowHeight;
// Get layout item grid position
const layoutItem = {
...draggingElemPrevItem,
w: screenWidthToGridWidth(width, config.cols, gridElemClientRect.width, config.gap),
h: screenHeightToGridHeight(height, rowHeightInPixels, gridElemClientRect.height, config.gap)
};
layoutItem.w = limitNumberWithinRange(layoutItem.w, gridItem.minW ?? layoutItem.minW, gridItem.maxW ?? layoutItem.maxW);
layoutItem.h = limitNumberWithinRange(layoutItem.h, gridItem.minH ?? layoutItem.minH, gridItem.maxH ?? layoutItem.maxH);
if (layoutItem.x + layoutItem.w > config.cols) {
layoutItem.w = Math.max(1, config.cols - layoutItem.x);
}
if (config.preventCollision) {
const maxW = layoutItem.w;
const maxH = layoutItem.h;
let colliding = hasCollision(config.layout, layoutItem);
let shrunkDimension;
while (colliding) {
shrunkDimension = getDimensionToShrink(layoutItem, shrunkDimension);
layoutItem[shrunkDimension]--;
colliding = hasCollision(config.layout, layoutItem);
}
if (shrunkDimension === 'w') {
layoutItem.h = maxH;
colliding = hasCollision(config.layout, layoutItem);
while (colliding) {
layoutItem.h--;
colliding = hasCollision(config.layout, layoutItem);
}
}
if (shrunkDimension === 'h') {
layoutItem.w = maxW;
colliding = hasCollision(config.layout, layoutItem);
while (colliding) {
layoutItem.w--;
colliding = hasCollision(config.layout, layoutItem);
}
}
}
const newLayoutItems = config.layout.map((item) => {
return item.id === gridItemId ? layoutItem : item;
});
return {
layout: compact(newLayoutItems, compactionType, config.cols),
draggedItemPos: {
top: dragElemClientRect.top - gridElemClientRect.top,
left: dragElemClientRect.left - gridElemClientRect.left,
width,
height,
}
};
}
function hasCollision(layout, layoutItem) {
return !!getFirstCollision(layout, layoutItem);
}
function getDimensionToShrink(layoutItem, lastShrunk) {
if (layoutItem.h <= 1) {
return 'w';
}
if (layoutItem.w <= 1) {
return 'h';
}
return lastShrunk === 'w' ? 'h' : 'w';
}
/**
* Given the current number and min/max values, returns the number within the range
* @param number can be any numeric value
* @param min minimum value of range
* @param max maximum value of range
*/
function limitNumberWithinRange(num, min = 1, max = Infinity) {
return Math.min(Math.max(num, min < 1 ? 1 : min), max);
}
/** Returns true if both item1 and item2 KtdGridLayoutItems are equivalent. */
export function ktdGridItemLayoutItemAreEqual(item1, item2) {
return item1.id === item2.id
&& item1.x === item2.x
&& item1.y === item2.y
&& item1.w === item2.w
&& item1.h === item2.h;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JpZC51dGlscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItZ3JpZC1sYXlvdXQvc3JjL2xpYi91dGlscy9ncmlkLnV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxPQUFPLEVBQWUsaUJBQWlCLEVBQXNCLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBSXJILE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBSXZFLDJIQUEySDtBQUMzSCxNQUFNLFVBQVUsWUFBWSxDQUFDLEtBQWEsRUFBRSxJQUFrQjtJQUMxRCxPQUFPLElBQUksQ0FBQyxFQUFFLENBQUM7QUFDbkIsQ0FBQztBQUVELGdGQUFnRjtBQUNoRixNQUFNLFVBQVUsdUJBQXVCLENBQUMsTUFBcUIsRUFBRSxVQUFrQixFQUFFLEdBQVc7SUFDMUYsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDL0YsTUFBTSxjQUFjLEdBQUcsQ0FBQyxZQUFZLEdBQUcsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDO0lBQ2hELE1BQU0sa0JBQWtCLEdBQUcsVUFBVSxHQUFHLGNBQWMsQ0FBQztJQUN2RCxPQUFPLGtCQUFrQixHQUFHLFlBQVksQ0FBQztBQUM3QyxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsY0FBYyxDQUFDLE1BQXFCLEVBQUUsV0FBK0IsRUFBRSxJQUFZO0lBQy9GLE9BQU8sT0FBTyxDQUFDLE1BQU0sRUFBRSxXQUFXLEVB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QztBQUVELDhFQUE4RTtBQUM5RSxNQUFNLFVBQVUsNkJBQTZCLENBQUMsS0FBd0IsRUFBRSxLQUF3QjtJQUM1RixPQUFPLEtBQUssQ0FBQyxFQUFFLEtBQUssS0FBSyxDQUFDLEVBQUU7V0FDckIsS0FBSyxDQUFDLENBQUMsS0FBSyxLQUFLLENBQUMsQ0FBQztXQUNuQixLQUFLLENBQUMsQ0FBQyxLQUFLLEtBQUssQ0FBQyxDQUFDO1dBQ25CLEtBQUssQ0FBQyxDQUFDLEtBQUssS0FBSyxDQUFDLENBQUM7V0FDbkIsS0FBSyxDQUFDLENBQUMsS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFBO0FBQzlCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjb21wYWN0LCBDb21wYWN0VHlwZSwgZ2V0Rmlyc3RDb2xsaXNpb24sIExheW91dCwgTGF5b3V0SXRlbSwgbW92ZUVsZW1lbnQgfSBmcm9tICcuL3JlYWN0LWdyaWQtbGF5b3V0LnV0aWxzJztcclxuaW1wb3J0IHtcclxuICAgIEt0ZERyYWdnaW5nRGF0YSwgS3RkR3JpZENmZywgS3RkR3JpZENvbXBhY3RUeXBlLCBLdGRHcmlkSXRlbVJlY3QsIEt0ZEdyaWRJdGVtUmVuZGVyRGF0YSwgS3RkR3JpZExheW91dCwgS3RkR3JpZExheW91dEl0ZW1cclxufSBmcm9tICcuLi9ncmlkLmRlZmluaXRpb25zJztcclxuaW1wb3J0IHsga3RkUG9pbnRlckNsaWVudFgsIGt0ZFBvaW50ZXJDbGllbnRZIH0gZnJvbSAnLi9wb2ludGVyLnV0aWxzJztcclxuaW1wb3J0IHsgS3RkRGljdGlvbmFyeSB9IGZyb20gJy4uLy4uL3R5cGVzJztcclxuaW1wb3J0IHsgS3RkR3JpZEl0ZW1Db21wb25lbnQgfSBmcm9tICcuLi9ncmlkLWl0ZW0vZ3JpZC1pdGVtLmNvbXBvbmVudCc7XHJcblxyXG4vKiogVHJhY2tzIGl0ZW1zIGJ5IGlkLiBUaGlzIGZ1bmN0aW9uIGlzIG1lYW4gdG8gYmUgdXNlZCBpbiBjb25qdW5jdGlvbiB3aXRoIHRoZSBuZ0ZvciB0aGF0IHJlbmRlcnMgdGhlICdrdGQtZ3JpZC1pdGVtcycgKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGt0ZFRyYWNrQnlJZChpbmRleDogbnVtYmVyLCBpdGVtOiB7aWQ6IHN0cmluZ30pIHtcclxuICAgIHJldHVybiBpdGVtLmlkO1xyXG59XHJcblxyXG4vKiogR2l2ZW4gYSBsYXlvdXQsIHRoZSBncmlkSGVpZ2h0IGFuZCB0aGUgZ2FwIHJldHVybiB0aGUgcmVzdWx0aW5nIHJvd0hlaWdodCAqL1xyXG5leHBvcnQgZnVuY3Rpb24ga3RkR2V0R3JpZEl0ZW1Sb3dIZWlnaHQobGF5b3V0OiBLdGRHcmlkTGF5b3V0LCBncmlkSGVpZ2h0OiBudW1iZXIsIGdhcDogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgIGNvbnN0IG51bWJlck9mUm93cyA9IGxheW91dC5yZWR1Y2UoKGFjYywgY3VyKSA9PiBNYXRoLm1heChhY2MsIE1hdGgubWF4KGN1ci55ICsgY3VyLmgsIDApKSwgMCk7XHJcbiAgICBjb25zdCBnYXBUb3RhbEhlaWdodCA9IChudW1iZXJPZlJvd3MgLSAxKSAqIGdhcDtcclxuICAgIGNvbnN0IGdyaWRIZWlnaHRNaW51c0dhcCA9IGdyaWRIZWlnaHQgLSBnYXBUb3RhbEhlaWdodDtcclxuICAgIHJldHVybiBncmlkSGVpZ2h0TWludXNHYXAgLyBudW1iZXJPZlJvd3M7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDYWxsIHJlYWN0LWdyaWQtbGF5b3V0IHV0aWxzICdjb21wYWN0KCknIGZ1bmN0aW9uIGFuZCByZXR1cm4gdGhlIGNvbXBhY3RlZCBsYXlvdXQuXHJcbiAqIEBwYXJhbSBsYXlvdXQgdG8gYmUgY29tcGFjdGVkLlxyXG4gKiBAcGFyYW0gY29tcGFjdFR5cGUsIHR5cGUgb2YgY29tcGFjdGlvbi5cclxuICogQHBhcmFtIGNvbHMsIG51bWJlciBvZiBjb2x1bW5zIG9mIHRoZSBncmlkLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGt0ZEdyaWRDb21wYWN0KGxheW91dDogS3RkR3JpZExheW91dCwgY29tcGFjdFR5cGU6IEt0ZEdyaWRDb21wYWN0VHlwZSwgY29sczogbnVtYmVyKTogS3RkR3JpZExheW91dCB7XHJcbiAgICByZXR1cm4gY29tcGFjdChsYXlvdXQsIGNvbXBhY3RUeXBlLCBjb2xzKVxyXG4gICAgICAgIC8vIFBydW5lIHJlYWN0LWdyaWQtbGF5b3V0IGNvbXBhY3QgZXh0cmEgcHJvcGVydGllcy5cclxuICAgICAgICAubWFwKGl0ZW0gPT4gKHsgaWQ6IGl0ZW0uaWQsIHg6IGl0ZW0ueCwgeTogaXRlbS55LCB3OiBpdGVtLncsIGg6IGl0ZW0uaCwgbWluVzogaXRlbS5taW5XLCBtaW5IOiBpdGVtLm1pbkgsIG1heFc6IGl0ZW0ubWF4VywgbWF4SDogaXRlbS5tYXhIIH0pKTtcclxufVxyXG5cclxuZnVuY3Rpb24gc2NyZWVuWFRvR3JpZFgoc2NyZWVuWFBvczogbnVtYmVyLCBjb2xzOiBudW1iZXIsIHdpZHRoOiBudW1iZXIsIGdhcDogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgIGlmIChjb2xzIDw9IDEpIHtcclxuICAgICAgICByZXR1cm4gMDtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB0b3RhbEdhcHNXaWR0aCA9IGdhcCAqIChjb2xzIC0gMSk7XHJcbiAgICBjb25zdCB0b3RhbEl0ZW1zV2lkdGggPSB3aWR0aCAtIHRvdGFsR2Fwc1dpZHRoO1xyXG4gICAgY29uc3QgaXRlbVBsdXNHYXBXaWR0aCA9IHRvdGFsSXRlbXNXaWR0aCAvIGNvbHMgKyBnYXA7XHJcbiAgICByZXR1cm4gTWF0aC5yb3VuZChzY3JlZW5YUG9zIC8gaXRlbVBsdXNHYXBXaWR0aCk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHNjcmVlbllUb0dyaWRZKHNjcmVlbllQb3M6IG51bWJlciwgcm93SGVpZ2h0OiBudW1iZXIsIGhlaWdodDogbnVtYmVyLCBnYXA6IG51bWJlcik6IG51bWJlciB7XHJcbiAgICByZXR1cm4gTWF0aC5yb3VuZChzY3JlZW5ZUG9zIC8gKHJvd0hlaWdodCArIGdhcCkpO1xyXG59XHJcblxyXG5mdW5jdGlvbiBzY3JlZW5XaWR0aFRvR3JpZFdpZHRoKGdyaWRTY3JlZW5XaWR0aDogbnVtYmVyLCBjb2xzOiBudW1iZXIsIHdpZHRoOiBudW1iZXIsIGdhcDogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgIGNvbnN0IHdpZHRoTWludXNHYXBzID0gd2lkdGggLSAoZ2FwICogKGNvbHMgLSAxKSk7XHJcbiAgICBjb25zdCBpdGVtV2lkdGggPSB3aWR0aE1pbnVzR2FwcyAvIGNvbHM7XHJcbiAgICBjb25zdCBncmlkU2NyZWVuV2lkdGhNaW51c0ZpcnN0ID0gZ3JpZFNjcmVlbldpZHRoIC0gaXRlbVdpZHRoO1xyXG4gICAgcmV0dXJuIE1hdGgucm91bmQoZ3JpZFNjcmVlbldpZHRoTWludXNGaXJzdCAvIChpdGVtV2lkdGggKyBnYXApKSArIDE7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHNjcmVlbkhlaWdodFRvR3JpZEhlaWdodChncmlkU2NyZWVuSGVpZ2h0OiBudW1iZXIsIHJvd0hlaWdodDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciwgZ2FwOiBudW1iZXIpOiBudW1iZXIge1xyXG4gICAgY29uc3QgZ3JpZFNjcmVlbkhlaWdodE1pbnVzRmlyc3QgPSBncmlkU2NyZWVuSGVpZ2h0IC0gcm93SGVpZ2h0O1xyXG4gICAgcmV0dXJuIE1hdGgucm91bmQoZ3JpZFNjcmVlbkhlaWdodE1pbnVzRmlyc3QgLyAocm93SGVpZ2h0ICsgZ2FwKSkgKyAxO1xyXG59XHJcblxyXG4vKiogUmV0dXJucyBhIERpY3Rpb25hcnkgd2hlcmUgdGhlIGtleSBpcyB0aGUgaWQgYW5kIHRoZSB2YWx1ZSBpcyB0aGUgY2hhbmdlIGFwcGxpZWQgdG8gdGhhdCBpdGVtLiBJZiBubyBjaGFuZ2VzIERpY3Rpb25hcnkgaXMgZW1wdHkuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBrdGRHZXRHcmlkTGF5b3V0RGlmZihncmlkTGF5b3V0QTogS3RkR3JpZExheW91dEl0ZW1bXSwgZ3JpZExheW91dEI6IEt0ZEdyaWRMYXlvdXRJdGVtW10pOiBLdGREaWN0aW9uYXJ5PHsgY2hhbmdlOiAnbW92ZScgfCAncmVzaXplJyB8ICdtb3ZlcmVzaXplJyB9PiB7XHJcbiAgICBjb25zdCBkaWZmOiBLdGREaWN0aW9uYXJ5PHsgY2hhbmdlOiAnbW92ZScgfCAncmVzaXplJyB8ICdtb3ZlcmVzaXplJyB9PiA9IHt9O1xyXG5cclxuICAgIGdyaWRMYXlvdXRBLmZvckVhY2goaXRlbUEgPT4ge1xyXG4gICAgICAgIGNvbnN0IGl0ZW1CID0gZ3JpZExheW91dEIuZmluZChfaXRlbUIgPT4gX2l0ZW1CLmlkID09PSBpdGVtQS5pZCk7XHJcbiAgICAgICAgaWYgKGl0ZW1CICE9IG51bGwpIHtcclxuICAgICAgICAgICAgY29uc3QgcG9zQ2hhbmdlZCA9IGl0ZW1BLnggIT09IGl0ZW1CLnggfHwgaXRlbUEueSAhPT0gaXRlbUIueTtcclxuICAgICAgICAgICAgY29uc3Qgc2l6ZUNoYW5nZWQgPSBpdGVtQS53ICE9PSBpdGVtQi53IHx8IGl0ZW1BLmggIT09IGl0ZW1CLmg7XHJcbiAgICAgICAgICAgIGNvbnN0IGNoYW5nZTogJ21vdmUnIHwgJ3Jlc2l6ZScgfCAnbW92ZXJlc2l6ZScgfCBudWxsID0gcG9zQ2hhbmdlZCAmJiBzaXplQ2hhbmdlZCA/ICdtb3ZlcmVzaXplJyA6IHBvc0NoYW5nZWQgPyAnbW92ZScgOiBzaXplQ2hhbmdlZCA/ICdyZXNpemUnIDogbnVsbDtcclxuICAgICAgICAgICAgaWYgKGNoYW5nZSkge1xyXG4gICAgICAgICAgICAgICAgZGlmZltpdGVtQi5pZF0gPSB7Y2hhbmdlfTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIGRpZmY7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBHaXZlbiB0aGUgZ3JpZCBjb25maWcgJiBsYXlvdXQgZGF0YSBhbmQgdGhlIGN1cnJlbnQgZHJhZyBwb3NpdGlvbiAmIGluZm9ybWF0aW9uLCByZXR1cm5zIHRoZSBjb3JyZXNwb25kaW5nIGxheW91dCBhbmQgZHJhZyBpdGVtIHBvc2l0aW9uXHJcbiAqIEBwYXJhbSBncmlkSXRlbSBncmlkIGl0ZW0gdGhhdCBpcyBiZWVuIGRyYWdnZWRcclxuICogQHBhcmFtIGNvbmZpZyBjdXJyZW50IGdyaWQgY29uZmlndXJhdGlvblxyXG4gKiBAcGFyYW0gY29tcGFjdGlvblR5cGUgdHlwZSBvZiBjb21wYWN0aW9uIHRoYXQgd2lsbCBiZSBwZXJmb3JtZWRcclxuICogQHBhcmFtIGRyYWdnaW5nRGF0YSBjb250YWlucyBhbGwgdGhlIGluZm9ybWF0aW9uIGFib3V0IHRoZSBkcmFnXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24ga3RkR3JpZEl0ZW1EcmFnZ2luZyhncmlkSXRlbTogS3RkR3JpZEl0ZW1Db21wb25lbnQsIGNvbmZpZzogS3RkR3JpZENmZywgY29tcGFjdGlvblR5cGU6IENvbXBhY3RUeXBlLCBkcmFnZ2luZ0RhdGE6IEt0ZERyYWdnaW5nRGF0YSk6IHsgbGF5b3V0OiBLdGRHcmlkTGF5b3V0SXRlbVtdOyBkcmFnZ2VkSXRlbVBvczogS3RkR3JpZEl0ZW1SZWN0IH0ge1xyXG4gICAgY29uc3Qge3BvaW50ZXJEb3duRXZlbnQsIHBvaW50ZXJEcmFnRXZlbnQsIGdyaWRFbGVtQ2xpZW50UmVjdCwgZHJhZ0VsZW1DbGllbnRSZWN0LCBzY3JvbGxEaWZmZXJlbmNlfSA9IGRyYWdnaW5nRGF0YTtcclxuXHJcbiAgICBjb25zdCBncmlkSXRlbUlkID0gZ3JpZEl0ZW0uaWQ7XHJcblxyXG4gICAgY29uc3QgZHJhZ2dpbmdFbGVtUHJldkl0ZW0gPSBjb25maWcubGF5b3V0LmZpbmQoaXRlbSA9PiBpdGVtLmlkID09PSBncmlkSXRlbUlkKSE7XHJcblxyXG4gICAgY29uc3QgY2xpZW50U3RhcnRYID0ga3RkUG9pbnRlckNsaWVudFgocG9pbnRlckRvd25FdmVudCk7XHJcbiAgICBjb25zdCBjbGllbnRTdGFydFkgPSBrdGRQb2ludGVyQ2xpZW50WShwb2ludGVyRG93bkV2ZW50KTtcclxuICAgIGNvbnN0IGNsaWVudFggPSBrdGRQb2ludGVyQ2xpZW50WChwb2ludGVyRHJhZ0V2ZW50KTtcclxuICAgIGNvbnN0IGNsaWVudFkgPSBrdGRQb2ludGVyQ2xpZW50WShwb2ludGVyRHJhZ0V2ZW50KTtcclxuXHJcbiAgICBjb25zdCBvZmZzZXRYID0gY2xpZW50U3RhcnRYIC0gZHJhZ0VsZW1DbGllbnRSZWN0LmxlZnQ7XHJcbiAgICBjb25zdCBvZmZzZXRZID0gY2xpZW50U3RhcnRZIC0gZHJhZ0VsZW1DbGllbnRSZWN0LnRvcDtcclxuXHJcbiAgICAvLyBHcmlkIGVsZW1lbnQgcG9zaXRpb25zIHRha2luZyBpbnRvIGFjY291bnQgdGhlIHBvc3NpYmxlIHNjcm9sbCB0b3RhbCBkaWZmZXJlbmNlIGZyb20gdGhlIGJlZ2lubmluZy5cclxuICAgIGNvbnN0IGdyaWRFbGVtZW50TGVmdFBvc2l0aW9uID0gZ3JpZEVsZW1DbGllbnRSZWN0LmxlZnQgKyBzY3JvbGxEaWZmZXJlbmNlLmxlZnQ7XHJcbiAgICBjb25zdCBncmlkRWxlbWVudFRvcFBvc2l0aW9uID0gZ3JpZEVsZW1DbGllbnRSZWN0LnRvcCArIHNjcm9sbERpZmZlcmVuY2UudG9wO1xyXG5cclxuICAgIC8vIENhbGN1bGF0ZSBwb3NpdGlvbiByZWxhdGl2ZSB0byB0aGUgZ3JpZCBlbGVtZW50LlxyXG4gICAgY29uc3QgZ3JpZFJlbFhQb3MgPSBjbGllbnRYIC0gZ3JpZEVsZW1lbnRMZWZ0UG9zaXRpb24gLSBvZmZzZXRYO1xyXG4gICAgY29uc3QgZ3JpZFJlbFlQb3MgPSBjbGllbnRZIC0gZ3JpZEVsZW1lbnRUb3BQb3NpdGlvbiAtIG9mZnNldFk7XHJcblxyXG4gICAgY29uc3Qgcm93SGVpZ2h0SW5QaXhlbHMgPSBjb25maWcucm93SGVpZ2h0ID09PSAnZml0J1xyXG4gICAgICAgID8ga3RkR2V0R3JpZEl0ZW1Sb3dIZWlnaHQoY29uZmlnLmxheW91dCwgY29uZmlnLmhlaWdodCA/PyBncmlkRWxlbUNsaWVudFJlY3QuaGVpZ2h0LCBjb25maWcuZ2FwKVxyXG4gICAgICAgIDogY29uZmlnLnJvd0hlaWdodDtcclxuXHJcbiAgICAvLyBHZXQgbGF5b3V0IGl0ZW0gcG9zaXRpb25cclxuICAgIGNvbnN0IGxheW91dEl0ZW06IEt0ZEdyaWRMYXlvdXRJdGVtID0ge1xyXG4gICAgICAgIC4uLmRyYWdnaW5nRWxlbVByZXZJdGVtLFxyXG4gICAgICAgIHg6IHNjcmVlblhUb0dyaWRYKGdyaWRSZWxYUG9zICwgY29uZmlnLmNvbHMsIGdyaWRFbGVtQ2xpZW50UmVjdC53aWR0aCwgY29uZmlnLmdhcCksXHJcbiAgICAgICAgeTogc2NyZWVuWVRvR3JpZFkoZ3JpZFJlbFlQb3MsIHJvd0hlaWdodEluUGl4ZWxzLCBncmlkRWxlbUNsaWVudFJlY3QuaGVpZ2h0LCBjb25maWcuZ2FwKVxyXG4gICAgfTtcclxuXHJcbiAgICAvLyBDb3JyZWN0IHRoZSB2YWx1ZXMgaWYgdGhleSBvdmVyZmxvdywgc2luY2UgJ21vdmVFbGVtZW50JyBmdW5jdGlvbiBkb2Vzbid0IGRvIGl0XHJcbiAgICBsYXlvdXRJdGVtLnggPSBNYXRoLm1heCgwLCBsYXlvdXRJdGVtLngpO1xyXG4gICAgbGF5b3V0SXRlbS55ID0gTWF0aC5tYXgoMCwgbGF5b3V0SXRlbS55KTtcclxuICAgIGlmIChsYXlvdXRJdGVtLnggKyBsYXlvdXRJdGVtLncgPiBjb25maWcuY29scykge1xyXG4gICAgICAgIGxheW91dEl0ZW0ueCA9IE1hdGgubWF4KDAsIGNvbmZpZy5jb2xzIC0gbGF5b3V0SXRlbS53KTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBQYXJzZSB0byBMYXlvdXRJdGVtIGFycmF5IGRhdGEgaW4gb3JkZXIgdG8gdXNlICdyZWFjdC5ncmlkLWxheW91dCcgdXRpbHNcclxuICAgIGNvbnN0IGxheW91dEl0ZW1zOiBMYXlvdXRJdGVtW10gPSBjb25maWcubGF5b3V0O1xyXG4gICAgY29uc3QgZHJhZ2dlZExheW91dEl0ZW06IExheW91dEl0ZW0gPSBsYXlvdXRJdGVtcy5maW5kKGl0ZW0gPT4gaXRlbS5pZCA9PT0gZ3JpZEl0ZW1JZCkhO1xyXG5cclxuICAgIGxldCBuZXdMYXlvdXRJdGVtczogTGF5b3V0SXRlbVtdID0gbW92ZUVsZW1lbnQoXHJcbiAgICAgICAgbGF5b3V0SXRlbXMsXHJcbiAgICAgICAgZHJhZ2dlZExheW91dEl0ZW0sXHJcbiAgICAgICAgbGF5b3V0SXRlbS54LFxyXG4gICAgICAgIGxheW91dEl0ZW0ueSxcclxuICAgICAgICB0cnVlLFxyXG4gICAgICAgIGNvbmZpZy5wcmV2ZW50Q29sbGlzaW9uLFxyXG4gICAgICAgIGNvbXBhY3Rpb25UeXBlLFxyXG4gICAgICAgIGNvbmZpZy5jb2xzXHJcbiAgICApO1xyXG5cclxuICAgIG5ld0xheW91dEl0ZW1zID0gY29tcGFjdChuZXdMYXlvdXRJdGVtcywgY29tcGFjdGlvblR5cGUsIGNvbmZpZy5jb2xzKTtcclxuXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAgIGxheW91dDogbmV3TGF5b3V0SXRlbXMsXHJcbiAgICAgICAgZHJhZ2dlZEl0ZW1Qb3M6IHtcclxuICAgICAgICAgICAgdG9wOiBncmlkUmVsWVBvcyxcclxuICAgICAgICAgICAgbGVmdDogZ3JpZFJlbFhQb3MsXHJcbiAgICAgICAgICAgIHdpZHRoOiBkcmFnRWxlbUNsaWVudFJlY3Qud2lkdGgsXHJcbiAgICAgICAgICAgIGhlaWdodDogZHJhZ0VsZW1DbGllbnRSZWN0LmhlaWdodCxcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG59XHJcblxyXG4vKipcclxuICogR2l2ZW4gdGhlIGdyaWQgY29uZmlnICYgbGF5b3V0IGRhdGEgYW5kIHRoZSBjdXJyZW50IGRyYWcgcG9zaXRpb24gJiBpbmZvcm1hdGlvbiwgcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZyBsYXlvdXQgYW5kIGRyYWcgaXRlbSBwb3NpdGlvblxyXG4gKiBAcGFyYW0gZ3JpZEl0ZW0gZ3JpZCBpdGVtIHRoYXQgaXMgYmVlbiBkcmFnZ2VkXHJcbiAqIEBwYXJhbSBjb25maWcgY3VycmVudCBncmlkIGNvbmZpZ3VyYXRpb25cclxuICogQHBhcmFtIGNvbXBhY3Rpb25UeXBlIHR5cGUgb2YgY29tcGFjdGlvbiB0aGF0IHdpbGwgYmUgcGVyZm9ybWVkXHJcbiAqIEBwYXJhbSBkcmFnZ2luZ0RhdGEgY29udGFpbnMgYWxsIHRoZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZHJhZ1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGt0ZEdyaWRJdGVtUmVzaXppbmcoZ3JpZEl0ZW06IEt0ZEdyaWRJdGVtQ29tcG9uZW50LCBjb25maWc6IEt0ZEdyaWRDZmcsIGNvbXBhY3Rpb25UeXBlOiBDb21wYWN0VHlwZSwgZHJhZ2dpbmdEYXRhOiBLdGREcmFnZ2luZ0RhdGEpOiB7IGxheW91dDogS3RkR3JpZExheW91dEl0ZW1bXTsgZHJhZ2dlZEl0ZW1Qb3M6IEt0ZEdyaWRJdGVtUmVjdCB9IHtcclxuICAgIGNvbnN0IHtwb2ludGVyRG93bkV2ZW50LCBwb2ludGVyRHJhZ0V2ZW50LCBncmlkRWxlbUNsaWVudFJlY3QsIGRyYWdFbGVtQ2xpZW50UmVjdCwgc2Nyb2xsRGlmZmVyZW5jZX0gPSBkcmFnZ2luZ0RhdGE7XHJcbiAgICBjb25zdCBncmlkSXRlbUlkID0gZ3JpZEl0ZW0uaWQ7XHJcblxyXG4gICAgY29uc3QgY2xpZW50U3RhcnRYID0ga3RkUG9pbnRlckNsaWVudFgocG9pbnRlckRvd25FdmVudCk7XHJcbiAgICBjb25zdCBjbGllbnRTdGFydFkgPSBrdGRQb2ludGVyQ2xpZW50WShwb2ludGVyRG93bkV2ZW50KTtcclxuICAgIGNvbnN0IGNsaWVudFggPSBrdGRQb2ludGVyQ2xpZW50WChwb2ludGVyRHJhZ0V2ZW50KTtcclxuICAgIGNvbnN0IGNsaWVudFkgPSBrdGRQb2ludGVyQ2xpZW50WShwb2ludGVyRHJhZ0V2ZW50KTtcclxuXHJcbiAgICAvLyBHZXQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbW91c2VEb3duIGFuZCB0aGUgcG9zaXRpb24gJ3JpZ2h0JyBvZiB0aGUgcmVzaXplIGVsZW1lbnQuXHJcbiAgICBjb25zdCByZXNpemVFbGVtT2Zmc2V0WCA9IGRyYWdFbGVtQ2xpZW50UmVjdC53aWR0aCAtIChjbGllbnRTdGFydFggLSBkcmFnRWxlbUNsaWVudFJlY3QubGVmdCk7XHJcbiAgICBjb25zdCByZXNpemVFbGVtT2Zmc2V0WSA9IGRyYWdFbGVtQ2xpZW50UmVjdC5oZWlnaHQgLSAoY2xpZW50U3RhcnRZIC0gZHJhZ0VsZW1DbGllbnRSZWN0LnRvcCk7XHJcblxyXG4gICAgY29uc3QgZHJhZ2dpbmdFbGVtUHJldkl0ZW0gPSBjb25maWcubGF5b3V0LmZpbmQoaXRlbSA9PiBpdGVtLmlkID09PSBncmlkSXRlbUlkKSE7XHJcbiAgICBjb25zdCB3aWR0aCA9IGNsaWVudFggKyByZXNpemVFbGVtT2Zmc2V0WCAtIChkcmFnRWxlbUNsaWVudFJlY3QubGVmdCArIHNjcm9sbERpZmZlcmVuY2UubGVmdCk7XHJcbiAgICBjb25zdCBoZWlnaHQgPSBjbGllbnRZICsgcmVzaXplRWxlbU9mZnNldFkgLSAoZHJhZ0VsZW1DbGllbnRSZWN0LnRvcCArIHNjcm9sbERpZmZlcmVuY2UudG9wKTtcclxuXHJcbiAgICBjb25zdCByb3dIZWlnaHRJblBpeGVscyA9IGNvbmZpZy5yb3dIZWlnaHQgPT09ICdmaXQnXHJcbiAgICAgICAgPyBrdGRHZXRHcmlkSXRlbVJvd0hlaWdodChjb25maWcubGF5b3V0LCBjb25maWcuaGVpZ2h0ID8/IGdyaWRFbGVtQ2xpZW50UmVjdC5oZWlnaHQsIGNvbmZpZy5nYXApXHJcbiAgICAgICAgOiBjb25maWcucm93SGVpZ2h0O1xyXG5cclxuICAgIC8vIEdldCBsYXlvdXQgaXRlbSBncmlkIHBvc2l0aW9uXHJcbiAgICBjb25zdCBsYXlvdXRJdGVtOiBLdGRHcmlkTGF5b3V0SXRlbSA9IHtcclxuICAgICAgICAuLi5kcmFnZ2luZ0VsZW1QcmV2SXRlbSxcclxuICAgICAgICB3OiBzY3JlZW5XaWR0aFRvR3JpZFdpZHRoKHdpZHRoLCBjb25maWcuY29scywgZ3JpZEVsZW1DbGllbnRSZWN0LndpZHRoLCBjb25maWcuZ2FwKSxcclxuICAgICAgICBoOiBzY3JlZW5IZWlnaHRUb0dyaWRIZWlnaHQoaGVpZ2h0LCByb3dIZWlnaHRJblBpeGVscywgZ3JpZEVsZW1DbGllbnRSZWN0LmhlaWdodCwgY29uZmlnLmdhcClcclxuICAgIH07XHJcblxyXG4gICAgbGF5b3V0SXRlbS53ID0gbGltaXROdW1iZXJXaXRoaW5SYW5nZShsYXlvdXRJdGVtLncsIGdyaWRJdGVtLm1pblcgPz8gbGF5b3V0SXRlbS5taW5XLCBncmlkSXRlbS5tYXhXID8/IGxheW91dEl0ZW0ubWF4Vyk7XHJcbiAgICBsYXlvdXRJdGVtLmggPSBsaW1pdE51bWJlcldpdGhpblJhbmdlKGxheW91dEl0ZW0uaCwgZ3JpZEl0ZW0ubWluSCA/PyBsYXlvdXRJdGVtLm1pbkgsIGdyaWRJdGVtLm1heEggPz8gbGF5b3V0SXRlbS5tYXhIKTtcclxuXHJcbiAgICBpZiAobGF5b3V0SXRlbS54ICsgbGF5b3V0SXRlbS53ID4gY29uZmlnLmNvbHMpIHtcclxuICAgICAgICBsYXlvdXRJdGVtLncgPSBNYXRoLm1heCgxLCBjb25maWcuY29scyAtIGxheW91dEl0ZW0ueCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGNvbmZpZy5wcmV2ZW50Q29sbGlzaW9uKSB7XHJcbiAgICAgICAgY29uc3QgbWF4VyA9IGxheW91dEl0ZW0udztcclxuICAgICAgICBjb25zdCBtYXhIID0gbGF5b3V0SXRlbS5oO1xyXG5cclxuICAgICAgICBsZXQgY29sbGlkaW5nID0gaGFzQ29sbGlzaW9uKGNvbmZpZy5sYXlvdXQsIGxheW91dEl0ZW0pO1xyXG4gICAgICAgIGxldCBzaHJ1bmtEaW1lbnNpb246ICd3JyB8ICdoJyB8IHVuZGVmaW5lZDtcclxuXHJcbiAgICAgICAgd2hpbGUgKGNvbGxpZGluZykge1xyXG4gICAgICAgICAgICBzaHJ1bmtEaW1lbnNpb24gPSBnZXREaW1lbnNpb25Ub1NocmluayhsYXlvdXRJdGVtLCBzaHJ1bmtEaW1lbnNpb24pO1xyXG4gICAgICAgICAgICBsYXlvdXRJdGVtW3NocnVua0RpbWVuc2lvbl0tLTtcclxuICAgICAgICAgICAgY29sbGlkaW5nID0gaGFzQ29sbGlzaW9uKGNvbmZpZy5sYXlvdXQsIGxheW91dEl0ZW0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHNocnVua0RpbWVuc2lvbiA9PT0gJ3cnKSB7XHJcbiAgICAgICAgICAgIGxheW91dEl0ZW0uaCA9IG1heEg7XHJcblxyXG4gICAgICAgICAgICBjb2xsaWRpbmcgPSBoYXNDb2xsaXNpb24oY29uZmlnLmxheW91dCwgbGF5b3V0SXRlbSk7XHJcbiAgICAgICAgICAgIHdoaWxlIChjb2xsaWRpbmcpIHtcclxuICAgICAgICAgICAgICAgIGxheW91dEl0ZW0uaC0tO1xyXG4gICAgICAgICAgICAgICAgY29sbGlkaW5nID0gaGFzQ29sbGlzaW9uKGNvbmZpZy5sYXlvdXQsIGxheW91dEl0ZW0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChzaHJ1bmtEaW1lbnNpb24gPT09ICdoJykge1xyXG4gICAgICAgICAgICBsYXlvdXRJdGVtLncgPSBtYXhXO1xyXG5cclxuICAgICAgICAgICAgY29sbGlkaW5nID0gaGFzQ29sbGlzaW9uKGNvbmZpZy5sYXlvdXQsIGxheW91dEl0ZW0pO1xyXG4gICAgICAgICAgICB3aGlsZSAoY29sbGlkaW5nKSB7XHJcbiAgICAgICAgICAgICAgICBsYXlvdXRJdGVtLnctLTtcclxuICAgICAgICAgICAgICAgIGNvbGxpZGluZyA9IGhhc0NvbGxpc2lvbihjb25maWcubGF5b3V0LCBsYXlvdXRJdGVtKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgbmV3TGF5b3V0SXRlbXM6IExheW91dEl0ZW1bXSA9IGNvbmZpZy5sYXlvdXQubWFwKChpdGVtKSA9PiB7XHJcbiAgICAgICAgcmV0dXJuIGl0ZW0uaWQgPT09IGdyaWRJdGVtSWQgPyBsYXlvdXRJdGVtIDogaXRlbTtcclxuICAgIH0pO1xyXG5cclxuICAgIHJldHVybiB7XHJcbiAgICAgICAgbGF5b3V0OiBjb21wYWN0KG5ld0xheW91dEl0ZW1zLCBjb21wYWN0aW9uVHlwZSwgY29uZmlnLmNvbHMpLFxyXG4gICAgICAgIGRyYWdnZWRJdGVtUG9zOiB7XHJcbiAgICAgICAgICAgIHRvcDogZHJhZ0VsZW1DbGllbnRSZWN0LnRvcCAtIGdyaWRFbGVtQ2xpZW50UmVjdC50b3AsXHJcbiAgICAgICAgICAgIGxlZnQ6IGRyYWdFbGVtQ2xpZW50UmVjdC5sZWZ0IC0gZ3JpZEVsZW1DbGllbnRSZWN0LmxlZnQsXHJcbiAgICAgICAgICAgIHdpZHRoLFxyXG4gICAgICAgICAgICBoZWlnaHQsXHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxufVxyXG5cclxuZnVuY3Rpb24gaGFzQ29sbGlzaW9uKGxheW91dDogTGF5b3V0LCBsYXlvdXRJdGVtOiBMYXlvdXRJdGVtKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gISFnZXRGaXJzdENvbGxpc2lvbihsYXlvdXQsIGxheW91dEl0ZW0pO1xyXG59XHJcblxyXG5mdW5jdGlvbiBnZXREaW1lbnNpb25Ub1NocmluayhsYXlvdXRJdGVtLCBsYXN0U2hydW5rKTogJ3cnIHwgJ2gnIHtcclxuICAgIGlmIChsYXlvdXRJdGVtLmggPD0gMSkge1xyXG4gICAgICAgIHJldHVybiAndyc7XHJcbiAgICB9XHJcbiAgICBpZiAobGF5b3V0SXRlbS53IDw9IDEpIHtcclxuICAgICAgICByZXR1cm4gJ2gnO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBsYXN0U2hydW5rID09PSAndycgPyAnaCcgOiAndyc7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBHaXZlbiB0aGUgY3VycmVudCBudW1iZXIgYW5kIG1pbi9tYXggdmFsdWVzLCByZXR1cm5zIHRoZSBudW1iZXIgd2l0aGluIHRoZSByYW5nZVxyXG4gKiBAcGFyYW0gbnVtYmVyIGNhbiBiZSBhbnkgbnVtZXJpYyB2YWx1ZVxyXG4gKiBAcGFyYW0gbWluIG1pbmltdW0gdmFsdWUgb2YgcmFuZ2VcclxuICogQHBhcmFtIG1heCBtYXhpbXVtIHZhbHVlIG9mIHJhbmdlXHJcbiAqL1xyXG5mdW5jdGlvbiBsaW1pdE51bWJlcldpdGhpblJhbmdlKG51bTogbnVtYmVyLCBtaW46IG51bWJlciA9IDEsIG1heDogbnVtYmVyID0gSW5maW5pdHkpIHtcclxuICAgIHJldHVybiBNYXRoLm1pbihNYXRoLm1heChudW0sIG1pbiA8IDEgPyAxIDogbWluKSwgbWF4KTtcclxufVxyXG5cclxuLyoqIFJldHVybnMgdHJ1ZSBpZiBib3RoIGl0ZW0xIGFuZCBpdGVtMiBLdGRHcmlkTGF5b3V0SXRlbXMgYXJlIGVxdWl2YWxlbnQuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBrdGRHcmlkSXRlbUxheW91dEl0ZW1BcmVFcXVhbChpdGVtMTogS3RkR3JpZExheW91dEl0ZW0sIGl0ZW0yOiBLdGRHcmlkTGF5b3V0SXRlbSk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIGl0ZW0xLmlkID09PSBpdGVtMi5pZFxyXG4gICAgICAgICYmIGl0ZW0xLnggPT09IGl0ZW0yLnhcclxuICAgICAgICAmJiBpdGVtMS55ID09PSBpdGVtMi55XHJcbiAgICAgICAgJiYgaXRlbTEudyA9PT0gaXRlbTIud1xyXG4gICAgICAgICYmIGl0ZW0xLmggPT09IGl0ZW0yLmhcclxufVxyXG4iXX0=