@seniorsistemas/angular-components 19.5.5 → 19.6.0
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.
- package/accordion/README.md +95 -59
- package/calendar-mask/lib/calendar-mask/calendar-mask.directive.d.ts +4 -0
- package/datepicker/README.md +175 -0
- package/datepicker/index.d.ts +5 -0
- package/datepicker/lib/datepicker/date.utils.d.ts +21 -0
- package/datepicker/lib/datepicker/datepicker.component.d.ts +254 -0
- package/datepicker/lib/datepicker/models/index.d.ts +16 -0
- package/datepicker/public-api.d.ts +2 -0
- package/dynamic-form/dynamic-form/components/lookup/lookup.component.d.ts +3 -1
- package/dynamic-form/dynamic-form/components/lookup/models/lookup-alert-config.d.ts +5 -0
- package/dynamic-form/dynamic-form/form-field/configurations/fields/calendar-field.d.ts +119 -24
- package/dynamic-form/dynamic-form/form-field/configurations/fields/lookup-field.d.ts +6 -0
- package/dynamic-form/dynamic-form/form-field/fields/calendar/calendar-field.component.d.ts +6 -23
- package/dynamic-form/public-api.d.ts +1 -0
- package/editor/README.md +229 -0
- package/editor/index.d.ts +5 -0
- package/editor/lib/editor/editor.component.d.ts +127 -0
- package/editor/lib/editor/link-dialog/link-dialog.component.d.ts +18 -0
- package/editor/lib/editor/models/index.d.ts +12 -0
- package/editor/lib/editor/toolbar-button/editor-toolbar-button.component.d.ts +10 -0
- package/editor/public-api.d.ts +2 -0
- package/esm2022/calendar-mask/lib/calendar-mask/calendar-mask.directive.mjs +5 -1
- package/esm2022/datepicker/lib/datepicker/date.utils.mjs +182 -0
- package/esm2022/datepicker/lib/datepicker/datepicker.component.mjs +1062 -0
- package/esm2022/datepicker/lib/datepicker/models/index.mjs +2 -0
- package/esm2022/datepicker/public-api.mjs +2 -0
- package/esm2022/datepicker/seniorsistemas-angular-components-datepicker.mjs +5 -0
- package/esm2022/dynamic-form/dynamic-form/components/lookup/lookup.component.mjs +11 -5
- package/esm2022/dynamic-form/dynamic-form/components/lookup/models/lookup-alert-config.mjs +2 -0
- package/esm2022/dynamic-form/dynamic-form/form-field/configurations/fields/calendar-field.mjs +1 -1
- package/esm2022/dynamic-form/dynamic-form/form-field/configurations/fields/lookup-field.mjs +1 -1
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/autocomplete/autocomplete-field.component.mjs +2 -2
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/calendar/calendar-field.component.mjs +23 -116
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/lookup/lookup-field.component.mjs +3 -3
- package/esm2022/dynamic-form/public-api.mjs +1 -1
- package/esm2022/editor/lib/editor/editor.component.mjs +375 -0
- package/esm2022/editor/lib/editor/link-dialog/link-dialog.component.mjs +48 -0
- package/esm2022/editor/lib/editor/models/index.mjs +3 -0
- package/esm2022/editor/lib/editor/toolbar-button/editor-toolbar-button.component.mjs +17 -0
- package/esm2022/editor/public-api.mjs +3 -0
- package/esm2022/editor/seniorsistemas-angular-components-editor.mjs +5 -0
- package/esm2022/inline-edit/lib/inline-edit/components/fields/inline-edit-calendar/inline-edit-calendar.component.mjs +22 -12
- package/esm2022/inline-edit/lib/inline-edit/inline-edit.module.mjs +5 -5
- package/esm2022/lib/locale/fallback.mjs +82 -3
- package/esm2022/optional-fields/editor/editor-field/editor-field.component.mjs +5 -6
- package/esm2022/optional-fields/editor/editor-field.mjs +1 -1
- package/esm2022/panel/lib/panel/panel.component.mjs +7 -3
- package/esm2022/select/lib/select/select.component.mjs +4 -8
- package/esm2022/shared/lib/accessibility/datepicker-no-period-tab.directive.mjs +5 -1
- package/fesm2022/seniorsistemas-angular-components-calendar-mask.mjs +4 -0
- package/fesm2022/seniorsistemas-angular-components-calendar-mask.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-datepicker.mjs +1250 -0
- package/fesm2022/seniorsistemas-angular-components-datepicker.mjs.map +1 -0
- package/fesm2022/seniorsistemas-angular-components-dynamic-form.mjs +49 -135
- package/fesm2022/seniorsistemas-angular-components-dynamic-form.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-editor.mjs +437 -0
- package/fesm2022/seniorsistemas-angular-components-editor.mjs.map +1 -0
- package/fesm2022/seniorsistemas-angular-components-inline-edit.mjs +24 -15
- package/fesm2022/seniorsistemas-angular-components-inline-edit.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-optional-fields-editor.mjs +4 -5
- package/fesm2022/seniorsistemas-angular-components-optional-fields-editor.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-panel.mjs +6 -2
- package/fesm2022/seniorsistemas-angular-components-panel.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-select.mjs +3 -7
- package/fesm2022/seniorsistemas-angular-components-select.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-shared.mjs +4 -0
- package/fesm2022/seniorsistemas-angular-components-shared.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components.mjs +81 -2
- package/fesm2022/seniorsistemas-angular-components.mjs.map +1 -1
- package/inline-edit/lib/inline-edit/components/fields/inline-edit-calendar/inline-edit-calendar.component.d.ts +6 -4
- package/inline-edit/lib/inline-edit/inline-edit.module.d.ts +2 -2
- package/loading-state/README.md +57 -17
- package/optional-fields/editor/editor-field.d.ts +9 -6
- package/package.json +74 -8
- package/panel/README.md +12 -1
- package/panel/lib/panel/panel.component.d.ts +3 -1
- package/schematics/collection.json +4 -0
- package/schematics/migrations/migrate-p-datepicker/index.d.ts +2 -0
- package/schematics/migrations/migrate-p-datepicker/index.js +141 -0
- package/schematics/migrations/migrate-p-datepicker/index.js.map +1 -0
- package/schematics/migrations/migrate-p-datepicker/index.test.d.ts +1 -0
- package/schematics/migrations/migrate-p-datepicker/index.test.js +392 -0
- package/schematics/migrations/migrate-p-datepicker/index.test.js.map +1 -0
- package/schematics/migrations.json +10 -0
- package/schematics/utils/ast-utils.d.ts +28 -0
- package/schematics/utils/ast-utils.js +116 -0
- package/schematics/utils/ast-utils.js.map +1 -0
- package/schematics/utils/ast-utils.test.d.ts +1 -0
- package/schematics/utils/ast-utils.test.js +138 -0
- package/schematics/utils/ast-utils.test.js.map +1 -0
- package/schematics/utils/workspace-utils.d.ts +6 -0
- package/schematics/utils/workspace-utils.js +37 -0
- package/schematics/utils/workspace-utils.js.map +1 -0
- package/schematics/utils/workspace-utils.test.d.ts +1 -0
- package/schematics/utils/workspace-utils.test.js +152 -0
- package/schematics/utils/workspace-utils.test.js.map +1 -0
- package/shared/lib/accessibility/datepicker-no-period-tab.directive.d.ts +4 -0
- package/stats-card/README.md +80 -45
|
@@ -0,0 +1,1062 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { CdkTrapFocus } from '@angular/cdk/a11y';
|
|
3
|
+
import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
|
|
4
|
+
import { NgClass } from '@angular/common';
|
|
5
|
+
import { afterNextRender, Component, computed, ElementRef, inject, Injector, input, model, output, signal, viewChild, } from '@angular/core';
|
|
6
|
+
import { FormsModule, NG_VALIDATORS, NG_VALUE_ACCESSOR, NgControl, ReactiveFormsModule, Validators, } from '@angular/forms';
|
|
7
|
+
import { TranslateModule } from '@ngx-translate/core';
|
|
8
|
+
import { formatValueForInput, isSameDay, parseInput, stripTime } from './date.utils';
|
|
9
|
+
import * as i0 from "@angular/core";
|
|
10
|
+
import * as i1 from "@ngx-translate/core";
|
|
11
|
+
import * as i2 from "@angular/forms";
|
|
12
|
+
function numericKeysOnly() {
|
|
13
|
+
return (_target, _key, descriptor) => {
|
|
14
|
+
const original = descriptor.value;
|
|
15
|
+
descriptor.value = function (event) {
|
|
16
|
+
const isValidKey = ['ArrowUp', 'ArrowDown', 'Backspace', 'Delete', 'Tab'].includes(event.key) || /^\d$/.test(event.key);
|
|
17
|
+
if (!isValidKey) {
|
|
18
|
+
event.preventDefault();
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
original.call(this, event);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
return descriptor;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export class DatepickerComponent {
|
|
28
|
+
static idCounter = 0;
|
|
29
|
+
static DAYS_IN_WEEK = 7;
|
|
30
|
+
static MONTHS_IN_YEAR = 12;
|
|
31
|
+
static MONTHS_PER_ROW = 3;
|
|
32
|
+
static YEARS_PER_GRID = 12;
|
|
33
|
+
static YEARS_PER_ROW = 3;
|
|
34
|
+
static DEFAULT_MINUTE_STEP = 5;
|
|
35
|
+
static MAX_HOURS = 24;
|
|
36
|
+
static MAX_MINUTES = 60;
|
|
37
|
+
static HOURS_PER_MERIDIEM = 12;
|
|
38
|
+
static nextId() {
|
|
39
|
+
DatepickerComponent.idCounter++;
|
|
40
|
+
return `s-datepicker-${DatepickerComponent.idCounter}`;
|
|
41
|
+
}
|
|
42
|
+
// ── Inputs ────────────────────────────────────────────────────────────
|
|
43
|
+
/** HTML `id` aplicado ao elemento `<input>`. Auto-gerado quando omitido. */
|
|
44
|
+
inputId = input(DatepickerComponent.nextId());
|
|
45
|
+
/** Atributo `name` do `<input>` nativo. */
|
|
46
|
+
name = input();
|
|
47
|
+
/** Texto exibido quando nenhum valor está selecionado. */
|
|
48
|
+
placeholder = input();
|
|
49
|
+
/**
|
|
50
|
+
* Modo de seleção do componente.
|
|
51
|
+
* - `'date'` — seleção de data única (padrão)
|
|
52
|
+
* - `'month'` — seleção de mês/ano
|
|
53
|
+
* - `'datetime'` — data com hora (requer confirmação)
|
|
54
|
+
* - `'time'` — apenas seleção de hora
|
|
55
|
+
* - `'range'` — intervalo entre duas datas
|
|
56
|
+
*/
|
|
57
|
+
mode = input('date');
|
|
58
|
+
/**
|
|
59
|
+
* Modo de seleção quando `mode` é `'date'`.
|
|
60
|
+
* - `'single'` — seleção de uma única data (padrão)
|
|
61
|
+
* - `'multiple'` — seleção de múltiplas datas avulsas
|
|
62
|
+
*/
|
|
63
|
+
selectionMode = input('single');
|
|
64
|
+
/** Separador exibido entre as datas no modo `selectionMode = 'multiple'`. */
|
|
65
|
+
multipleSeparator = input(', ');
|
|
66
|
+
/** Quando `true`, exibe o botão de ícone ao lado do campo. */
|
|
67
|
+
showIcon = input(true);
|
|
68
|
+
/**
|
|
69
|
+
* Classe do ícone exibido no botão do campo.
|
|
70
|
+
* Quando `mode` é `'time'`, o padrão muda automaticamente para `'fas fa-clock'`.
|
|
71
|
+
*/
|
|
72
|
+
icon = input('fas fa-calendar');
|
|
73
|
+
/** Data mínima selecionável. Dias/meses anteriores ficam desabilitados. */
|
|
74
|
+
min = input(null);
|
|
75
|
+
/** Data máxima selecionável. Dias/meses posteriores ficam desabilitados. */
|
|
76
|
+
max = input(null);
|
|
77
|
+
/** Data exibida ao abrir o calendário quando nenhuma data está selecionada. */
|
|
78
|
+
defaultDate = input(null);
|
|
79
|
+
/** Formato de exibição da data no campo (usado apenas para display). */
|
|
80
|
+
dateFormat = input('dd/MM/yyyy');
|
|
81
|
+
/** Formato de exibição das horas: `'12'` ou `'24'`. */
|
|
82
|
+
hourFormat = input('24');
|
|
83
|
+
/** Incremento em minutos ao usar as setas do time picker. */
|
|
84
|
+
minuteStep = input(DatepickerComponent.DEFAULT_MINUTE_STEP);
|
|
85
|
+
/** Quando `true`, exibe o campo de segundos no time picker. */
|
|
86
|
+
showSeconds = input(false);
|
|
87
|
+
/** Separador exibido entre as datas no modo `'range'`. */
|
|
88
|
+
rangeSeparator = input(' — ');
|
|
89
|
+
/** Abre o painel ao focar o input; foco permanece no input, não pula para o dropdown. */
|
|
90
|
+
showOnFocus = input(true);
|
|
91
|
+
/** Impede digitação manual; valor só pode ser selecionado pelo calendário. */
|
|
92
|
+
readonlyInput = input(false);
|
|
93
|
+
/** Primeiro dia da semana (0 = domingo, 1 = segunda-feira, ..., 6 = sábado). */
|
|
94
|
+
firstDayOfWeek = input(0);
|
|
95
|
+
/** Exibe/oculta a barra de botões Hoje e Limpar no rodapé. */
|
|
96
|
+
showButtonBar = input(true);
|
|
97
|
+
/** Exibe ícone de limpar inline no campo de input. */
|
|
98
|
+
showClear = input(false);
|
|
99
|
+
/** Exibe dias de meses adjacentes na grade do calendário. */
|
|
100
|
+
showOtherMonths = input(true);
|
|
101
|
+
/** Permite selecionar dias de meses adjacentes na grade do calendário. */
|
|
102
|
+
selectOtherMonths = input(false);
|
|
103
|
+
/** Fecha o painel após selecionar uma data no modo `datetime`. */
|
|
104
|
+
hideOnDateTimeSelect = input(false);
|
|
105
|
+
/** Incremento de horas no time picker. */
|
|
106
|
+
stepHour = input(1);
|
|
107
|
+
/** Incremento de segundos no time picker. */
|
|
108
|
+
stepSecond = input(1);
|
|
109
|
+
/** Índice de tab do campo de input. */
|
|
110
|
+
tabindex = input();
|
|
111
|
+
/** Foca automaticamente o campo ao carregar o componente. */
|
|
112
|
+
autofocus = input(false);
|
|
113
|
+
/** Datas específicas desabilitadas no calendário. */
|
|
114
|
+
disabledDates = input([]);
|
|
115
|
+
/** Dias da semana desabilitados (0 = domingo, ..., 6 = sábado). */
|
|
116
|
+
disabledDays = input([]);
|
|
117
|
+
// ── Two-way models ────────────────────────────────────────────────────
|
|
118
|
+
/** Estado desabilitado do componente. */
|
|
119
|
+
disabled = model(false);
|
|
120
|
+
// ── Outputs ───────────────────────────────────────────────────────────
|
|
121
|
+
/** Emitido quando o campo perde o foco. */
|
|
122
|
+
blurred = output();
|
|
123
|
+
/** Emitido quando o campo recebe o foco. */
|
|
124
|
+
focused = output();
|
|
125
|
+
/** Emitido ao selecionar uma data, mês, horário ou intervalo. */
|
|
126
|
+
selected = output();
|
|
127
|
+
/** Emitido quando o painel do calendário fecha. Emite o elemento do painel. */
|
|
128
|
+
closed = output();
|
|
129
|
+
/** Emitido ao clicar no botão "Hoje". */
|
|
130
|
+
todayClick = output();
|
|
131
|
+
/** Emitido ao clicar no botão "Limpar" ou no ícone de limpar inline. */
|
|
132
|
+
clearClick = output();
|
|
133
|
+
/** Emitido quando o mês visualizado muda. */
|
|
134
|
+
monthChange = output();
|
|
135
|
+
/** Emitido quando o ano visualizado muda. */
|
|
136
|
+
yearChange = output();
|
|
137
|
+
/** Emitido quando o painel do calendário abre. */
|
|
138
|
+
show = output();
|
|
139
|
+
/** Emitido quando o usuário digita manualmente no campo. */
|
|
140
|
+
valueInput = output();
|
|
141
|
+
// ── Internal state ────────────────────────────────────────────────────
|
|
142
|
+
maxHours = DatepickerComponent.MAX_HOURS;
|
|
143
|
+
maxMinutes = DatepickerComponent.MAX_MINUTES;
|
|
144
|
+
timeInputMaxLength = 2;
|
|
145
|
+
inputDate = '';
|
|
146
|
+
ngControl = null;
|
|
147
|
+
value = signal(null);
|
|
148
|
+
isOpen = signal(false);
|
|
149
|
+
viewDate = signal(new Date());
|
|
150
|
+
pickerView = signal('calendar');
|
|
151
|
+
hours = signal(0);
|
|
152
|
+
minutes = signal(0);
|
|
153
|
+
seconds = signal(0);
|
|
154
|
+
rangeValue = signal(null);
|
|
155
|
+
multipleValues = signal([]);
|
|
156
|
+
pendingRangeStart = signal(null);
|
|
157
|
+
hoverDate = signal(null);
|
|
158
|
+
_hasFormatError = false;
|
|
159
|
+
_isBadInput = false;
|
|
160
|
+
onValidatorChange = () => { };
|
|
161
|
+
_onChange = () => { };
|
|
162
|
+
_onTouched = () => { };
|
|
163
|
+
popupPanel = viewChild('popupPanel', { read: ElementRef });
|
|
164
|
+
increaseHourButton = viewChild('increaseHourButton', { read: ElementRef });
|
|
165
|
+
iconButton = viewChild('iconButton', { read: ElementRef });
|
|
166
|
+
injector = inject(Injector);
|
|
167
|
+
hostElement = inject(ElementRef);
|
|
168
|
+
// ── Computed ──────────────────────────────────────────────────────────
|
|
169
|
+
resolvedIcon = computed(() => (this.mode() === 'time' ? 'fas fa-clock' : this.icon()));
|
|
170
|
+
/** Indica se o time picker deve usar o formato de 12 horas com seletor AM/PM. */
|
|
171
|
+
is12HourFormat = computed(() => this.hourFormat() === '12');
|
|
172
|
+
/** Hora exibida no time picker: 1–12 no formato 12h, 0–23 no formato 24h. */
|
|
173
|
+
displayHours = computed(() => {
|
|
174
|
+
if (!this.is12HourFormat())
|
|
175
|
+
return this.hours();
|
|
176
|
+
const h12 = this.hours() % DatepickerComponent.HOURS_PER_MERIDIEM;
|
|
177
|
+
return h12 === 0 ? DatepickerComponent.HOURS_PER_MERIDIEM : h12;
|
|
178
|
+
});
|
|
179
|
+
/** Meridiano atual derivado da hora interna (0–23). */
|
|
180
|
+
amPm = computed(() => this.hours() < DatepickerComponent.HOURS_PER_MERIDIEM ? 'AM' : 'PM');
|
|
181
|
+
positions = [
|
|
182
|
+
{ originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: 4 },
|
|
183
|
+
{ originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -4 },
|
|
184
|
+
];
|
|
185
|
+
popupId = computed(() => `${this.inputId()}-popup`);
|
|
186
|
+
currentMonthIndex = computed(() => this.viewDate().getMonth());
|
|
187
|
+
currentYear = computed(() => this.viewDate().getFullYear());
|
|
188
|
+
currentMonthKey = computed(() => this.monthKeys[this.currentMonthIndex()]);
|
|
189
|
+
showCalendar = computed(() => this.mode() !== 'time');
|
|
190
|
+
showTimePicker = computed(() => this.mode() === 'datetime' || this.mode() === 'time');
|
|
191
|
+
/** Seleção múltipla ativa: apenas no modo `date` com `selectionMode = 'multiple'`. */
|
|
192
|
+
isMultipleMode = computed(() => this.selectionMode() === 'multiple' && this.mode() === 'date');
|
|
193
|
+
orderedWeekDayKeys = computed(() => {
|
|
194
|
+
const start = this.firstDayOfWeek();
|
|
195
|
+
return [...this.weekDayKeys.slice(start), ...this.weekDayKeys.slice(0, start)];
|
|
196
|
+
});
|
|
197
|
+
inputType = computed(() => {
|
|
198
|
+
if (this.isMultipleMode())
|
|
199
|
+
return 'text';
|
|
200
|
+
const mode = this.mode();
|
|
201
|
+
if (mode === 'datetime')
|
|
202
|
+
return 'datetime-local';
|
|
203
|
+
if (mode === 'range' || mode === 'year')
|
|
204
|
+
return 'text';
|
|
205
|
+
return mode;
|
|
206
|
+
});
|
|
207
|
+
dialogAriaLabelKey = computed(() => this.mode() === 'range'
|
|
208
|
+
? 'platform.angular_components.datepicker_select_range'
|
|
209
|
+
: 'platform.angular_components.datepicker_select_date');
|
|
210
|
+
placeholderKey = computed(() => {
|
|
211
|
+
const mode = this.mode();
|
|
212
|
+
return `platform.angular_components.datepicker_placeholder_${mode}`;
|
|
213
|
+
});
|
|
214
|
+
effectiveRange = computed(() => {
|
|
215
|
+
const pending = this.pendingRangeStart();
|
|
216
|
+
const hover = this.hoverDate();
|
|
217
|
+
if (pending) {
|
|
218
|
+
if (hover) {
|
|
219
|
+
const [start, end] = pending.getTime() <= hover.getTime() ? [pending, hover] : [hover, pending];
|
|
220
|
+
return { start, end };
|
|
221
|
+
}
|
|
222
|
+
return { start: pending, end: null };
|
|
223
|
+
}
|
|
224
|
+
return this.rangeValue() ?? { start: null, end: null };
|
|
225
|
+
});
|
|
226
|
+
calendarWeeks = computed(() => {
|
|
227
|
+
const year = this.currentYear();
|
|
228
|
+
const month = this.currentMonthIndex();
|
|
229
|
+
const today = new Date();
|
|
230
|
+
const selected = this.value();
|
|
231
|
+
const range = this.effectiveRange();
|
|
232
|
+
const rangeStartTime = range.start ? stripTime(range.start) : null;
|
|
233
|
+
const rangeEndTime = range.end ? stripTime(range.end) : null;
|
|
234
|
+
const firstDayOfMonth = new Date(year, month, 1);
|
|
235
|
+
const startWeekDay = firstDayOfMonth.getDay();
|
|
236
|
+
const adjustedStartDay = (startWeekDay - this.firstDayOfWeek() + 7) % 7;
|
|
237
|
+
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
238
|
+
const daysInPrevMonth = new Date(year, month, 0).getDate();
|
|
239
|
+
const allDays = [];
|
|
240
|
+
for (let i = adjustedStartDay - 1; i >= 0; i--) {
|
|
241
|
+
const date = new Date(year, month - 1, daysInPrevMonth - i);
|
|
242
|
+
allDays.push(this.buildCalendarDay(date, false, today, selected, range, rangeStartTime, rangeEndTime));
|
|
243
|
+
}
|
|
244
|
+
for (let d = 1; d <= daysInMonth; d++) {
|
|
245
|
+
const date = new Date(year, month, d);
|
|
246
|
+
allDays.push(this.buildCalendarDay(date, true, today, selected, range, rangeStartTime, rangeEndTime));
|
|
247
|
+
}
|
|
248
|
+
const totalCells = Math.ceil(allDays.length / DatepickerComponent.DAYS_IN_WEEK) * DatepickerComponent.DAYS_IN_WEEK;
|
|
249
|
+
let nextDay = 1;
|
|
250
|
+
while (allDays.length < totalCells) {
|
|
251
|
+
const date = new Date(year, month + 1, nextDay);
|
|
252
|
+
nextDay++;
|
|
253
|
+
allDays.push(this.buildCalendarDay(date, false, today, selected, range, rangeStartTime, rangeEndTime));
|
|
254
|
+
}
|
|
255
|
+
const weeks = [];
|
|
256
|
+
for (let i = 0; i < allDays.length; i += DatepickerComponent.DAYS_IN_WEEK) {
|
|
257
|
+
weeks.push(allDays.slice(i, i + DatepickerComponent.DAYS_IN_WEEK));
|
|
258
|
+
}
|
|
259
|
+
return weeks;
|
|
260
|
+
});
|
|
261
|
+
monthsGrid = computed(() => {
|
|
262
|
+
const rows = [];
|
|
263
|
+
for (let i = 0; i < DatepickerComponent.MONTHS_IN_YEAR; i += DatepickerComponent.MONTHS_PER_ROW) {
|
|
264
|
+
rows.push([
|
|
265
|
+
{ key: this.monthKeys[i], index: i },
|
|
266
|
+
{ key: this.monthKeys[i + 1], index: i + 1 },
|
|
267
|
+
{ key: this.monthKeys[i + 2], index: i + 2 },
|
|
268
|
+
]);
|
|
269
|
+
}
|
|
270
|
+
return rows;
|
|
271
|
+
});
|
|
272
|
+
currentDecadeStart = computed(() => Math.floor(this.currentYear() / 10) * 10);
|
|
273
|
+
yearsGrid = computed(() => {
|
|
274
|
+
const start = this.currentDecadeStart();
|
|
275
|
+
const rows = [];
|
|
276
|
+
for (let i = 0; i < DatepickerComponent.YEARS_PER_GRID; i += DatepickerComponent.YEARS_PER_ROW) {
|
|
277
|
+
rows.push([start + i, start + i + 1, start + i + 2]);
|
|
278
|
+
}
|
|
279
|
+
return rows;
|
|
280
|
+
});
|
|
281
|
+
prevDisabled = computed(() => {
|
|
282
|
+
const min = this.min();
|
|
283
|
+
if (!min)
|
|
284
|
+
return false;
|
|
285
|
+
const view = this.viewDate();
|
|
286
|
+
if (this.pickerView() === 'years') {
|
|
287
|
+
return this.currentDecadeStart() <= min.getFullYear();
|
|
288
|
+
}
|
|
289
|
+
if (this.pickerView() === 'months') {
|
|
290
|
+
return view.getFullYear() <= min.getFullYear();
|
|
291
|
+
}
|
|
292
|
+
return (view.getFullYear() < min.getFullYear() ||
|
|
293
|
+
(view.getFullYear() === min.getFullYear() && view.getMonth() <= min.getMonth()));
|
|
294
|
+
});
|
|
295
|
+
nextDisabled = computed(() => {
|
|
296
|
+
const max = this.max();
|
|
297
|
+
if (!max)
|
|
298
|
+
return false;
|
|
299
|
+
const view = this.viewDate();
|
|
300
|
+
if (this.pickerView() === 'years') {
|
|
301
|
+
return this.currentDecadeStart() + DatepickerComponent.YEARS_PER_GRID - 1 >= max.getFullYear();
|
|
302
|
+
}
|
|
303
|
+
if (this.pickerView() === 'months') {
|
|
304
|
+
return view.getFullYear() >= max.getFullYear();
|
|
305
|
+
}
|
|
306
|
+
return (view.getFullYear() > max.getFullYear() ||
|
|
307
|
+
(view.getFullYear() === max.getFullYear() && view.getMonth() >= max.getMonth()));
|
|
308
|
+
});
|
|
309
|
+
// ── Translation keys ──────────────────────────────────────────────────
|
|
310
|
+
weekDayKeys = [
|
|
311
|
+
'platform.angular_components.datepicker_day_sun',
|
|
312
|
+
'platform.angular_components.datepicker_day_mon',
|
|
313
|
+
'platform.angular_components.datepicker_day_tue',
|
|
314
|
+
'platform.angular_components.datepicker_day_wed',
|
|
315
|
+
'platform.angular_components.datepicker_day_thu',
|
|
316
|
+
'platform.angular_components.datepicker_day_fri',
|
|
317
|
+
'platform.angular_components.datepicker_day_sat',
|
|
318
|
+
];
|
|
319
|
+
monthKeys = [
|
|
320
|
+
'platform.angular_components.datepicker_month_jan',
|
|
321
|
+
'platform.angular_components.datepicker_month_feb',
|
|
322
|
+
'platform.angular_components.datepicker_month_mar',
|
|
323
|
+
'platform.angular_components.datepicker_month_apr',
|
|
324
|
+
'platform.angular_components.datepicker_month_may',
|
|
325
|
+
'platform.angular_components.datepicker_month_jun',
|
|
326
|
+
'platform.angular_components.datepicker_month_jul',
|
|
327
|
+
'platform.angular_components.datepicker_month_aug',
|
|
328
|
+
'platform.angular_components.datepicker_month_sep',
|
|
329
|
+
'platform.angular_components.datepicker_month_oct',
|
|
330
|
+
'platform.angular_components.datepicker_month_nov',
|
|
331
|
+
'platform.angular_components.datepicker_month_dec',
|
|
332
|
+
];
|
|
333
|
+
// ── Lifecycle ─────────────────────────────────────────────────────────
|
|
334
|
+
ngOnInit() {
|
|
335
|
+
this.ngControl = this.injector.get(NgControl, null, { self: true, optional: true });
|
|
336
|
+
afterNextRender(() => {
|
|
337
|
+
const d = this.defaultDate();
|
|
338
|
+
if (d && !this.value() && !this.rangeValue() && this.multipleValues().length === 0) {
|
|
339
|
+
this.value.set(d);
|
|
340
|
+
this.inputDate = this.formatForDisplay(d);
|
|
341
|
+
this.viewDate.set(new Date(d.getFullYear(), d.getMonth(), 1));
|
|
342
|
+
this._onChange(d);
|
|
343
|
+
}
|
|
344
|
+
}, { injector: this.injector });
|
|
345
|
+
}
|
|
346
|
+
// ── ControlValueAccessor ──────────────────────────────────────────────
|
|
347
|
+
writeValue(value) {
|
|
348
|
+
if (!value || (Array.isArray(value) && value.length === 0)) {
|
|
349
|
+
this.value.set(null);
|
|
350
|
+
this.rangeValue.set(null);
|
|
351
|
+
this.multipleValues.set([]);
|
|
352
|
+
this.inputDate = '';
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
if (Array.isArray(value)) {
|
|
356
|
+
const sorted = [...value].sort((a, b) => a.getTime() - b.getTime());
|
|
357
|
+
this.multipleValues.set(sorted);
|
|
358
|
+
this.inputDate = this.formatForDisplay(sorted);
|
|
359
|
+
const first = sorted[0];
|
|
360
|
+
this.viewDate.set(new Date(first.getFullYear(), first.getMonth(), 1));
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
if (this.isDateRange(value)) {
|
|
364
|
+
this.rangeValue.set(value);
|
|
365
|
+
this.inputDate = this.formatForDisplay(value);
|
|
366
|
+
if (value.start) {
|
|
367
|
+
this.viewDate.set(new Date(value.start.getFullYear(), value.start.getMonth(), 1));
|
|
368
|
+
}
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
this.value.set(value);
|
|
372
|
+
this.inputDate = this.formatForDisplay(value);
|
|
373
|
+
const d = value;
|
|
374
|
+
this.viewDate.set(new Date(d.getFullYear(), d.getMonth(), 1));
|
|
375
|
+
this.hours.set(d.getHours());
|
|
376
|
+
this.minutes.set(d.getMinutes());
|
|
377
|
+
this.seconds.set(d.getSeconds());
|
|
378
|
+
}
|
|
379
|
+
registerOnChange(fn) {
|
|
380
|
+
this._onChange = fn;
|
|
381
|
+
}
|
|
382
|
+
registerOnTouched(fn) {
|
|
383
|
+
this._onTouched = fn;
|
|
384
|
+
}
|
|
385
|
+
setDisabledState(isDisabled) {
|
|
386
|
+
this.disabled.set(isDisabled);
|
|
387
|
+
}
|
|
388
|
+
// ── Validator ─────────────────────────────────────────────────────────
|
|
389
|
+
validate(control) {
|
|
390
|
+
let value;
|
|
391
|
+
if (this.isMultipleMode()) {
|
|
392
|
+
value = this.multipleValues();
|
|
393
|
+
}
|
|
394
|
+
else if (this.mode() === 'range') {
|
|
395
|
+
value = this.rangeValue();
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
value = this.value();
|
|
399
|
+
}
|
|
400
|
+
return this.computeValidationErrors(value, control);
|
|
401
|
+
}
|
|
402
|
+
registerOnValidatorChange(fn) {
|
|
403
|
+
this.onValidatorChange = fn;
|
|
404
|
+
}
|
|
405
|
+
// ── Public actions ────────────────────────────────────────────────────
|
|
406
|
+
open() {
|
|
407
|
+
if (this.disabled())
|
|
408
|
+
return;
|
|
409
|
+
this.isOpen.set(true);
|
|
410
|
+
this.prepareOpenView();
|
|
411
|
+
this.show.emit();
|
|
412
|
+
if (this.mode() === 'time') {
|
|
413
|
+
afterNextRender(() => this.increaseHourButton()?.nativeElement.focus(), { injector: this.injector });
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
this.focusBestCalendarTarget();
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
/** Abre o painel sem transferir o foco para o dropdown (usado pelo showOnFocus). */
|
|
420
|
+
openOnFocus() {
|
|
421
|
+
if (this.disabled() || this.isOpen())
|
|
422
|
+
return;
|
|
423
|
+
this.isOpen.set(true);
|
|
424
|
+
this.prepareOpenView();
|
|
425
|
+
this.show.emit();
|
|
426
|
+
// Foco permanece no input — não chama focusBestCalendarTarget()
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Define a view inicial do painel e posiciona o calendário no `defaultDate`
|
|
430
|
+
* quando nenhum valor está selecionado.
|
|
431
|
+
*/
|
|
432
|
+
prepareOpenView() {
|
|
433
|
+
const defaultDate = this.defaultDate();
|
|
434
|
+
if (defaultDate && !this.value() && !this.rangeValue()) {
|
|
435
|
+
this.viewDate.set(new Date(defaultDate.getFullYear(), defaultDate.getMonth(), 1));
|
|
436
|
+
}
|
|
437
|
+
if (this.mode() === 'month') {
|
|
438
|
+
this.pickerView.set('months');
|
|
439
|
+
}
|
|
440
|
+
else if (this.mode() === 'year') {
|
|
441
|
+
this.pickerView.set('years');
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
this.pickerView.set('calendar');
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
focusBestCalendarTarget() {
|
|
448
|
+
afterNextRender(() => {
|
|
449
|
+
const panel = this.popupPanel()?.nativeElement;
|
|
450
|
+
if (!panel)
|
|
451
|
+
return;
|
|
452
|
+
const target = panel.querySelector('[data-focus="selected"]') ??
|
|
453
|
+
panel.querySelector('[data-focus="today"]') ??
|
|
454
|
+
panel.querySelector('button:not([disabled])');
|
|
455
|
+
target?.focus();
|
|
456
|
+
}, { injector: this.injector });
|
|
457
|
+
}
|
|
458
|
+
closePanel() {
|
|
459
|
+
const panel = (this.popupPanel()?.nativeElement ?? this.hostElement.nativeElement);
|
|
460
|
+
this.isOpen.set(false);
|
|
461
|
+
this.pendingRangeStart.set(null);
|
|
462
|
+
this.hoverDate.set(null);
|
|
463
|
+
this._onTouched();
|
|
464
|
+
this.closed.emit(panel);
|
|
465
|
+
afterNextRender(() => {
|
|
466
|
+
this.iconButton()?.nativeElement.focus();
|
|
467
|
+
}, { injector: this.injector });
|
|
468
|
+
}
|
|
469
|
+
toggle() {
|
|
470
|
+
if (this.isOpen()) {
|
|
471
|
+
this.closePanel();
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
this.open();
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
handleOverlayKeydown(event) {
|
|
478
|
+
if (event.key === 'Escape') {
|
|
479
|
+
this.closePanel();
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
handleInputClick() { }
|
|
483
|
+
handleInputFocus(event) {
|
|
484
|
+
this.focused.emit(event);
|
|
485
|
+
if (this.showOnFocus()) {
|
|
486
|
+
this.openOnFocus();
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
handleNativeInput(event) {
|
|
490
|
+
this.valueInput.emit(event);
|
|
491
|
+
}
|
|
492
|
+
handleInputBlur(event) {
|
|
493
|
+
this.blurred.emit(event);
|
|
494
|
+
const input = event.target;
|
|
495
|
+
this._isBadInput = input.validity?.badInput ?? false;
|
|
496
|
+
if (!input.value?.trim()) {
|
|
497
|
+
this.onValidatorChange();
|
|
498
|
+
}
|
|
499
|
+
if (this.isOpen()) {
|
|
500
|
+
const relatedTarget = event.relatedTarget;
|
|
501
|
+
const panel = this.popupPanel()?.nativeElement;
|
|
502
|
+
if (!relatedTarget || !panel?.contains(relatedTarget)) {
|
|
503
|
+
if (this.mode() === 'time') {
|
|
504
|
+
this.increaseHourButton()?.nativeElement.focus();
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
const target = panel?.querySelector('[data-focus="selected"]') ??
|
|
508
|
+
panel?.querySelector('[data-focus="today"]') ??
|
|
509
|
+
panel?.querySelector('button:not([disabled])');
|
|
510
|
+
target?.focus();
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
handleInputChange(raw) {
|
|
516
|
+
if (!raw?.trim()) {
|
|
517
|
+
this.value.set(null);
|
|
518
|
+
this.rangeValue.set(null);
|
|
519
|
+
this._hasFormatError = false;
|
|
520
|
+
this.onValidatorChange();
|
|
521
|
+
this._onChange(null);
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
const parsed = parseInput(this.mode(), raw, this.value(), this.maxHours, this.maxMinutes, this.rangeSeparator());
|
|
525
|
+
if (parsed === null) {
|
|
526
|
+
this._hasFormatError = true;
|
|
527
|
+
this.onValidatorChange();
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
this._hasFormatError = false;
|
|
531
|
+
this._isBadInput = false;
|
|
532
|
+
this.onValidatorChange();
|
|
533
|
+
if (this.isDateRange(parsed)) {
|
|
534
|
+
this.rangeValue.set(parsed);
|
|
535
|
+
this._onChange(parsed);
|
|
536
|
+
}
|
|
537
|
+
else {
|
|
538
|
+
const d = parsed;
|
|
539
|
+
this.value.set(d);
|
|
540
|
+
this.viewDate.set(new Date(d.getFullYear(), d.getMonth(), 1));
|
|
541
|
+
this.hours.set(d.getHours());
|
|
542
|
+
this.minutes.set(d.getMinutes());
|
|
543
|
+
this._onChange(d);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
handleTriggerKeydown(event) {
|
|
547
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
548
|
+
event.preventDefault();
|
|
549
|
+
this.open();
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
// ── Navigation ────────────────────────────────────────────────────────
|
|
553
|
+
navigatePrev() {
|
|
554
|
+
const view = this.viewDate();
|
|
555
|
+
if (this.pickerView() === 'years') {
|
|
556
|
+
this.viewDate.set(new Date(view.getFullYear() - 10, view.getMonth(), 1));
|
|
557
|
+
this.yearChange.emit({ month: view.getMonth(), year: view.getFullYear() - 10 });
|
|
558
|
+
}
|
|
559
|
+
else if (this.pickerView() === 'months') {
|
|
560
|
+
this.viewDate.set(new Date(view.getFullYear() - 1, view.getMonth(), 1));
|
|
561
|
+
this.yearChange.emit({ month: view.getMonth(), year: view.getFullYear() - 1 });
|
|
562
|
+
}
|
|
563
|
+
else {
|
|
564
|
+
const newDate = new Date(view.getFullYear(), view.getMonth() - 1, 1);
|
|
565
|
+
this.viewDate.set(newDate);
|
|
566
|
+
this.monthChange.emit({ month: newDate.getMonth(), year: newDate.getFullYear() });
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
navigateNext() {
|
|
570
|
+
const view = this.viewDate();
|
|
571
|
+
if (this.pickerView() === 'years') {
|
|
572
|
+
this.viewDate.set(new Date(view.getFullYear() + 10, view.getMonth(), 1));
|
|
573
|
+
this.yearChange.emit({ month: view.getMonth(), year: view.getFullYear() + 10 });
|
|
574
|
+
}
|
|
575
|
+
else if (this.pickerView() === 'months') {
|
|
576
|
+
this.viewDate.set(new Date(view.getFullYear() + 1, view.getMonth(), 1));
|
|
577
|
+
this.yearChange.emit({ month: view.getMonth(), year: view.getFullYear() + 1 });
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
const newDate = new Date(view.getFullYear(), view.getMonth() + 1, 1);
|
|
581
|
+
this.viewDate.set(newDate);
|
|
582
|
+
this.monthChange.emit({ month: newDate.getMonth(), year: newDate.getFullYear() });
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
handleCalendarGridKeydown(event) {
|
|
586
|
+
const ARROWS = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
|
|
587
|
+
if (!ARROWS.includes(event.key))
|
|
588
|
+
return;
|
|
589
|
+
event.preventDefault();
|
|
590
|
+
const grid = event.currentTarget;
|
|
591
|
+
const buttons = Array.from(grid.querySelectorAll('button[role="gridcell"]'));
|
|
592
|
+
const currentIdx = buttons.indexOf(event.target);
|
|
593
|
+
if (currentIdx === -1)
|
|
594
|
+
return;
|
|
595
|
+
let delta = 0;
|
|
596
|
+
if (event.key === 'ArrowRight')
|
|
597
|
+
delta = 1;
|
|
598
|
+
else if (event.key === 'ArrowLeft')
|
|
599
|
+
delta = -1;
|
|
600
|
+
else if (event.key === 'ArrowDown')
|
|
601
|
+
delta = DatepickerComponent.DAYS_IN_WEEK;
|
|
602
|
+
else if (event.key === 'ArrowUp')
|
|
603
|
+
delta = -DatepickerComponent.DAYS_IN_WEEK;
|
|
604
|
+
const nextIdx = currentIdx + delta;
|
|
605
|
+
if (nextIdx < 0) {
|
|
606
|
+
if (this.prevDisabled())
|
|
607
|
+
return;
|
|
608
|
+
this.navigatePrev();
|
|
609
|
+
afterNextRender(() => {
|
|
610
|
+
const panel = this.popupPanel()?.nativeElement;
|
|
611
|
+
const btns = Array.from(panel?.querySelectorAll('button[role="gridcell"]') ?? []);
|
|
612
|
+
const targetIdx = Math.max(0, btns.length + nextIdx);
|
|
613
|
+
const target = DatepickerComponent.findEnabled(btns, targetIdx, -1) ??
|
|
614
|
+
DatepickerComponent.findEnabled(btns, targetIdx, 1);
|
|
615
|
+
target?.focus();
|
|
616
|
+
}, { injector: this.injector });
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
if (nextIdx >= buttons.length) {
|
|
620
|
+
if (this.nextDisabled())
|
|
621
|
+
return;
|
|
622
|
+
this.navigateNext();
|
|
623
|
+
afterNextRender(() => {
|
|
624
|
+
const panel = this.popupPanel()?.nativeElement;
|
|
625
|
+
const btns = Array.from(panel?.querySelectorAll('button[role="gridcell"]') ?? []);
|
|
626
|
+
const targetIdx = Math.min(nextIdx - buttons.length, btns.length - 1);
|
|
627
|
+
const target = DatepickerComponent.findEnabled(btns, targetIdx, 1) ??
|
|
628
|
+
DatepickerComponent.findEnabled(btns, targetIdx, -1);
|
|
629
|
+
target?.focus();
|
|
630
|
+
}, { injector: this.injector });
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
if (!buttons[nextIdx]?.disabled) {
|
|
634
|
+
buttons[nextIdx].focus();
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
static findEnabled(buttons, startIdx, direction) {
|
|
638
|
+
for (let i = startIdx; i >= 0 && i < buttons.length; i += direction) {
|
|
639
|
+
if (!buttons[i].disabled)
|
|
640
|
+
return buttons[i];
|
|
641
|
+
}
|
|
642
|
+
return null;
|
|
643
|
+
}
|
|
644
|
+
switchToMonths() {
|
|
645
|
+
this.pickerView.set('months');
|
|
646
|
+
this.focusBestCalendarTarget();
|
|
647
|
+
}
|
|
648
|
+
backToCalendar() {
|
|
649
|
+
this.pickerView.set('calendar');
|
|
650
|
+
this.focusBestCalendarTarget();
|
|
651
|
+
}
|
|
652
|
+
// ── Selection ─────────────────────────────────────────────────────────
|
|
653
|
+
selectDate(day) {
|
|
654
|
+
if (day.isDisabled)
|
|
655
|
+
return;
|
|
656
|
+
if (this.isMultipleMode()) {
|
|
657
|
+
this.toggleMultipleDate(day.date);
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
if (this.mode() === 'range') {
|
|
661
|
+
const pending = this.pendingRangeStart();
|
|
662
|
+
if (!pending) {
|
|
663
|
+
this.pendingRangeStart.set(day.date);
|
|
664
|
+
}
|
|
665
|
+
else {
|
|
666
|
+
const [start, end] = pending.getTime() <= day.date.getTime() ? [pending, day.date] : [day.date, pending];
|
|
667
|
+
const range = { start, end };
|
|
668
|
+
this.rangeValue.set(range);
|
|
669
|
+
this.inputDate = this.formatForDisplay(range);
|
|
670
|
+
this._onChange(range);
|
|
671
|
+
this.selected.emit(range);
|
|
672
|
+
this.closePanel();
|
|
673
|
+
}
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
const newDate = new Date(day.date.getFullYear(), day.date.getMonth(), day.date.getDate(), this.hours(), this.minutes(), this.showSeconds() ? this.seconds() : 0);
|
|
677
|
+
this.value.set(newDate);
|
|
678
|
+
if (this.mode() === 'date') {
|
|
679
|
+
this.inputDate = this.formatForDisplay(newDate);
|
|
680
|
+
this._onChange(newDate);
|
|
681
|
+
this.selected.emit(newDate);
|
|
682
|
+
this.closePanel();
|
|
683
|
+
}
|
|
684
|
+
else if (this.mode() === 'datetime') {
|
|
685
|
+
this.inputDate = this.formatForDisplay(newDate);
|
|
686
|
+
this._onChange(newDate);
|
|
687
|
+
this.selected.emit(newDate);
|
|
688
|
+
if (this.hideOnDateTimeSelect()) {
|
|
689
|
+
this.closePanel();
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
/** Adiciona/remove uma data da seleção múltipla. O painel permanece aberto. */
|
|
694
|
+
toggleMultipleDate(date) {
|
|
695
|
+
const normalized = new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
696
|
+
const existing = this.multipleValues();
|
|
697
|
+
const index = existing.findIndex((d) => isSameDay(d, normalized));
|
|
698
|
+
const next = index >= 0
|
|
699
|
+
? existing.filter((_, i) => i !== index)
|
|
700
|
+
: [...existing, normalized].sort((a, b) => a.getTime() - b.getTime());
|
|
701
|
+
this.multipleValues.set(next);
|
|
702
|
+
this.inputDate = this.formatForDisplay(next);
|
|
703
|
+
const emitValue = next.length ? next : null;
|
|
704
|
+
this.onValidatorChange();
|
|
705
|
+
this._onChange(emitValue);
|
|
706
|
+
this.selected.emit(emitValue);
|
|
707
|
+
}
|
|
708
|
+
selectYear(year) {
|
|
709
|
+
if (this.isYearDisabled(year))
|
|
710
|
+
return;
|
|
711
|
+
const newDate = new Date(year, 0, 1);
|
|
712
|
+
this.value.set(newDate);
|
|
713
|
+
this.inputDate = this.formatForDisplay(newDate);
|
|
714
|
+
this._onChange(newDate);
|
|
715
|
+
this.selected.emit(newDate);
|
|
716
|
+
this.closePanel();
|
|
717
|
+
}
|
|
718
|
+
selectMonth(monthIndex) {
|
|
719
|
+
if (this.isMonthDisabled(monthIndex))
|
|
720
|
+
return;
|
|
721
|
+
const year = this.currentYear();
|
|
722
|
+
const newViewDate = new Date(year, monthIndex, 1);
|
|
723
|
+
if (this.mode() === 'month') {
|
|
724
|
+
this.value.set(newViewDate);
|
|
725
|
+
this.inputDate = this.formatForDisplay(newViewDate);
|
|
726
|
+
this._onChange(newViewDate);
|
|
727
|
+
this.selected.emit(newViewDate);
|
|
728
|
+
this.closePanel();
|
|
729
|
+
}
|
|
730
|
+
else {
|
|
731
|
+
this.viewDate.set(newViewDate);
|
|
732
|
+
this.pickerView.set('calendar');
|
|
733
|
+
this.focusBestCalendarTarget();
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
selectToday() {
|
|
737
|
+
const today = new Date();
|
|
738
|
+
if (!this.isDateDisabled(today)) {
|
|
739
|
+
const calDay = {
|
|
740
|
+
date: today,
|
|
741
|
+
dayOfMonth: today.getDate(),
|
|
742
|
+
isCurrentMonth: true,
|
|
743
|
+
isToday: true,
|
|
744
|
+
isSelected: false,
|
|
745
|
+
isDisabled: false,
|
|
746
|
+
isRangeStart: false,
|
|
747
|
+
isRangeEnd: false,
|
|
748
|
+
isInRange: false,
|
|
749
|
+
};
|
|
750
|
+
this.selectDate(calDay);
|
|
751
|
+
this.todayClick.emit(today);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
clearValue(event) {
|
|
755
|
+
this.value.set(null);
|
|
756
|
+
this.hours.set(0);
|
|
757
|
+
this.minutes.set(0);
|
|
758
|
+
this.seconds.set(0);
|
|
759
|
+
this.rangeValue.set(null);
|
|
760
|
+
this.multipleValues.set([]);
|
|
761
|
+
this.pendingRangeStart.set(null);
|
|
762
|
+
this.inputDate = '';
|
|
763
|
+
this._onChange(null);
|
|
764
|
+
this.clearClick.emit(event);
|
|
765
|
+
this.closePanel();
|
|
766
|
+
}
|
|
767
|
+
confirm() {
|
|
768
|
+
const current = this.value() ?? new Date();
|
|
769
|
+
const confirmed = new Date(current.getFullYear(), current.getMonth(), current.getDate(), this.hours(), this.minutes(), this.showSeconds() ? this.seconds() : 0);
|
|
770
|
+
this.value.set(confirmed);
|
|
771
|
+
this.inputDate = this.formatForDisplay(confirmed);
|
|
772
|
+
this._onChange(confirmed);
|
|
773
|
+
this.selected.emit(confirmed);
|
|
774
|
+
this.closePanel();
|
|
775
|
+
}
|
|
776
|
+
// ── Time picker ───────────────────────────────────────────────────────
|
|
777
|
+
incrementHours() {
|
|
778
|
+
this.hours.set((this.hours() + this.stepHour()) % this.maxHours);
|
|
779
|
+
this.syncTimeToValue();
|
|
780
|
+
}
|
|
781
|
+
decrementHours() {
|
|
782
|
+
this.hours.set((this.hours() - this.stepHour() + this.maxHours) % this.maxHours);
|
|
783
|
+
this.syncTimeToValue();
|
|
784
|
+
}
|
|
785
|
+
incrementMinutes() {
|
|
786
|
+
this.minutes.set((this.minutes() + this.minuteStep()) % this.maxMinutes);
|
|
787
|
+
this.syncTimeToValue();
|
|
788
|
+
}
|
|
789
|
+
decrementMinutes() {
|
|
790
|
+
this.minutes.set((this.minutes() - this.minuteStep() + this.maxMinutes) % this.maxMinutes);
|
|
791
|
+
this.syncTimeToValue();
|
|
792
|
+
}
|
|
793
|
+
incrementSeconds() {
|
|
794
|
+
this.seconds.set((this.seconds() + this.stepSecond()) % 60);
|
|
795
|
+
this.syncTimeToValue();
|
|
796
|
+
}
|
|
797
|
+
decrementSeconds() {
|
|
798
|
+
this.seconds.set((this.seconds() - this.stepSecond() + 60) % 60);
|
|
799
|
+
this.syncTimeToValue();
|
|
800
|
+
}
|
|
801
|
+
handleHoursKeydown(event) {
|
|
802
|
+
if (event.key === 'ArrowUp') {
|
|
803
|
+
event.preventDefault();
|
|
804
|
+
this.incrementHours();
|
|
805
|
+
}
|
|
806
|
+
else if (event.key === 'ArrowDown') {
|
|
807
|
+
event.preventDefault();
|
|
808
|
+
this.decrementHours();
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
handleMinutesKeydown(event) {
|
|
812
|
+
if (event.key === 'ArrowUp') {
|
|
813
|
+
event.preventDefault();
|
|
814
|
+
this.incrementMinutes();
|
|
815
|
+
}
|
|
816
|
+
else if (event.key === 'ArrowDown') {
|
|
817
|
+
event.preventDefault();
|
|
818
|
+
this.decrementMinutes();
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
handleSecondsKeydown(event) {
|
|
822
|
+
if (event.key === 'ArrowUp') {
|
|
823
|
+
event.preventDefault();
|
|
824
|
+
this.incrementSeconds();
|
|
825
|
+
}
|
|
826
|
+
else if (event.key === 'ArrowDown') {
|
|
827
|
+
event.preventDefault();
|
|
828
|
+
this.decrementSeconds();
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
handleHoursInput(event) {
|
|
832
|
+
const raw = event.target.value;
|
|
833
|
+
const parsed = parseInt(raw, 10);
|
|
834
|
+
if (isNaN(parsed))
|
|
835
|
+
return;
|
|
836
|
+
if (this.is12HourFormat()) {
|
|
837
|
+
const half = DatepickerComponent.HOURS_PER_MERIDIEM;
|
|
838
|
+
const h12 = Math.min(half, Math.max(1, parsed));
|
|
839
|
+
const base = h12 % half;
|
|
840
|
+
this.hours.set(this.amPm() === 'PM' ? base + half : base);
|
|
841
|
+
}
|
|
842
|
+
else {
|
|
843
|
+
this.hours.set(Math.min(this.maxHours - 1, Math.max(0, parsed)));
|
|
844
|
+
}
|
|
845
|
+
this.syncTimeToValue();
|
|
846
|
+
}
|
|
847
|
+
/** Alterna entre AM e PM somando/subtraindo 12 horas da hora interna. */
|
|
848
|
+
toggleAmPm() {
|
|
849
|
+
const half = DatepickerComponent.HOURS_PER_MERIDIEM;
|
|
850
|
+
this.hours.set(this.hours() < half ? this.hours() + half : this.hours() - half);
|
|
851
|
+
this.syncTimeToValue();
|
|
852
|
+
}
|
|
853
|
+
handleMinutesInput(event) {
|
|
854
|
+
const raw = event.target.value;
|
|
855
|
+
const parsed = parseInt(raw, 10);
|
|
856
|
+
if (!isNaN(parsed)) {
|
|
857
|
+
this.minutes.set(Math.min(this.maxMinutes - 1, Math.max(0, parsed)));
|
|
858
|
+
this.syncTimeToValue();
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
handleSecondsInput(event) {
|
|
862
|
+
const raw = event.target.value;
|
|
863
|
+
const parsed = parseInt(raw, 10);
|
|
864
|
+
if (!isNaN(parsed)) {
|
|
865
|
+
this.seconds.set(Math.min(59, Math.max(0, parsed)));
|
|
866
|
+
this.syncTimeToValue();
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
onDayHover(date) {
|
|
870
|
+
if (this.mode() === 'range') {
|
|
871
|
+
this.hoverDate.set(date);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
// ── Helpers ───────────────────────────────────────────────────────────
|
|
875
|
+
isDateDisabled(date) {
|
|
876
|
+
const min = this.min();
|
|
877
|
+
const max = this.max();
|
|
878
|
+
if (min && stripTime(date) < stripTime(min))
|
|
879
|
+
return true;
|
|
880
|
+
if (max && stripTime(date) > stripTime(max))
|
|
881
|
+
return true;
|
|
882
|
+
const disabledDays = this.disabledDays();
|
|
883
|
+
if (disabledDays.length && disabledDays.includes(date.getDay()))
|
|
884
|
+
return true;
|
|
885
|
+
const disabledDates = this.disabledDates();
|
|
886
|
+
if (disabledDates.length && disabledDates.some(d => isSameDay(d, date)))
|
|
887
|
+
return true;
|
|
888
|
+
return false;
|
|
889
|
+
}
|
|
890
|
+
isYearSelected(year) {
|
|
891
|
+
const selected = this.value();
|
|
892
|
+
return !!selected && selected.getFullYear() === year;
|
|
893
|
+
}
|
|
894
|
+
isYearDisabled(year) {
|
|
895
|
+
const min = this.min();
|
|
896
|
+
const max = this.max();
|
|
897
|
+
if (min && year < min.getFullYear())
|
|
898
|
+
return true;
|
|
899
|
+
if (max && year > max.getFullYear())
|
|
900
|
+
return true;
|
|
901
|
+
return false;
|
|
902
|
+
}
|
|
903
|
+
isCurrentYear(year) {
|
|
904
|
+
return year === new Date().getFullYear();
|
|
905
|
+
}
|
|
906
|
+
isMonthSelected(monthIndex) {
|
|
907
|
+
const selected = this.value();
|
|
908
|
+
return !!selected && selected.getMonth() === monthIndex && selected.getFullYear() === this.currentYear();
|
|
909
|
+
}
|
|
910
|
+
isMonthDisabled(monthIndex) {
|
|
911
|
+
const year = this.currentYear();
|
|
912
|
+
const min = this.min();
|
|
913
|
+
const max = this.max();
|
|
914
|
+
if (min && (year < min.getFullYear() || (year === min.getFullYear() && monthIndex < min.getMonth()))) {
|
|
915
|
+
return true;
|
|
916
|
+
}
|
|
917
|
+
if (max && (year > max.getFullYear() || (year === max.getFullYear() && monthIndex > max.getMonth()))) {
|
|
918
|
+
return true;
|
|
919
|
+
}
|
|
920
|
+
return false;
|
|
921
|
+
}
|
|
922
|
+
padTime(value) {
|
|
923
|
+
return String(value).padStart(2, '0');
|
|
924
|
+
}
|
|
925
|
+
formatDayAriaLabel(date) {
|
|
926
|
+
return date.toLocaleDateString(undefined, {
|
|
927
|
+
weekday: 'long',
|
|
928
|
+
year: 'numeric',
|
|
929
|
+
month: 'long',
|
|
930
|
+
day: 'numeric',
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
/** Formata o valor para exibição no input, aplicando rangeSeparator, dateFormat e multipleSeparator. */
|
|
934
|
+
formatForDisplay(value) {
|
|
935
|
+
return formatValueForInput(this.mode(), value, this.rangeSeparator(), this.dateFormat(), this.multipleSeparator());
|
|
936
|
+
}
|
|
937
|
+
syncTimeToValue() {
|
|
938
|
+
const date = this.value() ?? new Date();
|
|
939
|
+
const newDate = new Date(date.getFullYear(), date.getMonth(), date.getDate(), this.hours(), this.minutes(), this.showSeconds() ? this.seconds() : 0);
|
|
940
|
+
this.value.set(newDate);
|
|
941
|
+
this.inputDate = this.formatForDisplay(newDate);
|
|
942
|
+
if (this.mode() === 'time') {
|
|
943
|
+
this._onChange(newDate);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
buildCalendarDay(date, isCurrentMonth, today, selected, range, rangeStartTime, rangeEndTime) {
|
|
947
|
+
const isRangeStart = range.start ? isSameDay(date, range.start) : false;
|
|
948
|
+
const isRangeEnd = range.end ? isSameDay(date, range.end) : false;
|
|
949
|
+
const dateTime = stripTime(date);
|
|
950
|
+
const isInRange = rangeStartTime !== null && rangeEndTime !== null
|
|
951
|
+
? dateTime > rangeStartTime && dateTime < rangeEndTime
|
|
952
|
+
: false;
|
|
953
|
+
const isSelected = this.isMultipleMode()
|
|
954
|
+
? this.multipleValues().some((d) => isSameDay(d, date))
|
|
955
|
+
: selected
|
|
956
|
+
? isSameDay(date, selected)
|
|
957
|
+
: false;
|
|
958
|
+
return {
|
|
959
|
+
dayOfMonth: date.getDate(),
|
|
960
|
+
isToday: isSameDay(date, today),
|
|
961
|
+
isSelected,
|
|
962
|
+
isDisabled: this.isDateDisabled(date) || (!isCurrentMonth && !this.selectOtherMonths()),
|
|
963
|
+
date,
|
|
964
|
+
isCurrentMonth,
|
|
965
|
+
isRangeStart,
|
|
966
|
+
isRangeEnd,
|
|
967
|
+
isInRange,
|
|
968
|
+
};
|
|
969
|
+
}
|
|
970
|
+
computeValidationErrors(value, control) {
|
|
971
|
+
if (this._hasFormatError)
|
|
972
|
+
return { invalidFormat: true };
|
|
973
|
+
if (this._isBadInput)
|
|
974
|
+
return { badInput: true };
|
|
975
|
+
if (!value || (Array.isArray(value) && value.length === 0))
|
|
976
|
+
return Validators.nullValidator(control);
|
|
977
|
+
const min = this.min();
|
|
978
|
+
const max = this.max();
|
|
979
|
+
if (Array.isArray(value)) {
|
|
980
|
+
for (const d of value) {
|
|
981
|
+
if (min && stripTime(d) < stripTime(min))
|
|
982
|
+
return { min: { min, actual: d } };
|
|
983
|
+
if (max && stripTime(d) > stripTime(max))
|
|
984
|
+
return { max: { max, actual: d } };
|
|
985
|
+
}
|
|
986
|
+
return Validators.nullValidator(control);
|
|
987
|
+
}
|
|
988
|
+
if (this.isDateRange(value)) {
|
|
989
|
+
if (value.start && min && stripTime(value.start) < stripTime(min)) {
|
|
990
|
+
return { min: { min, actual: value.start } };
|
|
991
|
+
}
|
|
992
|
+
if (value.end && max && stripTime(value.end) > stripTime(max)) {
|
|
993
|
+
return { max: { max, actual: value.end } };
|
|
994
|
+
}
|
|
995
|
+
return Validators.nullValidator(control);
|
|
996
|
+
}
|
|
997
|
+
const d = value;
|
|
998
|
+
if (this.mode() === 'year') {
|
|
999
|
+
if (min && d.getFullYear() < min.getFullYear())
|
|
1000
|
+
return { min: { min, actual: d } };
|
|
1001
|
+
if (max && d.getFullYear() > max.getFullYear())
|
|
1002
|
+
return { max: { max, actual: d } };
|
|
1003
|
+
return Validators.nullValidator(control);
|
|
1004
|
+
}
|
|
1005
|
+
if (min && stripTime(d) < stripTime(min))
|
|
1006
|
+
return { min: { min, actual: d } };
|
|
1007
|
+
if (max && stripTime(d) > stripTime(max))
|
|
1008
|
+
return { max: { max, actual: d } };
|
|
1009
|
+
return Validators.nullValidator(control);
|
|
1010
|
+
}
|
|
1011
|
+
isDateRange(value) {
|
|
1012
|
+
return typeof value === 'object' && value !== null && 'start' in value && 'end' in value;
|
|
1013
|
+
}
|
|
1014
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DatepickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1015
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: DatepickerComponent, isStandalone: true, selector: "s-datepicker", inputs: { inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, multipleSeparator: { classPropertyName: "multipleSeparator", publicName: "multipleSeparator", isSignal: true, isRequired: false, transformFunction: null }, showIcon: { classPropertyName: "showIcon", publicName: "showIcon", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, defaultDate: { classPropertyName: "defaultDate", publicName: "defaultDate", isSignal: true, isRequired: false, transformFunction: null }, dateFormat: { classPropertyName: "dateFormat", publicName: "dateFormat", isSignal: true, isRequired: false, transformFunction: null }, hourFormat: { classPropertyName: "hourFormat", publicName: "hourFormat", isSignal: true, isRequired: false, transformFunction: null }, minuteStep: { classPropertyName: "minuteStep", publicName: "minuteStep", isSignal: true, isRequired: false, transformFunction: null }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: true, isRequired: false, transformFunction: null }, rangeSeparator: { classPropertyName: "rangeSeparator", publicName: "rangeSeparator", isSignal: true, isRequired: false, transformFunction: null }, showOnFocus: { classPropertyName: "showOnFocus", publicName: "showOnFocus", isSignal: true, isRequired: false, transformFunction: null }, readonlyInput: { classPropertyName: "readonlyInput", publicName: "readonlyInput", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, showButtonBar: { classPropertyName: "showButtonBar", publicName: "showButtonBar", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, showOtherMonths: { classPropertyName: "showOtherMonths", publicName: "showOtherMonths", isSignal: true, isRequired: false, transformFunction: null }, selectOtherMonths: { classPropertyName: "selectOtherMonths", publicName: "selectOtherMonths", isSignal: true, isRequired: false, transformFunction: null }, hideOnDateTimeSelect: { classPropertyName: "hideOnDateTimeSelect", publicName: "hideOnDateTimeSelect", isSignal: true, isRequired: false, transformFunction: null }, stepHour: { classPropertyName: "stepHour", publicName: "stepHour", isSignal: true, isRequired: false, transformFunction: null }, stepSecond: { classPropertyName: "stepSecond", publicName: "stepSecond", isSignal: true, isRequired: false, transformFunction: null }, tabindex: { classPropertyName: "tabindex", publicName: "tabindex", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, disabledDates: { classPropertyName: "disabledDates", publicName: "disabledDates", isSignal: true, isRequired: false, transformFunction: null }, disabledDays: { classPropertyName: "disabledDays", publicName: "disabledDays", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", blurred: "blurred", focused: "focused", selected: "selected", closed: "closed", todayClick: "todayClick", clearClick: "clearClick", monthChange: "monthChange", yearChange: "yearChange", show: "show", valueInput: "valueInput" }, host: { properties: { "class.no-icon": "!showIcon()" } }, providers: [
|
|
1016
|
+
{
|
|
1017
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1018
|
+
useExisting: DatepickerComponent,
|
|
1019
|
+
multi: true,
|
|
1020
|
+
},
|
|
1021
|
+
{
|
|
1022
|
+
provide: NG_VALIDATORS,
|
|
1023
|
+
useExisting: DatepickerComponent,
|
|
1024
|
+
multi: true,
|
|
1025
|
+
},
|
|
1026
|
+
], viewQueries: [{ propertyName: "popupPanel", first: true, predicate: ["popupPanel"], descendants: true, read: ElementRef, isSignal: true }, { propertyName: "increaseHourButton", first: true, predicate: ["increaseHourButton"], descendants: true, read: ElementRef, isSignal: true }, { propertyName: "iconButton", first: true, predicate: ["iconButton"], descendants: true, read: ElementRef, isSignal: true }], ngImport: i0, template: "<div\n cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n class=\"relative flex w-full items-center\"\n role=\"combobox\"\n aria-haspopup=\"grid\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"popupId()\"\n>\n <input\n class=\"hide-native-icon h-[35px] w-full rounded-small border border-solid border-grayscale-30 pl-3 text-sm outline-none transition-colors focus:border-primary focus:outline-1 focus:outline-primary\"\n [class.pr-10]=\"showIcon() && !showClear()\"\n [class.pr-16]=\"showIcon() && showClear()\"\n [class.pr-6]=\"!showIcon() && showClear()\"\n [class.bg-grayscale-0]=\"!disabled()\"\n [class.text-grayscale-90]=\"!disabled()\"\n [class.border-grayscale-20]=\"disabled()\"\n [class.bg-grayscale-5]=\"disabled()\"\n [class.text-grayscale-30]=\"disabled()\"\n [class.cursor-not-allowed]=\"disabled()\"\n [id]=\"inputId()\"\n [name]=\"name() ?? inputId()\"\n [type]=\"inputType()\"\n [placeholder]=\"placeholder() ?? (placeholderKey() | translate)\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonlyInput() || mode() === 'range' || mode() === 'year' || isMultipleMode()\"\n [tabIndex]=\"tabindex() ?? null\"\n [autofocus]=\"autofocus()\"\n [(ngModel)]=\"inputDate\"\n (ngModelChange)=\"handleInputChange($event)\"\n (focus)=\"handleInputFocus($event)\"\n (blur)=\"handleInputBlur($event)\"\n (click)=\"handleInputClick()\"\n (keydown)=\"handleTriggerKeydown($event)\"\n (input)=\"handleNativeInput($event)\"\n [attr.aria-invalid]=\"ngControl?.control?.invalid || null\"\n />\n\n @if (showClear() && inputDate) {\n <button\n type=\"button\"\n class=\"absolute flex h-[35px] w-6 items-center justify-center text-grayscale-60 transition-colors hover:text-grayscale-90\"\n [class.right-9]=\"showIcon()\"\n [class.right-0]=\"!showIcon()\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_clear' | translate\"\n (click)=\"clearValue($event)\"\n >\n <i class=\"fas fa-times text-xs\" aria-hidden=\"true\"></i>\n </button>\n }\n\n @if (showIcon()) {\n <button\n #iconButton\n type=\"button\"\n class=\"absolute right-0 flex h-[35px] w-9 items-center justify-center border-l border-solid transition-colors\"\n [class.border-grayscale-20]=\"disabled()\"\n [class.text-grayscale-30]=\"disabled()\"\n [class.cursor-not-allowed]=\"disabled()\"\n [class.border-grayscale-30]=\"!disabled()\"\n [class.text-grayscale-90]=\"!disabled()\"\n [class.hover:bg-grayscale-10]=\"!disabled()\"\n [disabled]=\"disabled()\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_open' | translate\"\n (click)=\"toggle()\"\n (keydown)=\"handleTriggerKeydown($event)\"\n >\n <i [class]=\"resolvedIcon()\" aria-hidden=\"true\"></i>\n </button>\n }\n</div>\n\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n [cdkConnectedOverlayPositions]=\"positions\"\n (backdropClick)=\"closePanel()\"\n (overlayKeydown)=\"handleOverlayKeydown($event)\"\n (detach)=\"isOpen.set(false)\"\n>\n <div\n #popupPanel\n class=\"z-50 w-72 rounded-medium border border-solid border-grayscale-30 bg-grayscale-0 shadow-md\"\n role=\"dialog\"\n cdkTrapFocus\n [id]=\"popupId()\"\n [attr.aria-label]=\"dialogAriaLabelKey() | translate\"\n >\n @if (showCalendar()) {\n @if (pickerView() === 'calendar') {\n <!-- Cabe\u00E7alho de navega\u00E7\u00E3o mensal -->\n <div class=\"flex items-center justify-between border-b border-solid border-grayscale-30 px-3 py-2\">\n <button\n type=\"button\"\n class=\"flex h-7 w-7 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10 disabled:cursor-not-allowed disabled:text-grayscale-30\"\n [disabled]=\"prevDisabled()\"\n [attr.aria-disabled]=\"prevDisabled() ? 'true' : null\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_prev_month' | translate\"\n (click)=\"navigatePrev()\"\n >\n <i class=\"fas fa-chevron-left text-xs\" aria-hidden=\"true\"></i>\n </button>\n\n <button\n type=\"button\"\n class=\"flex items-center gap-1 rounded-small px-2 py-1 text-sm font-medium text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_select_month_year' | translate\"\n (click)=\"switchToMonths()\"\n >\n {{ currentMonthKey() | translate }} {{ currentYear() }}\n <i class=\"fas fa-chevron-down text-[10px]\" aria-hidden=\"true\"></i>\n </button>\n\n <button\n type=\"button\"\n class=\"flex h-7 w-7 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10 disabled:cursor-not-allowed disabled:text-grayscale-30\"\n [disabled]=\"nextDisabled()\"\n [attr.aria-disabled]=\"nextDisabled() ? 'true' : null\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_next_month' | translate\"\n (click)=\"navigateNext()\"\n >\n <i class=\"fas fa-chevron-right text-xs\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <!-- Cabe\u00E7alhos dos dias da semana -->\n <div class=\"grid grid-cols-7 px-3 pt-2\" role=\"row\">\n @for (dayKey of orderedWeekDayKeys(); track dayKey) {\n <div\n class=\"flex h-8 items-center justify-center text-xs font-medium text-grayscale-60\"\n role=\"columnheader\"\n [attr.aria-label]=\"dayKey | translate\"\n >\n {{ dayKey | translate }}\n </div>\n }\n </div>\n\n <!-- Grade do calend\u00E1rio -->\n <div\n class=\"grid grid-cols-7 px-3 pb-2\"\n role=\"grid\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_calendar_label' | translate: { month: (currentMonthKey() | translate), year: currentYear() }\"\n (keydown)=\"handleCalendarGridKeydown($event)\"\n >\n @for (week of calendarWeeks(); track $index) {\n <div role=\"row\" class=\"contents\">\n @for (day of week; track day.date.toISOString()) {\n <button\n type=\"button\"\n role=\"gridcell\"\n class=\"flex h-8 w-8 items-center justify-center rounded-full text-sm font-normal transition-colors\"\n [class.invisible]=\"!showOtherMonths() && !day.isCurrentMonth\"\n [attr.aria-label]=\"formatDayAriaLabel(day.date)\"\n [attr.aria-selected]=\"day.isSelected || day.isRangeStart || day.isRangeEnd || null\"\n [attr.aria-current]=\"day.isToday ? 'date' : null\"\n [attr.aria-disabled]=\"day.isDisabled ? 'true' : null\"\n [attr.aria-hidden]=\"!showOtherMonths() && !day.isCurrentMonth ? 'true' : null\"\n [attr.data-focus]=\"day.isSelected || day.isRangeStart || day.isRangeEnd ? 'selected' : day.isToday ? 'today' : null\"\n [disabled]=\"day.isDisabled\"\n [ngClass]=\"{\n 'bg-primary font-semibold text-grayscale-0':\n day.isSelected || day.isRangeStart || day.isRangeEnd,\n 'bg-grayscale-10 hover:bg-grayscale-20':\n day.isInRange && !day.isRangeStart && !day.isRangeEnd,\n 'text-grayscale-90 hover:bg-grayscale-10':\n !day.isSelected &&\n !day.isRangeStart &&\n !day.isRangeEnd &&\n !day.isDisabled &&\n day.isCurrentMonth,\n 'text-grayscale-60 hover:bg-grayscale-10':\n !day.isSelected &&\n !day.isRangeStart &&\n !day.isRangeEnd &&\n !day.isDisabled &&\n !day.isCurrentMonth,\n 'ring-2 ring-inset ring-primary':\n day.isToday &&\n !day.isSelected &&\n !day.isRangeStart &&\n !day.isRangeEnd,\n 'cursor-not-allowed text-grayscale-30': day.isDisabled\n }\"\n (mouseenter)=\"onDayHover(day.date)\"\n (mouseleave)=\"onDayHover(null)\"\n (click)=\"selectDate(day)\"\n >\n {{ day.dayOfMonth }}\n </button>\n }\n </div>\n }\n </div>\n }\n\n @if (pickerView() === 'years') {\n <!-- Cabe\u00E7alho de navega\u00E7\u00E3o por d\u00E9cada -->\n <div class=\"flex items-center justify-between border-b border-solid border-grayscale-30 px-3 py-2\">\n <button\n type=\"button\"\n class=\"flex h-7 w-7 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10 disabled:cursor-not-allowed disabled:text-grayscale-30\"\n [disabled]=\"prevDisabled()\"\n [attr.aria-disabled]=\"prevDisabled() ? 'true' : null\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_prev_decade' | translate\"\n (click)=\"navigatePrev()\"\n >\n <i class=\"fas fa-chevron-left text-xs\" aria-hidden=\"true\"></i>\n </button>\n\n <span class=\"text-sm font-medium text-grayscale-90\">{{ currentDecadeStart() }} \u2013 {{ currentDecadeStart() + 11 }}</span>\n\n <button\n type=\"button\"\n class=\"flex h-7 w-7 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10 disabled:cursor-not-allowed disabled:text-grayscale-30\"\n [disabled]=\"nextDisabled()\"\n [attr.aria-disabled]=\"nextDisabled() ? 'true' : null\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_next_decade' | translate\"\n (click)=\"navigateNext()\"\n >\n <i class=\"fas fa-chevron-right text-xs\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <!-- Grade de anos -->\n <div\n class=\"grid grid-cols-3 gap-2 px-3 py-3\"\n role=\"grid\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_select_year' | translate\"\n >\n @for (row of yearsGrid(); track $index) {\n @for (year of row; track year) {\n <button\n type=\"button\"\n role=\"gridcell\"\n class=\"flex h-9 items-center justify-center rounded-small text-sm font-normal transition-colors\"\n [attr.aria-selected]=\"isYearSelected(year) || null\"\n [attr.aria-disabled]=\"isYearDisabled(year) ? 'true' : null\"\n [attr.aria-current]=\"isCurrentYear(year) ? 'date' : null\"\n [attr.data-focus]=\"isYearSelected(year) ? 'selected' : isCurrentYear(year) ? 'today' : null\"\n [disabled]=\"isYearDisabled(year)\"\n [ngClass]=\"{\n 'bg-primary font-semibold text-grayscale-0': isYearSelected(year),\n 'ring-2 ring-inset ring-primary': isCurrentYear(year) && !isYearSelected(year) && !isYearDisabled(year),\n 'text-grayscale-90 hover:bg-grayscale-10': !isYearSelected(year) && !isYearDisabled(year),\n 'cursor-not-allowed text-grayscale-30': isYearDisabled(year)\n }\"\n (click)=\"selectYear(year)\"\n >\n {{ year }}\n </button>\n }\n }\n </div>\n }\n\n @if (pickerView() === 'months') {\n <!-- Cabe\u00E7alho de navega\u00E7\u00E3o anual -->\n <div class=\"flex items-center justify-between border-b border-solid border-grayscale-30 px-3 py-2\">\n <button\n type=\"button\"\n class=\"flex h-7 w-7 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10 disabled:cursor-not-allowed disabled:text-grayscale-30\"\n [disabled]=\"prevDisabled()\"\n [attr.aria-disabled]=\"prevDisabled() ? 'true' : null\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_prev_year' | translate\"\n (click)=\"navigatePrev()\"\n >\n <i class=\"fas fa-chevron-left text-xs\" aria-hidden=\"true\"></i>\n </button>\n\n <span class=\"text-sm font-medium text-grayscale-90\">{{ currentYear() }}</span>\n\n <button\n type=\"button\"\n class=\"flex h-7 w-7 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10 disabled:cursor-not-allowed disabled:text-grayscale-30\"\n [disabled]=\"nextDisabled()\"\n [attr.aria-disabled]=\"nextDisabled() ? 'true' : null\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_next_year' | translate\"\n (click)=\"navigateNext()\"\n >\n <i class=\"fas fa-chevron-right text-xs\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <!-- Grade de meses -->\n <div\n class=\"grid grid-cols-3 gap-2 px-3 py-3\"\n role=\"grid\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_select_month' | translate\"\n >\n @for (row of monthsGrid(); track $index) {\n @for (month of row; track month.index) {\n <button\n type=\"button\"\n role=\"gridcell\"\n class=\"flex h-9 items-center justify-center rounded-small text-sm font-normal transition-colors\"\n [attr.aria-selected]=\"isMonthSelected(month.index) || null\"\n [attr.aria-disabled]=\"isMonthDisabled(month.index) ? 'true' : null\"\n [attr.data-focus]=\"isMonthSelected(month.index) ? 'selected' : null\"\n [disabled]=\"isMonthDisabled(month.index)\"\n [ngClass]=\"{\n 'bg-primary font-semibold text-grayscale-0': isMonthSelected(month.index),\n 'text-grayscale-90 hover:bg-grayscale-10':\n !isMonthSelected(month.index) && !isMonthDisabled(month.index),\n 'cursor-not-allowed text-grayscale-30': isMonthDisabled(month.index)\n }\"\n (click)=\"selectMonth(month.index)\"\n >\n {{ month.key | translate }}\n </button>\n }\n }\n </div>\n\n @if (mode() !== 'month') {\n <div class=\"border-t border-solid border-grayscale-30 px-3 py-2\">\n <button\n type=\"button\"\n class=\"flex items-center gap-2 rounded-small px-2 py-1 text-sm text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n (click)=\"backToCalendar()\"\n >\n <i class=\"fas fa-arrow-left\" aria-hidden=\"true\"></i>\n {{ 'platform.angular_components.datepicker_back_to_calendar' | translate }}\n </button>\n </div>\n }\n }\n }\n\n <!-- Time picker -->\n @if (showTimePicker()) {\n <div\n class=\"flex items-center justify-center gap-3 px-4 py-3\"\n [class.border-t]=\"showCalendar()\"\n [class.border-solid]=\"showCalendar()\"\n [class.border-grayscale-30]=\"showCalendar()\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_select_time' | translate\"\n >\n <!-- Horas -->\n <div class=\"flex flex-col items-center gap-1\">\n <button\n #increaseHourButton\n type=\"button\"\n class=\"flex h-6 w-6 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_increment_hour' | translate\"\n (click)=\"incrementHours()\"\n >\n <i class=\"fas fa-chevron-up text-xs\" aria-hidden=\"true\"></i>\n </button>\n <input\n type=\"text\"\n inputmode=\"numeric\"\n [attr.maxlength]=\"timeInputMaxLength\"\n class=\"h-9 w-12 rounded-small border border-solid border-grayscale-30 bg-grayscale-5 text-center text-base font-medium text-grayscale-90 outline-none focus:border-primary focus:outline-1 focus:outline-primary\"\n [value]=\"padTime(displayHours())\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_hour' | translate\"\n aria-live=\"polite\"\n pattern=\"[0-9]+\"\n (keydown)=\"handleHoursKeydown($event)\"\n (change)=\"handleHoursInput($event)\"\n />\n <button\n type=\"button\"\n class=\"flex h-6 w-6 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_decrement_hour' | translate\"\n (click)=\"decrementHours()\"\n >\n <i class=\"fas fa-chevron-down text-xs\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <span class=\"text-xl font-bold text-grayscale-60\" aria-hidden=\"true\">:</span>\n\n <!-- Minutos -->\n <div class=\"flex flex-col items-center gap-1\">\n <button\n type=\"button\"\n class=\"flex h-6 w-6 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_increment_minute' | translate\"\n (click)=\"incrementMinutes()\"\n >\n <i class=\"fas fa-chevron-up text-xs\" aria-hidden=\"true\"></i>\n </button>\n <input\n type=\"text\"\n inputmode=\"numeric\"\n [attr.maxlength]=\"timeInputMaxLength\"\n class=\"h-9 w-12 rounded-small border border-solid border-grayscale-30 bg-grayscale-5 text-center text-base font-medium text-grayscale-90 outline-none focus:border-primary focus:outline-1 focus:outline-primary\"\n [value]=\"padTime(minutes())\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_minute' | translate\"\n aria-live=\"polite\"\n pattern=\"[0-9]+\"\n (keydown)=\"handleMinutesKeydown($event)\"\n (change)=\"handleMinutesInput($event)\"\n />\n <button\n type=\"button\"\n class=\"flex h-6 w-6 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_decrement_minute' | translate\"\n (click)=\"decrementMinutes()\"\n >\n <i class=\"fas fa-chevron-down text-xs\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n @if (showSeconds()) {\n <span class=\"text-xl font-bold text-grayscale-60\" aria-hidden=\"true\">:</span>\n\n <!-- Segundos -->\n <div class=\"flex flex-col items-center gap-1\">\n <button\n type=\"button\"\n class=\"flex h-6 w-6 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_increment_second' | translate\"\n (click)=\"incrementSeconds()\"\n >\n <i class=\"fas fa-chevron-up text-xs\" aria-hidden=\"true\"></i>\n </button>\n <input\n type=\"text\"\n inputmode=\"numeric\"\n [attr.maxlength]=\"timeInputMaxLength\"\n class=\"h-9 w-12 rounded-small border border-solid border-grayscale-30 bg-grayscale-5 text-center text-base font-medium text-grayscale-90 outline-none focus:border-primary focus:outline-1 focus:outline-primary\"\n [value]=\"padTime(seconds())\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_second' | translate\"\n aria-live=\"polite\"\n pattern=\"[0-9]+\"\n (keydown)=\"handleSecondsKeydown($event)\"\n (change)=\"handleSecondsInput($event)\"\n />\n <button\n type=\"button\"\n class=\"flex h-6 w-6 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_decrement_second' | translate\"\n (click)=\"decrementSeconds()\"\n >\n <i class=\"fas fa-chevron-down text-xs\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n\n @if (is12HourFormat()) {\n <!-- Seletor AM/PM -->\n <button\n type=\"button\"\n class=\"flex h-9 w-12 items-center justify-center rounded-small border border-solid border-grayscale-30 bg-grayscale-5 text-base font-medium text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_toggle_meridiem' | translate\"\n aria-live=\"polite\"\n (click)=\"toggleAmPm()\"\n >\n {{ amPm() }}\n </button>\n }\n </div>\n }\n\n <!-- Rodap\u00E9 de a\u00E7\u00F5es -->\n @if (showButtonBar() || mode() === 'datetime' || mode() === 'time') {\n <div class=\"flex items-center justify-between border-t border-solid border-grayscale-30 px-3 py-2\">\n @if (showButtonBar()) {\n <div>\n @if (mode() === 'date' || mode() === 'datetime' || mode() === 'range') {\n <button\n type=\"button\"\n class=\"rounded-small px-2 py-1 text-sm text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n (click)=\"selectToday()\"\n >\n {{ 'platform.angular_components.datepicker_today' | translate }}\n </button>\n }\n </div>\n\n <div class=\"flex gap-2\">\n <button\n type=\"button\"\n class=\"rounded-small px-2 py-1 text-sm text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n (click)=\"clearValue($event)\"\n >\n {{ 'platform.angular_components.datepicker_clear' | translate }}\n </button>\n\n @if (mode() === 'datetime' || mode() === 'time') {\n <button\n type=\"button\"\n class=\"rounded-small bg-primary px-3 py-1 text-sm font-medium text-grayscale-0 transition-colors hover:opacity-90\"\n (click)=\"confirm()\"\n >\n {{ 'platform.angular_components.datepicker_confirm' | translate }}\n </button>\n }\n </div>\n } @else {\n <div></div>\n <div>\n @if (mode() === 'datetime' || mode() === 'time') {\n <button\n type=\"button\"\n class=\"rounded-small bg-primary px-3 py-1 text-sm font-medium text-grayscale-0 transition-colors hover:opacity-90\"\n (click)=\"confirm()\"\n >\n {{ 'platform.angular_components.datepicker_confirm' | translate }}\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n", styles: [":host{display:block;position:relative;width:100%}:host.ng-invalid.ng-dirty input{border-color:#c13018}:host.ng-invalid.ng-dirty input:focus{border-color:#c13018;outline-color:#c13018}:host.ng-invalid.ng-dirty button[type=button]{border-color:#c13018}:host.no-icon button[type=button]{display:none}:host.no-icon input{padding-right:.75rem}input.hide-native-icon::-webkit-calendar-picker-indicator{display:none}button[type=button]:focus-visible{outline:2px solid #428BCA;outline-offset:1px;border-radius:inherit}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }] });
|
|
1027
|
+
}
|
|
1028
|
+
__decorate([
|
|
1029
|
+
numericKeysOnly()
|
|
1030
|
+
], DatepickerComponent.prototype, "handleHoursKeydown", null);
|
|
1031
|
+
__decorate([
|
|
1032
|
+
numericKeysOnly()
|
|
1033
|
+
], DatepickerComponent.prototype, "handleMinutesKeydown", null);
|
|
1034
|
+
__decorate([
|
|
1035
|
+
numericKeysOnly()
|
|
1036
|
+
], DatepickerComponent.prototype, "handleSecondsKeydown", null);
|
|
1037
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DatepickerComponent, decorators: [{
|
|
1038
|
+
type: Component,
|
|
1039
|
+
args: [{ selector: 's-datepicker', standalone: true, imports: [
|
|
1040
|
+
NgClass,
|
|
1041
|
+
TranslateModule,
|
|
1042
|
+
CdkTrapFocus,
|
|
1043
|
+
CdkOverlayOrigin,
|
|
1044
|
+
CdkConnectedOverlay,
|
|
1045
|
+
FormsModule,
|
|
1046
|
+
ReactiveFormsModule,
|
|
1047
|
+
], host: {
|
|
1048
|
+
'[class.no-icon]': '!showIcon()',
|
|
1049
|
+
}, providers: [
|
|
1050
|
+
{
|
|
1051
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1052
|
+
useExisting: DatepickerComponent,
|
|
1053
|
+
multi: true,
|
|
1054
|
+
},
|
|
1055
|
+
{
|
|
1056
|
+
provide: NG_VALIDATORS,
|
|
1057
|
+
useExisting: DatepickerComponent,
|
|
1058
|
+
multi: true,
|
|
1059
|
+
},
|
|
1060
|
+
], template: "<div\n cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n class=\"relative flex w-full items-center\"\n role=\"combobox\"\n aria-haspopup=\"grid\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"popupId()\"\n>\n <input\n class=\"hide-native-icon h-[35px] w-full rounded-small border border-solid border-grayscale-30 pl-3 text-sm outline-none transition-colors focus:border-primary focus:outline-1 focus:outline-primary\"\n [class.pr-10]=\"showIcon() && !showClear()\"\n [class.pr-16]=\"showIcon() && showClear()\"\n [class.pr-6]=\"!showIcon() && showClear()\"\n [class.bg-grayscale-0]=\"!disabled()\"\n [class.text-grayscale-90]=\"!disabled()\"\n [class.border-grayscale-20]=\"disabled()\"\n [class.bg-grayscale-5]=\"disabled()\"\n [class.text-grayscale-30]=\"disabled()\"\n [class.cursor-not-allowed]=\"disabled()\"\n [id]=\"inputId()\"\n [name]=\"name() ?? inputId()\"\n [type]=\"inputType()\"\n [placeholder]=\"placeholder() ?? (placeholderKey() | translate)\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonlyInput() || mode() === 'range' || mode() === 'year' || isMultipleMode()\"\n [tabIndex]=\"tabindex() ?? null\"\n [autofocus]=\"autofocus()\"\n [(ngModel)]=\"inputDate\"\n (ngModelChange)=\"handleInputChange($event)\"\n (focus)=\"handleInputFocus($event)\"\n (blur)=\"handleInputBlur($event)\"\n (click)=\"handleInputClick()\"\n (keydown)=\"handleTriggerKeydown($event)\"\n (input)=\"handleNativeInput($event)\"\n [attr.aria-invalid]=\"ngControl?.control?.invalid || null\"\n />\n\n @if (showClear() && inputDate) {\n <button\n type=\"button\"\n class=\"absolute flex h-[35px] w-6 items-center justify-center text-grayscale-60 transition-colors hover:text-grayscale-90\"\n [class.right-9]=\"showIcon()\"\n [class.right-0]=\"!showIcon()\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_clear' | translate\"\n (click)=\"clearValue($event)\"\n >\n <i class=\"fas fa-times text-xs\" aria-hidden=\"true\"></i>\n </button>\n }\n\n @if (showIcon()) {\n <button\n #iconButton\n type=\"button\"\n class=\"absolute right-0 flex h-[35px] w-9 items-center justify-center border-l border-solid transition-colors\"\n [class.border-grayscale-20]=\"disabled()\"\n [class.text-grayscale-30]=\"disabled()\"\n [class.cursor-not-allowed]=\"disabled()\"\n [class.border-grayscale-30]=\"!disabled()\"\n [class.text-grayscale-90]=\"!disabled()\"\n [class.hover:bg-grayscale-10]=\"!disabled()\"\n [disabled]=\"disabled()\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_open' | translate\"\n (click)=\"toggle()\"\n (keydown)=\"handleTriggerKeydown($event)\"\n >\n <i [class]=\"resolvedIcon()\" aria-hidden=\"true\"></i>\n </button>\n }\n</div>\n\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n [cdkConnectedOverlayPositions]=\"positions\"\n (backdropClick)=\"closePanel()\"\n (overlayKeydown)=\"handleOverlayKeydown($event)\"\n (detach)=\"isOpen.set(false)\"\n>\n <div\n #popupPanel\n class=\"z-50 w-72 rounded-medium border border-solid border-grayscale-30 bg-grayscale-0 shadow-md\"\n role=\"dialog\"\n cdkTrapFocus\n [id]=\"popupId()\"\n [attr.aria-label]=\"dialogAriaLabelKey() | translate\"\n >\n @if (showCalendar()) {\n @if (pickerView() === 'calendar') {\n <!-- Cabe\u00E7alho de navega\u00E7\u00E3o mensal -->\n <div class=\"flex items-center justify-between border-b border-solid border-grayscale-30 px-3 py-2\">\n <button\n type=\"button\"\n class=\"flex h-7 w-7 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10 disabled:cursor-not-allowed disabled:text-grayscale-30\"\n [disabled]=\"prevDisabled()\"\n [attr.aria-disabled]=\"prevDisabled() ? 'true' : null\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_prev_month' | translate\"\n (click)=\"navigatePrev()\"\n >\n <i class=\"fas fa-chevron-left text-xs\" aria-hidden=\"true\"></i>\n </button>\n\n <button\n type=\"button\"\n class=\"flex items-center gap-1 rounded-small px-2 py-1 text-sm font-medium text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_select_month_year' | translate\"\n (click)=\"switchToMonths()\"\n >\n {{ currentMonthKey() | translate }} {{ currentYear() }}\n <i class=\"fas fa-chevron-down text-[10px]\" aria-hidden=\"true\"></i>\n </button>\n\n <button\n type=\"button\"\n class=\"flex h-7 w-7 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10 disabled:cursor-not-allowed disabled:text-grayscale-30\"\n [disabled]=\"nextDisabled()\"\n [attr.aria-disabled]=\"nextDisabled() ? 'true' : null\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_next_month' | translate\"\n (click)=\"navigateNext()\"\n >\n <i class=\"fas fa-chevron-right text-xs\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <!-- Cabe\u00E7alhos dos dias da semana -->\n <div class=\"grid grid-cols-7 px-3 pt-2\" role=\"row\">\n @for (dayKey of orderedWeekDayKeys(); track dayKey) {\n <div\n class=\"flex h-8 items-center justify-center text-xs font-medium text-grayscale-60\"\n role=\"columnheader\"\n [attr.aria-label]=\"dayKey | translate\"\n >\n {{ dayKey | translate }}\n </div>\n }\n </div>\n\n <!-- Grade do calend\u00E1rio -->\n <div\n class=\"grid grid-cols-7 px-3 pb-2\"\n role=\"grid\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_calendar_label' | translate: { month: (currentMonthKey() | translate), year: currentYear() }\"\n (keydown)=\"handleCalendarGridKeydown($event)\"\n >\n @for (week of calendarWeeks(); track $index) {\n <div role=\"row\" class=\"contents\">\n @for (day of week; track day.date.toISOString()) {\n <button\n type=\"button\"\n role=\"gridcell\"\n class=\"flex h-8 w-8 items-center justify-center rounded-full text-sm font-normal transition-colors\"\n [class.invisible]=\"!showOtherMonths() && !day.isCurrentMonth\"\n [attr.aria-label]=\"formatDayAriaLabel(day.date)\"\n [attr.aria-selected]=\"day.isSelected || day.isRangeStart || day.isRangeEnd || null\"\n [attr.aria-current]=\"day.isToday ? 'date' : null\"\n [attr.aria-disabled]=\"day.isDisabled ? 'true' : null\"\n [attr.aria-hidden]=\"!showOtherMonths() && !day.isCurrentMonth ? 'true' : null\"\n [attr.data-focus]=\"day.isSelected || day.isRangeStart || day.isRangeEnd ? 'selected' : day.isToday ? 'today' : null\"\n [disabled]=\"day.isDisabled\"\n [ngClass]=\"{\n 'bg-primary font-semibold text-grayscale-0':\n day.isSelected || day.isRangeStart || day.isRangeEnd,\n 'bg-grayscale-10 hover:bg-grayscale-20':\n day.isInRange && !day.isRangeStart && !day.isRangeEnd,\n 'text-grayscale-90 hover:bg-grayscale-10':\n !day.isSelected &&\n !day.isRangeStart &&\n !day.isRangeEnd &&\n !day.isDisabled &&\n day.isCurrentMonth,\n 'text-grayscale-60 hover:bg-grayscale-10':\n !day.isSelected &&\n !day.isRangeStart &&\n !day.isRangeEnd &&\n !day.isDisabled &&\n !day.isCurrentMonth,\n 'ring-2 ring-inset ring-primary':\n day.isToday &&\n !day.isSelected &&\n !day.isRangeStart &&\n !day.isRangeEnd,\n 'cursor-not-allowed text-grayscale-30': day.isDisabled\n }\"\n (mouseenter)=\"onDayHover(day.date)\"\n (mouseleave)=\"onDayHover(null)\"\n (click)=\"selectDate(day)\"\n >\n {{ day.dayOfMonth }}\n </button>\n }\n </div>\n }\n </div>\n }\n\n @if (pickerView() === 'years') {\n <!-- Cabe\u00E7alho de navega\u00E7\u00E3o por d\u00E9cada -->\n <div class=\"flex items-center justify-between border-b border-solid border-grayscale-30 px-3 py-2\">\n <button\n type=\"button\"\n class=\"flex h-7 w-7 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10 disabled:cursor-not-allowed disabled:text-grayscale-30\"\n [disabled]=\"prevDisabled()\"\n [attr.aria-disabled]=\"prevDisabled() ? 'true' : null\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_prev_decade' | translate\"\n (click)=\"navigatePrev()\"\n >\n <i class=\"fas fa-chevron-left text-xs\" aria-hidden=\"true\"></i>\n </button>\n\n <span class=\"text-sm font-medium text-grayscale-90\">{{ currentDecadeStart() }} \u2013 {{ currentDecadeStart() + 11 }}</span>\n\n <button\n type=\"button\"\n class=\"flex h-7 w-7 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10 disabled:cursor-not-allowed disabled:text-grayscale-30\"\n [disabled]=\"nextDisabled()\"\n [attr.aria-disabled]=\"nextDisabled() ? 'true' : null\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_next_decade' | translate\"\n (click)=\"navigateNext()\"\n >\n <i class=\"fas fa-chevron-right text-xs\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <!-- Grade de anos -->\n <div\n class=\"grid grid-cols-3 gap-2 px-3 py-3\"\n role=\"grid\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_select_year' | translate\"\n >\n @for (row of yearsGrid(); track $index) {\n @for (year of row; track year) {\n <button\n type=\"button\"\n role=\"gridcell\"\n class=\"flex h-9 items-center justify-center rounded-small text-sm font-normal transition-colors\"\n [attr.aria-selected]=\"isYearSelected(year) || null\"\n [attr.aria-disabled]=\"isYearDisabled(year) ? 'true' : null\"\n [attr.aria-current]=\"isCurrentYear(year) ? 'date' : null\"\n [attr.data-focus]=\"isYearSelected(year) ? 'selected' : isCurrentYear(year) ? 'today' : null\"\n [disabled]=\"isYearDisabled(year)\"\n [ngClass]=\"{\n 'bg-primary font-semibold text-grayscale-0': isYearSelected(year),\n 'ring-2 ring-inset ring-primary': isCurrentYear(year) && !isYearSelected(year) && !isYearDisabled(year),\n 'text-grayscale-90 hover:bg-grayscale-10': !isYearSelected(year) && !isYearDisabled(year),\n 'cursor-not-allowed text-grayscale-30': isYearDisabled(year)\n }\"\n (click)=\"selectYear(year)\"\n >\n {{ year }}\n </button>\n }\n }\n </div>\n }\n\n @if (pickerView() === 'months') {\n <!-- Cabe\u00E7alho de navega\u00E7\u00E3o anual -->\n <div class=\"flex items-center justify-between border-b border-solid border-grayscale-30 px-3 py-2\">\n <button\n type=\"button\"\n class=\"flex h-7 w-7 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10 disabled:cursor-not-allowed disabled:text-grayscale-30\"\n [disabled]=\"prevDisabled()\"\n [attr.aria-disabled]=\"prevDisabled() ? 'true' : null\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_prev_year' | translate\"\n (click)=\"navigatePrev()\"\n >\n <i class=\"fas fa-chevron-left text-xs\" aria-hidden=\"true\"></i>\n </button>\n\n <span class=\"text-sm font-medium text-grayscale-90\">{{ currentYear() }}</span>\n\n <button\n type=\"button\"\n class=\"flex h-7 w-7 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10 disabled:cursor-not-allowed disabled:text-grayscale-30\"\n [disabled]=\"nextDisabled()\"\n [attr.aria-disabled]=\"nextDisabled() ? 'true' : null\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_next_year' | translate\"\n (click)=\"navigateNext()\"\n >\n <i class=\"fas fa-chevron-right text-xs\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <!-- Grade de meses -->\n <div\n class=\"grid grid-cols-3 gap-2 px-3 py-3\"\n role=\"grid\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_select_month' | translate\"\n >\n @for (row of monthsGrid(); track $index) {\n @for (month of row; track month.index) {\n <button\n type=\"button\"\n role=\"gridcell\"\n class=\"flex h-9 items-center justify-center rounded-small text-sm font-normal transition-colors\"\n [attr.aria-selected]=\"isMonthSelected(month.index) || null\"\n [attr.aria-disabled]=\"isMonthDisabled(month.index) ? 'true' : null\"\n [attr.data-focus]=\"isMonthSelected(month.index) ? 'selected' : null\"\n [disabled]=\"isMonthDisabled(month.index)\"\n [ngClass]=\"{\n 'bg-primary font-semibold text-grayscale-0': isMonthSelected(month.index),\n 'text-grayscale-90 hover:bg-grayscale-10':\n !isMonthSelected(month.index) && !isMonthDisabled(month.index),\n 'cursor-not-allowed text-grayscale-30': isMonthDisabled(month.index)\n }\"\n (click)=\"selectMonth(month.index)\"\n >\n {{ month.key | translate }}\n </button>\n }\n }\n </div>\n\n @if (mode() !== 'month') {\n <div class=\"border-t border-solid border-grayscale-30 px-3 py-2\">\n <button\n type=\"button\"\n class=\"flex items-center gap-2 rounded-small px-2 py-1 text-sm text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n (click)=\"backToCalendar()\"\n >\n <i class=\"fas fa-arrow-left\" aria-hidden=\"true\"></i>\n {{ 'platform.angular_components.datepicker_back_to_calendar' | translate }}\n </button>\n </div>\n }\n }\n }\n\n <!-- Time picker -->\n @if (showTimePicker()) {\n <div\n class=\"flex items-center justify-center gap-3 px-4 py-3\"\n [class.border-t]=\"showCalendar()\"\n [class.border-solid]=\"showCalendar()\"\n [class.border-grayscale-30]=\"showCalendar()\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_select_time' | translate\"\n >\n <!-- Horas -->\n <div class=\"flex flex-col items-center gap-1\">\n <button\n #increaseHourButton\n type=\"button\"\n class=\"flex h-6 w-6 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_increment_hour' | translate\"\n (click)=\"incrementHours()\"\n >\n <i class=\"fas fa-chevron-up text-xs\" aria-hidden=\"true\"></i>\n </button>\n <input\n type=\"text\"\n inputmode=\"numeric\"\n [attr.maxlength]=\"timeInputMaxLength\"\n class=\"h-9 w-12 rounded-small border border-solid border-grayscale-30 bg-grayscale-5 text-center text-base font-medium text-grayscale-90 outline-none focus:border-primary focus:outline-1 focus:outline-primary\"\n [value]=\"padTime(displayHours())\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_hour' | translate\"\n aria-live=\"polite\"\n pattern=\"[0-9]+\"\n (keydown)=\"handleHoursKeydown($event)\"\n (change)=\"handleHoursInput($event)\"\n />\n <button\n type=\"button\"\n class=\"flex h-6 w-6 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_decrement_hour' | translate\"\n (click)=\"decrementHours()\"\n >\n <i class=\"fas fa-chevron-down text-xs\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <span class=\"text-xl font-bold text-grayscale-60\" aria-hidden=\"true\">:</span>\n\n <!-- Minutos -->\n <div class=\"flex flex-col items-center gap-1\">\n <button\n type=\"button\"\n class=\"flex h-6 w-6 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_increment_minute' | translate\"\n (click)=\"incrementMinutes()\"\n >\n <i class=\"fas fa-chevron-up text-xs\" aria-hidden=\"true\"></i>\n </button>\n <input\n type=\"text\"\n inputmode=\"numeric\"\n [attr.maxlength]=\"timeInputMaxLength\"\n class=\"h-9 w-12 rounded-small border border-solid border-grayscale-30 bg-grayscale-5 text-center text-base font-medium text-grayscale-90 outline-none focus:border-primary focus:outline-1 focus:outline-primary\"\n [value]=\"padTime(minutes())\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_minute' | translate\"\n aria-live=\"polite\"\n pattern=\"[0-9]+\"\n (keydown)=\"handleMinutesKeydown($event)\"\n (change)=\"handleMinutesInput($event)\"\n />\n <button\n type=\"button\"\n class=\"flex h-6 w-6 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_decrement_minute' | translate\"\n (click)=\"decrementMinutes()\"\n >\n <i class=\"fas fa-chevron-down text-xs\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n @if (showSeconds()) {\n <span class=\"text-xl font-bold text-grayscale-60\" aria-hidden=\"true\">:</span>\n\n <!-- Segundos -->\n <div class=\"flex flex-col items-center gap-1\">\n <button\n type=\"button\"\n class=\"flex h-6 w-6 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_increment_second' | translate\"\n (click)=\"incrementSeconds()\"\n >\n <i class=\"fas fa-chevron-up text-xs\" aria-hidden=\"true\"></i>\n </button>\n <input\n type=\"text\"\n inputmode=\"numeric\"\n [attr.maxlength]=\"timeInputMaxLength\"\n class=\"h-9 w-12 rounded-small border border-solid border-grayscale-30 bg-grayscale-5 text-center text-base font-medium text-grayscale-90 outline-none focus:border-primary focus:outline-1 focus:outline-primary\"\n [value]=\"padTime(seconds())\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_second' | translate\"\n aria-live=\"polite\"\n pattern=\"[0-9]+\"\n (keydown)=\"handleSecondsKeydown($event)\"\n (change)=\"handleSecondsInput($event)\"\n />\n <button\n type=\"button\"\n class=\"flex h-6 w-6 items-center justify-center rounded-small text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_decrement_second' | translate\"\n (click)=\"decrementSeconds()\"\n >\n <i class=\"fas fa-chevron-down text-xs\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n\n @if (is12HourFormat()) {\n <!-- Seletor AM/PM -->\n <button\n type=\"button\"\n class=\"flex h-9 w-12 items-center justify-center rounded-small border border-solid border-grayscale-30 bg-grayscale-5 text-base font-medium text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n [attr.aria-label]=\"'platform.angular_components.datepicker_toggle_meridiem' | translate\"\n aria-live=\"polite\"\n (click)=\"toggleAmPm()\"\n >\n {{ amPm() }}\n </button>\n }\n </div>\n }\n\n <!-- Rodap\u00E9 de a\u00E7\u00F5es -->\n @if (showButtonBar() || mode() === 'datetime' || mode() === 'time') {\n <div class=\"flex items-center justify-between border-t border-solid border-grayscale-30 px-3 py-2\">\n @if (showButtonBar()) {\n <div>\n @if (mode() === 'date' || mode() === 'datetime' || mode() === 'range') {\n <button\n type=\"button\"\n class=\"rounded-small px-2 py-1 text-sm text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n (click)=\"selectToday()\"\n >\n {{ 'platform.angular_components.datepicker_today' | translate }}\n </button>\n }\n </div>\n\n <div class=\"flex gap-2\">\n <button\n type=\"button\"\n class=\"rounded-small px-2 py-1 text-sm text-grayscale-90 transition-colors hover:bg-grayscale-10\"\n (click)=\"clearValue($event)\"\n >\n {{ 'platform.angular_components.datepicker_clear' | translate }}\n </button>\n\n @if (mode() === 'datetime' || mode() === 'time') {\n <button\n type=\"button\"\n class=\"rounded-small bg-primary px-3 py-1 text-sm font-medium text-grayscale-0 transition-colors hover:opacity-90\"\n (click)=\"confirm()\"\n >\n {{ 'platform.angular_components.datepicker_confirm' | translate }}\n </button>\n }\n </div>\n } @else {\n <div></div>\n <div>\n @if (mode() === 'datetime' || mode() === 'time') {\n <button\n type=\"button\"\n class=\"rounded-small bg-primary px-3 py-1 text-sm font-medium text-grayscale-0 transition-colors hover:opacity-90\"\n (click)=\"confirm()\"\n >\n {{ 'platform.angular_components.datepicker_confirm' | translate }}\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n", styles: [":host{display:block;position:relative;width:100%}:host.ng-invalid.ng-dirty input{border-color:#c13018}:host.ng-invalid.ng-dirty input:focus{border-color:#c13018;outline-color:#c13018}:host.ng-invalid.ng-dirty button[type=button]{border-color:#c13018}:host.no-icon button[type=button]{display:none}:host.no-icon input{padding-right:.75rem}input.hide-native-icon::-webkit-calendar-picker-indicator{display:none}button[type=button]:focus-visible{outline:2px solid #428BCA;outline-offset:1px;border-radius:inherit}\n"] }]
|
|
1061
|
+
}], propDecorators: { handleHoursKeydown: [], handleMinutesKeydown: [], handleSecondsKeydown: [] } });
|
|
1062
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLWNvbXBvbmVudHMvZGF0ZXBpY2tlci9zcmMvbGliL2RhdGVwaWNrZXIvZGF0ZXBpY2tlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLWNvbXBvbmVudHMvZGF0ZXBpY2tlci9zcmMvbGliL2RhdGVwaWNrZXIvZGF0ZXBpY2tlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2pELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxnQkFBZ0IsRUFBcUIsTUFBTSxzQkFBc0IsQ0FBQztBQUNoRyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxFQUNILGVBQWUsRUFDZixTQUFTLEVBQ1QsUUFBUSxFQUNSLFVBQVUsRUFDVixNQUFNLEVBQ04sUUFBUSxFQUNSLEtBQUssRUFDTCxLQUFLLEVBRUwsTUFBTSxFQUNOLE1BQU0sRUFDTixTQUFTLEdBQ1osTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUdILFdBQVcsRUFDWCxhQUFhLEVBQ2IsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxtQkFBbUIsRUFHbkIsVUFBVSxHQUNiLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxNQUFNLGNBQWMsQ0FBQzs7OztBQU1yRixTQUFTLGVBQWU7SUFDcEIsT0FBTyxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsVUFBOEIsRUFBRSxFQUFFO1FBQ3JELE1BQU0sUUFBUSxHQUFtQyxVQUFVLENBQUMs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ZSxFQUFFOytEQVNqQjs0RkExN0JRLG1CQUFtQjtrQkE5Qi9CLFNBQVM7K0JBQ0ksY0FBYyxjQUNaLElBQUksV0FDUDt3QkFDTCxPQUFPO3dCQUNQLGVBQWU7d0JBQ2YsWUFBWTt3QkFDWixnQkFBZ0I7d0JBQ2hCLG1CQUFtQjt3QkFDbkIsV0FBVzt3QkFDWCxtQkFBbUI7cUJBQ3RCLFFBR0s7d0JBQ0YsaUJBQWlCLEVBQUUsYUFBYTtxQkFDbkMsYUFDVTt3QkFDUDs0QkFDSSxPQUFPLEVBQUUsaUJBQWlCOzRCQUMxQixXQUFXLHFCQUFxQjs0QkFDaEMsS0FBSyxFQUFFLElBQUk7eUJBQ2Q7d0JBQ0Q7NEJBQ0ksT0FBTyxFQUFFLGFBQWE7NEJBQ3RCLFdBQVcscUJBQXFCOzRCQUNoQyxLQUFLLEVBQUUsSUFBSTt5QkFDZDtxQkFDSjs4QkE4NUJTLGtCQUFrQixNQVdsQixvQkFBb0IsTUFXcEIsb0JBQW9CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2RrVHJhcEZvY3VzIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2ExMXknO1xuaW1wb3J0IHsgQ2RrQ29ubmVjdGVkT3ZlcmxheSwgQ2RrT3ZlcmxheU9yaWdpbiwgQ29ubmVjdGVkUG9zaXRpb24gfSBmcm9tICdAYW5ndWxhci9jZGsvb3ZlcmxheSc7XG5pbXBvcnQgeyBOZ0NsYXNzIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7XG4gICAgYWZ0ZXJOZXh0UmVuZGVyLFxuICAgIENvbXBvbmVudCxcbiAgICBjb21wdXRlZCxcbiAgICBFbGVtZW50UmVmLFxuICAgIGluamVjdCxcbiAgICBJbmplY3RvcixcbiAgICBpbnB1dCxcbiAgICBtb2RlbCxcbiAgICBPbkluaXQsXG4gICAgb3V0cHV0LFxuICAgIHNpZ25hbCxcbiAgICB2aWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgICBBYnN0cmFjdENvbnRyb2wsXG4gICAgQ29udHJvbFZhbHVlQWNjZXNzb3IsXG4gICAgRm9ybXNNb2R1bGUsXG4gICAgTkdfVkFMSURBVE9SUyxcbiAgICBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICBOZ0NvbnRyb2wsXG4gICAgUmVhY3RpdmVGb3Jtc01vZHVsZSxcbiAgICBWYWxpZGF0aW9uRXJyb3JzLFxuICAgIFZhbGlkYXRvcixcbiAgICBWYWxpZGF0b3JzLFxufSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBUcmFuc2xhdGVNb2R1bGUgfSBmcm9tICdAbmd4LXRyYW5zbGF0ZS9jb3JlJztcbmltcG9ydCB7IGZvcm1hdFZhbHVlRm9ySW5wdXQsIGlzU2FtZURheSwgcGFyc2VJbnB1dCwgc3RyaXBUaW1lIH0gZnJvbSAnLi9kYXRlLnV0aWxzJztcbmltcG9ydCB0eXBlIHsgQ2FsZW5kYXJEYXksIERhdGVQaWNrZXJNb2RlLCBEYXRlUmFuZ2UgfSBmcm9tICcuL21vZGVscyc7XG5cbnR5cGUgRGF0ZXBpY2tlclZhbHVlID0gRGF0ZSB8IERhdGVSYW5nZSB8IERhdGVbXSB8IG51bGw7XG50eXBlIFBpY2tlclZpZXcgPSAnY2FsZW5kYXInIHwgJ21vbnRocycgfCAneWVhcnMnO1xuXG5mdW5jdGlvbiBudW1lcmljS2V5c09ubHkoKTogTWV0aG9kRGVjb3JhdG9yIHtcbiAgICByZXR1cm4gKF90YXJnZXQsIF9rZXksIGRlc2NyaXB0b3I6IFByb3BlcnR5RGVzY3JpcHRvcikgPT4ge1xuICAgICAgICBjb25zdCBvcmlnaW5hbDogKGV2ZW50OiBLZXlib2FyZEV2ZW50KSA9PiB2b2lkID0gZGVzY3JpcHRvci52YWx1ZTtcbiAgICAgICAgZGVzY3JpcHRvci52YWx1ZSA9IGZ1bmN0aW9uICh0aGlzOiB1bmtub3duLCBldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgICAgICAgICAgY29uc3QgaXNWYWxpZEtleSA9XG4gICAgICAgICAgICAgICAgWydBcnJvd1VwJywgJ0Fycm93RG93bicsICdCYWNrc3BhY2UnLCAnRGVsZXRlJywgJ1RhYiddLmluY2x1ZGVzKGV2ZW50LmtleSkgfHwgL15cXGQkLy50ZXN0KGV2ZW50LmtleSk7XG4gICAgICAgICAgICBpZiAoIWlzVmFsaWRLZXkpIHtcbiAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBvcmlnaW5hbC5jYWxsKHRoaXMsIGV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIGRlc2NyaXB0b3I7XG4gICAgfTtcbn1cblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdzLWRhdGVwaWNrZXInLFxuICAgIHN0YW5kYWxvbmU6IHRydWUsXG4gICAgaW1wb3J0czogW1xuICAgICAgICBOZ0NsYXNzLFxuICAgICAgICBUcmFuc2xhdGVNb2R1bGUsXG4gICAgICAgIENka1RyYXBGb2N1cyxcbiAgICAgICAgQ2RrT3ZlcmxheU9yaWdpbixcbiAgICAgICAgQ2RrQ29ubmVjdGVkT3ZlcmxheSxcbiAgICAgICAgRm9ybXNNb2R1bGUsXG4gICAgICAgIFJlYWN0aXZlRm9ybXNNb2R1bGUsXG4gICAgXSxcbiAgICB0ZW1wbGF0ZVVybDogJy4vZGF0ZXBpY2tlci5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmw6ICcuL2RhdGVwaWNrZXIuY29tcG9uZW50LnNjc3MnLFxuICAgIGhvc3Q6IHtcbiAgICAgICAgJ1tjbGFzcy5uby1pY29uXSc6ICchc2hvd0ljb24oKScsXG4gICAgfSxcbiAgICBwcm92aWRlcnM6IFtcbiAgICAgICAge1xuICAgICAgICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICAgICAgICB1c2VFeGlzdGluZzogRGF0ZXBpY2tlckNvbXBvbmVudCxcbiAgICAgICAgICAgIG11bHRpOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICBwcm92aWRlOiBOR19WQUxJREFUT1JTLFxuICAgICAgICAgICAgdXNlRXhpc3Rpbmc6IERhdGVwaWNrZXJDb21wb25lbnQsXG4gICAgICAgICAgICBtdWx0aTogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICBdLFxufSlcbmV4cG9ydCBjbGFzcyBEYXRlcGlja2VyQ29tcG9uZW50IGltcGxlbWVudHMgQ29udHJvbFZhbHVlQWNjZXNzb3IsIFZhbGlkYXRvciwgT25Jbml0IHtcbiAgICBwcml2YXRlIHN0YXRpYyBpZENvdW50ZXIgPSAwO1xuICAgIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IERBWVNfSU5fV0VFSyA9IDc7XG4gICAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgTU9OVEhTX0lOX1lFQVIgPSAxMjtcbiAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBNT05USFNfUEVSX1JPVyA9IDM7XG4gICAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgWUVBUlNfUEVSX0dSSUQgPSAxMjtcbiAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBZRUFSU19QRVJfUk9XID0gMztcbiAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBERUZBVUxUX01JTlVURV9TVEVQID0gNTtcbiAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBNQVhfSE9VUlMgPSAyNDtcbiAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBNQVhfTUlOVVRFUyA9IDYwO1xuICAgIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IEhPVVJTX1BFUl9NRVJJRElFTSA9IDEyO1xuXG4gICAgcHJpdmF0ZSBzdGF0aWMgbmV4dElkKCk6IHN0cmluZyB7XG4gICAgICAgIERhdGVwaWNrZXJDb21wb25lbnQuaWRDb3VudGVyKys7XG4gICAgICAgIHJldHVybiBgcy1kYXRlcGlja2VyLSR7RGF0ZXBpY2tlckNvbXBvbmVudC5pZENvdW50ZXJ9YDtcbiAgICB9XG5cbiAgICAvLyDilIDilIAgSW5wdXRzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gICAgLyoqIEhUTUwgYGlkYCBhcGxpY2FkbyBhbyBlbGVtZW50byBgPGlucHV0PmAuIEF1dG8tZ2VyYWRvIHF1YW5kbyBvbWl0aWRvLiAqL1xuICAgIHJlYWRvbmx5IGlucHV0SWQgPSBpbnB1dDxzdHJpbmc+KERhdGVwaWNrZXJDb21wb25lbnQubmV4dElkKCkpO1xuXG4gICAgLyoqIEF0cmlidXRvIGBuYW1lYCBkbyBgPGlucHV0PmAgbmF0aXZvLiAqL1xuICAgIHJlYWRvbmx5IG5hbWUgPSBpbnB1dDxzdHJpbmc+KCk7XG5cbiAgICAvKiogVGV4dG8gZXhpYmlkbyBxdWFuZG8gbmVuaHVtIHZhbG9yIGVzdMOhIHNlbGVjaW9uYWRvLiAqL1xuICAgIHJlYWRvbmx5IHBsYWNlaG9sZGVyID0gaW5wdXQ8c3RyaW5nPigpO1xuXG4gICAgLyoqXG4gICAgICogTW9kbyBkZSBzZWxlw6fDo28gZG8gY29tcG9uZW50ZS5cbiAgICAgKiAtIGAnZGF0ZSdgIOKAlCBzZWxlw6fDo28gZGUgZGF0YSDDum5pY2EgKHBhZHLDo28pXG4gICAgICogLSBgJ21vbnRoJ2Ag4oCUIHNlbGXDp8OjbyBkZSBtw6pzL2Fub1xuICAgICAqIC0gYCdkYXRldGltZSdgIOKAlCBkYXRhIGNvbSBob3JhIChyZXF1ZXIgY29uZmlybWHDp8OjbylcbiAgICAgKiAtIGAndGltZSdgIOKAlCBhcGVuYXMgc2VsZcOnw6NvIGRlIGhvcmFcbiAgICAgKiAtIGAncmFuZ2UnYCDigJQgaW50ZXJ2YWxvIGVudHJlIGR1YXMgZGF0YXNcbiAgICAgKi9cbiAgICByZWFkb25seSBtb2RlID0gaW5wdXQ8RGF0ZVBpY2tlck1vZGU+KCdkYXRlJyk7XG5cbiAgICAvKipcbiAgICAgKiBNb2RvIGRlIHNlbGXDp8OjbyBxdWFuZG8gYG1vZGVgIMOpIGAnZGF0ZSdgLlxuICAgICAqIC0gYCdzaW5nbGUnYCDigJQgc2VsZcOnw6NvIGRlIHVtYSDDum5pY2EgZGF0YSAocGFkcsOjbylcbiAgICAgKiAtIGAnbXVsdGlwbGUnYCDigJQgc2VsZcOnw6NvIGRlIG3Dumx0aXBsYXMgZGF0YXMgYXZ1bHNhc1xuICAgICAqL1xuICAgIHJlYWRvbmx5IHNlbGVjdGlvbk1vZGUgPSBpbnB1dDwnc2luZ2xlJyB8ICdtdWx0aXBsZSc+KCdzaW5nbGUnKTtcblxuICAgIC8qKiBTZXBhcmFkb3IgZXhpYmlkbyBlbnRyZSBhcyBkYXRhcyBubyBtb2RvIGBzZWxlY3Rpb25Nb2RlID0gJ211bHRpcGxlJ2AuICovXG4gICAgcmVhZG9ubHkgbXVsdGlwbGVTZXBhcmF0b3IgPSBpbnB1dDxzdHJpbmc+KCcsICcpO1xuXG4gICAgLyoqIFF1YW5kbyBgdHJ1ZWAsIGV4aWJlIG8gYm90w6NvIGRlIMOtY29uZSBhbyBsYWRvIGRvIGNhbXBvLiAqL1xuICAgIHJlYWRvbmx5IHNob3dJY29uID0gaW5wdXQ8Ym9vbGVhbj4odHJ1ZSk7XG5cbiAgICAvKipcbiAgICAgKiBDbGFzc2UgZG8gw61jb25lIGV4aWJpZG8gbm8gYm90w6NvIGRvIGNhbXBvLlxuICAgICAqIFF1YW5kbyBgbW9kZWAgw6kgYCd0aW1lJ2AsIG8gcGFkcsOjbyBtdWRhIGF1dG9tYXRpY2FtZW50ZSBwYXJhIGAnZmFzIGZhLWNsb2NrJ2AuXG4gICAgICovXG4gICAgcmVhZG9ubHkgaWNvbiA9IGlucHV0PHN0cmluZz4oJ2ZhcyBmYS1jYWxlbmRhcicpO1xuXG4gICAgLyoqIERhdGEgbcOtbmltYSBzZWxlY2lvbsOhdmVsLiBEaWFzL21lc2VzIGFudGVyaW9yZXMgZmljYW0gZGVzYWJpbGl0YWRvcy4gKi9cbiAgICByZWFkb25seSBtaW4gPSBpbnB1dDxEYXRlIHwgbnVsbD4obnVsbCk7XG5cbiAgICAvKiogRGF0YSBtw6F4aW1hIHNlbGVjaW9uw6F2ZWwuIERpYXMvbWVzZXMgcG9zdGVyaW9yZXMgZmljYW0gZGVzYWJpbGl0YWRvcy4gKi9cbiAgICByZWFkb25seSBtYXggPSBpbnB1dDxEYXRlIHwgbnVsbD4obnVsbCk7XG5cbiAgICAvKiogRGF0YSBleGliaWRhIGFvIGFicmlyIG8gY2FsZW5kw6FyaW8gcXVhbmRvIG5lbmh1bWEgZGF0YSBlc3TDoSBzZWxlY2lvbmFkYS4gKi9cbiAgICByZWFkb25seSBkZWZhdWx0RGF0ZSA9IGlucHV0PERhdGUgfCBudWxsPihudWxsKTtcblxuICAgIC8qKiBGb3JtYXRvIGRlIGV4aWJpw6fDo28gZGEgZGF0YSBubyBjYW1wbyAodXNhZG8gYXBlbmFzIHBhcmEgZGlzcGxheSkuICovXG4gICAgcmVhZG9ubHkgZGF0ZUZvcm1hdCA9IGlucHV0PHN0cmluZz4oJ2RkL01NL3l5eXknKTtcblxuICAgIC8qKiBGb3JtYXRvIGRlIGV4aWJpw6fDo28gZGFzIGhvcmFzOiBgJzEyJ2Agb3UgYCcyNCdgLiAqL1xuICAgIHJlYWRvbmx5IGhvdXJGb3JtYXQgPSBpbnB1dDwnMTInIHwgJzI0Jz4oJzI0Jyk7XG5cbiAgICAvKiogSW5jcmVtZW50byBlbSBtaW51dG9zIGFvIHVzYXIgYXMgc2V0YXMgZG8gdGltZSBwaWNrZXIuICovXG4gICAgcmVhZG9ubHkgbWludXRlU3RlcCA9IGlucHV0PG51bWJlcj4oRGF0ZXBpY2tlckNvbXBvbmVudC5ERUZBVUxUX01JTlVURV9TVEVQKTtcblxuICAgIC8qKiBRdWFuZG8gYHRydWVgLCBleGliZSBvIGNhbXBvIGRlIHNlZ3VuZG9zIG5vIHRpbWUgcGlja2VyLiAqL1xuICAgIHJlYWRvbmx5IHNob3dTZWNvbmRzID0gaW5wdXQ8Ym9vbGVhbj4oZmFsc2UpO1xuXG4gICAgLyoqIFNlcGFyYWRvciBleGliaWRvIGVudHJlIGFzIGRhdGFzIG5vIG1vZG8gYCdyYW5nZSdgLiAqL1xuICAgIHJlYWRvbmx5IHJhbmdlU2VwYXJhdG9yID0gaW5wdXQ8c3RyaW5nPignIOKAlCAnKTtcblxuICAgIC8qKiBBYnJlIG8gcGFpbmVsIGFvIGZvY2FyIG8gaW5wdXQ7IGZvY28gcGVybWFuZWNlIG5vIGlucHV0LCBuw6NvIHB1bGEgcGFyYSBvIGRyb3Bkb3duLiAqL1xuICAgIHJlYWRvbmx5IHNob3dPbkZvY3VzID0gaW5wdXQ8Ym9vbGVhbj4odHJ1ZSk7XG5cbiAgICAvKiogSW1wZWRlIGRpZ2l0YcOnw6NvIG1hbnVhbDsgdmFsb3Igc8OzIHBvZGUgc2VyIHNlbGVjaW9uYWRvIHBlbG8gY2FsZW5kw6FyaW8uICovXG4gICAgcmVhZG9ubHkgcmVhZG9ubHlJbnB1dCA9IGlucHV0PGJvb2xlYW4+KGZhbHNlKTtcblxuICAgIC8qKiBQcmltZWlybyBkaWEgZGEgc2VtYW5hICgwID0gZG9taW5nbywgMSA9IHNlZ3VuZGEtZmVpcmEsIC4uLiwgNiA9IHPDoWJhZG8pLiAqL1xuICAgIHJlYWRvbmx5IGZpcnN0RGF5T2ZXZWVrID0gaW5wdXQ8bnVtYmVyPigwKTtcblxuICAgIC8qKiBFeGliZS9vY3VsdGEgYSBiYXJyYSBkZSBib3TDtWVzIEhvamUgZSBMaW1wYXIgbm8gcm9kYXDDqS4gKi9cbiAgICByZWFkb25seSBzaG93QnV0dG9uQmFyID0gaW5wdXQ8Ym9vbGVhbj4odHJ1ZSk7XG5cbiAgICAvKiogRXhpYmUgw61jb25lIGRlIGxpbXBhciBpbmxpbmUgbm8gY2FtcG8gZGUgaW5wdXQuICovXG4gICAgcmVhZG9ubHkgc2hvd0NsZWFyID0gaW5wdXQ8Ym9vbGVhbj4oZmFsc2UpO1xuXG4gICAgLyoqIEV4aWJlIGRpYXMgZGUgbWVzZXMgYWRqYWNlbnRlcyBuYSBncmFkZSBkbyBjYWxlbmTDoXJpby4gKi9cbiAgICByZWFkb25seSBzaG93T3RoZXJNb250aHMgPSBpbnB1dDxib29sZWFuPih0cnVlKTtcblxuICAgIC8qKiBQZXJtaXRlIHNlbGVjaW9uYXIgZGlhcyBkZSBtZXNlcyBhZGphY2VudGVzIG5hIGdyYWRlIGRvIGNhbGVuZMOhcmlvLiAqL1xuICAgIHJlYWRvbmx5IHNlbGVjdE90aGVyTW9udGhzID0gaW5wdXQ8Ym9vbGVhbj4oZmFsc2UpO1xuXG4gICAgLyoqIEZlY2hhIG8gcGFpbmVsIGFww7NzIHNlbGVjaW9uYXIgdW1hIGRhdGEgbm8gbW9kbyBgZGF0ZXRpbWVgLiAqL1xuICAgIHJlYWRvbmx5IGhpZGVPbkRhdGVUaW1lU2VsZWN0ID0gaW5wdXQ8Ym9vbGVhbj4oZmFsc2UpO1xuXG4gICAgLyoqIEluY3JlbWVudG8gZGUgaG9yYXMgbm8gdGltZSBwaWNrZXIuICovXG4gICAgcmVhZG9ubHkgc3RlcEhvdXIgPSBpbnB1dDxudW1iZXI+KDEpO1xuXG4gICAgLyoqIEluY3JlbWVudG8gZGUgc2VndW5kb3Mgbm8gdGltZSBwaWNrZXIuICovXG4gICAgcmVhZG9ubHkgc3RlcFNlY29uZCA9IGlucHV0PG51bWJlcj4oMSk7XG5cbiAgICAvKiogw41uZGljZSBkZSB0YWIgZG8gY2FtcG8gZGUgaW5wdXQuICovXG4gICAgcmVhZG9ubHkgdGFiaW5kZXggPSBpbnB1dDxudW1iZXI+KCk7XG5cbiAgICAvKiogRm9jYSBhdXRvbWF0aWNhbWVudGUgbyBjYW1wbyBhbyBjYXJyZWdhciBvIGNvbXBvbmVudGUuICovXG4gICAgcmVhZG9ubHkgYXV0b2ZvY3VzID0gaW5wdXQ8Ym9vbGVhbj4oZmFsc2UpO1xuXG4gICAgLyoqIERhdGFzIGVzcGVjw61maWNhcyBkZXNhYmlsaXRhZGFzIG5vIGNhbGVuZMOhcmlvLiAqL1xuICAgIHJlYWRvbmx5IGRpc2FibGVkRGF0ZXMgPSBpbnB1dDxEYXRlW10+KFtdKTtcblxuICAgIC8qKiBEaWFzIGRhIHNlbWFuYSBkZXNhYmlsaXRhZG9zICgwID0gZG9taW5nbywgLi4uLCA2ID0gc8OhYmFkbykuICovXG4gICAgcmVhZG9ubHkgZGlzYWJsZWREYXlzID0gaW5wdXQ8bnVtYmVyW10+KFtdKTtcblxuICAgIC8vIOKUgOKUgCBUd28td2F5IG1vZGVscyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAgIC8qKiBFc3RhZG8gZGVzYWJpbGl0YWRvIGRvIGNvbXBvbmVudGUuICovXG4gICAgcmVhZG9ubHkgZGlzYWJsZWQgPSBtb2RlbDxib29sZWFuPihmYWxzZSk7XG5cbiAgICAvLyDilIDilIAgT3V0cHV0cyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAgIC8qKiBFbWl0aWRvIHF1YW5kbyBvIGNhbXBvIHBlcmRlIG8gZm9jby4gKi9cbiAgICByZWFkb25seSBibHVycmVkID0gb3V0cHV0PEV2ZW50PigpO1xuXG4gICAgLyoqIEVtaXRpZG8gcXVhbmRvIG8gY2FtcG8gcmVjZWJlIG8gZm9jby4gKi9cbiAgICByZWFkb25seSBmb2N1c2VkID0gb3V0cHV0PEV2ZW50PigpO1xuXG4gICAgLyoqIEVtaXRpZG8gYW8gc2VsZWNpb25hciB1bWEgZGF0YSwgbcOqcywgaG9yw6FyaW8gb3UgaW50ZXJ2YWxvLiAqL1xuICAgIHJlYWRvbmx5IHNlbGVjdGVkID0gb3V0cHV0PERhdGVwaWNrZXJWYWx1ZT4oKTtcblxuICAgIC8qKiBFbWl0aWRvIHF1YW5kbyBvIHBhaW5lbCBkbyBjYWxlbmTDoXJpbyBmZWNoYS4gRW1pdGUgbyBlbGVtZW50byBkbyBwYWluZWwuICovXG4gICAgcmVhZG9ubHkgY2xvc2VkID0gb3V0cHV0PEhUTUxFbGVtZW50PigpO1xuXG4gICAgLyoqIEVtaXRpZG8gYW8gY2xpY2FyIG5vIGJvdMOjbyBcIkhvamVcIi4gKi9cbiAgICByZWFkb25seSB0b2RheUNsaWNrID0gb3V0cHV0PERhdGU+KCk7XG5cbiAgICAvKiogRW1pdGlkbyBhbyBjbGljYXIgbm8gYm90w6NvIFwiTGltcGFyXCIgb3Ugbm8gw61jb25lIGRlIGxpbXBhciBpbmxpbmUuICovXG4gICAgcmVhZG9ubHkgY2xlYXJDbGljayA9IG91dHB1dDxNb3VzZUV2ZW50PigpO1xuXG4gICAgLyoqIEVtaXRpZG8gcXVhbmRvIG8gbcOqcyB2aXN1YWxpemFkbyBtdWRhLiAqL1xuICAgIHJlYWRvbmx5IG1vbnRoQ2hhbmdlID0gb3V0cHV0PHsgbW9udGg6IG51bWJlcjsgeWVhcjogbnVtYmVyIH0+KCk7XG5cbiAgICAvKiogRW1pdGlkbyBxdWFuZG8gbyBhbm8gdmlzdWFsaXphZG8gbXVkYS4gKi9cbiAgICByZWFkb25seSB5ZWFyQ2hhbmdlID0gb3V0cHV0PHsgbW9udGg6IG51bWJlcjsgeWVhcjogbnVtYmVyIH0+KCk7XG5cbiAgICAvKiogRW1pdGlkbyBxdWFuZG8gbyBwYWluZWwgZG8gY2FsZW5kw6FyaW8gYWJyZS4gKi9cbiAgICByZWFkb25seSBzaG93ID0gb3V0cHV0PHZvaWQ+KCk7XG5cbiAgICAvKiogRW1pdGlkbyBxdWFuZG8gbyB1c3XDoXJpbyBkaWdpdGEgbWFudWFsbWVudGUgbm8gY2FtcG8uICovXG4gICAgcmVhZG9ubHkgdmFsdWVJbnB1dCA9IG91dHB1dDxFdmVudD4oKTtcblxuICAgIC8vIOKUgOKUgCBJbnRlcm5hbCBzdGF0ZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAgIHByb3RlY3RlZCByZWFkb25seSBtYXhIb3VycyA9IERhdGVwaWNrZXJDb21wb25lbnQuTUFYX0hPVVJTO1xuICAgIHByb3RlY3RlZCByZWFkb25seSBtYXhNaW51dGVzID0gRGF0ZXBpY2tlckNvbXBvbmVudC5NQVhfTUlOVVRFUztcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgdGltZUlucHV0TWF4TGVuZ3RoID0gMjtcblxuICAgIHByb3RlY3RlZCBpbnB1dERhdGUgPSAnJztcblxuICAgIHByb3RlY3RlZCBuZ0NvbnRyb2w6IE5nQ29udHJvbCB8IG51bGwgPSBudWxsO1xuXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IHZhbHVlID0gc2lnbmFsPERhdGUgfCBudWxsPihudWxsKTtcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgaXNPcGVuID0gc2lnbmFsKGZhbHNlKTtcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgdmlld0RhdGUgPSBzaWduYWwobmV3IERhdGUoKSk7XG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IHBpY2tlclZpZXcgPSBzaWduYWw8UGlja2VyVmlldz4oJ2NhbGVuZGFyJyk7XG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGhvdXJzID0gc2lnbmFsKDApO1xuICAgIHByb3RlY3RlZCByZWFkb25seSBtaW51dGVzID0gc2lnbmFsKDApO1xuICAgIHByb3RlY3RlZCByZWFkb25seSBzZWNvbmRzID0gc2lnbmFsKDApO1xuICAgIHByb3RlY3RlZCByZWFkb25seSByYW5nZVZhbHVlID0gc2lnbmFsPERhdGVSYW5nZSB8IG51bGw+KG51bGwpO1xuICAgIHByb3RlY3RlZCByZWFkb25seSBtdWx0aXBsZVZhbHVlcyA9IHNpZ25hbDxEYXRlW10+KFtdKTtcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgcGVuZGluZ1JhbmdlU3RhcnQgPSBzaWduYWw8RGF0ZSB8IG51bGw+KG51bGwpO1xuICAgIHByb3RlY3RlZCByZWFkb25seSBob3ZlckRhdGUgPSBzaWduYWw8RGF0ZSB8IG51bGw+KG51bGwpO1xuICAgIHByaXZhdGUgX2hhc0Zvcm1hdEVycm9yID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBfaXNCYWRJbnB1dCA9IGZhbHNlO1xuICAgIHByaXZhdGUgb25WYWxpZGF0b3JDaGFuZ2U6ICgpID0+IHZvaWQgPSAoKSA9PiB7fTtcbiAgICBwcml2YXRlIF9vbkNoYW5nZTogKHZhbHVlOiBEYXRlcGlja2VyVmFsdWUpID0+IHZvaWQgPSAoKSA9PiB7fTtcbiAgICBwcml2YXRlIF9vblRvdWNoZWQ6ICgpID0+IHZvaWQgPSAoKSA9PiB7fTtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgcG9wdXBQYW5lbCA9IHZpZXdDaGlsZCgncG9wdXBQYW5lbCcsIHsgcmVhZDogRWxlbWVudFJlZiB9KTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IGluY3JlYXNlSG91ckJ1dHRvbiA9IHZpZXdDaGlsZCgnaW5jcmVhc2VIb3VyQnV0dG9uJywgeyByZWFkOiBFbGVtZW50UmVmIH0pO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgaWNvbkJ1dHRvbiA9IHZpZXdDaGlsZCgnaWNvbkJ1dHRvbicsIHsgcmVhZDogRWxlbWVudFJlZiB9KTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IGluamVjdG9yID0gaW5qZWN0KEluamVjdG9yKTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IGhvc3RFbGVtZW50ID0gaW5qZWN0KEVsZW1lbnRSZWYpO1xuXG4gICAgLy8g4pSA4pSAIENvbXB1dGVkIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IHJlc29sdmVkSWNvbiA9IGNvbXB1dGVkKCgpID0+ICh0aGlzLm1vZGUoKSA9PT0gJ3RpbWUnID8gJ2ZhcyBmYS1jbG9jaycgOiB0aGlzLmljb24oKSkpO1xuXG4gICAgLyoqIEluZGljYSBzZSBvIHRpbWUgcGlja2VyIGRldmUgdXNhciBvIGZvcm1hdG8gZGUgMTIgaG9yYXMgY29tIHNlbGV0b3IgQU0vUE0uICovXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGlzMTJIb3VyRm9ybWF0ID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5ob3VyRm9ybWF0KCkgPT09ICcxMicpO1xuXG4gICAgLyoqIEhvcmEgZXhpYmlkYSBubyB0aW1lIHBpY2tlcjogMeKAkzEyIG5vIGZvcm1hdG8gMTJoLCAw4oCTMjMgbm8gZm9ybWF0byAyNGguICovXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGRpc3BsYXlIb3VycyA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICAgICAgaWYgKCF0aGlzLmlzMTJIb3VyRm9ybWF0KCkpIHJldHVybiB0aGlzLmhvdXJzKCk7XG4gICAgICAgIGNvbnN0IGgxMiA9IHRoaXMuaG91cnMoKSAlIERhdGVwaWNrZXJDb21wb25lbnQuSE9VUlNfUEVSX01FUklESUVNO1xuICAgICAgICByZXR1cm4gaDEyID09PSAwID8gRGF0ZXBpY2tlckNvbXBvbmVudC5IT1VSU19QRVJfTUVSSURJRU0gOiBoMTI7XG4gICAgfSk7XG5cbiAgICAvKiogTWVyaWRpYW5vIGF0dWFsIGRlcml2YWRvIGRhIGhvcmEgaW50ZXJuYSAoMOKAkzIzKS4gKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgYW1QbSA9IGNvbXB1dGVkPCdBTScgfCAnUE0nPigoKSA9PlxuICAgICAgICB0aGlzLmhvdXJzKCkgPCBEYXRlcGlja2VyQ29tcG9uZW50LkhPVVJTX1BFUl9NRVJJRElFTSA/ICdBTScgOiAnUE0nLFxuICAgICk7XG5cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgcG9zaXRpb25zOiBDb25uZWN0ZWRQb3NpdGlvbltdID0gW1xuICAgICAgICB7IG9yaWdpblg6ICdzdGFydCcsIG9yaWdpblk6ICdib3R0b20nLCBvdmVybGF5WDogJ3N0YXJ0Jywgb3ZlcmxheVk6ICd0b3AnLCBvZmZzZXRZOiA0IH0sXG4gICAgICAgIHsgb3JpZ2luWDogJ3N0YXJ0Jywgb3JpZ2luWTogJ3RvcCcsIG92ZXJsYXlYOiAnc3RhcnQnLCBvdmVybGF5WTogJ2JvdHRvbScsIG9mZnNldFk6IC00IH0sXG4gICAgXTtcblxuICAgIHByb3RlY3RlZCByZWFkb25seSBwb3B1cElkID0gY29tcHV0ZWQoKCkgPT4gYCR7dGhpcy5pbnB1dElkKCl9LXBvcHVwYCk7XG5cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgY3VycmVudE1vbnRoSW5kZXggPSBjb21wdXRlZCgoKSA9PiB0aGlzLnZpZXdEYXRlKCkuZ2V0TW9udGgoKSk7XG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGN1cnJlbnRZZWFyID0gY29tcHV0ZWQoKCkgPT4gdGhpcy52aWV3RGF0ZSgpLmdldEZ1bGxZZWFyKCkpO1xuICAgIHByb3RlY3RlZCByZWFkb25seSBjdXJyZW50TW9udGhLZXkgPSBjb21wdXRlZCgoKSA9PiB0aGlzLm1vbnRoS2V5c1t0aGlzLmN1cnJlbnRNb250aEluZGV4KCldKTtcblxuICAgIHByb3RlY3RlZCByZWFkb25seSBzaG93Q2FsZW5kYXIgPSBjb21wdXRlZCgoKSA9PiB0aGlzLm1vZGUoKSAhPT0gJ3RpbWUnKTtcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgc2hvd1RpbWVQaWNrZXIgPSBjb21wdXRlZCgoKSA9PiB0aGlzLm1vZGUoKSA9PT0gJ2RhdGV0aW1lJyB8fCB0aGlzLm1vZGUoKSA9PT0gJ3RpbWUnKTtcblxuICAgIC8qKiBTZWxlw6fDo28gbcO6bHRpcGxhIGF0aXZhOiBhcGVuYXMgbm8gbW9kbyBgZGF0ZWAgY29tIGBzZWxlY3Rpb25Nb2RlID0gJ211bHRpcGxlJ2AuICovXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGlzTXVsdGlwbGVNb2RlID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5zZWxlY3Rpb25Nb2RlKCkgPT09ICdtdWx0aXBsZScgJiYgdGhpcy5tb2RlKCkgPT09ICdkYXRlJyk7XG5cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgb3JkZXJlZFdlZWtEYXlLZXlzID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgICAgICBjb25zdCBzdGFydCA9IHRoaXMuZmlyc3REYXlPZldlZWsoKTtcbiAgICAgICAgcmV0dXJuIFsuLi50aGlzLndlZWtEYXlLZXlzLnNsaWNlKHN0YXJ0KSwgLi4udGhpcy53ZWVrRGF5S2V5cy5zbGljZSgwLCBzdGFydCldO1xuICAgIH0pO1xuXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGlucHV0VHlwZSA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuaXNNdWx0aXBsZU1vZGUoKSkgcmV0dXJuICd0ZXh0JztcbiAgICAgICAgY29uc3QgbW9kZSA9IHRoaXMubW9kZSgpO1xuICAgICAgICBpZiAobW9kZSA9PT0gJ2RhdGV0aW1lJykgcmV0dXJuICdkYXRldGltZS1sb2NhbCc7XG4gICAgICAgIGlmIChtb2RlID09PSAncmFuZ2UnIHx8IG1vZGUgPT09ICd5ZWFyJykgcmV0dXJuICd0ZXh0JztcbiAgICAgICAgcmV0dXJuIG1vZGU7XG4gICAgfSk7XG5cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgZGlhbG9nQXJpYUxhYmVsS2V5ID0gY29tcHV0ZWQoKCkgPT5cbiAgICAgICAgdGhpcy5tb2RlKCkgPT09ICdyYW5nZSdcbiAgICAgICAgICAgID8gJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX3NlbGVjdF9yYW5nZSdcbiAgICAgICAgICAgIDogJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX3NlbGVjdF9kYXRlJyxcbiAgICApO1xuXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IHBsYWNlaG9sZGVyS2V5ID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgICAgICBjb25zdCBtb2RlID0gdGhpcy5tb2RlKCk7XG4gICAgICAgIHJldHVybiBgcGxhdGZvcm0uYW5ndWxhcl9jb21wb25lbnRzLmRhdGVwaWNrZXJfcGxhY2Vob2xkZXJfJHttb2RlfWA7XG4gICAgfSk7XG5cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgZWZmZWN0aXZlUmFuZ2UgPSBjb21wdXRlZCgoKTogeyBzdGFydDogRGF0ZSB8IG51bGw7IGVuZDogRGF0ZSB8IG51bGwgfSA9PiB7XG4gICAgICAgIGNvbnN0IHBlbmRpbmcgPSB0aGlzLnBlbmRpbmdSYW5nZVN0YXJ0KCk7XG4gICAgICAgIGNvbnN0IGhvdmVyID0gdGhpcy5ob3ZlckRhdGUoKTtcbiAgICAgICAgaWYgKHBlbmRpbmcpIHtcbiAgICAgICAgICAgIGlmIChob3Zlcikge1xuICAgICAgICAgICAgICAgIGNvbnN0IFtzdGFydCwgZW5kXSA9IHBlbmRpbmcuZ2V0VGltZSgpIDw9IGhvdmVyLmdldFRpbWUoKSA/IFtwZW5kaW5nLCBob3Zlcl0gOiBbaG92ZXIsIHBlbmRpbmddO1xuICAgICAgICAgICAgICAgIHJldHVybiB7IHN0YXJ0LCBlbmQgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB7IHN0YXJ0OiBwZW5kaW5nLCBlbmQ6IG51bGwgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5yYW5nZVZhbHVlKCkgPz8geyBzdGFydDogbnVsbCwgZW5kOiBudWxsIH07XG4gICAgfSk7XG5cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgY2FsZW5kYXJXZWVrcyA9IGNvbXB1dGVkKCgpOiBDYWxlbmRhckRheVtdW10gPT4ge1xuICAgICAgICBjb25zdCB5ZWFyID0gdGhpcy5jdXJyZW50WWVhcigpO1xuICAgICAgICBjb25zdCBtb250aCA9IHRoaXMuY3VycmVudE1vbnRoSW5kZXgoKTtcbiAgICAgICAgY29uc3QgdG9kYXkgPSBuZXcgRGF0ZSgpO1xuICAgICAgICBjb25zdCBzZWxlY3RlZCA9IHRoaXMudmFsdWUoKTtcbiAgICAgICAgY29uc3QgcmFuZ2UgPSB0aGlzLmVmZmVjdGl2ZVJhbmdlKCk7XG4gICAgICAgIGNvbnN0IHJhbmdlU3RhcnRUaW1lID0gcmFuZ2Uuc3RhcnQgPyBzdHJpcFRpbWUocmFuZ2Uuc3RhcnQpIDogbnVsbDtcbiAgICAgICAgY29uc3QgcmFuZ2VFbmRUaW1lID0gcmFuZ2UuZW5kID8gc3RyaXBUaW1lKHJhbmdlLmVuZCkgOiBudWxsO1xuXG4gICAgICAgIGNvbnN0IGZpcnN0RGF5T2ZNb250aCA9IG5ldyBEYXRlKHllYXIsIG1vbnRoLCAxKTtcbiAgICAgICAgY29uc3Qgc3RhcnRXZWVrRGF5ID0gZmlyc3REYXlPZk1vbnRoLmdldERheSgpO1xuICAgICAgICBjb25zdCBhZGp1c3RlZFN0YXJ0RGF5ID0gKHN0YXJ0V2Vla0RheSAtIHRoaXMuZmlyc3REYXlPZldlZWsoKSArIDcpICUgNztcbiAgICAgICAgY29uc3QgZGF5c0luTW9udGggPSBuZXcgRGF0ZSh5ZWFyLCBtb250aCArIDEsIDApLmdldERhdGUoKTtcbiAgICAgICAgY29uc3QgZGF5c0luUHJldk1vbnRoID0gbmV3IERhdGUoeWVhciwgbW9udGgsIDApLmdldERhdGUoKTtcblxuICAgICAgICBjb25zdCBhbGxEYXlzOiBDYWxlbmRhckRheVtdID0gW107XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IGFkanVzdGVkU3RhcnREYXkgLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKHllYXIsIG1vbnRoIC0gMSwgZGF5c0luUHJldk1vbnRoIC0gaSk7XG4gICAgICAgICAgICBhbGxEYXlzLnB1c2godGhpcy5idWlsZENhbGVuZGFyRGF5KGRhdGUsIGZhbHNlLCB0b2RheSwgc2VsZWN0ZWQsIHJhbmdlLCByYW5nZVN0YXJ0VGltZSwgcmFuZ2VFbmRUaW1lKSk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGxldCBkID0gMTsgZCA8PSBkYXlzSW5Nb250aDsgZCsrKSB7XG4gICAgICAgICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoeWVhciwgbW9udGgsIGQpO1xuICAgICAgICAgICAgYWxsRGF5cy5wdXNoKHRoaXMuYnVpbGRDYWxlbmRhckRheShkYXRlLCB0cnVlLCB0b2RheSwgc2VsZWN0ZWQsIHJhbmdlLCByYW5nZVN0YXJ0VGltZSwgcmFuZ2VFbmRUaW1lKSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB0b3RhbENlbGxzID1cbiAgICAgICAgICAgIE1hdGguY2VpbChhbGxEYXlzLmxlbmd0aCAvIERhdGVwaWNrZXJDb21wb25lbnQuREFZU19JTl9XRUVLKSAqIERhdGVwaWNrZXJDb21wb25lbnQuREFZU19JTl9XRUVLO1xuICAgICAgICBsZXQgbmV4dERheSA9IDE7XG4gICAgICAgIHdoaWxlIChhbGxEYXlzLmxlbmd0aCA8IHRvdGFsQ2VsbHMpIHtcbiAgICAgICAgICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZSh5ZWFyLCBtb250aCArIDEsIG5leHREYXkpO1xuICAgICAgICAgICAgbmV4dERheSsrO1xuICAgICAgICAgICAgYWxsRGF5cy5wdXNoKHRoaXMuYnVpbGRDYWxlbmRhckRheShkYXRlLCBmYWxzZSwgdG9kYXksIHNlbGVjdGVkLCByYW5nZSwgcmFuZ2VTdGFydFRpbWUsIHJhbmdlRW5kVGltZSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgd2Vla3M6IENhbGVuZGFyRGF5W11bXSA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFsbERheXMubGVuZ3RoOyBpICs9IERhdGVwaWNrZXJDb21wb25lbnQuREFZU19JTl9XRUVLKSB7XG4gICAgICAgICAgICB3ZWVrcy5wdXNoKGFsbERheXMuc2xpY2UoaSwgaSArIERhdGVwaWNrZXJDb21wb25lbnQuREFZU19JTl9XRUVLKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHdlZWtzO1xuICAgIH0pO1xuXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IG1vbnRoc0dyaWQgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IHJvd3M6IHsga2V5OiBzdHJpbmc7IGluZGV4OiBudW1iZXIgfVtdW10gPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBEYXRlcGlja2VyQ29tcG9uZW50Lk1PTlRIU19JTl9ZRUFSOyBpICs9IERhdGVwaWNrZXJDb21wb25lbnQuTU9OVEhTX1BFUl9ST1cpIHtcbiAgICAgICAgICAgIHJvd3MucHVzaChbXG4gICAgICAgICAgICAgICAgeyBrZXk6IHRoaXMubW9udGhLZXlzW2ldLCBpbmRleDogaSB9LFxuICAgICAgICAgICAgICAgIHsga2V5OiB0aGlzLm1vbnRoS2V5c1tpICsgMV0sIGluZGV4OiBpICsgMSB9LFxuICAgICAgICAgICAgICAgIHsga2V5OiB0aGlzLm1vbnRoS2V5c1tpICsgMl0sIGluZGV4OiBpICsgMiB9LFxuICAgICAgICAgICAgXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJvd3M7XG4gICAgfSk7XG5cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgY3VycmVudERlY2FkZVN0YXJ0ID0gY29tcHV0ZWQoKCkgPT4gTWF0aC5mbG9vcih0aGlzLmN1cnJlbnRZZWFyKCkgLyAxMCkgKiAxMCk7XG5cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgeWVhcnNHcmlkID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgICAgICBjb25zdCBzdGFydCA9IHRoaXMuY3VycmVudERlY2FkZVN0YXJ0KCk7XG4gICAgICAgIGNvbnN0IHJvd3M6IG51bWJlcltdW10gPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBEYXRlcGlja2VyQ29tcG9uZW50LllFQVJTX1BFUl9HUklEOyBpICs9IERhdGVwaWNrZXJDb21wb25lbnQuWUVBUlNfUEVSX1JPVykge1xuICAgICAgICAgICAgcm93cy5wdXNoKFtzdGFydCArIGksIHN0YXJ0ICsgaSArIDEsIHN0YXJ0ICsgaSArIDJdKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcm93cztcbiAgICB9KTtcblxuICAgIHByb3RlY3RlZCByZWFkb25seSBwcmV2RGlzYWJsZWQgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IG1pbiA9IHRoaXMubWluKCk7XG4gICAgICAgIGlmICghbWluKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIGNvbnN0IHZpZXcgPSB0aGlzLnZpZXdEYXRlKCk7XG4gICAgICAgIGlmICh0aGlzLnBpY2tlclZpZXcoKSA9PT0gJ3llYXJzJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY3VycmVudERlY2FkZVN0YXJ0KCkgPD0gbWluLmdldEZ1bGxZZWFyKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMucGlja2VyVmlldygpID09PSAnbW9udGhzJykge1xuICAgICAgICAgICAgcmV0dXJuIHZpZXcuZ2V0RnVsbFllYXIoKSA8PSBtaW4uZ2V0RnVsbFllYXIoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgdmlldy5nZXRGdWxsWWVhcigpIDwgbWluLmdldEZ1bGxZZWFyKCkgfHxcbiAgICAgICAgICAgICh2aWV3LmdldEZ1bGxZZWFyKCkgPT09IG1pbi5nZXRGdWxsWWVhcigpICYmIHZpZXcuZ2V0TW9udGgoKSA8PSBtaW4uZ2V0TW9udGgoKSlcbiAgICAgICAgKTtcbiAgICB9KTtcblxuICAgIHByb3RlY3RlZCByZWFkb25seSBuZXh0RGlzYWJsZWQgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IG1heCA9IHRoaXMubWF4KCk7XG4gICAgICAgIGlmICghbWF4KSByZXR1cm4gZmFsc2U7XG4gICAgICAgIGNvbnN0IHZpZXcgPSB0aGlzLnZpZXdEYXRlKCk7XG4gICAgICAgIGlmICh0aGlzLnBpY2tlclZpZXcoKSA9PT0gJ3llYXJzJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY3VycmVudERlY2FkZVN0YXJ0KCkgKyBEYXRlcGlja2VyQ29tcG9uZW50LllFQVJTX1BFUl9HUklEIC0gMSA+PSBtYXguZ2V0RnVsbFllYXIoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5waWNrZXJWaWV3KCkgPT09ICdtb250aHMnKSB7XG4gICAgICAgICAgICByZXR1cm4gdmlldy5nZXRGdWxsWWVhcigpID49IG1heC5nZXRGdWxsWWVhcigpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB2aWV3LmdldEZ1bGxZZWFyKCkgPiBtYXguZ2V0RnVsbFllYXIoKSB8fFxuICAgICAgICAgICAgKHZpZXcuZ2V0RnVsbFllYXIoKSA9PT0gbWF4LmdldEZ1bGxZZWFyKCkgJiYgdmlldy5nZXRNb250aCgpID49IG1heC5nZXRNb250aCgpKVxuICAgICAgICApO1xuICAgIH0pO1xuXG4gICAgLy8g4pSA4pSAIFRyYW5zbGF0aW9uIGtleXMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgd2Vla0RheUtleXMgPSBbXG4gICAgICAgICdwbGF0Zm9ybS5hbmd1bGFyX2NvbXBvbmVudHMuZGF0ZXBpY2tlcl9kYXlfc3VuJyxcbiAgICAgICAgJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX2RheV9tb24nLFxuICAgICAgICAncGxhdGZvcm0uYW5ndWxhcl9jb21wb25lbnRzLmRhdGVwaWNrZXJfZGF5X3R1ZScsXG4gICAgICAgICdwbGF0Zm9ybS5hbmd1bGFyX2NvbXBvbmVudHMuZGF0ZXBpY2tlcl9kYXlfd2VkJyxcbiAgICAgICAgJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX2RheV90aHUnLFxuICAgICAgICAncGxhdGZvcm0uYW5ndWxhcl9jb21wb25lbnRzLmRhdGVwaWNrZXJfZGF5X2ZyaScsXG4gICAgICAgICdwbGF0Zm9ybS5hbmd1bGFyX2NvbXBvbmVudHMuZGF0ZXBpY2tlcl9kYXlfc2F0JyxcbiAgICBdO1xuXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IG1vbnRoS2V5cyA9IFtcbiAgICAgICAgJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX21vbnRoX2phbicsXG4gICAgICAgICdwbGF0Zm9ybS5hbmd1bGFyX2NvbXBvbmVudHMuZGF0ZXBpY2tlcl9tb250aF9mZWInLFxuICAgICAgICAncGxhdGZvcm0uYW5ndWxhcl9jb21wb25lbnRzLmRhdGVwaWNrZXJfbW9udGhfbWFyJyxcbiAgICAgICAgJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX21vbnRoX2FwcicsXG4gICAgICAgICdwbGF0Zm9ybS5hbmd1bGFyX2NvbXBvbmVudHMuZGF0ZXBpY2tlcl9tb250aF9tYXknLFxuICAgICAgICAncGxhdGZvcm0uYW5ndWxhcl9jb21wb25lbnRzLmRhdGVwaWNrZXJfbW9udGhfanVuJyxcbiAgICAgICAgJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX21vbnRoX2p1bCcsXG4gICAgICAgICdwbGF0Zm9ybS5hbmd1bGFyX2NvbXBvbmVudHMuZGF0ZXBpY2tlcl9tb250aF9hdWcnLFxuICAgICAgICAncGxhdGZvcm0uYW5ndWxhcl9jb21wb25lbnRzLmRhdGVwaWNrZXJfbW9udGhfc2VwJyxcbiAgICAgICAgJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX21vbnRoX29jdCcsXG4gICAgICAgICdwbGF0Zm9ybS5hbmd1bGFyX2NvbXBvbmVudHMuZGF0ZXBpY2tlcl9tb250aF9ub3YnLFxuICAgICAgICAncGxhdGZvcm0uYW5ndWxhcl9jb21wb25lbnRzLmRhdGVwaWNrZXJfbW9udGhfZGVjJyxcbiAgICBdO1xuXG4gICAgLy8g4pSA4pSAIExpZmVjeWNsZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAgIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5uZ0NvbnRyb2wgPSB0aGlzLmluamVjdG9yLmdldChOZ0NvbnRyb2wsIG51bGwsIHsgc2VsZjogdHJ1ZSwgb3B0aW9uYWw6IHRydWUgfSk7XG4gICAgICAgIGFmdGVyTmV4dFJlbmRlcigoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBkID0gdGhpcy5kZWZhdWx0RGF0ZSgpO1xuICAgICAgICAgICAgaWYgKGQgJiYgIXRoaXMudmFsdWUoKSAmJiAhdGhpcy5yYW5nZVZhbHVlKCkgJiYgdGhpcy5tdWx0aXBsZVZhbHVlcygpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUuc2V0KGQpO1xuICAgICAgICAgICAgICAgIHRoaXMuaW5wdXREYXRlID0gdGhpcy5mb3JtYXRGb3JEaXNwbGF5KGQpO1xuICAgICAgICAgICAgICAgIHRoaXMudmlld0RhdGUuc2V0KG5ldyBEYXRlKGQuZ2V0RnVsbFllYXIoKSwgZC5nZXRNb250aCgpLCAxKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5fb25DaGFuZ2UoZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgaW5qZWN0b3I6IHRoaXMuaW5qZWN0b3IgfSk7XG4gICAgfVxuXG4gICAgLy8g4pSA4pSAIENvbnRyb2xWYWx1ZUFjY2Vzc29yIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gICAgcHVibGljIHdyaXRlVmFsdWUodmFsdWU6IERhdGVwaWNrZXJWYWx1ZSk6IHZvaWQge1xuICAgICAgICBpZiAoIXZhbHVlIHx8IChBcnJheS5pc0FycmF5KHZhbHVlKSAmJiB2YWx1ZS5sZW5ndGggPT09IDApKSB7XG4gICAgICAgICAgICB0aGlzLnZhbHVlLnNldChudWxsKTtcbiAgICAgICAgICAgIHRoaXMucmFuZ2VWYWx1ZS5zZXQobnVsbCk7XG4gICAgICAgICAgICB0aGlzLm11bHRpcGxlVmFsdWVzLnNldChbXSk7XG4gICAgICAgICAgICB0aGlzLmlucHV0RGF0ZSA9ICcnO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICAgICAgY29uc3Qgc29ydGVkID0gWy4uLnZhbHVlXS5zb3J0KChhLCBiKSA9PiBhLmdldFRpbWUoKSAtIGIuZ2V0VGltZSgpKTtcbiAgICAgICAgICAgIHRoaXMubXVsdGlwbGVWYWx1ZXMuc2V0KHNvcnRlZCk7XG4gICAgICAgICAgICB0aGlzLmlucHV0RGF0ZSA9IHRoaXMuZm9ybWF0Rm9yRGlzcGxheShzb3J0ZWQpO1xuICAgICAgICAgICAgY29uc3QgZmlyc3QgPSBzb3J0ZWRbMF07XG4gICAgICAgICAgICB0aGlzLnZpZXdEYXRlLnNldChuZXcgRGF0ZShmaXJzdC5nZXRGdWxsWWVhcigpLCBmaXJzdC5nZXRNb250aCgpLCAxKSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaXNEYXRlUmFuZ2UodmFsdWUpKSB7XG4gICAgICAgICAgICB0aGlzLnJhbmdlVmFsdWUuc2V0KHZhbHVlKTtcbiAgICAgICAgICAgIHRoaXMuaW5wdXREYXRlID0gdGhpcy5mb3JtYXRGb3JEaXNwbGF5KHZhbHVlKTtcbiAgICAgICAgICAgIGlmICh2YWx1ZS5zdGFydCkge1xuICAgICAgICAgICAgICAgIHRoaXMudmlld0RhdGUuc2V0KG5ldyBEYXRlKHZhbHVlLnN0YXJ0LmdldEZ1bGxZZWFyKCksIHZhbHVlLnN0YXJ0LmdldE1vbnRoKCksIDEpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnZhbHVlLnNldCh2YWx1ZSBhcyBEYXRlKTtcbiAgICAgICAgdGhpcy5pbnB1dERhdGUgPSB0aGlzLmZvcm1hdEZvckRpc3BsYXkodmFsdWUgYXMgRGF0ZSk7XG4gICAgICAgIGNvbnN0IGQgPSB2YWx1ZSBhcyBEYXRlO1xuICAgICAgICB0aGlzLnZpZXdEYXRlLnNldChuZXcgRGF0ZShkLmdldEZ1bGxZZWFyKCksIGQuZ2V0TW9udGgoKSwgMSkpO1xuICAgICAgICB0aGlzLmhvdXJzLnNldChkLmdldEhvdXJzKCkpO1xuICAgICAgICB0aGlzLm1pbnV0ZXMuc2V0KGQuZ2V0TWludXRlcygpKTtcbiAgICAgICAgdGhpcy5zZWNvbmRzLnNldChkLmdldFNlY29uZHMoKSk7XG4gICAgfVxuXG4gICAgcHVibGljIHJlZ2lzdGVyT25DaGFuZ2UoZm46ICh2YWx1ZTogRGF0ZXBpY2tlclZhbHVlKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX29uQ2hhbmdlID0gZm47XG4gICAgfVxuXG4gICAgcHVibGljIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX29uVG91Y2hlZCA9IGZuO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kaXNhYmxlZC5zZXQoaXNEaXNhYmxlZCk7XG4gICAgfVxuXG4gICAgLy8g4pSA4pSAIFZhbGlkYXRvciDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAgIHB1YmxpYyB2YWxpZGF0ZShjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiBWYWxpZGF0aW9uRXJyb3JzIHwgbnVsbCB7XG4gICAgICAgIGxldCB2YWx1ZTogRGF0ZXBpY2tlclZhbHVlO1xuICAgICAgICBpZiAodGhpcy5pc011bHRpcGxlTW9kZSgpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHRoaXMubXVsdGlwbGVWYWx1ZXMoKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLm1vZGUoKSA9PT0gJ3JhbmdlJykge1xuICAgICAgICAgICAgdmFsdWUgPSB0aGlzLnJhbmdlVmFsdWUoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhbHVlID0gdGhpcy52YWx1ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmNvbXB1dGVWYWxpZGF0aW9uRXJyb3JzKHZhbHVlLCBjb250cm9sKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVnaXN0ZXJPblZhbGlkYXRvckNoYW5nZShmbjogKCkgPT4gdm9pZCk6IHZvaWQge1xuICAgICAgICB0aGlzLm9uVmFsaWRhdG9yQ2hhbmdlID0gZm47XG4gICAgfVxuXG4gICAgLy8g4pSA4pSAIFB1YmxpYyBhY3Rpb25zIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gICAgcHJvdGVjdGVkIG9wZW4oKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmRpc2FibGVkKCkpIHJldHVybjtcbiAgICAgICAgdGhpcy5pc09wZW4uc2V0KHRydWUpO1xuICAgICAgICB0aGlzLnByZXBhcmVPcGVuVmlldygpO1xuICAgICAgICB0aGlzLnNob3cuZW1pdCgpO1xuICAgICAgICBpZiAodGhpcy5tb2RlKCkgPT09ICd0aW1lJykge1xuICAgICAgICAgICAgYWZ0ZXJOZXh0UmVuZGVyKCgpID0+IHRoaXMuaW5jcmVhc2VIb3VyQnV0dG9uKCk/Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKSwgeyBpbmplY3RvcjogdGhpcy5pbmplY3RvciB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZm9jdXNCZXN0Q2FsZW5kYXJUYXJnZXQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBBYnJlIG8gcGFpbmVsIHNlbSB0cmFuc2ZlcmlyIG8gZm9jbyBwYXJhIG8gZHJvcGRvd24gKHVzYWRvIHBlbG8gc2hvd09uRm9jdXMpLiAqL1xuICAgIHByaXZhdGUgb3Blbk9uRm9jdXMoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmRpc2FibGVkKCkgfHwgdGhpcy5pc09wZW4oKSkgcmV0dXJuO1xuICAgICAgICB0aGlzLmlzT3Blbi5zZXQodHJ1ZSk7XG4gICAgICAgIHRoaXMucHJlcGFyZU9wZW5WaWV3KCk7XG4gICAgICAgIHRoaXMuc2hvdy5lbWl0KCk7XG4gICAgICAgIC8vIEZvY28gcGVybWFuZWNlIG5vIGlucHV0IOKAlCBuw6NvIGNoYW1hIGZvY3VzQmVzdENhbGVuZGFyVGFyZ2V0KClcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZWZpbmUgYSB2aWV3IGluaWNpYWwgZG8gcGFpbmVsIGUgcG9zaWNpb25hIG8gY2FsZW5kw6FyaW8gbm8gYGRlZmF1bHREYXRlYFxuICAgICAqIHF1YW5kbyBuZW5odW0gdmFsb3IgZXN0w6Egc2VsZWNpb25hZG8uXG4gICAgICovXG4gICAgcHJpdmF0ZSBwcmVwYXJlT3BlblZpZXcoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGRlZmF1bHREYXRlID0gdGhpcy5kZWZhdWx0RGF0ZSgpO1xuICAgICAgICBpZiAoZGVmYXVsdERhdGUgJiYgIXRoaXMudmFsdWUoKSAmJiAhdGhpcy5yYW5nZVZhbHVlKCkpIHtcbiAgICAgICAgICAgIHRoaXMudmlld0RhdGUuc2V0KG5ldyBEYXRlKGRlZmF1bHREYXRlLmdldEZ1bGxZZWFyKCksIGRlZmF1bHREYXRlLmdldE1vbnRoKCksIDEpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5tb2RlKCkgPT09ICdtb250aCcpIHtcbiAgICAgICAgICAgIHRoaXMucGlja2VyVmlldy5zZXQoJ21vbnRocycpO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMubW9kZSgpID09PSAneWVhcicpIHtcbiAgICAgICAgICAgIHRoaXMucGlja2VyVmlldy5zZXQoJ3llYXJzJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnBpY2tlclZpZXcuc2V0KCdjYWxlbmRhcicpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBmb2N1c0Jlc3RDYWxlbmRhclRhcmdldCgpOiB2b2lkIHtcbiAgICAgICAgYWZ0ZXJOZXh0UmVuZGVyKFxuICAgICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhbmVsID0gdGhpcy5wb3B1cFBhbmVsKCk/Lm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgaWYgKCFwYW5lbCkgcmV0dXJuO1xuICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldCA9XG4gICAgICAgICAgICAgICAgICAgIHBhbmVsLnF1ZXJ5U2VsZWN0b3I8SFRNTEVsZW1lbnQ+KCdbZGF0YS1mb2N1cz1cInNlbGVjdGVkXCJdJykgPz9cbiAgICAgICAgICAgICAgICAgICAgcGFuZWwucXVlcnlTZWxlY3RvcjxIVE1MRWxlbWVudD4oJ1tkYXRhLWZvY3VzPVwidG9kYXlcIl0nKSA/P1xuICAgICAgICAgICAgICAgICAgICBwYW5lbC5xdWVyeVNlbGVjdG9yPEhUTUxFbGVtZW50PignYnV0dG9uOm5vdChbZGlzYWJsZWRdKScpO1xuICAgICAgICAgICAgICAgIHRhcmdldD8uZm9jdXMoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7IGluamVjdG9yOiB0aGlzLmluamVjdG9yIH0sXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGNsb3NlUGFuZWwoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHBhbmVsID0gKHRoaXMucG9wdXBQYW5lbCgpPy5uYXRpdmVFbGVtZW50ID8/IHRoaXMuaG9zdEVsZW1lbnQubmF0aXZlRWxlbWVudCkgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgIHRoaXMuaXNPcGVuLnNldChmYWxzZSk7XG4gICAgICAgIHRoaXMucGVuZGluZ1JhbmdlU3RhcnQuc2V0KG51bGwpO1xuICAgICAgICB0aGlzLmhvdmVyRGF0ZS5zZXQobnVsbCk7XG4gICAgICAgIHRoaXMuX29uVG91Y2hlZCgpO1xuICAgICAgICB0aGlzLmNsb3NlZC5lbWl0KHBhbmVsKTtcblxuICAgICAgICBhZnRlck5leHRSZW5kZXIoXG4gICAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5pY29uQnV0dG9uKCk/Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7IGluamVjdG9yOiB0aGlzLmluamVjdG9yIH0sXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIHRvZ2dsZSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuaXNPcGVuKCkpIHtcbiAgICAgICAgICAgIHRoaXMuY2xvc2VQYW5lbCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5vcGVuKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgaGFuZGxlT3ZlcmxheUtleWRvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgaWYgKGV2ZW50LmtleSA9PT0gJ0VzY2FwZScpIHtcbiAgICAgICAgICAgIHRoaXMuY2xvc2VQYW5lbCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGhhbmRsZUlucHV0Q2xpY2soKTogdm9pZCB7fVxuXG4gICAgcHJvdGVjdGVkIGhhbmRsZUlucHV0Rm9jdXMoZXZlbnQ6IEV2ZW50KTogdm9pZCB7XG4gICAgICAgIHRoaXMuZm9jdXNlZC5lbWl0KGV2ZW50KTtcbiAgICAgICAgaWYgKHRoaXMuc2hvd09uRm9jdXMoKSkge1xuICAgICAgICAgICAgdGhpcy5vcGVuT25Gb2N1cygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGhhbmRsZU5hdGl2ZUlucHV0KGV2ZW50OiBFdmVudCk6IHZvaWQge1xuICAgICAgICB0aGlzLnZhbHVlSW5wdXQuZW1pdChldmVudCk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGhhbmRsZUlucHV0Qmx1cihldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5ibHVycmVkLmVtaXQoZXZlbnQpO1xuICAgICAgICBjb25zdCBpbnB1dCA9IGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50O1xuICAgICAgICB0aGlzLl9pc0JhZElucHV0ID0gaW5wdXQudmFsaWRpdHk/LmJhZElucHV0ID8/IGZhbHNlO1xuICAgICAgICBpZiAoIWlucHV0LnZhbHVlPy50cmltKCkpIHtcbiAgICAgICAgICAgIHRoaXMub25WYWxpZGF0b3JDaGFuZ2UoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5pc09wZW4oKSkge1xuICAgICAgICAgICAgY29uc3QgcmVsYXRlZFRhcmdldCA9IChldmVudCBhcyBGb2N1c0V2ZW50KS5yZWxhdGVkVGFyZ2V0IGFzIEhUTUxFbGVtZW50IHwgbnVsbDtcbiAgICAgICAgICAgIGNvbnN0IHBhbmVsID0gdGhpcy5wb3B1cFBhbmVsKCk/Lm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgICAgICAgICBpZiAoIXJlbGF0ZWRUYXJnZXQgfHwgIXBhbmVsPy5jb250YWlucyhyZWxhdGVkVGFyZ2V0KSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLm1vZGUoKSA9PT0gJ3RpbWUnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5jcmVhc2VIb3VyQnV0dG9uKCk/Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0YXJnZXQgPVxuICAgICAgICAgICAgICAgICAgICAgICAgcGFuZWw/LnF1ZXJ5U2VsZWN0b3I8SFRNTEVsZW1lbnQ+KCdbZGF0YS1mb2N1cz1cInNlbGVjdGVkXCJdJykgPz9cbiAgICAgICAgICAgICAgICAgICAgICAgIHBhbmVsPy5xdWVyeVNlbGVjdG9yPEhUTUxFbGVtZW50PignW2RhdGEtZm9jdXM9XCJ0b2RheVwiXScpID8/XG4gICAgICAgICAgICAgICAgICAgICAgICBwYW5lbD8ucXVlcnlTZWxlY3RvcjxIVE1MRWxlbWVudD4oJ2J1dHRvbjpub3QoW2Rpc2FibGVkXSknKTtcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0Py5mb2N1cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBoYW5kbGVJbnB1dENoYW5nZShyYXc6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBpZiAoIXJhdz8udHJpbSgpKSB7XG4gICAgICAgICAgICB0aGlzLnZhbHVlLnNldChudWxsKTtcbiAgICAgICAgICAgIHRoaXMucmFuZ2VWYWx1ZS5zZXQobnVsbCk7XG4gICAgICAgICAgICB0aGlzLl9oYXNGb3JtYXRFcnJvciA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5vblZhbGlkYXRvckNoYW5nZSgpO1xuICAgICAgICAgICAgdGhpcy5fb25DaGFuZ2UobnVsbCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2VJbnB1dCh0aGlzLm1vZGUoKSwgcmF3LCB0aGlzLnZhbHVlKCksIHRoaXMubWF4SG91cnMsIHRoaXMubWF4TWludXRlcywgdGhpcy5yYW5nZVNlcGFyYXRvcigpKTtcbiAgICAgICAgaWYgKHBhcnNlZCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5faGFzRm9ybWF0RXJyb3IgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5vblZhbGlkYXRvckNoYW5nZSgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2hhc0Zvcm1hdEVycm9yID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX2lzQmFkSW5wdXQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5vblZhbGlkYXRvckNoYW5nZSgpO1xuICAgICAgICBpZiAodGhpcy5pc0RhdGVSYW5nZShwYXJzZWQpKSB7XG4gICAgICAgICAgICB0aGlzLnJhbmdlVmFsdWUuc2V0KHBhcnNlZCk7XG4gICAgICAgICAgICB0aGlzLl9vbkNoYW5nZShwYXJzZWQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgZCA9IHBhcnNlZCBhcyBEYXRlO1xuICAgICAgICAgICAgdGhpcy52YWx1ZS5zZXQoZCk7XG4gICAgICAgICAgICB0aGlzLnZpZXdEYXRlLnNldChuZXcgRGF0ZShkLmdldEZ1bGxZZWFyKCksIGQuZ2V0TW9udGgoKSwgMSkpO1xuICAgICAgICAgICAgdGhpcy5ob3Vycy5zZXQoZC5nZXRIb3VycygpKTtcbiAgICAgICAgICAgIHRoaXMubWludXRlcy5zZXQoZC5nZXRNaW51dGVzKCkpO1xuICAgICAgICAgICAgdGhpcy5fb25DaGFuZ2UoZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgaGFuZGxlVHJpZ2dlcktleWRvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgaWYgKGV2ZW50LmtleSA9PT0gJ0VudGVyJyB8fCBldmVudC5rZXkgPT09ICcgJykge1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHRoaXMub3BlbigpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8g4pSA4pSAIE5hdmlnYXRpb24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgICBwcm90ZWN0ZWQgbmF2aWdhdGVQcmV2KCk6IHZvaWQge1xuICAgICAgICBjb25zdCB2aWV3ID0gdGhpcy52aWV3RGF0ZSgpO1xuICAgICAgICBpZiAodGhpcy5waWNrZXJWaWV3KCkgPT09ICd5ZWFycycpIHtcbiAgICAgICAgICAgIHRoaXMudmlld0RhdGUuc2V0KG5ldyBEYXRlKHZpZXcuZ2V0RnVsbFllYXIoKSAtIDEwLCB2aWV3LmdldE1vbnRoKCksIDEpKTtcbiAgICAgICAgICAgIHRoaXMueWVhckNoYW5nZS5lbWl0KHsgbW9udGg6IHZpZXcuZ2V0TW9udGgoKSwgeWVhcjogdmlldy5nZXRGdWxsWWVhcigpIC0gMTAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5waWNrZXJWaWV3KCkgPT09ICdtb250aHMnKSB7XG4gICAgICAgICAgICB0aGlzLnZpZXdEYXRlLnNldChuZXcgRGF0ZSh2aWV3LmdldEZ1bGxZZWFyKCkgLSAxLCB2aWV3LmdldE1vbnRoKCksIDEpKTtcbiAgICAgICAgICAgIHRoaXMueWVhckNoYW5nZS5lbWl0KHsgbW9udGg6IHZpZXcuZ2V0TW9udGgoKSwgeWVhcjogdmlldy5nZXRGdWxsWWVhcigpIC0gMSB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IG5ld0RhdGUgPSBuZXcgRGF0ZSh2aWV3LmdldEZ1bGxZZWFyKCksIHZpZXcuZ2V0TW9udGgoKSAtIDEsIDEpO1xuICAgICAgICAgICAgdGhpcy52aWV3RGF0ZS5zZXQobmV3RGF0ZSk7XG4gICAgICAgICAgICB0aGlzLm1vbnRoQ2hhbmdlLmVtaXQoeyBtb250aDogbmV3RGF0ZS5nZXRNb250aCgpLCB5ZWFyOiBuZXdEYXRlLmdldEZ1bGxZZWFyKCkgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgbmF2aWdhdGVOZXh0KCk6IHZvaWQge1xuICAgICAgICBjb25zdCB2aWV3ID0gdGhpcy52aWV3RGF0ZSgpO1xuICAgICAgICBpZiAodGhpcy5waWNrZXJWaWV3KCkgPT09ICd5ZWFycycpIHtcbiAgICAgICAgICAgIHRoaXMudmlld0RhdGUuc2V0KG5ldyBEYXRlKHZpZXcuZ2V0RnVsbFllYXIoKSArIDEwLCB2aWV3LmdldE1vbnRoKCksIDEpKTtcbiAgICAgICAgICAgIHRoaXMueWVhckNoYW5nZS5lbWl0KHsgbW9udGg6IHZpZXcuZ2V0TW9udGgoKSwgeWVhcjogdmlldy5nZXRGdWxsWWVhcigpICsgMTAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5waWNrZXJWaWV3KCkgPT09ICdtb250aHMnKSB7XG4gICAgICAgICAgICB0aGlzLnZpZXdEYXRlLnNldChuZXcgRGF0ZSh2aWV3LmdldEZ1bGxZZWFyKCkgKyAxLCB2aWV3LmdldE1vbnRoKCksIDEpKTtcbiAgICAgICAgICAgIHRoaXMueWVhckNoYW5nZS5lbWl0KHsgbW9udGg6IHZpZXcuZ2V0TW9udGgoKSwgeWVhcjogdmlldy5nZXRGdWxsWWVhcigpICsgMSB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IG5ld0RhdGUgPSBuZXcgRGF0ZSh2aWV3LmdldEZ1bGxZZWFyKCksIHZpZXcuZ2V0TW9udGgoKSArIDEsIDEpO1xuICAgICAgICAgICAgdGhpcy52aWV3RGF0ZS5zZXQobmV3RGF0ZSk7XG4gICAgICAgICAgICB0aGlzLm1vbnRoQ2hhbmdlLmVtaXQoeyBtb250aDogbmV3RGF0ZS5nZXRNb250aCgpLCB5ZWFyOiBuZXdEYXRlLmdldEZ1bGxZZWFyKCkgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgaGFuZGxlQ2FsZW5kYXJHcmlkS2V5ZG93bihldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgICAgICBjb25zdCBBUlJPV1MgPSBbJ0Fycm93TGVmdCcsICdBcnJvd1JpZ2h0JywgJ0Fycm93VXAnLCAnQXJyb3dEb3duJ107XG4gICAgICAgIGlmICghQVJST1dTLmluY2x1ZGVzKGV2ZW50LmtleSkpIHJldHVybjtcblxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIGNvbnN0IGdyaWQgPSBldmVudC5jdXJyZW50VGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuICAgICAgICBjb25zdCBidXR0b25zID0gQXJyYXkuZnJvbShncmlkLnF1ZXJ5U2VsZWN0b3JBbGw8SFRNTEJ1dHRvbkVsZW1lbnQ+KCdidXR0b25bcm9sZT1cImdyaWRjZWxsXCJdJykpO1xuICAgICAgICBjb25zdCBjdXJyZW50SWR4ID0gYnV0dG9ucy5pbmRleE9mKGV2ZW50LnRhcmdldCBhcyBIVE1MQnV0dG9uRWxlbWVudCk7XG4gICAgICAgIGlmIChjdXJyZW50SWR4ID09PSAtMSkgcmV0dXJuO1xuXG4gICAgICAgIGxldCBkZWx0YSA9IDA7XG4gICAgICAgIGlmIChldmVudC5rZXkgPT09ICdBcnJvd1JpZ2h0JykgZGVsdGEgPSAxO1xuICAgICAgICBlbHNlIGlmIChldmVudC5rZXkgPT09ICdBcnJvd0xlZnQnKSBkZWx0YSA9IC0xO1xuICAgICAgICBlbHNlIGlmIChldmVudC5rZXkgPT09ICdBcnJvd0Rvd24nKSBkZWx0YSA9IERhdGVwaWNrZXJDb21wb25lbnQuREFZU19JTl9XRUVLO1xuICAgICAgICBlbHNlIGlmIChldmVudC5rZXkgPT09ICdBcnJvd1VwJykgZGVsdGEgPSAtRGF0ZXBpY2tlckNvbXBvbmVudC5EQVlTX0lOX1dFRUs7XG5cbiAgICAgICAgY29uc3QgbmV4dElkeCA9IGN1cnJlbnRJZHggKyBkZWx0YTtcblxuICAgICAgICBpZiAobmV4dElkeCA8IDApIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnByZXZEaXNhYmxlZCgpKSByZXR1cm47XG4gICAgICAgICAgICB0aGlzLm5hdmlnYXRlUHJldigpO1xuICAgICAgICAgICAgYWZ0ZXJOZXh0UmVuZGVyKFxuICAgICAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFuZWwgPSB0aGlzLnBvcHVwUGFuZWwoKT8ubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudDtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYnRucyA9IEFycmF5LmZyb20oXG4gICAgICAgICAgICAgICAgICAgICAgICBwYW5lbD8ucXVlcnlTZWxlY3RvckFsbDxIVE1MQnV0dG9uRWxlbWVudD4oJ2J1dHRvbltyb2xlPVwiZ3JpZGNlbGxcIl0nKSA/PyBbXSxcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0SWR4ID0gTWF0aC5tYXgoMCwgYnRucy5sZW5ndGggKyBuZXh0SWR4KTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0ID1cbiAgICAgICAgICAgICAgICAgICAgICAgIERhdGVwaWNrZXJDb21wb25lbnQuZmluZEVuYWJsZWQoYnRucywgdGFyZ2V0SWR4LCAtMSkgPz9cbiAgICAgICAgICAgICAgICAgICAgICAgIERhdGVwaWNrZXJDb21wb25lbnQuZmluZEVuYWJsZWQoYnRucywgdGFyZ2V0SWR4LCAxKTtcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0Py5mb2N1cygpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgeyBpbmplY3RvcjogdGhpcy5pbmplY3RvciB9LFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChuZXh0SWR4ID49IGJ1dHRvbnMubGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5uZXh0RGlzYWJsZWQoKSkgcmV0dXJuO1xuICAgICAgICAgICAgdGhpcy5uYXZpZ2F0ZU5leHQoKTtcbiAgICAgICAgICAgIGFmdGVyTmV4dFJlbmRlcihcbiAgICAgICAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhbmVsID0gdGhpcy5wb3B1cFBhbmVsKCk/Lm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGJ0bnMgPSBBcnJheS5mcm9tKFxuICAgICAgICAgICAgICAgICAgICAgICAgcGFuZWw/LnF1ZXJ5U2VsZWN0b3JBbGw8SFRNTEJ1dHRvbkVsZW1lbnQ+KCdidXR0b25bcm9sZT1cImdyaWRjZWxsXCJdJykgPz8gW10sXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldElkeCA9IE1hdGgubWluKG5leHRJZHggLSBidXR0b25zLmxlbmd0aCwgYnRucy5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0ID1cbiAgICAgICAgICAgICAgICAgICAgICAgIERhdGVwaWNrZXJDb21wb25lbnQuZmluZEVuYWJsZWQoYnRucywgdGFyZ2V0SWR4LCAxKSA/P1xuICAgICAgICAgICAgICAgICAgICAgICAgRGF0ZXBpY2tlckNvbXBvbmVudC5maW5kRW5hYmxlZChidG5zLCB0YXJnZXRJZHgsIC0xKTtcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0Py5mb2N1cygpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgeyBpbmplY3RvcjogdGhpcy5pbmplY3RvciB9LFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghYnV0dG9uc1tuZXh0SWR4XT8uZGlzYWJsZWQpIHtcbiAgICAgICAgICAgIGJ1dHRvbnNbbmV4dElkeF0uZm9jdXMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGZpbmRFbmFibGVkKFxuICAgICAgICBidXR0b25zOiBIVE1MQnV0dG9uRWxlbWVudFtdLFxuICAgICAgICBzdGFydElkeDogbnVtYmVyLFxuICAgICAgICBkaXJlY3Rpb246IDEgfCAtMSxcbiAgICApOiBIVE1MQnV0dG9uRWxlbWVudCB8IG51bGwge1xuICAgICAgICBmb3IgKGxldCBpID0gc3RhcnRJZHg7IGkgPj0gMCAmJiBpIDwgYnV0dG9ucy5sZW5ndGg7IGkgKz0gZGlyZWN0aW9uKSB7XG4gICAgICAgICAgICBpZiAoIWJ1dHRvbnNbaV0uZGlzYWJsZWQpIHJldHVybiBidXR0b25zW2ldO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBzd2l0Y2hUb01vbnRocygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5waWNrZXJWaWV3LnNldCgnbW9udGhzJyk7XG4gICAgICAgIHRoaXMuZm9jdXNCZXN0Q2FsZW5kYXJUYXJnZXQoKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYmFja1RvQ2FsZW5kYXIoKTogdm9pZCB7XG4gICAgICAgIHRoaXMucGlja2VyVmlldy5zZXQoJ2NhbGVuZGFyJyk7XG4gICAgICAgIHRoaXMuZm9jdXNCZXN0Q2FsZW5kYXJUYXJnZXQoKTtcbiAgICB9XG5cbiAgICAvLyDilIDilIAgU2VsZWN0aW9uIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gICAgcHJvdGVjdGVkIHNlbGVjdERhdGUoZGF5OiBDYWxlbmRhckRheSk6IHZvaWQge1xuICAgICAgICBpZiAoZGF5LmlzRGlzYWJsZWQpIHJldHVybjtcbiAgICAgICAgaWYgKHRoaXMuaXNNdWx0aXBsZU1vZGUoKSkge1xuICAgICAgICAgICAgdGhpcy50b2dnbGVNdWx0aXBsZURhdGUoZGF5LmRhdGUpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLm1vZGUoKSA9PT0gJ3JhbmdlJykge1xuICAgICAgICAgICAgY29uc3QgcGVuZGluZyA9IHRoaXMucGVuZGluZ1JhbmdlU3RhcnQoKTtcbiAgICAgICAgICAgIGlmICghcGVuZGluZykge1xuICAgICAgICAgICAgICAgIHRoaXMucGVuZGluZ1JhbmdlU3RhcnQuc2V0KGRheS5kYXRlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgW3N0YXJ0LCBlbmRdID1cbiAgICAgICAgICAgICAgICAgICAgcGVuZGluZy5nZXRUaW1lKCkgPD0gZGF5LmRhdGUuZ2V0VGltZSgpID8gW3BlbmRpbmcsIGRheS5kYXRlXSA6IFtkYXkuZGF0ZSwgcGVuZGluZ107XG4gICAgICAgICAgICAgICAgY29uc3QgcmFuZ2U6IERhdGVSYW5nZSA9IHsgc3RhcnQsIGVuZCB9O1xuICAgICAgICAgICAgICAgIHRoaXMucmFuZ2VWYWx1ZS5zZXQocmFuZ2UpO1xuICAgICAgICAgICAgICAgIHRoaXMuaW5wdXREYXRlID0gdGhpcy5mb3JtYXRGb3JEaXNwbGF5KHJhbmdlKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9vbkNoYW5nZShyYW5nZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZC5lbWl0KHJhbmdlKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNsb3NlUGFuZWwoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBuZXdEYXRlID0gbmV3IERhdGUoXG4gICAgICAgICAgICBkYXkuZGF0ZS5nZXRGdWxsWWVhcigpLFxuICAgICAgICAgICAgZGF5LmRhdGUuZ2V0TW9udGgoKSxcbiAgICAgICAgICAgIGRheS5kYXRlLmdldERhdGUoKSxcbiAgICAgICAgICAgIHRoaXMuaG91cnMoKSxcbiAgICAgICAgICAgIHRoaXMubWludXRlcygpLFxuICAgICAgICAgICAgdGhpcy5zaG93U2Vjb25kcygpID8gdGhpcy5zZWNvbmRzKCkgOiAwLFxuICAgICAgICApO1xuICAgICAgICB0aGlzLnZhbHVlLnNldChuZXdEYXRlKTtcbiAgICAgICAgaWYgKHRoaXMubW9kZSgpID09PSAnZGF0ZScpIHtcbiAgICAgICAgICAgIHRoaXMuaW5wdXREYXRlID0gdGhpcy5mb3JtYXRGb3JEaXNwbGF5KG5ld0RhdGUpO1xuICAgICAgICAgICAgdGhpcy5fb25DaGFuZ2UobmV3RGF0ZSk7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkLmVtaXQobmV3RGF0ZSk7XG4gICAgICAgICAgICB0aGlzLmNsb3NlUGFuZWwoKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLm1vZGUoKSA9PT0gJ2RhdGV0aW1lJykge1xuICAgICAgICAgICAgdGhpcy5pbnB1dERhdGUgPSB0aGlzLmZvcm1hdEZvckRpc3BsYXkobmV3RGF0ZSk7XG4gICAgICAgICAgICB0aGlzLl9vbkNoYW5nZShuZXdEYXRlKTtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWQuZW1pdChuZXdEYXRlKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmhpZGVPbkRhdGVUaW1lU2VsZWN0KCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNsb3NlUGFuZWwoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBBZGljaW9uYS9yZW1vdmUgdW1hIGRhdGEgZGEgc2VsZcOnw6NvIG3Dumx0aXBsYS4gTyBwYWluZWwgcGVybWFuZWNlIGFiZXJ0by4gKi9cbiAgICBwcml2YXRlIHRvZ2dsZU11bHRpcGxlRGF0ZShkYXRlOiBEYXRlKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSBuZXcgRGF0ZShkYXRlLmdldEZ1bGxZZWFyKCksIGRhdGUuZ2V0TW9udGgoKSwgZGF0ZS5nZXREYXRlKCkpO1xuICAgICAgICBjb25zdCBleGlzdGluZyA9IHRoaXMubXVsdGlwbGVWYWx1ZXMoKTtcbiAgICAgICAgY29uc3QgaW5kZXggPSBleGlzdGluZy5maW5kSW5kZXgoKGQpID0+IGlzU2FtZURheShkLCBub3JtYWxpemVkKSk7XG4gICAgICAgIGNvbnN0IG5leHQgPVxuICAgICAgICAgICAgaW5kZXggPj0gMFxuICAgICAgICAgICAgICAgID8gZXhpc3RpbmcuZmlsdGVyKChfLCBpKSA9PiBpICE9PSBpbmRleClcbiAgICAgICAgICAgICAgICA6IFsuLi5leGlzdGluZywgbm9ybWFsaXplZF0uc29ydCgoYSwgYikgPT4gYS5nZXRUaW1lKCkgLSBiLmdldFRpbWUoKSk7XG4gICAgICAgIHRoaXMubXVsdGlwbGVWYWx1ZXMuc2V0KG5leHQpO1xuICAgICAgICB0aGlzLmlucHV0RGF0ZSA9IHRoaXMuZm9ybWF0Rm9yRGlzcGxheShuZXh0KTtcbiAgICAgICAgY29uc3QgZW1pdFZhbHVlID0gbmV4dC5sZW5ndGggPyBuZXh0IDogbnVsbDtcbiAgICAgICAgdGhpcy5vblZhbGlkYXRvckNoYW5nZSgpO1xuICAgICAgICB0aGlzLl9vbkNoYW5nZShlbWl0VmFsdWUpO1xuICAgICAgICB0aGlzLnNlbGVjdGVkLmVtaXQoZW1pdFZhbHVlKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgc2VsZWN0WWVhcih5ZWFyOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuaXNZZWFyRGlzYWJsZWQoeWVhcikpIHJldHVybjtcbiAgICAgICAgY29uc3QgbmV3RGF0ZSA9IG5ldyBEYXRlKHllYXIsIDAsIDEpO1xuICAgICAgICB0aGlzLnZhbHVlLnNldChuZXdEYXRlKTtcbiAgICAgICAgdGhpcy5pbnB1dERhdGUgPSB0aGlzLmZvcm1hdEZvckRpc3BsYXkobmV3RGF0ZSk7XG4gICAgICAgIHRoaXMuX29uQ2hhbmdlKG5ld0RhdGUpO1xuICAgICAgICB0aGlzLnNlbGVjdGVkLmVtaXQobmV3RGF0ZSk7XG4gICAgICAgIHRoaXMuY2xvc2VQYW5lbCgpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBzZWxlY3RNb250aChtb250aEluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuaXNNb250aERpc2FibGVkKG1vbnRoSW5kZXgpKSByZXR1cm47XG4gICAgICAgIGNvbnN0IHllYXIgPSB0aGlzLmN1cnJlbnRZZWFyKCk7XG4gICAgICAgIGNvbnN0IG5ld1ZpZXdEYXRlID0gbmV3IERhdGUoeWVhciwgbW9udGhJbmRleCwgMSk7XG4gICAgICAgIGlmICh0aGlzLm1vZGUoKSA9PT0gJ21vbnRoJykge1xuICAgICAgICAgICAgdGhpcy52YWx1ZS5zZXQobmV3Vmlld0RhdGUpO1xuICAgICAgICAgICAgdGhpcy5pbnB1dERhdGUgPSB0aGlzLmZvcm1hdEZvckRpc3BsYXkobmV3Vmlld0RhdGUpO1xuICAgICAgICAgICAgdGhpcy5fb25DaGFuZ2UobmV3Vmlld0RhdGUpO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZC5lbWl0KG5ld1ZpZXdEYXRlKTtcbiAgICAgICAgICAgIHRoaXMuY2xvc2VQYW5lbCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy52aWV3RGF0ZS5zZXQobmV3Vmlld0RhdGUpO1xuICAgICAgICAgICAgdGhpcy5waWNrZXJWaWV3LnNldCgnY2FsZW5kYXInKTtcbiAgICAgICAgICAgIHRoaXMuZm9jdXNCZXN0Q2FsZW5kYXJUYXJnZXQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBzZWxlY3RUb2RheSgpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgdG9kYXkgPSBuZXcgRGF0ZSgpO1xuICAgICAgICBpZiAoIXRoaXMuaXNEYXRlRGlzYWJsZWQodG9kYXkpKSB7XG4gICAgICAgICAgICBjb25zdCBjYWxEYXk6IENhbGVuZGFyRGF5ID0ge1xuICAgICAgICAgICAgICAgIGRhdGU6IHRvZGF5LFxuICAgICAgICAgICAgICAgIGRheU9mTW9udGg6IHRvZGF5LmdldERhdGUoKSxcbiAgICAgICAgICAgICAgICBpc0N1cnJlbnRNb250aDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBpc1RvZGF5OiB0cnVlLFxuICAgICAgICAgICAgICAgIGlzU2VsZWN0ZWQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGlzRGlzYWJsZWQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGlzUmFuZ2VTdGFydDogZmFsc2UsXG4gICAgICAgICAgICAgICAgaXNSYW5nZUVuZDogZmFsc2UsXG4gICAgICAgICAgICAgICAgaXNJblJhbmdlOiBmYWxzZSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0aGlzLnNlbGVjdERhdGUoY2FsRGF5KTtcbiAgICAgICAgICAgIHRoaXMudG9kYXlDbGljay5lbWl0KHRvZGF5KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBjbGVhclZhbHVlKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgICAgIHRoaXMudmFsdWUuc2V0KG51bGwpO1xuICAgICAgICB0aGlzLmhvdXJzLnNldCgwKTtcbiAgICAgICAgdGhpcy5taW51dGVzLnNldCgwKTtcbiAgICAgICAgdGhpcy5zZWNvbmRzLnNldCgwKTtcbiAgICAgICAgdGhpcy5yYW5nZVZhbHVlLnNldChudWxsKTtcbiAgICAgICAgdGhpcy5tdWx0aXBsZVZhbHVlcy5zZXQoW10pO1xuICAgICAgICB0aGlzLnBlbmRpbmdSYW5nZVN0YXJ0LnNldChudWxsKTtcbiAgICAgICAgdGhpcy5pbnB1dERhdGUgPSAnJztcbiAgICAgICAgdGhpcy5fb25DaGFuZ2UobnVsbCk7XG4gICAgICAgIHRoaXMuY2xlYXJDbGljay5lbWl0KGV2ZW50KTtcbiAgICAgICAgdGhpcy5jbG9zZVBhbmVsKCk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGNvbmZpcm0oKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnQgPSB0aGlzLnZhbHVlKCkgPz8gbmV3IERhdGUoKTtcbiAgICAgICAgY29uc3QgY29uZmlybWVkID0gbmV3IERhdGUoXG4gICAgICAgICAgICBjdXJyZW50LmdldEZ1bGxZZWFyKCksXG4gICAgICAgICAgICBjdXJyZW50LmdldE1vbnRoKCksXG4gICAgICAgICAgICBjdXJyZW50LmdldERhdGUoKSxcbiAgICAgICAgICAgIHRoaXMuaG91cnMoKSxcbiAgICAgICAgICAgIHRoaXMubWludXRlcygpLFxuICAgICAgICAgICAgdGhpcy5zaG93U2Vjb25kcygpID8gdGhpcy5zZWNvbmRzKCkgOiAwLFxuICAgICAgICApO1xuICAgICAgICB0aGlzLnZhbHVlLnNldChjb25maXJtZWQpO1xuICAgICAgICB0aGlzLmlucHV0RGF0ZSA9IHRoaXMuZm9ybWF0Rm9yRGlzcGxheShjb25maXJtZWQpO1xuICAgICAgICB0aGlzLl9vbkNoYW5nZShjb25maXJtZWQpO1xuICAgICAgICB0aGlzLnNlbGVjdGVkLmVtaXQoY29uZmlybWVkKTtcbiAgICAgICAgdGhpcy5jbG9zZVBhbmVsKCk7XG4gICAgfVxuXG4gICAgLy8g4pSA4pSAIFRpbWUgcGlja2VyIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gICAgcHJvdGVjdGVkIGluY3JlbWVudEhvdXJzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmhvdXJzLnNldCgodGhpcy5ob3VycygpICsgdGhpcy5zdGVwSG91cigpKSAlIHRoaXMubWF4SG91cnMpO1xuICAgICAgICB0aGlzLnN5bmNUaW1lVG9WYWx1ZSgpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBkZWNyZW1lbnRIb3VycygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5ob3Vycy5zZXQoKHRoaXMuaG91cnMoKSAtIHRoaXMuc3RlcEhvdXIoKSArIHRoaXMubWF4SG91cnMpICUgdGhpcy5tYXhIb3Vycyk7XG4gICAgICAgIHRoaXMuc3luY1RpbWVUb1ZhbHVlKCk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGluY3JlbWVudE1pbnV0ZXMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMubWludXRlcy5zZXQoKHRoaXMubWludXRlcygpICsgdGhpcy5taW51dGVTdGVwKCkpICUgdGhpcy5tYXhNaW51dGVzKTtcbiAgICAgICAgdGhpcy5zeW5jVGltZVRvVmFsdWUoKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZGVjcmVtZW50TWludXRlcygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5taW51dGVzLnNldCgodGhpcy5taW51dGVzKCkgLSB0aGlzLm1pbnV0ZVN0ZXAoKSArIHRoaXMubWF4TWludXRlcykgJSB0aGlzLm1heE1pbnV0ZXMpO1xuICAgICAgICB0aGlzLnN5bmNUaW1lVG9WYWx1ZSgpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBpbmNyZW1lbnRTZWNvbmRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNlY29uZHMuc2V0KCh0aGlzLnNlY29uZHMoKSArIHRoaXMuc3RlcFNlY29uZCgpKSAlIDYwKTtcbiAgICAgICAgdGhpcy5zeW5jVGltZVRvVmFsdWUoKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZGVjcmVtZW50U2Vjb25kcygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZWNvbmRzLnNldCgodGhpcy5zZWNvbmRzKCkgLSB0aGlzLnN0ZXBTZWNvbmQoKSArIDYwKSAlIDYwKTtcbiAgICAgICAgdGhpcy5zeW5jVGltZVRvVmFsdWUoKTtcbiAgICB9XG5cbiAgICBAbnVtZXJpY0tleXNPbmx5KClcbiAgICBwcm90ZWN0ZWQgaGFuZGxlSG91cnNLZXlkb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgICAgIGlmIChldmVudC5rZXkgPT09ICdBcnJvd1VwJykge1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHRoaXMuaW5jcmVtZW50SG91cnMoKTtcbiAgICAgICAgfSBlbHNlIGlmIChldmVudC5rZXkgPT09ICdBcnJvd0Rvd24nKSB7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgdGhpcy5kZWNyZW1lbnRIb3VycygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgQG51bWVyaWNLZXlzT25seSgpXG4gICAgcHJvdGVjdGVkIGhhbmRsZU1pbnV0ZXNLZXlkb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgICAgIGlmIChldmVudC5rZXkgPT09ICdBcnJvd1VwJykge1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHRoaXMuaW5jcmVtZW50TWludXRlcygpO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50LmtleSA9PT0gJ0Fycm93RG93bicpIHtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICB0aGlzLmRlY3JlbWVudE1pbnV0ZXMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIEBudW1lcmljS2V5c09ubHkoKVxuICAgIHByb3RlY3RlZCBoYW5kbGVTZWNvbmRzS2V5ZG93bihldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgICAgICBpZiAoZXZlbnQua2V5ID09PSAnQXJyb3dVcCcpIHtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICB0aGlzLmluY3JlbWVudFNlY29uZHMoKTtcbiAgICAgICAgfSBlbHNlIGlmIChldmVudC5rZXkgPT09ICdBcnJvd0Rvd24nKSB7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgdGhpcy5kZWNyZW1lbnRTZWNvbmRzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgaGFuZGxlSG91cnNJbnB1dChldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgcmF3ID0gKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZTtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2VJbnQocmF3LCAxMCk7XG4gICAgICAgIGlmIChpc05hTihwYXJzZWQpKSByZXR1cm47XG4gICAgICAgIGlmICh0aGlzLmlzMTJIb3VyRm9ybWF0KCkpIHtcbiAgICAgICAgICAgIGNvbnN0IGhhbGYgPSBEYXRlcGlja2VyQ29tcG9uZW50LkhPVVJTX1BFUl9NRVJJRElFTTtcbiAgICAgICAgICAgIGNvbnN0IGgxMiA9IE1hdGgubWluKGhhbGYsIE1hdGgubWF4KDEsIHBhcnNlZCkpO1xuICAgICAgICAgICAgY29uc3QgYmFzZSA9IGgxMiAlIGhhbGY7XG4gICAgICAgICAgICB0aGlzLmhvdXJzLnNldCh0aGlzLmFtUG0oKSA9PT0gJ1BNJyA/IGJhc2UgKyBoYWxmIDogYmFzZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmhvdXJzLnNldChNYXRoLm1pbih0aGlzLm1heEhvdXJzIC0gMSwgTWF0aC5tYXgoMCwgcGFyc2VkKSkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc3luY1RpbWVUb1ZhbHVlKCk7XG4gICAgfVxuXG4gICAgLyoqIEFsdGVybmEgZW50cmUgQU0gZSBQTSBzb21hbmRvL3N1YnRyYWluZG8gMTIgaG9yYXMgZGEgaG9yYSBpbnRlcm5hLiAqL1xuICAgIHByb3RlY3RlZCB0b2dnbGVBbVBtKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBoYWxmID0gRGF0ZXBpY2tlckNvbXBvbmVudC5IT1VSU19QRVJfTUVSSURJRU07XG4gICAgICAgIHRoaXMuaG91cnMuc2V0KHRoaXMuaG91cnMoKSA8IGhhbGYgPyB0aGlzLmhvdXJzKCkgKyBoYWxmIDogdGhpcy5ob3VycygpIC0gaGFsZik7XG4gICAgICAgIHRoaXMuc3luY1RpbWVUb1ZhbHVlKCk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGhhbmRsZU1pbnV0ZXNJbnB1dChldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgcmF3ID0gKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZTtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2VJbnQocmF3LCAxMCk7XG4gICAgICAgIGlmICghaXNOYU4ocGFyc2VkKSkge1xuICAgICAgICAgICAgdGhpcy5taW51dGVzLnNldChNYXRoLm1pbih0aGlzLm1heE1pbnV0ZXMgLSAxLCBNYXRoLm1heCgwLCBwYXJzZWQpKSk7XG4gICAgICAgICAgICB0aGlzLnN5bmNUaW1lVG9WYWx1ZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGhhbmRsZVNlY29uZHNJbnB1dChldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgcmF3ID0gKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZTtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2VJbnQocmF3LCAxMCk7XG4gICAgICAgIGlmICghaXNOYU4ocGFyc2VkKSkge1xuICAgICAgICAgICAgdGhpcy5zZWNvbmRzLnNldChNYXRoLm1pbig1OSwgTWF0aC5tYXgoMCwgcGFyc2VkKSkpO1xuICAgICAgICAgICAgdGhpcy5zeW5jVGltZVRvVmFsdWUoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBvbkRheUhvdmVyKGRhdGU6IERhdGUgfCBudWxsKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLm1vZGUoKSA9PT0gJ3JhbmdlJykge1xuICAgICAgICAgICAgdGhpcy5ob3ZlckRhdGUuc2V0KGRhdGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8g4pSA4pSAIEhlbHBlcnMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgICBwcm90ZWN0ZWQgaXNEYXRlRGlzYWJsZWQoZGF0ZTogRGF0ZSk6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCBtaW4gPSB0aGlzLm1pbigpO1xuICAgICAgICBjb25zdCBtYXggPSB0aGlzLm1heCgpO1xuICAgICAgICBpZiAobWluICYmIHN0cmlwVGltZShkYXRlKSA8IHN0cmlwVGltZShtaW4pKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgaWYgKG1heCAmJiBzdHJpcFRpbWUoZGF0ZSkgPiBzdHJpcFRpbWUobWF4KSkgcmV0dXJuIHRydWU7XG4gICAgICAgIGNvbnN0IGRpc2FibGVkRGF5cyA9IHRoaXMuZGlzYWJsZWREYXlzKCk7XG4gICAgICAgIGlmIChkaXNhYmxlZERheXMubGVuZ3RoICYmIGRpc2FibGVkRGF5cy5pbmNsdWRlcyhkYXRlLmdldERheSgpKSkgcmV0dXJuIHRydWU7XG4gICAgICAgIGNvbnN0IGRpc2FibGVkRGF0ZXMgPSB0aGlzLmRpc2FibGVkRGF0ZXMoKTtcbiAgICAgICAgaWYgKGRpc2FibGVkRGF0ZXMubGVuZ3RoICYmIGRpc2FibGVkRGF0ZXMuc29tZShkID0+IGlzU2FtZURheShkLCBkYXRlKSkpIHJldHVybiB0cnVlO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGlzWWVhclNlbGVjdGVkKHllYXI6IG51bWJlcik6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCBzZWxlY3RlZCA9IHRoaXMudmFsdWUoKTtcbiAgICAgICAgcmV0dXJuICEhc2VsZWN0ZWQgJiYgc2VsZWN0ZWQuZ2V0RnVsbFllYXIoKSA9PT0geWVhcjtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgaXNZZWFyRGlzYWJsZWQoeWVhcjogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IG1pbiA9IHRoaXMubWluKCk7XG4gICAgICAgIGNvbnN0IG1heCA9IHRoaXMubWF4KCk7XG4gICAgICAgIGlmIChtaW4gJiYgeWVhciA8IG1pbi5nZXRGdWxsWWVhcigpKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgaWYgKG1heCAmJiB5ZWFyID4gbWF4LmdldEZ1bGxZZWFyKCkpIHJldHVybiB0cnVlO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGlzQ3VycmVudFllYXIoeWVhcjogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB5ZWFyID09PSBuZXcgRGF0ZSgpLmdldEZ1bGxZZWFyKCk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGlzTW9udGhTZWxlY3RlZChtb250aEluZGV4OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICAgICAgY29uc3Qgc2VsZWN0ZWQgPSB0aGlzLnZhbHVlKCk7XG4gICAgICAgIHJldHVybiAhIXNlbGVjdGVkICYmIHNlbGVjdGVkLmdldE1vbnRoKCkgPT09IG1vbnRoSW5kZXggJiYgc2VsZWN0ZWQuZ2V0RnVsbFllYXIoKSA9PT0gdGhpcy5jdXJyZW50WWVhcigpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBpc01vbnRoRGlzYWJsZWQobW9udGhJbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IHllYXIgPSB0aGlzLmN1cnJlbnRZZWFyKCk7XG4gICAgICAgIGNvbnN0IG1pbiA9IHRoaXMubWluKCk7XG4gICAgICAgIGNvbnN0IG1heCA9IHRoaXMubWF4KCk7XG4gICAgICAgIGlmIChtaW4gJiYgKHllYXIgPCBtaW4uZ2V0RnVsbFllYXIoKSB8fCAoeWVhciA9PT0gbWluLmdldEZ1bGxZZWFyKCkgJiYgbW9udGhJbmRleCA8IG1pbi5nZXRNb250aCgpKSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtYXggJiYgKHllYXIgPiBtYXguZ2V0RnVsbFllYXIoKSB8fCAoeWVhciA9PT0gbWF4LmdldEZ1bGxZZWFyKCkgJiYgbW9udGhJbmRleCA+IG1heC5nZXRNb250aCgpKSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgcGFkVGltZSh2YWx1ZTogbnVtYmVyKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIFN0cmluZyh2YWx1ZSkucGFkU3RhcnQoMiwgJzAnKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZm9ybWF0RGF5QXJpYUxhYmVsKGRhdGU6IERhdGUpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gZGF0ZS50b0xvY2FsZURhdGVTdHJpbmcodW5kZWZpbmVkLCB7XG4gICAgICAgICAgICB3ZWVrZGF5OiAnbG9uZycsXG4gICAgICAgICAgICB5ZWFyOiAnbnVtZXJpYycsXG4gICAgICAgICAgICBtb250aDogJ2xvbmcnLFxuICAgICAgICAgICAgZGF5OiAnbnVtZXJpYycsXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKiBGb3JtYXRhIG8gdmFsb3IgcGFyYSBleGliacOnw6NvIG5vIGlucHV0LCBhcGxpY2FuZG8gcmFuZ2VTZXBhcmF0b3IsIGRhdGVGb3JtYXQgZSBtdWx0aXBsZVNlcGFyYXRvci4gKi9cbiAgICBwcml2YXRlIGZvcm1hdEZvckRpc3BsYXkodmFsdWU6IERhdGUgfCBEYXRlUmFuZ2UgfCBEYXRlW10gfCBudWxsKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIGZvcm1hdFZhbHVlRm9ySW5wdXQoXG4gICAgICAgICAgICB0aGlzLm1vZGUoKSxcbiAgICAgICAgICAgIHZhbHVlLFxuICAgICAgICAgICAgdGhpcy5yYW5nZVNlcGFyYXRvcigpLFxuICAgICAgICAgICAgdGhpcy5kYXRlRm9ybWF0KCksXG4gICAgICAgICAgICB0aGlzLm11bHRpcGxlU2VwYXJhdG9yKCksXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzeW5jVGltZVRvVmFsdWUoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGRhdGUgPSB0aGlzLnZhbHVlKCkgPz8gbmV3IERhdGUoKTtcbiAgICAgICAgY29uc3QgbmV3RGF0ZSA9IG5ldyBEYXRlKFxuICAgICAgICAgICAgZGF0ZS5nZXRGdWxsWWVhcigpLFxuICAgICAgICAgICAgZGF0ZS5nZXRNb250aCgpLFxuICAgICAgICAgICAgZGF0ZS5nZXREYXRlKCksXG4gICAgICAgICAgICB0aGlzLmhvdXJzKCksXG4gICAgICAgICAgICB0aGlzLm1pbnV0ZXMoKSxcbiAgICAgICAgICAgIHRoaXMuc2hvd1NlY29uZHMoKSA/IHRoaXMuc2Vjb25kcygpIDogMCxcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy52YWx1ZS5zZXQobmV3RGF0ZSk7XG4gICAgICAgIHRoaXMuaW5wdXREYXRlID0gdGhpcy5mb3JtYXRGb3JEaXNwbGF5KG5ld0RhdGUpO1xuICAgICAgICBpZiAodGhpcy5tb2RlKCkgPT09ICd0aW1lJykge1xuICAgICAgICAgICAgdGhpcy5fb25DaGFuZ2UobmV3RGF0ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGJ1aWxkQ2FsZW5kYXJEYXkoXG4gICAgICAgIGRhdGU6IERhdGUsXG4gICAgICAgIGlzQ3VycmVudE1vbnRoOiBib29sZWFuLFxuICAgICAgICB0b2RheTogRGF0ZSxcbiAgICAgICAgc2VsZWN0ZWQ6IERhdGUgfCBudWxsLFxuICAgICAgICByYW5nZTogeyBzdGFydDogRGF0ZSB8IG51bGw7IGVuZDogRGF0ZSB8IG51bGwgfSxcbiAgICAgICAgcmFuZ2VTdGFydFRpbWU6IG51bWJlciB8IG51bGwsXG4gICAgICAgIHJhbmdlRW5kVGltZTogbnVtYmVyIHwgbnVsbCxcbiAgICApOiBDYWxlbmRhckRheSB7XG4gICAgICAgIGNvbnN0IGlzUmFuZ2VTdGFydCA9IHJhbmdlLnN0YXJ0ID8gaXNTYW1lRGF5KGRhdGUsIHJhbmdlLnN0YXJ0KSA6IGZhbHNlO1xuICAgICAgICBjb25zdCBpc1JhbmdlRW5kID0gcmFuZ2UuZW5kID8gaXNTYW1lRGF5KGRhdGUsIHJhbmdlLmVuZCkgOiBmYWxzZTtcbiAgICAgICAgY29uc3QgZGF0ZVRpbWUgPSBzdHJpcFRpbWUoZGF0ZSk7XG4gICAgICAgIGNvbnN0IGlzSW5SYW5nZSA9XG4gICAgICAgICAgICByYW5nZVN0YXJ0VGltZSAhPT0gbnVsbCAmJiByYW5nZUVuZFRpbWUgIT09IG51bGxcbiAgICAgICAgICAgICAgICA/IGRhdGVUaW1lID4gcmFuZ2VTdGFydFRpbWUgJiYgZGF0ZVRpbWUgPCByYW5nZUVuZFRpbWVcbiAgICAgICAgICAgICAgICA6IGZhbHNlO1xuICAgICAgICBjb25zdCBpc1NlbGVjdGVkID0gdGhpcy5pc011bHRpcGxlTW9kZSgpXG4gICAgICAgICAgICA/IHRoaXMubXVsdGlwbGVWYWx1ZXMoKS5zb21lKChkKSA9PiBpc1NhbWVEYXkoZCwgZGF0ZSkpXG4gICAgICAgICAgICA6IHNlbGVjdGVkXG4gICAgICAgICAgICAgID8gaXNTYW1lRGF5KGRhdGUsIHNlbGVjdGVkKVxuICAgICAgICAgICAgICA6IGZhbHNlO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZGF5T2ZNb250aDogZGF0ZS5nZXREYXRlKCksXG4gICAgICAgICAgICBpc1RvZGF5OiBpc1NhbWVEYXkoZGF0ZSwgdG9kYXkpLFxuICAgICAgICAgICAgaXNTZWxlY3RlZCxcbiAgICAgICAgICAgIGlzRGlzYWJsZWQ6IHRoaXMuaXNEYXRlRGlzYWJsZWQoZGF0ZSkgfHwgKCFpc0N1cnJlbnRNb250aCAmJiAhdGhpcy5zZWxlY3RPdGhlck1vbnRocygpKSxcbiAgICAgICAgICAgIGRhdGUsXG4gICAgICAgICAgICBpc0N1cnJlbnRNb250aCxcbiAgICAgICAgICAgIGlzUmFuZ2VTdGFydCxcbiAgICAgICAgICAgIGlzUmFuZ2VFbmQsXG4gICAgICAgICAgICBpc0luUmFuZ2UsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjb21wdXRlVmFsaWRhdGlvbkVycm9ycyh2YWx1ZTogRGF0ZXBpY2tlclZhbHVlLCBjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiBWYWxpZGF0aW9uRXJyb3JzIHwgbnVsbCB7XG4gICAgICAgIGlmICh0aGlzLl9oYXNGb3JtYXRFcnJvcikgcmV0dXJuIHsgaW52YWxpZEZvcm1hdDogdHJ1ZSB9O1xuICAgICAgICBpZiAodGhpcy5faXNCYWRJbnB1dCkgcmV0dXJuIHsgYmFkSW5wdXQ6IHRydWUgfTtcbiAgICAgICAgaWYgKCF2YWx1ZSB8fCAoQXJyYXkuaXNBcnJheSh2YWx1ZSkgJiYgdmFsdWUubGVuZ3RoID09PSAwKSkgcmV0dXJuIFZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcihjb250cm9sKTtcbiAgICAgICAgY29uc3QgbWluID0gdGhpcy5taW4oKTtcbiAgICAgICAgY29uc3QgbWF4ID0gdGhpcy5tYXgoKTtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGQgb2YgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAobWluICYmIHN0cmlwVGltZShkKSA8IHN0cmlwVGltZShtaW4pKSByZXR1cm4geyBtaW46IHsgbWluLCBhY3R1YWw6IGQgfSB9O1xuICAgICAgICAgICAgICAgIGlmIChtYXggJiYgc3RyaXBUaW1lKGQpID4gc3RyaXBUaW1lKG1heCkpIHJldHVybiB7IG1heDogeyBtYXgsIGFjdHVhbDogZCB9IH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gVmFsaWRhdG9ycy5udWxsVmFsaWRhdG9yKGNvbnRyb2wpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmlzRGF0ZVJhbmdlKHZhbHVlKSkge1xuICAgICAgICAgICAgaWYgKHZhbHVlLnN0YXJ0ICYmIG1pbiAmJiBzdHJpcFRpbWUodmFsdWUuc3RhcnQpIDwgc3RyaXBUaW1lKG1pbikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geyBtaW46IHsgbWluLCBhY3R1YWw6IHZhbHVlLnN0YXJ0IH0gfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh2YWx1ZS5lbmQgJiYgbWF4ICYmIHN0cmlwVGltZSh2YWx1ZS5lbmQpID4gc3RyaXBUaW1lKG1heCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geyBtYXg6IHsgbWF4LCBhY3R1YWw6IHZhbHVlLmVuZCB9IH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gVmFsaWRhdG9ycy5udWxsVmFsaWRhdG9yKGNvbnRyb2wpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGQgPSB2YWx1ZSBhcyBEYXRlO1xuICAgICAgICBpZiAodGhpcy5tb2RlKCkgPT09ICd5ZWFyJykge1xuICAgICAgICAgICAgaWYgKG1pbiAmJiBkLmdldEZ1bGxZZWFyKCkgPCBtaW4uZ2V0RnVsbFllYXIoKSkgcmV0dXJuIHsgbWluOiB7IG1pbiwgYWN0dWFsOiBkIH0gfTtcbiAgICAgICAgICAgIGlmIChtYXggJiYgZC5nZXRGdWxsWWVhcigpID4gbWF4LmdldEZ1bGxZZWFyKCkpIHJldHVybiB7IG1heDogeyBtYXgsIGFjdHVhbDogZCB9IH07XG4gICAgICAgICAgICByZXR1cm4gVmFsaWRhdG9ycy5udWxsVmFsaWRhdG9yKGNvbnRyb2wpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtaW4gJiYgc3RyaXBUaW1lKGQpIDwgc3RyaXBUaW1lKG1pbikpIHJldHVybiB7IG1pbjogeyBtaW4sIGFjdHVhbDogZCB9IH07XG4gICAgICAgIGlmIChtYXggJiYgc3RyaXBUaW1lKGQpID4gc3RyaXBUaW1lKG1heCkpIHJldHVybiB7IG1heDogeyBtYXgsIGFjdHVhbDogZCB9IH07XG4gICAgICAgIHJldHVybiBWYWxpZGF0b3JzLm51bGxWYWxpZGF0b3IoY29udHJvbCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpc0RhdGVSYW5nZSh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIERhdGVSYW5nZSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlICE9PSBudWxsICYmICdzdGFydCcgaW4gdmFsdWUgJiYgJ2VuZCcgaW4gdmFsdWU7XG4gICAgfVxufVxuXG4iLCI8ZGl2XG4gICAgY2RrT3ZlcmxheU9yaWdpblxuICAgICN0cmlnZ2VyPVwiY2RrT3ZlcmxheU9yaWdpblwiXG4gICAgY2xhc3M9XCJyZWxhdGl2ZSBmbGV4IHctZnVsbCBpdGVtcy1jZW50ZXJcIlxuICAgIHJvbGU9XCJjb21ib2JveFwiXG4gICAgYXJpYS1oYXNwb3B1cD1cImdyaWRcIlxuICAgIFthdHRyLmFyaWEtZXhwYW5kZWRdPVwiaXNPcGVuKClcIlxuICAgIFthdHRyLmFyaWEtY29udHJvbHNdPVwicG9wdXBJZCgpXCJcbj5cbiAgICA8aW5wdXRcbiAgICAgICAgY2xhc3M9XCJoaWRlLW5hdGl2ZS1pY29uIGgtWzM1cHhdIHctZnVsbCByb3VuZGVkLXNtYWxsIGJvcmRlciBib3JkZXItc29saWQgYm9yZGVyLWdyYXlzY2FsZS0zMCBwbC0zIHRleHQtc20gb3V0bGluZS1ub25lIHRyYW5zaXRpb24tY29sb3JzIGZvY3VzOmJvcmRlci1wcmltYXJ5IGZvY3VzOm91dGxpbmUtMSBmb2N1czpvdXRsaW5lLXByaW1hcnlcIlxuICAgICAgICBbY2xhc3MucHItMTBdPVwic2hvd0ljb24oKSAmJiAhc2hvd0NsZWFyKClcIlxuICAgICAgICBbY2xhc3MucHItMTZdPVwic2hvd0ljb24oKSAmJiBzaG93Q2xlYXIoKVwiXG4gICAgICAgIFtjbGFzcy5wci02XT1cIiFzaG93SWNvbigpICYmIHNob3dDbGVhcigpXCJcbiAgICAgICAgW2NsYXNzLmJnLWdyYXlzY2FsZS0wXT1cIiFkaXNhYmxlZCgpXCJcbiAgICAgICAgW2NsYXNzLnRleHQtZ3JheXNjYWxlLTkwXT1cIiFkaXNhYmxlZCgpXCJcbiAgICAgICAgW2NsYXNzLmJvcmRlci1ncmF5c2NhbGUtMjBdPVwiZGlzYWJsZWQoKVwiXG4gICAgICAgIFtjbGFzcy5iZy1ncmF5c2NhbGUtNV09XCJkaXNhYmxlZCgpXCJcbiAgICAgICAgW2NsYXNzLnRleHQtZ3JheXNjYWxlLTMwXT1cImRpc2FibGVkKClcIlxuICAgICAgICBbY2xhc3MuY3Vyc29yLW5vdC1hbGxvd2VkXT1cImRpc2FibGVkKClcIlxuICAgICAgICBbaWRdPVwiaW5wdXRJZCgpXCJcbiAgICAgICAgW25hbWVdPVwibmFtZSgpID8/IGlucHV0SWQoKVwiXG4gICAgICAgIFt0eXBlXT1cImlucHV0VHlwZSgpXCJcbiAgICAgICAgW3BsYWNlaG9sZGVyXT1cInBsYWNlaG9sZGVyKCkgPz8gKHBsYWNlaG9sZGVyS2V5KCkgfCB0cmFuc2xhdGUpXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkKClcIlxuICAgICAgICBbcmVhZG9ubHldPVwicmVhZG9ubHlJbnB1dCgpIHx8IG1vZGUoKSA9PT0gJ3JhbmdlJyB8fCBtb2RlKCkgPT09ICd5ZWFyJyB8fCBpc011bHRpcGxlTW9kZSgpXCJcbiAgICAgICAgW3RhYkluZGV4XT1cInRhYmluZGV4KCkgPz8gbnVsbFwiXG4gICAgICAgIFthdXRvZm9jdXNdPVwiYXV0b2ZvY3VzKClcIlxuICAgICAgICBbKG5nTW9kZWwpXT1cImlucHV0RGF0ZVwiXG4gICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cImhhbmRsZUlucHV0Q2hhbmdlKCRldmVudClcIlxuICAgICAgICAoZm9jdXMpPVwiaGFuZGxlSW5wdXRGb2N1cygkZXZlbnQpXCJcbiAgICAgICAgKGJsdXIpPVwiaGFuZGxlSW5wdXRCbHVyKCRldmVudClcIlxuICAgICAgICAoY2xpY2spPVwiaGFuZGxlSW5wdXRDbGljaygpXCJcbiAgICAgICAgKGtleWRvd24pPVwiaGFuZGxlVHJpZ2dlcktleWRvd24oJGV2ZW50KVwiXG4gICAgICAgIChpbnB1dCk9XCJoYW5kbGVOYXRpdmVJbnB1dCgkZXZlbnQpXCJcbiAgICAgICAgW2F0dHIuYXJpYS1pbnZhbGlkXT1cIm5nQ29udHJvbD8uY29udHJvbD8uaW52YWxpZCB8fCBudWxsXCJcbiAgICAvPlxuXG4gICAgQGlmIChzaG93Q2xlYXIoKSAmJiBpbnB1dERhdGUpIHtcbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICBjbGFzcz1cImFic29sdXRlIGZsZXggaC1bMzVweF0gdy02IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciB0ZXh0LWdyYXlzY2FsZS02MCB0cmFuc2l0aW9uLWNvbG9ycyBob3Zlcjp0ZXh0LWdyYXlzY2FsZS05MFwiXG4gICAgICAgICAgICBbY2xhc3MucmlnaHQtOV09XCJzaG93SWNvbigpXCJcbiAgICAgICAgICAgIFtjbGFzcy5yaWdodC0wXT1cIiFzaG93SWNvbigpXCJcbiAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX2NsZWFyJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAoY2xpY2spPVwiY2xlYXJWYWx1ZSgkZXZlbnQpXCJcbiAgICAgICAgPlxuICAgICAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtdGltZXMgdGV4dC14c1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgICAgPC9idXR0b24+XG4gICAgfVxuXG4gICAgQGlmIChzaG93SWNvbigpKSB7XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICNpY29uQnV0dG9uXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIGNsYXNzPVwiYWJzb2x1dGUgcmlnaHQtMCBmbGV4IGgtWzM1cHhdIHctOSBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgYm9yZGVyLWwgYm9yZGVyLXNvbGlkIHRyYW5zaXRpb24tY29sb3JzXCJcbiAgICAgICAgICAgIFtjbGFzcy5ib3JkZXItZ3JheXNjYWxlLTIwXT1cImRpc2FibGVkKClcIlxuICAgICAgICAgICAgW2NsYXNzLnRleHQtZ3JheXNjYWxlLTMwXT1cImRpc2FibGVkKClcIlxuICAgICAgICAgICAgW2NsYXNzLmN1cnNvci1ub3QtYWxsb3dlZF09XCJkaXNhYmxlZCgpXCJcbiAgICAgICAgICAgIFtjbGFzcy5ib3JkZXItZ3JheXNjYWxlLTMwXT1cIiFkaXNhYmxlZCgpXCJcbiAgICAgICAgICAgIFtjbGFzcy50ZXh0LWdyYXlzY2FsZS05MF09XCIhZGlzYWJsZWQoKVwiXG4gICAgICAgICAgICBbY2xhc3MuaG92ZXI6YmctZ3JheXNjYWxlLTEwXT1cIiFkaXNhYmxlZCgpXCJcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZCgpXCJcbiAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX29wZW4nIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgIChjbGljayk9XCJ0b2dnbGUoKVwiXG4gICAgICAgICAgICAoa2V5ZG93bik9XCJoYW5kbGVUcmlnZ2VyS2V5ZG93bigkZXZlbnQpXCJcbiAgICAgICAgPlxuICAgICAgICAgICAgPGkgW2NsYXNzXT1cInJlc29sdmVkSWNvbigpXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICB9XG48L2Rpdj5cblxuPG5nLXRlbXBsYXRlXG4gICAgY2RrQ29ubmVjdGVkT3ZlcmxheVxuICAgIFtjZGtDb25uZWN0ZWRPdmVybGF5T3JpZ2luXT1cInRyaWdnZXJcIlxuICAgIFtjZGtDb25uZWN0ZWRPdmVybGF5T3Blbl09XCJpc09wZW4oKVwiXG4gICAgW2Nka0Nvbm5lY3RlZE92ZXJsYXlIYXNCYWNrZHJvcF09XCJ0cnVlXCJcbiAgICBjZGtDb25uZWN0ZWRPdmVybGF5QmFja2Ryb3BDbGFzcz1cImNkay1vdmVybGF5LXRyYW5zcGFyZW50LWJhY2tkcm9wXCJcbiAgICBbY2RrQ29ubmVjdGVkT3ZlcmxheVBvc2l0aW9uc109XCJwb3NpdGlvbnNcIlxuICAgIChiYWNrZHJvcENsaWNrKT1cImNsb3NlUGFuZWwoKVwiXG4gICAgKG92ZXJsYXlLZXlkb3duKT1cImhhbmRsZU92ZXJsYXlLZXlkb3duKCRldmVudClcIlxuICAgIChkZXRhY2gpPVwiaXNPcGVuLnNldChmYWxzZSlcIlxuPlxuICAgIDxkaXZcbiAgICAgICAgI3BvcHVwUGFuZWxcbiAgICAgICAgY2xhc3M9XCJ6LTUwIHctNzIgcm91bmRlZC1tZWRpdW0gYm9yZGVyIGJvcmRlci1zb2xpZCBib3JkZXItZ3JheXNjYWxlLTMwIGJnLWdyYXlzY2FsZS0wIHNoYWRvdy1tZFwiXG4gICAgICAgIHJvbGU9XCJkaWFsb2dcIlxuICAgICAgICBjZGtUcmFwRm9jdXNcbiAgICAgICAgW2lkXT1cInBvcHVwSWQoKVwiXG4gICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiZGlhbG9nQXJpYUxhYmVsS2V5KCkgfCB0cmFuc2xhdGVcIlxuICAgID5cbiAgICAgICAgQGlmIChzaG93Q2FsZW5kYXIoKSkge1xuICAgICAgICAgICAgQGlmIChwaWNrZXJWaWV3KCkgPT09ICdjYWxlbmRhcicpIHtcbiAgICAgICAgICAgICAgICA8IS0tIENhYmXDp2FsaG8gZGUgbmF2ZWdhw6fDo28gbWVuc2FsIC0tPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWJldHdlZW4gYm9yZGVyLWIgYm9yZGVyLXNvbGlkIGJvcmRlci1ncmF5c2NhbGUtMzAgcHgtMyBweS0yXCI+XG4gICAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmbGV4IGgtNyB3LTcgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIHJvdW5kZWQtc21hbGwgdGV4dC1ncmF5c2NhbGUtOTAgdHJhbnNpdGlvbi1jb2xvcnMgaG92ZXI6YmctZ3JheXNjYWxlLTEwIGRpc2FibGVkOmN1cnNvci1ub3QtYWxsb3dlZCBkaXNhYmxlZDp0ZXh0LWdyYXlzY2FsZS0zMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwicHJldkRpc2FibGVkKClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1kaXNhYmxlZF09XCJwcmV2RGlzYWJsZWQoKSA/ICd0cnVlJyA6IG51bGxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCIncGxhdGZvcm0uYW5ndWxhcl9jb21wb25lbnRzLmRhdGVwaWNrZXJfcHJldl9tb250aCcgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm5hdmlnYXRlUHJldigpXCJcbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtY2hldnJvbi1sZWZ0IHRleHQteHNcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuXG4gICAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMSByb3VuZGVkLXNtYWxsIHB4LTIgcHktMSB0ZXh0LXNtIGZvbnQtbWVkaXVtIHRleHQtZ3JheXNjYWxlLTkwIHRyYW5zaXRpb24tY29sb3JzIGhvdmVyOmJnLWdyYXlzY2FsZS0xMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidwbGF0Zm9ybS5hbmd1bGFyX2NvbXBvbmVudHMuZGF0ZXBpY2tlcl9zZWxlY3RfbW9udGhfeWVhcicgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInN3aXRjaFRvTW9udGhzKClcIlxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICB7eyBjdXJyZW50TW9udGhLZXkoKSB8IHRyYW5zbGF0ZSB9fSZuYnNwO3t7IGN1cnJlbnRZZWFyKCkgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWNoZXZyb24tZG93biB0ZXh0LVsxMHB4XVwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG5cbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZsZXggaC03IHctNyBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgcm91bmRlZC1zbWFsbCB0ZXh0LWdyYXlzY2FsZS05MCB0cmFuc2l0aW9uLWNvbG9ycyBob3ZlcjpiZy1ncmF5c2NhbGUtMTAgZGlzYWJsZWQ6Y3Vyc29yLW5vdC1hbGxvd2VkIGRpc2FibGVkOnRleHQtZ3JheXNjYWxlLTMwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJuZXh0RGlzYWJsZWQoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWRpc2FibGVkXT1cIm5leHREaXNhYmxlZCgpID8gJ3RydWUnIDogbnVsbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidwbGF0Zm9ybS5hbmd1bGFyX2NvbXBvbmVudHMuZGF0ZXBpY2tlcl9uZXh0X21vbnRoJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwibmF2aWdhdGVOZXh0KClcIlxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1jaGV2cm9uLXJpZ2h0IHRleHQteHNcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgPCEtLSBDYWJlw6dhbGhvcyBkb3MgZGlhcyBkYSBzZW1hbmEgLS0+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImdyaWQgZ3JpZC1jb2xzLTcgcHgtMyBwdC0yXCIgcm9sZT1cInJvd1wiPlxuICAgICAgICAgICAgICAgICAgICBAZm9yIChkYXlLZXkgb2Ygb3JkZXJlZFdlZWtEYXlLZXlzKCk7IHRyYWNrIGRheUtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZmxleCBoLTggaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIHRleHQteHMgZm9udC1tZWRpdW0gdGV4dC1ncmF5c2NhbGUtNjBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvbGU9XCJjb2x1bW5oZWFkZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiZGF5S2V5IHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBkYXlLZXkgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICA8IS0tIEdyYWRlIGRvIGNhbGVuZMOhcmlvIC0tPlxuICAgICAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJncmlkIGdyaWQtY29scy03IHB4LTMgcGItMlwiXG4gICAgICAgICAgICAgICAgICAgIHJvbGU9XCJncmlkXCJcbiAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCIncGxhdGZvcm0uYW5ndWxhcl9jb21wb25lbnRzLmRhdGVwaWNrZXJfY2FsZW5kYXJfbGFiZWwnIHwgdHJhbnNsYXRlOiB7IG1vbnRoOiAoY3VycmVudE1vbnRoS2V5KCkgfCB0cmFuc2xhdGUpLCB5ZWFyOiBjdXJyZW50WWVhcigpIH1cIlxuICAgICAgICAgICAgICAgICAgICAoa2V5ZG93bik9XCJoYW5kbGVDYWxlbmRhckdyaWRLZXlkb3duKCRldmVudClcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgQGZvciAod2VlayBvZiBjYWxlbmRhcldlZWtzKCk7IHRyYWNrICRpbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiByb2xlPVwicm93XCIgY2xhc3M9XCJjb250ZW50c1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBmb3IgKGRheSBvZiB3ZWVrOyB0cmFjayBkYXkuZGF0ZS50b0lTT1N0cmluZygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9sZT1cImdyaWRjZWxsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZmxleCBoLTggdy04IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciByb3VuZGVkLWZ1bGwgdGV4dC1zbSBmb250LW5vcm1hbCB0cmFuc2l0aW9uLWNvbG9yc1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbY2xhc3MuaW52aXNpYmxlXT1cIiFzaG93T3RoZXJNb250aHMoKSAmJiAhZGF5LmlzQ3VycmVudE1vbnRoXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiZm9ybWF0RGF5QXJpYUxhYmVsKGRheS5kYXRlKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLXNlbGVjdGVkXT1cImRheS5pc1NlbGVjdGVkIHx8IGRheS5pc1JhbmdlU3RhcnQgfHwgZGF5LmlzUmFuZ2VFbmQgfHwgbnVsbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWN1cnJlbnRdPVwiZGF5LmlzVG9kYXkgPyAnZGF0ZScgOiBudWxsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtZGlzYWJsZWRdPVwiZGF5LmlzRGlzYWJsZWQgPyAndHJ1ZScgOiBudWxsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtaGlkZGVuXT1cIiFzaG93T3RoZXJNb250aHMoKSAmJiAhZGF5LmlzQ3VycmVudE1vbnRoID8gJ3RydWUnIDogbnVsbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5kYXRhLWZvY3VzXT1cImRheS5pc1NlbGVjdGVkIHx8IGRheS5pc1JhbmdlU3RhcnQgfHwgZGF5LmlzUmFuZ2VFbmQgPyAnc2VsZWN0ZWQnIDogZGF5LmlzVG9kYXkgPyAndG9kYXknIDogbnVsbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGF5LmlzRGlzYWJsZWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwie1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdiZy1wcmltYXJ5IGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5c2NhbGUtMCc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRheS5pc1NlbGVjdGVkIHx8IGRheS5pc1JhbmdlU3RhcnQgfHwgZGF5LmlzUmFuZ2VFbmQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2JnLWdyYXlzY2FsZS0xMCBob3ZlcjpiZy1ncmF5c2NhbGUtMjAnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXkuaXNJblJhbmdlICYmICFkYXkuaXNSYW5nZVN0YXJ0ICYmICFkYXkuaXNSYW5nZUVuZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndGV4dC1ncmF5c2NhbGUtOTAgaG92ZXI6YmctZ3JheXNjYWxlLTEwJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIWRheS5pc1NlbGVjdGVkICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICFkYXkuaXNSYW5nZVN0YXJ0ICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICFkYXkuaXNSYW5nZUVuZCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhZGF5LmlzRGlzYWJsZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF5LmlzQ3VycmVudE1vbnRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0ZXh0LWdyYXlzY2FsZS02MCBob3ZlcjpiZy1ncmF5c2NhbGUtMTAnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhZGF5LmlzU2VsZWN0ZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIWRheS5pc1JhbmdlU3RhcnQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIWRheS5pc1JhbmdlRW5kICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICFkYXkuaXNEaXNhYmxlZCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhZGF5LmlzQ3VycmVudE1vbnRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdyaW5nLTIgcmluZy1pbnNldCByaW5nLXByaW1hcnknOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXkuaXNUb2RheSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhZGF5LmlzU2VsZWN0ZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIWRheS5pc1JhbmdlU3RhcnQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIWRheS5pc1JhbmdlRW5kLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjdXJzb3Itbm90LWFsbG93ZWQgdGV4dC1ncmF5c2NhbGUtMzAnOiBkYXkuaXNEaXNhYmxlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAobW91c2VlbnRlcik9XCJvbkRheUhvdmVyKGRheS5kYXRlKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAobW91c2VsZWF2ZSk9XCJvbkRheUhvdmVyKG51bGwpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJzZWxlY3REYXRlKGRheSlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBkYXkuZGF5T2ZNb250aCB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBAaWYgKHBpY2tlclZpZXcoKSA9PT0gJ3llYXJzJykge1xuICAgICAgICAgICAgICAgIDwhLS0gQ2FiZcOnYWxobyBkZSBuYXZlZ2HDp8OjbyBwb3IgZMOpY2FkYSAtLT5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1iZXR3ZWVuIGJvcmRlci1iIGJvcmRlci1zb2xpZCBib3JkZXItZ3JheXNjYWxlLTMwIHB4LTMgcHktMlwiPlxuICAgICAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZmxleCBoLTcgdy03IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciByb3VuZGVkLXNtYWxsIHRleHQtZ3JheXNjYWxlLTkwIHRyYW5zaXRpb24tY29sb3JzIGhvdmVyOmJnLWdyYXlzY2FsZS0xMCBkaXNhYmxlZDpjdXJzb3Itbm90LWFsbG93ZWQgZGlzYWJsZWQ6dGV4dC1ncmF5c2NhbGUtMzBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cInByZXZEaXNhYmxlZCgpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtZGlzYWJsZWRdPVwicHJldkRpc2FibGVkKCkgPyAndHJ1ZScgOiBudWxsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX3ByZXZfZGVjYWRlJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwibmF2aWdhdGVQcmV2KClcIlxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1jaGV2cm9uLWxlZnQgdGV4dC14c1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LXNtIGZvbnQtbWVkaXVtIHRleHQtZ3JheXNjYWxlLTkwXCI+e3sgY3VycmVudERlY2FkZVN0YXJ0KCkgfX0g4oCTIHt7IGN1cnJlbnREZWNhZGVTdGFydCgpICsgMTEgfX08L3NwYW4+XG5cbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZsZXggaC03IHctNyBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgcm91bmRlZC1zbWFsbCB0ZXh0LWdyYXlzY2FsZS05MCB0cmFuc2l0aW9uLWNvbG9ycyBob3ZlcjpiZy1ncmF5c2NhbGUtMTAgZGlzYWJsZWQ6Y3Vyc29yLW5vdC1hbGxvd2VkIGRpc2FibGVkOnRleHQtZ3JheXNjYWxlLTMwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJuZXh0RGlzYWJsZWQoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWRpc2FibGVkXT1cIm5leHREaXNhYmxlZCgpID8gJ3RydWUnIDogbnVsbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidwbGF0Zm9ybS5hbmd1bGFyX2NvbXBvbmVudHMuZGF0ZXBpY2tlcl9uZXh0X2RlY2FkZScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm5hdmlnYXRlTmV4dCgpXCJcbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtY2hldnJvbi1yaWdodCB0ZXh0LXhzXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgIDwhLS0gR3JhZGUgZGUgYW5vcyAtLT5cbiAgICAgICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZ3JpZCBncmlkLWNvbHMtMyBnYXAtMiBweC0zIHB5LTNcIlxuICAgICAgICAgICAgICAgICAgICByb2xlPVwiZ3JpZFwiXG4gICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX3NlbGVjdF95ZWFyJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICBAZm9yIChyb3cgb2YgeWVhcnNHcmlkKCk7IHRyYWNrICRpbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgQGZvciAoeWVhciBvZiByb3c7IHRyYWNrIHllYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb2xlPVwiZ3JpZGNlbGxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZsZXggaC05IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciByb3VuZGVkLXNtYWxsIHRleHQtc20gZm9udC1ub3JtYWwgdHJhbnNpdGlvbi1jb2xvcnNcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLXNlbGVjdGVkXT1cImlzWWVhclNlbGVjdGVkKHllYXIpIHx8IG51bGxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWRpc2FibGVkXT1cImlzWWVhckRpc2FibGVkKHllYXIpID8gJ3RydWUnIDogbnVsbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtY3VycmVudF09XCJpc0N1cnJlbnRZZWFyKHllYXIpID8gJ2RhdGUnIDogbnVsbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmRhdGEtZm9jdXNdPVwiaXNZZWFyU2VsZWN0ZWQoeWVhcikgPyAnc2VsZWN0ZWQnIDogaXNDdXJyZW50WWVhcih5ZWFyKSA/ICd0b2RheScgOiBudWxsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImlzWWVhckRpc2FibGVkKHllYXIpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwie1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2JnLXByaW1hcnkgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXlzY2FsZS0wJzogaXNZZWFyU2VsZWN0ZWQoeWVhciksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAncmluZy0yIHJpbmctaW5zZXQgcmluZy1wcmltYXJ5JzogaXNDdXJyZW50WWVhcih5ZWFyKSAmJiAhaXNZZWFyU2VsZWN0ZWQoeWVhcikgJiYgIWlzWWVhckRpc2FibGVkKHllYXIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3RleHQtZ3JheXNjYWxlLTkwIGhvdmVyOmJnLWdyYXlzY2FsZS0xMCc6ICFpc1llYXJTZWxlY3RlZCh5ZWFyKSAmJiAhaXNZZWFyRGlzYWJsZWQoeWVhciksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY3Vyc29yLW5vdC1hbGxvd2VkIHRleHQtZ3JheXNjYWxlLTMwJzogaXNZZWFyRGlzYWJsZWQoeWVhcilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJzZWxlY3RZZWFyKHllYXIpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IHllYXIgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBAaWYgKHBpY2tlclZpZXcoKSA9PT0gJ21vbnRocycpIHtcbiAgICAgICAgICAgICAgICA8IS0tIENhYmXDp2FsaG8gZGUgbmF2ZWdhw6fDo28gYW51YWwgLS0+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIGp1c3RpZnktYmV0d2VlbiBib3JkZXItYiBib3JkZXItc29saWQgYm9yZGVyLWdyYXlzY2FsZS0zMCBweC0zIHB5LTJcIj5cbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZsZXggaC03IHctNyBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgcm91bmRlZC1zbWFsbCB0ZXh0LWdyYXlzY2FsZS05MCB0cmFuc2l0aW9uLWNvbG9ycyBob3ZlcjpiZy1ncmF5c2NhbGUtMTAgZGlzYWJsZWQ6Y3Vyc29yLW5vdC1hbGxvd2VkIGRpc2FibGVkOnRleHQtZ3JheXNjYWxlLTMwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJwcmV2RGlzYWJsZWQoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWRpc2FibGVkXT1cInByZXZEaXNhYmxlZCgpID8gJ3RydWUnIDogbnVsbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidwbGF0Zm9ybS5hbmd1bGFyX2NvbXBvbmVudHMuZGF0ZXBpY2tlcl9wcmV2X3llYXInIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJuYXZpZ2F0ZVByZXYoKVwiXG4gICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWNoZXZyb24tbGVmdCB0ZXh0LXhzXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cblxuICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtc20gZm9udC1tZWRpdW0gdGV4dC1ncmF5c2NhbGUtOTBcIj57eyBjdXJyZW50WWVhcigpIH19PC9zcGFuPlxuXG4gICAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmbGV4IGgtNyB3LTcgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIHJvdW5kZWQtc21hbGwgdGV4dC1ncmF5c2NhbGUtOTAgdHJhbnNpdGlvbi1jb2xvcnMgaG92ZXI6YmctZ3JheXNjYWxlLTEwIGRpc2FibGVkOmN1cnNvci1ub3QtYWxsb3dlZCBkaXNhYmxlZDp0ZXh0LWdyYXlzY2FsZS0zMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwibmV4dERpc2FibGVkKClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1kaXNhYmxlZF09XCJuZXh0RGlzYWJsZWQoKSA/ICd0cnVlJyA6IG51bGxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCIncGxhdGZvcm0uYW5ndWxhcl9jb21wb25lbnRzLmRhdGVwaWNrZXJfbmV4dF95ZWFyJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwibmF2aWdhdGVOZXh0KClcIlxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1jaGV2cm9uLXJpZ2h0IHRleHQteHNcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgPCEtLSBHcmFkZSBkZSBtZXNlcyAtLT5cbiAgICAgICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZ3JpZCBncmlkLWNvbHMtMyBnYXAtMiBweC0zIHB5LTNcIlxuICAgICAgICAgICAgICAgICAgICByb2xlPVwiZ3JpZFwiXG4gICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX3NlbGVjdF9tb250aCcgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgQGZvciAocm93IG9mIG1vbnRoc0dyaWQoKTsgdHJhY2sgJGluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBAZm9yIChtb250aCBvZiByb3c7IHRyYWNrIG1vbnRoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9sZT1cImdyaWRjZWxsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmbGV4IGgtOSBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgcm91bmRlZC1zbWFsbCB0ZXh0LXNtIGZvbnQtbm9ybWFsIHRyYW5zaXRpb24tY29sb3JzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1zZWxlY3RlZF09XCJpc01vbnRoU2VsZWN0ZWQobW9udGguaW5kZXgpIHx8IG51bGxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWRpc2FibGVkXT1cImlzTW9udGhEaXNhYmxlZChtb250aC5pbmRleCkgPyAndHJ1ZScgOiBudWxsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuZGF0YS1mb2N1c109XCJpc01vbnRoU2VsZWN0ZWQobW9udGguaW5kZXgpID8gJ3NlbGVjdGVkJyA6IG51bGxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiaXNNb250aERpc2FibGVkKG1vbnRoLmluZGV4KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cIntcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdiZy1wcmltYXJ5IGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5c2NhbGUtMCc6IGlzTW9udGhTZWxlY3RlZChtb250aC5pbmRleCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndGV4dC1ncmF5c2NhbGUtOTAgaG92ZXI6YmctZ3JheXNjYWxlLTEwJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhaXNNb250aFNlbGVjdGVkKG1vbnRoLmluZGV4KSAmJiAhaXNNb250aERpc2FibGVkKG1vbnRoLmluZGV4KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjdXJzb3Itbm90LWFsbG93ZWQgdGV4dC1ncmF5c2NhbGUtMzAnOiBpc01vbnRoRGlzYWJsZWQobW9udGguaW5kZXgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwic2VsZWN0TW9udGgobW9udGguaW5kZXgpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IG1vbnRoLmtleSB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICBAaWYgKG1vZGUoKSAhPT0gJ21vbnRoJykge1xuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYm9yZGVyLXQgYm9yZGVyLXNvbGlkIGJvcmRlci1ncmF5c2NhbGUtMzAgcHgtMyBweS0yXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMiByb3VuZGVkLXNtYWxsIHB4LTIgcHktMSB0ZXh0LXNtIHRleHQtZ3JheXNjYWxlLTkwIHRyYW5zaXRpb24tY29sb3JzIGhvdmVyOmJnLWdyYXlzY2FsZS0xMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImJhY2tUb0NhbGVuZGFyKClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWFycm93LWxlZnRcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX2JhY2tfdG9fY2FsZW5kYXInIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgPCEtLSBUaW1lIHBpY2tlciAtLT5cbiAgICAgICAgQGlmIChzaG93VGltZVBpY2tlcigpKSB7XG4gICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICAgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciBnYXAtMyBweC00IHB5LTNcIlxuICAgICAgICAgICAgICAgIFtjbGFzcy5ib3JkZXItdF09XCJzaG93Q2FsZW5kYXIoKVwiXG4gICAgICAgICAgICAgICAgW2NsYXNzLmJvcmRlci1zb2xpZF09XCJzaG93Q2FsZW5kYXIoKVwiXG4gICAgICAgICAgICAgICAgW2NsYXNzLmJvcmRlci1ncmF5c2NhbGUtMzBdPVwic2hvd0NhbGVuZGFyKClcIlxuICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX3NlbGVjdF90aW1lJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPCEtLSBIb3JhcyAtLT5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBmbGV4LWNvbCBpdGVtcy1jZW50ZXIgZ2FwLTFcIj5cbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgI2luY3JlYXNlSG91ckJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZsZXggaC02IHctNiBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgcm91bmRlZC1zbWFsbCB0ZXh0LWdyYXlzY2FsZS05MCB0cmFuc2l0aW9uLWNvbG9ycyBob3ZlcjpiZy1ncmF5c2NhbGUtMTBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCIncGxhdGZvcm0uYW5ndWxhcl9jb21wb25lbnRzLmRhdGVwaWNrZXJfaW5jcmVtZW50X2hvdXInIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJpbmNyZW1lbnRIb3VycygpXCJcbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtY2hldnJvbi11cCB0ZXh0LXhzXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnB1dG1vZGU9XCJudW1lcmljXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLm1heGxlbmd0aF09XCJ0aW1lSW5wdXRNYXhMZW5ndGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJoLTkgdy0xMiByb3VuZGVkLXNtYWxsIGJvcmRlciBib3JkZXItc29saWQgYm9yZGVyLWdyYXlzY2FsZS0zMCBiZy1ncmF5c2NhbGUtNSB0ZXh0LWNlbnRlciB0ZXh0LWJhc2UgZm9udC1tZWRpdW0gdGV4dC1ncmF5c2NhbGUtOTAgb3V0bGluZS1ub25lIGZvY3VzOmJvcmRlci1wcmltYXJ5IGZvY3VzOm91dGxpbmUtMSBmb2N1czpvdXRsaW5lLXByaW1hcnlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW3ZhbHVlXT1cInBhZFRpbWUoZGlzcGxheUhvdXJzKCkpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX2hvdXInIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyaWEtbGl2ZT1cInBvbGl0ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuPVwiWzAtOV0rXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIChrZXlkb3duKT1cImhhbmRsZUhvdXJzS2V5ZG93bigkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIChjaGFuZ2UpPVwiaGFuZGxlSG91cnNJbnB1dCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZsZXggaC02IHctNiBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgcm91bmRlZC1zbWFsbCB0ZXh0LWdyYXlzY2FsZS05MCB0cmFuc2l0aW9uLWNvbG9ycyBob3ZlcjpiZy1ncmF5c2NhbGUtMTBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCIncGxhdGZvcm0uYW5ndWxhcl9jb21wb25lbnRzLmRhdGVwaWNrZXJfZGVjcmVtZW50X2hvdXInIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJkZWNyZW1lbnRIb3VycygpXCJcbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtY2hldnJvbi1kb3duIHRleHQteHNcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtYm9sZCB0ZXh0LWdyYXlzY2FsZS02MFwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjo8L3NwYW4+XG5cbiAgICAgICAgICAgICAgICA8IS0tIE1pbnV0b3MgLS0+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggZmxleC1jb2wgaXRlbXMtY2VudGVyIGdhcC0xXCI+XG4gICAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmbGV4IGgtNiB3LTYgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIHJvdW5kZWQtc21hbGwgdGV4dC1ncmF5c2NhbGUtOTAgdHJhbnNpdGlvbi1jb2xvcnMgaG92ZXI6YmctZ3JheXNjYWxlLTEwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX2luY3JlbWVudF9taW51dGUnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJpbmNyZW1lbnRNaW51dGVzKClcIlxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1jaGV2cm9uLXVwIHRleHQteHNcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0bW9kZT1cIm51bWVyaWNcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIubWF4bGVuZ3RoXT1cInRpbWVJbnB1dE1heExlbmd0aFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImgtOSB3LTEyIHJvdW5kZWQtc21hbGwgYm9yZGVyIGJvcmRlci1zb2xpZCBib3JkZXItZ3JheXNjYWxlLTMwIGJnLWdyYXlzY2FsZS01IHRleHQtY2VudGVyIHRleHQtYmFzZSBmb250LW1lZGl1bSB0ZXh0LWdyYXlzY2FsZS05MCBvdXRsaW5lLW5vbmUgZm9jdXM6Ym9yZGVyLXByaW1hcnkgZm9jdXM6b3V0bGluZS0xIGZvY3VzOm91dGxpbmUtcHJpbWFyeVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbdmFsdWVdPVwicGFkVGltZShtaW51dGVzKCkpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX21pbnV0ZScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJpYS1saXZlPVwicG9saXRlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm49XCJbMC05XStcIlxuICAgICAgICAgICAgICAgICAgICAgICAgKGtleWRvd24pPVwiaGFuZGxlTWludXRlc0tleWRvd24oJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAoY2hhbmdlKT1cImhhbmRsZU1pbnV0ZXNJbnB1dCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZsZXggaC02IHctNiBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgcm91bmRlZC1zbWFsbCB0ZXh0LWdyYXlzY2FsZS05MCB0cmFuc2l0aW9uLWNvbG9ycyBob3ZlcjpiZy1ncmF5c2NhbGUtMTBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCIncGxhdGZvcm0uYW5ndWxhcl9jb21wb25lbnRzLmRhdGVwaWNrZXJfZGVjcmVtZW50X21pbnV0ZScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImRlY3JlbWVudE1pbnV0ZXMoKVwiXG4gICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWNoZXZyb24tZG93biB0ZXh0LXhzXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgIEBpZiAoc2hvd1NlY29uZHMoKSkge1xuICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQteGwgZm9udC1ib2xkIHRleHQtZ3JheXNjYWxlLTYwXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+Ojwvc3Bhbj5cblxuICAgICAgICAgICAgICAgICAgICA8IS0tIFNlZ3VuZG9zIC0tPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBmbGV4LWNvbCBpdGVtcy1jZW50ZXIgZ2FwLTFcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZsZXggaC02IHctNiBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgcm91bmRlZC1zbWFsbCB0ZXh0LWdyYXlzY2FsZS05MCB0cmFuc2l0aW9uLWNvbG9ycyBob3ZlcjpiZy1ncmF5c2NhbGUtMTBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX2luY3JlbWVudF9zZWNvbmQnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwiaW5jcmVtZW50U2Vjb25kcygpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1jaGV2cm9uLXVwIHRleHQteHNcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dG1vZGU9XCJudW1lcmljXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5tYXhsZW5ndGhdPVwidGltZUlucHV0TWF4TGVuZ3RoXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImgtOSB3LTEyIHJvdW5kZWQtc21hbGwgYm9yZGVyIGJvcmRlci1zb2xpZCBib3JkZXItZ3JheXNjYWxlLTMwIGJnLWdyYXlzY2FsZS01IHRleHQtY2VudGVyIHRleHQtYmFzZSBmb250LW1lZGl1bSB0ZXh0LWdyYXlzY2FsZS05MCBvdXRsaW5lLW5vbmUgZm9jdXM6Ym9yZGVyLXByaW1hcnkgZm9jdXM6b3V0bGluZS0xIGZvY3VzOm91dGxpbmUtcHJpbWFyeVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3ZhbHVlXT1cInBhZFRpbWUoc2Vjb25kcygpKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCIncGxhdGZvcm0uYW5ndWxhcl9jb21wb25lbnRzLmRhdGVwaWNrZXJfc2Vjb25kJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJpYS1saXZlPVwicG9saXRlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuPVwiWzAtOV0rXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoa2V5ZG93bik9XCJoYW5kbGVTZWNvbmRzS2V5ZG93bigkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2hhbmdlKT1cImhhbmRsZVNlY29uZHNJbnB1dCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmbGV4IGgtNiB3LTYgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIHJvdW5kZWQtc21hbGwgdGV4dC1ncmF5c2NhbGUtOTAgdHJhbnNpdGlvbi1jb2xvcnMgaG92ZXI6YmctZ3JheXNjYWxlLTEwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidwbGF0Zm9ybS5hbmd1bGFyX2NvbXBvbmVudHMuZGF0ZXBpY2tlcl9kZWNyZW1lbnRfc2Vjb25kJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImRlY3JlbWVudFNlY29uZHMoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtY2hldnJvbi1kb3duIHRleHQteHNcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgQGlmIChpczEySG91ckZvcm1hdCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIDwhLS0gU2VsZXRvciBBTS9QTSAtLT5cbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZsZXggaC05IHctMTIgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIHJvdW5kZWQtc21hbGwgYm9yZGVyIGJvcmRlci1zb2xpZCBib3JkZXItZ3JheXNjYWxlLTMwIGJnLWdyYXlzY2FsZS01IHRleHQtYmFzZSBmb250LW1lZGl1bSB0ZXh0LWdyYXlzY2FsZS05MCB0cmFuc2l0aW9uLWNvbG9ycyBob3ZlcjpiZy1ncmF5c2NhbGUtMTBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCIncGxhdGZvcm0uYW5ndWxhcl9jb21wb25lbnRzLmRhdGVwaWNrZXJfdG9nZ2xlX21lcmlkaWVtJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBhcmlhLWxpdmU9XCJwb2xpdGVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInRvZ2dsZUFtUG0oKVwiXG4gICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgIHt7IGFtUG0oKSB9fVxuICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgfVxuXG4gICAgICAgIDwhLS0gUm9kYXDDqSBkZSBhw6fDtWVzIC0tPlxuICAgICAgICBAaWYgKHNob3dCdXR0b25CYXIoKSB8fCBtb2RlKCkgPT09ICdkYXRldGltZScgfHwgbW9kZSgpID09PSAndGltZScpIHtcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWJldHdlZW4gYm9yZGVyLXQgYm9yZGVyLXNvbGlkIGJvcmRlci1ncmF5c2NhbGUtMzAgcHgtMyBweS0yXCI+XG4gICAgICAgICAgICAgICAgQGlmIChzaG93QnV0dG9uQmFyKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAobW9kZSgpID09PSAnZGF0ZScgfHwgbW9kZSgpID09PSAnZGF0ZXRpbWUnIHx8IG1vZGUoKSA9PT0gJ3JhbmdlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwicm91bmRlZC1zbWFsbCBweC0yIHB5LTEgdGV4dC1zbSB0ZXh0LWdyYXlzY2FsZS05MCB0cmFuc2l0aW9uLWNvbG9ycyBob3ZlcjpiZy1ncmF5c2NhbGUtMTBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwic2VsZWN0VG9kYXkoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyAncGxhdGZvcm0uYW5ndWxhcl9jb21wb25lbnRzLmRhdGVwaWNrZXJfdG9kYXknIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGdhcC0yXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJyb3VuZGVkLXNtYWxsIHB4LTIgcHktMSB0ZXh0LXNtIHRleHQtZ3JheXNjYWxlLTkwIHRyYW5zaXRpb24tY29sb3JzIGhvdmVyOmJnLWdyYXlzY2FsZS0xMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImNsZWFyVmFsdWUoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX2NsZWFyJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAobW9kZSgpID09PSAnZGF0ZXRpbWUnIHx8IG1vZGUoKSA9PT0gJ3RpbWUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJyb3VuZGVkLXNtYWxsIGJnLXByaW1hcnkgcHgtMyBweS0xIHRleHQtc20gZm9udC1tZWRpdW0gdGV4dC1ncmF5c2NhbGUtMCB0cmFuc2l0aW9uLWNvbG9ycyBob3ZlcjpvcGFjaXR5LTkwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImNvbmZpcm0oKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyAncGxhdGZvcm0uYW5ndWxhcl9jb21wb25lbnRzLmRhdGVwaWNrZXJfY29uZmlybScgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIDxkaXY+PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICBAaWYgKG1vZGUoKSA9PT0gJ2RhdGV0aW1lJyB8fCBtb2RlKCkgPT09ICd0aW1lJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwicm91bmRlZC1zbWFsbCBiZy1wcmltYXJ5IHB4LTMgcHktMSB0ZXh0LXNtIGZvbnQtbWVkaXVtIHRleHQtZ3JheXNjYWxlLTAgdHJhbnNpdGlvbi1jb2xvcnMgaG92ZXI6b3BhY2l0eS05MFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJjb25maXJtKClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgJ3BsYXRmb3JtLmFuZ3VsYXJfY29tcG9uZW50cy5kYXRlcGlja2VyX2NvbmZpcm0nIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICB9XG4gICAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuIl19
|