UNPKG

bp-prism-game

Version:
203 lines 24.1 kB
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=