@satheshsat/puzzle
Version:
Puzzle game
147 lines • 29.9 kB
JavaScript
import { Component } from '@angular/core';
import { timer } from 'rxjs';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "@angular/forms";
export class ImagePuzzleComponent {
constructor() {
this.imageUrl = 'https://cdn.britannica.com/86/170586-050-AB7FEFAE/Taj-Mahal-Agra-India.jpg';
this.imageSize = 500;
this.gridsize = 2;
this.boxSize = 100 / (this.gridsize - 1);
this.index = 0;
this.totalBoxes = this.gridsize * this.gridsize;
this.Image = [];
this.imageName = this.imageUrl.substr(this.imageUrl.lastIndexOf('/') + 1).split('.')[0];
this.difficulty = '2';
this.steps = 0;
this.ticks = '0:00';
this.timer = timer(0, 1000);
this.gameComplete = false;
this.indexes = [];
this.position = [];
}
ngOnInit() {
this.startGame();
}
isSorted(indexes) {
let i = 0;
for (i = 0; i < indexes.length; i++) {
if (indexes[i] !== i) {
return false;
}
}
return true;
}
randomize(imageParts) {
let i = 0, img = [], ran = 0;
for (i = 0; i < imageParts.length; i++) {
ran = Math.floor(Math.random() * imageParts.length);
while (imageParts[ran] == null) {
ran = Math.floor(Math.random() * imageParts.length);
}
img.push(imageParts[ran]);
this.position.push(imageParts[ran].index);
imageParts[ran] = null;
}
this.printIndexes(this.indexes);
this.printIndexes(this.position);
return img;
}
onDragStart(event) {
event.dataTransfer.setData('data', event.target.id);
}
onDrop(event) {
let origin = event.dataTransfer.getData('data');
let dest = event.target.id;
let originEl = document.getElementById(origin);
let destEl = document.getElementById(dest);
let origincss = originEl.style.cssText;
let destcss = event.target.style.cssText;
destEl.style.cssText = origincss;
originEl.style.cssText = destcss;
originEl.id = dest;
destEl.id = origin;
for (let i = 0; i < this.position.length; i++) {
if (this.position[i].toString() === originEl.id) {
this.position[i] = Number(destEl.id);
}
else if (this.position[i].toString() === destEl.id) {
this.position[i] = Number(originEl.id);
}
}
this.printIndexes(this.position);
this.steps++;
this.gameComplete = this.isSorted(this.position);
if (this.gameComplete) {
if (this.timeVar) {
this.timeVar.unsubscribe();
}
}
}
allowDrop(event) {
event.preventDefault();
event.target.style.opacity = 1;
}
printIndexes(sorts) {
let i = 0, ind = '';
for (i = 0; i < sorts.length; i++) {
ind += sorts[i].toString() + ' , ';
}
console.log(ind);
}
reRandomize() {
this.gameComplete = false;
this.Image = this.randomize(this.Image);
}
startGame() {
this.reset();
this.initializeGame();
this.breakImageParts();
this.reRandomize();
if (this.timeVar) {
this.timeVar.unsubscribe();
}
this.timeVar = this.timer.subscribe((t) => {
this.settime(t);
});
}
settime(t) {
this.ticks = Math.floor(t / 60).toLocaleString('en-US', { minimumIntegerDigits: 2, useGrouping: false }) + ':' +
(t % 60).toLocaleString('en-US', { minimumIntegerDigits: 2, useGrouping: false });
}
breakImageParts() {
for (this.index = 0; this.index < this.totalBoxes; this.index++) {
const x = (this.boxSize * (this.index % this.gridsize)) + '%';
const y = (this.boxSize * Math.floor(this.index / this.gridsize)) + '%';
let img = new ImageBox();
img.x_pos = x;
img.y_pos = y;
img.index = this.index;
this.indexes.push(this.index);
this.Image.push(img);
}
this.boxSize = this.imageSize / this.gridsize;
}
initializeGame() {
this.gridsize = Number(this.difficulty);
console.log(this.gridsize);
this.boxSize = 100 / (this.gridsize - 1);
this.index = 0;
this.totalBoxes = this.gridsize * this.gridsize;
}
reset() {
this.Image = [];
this.indexes = [];
this.position = [];
}
}
ImagePuzzleComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ImagePuzzleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
ImagePuzzleComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: ImagePuzzleComponent, selector: "lib-image-puzzle", ngImport: i0, template: "<div class=\"imagePuzzle\">\n\t<div class=\"unsolvedPuzzle\">\n\t\t<h1 class=\"sectionName\">{{imageName}}</h1>\n\t\t<ul class=\"puzzle\" dropzone=\"true\">\n\t\t\t<li *ngFor=\"let img of Image\" class=\"box\" [draggable]=\"true\" [id]=\"img.index\" (dragstart)=\"onDragStart($event)\"\n\t\t\t\t(drop)=\"onDrop($event)\" (dragover)=\"allowDrop($event)\" [style.width.px]=\"boxSize\" [style.height.px]=\"boxSize\"\n\t\t\t\t[ngStyle]=\"{'background-image':'url(' + imageUrl + ') ','background-repeat':'no-repeat', 'background-position': '' + img.x_pos + ' ' + img.y_pos + '','background-size':''+ (gridsize * 100) +'% '+ (gridsize * 100) +'%'}\">\n\n\t\t\t</li>\n\t\t</ul>\n\t\t<div class=\"successMessage\" *ngIf=\"gameComplete\">\n\t\t\tGame Complete. <br>\n\t\t\tYou completed the game in time = {{ticks}} & {{steps }} steps.\n\t\t</div>\n\n\t</div>\n\t<div class=\"scoreboard\">\n\t\t<h1 class=\"sectionName\">Scoreboard</h1>\n\t\t<h3 class=\"score-detail\">\n\t\t\t<span>Time Spent: {{ ticks }} </span>\n\t\t\t<span> Steps : {{steps}}</span>\n\t\t</h3>\n\t\t<div class=\"finalImage\" [ngStyle]=\"{'background-image':'url(' + imageUrl + ') '}\"></div>\n\t\t<div class=\"image-url\">\n\t\t\t<div class=\"input-group\">\n\t\t\t\t<span class=\"input-group-btn\">\n <div class=\"btn btn-default\" >Image Url!</div>\n </span>\n\t\t\t\t<input type=\"url\" class=\"form-control\" placeholder=\"Image Url...\" [(ngModel)]=\"imageUrl\">\n\t\t\t</div>\n\t\t</div>\n\n\t\t<h3>Difficulty Level</h3>\n\t\t<div class=\"difficulty-levels\">\n\t\t\t<div class=\"input-group\">\n\t\t\t\t<input type=\"radio\" [(ngModel)]=\"difficulty\" name=\"difficulty\" value=\"2\" checked (change)=\"startGame()\">Low\n\t\t\t</div>\n\t\t\t<div class=\"input-group\">\n\t\t\t\t<input type=\"radio\" [(ngModel)]=\"difficulty\" name=\"difficulty\" value=\"3\" (change)=\"startGame()\">Medium\n\t\t\t</div>\n\t\t\t<div class=\"input-group\">\n\t\t\t\t<input type=\"radio\" [(ngModel)]=\"difficulty\" name=\"difficulty\" value=\"4\" (change)=\"startGame()\">High\n\t\t\t</div>\n\t\t</div>\n\t\t<br>\n\t\t<div class=\"score-detail\">\n\t\t\t<button type=\"button\" class=\"btn btn-primary\" (click)=\"startGame()\"> Restart Game</button>\n\t\t\t<button type=\"button\" class=\"btn btn-primary\" (click)=\"reRandomize()\"> Randomize</button>\n\t\t</div>\n\n\t</div>\n</div>", styles: [".imagePuzzle{color:#fff;width:1200px;height:700px;margin:auto;display:flex;justify-content:center;background-color:#789}.unsolvedPuzzle,.scoreboard{width:50%;box-sizing:border-box;padding:0 5%}.sectionName{background-color:#fff;color:#000;text-align:center;width:500px;height:50px}.score-detail,.difficulty-levels{color:#fff;display:flex;justify-content:space-around}li{width:100px;list-style-type:none}.puzzle{width:500px;height:500px;display:flex;justify-content:center;padding:0;flex-wrap:wrap;box-sizing:initial;border:1px solid red}.box{display:inline-block;border:0;padding:0;margin:0}.finalImage{width:250px;height:250px;margin:auto;background-size:100% 100%}.unsolved,.solved{width:50%}.image-url{margin-top:5%}.successMessage{margin:5%;border:1px solid green;border-radius:10px;color:#000;background-color:#90ee90;padding:5%}\n"], directives: [{ type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i2.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ImagePuzzleComponent, decorators: [{
type: Component,
args: [{ selector: 'lib-image-puzzle', template: "<div class=\"imagePuzzle\">\n\t<div class=\"unsolvedPuzzle\">\n\t\t<h1 class=\"sectionName\">{{imageName}}</h1>\n\t\t<ul class=\"puzzle\" dropzone=\"true\">\n\t\t\t<li *ngFor=\"let img of Image\" class=\"box\" [draggable]=\"true\" [id]=\"img.index\" (dragstart)=\"onDragStart($event)\"\n\t\t\t\t(drop)=\"onDrop($event)\" (dragover)=\"allowDrop($event)\" [style.width.px]=\"boxSize\" [style.height.px]=\"boxSize\"\n\t\t\t\t[ngStyle]=\"{'background-image':'url(' + imageUrl + ') ','background-repeat':'no-repeat', 'background-position': '' + img.x_pos + ' ' + img.y_pos + '','background-size':''+ (gridsize * 100) +'% '+ (gridsize * 100) +'%'}\">\n\n\t\t\t</li>\n\t\t</ul>\n\t\t<div class=\"successMessage\" *ngIf=\"gameComplete\">\n\t\t\tGame Complete. <br>\n\t\t\tYou completed the game in time = {{ticks}} & {{steps }} steps.\n\t\t</div>\n\n\t</div>\n\t<div class=\"scoreboard\">\n\t\t<h1 class=\"sectionName\">Scoreboard</h1>\n\t\t<h3 class=\"score-detail\">\n\t\t\t<span>Time Spent: {{ ticks }} </span>\n\t\t\t<span> Steps : {{steps}}</span>\n\t\t</h3>\n\t\t<div class=\"finalImage\" [ngStyle]=\"{'background-image':'url(' + imageUrl + ') '}\"></div>\n\t\t<div class=\"image-url\">\n\t\t\t<div class=\"input-group\">\n\t\t\t\t<span class=\"input-group-btn\">\n <div class=\"btn btn-default\" >Image Url!</div>\n </span>\n\t\t\t\t<input type=\"url\" class=\"form-control\" placeholder=\"Image Url...\" [(ngModel)]=\"imageUrl\">\n\t\t\t</div>\n\t\t</div>\n\n\t\t<h3>Difficulty Level</h3>\n\t\t<div class=\"difficulty-levels\">\n\t\t\t<div class=\"input-group\">\n\t\t\t\t<input type=\"radio\" [(ngModel)]=\"difficulty\" name=\"difficulty\" value=\"2\" checked (change)=\"startGame()\">Low\n\t\t\t</div>\n\t\t\t<div class=\"input-group\">\n\t\t\t\t<input type=\"radio\" [(ngModel)]=\"difficulty\" name=\"difficulty\" value=\"3\" (change)=\"startGame()\">Medium\n\t\t\t</div>\n\t\t\t<div class=\"input-group\">\n\t\t\t\t<input type=\"radio\" [(ngModel)]=\"difficulty\" name=\"difficulty\" value=\"4\" (change)=\"startGame()\">High\n\t\t\t</div>\n\t\t</div>\n\t\t<br>\n\t\t<div class=\"score-detail\">\n\t\t\t<button type=\"button\" class=\"btn btn-primary\" (click)=\"startGame()\"> Restart Game</button>\n\t\t\t<button type=\"button\" class=\"btn btn-primary\" (click)=\"reRandomize()\"> Randomize</button>\n\t\t</div>\n\n\t</div>\n</div>", styles: [".imagePuzzle{color:#fff;width:1200px;height:700px;margin:auto;display:flex;justify-content:center;background-color:#789}.unsolvedPuzzle,.scoreboard{width:50%;box-sizing:border-box;padding:0 5%}.sectionName{background-color:#fff;color:#000;text-align:center;width:500px;height:50px}.score-detail,.difficulty-levels{color:#fff;display:flex;justify-content:space-around}li{width:100px;list-style-type:none}.puzzle{width:500px;height:500px;display:flex;justify-content:center;padding:0;flex-wrap:wrap;box-sizing:initial;border:1px solid red}.box{display:inline-block;border:0;padding:0;margin:0}.finalImage{width:250px;height:250px;margin:auto;background-size:100% 100%}.unsolved,.solved{width:50%}.image-url{margin-top:5%}.successMessage{margin:5%;border:1px solid green;border-radius:10px;color:#000;background-color:#90ee90;padding:5%}\n"] }]
}] });
class ImageBox {
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2UtcHV6emxlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3B1enpsZS9zcmMvbGliL2ltYWdlLXB1enpsZS9pbWFnZS1wdXp6bGUuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvcHV6emxlL3NyYy9saWIvaW1hZ2UtcHV6emxlL2ltYWdlLXB1enpsZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFVLE1BQU0sZUFBZSxDQUFDO0FBQ2xELE9BQU8sRUFBYyxLQUFLLEVBQUUsTUFBTSxNQUFNLENBQUM7Ozs7QUFPekMsTUFBTSxPQUFPLG9CQUFvQjtJQUxqQztRQU9FLGFBQVEsR0FBVyw0RUFBNEUsQ0FBQztRQUNoRyxjQUFTLEdBQVcsR0FBRyxDQUFDO1FBQ3hCLGFBQVEsR0FBVyxDQUFDLENBQUM7UUFDckIsWUFBTyxHQUFXLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDNUMsVUFBSyxHQUFXLENBQUMsQ0FBQztRQUNsQixlQUFVLEdBQVcsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQ25ELFVBQUssR0FBVSxFQUFFLENBQUM7UUFDbEIsY0FBUyxHQUFXLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzRixlQUFVLEdBQVcsR0FBRyxDQUFDO1FBQ3pCLFVBQUssR0FBVyxDQUFDLENBQUM7UUFDbEIsVUFBSyxHQUFXLE1BQU0sQ0FBQztRQUN2QixVQUFLLEdBQVEsS0FBSyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FB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QUssR0FBRyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUNsRCxDQUFDO0lBRUQsS0FBSztRQUNILElBQUksQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ2hCLElBQUksQ0FBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2xCLElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO0lBQ3JCLENBQUM7O2tIQTNKVSxvQkFBb0I7c0dBQXBCLG9CQUFvQix3RENSakMsODBFQW1ETTs0RkQzQ08sb0JBQW9CO2tCQUxoQyxTQUFTOytCQUNFLGtCQUFrQjs7QUFtSzlCLE1BQU0sUUFBUTtDQUliIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE9ic2VydmFibGUsIHRpbWVyIH0gZnJvbSAncnhqcyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2xpYi1pbWFnZS1wdXp6bGUnLFxuICB0ZW1wbGF0ZVVybDogJy4vaW1hZ2UtcHV6emxlLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vaW1hZ2UtcHV6emxlLmNvbXBvbmVudC5jc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBJbWFnZVB1enpsZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgaW1hZ2VVcmw6IHN0cmluZyA9ICdodHRwczovL2Nkbi5icml0YW5uaWNhLmNvbS84Ni8xNzA1ODYtMDUwLUFCN0ZFRkFFL1Rhai1NYWhhbC1BZ3JhLUluZGlhLmpwZyc7XG4gIGltYWdlU2l6ZTogbnVtYmVyID0gNTAwO1xuICBncmlkc2l6ZTogbnVtYmVyID0gMjtcbiAgYm94U2l6ZTogbnVtYmVyID0gMTAwIC8gKHRoaXMuZ3JpZHNpemUgLSAxKTtcbiAgaW5kZXg6IG51bWJlciA9IDA7XG4gIHRvdGFsQm94ZXM6IG51bWJlciA9IHRoaXMuZ3JpZHNpemUgKiB0aGlzLmdyaWRzaXplO1xuICBJbWFnZTogYW55W10gPSBbXTtcbiAgaW1hZ2VOYW1lOiBzdHJpbmcgPSB0aGlzLmltYWdlVXJsLnN1YnN0cih0aGlzLmltYWdlVXJsLmxhc3RJbmRleE9mKCcvJykgKyAxKS5zcGxpdCgnLicpWzBdO1xuICBkaWZmaWN1bHR5OiBzdHJpbmcgPSAnMic7XG4gIHN0ZXBzOiBudW1iZXIgPSAwO1xuICB0aWNrczogc3RyaW5nID0gJzA6MDAnO1xuICB0aW1lcjogYW55ID0gdGltZXIoMCwgMTAwMCk7XG4gIHRpbWVWYXI6IGFueTtcbiAgZ2FtZUNvbXBsZXRlOiBCb29sZWFuID0gZmFsc2U7XG5cbiAgaW5kZXhlczogbnVtYmVyW10gPSBbXTtcbiAgcG9zaXRpb246IG51bWJlcltdID0gW107XG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuc3RhcnRHYW1lKCk7XG4gIH1cblxuICBpc1NvcnRlZChpbmRleGVzOiBhbnkpOiBCb29sZWFuIHtcbiAgICBsZXQgaTogbnVtYmVyID0gMDtcbiAgICBmb3IgKGkgPSAwOyBpIDwgaW5kZXhlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGluZGV4ZXNbaV0gIT09IGkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHJhbmRvbWl6ZShpbWFnZVBhcnRzOiBhbnlbXSk6IGFueVtdIHtcbiAgICBsZXQgaSA9IDAsIGltZzogYW55W10gPSBbXSwgcmFuID0gMDtcbiAgICBmb3IgKGkgPSAwOyBpIDwgaW1hZ2VQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgcmFuID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogaW1hZ2VQYXJ0cy5sZW5ndGgpO1xuICAgICAgd2hpbGUgKGltYWdlUGFydHNbcmFuXSA9PSBudWxsKSB7XG4gICAgICAgIHJhbiA9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIGltYWdlUGFydHMubGVuZ3RoKTtcbiAgICAgIH1cbiAgICAgIGltZy5wdXNoKGltYWdlUGFydHNbcmFuXSk7XG4gICAgICB0aGlzLnBvc2l0aW9uLnB1c2goaW1hZ2VQYXJ0c1tyYW5dLmluZGV4KTtcbiAgICAgIGltYWdlUGFydHNbcmFuXSA9IG51bGw7XG4gICAgfVxuICAgIHRoaXMucHJpbnRJbmRleGVzKHRoaXMuaW5kZXhlcyk7XG4gICAgdGhpcy5wcmludEluZGV4ZXModGhpcy5wb3NpdGlvbik7XG4gICAgcmV0dXJuIGltZztcbiAgfVxuXG4gIG9uRHJhZ1N0YXJ0KGV2ZW50OiBhbnkpOiB2b2lkIHtcbiAgICBldmVudC5kYXRhVHJhbnNmZXIuc2V0RGF0YSgnZGF0YScsIGV2ZW50LnRhcmdldC5pZCk7XG4gIH1cbiAgb25Ecm9wKGV2ZW50OiBhbnkpOiB2b2lkIHtcbiAgICBsZXQgb3JpZ2luID0gZXZlbnQuZGF0YVRyYW5zZmVyLmdldERhdGEoJ2RhdGEnKTtcbiAgICBsZXQgZGVzdCA9IGV2ZW50LnRhcmdldC5pZDtcblxuXG4gICAgbGV0IG9yaWdpbkVsOiBhbnkgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChvcmlnaW4pO1xuICAgIGxldCBkZXN0RWw6IGFueSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGRlc3QpO1xuXG4gICAgbGV0IG9yaWdpbmNzcyA9IG9yaWdpbkVsLnN0eWxlLmNzc1RleHQ7XG4gICAgbGV0IGRlc3Rjc3MgPSBldmVudC50YXJnZXQuc3R5bGUuY3NzVGV4dDtcblxuXG4gICAgZGVzdEVsLnN0eWxlLmNzc1RleHQgPSBvcmlnaW5jc3M7XG4gICAgb3JpZ2luRWwuc3R5bGUuY3NzVGV4dCA9IGRlc3Rjc3M7XG4gICAgb3JpZ2luRWwuaWQgPSBkZXN0O1xuICAgIGRlc3RFbC5pZCA9IG9yaWdpbjtcblxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnBvc2l0aW9uLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAodGhpcy5wb3NpdGlvbltpXS50b1N0cmluZygpID09PSBvcmlnaW5FbC5pZCkge1xuICAgICAgICB0aGlzLnBvc2l0aW9uW2ldID0gTnVtYmVyKGRlc3RFbC5pZCk7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMucG9zaXRpb25baV0udG9TdHJpbmcoKSA9PT0gZGVzdEVsLmlkKSB7XG4gICAgICAgIHRoaXMucG9zaXRpb25baV0gPSBOdW1iZXIob3JpZ2luRWwuaWQpO1xuICAgICAgfVxuXG4gICAgfVxuXG4gICAgdGhpcy5wcmludEluZGV4ZXModGhpcy5wb3NpdGlvbik7XG4gICAgdGhpcy5zdGVwcysrO1xuICAgIHRoaXMuZ2FtZUNvbXBsZXRlID0gdGhpcy5pc1NvcnRlZCh0aGlzLnBvc2l0aW9uKTtcbiAgICBpZiAodGhpcy5nYW1lQ29tcGxldGUpIHtcblxuICAgICAgaWYgKHRoaXMudGltZVZhcikge1xuICAgICAgICB0aGlzLnRpbWVWYXIudW5zdWJzY3JpYmUoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgIFxuICB9XG5cbiAgYWxsb3dEcm9wKGV2ZW50OiBhbnkpOiB2b2lkIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGV2ZW50LnRhcmdldC5zdHlsZS5vcGFjaXR5ID0gMTtcbiAgfVxuXG4gIHByaW50SW5kZXhlcyhzb3J0czogbnVtYmVyW10pOiB2b2lkIHtcbiAgICBsZXQgaTogbnVtYmVyID0gMCwgaW5kOiBzdHJpbmcgPSAnJztcbiAgICBmb3IgKGkgPSAwOyBpIDwgc29ydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGluZCArPSBzb3J0c1tpXS50b1N0cmluZygpICsgJyAsICc7XG4gICAgfVxuICAgIGNvbnNvbGUubG9nKGluZCk7XG4gIH1cblxuICByZVJhbmRvbWl6ZSgpOiB2b2lkIHtcbiAgICB0aGlzLmdhbWVDb21wbGV0ZSA9IGZhbHNlO1xuICAgIHRoaXMuSW1hZ2UgPSB0aGlzLnJhbmRvbWl6ZSh0aGlzLkltYWdlKTtcbiAgfVxuXG4gIHN0YXJ0R2FtZSgpOiB2b2lkIHtcbiAgICB0aGlzLnJlc2V0KCk7XG4gICAgdGhpcy5pbml0aWFsaXplR2FtZSgpO1xuICAgIHRoaXMuYnJlYWtJbWFnZVBhcnRzKCk7XG4gICAgdGhpcy5yZVJhbmRvbWl6ZSgpO1xuXG4gICAgaWYgKHRoaXMudGltZVZhcikge1xuICAgICAgdGhpcy50aW1lVmFyLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuICAgIHRoaXMudGltZVZhciA9IHRoaXMudGltZXIuc3Vic2NyaWJlKCh0OiBhbnkpID0+IHtcbiAgICAgIHRoaXMuc2V0dGltZSh0KTtcbiAgICB9KTtcbiAgfVxuXG4gIHNldHRpbWUodDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy50aWNrcyA9IE1hdGguZmxvb3IodCAvIDYwKS50b0xvY2FsZVN0cmluZygnZW4tVVMnLCB7IG1pbmltdW1JbnRlZ2VyRGlnaXRzOiAyLCB1c2VHcm91cGluZzogZmFsc2UgfSkgKyAnOicgK1xuICAgICAgKHQgJSA2MCkudG9Mb2NhbGVTdHJpbmcoJ2VuLVVTJywgeyBtaW5pbXVtSW50ZWdlckRpZ2l0czogMiwgdXNlR3JvdXBpbmc6IGZhbHNlIH0pO1xuICB9XG4gIGJyZWFrSW1hZ2VQYXJ0cygpOiB2b2lkIHtcbiAgICBmb3IgKHRoaXMuaW5kZXggPSAwOyB0aGlzLmluZGV4IDwgdGhpcy50b3RhbEJveGVzOyB0aGlzLmluZGV4KyspIHtcbiAgICAgIGNvbnN0IHg6IHN0cmluZyA9ICh0aGlzLmJveFNpemUgKiAodGhpcy5pbmRleCAlIHRoaXMuZ3JpZHNpemUpKSArICclJztcbiAgICAgIGNvbnN0IHk6IHN0cmluZyA9ICh0aGlzLmJveFNpemUgKiBNYXRoLmZsb29yKHRoaXMuaW5kZXggLyB0aGlzLmdyaWRzaXplKSkgKyAnJSc7XG4gICAgICBsZXQgaW1nOiBJbWFnZUJveCA9IG5ldyBJbWFnZUJveCgpO1xuICAgICAgaW1nLnhfcG9zID0geDtcbiAgICAgIGltZy55X3BvcyA9IHk7XG4gICAgICBpbWcuaW5kZXggPSB0aGlzLmluZGV4O1xuICAgICAgdGhpcy5pbmRleGVzLnB1c2godGhpcy5pbmRleCk7XG4gICAgICB0aGlzLkltYWdlLnB1c2goaW1nKTtcbiAgICB9XG4gICAgdGhpcy5ib3hTaXplID0gdGhpcy5pbWFnZVNpemUgLyB0aGlzLmdyaWRzaXplO1xuICB9XG5cbiAgaW5pdGlhbGl6ZUdhbWUoKTogdm9pZCB7XG5cbiAgICB0aGlzLmdyaWRzaXplID0gTnVtYmVyKHRoaXMuZGlmZmljdWx0eSk7XG4gICAgY29uc29sZS5sb2codGhpcy5ncmlkc2l6ZSk7XG4gICAgdGhpcy5ib3hTaXplID0gMTAwIC8gKHRoaXMuZ3JpZHNpemUgLSAxKTtcbiAgICB0aGlzLmluZGV4ID0gMDtcbiAgICB0aGlzLnRvdGFsQm94ZXMgPSB0aGlzLmdyaWRzaXplICogdGhpcy5ncmlkc2l6ZTtcbiAgfVxuXG4gIHJlc2V0KCk6IHZvaWQge1xuICAgIHRoaXMuSW1hZ2UgPSBbXTtcbiAgICB0aGlzLmluZGV4ZXMgPSBbXTtcbiAgICB0aGlzLnBvc2l0aW9uID0gW107XG4gIH1cblxufVxuXG5jbGFzcyBJbWFnZUJveCB7XG4gIHhfcG9zOiBzdHJpbmcgfCBhbnk7XG4gIHlfcG9zOiBzdHJpbmcgfCBhbnk7XG4gIGluZGV4OiBudW1iZXIgfCBhbnk7XG59XG4iLCI8ZGl2IGNsYXNzPVwiaW1hZ2VQdXp6bGVcIj5cblx0PGRpdiBjbGFzcz1cInVuc29sdmVkUHV6emxlXCI+XG5cdFx0PGgxIGNsYXNzPVwic2VjdGlvbk5hbWVcIj57e2ltYWdlTmFtZX19PC9oMT5cblx0XHQ8dWwgY2xhc3M9XCJwdXp6bGVcIiBkcm9wem9uZT1cInRydWVcIj5cblx0XHRcdDxsaSAqbmdGb3I9XCJsZXQgaW1nIG9mIEltYWdlXCIgY2xhc3M9XCJib3hcIiBbZHJhZ2dhYmxlXT1cInRydWVcIiBbaWRdPVwiaW1nLmluZGV4XCIgKGRyYWdzdGFydCk9XCJvbkRyYWdTdGFydCgkZXZlbnQpXCJcblx0XHRcdFx0KGRyb3ApPVwib25Ecm9wKCRldmVudClcIiAoZHJhZ292ZXIpPVwiYWxsb3dEcm9wKCRldmVudClcIiBbc3R5bGUud2lkdGgucHhdPVwiYm94U2l6ZVwiIFtzdHlsZS5oZWlnaHQucHhdPVwiYm94U2l6ZVwiXG5cdFx0XHRcdFtuZ1N0eWxlXT1cInsnYmFja2dyb3VuZC1pbWFnZSc6J3VybCgnICsgaW1hZ2VVcmwgKyAnKSAnLCdiYWNrZ3JvdW5kLXJlcGVhdCc6J25vLXJlcGVhdCcsICdiYWNrZ3JvdW5kLXBvc2l0aW9uJzogJycgKyBpbWcueF9wb3MgKyAnICcgICsgaW1nLnlfcG9zICsgJycsJ2JhY2tncm91bmQtc2l6ZSc6JycrIChncmlkc2l6ZSAqIDEwMCkgKyclICcrIChncmlkc2l6ZSAqIDEwMCkgKyclJ31cIj5cblxuXHRcdFx0PC9saT5cblx0XHQ8L3VsPlxuXHRcdDxkaXYgY2xhc3M9XCJzdWNjZXNzTWVzc2FnZVwiICpuZ0lmPVwiZ2FtZUNvbXBsZXRlXCI+XG5cdFx0XHRHYW1lIENvbXBsZXRlLiA8YnI+XG5cdFx0XHRZb3UgY29tcGxldGVkIHRoZSBnYW1lIGluIHRpbWUgPSB7e3RpY2tzfX0gJiB7e3N0ZXBzIH19IHN0ZXBzLlxuXHRcdDwvZGl2PlxuXG5cdDwvZGl2PlxuXHQ8ZGl2IGNsYXNzPVwic2NvcmVib2FyZFwiPlxuXHRcdDxoMSBjbGFzcz1cInNlY3Rpb25OYW1lXCI+U2NvcmVib2FyZDwvaDE+XG5cdFx0PGgzIGNsYXNzPVwic2NvcmUtZGV0YWlsXCI+XG5cdFx0XHQ8c3Bhbj5UaW1lIFNwZW50OiB7eyB0aWNrcyB9fSAgICAgICAgPC9zcGFuPlxuXHRcdFx0PHNwYW4+ICBTdGVwcyA6IHt7c3RlcHN9fTwvc3Bhbj5cblx0XHQ8L2gzPlxuXHRcdDxkaXYgY2xhc3M9XCJmaW5hbEltYWdlXCIgW25nU3R5bGVdPVwieydiYWNrZ3JvdW5kLWltYWdlJzondXJsKCcgKyBpbWFnZVVybCArICcpICd9XCI+PC9kaXY+XG5cdFx0PGRpdiBjbGFzcz1cImltYWdlLXVybFwiPlxuXHRcdFx0PGRpdiBjbGFzcz1cImlucHV0LWdyb3VwXCI+XG5cdFx0XHRcdDxzcGFuIGNsYXNzPVwiaW5wdXQtZ3JvdXAtYnRuXCI+XG4gICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImJ0biBidG4tZGVmYXVsdFwiID5JbWFnZSBVcmwhPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9zcGFuPlxuXHRcdFx0XHQ8aW5wdXQgdHlwZT1cInVybFwiIGNsYXNzPVwiZm9ybS1jb250cm9sXCIgcGxhY2Vob2xkZXI9XCJJbWFnZSBVcmwuLi5cIiBbKG5nTW9kZWwpXT1cImltYWdlVXJsXCI+XG5cdFx0XHQ8L2Rpdj5cblx0XHQ8L2Rpdj5cblxuXHRcdDxoMz5EaWZmaWN1bHR5IExldmVsPC9oMz5cblx0XHQ8ZGl2IGNsYXNzPVwiZGlmZmljdWx0eS1sZXZlbHNcIj5cblx0XHRcdDxkaXYgY2xhc3M9XCJpbnB1dC1ncm91cFwiPlxuXHRcdFx0XHQ8aW5wdXQgdHlwZT1cInJhZGlvXCIgWyhuZ01vZGVsKV09XCJkaWZmaWN1bHR5XCIgbmFtZT1cImRpZmZpY3VsdHlcIiB2YWx1ZT1cIjJcIiBjaGVja2VkIChjaGFuZ2UpPVwic3RhcnRHYW1lKClcIj5Mb3dcblx0XHRcdDwvZGl2PlxuXHRcdFx0PGRpdiBjbGFzcz1cImlucHV0LWdyb3VwXCI+XG5cdFx0XHRcdDxpbnB1dCB0eXBlPVwicmFkaW9cIiBbKG5nTW9kZWwpXT1cImRpZmZpY3VsdHlcIiBuYW1lPVwiZGlmZmljdWx0eVwiIHZhbHVlPVwiM1wiIChjaGFuZ2UpPVwic3RhcnRHYW1lKClcIj5NZWRpdW1cblx0XHRcdDwvZGl2PlxuXHRcdFx0PGRpdiBjbGFzcz1cImlucHV0LWdyb3VwXCI+XG5cdFx0XHRcdDxpbnB1dCB0eXBlPVwicmFkaW9cIiBbKG5nTW9kZWwpXT1cImRpZmZpY3VsdHlcIiBuYW1lPVwiZGlmZmljdWx0eVwiIHZhbHVlPVwiNFwiIChjaGFuZ2UpPVwic3RhcnRHYW1lKClcIj5IaWdoXG5cdFx0XHQ8L2Rpdj5cblx0XHQ8L2Rpdj5cblx0XHQ8YnI+XG5cdFx0PGRpdiBjbGFzcz1cInNjb3JlLWRldGFpbFwiPlxuXHRcdFx0PGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLXByaW1hcnlcIiAoY2xpY2spPVwic3RhcnRHYW1lKClcIj4gUmVzdGFydCBHYW1lPC9idXR0b24+XG5cdFx0XHQ8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tcHJpbWFyeVwiIChjbGljayk9XCJyZVJhbmRvbWl6ZSgpXCI+IFJhbmRvbWl6ZTwvYnV0dG9uPlxuXHRcdDwvZGl2PlxuXG5cdDwvZGl2PlxuPC9kaXY+Il19