UNPKG

react-planner-viewer

Version:

react-planner-viewer is a React Component for view plans builded with react-planner in 2D mode

328 lines (257 loc) 44.7 kB
import { List, Map } from 'immutable'; import { SELECT_TOOL_DRAWING_HOLE, UPDATE_DRAWING_HOLE, END_DRAWING_HOLE, BEGIN_DRAGGING_HOLE, UPDATE_DRAGGING_HOLE, END_DRAGGING_HOLE, SELECT_HOLE, MODE_IDLE, MODE_DRAWING_HOLE, MODE_DRAGGING_HOLE } from '../constants'; import * as Geometry from '../utils/geometry'; import { select, unselect, unselectAll, addHole, removeHole } from '../utils/layer-operations'; import { nearestSnap, addPointSnap, addLineSnap, addLineSegmentSnap, SNAP_POINT, SNAP_LINE, SNAP_SEGMENT } from '../utils/snap'; export default function (state, action) { switch (action.type) { case SELECT_TOOL_DRAWING_HOLE: return selectToolDrawingHole(state, action.sceneComponentType); case UPDATE_DRAWING_HOLE: return updateDrawingHole(state, action.layerID, action.x, action.y); case END_DRAWING_HOLE: return endDrawingHole(state, action.layerID, action.x, action.y); case BEGIN_DRAGGING_HOLE: return beginDraggingHole(state, action.layerID, action.holeID, action.x, action.y); case UPDATE_DRAGGING_HOLE: return updateDraggingHole(state, action.x, action.y); case END_DRAGGING_HOLE: return endDraggingHole(state, action.x, action.y); case SELECT_HOLE: return selectHole(state, action.layerID, action.holeID); default: return state; } } function selectToolDrawingHole(state, sceneComponentType) { var snapElements = new List().withMutations(function (snapElements) { var _state$getIn = state.getIn(['scene', 'layers', state.scene.selectedLayer]), lines = _state$getIn.lines, vertices = _state$getIn.vertices; lines.forEach(function (line) { var _vertices$get = vertices.get(line.vertices.get(0)), x1 = _vertices$get.x, y1 = _vertices$get.y; var _vertices$get2 = vertices.get(line.vertices.get(1)), x2 = _vertices$get2.x, y2 = _vertices$get2.y; addLineSegmentSnap(snapElements, x1, y1, x2, y2, 20, 1, line.id); }); }); return state.merge({ mode: MODE_DRAWING_HOLE, snapElements: snapElements, drawingSupport: Map({ type: sceneComponentType }) }); } /** holes operations **/ function updateDrawingHole(state, layerID, x, y) { var catalog = state.catalog; //calculate snap and overwrite coords if needed //force snap to segment var snap = nearestSnap(state.snapElements, x, y, state.snapMask.merge({ SNAP_SEGMENT: true })); if (snap) { ; var _snap$point = snap.point; x = _snap$point.x; y = _snap$point.y; }var scene = state.scene.updateIn(['layers', layerID], function (layer) { return layer.withMutations(function (layer) { var selectedHole = layer.getIn(['selected', 'holes']).first(); if (selectedHole) { unselect(layer, 'holes', selectedHole); removeHole(layer, selectedHole); } if (snap) { var lineID = snap.snap.related.get(0); var line = layer.getIn(['lines', lineID]); var _layer$vertices$get = layer.vertices.get(line.vertices.get(0)), x1 = _layer$vertices$get.x, y1 = _layer$vertices$get.y; var _layer$vertices$get2 = layer.vertices.get(line.vertices.get(1)), x2 = _layer$vertices$get2.x, y2 = _layer$vertices$get2.y; // I need min and max vertices on this line segment var minVertex = Geometry.minVertex({ x: x1, y: y1 }, { x: x2, y: y2 }); var maxVertex = Geometry.maxVertex({ x: x1, y: y1 }, { x: x2, y: y2 }); var width = catalog.factoryElement(state.drawingSupport.get('type'), {}, {}).properties.get('width').get('length'); // Now I need min and max possible coordinates for the hole on the line. They depend on the width of the hole // let width = hole.properties.get('width').get('length'); var lineLength = Geometry.pointsDistance(x1, y1, x2, y2); var alpha = Math.atan2(Math.abs(y2 - y1), Math.abs(x2 - x1)); var cosWithThreshold = function cosWithThreshold(alpha) { var cos = Math.cos(alpha); return cos < 0.0000001 ? 0 : cos; }; var sinWithThreshold = function sinWithThreshold(alpha) { var sin = Math.sin(alpha); return sin < 0.0000001 ? 0 : sin; }; var cosAlpha = cosWithThreshold(alpha); var sinAlpha = sinWithThreshold(alpha); var minLeftVertexHole = { x: minVertex.x + width / 2 * cosAlpha, y: minVertex.y + width / 2 * sinAlpha }; var maxRightVertexHole = { x: minVertex.x + lineLength * cosAlpha - width / 2 * cosAlpha, y: minVertex.y + lineLength * sinAlpha - width / 2 * sinAlpha }; var offset = void 0; if (x < minLeftVertexHole.x) { offset = Geometry.pointPositionOnLineSegment(minVertex.x, minVertex.y, maxVertex.x, maxVertex.y, minLeftVertexHole.x, minLeftVertexHole.y); } else if (x > maxRightVertexHole.x) { offset = Geometry.pointPositionOnLineSegment(minVertex.x, minVertex.y, maxVertex.x, maxVertex.y, maxRightVertexHole.x, maxRightVertexHole.y); } else { if (x === minLeftVertexHole.x && x === maxRightVertexHole.x) { if (y < minLeftVertexHole.y) { offset = Geometry.pointPositionOnLineSegment(minVertex.x, minVertex.y, maxVertex.x, maxVertex.y, minLeftVertexHole.x, minLeftVertexHole.y); offset = minVertex.x === x1 && minVertex.y === y1 ? offset : 1 - offset; } else if (y > maxRightVertexHole.y) { offset = Geometry.pointPositionOnLineSegment(minVertex.x, minVertex.y, maxVertex.x, maxVertex.y, maxRightVertexHole.x, maxRightVertexHole.y); offset = minVertex.x === x1 && minVertex.y === y1 ? offset : 1 - offset; } else { offset = Geometry.pointPositionOnLineSegment(x1, y1, x2, y2, x, y); } } else { offset = Geometry.pointPositionOnLineSegment(x1, y1, x2, y2, x, y); } } // let offset = Geometry.pointPositionOnLineSegment(x1, y1, x2, y2, x, y); var _addHole = addHole(layer, state.drawingSupport.get('type'), lineID, offset, catalog), hole = _addHole.hole; select(layer, 'holes', hole.id); } }); }); return state.set('scene', scene); } function endDrawingHole(state, layerID, x, y) { var catalog = state.catalog; state = updateDrawingHole(state, layerID, x, y, catalog); var scene = state.scene.updateIn(['layers', layerID], function (layer) { return unselectAll(layer); }); return state.merge({ scene: scene, sceneHistory: state.sceneHistory.push(scene) }); } function beginDraggingHole(state, layerID, holeID, x, y) { var layer = state.getIn(['scene', 'layers', layerID]); var hole = layer.getIn(['holes', holeID]); var line = layer.getIn(['lines', hole.line]); var v0 = layer.getIn(['vertices', line.vertices.get(0)]); var v1 = layer.getIn(['vertices', line.vertices.get(1)]); var snapElements = addLineSegmentSnap(List(), v0.x, v0.y, v1.x, v1.y, 9999999, 1, null); return state.merge({ mode: MODE_DRAGGING_HOLE, snapElements: snapElements, draggingSupport: Map({ layerID: layerID, holeID: holeID, startPointX: x, startPointY: y }) }); } function updateDraggingHole(state, x, y) { //calculate snap and overwrite coords if needed //force snap to segment var snap = nearestSnap(state.snapElements, x, y, state.snapMask.merge({ SNAP_SEGMENT: true })); if (!snap) return state; var draggingSupport = state.draggingSupport, scene = state.scene; var layerID = draggingSupport.get('layerID'); var holeID = draggingSupport.get('holeID'); var startPointX = draggingSupport.get('startPointX'); var startPointY = draggingSupport.get('startPointY'); var layer = state.getIn(['scene', 'layers', layerID]); var hole = layer.getIn(['holes', holeID]); var line = layer.getIn(['lines', hole.line]); var v0 = layer.getIn(['vertices', line.vertices.get(0)]); var v1 = layer.getIn(['vertices', line.vertices.get(1)]); // I need min and max vertices on this line segment var _snap$point2 = snap.point; x = _snap$point2.x; y = _snap$point2.y; var minVertex = Geometry.minVertex(v0, v1); var maxVertex = Geometry.maxVertex(v0, v1); // Now I need min and max possible coordinates for the hole on the line. They depend on the width of the hole var width = hole.properties.get('width').get('length'); var lineLength = Geometry.pointsDistance(v0.x, v0.y, v1.x, v1.y); var alpha = Math.atan2(Math.abs(v1.y - v0.y), Math.abs(v1.x - v0.x)); var cosWithThreshold = function cosWithThreshold(alpha) { var cos = Math.cos(alpha); return cos < 0.0000001 ? 0 : cos; }; var sinWithThreshold = function sinWithThreshold(alpha) { var sin = Math.sin(alpha); return sin < 0.0000001 ? 0 : sin; }; var cosAlpha = cosWithThreshold(alpha); var sinAlpha = sinWithThreshold(alpha); var minLeftVertexHole = { x: minVertex.x + width / 2 * cosAlpha, y: minVertex.y + width / 2 * sinAlpha }; var maxRightVertexHole = { x: minVertex.x + lineLength * cosAlpha - width / 2 * cosAlpha, y: minVertex.y + lineLength * sinAlpha - width / 2 * sinAlpha }; // Now I need to verify if the snap vertex (with coordinates x and y) is on the line segment var offset = void 0; if (x < minLeftVertexHole.x) { // Snap point is previous the the line offset = Geometry.pointPositionOnLineSegment(minVertex.x, minVertex.y, maxVertex.x, maxVertex.y, minLeftVertexHole.x, minLeftVertexHole.y); } else { // Snap point is after the line or on the line if (x > maxRightVertexHole.x) { offset = Geometry.pointPositionOnLineSegment(minVertex.x, minVertex.y, maxVertex.x, maxVertex.y, maxRightVertexHole.x, maxRightVertexHole.y); } else if (x === minLeftVertexHole.x && x === maxRightVertexHole.x) { // I am on a vertical line, I need to check y coordinates if (y < minLeftVertexHole.y) { offset = Geometry.pointPositionOnLineSegment(minVertex.x, minVertex.y, maxVertex.x, maxVertex.y, minLeftVertexHole.x, minLeftVertexHole.y); offset = minVertex === v0 ? offset : 1 - offset; } else if (y > maxRightVertexHole.y) { offset = Geometry.pointPositionOnLineSegment(minVertex.x, minVertex.y, maxVertex.x, maxVertex.y, maxRightVertexHole.x, maxRightVertexHole.y); offset = minVertex === v0 ? offset : 1 - offset; } else { offset = Geometry.pointPositionOnLineSegment(minVertex.x, minVertex.y, maxVertex.x, maxVertex.y, x, y); offset = minVertex === v0 ? offset : 1 - offset; } } else { offset = Geometry.pointPositionOnLineSegment(minVertex.x, minVertex.y, maxVertex.x, maxVertex.y, x, y); } } hole = hole.set('offset', offset); return state.merge({ scene: scene.mergeIn(['layers', layerID, 'holes', holeID], hole) }); } function endDraggingHole(state, x, y) { state = updateDraggingHole(state, x, y); return state.merge({ mode: MODE_IDLE, sceneHistory: state.sceneHistory.push(state.scene) }); } function selectHole(state, layerID, holeID) { var scene = state.scene; scene = scene.merge({ layers: scene.layers.map(unselectAll), selectedLayer: layerID }); scene = scene.updateIn(['layers', layerID], function (layer) { return layer.withMutations(function (layer) { select(layer, 'holes', holeID); }); }); return state.merge({ scene: scene, sceneHistory: state.sceneHistory.push(scene) }); } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yZWR1Y2Vycy9ob2xlcy1yZWR1Y2VyLmpzIl0sIm5hbWVzIjpbIkxpc3QiLCJNYXAiLCJTRUxFQ1RfVE9PTF9EUkFXSU5HX0hPTEUiLCJVUERBVEVfRFJBV0lOR19IT0xFIiwiRU5EX0RSQVdJTkdfSE9MRSIsIkJFR0lOX0RSQUdHSU5HX0hPTEUiLCJVUERBVEVfRFJBR0dJTkdfSE9MRSIsIkVORF9EUkFHR0lOR19IT0xFIiwiU0VMRUNUX0hPTEUiLCJNT0RFX0lETEUiLCJNT0RFX0RSQVdJTkdfSE9MRSIsIk1PREVfRFJBR0dJTkdfSE9MRSIsIkdlb21ldHJ5Iiwic2VsZWN0IiwidW5zZWxlY3QiLCJ1bnNlbGVjdEFsbCIsImFkZEhvbGUiLCJyZW1vdmVIb2xlIiwibmVhcmVzdFNuYXAiLCJhZGRQb2ludFNuYXAiLCJhZGRMaW5lU25hcCIsImFkZExpbmVTZWdtZW50U25hcCIsIlNOQVBfUE9JTlQiLCJTTkFQX0xJTkUiLCJTTkFQX1NFR01FTlQiLCJzdGF0ZSIsImFjdGlvbiIsInR5cGUiLCJzZWxlY3RUb29sRHJhd2luZ0hvbGUiLCJzY2VuZUNvbXBvbmVudFR5cGUiLCJ1cGRhdGVEcmF3aW5nSG9sZSIsImxheWVySUQiLCJ4IiwieSIsImVuZERyYXdpbmdIb2xlIiwiYmVnaW5EcmFnZ2luZ0hvbGUiLCJob2xlSUQiLCJ1cGRhdGVEcmFnZ2luZ0hvbGUiLCJlbmREcmFnZ2luZ0hvbGUiLCJzZWxlY3RIb2xlIiwic25hcEVsZW1lbnRzIiwid2l0aE11dGF0aW9ucyIsImdldEluIiwic2NlbmUiLCJzZWxlY3RlZExheWVyIiwibGluZXMiLCJ2ZXJ0aWNlcyIsImZvckVhY2giLCJnZXQiLCJsaW5lIiwieDEiLCJ5MSIsIngyIiwieTIiLCJpZCIsIm1lcmdlIiwibW9kZSIsImRyYXdpbmdTdXBwb3J0IiwiY2F0YWxvZyIsInNuYXAiLCJzbmFwTWFzayIsInBvaW50IiwidXBkYXRlSW4iLCJsYXllciIsInNlbGVjdGVkSG9sZSIsImZpcnN0IiwibGluZUlEIiwicmVsYXRlZCIsIm1pblZlcnRleCIsIm1heFZlcnRleCIsIndpZHRoIiwiZmFjdG9yeUVsZW1lbnQiLCJwcm9wZXJ0aWVzIiwibGluZUxlbmd0aCIsInBvaW50c0Rpc3RhbmNlIiwiYWxwaGEiLCJNYXRoIiwiYXRhbjIiLCJhYnMiLCJjb3NXaXRoVGhyZXNob2xkIiwiY29zIiwic2luV2l0aFRocmVzaG9sZCIsInNpbiIsImNvc0FscGhhIiwic2luQWxwaGEiLCJtaW5MZWZ0VmVydGV4SG9sZSIsIm1heFJpZ2h0VmVydGV4SG9sZSIsIm9mZnNldCIsInBvaW50UG9zaXRpb25PbkxpbmVTZWdtZW50IiwiaG9sZSIsInNldCIsInNjZW5lSGlzdG9yeSIsInB1c2giLCJ2MCIsInYxIiwiZHJhZ2dpbmdTdXBwb3J0Iiwic3RhcnRQb2ludFgiLCJzdGFydFBvaW50WSIsIm1lcmdlSW4iLCJsYXllcnMiLCJtYXAiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVFBLElBQVIsRUFBY0MsR0FBZCxRQUF3QixXQUF4Qjs7QUFFQSxTQUNFQyx3QkFERixFQUVFQyxtQkFGRixFQUdFQyxnQkFIRixFQUlFQyxtQkFKRixFQUtFQyxvQkFMRixFQU1FQyxpQkFORixFQU9FQyxXQVBGLEVBU0VDLFNBVEYsRUFVRUMsaUJBVkYsRUFXRUMsa0JBWEYsUUFZTyxjQVpQOztBQWNBLE9BQU8sS0FBS0MsUUFBWixNQUEwQixtQkFBMUI7QUFDQSxTQUNFQyxNQURGLEVBRUVDLFFBRkYsRUFHRUMsV0FIRixFQUlFQyxPQUpGLEVBS0VDLFVBTEYsUUFNTywyQkFOUDtBQU9BLFNBQ0VDLFdBREYsRUFFRUMsWUFGRixFQUdFQyxXQUhGLEVBSUVDLGtCQUpGLEVBS0VDLFVBTEYsRUFNRUMsU0FORixFQU9FQyxZQVBGLFFBUU8sZUFSUDs7QUFVQSxlQUFlLFVBQVVDLEtBQVYsRUFBaUJDLE1BQWpCLEVBQXlCO0FBQ3RDLFVBQVFBLE9BQU9DLElBQWY7QUFDRSxTQUFLekIsd0JBQUw7QUFDRSxhQUFPMEIsc0JBQXNCSCxLQUF0QixFQUE2QkMsT0FBT0csa0JBQXBDLENBQVA7O0FBRUYsU0FBSzFCLG1CQUFMO0FBQ0UsYUFBTzJCLGtCQUFrQkwsS0FBbEIsRUFBeUJDLE9BQU9LLE9BQWhDLEVBQXlDTCxPQUFPTSxDQUFoRCxFQUFtRE4sT0FBT08sQ0FBMUQsQ0FBUDs7QUFFRixTQUFLN0IsZ0JBQUw7QUFDRSxhQUFPOEIsZUFBZVQsS0FBZixFQUFzQkMsT0FBT0ssT0FBN0IsRUFBc0NMLE9BQU9NLENBQTdDLEVBQWdETixPQUFPTyxDQUF2RCxDQUFQOztBQUVGLFNBQUs1QixtQkFBTDtBQUNFLGFBQU84QixrQkFBa0JWLEtBQWxCLEVBQXlCQyxPQUFPSyxPQUFoQyxFQUF5Q0wsT0FBT1UsTUFBaEQsRUFBd0RWLE9BQU9NLENBQS9ELEVBQWtFTixPQUFPTyxDQUF6RSxDQUFQOztBQUVGLFNBQUszQixvQkFBTDtBQUNFLGFBQU8rQixtQkFBbUJaLEtBQW5CLEVBQTBCQyxPQUFPTSxDQUFqQyxFQUFvQ04sT0FBT08sQ0FBM0MsQ0FBUDs7QUFFRixTQUFLMUIsaUJBQUw7QUFDRSxhQUFPK0IsZ0JBQWdCYixLQUFoQixFQUF1QkMsT0FBT00sQ0FBOUIsRUFBaUNOLE9BQU9PLENBQXhDLENBQVA7O0FBRUYsU0FBS3pCLFdBQUw7QUFDRSxhQUFPK0IsV0FBV2QsS0FBWCxFQUFrQkMsT0FBT0ssT0FBekIsRUFBa0NMLE9BQU9VLE1BQXpDLENBQVA7O0FBRUY7QUFDRSxhQUFPWCxLQUFQO0FBdkJKO0FBeUJEOztBQUVELFNBQVNHLHFCQUFULENBQStCSCxLQUEvQixFQUFzQ0ksa0JBQXRDLEVBQTBEOztBQUV4RCxNQUFJVyxlQUFnQixJQUFJeEMsSUFBSixFQUFELENBQWF5QyxhQUFiLENBQTJCLHdCQUFnQjtBQUFBLHVCQUNwQ2hCLE1BQU1pQixLQUFOLENBQVksQ0FBQyxPQUFELEVBQVUsUUFBVixFQUFvQmpCLE1BQU1rQixLQUFOLENBQVlDLGFBQWhDLENBQVosQ0FEb0M7QUFBQSxRQUN2REMsS0FEdUQsZ0JBQ3ZEQSxLQUR1RDtBQUFBLFFBQ2hEQyxRQURnRCxnQkFDaERBLFFBRGdEOztBQUc1REQsVUFBTUUsT0FBTixDQUFjLGdCQUFRO0FBQUEsMEJBQ0NELFNBQVNFLEdBQVQsQ0FBYUMsS0FBS0gsUUFBTCxDQUFjRSxHQUFkLENBQWtCLENBQWxCLENBQWIsQ0FERDtBQUFBLFVBQ1pFLEVBRFksaUJBQ2ZsQixDQURlO0FBQUEsVUFDTG1CLEVBREssaUJBQ1JsQixDQURROztBQUFBLDJCQUVDYSxTQUFTRSxHQUFULENBQWFDLEtBQUtILFFBQUwsQ0FBY0UsR0FBZCxDQUFrQixDQUFsQixDQUFiLENBRkQ7QUFBQSxVQUVaSSxFQUZZLGtCQUVmcEIsQ0FGZTtBQUFBLFVBRUxxQixFQUZLLGtCQUVScEIsQ0FGUTs7QUFJcEJaLHlCQUFtQm1CLFlBQW5CLEVBQWlDVSxFQUFqQyxFQUFxQ0MsRUFBckMsRUFBeUNDLEVBQXpDLEVBQTZDQyxFQUE3QyxFQUFpRCxFQUFqRCxFQUFxRCxDQUFyRCxFQUF3REosS0FBS0ssRUFBN0Q7QUFDRCxLQUxEO0FBTUQsR0FUa0IsQ0FBbkI7O0FBV0EsU0FBTzdCLE1BQU04QixLQUFOLENBQVk7QUFDakJDLFVBQU05QyxpQkFEVztBQUVqQjhCLDhCQUZpQjtBQUdqQmlCLG9CQUFnQnhELElBQUk7QUFDbEIwQixZQUFNRTtBQURZLEtBQUo7QUFIQyxHQUFaLENBQVA7QUFPRDs7QUFFRDtBQUNBLFNBQVNDLGlCQUFULENBQTJCTCxLQUEzQixFQUFrQ00sT0FBbEMsRUFBMkNDLENBQTNDLEVBQThDQyxDQUE5QyxFQUFpRDtBQUMvQyxNQUFJeUIsVUFBVWpDLE1BQU1pQyxPQUFwQjs7QUFFQTtBQUNBO0FBQ0EsTUFBSUMsT0FBT3pDLFlBQVlPLE1BQU1lLFlBQWxCLEVBQWdDUixDQUFoQyxFQUFtQ0MsQ0FBbkMsRUFBc0NSLE1BQU1tQyxRQUFOLENBQWVMLEtBQWYsQ0FBcUIsRUFBQy9CLGNBQWMsSUFBZixFQUFyQixDQUF0QyxDQUFYO0FBQ0EsTUFBSW1DLElBQUo7QUFBVTs7QUFBVixzQkFBb0JBLEtBQUtFLEtBQXpCO0FBQVk3QixLQUFaLGVBQVlBLENBQVo7QUFBZUMsS0FBZixlQUFlQSxDQUFmO0FBQUEsR0FFQSxJQUFJVSxRQUFRbEIsTUFBTWtCLEtBQU4sQ0FBWW1CLFFBQVosQ0FBcUIsQ0FBQyxRQUFELEVBQVcvQixPQUFYLENBQXJCLEVBQTBDO0FBQUEsV0FBU2dDLE1BQU10QixhQUFOLENBQW9CLGlCQUFTO0FBQzFGLFVBQUl1QixlQUFlRCxNQUFNckIsS0FBTixDQUFZLENBQUMsVUFBRCxFQUFhLE9BQWIsQ0FBWixFQUFtQ3VCLEtBQW5DLEVBQW5CO0FBQ0EsVUFBSUQsWUFBSixFQUFrQjtBQUNoQmxELGlCQUFTaUQsS0FBVCxFQUFnQixPQUFoQixFQUF5QkMsWUFBekI7QUFDQS9DLG1CQUFXOEMsS0FBWCxFQUFrQkMsWUFBbEI7QUFDRDs7QUFFRCxVQUFJTCxJQUFKLEVBQVU7QUFDUixZQUFJTyxTQUFTUCxLQUFLQSxJQUFMLENBQVVRLE9BQVYsQ0FBa0JuQixHQUFsQixDQUFzQixDQUF0QixDQUFiO0FBQ0EsWUFBSUMsT0FBT2MsTUFBTXJCLEtBQU4sQ0FBWSxDQUFDLE9BQUQsRUFBVXdCLE1BQVYsQ0FBWixDQUFYOztBQUZRLGtDQUdhSCxNQUFNakIsUUFBTixDQUFlRSxHQUFmLENBQW1CQyxLQUFLSCxRQUFMLENBQWNFLEdBQWQsQ0FBa0IsQ0FBbEIsQ0FBbkIsQ0FIYjtBQUFBLFlBR0FFLEVBSEEsdUJBR0hsQixDQUhHO0FBQUEsWUFHT21CLEVBSFAsdUJBR0lsQixDQUhKOztBQUFBLG1DQUlhOEIsTUFBTWpCLFFBQU4sQ0FBZUUsR0FBZixDQUFtQkMsS0FBS0gsUUFBTCxDQUFjRSxHQUFkLENBQWtCLENBQWxCLENBQW5CLENBSmI7QUFBQSxZQUlBSSxFQUpBLHdCQUlIcEIsQ0FKRztBQUFBLFlBSU9xQixFQUpQLHdCQUlJcEIsQ0FKSjs7QUFNUjs7O0FBQ0EsWUFBSW1DLFlBQVl4RCxTQUFTd0QsU0FBVCxDQUFtQixFQUFDcEMsR0FBR2tCLEVBQUosRUFBUWpCLEdBQUdrQixFQUFYLEVBQW5CLEVBQW1DLEVBQUNuQixHQUFHb0IsRUFBSixFQUFRbkIsR0FBR29CLEVBQVgsRUFBbkMsQ0FBaEI7QUFDQSxZQUFJZ0IsWUFBWXpELFNBQVN5RCxTQUFULENBQW1CLEVBQUNyQyxHQUFHa0IsRUFBSixFQUFRakIsR0FBR2tCLEVBQVgsRUFBbkIsRUFBbUMsRUFBQ25CLEdBQUdvQixFQUFKLEVBQVFuQixHQUFHb0IsRUFBWCxFQUFuQyxDQUFoQjtBQUNBLFlBQUlpQixRQUFRWixRQUFRYSxjQUFSLENBQXVCOUMsTUFBTWdDLGNBQU4sQ0FBcUJULEdBQXJCLENBQXlCLE1BQXpCLENBQXZCLEVBQXlELEVBQXpELEVBQTZELEVBQTdELEVBQWlFd0IsVUFBakUsQ0FBNEV4QixHQUE1RSxDQUFnRixPQUFoRixFQUF5RkEsR0FBekYsQ0FBNkYsUUFBN0YsQ0FBWjs7QUFHQTs7QUFFQTtBQUNBLFlBQUl5QixhQUFhN0QsU0FBUzhELGNBQVQsQ0FBd0J4QixFQUF4QixFQUE0QkMsRUFBNUIsRUFBZ0NDLEVBQWhDLEVBQW9DQyxFQUFwQyxDQUFqQjtBQUNBLFlBQUlzQixRQUFRQyxLQUFLQyxLQUFMLENBQVdELEtBQUtFLEdBQUwsQ0FBU3pCLEtBQUtGLEVBQWQsQ0FBWCxFQUE4QnlCLEtBQUtFLEdBQUwsQ0FBUzFCLEtBQUtGLEVBQWQsQ0FBOUIsQ0FBWjs7QUFFQSxZQUFJNkIsbUJBQW1CLFNBQW5CQSxnQkFBbUIsQ0FBQ0osS0FBRCxFQUFXO0FBQ2hDLGNBQUlLLE1BQU1KLEtBQUtJLEdBQUwsQ0FBU0wsS0FBVCxDQUFWO0FBQ0EsaUJBQU9LLE1BQU0sU0FBTixHQUFrQixDQUFsQixHQUFzQkEsR0FBN0I7QUFDRCxTQUhEOztBQUtBLFlBQUlDLG1CQUFtQixTQUFuQkEsZ0JBQW1CLENBQUNOLEtBQUQsRUFBVztBQUNoQyxjQUFJTyxNQUFNTixLQUFLTSxHQUFMLENBQVNQLEtBQVQsQ0FBVjtBQUNBLGlCQUFPTyxNQUFNLFNBQU4sR0FBa0IsQ0FBbEIsR0FBc0JBLEdBQTdCO0FBQ0QsU0FIRDs7QUFLQSxZQUFJQyxXQUFXSixpQkFBaUJKLEtBQWpCLENBQWY7QUFDQSxZQUFJUyxXQUFXSCxpQkFBaUJOLEtBQWpCLENBQWY7O0FBRUEsWUFBSVUsb0JBQW9CO0FBQ3RCckQsYUFBR29DLFVBQVVwQyxDQUFWLEdBQWNzQyxRQUFRLENBQVIsR0FBWWEsUUFEUDtBQUV0QmxELGFBQUdtQyxVQUFVbkMsQ0FBVixHQUFjcUMsUUFBUSxDQUFSLEdBQVljO0FBRlAsU0FBeEI7O0FBS0EsWUFBSUUscUJBQXFCO0FBQ3ZCdEQsYUFBR29DLFVBQVVwQyxDQUFWLEdBQWN5QyxhQUFhVSxRQUEzQixHQUFzQ2IsUUFBUSxDQUFSLEdBQVlhLFFBRDlCO0FBRXZCbEQsYUFBR21DLFVBQVVuQyxDQUFWLEdBQWN3QyxhQUFhVyxRQUEzQixHQUFzQ2QsUUFBUSxDQUFSLEdBQVljO0FBRjlCLFNBQXpCOztBQUtBLFlBQUlHLGVBQUo7QUFDQSxZQUFJdkQsSUFBSXFELGtCQUFrQnJELENBQTFCLEVBQTZCO0FBQzNCdUQsbUJBQVMzRSxTQUFTNEUsMEJBQVQsQ0FBb0NwQixVQUFVcEMsQ0FBOUMsRUFBaURvQyxVQUFVbkMsQ0FBM0QsRUFDUG9DLFVBQVVyQyxDQURILEVBQ01xQyxVQUFVcEMsQ0FEaEIsRUFFUG9ELGtCQUFrQnJELENBRlgsRUFFY3FELGtCQUFrQnBELENBRmhDLENBQVQ7QUFHRCxTQUpELE1BSU8sSUFBSUQsSUFBSXNELG1CQUFtQnRELENBQTNCLEVBQThCO0FBQ25DdUQsbUJBQVMzRSxTQUFTNEUsMEJBQVQsQ0FBb0NwQixVQUFVcEMsQ0FBOUMsRUFBaURvQyxVQUFVbkMsQ0FBM0QsRUFDUG9DLFVBQVVyQyxDQURILEVBQ01xQyxVQUFVcEMsQ0FEaEIsRUFFUHFELG1CQUFtQnRELENBRlosRUFFZXNELG1CQUFtQnJELENBRmxDLENBQVQ7QUFHRCxTQUpNLE1BSUE7O0FBRUwsY0FBSUQsTUFBTXFELGtCQUFrQnJELENBQXhCLElBQTZCQSxNQUFNc0QsbUJBQW1CdEQsQ0FBMUQsRUFBNkQ7O0FBRTNELGdCQUFJQyxJQUFJb0Qsa0JBQWtCcEQsQ0FBMUIsRUFBNkI7QUFDM0JzRCx1QkFBUzNFLFNBQVM0RSwwQkFBVCxDQUFvQ3BCLFVBQVVwQyxDQUE5QyxFQUFpRG9DLFVBQVVuQyxDQUEzRCxFQUNQb0MsVUFBVXJDLENBREgsRUFDTXFDLFVBQVVwQyxDQURoQixFQUVQb0Qsa0JBQWtCckQsQ0FGWCxFQUVjcUQsa0JBQWtCcEQsQ0FGaEMsQ0FBVDtBQUdBc0QsdUJBQVNuQixVQUFVcEMsQ0FBVixLQUFnQmtCLEVBQWhCLElBQXNCa0IsVUFBVW5DLENBQVYsS0FBZ0JrQixFQUF0QyxHQUEyQ29DLE1BQTNDLEdBQW9ELElBQUlBLE1BQWpFO0FBQ0QsYUFMRCxNQUtPLElBQUl0RCxJQUFJcUQsbUJBQW1CckQsQ0FBM0IsRUFBOEI7QUFDbkNzRCx1QkFBUzNFLFNBQVM0RSwwQkFBVCxDQUFvQ3BCLFVBQVVwQyxDQUE5QyxFQUFpRG9DLFVBQVVuQyxDQUEzRCxFQUNQb0MsVUFBVXJDLENBREgsRUFDTXFDLFVBQVVwQyxDQURoQixFQUVQcUQsbUJBQW1CdEQsQ0FGWixFQUVlc0QsbUJBQW1CckQsQ0FGbEMsQ0FBVDtBQUdBc0QsdUJBQVNuQixVQUFVcEMsQ0FBVixLQUFnQmtCLEVBQWhCLElBQXNCa0IsVUFBVW5DLENBQVYsS0FBZ0JrQixFQUF0QyxHQUEyQ29DLE1BQTNDLEdBQW9ELElBQUlBLE1BQWpFO0FBQ0QsYUFMTSxNQUtBO0FBQ0xBLHVCQUFTM0UsU0FBUzRFLDBCQUFULENBQW9DdEMsRUFBcEMsRUFBd0NDLEVBQXhDLEVBQTRDQyxFQUE1QyxFQUFnREMsRUFBaEQsRUFBb0RyQixDQUFwRCxFQUF1REMsQ0FBdkQsQ0FBVDtBQUNEO0FBQ0YsV0FmRCxNQWVPO0FBQ0xzRCxxQkFBUzNFLFNBQVM0RSwwQkFBVCxDQUFvQ3RDLEVBQXBDLEVBQXdDQyxFQUF4QyxFQUE0Q0MsRUFBNUMsRUFBZ0RDLEVBQWhELEVBQW9EckIsQ0FBcEQsRUFBdURDLENBQXZELENBQVQ7QUFDRDtBQUNGOztBQUVEOztBQXhFUSx1QkF5RUtqQixRQUFRK0MsS0FBUixFQUFldEMsTUFBTWdDLGNBQU4sQ0FBcUJULEdBQXJCLENBQXlCLE1BQXpCLENBQWYsRUFBaURrQixNQUFqRCxFQUF5RHFCLE1BQXpELEVBQWlFN0IsT0FBakUsQ0F6RUw7QUFBQSxZQXlFSCtCLElBekVHLFlBeUVIQSxJQXpFRzs7QUEwRVI1RSxlQUFPa0QsS0FBUCxFQUFjLE9BQWQsRUFBdUIwQixLQUFLbkMsRUFBNUI7QUFDRDtBQUNGLEtBbkY4RCxDQUFUO0FBQUEsR0FBMUMsQ0FBWjs7QUFxRkEsU0FBTzdCLE1BQU1pRSxHQUFOLENBQVUsT0FBVixFQUFtQi9DLEtBQW5CLENBQVA7QUFDRDs7QUFFRCxTQUFTVCxjQUFULENBQXdCVCxLQUF4QixFQUErQk0sT0FBL0IsRUFBd0NDLENBQXhDLEVBQTJDQyxDQUEzQyxFQUE4QztBQUM1QyxNQUFJeUIsVUFBVWpDLE1BQU1pQyxPQUFwQjs7QUFFQWpDLFVBQVFLLGtCQUFrQkwsS0FBbEIsRUFBeUJNLE9BQXpCLEVBQWtDQyxDQUFsQyxFQUFxQ0MsQ0FBckMsRUFBd0N5QixPQUF4QyxDQUFSO0FBQ0EsTUFBSWYsUUFBUWxCLE1BQU1rQixLQUFOLENBQVltQixRQUFaLENBQXFCLENBQUMsUUFBRCxFQUFXL0IsT0FBWCxDQUFyQixFQUEwQztBQUFBLFdBQVNoQixZQUFZZ0QsS0FBWixDQUFUO0FBQUEsR0FBMUMsQ0FBWjtBQUNBLFNBQU90QyxNQUFNOEIsS0FBTixDQUFZO0FBQ2pCWixnQkFEaUI7QUFFakJnRCxrQkFBY2xFLE1BQU1rRSxZQUFOLENBQW1CQyxJQUFuQixDQUF3QmpELEtBQXhCO0FBRkcsR0FBWixDQUFQO0FBSUQ7O0FBRUQsU0FBU1IsaUJBQVQsQ0FBMkJWLEtBQTNCLEVBQWtDTSxPQUFsQyxFQUEyQ0ssTUFBM0MsRUFBbURKLENBQW5ELEVBQXNEQyxDQUF0RCxFQUF5RDtBQUN2RCxNQUFJOEIsUUFBUXRDLE1BQU1pQixLQUFOLENBQVksQ0FBQyxPQUFELEVBQVUsUUFBVixFQUFvQlgsT0FBcEIsQ0FBWixDQUFaO0FBQ0EsTUFBSTBELE9BQU8xQixNQUFNckIsS0FBTixDQUFZLENBQUMsT0FBRCxFQUFVTixNQUFWLENBQVosQ0FBWDtBQUNBLE1BQUlhLE9BQU9jLE1BQU1yQixLQUFOLENBQVksQ0FBQyxPQUFELEVBQVUrQyxLQUFLeEMsSUFBZixDQUFaLENBQVg7QUFDQSxNQUFJNEMsS0FBSzlCLE1BQU1yQixLQUFOLENBQVksQ0FBQyxVQUFELEVBQWFPLEtBQUtILFFBQUwsQ0FBY0UsR0FBZCxDQUFrQixDQUFsQixDQUFiLENBQVosQ0FBVDtBQUNBLE1BQUk4QyxLQUFLL0IsTUFBTXJCLEtBQU4sQ0FBWSxDQUFDLFVBQUQsRUFBYU8sS0FBS0gsUUFBTCxDQUFjRSxHQUFkLENBQWtCLENBQWxCLENBQWIsQ0FBWixDQUFUOztBQUVBLE1BQUlSLGVBQWVuQixtQkFBbUJyQixNQUFuQixFQUEyQjZGLEdBQUc3RCxDQUE5QixFQUFpQzZELEdBQUc1RCxDQUFwQyxFQUF1QzZELEdBQUc5RCxDQUExQyxFQUE2QzhELEdBQUc3RCxDQUFoRCxFQUFtRCxPQUFuRCxFQUE0RCxDQUE1RCxFQUErRCxJQUEvRCxDQUFuQjs7QUFFQSxTQUFPUixNQUFNOEIsS0FBTixDQUFZO0FBQ2pCQyxVQUFNN0Msa0JBRFc7QUFFakI2Qiw4QkFGaUI7QUFHakJ1RCxxQkFBaUI5RixJQUFJO0FBQ25COEIsc0JBRG1CO0FBRW5CSyxvQkFGbUI7QUFHbkI0RCxtQkFBYWhFLENBSE07QUFJbkJpRSxtQkFBYWhFO0FBSk0sS0FBSjtBQUhBLEdBQVosQ0FBUDtBQVVEOztBQUVELFNBQVNJLGtCQUFULENBQTRCWixLQUE1QixFQUFtQ08sQ0FBbkMsRUFBc0NDLENBQXRDLEVBQXlDOztBQUV2QztBQUNBO0FBQ0EsTUFBSTBCLE9BQU96QyxZQUFZTyxNQUFNZSxZQUFsQixFQUFnQ1IsQ0FBaEMsRUFBbUNDLENBQW5DLEVBQXNDUixNQUFNbUMsUUFBTixDQUFlTCxLQUFmLENBQXFCLEVBQUMvQixjQUFjLElBQWYsRUFBckIsQ0FBdEMsQ0FBWDtBQUNBLE1BQUksQ0FBQ21DLElBQUwsRUFBVyxPQUFPbEMsS0FBUDs7QUFMNEIsTUFPbENzRSxlQVBrQyxHQU9SdEUsS0FQUSxDQU9sQ3NFLGVBUGtDO0FBQUEsTUFPakJwRCxLQVBpQixHQU9SbEIsS0FQUSxDQU9qQmtCLEtBUGlCOzs7QUFTdkMsTUFBSVosVUFBVWdFLGdCQUFnQi9DLEdBQWhCLENBQW9CLFNBQXBCLENBQWQ7QUFDQSxNQUFJWixTQUFTMkQsZ0JBQWdCL0MsR0FBaEIsQ0FBb0IsUUFBcEIsQ0FBYjtBQUNBLE1BQUlnRCxjQUFjRCxnQkFBZ0IvQyxHQUFoQixDQUFvQixhQUFwQixDQUFsQjtBQUNBLE1BQUlpRCxjQUFjRixnQkFBZ0IvQyxHQUFoQixDQUFvQixhQUFwQixDQUFsQjs7QUFFQSxNQUFJZSxRQUFRdEMsTUFBTWlCLEtBQU4sQ0FBWSxDQUFDLE9BQUQsRUFBVSxRQUFWLEVBQW9CWCxPQUFwQixDQUFaLENBQVo7QUFDQSxNQUFJMEQsT0FBTzFCLE1BQU1yQixLQUFOLENBQVksQ0FBQyxPQUFELEVBQVVOLE1BQVYsQ0FBWixDQUFYO0FBQ0EsTUFBSWEsT0FBT2MsTUFBTXJCLEtBQU4sQ0FBWSxDQUFDLE9BQUQsRUFBVStDLEtBQUt4QyxJQUFmLENBQVosQ0FBWDtBQUNBLE1BQUk0QyxLQUFLOUIsTUFBTXJCLEtBQU4sQ0FBWSxDQUFDLFVBQUQsRUFBYU8sS0FBS0gsUUFBTCxDQUFjRSxHQUFkLENBQWtCLENBQWxCLENBQWIsQ0FBWixDQUFUO0FBQ0EsTUFBSThDLEtBQUsvQixNQUFNckIsS0FBTixDQUFZLENBQUMsVUFBRCxFQUFhTyxLQUFLSCxRQUFMLENBQWNFLEdBQWQsQ0FBa0IsQ0FBbEIsQ0FBYixDQUFaLENBQVQ7O0FBSUE7QUF0QnVDLHFCQW9CN0JXLEtBQUtFLEtBcEJ3QjtBQW9CckM3QixHQXBCcUMsZ0JBb0JyQ0EsQ0FwQnFDO0FBb0JsQ0MsR0FwQmtDLGdCQW9CbENBLENBcEJrQztBQXVCdkMsTUFBSW1DLFlBQVl4RCxTQUFTd0QsU0FBVCxDQUFtQnlCLEVBQW5CLEVBQXVCQyxFQUF2QixDQUFoQjtBQUNBLE1BQUl6QixZQUFZekQsU0FBU3lELFNBQVQsQ0FBbUJ3QixFQUFuQixFQUF1QkMsRUFBdkIsQ0FBaEI7O0FBRUE7O0FBRUEsTUFBSXhCLFFBQVFtQixLQUFLakIsVUFBTCxDQUFnQnhCLEdBQWhCLENBQW9CLE9BQXBCLEVBQTZCQSxHQUE3QixDQUFpQyxRQUFqQyxDQUFaO0FBQ0EsTUFBSXlCLGFBQWE3RCxTQUFTOEQsY0FBVCxDQUF3Qm1CLEdBQUc3RCxDQUEzQixFQUE4QjZELEdBQUc1RCxDQUFqQyxFQUFvQzZELEdBQUc5RCxDQUF2QyxFQUEwQzhELEdBQUc3RCxDQUE3QyxDQUFqQjtBQUNBLE1BQUkwQyxRQUFRQyxLQUFLQyxLQUFMLENBQVdELEtBQUtFLEdBQUwsQ0FBU2dCLEdBQUc3RCxDQUFILEdBQU80RCxHQUFHNUQsQ0FBbkIsQ0FBWCxFQUFrQzJDLEtBQUtFLEdBQUwsQ0FBU2dCLEdBQUc5RCxDQUFILEdBQU82RCxHQUFHN0QsQ0FBbkIsQ0FBbEMsQ0FBWjs7QUFFQSxNQUFJK0MsbUJBQW1CLFNBQW5CQSxnQkFBbUIsQ0FBQ0osS0FBRCxFQUFXO0FBQ2hDLFFBQUlLLE1BQU1KLEtBQUtJLEdBQUwsQ0FBU0wsS0FBVCxDQUFWO0FBQ0EsV0FBT0ssTUFBTSxTQUFOLEdBQWtCLENBQWxCLEdBQXNCQSxHQUE3QjtBQUNELEdBSEQ7O0FBS0EsTUFBSUMsbUJBQW1CLFNBQW5CQSxnQkFBbUIsQ0FBQ04sS0FBRCxFQUFXO0FBQ2hDLFFBQUlPLE1BQU1OLEtBQUtNLEdBQUwsQ0FBU1AsS0FBVCxDQUFWO0FBQ0EsV0FBT08sTUFBTSxTQUFOLEdBQWtCLENBQWxCLEdBQXNCQSxHQUE3QjtBQUNELEdBSEQ7O0FBS0EsTUFBSUMsV0FBV0osaUJBQWlCSixLQUFqQixDQUFmO0FBQ0EsTUFBSVMsV0FBV0gsaUJBQWlCTixLQUFqQixDQUFmOztBQUVBLE1BQUlVLG9CQUFvQjtBQUN0QnJELE9BQUdvQyxVQUFVcEMsQ0FBVixHQUFjc0MsUUFBUSxDQUFSLEdBQVlhLFFBRFA7QUFFdEJsRCxPQUFHbUMsVUFBVW5DLENBQVYsR0FBY3FDLFFBQVEsQ0FBUixHQUFZYztBQUZQLEdBQXhCOztBQUtBLE1BQUlFLHFCQUFxQjtBQUN2QnRELE9BQUdvQyxVQUFVcEMsQ0FBVixHQUFjeUMsYUFBYVUsUUFBM0IsR0FBc0NiLFFBQVEsQ0FBUixHQUFZYSxRQUQ5QjtBQUV2QmxELE9BQUdtQyxVQUFVbkMsQ0FBVixHQUFjd0MsYUFBYVcsUUFBM0IsR0FBc0NkLFFBQVEsQ0FBUixHQUFZYztBQUY5QixHQUF6Qjs7QUFLQTs7QUFFQSxNQUFJRyxlQUFKOztBQUVBLE1BQUl2RCxJQUFJcUQsa0JBQWtCckQsQ0FBMUIsRUFBNkI7QUFDM0I7QUFDQXVELGFBQVMzRSxTQUFTNEUsMEJBQVQsQ0FBb0NwQixVQUFVcEMsQ0FBOUMsRUFBaURvQyxVQUFVbkMsQ0FBM0QsRUFDUG9DLFVBQVVyQyxDQURILEVBQ01xQyxVQUFVcEMsQ0FEaEIsRUFFUG9ELGtCQUFrQnJELENBRlgsRUFFY3FELGtCQUFrQnBELENBRmhDLENBQVQ7QUFHRCxHQUxELE1BS087QUFDTDtBQUNBLFFBQUlELElBQUlzRCxtQkFBbUJ0RCxDQUEzQixFQUE4QjtBQUM1QnVELGVBQVMzRSxTQUFTNEUsMEJBQVQsQ0FBb0NwQixVQUFVcEMsQ0FBOUMsRUFBaURvQyxVQUFVbkMsQ0FBM0QsRUFDUG9DLFVBQVVyQyxDQURILEVBQ01xQyxVQUFVcEMsQ0FEaEIsRUFFUHFELG1CQUFtQnRELENBRlosRUFFZXNELG1CQUFtQnJELENBRmxDLENBQVQ7QUFHRCxLQUpELE1BSU8sSUFBSUQsTUFBTXFELGtCQUFrQnJELENBQXhCLElBQTZCQSxNQUFNc0QsbUJBQW1CdEQsQ0FBMUQsRUFBNkQ7QUFDbEU7QUFDQSxVQUFJQyxJQUFJb0Qsa0JBQWtCcEQsQ0FBMUIsRUFBNkI7QUFDM0JzRCxpQkFBUzNFLFNBQVM0RSwwQkFBVCxDQUFvQ3BCLFVBQVVwQyxDQUE5QyxFQUFpRG9DLFVBQVVuQyxDQUEzRCxFQUNQb0MsVUFBVXJDLENBREgsRUFDTXFDLFVBQVVwQyxDQURoQixFQUVQb0Qsa0JBQWtCckQsQ0FGWCxFQUVjcUQsa0JBQWtCcEQsQ0FGaEMsQ0FBVDs7QUFJQXNELGlCQUFTbkIsY0FBY3lCLEVBQWQsR0FBbUJOLE1BQW5CLEdBQTRCLElBQUlBLE1BQXpDO0FBRUQsT0FQRCxNQU9PLElBQUl0RCxJQUFJcUQsbUJBQW1CckQsQ0FBM0IsRUFBOEI7QUFDbkNzRCxpQkFBUzNFLFNBQVM0RSwwQkFBVCxDQUFvQ3BCLFVBQVVwQyxDQUE5QyxFQUFpRG9DLFVBQVVuQyxDQUEzRCxFQUNQb0MsVUFBVXJDLENBREgsRUFDTXFDLFVBQVVwQyxDQURoQixFQUVQcUQsbUJBQW1CdEQsQ0FGWixFQUVlc0QsbUJBQW1CckQsQ0FGbEMsQ0FBVDs7QUFJQXNELGlCQUFTbkIsY0FBY3lCLEVBQWQsR0FBbUJOLE1BQW5CLEdBQTRCLElBQUlBLE1BQXpDO0FBRUQsT0FQTSxNQU9BO0FBQ0xBLGlCQUFTM0UsU0FBUzRFLDBCQUFULENBQW9DcEIsVUFBVXBDLENBQTlDLEVBQWlEb0MsVUFBVW5DLENBQTNELEVBQ1BvQyxVQUFVckMsQ0FESCxFQUNNcUMsVUFBVXBDLENBRGhCLEVBRVBELENBRk8sRUFFSkMsQ0FGSSxDQUFUOztBQUlBc0QsaUJBQVNuQixjQUFjeUIsRUFBZCxHQUFtQk4sTUFBbkIsR0FBNEIsSUFBSUEsTUFBekM7QUFDRDtBQUNGLEtBdkJNLE1BdUJBO0FBQ0xBLGVBQVMzRSxTQUFTNEUsMEJBQVQsQ0FBb0NwQixVQUFVcEMsQ0FBOUMsRUFBaURvQyxVQUFVbkMsQ0FBM0QsRUFDUG9DLFVBQVVyQyxDQURILEVBQ01xQyxVQUFVcEMsQ0FEaEIsRUFFUEQsQ0FGTyxFQUVKQyxDQUZJLENBQVQ7QUFHRDtBQUNGOztBQUVEd0QsU0FBT0EsS0FBS0MsR0FBTCxDQUFTLFFBQVQsRUFBbUJILE1BQW5CLENBQVA7O0FBRUEsU0FBTzlELE1BQU04QixLQUFOLENBQVk7QUFDakJaLFdBQU9BLE1BQU11RCxPQUFOLENBQWMsQ0FBQyxRQUFELEVBQVduRSxPQUFYLEVBQW9CLE9BQXBCLEVBQTZCSyxNQUE3QixDQUFkLEVBQW9EcUQsSUFBcEQ7QUFEVSxHQUFaLENBQVA7QUFJRDs7QUFFRCxTQUFTbkQsZUFBVCxDQUF5QmIsS0FBekIsRUFBZ0NPLENBQWhDLEVBQW1DQyxDQUFuQyxFQUFzQztBQUNwQ1IsVUFBUVksbUJBQW1CWixLQUFuQixFQUEwQk8sQ0FBMUIsRUFBNkJDLENBQTdCLENBQVI7QUFDQSxTQUFPUixNQUFNOEIsS0FBTixDQUFZO0FBQ2pCQyxVQUFNL0MsU0FEVztBQUVqQmtGLGtCQUFjbEUsTUFBTWtFLFlBQU4sQ0FBbUJDLElBQW5CLENBQXdCbkUsTUFBTWtCLEtBQTlCO0FBRkcsR0FBWixDQUFQO0FBSUQ7O0FBRUQsU0FBU0osVUFBVCxDQUFvQmQsS0FBcEIsRUFBMkJNLE9BQTNCLEVBQW9DSyxNQUFwQyxFQUE0QztBQUMxQyxNQUFJTyxRQUFRbEIsTUFBTWtCLEtBQWxCOztBQUVBQSxVQUFRQSxNQUFNWSxLQUFOLENBQVk7QUFDbEI0QyxZQUFReEQsTUFBTXdELE1BQU4sQ0FBYUMsR0FBYixDQUFpQnJGLFdBQWpCLENBRFU7QUFFbEI2QixtQkFBZWI7QUFGRyxHQUFaLENBQVI7O0FBS0FZLFVBQVFBLE1BQU1tQixRQUFOLENBQWUsQ0FBQyxRQUFELEVBQVcvQixPQUFYLENBQWYsRUFBb0M7QUFBQSxXQUFTZ0MsTUFBTXRCLGFBQU4sQ0FBb0IsaUJBQVM7QUFDaEY1QixhQUFPa0QsS0FBUCxFQUFjLE9BQWQsRUFBdUIzQixNQUF2QjtBQUNELEtBRm9ELENBQVQ7QUFBQSxHQUFwQyxDQUFSOztBQUlBLFNBQU9YLE1BQU04QixLQUFOLENBQVk7QUFDakJaLGdCQURpQjtBQUVqQmdELGtCQUFjbEUsTUFBTWtFLFlBQU4sQ0FBbUJDLElBQW5CLENBQXdCakQsS0FBeEI7QUFGRyxHQUFaLENBQVA7QUFJRCIsImZpbGUiOiJob2xlcy1yZWR1Y2VyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtMaXN0LCBNYXB9IGZyb20gJ2ltbXV0YWJsZSc7XG5cbmltcG9ydCB7XG4gIFNFTEVDVF9UT09MX0RSQVdJTkdfSE9MRSxcbiAgVVBEQVRFX0RSQVdJTkdfSE9MRSxcbiAgRU5EX0RSQVdJTkdfSE9MRSxcbiAgQkVHSU5fRFJBR0dJTkdfSE9MRSxcbiAgVVBEQVRFX0RSQUdHSU5HX0hPTEUsXG4gIEVORF9EUkFHR0lOR19IT0xFLFxuICBTRUxFQ1RfSE9MRSxcblxuICBNT0RFX0lETEUsXG4gIE1PREVfRFJBV0lOR19IT0xFLFxuICBNT0RFX0RSQUdHSU5HX0hPTEUsXG59IGZyb20gJy4uL2NvbnN0YW50cyc7XG5cbmltcG9ydCAqIGFzIEdlb21ldHJ5IGZyb20gJy4uL3V0aWxzL2dlb21ldHJ5JztcbmltcG9ydCB7XG4gIHNlbGVjdCxcbiAgdW5zZWxlY3QsXG4gIHVuc2VsZWN0QWxsLFxuICBhZGRIb2xlLFxuICByZW1vdmVIb2xlLFxufSBmcm9tICcuLi91dGlscy9sYXllci1vcGVyYXRpb25zJztcbmltcG9ydCB7XG4gIG5lYXJlc3RTbmFwLFxuICBhZGRQb2ludFNuYXAsXG4gIGFkZExpbmVTbmFwLFxuICBhZGRMaW5lU2VnbWVudFNuYXAsXG4gIFNOQVBfUE9JTlQsXG4gIFNOQVBfTElORSxcbiAgU05BUF9TRUdNRU5UXG59IGZyb20gJy4uL3V0aWxzL3NuYXAnO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiAoc3RhdGUsIGFjdGlvbikge1xuICBzd2l0Y2ggKGFjdGlvbi50eXBlKSB7XG4gICAgY2FzZSBTRUxFQ1RfVE9PTF9EUkFXSU5HX0hPTEU6XG4gICAgICByZXR1cm4gc2VsZWN0VG9vbERyYXdpbmdIb2xlKHN0YXRlLCBhY3Rpb24uc2NlbmVDb21wb25lbnRUeXBlKTtcblxuICAgIGNhc2UgVVBEQVRFX0RSQVdJTkdfSE9MRTpcbiAgICAgIHJldHVybiB1cGRhdGVEcmF3aW5nSG9sZShzdGF0ZSwgYWN0aW9uLmxheWVySUQsIGFjdGlvbi54LCBhY3Rpb24ueSk7XG5cbiAgICBjYXNlIEVORF9EUkFXSU5HX0hPTEU6XG4gICAgICByZXR1cm4gZW5kRHJhd2luZ0hvbGUoc3RhdGUsIGFjdGlvbi5sYXllcklELCBhY3Rpb24ueCwgYWN0aW9uLnkpO1xuXG4gICAgY2FzZSBCRUdJTl9EUkFHR0lOR19IT0xFOlxuICAgICAgcmV0dXJuIGJlZ2luRHJhZ2dpbmdIb2xlKHN0YXRlLCBhY3Rpb24ubGF5ZXJJRCwgYWN0aW9uLmhvbGVJRCwgYWN0aW9uLngsIGFjdGlvbi55KTtcblxuICAgIGNhc2UgVVBEQVRFX0RSQUdHSU5HX0hPTEU6XG4gICAgICByZXR1cm4gdXBkYXRlRHJhZ2dpbmdIb2xlKHN0YXRlLCBhY3Rpb24ueCwgYWN0aW9uLnkpO1xuXG4gICAgY2FzZSBFTkRfRFJBR0dJTkdfSE9MRTpcbiAgICAgIHJldHVybiBlbmREcmFnZ2luZ0hvbGUoc3RhdGUsIGFjdGlvbi54LCBhY3Rpb24ueSk7XG5cbiAgICBjYXNlIFNFTEVDVF9IT0xFOlxuICAgICAgcmV0dXJuIHNlbGVjdEhvbGUoc3RhdGUsIGFjdGlvbi5sYXllcklELCBhY3Rpb24uaG9sZUlEKTtcblxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gc3RhdGU7XG4gIH1cbn1cblxuZnVuY3Rpb24gc2VsZWN0VG9vbERyYXdpbmdIb2xlKHN0YXRlLCBzY2VuZUNvbXBvbmVudFR5cGUpIHtcblxuICBsZXQgc25hcEVsZW1lbnRzID0gKG5ldyBMaXN0KCkpLndpdGhNdXRhdGlvbnMoc25hcEVsZW1lbnRzID0+IHtcbiAgICBsZXQge2xpbmVzLCB2ZXJ0aWNlc30gPSBzdGF0ZS5nZXRJbihbJ3NjZW5lJywgJ2xheWVycycsIHN0YXRlLnNjZW5lLnNlbGVjdGVkTGF5ZXJdKTtcblxuICAgIGxpbmVzLmZvckVhY2gobGluZSA9PiB7XG4gICAgICBsZXQge3g6IHgxLCB5OiB5MX0gPSB2ZXJ0aWNlcy5nZXQobGluZS52ZXJ0aWNlcy5nZXQoMCkpO1xuICAgICAgbGV0IHt4OiB4MiwgeTogeTJ9ID0gdmVydGljZXMuZ2V0KGxpbmUudmVydGljZXMuZ2V0KDEpKTtcblxuICAgICAgYWRkTGluZVNlZ21lbnRTbmFwKHNuYXBFbGVtZW50cywgeDEsIHkxLCB4MiwgeTIsIDIwLCAxLCBsaW5lLmlkKTtcbiAgICB9KVxuICB9KTtcblxuICByZXR1cm4gc3RhdGUubWVyZ2Uoe1xuICAgIG1vZGU6IE1PREVfRFJBV0lOR19IT0xFLFxuICAgIHNuYXBFbGVtZW50cyxcbiAgICBkcmF3aW5nU3VwcG9ydDogTWFwKHtcbiAgICAgIHR5cGU6IHNjZW5lQ29tcG9uZW50VHlwZVxuICAgIH0pXG4gIH0pO1xufVxuXG4vKiogaG9sZXMgb3BlcmF0aW9ucyAqKi9cbmZ1bmN0aW9uIHVwZGF0ZURyYXdpbmdIb2xlKHN0YXRlLCBsYXllcklELCB4LCB5KSB7XG4gIGxldCBjYXRhbG9nID0gc3RhdGUuY2F0YWxvZztcblxuICAvL2NhbGN1bGF0ZSBzbmFwIGFuZCBvdmVyd3JpdGUgY29vcmRzIGlmIG5lZWRlZFxuICAvL2ZvcmNlIHNuYXAgdG8gc2VnbWVudFxuICBsZXQgc25hcCA9IG5lYXJlc3RTbmFwKHN0YXRlLnNuYXBFbGVtZW50cywgeCwgeSwgc3RhdGUuc25hcE1hc2subWVyZ2Uoe1NOQVBfU0VHTUVOVDogdHJ1ZX0pKTtcbiAgaWYgKHNuYXApICh7eCwgeX0gPSBzbmFwLnBvaW50KTtcblxuICBsZXQgc2NlbmUgPSBzdGF0ZS5zY2VuZS51cGRhdGVJbihbJ2xheWVycycsIGxheWVySURdLCBsYXllciA9PiBsYXllci53aXRoTXV0YXRpb25zKGxheWVyID0+IHtcbiAgICBsZXQgc2VsZWN0ZWRIb2xlID0gbGF5ZXIuZ2V0SW4oWydzZWxlY3RlZCcsICdob2xlcyddKS5maXJzdCgpO1xuICAgIGlmIChzZWxlY3RlZEhvbGUpIHtcbiAgICAgIHVuc2VsZWN0KGxheWVyLCAnaG9sZXMnLCBzZWxlY3RlZEhvbGUpO1xuICAgICAgcmVtb3ZlSG9sZShsYXllciwgc2VsZWN0ZWRIb2xlKTtcbiAgICB9XG5cbiAgICBpZiAoc25hcCkge1xuICAgICAgbGV0IGxpbmVJRCA9IHNuYXAuc25hcC5yZWxhdGVkLmdldCgwKTtcbiAgICAgIGxldCBsaW5lID0gbGF5ZXIuZ2V0SW4oWydsaW5lcycsIGxpbmVJRF0pO1xuICAgICAgbGV0IHt4OiB4MSwgeTogeTF9ID0gbGF5ZXIudmVydGljZXMuZ2V0KGxpbmUudmVydGljZXMuZ2V0KDApKTtcbiAgICAgIGxldCB7eDogeDIsIHk6IHkyfSA9IGxheWVyLnZlcnRpY2VzLmdldChsaW5lLnZlcnRpY2VzLmdldCgxKSk7XG5cbiAgICAgIC8vIEkgbmVlZCBtaW4gYW5kIG1heCB2ZXJ0aWNlcyBvbiB0aGlzIGxpbmUgc2VnbWVudFxuICAgICAgbGV0IG1pblZlcnRleCA9IEdlb21ldHJ5Lm1pblZlcnRleCh7eDogeDEsIHk6IHkxfSwge3g6IHgyLCB5OiB5Mn0pO1xuICAgICAgbGV0IG1heFZlcnRleCA9IEdlb21ldHJ5Lm1heFZlcnRleCh7eDogeDEsIHk6IHkxfSwge3g6IHgyLCB5OiB5Mn0pO1xuICAgICAgbGV0IHdpZHRoID0gY2F0YWxvZy5mYWN0b3J5RWxlbWVudChzdGF0ZS5kcmF3aW5nU3VwcG9ydC5nZXQoJ3R5cGUnKSwge30sIHt9KS5wcm9wZXJ0aWVzLmdldCgnd2lkdGgnKS5nZXQoJ2xlbmd0aCcpO1xuXG5cbiAgICAgIC8vIE5vdyBJIG5lZWQgbWluIGFuZCBtYXggcG9zc2libGUgY29vcmRpbmF0ZXMgZm9yIHRoZSBob2xlIG9uIHRoZSBsaW5lLiBUaGV5IGRlcGVuZCBvbiB0aGUgd2lkdGggb2YgdGhlIGhvbGVcblxuICAgICAgLy8gbGV0IHdpZHRoID0gaG9sZS5wcm9wZXJ0aWVzLmdldCgnd2lkdGgnKS5nZXQoJ2xlbmd0aCcpO1xuICAgICAgbGV0IGxpbmVMZW5ndGggPSBHZW9tZXRyeS5wb2ludHNEaXN0YW5jZSh4MSwgeTEsIHgyLCB5Mik7XG4gICAgICBsZXQgYWxwaGEgPSBNYXRoLmF0YW4yKE1hdGguYWJzKHkyIC0geTEpLCBNYXRoLmFicyh4MiAtIHgxKSk7XG5cbiAgICAgIGxldCBjb3NXaXRoVGhyZXNob2xkID0gKGFscGhhKSA9PiB7XG4gICAgICAgIGxldCBjb3MgPSBNYXRoLmNvcyhhbHBoYSk7XG4gICAgICAgIHJldHVybiBjb3MgPCAwLjAwMDAwMDEgPyAwIDogY29zO1xuICAgICAgfTtcblxuICAgICAgbGV0IHNpbldpdGhUaHJlc2hvbGQgPSAoYWxwaGEpID0+IHtcbiAgICAgICAgbGV0IHNpbiA9IE1hdGguc2luKGFscGhhKTtcbiAgICAgICAgcmV0dXJuIHNpbiA8IDAuMDAwMDAwMSA/IDAgOiBzaW47XG4gICAgICB9O1xuXG4gICAgICBsZXQgY29zQWxwaGEgPSBjb3NXaXRoVGhyZXNob2xkKGFscGhhKTtcbiAgICAgIGxldCBzaW5BbHBoYSA9IHNpbldpdGhUaHJlc2hvbGQoYWxwaGEpO1xuXG4gICAgICBsZXQgbWluTGVmdFZlcnRleEhvbGUgPSB7XG4gICAgICAgIHg6IG1pblZlcnRleC54ICsgd2lkdGggLyAyICogY29zQWxwaGEsXG4gICAgICAgIHk6IG1pblZlcnRleC55ICsgd2lkdGggLyAyICogc2luQWxwaGFcbiAgICAgIH07XG5cbiAgICAgIGxldCBtYXhSaWdodFZlcnRleEhvbGUgPSB7XG4gICAgICAgIHg6IG1pblZlcnRleC54ICsgbGluZUxlbmd0aCAqIGNvc0FscGhhIC0gd2lkdGggLyAyICogY29zQWxwaGEsXG4gICAgICAgIHk6IG1pblZlcnRleC55ICsgbGluZUxlbmd0aCAqIHNpbkFscGhhIC0gd2lkdGggLyAyICogc2luQWxwaGFcbiAgICAgIH07XG5cbiAgICAgIGxldCBvZmZzZXQ7XG4gICAgICBpZiAoeCA8IG1pbkxlZnRWZXJ0ZXhIb2xlLngpIHtcbiAgICAgICAgb2Zmc2V0ID0gR2VvbWV0cnkucG9pbnRQb3NpdGlvbk9uTGluZVNlZ21lbnQobWluVmVydGV4LngsIG1pblZlcnRleC55LFxuICAgICAgICAgIG1heFZlcnRleC54LCBtYXhWZXJ0ZXgueSxcbiAgICAgICAgICBtaW5MZWZ0VmVydGV4SG9sZS54LCBtaW5MZWZ0VmVydGV4SG9sZS55KTtcbiAgICAgIH0gZWxzZSBpZiAoeCA+IG1heFJpZ2h0VmVydGV4SG9sZS54KSB7XG4gICAgICAgIG9mZnNldCA9IEdlb21ldHJ5LnBvaW50UG9zaXRpb25PbkxpbmVTZWdtZW50KG1pblZlcnRleC54LCBtaW5WZXJ0ZXgueSxcbiAgICAgICAgICBtYXhWZXJ0ZXgueCwgbWF4VmVydGV4LnksXG4gICAgICAgICAgbWF4UmlnaHRWZXJ0ZXhIb2xlLngsIG1heFJpZ2h0VmVydGV4SG9sZS55KTtcbiAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgaWYgKHggPT09IG1pbkxlZnRWZXJ0ZXhIb2xlLnggJiYgeCA9PT0gbWF4UmlnaHRWZXJ0ZXhIb2xlLngpIHtcblxuICAgICAgICAgIGlmICh5IDwgbWluTGVmdFZlcnRleEhvbGUueSkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gR2VvbWV0cnkucG9pbnRQb3NpdGlvbk9uTGluZVNlZ21lbnQobWluVmVydGV4LngsIG1pblZlcnRleC55LFxuICAgICAgICAgICAgICBtYXhWZXJ0ZXgueCwgbWF4VmVydGV4LnksXG4gICAgICAgICAgICAgIG1pbkxlZnRWZXJ0ZXhIb2xlLngsIG1pbkxlZnRWZXJ0ZXhIb2xlLnkpO1xuICAgICAgICAgICAgb2Zmc2V0ID0gbWluVmVydGV4LnggPT09IHgxICYmIG1pblZlcnRleC55ID09PSB5MSA/IG9mZnNldCA6IDEgLSBvZmZzZXQ7XG4gICAgICAgICAgfSBlbHNlIGlmICh5ID4gbWF4UmlnaHRWZXJ0ZXhIb2xlLnkpIHtcbiAgICAgICAgICAgIG9mZnNldCA9IEdlb21ldHJ5LnBvaW50UG9zaXRpb25PbkxpbmVTZWdtZW50KG1pblZlcnRleC54LCBtaW5WZXJ0ZXgueSxcbiAgICAgICAgICAgICAgbWF4VmVydGV4LngsIG1heFZlcnRleC55LFxuICAgICAgICAgICAgICBtYXhSaWdodFZlcnRleEhvbGUueCwgbWF4UmlnaHRWZXJ0ZXhIb2xlLnkpO1xuICAgICAgICAgICAgb2Zmc2V0ID0gbWluVmVydGV4LnggPT09IHgxICYmIG1pblZlcnRleC55ID09PSB5MSA/IG9mZnNldCA6IDEgLSBvZmZzZXQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG9mZnNldCA9IEdlb21ldHJ5LnBvaW50UG9zaXRpb25PbkxpbmVTZWdtZW50KHgxLCB5MSwgeDIsIHkyLCB4LCB5KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb2Zmc2V0ID0gR2VvbWV0cnkucG9pbnRQb3NpdGlvbk9uTGluZVNlZ21lbnQoeDEsIHkxLCB4MiwgeTIsIHgsIHkpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIGxldCBvZmZzZXQgPSBHZW9tZXRyeS5wb2ludFBvc2l0aW9uT25MaW5lU2VnbWVudCh4MSwgeTEsIHgyLCB5MiwgeCwgeSk7XG4gICAgICBsZXQge2hvbGV9ID0gYWRkSG9sZShsYXllciwgc3RhdGUuZHJhd2luZ1N1cHBvcnQuZ2V0KCd0eXBlJyksIGxpbmVJRCwgb2Zmc2V0LCBjYXRhbG9nKTtcbiAgICAgIHNlbGVjdChsYXllciwgJ2hvbGVzJywgaG9sZS5pZCk7XG4gICAgfVxuICB9KSk7XG5cbiAgcmV0dXJuIHN0YXRlLnNldCgnc2NlbmUnLCBzY2VuZSk7XG59XG5cbmZ1bmN0aW9uIGVuZERyYXdpbmdIb2xlKHN0YXRlLCBsYXllcklELCB4LCB5KSB7XG4gIGxldCBjYXRhbG9nID0gc3RhdGUuY2F0YWxvZztcblxuICBzdGF0ZSA9IHVwZGF0ZURyYXdpbmdIb2xlKHN0YXRlLCBsYXllcklELCB4LCB5LCBjYXRhbG9nKTtcbiAgbGV0IHNjZW5lID0gc3RhdGUuc2NlbmUudXBkYXRlSW4oWydsYXllcnMnLCBsYXllcklEXSwgbGF5ZXIgPT4gdW5zZWxlY3RBbGwobGF5ZXIpKTtcbiAgcmV0dXJuIHN0YXRlLm1lcmdlKHtcbiAgICBzY2VuZSxcbiAgICBzY2VuZUhpc3Rvcnk6IHN0YXRlLnNjZW5lSGlzdG9yeS5wdXNoKHNjZW5lKVxuICB9KTtcbn1cblxuZnVuY3Rpb24gYmVnaW5EcmFnZ2luZ0hvbGUoc3RhdGUsIGxheWVySUQsIGhvbGVJRCwgeCwgeSkge1xuICBsZXQgbGF5ZXIgPSBzdGF0ZS5nZXRJbihbJ3NjZW5lJywgJ2xheWVycycsIGxheWVySURdKTtcbiAgbGV0IGhvbGUgPSBsYXllci5nZXRJbihbJ2hvbGVzJywgaG9sZUlEXSk7XG4gIGxldCBsaW5lID0gbGF5ZXIuZ2V0SW4oWydsaW5lcycsIGhvbGUubGluZV0pO1xuICBsZXQgdjAgPSBsYXllci5nZXRJbihbJ3ZlcnRpY2VzJywgbGluZS52ZXJ0aWNlcy5nZXQoMCldKTtcbiAgbGV0IHYxID0gbGF5ZXIuZ2V0SW4oWyd2ZXJ0aWNlcycsIGxpbmUudmVydGljZXMuZ2V0KDEpXSk7XG5cbiAgbGV0IHNuYXBFbGVtZW50cyA9IGFkZExpbmVTZWdtZW50U25hcChMaXN0KCksIHYwLngsIHYwLnksIHYxLngsIHYxLnksIDk5OTk5OTksIDEsIG51bGwpO1xuXG4gIHJldHVybiBzdGF0ZS5tZXJnZSh7XG4gICAgbW9kZTogTU9ERV9EUkFHR0lOR19IT0xFLFxuICAgIHNuYXBFbGVtZW50cyxcbiAgICBkcmFnZ2luZ1N1cHBvcnQ6IE1hcCh7XG4gICAgICBsYXllcklELFxuICAgICAgaG9sZUlELFxuICAgICAgc3RhcnRQb2ludFg6IHgsXG4gICAgICBzdGFydFBvaW50WTogeSxcbiAgICB9KVxuICB9KTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlRHJhZ2dpbmdIb2xlKHN0YXRlLCB4LCB5KSB7XG5cbiAgLy9jYWxjdWxhdGUgc25hcCBhbmQgb3ZlcndyaXRlIGNvb3JkcyBpZiBuZWVkZWRcbiAgLy9mb3JjZSBzbmFwIHRvIHNlZ21lbnRcbiAgbGV0IHNuYXAgPSBuZWFyZXN0U25hcChzdGF0ZS5zbmFwRWxlbWVudHMsIHgsIHksIHN0YXRlLnNuYXBNYXNrLm1lcmdlKHtTTkFQX1NFR01FTlQ6IHRydWV9KSk7XG4gIGlmICghc25hcCkgcmV0dXJuIHN0YXRlO1xuXG4gIGxldCB7ZHJhZ2dpbmdTdXBwb3J0LCBzY2VuZX0gPSBzdGF0ZTtcblxuICBsZXQgbGF5ZXJJRCA9IGRyYWdnaW5nU3VwcG9ydC5nZXQoJ2xheWVySUQnKTtcbiAgbGV0IGhvbGVJRCA9IGRyYWdnaW5nU3VwcG9ydC5nZXQoJ2hvbGVJRCcpO1xuICBsZXQgc3RhcnRQb2ludFggPSBkcmFnZ2luZ1N1cHBvcnQuZ2V0KCdzdGFydFBvaW50WCcpO1xuICBsZXQgc3RhcnRQb2ludFkgPSBkcmFnZ2luZ1N1cHBvcnQuZ2V0KCdzdGFydFBvaW50WScpO1xuXG4gIGxldCBsYXllciA9IHN0YXRlLmdldEluKFsnc2NlbmUnLCAnbGF5ZXJzJywgbGF5ZXJJRF0pO1xuICBsZXQgaG9sZSA9IGxheWVyLmdldEluKFsnaG9sZXMnLCBob2xlSURdKTtcbiAgbGV0IGxpbmUgPSBsYXllci5nZXRJbihbJ2xpbmVzJywgaG9sZS5saW5lXSk7XG4gIGxldCB2MCA9IGxheWVyLmdldEluKFsndmVydGljZXMnLCBsaW5lLnZlcnRpY2VzLmdldCgwKV0pO1xuICBsZXQgdjEgPSBsYXllci5nZXRJbihbJ3ZlcnRpY2VzJywgbGluZS52ZXJ0aWNlcy5nZXQoMSldKTtcblxuICAoe3gsIHl9ID0gc25hcC5wb2ludCk7XG5cbiAgLy8gSSBuZWVkIG1pbiBhbmQgbWF4IHZlcnRpY2VzIG9uIHRoaXMgbGluZSBzZWdtZW50XG4gIGxldCBtaW5WZXJ0ZXggPSBHZW9tZXRyeS5taW5WZXJ0ZXgodjAsIHYxKTtcbiAgbGV0IG1heFZlcnRleCA9IEdlb21ldHJ5Lm1heFZlcnRleCh2MCwgdjEpO1xuXG4gIC8vIE5vdyBJIG5lZWQgbWluIGFuZCBtYXggcG9zc2libGUgY29vcmRpbmF0ZXMgZm9yIHRoZSBob2xlIG9uIHRoZSBsaW5lLiBUaGV5IGRlcGVuZCBvbiB0aGUgd2lkdGggb2YgdGhlIGhvbGVcblxuICBsZXQgd2lkdGggPSBob2xlLnByb3BlcnRpZXMuZ2V0KCd3aWR0aCcpLmdldCgnbGVuZ3RoJyk7XG4gIGxldCBsaW5lTGVuZ3RoID0gR2VvbWV0cnkucG9pbnRzRGlzdGFuY2UodjAueCwgdjAueSwgdjEueCwgdjEueSk7XG4gIGxldCBhbHBoYSA9IE1hdGguYXRhbjIoTWF0aC5hYnModjEueSAtIHYwLnkpLCBNYXRoLmFicyh2MS54IC0gdjAueCkpO1xuXG4gIGxldCBjb3NXaXRoVGhyZXNob2xkID0gKGFscGhhKSA9PiB7XG4gICAgbGV0IGNvcyA9IE1hdGguY29zKGFscGhhKTtcbiAgICByZXR1cm4gY29zIDwgMC4wMDAwMDAxID8gMCA6IGNvcztcbiAgfTtcblxuICBsZXQgc2luV2l0aFRocmVzaG9sZCA9IChhbHBoYSkgPT4ge1xuICAgIGxldCBzaW4gPSBNYXRoLnNpbihhbHBoYSk7XG4gICAgcmV0dXJuIHNpbiA8IDAuMDAwMDAwMSA/IDAgOiBzaW47XG4gIH07XG5cbiAgbGV0IGNvc0FscGhhID0gY29zV2l0aFRocmVzaG9sZChhbHBoYSk7XG4gIGxldCBzaW5BbHBoYSA9IHNpbldpdGhUaHJlc2hvbGQoYWxwaGEpO1xuXG4gIGxldCBtaW5MZWZ0VmVydGV4SG9sZSA9IHtcbiAgICB4OiBtaW5WZXJ0ZXgueCArIHdpZHRoIC8gMiAqIGNvc0FscGhhLFxuICAgIHk6IG1pblZlcnRleC55ICsgd2lkdGggLyAyICogc2luQWxwaGFcbiAgfTtcblxuICBsZXQgbWF4UmlnaHRWZXJ0ZXhIb2xlID0ge1xuICAgIHg6IG1pblZlcnRleC54ICsgbGluZUxlbmd0aCAqIGNvc0FscGhhIC0gd2lkdGggLyAyICogY29zQWxwaGEsXG4gICAgeTogbWluVmVydGV4LnkgKyBsaW5lTGVuZ3RoICogc2luQWxwaGEgLSB3aWR0aCAvIDIgKiBzaW5BbHBoYVxuICB9O1xuXG4gIC8vIE5vdyBJIG5lZWQgdG8gdmVyaWZ5IGlmIHRoZSBzbmFwIHZlcnRleCAod2l0aCBjb29yZGluYXRlcyB4IGFuZCB5KSBpcyBvbiB0aGUgbGluZSBzZWdtZW50XG5cbiAgbGV0IG9mZnNldDtcblxuICBpZiAoeCA8IG1pbkxlZnRWZXJ0ZXhIb2xlLngpIHtcbiAgICAvLyBTbmFwIHBvaW50IGlzIHByZXZpb3VzIHRoZSB0aGUgbGluZVxuICAgIG9mZnNldCA9IEdlb21ldHJ5LnBvaW50UG9zaXRpb25PbkxpbmVTZWdtZW50KG1pblZlcnRleC54LCBtaW5WZXJ0ZXgueSxcbiAgICAgIG1heFZlcnRleC54LCBtYXhWZXJ0ZXgueSxcbiAgICAgIG1pbkxlZnRWZXJ0ZXhIb2xlLngsIG1pbkxlZnRWZXJ0ZXhIb2xlLnkpO1xuICB9IGVsc2Uge1xuICAgIC8vIFNuYXAgcG9pbnQgaXMgYWZ0ZXIgdGhlIGxpbmUgb3Igb24gdGhlIGxpbmVcbiAgICBpZiAoeCA+IG1heFJpZ2h0VmVydGV4SG9sZS54KSB7XG4gICAgICBvZmZzZXQgPSBHZW9tZXRyeS5wb2ludFBvc2l0aW9uT25MaW5lU2VnbWVudChtaW5WZXJ0ZXgueCwgbWluVmVydGV4LnksXG4gICAgICAgIG1heFZlcnRleC54LCBtYXhWZXJ0ZXgueSxcbiAgICAgICAgbWF4UmlnaHRWZXJ0ZXhIb2xlLngsIG1heFJpZ2h0VmVydGV4SG9sZS55KTtcbiAgICB9IGVsc2UgaWYgKHggPT09IG1pbkxlZnRWZXJ0ZXhIb2xlLnggJiYgeCA9PT0gbWF4UmlnaHRWZXJ0ZXhIb2xlLngpIHtcbiAgICAgIC8vIEkgYW0gb24gYSB2ZXJ0aWNhbCBsaW5lLCBJIG5lZWQgdG8gY2hlY2sgeSBjb29yZGluYXRlc1xuICAgICAgaWYgKHkgPCBtaW5MZWZ0VmVydGV4SG9sZS55KSB7XG4gICAgICAgIG9mZnNldCA9IEdlb21ldHJ5LnBvaW50UG9zaXRpb25PbkxpbmVTZWdtZW50KG1pblZlcnRleC54LCBtaW5WZXJ0ZXgueSxcbiAgICAgICAgICBtYXhWZXJ0ZXgueCwgbWF4VmVydGV4LnksXG4gICAgICAgICAgbWluTGVmdFZlcnRleEhvbGUueCwgbWluTGVmdFZlcnRleEhvbGUueSk7XG5cbiAgICAgICAgb2Zmc2V0ID0gbWluVmVydGV4ID09PSB2MCA/IG9mZnNldCA6IDEgLSBvZmZzZXQ7XG5cbiAgICAgIH0gZWxzZSBpZiAoeSA+IG1heFJpZ2h0VmVydGV4SG9sZS55KSB7XG4gICAgICAgIG9mZnNldCA9IEdlb21ldHJ5LnBvaW50UG9zaXRpb25PbkxpbmVTZWdtZW50KG1pblZlcnRleC54LCBtaW5WZXJ0ZXgueSxcbiAgICAgICAgICBtYXhWZXJ0ZXgueCwgbWF4VmVydGV4LnksXG4gICAgICAgICAgbWF4UmlnaHRWZXJ0ZXhIb2xlLngsIG1heFJpZ2h0VmVydGV4SG9sZS55KTtcblxuICAgICAgICBvZmZzZXQgPSBtaW5WZXJ0ZXggPT09IHYwID8gb2Zmc2V0IDogMSAtIG9mZnNldDtcblxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb2Zmc2V0ID0gR2VvbWV0cnkucG9pbnRQb3NpdGlvbk9uTGluZVNlZ21lbnQobWluVmVydGV4LngsIG1pblZlcnRleC55LFxuICAgICAgICAgIG1heFZlcnRleC54LCBtYXhWZXJ0ZXgueSxcbiAgICAgICAgICB4LCB5KTtcblxuICAgICAgICBvZmZzZXQgPSBtaW5WZXJ0ZXggPT09IHYwID8gb2Zmc2V0IDogMSAtIG9mZnNldDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgb2Zmc2V0ID0gR2VvbWV0cnkucG9pbnRQb3NpdGlvbk9uTGluZVNlZ21lbnQobWluVmVydGV4LngsIG1pblZlcnRleC55LFxuICAgICAgICBtYXhWZXJ0ZXgueCwgbWF4VmVydGV4LnksXG4gICAgICAgIHgsIHkpO1xuICAgIH1cbiAgfVxuXG4gIGhvbGUgPSBob2xlLnNldCgnb2Zmc2V0Jywgb2Zmc2V0KTtcblxuICByZXR1cm4gc3RhdGUubWVyZ2Uoe1xuICAgIHNjZW5lOiBzY2VuZS5tZXJnZUluKFsnbGF5ZXJzJywgbGF5ZXJJRCwgJ2hvbGVzJywgaG9sZUlEXSwgaG9sZSlcbiAgfSk7XG5cbn1cblxuZnVuY3Rpb24gZW5kRHJhZ2dpbmdIb2xlKHN0YXRlLCB4LCB5KSB7XG4gIHN0YXRlID0gdXBkYXRlRHJhZ2dpbmdIb2xlKHN0YXRlLCB4LCB5KTtcbiAgcmV0dXJuIHN0YXRlLm1lcmdlKHtcbiAgICBtb2RlOiBNT0RFX0lETEUsXG4gICAgc2NlbmVIaXN0b3J5OiBzdGF0ZS5zY2VuZUhpc3RvcnkucHVzaChzdGF0ZS5zY2VuZSlcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHNlbGVjdEhvbGUoc3RhdGUsIGxheWVySUQsIGhvbGVJRCkge1xuICBsZXQgc2NlbmUgPSBzdGF0ZS5zY2VuZTtcblxuICBzY2VuZSA9IHNjZW5lLm1lcmdlKHtcbiAgICBsYXllcnM6IHNjZW5lLmxheWVycy5tYXAodW5zZWxlY3RBbGwpLFxuICAgIHNlbGVjdGVkTGF5ZXI6IGxheWVySURcbiAgfSk7XG5cbiAgc2NlbmUgPSBzY2VuZS51cGRhdGVJbihbJ2xheWVycycsIGxheWVySURdLCBsYXllciA9PiBsYXllci53aXRoTXV0YXRpb25zKGxheWVyID0+IHtcbiAgICBzZWxlY3QobGF5ZXIsICdob2xlcycsIGhvbGVJRCk7XG4gIH0pKTtcblxuICByZXR1cm4gc3RhdGUubWVyZ2Uoe1xuICAgIHNjZW5lLFxuICAgIHNjZW5lSGlzdG9yeTogc3RhdGUuc2NlbmVIaXN0b3J5LnB1c2goc2NlbmUpXG4gIH0pXG59XG4iXX0=