@firestitch/report 18.8.1 → 18.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) 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/component-text/component-text.component.d.ts +47 -2
  6. package/app/reports/components/component-text/value-embed.plugin.d.ts +67 -0
  7. package/app/reports/components/report-canvas/report-canvas.component.d.ts +37 -9
  8. package/app/reports/components/report-component/report-component.component.d.ts +45 -2
  9. package/app/reports/components/report-view-picker/report-view-picker.component.d.ts +21 -0
  10. package/app/reports/data/report.data.d.ts +18 -2
  11. package/app/reports/dialogs/component-settings/component-settings.component.d.ts +25 -2
  12. package/app/reports/dialogs/report-settings/report-settings.component.d.ts +15 -6
  13. package/app/reports/dialogs/report-view/report-view-dialog.component.d.ts +13 -0
  14. package/app/reports/drill-crumbs.d.ts +12 -0
  15. package/app/reports/enums/report-value-formula.enum.d.ts +6 -0
  16. package/app/reports/export/report-export-collector.service.d.ts +35 -4
  17. package/app/reports/export/report-export.service.d.ts +3 -1
  18. package/app/reports/export/report-filter-lines.d.ts +18 -0
  19. package/app/reports/export/report-pdf.service.d.ts +18 -2
  20. package/app/reports/export/report-pptx.service.d.ts +15 -2
  21. package/app/reports/export/report-text-layout.service.d.ts +35 -0
  22. package/app/reports/filter-settings-rules.d.ts +33 -0
  23. package/app/reports/format.d.ts +2 -1
  24. package/app/reports/interfaces/canvas-landing-input.interface.d.ts +8 -0
  25. package/app/reports/interfaces/component-data-applied.interface.d.ts +13 -0
  26. package/app/reports/interfaces/component-data-drill.interface.d.ts +22 -0
  27. package/app/reports/interfaces/filter-bar-placement.type.d.ts +1 -0
  28. package/app/reports/interfaces/filter-component-toggle-state.interface.d.ts +4 -0
  29. package/app/reports/interfaces/filter-settings-option.interface.d.ts +4 -0
  30. package/app/reports/interfaces/filter-type-select-state.interface.d.ts +5 -0
  31. package/app/reports/interfaces/report-chart-hit.interface.d.ts +5 -0
  32. package/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.d.ts +4 -0
  33. package/app/reports/interfaces/report-chat-viewer-cross-filter.interface.d.ts +7 -0
  34. package/app/reports/interfaces/report-chat-viewer-detail.interface.d.ts +4 -0
  35. package/app/reports/interfaces/report-chat-viewer-drill-step.interface.d.ts +5 -0
  36. package/app/reports/interfaces/report-chat-viewer-drill.interface.d.ts +5 -0
  37. package/app/reports/interfaces/report-chat-viewer-filter.interface.d.ts +3 -0
  38. package/app/reports/interfaces/report-chat-viewer-selection.interface.d.ts +5 -0
  39. package/app/reports/interfaces/report-chat-viewer-state.interface.d.ts +12 -0
  40. package/app/reports/interfaces/report-drill-crumb.interface.d.ts +6 -0
  41. package/app/reports/interfaces/report-drill-refusal.type.d.ts +1 -0
  42. package/app/reports/interfaces/report-drill-step.interface.d.ts +5 -0
  43. package/app/reports/interfaces/report-export-line-kind.type.d.ts +1 -0
  44. package/app/reports/interfaces/report-export-line.interface.d.ts +8 -0
  45. package/app/reports/interfaces/report-export-lines-input.interface.d.ts +9 -0
  46. package/app/reports/interfaces/report-export-snapshot.interface.d.ts +15 -0
  47. package/app/reports/interfaces/report-filter-line-context.interface.d.ts +8 -0
  48. package/app/reports/interfaces/report-filter-line-form.type.d.ts +1 -0
  49. package/app/reports/interfaces/report-filter-match.type.d.ts +1 -0
  50. package/app/reports/interfaces/report-filter-option-pair.interface.d.ts +4 -0
  51. package/app/reports/interfaces/report-filter-options-ask.interface.d.ts +6 -0
  52. package/app/reports/interfaces/report-filter-options-list.interface.d.ts +7 -0
  53. package/app/reports/interfaces/report-filter-options-request.interface.d.ts +6 -0
  54. package/app/reports/interfaces/report-filter-options-stream.interface.d.ts +11 -0
  55. package/app/reports/interfaces/report-filter-options.interface.d.ts +7 -0
  56. package/app/reports/interfaces/report-filter-skip.type.d.ts +1 -0
  57. package/app/reports/interfaces/report-mark-action.type.d.ts +1 -0
  58. package/app/reports/interfaces/report-mark-click.interface.d.ts +13 -0
  59. package/app/reports/interfaces/report-mark-context.interface.d.ts +6 -0
  60. package/app/reports/interfaces/report-mark-decision.interface.d.ts +6 -0
  61. package/app/reports/interfaces/report-mark-event.interface.d.ts +11 -0
  62. package/app/reports/interfaces/report-mark-point.interface.d.ts +8 -0
  63. package/app/reports/interfaces/report-temporary-state.interface.d.ts +4 -0
  64. package/app/reports/interfaces/report-tile-state.interface.d.ts +8 -0
  65. package/app/reports/interfaces/report-url-link.interface.d.ts +4 -0
  66. package/app/reports/interfaces/report-url-value-name.type.d.ts +1 -0
  67. package/app/reports/interfaces/report-url-write.interface.d.ts +4 -0
  68. package/app/reports/interfaces/report-view-config.interface.d.ts +11 -0
  69. package/app/reports/interfaces/report-view-create.interface.d.ts +7 -0
  70. package/app/reports/interfaces/report-view-deleted.interface.d.ts +4 -0
  71. package/app/reports/interfaces/report-view-dialog-data.interface.d.ts +7 -0
  72. package/app/reports/interfaces/report-view-dropped.interface.d.ts +5 -0
  73. package/app/reports/interfaces/report-view-menu-item.interface.d.ts +10 -0
  74. package/app/reports/interfaces/report-view-summary.interface.d.ts +11 -0
  75. package/app/reports/interfaces/report-view.interface.d.ts +7 -0
  76. package/app/reports/interfaces/report-viewer-feature.type.d.ts +1 -0
  77. package/app/reports/interfaces/report-views.interface.d.ts +7 -0
  78. package/app/reports/interfaces/report.interface.d.ts +48 -5
  79. package/app/reports/interfaces/tile-load-result.interface.d.ts +4 -0
  80. package/app/reports/layout.d.ts +2 -0
  81. package/app/reports/mark-click.d.ts +20 -0
  82. package/app/reports/option-builder.d.ts +12 -1
  83. package/app/reports/report-chat-viewer-state.d.ts +8 -0
  84. package/app/reports/report-date-presets.d.ts +2 -0
  85. package/app/reports/report-filter-items.d.ts +27 -22
  86. package/app/reports/report-tile.d.ts +2 -0
  87. package/app/reports/report-url-state.d.ts +27 -10
  88. package/app/reports/report-view-config.d.ts +36 -0
  89. package/app/reports/report-view-menu.d.ts +15 -0
  90. package/app/reports/report-viewer-features.d.ts +5 -0
  91. package/app/reports/services/report-filter-options.service.d.ts +26 -0
  92. package/app/reports/services/report-filter-state.service.d.ts +65 -2
  93. package/app/reports/services/report-view.service.d.ts +51 -0
  94. package/app/reports/text.d.ts +50 -0
  95. package/app/reports/tile-data-state.d.ts +7 -0
  96. package/app/reports/tile-loads.d.ts +4 -0
  97. package/app/reports/values.d.ts +17 -0
  98. package/app/reports/views/report/fs-ai-report.component.d.ts +9 -1
  99. package/app/reports/views/report/report.component.d.ts +6 -0
  100. package/esm2022/app/reports/anchor-at-point.mjs +49 -0
  101. package/esm2022/app/reports/canvas-landing-page.mjs +25 -0
  102. package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +97 -5
  103. package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +11 -4
  104. package/esm2022/app/reports/components/component-list/component-list.component.mjs +7 -1
  105. package/esm2022/app/reports/components/component-text/component-text.component.mjs +213 -16
  106. package/esm2022/app/reports/components/component-text/value-embed.plugin.mjs +484 -0
  107. package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +296 -55
  108. package/esm2022/app/reports/components/report-component/report-component.component.mjs +318 -76
  109. package/esm2022/app/reports/components/report-view-picker/report-view-picker.component.mjs +115 -0
  110. package/esm2022/app/reports/data/report.data.mjs +103 -8
  111. package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +210 -44
  112. package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +86 -90
  113. package/esm2022/app/reports/dialogs/report-view/report-view-dialog.component.mjs +52 -0
  114. package/esm2022/app/reports/drill-crumbs.mjs +73 -0
  115. package/esm2022/app/reports/enums/report-value-formula.enum.mjs +14 -0
  116. package/esm2022/app/reports/export/report-export-collector.service.mjs +299 -125
  117. package/esm2022/app/reports/export/report-export.service.mjs +57 -19
  118. package/esm2022/app/reports/export/report-filter-lines.mjs +235 -0
  119. package/esm2022/app/reports/export/report-pdf.service.mjs +315 -71
  120. package/esm2022/app/reports/export/report-pptx.service.mjs +293 -71
  121. package/esm2022/app/reports/export/report-text-layout.service.mjs +241 -0
  122. package/esm2022/app/reports/filter-settings-rules.mjs +283 -0
  123. package/esm2022/app/reports/format.mjs +13 -30
  124. package/esm2022/app/reports/interfaces/canvas-landing-input.interface.mjs +2 -0
  125. package/esm2022/app/reports/interfaces/component-data-applied.interface.mjs +2 -0
  126. package/esm2022/app/reports/interfaces/component-data-drill.interface.mjs +2 -0
  127. package/esm2022/app/reports/interfaces/filter-bar-placement.type.mjs +2 -0
  128. package/esm2022/app/reports/interfaces/filter-component-toggle-state.interface.mjs +2 -0
  129. package/esm2022/app/reports/interfaces/filter-settings-option.interface.mjs +2 -0
  130. package/esm2022/app/reports/interfaces/filter-type-select-state.interface.mjs +2 -0
  131. package/esm2022/app/reports/interfaces/report-chart-hit.interface.mjs +2 -0
  132. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.mjs +2 -0
  133. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter.interface.mjs +2 -0
  134. package/esm2022/app/reports/interfaces/report-chat-viewer-detail.interface.mjs +2 -0
  135. package/esm2022/app/reports/interfaces/report-chat-viewer-drill-step.interface.mjs +2 -0
  136. package/esm2022/app/reports/interfaces/report-chat-viewer-drill.interface.mjs +2 -0
  137. package/esm2022/app/reports/interfaces/report-chat-viewer-filter.interface.mjs +1 -1
  138. package/esm2022/app/reports/interfaces/report-chat-viewer-selection.interface.mjs +2 -0
  139. package/esm2022/app/reports/interfaces/report-chat-viewer-state.interface.mjs +1 -1
  140. package/esm2022/app/reports/interfaces/report-drill-crumb.interface.mjs +2 -0
  141. package/esm2022/app/reports/interfaces/report-drill-refusal.type.mjs +2 -0
  142. package/esm2022/app/reports/interfaces/report-drill-step.interface.mjs +2 -0
  143. package/esm2022/app/reports/interfaces/report-export-line-kind.type.mjs +2 -0
  144. package/esm2022/app/reports/interfaces/report-export-line.interface.mjs +2 -0
  145. package/esm2022/app/reports/interfaces/report-export-lines-input.interface.mjs +2 -0
  146. package/esm2022/app/reports/interfaces/report-export-snapshot.interface.mjs +2 -0
  147. package/esm2022/app/reports/interfaces/report-filter-line-context.interface.mjs +2 -0
  148. package/esm2022/app/reports/interfaces/report-filter-line-form.type.mjs +2 -0
  149. package/esm2022/app/reports/interfaces/report-filter-match.type.mjs +2 -0
  150. package/esm2022/app/reports/interfaces/report-filter-option-pair.interface.mjs +2 -0
  151. package/esm2022/app/reports/interfaces/report-filter-options-ask.interface.mjs +2 -0
  152. package/esm2022/app/reports/interfaces/report-filter-options-list.interface.mjs +2 -0
  153. package/esm2022/app/reports/interfaces/report-filter-options-request.interface.mjs +2 -0
  154. package/esm2022/app/reports/interfaces/report-filter-options-stream.interface.mjs +2 -0
  155. package/esm2022/app/reports/interfaces/report-filter-options.interface.mjs +2 -0
  156. package/esm2022/app/reports/interfaces/report-filter-skip.type.mjs +2 -0
  157. package/esm2022/app/reports/interfaces/report-mark-action.type.mjs +2 -0
  158. package/esm2022/app/reports/interfaces/report-mark-click.interface.mjs +2 -0
  159. package/esm2022/app/reports/interfaces/report-mark-context.interface.mjs +2 -0
  160. package/esm2022/app/reports/interfaces/report-mark-decision.interface.mjs +2 -0
  161. package/esm2022/app/reports/interfaces/report-mark-event.interface.mjs +2 -0
  162. package/esm2022/app/reports/interfaces/report-mark-point.interface.mjs +2 -0
  163. package/esm2022/app/reports/interfaces/report-temporary-state.interface.mjs +2 -0
  164. package/esm2022/app/reports/interfaces/report-tile-state.interface.mjs +2 -0
  165. package/esm2022/app/reports/interfaces/report-url-link.interface.mjs +2 -0
  166. package/esm2022/app/reports/interfaces/report-url-value-name.type.mjs +2 -0
  167. package/esm2022/app/reports/interfaces/report-url-write.interface.mjs +2 -0
  168. package/esm2022/app/reports/interfaces/report-view-config.interface.mjs +2 -0
  169. package/esm2022/app/reports/interfaces/report-view-create.interface.mjs +2 -0
  170. package/esm2022/app/reports/interfaces/report-view-deleted.interface.mjs +2 -0
  171. package/esm2022/app/reports/interfaces/report-view-dialog-data.interface.mjs +2 -0
  172. package/esm2022/app/reports/interfaces/report-view-dropped.interface.mjs +2 -0
  173. package/esm2022/app/reports/interfaces/report-view-menu-item.interface.mjs +2 -0
  174. package/esm2022/app/reports/interfaces/report-view-summary.interface.mjs +2 -0
  175. package/esm2022/app/reports/interfaces/report-view.interface.mjs +2 -0
  176. package/esm2022/app/reports/interfaces/report-viewer-feature.type.mjs +2 -0
  177. package/esm2022/app/reports/interfaces/report-views.interface.mjs +2 -0
  178. package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
  179. package/esm2022/app/reports/interfaces/tile-load-result.interface.mjs +2 -0
  180. package/esm2022/app/reports/layout.mjs +11 -1
  181. package/esm2022/app/reports/mark-click.mjs +193 -0
  182. package/esm2022/app/reports/option-builder.mjs +159 -15
  183. package/esm2022/app/reports/report-chat-viewer-state.mjs +34 -0
  184. package/esm2022/app/reports/report-date-presets.mjs +18 -0
  185. package/esm2022/app/reports/report-filter-items.mjs +343 -72
  186. package/esm2022/app/reports/report-tile.mjs +12 -0
  187. package/esm2022/app/reports/report-url-state.mjs +596 -108
  188. package/esm2022/app/reports/report-view-config.mjs +697 -0
  189. package/esm2022/app/reports/report-view-menu.mjs +119 -0
  190. package/esm2022/app/reports/report-viewer-features.mjs +42 -0
  191. package/esm2022/app/reports/services/report-filter-options.service.mjs +238 -0
  192. package/esm2022/app/reports/services/report-filter-state.service.mjs +715 -71
  193. package/esm2022/app/reports/services/report-view.service.mjs +358 -0
  194. package/esm2022/app/reports/text.mjs +293 -85
  195. package/esm2022/app/reports/tile-data-state.mjs +127 -0
  196. package/esm2022/app/reports/tile-loads.mjs +38 -0
  197. package/esm2022/app/reports/values.mjs +183 -0
  198. package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +180 -46
  199. package/esm2022/app/reports/views/report/report.component.mjs +106 -23
  200. package/esm2022/public_api.mjs +24 -1
  201. package/fesm2022/{firestitch-report-echarts-CFnbJx44.mjs → firestitch-report-echarts-UBg8Wlhd.mjs} +2 -2
  202. package/fesm2022/{firestitch-report-echarts-CFnbJx44.mjs.map → firestitch-report-echarts-UBg8Wlhd.mjs.map} +1 -1
  203. package/fesm2022/{firestitch-report-firestitch-report-CSylkyko.mjs → firestitch-report-firestitch-report-B1keNrcK.mjs} +11315 -4201
  204. package/fesm2022/firestitch-report-firestitch-report-B1keNrcK.mjs.map +1 -0
  205. package/fesm2022/firestitch-report.mjs +1 -1
  206. package/package.json +1 -1
  207. package/public_api.d.ts +23 -0
  208. package/fesm2022/firestitch-report-firestitch-report-CSylkyko.mjs.map +0 -1
@@ -1,9 +1,11 @@
1
- import { ItemType } from '@firestitch/filter';
1
+ import { ItemType, getExcludeName } from '@firestitch/filter';
2
2
  import { format, parseISO } from 'date-fns';
3
3
  import { of } from 'rxjs';
4
4
  import { map, shareReplay } from 'rxjs/operators';
5
- import { DAY_SHORT, formatLocalDate } from './format';
5
+ import { filterLineText, matchLineText } from './export/report-filter-lines';
6
+ import { DAY_SHORT, formatLocalDate, resolveFormatContext } from './format';
6
7
  import { GRANULARITY_OPTIONS, } from './interfaces/report.interface';
8
+ import { offersExclude } from './report-viewer-features';
7
9
  // A date-range boundary as the picked LOCAL calendar day (no time, no tz).
8
10
  // Date-range filters are calendar-day semantics, so the boundary must carry
9
11
  // only Y-M-D — never a timezone-bearing instant the backend would shift.
