@fatcore/gantt-lite 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +9 -12
  2. package/fatcore-gantt-lite-1.0.0.tgz +0 -0
  3. package/fatcore-gantt-lite-1.0.2.tgz +0 -0
  4. package/{dist19/gantt-lite/fesm2022/gantt-lite.mjs → fesm2022/fatcore-gantt-lite.mjs} +13 -13
  5. package/fesm2022/fatcore-gantt-lite.mjs.map +1 -0
  6. package/{dist20/gantt-lite/fesm2022 → fesm2022}/gantt-lite.mjs +1 -1
  7. package/fesm2022/gantt-lite.mjs.map +1 -0
  8. package/gantt-lite-1.0.2.tgz +0 -0
  9. package/{dist20/gantt-lite/index.d.ts → index.d.ts} +22 -1
  10. package/package.json +16 -40
  11. package/.editorconfig +0 -16
  12. package/.vscode/extensions.json +0 -4
  13. package/.vscode/launch.json +0 -20
  14. package/.vscode/tasks.json +0 -42
  15. package/angular.json +0 -165
  16. package/dist17/gantt-lite/README.md +0 -24
  17. package/dist17/gantt-lite/esm2022/gantt-lite.mjs +0 -5
  18. package/dist17/gantt-lite/esm2022/gantt-lite.module.mjs +0 -18
  19. package/dist17/gantt-lite/esm2022/lib/gantt-lite-base.mjs +0 -290
  20. package/dist17/gantt-lite/esm2022/lib/gantt-lite.component.mjs +0 -359
  21. package/dist17/gantt-lite/esm2022/lib/gantt-lite.helper.mjs +0 -107
  22. package/dist17/gantt-lite/esm2022/lib/gantt-lite.model.mjs +0 -2
  23. package/dist17/gantt-lite/esm2022/public-api.mjs +0 -3
  24. package/dist17/gantt-lite/fesm2022/gantt-lite.mjs +0 -774
  25. package/dist17/gantt-lite/fesm2022/gantt-lite.mjs.map +0 -1
  26. package/dist17/gantt-lite/gantt-lite.module.d.ts +0 -8
  27. package/dist17/gantt-lite/index.d.ts +0 -5
  28. package/dist17/gantt-lite/lib/gantt-lite-base.d.ts +0 -50
  29. package/dist17/gantt-lite/lib/gantt-lite.component.d.ts +0 -55
  30. package/dist17/gantt-lite/lib/gantt-lite.helper.d.ts +0 -20
  31. package/dist17/gantt-lite/lib/gantt-lite.model.d.ts +0 -47
  32. package/dist17/gantt-lite/public-api.d.ts +0 -2
  33. package/dist18/gantt-lite/README.md +0 -24
  34. package/dist18/gantt-lite/esm2022/gantt-lite.mjs +0 -5
  35. package/dist18/gantt-lite/esm2022/gantt-lite.module.mjs +0 -18
  36. package/dist18/gantt-lite/esm2022/lib/gantt-lite-base.mjs +0 -290
  37. package/dist18/gantt-lite/esm2022/lib/gantt-lite.component.mjs +0 -359
  38. package/dist18/gantt-lite/esm2022/lib/gantt-lite.helper.mjs +0 -107
  39. package/dist18/gantt-lite/esm2022/lib/gantt-lite.model.mjs +0 -2
  40. package/dist18/gantt-lite/esm2022/public-api.mjs +0 -3
  41. package/dist18/gantt-lite/fesm2022/gantt-lite.mjs +0 -774
  42. package/dist18/gantt-lite/fesm2022/gantt-lite.mjs.map +0 -1
  43. package/dist18/gantt-lite/gantt-lite.module.d.ts +0 -8
  44. package/dist18/gantt-lite/index.d.ts +0 -5
  45. package/dist18/gantt-lite/lib/gantt-lite-base.d.ts +0 -50
  46. package/dist18/gantt-lite/lib/gantt-lite.component.d.ts +0 -55
  47. package/dist18/gantt-lite/lib/gantt-lite.helper.d.ts +0 -20
  48. package/dist18/gantt-lite/lib/gantt-lite.model.d.ts +0 -47
  49. package/dist18/gantt-lite/public-api.d.ts +0 -2
  50. package/dist19/gantt-lite/README.md +0 -24
  51. package/dist19/gantt-lite/fesm2022/gantt-lite.mjs.map +0 -1
  52. package/dist19/gantt-lite/gantt-lite.module.d.ts +0 -8
  53. package/dist19/gantt-lite/index.d.ts +0 -5
  54. package/dist19/gantt-lite/lib/gantt-lite-base.d.ts +0 -50
  55. package/dist19/gantt-lite/lib/gantt-lite.component.d.ts +0 -55
  56. package/dist19/gantt-lite/lib/gantt-lite.helper.d.ts +0 -20
  57. package/dist19/gantt-lite/lib/gantt-lite.model.d.ts +0 -47
  58. package/dist19/gantt-lite/public-api.d.ts +0 -2
  59. package/dist20/gantt-lite/README.md +0 -24
  60. package/dist20/gantt-lite/fesm2022/gantt-lite.mjs.map +0 -1
  61. package/my-workspace-0.0.0.tgz +0 -0
  62. package/projects/gantt-lite/README.md +0 -24
  63. package/projects/gantt-lite/ng-package.json +0 -7
  64. package/projects/gantt-lite/package.json +0 -10
  65. package/projects/gantt-lite/src/gantt-lite.module.ts +0 -10
  66. package/projects/gantt-lite/src/lib/gantt-lite-base.ts +0 -300
  67. package/projects/gantt-lite/src/lib/gantt-lite.component.html +0 -128
  68. package/projects/gantt-lite/src/lib/gantt-lite.component.scss +0 -323
  69. package/projects/gantt-lite/src/lib/gantt-lite.component.ts +0 -391
  70. package/projects/gantt-lite/src/lib/gantt-lite.helper.ts +0 -124
  71. package/projects/gantt-lite/src/lib/gantt-lite.model.ts +0 -56
  72. package/projects/gantt-lite/src/public-api.ts +0 -5
  73. package/projects/gantt-lite/tsconfig.lib.json +0 -14
  74. package/projects/gantt-lite/tsconfig.lib.prod.json +0 -10
  75. package/projects/gantt-lite/tsconfig.spec.json +0 -14
  76. package/projects/my-app/server.ts +0 -56
  77. package/projects/my-app/src/app/app.component.html +0 -336
  78. package/projects/my-app/src/app/app.component.scss +0 -0
  79. package/projects/my-app/src/app/app.component.spec.ts +0 -29
  80. package/projects/my-app/src/app/app.component.ts +0 -13
  81. package/projects/my-app/src/app/app.config.server.ts +0 -11
  82. package/projects/my-app/src/app/app.config.ts +0 -9
  83. package/projects/my-app/src/app/app.routes.ts +0 -3
  84. package/projects/my-app/src/assets/.gitkeep +0 -0
  85. package/projects/my-app/src/favicon.ico +0 -0
  86. package/projects/my-app/src/index.html +0 -13
  87. package/projects/my-app/src/main.server.ts +0 -7
  88. package/projects/my-app/src/main.ts +0 -6
  89. package/projects/my-app/src/styles.scss +0 -1
  90. package/projects/my-app/tsconfig.app.json +0 -18
  91. package/projects/my-app/tsconfig.spec.json +0 -14
  92. package/tsconfig.json +0 -37
