UNPKG

iamferraz-gantt-chart

Version:

Gantt Chart Component using Echarts library

465 lines 60.2 kB
import { Component, EventEmitter, HostListener, Input, Output, ViewChild } from '@angular/core'; import * as echarts from 'echarts/core'; import { GanttRenderers } from '../shared/gantt-renderers'; import { TaskDataManipulator } from '../shared/task-data-manipulator'; export class GanttComponent { constructor() { this.taskData = []; this.taskDataChange = new EventEmitter(); //this.dataChange.emit(this.size); this.editClicked = new EventEmitter(); this.taskClicked = new EventEmitter(); /** * The scroll will stop to work... its a bug that I cant figure it out :( */ this.enableDataZoom = false; this.enableDarkTheme = false; this.enableGroup = true; this.chartTitle = ""; this.dateFormat = "{MM}/{dd}/{yyyy}"; this.colours = ["#F94144", "#F3722C", "#F8961E", "#F9844A", "#F9C74F", "#90BE6D", "#43AA8B", "#4D908E", "#577590", "#277DA1"]; this.heightRatio = 0.6; this.loading = false; this.height = 300; /** * To replace the strings */ this.translation = { DONE: "done", TO_END: "days to finish", DELAYED: "delayed", FINISHED: "completed", JANUARY: "Jan", FEBRUARY: "Fev", MARCH: "Mar", APRIL: "Apr", MAY: "May", JUNE: "Jun", JULY: "Jul", AUGUST: "Aug", SEPTEMBER: "Sep", OCTOBER: "Oct", NOVEMBER: "Nov", DECEMBER: "Dec" }; /** * Variable to control chart */ this.ganttWidth = 700; this.ganttHeight = 500; this.taskDataManipulator = new TaskDataManipulator(this.colours, this.enableGroup); this.taskData = this.taskData.sort(this.taskDataManipulator.compareTasks); //after sort we map to maintain the order this.mappedData = this.taskDataManipulator.mapData(this.taskData); this.zebraData = this.taskDataManipulator.mapZebra(this.taskData); this.todayData = [new Date()]; } getTitleOption() { if (this.chartTitle === "") return {}; return { text: this.chartTitle, textStyle: { color: this.enableDarkTheme ? '#fff' : '#000' }, left: 'center' }; } getGridOption() { return { show: true, top: 70, bottom: 20, left: 225, right: 20, //height: '1000px', backgroundColor: '#fff', borderWidth: 0 }; } getTooltipOption() { let DATE_FORMAT = this.dateFormat; let translation = this.translation; return { confine: true, appendToBody: true, trigger: 'item', formatter: function (info) { //removing tooltip from the lines if (info != undefined && info.seriesIndex != 2) { return ""; } //console.log("info", info) var value = info.value; var taskName = value[1]; var start = echarts.time.format((new Date(value[2])), DATE_FORMAT, false); var end = echarts.time.format((new Date(value[3])), DATE_FORMAT, false); var donePercentage = value[5]; return [ '<div class="tooltip-title">' + echarts.format.encodeHTML(taskName) + '</div>', start + ' - ', end + '<br>', donePercentage + '% ' + (translation ? translation.DONE : "DONE") ].join(''); } }; } resetZoomAction() { this.echartsInstance.dispatchAction({ type: 'dataZoom', start: 0, end: 100 }); } editAction() { this.editClicked.emit(true); } getToolboxOption() { return { left: 20, top: 0, itemSize: 20, feature: { myEditor: { show: true, title: 'Edit', icon: 'path://M990.55 380.08 q11.69 0 19.88 8.19 q7.02 7.01 7.02 18.71 l0 480.65 q-1.17 43.27 -29.83 71.93 q-28.65 28.65 -71.92 29.82 l-813.96 0 q-43.27 -1.17 -72.5 -30.41 q-28.07 -28.07 -29.24 -71.34 l0 -785.89 q1.17 -43.27 29.24 -72.5 q29.23 -29.24 72.5 -29.24 l522.76 0 q11.7 0 18.71 7.02 q8.19 8.18 8.19 18.71 q0 11.69 -7.6 19.29 q-7.6 7.61 -19.3 7.61 l-518.08 0 q-22.22 1.17 -37.42 16.37 q-15.2 15.2 -15.2 37.42 l0 775.37 q0 23.39 15.2 38.59 q15.2 15.2 37.42 15.2 l804.6 0 q22.22 0 37.43 -15.2 q15.2 -15.2 16.37 -38.59 l0 -474.81 q0 -11.7 7.02 -18.71 q8.18 -8.19 18.71 -8.19 l0 0 ZM493.52 723.91 l-170.74 -170.75 l509.89 -509.89 q23.39 -23.39 56.13 -21.05 q32.75 1.17 59.65 26.9 l47.94 47.95 q25.73 26.89 27.49 59.64 q1.75 32.75 -21.64 57.3 l-508.72 509.9 l0 0 ZM870.09 80.69 l-56.13 56.14 l94.72 95.9 l56.14 -57.31 q8.19 -9.35 8.19 -21.05 q-1.17 -12.86 -10.53 -22.22 l-47.95 -49.12 q-10.52 -9.35 -23.39 -9.35 q-11.69 -1.17 -21.05 7.01 l0 0 ZM867.75 272.49 l-93.56 -95.9 l-380.08 380.08 l94.73 94.73 l378.91 -378.91 l0 0 ZM322.78 553.16 l38.59 39.77 l-33.92 125.13 l125.14 -33.92 l38.59 38.6 l-191.79 52.62 q-5.85 1.17 -12.28 0 q-6.44 -1.17 -11.11 -5.84 q-4.68 -4.68 -5.85 -11.7 q-2.34 -5.85 0 -11.69 l52.63 -192.97 l0 0 Z', onclick: this.editAction.bind(this) }, myZoomMinus: this.enableDataZoom ? { show: true, title: 'Reset Zoom', icon: 'path://M10,1.344c-4.781,0-8.656,3.875-8.656,8.656c0,4.781,3.875,8.656,8.656,8.656c4.781,0,8.656-3.875,8.656-8.656C18.656,5.219,14.781,1.344,10,1.344z M10,17.903c-4.365,0-7.904-3.538-7.904-7.903S5.635,2.096,10,2.096S17.903,5.635,17.903,10S14.365,17.903,10,17.903z M13.388,9.624H6.613c-0.208,0-0.376,0.168-0.376,0.376s0.168,0.376,0.376,0.376h6.775c0.207,0,0.377-0.168,0.377-0.376S13.595,9.624,13.388,9.624z', onclick: this.resetZoomAction.bind(this) } : {}, saveAsImage: { show: true, icon: 'path://M6.523,7.683c0.96,0,1.738-0.778,1.738-1.738c0-0.96-0.778-1.738-1.738-1.738c-0.96,0-1.738,0.778-1.738,1.738 C4.785,6.904,5.563,7.683,6.523,7.683z M5.944,5.365h1.159v1.159H5.944V5.365z M18.113,0.729H1.888 c-0.64,0-1.159,0.519-1.159,1.159v16.224c0,0.64,0.519,1.159,1.159,1.159h16.225c0.639,0,1.158-0.52,1.158-1.159V1.889 C19.271,1.249,18.752,0.729,18.113,0.729z M18.113,17.532c0,0.321-0.262,0.58-0.58,0.58H2.467c-0.32,0-0.579-0.259-0.579-0.58 V2.468c0-0.32,0.259-0.579,0.579-0.579h15.066c0.318,0,0.58,0.259,0.58,0.579V17.532z M15.91,7.85l-4.842,5.385l-3.502-2.488 c-0.127-0.127-0.296-0.18-0.463-0.17c-0.167-0.009-0.336,0.043-0.463,0.17l-3.425,4.584c-0.237,0.236-0.237,0.619,0,0.856 c0.236,0.236,0.62,0.236,0.856,0l3.152-4.22l3.491,2.481c0.123,0.123,0.284,0.179,0.446,0.174c0.16,0.005,0.32-0.051,0.443-0.174 l5.162-5.743c0.238-0.236,0.238-0.619,0-0.856C16.529,7.614,16.146,7.614,15.91,7.85z' } } }; } getXAxisOption() { return { type: 'time', position: 'top', splitLine: { lineStyle: { color: ['#E9EDFF'] } }, axisLine: { show: false }, axisTick: { lineStyle: { color: '#929ABA' } }, axisLabel: { color: '#929ABA', inside: false, align: 'center', formatter: this.formatLabelDate.bind(this) } }; } formatLabelDate(value, index) { let valueDate = new Date(value); let dayToday = valueDate.getDate(); let monthToday = valueDate.getMonth(); if (this.isFirstDay(dayToday, monthToday)) { return this.getMonthName(monthToday); } return dayToday + ""; /*let DATE_FORMAT = this.dateFormat return echarts.time.format( value, DATE_FORMAT, false );*/ } /** * * @param dayToday day reference to check if is the last day of the month * @param month (0-11) month reference to check if the day passed is the last day of the month. * @returns true if day is the last day of the month. False otherwise */ getLastDayMonth(dayToday, month) { //var month = 0; // January var d = new Date(new Date().getFullYear(), month + 1, 0).getDate(); return d == dayToday; } isFirstDay(dayToday, month) { return dayToday == 1; } getMonthName(month) { switch (month) { case 0: return this.translation ? this.translation.JANUARY : "Jan"; case 1: return this.translation ? this.translation.FEBRUARY : "Fev"; case 2: return this.translation ? this.translation.MARCH : "Mar"; case 3: return this.translation ? this.translation.APRIL : "Apr"; case 4: return this.translation ? this.translation.MAY : "May"; case 5: return this.translation ? this.translation.JUNE : "Jun"; case 6: return this.translation ? this.translation.JULY : "Jul"; case 7: return this.translation ? this.translation.AUGUST : "Aug"; case 8: return this.translation ? this.translation.SEPTEMBER : "Sep"; case 9: return this.translation ? this.translation.OCTOBER : "Oct"; case 10: return this.translation ? this.translation.NOVEMBER : "Nov"; case 11: return this.translation ? this.translation.DECEMBER : "Dec"; } return ""; } getYAxisOption() { return { axisTick: { show: false }, splitLine: { show: false }, axisLine: { show: false }, axisLabel: { show: false }, min: 0, max: this.taskData.length }; } getSerieZebra() { var _zebraDataDimensions = [ { name: 'index', type: 'number' }, { name: 'start', type: 'time' }, { name: 'end', type: 'time' }, { name: 'taskId', type: 'number' } ]; return { id: 'zebra', type: 'custom', renderItem: this.renderers.renderZebra.bind(this.renderers), dimensions: _zebraDataDimensions, encode: { x: -1, y: 3, }, data: this.zebraData //Im changing the item object to array... this is why the encode is filled with indexed }; } getSerieArrow(taskDataDimensions) { return { id: 'arrow', type: 'custom', clip: true, silent: true, itemStyle: { borderType: 'dashed' }, renderItem: this.renderers.renderArrowsItem.bind(this.renderers), dimensions: taskDataDimensions, tooltip: null, encode: { x: -1, y: 4, }, data: this.mappedData //Im changing the item object to array... this is why the encode is filled with indexed }; } getSerieGantt(taskDataDimensions) { return { id: 'taskData', type: 'custom', itemStyle: {}, renderItem: this.renderers.renderGanttItem.bind(this.renderers), dimensions: taskDataDimensions, encode: { x: [1, 2, 3, 4], y: 4, tooltip: [0, 1, 2] }, data: this.mappedData //Im changing the item object to array... this is why the encode is filled with indexed }; } getSerieAxisY(taskDataDimensions) { return { type: 'custom', renderItem: this.renderers.renderAxisLabelItem.bind(this.renderers), dimensions: taskDataDimensions, encode: { x: -1, y: 4, tooltip: [0, 1, 2] }, data: this.mappedData //Im changing the item object to array... this is why the encode is filled with indexed }; } getSerieToday() { return { id: 'today', type: 'custom', renderItem: this.renderers.renderToday.bind(this.renderers), dimensions: [{ name: 'today', type: 'time' }], encode: { x: 0, y: -1, }, data: this.todayData }; } getDataZoom() { if (this.enableDataZoom == false) { return []; } return [{ type: 'slider', xAxisIndex: 0, filterMode: 'weakFilter', height: 30, bottom: 0, start: 0, end: 30, showDetail: false }, { type: 'inside', id: 'insideX', xAxisIndex: 0, filterMode: 'weakFilter', start: 0, end: 30, zoomOnMouseWheel: false, moveOnMouseMove: false, moveOnMouseWheel: true, preventDefaultMouseMove: false, preventDefaultMouseWheel: false }]; } getSeries() { var taskDataDimensions = [ { name: 'index', type: 'number' }, { name: 'taskName', type: 'ordinal' }, { name: 'start', type: 'time' }, { name: 'end', type: 'time' }, { name: 'taskId', type: 'number' }, { name: 'donePercentage', type: 'number' }, { name: 'owner', type: 'ordinal' }, { name: 'image', type: 'ordinal' }, { name: 'groupName', type: 'ordinal' }, { name: 'isToDrawGroup', type: 'number' }, { name: 'groupColor', type: 'ordinal' }, ]; return [this.getSerieZebra(), this.getSerieArrow(taskDataDimensions), this.getSerieGantt(taskDataDimensions), this.getSerieAxisY(taskDataDimensions), this.getSerieToday()]; } setChartOptions() { this.chartOptions = { backgroundColor: "transparent", tooltip: this.getTooltipOption(), animation: false, toolbox: this.getToolboxOption(), title: this.getTitleOption(), dataZoom: this.getDataZoom(), grid: this.getGridOption(), xAxis: this.getXAxisOption(), yAxis: this.getYAxisOption(), series: this.getSeries() }; /*if(this.echartsInstance){ this.echartsInstance.setOption(this.chartOptions) }*/ } ngOnInit() { this.setChartOptions(); } ngAfterViewInit() { //import * as echarts from 'echarts'; //@ViewChild('gantt') //public gantt: ElementRef | undefined; //public ganttEchart: any; //this.ganttEchart = echarts.init(this.gantt!.nativeElement); } ngOnChanges(changes) { if (this.echartsInstance) { this.echartsInstance.clear(); } this.taskDataManipulator = new TaskDataManipulator(this.colours, this.enableGroup); this.taskData = this.taskData.sort(this.taskDataManipulator.compareTasks); //after sort we map to maintain the order this.mappedData = this.taskDataManipulator.mapData(this.taskData); this.zebraData = this.taskDataManipulator.mapZebra(this.taskData); this.todayData = [new Date()]; this.renderers = new GanttRenderers(this.taskData, this.mappedData, this.colours, this.dateFormat, this.heightRatio, this.translation, this.enableGroup, this.enableDarkTheme); this.setChartOptions(); } ngAfterContentChecked() { if (this.wrapper == undefined) return; this.ganttWidth = this.wrapper.nativeElement.offsetWidth; this.ganttHeight = this.wrapper.nativeElement.offsetHeight; var chartHeight = this.taskData.length * 80; this.ganttHeight = chartHeight < 300 ? 300 : chartHeight; } onChartInit(ec) { this.echartsInstance = ec; this.echartsInstance.resize(); } onTaskClicked(params) { if (params != undefined) { /*let task:TaskModel = new TaskModel() task.taskName = params.value[1] task.start = params.value[2] task.end = params.value[3] task.taskId = params.value[4] task.donePercentage = params.value[5] task.owner = params.value[6] task.image = params.value[7] task.groupName = params.value[8]*/ //re-mapping [index, item.taskName, item.start, item.end, item.taskId, item.donePercentage, item.owner, item.image, item.groupName, isToDrawGroup, color] into taskmodel let task = this.taskDataManipulator.getTaskById(this.taskData, params.value[4]); if (this.taskClicked != undefined) this.taskClicked.emit(task); } } resizeChart() { if (this.echartsInstance) { this.echartsInstance.resize(); } } sizeChange(event) { this.resizeChart(); } } GanttComponent.decorators = [ { type: Component, args: [{ selector: 'iamferraz-gantt', template: "<div class=\"wrapper\" [style.width.%]=\"100\" [style.height.%]=\"100\" #wrapper>\n <div echarts class=\"gantt-chart\" [options]=\"chartOptions\" [loading]=\"loading\" (chartInit)=\"onChartInit($event)\" (chartClick)=\"onTaskClicked($event)\" [style.width.px]=\"ganttWidth\" [style.height.px]=\"ganttHeight\" #gantt></div>\n</div>", styles: [".wrapper{display:inline-block;width:100%;overflow-y:auto;overflow-x:hidden}::-webkit-scrollbar{width:10px}::-webkit-scrollbar-track{background:#f1f1f1}::-webkit-scrollbar-thumb{background:#888}::-webkit-scrollbar-thumb:hover{background:#555}"] },] } ]; GanttComponent.ctorParameters = () => []; GanttComponent.propDecorators = { wrapper: [{ type: ViewChild, args: ['wrapper',] }], gantt: [{ type: ViewChild, args: ['gantt',] }], taskData: [{ type: Input }], taskDataChange: [{ type: Output }], editClicked: [{ type: Output }], taskClicked: [{ type: Output }], enableDataZoom: [{ type: Input }], enableDarkTheme: [{ type: Input }], enableGroup: [{ type: Input }], chartTitle: [{ type: Input }], dateFormat: [{ type: Input }], colours: [{ type: Input }], heightRatio: [{ type: Input }], loading: [{ type: Input }], height: [{ type: Input }], translation: [{ type: Input }], sizeChange: [{ type: HostListener, args: ['window:resize', ['$event'],] }] }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2FudHQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZ2FudHQtY2hhcnQvc3JjL2xpYi9nYW50dC9nYW50dC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFzQyxTQUFTLEVBQWMsWUFBWSxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQXFCLE1BQU0sRUFBaUIsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2xMLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBRXhDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQU90RSxNQUFNLE9BQU8sY0FBYztJQXFGekI7UUFoRk8sYUFBUSxHQUFnQixFQUFFLENBQUM7UUFFM0IsbUJBQWMsR0FBOEIsSUFBSSxZQUFZLEVBQWUsQ0FBQztRQUNuRixrQ0FBa0M7UUFHM0IsZ0JBQVcsR0FBMEIsSUFBSSxZQUFZLEVBQVcsQ0FBQztRQUdqRSxnQkFBVyxHQUFtQyxJQUFJLFlBQVksRUFBb0IsQ0FBQztRQUMxRjs7V0FFRztRQUVJLG1CQUFjLEdBQVksS0FBSyxDQUFDO1FBR2hDLG9CQUFlLEdBQVksS0FBSyxDQUFDO1FBR2pDLGdCQUFXLEdBQVksSUFBSSxDQUFDO1FBRzVCLGVBQVUsR0FBVyxFQUFFLENBQUM7UUFHeEIsZUFBVSxHQUFXLGtCQUFrQixDQUFDO1FBR3hDLFlBQU8sR0FBYSxDQUFDLFNBQVMsRUFBQyxTQUFTLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBR2xJLGdCQUFXLEdBQVcsR0FBRyxDQUFBO1FBR3pCLFlBQU8sR0FBWSxLQUFLLENBQUM7UUFHekIsV0FBTSxH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YSxDQUFDLE1BQVU7UUFDdEIsSUFBRyxNQUFNLElBQUksU0FBUyxFQUFDO1lBQ3JCOzs7Ozs7Ozs4Q0FRa0M7WUFDbEMsd0tBQXdLO1lBQ3hLLElBQUksSUFBSSxHQUFvQixJQUFJLENBQUMsbUJBQW1CLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQ2hHLElBQUcsSUFBSSxDQUFDLFdBQVcsSUFBSSxTQUFTO2dCQUM5QixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtTQUM5QjtJQUVILENBQUM7SUFHRCxXQUFXO1FBQ1QsSUFBSSxJQUFJLENBQUMsZUFBZSxFQUFFO1lBQ3hCLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxFQUFFLENBQUM7U0FDL0I7SUFDSCxDQUFDO0lBR0QsVUFBVSxDQUFDLEtBQVM7UUFDbEIsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFBO0lBQ3BCLENBQUM7OztZQW5oQkYsU0FBUyxTQUFDO2dCQUNULFFBQVEsRUFBRSxpQkFBaUI7Z0JBQzNCLDBWQUFxQzs7YUFFdEM7Ozs7c0JBRUUsU0FBUyxTQUFDLFNBQVM7b0JBQ25CLFNBQVMsU0FBQyxPQUFPO3VCQUVqQixLQUFLOzZCQUVMLE1BQU07MEJBSU4sTUFBTTswQkFHTixNQUFNOzZCQUtOLEtBQUs7OEJBR0wsS0FBSzswQkFHTCxLQUFLO3lCQUdMLEtBQUs7eUJBR0wsS0FBSztzQkFHTCxLQUFLOzBCQUdMLEtBQUs7c0JBR0wsS0FBSztxQkFHTCxLQUFLOzBCQU1MLEtBQUs7eUJBMmRMLFlBQVksU0FBQyxlQUFlLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBZnRlckNvbnRlbnRDaGVja2VkLCBBZnRlclZpZXdJbml0LCBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgSG9zdExpc3RlbmVyLCBJbnB1dCwgT25DaGFuZ2VzLCBPbkluaXQsIE91dHB1dCwgU2ltcGxlQ2hhbmdlcywgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgKiBhcyBlY2hhcnRzIGZyb20gJ2VjaGFydHMvY29yZSc7XG5pbXBvcnQgeyBUYXNrTW9kZWwgfSBmcm9tICcuLi9tb2RlbHMvdGFzay1kYXRhLm1vZGVsJztcbmltcG9ydCB7IEdhbnR0UmVuZGVyZXJzIH0gZnJvbSAnLi4vc2hhcmVkL2dhbnR0LXJlbmRlcmVycyc7XG5pbXBvcnQgeyBUYXNrRGF0YU1hbmlwdWxhdG9yIH0gZnJvbSAnLi4vc2hhcmVkL3Rhc2stZGF0YS1tYW5pcHVsYXRvcic7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2lhbWZlcnJhei1nYW50dCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9nYW50dC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2dhbnR0LmNvbXBvbmVudC5jc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBHYW50dENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgT25DaGFuZ2VzLCBBZnRlckNvbnRlbnRDaGVja2VkIHtcbiAgQFZpZXdDaGlsZCgnd3JhcHBlcicpIHdyYXBwZXI6IEVsZW1lbnRSZWYgfCB1bmRlZmluZWQ7XG4gIEBWaWV3Q2hpbGQoJ2dhbnR0JykgZ2FudHQ6IEVsZW1lbnRSZWYgfCB1bmRlZmluZWQ7XG5cbiAgQElucHV0KClcbiAgcHVibGljIHRhc2tEYXRhOiBUYXNrTW9kZWxbXSA9IFtdO1xuICBAT3V0cHV0KCkgXG4gIHB1YmxpYyB0YXNrRGF0YUNoYW5nZTogRXZlbnRFbWl0dGVyPFRhc2tNb2RlbFtdPiA9IG5ldyBFdmVudEVtaXR0ZXI8VGFza01vZGVsW10+KCk7XG4gIC8vdGhpcy5kYXRhQ2hhbmdlLmVtaXQodGhpcy5zaXplKTtcblxuICBAT3V0cHV0KClcbiAgcHVibGljIGVkaXRDbGlja2VkOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4gPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7XG5cbiAgQE91dHB1dCgpIFxuICBwdWJsaWMgdGFza0NsaWNrZWQ6IEV2ZW50RW1pdHRlcjxUYXNrTW9kZWwgfCBudWxsPiA9IG5ldyBFdmVudEVtaXR0ZXI8VGFza01vZGVsIHwgbnVsbD4oKTtcbiAgLyoqXG4gICAqIFRoZSBzY3JvbGwgd2lsbCBzdG9wIHRvIHdvcmsuLi4gaXRzIGEgYnVnIHRoYXQgSSBjYW50IGZpZ3VyZSBpdCBvdXQgOihcbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBlbmFibGVEYXRhWm9vbTogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBlbmFibGVEYXJrVGhlbWU6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBASW5wdXQoKVxuICBwdWJsaWMgZW5hYmxlR3JvdXA6IGJvb2xlYW4gPSB0cnVlO1xuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBjaGFydFRpdGxlOiBzdHJpbmcgPSBcIlwiO1xuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBkYXRlRm9ybWF0OiBzdHJpbmcgPSBcIntNTX0ve2RkfS97eXl5eX1cIjtcblxuICBASW5wdXQoKVxuICBwdWJsaWMgY29sb3Vyczogc3RyaW5nW10gPSBbXCIjRjk0MTQ0XCIsXCIjRjM3MjJDXCIsIFwiI0Y4OTYxRVwiLCBcIiNGOTg0NEFcIiwgXCIjRjlDNzRGXCIsIFwiIzkwQkU2RFwiLCBcIiM0M0FBOEJcIiwgXCIjNEQ5MDhFXCIsIFwiIzU3NzU5MFwiLCBcIiMyNzdEQTFcIl07XG5cbiAgQElucHV0KClcbiAgcHVibGljIGhlaWdodFJhdGlvOiBudW1iZXIgPSAwLjZcblxuICBASW5wdXQoKVxuICBwdWJsaWMgbG9hZGluZzogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBoZWlnaHQ6IG51bWJlciA9IDMwMDtcblxuICAvKipcbiAgICogVG8gcmVwbGFjZSB0aGUgc3RyaW5nc1xuICAgKi9cbiAgQElucHV0KClcbiAgcHVibGljIHRyYW5zbGF0aW9uOiBhbnkgPSB7XG4gICAgRE9ORTogXCJkb25lXCIsXG4gICAgVE9fRU5EOiBcImRheXMgdG8gZmluaXNoXCIsXG4gICAgREVMQVlFRDogXCJkZWxheWVkXCIsXG4gICAgRklOSVNIRUQ6IFwiY29tcGxldGVkXCIsXG4gICAgSkFOVUFSWSA6IFwiSmFuXCIsXG4gICAgRkVCUlVBUlkgOiBcIkZldlwiLFxuICAgIE1BUkNIIDogXCJNYXJcIixcbiAgICBBUFJJTCA6IFwiQXByXCIsXG4gICAgTUFZIDogXCJNYXlcIixcbiAgICBKVU5FIDogXCJKdW5cIixcbiAgICBKVUxZIDogXCJKdWxcIixcbiAgICBBVUdVU1QgOiBcIkF1Z1wiLFxuICAgIFNFUFRFTUJFUiA6IFwiU2VwXCIsXG4gICAgT0NUT0JFUiA6IFwiT2N0XCIsXG4gICAgTk9WRU1CRVIgOiBcIk5vdlwiLFxuICAgIERFQ0VNQkVSIDogXCJEZWNcIlxuICB9O1xuXG4gIC8qKlxuICAgKiBWYXJpYWJsZSB0byBjb250cm9sIGNoYXJ0XG4gICAqL1xuICBnYW50dFdpZHRoOiBudW1iZXIgPSA3MDA7XG5cbiAgZ2FudHRIZWlnaHQ6IG51bWJlciA9IDUwMDtcbiAgXG4gIGNoYXJ0T3B0aW9uczogYW55O1xuXG4gIGVjaGFydHNJbnN0YW5jZTogYW55O1xuXG4gIHByaXZhdGUgcmVuZGVyZXJzPzpHYW50dFJlbmRlcmVycztcbiAgcHJpdmF0ZSB0YXNrRGF0YU1hbmlwdWxhdG9yOlRhc2tEYXRhTWFuaXB1bGF0b3I7XG4gIHByaXZhdGUgbWFwcGVkRGF0YTphbnlbXTtcbiAgcHJpdmF0ZSB6ZWJyYURhdGE6YW55W107XG4gIHByaXZhdGUgdG9kYXlEYXRhOmFueVtdO1xuXG4gIGNvbnN0cnVjdG9yKCkgeyBcbiAgICB0aGlzLnRhc2tEYXRhTWFuaXB1bGF0b3IgPSBuZXcgVGFza0RhdGFNYW5pcHVsYXRvcih0aGlzLmNvbG91cnMsIHRoaXMuZW5hYmxlR3JvdXApXG4gICAgXG4gICAgdGhpcy50YXNrRGF0YSA9IHRoaXMudGFza0RhdGEuc29ydCh0aGlzLnRhc2tEYXRhTWFuaXB1bGF0b3IuY29tcGFyZVRhc2tzKVxuXG4gICAgLy9hZnRlciBzb3J0IHdlIG1hcCB0byBtYWludGFpbiB0aGUgb3JkZXJcbiAgICB0aGlzLm1hcHBlZERhdGEgPSB0aGlzLnRhc2tEYXRhTWFuaXB1bGF0b3IubWFwRGF0YSh0aGlzLnRhc2tEYXRhKVxuICAgIHRoaXMuemVicmFEYXRhID0gdGhpcy50YXNrRGF0YU1hbmlwdWxhdG9yLm1hcFplYnJhKHRoaXMudGFza0RhdGEpXG4gICAgdGhpcy50b2RheURhdGEgPSBbbmV3IERhdGUoKV1cbiAgfVxuXG4gIGdldFRpdGxlT3B0aW9uKCk6YW55e1xuICAgIGlmKHRoaXMuY2hhcnRUaXRsZSA9PT0gXCJcIilcbiAgICAgIHJldHVybiB7fVxuICAgIFxuICAgIHJldHVybiB7XG4gICAgICB0ZXh0OiB0aGlzLmNoYXJ0VGl0bGUsXG4gICAgICB0ZXh0U3R5bGU6IHtcbiAgICAgICAgY29sb3I6IHRoaXMuZW5hYmxlRGFya1RoZW1lID8gJyNmZmYnIDogJyMwMDAnXG4gICAgICB9LFxuICAgICAgbGVmdDogJ2NlbnRlcidcbiAgICB9XG4gIH1cblxuICBnZXRHcmlkT3B0aW9uKCk6YW55e1xuICAgIHJldHVybiB7XG4gICAgICAgIHNob3c6IHRydWUsXG4gICAgICAgIHRvcDogNzAsXG4gICAgICAgIGJvdHRvbTogMjAsXG4gICAgICAgIGxlZnQ6IDIyNSxcbiAgICAgICAgcmlnaHQ6IDIwLFxuICAgICAgICAvL2hlaWdodDogJzEwMDBweCcsXG4gICAgICAgIGJhY2tncm91bmRDb2xvcjogJyNmZmYnLFxuICAgICAgICBib3JkZXJXaWR0aDogMFxuICAgIH1cbiAgfVxuXG4gIGdldFRvb2x0aXBPcHRpb24oKTphbnl7XG4gICAgbGV0IERBVEVfRk9STUFUID0gdGhpcy5kYXRlRm9ybWF0XG4gICAgbGV0IHRyYW5zbGF0aW9uID0gdGhpcy50cmFuc2xhdGlvblxuICAgIHJldHVybiB7XG4gICAgICBjb25maW5lOiB0cnVlLFxuICAgICAgYXBwZW5kVG9Cb2R5OiB0cnVlLFxuICAgICAgdHJpZ2dlcjogJ2l0ZW0nLFxuICAgICAgZm9ybWF0dGVyOiBmdW5jdGlvbiAoaW5mbzphbnkpIHtcbiAgICAgICAgICAvL3JlbW92aW5nIHRvb2x0aXAgZnJvbSB0aGUgbGluZXNcbiAgICAgICAgICBpZihpbmZvICE9IHVuZGVmaW5lZCAmJiBpbmZvLnNlcmllc0luZGV4ICE9IDIpe1xuICAgICAgICAgICAgICByZXR1cm4gXCJcIjtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy9jb25zb2xlLmxvZyhcImluZm9cIiwgaW5mbylcbiAgICAgICAgICB2YXIgdmFsdWUgPSBpbmZvLnZhbHVlO1xuXG4gICAgICAgICAgdmFyIHRhc2tOYW1lID0gdmFsdWVbMV07XG4gICAgICAgICAgdmFyIHN0YXJ0ID0gZWNoYXJ0cy50aW1lLmZvcm1hdChcbiAgICAgICAgICAgICAgKG5ldyBEYXRlKHZhbHVlWzJdKSksXG4gICAgICAgICAgICAgIERBVEVfRk9STUFULFxuICAgICAgICAgICAgICBmYWxzZVxuICAgICAgICAgICk7XG4gICAgICAgICAgdmFyIGVuZCA9IGVjaGFydHMudGltZS5mb3JtYXQoXG4gICAgICAgICAgICAgIChuZXcgRGF0ZSh2YWx1ZVszXSkpLFxuICAgICAgICAgICAgICBEQVRFX0ZPUk1BVCxcbiAgICAgICAgICAgICAgZmFsc2VcbiAgICAgICAgICApO1xuICAgICAgICAgIHZhciBkb25lUGVyY2VudGFnZSA9IHZhbHVlWzVdXG5cbiAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAnPGRpdiBjbGFzcz1cInRvb2x0aXAtdGl0bGVcIj4nICsgZWNoYXJ0cy5mb3JtYXQuZW5jb2RlSFRNTCh0YXNrTmFtZSkgKyAnPC9kaXY+JyxcbiAgICAgICAgICAgICAgc3RhcnQgKyAnIC0gJyxcbiAgICAgICAgICAgICAgZW5kICsgJzxicj4nLCBkb25lUGVyY2VudGFnZSArICclICcgKyAodHJhbnNsYXRpb24gPyB0cmFuc2xhdGlvbi5ET05FIDogXCJET05FXCIpXG4gICAgICAgICAgXS5qb2luKCcnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXNldFpvb21BY3Rpb24oKTp2b2lke1xuICAgIHRoaXMuZWNoYXJ0c0luc3RhbmNlLmRpc3BhdGNoQWN0aW9uKHtcbiAgICAgIHR5cGU6ICdkYXRhWm9vbScsXG4gICAgICBzdGFydDogMCxcbiAgICAgIGVuZDogMTAwXG4gICAgfSlcbiAgfVxuXG4gIGVkaXRBY3Rpb24oKTp2b2lke1xuICAgIHRoaXMuZWRpdENsaWNrZWQuZW1pdCh0cnVlKVxuICB9XG5cbiAgZ2V0VG9vbGJveE9wdGlvbigpOmFueXtcbiAgICByZXR1cm4ge1xuICAgICAgbGVmdDogMjAsXG4gICAgICB0b3A6IDAsXG4gICAgICBpdGVtU2l6ZTogMjAsXG4gICAgICBmZWF0dXJlOiB7XG4gICAgICAgICAgbXlFZGl0b3I6IHtcbiAgICAgICAgICAgICAgc2hvdzogdHJ1ZSxcbiAgICAgICAgICAgICAgdGl0bGU6ICdFZGl0JyxcbiAgICAgICAgICAgICAgaWNvbjogJ3BhdGg6Ly9NOTkwLjU1IDM4MC4wOCBxMTEuNjkgMCAxOS44OCA4LjE5IHE3LjAyIDcuMDEgNy4wMiAxOC43MSBsMCA0ODAuNjUgcS0xLjE3IDQzLjI3IC0yOS44MyA3MS45MyBxLTI4LjY1IDI4LjY1IC03MS45MiAyOS44MiBsLTgxMy45NiAwIHEtNDMuMjcgLTEuMTcgLTcyLjUgLTMwLjQxIHEtMjguMDcgLTI4LjA3IC0yOS4yNCAtNzEuMzQgbDAgLTc4NS44OSBxMS4xNyAtNDMuMjcgMjkuMjQgLTcyLjUgcTI5LjIzIC0yOS4yNCA3Mi41IC0yOS4yNCBsNTIyLjc2IDAgcTExLjcgMCAxOC43MSA3LjAyIHE4LjE5IDguMTggOC4xOSAxOC43MSBxMCAxMS42OSAtNy42IDE5LjI5IHEtNy42IDcuNjEgLTE5LjMgNy42MSBsLTUxOC4wOCAwIHEtMjIuMjIgMS4xNyAtMzcuNDIgMTYuMzcgcS0xNS4yIDE1LjIgLTE1LjIgMzcuNDIgbDAgNzc1LjM3IHEwIDIzLjM5IDE1LjIgMzguNTkgcTE1LjIgMTUuMiAzNy40MiAxNS4yIGw4MDQuNiAwIHEyMi4yMiAwIDM3LjQzIC0xNS4yIHExNS4yIC0xNS4yIDE2LjM3IC0zOC41OSBsMCAtNDc0LjgxIHEwIC0xMS43IDcuMDIgLTE4LjcxIHE4LjE4IC04LjE5IDE4LjcxIC04LjE5IGwwIDAgWk00OTMuNTIgNzIzLjkxIGwtMTcwLjc0IC0xNzAuNzUgbDUwOS44OSAtNTA5Ljg5IHEyMy4zOSAtMjMuMzkgNTYuMTMgLTIxLjA1IHEzMi43NSAxLjE3IDU5LjY1IDI2LjkgbDQ3Ljk0IDQ3Ljk1IHEyNS43MyAyNi44OSAyNy40OSA1OS42NCBxMS43NSAzMi43NSAtMjEuNjQgNTcuMyBsLTUwOC43MiA1MDkuOSBsMCAwIFpNODcwLjA5IDgwLjY5IGwtNTYuMTMgNTYuMTQgbDk0LjcyIDk1LjkgbDU2LjE0IC01Ny4zMSBxOC4xOSAtOS4zNSA4LjE5IC0yMS4wNSBxLTEuMTcgLTEyLjg2IC0xMC41MyAtMjIuMjIgbC00Ny45NSAtNDkuMTIgcS0xMC41MiAtOS4zNSAtMjMuMzkgLTkuMzUgcS0xMS42OSAtMS4xNyAtMjEuMDUgNy4wMSBsMCAwIFpNODY3Ljc1IDI3Mi40OSBsLTkzLjU2IC05NS45IGwtMzgwLjA4IDM4MC4wOCBsOTQuNzMgOTQuNzMgbDM3OC45MSAtMzc4LjkxIGwwIDAgWk0zMjIuNzggNTUzLjE2IGwzOC41OSAzOS43NyBsLTMzLjkyIDEyNS4xMyBsMTI1LjE0IC0zMy45MiBsMzguNTkgMzguNiBsLTE5MS43OSA1Mi42MiBxLTUuODUgMS4xNyAtMTIuMjggMCBxLTYuNDQgLTEuMTcgLTExLjExIC01Ljg0IHEtNC42OCAtNC42OCAtNS44NSAtMTEuNyBxLTIuMzQgLTUuODUgMCAtMTEuNjkgbDUyLjYzIC0xOTIuOTcgbDAgMCBaJyxcbiAgICAgICAgICAgICAgb25jbGljazogdGhpcy5lZGl0QWN0aW9uLmJpbmQodGhpcylcbiAgICAgICAgICB9LFxuICAgICAgICAgIG15Wm9vbU1pbnVzOiB0aGlzLmVuYWJsZURhdGFab29tID8ge1xuICAgICAgICAgICAgc2hvdzogdHJ1ZSxcbiAgICAgICAgICAgIHRpdGxlOiAnUmVzZXQgWm9vbScsXG4gICAgICAgICAgICBpY29uOiAncGF0aDovL00xMCwxLjM0NGMtNC43ODEsMC04LjY1NiwzLjg3NS04LjY1Niw4LjY1NmMwLDQuNzgxLDMuODc1LDguNjU2LDguNjU2LDguNjU2YzQuNzgxLDAsOC42NTYtMy44NzUsOC42NTYtOC42NTZDMTguNjU2LDUuMjE5LDE0Ljc4MSwxLjM0NCwxMCwxLjM0NHogTTEwLDE3LjkwM2MtNC4zNjUsMC03LjkwNC0zLjUzOC03LjkwNC03LjkwM1M1LjYzNSwyLjA5NiwxMCwyLjA5NlMxNy45MDMsNS42MzUsMTcuOTAzLDEwUzE0LjM2NSwxNy45MDMsMTAsMTcuOTAzeiBNMTMuMzg4LDkuNjI0SDYuNjEzYy0wLjIwOCwwLTAuMzc2LDAuMTY4LTAuMzc2LDAuMzc2czAuMTY4LDAuMzc2LDAuMzc2LDAuMzc2aDYuNzc1YzAuMjA3LDAsMC4zNzctMC4xNjgsMC4zNzctMC4zNzZTMTMuNTk1LDkuNjI0LDEzLjM4OCw5LjYyNHonLFxuICAgICAgICAgICAgb25jbGljazogdGhpcy5yZXNldFpvb21BY3Rpb24uYmluZCh0aGlzKVxuICAgICAgICAgIH0gOiB7fSxcbiAgICAgICAgICBzYXZlQXNJbWFnZSA6IHtcbiAgICAgICAgICAgIHNob3c6IHRydWUsXG4gICAgICAgICAgICBpY29uOiAncGF0aDovL002LjUyMyw3LjY4M2MwLjk2LDAsMS43MzgtMC43NzgsMS43MzgtMS43MzhjMC0wLjk2LTAuNzc4LTEuNzM4LTEuNzM4LTEuNzM4Yy0wLjk2LDAtMS43MzgsMC43NzgtMS43MzgsMS43MzggQzQuNzg1LDYuOTA0LDUuNTYzLDcuNjgzLDYuNTIzLDcuNjgzeiBNNS45NDQsNS4zNjVoMS4xNTl2MS4xNTlINS45NDRWNS4zNjV6IE0xOC4xMTMsMC43MjlIMS44ODggYy0wLjY0LDAtMS4xNTksMC41MTktMS4xNTksMS4xNTl2MTYuMjI0YzAsMC42NCwwLjUxOSwxLjE1OSwxLjE1OSwxLjE1OWgxNi4yMjVjMC42MzksMCwxLjE1OC0wLjUyLDEuMTU4LTEuMTU5VjEuODg5IEMxOS4yNzEsMS4yNDksMTguNzUyLDAuNzI5LDE4LjExMywwLjcyOXogTTE4LjExMywxNy41MzJjMCwwLjMyMS0wLjI2MiwwLjU4LTAuNTgsMC41OEgyLjQ2N2MtMC4zMiwwLTAuNTc5LTAuMjU5LTAuNTc5LTAuNTggVjIuNDY4YzAtMC4zMiwwLjI1OS0wLjU3OSwwLjU3OS0wLjU3OWgxNS4wNjZjMC4zMTgsMCwwLjU4LDAuMjU5LDAuNTgsMC41NzlWMTcuNTMyeiBNMTUuOTEsNy44NWwtNC44NDIsNS4zODVsLTMuNTAyLTIuNDg4IGMtMC4xMjctMC4xMjctMC4yOTYtMC4xOC0wLjQ2My0wLjE3Yy0wLjE2Ny0wLjAwOS0wLjMzNiwwLjA0My0wLjQ2MywwLjE3bC0zLjQyNSw0LjU4NGMtMC4yMzcsMC4yMzYtMC4yMzcsMC42MTksMCwwLjg1NiBjMC4yMzYsMC4yMzYsMC42MiwwLjIzNiwwLjg1NiwwbDMuMTUyLTQuMjJsMy40OTEsMi40ODFjMC4xMjMsMC4xMjMsMC4yODQsMC4xNzksMC40NDYsMC4xNzRjMC4xNiwwLjAwNSwwLjMyLTAuMDUxLDAuNDQzLTAuMTc0IGw1LjE2Mi01Ljc0M2MwLjIzOC0wLjIzNiwwLjIzOC0wLjYxOSwwLTAuODU2QzE2LjUyOSw3LjYxNCwxNi4xNDYsNy42MTQsMTUuOTEsNy44NXonXG4gICAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGdldFhBeGlzT3B0aW9uKCk6YW55e1xuICAgIFxuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiAndGltZScsXG4gICAgICBwb3NpdGlvbjogJ3RvcCcsXG4gICAgICBzcGxpdExpbmU6IHtcbiAgICAgICAgICBsaW5lU3R5bGU6IHtcbiAgICAgICAgICAgICAgY29sb3I6IFsnI0U5RURGRiddXG4gICAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIGF4aXNMaW5lOiB7XG4gICAgICAgICAgc2hvdzogZmFsc2VcbiAgICAgIH0sXG4gICAgICBheGlzVGljazoge1xuICAgICAgICAgIGxpbmVTdHlsZToge1xuICAgICAgICAgICAgICBjb2xvcjogJyM5MjlBQkEnXG4gICAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIGF4aXNMYWJlbDoge1xuICAgICAgICAgIGNvbG9yOiAnIzkyOUFCQScsXG4gICAgICAgICAgaW5zaWRlOiBmYWxzZSxcbiAgICAgICAgICBhbGlnbjogJ2NlbnRlcicsXG4gICAgICAgICAgZm9ybWF0dGVyOiB0aGlzLmZvcm1hdExhYmVsRGF0ZS5iaW5kKHRoaXMpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZm9ybWF0TGFiZWxEYXRlKHZhbHVlOkRhdGUsIGluZGV4Om51bWJlcik6c3RyaW5ne1xuICAgIGxldCB2YWx1ZURhdGUgPSBuZXcgRGF0ZSh2YWx1ZSlcblxuICAgIGxldCBkYXlUb2RheSA9IHZhbHVlRGF0ZS5nZXREYXRlKClcbiAgICBsZXQgbW9udGhUb2RheSA9IHZhbHVlRGF0ZS5nZXRNb250aCgpXG4gICAgaWYodGhpcy5pc0ZpcnN0RGF5KGRheVRvZGF5LG1vbnRoVG9kYXkpKXtcbiAgICAgIHJldHVybiB0aGlzLmdldE1vbnRoTmFtZShtb250aFRvZGF5KVxuICAgIH1cbiAgICByZXR1cm4gZGF5VG9kYXkgKyBcIlwiO1xuICAgIC8qbGV0IERBVEVfRk9STUFUID0gdGhpcy5kYXRlRm9ybWF0XG4gICAgcmV0dXJuIGVjaGFydHMudGltZS5mb3JtYXQoXG4gICAgICAgIHZhbHVlLFxuICAgICAgICBEQVRFX0ZPUk1BVCxcbiAgICAgICAgZmFsc2VcbiAgICApOyovXG4gIH1cblxuICAvKipcbiAgICogXG4gICAqIEBwYXJhbSBkYXlUb2RheSBkYXkgcmVmZXJlbmNlIHRvIGNoZWNrIGlmIGlzIHRoZSBsYXN0IGRheSBvZiB0aGUgbW9udGhcbiAgICogQHBhcmFtIG1vbnRoICgwLTExKSBtb250aCByZWZlcmVuY2UgdG8gY2hlY2sgaWYgdGhlIGRheSBwYXNzZWQgaXMgdGhlIGxhc3QgZGF5IG9mIHRoZSBtb250aC5cbiAgICogQHJldHVybnMgdHJ1ZSBpZiBkYXkgaXMgdGhlIGxhc3QgZGF5IG9mIHRoZSBtb250aC4gRmFsc2Ugb3RoZXJ3aXNlXG4gICAqL1xuICBnZXRMYXN0RGF5TW9udGgoZGF5VG9kYXk6bnVtYmVyLCBtb250aDpudW1iZXIpOmJvb2xlYW57XG4gICAgLy92YXIgbW9udGggPSAwOyAvLyBKYW51YXJ5XG4gICAgdmFyIGQgPSBuZXcgRGF0ZShuZXcgRGF0ZSgpLmdldEZ1bGxZZWFyKCksIG1vbnRoICsgMSwgMCkuZ2V0RGF0ZSgpO1xuXG4gICAgcmV0dXJuIGQgPT0gZGF5VG9kYXlcbiAgfVxuXG4gIGlzRmlyc3REYXkoZGF5VG9kYXk6bnVtYmVyLCBtb250aDpudW1iZXIpOmJvb2xlYW57XG4gICAgcmV0dXJuIGRheVRvZGF5ID09IDFcbiAgfVxuXG4gIGdldE1vbnRoTmFtZShtb250aDpudW1iZXIpOnN0cmluZ3tcbiAgICBzd2l0Y2gobW9udGgpe1xuICAgICAgY2FzZSAwOlxuICAgICAgICByZXR1cm4gdGhpcy50cmFuc2xhdGlvbiA/IHRoaXMudHJhbnNsYXRpb24uSkFOVUFSWSA6IFwiSmFuXCJcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgcmV0dXJuIHRoaXMudHJhbnNsYXRpb24gPyB0aGlzLnRyYW5zbGF0aW9uLkZFQlJVQVJZIDogXCJGZXZcIlxuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gdGhpcy50cmFuc2xhdGlvbiA/IHRoaXMudHJhbnNsYXRpb24uTUFSQ0ggOiBcIk1hclwiXG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiB0aGlzLnRyYW5zbGF0aW9uID8gdGhpcy50cmFuc2xhdGlvbi5BUFJJTCA6IFwiQXByXCJcbiAgICAgIGNhc2UgNDpcbiAgICAgICAgcmV0dXJuIHRoaXMudHJhbnNsYXRpb24gPyB0aGlzLnRyYW5zbGF0aW9uLk1BWSA6IFwiTWF5XCJcbiAgICAgIGNhc2UgNTpcbiAgICAgICAgcmV0dXJuIHRoaXMudHJhbnNsYXRpb24gPyB0aGlzLnRyYW5zbGF0aW9uLkpVTkUgOiBcIkp1blwiXG4gICAgICBjYXNlIDY6XG4gICAgICAgIHJldHVybiB0aGlzLnRyYW5zbGF0aW9uID8gdGhpcy50cmFuc2xhdGlvbi5KVUxZIDogXCJKdWxcIlxuICAg