@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
@@ -4,12 +4,49 @@
4
4
  // A block's html arrives already rebuilt server-side from a small allowlist
5
5
  // (ReportTextHtml): p, h1-h3, strong, em, u, s, ul/ol/li, br, a, and span with
6
6
  // color / background-color / font-size / font-weight / font-family, plus
7
- // text-align on a block. Everything here only has to understand that set.
7
+ // text-align on a block. A table may sit at the top level of a block: table,
8
+ // thead, tbody, tfoot, tr, th and td, a width on the table, and on a cell
9
+ // text-align, vertical-align, background-color, a width and a colspan or
10
+ // rowspan. Its grid lines, padding and margin are never stored: every renderer
11
+ // draws them from the TEXT_TABLE_* constants below. Transparent, currentcolor
12
+ // and the CSS-wide keywords (inherit, initial, …) are not colors, so the
13
+ // server drops them and hexColor reads them as no color. Everything here only
14
+ // has to understand that set.
8
15
  // Body text size, points, and the heading sizes — the same numbers the canvas
9
16
  // stylesheet uses, so an unstyled paragraph is one size everywhere.
10
17
  export const DEFAULT_TEXT_SIZE = 12;
11
18
  export const HEADING_TEXT_SIZES = { 1: 24, 2: 18, 3: 14 };
12
19
  export const DEFAULT_TEXT_COLOR = '#1f2933';
20
+ // A table's grid lines: their color, and their width in points (0.75pt is one
21
+ // pixel on the canvas). The html never stores borders or padding
22
+ // (ReportTextHtml drops them), so the canvas, the editor and both exports all
23
+ // draw this one look.
24
+ export const TEXT_TABLE_BORDER_COLOR = '#cbd2d9';
25
+ export const TEXT_TABLE_BORDER_WIDTH = 0.75;
26
+ // The space between a cell's grid lines and its words, in points.
27
+ export const TEXT_TABLE_CELL_PADDING = { vertical: 2, horizontal: 4 };
28
+ // The space above and below a table, between it and the words around it, in
29
+ // points.
30
+ export const TEXT_TABLE_MARGIN = 4;
31
+ // A value token: {{value.total_visits}}. Keys are lowercase letters, digits and
32
+ // underscores, starting with a letter.
33
+ export const VALUE_TOKEN_PATTERN = /\{\{\s*value\.([a-z][a-z0-9_]*)\s*\}\}/gi;
34
+ // What a value with no number reads as — it failed, it is not on this page, or
35
+ // its query found nothing — so a block never prints a raw token.
36
+ export const VALUE_EMPTY_TEXT = '—';
37
+ // What a value reads as while its number is on its way (on screen only: an
38
+ // export waits for every number).
39
+ export const VALUE_LOADING_TEXT = '…';
40
+ export function valueToken(key) {
41
+ return `{{value.${key}}}`;
42
+ }
43
+ // What a value reads as in a block, viewed or edited: its formatted number,
44
+ // the ellipsis while that loads, else the em dash.
45
+ export function valueText(value) {
46
+ return value?.text ?? (value?.loading ? VALUE_LOADING_TEXT : VALUE_EMPTY_TEXT);
47
+ }
48
+ // What a table's cells are joined by where it reads as lines of text.
49
+ const TABLE_CELL_SEPARATOR = ' · ';
13
50
  // The tokens a block may carry, with what fills each. {{page.number}} is the
14
51
  // page's position among the report's pages (1-based), which is what makes a
15
52
  // shared footer number every page correctly.
@@ -19,23 +56,46 @@ const TOKENS = {
19
56
  'report.name': (context) => context.reportName,
20
57
  };
21
58
  // Replace every {{token}} in the html. Values are html-escaped: a page named