@@ -67,14 +69,8 @@ export function relativeLabel(relative) {
67
69
  // query values back into per-group FilterGroupValues. Shared by the report-bar
68
70
  // fs-filter and the per-component fs-filter so both render through the same
69
71
  // library and write into ReportFilterStateService identically. Items are named
70
- // `g<groupId>` so the query keys map straight back to the group.
71
- // The prefix of a group's item name, and of its key in the report URL.
72
- export const GROUP_PARAM_PREFIX = 'g';
73
- // The query key fs-filter uses for a group's item(s), and the report URL's key
74
- // for the group's value (report-url-state.ts). One naming for both.
75
- export function groupItemName(group) {
76
- return `${GROUP_PARAM_PREFIX}${group.id}`;
77
- }
72
+ // by the group's key (groupParamKeys), so the query keys map straight back to
73
+ // the group, and the report link uses the same query keys (report-url-state.ts).
78
74
  // The query key for the report's group-by control. Fixed rather than derived
79
75
  // from an id because a report has exactly one — and it is NOT a filter group,
80
76
  // so it is read straight off the change query instead of through
@@ -82,15 +78,115 @@ export function groupItemName(group) {
82
78
  // (report-url-state.ts). The grain travels to the server as the data
83
79
  // request's `state.frequency`.
84
80
  export const GROUP_BY_ITEM = 'groupBy';
81
+ // The keys of the report URL that are not filter groups (report-url-state.ts
82
+ // reads and writes them). They are declared here because a group key must
83
+ // not take one, and report-url-state.ts imports this file.
84
+ // The shared view the state is a diff from, and the open personal view.
85
+ export const VIEW_PARAM = 'rv';
86
+ export const PERSONAL_VIEW_PARAM = 'rpv';
87
+ // The link's format.
88
+ export const FORMAT_PARAM = 'rf';
89
+ // The host's page key (FsAiReportComponent.pageQueryParam), as most hosts
90
+ // name it.
91
+ export const PAGE_PARAM = 'page';
92
+ // The word before a group's id in the key of a group whose label gives no
93
+ // key it can use (filter12).
94
+ const FALLBACK_KEY_WORD = 'filter';
95
+ // The query key of one end of an fs-filter range item: the item's name and
96
+ // the end with its first letter upper-cased (fs-filter's getRangeName), so
97
+ // units gives unitsMin and date gives dateFrom.
98
+ export function itemRangeName(name, end) {
99
+ return `${name}${end.charAt(0).toUpperCase()}${end.slice(1)}`;
100
+ }
101
+ // Each group's key in the report URL, by group id, which is also the name of
102
+ // its fs-filter item: the camelCase of the label the bar shows ('Region' ->
103
+ // region, 'Report Period' -> reportPeriod). The link writes a group under
104
+ // the item's own query keys (region=, excludeRegion=, unitsMin=, dateFrom=).
105
+ // A key the report cannot give a group as it is (another group with a lower
106
+ // id has it or one of its forms, another link key or bar item uses it, or it
107
+ // is shaped like a tile's id key, such as q4) is the key and the group's id
108
+ // (region12). A label with no letter or digit, or a clash even then, keys on
109
+ // filter<id>. `groups` is every group of the report, so every bar and the
110
+ // link name a group alike.
111
+ export function groupParamKeys(groups) {
112
+ // The URL's other keys and the bar's other items.
113
+ const taken = new Set([
114
+ PAGE_PARAM, GROUP_BY_ITEM, MATCH_ITEM, LIST_SEARCH_ITEM, VIEW_PARAM, PERSONAL_VIEW_PARAM, FORMAT_PARAM,
115
+ ]);
116
+ const free = (candidate) => !!candidate
117
+ && keyForms(candidate).every((form) => !taken.has(form) && !ID_KEY.test(form));
118
+ const keys = new Map();
119
+ [...groups]
120
+ .sort((a, b) => a.id - b.id)
121
+ .forEach((group) => {
122
+ const wanted = labelKey(groupLabel(group));
123
+ const key = [wanted, wanted && `${wanted}${group.id}`].find(free) ?? fallbackKey(group.id, free);
124
+ keyForms(key).forEach((form) => taken.add(form));
125
+ keys.set(group.id, key);
126
+ });
127
+ return keys;
128
+ }
129
+ // filter<id>, or, in the rare report where another group's label already
130
+ // gives that, filter<id> and a count.
131
+ function fallbackKey(groupId, free) {
132
+ const base = `${FALLBACK_KEY_WORD}${groupId}`;
133
+ let key = base;
134
+ for (let count = 2; !free(key); count++) {
135
+ key = `${base}N${count}`;
136
+ }
137
+ return key;
138
+ }
139
+ // A group's key among `groups` (every group of the report). A group that is
140
+ // not among them is keyed as one more of them.
141
+ export function groupParamKey(group, groups) {
142
+ return groupParamKeys(groups.some((candidate) => candidate.id === group.id) ? groups : [...groups, group])
143
+ .get(group.id);
144
+ }
145
+ // The name of a group's fs-filter item: its key among the report's groups.
146
+ export function groupItemName(group, report) {
147
+ return groupParamKey(group, report?.filterGroups ?? []);
148
+ }
149
+ // The label a group's chip shows: its own, else its first member's column.
150
+ function groupLabel(group) {
151
+ return group.label || group.filters?.[0]?.filterColumn || '';
152
+ }
153
+ // A letter and then digits: the shape of the URL's tile keys (s31, q31,
154
+ // h31, d44), kept off the groups so a group key never reads as one.
155
+ const ID_KEY = /^[a-z]\d+$/;
156
+ const RANGE_ENDS = ['min', 'max', 'from', 'to'];
157
+ // Every key a group's item or link may write under `key`: the key, its
158
+ // exclude key (excludeRegion) and an fs-filter range's own keys.
159
+ function keyForms(key) {
160
+ return [key, getExcludeName(key), ...RANGE_ENDS.map((end) => itemRangeName(key, end))];
161
+ }
162
+ // A label as a camelCase key: accents dropped, words split on anything that
163
+ // is not a letter or digit (and where a lower-case letter meets an upper-case
164
+ // one), the first word lower-case, every later one capitalized.
165
+ function labelKey(label) {
166
+ return label
167
+ .normalize('NFD')
168
+ .replace(/\p{M}/gu, '')
169
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
170
+ .split(/[^A-Za-z0-9]+/)
171
+ .filter((word) => word !== '')
172
+ .map((word, index) => {
173
+ const lower = word.toLowerCase();
174
+ return index ? lower.charAt(0).toUpperCase() + lower.slice(1) : lower;
175
+ })
176
+ .join('');
177
+ }
85
178
  // A select group's distinct options, as { name, value } pairs. The server sends
86
179
  // { value, label }: the value is what the filter matches on (an entity's stable
87
180
  // id) and the label is what the viewer reads — so a renamed entity keeps its id
88
181
  // and simply shows its new name here. Options come from the first member filter
89
182
  // that declares them — members are the same data point, so any member's list
90
183
  // serves the group. The list is fetched once (the server caps it) and replayed
91
- // (shareReplay), so repeated reads never refetch. Shared by the report-bar
92
- // select control and the report-settings default picker so the two never drift.
93
- // Returns an empty list when no member provides options.
184
+ // (shareReplay), so repeated reads never refetch. This is the full list, never
185
+ // narrowed by other filters: the report-settings default picker reads it (an
186
+ // author sets a default against the whole list), and so does the export's
187
+ // filter wording for a pick the bar has not named. The bars read
188
+ // ReportFilterOptionsService instead. Returns an empty list when no member
189
+ // provides options.
94
190
  export function loadGroupOptions(group, reportData, reportId) {
95
191
  const optionFilter = (group.filters ?? []).find((member) => member.hasOptions);
96
192
  if (!optionFilter) {
@@ -102,15 +198,21 @@ export function loadGroupOptions(group, reportData, reportId) {
102
198
  }
103
199
  // Stored filter values (ids) paired back with the labels to show for them.
104
200
  // A saved default holds only values, so the names have to be read back off the
105
- // option list — that indirection is exactly what survives a rename. A value with
106
- // no matching option (its entity was deleted, so it is no longer listed) falls
107
- // back to showing the raw value rather than dropping the chip, which would
108
- // silently widen the filter.
109
- export function resolveOptionValues(options$, values) {
110
- return options$.pipe(map((options) => values.map((value) => {
201
+ // option list — that indirection is exactly what survives a rename. `label`
202
+ // names a value first: a name already learned (ReportFilterOptionsService.label)
203
+ // holds for a pick a narrowed list leaves out, and when it names every value
204
+ // the list is not read at all. A value with no name and no matching option
205
+ // (its entity was deleted, so it is no longer listed) falls back to showing
206
+ // the raw value rather than dropping the chip, which would silently widen the
207
+ // filter.
208
+ export function resolveOptionValues(options$, values, label = () => null) {
209
+ const named = (options) => values.map((value) => {
111
210
  const option = options.find((candidate) => String(candidate.value) === String(value));
112
- return { name: option?.name ?? String(value), value };
113
- })));
211
+ return { name: label(value) ?? option?.name ?? String(value), value };
212
+ });
213
+ return values.every((value) => label(value) !== null)
214
+ ? of(named([]))
215
+ : options$.pipe(map(named));
114
216
  }
115
217
  // Case-insensitive name filter applied to a loaded option list — the typed
116
218
  // keyword has to be matched here because fs-autocomplete renders what we return
@@ -121,47 +223,161 @@ export function matchOptions(options$, keyword) {
121
223
  ? options.filter((option) => option.name.toLowerCase().includes(term))
122
224
  : options));
123
225
  }
226
+ // The panel row of a select whose list the server cut at 500.
227
+ export const OPTIONS_TRUNCATED_NOTE = 'Showing the first 500. Type to narrow.';
228
+ // The panel row of a select whose list could not be read. The next focus or
229
+ // keystroke asks again.
230
+ export const OPTIONS_FAILED_NOTE = 'Could not load the list.';
124
231
  // Build the fs-filter config item for a group, seeding its default from the
125
232
  // current session value so authored/relative defaults show selected on open.
126
- export function filterItemForGroup(group, reportData, reportId, initial) {
127
- const name = groupItemName(group);
128
- const label = group.label || group.filters?.[0]?.filterColumn || '';
233
+ // A select lists what `options` offers for it in `report`. `features` is the
234
+ // report's viewerFeatures: a select offers 'Exclude these' by the rule of
235
+ // offersExclude (the server lists excludeValues and no member binds several
236
+ // columns), and a number range is a min/max control only when it lists
237
+ // numberRange.
238
+ export function filterItemForGroup(group, options, report, initial, features = []) {
239
+ const name = groupItemName(group, report);
240
+ const label = groupLabel(group);
129
241
  switch (group.type) {
130
242
  case 'dateRange':
131
- return {
132
- name,
133
- type: ItemType.DateRange,
134
- label: { from: `${label} From`, to: `${label} To` },
135
- default: (initial?.start || initial?.end)
136
- ? { from: initial.start ?? undefined, to: initial.end ?? undefined }
137
- : undefined,
138
- };
139
- case 'select': {
140
- // One shared, replayed option stream so typing never refetches.
141
- const options$ = loadGroupOptions(group, reportData, reportId);
142
- const values = initial?.values;
143
- return {
144
- name,
145
- type: ItemType.AutoCompleteChips,
146
- label,
147
- fetchOnFocus: true,
148
- values: (keyword) => matchOptions(options$, keyword),
149
- // Stored values are ids, so the chips can only be named once the option
150
- // list has loaded — hence the observable form of `default`.
151
- default: values?.length
152
- ? () => resolveOptionValues(options$, values)
153
- : undefined,
154
- };
155
- }
243
+ return dateRangeFilterItem(name, label, initial);
244
+ case 'select':
245
+ return selectFilterItem(group, label, options, report, initial, offersExclude(group, features));
246
+ case 'numberRange':
247
+ return features.includes('numberRange')
248
+ ? numberRangeFilterItem(group, label, report, initial)
249
+ : keywordFilterItem(name, label, initial);
156
250
  case 'keyword':
157
251
  default:
158
- return {
159
- name,
160
- type: ItemType.Keyword,
161
- label,
162
- default: initial?.value,
163
- };
252
+ return keywordFilterItem(name, label, initial);
253
+ }
254
+ }
255
+ // A date range opens on its days, and its chip shows them. A preset picked in
256
+ // the date picker only sets the days.
257
+ function dateRangeFilterItem(name, label, initial) {
258
+ const hasDays = !!(initial?.start || initial?.end);
259
+ return {
260
+ name,
261
+ type: ItemType.DateRange,
262
+ label: { from: `${label} From`, to: `${label} To` },
263
+ default: hasDays
264
+ ? { from: initial.start ?? undefined, to: initial.end ?? undefined }
265
+ : undefined,
266
+ };
267
+ }
268
+ // A select's picks, kept or left out. With `exclude` the list has the
269
+ // 'Exclude these' row, and a value that leaves out opens with it on. Its list
270
+ // is read on focus and on each keystroke: the options service fetches it when
271
+ // the other filters changed since and replays it otherwise, and typing
272
+ // filters it here. A list the server cut, or one that could not be read,
273
+ // says so in a panel row.
274
+ function selectFilterItem(group, label, options, report, initial, exclude) {
275
+ const excluding = exclude && !initial?.values?.length && !!initial?.excludeValues?.length;
276
+ const picks = excluding ? initial.excludeValues : initial?.values;
277
+ const options$ = options.options(group, report);
278
+ return {
279
+ name: groupItemName(group, report),
280
+ type: ItemType.AutoCompleteChips,
281
+ label,
282
+ fetchOnFocus: true,
283
+ exclude: exclude ? {} : undefined,
284
+ values: (keyword) => matchOptions(options$, keyword),
285
+ panelNote: () => optionsNote(options, group.id),
286
+ // Stored values are ids, so a chip is named by a name already learned or
287
+ // once the option list has loaded — hence the observable form of `default`.
288
+ default: picks?.length
289
+ ? () => resolveOptionValues(options$, picks, (value) => options.label(group.id, value))
290
+ .pipe(map((selected) => (excluding ? { exclude: true, selected } : selected)))
291
+ : undefined,
292
+ };
293
+ }
294
+ // The panel row of a select's latest list: a failure first, then a cut list.
295
+ function optionsNote(options, groupId) {
296
+ if (options.failed(groupId)) {
297
+ return OPTIONS_FAILED_NOTE;
164
298
  }
299
+ return options.truncated(groupId) ? OPTIONS_TRUNCATED_NOTE : null;
300
+ }
301
+ // A number range's low and high ends, either one open. 0 is an end like any
302
+ // other. Its chip reads as the export lines do ('Amount: 0 or more',
303
+ // 'Amount: 0 to 10'): the ends are read off the item's query the way the
304
+ // bar's change reads them, and worded in the report's locale.
305
+ function numberRangeFilterItem(group, label, report, initial) {
306
+ const name = groupItemName(group, report);
307
+ const min = initial?.min ?? undefined;
308
+ const max = initial?.max ?? undefined;
309
+ const locale = resolveFormatContext(report ?? {}).locale;
310
+ return {
311
+ name,
312
+ type: ItemType.Range,
313
+ label,
314
+ default: min !== undefined || max !== undefined ? { min, max } : undefined,
315
+ chipText: (item) => filterLineText({ label, level: group.level }, numberRangeFromQuery(item.query, name), { locale }, 'chip'),
316
+ };
317
+ }
318
+ function keywordFilterItem(name, label, initial) {
319
+ return {
320
+ name,
321
+ type: ItemType.Keyword,
322
+ label,
323
+ default: initial?.value,
324
+ };
325
+ }
326
+ // The groups a match of 'any' combines: report bar groups (a page group on
327
+ // its own page only) that a viewer picks values, text or a number range in.
328
+ // Dates, tile-only groups and the cross-filter always narrow on their own.
329
+ // The server holds the same rule and checks every id it is sent.
330
+ const MATCH_ANY_LEVELS = ['report', 'both', 'page'];
331
+ const MATCH_ANY_TYPES = ['select', 'keyword', 'numberRange'];
332
+ // Whether a group joins a match of 'any' on page `pageId`.
333
+ export function isMatchAnyGroup(group, pageId) {
334
+ return MATCH_ANY_LEVELS.includes(group.level)
335
+ && MATCH_ANY_TYPES.includes(group.type)
336
+ && (group.level !== 'page' || (!!pageId && group.pageId === pageId));
337
+ }
338
+ // The report bar's groups in their saved order: the report and both groups,
339
+ // and the page groups of the page on screen (`pageId`).
340
+ export function reportBarGroups(report, pageId) {
341
+ return (report?.filterGroups ?? [])
342
+ .filter((group) => group.level === 'report' || group.level === 'both'
343
+ || (group.level === 'page' && !!pageId && group.pageId === pageId))
344
+ .sort((a, b) => a.order - b.order);
345
+ }
346
+ // Whether the report has a group shown on one page only, so its report bar
347
+ // changes with the page on screen.
348
+ export function hasPageGroup(report) {
349
+ return (report?.filterGroups ?? []).some((group) => group.level === 'page');
350
+ }
351
+ // The query key of the report bar's Match control. Not a filter group: it
352
+ // says how the groups combine, so it is read straight off the change query.
353
+ // It is also the report URL's key for the match (match=any).
354
+ export const MATCH_ITEM = 'match';
355
+ const MATCH_OPTIONS = [
356
+ { name: 'All filters', value: 'all' },
357
+ { name: 'Any filter', value: 'any' },
358
+ ];
359
+ // The report bar's Match control, last in the bar, or null when it would do
360
+ // nothing: the server must serve matchAny, and the bar must hold two or more
361
+ // groups that combine (an 'any' over one group is that group).
362
+ export function matchFilterItem(report, groups, pageId, match) {
363
+ const eligible = groups.filter((group) => isMatchAnyGroup(group, pageId));
364
+ if (!report?.viewerFeatures?.includes('matchAny') || eligible.length < 2) {
365
+ return null;
366
+ }
367
+ return {
368
+ name: MATCH_ITEM,
369
+ type: ItemType.Select,
370
+ label: 'Match',
371
+ multiple: false,
372
+ values: () => MATCH_OPTIONS,
373
+ default: match,
374
+ // 'Match: any filter' or 'Match: all filters', in the export lines' words.
375
+ chipText: (item) => matchLineText(matchFromQuery(item.query), 'chip'),
376
+ };
377
+ }
378
+ // The match a change query of a bar with the Match control asks for.
379
+ export function matchFromQuery(query) {
380
+ return query?.[MATCH_ITEM] === 'any' ? 'any' : 'all';
165
381
  }
166
382
  // The query key of a list's search box in its component header. Fixed rather
167
383
  // than derived from an id because a header holds at most one, and it is NOT a
@@ -245,26 +461,81 @@ export function groupBySignature(report) {
245
461
  }
246
462
  // Read an fs-filter change query into per-group values. Returns one entry per
247
463
  // group with the value to store (or null to clear) — callers feed these to
248
- // ReportFilterStateService.setValue.
249
- export function groupValuesFromQuery(query, groups) {
464
+ // ReportFilterStateService.setValue. `report` names the groups' items.
465
+ export function groupValuesFromQuery(query, groups, report) {
250
466
  return groups.map((group) => {
251
- const name = groupItemName(group);
252
- if (group.type === 'dateRange') {
253
- const start = query[`${name}From`];
254
- const end = query[`${name}To`];
255
- return {
256
- groupId: group.id,
257
- value: (start || end) ? { start: start || null, end: end || null } : null,
258
- };
467
+ const name = groupItemName(group, report);
468
+ switch (group.type) {
469
+ case 'dateRange':
470
+ return { groupId: group.id, value: dateRangeFromQuery(query, name) };
471
+ case 'select':
472
+ return { groupId: group.id, value: selectFromQuery(query, name) };
473
+ case 'numberRange':
474
+ return { groupId: group.id, value: numberRangeFromQuery(query, name) };
475
+ default: {
476
+ const keyword = String(query[name] ?? '').trim();
477
+ return { groupId: group.id, value: keyword ? { value: keyword } : null };
478
+ }
259
479
  }
260
- if (group.type === 'select') {
261
- const values = selectQueryValues(query[name]);
262
- return { groupId: group.id, value: values.length ? { values } : null };
263
- }
264
- const keyword = String(query[name] ?? '').trim();
265
- return { groupId: group.id, value: keyword ? { value: keyword } : null };
266
480
  });
267
481
  }
482
+ // A date range's days (<key>From, <key>To).
483
+ function dateRangeFromQuery(query, name) {
484
+ const start = query[itemRangeName(name, 'from')];
485
+ const end = query[itemRangeName(name, 'to')];
486
+ if (!start && !end) {
487
+ return null;
488
+ }
489
+ return { start: start || null, end: end || null };
490
+ }
491
+ // A select's picks: kept (<key>), or left out while its exclude row is on
492
+ // (exclude<Key>).
493
+ function selectFromQuery(query, name) {
494
+ const excludeValues = selectQueryValues(query[getExcludeName(name)]);
495
+ if (excludeValues.length) {
496
+ return { excludeValues };
497
+ }
498
+ const values = selectQueryValues(query[name]);
499
+ return values.length ? { values } : null;
500
+ }
501
+ // A number range's ends (<key>Min, <key>Max). An end left empty is open.
502
+ function numberRangeFromQuery(query, name) {
503
+ const min = rangeBound(query[itemRangeName(name, 'min')]);
504
+ const max = rangeBound(query[itemRangeName(name, 'max')]);
505
+ if (min === null && max === null) {
506
+ return null;
507
+ }
508
+ return {
509
+ ...(min !== null ? { min } : {}),
510
+ ...(max !== null ? { max } : {}),
511
+ };
512
+ }
513
+ // One end of a number range as fs-filter's Range sends it: the text typed in
514
+ // its input. Number() reads any non-empty text, so '0' is the end 0; empty or
515
+ // unreadable text is an open end.
516
+ function rangeBound(raw) {
517
+ const text = typeof raw === 'number' ? String(raw) : String(raw ?? '').trim();
518
+ const number = text === '' ? NaN : Number(text);
519
+ return Number.isFinite(number) ? number : null;
520
+ }
521
+ // A group value as text, the same for the same value whatever its source:
522
+ // days as calendar days, picks and ends as text, keyword text trimmed. The
523
+ // value a tile header was built with is keyed on it, so a header is created
524
+ // again when another bar changes a group it shows.
525
+ export function groupValueSignature(value) {
526
+ if (!value) {
527
+ return '';
528
+ }
529
+ return JSON.stringify([
530
+ dateBoundString(value.start) ?? '',
531
+ dateBoundString(value.end) ?? '',
532
+ (value.values ?? []).map(String),
533
+ (value.excludeValues ?? []).map(String),
534
+ (value.value ?? '').trim(),
535
+ value.min ?? '',
536
+ value.max ?? '',
537
+ ]);
538
+ }
268
539
  // fs-filter's AutoCompleteChips serialises a multi-select into ONE query value:
269
540
  // the selected values joined by "," (its `query` getter does `.map(value).join(',')`).
270
541
  // So a 2+ selection arrives as the string "a,b", not an array — splitting on ","
@@ -279,4 +550,4 @@ function selectQueryValues(raw) {
279
550
  }
280
551
  return String(raw).split(',');
281
552
  }
282
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LWZpbHRlci1pdGVtcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9yZXBvcnQtZmlsdGVyLWl0ZW1zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBcUIsUUFBUSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFakUsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFNUMsT0FBTyxFQUFjLEVBQUUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN0QyxPQUFPLEVBQUUsR0FBRyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBR2xELE9BQU8sRUFBRSxTQUFTLEVBQUUsZUFBZSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ3RELE9BQU8sRUFDK0IsbUJBQW1CLEdBRXhELE1BQU0sK0JBQStCLENBQUM7QUFHdkMsMkVBQTJFO0FBQzNFLDRFQUE0RTtBQUM1RSx5RUFBeUU7QUFDekUsTUFBTSxVQUFVLGVBQWUsQ0FBQyxLQUF1QztJQUNyRSxJQUFJLEtBQUssWUFBWSxJQUFJLEVBQUUsQ0FBQztRQUMxQixPQUFPLE1BQU0sQ0FBQyxLQUFLLEVBQUUsWUFBWSxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVELHNFQUFzRTtJQUN0RSw4QkFBOEI7SUFDOUIsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDeEQsQ0FBQztBQUdELDhFQUE4RTtBQUM5RSwrRUFBK0U7QUFDL0UsOEVBQThFO0FBQzlFLGlFQUFpRTtBQUNqRSxFQUFFO0FBQ0YsZ0ZBQWdGO0FBQ2hGLGdGQUFnRjtBQUNoRiw2REFBNkQ7QUFDN0QsRUFBRTtBQUNGLDRFQUE0RTtBQUM1RSwyQ0FBMkM7QUFDM0MsTUFBTSxVQUFVLGNB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QUVELE9BQU8sTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNoQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSUZpbHRlckNvbmZpZ0l0ZW0sIEl0ZW1UeXBlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvZmlsdGVyJztcblxuaW1wb3J0IHsgZm9ybWF0LCBwYXJzZUlTTyB9IGZyb20gJ2RhdGUtZm5zJztcblxuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgb2YgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IG1hcCwgc2hhcmVSZXBsYXkgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IFJlcG9ydERhdGEgfSBmcm9tICcuL2RhdGEvcmVwb3J0LmRhdGEnO1xuaW1wb3J0IHsgREFZX1NIT1JULCBmb3JtYXRMb2NhbERhdGUgfSBmcm9tICcuL2Zvcm1hdCc7XG5pbXBvcnQge1xuICBDaGFydEdyYW51bGFyaXR5LCBGaWx0ZXJHcm91cFZhbHVlLCBHUkFOVUxBUklUWV9PUFRJT05TLCBSZXBvcnQsIFJlcG9ydEZpbHRlckdyb3VwLCBSZXBvcnRGaWx0ZXJPcHRpb24sXG4gIFJlcG9ydExvY2FsZVRhZyxcbn0gZnJvbSAnLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuXG5cbi8vIEEgZGF0ZS1yYW5nZSBib3VuZGFyeSBhcyB0aGUgcGlja2VkIExPQ0FMIGNhbGVuZGFyIGRheSAobm8gdGltZSwgbm8gdHopLlxuLy8gRGF0ZS1yYW5nZSBmaWx0ZXJzIGFyZSBjYWxlbmRhci1kYXkgc2VtYW50aWNzLCBzbyB0aGUgYm91bmRhcnkgbXVzdCBjYXJyeVxuLy8gb25seSBZLU0tRCDigJQgbmV2ZXIgYSB0aW1lem9uZS1iZWFyaW5nIGluc3RhbnQgdGhlIGJhY2tlbmQgd291bGQgc2hpZnQuXG5leHBvcnQgZnVuY3Rpb24gZGF0ZUJvdW5kU3RyaW5nKHZhbHVlOiBEYXRlIHwgc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICByZXR1cm4gZm9ybWF0KHZhbHVlLCAneXl5eS1NTS1kZCcpO1xuICB9XG5cbiAgLy8gQXV0aG9yZWQvcmVsYXRpdmUgZGVmYXVsdHMgYXJyaXZlIGFzIHN0cmluZ3MgYWxyZWFkeSBpbiBZLU0tRCBmb3JtO1xuICAvLyBrZWVwIGp1c3QgdGhlIGRhdGUgcG9ydGlvbi5cbiAgcmV0dXJuIHZhbHVlID8gU3RyaW5nKHZhbHVlKS5zbGljZSgwLCAxMCkgOiB1bmRlZmluZWQ7XG59XG5cblxuLy8gQSBkYXRlLXJhbmdlIGJvdW5kYXJ5IGFzIGl0IHNob3VsZCBSRUFEIG9uIGEgY292ZXIgcGFnZSDigJQgdGhlIHNhbWUgY2FsZW5kYXJcbi8vIGRheSBkYXRlQm91bmRTdHJpbmcoKSBoYW5kcyB0aGUgc2VydmVyLCBzbyBhIHByaW50ZWQgcGVyaW9kIGNhbiBuZXZlciBuYW1lIGFcbi8vIGRpZmZlcmVudCBkYXkgdGhhbiB0aGUgbnVtYmVycyB1bmRlciBpdCB3ZXJlIGZpbHRlcmVkIGJ5LiBSZXR1cm5zIG51bGwgd2hlblxuLy8gdGhlcmUgaXMgbm8gYm91bmRhcnk7IHRoZSBjYWxsZXIgc3VwcGxpZXMgaXRzIG93biBwbGFjZWhvbGRlci5cbi8vXG4vLyBUaGUgcGFyc2UgaGFzIHRvIGJlIHBhcnNlSVNPLCBub3QgYG5ldyBEYXRlYDogYG5ldyBEYXRlKCcyMDI2LTA1LTAxJylgIGlzIFVUQ1xuLy8gbWlkbmlnaHQsIHNvIGZvcm1hdHRpbmcgaXQgYW55d2hlcmUgd2VzdCBvZiBVVEMgcHJpbnRzIEFwciAzMC4gcGFyc2VJU08gcmVhZHNcbi8vIGEgYmFyZSBZLU0tRCBhcyBMT0NBTCBtaWRuaWdodCwgd2hpY2ggbm8gb2Zmc2V0IGNhbiBzaGlmdC5cbi8vXG4vLyBUaGUgZGF5IGlzIHdyaXR0ZW4gaW4gdGhlIHJlcG9ydCdzIGxvY2FsZSwgYXMgaXRzIGRhdGUgY2VsbHMgYXJlOiAnSmFuIDUsXG4vLyAyMDI2JyBpbiBlbi1VUywgJzUgamFudi4gMjAyNicgaW4gZnItQ0EuXG5leHBvcnQgZnVuY3Rpb24gZGF0ZUJvdW5kTGFiZWwodmFsdWU6IERhdGUgfCBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkLCBsb2NhbGU6IFJlcG9ydExvY2FsZVRhZyk6IHN0cmluZyB8IG51bGwge1xuICBjb25zdCBib3VuZCA9IGRhdGVCb3VuZFN0cmluZyh2YWx1ZSk7XG5cbiAgaWYgKCFib3VuZCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgZGF0ZSA9IHBhcnNlSVNPKGJvdW5kKTtcblxuICByZXR1cm4gTnVtYmVyLmlzTmFOKGRhdGUuZ2V0VGltZSgpKSA/IFN0cmluZyh2YWx1ZSkgOiBmb3JtYXRMb2NhbERhdGUoZGF0ZSwgbG9jYWxlLCBEQVlfU0hPUlQpO1xufVxuXG5cbi8vIEEgc3RvcmVkIHl5eXktTU0tZGQgYm91bmRhcnkgYXMgYSBsb2NhbCBEYXRlIGZvciBhIGRhdGUgcGlja2VyLCBvciBudWxsLlxuLy8gcGFyc2VJU08gcmVhZHMgYSBiYXJlIFktTS1EIGFzIExPQ0FMIG1pZG5pZ2h0LCBzbyB0aGUgcGlja2VyIHNob3dzIHRoZSBkYXlcbi8vIHRoYXQgd2FzIHN0b3JlZCwgd2hhdGV2ZXIgdGhlIGJyb3dzZXIncyB6b25lLlxuZXhwb3J0IGZ1bmN0aW9uIGRhdGVGcm9tQm91bmQodmFsdWU6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQpOiBEYXRlIHwgbnVsbCB7XG4gIGlmICghdmFsdWUpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGRhdGUgPSBwYXJzZUlTTyh2YWx1ZS5zbGljZSgwLCAxMCkpO1xuXG4gIHJldHVybiBOdW1iZXIuaXNOYU4oZGF0ZS5nZXRUaW1lKCkpID8gbnVsbCA6IGRhdGU7XG59XG5cblxuLy8gQSBwaWNrZWQgRGF0ZSBhcyBhIHl5eXktTU0tZGQgYm91bmRhcnkgZm9yIHN0b3JhZ2UsIG9yIG51bGwuIFVzZXMgdGhlIGxvY2FsXG4vLyBjYWxlbmRhciBkYXkgKGZvcm1hdCwgbm90IHRvSVNPU3RyaW5nKSBzbyB0aGUgYm91bmRhcnkgaXMgdGhlIGRheSB0aGF0IHdhc1xuLy8gcGlja2VkLCByZWdhcmRsZXNzIG9mIHRoZSBicm93c2VyJ3Mgem9uZS5cbmV4cG9ydCBmdW5jdGlvbiBkYXRlVG9Cb3VuZCh2YWx1ZTogRGF0ZSB8IG51bGwgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCBudWxsIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgRGF0ZSAmJiAhTnVtYmVyLmlzTmFOKHZhbHVlLmdldFRpbWUoKSlcbiAgICA/IGZvcm1hdCh2YWx1ZSwgJ3l5eXktTU0tZGQnKVxuICAgIDogbnVsbDtcbn1cblxuXG4vLyBBIHJlbGF0aXZlIGRhdGUtcmFuZ2UgcHJlc2V0IGtleSBhcyBhIHNlbnRlbmNlLWNhc2UgbGFiZWwsIGRlcml2ZWQgZnJvbSB0aGVcbi8vIGNhbWVsQ2FzZSBrZXkgaXRzZWxmICgnbGFzdDEyTW9udGhzJyByZWFkcyAnTGFzdCAxMiBtb250aHMnLCAndGhpc1dlZWsnXG4vLyByZWFkcyAnVGhpcyB3ZWVrJyksIHNvIG5vIGxpc3Qgb2YgcHJlc2V0cyBpcyBtaXJyb3JlZCBoZXJlIGFuZCBhIGtleSB0aGVcbi8vIHNlcnZlciBhZGRzIGxhdGVyIHN0aWxsIHJlYWRzIHNlbnNpYmx5LlxuZXhwb3J0IGZ1bmN0aW9uIHJlbGF0aXZlTGFiZWwocmVsYXRpdmU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHdvcmRzID0gcmVsYXRpdmVcbiAgICAucmVwbGFjZSgvKFthLXpdKShbQS1aMC05XSkvZywgJyQxICQyJylcbiAgICAucmVwbGFjZSgvKFxcZCkoW0EtWl0pL2csICckMSAkMicpXG4gICAgLnRvTG93ZXJDYXNlKCk7XG5cbiAgcmV0dXJuIHdvcmRzLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgd29yZHMuc2xpY2UoMSk7XG59XG5cblxuLy8gTWFwcyBhIHJlcG9ydCBmaWx0ZXIgR1JPVVAgdG8gYW4gZnMtZmlsdGVyIGNvbmZpZyBpdGVtLCBhbmQgcmVhZHMgZnMtZmlsdGVyXG4vLyBxdWVyeSB2YWx1ZXMgYmFjayBpbnRvIHBlci1ncm91cCBGaWx0ZXJHcm91cFZhbHVlcy4gU2hhcmVkIGJ5IHRoZSByZXBvcnQtYmFyXG4vLyBmcy1maWx0ZXIgYW5kIHRoZSBwZXItY29tcG9uZW50IGZzLWZpbHRlciBzbyBib3RoIHJlbmRlciB0aHJvdWdoIHRoZSBzYW1lXG4vLyBsaWJyYXJ5IGFuZCB3cml0ZSBpbnRvIFJlcG9ydEZpbHRlclN0YXRlU2VydmljZSBpZGVudGljYWxseS4gSXRlbXMgYXJlIG5hbWVkXG4vLyBgZzxncm91cElkPmAgc28gdGhlIHF1ZXJ5IGtleXMgbWFwIHN0cmFpZ2h0IGJhY2sgdG8gdGhlIGdyb3VwLlxuXG4vLyBUaGUgcHJlZml4IG9mIGEgZ3JvdXAncyBpdGVtIG5hbWUsIGFuZCBvZiBpdHMga2V5IGluIHRoZSByZXBvcnQgVVJMLlxuZXhwb3J0IGNvbnN0IEdST1VQX1BBUkFNX1BSRUZJWCA9ICdnJztcblxuLy8gVGhlIHF1ZXJ5IGtleSBmcy1maWx0ZXIgdXNlcyBmb3IgYSBncm91cCdzIGl0ZW0ocyksIGFuZCB0aGUgcmVwb3J0IFVSTCdzIGtleVxuLy8gZm9yIHRoZSBncm91cCdzIHZhbHVlIChyZXBvcnQtdXJsLXN0YXRlLnRzKS4gT25lIG5hbWluZyBmb3IgYm90aC5cbmV4cG9ydCBmdW5jdGlvbiBncm91cEl0ZW1OYW1lKGdyb3VwOiBQaWNrPFJlcG9ydEZpbHRlckdyb3VwLCAnaWQnPik6IHN0cmluZyB7XG4gIHJldHVybiBgJHtHUk9VUF9QQVJBTV9QUkVGSVh9JHtncm91cC5pZH1gO1xufVxuXG4vLyBUaGUgcXVlcnkga2V5IGZvciB0aGUgcmVwb3J0J3MgZ3JvdXAtYnkgY29udHJvbC4gRml4ZWQgcmF0aGVyIHRoYW4gZGVyaXZlZFxuLy8gZnJvbSBhbiBpZCBiZWNhdXNlIGEgcmVwb3J0IGhhcyBleGFjdGx5IG9uZSDigJQgYW5kIGl0IGlzIE5PVCBhIGZpbHRlciBncm91cCxcbi8vIHNvIGl0IGlzIHJlYWQgc3RyYWlnaHQgb2ZmIHRoZSBjaGFuZ2UgcXVlcnkgaW5zdGVhZCBvZiB0aHJvdWdoXG4vLyBncm91cFZhbHVlc0Zyb21RdWVyeS4gSXQgaXMgYWxzbyB0aGUgcmVwb3J0IFVSTCdzIGtleSBmb3IgdGhlIGdyYWluXG4vLyAocmVwb3J0LXVybC1zdGF0ZS50cykuIFRoZSBncmFpbiB0cmF2ZWxzIHRvIHRoZSBzZXJ2ZXIgYXMgdGhlIGRhdGFcbi8vIHJlcXVlc3QncyBgc3RhdGUuZnJlcXVlbmN5YC5cbmV4cG9ydCBjb25zdCBHUk9VUF9CWV9JVEVNID0gJ2dyb3VwQnknO1xuXG4vLyBBIHNlbGVjdCBncm91cCdzIGRpc3RpbmN0IG9wdGlvbnMsIGFzIHsgbmFtZSwgdmFsdWUgfSBwYWlycy4gVGhlIHNlcnZlciBzZW5kc1xuLy8geyB2YWx1ZSwgbGFiZWwgfTogdGhlIHZhbHVlIGlzIHdoYXQgdGhlIGZpbHRlciBtYXRjaGVzIG9uIChhbiBlbnRpdHkncyBzdGFibGVcbi8vIGlkKSBhbmQgdGhlIGxhYmVsIGlzIHdoYXQgdGhlIHZpZXdlciByZWFkcyDigJQgc28gYSByZW5hbWVkIGVudGl0eSBrZWVwcyBpdHMgaWRcbi8vIGFuZCBzaW1wbHkgc2hvd3MgaXRzIG5ldyBuYW1lIGhlcmUuIE9wdGlvbnMgY29tZSBmcm9tIHRoZSBmaXJzdCBtZW1iZXIgZmlsdGVyXG4vLyB0aGF0IGRlY2xhcmVzIHRoZW0g4oCUIG1lbWJlcnMgYXJlIHRoZSBzYW1lIGRhdGEgcG9pbnQsIHNvIGFueSBtZW1iZXIncyBsaXN0XG4vLyBzZXJ2ZXMgdGhlIGdyb3VwLiBUaGUgbGlzdCBpcyBmZXRjaGVkIG9uY2UgKHRoZSBzZXJ2ZXIgY2FwcyBpdCkgYW5kIHJlcGxheWVkXG4vLyAoc2hhcmVSZXBsYXkpLCBzbyByZXBlYXRlZCByZWFkcyBuZXZlciByZWZldGNoLiBTaGFyZWQgYnkgdGhlIHJlcG9ydC1iYXJcbi8vIHNlbGVjdCBjb250cm9sIGFuZCB0aGUgcmVwb3J0LXNldHRpbmdzIGRlZmF1bHQgcGlja2VyIHNvIHRoZSB0d28gbmV2ZXIgZHJpZnQuXG4vLyBSZXR1cm5zIGFuIGVtcHR5IGxpc3Qgd2hlbiBubyBtZW1iZXIgcHJvdmlkZXMgb3B0aW9ucy5cbmV4cG9ydCBmdW5jdGlvbiBsb2FkR3JvdXBPcHRpb25zKFxuICBncm91cDogUmVwb3J0RmlsdGVyR3JvdXAsXG4gIHJlcG9ydERhdGE6IFJlcG9ydERhdGEsXG4gIHJlcG9ydElkOiBudW1iZXIsXG4pOiBPYnNlcnZhYmxlPHsgbmFtZTogc3RyaW5nOyB2YWx1ZTogdW5rbm93biB9W10+IHtcbiAgY29uc3Qgb3B0aW9uRmlsdGVyID0gKGdyb3VwLmZpbHRlcnMgPz8gW10pLmZpbmQoKG1lbWJlcikgPT4gbWVtYmVyLmhhc09wdGlvbnMpO1xuICBpZiAoIW9wdGlvbkZpbHRlcikge1xuICAgIHJldHVybiBvZihbXSk7XG4gIH1cblxuICByZXR1cm4gcmVwb3J0RGF0YS5maWx0ZXJPcHRpb25zKHJlcG9ydElkLCBvcHRpb25GaWx0ZXIuaWQpXG4gICAgLnBpcGUoXG4gICAgICBtYXAoKG9wdGlvbnM6IFJlcG9ydEZpbHRlck9wdGlvbltdKSA9PiAob3B0aW9ucyA/PyBbXSlcbiAgICAgICAgLm1hcCgob3B0aW9uKSA9PiAoeyBuYW1lOiBvcHRpb24ubGFiZWwsIHZhbHVlOiBvcHRpb24udmFsdWUgfSkpKSxcbiAgICAgIHNoYXJlUmVwbGF5KHsgYnVmZmVyU2l6ZTogMSwgcmVmQ291bnQ6IGZhbHNlIH0pLFxuICAgICk7XG59XG5cbi8vIFN0b3JlZCBmaWx0ZXIgdmFsdWVzIChpZHMpIHBhaXJlZCBiYWNrIHdpdGggdGhlIGxhYmVscyB0byBzaG93IGZvciB0aGVtLlxuLy8gQSBzYXZlZCBkZWZhdWx0IGhvbGRzIG9ubHkgdmFsdWVzLCBzbyB0aGUgbmFtZXMgaGF2ZSB0byBiZSByZWFkIGJhY2sgb2ZmIHRoZVxuLy8gb3B0aW9uIGxpc3Qg4oCUIHRoYXQgaW5kaXJlY3Rpb24gaXMgZXhhY3RseSB3aGF0IHN1cnZpdmVzIGEgcmVuYW1lLiBBIHZhbHVlIHdpdGhcbi8vIG5vIG1hdGNoaW5nIG9wdGlvbiAoaXRzIGVudGl0eSB3YXMgZGVsZXRlZCwgc28gaXQgaXMgbm8gbG9uZ2VyIGxpc3RlZCkgZmFsbHNcbi8vIGJhY2sgdG8gc2hvd2luZyB0aGUgcmF3IHZhbHVlIHJhdGhlciB0aGFuIGRyb3BwaW5nIHRoZSBjaGlwLCB3aGljaCB3b3VsZFxuLy8gc2lsZW50bHkgd2lkZW4gdGhlIGZpbHRlci5cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlT3B0aW9uVmFsdWVzKFxuICBvcHRpb25zJDogT2JzZXJ2YWJsZTx7IG5hbWU6IHN0cmluZzsgdmFsdWU6IHVua25vd24gfVtdPixcbiAgdmFsdWVzOiB1bmtub3duW10sXG4pOiBPYnNlcnZhYmxlPHsgbmFtZTogc3RyaW5nOyB2YWx1ZTogdW5rbm93biB9W10+IHtcbiAgcmV0dXJuIG9wdGlvbnMkLnBpcGUobWFwKChvcHRpb25zKSA9PiB2YWx1ZXMubWFwKCh2YWx1ZSkgPT4ge1xuICAgIGNvbnN0IG9wdGlvbiA9IG9wdGlvbnMuZmluZCgoY2FuZGlkYXRlKSA9PiBTdHJpbmcoY2FuZGlkYXRlLnZhbHVlKSA9PT0gU3RyaW5nKHZhbHVlKSk7XG5cbiAgICByZXR1cm4geyBuYW1lOiBvcHRpb24/Lm5hbWUgPz8gU3RyaW5nKHZhbHVlKSwgdmFsdWUgfTtcbiAgfSkpKTtcbn1cblxuLy8gQ2FzZS1pbnNlbnNpdGl2ZSBuYW1lIGZpbHRlciBhcHBsaWVkIHRvIGEgbG9hZGVkIG9wdGlvbiBsaXN0IOKAlCB0aGUgdHlwZWRcbi8vIGtleXdvcmQgaGFzIHRvIGJlIG1hdGNoZWQgaGVyZSBiZWNhdXNlIGZzLWF1dG9jb21wbGV0ZSByZW5kZXJzIHdoYXQgd2UgcmV0dXJuXG4vLyB2ZXJiYXRpbS5cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaE9wdGlvbnMoXG4gIG9wdGlvbnMkOiBPYnNlcnZhYmxlPHsgbmFtZTogc3RyaW5nOyB2YWx1ZTogdW5rbm93biB9W10+LFxuICBrZXl3b3JkPzogc3RyaW5nLFxuKTogT2JzZXJ2YWJsZTx7IG5hbWU6IHN0cmluZzsgdmFsdWU6IHVua25vd24gfVtdPiB7XG4gIGNvbnN0IHRlcm0gPSAoa2V5d29yZCA/PyAnJykudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG5cbiAgcmV0dXJuIG9wdGlvbnMkLnBpcGUobWFwKChvcHRpb25zKSA9PiB0ZXJtXG4gICAgPyBvcHRpb25zLmZpbHRlcigob3B0aW9uKSA9PiBvcHRpb24ubmFtZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHRlcm0pKVxuICAgIDogb3B0aW9ucykpO1xufVxuXG4vLyBCdWlsZCB0aGUgZnMtZmlsdGVyIGNvbmZpZyBpdGVtIGZvciBhIGdyb3VwLCBzZWVkaW5nIGl0cyBkZWZhdWx0IGZyb20gdGhlXG4vLyBjdXJyZW50IHNlc3Npb24gdmFsdWUgc28gYXV0aG9yZWQvcmVsYXRpdmUgZGVmYXVsdHMgc2hvdyBzZWxlY3RlZCBvbiBvcGVuLlxuZXhwb3J0IGZ1bmN0aW9uIGZpbHRlckl0ZW1Gb3JHcm91cChcbiAgZ3JvdXA6IFJlcG9ydEZpbHRlckdyb3VwLFxuICByZXBvcnREYXRhOiBSZXBvcnREYXRhLFxuICByZXBvcnRJZDogbnVtYmVyLFxuICBpbml0aWFsPzogRmlsdGVyR3JvdXBWYWx1ZSxcbik6IElGaWx0ZXJDb25maWdJdGVtIHtcbiAgY29uc3QgbmFtZSA9IGdyb3VwSXRlbU5hbWUoZ3JvdXApO1xuICBjb25zdCBsYWJlbCA9IGdyb3VwLmxhYmVsIHx8IGdyb3VwLmZpbHRlcnM/LlswXT8uZmlsdGVyQ29sdW1uIHx8ICcnO1xuXG4gIHN3aXRjaCAoZ3JvdXAudHlwZSkge1xuICAgIGNhc2UgJ2RhdGVSYW5nZSc6XG4gICAgICByZXR1cm4ge1xuICAgICAgICBuYW1lLFxuICAgICAgICB0eXBlOiBJdGVtVHlwZS5EYXRlUmFuZ2UsXG4gICAgICAgIGxhYmVsOiB7IGZyb206IGAke2xhYmVsfSBGcm9tYCwgdG86IGAke2xhYmVsfSBUb2AgfSxcbiAgICAgICAgZGVmYXVsdDogKGluaXRpYWw/LnN0YXJ0IHx8IGluaXRpYWw/LmVuZClcbiAgICAgICAgICA/IHsgZnJvbTogaW5pdGlhbC5zdGFydCA/PyB1bmRlZmluZWQsIHRvOiBpbml0aWFsLmVuZCA/PyB1bmRlZmluZWQgfVxuICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgfTtcblxuICAgIGNhc2UgJ3NlbGVjdCc6IHtcbiAgICAgIC8vIE9uZSBzaGFyZWQsIHJlcGxheWVkIG9wdGlvbiBzdHJlYW0gc28gdHlwaW5nIG5ldmVyIHJlZmV0Y2hlcy5cbiAgICAgIGNvbnN0IG9wdGlvbnMkID0gbG9hZEdyb3VwT3B0aW9ucyhncm91cCwgcmVwb3J0RGF0YSwgcmVwb3J0SWQpO1xuICAgICAgY29uc3QgdmFsdWVzID0gaW5pdGlhbD8udmFsdWVzO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBuYW1lLFxuICAgICAgICB0eXBlOiBJdGVtVHlwZS5BdXRvQ29tcGxldGVDaGlwcyxcbiAgICAgICAgbGFiZWwsXG4gICAgICAgIGZldGNoT25Gb2N1czogdHJ1ZSxcbiAgICAgICAgdmFsdWVzOiAoa2V5d29yZD86IHN0cmluZykgPT4gbWF0Y2hPcHRpb25zKG9wdGlvbnMkLCBrZXl3b3JkKSxcbiAgICAgICAgLy8gU3RvcmVkIHZhbHVlcyBhcmUgaWRzLCBzbyB0aGUgY2hpcHMgY2FuIG9ubHkgYmUgbmFtZWQgb25jZSB0aGUgb3B0aW9uXG4gICAgICAgIC8vIGxpc3QgaGFzIGxvYWRlZCDigJQgaGVuY2UgdGhlIG9ic2VydmFibGUgZm9ybSBvZiBgZGVmYXVsdGAuXG4gICAgICAgIGRlZmF1bHQ6IHZhbHVlcz8ubGVuZ3RoXG4gICAgICAgICAgPyAoKSA9PiByZXNvbHZlT3B0aW9uVmFsdWVzKG9wdGlvbnMkLCB2YWx1ZXMpXG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNhc2UgJ2tleXdvcmQnOlxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4ge1xuICAgICAgICBuYW1lLFxuICAgICAgICB0eXBlOiBJdGVtVHlwZS5LZXl3b3JkLFxuICAgICAgICBsYWJlbCxcbiAgICAgICAgZGVmYXVsdDogaW5pdGlhbD8udmFsdWUsXG4gICAgICB9O1xuICB9XG59XG5cbi8vIFRoZSBxdWVyeSBrZXkgb2YgYSBsaXN0J3Mgc2VhcmNoIGJveCBpbiBpdHMgY29tcG9uZW50IGhlYWRlci4gRml4ZWQgcmF0aGVyXG4vLyB0aGFuIGRlcml2ZWQgZnJvbSBhbiBpZCBiZWNhdXNlIGEgaGVhZGVyIGhvbGRzIGF0IG1vc3Qgb25lLCBhbmQgaXQgaXMgTk9UIGFcbi8vIGZpbHRlciBncm91cDogaXRzIHRleHQgbmFycm93cyB0aGF0IGxpc3QgYWxvbmUsIHNvIGl0IGlzIHJlYWQgc3RyYWlnaHQgb2ZmXG4vLyB0aGUgY2hhbmdlIHF1ZXJ5IGFuZCB0cmF2ZWxzIGFzIHRoZSBsaXN0J3Mgb3duIGBzdGF0ZS5zZWFyY2hgLlxuZXhwb3J0IGNvbnN0IExJU1RfU0VBUkNIX0lURU0gPSAnbGlzdFNlYXJjaCc7XG5cbi8vIFRoZSBsb25nZXN0IHNlYXJjaCB0aGUgc2VydmVyIGFwcGxpZXMgKFJlcG9ydFF1ZXJ5UnVubmVyOjpNQVhfU0VBUkNIX0xFTkdUSCkuXG4vLyBUaGUgdmlld2VyIGN1dHMgdGhlIHRleHQgdG8gaXQgdG9vLCBzbyB0aGUgVVJMLCB0aGUgcmVxdWVzdCBhbmQgdGhlIGV4cG9ydFxuLy8gdGl0bGUgYWxsIGNhcnJ5IHRoZSB0ZXh0IHRoYXQgd2FzIGFjdHVhbGx5IHNlYXJjaGVkLlxuZXhwb3J0IGNvbnN0IExJU1RfU0VBUkNIX01BWF9MRU5HVEggPSAxMDA7XG5cbi8vIFRoZSBmcy1maWx0ZXIgY29uZmlnIGl0ZW0gZm9yIGEgbGlzdCdzIHNlYXJjaCBib3gsIHNlZWRlZCB3aXRoIHRoZSB0ZXh0IHRoZVxuLy8gdmlld2VyIGxhc3Qgc2VhcmNoZWQuIGZzLWZpbHRlciBzaG93cyBvbmUgc2VhcmNoIGJveCBwZXIgYmFyIChpdHMgbGFzdFxuLy8ga2V5d29yZCBpdGVtKSwgc28gdGhlIGNhbGxlciBhZGRzIHRoaXMgb25seSB0byBhIGhlYWRlciB3aXRoIG5vIGtleXdvcmRcbi8vIGdyb3VwIG9mIGl0cyBvd24uXG5leHBvcnQgZnVuY3Rpb24gbGlzdFNlYXJjaEl0ZW0odmFsdWU6IHN0cmluZyB8IG51bGwpOiBJRmlsdGVyQ29uZmlnSXRlbSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogSXRlbVR5cGUuS2V5d29yZCxcbiAgICBuYW1lOiBMSVNUX1NFQVJDSF9JVEVNLFxuICAgIGxhYmVsOiAnU2VhcmNoJyxcbiAgICBkZWZhdWx0OiB2YWx1ZSA/PyB1bmRlZmluZWQsXG4gIH07XG59XG5cbi8vIFdoZXRoZXIgdGhlIHJlcG9ydCBoYXMgYSBjaGFydCB0aGUgZ3JvdXAtYnkgY29udHJvbCBjYW4gcmUtYnVja2V0LiBBIHRpbWVcbi8vIHgtYXhpcyBpcyB0aGUgd2hvbGUgcXVhbGlmaWNhdGlvbjogdGhlIGNvbnRyb2wgY2hhbmdlcyB0aGUgZ3JhaW4gb2YgdGhhdFxuLy8gYXhpcywgYW5kIGEgY2F0ZWdvcnkgYXhpcyBoYXMgbm8gZ3JhaW4gdG8gY2hhbmdlLlxuZXhwb3J0IGZ1bmN0aW9uIGhhc1RpbWVTZXJpZXNDaGFydChyZXBvcnQ6IFJlcG9ydCB8IG51bGwpOiBib29sZWFuIHtcbiAgcmV0dXJuIChyZXBvcnQ/LnBhZ2VzID8/IFtdKS5zb21lKChwYWdlKSA9PiAocGFnZS5jb21wb25lbnRzID8/IFtdKS5zb21lKChjb21wb25lbnQpID0+XG4gICAgY29tcG9uZW50LnR5cGUgPT09ICdjaGFydCcgJiYgY29tcG9uZW50LmNvbmZpZz8ueEF4aXM/LmtpbmQgPT09ICd0aW1lJykpO1xufVxuXG4vLyBUaGUgZ3JhaW5zIHRoZSByZXBvcnQncyBncm91cC1ieSBjb250cm9sIG9mZmVycywgbmFtZWQgZm9yIHRoZSB2aWV3ZXIuIFdISUNIXG4vLyBvZiB0aGVtIGNvbWVzIGZyb20gdGhlIHJlcG9ydDsgaG93IHRoZXkgcmVhZCBjb21lcyBmcm9tIEdSQU5VTEFSSVRZX09QVElPTlMuXG4vLyBBbiBlbXB0eSBzdG9yZWQgbGlzdCBtZWFucyBldmVyeSBncmFpbiDigJQgdGhlIHNhbWUgcnVsZSB0aGUgYmFja2VuZCBhcHBsaWVzLlxuZnVuY3Rpb24gZ3JvdXBCeU9wdGlvbnMocmVwb3J0OiBSZXBvcnQpOiB7IHZhbHVlOiBDaGFydEdyYW51bGFyaXR5OyBuYW1lOiBzdHJpbmcgfVtdIHtcbiAgY29uc3QgZ3JhbnVsYXJpdGllcyA9IHJlcG9ydC5jb25maWc/Lmdyb3VwQnk/LmdyYW51bGFyaXRpZXMgPz8gW107XG5cbiAgcmV0dXJuIGdyYW51bGFyaXRpZXMubGVuZ3RoXG4gICAgPyBHUkFOVUxBUklUWV9PUFRJT05TLmZpbHRlcigob3B0aW9uKSA9PiBncmFudWxhcml0aWVzLmluY2x1ZGVzKG9wdGlvbi52YWx1ZSkpXG4gICAgOiBHUkFOVUxBUklUWV9PUFRJT05TO1xufVxuXG4vLyBXaGV0aGVyIGEgZ3JhaW4gaXMgb25lIHRoZSByZXBvcnQncyBjb250cm9sIHN0aWxsIG9mZmVycy4gQSBncmFpbiBpdCBkb2Vzbid0XG4vLyBjYW5ub3Qgc3RheSBpbiBlZmZlY3Q6IHRoZSBhZ2VudCBjYW4gbmFycm93IHRoZSBsaXN0IGF0IGFueSB0aW1lLCBhbmQgYSBjaGFydFxuLy8gbGVmdCBidWNrZXRpbmcgYXQgYSBkcm9wcGVkIGdyYWluIGlzIG9uZSB0aGUgdmlld2VyIGNhbiBuZWl0aGVyIHNlZSBub3IgY2hhbmdlLlxuZXhwb3J0IGZ1bmN0aW9uIGlzR3JhbnVsYXJpdHlPZmZlcmVkKHJlcG9ydDogUmVwb3J0LCBncmFudWxhcml0eTogQ2hhcnRHcmFudWxhcml0eSB8IG51bGwpOiBib29sZWFuIHtcbiAgcmV0dXJuICFncmFudWxhcml0eSB8fCBncm91cEJ5T3B0aW9ucyhyZXBvcnQpLnNvbWUoKG9wdGlvbikgPT4gb3B0aW9uLnZhbHVlID09PSBncmFudWxhcml0eSk7XG59XG5cbi8vIFRoZSBmcy1maWx0ZXIgY29uZmlnIGl0ZW0gZm9yIHRoZSByZXBvcnQncyBncm91cC1ieSBjb250cm9sLCBvciBudWxsIHdoZW4gdGhlXG4vLyByZXBvcnQgaGFzIG5vbmUgdG8gc2hvdy5cbi8vXG4vLyBJdCBsZWFkcyB0aGUgc2FtZSBiYXIgdGhlIGZpbHRlcnMgcmVuZGVyIGluLCBidXQgaXQgaXMgTk9UIG9uZTogYSBmaWx0ZXJcbi8vIG5hcnJvd3MgV0hJQ0ggcm93cyBhcmUgY291bnRlZCwgdGhpcyBjaGFuZ2VzIGhvdyB0aGUgc3Vydml2aW5nIHJvd3MgYXJlXG4vLyBCVUNLRVRFRCDigJQgYW5kIGl0IGNvbWVzIGZpcnN0IGJlY2F1c2UgdGhlIGdyYWluIGlzIHdoYXQgYSB2aWV3ZXIgc2V0dGxlc1xuLy8gYmVmb3JlIGRlY2lkaW5nIHdoaWNoIHJvd3MgdGhleSB3YW50LlxuLy8gUGlja2luZyBhIGdyYWluIHNldHMgYSBzZXNzaW9uLXdpZGUgb3ZlcnJpZGUgdGhhdCByaWRlcyBhbG9uZyBpbiBlYWNoIGNoYXJ0J3Ncbi8vIGRhdGEgcmVxdWVzdCwgc28gdGhlIGNoYXJ0cyB0aGVtc2VsdmVzIGFyZSBuZXZlciByZXdyaXR0ZW4uXG5leHBvcnQgZnVuY3Rpb24gZ3JvdXBCeUZpbHRlckl0ZW0oXG4gIHJlcG9ydDogUmVwb3J0LFxuICBpbml0aWFsPzogQ2hhcnRHcmFudWxhcml0eSB8IG51bGwsXG4pOiBJRmlsdGVyQ29uZmlnSXRlbSB8IG51bGwge1xuICBjb25zdCBncm91cEJ5ID0gcmVwb3J0LmNvbmZpZz8uZ3JvdXBCeTtcblxuICAvLyBPbmx5IGFuIEVYUExJQ0lUIGZhbHNlIGhpZGVzIHRoZSBjb250cm9sLiBBbiBhYnNlbnQgYmxvY2sgbWVhbnMgYSByZXBvcnRcbiAgLy8gc2VydmVkIGJ5IGEgYnVpbGQgdGhhdCBwcmVkYXRlcyB0aGUgY29udHJvbCBiZWluZyBzdG9yZWQsIGFuZCBldmVyeSBvbmUgb2ZcbiAgLy8gdGhvc2UgaGFkIG9uZSDigJQgdGhlIGJhY2tlbmQgcmVzb2x2ZXMgaXQgdGhlIHNhbWUgd2F5IChSZXBvcnRHcm91cEJ5KS5cbiAgaWYgKGdyb3VwQnk/LmVuYWJsZWQgPT09IGZhbHNlIHx8ICFoYXNUaW1lU2VyaWVzQ2hhcnQocmVwb3J0KSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgdmFsdWVzID0gZ3JvdXBCeU9wdGlvbnMocmVwb3J0KTtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6IEdST1VQX0JZX0lURU0sXG4gICAgdHlwZTogSXRlbVR5cGUuU2VsZWN0LFxuICAgIGxhYmVsOiBncm91cEJ5Py5sYWJlbCB8fCAnR3JvdXAgQnknLFxuICAgIG11bHRpcGxlOiBmYWxzZSxcbiAgICB2YWx1ZXM6ICgpID0+IHZhbHVlcyxcbiAgICBkZWZhdWx0OiBpc0dyYW51bGFyaXR5T2ZmZXJlZChyZXBvcnQsIGluaXRpYWwgPz8gbnVsbCkgPyAoaW5pdGlhbCA/PyB1bmRlZmluZWQpIDogdW5kZWZpbmVkLFxuICB9O1xufVxuXG4vLyBUaGUgZ3JvdXAtYnkgY29udHJvbCdzIGNvbnRyaWJ1dGlvbiB0byB0aGUgdG9vbGJhcidzIGZzLWZpbHRlciBrZXkuIGZzLWZpbHRlclxuLy8gcmVhZHMgaXRzIGNvbmZpZyBvbmNlIGF0IGluaXQsIGFuZCB0aGUgYWdlbnQgY2FuIGNoYW5nZSB0aGUgY29udHJvbCdzIGxhYmVsXG4vLyBvciB0aGUgZ3JhaW5zIGl0IG9mZmVycyDigJQgd2l0aG91dCB0aG9zZSBpbiB0aGUga2V5IHRoZSBiYXIga2VlcHMgcmVuZGVyaW5nXG4vLyB0aGUgY29udHJvbCBpdCB3YXMgY3JlYXRlZCB3aXRoIHVudGlsIGEgZnVsbCBwYWdlIHJlbG9hZC5cbmV4cG9ydCBmdW5jdGlvbiBncm91cEJ5U2lnbmF0dXJlKHJlcG9ydDogUmVwb3J0IHwgbnVsbCk6IHN0cmluZyB7XG4gIGlmICghcmVwb3J0IHx8ICFncm91cEJ5RmlsdGVySXRlbShyZXBvcnQpKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgY29uc3QgZ3JvdXBCeSA9IHJlcG9ydC5jb25maWc/Lmdyb3VwQnk7XG5cbiAgcmV0dXJuIFsnZ3JvdXBCeScsIGdyb3VwQnk/LmxhYmVsID8/ICcnLCAoZ3JvdXBCeT8uZ3JhbnVsYXJpdGllcyA/PyBbXSkuam9pbignLCcpXS5qb2luKCc6Jyk7XG59XG5cbi8vIFJlYWQgYW4gZnMtZmlsdGVyIGNoYW5nZSBxdWVyeSBpbnRvIHBlci1ncm91cCB2YWx1ZXMuIFJldHVybnMgb25lIGVudHJ5IHBlclxuLy8gZ3JvdXAgd2l0aCB0aGUgdmFsdWUgdG8gc3RvcmUgKG9yIG51bGwgdG8gY2xlYXIpIOKAlCBjYWxsZXJzIGZlZWQgdGhlc2UgdG9cbi8vIFJlcG9ydEZpbHRlclN0YXRlU2VydmljZS5zZXRWYWx1ZS5cbmV4cG9ydCBmdW5jdGlvbiBncm91cFZhbHVlc0Zyb21RdWVyeShcbiAgcXVlcnk6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gIGdyb3VwczogUmVwb3J0RmlsdGVyR3JvdXBbXSxcbik6IHsgZ3JvdXBJZDogbnVtYmVyOyB2YWx1ZTogRmlsdGVyR3JvdXBWYWx1ZSB8IG51bGwgfVtdIHtcbiAgcmV0dXJuIGdyb3Vwcy5tYXAoKGdyb3VwKSA9PiB7XG4gICAgY29uc3QgbmFtZSA9IGdyb3VwSXRlbU5hbWUoZ3JvdXApO1xuXG4gICAgaWYgKGdyb3VwLnR5cGUgPT09ICdkYXRlUmFuZ2UnKSB7XG4gICAgICBjb25zdCBzdGFydCA9IHF1ZXJ5W2Ake25hbWV9RnJvbWBdO1xuICAgICAgY29uc3QgZW5kID0gcXVlcnlbYCR7bmFtZX1Ub2BdO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBncm91cElkOiBncm91cC5pZCxcbiAgICAgICAgdmFsdWU6IChzdGFydCB8fCBlbmQpID8geyBzdGFydDogc3RhcnQgfHwgbnVsbCwgZW5kOiBlbmQgfHwgbnVsbCB9IDogbnVsbCxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKGdyb3VwLnR5cGUgPT09ICdzZWxlY3QnKSB7XG4gICAgICBjb25zdCB2YWx1ZXMgPSBzZWxlY3RRdWVyeVZhbHVlcyhxdWVyeVtuYW1lXSk7XG5cbiAgICAgIHJldHVybiB7IGdyb3VwSWQ6IGdyb3VwLmlkLCB2YWx1ZTogdmFsdWVzLmxlbmd0aCA/IHsgdmFsdWVzIH0gOiBudWxsIH07XG4gICAgfVxuXG4gICAgY29uc3Qga2V5d29yZCA9IFN0cmluZyhxdWVyeVtuYW1lXSA/PyAnJykudHJpbSgpO1xuXG4gICAgcmV0dXJuIHsgZ3JvdXBJZDogZ3JvdXAuaWQsIHZhbHVlOiBrZXl3b3JkID8geyB2YWx1ZToga2V5d29yZCB9IDogbnVsbCB9O1xuICB9KTtcbn1cblxuLy8gZnMtZmlsdGVyJ3MgQXV0b0NvbXBsZXRlQ2hpcHMgc2VyaWFsaXNlcyBhIG11bHRpLXNlbGVjdCBpbnRvIE9ORSBxdWVyeSB2YWx1ZTpcbi8vIHRoZSBzZWxlY3RlZCB2YWx1ZXMgam9pbmVkIGJ5IFwiLFwiIChpdHMgYHF1ZXJ5YCBnZXR0ZXIgZG9lcyBgLm1hcCh2YWx1ZSkuam9pbignLCcpYCkuXG4vLyBTbyBhIDIrIHNlbGVjdGlvbiBhcnJpdmVzIGFzIHRoZSBzdHJpbmcgXCJhLGJcIiwgbm90IGFuIGFycmF5IOKAlCBzcGxpdHRpbmcgb24gXCIsXCJcbi8vIHJldmVyc2VzIHRoYXQgZmFpdGhmdWxseS4gV2l0aG91dCB0aGlzLCBhIG11bHRpLXNlbGVjdCB3YXMgc2VudCBhcyB0aGUgc2luZ2xlXG4vLyB2YWx1ZSBbXCJhLGJcIl0sIHByb2R1Y2luZyBgY29sIElOICgnYSxiJylgIHNlcnZlci1zaWRlLCB3aGljaCBtYXRjaGVzIG5vdGhpbmcuXG5mdW5jdGlvbiBzZWxlY3RRdWVyeVZhbHVlcyhyYXc6IHVua25vd24pOiB1bmtub3duW10ge1xuICBpZiAoQXJyYXkuaXNBcnJheShyYXcpKSB7XG4gICAgcmV0dXJuIHJhdztcbiAgfVxuXG4gIGlmIChyYXcgPT09IG51bGwgfHwgcmF3ID09PSB1bmRlZmluZWQgfHwgcmF3ID09PSAnJykge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIHJldHVybiBTdHJpbmcocmF3KS5zcGxpdCgnLCcpO1xufVxuIl19
553
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LWZpbHRlci1pdGVtcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9yZXBvcnQtZmlsdGVyLWl0ZW1zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBcUIsUUFBUSxFQUFFLGNBQWMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRWpGLE9BQU8sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBRTVDLE9BQU8sRUFBYyxFQUFFLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEMsT0FBTyxFQUFFLEdBQUcsRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUdsRCxPQUFPLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzdFLE9BQU8sRUFBRSxTQUFTLEVBQUUsZUFBZSxFQUFFLG9CQUFvQixFQUFFLE1BQU0sVUFBVSxDQUFDO0FBSTVFLE9BQU8sRUFDK0IsbUJBQW1CLEdBRXhELE1BQU0sK0JBQStCLENBQUM7QUFDdkMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBSXpELDJFQUEyRTtBQUMzRSw0RUFBNEU7QUFDNUUseUVBQXlFO0FBQ3pFLE1BQU0sVUFBVSxlQUFlLENBQUMsS0FBdUM7SUFDckUsSUFBSSxLQUFLLFlBQVksSUFBSSxFQUFFLENBQUM7UUFDMUIsT0FBTyxNQUFNLENBQUMsS0FBSyxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFRCxzRUFBc0U7SUFDdEUsOEJBQThCO0lBQzlCLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQ3hELENBQUM7QUFHRCw4RUFBOEU7QUFDOUUsK0VBQStFO0FBQy9FLDhFQUE4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O0FBQ2pGLGdGQUFnRjtBQUNoRixnRkFBZ0Y7QUFDaEYsU0FBUyxpQkFBaUIsQ0FBQyxHQUFZO0lBQ3JDLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3ZCLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztJQUVELElBQUksR0FBRyxLQUFLLElBQUksSUFBSSxHQUFHLEtBQUssU0FBUyxJQUFJLEdBQUcsS0FBSyxFQUFFLEVBQUUsQ0FBQztRQUNwRCxPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFFRCxPQUFPLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDaEMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IElGaWx0ZXJDb25maWdJdGVtLCBJdGVtVHlwZSwgZ2V0RXhjbHVkZU5hbWUgfSBmcm9tICdAZmlyZXN0aXRjaC9maWx0ZXInO1xuXG5pbXBvcnQgeyBmb3JtYXQsIHBhcnNlSVNPIH0gZnJvbSAnZGF0ZS1mbnMnO1xuXG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwLCBzaGFyZVJlcGxheSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgUmVwb3J0RGF0YSB9IGZyb20gJy4vZGF0YS9yZXBvcnQuZGF0YSc7XG5pbXBvcnQgeyBmaWx0ZXJMaW5lVGV4dCwgbWF0Y2hMaW5lVGV4dCB9IGZyb20gJy4vZXhwb3J0L3JlcG9ydC1maWx0ZXItbGluZXMnO1xuaW1wb3J0IHsgREFZX1NIT1JULCBmb3JtYXRMb2NhbERhdGUsIHJlc29sdmVGb3JtYXRDb250ZXh0IH0gZnJvbSAnLi9mb3JtYXQnO1xuaW1wb3J0IHsgUmVwb3J0RmlsdGVyTWF0Y2ggfSBmcm9tICcuL2ludGVyZmFjZXMvcmVwb3J0LWZpbHRlci1tYXRjaC50eXBlJztcbmltcG9ydCB7IFJlcG9ydEZpbHRlck9wdGlvblBhaXIgfSBmcm9tICcuL2ludGVyZmFjZXMvcmVwb3J0LWZpbHRlci1vcHRpb24tcGFpci5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVwb3J0Vmlld2VyRmVhdHVyZSB9IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQtdmlld2VyLWZlYXR1cmUudHlwZSc7XG5pbXBvcnQge1xuICBDaGFydEdyYW51bGFyaXR5LCBGaWx0ZXJHcm91cFZhbHVlLCBHUkFOVUxBUklUWV9PUFRJT05TLCBSZXBvcnQsIFJlcG9ydEZpbHRlckdyb3VwLCBSZXBvcnRGaWx0ZXJMZXZlbCxcbiAgUmVwb3J0RmlsdGVyT3B0aW9uLCBSZXBvcnRGaWx0ZXJUeXBlLCBSZXBvcnRMb2NhbGVUYWcsXG59IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcbmltcG9ydCB7IG9mZmVyc0V4Y2x1ZGUgfSBmcm9tICcuL3JlcG9ydC12aWV3ZXItZmVhdHVyZXMnO1xuaW1wb3J0IHsgUmVwb3J0RmlsdGVyT3B0aW9uc1NlcnZpY2UgfSBmcm9tICcuL3NlcnZpY2VzL3JlcG9ydC1maWx0ZXItb3B0aW9ucy5zZXJ2aWNlJztcblxuXG4vLyBBIGRhdGUtcmFuZ2UgYm91bmRhcnkgYXMgdGhlIHBpY2tlZCBMT0NBTCBjYWxlbmRhciBkYXkgKG5vIHRpbWUsIG5vIHR6KS5cbi8vIERhdGUtcmFuZ2UgZmlsdGVycyBhcmUgY2FsZW5kYXItZGF5IHNlbWFudGljcywgc28gdGhlIGJvdW5kYXJ5IG11c3QgY2Fycnlcbi8vIG9ubHkgWS1NLUQg4oCUIG5ldmVyIGEgdGltZXpvbmUtYmVhcmluZyBpbnN0YW50IHRoZSBiYWNrZW5kIHdvdWxkIHNoaWZ0LlxuZXhwb3J0IGZ1bmN0aW9uIGRhdGVCb3VuZFN0cmluZyh2YWx1ZTogRGF0ZSB8IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAodmFsdWUgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgcmV0dXJuIGZvcm1hdCh2YWx1ZSwgJ3l5eXktTU0tZGQnKTtcbiAgfVxuXG4gIC8vIEF1dGhvcmVkL3JlbGF0aXZlIGRlZmF1bHRzIGFycml2ZSBhcyBzdHJpbmdzIGFscmVhZHkgaW4gWS1NLUQgZm9ybTtcbiAgLy8ga2VlcCBqdXN0IHRoZSBkYXRlIHBvcnRpb24uXG4gIHJldHVybiB2YWx1ZSA/IFN0cmluZyh2YWx1ZSkuc2xpY2UoMCwgMTApIDogdW5kZWZpbmVkO1xufVxuXG5cbi8vIEEgZGF0ZS1yYW5nZSBib3VuZGFyeSBhcyBpdCBzaG91bGQgUkVBRCBvbiBhIGNvdmVyIHBhZ2Ug4oCUIHRoZSBzYW1lIGNhbGVuZGFyXG4vLyBkYXkgZGF0ZUJvdW5kU3RyaW5nKCkgaGFuZHMgdGhlIHNlcnZlciwgc28gYSBwcmludGVkIHBlcmlvZCBjYW4gbmV2ZXIgbmFtZSBhXG4vLyBkaWZmZXJlbnQgZGF5IHRoYW4gdGhlIG51bWJlcnMgdW5kZXIgaXQgd2VyZSBmaWx0ZXJlZCBieS4gUmV0dXJucyBudWxsIHdoZW5cbi8vIHRoZXJlIGlzIG5vIGJvdW5kYXJ5OyB0aGUgY2FsbGVyIHN1cHBsaWVzIGl0cyBvd24gcGxhY2Vob2xkZXIuXG4vL1xuLy8gVGhlIHBhcnNlIGhhcyB0byBiZSBwYXJzZUlTTywgbm90IGBuZXcgRGF0ZWA6IGBuZXcgRGF0ZSgnMjAyNi0wNS0wMScpYCBpcyBVVENcbi8vIG1pZG5pZ2h0LCBzbyBmb3JtYXR0aW5nIGl0IGFueXdoZXJlIHdlc3Qgb2YgVVRDIHByaW50cyBBcHIgMzAuIHBhcnNlSVNPIHJlYWRzXG4vLyBhIGJhcmUgWS1NLUQgYXMgTE9DQUwgbWlkbmlnaHQsIHdoaWNoIG5vIG9mZnNldCBjYW4gc2hpZnQuXG4vL1xuLy8gVGhlIGRheSBpcyB3cml0dGVuIGluIHRoZSByZXBvcnQncyBsb2NhbGUsIGFzIGl0cyBkYXRlIGNlbGxzIGFyZTogJ0phbiA1LFxuLy8gMjAyNicgaW4gZW4tVVMsICc1IGphbnYuIDIwMjYnIGluIGZyLUNBLlxuZXhwb3J0IGZ1bmN0aW9uIGRhdGVCb3VuZExhYmVsKHZhbHVlOiBEYXRlIHwgc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCwgbG9jYWxlOiBSZXBvcnRMb2NhbGVUYWcpOiBzdHJpbmcgfCBudWxsIHtcbiAgY29uc3QgYm91bmQgPSBkYXRlQm91bmRTdHJpbmcodmFsdWUpO1xuXG4gIGlmICghYm91bmQpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGRhdGUgPSBwYXJzZUlTTyhib3VuZCk7XG5cbiAgcmV0dXJuIE51bWJlci5pc05hTihkYXRlLmdldFRpbWUoKSkgPyBTdHJpbmcodmFsdWUpIDogZm9ybWF0TG9jYWxEYXRlKGRhdGUsIGxvY2FsZSwgREFZX1NIT1JUKTtcbn1cblxuXG4vLyBBIHN0b3JlZCB5eXl5LU1NLWRkIGJvdW5kYXJ5IGFzIGEgbG9jYWwgRGF0ZSBmb3IgYSBkYXRlIHBpY2tlciwgb3IgbnVsbC5cbi8vIHBhcnNlSVNPIHJlYWRzIGEgYmFyZSBZLU0tRCBhcyBMT0NBTCBtaWRuaWdodCwgc28gdGhlIHBpY2tlciBzaG93cyB0aGUgZGF5XG4vLyB0aGF0IHdhcyBzdG9yZWQsIHdoYXRldmVyIHRoZSBicm93c2VyJ3Mgem9uZS5cbmV4cG9ydCBmdW5jdGlvbiBkYXRlRnJvbUJvdW5kKHZhbHVlOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKTogRGF0ZSB8IG51bGwge1xuICBpZiAoIXZhbHVlKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBkYXRlID0gcGFyc2VJU08odmFsdWUuc2xpY2UoMCwgMTApKTtcblxuICByZXR1cm4gTnVtYmVyLmlzTmFOKGRhdGUuZ2V0VGltZSgpKSA/IG51bGwgOiBkYXRlO1xufVxuXG5cbi8vIEEgcGlja2VkIERhdGUgYXMgYSB5eXl5LU1NLWRkIGJvdW5kYXJ5IGZvciBzdG9yYWdlLCBvciBudWxsLiBVc2VzIHRoZSBsb2NhbFxuLy8gY2FsZW5kYXIgZGF5IChmb3JtYXQsIG5vdCB0b0lTT1N0cmluZykgc28gdGhlIGJvdW5kYXJ5IGlzIHRoZSBkYXkgdGhhdCB3YXNcbi8vIHBpY2tlZCwgcmVnYXJkbGVzcyBvZiB0aGUgYnJvd3NlcidzIHpvbmUuXG5leHBvcnQgZnVuY3Rpb24gZGF0ZVRvQm91bmQodmFsdWU6IERhdGUgfCBudWxsIHwgdW5kZWZpbmVkKTogc3RyaW5nIHwgbnVsbCB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIERhdGUgJiYgIU51bWJlci5pc05hTih2YWx1ZS5nZXRUaW1lKCkpXG4gICAgPyBmb3JtYXQodmFsdWUsICd5eXl5LU1NLWRkJylcbiAgICA6IG51bGw7XG59XG5cblxuLy8gQSByZWxhdGl2ZSBkYXRlLXJhbmdlIHByZXNldCBrZXkgYXMgYSBzZW50ZW5jZS1jYXNlIGxhYmVsLCBkZXJpdmVkIGZyb20gdGhlXG4vLyBjYW1lbENhc2Uga2V5IGl0c2VsZiAoJ2xhc3QxMk1vbnRocycgcmVhZHMgJ0xhc3QgMTIgbW9udGhzJywgJ3RoaXNXZWVrJ1xuLy8gcmVhZHMgJ1RoaXMgd2VlaycpLCBzbyBubyBsaXN0IG9mIHByZXNldHMgaXMgbWlycm9yZWQgaGVyZSBhbmQgYSBrZXkgdGhlXG4vLyBzZXJ2ZXIgYWRkcyBsYXRlciBzdGlsbCByZWFkcyBzZW5zaWJseS5cbmV4cG9ydCBmdW5jdGlvbiByZWxhdGl2ZUxhYmVsKHJlbGF0aXZlOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCB3b3JkcyA9IHJlbGF0aXZlXG4gICAgLnJlcGxhY2UoLyhbYS16XSkoW0EtWjAtOV0pL2csICckMSAkMicpXG4gICAgLnJlcGxhY2UoLyhcXGQpKFtBLVpdKS9nLCAnJDEgJDInKVxuICAgIC50b0xvd2VyQ2FzZSgpO1xuXG4gIHJldHVybiB3b3Jkcy5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHdvcmRzLnNsaWNlKDEpO1xufVxuXG5cbi8vIE1hcHMgYSByZXBvcnQgZmlsdGVyIEdST1VQIHRvIGFuIGZzLWZpbHRlciBjb25maWcgaXRlbSwgYW5kIHJlYWRzIGZzLWZpbHRlclxuLy8gcXVlcnkgdmFsdWVzIGJhY2sgaW50byBwZXItZ3JvdXAgRmlsdGVyR3JvdXBWYWx1ZXMuIFNoYXJlZCBieSB0aGUgcmVwb3J0LWJhclxuLy8gZnMtZmlsdGVyIGFuZCB0aGUgcGVyLWNvbXBvbmVudCBmcy1maWx0ZXIgc28gYm90aCByZW5kZXIgdGhyb3VnaCB0aGUgc2FtZVxuLy8gbGlicmFyeSBhbmQgd3JpdGUgaW50byBSZXBvcnRGaWx0ZXJTdGF0ZVNlcnZpY2UgaWRlbnRpY2FsbHkuIEl0ZW1zIGFyZSBuYW1lZFxuLy8gYnkgdGhlIGdyb3VwJ3Mga2V5IChncm91cFBhcmFtS2V5cyksIHNvIHRoZSBxdWVyeSBrZXlzIG1hcCBzdHJhaWdodCBiYWNrIHRvXG4vLyB0aGUgZ3JvdXAsIGFuZCB0aGUgcmVwb3J0IGxpbmsgdXNlcyB0aGUgc2FtZSBxdWVyeSBrZXlzIChyZXBvcnQtdXJsLXN0YXRlLnRzKS5cblxuLy8gVGhlIHF1ZXJ5IGtleSBmb3IgdGhlIHJlcG9ydCdzIGdyb3VwLWJ5IGNvbnRyb2wuIEZpeGVkIHJhdGhlciB0aGFuIGRlcml2ZWRcbi8vIGZyb20gYW4gaWQgYmVjYXVzZSBhIHJlcG9ydCBoYXMgZXhhY3RseSBvbmUg4oCUIGFuZCBpdCBpcyBOT1QgYSBmaWx0ZXIgZ3JvdXAsXG4vLyBzbyBpdCBpcyByZWFkIHN0cmFpZ2h0IG9mZiB0aGUgY2hhbmdlIHF1ZXJ5IGluc3RlYWQgb2YgdGhyb3VnaFxuLy8gZ3JvdXBWYWx1ZXNGcm9tUXVlcnkuIEl0IGlzIGFsc28gdGhlIHJlcG9ydCBVUkwncyBrZXkgZm9yIHRoZSBncmFpblxuLy8gKHJlcG9ydC11cmwtc3RhdGUudHMpLiBUaGUgZ3JhaW4gdHJhdmVscyB0byB0aGUgc2VydmVyIGFzIHRoZSBkYXRhXG4vLyByZXF1ZXN0J3MgYHN0YXRlLmZyZXF1ZW5jeWAuXG5leHBvcnQgY29uc3QgR1JPVVBfQllfSVRFTSA9ICdncm91cEJ5JztcblxuLy8gVGhlIGtleXMgb2YgdGhlIHJlcG9ydCBVUkwgdGhhdCBhcmUgbm90IGZpbHRlciBncm91cHMgKHJlcG9ydC11cmwtc3RhdGUudHNcbi8vIHJlYWRzIGFuZCB3cml0ZXMgdGhlbSkuIFRoZXkgYXJlIGRlY2xhcmVkIGhlcmUgYmVjYXVzZSBhIGdyb3VwIGtleSBtdXN0XG4vLyBub3QgdGFrZSBvbmUsIGFuZCByZXBvcnQtdXJsLXN0YXRlLnRzIGltcG9ydHMgdGhpcyBmaWxlLlxuLy8gVGhlIHNoYXJlZCB2aWV3IHRoZSBzdGF0ZSBpcyBhIGRpZmYgZnJvbSwgYW5kIHRoZSBvcGVuIHBlcnNvbmFsIHZpZXcuXG5leHBvcnQgY29uc3QgVklFV19QQVJBTSA9ICdydic7XG5leHBvcnQgY29uc3QgUEVSU09OQUxfVklFV19QQVJBTSA9ICdycHYnO1xuLy8gVGhlIGxpbmsncyBmb3JtYXQuXG5leHBvcnQgY29uc3QgRk9STUFUX1BBUkFNID0gJ3JmJztcbi8vIFRoZSBob3N0J3MgcGFnZSBrZXkgKEZzQWlSZXBvcnRDb21wb25lbnQucGFnZVF1ZXJ5UGFyYW0pLCBhcyBtb3N0IGhvc3RzXG4vLyBuYW1lIGl0LlxuZXhwb3J0IGNvbnN0IFBBR0VfUEFSQU0gPSAncGFnZSc7XG5cbi8vIFRoZSB3b3JkIGJlZm9yZSBhIGdyb3VwJ3MgaWQgaW4gdGhlIGtleSBvZiBhIGdyb3VwIHdob3NlIGxhYmVsIGdpdmVzIG5vXG4vLyBrZXkgaXQgY2FuIHVzZSAoZmlsdGVyMTIpLlxuY29uc3QgRkFMTEJBQ0tfS0VZX1dPUkQgPSAnZmlsdGVyJztcblxuLy8gVGhlIGVuZHMgb2YgYW4gZnMtZmlsdGVyIHJhbmdlIGl0ZW06IFJhbmdlIHdyaXRlcyA8a2V5Pk1pbiBhbmQgPGtleT5NYXgsXG4vLyBEYXRlUmFuZ2UgPGtleT5Gcm9tIGFuZCA8a2V5PlRvLlxuZXhwb3J0IHR5cGUgSXRlbVJhbmdlRW5kID0gJ21pbicgfCAnbWF4JyB8ICdmcm9tJyB8ICd0byc7XG5cbi8vIFRoZSBxdWVyeSBrZXkgb2Ygb25lIGVuZCBvZiBhbiBmcy1maWx0ZXIgcmFuZ2UgaXRlbTogdGhlIGl0ZW0ncyBuYW1lIGFuZFxuLy8gdGhlIGVuZCB3aXRoIGl0cyBmaXJzdCBsZXR0ZXIgdXBwZXItY2FzZWQgKGZzLWZpbHRlcidzIGdldFJhbmdlTmFtZSksIHNvXG4vLyB1bml0cyBnaXZlcyB1bml0c01pbiBhbmQgZGF0ZSBnaXZlcyBkYXRlRnJvbS5cbmV4cG9ydCBmdW5jdGlvbiBpdGVtUmFuZ2VOYW1lKG5hbWU6IHN0cmluZywgZW5kOiBJdGVtUmFuZ2VFbmQpOiBzdHJpbmcge1xuICByZXR1cm4gYCR7bmFtZX0ke2VuZC5jaGFyQXQoMCkudG9VcHBlckNhc2UoKX0ke2VuZC5zbGljZSgxKX1gO1xufVxuXG4vLyBFYWNoIGdyb3VwJ3Mga2V5IGluIHRoZSByZXBvcnQgVVJMLCBieSBncm91cCBpZCwgd2hpY2ggaXMgYWxzbyB0aGUgbmFtZSBvZlxuLy8gaXRzIGZzLWZpbHRlciBpdGVtOiB0aGUgY2FtZWxDYXNlIG9mIHRoZSBsYWJlbCB0aGUgYmFyIHNob3dzICgnUmVnaW9uJyAtPlxuLy8gcmVnaW9uLCAnUmVwb3J0IFBlcmlvZCcgLT4gcmVwb3J0UGVyaW9kKS4gVGhlIGxpbmsgd3JpdGVzIGEgZ3JvdXAgdW5kZXJcbi8vIHRoZSBpdGVtJ3Mgb3duIHF1ZXJ5IGtleXMgKHJlZ2lvbj0sIGV4Y2x1ZGVSZWdpb249LCB1bml0c01pbj0sIGRhdGVGcm9tPSkuXG4vLyBBIGtleSB0aGUgcmVwb3J0IGNhbm5vdCBnaXZlIGEgZ3JvdXAgYXMgaXQgaXMgKGFub3RoZXIgZ3JvdXAgd2l0aCBhIGxvd2VyXG4vLyBpZCBoYXMgaXQgb3Igb25lIG9mIGl0cyBmb3JtcywgYW5vdGhlciBsaW5rIGtleSBvciBiYXIgaXRlbSB1c2VzIGl0LCBvciBpdFxuLy8gaXMgc2hhcGVkIGxpa2UgYSB0aWxlJ3MgaWQga2V5LCBzdWNoIGFzIHE0KSBpcyB0aGUga2V5IGFuZCB0aGUgZ3JvdXAncyBpZFxuLy8gKHJlZ2lvbjEyKS4gQSBsYWJlbCB3aXRoIG5vIGxldHRlciBvciBkaWdpdCwgb3IgYSBjbGFzaCBldmVuIHRoZW4sIGtleXMgb25cbi8vIGZpbHRlcjxpZD4uIGBncm91cHNgIGlzIGV2ZXJ5IGdyb3VwIG9mIHRoZSByZXBvcnQsIHNvIGV2ZXJ5IGJhciBhbmQgdGhlXG4vLyBsaW5rIG5hbWUgYSBncm91cCBhbGlrZS5cbmV4cG9ydCBmdW5jdGlvbiBncm91cFBhcmFtS2V5cyhncm91cHM6IHJlYWRvbmx5IFBpY2s8UmVwb3J0RmlsdGVyR3JvdXAsICdpZCcgfCAnbGFiZWwnIHwgJ2ZpbHRlcnMnPltdKTogTWFwPG51bWJlciwgc3RyaW5nPiB7XG4gIC8vIFRoZSBVUkwncyBvdGhlciBrZXlzIGFuZCB0aGUgYmFyJ3Mgb3RoZXIgaXRlbXMuXG4gIGNvbnN0IHRha2VuID0gbmV3IFNldChbXG4gICAgUEFHRV9QQVJBTSwgR1JPVVBfQllfSVRFTSwgTUFUQ0hfSVRFTSwgTElTVF9TRUFSQ0hfSVRFTSwgVklFV19QQVJBTSwgUEVSU09OQUxfVklFV19QQVJBTSwgRk9STUFUX1BBUkFNLFxuICBdKTtcbiAgY29uc3QgZnJlZSA9IChjYW5kaWRhdGU6IHN0cmluZykgPT4gISFjYW5kaWRhdGVcbiAgICAmJiBrZXlGb3JtcyhjYW5kaWRhdGUpLmV2ZXJ5KChmb3JtKSA9PiAhdGFrZW4uaGFzKGZvcm0pICYmICFJRF9LRVkudGVzdChmb3JtKSk7XG4gIGNvbnN0IGtleXMgPSBuZXcgTWFwPG51bWJlciwgc3RyaW5nPigpO1xuXG4gIFsuLi5ncm91cHNdXG4gICAgLnNvcnQoKGEsIGIpID0+IGEuaWQgLSBiLmlkKVxuICAgIC5mb3JFYWNoKChncm91cCkgPT4ge1xuICAgICAgY29uc3Qgd2FudGVkID0gbGFiZWxLZXkoZ3JvdXBMYWJlbChncm91cCkpO1xuICAgICAgY29uc3Qga2V5ID0gW3dhbnRlZCwgd2FudGVkICYmIGAke3dhbnRlZH0ke2dyb3VwLmlkfWBdLmZpbmQoZnJlZSkgPz8gZmFsbGJhY2tLZXkoZ3JvdXAuaWQsIGZyZWUpO1xuXG4gICAgICBrZXlGb3JtcyhrZXkpLmZvckVhY2goKGZvcm0pID0+IHRha2VuLmFkZChmb3JtKSk7XG4gICAgICBrZXlzLnNldChncm91cC5pZCwga2V5KTtcbiAgICB9KTtcblxuICByZXR1cm4ga2V5cztcbn1cblxuLy8gZmlsdGVyPGlkPiwgb3IsIGluIHRoZSByYXJlIHJlcG9ydCB3aGVyZSBhbm90aGVyIGdyb3VwJ3MgbGFiZWwgYWxyZWFkeVxuLy8gZ2l2ZXMgdGhhdCwgZmlsdGVyPGlkPiBhbmQgYSBjb3VudC5cbmZ1bmN0aW9uIGZhbGxiYWNrS2V5KGdyb3VwSWQ6IG51bWJlciwgZnJlZTogKGNhbmRpZGF0ZTogc3RyaW5nKSA9PiBib29sZWFuKTogc3RyaW5nIHtcbiAgY29uc3QgYmFzZSA9IGAke0ZBTExCQUNLX0tFWV9XT1JEfSR7Z3JvdXBJZH1gO1xuICBsZXQga2V5ID0gYmFzZTtcblxuICBmb3IgKGxldCBjb3VudCA9IDI7ICFmcmVlKGtleSk7IGNvdW50KyspIHtcbiAgICBrZXkgPSBgJHtiYXNlfU4ke2NvdW50fWA7XG4gIH1cblxuICByZXR1cm4ga2V5O1xufVxuXG4vLyBBIGdyb3VwJ3Mga2V5IGFtb25nIGBncm91cHNgIChldmVyeSBncm91cCBvZiB0aGUgcmVwb3J0KS4gQSBncm91cCB0aGF0IGlzXG4vLyBub3QgYW1vbmcgdGhlbSBpcyBrZXllZCBhcyBvbmUgbW9yZSBvZiB0aGVtLlxuZXhwb3J0IGZ1bmN0aW9uIGdyb3VwUGFyYW1LZXkoXG4gIGdyb3VwOiBQaWNrPFJlcG9ydEZpbHRlckdyb3VwLCAnaWQnIHwgJ2xhYmVsJyB8ICdmaWx0ZXJzJz4sXG4gIGdyb3VwczogcmVhZG9ubHkgUGljazxSZXBvcnRGaWx0ZXJHcm91cCwgJ2lkJyB8ICdsYWJlbCcgfCAnZmlsdGVycyc+W10sXG4pOiBzdHJpbmcge1xuICByZXR1cm4gZ3JvdXBQYXJhbUtleXMoZ3JvdXBzLnNvbWUoKGNhbmRpZGF0ZSkgPT4gY2FuZGlkYXRlLmlkID09PSBncm91cC5pZCkgPyBncm91cHMgOiBbLi4uZ3JvdXBzLCBncm91cF0pXG4gICAgLmdldChncm91cC5pZCk7XG59XG5cbi8vIFRoZSBuYW1lIG9mIGEgZ3JvdXAncyBmcy1maWx0ZXIgaXRlbTogaXRzIGtleSBhbW9uZyB0aGUgcmVwb3J0J3MgZ3JvdXBzLlxuZXhwb3J0IGZ1bmN0aW9uIGdyb3VwSXRlbU5hbWUoZ3JvdXA6IFJlcG9ydEZpbHRlckdyb3VwLCByZXBvcnQ6IFJlcG9ydCB8IG51bGwpOiBzdHJpbmcge1xuICByZXR1cm4gZ3JvdXBQYXJhbUtleShncm91cCwgcmVwb3J0Py5maWx0ZXJHcm91cHMgPz8gW10pO1xufVxuXG4vLyBUaGUgbGFiZWwgYSBncm91cCdzIGNoaXAgc2hvd3M6IGl0cyBvd24sIGVsc2UgaXRzIGZpcnN0IG1lbWJlcidzIGNvbHVtbi5cbmZ1bmN0aW9uIGdyb3VwTGFiZWwoZ3JvdXA6IFBpY2s8UmVwb3J0RmlsdGVyR3JvdXAsICdsYWJlbCcgfCAnZmlsdGVycyc+KTogc3RyaW5nIHtcbiAgcmV0dXJuIGdyb3VwLmxhYmVsIHx8IGdyb3VwLmZpbHRlcnM/LlswXT8uZmlsdGVyQ29sdW1uIHx8ICcnO1xufVxuXG4vLyBBIGxldHRlciBhbmQgdGhlbiBkaWdpdHM6IHRoZSBzaGFwZSBvZiB0aGUgVVJMJ3MgdGlsZSBrZXlzIChzMzEsIHEzMSxcbi8vIGgzMSwgZDQ0KSwga2VwdCBvZmYgdGhlIGdyb3VwcyBzbyBhIGdyb3VwIGtleSBuZXZlciByZWFkcyBhcyBvbmUuXG5jb25zdCBJRF9LRVkgPSAvXlthLXpdXFxkKyQvO1xuXG5jb25zdCBSQU5HRV9FTkRTOiByZWFkb25seSBJdGVtUmFuZ2VFbmRbXSA9IFsnbWluJywgJ21heCcsICdmcm9tJywgJ3RvJ107XG5cbi8vIEV2ZXJ5IGtleSBhIGdyb3VwJ3MgaXRlbSBvciBsaW5rIG1heSB3cml0ZSB1bmRlciBga2V5YDogdGhlIGtleSwgaXRzXG4vLyBleGNsdWRlIGtleSAoZXhjbHVkZVJlZ2lvbikgYW5kIGFuIGZzLWZpbHRlciByYW5nZSdzIG93biBrZXlzLlxuZnVuY3Rpb24ga2V5Rm9ybXMoa2V5OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIHJldHVybiBba2V5LCBnZXRFeGNsdWRlTmFtZShrZXkpLCAuLi5SQU5HRV9FTkRTLm1hcCgoZW5kKSA9PiBpdGVtUmFuZ2VOYW1lKGtleSwgZW5kKSldO1xufVxuXG4vLyBBIGxhYmVsIGFzIGEgY2FtZWxDYXNlIGtleTogYWNjZW50cyBkcm9wcGVkLCB3b3JkcyBzcGxpdCBvbiBhbnl0aGluZyB0aGF0XG4vLyBpcyBub3QgYSBsZXR0ZXIgb3IgZGlnaXQgKGFuZCB3aGVyZSBhIGxvd2VyLWNhc2UgbGV0dGVyIG1lZXRzIGFuIHVwcGVyLWNhc2Vcbi8vIG9uZSksIHRoZSBmaXJzdCB3b3JkIGxvd2VyLWNhc2UsIGV2ZXJ5IGxhdGVyIG9uZSBjYXBpdGFsaXplZC5cbmZ1bmN0aW9uIGxhYmVsS2V5KGxhYmVsOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gbGFiZWxcbiAgICAubm9ybWFsaXplKCdORkQnKVxuICAgIC5yZXBsYWNlKC9cXHB7TX0vZ3UsICcnKVxuICAgIC5yZXBsYWNlKC8oW2EtejAtOV0pKFtBLVpdKS9nLCAnJDEgJDInKVxuICAgIC5zcGxpdCgvW15BLVphLXowLTldKy8pXG4gICAgLmZpbHRlcigod29yZCkgPT4gd29yZCAhPT0gJycpXG4gICAgLm1hcCgod29yZCwgaW5kZXgpID0+IHtcbiAgICAgIGNvbnN0IGxvd2VyID0gd29yZC50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICByZXR1cm4gaW5kZXggPyBsb3dlci5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIGxvd2VyLnNsaWNlKDEpIDogbG93ZXI7XG4gICAgfSlcbiAgICAuam9pbignJyk7XG59XG5cbi8vIEEgc2VsZWN0IGdyb3VwJ3MgZGlzdGluY3Qgb3B0aW9ucywgYXMgeyBuYW1lLCB2YWx1ZSB9IHBhaXJzLiBUaGUgc2VydmVyIHNlbmRzXG4vLyB7IHZhbHVlLCBsYWJlbCB9OiB0aGUgdmFsdWUgaXMgd2hhdCB0aGUgZmlsdGVyIG1hdGNoZXMgb24gKGFuIGVudGl0eSdzIHN0YWJsZVxuLy8gaWQpIGFuZCB0aGUgbGFiZWwgaXMgd2hhdCB0aGUgdmlld2VyIHJlYWRzIOKAlCBzbyBhIHJlbmFtZWQgZW50aXR5IGtlZXBzIGl0cyBpZFxuLy8gYW5kIHNpbXBseSBzaG93cyBpdHMgbmV3IG5hbWUgaGVyZS4gT3B0aW9ucyBjb21lIGZyb20gdGhlIGZpcnN0IG1lbWJlciBmaWx0ZXJcbi8vIHRoYXQgZGVjbGFyZXMgdGhlbSDigJQgbWVtYmVycyBhcmUgdGhlIHNhbWUgZGF0YSBwb2ludCwgc28gYW55IG1lbWJlcidzIGxpc3Rcbi8vIHNlcnZlcyB0aGUgZ3JvdXAuIFRoZSBsaXN0IGlzIGZldGNoZWQgb25jZSAodGhlIHNlcnZlciBjYXBzIGl0KSBhbmQgcmVwbGF5ZWRcbi8vIChzaGFyZVJlcGxheSksIHNvIHJlcGVhdGVkIHJlYWRzIG5ldmVyIHJlZmV0Y2guIFRoaXMgaXMgdGhlIGZ1bGwgbGlzdCwgbmV2ZXJcbi8vIG5hcnJvd2VkIGJ5IG90aGVyIGZpbHRlcnM6IHRoZSByZXBvcnQtc2V0dGluZ3MgZGVmYXVsdCBwaWNrZXIgcmVhZHMgaXQgKGFuXG4vLyBhdXRob3Igc2V0cyBhIGRlZmF1bHQgYWdhaW5zdCB0aGUgd2hvbGUgbGlzdCksIGFuZCBzbyBkb2VzIHRoZSBleHBvcnQnc1xuLy8gZmlsdGVyIHdvcmRpbmcgZm9yIGEgcGljayB0aGUgYmFyIGhhcyBub3QgbmFtZWQuIFRoZSBiYXJzIHJlYWRcbi8vIFJlcG9ydEZpbHRlck9wdGlvbnNTZXJ2aWNlIGluc3RlYWQuIFJldHVybnMgYW4gZW1wdHkgbGlzdCB3aGVuIG5vIG1lbWJlclxuLy8gcHJvdmlkZXMgb3B0aW9ucy5cbmV4cG9ydCBmdW5jdGlvbiBsb2FkR3JvdXBPcHRpb25zKFxuICBncm91cDogUmVwb3J0RmlsdGVyR3JvdXAsXG4gIHJlcG9ydERhdGE6IFJlcG9ydERhdGEsXG4gIHJlcG9ydElkOiBudW1iZXIsXG4pOiBPYnNlcnZhYmxlPFJlcG9ydEZpbHRlck9wdGlvblBhaXJbXT4ge1xuICBjb25zdCBvcHRpb25GaWx0ZXIgPSAoZ3JvdXAuZmlsdGVycyA/PyBbXSkuZmluZCgobWVtYmVyKSA9PiBtZW1iZXIuaGFzT3B0aW9ucyk7XG4gIGlmICghb3B0aW9uRmlsdGVyKSB7XG4gICAgcmV0dXJuIG9mKFtdKTtcbiAgfVxuXG4gIHJldHVybiByZXBvcnREYXRhLmZpbHRlck9wdGlvbnMocmVwb3J0SWQsIG9wdGlvbkZpbHRlci5pZClcbiAgICAucGlwZShcbiAgICAgIG1hcCgob3B0aW9uczogUmVwb3J0RmlsdGVyT3B0aW9uW10pID0+IChvcHRpb25zID8/IFtdKVxuICAgICAgICAubWFwKChvcHRpb24pID0+ICh7IG5hbWU6IG9wdGlvbi5sYWJlbCwgdmFsdWU6IG9wdGlvbi52YWx1ZSB9KSkpLFxuICAgICAgc2hhcmVSZXBsYXkoeyBidWZmZXJTaXplOiAxLCByZWZDb3VudDogZmFsc2UgfSksXG4gICAgKTtcbn1cblxuLy8gU3RvcmVkIGZpbHRlciB2YWx1ZXMgKGlkcykgcGFpcmVkIGJhY2sgd2l0aCB0aGUgbGFiZWxzIHRvIHNob3cgZm9yIHRoZW0uXG4vLyBBIHNhdmVkIGRlZmF1bHQgaG9sZHMgb25seSB2YWx1ZXMsIHNvIHRoZSBuYW1lcyBoYXZlIHRvIGJlIHJlYWQgYmFjayBvZmYgdGhlXG4vLyBvcHRpb24gbGlzdCDigJQgdGhhdCBpbmRpcmVjdGlvbiBpcyBleGFjdGx5IHdoYXQgc3Vydml2ZXMgYSByZW5hbWUuIGBsYWJlbGBcbi8vIG5hbWVzIGEgdmFsdWUgZmlyc3Q6IGEgbmFtZSBhbHJlYWR5IGxlYXJuZWQgKFJlcG9ydEZpbHRlck9wdGlvbnNTZXJ2aWNlLmxhYmVsKVxuLy8gaG9sZHMgZm9yIGEgcGljayBhIG5hcnJvd2VkIGxpc3QgbGVhdmVzIG91dCwgYW5kIHdoZW4gaXQgbmFtZXMgZXZlcnkgdmFsdWVcbi8vIHRoZSBsaXN0IGlzIG5vdCByZWFkIGF0IGFsbC4gQSB2YWx1ZSB3aXRoIG5vIG5hbWUgYW5kIG5vIG1hdGNoaW5nIG9wdGlvblxuLy8gKGl0cyBlbnRpdHkgd2FzIGRlbGV0ZWQsIHNvIGl0IGlzIG5vIGxvbmdlciBsaXN0ZWQpIGZhbGxzIGJhY2sgdG8gc2hvd2luZ1xuLy8gdGhlIHJhdyB2YWx1ZSByYXRoZXIgdGhhbiBkcm9wcGluZyB0aGUgY2hpcCwgd2hpY2ggd291bGQgc2lsZW50bHkgd2lkZW4gdGhlXG4vLyBmaWx0ZXIuXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZU9wdGlvblZhbHVlcyhcbiAgb3B0aW9ucyQ6IE9ic2VydmFibGU8UmVwb3J0RmlsdGVyT3B0aW9uUGFpcltdPixcbiAgdmFsdWVzOiB1bmtub3duW10sXG4gIGxhYmVsOiAodmFsdWU6IHVua25vd24pID0+IHN0cmluZyB8IG51bGwgPSAoKSA9PiBudWxsLFxuKTogT2JzZXJ2YWJsZTxSZXBvcnRGaWx0ZXJPcHRpb25QYWlyW10+IHtcbiAgY29uc3QgbmFtZWQgPSAob3B0aW9uczogUmVwb3J0RmlsdGVyT3B0aW9uUGFpcltdKSA9PiB2YWx1ZXMubWFwKCh2YWx1ZSkgPT4ge1xuICAgIGNvbnN0IG9wdGlvbiA9IG9wdGlvbnMuZmluZCgoY2FuZGlkYXRlKSA9PiBTdHJpbmcoY2FuZGlkYXRlLnZhbHVlKSA9PT0gU3RyaW5nKHZhbHVlKSk7XG5cbiAgICByZXR1cm4geyBuYW1lOiBsYWJlbCh2YWx1ZSkgPz8gb3B0aW9uPy5uYW1lID8/IFN0cmluZyh2YWx1ZSksIHZhbHVlIH07XG4gIH0pO1xuXG4gIHJldHVybiB2YWx1ZXMuZXZlcnkoKHZhbHVlKSA9PiBsYWJlbCh2YWx1ZSkgIT09IG51bGwpXG4gICAgPyBvZihuYW1lZChbXSkpXG4gICAgOiBvcHRpb25zJC5waXBlKG1hcChuYW1lZCkpO1xufVxuXG4vLyBDYXNlLWluc2Vuc2l0aXZlIG5hbWUgZmlsdGVyIGFwcGxpZWQgdG8gYSBsb2FkZWQgb3B0aW9uIGxpc3Qg4oCUIHRoZSB0eXBlZFxuLy8ga2V5d29yZCBoYXMgdG8gYmUgbWF0Y2hlZCBoZXJlIGJlY2F1c2UgZnMtYXV0b2NvbXBsZXRlIHJlbmRlcnMgd2hhdCB3ZSByZXR1cm5cbi8vIHZlcmJhdGltLlxuZXhwb3J0IGZ1bmN0aW9uIG1hdGNoT3B0aW9ucyhcbiAgb3B0aW9ucyQ6IE9ic2VydmFibGU8UmVwb3J0RmlsdGVyT3B0aW9uUGFpcltdPixcbiAga2V5d29yZD86IHN0cmluZyxcbik6IE9ic2VydmFibGU8UmVwb3J0RmlsdGVyT3B0aW9uUGFpcltdPiB7XG4gIGNvbnN0IHRlcm0gPSAoa2V5d29yZCA/PyAnJykudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG5cbiAgcmV0dXJuIG9wdGlvbnMkLnBpcGUobWFwKChvcHRpb25zKSA9PiB0ZXJtXG4gICAgPyBvcHRpb25zLmZpbHRlcigob3B0aW9uKSA9PiBvcHRpb24ubmFtZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHRlcm0pKVxuICAgIDogb3B0aW9ucykpO1xufVxuXG4vLyBUaGUgcGFuZWwgcm93IG9mIGEgc2VsZWN0IHdob3NlIGxpc3QgdGhlIHNlcnZlciBjdXQgYXQgNTAwLlxuZXhwb3J0IGNvbnN0IE9QVElPTlNfVFJVTkNBVEVEX05PVEUgPSAnU2hvd2luZyB0aGUgZmlyc3QgNTAwLiBUeXBlIHRvIG5hcnJvdy4nO1xuXG4vLyBUaGUgcGFuZWwgcm93IG9mIGEgc2VsZWN0IHdob3NlIGxpc3QgY291bGQgbm90IGJlIHJlYWQuIFRoZSBuZXh0IGZvY3VzIG9yXG4vLyBrZXlzdHJva2UgYXNrcyBhZ2Fpbi5cbmV4cG9ydCBjb25zdCBPUFRJT05TX0ZBSUxFRF9OT1RFID0gJ0NvdWxkIG5vdCBsb2FkIHRoZSBsaXN0Lic7XG5cbi8vIEJ1aWxkIHRoZSBmcy1maWx0ZXIgY29uZmlnIGl0ZW0gZm9yIGEgZ3JvdXAsIHNlZWRpbmcgaXRzIGRlZmF1bHQgZnJvbSB0aGVcbi8vIGN1cnJlbnQgc2Vzc2lvbiB2YWx1ZSBzbyBhdXRob3JlZC9yZWxhdGl2ZSBkZWZhdWx0cyBzaG93IHNlbGVjdGVkIG9uIG9wZW4uXG4vLyBBIHNlbGVjdCBsaXN0cyB3aGF0IGBvcHRpb25zYCBvZmZlcnMgZm9yIGl0IGluIGByZXBvcnRgLiBgZmVhdHVyZXNgIGlzIHRoZVxuLy8gcmVwb3J0J3Mgdmlld2VyRmVhdHVyZXM6IGEgc2VsZWN0IG9mZmVycyAnRXhjbHVkZSB0aGVzZScgYnkgdGhlIHJ1bGUgb2Zcbi8vIG9mZmVyc0V4Y2x1ZGUgKHRoZSBzZXJ2ZXIgbGlzdHMgZXhjbHVkZVZhbHVlcyBhbmQgbm8gbWVtYmVyIGJpbmRzIHNldmVyYWxcbi8vIGNvbHVtbnMpLCBhbmQgYSBudW1iZXIgcmFuZ2UgaXMgYSBtaW4vbWF4IGNvbnRyb2wgb25seSB3aGVuIGl0IGxpc3RzXG4vLyBudW1iZXJSYW5nZS5cbmV4cG9ydCBmdW5jdGlvbiBmaWx0ZXJJdGVtRm9yR3JvdXAoXG4gIGdyb3VwOiBSZXBvcnRGaWx0ZXJHcm91cCxcbiAgb3B0aW9uczogUmVwb3J0RmlsdGVyT3B0aW9uc1NlcnZpY2UsXG4gIHJlcG9ydDogUmVwb3J0IHwgbnVsbCxcbiAgaW5pdGlhbD86IEZpbHRlckdyb3VwVmFsdWUsXG4gIGZlYXR1cmVzOiByZWFkb25seSBSZXBvcnRWaWV3ZXJGZWF0dXJlW10gPSBbXSxcbik6IElGaWx0ZXJDb25maWdJdGVtIHtcbiAgY29uc3QgbmFtZSA9IGdyb3VwSXRlbU5hbWUoZ3JvdXAsIHJlcG9ydCk7XG4gIGNvbnN0IGxhYmVsID0gZ3JvdXBMYWJlbChncm91cCk7XG5cbiAgc3dpdGNoIChncm91cC50eXBlKSB7XG4gICAgY2FzZSAnZGF0ZVJhbmdlJzpcbiAgICAgIHJldHVybiBkYXRlUmFuZ2VGaWx0ZXJJdGVtKG5hbWUsIGxhYmVsLCBpbml0aWFsKTtcblxuICAgIGNhc2UgJ3NlbGVjdCc6XG4gICAgICByZXR1cm4gc2VsZWN0RmlsdGVySXRlbShncm91cCwgbGFiZWwsIG9wdGlvbnMsIHJlcG9ydCwgaW5pdGlhbCwgb2ZmZXJzRXhjbHVkZShncm91cCwgZmVhdHVyZXMpKTtcblxuICAgIGNhc2UgJ251bWJlclJhbmdlJzpcbiAgICAgIHJldHVybiBmZWF0dXJlcy5pbmNsdWRlcygnbnVtYmVyUmFuZ2UnKVxuICAgICAgICA/IG51bWJlclJhbmdlRmlsdGVySXRlbShncm91cCwgbGFiZWwsIHJlcG9ydCwgaW5pdGlhbClcbiAgICAgICAgOiBrZXl3b3JkRmlsdGVySXRlbShuYW1lLCBsYWJlbCwgaW5pdGlhbCk7XG5cbiAgICBjYXNlICdrZXl3b3JkJzpcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGtleXdvcmRGaWx0ZXJJdGVtKG5hbWUsIGxhYmVsLCBpbml0aWFsKTtcbiAgfVxufVxuXG4vLyBBIGRhdGUgcmFuZ2Ugb3BlbnMgb24gaXRzIGRheXMsIGFuZCBpdHMgY2hpcCBzaG93cyB0aGVtLiBBIHByZXNldCBwaWNrZWQgaW5cbi8vIHRoZSBkYXRlIHBpY2tlciBvbmx5IHNldHMgdGhlIGRheXMuXG5mdW5jdGlvbiBkYXRlUmFuZ2VGaWx0ZXJJdGVtKG5hbWU6IHN0cmluZywgbGFiZWw6IHN0cmluZywgaW5pdGlhbD86IEZpbHRlckdyb3VwVmFsdWUpOiBJRmlsdGVyQ29uZmlnSXRlbSB7XG4gIGNvbnN0IGhhc0RheXMgPSAhIShpbml0aWFsPy5zdGFydCB8fCBpbml0aWFsPy5lbmQpO1xuXG4gIHJldHVybiB7XG4gICAgbmFtZSxcbiAgICB0eXBlOiBJdGVtVHlwZS5EYXRlUmFuZ2UsXG4gICAgbGFiZWw6IHsgZnJvbTogYCR7bGFiZWx9IEZyb21gLCB0bzogYCR7bGFiZWx9IFRvYCB9LFxuICAgIGRlZmF1bHQ6IGhhc0RheXNcbiAgICAgID8geyBmcm9tOiBpbml0aWFsLnN0YXJ0ID8/IHVuZGVmaW5lZCwgdG86IGluaXRpYWwuZW5kID8/IHVuZGVmaW5lZCB9XG4gICAgICA6IHVuZGVmaW5lZCxcbiAgfTtcbn1cblxuLy8gQSBzZWxlY3QncyBwaWNrcywga2VwdCBvciBsZWZ0IG91dC4gV2l0aCBgZXhjbHVkZWAgdGhlIGxpc3QgaGFzIHRoZVxuLy8gJ0V4Y2x1ZGUgdGhlc2UnIHJvdywgYW5kIGEgdmFsdWUgdGhhdCBsZWF2ZXMgb3V0IG9wZW5zIHdpdGggaXQgb24uIEl0cyBsaXN0XG4vLyBpcyByZWFkIG9uIGZvY3VzIGFuZCBvbiBlYWNoIGtleXN0cm9rZTogdGhlIG9wdGlvbnMgc2VydmljZSBmZXRjaGVzIGl0IHdoZW5cbi8vIHRoZSBvdGhlciBmaWx0ZXJzIGNoYW5nZWQgc2luY2UgYW5kIHJlcGxheXMgaXQgb3RoZXJ3aXNlLCBhbmQgdHlwaW5nXG4vLyBmaWx0ZXJzIGl0IGhlcmUuIEEgbGlzdCB0aGUgc2VydmVyIGN1dCwgb3Igb25lIHRoYXQgY291bGQgbm90IGJlIHJlYWQsXG4vLyBzYXlzIHNvIGluIGEgcGFuZWwgcm93LlxuZnVuY3Rpb24gc2VsZWN0RmlsdGVySXRlbShcbiAgZ3JvdXA6IFJlcG9ydEZpbHRlckdyb3VwLFxuICBsYWJlbDogc3RyaW5nLFxuICBvcHRpb25zOiBSZXBvcnRGaWx0ZXJPcHRpb25zU2VydmljZSxcbiAgcmVwb3J0OiBSZXBvcnQgfCBudWxsLFxuICBpbml0aWFsOiBGaWx0ZXJHcm91cFZhbHVlIHwgdW5kZWZpbmVkLFxuICBleGNsdWRlOiBib29sZWFuLFxuKTogSUZpbHRlckNvbmZpZ0l0ZW0ge1xuICBjb25zdCBleGNsdWRpbmcgPSBleGNsdWRlICYmICFpbml0aWFsPy52YWx1ZXM/Lmxlbmd0aCAmJiAhIWluaXRpYWw/LmV4Y2x1ZGVWYWx1ZXM/Lmxlbmd0aDtcbiAgY29uc3QgcGlja3MgPSBleGNsdWRpbmcgPyBpbml0aWFsLmV4Y2x1ZGVWYWx1ZXMgOiBpbml0aWFsPy52YWx1ZXM7XG4gIGNvbnN0IG9wdGlvbnMkID0gb3B0aW9ucy5vcHRpb25zKGdyb3VwLCByZXBvcnQpO1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogZ3JvdXBJdGVtTmFtZShncm91cCwgcmVwb3J0KSxcbiAgICB0eXBlOiBJdGVtVHlwZS5BdXRvQ29tcGxldGVDaGlwcyxcbiAgICBsYWJlbCxcbiAgICBmZXRjaE9uRm9jdXM6IHRydWUsXG4gICAgZXhjbHVkZTogZXhjbHVkZSA/IHt9IDogdW5kZWZpbmVkLFxuICAgIHZhbHVlczogKGtleXdvcmQ/OiBzdHJpbmcpID0+IG1hdGNoT3B0aW9ucyhvcHRpb25zJCwga2V5d29yZCksXG4gICAgcGFuZWxOb3RlOiAoKSA9PiBvcHRpb25zTm90ZShvcHRpb25zLCBncm91cC5pZCksXG4gICAgLy8gU3RvcmVkIHZhbHVlcyBhcmUgaWRzLCBzbyBhIGNoaXAgaXMgbmFtZWQgYnkgYSBuYW1lIGFscmVhZHkgbGVhcm5lZCBvclxuICAgIC8vIG9uY2UgdGhlIG9wdGlvbiBsaXN0IGhhcyBsb2FkZWQg4oCUIGhlbmNlIHRoZSBvYnNlcnZhYmxlIGZvcm0gb2YgYGRlZmF1bHRgLlxuICAgIGRlZmF1bHQ6IHBpY2tzPy5sZW5ndGhcbiAgICAgID8gKCkgPT4gcmVzb2x2ZU9wdGlvblZhbHVlcyhvcHRpb25zJCwgcGlja3MsICh2YWx1ZSkgPT4gb3B0aW9ucy5sYWJlbChncm91cC5pZCwgdmFsdWUpKVxuICAgICAgICAucGlwZShtYXAoKHNlbGVjdGVkKSA9PiAoZXhjbHVkaW5nID8geyBleGNsdWRlOiB0cnVlLCBzZWxlY3RlZCB9IDogc2VsZWN0ZWQpKSlcbiAgICAgIDogdW5kZWZpbmVkLFxuICB9O1xufVxuXG4vLyBUaGUgcGFuZWwgcm93IG9mIGEgc2VsZWN0J3MgbGF0ZXN0IGxpc3Q6IGEgZmFpbHVyZSBmaXJzdCwgdGhlbiBhIGN1dCBsaXN0LlxuZnVuY3Rpb24gb3B0aW9uc05vdGUob3B0aW9uczogUmVwb3J0RmlsdGVyT3B0aW9uc1NlcnZpY2UsIGdyb3VwSWQ6IG51bWJlcik6IHN0cmluZyB8IG51bGwge1xuICBpZiAob3B0aW9ucy5mYWlsZWQoZ3JvdXBJZCkpIHtcbiAgICByZXR1cm4gT1BUSU9OU19GQUlMRURfTk9URTtcbiAgfVxuXG4gIHJldHVybiBvcHRpb25zLnRydW5jYXRlZChncm91cElkKSA/IE9QVElPTlNfVFJVTkNBVEVEX05PVEUgOiBudWxsO1xufVxuXG4vLyBBIG51bWJlciByYW5nZSdzIGxvdyBhbmQgaGlnaCBlbmRzLCBlaXRoZXIgb25lIG9wZW4uIDAgaXMgYW4gZW5kIGxpa2UgYW55XG4vLyBvdGhlci4gSXRzIGNoaXAgcmVhZHMgYXMgdGhlIGV4cG9ydCBsaW5lcyBkbyAoJ0Ftb3VudDogMCBvciBtb3JlJyxcbi8vICdBbW91bnQ6IDAgdG8gMTAnKTogdGhlIGVuZHMgYXJlIHJlYWQgb2ZmIHRoZSBpdGVtJ3MgcXVlcnkgdGhlIHdheSB0aGVcbi8vIGJhcidzIGNoYW5nZSByZWFkcyB0aGVtLCBhbmQgd29yZGVkIGluIHRoZSByZXBvcnQncyBsb2NhbGUuXG5mdW5jdGlvbiBudW1iZXJSYW5nZUZpbHRlckl0ZW0oXG4gIGdyb3VwOiBSZXBvcnRGaWx0ZXJHcm91cCxcbiAgbGFiZWw6IHN0cmluZyxcbiAgcmVwb3J0OiBSZXBvcnQgfCBudWxsLFxuICBpbml0aWFsPzogRmlsdGVyR3JvdXBWYWx1ZSxcbik6IElGaWx0ZXJDb25maWdJdGVtIHtcbiAgY29uc3QgbmFtZSA9IGdyb3VwSXRlbU5hbWUoZ3JvdXAsIHJlcG9ydCk7XG4gIGNvbnN0IG1pbiA9IGluaXRpYWw/Lm1pbiA/PyB1bmRlZmluZWQ7XG4gIGNvbnN0IG1heCA9IGluaXRpYWw/Lm1heCA/PyB1bmRlZmluZWQ7XG4gIGNvbnN0IGxvY2FsZSA9IHJlc29sdmVGb3JtYXRDb250ZXh0KHJlcG9ydCA/PyB7fSkubG9jYWxlO1xuXG4gIHJldHVybiB7XG4gICAgbmFtZSxcbiAgICB0eXBlOiBJdGVtVHlwZS5SYW5nZSxcbiAgICBsYWJlbCxcbiAgICBkZWZhdWx0OiBtaW4gIT09IHVuZGVmaW5lZCB8fCBtYXggIT09IHVuZGVmaW5lZCA/IHsgbWluLCBtYXggfSA6IHVuZGVmaW5lZCxcbiAgICBjaGlwVGV4dDogKGl0ZW0pID0+IGZpbHRlckxpbmVUZXh0KFxuICAgICAgeyBsYWJlbCwgbGV2ZWw6IGdyb3VwLmxldmVsIH0sXG4gICAgICBudW1iZXJSYW5nZUZyb21RdWVyeShpdGVtLnF1ZXJ5LCBuYW1lKSxcbiAgICAgIHsgbG9jYWxlIH0sXG4gICAgICAnY2hpcCcsXG4gICAgKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24ga2V5d29yZEZpbHRlckl0ZW0obmFtZTogc3RyaW5nLCBsYWJlbDogc3RyaW5nLCBpbml0aWFsPzogRmlsdGVyR3JvdXBWYWx1ZSk6IElGaWx0ZXJDb25maWdJdGVtIHtcbiAgcmV0dXJuIHtcbiAgICBuYW1lLFxuICAgIHR5cGU6IEl0ZW1UeXBlLktleXdvcmQsXG4gICAgbGFiZWwsXG4gICAgZGVmYXVsdDogaW5pdGlhbD8udmFsdWUsXG4gIH07XG59XG5cbi8vIFRoZSBncm91cHMgYSBtYXRjaCBvZiAnYW55JyBjb21iaW5lczogcmVwb3J0IGJhciBncm91cHMgKGEgcGFnZSBncm91cCBvblxuLy8gaXRzIG93biBwYWdlIG9ubHkpIHRoYXQgYSB2aWV3ZXIgcGlja3MgdmFsdWVzLCB0ZXh0IG9yIGEgbnVtYmVyIHJhbmdlIGluLlxuLy8gRGF0ZXMsIHRpbGUtb25seSBncm91cHMgYW5kIHRoZSBjcm9zcy1maWx0ZXIgYWx3YXlzIG5hcnJvdyBvbiB0aGVpciBvd24uXG4vLyBUaGUgc2VydmVyIGhvbGRzIHRoZSBzYW1lIHJ1bGUgYW5kIGNoZWNrcyBldmVyeSBpZCBpdCBpcyBzZW50LlxuY29uc3QgTUFUQ0hfQU5ZX0xFVkVMUzogcmVhZG9ubHkgUmVwb3J0RmlsdGVyTGV2ZWxbXSA9IFsncmVwb3J0JywgJ2JvdGgnLCAncGFnZSddO1xuY29uc3QgTUFUQ0hfQU5ZX1RZUEVTOiByZWFkb25seSBSZXBvcnRGaWx0ZXJUeXBlW10gPSBbJ3NlbGVjdCcsICdrZXl3b3JkJywgJ251bWJlclJhbmdlJ107XG5cbi8vIFdoZXRoZXIgYSBncm91cCBqb2lucyBhIG1hdGNoIG9mICdhbnknIG9uIHBhZ2UgYHBhZ2VJZGAuXG5leHBvcnQgZnVuY3Rpb24gaXNNYXRjaEFueUdyb3VwKGdyb3VwOiBSZXBvcnRGaWx0ZXJHcm91cCwgcGFnZUlkOiBudW1iZXIgfCBudWxsKTogYm9vbGVhbiB7XG4gIHJldHVybiBNQVRDSF9BTllfTEVWRUxTLmluY2x1ZGVzKGdyb3VwLmxldmVsKVxuICAgICYmIE1BVENIX0FOWV9UWVBFUy5pbmNsdWRlcyhncm91cC50eXBlKVxuICAgICYmIChncm91cC5sZXZlbCAhPT0gJ3BhZ2UnIHx8ICghIXBhZ2VJZCAmJiBncm91cC5wYWdlSWQgPT09IHBhZ2VJZCkpO1xufVxuXG4vLyBUaGUgcmVwb3J0IGJhcidzIGdyb3VwcyBpbiB0aGVpciBzYXZlZCBvcmRlcjogdGhlIHJlcG9ydCBhbmQgYm90aCBncm91cHMsXG4vLyBhbmQgdGhlIHBhZ2UgZ3JvdXBzIG9mIHRoZSBwYWdlIG9uIHNjcmVlbiAoYHBhZ2VJZGApLlxuZXhwb3J0IGZ1bmN0aW9uIHJlcG9ydEJhckdyb3VwcyhyZXBvcnQ6IFJlcG9ydCB8IG51bGwsIHBhZ2VJZDogbnVtYmVyIHwgbnVsbCk6IFJlcG9ydEZpbHRlckdyb3VwW10ge1xuICByZXR1cm4gKHJlcG9ydD8uZmlsdGVyR3JvdXBzID8/IFtdKVxuICAgIC5maWx0ZXIoKGdyb3VwKSA9PiBncm91cC5sZXZlbCA9PT0gJ3JlcG9ydCcgfHwgZ3JvdXAubGV2ZWwgPT09ICdib3RoJ1xuICAgICAgfHwgKGdyb3VwLmxldmVsID09PSAncGFnZScgJiYgISFwYWdlSWQgJiYgZ3JvdXAucGFnZUlkID09PSBwYWdlSWQpKVxuICAgIC5zb3J0KChhLCBiKSA9PiBhLm9yZGVyIC0gYi5vcmRlcik7XG59XG5cbi8vIFdoZXRoZXIgdGhlIHJlcG9ydCBoYXMgYSBncm91cCBzaG93biBvbiBvbmUgcGFnZSBvbmx5LCBzbyBpdHMgcmVwb3J0IGJhclxuLy8gY2hhbmdlcyB3aXRoIHRoZSBwYWdlIG9uIHNjcmVlbi5cbmV4cG9ydCBmdW5jdGlvbiBoYXNQYWdlR3JvdXAocmVwb3J0OiBSZXBvcnQgfCBudWxsKTogYm9vbGVhbiB7XG4gIHJldHVybiAocmVwb3J0Py5maWx0ZXJHcm91cHMgPz8gW10pLnNvbWUoKGdyb3VwKSA9PiBncm91cC5sZXZlbCA9PT0gJ3BhZ2UnKTtcbn1cblxuLy8gVGhlIHF1ZXJ5IGtleSBvZiB0aGUgcmVwb3J0IGJhcidzIE1hdGNoIGNvbnRyb2wuIE5vdCBhIGZpbHRlciBncm91cDogaXRcbi8vIHNheXMgaG93IHRoZSBncm91cHMgY29tYmluZSwgc28gaXQgaXMgcmVhZCBzdHJhaWdodCBvZmYgdGhlIGNoYW5nZSBxdWVyeS5cbi8vIEl0IGlzIGFsc28gdGhlIHJlcG9ydCBVUkwncyBrZXkgZm9yIHRoZSBtYXRjaCAobWF0Y2g9YW55KS5cbmV4cG9ydCBjb25zdCBNQVRDSF9JVEVNID0gJ21hdGNoJztcblxuY29uc3QgTUFUQ0hfT1BUSU9OUzogeyBuYW1lOiBzdHJpbmc7IHZhbHVlOiBSZXBvcnRGaWx0ZXJNYXRjaCB9W10gPSBbXG4gIHsgbmFtZTogJ0FsbCBmaWx0ZXJzJywgdmFsdWU6ICdhbGwnIH0sXG4gIHsgbmFtZTogJ0FueSBmaWx0ZXInLCB2YWx1ZTogJ2FueScgfSxcbl07XG5cbi8vIFRoZSByZXBvcnQgYmFyJ3MgTWF0Y2ggY29udHJvbCwgbGFzdCBpbiB0aGUgYmFyLCBvciBudWxsIHdoZW4gaXQgd291bGQgZG9cbi8vIG5vdGhpbmc6IHRoZSBzZXJ2ZXIgbXVzdCBzZXJ2ZSBtYXRjaEFueSwgYW5kIHRoZSBiYXIgbXVzdCBob2xkIHR3byBvciBtb3JlXG4vLyBncm91cHMgdGhhdCBjb21iaW5lIChhbiAnYW55JyBvdmVyIG9uZSBncm91cCBpcyB0aGF0IGdyb3VwKS5cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaEZpbHRlckl0ZW0oXG4gIHJlcG9ydDogUmVwb3J0IHwgbnVsbCxcbiAgZ3JvdXBzOiBSZXBvcnRGaWx0ZXJHcm91cFtdLFxuICBwYWdlSWQ6IG51bWJlciB8IG51bGwsXG4gIG1hdGNoOiBSZXBvcnRGaWx0ZXJNYXRjaCxcbik6IElGaWx0ZXJDb25maWdJdGVtIHwgbnVsbCB7XG4gIGNvbnN0IGVsaWdpYmxlID0gZ3JvdXBzLmZpbHRlcigoZ3JvdXApID0+IGlzTWF0Y2hBbnlHcm91cChncm91cCwgcGFnZUlkKSk7XG5cbiAgaWYgKCFyZXBvcnQ/LnZpZXdlckZlYXR1cmVzPy5pbmNsdWRlcygnbWF0Y2hBbnknKSB8fCBlbGlnaWJsZS5sZW5ndGggPCAyKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG5hbWU6IE1BVENIX0lURU0sXG4gICAgdHlwZTogSXRlbVR5cGUuU2VsZWN0LFxuICAgIGxhYmVsOiAnTWF0Y2gnLFxuICAgIG11bHRpcGxlOiBmYWxzZSxcbiAgICB2YWx1ZXM6ICgpID0+IE1BVENIX09QVElPTlMsXG4gICAgZGVmYXVsdDogbWF0Y2gsXG4gICAgLy8gJ01hdGNoOiBhbnkgZmlsdGVyJyBvciAnTWF0Y2g6IGFsbCBmaWx0ZXJzJywgaW4gdGhlIGV4cG9ydCBsaW5lcycgd29yZHMuXG4gICAgY2hpcFRleHQ6IChpdGVtKSA9PiBtYXRjaExpbmVUZXh0KG1hdGNoRnJvbVF1ZXJ5KGl0ZW0ucXVlcnkpLCAnY2hpcCcpLFxuICB9O1xufVxuXG4vLyBUaGUgbWF0Y2ggYSBjaGFuZ2UgcXVlcnkgb2YgYSBiYXIgd2l0aCB0aGUgTWF0Y2ggY29udHJvbCBhc2tzIGZvci5cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaEZyb21RdWVyeShxdWVyeTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBSZXBvcnRGaWx0ZXJNYXRjaCB7XG4gIHJldHVybiBxdWVyeT8uW01BVENIX0lURU1dID09PSAnYW55JyA/ICdhbnknIDogJ2FsbCc7XG59XG5cbi8vIFRoZSBxdWVyeSBrZXkgb2YgYSBsaXN0J3Mgc2VhcmNoIGJveCBpbiBpdHMgY29tcG9uZW50IGhlYWRlci4gRml4ZWQgcmF0aGVyXG4vLyB0aGFuIGRlcml2ZWQgZnJvbSBhbiBpZCBiZWNhdXNlIGEgaGVhZGVyIGhvbGRzIGF0IG1vc3Qgb25lLCBhbmQgaXQgaXMgTk9UIGFcbi8vIGZpbHRlciBncm91cDogaXRzIHRleHQgbmFycm93cyB0aGF0IGxpc3QgYWxvbmUsIHNvIGl0IGlzIHJlYWQgc3RyYWlnaHQgb2ZmXG4vLyB0aGUgY2hhbmdlIHF1ZXJ5IGFuZCB0cmF2ZWxzIGFzIHRoZSBsaXN0J3Mgb3duIGBzdGF0ZS5zZWFyY2hgLlxuZXhwb3J0IGNvbnN0IExJU1RfU0VBUkNIX0lURU0gPSAnbGlzdFNlYXJjaCc7XG5cbi8vIFRoZSBsb25nZXN0IHNlYXJjaCB0aGUgc2VydmVyIGFwcGxpZXMgKFJlcG9ydFF1ZXJ5UnVubmVyOjpNQVhfU0VBUkNIX0xFTkdUSCkuXG4vLyBUaGUgdmlld2VyIGN1dHMgdGhlIHRleHQgdG8gaXQgdG9vLCBzbyB0aGUgVVJMLCB0aGUgcmVxdWVzdCBhbmQgdGhlIGV4cG9ydFxuLy8gdGl0bGUgYWxsIGNhcnJ5IHRoZSB0ZXh0IHRoYXQgd2FzIGFjdHVhbGx5IHNlYXJjaGVkLlxuZXhwb3J0IGNvbnN0IExJU1RfU0VBUkNIX01BWF9MRU5HVEggPSAxMDA7XG5cbi8vIFRoZSBmcy1maWx0ZXIgY29uZmlnIGl0ZW0gZm9yIGEgbGlzdCdzIHNlYXJjaCBib3gsIHNlZWRlZCB3aXRoIHRoZSB0ZXh0IHRoZVxuLy8gdmlld2VyIGxhc3Qgc2VhcmNoZWQuIGZzLWZpbHRlciBzaG93cyBvbmUgc2VhcmNoIGJveCBwZXIgYmFyIChpdHMgbGFzdFxuLy8ga2V5d29yZCBpdGVtKSwgc28gdGhlIGNhbGxlciBhZGRzIHRoaXMgb25seSB0byBhIGhlYWRlciB3aXRoIG5vIGtleXdvcmRcbi8vIGdyb3VwIG9mIGl0cyBvd24uXG5leHBvcnQgZnVuY3Rpb24gbGlzdFNlYXJjaEl0ZW0odmFsdWU6IHN0cmluZyB8IG51bGwpOiBJRmlsdGVyQ29uZmlnSXRlbSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogSXRlbVR5cGUuS2V5d29yZCxcbiAgICBuYW1lOiBMSVNUX1NFQVJDSF9JVEVNLFxuICAgIGxhYmVsOiAnU2VhcmNoJyxcbiAgICBkZWZhdWx0OiB2YWx1ZSA/PyB1bmRlZmluZWQsXG4gIH07XG59XG5cbi8vIFdoZXRoZXIgdGhlIHJlcG9ydCBoYXMgYSBjaGFydCB0aGUgZ3JvdXAtYnkgY29udHJvbCBjYW4gcmUtYnVja2V0LiBBIHRpbWVcbi8vIHgtYXhpcyBpcyB0aGUgd2hvbGUgcXVhbGlmaWNhdGlvbjogdGhlIGNvbnRyb2wgY2hhbmdlcyB0aGUgZ3JhaW4gb2YgdGhhdFxuLy8gYXhpcywgYW5kIGEgY2F0ZWdvcnkgYXhpcyBoYXMgbm8gZ3JhaW4gdG8gY2hhbmdlLlxuZXhwb3J0IGZ1bmN0aW9uIGhhc1RpbWVTZXJpZXNDaGFydChyZXBvcnQ6IFJlcG9ydCB8IG51bGwpOiBib29sZWFuIHtcbiAgcmV0dXJuIChyZXBvcnQ/LnBhZ2VzID8/IFtdKS5zb21lKChwYWdlKSA9PiAocGFnZS5jb21wb25lbnRzID8/IFtdKS5zb21lKChjb21wb25lbnQpID0+XG4gICAgY29tcG9uZW50LnR5cGUgPT09ICdjaGFydCcgJiYgY29tcG9uZW50LmNvbmZpZz8ueEF4aXM/LmtpbmQgPT09ICd0aW1lJykpO1xufVxuXG4vLyBUaGUgZ3JhaW5zIHRoZSByZXBvcnQncyBncm91cC1ieSBjb250cm9sIG9mZmVycywgbmFtZWQgZm9yIHRoZSB2aWV3ZXIuIFdISUNIXG4vLyBvZiB0aGVtIGNvbWVzIGZyb20gdGhlIHJlcG9ydDsgaG93IHRoZXkgcmVhZCBjb21lcyBmcm9tIEdSQU5VTEFSSVRZX09QVElPTlMuXG4vLyBBbiBlbXB0eSBzdG9yZWQgbGlzdCBtZWFucyBldmVyeSBncmFpbiDigJQgdGhlIHNhbWUgcnVsZSB0aGUgYmFja2VuZCBhcHBsaWVzLlxuZnVuY3Rpb24gZ3JvdXBCeU9wdGlvbnMocmVwb3J0OiBSZXBvcnQpOiB7IHZhbHVlOiBDaGFydEdyYW51bGFyaXR5OyBuYW1lOiBzdHJpbmcgfVtdIHtcbiAgY29uc3QgZ3JhbnVsYXJpdGllcyA9IHJlcG9ydC5jb25maWc/Lmdyb3VwQnk/LmdyYW51bGFyaXRpZXMgPz8gW107XG5cbiAgcmV0dXJuIGdyYW51bGFyaXRpZXMubGVuZ3RoXG4gICAgPyBHUkFOVUxBUklUWV9PUFRJT05TLmZpbHRlcigob3B0aW9uKSA9PiBncmFudWxhcml0aWVzLmluY2x1ZGVzKG9wdGlvbi52YWx1ZSkpXG4gICAgOiBHUkFOVUxBUklUWV9PUFRJT05TO1xufVxuXG4vLyBXaGV0aGVyIGEgZ3JhaW4gaXMgb25lIHRoZSByZXBvcnQncyBjb250cm9sIHN0aWxsIG9mZmVycy4gQSBncmFpbiBpdCBkb2Vzbid0XG4vLyBjYW5ub3Qgc3RheSBpbiBlZmZlY3Q6IHRoZSBhZ2VudCBjYW4gbmFycm93IHRoZSBsaXN0IGF0IGFueSB0aW1lLCBhbmQgYSBjaGFydFxuLy8gbGVmdCBidWNrZXRpbmcgYXQgYSBkcm9wcGVkIGdyYWluIGlzIG9uZSB0aGUgdmlld2VyIGNhbiBuZWl0aGVyIHNlZSBub3IgY2hhbmdlLlxuZXhwb3J0IGZ1bmN0aW9uIGlzR3JhbnVsYXJpdHlPZmZlcmVkKHJlcG9ydDogUmVwb3J0LCBncmFudWxhcml0eTogQ2hhcnRHcmFudWxhcml0eSB8IG51bGwpOiBib29sZWFuIHtcbiAgcmV0dXJuICFncmFudWxhcml0eSB8fCBncm91cEJ5T3B0aW9ucyhyZXBvcnQpLnNvbWUoKG9wdGlvbikgPT4gb3B0aW9uLnZhbHVlID09PSBncmFudWxhcml0eSk7XG59XG5cbi8vIFRoZSBmcy1maWx0ZXIgY29uZmlnIGl0ZW0gZm9yIHRoZSByZXBvcnQncyBncm91cC1ieSBjb250cm9sLCBvciBudWxsIHdoZW4gdGhlXG4vLyByZXBvcnQgaGFzIG5vbmUgdG8gc2hvdy5cbi8vXG4vLyBJdCBsZWFkcyB0aGUgc2FtZSBiYXIgdGhlIGZpbHRlcnMgcmVuZGVyIGluLCBidXQgaXQgaXMgTk9UIG9uZTogYSBmaWx0ZXJcbi8vIG5hcnJvd3MgV0hJQ0ggcm93cyBhcmUgY291bnRlZCwgdGhpcyBjaGFuZ2VzIGhvdyB0aGUgc3Vydml2aW5nIHJvd3MgYXJlXG4vLyBCVUNLRVRFRCDigJQgYW5kIGl0IGNvbWVzIGZpcnN0IGJlY2F1c2UgdGhlIGdyYWluIGlzIHdoYXQgYSB2aWV3ZXIgc2V0dGxlc1xuLy8gYmVmb3JlIGRlY2lkaW5nIHdoaWNoIHJvd3MgdGhleSB3YW50LlxuLy8gUGlja2luZyBhIGdyYWluIHNldHMgYSBzZXNzaW9uLXdpZGUgb3ZlcnJpZGUgdGhhdCByaWRlcyBhbG9uZyBpbiBlYWNoIGNoYXJ0J3Ncbi8vIGRhdGEgcmVxdWVzdCwgc28gdGhlIGNoYXJ0cyB0aGVtc2VsdmVzIGFyZSBuZXZlciByZXdyaXR0ZW4uXG5leHBvcnQgZnVuY3Rpb24gZ3JvdXBCeUZpbHRlckl0ZW0oXG4gIHJlcG9ydDogUmVwb3J0LFxuICBpbml0aWFsPzogQ2hhcnRHcmFudWxhcml0eSB8IG51bGwsXG4pOiBJRmlsdGVyQ29uZmlnSXRlbSB8IG51bGwge1xuICBjb25zdCBncm91cEJ5ID0gcmVwb3J0LmNvbmZpZz8uZ3JvdXBCeTtcblxuICAvLyBPbmx5IGFuIEVYUExJQ0lUIGZhbHNlIGhpZGVzIHRoZSBjb250cm9sLiBBbiBhYnNlbnQgYmxvY2sgbWVhbnMgYSByZXBvcnRcbiAgLy8gc2VydmVkIGJ5IGEgYnVpbGQgdGhhdCBwcmVkYXRlcyB0aGUgY29udHJvbCBiZWluZyBzdG9yZWQsIGFuZCBldmVyeSBvbmUgb2ZcbiAgLy8gdGhvc2UgaGFkIG9uZSDigJQgdGhlIGJhY2tlbmQgcmVzb2x2ZXMgaXQgdGhlIHNhbWUgd2F5IChSZXBvcnRHcm91cEJ5KS5cbiAgaWYgKGdyb3VwQnk/LmVuYWJsZWQgPT09IGZhbHNlIHx8ICFoYXNUaW1lU2VyaWVzQ2hhcnQocmVwb3J0KSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgdmFsdWVzID0gZ3JvdXBCeU9wdGlvbnMocmVwb3J0KTtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6IEdST1VQX0JZX0lURU0sXG4gICAgdHlwZTogSXRlbVR5cGUuU2VsZWN0LFxuICAgIGxhYmVsOiBncm91cEJ5Py5sYWJlbCB8fCAnR3JvdXAgQnknLFxuICAgIG11bHRpcGxlOiBmYWxzZSxcbiAgICB2YWx1ZXM6ICgpID0+IHZhbHVlcyxcbiAgICBkZWZhdWx0OiBpc0dyYW51bGFyaXR5T2ZmZXJlZChyZXBvcnQsIGluaXRpYWwgPz8gbnVsbCkgPyAoaW5pdGlhbCA/PyB1bmRlZmluZWQpIDogdW5kZWZpbmVkLFxuICB9O1xufVxuXG4vLyBUaGUgZ3JvdXAtYnkgY29udHJvbCdzIGNvbnRyaWJ1dGlvbiB0byB0aGUgdG9vbGJhcidzIGZzLWZpbHRlciBrZXkuIGZzLWZpbHRlclxuLy8gcmVhZHMgaXRzIGNvbmZpZyBvbmNlIGF0IGluaXQsIGFuZCB0aGUgYWdlbnQgY2FuIGNoYW5nZSB0aGUgY29udHJvbCdzIGxhYmVsXG4vLyBvciB0aGUgZ3JhaW5zIGl0IG9mZmVycyDigJQgd2l0aG91dCB0aG9zZSBpbiB0aGUga2V5IHRoZSBiYXIga2VlcHMgcmVuZGVyaW5nXG4vLyB0aGUgY29udHJvbCBpdCB3YXMgY3JlYXRlZCB3aXRoIHVudGlsIGEgZnVsbCBwYWdlIHJlbG9hZC5cbmV4cG9ydCBmdW5jdGlvbiBncm91cEJ5U2lnbmF0dXJlKHJlcG9ydDogUmVwb3J0IHwgbnVsbCk6IHN0cmluZyB7XG4gIGlmICghcmVwb3J0IHx8ICFncm91cEJ5RmlsdGVySXRlbShyZXBvcnQpKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgY29uc3QgZ3JvdXBCeSA9IHJlcG9ydC5jb25maWc/Lmdyb3VwQnk7XG5cbiAgcmV0dXJuIFsnZ3JvdXBCeScsIGdyb3VwQnk/LmxhYmVsID8/ICcnLCAoZ3JvdXBCeT8uZ3JhbnVsYXJpdGllcyA/PyBbXSkuam9pbignLCcpXS5qb2luKCc6Jyk7XG59XG5cbi8vIFJlYWQgYW4gZnMtZmlsdGVyIGNoYW5nZSBxdWVyeSBpbnRvIHBlci1ncm91cCB2YWx1ZXMuIFJldHVybnMgb25lIGVudHJ5IHBlclxuLy8gZ3JvdXAgd2l0aCB0aGUgdmFsdWUgdG8gc3RvcmUgKG9yIG51bGwgdG8gY2xlYXIpIOKAlCBjYWxsZXJzIGZlZWQgdGhlc2UgdG9cbi8vIFJlcG9ydEZpbHRlclN0YXRlU2VydmljZS5zZXRWYWx1ZS4gYHJlcG9ydGAgbmFtZXMgdGhlIGdyb3VwcycgaXRlbXMuXG5leHBvcnQgZnVuY3Rpb24gZ3JvdXBWYWx1ZXNGcm9tUXVlcnkoXG4gIHF1ZXJ5OiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICBncm91cHM6IFJlcG9ydEZpbHRlckdyb3VwW10sXG4gIHJlcG9ydDogUmVwb3J0IHwgbnVsbCxcbik6IHsgZ3JvdXBJZDogbnVtYmVyOyB2YWx1ZTogRmlsdGVyR3JvdXBWYWx1ZSB8IG51bGwgfVtdIHtcbiAgcmV0dXJuIGdyb3Vwcy5tYXAoKGdyb3VwKSA9PiB7XG4gICAgY29uc3QgbmFtZSA9IGdyb3VwSXRlbU5hbWUoZ3JvdXAsIHJlcG9ydCk7XG5cbiAgICBzd2l0Y2ggKGdyb3VwLnR5cGUpIHtcbiAgICAgIGNhc2UgJ2RhdGVSYW5nZSc6XG4gICAgICAgIHJldHVybiB7IGdyb3VwSWQ6IGdyb3VwLmlkLCB2YWx1ZTogZGF0ZVJhbmdlRnJvbVF1ZXJ5KHF1ZXJ5LCBuYW1lKSB9O1xuXG4gICAgICBjYXNlICdzZWxlY3QnOlxuICAgICAgICByZXR1cm4geyBncm91cElkOiBncm91cC5pZCwgdmFsdWU6IHNlbGVjdEZyb21RdWVyeShxdWVyeSwgbmFtZSkgfTtcblxuICAgICAgY2FzZSAnbnVtYmVyUmFuZ2UnOlxuICAgICAgICByZXR1cm4geyBncm91cElkOiBncm91cC5pZCwgdmFsdWU6IG51bWJlclJhbmdlRnJvbVF1ZXJ5KHF1ZXJ5LCBuYW1lKSB9O1xuXG4gICAgICBkZWZhdWx0OiB7XG4gICAgICAgIGNvbnN0IGtleXdvcmQgPSBTdHJpbmcocXVlcnlbbmFtZV0gPz8gJycpLnRyaW0oKTtcblxuICAgICAgICByZXR1cm4geyBncm91cElkOiBncm91cC5pZCwgdmFsdWU6IGtleXdvcmQgPyB7IHZhbHVlOiBrZXl3b3JkIH0gOiBudWxsIH07XG4gICAgICB9XG4gICAgfVxuICB9KTtcbn1cblxuLy8gQSBkYXRlIHJhbmdlJ3MgZGF5cyAoPGtleT5Gcm9tLCA8a2V5PlRvKS5cbmZ1bmN0aW9uIGRhdGVSYW5nZUZyb21RdWVyeShxdWVyeTogUmVjb3JkPHN0cmluZywgYW55PiwgbmFtZTogc3RyaW5nKTogRmlsdGVyR3JvdXBWYWx1ZSB8IG51bGwge1xuICBjb25zdCBzdGFydCA9IHF1ZXJ5W2l0ZW1SYW5nZU5hbWUobmFtZSwgJ2Zyb20nKV07XG4gIGNvbnN0IGVuZCA9IHF1ZXJ5W2l0ZW1SYW5nZU5hbWUobmFtZSwgJ3RvJyldO1xuXG4gIGlmICghc3RhcnQgJiYgIWVuZCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHsgc3RhcnQ6IHN0YXJ0IHx8IG51bGwsIGVuZDogZW5kIHx8IG51bGwgfTtcbn1cblxuLy8gQSBzZWxlY3QncyBwaWNrczoga2VwdCAoPGtleT4pLCBvciBsZWZ0IG91dCB3aGlsZSBpdHMgZXhjbHVkZSByb3cgaXMgb25cbi8vIChleGNsdWRlPEtleT4pLlxuZnVuY3Rpb24gc2VsZWN0RnJvbVF1ZXJ5KHF1ZXJ5OiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBuYW1lOiBzdHJpbmcpOiBGaWx0ZXJHcm91cFZhbHVlIHwgbnVsbCB7XG4gIGNvbnN0IGV4Y2x1ZGVWYWx1ZXMgPSBzZWxlY3RRdWVyeVZhbHVlcyhxdWVyeVtnZXRFeGNsdWRlTmFtZShuYW1lKV0pO1xuICBpZiAoZXhjbHVkZVZhbHVlcy5sZW5ndGgpIHtcbiAgICByZXR1cm4geyBleGNsdWRlVmFsdWVzIH07XG4gIH1cblxuICBjb25zdCB2YWx1ZXMgPSBzZWxlY3RRdWVyeVZhbHVlcyhxdWVyeVtuYW1lXSk7XG5cbiAgcmV0dXJuIHZhbHVlcy5sZW5ndGggPyB7IHZhbHVlcyB9IDogbnVsbDtcbn1cblxuLy8gQSBudW1iZXIgcmFuZ2UncyBlbmRzICg8a2V5Pk1pbiwgPGtleT5NYXgpLiBBbiBlbmQgbGVmdCBlbXB0eSBpcyBvcGVuLlxuZnVuY3Rpb24gbnVtYmVyUmFuZ2VGcm9tUXVlcnkocXVlcnk6IFJlY29yZDxzdHJpbmcsIGFueT4sIG5hbWU6IHN0cmluZyk6IEZpbHRlckdyb3VwVmFsdWUgfCBudWxsIHtcbiAgY29uc3QgbWluID0gcmFuZ2VCb3VuZChxdWVyeVtpdGVtUmFuZ2VOYW1lKG5hbWUsICdtaW4nKV0pO1xuICBjb25zdCBtYXggPSByYW5nZUJvdW5kKHF1ZXJ5W2l0ZW1SYW5nZU5hbWUobmFtZSwgJ21heCcpXSk7XG5cbiAgaWYgKG1pbiA9PT0gbnVsbCAmJiBtYXggPT09IG51bGwpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgLi4uKG1pbiAhPT0gbnVsbCA/IHsgbWluIH0gOiB7fSksXG4gICAgLi4uKG1heCAhPT0gbnVsbCA/IHsgbWF4IH0gOiB7fSksXG4gIH07XG59XG5cbi8vIE9uZSBlbmQgb2YgYSBudW1iZXIgcmFuZ2UgYXMgZnMtZmlsdGVyJ3MgUmFuZ2Ugc2VuZHMgaXQ6IHRoZSB0ZXh0IHR5cGVkIGluXG4vLyBpdHMgaW5wdXQuIE51bWJlcigpIHJlYWRzIGFueSBub24tZW1wdHkgdGV4dCwgc28gJzAnIGlzIHRoZSBlbmQgMDsgZW1wdHkgb3Jcbi8vIHVucmVhZGFibGUgdGV4dCBpcyBhbiBvcGVuIGVuZC5cbmZ1bmN0aW9uIHJhbmdlQm91bmQocmF3OiB1bmtub3duKTogbnVtYmVyIHwgbnVsbCB7XG4gIGNvbnN0IHRleHQgPSB0eXBlb2YgcmF3ID09PSAnbnVtYmVyJyA/IFN0cmluZyhyYXcpIDogU3RyaW5nKHJhdyA/PyAnJykudHJpbSgpO1xuICBjb25zdCBudW1iZXIgPSB0ZXh0ID09PSAnJyA/IE5hTiA6IE51bWJlcih0ZXh0KTtcblxuICByZXR1cm4gTnVtYmVyLmlzRmluaXRlKG51bWJlcikgPyBudW1iZXIgOiBudWxsO1xufVxuXG4vLyBBIGdyb3VwIHZhbHVlIGFzIHRleHQsIHRoZSBzYW1lIGZvciB0aGUgc2FtZSB2YWx1ZSB3aGF0ZXZlciBpdHMgc291cmNlOlxuLy8gZGF5cyBhcyBjYWxlbmRhciBkYXlzLCBwaWNrcyBhbmQgZW5kcyBhcyB0ZXh0LCBrZXl3b3JkIHRleHQgdHJpbW1lZC4gVGhlXG4vLyB2YWx1ZSBhIHRpbGUgaGVhZGVyIHdhcyBidWlsdCB3aXRoIGlzIGtleWVkIG9uIGl0LCBzbyBhIGhlYWRlciBpcyBjcmVhdGVkXG4vLyBhZ2FpbiB3aGVuIGFub3RoZXIgYmFyIGNoYW5nZXMgYSBncm91cCBpdCBzaG93cy5cbmV4cG9ydCBmdW5jdGlvbiBncm91cFZhbHVlU2lnbmF0dXJlKHZhbHVlOiBGaWx0ZXJHcm91cFZhbHVlIHwgbnVsbCB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG4gIGlmICghdmFsdWUpIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoW1xuICAgIGRhdGVCb3VuZFN0cmluZyh2YWx1ZS5zdGFydCkgPz8gJycsXG4gICAgZGF0ZUJvdW5kU3RyaW5nKHZhbHVlLmVuZCkgPz8gJycsXG4gICAgKHZhbHVlLnZhbHVlcyA/PyBbXSkubWFwKFN0cmluZyksXG4gICAgKHZhbHVlLmV4Y2x1ZGVWYWx1ZXMgPz8gW10pLm1hcChTdHJpbmcpLFxuICAgICh2YWx1ZS52YWx1ZSA/PyAnJykudHJpbSgpLFxuICAgIHZhbHVlLm1pbiA/PyAnJyxcbiAgICB2YWx1ZS5tYXggPz8gJycsXG4gIF0pO1xufVxuXG4vLyBmcy1maWx0ZXIncyBBdXRvQ29tcGxldGVDaGlwcyBzZXJpYWxpc2VzIGEgbXVsdGktc2VsZWN0IGludG8gT05FIHF1ZXJ5IHZhbHVlOlxuLy8gdGhlIHNlbGVjdGVkIHZhbHVlcyBqb2luZWQgYnkgXCIsXCIgKGl0cyBgcXVlcnlgIGdldHRlciBkb2VzIGAubWFwKHZhbHVlKS5qb2luKCcsJylgKS5cbi8vIFNvIGEgMisgc2VsZWN0aW9uIGFycml2ZXMgYXMgdGhlIHN0cmluZyBcImEsYlwiLCBub3QgYW4gYXJyYXkg4oCUIHNwbGl0dGluZyBvbiBcIixcIlxuLy8gcmV2ZXJzZXMgdGhhdCBmYWl0aGZ1bGx5LiBXaXRob3V0IHRoaXMsIGEgbXVsdGktc2VsZWN0IHdhcyBzZW50IGFzIHRoZSBzaW5nbGVcbi8vIHZhbHVlIFtcImEsYlwiXSwgcHJvZHVjaW5nIGBjb2wgSU4gKCdhLGInKWAgc2VydmVyLXNpZGUsIHdoaWNoIG1hdGNoZXMgbm90aGluZy5cbmZ1bmN0aW9uIHNlbGVjdFF1ZXJ5VmFsdWVzKHJhdzogdW5rbm93bik6IHVua25vd25bXSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHJhdykpIHtcbiAgICByZXR1cm4gcmF3O1xuICB9XG5cbiAgaWYgKHJhdyA9PT0gbnVsbCB8fCByYXcgPT09IHVuZGVmaW5lZCB8fCByYXcgPT09ICcnKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgcmV0dXJuIFN0cmluZyhyYXcpLnNwbGl0KCcsJyk7XG59XG4iXX0=