@@ -1,359 +0,0 @@
1
- import { Component, ViewChild, Input, ChangeDetectionStrategy } from '@angular/core';
2
- import { SlotIndexToDateLabelConverter } from './gantt-lite.helper';
3
- import { GanttLiteBase } from './gantt-lite-base';
4
- import * as i0 from "@angular/core";
5
- import * as i1 from "@angular/common";
6
- export class GanttLiteComponent extends GanttLiteBase {
7
- set rawTasks(value) {
8
- this._rawTasks = value ?? [];
9
- this.recalculteAll();
10
- }
11
- get rawTasks() {
12
- return this._rawTasks;
13
- }
14
- constructor(cdr) {
15
- super();
16
- this.cdr = cdr;
17
- this.toolbarHeight = 27;
18
- this.hoveredDependencyIds = new Set();
19
- this.selectedTaskId = null;
20
- this.tooltipTask = null;
21
- this.tooltipX = 0;
22
- this.tooltipY = 0;
23
- this.maxSlotsAlert = false;
24
- this.loading = false;
25
- this.showLeftBtn = false;
26
- this.showRightBtn = true;
27
- this.buttonsHeight = 20;
28
- this.viewTasks = [];
29
- this._rawTasks = [];
30
- this.originDate = 0;
31
- this.resizing = false;
32
- this.labelConverter = null;
33
- }
34
- // recalculate all Gantt
35
- recalculteAll() {
36
- this.loading = true;
37
- this.cdr.markForCheck();
38
- setTimeout(() => {
39
- const start = performance.now();
40
- this.refreshVisibleColumns();
41
- this.scaleSelected = this.getScaleConfig(this.defaultScale);
42
- if (this.dataType !== 'duration') {
43
- const base = new Date(Math.min(...this.rawTasks.map((t) => t.start.getTime())));
44
- this.originDate = this.alignOriginByScale(base, this.defaultScale).getTime();
45
- this.labelConverter = new SlotIndexToDateLabelConverter(this.dateMode, this.originDate, this.scaleSelected.secondes, this.hasNegativeDependencySpace);
46
- this.buildTaskSlotsFromDates();
47
- }
48
- else {
49
- this.labelConverter = new SlotIndexToDateLabelConverter(this.dateMode, this.originDate, this.scaleSelected.secondes, this.hasNegativeDependencySpace);
50
- this.buildTaskSlotsFromDuration();
51
- }
52
- this.detectNegativeDependencySpace();
53
- this.calculateTimelineSlots();
54
- this.getAllDependencyPaths();
55
- this.ganttHeightCalcul();
56
- this.ganttWidthCalcul();
57
- this.recomputeLayout();
58
- this.ganttScroll.nativeElement.style.height = this.layout.scrollHeight + 'px';
59
- this.ganttBodyScroll.nativeElement.style.height = this.layout.bodyHeight + 'px';
60
- this.timelineHeader.nativeElement.style.height = this.headerHeight + 'px';
61
- this.ganttContent.nativeElement.style.height = this.ganttHeight - this.rowHeight + 'px';
62
- this.ganttContent.nativeElement.style.width = this.ganttWidth + 'px';
63
- this.leftPanel.nativeElement.style.width = this.leftPanelWidth + 'px';
64
- this.buildViewTasks();
65
- setTimeout(() => {
66
- this.recenterSelectedTask();
67
- }, 0);
68
- this.loading = false;
69
- this.cdr.markForCheck();
70
- requestAnimationFrame(() => {
71
- const end = performance.now();
72
- console.log('frame time including render:', end - start, 'ms');
73
- });
74
- }, 0);
75
- }
76
- buildViewTasks() {
77
- const h = this.rowHeight / 1.25;
78
- this.viewTasks = this.tasks.map((t) => {
79
- return {
80
- ...t,
81
- x: this.getTaskX(t),
82
- y: this.getTaskY(t),
83
- width: this.getTaskWidth(t),
84
- height: h,
85
- };
86
- });
87
- }
88
- // click on button 10m, hour, months
89
- setScale(scale) {
90
- this.defaultScale = scale;
91
- this.recalculteAll();
92
- }
93
- // if task was selected scroll back to it
94
- recenterSelectedTask() {
95
- if (!this.selectedTaskId) {
96
- if (!this.ganttScroll)
97
- return;
98
- this.ganttScroll.nativeElement.scrollLeft = 0;
99
- // force header sync
100
- if (this.timelineHeader?.nativeElement) {
101
- this.timelineHeader.nativeElement.scrollLeft = 0;
102
- }
103
- this.onScrolled();
104
- }
105
- const task = this.tasks.find((t) => t.id === this.selectedTaskId);
106
- if (!task || !this.ganttScroll)
107
- return;
108
- // scroll X
109
- const viewportWidth = this.ganttScroll.nativeElement.clientWidth;
110
- const targetScrollLeft = this.getTaskX(task) - viewportWidth / 2;
111
- this.ganttScroll.nativeElement.scrollTo({ left: Math.max(targetScrollLeft, 0), behavior: 'auto' });
112
- // scroll Y
113
- const viewportHeight = this.ganttBodyScroll.nativeElement.clientHeight;
114
- const targetTop = task.row * this.rowHeight;
115
- const scrollTop = targetTop - viewportHeight / 2 + this.rowHeight / 2;
116
- this.ganttBodyScroll.nativeElement.scrollTo({ top: Math.max(scrollTop, 0), behavior: 'auto' });
117
- this.onScrolled();
118
- }
119
- // detect if there is a need to add the N/A slot in order to be able to show dependency arrow before 0.
120
- detectNegativeDependencySpace() {
121
- const originTasks = this.tasks.filter((t) => (t.startSlot ?? 0) === 0);
122
- this.hasNegativeDependencySpace = originTasks.some((task) => {
123
- const fromRight = this.getRawTaskX(task) + this.getTaskWidth(task);
124
- return (task.dependencies ?? []).some((depId) => {
125
- const target = this.tasks.find((t) => t.id === depId);
126
- if (!target)
127
- return false;
128
- const toLeft = this.getRawTaskX(target);
129
- // true if dependency goes "backwards"
130
- return toLeft < fromRight;
131
- });
132
- });
133
- }
134
- // scroll buttons left/right => click small go, stay clicked scroll a lot
135
- startScroll(direction) {
136
- // instant first move
137
- this.scrollInterval = setInterval(() => {
138
- this.ganttScroll.nativeElement.scrollLeft += direction === 'left' ? -100 : 100;
139
- this.onScrolled();
140
- }, 50);
141
- }
142
- // update buttons left/right after a scroll.
143
- onScrolled() {
144
- const el = this.ganttScroll.nativeElement;
145
- const maxScrollLeft = el.scrollWidth - el.clientWidth;
146
- // left button
147
- this.showLeftBtn = el.scrollLeft > 0;
148
- if (this.leftBtn?.nativeElement) {
149
- if (this.showLeftBtn) {
150
- this.leftBtn.nativeElement.style.display = 'block';
151
- this.leftBtn.nativeElement.style.left = this.leftPanel.nativeElement.style.width;
152
- }
153
- else {
154
- this.leftBtn.nativeElement.style.display = 'none';
155
- this.leftBtn.nativeElement.style.left = this.leftPanel.nativeElement.style.width;
156
- }
157
- }
158
- // right button
159
- this.showRightBtn = el.scrollLeft < maxScrollLeft - 1 || el.scrollLeft === 0; // small tolerance
160
- if (this.rightBtn?.nativeElement) {
161
- if (this.showRightBtn) {
162
- this.rightBtn.nativeElement.style.display = 'block';
163
- }
164
- else {
165
- this.rightBtn.nativeElement.style.display = 'none';
166
- }
167
- }
168
- if (!this.showLeftBtn || !this.showRightBtn) {
169
- this.stopScroll();
170
- }
171
- }
172
- stopScroll() {
173
- clearInterval(this.scrollInterval);
174
- }
175
- // to sync header and grid
176
- onHorizontalScroll(event) {
177
- this.timelineHeader.nativeElement.scrollLeft = event.target.scrollLeft;
178
- }
179
- // highlight dependencies (arrows)
180
- updateHoveredDependencies(task) {
181
- this.hoveredDependencyIds.clear();
182
- if (!task) {
183
- return;
184
- }
185
- // outgoing dependencies
186
- for (const dep of task.dependencies ?? []) {
187
- this.hoveredDependencyIds.add(`${dep}->${task.id}`);
188
- }
189
- // incoming dependencies
190
- for (const t of this.tasks) {
191
- if ((t.dependencies ?? []).includes(task.id)) {
192
- this.hoveredDependencyIds.add(`${task.id}->${t.id}`);
193
- }
194
- }
195
- }
196
- // select task left and right panel
197
- selectTask(task, scroll) {
198
- if (this.selectedTaskId === task.id) {
199
- this.selectedTaskId = null;
200
- this.hoveredDependencyIds.clear();
201
- this.hideTooltip();
202
- this.onScrolled();
203
- return;
204
- }
205
- this.selectedTaskId = task.id;
206
- this.updateHoveredDependencies(task);
207
- this.onScrolled();
208
- if (!scroll || !this.ganttScroll)
209
- return;
210
- const container = this.ganttScroll.nativeElement;
211
- const viewportWidth = container.clientWidth;
212
- const targetScrollLeft = this.getTaskX(task) - viewportWidth / 2;
213
- container.scrollTo({
214
- left: Math.max(targetScrollLeft, 0),
215
- behavior: 'smooth',
216
- });
217
- this.onScrolled();
218
- }
219
- // resize between panel left and right
220
- startResize(event) {
221
- event.preventDefault();
222
- this.resizing = true;
223
- const containerRect = this.ganttBodyScroll.nativeElement.getBoundingClientRect();
224
- const left = containerRect.left;
225
- const min = 50;
226
- const max = containerRect.width - 75;
227
- const moveHandler = (e) => {
228
- if (!this.resizing)
229
- return;
230
- const x = e.clientX - left;
231
- const width = x < min ? min : x > max ? max : x;
232
- // direct DOM update (no Angular)
233
- this.leftPanel.nativeElement.style.width = width + 'px';
234
- if (this.leftBtn?.nativeElement) {
235
- this.leftBtn.nativeElement.style.left = `${width}px`;
236
- }
237
- };
238
- const upHandler = () => {
239
- this.resizing = false;
240
- window.removeEventListener('mousemove', moveHandler);
241
- window.removeEventListener('mouseup', upHandler);
242
- };
243
- window.addEventListener('mousemove', moveHandler);
244
- window.addEventListener('mouseup', upHandler);
245
- }
246
- showTooltip(event, task) {
247
- this.tooltipTask = task;
248
- const tooltip = document.querySelector('.global-tooltip');
249
- if (!tooltip)
250
- return;
251
- tooltip.style.left = `${event.clientX + 10}px`;
252
- tooltip.style.top = `${event.clientY - 50}px`;
253
- tooltip.style.display = 'block';
254
- }
255
- hideTooltip() {
256
- this.tooltipTask = null;
257
- const tooltip = document.querySelector('.global-tooltip');
258
- if (!tooltip)
259
- return;
260
- tooltip.style.display = 'none';
261
- }
262
- buildTaskSlotsFromDates() {
263
- const slotMs = this.scaleSelected.secondes * 1000;
264
- this.tasks = this.rawTasks.map((t) => {
265
- if (!(t.start instanceof Date) || !(t.end instanceof Date)) {
266
- throw new Error(`Task "${t.id}" must have Date start/end values.`);
267
- }
268
- const startSlot = (t.start.getTime() - this.originDate) / slotMs;
269
- const endSlot = (t.end.getTime() - this.originDate) / slotMs;
270
- return { ...t, startSlot, endSlot };
271
- });
272
- }
273
- buildTaskSlotsFromDuration() {
274
- this.tasks = this.rawTasks.map((t) => {
275
- if (typeof t.start !== 'number' || typeof t.end !== 'number') {
276
- throw new Error(`Task "${t.id}" must have numeric start/end values expressed in minutes.`);
277
- }
278
- const startSlot = t.start / this.scaleSelected.secondes;
279
- const endSlot = t.end / this.scaleSelected.secondes;
280
- return { ...t, startSlot, endSlot };
281
- });
282
- }
283
- // get all slots (timeline)
284
- calculateTimelineSlots() {
285
- const maxSlot = Math.max(...this.tasks.map(t => t.endSlot ?? 0));
286
- if (maxSlot > 53000) {
287
- this.maxSlotsAlert = true;
288
- this.slots = [];
289
- return;
290
- }
291
- this.maxSlotsAlert = false;
292
- const buffer = [];
293
- let offsetX = 0;
294
- if (this.hasNegativeDependencySpace) {
295
- buffer.push({
296
- index: -1,
297
- x: 0,
298
- width: this.negativeSlotWidth,
299
- label: 'N/A'
300
- });
301
- offsetX = this.negativeSlotWidth;
302
- }
303
- for (let i = 0; i <= maxSlot + 2; i++) {
304
- buffer.push({
305
- index: i,
306
- x: offsetX + i * this.scaleSelected.px,
307
- width: this.scaleSelected.px,
308
- label: this.getSlotLabel(i) ?? 'Error',
309
- });
310
- }
311
- this.slots = buffer;
312
- }
313
- // get all paths of arrows
314
- getAllDependencyPaths() {
315
- this.dependencyPaths = this.tasks.flatMap((task) => (task.dependencies ?? []).map((dep) => ({
316
- from: dep,
317
- to: task.id,
318
- id: `${dep}->${task.id}`,
319
- path: this.getDependencyPath(dep, task.id),
320
- })));
321
- }
322
- // get label for date header
323
- getSlotLabel(index) {
324
- if (this.dataType === 'calendar') {
325
- return this.labelConverter?.getLabelCalendar(index, this.defaultScale) ?? 'Error';
326
- }
327
- return this.labelConverter?.getLabelDuration(index, this.defaultScale) ?? 'Error';
328
- }
329
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GanttLiteComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
330
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: GanttLiteComponent, selector: "gantt-lite", inputs: { rawTasks: "rawTasks" }, viewQueries: [{ propertyName: "ganttBodyScroll", first: true, predicate: ["ganttBodyScroll"], descendants: true }, { propertyName: "ganttContent", first: true, predicate: ["ganttContent"], descendants: true }, { propertyName: "ganttScroll", first: true, predicate: ["ganttScroll"], descendants: true }, { propertyName: "leftPanel", first: true, predicate: ["leftPanel"], descendants: true }, { propertyName: "timelineHeader", first: true, predicate: ["timelineHeader"], descendants: true }, { propertyName: "leftBtn", first: true, predicate: ["leftBtn"], descendants: true }, { propertyName: "rightBtn", first: true, predicate: ["rightBtn"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"gantt-root\" [style.max-height.px]=\"layout.rootMaxHeight\" [style.min-height.px]=\"100\">\n <!-- TOOLBAR -->\n <div class=\"toolbar\" [style.height.px]=\"buttonsHeight\">\n <div *ngIf=\"dateMode === 'utc' || dataType === 'duration'\">\n <button class=\"gantt-button\" *ngFor=\"let s of scales\" (click)=\"setScale(s)\" [class.active]=\"defaultScale === s\">\n {{ s }}\n </button>\n </div>\n <div *ngIf=\"dateMode !== 'utc' && dataType === 'calendar'\">\n <button class=\"gantt-button\" *ngFor=\"let s of scalesDate\" (click)=\"setScale(s)\"\n [class.active]=\"defaultScale === s\">\n {{ s }}\n </button>\n </div>\n <label *ngIf=\"maxSlotsAlert\" style=\"color: red;\">\n Data is too massive to show Gantt smoothly, try changing the scale\n </label>\n </div>\n <!-- TOOLTIP -->\n <div class=\"global-tooltip\" [style.display]=\"tooltipTask ? 'block' : 'none'\">\n <ng-container *ngIf=\"tooltipTask as task\">\n <div *ngFor=\"let column of visibleTooltipColumns\">\n <strong>{{ column?.title }}:</strong>\n {{ column?.valueGetter(task) }}\n </div>\n </ng-container>\n </div>\n <!-- BUTTONS FOR SCROLL GANTT -->\n <div *ngIf=\"!maxSlotsAlert && loading === false\" class=\"floating-nav\">\n <button class=\"nav-btn left\" (mousedown)=\"startScroll('left')\"\n (mouseup)=\"stopScroll()\" (mouseleave)=\"stopScroll()\" #leftBtn >\n \u2039\n </button>\n <button class=\"nav-btn right\" (mousedown)=\"startScroll('right')\"\n (mouseup)=\"stopScroll()\" (mouseleave)=\"stopScroll()\" #rightBtn>\n \u203A\n </button>\n </div>\n <!-- LOADING -->\n <div class=\"loading-overlay\" *ngIf=\"loading\" [style.top]=\"'50%'\">\n <div class=\"spinner\"></div>\n </div>\n <!-- SINGLE VERTICAL SCROLL -->\n <div class=\"gantt-body\" #ganttBodyScroll>\n <!-- LEFT PANEL -->\n <div class=\"left-panel\" #leftPanel>\n <div class=\"task-row header\" [style.height.px]=\"headerHeight\">\n <div class=\"cell\" *ngFor=\"let column of visibleGridColumns\" [style.width.px]=\"column.width || 120\">\n {{ column?.title }}\n </div>\n </div>\n <div class=\"task-row\" *ngFor=\"let task of tasks\" [style.height.px]=\"rowHeight\"\n (click)=\"selectTask(task, true); $event.stopPropagation()\"\n [class.highlighted-row]=\"selectedTaskId === task.id\">\n <div class=\"cell\" *ngFor=\"let column of visibleGridColumns\" [style.width.px]=\"column.width || 120\">\n {{ column?.valueGetter(task) }}\n </div>\n </div>\n </div>\n <!-- RESIZER -->\n <div class=\"resizer\" [style.height.px]=\"layout.resizerHeight\" (mousedown)=\"startResize($event)\">\n </div>\n <!-- RIGHT PANEL -->\n <div class=\"right-panel\" *ngIf=\"!maxSlotsAlert\">\n <!-- TIMELINE -->\n <div class=\"timeline-header\" #timelineHeader>\n <div class=\"timeline-slot\" *ngFor=\"let slot of slots\" [style.width.px]=\"slot.width\">\n {{ slot.label }}\n </div>\n </div>\n <!-- HORIZONTAL SCROLL ONLY -->\n <div class=\"horizontal-scroll\" (scroll)=\"onHorizontalScroll($event)\" #ganttScroll>\n <div class=\"gantt-content\" #ganttContent>\n <!-- GRID -->\n <div class=\"grid-layer\">\n <div *ngFor=\"let slot of slots; let i = index; trackBy: trackByIndex\" class=\"grid-line\"\n [style.left.px]=\"slot.x - 1\">\n </div>\n <!-- final vertical line -->\n <div class=\"grid-line\" [style.left.px]=\"ganttWidth - 1\">\n </div>\n <!-- horizontal lines -->\n <div class=\"horizontal-grid-layer\">\n <div *ngFor=\"let task of tasks; let i = index; trackBy: trackByIndex\"\n class=\"horizontal-line\" [style.top.px]=\"getGridTop(i)\">\n </div>\n <!-- final horizontal line -->\n <div class=\"horizontal-line\" [style.top.px]=\"ganttHeight\">\n </div>\n </div>\n </div>\n <!-- TASKS -->\n <div class=\"tasks-layer\">\n <div *ngFor=\"let task of viewTasks; let i = index; trackBy: trackByIndex\" class=\"task\"\n (mouseenter)=\"showTooltip($event, task)\" (mouseleave)=\"hideTooltip()\"\n (click)=\"selectTask(task, false); $event.stopPropagation()\"\n [class.highlighted-task]=\"selectedTaskId === task.id\" [style.left.px]=\"task.x\"\n [style.top.px]=\"task.y\" [style.width.px]=\"task.width\" [style.height.px]=\"task.height\">\n <div class=\"task-label\">\n {{ task.label }}\n </div>\n </div>\n </div>\n <!-- DEPENDENCIES -->\n <svg class=\"dependencies-svg\">\n <defs>\n <marker id=\"arrow\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"6\" markerHeight=\"6\"\n orient=\"auto\">\n <path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"#868d97\" />\n </marker>\n </defs>\n <g class=\"dependencies-normal\">\n <path *ngFor=\"let dep of dependencyPaths\" [attr.d]=\"dep.path\" class=\"dependency\"\n [class.hidden]=\"hoveredDependencyIds.has(dep.id)\" marker-end=\"url(#arrow)\">\n </path>\n </g>\n <g class=\"dependencies-highlighted\">\n <path *ngFor=\"let dep of dependencyPaths\" [attr.d]=\"dep.path\" class=\"highlighted-dependency\"\n [class.hidden]=\"!hoveredDependencyIds.has(dep.id)\" marker-end=\"url(#arrow)\">\n </path>\n </g>\n </svg>\n </div>\n </div>\n </div>\n <div class=\"right-panel-dead\" *ngIf=\"maxSlotsAlert\"></div>\n </div>\n</div>", styles: [":host{display:block;width:100%;height:100%}.gantt-root{height:100%;width:100%;display:flex;flex-direction:column;overflow:hidden}.gantt-body{flex:1;display:flex;overflow-y:auto;overflow-x:hidden;border-width:1px;border-style:solid;border-color:#aaac}.toolbar{flex-shrink:0;display:flex;gap:8px;background:#fff;position:sticky;top:0;z-index:50}.toolbar button.active{font-weight:700}.loading-overlay{position:sticky;inset:0;display:flex;align-items:center;justify-content:center;z-index:1000}.global-tooltip{position:fixed;background:#585858e6;color:#fff;padding:8px;border-radius:6px;font-size:12px;z-index:1000;pointer-events:none}.left-panel{flex-shrink:0;background:#fff;border-right:1px solid #dcdcdc}.task-row{display:grid;grid-auto-flow:column;grid-auto-columns:120px;gap:0 10px;font-size:small;align-items:center;border-bottom:1px solid #eee;white-space:nowrap;overflow:hidden}.cell{padding:0 8px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.task-row.header{font-size:small;font-weight:600;position:sticky;top:0;background:#fff!important;z-index:1}.task-row:hover{background:#ff00001a}.highlighted-row{background:#ff00004d!important}.resizer{min-width:7px;cursor:col-resize;background:#b4b4b4}.resizer:hover{background:#696969}.right-panel{flex:1;min-width:100px!important;position:relative}.right-panel-dead{flex:1;height:10000px;min-width:100px!important;position:relative;background-color:#696969}.horizontal-scroll{overflow-x:hidden;overflow-y:hidden;position:relative}.gantt-content{position:relative}.timeline-header{display:flex;position:sticky;top:0;overflow:hidden;white-space:nowrap;z-index:20;background:#fff;border-bottom:1px solid #ccc}.timeline-slot{flex:0 0 auto;border-right:1px solid #e0e0e0;padding:8px;box-sizing:border-box;text-align:center;font-size:12px}.highlighted-task{background:#f006!important;border-color:#b71c1c!important;z-index:10}.grid-layer{position:absolute;inset:0;pointer-events:none}.grid-line{position:absolute;top:0;bottom:0;width:1px;background:#c8c8c859}.horizontal-grid-layer{position:absolute;inset:0;pointer-events:none}.horizontal-line{position:absolute;left:0;right:0;height:1px;background:#c8c8c840}.dependencies-svg{overflow:visible}.dependencies-normal,.dependencies-highlighted{pointer-events:none}.dependency{stroke:#9ba2ad;stroke-width:1.6;fill:none;opacity:.35}.highlighted-dependency{stroke:#52555a;stroke-width:2.7;fill:none;opacity:1}.dependencies-svg.hovering .dependency{opacity:.035}.tasks-layer{position:relative;z-index:2}.task{position:absolute;background:#9b94f7bf;opacity:.85;color:#505050;padding-top:4px;border-radius:4px;font-size:11px;white-space:nowrap;min-width:2px}.task:hover{background:#ff000026}.spinner{width:40px;height:40px;border:4px solid #ddd;border-top-color:#3f51b5;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}*{box-sizing:border-box}.floating-nav{position:sticky;top:50%;transform:translateY(-50%);z-index:100;pointer-events:none}.nav-btn{position:absolute;width:45px;height:45px;display:flex;align-items:center;justify-content:center;pointer-events:auto;background:#5c9af866;border:none;color:#535353;font-size:26px;cursor:pointer;backdrop-filter:blur(1px);border-radius:2px;line-height:1;text-align:center}.nav-btn:hover{background:#5c9af8b3}.nav-btn.left{margin-left:13px}.nav-btn.right{right:23px}.task-label{padding-left:6px}.hidden{display:none}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
331
- }
332
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GanttLiteComponent, decorators: [{
333
- type: Component,
334
- args: [{ selector: 'gantt-lite', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"gantt-root\" [style.max-height.px]=\"layout.rootMaxHeight\" [style.min-height.px]=\"100\">\n <!-- TOOLBAR -->\n <div class=\"toolbar\" [style.height.px]=\"buttonsHeight\">\n <div *ngIf=\"dateMode === 'utc' || dataType === 'duration'\">\n <button class=\"gantt-button\" *ngFor=\"let s of scales\" (click)=\"setScale(s)\" [class.active]=\"defaultScale === s\">\n {{ s }}\n </button>\n </div>\n <div *ngIf=\"dateMode !== 'utc' && dataType === 'calendar'\">\n <button class=\"gantt-button\" *ngFor=\"let s of scalesDate\" (click)=\"setScale(s)\"\n [class.active]=\"defaultScale === s\">\n {{ s }}\n </button>\n </div>\n <label *ngIf=\"maxSlotsAlert\" style=\"color: red;\">\n Data is too massive to show Gantt smoothly, try changing the scale\n </label>\n </div>\n <!-- TOOLTIP -->\n <div class=\"global-tooltip\" [style.display]=\"tooltipTask ? 'block' : 'none'\">\n <ng-container *ngIf=\"tooltipTask as task\">\n <div *ngFor=\"let column of visibleTooltipColumns\">\n <strong>{{ column?.title }}:</strong>\n {{ column?.valueGetter(task) }}\n </div>\n </ng-container>\n </div>\n <!-- BUTTONS FOR SCROLL GANTT -->\n <div *ngIf=\"!maxSlotsAlert && loading === false\" class=\"floating-nav\">\n <button class=\"nav-btn left\" (mousedown)=\"startScroll('left')\"\n (mouseup)=\"stopScroll()\" (mouseleave)=\"stopScroll()\" #leftBtn >\n \u2039\n </button>\n <button class=\"nav-btn right\" (mousedown)=\"startScroll('right')\"\n (mouseup)=\"stopScroll()\" (mouseleave)=\"stopScroll()\" #rightBtn>\n \u203A\n </button>\n </div>\n <!-- LOADING -->\n <div class=\"loading-overlay\" *ngIf=\"loading\" [style.top]=\"'50%'\">\n <div class=\"spinner\"></div>\n </div>\n <!-- SINGLE VERTICAL SCROLL -->\n <div class=\"gantt-body\" #ganttBodyScroll>\n <!-- LEFT PANEL -->\n <div class=\"left-panel\" #leftPanel>\n <div class=\"task-row header\" [style.height.px]=\"headerHeight\">\n <div class=\"cell\" *ngFor=\"let column of visibleGridColumns\" [style.width.px]=\"column.width || 120\">\n {{ column?.title }}\n </div>\n </div>\n <div class=\"task-row\" *ngFor=\"let task of tasks\" [style.height.px]=\"rowHeight\"\n (click)=\"selectTask(task, true); $event.stopPropagation()\"\n [class.highlighted-row]=\"selectedTaskId === task.id\">\n <div class=\"cell\" *ngFor=\"let column of visibleGridColumns\" [style.width.px]=\"column.width || 120\">\n {{ column?.valueGetter(task) }}\n </div>\n </div>\n </div>\n <!-- RESIZER -->\n <div class=\"resizer\" [style.height.px]=\"layout.resizerHeight\" (mousedown)=\"startResize($event)\">\n </div>\n <!-- RIGHT PANEL -->\n <div class=\"right-panel\" *ngIf=\"!maxSlotsAlert\">\n <!-- TIMELINE -->\n <div class=\"timeline-header\" #timelineHeader>\n <div class=\"timeline-slot\" *ngFor=\"let slot of slots\" [style.width.px]=\"slot.width\">\n {{ slot.label }}\n </div>\n </div>\n <!-- HORIZONTAL SCROLL ONLY -->\n <div class=\"horizontal-scroll\" (scroll)=\"onHorizontalScroll($event)\" #ganttScroll>\n <div class=\"gantt-content\" #ganttContent>\n <!-- GRID -->\n <div class=\"grid-layer\">\n <div *ngFor=\"let slot of slots; let i = index; trackBy: trackByIndex\" class=\"grid-line\"\n [style.left.px]=\"slot.x - 1\">\n </div>\n <!-- final vertical line -->\n <div class=\"grid-line\" [style.left.px]=\"ganttWidth - 1\">\n </div>\n <!-- horizontal lines -->\n <div class=\"horizontal-grid-layer\">\n <div *ngFor=\"let task of tasks; let i = index; trackBy: trackByIndex\"\n class=\"horizontal-line\" [style.top.px]=\"getGridTop(i)\">\n </div>\n <!-- final horizontal line -->\n <div class=\"horizontal-line\" [style.top.px]=\"ganttHeight\">\n </div>\n </div>\n </div>\n <!-- TASKS -->\n <div class=\"tasks-layer\">\n <div *ngFor=\"let task of viewTasks; let i = index; trackBy: trackByIndex\" class=\"task\"\n (mouseenter)=\"showTooltip($event, task)\" (mouseleave)=\"hideTooltip()\"\n (click)=\"selectTask(task, false); $event.stopPropagation()\"\n [class.highlighted-task]=\"selectedTaskId === task.id\" [style.left.px]=\"task.x\"\n [style.top.px]=\"task.y\" [style.width.px]=\"task.width\" [style.height.px]=\"task.height\">\n <div class=\"task-label\">\n {{ task.label }}\n </div>\n </div>\n </div>\n <!-- DEPENDENCIES -->\n <svg class=\"dependencies-svg\">\n <defs>\n <marker id=\"arrow\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"6\" markerHeight=\"6\"\n orient=\"auto\">\n <path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"#868d97\" />\n </marker>\n </defs>\n <g class=\"dependencies-normal\">\n <path *ngFor=\"let dep of dependencyPaths\" [attr.d]=\"dep.path\" class=\"dependency\"\n [class.hidden]=\"hoveredDependencyIds.has(dep.id)\" marker-end=\"url(#arrow)\">\n </path>\n </g>\n <g class=\"dependencies-highlighted\">\n <path *ngFor=\"let dep of dependencyPaths\" [attr.d]=\"dep.path\" class=\"highlighted-dependency\"\n [class.hidden]=\"!hoveredDependencyIds.has(dep.id)\" marker-end=\"url(#arrow)\">\n </path>\n </g>\n </svg>\n </div>\n </div>\n </div>\n <div class=\"right-panel-dead\" *ngIf=\"maxSlotsAlert\"></div>\n </div>\n</div>", styles: [":host{display:block;width:100%;height:100%}.gantt-root{height:100%;width:100%;display:flex;flex-direction:column;overflow:hidden}.gantt-body{flex:1;display:flex;overflow-y:auto;overflow-x:hidden;border-width:1px;border-style:solid;border-color:#aaac}.toolbar{flex-shrink:0;display:flex;gap:8px;background:#fff;position:sticky;top:0;z-index:50}.toolbar button.active{font-weight:700}.loading-overlay{position:sticky;inset:0;display:flex;align-items:center;justify-content:center;z-index:1000}.global-tooltip{position:fixed;background:#585858e6;color:#fff;padding:8px;border-radius:6px;font-size:12px;z-index:1000;pointer-events:none}.left-panel{flex-shrink:0;background:#fff;border-right:1px solid #dcdcdc}.task-row{display:grid;grid-auto-flow:column;grid-auto-columns:120px;gap:0 10px;font-size:small;align-items:center;border-bottom:1px solid #eee;white-space:nowrap;overflow:hidden}.cell{padding:0 8px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.task-row.header{font-size:small;font-weight:600;position:sticky;top:0;background:#fff!important;z-index:1}.task-row:hover{background:#ff00001a}.highlighted-row{background:#ff00004d!important}.resizer{min-width:7px;cursor:col-resize;background:#b4b4b4}.resizer:hover{background:#696969}.right-panel{flex:1;min-width:100px!important;position:relative}.right-panel-dead{flex:1;height:10000px;min-width:100px!important;position:relative;background-color:#696969}.horizontal-scroll{overflow-x:hidden;overflow-y:hidden;position:relative}.gantt-content{position:relative}.timeline-header{display:flex;position:sticky;top:0;overflow:hidden;white-space:nowrap;z-index:20;background:#fff;border-bottom:1px solid #ccc}.timeline-slot{flex:0 0 auto;border-right:1px solid #e0e0e0;padding:8px;box-sizing:border-box;text-align:center;font-size:12px}.highlighted-task{background:#f006!important;border-color:#b71c1c!important;z-index:10}.grid-layer{position:absolute;inset:0;pointer-events:none}.grid-line{position:absolute;top:0;bottom:0;width:1px;background:#c8c8c859}.horizontal-grid-layer{position:absolute;inset:0;pointer-events:none}.horizontal-line{position:absolute;left:0;right:0;height:1px;background:#c8c8c840}.dependencies-svg{overflow:visible}.dependencies-normal,.dependencies-highlighted{pointer-events:none}.dependency{stroke:#9ba2ad;stroke-width:1.6;fill:none;opacity:.35}.highlighted-dependency{stroke:#52555a;stroke-width:2.7;fill:none;opacity:1}.dependencies-svg.hovering .dependency{opacity:.035}.tasks-layer{position:relative;z-index:2}.task{position:absolute;background:#9b94f7bf;opacity:.85;color:#505050;padding-top:4px;border-radius:4px;font-size:11px;white-space:nowrap;min-width:2px}.task:hover{background:#ff000026}.spinner{width:40px;height:40px;border:4px solid #ddd;border-top-color:#3f51b5;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}*{box-sizing:border-box}.floating-nav{position:sticky;top:50%;transform:translateY(-50%);z-index:100;pointer-events:none}.nav-btn{position:absolute;width:45px;height:45px;display:flex;align-items:center;justify-content:center;pointer-events:auto;background:#5c9af866;border:none;color:#535353;font-size:26px;cursor:pointer;backdrop-filter:blur(1px);border-radius:2px;line-height:1;text-align:center}.nav-btn:hover{background:#5c9af8b3}.nav-btn.left{margin-left:13px}.nav-btn.right{right:23px}.task-label{padding-left:6px}.hidden{display:none}\n"] }]
335
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { rawTasks: [{
336
- type: Input
337
- }], ganttBodyScroll: [{
338
- type: ViewChild,
339
- args: ['ganttBodyScroll']
340
- }], ganttContent: [{
341
- type: ViewChild,
342
- args: ['ganttContent']
343
- }], ganttScroll: [{
344
- type: ViewChild,
345
- args: ['ganttScroll']
346
- }], leftPanel: [{
347
- type: ViewChild,
348
- args: ['leftPanel']
349
- }], timelineHeader: [{
350
- type: ViewChild,
351
- args: ['timelineHeader']
352
- }], leftBtn: [{
353
- type: ViewChild,
354
- args: ['leftBtn']
355
- }], rightBtn: [{
356
- type: ViewChild,
357
- args: ['rightBtn']
358
- }] } });
359
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2FudHQtbGl0ZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9nYW50dC1saXRlL3NyYy9saWIvZ2FudHQtbGl0ZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9nYW50dC1saXRlL3NyYy9saWIvZ2FudHQtbGl0ZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFjLFNBQVMsRUFBRSxLQUFLLEVBQXFCLHVCQUF1QixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRXBILE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQzs7O0FBU2xELE1BQU0sT0FBTyxrQkFBbUIsU0FBUSxhQUFhO0lBQ2pELElBQ1csUUFBUSxDQUFDLEtBQWtCO1FBQ2xDLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUM3QixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDekIsQ0FBQztJQUNELElBQVcsUUFBUTtRQUNmLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQztJQUMxQixDQUFDO0lBMEJELFlBQW9CLEdBQXNCO1FBQUksS0FBSyxFQUFFLENBQUM7UUFBbEMsUUFBRyxHQUFILEdBQUcsQ0FBbUI7UUFsQm5DLGtCQUFhLEdBQVcsRUFBRSxDQUFDO1FBQzNCLHlCQUFvQixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFDekMsbUJBQWMsR0FBa0IsSUFBSSxDQUFDO1FBQ3JDLGdCQUFXLEdBQXFCLElBQUksQ0FBQztRQUNyQyxhQUFRLEdBQUcsQ0FBQyxDQUFDO1FBQ2IsYUFBUSxHQUFHLENBQUMsQ0FBQztRQUNiLGtCQUFhLEdBQVksS0FBSyxDQUFDO1FBQy9CLFlBQU8sR0FBWSxLQUFLLENBQUM7UUFDekIsZ0JBQVcs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LElBQUksRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUM7U0FDN0MsQ0FBQyxDQUNMLENBQ0osQ0FBQztJQUNOLENBQUM7SUFFRCw0QkFBNEI7SUFDcEIsWUFBWSxDQUFDLEtBQWE7UUFDOUIsSUFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLFVBQVUsRUFBRSxDQUFDO1lBQy9CLE9BQU8sSUFBSSxDQUFDLGNBQWMsRUFBRSxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLE9BQU8sQ0FBQztRQUN0RixDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsY0FBYyxFQUFFLGdCQUFnQixDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksT0FBTyxDQUFDO0lBQ3RGLENBQUM7K0dBelhRLGtCQUFrQjttR0FBbEIsa0JBQWtCLG13QkNaL0IsMndOQStITTs7NEZEbkhPLGtCQUFrQjtrQkFQOUIsU0FBUzsrQkFDSSxZQUFZLGNBR1YsS0FBSyxtQkFDQSx1QkFBdUIsQ0FBQyxNQUFNO3NGQUlwQyxRQUFRO3NCQURsQixLQUFLO2dCQVFnQyxlQUFlO3NCQUFwRCxTQUFTO3VCQUFDLGlCQUFpQjtnQkFDTyxZQUFZO3NCQUE5QyxTQUFTO3VCQUFDLGNBQWM7Z0JBQ1MsV0FBVztzQkFBNUMsU0FBUzt1QkFBQyxhQUFhO2dCQUNRLFNBQVM7c0JBQXhDLFNBQVM7dUJBQUMsV0FBVztnQkFDZSxjQUFjO3NCQUFsRCxTQUFTO3VCQUFDLGdCQUFnQjtnQkFDRyxPQUFPO3NCQUFwQyxTQUFTO3VCQUFDLFNBQVM7Z0JBQ1csUUFBUTtzQkFBdEMsU0FBUzt1QkFBQyxVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBWaWV3Q2hpbGQsIElucHV0LCBDaGFuZ2VEZXRlY3RvclJlZiwgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRGVwZW5kZW5jeVBhdGgsIEdhbnR0U2NhbGUsIEdhbnR0VGFzaywgR2FudHRUYXNrVmlldyB9IGZyb20gJy4vZ2FudHQtbGl0ZS5tb2RlbCc7XHJcbmltcG9ydCB7IFNsb3RJbmRleFRvRGF0ZUxhYmVsQ29udmVydGVyIH0gZnJvbSAnLi9nYW50dC1saXRlLmhlbHBlcic7XHJcbmltcG9ydCB7IEdhbnR0TGl0ZUJhc2UgfSBmcm9tICcuL2dhbnR0LWxpdGUtYmFzZSc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICAgIHNlbGVjdG9yOiAnZ2FudHQtbGl0ZScsXHJcbiAgICB0ZW1wbGF0ZVVybDogJy4vZ2FudHQtbGl0ZS5jb21wb25lbnQuaHRtbCcsXHJcbiAgICBzdHlsZVVybHM6IFsnLi9nYW50dC1saXRlLmNvbXBvbmVudC5zY3NzJ10sXHJcbiAgICBzdGFuZGFsb25lOiBmYWxzZSxcclxuICAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgR2FudHRMaXRlQ29tcG9uZW50IGV4dGVuZHMgR2FudHRMaXRlQmFzZSB7XHJcbiAgICBASW5wdXQoKVxyXG4gICAgcHVibGljIHNldCByYXdUYXNrcyh2YWx1ZTogR2FudHRUYXNrW10pIHtcclxuICAgICAgICB0aGlzLl9yYXdUYXNrcyA9IHZhbHVlID8/IFtdO1xyXG4gICAgICAgIHRoaXMucmVjYWxjdWx0ZUFsbCgpO1xyXG4gICAgfVxyXG4gICAgcHVibGljIGdldCByYXdUYXNrcygpOiBHYW50dFRhc2tbXSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3Jhd1Rhc2tzO1xyXG4gICAgfVxyXG4gICAgQFZpZXdDaGlsZCgnZ2FudHRCb2R5U2Nyb2xsJykgcHJpdmF0ZSBnYW50dEJvZHlTY3JvbGwhOiBFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50PjtcclxuICAgIEBWaWV3Q2hpbGQoJ2dhbnR0Q29udGVudCcpIHByaXZhdGUgZ2FudHRDb250ZW50ITogRWxlbWVudFJlZjxIVE1MRGl2RWxlbWVudD47XHJcbiAgICBAVmlld0NoaWxkKCdnYW50dFNjcm9sbCcpIHByaXZhdGUgZ2FudHRTY3JvbGwhOiBFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50PjtcclxuICAgIEBWaWV3Q2hpbGQoJ2xlZnRQYW5lbCcpIHByaXZhdGUgbGVmdFBhbmVsITogRWxlbWVudFJlZjxIVE1MQnV0dG9uRWxlbWVudD47XHJcbiAgICBAVmlld0NoaWxkKCd0aW1lbGluZUhlYWRlcicpIHByaXZhdGUgdGltZWxpbmVIZWFkZXIhOiBFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50PjtcclxuICAgIEBWaWV3Q2hpbGQoJ2xlZnRCdG4nKSBwcml2YXRlIGxlZnRCdG4hOiBFbGVtZW50UmVmPEhUTUxCdXR0b25FbGVtZW50PjtcclxuICAgIEBWaWV3Q2hpbGQoJ3JpZ2h0QnRuJykgcHJpdmF0ZSByaWdodEJ0biE6IEVsZW1lbnRSZWY8SFRNTEJ1dHRvbkVsZW1lbnQ+O1xyXG4gICAgcHVibGljIHRvb2xiYXJIZWlnaHQ6IG51bWJlciA9IDI3O1xyXG4gICAgcHVibGljIGhvdmVyZWREZXBlbmRlbmN5SWRzID0gbmV3IFNldDxzdHJpbmc+KCk7XHJcbiAgICBwdWJsaWMgc2VsZWN0ZWRUYXNrSWQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xyXG4gICAgcHVibGljIHRvb2x0aXBUYXNrOiBHYW50dFRhc2sgfCBudWxsID0gbnVsbDtcclxuICAgIHB1YmxpYyB0b29sdGlwWCA9IDA7XHJcbiAgICBwdWJsaWMgdG9vbHRpcFkgPSAwO1xyXG4gICAgcHVibGljIG1heFNsb3RzQWxlcnQ6IGJvb2xlYW4gPSBmYWxzZTtcclxuICAgIHB1YmxpYyBsb2FkaW5nOiBib29sZWFuID0gZmFsc2U7XHJcbiAgICBwdWJsaWMgc2hvd0xlZnRCdG4gPSBmYWxzZTtcclxuICAgIHB1YmxpYyBzaG93UmlnaHRCdG4gPSB0cnVlO1xyXG4gICAgcHVibGljIGJ1dHRvbnNIZWlnaHQ6IG51bWJlciA9IDIwO1xyXG4gICAgcHVibGljIHZpZXdUYXNrczogR2FudHRUYXNrVmlld1tdID0gW107XHJcbiAgICBwcml2YXRlIF9yYXdUYXNrczogR2FudHRUYXNrW10gPSBbXTtcclxuICAgIHByaXZhdGUgb3JpZ2luRGF0ZTogbnVtYmVyID0gMDtcclxuICAgIHByaXZhdGUgcmVzaXppbmcgPSBmYWxzZTtcclxuICAgIHByaXZhdGUgc2Nyb2xsSW50ZXJ2YWw6IGFueTtcclxuICAgIHByaXZhdGUgbGFiZWxDb252ZXJ0ZXI6IFNsb3RJbmRleFRvRGF0ZUxhYmVsQ29udmVydGVyIHwgbnVsbCA9IG51bGw7XHJcblxyXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBjZHI6IENoYW5nZURldGVjdG9yUmVmKSB7IHN1cGVyKCk7IH1cclxuXHJcbiAgICAvLyByZWNhbGN1bGF0ZSBhbGwgR2FudHRcclxuICAgIHByaXZhdGUgcmVjYWxjdWx0ZUFsbCgpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmxvYWRpbmcgPSB0cnVlO1xyXG4gICAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xyXG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCBzdGFydCA9IHBlcmZvcm1hbmNlLm5vdygpO1xyXG4gICAgICAgICAgICB0aGlzLnJlZnJlc2hWaXNpYmxlQ29sdW1ucygpO1xyXG4gICAgICAgICAgICB0aGlzLnNjYWxlU2VsZWN0ZWQgPSB0aGlzLmdldFNjYWxlQ29uZmlnKHRoaXMuZGVmYXVsdFNjYWxlKTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLmRhdGFUeXBlICE9PSAnZHVyYXRpb24nKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBiYXNlID0gbmV3IERhdGUoTWF0aC5taW4oLi4udGhpcy5yYXdUYXNrcy5tYXAoKHQpID0+ICh0LnN0YXJ0IGFzIERhdGUpLmdldFRpbWUoKSkpKTtcclxuICAgICAgICAgICAgICAgIHRoaXMub3JpZ2luRGF0ZSA9IHRoaXMuYWxpZ25PcmlnaW5CeVNjYWxlKGJhc2UsIHRoaXMuZGVmYXVsdFNjYWxlKS5nZXRUaW1lKCk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmxhYmVsQ29udmVydGVyID0gbmV3IFNsb3RJbmRleFRvRGF0ZUxhYmVsQ29udmVydGVyKFxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZU1vZGUsXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vcmlnaW5EYXRlLFxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2NhbGVTZWxlY3RlZC5zZWNvbmRlcyxcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmhhc05lZ2F0aXZlRGVwZW5kZW5jeVNwYWNlXHJcbiAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5idWlsZFRhc2tTbG90c0Zyb21EYXRlcygpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5sYWJlbENvbnZlcnRlciA9IG5ldyBTbG90SW5kZXhUb0RhdGVMYWJlbENvbnZlcnRlcihcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGVNb2RlLFxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3JpZ2luRGF0ZSxcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnNjYWxlU2VsZWN0ZWQuc2Vjb25kZXMsXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oYXNOZWdhdGl2ZURlcGVuZGVuY3lTcGFjZVxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuYnVpbGRUYXNrU2xvdHNGcm9tRHVyYXRpb24oKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB0aGlzLmRldGVjdE5lZ2F0aXZlRGVwZW5kZW5jeVNwYWNlKCk7XHJcbiAgICAgICAgICAgIHRoaXMuY2FsY3VsYXRlVGltZWxpbmVTbG90cygpO1xyXG4gICAgICAgICAgICB0aGlzLmdldEFsbERlcGVuZGVuY3lQYXRocygpO1xyXG4gICAgICAgICAgICB0aGlzLmdhbnR0SGVpZ2h0Q2FsY3VsKCk7XHJcbiAgICAgICAgICAgIHRoaXMuZ2FudHRXaWR0aENhbGN1bCgpO1xyXG4gICAgICAgICAgICB0aGlzLnJlY29tcHV0ZUxheW91dCgpO1xyXG4gICAgICAgICAgICB0aGlzLmdhbnR0U2Nyb2xsLm5hdGl2ZUVsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gdGhpcy5sYXlvdXQuc2Nyb2xsSGVpZ2h0ICsgJ3B4JztcclxuICAgICAgICAgICAgdGhpcy5nYW50dEJvZHlTY3JvbGwubmF0aXZlRWxlbWVudC5zdHlsZS5oZWlnaHQgPSB0aGlzLmxheW91dC5ib2R5SGVpZ2h0ICsgJ3B4JztcclxuICAgICAgICAgICAgdGhpcy50aW1lbGluZUhlYWRlci5uYXRpdmVFbGVtZW50LnN0eWxlLmhlaWdodCA9IHRoaXMuaGVhZGVySGVpZ2h0ICsgJ3B4JztcclxuICAgICAgICAgICAgdGhpcy5nYW50dENvbnRlbnQubmF0aXZlRWxlbWVudC5zdHlsZS5oZWlnaHQgPSB0aGlzLmdhbnR0SGVpZ2h0IC0gdGhpcy5yb3dIZWlnaHQgKyAncHgnO1xyXG4gICAgICAgICAgICB0aGlzLmdhbnR0Q29udGVudC5uYXRpdmVFbGVtZW50LnN0eWxlLndpZHRoID0gdGhpcy5nYW50dFdpZHRoICsgJ3B4JztcclxuICAgICAgICAgICAgdGhpcy5sZWZ0UGFuZWwubmF0aXZlRWxlbWVudC5zdHlsZS53aWR0aCA9IHRoaXMubGVmdFBhbmVsV2lkdGggKyAncHgnO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5idWlsZFZpZXdUYXNrcygpO1xyXG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMucmVjZW50ZXJTZWxlY3RlZFRhc2soKTtcclxuICAgICAgICAgICAgfSwgMCk7XHJcbiAgICAgICAgICAgIHRoaXMubG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcclxuICAgICAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGVuZCA9IHBlcmZvcm1hbmNlLm5vdygpO1xyXG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ2ZyYW1lIHRpbWUgaW5jbHVkaW5nIHJlbmRlcjonLCBlbmQgLSBzdGFydCwgJ21zJyk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0sIDApO1xyXG4gICAgfVxyXG4gICAgXHJcblxyXG4gICAgcHJpdmF0ZSBidWlsZFZpZXdUYXNrcygpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBoID0gdGhpcy5yb3dIZWlnaHQgLyAxLjI1O1xyXG5cclxuICAgICAgICB0aGlzLnZpZXdUYXNrcyA9IHRoaXMudGFza3MubWFwKCh0KTogR2FudHRUYXNrVmlldyA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICAuLi50LFxyXG4gICAgICAgICAgICAgICAgeDogdGhpcy5nZXRUYXNrWCh0KSxcclxuICAgICAgICAgICAgICAgIHk6IHRoaXMuZ2V0VGFza1kodCksXHJcbiAgICAgICAgICAgICAgICB3aWR0aDogdGhpcy5nZXRUYXNrV2lkdGgodCksXHJcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IGgsXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gY2xpY2sgb24gYnV0dG9uIDEwbSwgaG91ciwgbW9udGhzXHJcbiAgICBwdWJsaWMgc2V0U2NhbGUoc2NhbGU6IEdhbnR0U2NhbGUpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmRlZmF1bHRTY2FsZSA9IHNjYWxlO1xyXG4gICAgICAgIHRoaXMucmVjYWxjdWx0ZUFsbCgpO1xyXG4gICAgfVxyXG5cclxuXHJcbiAgICAvLyBpZiB0YXNrIHdhcyBzZWxlY3RlZCBzY3JvbGwgYmFjayB0byBpdFxyXG4gICAgcHJpdmF0ZSByZWNlbnRlclNlbGVjdGVkVGFzaygpOiB2b2lkIHtcclxuICAgICAgICBpZiAoIXRoaXMuc2VsZWN0ZWRUYXNrSWQpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmdhbnR0U2Nyb2xsKSByZXR1cm47XHJcbiAgICAgICAgICAgIHRoaXMuZ2FudHRTY3JvbGwubmF0aXZlRWxlbWVudC5zY3JvbGxMZWZ0ID0gMDtcclxuXHJcbiAgICAgICAgICAgIC8vIGZvcmNlIGhlYWRlciBzeW5jXHJcbiAgICAgICAgICAgIGlmICh0aGlzLnRpbWVsaW5lSGVhZGVyPy5uYXRpdmVFbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnRpbWVsaW5lSGVhZGVyLm5hdGl2ZUVsZW1lbnQuc2Nyb2xsTGVmdCA9IDA7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdGhpcy5vblNjcm9sbGVkKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCB0YXNrID0gdGhpcy50YXNrcy5maW5kKCh0KSA9PiB0LmlkID09PSB0aGlzLnNlbGVjdGVkVGFza0lkKTtcclxuICAgICAgICBpZiAoIXRhc2sgfHwgIXRoaXMuZ2FudHRTY3JvbGwpIHJldHVybjtcclxuXHJcbiAgICAgICAgLy8gc2Nyb2xsIFhcclxuICAgICAgICBjb25zdCB2aWV3cG9ydFdpZHRoID0gdGhpcy5nYW50dFNjcm9sbC5uYXRpdmVFbGVtZW50LmNsaWVudFdpZHRoO1xyXG4gICAgICAgIGNvbnN0IHRhcmdldFNjcm9sbExlZnQgPSB0aGlzLmdldFRhc2tYKHRhc2spIC0gdmlld3BvcnRXaWR0aCAvIDI7XHJcbiAgICAgICAgdGhpcy5nYW50dFNjcm9sbC5uYXRpdmVFbGVtZW50LnNjcm9sbFRvKHsgbGVmdDogTWF0aC5tYXgodGFyZ2V0U2Nyb2xsTGVmdCwgMCksIGJlaGF2aW9yOiAnYXV0bycgfSk7XHJcblxyXG4gICAgICAgIC8vIHNjcm9sbCBZXHJcbiAgICAgICAgY29uc3Qgdmlld3BvcnRIZWlnaHQgPSB0aGlzLmdhbnR0Qm9keVNjcm9sbC5uYXRpdmVFbGVtZW50LmNsaWVudEhlaWdodDtcclxuICAgICAgICBjb25zdCB0YXJnZXRUb3AgPSB0YXNrLnJvdyAqIHRoaXMucm93SGVpZ2h0O1xyXG4gICAgICAgIGNvbnN0IHNjcm9sbFRvcCA9IHRhcmdldFRvcCAtIHZpZXdwb3J0SGVpZ2h0IC8gMiArIHRoaXMucm93SGVpZ2h0IC8gMjtcclxuICAgICAgICB0aGlzLmdhbnR0Qm9keVNjcm9sbC5uYXRpdmVFbGVtZW50LnNjcm9sbFRvKHsgdG9wOiBNYXRoLm1heChzY3JvbGxUb3AsIDApLCBiZWhhdmlvcjogJ2F1dG8nIH0pO1xyXG5cclxuICAgICAgICB0aGlzLm9uU2Nyb2xsZWQoKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBkZXRlY3QgaWYgdGhlcmUgaXMgYSBuZWVkIHRvIGFkZCB0aGUgTi9BIHNsb3QgaW4gb3JkZXIgdG8gYmUgYWJsZSB0byBzaG93IGRlcGVuZGVuY3kgYXJyb3cgYmVmb3JlIDAuXHJcbiAgICBwcml2YXRlIGRldGVjdE5lZ2F0aXZlRGVwZW5kZW5jeVNwYWNlKCk6IHZvaWQge1xyXG4gICAgICAgIGNvbnN0IG9yaWdpblRhc2tzID0gdGhpcy50YXNrcy5maWx0ZXIoKHQpID0+ICh0LnN0YXJ0U2xvdCA/PyAwKSA9PT0gMCk7XHJcblxyXG4gICAgICAgIHRoaXMuaGFzTmVnYXRpdmVEZXBlbmRlbmN5U3BhY2UgPSBvcmlnaW5UYXNrcy5zb21lKCh0YXNrKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IGZyb21SaWdodCA9IHRoaXMuZ2V0UmF3VGFza1godGFzaykgKyB0aGlzLmdldFRhc2tXaWR0aCh0YXNrKTtcclxuICAgICAgICAgICAgcmV0dXJuICh0YXNrLmRlcGVuZGVuY2llcyA/PyBbXSkuc29tZSgoZGVwSWQ6IGFueSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0ID0gdGhpcy50YXNrcy5maW5kKCh0KSA9PiB0LmlkID09PSBkZXBJZCk7XHJcbiAgICAgICAgICAgICAgICBpZiAoIXRhcmdldCkgcmV0dXJuIGZhbHNlO1xyXG5cclxuICAgICAgICAgICAgICAgIGNvbnN0IHRvTGVmdCA9IHRoaXMuZ2V0UmF3VGFza1godGFyZ2V0KTtcclxuICAgICAgICAgICAgICAgIC8vIHRydWUgaWYgZGVwZW5kZW5jeSBnb2VzIFwiYmFja3dhcmRzXCJcclxuICAgICAgICAgICAgICAgIHJldHVybiB0b0xlZnQgPCBmcm9tUmlnaHQ7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIHNjcm9sbCBidXR0b25zIGxlZnQvcmlnaHQgPT4gY2xpY2sgc21hbGwgZ28sIHN0YXkgY2xpY2tlZCBzY3JvbGwgYSBsb3RcclxuICAgIHB1YmxpYyBzdGFydFNjcm9sbChkaXJlY3Rpb246ICdsZWZ0JyB8ICdyaWdodCcpOiB2b2lkIHtcclxuICAgICAgICAvLyBpbnN0YW50IGZpcnN0IG1vdmUgICAgICAgICAgIFxyXG4gICAgICAgIHRoaXMuc2Nyb2xsSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuZ2FudHRTY3JvbGwubmF0aXZlRWxlbWVudC5zY3JvbGxMZWZ0ICs9IGRpcmVjdGlvbiA9PT0gJ2xlZnQnID8gLTEwMCA6IDEwMDtcclxuICAgICAgICAgICAgdGhpcy5vblNjcm9sbGVkKCk7XHJcbiAgICAgICAgfSwgNTApO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIHVwZGF0ZSBidXR0b25zIGxlZnQvcmlnaHQgYWZ0ZXIgYSBzY3JvbGwuXHJcbiAgICBwcml2YXRlIG9uU2Nyb2xsZWQoKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3QgZWwgPSB0aGlzLmdhbnR0U2Nyb2xsLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICAgICAgY29uc3QgbWF4U2Nyb2xsTGVmdCA9IGVsLnNjcm9sbFdpZHRoIC0gZWwuY2xpZW50V2lkdGg7XHJcbiAgICAgICAgLy8gbGVmdCBidXR0b25cclxuICAgICAgICB0aGlzLnNob3dMZWZ0QnRuID0gZWwuc2Nyb2xsTGVmdCA+IDA7XHJcbiAgICAgICAgaWYgKHRoaXMubGVmdEJ0bj8ubmF0aXZlRWxlbWVudCkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5zaG93TGVmdEJ0bikge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5sZWZ0QnRuLm5hdGl2ZUVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmxlZnRCdG4ubmF0aXZlRWxlbWVudC5zdHlsZS5sZWZ0ID0gdGhpcy5sZWZ0UGFuZWwubmF0aXZlRWxlbWVudC5zdHlsZS53aWR0aDtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRoaXMubGVmdEJ0bi5uYXRpdmVFbGVtZW50LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmxlZnRCdG4ubmF0aXZlRWxlbWVudC5zdHlsZS5sZWZ0ID0gdGhpcy5sZWZ0UGFuZWwubmF0aXZlRWxlbWVudC5zdHlsZS53aWR0aDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICAvLyByaWdodCBidXR0b25cclxuICAgICAgICB0aGlzLnNob3dSaWdodEJ0biA9IGVsLnNjcm9sbExlZnQgPCBtYXhTY3JvbGxMZWZ0IC0gMSB8fCBlbC5zY3JvbGxMZWZ0ID09PSAwOyAvLyBzbWFsbCB0b2xlcmFuY2VcclxuICAgICAgICBpZiAodGhpcy5yaWdodEJ0bj8ubmF0aXZlRWxlbWVudCkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5zaG93UmlnaHRCdG4pIHtcclxuICAgICAgICAgICAgICAgIHRoaXMucmlnaHRCdG4ubmF0aXZlRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRoaXMucmlnaHRCdG4ubmF0aXZlRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICghdGhpcy5zaG93TGVmdEJ0biB8fCAhdGhpcy5zaG93UmlnaHRCdG4pIHtcclxuICAgICAgICAgICAgdGhpcy5zdG9wU2Nyb2xsKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBzdG9wU2Nyb2xsKCk6IHZvaWR7XHJcbiAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLnNjcm9sbEludGVydmFsKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyB0byBzeW5jIGhlYWRlciBhbmQgZ3JpZFxyXG4gICAgcHVibGljIG9uSG9yaXpvbnRhbFNjcm9sbChldmVudDogRXZlbnQpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLnRpbWVsaW5lSGVhZGVyLm5hdGl2ZUVsZW1lbnQuc2Nyb2xsTGVmdCA9IChldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQpLnNjcm9sbExlZnQ7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gaGlnaGxpZ2h0IGRlcGVuZGVuY2llcyAoYXJyb3dzKVxyXG4gICAgcHJpdmF0ZSB1cGRhdGVIb3ZlcmVkRGVwZW5kZW5jaWVzKHRhc2s6IEdhbnR0VGFzayB8IG51bGwpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmhvdmVyZWREZXBlbmRlbmN5SWRzLmNsZWFyKCk7XHJcbiAgICAgICAgaWYgKCF0YXNrKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIG91dGdvaW5nIGRlcGVuZGVuY2llc1xyXG4gICAgICAgIGZvciAoY29uc3QgZGVwIG9mIHRhc2suZGVwZW5kZW5jaWVzID8/IFtdKSB7XHJcbiAgICAgICAgICAgIHRoaXMuaG92ZXJlZERlcGVuZGVuY3lJZHMuYWRkKGAke2RlcH0tPiR7dGFzay5pZH1gKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIGluY29taW5nIGRlcGVuZGVuY2llc1xyXG4gICAgICAgIGZvciAoY29uc3QgdCBvZiB0aGlzLnRhc2tzKSB7XHJcbiAgICAgICAgICAgIGlmICgodC5kZXBlbmRlbmNpZXMgPz8gW10pLmluY2x1ZGVzKHRhc2suaWQpKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmhvdmVyZWREZXBlbmRlbmN5SWRzLmFkZChgJHt0YXNrLmlkfS0+JHt0LmlkfWApO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIHNlbGVjdCB0YXNrIGxlZnQgYW5kIHJpZ2h0IHBhbmVsXHJcbiAgICBwdWJsaWMgc2VsZWN0VGFzayh0YXNrOiBHYW50dFRhc2ssIHNjcm9sbDogYm9vbGVhbik6IHZvaWQge1xyXG4gICAgICAgIGlmICh0aGlzLnNlbGVjdGVkVGFza0lkID09PSB0YXNrLmlkKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRUYXNrSWQgPSBudWxsO1xyXG4gICAgICAgICAgICB0aGlzLmhvdmVyZWREZXBlbmRlbmN5SWRzLmNsZWFyKCk7XHJcbiAgICAgICAgICAgIHRoaXMuaGlkZVRvb2x0aXAoKTtcclxuICAgICAgICAgICAgdGhpcy5vblNjcm9sbGVkKCk7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuc2VsZWN0ZWRUYXNrSWQgPSB0YXNrLmlkO1xyXG4gICAgICAgIHRoaXMudXBkYXRlSG92ZXJlZERlcGVuZGVuY2llcyh0YXNrKTtcclxuICAgICAgICB0aGlzLm9uU2Nyb2xsZWQoKTtcclxuICAgICAgICBpZiAoIXNjcm9sbCB8fCAhdGhpcy5nYW50dFNjcm9sbCkgcmV0dXJuO1xyXG5cclxuICAgICAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLmdhbnR0U2Nyb2xsLm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnQ7XHJcbiAgICAgICAgY29uc3Qgdmlld3BvcnRXaWR0aCA9IGNvbnRhaW5lci5jbGllbnRXaWR0aDtcclxuICAgICAgICBjb25zdCB0YXJnZXRTY3JvbGxMZWZ0ID0gdGhpcy5nZXRUYXNrWCh0YXNrKSAtIHZpZXdwb3J0V2lkdGggLyAyO1xyXG5cclxuICAgICAgICBjb250YWluZXIuc2Nyb2xsVG8oe1xyXG4gICAgICAgICAgICBsZWZ0OiBNYXRoLm1heCh0YXJnZXRTY3JvbGxMZWZ0LCAwKSxcclxuICAgICAgICAgICAgYmVoYXZpb3I6ICdzbW9vdGgnLFxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHRoaXMub25TY3JvbGxlZCgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIHJlc2l6ZSBiZXR3ZWVuIHBhbmVsIGxlZnQgYW5kIHJpZ2h0XHJcbiAgICBwdWJsaWMgc3RhcnRSZXNpemUoZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcclxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgIHRoaXMucmVzaXppbmcgPSB0cnVlO1xyXG4gICAgICAgIGNvbnN0IGNvbnRhaW5lclJlY3QgPSB0aGlzLmdhbnR0Qm9keVNjcm9sbC5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG4gICAgICAgIGNvbnN0IGxlZnQgPSBjb250YWluZXJSZWN0LmxlZnQ7XHJcbiAgICAgICAgY29uc3QgbWluID0gNTA7XHJcbiAgICAgICAgY29uc3QgbWF4ID0gY29udGFpbmVyUmVjdC53aWR0aCAtIDc1O1xyXG4gICAgICAgIGNvbnN0IG1vdmVIYW5kbGVyID0gKGU6IE1vdXNlRXZlbnQpOiB2b2lkID0+IHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLnJlc2l6aW5nKSByZXR1cm47XHJcbiAgICAgICAgICAgIGNvbnN0IHggPSBlLmNsaWVudFggLSBsZWZ0O1xyXG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IHggPCBtaW4gPyBtaW4gOiB4ID4gbWF4ID8gbWF4IDogeDtcclxuXHJcbiAgICAgICAgICAgIC8vIGRpcmVjdCBET00gdXBkYXRlIChubyBBbmd1bGFyKVxyXG4gICAgICAgICAgICB0aGlzLmxlZnRQYW5lbC5uYXRpdmVFbGVtZW50LnN0eWxlLndpZHRoID0gd2lkdGggKyAncHgnO1xyXG4gICAgICAgICAgICBpZiAodGhpcy5sZWZ0QnRuPy5uYXRpdmVFbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmxlZnRCdG4ubmF0aXZlRWxlbWVudC5zdHlsZS5sZWZ0ID0gYCR7d2lkdGh9cHhgO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgY29uc3QgdXBIYW5kbGVyID0gKCk6IHZvaWQgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLnJlc2l6aW5nID0gZmFsc2U7XHJcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBtb3ZlSGFuZGxlcik7XHJcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdXBIYW5kbGVyKTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgbW92ZUhhbmRsZXIpO1xyXG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdXBIYW5kbGVyKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgc2hvd1Rvb2x0aXAoZXZlbnQ6IE1vdXNlRXZlbnQsIHRhc2s6IEdhbnR0VGFzayk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMudG9vbHRpcFRhc2sgPSB0YXNrO1xyXG4gICAgICAgIGNvbnN0IHRvb2x0aXAgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcuZ2xvYmFsLXRvb2x0aXAnKSBhcyBIVE1MRWxlbWVudDtcclxuICAgICAgICBpZiAoIXRvb2x0aXApIHJldHVybjtcclxuICAgICAgICB0b29sdGlwLnN0eWxlLmxlZnQgPSBgJHtldmVudC5jbGllbnRYICsgMTB9cHhgO1xyXG4gICAgICAgIHRvb2x0aXAuc3R5bGUudG9wID0gYCR7ZXZlbnQuY2xpZW50WSAtIDUwfXB4YDtcclxuICAgICAgICB0b29sdGlwLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBoaWRlVG9vbHRpcCgpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLnRvb2x0aXBUYXNrID0gbnVsbDtcclxuICAgICAgICBjb25zdCB0b29sdGlwID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLmdsb2JhbC10b29sdGlwJykgYXMgSFRNTEVsZW1lbnQ7XHJcbiAgICAgICAgaWYgKCF0b29sdGlwKSByZXR1cm47XHJcbiAgICAgICAgdG9vbHRpcC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgYnVpbGRUYXNrU2xvdHNGcm9tRGF0ZXMoKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3Qgc2xvdE1zID0gdGhpcy5zY2FsZVNlbGVjdGVkLnNlY29uZGVzICogMTAwMDtcclxuICAgICAgICB0aGlzLnRhc2tzID0gdGhpcy5yYXdUYXNrcy5tYXAoKHQpID0+IHtcclxuICAgICAgICAgICAgaWYgKCEodC5zdGFydCBpbnN0YW5jZW9mIERhdGUpIHx8ICEodC5lbmQgaW5zdGFuY2VvZiBEYXRlKSkge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUYXNrIFwiJHt0LmlkfVwiIG11c3QgaGF2ZSBEYXRlIHN0YXJ0L2VuZCB2YWx1ZXMuYCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHN0YXJ0U2xvdCA9ICgodC5zdGFydCBhcyBEYXRlKS5nZXRUaW1lKCkgLSB0aGlzLm9yaWdpbkRhdGUpIC8gc2xvdE1zO1xyXG4gICAgICAgICAgICBjb25zdCBlbmRTbG90ID0gKCh0LmVuZCBhcyBEYXRlKS5nZXRUaW1lKCkgLSB0aGlzLm9yaWdpbkRhdGUpIC8gc2xvdE1zO1xyXG4gICAgICAgICAgICByZXR1cm4geyAuLi50LCBzdGFydFNsb3QsIGVuZFNsb3QgfTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGJ1aWxkVGFza1Nsb3RzRnJvbUR1cmF0aW9uKCk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMudGFza3MgPSB0aGlzLnJhd1Rhc2tzLm1hcCgodCkgPT4ge1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIHQuc3RhcnQgIT09ICdudW1iZXInIHx8IHR5cGVvZiB0LmVuZCAhPT0gJ251bWJlcicpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVGFzayBcIiR7dC5pZH1cIiBtdXN0IGhhdmUgbnVtZXJpYyBzdGFydC9lbmQgdmFsdWVzIGV4cHJlc3NlZCBpbiBtaW51dGVzLmApO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBzdGFydFNsb3QgPSB0LnN0YXJ0IC8gdGhpcy5zY2FsZVNlbGVjdGVkLnNlY29uZGVzO1xyXG4gICAgICAgICAgICBjb25zdCBlbmRTbG90ID0gdC5lbmQgLyB0aGlzLnNjYWxlU2VsZWN0ZWQuc2Vjb25kZXM7XHJcbiAgICAgICAgICAgIHJldHVybiB7IC4uLnQsIHN0YXJ0U2xvdCwgZW5kU2xvdCB9O1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIGdldCBhbGwgc2xvdHMgKHRpbWVsaW5lKVxyXG4gICAgcHJpdmF0ZSBjYWxjdWxhdGVUaW1lbGluZVNsb3RzKCk6IHZvaWQge1xyXG4gICAgICAgIGNvbnN0IG1heFNsb3QgPSBNYXRoLm1heCguLi50aGlzLnRhc2tzLm1hcCh0ID0+IHQuZW5kU2xvdCA/PyAwKSk7XHJcbiAgICAgICAgaWYgKG1heFNsb3QgPiA1MzAwMCkge1xyXG4gICAgICAgICAgICB0aGlzLm1heFNsb3RzQWxlcnQgPSB0cnVlO1xyXG4gICAgICAgICAgICB0aGlzLnNsb3RzID0gW107XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5tYXhTbG90c0FsZXJ0ID0gZmFsc2U7XHJcbiAgICAgICAgY29uc3QgYnVmZmVyID0gW107XHJcbiAgICAgICAgbGV0IG9mZnNldFggPSAwO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5oYXNOZWdhdGl2ZURlcGVuZGVuY3lTcGFjZSkge1xyXG4gICAgICAgICAgICBidWZmZXIucHVzaCh7XHJcbiAgICAgICAgICAgICAgICBpbmRleDogLTEsXHJcbiAgICAgICAgICAgICAgICB4OiAwLFxyXG4gICAgICAgICAgICAgICAgd2lkdGg6IHRoaXMubmVnYXRpdmVTbG90V2lkdGgsXHJcbiAgICAgICAgICAgICAgICBsYWJlbDogJ04vQSdcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIG9mZnNldFggPSB0aGlzLm5lZ2F0aXZlU2xvdFdpZHRoO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPD0gbWF4U2xvdCArIDI7IGkrKykge1xyXG4gICAgICAgICAgICBidWZmZXIucHVzaCh7XHJcbiAgICAgICAgICAgICAgICBpbmRleDogaSxcclxuICAgICAgICAgICAgICAgIHg6IG9mZnNldFggKyBpICogdGhpcy5zY2FsZVNlbGVjdGVkLnB4LFxyXG4gICAgICAgICAgICAgICAgd2lkdGg6IHRoaXMuc2NhbGVTZWxlY3RlZC5weCxcclxuICAgICAgICAgICAgICAgIGxhYmVsOiB0aGlzLmdldFNsb3RMYWJlbChpKSA/PyAnRXJyb3InLFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuc2xvdHMgPSBidWZmZXI7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gZ2V0IGFsbCBwYXRocyBvZiBhcnJvd3NcclxuICAgIHByb3RlY3RlZCBnZXRBbGxEZXBlbmRlbmN5UGF0aHMoKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5kZXBlbmRlbmN5UGF0aHMgPSB0aGlzLnRhc2tzLmZsYXRNYXAoKHRhc2spOiBEZXBlbmRlbmN5UGF0aFtdID0+XHJcbiAgICAgICAgICAgICh0YXNrLmRlcGVuZGVuY2llcyA/PyBbXSkubWFwKFxyXG4gICAgICAgICAgICAgICAgKGRlcDogYW55KTogRGVwZW5kZW5jeVBhdGggPT4gKHtcclxuICAgICAgICAgICAgICAgICAgICBmcm9tOiBkZXAsXHJcbiAgICAgICAgICAgICAgICAgICAgdG86IHRhc2suaWQsXHJcbiAgICAgICAgICAgICAgICAgICAgaWQ6IGAke2RlcH0tPiR7dGFzay5pZH1gLFxyXG4gICAgICAgICAgICAgICAgICAgIHBhdGg6IHRoaXMuZ2V0RGVwZW5kZW5jeVBhdGgoZGVwLCB0YXNrLmlkKSxcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgIClcclxuICAgICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIGdldCBsYWJlbCBmb3IgZGF0ZSBoZWFkZXJcclxuICAgIHByaXZhdGUgZ2V0U2xvdExhYmVsKGluZGV4OiBudW1iZXIpOiBzdHJpbmcge1xyXG4gICAgICAgIGlmICh0aGlzLmRhdGFUeXBlID09PSAnY2FsZW5kYXInKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxhYmVsQ29udmVydGVyPy5nZXRMYWJlbENhbGVuZGFyKGluZGV4LCB0aGlzLmRlZmF1bHRTY2FsZSkgPz8gJ0Vycm9yJztcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXMubGFiZWxDb252ZXJ0ZXI/LmdldExhYmVsRHVyYXRpb24oaW5kZXgsIHRoaXMuZGVmYXVsdFNjYWxlKSA/PyAnRXJyb3InO1xyXG4gICAgfVxyXG59XHJcbiIsIjxkaXYgY2xhc3M9XCJnYW50dC1yb290XCIgW3N0eWxlLm1heC1oZWlnaHQucHhdPVwibGF5b3V0LnJvb3RNYXhIZWlnaHRcIiBbc3R5bGUubWluLWhlaWdodC5weF09XCIxMDBcIj5cbiAgICA8IS0tIFRPT0xCQVIgLS0+XG4gICAgPGRpdiBjbGFzcz1cInRvb2xiYXJcIiBbc3R5bGUuaGVpZ2h0LnB4XT1cImJ1dHRvbnNIZWlnaHRcIj5cbiAgICAgICAgPGRpdiAqbmdJZj1cImRhdGVNb2RlID09PSAndXRjJyB8fCBkYXRhVHlwZSA9PT0gJ2R1cmF0aW9uJ1wiPlxuICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImdhbnR0LWJ1dHRvblwiICpuZ0Zvcj1cImxldCBzIG9mIHNjYWxlc1wiIChjbGljayk9XCJzZXRTY2FsZShzKVwiIFtjbGFzcy5hY3RpdmVdPVwiZGVmYXVsdFNjYWxlID09PSBzXCI+XG4gICAgICAgICAgICAgICAge3sgcyB9fVxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2ICpuZ0lmPVwiZGF0ZU1vZGUgIT09ICd1dGMnICYmIGRhdGFUeXBlID09PSAnY2FsZW5kYXInXCI+XG4gICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiZ2FudHQtYnV0dG9uXCIgKm5nRm9yPVwibGV0IHMgb2Ygc2NhbGVzRGF0ZVwiIChjbGljayk9XCJzZXRTY2FsZShzKVwiXG4gICAgICAgICAgICAgICAgW2NsYXNzLmFjdGl2ZV09XCJkZWZhdWx0U2NhbGUgPT09IHNcIj5cbiAgICAgICAgICAgICAgICB7eyBzIH19XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxsYWJlbCAqbmdJZj1cIm1heFNsb3RzQWxlcnRcIiBzdHlsZT1cImNvbG9yOiByZWQ7XCI+XG4gICAgICAgICAgICBEYXRhIGlzIHRvbyBtYXNzaXZlIHRvIHNob3cgR2FudHQgc21vb3RobHksIHRyeSBjaGFuZ2luZyB0aGUgc2NhbGVcbiAgICAgICAgPC9sYWJlbD5cbiAgICA8L2Rpdj5cbiAgICA8IS0tIFRPT0xUSVAgLS0+XG4gICAgPGRpdiBjbGFzcz1cImdsb2JhbC10b29sdGlwXCIgW3N0eWxlLmRpc3BsYXldPVwidG9vbHRpcFRhc2sgPyAnYmxvY2snIDogJ25vbmUnXCI+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJ0b29sdGlwVGFzayBhcyB0YXNrXCI+XG4gICAgICAgICAgICA8ZGl2ICpuZ0Zvcj1cImxldCBjb2x1bW4gb2YgdmlzaWJsZVRvb2x0aXBDb2x1bW5zXCI+XG4gICAgICAgICAgICAgICAgPHN0cm9uZz57eyBjb2x1bW4/LnRpdGxlIH19Ojwvc3Ryb25nPlxuICAgICAgICAgICAgICAgIHt7IGNvbHVtbj8udmFsdWVHZXR0ZXIodGFzaykgfX1cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8L2Rpdj5cbiAgICA8IS0tIEJVVFRPTlMgRk9SIFNDUk9MTCBHQU5UVCAtLT5cbiAgICA8ZGl2ICpuZ0lmPVwiIW1heFNsb3RzQWxlcnQgJiYgbG9hZGluZyA9PT0gZmFsc2VcIiBjbGFzcz1cImZsb2F0aW5nLW5hdlwiPlxuICAgICAgICA8YnV0dG9uIGNsYXNzPVwibmF2LWJ0biBsZWZ0XCIgKG1vdXNlZG93bik9XCJzdGFydFNjcm9sbCgnbGVmdCcpXCJcbiAgICAgICAgICAgIChtb3VzZXVwKT1cInN0b3BTY3JvbGwoKVwiIChtb3VzZWxlYXZlKT1cInN0b3BTY3JvbGwoKVwiICNsZWZ0QnRuID5cbiAgICAgICAgICAgIOKAuVxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPGJ1dHRvbiBjbGFzcz1cIm5hdi1idG4gcmlnaHRcIiAobW91c2Vkb3duKT1cInN0YXJ0U2Nyb2xsKCdyaWdodCcpXCJcbiAgICAgICAgICAgIChtb3VzZXVwKT1cInN0b3BTY3JvbGwoKVwiIChtb3VzZWxlYXZlKT1cInN0b3BTY3JvbGwoKVwiICNyaWdodEJ0bj5cbiAgICAgICAgICAgIOKAulxuICAgICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgICA8IS0tIExPQURJTkcgLS0+XG4gICAgPGRpdiBjbGFzcz1cImxvYWRpbmctb3ZlcmxheVwiICpuZ0lmPVwibG9hZGluZ1wiIFtzdHlsZS50b3BdPVwiJzUwJSdcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInNwaW5uZXJcIj48L2Rpdj5cbiAgICA8L2Rpdj5cbiAgICA8IS0tIFNJTkdMRSBWRVJUSUNBTCBTQ1JPTEwgLS0+XG4gICAgPGRpdiBjbGFzcz1cImdhbnR0LWJvZHlcIiAjZ2FudHRCb2R5U2Nyb2xsPlxuICAgICAgICA8IS0tIExFRlQgUEFORUwgLS0+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJsZWZ0LXBhbmVsXCIgI2xlZnRQYW5lbD5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0YXNrLXJvdyBoZWFkZXJcIiBbc3R5bGUuaGVpZ2h0LnB4XT1cImhlYWRlckhlaWdodFwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjZWxsXCIgKm5nRm9yPVwibGV0IGNvbHVtbiBvZiB2aXNpYmxlR3JpZENvbHVtbnNcIiBbc3R5bGUud2lkdGgucHhdPVwiY29sdW1uLndpZHRoIHx8IDEyMFwiPlxuICAgICAgICAgICAgICAgICAgICB7eyBjb2x1bW4/LnRpdGxlIH19XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0YXNrLXJvd1wiICpuZ0Zvcj1cImxldCB0YXNrIG9mIHRhc2tzXCIgW3N0eWxlLmhlaWdodC5weF09XCJyb3dIZWlnaHRcIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJzZWxlY3RUYXNrKHRhc2ssIHRydWUpOyAkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxuICAgICAgICAgICAgICAgIFtjbGFzcy5oaWdobGlnaHRlZC1yb3ddPVwic2VsZWN0ZWRUYXNrSWQgPT09IHRhc2suaWRcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY2VsbFwiICpuZ0Zvcj1cImxldCBjb2x1bW4gb2YgdmlzaWJsZUdyaWRDb2x1bW5zXCIgW3N0eWxlLndpZHRoLnB4XT1cImNvbHVtbi53aWR0aCB8fCAxMjBcIj5cbiAgICAgICAgICAgICAgICAgICAge3sgY29sdW1uPy52YWx1ZUdldHRlcih0YXNrKSB9fVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8IS0tIFJFU0laRVIgLS0+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJyZXNpemVyXCIgW3N0eWxlLmhlaWdodC5weF09XCJsYXlvdXQucmVzaXplckhlaWdodFwiIChtb3VzZWRvd24pPVwic3RhcnRSZXNpemUoJGV2ZW50KVwiPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPCEtLSBSSUdIVCBQQU5FTCAtLT5cbiAgICAgICAgPGRpdiBjbGFzcz1cInJpZ2h0LXBhbmVsXCIgKm5nSWY9XCIhbWF4U2xvdHNBbGVydFwiPlxuICAgICAgICAgICAgPCEtLSBUSU1FTElORSAtLT5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0aW1lbGluZS1oZWFkZXJcIiAjdGltZWxpbmVIZWFkZXI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRpbWVsaW5lLXNsb3RcIiAqbmdGb3I9XCJsZXQgc2xvdCBvZiBzbG90c1wiIFtzdHlsZS53aWR0aC5weF09XCJzbG90LndpZHRoXCI+XG4gICAgICAgICAgICAgICAgICAgIHt7IHNsb3QubGFiZWwgfX1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPCEtLSBIT1JJWk9OVEFMIFNDUk9MTCBPTkxZIC0tPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImhvcml6b250YWwtc2Nyb2xsXCIgKHNjcm9sbCk9XCJvbkhvcml6b250YWxTY3JvbGwoJGV2ZW50KVwiICNnYW50dFNjcm9sbD5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZ2FudHQtY29udGVudFwiICNnYW50dENvbnRlbnQ+XG4gICAgICAgICAgICAgICAgICAgIDwhLS0gR1JJRCAtLT5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImdyaWQtbGF5ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgKm5nRm9yPVwibGV0IHNsb3Qgb2Ygc2xvdHM7IGxldCBpID0gaW5kZXg7IHRyYWNrQnk6IHRyYWNrQnlJbmRleFwiIGNsYXNzPVwiZ3JpZC1saW5lXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUubGVmdC5weF09XCJzbG90LnggLSAxXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gZmluYWwgdmVydGljYWwgbGluZSAtLT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJncmlkLWxpbmVcIiBbc3R5bGUubGVmdC5weF09XCJnYW50dFdpZHRoIC0gMVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8IS0tIGhvcml6b250YWwgbGluZXMgLS0+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaG9yaXpvbnRhbC1ncmlkLWxheWVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiAqbmdGb3I9XCJsZXQgdGFzayBvZiB0YXNrczsgbGV0IGkgPSBpbmRleDsgdHJhY2tCeTogdHJhY2tCeUluZGV4XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJob3Jpem9udGFsLWxpbmVcIiBbc3R5bGUudG9wLnB4XT1cImdldEdyaWRUb3AoaSlcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIGZpbmFsIGhvcml6b250YWwgbGluZSAtLT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaG9yaXpvbnRhbC1saW5lXCIgW3N0eWxlLnRvcC5weF09XCJnYW50dEhlaWdodFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8IS0tIFRBU0tTIC0tPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGFza3MtbGF5ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgKm5nRm9yPVwibGV0IHRhc2sgb2Ygdmlld1Rhc2tzOyBsZXQgaSA9IGluZGV4OyB0cmFja0J5OiB0cmFja0J5SW5kZXhcIiBjbGFzcz1cInRhc2tcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChtb3VzZWVudGVyKT1cInNob3dUb29sdGlwKCRldmVudCwgdGFzaylcIiAobW91c2VsZWF2ZSk9XCJoaWRlVG9vbHRpcCgpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwic2VsZWN0VGFzayh0YXNrLCBmYWxzZSk7ICRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW2NsYXNzLmhpZ2hsaWdodGVkLXRhc2tdPVwic2VsZWN0ZWRUYXNrSWQgPT09IHRhc2suaWRcIiBbc3R5bGUubGVmdC5weF09XCJ0YXNrLnhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS50b3AucHhdPVwidGFzay55XCIgW3N0eWxlLndpZHRoLnB4XT1cInRhc2sud2lkdGhcIiBbc3R5bGUuaGVpZ2h0LnB4XT1cInRhc2suaGVpZ2h0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRhc2stbGFiZWxcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgdGFzay5sYWJlbCB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8IS0tIERFUEVOREVOQ0lFUyAtLT5cbiAgICAgICAgICAgICAgICAgICAgPHN2ZyBjbGFzcz1cImRlcGVuZGVuY2llcy1zdmdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkZWZzPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXJrZXIgaWQ9XCJhcnJvd1wiIHZpZXdCb3g9XCIwIDAgMTAgMTBcIiByZWZYPVwiOVwiIHJlZlk9XCI1XCIgbWFya2VyV2lkdGg9XCI2XCIgbWFya2VySGVpZ2h0PVwiNlwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yaWVudD1cImF1dG9cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZD1cIk0gMCAwIEwgMTAgNSBMIDAgMTAgelwiIGZpbGw9XCIjODY4ZDk3XCIgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hcmtlcj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGVmcz5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxnIGNsYXNzPVwiZGVwZW5kZW5jaWVzLW5vcm1hbFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoICpuZ0Zvcj1cImxldCBkZXAgb2YgZGVwZW5kZW5jeVBhdGhzXCIgW2F0dHIuZF09XCJkZXAucGF0aFwiIGNsYXNzPVwiZGVwZW5kZW5jeVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtjbGFzcy5oaWRkZW5dPVwiaG92ZXJlZERlcGVuZGVuY3lJZHMuaGFzKGRlcC5pZClcIiBtYXJrZXItZW5kPVwidXJsKCNhcnJvdylcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3BhdGg+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2c+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZyBjbGFzcz1cImRlcGVuZGVuY2llcy1oaWdobGlnaHRlZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoICpuZ0Zvcj1cImxldCBkZXAgb2YgZGVwZW5kZW5jeVBhdGhzXCIgW2F0dHIuZF09XCJkZXAucGF0aFwiIGNsYXNzPVwiaGlnaGxpZ2h0ZWQtZGVwZW5kZW5jeVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtjbGFzcy5oaWRkZW5dPVwiIWhvdmVyZWREZXBlbmRlbmN5SWRzLmhhcyhkZXAuaWQpXCIgbWFya2VyLWVuZD1cInVybCgjYXJyb3cpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9wYXRoPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9nPlxuICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInJpZ2h0LXBhbmVsLWRlYWRcIiAqbmdJZj1cIm1heFNsb3RzQWxlcnRcIj48L2Rpdj5cbiAgICA8L2Rpdj5cbjwvZGl2PiJdfQ==
@@ -1,107 +0,0 @@
1
- export class SlotIndexToDateLabelConverter {
2
- constructor(dateMode, originDate, slotSeconds, hasNegativeDependencySpace) {
3
- this.dateMode = dateMode;
4
- this.originDate = originDate;
5
- this.slotSeconds = slotSeconds;
6
- this.hasNegativeDependencySpace = hasNegativeDependencySpace;
7
- this.initFormatters();
8
- }
9
- initFormatters() {
10
- this.timeFormatter = new Intl.DateTimeFormat([], {
11
- timeZone: this.dateMode === 'utc' ? 'UTC' : undefined,
12
- day: '2-digit',
13
- month: '2-digit',
14
- year: 'numeric',
15
- hour: '2-digit',
16
- minute: '2-digit',
17
- hour12: false
18
- });
19
- this.dayFormatter = new Intl.DateTimeFormat([], {
20
- timeZone: this.dateMode === 'utc' ? 'UTC' : undefined,
21
- day: '2-digit',
22
- month: '2-digit',
23
- year: 'numeric'
24
- });
25
- }
26
- get slotMs() {
27
- return this.slotSeconds * 1000;
28
- }
29
- indexToDate(index) {
30
- const realIndex = this.hasNegativeDependencySpace && index > 0 ? index - 1 : index;
31
- return new Date(this.originDate + realIndex * this.slotMs);
32
- }
33
- getLabelCalendar(index, scale) {
34
- if (this.hasNegativeDependencySpace && index === 0) {
35
- return 'N/A';
36
- }
37
- const date = this.indexToDate(index);
38
- switch (scale) {
39
- case '1m':
40
- case '10m':
41
- case '30m':
42
- case 'hour':
43
- case '6 hours':
44
- case '12 hours':
45
- return this.formatTime(date);
46
- case 'day':
47
- return this.formatDay(date);
48
- case 'week':
49
- return this.formatRange(date, 7);
50
- case 'month':
51
- return this.formatMonthRange(date);
52
- case 'year':
53
- return this.formatYearRange(date);
54
- default:
55
- return '';
56
- }
57
- }
58
- getLabelDuration(index, scale) {
59
- if (index === -1) {
60
- return 'N/A';
61
- }
62
- switch (scale) {
63
- case '1m':
64
- return `${index * 1}m`;
65
- case '10m':
66
- return `${index * 10}m`;
67
- case '30m':
68
- return `${index * 30}m`;
69
- case 'hour':
70
- return `${index}h`;
71
- case '6 hours':
72
- return `${index * 6}h`;
73
- case '12 hours':
74
- return `${index * 12}h`;
75
- case 'day':
76
- return `${index}D`;
77
- case 'week':
78
- return `${index * 7}D - ${index * 7 + 7}D`;
79
- case 'month':
80
- return `${index * 30}D - ${index * 30 + 30}D`;
81
- case 'year':
82
- return `${index * 365}D - ${index * 365 + 365}D`;
83
- default:
84
- return '';
85
- }
86
- }
87
- formatTime(date) {
88
- return this.timeFormatter.format(date);
89
- }
90
- formatDay(date) {
91
- return this.dayFormatter.format(date);
92
- }
93
- formatRange(start, days) {
94
- const end = new Date(start);
95
- end.setDate(end.getDate() + days);
96
- return `${start.toLocaleDateString()} - ${end.toLocaleDateString()}`;
97
- }
98
- formatMonthRange(start) {
99
- const date = new Date(start);
100
- date.setDate(1);
101
- return date.toLocaleDateString();
102
- }
103
- formatYearRange(start) {
104
- return `${start.toLocaleDateString()}`;
105
- }
106
- }
107
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2FudHQtbGl0ZS5oZWxwZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9nYW50dC1saXRlL3NyYy9saWIvZ2FudHQtbGl0ZS5oZWxwZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsTUFBTSxPQUFPLDZCQUE2QjtJQUd0QyxZQUNZLFFBQWtCLEVBQ2xCLFVBQWtCLEVBQ2xCLFdBQW1CLEVBQ25CLDBCQUFtQztRQUhuQyxhQUFRLEdBQVIsUUFBUSxDQUFVO1FBQ2xCLGVBQVUsR0FBVixVQUFVLENBQVE7UUFDbEIsZ0JBQVcsR0FBWCxXQUFXLENBQVE7UUFDbkIsK0JBQTBCLEdBQTFCLDBCQUEwQixDQUFTO1FBRTNDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBRU8sY0FBYztRQUN0QixJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxFQUFFLEVBQUU7WUFDN0MsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFNBQVM7WUFDckQsR0FBRyxFQUFFLFNBQVM7WUFDZCxLQUFLLEVBQUUsU0FBUztZQUNoQixJQUFJLEVBQUUsU0FBUztZQUNmLElBQUksRUFBRSxTQUFTO1lBQ2YsTUFBTSxFQUFFLFNBQVM7WUFDakIsTUFBTSxFQUFFLEtBQUs7U0FDaEIsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsRUFBRSxFQUFFO1lBQzVDLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUSxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxTQUFTO1lBQ3JELEdBQUcsRUFBRSxTQUFTO1lBQ2QsS0FBSyxFQUFFLFNBQVM7WUFDaEIsSUFBSSxFQUFFLFNBQVM7U0FDbEIsQ0FBQyxDQUFDO0lBQ1As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QUFVO1FBQ3pCLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUVPLFNBQVMsQ0FBQyxJQUFVO1FBQ3hCLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVPLFdBQVcsQ0FBQyxLQUFXLEVBQUUsSUFBWTtRQUN6QyxNQUFNLEdBQUcsR0FBRyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM1QixHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQztRQUNsQyxPQUFPLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixFQUFFLE1BQU0sR0FBRyxDQUFDLGtCQUFrQixFQUFFLEVBQUUsQ0FBQztJQUN6RSxDQUFDO0lBRUssZ0JBQWdCLENBQUMsS0FBVztRQUM5QixNQUFNLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM3QixJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7SUFDckMsQ0FBQztJQUVPLGVBQWUsQ0FBQyxLQUFXO1FBQy9CLE9BQU8sR0FBRyxLQUFLLENBQUMsa0JBQWtCLEVBQUUsRUFBRSxDQUFDO0lBQzNDLENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERhdGVNb2RlLCBHYW50dFNjYWxlLCBTY2FsZUNvbmZpZyB9IGZyb20gXCIuL2dhbnR0LWxpdGUubW9kZWxcIjtcblxuZXhwb3J0IGNsYXNzIFNsb3RJbmRleFRvRGF0ZUxhYmVsQ29udmVydGVyIHtcbiAgICBwcml2YXRlIHRpbWVGb3JtYXR0ZXIhOiBJbnRsLkRhdGVUaW1lRm9ybWF0O1xuICAgIHByaXZhdGUgZGF5Rm9ybWF0dGVyITogSW50bC5EYXRlVGltZUZvcm1hdDtcbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJpdmF0ZSBkYXRlTW9kZTogRGF0ZU1vZGUsXG4gICAgICAgIHByaXZhdGUgb3JpZ2luRGF0ZTogbnVtYmVyLFxuICAgICAgICBwcml2YXRlIHNsb3RTZWNvbmRzOiBudW1iZXIsXG4gICAgICAgIHByaXZhdGUgaGFzTmVnYXRpdmVEZXBlbmRlbmN5U3BhY2U6IGJvb2xlYW5cbiAgICApIHtcbiAgICAgICAgdGhpcy5pbml0Rm9ybWF0dGVycygpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaW5pdEZvcm1hdHRlcnMoKTogdm9pZCB7XG4gICAgdGhpcy50aW1lRm9ybWF0dGVyID0gbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQoW10sIHtcbiAgICAgICAgdGltZVpvbmU6IHRoaXMuZGF0ZU1vZGUgPT09ICd1dGMnID8gJ1VUQycgOiB1bmRlZmluZWQsXG4gICAgICAgIGRheTogJzItZGlnaXQnLFxuICAgICAgICBtb250aDogJzItZGlnaXQnLFxuICAgICAgICB5ZWFyOiAnbnVtZXJpYycsXG4gICAgICAgIGhvdXI6ICcyLWRpZ2l0JyxcbiAgICAgICAgbWludXRlOiAnMi1kaWdpdCcsXG4gICAgICAgIGhvdXIxMjogZmFsc2VcbiAgICB9KTtcblxuICAgIHRoaXMuZGF5Rm9ybWF0dGVyID0gbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQoW10sIHtcbiAgICAgICAgdGltZVpvbmU6IHRoaXMuZGF0ZU1vZGUgPT09ICd1dGMnID8gJ1VUQycgOiB1bmRlZmluZWQsXG4gICAgICAgIGRheTogJzItZGlnaXQnLFxuICAgICAgICBtb250aDogJzItZGlnaXQnLFxuICAgICAgICB5ZWFyOiAnbnVtZXJpYydcbiAgICB9KTtcbn1cblxuICAgIHByaXZhdGUgZ2V0IHNsb3RNcygpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5zbG90U2Vjb25kcyAqIDEwMDA7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbmRleFRvRGF0ZShpbmRleDogbnVtYmVyKTogRGF0ZSB7XG4gICAgICAgIGNvbnN0IHJlYWxJbmRleCA9IHRoaXMuaGFzTmVnYXRpdmVEZXBlbmRlbmN5U3BhY2UgJiYgaW5kZXggPiAwID8gaW5kZXggLSAxIDogaW5kZXg7XG4gICAgICAgIHJldHVybiBuZXcgRGF0ZSh0aGlzLm9yaWdpbkRhdGUgKyByZWFsSW5kZXggKiB0aGlzLnNsb3RNcyk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldExhYmVsQ2FsZW5kYXIoaW5kZXg6IG51bWJlciwgc2NhbGU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIGlmICh0aGlzLmhhc05lZ2F0aXZlRGVwZW5kZW5jeVNwYWNlICYmIGluZGV4ID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gJ04vQSc7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkYXRlID0gdGhpcy5pbmRleFRvRGF0ZShpbmRleCk7XG4gICAgICAgIHN3aXRjaCAoc2NhbGUpIHtcbiAgICAgICAgICAgIGNhc2UgJzFtJzpcbiAgICAgICAgICAgIGNhc2UgJzEwbSc6XG4gICAgICAgICAgICBjYXNlICczMG0nOlxuICAgICAgICAgICAgY2FzZSAnaG91cic6XG4gICAgICAgICAgICBjYXNlICc2IGhvdXJzJzpcbiAgICAgICAgICAgIGNhc2UgJzEyIGhvdXJzJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5mb3JtYXRUaW1lKGRhdGUpO1xuICAgICAgICAgICAgY2FzZSAnZGF5JzpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5mb3JtYXREYXkoZGF0ZSk7XG4gICAgICAgICAgICBjYXNlICd3ZWVrJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5mb3JtYXRSYW5nZShkYXRlLCA3KTtcbiAgICAgICAgICAgIGNhc2UgJ21vbnRoJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5mb3JtYXRNb250aFJhbmdlKGRhdGUpO1xuICAgICAgICAgICAgY2FzZSAneWVhcic6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZm9ybWF0WWVhclJhbmdlKGRhdGUpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0TGFiZWxEdXJhdGlvbihpbmRleDogbnVtYmVyLCBzY2FsZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKGluZGV4ID09PSAtMSkge1xuICAgICAgICAgICAgcmV0dXJuICdOL0EnO1xuICAgICAgICB9XG5cbiAgICAgICAgc3dpdGNoIChzY2FsZSkge1xuICAgICAgICAgICAgY2FzZSAnMW0nOlxuICAgICAgICAgICAgICAgIHJldHVybiBgJHtpbmRleCAqIDF9bWA7XG4gICAgICAgICAgICBjYXNlICcxMG0nOlxuICAgICAgICAgICAgICAgIHJldHVybiBgJHtpbmRleCAqIDEwfW1gO1xuICAgICAgICAgICAgY2FzZSAnMzBtJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gYCR7aW5kZXggKiAzMH1tYDtcbiAgICAgICAgICAgIGNhc2UgJ2hvdXInOlxuICAgICAgICAgICAgICAgIHJldHVybiBgJHtpbmRleH1oYDtcbiAgICAgICAgICAgIGNhc2UgJzYgaG91cnMnOlxuICAgICAgICAgICAgICAgIHJldHVybiBgJHtpbmRleCAqIDZ9aGA7XG4gICAgICAgICAgICBjYXNlICcxMiBob3Vycyc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGAke2luZGV4ICogMTJ9aGA7XG4gICAgICAgICAgICBjYXNlICdkYXknOlxuICAgICAgICAgICAgICAgIHJldHVybiBgJHtpbmRleH1EYDtcbiAgICAgICAgICAgIGNhc2UgJ3dlZWsnOlxuICAgICAgICAgICAgICAgIHJldHVybiBgJHtpbmRleCAqIDd9RCAtICR7aW5kZXggKiA3ICsgN31EYDtcbiAgICAgICAgICAgIGNhc2UgJ21vbnRoJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gYCR7aW5kZXggKiAzMH1EIC0gJHtpbmRleCAqIDMwICsgMzB9RGA7XG4gICAgICAgICAgICBjYXNlICd5ZWFyJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gYCR7aW5kZXggKiAzNjV9RCAtICR7aW5kZXggKiAzNjUgKyAzNjV9RGA7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZm9ybWF0VGltZShkYXRlOiBEYXRlKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGltZUZvcm1hdHRlci5mb3JtYXQoZGF0ZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBmb3JtYXREYXkoZGF0ZTogRGF0ZSk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLmRheUZvcm1hdHRlci5mb3JtYXQoZGF0ZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBmb3JtYXRSYW5nZShzdGFydDogRGF0ZSwgZGF5czogbnVtYmVyKTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgZW5kID0gbmV3IERhdGUoc3RhcnQpO1xuICAgICAgICBlbmQuc2V0RGF0ZShlbmQuZ2V0RGF0ZSgpICsgZGF5cyk7XG4gICAgICAgIHJldHVybiBgJHtzdGFydC50b0xvY2FsZURhdGVTdHJpbmcoKX0gLSAke2VuZC50b0xvY2FsZURhdGVTdHJpbmcoKX1gO1xuICAgIH1cblxuICBwcml2YXRlIGZvcm1hdE1vbnRoUmFuZ2Uoc3RhcnQ6IERhdGUpOiBzdHJpbmcge1xuICAgICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoc3RhcnQpO1xuICAgICAgICBkYXRlLnNldERhdGUoMSk7XG4gICAgICAgIHJldHVybiBkYXRlLnRvTG9jYWxlRGF0ZVN0cmluZygpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZm9ybWF0WWVhclJhbmdlKHN0YXJ0OiBEYXRlKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIGAke3N0YXJ0LnRvTG9jYWxlRGF0ZVN0cmluZygpfWA7XG4gICAgfVxufVxuIl19