UNPKG

angular-grid-layout-ngx13

Version:

Grid Layout with draggable and resizable items for Angular

182 lines 32.6 kB
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; } /** * 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 screenXPosToGridValue(screenXPos, cols, width) { return Math.round((screenXPos * cols) / width); } function screenYPosToGridValue(screenYPos, rowHeight, height) { return Math.round(screenYPos / rowHeight); } /** 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; // Get layout item position const layoutItem = { ...draggingElemPrevItem, x: screenXPosToGridValue(gridRelXPos, config.cols, gridElemClientRect.width), y: screenYPosToGridValue(gridRelYPos, config.rowHeight, gridElemClientRect.height) }; // 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); // Get layout item grid position const layoutItem = { ...draggingElemPrevItem, w: screenXPosToGridValue(width, config.cols, gridElemClientRect.width), h: screenYPosToGridValue(height, config.rowHeight, gridElemClientRect.height) }; 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); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JpZC51dGlscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItZ3JpZC1sYXlvdXQvc3JjL2xpYi91dGlscy9ncmlkLnV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxPQUFPLEVBQWUsaUJBQWlCLEVBQXNCLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBRXJILE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBSXZFLDJIQUEySDtBQUMzSCxNQUFNLFVBQVUsWUFBWSxDQUFDLEtBQWEsRUFBRSxJQUFrQjtJQUMxRCxPQUFPLElBQUksQ0FBQyxFQUFFLENBQUM7QUFDbkIsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FBQyxNQUFxQixFQUFFLFdBQStCLEVBQUUsSUFBWTtJQUMvRixPQUFPLE9BQU8sQ0FBQyxNQUFNLEVBQUUsV0FBVyxFQUFFLElBQUksQ0FBQztRQUNyQyxvREFBb0Q7U0FDbkQsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQ3hKLENBQUM7QUFFRCxTQUFTLHFCQUFxQixDQUFDLFVBQWtCLEVBQUUsSUFBWSxFQUFFLEtBQWE7SUFDMUUsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDO0FBQ25ELENBQUM7QUFFRCxTQUFTLHFCQUFxQixDQUFDLFVBQWtCLEVBQUUsU0FBaUIsRUFBRSxNQUFjO0lBQ2hGLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEdBQUcsU0FBUyxDQUFDLENBQUM7QUFDOUMsQ0FBQztBQUVELHdJQUF3STtBQUN4SSxNQUFNLFVBQVUsb0JBQW9CLENBQUMsV0FBZ0MsRUFBRSxXQUFnQztJQUNuRyxNQUFNLElBQUksR0FBZ0UsRUFBRSxDQUFDO0lBRTdFLFdBQVcsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUU7UUFDeEIsTUFBTSxLQUFLLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ2pFLElBQUksS0FBSyxJQUFJLElBQUksRUFBRTtZQUNmLE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxDQUFDLEtBQUssS0FBSyxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsQ0FBQyxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDOUQsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxLQUFLLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxDQUFDLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FBQztZQUMvRCxNQUFNLE1BQU0sR0FBNEMsVUFBVSxJQUFJLFdBQVcsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUN2SixJQUFJLE1BQU0sRUFBRTtnQkFDUixJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUMsTUFBTSxFQUFDLENBQUM7YUFDN0I7U0FDSjtJQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxJQUFJLENBQUM7QUFDaEIsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxRQUE4QixFQUFFLE1BQWtCLEVBQUUsY0FBMkIsRUFBRSxZQUE2QjtJQUM5SSxNQUFNLEVBQUMsZ0JBQWdCLEVBQUUsZ0JBQWdCLEVBQUUsa0JBQWtCLEVBQUUsa0JBQWtCLEVBQUUsZ0JBQWdCLEVBQUMsR0FBRyxZQUFZLENBQUM7SUFFcEgsTUFBTSxVQUFVLEdBQUcsUUFBUSxDQUFDLEVBQUUsQ0FBQztJQUUvQixNQUFNLG9CQUFvQixHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxVQUFVLENBQUUsQ0FBQztJQUVqRixNQUFNLFlBQVksR0FBRyxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQ3pELE1BQU0sWUFBWSxHQUFHLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDekQsTUFBTSxPQUFPLEdBQUcsaUJBQWlCLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUNwRCxNQUFNLE9BQU8sR0FBRyxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBRXBELE1BQU0sT0FBTyxHQUFHLFlBQVksR0FBRyxrQkFBa0IsQ0FBQyxJQUFJLENBQUM7SUFDdkQsTUFBTSxPQUFPLEdBQUcsWUFBWSxHQUFHLGtCQUFrQixDQUFDLEdBQUcsQ0FBQztJQUV0RCxzR0FBc0c7SUFDdEcsTUFBTSx1QkFBdUIsR0FBRyxrQkFBa0IsQ0FBQyxJQUFJLEdBQUcsZ0JBQWdCLENBQUMsSUFBSSxDQUFDO0lBQ2hGLE1BQU0sc0JBQXNCLEdBQUcsa0JBQWtCLENBQUMsR0FBRyxHQUFHLGdCQUFnQixDQUFDLEdBQUcsQ0FBQztJQUU3RSxtREFBbUQ7SUFDbkQsTUFBTSxXQUFXLEdBQUcsT0FBTyxHQUFHLHVCQUF1QixHQUFHLE9BQU8sQ0FBQztJQUNoRSxNQUFNLFdBQVcsR0FBRyxPQUFPLEdBQUcsc0JBQXNCLEdBQUcsT0FBTyxDQUFDO0lBRS9ELDJCQUEyQjtJQUMzQixNQUFNLFVBQVUsR0FBc0I7UUFDbEMsR0FBRyxvQkFBb0I7UUFDdkIsQ0FBQyxFQUFFLHFCQUFxQixDQUFDLFdBQVcsRUFBRSxNQUFNLENBQUMsSUFBSSxFQUFFLGtCQUFrQixDQUFDLEtBQUssQ0FBQztRQUM1RSxDQUFDLEVBQUUscUJBQXFCLENBQUMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxTQUFTLEVBQUUsa0JBQWtCLENBQUMsTUFBTSxDQUFDO0tBQ3JGLENBQUM7SUFFRixrRkFBa0Y7SUFDbEYsVUFBVSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDekMsVUFBVSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDekMsSUFBSSxVQUFVLENBQUMsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxDQUFDLEdBQUcsTUFBTSxDQUFDLElBQUksRUFBRTtRQUMzQyxVQUFVLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxJQUFJLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQzFEO0lBRUQsMkVBQTJFO0lBQzNFLE1BQU0sV0FBVyxHQUFpQixNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ2hELE1BQU0saUJBQWlCLEdBQWUsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssVUFBVSxDQUFFLENBQUM7SUFFeEYsSUFBSSxjQUFjLEdBQWlCLFdBQVcsQ0FDMUMsV0FBVyxFQUNYLGlCQUFpQixFQUNqQixVQUFVLENBQUMsQ0FBQyxFQUNaLFVBQVUsQ0FBQyxDQUFDLEVBQ1osSUFBSSxFQUNKLE1BQU0sQ0FBQyxnQkFBZ0IsRUFDdkIsY0FBYyxFQUNkLE1BQU0sQ0FBQyxJQUFJLENBQ2QsQ0FBQztJQUVGLGNBQWMsR0FBRyxPQUFPLENBQUMsY0FBYyxFQUFFLGNBQWMsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFdEUsT0FBTztRQUNILE1BQU0sRUFBRSxjQUFjO1FBQ3RCLGNBQWMsRUFBRTtZQUNaLEdBQUcsRUFBRSxXQUFXO1lBQ2hCLElBQUksRUFBRSxXQUFXO1lBQ2pCLEtBQUssRUFBRSxrQkFBa0IsQ0FBQyxLQUFLO1lBQy9CLE1BQU0sRUFBRSxrQkFBa0IsQ0FBQyxNQUFNO1NBQ3BDO0tBQ0osQ0FBQztBQUNOLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsbUJBQW1CLENBQUMsUUFBOEIsRUFBRSxNQUFrQixFQUFFLGNBQTJCLEVBQUUsWUFBNkI7SUFDOUksTUFBTSxFQUFDLGdCQUFnQixFQUFFLGdCQUFnQixFQUFFLGtCQUFrQixFQUFFLGtCQUFrQixFQUFFLGdCQUFnQixFQUFDLEdBQUcsWUFBWSxDQUFDO0lBQ3BILE1BQU0sVUFBVSxHQUFHLFFBQVEsQ0FBQyxFQUFFLENBQUM7SUFFL0IsTUFBTSxZQUFZLEdBQUcsaUJBQWlCLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUN6RCxNQUFNLFlBQVksR0FBRyxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQ3pELE1BQU0sT0FBTyxHQUFHLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDcEQsTUFBTSxPQUFPLEdBQUcsaUJBQWlCLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUVwRCwyRkFBMkY7SUFDM0YsTUFBTSxpQkFBaUIsR0FBRyxrQkFBa0IsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxZQUFZLEdBQUcsa0JBQWtCLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDOUYsTUFBTSxpQkFBaUIsR0FBRyxrQkFBa0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxZQUFZLEdBQUcsa0JBQWtCLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFOUYsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssVUFBVSxDQUFFLENBQUM7SUFDakYsTUFBTSxLQUFLLEdBQUcsT0FBTyxHQUFHLGlCQUFpQixHQUFHLENBQUMsa0JBQWtCLENBQUMsSUFBSSxHQUFHLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzlGLE1BQU0sTUFBTSxHQUFHLE9BQU8sR0FBRyxpQkFBaUIsR0FBRyxDQUFDLGtCQUFrQixDQUFDLEdBQUcsR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUc3RixnQ0FBZ0M7SUFDaEMsTUFBTSxVQUFVLEdBQXNCO1FBQ2xDLEdBQUcsb0JBQW9CO1FBQ3ZCLENBQUMsRUFBRSxxQkFBcUIsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLElBQUksRUFBRSxrQkFBa0IsQ0FBQyxLQUFLLENBQUM7UUFDdEUsQ0FBQyxFQUFFLHFCQUFxQixDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsU0FBUyxFQUFFLGtCQUFrQixDQUFDLE1BQU0sQ0FBQztLQUNoRixDQUFDO0lBRUYsVUFBVSxDQUFDLENBQUMsR0FBRyxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxJQUFJLElBQUksVUFBVSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsSUFBSSxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN4SCxVQUFVLENBQUMsQ0FBQyxHQUFHLHNCQUFzQixDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLElBQUksSUFBSSxVQUFVLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxJQUFJLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRXhILElBQUksVUFBVSxDQUFDLENBQUMsR0FBRyxVQUFVLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxJQUFJLEVBQUU7UUFDM0MsVUFBVSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsSUFBSSxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUMxRDtJQUVELElBQUksTUFBTSxDQUFDLGdCQUFnQixFQUFFO1FBQ3pCLE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUM7UUFDMUIsTUFBTSxJQUFJLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQztRQUUxQixJQUFJLFNBQVMsR0FBRyxZQUFZLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsQ0FBQztRQUN4RCxJQUFJLGVBQXNDLENBQUM7UUFFM0MsT0FBTyxTQUFTLEVBQUU7WUFDZCxlQUFlLEdBQUcsb0JBQW9CLENBQUMsVUFBVSxFQUFFLGVBQWUsQ0FBQyxDQUFDO1lBQ3BFLFVBQVUsQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO1lBQzlCLFNBQVMsR0FBRyxZQUFZLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsQ0FBQztTQUN2RDtRQUVELElBQUksZUFBZSxLQUFLLEdBQUcsRUFBRTtZQUN6QixVQUFVLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQztZQUVwQixTQUFTLEdBQUcsWUFBWSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDcEQsT0FBTyxTQUFTLEVBQUU7Z0JBQ2QsVUFBVSxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUNmLFNBQVMsR0FBRyxZQUFZLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsQ0FBQzthQUN2RDtTQUNKO1FBQ0QsSUFBSSxlQUFlLEtBQUssR0FBRyxFQUFFO1lBQ3pCLFVBQVUsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDO1lBRXBCLFNBQVMsR0FBRyxZQUFZLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsQ0FBQztZQUNwRCxPQUFPLFNBQVMsRUFBRTtnQkFDZCxVQUFVLENBQUMsQ0FBQyxFQUFFLENBQUM7Z0JBQ2YsU0FBUyxHQUFHLFlBQVksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLFVBQVUsQ0FBQyxDQUFDO2FBQ3ZEO1NBQ0o7S0FFSjtJQUVELE1BQU0sY0FBYyxHQUFpQixNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1FBQzVELE9BQU8sSUFBSSxDQUFDLEVBQUUsS0FBSyxVQUFVLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQ3RELENBQUMsQ0FBQyxDQUFDO0lBRUgsT0FBTztRQUNILE1BQU0sRUFBRSxPQUFPLENBQUMsY0FBYyxFQUFFLGNBQWMsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDO1FBQzVELGNBQWMsRUFBRTtZQUNaLEdBQUcsRUFBRSxrQkFBa0IsQ0FBQyxHQUFHLEdBQUcsa0JBQWtCLENBQUMsR0FBRztZQUNwRCxJQUFJLEVBQUUsa0JBQWtCLENBQUMsSUFBSSxHQUFHLGtCQUFrQixDQUFDLElBQUk7WUFDdkQsS0FBSztZQUNMLE1BQU07U0FDVDtLQUNKLENBQUM7QUFDTixDQUFDO0FBRUQsU0FBUyxZQUFZLENBQUMsTUFBYyxFQUFFLFVBQXNCO0lBQ3hELE9BQU8sQ0FBQyxDQUFDLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsQ0FBQztBQUNuRCxDQUFDO0FBRUQsU0FBUyxvQkFBb0IsQ0FBQyxVQUFVLEVBQUUsVUFBVTtJQUNoRCxJQUFJLFVBQVUsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFO1FBQ25CLE9BQU8sR0FBRyxDQUFDO0tBQ2Q7SUFDRCxJQUFJLFVBQVUsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFO1FBQ25CLE9BQU8sR0FBRyxDQUFDO0tBQ2Q7SUFFRCxPQUFPLFVBQVUsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO0FBQzFDLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQVMsc0JBQXNCLENBQUMsR0FBVyxFQUFFLE1BQWMsQ0FBQyxFQUFFLE1BQWMsUUFBUTtJQUNoRixPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztBQUMzRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY29tcGFjdCwgQ29tcGFjdFR5cGUsIGdldEZpcnN0Q29sbGlzaW9uLCBMYXlvdXQsIExheW91dEl0ZW0sIG1vdmVFbGVtZW50IH0gZnJvbSAnLi9yZWFjdC1ncmlkLWxheW91dC51dGlscyc7XG5pbXBvcnQgeyBLdGREcmFnZ2luZ0RhdGEsIEt0ZEdyaWRDZmcsIEt0ZEdyaWRDb21wYWN0VHlwZSwgS3RkR3JpZEl0ZW1SZWN0LCBLdGRHcmlkTGF5b3V0LCBLdGRHcmlkTGF5b3V0SXRlbSB9IGZyb20gJy4uL2dyaWQuZGVmaW5pdGlvbnMnO1xuaW1wb3J0IHsga3RkUG9pbnRlckNsaWVudFgsIGt0ZFBvaW50ZXJDbGllbnRZIH0gZnJvbSAnLi9wb2ludGVyLnV0aWxzJztcbmltcG9ydCB7IEt0ZERpY3Rpb25hcnkgfSBmcm9tICcuLi8uLi90eXBlcyc7XG5pbXBvcnQgeyBLdGRHcmlkSXRlbUNvbXBvbmVudCB9IGZyb20gJy4uL2dyaWQtaXRlbS9ncmlkLWl0ZW0uY29tcG9uZW50JztcblxuLyoqIFRyYWNrcyBpdGVtcyBieSBpZC4gVGhpcyBmdW5jdGlvbiBpcyBtZWFuIHRvIGJlIHVzZWQgaW4gY29uanVuY3Rpb24gd2l0aCB0aGUgbmdGb3IgdGhhdCByZW5kZXJzIHRoZSAna3RkLWdyaWQtaXRlbXMnICovXG5leHBvcnQgZnVuY3Rpb24ga3RkVHJhY2tCeUlkKGluZGV4OiBudW1iZXIsIGl0ZW06IHtpZDogc3RyaW5nfSkge1xuICAgIHJldHVybiBpdGVtLmlkO1xufVxuXG4vKipcbiAqIENhbGwgcmVhY3QtZ3JpZC1sYXlvdXQgdXRpbHMgJ2NvbXBhY3QoKScgZnVuY3Rpb24gYW5kIHJldHVybiB0aGUgY29tcGFjdGVkIGxheW91dC5cbiAqIEBwYXJhbSBsYXlvdXQgdG8gYmUgY29tcGFjdGVkLlxuICogQHBhcmFtIGNvbXBhY3RUeXBlLCB0eXBlIG9mIGNvbXBhY3Rpb24uXG4gKiBAcGFyYW0gY29scywgbnVtYmVyIG9mIGNvbHVtbnMgb2YgdGhlIGdyaWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBrdGRHcmlkQ29tcGFjdChsYXlvdXQ6IEt0ZEdyaWRMYXlvdXQsIGNvbXBhY3RUeXBlOiBLdGRHcmlkQ29tcGFjdFR5cGUsIGNvbHM6IG51bWJlcik6IEt0ZEdyaWRMYXlvdXQge1xuICAgIHJldHVybiBjb21wYWN0KGxheW91dCwgY29tcGFjdFR5cGUsIGNvbHMpXG4gICAgICAgIC8vIFBydW5lIHJlYWN0LWdyaWQtbGF5b3V0IGNvbXBhY3QgZXh0cmEgcHJvcGVydGllcy5cbiAgICAgICAgLm1hcChpdGVtID0+ICh7IGlkOiBpdGVtLmlkLCB4OiBpdGVtLngsIHk6IGl0ZW0ueSwgdzogaXRlbS53LCBoOiBpdGVtLmgsIG1pblc6IGl0ZW0ubWluVywgbWluSDogaXRlbS5taW5ILCBtYXhXOiBpdGVtLm1heFcsIG1heEg6IGl0ZW0ubWF4SCB9KSk7XG59XG5cbmZ1bmN0aW9uIHNjcmVlblhQb3NUb0dyaWRWYWx1ZShzY3JlZW5YUG9zOiBudW1iZXIsIGNvbHM6IG51bWJlciwgd2lkdGg6IG51bWJlcik6IG51bWJlciB7XG4gICAgcmV0dXJuIE1hdGgucm91bmQoKHNjcmVlblhQb3MgKiBjb2xzKSAvIHdpZHRoKTtcbn1cblxuZnVuY3Rpb24gc2NyZWVuWVBvc1RvR3JpZFZhbHVlKHNjcmVlbllQb3M6IG51bWJlciwgcm93SGVpZ2h0OiBudW1iZXIsIGhlaWdodDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZChzY3JlZW5ZUG9zIC8gcm93SGVpZ2h0KTtcbn1cblxuLyoqIFJldHVybnMgYSBEaWN0aW9uYXJ5IHdoZXJlIHRoZSBrZXkgaXMgdGhlIGlkIGFuZCB0aGUgdmFsdWUgaXMgdGhlIGNoYW5nZSBhcHBsaWVkIHRvIHRoYXQgaXRlbS4gSWYgbm8gY2hhbmdlcyBEaWN0aW9uYXJ5IGlzIGVtcHR5LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGt0ZEdldEdyaWRMYXlvdXREaWZmKGdyaWRMYXlvdXRBOiBLdGRHcmlkTGF5b3V0SXRlbVtdLCBncmlkTGF5b3V0QjogS3RkR3JpZExheW91dEl0ZW1bXSk6IEt0ZERpY3Rpb25hcnk8eyBjaGFuZ2U6ICdtb3ZlJyB8ICdyZXNpemUnIHwgJ21vdmVyZXNpemUnIH0+IHtcbiAgICBjb25zdCBkaWZmOiBLdGREaWN0aW9uYXJ5PHsgY2hhbmdlOiAnbW92ZScgfCAncmVzaXplJyB8ICdtb3ZlcmVzaXplJyB9PiA9IHt9O1xuXG4gICAgZ3JpZExheW91dEEuZm9yRWFjaChpdGVtQSA9PiB7XG4gICAgICAgIGNvbnN0IGl0ZW1CID0gZ3JpZExheW91dEIuZmluZChfaXRlbUIgPT4gX2l0ZW1CLmlkID09PSBpdGVtQS5pZCk7XG4gICAgICAgIGlmIChpdGVtQiAhPSBudWxsKSB7XG4gICAgICAgICAgICBjb25zdCBwb3NDaGFuZ2VkID0gaXRlbUEueCAhPT0gaXRlbUIueCB8fCBpdGVtQS55ICE9PSBpdGVtQi55O1xuICAgICAgICAgICAgY29uc3Qgc2l6ZUNoYW5nZWQgPSBpdGVtQS53ICE9PSBpdGVtQi53IHx8IGl0ZW1BLmggIT09IGl0ZW1CLmg7XG4gICAgICAgICAgICBjb25zdCBjaGFuZ2U6ICdtb3ZlJyB8ICdyZXNpemUnIHwgJ21vdmVyZXNpemUnIHwgbnVsbCA9IHBvc0NoYW5nZWQgJiYgc2l6ZUNoYW5nZWQgPyAnbW92ZXJlc2l6ZScgOiBwb3NDaGFuZ2VkID8gJ21vdmUnIDogc2l6ZUNoYW5nZWQgPyAncmVzaXplJyA6IG51bGw7XG4gICAgICAgICAgICBpZiAoY2hhbmdlKSB7XG4gICAgICAgICAgICAgICAgZGlmZltpdGVtQi5pZF0gPSB7Y2hhbmdlfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBkaWZmO1xufVxuXG4vKipcbiAqIEdpdmVuIHRoZSBncmlkIGNvbmZpZyAmIGxheW91dCBkYXRhIGFuZCB0aGUgY3VycmVudCBkcmFnIHBvc2l0aW9uICYgaW5mb3JtYXRpb24sIHJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmcgbGF5b3V0IGFuZCBkcmFnIGl0ZW0gcG9zaXRpb25cbiAqIEBwYXJhbSBncmlkSXRlbSBncmlkIGl0ZW0gdGhhdCBpcyBiZWVuIGRyYWdnZWRcbiAqIEBwYXJhbSBjb25maWcgY3VycmVudCBncmlkIGNvbmZpZ3VyYXRpb25cbiAqIEBwYXJhbSBjb21wYWN0aW9uVHlwZSB0eXBlIG9mIGNvbXBhY3Rpb24gdGhhdCB3aWxsIGJlIHBlcmZvcm1lZFxuICogQHBhcmFtIGRyYWdnaW5nRGF0YSBjb250YWlucyBhbGwgdGhlIGluZm9ybWF0aW9uIGFib3V0IHRoZSBkcmFnXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBrdGRHcmlkSXRlbURyYWdnaW5nKGdyaWRJdGVtOiBLdGRHcmlkSXRlbUNvbXBvbmVudCwgY29uZmlnOiBLdGRHcmlkQ2ZnLCBjb21wYWN0aW9uVHlwZTogQ29tcGFjdFR5cGUsIGRyYWdnaW5nRGF0YTogS3RkRHJhZ2dpbmdEYXRhKTogeyBsYXlvdXQ6IEt0ZEdyaWRMYXlvdXRJdGVtW107IGRyYWdnZWRJdGVtUG9zOiBLdGRHcmlkSXRlbVJlY3QgfSB7XG4gICAgY29uc3Qge3BvaW50ZXJEb3duRXZlbnQsIHBvaW50ZXJEcmFnRXZlbnQsIGdyaWRFbGVtQ2xpZW50UmVjdCwgZHJhZ0VsZW1DbGllbnRSZWN0LCBzY3JvbGxEaWZmZXJlbmNlfSA9IGRyYWdnaW5nRGF0YTtcblxuICAgIGNvbnN0IGdyaWRJdGVtSWQgPSBncmlkSXRlbS5pZDtcblxuICAgIGNvbnN0IGRyYWdnaW5nRWxlbVByZXZJdGVtID0gY29uZmlnLmxheW91dC5maW5kKGl0ZW0gPT4gaXRlbS5pZCA9PT0gZ3JpZEl0ZW1JZCkhO1xuXG4gICAgY29uc3QgY2xpZW50U3RhcnRYID0ga3RkUG9pbnRlckNsaWVudFgocG9pbnRlckRvd25FdmVudCk7XG4gICAgY29uc3QgY2xpZW50U3RhcnRZID0ga3RkUG9pbnRlckNsaWVudFkocG9pbnRlckRvd25FdmVudCk7XG4gICAgY29uc3QgY2xpZW50WCA9IGt0ZFBvaW50ZXJDbGllbnRYKHBvaW50ZXJEcmFnRXZlbnQpO1xuICAgIGNvbnN0IGNsaWVudFkgPSBrdGRQb2ludGVyQ2xpZW50WShwb2ludGVyRHJhZ0V2ZW50KTtcblxuICAgIGNvbnN0IG9mZnNldFggPSBjbGllbnRTdGFydFggLSBkcmFnRWxlbUNsaWVudFJlY3QubGVmdDtcbiAgICBjb25zdCBvZmZzZXRZID0gY2xpZW50U3RhcnRZIC0gZHJhZ0VsZW1DbGllbnRSZWN0LnRvcDtcblxuICAgIC8vIEdyaWQgZWxlbWVudCBwb3NpdGlvbnMgdGFraW5nIGludG8gYWNjb3VudCB0aGUgcG9zc2libGUgc2Nyb2xsIHRvdGFsIGRpZmZlcmVuY2UgZnJvbSB0aGUgYmVnaW5uaW5nLlxuICAgIGNvbnN0IGdyaWRFbGVtZW50TGVmdFBvc2l0aW9uID0gZ3JpZEVsZW1DbGllbnRSZWN0LmxlZnQgKyBzY3JvbGxEaWZmZXJlbmNlLmxlZnQ7XG4gICAgY29uc3QgZ3JpZEVsZW1lbnRUb3BQb3NpdGlvbiA9IGdyaWRFbGVtQ2xpZW50UmVjdC50b3AgKyBzY3JvbGxEaWZmZXJlbmNlLnRvcDtcblxuICAgIC8vIENhbGN1bGF0ZSBwb3NpdGlvbiByZWxhdGl2ZSB0byB0aGUgZ3JpZCBlbGVtZW50LlxuICAgIGNvbnN0IGdyaWRSZWxYUG9zID0gY2xpZW50WCAtIGdyaWRFbGVtZW50TGVmdFBvc2l0aW9uIC0gb2Zmc2V0WDtcbiAgICBjb25zdCBncmlkUmVsWVBvcyA9IGNsaWVudFkgLSBncmlkRWxlbWVudFRvcFBvc2l0aW9uIC0gb2Zmc2V0WTtcblxuICAgIC8vIEdldCBsYXlvdXQgaXRlbSBwb3NpdGlvblxuICAgIGNvbnN0IGxheW91dEl0ZW06IEt0ZEdyaWRMYXlvdXRJdGVtID0ge1xuICAgICAgICAuLi5kcmFnZ2luZ0VsZW1QcmV2SXRlbSxcbiAgICAgICAgeDogc2NyZWVuWFBvc1RvR3JpZFZhbHVlKGdyaWRSZWxYUG9zLCBjb25maWcuY29scywgZ3JpZEVsZW1DbGllbnRSZWN0LndpZHRoKSxcbiAgICAgICAgeTogc2NyZWVuWVBvc1RvR3JpZFZhbHVlKGdyaWRSZWxZUG9zLCBjb25maWcucm93SGVpZ2h0LCBncmlkRWxlbUNsaWVudFJlY3QuaGVpZ2h0KVxuICAgIH07XG5cbiAgICAvLyBDb3JyZWN0IHRoZSB2YWx1ZXMgaWYgdGhleSBvdmVyZmxvdywgc2luY2UgJ21vdmVFbGVtZW50JyBmdW5jdGlvbiBkb2Vzbid0IGRvIGl0XG4gICAgbGF5b3V0SXRlbS54ID0gTWF0aC5tYXgoMCwgbGF5b3V0SXRlbS54KTtcbiAgICBsYXlvdXRJdGVtLnkgPSBNYXRoLm1heCgwLCBsYXlvdXRJdGVtLnkpO1xuICAgIGlmIChsYXlvdXRJdGVtLnggKyBsYXlvdXRJdGVtLncgPiBjb25maWcuY29scykge1xuICAgICAgICBsYXlvdXRJdGVtLnggPSBNYXRoLm1heCgwLCBjb25maWcuY29scyAtIGxheW91dEl0ZW0udyk7XG4gICAgfVxuXG4gICAgLy8gUGFyc2UgdG8gTGF5b3V0SXRlbSBhcnJheSBkYXRhIGluIG9yZGVyIHRvIHVzZSAncmVhY3QuZ3JpZC1sYXlvdXQnIHV0aWxzXG4gICAgY29uc3QgbGF5b3V0SXRlbXM6IExheW91dEl0ZW1bXSA9IGNvbmZpZy5sYXlvdXQ7XG4gICAgY29uc3QgZHJhZ2dlZExheW91dEl0ZW06IExheW91dEl0ZW0gPSBsYXlvdXRJdGVtcy5maW5kKGl0ZW0gPT4gaXRlbS5pZCA9PT0gZ3JpZEl0ZW1JZCkhO1xuXG4gICAgbGV0IG5ld0xheW91dEl0ZW1zOiBMYXlvdXRJdGVtW10gPSBtb3ZlRWxlbWVudChcbiAgICAgICAgbGF5b3V0SXRlbXMsXG4gICAgICAgIGRyYWdnZWRMYXlvdXRJdGVtLFxuICAgICAgICBsYXlvdXRJdGVtLngsXG4gICAgICAgIGxheW91dEl0ZW0ueSxcbiAgICAgICAgdHJ1ZSxcbiAgICAgICAgY29uZmlnLnByZXZlbnRDb2xsaXNpb24sXG4gICAgICAgIGNvbXBhY3Rpb25UeXBlLFxuICAgICAgICBjb25maWcuY29sc1xuICAgICk7XG5cbiAgICBuZXdMYXlvdXRJdGVtcyA9IGNvbXBhY3QobmV3TGF5b3V0SXRlbXMsIGNvbXBhY3Rpb25UeXBlLCBjb25maWcuY29scyk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBsYXlvdXQ6IG5ld0xheW91dEl0ZW1zLFxuICAgICAgICBkcmFnZ2VkSXRlbVBvczoge1xuICAgICAgICAgICAgdG9wOiBncmlkUmVsWVBvcyxcbiAgICAgICAgICAgIGxlZnQ6IGdyaWRSZWxYUG9zLFxuICAgICAgICAgICAgd2lkdGg6IGRyYWdFbGVtQ2xpZW50UmVjdC53aWR0aCxcbiAgICAgICAgICAgIGhlaWdodDogZHJhZ0VsZW1DbGllbnRSZWN0LmhlaWdodCxcbiAgICAgICAgfVxuICAgIH07XG59XG5cbi8qKlxuICogR2l2ZW4gdGhlIGdyaWQgY29uZmlnICYgbGF5b3V0IGRhdGEgYW5kIHRoZSBjdXJyZW50IGRyYWcgcG9zaXRpb24gJiBpbmZvcm1hdGlvbiwgcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZyBsYXlvdXQgYW5kIGRyYWcgaXRlbSBwb3NpdGlvblxuICogQHBhcmFtIGdyaWRJdGVtIGdyaWQgaXRlbSB0aGF0IGlzIGJlZW4gZHJhZ2dlZFxuICogQHBhcmFtIGNvbmZpZyBjdXJyZW50IGdyaWQgY29uZmlndXJhdGlvblxuICogQHBhcmFtIGNvbXBhY3Rpb25UeXBlIHR5cGUgb2YgY29tcGFjdGlvbiB0aGF0IHdpbGwgYmUgcGVyZm9ybWVkXG4gKiBAcGFyYW0gZHJhZ2dpbmdEYXRhIGNvbnRhaW5zIGFsbCB0aGUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGRyYWdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGt0ZEdyaWRJdGVtUmVzaXppbmcoZ3JpZEl0ZW06IEt0ZEdyaWRJdGVtQ29tcG9uZW50LCBjb25maWc6IEt0ZEdyaWRDZmcsIGNvbXBhY3Rpb25UeXBlOiBDb21wYWN0VHlwZSwgZHJhZ2dpbmdEYXRhOiBLdGREcmFnZ2luZ0RhdGEpOiB7IGxheW91dDogS3RkR3JpZExheW91dEl0ZW1bXTsgZHJhZ2dlZEl0ZW1Qb3M6IEt0ZEdyaWRJdGVtUmVjdCB9IHtcbiAgICBjb25zdCB7cG9pbnRlckRvd25FdmVudCwgcG9pbnRlckRyYWdFdmVudCwgZ3JpZEVsZW1DbGllbnRSZWN0LCBkcmFnRWxlbUNsaWVudFJlY3QsIHNjcm9sbERpZmZlcmVuY2V9ID0gZHJhZ2dpbmdEYXRhO1xuICAgIGNvbnN0IGdyaWRJdGVtSWQgPSBncmlkSXRlbS5pZDtcblxuICAgIGNvbnN0IGNsaWVudFN0YXJ0WCA9IGt0ZFBvaW50ZXJDbGllbnRYKHBvaW50ZXJEb3duRXZlbnQpO1xuICAgIGNvbnN0IGNsaWVudFN0YXJ0WSA9IGt0ZFBvaW50ZXJDbGllbnRZKHBvaW50ZXJEb3duRXZlbnQpO1xuICAgIGNvbnN0IGNsaWVudFggPSBrdGRQb2ludGVyQ2xpZW50WChwb2ludGVyRHJhZ0V2ZW50KTtcbiAgICBjb25zdCBjbGllbnRZID0ga3RkUG9pbnRlckNsaWVudFkocG9pbnRlckRyYWdFdmVudCk7XG5cbiAgICAvLyBHZXQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbW91c2VEb3duIGFuZCB0aGUgcG9zaXRpb24gJ3JpZ2h0JyBvZiB0aGUgcmVzaXplIGVsZW1lbnQuXG4gICAgY29uc3QgcmVzaXplRWxlbU9mZnNldFggPSBkcmFnRWxlbUNsaWVudFJlY3Qud2lkdGggLSAoY2xpZW50U3RhcnRYIC0gZHJhZ0VsZW1DbGllbnRSZWN0LmxlZnQpO1xuICAgIGNvbnN0IHJlc2l6ZUVsZW1PZmZzZXRZID0gZHJhZ0VsZW1DbGllbnRSZWN0LmhlaWdodCAtIChjbGllbnRTdGFydFkgLSBkcmFnRWxlbUNsaWVudFJlY3QudG9wKTtcblxuICAgIGNvbnN0IGRyYWdnaW5nRWxlbVByZXZJdGVtID0gY29uZmlnLmxheW91dC5maW5kKGl0ZW0gPT4gaXRlbS5pZCA9PT0gZ3JpZEl0ZW1JZCkhO1xuICAgIGNvbnN0IHdpZHRoID0gY2xpZW50WCArIHJlc2l6ZUVsZW1PZmZzZXRYIC0gKGRyYWdFbGVtQ2xpZW50UmVjdC5sZWZ0ICsgc2Nyb2xsRGlmZmVyZW5jZS5sZWZ0KTtcbiAgICBjb25zdCBoZWlnaHQgPSBjbGllbnRZICsgcmVzaXplRWxlbU9mZnNldFkgLSAoZHJhZ0VsZW1DbGllbnRSZWN0LnRvcCArIHNjcm9sbERpZmZlcmVuY2UudG9wKTtcblxuXG4gICAgLy8gR2V0IGxheW91dCBpdGVtIGdyaWQgcG9zaXRpb25cbiAgICBjb25zdCBsYXlvdXRJdGVtOiBLdGRHcmlkTGF5b3V0SXRlbSA9IHtcbiAgICAgICAgLi4uZHJhZ2dpbmdFbGVtUHJldkl0ZW0sXG4gICAgICAgIHc6IHNjcmVlblhQb3NUb0dyaWRWYWx1ZSh3aWR0aCwgY29uZmlnLmNvbHMsIGdyaWRFbGVtQ2xpZW50UmVjdC53aWR0aCksXG4gICAgICAgIGg6IHNjcmVlbllQb3NUb0dyaWRWYWx1ZShoZWlnaHQsIGNvbmZpZy5yb3dIZWlnaHQsIGdyaWRFbGVtQ2xpZW50UmVjdC5oZWlnaHQpXG4gICAgfTtcblxuICAgIGxheW91dEl0ZW0udyA9IGxpbWl0TnVtYmVyV2l0aGluUmFuZ2UobGF5b3V0SXRlbS53LCBncmlkSXRlbS5taW5XID8/IGxheW91dEl0ZW0ubWluVywgZ3JpZEl0ZW0ubWF4VyA/PyBsYXlvdXRJdGVtLm1heFcpO1xuICAgIGxheW91dEl0ZW0uaCA9IGxpbWl0TnVtYmVyV2l0aGluUmFuZ2UobGF5b3V0SXRlbS5oLCBncmlkSXRlbS5taW5IID8/IGxheW91dEl0ZW0ubWluSCwgZ3JpZEl0ZW0ubWF4SCA/PyBsYXlvdXRJdGVtLm1heEgpO1xuXG4gICAgaWYgKGxheW91dEl0ZW0ueCArIGxheW91dEl0ZW0udyA+IGNvbmZpZy5jb2xzKSB7XG4gICAgICAgIGxheW91dEl0ZW0udyA9IE1hdGgubWF4KDEsIGNvbmZpZy5jb2xzIC0gbGF5b3V0SXRlbS54KTtcbiAgICB9XG5cbiAgICBpZiAoY29uZmlnLnByZXZlbnRDb2xsaXNpb24pIHtcbiAgICAgICAgY29uc3QgbWF4VyA9IGxheW91dEl0ZW0udztcbiAgICAgICAgY29uc3QgbWF4SCA9IGxheW91dEl0ZW0uaDtcblxuICAgICAgICBsZXQgY29sbGlkaW5nID0gaGFzQ29sbGlzaW9uKGNvbmZpZy5sYXlvdXQsIGxheW91dEl0ZW0pO1xuICAgICAgICBsZXQgc2hydW5rRGltZW5zaW9uOiAndycgfCAnaCcgfCB1bmRlZmluZWQ7XG5cbiAgICAgICAgd2hpbGUgKGNvbGxpZGluZykge1xuICAgICAgICAgICAgc2hydW5rRGltZW5zaW9uID0gZ2V0RGltZW5zaW9uVG9TaHJpbmsobGF5b3V0SXRlbSwgc2hydW5rRGltZW5zaW9uKTtcbiAgICAgICAgICAgIGxheW91dEl0ZW1bc2hydW5rRGltZW5zaW9uXS0tO1xuICAgICAgICAgICAgY29sbGlkaW5nID0gaGFzQ29sbGlzaW9uKGNvbmZpZy5sYXlvdXQsIGxheW91dEl0ZW0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNocnVua0RpbWVuc2lvbiA9PT0gJ3cnKSB7XG4gICAgICAgICAgICBsYXlvdXRJdGVtLmggPSBtYXhIO1xuXG4gICAgICAgICAgICBjb2xsaWRpbmcgPSBoYXNDb2xsaXNpb24oY29uZmlnLmxheW91dCwgbGF5b3V0SXRlbSk7XG4gICAgICAgICAgICB3aGlsZSAoY29sbGlkaW5nKSB7XG4gICAgICAgICAgICAgICAgbGF5b3V0SXRlbS5oLS07XG4gICAgICAgICAgICAgICAgY29sbGlkaW5nID0gaGFzQ29sbGlzaW9uKGNvbmZpZy5sYXlvdXQsIGxheW91dEl0ZW0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChzaHJ1bmtEaW1lbnNpb24gPT09ICdoJykge1xuICAgICAgICAgICAgbGF5b3V0SXRlbS53ID0gbWF4VztcblxuICAgICAgICAgICAgY29sbGlkaW5nID0gaGFzQ29sbGlzaW9uKGNvbmZpZy5sYXlvdXQsIGxheW91dEl0ZW0pO1xuICAgICAgICAgICAgd2hpbGUgKGNvbGxpZGluZykge1xuICAgICAgICAgICAgICAgIGxheW91dEl0ZW0udy0tO1xuICAgICAgICAgICAgICAgIGNvbGxpZGluZyA9IGhhc0NvbGxpc2lvbihjb25maWcubGF5b3V0LCBsYXlvdXRJdGVtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgfVxuXG4gICAgY29uc3QgbmV3TGF5b3V0SXRlbXM6IExheW91dEl0ZW1bXSA9IGNvbmZpZy5sYXlvdXQubWFwKChpdGVtKSA9PiB7XG4gICAgICAgIHJldHVybiBpdGVtLmlkID09PSBncmlkSXRlbUlkID8gbGF5b3V0SXRlbSA6IGl0ZW07XG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBsYXlvdXQ6IGNvbXBhY3QobmV3TGF5b3V0SXRlbXMsIGNvbXBhY3Rpb25UeXBlLCBjb25maWcuY29scyksXG4gICAgICAgIGRyYWdnZWRJdGVtUG9zOiB7XG4gICAgICAgICAgICB0b3A6IGRyYWdFbGVtQ2xpZW50UmVjdC50b3AgLSBncmlkRWxlbUNsaWVudFJlY3QudG9wLFxuICAgICAgICAgICAgbGVmdDogZHJhZ0VsZW1DbGllbnRSZWN0LmxlZnQgLSBncmlkRWxlbUNsaWVudFJlY3QubGVmdCxcbiAgICAgICAgICAgIHdpZHRoLFxuICAgICAgICAgICAgaGVpZ2h0LFxuICAgICAgICB9XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gaGFzQ29sbGlzaW9uKGxheW91dDogTGF5b3V0LCBsYXlvdXRJdGVtOiBMYXlvdXRJdGVtKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhZ2V0Rmlyc3RDb2xsaXNpb24obGF5b3V0LCBsYXlvdXRJdGVtKTtcbn1cblxuZnVuY3Rpb24gZ2V0RGltZW5zaW9uVG9TaHJpbmsobGF5b3V0SXRlbSwgbGFzdFNocnVuayk6ICd3JyB8ICdoJyB7XG4gICAgaWYgKGxheW91dEl0ZW0uaCA8PSAxKSB7XG4gICAgICAgIHJldHVybiAndyc7XG4gICAgfVxuICAgIGlmIChsYXlvdXRJdGVtLncgPD0gMSkge1xuICAgICAgICByZXR1cm4gJ2gnO1xuICAgIH1cblxuICAgIHJldHVybiBsYXN0U2hydW5rID09PSAndycgPyAnaCcgOiAndyc7XG59XG5cbi8qKlxuICogR2l2ZW4gdGhlIGN1cnJlbnQgbnVtYmVyIGFuZCBtaW4vbWF4IHZhbHVlcywgcmV0dXJucyB0aGUgbnVtYmVyIHdpdGhpbiB0aGUgcmFuZ2VcbiAqIEBwYXJhbSBudW1iZXIgY2FuIGJlIGFueSBudW1lcmljIHZhbHVlXG4gKiBAcGFyYW0gbWluIG1pbmltdW0gdmFsdWUgb2YgcmFuZ2VcbiAqIEBwYXJhbSBtYXggbWF4aW11bSB2YWx1ZSBvZiByYW5nZVxuICovXG5mdW5jdGlvbiBsaW1pdE51bWJlcldpdGhpblJhbmdlKG51bTogbnVtYmVyLCBtaW46IG51bWJlciA9IDEsIG1heDogbnVtYmVyID0gSW5maW5pdHkpIHtcbiAgICByZXR1cm4gTWF0aC5taW4oTWF0aC5tYXgobnVtLCBtaW4gPCAxID8gMSA6IG1pbiksIG1heCk7XG59XG4iXX0=