ng-jalali-date-time
Version:
Jalali date / month / range picker for Angular with Material Design support
190 lines • 45 kB
JavaScript
import { Component, Output, EventEmitter } from '@angular/core';
import { FormControl } from '@angular/forms';
import { trigger, state, style, transition, animate } from '@angular/animations';
import { JalaliLocale } from '../../shared/jalali.locale';
import { NgJalaliDateTimeService } from '../../ng-jalali-date-time.service';
export class NgJalaliRangeComponent {
constructor(service) {
this.service = service;
this.show = false;
this.random = Date.now().toString();
this.today = '';
this.reset = false;
this.jalaliLocale = new JalaliLocale();
this.week = this.jalaliLocale.dayNames;
this.changed = new EventEmitter();
}
ngOnInit() {
this.custom = { from: this.value.range ? this.value.from : '', to: this.value.range ? this.value.to : '' };
this.setCustomTitle();
this.fMonth = this.value.range ? this.value.from.substr(0, 7) : this.service.jalali.now({ format: 'Y-M' });
this.fCalendar = this.service.getCalendar(this.fMonth);
this.tMonth = this.value.range ? this.value.to.substr(0, 7) : this.service.jalali.now({ format: 'Y-M' });
this.tCalendar = this.service.getCalendar(this.tMonth);
this.today = this.service.jalali.now({ format: 'Y-M-D' });
const validators = [];
if (this.config.required)
validators.push(this.validate.bind(this));
this.form.addControl(this.name, new FormControl(this.value));
this.form.addControl(this.name + '-title', new FormControl('', validators));
this.setTitle();
}
validate() {
return this.value.range ? null : { required: true };
}
showCalendar(show) {
const input = document.querySelector('#input' + this.random);
input.blur();
if (this.reset) {
this.reset = false;
show = false;
}
this.show = show;
if (this.show) {
this.setCustomTitle();
this.form.get(this.name + '-title').markAsUntouched();
if (this.value.range) {
this.fMonth = this.value.from.substr(0, 7);
this.fCalendar = this.service.getCalendar(this.fMonth);
this.tMonth = this.value.to.substr(0, 7);
this.tCalendar = this.service.getCalendar(this.tMonth);
}
else {
this.fMonth = this.service.jalali.now({ format: 'Y-M' });
this.fCalendar = this.service.getCalendar(this.fMonth);
this.tMonth = this.service.jalali.now({ format: 'Y-M' });
this.tCalendar = this.service.getCalendar(this.tMonth);
this.setCustomDate('', '');
}
}
else
this.form.get(this.name + '-title').markAsTouched();
}
changeMonth(type, change) {
let Y = '';
let M = '';
switch (type) {
case 'from':
[Y, M] = this.fMonth.split('-');
break;
case 'to':
[Y, M] = this.tMonth.split('-');
break;
}
let year = Number(Y);
let month = Number(M) + change;
while (month > 12) {
month -= 12;
year++;
}
while (month < 1) {
month += 12;
year--;
}
switch (type) {
case 'from':
this.fMonth = year.toString() + '-' + (month < 10 ? '0' : '') + month.toString();
this.fCalendar = this.service.getCalendar(this.fMonth);
break;
case 'to':
this.tMonth = year.toString() + '-' + (month < 10 ? '0' : '') + month.toString();
this.tCalendar = this.service.getCalendar(this.tMonth);
break;
}
}
setTitle() {
this.form.get(this.name).setValue(this.value);
const title = this.service.getRangeTitle(this.value);
this.form.get(this.name + '-title').setValue(title);
}
setCustomTitle() {
this.fTitle = this.custom.from
? this.service.jalali.toTitle(this.service.jalaliToGregorian(this.custom.from))
: this.jalaliLocale.notSpecified;
this.tTitle = this.custom.to
? this.service.jalali.toTitle(this.service.jalaliToGregorian(this.custom.to))
: this.jalaliLocale.notSpecified;
}
setCustomDate(from, to) {
if (from && to && from >= to)
return;
this.custom.from = from;
this.custom.to = to;
this.setCustomTitle();
}
setRange(type) {
const format = { format: 'Y-M-D' };
let from = '';
let to = '';
let date = null;
switch (type) {
case 'current-week':
date = this.service.jalaliToGregorian(this.today);
while (date.getDay() !== 6) {
date = new Date(date.getTime() - 24 * 3600 * 1000);
}
from = this.service.jalali.toString(date, format);
to = this.service.jalali.toString(new Date(date.getTime() + 6 * 24 * 3600 * 1000), format);
break;
case 'current-month':
date = this.service.jalaliToGregorian(this.today.substr(0, 8) + '01');
const days = this.service.getDayInMonth(this.today.substr(0, 7));
from = this.service.jalali.toString(date, format);
to = this.service.jalali.toString(new Date(date.getTime() + (days - 1) * 24 * 3600 * 1000), format);
break;
case 'last-7days':
date = this.service.jalaliToGregorian(this.today);
from = this.service.jalali.toString(new Date(date.getTime() - 6 * 24 * 3600 * 1000), format);
to = this.service.jalali.toString(date, format);
break;
case 'last-30days':
date = this.service.jalaliToGregorian(this.today);
from = this.service.jalali.toString(new Date(date.getTime() - 29 * 24 * 3600 * 1000), format);
to = this.service.jalali.toString(date, format);
break;
case 'next-7days':
date = this.service.jalaliToGregorian(this.today);
from = this.service.jalali.toString(date, format);
to = this.service.jalali.toString(new Date(date.getTime() + 6 * 24 * 3600 * 1000), format);
break;
case 'next-30days':
date = this.service.jalaliToGregorian(this.today);
from = this.service.jalali.toString(date, format);
to = this.service.jalali.toString(new Date(date.getTime() + 29 * 24 * 3600 * 1000), format);
break;
case 'custom':
from = this.custom.from;
to = this.custom.to;
break;
case 'reset':
default:
break;
}
this.custom = { from, to };
this.value = this.service.getRangeValue(from, to);
this.setTitle();
this.showCalendar(false);
this.changed.emit(this.value.range ? this.value : null);
this.form.get(this.name + '-title').updateValueAndValidity();
}
}
NgJalaliRangeComponent.decorators = [
{ type: Component, args: [{
template: "<div class=\"ng-jalali-back\" *ngIf=\"show\" (click)=\"showCalendar(false)\"></div>\n\n<div [formGroup]=\"form\" [ngStyle]=\"{ display: 'none' }\">\n <input type=\"text\" [formControlName]=\"name\" />\n</div>\n\n<content class=\"ng-jalali\" dir=\"rtl\">\n <mat-form-field [ngStyle]=\"css.field\" class=\"ng-jalali\" [formGroup]=\"form\" [appearance]=\"appearance\">\n <mat-label [ngStyle]=\"{ fontFamily: css.font }\">{{ label }}</mat-label>\n <input\n matInput\n id=\"input{{ random }}\"\n type=\"text\"\n [formControlName]=\"name + '-title'\"\n (focus)=\"showCalendar(true)\"\n [ngStyle]=\"css.input\"\n class=\"ng-jalali\"\n />\n <span *ngIf=\"config.reset && value.range !== ''\" matSuffix (click)=\"setRange('reset'); reset = true\">\n <button mat-button type=\"button\" [ngStyle]=\"css.reset\" class=\"ng-jalali-reset\">x</button>\n </span>\n <mat-error [ngStyle]=\"{ fontFamily: css.font }\" *ngIf=\"form.get(name + '-title').hasError('required')\">\n {{ config.error }}\n </mat-error>\n </mat-form-field>\n\n <div class=\"ng-jalali-calendar\" [ngStyle]=\"css.box\" [@calendar] *ngIf=\"show\">\n <div class=\"ng-jalali-range-tools\">\n <button\n mat-button\n type=\"button\"\n [ngStyle]=\"custom.from === '' || custom.to === '' ? css.range.custom : css.range.confirm\"\n [disabled]=\"custom.from === '' || custom.to === ''\"\n (click)=\"setRange('custom')\"\n class=\"ng-jalali-range-custom\"\n >\n {{\n custom.from === '' || custom.to === '' ? jalaliLocale.rangeCustom : jalaliLocale.rangeCustomConfirm\n }}\n </button>\n <button mat-button type=\"button\" [ngStyle]=\"css.range.tool\" (click)=\"setRange('current-week')\">\n {{ jalaliLocale.rangeCurrentWeek }}\n </button>\n <button mat-button type=\"button\" [ngStyle]=\"css.range.tool\" (click)=\"setRange('current-month')\">\n {{ jalaliLocale.rangeCurrentMonth }}\n </button>\n <button mat-button type=\"button\" [ngStyle]=\"css.range.tool\" (click)=\"setRange('last-7days')\">\n {{ jalaliLocale.rangeLast7Days }}\n </button>\n <button mat-button type=\"button\" [ngStyle]=\"css.range.tool\" (click)=\"setRange('last-30days')\">\n {{ jalaliLocale.rangeLast30Days }}\n </button>\n <button mat-button type=\"button\" [ngStyle]=\"css.range.tool\" (click)=\"setRange('next-7days')\">\n {{ jalaliLocale.rangeNext7Days }}\n </button>\n <button mat-button type=\"button\" [ngStyle]=\"css.range.tool\" (click)=\"setRange('next-30days')\">\n {{ jalaliLocale.rangeNext30Days }}\n </button>\n </div>\n <div class=\"ng-jalali-range-custom\">\n <div class=\"ng-jalali-range-from\">\n <div class=\"ng-jalali-header\">\n <div>\n <button\n mat-icon-button\n type=\"button\"\n [ngStyle]=\"css.arrow\"\n (click)=\"changeMonth('from', -12)\"\n [disabled]=\"fMonth.substr(0, 4) === '1000'\"\n >\n <<\n </button>\n </div>\n <div>\n <button\n mat-icon-button\n type=\"button\"\n [ngStyle]=\"css.arrow\"\n (click)=\"changeMonth('from', -1)\"\n [disabled]=\"fMonth === '1000-01'\"\n >\n <\n </button>\n </div>\n <div class=\"ng-jalali-title\" [ngStyle]=\"css.header\">{{ fCalendar.title }}</div>\n <div>\n <button mat-icon-button type=\"button\" [ngStyle]=\"css.arrow\" (click)=\"changeMonth('from', 1)\">\n >\n </button>\n </div>\n <div>\n <button mat-icon-button type=\"button\" [ngStyle]=\"css.arrow\" (click)=\"changeMonth('from', 12)\">\n >>\n </button>\n </div>\n </div>\n <div class=\"ng-jalali-range-header\">\n <div [ngStyle]=\"css.range.name\" *ngFor=\"let day of week\">{{ day }}</div>\n </div>\n <section>\n <div *ngFor=\"let week of fCalendar.weeks\" class=\"ng-jalali-range-week\">\n <div *ngFor=\"let day of week.days\" class=\"ng-jalali-range-day\">\n <button\n mat-icon-button\n type=\"button\"\n [disabled]=\"\n day.month !== fMonth ||\n (config.min && day.date < config.min) ||\n (config.max && day.date > config.max) ||\n (custom.to !== '' && day.date >= custom.to)\n \"\n [ngClass]=\"{\n 'ng-jalali-selected': day.date === custom.from,\n 'ng-jalali-current': day.date === today\n }\"\n [ngStyle]=\"\n day.date === today\n ? css.current\n : day.date === custom.from\n ? css.selected\n : css.item\n \"\n (click)=\"setCustomDate(day.date, custom.to)\"\n >\n {{ day.day }}\n </button>\n </div>\n </div>\n </section>\n <div class=\"ng-jalali-range-custom-title\" [ngStyle]=\"css.range.date\">{{ fTitle }}</div>\n </div>\n <div class=\"ng-jalali-range-to\">\n <div class=\"ng-jalali-header\">\n <div>\n <button\n mat-icon-button\n type=\"button\"\n [ngStyle]=\"css.arrow\"\n (click)=\"changeMonth('to', -12)\"\n [disabled]=\"tMonth.substr(0, 4) === '1000'\"\n >\n <<\n </button>\n </div>\n <div>\n <button\n mat-icon-button\n type=\"button\"\n [ngStyle]=\"css.arrow\"\n (click)=\"changeMonth('to', -1)\"\n [disabled]=\"tMonth === '1000-01'\"\n >\n <\n </button>\n </div>\n <div class=\"ng-jalali-title\" [ngStyle]=\"css.header\">{{ tCalendar.title }}</div>\n <div>\n <button mat-icon-button type=\"button\" [ngStyle]=\"css.arrow\" (click)=\"changeMonth('to', 1)\">\n >\n </button>\n </div>\n <div>\n <button mat-icon-button type=\"button\" [ngStyle]=\"css.arrow\" (click)=\"changeMonth('to', 12)\">\n >>\n </button>\n </div>\n </div>\n <div class=\"ng-jalali-range-header\">\n <div [ngStyle]=\"css.range.name\" *ngFor=\"let day of week\">{{ day }}</div>\n </div>\n <section>\n <div *ngFor=\"let week of tCalendar.weeks\" class=\"ng-jalali-range-week\">\n <div *ngFor=\"let day of week.days\" class=\"ng-jalali-range-day\">\n <button\n mat-icon-button\n type=\"button\"\n [disabled]=\"\n day.month !== tMonth ||\n (config.min && day.date < config.min) ||\n (config.max && day.date > config.max) ||\n (custom.from !== '' && day.date <= custom.from)\n \"\n [ngClass]=\"{\n 'ng-jalali-selected': day.date === custom.to,\n 'ng-jalali-current': day.date === today\n }\"\n [ngStyle]=\"\n day.date === today ? css.current : day.date === custom.to ? css.selected : css.item\n \"\n (click)=\"setCustomDate(custom.from, day.date)\"\n >\n {{ day.day }}\n </button>\n </div>\n </div>\n </section>\n <div class=\"ng-jalali-range-custom-title\" [ngStyle]=\"css.range.date\">{{ tTitle }}</div>\n </div>\n </div>\n </div>\n</content>\n",
animations: [
trigger('calendar', [
state('init', style({ opacity: 1, transform: 'translateY(0) scaleY(1)' })),
transition('void => *', [style({ opacity: 0, transform: 'translateY(-45%) scaleY(0)' }), animate(100)]),
transition('* => void', animate(100, style({ opacity: 0, transform: 'translateY(-45%) scaleY(0)' })))
])
],
styles: ["div.ng-jalali-range-tools{display:flex}div.ng-jalali-range-tools button{background-color:#fafafa;border-bottom:1px solid #ccc;border-radius:0;border-right:1px solid #ccc;flex:1;min-width:auto;padding:.5rem 0;text-align:center;white-space:normal}div.ng-jalali-range-tools button.ng-jalali-range-custom{background-color:#fff;border-width:0}div.ng-jalali-range-custom{display:flex;flex-direction:row}div.ng-jalali-range-from{flex:1;margin:0 0 0 .5rem}div.ng-jalali-range-to{flex:1;margin:0 .5rem 0 0}@media only screen and (max-width:800px){div.ng-jalali-range-custom{flex-direction:column}div.ng-jalali-range-from{flex:1;margin:0 0 .5rem}div.ng-jalali-range-to{flex:1;margin:.5rem 0 0}}div.ng-jalali-range-from,div.ng-jalali-range-to{display:flex;flex-direction:column}div.ng-jalali-range-from section,div.ng-jalali-range-to section{flex:1}div.ng-jalali-range-header{align-items:center;display:flex}div.ng-jalali-range-header div{background-color:#ddd;flex:1;padding:1rem .2rem;text-align:center}div.ng-jalali-range-week{display:flex}div.ng-jalali-range-day{flex:1;padding:.2rem;text-align:center}div.ng-jalali-range-custom-title{border-top:1px solid #ccc;font-size:14px;padding:1rem;text-align:center}@media only screen and (max-width:800px){div.ng-jalali-range-custom-title{border-bottom:1px solid #ccc;border-top-width:0}}", "div.ng-jalali-back{background-color:transparent;bottom:0;left:0;position:fixed;right:0;top:0;z-index:999}content.ng-jalali{display:block;position:relative}mat-form-field.ng-jalali{direction:rtl;margin:0;text-align:right;width:100%}input.ng-jalali{cursor:default;text-align:right}button.ng-jalali-reset{color:#555;line-height:30px;min-width:auto;padding:0 .5rem}div.ng-jalali-calendar{background-color:#fff;box-shadow:0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12);direction:rtl;position:absolute;right:0;top:45px;z-index:1000}div.ng-jalali-header{align-items:center;display:flex}div.ng-jalali-header div{flex:1;padding:.5rem .2rem;text-align:center}div.ng-jalali-header div.ng-jalali-title{flex:3}button.ng-jalali-selected{background-color:#eee;border:1px solid #999}button.ng-jalali-current{color:#009}"]
},] }
];
NgJalaliRangeComponent.ctorParameters = () => [
{ type: NgJalaliDateTimeService }
];
NgJalaliRangeComponent.propDecorators = {
changed: [{ type: Output }]
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctamFsYWxpLXJhbmdlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25nLWphbGFsaS1kYXRlLXRpbWUvc3JjL2xpYi9jb21wb25lbnQvbmctamFsYWxpLXJhbmdlL25nLWphbGFsaS1yYW5nZS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBVSxNQUFNLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3hFLE9BQU8sRUFBYSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4RCxPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRWpGLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUcxRCxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQWM1RSxNQUFNLE9BQU8sc0JBQXNCO0lBNkIvQixZQUE2QixPQUFnQztRQUFoQyxZQUFPLEdBQVAsT0FBTyxDQUF5QjtRQVZ0RCxTQUFJLEdBQVksS0FBSyxDQUFDO1FBQ3RCLFdBQU0sR0FBVyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDdkMsVUFBSyxHQUFXLEVBQUUsQ0FBQztRQUNuQixVQUFLLEdBQVksS0FBSyxDQUFDO1FBRXZCLGlCQUFZLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUNsQyxTQUFJLEdBQWEsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUM7UUFFekMsWUFBTyxHQUFHLElBQUksWUFBWSxFQUErQixDQUFDO0lBRUosQ0FBQztJQUVqRSxRQUFRO1FBQ0osSUFBSSxDQUFDLE1BQU0sR0FBRyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUMzRyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFFdEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDM0csSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFdkQsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDekcsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFdkQsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUUxRCxN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LEVBQUUsS0FBSyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUUseUJBQXlCLEVBQUUsQ0FBQyxDQUFDO3dCQUMxRSxVQUFVLENBQUMsV0FBVyxFQUFFLENBQUMsS0FBSyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUUsNEJBQTRCLEVBQUUsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO3dCQUN2RyxVQUFVLENBQUMsV0FBVyxFQUFFLE9BQU8sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUUsNEJBQTRCLEVBQUUsQ0FBQyxDQUFDLENBQUM7cUJBQ3hHLENBQUM7aUJBQ0w7O2FBQ0o7OztZQWJRLHVCQUF1Qjs7O3NCQXlDM0IsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUdyb3VwLCBGb3JtQ29udHJvbCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IHRyaWdnZXIsIHN0YXRlLCBzdHlsZSwgdHJhbnNpdGlvbiwgYW5pbWF0ZSB9IGZyb20gJ0Bhbmd1bGFyL2FuaW1hdGlvbnMnO1xuXG5pbXBvcnQgeyBKYWxhbGlMb2NhbGUgfSBmcm9tICcuLi8uLi9zaGFyZWQvamFsYWxpLmxvY2FsZSc7XG5pbXBvcnQgeyBOZ0phbGFsaVJhbmdlVmFsdWVJbnRlcmZhY2UgfSBmcm9tICcuL25nLWphbGFsaS1yYW5nZS5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgSmFsYWxpQ2FsZW5kYXJJbnRlcmZhY2UgfSBmcm9tICcuLi8uLi9zaGFyZWQvamFsYWxpLmludGVyZmFjZSc7XG5pbXBvcnQgeyBOZ0phbGFsaURhdGVUaW1lU2VydmljZSB9IGZyb20gJy4uLy4uL25nLWphbGFsaS1kYXRlLXRpbWUuc2VydmljZSc7XG5pbXBvcnQgeyBOZ0phbGFsaURhdGVUaW1lQ29uZmlnSW50ZXJmYWNlLCBOZ0phbGFsaURhdGVUaW1lQ3NzSW50ZXJmYWNlIH0gZnJvbSAnLi4vLi4vbmctamFsYWxpLWRhdGUtdGltZS5pbnRlcmZhY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgICB0ZW1wbGF0ZVVybDogJy4vbmctamFsYWxpLXJhbmdlLmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi9uZy1qYWxhbGktcmFuZ2UuY29tcG9uZW50LmNzcycsICcuLi8uLi9zaGFyZWQvbmctamFsYWxpLnN0eWxlLmNzcyddLFxuICAgIGFuaW1hdGlvbnM6IFtcbiAgICAgICAgdHJpZ2dlcignY2FsZW5kYXInLCBbXG4gICAgICAgICAgICBzdGF0ZSgnaW5pdCcsIHN0eWxlKHsgb3BhY2l0eTogMSwgdHJhbnNmb3JtOiAndHJhbnNsYXRlWSgwKSBzY2FsZVkoMSknIH0pKSxcbiAgICAgICAgICAgIHRyYW5zaXRpb24oJ3ZvaWQgPT4gKicsIFtzdHlsZSh7IG9wYWNpdHk6IDAsIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZVkoLTQ1JSkgc2NhbGVZKDApJyB9KSwgYW5pbWF0ZSgxMDApXSksXG4gICAgICAgICAgICB0cmFuc2l0aW9uKCcqID0+IHZvaWQnLCBhbmltYXRlKDEwMCwgc3R5bGUoeyBvcGFjaXR5OiAwLCB0cmFuc2Zvcm06ICd0cmFuc2xhdGVZKC00NSUpIHNjYWxlWSgwKScgfSkpKVxuICAgICAgICBdKVxuICAgIF1cbn0pXG5leHBvcnQgY2xhc3MgTmdKYWxhbGlSYW5nZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gICAgcHVibGljIGZvcm06IEZvcm1Hcm91cDtcbiAgICBwdWJsaWMgbmFtZTogc3RyaW5nO1xuICAgIHB1YmxpYyBhcHBlYXJhbmNlOiBzdHJpbmc7XG4gICAgcHVibGljIGNvbmZpZzogTmdKYWxhbGlEYXRlVGltZUNvbmZpZ0ludGVyZmFjZTtcbiAgICBwdWJsaWMgY3NzOiBOZ0phbGFsaURhdGVUaW1lQ3NzSW50ZXJmYWNlO1xuXG4gICAgcHVibGljIHZhbHVlOiBOZ0phbGFsaVJhbmdlVmFsdWVJbnRlcmZhY2U7XG4gICAgcHVibGljIGxhYmVsOiBzdHJpbmc7XG5cbiAgICBwdWJsaWMgY3VzdG9tOiB7IGZyb206IHN0cmluZzsgdG86IHN0cmluZyB9O1xuICAgIHB1YmxpYyBmTW9udGg6IHN0cmluZztcbiAgICBwdWJsaWMgZkNhbGVuZGFyOiBKYWxhbGlDYWxlbmRhckludGVyZmFjZTtcbiAgICBwdWJsaWMgZlRpdGxlOiBzdHJpbmc7XG5cbiAgICBwdWJsaWMgdE1vbnRoOiBzdHJpbmc7XG4gICAgcHVibGljIHRDYWxlbmRhcjogSmFsYWxpQ2FsZW5kYXJJbnRlcmZhY2U7XG4gICAgcHVibGljIHRUaXRsZTogc3RyaW5nO1xuXG4gICAgcHVibGljIHNob3c6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBwdWJsaWMgcmFuZG9tOiBzdHJpbmcgPSBEYXRlLm5vdygpLnRvU3RyaW5nKCk7XG4gICAgcHVibGljIHRvZGF5OiBzdHJpbmcgPSAnJztcbiAgICBwdWJsaWMgcmVzZXQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIHB1YmxpYyBqYWxhbGlMb2NhbGUgPSBuZXcgSmFsYWxpTG9jYWxlKCk7XG4gICAgcHVibGljIHdlZWs6IHN0cmluZ1tdID0gdGhpcy5qYWxhbGlMb2NhbGUuZGF5TmFtZXM7XG5cbiAgICBAT3V0cHV0KCkgY2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8TmdKYWxhbGlSYW5nZVZhbHVlSW50ZXJmYWNlPigpO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBzZXJ2aWNlOiBOZ0phbGFsaURhdGVUaW1lU2VydmljZSkge31cblxuICAgIG5nT25Jbml0KCkge1xuICAgICAgICB0aGlzLmN1c3RvbSA9IHsgZnJvbTogdGhpcy52YWx1ZS5yYW5nZSA/IHRoaXMudmFsdWUuZnJvbSA6ICcnLCB0bzogdGhpcy52YWx1ZS5yYW5nZSA/IHRoaXMudmFsdWUudG8gOiAnJyB9O1xuICAgICAgICB0aGlzLnNldEN1c3RvbVRpdGxlKCk7XG5cbiAgICAgICAgdGhpcy5mTW9udGggPSB0aGlzLnZhbHVlLnJhbmdlID8gdGhpcy52YWx1ZS5mcm9tLnN1YnN0cigwLCA3KSA6IHRoaXMuc2VydmljZS5qYWxhbGkubm93KHsgZm9ybWF0OiAnWS1NJyB9KTtcbiAgICAgICAgdGhpcy5mQ2FsZW5kYXIgPSB0aGlzLnNlcnZpY2UuZ2V0Q2FsZW5kYXIodGhpcy5mTW9udGgpO1xuXG4gICAgICAgIHRoaXMudE1vbnRoID0gdGhpcy52YWx1ZS5yYW5nZSA/IHRoaXMudmFsdWUudG8uc3Vic3RyKDAsIDcpIDogdGhpcy5zZXJ2aWNlLmphbGFsaS5ub3coeyBmb3JtYXQ6ICdZLU0nIH0pO1xuICAgICAgICB0aGlzLnRDYWxlbmRhciA9IHRoaXMuc2VydmljZS5nZXRDYWxlbmRhcih0aGlzLnRNb250aCk7XG5cbiAgICAgICAgdGhpcy50b2RheSA9IHRoaXMuc2VydmljZS5qYWxhbGkubm93KHsgZm9ybWF0OiAnWS1NLUQnIH0pO1xuXG4gICAgICAgIGNvbnN0IHZhbGlkYXRvcnM6IGFueVtdID0gW107XG4gICAgICAgIGlmICh0aGlzLmNvbmZpZy5yZXF1aXJlZCkgdmFsaWRhdG9ycy5wdXNoKHRoaXMudmFsaWRhdGUuYmluZCh0aGlzKSk7XG5cbiAgICAgICAgdGhpcy5mb3JtLmFkZENvbnRyb2wodGhpcy5uYW1lLCBuZXcgRm9ybUNvbnRyb2wodGhpcy52YWx1ZSkpO1xuICAgICAgICB0aGlzLmZvcm0uYWRkQ29udHJvbCh0aGlzLm5hbWUgKyAnLXRpdGxlJywgbmV3IEZvcm1Db250cm9sKCcnLCB2YWxpZGF0b3JzKSk7XG4gICAgICAgIHRoaXMuc2V0VGl0bGUoKTtcbiAgICB9XG5cbiAgICB2YWxpZGF0ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWUucmFuZ2UgPyBudWxsIDogeyByZXF1aXJlZDogdHJ1ZSB9O1xuICAgIH1cblxuICAgIHNob3dDYWxlbmRhcihzaG93OiBib29sZWFuKSB7XG4gICAgICAgIGNvbnN0IGlucHV0OiBIVE1MSW5wdXRFbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2lucHV0JyArIHRoaXMucmFuZG9tKTtcbiAgICAgICAgaW5wdXQuYmx1cigpO1xuXG4gICAgICAgIGlmICh0aGlzLnJlc2V0KSB7XG4gICAgICAgICAgICB0aGlzLnJlc2V0ID0gZmFsc2U7XG4gICAgICAgICAgICBzaG93ID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnNob3cgPSBzaG93O1xuICAgICAgICBpZiAodGhpcy5zaG93KSB7XG4gICAgICAgICAgICB0aGlzLnNldEN1c3RvbVRpdGxlKCk7XG4gICAgICAgICAgICB0aGlzLmZvcm0uZ2V0KHRoaXMubmFtZSArICctdGl0bGUnKS5tYXJrQXNVbnRvdWNoZWQoKTtcbiAgICAgICAgICAgIGlmICh0aGlzLnZhbHVlLnJhbmdlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5mTW9udGggPSB0aGlzLnZhbHVlLmZyb20uc3Vic3RyKDAsIDcpO1xuICAgICAgICAgICAgICAgIHRoaXMuZkNhbGVuZGFyID0gdGhpcy5zZXJ2aWNlLmdldENhbGVuZGFyKHRoaXMuZk1vbnRoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnRNb250aCA9IHRoaXMudmFsdWUudG8uc3Vic3RyKDAsIDcpO1xuICAgICAgICAgICAgICAgIHRoaXMudENhbGVuZGFyID0gdGhpcy5zZXJ2aWNlLmdldENhbGVuZGFyKHRoaXMudE1vbnRoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5mTW9udGggPSB0aGlzLnNlcnZpY2UuamFsYWxpLm5vdyh7IGZvcm1hdDogJ1ktTScgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5mQ2FsZW5kYXIgPSB0aGlzLnNlcnZpY2UuZ2V0Q2FsZW5kYXIodGhpcy5mTW9udGgpO1xuICAgICAgICAgICAgICAgIHRoaXMudE1vbnRoID0gdGhpcy5zZXJ2aWNlLmphbGFsaS5ub3coeyBmb3JtYXQ6ICdZLU0nIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMudENhbGVuZGFyID0gdGhpcy5zZXJ2aWNlLmdldENhbGVuZGFyKHRoaXMudE1vbnRoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldEN1c3RvbURhdGUoJycsICcnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHRoaXMuZm9ybS5nZXQodGhpcy5uYW1lICsgJy10aXRsZScpLm1hcmtBc1RvdWNoZWQoKTtcbiAgICB9XG5cbiAgICBjaGFuZ2VNb250aCh0eXBlOiBzdHJpbmcsIGNoYW5nZTogbnVtYmVyKSB7XG4gICAgICAgIGxldCBZOiBzdHJpbmcgPSAnJztcbiAgICAgICAgbGV0IE06IHN0cmluZyA9ICcnO1xuXG4gICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgY2FzZSAnZnJvbSc6XG4gICAgICAgICAgICAgICAgW1ksIE1dID0gdGhpcy5mTW9udGguc3BsaXQoJy0nKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3RvJzpcbiAgICAgICAgICAgICAgICBbWSwgTV0gPSB0aGlzLnRNb250aC5zcGxpdCgnLScpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHllYXI6IG51bWJlciA9IE51bWJlcihZKTtcbiAgICAgICAgbGV0IG1vbnRoOiBudW1iZXIgPSBOdW1iZXIoTSkgKyBjaGFuZ2U7XG5cbiAgICAgICAgd2hpbGUgKG1vbnRoID4gMTIpIHtcbiAgICAgICAgICAgIG1vbnRoIC09IDEyO1xuICAgICAgICAgICAgeWVhcisrO1xuICAgICAgICB9XG5cbiAgICAgICAgd2hpbGUgKG1vbnRoIDwgMSkge1xuICAgICAgICAgICAgbW9udGggKz0gMTI7XG4gICAgICAgICAgICB5ZWFyLS07XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ2Zyb20nOlxuICAgICAgICAgICAgICAgIHRoaXMuZk1vbnRoID0geWVhci50b1N0cmluZygpICsgJy0nICsgKG1vbnRoIDwgMTAgPyAnMCcgOiAnJykgKyBtb250aC50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgIHRoaXMuZkNhbGVuZGFyID0gdGhpcy5zZXJ2aWNlLmdldENhbGVuZGFyKHRoaXMuZk1vbnRoKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3RvJzpcbiAgICAgICAgICAgICAgICB0aGlzLnRNb250aCA9IHllYXIudG9TdHJpbmcoKSArICctJyArIChtb250aCA8IDEwID8gJzAnIDogJycpICsgbW9udGgudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnRDYWxlbmRhciA9IHRoaXMuc2VydmljZS5nZXRDYWxlbmRhcih0aGlzLnRNb250aCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRUaXRsZSgpIHtcbiAgICAgICAgdGhpcy5mb3JtLmdldCh0aGlzLm5hbWUpLnNldFZhbHVlKHRoaXMudmFsdWUpO1xuXG4gICAgICAgIGNvbnN0IHRpdGxlOiBzdHJpbmcgPSB0aGlzLnNlcnZpY2UuZ2V0UmFuZ2VUaXRsZSh0aGlzLnZhbHVlKTtcbiAgICAgICAgdGhpcy5mb3JtLmdldCh0aGlzLm5hbWUgKyAnLXRpdGxlJykuc2V0VmFsdWUodGl0bGUpO1xuICAgIH1cblxuICAgIHNldEN1c3RvbVRpdGxlKCkge1xuICAgICAgICB0aGlzLmZUaXRsZSA9IHRoaXMuY3VzdG9tLmZyb21cbiAgICAgICAgICAgID8gdGhpcy5zZXJ2aWNlLmphbGFsaS50b1RpdGxlKHRoaXMuc2VydmljZS5qYWxhbGlUb0dyZWdvcmlhbih0aGlzLmN1c3RvbS5mcm9tKSlcbiAgICAgICAgICAgIDogdGhpcy5qYWxhbGlMb2NhbGUubm90U3BlY2lmaWVkO1xuICAgICAgICB0aGlzLnRUaXRsZSA9IHRoaXMuY3VzdG9tLnRvXG4gICAgICAgICAgICA/IHRoaXMuc2VydmljZS5qYWxhbGkudG9UaXRsZSh0aGlzLnNlcnZpY2UuamFsYWxpVG9HcmVnb3JpYW4odGhpcy5jdXN0b20udG8pKVxuICAgICAgICAgICAgOiB0aGlzLmphbGFsaUxvY2FsZS5ub3RTcGVjaWZpZWQ7XG4gICAgfVxuXG4gICAgc2V0Q3VzdG9tRGF0ZShmcm9tOiBzdHJpbmcsIHRvOiBzdHJpbmcpIHtcbiAgICAgICAgaWYgKGZyb20gJiYgdG8gJiYgZnJvbSA+PSB0bykgcmV0dXJuO1xuICAgICAgICB0aGlzLmN1c3RvbS5mcm9tID0gZnJvbTtcbiAgICAgICAgdGhpcy5jdXN0b20udG8gPSB0bztcbiAgICAgICAgdGhpcy5zZXRDdXN0b21UaXRsZSgpO1xuICAgIH1cblxuICAgIHNldFJhbmdlKHR5cGUpIHtcbiAgICAgICAgY29uc3QgZm9ybWF0ID0geyBmb3JtYXQ6ICdZLU0tRCcgfTtcblxuICAgICAgICBsZXQgZnJvbTogc3RyaW5nID0gJyc7XG4gICAgICAgIGxldCB0bzogc3RyaW5nID0gJyc7XG4gICAgICAgIGxldCBkYXRlOiBEYXRlID0gbnVsbDtcblxuICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ2N1cnJlbnQtd2Vlayc6XG4gICAgICAgICAgICAgICAgZGF0ZSA9IHRoaXMuc2VydmljZS5qYWxhbGlUb0dyZWdvcmlhbih0aGlzLnRvZGF5KTtcbiAgICAgICAgICAgICAgICB3aGlsZSAoZGF0ZS5nZXREYXkoKSAhPT0gNikge1xuICAgICAgICAgICAgICAgICAgICBkYXRlID0gbmV3IERhdGUoZGF0ZS5nZXRUaW1lKCkgLSAyNCAqIDM2MDAgKiAxMDAwKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmcm9tID0gdGhpcy5zZXJ2aWNlLmphbGFsaS50b1N0cmluZyhkYXRlLCBmb3JtYXQpO1xuICAgICAgICAgICAgICAgIHRvID0gdGhpcy5zZXJ2aWNlLmphbGFsaS50b1N0cmluZyhuZXcgRGF0ZShkYXRlLmdldFRpbWUoKSArIDYgKiAyNCAqIDM2MDAgKiAxMDAwKSwgZm9ybWF0KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2N1cnJlbnQtbW9udGgnOlxuICAgICAgICAgICAgICAgIGRhdGUgPSB0aGlzLnNlcnZpY2UuamFsYWxpVG9HcmVnb3JpYW4odGhpcy50b2RheS5zdWJzdHIoMCwgOCkgKyAnMDEnKTtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXlzID0gdGhpcy5zZXJ2aWNlLmdldERheUluTW9udGgodGhpcy50b2RheS5zdWJzdHIoMCwgNykpO1xuICAgICAgICAgICAgICAgIGZyb20gPSB0aGlzLnNlcnZpY2UuamFsYWxpLnRvU3RyaW5nKGRhdGUsIGZvcm1hdCk7XG4gICAgICAgICAgICAgICAgdG8gPSB0aGlzLnNlcnZpY2UuamFsYWxpLnRvU3RyaW5nKG5ldyBEYXRlKGRhdGUuZ2V0VGltZSgpICsgKGRheXMgLSAxKSAqIDI0ICogMzYwMCAqIDEwMDApLCBmb3JtYXQpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnbGFzdC03ZGF5cyc6XG4gICAgICAgICAgICAgICAgZGF0ZSA9IHRoaXMuc2VydmljZS5qYWxhbGlUb0dyZWdvcmlhbih0aGlzLnRvZGF5KTtcbiAgICAgICAgICAgICAgICBmcm9tID0gdGhpcy5zZXJ2aWNlLmphbGFsaS50b1N0cmluZyhuZXcgRGF0ZShkYXRlLmdldFRpbWUoKSAtIDYgKiAyNCAqIDM2MDAgKiAxMDAwKSwgZm9ybWF0KTtcbiAgICAgICAgICAgICAgICB0byA9IHRoaXMuc2VydmljZS5qYWxhbGkudG9TdHJpbmcoZGF0ZSwgZm9ybWF0KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2xhc3QtMzBkYXlzJzpcbiAgICAgICAgICAgICAgICBkYXRlID0gdGhpcy5zZXJ2aWNlLmphbGFsaVRvR3JlZ29yaWFuKHRoaXMudG9kYXkpO1xuICAgICAgICAgICAgICAgIGZyb20gPSB0aGlzLnNlcnZpY2UuamFsYWxpLnRvU3RyaW5nKG5ldyBEYXRlKGRhdGUuZ2V0VGltZSgpIC0gMjkgKiAyNCAqIDM2MDAgKiAxMDAwKSwgZm9ybWF0KTtcbiAgICAgICAgICAgICAgICB0byA9IHRoaXMuc2VydmljZS5qYWxhbGkudG9TdHJpbmcoZGF0ZSwgZm9ybWF0KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ25leHQtN2RheXMnOlxuICAgICAgICAgICAgICAgIGRhdGUgPSB0aGlzLnNlcnZpY2UuamFsYWxpVG9HcmVnb3JpYW4odGhpcy50b2RheSk7XG4gICAgICAgICAgICAgICAgZnJvbSA9IHRoaXMuc2VydmljZS5qYWxhbGkudG9TdHJpbmcoZGF0ZSwgZm9ybWF0KTtcbiAgICAgICAgICAgICAgICB0byA9IHRoaXMuc2VydmljZS5qYWxhbGkudG9TdHJpbmcobmV3IERhdGUoZGF0ZS5nZXRUaW1lKCkgKyA2ICogMjQgKiAzNjAwICogMTAwMCksIGZvcm1hdCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICduZXh0LTMwZGF5cyc6XG4gICAgICAgICAgICAgICAgZGF0ZSA9IHRoaXMuc2VydmljZS5qYWxhbGlUb0dyZWdvcmlhbih0aGlzLnRvZGF5KTtcbiAgICAgICAgICAgICAgICBmcm9tID0gdGhpcy5zZXJ2aWNlLmphbGFsaS50b1N0cmluZyhkYXRlLCBmb3JtYXQpO1xuICAgICAgICAgICAgICAgIHRvID0gdGhpcy5zZXJ2aWNlLmphbGFsaS50b1N0cmluZyhuZXcgRGF0ZShkYXRlLmdldFRpbWUoKSArIDI5ICogMjQgKiAzNjAwICogMTAwMCksIGZvcm1hdCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdjdXN0b20nOlxuICAgICAgICAgICAgICAgIGZyb20gPSB0aGlzLmN1c3RvbS5mcm9tO1xuICAgICAgICAgICAgICAgIHRvID0gdGhpcy5jdXN0b20udG87XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdyZXNldCc6XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jdXN0b20gPSB7IGZyb20sIHRvIH07XG4gICAgICAgIHRoaXMudmFsdWUgPSB0aGlzLnNlcnZpY2UuZ2V0UmFuZ2VWYWx1ZShmcm9tLCB0byk7XG4gICAgICAgIHRoaXMuc2V0VGl0bGUoKTtcbiAgICAgICAgdGhpcy5zaG93Q2FsZW5kYXIoZmFsc2UpO1xuICAgICAgICB0aGlzLmNoYW5nZWQuZW1pdCh0aGlzLnZhbHVlLnJhbmdlID8gdGhpcy52YWx1ZSA6IG51bGwpO1xuICAgICAgICB0aGlzLmZvcm0uZ2V0KHRoaXMubmFtZSArICctdGl0bGUnKS51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KCk7XG4gICAgfVxufVxuIl19