@tolle_/tolle-ui 18.2.29 → 18.2.30
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/esm2022/lib/accordion-item.component.mjs +5 -11
- package/esm2022/lib/accordion.component.mjs +4 -9
- package/esm2022/lib/alert-dialog-dynamic.component.mjs +5 -10
- package/esm2022/lib/alert-dialog.component.mjs +44 -59
- package/esm2022/lib/alert.component.mjs +5 -11
- package/esm2022/lib/aspect-ratio.component.mjs +119 -0
- package/esm2022/lib/attachment.component.mjs +334 -0
- package/esm2022/lib/avatar-fallback.component.mjs +3 -3
- package/esm2022/lib/avatar.component.mjs +4 -9
- package/esm2022/lib/badge.component.mjs +4 -9
- package/esm2022/lib/breadcrumb-item.component.mjs +3 -3
- package/esm2022/lib/breadcrumb-link.component.mjs +3 -3
- package/esm2022/lib/breadcrumb-separator.component.mjs +3 -3
- package/esm2022/lib/breadcrumb.component.mjs +3 -3
- package/esm2022/lib/bubble.component.mjs +301 -0
- package/esm2022/lib/button.component.mjs +5 -11
- package/esm2022/lib/calendar.component.mjs +5 -11
- package/esm2022/lib/card.component.mjs +14 -43
- package/esm2022/lib/carousel/carousel.component.mjs +5 -12
- package/esm2022/lib/chain-of-thought.component.mjs +380 -0
- package/esm2022/lib/chart-pie.component.mjs +386 -0
- package/esm2022/lib/chart.component.mjs +1146 -0
- package/esm2022/lib/chart.service.mjs +555 -0
- package/esm2022/lib/checkbox.component.mjs +5 -11
- package/esm2022/lib/checkpoint.component.mjs +134 -0
- package/esm2022/lib/collapsible.component.mjs +4 -11
- package/esm2022/lib/combobox.component.mjs +372 -0
- package/esm2022/lib/command-dialog.component.mjs +164 -0
- package/esm2022/lib/command.component.mjs +514 -0
- package/esm2022/lib/command.service.mjs +130 -0
- package/esm2022/lib/confirmation.component.mjs +219 -0
- package/esm2022/lib/context-menu-trigger.directive.mjs +36 -0
- package/esm2022/lib/context-menu.component.mjs +460 -0
- package/esm2022/lib/context-menu.service.mjs +121 -0
- package/esm2022/lib/context.component.mjs +377 -0
- package/esm2022/lib/conversation.component.mjs +442 -0
- package/esm2022/lib/country-selector.component.mjs +5 -11
- package/esm2022/lib/data-table.component.mjs +59 -12
- package/esm2022/lib/date-picker.component.mjs +251 -198
- package/esm2022/lib/date-range-picker.component.mjs +224 -116
- package/esm2022/lib/date-time-picker.component.mjs +506 -0
- package/esm2022/lib/direction.component.mjs +79 -0
- package/esm2022/lib/dropdown-item.component.mjs +3 -3
- package/esm2022/lib/dropdown-label.component.mjs +3 -3
- package/esm2022/lib/dropdown-menu.component.mjs +3 -3
- package/esm2022/lib/dropdown-separator.component.mjs +3 -3
- package/esm2022/lib/dropdown-trigger.directive.mjs +6 -4
- package/esm2022/lib/empty-state.component.mjs +4 -9
- package/esm2022/lib/field.component.mjs +394 -0
- package/esm2022/lib/hover-card.component.mjs +6 -16
- package/esm2022/lib/inline-citation.component.mjs +263 -0
- package/esm2022/lib/input-group.component.mjs +418 -0
- package/esm2022/lib/input.component.mjs +5 -11
- package/esm2022/lib/item.component.mjs +243 -0
- package/esm2022/lib/kbd.component.mjs +82 -0
- package/esm2022/lib/label.component.mjs +4 -9
- package/esm2022/lib/marker.component.mjs +135 -0
- package/esm2022/lib/masked-input.component.mjs +5 -11
- package/esm2022/lib/menubar.component.mjs +683 -0
- package/esm2022/lib/message-scroller.component.mjs +353 -0
- package/esm2022/lib/message-scroller.service.mjs +157 -0
- package/esm2022/lib/message.component.mjs +228 -0
- package/esm2022/lib/model-selector.component.mjs +310 -0
- package/esm2022/lib/multi-select.component.mjs +155 -72
- package/esm2022/lib/native-select.component.mjs +201 -0
- package/esm2022/lib/navigation-menu.component.mjs +642 -0
- package/esm2022/lib/otp-group.component.mjs +3 -3
- package/esm2022/lib/otp-slot.component.mjs +4 -9
- package/esm2022/lib/otp.component.mjs +5 -11
- package/esm2022/lib/pagination.component.mjs +7 -10
- package/esm2022/lib/plan.component.mjs +335 -0
- package/esm2022/lib/popover-content.component.mjs +4 -9
- package/esm2022/lib/popover.component.mjs +15 -13
- package/esm2022/lib/progress.component.mjs +4 -9
- package/esm2022/lib/prompt-input.component.mjs +526 -0
- package/esm2022/lib/queue.component.mjs +280 -0
- package/esm2022/lib/radio-group.component.mjs +6 -13
- package/esm2022/lib/radio-item.component.mjs +4 -9
- package/esm2022/lib/range-calendar.component.mjs +5 -11
- package/esm2022/lib/reasoning.component.mjs +335 -0
- package/esm2022/lib/resizable.component.mjs +219 -0
- package/esm2022/lib/segment.component.mjs +17 -7
- package/esm2022/lib/select-group.component.mjs +4 -8
- package/esm2022/lib/select-item.component.mjs +4 -9
- package/esm2022/lib/select-separator.component.mjs +4 -8
- package/esm2022/lib/select.component.mjs +133 -49
- package/esm2022/lib/separator.component.mjs +4 -9
- package/esm2022/lib/sheet.component.mjs +38 -56
- package/esm2022/lib/shimmer.component.mjs +84 -0
- package/esm2022/lib/sidebar.component.mjs +11 -1
- package/esm2022/lib/skeleton.component.mjs +4 -9
- package/esm2022/lib/sources.component.mjs +452 -0
- package/esm2022/lib/spinner.component.mjs +68 -0
- package/esm2022/lib/suggestion.component.mjs +207 -0
- package/esm2022/lib/switch.component.mjs +5 -11
- package/esm2022/lib/table.component.mjs +213 -0
- package/esm2022/lib/tabs.component.mjs +4 -11
- package/esm2022/lib/tag-input.component.mjs +5 -11
- package/esm2022/lib/task.component.mjs +359 -0
- package/esm2022/lib/textarea.component.mjs +5 -11
- package/esm2022/lib/theme.service.mjs +17 -6
- package/esm2022/lib/time-picker.component.mjs +923 -0
- package/esm2022/lib/toast.service.mjs +3 -2
- package/esm2022/lib/toaster.component.mjs +76 -39
- package/esm2022/lib/toggle-group.component.mjs +4 -9
- package/esm2022/lib/toggle.component.mjs +5 -11
- package/esm2022/lib/tool.component.mjs +462 -0
- package/esm2022/lib/typography.component.mjs +83 -0
- package/esm2022/lib/utils/color.mjs +140 -19
- package/esm2022/public-api.mjs +61 -1
- package/fesm2022/tolle-ui.mjs +16453 -1024
- package/fesm2022/tolle-ui.mjs.map +1 -1
- package/lib/alert-dialog.component.d.ts +10 -2
- package/lib/aspect-ratio.component.d.ts +20 -0
- package/lib/attachment.component.d.ts +101 -0
- package/lib/bubble.component.d.ts +112 -0
- package/lib/chain-of-thought.component.d.ts +166 -0
- package/lib/chart-pie.component.d.ts +108 -0
- package/lib/chart.component.d.ts +369 -0
- package/lib/chart.service.d.ts +222 -0
- package/lib/checkpoint.component.d.ts +51 -0
- package/lib/combobox.component.d.ts +90 -0
- package/lib/command-dialog.component.d.ts +53 -0
- package/lib/command.component.d.ts +189 -0
- package/lib/command.service.d.ts +67 -0
- package/lib/confirmation.component.d.ts +70 -0
- package/lib/context-menu-trigger.directive.d.ts +12 -0
- package/lib/context-menu.component.d.ts +41 -0
- package/lib/context-menu.service.d.ts +38 -0
- package/lib/context.component.d.ts +134 -0
- package/lib/conversation.component.d.ts +165 -0
- package/lib/data-table.component.d.ts +26 -1
- package/lib/date-picker.component.d.ts +72 -11
- package/lib/date-range-picker.component.d.ts +63 -6
- package/lib/date-time-picker.component.d.ts +119 -0
- package/lib/direction.component.d.ts +45 -0
- package/lib/field.component.d.ts +201 -0
- package/lib/inline-citation.component.d.ts +103 -0
- package/lib/input-group.component.d.ts +150 -0
- package/lib/item.component.d.ts +154 -0
- package/lib/kbd.component.d.ts +50 -0
- package/lib/marker.component.d.ts +58 -0
- package/lib/menubar.component.d.ts +247 -0
- package/lib/message-scroller.component.d.ts +159 -0
- package/lib/message-scroller.service.d.ts +73 -0
- package/lib/message.component.d.ts +128 -0
- package/lib/model-selector.component.d.ts +103 -0
- package/lib/multi-select.component.d.ts +66 -14
- package/lib/native-select.component.d.ts +57 -0
- package/lib/navigation-menu.component.d.ts +230 -0
- package/lib/plan.component.d.ts +120 -0
- package/lib/popover.component.d.ts +1 -0
- package/lib/prompt-input.component.d.ts +194 -0
- package/lib/queue.component.d.ts +106 -0
- package/lib/reasoning.component.d.ts +127 -0
- package/lib/resizable.component.d.ts +43 -0
- package/lib/segment.component.d.ts +13 -3
- package/lib/select.component.d.ts +37 -5
- package/lib/sheet.component.d.ts +3 -0
- package/lib/shimmer.component.d.ts +38 -0
- package/lib/sidebar.component.d.ts +2 -0
- package/lib/sources.component.d.ts +156 -0
- package/lib/spinner.component.d.ts +29 -0
- package/lib/suggestion.component.d.ts +96 -0
- package/lib/table.component.d.ts +106 -0
- package/lib/task.component.d.ts +151 -0
- package/lib/theme.service.d.ts +9 -0
- package/lib/time-picker.component.d.ts +243 -0
- package/lib/toast.service.d.ts +3 -1
- package/lib/toaster.component.d.ts +26 -9
- package/lib/tool.component.d.ts +158 -0
- package/lib/typography.component.d.ts +32 -0
- package/lib/utils/color.d.ts +19 -5
- package/package.json +1 -1
- package/public-api.d.ts +50 -0
- package/registry/docs-content.json +8480 -1542
- package/registry/llms-full.txt +2679 -319
- package/registry/llms.txt +43 -4
- package/registry/manifest.json +9090 -1742
- package/registry/r/accordion-item.json +1 -1
- package/registry/r/accordion.json +1 -1
- package/registry/r/alert-dialog-dynamic.json +1 -1
- package/registry/r/alert-dialog.json +1 -1
- package/registry/r/alert.json +1 -1
- package/registry/r/attachment.json +23 -0
- package/registry/r/avatar-fallback.json +1 -1
- package/registry/r/avatar.json +1 -1
- package/registry/r/badge.json +1 -1
- package/registry/r/breadcrumb-item.json +1 -1
- package/registry/r/breadcrumb-link.json +1 -1
- package/registry/r/breadcrumb-separator.json +1 -1
- package/registry/r/breadcrumb.json +1 -1
- package/registry/r/bubble.json +23 -0
- package/registry/r/button.json +1 -1
- package/registry/r/calendar.json +1 -1
- package/registry/r/card.json +1 -1
- package/registry/r/carousel.json +1 -1
- package/registry/r/chain-of-thought.json +23 -0
- package/registry/r/chart-pie.json +30 -0
- package/registry/r/chart.json +28 -0
- package/registry/r/checkbox.json +1 -1
- package/registry/r/checkpoint.json +23 -0
- package/registry/r/collapsible.json +1 -1
- package/registry/r/combobox.json +31 -0
- package/registry/r/command-dialog.json +21 -0
- package/registry/r/command.json +26 -0
- package/registry/r/confirmation.json +23 -0
- package/registry/r/context.json +26 -0
- package/registry/r/conversation.json +23 -0
- package/registry/r/country-selector.json +1 -1
- package/registry/r/data-table.json +1 -1
- package/registry/r/date-picker.json +4 -4
- package/registry/r/date-range-picker.json +3 -3
- package/registry/r/date-time-picker.json +28 -0
- package/registry/r/direction.json +16 -0
- package/registry/r/dropdown-item.json +1 -1
- package/registry/r/dropdown-label.json +1 -1
- package/registry/r/dropdown-menu.json +1 -1
- package/registry/r/dropdown-separator.json +1 -1
- package/registry/r/dropdown-trigger.json +1 -1
- package/registry/r/empty-state.json +1 -1
- package/registry/r/field.json +23 -0
- package/registry/r/hover-card.json +1 -1
- package/registry/r/inline-citation.json +26 -0
- package/registry/r/input-group.json +23 -0
- package/registry/r/input.json +1 -1
- package/registry/r/item.json +23 -0
- package/registry/r/kbd.json +23 -0
- package/registry/r/label.json +1 -1
- package/registry/r/marker.json +23 -0
- package/registry/r/masked-input.json +1 -1
- package/registry/r/menubar.json +24 -0
- package/registry/r/message-scroller.json +26 -0
- package/registry/r/message.json +23 -0
- package/registry/r/model-selector.json +32 -0
- package/registry/r/multi-select.json +2 -2
- package/registry/r/native-select.json +23 -0
- package/registry/r/navigation-menu.json +24 -0
- package/registry/r/otp-group.json +1 -1
- package/registry/r/otp-slot.json +1 -1
- package/registry/r/otp.json +1 -1
- package/registry/r/pagination.json +3 -2
- package/registry/r/plan.json +23 -0
- package/registry/r/popover-content.json +1 -1
- package/registry/r/popover.json +1 -1
- package/registry/r/progress.json +1 -1
- package/registry/r/prompt-input.json +23 -0
- package/registry/r/queue.json +23 -0
- package/registry/r/radio-group.json +1 -1
- package/registry/r/radio-item.json +1 -1
- package/registry/r/range-calendar.json +1 -1
- package/registry/r/reasoning.json +23 -0
- package/registry/r/segment.json +1 -1
- package/registry/r/select-group.json +1 -1
- package/registry/r/select-item.json +1 -1
- package/registry/r/select-separator.json +1 -1
- package/registry/r/select.json +4 -3
- package/registry/r/separator.json +1 -1
- package/registry/r/sheet.json +1 -1
- package/registry/r/shimmer.json +23 -0
- package/registry/r/sidebar.json +1 -1
- package/registry/r/skeleton.json +1 -1
- package/registry/r/sources.json +23 -0
- package/registry/r/spinner.json +23 -0
- package/registry/r/suggestion.json +23 -0
- package/registry/r/switch.json +1 -1
- package/registry/r/table.json +21 -0
- package/registry/r/tabs.json +1 -1
- package/registry/r/tag-input.json +1 -1
- package/registry/r/task.json +23 -0
- package/registry/r/textarea.json +1 -1
- package/registry/r/time-picker.json +24 -0
- package/registry/r/toaster.json +2 -2
- package/registry/r/toggle-group.json +1 -1
- package/registry/r/toggle.json +1 -1
- package/registry/r/tool.json +23 -0
- package/registry/r/typography.json +23 -0
- package/registry/registry.json +915 -22
- package/theme.css +109 -8
|
@@ -0,0 +1,555 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import { BehaviorSubject } from 'rxjs';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/** Number of chart palette steps that exist. A 6th series does not get a colour. */
|
|
5
|
+
export const CHART_COLOR_LIMIT = 5;
|
|
6
|
+
/**
|
|
7
|
+
* The paint used for a series past `CHART_COLOR_LIMIT`.
|
|
8
|
+
*
|
|
9
|
+
* The palette is validated for lightness, chroma and colour-blind separation at
|
|
10
|
+
* exactly five steps; generating a sixth would land outside that validation, and
|
|
11
|
+
* wrapping back to step 1 would make two series share an identity. Both are
|
|
12
|
+
* worse than dropping to a neutral, so the overflow is explicitly uncoloured.
|
|
13
|
+
*/
|
|
14
|
+
export const CHART_OVERFLOW_COLOR = 'rgb(var(--muted-foreground))';
|
|
15
|
+
/**
|
|
16
|
+
* Hands out palette steps by entity key rather than by position.
|
|
17
|
+
*
|
|
18
|
+
* A key keeps its slot for the lifetime of the scale, which is what makes
|
|
19
|
+
* colour follow the entity: filtering a series out and back in, or removing an
|
|
20
|
+
* earlier one, must never repaint the survivors. Past the fifth distinct key
|
|
21
|
+
* the scale stops colouring rather than inventing a step or wrapping around.
|
|
22
|
+
*/
|
|
23
|
+
export class ChartColorScale {
|
|
24
|
+
slots = new Map();
|
|
25
|
+
next = 0;
|
|
26
|
+
/** Reserves slots for `keys` in order, leaving already-known keys alone. */
|
|
27
|
+
register(keys) {
|
|
28
|
+
for (const key of keys) {
|
|
29
|
+
if (!this.slots.has(key))
|
|
30
|
+
this.slots.set(key, this.next++);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Paint for `key`, registering it on first sight. */
|
|
34
|
+
colorFor(key) {
|
|
35
|
+
let slot = this.slots.get(key);
|
|
36
|
+
if (slot === undefined) {
|
|
37
|
+
slot = this.next++;
|
|
38
|
+
this.slots.set(key, slot);
|
|
39
|
+
}
|
|
40
|
+
if (slot >= CHART_COLOR_LIMIT)
|
|
41
|
+
return CHART_OVERFLOW_COLOR;
|
|
42
|
+
return 'rgb(var(--chart-' + (slot + 1) + '))';
|
|
43
|
+
}
|
|
44
|
+
/** True when `key` fell past the palette and renders neutral. */
|
|
45
|
+
isOverflow(key) {
|
|
46
|
+
const slot = this.slots.get(key);
|
|
47
|
+
return slot !== undefined && slot >= CHART_COLOR_LIMIT;
|
|
48
|
+
}
|
|
49
|
+
/** Slot index assigned to `key`, or undefined when it is unknown. */
|
|
50
|
+
slotOf(key) {
|
|
51
|
+
return this.slots.get(key);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Owns layout, scales and colour assignment for one `tolle-chart`, so every
|
|
56
|
+
* child draws into the same coordinate space. Renders nothing itself.
|
|
57
|
+
*
|
|
58
|
+
* Provided on `ChartComponent`, so each chart gets its own instance.
|
|
59
|
+
*/
|
|
60
|
+
export class ChartService {
|
|
61
|
+
/** Rows being plotted, in x order. */
|
|
62
|
+
data = [];
|
|
63
|
+
/** Series definitions, in the order they should take palette steps. */
|
|
64
|
+
series = [];
|
|
65
|
+
/** Row key holding the x category/label. */
|
|
66
|
+
xKey = '';
|
|
67
|
+
/** Whether marks stack on a shared baseline rather than sitting side by side. */
|
|
68
|
+
stacked = false;
|
|
69
|
+
/** Full svg width in px, tracked from the container's ResizeObserver. */
|
|
70
|
+
width = 0;
|
|
71
|
+
/** Full svg height in px. */
|
|
72
|
+
height = 260;
|
|
73
|
+
/** Space reserved around the plot area. */
|
|
74
|
+
margin = { top: 8, right: 8, bottom: 24, left: 40 };
|
|
75
|
+
/** Fraction of a band's step spent on padding, split either side. */
|
|
76
|
+
bandPadding = 0.2;
|
|
77
|
+
scaleMode = 'point';
|
|
78
|
+
zeroRequired = false;
|
|
79
|
+
domainMin = 0;
|
|
80
|
+
domainMax = 1;
|
|
81
|
+
tickValues = [];
|
|
82
|
+
tickStep = 1;
|
|
83
|
+
/** Palette assignment, keyed by series identity. */
|
|
84
|
+
colors = new ChartColorScale();
|
|
85
|
+
layoutSubject = new BehaviorSubject(0);
|
|
86
|
+
/** Emits a version number whenever scales, dimensions or data change. */
|
|
87
|
+
layout$ = this.layoutSubject.asObservable();
|
|
88
|
+
activeIndexSubject = new BehaviorSubject(null);
|
|
89
|
+
/** Index of the x position under the pointer, or null when not hovering. */
|
|
90
|
+
activeIndex$ = this.activeIndexSubject.asObservable();
|
|
91
|
+
layoutVersion = 0;
|
|
92
|
+
emitScheduled = false;
|
|
93
|
+
// ---------------------------------------------------------------- geometry
|
|
94
|
+
get plotLeft() {
|
|
95
|
+
return this.margin.left;
|
|
96
|
+
}
|
|
97
|
+
get plotTop() {
|
|
98
|
+
return this.margin.top;
|
|
99
|
+
}
|
|
100
|
+
get plotWidth() {
|
|
101
|
+
return Math.max(0, this.width - this.margin.left - this.margin.right);
|
|
102
|
+
}
|
|
103
|
+
get plotHeight() {
|
|
104
|
+
return Math.max(0, this.height - this.margin.top - this.margin.bottom);
|
|
105
|
+
}
|
|
106
|
+
get plotRight() {
|
|
107
|
+
return this.plotLeft + this.plotWidth;
|
|
108
|
+
}
|
|
109
|
+
get plotBottom() {
|
|
110
|
+
return this.plotTop + this.plotHeight;
|
|
111
|
+
}
|
|
112
|
+
/** Number of x positions. */
|
|
113
|
+
get count() {
|
|
114
|
+
return this.data.length;
|
|
115
|
+
}
|
|
116
|
+
/** How x is currently resolved. Bars flip this to 'band'. */
|
|
117
|
+
get mode() {
|
|
118
|
+
return this.scaleMode;
|
|
119
|
+
}
|
|
120
|
+
/** Resolved y ticks, with svg coordinates and formatted labels. */
|
|
121
|
+
get ticks() {
|
|
122
|
+
return this.tickValues.map((value) => ({
|
|
123
|
+
value,
|
|
124
|
+
y: this.yFor(value),
|
|
125
|
+
label: this.formatValue(value),
|
|
126
|
+
}));
|
|
127
|
+
}
|
|
128
|
+
/** Current y domain as [min, max]. */
|
|
129
|
+
get domain() {
|
|
130
|
+
return [this.domainMin, this.domainMax];
|
|
131
|
+
}
|
|
132
|
+
/** The x-axis category labels, one per row. */
|
|
133
|
+
get xLabels() {
|
|
134
|
+
return this.data.map((row) => {
|
|
135
|
+
const raw = row?.[this.xKey];
|
|
136
|
+
return raw == null ? '' : String(raw);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
// ------------------------------------------------------------ registration
|
|
140
|
+
/**
|
|
141
|
+
* Replaces the chart's configuration and recomputes the scales.
|
|
142
|
+
* Called by the container on input changes and on resize.
|
|
143
|
+
*/
|
|
144
|
+
configure(config) {
|
|
145
|
+
Object.assign(this, config);
|
|
146
|
+
if (config.series)
|
|
147
|
+
this.syncColorSlots(config.series);
|
|
148
|
+
this.recompute();
|
|
149
|
+
}
|
|
150
|
+
/** Switches x to a band scale. Bars call this; it also forces zero into the domain. */
|
|
151
|
+
useBandScale() {
|
|
152
|
+
if (this.scaleMode === 'band' && this.zeroRequired)
|
|
153
|
+
return;
|
|
154
|
+
this.scaleMode = 'band';
|
|
155
|
+
this.zeroRequired = true;
|
|
156
|
+
this.recompute();
|
|
157
|
+
}
|
|
158
|
+
/** Forces zero into the y domain, for marks anchored to a baseline. */
|
|
159
|
+
requireZero() {
|
|
160
|
+
if (this.zeroRequired)
|
|
161
|
+
return;
|
|
162
|
+
this.zeroRequired = true;
|
|
163
|
+
this.recompute();
|
|
164
|
+
}
|
|
165
|
+
/** Reserves palette slots in series order, leaving known keys untouched. */
|
|
166
|
+
syncColorSlots(series) {
|
|
167
|
+
this.colors.register(series.map((item) => item.key));
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Paint for a series, keyed by identity rather than by index in the visible
|
|
171
|
+
* array. Past the fifth distinct key this returns the neutral overflow colour.
|
|
172
|
+
*/
|
|
173
|
+
colorFor(seriesKey) {
|
|
174
|
+
return this.colors.colorFor(seriesKey);
|
|
175
|
+
}
|
|
176
|
+
/** True when this series fell past the palette and renders neutral. */
|
|
177
|
+
isOverflowSeries(seriesKey) {
|
|
178
|
+
return this.colors.isOverflow(seriesKey);
|
|
179
|
+
}
|
|
180
|
+
// -------------------------------------------------------------- the scales
|
|
181
|
+
/** Reads a series value off a row, or null when it is missing/non-numeric. */
|
|
182
|
+
valueAt(seriesKey, index) {
|
|
183
|
+
const raw = this.data[index]?.[seriesKey];
|
|
184
|
+
if (raw == null || raw === '')
|
|
185
|
+
return null;
|
|
186
|
+
const num = Number(raw);
|
|
187
|
+
return Number.isFinite(num) ? num : null;
|
|
188
|
+
}
|
|
189
|
+
/** Sum of every series below `seriesKey` at `index`, for stacked marks. */
|
|
190
|
+
stackBase(seriesKey, index) {
|
|
191
|
+
if (!this.stacked)
|
|
192
|
+
return 0;
|
|
193
|
+
let base = 0;
|
|
194
|
+
for (const item of this.series) {
|
|
195
|
+
if (item.key === seriesKey)
|
|
196
|
+
break;
|
|
197
|
+
base += this.valueAt(item.key, index) ?? 0;
|
|
198
|
+
}
|
|
199
|
+
return base;
|
|
200
|
+
}
|
|
201
|
+
/** Sum of every series at `index`. */
|
|
202
|
+
stackTotal(index) {
|
|
203
|
+
let total = 0;
|
|
204
|
+
for (const item of this.series)
|
|
205
|
+
total += this.valueAt(item.key, index) ?? 0;
|
|
206
|
+
return total;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Maps a data value to an svg y. SVG y grows downward, so the domain maximum
|
|
210
|
+
* lands on `plotTop` and the minimum on `plotBottom`.
|
|
211
|
+
*/
|
|
212
|
+
yFor(value) {
|
|
213
|
+
const span = this.domainMax - this.domainMin;
|
|
214
|
+
if (span <= 0)
|
|
215
|
+
return this.plotBottom;
|
|
216
|
+
const ratio = (value - this.domainMin) / span;
|
|
217
|
+
return this.plotBottom - ratio * this.plotHeight;
|
|
218
|
+
}
|
|
219
|
+
/** The svg y of the zero line, clamped into the plot. */
|
|
220
|
+
get baselineY() {
|
|
221
|
+
const zero = Math.min(Math.max(0, this.domainMin), this.domainMax);
|
|
222
|
+
return this.yFor(zero);
|
|
223
|
+
}
|
|
224
|
+
/** Width of one band, excluding its padding. Meaningful in band mode. */
|
|
225
|
+
get bandWidth() {
|
|
226
|
+
if (this.count === 0)
|
|
227
|
+
return 0;
|
|
228
|
+
return this.bandStep * (1 - this.bandPadding);
|
|
229
|
+
}
|
|
230
|
+
/** Distance between adjacent band starts. Bands tile the plot exactly. */
|
|
231
|
+
get bandStep() {
|
|
232
|
+
if (this.count === 0)
|
|
233
|
+
return 0;
|
|
234
|
+
return this.plotWidth / this.count;
|
|
235
|
+
}
|
|
236
|
+
/** Geometry of the band at `index`. */
|
|
237
|
+
bandFor(index) {
|
|
238
|
+
const step = this.bandStep;
|
|
239
|
+
const width = this.bandWidth;
|
|
240
|
+
const start = this.plotLeft + index * step + (step - width) / 2;
|
|
241
|
+
return { start, centre: start + width / 2, width };
|
|
242
|
+
}
|
|
243
|
+
/** x of the data point at `index` on the point scale. */
|
|
244
|
+
pointX(index) {
|
|
245
|
+
if (this.count === 0)
|
|
246
|
+
return this.plotLeft;
|
|
247
|
+
if (this.count === 1)
|
|
248
|
+
return this.plotLeft + this.plotWidth / 2;
|
|
249
|
+
return this.plotLeft + (index * this.plotWidth) / (this.count - 1);
|
|
250
|
+
}
|
|
251
|
+
/** x of `index` under whichever scale the chart is currently using. */
|
|
252
|
+
xFor(index) {
|
|
253
|
+
return this.scaleMode === 'band' ? this.bandFor(index).centre : this.pointX(index);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* The pointer catchment area for `index` — deliberately wider than the mark.
|
|
257
|
+
* In band mode it is the whole band step; on the point scale it runs to the
|
|
258
|
+
* midpoints of the neighbouring points, so the pointer only has to be nearest.
|
|
259
|
+
*/
|
|
260
|
+
hitBandFor(index) {
|
|
261
|
+
if (this.scaleMode === 'band') {
|
|
262
|
+
const step = this.bandStep;
|
|
263
|
+
const start = this.plotLeft + index * step;
|
|
264
|
+
return { start, centre: start + step / 2, width: step };
|
|
265
|
+
}
|
|
266
|
+
const x = this.pointX(index);
|
|
267
|
+
const prev = index > 0 ? this.pointX(index - 1) : this.plotLeft - (this.plotRight - this.plotLeft);
|
|
268
|
+
const next = index < this.count - 1 ? this.pointX(index + 1) : this.plotRight + (this.plotRight - this.plotLeft);
|
|
269
|
+
const start = Math.max(this.plotLeft, (prev + x) / 2);
|
|
270
|
+
const end = Math.min(this.plotRight, (x + next) / 2);
|
|
271
|
+
return { start, centre: x, width: Math.max(0, end - start) };
|
|
272
|
+
}
|
|
273
|
+
// --------------------------------------------------------------- hovering
|
|
274
|
+
/** Index currently under the pointer, or null. */
|
|
275
|
+
get activeIndex() {
|
|
276
|
+
return this.activeIndexSubject.value;
|
|
277
|
+
}
|
|
278
|
+
setActiveIndex(index) {
|
|
279
|
+
if (this.activeIndexSubject.value === index)
|
|
280
|
+
return;
|
|
281
|
+
this.activeIndexSubject.next(index);
|
|
282
|
+
}
|
|
283
|
+
// ----------------------------------------------------------------- domains
|
|
284
|
+
recompute() {
|
|
285
|
+
const values = [];
|
|
286
|
+
if (this.stacked) {
|
|
287
|
+
for (let i = 0; i < this.count; i++)
|
|
288
|
+
values.push(this.stackTotal(i));
|
|
289
|
+
// A stack still has to show its own floor when a series goes negative.
|
|
290
|
+
for (const item of this.series) {
|
|
291
|
+
for (let i = 0; i < this.count; i++) {
|
|
292
|
+
const v = this.valueAt(item.key, i);
|
|
293
|
+
if (v != null && v < 0)
|
|
294
|
+
values.push(v);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
for (const item of this.series) {
|
|
300
|
+
for (let i = 0; i < this.count; i++) {
|
|
301
|
+
const v = this.valueAt(item.key, i);
|
|
302
|
+
if (v != null)
|
|
303
|
+
values.push(v);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (this.zeroRequired)
|
|
308
|
+
values.push(0);
|
|
309
|
+
const [min, max, step, ticks] = niceScale(values);
|
|
310
|
+
this.domainMin = min;
|
|
311
|
+
this.domainMax = max;
|
|
312
|
+
this.tickStep = step;
|
|
313
|
+
this.tickValues = ticks;
|
|
314
|
+
// Only tell subscribers when something they would draw differently actually
|
|
315
|
+
// changed. `configure()` is called from ngOnChanges, and an app binding
|
|
316
|
+
// `[data]="items.filter(...)"` hands us a fresh array reference on every
|
|
317
|
+
// change-detection pass — an ordinary thing to write. Emitting on every call
|
|
318
|
+
// made subscribers markForCheck, which scheduled another pass, which called
|
|
319
|
+
// configure again: the cycle never closed and the page locked up.
|
|
320
|
+
const signature = this.layoutSignature(values);
|
|
321
|
+
if (signature === this.lastSignature)
|
|
322
|
+
return;
|
|
323
|
+
this.lastSignature = signature;
|
|
324
|
+
this.scheduleEmit();
|
|
325
|
+
}
|
|
326
|
+
/** Everything a subscriber would render differently, flattened for comparison. */
|
|
327
|
+
lastSignature = '';
|
|
328
|
+
layoutSignature(values) {
|
|
329
|
+
return [
|
|
330
|
+
this.count,
|
|
331
|
+
this.xKey,
|
|
332
|
+
this.stacked,
|
|
333
|
+
this.width,
|
|
334
|
+
this.height,
|
|
335
|
+
this.bandPadding,
|
|
336
|
+
this.scaleMode,
|
|
337
|
+
this.zeroRequired,
|
|
338
|
+
this.margin.top, this.margin.right, this.margin.bottom, this.margin.left,
|
|
339
|
+
this.domainMin, this.domainMax, this.tickStep,
|
|
340
|
+
this.tickValues.join(','),
|
|
341
|
+
this.series.map((s) => s.key + ':' + s.label).join(','),
|
|
342
|
+
this.xLabels.join(''),
|
|
343
|
+
values.join(','),
|
|
344
|
+
].join('');
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Coalesces layout notifications into a microtask, so several children
|
|
348
|
+
* registering in the same change-detection pass produce one emission after
|
|
349
|
+
* they have all settled rather than one each mid-pass.
|
|
350
|
+
*/
|
|
351
|
+
scheduleEmit() {
|
|
352
|
+
this.layoutVersion++;
|
|
353
|
+
if (this.emitScheduled)
|
|
354
|
+
return;
|
|
355
|
+
this.emitScheduled = true;
|
|
356
|
+
queueMicrotask(() => {
|
|
357
|
+
this.emitScheduled = false;
|
|
358
|
+
this.layoutSubject.next(this.layoutVersion);
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
/** Formats a value for a tick label at the current tick step's precision. */
|
|
362
|
+
formatValue(value) {
|
|
363
|
+
const decimals = decimalsFor(this.tickStep);
|
|
364
|
+
return value.toLocaleString('en-US', {
|
|
365
|
+
minimumFractionDigits: decimals,
|
|
366
|
+
maximumFractionDigits: decimals,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
// ------------------------------------------------------------------- paths
|
|
370
|
+
/** Straight-segment path through the series' defined points. */
|
|
371
|
+
linePath(seriesKey) {
|
|
372
|
+
return buildPath(this.pointsFor(seriesKey), false);
|
|
373
|
+
}
|
|
374
|
+
/** Monotone-cubic path through the series' defined points. */
|
|
375
|
+
smoothPath(seriesKey) {
|
|
376
|
+
return buildPath(this.pointsFor(seriesKey), true);
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Filled-area path: the series' line, closed back along its baseline. When
|
|
380
|
+
* stacked, the floor is the top of the series below rather than zero.
|
|
381
|
+
*/
|
|
382
|
+
areaPath(seriesKey, smooth) {
|
|
383
|
+
const points = this.pointsFor(seriesKey);
|
|
384
|
+
if (points.length === 0)
|
|
385
|
+
return '';
|
|
386
|
+
const top = buildPath(points, smooth);
|
|
387
|
+
const floor = points
|
|
388
|
+
.map((p) => {
|
|
389
|
+
const base = this.stacked ? this.stackBase(seriesKey, p.index) : 0;
|
|
390
|
+
return { x: p.x, y: this.yFor(base), index: p.index };
|
|
391
|
+
})
|
|
392
|
+
.reverse();
|
|
393
|
+
const bottom = buildPath(floor, smooth);
|
|
394
|
+
// Re-enter the reversed floor with a line, then close.
|
|
395
|
+
return top + ' L ' + floor[0].x + ' ' + floor[0].y + ' ' + bottom.replace(/^M/, 'L') + ' Z';
|
|
396
|
+
}
|
|
397
|
+
/** Resolved svg points for a series, skipping rows where it has no value. */
|
|
398
|
+
pointsFor(seriesKey) {
|
|
399
|
+
const points = [];
|
|
400
|
+
for (let i = 0; i < this.count; i++) {
|
|
401
|
+
const v = this.valueAt(seriesKey, i);
|
|
402
|
+
if (v == null)
|
|
403
|
+
continue;
|
|
404
|
+
const stacked = this.stacked ? this.stackBase(seriesKey, i) + v : v;
|
|
405
|
+
points.push({ x: this.xFor(i), y: this.yFor(stacked), index: i });
|
|
406
|
+
}
|
|
407
|
+
return points;
|
|
408
|
+
}
|
|
409
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ChartService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
410
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ChartService });
|
|
411
|
+
}
|
|
412
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ChartService, decorators: [{
|
|
413
|
+
type: Injectable
|
|
414
|
+
}] });
|
|
415
|
+
// ------------------------------------------------------------- pure helpers
|
|
416
|
+
/** Decimal places worth showing for a given tick step. */
|
|
417
|
+
export function decimalsFor(step) {
|
|
418
|
+
if (!Number.isFinite(step) || step <= 0)
|
|
419
|
+
return 0;
|
|
420
|
+
return Math.max(0, Math.min(6, -Math.floor(Math.log10(step))));
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Rounds a raw step up to the next 1/2/5 x 10^n.
|
|
424
|
+
*
|
|
425
|
+
* Dividing the range by a tick count instead would produce steps like 19.4 and
|
|
426
|
+
* so axis labels like 19.4 / 38.8 / 58.2, which nobody can read a value off.
|
|
427
|
+
*/
|
|
428
|
+
export function niceStep(rawStep) {
|
|
429
|
+
if (!Number.isFinite(rawStep) || rawStep <= 0)
|
|
430
|
+
return 1;
|
|
431
|
+
const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));
|
|
432
|
+
const normalised = rawStep / magnitude;
|
|
433
|
+
let multiplier;
|
|
434
|
+
if (normalised <= 1)
|
|
435
|
+
multiplier = 1;
|
|
436
|
+
else if (normalised <= 2)
|
|
437
|
+
multiplier = 2;
|
|
438
|
+
else if (normalised <= 5)
|
|
439
|
+
multiplier = 5;
|
|
440
|
+
else
|
|
441
|
+
multiplier = 10;
|
|
442
|
+
return multiplier * magnitude;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Builds a readable y scale over `values`: returns `[min, max, step, ticks]`
|
|
446
|
+
* with the domain snapped outward to whole steps.
|
|
447
|
+
*
|
|
448
|
+
* Degenerate inputs (empty, all-identical) still produce a usable one-unit
|
|
449
|
+
* domain rather than a zero-height plot.
|
|
450
|
+
*/
|
|
451
|
+
export function niceScale(values, targetTicks = 5) {
|
|
452
|
+
const finite = values.filter((v) => Number.isFinite(v));
|
|
453
|
+
let min = finite.length ? Math.min(...finite) : 0;
|
|
454
|
+
let max = finite.length ? Math.max(...finite) : 1;
|
|
455
|
+
if (min === max) {
|
|
456
|
+
// A flat or single-point domain has no span to divide; open it to one unit
|
|
457
|
+
// around the value so the mark sits on a real axis instead of on the floor.
|
|
458
|
+
if (min === 0) {
|
|
459
|
+
min = 0;
|
|
460
|
+
max = 1;
|
|
461
|
+
}
|
|
462
|
+
else if (min > 0) {
|
|
463
|
+
min = Math.min(0, min);
|
|
464
|
+
max = max === 0 ? 1 : max;
|
|
465
|
+
if (min === max)
|
|
466
|
+
max = min + 1;
|
|
467
|
+
}
|
|
468
|
+
else {
|
|
469
|
+
max = Math.max(0, max);
|
|
470
|
+
if (min === max)
|
|
471
|
+
min = max - 1;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
const step = niceStep((max - min) / targetTicks);
|
|
475
|
+
// Nudge before rounding outward: 100/20 lands a hair above 5 in binary
|
|
476
|
+
// floating point, which would otherwise add a phantom tick at 120.
|
|
477
|
+
const epsilon = 1e-9;
|
|
478
|
+
const niceMin = Math.floor(min / step + epsilon) * step;
|
|
479
|
+
const niceMax = Math.ceil(max / step - epsilon) * step;
|
|
480
|
+
const decimals = decimalsFor(step);
|
|
481
|
+
const ticks = [];
|
|
482
|
+
const total = Math.round((niceMax - niceMin) / step);
|
|
483
|
+
for (let i = 0; i <= total; i++) {
|
|
484
|
+
ticks.push(Number((niceMin + i * step).toFixed(decimals)));
|
|
485
|
+
}
|
|
486
|
+
return [Number(niceMin.toFixed(decimals)), Number(niceMax.toFixed(decimals)), step, ticks];
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Monotone-cubic tangents (Fritsch-Carlson). Limiting each tangent to the
|
|
490
|
+
* neighbouring secants is what stops the curve overshooting: a plain
|
|
491
|
+
* Catmull-Rom spline bulges past the data and invents peaks that were never
|
|
492
|
+
* measured, which on a chart is a false statement about the numbers.
|
|
493
|
+
*/
|
|
494
|
+
export function monotoneTangents(xs, ys) {
|
|
495
|
+
const n = xs.length;
|
|
496
|
+
if (n < 2)
|
|
497
|
+
return new Array(n).fill(0);
|
|
498
|
+
const secants = [];
|
|
499
|
+
for (let i = 0; i < n - 1; i++) {
|
|
500
|
+
const dx = xs[i + 1] - xs[i];
|
|
501
|
+
secants.push(dx === 0 ? 0 : (ys[i + 1] - ys[i]) / dx);
|
|
502
|
+
}
|
|
503
|
+
const m = new Array(n);
|
|
504
|
+
m[0] = secants[0];
|
|
505
|
+
m[n - 1] = secants[n - 2];
|
|
506
|
+
for (let i = 1; i < n - 1; i++)
|
|
507
|
+
m[i] = (secants[i - 1] + secants[i]) / 2;
|
|
508
|
+
for (let i = 0; i < n - 1; i++) {
|
|
509
|
+
if (secants[i] === 0) {
|
|
510
|
+
// Flat segment: both ends must be flat or the curve leaves the data range.
|
|
511
|
+
m[i] = 0;
|
|
512
|
+
m[i + 1] = 0;
|
|
513
|
+
continue;
|
|
514
|
+
}
|
|
515
|
+
const a = m[i] / secants[i];
|
|
516
|
+
const b = m[i + 1] / secants[i];
|
|
517
|
+
// Negative ratios mean the tangent points away from the secant.
|
|
518
|
+
if (a < 0)
|
|
519
|
+
m[i] = 0;
|
|
520
|
+
if (b < 0)
|
|
521
|
+
m[i + 1] = 0;
|
|
522
|
+
const sum = a * a + b * b;
|
|
523
|
+
if (sum > 9) {
|
|
524
|
+
const t = 3 / Math.sqrt(sum);
|
|
525
|
+
m[i] = t * a * secants[i];
|
|
526
|
+
m[i + 1] = t * b * secants[i];
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return m;
|
|
530
|
+
}
|
|
531
|
+
/** Turns resolved points into an svg path, optionally monotone-smoothed. */
|
|
532
|
+
export function buildPath(points, smooth) {
|
|
533
|
+
if (points.length === 0)
|
|
534
|
+
return '';
|
|
535
|
+
if (points.length === 1)
|
|
536
|
+
return 'M ' + points[0].x + ' ' + points[0].y;
|
|
537
|
+
const head = 'M ' + points[0].x + ' ' + points[0].y;
|
|
538
|
+
if (!smooth) {
|
|
539
|
+
return head + points.slice(1).map((p) => ' L ' + p.x + ' ' + p.y).join('');
|
|
540
|
+
}
|
|
541
|
+
const xs = points.map((p) => p.x);
|
|
542
|
+
const ys = points.map((p) => p.y);
|
|
543
|
+
const m = monotoneTangents(xs, ys);
|
|
544
|
+
let d = head;
|
|
545
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
546
|
+
const dx = xs[i + 1] - xs[i];
|
|
547
|
+
const c1x = xs[i] + dx / 3;
|
|
548
|
+
const c1y = ys[i] + (m[i] * dx) / 3;
|
|
549
|
+
const c2x = xs[i + 1] - dx / 3;
|
|
550
|
+
const c2y = ys[i + 1] - (m[i + 1] * dx) / 3;
|
|
551
|
+
d += ' C ' + c1x + ' ' + c1y + ' ' + c2x + ' ' + c2y + ' ' + xs[i + 1] + ' ' + ys[i + 1];
|
|
552
|
+
}
|
|
553
|
+
return d;
|
|
554
|
+
}
|
|
555
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhcnQuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL3RvbGxlL3NyYy9saWIvY2hhcnQuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxNQUFNLENBQUM7O0FBaUN2QyxvRkFBb0Y7QUFDcEYsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxDQUFDO0FBRW5DOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyw4QkFBOEIsQ0FBQztBQUVuRTs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxPQUFPLGVBQWU7SUFDVCxLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7SUFDM0MsSUFBSSxHQUFHLENBQUMsQ0FBQztJQUVqQiw0RUFBNEU7SUFDNUUsUUFBUSxDQUFDLElBQWM7UUFDckIsS0FBSyxNQUFNLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUN2QixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDO2dCQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUM3RCxDQUFDO0lBQ0gsQ0FBQztJQUVELHNEQUFzRDtJQUN0RCxRQUFRLENBQUMsR0FBVztRQUNsQixJQUFJLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUMvQixJQUFJLElBQUksS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUN2QixJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ25CLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENB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QzVFLE1BQU0sVUFBVSxTQUFTLENBQUMsTUFBa0MsRUFBRSxNQUFlO0lBQzNFLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxFQUFFLENBQUM7SUFDbkMsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUM7UUFBRSxPQUFPLElBQUksR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRXZFLE1BQU0sSUFBSSxHQUFHLElBQUksR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNaLE9BQU8sSUFBSSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM3RSxDQUFDO0lBRUQsTUFBTSxFQUFFLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xDLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsQyxNQUFNLENBQUMsR0FBRyxnQkFBZ0IsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFbkMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDO0lBQ2IsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDM0MsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0IsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDM0IsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNwQyxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDL0IsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzVDLENBQUMsSUFBSSxLQUFLLEdBQUcsR0FBRyxHQUFHLEdBQUcsR0FBRyxHQUFHLEdBQUcsR0FBRyxHQUFHLEdBQUcsR0FBRyxHQUFHLEdBQUcsR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzNGLENBQUM7SUFDRCxPQUFPLENBQUMsQ0FBQztBQUNYLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QgfSBmcm9tICdyeGpzJztcblxuLyoqIE9uZSBwbG90dGVkIHNlcmllczogd2hpY2gga2V5IHRvIHJlYWQgb2ZmIGVhY2ggcm93LCBhbmQgaG93IHRvIG5hbWUgaXQuICovXG5leHBvcnQgaW50ZXJmYWNlIENoYXJ0U2VyaWVzIHtcbiAga2V5OiBzdHJpbmc7XG4gIGxhYmVsOiBzdHJpbmc7XG59XG5cbi8qKiBTcGFjZSByZXNlcnZlZCBhcm91bmQgdGhlIHBsb3QgYXJlYSBmb3IgYXhlcyBhbmQgbGFiZWxzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBDaGFydE1hcmdpbiB7XG4gIHRvcDogbnVtYmVyO1xuICByaWdodDogbnVtYmVyO1xuICBib3R0b206IG51bWJlcjtcbiAgbGVmdDogbnVtYmVyO1xufVxuXG4vKiogQSB5LWF4aXMgdGljazogaXRzIGRhdGEgdmFsdWUsIGl0cyByZXNvbHZlZCBzdmcgeSwgYW5kIGl0cyBmb3JtYXR0ZWQgbGFiZWwuICovXG5leHBvcnQgaW50ZXJmYWNlIENoYXJ0VGljayB7XG4gIHZhbHVlOiBudW1iZXI7XG4gIHk6IG51bWJlcjtcbiAgbGFiZWw6IHN0cmluZztcbn1cblxuLyoqIEEgaG9yaXpvbnRhbCBzbGljZSBvZiB0aGUgcGxvdCBiZWxvbmdpbmcgdG8gb25lIHggcG9zaXRpb24uICovXG5leHBvcnQgaW50ZXJmYWNlIENoYXJ0QmFuZCB7XG4gIHN0YXJ0OiBudW1iZXI7XG4gIGNlbnRyZTogbnVtYmVyO1xuICB3aWR0aDogbnVtYmVyO1xufVxuXG4vKiogSG93IHggcG9zaXRpb25zIGFyZSByZXNvbHZlZDogZGlzY3JldGUgYmFuZHMgKGJhcnMpIG9yIHBvaW50cyAobGluZS9hcmVhKS4gKi9cbmV4cG9ydCB0eXBlIENoYXJ0U2NhbGVNb2RlID0gJ3BvaW50JyB8ICdiYW5kJztcblxuLyoqIE51bWJlciBvZiBjaGFydCBwYWxldHRlIHN0ZXBzIHRoYXQgZXhpc3QuIEEgNnRoIHNlcmllcyBkb2VzIG5vdCBnZXQgYSBjb2xvdXIuICovXG5leHBvcnQgY29uc3QgQ0hBUlRfQ09MT1JfTElNSVQgPSA1O1xuXG4vKipcbiAqIFRoZSBwYWludCB1c2VkIGZvciBhIHNlcmllcyBwYXN0IGBDSEFSVF9DT0xPUl9MSU1JVGAuXG4gKlxuICogVGhlIHBhbGV0dGUgaXMgdmFsaWRhdGVkIGZvciBsaWdodG5lc3MsIGNocm9tYSBhbmQgY29sb3VyLWJsaW5kIHNlcGFyYXRpb24gYXRcbiAqIGV4YWN0bHkgZml2ZSBzdGVwczsgZ2VuZXJhdGluZyBhIHNpeHRoIHdvdWxkIGxhbmQgb3V0c2lkZSB0aGF0IHZhbGlkYXRpb24sIGFuZFxuICogd3JhcHBpbmcgYmFjayB0byBzdGVwIDEgd291bGQgbWFrZSB0d28gc2VyaWVzIHNoYXJlIGFuIGlkZW50aXR5LiBCb3RoIGFyZVxuICogd29yc2UgdGhhbiBkcm9wcGluZyB0byBhIG5ldXRyYWwsIHNvIHRoZSBvdmVyZmxvdyBpcyBleHBsaWNpdGx5IHVuY29sb3VyZWQuXG4gKi9cbmV4cG9ydCBjb25zdCBDSEFSVF9PVkVSRkxPV19DT0xPUiA9ICdyZ2IodmFyKC0tbXV0ZWQtZm9yZWdyb3VuZCkpJztcblxuLyoqXG4gKiBIYW5kcyBvdXQgcGFsZXR0ZSBzdGVwcyBieSBlbnRpdHkga2V5IHJhdGhlciB0aGFuIGJ5IHBvc2l0aW9uLlxuICpcbiAqIEEga2V5IGtlZXBzIGl0cyBzbG90IGZvciB0aGUgbGlmZXRpbWUgb2YgdGhlIHNjYWxlLCB3aGljaCBpcyB3aGF0IG1ha2VzXG4gKiBjb2xvdXIgZm9sbG93IHRoZSBlbnRpdHk6IGZpbHRlcmluZyBhIHNlcmllcyBvdXQgYW5kIGJhY2sgaW4sIG9yIHJlbW92aW5nIGFuXG4gKiBlYXJsaWVyIG9uZSwgbXVzdCBuZXZlciByZXBhaW50IHRoZSBzdXJ2aXZvcnMuIFBhc3QgdGhlIGZpZnRoIGRpc3RpbmN0IGtleVxuICogdGhlIHNjYWxlIHN0b3BzIGNvbG91cmluZyByYXRoZXIgdGhhbiBpbnZlbnRpbmcgYSBzdGVwIG9yIHdyYXBwaW5nIGFyb3VuZC5cbiAqL1xuZXhwb3J0IGNsYXNzIENoYXJ0Q29sb3JTY2FsZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgc2xvdHMgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xuICBwcml2YXRlIG5leHQgPSAwO1xuXG4gIC8qKiBSZXNlcnZlcyBzbG90cyBmb3IgYGtleXNgIGluIG9yZGVyLCBsZWF2aW5nIGFscmVhZHkta25vd24ga2V5cyBhbG9uZS4gKi9cbiAgcmVnaXN0ZXIoa2V5czogc3RyaW5nW10pOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7XG4gICAgICBpZiAoIXRoaXMuc2xvdHMuaGFzKGtleSkpIHRoaXMuc2xvdHMuc2V0KGtleSwgdGhpcy5uZXh0KyspO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBQYWludCBmb3IgYGtleWAsIHJlZ2lzdGVyaW5nIGl0IG9uIGZpcnN0IHNpZ2h0LiAqL1xuICBjb2xvckZvcihrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgbGV0IHNsb3QgPSB0aGlzLnNsb3RzLmdldChrZXkpO1xuICAgIGlmIChzbG90ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHNsb3QgPSB0aGlzLm5leHQrKztcbiAgICAgIHRoaXMuc2xvdHMuc2V0KGtleSwgc2xvdCk7XG4gICAgfVxuICAgIGlmIChzbG90ID49IENIQVJUX0NPTE9SX0xJTUlUKSByZXR1cm4gQ0hBUlRfT1ZFUkZMT1dfQ09MT1I7XG4gICAgcmV0dXJuICdyZ2IodmFyKC0tY2hhcnQtJyArIChzbG90ICsgMSkgKyAnKSknO1xuICB9XG5cbiAgLyoqIFRydWUgd2hlbiBga2V5YCBmZWxsIHBhc3QgdGhlIHBhbGV0dGUgYW5kIHJlbmRlcnMgbmV1dHJhbC4gKi9cbiAgaXNPdmVyZmxvdyhrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHNsb3QgPSB0aGlzLnNsb3RzLmdldChrZXkpO1xuICAgIHJldHVybiBzbG90ICE9PSB1bmRlZmluZWQgJiYgc2xvdCA+PSBDSEFSVF9DT0xPUl9MSU1JVDtcbiAgfVxuXG4gIC8qKiBTbG90IGluZGV4IGFzc2lnbmVkIHRvIGBrZXlgLCBvciB1bmRlZmluZWQgd2hlbiBpdCBpcyB1bmtub3duLiAqL1xuICBzbG90T2Yoa2V5OiBzdHJpbmcpOiBudW1iZXIgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLnNsb3RzLmdldChrZXkpO1xuICB9XG59XG5cbi8qKlxuICogT3ducyBsYXlvdXQsIHNjYWxlcyBhbmQgY29sb3VyIGFzc2lnbm1lbnQgZm9yIG9uZSBgdG9sbGUtY2hhcnRgLCBzbyBldmVyeVxuICogY2hpbGQgZHJhd3MgaW50byB0aGUgc2FtZSBjb29yZGluYXRlIHNwYWNlLiBSZW5kZXJzIG5vdGhpbmcgaXRzZWxmLlxuICpcbiAqIFByb3ZpZGVkIG9uIGBDaGFydENvbXBvbmVudGAsIHNvIGVhY2ggY2hhcnQgZ2V0cyBpdHMgb3duIGluc3RhbmNlLlxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgQ2hhcnRTZXJ2aWNlIHtcbiAgLyoqIFJvd3MgYmVpbmcgcGxvdHRlZCwgaW4geCBvcmRlci4gKi9cbiAgZGF0YTogUmVjb3JkPHN0cmluZywgYW55PltdID0gW107XG4gIC8qKiBTZXJpZXMgZGVmaW5pdGlvbnMsIGluIHRoZSBvcmRlciB0aGV5IHNob3VsZCB0YWtlIHBhbGV0dGUgc3RlcHMuICovXG4gIHNlcmllczogQ2hhcnRTZXJpZXNbXSA9IFtdO1xuICAvKiogUm93IGtleSBob2xkaW5nIHRoZSB4IGNhdGVnb3J5L2xhYmVsLiAqL1xuICB4S2V5ID0gJyc7XG4gIC8qKiBXaGV0aGVyIG1hcmtzIHN0YWNrIG9uIGEgc2hhcmVkIGJhc2VsaW5lIHJhdGhlciB0aGFuIHNpdHRpbmcgc2lkZSBieSBzaWRlLiAqL1xuICBzdGFja2VkID0gZmFsc2U7XG4gIC8qKiBGdWxsIHN2ZyB3aWR0aCBpbiBweCwgdHJhY2tlZCBmcm9tIHRoZSBjb250YWluZXIncyBSZXNpemVPYnNlcnZlci4gKi9cbiAgd2lkdGggPSAwO1xuICAvKiogRnVsbCBzdmcgaGVpZ2h0IGluIHB4LiAqL1xuICBoZWlnaHQgPSAyNjA7XG4gIC8qKiBTcGFjZSByZXNlcnZlZCBhcm91bmQgdGhlIHBsb3QgYXJlYS4gKi9cbiAgbWFyZ2luOiBDaGFydE1hcmdpbiA9IHsgdG9wOiA4LCByaWdodDogOCwgYm90dG9tOiAyNCwgbGVmdDogNDAgfTtcbiAgLyoqIEZyYWN0aW9uIG9mIGEgYmFuZCdzIHN0ZXAgc3BlbnQgb24gcGFkZGluZywgc3BsaXQgZWl0aGVyIHNpZGUuICovXG4gIGJhbmRQYWRkaW5nID0gMC4yO1xuXG4gIHByaXZhdGUgc2NhbGVNb2RlOiBDaGFydFNjYWxlTW9kZSA9ICdwb2ludCc7XG4gIHByaXZhdGUgemVyb1JlcXVpcmVkID0gZmFsc2U7XG5cbiAgcHJpdmF0ZSBkb21haW5NaW4gPSAwO1xuICBwcml2YXRlIGRvbWFpbk1heCA9IDE7XG4gIHByaXZhdGUgdGlja1ZhbHVlczogbnVtYmVyW10gPSBbXTtcbiAgcHJpdmF0ZSB0aWNrU3RlcCA9IDE7XG5cbiAgLyoqIFBhbGV0dGUgYXNzaWdubWVudCwga2V5ZWQgYnkgc2VyaWVzIGlkZW50aXR5LiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGNvbG9ycyA9IG5ldyBDaGFydENvbG9yU2NhbGUoKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGxheW91dFN1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PG51bWJlcj4oMCk7XG4gIC8qKiBFbWl0cyBhIHZlcnNpb24gbnVtYmVyIHdoZW5ldmVyIHNjYWxlcywgZGltZW5zaW9ucyBvciBkYXRhIGNoYW5nZS4gKi9cbiAgcmVhZG9ubHkgbGF5b3V0JCA9IHRoaXMubGF5b3V0U3ViamVjdC5hc09ic2VydmFibGUoKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGFjdGl2ZUluZGV4U3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8bnVtYmVyIHwgbnVsbD4obnVsbCk7XG4gIC8qKiBJbmRleCBvZiB0aGUgeCBwb3NpdGlvbiB1bmRlciB0aGUgcG9pbnRlciwgb3IgbnVsbCB3aGVuIG5vdCBob3ZlcmluZy4gKi9cbiAgcmVhZG9ubHkgYWN0aXZlSW5kZXgkID0gdGhpcy5hY3RpdmVJbmRleFN1YmplY3QuYXNPYnNlcnZhYmxlKCk7XG5cbiAgcHJpdmF0ZSBsYXlvdXRWZXJzaW9uID0gMDtcbiAgcHJpdmF0ZSBlbWl0U2NoZWR1bGVkID0gZmFsc2U7XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBnZW9tZXRyeVxuXG4gIGdldCBwbG90TGVmdCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLm1hcmdpbi5sZWZ0O1xuICB9XG5cbiAgZ2V0IHBsb3RUb3AoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5tYXJnaW4udG9wO1xuICB9XG5cbiAgZ2V0IHBsb3RXaWR0aCgpOiBudW1iZXIge1xuICAgIHJldHVybiBNYXRoLm1heCgwLCB0aGlzLndpZHRoIC0gdGhpcy5tYXJnaW4ubGVmdCAtIHRoaXMubWFyZ2luLnJpZ2h0KTtcbiAgfVxuXG4gIGdldCBwbG90SGVpZ2h0KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIE1hdGgubWF4KDAsIHRoaXMuaGVpZ2h0IC0gdGhpcy5tYXJnaW4udG9wIC0gdGhpcy5tYXJnaW4uYm90dG9tKTtcbiAgfVxuXG4gIGdldCBwbG90UmlnaHQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5wbG90TGVmdCArIHRoaXMucGxvdFdpZHRoO1xuICB9XG5cbiAgZ2V0IHBsb3RCb3R0b20oKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5wbG90VG9wICsgdGhpcy5wbG90SGVpZ2h0O1xuICB9XG5cbiAgLyoqIE51bWJlciBvZiB4IHBvc2l0aW9ucy4gKi9cbiAgZ2V0IGNvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YS5sZW5ndGg7XG4gIH1cblxuICAvKiogSG93IHggaXMgY3VycmVudGx5IHJlc29sdmVkLiBCYXJzIGZsaXAgdGhpcyB0byAnYmFuZCcuICovXG4gIGdldCBtb2RlKCk6IENoYXJ0U2NhbGVNb2RlIHtcbiAgICByZXR1cm4gdGhpcy5zY2FsZU1vZGU7XG4gIH1cblxuICAvKiogUmVzb2x2ZWQgeSB0aWNrcywgd2l0aCBzdmcgY29vcmRpbmF0ZXMgYW5kIGZvcm1hdHRlZCBsYWJlbHMuICovXG4gIGdldCB0aWNrcygpOiBDaGFydFRpY2tbXSB7XG4gICAgcmV0dXJuIHRoaXMudGlja1ZhbHVlcy5tYXAoKHZhbHVlKSA9PiAoe1xuICAgICAgdmFsdWUsXG4gICAgICB5OiB0aGlzLnlGb3IodmFsdWUpLFxuICAgICAgbGFiZWw6IHRoaXMuZm9ybWF0VmFsdWUodmFsdWUpLFxuICAgIH0pKTtcbiAgfVxuXG4gIC8qKiBDdXJyZW50IHkgZG9tYWluIGFzIFttaW4sIG1heF0uICovXG4gIGdldCBkb21haW4oKTogW251bWJlciwgbnVtYmVyXSB7XG4gICAgcmV0dXJuIFt0aGlzLmRvbWFpbk1pbiwgdGhpcy5kb21haW5NYXhdO1xuICB9XG5cbiAgLyoqIFRoZSB4LWF4aXMgY2F0ZWdvcnkgbGFiZWxzLCBvbmUgcGVyIHJvdy4gKi9cbiAgZ2V0IHhMYWJlbHMoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiB0aGlzLmRhdGEubWFwKChyb3cpID0+IHtcbiAgICAgIGNvbnN0IHJhdyA9IHJvdz8uW3RoaXMueEtleV07XG4gICAgICByZXR1cm4gcmF3ID09IG51bGwgPyAnJyA6IFN0cmluZyhyYXcpO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHJlZ2lzdHJhdGlvblxuXG4gIC8qKlxuICAgKiBSZXBsYWNlcyB0aGUgY2hhcnQncyBjb25maWd1cmF0aW9uIGFuZCByZWNvbXB1dGVzIHRoZSBzY2FsZXMuXG4gICAqIENhbGxlZCBieSB0aGUgY29udGFpbmVyIG9uIGlucHV0IGNoYW5nZXMgYW5kIG9uIHJlc2l6ZS5cbiAgICovXG4gIGNvbmZpZ3VyZShjb25maWc6IFBhcnRpYWw8UGljazxDaGFydFNlcnZpY2UsXG4gICAgJ2RhdGEnIHwgJ3NlcmllcycgfCAneEtleScgfCAnc3RhY2tlZCcgfCAnd2lkdGgnIHwgJ2hlaWdodCcgfCAnbWFyZ2luJyB8ICdiYW5kUGFkZGluZyc+Pik6IHZvaWQge1xuICAgIE9iamVjdC5hc3NpZ24odGhpcywgY29uZmlnKTtcbiAgICBpZiAoY29uZmlnLnNlcmllcykgdGhpcy5zeW5jQ29sb3JTbG90cyhjb25maWcuc2VyaWVzKTtcbiAgICB0aGlzLnJlY29tcHV0ZSgpO1xuICB9XG5cbiAgLyoqIFN3aXRjaGVzIHggdG8gYSBiYW5kIHNjYWxlLiBCYXJzIGNhbGwgdGhpczsgaXQgYWxzbyBmb3JjZXMgemVybyBpbnRvIHRoZSBkb21haW4uICovXG4gIHVzZUJhbmRTY2FsZSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zY2FsZU1vZGUgPT09ICdiYW5kJyAmJiB0aGlzLnplcm9SZXF1aXJlZCkgcmV0dXJuO1xuICAgIHRoaXMuc2NhbGVNb2RlID0gJ2JhbmQnO1xuICAgIHRoaXMuemVyb1JlcXVpcmVkID0gdHJ1ZTtcbiAgICB0aGlzLnJlY29tcHV0ZSgpO1xuICB9XG5cbiAgLyoqIEZvcmNlcyB6ZXJvIGludG8gdGhlIHkgZG9tYWluLCBmb3IgbWFya3MgYW5jaG9yZWQgdG8gYSBiYXNlbGluZS4gKi9cbiAgcmVxdWlyZVplcm8oKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuemVyb1JlcXVpcmVkKSByZXR1cm47XG4gICAgdGhpcy56ZXJvUmVxdWlyZWQgPSB0cnVlO1xuICAgIHRoaXMucmVjb21wdXRlKCk7XG4gIH1cblxuICAvKiogUmVzZXJ2ZXMgcGFsZXR0ZSBzbG90cyBpbiBzZXJpZXMgb3JkZXIsIGxlYXZpbmcga25vd24ga2V5cyB1bnRvdWNoZWQuICovXG4gIHByaXZhdGUgc3luY0NvbG9yU2xvdHMoc2VyaWVzOiBDaGFydFNlcmllc1tdKTogdm9pZCB7XG4gICAgdGhpcy5jb2xvcnMucmVnaXN0ZXIoc2VyaWVzLm1hcCgoaXRlbSkgPT4gaXRlbS5rZXkpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYWludCBmb3IgYSBzZXJpZXMsIGtleWVkIGJ5IGlkZW50aXR5IHJhdGhlciB0aGFuIGJ5IGluZGV4IGluIHRoZSB2aXNpYmxlXG4gICAqIGFycmF5LiBQYXN0IHRoZSBmaWZ0aCBkaXN0aW5jdCBrZXkgdGhpcyByZXR1cm5zIHRoZSBuZXV0cmFsIG92ZXJmbG93IGNvbG91ci5cbiAgICovXG4gIGNvbG9yRm9yKHNlcmllc0tleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5jb2xvcnMuY29sb3JGb3Ioc2VyaWVzS2V5KTtcbiAgfVxuXG4gIC8qKiBUcnVlIHdoZW4gdGhpcyBzZXJpZXMgZmVsbCBwYXN0IHRoZSBwYWxldHRlIGFuZCByZW5kZXJzIG5ldXRyYWwuICovXG4gIGlzT3ZlcmZsb3dTZXJpZXMoc2VyaWVzS2V5OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5jb2xvcnMuaXNPdmVyZmxvdyhzZXJpZXNLZXkpO1xuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gdGhlIHNjYWxlc1xuXG4gIC8qKiBSZWFkcyBhIHNlcmllcyB2YWx1ZSBvZmYgYSByb3csIG9yIG51bGwgd2hlbiBpdCBpcyBtaXNzaW5nL25vbi1udW1lcmljLiAqL1xuICB2YWx1ZUF0KHNlcmllc0tleTogc3RyaW5nLCBpbmRleDogbnVtYmVyKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgY29uc3QgcmF3ID0gdGhpcy5kYXRhW2luZGV4XT8uW3Nlcmllc0tleV07XG4gICAgaWYgKHJhdyA9PSBudWxsIHx8IHJhdyA9PT0gJycpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IG51bSA9IE51bWJlcihyYXcpO1xuICAgIHJldHVybiBOdW1iZXIuaXNGaW5pdGUobnVtKSA/IG51bSA6IG51bGw7XG4gIH1cblxuICAvKiogU3VtIG9mIGV2ZXJ5IHNlcmllcyBiZWxvdyBgc2VyaWVzS2V5YCBhdCBgaW5kZXhgLCBmb3Igc3RhY2tlZCBtYXJrcy4gKi9cbiAgc3RhY2tCYXNlKHNlcmllc0tleTogc3RyaW5nLCBpbmRleDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBpZiAoIXRoaXMuc3RhY2tlZCkgcmV0dXJuIDA7XG4gICAgbGV0IGJhc2UgPSAwO1xuICAgIGZvciAoY29uc3QgaXRlbSBvZiB0aGlzLnNlcmllcykge1xuICAgICAgaWYgKGl0ZW0ua2V5ID09PSBzZXJpZXNLZXkpIGJyZWFrO1xuICAgICAgYmFzZSArPSB0aGlzLnZhbHVlQXQoaXRlbS5rZXksIGluZGV4KSA/PyAwO1xuICAgIH1cbiAgICByZXR1cm4gYmFzZTtcbiAgfVxuXG4gIC8qKiBTdW0gb2YgZXZlcnkgc2VyaWVzIGF0IGBpbmRleGAuICovXG4gIHN0YWNrVG90YWwoaW5kZXg6IG51bWJlcik6IG51bWJlciB7XG4gICAgbGV0IHRvdGFsID0gMDtcbiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgdGhpcy5zZXJpZXMpIHRvdGFsICs9IHRoaXMudmFsdWVBdChpdGVtLmtleSwgaW5kZXgpID8/IDA7XG4gICAgcmV0dXJuIHRvdGFsO1xuICB9XG5cbiAgLyoqXG4gICAqIE1hcHMgYSBkYXRhIHZhbHVlIHRvIGFuIHN2ZyB5LiBTVkcgeSBncm93cyBkb3dud2FyZCwgc28gdGhlIGRvbWFpbiBtYXhpbXVtXG4gICAqIGxhbmRzIG9uIGBwbG90VG9wYCBhbmQgdGhlIG1pbmltdW0gb24gYHBsb3RCb3R0b21gLlxuICAgKi9cbiAgeUZvcih2YWx1ZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBjb25zdCBzcGFuID0gdGhpcy5kb21haW5NYXggLSB0aGlzLmRvbWFpbk1pbjtcbiAgICBpZiAoc3BhbiA8PSAwKSByZXR1cm4gdGhpcy5wbG90Qm90dG9tO1xuICAgIGNvbnN0IHJhdGlvID0gKHZhbHVlIC0gdGhpcy5kb21haW5NaW4pIC8gc3BhbjtcbiAgICByZXR1cm4gdGhpcy5wbG90Qm90dG9tIC0gcmF0aW8gKiB0aGlzLnBsb3RIZWlnaHQ7XG4gIH1cblxuICAvKiogVGhlIHN2ZyB5IG9mIHRoZSB6ZXJvIGxpbmUsIGNsYW1wZWQgaW50byB0aGUgcGxvdC4gKi9cbiAgZ2V0IGJhc2VsaW5lWSgpOiBudW1iZXIge1xuICAgIGNvbnN0IHplcm8gPSBNYXRoLm1pbihNYXRoLm1heCgwLCB0aGlzLmRvbWFpbk1pbiksIHRoaXMuZG9tYWluTWF4KTtcbiAgICByZXR1cm4gdGhpcy55Rm9yKHplcm8pO1xuICB9XG5cbiAgLyoqIFdpZHRoIG9mIG9uZSBiYW5kLCBleGNsdWRpbmcgaXRzIHBhZGRpbmcuIE1lYW5pbmdmdWwgaW4gYmFuZCBtb2RlLiAqL1xuICBnZXQgYmFuZFdpZHRoKCk6IG51bWJlciB7XG4gICAgaWYgKHRoaXMuY291bnQgPT09IDApIHJldHVybiAwO1xuICAgIHJldHVybiB0aGlzLmJhbmRTdGVwICogKDEgLSB0aGlzLmJhbmRQYWRkaW5nKTtcbiAgfVxuXG4gIC8qKiBEaXN0YW5jZSBiZXR3ZWVuIGFkamFjZW50IGJhbmQgc3RhcnRzLiBCYW5kcyB0aWxlIHRoZSBwbG90IGV4YWN0bHkuICovXG4gIGdldCBiYW5kU3RlcCgpOiBudW1iZXIge1xuICAgIGlmICh0aGlzLmNvdW50ID09PSAwKSByZXR1cm4gMDtcbiAgICByZXR1cm4gdGhpcy5wbG90V2lkdGggLyB0aGlzLmNvdW50O1xuICB9XG5cbiAgLyoqIEdlb21ldHJ5IG9mIHRoZSBiYW5kIGF0IGBpbmRleGAuICovXG4gIGJhbmRGb3IoaW5kZXg6IG51bWJlcik6IENoYXJ0QmFuZCB7XG4gICAgY29uc3Qgc3RlcCA9IHRoaXMuYmFuZFN0ZXA7XG4gICAgY29uc3Qgd2lkdGggPSB0aGlzLmJhbmRXaWR0aDtcbiAgICBjb25zdCBzdGFydCA9IHRoaXMucGxvdExlZnQgKyBpbmRleCAqIHN0ZXAgKyAoc3RlcCAtIHdpZHRoKSAvIDI7XG4gICAgcmV0dXJuIHsgc3RhcnQsIGNlbnRyZTogc3RhcnQgKyB3aWR0aCAvIDIsIHdpZHRoIH07XG4gIH1cblxuICAvKiogeCBvZiB0aGUgZGF0YSBwb2ludCBhdCBgaW5kZXhgIG9uIHRoZSBwb2ludCBzY2FsZS4gKi9cbiAgcG9pbnRYKGluZGV4OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGlmICh0aGlzLmNvdW50ID09PSAwKSByZXR1cm4gdGhpcy5wbG90TGVmdDtcbiAgICBpZiAodGhpcy5jb3VudCA9PT0gMSkgcmV0dXJuIHRoaXMucGxvdExlZnQgKyB0aGlzLnBsb3RXaWR0aCAvIDI7XG4gICAgcmV0dXJuIHRoaXMucGxvdExlZnQgKyAoaW5kZXggKiB0aGlzLnBsb3RXaWR0aCkgLyAodGhpcy5jb3VudCAtIDEpO1xuICB9XG5cbiAgLyoqIHggb2YgYGluZGV4YCB1bmRlciB3aGljaGV2ZXIgc2NhbGUgdGhlIGNoYXJ0IGlzIGN1cnJlbnRseSB1c2luZy4gKi9cbiAgeEZvcihpbmRleDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5zY2FsZU1vZGUgPT09ICdiYW5kJyA/IHRoaXMuYmFuZEZvcihpbmRleCkuY2VudHJlIDogdGhpcy5wb2ludFgoaW5kZXgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBwb2ludGVyIGNhdGNobWVudCBhcmVhIGZvciBgaW5kZXhgIOKAlCBkZWxpYmVyYXRlbHkgd2lkZXIgdGhhbiB0aGUgbWFyay5cbiAgICogSW4gYmFuZCBtb2RlIGl0IGlzIHRoZSB3aG9sZSBiYW5kIHN0ZXA7IG9uIHRoZSBwb2ludCBzY2FsZSBpdCBydW5zIHRvIHRoZVxuICAgKiBtaWRwb2ludHMgb2YgdGhlIG5laWdoYm91cmluZyBwb2ludHMsIHNvIHRoZSBwb2ludGVyIG9ubHkgaGFzIHRvIGJlIG5lYXJlc3QuXG4gICAqL1xuICBoaXRCYW5kRm9yKGluZGV4OiBudW1iZXIpOiBDaGFydEJhbmQge1xuICAgIGlmICh0aGlzLnNjYWxlTW9kZSA9PT0gJ2JhbmQnKSB7XG4gICAgICBjb25zdCBzdGVwID0gdGhpcy5iYW5kU3RlcDtcbiAgICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5wbG90TGVmdCArIGluZGV4ICogc3RlcDtcbiAgICAgIHJldHVybiB7IHN0YXJ0LCBjZW50cmU6IHN0YXJ0ICsgc3RlcCAvIDIsIHdpZHRoOiBzdGVwIH07XG4gICAgfVxuICAgIGNvbnN0IHggPSB0aGlzLnBvaW50WChpbmRleCk7XG4gICAgY29uc3QgcHJldiA9IGluZGV4ID4gMCA/IHRoaXMucG9pbnRYKGluZGV4IC0gMSkgOiB0aGlzLnBsb3RMZWZ0IC0gKHRoaXMucGxvdFJpZ2h0IC0gdGhpcy5wbG90TGVmdCk7XG4gICAgY29uc3QgbmV4dCA9XG4gICAgICBpbmRleCA8IHRoaXMuY291bnQgLSAxID8gdGhpcy5wb2ludFgoaW5kZXggKyAxKSA6IHRoaXMucGxvdFJpZ2h0ICsgKHRoaXMucGxvdFJpZ2h0IC0gdGhpcy5wbG90TGVmdCk7XG4gICAgY29uc3Qgc3RhcnQgPSBNYXRoLm1heCh0aGlzLnBsb3RMZWZ0LCAocHJldiArIHgpIC8gMik7XG4gICAgY29uc3QgZW5kID0gTWF0aC5taW4odGhpcy5wbG90UmlnaHQsICh4ICsgbmV4dCkgLyAyKTtcbiAgICByZXR1cm4geyBzdGFydCwgY2VudHJlOiB4LCB3aWR0aDogTWF0aC5tYXgoMCwgZW5kIC0gc3RhcnQpIH07XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gaG92ZXJpbmdcblxuICAvKiogSW5kZXggY3VycmVudGx5IHVuZGVyIHRoZSBwb2ludGVyLCBvciBudWxsLiAqL1xuICBnZXQgYWN0aXZlSW5kZXgoKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuYWN0aXZlSW5kZXhTdWJqZWN0LnZhbHVlO1xuICB9XG5cbiAgc2V0QWN0aXZlSW5kZXgoaW5kZXg6IG51bWJlciB8IG51bGwpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5hY3RpdmVJbmRleFN1YmplY3QudmFsdWUgPT09IGluZGV4KSByZXR1cm47XG4gICAgdGhpcy5hY3RpdmVJbmRleFN1YmplY3QubmV4dChpbmRleCk7XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBkb21haW5zXG5cbiAgcHJpdmF0ZSByZWNvbXB1dGUoKTogdm9pZCB7XG4gICAgY29uc3QgdmFsdWVzOiBudW1iZXJbXSA9IFtdO1xuXG4gICAgaWYgKHRoaXMuc3RhY2tlZCkge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmNvdW50OyBpKyspIHZhbHVlcy5wdXNoKHRoaXMuc3RhY2tUb3RhbChpKSk7XG4gICAgICAvLyBBIHN0YWNrIHN0aWxsIGhhcyB0byBzaG93IGl0cyBvd24gZmxvb3Igd2hlbiBhIHNlcmllcyBnb2VzIG5lZ2F0aXZlLlxuICAgICAgZm9yIChjb25zdCBpdGVtIG9mIHRoaXMuc2VyaWVzKSB7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5jb3VudDsgaSsrKSB7XG4gICAgICAgICAgY29uc3QgdiA9IHRoaXMudmFsdWVBdChpdGVtLmtleSwgaSk7XG4gICAgICAgICAgaWYgKHYgIT0gbnVsbCAmJiB2IDwgMCkgdmFsdWVzLnB1c2godik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZm9yIChjb25zdCBpdGVtIG9mIHRoaXMuc2VyaWVzKSB7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5jb3VudDsgaSsrKSB7XG4gICAgICAgICAgY29uc3QgdiA9IHRoaXMudmFsdWVBdChpdGVtLmtleSwgaSk7XG4gICAgICAgICAgaWYgKHYgIT0gbnVsbCkgdmFsdWVzLnB1c2godik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy56ZXJvUmVxdWlyZWQpIHZhbHVlcy5wdXNoKDApO1xuXG4gICAgY29uc3QgW21pbiwgbWF4LCBzdGVwLCB0aWNrc10gPSBuaWNlU2NhbGUodmFsdWVzKTtcbiAgICB0aGlzLmRvbWFpbk1pbiA9IG1pbjtcbiAgICB0aGlzLmRvbWFpbk1heCA9IG1heDtcbiAgICB0aGlzLnRpY2tTdGVwID0gc3RlcDtcbiAgICB0aGlzLnRpY2tWYWx1ZXMgPSB0aWNrcztcblxuICAgIC8vIE9ubHkgdGVsbCBzdWJzY3JpYmVycyB3aGVuIHNvbWV0aGluZyB0aGV5IHdvdWxkIGRyYXcgZGlmZmVyZW50bHkgYWN0dWFsbHlcbiAgICAvLyBjaGFuZ2VkLiBgY29uZmlndXJlKClgIGlzIGNhbGxlZCBmcm9tIG5nT25DaGFuZ2VzLCBhbmQgYW4gYXBwIGJpbmRpbmdcbiAgICAvLyBgW2RhdGFdPVwiaXRlbXMuZmlsdGVyKC4uLilcImAgaGFuZHMgdXMgYSBmcmVzaCBhcnJheSByZWZlcmVuY2Ugb24gZXZlcnlcbiAgICAvLyBjaGFuZ2UtZGV0ZWN0aW9uIHBhc3Mg4oCUIGFuIG9yZGluYXJ5IHRoaW5nIHRvIHdyaXRlLiBFbWl0dGluZyBvbiBldmVyeSBjYWxsXG4gICAgLy8gbWFkZSBzdWJzY3JpYmVycyBtYXJrRm9yQ2hlY2ssIHdoaWNoIHNjaGVkdWxlZCBhbm90aGVyIHBhc3MsIHdoaWNoIGNhbGxlZFxuICAgIC8vIGNvbmZpZ3VyZSBhZ2FpbjogdGhlIGN5Y2xlIG5ldmVyIGNsb3NlZCBhbmQgdGhlIHBhZ2UgbG9ja2VkIHVwLlxuICAgIGNvbnN0IHNpZ25hdHVyZSA9IHRoaXMubGF5b3V0U2lnbmF0dXJlKHZhbHVlcyk7XG4gICAgaWYgKHNpZ25hdHVyZSA9PT0gdGhpcy5sYXN0U2lnbmF0dXJlKSByZXR1cm47XG4gICAgdGhpcy5sYXN0U2lnbmF0dXJlID0gc2lnbmF0dXJlO1xuXG4gICAgdGhpcy5zY2hlZHVsZUVtaXQoKTtcbiAgfVxuXG4gIC8qKiBFdmVyeXRoaW5nIGEgc3Vic2NyaWJlciB3b3VsZCByZW5kZXIgZGlmZmVyZW50bHksIGZsYXR0ZW5lZCBmb3IgY29tcGFyaXNvbi4gKi9cbiAgcHJpdmF0ZSBsYXN0U2lnbmF0dXJlID0gJyc7XG5cbiAgcHJpdmF0ZSBsYXlvdXRTaWduYXR1cmUodmFsdWVzOiBudW1iZXJbXSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIFtcbiAgICAgIHRoaXMuY291bnQsXG4gICAgICB0aGlzLnhLZXksXG4gICAgICB0aGlzLnN0YWNrZWQsXG4gICAgICB0aGlzLndpZHRoLFxuICAgICAgdGhpcy5oZWlnaHQsXG4gICAgICB0aGlzLmJhbmRQYWRkaW5nLFxuICAgICAgdGhpcy5zY2FsZU1vZGUsXG4gICAgICB0aGlzLnplcm9SZXF1aXJlZCxcbiAgICAgIHRoaXMubWFyZ2luLnRvcCwgdGhpcy5tYXJnaW4ucmlnaHQsIHRoaXMubWFyZ2luLmJvdHRvbSwgdGhpcy5tYXJnaW4ubGVmdCxcbiAgICAgIHRoaXMuZG9tYWluTWluLCB0aGlzLmRvbWFpbk1heCwgdGhpcy50aWNrU3RlcCxcbiAgICAgIHRoaXMudGlja1ZhbHVlcy5qb2luKCcsJyksXG4gICAgICB0aGlzLnNlcmllcy5tYXAoKHMpID0+IHMua2V5ICsgJzonICsgcy5sYWJlbCkuam9pbignLCcpLFxuICAgICAgdGhpcy54TGFiZWxzLmpvaW4oJ1x1MDAwMScpLFxuICAgICAgdmFsdWVzLmpvaW4oJywnKSxcbiAgICBdLmpvaW4oJ1x1MDAwMCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvYWxlc2NlcyBsYXlvdXQgbm90aWZpY2F0aW9ucyBpbnRvIGEgbWljcm90YXNrLCBzbyBzZXZlcmFsIGNoaWxkcmVuXG4gICAqIHJlZ2lzdGVyaW5nIGluIHRoZSBzYW1lIGNoYW5nZS1kZXRlY3Rpb24gcGFzcyBwcm9kdWNlIG9uZSBlbWlzc2lvbiBhZnRlclxuICAgKiB0aGV5IGhhdmUgYWxsIHNldHRsZWQgcmF0aGVyIHRoYW4gb25lIGVhY2ggbWlkLXBhc3MuXG4gICAqL1xuICBwcml2YXRlIHNjaGVkdWxlRW1pdCgpOiB2b2lkIHtcbiAgICB0aGlzLmxheW91dFZlcnNpb24rKztcbiAgICBpZiAodGhpcy5lbWl0U2NoZWR1bGVkKSByZXR1cm47XG4gICAgdGhpcy5lbWl0U2NoZWR1bGVkID0gdHJ1ZTtcbiAgICBxdWV1ZU1pY3JvdGFzaygoKSA9PiB7XG4gICAgICB0aGlzLmVtaXRTY2hlZHVsZWQgPSBmYWxzZTtcbiAgICAgIHRoaXMubGF5b3V0U3ViamVjdC5uZXh0KHRoaXMubGF5b3V0VmVyc2lvbik7XG4gICAgfSk7XG4gIH1cblxuICAvKiogRm9ybWF0cyBhIHZhbHVlIGZvciBhIHRpY2sgbGFiZWwgYXQgdGhlIGN1cnJlbnQgdGljayBzdGVwJ3MgcHJlY2lzaW9uLiAqL1xuICBmb3JtYXRWYWx1ZSh2YWx1ZTogbnVtYmVyKTogc3RyaW5nIHtcbiAgICBjb25zdCBkZWNpbWFscyA9IGRlY2ltYWxzRm9yKHRoaXMudGlja1N0ZXApO1xuICAgIHJldHVybiB2YWx1ZS50b0xvY2FsZVN0cmluZygnZW4tVVMnLCB7XG4gICAgICBtaW5pbXVtRnJhY3Rpb25EaWdpdHM6IGRlY2ltYWxzLFxuICAgICAgbWF4aW11bUZyYWN0aW9uRGlnaXRzOiBkZWNpbWFscyxcbiAgICB9KTtcbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gcGF0aHNcblxuICAvKiogU3RyYWlnaHQtc2VnbWVudCBwYXRoIHRocm91Z2ggdGhlIHNlcmllcycgZGVmaW5lZCBwb2ludHMuICovXG4gIGxpbmVQYXRoKHNlcmllc0tleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYnVpbGRQYXRoKHRoaXMucG9pbnRzRm9yKHNlcmllc0tleSksIGZhbHNlKTtcbiAgfVxuXG4gIC8qKiBNb25vdG9uZS1jdWJpYyBwYXRoIHRocm91Z2ggdGhlIHNlcmllcycgZGVmaW5lZCBwb2ludHMuICovXG4gIHNtb290aFBhdGgoc2VyaWVzS2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBidWlsZFBhdGgodGhpcy5wb2ludHNGb3Ioc2VyaWVzS2V5KSwgdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogRmlsbGVkLWFyZWEgcGF0aDogdGhlIHNlcmllcycgbGluZSwgY2xvc2VkIGJhY2sgYWxvbmcgaXRzIGJhc2VsaW5lLiBXaGVuXG4gICAqIHN0YWNrZWQsIHRoZSBmbG9vciBpcyB0aGUgdG9wIG9mIHRoZSBzZXJpZXMgYmVsb3cgcmF0aGVyIHRoYW4gemVyby5cbiAgICovXG4gIGFyZWFQYXRoKHNlcmllc0tleTogc3RyaW5nLCBzbW9vdGg6IGJvb2xlYW4pOiBzdHJpbmcge1xuICAgIGNvbnN0IHBvaW50cyA9IHRoaXMucG9pbnRzRm9yKHNlcmllc0tleSk7XG4gICAgaWYgKHBvaW50cy5sZW5ndGggPT09IDApIHJldHVybiAnJztcblxuICAgIGNvbnN0IHRvcCA9IGJ1aWxkUGF0aChwb2ludHMsIHNtb290aCk7XG4gICAgY29uc3QgZmxvb3IgPSBwb2ludHNcbiAgICAgIC5tYXAoKHApID0+IHtcbiAgICAgICAgY29uc3QgYmFzZSA9IHRoaXMuc3RhY2tlZCA/IHRoaXMuc3RhY2tCYXNlKHNlcmllc0tleSwgcC5pbmRleCkgOiAwO1xuICAgICAgICByZXR1cm4geyB4OiBwLngsIHk6IHRoaXMueUZvcihiYXNlKSwgaW5kZXg6IHAuaW5kZXggfTtcbiAgICAgIH0pXG4gICAgICAucmV2ZXJzZSgpO1xuICAgIGNvbnN0IGJvdHRvbSA9IGJ1aWxkUGF0aChmbG9vciwgc21vb3RoKTtcbiAgICAvLyBSZS1lbnRlciB0aGUgcmV2ZXJzZWQgZmxvb3Igd2l0aCBhIGxpbmUsIHRoZW4gY2xvc2UuXG4gICAgcmV0dXJuIHRvcCArICcgTCAnICsgZmxvb3JbMF0ueCArICcgJyArIGZsb29yWzBdLnkgKyAnICcgKyBib3R0b20ucmVwbGFjZSgvXk0vLCAnTCcpICsgJyBaJztcbiAgfVxuXG4gIC8qKiBSZXNvbHZlZCBzdmcgcG9pbnRzIGZvciBhIHNlcmllcywgc2tpcHBpbmcgcm93cyB3aGVyZSBpdCBoYXMgbm8gdmFsdWUuICovXG4gIHBvaW50c0ZvcihzZXJpZXNLZXk6IHN0cmluZyk6IHsgeDogbnVtYmVyOyB5OiBudW1iZXI7IGluZGV4OiBudW1iZXIgfVtdIHtcbiAgICBjb25zdCBwb2ludHM6IHsgeDogbnVtYmVyOyB5OiBudW1iZXI7IGluZGV4OiBudW1iZXIgfVtdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmNvdW50OyBpKyspIHtcbiAgICAgIGNvbnN0IHYgPSB0aGlzLnZhbHVlQXQoc2VyaWVzS2V5LCBpKTtcbiAgICAgIGlmICh2ID09IG51bGwpIGNvbnRpbnVlO1xuICAgICAgY29uc3Qgc3RhY2tlZCA9IHRoaXMuc3RhY2tlZCA/IHRoaXMuc3RhY2tCYXNlKHNlcmllc0tleSwgaSkgKyB2IDogdjtcbiAgICAgIHBvaW50cy5wdXNoKHsgeDogdGhpcy54Rm9yKGkpLCB5OiB0aGlzLnlGb3Ioc3RhY2tlZCksIGluZGV4OiBpIH0pO1xuICAgIH1cbiAgICByZXR1cm4gcG9pbnRzO1xuICB9XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gcHVyZSBoZWxwZXJzXG5cbi8qKiBEZWNpbWFsIHBsYWNlcyB3b3J0aCBzaG93aW5nIGZvciBhIGdpdmVuIHRpY2sgc3RlcC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNpbWFsc0ZvcihzdGVwOiBudW1iZXIpOiBudW1iZXIge1xuICBpZiAoIU51bWJlci5pc0Zpbml0ZShzdGVwKSB8fCBzdGVwIDw9IDApIHJldHVybiAwO1xuICByZXR1cm4gTWF0aC5tYXgoMCwgTWF0aC5taW4oNiwgLU1hdGguZmxvb3IoTWF0aC5sb2cxMChzdGVwKSkpKTtcbn1cblxuLyoqXG4gKiBSb3VuZHMgYSByYXcgc3RlcCB1cCB0byB0aGUgbmV4dCAxLzIvNSB4IDEwXm4uXG4gKlxuICogRGl2aWRpbmcgdGhlIHJhbmdlIGJ5IGEgdGljayBjb3VudCBpbnN0ZWFkIHdvdWxkIHByb2R1Y2Ugc3RlcHMgbGlrZSAxOS40IGFuZFxuICogc28gYXhpcyBsYWJlbHMgbGlrZSAxOS40IC8gMzguOCAvIDU4LjIsIHdoaWNoIG5vYm9keSBjYW4gcmVhZCBhIHZhbHVlIG9mZi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG5pY2VTdGVwKHJhd1N0ZXA6IG51bWJlcik6IG51bWJlciB7XG4gIGlmICghTnVtYmVyLmlzRmluaXRlKHJhd1N0ZXApIHx8IHJhd1N0ZXAgPD0gMCkgcmV0dXJuIDE7XG4gIGNvbnN0IG1hZ25pdHVkZSA9IE1hdGgucG93KDEwLCBNYXRoLmZsb29yKE1hdGgubG9nMTAocmF3U3RlcCkpKTtcbiAgY29uc3Qgbm9ybWFsaXNlZCA9IHJhd1N0ZXAgLyBtYWduaXR1ZGU7XG4gIGxldCBtdWx0aXBsaWVyOiBudW1iZXI7XG4gIGlmIChub3JtYWxpc2VkIDw9IDEpIG11bHRpcGxpZXIgPSAxO1xuICBlbHNlIGlmIChub3JtYWxpc2VkIDw9IDIpIG11bHRpcGxpZXIgPSAyO1xuICBlbHNlIGlmIChub3JtYWxpc2VkIDw9IDUpIG11bHRpcGxpZXIgPSA1O1xuICBlbHNlIG11bHRpcGxpZXIgPSAxMDtcbiAgcmV0dXJuIG11bHRpcGxpZXIgKiBtYWduaXR1ZGU7XG59XG5cbi8qKlxuICogQnVpbGRzIGEgcmVhZGFibGUgeSBzY2FsZSBvdmVyIGB2YWx1ZXNgOiByZXR1cm5zIGBbbWluLCBtYXgsIHN0ZXAsIHRpY2tzXWBcbiAqIHdpdGggdGhlIGRvbWFpbiBzbmFwcGVkIG91dHdhcmQgdG8gd2hvbGUgc3RlcHMuXG4gKlxuICogRGVnZW5lcmF0ZSBpbnB1dHMgKGVtcHR5LCBhbGwtaWRlbnRpY2FsKSBzdGlsbCBwcm9kdWNlIGEgdXNhYmxlIG9uZS11bml0XG4gKiBkb21haW4gcmF0aGVyIHRoYW4gYSB6ZXJvLWhlaWdodCBwbG90LlxuICovXG5leHBvcnQgZnVuY3Rpb24gbmljZVNjYWxlKHZhbHVlczogbnVtYmVyW10sIHRhcmdldFRpY2tzID0gNSk6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJbXV0ge1xuICBjb25zdCBmaW5pdGUgPSB2YWx1ZXMuZmlsdGVyKCh2KSA9PiBOdW1iZXIuaXNGaW5pdGUodikpO1xuXG4gIGxldCBtaW4gPSBmaW5pdGUubGVuZ3RoID8gTWF0aC5taW4oLi4uZmluaXRlKSA6IDA7XG4gIGxldCBtYXggPSBmaW5pdGUubGVuZ3RoID8gTWF0aC5tYXgoLi4uZmluaXRlKSA6IDE7XG5cbiAgaWYgKG1pbiA9PT0gbWF4KSB7XG4gICAgLy8gQSBmbGF0IG9yIHNpbmdsZS1wb2ludCBkb21haW4gaGFzIG5vIHNwYW4gdG8gZGl2aWRlOyBvcGVuIGl0IHRvIG9uZSB1bml0XG4gICAgLy8gYXJvdW5kIHRoZSB2YWx1ZSBzbyB0aGUgbWFyayBzaXRzIG9uIGEgcmVhbCBheGlzIGluc3RlYWQgb2Ygb24gdGhlIGZsb29yLlxuICAgIGlmIChtaW4gPT09IDApIHtcbiAgICAgIG1pbiA9IDA7XG4gICAgICBtYXggPSAxO1xuICAgIH0gZWxzZSBpZiAobWluID4gMCkge1xuICAgICAgbWluID0gTWF0aC5taW4oMCwgbWluKTtcbiAgICAgIG1heCA9IG1heCA9PT0gMCA/IDEgOiBtYXg7XG4gICAgICBpZiAobWluID09PSBtYXgpIG1heCA9IG1pbiArIDE7XG4gICAgfSBlbHNlIHtcbiAgICAgIG1heCA9IE1hdGgubWF4KDAsIG1heCk7XG4gICAgICBpZiAobWluID09PSBtYXgpIG1pbiA9IG1heCAtIDE7XG4gICAgfVxuICB9XG5cbiAgY29uc3Qgc3RlcCA9IG5pY2VTdGVwKChtYXggLSBtaW4pIC8gdGFyZ2V0VGlja3MpO1xuICAvLyBOdWRnZSBiZWZvcmUgcm91bmRpbmcgb3V0d2FyZDogMTAwLzIwIGxhbmRzIGEgaGFpciBhYm92ZSA1IGluIGJpbmFyeVxuICAvLyBmbG9hdGluZyBwb2ludCwgd2hpY2ggd291bGQgb3RoZXJ3aXNlIGFkZCBhIHBoYW50b20gdGljayBhdCAxMjAuXG4gIGNvbnN0IGVwc2lsb24gPSAxZS05O1xuICBjb25zdCBuaWNlTWluID0gTWF0aC5mbG9vcihtaW4gLyBzdGVwICsgZXBzaWxvbikgKiBzdGVwO1xuICBjb25zdCBuaWNlTWF4ID0gTWF0aC5jZWlsKG1heCAvIHN0ZXAgLSBlcHNpbG9uKSAqIHN0ZXA7XG4gIGNvbnN0IGRlY2ltYWxzID0gZGVjaW1hbHNGb3Ioc3RlcCk7XG5cbiAgY29uc3QgdGlja3M6IG51bWJlcltdID0gW107XG4gIGNvbnN0IHRvdGFsID0gTWF0aC5yb3VuZCgobmljZU1heCAtIG5pY2VNaW4pIC8gc3RlcCk7XG4gIGZvciAobGV0IGkgPSAwOyBpIDw9IHRvdGFsOyBpKyspIHtcbiAgICB0aWNrcy5wdXNoKE51bWJlcigobmljZU1pbiArIGkgKiBzdGVwKS50b0ZpeGVkKGRlY2ltYWxzKSkpO1xuICB9XG5cbiAgcmV0dXJuIFtOdW1iZXIobmljZU1pbi50b0ZpeGVkKGRlY2ltYWxzKSksIE51bWJlcihuaWNlTWF4LnRvRml4ZWQoZGVjaW1hbHMpKSwgc3RlcCwgdGlja3NdO1xufVxuXG4vKipcbiAqIE1vbm90b25lLWN1YmljIHRhbmdlbnRzIChGcml0c2NoLUNhcmxzb24pLiBMaW1pdGluZyBlYWNoIHRhbmdlbnQgdG8gdGhlXG4gKiBuZWlnaGJvdXJpbmcgc2VjYW50cyBpcyB3aGF0IHN0b3BzIHRoZSBjdXJ2ZSBvdmVyc2hvb3Rpbmc6IGEgcGxhaW5cbiAqIENhdG11bGwtUm9tIHNwbGluZSBidWxnZXMgcGFzdCB0aGUgZGF0YSBhbmQgaW52ZW50cyBwZWFrcyB0aGF0IHdlcmUgbmV2ZXJcbiAqIG1lYXN1cmVkLCB3aGljaCBvbiBhIGNoYXJ0IGlzIGEgZmFsc2Ugc3RhdGVtZW50IGFib3V0IHRoZSBudW1iZXJzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbW9ub3RvbmVUYW5nZW50cyh4czogbnVtYmVyW10sIHlzOiBudW1iZXJbXSk6IG51bWJlcltdIHtcbiAgY29uc3QgbiA9IHhzLmxlbmd0aDtcbiAgaWYgKG4gPCAyKSByZXR1cm4gbmV3IEFycmF5KG4pLmZpbGwoMCk7XG5cbiAgY29uc3Qgc2VjYW50czogbnVtYmVyW10gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBuIC0gMTsgaSsrKSB7XG4gICAgY29uc3QgZHggPSB4c1tpICsgMV0gLSB4c1tpXTtcbiAgICBzZWNhbnRzLnB1c2goZHggPT09IDAgPyAwIDogKHlzW2kgKyAxXSAtIHlzW2ldKSAvIGR4KTtcbiAgfVxuXG4gIGNvbnN0IG06IG51bWJlcltdID0gbmV3IEFycmF5KG4pO1xuICBtWzBdID0gc2VjYW50c1swXTtcbiAgbVtuIC0gMV0gPSBzZWNhbnRzW24gLSAyXTtcbiAgZm9yIChsZXQgaSA9IDE7IGkgPCBuIC0gMTsgaSsrKSBtW2ldID0gKHNlY2FudHNbaSAtIDFdICsgc2VjYW50c1tpXSkgLyAyO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbiAtIDE7IGkrKykge1xuICAgIGlmIChzZWNhbnRzW2ldID09PSAwKSB7XG4gICAgICAvLyBGbGF0IHNlZ21lbnQ6IGJvdGggZW5kcyBtdXN0IGJlIGZsYXQgb3IgdGhlIGN1cnZlIGxlYXZlcyB0aGUgZGF0YSByYW5nZS5cbiAgICAgIG1baV0gPSAwO1xuICAgICAgbVtpICsgMV0gPSAwO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGNvbnN0IGEgPSBtW2ldIC8gc2VjYW50c1tpXTtcbiAgICBjb25zdCBiID0gbVtpICsgMV0gLyBzZWNhbnRzW2ldO1xuICAgIC8vIE5lZ2F0aXZlIHJhdGlvcyBtZWFuIHRoZSB0YW5nZW50IHBvaW50cyBhd2F5IGZyb20gdGhlIHNlY2FudC5cbiAgICBpZiAoYSA8IDApIG1baV0gPSAwO1xuICAgIGlmIChiIDwgMCkgbVtpICsgMV0gPSAwO1xuICAgIGNvbnN0IHN1bSA9IGEgKiBhICsgYiAqIGI7XG4gICAgaWYgKHN1bSA+IDkpIHtcbiAgICAgIGNvbnN0IHQgPSAzIC8gTWF0aC5zcXJ0KHN1bSk7XG4gICAgICBtW2ldID0gdCAqIGEgKiBzZWNhbnRzW2ldO1xuICAgICAgbVtpICsgMV0gPSB0ICogYiAqIHNlY2FudHNbaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG07XG59XG5cbi8qKiBUdXJucyByZXNvbHZlZCBwb2ludHMgaW50byBhbiBzdmcgcGF0aCwgb3B0aW9uYWxseSBtb25vdG9uZS1zbW9vdGhlZC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZFBhdGgocG9pbnRzOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH1bXSwgc21vb3RoOiBib29sZWFuKTogc3RyaW5nIHtcbiAgaWYgKHBvaW50cy5sZW5ndGggPT09IDApIHJldHVybiAnJztcbiAgaWYgKHBvaW50cy5sZW5ndGggPT09IDEpIHJldHVybiAnTSAnICsgcG9pbnRzWzBdLnggKyAnICcgKyBwb2ludHNbMF0ueTtcblxuICBjb25zdCBoZWFkID0gJ00gJyArIHBvaW50c1swXS54ICsgJyAnICsgcG9pbnRzWzBdLnk7XG4gIGlmICghc21vb3RoKSB7XG4gICAgcmV0dXJuIGhlYWQgKyBwb2ludHMuc2xpY2UoMSkubWFwKChwKSA9PiAnIEwgJyArIHAueCArICcgJyArIHAueSkuam9pbignJyk7XG4gIH1cblxuICBjb25zdCB4cyA9IHBvaW50cy5tYXAoKHApID0+IHAueCk7XG4gIGNvbnN0IHlzID0gcG9pbnRzLm1hcCgocCkgPT4gcC55KTtcbiAgY29uc3QgbSA9IG1vbm90b25lVGFuZ2VudHMoeHMsIHlzKTtcblxuICBsZXQgZCA9IGhlYWQ7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcG9pbnRzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgIGNvbnN0IGR4ID0geHNbaSArIDFdIC0geHNbaV07XG4gICAgY29uc3QgYzF4ID0geHNbaV0gKyBkeCAvIDM7XG4gICAgY29uc3QgYzF5ID0geXNbaV0gKyAobVtpXSAqIGR4KSAvIDM7XG4gICAgY29uc3QgYzJ4ID0geHNbaSArIDFdIC0gZHggLyAzO1xuICAgIGNvbnN0IGMyeSA9IHlzW2kgKyAxXSAtIChtW2kgKyAxXSAqIGR4KSAvIDM7XG4gICAgZCArPSAnIEMgJyArIGMxeCArICcgJyArIGMxeSArICcgJyArIGMyeCArICcgJyArIGMyeSArICcgJyArIHhzW2kgKyAxXSArICcgJyArIHlzW2kgKyAxXTtcbiAgfVxuICByZXR1cm4gZDtcbn1cbiJdfQ==
|