ngx-snake
Version:
Snake game as an angular component, its only the core of the game... you need to add everything around it (controls, score...) yourself :)
214 lines • 28.4 kB
JavaScript
import { Injectable } from '@angular/core';
import { BehaviorSubject, interval, ReplaySubject, Subject } from 'rxjs';
import { MoveDirections, TileState } from '../definitions';
import { filter, switchMap, take, tap } from 'rxjs/operators';
import * as i0 from "@angular/core";
const INITIAL_SPEED = 700;
export class GameManagerService {
constructor() {
this._grid = [];
this._grid$ = new ReplaySubject(1);
this.grid$ = this._grid$.asObservable();
this._gameOver$ = new Subject();
this.gameOver$ = this._gameOver$;
this._foodEaten$ = new Subject();
this.foodEaten$ = this._foodEaten$;
this._gridSize = {
h: 10,
w: 10
};
this._snake = [];
this._nextMoveDir = MoveDirections.RIGHT;
this._moveDir = MoveDirections.RIGHT;
this._food = null;
this._interval$ = new BehaviorSubject(INITIAL_SPEED);
this._paused = true;
this._playable = true;
this.signal$ = this._interval$
.asObservable()
.pipe(switchMap((period) => interval(period)), filter(() => !this._paused), tap(() => this._gameCycle()));
}
initialize(height, width) {
this._gridSize.w = width;
this._gridSize.h = height;
this._buildEmptyGrid();
this._initSnake();
this._drawSnake();
this._gridChanged();
this._signalSub = this.signal$.subscribe();
}
ngOnDestroy() {
if (this._signalSub) {
this._signalSub.unsubscribe();
}
}
start() {
if (this._playable) {
this._paused = false;
}
}
changeSpeed(period) {
this._interval$.next(period);
}
pause() {
this._paused = true;
}
reset() {
this.pause();
this._playable = true;
this._moveDir = MoveDirections.RIGHT;
this._nextMoveDir = this._moveDir;
this._interval$.next(INITIAL_SPEED);
this._buildEmptyGrid();
this._initSnake();
this._drawSnake();
this._gridChanged();
}
up() { this._moveDir !== MoveDirections.DOWN ? this._nextMoveDir = MoveDirections.UP : this._moveDir; }
right() { this._moveDir !== MoveDirections.LEFT ? this._nextMoveDir = MoveDirections.RIGHT : this._moveDir; }
down() { this._moveDir !== MoveDirections.UP ? this._nextMoveDir = MoveDirections.DOWN : this._moveDir; }
left() { this._moveDir !== MoveDirections.RIGHT ? this._nextMoveDir = MoveDirections.LEFT : this._moveDir; }
_endGame() {
this._playable = false;
this.pause();
this._gameOver$.next();
}
_buildEmptyGrid() {
const newGrid = [];
for (let y = 0; y <= this._gridSize.h; y++) {
const row = [];
for (let x = 0; x <= this._gridSize.w; x++) {
row.push(TileState.Free);
}
newGrid.push(row);
}
this._grid = newGrid;
}
_gridChanged() {
this._grid$.next(this._grid);
}
_initSnake() {
this._snake = [];
const xCenter = Math.floor(this._gridSize.w / 2);
const yCenter = Math.floor(this._gridSize.h / 2);
this._snake.push({ x: xCenter, y: yCenter });
this._snake.push({ x: xCenter - 1, y: yCenter });
this._snake.push({ x: xCenter - 2, y: yCenter });
}
_spawnFood() {
if (!this._food) {
const eligibleFields = [];
for (let y = 1; y <= this._gridSize.h - 1; y++) {
for (let x = 1; x <= this._gridSize.w - 1; x++) {
if (this._grid[y][x] === TileState.Free) {
eligibleFields.push({
x, y
});
}
}
}
const shuffled = eligibleFields.sort((a, b) => 0.5 - Math.random());
this._food = shuffled[0];
}
this._grid[this._food.y][this._food.x] = TileState.Food;
}
_drawSnake() {
const head = this._snake[0];
const tail = this._snake[this._snake.length - 1];
this._grid[head.y][head.x] = TileState.Head;
for (let i = 1; i < this._snake.length - 1; i++) {
const part = this._snake[i];
this._grid[part.y][part.x] = TileState.Body;
}
this._grid[tail.y][tail.x] = TileState.Tail;
}
_gameCycle() {
const head = this._snake[0];
let newHead;
this._moveDir = this._nextMoveDir;
if (this._moveDir === MoveDirections.UP) {
newHead = { x: head.x, y: head.y - 1 };
}
else if (this._moveDir === MoveDirections.RIGHT) {
newHead = { x: head.x + 1, y: head.y };
}
else if (this._moveDir === MoveDirections.DOWN) {
newHead = { x: head.x, y: head.y + 1 };
}
else {
// Moving left
newHead = { x: head.x - 1, y: head.y };
}
if (this._willCrash(newHead)) {
return this._endGame();
}
// position new head
this._snake.unshift(newHead);
if (this._willGrow(newHead)) {
this._increaseSpeed();
this._foodEaten$.next();
this._food = null;
}
else {
// drop old tail
this._snake.pop();
}
this._buildEmptyGrid();
this._drawSnake();
this._spawnFood();
this._gridChanged();
}
/**
* Checks if field is not currently occupied (is free to take)
* @param newHead
* @private
*/
_willCrash(newHead) {
// Gets out of the board
if (newHead.x < 0 || newHead.y < 0 || newHead.x > this._gridSize.w || newHead.y > this._gridSize.h) {
return true;
}
const CRASHABLE_FIELDS = [
TileState.Body,
TileState.Wall
];
if (CRASHABLE_FIELDS.includes(this._grid[newHead.y][newHead.x])) {
return true;
}
// If crashing with tail then check if tail will move...
if (this._grid[newHead.y][newHead.x] === TileState.Tail && this._willGrow(newHead)) {
return true;
}
return false;
}
_willGrow(newHead) {
if (this._food && this._food.y === newHead.y && this._food.x === newHead.x) {
return true;
}
return false;
}
_increaseSpeed() {
this._interval$
.pipe(take(1))
.subscribe((current) => {
if (current >= 600) {
this._interval$.next(current - 100);
}
else if (current >= 500) {
this._interval$.next(current - 30);
}
else if (current >= 400) {
this._interval$.next(current - 20);
}
else {
this._interval$.next(current - 10);
}
});
}
}
GameManagerService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: GameManagerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
GameManagerService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: GameManagerService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: GameManagerService, decorators: [{
type: Injectable
}] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2FtZS1tYW5hZ2VyLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtc25ha2Uvc3JjL2xpYi9zZXJ2aWNlcy9nYW1lLW1hbmFnZXIuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsVUFBVSxFQUFZLE1BQU0sZUFBZSxDQUFDO0FBQ3BELE9BQU8sRUFBQyxlQUFlLEVBQUUsUUFBUSxFQUFFLGFBQWEsRUFBRSxPQUFPLEVBQWUsTUFBTSxNQUFNLENBQUM7QUFDckYsT0FBTyxFQUFXLGNBQWMsRUFBRSxTQUFTLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUNuRSxPQUFPLEVBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7O0FBTTVELE1BQU0sYUFBYSxHQUFHLEdBQUcsQ0FBQztBQUcxQixNQUFNLE9BQU8sa0JBQWtCO0lBRC9CO1FBRVksVUFBSyxHQUFhLEVBQUUsQ0FBQztRQUNyQixXQUFNLEdBQUcsSUFBSSxhQUFhLENBQVcsQ0FBQyxDQUFDLENBQUM7UUFDekMsVUFBSyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7UUFFbEMsZUFBVSxHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7UUFDNUIsY0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7UUFFM0IsZ0JBQVcsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQzdCLGVBQVUsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO1FBRzdCLGNBQVMsR0FBRztZQUNoQixDQUFDLEVBQUUsRUFBRTtZQUNMLENBQUMsRUFBRSxFQUFFO1NBQ1IsQ0FBQTtRQUVPLFdBQU0sR0FBZ0IsRUFBRSxDQUFDO1FBQ3pCLGlCQUFZLEdBQW1CLGNBQWMsQ0FBQyxLQUFLLENBQUM7UUFDcEQsYUFBUSxHQUFtQixjQUFjLENBQUMsS0FB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RUFBRSxFQUFFLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQ3BFLElBQUksQ0FBQyxLQUFLLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBRTVCO1FBRUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQztJQUM1RCxDQUFDO0lBRU8sVUFBVTtRQUNkLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDNUIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztRQUVqRCxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQztRQUU1QyxLQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQzVDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDNUIsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUM7U0FDL0M7UUFFRCxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQztJQUNoRCxDQUFDO0lBRU8sVUFBVTtRQUNkLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMs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QUssQ0FBQztJQUNqQixDQUFDO0lBRU8sU0FBUyxDQUFDLE9BQWE7UUFDM0IsSUFBSSxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLE9BQU8sQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssT0FBTyxDQUFDLENBQUMsRUFBRTtZQUN4RSxPQUFPLElBQUksQ0FBQztTQUNmO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDakIsQ0FBQztJQUVPLGNBQWM7UUFDbEIsSUFBSSxDQUFDLFVBQVU7YUFDVixJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ2IsU0FBUyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUU7WUFDbkIsSUFBSSxPQUFPLElBQUksR0FBRyxFQUFFO2dCQUNoQixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLEdBQUcsR0FBRyxDQUFDLENBQUM7YUFFdkM7aUJBQU0sSUFBSSxPQUFPLElBQUksR0FBRyxFQUFFO2dCQUN2QixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLEdBQUcsRUFBRSxDQUFDLENBQUM7YUFFdEM7aUJBQU0sSUFBSSxPQUFPLElBQUksR0FBRyxFQUFFO2dCQUN2QixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLEdBQUcsRUFBRSxDQUFDLENBQUM7YUFFdEM7aUJBQU07Z0JBQ0gsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQyxDQUFDO2FBQ3RDO1FBQ0wsQ0FBQyxDQUFDLENBQUE7SUFDVixDQUFDOzsrR0ExUFEsa0JBQWtCO21IQUFsQixrQkFBa0I7MkZBQWxCLGtCQUFrQjtrQkFEOUIsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7SW5qZWN0YWJsZSwgT25EZXN0cm95fSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7QmVoYXZpb3JTdWJqZWN0LCBpbnRlcnZhbCwgUmVwbGF5U3ViamVjdCwgU3ViamVjdCwgU3Vic2NyaXB0aW9ufSBmcm9tICdyeGpzJztcbmltcG9ydCB7R2FtZUdyaWQsIE1vdmVEaXJlY3Rpb25zLCBUaWxlU3RhdGV9IGZyb20gJy4uL2RlZmluaXRpb25zJztcbmltcG9ydCB7ZmlsdGVyLCBzd2l0Y2hNYXAsIHRha2UsIHRhcH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbnRlcmZhY2UgUGFydCB7XG4gICAgeDogbnVtYmVyLCB5OiBudW1iZXJcbn1cblxuY29uc3QgSU5JVElBTF9TUEVFRCA9IDcwMDtcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIEdhbWVNYW5hZ2VyU2VydmljZSBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG4gICAgcHJpdmF0ZSBfZ3JpZDogR2FtZUdyaWQgPSBbXTtcbiAgICBwcml2YXRlIF9ncmlkJCA9IG5ldyBSZXBsYXlTdWJqZWN0PEdhbWVHcmlkPigxKTtcbiAgICBwdWJsaWMgZ3JpZCQgPSB0aGlzLl9ncmlkJC5hc09ic2VydmFibGUoKTtcblxuICAgIHByaXZhdGUgX2dhbWVPdmVyJCA9IG5ldyBTdWJqZWN0KCk7XG4gICAgcHVibGljIGdhbWVPdmVyJCA9IHRoaXMuX2dhbWVPdmVyJDtcblxuICAgIHByaXZhdGUgX2Zvb2RFYXRlbiQgPSBuZXcgU3ViamVjdCgpO1xuICAgIHB1YmxpYyBmb29kRWF0ZW4kID0gdGhpcy5fZm9vZEVhdGVuJDtcblxuXG4gICAgcHJpdmF0ZSBfZ3JpZFNpemUgPSB7XG4gICAgICAgIGg6IDEwLFxuICAgICAgICB3OiAxMFxuICAgIH1cblxuICAgIHByaXZhdGUgX3NuYWtlOiBBcnJheTxQYXJ0PiA9IFtdO1xuICAgIHByaXZhdGUgX25leHRNb3ZlRGlyOiBNb3ZlRGlyZWN0aW9ucyA9IE1vdmVEaXJlY3Rpb25zLlJJR0hUO1xuICAgIHByaXZhdGUgX21vdmVEaXI6IE1vdmVEaXJlY3Rpb25zID0gTW92ZURpcmVjdGlvbnMuUklHSFQ7XG5cbiAgICBwcml2YXRlIF9mb29kOiBQYXJ0IHwgbnVsbCA9IG51bGw7XG5cbiAgICBwcml2YXRlIF9pbnRlcnZhbCQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0KElOSVRJQUxfU1BFRUQpO1xuICAgIHByaXZhdGUgX3BhdXNlZCA9IHRydWU7XG4gICAgcHJpdmF0ZSBfcGxheWFibGUgPSB0cnVlO1xuICAgIHByaXZhdGUgX3NpZ25hbFN1YjogU3Vic2NyaXB0aW9uO1xuICAgIHB1YmxpYyBzaWduYWwkID0gdGhpcy5faW50ZXJ2YWwkXG4gICAgICAgIC5hc09ic2VydmFibGUoKVxuICAgICAgICAucGlwZShcbiAgICAgICAgICAgIHN3aXRjaE1hcCgocGVyaW9kKSA9PiBpbnRlcnZhbChwZXJpb2QpKSxcbiAgICAgICAgICAgIGZpbHRlcigoKSA9PiAhdGhpcy5fcGF1c2VkKSxcbiAgICAgICAgICAgIHRhcCgoKSA9PiB0aGlzLl9nYW1lQ3ljbGUoKSksXG4gICAgICAgICk7XG5cbiAgICBpbml0aWFsaXplKGhlaWdodDogbnVtYmVyLCB3aWR0aDogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMuX2dyaWRTaXplLncgPSB3aWR0aDtcbiAgICAgICAgdGhpcy5fZ3JpZFNpemUuaCA9IGhlaWdodDtcblxuICAgICAgICB0aGlzLl9idWlsZEVtcHR5R3JpZCgpO1xuICAgICAgICB0aGlzLl9pbml0U25ha2UoKTtcbiAgICAgICAgdGhpcy5fZHJhd1NuYWtlKCk7XG5cbiAgICAgICAgdGhpcy5fZ3JpZENoYW5nZWQoKTtcblxuICAgICAgICB0aGlzLl9zaWduYWxTdWIgPSB0aGlzLnNpZ25hbCQuc3Vic2NyaWJlKCk7XG4gICAgfVxuXG4gICAgbmdPbkRlc3Ryb3koKSB7XG4gICAgICAgIGlmICh0aGlzLl9zaWduYWxTdWIpIHtcbiAgICAgICAgICAgIHRoaXMuX3NpZ25hbFN1Yi51bnN1YnNjcmliZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIHN0YXJ0KCkge1xuICAgICAgICBpZiAodGhpcy5fcGxheWFibGUpIHtcbiAgICAgICAgICAgIHRoaXMuX3BhdXNlZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGNoYW5nZVNwZWVkKHBlcmlvZDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX2ludGVydmFsJC5uZXh0KHBlcmlvZCk7XG4gICAgfVxuXG4gICAgcHVibGljIHBhdXNlKCkge1xuICAgICAgICB0aGlzLl9wYXVzZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIHB1YmxpYyByZXNldCgpIHtcbiAgICAgICAgdGhpcy5wYXVzZSgpO1xuICAgICAgICB0aGlzLl9wbGF5YWJsZSA9IHRydWU7XG4gICAgICAgIHRoaXMuX21vdmVEaXIgPSBNb3ZlRGlyZWN0aW9ucy5SSUdIVDtcbiAgICAgICAgdGhpcy5fbmV4dE1vdmVEaXIgPSB0aGlzLl9tb3ZlRGlyO1xuICAgICAgICB0aGlzLl9pbnRlcnZhbCQubmV4dChJTklUSUFMX1NQRUVEKTtcblxuICAgICAgICB0aGlzLl9idWlsZEVtcHR5R3JpZCgpO1xuICAgICAgICB0aGlzLl9pbml0U25ha2UoKTtcbiAgICAgICAgdGhpcy5fZHJhd1NuYWtlKCk7XG5cbiAgICAgICAgdGhpcy5fZ3JpZENoYW5nZWQoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgdXAoKSB7ICAgICAgIHRoaXMuX21vdmVEaXIgIT09IE1vdmVEaXJlY3Rpb25zLkRPV04gICA/IHRoaXMuX25leHRNb3ZlRGlyID0gTW92ZURpcmVjdGlvbnMuVVAgOiB0aGlzLl9tb3ZlRGlyIH1cbiAgICBwdWJsaWMgcmlnaHQoKSB7ICAgIHRoaXMuX21vdmVEaXIgIT09IE1vdmVEaXJlY3Rpb25zLkxFRlQgICA/IHRoaXMuX25leHRNb3ZlRGlyID0gTW92ZURpcmVjdGlvbnMuUklHSFQgOiB0aGlzLl9tb3ZlRGlyIH1cbiAgICBwdWJsaWMgZG93bigpIHsgICAgIHRoaXMuX21vdmVEaXIgIT09IE1vdmVEaXJlY3Rpb25zLlVQICAgICA/IHRoaXMuX25leHRNb3ZlRGlyID0gTW92ZURpcmVjdGlvbnMuRE9XTiA6IHRoaXMuX21vdmVEaXIgfVxuICAgIHB1YmxpYyBsZWZ0KCkgeyAgICAgdGhpcy5fbW92ZURpciAhPT0gTW92ZURpcmVjdGlvbnMuUklHSFQgID8gdGhpcy5fbmV4dE1vdmVEaXIgPSBNb3ZlRGlyZWN0aW9ucy5MRUZUIDogdGhpcy5fbW92ZURpciB9XG5cbiAgICBwcml2YXRlIF9lbmRHYW1lKCkge1xuICAgICAgICB0aGlzLl9wbGF5YWJsZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLnBhdXNlKCk7XG5cbiAgICAgICAgdGhpcy5fZ2FtZU92ZXIkLm5leHQoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9idWlsZEVtcHR5R3JpZCgpIHtcbiAgICAgICAgY29uc3QgbmV3R3JpZCA9IFtdO1xuICAgICAgICBmb3IobGV0IHkgPSAwOyB5IDw9IHRoaXMuX2dyaWRTaXplLmg7IHkrKykge1xuICAgICAgICAgICAgY29uc3Qgcm93ID0gW107XG4gICAgICAgICAgICBmb3IobGV0IHggPSAwOyB4IDw9IHRoaXMuX2dyaWRTaXplLnc7IHgrKykge1xuICAgICAgICAgICAgICAgIHJvdy5wdXNoKFRpbGVTdGF0ZS5GcmVlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbmV3R3JpZC5wdXNoKHJvdyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9ncmlkID0gIG5ld0dyaWQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfZ3JpZENoYW5nZWQoKSB7XG4gICAgICAgIHRoaXMuX2dyaWQkLm5leHQodGhpcy5fZ3JpZClcbiAgICB9XG5cbiAgICBwcml2YXRlIF9pbml0U25ha2UoKSB7XG4gICAgICAgIHRoaXMuX3NuYWtlID0gW107XG5cbiAgICAgICAgY29uc3QgeENlbnRlciA9IE1hdGguZmxvb3IodGhpcy5fZ3JpZFNpemUudyAvIDIpO1xuICAgICAgICBjb25zdCB5Q2VudGVyID0gTWF0aC5mbG9vcih0aGlzLl9ncmlkU2l6ZS5oIC8gMik7XG5cbiAgICAgICAgdGhpcy5fc25ha2UucHVzaCh7IHg6IHhDZW50ZXIsIHk6IHlDZW50ZXIgfSk7XG4gICAgICAgIHRoaXMuX3NuYWtlLnB1c2goeyB4OiB4Q2VudGVyIC0gMSwgeTogeUNlbnRlciB9KTtcbiAgICAgICAgdGhpcy5fc25ha2UucHVzaCh7IHg6IHhDZW50ZXIgLSAyLCB5OiB5Q2VudGVyIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3NwYXduRm9vZCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9mb29kKSB7XG4gICAgICAgICAgICBjb25zdCBlbGlnaWJsZUZpZWxkcyA9IFtdO1xuICAgICAgICAgICAgZm9yKGxldCB5ID0gMTsgeSA8PSB0aGlzLl9ncmlkU2l6ZS5oIC0gMTsgeSsrKSB7XG4gICAgICAgICAgICAgICAgZm9yKGxldCB4ID0gMTsgeCA8PSB0aGlzLl9ncmlkU2l6ZS53IC0gMSA7IHgrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fZ3JpZFt5XVt4XSA9PT0gVGlsZVN0YXRlLkZyZWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsaWdpYmxlRmllbGRzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHgsIHlcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHNodWZmbGVkID0gZWxpZ2libGVGaWVsZHMuc29ydCgoYSwgYikgPT4gMC41IC0gTWF0aC5yYW5kb20oKSk7XG4gICAgICAgICAgICB0aGlzLl9mb29kID0gc2h1ZmZsZWRbMF07XG5cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2dyaWRbdGhpcy5fZm9vZC55XVt0aGlzLl9mb29kLnhdID0gVGlsZVN0YXRlLkZvb2Q7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfZHJhd1NuYWtlKCkge1xuICAgICAgICBjb25zdCBoZWFkID0gdGhpcy5fc25ha2VbMF07XG4gICAgICAgIGNvbnN0IHRhaWwgPSB0aGlzLl9zbmFrZVt0aGlzLl9zbmFrZS5sZW5ndGggLSAxXTtcblxuICAgICAgICB0aGlzLl9ncmlkW2hlYWQueV1baGVhZC54XSA9IFRpbGVTdGF0ZS5IZWFkO1xuXG4gICAgICAgIGZvcihsZXQgaSA9IDE7IGkgPCB0aGlzLl9zbmFrZS5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IHBhcnQgPSB0aGlzLl9zbmFrZVtpXTtcbiAgICAgICAgICAgIHRoaXMuX2dyaWRbcGFydC55XVtwYXJ0LnhdID0gVGlsZVN0YXRlLkJvZHk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9ncmlkW3RhaWwueV1bdGFpbC54XSA9IFRpbGVTdGF0ZS5UYWlsO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2dhbWVDeWNsZSgpIHtcbiAgICAgICAgY29uc3QgaGVhZCA9IHRoaXMuX3NuYWtlWzBdO1xuICAgICAgICBsZXQgbmV3SGVhZDogUGFydDtcbiAgICAgICAgdGhpcy5fbW92ZURpciA9IHRoaXMuX25leHRNb3ZlRGlyO1xuICAgICAgICBpZiAodGhpcy5fbW92ZURpciA9PT0gTW92ZURpcmVjdGlvbnMuVVApIHtcbiAgICAgICAgICAgIG5ld0hlYWQgPSB7IHg6IGhlYWQueCwgeTogaGVhZC55IC0gMSB9O1xuXG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5fbW92ZURpciA9PT0gTW92ZURpcmVjdGlvbnMuUklHSFQpIHtcbiAgICAgICAgICAgIG5ld0hlYWQgPSB7IHg6IGhlYWQueCArIDEsIHk6IGhlYWQueSB9O1xuXG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5fbW92ZURpciA9PT0gTW92ZURpcmVjdGlvbnMuRE9XTikge1xuICAgICAgICAgICAgbmV3SGVhZCA9IHsgeDogaGVhZC54LCB5OiBoZWFkLnkgKyAxIH07XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE1vdmluZyBsZWZ0XG4gICAgICAgICAgICBuZXdIZWFkID0geyB4OiBoZWFkLnggLSAxLCB5OiBoZWFkLnkgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLl93aWxsQ3Jhc2gobmV3SGVhZCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9lbmRHYW1lKCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBwb3NpdGlvbiBuZXcgaGVhZFxuICAgICAgICB0aGlzLl9zbmFrZS51bnNoaWZ0KG5ld0hlYWQpO1xuXG4gICAgICAgIGlmICh0aGlzLl93aWxsR3JvdyhuZXdIZWFkKSkge1xuICAgICAgICAgICAgdGhpcy5faW5jcmVhc2VTcGVlZCgpO1xuICAgICAgICAgICAgdGhpcy5fZm9vZEVhdGVuJC5uZXh0KCk7XG4gICAgICAgICAgICB0aGlzLl9mb29kID0gbnVsbDtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gZHJvcCBvbGQgdGFpbFxuICAgICAgICAgICAgdGhpcy5fc25ha2UucG9wKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9idWlsZEVtcHR5R3JpZCgpO1xuICAgICAgICB0aGlzLl9kcmF3U25ha2UoKTtcbiAgICAgICAgdGhpcy5fc3Bhd25Gb29kKCk7XG4gICAgICAgIHRoaXMuX2dyaWRDaGFuZ2VkKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGZpZWxkIGlzIG5vdCBjdXJyZW50bHkgb2NjdXBpZWQgKGlzIGZyZWUgdG8gdGFrZSlcbiAgICAgKiBAcGFyYW0gbmV3SGVhZFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgcHJpdmF0ZSBfd2lsbENyYXNoKG5ld0hlYWQ6IFBhcnQpOiBib29sZWFuIHtcbiAgICAgICAgLy8gR2V0cyBvdXQgb2YgdGhlIGJvYXJkXG4gICAgICAgIGlmIChuZXdIZWFkLnggPCAwIHx8IG5ld0hlYWQueSA8IDAgfHwgbmV3SGVhZC54ID4gdGhpcy5fZ3JpZFNpemUudyB8fCBuZXdIZWFkLnkgPiB0aGlzLl9ncmlkU2l6ZS5oKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IENSQVNIQUJMRV9GSUVMRFM6IEFycmF5PFRpbGVTdGF0ZT4gPSBbXG4gICAgICAgICAgICBUaWxlU3RhdGUuQm9keSxcbiAgICAgICAgICAgIFRpbGVTdGF0ZS5XYWxsXG4gICAgICAgIF07XG4gICAgICAgIGlmIChDUkFTSEFCTEVfRklFTERTLmluY2x1ZGVzKHRoaXMuX2dyaWRbbmV3SGVhZC55XVtuZXdIZWFkLnhdKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiBjcmFzaGluZyB3aXRoIHRhaWwgdGhlbiBjaGVjayBpZiB0YWlsIHdpbGwgbW92ZS4uLlxuICAgICAgICBpZiAodGhpcy5fZ3JpZFtuZXdIZWFkLnldW25ld0hlYWQueF0gPT09IFRpbGVTdGF0ZS5UYWlsICYmIHRoaXMuX3dpbGxHcm93KG5ld0hlYWQpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF93aWxsR3JvdyhuZXdIZWFkOiBQYXJ0KTogYm9vbGVhbiB7XG4gICAgICAgIGlmICh0aGlzLl9mb29kICYmIHRoaXMuX2Zvb2QueSA9PT0gbmV3SGVhZC55ICYmIHRoaXMuX2Zvb2QueCA9PT0gbmV3SGVhZC54KSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfaW5jcmVhc2VTcGVlZCgpIHtcbiAgICAgICAgdGhpcy5faW50ZXJ2YWwkXG4gICAgICAgICAgICAucGlwZSh0YWtlKDEpKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoY3VycmVudCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50ID49IDYwMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9pbnRlcnZhbCQubmV4dChjdXJyZW50IC0gMTAwKTtcblxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudCA+PSA1MDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5faW50ZXJ2YWwkLm5leHQoY3VycmVudCAtIDMwKTtcblxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudCA+PSA0MDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5faW50ZXJ2YWwkLm5leHQoY3VycmVudCAtIDIwKTtcblxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2ludGVydmFsJC5uZXh0KGN1cnJlbnQgLSAxMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICB9XG59XG4iXX0=