ngx-surveys
Version:
Angular 18+ survey / form builder
416 lines • 63.6 kB
JavaScript
import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';
import { Observable } from 'rxjs';
import { SurveyErrorStateMatcher } from '../index';
import { FormItem, SurveyFile } from '../form-item';
import * as _ from 'lodash';
//import { map } from 'rxjs/operators';
import * as WaveSurfer from 'wavesurfer.js';
import RecordRTC, { StereoAudioRecorder } from 'recordrtc';
import * as i0 from "@angular/core";
import * as i1 from "../../ngx-survey.service";
import * as i2 from "@angular/common";
import * as i3 from "@angular/material/button";
import * as i4 from "@angular/material/form-field";
import * as i5 from "@angular/material/icon";
import * as i6 from "@angular/material/progress-bar";
import * as i7 from "../../pipes/duration.pipe";
export class FormItemVoice extends FormItem {
}
export class FormItemVoiceComponent {
constructor(service, zone) {
this.service = service;
this.zone = zone;
this.editable = true;
this.changes = new EventEmitter();
this.matcher = new SurveyErrorStateMatcher();
this.allowDelete = true;
this.uploadedFilesNumber = 0;
this.uploadFilesNumber = 0;
this.timeLimit = 120;
this.isEdge = navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator['msSaveOrOpenBlob'] || !!navigator['msSaveBlob']);
this.isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
this.controlIcon = 'record-circle';
}
ngOnInit() {
if (this.item.value) {
this.file = _.extend(new SurveyFile(), this.item.value);
if (this.file?.url) {
this.hasRecord = true;
}
}
this.matcher.item = this.item;
this.service;
this.zone;
Observable;
}
ngAfterViewInit() {
// set the initial state of the video
let audio = this.audio.nativeElement;
audio.muted = false;
audio.controls = true;
audio.autoplay = false;
if (this.file?.url) {
this.hasRecord = true;
this.wavesurfer = WaveSurfer.create({
container: this.waveformElement.nativeElement,
height: 190,
waveColor: '#d4d9dd',
progressColor: '#555',
normalize: true,
barHeight: 8,
cursorWidth: 1,
cursorColor: '#d9d9d9'
});
this.wavesurfer.load(this.file.url);
this.wavesurfer.on('ready', () => {
console.log(this.wavesurfer);
this.zone.run(() => {
if (this.file) {
this.file.duration = this.wavesurfer.getDuration();
this.duration = this.file.duration * 1000;
this.wavesurferPlay = false;
}
});
});
this.wavesurfer.on('play', () => {
this.zone.run(() => {
this.wavesurferPlay = true;
});
});
this.wavesurfer.on('pause', () => {
this.zone.run(() => {
this.wavesurferPlay = false;
});
});
}
}
ngOnChanges() {
this.matcher.item = this.item;
}
checkRequired(placeholder) {
if (placeholder === 'Required') {
return true;
}
}
onValueChanges(item) {
this.changes.emit(item);
}
clear() {
this.file = undefined;
this.fileObject = undefined;
}
/*
uploadFiles(files: SurveyFile[]) {
console.log(files);
if(!files.length){
return;
}
files.forEach(file=>{
file.uploading=true;
file.progressSubject = new Observable(observer => {
file.progressObserver = observer
});
file.progressSubject.subscribe(
data => {
this.zone.run(()=>{
file.progressValue=data;
//console.log(file);
if (file.url){
this.item.value=this.files.filter(f=>f.url).map(f=>{
const obj=new SurveyFile;
obj.url=f.url;
obj.name=f.name;
obj.mime=f.mime;
return obj;
});
console.log(this.item);
this.changes.emit(this.item);
}
})
}
);
})
this.service.onFilesSelected.next(files);
this.files=_.union(this.files, files);
this.isFilesUploading = true;
this.uploadFilesNumber=files.length;
this.uploadedFilesNumber=1;
}
*/
onCloseClick() {
//this.dialogRef.close();
}
startRecording() {
let mediaConstraints = {
audio: this.isEdge ? true : {
echoCancellation: false
}
};
this.blobSize = 0;
//window['AudioContext'] = window['AudioContext'] || window['webkitAudioContext'];
navigator.mediaDevices
.getUserMedia(mediaConstraints)
.then(this.successCallback.bind(this), this.errorCallback.bind(this));
}
errorCallback(stream) {
//console.log(stream);
}
successCallback(stream) {
const microphone = stream;
if (this.isSafari) {
this.audio.muted = true;
this.audio.srcObject = microphone;
}
//console.log(stream);
//let audio: HTMLAudioElement = this.audio.nativeElement;
let options = {
mimeType: 'audio/webm',
numberOfAudioChannels: this.isEdge ? 1 : 2,
checkForInactiveTracks: true,
bufferSize: 16384,
elementClass: 'multi-streams-mixer'
};
this.stream = stream;
if (this.isSafari || this.isEdge) {
options['recorderType'] = StereoAudioRecorder;
}
if (navigator.platform && navigator.platform.toString().toLowerCase().indexOf('win') === -1) {
options['sampleRate'] = 48000; // or 44100 or remove this line for default
}
if (this.isSafari) {
options['sampleRate'] = 44100;
options['bufferSize'] = 4096;
options['numberOfAudioChannels'] = 2;
options['mimeType'] = 'audio/wav';
}
if (this.recordRTC) {
this.recordRTC.destroy();
this.recordRTC = null;
}
this.recordRTC = new RecordRTC(stream, options);
this.recordRTC.startRecording();
this.audio.srcObject = stream;
//audio.src = this.recordRTC.toURL();
this.duration = 0;
this.durationInterval = setInterval(() => {
//console.log(this.recordRTC.getState(), this.recordRTC);
if (this.recordRTC && this.recordRTC.getState() === 'recording') {
this.duration++;
//this.cd.detectChanges();
}
else {
//clearInterval(durationInterval);
}
}, 1000);
//console.log(this.recordRTC);
this.toggleControls();
this.recordingInprogress = true;
}
toggleControls() {
let audio = this.audio.nativeElement;
audio.muted = !audio.muted;
audio.controls = !audio.controls;
audio.autoplay = !audio.autoplay;
}
stopRecording() {
let recordRTC = this.recordRTC;
recordRTC.stopRecording(this.processAudio.bind(this));
let stream = this.stream;
stream.getTracks().forEach(track => track.stop());
this.recordingInprogress = false;
if (this.durationInterval) {
clearInterval(this.durationInterval);
}
}
processAudio(audioVideoWebMURL) {
let audio = this.audio.nativeElement;
let recordRTC = this.recordRTC;
let fileReader = new FileReader();
fileReader;
audio.src = audioVideoWebMURL;
this.toggleControls();
this.recordedBlob = recordRTC.getBlob();
if (!this.recordedBlob) {
this.hasRecord = false;
return;
}
let ext = 'mp3';
if (this.recordedBlob.type) {
ext = this.recordedBlob.type.split('/')[1];
ext = ext.split(';')[0];
}
this.recordedBlob.name = 'audio.' + ext;
if (!this.file) {
this.file = new SurveyFile();
this.file.name = 'audio.' + ext;
}
//this.file.workflow='audio';
this.file.mime = this.recordedBlob.type;
fileReader.onload = (event) => {
if (this.file && event?.target) {
this.file.src = event.target['result'];
this.uploadFile(this.file);
}
};
fileReader.readAsArrayBuffer(this.recordedBlob);
this.file.size = this.recordedBlob.size;
this.zone.run(() => {
this.hasRecord = true;
});
//console.log(this.recordedBlob);
recordRTC.getDataURL(dataURL => {
//console.log(audioVideoWebMURL, dataURL, audio.src);
this.wavesurfer = WaveSurfer.create({
container: this.waveformElement.nativeElement,
height: 190,
waveColor: '#d4d9dd',
progressColor: '#555',
normalize: true,
barHeight: 8,
cursorWidth: 1,
cursorColor: '#d9d9d9'
});
this.wavesurfer.loadBlob(this.recordedBlob);
this.wavesurfer.on('ready', () => {
//console.log(this.wavesurfer.getDuration());
if (this.file) {
this.file.duration = this.wavesurfer.getDuration();
this.duration = this.file.duration * 1000;
this.wavesurferPlay = false;
}
});
this.wavesurfer.on('play', () => {
this.zone.run(() => {
this.wavesurferPlay = true;
});
});
this.wavesurfer.on('pause', () => {
this.zone.run(() => {
this.wavesurferPlay = false;
});
});
});
return this.file;
}
uploadFile(file) {
file.uploading = true;
file.progressSubject = new Observable(observer => {
file.progressObserver = observer;
});
this.item.busy = true;
file.progressSubject.subscribe(data => {
this.zone.run(() => {
file.progressValue = data;
//console.log(file);
if (file.url) {
const obj = new SurveyFile;
obj.url = file.url;
obj.name = file.name;
obj.mime = file.mime;
this.item.value = obj;
console.log(this.item);
this.item.busy = false;
this.changes.emit(this.item);
}
});
}, err => {
this.item.busy = false;
});
this.service.onFilesSelected.next([file]);
this.file = file;
}
play() {
if (this.wavesurfer) {
this.wavesurfer.play();
}
}
pause() {
if (this.wavesurfer) {
this.wavesurfer.pause();
}
}
togglePlay() {
if (this.wavesurfer) {
if (this.wavesurferPlay) {
this.pause();
this.controlIcon = 'play-circle-thin';
}
else {
this.play();
this.controlIcon = 'pause-circle-thin';
}
}
}
toggleRecording() {
//console.log('CLICKED');
if (this.recordingInprogress) {
this.stopRecording();
this.controlIcon = 'play-circle-thin';
}
else {
this.startRecording();
this.controlIcon = 'record-round';
}
}
clearBlob() {
this.file = undefined;
this.recordedBlob = null;
this.hasRecord = false;
if (this.wavesurfer) {
this.wavesurfer.destroy();
}
if (this.recordRTC) {
//this.recordRTC.destroy()
}
this.controlIcon = 'record-circle';
this.item.value = undefined;
this.changes.emit(this.item);
}
download() {
this.recordRTC.save('audio.webm');
}
onSave() {
//this.stopRecording();
}
ngOnDestroy() {
if (this.wavesurfer) {
this.wavesurfer.destroy();
}
if (this.recordRTC && this.recordRTC.state === 'recording') {
this.recordRTC.stopRecording();
this.recordRTC.clearRecordedData();
//this.stopRecording();
}
if (this.recordRTC) {
this.recordRTC.destroy();
}
if (this.stream) {
this.stream.getTracks().forEach(track => track.stop());
}
if (this.durationInterval) {
this.duration = 0;
clearInterval(this.durationInterval);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: FormItemVoiceComponent, deps: [{ token: i1.NgxSurveyService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.12", type: FormItemVoiceComponent, selector: "app-form-item-voice", inputs: { item: "item", editable: "editable" }, outputs: { changes: "changes" }, viewQueries: [{ propertyName: "audio", first: true, predicate: ["audio"], descendants: true, static: true }, { propertyName: "waveformElement", first: true, predicate: ["waveform"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"form-group\">\n <div class=\"col-xs-12 voice-recorder\">\n <div *ngIf=\"item.label\" class=\"voice-recorder-title label\" [ngClass]=\"{'has-error':item.errors && item.errors.length}\">{{item.label}} <span *ngIf=\"item.required\" class=\"required-asterix\">*</span></div>\n <div class=\"audio-recorder\">\n <audio #audio class=\"audio\" style=\"display:none;\" [src]=\"file?.url\"></audio>\n <div class=\"main-screen\">\n <div #waveform class=\"waveform\" [ngClass]=\"{hidden:recordingInprogress || !hasRecord}\"></div>\n <ng-container *ngIf=\"!recordingInprogress && hasRecord; else startScreen\">\n <button mat-button class=\"main-screen-button\" (click)=\"togglePlay()\" type=\"button\">\n <mat-icon class=\"main-screen-icon-big\">{{this.wavesurferPlay ? 'pause_circle_outline' : 'play_circle_outline'}}</mat-icon>\n </button>\n\n <a mat-button class=\"main-screen-button-aside download-btn\" *ngIf=\"item.value && item.value.url\" [href]=\"item.value.url\" target=\"_blank\" title=\"Dowload Record\">\n <mat-icon class=\"main-screen-icon-small\">download</mat-icon>\n </a>\n <button mat-button class=\"main-screen-button-aside delete-btn\" title=\"Delete Record\" (click)=\"clearBlob()\" *ngIf=\"editable\" type=\"button\">\n <mat-icon class=\"main-screen-icon-small\">cancel</mat-icon>\n </button>\n <mat-progress-bar mode=\"determinate\" *ngIf=\"file && file.uploading\" [value]=\"file.progressValue\"></mat-progress-bar>\n </ng-container>\n\n </div>\n\n <ng-template #startScreen>\n <div class=\"start-screen\">\n <button mat-button class=\"start-screen-button\" (click)=\"toggleRecording()\" [disabled]=\"!editable\" type=\"button\">\n <mat-icon class=\"start-screen-icon\" >{{recordingInprogress ? 'mic':'mic_none'}}</mat-icon>\n <div *ngIf=\"!recordingInprogress && !hasRecord\" class=\"start-screen-text\">Tap to record audio</div>\n <div *ngIf=\"recordingInprogress\" class=\"start-screen-text\">\n {{duration | duration:'seconds'}}\n / {{timeLimit - duration | duration:'seconds'}}\n </div>\n </button>\n </div>\n </ng-template>\n </div>\n <mat-error *ngIf=\"item.errors && item.errors.length\">\n <div *ngFor=\"let error of item.errors\">{{error.message}}</div>\n </mat-error>\n <mat-hint align=\"start\" *ngIf=\"!(item.errors && item.errors.length)\"><strong>{{item.hint}}</strong> </mat-hint>\n </div>\n</div>\n", styles: [".mat-mdc-form-field{width:100%}.audio-recorder{height:192px;background-color:#f9f9f9;border:1px solid #efefef;border-radius:4px}.start-screen{display:flex;align-items:center;justify-content:center;height:100%;position:absolute;top:0;width:100%}.start-screen-button{height:100%;width:100%}.start-screen-icon{font-size:6rem;color:#9b0000;width:96px;height:96px}.start-screen-text{color:#919191;margin-top:15px}.main-screen{position:relative;height:100%}.main-screen-button{position:absolute;top:50%;left:50%;transform:translate3d(-50%,-50%,0);padding:0;z-index:3;border-radius:50%}.main-screen-button-aside{position:absolute;bottom:15px;right:15px;min-width:48px;padding:0;border-radius:50%;z-index:3}.main-screen-button-aside.delete-btn .mat-icon{color:#c72939}.main-screen-button-aside.download-btn{left:15px;right:auto}.main-screen-button-aside.download-btn .mat-icon{color:#3f51b5}.main-screen-icon-big{font-size:6rem;color:#10027b;width:96px;height:96px}.main-screen-icon-small{font-size:3rem;color:#b1b1b1;width:48px;height:48px}#waveform{height:100%!important;background-color:#f9f9f9;display:block}#waveform.hidden{display:block}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.MatAnchor, selector: "a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i4.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i6.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "pipe", type: i7.DurationPipe, name: "duration" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: FormItemVoiceComponent, decorators: [{
type: Component,
args: [{ selector: 'app-form-item-voice', template: "<div class=\"form-group\">\n <div class=\"col-xs-12 voice-recorder\">\n <div *ngIf=\"item.label\" class=\"voice-recorder-title label\" [ngClass]=\"{'has-error':item.errors && item.errors.length}\">{{item.label}} <span *ngIf=\"item.required\" class=\"required-asterix\">*</span></div>\n <div class=\"audio-recorder\">\n <audio #audio class=\"audio\" style=\"display:none;\" [src]=\"file?.url\"></audio>\n <div class=\"main-screen\">\n <div #waveform class=\"waveform\" [ngClass]=\"{hidden:recordingInprogress || !hasRecord}\"></div>\n <ng-container *ngIf=\"!recordingInprogress && hasRecord; else startScreen\">\n <button mat-button class=\"main-screen-button\" (click)=\"togglePlay()\" type=\"button\">\n <mat-icon class=\"main-screen-icon-big\">{{this.wavesurferPlay ? 'pause_circle_outline' : 'play_circle_outline'}}</mat-icon>\n </button>\n\n <a mat-button class=\"main-screen-button-aside download-btn\" *ngIf=\"item.value && item.value.url\" [href]=\"item.value.url\" target=\"_blank\" title=\"Dowload Record\">\n <mat-icon class=\"main-screen-icon-small\">download</mat-icon>\n </a>\n <button mat-button class=\"main-screen-button-aside delete-btn\" title=\"Delete Record\" (click)=\"clearBlob()\" *ngIf=\"editable\" type=\"button\">\n <mat-icon class=\"main-screen-icon-small\">cancel</mat-icon>\n </button>\n <mat-progress-bar mode=\"determinate\" *ngIf=\"file && file.uploading\" [value]=\"file.progressValue\"></mat-progress-bar>\n </ng-container>\n\n </div>\n\n <ng-template #startScreen>\n <div class=\"start-screen\">\n <button mat-button class=\"start-screen-button\" (click)=\"toggleRecording()\" [disabled]=\"!editable\" type=\"button\">\n <mat-icon class=\"start-screen-icon\" >{{recordingInprogress ? 'mic':'mic_none'}}</mat-icon>\n <div *ngIf=\"!recordingInprogress && !hasRecord\" class=\"start-screen-text\">Tap to record audio</div>\n <div *ngIf=\"recordingInprogress\" class=\"start-screen-text\">\n {{duration | duration:'seconds'}}\n / {{timeLimit - duration | duration:'seconds'}}\n </div>\n </button>\n </div>\n </ng-template>\n </div>\n <mat-error *ngIf=\"item.errors && item.errors.length\">\n <div *ngFor=\"let error of item.errors\">{{error.message}}</div>\n </mat-error>\n <mat-hint align=\"start\" *ngIf=\"!(item.errors && item.errors.length)\"><strong>{{item.hint}}</strong> </mat-hint>\n </div>\n</div>\n", styles: [".mat-mdc-form-field{width:100%}.audio-recorder{height:192px;background-color:#f9f9f9;border:1px solid #efefef;border-radius:4px}.start-screen{display:flex;align-items:center;justify-content:center;height:100%;position:absolute;top:0;width:100%}.start-screen-button{height:100%;width:100%}.start-screen-icon{font-size:6rem;color:#9b0000;width:96px;height:96px}.start-screen-text{color:#919191;margin-top:15px}.main-screen{position:relative;height:100%}.main-screen-button{position:absolute;top:50%;left:50%;transform:translate3d(-50%,-50%,0);padding:0;z-index:3;border-radius:50%}.main-screen-button-aside{position:absolute;bottom:15px;right:15px;min-width:48px;padding:0;border-radius:50%;z-index:3}.main-screen-button-aside.delete-btn .mat-icon{color:#c72939}.main-screen-button-aside.download-btn{left:15px;right:auto}.main-screen-button-aside.download-btn .mat-icon{color:#3f51b5}.main-screen-icon-big{font-size:6rem;color:#10027b;width:96px;height:96px}.main-screen-icon-small{font-size:3rem;color:#b1b1b1;width:48px;height:48px}#waveform{height:100%!important;background-color:#f9f9f9;display:block}#waveform.hidden{display:block}\n"] }]
}], ctorParameters: () => [{ type: i1.NgxSurveyService }, { type: i0.NgZone }], propDecorators: { audio: [{
type: ViewChild,
args: ['audio', { static: true }]
}], waveformElement: [{
type: ViewChild,
args: ['waveform', { static: true }]
}], item: [{
type: Input
}], editable: [{
type: Input
}], changes: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybS1pdGVtLXZvaWNlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zdXJ2ZXlzL3NyYy9saWIvZm9ybS1pdGVtL2Zvcm0taXRlbS12b2ljZS9mb3JtLWl0ZW0tdm9pY2UuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXN1cnZleXMvc3JjL2xpYi9mb3JtLWl0ZW0vZm9ybS1pdGVtLXZvaWNlL2Zvcm0taXRlbS12b2ljZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFVLEtBQUssRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUF5QixTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDakgsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNsQyxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDbkQsT0FBTyxFQUFFLFFBQVEsRUFBa0IsVUFBVSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3BFLE9BQU8sS0FBSyxDQUFDLE1BQU0sUUFBUSxDQUFDO0FBRTVCLHVDQUF1QztBQUN2QyxPQUFPLEtBQUssVUFBVSxNQUFNLGVBQWUsQ0FBQztBQUM1QyxPQUFPLFNBQVMsRUFBRSxFQUFFLG1CQUFtQixFQUFFLE1BQU0sV0FBVyxDQUFDOzs7Ozs7Ozs7QUFFM0QsTUFBTSxPQUFPLGFBQWMsU0FBUSxRQUFRO0NBSTFDO0FBT0QsTUFBTSxPQUFPLHNCQUFzQjtJQW1DL0IsWUFDWSxPQUF5QixFQUN6QixJQUFZO1FBRFosWUFBTyxHQUFQLE9BQU8sQ0FBa0I7UUFDekIsU0FBSSxHQUFKLElBQUksQ0FBUTtRQS9CZixhQUFRLEdBQVUsSUFBSSxDQUFDO1FBQ3RCLFlBQU8sR0FBRyxJQUFJLFlBQVksRUFBaUIsQ0FBQztRQUN0RCxZQUFPLEdBQUcsSUFBSSx1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LE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBQ0ssZUFBZTtzQkFBdkQsU0FBUzt1QkFBQyxVQUFVLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUU5QixJQUFJO3NCQUFaLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDSSxPQUFPO3NCQUFoQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgTmdab25lLCBBZnRlclZpZXdJbml0LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFN1cnZleUVycm9yU3RhdGVNYXRjaGVyIH0gZnJvbSAnLi4vaW5kZXgnO1xuaW1wb3J0IHsgRm9ybUl0ZW0sIEZvcm1JdGVtV2lkZ2V0LCBTdXJ2ZXlGaWxlIH0gZnJvbSAnLi4vZm9ybS1pdGVtJztcbmltcG9ydCAqIGFzIF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IE5neFN1cnZleVNlcnZpY2UgfSBmcm9tICcuLi8uLi9uZ3gtc3VydmV5LnNlcnZpY2UnO1xuLy9pbXBvcnQgeyBtYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgKiBhcyBXYXZlU3VyZmVyIGZyb20gJ3dhdmVzdXJmZXIuanMnO1xuaW1wb3J0IFJlY29yZFJUQywgeyBTdGVyZW9BdWRpb1JlY29yZGVyIH0gZnJvbSAncmVjb3JkcnRjJztcblxuZXhwb3J0IGNsYXNzIEZvcm1JdGVtVm9pY2UgZXh0ZW5kcyBGb3JtSXRlbSB7XG4gICAgdmFsdWU/OiBTdXJ2ZXlGaWxlO1xuICAgIGFyZWFMYWJlbDogc3RyaW5nO1xuICAgIGJ1dHRvbkxhYmVsOiBzdHJpbmc7XG59XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnYXBwLWZvcm0taXRlbS12b2ljZScsXG4gICAgdGVtcGxhdGVVcmw6ICcuL2Zvcm0taXRlbS12b2ljZS5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJy4vZm9ybS1pdGVtLXZvaWNlLmNvbXBvbmVudC5zY3NzJ11cbiAgfSlcbmV4cG9ydCBjbGFzcyBGb3JtSXRlbVZvaWNlQ29tcG9uZW50IGltcGxlbWVudHMgRm9ybUl0ZW1XaWRnZXQsIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XG5cbiAgICBAVmlld0NoaWxkKCdhdWRpbycsIHsgc3RhdGljOiB0cnVlIH0pIGF1ZGlvOiBhbnk7XG4gICAgQFZpZXdDaGlsZCgnd2F2ZWZvcm0nLCB7IHN0YXRpYzogdHJ1ZSB9KSB3YXZlZm9ybUVsZW1lbnQ6IGFueTtcblxuICAgIEBJbnB1dCgpIGl0ZW06IEZvcm1JdGVtVm9pY2U7XG4gICAgQElucHV0KCkgZWRpdGFibGU6IGJvb2xlYW49dHJ1ZTtcbiAgICBAT3V0cHV0KCkgY2hhbmdlcyA9IG5ldyBFdmVudEVtaXR0ZXI8Rm9ybUl0ZW1Wb2ljZT4oKTtcbiAgICBtYXRjaGVyID0gbmV3IFN1cnZleUVycm9yU3RhdGVNYXRjaGVyKCk7XG5cbiAgICBwdWJsaWMgZmlsZU9iamVjdDogYW55O1xuXG4gICAgcHVibGljIGZpbGU6IHVuZGVmaW5lZCB8IFN1cnZleUZpbGU7XG5cbiAgICBwdWJsaWMgaXNGaWxlc1VwbG9hZGluZzogYm9vbGVhbjtcbiAgICBwdWJsaWMgYWxsb3dEZWxldGU6IGJvb2xlYW49dHJ1ZTtcbiAgICBwdWJsaWMgdXBsb2FkZWRGaWxlc051bWJlcjogbnVtYmVyPTA7XG4gICAgcHVibGljIHVwbG9hZEZpbGVzTnVtYmVyOiBudW1iZXI9MDtcblxuICAgIHB1YmxpYyBzdHJlYW06YW55O1xuICAgIHB1YmxpYyByZWNvcmRSVEM6YW55O1xuICAgIHB1YmxpYyByZWNvcmRlZEJsb2I6IGFueTtcbiAgICBwdWJsaWMgcmVjb3JkaW5nSW5wcm9ncmVzczogYm9vbGVhbjtcbiAgICBwdWJsaWMgYmxvYlNpemU6bnVtYmVyO1xuICAgIHB1YmxpYyBoYXNSZWNvcmQ6Ym9vbGVhbjtcbiAgICBwdWJsaWMgZHVyYXRpb246bnVtYmVyO1xuICAgIHB1YmxpYyB0aW1lTGltaXQ6bnVtYmVyPTEyMDtcbiAgICBwdWJsaWMgd2F2ZXN1cmZlcjphbnk7XG4gICAgcHVibGljIHdhdmVzdXJmZXJQbGF5OmJvb2xlYW47XG4gICAgcHVibGljIGlzRWRnZTogYm9vbGVhbiA9IG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignRWRnZScpICE9PSAtMSAmJiAoISFuYXZpZ2F0b3JbJ21zU2F2ZU9yT3BlbkJsb2InXSB8fCAhIW5hdmlnYXRvclsnbXNTYXZlQmxvYiddKTtcbiAgICBwdWJsaWMgaXNTYWZhcmk6IGJvb2xlYW4gPSAvXigoPyFjaHJvbWV8YW5kcm9pZCkuKSpzYWZhcmkvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgIHB1YmxpYyBkdXJhdGlvbkludGVydmFsO1xuICAgIHB1YmxpYyBjb250cm9sSWNvbjpzdHJpbmcgPSAncmVjb3JkLWNpcmNsZSc7XG5cblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwcml2YXRlIHNlcnZpY2U6IE5neFN1cnZleVNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgem9uZTogTmdab25lLFxuICAgICkgeyB9XG5cblxuICAgIG5nT25Jbml0KCkge1xuICAgICAgICBpZiAodGhpcy5pdGVtLnZhbHVlKXtcbiAgICAgICAgICAgIHRoaXMuZmlsZT1fLmV4dGVuZChuZXcgU3VydmV5RmlsZSgpLCB0aGlzLml0ZW0udmFsdWUpO1xuICAgICAgICAgICAgaWYgKHRoaXMuZmlsZT8udXJsKXtcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1JlY29yZD10cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMubWF0Y2hlci5pdGVtPXRoaXMuaXRlbTtcbiAgICAgICAgdGhpcy5zZXJ2aWNlO1xuICAgICAgICB0aGlzLnpvbmU7XG4gICAgICAgIE9ic2VydmFibGU7XG4gICAgfVxuXG4gICAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgICAgICAvLyBzZXQgdGhlIGluaXRpYWwgc3RhdGUgb2YgdGhlIHZpZGVvXG4gICAgICAgIGxldCBhdWRpbzpIVE1MQXVkaW9FbGVtZW50ID0gdGhpcy5hdWRpby5uYXRpdmVFbGVtZW50O1xuICAgICAgICBhdWRpby5tdXRlZCA9IGZhbHNlO1xuICAgICAgICBhdWRpby5jb250cm9scyA9IHRydWU7XG4gICAgICAgIGF1ZGlvLmF1dG9wbGF5ID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKHRoaXMuZmlsZT8udXJsKXtcbiAgICAgICAgICAgIHRoaXMuaGFzUmVjb3JkPXRydWU7XG4gICAgICAgICAgICB0aGlzLndhdmVzdXJmZXIgPSBXYXZlU3VyZmVyLmNyZWF0ZSh7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyOiB0aGlzLndhdmVmb3JtRWxlbWVudC5uYXRpdmVFbGVtZW50LFxuICAgICAgICAgICAgICAgIGhlaWdodDogMTkwLFxuICAgICAgICAgICAgICAgIHdhdmVDb2xvcjogJyNkNGQ5ZGQnLFxuICAgICAgICAgICAgICAgIHByb2dyZXNzQ29sb3I6ICcjNTU1JyxcbiAgICAgICAgICAgICAgICBub3JtYWxpemU6IHRydWUsXG4gICAgICAgICAgICAgICAgYmFySGVpZ2h0OiA4LFxuICAgICAgICAgICAgICAgIGN1cnNvcldpZHRoOiAxLFxuICAgICAgICAgICAgICAgIGN1cnNvckNvbG9yOiAnI2Q5ZDlkOSdcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy53YXZlc3VyZmVyLmxvYWQodGhpcy5maWxlLnVybCk7XG5cbiAgICAgICAgICAgIHRoaXMud2F2ZXN1cmZlci5vbigncmVhZHknLCAoKT0+e1xuICAgICAgICAgICAgY29uc29sZS5sb2codGhpcy53YXZlc3VyZmVyKTtcbiAgICAgICAgICAgICAgICB0aGlzLnpvbmUucnVuKCgpPT57XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmZpbGUpe1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maWxlLmR1cmF0aW9uPXRoaXMud2F2ZXN1cmZlci5nZXREdXJhdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kdXJhdGlvbj10aGlzLmZpbGUuZHVyYXRpb24qMTAwMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud2F2ZXN1cmZlclBsYXk9ZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMud2F2ZXN1cmZlci5vbigncGxheScsICgpPT57XG4gICAgICAgICAgICAgICAgdGhpcy56b25lLnJ1bigoKT0+e1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndhdmVzdXJmZXJQbGF5PXRydWU7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy53YXZlc3VyZmVyLm9uKCdwYXVzZScsICgpPT57XG4gICAgICAgICAgICAgICAgdGhpcy56b25lLnJ1bigoKT0+e1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndhdmVzdXJmZXJQbGF5PWZhbHNlO1xuICAgICAgICAgICAgICAgIH0pXG5cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmdPbkNoYW5nZXMoKSB7XG4gICAgICAgIHRoaXMubWF0Y2hlci5pdGVtPXRoaXMuaXRlbTtcbiAgICB9XG5cbiAgICBjaGVja1JlcXVpcmVkKHBsYWNlaG9sZGVyKSB7XG4gICAgICAgIGlmIChwbGFjZWhvbGRlciA9PT0gJ1JlcXVpcmVkJykge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvblZhbHVlQ2hhbmdlcyhpdGVtKSB7XG4gICAgICAgIHRoaXMuY2hhbmdlcy5lbWl0KGl0ZW0pO1xuICAgIH1cblxuICAgIGNsZWFyKCl7XG4gICAgICAgIHRoaXMuZmlsZT11bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuZmlsZU9iamVjdD11bmRlZmluZWQ7XG4gICAgfVxuLypcbiAgICB1cGxvYWRGaWxlcyhmaWxlczogU3VydmV5RmlsZVtdKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGZpbGVzKTtcbiAgICAgICAgaWYoIWZpbGVzLmxlbmd0aCl7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZmlsZXMuZm9yRWFjaChmaWxlPT57XG4gICAgICAgICAgICBmaWxlLnVwbG9hZGluZz10cnVlO1xuICAgICAgICAgICAgZmlsZS5wcm9ncmVzc1N1YmplY3QgPSBuZXcgT2JzZXJ2YWJsZShvYnNlcnZlciA9PiB7XG4gICAgICAgICAgICAgICAgZmlsZS5wcm9ncmVzc09ic2VydmVyID0gb2JzZXJ2ZXJcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZmlsZS5wcm9ncmVzc1N1YmplY3Quc3Vic2NyaWJlKFxuICAgICAgICAgICAgICBkYXRhID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnpvbmUucnVuKCgpPT57XG4gICAgICAgICAgICAgICAgICAgIGZpbGUucHJvZ3Jlc3NWYWx1ZT1kYXRhO1xuICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUubG9nKGZpbGUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZmlsZS51cmwpe1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pdGVtLnZhbHVlPXRoaXMuZmlsZXMuZmlsdGVyKGY9PmYudXJsKS5tYXAoZj0+e1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9iaj1uZXcgU3VydmV5RmlsZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYmoudXJsPWYudXJsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9iai5uYW1lPWYubmFtZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYmoubWltZT1mLm1pbWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2codGhpcy5pdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2hhbmdlcy5lbWl0KHRoaXMuaXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICB9KVxuICAgICAgICB0aGlzLnNlcnZpY2Uub25GaWxlc1NlbGVjdGVkLm5leHQoZmlsZXMpO1xuICAgICAgICB0aGlzLmZpbGVzPV8udW5pb24odGhpcy5maWxlcywgZmlsZXMpO1xuXG4gICAgICAgIHRoaXMuaXNGaWxlc1VwbG9hZGluZyA9IHRydWU7XG5cbiAgICAgICAgdGhpcy51cGxvYWRGaWxlc051bWJlcj1maWxlcy5sZW5ndGg7XG4gICAgICAgIHRoaXMudXBsb2FkZWRGaWxlc051bWJlcj0xO1xuICAgIH1cbiAgICAqL1xuXG4gICAgb25DbG9zZUNsaWNrKCk6IHZvaWQge1xuICAgICAgICAvL3RoaXMuZGlhbG9nUmVmLmNsb3NlKCk7XG4gICAgfVxuXG4gICAgc3RhcnRSZWNvcmRpbmcoKSB7XG4gICAgICAgIGxldCBtZWRpYUNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgYXVkaW86IHRoaXMuaXNFZGdlID8gdHJ1ZSA6IHtcbiAgICAgICAgICAgICAgICBlY2hvQ2FuY2VsbGF0aW9uOiBmYWxzZVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmJsb2JTaXplPTA7XG4gICAgICAgIC8vd2luZG93WydBdWRpb0NvbnRleHQnXSA9IHdpbmRvd1snQXVkaW9Db250ZXh0J10gfHwgd2luZG93Wyd3ZWJraXRBdWRpb0NvbnRleHQnXTtcbiAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlc1xuICAgICAgICAgIC5nZXRVc2VyTWVkaWEobWVkaWFDb25zdHJhaW50cylcbiAgICAgICAgICAudGhlbih0aGlzLnN1Y2Nlc3NDYWxsYmFjay5iaW5kKHRoaXMpLCB0aGlzLmVycm9yQ2FsbGJhY2suYmluZCh0aGlzKSk7XG4gICAgfVxuXG4gICAgZXJyb3JDYWxsYmFjayhzdHJlYW06IE1lZGlhU3RyZWFtKSB7XG4gICAgICAgIC8vY29uc29sZS5sb2coc3RyZWFtKTtcbiAgICB9XG5cbiAgICBzdWNjZXNzQ2FsbGJhY2soc3RyZWFtOiBNZWRpYVN0cmVhbSkge1xuICAgICAgICBjb25zdCBtaWNyb3Bob25lPXN0cmVhbTtcblxuICAgICAgICBpZih0aGlzLmlzU2FmYXJpKSB7XG4gICAgICAgICAgICB0aGlzLmF1ZGlvLm11dGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuYXVkaW8uc3JjT2JqZWN0ID0gbWljcm9waG9uZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vY29uc29sZS5sb2coc3RyZWFtKTtcbiAgICAgICAgLy9sZXQgYXVkaW86IEhUTUxBdWRpb0VsZW1lbnQgPSB0aGlzLmF1ZGlvLm5hdGl2ZUVsZW1lbnQ7XG4gICAgICAgIGxldCBvcHRpb25zID0ge1xuICAgICAgICAgICAgbWltZVR5cGU6ICdhdWRpby93ZWJtJyxcbiAgICAgICAgICAgIG51bWJlck9mQXVkaW9DaGFubmVsczogdGhpcy5pc0VkZ2UgPyAxIDogMixcbiAgICAgICAgICAgIGNoZWNrRm9ySW5hY3RpdmVUcmFja3M6IHRydWUsXG4gICAgICAgICAgICBidWZmZXJTaXplOiAxNjM4NCxcbiAgICAgICAgICAgIGVsZW1lbnRDbGFzczogJ211bHRpLXN0cmVhbXMtbWl4ZXInXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuXG4gICAgICAgIGlmKHRoaXMuaXNTYWZhcmkgfHwgdGhpcy5pc0VkZ2UpIHtcbiAgICAgICAgICAgIG9wdGlvbnNbJ3JlY29yZGVyVHlwZSddID0gU3RlcmVvQXVkaW9SZWNvcmRlcjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKG5hdmlnYXRvci5wbGF0Zm9ybSAmJiBuYXZpZ2F0b3IucGxhdGZvcm0udG9TdHJpbmcoKS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ3dpbicpID09PSAtMSkge1xuICAgICAgICAgICAgb3B0aW9uc1snc2FtcGxlUmF0ZSddID0gNDgwMDA7IC8vIG9yIDQ0MTAwIG9yIHJlbW92ZSB0aGlzIGxpbmUgZm9yIGRlZmF1bHRcbiAgICAgICAgfVxuICAgICAgICBpZih0aGlzLmlzU2FmYXJpKSB7XG4gICAgICAgICAgICBvcHRpb25zWydzYW1wbGVSYXRlJ10gPSA0NDEwMDtcbiAgICAgICAgICAgIG9wdGlvbnNbJ2J1ZmZlclNpemUnXSA9IDQwOTY7XG4gICAgICAgICAgICBvcHRpb25zWydudW1iZXJPZkF1ZGlvQ2hhbm5lbHMnXSA9IDI7XG4gICAgICAgICAgICBvcHRpb25zWydtaW1lVHlwZSddPSdhdWRpby93YXYnO1xuICAgICAgICB9XG4gICAgICAgIGlmKHRoaXMucmVjb3JkUlRDKSB7XG4gICAgICAgICAgICB0aGlzLnJlY29yZFJUQy5kZXN0cm95KCk7XG4gICAgICAgICAgICB0aGlzLnJlY29yZFJUQyA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnJlY29yZFJUQyA9IG5ldyBSZWNvcmRSVEMoc3RyZWFtLCBvcHRpb25zKTtcbiAgICAgICAgdGhpcy5yZWNvcmRSVEMuc3RhcnRSZWNvcmRpbmcoKTtcbiAgICAgICAgdGhpcy5hdWRpby5zcmNPYmplY3QgPSBzdHJlYW07XG4gICAgICAgIC8vYXVkaW8uc3JjID0gdGhpcy5yZWNvcmRSVEMudG9VUkwoKTtcbiAgICAgICAgdGhpcy5kdXJhdGlvbj0wO1xuICAgICAgICB0aGlzLmR1cmF0aW9uSW50ZXJ2YWw9c2V0SW50ZXJ2YWwoKCk9PntcbiAgICAgICAgICAgIC8vY29uc29sZS5sb2codGhpcy5yZWNvcmRSVEMuZ2V0U3RhdGUoKSwgdGhpcy5yZWNvcmRSVEMpO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVjb3JkUlRDICYmIHRoaXMucmVjb3JkUlRDLmdldFN0YXRlKCk9PT0ncmVjb3JkaW5nJyl7XG4gICAgICAgICAgICAgICAgdGhpcy5kdXJhdGlvbisrO1xuICAgICAgICAgICAgICAgIC8vdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvL2NsZWFySW50ZXJ2YWwoZHVyYXRpb25JbnRlcnZhbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIDEwMDApO1xuICAgICAgICAvL2NvbnNvbGUubG9nKHRoaXMucmVjb3JkUlRDKTtcblxuICAgICAgICB0aGlzLnRvZ2dsZUNvbnRyb2xzKCk7XG4gICAgICAgIHRoaXMucmVjb3JkaW5nSW5wcm9ncmVzcz10cnVlO1xuICAgIH1cblxuICAgIHRvZ2dsZUNvbnRyb2xzKCkge1xuICAgICAgICBsZXQgYXVkaW86IEhUTUxBdWRpb0VsZW1lbnQgPSB0aGlzLmF1ZGlvLm5hdGl2ZUVsZW1lbnQ7XG4gICAgICAgIGF1ZGlvLm11dGVkID0gIWF1ZGlvLm11dGVkO1xuICAgICAgICBhdWRpby5jb250cm9scyA9ICFhdWRpby5jb250cm9scztcbiAgICAgICAgYXVkaW8uYXV0b3BsYXkgPSAhYXVkaW8uYXV0b3BsYXk7XG4gICAgfVxuXG4gICAgc3RvcFJlY29yZGluZygpIHtcbiAgICAgICAgbGV0IHJlY29yZFJUQyA9IHRoaXMucmVjb3JkUlRDO1xuICAgICAgICByZWNvcmRSVEMuc3RvcFJlY29yZGluZyh0aGlzLnByb2Nlc3NBdWRpby5iaW5kKHRoaXMpKTtcbiAgICAgICAgbGV0IHN0cmVhbSA9IHRoaXMuc3RyZWFtO1xuICAgICAgICBzdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaCh0cmFjayA9PiB0cmFjay5zdG9wKCkpO1xuICAgICAgICB0aGlzLnJlY29yZGluZ0lucHJvZ3Jlc3M9ZmFsc2U7XG4gICAgICAgIGlmICh0aGlzLmR1cmF0aW9uSW50ZXJ2YWwpe1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLmR1cmF0aW9uSW50ZXJ2YWwpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJvY2Vzc0F1ZGlvKGF1ZGlvVmlkZW9XZWJNVVJMKSB7XG4gICAgICAgIGxldCBhdWRpbzogSFRNTEF1ZGlvRWxlbWVudCA9IHRoaXMuYXVkaW8ubmF0aXZlRWxlbWVudDtcbiAgICAgICAgbGV0IHJlY29yZFJUQyA9IHRoaXMucmVjb3JkUlRDO1xuICAgICAgICBsZXQgZmlsZVJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XG4gICAgICAgIGZpbGVSZWFkZXI7XG5cbiAgICAgICAgYXVkaW8uc3JjID0gYXVkaW9WaWRlb1dlYk1VUkw7XG4gICAgICAgIHRoaXMudG9nZ2xlQ29udHJvbHMoKTtcbiAgICAgICAgdGhpcy5yZWNvcmRlZEJsb2IgPSByZWNvcmRSVEMuZ2V0QmxvYigpO1xuICAgICAgICBpZiAoIXRoaXMucmVjb3JkZWRCbG9iKXtcbiAgICAgICAgICAgIHRoaXMuaGFzUmVjb3JkPWZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGxldCBleHQ9J21wMyc7XG4gICAgICAgIGlmICh0aGlzLnJlY29yZGVkQmxvYi50eXBlKXtcbiAgICAgICAgICAgIGV4dD10aGlzLnJlY29yZGVkQmxvYi50eXBlLnNwbGl0KCcvJylbMV07XG4gICAgICAgICAgICBleHQ9ZXh0LnNwbGl0KCc7JylbMF07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZWNvcmRlZEJsb2IubmFtZT0nYXVkaW8uJytleHQ7XG5cbiAgICAgICAgaWYgKCF0aGlzLmZpbGUpe1xuICAgICAgICAgICAgdGhpcy5maWxlPW5ldyBTdXJ2ZXlGaWxlKCk7XG4gICAgICAgICAgICB0aGlzLmZpbGUubmFtZT0nYXVkaW8uJytleHQ7XG4gICAgICAgIH1cbiAgICAgICAgLy90aGlzLmZpbGUud29ya2Zsb3c9J2F1ZGlvJztcbiAgICAgICAgdGhpcy5maWxlLm1pbWU9dGhpcy5yZWNvcmRlZEJsb2IudHlwZTtcbiAgICAgICAgZmlsZVJlYWRlci5vbmxvYWQgPSAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLmZpbGUgJiYgZXZlbnQ/LnRhcmdldCl7XG4gICAgICAgICAgICAgICAgdGhpcy5maWxlLnNyYz1ldmVudC50YXJnZXRbJ3Jlc3VsdCddO1xuICAgICAgICAgICAgICAgIHRoaXMudXBsb2FkRmlsZSh0aGlzLmZpbGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBmaWxlUmVhZGVyLnJlYWRBc0FycmF5QnVmZmVyKHRoaXMucmVjb3JkZWRCbG9iKTtcbiAgICAgICAgdGhpcy5maWxlLnNpemU9dGhpcy5yZWNvcmRlZEJsb2Iuc2l6ZTtcbiAgICAgICAgdGhpcy56b25lLnJ1bigoKT0+e1xuICAgICAgICAgICAgdGhpcy5oYXNSZWNvcmQ9dHJ1ZTtcbiAgICAgICAgfSlcbiAgICAgICAgLy9jb25zb2xlLmxvZyh0aGlzLnJlY29yZGVkQmxvYik7XG4gICAgICAgIHJlY29yZFJUQy5nZXREYXRhVVJMKGRhdGFVUkw9PntcbiAgICAgICAgICAgIC8vY29uc29sZS5sb2coYXVkaW9WaWRlb1dlYk1VUkwsIGRhdGFVUkwsIGF1ZGlvLnNyYyk7XG4gICAgICAgICAgICB0aGlzLndhdmVzdXJmZXIgPSBXYXZlU3VyZmVyLmNyZWF0ZSh7XG4gICAgICAgICAgICAgICAgICBjb250YWluZXI6IHRoaXMud2F2ZWZvcm1FbGVtZW50Lm5hdGl2ZUVsZW1lbnQsXG4gICAgICAgICAgICAgICAgICBoZWlnaHQ6IDE5MCxcbiAgICAgICAgICAgICAgICAgIHdhdmVDb2xvcjogJyNkNGQ5ZGQnLFxuICAgICAgICAgICAgICAgICAgcHJvZ3Jlc3NDb2xvcjogJyM1NTUnLFxuICAgICAgICAgICAgICAgICAgbm9ybWFsaXplOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgYmFySGVpZ2h0OiA4LFxuICAgICAgICAgICAgICAgICAgY3Vyc29yV2lkdGg6IDEsXG4gICAgICAgICAgICAgICAgICBjdXJzb3JDb2xvcjogJyNkOWQ5ZDknXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMud2F2ZXN1cmZlci5sb2FkQmxvYih0aGlzLnJlY29yZGVkQmxvYik7XG5cbiAgICAgICAgICAgIHRoaXMud2F2ZXN1cmZlci5vbigncmVhZHknLCAoKT0+e1xuICAgICAgICAgICAgICAgIC8vY29uc29sZS5sb2codGhpcy53YXZlc3VyZmVyLmdldER1cmF0aW9uKCkpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmZpbGUpe1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbGUuZHVyYXRpb249dGhpcy53YXZlc3VyZmVyLmdldER1cmF0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZHVyYXRpb249dGhpcy5maWxlLmR1cmF0aW9uKjEwMDA7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2F2ZXN1cmZlclBsYXk9ZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLndhdmVzdXJmZXIub24oJ3BsYXknLCAoKT0+e1xuICAgICAgICAgICAgICAgIHRoaXMuem9uZS5ydW4oKCk9PntcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53YXZlc3VyZmVyUGxheT10cnVlO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMud2F2ZXN1cmZlci5vbigncGF1c2UnLCAoKT0+e1xuICAgICAgICAgICAgICAgIHRoaXMuem9uZS5ydW4oKCk9PntcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53YXZlc3VyZmVyUGxheT1mYWxzZTtcbiAgICAgICAgICAgICAgICB9KVxuXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuZmlsZTtcbiAgICB9XG5cbiAgICB1cGxvYWRGaWxlKGZpbGU6U3VydmV5RmlsZSl7XG4gICAgICAgIGZpbGUudXBsb2FkaW5nPXRydWU7XG4gICAgICAgIGZpbGUucHJvZ3Jlc3NTdWJqZWN0ID0gbmV3IE9ic2VydmFibGUob2JzZXJ2ZXIgPT4ge1xuICAgICAgICAgICAgZmlsZS5wcm9ncmVzc09ic2VydmVyID0gb2JzZXJ2ZXJcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuaXRlbS5idXN5PXRydWU7XG4gICAgICAgIGZpbGUucHJvZ3Jlc3NTdWJqZWN0LnN1YnNjcmliZShcbiAgICAgICAgICAgIGRhdGEgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuem9uZS5ydW4oKCk9PntcbiAgICAgICAgICAgICAgICAgICAgZmlsZS5wcm9ncmVzc1ZhbHVlPWRhdGE7XG4gICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5sb2coZmlsZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWxlLnVybCl7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvYmo9bmV3IFN1cnZleUZpbGU7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYmoudXJsPWZpbGUudXJsO1xuICAgICAgICAgICAgICAgICAgICAgICAgb2JqLm5hbWU9ZmlsZS5uYW1lO1xuICAgICAgICAgICAgICAgICAgICAgICAgb2JqLm1pbWU9ZmlsZS5taW1lO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pdGVtLnZhbHVlPW9iajtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKHRoaXMuaXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLml0ZW0uYnVzeT1mYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2hhbmdlcy5lbWl0KHRoaXMuaXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVycj0+e1xuICAgICAgICAgICAgICAgIHRoaXMuaXRlbS5idXN5PWZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnNlcnZpY2Uub25GaWxlc1NlbGVjdGVkLm5leHQoW2ZpbGVdKTtcbiAgICAgICAgdGhpcy5maWxlPWZpbGU7XG4gICAgfVxuXG4gICAgcGxheSgpe1xuICAgICAgICBpZiAodGhpcy53YXZlc3VyZmVyKXtcbiAgICAgICAgICAgIHRoaXMud2F2ZXN1cmZlci5wbGF5KCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcGF1c2UoKXtcbiAgICAgICAgaWYgKHRoaXMud2F2ZXN1cmZlcil7XG4gICAgICAgICAgICB0aGlzLndhdmVzdXJmZXIucGF1c2UoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRvZ2dsZVBsYXkoKXtcbiAgICAgICAgaWYgKHRoaXMud2F2ZXN1cmZlcil7XG4gICAgICAgICAgICBpZiAodGhpcy53YXZlc3VyZmVyUGxheSkge1xuICAgICAgICAgICAgICAgIHRoaXMucGF1c2UoKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRyb2xJY29uID0gJ3BsYXktY2lyY2xlLXRoaW4nO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBsYXkoKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRyb2xJY29uID0gJ3BhdXNlLWNpcmNsZS10aGluJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRvZ2dsZVJlY29yZGluZygpe1xuICAgICAgICAvL2NvbnNvbGUubG9nKCdDTElDS0VEJyk7XG4gICAgICAgIGlmICh0aGlzLnJlY29yZGluZ0lucHJvZ3Jlc3Mpe1xuICAgICAgICAgICAgdGhpcy5zdG9wUmVjb3JkaW5nKCk7XG4gICAgICAgICAgICB0aGlzLmNvbnRyb2xJY29uID0gJ3BsYXktY2lyY2xlLXRoaW4nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zdGFydFJlY29yZGluZygpO1xuICAgICAgICAgICAgdGhpcy5jb250cm9sSWNvbiA9ICdyZWNvcmQtcm91bmQnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2xlYXJCbG9iKCl7XG4gICAgICAgIHRoaXMuZmlsZT11bmRlZmluZWQ7XG4gICAgICAgIHRoaXMucmVjb3JkZWRCbG9iPW51bGw7XG4gICAgICAgIHRoaXMuaGFzUmVjb3JkPWZhbHNlO1xuICAgICAgICBpZiAodGhpcy53YXZlc3VyZmVyKXtcbiAgICAgICAgICAgIHRoaXMud2F2ZXN1cmZlci5kZXN0cm95KClcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5yZWNvcmRSVEMpe1xuICAgICAgICAgICAgLy90aGlzLnJlY29yZFJUQy5kZXN0cm95KClcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbnRyb2xJY29uID0gJ3JlY29yZC1jaXJjbGUnO1xuICAgICAgICB0aGlzLml0ZW0udmFsdWU9dW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmNoYW5nZXMuZW1pdCh0aGlzLml0ZW0pO1xuICAgIH1cblxuICAgIGRvd25sb2FkKCkge1xuICAgICAgICB0aGlzLnJlY29yZFJUQy5zYXZlKCdhdWRpby53ZWJtJyk7XG4gICAgfVxuXG4gICAgb25TYXZlKCl7XG4gICAgICAgIC8vdGhpcy5zdG9wUmVjb3JkaW5nKCk7XG4gICAgfVxuXG4gICAgbmdPbkRlc3Ryb3koKSB7XG4gICAgICAgIGlmICh0aGlzLndhdmVzdXJmZXIpe1xuICAgICAgICAgICAgdGhpcy53YXZlc3VyZmVyLmRlc3Ryb3koKVxuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnJlY29yZFJUQyAmJiB0aGlzLnJlY29yZFJUQy5zdGF0ZT09PSdyZWNvcmRpbmcnKXtcbiAgICAgICAgICAgIHRoaXMucmVjb3JkUlRDLnN0b3BSZWNvcmRpbmcoKTtcbiAgICAgICAgICAgIHRoaXMucmVjb3JkUlRDLmNsZWFyUmVjb3JkZWREYXRhKCk7XG4gICAgICAgICAgICAvL3RoaXMuc3RvcFJlY29yZGluZygpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnJlY29yZFJUQyl7XG4gICAgICAgICAgICB0aGlzLnJlY29yZFJUQy5kZXN0cm95KClcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5zdHJlYW0pe1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaCh0cmFjayA9PiB0cmFjay5zdG9wKCkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmR1cmF0aW9uSW50ZXJ2YWwpe1xuICAgICAgICAgICAgdGhpcy5kdXJhdGlvbj0wO1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLmR1cmF0aW9uSW50ZXJ2YWwpO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8ZGl2IGNsYXNzPVwiY29sLXhzLTEyIHZvaWNlLXJlY29yZGVyXCI+XG4gICAgICAgIDxkaXYgKm5nSWY9XCJpdGVtLmxhYmVsXCIgY2xhc3M9XCJ2b2ljZS1yZWNvcmRlci10aXRsZSBsYWJlbFwiIFtuZ0NsYXNzXT1cInsnaGFzLWVycm9yJzppdGVtLmVycm9ycyAmJiBpdGVtLmVycm9ycy5sZW5ndGh9XCI+e3tpdGVtLmxhYmVsfX0gPHNwYW4gKm5nSWY9XCJpdGVtLnJlcXVpcmVkXCIgY2xhc3M9XCJyZXF1aXJlZC1hc3Rlcml4XCI+Kjwvc3Bhbj48L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImF1ZGlvLXJlY29yZGVyXCI+XG4gICAgICAgICAgICA8YXVkaW8gI2F1ZGlvIGNsYXNzPVwiYXVkaW9cIiBzdHlsZT1cImRpc3BsYXk6bm9uZTtcIiBbc3JjXT1cImZpbGU/LnVybFwiPjwvYXVkaW8+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWFpbi1zY3JlZW5cIj5cbiAgICAgICAgICAgICAgICA8ZGl2ICN3YXZlZm9ybSBjbGFzcz1cIndhdmVmb3JtXCIgW25nQ2xhc3NdPVwie2hpZGRlbjpyZWNvcmRpbmdJbnByb2dyZXNzIHx8ICFoYXNSZWNvcmR9XCI+PC9kaXY+XG4gICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFyZWNvcmRpbmdJbnByb2dyZXNzICYmIGhhc1JlY29yZDsgZWxzZSBzdGFydFNjcmVlblwiPlxuICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gY2xhc3M9XCJtYWluLXNjcmVlbi1idXR0b25cIiAoY2xpY2spPVwidG9nZ2xlUGxheSgpXCIgdHlwZT1cImJ1dHRvblwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwibWFpbi1zY3JlZW4taWNvbi1iaWdcIj57e3RoaXMud2F2ZXN1cmZlclBsYXkgPyAncGF1c2VfY2lyY2xlX291dGxpbmUnIDogJ3BsYXlfY2lyY2xlX291dGxpbmUnfX08L21hdC1pY29uPlxuICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cblxuICAgICAgICAgICAgICAgICAgICA8YSBtYXQtYnV0dG9uIGNsYXNzPVwibWFpbi1zY3JlZW4tYnV0dG9uLWFzaWRlIGRvd25sb2FkLWJ0blwiICpuZ0lmPVwiaXRlbS52YWx1ZSAmJiBpdGVtLnZhbHVlLnVybFwiIFtocmVmXT1cIml0ZW0udmFsdWUudXJsXCIgdGFyZ2V0PVwiX2JsYW5rXCIgdGl0bGU9XCJEb3dsb2FkIFJlY29yZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwibWFpbi1zY3JlZW4taWNvbi1zbWFsbFwiPmRvd25sb2FkPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gY2xhc3M9XCJtYWluLXNjcmVlbi1idXR0b24tYXNpZGUgZGVsZXRlLWJ0blwiIHRpdGxlPVwiRGVsZXRlIFJlY29yZFwiIChjbGljayk9XCJjbGVhckJsb2IoKVwiICpuZ0lmPVwiZWRpdGFibGVcIiB0eXBlPVwiYnV0dG9uXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJtYWluLXNjcmVlbi1pY29uLXNtYWxsXCI+Y2FuY2VsPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgIDxtYXQtcHJvZ3Jlc3MtYmFyIG1vZGU9XCJkZXRlcm1pbmF0ZVwiICAqbmdJZj1cImZpbGUgJiYgZmlsZS51cGxvYWRpbmdcIiBbdmFsdWVdPVwiZmlsZS5wcm9ncmVzc1ZhbHVlXCI+PC9tYXQtcHJvZ3Jlc3MtYmFyPlxuICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNzdGFydFNjcmVlbj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3RhcnQtc2NyZWVuXCI+XG4gICAgICAgICAgICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiBjbGFzcz1cInN0YXJ0LXNjcmVlbi1idXR0b25cIiAoY2xpY2spPVwidG9nZ2xlUmVjb3JkaW5nKClcIiBbZGlzYWJsZWRdPVwiIWVkaXRhYmxlXCIgdHlwZT1cImJ1dHRvblwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwic3RhcnQtc2NyZWVuLWljb25cIiA+e3tyZWNvcmRpbmdJbnByb2dyZXNzID8gJ21pYyc6J21pY19ub25lJ319PC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgKm5nSWY9XCIhcmVjb3JkaW5nSW5wcm9ncmVzcyAmJiAhaGFzUmVjb3JkXCIgY2xhc3M9XCJzdGFydC1zY3JlZW4tdGV4dFwiPlRhcCB0byByZWNvcmQgYXVkaW88L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJyZWNvcmRpbmdJbnByb2dyZXNzXCIgY2xhc3M9XCJzdGFydC1zY3JlZW4tdGV4dFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7ZHVyYXRpb24gfCBkdXJhdGlvbjonc2Vjb25kcyd9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8ge3t0aW1lTGltaXQgLSBkdXJhdGlvbiB8IGR1cmF0aW9uOidzZWNvbmRzJ319XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cIml0ZW0uZXJyb3JzICYmIGl0ZW0uZXJyb3JzLmxlbmd0aFwiPlxuICAgICAgICAgICAgPGRpdiAqbmdGb3I9XCJsZXQgZXJyb3Igb2YgaXRlbS5lcnJvcnNcIj57e2Vycm9yLm1lc3NhZ2V9fTwvZGl2PlxuICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgPG1hdC1oaW50IGFsaWduPVwic3RhcnRcIiAqbmdJZj1cIiEoaXRlbS5lcnJvcnMgJiYgaXRlbS5lcnJvcnMubGVuZ3RoKVwiPjxzdHJvbmc+e3tpdGVtLmhpbnR9fTwvc3Ryb25nPiA8L21hdC1oaW50PlxuICAgIDwvZGl2PlxuPC9kaXY+XG4iXX0=