@firestitch/report 18.9.0 → 18.10.1

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 (186) hide show
  1. package/app/reports/anchor-at-point.d.ts +14 -0
  2. package/app/reports/canvas-landing-page.d.ts +2 -0
  3. package/app/reports/components/component-chart/component-chart.component.d.ts +18 -2
  4. package/app/reports/components/component-kpi/component-kpi.component.d.ts +4 -1
  5. package/app/reports/components/report-canvas/report-canvas.component.d.ts +3 -0
  6. package/app/reports/components/report-component/report-component.component.d.ts +35 -1
  7. package/app/reports/components/report-view-picker/report-view-picker.component.d.ts +21 -0
  8. package/app/reports/data/report.data.d.ts +20 -7
  9. package/app/reports/dialogs/component-settings/component-settings.component.d.ts +18 -3
  10. package/app/reports/dialogs/report-settings/report-settings.component.d.ts +45 -8
  11. package/app/reports/dialogs/report-view/report-view-dialog.component.d.ts +13 -0
  12. package/app/reports/drill-crumbs.d.ts +12 -0
  13. package/app/reports/export/report-export-collector.service.d.ts +13 -4
  14. package/app/reports/export/report-filter-lines.d.ts +18 -0
  15. package/app/reports/filter-settings-rules.d.ts +37 -0
  16. package/app/reports/format.d.ts +0 -1
  17. package/app/reports/interfaces/canvas-landing-input.interface.d.ts +8 -0
  18. package/app/reports/interfaces/component-data-applied.interface.d.ts +13 -0
  19. package/app/reports/interfaces/component-data-drill.interface.d.ts +22 -0
  20. package/app/reports/interfaces/filter-bar-placement.type.d.ts +1 -0
  21. package/app/reports/interfaces/filter-component-toggle-state.interface.d.ts +4 -0
  22. package/app/reports/interfaces/filter-settings-option.interface.d.ts +4 -0
  23. package/app/reports/interfaces/filter-type-select-state.interface.d.ts +5 -0
  24. package/app/reports/interfaces/report-chart-hit.interface.d.ts +5 -0
  25. package/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.d.ts +4 -0
  26. package/app/reports/interfaces/report-chat-viewer-cross-filter.interface.d.ts +7 -0
  27. package/app/reports/interfaces/report-chat-viewer-detail.interface.d.ts +4 -0
  28. package/app/reports/interfaces/report-chat-viewer-drill-step.interface.d.ts +5 -0
  29. package/app/reports/interfaces/report-chat-viewer-drill.interface.d.ts +5 -0
  30. package/app/reports/interfaces/report-chat-viewer-filter.interface.d.ts +3 -0
  31. package/app/reports/interfaces/report-chat-viewer-selection.interface.d.ts +5 -0
  32. package/app/reports/interfaces/report-chat-viewer-state.interface.d.ts +12 -0
  33. package/app/reports/interfaces/report-drill-crumb.interface.d.ts +6 -0
  34. package/app/reports/interfaces/report-drill-refusal.type.d.ts +1 -0
  35. package/app/reports/interfaces/report-drill-step.interface.d.ts +5 -0
  36. package/app/reports/interfaces/report-export-line-kind.type.d.ts +1 -0
  37. package/app/reports/interfaces/report-export-line.interface.d.ts +8 -0
  38. package/app/reports/interfaces/report-export-lines-input.interface.d.ts +9 -0
  39. package/app/reports/interfaces/report-export-snapshot.interface.d.ts +15 -0
  40. package/app/reports/interfaces/report-filter-group-changes.interface.d.ts +7 -0
  41. package/app/reports/interfaces/report-filter-line-context.interface.d.ts +8 -0
  42. package/app/reports/interfaces/report-filter-line-form.type.d.ts +1 -0
  43. package/app/reports/interfaces/report-filter-match.type.d.ts +1 -0
  44. package/app/reports/interfaces/report-filter-option-pair.interface.d.ts +4 -0
  45. package/app/reports/interfaces/report-filter-options-ask.interface.d.ts +6 -0
  46. package/app/reports/interfaces/report-filter-options-list.interface.d.ts +7 -0
  47. package/app/reports/interfaces/report-filter-options-request.interface.d.ts +6 -0
  48. package/app/reports/interfaces/report-filter-options-stream.interface.d.ts +11 -0
  49. package/app/reports/interfaces/report-filter-options.interface.d.ts +7 -0
  50. package/app/reports/interfaces/report-filter-skip.type.d.ts +1 -0
  51. package/app/reports/interfaces/report-mark-action.type.d.ts +1 -0
  52. package/app/reports/interfaces/report-mark-click.interface.d.ts +13 -0
  53. package/app/reports/interfaces/report-mark-context.interface.d.ts +6 -0
  54. package/app/reports/interfaces/report-mark-decision.interface.d.ts +6 -0
  55. package/app/reports/interfaces/report-mark-event.interface.d.ts +11 -0
  56. package/app/reports/interfaces/report-mark-point.interface.d.ts +8 -0
  57. package/app/reports/interfaces/report-temporary-state.interface.d.ts +4 -0
  58. package/app/reports/interfaces/report-tile-state.interface.d.ts +8 -0
  59. package/app/reports/interfaces/report-view-config.interface.d.ts +11 -0
  60. package/app/reports/interfaces/report-view-create.interface.d.ts +7 -0
  61. package/app/reports/interfaces/report-view-deleted.interface.d.ts +4 -0
  62. package/app/reports/interfaces/report-view-dialog-data.interface.d.ts +7 -0
  63. package/app/reports/interfaces/report-view-dropped.interface.d.ts +5 -0
  64. package/app/reports/interfaces/report-view-menu-item.interface.d.ts +10 -0
  65. package/app/reports/interfaces/report-view-summary.interface.d.ts +11 -0
  66. package/app/reports/interfaces/report-view.interface.d.ts +7 -0
  67. package/app/reports/interfaces/report-viewer-feature.type.d.ts +1 -0
  68. package/app/reports/interfaces/report-views.interface.d.ts +7 -0
  69. package/app/reports/interfaces/report.interface.d.ts +27 -16
  70. package/app/reports/interfaces/tile-load-result.interface.d.ts +4 -0
  71. package/app/reports/mark-click.d.ts +20 -0
  72. package/app/reports/option-builder.d.ts +12 -1
  73. package/app/reports/report-chat-viewer-state.d.ts +8 -0
  74. package/app/reports/report-date-presets.d.ts +2 -0
  75. package/app/reports/report-filter-items.d.ts +20 -21
  76. package/app/reports/report-tile.d.ts +2 -0
  77. package/app/reports/report-view-config.d.ts +34 -0
  78. package/app/reports/report-view-menu.d.ts +15 -0
  79. package/app/reports/report-viewer-features.d.ts +5 -0
  80. package/app/reports/services/report-filter-options.service.d.ts +26 -0
  81. package/app/reports/services/report-filter-state.service.d.ts +65 -11
  82. package/app/reports/services/report-view.service.d.ts +39 -0
  83. package/app/reports/tile-data-state.d.ts +7 -0
  84. package/app/reports/tile-loads.d.ts +4 -0
  85. package/app/reports/views/report/fs-ai-report.component.d.ts +10 -8
  86. package/app/reports/views/report/report.component.d.ts +6 -0
  87. package/esm2022/app/reports/anchor-at-point.mjs +49 -0
  88. package/esm2022/app/reports/canvas-landing-page.mjs +26 -0
  89. package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +97 -5
  90. package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +11 -4
  91. package/esm2022/app/reports/components/component-list/component-list.component.mjs +11 -5
  92. package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +56 -40
  93. package/esm2022/app/reports/components/report-component/report-component.component.mjs +261 -65
  94. package/esm2022/app/reports/components/report-view-picker/report-view-picker.component.mjs +115 -0
  95. package/esm2022/app/reports/data/report.data.mjs +94 -14
  96. package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +106 -51
  97. package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +248 -104
  98. package/esm2022/app/reports/dialogs/report-view/report-view-dialog.component.mjs +52 -0
  99. package/esm2022/app/reports/drill-crumbs.mjs +73 -0
  100. package/esm2022/app/reports/export/report-export-collector.service.mjs +187 -117
  101. package/esm2022/app/reports/export/report-filter-lines.mjs +235 -0
  102. package/esm2022/app/reports/export/report-pdf.service.mjs +12 -7
  103. package/esm2022/app/reports/export/report-pptx.service.mjs +18 -14
  104. package/esm2022/app/reports/filter-settings-rules.mjs +290 -0
  105. package/esm2022/app/reports/format.mjs +2 -22
  106. package/esm2022/app/reports/interfaces/canvas-landing-input.interface.mjs +2 -0
  107. package/esm2022/app/reports/interfaces/component-data-applied.interface.mjs +2 -0
  108. package/esm2022/app/reports/interfaces/component-data-drill.interface.mjs +2 -0
  109. package/esm2022/app/reports/interfaces/filter-bar-placement.type.mjs +2 -0
  110. package/esm2022/app/reports/interfaces/filter-component-toggle-state.interface.mjs +2 -0
  111. package/esm2022/app/reports/interfaces/filter-settings-option.interface.mjs +2 -0
  112. package/esm2022/app/reports/interfaces/filter-type-select-state.interface.mjs +2 -0
  113. package/esm2022/app/reports/interfaces/report-chart-hit.interface.mjs +2 -0
  114. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.mjs +2 -0
  115. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter.interface.mjs +2 -0
  116. package/esm2022/app/reports/interfaces/report-chat-viewer-detail.interface.mjs +2 -0
  117. package/esm2022/app/reports/interfaces/report-chat-viewer-drill-step.interface.mjs +2 -0
  118. package/esm2022/app/reports/interfaces/report-chat-viewer-drill.interface.mjs +2 -0
  119. package/esm2022/app/reports/interfaces/report-chat-viewer-filter.interface.mjs +1 -1
  120. package/esm2022/app/reports/interfaces/report-chat-viewer-selection.interface.mjs +2 -0
  121. package/esm2022/app/reports/interfaces/report-chat-viewer-state.interface.mjs +1 -1
  122. package/esm2022/app/reports/interfaces/report-drill-crumb.interface.mjs +2 -0
  123. package/esm2022/app/reports/interfaces/report-drill-refusal.type.mjs +2 -0
  124. package/esm2022/app/reports/interfaces/report-drill-step.interface.mjs +2 -0
  125. package/esm2022/app/reports/interfaces/report-export-line-kind.type.mjs +2 -0
  126. package/esm2022/app/reports/interfaces/report-export-line.interface.mjs +2 -0
  127. package/esm2022/app/reports/interfaces/report-export-lines-input.interface.mjs +2 -0
  128. package/esm2022/app/reports/interfaces/report-export-snapshot.interface.mjs +2 -0
  129. package/esm2022/app/reports/interfaces/report-filter-group-changes.interface.mjs +2 -0
  130. package/esm2022/app/reports/interfaces/report-filter-line-context.interface.mjs +2 -0
  131. package/esm2022/app/reports/interfaces/report-filter-line-form.type.mjs +2 -0
  132. package/esm2022/app/reports/interfaces/report-filter-match.type.mjs +2 -0
  133. package/esm2022/app/reports/interfaces/report-filter-option-pair.interface.mjs +2 -0
  134. package/esm2022/app/reports/interfaces/report-filter-options-ask.interface.mjs +2 -0
  135. package/esm2022/app/reports/interfaces/report-filter-options-list.interface.mjs +2 -0
  136. package/esm2022/app/reports/interfaces/report-filter-options-request.interface.mjs +2 -0
  137. package/esm2022/app/reports/interfaces/report-filter-options-stream.interface.mjs +2 -0
  138. package/esm2022/app/reports/interfaces/report-filter-options.interface.mjs +2 -0
  139. package/esm2022/app/reports/interfaces/report-filter-skip.type.mjs +2 -0
  140. package/esm2022/app/reports/interfaces/report-mark-action.type.mjs +2 -0
  141. package/esm2022/app/reports/interfaces/report-mark-click.interface.mjs +2 -0
  142. package/esm2022/app/reports/interfaces/report-mark-context.interface.mjs +2 -0
  143. package/esm2022/app/reports/interfaces/report-mark-decision.interface.mjs +2 -0
  144. package/esm2022/app/reports/interfaces/report-mark-event.interface.mjs +2 -0
  145. package/esm2022/app/reports/interfaces/report-mark-point.interface.mjs +2 -0
  146. package/esm2022/app/reports/interfaces/report-temporary-state.interface.mjs +2 -0
  147. package/esm2022/app/reports/interfaces/report-tile-state.interface.mjs +2 -0
  148. package/esm2022/app/reports/interfaces/report-view-config.interface.mjs +2 -0
  149. package/esm2022/app/reports/interfaces/report-view-create.interface.mjs +2 -0
  150. package/esm2022/app/reports/interfaces/report-view-deleted.interface.mjs +2 -0
  151. package/esm2022/app/reports/interfaces/report-view-dialog-data.interface.mjs +2 -0
  152. package/esm2022/app/reports/interfaces/report-view-dropped.interface.mjs +2 -0
  153. package/esm2022/app/reports/interfaces/report-view-menu-item.interface.mjs +2 -0
  154. package/esm2022/app/reports/interfaces/report-view-summary.interface.mjs +2 -0
  155. package/esm2022/app/reports/interfaces/report-view.interface.mjs +2 -0
  156. package/esm2022/app/reports/interfaces/report-viewer-feature.type.mjs +2 -0
  157. package/esm2022/app/reports/interfaces/report-views.interface.mjs +2 -0
  158. package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
  159. package/esm2022/app/reports/interfaces/tile-load-result.interface.mjs +2 -0
  160. package/esm2022/app/reports/mark-click.mjs +193 -0
  161. package/esm2022/app/reports/option-builder.mjs +159 -15
  162. package/esm2022/app/reports/report-chat-viewer-state.mjs +34 -0
  163. package/esm2022/app/reports/report-date-presets.mjs +18 -0
  164. package/esm2022/app/reports/report-filter-items.mjs +263 -72
  165. package/esm2022/app/reports/report-tile.mjs +12 -0
  166. package/esm2022/app/reports/report-view-config.mjs +587 -0
  167. package/esm2022/app/reports/report-view-menu.mjs +119 -0
  168. package/esm2022/app/reports/report-viewer-features.mjs +42 -0
  169. package/esm2022/app/reports/services/report-filter-options.service.mjs +238 -0
  170. package/esm2022/app/reports/services/report-filter-state.service.mjs +668 -210
  171. package/esm2022/app/reports/services/report-view.service.mjs +218 -0
  172. package/esm2022/app/reports/tile-data-state.mjs +127 -0
  173. package/esm2022/app/reports/tile-loads.mjs +38 -0
  174. package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +194 -127
  175. package/esm2022/app/reports/views/report/report.component.mjs +112 -29
  176. package/esm2022/public_api.mjs +23 -1
  177. package/fesm2022/{firestitch-report-echarts-DBMOHmBF.mjs → firestitch-report-echarts-DHEH_K_q.mjs} +2 -2
  178. package/fesm2022/{firestitch-report-echarts-DBMOHmBF.mjs.map → firestitch-report-echarts-DHEH_K_q.mjs.map} +1 -1
  179. package/fesm2022/{firestitch-report-firestitch-report-CqbXT1gh.mjs → firestitch-report-firestitch-report-ZcHTnNKq.mjs} +8222 -4447
  180. package/fesm2022/firestitch-report-firestitch-report-ZcHTnNKq.mjs.map +1 -0
  181. package/fesm2022/firestitch-report.mjs +1 -1
  182. package/package.json +1 -1
  183. package/public_api.d.ts +22 -0
  184. package/app/reports/report-url-state.d.ts +0 -19
  185. package/esm2022/app/reports/report-url-state.mjs +0 -189
  186. package/fesm2022/firestitch-report-firestitch-report-CqbXT1gh.mjs.map +0 -1
