UNPKG

ethio-calendar-converter-angular

Version:
494 lines (468 loc) 48.6 kB
import { Component, Output, EventEmitter } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { CommonModule } from '@angular/common'; import * as i0 from "@angular/core"; import * as i1 from "./ethiopian-calendar.service"; import * as i2 from "@angular/common"; import * as i3 from "@angular/forms"; export class EthiopianCalendarComponent { calendarService; ethiopianDate = { year: 2015, month: 4, day: 25 }; gregorianDate = { year: 2022, month: 3, day: 25 }; lastConversion = ''; showEthiopianPicker = false; ethiopianMonths = [ { value: 1, label: 'Meskerem' }, { value: 2, label: 'Tikimt' }, { value: 3, label: 'Hidar' }, { value: 4, label: 'Tahsas' }, { value: 5, label: 'Tir' }, { value: 6, label: 'Yekatit' }, { value: 7, label: 'Megabit' }, { value: 8, label: 'Miyazia' }, { value: 9, label: 'Ginbot' }, { value: 10, label: 'Sene' }, { value: 11, label: 'Hamle' }, { value: 12, label: 'Nehase' }, { value: 13, label: 'Pagume' } ]; get ethiopianYears() { const currentYear = new Date().getFullYear(); const years = []; for (let i = currentYear - 100; i <= currentYear + 100; i++) { years.push(i - 8); // Convert to approximate Ethiopian year } return years; } ethiopianDateChange = new EventEmitter(); gregorianDateChange = new EventEmitter(); constructor(calendarService) { this.calendarService = calendarService; } toggleEthiopianPicker() { this.showEthiopianPicker = !this.showEthiopianPicker; } getEthiopianDays() { const maxDays = this.ethiopianDate.month === 13 ? (this.calendarService['isEthiopianLeapYear'](this.ethiopianDate.year) ? 6 : 5) : 30; return Array.from({ length: maxDays }, (_, i) => i + 1); } applyEthiopianDate() { this.convertToGregorian(); this.toggleEthiopianPicker(); } formatEthiopianDateForDisplay(date) { const monthName = this.ethiopianMonths.find(m => m.value === date.month)?.label || ''; return `${monthName} ${date.day}, ${date.year}`; } convertToGregorian() { try { this.gregorianDate = this.calendarService.toGregorian(this.ethiopianDate); this.gregorianDateChange.emit(this.gregorianDate); this.lastConversion = `Ethiopian ${this.formatDate(this.ethiopianDate)} → Gregorian ${this.formatDate(this.gregorianDate)}`; } catch (error) { this.lastConversion = 'Invalid Ethiopian date'; } } convertToEthiopian() { try { this.ethiopianDate = this.calendarService.toEthiopian(this.gregorianDate); this.ethiopianDateChange.emit(this.ethiopianDate); this.lastConversion = `Gregorian ${this.formatDate(this.gregorianDate)} → Ethiopian ${this.formatDate(this.ethiopianDate)}`; } catch (error) { this.lastConversion = 'Invalid Gregorian date'; } } onGregorianDateSelected(event) { const date = new Date(event.target.value); this.gregorianDate = { year: date.getFullYear(), month: date.getMonth() + 1, day: date.getDate() }; this.convertToEthiopian(); } formatDate(date) { return `${date.year}-${String(date.month).padStart(2, '0')}-${String(date.day).padStart(2, '0')}`; } formatDateForInput(date) { return `${date.year}-${String(date.month).padStart(2, '0')}-${String(date.day).padStart(2, '0')}`; } formatGregorianDate(date) { return new Date(date.year, date.month - 1, date.day) .toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }); } weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; previousMonth() { if (this.ethiopianDate.month > 1) { this.ethiopianDate.month--; } else { this.ethiopianDate.month = 13; this.ethiopianDate.year--; } this.updateEthiopianDate(); } nextMonth() { if (this.ethiopianDate.month < 13) { this.ethiopianDate.month++; } else { this.ethiopianDate.month = 1; this.ethiopianDate.year++; } this.updateEthiopianDate(); } getDaysArray() { const daysInMonth = this.ethiopianDate.month === 13 ? (this.calendarService['isEthiopianLeapYear'](this.ethiopianDate.year) ? 6 : 5) : 30; // Create array with padding for alignment const days = []; const firstDayOffset = this.getFirstDayOffset(); // Add padding for (let i = 0; i < firstDayOffset; i++) { days.push(0); } // Add days for (let i = 1; i <= daysInMonth; i++) { days.push(i); } return days; } getFirstDayOffset() { // This is a simplified version - you might want to implement proper Ethiopian calendar day-of-week calculation return (this.ethiopianDate.month * 2) % 7; } getDayClasses(day) { const baseClasses = 'h-8 w-8 rounded-full flex items-center justify-center text-sm'; const isSelected = day === this.ethiopianDate.day; if (isSelected) { return `${baseClasses} bg-blue-600 text-white`; } return `${baseClasses} hover:bg-gray-100 text-gray-700`; } selectDay(day) { this.ethiopianDate.day = day; this.updateEthiopianDate(); this.toggleEthiopianPicker(); } selectToday() { const today = this.calendarService.toEthiopian({ year: new Date().getFullYear(), month: new Date().getMonth() + 1, day: new Date().getDate() }); this.ethiopianDate = today; this.updateEthiopianDate(); this.toggleEthiopianPicker(); } updateEthiopianDate() { this.ethiopianDateChange.emit(this.ethiopianDate); this.convertToGregorian(); } formatEthiopianDateForInput(date) { const monthName = this.ethiopianMonths.find(m => m.value === date.month)?.label || ''; return `${monthName} ${date.day}, ${date.year}`; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EthiopianCalendarComponent, deps: [{ token: i1.EthiopianCalendarService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: EthiopianCalendarComponent, isStandalone: true, selector: "ethiopian-calendar", outputs: { ethiopianDateChange: "ethiopianDateChange", gregorianDateChange: "gregorianDateChange" }, ngImport: i0, template: ` <div class="bg-white rounded-lg shadow-lg p-6 max-w-md mx-auto"> <!-- Ethiopian Calendar Input --> <div class="mb-8"> <h3 class="text-lg font-medium text-gray-900 mb-4">Ethiopian Calendar</h3> <div class="relative"> <input type="text" [value]="formatEthiopianDateForInput(ethiopianDate)" (click)="toggleEthiopianPicker()" readonly class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all cursor-pointer" /> <label class="absolute -top-2 left-2 bg-white px-1 text-xs text-gray-600">Select Date</label> <!-- Calendar Icon --> <button (click)="toggleEthiopianPicker()" class="absolute right-2 top-2 text-gray-400 hover:text-gray-600 focus:outline-none" > <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" /> </svg> </button> <!-- Ethiopian Calendar Picker --> <div *ngIf="showEthiopianPicker" class="absolute left-0 mt-1 p-4 bg-white rounded-lg shadow-lg border border-gray-200 z-50 w-[320px]"> <!-- Month and Year Navigation --> <div class="flex justify-between items-center mb-4"> <button (click)="previousMonth()" class="p-1 hover:bg-gray-100 rounded-full" > <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" /> </svg> </button> <div class="flex items-center space-x-2"> <select [(ngModel)]="ethiopianDate.month" (change)="updateEthiopianDate()" class="text-sm border-none bg-transparent font-semibold focus:outline-none focus:ring-0" > <option *ngFor="let month of ethiopianMonths" [value]="month.value"> {{month.label}} </option> </select> <select [(ngModel)]="ethiopianDate.year" (change)="updateEthiopianDate()" class="text-sm border-none bg-transparent font-semibold focus:outline-none focus:ring-0" > <option *ngFor="let year of ethiopianYears" [value]="year">{{year}}</option> </select> </div> <button (click)="nextMonth()" class="p-1 hover:bg-gray-100 rounded-full" > <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" /> </svg> </button> </div> <!-- Calendar Grid --> <div class="grid grid-cols-7 gap-1"> <!-- Week days --> <div *ngFor="let day of weekDays" class="text-center text-xs font-medium text-gray-500 py-1"> {{day}} </div> <!-- Days --> <ng-container *ngFor="let day of getDaysArray()"> <button *ngIf="day !== 0" (click)="selectDay(day)" [class]="getDayClasses(day)" > {{day}} </button> <div *ngIf="day === 0" class="h-8"></div> </ng-container> </div> <!-- Today Button --> <div class="mt-4 flex justify-between items-center border-t pt-4"> <button (click)="selectToday()" class="text-sm text-blue-600 hover:text-blue-800 font-medium" > Today </button> <button (click)="toggleEthiopianPicker()" class="text-sm text-gray-600 hover:text-gray-800 font-medium" > Close </button> </div> </div> </div> <div *ngIf="ethiopianDate" class="mt-2 text-sm text-gray-600"> Selected: {{formatEthiopianDateForDisplay(ethiopianDate)}} </div> <button (click)="convertToGregorian()" class="mt-4 w-full bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors" > Convert to Gregorian </button> </div> <!-- Gregorian Calendar Input --> <div class="mb-8"> <h3 class="text-lg font-medium text-gray-900 mb-4">Gregorian Calendar</h3> <div class="relative"> <input type="date" [value]="formatDateForInput(gregorianDate)" (change)="onGregorianDateSelected($event)" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all" /> <label class="absolute -top-2 left-2 bg-white px-1 text-xs text-gray-600">Select Date</label> </div> <div *ngIf="gregorianDate" class="mt-2 text-sm text-gray-600"> Selected: {{formatGregorianDate(gregorianDate)}} </div> <button (click)="convertToEthiopian()" class="mt-4 w-full bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors" > Convert to Ethiopian </button> </div> <!-- Conversion Result --> <div *ngIf="lastConversion" class="p-4 bg-gray-50 rounded-lg border border-gray-200"> <p class="text-sm font-medium text-gray-900">Last Conversion:</p> <p class="text-sm text-gray-600 mt-1">{{lastConversion}}</p> </div> </div> `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i3.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EthiopianCalendarComponent, decorators: [{ type: Component, args: [{ selector: 'ethiopian-calendar', standalone: true, imports: [ CommonModule, FormsModule ], template: ` <div class="bg-white rounded-lg shadow-lg p-6 max-w-md mx-auto"> <!-- Ethiopian Calendar Input --> <div class="mb-8"> <h3 class="text-lg font-medium text-gray-900 mb-4">Ethiopian Calendar</h3> <div class="relative"> <input type="text" [value]="formatEthiopianDateForInput(ethiopianDate)" (click)="toggleEthiopianPicker()" readonly class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all cursor-pointer" /> <label class="absolute -top-2 left-2 bg-white px-1 text-xs text-gray-600">Select Date</label> <!-- Calendar Icon --> <button (click)="toggleEthiopianPicker()" class="absolute right-2 top-2 text-gray-400 hover:text-gray-600 focus:outline-none" > <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" /> </svg> </button> <!-- Ethiopian Calendar Picker --> <div *ngIf="showEthiopianPicker" class="absolute left-0 mt-1 p-4 bg-white rounded-lg shadow-lg border border-gray-200 z-50 w-[320px]"> <!-- Month and Year Navigation --> <div class="flex justify-between items-center mb-4"> <button (click)="previousMonth()" class="p-1 hover:bg-gray-100 rounded-full" > <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" /> </svg> </button> <div class="flex items-center space-x-2"> <select [(ngModel)]="ethiopianDate.month" (change)="updateEthiopianDate()" class="text-sm border-none bg-transparent font-semibold focus:outline-none focus:ring-0" > <option *ngFor="let month of ethiopianMonths" [value]="month.value"> {{month.label}} </option> </select> <select [(ngModel)]="ethiopianDate.year" (change)="updateEthiopianDate()" class="text-sm border-none bg-transparent font-semibold focus:outline-none focus:ring-0" > <option *ngFor="let year of ethiopianYears" [value]="year">{{year}}</option> </select> </div> <button (click)="nextMonth()" class="p-1 hover:bg-gray-100 rounded-full" > <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" /> </svg> </button> </div> <!-- Calendar Grid --> <div class="grid grid-cols-7 gap-1"> <!-- Week days --> <div *ngFor="let day of weekDays" class="text-center text-xs font-medium text-gray-500 py-1"> {{day}} </div> <!-- Days --> <ng-container *ngFor="let day of getDaysArray()"> <button *ngIf="day !== 0" (click)="selectDay(day)" [class]="getDayClasses(day)" > {{day}} </button> <div *ngIf="day === 0" class="h-8"></div> </ng-container> </div> <!-- Today Button --> <div class="mt-4 flex justify-between items-center border-t pt-4"> <button (click)="selectToday()" class="text-sm text-blue-600 hover:text-blue-800 font-medium" > Today </button> <button (click)="toggleEthiopianPicker()" class="text-sm text-gray-600 hover:text-gray-800 font-medium" > Close </button> </div> </div> </div> <div *ngIf="ethiopianDate" class="mt-2 text-sm text-gray-600"> Selected: {{formatEthiopianDateForDisplay(ethiopianDate)}} </div> <button (click)="convertToGregorian()" class="mt-4 w-full bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors" > Convert to Gregorian </button> </div> <!-- Gregorian Calendar Input --> <div class="mb-8"> <h3 class="text-lg font-medium text-gray-900 mb-4">Gregorian Calendar</h3> <div class="relative"> <input type="date" [value]="formatDateForInput(gregorianDate)" (change)="onGregorianDateSelected($event)" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all" /> <label class="absolute -top-2 left-2 bg-white px-1 text-xs text-gray-600">Select Date</label> </div> <div *ngIf="gregorianDate" class="mt-2 text-sm text-gray-600"> Selected: {{formatGregorianDate(gregorianDate)}} </div> <button (click)="convertToEthiopian()" class="mt-4 w-full bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors" > Convert to Ethiopian </button> </div> <!-- Conversion Result --> <div *ngIf="lastConversion" class="p-4 bg-gray-50 rounded-lg border border-gray-200"> <p class="text-sm font-medium text-gray-900">Last Conversion:</p> <p class="text-sm text-gray-600 mt-1">{{lastConversion}}</p> </div> </div> ` }] }], ctorParameters: () => [{ type: i1.EthiopianCalendarService }], propDecorators: { ethiopianDateChange: [{ type: Output }], gregorianDateChange: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXRoaW9waWFuLWNhbGVuZGFyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvZXRoaW9waWFuLWNhbGVuZGFyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDaEUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQzs7Ozs7QUFtSy9DLE1BQU0sT0FBTywwQkFBMEI7SUFrQ2pCO0lBakNwQixhQUFhLEdBQWtCLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNqRSxhQUFhLEdBQWtCLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNqRSxjQUFjLEdBQVcsRUFBRSxDQUFDO0lBQzVCLG1CQUFtQixHQUFZLEtBQUssQ0FBQztJQUVyQyxlQUFlLEdBQUc7UUFDaEIsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUU7UUFDL0IsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUU7UUFDN0IsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUU7UUFDNUIsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUU7UUFDN0IsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUU7UUFDMUIsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUU7UUFDOUIsRUFBRSxL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SSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxLQUFLLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDO1FBQ3RGLE9BQU8sR0FBRyxTQUFTLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDbEQsQ0FBQzt3R0E3TFUsMEJBQTBCOzRGQUExQiwwQkFBMEIsbUxBeEozQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0pULDJEQXpKQyxZQUFZLCtQQUNaLFdBQVc7OzRGQTBKRiwwQkFBMEI7a0JBL0p0QyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxvQkFBb0I7b0JBQzlCLFVBQVUsRUFBRSxJQUFJO29CQUNoQixPQUFPLEVBQUU7d0JBQ1AsWUFBWTt3QkFDWixXQUFXO3FCQUNaO29CQUNELFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0pUO2lCQUNGOzZGQWdDVyxtQkFBbUI7c0JBQTVCLE1BQU07Z0JBQ0csbUJBQW1CO3NCQUE1QixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPdXRwdXQsIEV2ZW50RW1pdHRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgRXRoaW9waWFuQ2FsZW5kYXJTZXJ2aWNlIH0gZnJvbSAnLi9ldGhpb3BpYW4tY2FsZW5kYXIuc2VydmljZSc7XG5pbXBvcnQgeyBFdGhpb3BpYW5EYXRlLCBHcmVnb3JpYW5EYXRlIH0gZnJvbSAnLi9tb2RlbHMvY2FsZW5kYXIubW9kZWwnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdldGhpb3BpYW4tY2FsZW5kYXInLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXG4gICAgQ29tbW9uTW9kdWxlLFxuICAgIEZvcm1zTW9kdWxlXG4gIF0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cImJnLXdoaXRlIHJvdW5kZWQtbGcgc2hhZG93LWxnIHAtNiBtYXgtdy1tZCBteC1hdXRvXCI+XG4gICAgICA8IS0tIEV0aGlvcGlhbiBDYWxlbmRhciBJbnB1dCAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJtYi04XCI+XG4gICAgICAgIDxoMyBjbGFzcz1cInRleHQtbGcgZm9udC1tZWRpdW0gdGV4dC1ncmF5LTkwMCBtYi00XCI+RXRoaW9waWFuIENhbGVuZGFyPC9oMz5cbiAgICAgICAgPGRpdiBjbGFzcz1cInJlbGF0aXZlXCI+XG4gICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICBbdmFsdWVdPVwiZm9ybWF0RXRoaW9waWFuRGF0ZUZvcklucHV0KGV0aGlvcGlhbkRhdGUpXCJcbiAgICAgICAgICAgIChjbGljayk9XCJ0b2dnbGVFdGhpb3BpYW5QaWNrZXIoKVwiXG4gICAgICAgICAgICByZWFkb25seVxuICAgICAgICAgICAgY2xhc3M9XCJ3LWZ1bGwgcHgtMyBweS0yIGJvcmRlciBib3JkZXItZ3JheS0zMDAgcm91bmRlZC1tZCBmb2N1czpvdXRsaW5lLW5vbmUgZm9jdXM6cmluZy0yIGZvY3VzOnJpbmctYmx1ZS01MDAgZm9jdXM6Ym9yZGVyLXRyYW5zcGFyZW50IHRyYW5zaXRpb24tYWxsIGN1cnNvci1wb2ludGVyXCJcbiAgICAgICAgICAvPlxuICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImFic29sdXRlIC10b3AtMiBsZWZ0LTIgYmctd2hpdGUgcHgtMSB0ZXh0LXhzIHRleHQtZ3JheS02MDBcIj5TZWxlY3QgRGF0ZTwvbGFiZWw+XG4gICAgICAgICAgXG4gICAgICAgICAgPCEtLSBDYWxlbmRhciBJY29uIC0tPlxuICAgICAgICAgIDxidXR0b24gXG4gICAgICAgICAgICAoY2xpY2spPVwidG9nZ2xlRXRoaW9waWFuUGlja2VyKClcIlxuICAgICAgICAgICAgY2xhc3M9XCJhYnNvbHV0ZSByaWdodC0yIHRvcC0yIHRleHQtZ3JheS00MDAgaG92ZXI6dGV4dC1ncmF5LTYwMCBmb2N1czpvdXRsaW5lLW5vbmVcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxzdmcgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIGNsYXNzPVwiaC01IHctNVwiIGZpbGw9XCJub25lXCIgdmlld0JveD1cIjAgMCAyNCAyNFwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiPlxuICAgICAgICAgICAgICA8cGF0aCBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIiBzdHJva2Utd2lkdGg9XCIyXCIgZD1cIk04IDdWM204IDRWM20tOSA4aDEwTTUgMjFoMTRhMiAyIDAgMDAyLTJWN2EyIDIgMCAwMC0yLTJINWEyIDIgMCAwMC0yIDJ2MTJhMiAyIDAgMDAyIDJ6XCIgLz5cbiAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgIDwvYnV0dG9uPlxuXG4gICAgICAgICAgPCEtLSBFdGhpb3BpYW4gQ2FsZW5kYXIgUGlja2VyIC0tPlxuICAgICAgICAgIDxkaXYgKm5nSWY9XCJzaG93RXRoaW9waWFuUGlja2VyXCIgXG4gICAgICAgICAgICAgICBjbGFzcz1cImFic29sdXRlIGxlZnQtMCBtdC0xIHAtNCBiZy13aGl0ZSByb3VuZGVkLWxnIHNoYWRvdy1sZyBib3JkZXIgYm9yZGVyLWdyYXktMjAwIHotNTAgdy1bMzIwcHhdXCI+XG4gICAgICAgICAgICA8IS0tIE1vbnRoIGFuZCBZZWFyIE5hdmlnYXRpb24gLS0+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBqdXN0aWZ5LWJldHdlZW4gaXRlbXMtY2VudGVyIG1iLTRcIj5cbiAgICAgICAgICAgICAgPGJ1dHRvbiBcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwicHJldmlvdXNNb250aCgpXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cInAtMSBob3ZlcjpiZy1ncmF5LTEwMCByb3VuZGVkLWZ1bGxcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPHN2ZyBjbGFzcz1cImgtNSB3LTVcIiBmaWxsPVwibm9uZVwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIj5cbiAgICAgICAgICAgICAgICAgIDxwYXRoIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiIHN0cm9rZS13aWR0aD1cIjJcIiBkPVwiTTE1IDE5bC03LTcgNy03XCIgLz5cbiAgICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgIFxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgc3BhY2UteC0yXCI+XG4gICAgICAgICAgICAgICAgPHNlbGVjdCBcbiAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiZXRoaW9waWFuRGF0ZS5tb250aFwiXG4gICAgICAgICAgICAgICAgICAoY2hhbmdlKT1cInVwZGF0ZUV0aGlvcGlhbkRhdGUoKVwiXG4gICAgICAgICAgICAgICAgICBjbGFzcz1cInRleHQtc20gYm9yZGVyLW5vbmUgYmctdHJhbnNwYXJlbnQgZm9udC1zZW1pYm9sZCBmb2N1czpvdXRsaW5lLW5vbmUgZm9jdXM6cmluZy0wXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICA8b3B0aW9uICpuZ0Zvcj1cImxldCBtb250aCBvZiBldGhpb3BpYW5Nb250aHNcIiBbdmFsdWVdPVwibW9udGgudmFsdWVcIj5cbiAgICAgICAgICAgICAgICAgICAge3ttb250aC5sYWJlbH19XG4gICAgICAgICAgICAgICAgICA8L29wdGlvbj5cbiAgICAgICAgICAgICAgICA8L3NlbGVjdD5cbiAgICAgICAgICAgICAgICA8c2VsZWN0IFxuICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJldGhpb3BpYW5EYXRlLnllYXJcIlxuICAgICAgICAgICAgICAgICAgKGNoYW5nZSk9XCJ1cGRhdGVFdGhpb3BpYW5EYXRlKClcIlxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LXNtIGJvcmRlci1ub25lIGJnLXRyYW5zcGFyZW50IGZvbnQtc2VtaWJvbGQgZm9jdXM6b3V0bGluZS1ub25lIGZvY3VzOnJpbmctMFwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgPG9wdGlvbiAqbmdGb3I9XCJsZXQgeWVhciBvZiBldGhpb3BpYW5ZZWFyc1wiIFt2YWx1ZV09XCJ5ZWFyXCI+e3t5ZWFyfX08L29wdGlvbj5cbiAgICAgICAgICAgICAgICA8L3NlbGVjdD5cbiAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgPGJ1dHRvbiBcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwibmV4dE1vbnRoKClcIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwicC0xIGhvdmVyOmJnLWdyYXktMTAwIHJvdW5kZWQtZnVsbFwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8c3ZnIGNsYXNzPVwiaC01IHctNVwiIGZpbGw9XCJub25lXCIgc3Ryb2tlPVwiY3VycmVudENvbG9yXCIgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICAgICAgICAgICAgICAgICAgPHBhdGggc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIgc3Ryb2tlLXdpZHRoPVwiMlwiIGQ9XCJNOSA1bDcgNy03IDdcIiAvPlxuICAgICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICA8IS0tIENhbGVuZGFyIEdyaWQgLS0+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZ3JpZCBncmlkLWNvbHMtNyBnYXAtMVwiPlxuICAgICAgICAgICAgICA8IS0tIFdlZWsgZGF5cyAtLT5cbiAgICAgICAgICAgICAgPGRpdiAqbmdGb3I9XCJsZXQgZGF5IG9mIHdlZWtEYXlzXCIgXG4gICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LWNlbnRlciB0ZXh0LXhzIGZvbnQtbWVkaXVtIHRleHQtZ3JheS01MDAgcHktMVwiPlxuICAgICAgICAgICAgICAgIHt7ZGF5fX1cbiAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgPCEtLSBEYXlzIC0tPlxuICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBkYXkgb2YgZ2V0RGF5c0FycmF5KClcIj5cbiAgICAgICAgICAgICAgICA8YnV0dG9uICpuZ0lmPVwiZGF5ICE9PSAwXCJcbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJzZWxlY3REYXkoZGF5KVwiXG4gICAgICAgICAgICAgICAgICBbY2xhc3NdPVwiZ2V0RGF5Q2xhc3NlcyhkYXkpXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICB7e2RheX19XG4gICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgPGRpdiAqbmdJZj1cImRheSA9PT0gMFwiIGNsYXNzPVwiaC04XCI+PC9kaXY+XG4gICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIDwhLS0gVG9kYXkgQnV0dG9uIC0tPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm10LTQgZmxleCBqdXN0aWZ5LWJldHdlZW4gaXRlbXMtY2VudGVyIGJvcmRlci10IHB0LTRcIj5cbiAgICAgICAgICAgICAgPGJ1dHRvbiBcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwic2VsZWN0VG9kYXkoKVwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LXNtIHRleHQtYmx1ZS02MDAgaG92ZXI6dGV4dC1ibHVlLTgwMCBmb250LW1lZGl1bVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICBUb2RheVxuICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgPGJ1dHRvbiBcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwidG9nZ2xlRXRoaW9waWFuUGlja2VyKClcIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1zbSB0ZXh0LWdyYXktNjAwIGhvdmVyOnRleHQtZ3JheS04MDAgZm9udC1tZWRpdW1cIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgQ2xvc2VcbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPGRpdiAqbmdJZj1cImV0aGlvcGlhbkRhdGVcIiBjbGFzcz1cIm10LTIgdGV4dC1zbSB0ZXh0LWdyYXktNjAwXCI+XG4gICAgICAgICAgU2VsZWN0ZWQ6IHt7Zm9ybWF0RXRoaW9waWFuRGF0ZUZvckRpc3BsYXkoZXRoaW9waWFuRGF0ZSl9fVxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgKGNsaWNrKT1cImNvbnZlcnRUb0dyZWdvcmlhbigpXCJcbiAgICAgICAgICBjbGFzcz1cIm10LTQgdy1mdWxsIGJnLWJsdWUtNjAwIHRleHQtd2hpdGUgcHgtNCBweS0yIHJvdW5kZWQtbWQgaG92ZXI6YmctYmx1ZS03MDAgZm9jdXM6b3V0bGluZS1ub25lIGZvY3VzOnJpbmctMiBmb2N1czpyaW5nLWJsdWUtNTAwIGZvY3VzOnJpbmctb2Zmc2V0LTIgdHJhbnNpdGlvbi1jb2xvcnNcIlxuICAgICAgICA+XG4gICAgICAgICAgQ29udmVydCB0byBHcmVnb3JpYW5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPCEtLSBHcmVnb3JpYW4gQ2FsZW5kYXIgSW5wdXQgLS0+XG4gICAgICA8ZGl2IGNsYXNzPVwibWItOFwiPlxuICAgICAgICA8aDMgY2xhc3M9XCJ0ZXh0LWxnIGZvbnQtbWVkaXVtIHRleHQtZ3JheS05MDAgbWItNFwiPkdyZWdvcmlhbiBDYWxlbmRhcjwvaDM+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJyZWxhdGl2ZVwiPlxuICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgdHlwZT1cImRhdGVcIlxuICAgICAgICAgICAgW3ZhbHVlXT1cImZvcm1hdERhdGVGb3JJbnB1dChncmVnb3JpYW5EYXRlKVwiXG4gICAgICAgICAgICAoY2hhbmdlKT1cIm9uR3JlZ29yaWFuRGF0ZVNlbGVjdGVkKCRldmVudClcIlxuICAgICAgICAgICAgY2xhc3M9XCJ3LWZ1bGwgcHgtMyBweS0yIGJvcmRlciBib3JkZXItZ3JheS0zMDAgcm91bmRlZC1tZCBmb2N1czpvdXRsaW5lLW5vbmUgZm9jdXM6cmluZy0yIGZvY3VzOnJpbmctYmx1ZS01MDAgZm9jdXM6Ym9yZGVyLXRyYW5zcGFyZW50IHRyYW5zaXRpb24tYWxsXCJcbiAgICAgICAgICAvPlxuICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImFic29sdXRlIC10b3AtMiBsZWZ0LTIgYmctd2hpdGUgcHgtMSB0ZXh0LXhzIHRleHQtZ3JheS02MDBcIj5TZWxlY3QgRGF0ZTwvbGFiZWw+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxkaXYgKm5nSWY9XCJncmVnb3JpYW5EYXRlXCIgY2xhc3M9XCJtdC0yIHRleHQtc20gdGV4dC1ncmF5LTYwMFwiPlxuICAgICAgICAgIFNlbGVjdGVkOiB7e2Zvcm1hdEdyZWdvcmlhbkRhdGUoZ3JlZ29yaWFuRGF0ZSl9fVxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgKGNsaWNrKT1cImNvbnZlcnRUb0V0aGlvcGlhbigpXCJcbiAgICAgICAgICBjbGFzcz1cIm10LTQgdy1mdWxsIGJnLWJsdWUtNjAwIHRleHQtd2hpdGUgcHgtNCBweS0yIHJvdW5kZWQtbWQgaG92ZXI6YmctYmx1ZS03MDAgZm9jdXM6b3V0bGluZS1ub25lIGZvY3VzOnJpbmctMiBmb2N1czpyaW5nLWJsdWUtNTAwIGZvY3VzOnJpbmctb2Zmc2V0LTIgdHJhbnNpdGlvbi1jb2xvcnNcIlxuICAgICAgICA+XG4gICAgICAgICAgQ29udmVydCB0byBFdGhpb3BpYW5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPCEtLSBDb252ZXJzaW9uIFJlc3VsdCAtLT5cbiAgICAgIDxkaXYgKm5nSWY9XCJsYXN0Q29udmVyc2lvblwiIFxuICAgICAgICAgICBjbGFzcz1cInAtNCBiZy1ncmF5LTUwIHJvdW5kZWQtbGcgYm9yZGVyIGJvcmRlci1ncmF5LTIwMFwiPlxuICAgICAgICA8cCBjbGFzcz1cInRleHQtc20gZm9udC1tZWRpdW0gdGV4dC1ncmF5LTkwMFwiPkxhc3QgQ29udmVyc2lvbjo8L3A+XG4gICAgICAgIDxwIGNsYXNzPVwidGV4dC1zbSB0ZXh0LWdyYXktNjAwIG10LTFcIj57e2xhc3RDb252ZXJzaW9ufX08L3A+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgYFxufSlcbmV4cG9ydCBjbGFzcyBFdGhpb3BpYW5DYWxlbmRhckNvbXBvbmVudCB7XG4gIGV0aGlvcGlhbkRhdGU6IEV0aGlvcGlhbkRhdGUgPSB7IHllYXI6IDIwMTUsIG1vbnRoOiA0LCBkYXk6IDI1IH07XG4gIGdyZWdvcmlhbkRhdGU6IEdyZWdvcmlhbkRhdGUgPSB7IHllYXI6IDIwMjIsIG1vbnRoOiAzLCBkYXk6IDI1IH07XG4gIGxhc3RDb252ZXJzaW9uOiBzdHJpbmcgPSAnJztcbiAgc2hvd0V0aGlvcGlhblBpY2tlcjogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIGV0aGlvcGlhbk1vbnRocyA9IFtcbiAgICB7IHZhbHVlOiAxLCBsYWJlbDogJ01lc2tlcmVtJyB9LFxuICAgIHsgdmFsdWU6IDIsIGxhYmVsOiAnVGlraW10JyB9LFxuICAgIHsgdmFsdWU6IDMsIGxhYmVsOiAnSGlkYXInIH0sXG4gICAgeyB2YWx1ZTogNCwgbGFiZWw6ICdUYWhzYXMnIH0sXG4gICAgeyB2YWx1ZTogNSwgbGFiZWw6ICdUaXInIH0sXG4gICAgeyB2YWx1ZTogNiwgbGFiZWw6ICdZZWthdGl0JyB9LFxuICAgIHsgdmFsdWU6IDcsIGxhYmVsOiAnTWVnYWJpdCcgfSxcbiAgICB7IHZhbHVlOiA4LCBsYWJlbDogJ01peWF6aWEnIH0sXG4gICAgeyB2YWx1ZTogOSwgbGFiZWw6ICdHaW5ib3QnIH0sXG4gICAgeyB2YWx1ZTogMTAsIGxhYmVsOiAnU2VuZScgfSxcbiAgICB7IHZhbHVlOiAxMSwgbGFiZWw6ICdIYW1sZScgfSxcbiAgICB7IHZhbHVlOiAxMiwgbGFiZWw6ICdOZWhhc2UnIH0sXG4gICAgeyB2YWx1ZTogMTMsIGxhYmVsOiAnUGFndW1lJyB9XG4gIF07XG5cbiAgZ2V0IGV0aGlvcGlhblllYXJzKCk6IG51bWJlcltdIHtcbiAgICBjb25zdCBjdXJyZW50WWVhciA9IG5ldyBEYXRlKCkuZ2V0RnVsbFllYXIoKTtcbiAgICBjb25zdCB5ZWFyczogbnVtYmVyW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gY3VycmVudFllYXIgLSAxMDA7IGkgPD0gY3VycmVudFllYXIgKyAxMDA7IGkrKykge1xuICAgICAgeWVhcnMucHVzaChpIC0gOCk7IC8vIENvbnZlcnQgdG8gYXBwcm94aW1hdGUgRXRoaW9waWFuIHllYXJcbiAgICB9XG4gICAgcmV0dXJuIHllYXJzO1xuICB9XG5cbiAgQE91dHB1dCgpIGV0aGlvcGlhbkRhdGVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPEV0aGlvcGlhbkRhdGU+KCk7XG4gIEBPdXRwdXQoKSBncmVnb3JpYW5EYXRlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxHcmVnb3JpYW5EYXRlPigpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgY2FsZW5kYXJTZXJ2aWNlOiBFdGhpb3BpYW5DYWxlbmRhclNlcnZpY2UpIHt9XG5cbiAgdG9nZ2xlRXRoaW9waWFuUGlja2VyKCkge1xuICAgIHRoaXMuc2hvd0V0aGlvcGlhblBpY2tlciA9ICF0aGlzLnNob3dFdGhpb3BpYW5QaWNrZXI7XG4gIH1cblxuICBnZXRFdGhpb3BpYW5EYXlzKCk6IG51bWJlcltdIHtcbiAgICBjb25zdCBtYXhEYXlzID0gdGhpcy5ldGhpb3BpYW5EYXRlLm1vbnRoID09PSAxMyA/IFxuICAgICAgKHRoaXMuY2FsZW5kYXJTZXJ2aWNlWydpc0V0aGlvcGlhbkxlYXBZZWFyJ10odGhpcy5ldGhpb3BpYW5EYXRlLnllYXIpID8gNiA6IDUpIDogXG4gICAgICAzMDtcbiAgICByZXR1cm4gQXJyYXkuZnJvbSh7bGVuZ3RoOiBtYXhEYXlzfSwgKF8sIGkpID0+IGkgKyAxKTtcbiAgfVxuXG4gIGFwcGx5RXRoaW9waWFuRGF0ZSgpIHtcbiAgICB0aGlzLmNvbnZlcnRUb0dyZWdvcmlhbigpO1xuICAgIHRoaXMudG9nZ2xlRXRoaW9waWFuUGlja2VyKCk7XG4gIH1cblxuICBmb3JtYXRFdGhpb3BpYW5EYXRlRm9yRGlzcGxheShkYXRlOiBFdGhpb3BpYW5EYXRlKTogc3RyaW5nIHtcbiAgICBjb25zdCBtb250aE5hbWUgPSB0aGlzLmV0aGlvcGlhbk1vbnRocy5maW5kKG0gPT4gbS52YWx1ZSA9PT0gZGF0ZS5tb250aCk/LmxhYmVsIHx8ICcnO1xuICAgIHJldHVybiBgJHttb250aE5hbWV9ICR7ZGF0ZS5kYXl9LCAke2RhdGUueWVhcn1gO1xuICB9XG5cbiAgY29udmVydFRvR3JlZ29yaWFuKCkge1xuICAgIHRyeSB7XG4gICAgICB0aGlzLmdyZWdvcmlhbkRhdGUgPSB0aGlzLmNhbGVuZGFyU2VydmljZS50b0dyZWdvcmlhbih0aGlzLmV0aGlvcGlhbkRhdGUpO1xuICAgICAgdGhpcy5ncmVnb3JpYW5EYXRlQ2hhbmdlLmVtaXQodGhpcy5ncmVnb3JpYW5EYXRlKTtcbiAgICAgIHRoaXMubGFzdENvbnZlcnNpb24gPSBgRXRoaW9waWFuICR7dGhpcy5mb3JtYXREYXRlKHRoaXMuZXRoaW9waWFuRGF0ZSl9IOKGkiBHcmVnb3JpYW4gJHt0aGlzLmZvcm1hdERhdGUodGhpcy5ncmVnb3JpYW5EYXRlKX1gO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLmxhc3RDb252ZXJzaW9uID0gJ0ludmFsaWQgRXRoaW9waWFuIGRhdGUnO1xuICAgIH1cbiAgfVxuXG4gIGNvbnZlcnRUb0V0aGlvcGlhbigpIHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5ldGhpb3BpYW5EYXRlID0gdGhpcy5jYWxlbmRhclNlcnZpY2UudG9FdGhpb3BpYW4odGhpcy5ncmVnb3JpYW5EYXRlKTtcbiAgICAgIHRoaXMuZXRoaW9waWFuRGF0ZUNoYW5nZS5lbWl0KHRoaXMuZXRoaW9waWFuRGF0ZSk7XG4gICAgICB0aGlzLmxhc3RDb252ZXJzaW9uID0gYEdyZWdvcmlhbiAke3RoaXMuZm9ybWF0RGF0ZSh0aGlzLmdyZWdvcmlhbkRhdGUpfSDihpIgRXRoaW9waWFuICR7dGhpcy5mb3JtYXREYXRlKHRoaXMuZXRoaW9waWFuRGF0ZSl9YDtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhpcy5sYXN0Q29udmVyc2lvbiA9ICdJbnZhbGlkIEdyZWdvcmlhbiBkYXRlJztcbiAgICB9XG4gIH1cblxuICBvbkdyZWdvcmlhbkRhdGVTZWxlY3RlZChldmVudDogYW55KSB7XG4gICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKGV2ZW50LnRhcmdldC52YWx1ZSk7XG4gICAgdGhpcy5ncmVnb3JpYW5EYXRlID0ge1xuICAgICAgeWVhcjogZGF0ZS5nZXRGdWxsWWVhcigpLFxuICAgICAgbW9udGg6IGRhdGUuZ2V0TW9udGgoKSArIDEsXG4gICAgICBkYXk6IGRhdGUuZ2V0RGF0ZSgpXG4gICAgfTtcbiAgICB0aGlzLmNvbnZlcnRUb0V0aGlvcGlhbigpO1xuICB9XG5cbiAgZm9ybWF0RGF0ZShkYXRlOiBFdGhpb3BpYW5EYXRlIHwgR3JlZ29yaWFuRGF0ZSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke2RhdGUueWVhcn0tJHtTdHJpbmcoZGF0ZS5tb250aCkucGFkU3RhcnQoMiwgJzAnKX0tJHtTdHJpbmcoZGF0ZS5kYXkpLnBhZFN0YXJ0KDIsICcwJyl9YDtcbiAgfVxuXG4gIGZvcm1hdERhdGVGb3JJbnB1dChkYXRlOiBHcmVnb3JpYW5EYXRlKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYCR7ZGF0ZS55ZWFyfS0ke1N0cmluZyhkYXRlLm1vbnRoKS5wYWRTdGFydCgyLCAnMCcpfS0ke1N0cmluZyhkYXRlLmRheSkucGFkU3RhcnQoMiwgJzAnKX1gO1xuICB9XG5cbiAgZm9ybWF0R3JlZ29yaWFuRGF0ZShkYXRlOiBHcmVnb3JpYW5EYXRlKTogc3RyaW5nIHtcbiAgICByZXR1cm4gbmV3IERhdGUoZGF0ZS55ZWFyLCBkYXRlLm1vbnRoIC0gMSwgZGF0ZS5kYXkpXG4gICAgICAudG9Mb2NhbGVEYXRlU3RyaW5nKCdlbi1VUycsIHtcbiAgICAgICAgeWVhcjogJ251bWVyaWMnLFxuICAgICAgICBtb250aDogJ2xvbmcnLFxuICAgICAgICBkYXk6ICdudW1lcmljJ1xuICAgICAgfSk7XG4gIH1cblxuICB3ZWVrRGF5cyA9IFsnU3VuJywgJ01vbicsICdUdWUnLCAnV2VkJywgJ1RodScsICdGcmknLCAnU2F0J107XG5cbiAgcHJldmlvdXNNb250aCgpIHtcbiAgICBpZiAodGhpcy5ldGhpb3BpYW5EYXRlLm1vbnRoID4gMSkge1xuICAgICAgdGhpcy5ldGhpb3BpYW5EYXRlLm1vbnRoLS07XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZXRoaW9waWFuRGF0ZS5tb250aCA9IDEzO1xuICAgICAgdGhpcy5ldGhpb3BpYW5EYXRlLnllYXItLTtcbiAgICB9XG4gICAgdGhpcy51cGRhdGVFdGhpb3BpYW5EYXRlKCk7XG4gIH1cblxuICBuZXh0TW9udGgoKSB7XG4gICAgaWYgKHRoaXMuZXRoaW9waWFuRGF0ZS5tb250aCA8IDEzKSB7XG4gICAgICB0aGlzLmV0aGlvcGlhbkRhdGUubW9udGgrKztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5ldGhpb3BpYW5EYXRlLm1vbnRoID0gMTtcbiAgICAgIHRoaXMuZXRoaW9waWFuRGF0ZS55ZWFyKys7XG4gICAgfVxuICAgIHRoaXMudXBkYXRlRXRoaW9waWFuRGF0ZSgpO1xuICB9XG5cbiAgZ2V0RGF5c0FycmF5KCk6IG51bWJlcltdIHtcbiAgICBjb25zdCBkYXlzSW5Nb250aCA9IHRoaXMuZXRoaW9waWFuRGF0ZS5tb250aCA9PT0gMTMgPyBcbiAgICAgICh0aGlzLmNhbGVuZGFyU2VydmljZVsnaXNFdGhpb3BpYW5MZWFwWWVhciddKHRoaXMuZXRoaW9waWFuRGF0ZS55ZWFyKSA/IDYgOiA1KSA6IFxuICAgICAgMzA7XG4gICAgXG4gICAgLy8gQ3JlYXRlIGFycmF5IHdpdGggcGFkZGluZyBmb3IgYWxpZ25tZW50XG4gICAgY29uc3QgZGF5czogbnVtYmVyW10gPSBbXTtcbiAgICBjb25zdCBmaXJzdERheU9mZnNldCA9IHRoaXMuZ2V0Rmlyc3REYXlPZmZzZXQoKTtcbiAgICBcbiAgICAvLyBBZGQgcGFkZGluZ1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZmlyc3REYXlPZmZzZXQ7IGkrKykge1xuICAgICAgZGF5cy5wdXNoKDApO1xuICAgIH1cbiAgICBcbiAgICAvLyBBZGQgZGF5c1xuICAgIGZvciAobGV0IGkgPSAxOyBpIDw9IGRheXNJbk1vbnRoOyBpKyspIHtcbiAgICAgIGRheXMucHVzaChpKTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIGRheXM7XG4gIH1cblxuICBnZXRGaXJzdERheU9mZnNldCgpOiBudW1iZXIge1xuICAgIC8vIFRoaXMgaXMgYSBzaW1wbGlmaWVkIHZlcnNpb24gLSB5b3UgbWlnaHQgd2FudCB0byBpbXBsZW1lbnQgcHJvcGVyIEV0aGlvcGlhbiBjYWxlbmRhciBkYXktb2Ytd2VlayBjYWxjdWxhdGlvblxuICAgIHJldHVybiAodGhpcy5ldGhpb3BpYW5EYXRlLm1vbnRoICogMikgJSA3O1xuICB9XG5cbiAgZ2V0RGF5Q2xhc3NlcyhkYXk6IG51bWJlcik6IHN0cmluZyB7XG4gICAgY29uc3QgYmFzZUNsYXNzZXMgPSAnaC04IHctOCByb3VuZGVkLWZ1bGwgZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgdGV4dC1zbSc7XG4gICAgY29uc3QgaXNTZWxlY3RlZCA9IGRheSA9PT0gdGhpcy5ldGhpb3BpYW5EYXRlLmRheTtcbiAgICBcbiAgICBpZiAoaXNTZWxlY3RlZCkge1xuICAgICAgcmV0dXJuIGAke2Jhc2VDbGFzc2VzfSBiZy1ibHVlLTYwMCB0ZXh0LXdoaXRlYDtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIGAke2Jhc2VDbGFzc2VzfSBob3ZlcjpiZy1ncmF5LTEwMCB0ZXh0LWdyYXktNzAwYDtcbiAgfVxuXG4gIHNlbGVjdERheShkYXk6IG51bWJlcikge1xuICAgIHRoaXMuZXRoaW9waWFuRGF0ZS5kYXkgPSBkYXk7XG4gICAgdGhpcy51cGRhdGVFdGhpb3BpYW5EYXRlKCk7XG4gICAgdGhpcy50b2dnbGVFdGhpb3BpYW5QaWNrZXIoKTtcbiAgfVxuXG4gIHNlbGVjdFRvZGF5KCkge1xuICAgIGNvbnN0IHRvZGF5ID0gdGhpcy5jYWxlbmRhclNlcnZpY2UudG9FdGhpb3BpYW4oe1xuICAgICAgeWVhcjogbmV3IERhdGUoKS5nZXRGdWxsWWVhcigpLFxuICAgICAgbW9udGg6IG5ldyBEYXRlKCkuZ2V0TW9udGgoKSArIDEsXG4gICAgICBkYXk6IG5ldyBEYXRlKCkuZ2V0RGF0ZSgpXG4gICAgfSk7XG4gICAgdGhpcy5ldGhpb3BpYW5EYXRlID0gdG9kYXk7XG4gICAgdGhpcy51cGRhdGVFdGhpb3BpYW5EYXRlKCk7XG4gICAgdGhpcy50b2dnbGVFdGhpb3BpYW5QaWNrZXIoKTtcbiAgfVxuXG4gIHVwZGF0ZUV0aGlvcGlhbkRhdGUoKSB7XG4gICAgdGhpcy5ldGhpb3BpYW5EYXRlQ2hhbmdlLmVtaXQodGhpcy5ldGhpb3BpYW5EYXRlKTtcbiAgICB0aGlzLmNvbnZlcnRUb0dyZWdvcmlhbigpO1xuICB9XG5cbiAgZm9ybWF0RXRoaW9waWFuRGF0ZUZvcklucHV0KGRhdGU6IEV0aGlvcGlhbkRhdGUpOiBzdHJpbmcge1xuICAgIGNvbnN0IG1vbnRoTmFtZSA9IHRoaXMuZXRoaW9waWFuTW9udGhzLmZpbmQobSA9PiBtLnZhbHVlID09PSBkYXRlLm1vbnRoKT8ubGFiZWwgfHwgJyc7XG4gICAgcmV0dXJuIGAke21vbnRoTmFtZX0gJHtkYXRlLmRheX0sICR7ZGF0ZS55ZWFyfWA7XG4gIH1cbn0gIl19