bp-prism-game
Version:
The BP Prism Game
203 lines • 24.1 kB
JavaScript
import { Injectable } from '@angular/core';
import { AlienPathEnum } from '../enum/alien-path.enum';
import { AlienPathDirectionEnum } from '../enum/alien-path-direction.enum';
import { BLOCK_SIZE } from '../gameboard/gameboard-constants';
import { AssetDirectionEnum } from '../enum/asset-direction.enum';
import * as i0 from "@angular/core";
/**
* The path service
*/
export class PathService {
// http://gregtrowbridge.com/a-basic-pathfinding-algorithm/
/**
* Finds the shortest path for an alien from the spawn location
* To the base
*
* @param startCoordinates the Starting Coordinating
*/
findShortestPath(startCoordinates, gameboard) {
const pathBoard = JSON.parse(JSON.stringify(gameboard));
const distanceFromLeft = startCoordinates.x;
const distanceFromTop = startCoordinates.y;
// Each "location" will store its coordinates
// and the shortest path required to arrive there
const location = {
distanceFromTop,
distanceFromLeft,
path: [
{
x: distanceFromLeft * BLOCK_SIZE,
y: distanceFromTop * BLOCK_SIZE
}
],
status: AlienPathEnum.start
};
// Initialize the queue with the start location already inside
const queue = [location];
// Loop through the grid searching for the goal
while (queue.length > 0) {
// Take the first location off the queue
const currentLocation = queue.shift();
// Explore South
let newLocation = this.exploreInDirection(currentLocation, AlienPathDirectionEnum.south, pathBoard);
if (newLocation.status === AlienPathEnum.goal) {
return newLocation.path;
}
else if (newLocation.status === AlienPathEnum.valid) {
queue.push(newLocation);
}
// Explore East
newLocation = this.exploreInDirection(currentLocation, AlienPathDirectionEnum.east, pathBoard);
if (newLocation.status === AlienPathEnum.goal) {
return newLocation.path;
}
else if (newLocation.status === AlienPathEnum.valid) {
queue.push(newLocation);
}
// Explore West
newLocation = this.exploreInDirection(currentLocation, AlienPathDirectionEnum.west, pathBoard);
if (newLocation.status === AlienPathEnum.goal) {
return newLocation.path;
}
else if (newLocation.status === AlienPathEnum.valid) {
queue.push(newLocation);
}
// Explore North
newLocation = this.exploreInDirection(currentLocation, AlienPathDirectionEnum.north, pathBoard);
if (newLocation.status === AlienPathEnum.goal) {
return newLocation.path;
}
else if (newLocation.status === AlienPathEnum.valid) {
queue.push(newLocation);
}
}
// No valid path found
return [];
// Emergency map fix
/*
return [
{
x: 0,
y: 0,
rotate: 0
} as IAsset
];
*/
}
/**
* Checks the location status
*/
locationStatus(location, localPathboard) {
const yGridSize = localPathboard.length;
const xGridSize = localPathboard[0].length;
const distanceFromTop = location.distanceFromTop;
const distanceFromLeft = location.distanceFromLeft;
if (location.distanceFromLeft < 0 ||
location.distanceFromLeft >= xGridSize ||
location.distanceFromTop < 0 ||
location.distanceFromTop >= yGridSize) {
// location is not on the grid--return false
return AlienPathEnum.invalid;
}
else if (localPathboard[distanceFromTop][distanceFromLeft] === AlienPathEnum.goal) {
return AlienPathEnum.goal;
}
else if (localPathboard[distanceFromTop][distanceFromLeft] !== AlienPathEnum.empty) {
// location is either an obstacle or has been visited
return AlienPathEnum.blocked;
}
else {
return AlienPathEnum.valid;
}
}
/**
* Explore around the current location
* @param currentLocation The current location
* @param direction the direction to explore
*/
exploreInDirection(currentLocation, direction, localPathboard) {
const newPath = currentLocation.path.slice();
let rotation = 0;
let distanceFromTop = currentLocation.distanceFromTop;
let distanceFromLeft = currentLocation.distanceFromLeft;
if (direction === AlienPathDirectionEnum.north) {
distanceFromTop -= 1;
rotation = AssetDirectionEnum.north;
}
else if (direction === AlienPathDirectionEnum.east) {
rotation = AssetDirectionEnum.east;
distanceFromLeft += 1;
}
else if (direction === AlienPathDirectionEnum.south) {
rotation = AssetDirectionEnum.south;
distanceFromTop += 1;
}
else {
rotation = AssetDirectionEnum.west;
distanceFromLeft -= 1;
}
let xOffset = 0;
let yOffset = 0;
const offset = BLOCK_SIZE / 2;
if (rotation === AssetDirectionEnum.north) {
yOffset = offset;
}
else if (rotation === AssetDirectionEnum.south) {
yOffset = -offset;
}
else if (rotation === AssetDirectionEnum.east) {
xOffset = -offset;
}
else {
xOffset = offset;
}
newPath.push({
x: distanceFromLeft * BLOCK_SIZE + xOffset,
y: distanceFromTop * BLOCK_SIZE + yOffset,
rotate: rotation
});
newPath.push({
x: distanceFromLeft * BLOCK_SIZE,
y: distanceFromTop * BLOCK_SIZE,
rotate: rotation
});
const newLocation = {
distanceFromTop,
distanceFromLeft,
path: newPath,
status: AlienPathEnum.unknown
};
newLocation.status = this.locationStatus(newLocation, localPathboard);
// If this new location is valid, mark it as 'Visited'
if (newLocation.status === AlienPathEnum.valid) {
localPathboard[newLocation.distanceFromTop][newLocation.distanceFromLeft] = AlienPathEnum.visited;
}
return newLocation;
}
/**
* Get the Alien Drop Ship Path
* @param startPosition The starting position
* @param endPosition The ending position
*/
getAlienDropShipPath(startPosition, endPosition) {
const path = [];
const yPosition = endPosition.y > 0 ? endPosition.y - BLOCK_SIZE : endPosition.y;
for (let index = startPosition.x; index <= endPosition.x; index += BLOCK_SIZE / 2) {
path.push({
x: index,
y: yPosition,
rotate: AssetDirectionEnum.north
});
}
return path;
}
}
PathService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: PathService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
PathService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: PathService, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: PathService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF0aC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvcHJpc20vc3JjL2xpYi9zZXJ2aWNlL3BhdGguc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRTNDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUV4RCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUMzRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDOUQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sOEJBQThCLENBQUM7O0FBRWxFOztHQUVHO0FBSUgsTUFBTSxPQUFPLFdBQVc7SUFDdEIsMkRBQTJEO0lBQzNEOzs7OztPQUtHO0lBQ0gsZ0JBQWdCLENBQUMsZ0JBQXdCLEVBQUUsU0FBNEI7UUFDckUsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFzQixDQUFDO1FBQzdFLE1BQU0sZ0JBQWdCLEdBQUcsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDO1FBQzVDLE1BQU0sZUFBZSxHQUFHLGdCQUFnQixDQUFDLENBQUMsQ0FBQztRQUUzQyw2Q0FBNkM7UUFDN0MsaURBQWlEO1FBQ2pELE1BQU0sUUFBUSxHQUFHO1lBQ2YsZUFBZTtZQUNmLGdCQUFnQjtZQUNoQixJQUFJLEVBQUU7Z0JBQ0o7b0JBQ0UsQ0FBQyxFQUFFLGdCQUFnQixHQUFHLFVBQVU7b0JBQ2hDLENBQUMsRUFBRSxlQUFlLEdBQUcsVUFBVTtpQkFDdEI7YUFDWjtZQUNELE1BQU0sRUFBRSxhQUFhLENBQUMsS0FBSztTQUNOLENBQUM7UUFFeEIsOERBQThEO1FBQzlELE1BQU0sS0FBSyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7UUFF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QyxnQkFBZ0IsQ0FBQyxHQUFHLGFBQWEsQ0FBQyxPQUFPLENBQUM7U0FDbkc7UUFFRCxPQUFPLFdBQVcsQ0FBQztJQUNyQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILG9CQUFvQixDQUFDLGFBQXFCLEVBQUUsV0FBbUI7UUFDN0QsTUFBTSxJQUFJLEdBQWEsRUFBRSxDQUFDO1FBQzFCLE1BQU0sU0FBUyxHQUFHLFdBQVcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztRQUNqRixLQUFLLElBQUksS0FBSyxHQUFHLGFBQWEsQ0FBQyxDQUFDLEVBQUUsS0FBSyxJQUFJLFdBQVcsQ0FBQyxDQUFDLEVBQUUsS0FBSyxJQUFJLFVBQVUsR0FBRyxDQUFDLEVBQUU7WUFDakYsSUFBSSxDQUFDLElBQUksQ0FBQztnQkFDUixDQUFDLEVBQUUsS0FBSztnQkFDUixDQUFDLEVBQUUsU0FBUztnQkFDWixNQUFNLEVBQUUsa0JBQWtCLENBQUMsS0FBSzthQUN2QixDQUFDLENBQUM7U0FDZDtRQUVELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQzs7d0dBdE1VLFdBQVc7NEdBQVgsV0FBVyxjQUZWLE1BQU07MkZBRVAsV0FBVztrQkFIdkIsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBJQXNzZXQgfSBmcm9tICcuLi9pbnRlcmZhY2UvYXNzZXQuaW50ZXJmYWNlJztcbmltcG9ydCB7IEFsaWVuUGF0aEVudW0gfSBmcm9tICcuLi9lbnVtL2FsaWVuLXBhdGguZW51bSc7XG5pbXBvcnQgeyBBbGllbkxvY2F0aW9uTW9kZWwgfSBmcm9tICcuLi9tb2RlbC9hbGllbi9hbGllbi1sb2NhdGlvbi5tb2RlbCc7XG5pbXBvcnQgeyBBbGllblBhdGhEaXJlY3Rpb25FbnVtIH0gZnJvbSAnLi4vZW51bS9hbGllbi1wYXRoLWRpcmVjdGlvbi5lbnVtJztcbmltcG9ydCB7IEJMT0NLX1NJWkUgfSBmcm9tICcuLi9nYW1lYm9hcmQvZ2FtZWJvYXJkLWNvbnN0YW50cyc7XG5pbXBvcnQgeyBBc3NldERpcmVjdGlvbkVudW0gfSBmcm9tICcuLi9lbnVtL2Fzc2V0LWRpcmVjdGlvbi5lbnVtJztcblxuLyoqXG4gKiBUaGUgcGF0aCBzZXJ2aWNlXG4gKi9cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIFBhdGhTZXJ2aWNlIHtcbiAgLy8gaHR0cDovL2dyZWd0cm93YnJpZGdlLmNvbS9hLWJhc2ljLXBhdGhmaW5kaW5nLWFsZ29yaXRobS9cbiAgLyoqXG4gICAqIEZpbmRzIHRoZSBzaG9ydGVzdCBwYXRoIGZvciBhbiBhbGllbiBmcm9tIHRoZSBzcGF3biBsb2NhdGlvblxuICAgKiBUbyB0aGUgYmFzZVxuICAgKlxuICAgKiBAcGFyYW0gc3RhcnRDb29yZGluYXRlcyAgdGhlIFN0YXJ0aW5nIENvb3JkaW5hdGluZ1xuICAgKi9cbiAgZmluZFNob3J0ZXN0UGF0aChzdGFydENvb3JkaW5hdGVzOiBJQXNzZXQsIGdhbWVib2FyZDogQWxpZW5QYXRoRW51bVtdW10pOiBJQXNzZXRbXSB7XG4gICAgY29uc3QgcGF0aEJvYXJkID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShnYW1lYm9hcmQpKSBhcyBBbGllblBhdGhFbnVtW11bXTtcbiAgICBjb25zdCBkaXN0YW5jZUZyb21MZWZ0ID0gc3RhcnRDb29yZGluYXRlcy54O1xuICAgIGNvbnN0IGRpc3RhbmNlRnJvbVRvcCA9IHN0YXJ0Q29vcmRpbmF0ZXMueTtcblxuICAgIC8vIEVhY2ggXCJsb2NhdGlvblwiIHdpbGwgc3RvcmUgaXRzIGNvb3JkaW5hdGVzXG4gICAgLy8gYW5kIHRoZSBzaG9ydGVzdCBwYXRoIHJlcXVpcmVkIHRvIGFycml2ZSB0aGVyZVxuICAgIGNvbnN0IGxvY2F0aW9uID0ge1xuICAgICAgZGlzdGFuY2VGcm9tVG9wLFxuICAgICAgZGlzdGFuY2VGcm9tTGVmdCxcbiAgICAgIHBhdGg6IFtcbiAgICAgICAge1xuICAgICAgICAgIHg6IGRpc3RhbmNlRnJvbUxlZnQgKiBCTE9DS19TSVpFLFxuICAgICAgICAgIHk6IGRpc3RhbmNlRnJvbVRvcCAqIEJMT0NLX1NJWkVcbiAgICAgICAgfSBhcyBJQXNzZXRcbiAgICAgIF0sXG4gICAgICBzdGF0dXM6IEFsaWVuUGF0aEVudW0uc3RhcnRcbiAgICB9IGFzIEFsaWVuTG9jYXRpb25Nb2RlbDtcblxuICAgIC8vIEluaXRpYWxpemUgdGhlIHF1ZXVlIHdpdGggdGhlIHN0YXJ0IGxvY2F0aW9uIGFscmVhZHkgaW5zaWRlXG4gICAgY29uc3QgcXVldWUgPSBbbG9jYXRpb25dO1xuXG4gICAgLy8gTG9vcCB0aHJvdWdoIHRoZSBncmlkIHNlYXJjaGluZyBmb3IgdGhlIGdvYWxcbiAgICB3aGlsZSAocXVldWUubGVuZ3RoID4gMCkge1xuICAgICAgLy8gVGFrZSB0aGUgZmlyc3QgbG9jYXRpb24gb2ZmIHRoZSBxdWV1ZVxuICAgICAgY29uc3QgY3VycmVudExvY2F0aW9uID0gcXVldWUuc2hpZnQoKTtcblxuICAgICAgLy8gRXhwbG9yZSBTb3V0aFxuICAgICAgbGV0IG5ld0xvY2F0aW9uID0gdGhpcy5leHBsb3JlSW5EaXJlY3Rpb24oY3VycmVudExvY2F0aW9uLCBBbGllblBhdGhEaXJlY3Rpb25FbnVtLnNvdXRoLCBwYXRoQm9hcmQpO1xuICAgICAgaWYgKG5ld0xvY2F0aW9uLnN0YXR1cyA9PT0gQWxpZW5QYXRoRW51bS5nb2FsKSB7XG4gICAgICAgIHJldHVybiBuZXdMb2NhdGlvbi5wYXRoO1xuICAgICAgfSBlbHNlIGlmIChuZXdMb2NhdGlvbi5zdGF0dXMgPT09IEFsaWVuUGF0aEVudW0udmFsaWQpIHtcbiAgICAgICAgcXVldWUucHVzaChuZXdMb2NhdGlvbik7XG4gICAgICB9XG5cbiAgICAgIC8vIEV4cGxvcmUgRWFzdFxuICAgICAgbmV3TG9jYXRpb24gPSB0aGlzLmV4cGxvcmVJbkRpcmVjdGlvbihjdXJyZW50TG9jYXRpb24sIEFsaWVuUGF0aERpcmVjdGlvbkVudW0uZWFzdCwgcGF0aEJvYXJkKTtcbiAgICAgIGlmIChuZXdMb2NhdGlvbi5zdGF0dXMgPT09IEFsaWVuUGF0aEVudW0uZ29hbCkge1xuICAgICAgICByZXR1cm4gbmV3TG9jYXRpb24ucGF0aDtcbiAgICAgIH0gZWxzZSBpZiAobmV3TG9jYXRpb24uc3RhdHVzID09PSBBbGllblBhdGhFbnVtLnZhbGlkKSB7XG4gICAgICAgIHF1ZXVlLnB1c2gobmV3TG9jYXRpb24pO1xuICAgICAgfVxuXG4gICAgICAvLyBFeHBsb3JlIFdlc3RcbiAgICAgIG5ld0xvY2F0aW9uID0gdGhpcy5leHBsb3JlSW5EaXJlY3Rpb24oY3VycmVudExvY2F0aW9uLCBBbGllblBhdGhEaXJlY3Rpb25FbnVtLndlc3QsIHBhdGhCb2FyZCk7XG4gICAgICBpZiAobmV3TG9jYXRpb24uc3RhdHVzID09PSBBbGllblBhdGhFbnVtLmdvYWwpIHtcbiAgICAgICAgcmV0dXJuIG5ld0xvY2F0aW9uLnBhdGg7XG4gICAgICB9IGVsc2UgaWYgKG5ld0xvY2F0aW9uLnN0YXR1cyA9PT0gQWxpZW5QYXRoRW51bS52YWxpZCkge1xuICAgICAgICBxdWV1ZS5wdXNoKG5ld0xvY2F0aW9uKTtcbiAgICAgIH1cblxuICAgICAgLy8gRXhwbG9yZSBOb3J0aFxuICAgICAgbmV3TG9jYXRpb24gPSB0aGlzLmV4cGxvcmVJbkRpcmVjdGlvbihjdXJyZW50TG9jYXRpb24sIEFsaWVuUGF0aERpcmVjdGlvbkVudW0ubm9ydGgsIHBhdGhCb2FyZCk7XG4gICAgICBpZiAobmV3TG9jYXRpb24uc3RhdHVzID09PSBBbGllblBhdGhFbnVtLmdvYWwpIHtcbiAgICAgICAgcmV0dXJuIG5ld0xvY2F0aW9uLnBhdGg7XG4gICAgICB9IGVsc2UgaWYgKG5ld0xvY2F0aW9uLnN0YXR1cyA9PT0gQWxpZW5QYXRoRW51bS52YWxpZCkge1xuICAgICAgICBxdWV1ZS5wdXNoKG5ld0xvY2F0aW9uKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBObyB2YWxpZCBwYXRoIGZvdW5kXG4gICAgcmV0dXJuIFtdO1xuICAgIC8vIEVtZXJnZW5jeSBtYXAgZml4XG4gICAgLypcbiAgICByZXR1cm4gW1xuICAgICAge1xuICAgICAgICB4OiAwLFxuICAgICAgICB5OiAwLFxuICAgICAgICByb3RhdGU6IDBcbiAgICAgIH0gYXMgSUFzc2V0XG4gICAgXTtcbiAgICAqL1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyB0aGUgbG9jYXRpb24gc3RhdHVzXG4gICAqL1xuICBwcml2YXRlIGxvY2F0aW9uU3RhdHVzKGxvY2F0aW9uOiBBbGllbkxvY2F0aW9uTW9kZWwsIGxvY2FsUGF0aGJvYXJkOiBBbGllblBhdGhFbnVtW11bXSk6IEFsaWVuUGF0aEVudW0ge1xuICAgIGNvbnN0IHlHcmlkU2l6ZSA9IGxvY2FsUGF0aGJvYXJkLmxlbmd0aDtcbiAgICBjb25zdCB4R3JpZFNpemUgPSBsb2NhbFBhdGhib2FyZFswXS5sZW5ndGg7XG4gICAgY29uc3QgZGlzdGFuY2VGcm9tVG9wID0gbG9jYXRpb24uZGlzdGFuY2VGcm9tVG9wO1xuICAgIGNvbnN0IGRpc3RhbmNlRnJvbUxlZnQgPSBsb2NhdGlvbi5kaXN0YW5jZUZyb21MZWZ0O1xuXG4gICAgaWYgKFxuICAgICAgbG9jYXRpb24uZGlzdGFuY2VGcm9tTGVmdCA8IDAgfHxcbiAgICAgIGxvY2F0aW9uLmRpc3RhbmNlRnJvbUxlZnQgPj0geEdyaWRTaXplIHx8XG4gICAgICBsb2NhdGlvbi5kaXN0YW5jZUZyb21Ub3AgPCAwIHx8XG4gICAgICBsb2NhdGlvbi5kaXN0YW5jZUZyb21Ub3AgPj0geUdyaWRTaXplXG4gICAgKSB7XG4gICAgICAvLyBsb2NhdGlvbiBpcyBub3Qgb24gdGhlIGdyaWQtLXJldHVybiBmYWxzZVxuICAgICAgcmV0dXJuIEFsaWVuUGF0aEVudW0uaW52YWxpZDtcbiAgICB9IGVsc2UgaWYgKGxvY2FsUGF0aGJvYXJkW2Rpc3RhbmNlRnJvbVRvcF1bZGlzdGFuY2VGcm9tTGVmdF0gPT09IEFsaWVuUGF0aEVudW0uZ29hbCkge1xuICAgICAgcmV0dXJuIEFsaWVuUGF0aEVudW0uZ29hbDtcbiAgICB9IGVsc2UgaWYgKGxvY2FsUGF0aGJvYXJkW2Rpc3RhbmNlRnJvbVRvcF1bZGlzdGFuY2VGcm9tTGVmdF0gIT09IEFsaWVuUGF0aEVudW0uZW1wdHkpIHtcbiAgICAgIC8vIGxvY2F0aW9uIGlzIGVpdGhlciBhbiBvYnN0YWNsZSBvciBoYXMgYmVlbiB2aXNpdGVkXG4gICAgICByZXR1cm4gQWxpZW5QYXRoRW51bS5ibG9ja2VkO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gQWxpZW5QYXRoRW51bS52YWxpZDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRXhwbG9yZSBhcm91bmQgdGhlIGN1cnJlbnQgbG9jYXRpb25cbiAgICogQHBhcmFtIGN1cnJlbnRMb2NhdGlvbiBUaGUgY3VycmVudCBsb2NhdGlvblxuICAgKiBAcGFyYW0gZGlyZWN0aW9uIHRoZSBkaXJlY3Rpb24gdG8gZXhwbG9yZVxuICAgKi9cbiAgcHJpdmF0ZSBleHBsb3JlSW5EaXJlY3Rpb24oXG4gICAgY3VycmVudExvY2F0aW9uOiBBbGllbkxvY2F0aW9uTW9kZWwsXG4gICAgZGlyZWN0aW9uOiBBbGllblBhdGhEaXJlY3Rpb25FbnVtLFxuICAgIGxvY2FsUGF0aGJvYXJkOiBBbGllblBhdGhFbnVtW11bXVxuICApOiBBbGllbkxvY2F0aW9uTW9kZWwge1xuICAgIGNvbnN0IG5ld1BhdGggPSBjdXJyZW50TG9jYXRpb24ucGF0aC5zbGljZSgpO1xuICAgIGxldCByb3RhdGlvbiA9IDA7XG5cbiAgICBsZXQgZGlzdGFuY2VGcm9tVG9wID0gY3VycmVudExvY2F0aW9uLmRpc3RhbmNlRnJvbVRvcDtcbiAgICBsZXQgZGlzdGFuY2VGcm9tTGVmdCA9IGN1cnJlbnRMb2NhdGlvbi5kaXN0YW5jZUZyb21MZWZ0O1xuXG4gICAgaWYgKGRpcmVjdGlvbiA9PT0gQWxpZW5QYXRoRGlyZWN0aW9uRW51bS5ub3J0aCkge1xuICAgICAgZGlzdGFuY2VGcm9tVG9wIC09IDE7XG4gICAgICByb3RhdGlvbiA9IEFzc2V0RGlyZWN0aW9uRW51bS5ub3J0aDtcbiAgICB9IGVsc2UgaWYgKGRpcmVjdGlvbiA9PT0gQWxpZW5QYXRoRGlyZWN0aW9uRW51bS5lYXN0KSB7XG4gICAgICByb3RhdGlvbiA9IEFzc2V0RGlyZWN0aW9uRW51bS5lYXN0O1xuICAgICAgZGlzdGFuY2VGcm9tTGVmdCArPSAxO1xuICAgIH0gZWxzZSBpZiAoZGlyZWN0aW9uID09PSBBbGllblBhdGhEaXJlY3Rpb25FbnVtLnNvdXRoKSB7XG4gICAgICByb3RhdGlvbiA9IEFzc2V0RGlyZWN0aW9uRW51bS5zb3V0aDtcbiAgICAgIGRpc3RhbmNlRnJvbVRvcCArPSAxO1xuICAgIH0gZWxzZSB7XG4gICAgICByb3RhdGlvbiA9IEFzc2V0RGlyZWN0aW9uRW51bS53ZXN0O1xuICAgICAgZGlzdGFuY2VGcm9tTGVmdCAtPSAxO1xuICAgIH1cblxuICAgIGxldCB4T2Zmc2V0ID0gMDtcbiAgICBsZXQgeU9mZnNldCA9IDA7XG4gICAgY29uc3Qgb2Zmc2V0ID0gQkxPQ0tfU0laRSAvIDI7XG5cbiAgICBpZiAocm90YXRpb24gPT09IEFzc2V0RGlyZWN0aW9uRW51bS5ub3J0aCkge1xuICAgICAgeU9mZnNldCA9IG9mZnNldDtcbiAgICB9IGVsc2UgaWYgKHJvdGF0aW9uID09PSBBc3NldERpcmVjdGlvbkVudW0uc291dGgpIHtcbiAgICAgIHlPZmZzZXQgPSAtb2Zmc2V0O1xuICAgIH0gZWxzZSBpZiAocm90YXRpb24gPT09IEFzc2V0RGlyZWN0aW9uRW51bS5lYXN0KSB7XG4gICAgICB4T2Zmc2V0ID0gLW9mZnNldDtcbiAgICB9IGVsc2Uge1xuICAgICAgeE9mZnNldCA9IG9mZnNldDtcbiAgICB9XG5cbiAgICBuZXdQYXRoLnB1c2goe1xuICAgICAgeDogZGlzdGFuY2VGcm9tTGVmdCAqIEJMT0NLX1NJWkUgKyB4T2Zmc2V0LFxuICAgICAgeTogZGlzdGFuY2VGcm9tVG9wICogQkxPQ0tfU0laRSArIHlPZmZzZXQsXG4gICAgICByb3RhdGU6IHJvdGF0aW9uXG4gICAgfSBhcyBJQXNzZXQpO1xuXG4gICAgbmV3UGF0aC5wdXNoKHtcbiAgICAgIHg6IGRpc3RhbmNlRnJvbUxlZnQgKiBCTE9DS19TSVpFLFxuICAgICAgeTogZGlzdGFuY2VGcm9tVG9wICogQkxPQ0tfU0laRSxcbiAgICAgIHJvdGF0ZTogcm90YXRpb25cbiAgICB9IGFzIElBc3NldCk7XG5cbiAgICBjb25zdCBuZXdMb2NhdGlvbiA9IHtcbiAgICAgIGRpc3RhbmNlRnJvbVRvcCxcbiAgICAgIGRpc3RhbmNlRnJvbUxlZnQsXG4gICAgICBwYXRoOiBuZXdQYXRoLFxuICAgICAgc3RhdHVzOiBBbGllblBhdGhFbnVtLnVua25vd25cbiAgICB9IGFzIEFsaWVuTG9jYXRpb25Nb2RlbDtcbiAgICBuZXdMb2NhdGlvbi5zdGF0dXMgPSB0aGlzLmxvY2F0aW9uU3RhdHVzKG5ld0xvY2F0aW9uLCBsb2NhbFBhdGhib2FyZCk7XG5cbiAgICAvLyBJZiB0aGlzIG5ldyBsb2NhdGlvbiBpcyB2YWxpZCwgbWFyayBpdCBhcyAnVmlzaXRlZCdcbiAgICBpZiAobmV3TG9jYXRpb24uc3RhdHVzID09PSBBbGllblBhdGhFbnVtLnZhbGlkKSB7XG4gICAgICBsb2NhbFBhdGhib2FyZFtuZXdMb2NhdGlvbi5kaXN0YW5jZUZyb21Ub3BdW25ld0xvY2F0aW9uLmRpc3RhbmNlRnJvbUxlZnRdID0gQWxpZW5QYXRoRW51bS52aXNpdGVkO1xuICAgIH1cblxuICAgIHJldHVybiBuZXdMb2NhdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIEFsaWVuIERyb3AgU2hpcCBQYXRoXG4gICAqIEBwYXJhbSBzdGFydFBvc2l0aW9uIFRoZSBzdGFydGluZyBwb3NpdGlvblxuICAgKiBAcGFyYW0gZW5kUG9zaXRpb24gVGhlIGVuZGluZyBwb3NpdGlvblxuICAgKi9cbiAgZ2V0QWxpZW5Ecm9wU2hpcFBhdGgoc3RhcnRQb3NpdGlvbjogSUFzc2V0LCBlbmRQb3NpdGlvbjogSUFzc2V0KTogSUFzc2V0W10ge1xuICAgIGNvbnN0IHBhdGg6IElBc3NldFtdID0gW107XG4gICAgY29uc3QgeVBvc2l0aW9uID0gZW5kUG9zaXRpb24ueSA+IDAgPyBlbmRQb3NpdGlvbi55IC0gQkxPQ0tfU0laRSA6IGVuZFBvc2l0aW9uLnk7XG4gICAgZm9yIChsZXQgaW5kZXggPSBzdGFydFBvc2l0aW9uLng7IGluZGV4IDw9IGVuZFBvc2l0aW9uLng7IGluZGV4ICs9IEJMT0NLX1NJWkUgLyAyKSB7XG4gICAgICBwYXRoLnB1c2goe1xuICAgICAgICB4OiBpbmRleCxcbiAgICAgICAgeTogeVBvc2l0aW9uLFxuICAgICAgICByb3RhdGU6IEFzc2V0RGlyZWN0aW9uRW51bS5ub3J0aFxuICAgICAgfSBhcyBJQXNzZXQpO1xuICAgIH1cblxuICAgIHJldHVybiBwYXRoO1xuICB9XG59XG4iXX0=