22
- // "R&D <draft>" must read as that, not as markup.
59
+ // "R&D <draft>" must read as that, not as markup. A {{value.<key>}} token reads
60
+ // as its formatted number, the ellipsis while that loads, else the em dash.
23
61
  export function fillTextTokens(html, context) {
24
- return html.replace(/\{\{\s*([a-z.]+)\s*\}\}/gi, (match, token) => {
62
+ return html
63
+ .replace(VALUE_TOKEN_PATTERN, (match, key) => escapeHtml(valueText(context.values?.[key.toLowerCase()])))
64
+ .replace(/\{\{\s*([a-z.]+)\s*\}\}/gi, (match, token) => {
25
65
  const fill = TOKENS[token.toLowerCase()];
26
66
  return fill ? escapeHtml(fill(context)) : match;
27
67
  });
28
68
  }
29
- // Walk a block's html into paragraphs of styled runs — the shape both exports
30
- // draw from. Tokens are filled first so a page number is just text by then.
31
- export function textParagraphs(html, context) {
69
+ // Walk a block's html into what the exports draw: the words between its tables
70
+ // as paragraphs of styled runs, and each table as a grid of cells. Tokens are
71
+ // filled first so a page number is just text by then. There is a text part for
72
+ // every run of nodes splitAtTables finds, even one that holds no words, so the
73
+ // nth text part is the nth run the export's DOM measure finds.
74
+ export function textBlocks(html, context) {
32
75
  const document = new DOMParser().parseFromString(`<body>${fillTextTokens(html, context)}</body>`, 'text/html');
33
- const paragraphs = [];
34
- walkBlocks(document.body, paragraphs, null);
35
- return paragraphs.filter((paragraph, index) =>
36
- // Keep an empty paragraph between two others (a deliberate blank line), but
37
- // not one left dangling at either end.
38
- paragraph.runs.length || (index > 0 && index < paragraphs.length - 1));
76
+ const blocks = splitAtTables(document.body).map((part) => {
77
+ if (!Array.isArray(part)) {
78
+ return { kind: 'table', table: parseTable(part) };
79
+ }
80
+ const fragment = document.createDocumentFragment();
81
+ const paragraphs = [];
82
+ fragment.append(...part);
83
+ walkBlocks(fragment, paragraphs, null);
84
+ return { kind: 'text', paragraphs };
85
+ });
86
+ trimBlankEnd(blocks);
87
+ return blocks;
88
+ }
89
+ // The block as paragraphs alone, for anything that draws no grid: a table reads
90
+ // as a line per row, its cells' words joined by ' · '.
91
+ export function textParagraphs(html, context) {
92
+ return blockParagraphs(textBlocks(html, context));
93
+ }
94
+ // Blocks textBlocks already walked, as textParagraphs reads them.
95
+ export function blockParagraphs(blocks) {
96
+ return blocks.flatMap((block) => block.kind === 'text'
97
+ ? block.paragraphs
98
+ : block.table.rows.map(rowParagraph));
39
99
  }
40
100
  // The html as plain text — what a block says, for anything that cannot style it.
41
101
  export function textPlain(html, context) {
@@ -43,85 +103,218 @@ export function textPlain(html, context) {
43
103
  .map((paragraph) => paragraph.runs.map((run) => run.text).join(''))
44
104
  .join('\n');
45
105
  }
46
- function walkBlocks(parent, paragraphs, list) {
47
- // Loose inline content between blocks (text straight under <body> or <li>)
48
- // is gathered into a paragraph of its own.
106
+ // A block's top-level nodes split at each table: each table on its own, and
107
+ // each run of the nodes between them as a list. A table sits only at the top
108
+ // level (ReportTextHtml flattens any other), so this is the whole split.
109
+ // textBlocks and the export's measure of the rendered block both split here.
110
+ export function splitAtTables(parent) {
111
+ const parts = [];
112
+ let run = null;
113
+ parent.childNodes.forEach((node) => {
114
+ if (node.nodeName === 'TABLE') {
115
+ parts.push(node);
116
+ run = null;
117
+ }
118
+ else if (run) {
119
+ run.push(node);
120
+ }
121
+ else {
122
+ run = [node];
123
+ parts.push(run);
124
+ }
125
+ });
126
+ return parts;
127
+ }
128
+ // A table as a grid of cells, each holding its words as paragraphs. Rows come
129
+ // as a browser draws them, the head first and the foot last, whatever order the
130
+ // html writes its sections in.
131
+ export function parseTable(element) {
132
+ const rows = Array.from(element.rows, (row) => ({
133
+ section: tableSection(row),
134
+ cells: Array.from(row.cells, tableCell),
135
+ }));
136
+ return tableGrid({ rows, columns: 0 });
137
+ }
138
+ // Where each cell sits, by the HTML table algorithm: a cell takes the first
139
+ // column of its row that no cell spanning down from a row above holds. A rowspan
140
+ // stops at the last row of its section, as a browser draws it, and the grid is
141
+ // as wide as the widest right edge of any cell.
142
+ export function tableGrid(table) {
143
+ const taken = table.rows.map(() => []);
144
+ let columns = 0;
145
+ const rows = table.rows.map((row, index) => {
146
+ const sectionEnd = rowSectionEnd(table.rows, index);
147
+ let column = 0;
148
+ const cells = row.cells.map((cell) => {
149
+ while (taken[index][column]) {
150
+ column++;
151
+ }
152
+ const placed = { ...cell, row: index, column, rowSpan: Math.min(cell.rowSpan, sectionEnd - index) };
153
+ occupy(taken, placed);
154
+ column += placed.colSpan;
155
+ columns = Math.max(columns, column);
156
+ return placed;
157
+ });
158
+ return { ...row, cells };
159
+ });
160
+ return { rows, columns };
161
+ }
162
+ function tableSection(row) {
163
+ const section = row.parentElement?.nodeName;
164
+ return section === 'THEAD' ? 'head' : section === 'TFOOT' ? 'foot' : 'body';
165
+ }
166
+ // One th or td. A header cell's runs are bold, and every paragraph takes the
167
+ // cell's text-align unless it has its own: the default look centers a header
168
+ // cell and puts any other on the left.
169
+ function tableCell(cell) {
170
+ const header = cell.nodeName === 'TH';
171
+ const align = cellAlign(cell.style.textAlign) ?? (header ? 'center' : 'left');
172
+ const valign = cell.style.verticalAlign;
173
+ const paragraphs = [];
174
+ walkBlocks(cell, paragraphs, null, header ? { bold: true } : {});
175
+ return {
176
+ paragraphs: paragraphs.map((paragraph) => ({ ...paragraph, align: paragraph.align ?? align })),
177
+ colSpan: Math.max(1, cell.colSpan),
178
+ rowSpan: Math.max(1, cell.rowSpan),
179
+ row: 0,
180
+ column: 0,
181
+ align,
182
+ valign: valign === 'top' || valign === 'middle' || valign === 'bottom' ? valign : undefined,
183
+ fill: cell.style.backgroundColor ? hexColor(cell.style.backgroundColor) : undefined,
184
+ };
185
+ }
186
+ function cellAlign(value) {
187
+ return value === 'left' || value === 'center' || value === 'right' || value === 'justify' ? value : undefined;
188
+ }
189
+ // The index just past the last row of the section the row at index sits in.
190
+ function rowSectionEnd(rows, index) {
191
+ let end = index + 1;
192
+ while (end < rows.length && rows[end].section === rows[index].section) {
193
+ end++;
194
+ }
195
+ return end;
196
+ }
197
+ // Mark the grid slots a placed cell covers.
198
+ function occupy(taken, cell) {
199
+ for (let row = cell.row; row < cell.row + cell.rowSpan; row++) {
200
+ for (let column = cell.column; column < cell.column + cell.colSpan; column++) {
201
+ taken[row][column] = true;
202
+ }
203
+ }
204
+ }
205
+ // A table row as one line of text: its cells in order, a cell's own lines
206
+ // joined by a space.
207
+ function rowParagraph(row) {
208
+ return {
209
+ runs: row.cells.flatMap((cell, index) => [
210
+ ...(index ? [{ text: TABLE_CELL_SEPARATOR }] : []),
211
+ ...cell.paragraphs.flatMap((paragraph, line) => [...(line ? [{ text: ' ' }] : []), ...paragraph.runs]),
212
+ ]),
213
+ };
214
+ }
215
+ // An empty paragraph is a blank line the canvas draws (<p><br></p>, or an empty
216
+ // <p>), so one at the start of the block keeps the words below it where the
217
+ // canvas puts them. At the end of the whole block it draws nothing, and is
218
+ // dropped so it never counts as running past the box. An empty paragraph
219
+ // before a table is not at the end.
220
+ function trimBlankEnd(blocks) {
221
+ const last = blocks[blocks.length - 1];
222
+ while (last?.kind === 'text' && last.paragraphs.length && !last.paragraphs[last.paragraphs.length - 1].runs.length) {
223
+ last.paragraphs.pop();
224
+ }
225
+ }
226
+ // base is the style every run starts from: bold for a header cell's words.
227
+ function walkBlocks(parent, paragraphs, list, base = {}) {
228
+ // Loose inline content between blocks (text straight under the block, an
229
+ // <li> or a cell) is gathered into a paragraph of its own.
49
230
  let loose = null;
50
231
  const flush = () => {
51
- if (loose) {
232
+ if (loose && isShown(loose)) {
52
233
  paragraphs.push(loose);
53
- loose = null;
54
234
  }
235
+ loose = null;
55
236
  };
56
237
  parent.childNodes.forEach((node) => {
57
238
  const name = node.nodeName.toLowerCase();
58
- if (name === 'ul' || name === 'ol') {
59
- flush();
60
- walkBlocks(node, paragraphs, name === 'ul' ? 'bullet' : 'number');
61
- return;
62
- }
63
- if (name === 'li') {
239
+ if (name === 'ul' || name === 'ol' || name === 'li' || name === 'p' || /^h[1-3]$/.test(name)) {
64
240
  flush();
65
- const item = { runs: [], bullet: list ?? 'bullet' };
66
- const nested = [];
67
- // A list item's first paragraph IS the item; anything after it is its own
68
- // line under the same bullet.
69
- walkBlocks(node, nested, list);
70
- const [first, ...rest] = nested.length ? nested : [item];
71
- paragraphs.push({ ...first, bullet: list ?? 'bullet' }, ...rest);
72
- return;
73
- }
74
- if (name === 'p' || /^h[1-3]$/.test(name)) {
75
- flush();
76
- const element = node;
77
- const heading = name.startsWith('h') ? Number(name[1]) : undefined;
78
- const paragraph = {
79
- runs: [],
80
- align: blockAlign(element),
81
- bullet: undefined,
82
- heading,
83
- };
84
- const base = heading
85
- ? { bold: true, fontSize: HEADING_TEXT_SIZES[heading] }
86
- : {};
87
- walkInline(node, base, paragraph, paragraphs);
88
- paragraphs.push(paragraph);
241
+ walkBlock(node, paragraphs, list, base);
89
242
  return;
90
243
  }
91
244
  loose = loose ?? { runs: [] };
92
- walkInline(node, {}, loose, paragraphs, true);
245
+ walkInline(node, base, loose, paragraphs, true);
93
246
  });
94
247
  flush();
95
248
  }
249
+ // Whether loose content's last line shows anything. Whitespace alone between
250
+ // blocks is not drawn, and a line a <br> ended was pushed when it ended, so a
251
+ // trailing <br> adds no empty line after it.
252
+ function isShown(loose) {
253
+ return loose.runs.some((run) => /[^ \t\n\r\f]/.test(run.text));
254
+ }
255
+ function walkBlock(element, paragraphs, list, base) {
256
+ const name = element.nodeName.toLowerCase();
257
+ if (name === 'ul' || name === 'ol') {
258
+ walkBlocks(element, paragraphs, name === 'ul' ? 'bullet' : 'number', base);
259
+ }
260
+ else if (name === 'li') {
261
+ const item = { runs: [], bullet: list ?? 'bullet' };
262
+ const nested = [];
263
+ // A list item's first paragraph IS the item; anything after it is its own
264
+ // line under the same bullet.
265
+ walkBlocks(element, nested, list, base);
266
+ const [first, ...rest] = nested.length ? nested : [item];
267
+ paragraphs.push({ ...first, bullet: list ?? 'bullet' }, ...rest);
268
+ }
269
+ else {
270
+ walkParagraph(element, paragraphs, base);
271
+ }
272
+ }
273
+ // A p or a heading. A <br> ends a line, so its last line is pushed only when it
274
+ // holds words or no <br> came before it: <p><br></p> is one blank line,
275
+ // <p>a<br></p> one line and <p>a<br>b</p> two, as a browser draws them.
276
+ function walkParagraph(element, paragraphs, base) {
277
+ const name = element.nodeName.toLowerCase();
278
+ const heading = name.startsWith('h') ? Number(name[1]) : undefined;
279
+ const paragraph = {
280
+ runs: [],
281
+ align: blockAlign(element),
282
+ bullet: undefined,
283
+ heading,
284
+ };
285
+ const style = heading
286
+ ? { ...base, bold: true, fontSize: HEADING_TEXT_SIZES[heading] }
287
+ : base;
288
+ const breaks = walkInline(element, style, paragraph, paragraphs);
289
+ if (paragraph.runs.length || !breaks) {
290
+ paragraphs.push(paragraph);
291
+ }
292
+ }
96
293
  // Accumulate inline styles down the tree. A <br> ends the current line: the
97
294
  // runs after it start a new paragraph with the same alignment and bullet.
295
+ // Returns how many lines a <br> ended.
98
296
  function walkInline(node, style, paragraph, paragraphs, isSelf = false) {
99
- const visit = (child) => {
100
- if (child.nodeType === Node.TEXT_NODE) {
101
- const text = child.textContent ?? '';
102
- if (text) {
103
- paragraph.runs.push({ ...style, text });
104
- }
105
- return;
106
- }
107
- if (child.nodeType !== Node.ELEMENT_NODE) {
108
- return;
109
- }
110
- const element = child;
111
- const name = element.nodeName.toLowerCase();
112
- if (name === 'br') {
113
- paragraphs.push({ ...paragraph, runs: [...paragraph.runs] });
114
- paragraph.runs.length = 0;
115
- return;
297
+ const nodes = isSelf ? [node] : Array.from(node.childNodes);
298
+ return nodes.reduce((breaks, child) => breaks + walkInlineNode(child, style, paragraph, paragraphs), 0);
299
+ }
300
+ function walkInlineNode(node, style, paragraph, paragraphs) {
301
+ if (node.nodeType === Node.TEXT_NODE) {
302
+ const text = node.textContent ?? '';
303
+ if (text) {
304
+ paragraph.runs.push({ ...style, text });
116
305
  }
117
- walkInline(element, { ...style, ...inlineStyle(element) }, paragraph, paragraphs);
118
- };
119
- if (isSelf) {
120
- visit(node);
306
+ return 0;
121
307
  }
122
- else {
123
- node.childNodes.forEach(visit);
308
+ if (node.nodeType !== Node.ELEMENT_NODE) {
309
+ return 0;
310
+ }
311
+ const element = node;
312
+ if (element.nodeName.toLowerCase() === 'br') {
313
+ paragraphs.push({ ...paragraph, runs: [...paragraph.runs] });
314
+ paragraph.runs.length = 0;
315
+ return 1;
124
316
  }
317
+ return walkInline(element, { ...style, ...inlineStyle(element) }, paragraph, paragraphs);
125
318
  }
126
319
  function inlineStyle(element) {
127
320
  const name = element.nodeName.toLowerCase();
@@ -142,12 +335,15 @@ function inlineStyle(element) {
142
335
  style.link = element.getAttribute('href') ?? undefined;
143
336
  style.underline = true;
144
337
  }
338
+ // What is no color leaves the color the run inherits.
145
339
  const css = element.style;
146
- if (css.color) {
147
- style.color = hexColor(css.color);
340
+ const color = css.color ? hexColor(css.color) : undefined;
341
+ const highlight = css.backgroundColor ? hexColor(css.backgroundColor) : undefined;
342
+ if (color) {
343
+ style.color = color;
148
344
  }
149
- if (css.backgroundColor) {
150
- style.highlight = hexColor(css.backgroundColor);
345
+ if (highlight) {
346
+ style.highlight = highlight;
151
347
  }
152
348
  if (css.fontSize) {
153
349
  style.fontSize = points(css.fontSize);
@@ -192,24 +388,36 @@ function points(value) {
192
388
  }
193
389
  // Any CSS color the allowlist lets through (hex, rgb(), a name) as #rrggbb —
194
390
  // the one form both exports accept. The browser resolves it, so a named color
195
- // comes out exactly as the canvas painted it.
391
+ // comes out exactly as the canvas painted it. A value that is no color of its
392
+ // own (inherit, currentcolor, a typo) or paints nothing (transparent, an alpha
393
+ // of 0) is undefined, so an export never paints it black.
196
394
  let colorContext = null;
197
395
  function hexColor(value) {
198
396
  colorContext = colorContext ?? document.createElement('canvas').getContext('2d');
199
- if (!colorContext) {
397
+ if (!colorContext || /^\s*currentcolor\s*$/i.test(value)) {
398
+ return undefined;
399
+ }
400
+ // A value the canvas cannot read leaves the color set before it, so it reads
401
+ // back one way over black and another over white. (currentcolor reads as
402
+ // black over both, hence the check above.)
403
+ const resolved = resolveColor(colorContext, '#000000', value);
404
+ if (resolved !== resolveColor(colorContext, '#ffffff', value)) {
200
405
  return undefined;
201
406
  }
202
- colorContext.fillStyle = '#000000';
203
- colorContext.fillStyle = value;
204
- const resolved = String(colorContext.fillStyle);
205
407
  if (resolved.startsWith('#')) {
206
408
  return resolved;
207
409
  }
208
410
  // rgba(...) for a translucent color — drop the alpha, keep the hue.
209
- const channels = resolved.match(/[\d.]+/g)?.slice(0, 3).map(Number) ?? [];
210
- return channels.length === 3
211
- ? `#${channels.map((channel) => Math.round(channel).toString(16).padStart(2, '0')).join('')}`
212
- : undefined;
411
+ const [red, green, blue, alpha] = resolved.match(/[\d.]+/g)?.map(Number) ?? [];
412
+ return blue === undefined || alpha === 0
413
+ ? undefined
414
+ : `#${[red, green, blue].map((channel) => Math.round(channel).toString(16).padStart(2, '0')).join('')}`;
415
+ }
416
+ // What the canvas reads value as, set over seed.
417
+ function resolveColor(context, seed, value) {
418
+ context.fillStyle = seed;
419
+ context.fillStyle = value;
420
+ return String(context.fillStyle);
213
421
  }
214
422
  export function escapeHtml(value) {
215
423
  return value
@@ -218,4 +426,4 @@ export function escapeHtml(value) {
218
426
  .replace(/>/g, '&gt;')
219
427
  .replace(/"/g, '&quot;');
220
428
  }
221
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4dC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy90ZXh0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDRFQUE0RTtBQUM1RSw4Q0FBOEM7QUFDOUMsRUFBRTtBQUNGLDRFQUE0RTtBQUM1RSwrRUFBK0U7QUFDL0UseUVBQXlFO0FBQ3pFLDBFQUEwRTtBQUcxRSw4RUFBOEU7QUFDOUUsb0VBQW9FO0FBQ3BFLE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLEVBQUUsQ0FBQztBQUNwQyxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBMkIsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ2xGLE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLFNBQVMsQ0FBQztBQWlDNUMsNkVBQTZFO0FBQzdFLDRFQUE0RTtBQUM1RSw2Q0FBNkM7QUFDN0MsTUFBTSxNQUFNLEdBQTBEO0lBQ3BFLGFBQWEsRUFBRSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUM7SUFDdEQsV0FBVyxFQUFFLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsUUFBUTtJQUMxQyxhQUFhLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFVO0NBQy9DLENBQUM7QUFFRiw2RUFBNkU7QUFDN0Usa0RBQWtEO0FBQ2xELE1BQU0sVUFBVSxjQUFjLENBQUMsSUFBWSxFQUFFLE9BQXlCO0lBQ3BFLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQywyQkFBMkIsRUFBRSxDQUFDLEtBQUssRUFBRSxLQUFhLEVBQUUsRUFBRTtRQUN4RSxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFFekMsT0FBTyxJQUFJLENBQUMs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UyxHQUFHLFNBQVMsQ0FBQztJQUNuQyxZQUFZLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztJQUMvQixNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRWhELElBQUksUUFBUSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQzdCLE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFFRCxvRUFBb0U7SUFDcEUsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7SUFFMUUsT0FBTyxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUM7UUFDMUIsQ0FBQyxDQUFDLElBQUksUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRTtRQUM3RixDQUFDLENBQUMsU0FBUyxDQUFDO0FBQ2hCLENBQUM7QUFFRCxNQUFNLFVBQVUsVUFBVSxDQUFDLEtBQWE7SUFDdEMsT0FBTyxLQUFLO1NBQ1QsT0FBTyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUM7U0FDdEIsT0FBTyxDQUFDLElBQUksRUFBRSxNQUFNLENBQUM7U0FDckIsT0FBTyxDQUFDLElBQUksRUFBRSxNQUFNLENBQUM7U0FDckIsT0FBTyxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQztBQUM3QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gVGV4dCBibG9ja3Mg4oCUIHNoYXJlZCBieSB0aGUgY2FudmFzIGFuZCBib3RoIGV4cG9ydHMsIHNvIGEgYmxvY2sgcmVhZHMgdGhlXG4vLyBzYW1lIG9uIHNjcmVlbiwgaW4gdGhlIGRlY2sgYW5kIGluIHRoZSBQREYuXG4vL1xuLy8gQSBibG9jaydzIGh0bWwgYXJyaXZlcyBhbHJlYWR5IHJlYnVpbHQgc2VydmVyLXNpZGUgZnJvbSBhIHNtYWxsIGFsbG93bGlzdFxuLy8gKFJlcG9ydFRleHRIdG1sKTogcCwgaDEtaDMsIHN0cm9uZywgZW0sIHUsIHMsIHVsL29sL2xpLCBiciwgYSwgYW5kIHNwYW4gd2l0aFxuLy8gY29sb3IgLyBiYWNrZ3JvdW5kLWNvbG9yIC8gZm9udC1zaXplIC8gZm9udC13ZWlnaHQgLyBmb250LWZhbWlseSwgcGx1c1xuLy8gdGV4dC1hbGlnbiBvbiBhIGJsb2NrLiBFdmVyeXRoaW5nIGhlcmUgb25seSBoYXMgdG8gdW5kZXJzdGFuZCB0aGF0IHNldC5cblxuXG4vLyBCb2R5IHRleHQgc2l6ZSwgcG9pbnRzLCBhbmQgdGhlIGhlYWRpbmcgc2l6ZXMg4oCUIHRoZSBzYW1lIG51bWJlcnMgdGhlIGNhbnZhc1xuLy8gc3R5bGVzaGVldCB1c2VzLCBzbyBhbiB1bnN0eWxlZCBwYXJhZ3JhcGggaXMgb25lIHNpemUgZXZlcnl3aGVyZS5cbmV4cG9ydCBjb25zdCBERUZBVUxUX1RFWFRfU0laRSA9IDEyO1xuZXhwb3J0IGNvbnN0IEhFQURJTkdfVEVYVF9TSVpFUzogUmVjb3JkPG51bWJlciwgbnVtYmVyPiA9IHsgMTogMjQsIDI6IDE4LCAzOiAxNCB9O1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfVEVYVF9DT0xPUiA9ICcjMWYyOTMzJztcblxuLy8gV2hhdCB0aGUgdG9rZW5zIGluIGEgYmxvY2sncyBodG1sIGFyZSBmaWxsZWQgd2l0aCwgcGVyIHBhZ2UuXG5leHBvcnQgaW50ZXJmYWNlIFRleHRUb2tlbkNvbnRleHQge1xuICBwYWdlTnVtYmVyOiBudW1iZXI7XG4gIHBhZ2VOYW1lOiBzdHJpbmc7XG4gIHJlcG9ydE5hbWU6IHN0cmluZztcbn1cblxuLy8gT25lIHN0eWxlZCBzdHJldGNoIG9mIHRleHQuXG5leHBvcnQgaW50ZXJmYWNlIFRleHRSdW4ge1xuICB0ZXh0OiBzdHJpbmc7XG4gIGJvbGQ/OiBib29sZWFuO1xuICBpdGFsaWM/OiBib29sZWFuO1xuICB1bmRlcmxpbmU/OiBib29sZWFuO1xuICBzdHJpa2U/OiBib29sZWFuO1xuICAvLyAjcnJnZ2JiXG4gIGNvbG9yPzogc3RyaW5nO1xuICBoaWdobGlnaHQ/OiBzdHJpbmc7XG4gIC8vIHBvaW50c1xuICBmb250U2l6ZT86IG51bWJlcjtcbiAgZm9udEZhY2U/OiBzdHJpbmc7XG4gIGxpbms/OiBzdHJpbmc7XG59XG5cbi8vIE9uZSBsaW5lLXN0YXJ0aW5nIGJsb2NrOiBhIHBhcmFncmFwaCwgYSBoZWFkaW5nIG9yIGEgbGlzdCBpdGVtLlxuZXhwb3J0IGludGVyZmFjZSBUZXh0UGFyYWdyYXBoIHtcbiAgcnVuczogVGV4dFJ1bltdO1xuICBhbGlnbj86ICdsZWZ0JyB8ICdjZW50ZXInIHwgJ3JpZ2h0JyB8ICdqdXN0aWZ5JztcbiAgYnVsbGV0PzogJ2J1bGxldCcgfCAnbnVtYmVyJztcbiAgaGVhZGluZz86IG51bWJlcjtcbn1cblxuLy8gVGhlIHRva2VucyBhIGJsb2NrIG1heSBjYXJyeSwgd2l0aCB3aGF0IGZpbGxzIGVhY2guIHt7cGFnZS5udW1iZXJ9fSBpcyB0aGVcbi8vIHBhZ2UncyBwb3NpdGlvbiBhbW9uZyB0aGUgcmVwb3J0J3MgcGFnZXMgKDEtYmFzZWQpLCB3aGljaCBpcyB3aGF0IG1ha2VzIGFcbi8vIHNoYXJlZCBmb290ZXIgbnVtYmVyIGV2ZXJ5IHBhZ2UgY29ycmVjdGx5LlxuY29uc3QgVE9LRU5TOiBSZWNvcmQ8c3RyaW5nLCAoY29udGV4dDogVGV4dFRva2VuQ29udGV4dCkgPT4gc3RyaW5nPiA9IHtcbiAgJ3BhZ2UubnVtYmVyJzogKGNvbnRleHQpID0+IFN0cmluZyhjb250ZXh0LnBhZ2VOdW1iZXIpLFxuICAncGFnZS5uYW1lJzogKGNvbnRleHQpID0+IGNvbnRleHQucGFnZU5hbWUsXG4gICdyZXBvcnQubmFtZSc6IChjb250ZXh0KSA9PiBjb250ZXh0LnJlcG9ydE5hbWUsXG59O1xuXG4vLyBSZXBsYWNlIGV2ZXJ5IHt7dG9rZW59fSBpbiB0aGUgaHRtbC4gVmFsdWVzIGFyZSBodG1sLWVzY2FwZWQ6IGEgcGFnZSBuYW1lZFxuLy8gXCJSJkQgPGRyYWZ0PlwiIG11c3QgcmVhZCBhcyB0aGF0LCBub3QgYXMgbWFya3VwLlxuZXhwb3J0IGZ1bmN0aW9uIGZpbGxUZXh0VG9rZW5zKGh0bWw6IHN0cmluZywgY29udGV4dDogVGV4dFRva2VuQ29udGV4dCk6IHN0cmluZyB7XG4gIHJldHVybiBodG1sLnJlcGxhY2UoL1xce1xce1xccyooW2Etei5dKylcXHMqXFx9XFx9L2dpLCAobWF0Y2gsIHRva2VuOiBzdHJpbmcpID0+IHtcbiAgICBjb25zdCBmaWxsID0gVE9LRU5TW3Rva2VuLnRvTG93ZXJDYXNlKCldO1xuXG4gICAgcmV0dXJuIGZpbGwgPyBlc2NhcGVIdG1sKGZpbGwoY29udGV4dCkpIDogbWF0Y2g7XG4gIH0pO1xufVxuXG4vLyBXYWxrIGEgYmxvY2sncyBodG1sIGludG8gcGFyYWdyYXBocyBvZiBzdHlsZWQgcnVucyDigJQgdGhlIHNoYXBlIGJvdGggZXhwb3J0c1xuLy8gZHJhdyBmcm9tLiBUb2tlbnMgYXJlIGZpbGxlZCBmaXJzdCBzbyBhIHBhZ2UgbnVtYmVyIGlzIGp1c3QgdGV4dCBieSB0aGVuLlxuZXhwb3J0IGZ1bmN0aW9uIHRleHRQYXJhZ3JhcGhzKGh0bWw6IHN0cmluZywgY29udGV4dDogVGV4dFRva2VuQ29udGV4dCk6IFRleHRQYXJhZ3JhcGhbXSB7XG4gIGNvbnN0IGRvY3VtZW50ID0gbmV3IERPTVBhcnNlcigpLnBhcnNlRnJvbVN0cmluZyhgPGJvZHk+JHtmaWxsVGV4dFRva2VucyhodG1sLCBjb250ZXh0KX08L2JvZHk+YCwgJ3RleHQvaHRtbCcpO1xuICBjb25zdCBwYXJhZ3JhcGhzOiBUZXh0UGFyYWdyYXBoW10gPSBbXTtcblxuICB3YWxrQmxvY2tzKGRvY3VtZW50LmJvZHksIHBhcmFncmFwaHMsIG51bGwpO1xuXG4gIHJldHVybiBwYXJhZ3JhcGhzLmZpbHRlcigocGFyYWdyYXBoLCBpbmRleCkgPT5cbiAgICAvLyBLZWVwIGFuIGVtcHR5IHBhcmFncmFwaCBiZXR3ZWVuIHR3byBvdGhlcnMgKGEgZGVsaWJlcmF0ZSBibGFuayBsaW5lKSwgYnV0XG4gICAgLy8gbm90IG9uZSBsZWZ0IGRhbmdsaW5nIGF0IGVpdGhlciBlbmQuXG4gICAgcGFyYWdyYXBoLnJ1bnMubGVuZ3RoIHx8IChpbmRleCA+IDAgJiYgaW5kZXggPCBwYXJhZ3JhcGhzLmxlbmd0aCAtIDEpKTtcbn1cblxuLy8gVGhlIGh0bWwgYXMgcGxhaW4gdGV4dCDigJQgd2hhdCBhIGJsb2NrIHNheXMsIGZvciBhbnl0aGluZyB0aGF0IGNhbm5vdCBzdHlsZSBpdC5cbmV4cG9ydCBmdW5jdGlvbiB0ZXh0UGxhaW4oaHRtbDogc3RyaW5nLCBjb250ZXh0OiBUZXh0VG9rZW5Db250ZXh0KTogc3RyaW5nIHtcbiAgcmV0dXJuIHRleHRQYXJhZ3JhcGhzKGh0bWwsIGNvbnRleHQpXG4gICAgLm1hcCgocGFyYWdyYXBoKSA9PiBwYXJhZ3JhcGgucnVucy5tYXAoKHJ1bikgPT4gcnVuLnRleHQpLmpvaW4oJycpKVxuICAgIC5qb2luKCdcXG4nKTtcbn1cblxuZnVuY3Rpb24gd2Fsa0Jsb2NrcyhcbiAgcGFyZW50OiBOb2RlLFxuICBwYXJhZ3JhcGhzOiBUZXh0UGFyYWdyYXBoW10sXG4gIGxpc3Q6ICdidWxsZXQnIHwgJ251bWJlcicgfCBudWxsLFxuKTogdm9pZCB7XG4gIC8vIExvb3NlIGlubGluZSBjb250ZW50IGJldHdlZW4gYmxvY2tzICh0ZXh0IHN0cmFpZ2h0IHVuZGVyIDxib2R5PiBvciA8bGk+KVxuICAvLyBpcyBnYXRoZXJlZCBpbnRvIGEgcGFyYWdyYXBoIG9mIGl0cyBvd24uXG4gIGxldCBsb29zZTogVGV4dFBhcmFncmFwaCB8IG51bGwgPSBudWxsO1xuICBjb25zdCBmbHVzaCA9ICgpID0+IHtcbiAgICBpZiAobG9vc2UpIHtcbiAgICAgIHBhcmFncmFwaHMucHVzaChsb29zZSk7XG4gICAgICBsb29zZSA9IG51bGw7XG4gICAgfVxuICB9O1xuXG4gIHBhcmVudC5jaGlsZE5vZGVzLmZvckVhY2goKG5vZGUpID0+IHtcbiAgICBjb25zdCBuYW1lID0gbm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgaWYgKG5hbWUgPT09ICd1bCcgfHwgbmFtZSA9PT0gJ29sJykge1xuICAgICAgZmx1c2goKTtcbiAgICAgIHdhbGtCbG9ja3Mobm9kZSwgcGFyYWdyYXBocywgbmFtZSA9PT0gJ3VsJyA/ICdidWxsZXQnIDogJ251bWJlcicpO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKG5hbWUgPT09ICdsaScpIHtcbiAgICAgIGZsdXNoKCk7XG4gICAgICBjb25zdCBpdGVtOiBUZXh0UGFyYWdyYXBoID0geyBydW5zOiBbXSwgYnVsbGV0OiBsaXN0ID8/ICdidWxsZXQnIH07XG4gICAgICBjb25zdCBuZXN0ZWQ6IFRleHRQYXJhZ3JhcGhbXSA9IFtdO1xuICAgICAgLy8gQSBsaXN0IGl0ZW0ncyBmaXJzdCBwYXJhZ3JhcGggSVMgdGhlIGl0ZW07IGFueXRoaW5nIGFmdGVyIGl0IGlzIGl0cyBvd25cbiAgICAgIC8vIGxpbmUgdW5kZXIgdGhlIHNhbWUgYnVsbGV0LlxuICAgICAgd2Fsa0Jsb2Nrcyhub2RlLCBuZXN0ZWQsIGxpc3QpO1xuICAgICAgY29uc3QgW2ZpcnN0LCAuLi5yZXN0XSA9IG5lc3RlZC5sZW5ndGggPyBuZXN0ZWQgOiBbaXRlbV07XG4gICAgICBwYXJhZ3JhcGhzLnB1c2goeyAuLi5maXJzdCwgYnVsbGV0OiBsaXN0ID8/ICdidWxsZXQnIH0sIC4uLnJlc3QpO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKG5hbWUgPT09ICdwJyB8fCAvXmhbMS0zXSQvLnRlc3QobmFtZSkpIHtcbiAgICAgIGZsdXNoKCk7XG4gICAgICBjb25zdCBlbGVtZW50ID0gbm9kZSBhcyBIVE1MRWxlbWVudDtcbiAgICAgIGNvbnN0IGhlYWRpbmcgPSBuYW1lLnN0YXJ0c1dpdGgoJ2gnKSA/IE51bWJlcihuYW1lWzFdKSA6IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IHBhcmFncmFwaDogVGV4dFBhcmFncmFwaCA9IHtcbiAgICAgICAgcnVuczogW10sXG4gICAgICAgIGFsaWduOiBibG9ja0FsaWduKGVsZW1lbnQpLFxuICAgICAgICBidWxsZXQ6IHVuZGVmaW5lZCxcbiAgICAgICAgaGVhZGluZyxcbiAgICAgIH07XG4gICAgICBjb25zdCBiYXNlOiBQYXJ0aWFsPFRleHRSdW4+ID0gaGVhZGluZ1xuICAgICAgICA/IHsgYm9sZDogdHJ1ZSwgZm9udFNpemU6IEhFQURJTkdfVEVYVF9TSVpFU1toZWFkaW5nXSB9XG4gICAgICAgIDoge307XG5cbiAgICAgIHdhbGtJbmxpbmUobm9kZSwgYmFzZSwgcGFyYWdyYXBoLCBwYXJhZ3JhcGhzKTtcbiAgICAgIHBhcmFncmFwaHMucHVzaChwYXJhZ3JhcGgpO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbG9vc2UgPSBsb29zZSA/PyB7IHJ1bnM6IFtdIH07XG4gICAgd2Fsa0lubGluZShub2RlLCB7fSwgbG9vc2UsIHBhcmFncmFwaHMsIHRydWUpO1xuICB9KTtcblxuICBmbHVzaCgpO1xufVxuXG4vLyBBY2N1bXVsYXRlIGlubGluZSBzdHlsZXMgZG93biB0aGUgdHJlZS4gQSA8YnI+IGVuZHMgdGhlIGN1cnJlbnQgbGluZTogdGhlXG4vLyBydW5zIGFmdGVyIGl0IHN0YXJ0IGEgbmV3IHBhcmFncmFwaCB3aXRoIHRoZSBzYW1lIGFsaWdubWVudCBhbmQgYnVsbGV0LlxuZnVuY3Rpb24gd2Fsa0lubGluZShcbiAgbm9kZTogTm9kZSxcbiAgc3R5bGU6IFBhcnRpYWw8VGV4dFJ1bj4sXG4gIHBhcmFncmFwaDogVGV4dFBhcmFncmFwaCxcbiAgcGFyYWdyYXBoczogVGV4dFBhcmFncmFwaFtdLFxuICBpc1NlbGYgPSBmYWxzZSxcbik6IHZvaWQge1xuICBjb25zdCB2aXNpdCA9IChjaGlsZDogTm9kZSkgPT4ge1xuICAgIGlmIChjaGlsZC5ub2RlVHlwZSA9PT0gTm9kZS5URVhUX05PREUpIHtcbiAgICAgIGNvbnN0IHRleHQgPSBjaGlsZC50ZXh0Q29udGVudCA/PyAnJztcbiAgICAgIGlmICh0ZXh0KSB7XG4gICAgICAgIHBhcmFncmFwaC5ydW5zLnB1c2goeyAuLi5zdHlsZSwgdGV4dCB9KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjaGlsZC5ub2RlVHlwZSAhPT0gTm9kZS5FTEVNRU5UX05PREUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBlbGVtZW50ID0gY2hpbGQgYXMgSFRNTEVsZW1lbnQ7XG4gICAgY29uc3QgbmFtZSA9IGVsZW1lbnQubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblxuICAgIGlmIChuYW1lID09PSAnYnInKSB7XG4gICAgICBwYXJhZ3JhcGhzLnB1c2goeyAuLi5wYXJhZ3JhcGgsIHJ1bnM6IFsuLi5wYXJhZ3JhcGgucnVuc10gfSk7XG4gICAgICBwYXJhZ3JhcGgucnVucy5sZW5ndGggPSAwO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2Fsa0lubGluZShlbGVtZW50LCB7IC4uLnN0eWxlLCAuLi5pbmxpbmVTdHlsZShlbGVtZW50KSB9LCBwYXJhZ3JhcGgsIHBhcmFncmFwaHMpO1xuICB9O1xuXG4gIGlmIChpc1NlbGYpIHtcbiAgICB2aXNpdChub2RlKTtcbiAgfSBlbHNlIHtcbiAgICBub2RlLmNoaWxkTm9kZXMuZm9yRWFjaCh2aXNpdCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gaW5saW5lU3R5bGUoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBQYXJ0aWFsPFRleHRSdW4+IHtcbiAgY29uc3QgbmFtZSA9IGVsZW1lbnQubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcbiAgY29uc3Qgc3R5bGU6IFBhcnRpYWw8VGV4dFJ1bj4gPSB7fTtcblxuICBpZiAobmFtZSA9PT0gJ3N0cm9uZycpIHtcbiAgICBzdHlsZS5ib2xkID0gdHJ1ZTtcbiAgfVxuICBpZiAobmFtZSA9PT0gJ2VtJykge1xuICAgIHN0eWxlLml0YWxpYyA9IHRydWU7XG4gIH1cbiAgaWYgKG5hbWUgPT09ICd1Jykge1xuICAgIHN0eWxlLnVuZGVybGluZSA9IHRydWU7XG4gIH1cbiAgaWYgKG5hbWUgPT09ICdzJykge1xuICAgIHN0eWxlLnN0cmlrZSA9IHRydWU7XG4gIH1cbiAgaWYgKG5hbWUgPT09ICdhJykge1xuICAgIHN0eWxlLmxpbmsgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnaHJlZicpID8/IHVuZGVmaW5lZDtcbiAgICBzdHlsZS51bmRlcmxpbmUgPSB0cnVlO1xuICB9XG5cbiAgY29uc3QgY3NzID0gZWxlbWVudC5zdHlsZTtcbiAgaWYgKGNzcy5jb2xvcikge1xuICAgIHN0eWxlLmNvbG9yID0gaGV4Q29sb3IoY3NzLmNvbG9yKTtcbiAgfVxuICBpZiAoY3NzLmJhY2tncm91bmRDb2xvcikge1xuICAgIHN0eWxlLmhpZ2hsaWdodCA9IGhleENvbG9yKGNzcy5iYWNrZ3JvdW5kQ29sb3IpO1xuICB9XG4gIGlmIChjc3MuZm9udFNpemUpIHtcbiAgICBzdHlsZS5mb250U2l6ZSA9IHBvaW50cyhjc3MuZm9udFNpemUpO1xuICB9XG4gIGlmIChjc3MuZm9udFdlaWdodCkge1xuICAgIHN0eWxlLmJvbGQgPSBjc3MuZm9udFdlaWdodCA9PT0gJ2JvbGQnIHx8IE51bWJlcihjc3MuZm9udFdlaWdodCkgPj0gNjAwO1xuICB9XG4gIGlmIChjc3MuZm9udFN0eWxlKSB7XG4gICAgc3R5bGUuaXRhbGljID0gY3NzLmZvbnRTdHlsZSA9PT0gJ2l0YWxpYyc7XG4gIH1cbiAgaWYgKGNzcy50ZXh0RGVjb3JhdGlvbikge1xuICAgIHN0eWxlLnVuZGVybGluZSA9IGNzcy50ZXh0RGVjb3JhdGlvbi5pbmNsdWRlcygndW5kZXJsaW5lJyk7XG4gICAgc3R5bGUuc3RyaWtlID0gY3NzLnRleHREZWNvcmF0aW9uLmluY2x1ZGVzKCdsaW5lLXRocm91Z2gnKTtcbiAgfVxuICBpZiAoY3NzLmZvbnRGYW1pbHkpIHtcbiAgICBzdHlsZS5mb250RmFjZSA9IGNzcy5mb250RmFtaWx5LnNwbGl0KCcsJylbMF0ucmVwbGFjZSgvW1wiJ10vZywgJycpLnRyaW0oKTtcbiAgfVxuXG4gIHJldHVybiBzdHlsZTtcbn1cblxuZnVuY3Rpb24gYmxvY2tBbGlnbihlbGVtZW50OiBIVE1MRWxlbWVudCk6IFRleHRQYXJhZ3JhcGhbJ2FsaWduJ10ge1xuICBjb25zdCBhbGlnbiA9IGVsZW1lbnQuc3R5bGUudGV4dEFsaWduO1xuXG4gIHJldHVybiBhbGlnbiA9PT0gJ2NlbnRlcicgfHwgYWxpZ24gPT09ICdyaWdodCcgfHwgYWxpZ24gPT09ICdqdXN0aWZ5JyA/IGFsaWduIDogdW5kZWZpbmVkO1xufVxuXG4vLyBBIENTUyBmb250LXNpemUgaW4gcG9pbnRzLiBUaGUgY2FudmFzIHJlbmRlcnMgYXQgOTZweCBwZXIgaW5jaCwgc28gMXB4IGlzXG4vLyBleGFjdGx5IDAuNzVwdDsgZW0vcmVtLyUgYXJlIHJlbGF0aXZlIHRvIHRoZSBib2R5IHNpemUuXG5mdW5jdGlvbiBwb2ludHModmFsdWU6IHN0cmluZyk6IG51bWJlciB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IG1hdGNoID0gL14oW1xcZC5dKykocHR8cHh8ZW18cmVtfCUpJC8uZXhlYyh2YWx1ZS50cmltKCkpO1xuICBpZiAoIW1hdGNoKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGNvbnN0IHNpemUgPSBOdW1iZXIobWF0Y2hbMV0pO1xuICBzd2l0Y2ggKG1hdGNoWzJdKSB7XG4gICAgY2FzZSAncHQnOlxuICAgICAgcmV0dXJuIHNpemU7XG4gICAgY2FzZSAncHgnOlxuICAgICAgcmV0dXJuIHNpemUgKiAwLjc1O1xuICAgIGNhc2UgJyUnOlxuICAgICAgcmV0dXJuIChzaXplIC8gMTAwKSAqIERFRkFVTFRfVEVYVF9TSVpFO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gc2l6ZSAqIERFRkFVTFRfVEVYVF9TSVpFO1xuICB9XG59XG5cbi8vIEFueSBDU1MgY29sb3IgdGhlIGFsbG93bGlzdCBsZXRzIHRocm91Z2ggKGhleCwgcmdiKCksIGEgbmFtZSkgYXMgI3JyZ2diYiDigJRcbi8vIHRoZSBvbmUgZm9ybSBib3RoIGV4cG9ydHMgYWNjZXB0LiBUaGUgYnJvd3NlciByZXNvbHZlcyBpdCwgc28gYSBuYW1lZCBjb2xvclxuLy8gY29tZXMgb3V0IGV4YWN0bHkgYXMgdGhlIGNhbnZhcyBwYWludGVkIGl0LlxubGV0IGNvbG9yQ29udGV4dDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEIHwgbnVsbCA9IG51bGw7XG5cbmZ1bmN0aW9uIGhleENvbG9yKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb2xvckNvbnRleHQgPSBjb2xvckNvbnRleHQgPz8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJykuZ2V0Q29udGV4dCgnMmQnKTtcbiAgaWYgKCFjb2xvckNvbnRleHQpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgY29sb3JDb250ZXh0LmZpbGxTdHlsZSA9ICcjMDAwMDAwJztcbiAgY29sb3JDb250ZXh0LmZpbGxTdHlsZSA9IHZhbHVlO1xuICBjb25zdCByZXNvbHZlZCA9IFN0cmluZyhjb2xvckNvbnRleHQuZmlsbFN0eWxlKTtcblxuICBpZiAocmVzb2x2ZWQuc3RhcnRzV2l0aCgnIycpKSB7XG4gICAgcmV0dXJuIHJlc29sdmVkO1xuICB9XG5cbiAgLy8gcmdiYSguLi4pIGZvciBhIHRyYW5zbHVjZW50IGNvbG9yIOKAlCBkcm9wIHRoZSBhbHBoYSwga2VlcCB0aGUgaHVlLlxuICBjb25zdCBjaGFubmVscyA9IHJlc29sdmVkLm1hdGNoKC9bXFxkLl0rL2cpPy5zbGljZSgwLCAzKS5tYXAoTnVtYmVyKSA/PyBbXTtcblxuICByZXR1cm4gY2hhbm5lbHMubGVuZ3RoID09PSAzXG4gICAgPyBgIyR7Y2hhbm5lbHMubWFwKChjaGFubmVsKSA9PiBNYXRoLnJvdW5kKGNoYW5uZWwpLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCAnMCcpKS5qb2luKCcnKX1gXG4gICAgOiB1bmRlZmluZWQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlc2NhcGVIdG1sKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gdmFsdWVcbiAgICAucmVwbGFjZSgvJi9nLCAnJmFtcDsnKVxuICAgIC5yZXBsYWNlKC88L2csICcmbHQ7JylcbiAgICAucmVwbGFjZSgvPi9nLCAnJmd0OycpXG4gICAgLnJlcGxhY2UoL1wiL2csICcmcXVvdDsnKTtcbn1cbiJdfQ==
429
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4dC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy90ZXh0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDRFQUE0RTtBQUM1RSw4Q0FBOEM7QUFDOUMsRUFBRTtBQUNGLDRFQUE0RTtBQUM1RSwrRUFBK0U7QUFDL0UseUVBQXlFO0FBQ3pFLDZFQUE2RTtBQUM3RSwwRUFBMEU7QUFDMUUseUVBQXlFO0FBQ3pFLCtFQUErRTtBQUMvRSw4RUFBOEU7QUFDOUUseUVBQXlFO0FBQ3pFLDhFQUE4RTtBQUM5RSw4QkFBOEI7QUFHOUIsOEVBQThFO0FBQzlFLG9FQUFvRTtBQUNwRSxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRyxFQUFFLENBQUM7QUFDcEMsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQTJCLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQztBQUNsRixNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxTQUFTLENBQUM7QUFFNUMsOEVBQThFO0FBQzlFLGlFQUFpRTtBQUNqRSw4RUFBOEU7QUFDOUUsc0JBQXNCO0FBQ3RCLE1BQU0sQ0FBQyxNQUFNLHVCQUF1QixHQUFHLFNBQVMsQ0FBQztBQUNqRCxNQUFNLENBQUMsTUFBTSx1QkFBdUIsR0FBRyxJQUFJLENBQUM7QUFDNUMsa0VBQWtFO0FBQ2xFLE1BQU0sQ0FBQyxNQUFNLHVCQUF1QixHQUFHLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRSxVQUFVLEVBQUUsQ0FBQyxFQUFFLENBQUM7QUFDdEUsNEVBQTRFO0FBQzVFLFVBQVU7QUFDVixNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLENBQUM7QUE4Qm5DLGdGQUFnRjtBQUNoRix1Q0FBdUM7QUFDdkMsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsMENBQTBDLENBQUM7QUFFOUUsK0VBQStFO0FBQy9FLGlFQUFpRTtBQUNqRSxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxHQUFHLENBQUM7QUFFcEMsMkVBQTJFO0FBQzNFLGtDQUFrQztBQUNsQyxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxHQUFHLENBQUM7QUFFdEMsTUFBTSxVQUFVLFVBQVUsQ0FBQyxHQUFXO0lBQ3BDLE9BQU8sV0FBVyxHQUFHLElBQUksQ0FBQztBQUM1QixDQUFDO0FBRUQsNEVBQTRFO0FBQzVFLG1EQUFtRDtBQUNuRCxNQUFNLFVBQVUsU0FBUyxDQUFDLEtBQTRCO0lBQ3BELE9BQU8sS0FBSyxFQUFFLElBQUksSUFBSSxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0FBQ2pGLENBQUM7QUFnRUQsc0VBQXNFO0FBQ3RFLE1BQU0sb0JBQW9CLEdBQUcsS0FBSyxDQUFDO0FBRW5DLDZFQUE2RTtBQUM3RSw0RUFBNEU7QUFDNUUsNkNBQTZDO0FBQzdDLE1BQU0sTUFBTSxHQUEwRDtJQUNwRSxhQUFhLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDO0lBQ3RELFdBQVcsRUFBRSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLFFBQVE7SUFDMUMsYUFBYSxFQUFFLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBVTtDQUMvQyxDQUFDO0FBRUYsNkVBQTZFO0FBQzdFLGdGQUFnRjtBQUNoRiw0RUFBNEU7QUFDNUUsTUFBTSxVQUFVLGNBQWMsQ0FBQyxJQUFZLEVBQUUsT0FBeUI7SUFDcEUsT0FBTyxJQUFJO1NBQ1IsT0FBTyxDQUFDLG1CQUFtQixFQUFFLENBQUMsS0FBSyxFQUFFLEdBQVcsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUM5RCxTQUFTLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQy9DLENBQUM7U0FDRCxPQUFPLENBQUMsMkJBQTJCLEVBQUUsQ0FBQyxLQUFLLEVBQUUsS0FBYSxFQUFFLEVBQUU7UUFDN0QsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBRXpDLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztJQUNsRCxDQUFDLENBQUMsQ0FBQztBQUNQLENBQUM7QUFFRCwrRUFBK0U7QUFDL0UsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSwrRUFBK0U7QUFDL0UsK0RBQStEO0FBQy9ELE1BQU0sVUFBVSxVQUFVLENBQUMsSUFBWSxFQUFFLE9BQXlCO0lBQ2hFLE1BQU0sUUFBUSxHQUFHLElBQUksU0FBUyxFQUFFLENBQUMsZUFBZSxDQUFDLFNBQVMsY0FBYyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsU0FBUyxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQy9HLE1BQU0sTUFBTSxHQUFHLGFBQWEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFhLEVBQUU7UUFDbEUsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUN6QixPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDcEQsQ0FBQztRQUVELE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1FBQ25ELE1BQU0sVUFBVSxHQUFvQixFQUFFLENBQUM7UUFDdkMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO1FBQ3pCLFVBQVUsQ0FBQyxRQUFRLEVBQUUsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBRXZDLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxDQUFDO0lBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBRUgsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRXJCLE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRCxnRkFBZ0Y7QUFDaEYsdURBQXVEO0FBQ3ZELE1BQU0sVUFBVSxjQUFjLENBQUMsSUFBWSxFQUFFLE9BQXlCO0lBQ3BFLE9BQU8sZUFBZSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztBQUNwRCxDQUFDO0FBRUQsa0VBQWtFO0FBQ2xFLE1BQU0sVUFBVSxlQUFlLENBQUMsTUFBbUI7SUFDakQsT0FBTyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLE1BQU07UUFDcEQsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFVO1FBQ2xCLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztBQUMxQyxDQUFDO0FBRUQsaUZBQWlGO0FBQ2pGLE1BQU0sVUFBVSxTQUFTLENBQUMsSUFBWSxFQUFFLE9BQXlCO0lBQy9ELE9BQU8sY0FBYyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUM7U0FDakMsR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztTQUNsRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDaEIsQ0FBQztBQUVELDRFQUE0RTtBQUM1RSw2RUFBNkU7QUFDN0UseUVBQXlFO0FBQ3pFLDZFQUE2RTtBQUM3RSxNQUFNLFVBQVUsYUFBYSxDQUFDLE1BQVk7SUFDeEMsTUFBTSxLQUFLLEdBQWtDLEVBQUUsQ0FBQztJQUNoRCxJQUFJLEdBQUcsR0FBa0IsSUFBSSxDQUFDO0lBRTlCLE1BQU0sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7UUFDakMsSUFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLE9BQU8sRUFBRSxDQUFDO1lBQzlCLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBd0IsQ0FBQyxDQUFDO1lBQ3JDLEdBQUcsR0FBRyxJQUFJLENBQUM7UUFDYixDQUFDO2FBQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUNmLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDakIsQ0FBQzthQUFNLENBQUM7WUFDTixHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNiLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbEIsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDO0lBRUgsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDO0FBRUQsOEVBQThFO0FBQzlFLGdGQUFnRjtBQUNoRiwrQkFBK0I7QUFDL0IsTUFBTSxVQUFVLFVBQVUsQ0FBQyxPQUF5QjtJQUNsRCxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQWdCLEVBQUUsQ0FBQyxDQUFDO1FBQzVELE9BQU8sRUFBRSxZQUFZLENBQUMsR0FBRyxDQUFDO1FBQzFCLEtBQUssRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsU0FBUyxDQUFDO0tBQ3hDLENBQUMsQ0FBQyxDQUFDO0lBRUosT0FBTyxTQUFTLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDekMsQ0FBQztBQUVELDRFQUE0RTtBQUM1RSxpRkFBaUY7QUFDakYsK0VBQStFO0FBQy9FLGdEQUFnRDtBQUNoRCxNQUFNLFVBQVUsU0FBUyxDQUFDLEtBQWdCO0lBQ3hDLE1BQU0sS0FBSyxHQUFnQixLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNwRCxJQUFJLE9BQU8sR0FBRyxDQUFDLENBQUM7SUFFaEIsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFnQixFQUFFO1FBQ3ZELE1BQU0sVUFBVSxHQUFHLGFBQWEsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3BELElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztRQUVmLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFpQixFQUFFO1lBQ2xELE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7Z0JBQzVCLE1BQU0sRUFBRSxDQUFDO1lBQ1gsQ0FBQztZQUVELE1BQU0sTUFBTSxHQUFHLEVBQUUsR0FBRyxJQUFJLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxVQUFVLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNwRyxNQUFNLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ3RCLE1BQU0sSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDO1lBQ3pCLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztZQUVwQyxPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sRUFBRSxHQUFHLEdBQUcsRUFBRSxLQUFLLEVBQUUsQ0FBQztJQUMzQixDQUFDLENBQUMsQ0FBQztJQUVILE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUM7QUFDM0IsQ0FBQztBQUVELFNBQVMsWUFBWSxDQUFDLEdBQXdCO0lBQzVDLE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxhQUFhLEVBQUUsUUFBUSxDQUFDO0lBRTVDLE9BQU8sT0FBTyxLQUFLLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLEtBQUssT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztBQUM5RSxDQUFDO0FBRUQsNkVBQTZFO0FBQzdFLDZFQUE2RTtBQUM3RSx1Q0FBdUM7QUFDdkMsU0FBUyxTQUFTLENBQUMsSUFBMEI7SUFDM0MsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsS0FBSyxJQUFJLENBQUM7SUFDdEMsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDOUUsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUM7SUFDeEMsTUFBTSxVQUFVLEdBQW9CLEVBQUUsQ0FBQztJQUV2QyxVQUFVLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7SUFFakUsT0FBTztRQUNMLFVBQVUsRUFBRSxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsR0FBRyxTQUFTLEVBQUUsS0FBSyxFQUFFLFNBQVMsQ0FBQyxLQUFLLElBQUksS0FBSyxFQUFFLENBQUMsQ0FBQztRQUM5RixPQUFPLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQztRQUNsQyxPQUFPLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQztRQUNsQyxHQUFHLEVBQUUsQ0FBQztRQUNOLE1BQU0sRUFBRSxDQUFDO1FBQ1QsS0FBSztRQUNMLE1BQU0sRUFBRSxNQUFNLEtBQUssS0FBSyxJQUFJLE1BQU0sS0FBSyxRQUFRLElBQUksTUFBTSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxTQUFTO1FBQzNGLElBQUksRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVM7S0FDcEYsQ0FBQztBQUNKLENBQUM7QUFFRCxTQUFTLFNBQVMsQ0FBQyxLQUFhO0lBQzlCLE9BQU8sS0FBSyxLQUFLLE1BQU0sSUFBSSxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssS0FBSyxPQUFPLElBQUksS0FBSyxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDaEgsQ0FBQztBQUVELDRFQUE0RTtBQUM1RSxTQUFTLGFBQWEsQ0FBQyxJQUFvQixFQUFFLEtBQWE7SUFDeEQsSUFBSSxHQUFHLEdBQUcsS0FBSyxHQUFHLENBQUMsQ0FBQztJQUNwQixPQUFPLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEtBQUssSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3RFLEdBQUcsRUFBRSxDQUFDO0lBQ1IsQ0FBQztJQUVELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQztBQUVELDRDQUE0QztBQUM1QyxTQUFTLE1BQU0sQ0FBQyxLQUFrQixFQUFFLElBQW1CO0lBQ3JELEtBQUssSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUM7UUFDOUQsS0FBSyxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQztZQUM3RSxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDO1FBQzVCLENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQztBQUVELDBFQUEwRTtBQUMxRSxxQkFBcUI7QUFDckIsU0FBUyxZQUFZLENBQUMsR0FBaUI7SUFDckMsT0FBTztRQUNMLElBQUksRUFBRSxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDO1lBQ3ZDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsb0JBQW9CLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDbEQsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUN2RyxDQUFDO0tBQ0gsQ0FBQztBQUNKLENBQUM7QUFFRCxnRkFBZ0Y7QUFDaEYsNEVBQTRFO0FBQzVFLDJFQUEyRTtBQUMzRSx5RUFBeUU7QUFDekUsb0NBQW9DO0FBQ3BDLFNBQVMsWUFBWSxDQUFDLE1BQW1CO0lBQ3ZDLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBRXZDLE9BQU8sSUFBSSxFQUFFLElBQUksS0FBSyxNQUFNLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNuSCxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ3hCLENBQUM7QUFDSCxDQUFDO0FBRUQsMkVBQTJFO0FBQzNFLFNBQVMsVUFBVSxDQUNqQixNQUFZLEVBQ1osVUFBMkIsRUFDM0IsSUFBZ0MsRUFDaEMsT0FBeUIsRUFBRTtJQUUzQix5RUFBeUU7SUFDekUsMkRBQTJEO0lBQzNELElBQUksS0FBSyxHQUF5QixJQUFJLENBQUM7SUFDdkMsTUFBTSxLQUFLLEdBQUcsR0FBRyxFQUFFO1FBQ2pCLElBQUksS0FBSyxJQUFJLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQzVCLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekIsQ0FBQztRQUNELEtBQUssR0FBRyxJQUFJLENBQUM7SUFDZixDQUFDLENBQUM7SUFFRixNQUFNLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1FBQ2pDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUM7UUFFekMsSUFBSSxJQUFJLEtBQUssSUFBSSxJQUFJLElBQUksS0FBSyxJQUFJLElBQUksSUFBSSxLQUFLLElBQUksSUFBSSxJQUFJLEtBQUssR0FBRyxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUM3RixLQUFLLEVBQUUsQ0FBQztZQUNSLFNBQVMsQ0FBQyxJQUFtQixFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFFdkQsT0FBTztRQUNULENBQUM7UUFFRCxLQUFLLEdBQUcsS0FBSyxJQUFJLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUFDO1FBQzlCLFVBQVUsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDbEQsQ0FBQyxDQUFDLENBQUM7SUFFSCxLQUFLLEVBQUUsQ0FBQztBQUNWLENBQUM7QUFFRCw2RUFBNkU7QUFDN0UsOEVBQThFO0FBQzlFLDZDQUE2QztBQUM3QyxTQUFTLE9BQU8sQ0FBQyxLQUFvQjtJQUNuQyxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQ2pFLENBQUM7QUFFRCxTQUFTLFNBQVMsQ0FDaEIsT0FBb0IsRUFDcEIsVUFBMkIsRUFDM0IsSUFBZ0MsRUFDaEMsSUFBc0I7SUFFdEIsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUU1QyxJQUFJLElBQUksS0FBSyxJQUFJLElBQUksSUFBSSxLQUFLLElBQUksRUFBRSxDQUFDO1FBQ25DLFVBQVUsQ0FBQyxPQUFPLEVBQUUsVUFBVSxFQUFFLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQzdFLENBQUM7U0FBTSxJQUFJLElBQUksS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUN6QixNQUFNLElBQUksR0FBa0IsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLElBQUksUUFBUSxFQUFFLENBQUM7UUFDbkUsTUFBTSxNQUFNLEdBQW9CLEVBQUUsQ0FBQztRQUNuQywwRUFBMEU7UUFDMUUsOEJBQThCO1FBQzlCLFVBQVUsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztRQUN4QyxNQUFNLENBQUMsS0FBSyxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pELFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLEtBQUssRUFBRSxNQUFNLEVBQUUsSUFBSSxJQUFJLFFBQVEsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDbkUsQ0FBQztTQUFNLENBQUM7UUFDTixhQUFhLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUMzQyxDQUFDO0FBQ0gsQ0FBQztBQUVELGdGQUFnRjtBQUNoRix3RUFBd0U7QUFDeEUsd0VBQXdFO0FBQ3hFLFNBQVMsYUFBYSxDQUFDLE9BQW9CLEVBQUUsVUFBMkIsRUFBRSxJQUFzQjtJQUM5RixNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQzVDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0lBQ25FLE1BQU0sU0FBUyxHQUFrQjtRQUMvQixJQUFJLEVBQUUsRUFBRTtRQUNSLEtBQUssRUFBRSxVQUFVLENBQUMsT0FBTyxDQUFDO1FBQzFCLE1BQU0sRUFBRSxTQUFTO1FBQ2pCLE9BQU87S0FDUixDQUFDO0lBQ0YsTUFBTSxLQUFLLEdBQXFCLE9BQU87UUFDckMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsa0JBQWtCLENBQUMsT0FBTyxDQUFDLEVBQUU7UUFDaEUsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUVULE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxVQUFVLENBQUMsQ0FBQztJQUNqRSxJQUFJLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDckMsVUFBVSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUM3QixDQUFDO0FBQ0gsQ0FBQztBQUVELDRFQUE0RTtBQUM1RSwwRUFBMEU7QUFDMUUsdUNBQXVDO0FBQ3ZDLFNBQVMsVUFBVSxDQUNqQixJQUFVLEVBQ1YsS0FBdUIsRUFDdkIsU0FBd0IsRUFDeEIsVUFBMkIsRUFDM0IsTUFBTSxHQUFHLEtBQUs7SUFFZCxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBRTVELE9BQU8sS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLE1BQU0sR0FBRyxjQUFjLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDMUcsQ0FBQztBQUVELFNBQVMsY0FBYyxDQUNyQixJQUFVLEVBQ1YsS0FBdUIsRUFDdkIsU0FBd0IsRUFDeEIsVUFBMkI7SUFFM0IsSUFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNyQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsV0FBVyxJQUFJLEVBQUUsQ0FBQztRQUNwQyxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ1QsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQzFDLENBQUM7UUFFRCxPQUFPLENBQUMsQ0FBQztJQUNYLENBQUM7SUFFRCxJQUFJLElBQUksQ0FBQyxRQUFRLEtBQUssSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3hDLE9BQU8sQ0FBQyxDQUFDO0lBQ1gsQ0FBQztJQUVELE1BQU0sT0FBTyxHQUFHLElBQW1CLENBQUM7SUFFcEMsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDO1FBQzVDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDN0QsU0FBUyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBRTFCLE9BQU8sQ0FBQyxDQUFDO0lBQ1gsQ0FBQztJQUVELE9BQU8sVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLEdBQUcsS0FBSyxFQUFFLEdBQUcsV0FBVyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsU0FBUyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0FBQzNGLENBQUM7QUFFRCxTQUFTLFdBQVcsQ0FBQyxPQUFvQjtJQUN2QyxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQzVDLE1BQU0sS0FBSyxHQUFxQixFQUFFLENBQUM7SUFFbkMsSUFBSSxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDdEIsS0FBSyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7SUFDcEIsQ0FBQztJQUNELElBQUksSUFBSSxLQUFLLElBQUksRUFBRSxDQUFDO1FBQ2xCLEtBQUssQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO0lBQ3RCLENBQUM7SUFDRCxJQUFJLElBQUksS0FBSyxHQUFHLEVBQUUsQ0FBQztRQUNqQixLQUFLLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztJQUN6QixDQUFDO0lBQ0QsSUFBSSxJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7UUFDakIsS0FBSyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7SUFDdEIsQ0FBQztJQUNELElBQUksSUFBSSxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ2pCLEtBQUssQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsSUFBSSxTQUFTLENBQUM7UUFDdkQsS0FBSyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7SUFDekIsQ0FBQztJQUVELHNEQUFzRDtJQUN0RCxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO0lBQzFCLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztJQUMxRCxNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7SUFDbEYsSUFBSSxLQUFLLEVBQUUsQ0FBQztRQUNWLEtBQUssQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO0lBQ3RCLENBQUM7SUFDRCxJQUFJLFNBQVMsRUFBRSxDQUFDO1FBQ2QsS0FBSyxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7SUFDOUIsQ0FBQztJQUNELElBQUksR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2pCLEtBQUssQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN4QyxDQUFDO0lBQ0QsSUFBSSxHQUFHLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDbkIsS0FBSyxDQUFDLElBQUksR0FBRyxHQUFHLENBQUMsVUFBVSxLQUFLLE1BQU0sSUFBSSxNQUFNLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxJQUFJLEdBQUcsQ0FBQztJQUMxRSxDQUFDO0lBQ0QsSUFBSSxHQUFHLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDbEIsS0FBSyxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUMsU0FBUyxLQUFLLFFBQVEsQ0FBQztJQUM1QyxDQUFDO0lBQ0QsSUFBSSxHQUFHLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDdkIsS0FBSyxDQUFDLFNBQVMsR0FBRyxHQUFHLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMzRCxLQUFLLENBQUMsTUFBTSxHQUFHLEdBQUcsQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBQzdELENBQUM7SUFDRCxJQUFJLEdBQUcsQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNuQixLQUFLLENBQUMsUUFBUSxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDNUUsQ0FBQztJQUVELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQztBQUVELFNBQVMsVUFBVSxDQUFDLE9BQW9CO0lBQ3RDLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDO0lBRXRDLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxLQUFLLEtBQUssT0FBTyxJQUFJLEtBQUssS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQzVGLENBQUM7QUFFRCw0RUFBNEU7QUFDNUUsMERBQTBEO0FBQzFELFNBQVMsTUFBTSxDQUFDLEtBQWE7SUFDM0IsTUFBTSxLQUFLLEdBQUcsNEJBQTRCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQzlELElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNYLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRCxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDOUIsUUFBUSxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUNqQixLQUFLLElBQUk7WUFDUCxPQUFPLElBQUksQ0FBQztRQUNkLEtBQUssSUFBSTtZQUNQLE9BQU8sSUFBSSxHQUFHLElBQUksQ0FBQztRQUNyQixLQUFLLEdBQUc7WUFDTixPQUFPLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQyxHQUFHLGlCQUFpQixDQUFDO1FBQzFDO1lBQ0UsT0FBTyxJQUFJLEdBQUcsaUJBQWlCLENBQUM7SUFDcEMsQ0FBQztBQUNILENBQUM7QUFFRCw2RUFBNkU7QUFDN0UsOEVBQThFO0FBQzlFLDhFQUE4RTtBQUM5RSwrRUFBK0U7QUFDL0UsMERBQTBEO0FBQzFELElBQUksWUFBWSxHQUFvQyxJQUFJLENBQUM7QUFFekQsU0FBUyxRQUFRLENBQUMsS0FBYTtJQUM3QixZQUFZLEdBQUcsWUFBWSxJQUFJLFFBQVEsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2pGLElBQUksQ0FBQyxZQUFZLElBQUksdUJBQXVCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDekQsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVELDZFQUE2RTtJQUM3RSx5RUFBeUU7SUFDekUsMkNBQTJDO0lBQzNDLE1BQU0sUUFBUSxHQUFHLFlBQVksQ0FBQyxZQUFZLEVBQUUsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQzlELElBQUksUUFBUSxLQUFLLFlBQVksQ0FBQyxZQUFZLEVBQUUsU0FBUyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDOUQsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVELElBQUksUUFBUSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQzdCLE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFFRCxvRUFBb0U7SUFDcEUsTUFBTSxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUUvRSxPQUFPLElBQUksS0FBSyxTQUFTLElBQUksS0FBSyxLQUFLLENBQUM7UUFDdEMsQ0FBQyxDQUFDLFNBQVM7UUFDWCxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7QUFDNUcsQ0FBQztBQUVELGlEQUFpRDtBQUNqRCxTQUFTLFlBQVksQ0FBQyxPQUFpQyxFQUFFLElBQVksRUFBRSxLQUFhO0lBQ2xGLE9BQU8sQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO0lBQ3pCLE9BQU8sQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO0lBRTFCLE9BQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUNuQyxDQUFDO0FBRUQsTUFBTSxVQUFVLFVBQVUsQ0FBQyxLQUFhO0lBQ3RDLE9BQU8sS0FBSztTQUNULE9BQU8sQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDO1NBQ3RCLE9BQU8sQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDO1NBQ3JCLE9BQU8sQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDO1NBQ3JCLE9BQU8sQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7QUFDN0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIFRleHQgYmxvY2tzIOKAlCBzaGFyZWQgYnkgdGhlIGNhbnZhcyBhbmQgYm90aCBleHBvcnRzLCBzbyBhIGJsb2NrIHJlYWRzIHRoZVxuLy8gc2FtZSBvbiBzY3JlZW4sIGluIHRoZSBkZWNrIGFuZCBpbiB0aGUgUERGLlxuLy9cbi8vIEEgYmxvY2sncyBodG1sIGFycml2ZXMgYWxyZWFkeSByZWJ1aWx0IHNlcnZlci1zaWRlIGZyb20gYSBzbWFsbCBhbGxvd2xpc3Rcbi8vIChSZXBvcnRUZXh0SHRtbCk6IHAsIGgxLWgzLCBzdHJvbmcsIGVtLCB1LCBzLCB1bC9vbC9saSwgYnIsIGEsIGFuZCBzcGFuIHdpdGhcbi8vIGNvbG9yIC8gYmFja2dyb3VuZC1jb2xvciAvIGZvbnQtc2l6ZSAvIGZvbnQtd2VpZ2h0IC8gZm9udC1mYW1pbHksIHBsdXNcbi8vIHRleHQtYWxpZ24gb24gYSBibG9jay4gQSB0YWJsZSBtYXkgc2l0IGF0IHRoZSB0b3AgbGV2ZWwgb2YgYSBibG9jazogdGFibGUsXG4vLyB0aGVhZCwgdGJvZHksIHRmb290LCB0ciwgdGggYW5kIHRkLCBhIHdpZHRoIG9uIHRoZSB0YWJsZSwgYW5kIG9uIGEgY2VsbFxuLy8gdGV4dC1hbGlnbiwgdmVydGljYWwtYWxpZ24sIGJhY2tncm91bmQtY29sb3IsIGEgd2lkdGggYW5kIGEgY29sc3BhbiBvclxuLy8gcm93c3Bhbi4gSXRzIGdyaWQgbGluZXMsIHBhZGRpbmcgYW5kIG1hcmdpbiBhcmUgbmV2ZXIgc3RvcmVkOiBldmVyeSByZW5kZXJlclxuLy8gZHJhd3MgdGhlbSBmcm9tIHRoZSBURVhUX1RBQkxFXyogY29uc3RhbnRzIGJlbG93LiBUcmFuc3BhcmVudCwgY3VycmVudGNvbG9yXG4vLyBhbmQgdGhlIENTUy13aWRlIGtleXdvcmRzIChpbmhlcml0LCBpbml0aWFsLCDigKYpIGFyZSBub3QgY29sb3JzLCBzbyB0aGVcbi8vIHNlcnZlciBkcm9wcyB0aGVtIGFuZCBoZXhDb2xvciByZWFkcyB0aGVtIGFzIG5vIGNvbG9yLiBFdmVyeXRoaW5nIGhlcmUgb25seVxuLy8gaGFzIHRvIHVuZGVyc3RhbmQgdGhhdCBzZXQuXG5cblxuLy8gQm9keSB0ZXh0IHNpemUsIHBvaW50cywgYW5kIHRoZSBoZWFkaW5nIHNpemVzIOKAlCB0aGUgc2FtZSBudW1iZXJzIHRoZSBjYW52YXNcbi8vIHN0eWxlc2hlZXQgdXNlcywgc28gYW4gdW5zdHlsZWQgcGFyYWdyYXBoIGlzIG9uZSBzaXplIGV2ZXJ5d2hlcmUuXG5leHBvcnQgY29uc3QgREVGQVVMVF9URVhUX1NJWkUgPSAxMjtcbmV4cG9ydCBjb25zdCBIRUFESU5HX1RFWFRfU0laRVM6IFJlY29yZDxudW1iZXIsIG51bWJlcj4gPSB7IDE6IDI0LCAyOiAxOCwgMzogMTQgfTtcbmV4cG9ydCBjb25zdCBERUZBVUxUX1RFWFRfQ09MT1IgPSAnIzFmMjkzMyc7XG5cbi8vIEEgdGFibGUncyBncmlkIGxpbmVzOiB0aGVpciBjb2xvciwgYW5kIHRoZWlyIHdpZHRoIGluIHBvaW50cyAoMC43NXB0IGlzIG9uZVxuLy8gcGl4ZWwgb24gdGhlIGNhbnZhcykuIFRoZSBodG1sIG5ldmVyIHN0b3JlcyBib3JkZXJzIG9yIHBhZGRpbmdcbi8vIChSZXBvcnRUZXh0SHRtbCBkcm9wcyB0aGVtKSwgc28gdGhlIGNhbnZhcywgdGhlIGVkaXRvciBhbmQgYm90aCBleHBvcnRzIGFsbFxuLy8gZHJhdyB0aGlzIG9uZSBsb29rLlxuZXhwb3J0IGNvbnN0IFRFWFRfVEFCTEVfQk9SREVSX0NPTE9SID0gJyNjYmQyZDknO1xuZXhwb3J0IGNvbnN0IFRFWFRfVEFCTEVfQk9SREVSX1dJRFRIID0gMC43NTtcbi8vIFRoZSBzcGFjZSBiZXR3ZWVuIGEgY2VsbCdzIGdyaWQgbGluZXMgYW5kIGl0cyB3b3JkcywgaW4gcG9pbnRzLlxuZXhwb3J0IGNvbnN0IFRFWFRfVEFCTEVfQ0VMTF9QQURESU5HID0geyB2ZXJ0aWNhbDogMiwgaG9yaXpvbnRhbDogNCB9O1xuLy8gVGhlIHNwYWNlIGFib3ZlIGFuZCBiZWxvdyBhIHRhYmxlLCBiZXR3ZWVuIGl0IGFuZCB0aGUgd29yZHMgYXJvdW5kIGl0LCBpblxuLy8gcG9pbnRzLlxuZXhwb3J0IGNvbnN0IFRFWFRfVEFCTEVfTUFSR0lOID0gNDtcblxuLy8gQSBsaXZlIHZhbHVlIGEgYmxvY2sgc2hvd3MgaW5saW5lLCB3cml0dGVuIHt7dmFsdWUuPGtleT59fSBpbiBpdHMgaHRtbDogd2hhdFxuLy8gdGhlIHZhbHVlIGlzLCBhbmQgaXRzIGZvcm1hdHRlZCB0ZXh0IG9uY2UgbG9hZGVkLiBWYWx1ZXMgYmVsb25nIHRvIHRoZSBwYWdlXG4vLyB0aGUgYmxvY2sgc2l0cyBvbiAodGhlIG1hc3RlciBmb3IgYSBoZWFkZXIgb3IgZm9vdGVyIGJsb2NrKSwgc28gdGhlIGtleSBpc1xuLy8gdW5pcXVlIHdpdGhpbiB0aGF0IHBhZ2UuXG5leHBvcnQgaW50ZXJmYWNlIFRleHRWYWx1ZSB7XG4gIG5hbWU6IHN0cmluZztcbiAgLy8gQWJzZW50IHdoaWxlIGxvYWRpbmcsIGFuZCB3aGVuIHRoZSB2YWx1ZSdzIHF1ZXJ5IGZhaWxlZC5cbiAgdGV4dD86IHN0cmluZztcbiAgLy8gSXRzIG51bWJlciBoYXMgYmVlbiBhc2tlZCBmb3IgYW5kIGhhcyBub3QgYXJyaXZlZCB5ZXQuXG4gIGxvYWRpbmc/OiBib29sZWFuO1xuICAvLyBBIGZvcm11bGEncyBvcGVyYW5kIGtleXMsIGxvd2VyY2FzZTogdGhlIHZhbHVlcyBpdCByZWFkcywgd2hpY2ggdGhlIHBhZ2VcbiAgLy8gcmVhZHMgdG9vIHdoaWxlIHRoZSBmb3JtdWxhIGlzIHNob3duLlxuICByZWFkcz86IHN0cmluZ1tdO1xufVxuXG4vLyBXaGF0IHRoZSB0b2tlbnMgaW4gYSBibG9jaydzIGh0bWwgYXJlIGZpbGxlZCB3aXRoLCBwZXIgcGFnZS5cbmV4cG9ydCBpbnRlcmZhY2UgVGV4dFRva2VuQ29udGV4dCB7XG4gIHBhZ2VOdW1iZXI6IG51bWJlcjtcbiAgcGFnZU5hbWU6IHN0cmluZztcbiAgcmVwb3J0TmFtZTogc3RyaW5nO1xuICAvLyBUaGUgcGFnZSdzIHZhbHVlcywgYnkgbG93ZXJjYXNlIGtleS5cbiAgdmFsdWVzPzogUmVjb3JkPHN0cmluZywgVGV4dFZhbHVlPjtcbiAgLy8gVGhlIHJlcG9ydCBwYWdlIHdob3NlIHZhbHVlcyB0aGUgYmxvY2sgc2hvd3M6IHRoZSBwYWdlIGl0IHNpdHMgb24sIG9yIHRoZVxuICAvLyBtYXN0ZXIgZm9yIGEgaGVhZGVyIG9yIGZvb3RlciBibG9jay4gSXQgaXMgYWxzbyB0aGUgZWRpdG9yJ3MgY2xpcGJvYXJkXG4gIC8vIHNjb3BlLCBzbyBhIGNvcGllZCBjaGlwIHBhc3RlcyBiYWNrIGFzIGEgY2hpcCBvbmx5IG9uIHRoYXQgcGFnZS5cbiAgdmFsdWVQYWdlSWQ/OiBudW1iZXIgfCBudWxsO1xufVxuXG4vLyBBIHZhbHVlIHRva2VuOiB7e3ZhbHVlLnRvdGFsX3Zpc2l0c319LiBLZXlzIGFyZSBsb3dlcmNhc2UgbGV0dGVycywgZGlnaXRzIGFuZFxuLy8gdW5kZXJzY29yZXMsIHN0YXJ0aW5nIHdpdGggYSBsZXR0ZXIuXG5leHBvcnQgY29uc3QgVkFMVUVfVE9LRU5fUEFUVEVSTiA9IC9cXHtcXHtcXHMqdmFsdWVcXC4oW2Etel1bYS16MC05X10qKVxccypcXH1cXH0vZ2k7XG5cbi8vIFdoYXQgYSB2YWx1ZSB3aXRoIG5vIG51bWJlciByZWFkcyBhcyDigJQgaXQgZmFpbGVkLCBpdCBpcyBub3Qgb24gdGhpcyBwYWdlLCBvclxuLy8gaXRzIHF1ZXJ5IGZvdW5kIG5vdGhpbmcg4oCUIHNvIGEgYmxvY2sgbmV2ZXIgcHJpbnRzIGEgcmF3IHRva2VuLlxuZXhwb3J0IGNvbnN0IFZBTFVFX0VNUFRZX1RFWFQgPSAn4oCUJztcblxuLy8gV2hhdCBhIHZhbHVlIHJlYWRzIGFzIHdoaWxlIGl0cyBudW1iZXIgaXMgb24gaXRzIHdheSAob24gc2NyZWVuIG9ubHk6IGFuXG4vLyBleHBvcnQgd2FpdHMgZm9yIGV2ZXJ5IG51bWJlcikuXG5leHBvcnQgY29uc3QgVkFMVUVfTE9BRElOR19URVhUID0gJ+KApic7XG5cbmV4cG9ydCBmdW5jdGlvbiB2YWx1ZVRva2VuKGtleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGB7e3ZhbHVlLiR7a2V5fX19YDtcbn1cblxuLy8gV2hhdCBhIHZhbHVlIHJlYWRzIGFzIGluIGEgYmxvY2ssIHZpZXdlZCBvciBlZGl0ZWQ6IGl0cyBmb3JtYXR0ZWQgbnVtYmVyLFxuLy8gdGhlIGVsbGlwc2lzIHdoaWxlIHRoYXQgbG9hZHMsIGVsc2UgdGhlIGVtIGRhc2guXG5leHBvcnQgZnVuY3Rpb24gdmFsdWVUZXh0KHZhbHVlOiBUZXh0VmFsdWUgfCB1bmRlZmluZWQpOiBzdHJpbmcge1xuICByZXR1cm4gdmFsdWU/LnRleHQgPz8gKHZhbHVlPy5sb2FkaW5nID8gVkFMVUVfTE9BRElOR19URVhUIDogVkFMVUVfRU1QVFlfVEVYVCk7XG59XG5cbi8vIE9uZSBzdHlsZWQgc3RyZXRjaCBvZiB0ZXh0LlxuZXhwb3J0IGludGVyZmFjZSBUZXh0UnVuIHtcbiAgdGV4dDogc3RyaW5nO1xuICBib2xkPzogYm9vbGVhbjtcbiAgaXRhbGljPzogYm9vbGVhbjtcbiAgdW5kZXJsaW5lPzogYm9vbGVhbjtcbiAgc3RyaWtlPzogYm9vbGVhbjtcbiAgLy8gI3JyZ2diYlxuICBjb2xvcj86IHN0cmluZztcbiAgaGlnaGxpZ2h0Pzogc3RyaW5nO1xuICAvLyBwb2ludHNcbiAgZm9udFNpemU/OiBudW1iZXI7XG4gIGZvbnRGYWNlPzogc3RyaW5nO1xuICBsaW5rPzogc3RyaW5nO1xufVxuXG4vLyBPbmUgbGluZS1zdGFydGluZyBibG9jazogYSBwYXJhZ3JhcGgsIGEgaGVhZGluZyBvciBhIGxpc3QgaXRlbS5cbmV4cG9ydCBpbnRlcmZhY2UgVGV4dFBhcmFncmFwaCB7XG4gIHJ1bnM6IFRleHRSdW5bXTtcbiAgYWxpZ24/OiAnbGVmdCcgfCAnY2VudGVyJyB8ICdyaWdodCcgfCAnanVzdGlmeSc7XG4gIGJ1bGxldD86ICdidWxsZXQnIHwgJ251bWJlcic7XG4gIGhlYWRpbmc/OiBudW1iZXI7XG59XG5cbi8vIE9uZSBjZWxsIG9mIGEgdGFibGUgaW4gYSBibG9jay4gSXRzIHdvcmRzIGFyZSBwYXJhZ3JhcGhzIGxpa2UgYW55IG90aGVyczogYVxuLy8gPGJyPiBpbiBhIGNlbGwgc3RhcnRzIGEgbmV3IG9uZSwgYW5kIGEgaGVhZGVyIGNlbGwncyBydW5zIGFyZSBib2xkLiBFYWNoXG4vLyBwYXJhZ3JhcGggY2FycmllcyB0aGUgY2VsbCdzIGFsaWdubWVudCB1bmxlc3MgaXQgaGFzIGl0cyBvd24sIHNvIGV2ZXJ5XG4vLyByZW5kZXJlciByZWFkcyBhbGlnbm1lbnQgYW5kIHdlaWdodCBmcm9tIHRoZSBwYXJhZ3JhcGhzLlxuZXhwb3J0IGludGVyZmFjZSBUZXh0VGFibGVDZWxsIHtcbiAgcGFyYWdyYXBoczogVGV4dFBhcmFncmFwaFtdO1xuICBjb2xTcGFuOiBudW1iZXI7XG4gIC8vIEN1dCBhdCB0aGUgbGFzdCByb3cgb2YgdGhlIGNlbGwncyBzZWN0aW9uLCBhcyBhIGJyb3dzZXIgZHJhd3MgaXQuXG4gIHJvd1NwYW46IG51bWJlcjtcbiAgLy8gV2hlcmUgdGhlIGNlbGwgc2l0cyBpbiB0aGUgZ3JpZCAodGFibGVHcmlkKSwgMC1iYXNlZDogaXRzIHRvcCByb3cgYW5kIGl0c1xuICAvLyBsZWZ0IGNvbHVtbi5cbiAgcm93OiBudW1iZXI7XG4gIGNvbHVtbjogbnVtYmVyO1xuICAvLyBJdHMgdGV4dC1hbGlnbiwgZWxzZSBjZW50ZXJlZCBmb3IgYSBoZWFkZXIgY2VsbCBhbmQgbGVmdCBmb3IgYW55IG90aGVyLlxuICBhbGlnbjogJ2xlZnQnIHwgJ2NlbnRlcicgfCAncmlnaHQnIHwgJ2p1c3RpZnknO1xuICB2YWxpZ24/OiAndG9wJyB8ICdtaWRkbGUnIHwgJ2JvdHRvbSc7XG4gIC8vIEl0cyBiYWNrZ3JvdW5kLCAjcnJnZ2JiLlxuICBmaWxsPzogc3RyaW5nO1xufVxuXG4vLyBBIHRhYmxlJ3Mgcm93LiBSb3dzIGNvbWUgaW4gdGhlIG9yZGVyIGEgYnJvd3NlciBkcmF3cyB0aGVtOiB0aGUgaGVhZCwgdGhlXG4vLyBib2R5LCB0aGVuIHRoZSBmb290LlxuZXhwb3J0IGludGVyZmFjZSBUZXh0VGFibGVSb3cge1xuICBzZWN0aW9uOiAnaGVhZCcgfCAnYm9keScgfCAnZm9vdCc7XG4gIGNlbGxzOiBUZXh0VGFibGVDZWxsW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGV4dFRhYmxlIHtcbiAgcm93czogVGV4dFRhYmxlUm93W107XG4gIC8vIEhvdyBtYW55IGNvbHVtbnMgdGhlIGdyaWQgaGFzOiB0aGUgd2lkZXN0IHJpZ2h0IGVkZ2Ugb2YgYW55IGNlbGwuXG4gIGNvbHVtbnM6IG51bWJlcjtcbn1cblxuLy8gQSBibG9jayBhcyB0aGUgZXhwb3J0cyBkcmF3IGl0OiBpdHMgd29yZHMsIHNwbGl0IGF0IGVhY2ggdGFibGUgaXQgaG9sZHMuXG5leHBvcnQgdHlwZSBUZXh0QmxvY2sgPVxuICB8IHsga2luZDogJ3RleHQnOyBwYXJhZ3JhcGhzOiBUZXh0UGFyYWdyYXBoW10gfVxuICB8IHsga2luZDogJ3RhYmxlJzsgdGFibGU6IFRleHRUYWJsZSB9O1xuXG4vLyBXaGF0IGEgdGFibGUncyBjZWxscyBhcmUgam9pbmVkIGJ5IHdoZXJlIGl0IHJlYWRzIGFzIGxpbmVzIG9mIHRleHQuXG5jb25zdCBUQUJMRV9DRUxMX1NFUEFSQVRPUiA9ICcgwrcgJztcblxuLy8gVGhlIHRva2VucyBhIGJsb2NrIG1heSBjYXJyeSwgd2l0aCB3aGF0IGZpbGxzIGVhY2guIHt7cGFnZS5udW1iZXJ9fSBpcyB0aGVcbi8vIHBhZ2UncyBwb3NpdGlvbiBhbW9uZyB0aGUgcmVwb3J0J3MgcGFnZXMgKDEtYmFzZWQpLCB3aGljaCBpcyB3aGF0IG1ha2VzIGFcbi8vIHNoYXJlZCBmb290ZXIgbnVtYmVyIGV2ZXJ5IHBhZ2UgY29ycmVjdGx5LlxuY29uc3QgVE9LRU5TOiBSZWNvcmQ8c3RyaW5nLCAoY29udGV4dDogVGV4dFRva2VuQ29udGV4dCkgPT4gc3RyaW5nPiA9IHtcbiAgJ3BhZ2UubnVtYmVyJzogKGNvbnRleHQpID0+IFN0cmluZyhjb250ZXh0LnBhZ2VOdW1iZXIpLFxuICAncGFnZS5uYW1lJzogKGNvbnRleHQpID0+IGNvbnRleHQucGFnZU5hbWUsXG4gICdyZXBvcnQubmFtZSc6IChjb250ZXh0KSA9PiBjb250ZXh0LnJlcG9ydE5hbWUsXG59O1xuXG4vLyBSZXBsYWNlIGV2ZXJ5IHt7dG9rZW59fSBpbiB0aGUgaHRtbC4gVmFsdWVzIGFyZSBodG1sLWVzY2FwZWQ6IGEgcGFnZSBuYW1lZFxuLy8gXCJSJkQgPGRyYWZ0PlwiIG11c3QgcmVhZCBhcyB0aGF0LCBub3QgYXMgbWFya3VwLiBBIHt7dmFsdWUuPGtleT59fSB0b2tlbiByZWFkc1xuLy8gYXMgaXRzIGZvcm1hdHRlZCBudW1iZXIsIHRoZSBlbGxpcHNpcyB3aGlsZSB0aGF0IGxvYWRzLCBlbHNlIHRoZSBlbSBkYXNoLlxuZXhwb3J0IGZ1bmN0aW9uIGZpbGxUZXh0VG9rZW5zKGh0bWw6IHN0cmluZywgY29udGV4dDogVGV4dFRva2VuQ29udGV4dCk6IHN0cmluZyB7XG4gIHJldHVybiBodG1sXG4gICAgLnJlcGxhY2UoVkFMVUVfVE9LRU5fUEFUVEVSTiwgKG1hdGNoLCBrZXk6IHN0cmluZykgPT4gZXNjYXBlSHRtbChcbiAgICAgIHZhbHVlVGV4dChjb250ZXh0LnZhbHVlcz8uW2tleS50b0xvd2VyQ2FzZSgpXSksXG4gICAgKSlcbiAgICAucmVwbGFjZSgvXFx7XFx7XFxzKihbYS16Ll0rKVxccypcXH1cXH0vZ2ksIChtYXRjaCwgdG9rZW46IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgZmlsbCA9IFRPS0VOU1t0b2tlbi50b0xvd2VyQ2FzZSgpXTtcblxuICAgICAgcmV0dXJuIGZpbGwgPyBlc2NhcGVIdG1sKGZpbGwoY29udGV4dCkpIDogbWF0Y2g7XG4gICAgfSk7XG59XG5cbi8vIFdhbGsgYSBibG9jaydzIGh0bWwgaW50byB3aGF0IHRoZSBleHBvcnRzIGRyYXc6IHRoZSB3b3JkcyBiZXR3ZWVuIGl0cyB0YWJsZXNcbi8vIGFzIHBhcmFncmFwaHMgb2Ygc3R5bGVkIHJ1bnMsIGFuZCBlYWNoIHRhYmxlIGFzIGEgZ3JpZCBvZiBjZWxscy4gVG9rZW5zIGFyZVxuLy8gZmlsbGVkIGZpcnN0IHNvIGEgcGFnZSBudW1iZXIgaXMganVzdCB0ZXh0IGJ5IHRoZW4uIFRoZXJlIGlzIGEgdGV4dCBwYXJ0IGZvclxuLy8gZXZlcnkgcnVuIG9mIG5vZGVzIHNwbGl0QXRUYWJsZXMgZmluZHMsIGV2ZW4gb25lIHRoYXQgaG9sZHMgbm8gd29yZHMsIHNvIHRoZVxuLy8gbnRoIHRleHQgcGFydCBpcyB0aGUgbnRoIHJ1biB0aGUgZXhwb3J0J3MgRE9NIG1lYXN1cmUgZmluZHMuXG5leHBvcnQgZnVuY3Rpb24gdGV4dEJsb2NrcyhodG1sOiBzdHJpbmcsIGNvbnRleHQ6IFRleHRUb2tlbkNvbnRleHQpOiBUZXh0QmxvY2tbXSB7XG4gIGNvbnN0IGRvY3VtZW50ID0gbmV3IERPTVBhcnNlcigpLnBhcnNlRnJvbVN0cmluZyhgPGJvZHk+JHtmaWxsVGV4dFRva2VucyhodG1sLCBjb250ZXh0KX08L2JvZHk+YCwgJ3RleHQvaHRtbCcpO1xuICBjb25zdCBibG9ja3MgPSBzcGxpdEF0VGFibGVzKGRvY3VtZW50LmJvZHkpLm1hcCgocGFydCk6IFRleHRCbG9jayA9PiB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHBhcnQpKSB7XG4gICAgICByZXR1cm4geyBraW5kOiAndGFibGUnLCB0YWJsZTogcGFyc2VUYWJsZShwYXJ0KSB9O1xuICAgIH1cblxuICAgIGNvbnN0IGZyYWdtZW50ID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpO1xuICAgIGNvbnN0IHBhcmFncmFwaHM6IFRleHRQYXJhZ3JhcGhbXSA9IFtdO1xuICAgIGZyYWdtZW50LmFwcGVuZCguLi5wYXJ0KTtcbiAgICB3YWxrQmxvY2tzKGZyYWdtZW50LCBwYXJhZ3JhcGhzLCBudWxsKTtcblxuICAgIHJldHVybiB7IGtpbmQ6ICd0ZXh0JywgcGFyYWdyYXBocyB9O1xuICB9KTtcblxuICB0cmltQmxhbmtFbmQoYmxvY2tzKTtcblxuICByZXR1cm4gYmxvY2tzO1xufVxuXG4vLyBUaGUgYmxvY2sgYXMgcGFyYWdyYXBocyBhbG9uZSwgZm9yIGFueXRoaW5nIHRoYXQgZHJhd3Mgbm8gZ3JpZDogYSB0YWJsZSByZWFkc1xuLy8gYXMgYSBsaW5lIHBlciByb3csIGl0cyBjZWxscycgd29yZHMgam9pbmVkIGJ5ICcgwrcgJy5cbmV4cG9ydCBmdW5jdGlvbiB0ZXh0UGFyYWdyYXBocyhodG1sOiBzdHJpbmcsIGNvbnRleHQ6IFRleHRUb2tlbkNvbnRleHQpOiBUZXh0UGFyYWdyYXBoW10ge1xuICByZXR1cm4gYmxvY2tQYXJhZ3JhcGhzKHRleHRCbG9ja3MoaHRtbCwgY29udGV4dCkpO1xufVxuXG4vLyBCbG9ja3MgdGV4dEJsb2NrcyBhbHJlYWR5IHdhbGtlZCwgYXMgdGV4dFBhcmFncmFwaHMgcmVhZHMgdGhlbS5cbmV4cG9ydCBmdW5jdGlvbiBibG9ja1BhcmFncmFwaHMoYmxvY2tzOiBUZXh0QmxvY2tbXSk6IFRleHRQYXJhZ3JhcGhbXSB7XG4gIHJldHVybiBibG9ja3MuZmxhdE1hcCgoYmxvY2spID0+IGJsb2NrLmtpbmQgPT09ICd0ZXh0J1xuICAgID8gYmxvY2sucGFyYWdyYXBoc1xuICAgIDogYmxvY2sudGFibGUucm93cy5tYXAocm93UGFyYWdyYXBoKSk7XG59XG5cbi8vIFRoZSBodG1sIGFzIHBsYWluIHRleHQg4oCUIHdoYXQgYSBibG9jayBzYXlzLCBmb3IgYW55dGhpbmcgdGhhdCBjYW5ub3Qgc3R5bGUgaXQuXG5leHBvcnQgZnVuY3Rpb24gdGV4dFBsYWluKGh0bWw6IHN0cmluZywgY29udGV4dDogVGV4dFRva2VuQ29udGV4dCk6IHN0cmluZyB7XG4gIHJldHVybiB0ZXh0UGFyYWdyYXBocyhodG1sLCBjb250ZXh0KVxuICAgIC5tYXAoKHBhcmFncmFwaCkgPT4gcGFyYWdyYXBoLnJ1bnMubWFwKChydW4pID0+IHJ1bi50ZXh0KS5qb2luKCcnKSlcbiAgICAuam9pbignXFxuJyk7XG59XG5cbi8vIEEgYmxvY2sncyB0b3AtbGV2ZWwgbm9kZXMgc3BsaXQgYXQgZWFjaCB0YWJsZTogZWFjaCB0YWJsZSBvbiBpdHMgb3duLCBhbmRcbi8vIGVhY2ggcnVuIG9mIHRoZSBub2RlcyBiZXR3ZWVuIHRoZW0gYXMgYSBsaXN0LiBBIHRhYmxlIHNpdHMgb25seSBhdCB0aGUgdG9wXG4vLyBsZXZlbCAoUmVwb3J0VGV4dEh0bWwgZmxhdHRlbnMgYW55IG90aGVyKSwgc28gdGhpcyBpcyB0aGUgd2hvbGUgc3BsaXQuXG4vLyB0ZXh0QmxvY2tzIGFuZCB0aGUgZXhwb3J0J3MgbWVhc3VyZSBvZiB0aGUgcmVuZGVyZWQgYmxvY2sgYm90aCBzcGxpdCBoZXJlLlxuZXhwb3J0IGZ1bmN0aW9uIHNwbGl0QXRUYWJsZXMocGFyZW50OiBOb2RlKTogKE5vZGVbXSB8IEhUTUxUYWJsZUVsZW1lbnQpW10ge1xuICBjb25zdCBwYXJ0czogKE5vZGVbXSB8IEhUTUxUYWJsZUVsZW1lbnQpW10gPSBbXTtcbiAgbGV0IHJ1bjogTm9kZVtdIHwgbnVsbCA9IG51bGw7XG5cbiAgcGFyZW50LmNoaWxkTm9kZXMuZm9yRWFjaCgobm9kZSkgPT4ge1xuICAgIGlmIChub2RlLm5vZGVOYW1lID09PSAnVEFCTEUnKSB7XG4gICAgICBwYXJ0cy5wdXNoKG5vZGUgYXMgSFRNTFRhYmxlRWxlbWVudCk7XG4gICAgICBydW4gPSBudWxsO1xuICAgIH0gZWxzZSBpZiAocnVuKSB7XG4gICAgICBydW4ucHVzaChub2RlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcnVuID0gW25vZGVdO1xuICAgICAgcGFydHMucHVzaChydW4pO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIHBhcnRzO1xufVxuXG4vLyBBIHRhYmxlIGFzIGEgZ3JpZCBvZiBjZWxscywgZWFjaCBob2xkaW5nIGl0cyB3b3JkcyBhcyBwYXJhZ3JhcGhzLiBSb3dzIGNvbWVcbi8vIGFzIGEgYnJvd3NlciBkcmF3cyB0aGVtLCB0aGUgaGVhZCBmaXJzdCBhbmQgdGhlIGZvb3QgbGFzdCwgd2hhdGV2ZXIgb3JkZXIgdGhlXG4vLyBodG1sIHdyaXRlcyBpdHMgc2VjdGlvbnMgaW4uXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VUYWJsZShlbGVtZW50OiBIVE1MVGFibGVFbGVtZW50KTogVGV4dFRhYmxlIHtcbiAgY29uc3Qgcm93cyA9IEFycmF5LmZyb20oZWxlbWVudC5yb3dzLCAocm93KTogVGV4dFRhYmxlUm93ID0+ICh7XG4gICAgc2VjdGlvbjogdGFibGVTZWN0aW9uKHJvdyksXG4gICAgY2VsbHM6IEFycmF5LmZyb20ocm93LmNlbGxzLCB0YWJsZUNlbGwpLFxuICB9KSk7XG5cbiAgcmV0dXJuIHRhYmxlR3JpZCh7IHJvd3MsIGNvbHVtbnM6IDAgfSk7XG59XG5cbi8vIFdoZXJlIGVhY2ggY2VsbCBzaXRzLCBieSB0aGUgSFRNTCB0YWJsZSBhbGdvcml0aG06IGEgY2VsbCB0YWtlcyB0aGUgZmlyc3Rcbi8vIGNvbHVtbiBvZiBpdHMgcm93IHRoYXQgbm8gY2VsbCBzcGFubmluZyBkb3duIGZyb20gYSByb3cgYWJvdmUgaG9sZHMuIEEgcm93c3BhblxuLy8gc3RvcHMgYXQgdGhlIGxhc3Qgcm93IG9mIGl0cyBzZWN0aW9uLCBhcyBhIGJyb3dzZXIgZHJhd3MgaXQsIGFuZCB0aGUgZ3JpZCBpc1xuLy8gYXMgd2lkZSBhcyB0aGUgd2lkZXN0IHJpZ2h0IGVkZ2Ugb2YgYW55IGNlbGwuXG5leHBvcnQgZnVuY3Rpb24gdGFibGVHcmlkKHRhYmxlOiBUZXh0VGFibGUpOiBUZXh0VGFibGUge1xuICBjb25zdCB0YWtlbjogYm9vbGVhbltdW10gPSB0YWJsZS5yb3dzLm1hcCgoKSA9PiBbXSk7XG4gIGxldCBjb2x1bW5zID0gMDtcblxuICBjb25zdCByb3dzID0gdGFibGUucm93cy5tYXAoKHJvdywgaW5kZXgpOiBUZXh0VGFibGVSb3cgPT4ge1xuICAgIGNvbnN0IHNlY3Rpb25FbmQgPSByb3dTZWN0aW9uRW5kKHRhYmxlLnJvd3MsIGluZGV4KTtcbiAgICBsZXQgY29sdW1uID0gMDtcblxuICAgIGNvbnN0IGNlbGxzID0gcm93LmNlbGxzLm1hcCgoY2VsbCk6IFRleHRUYWJsZUNlbGwgPT4ge1xuICAgICAgd2hpbGUgKHRha2VuW2luZGV4XVtjb2x1bW5dKSB7XG4gICAgICAgIGNvbHVtbisrO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwbGFjZWQgPSB7IC4uLmNlbGwsIHJvdzogaW5kZXgsIGNvbHVtbiwgcm93U3BhbjogTWF0aC5taW4oY2VsbC5yb3dTcGFuLCBzZWN0aW9uRW5kIC0gaW5kZXgpIH07XG4gICAgICBvY2N1cHkodGFrZW4sIHBsYWNlZCk7XG4gICAgICBjb2x1bW4gKz0gcGxhY2VkLmNvbFNwYW47XG4gICAgICBjb2x1bW5zID0gTWF0aC5tYXgoY29sdW1ucywgY29sdW1uKTtcblxuICAgICAgcmV0dXJuIHBsYWNlZDtcbiAgICB9KTtcblxuICAgIHJldHVybiB7IC4uLnJvdywgY2VsbHMgfTtcbiAgfSk7XG5cbiAgcmV0dXJuIHsgcm93cywgY29sdW1ucyB9O1xufVxuXG5mdW5jdGlvbiB0YWJsZVNlY3Rpb24ocm93OiBIVE1MVGFibGVSb3dFbGVtZW50KTogVGV4dFRhYmxlUm93WydzZWN0aW9uJ10ge1xuICBjb25zdCBzZWN0aW9uID0gcm93LnBhcmVudEVsZW1lbnQ/Lm5vZGVOYW1lO1xuXG4gIHJldHVybiBzZWN0aW9uID09PSAnVEhFQUQnID8gJ2hlYWQnIDogc2VjdGlvbiA9PT0gJ1RGT09UJyA/ICdmb290JyA6ICdib2R5Jztcbn1cblxuLy8gT25lIHRoIG9yIHRkLiBBIGhlYWRlciBjZWxsJ3MgcnVucyBhcmUgYm9sZCwgYW5kIGV2ZXJ5IHBhcmFncmFwaCB0YWtlcyB0aGVcbi8vIGNlbGwncyB0ZXh0LWFsaWduIHVubGVzcyBpdCBoYXMgaXRzIG93bjogdGhlIGRlZmF1bHQgbG9vayBjZW50ZXJzIGEgaGVhZGVyXG4vLyBjZWxsIGFuZCBwdXRzIGFueSBvdGhlciBvbiB0aGUgbGVmdC5cbmZ1bmN0aW9uIHRhYmxlQ2VsbChjZWxsOiBIVE1MVGFibGVDZWxsRWxlbWVudCk6IFRleHRUYWJsZUNlbGwge1xuICBjb25zdCBoZWFkZXIgPSBjZWxsLm5vZGVOYW1lID09PSAnVEgnO1xuICBjb25zdCBhbGlnbiA9IGNlbGxBbGlnbihjZWxsLnN0eWxlLnRleHRBbGlnbikgPz8gKGhlYWRlciA/ICdjZW50ZXInIDogJ2xlZnQnKTtcbiAgY29uc3QgdmFsaWduID0gY2VsbC5zdHlsZS52ZXJ0aWNhbEFsaWduO1xuICBjb25zdCBwYXJhZ3JhcGhzOiBUZXh0UGFyYWdyYXBoW10gPSBbXTtcblxuICB3YWxrQmxvY2tzKGNlbGwsIHBhcmFncmFwaHMsIG51bGwsIGhlYWRlciA/IHsgYm9sZDogdHJ1ZSB9IDoge30pO1xuXG4gIHJldHVybiB7XG4gICAgcGFyYWdyYXBoczogcGFyYWdyYXBocy5tYXAoKHBhcmFncmFwaCkgPT4gKHsgLi4ucGFyYWdyYXBoLCBhbGlnbjogcGFyYWdyYXBoLmFsaWduID8/IGFsaWduIH0pKSxcbiAgICBjb2xTcGFuOiBNYXRoLm1heCgxLCBjZWxsLmNvbFNwYW4pLFxuICAgIHJvd1NwYW46IE1hdGgubWF4KDEsIGNlbGwucm93U3BhbiksXG4gICAgcm93OiAwLFxuICAgIGNvbHVtbjogMCxcbiAgICBhbGlnbixcbiAgICB2YWxpZ246IHZhbGlnbiA9PT0gJ3RvcCcgfHwgdmFsaWduID09PSAnbWlkZGxlJyB8fCB2YWxpZ24gPT09ICdib3R0b20nID8gdmFsaWduIDogdW5kZWZpbmVkLFxuICAgIGZpbGw6IGNlbGwuc3R5bGUuYmFja2dyb3VuZENvbG9yID8gaGV4Q29sb3IoY2VsbC5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IpIDogdW5kZWZpbmVkLFxuICB9O1xufVxuXG5mdW5jdGlvbiBjZWxsQWxpZ24odmFsdWU6IHN0cmluZyk6IFRleHRUYWJsZUNlbGxbJ2FsaWduJ10gfCB1bmRlZmluZWQge1xuICByZXR1cm4gdmFsdWUgPT09ICdsZWZ0JyB8fCB2YWx1ZSA9PT0gJ2NlbnRlcicgfHwgdmFsdWUgPT09ICdyaWdodCcgfHwgdmFsdWUgPT09ICdqdXN0aWZ5JyA/IHZhbHVlIDogdW5kZWZpbmVkO1xufVxuXG4vLyBUaGUgaW5kZXgganVzdCBwYXN0IHRoZSBsYXN0IHJvdyBvZiB0aGUgc2VjdGlvbiB0aGUgcm93IGF0IGluZGV4IHNpdHMgaW4uXG5mdW5jdGlvbiByb3dTZWN0aW9uRW5kKHJvd3M6IFRleHRUYWJsZVJvd1tdLCBpbmRleDogbnVtYmVyKTogbnVtYmVyIHtcbiAgbGV0IGVuZCA9IGluZGV4ICsgMTtcbiAgd2hpbGUgKGVuZCA8IHJvd3MubGVuZ3RoICYmIHJvd3NbZW5kXS5zZWN0aW9uID09PSByb3dzW2luZGV4XS5zZWN0aW9uKSB7XG4gICAgZW5kKys7XG4gIH1cblxuICByZXR1cm4gZW5kO1xufVxuXG4vLyBNYXJrIHRoZSBncmlkIHNsb3RzIGEgcGxhY2VkIGNlbGwgY292ZXJzLlxuZnVuY3Rpb24gb2NjdXB5KHRha2VuOiBib29sZWFuW11bXSwgY2VsbDogVGV4dFRhYmxlQ2VsbCk6IHZvaWQge1xuICBmb3IgKGxldCByb3cgPSBjZWxsLnJvdzsgcm93IDwgY2VsbC5yb3cgKyBjZWxsLnJvd1NwYW47IHJvdysrKSB7XG4gICAgZm9yIChsZXQgY29sdW1uID0gY2VsbC5jb2x1bW47IGNvbHVtbiA8IGNlbGwuY29sdW1uICsgY2VsbC5jb2xTcGFuOyBjb2x1bW4rKykge1xuICAgICAgdGFrZW5bcm93XVtjb2x1bW5dID0gdHJ1ZTtcbiAgICB9XG4gIH1cbn1cblxuLy8gQSB0YWJsZSByb3cgYXMgb25lIGxpbmUgb2YgdGV4dDogaXRzIGNlbGxzIGluIG9yZGVyLCBhIGNlbGwncyBvd24gbGluZXNcbi8vIGpvaW5lZCBieSBhIHNwYWNlLlxuZnVuY3Rpb24gcm93UGFyYWdyYXBoKHJvdzogVGV4dFRhYmxlUm93KTogVGV4dFBhcmFncmFwaCB7XG4gIHJldHVybiB7XG4gICAgcnVuczogcm93LmNlbGxzLmZsYXRNYXAoKGNlbGwsIGluZGV4KSA9PiBbXG4gICAgICAuLi4oaW5kZXggPyBbeyB0ZXh0OiBUQUJMRV9DRUxMX1NFUEFSQVRPUiB9XSA6IFtdKSxcbiAgICAgIC4uLmNlbGwucGFyYWdyYXBocy5mbGF0TWFwKChwYXJhZ3JhcGgsIGxpbmUpID0+IFsuLi4obGluZSA/IFt7IHRleHQ6ICcgJyB9XSA6IFtdKSwgLi4ucGFyYWdyYXBoLnJ1bnNdKSxcbiAgICBdKSxcbiAgfTtcbn1cblxuLy8gQW4gZW1wdHkgcGFyYWdyYXBoIGlzIGEgYmxhbmsgbGluZSB0aGUgY2FudmFzIGRyYXdzICg8cD48YnI+PC9wPiwgb3IgYW4gZW1wdHlcbi8vIDxwPiksIHNvIG9uZSBhdCB0aGUgc3RhcnQgb2YgdGhlIGJsb2NrIGtlZXBzIHRoZSB3b3JkcyBiZWxvdyBpdCB3aGVyZSB0aGVcbi8vIGNhbnZhcyBwdXRzIHRoZW0uIEF0IHRoZSBlbmQgb2YgdGhlIHdob2xlIGJsb2NrIGl0IGRyYXdzIG5vdGhpbmcsIGFuZCBpc1xuLy8gZHJvcHBlZCBzbyBpdCBuZXZlciBjb3VudHMgYXMgcnVubmluZyBwYXN0IHRoZSBib3guIEFuIGVtcHR5IHBhcmFncmFwaFxuLy8gYmVmb3JlIGEgdGFibGUgaXMgbm90IGF0IHRoZSBlbmQuXG5mdW5jdGlvbiB0cmltQmxhbmtFbmQoYmxvY2tzOiBUZXh0QmxvY2tbXSk6IHZvaWQge1xuICBjb25zdCBsYXN0ID0gYmxvY2tzW2Jsb2Nrcy5sZW5ndGggLSAxXTtcblxuICB3aGlsZSAobGFzdD8ua2luZCA9PT0gJ3RleHQnICYmIGxhc3QucGFyYWdyYXBocy5sZW5ndGggJiYgIWxhc3QucGFyYWdyYXBoc1tsYXN0LnBhcmFncmFwaHMubGVuZ3RoIC0gMV0ucnVucy5sZW5ndGgpIHtcbiAgICBsYXN0LnBhcmFncmFwaHMucG9wKCk7XG4gIH1cbn1cblxuLy8gYmFzZSBpcyB0aGUgc3R5bGUgZXZlcnkgcnVuIHN0YXJ0cyBmcm9tOiBib2xkIGZvciBhIGhlYWRlciBjZWxsJ3Mgd29yZHMuXG5mdW5jdGlvbiB3YWxrQmxvY2tzKFxuICBwYXJlbnQ6IE5vZGUsXG4gIHBhcmFncmFwaHM6IFRleHRQYXJhZ3JhcGhbXSxcbiAgbGlzdDogJ2J1bGxldCcgfCAnbnVtYmVyJyB8IG51bGwsXG4gIGJhc2U6IFBhcnRpYWw8VGV4dFJ1bj4gPSB7fSxcbik6IHZvaWQge1xuICAvLyBMb29zZSBpbmxpbmUgY29udGVudCBiZXR3ZWVuIGJsb2NrcyAodGV4dCBzdHJhaWdodCB1bmRlciB0aGUgYmxvY2ssIGFuXG4gIC8vIDxsaT4gb3IgYSBjZWxsKSBpcyBnYXRoZXJlZCBpbnRvIGEgcGFyYWdyYXBoIG9mIGl0cyBvd24uXG4gIGxldCBsb29zZTogVGV4dFBhcmFncmFwaCB8IG51bGwgPSBudWxsO1xuICBjb25zdCBmbHVzaCA9ICgpID0+IHtcbiAgICBpZiAobG9vc2UgJiYgaXNTaG93bihsb29zZSkpIHtcbiAgICAgIHBhcmFncmFwaHMucHVzaChsb29zZSk7XG4gICAgfVxuICAgIGxvb3NlID0gbnVsbDtcbiAgfTtcblxuICBwYXJlbnQuY2hpbGROb2Rlcy5mb3JFYWNoKChub2RlKSA9PiB7XG4gICAgY29uc3QgbmFtZSA9IG5vZGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblxuICAgIGlmIChuYW1lID09PSAndWwnIHx8IG5hbWUgPT09ICdvbCcgfHwgbmFtZSA9PT0gJ2xpJyB8fCBuYW1lID09PSAncCcgfHwgL15oWzEtM10kLy50ZXN0KG5hbWUpKSB7XG4gICAgICBmbHVzaCgpO1xuICAgICAgd2Fsa0Jsb2NrKG5vZGUgYXMgSFRNTEVsZW1lbnQsIHBhcmFncmFwaHMsIGxpc3QsIGJhc2UpO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbG9vc2UgPSBsb29zZSA/PyB7IHJ1bnM6IFtdIH07XG4gICAgd2Fsa0lubGluZShub2RlLCBiYXNlLCBsb29zZSwgcGFyYWdyYXBocywgdHJ1ZSk7XG4gIH0pO1xuXG4gIGZsdXNoKCk7XG59XG5cbi8vIFdoZXRoZXIgbG9vc2UgY29udGVudCdzIGxhc3QgbGluZSBzaG93cyBhbnl0aGluZy4gV2hpdGVzcGFjZSBhbG9uZSBiZXR3ZWVuXG4vLyBibG9ja3MgaXMgbm90IGRyYXduLCBhbmQgYSBsaW5lIGEgPGJyPiBlbmRlZCB3YXMgcHVzaGVkIHdoZW4gaXQgZW5kZWQsIHNvIGFcbi8vIHRyYWlsaW5nIDxicj4gYWRkcyBubyBlbXB0eSBsaW5lIGFmdGVyIGl0LlxuZnVuY3Rpb24gaXNTaG93bihsb29zZTogVGV4dFBhcmFncmFwaCk6IGJvb2xlYW4ge1xuICByZXR1cm4gbG9vc2UucnVucy5zb21lKChydW4pID0+IC9bXiBcXHRcXG5cXHJcXGZdLy50ZXN0KHJ1bi50ZXh0KSk7XG59XG5cbmZ1bmN0aW9uIHdhbGtCbG9jayhcbiAgZWxlbWVudDogSFRNTEVsZW1lbnQsXG4gIHBhcmFncmFwaHM6IFRleHRQYXJhZ3JhcGhbXSxcbiAgbGlzdDogJ2J1bGxldCcgfCAnbnVtYmVyJyB8IG51bGwsXG4gIGJhc2U6IFBhcnRpYWw8VGV4dFJ1bj4sXG4pOiB2b2lkIHtcbiAgY29uc3QgbmFtZSA9IGVsZW1lbnQubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblxuICBpZiAobmFtZSA9PT0gJ3VsJyB8fCBuYW1lID09PSAnb2wnKSB7XG4gICAgd2Fsa0Jsb2NrcyhlbGVtZW50LCBwYXJhZ3JhcGhzLCBuYW1lID09PSAndWwnID8gJ2J1bGxldCcgOiAnbnVtYmVyJywgYmFzZSk7XG4gIH0gZWxzZSBpZiAobmFtZSA9PT0gJ2xpJykge1xuICAgIGNvbnN0IGl0ZW06IFRleHRQYXJhZ3JhcGggPSB7IHJ1bnM6IFtdLCBidWxsZXQ6IGxpc3QgPz8gJ2J1bGxldCcgfTtcbiAgICBjb25zdCBuZXN0ZWQ6IFRleHRQYXJhZ3JhcGhbXSA9IFtdO1xuICAgIC8vIEEgbGlzdCBpdGVtJ3MgZmlyc3QgcGFyYWdyYXBoIElTIHRoZSBpdGVtOyBhbnl0aGluZyBhZnRlciBpdCBpcyBpdHMgb3duXG4gICAgLy8gbGluZSB1bmRlciB0aGUgc2FtZSBidWxsZXQuXG4gICAgd2Fsa0Jsb2NrcyhlbGVtZW50LCBuZXN0ZWQsIGxpc3QsIGJhc2UpO1xuICAgIGNvbnN0IFtmaXJzdCwgLi4ucmVzdF0gPSBuZXN0ZWQubGVuZ3RoID8gbmVzdGVkIDogW2l0ZW1dO1xuICAgIHBhcmFncmFwaHMucHVzaCh7IC4uLmZpcnN0LCBidWxsZXQ6IGxpc3QgPz8gJ2J1bGxldCcgfSwgLi4ucmVzdCk7XG4gIH0gZWxzZSB7XG4gICAgd2Fsa1BhcmFncmFwaChlbGVtZW50LCBwYXJhZ3JhcGhzLCBiYXNlKTtcbiAgfVxufVxuXG4vLyBBIHAgb3IgYSBoZWFkaW5nLiBBIDxicj4gZW5kcyBhIGxpbmUsIHNvIGl0cyBsYXN0IGxpbmUgaXMgcHVzaGVkIG9ubHkgd2hlbiBpdFxuLy8gaG9sZHMgd29yZHMgb3Igbm8gPGJyPiBjYW1lIGJlZm9yZSBpdDogPHA+PGJyPjwvcD4gaXMgb25lIGJsYW5rIGxpbmUsXG4vLyA8cD5hPGJyPjwvcD4gb25lIGxpbmUgYW5kIDxwPmE8YnI+YjwvcD4gdHdvLCBhcyBhIGJyb3dzZXIgZHJhd3MgdGhlbS5cbmZ1bmN0aW9uIHdhbGtQYXJhZ3JhcGgoZWxlbWVudDogSFRNTEVsZW1lbnQsIHBhcmFncmFwaHM6IFRleHRQYXJhZ3JhcGhbXSwgYmFzZTogUGFydGlhbDxUZXh0UnVuPik6IHZvaWQge1xuICBjb25zdCBuYW1lID0gZWxlbWVudC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuICBjb25zdCBoZWFkaW5nID0gbmFtZS5zdGFydHNXaXRoKCdoJykgPyBOdW1iZXIobmFtZVsxXSkgOiB1bmRlZmluZWQ7XG4gIGNvbnN0IHBhcmFncmFwaDogVGV4dFBhcmFncmFwaCA9IHtcbiAgICBydW5zOiBbXSxcbiAgICBhbGlnbjogYmxvY2tBbGlnbihlbGVtZW50KSxcbiAgICBidWxsZXQ6IHVuZGVmaW5lZCxcbiAgICBoZWFkaW5nLFxuICB9O1xuICBjb25zdCBzdHlsZTogUGFydGlhbDxUZXh0UnVuPiA9IGhlYWRpbmdcbiAgICA/IHsgLi4uYmFzZSwgYm9sZDogdHJ1ZSwgZm9udFNpemU6IEhFQURJTkdfVEVYVF9TSVpFU1toZWFkaW5nXSB9XG4gICAgOiBiYXNlO1xuXG4gIGNvbnN0IGJyZWFrcyA9IHdhbGtJbmxpbmUoZWxlbWVudCwgc3R5bGUsIHBhcmFncmFwaCwgcGFyYWdyYXBocyk7XG4gIGlmIChwYXJhZ3JhcGgucnVucy5sZW5ndGggfHwgIWJyZWFrcykge1xuICAgIHBhcmFncmFwaHMucHVzaChwYXJhZ3JhcGgpO1xuICB9XG59XG5cbi8vIEFjY3VtdWxhdGUgaW5saW5lIHN0eWxlcyBkb3duIHRoZSB0cmVlLiBBIDxicj4gZW5kcyB0aGUgY3VycmVudCBsaW5lOiB0aGVcbi8vIHJ1bnMgYWZ0ZXIgaXQgc3RhcnQgYSBuZXcgcGFyYWdyYXBoIHdpdGggdGhlIHNhbWUgYWxpZ25tZW50IGFuZCBidWxsZXQuXG4vLyBSZXR1cm5zIGhvdyBtYW55IGxpbmVzIGEgPGJyPiBlbmRlZC5cbmZ1bmN0aW9uIHdhbGtJbmxpbmUoXG4gIG5vZGU6IE5vZGUsXG4gIHN0eWxlOiBQYXJ0aWFsPFRleHRSdW4+LFxuICBwYXJhZ3JhcGg6IFRleHRQYXJhZ3JhcGgsXG4gIHBhcmFncmFwaHM6IFRleHRQYXJhZ3JhcGhbXSxcbiAgaXNTZWxmID0gZmFsc2UsXG4pOiBudW1iZXIge1xuICBjb25zdCBub2RlcyA9IGlzU2VsZiA/IFtub2RlXSA6IEFycmF5LmZyb20obm9kZS5jaGlsZE5vZGVzKTtcblxuICByZXR1cm4gbm9kZXMucmVkdWNlKChicmVha3MsIGNoaWxkKSA9PiBicmVha3MgKyB3YWxrSW5saW5lTm9kZShjaGlsZCwgc3R5bGUsIHBhcmFncmFwaCwgcGFyYWdyYXBocyksIDApO1xufVxuXG5mdW5jdGlvbiB3YWxrSW5saW5lTm9kZShcbiAgbm9kZTogTm9kZSxcbiAgc3R5bGU6IFBhcnRpYWw8VGV4dFJ1bj4sXG4gIHBhcmFncmFwaDogVGV4dFBhcmFncmFwaCxcbiAgcGFyYWdyYXBoczogVGV4dFBhcmFncmFwaFtdLFxuKTogbnVtYmVyIHtcbiAgaWYgKG5vZGUubm9kZVR5cGUgPT09IE5vZGUuVEVYVF9OT0RFKSB7XG4gICAgY29uc3QgdGV4dCA9IG5vZGUudGV4dENvbnRlbnQgPz8gJyc7XG4gICAgaWYgKHRleHQpIHtcbiAgICAgIHBhcmFncmFwaC5ydW5zLnB1c2goeyAuLi5zdHlsZSwgdGV4dCB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gMDtcbiAgfVxuXG4gIGlmIChub2RlLm5vZGVUeXBlICE9PSBOb2RlLkVMRU1FTlRfTk9ERSkge1xuICAgIHJldHVybiAwO1xuICB9XG5cbiAgY29uc3QgZWxlbWVudCA9IG5vZGUgYXMgSFRNTEVsZW1lbnQ7XG5cbiAgaWYgKGVsZW1lbnQubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ2JyJykge1xuICAgIHBhcmFncmFwaHMucHVzaCh7IC4uLnBhcmFncmFwaCwgcnVuczogWy4uLnBhcmFncmFwaC5ydW5zXSB9KTtcbiAgICBwYXJhZ3JhcGgucnVucy5sZW5ndGggPSAwO1xuXG4gICAgcmV0dXJuIDE7XG4gIH1cblxuICByZXR1cm4gd2Fsa0lubGluZShlbGVtZW50LCB7IC4uLnN0eWxlLCAuLi5pbmxpbmVTdHlsZShlbGVtZW50KSB9LCBwYXJhZ3JhcGgsIHBhcmFncmFwaHMpO1xufVxuXG5mdW5jdGlvbiBpbmxpbmVTdHlsZShlbGVtZW50OiBIVE1MRWxlbWVudCk6IFBhcnRpYWw8VGV4dFJ1bj4ge1xuICBjb25zdCBuYW1lID0gZWxlbWVudC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuICBjb25zdCBzdHlsZTogUGFydGlhbDxUZXh0UnVuPiA9IHt9O1xuXG4gIGlmIChuYW1lID09PSAnc3Ryb25nJykge1xuICAgIHN0eWxlLmJvbGQgPSB0cnVlO1xuICB9XG4gIGlmIChuYW1lID09PSAnZW0nKSB7XG4gICAgc3R5bGUuaXRhbGljID0gdHJ1ZTtcbiAgfVxuICBpZiAobmFtZSA9PT0gJ3UnKSB7XG4gICAgc3R5bGUudW5kZXJsaW5lID0gdHJ1ZTtcbiAgfVxuICBpZiAobmFtZSA9PT0gJ3MnKSB7XG4gICAgc3R5bGUuc3RyaWtlID0gdHJ1ZTtcbiAgfVxuICBpZiAobmFtZSA9PT0gJ2EnKSB7XG4gICAgc3R5bGUubGluayA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdocmVmJykgPz8gdW5kZWZpbmVkO1xuICAgIHN0eWxlLnVuZGVybGluZSA9IHRydWU7XG4gIH1cblxuICAvLyBXaGF0IGlzIG5vIGNvbG9yIGxlYXZlcyB0aGUgY29sb3IgdGhlIHJ1biBpbmhlcml0cy5cbiAgY29uc3QgY3NzID0gZWxlbWVudC5zdHlsZTtcbiAgY29uc3QgY29sb3IgPSBjc3MuY29sb3IgPyBoZXhDb2xvcihjc3MuY29sb3IpIDogdW5kZWZpbmVkO1xuICBjb25zdCBoaWdobGlnaHQgPSBjc3MuYmFja2dyb3VuZENvbG9yID8gaGV4Q29sb3IoY3NzLmJhY2tncm91bmRDb2xvcikgOiB1bmRlZmluZWQ7XG4gIGlmIChjb2xvcikge1xuICAgIHN0eWxlLmNvbG9yID0gY29sb3I7XG4gIH1cbiAgaWYgKGhpZ2hsaWdodCkge1xuICAgIHN0eWxlLmhpZ2hsaWdodCA9IGhpZ2hsaWdodDtcbiAgfVxuICBpZiAoY3NzLmZvbnRTaXplKSB7XG4gICAgc3R5bGUuZm9udFNpemUgPSBwb2ludHMoY3NzLmZvbnRTaXplKTtcbiAgfVxuICBpZiAoY3NzLmZvbnRXZWlnaHQpIHtcbiAgICBzdHlsZS5ib2xkID0gY3NzLmZvbnRXZWlnaHQgPT09ICdib2xkJyB8fCBOdW1iZXIoY3NzLmZvbnRXZWlnaHQpID49IDYwMDtcbiAgfVxuICBpZiAoY3NzLmZvbnRTdHlsZSkge1xuICAgIHN0eWxlLml0YWxpYyA9IGNzcy5mb250U3R5bGUgPT09ICdpdGFsaWMnO1xuICB9XG4gIGlmIChjc3MudGV4dERlY29yYXRpb24pIHtcbiAgICBzdHlsZS51bmRlcmxpbmUgPSBjc3MudGV4dERlY29yYXRpb24uaW5jbHVkZXMoJ3VuZGVybGluZScpO1xuICAgIHN0eWxlLnN0cmlrZSA9IGNzcy50ZXh0RGVjb3JhdGlvbi5pbmNsdWRlcygnbGluZS10aHJvdWdoJyk7XG4gIH1cbiAgaWYgKGNzcy5mb250RmFtaWx5KSB7XG4gICAgc3R5bGUuZm9udEZhY2UgPSBjc3MuZm9udEZhbWlseS5zcGxpdCgnLCcpWzBdLnJlcGxhY2UoL1tcIiddL2csICcnKS50cmltKCk7XG4gIH1cblxuICByZXR1cm4gc3R5bGU7XG59XG5cbmZ1bmN0aW9uIGJsb2NrQWxpZ24oZWxlbWVudDogSFRNTEVsZW1lbnQpOiBUZXh0UGFyYWdyYXBoWydhbGlnbiddIHtcbiAgY29uc3QgYWxpZ24gPSBlbGVtZW50LnN0eWxlLnRleHRBbGlnbjtcblxuICByZXR1cm4gYWxpZ24gPT09ICdjZW50ZXInIHx8IGFsaWduID09PSAncmlnaHQnIHx8IGFsaWduID09PSAnanVzdGlmeScgPyBhbGlnbiA6IHVuZGVmaW5lZDtcbn1cblxuLy8gQSBDU1MgZm9udC1zaXplIGluIHBvaW50cy4gVGhlIGNhbnZhcyByZW5kZXJzIGF0IDk2cHggcGVyIGluY2gsIHNvIDFweCBpc1xuLy8gZXhhY3RseSAwLjc1cHQ7IGVtL3JlbS8lIGFyZSByZWxhdGl2ZSB0byB0aGUgYm9keSBzaXplLlxuZnVuY3Rpb24gcG9pbnRzKHZhbHVlOiBzdHJpbmcpOiBudW1iZXIgfCB1bmRlZmluZWQge1xuICBjb25zdCBtYXRjaCA9IC9eKFtcXGQuXSspKHB0fHB4fGVtfHJlbXwlKSQvLmV4ZWModmFsdWUudHJpbSgpKTtcbiAgaWYgKCFtYXRjaCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBzaXplID0gTnVtYmVyKG1hdGNoWzFdKTtcbiAgc3dpdGNoIChtYXRjaFsyXSkge1xuICAgIGNhc2UgJ3B0JzpcbiAgICAgIHJldHVybiBzaXplO1xuICAgIGNhc2UgJ3B4JzpcbiAgICAgIHJldHVybiBzaXplICogMC43NTtcbiAgICBjYXNlICclJzpcbiAgICAgIHJldHVybiAoc2l6ZSAvIDEwMCkgKiBERUZBVUxUX1RFWFRfU0laRTtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIHNpemUgKiBERUZBVUxUX1RFWFRfU0laRTtcbiAgfVxufVxuXG4vLyBBbnkgQ1NTIGNvbG9yIHRoZSBhbGxvd2xpc3QgbGV0cyB0aHJvdWdoIChoZXgsIHJnYigpLCBhIG5hbWUpIGFzICNycmdnYmIg4oCUXG4vLyB0aGUgb25lIGZvcm0gYm90aCBleHBvcnRzIGFjY2VwdC4gVGhlIGJyb3dzZXIgcmVzb2x2ZXMgaXQsIHNvIGEgbmFtZWQgY29sb3Jcbi8vIGNvbWVzIG91dCBleGFjdGx5IGFzIHRoZSBjYW52YXMgcGFpbnRlZCBpdC4gQSB2YWx1ZSB0aGF0IGlzIG5vIGNvbG9yIG9mIGl0c1xuLy8gb3duIChpbmhlcml0LCBjdXJyZW50Y29sb3IsIGEgdHlwbykgb3IgcGFpbnRzIG5vdGhpbmcgKHRyYW5zcGFyZW50LCBhbiBhbHBoYVxuLy8gb2YgMCkgaXMgdW5kZWZpbmVkLCBzbyBhbiBleHBvcnQgbmV2ZXIgcGFpbnRzIGl0IGJsYWNrLlxubGV0IGNvbG9yQ29udGV4dDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEIHwgbnVsbCA9IG51bGw7XG5cbmZ1bmN0aW9uIGhleENvbG9yKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb2xvckNvbnRleHQgPSBjb2xvckNvbnRleHQgPz8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJykuZ2V0Q29udGV4dCgnMmQnKTtcbiAgaWYgKCFjb2xvckNvbnRleHQgfHwgL15cXHMqY3VycmVudGNvbG9yXFxzKiQvaS50ZXN0KHZhbHVlKSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvLyBBIHZhbHVlIHRoZSBjYW52YXMgY2Fubm90IHJlYWQgbGVhdmVzIHRoZSBjb2xvciBzZXQgYmVmb3JlIGl0LCBzbyBpdCByZWFkc1xuICAvLyBiYWNrIG9uZSB3YXkgb3ZlciBibGFjayBhbmQgYW5vdGhlciBvdmVyIHdoaXRlLiAoY3VycmVudGNvbG9yIHJlYWRzIGFzXG4gIC8vIGJsYWNrIG92ZXIgYm90aCwgaGVuY2UgdGhlIGNoZWNrIGFib3ZlLilcbiAgY29uc3QgcmVzb2x2ZWQgPSByZXNvbHZlQ29sb3IoY29sb3JDb250ZXh0LCAnIzAwMDAwMCcsIHZhbHVlKTtcbiAgaWYgKHJlc29sdmVkICE9PSByZXNvbHZlQ29sb3IoY29sb3JDb250ZXh0LCAnI2ZmZmZmZicsIHZhbHVlKSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBpZiAocmVzb2x2ZWQuc3RhcnRzV2l0aCgnIycpKSB7XG4gICAgcmV0dXJuIHJlc29sdmVkO1xuICB9XG5cbiAgLy8gcmdiYSguLi4pIGZvciBhIHRyYW5zbHVjZW50IGNvbG9yIOKAlCBkcm9wIHRoZSBhbHBoYSwga2VlcCB0aGUgaHVlLlxuICBjb25zdCBbcmVkLCBncmVlbiwgYmx1ZSwgYWxwaGFdID0gcmVzb2x2ZWQubWF0Y2goL1tcXGQuXSsvZyk/Lm1hcChOdW1iZXIpID8/IFtdO1xuXG4gIHJldHVybiBibHVlID09PSB1bmRlZmluZWQgfHwgYWxwaGEgPT09IDBcbiAgICA/IHVuZGVmaW5lZFxuICAgIDogYCMke1tyZWQsIGdyZWVuLCBibHVlXS5tYXAoKGNoYW5uZWwpID0+IE1hdGgucm91bmQoY2hhbm5lbCkudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDIsICcwJykpLmpvaW4oJycpfWA7XG59XG5cbi8vIFdoYXQgdGhlIGNhbnZhcyByZWFkcyB2YWx1ZSBhcywgc2V0IG92ZXIgc2VlZC5cbmZ1bmN0aW9uIHJlc29sdmVDb2xvcihjb250ZXh0OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQsIHNlZWQ6IHN0cmluZywgdmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnRleHQuZmlsbFN0eWxlID0gc2VlZDtcbiAgY29udGV4dC5maWxsU3R5bGUgPSB2YWx1ZTtcblxuICByZXR1cm4gU3RyaW5nKGNvbnRleHQuZmlsbFN0eWxlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVzY2FwZUh0bWwodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiB2YWx1ZVxuICAgIC5yZXBsYWNlKC8mL2csICcmYW1wOycpXG4gICAgLnJlcGxhY2UoLzwvZywgJyZsdDsnKVxuICAgIC5yZXBsYWNlKC8+L2csICcmZ3Q7JylcbiAgICAucmVwbGFjZSgvXCIvZywgJyZxdW90OycpO1xufVxuIl19