@@ -0,0 +1,587 @@
1
+ import { GRANULARITY_OPTIONS, } from './interfaces/report.interface';
2
+ import { dateBoundString, dateFromBound } from './report-filter-items';
3
+ // The version this viewer writes and reads.
4
+ export const REPORT_VIEW_CONFIG_VERSION = 1;
5
+ // The caps of a view document, the server's.
6
+ export const VIEW_CONFIG_MAX_BYTES = 32 * 1024;
7
+ export const VIEW_CONFIG_MAX_GROUPS = 100;
8
+ export const VIEW_CONFIG_MAX_TILES = 200;
9
+ export const GROUP_VALUE_MAX_PICKS = 500;
10
+ export const DRILL_MAX_DEPTH = 5;
11
+ // Every relative range name the server knows, in its enum's order. A record
12
+ // rather than a list, so the build fails when ReportRelativeRange gains a
13
+ // name this misses.
14
+ const RELATIVE_RANGES = {
15
+ thisWeek: true,
16
+ lastWeek: true,
17
+ last7Days: true,
18
+ last30Days: true,
19
+ last3Months: true,
20
+ last6Months: true,
21
+ last12Months: true,
22
+ thisMonth: true,
23
+ thisQuarter: true,
24
+ thisYear: true,
25
+ yearToDate: true,
26
+ };
27
+ // The same names as a list, in the server enum's order (the record's key
28
+ // order): the order the date picker offers them in.
29
+ export const RELATIVE_RANGE_NAMES = Object.keys(RELATIVE_RANGES);
30
+ // The keys a group value may hold, by its group's type.
31
+ const GROUP_VALUE_KEYS = {
32
+ dateRange: ['relative', 'start', 'end'],
33
+ select: ['values', 'excludeValues'],
34
+ keyword: ['value'],
35
+ numberRange: ['min', 'max'],
36
+ };
37
+ // The keys of a view document and of a tile state this viewer reads. Any
38
+ // other key is kept as it was.
39
+ const VIEW_CONFIG_KEYS = ['v', 'pageId', 'groupBy', 'match', 'groups', 'tiles'];
40
+ const TILE_STATE_KEYS = ['sort', 'search', 'hidden', 'drill'];
41
+ const DAY_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
42
+ // A number as text: what a masked input sends.
43
+ const NUMBER_PATTERN = /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i;
44
+ const ID_KEY_PATTERN = /^[1-9]\d*$/;
45
+ // Whether a name is a relative range the server resolves.
46
+ export function isRelativeRange(name) {
47
+ return typeof name === 'string' && Object.prototype.hasOwnProperty.call(RELATIVE_RANGES, name);
48
+ }
49
+ export function isChartGranularity(value) {
50
+ return GRANULARITY_OPTIONS.some((option) => option.value === value);
51
+ }
52
+ // Whether text is a real calendar day written 'yyyy-MM-dd' (no 2026-02-30).
53
+ export function isCalendarDay(text) {
54
+ const parts = DAY_PATTERN.exec(text);
55
+ if (!parts) {
56
+ return false;
57
+ }
58
+ const [year, month, day] = parts.slice(1).map(Number);
59
+ const date = new Date(Date.UTC(year, month - 1, day));
60
+ return date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day;
61
+ }
62
+ // A number written as text (a masked input's value), or null when the text
63
+ // is not one finite number.
64
+ export function numberFromText(text) {
65
+ const number = NUMBER_PATTERN.test(text) ? Number(text) : NaN;
66
+ return Number.isFinite(number) ? number : null;
67
+ }
68
+ // A group value read for a group of `type`, on its way to being stored: only
69
+ // the parts that hold something. Throws, naming what is wrong, when a key
70
+ // does not belong to the type or a part breaks its type's rule.
71
+ export function groupValueFromArray(value, type) {
72
+ requireGroupKeys(value, type);
73
+ switch (type) {
74
+ case 'dateRange':
75
+ return dateRangeValue(value);
76
+ case 'select':
77
+ return selectValue(value);
78
+ case 'numberRange':
79
+ return numberRangeValue(value);
80
+ default:
81
+ return keywordValue(value);
82
+ }
83
+ }
84
+ // A group value read back (a saved view) for a group of `type`: what
85
+ // groupValueFromArray gives, or null when it would refuse it.
86
+ export function groupValueFromStored(value, type) {
87
+ if (!isPlainObject(value)) {
88
+ return null;
89
+ }
90
+ try {
91
+ return groupValueFromArray(value, type);
92
+ }
93
+ catch {
94
+ return null;
95
+ }
96
+ }
97
+ // A view document read for storing or applying. Throws when it is not a
98
+ // version 1 document, breaks a cap or holds a malformed known key.
99
+ export function viewConfigFromArray(input) {
100
+ const doc = requireObject(input, 'A view config must be an object.');
101
+ requireSize(doc);
102
+ requireVersion(doc.v);
103
+ const config = { v: REPORT_VIEW_CONFIG_VERSION, ...otherKeys(doc, VIEW_CONFIG_KEYS) };
104
+ const pageId = optionalId(doc.pageId, 'pageId must be a page id.');
105
+ if (pageId !== null) {
106
+ config.pageId = pageId;
107
+ }
108
+ if (isSet(doc.groupBy)) {
109
+ config.groupBy = requireGranularity(doc.groupBy, 'groupBy must be a time grain.');
110
+ }
111
+ if (isSet(doc.match)) {
112
+ config.match = requireMatch(doc.match);
113
+ }
114
+ if (isSet(doc.groups)) {
115
+ config.groups = viewGroups(doc.groups);
116
+ }
117
+ if (isSet(doc.tiles)) {
118
+ config.tiles = viewTiles(doc.tiles);
119
+ }
120
+ return config;
121
+ }
122
+ // A group's value as a view stores it, read for the keys its
123
+ // group's type owns, or null when it holds nothing. A date range that still
124
+ // carries its relative preset is stored as that preset whatever today is: the
125
+ // viewer did not edit it, so a view saved after midnight with the page still
126
+ // open keeps rolling.
127
+ export function toStoredGroupValue(type, value) {
128
+ if (!value) {
129
+ return null;
130
+ }
131
+ switch (type) {
132
+ case 'dateRange':
133
+ return isRelativeRange(value.preset)
134
+ ? { relative: value.preset }
135
+ : storedOrNull({ start: dateBoundString(value.start), end: dateBoundString(value.end) });
136
+ case 'select': {
137
+ const excludeValues = keptPicks(value.excludeValues);
138
+ return storedOrNull(excludeValues ? { excludeValues } : { values: keptPicks(value.values) });
139
+ }
140
+ case 'numberRange':
141
+ return storedOrNull({ min: finiteNumber(value.min), max: finiteNumber(value.max) });
142
+ default:
143
+ return storedOrNull({ value: value.value?.trim() || undefined });
144
+ }
145
+ }
146
+ // A group value in its stored shape as the value the bars and the requests
147
+ // read: a relative preset as today's days in the report's zone, carrying its
148
+ // name; fixed days as dates; any other value as it is. Null when it holds
149
+ // nothing, or names a preset `resolveRelative` does not know.
150
+ export function toLiveGroupValue(type, stored, resolveRelative) {
151
+ if (!stored || holdsNothing(stored)) {
152
+ return null;
153
+ }
154
+ if (type !== 'dateRange') {
155
+ return { ...stored };
156
+ }
157
+ if (stored.relative) {
158
+ const range = resolveRelative(stored.relative);
159
+ return range ? { start: range.start, end: range.end, preset: stored.relative } : null;
160
+ }
161
+ return { start: dateFromBound(stored.start), end: dateFromBound(stored.end) };
162
+ }
163
+ // Whether the screen's state differs from the view it opened on. `current`
164
+ // is a snapshot, so it holds every group the report has; a group only `base`
165
+ // holds is one the report no longer has, and is not compared. A group `base`
166
+ // does not hold was added after the view was saved: it is compared with its
167
+ // value in `authored` (the report's defaults), so leaving it at its default
168
+ // changes nothing. The page is not compared (moving to another page does not
169
+ // edit a view), and neither are keys this viewer does not know. Picks are
170
+ // compared in any order.
171
+ export function viewDiffers(base, current, authored = null) {
172
+ return (base.match ?? 'all') !== (current.match ?? 'all')
173
+ || (base.groupBy ?? null) !== (current.groupBy ?? null)
174
+ || groupsDiffer(base, current, authored)
175
+ || tilesDiffer(base.tiles ?? {}, current.tiles ?? {});
176
+ }
177
+ // Whether two stored group values are the same filter, as viewDiffers reads
178
+ // a group: picks in any order, text trimmed, an empty value read as none.
179
+ export function sameStoredGroupValue(a, b) {
180
+ return storedValueKey(a) === storedValueKey(b);
181
+ }
182
+ // A drill path kept to what a tile can carry: its steps up to the first that
183
+ // is not a time level with a plain value (the steps before it are kept), at
184
+ // most DRILL_MAX_DEPTH of them.
185
+ export function cleanDrillPath(path) {
186
+ const kept = [];
187
+ for (const step of path ?? []) {
188
+ if (!isPlainObject(step) || !isChartGranularity(step.level) || !isDrillValue(step.value)
189
+ || kept.length === DRILL_MAX_DEPTH) {
190
+ break;
191
+ }
192
+ kept.push({ level: step.level, value: step.value });
193
+ }
194
+ return kept;
195
+ }
196
+ // Whether two drill paths are the same steps. A value is compared as text,
197
+ // so 2026 and '2026' are the same step.
198
+ export function sameDrillPath(a, b) {
199
+ return drillKey(a) === drillKey(b);
200
+ }
201
+ // A view's config to save: the screen (`screen`, a snapshot), with the keys
202
+ // this viewer does not know kept from the stored document (`stored`), at the
203
+ // top and in each tile. They are never read here, and saving must not lose
204
+ // them.
205
+ export function withStoredKeys(stored, screen) {
206
+ if (!stored) {
207
+ return screen;
208
+ }
209
+ const tiles = { ...screen.tiles };
210
+ Object.entries(stored.tiles ?? {}).forEach(([componentId, tile]) => {
211
+ const kept = isPlainObject(tile) ? otherKeys(tile, TILE_STATE_KEYS) : {};
212
+ if (Object.keys(kept).length) {
213
+ tiles[Number(componentId)] = { ...kept, ...tiles[Number(componentId)] };
214
+ }
215
+ });
216
+ const config = { ...otherKeys(stored, VIEW_CONFIG_KEYS), ...screen };
217
+ delete config.tiles;
218
+ return Object.keys(tiles).length ? { ...config, tiles } : config;
219
+ }
220
+ // How many settings of a saved view no longer apply because the report
221
+ // changed: what the server left out when it read the view (`dropped`), and
222
+ // what the viewer could not apply (`applied` is the view as it applied, the
223
+ // state service's base): a group value that no longer fits its group, and a
224
+ // list sort, search or hidden columns, or a chart's drill path, its tile can
225
+ // no longer take (a list column gone, a chart turned into a list).
226
+ export function viewDroppedCount(view, applied) {
227
+ const dropped = view.dropped;
228
+ const groups = Object.entries(view.config?.groups ?? {})
229
+ .filter(([groupId, value]) => value !== null && !Object.prototype.hasOwnProperty.call(applied.groups ?? {}, groupId))
230
+ .length;
231
+ const tiles = Object.entries(view.config?.tiles ?? {})
232
+ .reduce((count, [componentId, tile]) => count + tileKeysLost(tile, applied.tiles?.[Number(componentId)]), 0);
233
+ return (dropped?.groups?.length ?? 0) + (dropped?.tiles?.length ?? 0) + (dropped?.page ? 1 : 0) + groups + tiles;
234
+ }
235
+ // The note a view opens with when some of its settings no longer apply, or
236
+ // null when every setting applies. Only a viewer who may change the view
237
+ // (`canChange`) is told to save it.
238
+ export function viewDroppedMessage(count, canChange = true) {
239
+ if (count < 1) {
240
+ return null;
241
+ }
242
+ const note = count === 1
243
+ ? '1 setting in this view no longer applies, because the report changed.'
244
+ : `${count} settings in this view no longer apply, because the report changed.`;
245
+ return canChange ? `${note} Save changes to update the view.` : note;
246
+ }
247
+ // The open view as a chat turn names it: its id, and whether the screen
248
+ // differs from it. Both are left out while no view is open.
249
+ export function chatViewFields(openView, viewChanged) {
250
+ return openView ? { viewId: openView.id, viewChanged } : {};
251
+ }
252
+ function groupsDiffer(base, current, authored) {
253
+ return Object.entries(current.groups ?? {}).some(([groupId, value]) => {
254
+ const kept = base.groups && Object.prototype.hasOwnProperty.call(base.groups, groupId)
255
+ ? base.groups[Number(groupId)]
256
+ : authored?.groups?.[Number(groupId)];
257
+ return storedValueKey(kept) !== storedValueKey(value);
258
+ });
259
+ }
260
+ function tilesDiffer(base, current) {
261
+ const ids = new Set([...Object.keys(base), ...Object.keys(current)].map(Number));
262
+ return [...ids].some((componentId) => tileStateKey(base[componentId]) !== tileStateKey(current[componentId]));
263
+ }
264
+ // How many keys of a stored tile state the tile, as it applied, lost: a
265
+ // sort, a search or a drill path it no longer has, and hidden columns it
266
+ // kept fewer of.
267
+ function tileKeysLost(stored, applied) {
268
+ if (!stored) {
269
+ return 0;
270
+ }
271
+ return [
272
+ !!stored.sort?.column && !applied?.sort?.column,
273
+ !!stored.search && !applied?.search,
274
+ (stored.hidden?.length ?? 0) > (applied?.hidden?.length ?? 0),
275
+ (stored.drill?.length ?? 0) > 0 && !applied?.drill?.length,
276
+ ].filter(Boolean).length;
277
+ }
278
+ // One text for a stored group value, the same for every way of writing the
279
+ // same filter: picks in any order, text trimmed, and an empty value read as
280
+ // none.
281
+ function storedValueKey(value) {
282
+ const stored = value ?? {};
283
+ const picks = (list) => [...(keptPicks(list) ?? [])].map(String).sort();
284
+ return JSON.stringify([
285
+ stored.relative ?? null,
286
+ stored.start?.slice(0, 10) ?? null,
287
+ stored.end?.slice(0, 10) ?? null,
288
+ picks(stored.values),
289
+ picks(stored.excludeValues),
290
+ (stored.value ?? '').trim(),
291
+ finiteNumber(stored.min) ?? null,
292
+ finiteNumber(stored.max) ?? null,
293
+ ]);
294
+ }
295
+ // One text for a tile's state, over the keys this viewer reads. No direction
296
+ // reads as ascending, the way a list applies it.
297
+ function tileStateKey(tile) {
298
+ return JSON.stringify([
299
+ tile?.sort?.column ? [tile.sort.column, tile.sort.direction ?? 'asc'] : null,
300
+ tile?.search ?? '',
301
+ [...(tile?.hidden ?? [])].sort(),
302
+ drillKey(tile?.drill),
303
+ ]);
304
+ }
305
+ function drillKey(path) {
306
+ return JSON.stringify((path ?? [])
307
+ .map((step) => [step.level, step.value === null || step.value === undefined ? null : String(step.value)]));
308
+ }
309
+ // The picks of a list with blanks (null, '') left out, or undefined when none
310
+ // is left.
311
+ function keptPicks(list) {
312
+ const kept = (list ?? []).filter((pick) => isSet(pick) && pick !== '');
313
+ return kept.length ? kept : undefined;
314
+ }
315
+ // A range end as a number. A masked input sends its number as text, so
316
+ // numeric text is read as its number, as boundPart reads it.
317
+ export function finiteNumber(value) {
318
+ const number = typeof value === 'string' ? numberFromText(value.trim()) : value;
319
+ return typeof number === 'number' && Number.isFinite(number) ? number : undefined;
320
+ }
321
+ // Whether a stored value reads the same as no value at all.
322
+ function holdsNothing(stored) {
323
+ return storedValueKey(stored) === storedValueKey(null);
324
+ }
325
+ // Only the parts that hold something, or null when none does.
326
+ function storedOrNull(value) {
327
+ const stored = compact(value);
328
+ return Object.keys(stored).length ? stored : null;
329
+ }
330
+ function requireGroupKeys(value, type) {
331
+ const allowed = GROUP_VALUE_KEYS[type] ?? GROUP_VALUE_KEYS.keyword;
332
+ const unknown = Object.keys(value).filter((key) => !allowed.includes(key));
333
+ if (unknown.length) {
334
+ throw new Error(`A ${type} default takes ${allowed.join(', ')} — not ${unknown.join(', ')}.`);
335
+ }
336
+ }
337
+ // A relative range, or fixed days; never both.
338
+ function dateRangeValue(value) {
339
+ const relative = textPart(value, 'relative');
340
+ const start = dayPart(value, 'start');
341
+ const end = dayPart(value, 'end');
342
+ if (relative === '') {
343
+ return compact({ start, end });
344
+ }
345
+ if (start !== null || end !== null) {
346
+ throw new Error('A dateRange default is either a relative preset or a fixed start/end, not both.');
347
+ }
348
+ if (!isRelativeRange(relative)) {
349
+ throw new Error(`relative must be one of: ${Object.keys(RELATIVE_RANGES).join(', ')}.`);
350
+ }
351
+ return { relative };
352
+ }
353
+ // The values to keep or the values to leave out; never both.
354
+ function selectValue(value) {
355
+ const values = pickList(value, 'values');
356
+ const excludeValues = pickList(value, 'excludeValues');
357
+ if (values !== null && excludeValues !== null) {
358
+ throw new Error('A select default either keeps values or leaves out exclude_values, not both.');
359
+ }
360
+ return compact({ values, excludeValues });
361
+ }
362
+ function keywordValue(value) {
363
+ const text = textPart(value, 'value');
364
+ return text !== '' ? { value: text } : {};
365
+ }
366
+ // Either end may be open; 0 is an end like any other.
367
+ function numberRangeValue(value) {
368
+ const min = boundPart(value, 'min');
369
+ const max = boundPart(value, 'max');
370
+ if (min !== null && max !== null && min > max) {
371
+ throw new Error(`min (${min}) is above max (${max}).`);
372
+ }
373
+ return compact({ min, max });
374
+ }
375
+ // The text `key` holds, trimmed, or '' when absent. A number is read as its
376
+ // text; any other kind is refused.
377
+ function textPart(value, key) {
378
+ const text = value[key];
379
+ if (text === undefined || text === null) {
380
+ return '';
381
+ }
382
+ if (typeof text !== 'string' && typeof text !== 'number') {
383
+ throw new Error(`${key} must be text.`);
384
+ }
385
+ return String(text).trim();
386
+ }
387
+ // A calendar-day bound: its first ten characters must be a real day.
388
+ function dayPart(value, key) {
389
+ const text = textPart(value, key);
390
+ if (text === '') {
391
+ return null;
392
+ }
393
+ const day = text.slice(0, 10);
394
+ if (!isCalendarDay(day)) {
395
+ throw new Error(`${key} must be a yyyy-MM-dd day.`);
396
+ }
397
+ return day;
398
+ }
399
+ // The picks of `key` with blanks (null, '') dropped, or null when none is
400
+ // left. A lone pick is a list of one; a pick that is a list or an object is
401
+ // refused.
402
+ function pickList(value, key) {
403
+ const raw = value[key] ?? [];
404
+ const picks = Array.isArray(raw) ? raw : [raw];
405
+ if (picks.some((pick) => isSet(pick) && !isScalar(pick))) {
406
+ throw new Error(`Each pick in ${key} must be a plain value, not a list.`);
407
+ }
408
+ const kept = picks.filter((pick) => isSet(pick) && pick !== '');
409
+ return kept.length ? kept : null;
410
+ }
411
+ // One end of a number range: null when absent or blank, else a finite number
412
+ // (numeric text is read as its number).
413
+ function boundPart(value, key) {
414
+ const raw = typeof value[key] === 'string' ? value[key].trim() : value[key];
415
+ if (!isSet(raw) || raw === '') {
416
+ return null;
417
+ }
418
+ const bound = typeof raw === 'string' ? numberFromText(raw) : raw;
419
+ if (typeof bound !== 'number' || !Number.isFinite(bound)) {
420
+ throw new Error(`${key} must be a finite number.`);
421
+ }
422
+ return bound;
423
+ }
424
+ function requireSize(doc) {
425
+ if (new TextEncoder().encode(JSON.stringify(doc)).length > VIEW_CONFIG_MAX_BYTES) {
426
+ throw new Error('A view config is over 32 KB.');
427
+ }
428
+ }
429
+ function requireVersion(version) {
430
+ if (!isSet(version)) {
431
+ throw new Error('A view config needs its version (v).');
432
+ }
433
+ if (version !== REPORT_VIEW_CONFIG_VERSION) {
434
+ throw new Error(`This viewer reads view config version ${REPORT_VIEW_CONFIG_VERSION} only.`);
435
+ }
436
+ }
437
+ function requireMatch(match) {
438
+ if (match !== 'all' && match !== 'any') {
439
+ throw new Error('match must be all or any.');
440
+ }
441
+ return match;
442
+ }
443
+ // Group id -> value. A value no group type could hold is dropped whole.
444
+ function viewGroups(raw) {
445
+ const entries = Object.entries(requireObject(raw, 'groups must map group ids to values.'));
446
+ if (entries.length > VIEW_CONFIG_MAX_GROUPS) {
447
+ throw new Error(`A view holds at most ${VIEW_CONFIG_MAX_GROUPS} groups.`);
448
+ }
449
+ const groups = {};
450
+ entries.forEach(([key, value]) => {
451
+ const id = requireIdKey(key, 'groups');
452
+ requirePickCount(value);
453
+ const kept = value === null ? null : storedGroupValue(value);
454
+ if (kept !== undefined) {
455
+ groups[id] = kept;
456
+ }
457
+ });
458
+ return groups;
459
+ }
460
+ // A stored group value, read for the one type its keys belong to (an empty
461
+ // value fits every type), or undefined when it fits none.
462
+ function storedGroupValue(value) {
463
+ if (!isPlainObject(value)) {
464
+ return undefined;
465
+ }
466
+ const keys = Object.keys(value);
467
+ const type = Object.keys(GROUP_VALUE_KEYS)
468
+ .find((candidate) => keys.every((key) => GROUP_VALUE_KEYS[candidate].includes(key)));
469
+ return type ? (groupValueFromStored(value, type) ?? undefined) : undefined;
470
+ }
471
+ function requirePickCount(value) {
472
+ const lists = isPlainObject(value) ? [value.values, value.excludeValues] : [];
473
+ if (lists.some((list) => Array.isArray(list) && list.length > GROUP_VALUE_MAX_PICKS)) {
474
+ throw new Error(`A group value holds at most ${GROUP_VALUE_MAX_PICKS} values.`);
475
+ }
476
+ }
477
+ // Component id -> tile state.
478
+ function viewTiles(raw) {
479
+ const entries = Object.entries(requireObject(raw, 'tiles must map component ids to tile states.'));
480
+ if (entries.length > VIEW_CONFIG_MAX_TILES) {
481
+ throw new Error(`A view holds at most ${VIEW_CONFIG_MAX_TILES} tiles.`);
482
+ }
483
+ const tiles = {};
484
+ entries.forEach(([key, value]) => {
485
+ tiles[requireIdKey(key, 'tiles')] = viewTile(value);
486
+ });
487
+ return tiles;
488
+ }
489
+ function viewTile(raw) {
490
+ const tile = requireObject(raw, 'A tile state must be an object.');
491
+ const state = otherKeys(tile, TILE_STATE_KEYS);
492
+ if (isSet(tile.sort)) {
493
+ state.sort = viewSort(tile.sort);
494
+ }
495
+ if (isSet(tile.search)) {
496
+ state.search = requireString(tile.search, 'search must be text.');
497
+ }
498
+ if (isSet(tile.hidden)) {
499
+ state.hidden = viewHidden(tile.hidden);
500
+ }
501
+ if (isSet(tile.drill)) {
502
+ state.drill = viewDrill(tile.drill);
503
+ }
504
+ return state;
505
+ }
506
+ function viewSort(raw) {
507
+ const sort = requireObject(raw, 'sort must be a column and a direction.');
508
+ const column = requireString(sort.column, 'sort must name a column.');
509
+ if (column === '' || (isSet(sort.direction) && sort.direction !== 'asc' && sort.direction !== 'desc')) {
510
+ throw new Error('sort must be a column and a direction.');
511
+ }
512
+ return sort.direction ? { column, direction: sort.direction } : { column };
513
+ }
514
+ function viewHidden(raw) {
515
+ if (!Array.isArray(raw) || raw.some((name) => typeof name !== 'string')) {
516
+ throw new Error('hidden must list column names.');
517
+ }
518
+ return [...raw];
519
+ }
520
+ function viewDrill(raw) {
521
+ if (!Array.isArray(raw)) {
522
+ throw new Error('drill must list steps.');
523
+ }
524
+ if (raw.length > DRILL_MAX_DEPTH) {
525
+ throw new Error(`A drill path holds at most ${DRILL_MAX_DEPTH} steps.`);
526
+ }
527
+ return raw.map((step) => {
528
+ if (!isPlainObject(step) || !isChartGranularity(step.level) || !isDrillValue(step.value)) {
529
+ throw new Error('A drill step needs a time level and a value.');
530
+ }
531
+ return { level: step.level, value: step.value };
532
+ });
533
+ }
534
+ function isDrillValue(value) {
535
+ return value === null || typeof value === 'string' || typeof value === 'number';
536
+ }
537
+ // The keys of `source` that are not in `known`, as they were.
538
+ function otherKeys(source, known) {
539
+ return Object.fromEntries(Object.entries(source).filter(([key]) => !known.includes(key)));
540
+ }
541
+ function optionalId(raw, refusal) {
542
+ if (!isSet(raw)) {
543
+ return null;
544
+ }
545
+ if (!Number.isInteger(raw) || raw < 1) {
546
+ throw new Error(refusal);
547
+ }
548
+ return raw;
549
+ }
550
+ function requireIdKey(key, where) {
551
+ if (!ID_KEY_PATTERN.test(key)) {
552
+ throw new Error(`${where} are keyed by id, not by '${key}'.`);
553
+ }
554
+ return Number(key);
555
+ }
556
+ function requireGranularity(raw, refusal) {
557
+ if (!isChartGranularity(raw)) {
558
+ throw new Error(refusal);
559
+ }
560
+ return raw;
561
+ }
562
+ function requireString(raw, refusal) {
563
+ if (typeof raw !== 'string') {
564
+ throw new Error(refusal);
565
+ }
566
+ return raw;
567
+ }
568
+ function requireObject(raw, refusal) {
569
+ if (!isPlainObject(raw)) {
570
+ throw new Error(refusal);
571
+ }
572
+ return raw;
573
+ }
574
+ function isSet(value) {
575
+ return value !== undefined && value !== null;
576
+ }
577
+ function isPlainObject(value) {
578
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
579
+ }
580
+ function isScalar(value) {
581
+ return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';
582
+ }
583
+ // Only the parts that hold something.
584
+ function compact(value) {
585
+ return Object.fromEntries(Object.entries(value).filter(([, part]) => isSet(part)));
586
+ }
587
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LXZpZXctY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL3JlcG9ydC12aWV3LWNvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUEwQkEsT0FBTyxFQUlMLG1CQUFtQixHQUlwQixNQUFNLCtCQUErQixDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxlQUFlLEVBQUUsYUFBYSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFHdkUsNENBQTRDO0FBQzVDLE1BQU0sQ0FBQyxNQUFNLDBCQUEwQixHQUFHLENBQUMsQ0FBQztBQUU1Qyw2Q0FBNkM7QUFDN0MsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUMvQyxNQUFNLENBQUMsTUFBTSxzQkFBc0IsR0FBRyxHQUFHLENBQUM7QUFDMUMsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUcsR0FBRyxDQUFDO0FBQ3pDLE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUFHLEdBQUcsQ0FBQztBQUN6QyxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsQ0FBQyxDQUFDO0FBRWpDLDRFQUE0RTtBQUM1RSwwRUFBMEU7QUFDMUUsb0JBQW9CO0FBQ3BCLE1BQU0sZUFBZSxHQUFzQztJQUN6RCxRQUFRLEVBQUUsSUFBSTtJQUNkLFFBQVEsRUFBRSxJQUFJO0lBQ2QsU0FBUyxFQUFFLElBQUk7SUFDZixVQUFVLEVBQUUsSUFBSTtJQUNoQixXQUFXLEVBQUUsSUFBSTtJQUNqQixXQUFXLEVBQUUsSUFBSTtJQUNqQixZQUFZLEVBQUUsSUFBSTtJQUNsQixTQUFTLEVBQUUsSUFBSTtJQUNmLFdBQVcsRUFBRSxJQUFJO0lBQ2pCLFFBQVEsRUFBRSxJQUFJO0lBQ2QsVUFBVSxFQUFFLElBQUk7Q0FDakIsQ0FBQztBQUVGLHlFQUF5RTtBQUN6RSxvREFBb0Q7QUFDcEQsTUFBTSxDQUFDLE1BQU0sb0JBQW9CLEdBQUcsTUFBTSxD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QUMsR0FBWSxFQUFFLE9BQWU7SUFDbEQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3hCLE1BQU0sSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDM0IsQ0FBQztJQUVELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQztBQUVELFNBQVMsS0FBSyxDQUFDLEtBQWM7SUFDM0IsT0FBTyxLQUFLLEtBQUssU0FBUyxJQUFJLEtBQUssS0FBSyxJQUFJLENBQUM7QUFDL0MsQ0FBQztBQUVELFNBQVMsYUFBYSxDQUFDLEtBQWM7SUFDbkMsT0FBTyxLQUFLLEtBQUssSUFBSSxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDOUUsQ0FBQztBQUVELFNBQVMsUUFBUSxDQUFDLEtBQWM7SUFDOUIsT0FBTyxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLE9BQU8sS0FBSyxLQUFLLFNBQVMsQ0FBQztBQUM5RixDQUFDO0FBRUQsc0NBQXNDO0FBQ3RDLFNBQVMsT0FBTyxDQUFDLEtBQThCO0lBQzdDLE9BQU8sTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQXVCLENBQUM7QUFDM0csQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIFRoZSB2aWV3ZXIncyBkdXJhYmxlIHN0YXRlIGFzIG9uZSBkb2N1bWVudCAoUmVwb3J0Vmlld0NvbmZpZywgdmVyc2lvbiAxKTogYVxuLy8gc2F2ZWQgdmlldydzIGNvbmZpZy5cbi8vIFB1cmUsIHNvIHRoZSBub2RlIGhhcm5lc3MgcnVucyBpdCBhZ2FpbnN0IHRoZSBzZXJ2ZXIncyBvd24gY2FzZSB0YWJsZTogdGhlXG4vLyBydWxlcyBiZWxvdyBtaXJyb3IgdGhlIHNlcnZlcidzIFJlcG9ydFZpZXdDb25maWcgYW5kIFJlcG9ydEZpbHRlckdyb3VwVmFsdWVcbi8vIERUT3MsIGFuZCB0aGUgdHdvIG11c3QgYWdyZWUgb24gZXZlcnkgY2FzZS5cbi8vXG4vLyAtIEEgZ3JvdXAgdmFsdWUgdGFrZXMgdGhlIGtleXMgaXRzIGdyb3VwJ3MgdHlwZSBvd25zIChncm91cFZhbHVlRnJvbUFycmF5KS5cbi8vICAgT25lIHdyaXR0ZW4gaW4gYSBzaGFwZSB0aGF0IGRvZXMgbm90IGZpdCBpcyByZWZ1c2VkLCBuYW1pbmcgd2hhdCBpc1xuLy8gICB3cm9uZzsgb25lIHJlYWQgYmFjayB0aGF0IGRvZXMgbm90IGZpdCBpcyBkcm9wcGVkIHdob2xlLCBuZXZlciBhcHBsaWVkIGluXG4vLyAgIHBhcnQgKGdyb3VwVmFsdWVGcm9tU3RvcmVkKS5cbi8vIC0gQSBkb2N1bWVudCAodmlld0NvbmZpZ0Zyb21BcnJheSkgaXMgcmVmdXNlZCB3aGVuIGl0IGlzIG5vdCBvbmUsIGJyZWFrcyBhXG4vLyAgIGNhcCBvciBob2xkcyBhIG1hbGZvcm1lZCBrbm93biBrZXkuIEtleXMgdGhpcyB2aWV3ZXIgZG9lcyBub3Qga25vdywgYXRcbi8vICAgdGhlIHRvcCBhbmQgaW4gYSB0aWxlLCBhcmUga2VwdCBhcyB0aGV5IHdlcmUgYW5kIG5ldmVyIHJlYWQuIEEgZ3JvdXBcbi8vICAgdmFsdWUgdGhhdCBubyBncm91cCB0eXBlIGNvdWxkIGhvbGQgaXMgZHJvcHBlZCB3aG9sZS5cbi8vIC0gVGhlIHZpZXdlcidzIHN0YXRlIHNlcnZpY2UgdHVybnMgaXRzIHZhbHVlcyBpbnRvIHRoaXMgc2hhcGUgYW5kIGJhY2tcbi8vICAgKHRvU3RvcmVkR3JvdXBWYWx1ZSwgdG9MaXZlR3JvdXBWYWx1ZSksIGFuZCBhc2tzIHZpZXdEaWZmZXJzIHdoZXRoZXIgdGhlXG4vLyAgIHNjcmVlbiBzdGlsbCBzaG93cyB0aGUgb3BlbiB2aWV3LlxuLy8gLSBUaGUgdmlldyBzZXJ2aWNlIChSZXBvcnRWaWV3U2VydmljZSkgc2F2ZXMgYSB2aWV3IHRocm91Z2ggd2l0aFN0b3JlZEtleXNcbi8vICAgYW5kIGNvdW50cyB3aGF0IGEgdmlldyBsb3N0IHRocm91Z2ggdmlld0Ryb3BwZWRDb3VudDsgdGhlIGNoYXQgbmFtZXMgdGhlXG4vLyAgIG9wZW4gdmlldyB0aHJvdWdoIGNoYXRWaWV3RmllbGRzLlxuaW1wb3J0IHsgUmVwb3J0Q2hhdFZpZXdlclN0YXRlIH0gZnJvbSAnLi9pbnRlcmZhY2VzL3JlcG9ydC1jaGF0LXZpZXdlci1zdGF0ZS5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVwb3J0RHJpbGxTdGVwIH0gZnJvbSAnLi9pbnRlcmZhY2VzL3JlcG9ydC1kcmlsbC1zdGVwLmludGVyZmFjZSc7XG5pbXBvcnQgeyBSZXBvcnRUaWxlU3RhdGUgfSBmcm9tICcuL2ludGVyZmFjZXMvcmVwb3J0LXRpbGUtc3RhdGUuaW50ZXJmYWNlJztcbmltcG9ydCB7IFJlcG9ydFZpZXdDb25maWcgfSBmcm9tICcuL2ludGVyZmFjZXMvcmVwb3J0LXZpZXctY29uZmlnLmludGVyZmFjZSc7XG5pbXBvcnQgeyBSZXBvcnRWaWV3U3VtbWFyeSB9IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQtdmlldy1zdW1tYXJ5LmludGVyZmFjZSc7XG5pbXBvcnQgeyBSZXBvcnRWaWV3IH0gZnJvbSAnLi9pbnRlcmZhY2VzL3JlcG9ydC12aWV3LmludGVyZmFjZSc7XG5pbXBvcnQge1xuICBDaGFydEdyYW51bGFyaXR5LFxuICBGaWx0ZXJHcm91cERlZmF1bHQsXG4gIEZpbHRlckdyb3VwVmFsdWUsXG4gIEdSQU5VTEFSSVRZX09QVElPTlMsXG4gIFJlcG9ydEZpbHRlclR5cGUsXG4gIFJlcG9ydFJlbGF0aXZlUmFuZ2UsXG4gIFJlcG9ydFNvcnQsXG59IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcbmltcG9ydCB7IGRhdGVCb3VuZFN0cmluZywgZGF0ZUZyb21Cb3VuZCB9IGZyb20gJy4vcmVwb3J0LWZpbHRlci1pdGVtcyc7XG5cblxuLy8gVGhlIHZlcnNpb24gdGhpcyB2aWV3ZXIgd3JpdGVzIGFuZCByZWFkcy5cbmV4cG9ydCBjb25zdCBSRVBPUlRfVklFV19DT05GSUdfVkVSU0lPTiA9IDE7XG5cbi8vIFRoZSBjYXBzIG9mIGEgdmlldyBkb2N1bWVudCwgdGhlIHNlcnZlcidzLlxuZXhwb3J0IGNvbnN0IFZJRVdfQ09ORklHX01BWF9CWVRFUyA9IDMyICogMTAyNDtcbmV4cG9ydCBjb25zdCBWSUVXX0NPTkZJR19NQVhfR1JPVVBTID0gMTAwO1xuZXhwb3J0IGNvbnN0IFZJRVdfQ09ORklHX01BWF9USUxFUyA9IDIwMDtcbmV4cG9ydCBjb25zdCBHUk9VUF9WQUxVRV9NQVhfUElDS1MgPSA1MDA7XG5leHBvcnQgY29uc3QgRFJJTExfTUFYX0RFUFRIID0gNTtcblxuLy8gRXZlcnkgcmVsYXRpdmUgcmFuZ2UgbmFtZSB0aGUgc2VydmVyIGtub3dzLCBpbiBpdHMgZW51bSdzIG9yZGVyLiBBIHJlY29yZFxuLy8gcmF0aGVyIHRoYW4gYSBsaXN0LCBzbyB0aGUgYnVpbGQgZmFpbHMgd2hlbiBSZXBvcnRSZWxhdGl2ZVJhbmdlIGdhaW5zIGFcbi8vIG5hbWUgdGhpcyBtaXNzZXMuXG5jb25zdCBSRUxBVElWRV9SQU5HRVM6IFJlY29yZDxSZXBvcnRSZWxhdGl2ZVJhbmdlLCB0cnVlPiA9IHtcbiAgdGhpc1dlZWs6IHRydWUsXG4gIGxhc3RXZWVrOiB0cnVlLFxuICBsYXN0N0RheXM6IHRydWUsXG4gIGxhc3QzMERheXM6IHRydWUsXG4gIGxhc3QzTW9udGhzOiB0cnVlLFxuICBsYXN0Nk1vbnRoczogdHJ1ZSxcbiAgbGFzdDEyTW9udGhzOiB0cnVlLFxuICB0aGlzTW9udGg6IHRydWUsXG4gIHRoaXNRdWFydGVyOiB0cnVlLFxuICB0aGlzWWVhcjogdHJ1ZSxcbiAgeWVhclRvRGF0ZTogdHJ1ZSxcbn07XG5cbi8vIFRoZSBzYW1lIG5hbWVzIGFzIGEgbGlzdCwgaW4gdGhlIHNlcnZlciBlbnVtJ3Mgb3JkZXIgKHRoZSByZWNvcmQncyBrZXlcbi8vIG9yZGVyKTogdGhlIG9yZGVyIHRoZSBkYXRlIHBpY2tlciBvZmZlcnMgdGhlbSBpbi5cbmV4cG9ydCBjb25zdCBSRUxBVElWRV9SQU5HRV9OQU1FUyA9IE9iamVjdC5rZXlzKFJFTEFUSVZFX1JBTkdFUykgYXMgUmVwb3J0UmVsYXRpdmVSYW5nZVtdO1xuXG4vLyBUaGUga2V5cyBhIGdyb3VwIHZhbHVlIG1heSBob2xkLCBieSBpdHMgZ3JvdXAncyB0eXBlLlxuY29uc3QgR1JPVVBfVkFMVUVfS0VZUzogUmVjb3JkPFJlcG9ydEZpbHRlclR5cGUsIHJlYWRvbmx5IChrZXlvZiBGaWx0ZXJHcm91cERlZmF1bHQpW10+ID0ge1xuICBkYXRlUmFuZ2U6IFsncmVsYXRpdmUnLCAnc3RhcnQnLCAnZW5kJ10sXG4gIHNlbGVjdDogWyd2YWx1ZXMnLCAnZXhjbHVkZVZhbHVlcyddLFxuICBrZXl3b3JkOiBbJ3ZhbHVlJ10sXG4gIG51bWJlclJhbmdlOiBbJ21pbicsICdtYXgnXSxcbn07XG5cbi8vIFRoZSBrZXlzIG9mIGEgdmlldyBkb2N1bWVudCBhbmQgb2YgYSB0aWxlIHN0YXRlIHRoaXMgdmlld2VyIHJlYWRzLiBBbnlcbi8vIG90aGVyIGtleSBpcyBrZXB0IGFzIGl0IHdhcy5cbmNvbnN0IFZJRVdfQ09ORklHX0tFWVMgPSBbJ3YnLCAncGFnZUlkJywgJ2dyb3VwQnknLCAnbWF0Y2gnLCAnZ3JvdXBzJywgJ3RpbGVzJ107XG5jb25zdCBUSUxFX1NUQVRFX0tFWVMgPSBbJ3NvcnQnLCAnc2VhcmNoJywgJ2hpZGRlbicsICdkcmlsbCddO1xuXG5jb25zdCBEQVlfUEFUVEVSTiA9IC9eKFxcZHs0fSktKFxcZHsyfSktKFxcZHsyfSkkLztcblxuLy8gQSBudW1iZXIgYXMgdGV4dDogd2hhdCBhIG1hc2tlZCBpbnB1dCBzZW5kcy5cbmNvbnN0IE5VTUJFUl9QQVRURVJOID0gL15bKy1dPyg/OlxcZCsoPzpcXC5cXGQqKT98XFwuXFxkKykoPzplWystXT9cXGQrKT8kL2k7XG5cbmNvbnN0IElEX0tFWV9QQVRURVJOID0gL15bMS05XVxcZCokLztcblxuXG4vLyBXaGV0aGVyIGEgbmFtZSBpcyBhIHJlbGF0aXZlIHJhbmdlIHRoZSBzZXJ2ZXIgcmVzb2x2ZXMuXG5leHBvcnQgZnVuY3Rpb24gaXNSZWxhdGl2ZVJhbmdlKG5hbWU6IHVua25vd24pOiBuYW1lIGlzIFJlcG9ydFJlbGF0aXZlUmFuZ2Uge1xuICByZXR1cm4gdHlwZW9mIG5hbWUgPT09ICdzdHJpbmcnICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChSRUxBVElWRV9SQU5HRVMsIG5hbWUpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNDaGFydEdyYW51bGFyaXR5KHZhbHVlOiB1bmtub3duKTogdmFsdWUgaXMgQ2hhcnRHcmFudWxhcml0eSB7XG4gIHJldHVybiBHUkFOVUxBUklUWV9PUFRJT05TLnNvbWUoKG9wdGlvbikgPT4gb3B0aW9uLnZhbHVlID09PSB2YWx1ZSk7XG59XG5cbi8vIFdoZXRoZXIgdGV4dCBpcyBhIHJlYWwgY2FsZW5kYXIgZGF5IHdyaXR0ZW4gJ3l5eXktTU0tZGQnIChubyAyMDI2LTAyLTMwKS5cbmV4cG9ydCBmdW5jdGlvbiBpc0NhbGVuZGFyRGF5KHRleHQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBjb25zdCBwYXJ0cyA9IERBWV9QQVRURVJOLmV4ZWModGV4dCk7XG4gIGlmICghcGFydHMpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBjb25zdCBbeWVhciwgbW9udGgsIGRheV0gPSBwYXJ0cy5zbGljZSgxKS5tYXAoTnVtYmVyKTtcbiAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKERhdGUuVVRDKHllYXIsIG1vbnRoIC0gMSwgZGF5KSk7XG5cbiAgcmV0dXJuIGRhdGUuZ2V0VVRDRnVsbFllYXIoKSA9PT0geWVhciAmJiBkYXRlLmdldFVUQ01vbnRoKCkgPT09IG1vbnRoIC0gMSAmJiBkYXRlLmdldFVUQ0RhdGUoKSA9PT0gZGF5O1xufVxuXG4vLyBBIG51bWJlciB3cml0dGVuIGFzIHRleHQgKGEgbWFza2VkIGlucHV0J3MgdmFsdWUpLCBvciBudWxsIHdoZW4gdGhlIHRleHRcbi8vIGlzIG5vdCBvbmUgZmluaXRlIG51bWJlci5cbmV4cG9ydCBmdW5jdGlvbiBudW1iZXJGcm9tVGV4dCh0ZXh0OiBzdHJpbmcpOiBudW1iZXIgfCBudWxsIHtcbiAgY29uc3QgbnVtYmVyID0gTlVNQkVSX1BBVFRFUk4udGVzdCh0ZXh0KSA/IE51bWJlcih0ZXh0KSA6IE5hTjtcblxuICByZXR1cm4gTnVtYmVyLmlzRmluaXRlKG51bWJlcikgPyBudW1iZXIgOiBudWxsO1xufVxuXG4vLyBBIGdyb3VwIHZhbHVlIHJlYWQgZm9yIGEgZ3JvdXAgb2YgYHR5cGVgLCBvbiBpdHMgd2F5IHRvIGJlaW5nIHN0b3JlZDogb25seVxuLy8gdGhlIHBhcnRzIHRoYXQgaG9sZCBzb21ldGhpbmcuIFRocm93cywgbmFtaW5nIHdoYXQgaXMgd3JvbmcsIHdoZW4gYSBrZXlcbi8vIGRvZXMgbm90IGJlbG9uZyB0byB0aGUgdHlwZSBvciBhIHBhcnQgYnJlYWtzIGl0cyB0eXBlJ3MgcnVsZS5cbmV4cG9ydCBmdW5jdGlvbiBncm91cFZhbHVlRnJvbUFycmF5KHZhbHVlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgdHlwZTogUmVwb3J0RmlsdGVyVHlwZSk6IEZpbHRlckdyb3VwRGVmYXVsdCB7XG4gIHJlcXVpcmVHcm91cEtleXModmFsdWUsIHR5cGUpO1xuXG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgJ2RhdGVSYW5nZSc6XG4gICAgICByZXR1cm4gZGF0ZVJhbmdlVmFsdWUodmFsdWUpO1xuXG4gICAgY2FzZSAnc2VsZWN0JzpcbiAgICAgIHJldHVybiBzZWxlY3RWYWx1ZSh2YWx1ZSk7XG5cbiAgICBjYXNlICdudW1iZXJSYW5nZSc6XG4gICAgICByZXR1cm4gbnVtYmVyUmFuZ2VWYWx1ZSh2YWx1ZSk7XG5cbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGtleXdvcmRWYWx1ZSh2YWx1ZSk7XG4gIH1cbn1cblxuLy8gQSBncm91cCB2YWx1ZSByZWFkIGJhY2sgKGEgc2F2ZWQgdmlldykgZm9yIGEgZ3JvdXAgb2YgYHR5cGVgOiB3aGF0XG4vLyBncm91cFZhbHVlRnJvbUFycmF5IGdpdmVzLCBvciBudWxsIHdoZW4gaXQgd291bGQgcmVmdXNlIGl0LlxuZXhwb3J0IGZ1bmN0aW9uIGdyb3VwVmFsdWVGcm9tU3RvcmVkKHZhbHVlOiB1bmtub3duLCB0eXBlOiBSZXBvcnRGaWx0ZXJUeXBlKTogRmlsdGVyR3JvdXBEZWZhdWx0IHwgbnVsbCB7XG4gIGlmICghaXNQbGFpbk9iamVjdCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHRyeSB7XG4gICAgcmV0dXJuIGdyb3VwVmFsdWVGcm9tQXJyYXkodmFsdWUsIHR5cGUpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG4vLyBBIHZpZXcgZG9jdW1lbnQgcmVhZCBmb3Igc3RvcmluZyBvciBhcHBseWluZy4gVGhyb3dzIHdoZW4gaXQgaXMgbm90IGFcbi8vIHZlcnNpb24gMSBkb2N1bWVudCwgYnJlYWtzIGEgY2FwIG9yIGhvbGRzIGEgbWFsZm9ybWVkIGtub3duIGtleS5cbmV4cG9ydCBmdW5jdGlvbiB2aWV3Q29uZmlnRnJvbUFycmF5KGlucHV0OiB1bmtub3duKTogUmVwb3J0Vmlld0NvbmZpZyB7XG4gIGNvbnN0IGRvYyA9IHJlcXVpcmVPYmplY3QoaW5wdXQsICdBIHZpZXcgY29uZmlnIG11c3QgYmUgYW4gb2JqZWN0LicpO1xuICByZXF1aXJlU2l6ZShkb2MpO1xuICByZXF1aXJlVmVyc2lvbihkb2Mudik7XG5cbiAgY29uc3QgY29uZmlnID0geyB2OiBSRVBPUlRfVklFV19DT05GSUdfVkVSU0lPTiwgLi4ub3RoZXJLZXlzKGRvYywgVklFV19DT05GSUdfS0VZUykgfSBhcyBSZXBvcnRWaWV3Q29uZmlnO1xuICBjb25zdCBwYWdlSWQgPSBvcHRpb25hbElkKGRvYy5wYWdlSWQsICdwYWdlSWQgbXVzdCBiZSBhIHBhZ2UgaWQuJyk7XG4gIGlmIChwYWdlSWQgIT09IG51bGwpIHtcbiAgICBjb25maWcucGFnZUlkID0gcGFnZUlkO1xuICB9XG5cbiAgaWYgKGlzU2V0KGRvYy5ncm91cEJ5KSkge1xuICAgIGNvbmZpZy5ncm91cEJ5ID0gcmVxdWlyZUdyYW51bGFyaXR5KGRvYy5ncm91cEJ5LCAnZ3JvdXBCeSBtdXN0IGJlIGEgdGltZSBncmFpbi4nKTtcbiAgfVxuXG4gIGlmIChpc1NldChkb2MubWF0Y2gpKSB7XG4gICAgY29uZmlnLm1hdGNoID0gcmVxdWlyZU1hdGNoKGRvYy5tYXRjaCk7XG4gIH1cblxuICBpZiAoaXNTZXQoZG9jLmdyb3VwcykpIHtcbiAgICBjb25maWcuZ3JvdXBzID0gdmlld0dyb3Vwcyhkb2MuZ3JvdXBzKTtcbiAgfVxuXG4gIGlmIChpc1NldChkb2MudGlsZXMpKSB7XG4gICAgY29uZmlnLnRpbGVzID0gdmlld1RpbGVzKGRvYy50aWxlcyk7XG4gIH1cblxuICByZXR1cm4gY29uZmlnO1xufVxuXG4vLyBBIGdyb3VwJ3MgdmFsdWUgYXMgYSB2aWV3IHN0b3JlcyBpdCwgcmVhZCBmb3IgdGhlIGtleXMgaXRzXG4vLyBncm91cCdzIHR5cGUgb3ducywgb3IgbnVsbCB3aGVuIGl0IGhvbGRzIG5vdGhpbmcuIEEgZGF0ZSByYW5nZSB0aGF0IHN0aWxsXG4vLyBjYXJyaWVzIGl0cyByZWxhdGl2ZSBwcmVzZXQgaXMgc3RvcmVkIGFzIHRoYXQgcHJlc2V0IHdoYXRldmVyIHRvZGF5IGlzOiB0aGVcbi8vIHZpZXdlciBkaWQgbm90IGVkaXQgaXQsIHNvIGEgdmlldyBzYXZlZCBhZnRlciBtaWRuaWdodCB3aXRoIHRoZSBwYWdlIHN0aWxsXG4vLyBvcGVuIGtlZXBzIHJvbGxpbmcuXG5leHBvcnQgZnVuY3Rpb24gdG9TdG9yZWRHcm91cFZhbHVlKFxuICB0eXBlOiBSZXBvcnRGaWx0ZXJUeXBlLFxuICB2YWx1ZTogRmlsdGVyR3JvdXBWYWx1ZSB8IG51bGwgfCB1bmRlZmluZWQsXG4pOiBGaWx0ZXJHcm91cERlZmF1bHQgfCBudWxsIHtcbiAgaWYgKCF2YWx1ZSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgc3dpdGNoICh0eXBlKSB7XG4gICAgY2FzZSAnZGF0ZVJhbmdlJzpcbiAgICAgIHJldHVybiBpc1JlbGF0aXZlUmFuZ2UodmFsdWUucHJlc2V0KVxuICAgICAgICA/IHsgcmVsYXRpdmU6IHZhbHVlLnByZXNldCB9XG4gICAgICAgIDogc3RvcmVkT3JOdWxsKHsgc3RhcnQ6IGRhdGVCb3VuZFN0cmluZyh2YWx1ZS5zdGFydCksIGVuZDogZGF0ZUJvdW5kU3RyaW5nKHZhbHVlLmVuZCkgfSk7XG5cbiAgICBjYXNlICdzZWxlY3QnOiB7XG4gICAgICBjb25zdCBleGNsdWRlVmFsdWVzID0ga2VwdFBpY2tzKHZhbHVlLmV4Y2x1ZGVWYWx1ZXMpO1xuXG4gICAgICByZXR1cm4gc3RvcmVkT3JOdWxsKGV4Y2x1ZGVWYWx1ZXMgPyB7IGV4Y2x1ZGVWYWx1ZXMgfSA6IHsgdmFsdWVzOiBrZXB0UGlja3ModmFsdWUudmFsdWVzKSB9KTtcbiAgICB9XG5cbiAgICBjYXNlICdudW1iZXJSYW5nZSc6XG4gICAgICByZXR1cm4gc3RvcmVkT3JOdWxsKHsgbWluOiBmaW5pdGVOdW1iZXIodmFsdWUubWluKSwgbWF4OiBmaW5pdGVOdW1iZXIodmFsdWUubWF4KSB9KTtcblxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gc3RvcmVkT3JOdWxsKHsgdmFsdWU6IHZhbHVlLnZhbHVlPy50cmltKCkgfHwgdW5kZWZpbmVkIH0pO1xuICB9XG59XG5cbi8vIEEgZ3JvdXAgdmFsdWUgaW4gaXRzIHN0b3JlZCBzaGFwZSBhcyB0aGUgdmFsdWUgdGhlIGJhcnMgYW5kIHRoZSByZXF1ZXN0c1xuLy8gcmVhZDogYSByZWxhdGl2ZSBwcmVzZXQgYXMgdG9kYXkncyBkYXlzIGluIHRoZSByZXBvcnQncyB6b25lLCBjYXJyeWluZyBpdHNcbi8vIG5hbWU7IGZpeGVkIGRheXMgYXMgZGF0ZXM7IGFueSBvdGhlciB2YWx1ZSBhcyBpdCBpcy4gTnVsbCB3aGVuIGl0IGhvbGRzXG4vLyBub3RoaW5nLCBvciBuYW1lcyBhIHByZXNldCBgcmVzb2x2ZVJlbGF0aXZlYCBkb2VzIG5vdCBrbm93LlxuZXhwb3J0IGZ1bmN0aW9uIHRvTGl2ZUdyb3VwVmFsdWUoXG4gIHR5cGU6IFJlcG9ydEZpbHRlclR5cGUsXG4gIHN0b3JlZDogRmlsdGVyR3JvdXBEZWZhdWx0IHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgcmVzb2x2ZVJlbGF0aXZlOiAobmFtZTogc3RyaW5nKSA9PiB7IHN0YXJ0OiBEYXRlOyBlbmQ6IERhdGUgfSB8IG51bGwsXG4pOiBGaWx0ZXJHcm91cFZhbHVlIHwgbnVsbCB7XG4gIGlmICghc3RvcmVkIHx8IGhvbGRzTm90aGluZyhzdG9yZWQpKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBpZiAodHlwZSAhPT0gJ2RhdGVSYW5nZScpIHtcbiAgICByZXR1cm4geyAuLi5zdG9yZWQgfTtcbiAgfVxuXG4gIGlmIChzdG9yZWQucmVsYXRpdmUpIHtcbiAgICBjb25zdCByYW5nZSA9IHJlc29sdmVSZWxhdGl2ZShzdG9yZWQucmVsYXRpdmUpO1xuXG4gICAgcmV0dXJuIHJhbmdlID8geyBzdGFydDogcmFuZ2Uuc3RhcnQsIGVuZDogcmFuZ2UuZW5kLCBwcmVzZXQ6IHN0b3JlZC5yZWxhdGl2ZSB9IDogbnVsbDtcbiAgfVxuXG4gIHJldHVybiB7IHN0YXJ0OiBkYXRlRnJvbUJvdW5kKHN0b3JlZC5zdGFydCksIGVuZDogZGF0ZUZyb21Cb3VuZChzdG9yZWQuZW5kKSB9O1xufVxuXG4vLyBXaGV0aGVyIHRoZSBzY3JlZW4ncyBzdGF0ZSBkaWZmZXJzIGZyb20gdGhlIHZpZXcgaXQgb3BlbmVkIG9uLiBgY3VycmVudGBcbi8vIGlzIGEgc25hcHNob3QsIHNvIGl0IGhvbGRzIGV2ZXJ5IGdyb3VwIHRoZSByZXBvcnQgaGFzOyBhIGdyb3VwIG9ubHkgYGJhc2VgXG4vLyBob2xkcyBpcyBvbmUgdGhlIHJlcG9ydCBubyBsb25nZXIgaGFzLCBhbmQgaXMgbm90IGNvbXBhcmVkLiBBIGdyb3VwIGBiYXNlYFxuLy8gZG9lcyBub3QgaG9sZCB3YXMgYWRkZWQgYWZ0ZXIgdGhlIHZpZXcgd2FzIHNhdmVkOiBpdCBpcyBjb21wYXJlZCB3aXRoIGl0c1xuLy8gdmFsdWUgaW4gYGF1dGhvcmVkYCAodGhlIHJlcG9ydCdzIGRlZmF1bHRzKSwgc28gbGVhdmluZyBpdCBhdCBpdHMgZGVmYXVsdFxuLy8gY2hhbmdlcyBub3RoaW5nLiBUaGUgcGFnZSBpcyBub3QgY29tcGFyZWQgKG1vdmluZyB0byBhbm90aGVyIHBhZ2UgZG9lcyBub3Rcbi8vIGVkaXQgYSB2aWV3KSwgYW5kIG5laXRoZXIgYXJlIGtleXMgdGhpcyB2aWV3ZXIgZG9lcyBub3Qga25vdy4gUGlja3MgYXJlXG4vLyBjb21wYXJlZCBpbiBhbnkgb3JkZXIuXG5leHBvcnQgZnVuY3Rpb24gdmlld0RpZmZlcnMoXG4gIGJhc2U6IFJlcG9ydFZpZXdDb25maWcsXG4gIGN1cnJlbnQ6IFJlcG9ydFZpZXdDb25maWcsXG4gIGF1dGhvcmVkOiBSZXBvcnRWaWV3Q29uZmlnIHwgbnVsbCA9IG51bGwsXG4pOiBib29sZWFuIHtcbiAgcmV0dXJuIChiYXNlLm1hdGNoID8/ICdhbGwnKSAhPT0gKGN1cnJlbnQubWF0Y2ggPz8gJ2FsbCcpXG4gICAgfHwgKGJhc2UuZ3JvdXBCeSA/PyBudWxsKSAhPT0gKGN1cnJlbnQuZ3JvdXBCeSA/PyBudWxsKVxuICAgIHx8IGdyb3Vwc0RpZmZlcihiYXNlLCBjdXJyZW50LCBhdXRob3JlZClcbiAgICB8fCB0aWxlc0RpZmZlcihiYXNlLnRpbGVzID8/IHt9LCBjdXJyZW50LnRpbGVzID8/IHt9KTtcbn1cblxuLy8gV2hldGhlciB0d28gc3RvcmVkIGdyb3VwIHZhbHVlcyBhcmUgdGhlIHNhbWUgZmlsdGVyLCBhcyB2aWV3RGlmZmVycyByZWFkc1xuLy8gYSBncm91cDogcGlja3MgaW4gYW55IG9yZGVyLCB0ZXh0IHRyaW1tZWQsIGFuIGVtcHR5IHZhbHVlIHJlYWQgYXMgbm9uZS5cbmV4cG9ydCBmdW5jdGlvbiBzYW1lU3RvcmVkR3JvdXBWYWx1ZShcbiAgYTogRmlsdGVyR3JvdXBEZWZhdWx0IHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgYjogRmlsdGVyR3JvdXBEZWZhdWx0IHwgbnVsbCB8IHVuZGVmaW5lZCxcbik6IGJvb2xlYW4ge1xuICByZXR1cm4gc3RvcmVkVmFsdWVLZXkoYSkgPT09IHN0b3JlZFZhbHVlS2V5KGIpO1xufVxuXG4vLyBBIGRyaWxsIHBhdGgga2VwdCB0byB3aGF0IGEgdGlsZSBjYW4gY2Fycnk6IGl0cyBzdGVwcyB1cCB0byB0aGUgZmlyc3QgdGhhdFxuLy8gaXMgbm90IGEgdGltZSBsZXZlbCB3aXRoIGEgcGxhaW4gdmFsdWUgKHRoZSBzdGVwcyBiZWZvcmUgaXQgYXJlIGtlcHQpLCBhdFxuLy8gbW9zdCBEUklMTF9NQVhfREVQVEggb2YgdGhlbS5cbmV4cG9ydCBmdW5jdGlvbiBjbGVhbkRyaWxsUGF0aChwYXRoOiByZWFkb25seSB1bmtub3duW10gfCBudWxsIHwgdW5kZWZpbmVkKTogUmVwb3J0RHJpbGxTdGVwW10ge1xuICBjb25zdCBrZXB0OiBSZXBvcnREcmlsbFN0ZXBbXSA9IFtdO1xuXG4gIGZvciAoY29uc3Qgc3RlcCBvZiBwYXRoID8/IFtdKSB7XG4gICAgaWYgKCFpc1BsYWluT2JqZWN0KHN0ZXApIHx8ICFpc0NoYXJ0R3JhbnVsYXJpdHkoc3RlcC5sZXZlbCkgfHwgIWlzRHJpbGxWYWx1ZShzdGVwLnZhbHVlKVxuICAgICAgfHwga2VwdC5sZW5ndGggPT09IERSSUxMX01BWF9ERVBUSCkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAga2VwdC5wdXNoKHsgbGV2ZWw6IHN0ZXAubGV2ZWwsIHZhbHVlOiBzdGVwLnZhbHVlIH0pO1xuICB9XG5cbiAgcmV0dXJuIGtlcHQ7XG59XG5cbi8vIFdoZXRoZXIgdHdvIGRyaWxsIHBhdGhzIGFyZSB0aGUgc2FtZSBzdGVwcy4gQSB2YWx1ZSBpcyBjb21wYXJlZCBhcyB0ZXh0LFxuLy8gc28gMjAyNiBhbmQgJzIwMjYnIGFyZSB0aGUgc2FtZSBzdGVwLlxuZXhwb3J0IGZ1bmN0aW9uIHNhbWVEcmlsbFBhdGgoXG4gIGE6IHJlYWRvbmx5IFJlcG9ydERyaWxsU3RlcFtdIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgYjogcmVhZG9ubHkgUmVwb3J0RHJpbGxTdGVwW10gfCBudWxsIHwgdW5kZWZpbmVkLFxuKTogYm9vbGVhbiB7XG4gIHJldHVybiBkcmlsbEtleShhKSA9PT0gZHJpbGxLZXkoYik7XG59XG5cbi8vIEEgdmlldydzIGNvbmZpZyB0byBzYXZlOiB0aGUgc2NyZWVuIChgc2NyZWVuYCwgYSBzbmFwc2hvdCksIHdpdGggdGhlIGtleXNcbi8vIHRoaXMgdmlld2VyIGRvZXMgbm90IGtub3cga2VwdCBmcm9tIHRoZSBzdG9yZWQgZG9jdW1lbnQgKGBzdG9yZWRgKSwgYXQgdGhlXG4vLyB0b3AgYW5kIGluIGVhY2ggdGlsZS4gVGhleSBhcmUgbmV2ZXIgcmVhZCBoZXJlLCBhbmQgc2F2aW5nIG11c3Qgbm90IGxvc2Vcbi8vIHRoZW0uXG5leHBvcnQgZnVuY3Rpb24gd2l0aFN0b3JlZEtleXMoc3RvcmVkOiBSZXBvcnRWaWV3Q29uZmlnIHwgbnVsbCB8IHVuZGVmaW5lZCwgc2NyZWVuOiBSZXBvcnRWaWV3Q29uZmlnKTogUmVwb3J0Vmlld0NvbmZpZyB7XG4gIGlmICghc3RvcmVkKSB7XG4gICAgcmV0dXJuIHNjcmVlbjtcbiAgfVxuXG4gIGNvbnN0IHRpbGVzOiBSZWNvcmQ8bnVtYmVyLCBSZXBvcnRUaWxlU3RhdGU+ID0geyAuLi5zY3JlZW4udGlsZXMgfTtcblxuICBPYmplY3QuZW50cmllcyhzdG9yZWQudGlsZXMgPz8ge30pLmZvckVhY2goKFtjb21wb25lbnRJZCwgdGlsZV0pID0+IHtcbiAgICBjb25zdCBrZXB0ID0gaXNQbGFpbk9iamVjdCh0aWxlKSA/IG90aGVyS2V5cyh0aWxlLCBUSUxFX1NUQVRFX0tFWVMpIDoge307XG5cbiAgICBpZiAoT2JqZWN0LmtleXMoa2VwdCkubGVuZ3RoKSB7XG4gICAgICB0aWxlc1tOdW1iZXIoY29tcG9uZW50SWQpXSA9IHsgLi4ua2VwdCwgLi4udGlsZXNbTnVtYmVyKGNvbXBvbmVudElkKV0gfTtcbiAgICB9XG4gIH0pO1xuXG4gIGNvbnN0IGNvbmZpZzogUmVwb3J0Vmlld0NvbmZpZyA9IHsgLi4ub3RoZXJLZXlzKHN0b3JlZCBhcyB1bmtub3duIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+LCBWSUVXX0NPTkZJR19LRVlTKSwgLi4uc2NyZWVuIH07XG4gIGRlbGV0ZSBjb25maWcudGlsZXM7XG5cbiAgcmV0dXJuIE9iamVjdC5rZXlzKHRpbGVzKS5sZW5ndGggPyB7IC4uLmNvbmZpZywgdGlsZXMgfSA6IGNvbmZpZztcbn1cblxuLy8gSG93IG1hbnkgc2V0dGluZ3Mgb2YgYSBzYXZlZCB2aWV3IG5vIGxvbmdlciBhcHBseSBiZWNhdXNlIHRoZSByZXBvcnRcbi8vIGNoYW5nZWQ6IHdoYXQgdGhlIHNlcnZlciBsZWZ0IG91dCB3aGVuIGl0IHJlYWQgdGhlIHZpZXcgKGBkcm9wcGVkYCksIGFuZFxuLy8gd2hhdCB0aGUgdmlld2VyIGNvdWxkIG5vdCBhcHBseSAoYGFwcGxpZWRgIGlzIHRoZSB2aWV3IGFzIGl0IGFwcGxpZWQsIHRoZVxuLy8gc3RhdGUgc2VydmljZSdzIGJhc2UpOiBhIGdyb3VwIHZhbHVlIHRoYXQgbm8gbG9uZ2VyIGZpdHMgaXRzIGdyb3VwLCBhbmQgYVxuLy8gbGlzdCBzb3J0LCBzZWFyY2ggb3IgaGlkZGVuIGNvbHVtbnMsIG9yIGEgY2hhcnQncyBkcmlsbCBwYXRoLCBpdHMgdGlsZSBjYW5cbi8vIG5vIGxvbmdlciB0YWtlIChhIGxpc3QgY29sdW1uIGdvbmUsIGEgY2hhcnQgdHVybmVkIGludG8gYSBsaXN0KS5cbmV4cG9ydCBmdW5jdGlvbiB2aWV3RHJvcHBlZENvdW50KHZpZXc6IFBpY2s8UmVwb3J0VmlldywgJ2NvbmZpZycgfCAnZHJvcHBlZCc+LCBhcHBsaWVkOiBSZXBvcnRWaWV3Q29uZmlnKTogbnVtYmVyIHtcbiAgY29uc3QgZHJvcHBlZCA9IHZpZXcuZHJvcHBlZDtcbiAgY29uc3QgZ3JvdXBzID0gT2JqZWN0LmVudHJpZXModmlldy5jb25maWc/Lmdyb3VwcyA/PyB7fSlcbiAgICAuZmlsdGVyKChbZ3JvdXBJZCwgdmFsdWVdKSA9PiB2YWx1ZSAhPT0gbnVsbCAmJiAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGFwcGxpZWQuZ3JvdXBzID8/IHt9LCBncm91cElkKSlcbiAgICAubGVuZ3RoO1xuICBjb25zdCB0aWxlcyA9IE9iamVjdC5lbnRyaWVzKHZpZXcuY29uZmlnPy50aWxlcyA/PyB7fSlcbiAgICAucmVkdWNlKChjb3VudCwgW2NvbXBvbmVudElkLCB0aWxlXSkgPT4gY291bnQgKyB0aWxlS2V5c0xvc3QodGlsZSwgYXBwbGllZC50aWxlcz8uW051bWJlcihjb21wb25lbnRJZCldKSwgMCk7XG5cbiAgcmV0dXJuIChkcm9wcGVkPy5ncm91cHM/Lmxlbmd0aCA/PyAwKSArIChkcm9wcGVkPy50aWxlcz8ubGVuZ3RoID8/IDApICsgKGRyb3BwZWQ/LnBhZ2UgPyAxIDogMCkgKyBncm91cHMgKyB0aWxlcztcbn1cblxuLy8gVGhlIG5vdGUgYSB2aWV3IG9wZW5zIHdpdGggd2hlbiBzb21lIG9mIGl0cyBzZXR0aW5ncyBubyBsb25nZXIgYXBwbHksIG9yXG4vLyBudWxsIHdoZW4gZXZlcnkgc2V0dGluZyBhcHBsaWVzLiBPbmx5IGEgdmlld2VyIHdobyBtYXkgY2hhbmdlIHRoZSB2aWV3XG4vLyAoYGNhbkNoYW5nZWApIGlzIHRvbGQgdG8gc2F2ZSBpdC5cbmV4cG9ydCBmdW5jdGlvbiB2aWV3RHJvcHBlZE1lc3NhZ2UoY291bnQ6IG51bWJlciwgY2FuQ2hhbmdlID0gdHJ1ZSk6IHN0cmluZyB8IG51bGwge1xuICBpZiAoY291bnQgPCAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBub3RlID0gY291bnQgPT09IDFcbiAgICA/ICcxIHNldHRpbmcgaW4gdGhpcyB2aWV3IG5vIGxvbmdlciBhcHBsaWVzLCBiZWNhdXNlIHRoZSByZXBvcnQgY2hhbmdlZC4nXG4gICAgOiBgJHtjb3VudH0gc2V0dGluZ3MgaW4gdGhpcyB2aWV3IG5vIGxvbmdlciBhcHBseSwgYmVjYXVzZSB0aGUgcmVwb3J0IGNoYW5nZWQuYDtcblxuICByZXR1cm4gY2FuQ2hhbmdlID8gYCR7bm90ZX0gU2F2ZSBjaGFuZ2VzIHRvIHVwZGF0ZSB0aGUgdmlldy5gIDogbm90ZTtcbn1cblxuLy8gVGhlIG9wZW4gdmlldyBhcyBhIGNoYXQgdHVybiBuYW1lcyBpdDogaXRzIGlkLCBhbmQgd2hldGhlciB0aGUgc2NyZWVuXG4vLyBkaWZmZXJzIGZyb20gaXQuIEJvdGggYXJlIGxlZnQgb3V0IHdoaWxlIG5vIHZpZXcgaXMgb3Blbi5cbmV4cG9ydCBmdW5jdGlvbiBjaGF0Vmlld0ZpZWxkcyhcbiAgb3BlblZpZXc6IFBpY2s8UmVwb3J0Vmlld1N1bW1hcnksICdpZCc+IHwgbnVsbCxcbiAgdmlld0NoYW5nZWQ6IGJvb2xlYW4sXG4pOiBQaWNrPFJlcG9ydENoYXRWaWV3ZXJTdGF0ZSwgJ3ZpZXdJZCcgfCAndmlld0NoYW5nZWQnPiB7XG4gIHJldHVybiBvcGVuVmlldyA/IHsgdmlld0lkOiBvcGVuVmlldy5pZCwgdmlld0NoYW5nZWQgfSA6IHt9O1xufVxuXG5mdW5jdGlvbiBncm91cHNEaWZmZXIoYmFzZTogUmVwb3J0Vmlld0NvbmZpZywgY3VycmVudDogUmVwb3J0Vmlld0NvbmZpZywgYXV0aG9yZWQ6IFJlcG9ydFZpZXdDb25maWcgfCBudWxsKTogYm9vbGVhbiB7XG4gIHJldHVybiBPYmplY3QuZW50cmllcyhjdXJyZW50Lmdyb3VwcyA/PyB7fSkuc29tZSgoW2dyb3VwSWQsIHZhbHVlXSkgPT4ge1xuICAgIGNvbnN0IGtlcHQgPSBiYXNlLmdyb3VwcyAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYmFzZS5ncm91cHMsIGdyb3VwSWQpXG4gICAgICA/IGJhc2UuZ3JvdXBzW051bWJlcihncm91cElkKV1cbiAgICAgIDogYXV0aG9yZWQ/Lmdyb3Vwcz8uW051bWJlcihncm91cElkKV07XG5cbiAgICByZXR1cm4gc3RvcmVkVmFsdWVLZXkoa2VwdCkgIT09IHN0b3JlZFZhbHVlS2V5KHZhbHVlKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHRpbGVzRGlmZmVyKGJhc2U6IFJlY29yZDxudW1iZXIsIFJlcG9ydFRpbGVTdGF0ZT4sIGN1cnJlbnQ6IFJlY29yZDxudW1iZXIsIFJlcG9ydFRpbGVTdGF0ZT4pOiBib29sZWFuIHtcbiAgY29uc3QgaWRzID0gbmV3IFNldChbLi4uT2JqZWN0LmtleXMoYmFzZSksIC4uLk9iamVjdC5rZXlzKGN1cnJlbnQpXS5tYXAoTnVtYmVyKSk7XG5cbiAgcmV0dXJuIFsuLi5pZHNdLnNvbWUoKGNvbXBvbmVudElkKSA9PiB0aWxlU3RhdGVLZXkoYmFzZVtjb21wb25lbnRJZF0pICE9PSB0aWxlU3RhdGVLZXkoY3VycmVudFtjb21wb25lbnRJZF0pKTtcbn1cblxuLy8gSG93IG1hbnkga2V5cyBvZiBhIHN0b3JlZCB0aWxlIHN0YXRlIHRoZSB0aWxlLCBhcyBpdCBhcHBsaWVkLCBsb3N0OiBhXG4vLyBzb3J0LCBhIHNlYXJjaCBvciBhIGRyaWxsIHBhdGggaXQgbm8gbG9uZ2VyIGhhcywgYW5kIGhpZGRlbiBjb2x1bW5zIGl0XG4vLyBrZXB0IGZld2VyIG9mLlxuZnVuY3Rpb24gdGlsZUtleXNMb3N0KHN0b3JlZDogUmVwb3J0VGlsZVN0YXRlIHwgdW5kZWZpbmVkLCBhcHBsaWVkOiBSZXBvcnRUaWxlU3RhdGUgfCB1bmRlZmluZWQpOiBudW1iZXIge1xuICBpZiAoIXN0b3JlZCkge1xuICAgIHJldHVybiAwO1xuICB9XG5cbiAgcmV0dXJuIFtcbiAgICAhIXN0b3JlZC5zb3J0Py5jb2x1bW4gJiYgIWFwcGxpZWQ/LnNvcnQ/LmNvbHVtbixcbiAgICAhIXN0b3JlZC5zZWFyY2ggJiYgIWFwcGxpZWQ/LnNlYXJjaCxcbiAgICAoc3RvcmVkLmhpZGRlbj8ubGVuZ3RoID8/IDApID4gKGFwcGxpZWQ/LmhpZGRlbj8ubGVuZ3RoID8/IDApLFxuICAgIChzdG9yZWQuZHJpbGw/Lmxlbmd0aCA/PyAwKSA+IDAgJiYgIWFwcGxpZWQ/LmRyaWxsPy5sZW5ndGgsXG4gIF0uZmlsdGVyKEJvb2xlYW4pLmxlbmd0aDtcbn1cblxuLy8gT25lIHRleHQgZm9yIGEgc3RvcmVkIGdyb3VwIHZhbHVlLCB0aGUgc2FtZSBmb3IgZXZlcnkgd2F5IG9mIHdyaXRpbmcgdGhlXG4vLyBzYW1lIGZpbHRlcjogcGlja3MgaW4gYW55IG9yZGVyLCB0ZXh0IHRyaW1tZWQsIGFuZCBhbiBlbXB0eSB2YWx1ZSByZWFkIGFzXG4vLyBub25lLlxuZnVuY3Rpb24gc3RvcmVkVmFsdWVLZXkodmFsdWU6IEZpbHRlckdyb3VwRGVmYXVsdCB8IG51bGwgfCB1bmRlZmluZWQpOiBzdHJpbmcge1xuICBjb25zdCBzdG9yZWQgPSB2YWx1ZSA/PyB7fTtcbiAgY29uc3QgcGlja3MgPSAobGlzdDogdW5rbm93bltdIHwgdW5kZWZpbmVkKSA9PiBbLi4uKGtlcHRQaWNrcyhsaXN0KSA/PyBbXSldLm1hcChTdHJpbmcpLnNvcnQoKTtcblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoW1xuICAgIHN0b3JlZC5yZWxhdGl2ZSA/PyBudWxsLFxuICAgIHN0b3JlZC5zdGFydD8uc2xpY2UoMCwgMTApID8/IG51bGwsXG4gICAgc3RvcmVkLmVuZD8uc2xpY2UoMCwgMTApID8/IG51bGwsXG4gICAgcGlja3Moc3RvcmVkLnZhbHVlcyksXG4gICAgcGlja3Moc3RvcmVkLmV4Y2x1ZGVWYWx1ZXMpLFxuICAgIChzdG9yZWQudmFsdWUgPz8gJycpLnRyaW0oKSxcbiAgICBmaW5pdGVOdW1iZXIoc3RvcmVkLm1pbikgPz8gbnVsbCxcbiAgICBmaW5pdGVOdW1iZXIoc3RvcmVkLm1heCkgPz8gbnVsbCxcbiAgXSk7XG59XG5cbi8vIE9uZSB0ZXh0IGZvciBhIHRpbGUncyBzdGF0ZSwgb3ZlciB0aGUga2V5cyB0aGlzIHZpZXdlciByZWFkcy4gTm8gZGlyZWN0aW9uXG4vLyByZWFkcyBhcyBhc2NlbmRpbmcsIHRoZSB3YXkgYSBsaXN0IGFwcGxpZXMgaXQuXG5mdW5jdGlvbiB0aWxlU3RhdGVLZXkodGlsZTogUmVwb3J0VGlsZVN0YXRlIHwgdW5kZWZpbmVkKTogc3RyaW5nIHtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KFtcbiAgICB0aWxlPy5zb3J0Py5jb2x1bW4gPyBbdGlsZS5zb3J0LmNvbHVtbiwgdGlsZS5zb3J0LmRpcmVjdGlvbiA/PyAnYXNjJ10gOiBudWxsLFxuICAgIHRpbGU/LnNlYXJjaCA/PyAnJyxcbiAgICBbLi4uKHRpbGU/LmhpZGRlbiA/PyBbXSldLnNvcnQoKSxcbiAgICBkcmlsbEtleSh0aWxlPy5kcmlsbCksXG4gIF0pO1xufVxuXG5mdW5jdGlvbiBkcmlsbEtleShwYXRoOiByZWFkb25seSBSZXBvcnREcmlsbFN0ZXBbXSB8IG51bGwgfCB1bmRlZmluZWQpOiBzdHJpbmcge1xuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoKHBhdGggPz8gW10pXG4gICAgLm1hcCgoc3RlcCkgPT4gW3N0ZXAubGV2ZWwsIHN0ZXAudmFsdWUgPT09IG51bGwgfHwgc3RlcC52YWx1ZSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IFN0cmluZyhzdGVwLnZhbHVlKV0pKTtcbn1cblxuLy8gVGhlIHBpY2tzIG9mIGEgbGlzdCB3aXRoIGJsYW5rcyAobnVsbCwgJycpIGxlZnQgb3V0LCBvciB1bmRlZmluZWQgd2hlbiBub25lXG4vLyBpcyBsZWZ0LlxuZnVuY3Rpb24ga2VwdFBpY2tzKGxpc3Q6IHVua25vd25bXSB8IG51bGwgfCB1bmRlZmluZWQpOiB1bmtub3duW10gfCB1bmRlZmluZWQge1xuICBjb25zdCBrZXB0ID0gKGxpc3QgPz8gW10pLmZpbHRlcigocGljaykgPT4gaXNTZXQocGljaykgJiYgcGljayAhPT0gJycpO1xuXG4gIHJldHVybiBrZXB0Lmxlbmd0aCA/IGtlcHQgOiB1bmRlZmluZWQ7XG59XG5cbi8vIEEgcmFuZ2UgZW5kIGFzIGEgbnVtYmVyLiBBIG1hc2tlZCBpbnB1dCBzZW5kcyBpdHMgbnVtYmVyIGFzIHRleHQsIHNvXG4vLyBudW1lcmljIHRleHQgaXMgcmVhZCBhcyBpdHMgbnVtYmVyLCBhcyBib3VuZFBhcnQgcmVhZHMgaXQuXG5leHBvcnQgZnVuY3Rpb24gZmluaXRlTnVtYmVyKHZhbHVlOiB1bmtub3duKTogbnVtYmVyIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgbnVtYmVyID0gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyA/IG51bWJlckZyb21UZXh0KHZhbHVlLnRyaW0oKSkgOiB2YWx1ZTtcblxuICByZXR1cm4gdHlwZW9mIG51bWJlciA9PT0gJ251bWJlcicgJiYgTnVtYmVyLmlzRmluaXRlKG51bWJlcikgPyBudW1iZXIgOiB1bmRlZmluZWQ7XG59XG5cbi8vIFdoZXRoZXIgYSBzdG9yZWQgdmFsdWUgcmVhZHMgdGhlIHNhbWUgYXMgbm8gdmFsdWUgYXQgYWxsLlxuZnVuY3Rpb24gaG9sZHNOb3RoaW5nKHN0b3JlZDogRmlsdGVyR3JvdXBEZWZhdWx0KTogYm9vbGVhbiB7XG4gIHJldHVybiBzdG9yZWRWYWx1ZUtleShzdG9yZWQpID09PSBzdG9yZWRWYWx1ZUtleShudWxsKTtcbn1cblxuLy8gT25seSB0aGUgcGFydHMgdGhhdCBob2xkIHNvbWV0aGluZywgb3IgbnVsbCB3aGVuIG5vbmUgZG9lcy5cbmZ1bmN0aW9uIHN0b3JlZE9yTnVsbCh2YWx1ZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBGaWx0ZXJHcm91cERlZmF1bHQgfCBudWxsIHtcbiAgY29uc3Qgc3RvcmVkID0gY29tcGFjdCh2YWx1ZSk7XG5cbiAgcmV0dXJuIE9iamVjdC5rZXlzKHN0b3JlZCkubGVuZ3RoID8gc3RvcmVkIDogbnVsbDtcbn1cblxuZnVuY3Rpb24gcmVxdWlyZUdyb3VwS2V5cyh2YWx1ZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sIHR5cGU6IFJlcG9ydEZpbHRlclR5cGUpOiB2b2lkIHtcbiAgY29uc3QgYWxsb3dlZDogcmVhZG9ubHkgc3RyaW5nW10gPSBHUk9VUF9WQUxVRV9LRVlTW3R5cGVdID8/IEdST1VQX1ZBTFVFX0tFWVMua2V5d29yZDtcbiAgY29uc3QgdW5rbm93biA9IE9iamVjdC5rZXlzKHZhbHVlKS5maWx0ZXIoKGtleSkgPT4gIWFsbG93ZWQuaW5jbHVkZXMoa2V5KSk7XG5cbiAgaWYgKHVua25vd24ubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBBICR7dHlwZX0gZGVmYXVsdCB0YWtlcyAke2FsbG93ZWQuam9pbignLCAnKX0g4oCUIG5vdCAke3Vua25vd24uam9pbignLCAnKX0uYCk7XG4gIH1cbn1cblxuLy8gQSByZWxhdGl2ZSByYW5nZSwgb3IgZml4ZWQgZGF5czsgbmV2ZXIgYm90aC5cbmZ1bmN0aW9uIGRhdGVSYW5nZVZhbHVlKHZhbHVlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IEZpbHRlckdyb3VwRGVmYXVsdCB7XG4gIGNvbnN0IHJlbGF0aXZlID0gdGV4dFBhcnQodmFsdWUsICdyZWxhdGl2ZScpO1xuICBjb25zdCBzdGFydCA9IGRheVBhcnQodmFsdWUsICdzdGFydCcpO1xuICBjb25zdCBlbmQgPSBkYXlQYXJ0KHZhbHVlLCAnZW5kJyk7XG5cbiAgaWYgKHJlbGF0aXZlID09PSAnJykge1xuICAgIHJldHVybiBjb21wYWN0KHsgc3RhcnQsIGVuZCB9KTtcbiAgfVxuXG4gIGlmIChzdGFydCAhPT0gbnVsbCB8fCBlbmQgIT09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0EgZGF0ZVJhbmdlIGRlZmF1bHQgaXMgZWl0aGVyIGEgcmVsYXRpdmUgcHJlc2V0IG9yIGEgZml4ZWQgc3RhcnQvZW5kLCBub3QgYm90aC4nKTtcbiAgfVxuXG4gIGlmICghaXNSZWxhdGl2ZVJhbmdlKHJlbGF0aXZlKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgcmVsYXRpdmUgbXVzdCBiZSBvbmUgb2Y6ICR7T2JqZWN0LmtleXMoUkVMQVRJVkVfUkFOR0VTKS5qb2luKCcsICcpfS5gKTtcbiAgfVxuXG4gIHJldHVybiB7IHJlbGF0aXZlIH07XG59XG5cbi8vIFRoZSB2YWx1ZXMgdG8ga2VlcCBvciB0aGUgdmFsdWVzIHRvIGxlYXZlIG91dDsgbmV2ZXIgYm90aC5cbmZ1bmN0aW9uIHNlbGVjdFZhbHVlKHZhbHVlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IEZpbHRlckdyb3VwRGVmYXVsdCB7XG4gIGNvbnN0IHZhbHVlcyA9IHBpY2tMaXN0KHZhbHVlLCAndmFsdWVzJyk7XG4gIGNvbnN0IGV4Y2x1ZGVWYWx1ZXMgPSBwaWNrTGlzdCh2YWx1ZSwgJ2V4Y2x1ZGVWYWx1ZXMnKTtcblxuICBpZiAodmFsdWVzICE9PSBudWxsICYmIGV4Y2x1ZGVWYWx1ZXMgIT09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0Egc2VsZWN0IGRlZmF1bHQgZWl0aGVyIGtlZXBzIHZhbHVlcyBvciBsZWF2ZXMgb3V0IGV4Y2x1ZGVfdmFsdWVzLCBub3QgYm90aC4nKTtcbiAgfVxuXG4gIHJldHVybiBjb21wYWN0KHsgdmFsdWVzLCBleGNsdWRlVmFsdWVzIH0pO1xufVxuXG5mdW5jdGlvbiBrZXl3b3JkVmFsdWUodmFsdWU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogRmlsdGVyR3JvdXBEZWZhdWx0IHtcbiAgY29uc3QgdGV4dCA9IHRleHRQYXJ0KHZhbHVlLCAndmFsdWUnKTtcblxuICByZXR1cm4gdGV4dCAhPT0gJycgPyB7IHZhbHVlOiB0ZXh0IH0gOiB7fTtcbn1cblxuLy8gRWl0aGVyIGVuZCBtYXkgYmUgb3BlbjsgMCBpcyBhbiBlbmQgbGlrZSBhbnkgb3RoZXIuXG5mdW5jdGlvbiBudW1iZXJSYW5nZVZhbHVlKHZhbHVlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IEZpbHRlckdyb3VwRGVmYXVsdCB7XG4gIGNvbnN0IG1pbiA9IGJvdW5kUGFydCh2YWx1ZSwgJ21pbicpO1xuICBjb25zdCBtYXggPSBib3VuZFBhcnQodmFsdWUsICdtYXgnKTtcblxuICBpZiAobWluICE9PSBudWxsICYmIG1heCAhPT0gbnVsbCAmJiBtaW4gPiBtYXgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYG1pbiAoJHttaW59KSBpcyBhYm92ZSBtYXggKCR7bWF4fSkuYCk7XG4gIH1cblxuICByZXR1cm4gY29tcGFjdCh7IG1pbiwgbWF4IH0pO1xufVxuXG4vLyBUaGUgdGV4dCBga2V5YCBob2xkcywgdHJpbW1lZCwgb3IgJycgd2hlbiBhYnNlbnQuIEEgbnVtYmVyIGlzIHJlYWQgYXMgaXRzXG4vLyB0ZXh0OyBhbnkgb3RoZXIga2luZCBpcyByZWZ1c2VkLlxuZnVuY3Rpb24gdGV4dFBhcnQodmFsdWU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LCBrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHRleHQgPSB2YWx1ZVtrZXldO1xuICBpZiAodGV4dCA9PT0gdW5kZWZpbmVkIHx8IHRleHQgPT09IG51bGwpIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICBpZiAodHlwZW9mIHRleHQgIT09ICdzdHJpbmcnICYmIHR5cGVvZiB0ZXh0ICE9PSAnbnVtYmVyJykge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHtrZXl9IG11c3QgYmUgdGV4dC5gKTtcbiAgfVxuXG4gIHJldHVybiBTdHJpbmcodGV4dCkudHJpbSgpO1xufVxuXG4vLyBBIGNhbGVuZGFyLWRheSBib3VuZDogaXRzIGZpcnN0IHRlbiBjaGFyYWN0ZXJzIG11c3QgYmUgYSByZWFsIGRheS5cbmZ1bmN0aW9uIGRheVBhcnQodmFsdWU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LCBrZXk6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICBjb25zdCB0ZXh0ID0gdGV4dFBhcnQodmFsdWUsIGtleSk7XG4gIGlmICh0ZXh0ID09PSAnJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgZGF5ID0gdGV4dC5zbGljZSgwLCAxMCk7XG4gIGlmICghaXNDYWxlbmRhckRheShkYXkpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke2tleX0gbXVzdCBiZSBhIHl5eXktTU0tZGQgZGF5LmApO1xuICB9XG5cbiAgcmV0dXJuIGRheTtcbn1cblxuLy8gVGhlIHBpY2tzIG9mIGBrZXlgIHdpdGggYmxhbmtzIChudWxsLCAnJykgZHJvcHBlZCwgb3IgbnVsbCB3aGVuIG5vbmUgaXNcbi8vIGxlZnQuIEEgbG9uZSBwaWNrIGlzIGEgbGlzdCBvZiBvbmU7IGEgcGljayB0aGF0IGlzIGEgbGlzdCBvciBhbiBvYmplY3QgaXNcbi8vIHJlZnVzZWQuXG5mdW5jdGlvbiBwaWNrTGlzdCh2YWx1ZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sIGtleTogc3RyaW5nKTogdW5rbm93bltdIHwgbnVsbCB7XG4gIGNvbnN0IHJhdyA9IHZhbHVlW2tleV0gPz8gW107XG4gIGNvbnN0IHBpY2tzOiB1bmtub3duW10gPSBBcnJheS5pc0FycmF5KHJhdykgPyByYXcgOiBbcmF3XTtcblxuICBpZiAocGlja3Muc29tZSgocGljaykgPT4gaXNTZXQocGljaykgJiYgIWlzU2NhbGFyKHBpY2spKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgRWFjaCBwaWNrIGluICR7a2V5fSBtdXN0IGJlIGEgcGxhaW4gdmFsdWUsIG5vdCBhIGxpc3QuYCk7XG4gIH1cblxuICBjb25zdCBrZXB0ID0gcGlja3MuZmlsdGVyKChwaWNrKSA9PiBpc1NldChwaWNrKSAmJiBwaWNrICE9PSAnJyk7XG5cbiAgcmV0dXJuIGtlcHQubGVuZ3RoID8ga2VwdCA6IG51bGw7XG59XG5cbi8vIE9uZSBlbmQgb2YgYSBudW1iZXIgcmFuZ2U6IG51bGwgd2hlbiBhYnNlbnQgb3IgYmxhbmssIGVsc2UgYSBmaW5pdGUgbnVtYmVyXG4vLyAobnVtZXJpYyB0ZXh0IGlzIHJlYWQgYXMgaXRzIG51bWJlcikuXG5mdW5jdGlvbiBib3VuZFBhcnQodmFsdWU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LCBrZXk6IHN0cmluZyk6IG51bWJlciB8IG51bGwge1xuICBjb25zdCByYXcgPSB0eXBlb2YgdmFsdWVba2V5XSA9PT0gJ3N0cmluZycgPyAodmFsdWVba2V5XSBhcyBzdHJpbmcpLnRyaW0oKSA6IHZhbHVlW2tleV07XG4gIGlmICghaXNTZXQocmF3KSB8fCByYXcgPT09ICcnKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBib3VuZCA9IHR5cGVvZiByYXcgPT09ICdzdHJpbmcnID8gbnVtYmVyRnJvbVRleHQocmF3KSA6IHJhdztcbiAgaWYgKHR5cGVvZiBib3VuZCAhPT0gJ251bWJlcicgfHwgIU51bWJlci5pc0Zpbml0ZShib3VuZCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7a2V5fSBtdXN0IGJlIGEgZmluaXRlIG51bWJlci5gKTtcbiAgfVxuXG4gIHJldHVybiBib3VuZDtcbn1cblxuZnVuY3Rpb24gcmVxdWlyZVNpemUoZG9jOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IHZvaWQge1xuICBpZiAobmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKEpTT04uc3RyaW5naWZ5KGRvYykpLmxlbmd0aCA+IFZJRVdfQ09ORklHX01BWF9CWVRFUykge1xuICAgIHRocm93IG5ldyBFcnJvcignQSB2aWV3IGNvbmZpZyBpcyBvdmVyIDMyIEtCLicpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlcXVpcmVWZXJzaW9uKHZlcnNpb246IHVua25vd24pOiB2b2lkIHtcbiAgaWYgKCFpc1NldCh2ZXJzaW9uKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignQSB2aWV3IGNvbmZpZyBuZWVkcyBpdHMgdmVyc2lvbiAodikuJyk7XG4gIH1cblxuICBpZiAodmVyc2lvbiAhPT0gUkVQT1JUX1ZJRVdfQ09ORklHX1ZFUlNJT04pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFRoaXMgdmlld2VyIHJlYWRzIHZpZXcgY29uZmlnIHZlcnNpb24gJHtSRVBPUlRfVklFV19DT05GSUdfVkVSU0lPTn0gb25seS5gKTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZXF1aXJlTWF0Y2gobWF0Y2g6IHVua25vd24pOiBSZXBvcnRWaWV3Q29uZmlnWydtYXRjaCddIHtcbiAgaWYgKG1hdGNoICE9PSAnYWxsJyAmJiBtYXRjaCAhPT0gJ2FueScpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ21hdGNoIG11c3QgYmUgYWxsIG9yIGFueS4nKTtcbiAgfVxuXG4gIHJldHVybiBtYXRjaDtcbn1cblxuLy8gR3JvdXAgaWQgLT4gdmFsdWUuIEEgdmFsdWUgbm8gZ3JvdXAgdHlwZSBjb3VsZCBob2xkIGlzIGRyb3BwZWQgd2hvbGUuXG5mdW5jdGlvbiB2aWV3R3JvdXBzKHJhdzogdW5rbm93bik6IFJlY29yZDxudW1iZXIsIEZpbHRlckdyb3VwRGVmYXVsdCB8IG51bGw+IHtcbiAgY29uc3QgZW50cmllcyA9IE9iamVjdC5lbnRyaWVzKHJlcXVpcmVPYmplY3QocmF3LCAnZ3JvdXBzIG11c3QgbWFwIGdyb3VwIGlkcyB0byB2YWx1ZXMuJykpO1xuICBpZiAoZW50cmllcy5sZW5ndGggPiBWSUVXX0NPTkZJR19NQVhfR1JPVVBTKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBBIHZpZXcgaG9sZHMgYXQgbW9zdCAke1ZJRVdfQ09ORklHX01BWF9HUk9VUFN9IGdyb3Vwcy5gKTtcbiAgfVxuXG4gIGNvbnN0IGdyb3VwczogUmVjb3JkPG51bWJlciwgRmlsdGVyR3JvdXBEZWZhdWx0IHwgbnVsbD4gPSB7fTtcbiAgZW50cmllcy5mb3JFYWNoKChba2V5LCB2YWx1ZV0pID0+IHtcbiAgICBjb25zdCBpZCA9IHJlcXVpcmVJZEtleShrZXksICdncm91cHMnKTtcbiAgICByZXF1aXJlUGlja0NvdW50KHZhbHVlKTtcbiAgICBjb25zdCBrZXB0ID0gdmFsdWUgPT09IG51bGwgPyBudWxsIDogc3RvcmVkR3JvdXBWYWx1ZSh2YWx1ZSk7XG5cbiAgICBpZiAoa2VwdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBncm91cHNbaWRdID0ga2VwdDtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBncm91cHM7XG59XG5cbi8vIEEgc3RvcmVkIGdyb3VwIHZhbHVlLCByZWFkIGZvciB0aGUgb25lIHR5cGUgaXRzIGtleXMgYmVsb25nIHRvIChhbiBlbXB0eVxuLy8gdmFsdWUgZml0cyBldmVyeSB0eXBlKSwgb3IgdW5kZWZpbmVkIHdoZW4gaXQgZml0cyBub25lLlxuZnVuY3Rpb24gc3RvcmVkR3JvdXBWYWx1ZSh2YWx1ZTogdW5rbm93bik6IEZpbHRlckdyb3VwRGVmYXVsdCB8IHVuZGVmaW5lZCB7XG4gIGlmICghaXNQbGFpbk9iamVjdCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKHZhbHVlKTtcbiAgY29uc3QgdHlwZSA9IChPYmplY3Qua2V5cyhHUk9VUF9WQUxVRV9LRVlTKSBhcyBSZXBvcnRGaWx0ZXJUeXBlW10pXG4gICAgLmZpbmQoKGNhbmRpZGF0ZSkgPT4ga2V5cy5ldmVyeSgoa2V5KSA9PiAoR1JPVVBfVkFMVUVfS0VZU1tjYW5kaWRhdGVdIGFzIHJlYWRvbmx5IHN0cmluZ1tdKS5pbmNsdWRlcyhrZXkpKSk7XG5cbiAgcmV0dXJuIHR5cGUgPyAoZ3JvdXBWYWx1ZUZyb21TdG9yZWQodmFsdWUsIHR5cGUpID8/IHVuZGVmaW5lZCkgOiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIHJlcXVpcmVQaWNrQ291bnQodmFsdWU6IHVua25vd24pOiB2b2lkIHtcbiAgY29uc3QgbGlzdHMgPSBpc1BsYWluT2JqZWN0KHZhbHVlKSA/IFt2YWx1ZS52YWx1ZXMsIHZhbHVlLmV4Y2x1ZGVWYWx1ZXNdIDogW107XG5cbiAgaWYgKGxpc3RzLnNvbWUoKGxpc3QpID0+IEFycmF5LmlzQXJyYXkobGlzdCkgJiYgbGlzdC5sZW5ndGggPiBHUk9VUF9WQUxVRV9NQVhfUElDS1MpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBBIGdyb3VwIHZhbHVlIGhvbGRzIGF0IG1vc3QgJHtHUk9VUF9WQUxVRV9NQVhfUElDS1N9IHZhbHVlcy5gKTtcbiAgfVxufVxuXG4vLyBDb21wb25lbnQgaWQgLT4gdGlsZSBzdGF0ZS5cbmZ1bmN0aW9uIHZpZXdUaWxlcyhyYXc6IHVua25vd24pOiBSZWNvcmQ8bnVtYmVyLCBSZXBvcnRUaWxlU3RhdGU+IHtcbiAgY29uc3QgZW50cmllcyA9IE9iamVjdC5lbnRyaWVzKHJlcXVpcmVPYmplY3QocmF3LCAndGlsZXMgbXVzdCBtYXAgY29tcG9uZW50IGlkcyB0byB0aWxlIHN0YXRlcy4nKSk7XG4gIGlmIChlbnRyaWVzLmxlbmd0aCA+IFZJRVdfQ09ORklHX01BWF9USUxFUykge1xuICAgIHRocm93IG5ldyBFcnJvcihgQSB2aWV3IGhvbGRzIGF0IG1vc3QgJHtWSUVXX0NPTkZJR19NQVhfVElMRVN9IHRpbGVzLmApO1xuICB9XG5cbiAgY29uc3QgdGlsZXM6IFJlY29yZDxudW1iZXIsIFJlcG9ydFRpbGVTdGF0ZT4gPSB7fTtcbiAgZW50cmllcy5mb3JFYWNoKChba2V5LCB2YWx1ZV0pID0+IHtcbiAgICB0aWxlc1tyZXF1aXJlSWRLZXkoa2V5LCAndGlsZXMnKV0gPSB2aWV3VGlsZSh2YWx1ZSk7XG4gIH0pO1xuXG4gIHJldHVybiB0aWxlcztcbn1cblxuZnVuY3Rpb24gdmlld1RpbGUocmF3OiB1bmtub3duKTogUmVwb3J0VGlsZVN0YXRlIHtcbiAgY29uc3QgdGlsZSA9IHJlcXVpcmVPYmplY3QocmF3LCAnQSB0aWxlIHN0YXRlIG11c3QgYmUgYW4gb2JqZWN0LicpO1xuICBjb25zdCBzdGF0ZSA9IG90aGVyS2V5cyh0aWxlLCBUSUxFX1NUQVRFX0tFWVMpIGFzIFJlcG9ydFRpbGVTdGF0ZTtcblxuICBpZiAoaXNTZXQodGlsZS5zb3J0KSkge1xuICAgIHN0YXRlLnNvcnQgPSB2aWV3U29ydCh0aWxlLnNvcnQpO1xuICB9XG5cbiAgaWYgKGlzU2V0KHRpbGUuc2VhcmNoKSkge1xuICAgIHN0YXRlLnNlYXJjaCA9IHJlcXVpcmVTdHJpbmcodGlsZS5zZWFyY2gsICdzZWFyY2ggbXVzdCBiZSB0ZXh0LicpO1xuICB9XG5cbiAgaWYgKGlzU2V0KHRpbGUuaGlkZGVuKSkge1xuICAgIHN0YXRlLmhpZGRlbiA9IHZpZXdIaWRkZW4odGlsZS5oaWRkZW4pO1xuICB9XG5cbiAgaWYgKGlzU2V0KHRpbGUuZHJpbGwpKSB7XG4gICAgc3RhdGUuZHJpbGwgPSB2aWV3RHJpbGwodGlsZS5kcmlsbCk7XG4gIH1cblxuICByZXR1cm4gc3RhdGU7XG59XG5cbmZ1bmN0aW9uIHZpZXdTb3J0KHJhdzogdW5rbm93bik6IFJlcG9ydFNvcnQge1xuICBjb25zdCBzb3J0ID0gcmVxdWlyZU9iamVjdChyYXcsICdzb3J0IG11c3QgYmUgYSBjb2x1bW4gYW5kIGEgZGlyZWN0aW9uLicpO1xuICBjb25zdCBjb2x1bW4gPSByZXF1aXJlU3RyaW5nKHNvcnQuY29sdW1uLCAnc29ydCBtdXN0IG5hbWUgYSBjb2x1bW4uJyk7XG4gIGlmIChjb2x1bW4gPT09ICcnIHx8IChpc1NldChzb3J0LmRpcmVjdGlvbikgJiYgc29ydC5kaXJlY3Rpb24gIT09ICdhc2MnICYmIHNvcnQuZGlyZWN0aW9uICE9PSAnZGVzYycpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzb3J0IG11c3QgYmUgYSBjb2x1bW4gYW5kIGEgZGlyZWN0aW9uLicpO1xuICB9XG5cbiAgcmV0dXJuIHNvcnQuZGlyZWN0aW9uID8geyBjb2x1bW4sIGRpcmVjdGlvbjogc29ydC5kaXJlY3Rpb24gYXMgUmVwb3J0U29ydFsnZGlyZWN0aW9uJ10gfSA6IHsgY29sdW1uIH07XG59XG5cbmZ1bmN0aW9uIHZpZXdIaWRkZW4ocmF3OiB1bmtub3duKTogc3RyaW5nW10ge1xuICBpZiAoIUFycmF5LmlzQXJyYXkocmF3KSB8fCByYXcuc29tZSgobmFtZSkgPT4gdHlwZW9mIG5hbWUgIT09ICdzdHJpbmcnKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignaGlkZGVuIG11c3QgbGlzdCBjb2x1bW4gbmFtZXMuJyk7XG4gIH1cblxuICByZXR1cm4gWy4uLnJhd107XG59XG5cbmZ1bmN0aW9uIHZpZXdEcmlsbChyYXc6IHVua25vd24pOiBSZXBvcnREcmlsbFN0ZXBbXSB7XG4gIGlmICghQXJyYXkuaXNBcnJheShyYXcpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdkcmlsbCBtdXN0IGxpc3Qgc3RlcHMuJyk7XG4gIH1cblxuICBpZiAocmF3Lmxlbmd0aCA+IERSSUxMX01BWF9ERVBUSCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgQSBkcmlsbCBwYXRoIGhvbGRzIGF0IG1vc3QgJHtEUklMTF9NQVhfREVQVEh9IHN0ZXBzLmApO1xuICB9XG5cbiAgcmV0dXJuIHJhdy5tYXAoKHN0ZXA6IHVua25vd24pID0+IHtcbiAgICBpZiAoIWlzUGxhaW5PYmplY3Qoc3RlcCkgfHwgIWlzQ2hhcnRHcmFudWxhcml0eShzdGVwLmxldmVsKSB8fCAhaXNEcmlsbFZhbHVlKHN0ZXAudmFsdWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0EgZHJpbGwgc3RlcCBuZWVkcyBhIHRpbWUgbGV2ZWwgYW5kIGEgdmFsdWUuJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgbGV2ZWw6IHN0ZXAubGV2ZWwsIHZhbHVlOiBzdGVwLnZhbHVlIH07XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBpc0RyaWxsVmFsdWUodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBSZXBvcnREcmlsbFN0ZXBbJ3ZhbHVlJ10ge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGwgfHwgdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInO1xufVxuXG4vLyBUaGUga2V5cyBvZiBgc291cmNlYCB0aGF0IGFyZSBub3QgaW4gYGtub3duYCwgYXMgdGhleSB3ZXJlLlxuZnVuY3Rpb24gb3RoZXJLZXlzKHNvdXJjZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sIGtub3duOiByZWFkb25seSBzdHJpbmdbXSk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhPYmplY3QuZW50cmllcyhzb3VyY2UpLmZpbHRlcigoW2tleV0pID0+ICFrbm93bi5pbmNsdWRlcyhrZXkpKSk7XG59XG5cbmZ1bmN0aW9uIG9wdGlvbmFsSWQocmF3OiB1bmtub3duLCByZWZ1c2FsOiBzdHJpbmcpOiBudW1iZXIgfCBudWxsIHtcbiAgaWYgKCFpc1NldChyYXcpKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBpZiAoIU51bWJlci5pc0ludGVnZXIocmF3KSB8fCAocmF3IGFzIG51bWJlcikgPCAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKHJlZnVzYWwpO1xuICB9XG5cbiAgcmV0dXJuIHJhdyBhcyBudW1iZXI7XG59XG5cbmZ1bmN0aW9uIHJlcXVpcmVJZEtleShrZXk6IHN0cmluZywgd2hlcmU6IHN0cmluZyk6IG51bWJlciB7XG4gIGlmICghSURfS0VZX1BBVFRFUk4udGVzdChrZXkpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke3doZXJlfSBhcmUga2V5ZWQgYnkgaWQsIG5vdCBieSAnJHtrZXl9Jy5gKTtcbiAgfVxuXG4gIHJldHVybiBOdW1iZXIoa2V5KTtcbn1cblxuZnVuY3Rpb24gcmVxdWlyZUdyYW51bGFyaXR5KHJhdzogdW5rbm93biwgcmVmdXNhbDogc3RyaW5nKTogQ2hhcnRHcmFudWxhcml0eSB7XG4gIGlmICghaXNDaGFydEdyYW51bGFyaXR5KHJhdykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IocmVmdXNhbCk7XG4gIH1cblxuICByZXR1cm4gcmF3O1xufVxuXG5mdW5jdGlvbiByZXF1aXJlU3RyaW5nKHJhdzogdW5rbm93biwgcmVmdXNhbDogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKHR5cGVvZiByYXcgIT09ICdzdHJpbmcnKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKHJlZnVzYWwpO1xuICB9XG5cbiAgcmV0dXJuIHJhdztcbn1cblxuZnVuY3Rpb24gcmVxdWlyZU9iamVjdChyYXc6IHVua25vd24sIHJlZnVzYWw6IHN0cmluZyk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgaWYgKCFpc1BsYWluT2JqZWN0KHJhdykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IocmVmdXNhbCk7XG4gIH1cblxuICByZXR1cm4gcmF3O1xufVxuXG5mdW5jdGlvbiBpc1NldCh2YWx1ZTogdW5rbm93bik6IGJvb2xlYW4ge1xuICByZXR1cm4gdmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNQbGFpbk9iamVjdCh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgcmV0dXJuIHZhbHVlICE9PSBudWxsICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuXG5mdW5jdGlvbiBpc1NjYWxhcih2YWx1ZTogdW5rbm93bik6IGJvb2xlYW4ge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nO1xufVxuXG4vLyBPbmx5IHRoZSBwYXJ0cyB0aGF0IGhvbGQgc29tZXRoaW5nLlxuZnVuY3Rpb24gY29tcGFjdCh2YWx1ZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBGaWx0ZXJHcm91cERlZmF1bHQge1xuICByZXR1cm4gT2JqZWN0LmZyb21FbnRyaWVzKE9iamVjdC5lbnRyaWVzKHZhbHVlKS5maWx0ZXIoKFssIHBhcnRdKSA9PiBpc1NldChwYXJ0KSkpIGFzIEZpbHRlckdyb3VwRGVmYXVsdDtcbn1cbiJdfQ==