barsa-calendar 2.1.1 → 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/fesm2022/barsa-calendar.mjs +26 -21
  2. package/fesm2022/barsa-calendar.mjs.map +1 -1
  3. package/package.json +3 -5
  4. package/esm2022/barsa-calendar.mjs +0 -5
  5. package/esm2022/lib/barsa-calendar.module.mjs +0 -117
  6. package/esm2022/lib/calendar-container/calendar-container.component.mjs +0 -230
  7. package/esm2022/lib/calendar-header/calendar-header.component.mjs +0 -66
  8. package/esm2022/lib/calendar-list/calendar-list.component.mjs +0 -18
  9. package/esm2022/lib/calendar-list-container/calendar-list-container.component.mjs +0 -29
  10. package/esm2022/lib/calendar-list-item/calendar-list-item.component.mjs +0 -14
  11. package/esm2022/lib/calendar-month/calendar-month.component.mjs +0 -249
  12. package/esm2022/lib/calendar-selection-days/calendar-selection-days.component.mjs +0 -196
  13. package/esm2022/lib/calendar-week/calendar-week.component.mjs +0 -255
  14. package/esm2022/lib/constants.mjs +0 -4
  15. package/esm2022/lib/date-time-picker/date-time-picker.component.mjs +0 -457
  16. package/esm2022/lib/day-event-list/day-event-list.component.mjs +0 -58
  17. package/esm2022/lib/day-number-box/day-number-box.component.mjs +0 -105
  18. package/esm2022/lib/days-in-week.pipe.mjs +0 -17
  19. package/esm2022/lib/equal-date.pipe.mjs +0 -23
  20. package/esm2022/lib/event-button/event-button.component.mjs +0 -100
  21. package/esm2022/lib/event-button-end-arrow/event-button-end-arrow.component.mjs +0 -29
  22. package/esm2022/lib/event-button-start-arrow/event-button-start-arrow.component.mjs +0 -29
  23. package/esm2022/lib/event-date.pipe.mjs +0 -24
  24. package/esm2022/lib/event-preview/event-preview.component.mjs +0 -81
  25. package/esm2022/lib/event-time.pipe.mjs +0 -22
  26. package/esm2022/lib/from-to-time.pipe.mjs +0 -23
  27. package/esm2022/lib/models.mjs +0 -14
  28. package/esm2022/lib/month-days/month-days.component.mjs +0 -222
  29. package/esm2022/lib/services/calendar.service.mjs +0 -645
  30. package/esm2022/public-api.mjs +0 -23
