@eliorar/angular-cesium
Version:
Angular library for working with Cesium.
315 lines • 47.9 kB
JavaScript
import { CallbackProperty, Cartesian3, ColorGeometryInstanceAttribute, GeometryInstance, GroundPolylineGeometry, GroundPolylinePrimitive, PolylineColorAppearance } from 'cesium';
import { AcEntity } from '../../angular-cesium/models/ac-entity';
import { EditPoint } from './edit-point';
import { EditPolyline } from './edit-polyline';
import { GeoUtilsService } from '../../angular-cesium/services/geo-utils/geo-utils.service';
import { defaultLabelProps } from './label-props';
export class EditablePolyline extends AcEntity {
constructor(id, pointsLayer, polylinesLayer, coordinateConverter, scene, editOptions, positions) {
super();
this.id = id;
this.pointsLayer = pointsLayer;
this.polylinesLayer = polylinesLayer;
this.coordinateConverter = coordinateConverter;
this.scene = scene;
this.editOptions = editOptions;
this.positions = [];
this.polylines = [];
this.doneCreation = false;
this._enableEdit = true;
this._labels = [];
this._outlineInstance = null;
this._pointProps = { ...editOptions.pointProps };
this.props = { ...editOptions.polylineProps };
if (positions && positions.length >= 2) {
this.createFromExisting(positions);
}
}
get labels() {
return this._labels;
}
set labels(labels) {
if (!labels) {
return;
}
const positions = this.getRealPositions();
this._labels = labels.map((label, index) => {
if (!label.position) {
label.position = positions[index];
}
return Object.assign({}, defaultLabelProps, label);
});
}
get props() {
return this.polylineProps;
}
set props(value) {
this.polylineProps = value;
}
get pointProps() {
return this._pointProps;
}
set pointProps(value) {
this._pointProps = value;
}
get enableEdit() {
return this._enableEdit;
}
set enableEdit(value) {
this._enableEdit = value;
this.positions.forEach(point => {
point.show = value;
this.updatePointsLayer(false, point);
});
}
createFromExisting(positions) {
positions.forEach((position) => {
this.addPointFromExisting(position);
});
this.addAllVirtualEditPoints();
this.doneCreation = true;
}
setManually(points, polylineProps) {
if (!this.doneCreation) {
throw new Error('Update manually only in edit mode, after polyline is created');
}
this.positions.forEach(p => this.pointsLayer.remove(p.getId()));
const newPoints = [];
for (let i = 0; i < points.length; i++) {
const pointOrCartesian = points[i];
let newPoint = null;
if (pointOrCartesian.pointProps) {
newPoint = new EditPoint(this.id, pointOrCartesian.position, pointOrCartesian.pointProps);
}
else {
newPoint = new EditPoint(this.id, pointOrCartesian, this._pointProps);
}
newPoints.push(newPoint);
}
this.positions = newPoints;
this.polylineProps = polylineProps ? polylineProps : this.polylineProps;
this.updatePointsLayer(true, ...this.positions);
this.addAllVirtualEditPoints();
}
addAllVirtualEditPoints() {
const currentPoints = [...this.positions];
currentPoints.forEach((pos, index) => {
if (index !== currentPoints.length - 1) {
const currentPoint = pos;
const nextIndex = (index + 1) % (currentPoints.length);
const nextPoint = currentPoints[nextIndex];
const midPoint = this.setMiddleVirtualPoint(currentPoint, nextPoint);
this.updatePointsLayer(false, midPoint);
}
});
}
setMiddleVirtualPoint(firstP, secondP) {
const pos1 = firstP.getPosition();
const pos2 = secondP.getPosition();
const midPointCartesian3 = Cartesian3.lerp(new Cartesian3(pos1.x, pos1.y, pos1.z), new Cartesian3(pos2.x, pos2.y, pos2.z), 0.5, new Cartesian3());
const midPoint = new EditPoint(this.id, midPointCartesian3, this._pointProps);
midPoint.setVirtualEditPoint(true);
const firstIndex = this.positions.indexOf(firstP);
this.positions.splice(firstIndex + 1, 0, midPoint);
return midPoint;
}
updateMiddleVirtualPoint(virtualEditPoint, prevPoint, nextPoint) {
const pos1 = prevPoint.getPosition();
const pos2 = nextPoint.getPosition();
const midPointCartesian3 = Cartesian3.lerp(new Cartesian3(pos1.x, pos1.y, pos1.z), new Cartesian3(pos2.x, pos2.y, pos2.z), 0.5, new Cartesian3());
virtualEditPoint.setPosition(midPointCartesian3);
}
changeVirtualPointToRealPoint(point) {
point.setVirtualEditPoint(false); // actual point becomes a real point
const pointsCount = this.positions.length;
const pointIndex = this.positions.indexOf(point);
const nextIndex = (pointIndex + 1) % (pointsCount);
const preIndex = ((pointIndex - 1) + pointsCount) % pointsCount;
const nextPoint = this.positions[nextIndex];
const prePoint = this.positions[preIndex];
const firstMidPoint = this.setMiddleVirtualPoint(prePoint, point);
const secMidPoint = this.setMiddleVirtualPoint(point, nextPoint);
this.updatePointsLayer(false, firstMidPoint, secMidPoint, point);
}
renderPolylines() {
const realPoints = this.positions.filter(point => !point.isVirtualEditPoint());
if (this.polylineProps.useGroundPrimitiveOutline) {
if (realPoints.length < 2) {
return;
}
this.scene.groundPrimitives.remove(this._outlineInstance);
const instance = new GeometryInstance({
geometry: new GroundPolylineGeometry({
positions: this.positions.map(p => p.getPosition()),
width: this.polylineProps.width,
loop: false
}),
id: 'edit-polygon-outline-' + this.id,
attributes: {
color: ColorGeometryInstanceAttribute.fromColor(this.polylineProps.material())
}
});
this._outlineInstance = this.scene.groundPrimitives.add(new GroundPolylinePrimitive({
geometryInstances: instance,
asynchronous: false,
appearance: new PolylineColorAppearance()
}));
}
else {
this.polylines.forEach(polyline => this.polylinesLayer.remove(polyline.getId()));
this.polylines = [];
realPoints.forEach((point, index) => {
if (index !== realPoints.length - 1) {
const nextIndex = (index + 1);
const nextPoint = realPoints[nextIndex];
const polyline = new EditPolyline(this.id, point.getPosition(), nextPoint.getPosition(), this.polylineProps);
this.polylines.push(polyline);
this.polylinesLayer.update(polyline, polyline.getId());
}
});
}
}
addPointFromExisting(position) {
const newPoint = new EditPoint(this.id, position, this._pointProps);
this.positions.push(newPoint);
this.updatePointsLayer(true, newPoint);
}
addPoint(position) {
if (this.doneCreation) {
return;
}
const isFirstPoint = !this.positions.length;
if (isFirstPoint) {
const firstPoint = new EditPoint(this.id, position, this._pointProps);
this.positions.push(firstPoint);
this.updatePointsLayer(true, firstPoint);
}
this.movingPoint = new EditPoint(this.id, position.clone(), this._pointProps);
this.positions.push(this.movingPoint);
this.updatePointsLayer(true, this.movingPoint);
}
movePointFinish(editPoint) {
if (this.editOptions.clampHeightTo3D) {
editPoint.props.disableDepthTestDistance = Number.POSITIVE_INFINITY;
this.updatePointsLayer(false, editPoint);
}
}
movePoint(toPosition, editPoint) {
editPoint.setPosition(toPosition);
if (this.doneCreation) {
if (editPoint.props.disableDepthTestDistance && this.editOptions.clampHeightTo3D) {
// To avoid bug with pickPosition() on point with disableDepthTestDistance
editPoint.props.disableDepthTestDistance = undefined;
return; // ignore first move because the pickPosition() could be wrong
}
if (editPoint.isVirtualEditPoint()) {
this.changeVirtualPointToRealPoint(editPoint);
}
const pointsCount = this.positions.length;
const pointIndex = this.positions.indexOf(editPoint);
if (pointIndex < this.positions.length - 1) {
const nextVirtualPoint = this.positions[(pointIndex + 1) % (pointsCount)];
const nextRealPoint = this.positions[(pointIndex + 2) % (pointsCount)];
this.updateMiddleVirtualPoint(nextVirtualPoint, editPoint, nextRealPoint);
}
if (pointIndex > 0) {
const prevVirtualPoint = this.positions[((pointIndex - 1) + pointsCount) % pointsCount];
const prevRealPoint = this.positions[((pointIndex - 2) + pointsCount) % pointsCount];
this.updateMiddleVirtualPoint(prevVirtualPoint, editPoint, prevRealPoint);
}
}
this.updatePointsLayer(true, editPoint);
}
moveTempMovingPoint(toPosition) {
if (this.movingPoint) {
this.movePoint(toPosition, this.movingPoint);
}
}
moveShape(startMovingPosition, draggedToPosition) {
if (!this.doneCreation) {
return;
}
if (!this.lastDraggedToPosition) {
this.lastDraggedToPosition = startMovingPosition;
}
const delta = GeoUtilsService.getPositionsDelta(this.lastDraggedToPosition, new Cartesian3(draggedToPosition.x, draggedToPosition.y, draggedToPosition.z));
this.positions.forEach(point => {
const pos = point.getPosition();
const newPos = GeoUtilsService.addDeltaToPosition(new Cartesian3(pos.x, pos.y, pos.z), delta, true);
point.setPosition(newPos);
});
this.updatePointsLayer(true, ...this.positions);
this.lastDraggedToPosition = draggedToPosition;
}
endMoveShape() {
this.lastDraggedToPosition = undefined;
this.updatePointsLayer(true, ...this.positions);
}
removePoint(pointToRemove) {
this.removePosition(pointToRemove);
this.positions
.filter(p => p.isVirtualEditPoint())
.forEach(p => this.removePosition(p));
this.addAllVirtualEditPoints();
this.renderPolylines();
}
addLastPoint(position) {
this.doneCreation = true;
this.removePosition(this.movingPoint); // remove movingPoint
this.movingPoint = null;
this.addAllVirtualEditPoints();
}
getRealPositions() {
return this.getRealPoints()
.map(position => position.getPosition());
}
getRealPoints() {
return this.positions
.filter(position => !position.isVirtualEditPoint() && position !== this.movingPoint);
}
getPoints() {
return this.positions.filter(position => position !== this.movingPoint);
}
getPositions() {
return this.positions.map(position => position.getPosition());
}
getPositionsCallbackProperty() {
return new CallbackProperty(this.getPositions.bind(this), false);
}
removePosition(point) {
const index = this.positions.findIndex((p) => p === point);
if (index < 0) {
return;
}
this.positions.splice(index, 1);
this.pointsLayer.remove(point.getId());
}
updatePointsLayer(renderPolylines = true, ...point) {
if (renderPolylines) {
this.renderPolylines();
}
point.forEach(p => this.pointsLayer.update(p, p.getId()));
}
update() {
this.updatePointsLayer();
}
dispose() {
this.scene.groundPrimitives.remove(this._outlineInstance);
this.positions.forEach(editPoint => {
this.pointsLayer.remove(editPoint.getId());
});
this.polylines.forEach(line => this.polylinesLayer.remove(line.getId()));
if (this.movingPoint) {
this.pointsLayer.remove(this.movingPoint.getId());
this.movingPoint = undefined;
}
this.positions.length = 0;
}
getPointsCount() {
return this.positions.length;
}
getId() {
return this.id;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWRpdGFibGUtcG9seWxpbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLWNlc2l1bS9zcmMvbGliL2FuZ3VsYXItY2VzaXVtLXdpZGdldHMvbW9kZWxzL2VkaXRhYmxlLXBvbHlsaW5lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxnQkFBZ0IsRUFDaEIsVUFBVSxFQUNWLDhCQUE4QixFQUM5QixnQkFBZ0IsRUFDaEIsc0JBQXNCLEVBQ3RCLHVCQUF1QixFQUN2Qix1QkFBdUIsRUFDeEIsTUFBTSxRQUFRLENBQUM7QUFDaEIsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLHVDQUF1QyxDQUFDO0FBQy9ELE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSxjQUFjLENBQUM7QUFDdkMsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBSzdDLE9BQU8sRUFBQyxlQUFlLEVBQUMsTUFBTSwyREFBMkQsQ0FBQztBQUMxRixPQUFPLEVBQUMsaUJBQWlCLEVBQWEsTUFBTSxlQUFlLENBQUM7QUFFNUQsTUFBTSxPQUFPLGdCQUFpQixTQUFRLFFBQVE7SUFhNUMsWUFBb0IsRUFBVSxFQUNWLFdBQTZCLEVBQzdCLGNBQWdDLEVBQ2hDLG1CQUF3QyxFQUN4QyxLQUFVLEVBQ1YsV0FBZ0MsRUFDeEMsU0FBd0I7UUFDbEMsS0FBSyxFQUFFLENBQUM7UUFQVSxPQUFFLEdBQUYsRUFBRSxDQUFRO1FBQ1YsZ0JBQVcsR0FBWCxXQUFXLENBQWtCO1FBQzdCLG1CQUFjLEdBQWQsY0FBYyxDQUFrQjtRQUNoQyx3QkFBbUIsR0FBbkIsbUJBQW1CLENBQXFCO1FBQ3hDLFVBQUssR0FBTCxLQUFLLENBQUs7UUFDVixnQkFBVyxHQUFYLFdBQVcsQ0FBcUI7UUFqQjVDLGNBQVMsR0FBZ0IsRUFBRSxDQUFDO1FBRTVCLGNBQVMsR0FBbUIsRUFBRSxDQUFDO1FBRS9CLGlCQUFZ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O1FBQ0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQzVCLENBQUM7SUFFRCxjQUFjO1FBQ1osT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztJQUMvQixDQUFDO0lBRUQsS0FBSztRQUNILE9BQU8sSUFBSSxDQUFDLEVBQUUsQ0FBQztJQUNqQixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDYWxsYmFja1Byb3BlcnR5LFxuICBDYXJ0ZXNpYW4zLFxuICBDb2xvckdlb21ldHJ5SW5zdGFuY2VBdHRyaWJ1dGUsXG4gIEdlb21ldHJ5SW5zdGFuY2UsXG4gIEdyb3VuZFBvbHlsaW5lR2VvbWV0cnksXG4gIEdyb3VuZFBvbHlsaW5lUHJpbWl0aXZlLFxuICBQb2x5bGluZUNvbG9yQXBwZWFyYW5jZVxufSBmcm9tICdjZXNpdW0nO1xuaW1wb3J0IHtBY0VudGl0eX0gZnJvbSAnLi4vLi4vYW5ndWxhci1jZXNpdW0vbW9kZWxzL2FjLWVudGl0eSc7XG5pbXBvcnQge0VkaXRQb2ludH0gZnJvbSAnLi9lZGl0LXBvaW50JztcbmltcG9ydCB7RWRpdFBvbHlsaW5lfSBmcm9tICcuL2VkaXQtcG9seWxpbmUnO1xuaW1wb3J0IHtBY0xheWVyQ29tcG9uZW50fSBmcm9tICcuLi8uLi9hbmd1bGFyLWNlc2l1bS9jb21wb25lbnRzL2FjLWxheWVyL2FjLWxheWVyLmNvbXBvbmVudCc7XG5pbXBvcnQge0Nvb3JkaW5hdGVDb252ZXJ0ZXJ9IGZyb20gJy4uLy4uL2FuZ3VsYXItY2VzaXVtL3NlcnZpY2VzL2Nvb3JkaW5hdGUtY29udmVydGVyL2Nvb3JkaW5hdGUtY29udmVydGVyLnNlcnZpY2UnO1xuaW1wb3J0IHtQb2ludFByb3BzfSBmcm9tICcuL3BvaW50LWVkaXQtb3B0aW9ucyc7XG5pbXBvcnQge1BvbHlsaW5lRWRpdE9wdGlvbnMsIFBvbHlsaW5lUHJvcHN9IGZyb20gJy4vcG9seWxpbmUtZWRpdC1vcHRpb25zJztcbmltcG9ydCB7R2VvVXRpbHNTZXJ2aWNlfSBmcm9tICcuLi8uLi9hbmd1bGFyLWNlc2l1bS9zZXJ2aWNlcy9nZW8tdXRpbHMvZ2VvLXV0aWxzLnNlcnZpY2UnO1xuaW1wb3J0IHtkZWZhdWx0TGFiZWxQcm9wcywgTGFiZWxQcm9wc30gZnJvbSAnLi9sYWJlbC1wcm9wcyc7XG5cbmV4cG9ydCBjbGFzcyBFZGl0YWJsZVBvbHlsaW5lIGV4dGVuZHMgQWNFbnRpdHkge1xuICBwcml2YXRlIHBvc2l0aW9uczogRWRpdFBvaW50W10gPSBbXTtcblxuICBwcml2YXRlIHBvbHlsaW5lczogRWRpdFBvbHlsaW5lW10gPSBbXTtcbiAgcHJpdmF0ZSBtb3ZpbmdQb2ludDogRWRpdFBvaW50O1xuICBwcml2YXRlIGRvbmVDcmVhdGlvbiA9IGZhbHNlO1xuICBwcml2YXRlIF9lbmFibGVFZGl0ID0gdHJ1ZTtcbiAgcHJpdmF0ZSBfcG9pbnRQcm9wczogUG9pbnRQcm9wcztcbiAgcHJpdmF0ZSBwb2x5bGluZVByb3BzOiBQb2x5bGluZVByb3BzO1xuICBwcml2YXRlIGxhc3REcmFnZ2VkVG9Qb3NpdGlvbjogYW55O1xuICBwcml2YXRlIF9sYWJlbHM6IExhYmVsUHJvcHNbXSA9IFtdO1xuICBwcml2YXRlIF9vdXRsaW5lSW5zdGFuY2UgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgaWQ6IHN0cmluZyxcbiAgICAgICAgICAgICAgcHJpdmF0ZSBwb2ludHNMYXllcjogQWNMYXllckNvbXBvbmVudCxcbiAgICAgICAgICAgICAgcHJpdmF0ZSBwb2x5bGluZXNMYXllcjogQWNMYXllckNvbXBvbmVudCxcbiAgICAgICAgICAgICAgcHJpdmF0ZSBjb29yZGluYXRlQ29udmVydGVyOiBDb29yZGluYXRlQ29udmVydGVyLFxuICAgICAgICAgICAgICBwcml2YXRlIHNjZW5lOiBhbnksXG4gICAgICAgICAgICAgIHByaXZhdGUgZWRpdE9wdGlvbnM6IFBvbHlsaW5lRWRpdE9wdGlvbnMsXG4gICAgICAgICAgICAgIHBvc2l0aW9ucz86IENhcnRlc2lhbjNbXSkge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5fcG9pbnRQcm9wcyA9IHsuLi5lZGl0T3B0aW9ucy5wb2ludFByb3BzfTtcbiAgICB0aGlzLnByb3BzID0gey4uLmVkaXRPcHRpb25zLnBvbHlsaW5lUHJvcHN9O1xuICAgIGlmIChwb3NpdGlvbnMgJiYgcG9zaXRpb25zLmxlbmd0aCA+PSAyKSB7XG4gICAgICB0aGlzLmNyZWF0ZUZyb21FeGlzdGluZyhwb3NpdGlvbnMpO1xuICAgIH1cbiAgfVxuXG4gIGdldCBsYWJlbHMoKTogTGFiZWxQcm9wc1tdIHtcbiAgICByZXR1cm4gdGhpcy5fbGFiZWxzO1xuICB9XG5cbiAgc2V0IGxhYmVscyhsYWJlbHM6IExhYmVsUHJvcHNbXSkge1xuICAgIGlmICghbGFiZWxzKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHBvc2l0aW9ucyA9IHRoaXMuZ2V0UmVhbFBvc2l0aW9ucygpO1xuICAgIHRoaXMuX2xhYmVscyA9IGxhYmVscy5tYXAoKGxhYmVsLCBpbmRleCkgPT4ge1xuICAgICAgaWYgKCFsYWJlbC5wb3NpdGlvbikge1xuICAgICAgICBsYWJlbC5wb3NpdGlvbiA9IHBvc2l0aW9uc1tpbmRleF07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCBkZWZhdWx0TGFiZWxQcm9wcywgbGFiZWwpO1xuICAgIH0pO1xuICB9XG5cbiAgZ2V0IHByb3BzKCk6IFBvbHlsaW5lUHJvcHMge1xuICAgIHJldHVybiB0aGlzLnBvbHlsaW5lUHJvcHM7XG4gIH1cblxuICBzZXQgcHJvcHModmFsdWU6IFBvbHlsaW5lUHJvcHMpIHtcbiAgICB0aGlzLnBvbHlsaW5lUHJvcHMgPSB2YWx1ZTtcbiAgfVxuXG4gIGdldCBwb2ludFByb3BzKCk6IFBvaW50UHJvcHMge1xuICAgIHJldHVybiB0aGlzLl9wb2ludFByb3BzO1xuICB9XG5cbiAgc2V0IHBvaW50UHJvcHModmFsdWU6IFBvaW50UHJvcHMpIHtcbiAgICB0aGlzLl9wb2ludFByb3BzID0gdmFsdWU7XG4gIH1cblxuICBnZXQgZW5hYmxlRWRpdCgpIHtcbiAgICByZXR1cm4gdGhpcy5fZW5hYmxlRWRpdDtcbiAgfVxuXG4gIHNldCBlbmFibGVFZGl0KHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5fZW5hYmxlRWRpdCA9IHZhbHVlO1xuICAgIHRoaXMucG9zaXRpb25zLmZvckVhY2gocG9pbnQgPT4ge1xuICAgICAgcG9pbnQuc2hvdyA9IHZhbHVlO1xuICAgICAgdGhpcy51cGRhdGVQb2ludHNMYXllcihmYWxzZSwgcG9pbnQpO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVGcm9tRXhpc3RpbmcocG9zaXRpb25zOiBDYXJ0ZXNpYW4zW10pIHtcbiAgICBwb3NpdGlvbnMuZm9yRWFjaCgocG9zaXRpb24pID0+IHtcbiAgICAgIHRoaXMuYWRkUG9pbnRGcm9tRXhpc3RpbmcocG9zaXRpb24pO1xuICAgIH0pO1xuICAgIHRoaXMuYWRkQWxsVmlydHVhbEVkaXRQb2ludHMoKTtcbiAgICB0aGlzLmRvbmVDcmVhdGlvbiA9IHRydWU7XG4gIH1cblxuICBzZXRNYW51YWxseShwb2ludHM6IHtcbiAgICBwb3NpdGlvbjogQ2FydGVzaWFuMyxcbiAgICBwb2ludFByb3A/OiBQb2ludFByb3BzXG4gIH1bXSB8IENhcnRlc2lhbjNbXSwgcG9seWxpbmVQcm9wcz86IFBvbHlsaW5lUHJvcHMpIHtcbiAgICBpZiAoIXRoaXMuZG9uZUNyZWF0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VwZGF0ZSBtYW51YWxseSBvbmx5IGluIGVkaXQgbW9kZSwgYWZ0ZXIgcG9seWxpbmUgaXMgY3JlYXRlZCcpO1xuICAgIH1cbiAgICB0aGlzLnBvc2l0aW9ucy5mb3JFYWNoKHAgPT4gdGhpcy5wb2ludHNMYXllci5yZW1vdmUocC5nZXRJZCgpKSk7XG5cbiAgICBjb25zdCBuZXdQb2ludHM6IEVkaXRQb2ludFtdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwb2ludHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHBvaW50T3JDYXJ0ZXNpYW46IGFueSA9IHBvaW50c1tpXTtcbiAgICAgIGxldCBuZXdQb2ludCA9IG51bGw7XG4gICAgICBpZiAocG9pbnRPckNhcnRlc2lhbi5wb2ludFByb3BzKSB7XG4gICAgICAgIG5ld1BvaW50ID0gbmV3IEVkaXRQb2ludCh0aGlzLmlkLCBwb2ludE9yQ2FydGVzaWFuLnBvc2l0aW9uLCBwb2ludE9yQ2FydGVzaWFuLnBvaW50UHJvcHMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmV3UG9pbnQgPSBuZXcgRWRpdFBvaW50KHRoaXMuaWQsIHBvaW50T3JDYXJ0ZXNpYW4sIHRoaXMuX3BvaW50UHJvcHMpO1xuICAgICAgfVxuICAgICAgbmV3UG9pbnRzLnB1c2gobmV3UG9pbnQpO1xuICAgIH1cbiAgICB0aGlzLnBvc2l0aW9ucyA9IG5ld1BvaW50cztcbiAgICB0aGlzLnBvbHlsaW5lUHJvcHMgPSBwb2x5bGluZVByb3BzID8gcG9seWxpbmVQcm9wcyA6IHRoaXMucG9seWxpbmVQcm9wcztcblxuICAgIHRoaXMudXBkYXRlUG9pbnRzTGF5ZXIodHJ1ZSwgLi4udGhpcy5wb3NpdGlvbnMpO1xuICAgIHRoaXMuYWRkQWxsVmlydHVhbEVkaXRQb2ludHMoKTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkQWxsVmlydHVhbEVkaXRQb2ludHMoKSB7XG4gICAgY29uc3QgY3VycmVudFBvaW50cyA9IFsuLi50aGlzLnBvc2l0aW9uc107XG4gICAgY3VycmVudFBvaW50cy5mb3JFYWNoKChwb3MsIGluZGV4KSA9PiB7XG4gICAgICBpZiAoaW5kZXggIT09IGN1cnJlbnRQb2ludHMubGVuZ3RoIC0gMSkge1xuICAgICAgICBjb25zdCBjdXJyZW50UG9pbnQgPSBwb3M7XG4gICAgICAgIGNvbnN0IG5leHRJbmRleCA9IChpbmRleCArIDEpICUgKGN1cnJlbnRQb2ludHMubGVuZ3RoKTtcbiAgICAgICAgY29uc3QgbmV4dFBvaW50ID0gY3VycmVudFBvaW50c1tuZXh0SW5kZXhdO1xuXG4gICAgICAgIGNvbnN0IG1pZFBvaW50ID0gdGhpcy5zZXRNaWRkbGVWaXJ0dWFsUG9pbnQoY3VycmVudFBvaW50LCBuZXh0UG9pbnQpO1xuXG4gICAgICAgIHRoaXMudXBkYXRlUG9pbnRzTGF5ZXIoZmFsc2UsIG1pZFBvaW50KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0TWlkZGxlVmlydHVhbFBvaW50KGZpcnN0UDogRWRpdFBvaW50LCBzZWNvbmRQOiBFZGl0UG9pbnQpOiBFZGl0UG9pbnQge1xuICAgIGNvbnN0IHBvczEgPSBmaXJzdFAuZ2V0UG9zaXRpb24oKTtcbiAgICBjb25zdCBwb3MyID0gc2Vjb25kUC5nZXRQb3NpdGlvbigpO1xuICAgIGNvbnN0IG1pZFBvaW50Q2FydGVzaWFuMyA9IENhcnRlc2lhbjMubGVycChuZXcgQ2FydGVzaWFuMyhwb3MxLngsIHBvczEueSwgcG9zMS56KSwgbmV3IENhcnRlc2lhbjMocG9zMi54LCBwb3MyLnksIHBvczIueiksIDAuNSwgbmV3IENhcnRlc2lhbjMoKSk7XG4gICAgY29uc3QgbWlkUG9pbnQgPSBuZXcgRWRpdFBvaW50KHRoaXMuaWQsIG1pZFBvaW50Q2FydGVzaWFuMywgdGhpcy5fcG9pbnRQcm9wcyk7XG4gICAgbWlkUG9pbnQuc2V0VmlydHVhbEVkaXRQb2ludCh0cnVlKTtcblxuICAgIGNvbnN0IGZpcnN0SW5kZXggPSB0aGlzLnBvc2l0aW9ucy5pbmRleE9mKGZpcnN0UCk7XG4gICAgdGhpcy5wb3NpdGlvbnMuc3BsaWNlKGZpcnN0SW5kZXggKyAxLCAwLCBtaWRQb2ludCk7XG4gICAgcmV0dXJuIG1pZFBvaW50O1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVNaWRkbGVWaXJ0dWFsUG9pbnQodmlydHVhbEVkaXRQb2ludDogRWRpdFBvaW50LCBwcmV2UG9pbnQ6IEVkaXRQb2ludCwgbmV4dFBvaW50OiBFZGl0UG9pbnQpIHtcbiAgICBjb25zdCBwb3MxID0gcHJldlBvaW50LmdldFBvc2l0aW9uKCk7XG4gICAgY29uc3QgcG9zMiA9IG5leHRQb2ludC5nZXRQb3NpdGlvbigpO1xuICAgIGNvbnN0IG1pZFBvaW50Q2FydGVzaWFuMyA9IENhcnRlc2lhbjMubGVycChuZXcgQ2FydGVzaWFuMyhwb3MxLngsIHBvczEueSwgcG9zMS56KSwgbmV3IENhcnRlc2lhbjMocG9zMi54LCBwb3MyLnksIHBvczIueiksIDAuNSwgbmV3IENhcnRlc2lhbjMoKSk7XG4gICAgdmlydHVhbEVkaXRQb2ludC5zZXRQb3NpdGlvbihtaWRQb2ludENhcnRlc2lhbjMpO1xuICB9XG5cbiAgY2hhbmdlVmlydHVhbFBvaW50VG9SZWFsUG9pbnQocG9pbnQ6IEVkaXRQb2ludCkge1xuICAgIHBvaW50LnNldFZpcnR1YWxFZGl0UG9pbnQoZmFsc2UpOyAvLyBhY3R1YWwgcG9pbnQgYmVjb21lcyBhIHJlYWwgcG9pbnRcbiAgICBjb25zdCBwb2ludHNDb3VudCA9IHRoaXMucG9zaXRpb25zLmxlbmd0aDtcbiAgICBjb25zdCBwb2ludEluZGV4ID0gdGhpcy5wb3NpdGlvbnMuaW5kZXhPZihwb2ludCk7XG4gICAgY29uc3QgbmV4dEluZGV4ID0gKHBvaW50SW5kZXggKyAxKSAlIChwb2ludHNDb3VudCk7XG4gICAgY29uc3QgcHJlSW5kZXggPSAoKHBvaW50SW5kZXggLSAxKSArIHBvaW50c0NvdW50KSAlIHBvaW50c0NvdW50O1xuXG4gICAgY29uc3QgbmV4dFBvaW50ID0gdGhpcy5wb3NpdGlvbnNbbmV4dEluZGV4XTtcbiAgICBjb25zdCBwcmVQb2ludCA9IHRoaXMucG9zaXRpb25zW3ByZUluZGV4XTtcblxuICAgIGNvbnN0IGZpcnN0TWlkUG9pbnQgPSB0aGlzLnNldE1pZGRsZVZpcnR1YWxQb2ludChwcmVQb2ludCwgcG9pbnQpO1xuICAgIGNvbnN0IHNlY01pZFBvaW50ID0gdGhpcy5zZXRNaWRkbGVWaXJ0dWFsUG9pbnQocG9pbnQsIG5leHRQb2ludCk7XG4gICAgdGhpcy51cGRhdGVQb2ludHNMYXllcihmYWxzZSwgZmlyc3RNaWRQb2ludCwgc2VjTWlkUG9pbnQsIHBvaW50KTtcblxuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXJQb2x5bGluZXMoKSB7XG4gICAgY29uc3QgcmVhbFBvaW50cyA9IHRoaXMucG9zaXRpb25zLmZpbHRlcihwb2ludCA9PiAhcG9pbnQuaXNWaXJ0dWFsRWRpdFBvaW50KCkpO1xuICAgIGlmICh0aGlzLnBvbHlsaW5lUHJvcHMudXNlR3JvdW5kUHJpbWl0aXZlT3V0bGluZSkge1xuICAgICAgaWYgKHJlYWxQb2ludHMubGVuZ3RoIDwgMikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aGlzLnNjZW5lLmdyb3VuZFByaW1pdGl2ZXMucmVtb3ZlKHRoaXMuX291dGxpbmVJbnN0YW5jZSk7XG4gICAgICBjb25zdCBpbnN0YW5jZSA9IG5ldyBHZW9tZXRyeUluc3RhbmNlKHtcbiAgICAgICAgZ2VvbWV0cnk6IG5ldyBHcm91bmRQb2x5bGluZUdlb21ldHJ5KHtcbiAgICAgICAgICBwb3NpdGlvbnM6IHRoaXMucG9zaXRpb25zLm1hcChwID0+IHAuZ2V0UG9zaXRpb24oKSksXG4gICAgICAgICAgd2lkdGg6IHRoaXMucG9seWxpbmVQcm9wcy53aWR0aCxcbiAgICAgICAgICBsb29wOiBmYWxzZVxuICAgICAgICB9KSxcbiAgICAgICAgaWQ6ICdlZGl0LXBvbHlnb24tb3V0bGluZS0nICsgdGhpcy5pZCxcbiAgICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICAgIGNvbG9yOiBDb2xvckdlb21ldHJ5SW5zdGFuY2VBdHRyaWJ1dGUuZnJvbUNvbG9yKHRoaXMucG9seWxpbmVQcm9wcy5tYXRlcmlhbCgpKVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHRoaXMuX291dGxpbmVJbnN0YW5jZSA9IHRoaXMuc2NlbmUuZ3JvdW5kUHJpbWl0aXZlcy5hZGQoXG4gICAgICAgIG5ldyBHcm91bmRQb2x5bGluZVByaW1pdGl2ZSh7XG4gICAgICAgICAgZ2VvbWV0cnlJbnN0YW5jZXM6IGluc3RhbmNlLFxuICAgICAgICAgIGFzeW5jaHJvbm91czogZmFsc2UsXG4gICAgICAgICAgYXBwZWFyYW5jZTogbmV3IFBvbHlsaW5lQ29sb3JBcHBlYXJhbmNlKClcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucG9seWxpbmVzLmZvckVhY2gocG9seWxpbmUgPT4gdGhpcy5wb2x5bGluZXNMYXllci5yZW1vdmUocG9seWxpbmUuZ2V0SWQoKSkpO1xuICAgICAgdGhpcy5wb2x5bGluZXMgPSBbXTtcbiAgICAgIHJlYWxQb2ludHMuZm9yRWFjaCgocG9pbnQsIGluZGV4KSA9PiB7XG4gICAgICAgIGlmIChpbmRleCAhPT0gcmVhbFBvaW50cy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgY29uc3QgbmV4dEluZGV4ID0gKGluZGV4ICsgMSk7XG4gICAgICAgICAgY29uc3QgbmV4dFBvaW50ID0gcmVhbFBvaW50c1tuZXh0SW5kZXhdO1xuICAgICAgICAgIGNvbnN0IHBvbHlsaW5lID0gbmV3IEVkaXRQb2x5bGluZSh0aGlzLmlkLCBwb2ludC5nZXRQb3NpdGlvbigpLCBuZXh0UG9pbnQuZ2V0UG9zaXRpb24oKSwgdGhpcy5wb2x5bGluZVByb3BzKTtcbiAgICAgICAgICB0aGlzLnBvbHlsaW5lcy5wdXNoKHBvbHlsaW5lKTtcbiAgICAgICAgICB0aGlzLnBvbHlsaW5lc0xheWVyLnVwZGF0ZShwb2x5bGluZSwgcG9seWxpbmUuZ2V0SWQoKSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGFkZFBvaW50RnJvbUV4aXN0aW5nKHBvc2l0aW9uOiBDYXJ0ZXNpYW4zKSB7XG4gICAgY29uc3QgbmV3UG9pbnQgPSBuZXcgRWRpdFBvaW50KHRoaXMuaWQsIHBvc2l0aW9uLCB0aGlzLl9wb2ludFByb3BzKTtcbiAgICB0aGlzLnBvc2l0aW9ucy5wdXNoKG5ld1BvaW50KTtcbiAgICB0aGlzLnVwZGF0ZVBvaW50c0xheWVyKHRydWUsIG5ld1BvaW50KTtcbiAgfVxuXG5cbiAgYWRkUG9pbnQocG9zaXRpb246IENhcnRlc2lhbjMpIHtcbiAgICBpZiAodGhpcy5kb25lQ3JlYXRpb24pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgaXNGaXJzdFBvaW50ID0gIXRoaXMucG9zaXRpb25zLmxlbmd0aDtcbiAgICBpZiAoaXNGaXJzdFBvaW50KSB7XG4gICAgICBjb25zdCBmaXJzdFBvaW50ID0gbmV3IEVkaXRQb2ludCh0aGlzLmlkLCBwb3NpdGlvbiwgdGhpcy5fcG9pbnRQcm9wcyk7XG4gICAgICB0aGlzLnBvc2l0aW9ucy5wdXNoKGZpcnN0UG9pbnQpO1xuICAgICAgdGhpcy51cGRhdGVQb2ludHNMYXllcih0cnVlLCBmaXJzdFBvaW50KTtcbiAgICB9XG5cbiAgICB0aGlzLm1vdmluZ1BvaW50ID0gbmV3IEVkaXRQb2ludCh0aGlzLmlkLCBwb3NpdGlvbi5jbG9uZSgpLCB0aGlzLl9wb2ludFByb3BzKTtcbiAgICB0aGlzLnBvc2l0aW9ucy5wdXNoKHRoaXMubW92aW5nUG9pbnQpO1xuXG4gICAgdGhpcy51cGRhdGVQb2ludHNMYXllcih0cnVlLCB0aGlzLm1vdmluZ1BvaW50KTtcbiAgfVxuXG4gIG1vdmVQb2ludEZpbmlzaChlZGl0UG9pbnQ6IEVkaXRQb2ludCkge1xuICAgIGlmICh0aGlzLmVkaXRPcHRpb25zLmNsYW1wSGVpZ2h0VG8zRCkge1xuICAgICAgZWRpdFBvaW50LnByb3BzLmRpc2FibGVEZXB0aFRlc3REaXN0YW5jZSA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICAgIHRoaXMudXBkYXRlUG9pbnRzTGF5ZXIoZmFsc2UsIGVkaXRQb2ludCk7XG4gICAgfVxuICB9XG5cbiAgbW92ZVBvaW50KHRvUG9zaXRpb246IENhcnRlc2lhbjMsIGVkaXRQb2ludDogRWRpdFBvaW50KSB7XG4gICAgZWRpdFBvaW50LnNldFBvc2l0aW9uKHRvUG9zaXRpb24pO1xuICAgIGlmICh0aGlzLmRvbmVDcmVhdGlvbikge1xuICAgICAgaWYgKGVkaXRQb2ludC5wcm9wcy5kaXNhYmxlRGVwdGhUZXN0RGlzdGFuY2UgJiYgdGhpcy5lZGl0T3B0aW9ucy5jbGFtcEhlaWdodFRvM0QpIHtcbiAgICAgICAgLy8gVG8gYXZvaWQgYnVnIHdpdGggcGlja1Bvc2l0aW9uKCkgb24gcG9pbnQgd2l0aCBkaXNhYmxlRGVwdGhUZXN0RGlzdGFuY2VcbiAgICAgICAgZWRpdFBvaW50LnByb3BzLmRpc2FibGVEZXB0aFRlc3REaXN0YW5jZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuOyAvLyBpZ25vcmUgZmlyc3QgbW92ZSBiZWNhdXNlIHRoZSBwaWNrUG9zaXRpb24oKSBjb3VsZCBiZSB3cm9uZ1xuICAgICAgfVxuXG4gICAgICBpZiAoZWRpdFBvaW50LmlzVmlydHVhbEVkaXRQb2ludCgpKSB7XG4gICAgICAgIHRoaXMuY2hhbmdlVmlydHVhbFBvaW50VG9SZWFsUG9pbnQoZWRpdFBvaW50KTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHBvaW50c0NvdW50ID0gdGhpcy5wb3NpdGlvbnMubGVuZ3RoO1xuICAgICAgY29uc3QgcG9pbnRJbmRleCA9IHRoaXMucG9zaXRpb25zLmluZGV4T2YoZWRpdFBvaW50KTtcblxuICAgICAgaWYgKHBvaW50SW5kZXggPCB0aGlzLnBvc2l0aW9ucy5sZW5ndGggLSAxKSB7XG4gICAgICAgIGNvbnN0IG5leHRWaXJ0dWFsUG9pbnQgPSB0aGlzLnBvc2l0aW9uc1socG9pbnRJbmRleCArIDEpICUgKHBvaW50c0NvdW50KV07XG4gICAgICAgIGNvbnN0IG5leHRSZWFsUG9pbnQgPSB0aGlzLnBvc2l0aW9uc1socG9pbnRJbmRleCArIDIpICUgKHBvaW50c0NvdW50KV07XG4gICAgICAgIHRoaXMudXBkYXRlTWlkZGxlVmlydHVhbFBvaW50KG5leHRWaXJ0dWFsUG9pbnQsIGVkaXRQb2ludCwgbmV4dFJlYWxQb2ludCk7XG4gICAgICB9XG4gICAgICBpZiAocG9pbnRJbmRleCA+IDApIHtcbiAgICAgICAgY29uc3QgcHJldlZpcnR1YWxQb2ludCA9IHRoaXMucG9zaXRpb25zWygocG9pbnRJbmRleCAtIDEpICsgcG9pbnRzQ291bnQpICUgcG9pbnRzQ291bnRdO1xuICAgICAgICBjb25zdCBwcmV2UmVhbFBvaW50ID0gdGhpcy5wb3NpdGlvbnNbKChwb2ludEluZGV4IC0gMikgKyBwb2ludHNDb3VudCkgJSBwb2ludHNDb3VudF07XG4gICAgICAgIHRoaXMudXBkYXRlTWlkZGxlVmlydHVhbFBvaW50KHByZXZWaXJ0dWFsUG9pbnQsIGVkaXRQb2ludCwgcHJldlJlYWxQb2ludCk7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMudXBkYXRlUG9pbnRzTGF5ZXIodHJ1ZSwgZWRpdFBvaW50KTtcbiAgfVxuXG4gIG1vdmVUZW1wTW92aW5nUG9pbnQodG9Qb3NpdGlvbjogQ2FydGVzaWFuMykge1xuICAgIGlmICh0aGlzLm1vdmluZ1BvaW50KSB7XG4gICAgICB0aGlzLm1vdmVQb2ludCh0b1Bvc2l0aW9uLCB0aGlzLm1vdmluZ1BvaW50KTtcbiAgICB9XG4gIH1cblxuICBtb3ZlU2hhcGUoc3RhcnRNb3ZpbmdQb3NpdGlvbjogQ2FydGVzaWFuMywgZHJhZ2dlZFRvUG9zaXRpb246IENhcnRlc2lhbjMpIHtcbiAgICBpZiAoIXRoaXMuZG9uZUNyZWF0aW9uKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghdGhpcy5sYXN0RHJhZ2dlZFRvUG9zaXRpb24pIHtcbiAgICAgIHRoaXMubGFzdERyYWdnZWRUb1Bvc2l0aW9uID0gc3RhcnRNb3ZpbmdQb3NpdGlvbjtcbiAgICB9XG5cbiAgICBjb25zdCBkZWx0YSA9IEdlb1V0aWxzU2VydmljZS5nZXRQb3NpdGlvbnNEZWx0YSh0aGlzLmxhc3REcmFnZ2VkVG9Qb3NpdGlvbiwgbmV3IENhcnRlc2lhbjMoZHJhZ2dlZFRvUG9zaXRpb24ueCwgZHJhZ2dlZFRvUG9zaXRpb24ueSwgZHJhZ2dlZFRvUG9zaXRpb24ueikpO1xuICAgIHRoaXMucG9zaXRpb25zLmZvckVhY2gocG9pbnQgPT4ge1xuICAgICAgY29uc3QgcG9zID0gcG9pbnQuZ2V0UG9zaXRpb24oKTtcbiAgICAgIGNvbnN0IG5ld1BvcyA9IEdlb1V0aWxzU2VydmljZS5hZGREZWx0YVRvUG9zaXRpb24obmV3IENhcnRlc2lhbjMocG9zLngsIHBvcy55LCBwb3MueiksIGRlbHRhLCB0cnVlKTtcbiAgICAgIHBvaW50LnNldFBvc2l0aW9uKG5ld1Bvcyk7XG4gICAgfSk7XG4gICAgdGhpcy51cGRhdGVQb2ludHNMYXllcih0cnVlLCAuLi50aGlzLnBvc2l0aW9ucyk7XG4gICAgdGhpcy5sYXN0RHJhZ2dlZFRvUG9zaXRpb24gPSBkcmFnZ2VkVG9Qb3NpdGlvbjtcbiAgfVxuXG4gIGVuZE1vdmVTaGFwZSgpIHtcbiAgICB0aGlzLmxhc3REcmFnZ2VkVG9Qb3NpdGlvbiA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLnVwZGF0ZVBvaW50c0xheWVyKHRydWUsIC4uLnRoaXMucG9zaXRpb25zKTtcbiAgfVxuXG4gIHJlbW92ZVBvaW50KHBvaW50VG9SZW1vdmU6IEVkaXRQb2ludCkge1xuICAgIHRoaXMucmVtb3ZlUG9zaXRpb24ocG9pbnRUb1JlbW92ZSk7XG4gICAgdGhpcy5wb3NpdGlvbnNcbiAgICAgIC5maWx0ZXIocCA9PiBwLmlzVmlydHVhbEVkaXRQb2ludCgpKVxuICAgICAgLmZvckVhY2gocCA9PiB0aGlzLnJlbW92ZVBvc2l0aW9uKHApKTtcbiAgICB0aGlzLmFkZEFsbFZpcnR1YWxFZGl0UG9pbnRzKCk7XG5cbiAgICB0aGlzLnJlbmRlclBvbHlsaW5lcygpO1xuICB9XG5cbiAgYWRkTGFzdFBvaW50KHBvc2l0aW9uOiBDYXJ0ZXNpYW4zKSB7XG4gICAgdGhpcy5kb25lQ3JlYXRpb24gPSB0cnVlO1xuICAgIHRoaXMucmVtb3ZlUG9zaXRpb24odGhpcy5tb3ZpbmdQb2ludCk7IC8vIHJlbW92ZSBtb3ZpbmdQb2ludFxuICAgIHRoaXMubW92aW5nUG9pbnQgPSBudWxsO1xuXG4gICAgdGhpcy5hZGRBbGxWaXJ0dWFsRWRpdFBvaW50cygpO1xuICB9XG5cbiAgZ2V0UmVhbFBvc2l0aW9ucygpOiBDYXJ0ZXNpYW4zW10ge1xuICAgIHJldHVybiB0aGlzLmdldFJlYWxQb2ludHMoKVxuICAgICAgLm1hcChwb3NpdGlvbiA9PiBwb3NpdGlvbi5nZXRQb3NpdGlvbigpKTtcbiAgfVxuXG4gIGdldFJlYWxQb2ludHMoKTogRWRpdFBvaW50W10ge1xuICAgIHJldHVybiB0aGlzLnBvc2l0aW9uc1xuICAgICAgLmZpbHRlcihwb3NpdGlvbiA9PiAhcG9zaXRpb24uaXNWaXJ0dWFsRWRpdFBvaW50KCkgJiYgcG9zaXRpb24gIT09IHRoaXMubW92aW5nUG9pbnQpO1xuICB9XG5cbiAgZ2V0UG9pbnRzKCk6IEVkaXRQb2ludFtdIHtcbiAgICByZXR1cm4gdGhpcy5wb3NpdGlvbnMuZmlsdGVyKHBvc2l0aW9uID0+IHBvc2l0aW9uICE9PSB0aGlzLm1vdmluZ1BvaW50KTtcbiAgfVxuXG4gIGdldFBvc2l0aW9ucygpOiBDYXJ0ZXNpYW4zW10ge1xuICAgIHJldHVybiB0aGlzLnBvc2l0aW9ucy5tYXAocG9zaXRpb24gPT4gcG9zaXRpb24uZ2V0UG9zaXRpb24oKSk7XG4gIH1cblxuICBnZXRQb3NpdGlvbnNDYWxsYmFja1Byb3BlcnR5KCk6IENhbGxiYWNrUHJvcGVydHkge1xuICAgIHJldHVybiBuZXcgQ2FsbGJhY2tQcm9wZXJ0eSh0aGlzLmdldFBvc2l0aW9ucy5iaW5kKHRoaXMpLCBmYWxzZSk7XG4gIH1cblxuICBwcml2YXRlIHJlbW92ZVBvc2l0aW9uKHBvaW50OiBFZGl0UG9pbnQpIHtcbiAgICBjb25zdCBpbmRleCA9IHRoaXMucG9zaXRpb25zLmZpbmRJbmRleCgocCkgPT4gcCA9PT0gcG9pbnQpO1xuICAgIGlmIChpbmRleCA8IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5wb3NpdGlvbnMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICB0aGlzLnBvaW50c0xheWVyLnJlbW92ZShwb2ludC5nZXRJZCgpKTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlUG9pbnRzTGF5ZXIocmVuZGVyUG9seWxpbmVzID0gdHJ1ZSwgLi4ucG9pbnQ6IEVkaXRQb2ludFtdKSB7XG4gICAgaWYgKHJlbmRlclBvbHlsaW5lcykge1xuICAgICAgdGhpcy5yZW5kZXJQb2x5bGluZXMoKTtcbiAgICB9XG4gICAgcG9pbnQuZm9yRWFjaChwID0+IHRoaXMucG9pbnRzTGF5ZXIudXBkYXRlKHAsIHAuZ2V0SWQoKSkpO1xuICB9XG5cbiAgdXBkYXRlKCkge1xuICAgIHRoaXMudXBkYXRlUG9pbnRzTGF5ZXIoKTtcbiAgfVxuXG4gIGRpc3Bvc2UoKSB7XG4gICAgdGhpcy5zY2VuZS5ncm91bmRQcmltaXRpdmVzLnJlbW92ZSh0aGlzLl9vdXRsaW5lSW5zdGFuY2UpO1xuICAgIHRoaXMucG9zaXRpb25zLmZvckVhY2goZWRpdFBvaW50ID0+IHtcbiAgICAgIHRoaXMucG9pbnRzTGF5ZXIucmVtb3ZlKGVkaXRQb2ludC5nZXRJZCgpKTtcbiAgICB9KTtcbiAgICB0aGlzLnBvbHlsaW5lcy5mb3JFYWNoKGxpbmUgPT4gdGhpcy5wb2x5bGluZXNMYXllci5yZW1vdmUobGluZS5nZXRJZCgpKSk7XG4gICAgaWYgKHRoaXMubW92aW5nUG9pbnQpIHtcbiAgICAgIHRoaXMucG9pbnRzTGF5ZXIucmVtb3ZlKHRoaXMubW92aW5nUG9pbnQuZ2V0SWQoKSk7XG4gICAgICB0aGlzLm1vdmluZ1BvaW50ID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICB0aGlzLnBvc2l0aW9ucy5sZW5ndGggPSAwO1xuICB9XG5cbiAgZ2V0UG9pbnRzQ291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5wb3NpdGlvbnMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0SWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaWQ7XG4gIH1cbn1cbiJdfQ==