@eliorar/angular-cesium
Version:
Angular library for working with Cesium.
237 lines • 34.1 kB
JavaScript
import { Injectable, Optional } from '@angular/core';
import { Cartographic, Rectangle } from 'cesium';
import * as i0 from "@angular/core";
import * as i1 from "../../angular-cesium/services/maps-manager/maps-manager.service";
import * as i2 from "../../angular-cesium/services/camera/camera.service";
import * as i3 from "../../angular-cesium/services/cesium/cesium.service";
/**
* The Service is as a "zoom to rectangle" tool
*
* example:
* ```
* constructor(
* private cameraService: CameraService,
* private cesiumService: CesiumService,
* private zoomToRectangleService: ZoomToRectangleService,
* ) {
* this.zoomToRectangleService.init(cesiumService, cameraService);
* }
* ...
* this.zoomToRectangleService.activate({onComplete: () => this.zoomToRectangleService.disable()});
* ```
*
* `init()` - initialize the service with CameraService and CesiumService.
* If no mapId is provided to activate() - must be called before calling `activate()`.
*
* `disable()` - disables the tool.
*
* `activate()` -
* @param options
* {
* onStart - optional - a callback that will be called when the user start drawing the rectangle
* onComplete - optional - a callback that will be called when the tool zoom in
* autoDisableOnZoom - optional - determines if the tool should auto disable after zoom - default: true
* animationDurationInSeconds - optional - zoom animation duration in seconds - default: 0.5
* borderStyle - optional - the style of the rectangle element border - default: '3px dashed #FFFFFF'
* backgroundColor - optional - the background color of the rectangle element - default: 'transparent'
* resetKeyCode - optional - the key code of the key that is used to reset the drawing of the rectangle - default: 27 (ESC key)
* threshold - optional - the minimum area of the screen rectangle (in pixels) that is required to perform zoom - default: 9
* keepRotation - optional - whether or not to keep the rotation when zooming in - default: true
* mouseButton - optional - sets the mouse button for drawing the rectangle - default: left mouse button (0)
* }
* @param mapId - optional - the mapId of the map that the tool will be used in.
*
*/
export var MouseButtons;
(function (MouseButtons) {
MouseButtons[MouseButtons["LEFT"] = 0] = "LEFT";
MouseButtons[MouseButtons["MIDDLE"] = 1] = "MIDDLE";
MouseButtons[MouseButtons["RIGHT"] = 2] = "RIGHT";
})(MouseButtons || (MouseButtons = {}));
export class ZoomToRectangleService {
constructor(mapsManager, cameraService, cesiumService) {
this.mapsManager = mapsManager;
this.mapsZoomElements = new Map();
this.defaultOptions = {
animationDurationInSeconds: 0.5,
resetKeyCode: 27,
borderStyle: '2px solid rgba(0,0,0,0.5)',
backgroundColor: 'rgba(0,0,0,0.2)',
autoDisableOnZoom: true,
threshold: 9,
keepRotation: true,
mouseButton: MouseButtons.LEFT,
};
}
init(cesiumService, cameraService) {
this.cameraService = cameraService;
this.cesiumService = cesiumService;
}
activate(options = {}, mapId) {
if ((!this.cameraService || !this.cesiumService) && !mapId) {
throw new Error(`The function must receive a mapId if the service wasn't initialized`);
}
const finalOptions = Object.assign({}, this.defaultOptions, options);
let cameraService = this.cameraService;
let mapContainer;
let map;
if (!mapId) {
map = this.mapsManager.getMap();
if (!map) {
throw new Error(`Map not found`);
}
mapId = map.getId();
mapContainer = this.cesiumService.getViewer().container;
}
else {
map = this.mapsManager.getMap(mapId);
if (!map) {
throw new Error(`Map not found with id: ${mapId}`);
}
cameraService = map.getCameraService();
mapContainer = map.getCesiumViewer().container;
}
if (!cameraService || !mapContainer) {
throw new Error(`The function must receive a mapId if the service wasn't initialized`);
}
this.disable(mapId);
const container = document.createElement('div');
mapContainer.style.position = 'relative';
container.style.position = 'absolute';
container.style.width = '100%';
container.style.height = '100%';
container.style.top = '0';
container.style.left = '0';
mapContainer.appendChild(container);
const mapZoomData = { container };
this.mapsZoomElements.set(mapId, mapZoomData);
let mouse = {
endX: 0,
endY: 0,
startX: 0,
startY: 0,
};
let borderElement;
container.onmousedown = e => {
if (e.button !== finalOptions.mouseButton) {
return;
}
if (!borderElement) {
if (options && options.onStart) {
options.onStart(map);
}
const rect = e.currentTarget.getBoundingClientRect();
const offsetX = e.clientX - rect.left;
const offsetY = e.clientY - rect.top;
mouse.startX = offsetX;
mouse.startY = offsetY;
borderElement = document.createElement('div');
borderElement.className = 'zoom-to-rectangle-border';
borderElement.style.position = 'absolute';
borderElement.style.border = finalOptions.borderStyle;
borderElement.style.backgroundColor = finalOptions.backgroundColor;
borderElement.style.left = mouse.startX + 'px';
borderElement.style.top = mouse.startY + 'px';
container.appendChild(borderElement);
mapZoomData.borderElement = borderElement;
}
};
container.onmouseup = e => {
if (borderElement) {
let zoomApplied;
if (mouse && Math.abs(mouse.endX - mouse.startX) * Math.abs(mouse.endY - mouse.startY) > finalOptions.threshold) {
zoomApplied = this.zoomCameraToRectangle(cameraService, mouse, finalOptions.animationDurationInSeconds, finalOptions);
}
borderElement.remove();
borderElement = undefined;
mapZoomData.borderElement = undefined;
mouse = {
endX: 0,
endY: 0,
startX: 0,
startY: 0,
};
if (!!finalOptions.onComplete) {
finalOptions.onComplete(map);
}
if (finalOptions.autoDisableOnZoom && zoomApplied) {
this.disable(mapId);
}
}
};
container.onmousemove = e => {
if (borderElement) {
const rect = e.currentTarget.getBoundingClientRect();
const offsetX = e.clientX - rect.left;
const offsetY = e.clientY - rect.top;
mouse.endX = offsetX;
mouse.endY = offsetY;
borderElement.style.width = Math.abs(mouse.endX - mouse.startX) + 'px';
borderElement.style.height = Math.abs(mouse.endY - mouse.startY) + 'px';
borderElement.style.left = Math.min(mouse.startX, mouse.endX) + 'px';
borderElement.style.top = Math.min(mouse.startY, mouse.endY) + 'px';
}
};
const resetOnEscapePress = e => {
if (e.keyCode === finalOptions.resetKeyCode && borderElement) {
borderElement.remove();
borderElement = undefined;
mapZoomData.borderElement = undefined;
mouse = {
endX: 0,
endY: 0,
startX: 0,
startY: 0,
};
}
};
document.addEventListener('keydown', resetOnEscapePress);
mapZoomData.resetOnEscapePressFunc = resetOnEscapePress;
}
disable(mapId) {
if (!this.mapsManager && !mapId) {
throw new Error('If the service was not initialized with MapsManager, mapId must be provided');
}
if (!mapId) {
const map = this.mapsManager.getMap();
mapId = map.getId();
}
const data = this.mapsZoomElements.get(mapId);
if (data) {
data.container.remove();
if (data.borderElement) {
data.borderElement.remove();
}
if (data.resetOnEscapePressFunc) {
document.removeEventListener('keydown', data.resetOnEscapePressFunc);
}
}
this.mapsZoomElements.delete(mapId);
}
zoomCameraToRectangle(cameraService, positions, animationDuration, options) {
const camera = cameraService.getCamera();
const cartesian1 = camera.pickEllipsoid({ x: positions.startX, y: positions.startY });
const cartesian2 = camera.pickEllipsoid({ x: positions.endX, y: positions.endY });
if (!cartesian1 || !cartesian2) {
return false;
}
const cartographic1 = Cartographic.fromCartesian(cartesian1);
const cartographic2 = Cartographic.fromCartesian(cartesian2);
cameraService.cameraFlyTo({
destination: new Rectangle(Math.min(cartographic1.longitude, cartographic2.longitude), Math.min(cartographic1.latitude, cartographic2.latitude), Math.max(cartographic1.longitude, cartographic2.longitude), Math.max(cartographic1.latitude, cartographic2.latitude)),
orientation: options.keepRotation ? { heading: camera.heading } : undefined,
duration: animationDuration,
});
return true;
}
}
ZoomToRectangleService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ZoomToRectangleService, deps: [{ token: i1.MapsManagerService }, { token: i2.CameraService, optional: true }, { token: i3.CesiumService, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
ZoomToRectangleService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ZoomToRectangleService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ZoomToRectangleService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i1.MapsManagerService }, { type: i2.CameraService, decorators: [{
type: Optional
}] }, { type: i3.CesiumService, decorators: [{
type: Optional
}] }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiem9vbS10by1yZWN0YW5nbGUuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItY2VzaXVtL3NyYy9saWIvYW5ndWxhci1jZXNpdW0td2lkZ2V0cy9zZXJ2aWNlcy96b29tLXRvLXJlY3RhbmdsZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxVQUFVLEVBQUUsUUFBUSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBQyxZQUFZLEVBQUUsU0FBUyxFQUFDLE1BQU0sUUFBUSxDQUFDOzs7OztBQVkvQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXFDRztBQUVILE1BQU0sQ0FBTixJQUFZLFlBSVg7QUFKRCxXQUFZLFlBQVk7SUFDdEIsK0NBQVEsQ0FBQTtJQUNSLG1EQUFVLENBQUE7SUFDVixpREFBUyxDQUFBO0FBQ1gsQ0FBQyxFQUpXLFlBQVksS0FBWixZQUFZLFFBSXZCO0FBR0QsTUFBTSxPQUFPLHNCQUFzQjtJQUNqQyxZQUNVLFdBQStCLEVBQzNCLGFBQTRCLEVBQzVCLGFBQTRCO1FBRmhDLGdCQUFXLEdBQVgsV0FBVyxDQUFvQjtRQVFqQyxxQkFBZ0IsR0FBRyxJQUFJLEdBQUcsRUFBb0IsQ0FBQztRQUMvQyxtQkFBYyxHQUFHO1lBQ3ZCLDBCQUEwQixFQUFFLEdBQUc7WUFDL0IsWUFBWSxFQUFFLEVBQUU7WUFDaEIsV0FBVyxFQUFFLDJCQUEyQjtZQUN4QyxlQUFlLEVBQUUsaUJBQWlCO1lBQ2xDLGlCQUFpQixFQUFFLElBQUk7WUFDdkIsU0FBUyxFQUFFLENBQUM7WUFDWixZQUFZLEVBQUUsSUFBSTtZQUNsQixXQUFXLEVBQUUsWUFBWSxDQUFDLElBQUk7U0FDL0IsQ0FBQztJQWZDLENBQUM7SUFpQkosSUFBSSxDQUFDLGFBQTRCLEVBQUUsYUFBNEI7UUFDN0QsSUFBSSxDQUFDLGFBQWEs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UixRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtJbmplY3RhYmxlLCBPcHRpb25hbH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0NhcnRvZ3JhcGhpYywgUmVjdGFuZ2xlfSBmcm9tICdjZXNpdW0nO1xuaW1wb3J0IHtNYXBzTWFuYWdlclNlcnZpY2V9IGZyb20gJy4uLy4uL2FuZ3VsYXItY2VzaXVtL3NlcnZpY2VzL21hcHMtbWFuYWdlci9tYXBzLW1hbmFnZXIuc2VydmljZSc7XG5pbXBvcnQge0NhbWVyYVNlcnZpY2V9IGZyb20gJy4uLy4uL2FuZ3VsYXItY2VzaXVtL3NlcnZpY2VzL2NhbWVyYS9jYW1lcmEuc2VydmljZSc7XG5pbXBvcnQge0Nlc2l1bVNlcnZpY2V9IGZyb20gJy4uLy4uL2FuZ3VsYXItY2VzaXVtL3NlcnZpY2VzL2Nlc2l1bS9jZXNpdW0uc2VydmljZSc7XG5pbXBvcnQge0FjTWFwQ29tcG9uZW50fSBmcm9tICcuLi8uLi9hbmd1bGFyLWNlc2l1bS9jb21wb25lbnRzL2FjLW1hcC9hYy1tYXAuY29tcG9uZW50JztcblxuaW50ZXJmYWNlIFpvb21EYXRhIHtcbiAgY29udGFpbmVyOiBIVE1MRWxlbWVudDtcbiAgYm9yZGVyRWxlbWVudD86IEhUTUxFbGVtZW50O1xuICByZXNldE9uRXNjYXBlUHJlc3NGdW5jPzogRXZlbnRMaXN0ZW5lck9yRXZlbnRMaXN0ZW5lck9iamVjdDtcbn1cblxuLyoqXG4gKiBUaGUgU2VydmljZSBpcyBhcyBhIFwiem9vbSB0byByZWN0YW5nbGVcIiB0b29sXG4gKlxuICogZXhhbXBsZTpcbiAqIGBgYFxuICogY29uc3RydWN0b3IoXG4gKiAgIHByaXZhdGUgY2FtZXJhU2VydmljZTogQ2FtZXJhU2VydmljZSxcbiAqICAgcHJpdmF0ZSBjZXNpdW1TZXJ2aWNlOiBDZXNpdW1TZXJ2aWNlLFxuICogICBwcml2YXRlIHpvb21Ub1JlY3RhbmdsZVNlcnZpY2U6IFpvb21Ub1JlY3RhbmdsZVNlcnZpY2UsXG4gKiApIHtcbiAqICAgdGhpcy56b29tVG9SZWN0YW5nbGVTZXJ2aWNlLmluaXQoY2VzaXVtU2VydmljZSwgY2FtZXJhU2VydmljZSk7XG4gKiB9XG4gKiAuLi5cbiAqIHRoaXMuem9vbVRvUmVjdGFuZ2xlU2VydmljZS5hY3RpdmF0ZSh7b25Db21wbGV0ZTogKCkgPT4gdGhpcy56b29tVG9SZWN0YW5nbGVTZXJ2aWNlLmRpc2FibGUoKX0pO1xuICogYGBgXG4gKlxuICogYGluaXQoKWAgLSBpbml0aWFsaXplIHRoZSBzZXJ2aWNlIHdpdGggQ2FtZXJhU2VydmljZSBhbmQgQ2VzaXVtU2VydmljZS5cbiAqIElmIG5vIG1hcElkIGlzIHByb3ZpZGVkIHRvIGFjdGl2YXRlKCkgLSBtdXN0IGJlIGNhbGxlZCBiZWZvcmUgY2FsbGluZyBgYWN0aXZhdGUoKWAuXG4gKlxuICogYGRpc2FibGUoKWAgLSBkaXNhYmxlcyB0aGUgdG9vbC5cbiAqXG4gKiBgYWN0aXZhdGUoKWAgLVxuICogQHBhcmFtIG9wdGlvbnNcbiAqIHtcbiAqICBvblN0YXJ0IC0gb3B0aW9uYWwgLSBhIGNhbGxiYWNrIHRoYXQgd2lsbCBiZSBjYWxsZWQgd2hlbiB0aGUgdXNlciBzdGFydCBkcmF3aW5nIHRoZSByZWN0YW5nbGVcbiAqICBvbkNvbXBsZXRlIC0gb3B0aW9uYWwgLSBhIGNhbGxiYWNrIHRoYXQgd2lsbCBiZSBjYWxsZWQgd2hlbiB0aGUgdG9vbCB6b29tIGluXG4gKiAgYXV0b0Rpc2FibGVPblpvb20gLSBvcHRpb25hbCAtIGRldGVybWluZXMgaWYgdGhlIHRvb2wgc2hvdWxkIGF1dG8gZGlzYWJsZSBhZnRlciB6b29tIC0gZGVmYXVsdDogdHJ1ZVxuICogIGFuaW1hdGlvbkR1cmF0aW9uSW5TZWNvbmRzIC0gb3B0aW9uYWwgLSB6b29tIGFuaW1hdGlvbiBkdXJhdGlvbiBpbiBzZWNvbmRzIC0gZGVmYXVsdDogMC41XG4gKiAgYm9yZGVyU3R5bGUgLSBvcHRpb25hbCAtIHRoZSBzdHlsZSBvZiB0aGUgcmVjdGFuZ2xlIGVsZW1lbnQgYm9yZGVyIC0gZGVmYXVsdDogJzNweCBkYXNoZWQgI0ZGRkZGRidcbiAqICBiYWNrZ3JvdW5kQ29sb3IgLSBvcHRpb25hbCAtIHRoZSBiYWNrZ3JvdW5kIGNvbG9yIG9mIHRoZSByZWN0YW5nbGUgZWxlbWVudCAtIGRlZmF1bHQ6ICd0cmFuc3BhcmVudCdcbiAqICByZXNldEtleUNvZGUgLSBvcHRpb25hbCAtIHRoZSBrZXkgY29kZSBvZiB0aGUga2V5IHRoYXQgaXMgdXNlZCB0byByZXNldCB0aGUgZHJhd2luZyBvZiB0aGUgcmVjdGFuZ2xlIC0gZGVmYXVsdDogMjcgKEVTQyBrZXkpXG4gKiAgdGhyZXNob2xkIC0gb3B0aW9uYWwgLSB0aGUgbWluaW11bSBhcmVhIG9mIHRoZSBzY3JlZW4gcmVjdGFuZ2xlIChpbiBwaXhlbHMpIHRoYXQgaXMgcmVxdWlyZWQgdG8gcGVyZm9ybSB6b29tIC0gZGVmYXVsdDogOVxuICogIGtlZXBSb3RhdGlvbiAtIG9wdGlvbmFsIC0gd2hldGhlciBvciBub3QgdG8ga2VlcCB0aGUgcm90YXRpb24gd2hlbiB6b29taW5nIGluIC0gZGVmYXVsdDogdHJ1ZVxuICogIG1vdXNlQnV0dG9uIC0gb3B0aW9uYWwgLSBzZXRzIHRoZSBtb3VzZSBidXR0b24gZm9yIGRyYXdpbmcgdGhlIHJlY3RhbmdsZSAtIGRlZmF1bHQ6IGxlZnQgbW91c2UgYnV0dG9uICgwKVxuICogfVxuICogQHBhcmFtIG1hcElkIC0gb3B0aW9uYWwgLSB0aGUgbWFwSWQgb2YgdGhlIG1hcCB0aGF0IHRoZSB0b29sIHdpbGwgYmUgdXNlZCBpbi5cbiAqXG4gKi9cblxuZXhwb3J0IGVudW0gTW91c2VCdXR0b25zIHtcbiAgTEVGVCA9IDAsXG4gIE1JRERMRSA9IDEsXG4gIFJJR0hUID0gMixcbn1cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFpvb21Ub1JlY3RhbmdsZVNlcnZpY2Uge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIG1hcHNNYW5hZ2VyOiBNYXBzTWFuYWdlclNlcnZpY2UsXG4gICAgQE9wdGlvbmFsKCkgY2FtZXJhU2VydmljZTogQ2FtZXJhU2VydmljZSxcbiAgICBAT3B0aW9uYWwoKSBjZXNpdW1TZXJ2aWNlOiBDZXNpdW1TZXJ2aWNlLFxuICApIHt9XG5cbiAgcHJpdmF0ZSBjYW1lcmFTZXJ2aWNlOiBDYW1lcmFTZXJ2aWNlO1xuICBwcml2YXRlIGNlc2l1bVNlcnZpY2U6IENlc2l1bVNlcnZpY2U7XG5cbiAgcHJpdmF0ZSBtYXBzWm9vbUVsZW1lbnRzID0gbmV3IE1hcDxzdHJpbmcsIFpvb21EYXRhPigpO1xuICBwcml2YXRlIGRlZmF1bHRPcHRpb25zID0ge1xuICAgIGFuaW1hdGlvbkR1cmF0aW9uSW5TZWNvbmRzOiAwLjUsXG4gICAgcmVzZXRLZXlDb2RlOiAyNyxcbiAgICBib3JkZXJTdHlsZTogJzJweCBzb2xpZCByZ2JhKDAsMCwwLDAuNSknLFxuICAgIGJhY2tncm91bmRDb2xvcjogJ3JnYmEoMCwwLDAsMC4yKScsXG4gICAgYXV0b0Rpc2FibGVPblpvb206IHRydWUsXG4gICAgdGhyZXNob2xkOiA5LFxuICAgIGtlZXBSb3RhdGlvbjogdHJ1ZSxcbiAgICBtb3VzZUJ1dHRvbjogTW91c2VCdXR0b25zLkxFRlQsXG4gIH07XG5cbiAgaW5pdChjZXNpdW1TZXJ2aWNlOiBDZXNpdW1TZXJ2aWNlLCBjYW1lcmFTZXJ2aWNlOiBDYW1lcmFTZXJ2aWNlKSB7XG4gICAgdGhpcy5jYW1lcmFTZXJ2aWNlID0gY2FtZXJhU2VydmljZTtcbiAgICB0aGlzLmNlc2l1bVNlcnZpY2UgPSBjZXNpdW1TZXJ2aWNlO1xuICB9XG5cbiAgYWN0aXZhdGUoXG4gICAgb3B0aW9uczoge1xuICAgICAgb25TdGFydD86IChhY01hcD86IEFjTWFwQ29tcG9uZW50KSA9PiBhbnk7XG4gICAgICBvbkNvbXBsZXRlPzogKGFjTWFwPzogQWNNYXBDb21wb25lbnQpID0+IGFueTtcbiAgICAgIG1vdXNlQnV0dG9uPzogTW91c2VCdXR0b25zO1xuICAgICAgYXV0b0Rpc2FibGVPblpvb20/OiBib29sZWFuO1xuICAgICAgYW5pbWF0aW9uRHVyYXRpb25JblNlY29uZHM/OiBudW1iZXI7XG4gICAgICB0aHJlc2hvbGQ/OiBudW1iZXI7XG4gICAgICBrZWVwUm90YXRpb24/OiBib29sZWFuO1xuICAgICAgYm9yZGVyU3R5bGU/OiBzdHJpbmc7XG4gICAgICBiYWNrZ3JvdW5kQ29sb3I/OiBzdHJpbmc7XG4gICAgICByZXNldEtleUNvZGU/OiBudW1iZXI7XG4gICAgfSA9IHt9LFxuICAgIG1hcElkPzogc3RyaW5nLFxuICApIHtcbiAgICBpZiAoKCF0aGlzLmNhbWVyYVNlcnZpY2UgfHwgIXRoaXMuY2VzaXVtU2VydmljZSkgJiYgIW1hcElkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSBmdW5jdGlvbiBtdXN0IHJlY2VpdmUgYSBtYXBJZCBpZiB0aGUgc2VydmljZSB3YXNuJ3QgaW5pdGlhbGl6ZWRgKTtcbiAgICB9XG4gICAgY29uc3QgZmluYWxPcHRpb25zID0gT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5kZWZhdWx0T3B0aW9ucywgb3B0aW9ucyk7XG4gICAgbGV0IGNhbWVyYVNlcnZpY2UgPSB0aGlzLmNhbWVyYVNlcnZpY2U7XG4gICAgbGV0IG1hcENvbnRhaW5lcjtcbiAgICBsZXQgbWFwO1xuICAgIGlmICghbWFwSWQpIHtcbiAgICAgIG1hcCA9IHRoaXMubWFwc01hbmFnZXIuZ2V0TWFwKCk7XG4gICAgICBpZiAoIW1hcCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE1hcCBub3QgZm91bmRgKTtcbiAgICAgIH1cbiAgICAgIG1hcElkID0gbWFwLmdldElkKCk7XG4gICAgICBtYXBDb250YWluZXIgPSB0aGlzLmNlc2l1bVNlcnZpY2UuZ2V0Vmlld2VyKCkuY29udGFpbmVyO1xuICAgIH0gZWxzZSB7XG4gICAgICBtYXAgPSB0aGlzLm1hcHNNYW5hZ2VyLmdldE1hcChtYXBJZCk7XG4gICAgICBpZiAoIW1hcCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE1hcCBub3QgZm91bmQgd2l0aCBpZDogJHttYXBJZH1gKTtcbiAgICAgIH1cbiAgICAgIGNhbWVyYVNlcnZpY2UgPSBtYXAuZ2V0Q2FtZXJhU2VydmljZSgpO1xuICAgICAgbWFwQ29udGFpbmVyID0gbWFwLmdldENlc2l1bVZpZXdlcigpLmNvbnRhaW5lcjtcbiAgICB9XG5cbiAgICBpZiAoIWNhbWVyYVNlcnZpY2UgfHwgIW1hcENvbnRhaW5lcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgZnVuY3Rpb24gbXVzdCByZWNlaXZlIGEgbWFwSWQgaWYgdGhlIHNlcnZpY2Ugd2Fzbid0IGluaXRpYWxpemVkYCk7XG4gICAgfVxuICAgIHRoaXMuZGlzYWJsZShtYXBJZCk7XG4gICAgY29uc3QgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgbWFwQ29udGFpbmVyLnN0eWxlLnBvc2l0aW9uID0gJ3JlbGF0aXZlJztcbiAgICBjb250YWluZXIuc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgIGNvbnRhaW5lci5zdHlsZS53aWR0aCA9ICcxMDAlJztcbiAgICBjb250YWluZXIuc3R5bGUuaGVpZ2h0ID0gJzEwMCUnO1xuICAgIGNvbnRhaW5lci5zdHlsZS50b3AgPSAnMCc7XG4gICAgY29udGFpbmVyLnN0eWxlLmxlZnQgPSAnMCc7XG4gICAgbWFwQ29udGFpbmVyLmFwcGVuZENoaWxkKGNvbnRhaW5lcik7XG4gICAgY29uc3QgbWFwWm9vbURhdGE6IFpvb21EYXRhID0geyBjb250YWluZXIgfTtcbiAgICB0aGlzLm1hcHNab29tRWxlbWVudHMuc2V0KG1hcElkLCBtYXBab29tRGF0YSk7XG4gICAgbGV0IG1vdXNlID0ge1xuICAgICAgZW5kWDogMCxcbiAgICAgIGVuZFk6IDAsXG4gICAgICBzdGFydFg6IDAsXG4gICAgICBzdGFydFk6IDAsXG4gICAgfTtcbiAgICBsZXQgYm9yZGVyRWxlbWVudDogSFRNTEVsZW1lbnQgfCB1bmRlZmluZWQ7XG5cbiAgICBjb250YWluZXIub25tb3VzZWRvd24gPSBlID0+IHtcbiAgICAgIGlmIChlLmJ1dHRvbiAhPT0gZmluYWxPcHRpb25zLm1vdXNlQnV0dG9uKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmICghYm9yZGVyRWxlbWVudCkge1xuICAgICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLm9uU3RhcnQpIHtcbiAgICAgICAgICBvcHRpb25zLm9uU3RhcnQobWFwKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlY3QgPSAoZS5jdXJyZW50VGFyZ2V0IGFzIGFueSkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIGNvbnN0IG9mZnNldFggPSBlLmNsaWVudFggLSByZWN0LmxlZnQ7XG4gICAgICAgIGNvbnN0IG9mZnNldFkgPSBlLmNsaWVudFkgLSByZWN0LnRvcDtcbiAgICAgICAgbW91c2Uuc3RhcnRYID0gb2Zmc2V0WDtcbiAgICAgICAgbW91c2Uuc3RhcnRZID0gb2Zmc2V0WTtcbiAgICAgICAgYm9yZGVyRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICBib3JkZXJFbGVtZW50LmNsYXNzTmFtZSA9ICd6b29tLXRvLXJlY3RhbmdsZS1ib3JkZXInO1xuICAgICAgICBib3JkZXJFbGVtZW50LnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICAgICAgYm9yZGVyRWxlbWVudC5zdHlsZS5ib3JkZXIgPSBmaW5hbE9wdGlvbnMuYm9yZGVyU3R5bGU7XG4gICAgICAgIGJvcmRlckVsZW1lbnQuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gZmluYWxPcHRpb25zLmJhY2tncm91bmRDb2xvcjtcbiAgICAgICAgYm9yZGVyRWxlbWVudC5zdHlsZS5sZWZ0ID0gbW91c2Uuc3RhcnRYICsgJ3B4JztcbiAgICAgICAgYm9yZGVyRWxlbWVudC5zdHlsZS50b3AgPSBtb3VzZS5zdGFydFkgKyAncHgnO1xuICAgICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQoYm9yZGVyRWxlbWVudCk7XG4gICAgICAgIG1hcFpvb21EYXRhLmJvcmRlckVsZW1lbnQgPSBib3JkZXJFbGVtZW50O1xuICAgICAgfVxuICAgIH07XG5cbiAgICBjb250YWluZXIub25tb3VzZXVwID0gZSA9PiB7XG4gICAgICBpZiAoYm9yZGVyRWxlbWVudCkge1xuICAgICAgICBsZXQgem9vbUFwcGxpZWQ7XG4gICAgICAgIGlmIChtb3VzZSAmJiBNYXRoLmFicyhtb3VzZS5lbmRYIC0gbW91c2Uuc3RhcnRYKSAqIE1hdGguYWJzKG1vdXNlLmVuZFkgLSBtb3VzZS5zdGFydFkpID4gZmluYWxPcHRpb25zLnRocmVzaG9sZCkge1xuICAgICAgICAgIHpvb21BcHBsaWVkID0gdGhpcy56b29tQ2FtZXJhVG9SZWN0YW5nbGUoXG4gICAgICAgICAgICBjYW1lcmFTZXJ2aWNlLFxuICAgICAgICAgICAgbW91c2UsXG4gICAgICAgICAgICBmaW5hbE9wdGlvbnMuYW5pbWF0aW9uRHVyYXRpb25JblNlY29uZHMsXG4gICAgICAgICAgICBmaW5hbE9wdGlvbnMsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBib3JkZXJFbGVtZW50LnJlbW92ZSgpO1xuICAgICAgICBib3JkZXJFbGVtZW50ID0gdW5kZWZpbmVkO1xuICAgICAgICBtYXBab29tRGF0YS5ib3JkZXJFbGVtZW50ID0gdW5kZWZpbmVkO1xuICAgICAgICBtb3VzZSA9IHtcbiAgICAgICAgICBlbmRYOiAwLFxuICAgICAgICAgIGVuZFk6IDAsXG4gICAgICAgICAgc3RhcnRYOiAwLFxuICAgICAgICAgIHN0YXJ0WTogMCxcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKCEhZmluYWxPcHRpb25zLm9uQ29tcGxldGUpIHtcbiAgICAgICAgICBmaW5hbE9wdGlvbnMub25Db21wbGV0ZShtYXApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmaW5hbE9wdGlvbnMuYXV0b0Rpc2FibGVPblpvb20gJiYgem9vbUFwcGxpZWQpIHtcbiAgICAgICAgICB0aGlzLmRpc2FibGUobWFwSWQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIGNvbnRhaW5lci5vbm1vdXNlbW92ZSA9IGUgPT4ge1xuICAgICAgaWYgKGJvcmRlckVsZW1lbnQpIHtcbiAgICAgICAgY29uc3QgcmVjdCA9IChlLmN1cnJlbnRUYXJnZXQgYXMgYW55KS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgY29uc3Qgb2Zmc2V0WCA9IGUuY2xpZW50WCAtIHJlY3QubGVmdDtcbiAgICAgICAgY29uc3Qgb2Zmc2V0WSA9IGUuY2xpZW50WSAtIHJlY3QudG9wO1xuICAgICAgICBtb3VzZS5lbmRYID0gb2Zmc2V0WDtcbiAgICAgICAgbW91c2UuZW5kWSA9IG9mZnNldFk7XG4gICAgICAgIGJvcmRlckVsZW1lbnQuc3R5bGUud2lkdGggPSBNYXRoLmFicyhtb3VzZS5lbmRYIC0gbW91c2Uuc3RhcnRYKSArICdweCc7XG4gICAgICAgIGJvcmRlckVsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gTWF0aC5hYnMobW91c2UuZW5kWSAtIG1vdXNlLnN0YXJ0WSkgKyAncHgnO1xuICAgICAgICBib3JkZXJFbGVtZW50LnN0eWxlLmxlZnQgPSBNYXRoLm1pbihtb3VzZS5zdGFydFgsIG1vdXNlLmVuZFgpICsgJ3B4JztcbiAgICAgICAgYm9yZGVyRWxlbWVudC5zdHlsZS50b3AgPSBNYXRoLm1pbihtb3VzZS5zdGFydFksIG1vdXNlLmVuZFkpICsgJ3B4JztcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3QgcmVzZXRPbkVzY2FwZVByZXNzID0gZSA9PiB7XG4gICAgICBpZiAoZS5rZXlDb2RlID09PSBmaW5hbE9wdGlvbnMucmVzZXRLZXlDb2RlICYmIGJvcmRlckVsZW1lbnQpIHtcbiAgICAgICAgYm9yZGVyRWxlbWVudC5yZW1vdmUoKTtcbiAgICAgICAgYm9yZGVyRWxlbWVudCA9IHVuZGVmaW5lZDtcbiAgICAgICAgbWFwWm9vbURhdGEuYm9yZGVyRWxlbWVudCA9IHVuZGVmaW5lZDtcbiAgICAgICAgbW91c2UgPSB7XG4gICAgICAgICAgZW5kWDogMCxcbiAgICAgICAgICBlbmRZOiAwLFxuICAgICAgICAgIHN0YXJ0WDogMCxcbiAgICAgICAgICBzdGFydFk6IDAsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgcmVzZXRPbkVzY2FwZVByZXNzKTtcbiAgICBtYXBab29tRGF0YS5yZXNldE9uRXNjYXBlUHJlc3NGdW5jID0gcmVzZXRPbkVzY2FwZVByZXNzO1xuICB9XG5cbiAgcHVibGljIGRpc2FibGUobWFwSWQ/OiBzdHJpbmcpIHtcbiAgICBpZiAoIXRoaXMubWFwc01hbmFnZXIgJiYgIW1hcElkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lmIHRoZSBzZXJ2aWNlIHdhcyBub3QgaW5pdGlhbGl6ZWQgd2l0aCBNYXBzTWFuYWdlciwgbWFwSWQgbXVzdCBiZSBwcm92aWRlZCcpO1xuICAgIH1cbiAgICBpZiAoIW1hcElkKSB7XG4gICAgICBjb25zdCBtYXAgPSB0aGlzLm1hcHNNYW5hZ2VyLmdldE1hcCgpO1xuICAgICAgbWFwSWQgPSBtYXAuZ2V0SWQoKTtcbiAgICB9XG4gICAgY29uc3QgZGF0YSA9IHRoaXMubWFwc1pvb21FbGVtZW50cy5nZXQobWFwSWQpO1xuICAgIGlmIChkYXRhKSB7XG4gICAgICBkYXRhLmNvbnRhaW5lci5yZW1vdmUoKTtcbiAgICAgIGlmIChkYXRhLmJvcmRlckVsZW1lbnQpIHtcbiAgICAgICAgZGF0YS5ib3JkZXJFbGVtZW50LnJlbW92ZSgpO1xuICAgICAgfVxuICAgICAgaWYgKGRhdGEucmVzZXRPbkVzY2FwZVByZXNzRnVuYykge1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdrZXlkb3duJywgZGF0YS5yZXNldE9uRXNjYXBlUHJlc3NGdW5jKTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5tYXBzWm9vbUVsZW1lbnRzLmRlbGV0ZShtYXBJZCk7XG4gIH1cblxuICBwcml2YXRlIHpvb21DYW1lcmFUb1JlY3RhbmdsZShcbiAgICBjYW1lcmFTZXJ2aWNlOiBDYW1lcmFTZXJ2aWNlLFxuICAgIHBvc2l0aW9uczogeyBlbmRYOiBudW1iZXI7IGVuZFk6IG51bWJlcjsgc3RhcnRYOiBudW1iZXI7IHN0YXJ0WTogbnVtYmVyIH0sXG4gICAgYW5pbWF0aW9uRHVyYXRpb24sXG4gICAgb3B0aW9ucyxcbiAgKTogYm9vbGVhbiB7XG4gICAgY29uc3QgY2FtZXJhID0gY2FtZXJhU2VydmljZS5nZXRDYW1lcmEoKTtcbiAgICBjb25zdCBjYXJ0ZXNpYW4xID0gY2FtZXJhLnBpY2tFbGxpcHNvaWQoeyB4OiBwb3NpdGlvbnMuc3RhcnRYLCB5OiBwb3NpdGlvbnMuc3RhcnRZIH0pO1xuICAgIGNvbnN0IGNhcnRlc2lhbjIgPSBjYW1lcmEucGlja0VsbGlwc29pZCh7IHg6IHBvc2l0aW9ucy5lbmRYLCB5OiBwb3NpdGlvbnMuZW5kWSB9KTtcbiAgICBpZiAoIWNhcnRlc2lhbjEgfHwgIWNhcnRlc2lhbjIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgY29uc3QgY2FydG9ncmFwaGljMSA9IENhcnRvZ3JhcGhpYy5mcm9tQ2FydGVzaWFuKGNhcnRlc2lhbjEpO1xuICAgIGNvbnN0IGNhcnRvZ3JhcGhpYzIgPSBDYXJ0b2dyYXBoaWMuZnJvbUNhcnRlc2lhbihjYXJ0ZXNpYW4yKTtcbiAgICBjYW1lcmFTZXJ2aWNlLmNhbWVyYUZseVRvKHtcbiAgICAgIGRlc3RpbmF0aW9uOiBuZXcgUmVjdGFuZ2xlKFxuICAgICAgICBNYXRoLm1pbihjYXJ0b2dyYXBoaWMxLmxvbmdpdHVkZSwgY2FydG9ncmFwaGljMi5sb25naXR1ZGUpLFxuICAgICAgICBNYXRoLm1pbihjYXJ0b2dyYXBoaWMxLmxhdGl0dWRlLCBjYXJ0b2dyYXBoaWMyLmxhdGl0dWRlKSxcbiAgICAgICAgTWF0aC5tYXgoY2FydG9ncmFwaGljMS5sb25naXR1ZGUsIGNhcnRvZ3JhcGhpYzIubG9uZ2l0dWRlKSxcbiAgICAgICAgTWF0aC5tYXgoY2FydG9ncmFwaGljMS5sYXRpdHVkZSwgY2FydG9ncmFwaGljMi5sYXRpdHVkZSksXG4gICAgICApLFxuICAgICAgb3JpZW50YXRpb246IG9wdGlvbnMua2VlcFJvdGF0aW9uID8geyBoZWFkaW5nOiBjYW1lcmEuaGVhZGluZyB9IDogdW5kZWZpbmVkLFxuICAgICAgZHVyYXRpb246IGFuaW1hdGlvbkR1cmF0aW9uLFxuICAgIH0pO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG4iXX0=