@@ -1,196 +0,0 @@
1
- import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, Self } from '@angular/core';
2
- import { distinctUntilChanged, map } from 'rxjs/operators';
3
- import { BaseComponent, DateService, getDateService } from 'barsa-novin-ray-core';
4
- import { CalendarService } from '../services/calendar.service';
5
- import * as i0 from "@angular/core";
6
- import * as i1 from "../services/calendar.service";
7
- import * as i2 from "barsa-novin-ray-core";
8
- import * as i3 from "@angular/common";
9
- import * as i4 from "@fundamental-ngx/core/button";
10
- import * as i5 from "@fundamental-ngx/core/title";
11
- import * as i6 from "@fundamental-ngx/core/popover";
12
- import * as i7 from "@fundamental-ngx/core/toolbar";
13
- import * as i8 from "../calendar-month/calendar-month.component";
14
- export class CalendarSelectionDaysComponent extends BaseComponent {
15
- constructor(_calendarService, _portalService) {
16
- super();
17
- this._calendarService = _calendarService;
18
- this.rangeChange = new EventEmitter();
19
- this.selectionMode = 'day';
20
- this.months = [];
21
- this._isMouseDown = false;
22
- this.rtl$ = _portalService.rtl$;
23
- this.width$ = _portalService.deviceSize$.pipe(distinctUntilChanged(), map((deviceSize) => {
24
- switch (deviceSize) {
25
- case 'l':
26
- case 'xl':
27
- return 480;
28
- case 's':
29
- return 320;
30
- default:
31
- return 480;
32
- }
33
- }));
34
- this.weekDaysMin = this._calendarService.weekDaysMin();
35
- this._calendarService.setMode('month');
36
- this.weekDays = this._calendarService.weekDays();
37
- this.selectedMonth$ = this._calendarService.selected$;
38
- this.today = this._calendarService.today;
39
- this.months = this._calendarService.Months;
40
- this._prepareYear(this._calendarService.selectedMonth.dateInfo.year);
41
- }
42
- ngOnChanges(changes) {
43
- super.ngOnChanges(changes);
44
- const { monthInfo } = changes;
45
- if (monthInfo) {
46
- this._calendarService.loadCalendarMonthInfo(monthInfo.currentValue);
47
- }
48
- }
49
- onMonthSelected(monthName, index) {
50
- this._calendarService.gotoMonth(monthName, index);
51
- }
52
- onYearSelected(year) {
53
- this._calendarService.gotoYear(+year);
54
- }
55
- onPrevTap() {
56
- if (this.selectionMode === 'day') {
57
- this._calendarService.loadPrevious();
58
- }
59
- else if (this.selectionMode === 'month') {
60
- this._calendarService.loadPrevYear();
61
- }
62
- else if (this.selectionMode === 'year') {
63
- this._prepareYear(Number(this.years[0]) - 20);
64
- }
65
- }
66
- onNextTap() {
67
- if (this.selectionMode === 'day') {
68
- this._calendarService.loadNext();
69
- }
70
- else if (this.selectionMode === 'month') {
71
- this._calendarService.loadNextYear();
72
- }
73
- else if (this.selectionMode === 'year') {
74
- this._prepareYear(Number(this.years[this.years.length - 1]) + 1);
75
- }
76
- }
77
- onToday() {
78
- this._calendarService.gotoToday();
79
- }
80
- onDayMouseMove(day, monthInfo) {
81
- if (this._isMouseDown) {
82
- const { endDay, startDay } = this.getStartAndEndDay(monthInfo, day);
83
- this.startSelectedDayIndex = startDay?.index;
84
- this.endSelectedDayIndex = endDay?.index;
85
- // console.log('-move-', this.startSelectedDay?.index, this.endSelectedDay?.index);
86
- }
87
- }
88
- onDayMouseDown(day) {
89
- this._isMouseDown = true;
90
- this.startSelectedDay = null;
91
- this.endSelectedDay = null;
92
- this.startSelectedDay = day;
93
- this.startSelectedDayIndex = day.index;
94
- }
95
- onDayMouseUp(day, monthInfo, popover) {
96
- this._isMouseDown = false;
97
- const { endDay, startDay } = this.getStartAndEndDay(monthInfo, day);
98
- this.startSelectedDay = startDay;
99
- this.endSelectedDay = endDay;
100
- this._setFirstAndEndDay(monthInfo, popover);
101
- }
102
- onDayClick(day, monthInfo, popover) {
103
- this.startSelectedDay = this.endSelectedDay = day;
104
- this._setFirstAndEndDay(monthInfo, popover);
105
- }
106
- _prepareYear(from) {
107
- const years = [];
108
- for (let i = 0; i < 20; i++) {
109
- years.push(`${from + i}`);
110
- }
111
- this.years = years;
112
- }
113
- getStartAndEndDay(monthInfo, day) {
114
- let startDay = null;
115
- let endDay = null;
116
- if (this.startSelectedDay && !this.endSelectedDay) {
117
- if (day && this.startSelectedDay.date > day.date) {
118
- startDay = day;
119
- endDay = this.startSelectedDay;
120
- }
121
- else {
122
- startDay = this.startSelectedDay;
123
- endDay = day;
124
- }
125
- }
126
- else if (this.startSelectedDay && this.endSelectedDay) {
127
- if (day && this.startSelectedDay.date < day.date) {
128
- startDay = this.startSelectedDay;
129
- endDay = day;
130
- }
131
- else {
132
- startDay = day;
133
- endDay = this.endSelectedDay;
134
- }
135
- }
136
- // console.log('-2-', startDay, endDay);
137
- if (startDay && endDay) {
138
- const diff = Math.abs(startDay.momentOfDate.diff(endDay.momentOfDate, 'day'));
139
- if (diff > 6) {
140
- startDay = monthInfo.days[Math.floor(startDay.index / 7) * 7];
141
- // const end = endDay.index % 7;
142
- const indexEnd = Math.ceil((endDay.index + 1) / 7);
143
- // if (end > 0) {
144
- // indexEnd++;
145
- // }
146
- endDay = monthInfo.days[indexEnd * 7 - 1];
147
- // console.log('-3-', startDay, endDay);
148
- }
149
- }
150
- return { endDay, startDay };
151
- }
152
- _setFirstAndEndDay(monthInfo, popover) {
153
- // console.log('-finish-', this.startSelectedDay, this.endSelectedDay);
154
- if (this.startSelectedDay && this.endSelectedDay) {
155
- if (popover) {
156
- popover.close();
157
- }
158
- this.rangeChange.emit({
159
- startDay: this.startSelectedDay,
160
- endDay: this.endSelectedDay,
161
- monthInfo
162
- });
163
- }
164
- }
165
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CalendarSelectionDaysComponent, deps: [{ token: i1.CalendarService, self: true }, { token: i2.PortalService }], target: i0.ɵɵFactoryTarget.Component }); }
166
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: CalendarSelectionDaysComponent, selector: "bc-calendar-selection-days", inputs: { startSelectedDayIndex: "startSelectedDayIndex", endSelectedDayIndex: "endSelectedDayIndex", monthInfo: "monthInfo", inline: "inline" }, outputs: { rangeChange: "rangeChange" }, providers: [
167
- {
168
- provide: DateService,
169
- useFactory: getDateService
170
- },
171
- CalendarService
172
- ], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "@if (inline) {\n<ng-container\n *ngTemplateOutlet=\"\n month;\n context: {\n $implicit: selectedMonth$ | async,\n width: width$ | async,\n height: height,\n rtl: rtl$ | async,\n weekDays: weekDays,\n weekDaysMin: weekDaysMin,\n today: today,\n deviceSize: deviceSize$ | async,\n popover: popover\n }\n \"\n>\n</ng-container>\n} @else {\n<button fd-button glyph=\"calendar\" fdType=\"transparent\" [fdPopoverTrigger]=\"popover\"></button>\n}\n<fd-popover #popover [focusTrapped]=\"true\" [focusAutoCapture]=\"true\" [mobile]=\"(deviceSize$ | async) === 's'\">\n <fd-popover-body [style.width.px]=\"width$ | async\" class=\"popover-selection-day\">\n <ng-container\n *ngTemplateOutlet=\"\n month;\n context: {\n $implicit: selectedMonth$ | async,\n width: width$ | async,\n height: height,\n rtl: rtl$ | async,\n weekDays: weekDays,\n weekDaysMin: weekDaysMin,\n today: today,\n deviceSize: deviceSize$ | async,\n popover: popover\n }\n \"\n >\n </ng-container>\n </fd-popover-body>\n</fd-popover>\n\n<ng-template\n #month\n let-selectedMonth\n let-width=\"width\"\n let-height=\"height\"\n let-rtl=\"rtl\"\n let-today=\"today\"\n let-showEvents=\"showEvents\"\n let-deviceSize=\"deviceSize\"\n let-popover=\"popover\"\n>\n <fd-toolbar [fdType]=\"'transparent'\">\n <button fd-button fd-toolbar-item [label]=\"'DateR_Today' | bbbTranslate\" (click)=\"onToday()\"></button>\n <button\n fd-button\n fdType=\"transparent\"\n fd-toolbar-item\n [glyph]=\"rtl ? 'navigation-right-arrow' : 'navigation-left-arrow'\"\n (click)=\"onPrevTap()\"\n ></button>\n <button\n fd-button\n fdType=\"transparent\"\n fd-toolbar-item\n [glyph]=\"rtl ? 'navigation-left-arrow' : 'navigation-right-arrow'\"\n (click)=\"onNextTap()\"\n ></button>\n <div class=\"month-years-wrapper\" fd-title fd-toolbar-item>\n @if (selectionMode === 'day' || selectionMode === 'month') {\n <button\n fd-button\n [fdType]=\"'transparent'\"\n [label]=\"selectedMonth.dateInfo.monthName\"\n (click)=\"selectionMode = 'month'\"\n ></button>\n }\n <button\n fd-button\n [fdType]=\"'transparent'\"\n [label]=\"selectedMonth.dateInfo.year\"\n (click)=\"selectionMode = 'year'\"\n ></button>\n </div>\n </fd-toolbar>\n @switch (selectionMode) { @case ('month') {\n <div class=\"month-year-selection-wrapper\">\n @for (month of months; track month; let i = $index) {\n <button\n style=\"flex-grow: 1; width: 33%\"\n fd-button\n [fdType]=\"selectedMonth.dateInfo.monthName === month ? 'emphasized' : 'transparent'\"\n [label]=\"month\"\n (click)=\"selectionMode = 'day'; onMonthSelected(month, i)\"\n ></button>\n }\n </div>\n } @case ('year') {\n <div class=\"month-year-selection-wrapper\">\n @for (year of years; track year) {\n <button\n style=\"flex-grow: 1; width: 25%\"\n fd-button\n [fdType]=\"selectedMonth.dateInfo.year === +year ? 'emphasized' : 'transparent'\"\n [label]=\"year\"\n (click)=\"selectionMode = 'day'; onYearSelected(year)\"\n ></button>\n }\n </div>\n } @default {\n <bc-calendar-month\n [style.width]=\"width\"\n [containerHeight]=\"height\"\n [containerWidth]=\"width\"\n [rtl]=\"rtl\"\n [monthWeeksCount]=\"6\"\n [weekDays]=\"weekDays\"\n [weekDaysMin]=\"weekDaysMin\"\n [today]=\"today\"\n [datePicker]=\"true\"\n [dateRange]=\"true\"\n [days]=\"selectedMonth.days\"\n [deviceSize]=\"deviceSize\"\n (dayClick)=\"onDayClick($event, selectedMonth, popover)\"\n (dayMouseMove)=\"onDayMouseMove($event, selectedMonth)\"\n (dayMouseUp)=\"onDayMouseUp($event, selectedMonth, popover)\"\n (dayMouseDown)=\"onDayMouseDown($event)\"\n [startSelectedDayIndex]=\"startSelectedDayIndex\"\n [endSelectedDayIndex]=\"endSelectedDayIndex\"\n ></bc-calendar-month>\n } }\n</ng-template>\n", styles: [":host ::ng-deep .fd-toolbar{background-color:var(--sapBaseColor);height:2.8rem}\n"], dependencies: [{ kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.MobileDirective, selector: "[mobile]" }, { kind: "component", type: i4.ButtonComponent, selector: "button[fd-button], a[fd-button], span[fd-button]", inputs: ["class"], exportAs: ["fd-button"] }, { kind: "component", type: i5.TitleComponent, selector: "[fd-title], [fdTitle]", inputs: ["headerSize", "wrap"], exportAs: ["fd-title"] }, { kind: "component", type: i6.PopoverBodyComponent, selector: "fd-popover-body", inputs: ["minWidth", "maxWidth", "minHeight", "maxHeight"] }, { kind: "component", type: i6.PopoverComponent, selector: "fd-popover", inputs: ["title", "trigger", "fixedPosition", "id", "mobile", "mobileConfig", "preventSpaceKeyScroll"] }, { kind: "directive", type: i6.PopoverTriggerDirective, selector: "[fdPopoverTrigger], [fd-popover-trigger]", inputs: ["fdPopoverTrigger"] }, { kind: "component", type: i7.ToolbarComponent, selector: "fd-toolbar", inputs: ["titleId", "class", "shouldOverflow", "fdType", "title", "active", "clearBorder", "forceOverflow", "tabindex", "headingLevel", "ariaLabel", "ariaLabelledBy"] }, { kind: "directive", type: i7.ToolbarItemDirective, selector: "[fd-toolbar-item], [fdOverflowGroup], [fdOverflowPriority]", inputs: ["fdOverflowPriority", "fdOverflowGroup"] }, { kind: "component", type: i8.CalendarMonthComponent, selector: "bc-calendar-month", inputs: ["monthWeeksCount", "weekDays", "weekDaysMin", "today", "containerHeight", "days", "calendarFields", "rtl", "deviceSize", "moDataList", "datePicker", "rangePicker", "canDelete", "canAdd", "canEdit", "canView", "selectedDate", "startSelectedDayIndex", "endSelectedDayIndex"], outputs: ["editEvent", "deleteEvent", "daySelect", "dayClick", "dayMouseMove", "dayMouseUp", "dayMouseDown", "showEvent"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.BbbTranslatePipe, name: "bbbTranslate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
173
- }
174
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CalendarSelectionDaysComponent, decorators: [{
175
- type: Component,
176
- args: [{ selector: 'bc-calendar-selection-days', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
177
- {
178
- provide: DateService,
179
- useFactory: getDateService
180
- },
181
- CalendarService
182
- ], template: "@if (inline) {\n<ng-container\n *ngTemplateOutlet=\"\n month;\n context: {\n $implicit: selectedMonth$ | async,\n width: width$ | async,\n height: height,\n rtl: rtl$ | async,\n weekDays: weekDays,\n weekDaysMin: weekDaysMin,\n today: today,\n deviceSize: deviceSize$ | async,\n popover: popover\n }\n \"\n>\n</ng-container>\n} @else {\n<button fd-button glyph=\"calendar\" fdType=\"transparent\" [fdPopoverTrigger]=\"popover\"></button>\n}\n<fd-popover #popover [focusTrapped]=\"true\" [focusAutoCapture]=\"true\" [mobile]=\"(deviceSize$ | async) === 's'\">\n <fd-popover-body [style.width.px]=\"width$ | async\" class=\"popover-selection-day\">\n <ng-container\n *ngTemplateOutlet=\"\n month;\n context: {\n $implicit: selectedMonth$ | async,\n width: width$ | async,\n height: height,\n rtl: rtl$ | async,\n weekDays: weekDays,\n weekDaysMin: weekDaysMin,\n today: today,\n deviceSize: deviceSize$ | async,\n popover: popover\n }\n \"\n >\n </ng-container>\n </fd-popover-body>\n</fd-popover>\n\n<ng-template\n #month\n let-selectedMonth\n let-width=\"width\"\n let-height=\"height\"\n let-rtl=\"rtl\"\n let-today=\"today\"\n let-showEvents=\"showEvents\"\n let-deviceSize=\"deviceSize\"\n let-popover=\"popover\"\n>\n <fd-toolbar [fdType]=\"'transparent'\">\n <button fd-button fd-toolbar-item [label]=\"'DateR_Today' | bbbTranslate\" (click)=\"onToday()\"></button>\n <button\n fd-button\n fdType=\"transparent\"\n fd-toolbar-item\n [glyph]=\"rtl ? 'navigation-right-arrow' : 'navigation-left-arrow'\"\n (click)=\"onPrevTap()\"\n ></button>\n <button\n fd-button\n fdType=\"transparent\"\n fd-toolbar-item\n [glyph]=\"rtl ? 'navigation-left-arrow' : 'navigation-right-arrow'\"\n (click)=\"onNextTap()\"\n ></button>\n <div class=\"month-years-wrapper\" fd-title fd-toolbar-item>\n @if (selectionMode === 'day' || selectionMode === 'month') {\n <button\n fd-button\n [fdType]=\"'transparent'\"\n [label]=\"selectedMonth.dateInfo.monthName\"\n (click)=\"selectionMode = 'month'\"\n ></button>\n }\n <button\n fd-button\n [fdType]=\"'transparent'\"\n [label]=\"selectedMonth.dateInfo.year\"\n (click)=\"selectionMode = 'year'\"\n ></button>\n </div>\n </fd-toolbar>\n @switch (selectionMode) { @case ('month') {\n <div class=\"month-year-selection-wrapper\">\n @for (month of months; track month; let i = $index) {\n <button\n style=\"flex-grow: 1; width: 33%\"\n fd-button\n [fdType]=\"selectedMonth.dateInfo.monthName === month ? 'emphasized' : 'transparent'\"\n [label]=\"month\"\n (click)=\"selectionMode = 'day'; onMonthSelected(month, i)\"\n ></button>\n }\n </div>\n } @case ('year') {\n <div class=\"month-year-selection-wrapper\">\n @for (year of years; track year) {\n <button\n style=\"flex-grow: 1; width: 25%\"\n fd-button\n [fdType]=\"selectedMonth.dateInfo.year === +year ? 'emphasized' : 'transparent'\"\n [label]=\"year\"\n (click)=\"selectionMode = 'day'; onYearSelected(year)\"\n ></button>\n }\n </div>\n } @default {\n <bc-calendar-month\n [style.width]=\"width\"\n [containerHeight]=\"height\"\n [containerWidth]=\"width\"\n [rtl]=\"rtl\"\n [monthWeeksCount]=\"6\"\n [weekDays]=\"weekDays\"\n [weekDaysMin]=\"weekDaysMin\"\n [today]=\"today\"\n [datePicker]=\"true\"\n [dateRange]=\"true\"\n [days]=\"selectedMonth.days\"\n [deviceSize]=\"deviceSize\"\n (dayClick)=\"onDayClick($event, selectedMonth, popover)\"\n (dayMouseMove)=\"onDayMouseMove($event, selectedMonth)\"\n (dayMouseUp)=\"onDayMouseUp($event, selectedMonth, popover)\"\n (dayMouseDown)=\"onDayMouseDown($event)\"\n [startSelectedDayIndex]=\"startSelectedDayIndex\"\n [endSelectedDayIndex]=\"endSelectedDayIndex\"\n ></bc-calendar-month>\n } }\n</ng-template>\n", styles: [":host ::ng-deep .fd-toolbar{background-color:var(--sapBaseColor);height:2.8rem}\n"] }]
183
- }], ctorParameters: () => [{ type: i1.CalendarService, decorators: [{
184
- type: Self
185
- }] }, { type: i2.PortalService }], propDecorators: { startSelectedDayIndex: [{
186
- type: Input
187
- }], endSelectedDayIndex: [{
188
- type: Input
189
- }], monthInfo: [{
190
- type: Input
191
- }], inline: [{
192
- type: Input
193
- }], rangeChange: [{
194
- type: Output
195
- }] } });
196
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsZW5kYXItc2VsZWN0aW9uLWRheXMuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYmFyc2EtY2FsZW5kYXIvc3JjL2xpYi9jYWxlbmRhci1zZWxlY3Rpb24tZGF5cy9jYWxlbmRhci1zZWxlY3Rpb24tZGF5cy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9iYXJzYS1jYWxlbmRhci9zcmMvbGliL2NhbGVuZGFyLXNlbGVjdGlvbi1kYXlzL2NhbGVuZGFyLXNlbGVjdGlvbi1kYXlzLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDSCx1QkFBdUIsRUFDdkIsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBRUwsTUFBTSxFQUNOLElBQUksRUFFUCxNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsb0JBQW9CLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0QsT0FBTyxFQUFFLGFBQWEsRUFBRSxXQUFXLEVBQUUsY0FBYyxFQUFpQixNQUFNLHNCQUFzQixDQUFDO0FBRWpHLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQzs7Ozs7Ozs7OztBQWMvRCxNQUFNLE9BQU8sOEJBQStCLFNBQVEsYUFBYTtJQXlCN0QsWUFBNEIsZ0JBQWlDLEVBQUUsY0FBNkI7UUFDeEYsS0FBSyxFQUFFLENBQUM7UUFEZ0IscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFpQjtRQXBCbkQsZ0JBQVcsR0FBRyxJQUFJLFlBQVksRUFJcEMsQ0FBQztRQUNMLGtCQUFhLEdBQTZCLEtBQUssQ0FBQztRQVloRCxXQUFNLEdBQWEsRUFBRSxDQUFDO1FBRWQsaUJBQVksR0FBRyxLQUFLLENBQUM7UUFHekIsSUFBSSxDQUFDLElBQUksR0FBRyxjQUFjLENBQUMsSUFBSSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxNQUFNLEdB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LENBQUMsU0FBUyxFQUFFLE9BQU87UUFDekMsdUVBQXVFO1FBQ3ZFLElBQUksSUFBSSxDQUFDLGdCQUFnQixJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUMvQyxJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUNWLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNwQixDQUFDO1lBQ0QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUM7Z0JBQ2xCLFFBQVEsRUFBRSxJQUFJLENBQUMsZ0JBQWdCO2dCQUMvQixNQUFNLEVBQUUsSUFBSSxDQUFDLGNBQWM7Z0JBQzNCLFNBQVM7YUFDWixDQUFDLENBQUM7UUFDUCxDQUFDO0lBQ0wsQ0FBQzsrR0EvS1EsOEJBQThCO21HQUE5Qiw4QkFBOEIsZ1BBUjVCO1lBQ1A7Z0JBQ0ksT0FBTyxFQUFFLFdBQVc7Z0JBQ3BCLFVBQVUsRUFBRSxjQUFjO2FBQzdCO1lBQ0QsZUFBZTtTQUNsQixzRUMxQkwsdW9KQXNJQTs7NEZEMUdhLDhCQUE4QjtrQkFiMUMsU0FBUzsrQkFDSSw0QkFBNEIsbUJBR3JCLHVCQUF1QixDQUFDLE1BQU0sYUFDcEM7d0JBQ1A7NEJBQ0ksT0FBTyxFQUFFLFdBQVc7NEJBQ3BCLFVBQVUsRUFBRSxjQUFjO3lCQUM3Qjt3QkFDRCxlQUFlO3FCQUNsQjs7MEJBMkJZLElBQUk7cUVBeEJSLHFCQUFxQjtzQkFBN0IsS0FBSztnQkFDRyxtQkFBbUI7c0JBQTNCLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFDRyxNQUFNO3NCQUFkLEtBQUs7Z0JBQ0ksV0FBVztzQkFBcEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcclxuICAgIENvbXBvbmVudCxcclxuICAgIEV2ZW50RW1pdHRlcixcclxuICAgIElucHV0LFxyXG4gICAgT25DaGFuZ2VzLFxyXG4gICAgT3V0cHV0LFxyXG4gICAgU2VsZixcclxuICAgIFNpbXBsZUNoYW5nZXNcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgbWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5pbXBvcnQgeyBCYXNlQ29tcG9uZW50LCBEYXRlU2VydmljZSwgZ2V0RGF0ZVNlcnZpY2UsIFBvcnRhbFNlcnZpY2UgfSBmcm9tICdiYXJzYS1ub3Zpbi1yYXktY29yZSc7XHJcbmltcG9ydCB7IENhbGVuZGFyTW9udGhJbmZvLCBEYXkgfSBmcm9tICcuLi9tb2RlbHMnO1xyXG5pbXBvcnQgeyBDYWxlbmRhclNlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy9jYWxlbmRhci5zZXJ2aWNlJztcclxuQENvbXBvbmVudCh7XHJcbiAgICBzZWxlY3RvcjogJ2JjLWNhbGVuZGFyLXNlbGVjdGlvbi1kYXlzJyxcclxuICAgIHRlbXBsYXRlVXJsOiAnLi9jYWxlbmRhci1zZWxlY3Rpb24tZGF5cy5jb21wb25lbnQuaHRtbCcsXHJcbiAgICBzdHlsZVVybHM6IFsnLi9jYWxlbmRhci1zZWxlY3Rpb24tZGF5cy5jb21wb25lbnQuc2NzcyddLFxyXG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXHJcbiAgICBwcm92aWRlcnM6IFtcclxuICAgICAgICB7XHJcbiAgICAgICAgICAgIHByb3ZpZGU6IERhdGVTZXJ2aWNlLFxyXG4gICAgICAgICAgICB1c2VGYWN0b3J5OiBnZXREYXRlU2VydmljZVxyXG4gICAgICAgIH0sXHJcbiAgICAgICAgQ2FsZW5kYXJTZXJ2aWNlXHJcbiAgICBdXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBDYWxlbmRhclNlbGVjdGlvbkRheXNDb21wb25lbnQgZXh0ZW5kcyBCYXNlQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzIHtcclxuICAgIEBJbnB1dCgpIHN0YXJ0U2VsZWN0ZWREYXlJbmRleDogbnVtYmVyIHwgdW5kZWZpbmVkO1xyXG4gICAgQElucHV0KCkgZW5kU2VsZWN0ZWREYXlJbmRleDogbnVtYmVyIHwgdW5kZWZpbmVkO1xyXG4gICAgQElucHV0KCkgbW9udGhJbmZvOiBDYWxlbmRhck1vbnRoSW5mbztcclxuICAgIEBJbnB1dCgpIGlubGluZTogYm9vbGVhbjtcclxuICAgIEBPdXRwdXQoKSByYW5nZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8e1xyXG4gICAgICAgIHN0YXJ0RGF5OiBEYXk7XHJcbiAgICAgICAgZW5kRGF5OiBEYXk7XHJcbiAgICAgICAgbW9udGhJbmZvOiBDYWxlbmRhck1vbnRoSW5mbztcclxuICAgIH0+KCk7XHJcbiAgICBzZWxlY3Rpb25Nb2RlOiAnZGF5JyB8ICdtb250aCcgfCAneWVhcicgPSAnZGF5JztcclxuXHJcbiAgICBlbmRTZWxlY3RlZERheTogRGF5IHwgbnVsbDtcclxuICAgIHN0YXJ0U2VsZWN0ZWREYXk6IERheSB8IG51bGw7XHJcbiAgICB3aWR0aCQ6IE9ic2VydmFibGU8bnVtYmVyPjtcclxuICAgIGhlaWdodDogbnVtYmVyO1xyXG4gICAgc2VsZWN0ZWRNb250aCQ6IE9ic2VydmFibGU8Q2FsZW5kYXJNb250aEluZm8+O1xyXG4gICAgcnRsJDogT2JzZXJ2YWJsZTxib29sZWFuPjtcclxuICAgIHRvZGF5OiBEYXRlO1xyXG4gICAgd2Vla0RheXNNaW46IHN0cmluZ1tdO1xyXG4gICAgd2Vla0RheXM6IHN0cmluZ1tdO1xyXG4gICAgZGV2aWNlU2l6ZSQ6IE9ic2VydmFibGU8c3RyaW5nPjtcclxuICAgIG1vbnRoczogc3RyaW5nW10gPSBbXTtcclxuICAgIHllYXJzOiBzdHJpbmdbXTtcclxuICAgIHByaXZhdGUgX2lzTW91c2VEb3duID0gZmFsc2U7XHJcbiAgICBjb25zdHJ1Y3RvcihAU2VsZigpIHByaXZhdGUgX2NhbGVuZGFyU2VydmljZTogQ2FsZW5kYXJTZXJ2aWNlLCBfcG9ydGFsU2VydmljZTogUG9ydGFsU2VydmljZSkge1xyXG4gICAgICAgIHN1cGVyKCk7XHJcbiAgICAgICAgdGhpcy5ydGwkID0gX3BvcnRhbFNlcnZpY2UucnRsJDtcclxuICAgICAgICB0aGlzLndpZHRoJCA9IF9wb3J0YWxTZXJ2aWNlLmRldmljZVNpemUkLnBpcGUoXHJcbiAgICAgICAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksXHJcbiAgICAgICAgICAgIG1hcCgoZGV2aWNlU2l6ZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgc3dpdGNoIChkZXZpY2VTaXplKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnbCc6XHJcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAneGwnOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gNDgwO1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3MnOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gMzIwO1xyXG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiA0ODA7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuICAgICAgICB0aGlzLndlZWtEYXlzTWluID0gdGhpcy5fY2FsZW5kYXJTZXJ2aWNlLndlZWtEYXlzTWluKCk7XHJcbiAgICAgICAgdGhpcy5fY2FsZW5kYXJTZXJ2aWNlLnNldE1vZGUoJ21vbnRoJyk7XHJcbiAgICAgICAgdGhpcy53ZWVrRGF5cyA9IHRoaXMuX2NhbGVuZGFyU2VydmljZS53ZWVrRGF5cygpO1xyXG4gICAgICAgIHRoaXMuc2VsZWN0ZWRNb250aCQgPSB0aGlzLl9jYWxlbmRhclNlcnZpY2Uuc2VsZWN0ZWQkO1xyXG4gICAgICAgIHRoaXMudG9kYXkgPSB0aGlzLl9jYWxlbmRhclNlcnZpY2UudG9kYXk7XHJcbiAgICAgICAgdGhpcy5tb250aHMgPSB0aGlzLl9jYWxlbmRhclNlcnZpY2UuTW9udGhzO1xyXG4gICAgICAgIHRoaXMuX3ByZXBhcmVZZWFyKHRoaXMuX2NhbGVuZGFyU2VydmljZS5zZWxlY3RlZE1vbnRoLmRhdGVJbmZvLnllYXIpO1xyXG4gICAgfVxyXG5cclxuICAgIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcclxuICAgICAgICBzdXBlci5uZ09uQ2hhbmdlcyhjaGFuZ2VzKTtcclxuICAgICAgICBjb25zdCB7IG1vbnRoSW5mbyB9ID0gY2hhbmdlcztcclxuICAgICAgICBpZiAobW9udGhJbmZvKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX2NhbGVuZGFyU2VydmljZS5sb2FkQ2FsZW5kYXJNb250aEluZm8obW9udGhJbmZvLmN1cnJlbnRWYWx1ZSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgb25Nb250aFNlbGVjdGVkKG1vbnRoTmFtZTogc3RyaW5nLCBpbmRleDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5fY2FsZW5kYXJTZXJ2aWNlLmdvdG9Nb250aChtb250aE5hbWUsIGluZGV4KTtcclxuICAgIH1cclxuICAgIG9uWWVhclNlbGVjdGVkKHllYXI6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuX2NhbGVuZGFyU2VydmljZS5nb3RvWWVhcigreWVhcik7XHJcbiAgICB9XHJcblxyXG4gICAgb25QcmV2VGFwKCk6IHZvaWQge1xyXG4gICAgICAgIGlmICh0aGlzLnNlbGVjdGlvbk1vZGUgPT09ICdkYXknKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX2NhbGVuZGFyU2VydmljZS5sb2FkUHJldmlvdXMoKTtcclxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2VsZWN0aW9uTW9kZSA9PT0gJ21vbnRoJykge1xyXG4gICAgICAgICAgICB0aGlzLl9jYWxlbmRhclNlcnZpY2UubG9hZFByZXZZZWFyKCk7XHJcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNlbGVjdGlvbk1vZGUgPT09ICd5ZWFyJykge1xyXG4gICAgICAgICAgICB0aGlzLl9wcmVwYXJlWWVhcihOdW1iZXIodGhpcy55ZWFyc1swXSkgLSAyMCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIG9uTmV4dFRhcCgpOiB2b2lkIHtcclxuICAgICAgICBpZiAodGhpcy5zZWxlY3Rpb25Nb2RlID09PSAnZGF5Jykge1xyXG4gICAgICAgICAgICB0aGlzLl9jYWxlbmRhclNlcnZpY2UubG9hZE5leHQoKTtcclxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2VsZWN0aW9uTW9kZSA9PT0gJ21vbnRoJykge1xyXG4gICAgICAgICAgICB0aGlzLl9jYWxlbmRhclNlcnZpY2UubG9hZE5leHRZZWFyKCk7XHJcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNlbGVjdGlvbk1vZGUgPT09ICd5ZWFyJykge1xyXG4gICAgICAgICAgICB0aGlzLl9wcmVwYXJlWWVhcihOdW1iZXIodGhpcy55ZWFyc1t0aGlzLnllYXJzLmxlbmd0aCAtIDFdKSArIDEpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBvblRvZGF5KCk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuX2NhbGVuZGFyU2VydmljZS5nb3RvVG9kYXkoKTtcclxuICAgIH1cclxuICAgIG9uRGF5TW91c2VNb3ZlKGRheTogRGF5LCBtb250aEluZm86IENhbGVuZGFyTW9udGhJbmZvKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKHRoaXMuX2lzTW91c2VEb3duKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHsgZW5kRGF5LCBzdGFydERheSB9ID0gdGhpcy5nZXRTdGFydEFuZEVuZERheShtb250aEluZm8sIGRheSk7XHJcbiAgICAgICAgICAgIHRoaXMuc3RhcnRTZWxlY3RlZERheUluZGV4ID0gc3RhcnREYXk/LmluZGV4O1xyXG4gICAgICAgICAgICB0aGlzLmVuZFNlbGVjdGVkRGF5SW5kZXggPSBlbmREYXk/LmluZGV4O1xyXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnLW1vdmUtJywgdGhpcy5zdGFydFNlbGVjdGVkRGF5Py5pbmRleCwgdGhpcy5lbmRTZWxlY3RlZERheT8uaW5kZXgpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBvbkRheU1vdXNlRG93bihkYXk6IERheSk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuX2lzTW91c2VEb3duID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLnN0YXJ0U2VsZWN0ZWREYXkgPSBudWxsO1xyXG4gICAgICAgIHRoaXMuZW5kU2VsZWN0ZWREYXkgPSBudWxsO1xyXG4gICAgICAgIHRoaXMuc3RhcnRTZWxlY3RlZERheSA9IGRheTtcclxuICAgICAgICB0aGlzLnN0YXJ0U2VsZWN0ZWREYXlJbmRleCA9IGRheS5pbmRleDtcclxuICAgIH1cclxuICAgIG9uRGF5TW91c2VVcChkYXk6IERheSwgbW9udGhJbmZvLCBwb3BvdmVyKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5faXNNb3VzZURvd24gPSBmYWxzZTtcclxuXHJcbiAgICAgICAgY29uc3QgeyBlbmREYXksIHN0YXJ0RGF5IH0gPSB0aGlzLmdldFN0YXJ0QW5kRW5kRGF5KG1vbnRoSW5mbywgZGF5KTtcclxuICAgICAgICB0aGlzLnN0YXJ0U2VsZWN0ZWREYXkgPSBzdGFydERheTtcclxuICAgICAgICB0aGlzLmVuZFNlbGVjdGVkRGF5ID0gZW5kRGF5O1xyXG4gICAgICAgIHRoaXMuX3NldEZpcnN0QW5kRW5kRGF5KG1vbnRoSW5mbywgcG9wb3Zlcik7XHJcbiAgICB9XHJcbiAgICBvbkRheUNsaWNrKGRheTogRGF5LCBtb250aEluZm8sIHBvcG92ZXIpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLnN0YXJ0U2VsZWN0ZWREYXkgPSB0aGlzLmVuZFNlbGVjdGVkRGF5ID0gZGF5O1xyXG4gICAgICAgIHRoaXMuX3NldEZpcnN0QW5kRW5kRGF5KG1vbnRoSW5mbywgcG9wb3Zlcik7XHJcbiAgICB9XHJcbiAgICBwcml2YXRlIF9wcmVwYXJlWWVhcihmcm9tOiBudW1iZXIpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCB5ZWFyczogc3RyaW5nW10gPSBbXTtcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDIwOyBpKyspIHtcclxuICAgICAgICAgICAgeWVhcnMucHVzaChgJHtmcm9tICsgaX1gKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy55ZWFycyA9IHllYXJzO1xyXG4gICAgfVxyXG4gICAgcHJpdmF0ZSBnZXRTdGFydEFuZEVuZERheShcclxuICAgICAgICBtb250aEluZm86IENhbGVuZGFyTW9udGhJbmZvLFxyXG4gICAgICAgIGRheTogRGF5IHwgbnVsbFxyXG4gICAgKTogeyBlbmREYXk6IERheSB8IG51bGw7IHN0YXJ0RGF5OiBEYXkgfCBudWxsIH0ge1xyXG4gICAgICAgIGxldCBzdGFydERheTogRGF5IHwgbnVsbCA9IG51bGw7XHJcbiAgICAgICAgbGV0IGVuZERheTogRGF5IHwgbnVsbCA9IG51bGw7XHJcbiAgICAgICAgaWYgKHRoaXMuc3RhcnRTZWxlY3RlZERheSAmJiAhdGhpcy5lbmRTZWxlY3RlZERheSkge1xyXG4gICAgICAgICAgICBpZiAoZGF5ICYmIHRoaXMuc3RhcnRTZWxlY3RlZERheS5kYXRlID4gZGF5LmRhdGUpIHtcclxuICAgICAgICAgICAgICAgIHN0YXJ0RGF5ID0gZGF5O1xyXG4gICAgICAgICAgICAgICAgZW5kRGF5ID0gdGhpcy5zdGFydFNlbGVjdGVkRGF5O1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgc3RhcnREYXkgPSB0aGlzLnN0YXJ0U2VsZWN0ZWREYXk7XHJcbiAgICAgICAgICAgICAgICBlbmREYXkgPSBkYXk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc3RhcnRTZWxlY3RlZERheSAmJiB0aGlzLmVuZFNlbGVjdGVkRGF5KSB7XHJcbiAgICAgICAgICAgIGlmIChkYXkgJiYgdGhpcy5zdGFydFNlbGVjdGVkRGF5LmRhdGUgPCBkYXkuZGF0ZSkge1xyXG4gICAgICAgICAgICAgICAgc3RhcnREYXkgPSB0aGlzLnN0YXJ0U2VsZWN0ZWREYXk7XHJcbiAgICAgICAgICAgICAgICBlbmREYXkgPSBkYXk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBzdGFydERheSA9IGRheTtcclxuICAgICAgICAgICAgICAgIGVuZERheSA9IHRoaXMuZW5kU2VsZWN0ZWREYXk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gY29uc29sZS5sb2coJy0yLScsIHN0YXJ0RGF5LCBlbmREYXkpO1xyXG4gICAgICAgIGlmIChzdGFydERheSAmJiBlbmREYXkpIHtcclxuICAgICAgICAgICAgY29uc3QgZGlmZiA9IE1hdGguYWJzKHN0YXJ0RGF5Lm1vbWVudE9mRGF0ZS5kaWZmKGVuZERheS5tb21lbnRPZkRhdGUsICdkYXknKSk7XHJcbiAgICAgICAgICAgIGlmIChkaWZmID4gNikge1xyXG4gICAgICAgICAgICAgICAgc3RhcnREYXkgPSBtb250aEluZm8uZGF5c1tNYXRoLmZsb29yKHN0YXJ0RGF5LmluZGV4IC8gNykgKiA3XTtcclxuICAgICAgICAgICAgICAgIC8vIGNvbnN0IGVuZCA9IGVuZERheS5pbmRleCAlIDc7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBpbmRleEVuZCA9IE1hdGguY2VpbCgoZW5kRGF5LmluZGV4ICsgMSkgLyA3KTtcclxuICAgICAgICAgICAgICAgIC8vIGlmIChlbmQgPiAwKSB7XHJcbiAgICAgICAgICAgICAgICAvLyAgICAgaW5kZXhFbmQrKztcclxuICAgICAgICAgICAgICAgIC8vIH1cclxuICAgICAgICAgICAgICAgIGVuZERheSA9IG1vbnRoSW5mby5kYXlzW2luZGV4RW5kICogNyAtIDFdO1xyXG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJy0zLScsIHN0YXJ0RGF5LCBlbmREYXkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB7IGVuZERheSwgc3RhcnREYXkgfTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9zZXRGaXJzdEFuZEVuZERheShtb250aEluZm8sIHBvcG92ZXIpOiB2b2lkIHtcclxuICAgICAgICAvLyBjb25zb2xlLmxvZygnLWZpbmlzaC0nLCB0aGlzLnN0YXJ0U2VsZWN0ZWREYXksIHRoaXMuZW5kU2VsZWN0ZWREYXkpO1xyXG4gICAgICAgIGlmICh0aGlzLnN0YXJ0U2VsZWN0ZWREYXkgJiYgdGhpcy5lbmRTZWxlY3RlZERheSkge1xyXG4gICAgICAgICAgICBpZiAocG9wb3Zlcikge1xyXG4gICAgICAgICAgICAgICAgcG9wb3Zlci5jbG9zZSgpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHRoaXMucmFuZ2VDaGFuZ2UuZW1pdCh7XHJcbiAgICAgICAgICAgICAgICBzdGFydERheTogdGhpcy5zdGFydFNlbGVjdGVkRGF5LFxyXG4gICAgICAgICAgICAgICAgZW5kRGF5OiB0aGlzLmVuZFNlbGVjdGVkRGF5LFxyXG4gICAgICAgICAgICAgICAgbW9udGhJbmZvXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG4iLCJAaWYgKGlubGluZSkge1xuPG5nLWNvbnRhaW5lclxuICAgICpuZ1RlbXBsYXRlT3V0bGV0PVwiXG4gICAgICAgIG1vbnRoO1xuICAgICAgICBjb250ZXh0OiB7XG4gICAgICAgICAgICAkaW1wbGljaXQ6IHNlbGVjdGVkTW9udGgkIHwgYXN5bmMsXG4gICAgICAgICAgICB3aWR0aDogd2lkdGgkIHwgYXN5bmMsXG4gICAgICAgICAgICBoZWlnaHQ6IGhlaWdodCxcbiAgICAgICAgICAgIHJ0bDogcnRsJCB8IGFzeW5jLFxuICAgICAgICAgICAgd2Vla0RheXM6IHdlZWtEYXlzLFxuICAgICAgICAgICAgd2Vla0RheXNNaW46IHdlZWtEYXlzTWluLFxuICAgICAgICAgICAgdG9kYXk6IHRvZGF5LFxuICAgICAgICAgICAgZGV2aWNlU2l6ZTogZGV2aWNlU2l6ZSQgfCBhc3luYyxcbiAgICAgICAgICAgIHBvcG92ZXI6IHBvcG92ZXJcbiAgICAgICAgfVxuICAgIFwiXG4+XG48L25nLWNvbnRhaW5lcj5cbn0gQGVsc2Uge1xuPGJ1dHRvbiBmZC1idXR0b24gZ2x5cGg9XCJjYWxlbmRhclwiIGZkVHlwZT1cInRyYW5zcGFyZW50XCIgW2ZkUG9wb3ZlclRyaWdnZXJdPVwicG9wb3ZlclwiPjwvYnV0dG9uPlxufVxuPGZkLXBvcG92ZXIgI3BvcG92ZXIgW2ZvY3VzVHJhcHBlZF09XCJ0cnVlXCIgW2ZvY3VzQXV0b0NhcHR1cmVdPVwidHJ1ZVwiIFttb2JpbGVdPVwiKGRldmljZVNpemUkIHwgYXN5bmMpID09PSAncydcIj5cbiAgICA8ZmQtcG9wb3Zlci1ib2R5IFtzdHlsZS53aWR0aC5weF09XCJ3aWR0aCQgfCBhc3luY1wiIGNsYXNzPVwicG9wb3Zlci1zZWxlY3Rpb24tZGF5XCI+XG4gICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICpuZ1RlbXBsYXRlT3V0bGV0PVwiXG4gICAgICAgICAgICAgICAgbW9udGg7XG4gICAgICAgICAgICAgICAgY29udGV4dDoge1xuICAgICAgICAgICAgICAgICAgICAkaW1wbGljaXQ6IHNlbGVjdGVkTW9udGgkIHwgYXN5bmMsXG4gICAgICAgICAgICAgICAgICAgIHdpZHRoOiB3aWR0aCQgfCBhc3luYyxcbiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQsXG4gICAgICAgICAgICAgICAgICAgIHJ0bDogcnRsJCB8IGFzeW5jLFxuICAgICAgICAgICAgICAgICAgICB3ZWVrRGF5czogd2Vla0RheXMsXG4gICAgICAgICAgICAgICAgICAgIHdlZWtEYXlzTWluOiB3ZWVrRGF5c01pbixcbiAgICAgICAgICAgICAgICAgICAgdG9kYXk6IHRvZGF5LFxuICAgICAgICAgICAgICAgICAgICBkZXZpY2VTaXplOiBkZXZpY2VTaXplJCB8IGFzeW5jLFxuICAgICAgICAgICAgICAgICAgICBwb3BvdmVyOiBwb3BvdmVyXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXCJcbiAgICAgICAgPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8L2ZkLXBvcG92ZXItYm9keT5cbjwvZmQtcG9wb3Zlcj5cblxuPG5nLXRlbXBsYXRlXG4gICAgI21vbnRoXG4gICAgbGV0LXNlbGVjdGVkTW9udGhcbiAgICBsZXQtd2lkdGg9XCJ3aWR0aFwiXG4gICAgbGV0LWhlaWdodD1cImhlaWdodFwiXG4gICAgbGV0LXJ0bD1cInJ0bFwiXG4gICAgbGV0LXRvZGF5PVwidG9kYXlcIlxuICAgIGxldC1zaG93RXZlbnRzPVwic2hvd0V2ZW50c1wiXG4gICAgbGV0LWRldmljZVNpemU9XCJkZXZpY2VTaXplXCJcbiAgICBsZXQtcG9wb3Zlcj1cInBvcG92ZXJcIlxuPlxuICAgIDxmZC10b29sYmFyIFtmZFR5cGVdPVwiJ3RyYW5zcGFyZW50J1wiPlxuICAgICAgICA8YnV0dG9uIGZkLWJ1dHRvbiBmZC10b29sYmFyLWl0ZW0gW2xhYmVsXT1cIidEYXRlUl9Ub2RheScgfCBiYmJUcmFuc2xhdGVcIiAoY2xpY2spPVwib25Ub2RheSgpXCI+PC9idXR0b24+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIGZkLWJ1dHRvblxuICAgICAgICAgICAgZmRUeXBlPVwidHJhbnNwYXJlbnRcIlxuICAgICAgICAgICAgZmQtdG9vbGJhci1pdGVtXG4gICAgICAgICAgICBbZ2x5cGhdPVwicnRsID8gJ25hdmlnYXRpb24tcmlnaHQtYXJyb3cnIDogJ25hdmlnYXRpb24tbGVmdC1hcnJvdydcIlxuICAgICAgICAgICAgKGNsaWNrKT1cIm9uUHJldlRhcCgpXCJcbiAgICAgICAgPjwvYnV0dG9uPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICBmZC1idXR0b25cbiAgICAgICAgICAgIGZkVHlwZT1cInRyYW5zcGFyZW50XCJcbiAgICAgICAgICAgIGZkLXRvb2xiYXItaXRlbVxuICAgICAgICAgICAgW2dseXBoXT1cInJ0bCA/ICduYXZpZ2F0aW9uLWxlZnQtYXJyb3cnIDogJ25hdmlnYXRpb24tcmlnaHQtYXJyb3cnXCJcbiAgICAgICAgICAgIChjbGljayk9XCJvbk5leHRUYXAoKVwiXG4gICAgICAgID48L2J1dHRvbj5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm1vbnRoLXllYXJzLXdyYXBwZXJcIiBmZC10aXRsZSBmZC10b29sYmFyLWl0ZW0+XG4gICAgICAgICAgICBAaWYgKHNlbGVjdGlvbk1vZGUgPT09ICdkYXknIHx8IHNlbGVjdGlvbk1vZGUgPT09ICdtb250aCcpIHtcbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICBmZC1idXR0b25cbiAgICAgICAgICAgICAgICBbZmRUeXBlXT1cIid0cmFuc3BhcmVudCdcIlxuICAgICAgICAgICAgICAgIFtsYWJlbF09XCJzZWxlY3RlZE1vbnRoLmRhdGVJbmZvLm1vbnRoTmFtZVwiXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cInNlbGVjdGlvbk1vZGUgPSAnbW9udGgnXCJcbiAgICAgICAgICAgID48L2J1dHRvbj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICBmZC1idXR0b25cbiAgICAgICAgICAgICAgICBbZmRUeXBlXT1cIid0cmFuc3BhcmVudCdcIlxuICAgICAgICAgICAgICAgIFtsYWJlbF09XCJzZWxlY3RlZE1vbnRoLmRhdGVJbmZvLnllYXJcIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJzZWxlY3Rpb25Nb2RlID0gJ3llYXInXCJcbiAgICAgICAgICAgID48L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgPC9mZC10b29sYmFyPlxuICAgIEBzd2l0Y2ggKHNlbGVjdGlvbk1vZGUpIHsgQGNhc2UgKCdtb250aCcpIHtcbiAgICA8ZGl2IGNsYXNzPVwibW9udGgteWVhci1zZWxlY3Rpb24td3JhcHBlclwiPlxuICAgICAgICBAZm9yIChtb250aCBvZiBtb250aHM7IHRyYWNrIG1vbnRoOyBsZXQgaSA9ICRpbmRleCkge1xuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICBzdHlsZT1cImZsZXgtZ3JvdzogMTsgd2lkdGg6IDMzJVwiXG4gICAgICAgICAgICBmZC1idXR0b25cbiAgICAgICAgICAgIFtmZFR5cGVdPVwic2VsZWN0ZWRNb250aC5kYXRlSW5mby5tb250aE5hbWUgPT09IG1vbnRoID8gJ2VtcGhhc2l6ZWQnIDogJ3RyYW5zcGFyZW50J1wiXG4gICAgICAgICAgICBbbGFiZWxdPVwibW9udGhcIlxuICAgICAgICAgICAgKGNsaWNrKT1cInNlbGVjdGlvbk1vZGUgPSAnZGF5Jzsgb25Nb250aFNlbGVjdGVkKG1vbnRoLCBpKVwiXG4gICAgICAgID48L2J1dHRvbj5cbiAgICAgICAgfVxuICAgIDwvZGl2PlxuICAgIH0gQGNhc2UgKCd5ZWFyJykge1xuICAgIDxkaXYgY2xhc3M9XCJtb250aC15ZWFyLXNlbGVjdGlvbi13cmFwcGVyXCI+XG4gICAgICAgIEBmb3IgKHllYXIgb2YgeWVhcnM7IHRyYWNrIHllYXIpIHtcbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgc3R5bGU9XCJmbGV4LWdyb3c6IDE7IHdpZHRoOiAyNSVcIlxuICAgICAgICAgICAgZmQtYnV0dG9uXG4gICAgICAgICAgICBbZmRUeXBlXT1cInNlbGVjdGVkTW9udGguZGF0ZUluZm8ueWVhciA9PT0gK3llYXIgPyAnZW1waGFzaXplZCcgOiAndHJhbnNwYXJlbnQnXCJcbiAgICAgICAgICAgIFtsYWJlbF09XCJ5ZWFyXCJcbiAgICAgICAgICAgIChjbGljayk9XCJzZWxlY3Rpb25Nb2RlID0gJ2RheSc7IG9uWWVhclNlbGVjdGVkKHllYXIpXCJcbiAgICAgICAgPjwvYnV0dG9uPlxuICAgICAgICB9XG4gICAgPC9kaXY+XG4gICAgfSBAZGVmYXVsdCB7XG4gICAgPGJjLWNhbGVuZGFyLW1vbnRoXG4gICAgICAgIFtzdHlsZS53aWR0aF09XCJ3aWR0aFwiXG4gICAgICAgIFtjb250YWluZXJIZWlnaHRdPVwiaGVpZ2h0XCJcbiAgICAgICAgW2NvbnRhaW5lcldpZHRoXT1cIndpZHRoXCJcbiAgICAgICAgW3J0bF09XCJydGxcIlxuICAgICAgICBbbW9udGhXZWVrc0NvdW50XT1cIjZcIlxuICAgICAgICBbd2Vla0RheXNdPVwid2Vla0RheXNcIlxuICAgICAgICBbd2Vla0RheXNNaW5dPVwid2Vla0RheXNNaW5cIlxuICAgICAgICBbdG9kYXldPVwidG9kYXlcIlxuICAgICAgICBbZGF0ZVBpY2tlcl09XCJ0cnVlXCJcbiAgICAgICAgW2RhdGVSYW5nZV09XCJ0cnVlXCJcbiAgICAgICAgW2RheXNdPVwic2VsZWN0ZWRNb250aC5kYXlzXCJcbiAgICAgICAgW2RldmljZVNpemVdPVwiZGV2aWNlU2l6ZVwiXG4gICAgICAgIChkYXlDbGljayk9XCJvbkRheUNsaWNrKCRldmVudCwgc2VsZWN0ZWRNb250aCwgcG9wb3ZlcilcIlxuICAgICAgICAoZGF5TW91c2VNb3ZlKT1cIm9uRGF5TW91c2VNb3ZlKCRldmVudCwgc2VsZWN0ZWRNb250aClcIlxuICAgICAgICAoZGF5TW91c2VVcCk9XCJvbkRheU1vdXNlVXAoJGV2ZW50LCBzZWxlY3RlZE1vbnRoLCBwb3BvdmVyKVwiXG4gICAgICAgIChkYXlNb3VzZURvd24pPVwib25EYXlNb3VzZURvd24oJGV2ZW50KVwiXG4gICAgICAgIFtzdGFydFNlbGVjdGVkRGF5SW5kZXhdPVwic3RhcnRTZWxlY3RlZERheUluZGV4XCJcbiAgICAgICAgW2VuZFNlbGVjdGVkRGF5SW5kZXhdPVwiZW5kU2VsZWN0ZWREYXlJbmRleFwiXG4gICAgPjwvYmMtY2FsZW5kYXItbW9udGg+XG4gICAgfSB9XG48L25nLXRlbXBsYXRlPlxuIl19