@firestitch/report 18.9.0 → 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 (190) hide show
  1. package/app/reports/anchor-at-point.d.ts +14 -0
  2. package/app/reports/canvas-landing-page.d.ts +2 -0
  3. package/app/reports/components/component-chart/component-chart.component.d.ts +18 -2
  4. package/app/reports/components/component-kpi/component-kpi.component.d.ts +4 -1
  5. package/app/reports/components/report-canvas/report-canvas.component.d.ts +3 -0
  6. package/app/reports/components/report-component/report-component.component.d.ts +35 -1
  7. package/app/reports/components/report-view-picker/report-view-picker.component.d.ts +21 -0
  8. package/app/reports/data/report.data.d.ts +17 -2
  9. package/app/reports/dialogs/component-settings/component-settings.component.d.ts +18 -3
  10. package/app/reports/dialogs/report-settings/report-settings.component.d.ts +15 -6
  11. package/app/reports/dialogs/report-view/report-view-dialog.component.d.ts +13 -0
  12. package/app/reports/drill-crumbs.d.ts +12 -0
  13. package/app/reports/export/report-export-collector.service.d.ts +13 -4
  14. package/app/reports/export/report-filter-lines.d.ts +18 -0
  15. package/app/reports/filter-settings-rules.d.ts +33 -0
  16. package/app/reports/format.d.ts +0 -1
  17. package/app/reports/interfaces/canvas-landing-input.interface.d.ts +8 -0
  18. package/app/reports/interfaces/component-data-applied.interface.d.ts +13 -0
  19. package/app/reports/interfaces/component-data-drill.interface.d.ts +22 -0
  20. package/app/reports/interfaces/filter-bar-placement.type.d.ts +1 -0
  21. package/app/reports/interfaces/filter-component-toggle-state.interface.d.ts +4 -0
  22. package/app/reports/interfaces/filter-settings-option.interface.d.ts +4 -0
  23. package/app/reports/interfaces/filter-type-select-state.interface.d.ts +5 -0
  24. package/app/reports/interfaces/report-chart-hit.interface.d.ts +5 -0
  25. package/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.d.ts +4 -0
  26. package/app/reports/interfaces/report-chat-viewer-cross-filter.interface.d.ts +7 -0
  27. package/app/reports/interfaces/report-chat-viewer-detail.interface.d.ts +4 -0
  28. package/app/reports/interfaces/report-chat-viewer-drill-step.interface.d.ts +5 -0
  29. package/app/reports/interfaces/report-chat-viewer-drill.interface.d.ts +5 -0
  30. package/app/reports/interfaces/report-chat-viewer-filter.interface.d.ts +3 -0
  31. package/app/reports/interfaces/report-chat-viewer-selection.interface.d.ts +5 -0
  32. package/app/reports/interfaces/report-chat-viewer-state.interface.d.ts +12 -0
  33. package/app/reports/interfaces/report-drill-crumb.interface.d.ts +6 -0
  34. package/app/reports/interfaces/report-drill-refusal.type.d.ts +1 -0
  35. package/app/reports/interfaces/report-drill-step.interface.d.ts +5 -0
  36. package/app/reports/interfaces/report-export-line-kind.type.d.ts +1 -0
  37. package/app/reports/interfaces/report-export-line.interface.d.ts +8 -0
  38. package/app/reports/interfaces/report-export-lines-input.interface.d.ts +9 -0
  39. package/app/reports/interfaces/report-export-snapshot.interface.d.ts +15 -0
  40. package/app/reports/interfaces/report-filter-line-context.interface.d.ts +8 -0
  41. package/app/reports/interfaces/report-filter-line-form.type.d.ts +1 -0
  42. package/app/reports/interfaces/report-filter-match.type.d.ts +1 -0
  43. package/app/reports/interfaces/report-filter-option-pair.interface.d.ts +4 -0
  44. package/app/reports/interfaces/report-filter-options-ask.interface.d.ts +6 -0
  45. package/app/reports/interfaces/report-filter-options-list.interface.d.ts +7 -0
  46. package/app/reports/interfaces/report-filter-options-request.interface.d.ts +6 -0
  47. package/app/reports/interfaces/report-filter-options-stream.interface.d.ts +11 -0
  48. package/app/reports/interfaces/report-filter-options.interface.d.ts +7 -0
  49. package/app/reports/interfaces/report-filter-skip.type.d.ts +1 -0
  50. package/app/reports/interfaces/report-mark-action.type.d.ts +1 -0
  51. package/app/reports/interfaces/report-mark-click.interface.d.ts +13 -0
  52. package/app/reports/interfaces/report-mark-context.interface.d.ts +6 -0
  53. package/app/reports/interfaces/report-mark-decision.interface.d.ts +6 -0
  54. package/app/reports/interfaces/report-mark-event.interface.d.ts +11 -0
  55. package/app/reports/interfaces/report-mark-point.interface.d.ts +8 -0
  56. package/app/reports/interfaces/report-temporary-state.interface.d.ts +4 -0
  57. package/app/reports/interfaces/report-tile-state.interface.d.ts +8 -0
  58. package/app/reports/interfaces/report-url-link.interface.d.ts +4 -0
  59. package/app/reports/interfaces/report-url-value-name.type.d.ts +1 -0
  60. package/app/reports/interfaces/report-url-write.interface.d.ts +4 -0
  61. package/app/reports/interfaces/report-view-config.interface.d.ts +11 -0
  62. package/app/reports/interfaces/report-view-create.interface.d.ts +7 -0
  63. package/app/reports/interfaces/report-view-deleted.interface.d.ts +4 -0
  64. package/app/reports/interfaces/report-view-dialog-data.interface.d.ts +7 -0
  65. package/app/reports/interfaces/report-view-dropped.interface.d.ts +5 -0
  66. package/app/reports/interfaces/report-view-menu-item.interface.d.ts +10 -0
  67. package/app/reports/interfaces/report-view-summary.interface.d.ts +11 -0
  68. package/app/reports/interfaces/report-view.interface.d.ts +7 -0
  69. package/app/reports/interfaces/report-viewer-feature.type.d.ts +1 -0
  70. package/app/reports/interfaces/report-views.interface.d.ts +7 -0
  71. package/app/reports/interfaces/report.interface.d.ts +27 -3
  72. package/app/reports/interfaces/tile-load-result.interface.d.ts +4 -0
  73. package/app/reports/mark-click.d.ts +20 -0
  74. package/app/reports/option-builder.d.ts +12 -1
  75. package/app/reports/report-chat-viewer-state.d.ts +8 -0
  76. package/app/reports/report-date-presets.d.ts +2 -0
  77. package/app/reports/report-filter-items.d.ts +27 -22
  78. package/app/reports/report-tile.d.ts +2 -0
  79. package/app/reports/report-url-state.d.ts +27 -10
  80. package/app/reports/report-view-config.d.ts +36 -0
  81. package/app/reports/report-view-menu.d.ts +15 -0
  82. package/app/reports/report-viewer-features.d.ts +5 -0
  83. package/app/reports/services/report-filter-options.service.d.ts +26 -0
  84. package/app/reports/services/report-filter-state.service.d.ts +64 -1
  85. package/app/reports/services/report-view.service.d.ts +51 -0
  86. package/app/reports/tile-data-state.d.ts +7 -0
  87. package/app/reports/tile-loads.d.ts +4 -0
  88. package/app/reports/views/report/fs-ai-report.component.d.ts +9 -1
  89. package/app/reports/views/report/report.component.d.ts +6 -0
  90. package/esm2022/app/reports/anchor-at-point.mjs +49 -0
  91. package/esm2022/app/reports/canvas-landing-page.mjs +25 -0
  92. package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +97 -5
  93. package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +11 -4
  94. package/esm2022/app/reports/components/component-list/component-list.component.mjs +7 -1
  95. package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +47 -32
  96. package/esm2022/app/reports/components/report-component/report-component.component.mjs +257 -61
  97. package/esm2022/app/reports/components/report-view-picker/report-view-picker.component.mjs +115 -0
  98. package/esm2022/app/reports/data/report.data.mjs +87 -10
  99. package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +106 -51
  100. package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +86 -90
  101. package/esm2022/app/reports/dialogs/report-view/report-view-dialog.component.mjs +52 -0
  102. package/esm2022/app/reports/drill-crumbs.mjs +73 -0
  103. package/esm2022/app/reports/export/report-export-collector.service.mjs +187 -117
  104. package/esm2022/app/reports/export/report-filter-lines.mjs +235 -0
  105. package/esm2022/app/reports/export/report-pdf.service.mjs +12 -7
  106. package/esm2022/app/reports/export/report-pptx.service.mjs +18 -14
  107. package/esm2022/app/reports/filter-settings-rules.mjs +283 -0
  108. package/esm2022/app/reports/format.mjs +2 -22
  109. package/esm2022/app/reports/interfaces/canvas-landing-input.interface.mjs +2 -0
  110. package/esm2022/app/reports/interfaces/component-data-applied.interface.mjs +2 -0
  111. package/esm2022/app/reports/interfaces/component-data-drill.interface.mjs +2 -0
  112. package/esm2022/app/reports/interfaces/filter-bar-placement.type.mjs +2 -0
  113. package/esm2022/app/reports/interfaces/filter-component-toggle-state.interface.mjs +2 -0
  114. package/esm2022/app/reports/interfaces/filter-settings-option.interface.mjs +2 -0
  115. package/esm2022/app/reports/interfaces/filter-type-select-state.interface.mjs +2 -0
  116. package/esm2022/app/reports/interfaces/report-chart-hit.interface.mjs +2 -0
  117. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.mjs +2 -0
  118. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter.interface.mjs +2 -0
  119. package/esm2022/app/reports/interfaces/report-chat-viewer-detail.interface.mjs +2 -0
  120. package/esm2022/app/reports/interfaces/report-chat-viewer-drill-step.interface.mjs +2 -0
  121. package/esm2022/app/reports/interfaces/report-chat-viewer-drill.interface.mjs +2 -0
  122. package/esm2022/app/reports/interfaces/report-chat-viewer-filter.interface.mjs +1 -1
  123. package/esm2022/app/reports/interfaces/report-chat-viewer-selection.interface.mjs +2 -0
  124. package/esm2022/app/reports/interfaces/report-chat-viewer-state.interface.mjs +1 -1
  125. package/esm2022/app/reports/interfaces/report-drill-crumb.interface.mjs +2 -0
  126. package/esm2022/app/reports/interfaces/report-drill-refusal.type.mjs +2 -0
  127. package/esm2022/app/reports/interfaces/report-drill-step.interface.mjs +2 -0
  128. package/esm2022/app/reports/interfaces/report-export-line-kind.type.mjs +2 -0
  129. package/esm2022/app/reports/interfaces/report-export-line.interface.mjs +2 -0
  130. package/esm2022/app/reports/interfaces/report-export-lines-input.interface.mjs +2 -0
  131. package/esm2022/app/reports/interfaces/report-export-snapshot.interface.mjs +2 -0
  132. package/esm2022/app/reports/interfaces/report-filter-line-context.interface.mjs +2 -0
  133. package/esm2022/app/reports/interfaces/report-filter-line-form.type.mjs +2 -0
  134. package/esm2022/app/reports/interfaces/report-filter-match.type.mjs +2 -0
  135. package/esm2022/app/reports/interfaces/report-filter-option-pair.interface.mjs +2 -0
  136. package/esm2022/app/reports/interfaces/report-filter-options-ask.interface.mjs +2 -0
  137. package/esm2022/app/reports/interfaces/report-filter-options-list.interface.mjs +2 -0
  138. package/esm2022/app/reports/interfaces/report-filter-options-request.interface.mjs +2 -0
  139. package/esm2022/app/reports/interfaces/report-filter-options-stream.interface.mjs +2 -0
  140. package/esm2022/app/reports/interfaces/report-filter-options.interface.mjs +2 -0
  141. package/esm2022/app/reports/interfaces/report-filter-skip.type.mjs +2 -0
  142. package/esm2022/app/reports/interfaces/report-mark-action.type.mjs +2 -0
  143. package/esm2022/app/reports/interfaces/report-mark-click.interface.mjs +2 -0
  144. package/esm2022/app/reports/interfaces/report-mark-context.interface.mjs +2 -0
  145. package/esm2022/app/reports/interfaces/report-mark-decision.interface.mjs +2 -0
  146. package/esm2022/app/reports/interfaces/report-mark-event.interface.mjs +2 -0
  147. package/esm2022/app/reports/interfaces/report-mark-point.interface.mjs +2 -0
  148. package/esm2022/app/reports/interfaces/report-temporary-state.interface.mjs +2 -0
  149. package/esm2022/app/reports/interfaces/report-tile-state.interface.mjs +2 -0
  150. package/esm2022/app/reports/interfaces/report-url-link.interface.mjs +2 -0
  151. package/esm2022/app/reports/interfaces/report-url-value-name.type.mjs +2 -0
  152. package/esm2022/app/reports/interfaces/report-url-write.interface.mjs +2 -0
  153. package/esm2022/app/reports/interfaces/report-view-config.interface.mjs +2 -0
  154. package/esm2022/app/reports/interfaces/report-view-create.interface.mjs +2 -0
  155. package/esm2022/app/reports/interfaces/report-view-deleted.interface.mjs +2 -0
  156. package/esm2022/app/reports/interfaces/report-view-dialog-data.interface.mjs +2 -0
  157. package/esm2022/app/reports/interfaces/report-view-dropped.interface.mjs +2 -0
  158. package/esm2022/app/reports/interfaces/report-view-menu-item.interface.mjs +2 -0
  159. package/esm2022/app/reports/interfaces/report-view-summary.interface.mjs +2 -0
  160. package/esm2022/app/reports/interfaces/report-view.interface.mjs +2 -0
  161. package/esm2022/app/reports/interfaces/report-viewer-feature.type.mjs +2 -0
  162. package/esm2022/app/reports/interfaces/report-views.interface.mjs +2 -0
  163. package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
  164. package/esm2022/app/reports/interfaces/tile-load-result.interface.mjs +2 -0
  165. package/esm2022/app/reports/mark-click.mjs +193 -0
  166. package/esm2022/app/reports/option-builder.mjs +159 -15
  167. package/esm2022/app/reports/report-chat-viewer-state.mjs +34 -0
  168. package/esm2022/app/reports/report-date-presets.mjs +18 -0
  169. package/esm2022/app/reports/report-filter-items.mjs +343 -72
  170. package/esm2022/app/reports/report-tile.mjs +12 -0
  171. package/esm2022/app/reports/report-url-state.mjs +596 -108
  172. package/esm2022/app/reports/report-view-config.mjs +697 -0
  173. package/esm2022/app/reports/report-view-menu.mjs +119 -0
  174. package/esm2022/app/reports/report-viewer-features.mjs +42 -0
  175. package/esm2022/app/reports/services/report-filter-options.service.mjs +238 -0
  176. package/esm2022/app/reports/services/report-filter-state.service.mjs +697 -62
  177. package/esm2022/app/reports/services/report-view.service.mjs +358 -0
  178. package/esm2022/app/reports/tile-data-state.mjs +127 -0
  179. package/esm2022/app/reports/tile-loads.mjs +38 -0
  180. package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +177 -46
  181. package/esm2022/app/reports/views/report/report.component.mjs +103 -23
  182. package/esm2022/public_api.mjs +23 -1
  183. package/fesm2022/{firestitch-report-echarts-DBMOHmBF.mjs → firestitch-report-echarts-UBg8Wlhd.mjs} +2 -2
  184. package/fesm2022/{firestitch-report-echarts-DBMOHmBF.mjs.map → firestitch-report-echarts-UBg8Wlhd.mjs.map} +1 -1
  185. package/fesm2022/{firestitch-report-firestitch-report-CqbXT1gh.mjs → firestitch-report-firestitch-report-B1keNrcK.mjs} +9063 -4272
  186. package/fesm2022/firestitch-report-firestitch-report-B1keNrcK.mjs.map +1 -0
  187. package/fesm2022/firestitch-report.mjs +1 -1
  188. package/package.json +1 -1
  189. package/public_api.d.ts +22 -0
  190. package/fesm2022/firestitch-report-firestitch-report-CqbXT1gh.mjs.map +0 -1
@@ -0,0 +1,358 @@
1
+ import { HttpContext } from '@angular/common/http';
2
+ import { DestroyRef, Injectable, computed, inject, signal } from '@angular/core';
3
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
+ import { DisplayApiError, ProcessApiError } from '@firestitch/api';
5
+ import { FsMessage } from '@firestitch/message';
6
+ import { EMPTY, of } from 'rxjs';
7
+ import { catchError, map, switchMap, tap } from 'rxjs/operators';
8
+ import { ReportData } from '../data/report.data';
9
+ import { listSortTerms } from '../list-config';
10
+ import { URL_TOO_LONG_MESSAGE, hasReportUrlState, paramsToViewConfig, readReportUrlLink, reportParamsToClear, urlValueNames, viewConfigToParams, } from '../report-url-state';
11
+ import { REPORT_VIEW_CONFIG_VERSION, VIEW_NOT_AVAILABLE_MESSAGE, toStoredGroupValue, viewConfigDiff, viewDroppedCount, viewDroppedMessage, withStoredKeys, } from '../report-view-config';
12
+ import { ReportFilterStateService } from './report-filter-state.service';
13
+ import * as i0 from "@angular/core";
14
+ // The open report's saved views, per open report beside the state service:
15
+ // the list the viewer may see, the view that is open, the order a report
16
+ // opens in, the calls that change a view, and the link the screen writes.
17
+ // The viewer state stays ReportFilterStateService's: this service puts a
18
+ // view on screen through apply() and reads the screen through snapshot(),
19
+ // base and viewChanged. Nothing here runs for a report whose server does not
20
+ // list 'views' (serves()); such a report keeps the link it always had.
21
+ //
22
+ // The order a report opens in (open(), on its first load only):
23
+ // 1. A link that carries state (any owned key, match or rv). rv names the shared
24
+ // view it is a diff from; one the viewer cannot open leaves the diff on
25
+ // the report's defaults, with a note. rpv never changes the screen: when
26
+ // the viewer owns that view it is the open view, and the screen is
27
+ // compared with it. The tiles wait for that one view only; the list loads
28
+ // behind them. A link with rpv and no state (the owner's view was open on
29
+ // the report's defaults) is a link for the owner only; for anyone else
30
+ // it is no link.
31
+ // 2. Else the viewer's default view.
32
+ // 3. Else the report's authored defaults.
33
+ // A page in the link beats a view's page.
34
+ //
35
+ // The link (urlParams): while a shared view is open, rv and what differs
36
+ // from it; while one of the viewer's own views is open, or when the screen
37
+ // went back to something a link cannot say on top of the shared view (see
38
+ // viewConfigDiff), everything that differs from the report's defaults, and
39
+ // rpv when the viewer owns the open view. Sharing the open view, or no
40
+ // longer sharing it, writes the link again.
41
+ export class ReportViewService {
42
+ // The views the viewer may see, names and flags only: its own first, then
43
+ // the ones others share. Empty until the list is read.
44
+ views = computed(() => this._views());
45
+ // The viewer may share its views with everyone.
46
+ canShare = computed(() => this._canShare());
47
+ // The open view, with its config as it was read or saved; null while the
48
+ // screen is on the report's defaults.
49
+ openView = computed(() => this._openView());
50
+ // Whether the screen differs from the open view; false with none open.
51
+ viewChanged = computed(() => !!this._openView() && this._filterState.viewChanged());
52
+ _reportData = inject(ReportData);
53
+ _filterState = inject(ReportFilterStateService);
54
+ _message = inject(FsMessage);
55
+ _destroyRef = inject(DestroyRef);
56
+ _views = signal([]);
57
+ _canShare = signal(false);
58
+ _openView = signal(null);
59
+ // The report the views belong to.
60
+ _reportId = null;
61
+ // The note that the screen is too long for a link shows once per report.
62
+ _tooLongShown = false;
63
+ // Whether the open report's server keeps saved views.
64
+ serves(report) {
65
+ return !!report?.viewerFeatures?.includes('views');
66
+ }
67
+ // A report's first load, in the open order above: the state service is
68
+ // set up for `report` (init) and the screen opened on a link (`params`,
69
+ // the URL's query params), a default view or the report's defaults.
70
+ // `pageId` is the page the link names, which beats a view's page. Ends
71
+ // once the screen is set; the list may still be loading behind it.
72
+ open(report, params, pageId) {
73
+ this._start(report);
74
+ const page = pageId ? { v: REPORT_VIEW_CONFIG_VERSION, pageId } : null;
75
+ const link = readReportUrlLink(params);
76
+ const state = hasReportUrlState(params, report.filterGroups ?? []);
77
+ if (!state && !link.personalViewId) {
78
+ return this._openDefault(report, page);
79
+ }
80
+ const linkDiff = { ...paramsToViewConfig(params, report.filterGroups ?? []), ...page };
81
+ const viewId = link.viewId ?? link.personalViewId;
82
+ return (viewId ? this._readView(report.id, viewId) : of(null))
83
+ .pipe(switchMap((view) => {
84
+ // A link that names only a personal view (its screen was the
85
+ // report's defaults) is the owner's link; for anyone else it says
86
+ // nothing, and the report opens as it would with no link.
87
+ if (!state && !view?.mine) {
88
+ return this._openDefault(report, page);
89
+ }
90
+ this._filterState.init(report);
91
+ this._openLink(link, view, linkDiff);
92
+ this._readViews(report)
93
+ .pipe(takeUntilDestroyed(this._destroyRef))
94
+ .subscribe();
95
+ return of(undefined);
96
+ }));
97
+ }
98
+ // A later load of the open report (a chat edit, a settings save): the
99
+ // screen and the open view stay, and the list is read again behind them so
100
+ // it names what the server holds now.
101
+ refresh(report) {
102
+ this._start(report);
103
+ this._readViews(report)
104
+ .pipe(takeUntilDestroyed(this._destroyRef))
105
+ .subscribe();
106
+ }
107
+ // Opens a view picked from the list; its config is read now.
108
+ pick(reportViewId) {
109
+ return this._reportData.view(this._reportId, reportViewId)
110
+ .pipe(tap((view) => this._openOn(view, () => this._filterState.apply(view.config))));
111
+ }
112
+ // Closes the open view and puts the screen on the report's defaults.
113
+ openDefaults() {
114
+ this._openView.set(null);
115
+ this._filterState.apply(null);
116
+ }
117
+ // Saves the screen as a new view, which becomes the open view. The screen
118
+ // is already the view, so nothing is applied again.
119
+ saveAsNew(view) {
120
+ return this._reportData.createView(this._reportId, { ...view, config: this._filterState.snapshot() })
121
+ .pipe(tap((saved) => {
122
+ this._openView.set(saved);
123
+ this._putRow(saved);
124
+ this._filterState.setBaseToScreen();
125
+ this._message.success('View saved');
126
+ }));
127
+ }
128
+ // Saves the screen over the open view, keeping the keys this viewer does
129
+ // not know (withStoredKeys).
130
+ saveChanges() {
131
+ const open = this._openView();
132
+ if (!open) {
133
+ return EMPTY;
134
+ }
135
+ return this._reportData.updateView(this._reportId, open.id, { config: withStoredKeys(open.config, this._filterState.snapshot()) })
136
+ .pipe(tap((saved) => {
137
+ this._openView.set(saved);
138
+ this._putRow(saved);
139
+ this._filterState.setBaseToScreen();
140
+ this._message.success('View saved');
141
+ }));
142
+ }
143
+ rename(name) {
144
+ return this._changeOpen((reportViewId) => this._reportData.updateView(this._reportId, reportViewId, { name }));
145
+ }
146
+ // Shares the open view with everyone who may open the report, or stops.
147
+ share(shared) {
148
+ return this._changeOpen((reportViewId) => this._reportData.shareView(this._reportId, reportViewId, shared));
149
+ }
150
+ // Makes the open view the viewer's default, or stops opening it by default.
151
+ setDefault(personalDefault) {
152
+ return this._changeOpen((reportViewId) => this._reportData.setViewDefault(this._reportId, reportViewId, personalDefault));
153
+ }
154
+ // Deletes the open view. The screen stays; the report's defaults become
155
+ // what it is compared with.
156
+ deleteOpen() {
157
+ const open = this._openView();
158
+ if (!open) {
159
+ return EMPTY;
160
+ }
161
+ return this._reportData.deleteView(this._reportId, open.id)
162
+ .pipe(tap(() => {
163
+ this._openView.set(null);
164
+ this._views.update((views) => views.filter((view) => view.id !== open.id));
165
+ this._filterState.clearBase();
166
+ this._message.success('View deleted');
167
+ }));
168
+ }
169
+ // The query params that make the URL carry the screen (see the class
170
+ // comment), spread over the owned keys `current` carries so the ones the
171
+ // screen no longer needs are removed. The host adds its page key.
172
+ // A select's value is named by `name`, else by the name `current` carries
173
+ // for it.
174
+ urlParams(current, name = () => null) {
175
+ const currentName = urlValueNames(current, this._reportGroups());
176
+ const write = this._linkWrite((groupId, value) => name(groupId, value) ?? currentName(groupId, value));
177
+ if (write.tooLong && !this._tooLongShown) {
178
+ this._tooLongShown = true;
179
+ this._message.warning(URL_TOO_LONG_MESSAGE);
180
+ }
181
+ return { ...reportParamsToClear(current, this._reportGroups()), ...write.params };
182
+ }
183
+ // Starts over for another report: no list and no open view.
184
+ _start(report) {
185
+ if (report.id === this._reportId) {
186
+ return;
187
+ }
188
+ this._reportId = report.id;
189
+ this._views.set([]);
190
+ this._canShare.set(false);
191
+ this._openView.set(null);
192
+ this._tooLongShown = false;
193
+ }
194
+ // No link: the viewer's default view, else the report's defaults, once the
195
+ // list is read.
196
+ _openDefault(report, page) {
197
+ return this._readViews(report)
198
+ .pipe(tap((list) => {
199
+ this._filterState.init(report);
200
+ if (list?.myDefault) {
201
+ this._openOn(list.myDefault, () => this._filterState.apply(list.myDefault.config, page));
202
+ }
203
+ }), map(() => undefined));
204
+ }
205
+ // A link with state: on the shared view rv names, else on the report's
206
+ // defaults; rpv's view is the open view only when the viewer owns it.
207
+ _openLink(link, view, linkDiff) {
208
+ if (link.viewId && view) {
209
+ this._openOn(view, () => this._filterState.apply(view.config, linkDiff));
210
+ return;
211
+ }
212
+ if (!link.viewId && view?.mine) {
213
+ this._openOn(view, () => this._filterState.apply(null, linkDiff, view.config));
214
+ return;
215
+ }
216
+ this._openView.set(null);
217
+ this._filterState.apply(null, linkDiff);
218
+ if (link.viewId) {
219
+ this._message.warning(VIEW_NOT_AVAILABLE_MESSAGE);
220
+ }
221
+ }
222
+ // Makes `view` the open view, puts it on screen (`applyView`), and says
223
+ // how many of its settings no longer apply (and to save it, when the
224
+ // viewer may).
225
+ _openOn(view, applyView) {
226
+ this._openView.set(view);
227
+ applyView();
228
+ const note = viewDroppedMessage(viewDroppedCount(view, this._filterState.base()), view.canChange);
229
+ if (note) {
230
+ this._message.warning(note);
231
+ }
232
+ }
233
+ // Runs a change on the open view and takes its answer as the open view
234
+ // and its row in the list. A change of who may see the view (shared, or
235
+ // whose it is) changes the key a link names it by, so the URL is written
236
+ // again.
237
+ _changeOpen(change) {
238
+ const open = this._openView();
239
+ if (!open) {
240
+ return EMPTY;
241
+ }
242
+ return change(open.id)
243
+ .pipe(tap((view) => {
244
+ this._openView.set(view);
245
+ this._putRow(view);
246
+ if (view.shared !== open.shared || view.mine !== open.mine) {
247
+ this._filterState.rewriteUrl();
248
+ }
249
+ }));
250
+ }
251
+ // A view's row in the list, replaced or added. A new default clears the
252
+ // flag on the viewer's other views, as the server does. A new row keeps
253
+ // the list's order: the viewer's own views first, then the ones others
254
+ // share.
255
+ _putRow(view) {
256
+ const summary = viewSummary(view);
257
+ this._views.update((views) => {
258
+ const rows = views.map((row) => (view.personalDefault && row.personalDefault ? { ...row, personalDefault: false } : row));
259
+ const index = rows.findIndex((row) => row.id === view.id);
260
+ if (index >= 0) {
261
+ return rows.map((row, at) => (at === index ? summary : row));
262
+ }
263
+ const othersAt = view.mine ? rows.findIndex((row) => !row.mine) : -1;
264
+ return othersAt < 0
265
+ ? [...rows, summary]
266
+ : [...rows.slice(0, othersAt), summary, ...rows.slice(othersAt)];
267
+ });
268
+ }
269
+ // The list, read for `report`; null when it cannot be read. Its answer is
270
+ // kept only while the report is still the open one.
271
+ _readViews(report) {
272
+ return this._reportData.views(report.id, { context: new HttpContext().set(DisplayApiError, false) })
273
+ .pipe(catchError(() => of(null)), tap((list) => {
274
+ if (list && report.id === this._reportId) {
275
+ this._views.set(list.views ?? []);
276
+ this._canShare.set(!!list.canShare);
277
+ }
278
+ }));
279
+ }
280
+ // A view a link names; null when the viewer cannot open it. The server
281
+ // answers 'View not found' for one it cannot see, which must not move the
282
+ // host to its not-found page.
283
+ _readView(reportId, reportViewId) {
284
+ return this._reportData.view(reportId, reportViewId, { context: new HttpContext().set(ProcessApiError, false) })
285
+ .pipe(catchError(() => of(null)));
286
+ }
287
+ // The params the screen writes (see the class comment).
288
+ _linkWrite(name) {
289
+ const open = this._openView();
290
+ const screen = this._filterState.snapshot();
291
+ const authored = this._filterState.authoredConfig();
292
+ const authoredSort = (componentId) => this._authoredSort(componentId);
293
+ if (open?.shared) {
294
+ // A group the view holds that the base let go of (its authored default
295
+ // changed while the view was open, and the screen took the new one)
296
+ // is still the view's value when a link opens the view, so it is
297
+ // compared with that value and written when the screen differs.
298
+ const base = this._filterState.base();
299
+ const linkBase = { ...base, groups: { ...open.config?.groups, ...base.groups } };
300
+ const diff = viewConfigDiff(linkBase, screen, authored, authoredSort);
301
+ if (diff) {
302
+ return viewConfigToParams(this._linkDays(diff), this._reportGroups(), { viewId: open.id }, name);
303
+ }
304
+ }
305
+ const full = viewConfigDiff(authored, screen, authored, authoredSort) ?? screen;
306
+ const link = open?.mine ? { personalViewId: open.id } : {};
307
+ return viewConfigToParams(this._linkDays(full), this._reportGroups(), link, name);
308
+ }
309
+ // `config` with each rolling range (a relative name, which a view keeps) as
310
+ // the days it gives today in the report's zone: a link carries days, never a
311
+ // preset name. A name the report does not know is left as it is, and the
312
+ // link leaves that group out.
313
+ _linkDays(config) {
314
+ if (!config.groups) {
315
+ return config;
316
+ }
317
+ const groups = Object.entries(config.groups)
318
+ .map(([groupId, value]) => [groupId, this._groupDays(value)]);
319
+ return { ...config, groups: Object.fromEntries(groups) };
320
+ }
321
+ _groupDays(value) {
322
+ const range = value?.relative ? this._filterState.resolveRelative(value.relative) : null;
323
+ return range ? toStoredGroupValue('dateRange', { start: range.start, end: range.end }) : value;
324
+ }
325
+ // Every filter group of the open report: the link keys each by its label.
326
+ _reportGroups() {
327
+ return this._filterState.report()?.filterGroups ?? [];
328
+ }
329
+ // A list's authored first sort term, or null for any other component.
330
+ _authoredSort(componentId) {
331
+ const report = this._filterState.report();
332
+ const component = [
333
+ ...(report?.pages ?? []).flatMap((page) => page.components ?? []),
334
+ ...(report?.master?.components ?? []),
335
+ ].find((candidate) => candidate.id === componentId);
336
+ return component?.type === 'list' ? listSortTerms(component.config)[0] ?? null : null;
337
+ }
338
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportViewService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
339
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportViewService });
340
+ }
341
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportViewService, decorators: [{
342
+ type: Injectable
343
+ }] });
344
+ // A view's row as the list holds it: names and flags, no config.
345
+ function viewSummary(view) {
346
+ return {
347
+ id: view.id,
348
+ name: view.name,
349
+ shared: view.shared,
350
+ mine: view.mine,
351
+ personalDefault: view.personalDefault,
352
+ ownerName: view.ownerName,
353
+ canChange: view.canChange,
354
+ canDelete: view.canDelete,
355
+ modifyDate: view.modifyDate,
356
+ };
357
+ }
358
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LXZpZXcuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9zZXJ2aWNlcy9yZXBvcnQtdmlldy5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNuRCxPQUFPLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNqRixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUdoRSxPQUFPLEVBQUUsZUFBZSxFQUFFLGVBQWUsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ25FLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUVoRCxPQUFPLEVBQUUsS0FBSyxFQUFjLEVBQUUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUM3QyxPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFakUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBV2pELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMvQyxPQUFPLEVBQ0wsb0JBQW9CLEVBQUUsaUJBQWlCLEVBQUUsa0JBQWtCLEVBQUUsaUJBQWlCLEVBQUUsbUJBQW1CLEVBQ25HLGFBQWEsRUFBRSxrQkFBa0IsR0FDbEMsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQ0wsMEJBQTBCLEVBQUUsMEJBQTBCLEVBQUUsa0JBQWtCLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixFQUM1RyxrQkFBa0IsRUFBRSxjQUFjLEdBQ25DLE1BQU0sdUJBQXVCLENBQUM7QUFDL0IsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sK0JBQStCLENBQUM7O0FBR3pFLDJFQUEyRTtBQUMzRSx5RUFBeUU7QUFDekUsMEVBQTBFO0FBQzFFLHlFQUF5RTtBQUN6RSwwRUFBMEU7QUFDMUUsNkVBQTZFO0FBQzdFLHVFQUF1RTtBQUN2RSxFQUFFO0FBQ0YsZ0VBQWdFO0FBQ2hFLGlGQUFpRjtBQUNqRiwyRUFBMkU7QUFDM0UsNEVBQTRFO0FBQzVFLHNFQUFzRTtBQUN0RSw2RUFBNkU7QUFDN0UsNkVBQTZFO0FBQzdFLDBFQUEwRTtBQUMxRSxvQkFBb0I7QUFDcEIscUNBQXFDO0FBQ3JDLDBDQUEwQztBQUMxQywwQ0FBMEM7QUFDMUMsRUFBRTtBQUNGLHlFQUF5RTtBQUN6RSwyRUFBMkU7QUFDM0UsMEVBQTBFO0FBQzFFLDJFQUEyRTtBQUMzRSx1RUFBdUU7QUFDdkUsNENBQTRDO0FBRTVDLE1BQU0sT0FBTyxpQkFBaUI7SUFFNUIsMEVBQTBFO0lBQzFFLHVEQUF1RDtJQUN2QyxLQUFLLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBRXRELGdEQUFnRDtJQUNoQyxRQUFRLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDO0lBRTVELHlFQUF5RTtJQUN6RSxzQ0FBc0M7SUFDdEIsUUFBUSxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQztJQUU1RCx1RUFBdUU7SUFDdkQsV0FBVyxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztJQUU1RixXQUFXLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ2pDLFlBQVksR0FBRyxNQUFNLENBQUMsd0JBQXdCLENBQUMsQ0FBQztJQUNoRCxRQUFRLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzdCLFdBQVcsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7SUFFakMsTUFBTSxHQUFHLE1BQU0sQ0FBc0IsRUFBRSxDQUFDLENBQUM7SUFDekMsU0FBUyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMxQixTQUFTLEdBQUcsTUFBTSxDQUFvQixJQUFJLENBQUMsQ0FBQztJQUVwRCxrQ0FBa0M7SUFDMUIsU0FBUyxHQUFrQixJQUFJLENBQUM7SUFFeEMseUVBQXlFO0lBQ2pFLGFBQWEsR0FBRyxLQUFLLENBQUM7SUFFOUIsc0RBQXNEO0lBQy9DLE1BQU0sQ0FBQyxNQUFxQjtRQUNqQyxPQUFPLENBQUMsQ0FBQyxNQUFNLEVBQUUsY0FBYyxFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNyRCxDQUFDO0lBRUQsdUVBQXVFO0lBQ3ZFLHdFQUF3RTtJQUN4RSxvRUFBb0U7SUFDcEUsdUVBQXVFO0lBQ3ZFLG1FQUFtRTtJQUM1RCxJQUFJLENBQUMsTUFBYyxFQUFFLE1BQWMsRUFBRSxNQUFxQjtRQUMvRCxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3BCLE1BQU0sSUFBSSxHQUE0QixNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDaEcsTUFBTSxJQUFJLEdBQUcsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdkMsTUFBTSxLQUFLLEdBQUcsaUJBQWlCLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxZQUFZLElBQUksRUFBRSxDQUFDLENBQUM7UUFFbkUsSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUNuQyxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3pDLENBQUM7UUFFRCxNQUFNLFFBQVEsR0FBcUIsRUFBRSxHQUFHLGtCQUFrQixDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsWUFBWSxJQUFJLEVBQUUsQ0FBQyxFQUFFLEdBQUcsSUFBSSxFQUFFLENBQUM7UUFDekcsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsY0FBYyxDQUFDO1FBRWxELE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO2FBQzNELElBQUksQ0FDSCxTQUFTLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUNqQiw2REFBNkQ7WUFDN0Qsa0VBQWtFO1lBQ2xFLDBEQUEwRDtZQUMxRCxJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDO2dCQUMxQixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ3pDLENBQUM7WUFFRCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUMvQixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDckMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7aUJBQ3BCLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7aUJBQzFDLFNBQVMsRUFBRSxDQUFDO1lBRWYsT0FBTyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDdkIsQ0FBQyxDQUFDLENBQ0gsQ0FBQztJQUNOLENBQUM7SUFFRCxzRUFBc0U7SUFDdEUsMkVBQTJFO0lBQzNFLHNDQUFzQztJQUMvQixPQUFPLENBQUMsTUFBYztRQUMzQixJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3BCLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDO2FBQ3BCLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7YUFDMUMsU0FBUyxFQUFFLENBQUM7SUFDakIsQ0FBQztJQUVELDZEQUE2RDtJQUN0RCxJQUFJLENBQUMsWUFBb0I7UUFDOUIsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQzthQUN2RCxJQUFJLENBQ0gsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUM5RSxDQUFDO0lBQ04sQ0FBQztJQUVELHFFQUFxRTtJQUM5RCxZQUFZO1FBQ2pCLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFFRCwwRUFBMEU7SUFDMUUsb0RBQW9EO0lBQzdDLFNBQVMsQ0FBQyxJQUFzQztRQUNyRCxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsRUFBRSxHQUFHLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO2FBQ2xHLElBQUksQ0FDSCxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUNaLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzFCLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDcEIsSUFBSSxDQUFDLFlBQVksQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUNwQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN0QyxDQUFDLENBQUMsQ0FDSCxDQUFDO0lBQ04sQ0FBQztJQUVELHlFQUF5RTtJQUN6RSw2QkFBNkI7SUFDdEIsV0FBVztRQUNoQixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDOUIsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ1YsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBRUQsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsY0FBYyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxFQUFFLENBQUM7YUFDL0gsSUFBSSxDQUNILEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ1osSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDMUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNwQixJQUFJLENBQUMsWUFBWSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3BDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUNILENBQUM7SUFDTixDQUFDO0lBRU0sTUFBTSxDQUFDLElBQVk7UUFDeEIsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFlBQVksRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqSCxDQUFDO0lBRUQsd0VBQXdFO0lBQ2pFLEtBQUssQ0FBQyxNQUFlO1FBQzFCLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxZQUFZLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUM5RyxDQUFDO0lBRUQsNEVBQTRFO0lBQ3JFLFVBQVUsQ0FBQyxlQUF3QjtRQUN4QyxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsWUFBWSxFQUFFLGVBQWUsQ0FBQyxDQUFDLENBQUM7SUFDNUgsQ0FBQztJQUVELHdFQUF3RTtJQUN4RSw0QkFBNEI7SUFDckIsVUFBVTtRQUNmLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUM5QixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDVixPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQzthQUN4RCxJQUFJLENBQ0gsR0FBRyxDQUFDLEdBQUcsRUFBRTtZQUNQLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3pCLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQzNFLElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDOUIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDeEMsQ0FBQyxDQUFDLENBQ0gsQ0FBQztJQUNOLENBQUM7SUFFRCxxRUFBcUU7SUFDckUseUVBQXlFO0lBQ3pFLGtFQUFrRTtJQUNsRSwwRUFBMEU7SUFDMUUsVUFBVTtJQUNILFNBQVMsQ0FBQyxPQUFpQixFQUFFLE9BQTJCLEdBQUcsRUFBRSxDQUFDLElBQUk7UUFDdkUsTUFBTSxXQUFXLEdBQUcsYUFBYSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUMsQ0FBQztRQUNqRSxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsSUFBSSxXQUFXLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFFdkcsSUFBSSxLQUFLLENBQUMsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ3pDLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDO1lBQzFCLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDOUMsQ0FBQztRQUVELE9BQU8sRUFBRSxHQUFHLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUMsRUFBRSxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUNwRixDQUFDO0lBRUQsNERBQTREO0lBQ3BELE1BQU0sQ0FBQyxNQUFjO1FBQzNCLElBQUksTUFBTSxDQUFDLEVBQUUsS0FBSyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDakMsT0FBTztRQUNULENBQUM7UUFFRCxJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDM0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDcEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDMUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekIsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUM7SUFDN0IsQ0FBQztJQUVELDJFQUEyRTtJQUMzRSxnQkFBZ0I7SUFDUixZQUFZLENBQUMsTUFBYyxFQUFFLElBQTZCO1FBQ2hFLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7YUFDM0IsSUFBSSxDQUNILEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1lBQ1gsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDL0IsSUFBSSxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUM7Z0JBQ3BCLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQzNGLENBQUM7UUFDSCxDQUFDLENBQUMsRUFDRixHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQ3JCLENBQUM7SUFDTixDQUFDO0lBRUQsdUVBQXVFO0lBQ3ZFLHNFQUFzRTtJQUM5RCxTQUFTLENBQUMsSUFBbUIsRUFBRSxJQUF1QixFQUFFLFFBQTBCO1FBQ3hGLElBQUksSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFFekUsT0FBTztRQUNULENBQUM7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUM7WUFDL0IsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztZQUUvRSxPQUFPO1FBQ1QsQ0FBQztRQUVELElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQztRQUV4QyxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNoQixJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1FBQ3BELENBQUM7SUFDSCxDQUFDO0lBRUQsd0VBQXdFO0lBQ3hFLHFFQUFxRTtJQUNyRSxlQUFlO0lBQ1AsT0FBTyxDQUFDLElBQWdCLEVBQUUsU0FBcUI7UUFDckQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekIsU0FBUyxFQUFFLENBQUM7UUFFWixNQUFNLElBQUksR0FBRyxrQkFBa0IsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNsRyxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ1QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDOUIsQ0FBQztJQUNILENBQUM7SUFFRCx1RUFBdUU7SUFDdkUsd0VBQXdFO0lBQ3hFLHlFQUF5RTtJQUN6RSxTQUFTO0lBQ0QsV0FBVyxDQUFDLE1BQXdEO1FBQzFFLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUM5QixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDVixPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7UUFFRCxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2FBQ25CLElBQUksQ0FDSCxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUNYLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3pCLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7WUFFbkIsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQzNELElBQUksQ0FBQyxZQUFZLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDakMsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUNILENBQUM7SUFDTixDQUFDO0lBRUQsd0VBQXdFO0lBQ3hFLHdFQUF3RTtJQUN4RSx1RUFBdUU7SUFDdkUsU0FBUztJQUNELE9BQU8sQ0FBQyxJQUFnQjtRQUM5QixNQUFNLE9BQU8sR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFbEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUMzQixNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxlQUFlLElBQUksR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEdBQUcsRUFBRSxlQUFlLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDMUgsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7WUFFMUQsSUFBSSxLQUFLLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQ2YsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDL0QsQ0FBQztZQUVELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUVyRSxPQUFPLFFBQVEsR0FBRyxDQUFDO2dCQUNqQixDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksRUFBRSxPQUFPLENBQUM7Z0JBQ3BCLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLEVBQUUsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQ3JFLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELDBFQUEwRTtJQUMxRSxvREFBb0Q7SUFDNUMsVUFBVSxDQUFDLE1BQWM7UUFDL0IsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksV0FBVyxFQUFFLENBQUMsR0FBRyxDQUFDLGVBQWUsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDO2FBQ2pHLElBQUksQ0FDSCxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQzFCLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1lBQ1gsSUFBSSxJQUFJLElBQUksTUFBTSxDQUFDLEVBQUUsS0FBSyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ3pDLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDLENBQUM7Z0JBQ2xDLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDdEMsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUNILENBQUM7SUFDTixDQUFDO0lBRUQsdUVBQXVFO0lBQ3ZFLDBFQUEwRTtJQUMxRSw4QkFBOEI7SUFDdEIsU0FBUyxDQUFDLFFBQWdCLEVBQUUsWUFBb0I7UUFDdEQsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsWUFBWSxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksV0FBVyxFQUFFLENBQUMsR0FBRyxDQUFDLGVBQWUsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDO2FBQzdHLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBRUQsd0RBQXdEO0lBQ2hELFVBQVUsQ0FBQyxJQUF3QjtRQUN6QyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDOUIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUM1QyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3BELE1BQU0sWUFBWSxHQUFHLENBQUMsV0FBbUIsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUU5RSxJQUFJLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQztZQUNqQix1RUFBdUU7WUFDdkUsb0VBQW9FO1lBQ3BFLGlFQUFpRTtZQUNqRSxnRUFBZ0U7WUFDaEUsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUN0QyxNQUFNLFFBQVEsR0FBcUIsRUFBRSxHQUFHLElBQUksRUFBRSxNQUFNLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7WUFDbkcsTUFBTSxJQUFJLEdBQUcsY0FBYyxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLFlBQVksQ0FBQyxDQUFDO1lBRXRFLElBQUksSUFBSSxFQUFFLENBQUM7Z0JBQ1QsT0FBTyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxhQUFhLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDbkcsQ0FBQztRQUNILENBQUM7UUFFRCxNQUFNLElBQUksR0FBRyxjQUFjLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsWUFBWSxDQUFDLElBQUksTUFBTSxDQUFDO1FBRWhGLE1BQU0sSUFBSSxHQUFHLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsY0FBYyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBRTNELE9BQU8sa0JBQWtCLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsYUFBYSxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3BGLENBQUM7SUFFRCw0RUFBNEU7SUFDNUUsNkVBQTZFO0lBQzdFLHlFQUF5RTtJQUN6RSw4QkFBOEI7SUFDdEIsU0FBUyxDQUFDLE1BQXdCO1FBQ3hDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDbkIsT0FBTyxNQUFNLENBQUM7UUFDaEIsQ0FBQztRQUVELE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQzthQUN6QyxHQUFHLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFaEUsT0FBTyxFQUFFLEdBQUcsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7SUFDM0QsQ0FBQztJQUVPLFVBQVUsQ0FBQyxLQUFnQztRQUNqRCxNQUFNLEtBQUssR0FBRyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUV6RixPQUFPLEtBQUssQ0FBQyxDQUFDLENBQUMsa0JBQWtCLENBQUMsV0FBVyxFQUFFLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7SUFDakcsQ0FBQztJQUVELDBFQUEwRTtJQUNsRSxhQUFhO1FBQ25CLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsRUFBRSxZQUFZLElBQUksRUFBRSxDQUFDO0lBQ3hELENBQUM7SUFFRCxzRUFBc0U7SUFDOUQsYUFBYSxDQUFDLFdBQW1CO1FBQ3ZDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDMUMsTUFBTSxTQUFTLEdBQUc7WUFDaEIsR0FBRyxDQUFDLE1BQU0sRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQztZQUNqRSxHQUFHLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxVQUFVLElBQUksRUFBRSxDQUFDO1NBQ3RDLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxTQUFTLENBQUMsRUFBRSxLQUFLLFdBQVcsQ0FBQyxDQUFDO1FBRXBELE9BQU8sU0FBUyxFQUFFLElBQUksS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDeEYsQ0FBQzt3R0ExWFUsaUJBQWlCOzRHQUFqQixpQkFBaUI7OzRGQUFqQixpQkFBaUI7a0JBRDdCLFVBQVU7O0FBK1hYLGlFQUFpRTtBQUNqRSxTQUFTLFdBQVcsQ0FBQyxJQUFnQjtJQUNuQyxPQUFPO1FBQ0wsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFO1FBQ1gsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO1FBQ2YsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO1FBQ25CLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSTtRQUNmLGVBQWUsRUFBRSxJQUFJLENBQUMsZUFBZTtRQUNyQyxTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7UUFDekIsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTO1FBQ3pCLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUztRQUN6QixVQUFVLEVBQUUsSUFBSSxDQUFDLFVBQVU7S0FDNUIsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBIdHRwQ29udGV4dCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IERlc3Ryb3lSZWYsIEluamVjdGFibGUsIGNvbXB1dGVkLCBpbmplY3QsIHNpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuaW1wb3J0IHsgUGFyYW1NYXAsIFBhcmFtcyB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5cbmltcG9ydCB7IERpc3BsYXlBcGlFcnJvciwgUHJvY2Vzc0FwaUVycm9yIH0gZnJvbSAnQGZpcmVzdGl0Y2gvYXBpJztcbmltcG9ydCB7IEZzTWVzc2FnZSB9IGZyb20gJ0BmaXJlc3RpdGNoL21lc3NhZ2UnO1xuXG5pbXBvcnQgeyBFTVBUWSwgT2JzZXJ2YWJsZSwgb2YgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGNhdGNoRXJyb3IsIG1hcCwgc3dpdGNoTWFwLCB0YXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IFJlcG9ydERhdGEgfSBmcm9tICcuLi9kYXRhL3JlcG9ydC5kYXRhJztcbmltcG9ydCB7IFJlcG9ydFVybExpbmsgfSBmcm9tICcuLi9pbnRlcmZhY2VzL3JlcG9ydC11cmwtbGluay5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVwb3J0VXJsVmFsdWVOYW1lIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZXBvcnQtdXJsLXZhbHVlLW5hbWUudHlwZSc7XG5pbXBvcnQgeyBSZXBvcnRVcmxXcml0ZSB9IGZyb20gJy4uL2ludGVyZmFjZXMvcmVwb3J0LXVybC13cml0ZS5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVwb3J0Vmlld0NvbmZpZyB9IGZyb20gJy4uL2ludGVyZmFjZXMvcmVwb3J0LXZpZXctY29uZmlnLmludGVyZmFjZSc7XG5pbXBvcnQgeyBSZXBvcnRWaWV3Q3JlYXRlIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZXBvcnQtdmlldy1jcmVhdGUuaW50ZXJmYWNlJztcbmltcG9ydCB7IFJlcG9ydFZpZXdEZWxldGVkIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZXBvcnQtdmlldy1kZWxldGVkLmludGVyZmFjZSc7XG5pbXBvcnQgeyBSZXBvcnRWaWV3U3VtbWFyeSB9IGZyb20gJy4uL2ludGVyZmFjZXMvcmVwb3J0LXZpZXctc3VtbWFyeS5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVwb3J0VmlldyB9IGZyb20gJy4uL2ludGVyZmFjZXMvcmVwb3J0LXZpZXcuaW50ZXJmYWNlJztcbmltcG9ydCB7IFJlcG9ydFZpZXdzIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZXBvcnQtdmlld3MuaW50ZXJmYWNlJztcbmltcG9ydCB7IEZpbHRlckdyb3VwRGVmYXVsdCwgUmVwb3J0LCBSZXBvcnRGaWx0ZXJHcm91cCwgUmVwb3J0U29ydCB9IGZyb20gJy4uL2ludGVyZmFjZXMvcmVwb3J0LmludGVyZmFjZSc7XG5pbXBvcnQgeyBsaXN0U29ydFRlcm1zIH0gZnJvbSAnLi4vbGlzdC1jb25maWcnO1xuaW1wb3J0IHtcbiAgVVJMX1RPT19MT05HX01FU1NBR0UsIGhhc1JlcG9ydFVybFN0YXRlLCBwYXJhbXNUb1ZpZXdDb25maWcsIHJlYWRSZXBvcnRVcmxMaW5rLCByZXBvcnRQYXJhbXNUb0NsZWFyLFxuICB1cmxWYWx1ZU5hbWVzLCB2aWV3Q29uZmlnVG9QYXJhbXMsXG59IGZyb20gJy4uL3JlcG9ydC11cmwtc3RhdGUnO1xuaW1wb3J0IHtcbiAgUkVQT1JUX1ZJRVdfQ09ORklHX1ZFUlNJT04sIFZJRVdfTk9UX0FWQUlMQUJMRV9NRVNTQUdFLCB0b1N0b3JlZEdyb3VwVmFsdWUsIHZpZXdDb25maWdEaWZmLCB2aWV3RHJvcHBlZENvdW50LFxuICB2aWV3RHJvcHBlZE1lc3NhZ2UsIHdpdGhTdG9yZWRLZXlzLFxufSBmcm9tICcuLi9yZXBvcnQtdmlldy1jb25maWcnO1xuaW1wb3J0IHsgUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlIH0gZnJvbSAnLi9yZXBvcnQtZmlsdGVyLXN0YXRlLnNlcnZpY2UnO1xuXG5cbi8vIFRoZSBvcGVuIHJlcG9ydCdzIHNhdmVkIHZpZXdzLCBwZXIgb3BlbiByZXBvcnQgYmVzaWRlIHRoZSBzdGF0ZSBzZXJ2aWNlOlxuLy8gdGhlIGxpc3QgdGhlIHZpZXdlciBtYXkgc2VlLCB0aGUgdmlldyB0aGF0IGlzIG9wZW4sIHRoZSBvcmRlciBhIHJlcG9ydFxuLy8gb3BlbnMgaW4sIHRoZSBjYWxscyB0aGF0IGNoYW5nZSBhIHZpZXcsIGFuZCB0aGUgbGluayB0aGUgc2NyZWVuIHdyaXRlcy5cbi8vIFRoZSB2aWV3ZXIgc3RhdGUgc3RheXMgUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlJ3M6IHRoaXMgc2VydmljZSBwdXRzIGFcbi8vIHZpZXcgb24gc2NyZWVuIHRocm91Z2ggYXBwbHkoKSBhbmQgcmVhZHMgdGhlIHNjcmVlbiB0aHJvdWdoIHNuYXBzaG90KCksXG4vLyBiYXNlIGFuZCB2aWV3Q2hhbmdlZC4gTm90aGluZyBoZXJlIHJ1bnMgZm9yIGEgcmVwb3J0IHdob3NlIHNlcnZlciBkb2VzIG5vdFxuLy8gbGlzdCAndmlld3MnIChzZXJ2ZXMoKSk7IHN1Y2ggYSByZXBvcnQga2VlcHMgdGhlIGxpbmsgaXQgYWx3YXlzIGhhZC5cbi8vXG4vLyBUaGUgb3JkZXIgYSByZXBvcnQgb3BlbnMgaW4gKG9wZW4oKSwgb24gaXRzIGZpcnN0IGxvYWQgb25seSk6XG4vLyAxLiBBIGxpbmsgdGhhdCBjYXJyaWVzIHN0YXRlIChhbnkgb3duZWQga2V5LCBtYXRjaCBvciBydikuIHJ2IG5hbWVzIHRoZSBzaGFyZWRcbi8vICAgIHZpZXcgaXQgaXMgYSBkaWZmIGZyb207IG9uZSB0aGUgdmlld2VyIGNhbm5vdCBvcGVuIGxlYXZlcyB0aGUgZGlmZiBvblxuLy8gICAgdGhlIHJlcG9ydCdzIGRlZmF1bHRzLCB3aXRoIGEgbm90ZS4gcnB2IG5ldmVyIGNoYW5nZXMgdGhlIHNjcmVlbjogd2hlblxuLy8gICAgdGhlIHZpZXdlciBvd25zIHRoYXQgdmlldyBpdCBpcyB0aGUgb3BlbiB2aWV3LCBhbmQgdGhlIHNjcmVlbiBpc1xuLy8gICAgY29tcGFyZWQgd2l0aCBpdC4gVGhlIHRpbGVzIHdhaXQgZm9yIHRoYXQgb25lIHZpZXcgb25seTsgdGhlIGxpc3QgbG9hZHNcbi8vICAgIGJlaGluZCB0aGVtLiBBIGxpbmsgd2l0aCBycHYgYW5kIG5vIHN0YXRlICh0aGUgb3duZXIncyB2aWV3IHdhcyBvcGVuIG9uXG4vLyAgICB0aGUgcmVwb3J0J3MgZGVmYXVsdHMpIGlzIGEgbGluayBmb3IgdGhlIG93bmVyIG9ubHk7IGZvciBhbnlvbmUgZWxzZVxuLy8gICAgaXQgaXMgbm8gbGluay5cbi8vIDIuIEVsc2UgdGhlIHZpZXdlcidzIGRlZmF1bHQgdmlldy5cbi8vIDMuIEVsc2UgdGhlIHJlcG9ydCdzIGF1dGhvcmVkIGRlZmF1bHRzLlxuLy8gQSBwYWdlIGluIHRoZSBsaW5rIGJlYXRzIGEgdmlldydzIHBhZ2UuXG4vL1xuLy8gVGhlIGxpbmsgKHVybFBhcmFtcyk6IHdoaWxlIGEgc2hhcmVkIHZpZXcgaXMgb3BlbiwgcnYgYW5kIHdoYXQgZGlmZmVyc1xuLy8gZnJvbSBpdDsgd2hpbGUgb25lIG9mIHRoZSB2aWV3ZXIncyBvd24gdmlld3MgaXMgb3Blbiwgb3Igd2hlbiB0aGUgc2NyZWVuXG4vLyB3ZW50IGJhY2sgdG8gc29tZXRoaW5nIGEgbGluayBjYW5ub3Qgc2F5IG9uIHRvcCBvZiB0aGUgc2hhcmVkIHZpZXcgKHNlZVxuLy8gdmlld0NvbmZpZ0RpZmYpLCBldmVyeXRoaW5nIHRoYXQgZGlmZmVycyBmcm9tIHRoZSByZXBvcnQncyBkZWZhdWx0cywgYW5kXG4vLyBycHYgd2hlbiB0aGUgdmlld2VyIG93bnMgdGhlIG9wZW4gdmlldy4gU2hhcmluZyB0aGUgb3BlbiB2aWV3LCBvciBub1xuLy8gbG9uZ2VyIHNoYXJpbmcgaXQsIHdyaXRlcyB0aGUgbGluayBhZ2Fpbi5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBSZXBvcnRWaWV3U2VydmljZSB7XG5cbiAgLy8gVGhlIHZpZXdzIHRoZSB2aWV3ZXIgbWF5IHNlZSwgbmFtZXMgYW5kIGZsYWdzIG9ubHk6IGl0cyBvd24gZmlyc3QsIHRoZW5cbiAgLy8gdGhlIG9uZXMgb3RoZXJzIHNoYXJlLiBFbXB0eSB1bnRpbCB0aGUgbGlzdCBpcyByZWFkLlxuICBwdWJsaWMgcmVhZG9ubHkgdmlld3MgPSBjb21wdXRlZCgoKSA9PiB0aGlzLl92aWV3cygpKTtcblxuICAvLyBUaGUgdmlld2VyIG1heSBzaGFyZSBpdHMgdmlld3Mgd2l0aCBldmVyeW9uZS5cbiAgcHVibGljIHJlYWRvbmx5IGNhblNoYXJlID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5fY2FuU2hhcmUoKSk7XG5cbiAgLy8gVGhlIG9wZW4gdmlldywgd2l0aCBpdHMgY29uZmlnIGFzIGl0IHdhcyByZWFkIG9yIHNhdmVkOyBudWxsIHdoaWxlIHRoZVxuICAvLyBzY3JlZW4gaXMgb24gdGhlIHJlcG9ydCdzIGRlZmF1bHRzLlxuICBwdWJsaWMgcmVhZG9ubHkgb3BlblZpZXcgPSBjb21wdXRlZCgoKSA9PiB0aGlzLl9vcGVuVmlldygpKTtcblxuICAvLyBXaGV0aGVyIHRoZSBzY3JlZW4gZGlmZmVycyBmcm9tIHRoZSBvcGVuIHZpZXc7IGZhbHNlIHdpdGggbm9uZSBvcGVuLlxuICBwdWJsaWMgcmVhZG9ubHkgdmlld0NoYW5nZWQgPSBjb21wdXRlZCgoKSA9PiAhIXRoaXMuX29wZW5WaWV3KCkgJiYgdGhpcy5fZmlsdGVyU3RhdGUudmlld0NoYW5nZWQoKSk7XG5cbiAgcHJpdmF0ZSBfcmVwb3J0RGF0YSA9IGluamVjdChSZXBvcnREYXRhKTtcbiAgcHJpdmF0ZSBfZmlsdGVyU3RhdGUgPSBpbmplY3QoUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlKTtcbiAgcHJpdmF0ZSBfbWVzc2FnZSA9IGluamVjdChGc01lc3NhZ2UpO1xuICBwcml2YXRlIF9kZXN0cm95UmVmID0gaW5qZWN0KERlc3Ryb3lSZWYpO1xuXG4gIHByaXZhdGUgX3ZpZXdzID0gc2lnbmFsPFJlcG9ydFZpZXdTdW1tYXJ5W10+KFtdKTtcbiAgcHJpdmF0ZSBfY2FuU2hhcmUgPSBzaWduYWwoZmFsc2UpO1xuICBwcml2YXRlIF9vcGVuVmlldyA9IHNpZ25hbDxSZXBvcnRWaWV3IHwgbnVsbD4obnVsbCk7XG5cbiAgLy8gVGhlIHJlcG9ydCB0aGUgdmlld3MgYmVsb25nIHRvLlxuICBwcml2YXRlIF9yZXBvcnRJZDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG5cbiAgLy8gVGhlIG5vdGUgdGhhdCB0aGUgc2NyZWVuIGlzIHRvbyBsb25nIGZvciBhIGxpbmsgc2hvd3Mgb25jZSBwZXIgcmVwb3J0LlxuICBwcml2YXRlIF90b29Mb25nU2hvd24gPSBmYWxzZTtcblxuICAvLyBXaGV0aGVyIHRoZSBvcGVuIHJlcG9ydCdzIHNlcnZlciBrZWVwcyBzYXZlZCB2aWV3cy5cbiAgcHVibGljIHNlcnZlcyhyZXBvcnQ6IFJlcG9ydCB8IG51bGwpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISFyZXBvcnQ/LnZpZXdlckZlYXR1cmVzPy5pbmNsdWRlcygndmlld3MnKTtcbiAgfVxuXG4gIC8vIEEgcmVwb3J0J3MgZmlyc3QgbG9hZCwgaW4gdGhlIG9wZW4gb3JkZXIgYWJvdmU6IHRoZSBzdGF0ZSBzZXJ2aWNlIGlzXG4gIC8vIHNldCB1cCBmb3IgYHJlcG9ydGAgKGluaXQpIGFuZCB0aGUgc2NyZWVuIG9wZW5lZCBvbiBhIGxpbmsgKGBwYXJhbXNgLFxuICAvLyB0aGUgVVJMJ3MgcXVlcnkgcGFyYW1zKSwgYSBkZWZhdWx0IHZpZXcgb3IgdGhlIHJlcG9ydCdzIGRlZmF1bHRzLlxuICAvLyBgcGFnZUlkYCBpcyB0aGUgcGFnZSB0aGUgbGluayBuYW1lcywgd2hpY2ggYmVhdHMgYSB2aWV3J3MgcGFnZS4gRW5kc1xuICAvLyBvbmNlIHRoZSBzY3JlZW4gaXMgc2V0OyB0aGUgbGlzdCBtYXkgc3RpbGwgYmUgbG9hZGluZyBiZWhpbmQgaXQuXG4gIHB1YmxpYyBvcGVuKHJlcG9ydDogUmVwb3J0LCBwYXJhbXM6IFBhcmFtcywgcGFnZUlkOiBudW1iZXIgfCBudWxsKTogT2JzZXJ2YWJsZTx2b2lkPiB7XG4gICAgdGhpcy5fc3RhcnQocmVwb3J0KTtcbiAgICBjb25zdCBwYWdlOiBSZXBvcnRWaWV3Q29uZmlnIHwgbnVsbCA9IHBhZ2VJZCA/IHsgdjogUkVQT1JUX1ZJRVdfQ09ORklHX1ZFUlNJT04sIHBhZ2VJZCB9IDogbnVsbDtcbiAgICBjb25zdCBsaW5rID0gcmVhZFJlcG9ydFVybExpbmsocGFyYW1zKTtcbiAgICBjb25zdCBzdGF0ZSA9IGhhc1JlcG9ydFVybFN0YXRlKHBhcmFtcywgcmVwb3J0LmZpbHRlckdyb3VwcyA/PyBbXSk7XG5cbiAgICBpZiAoIXN0YXRlICYmICFsaW5rLnBlcnNvbmFsVmlld0lkKSB7XG4gICAgICByZXR1cm4gdGhpcy5fb3BlbkRlZmF1bHQocmVwb3J0LCBwYWdlKTtcbiAgICB9XG5cbiAgICBjb25zdCBsaW5rRGlmZjogUmVwb3J0Vmlld0NvbmZpZyA9IHsgLi4ucGFyYW1zVG9WaWV3Q29uZmlnKHBhcmFtcywgcmVwb3J0LmZpbHRlckdyb3VwcyA/PyBbXSksIC4uLnBhZ2UgfTtcbiAgICBjb25zdCB2aWV3SWQgPSBsaW5rLnZpZXdJZCA/PyBsaW5rLnBlcnNvbmFsVmlld0lkO1xuXG4gICAgcmV0dXJuICh2aWV3SWQgPyB0aGlzLl9yZWFkVmlldyhyZXBvcnQuaWQsIHZpZXdJZCkgOiBvZihudWxsKSlcbiAgICAgIC5waXBlKFxuICAgICAgICBzd2l0Y2hNYXAoKHZpZXcpID0+IHtcbiAgICAgICAgICAvLyBBIGxpbmsgdGhhdCBuYW1lcyBvbmx5IGEgcGVyc29uYWwgdmlldyAoaXRzIHNjcmVlbiB3YXMgdGhlXG4gICAgICAgICAgLy8gcmVwb3J0J3MgZGVmYXVsdHMpIGlzIHRoZSBvd25lcidzIGxpbms7IGZvciBhbnlvbmUgZWxzZSBpdCBzYXlzXG4gICAgICAgICAgLy8gbm90aGluZywgYW5kIHRoZSByZXBvcnQgb3BlbnMgYXMgaXQgd291bGQgd2l0aCBubyBsaW5rLlxuICAgICAgICAgIGlmICghc3RhdGUgJiYgIXZpZXc/Lm1pbmUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcGVuRGVmYXVsdChyZXBvcnQsIHBhZ2UpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuX2ZpbHRlclN0YXRlLmluaXQocmVwb3J0KTtcbiAgICAgICAgICB0aGlzLl9vcGVuTGluayhsaW5rLCB2aWV3LCBsaW5rRGlmZik7XG4gICAgICAgICAgdGhpcy5fcmVhZFZpZXdzKHJlcG9ydClcbiAgICAgICAgICAgIC5waXBlKHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKTtcblxuICAgICAgICAgIHJldHVybiBvZih1bmRlZmluZWQpO1xuICAgICAgICB9KSxcbiAgICAgICk7XG4gIH1cblxuICAvLyBBIGxhdGVyIGxvYWQgb2YgdGhlIG9wZW4gcmVwb3J0IChhIGNoYXQgZWRpdCwgYSBzZXR0aW5ncyBzYXZlKTogdGhlXG4gIC8vIHNjcmVlbiBhbmQgdGhlIG9wZW4gdmlldyBzdGF5LCBhbmQgdGhlIGxpc3QgaXMgcmVhZCBhZ2FpbiBiZWhpbmQgdGhlbSBzb1xuICAvLyBpdCBuYW1lcyB3aGF0IHRoZSBzZXJ2ZXIgaG9sZHMgbm93LlxuICBwdWJsaWMgcmVmcmVzaChyZXBvcnQ6IFJlcG9ydCk6IHZvaWQge1xuICAgIHRoaXMuX3N0YXJ0KHJlcG9ydCk7XG4gICAgdGhpcy5fcmVhZFZpZXdzKHJlcG9ydClcbiAgICAgIC5waXBlKHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSlcbiAgICAgIC5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIC8vIE9wZW5zIGEgdmlldyBwaWNrZWQgZnJvbSB0aGUgbGlzdDsgaXRzIGNvbmZpZyBpcyByZWFkIG5vdy5cbiAgcHVibGljIHBpY2socmVwb3J0Vmlld0lkOiBudW1iZXIpOiBPYnNlcnZhYmxlPFJlcG9ydFZpZXc+IHtcbiAgICByZXR1cm4gdGhpcy5fcmVwb3J0RGF0YS52aWV3KHRoaXMuX3JlcG9ydElkLCByZXBvcnRWaWV3SWQpXG4gICAgICAucGlwZShcbiAgICAgICAgdGFwKCh2aWV3KSA9PiB0aGlzLl9vcGVuT24odmlldywgKCkgPT4gdGhpcy5fZmlsdGVyU3RhdGUuYXBwbHkodmlldy5jb25maWcpKSksXG4gICAgICApO1xuICB9XG5cbiAgLy8gQ2xvc2VzIHRoZSBvcGVuIHZpZXcgYW5kIHB1dHMgdGhlIHNjcmVlbiBvbiB0aGUgcmVwb3J0J3MgZGVmYXVsdHMuXG4gIHB1YmxpYyBvcGVuRGVmYXVsdHMoKTogdm9pZCB7XG4gICAgdGhpcy5fb3BlblZpZXcuc2V0KG51bGwpO1xuICAgIHRoaXMuX2ZpbHRlclN0YXRlLmFwcGx5KG51bGwpO1xuICB9XG5cbiAgLy8gU2F2ZXMgdGhlIHNjcmVlbiBhcyBhIG5ldyB2aWV3LCB3aGljaCBiZWNvbWVzIHRoZSBvcGVuIHZpZXcuIFRoZSBzY3JlZW5cbiAgLy8gaXMgYWxyZWFkeSB0aGUgdmlldywgc28gbm90aGluZyBpcyBhcHBsaWVkIGFnYWluLlxuICBwdWJsaWMgc2F2ZUFzTmV3KHZpZXc6IE9taXQ8UmVwb3J0Vmlld0NyZWF0ZSwgJ2NvbmZpZyc+KTogT2JzZXJ2YWJsZTxSZXBvcnRWaWV3PiB7XG4gICAgcmV0dXJuIHRoaXMuX3JlcG9ydERhdGEuY3JlYXRlVmlldyh0aGlzLl9yZXBvcnRJZCwgeyAuLi52aWV3LCBjb25maWc6IHRoaXMuX2ZpbHRlclN0YXRlLnNuYXBzaG90KCkgfSlcbiAgICAgIC5waXBlKFxuICAgICAgICB0YXAoKHNhdmVkKSA9PiB7XG4gICAgICAgICAgdGhpcy5fb3BlblZpZXcuc2V0KHNhdmVkKTtcbiAgICAgICAgICB0aGlzLl9wdXRSb3coc2F2ZWQpO1xuICAgICAgICAgIHRoaXMuX2ZpbHRlclN0YXRlLnNldEJhc2VUb1NjcmVlbigpO1xuICAgICAgICAgIHRoaXMuX21lc3NhZ2Uuc3VjY2VzcygnVmlldyBzYXZlZCcpO1xuICAgICAgICB9KSxcbiAgICAgICk7XG4gIH1cblxuICAvLyBTYXZlcyB0aGUgc2NyZWVuIG92ZXIgdGhlIG9wZW4gdmlldywga2VlcGluZyB0aGUga2V5cyB0aGlzIHZpZXdlciBkb2VzXG4gIC8vIG5vdCBrbm93ICh3aXRoU3RvcmVkS2V5cykuXG4gIHB1YmxpYyBzYXZlQ2hhbmdlcygpOiBPYnNlcnZhYmxlPFJlcG9ydFZpZXc+IHtcbiAgICBjb25zdCBvcGVuID0gdGhpcy5fb3BlblZpZXcoKTtcbiAgICBpZiAoIW9wZW4pIHtcbiAgICAgIHJldHVybiBFTVBUWTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fcmVwb3J0RGF0YS51cGRhdGVWaWV3KHRoaXMuX3JlcG9ydElkLCBvcGVuLmlkLCB7IGNvbmZpZzogd2l0aFN0b3JlZEtleXMob3Blbi5jb25maWcsIHRoaXMuX2ZpbHRlclN0YXRlLnNuYXBzaG90KCkpIH0pXG4gICAgICAucGlwZShcbiAgICAgICAgdGFwKChzYXZlZCkgPT4ge1xuICAgICAgICAgIHRoaXMuX29wZW5WaWV3LnNldChzYXZlZCk7XG4gICAgICAgICAgdGhpcy5fcHV0Um93KHNhdmVkKTtcbiAgICAgICAgICB0aGlzLl9maWx0ZXJTdGF0ZS5zZXRCYXNlVG9TY3JlZW4oKTtcbiAgICAgICAgICB0aGlzLl9tZXNzYWdlLnN1Y2Nlc3MoJ1ZpZXcgc2F2ZWQnKTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICB9XG5cbiAgcHVibGljIHJlbmFtZShuYW1lOiBzdHJpbmcpOiBPYnNlcnZhYmxlPFJlcG9ydFZpZXc+IHtcbiAgICByZXR1cm4gdGhpcy5fY2hhbmdlT3BlbigocmVwb3J0Vmlld0lkKSA9PiB0aGlzLl9yZXBvcnREYXRhLnVwZGF0ZVZpZXcodGhpcy5fcmVwb3J0SWQsIHJlcG9ydFZpZXdJZCwgeyBuYW1lIH0pKTtcbiAgfVxuXG4gIC8vIFNoYXJlcyB0aGUgb3BlbiB2aWV3IHdpdGggZXZlcnlvbmUgd2hvIG1heSBvcGVuIHRoZSByZXBvcnQsIG9yIHN0b3BzLlxuICBwdWJsaWMgc2hhcmUoc2hhcmVkOiBib29sZWFuKTogT2JzZXJ2YWJsZTxSZXBvcnRWaWV3PiB7XG4gICAgcmV0dXJuIHRoaXMuX2NoYW5nZU9wZW4oKHJlcG9ydFZpZXdJZCkgPT4gdGhpcy5fcmVwb3J0RGF0YS5zaGFyZVZpZXcodGhpcy5fcmVwb3J0SWQsIHJlcG9ydFZpZXdJZCwgc2hhcmVkKSk7XG4gIH1cblxuICAvLyBNYWtlcyB0aGUgb3BlbiB2aWV3IHRoZSB2aWV3ZXIncyBkZWZhdWx0LCBvciBzdG9wcyBvcGVuaW5nIGl0IGJ5IGRlZmF1bHQuXG4gIHB1YmxpYyBzZXREZWZhdWx0KHBlcnNvbmFsRGVmYXVsdDogYm9vbGVhbik6IE9ic2VydmFibGU8UmVwb3J0Vmlldz4ge1xuICAgIHJldHVybiB0aGlzLl9jaGFuZ2VPcGVuKChyZXBvcnRWaWV3SWQpID0+IHRoaXMuX3JlcG9ydERhdGEuc2V0Vmlld0RlZmF1bHQodGhpcy5fcmVwb3J0SWQsIHJlcG9ydFZpZXdJZCwgcGVyc29uYWxEZWZhdWx0KSk7XG4gIH1cblxuICAvLyBEZWxldGVzIHRoZSBvcGVuIHZpZXcuIFRoZSBzY3JlZW4gc3RheXM7IHRoZSByZXBvcnQncyBkZWZhdWx0cyBiZWNvbWVcbiAgLy8gd2hhdCBpdCBpcyBjb21wYXJlZCB3aXRoLlxuICBwdWJsaWMgZGVsZXRlT3BlbigpOiBPYnNlcnZhYmxlPFJlcG9ydFZpZXdEZWxldGVkPiB7XG4gICAgY29uc3Qgb3BlbiA9IHRoaXMuX29wZW5WaWV3KCk7XG4gICAgaWYgKCFvcGVuKSB7XG4gICAgICByZXR1cm4gRU1QVFk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX3JlcG9ydERhdGEuZGVsZXRlVmlldyh0aGlzLl9yZXBvcnRJZCwgb3Blbi5pZClcbiAgICAgIC5waXBlKFxuICAgICAgICB0YXAoKCkgPT4ge1xuICAgICAgICAgIHRoaXMuX29wZW5WaWV3LnNldChudWxsKTtcbiAgICAgICAgICB0aGlzLl92aWV3cy51cGRhdGUoKHZpZXdzKSA9PiB2aWV3cy5maWx0ZXIoKHZpZXcpID0+IHZpZXcuaWQgIT09IG9wZW4uaWQpKTtcbiAgICAgICAgICB0aGlzLl9maWx0ZXJTdGF0ZS5jbGVhckJhc2UoKTtcbiAgICAgICAgICB0aGlzLl9tZXNzYWdlLnN1Y2Nlc3MoJ1ZpZXcgZGVsZXRlZCcpO1xuICAgICAgICB9KSxcbiAgICAgICk7XG4gIH1cblxuICAvLyBUaGUgcXVlcnkgcGFyYW1zIHRoYXQgbWFrZSB0aGUgVVJMIGNhcnJ5IHRoZSBzY3JlZW4gKHNlZSB0aGUgY2xhc3NcbiAgLy8gY29tbWVudCksIHNwcmVhZCBvdmVyIHRoZSBvd25lZCBrZXlzIGBjdXJyZW50YCBjYXJyaWVzIHNvIHRoZSBvbmVzIHRoZVxuICAvLyBzY3JlZW4gbm8gbG9uZ2VyIG5lZWRzIGFyZSByZW1vdmVkLiBUaGUgaG9zdCBhZGRzIGl0cyBwYWdlIGtleS5cbiAgLy8gQSBzZWxlY3QncyB2YWx1ZSBpcyBuYW1lZCBieSBgbmFtZWAsIGVsc2UgYnkgdGhlIG5hbWUgYGN1cnJlbnRgIGNhcnJpZXNcbiAgLy8gZm9yIGl0LlxuICBwdWJsaWMgdXJsUGFyYW1zKGN1cnJlbnQ6IFBhcmFtTWFwLCBuYW1lOiBSZXBvcnRVcmxWYWx1ZU5hbWUgPSAoKSA9PiBudWxsKTogUGFyYW1zIHtcbiAgICBjb25zdCBjdXJyZW50TmFtZSA9IHVybFZhbHVlTmFtZXMoY3VycmVudCwgdGhpcy5fcmVwb3J0R3JvdXBzKCkpO1xuICAgIGNvbnN0IHdyaXRlID0gdGhpcy5fbGlua1dyaXRlKChncm91cElkLCB2YWx1ZSkgPT4gbmFtZShncm91cElkLCB2YWx1ZSkgPz8gY3VycmVudE5hbWUoZ3JvdXBJZCwgdmFsdWUpKTtcblxuICAgIGlmICh3cml0ZS50b29Mb25nICYmICF0aGlzLl90b29Mb25nU2hvd24pIHtcbiAgICAgIHRoaXMuX3Rvb0xvbmdTaG93biA9IHRydWU7XG4gICAgICB0aGlzLl9tZXNzYWdlLndhcm5pbmcoVVJMX1RPT19MT05HX01FU1NBR0UpO1xuICAgIH1cblxuICAgIHJldHVybiB7IC4uLnJlcG9ydFBhcmFtc1RvQ2xlYXIoY3VycmVudCwgdGhpcy5fcmVwb3J0R3JvdXBzKCkpLCAuLi53cml0ZS5wYXJhbXMgfTtcbiAgfVxuXG4gIC8vIFN0YXJ0cyBvdmVyIGZvciBhbm90aGVyIHJlcG9ydDogbm8gbGlzdCBhbmQgbm8gb3BlbiB2aWV3LlxuICBwcml2YXRlIF9zdGFydChyZXBvcnQ6IFJlcG9ydCk6IHZvaWQge1xuICAgIGlmIChyZXBvcnQuaWQgPT09IHRoaXMuX3JlcG9ydElkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fcmVwb3J0SWQgPSByZXBvcnQuaWQ7XG4gICAgdGhpcy5fdmlld3Muc2V0KFtdKTtcbiAgICB0aGlzLl9jYW5TaGFyZS5zZXQoZmFsc2UpO1xuICAgIHRoaXMuX29wZW5WaWV3LnNldChudWxsKTtcbiAgICB0aGlzLl90b29Mb25nU2hvd24gPSBmYWxzZTtcbiAgfVxuXG4gIC8vIE5vIGxpbms6IHRoZSB2aWV3ZXIncyBkZWZhdWx0IHZpZXcsIGVsc2UgdGhlIHJlcG9ydCdzIGRlZmF1bHRzLCBvbmNlIHRoZVxuICAvLyBsaXN0IGlzIHJlYWQuXG4gIHByaXZhdGUgX29wZW5EZWZhdWx0KHJlcG9ydDogUmVwb3J0LCBwYWdlOiBSZXBvcnRWaWV3Q29uZmlnIHwgbnVsbCk6IE9ic2VydmFibGU8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLl9yZWFkVmlld3MocmVwb3J0KVxuICAgICAgLnBpcGUoXG4gICAgICAgIHRhcCgobGlzdCkgPT4ge1xuICAgICAgICAgIHRoaXMuX2ZpbHRlclN0YXRlLmluaXQocmVwb3J0KTtcbiAgICAgICAgICBpZiAobGlzdD8ubXlEZWZhdWx0KSB7XG4gICAgICAgICAgICB0aGlzLl9vcGVuT24obGlzdC5teURlZmF1bHQsICgpID0+IHRoaXMuX2ZpbHRlclN0YXRlLmFwcGx5KGxpc3QubXlEZWZhdWx0LmNvbmZpZywgcGFnZSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSksXG4gICAgICAgIG1hcCgoKSA9PiB1bmRlZmluZWQpLFxuICAgICAgKTtcbiAgfVxuXG4gIC8vIEEgbGluayB3aXRoIHN0YXRlOiBvbiB0aGUgc2hhcmVkIHZpZXcgcnYgbmFtZXMsIGVsc2Ugb24gdGhlIHJlcG9ydCdzXG4gIC8vIGRlZmF1bHRzOyBycHYncyB2aWV3IGlzIHRoZSBvcGVuIHZpZXcgb25seSB3aGVuIHRoZSB2aWV3ZXIgb3ducyBpdC5cbiAgcHJpdmF0ZSBfb3BlbkxpbmsobGluazogUmVwb3J0VXJsTGluaywgdmlldzogUmVwb3J0VmlldyB8IG51bGwsIGxpbmtEaWZmOiBSZXBvcnRWaWV3Q29uZmlnKTogdm9pZCB7XG4gICAgaWYgKGxpbmsudmlld0lkICYmIHZpZXcpIHtcbiAgICAgIHRoaXMuX29wZW5Pbih2aWV3LCAoKSA9PiB0aGlzLl9maWx0ZXJTdGF0ZS5hcHBseSh2aWV3LmNvbmZpZywgbGlua0RpZmYpKTtcblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghbGluay52aWV3SWQgJiYgdmlldz8ubWluZSkge1xuICAgICAgdGhpcy5fb3Blbk9uKHZpZXcsICgpID0+IHRoaXMuX2ZpbHRlclN0YXRlLmFwcGx5KG51bGwsIGxpbmtEaWZmLCB2aWV3LmNvbmZpZykpO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fb3BlblZpZXcuc2V0KG51bGwpO1xuICAgIHRoaXMuX2ZpbHRlclN0YXRlLmFwcGx5KG51bGwsIGxpbmtEaWZmKTtcblxuICAgIGlmIChsaW5rLnZpZXdJZCkge1xuICAgICAgdGhpcy5fbWVzc2FnZS53YXJuaW5nKFZJRVdfTk9UX0FWQUlMQUJMRV9NRVNTQUdFKTtcbiAgICB9XG4gIH1cblxuICAvLyBNYWtlcyBgdmlld2AgdGhlIG9wZW4gdmlldywgcHV0cyBpdCBvbiBzY3JlZW4gKGBhcHBseVZpZXdgKSwgYW5kIHNheXNcbiAgLy8gaG93IG1hbnkgb2YgaXRzIHNldHRpbmdzIG5vIGxvbmdlciBhcHBseSAoYW5kIHRvIHNhdmUgaXQsIHdoZW4gdGhlXG4gIC8vIHZpZXdlciBtYXkpLlxuICBwcml2YXRlIF9vcGVuT24odmlldzogUmVwb3J0VmlldywgYXBwbHlWaWV3OiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5fb3BlblZpZXcuc2V0KHZpZXcpO1xuICAgIGFwcGx5VmlldygpO1xuXG4gICAgY29uc3Qgbm90ZSA9IHZpZXdEcm9wcGVkTWVzc2FnZSh2aWV3RHJvcHBlZENvdW50KHZpZXcsIHRoaXMuX2ZpbHRlclN0YXRlLmJhc2UoKSksIHZpZXcuY2FuQ2hhbmdlKTtcbiAgICBpZiAobm90ZSkge1xuICAgICAgdGhpcy5fbWVzc2FnZS53YXJuaW5nKG5vdGUpO1xuICAgIH1cbiAgfVxuXG4gIC8vIFJ1bnMgYSBjaGFuZ2Ugb24gdGhlIG9wZW4gdmlldyBhbmQgdGFrZXMgaXRzIGFuc3dlciBhcyB0aGUgb3BlbiB2aWV3XG4gIC8vIGFuZCBpdHMgcm93IGluIHRoZSBsaXN0LiBBIGNoYW5nZSBvZiB3aG8gbWF5IHNlZSB0aGUgdmlldyAoc2hhcmVkLCBvclxuICAvLyB3aG9zZSBpdCBpcykgY2hhbmdlcyB0aGUga2V5IGEgbGluayBuYW1lcyBpdCBieSwgc28gdGhlIFVSTCBpcyB3cml0dGVuXG4gIC8vIGFnYWluLlxuICBwcml2YXRlIF9jaGFuZ2VPcGVuKGNoYW5nZTogKHJlcG9ydFZpZXdJZDogbnVtYmVyKSA9PiBPYnNlcnZhYmxlPFJlcG9ydFZpZXc+KTogT2JzZXJ2YWJsZTxSZXBvcnRWaWV3PiB7XG4gICAgY29uc3Qgb3BlbiA9IHRoaXMuX29wZW5WaWV3KCk7XG4gICAgaWYgKCFvcGVuKSB7XG4gICAgICByZXR1cm4gRU1QVFk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNoYW5nZShvcGVuLmlkKVxuICAgICAgLnBpcGUoXG4gICAgICAgIHRhcCgodmlldykgPT4ge1xuICAgICAgICAgIHRoaXMuX29wZW5WaWV3LnNldCh2aWV3KTtcbiAgICAgICAgICB0aGlzLl9wdXRSb3codmlldyk7XG5cbiAgICAgICAgICBpZiAodmlldy5zaGFyZWQgIT09IG9wZW4uc2hhcmVkIHx8IHZpZXcubWluZSAhPT0gb3Blbi5taW5lKSB7XG4gICAgICAgICAgICB0aGlzLl9maWx0ZXJTdGF0ZS5yZXdyaXRlVXJsKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KSxcbiAgICAgICk7XG4gIH1cblxuICAvLyBBIHZpZXcncyByb3cgaW4gdGhlIGxpc3QsIHJlcGxhY2VkIG9yIGFkZGVkLiBBIG5ldyBkZWZhdWx0IGNsZWFycyB0aGVcbiAgLy8gZmxhZyBvbiB0aGUgdmlld2VyJ3Mgb3RoZXIgdmlld3MsIGFzIHRoZSBzZXJ2ZXIgZG9lcy4gQSBuZXcgcm93IGtlZXBzXG4gIC8vIHRoZSBsaXN0J3Mgb3JkZXI6IHRoZSB2aWV3ZXIncyBvd24gdmlld3MgZmlyc3QsIHRoZW4gdGhlIG9uZXMgb3RoZXJzXG4gIC8vIHNoYXJlLlxuICBwcml2YXRlIF9wdXRSb3codmlldzogUmVwb3J0Vmlldyk6IHZvaWQge1xuICAgIGNvbnN0IHN1bW1hcnkgPSB2aWV3U3VtbWFyeSh2aWV3KTtcblxuICAgIHRoaXMuX3ZpZXdzLnVwZGF0ZSgodmlld3MpID0+IHtcbiAgICAgIGNvbnN0IHJvd3MgPSB2aWV3cy5tYXAoKHJvdykgPT4gKHZpZXcucGVyc29uYWxEZWZhdWx0ICYmIHJvdy5wZXJzb25hbERlZmF1bHQgPyB7IC4uLnJvdywgcGVyc29uYWxEZWZhdWx0OiBmYWxzZSB9IDogcm93KSk7XG4gICAgICBjb25zdCBpbmRleCA9IHJvd3MuZmluZEluZGV4KChyb3cpID0+IHJvdy5pZCA9PT0gdmlldy5pZCk7XG5cbiAgICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICAgIHJldHVybiByb3dzLm1hcCgocm93LCBhdCkgPT4gKGF0ID09PSBpbmRleCA/IHN1bW1hcnkgOiByb3cpKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgb3RoZXJzQXQgPSB2aWV3Lm1pbmUgPyByb3dzLmZpbmRJbmRleCgocm93KSA9PiAhcm93Lm1pbmUpIDogLTE7XG5cbiAgICAgIHJldHVybiBvdGhlcnNBdCA8IDBcbiAgICAgICAgPyBbLi4ucm93cywgc3VtbWFyeV1cbiAgICAgICAgOiBbLi4ucm93cy5zbGljZSgwLCBvdGhlcnNBdCksIHN1bW1hcnksIC4uLnJvd3Muc2xpY2Uob3RoZXJzQXQpXTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFRoZSBsaXN0LCByZWFkIGZvciBgcmVwb3J0YDsgbnVsbCB3aGVuIGl0IGNhbm5vdCBiZSByZWFkLiBJdHMgYW5zd2VyIGlzXG4gIC8vIGtlcHQgb25seSB3aGlsZSB0aGUgcmVwb3J0IGlzIHN0aWxsIHRoZSBvcGVuIG9uZS5cbiAgcHJpdmF0ZSBfcmVhZFZpZXdzKHJlcG9ydDogUmVwb3J0KTogT2JzZXJ2YWJsZTxSZXBvcnRWaWV3cyB8IG51bGw+IHtcbiAgICByZXR1cm4gdGhpcy5fcmVwb3J0RGF0YS52aWV3cyhyZXBvcnQuaWQsIHsgY29udGV4dDogbmV3IEh0dHBDb250ZXh0KCkuc2V0KERpc3BsYXlBcGlFcnJvciwgZmFsc2UpIH0pXG4gICAgICAucGlwZShcbiAgICAgICAgY2F0Y2hFcnJvcigoKSA9PiBvZihudWxsKSksXG4gICAgICAgIHRhcCgobGlzdCkgPT4ge1xuICAgICAgICAgIGlmIChsaXN0ICYmIHJlcG9ydC5pZCA9PT0gdGhpcy5fcmVwb3J0SWQpIHtcbiAgICAgICAgICAgIHRoaXMuX3ZpZXdzLnNldChsaXN0LnZpZXdzID8/IFtdKTtcbiAgICAgICAgICAgIHRoaXMuX2NhblNoYXJlLnNldCghIWxpc3QuY2FuU2hhcmUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSksXG4gICAgICApO1xuICB9XG5cbiAgLy8gQSB2aWV3IGEgbGluayBuYW1lczsgbnVsbCB3aGVuIHRoZSB2aWV3ZXIgY2Fubm90IG9wZW4gaXQuIFRoZSBzZXJ2ZXJcbiAgLy8gYW5zd2VycyAnVmlldyBub3QgZm91bmQnIGZvciBvbmUgaXQgY2Fubm90IHNlZSwgd2hpY2ggbXVzdCBub3QgbW92ZSB0aGVcbiAgLy8gaG9zdCB0byBpdHMgbm90LWZvdW5kIHBhZ2UuXG4gIHByaXZhdGUgX3JlYWRWaWV3KHJlcG9ydElkOiBudW1iZXIsIHJlcG9ydFZpZXdJZDogbnVtYmVyKTogT2JzZXJ2YWJsZTxSZXBvcnRWaWV3IHwgbnVsbD4ge1xuICAgIHJldHVybiB0aGlzLl9yZXBvcnREYXRhLnZpZXcocmVwb3J0SWQsIHJlcG9ydFZpZXdJZCwgeyBjb250ZXh0OiBuZXcgSHR0cENvbnRleHQoKS5zZXQoUHJvY2Vzc0FwaUVycm9yLCBmYWxzZSkgfSlcbiAgICAgIC5waXBlKGNhdGNoRXJyb3IoKCkgPT4gb2YobnVsbCkpKTtcbiAgfVxuXG4gIC8vIFRoZSBwYXJhbXMgdGhlIHNjcmVlbiB3cml0ZXMgKHNlZSB0aGUgY2xhc3MgY29tbWVudCkuXG4gIHByaXZhdGUgX2xpbmtXcml0ZShuYW1lOiBSZXBvcnRVcmxWYWx1ZU5hbWUpOiBSZXBvcnRVcmxXcml0ZSB7XG4gICAgY29uc3Qgb3BlbiA9IHRoaXMuX29wZW5WaWV3KCk7XG4gICAgY29uc3Qgc2NyZWVuID0gdGhpcy5fZmlsdGVyU3RhdGUuc25hcHNob3QoKTtcbiAgICBjb25zdCBhdXRob3JlZCA9IHRoaXMuX2ZpbHRlclN0YXRlLmF1dGhvcmVkQ29uZmlnKCk7XG4gICAgY29uc3QgYXV0aG9yZWRTb3J0ID0gKGNvbXBvbmVudElkOiBudW1iZXIpID0+IHRoaXMuX2F1dGhvcmVkU29ydChjb21wb25lbnRJZCk7XG5cbiAgICBpZiAob3Blbj8uc2hhcmVkKSB7XG4gICAgICAvLyBBIGdyb3VwIHRoZSB2aWV3IGhvbGRzIHRoYXQgdGhlIGJhc2UgbGV0IGdvIG9mIChpdHMgYXV0aG9yZWQgZGVmYXVsdFxuICAgICAgLy8gY2hhbmdlZCB3aGlsZSB0aGUgdmlldyB3YXMgb3BlbiwgYW5kIHRoZSBzY3JlZW4gdG9vayB0aGUgbmV3IG9uZSlcbiAgICAgIC8vIGlzIHN0aWxsIHRoZSB2aWV3J3MgdmFsdWUgd2hlbiBhIGxpbmsgb3BlbnMgdGhlIHZpZXcsIHNvIGl0IGlzXG4gICAgICAvLyBjb21wYXJlZCB3aXRoIHRoYXQgdmFsdWUgYW5kIHdyaXR0ZW4gd2hlbiB0aGUgc2NyZWVuIGRpZmZlcnMuXG4gICAgICBjb25zdCBiYXNlID0gdGhpcy5fZmlsdGVyU3RhdGUuYmFzZSgpO1xuICAgICAgY29uc3QgbGlua0Jhc2U6IFJlcG9ydFZpZXdDb25maWcgPSB7IC4uLmJhc2UsIGdyb3VwczogeyAuLi5vcGVuLmNvbmZpZz8uZ3JvdXBzLCAuLi5iYXNlLmdyb3VwcyB9IH07XG4gICAgICBjb25zdCBkaWZmID0gdmlld0NvbmZpZ0RpZmYobGlua0Jhc2UsIHNjcmVlbiwgYXV0aG9yZWQsIGF1dGhvcmVkU29ydCk7XG5cbiAgICAgIGlmIChkaWZmKSB7XG4gICAgICAgIHJldHVybiB2aWV3Q29uZmlnVG9QYXJhbXModGhpcy5fbGlua0RheXMoZGlmZiksIHRoaXMuX3JlcG9ydEdyb3VwcygpLCB7IHZpZXdJZDogb3Blbi5pZCB9LCBuYW1lKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBmdWxsID0gdmlld0NvbmZpZ0RpZmYoYXV0aG9yZWQsIHNjcmVlbiwgYXV0aG9yZWQsIGF1dGhvcmVkU29ydCkgPz8gc2NyZWVuO1xuXG4gICAgY29uc3QgbGluayA9IG9wZW4/Lm1pbmUgPyB7IHBlcnNvbmFsVmlld0lkOiBvcGVuLmlkIH0gOiB7fTtcblxuICAgIHJldHVybiB2aWV3Q29uZmlnVG9QYXJhbXModGhpcy5fbGlua0RheXMoZnVsbCksIHRoaXMuX3JlcG9ydEdyb3VwcygpLCBsaW5rLCBuYW1lKTtcbiAgfVxuXG4gIC8vIGBjb25maWdgIHdpdGggZWFjaCByb2xsaW5nIHJhbmdlIChhIHJlbGF0aXZlIG5hbWUsIHdoaWNoIGEgdmlldyBrZWVwcykgYXNcbiAgLy8gdGhlIGRheXMgaXQgZ2l2ZXMgdG9kYXkgaW4gdGhlIHJlcG9ydCdzIHpvbmU6IGEgbGluayBjYXJyaWVzIGRheXMsIG5ldmVyIGFcbiAgLy8gcHJlc2V0IG5hbWUuIEEgbmFtZSB0aGUgcmVwb3J0IGRvZXMgbm90IGtub3cgaXMgbGVmdCBhcyBpdCBpcywgYW5kIHRoZVxuICAvLyBsaW5rIGxlYXZlcyB0aGF0IGdyb3VwIG91dC5cbiAgcHJpdmF0ZSBfbGlua0RheXMoY29uZmlnOiBSZXBvcnRWaWV3Q29uZmlnKTogUmVwb3J0Vmlld0NvbmZpZyB7XG4gICAgaWYgKCFjb25maWcuZ3JvdXBzKSB7XG4gICAgICByZXR1cm4gY29uZmlnO1xuICAgIH1cblxuICAgIGNvbnN0IGdyb3VwcyA9IE9iamVjdC5lbnRyaWVzKGNvbmZpZy5ncm91cHMpXG4gICAgICAubWFwKChbZ3JvdXBJZCwgdmFsdWVdKSA9PiBbZ3JvdXBJZCwgdGhpcy5fZ3JvdXBEYXlzKHZhbHVlKV0pO1xuXG4gICAgcmV0dXJuIHsgLi4uY29uZmlnLCBncm91cHM6IE9iamVjdC5mcm9tRW50cmllcyhncm91cHMpIH07XG4gIH1cblxuICBwcml2YXRlIF9ncm91cERheXModmFsdWU6IEZpbHRlckdyb3VwRGVmYXVsdCB8IG51bGwpOiBGaWx0ZXJHcm91cERlZmF1bHQgfCBudWxsIHtcbiAgICBjb25zdCByYW5nZSA9IHZhbHVlPy5yZWxhdGl2ZSA/IHRoaXMuX2ZpbHRlclN0YXRlLnJlc29sdmVSZWxhdGl2ZSh2YWx1ZS5yZWxhdGl2ZSkgOiBudWxsO1xuXG4gICAgcmV0dXJuIHJhbmdlID8gdG9TdG9yZWRHcm91cFZhbHVlKCdkYXRlUmFuZ2UnLCB7IHN0YXJ0OiByYW5nZS5zdGFydCwgZW5kOiByYW5nZS5lbmQgfSkgOiB2YWx1ZTtcbiAgfVxuXG4gIC8vIEV2ZXJ5IGZpbHRlciBncm91cCBvZiB0aGUgb3BlbiByZXBvcnQ6IHRoZSBsaW5rIGtleXMgZWFjaCBieSBpdHMgbGFiZWwuXG4gIHByaXZhdGUgX3JlcG9ydEdyb3VwcygpOiBSZXBvcnRGaWx0ZXJHcm91cFtdIHtcbiAgICByZXR1cm4gdGhpcy5fZmlsdGVyU3RhdGUucmVwb3J0KCk/LmZpbHRlckdyb3VwcyA/PyBbXTtcbiAgfVxuXG4gIC8vIEEgbGlzdCdzIGF1dGhvcmVkIGZpcnN0IHNvcnQgdGVybSwgb3IgbnVsbCBmb3IgYW55IG90aGVyIGNvbXBvbmVudC5cbiAgcHJpdmF0ZSBfYXV0aG9yZWRTb3J0KGNvbXBvbmVudElkOiBudW1iZXIpOiBSZXBvcnRTb3J0IHwgbnVsbCB7XG4gICAgY29uc3QgcmVwb3J0ID0gdGhpcy5fZmlsdGVyU3RhdGUucmVwb3J0KCk7XG4gICAgY29uc3QgY29tcG9uZW50ID0gW1xuICAgICAgLi4uKHJlcG9ydD8ucGFnZXMgPz8gW10pLmZsYXRNYXAoKHBhZ2UpID0+IHBhZ2UuY29tcG9uZW50cyA/PyBbXSksXG4gICAgICAuLi4ocmVwb3J0Py5tYXN0ZXI/LmNvbXBvbmVudHMgPz8gW10pLFxuICAgIF0uZmluZCgoY2FuZGlkYXRlKSA9PiBjYW5kaWRhdGUuaWQgPT09IGNvbXBvbmVudElkKTtcblxuICAgIHJldHVybiBjb21wb25lbnQ/LnR5cGUgPT09ICdsaXN0JyA/IGxpc3RTb3J0VGVybXMoY29tcG9uZW50LmNvbmZpZylbMF0gPz8gbnVsbCA6IG51bGw7XG4gIH1cbn1cblxuXG4vLyBBIHZpZXcncyByb3cgYXMgdGhlIGxpc3QgaG9sZHMgaXQ6IG5hbWVzIGFuZCBmbGFncywgbm8gY29uZmlnLlxuZnVuY3Rpb24gdmlld1N1bW1hcnkodmlldzogUmVwb3J0Vmlldyk6IFJlcG9ydFZpZXdTdW1tYXJ5IHtcbiAgcmV0dXJuIHtcbiAgICBpZDogdmlldy5pZCxcbiAgICBuYW1lOiB2aWV3Lm5hbWUsXG4gICAgc2hhcmVkOiB2aWV3LnNoYXJlZCxcbiAgICBtaW5lOiB2aWV3Lm1pbmUsXG4gICAgcGVyc29uYWxEZWZhdWx0OiB2aWV3LnBlcnNvbmFsRGVmYXVsdCxcbiAgICBvd25lck5hbWU6IHZpZXcub3duZXJOYW1lLFxuICAgIGNhbkNoYW5nZTogdmlldy5jYW5DaGFuZ2UsXG4gICAgY2FuRGVsZXRlOiB2aWV3LmNhbkRlbGV0ZSxcbiAgICBtb2RpZnlEYXRlOiB2aWV3Lm1vZGlmeURhdGUsXG4gIH07XG59XG4iXX0=
@@ -0,0 +1,127 @@
1
+ import { isMatchAnyGroup } from './report-filter-items';
2
+ import { isTile } from './report-tile';
3
+ import { isChartGranularity } from './report-view-config';
4
+ // Whether a component is a chart on a time x-axis: the only component the
5
+ // report's group-by grain applies to. A deliberate mirror of the server's
6
+ // ReportQueryRunner::_isTimeSeriesChart, which is canonical and drops the
7
+ // grain for every other component; kept so a product pinned to an older
8
+ // framework does not re-bucket a non-time chart.
9
+ export function isTimeSeriesChart(component) {
10
+ return component.type === 'chart' && component.config?.xAxis?.kind === 'time';
11
+ }
12
+ // The interaction state one tile's data request carries, read off a view
13
+ // document of the screen (the state service's snapshot()): the group-by grain
14
+ // for a time-series chart, a list's sort, search and hidden columns, a
15
+ // chart's drill path, and, while the groups match 'any', the groups that
16
+ // combine (matchAnyGroupIds). The tile on screen, its CSV, the PDF and
17
+ // PowerPoint collector and the zip all build their state here, so a file
18
+ // always holds what the screen shows. A list's paging is the caller's. Never
19
+ // sets unchangedIfUnreached: that belongs to an on-screen refetch alone.
20
+ //
21
+ // A drill path and the grain may both be sent: the server lets the drilled
22
+ // level win, and a server that does not drill keeps the grain.
23
+ export function tileDataState(report, component, snapshot) {
24
+ const state = {};
25
+ if (!isTile(component)) {
26
+ return state;
27
+ }
28
+ const tile = snapshot.tiles?.[component.id];
29
+ if (isTimeSeriesChart(component) && isChartGranularity(snapshot.groupBy)) {
30
+ state.frequency = snapshot.groupBy;
31
+ }
32
+ if (component.type === 'list') {
33
+ if (tile?.sort?.column) {
34
+ state.sort = { ...tile.sort };
35
+ }
36
+ if (tile?.search) {
37
+ state.search = tile.search;
38
+ }
39
+ if (tile?.hidden?.length) {
40
+ state.hiddenColumns = [...tile.hidden];
41
+ }
42
+ }
43
+ if (component.type === 'chart' && tile?.drill?.length) {
44
+ state.drill = tile.drill.map((step) => ({ ...step }));
45
+ }
46
+ const matchAnyGroupIds = tileMatchAnyGroupIds(report, component, snapshot);
47
+ if (matchAnyGroupIds.length) {
48
+ state.matchAnyGroupIds = matchAnyGroupIds;
49
+ }
50
+ return state;
51
+ }
52
+ // Each tile's state for the zip export (tileDataState), by component id: the
53
+ // tiles of every page, or of `pageId` alone. The zip holds no header or
54
+ // footer tile. A tile with nothing to send is left out, so an untouched report
55
+ // sends no states at all.
56
+ export function zipExportStates(report, snapshot, pageId = null) {
57
+ const states = {};
58
+ (report.pages ?? [])
59
+ .filter((page) => !pageId || page.id === pageId)
60
+ .flatMap((page) => page.components ?? [])
61
+ .forEach((component) => {
62
+ const state = tileDataState(report, component, snapshot);
63
+ if (Object.keys(state).length) {
64
+ states[component.id] = state;
65
+ }
66
+ });
67
+ return states;
68
+ }
69
+ // The groups a tile's 'any' combines, in id order: while the snapshot's
70
+ // match is 'any', every eligible group that holds a value. A group the tile
71
+ // has no member of is listed too, so the server can tell a tile that cannot
72
+ // test every group (it then applies none of them and says so). A page group
73
+ // counts only for the tiles of its own page: it is in the report bar of no
74
+ // other page. A header or footer tile is a tile of the page on screen.
75
+ function tileMatchAnyGroupIds(report, component, snapshot) {
76
+ if (!report) {
77
+ return [];
78
+ }
79
+ return matchAnyGroupIdsOnPage(report, tilePageId(report, component, snapshot), snapshot);
80
+ }
81
+ // The groups a layer's inline values combine (the page values request's
82
+ // matchAnyGroupIds), by the tile rule (tileDataState): while the snapshot's
83
+ // match is 'any', every eligible group that holds a value, in id order. A
84
+ // value has no member of some of them, and the server then applies none of
85
+ // them to it, as it does for such a tile. `layerId` is the page the values
86
+ // sit on; the header and footer's values (any other id) are values of the
87
+ // page on screen, as a header or footer tile is.
88
+ export function valuesMatchAnyGroupIds(report, layerId, snapshot) {
89
+ if (!report) {
90
+ return [];
91
+ }
92
+ const page = (report.pages ?? []).find((candidate) => candidate.id === layerId);
93
+ return matchAnyGroupIdsOnPage(report, page?.id ?? snapshot.pageId ?? null, snapshot);
94
+ }
95
+ // While the snapshot's match is 'any': the eligible groups of the report bar
96
+ // on `pageId` that hold a value, in id order.
97
+ function matchAnyGroupIdsOnPage(report, pageId, snapshot) {
98
+ if (snapshot.match !== 'any') {
99
+ return [];
100
+ }
101
+ return (report.filterGroups ?? [])
102
+ .filter((group) => isMatchAnyGroup(group, pageId) && holdsValue(snapshot.groups?.[group.id]))
103
+ .map((group) => group.id)
104
+ .sort((a, b) => a - b);
105
+ }
106
+ // The page a tile is drawn on: its own page, or, for a header or footer
107
+ // tile, the page on screen. Null when neither is known. An inline value's
108
+ // page is the page whose values hold it, the same way.
109
+ export function tilePageId(report, component, snapshot) {
110
+ const page = (report.pages ?? [])
111
+ .find((candidate) => [...(candidate.components ?? []), ...(candidate.values ?? [])]
112
+ .some((item) => item.id === component.id));
113
+ return page?.id ?? snapshot.pageId ?? null;
114
+ }
115
+ // Whether a group's stored value holds something a request sends: picks to
116
+ // keep or leave out, text, or a number range end (0 is an end).
117
+ function holdsValue(value) {
118
+ if (!value) {
119
+ return false;
120
+ }
121
+ return !!value.values?.length
122
+ || !!value.excludeValues?.length
123
+ || (typeof value.value === 'string' && !!value.value.trim())
124
+ || Number.isFinite(value.min)
125
+ || Number.isFinite(value.max);
126
+ }
127
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGlsZS1kYXRhLXN0YXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL3RpbGUtZGF0YS1zdGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFPQSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDeEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN2QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUcxRCwwRUFBMEU7QUFDMUUsMEVBQTBFO0FBQzFFLDBFQUEwRTtBQUMxRSx3RUFBd0U7QUFDeEUsaURBQWlEO0FBQ2pELE1BQU0sVUFBVSxpQkFBaUIsQ0FBQyxTQUEwQjtJQUMxRCxPQUFPLFNBQVMsQ0FBQyxJQUFJLEtBQUssT0FBTyxJQUFJLFNBQVMsQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLElBQUksS0FBSyxNQUFNLENBQUM7QUFDaEYsQ0FBQztBQUdELHlFQUF5RTtBQUN6RSw4RUFBOEU7QUFDOUUsdUVBQXVFO0FBQ3ZFLHlFQUF5RTtBQUN6RSx1RUFBdUU7QUFDdkUseUVBQXlFO0FBQ3pFLDZFQUE2RTtBQUM3RSx5RUFBeUU7QUFDekUsRUFBRTtBQUNGLDJFQUEyRTtBQUMzRSwrREFBK0Q7QUFDL0QsTUFBTSxVQUFVLGFBQWEsQ0FDM0IsTUFBcUIsRUFDckIsU0FBMEIsRUFDMUIsUUFBMEI7SUFFMUIsTUFBTSxLQUFLLEdBQXVCLEVBQUUsQ0FBQztJQUVyQyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7UUFDdkIsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUU1QyxJQUFJLGlCQUFpQixDQUFDLFNBQVMsQ0FBQyxJQUFJLGtCQUFrQixDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ3pFLEtBQUssQ0FBQyxTQUFTLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQztJQUNyQyxDQUFDO0lBRUQsSUFBSSxTQUFTLENBQUMsSUFBSSxLQUFLLE1BQU0sRUFBRSxDQUFDO1FBQzlCLElBQUksSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQztZQUN2QixLQUFLLENBQUMsSUFBSSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDaEMsQ0FBQztRQUNELElBQUksSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDO1lBQ2pCLEtBQUssQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUM3QixDQUFDO1FBQ0QsSUFBSSxJQUFJLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxDQUFDO1lBQ3pCLEtBQUssQ0FBQyxhQUFhLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN6QyxDQUFDO0lBQ0gsQ0FBQztJQUVELElBQUksU0FBUyxDQUFDLElBQUksS0FBSyxPQUFPLElBQUksSUFBSSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsQ0FBQztRQUN0RCxLQUFLLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsR0FBRyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUVELE1BQU0sZ0JBQWdCLEdBQUcsb0JBQW9CLENBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUMzRSxJQUFJLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzVCLEtBQUssQ0FBQyxnQkFBZ0IsR0FBRyxnQkFBZ0IsQ0FBQztJQUM1QyxDQUFDO0lBRUQsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDO0FBR0QsNkVBQTZFO0FBQzdFLHdFQUF3RTtBQUN4RSwrRUFBK0U7QUFDL0UsMEJBQTBCO0FBQzFCLE1BQU0sVUFBVSxlQUFlLENBQzdCLE1BQWMsRUFDZCxRQUEwQixFQUMxQixTQUF3QixJQUFJO0lBRTVCLE1BQU0sTUFBTSxHQUF1QyxFQUFFLENBQUM7SUFFdEQsQ0FBQyxNQUFNLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQztTQUNqQixNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxFQUFFLEtBQUssTUFBTSxDQUFDO1NBQy9DLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsSUFBSSxFQUFFLENBQUM7U0FDeEMsT0FBTyxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUU7UUFDckIsTUFBTSxLQUFLLEdBQUcsYUFBYSxDQUFDLE1BQU0sRUFBRSxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFFekQsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzlCLE1BQU0sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDO1FBQy9CLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztJQUVMLE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFHRCx3RUFBd0U7QUFDeEUsNEVBQTRFO0FBQzVFLDRFQUE0RTtBQUM1RSw0RUFBNEU7QUFDNUUsMkVBQTJFO0FBQzNFLHVFQUF1RTtBQUN2RSxTQUFTLG9CQUFvQixDQUFDLE1BQXFCLEVBQUUsU0FBMEIsRUFBRSxRQUEwQjtJQUN6RyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDWixPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFFRCxPQUFPLHNCQUFzQixDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQztBQUMzRixDQUFDO0FBR0Qsd0VBQXdFO0FBQ3hFLDRFQUE0RTtBQUM1RSwwRUFBMEU7QUFDMUUsMkVBQTJFO0FBQzNFLDJFQUEyRTtBQUMzRSwwRUFBMEU7QUFDMUUsaURBQWlEO0FBQ2pELE1BQU0sVUFBVSxzQkFBc0IsQ0FDcEMsTUFBcUIsRUFDckIsT0FBc0IsRUFDdEIsUUFBMEI7SUFFMUIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ1osT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQsTUFBTSxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLEVBQUUsS0FBSyxPQUFPLENBQUMsQ0FBQztJQUVoRixPQUFPLHNCQUFzQixDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxJQUFJLFFBQVEsQ0FBQyxNQUFNLElBQUksSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQ3ZGLENBQUM7QUFHRCw2RUFBNkU7QUFDN0UsOENBQThDO0FBQzlDLFNBQVMsc0JBQXNCLENBQUMsTUFBYyxFQUFFLE1BQXFCLEVBQUUsUUFBMEI7SUFDL0YsSUFBSSxRQUFRLENBQUMsS0FBSyxLQUFLLEtBQUssRUFBRSxDQUFDO1FBQzdCLE9BQU8sRUFBRSxDQUFDO0lBQ1osQ0FBQztJQUVELE9BQU8sQ0FBQyxNQUFNLENBQUMsWUFBWSxJQUFJLEVBQUUsQ0FBQztTQUMvQixNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLElBQUksVUFBVSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztTQUM1RixHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7U0FDeEIsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0FBQzNCLENBQUM7QUFHRCx3RUFBd0U7QUFDeEUsMEVBQTBFO0FBQzFFLHVEQUF1RDtBQUN2RCxNQUFNLFVBQVUsVUFBVSxDQUFDLE1BQWMsRUFBRSxTQUEwQixFQUFFLFFBQTBCO0lBQy9GLE1BQU0sSUFBSSxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7U0FDOUIsSUFBSSxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxTQUFTLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1NBQ2hGLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUUvQyxPQUFPLElBQUksRUFBRSxFQUFFLElBQUksUUFBUSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUM7QUFDN0MsQ0FBQztBQUdELDJFQUEyRTtBQUMzRSxnRUFBZ0U7QUFDaEUsU0FBUyxVQUFVLENBQUMsS0FBNEM7SUFDOUQsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ1gsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsT0FBTyxDQUFDLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxNQUFNO1dBQ3hCLENBQUMsQ0FBQyxLQUFLLENBQUMsYUFBYSxFQUFFLE1BQU07V0FDN0IsQ0FBQyxPQUFPLEtBQUssQ0FBQyxLQUFLLEtBQUssUUFBUSxJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO1dBQ3pELE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQztXQUMxQixNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNsQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUmVwb3J0Vmlld0NvbmZpZyB9IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQtdmlldy1jb25maWcuaW50ZXJmYWNlJztcbmltcG9ydCB7XG4gIENvbXBvbmVudERhdGFTdGF0ZSxcbiAgRmlsdGVyR3JvdXBEZWZhdWx0LFxuICBSZXBvcnQsXG4gIFJlcG9ydENvbXBvbmVudCxcbn0gZnJvbSAnLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgaXNNYXRjaEFueUdyb3VwIH0gZnJvbSAnLi9yZXBvcnQtZmlsdGVyLWl0ZW1zJztcbmltcG9ydCB7IGlzVGlsZSB9IGZyb20gJy4vcmVwb3J0LXRpbGUnO1xuaW1wb3J0IHsgaXNDaGFydEdyYW51bGFyaXR5IH0gZnJvbSAnLi9yZXBvcnQtdmlldy1jb25maWcnO1xuXG5cbi8vIFdoZXRoZXIgYSBjb21wb25lbnQgaXMgYSBjaGFydCBvbiBhIHRpbWUgeC1heGlzOiB0aGUgb25seSBjb21wb25lbnQgdGhlXG4vLyByZXBvcnQncyBncm91cC1ieSBncmFpbiBhcHBsaWVzIHRvLiBBIGRlbGliZXJhdGUgbWlycm9yIG9mIHRoZSBzZXJ2ZXInc1xuLy8gUmVwb3J0UXVlcnlSdW5uZXI6Ol9pc1RpbWVTZXJpZXNDaGFydCwgd2hpY2ggaXMgY2Fub25pY2FsIGFuZCBkcm9wcyB0aGVcbi8vIGdyYWluIGZvciBldmVyeSBvdGhlciBjb21wb25lbnQ7IGtlcHQgc28gYSBwcm9kdWN0IHBpbm5lZCB0byBhbiBvbGRlclxuLy8gZnJhbWV3b3JrIGRvZXMgbm90IHJlLWJ1Y2tldCBhIG5vbi10aW1lIGNoYXJ0LlxuZXhwb3J0IGZ1bmN0aW9uIGlzVGltZVNlcmllc0NoYXJ0KGNvbXBvbmVudDogUmVwb3J0Q29tcG9uZW50KTogYm9vbGVhbiB7XG4gIHJldHVybiBjb21wb25lbnQudHlwZSA9PT0gJ2NoYXJ0JyAmJiBjb21wb25lbnQuY29uZmlnPy54QXhpcz8ua2luZCA9PT0gJ3RpbWUnO1xufVxuXG5cbi8vIFRoZSBpbnRlcmFjdGlvbiBzdGF0ZSBvbmUgdGlsZSdzIGRhdGEgcmVxdWVzdCBjYXJyaWVzLCByZWFkIG9mZiBhIHZpZXdcbi8vIGRvY3VtZW50IG9mIHRoZSBzY3JlZW4gKHRoZSBzdGF0ZSBzZXJ2aWNlJ3Mgc25hcHNob3QoKSk6IHRoZSBncm91cC1ieSBncmFpblxuLy8gZm9yIGEgdGltZS1zZXJpZXMgY2hhcnQsIGEgbGlzdCdzIHNvcnQsIHNlYXJjaCBhbmQgaGlkZGVuIGNvbHVtbnMsIGFcbi8vIGNoYXJ0J3MgZHJpbGwgcGF0aCwgYW5kLCB3aGlsZSB0aGUgZ3JvdXBzIG1hdGNoICdhbnknLCB0aGUgZ3JvdXBzIHRoYXRcbi8vIGNvbWJpbmUgKG1hdGNoQW55R3JvdXBJZHMpLiBUaGUgdGlsZSBvbiBzY3JlZW4sIGl0cyBDU1YsIHRoZSBQREYgYW5kXG4vLyBQb3dlclBvaW50IGNvbGxlY3RvciBhbmQgdGhlIHppcCBhbGwgYnVpbGQgdGhlaXIgc3RhdGUgaGVyZSwgc28gYSBmaWxlXG4vLyBhbHdheXMgaG9sZHMgd2hhdCB0aGUgc2NyZWVuIHNob3dzLiBBIGxpc3QncyBwYWdpbmcgaXMgdGhlIGNhbGxlcidzLiBOZXZlclxuLy8gc2V0cyB1bmNoYW5nZWRJZlVucmVhY2hlZDogdGhhdCBiZWxvbmdzIHRvIGFuIG9uLXNjcmVlbiByZWZldGNoIGFsb25lLlxuLy9cbi8vIEEgZHJpbGwgcGF0aCBhbmQgdGhlIGdyYWluIG1heSBib3RoIGJlIHNlbnQ6IHRoZSBzZXJ2ZXIgbGV0cyB0aGUgZHJpbGxlZFxuLy8gbGV2ZWwgd2luLCBhbmQgYSBzZXJ2ZXIgdGhhdCBkb2VzIG5vdCBkcmlsbCBrZWVwcyB0aGUgZ3JhaW4uXG5leHBvcnQgZnVuY3Rpb24gdGlsZURhdGFTdGF0ZShcbiAgcmVwb3J0OiBSZXBvcnQgfCBudWxsLFxuICBjb21wb25lbnQ6IFJlcG9ydENvbXBvbmVudCxcbiAgc25hcHNob3Q6IFJlcG9ydFZpZXdDb25maWcsXG4pOiBDb21wb25lbnREYXRhU3RhdGUge1xuICBjb25zdCBzdGF0ZTogQ29tcG9uZW50RGF0YVN0YXRlID0ge307XG5cbiAgaWYgKCFpc1RpbGUoY29tcG9uZW50KSkge1xuICAgIHJldHVybiBzdGF0ZTtcbiAgfVxuXG4gIGNvbnN0IHRpbGUgPSBzbmFwc2hvdC50aWxlcz8uW2NvbXBvbmVudC5pZF07XG5cbiAgaWYgKGlzVGltZVNlcmllc0NoYXJ0KGNvbXBvbmVudCkgJiYgaXNDaGFydEdyYW51bGFyaXR5KHNuYXBzaG90Lmdyb3VwQnkpKSB7XG4gICAgc3RhdGUuZnJlcXVlbmN5ID0gc25hcHNob3QuZ3JvdXBCeTtcbiAgfVxuXG4gIGlmIChjb21wb25lbnQudHlwZSA9PT0gJ2xpc3QnKSB7XG4gICAgaWYgKHRpbGU/LnNvcnQ/LmNvbHVtbikge1xuICAgICAgc3RhdGUuc29ydCA9IHsgLi4udGlsZS5zb3J0IH07XG4gICAgfVxuICAgIGlmICh0aWxlPy5zZWFyY2gpIHtcbiAgICAgIHN0YXRlLnNlYXJjaCA9IHRpbGUuc2VhcmNoO1xuICAgIH1cbiAgICBpZiAodGlsZT8uaGlkZGVuPy5sZW5ndGgpIHtcbiAgICAgIHN0YXRlLmhpZGRlbkNvbHVtbnMgPSBbLi4udGlsZS5oaWRkZW5dO1xuICAgIH1cbiAgfVxuXG4gIGlmIChjb21wb25lbnQudHlwZSA9PT0gJ2NoYXJ0JyAmJiB0aWxlPy5kcmlsbD8ubGVuZ3RoKSB7XG4gICAgc3RhdGUuZHJpbGwgPSB0aWxlLmRyaWxsLm1hcCgoc3RlcCkgPT4gKHsgLi4uc3RlcCB9KSk7XG4gIH1cblxuICBjb25zdCBtYXRjaEFueUdyb3VwSWRzID0gdGlsZU1hdGNoQW55R3JvdXBJZHMocmVwb3J0LCBjb21wb25lbnQsIHNuYXBzaG90KTtcbiAgaWYgKG1hdGNoQW55R3JvdXBJZHMubGVuZ3RoKSB7XG4gICAgc3RhdGUubWF0Y2hBbnlHcm91cElkcyA9IG1hdGNoQW55R3JvdXBJZHM7XG4gIH1cblxuICByZXR1cm4gc3RhdGU7XG59XG5cblxuLy8gRWFjaCB0aWxlJ3Mgc3RhdGUgZm9yIHRoZSB6aXAgZXhwb3J0ICh0aWxlRGF0YVN0YXRlKSwgYnkgY29tcG9uZW50IGlkOiB0aGVcbi8vIHRpbGVzIG9mIGV2ZXJ5IHBhZ2UsIG9yIG9mIGBwYWdlSWRgIGFsb25lLiBUaGUgemlwIGhvbGRzIG5vIGhlYWRlciBvclxuLy8gZm9vdGVyIHRpbGUuIEEgdGlsZSB3aXRoIG5vdGhpbmcgdG8gc2VuZCBpcyBsZWZ0IG91dCwgc28gYW4gdW50b3VjaGVkIHJlcG9ydFxuLy8gc2VuZHMgbm8gc3RhdGVzIGF0IGFsbC5cbmV4cG9ydCBmdW5jdGlvbiB6aXBFeHBvcnRTdGF0ZXMoXG4gIHJlcG9ydDogUmVwb3J0LFxuICBzbmFwc2hvdDogUmVwb3J0Vmlld0NvbmZpZyxcbiAgcGFnZUlkOiBudW1iZXIgfCBudWxsID0gbnVsbCxcbik6IFJlY29yZDxudW1iZXIsIENvbXBvbmVudERhdGFTdGF0ZT4ge1xuICBjb25zdCBzdGF0ZXM6IFJlY29yZDxudW1iZXIsIENvbXBvbmVudERhdGFTdGF0ZT4gPSB7fTtcblxuICAocmVwb3J0LnBhZ2VzID8/IFtdKVxuICAgIC5maWx0ZXIoKHBhZ2UpID0+ICFwYWdlSWQgfHwgcGFnZS5pZCA9PT0gcGFnZUlkKVxuICAgIC5mbGF0TWFwKChwYWdlKSA9PiBwYWdlLmNvbXBvbmVudHMgPz8gW10pXG4gICAgLmZvckVhY2goKGNvbXBvbmVudCkgPT4ge1xuICAgICAgY29uc3Qgc3RhdGUgPSB0aWxlRGF0YVN0YXRlKHJlcG9ydCwgY29tcG9uZW50LCBzbmFwc2hvdCk7XG5cbiAgICAgIGlmIChPYmplY3Qua2V5cyhzdGF0ZSkubGVuZ3RoKSB7XG4gICAgICAgIHN0YXRlc1tjb21wb25lbnQuaWRdID0gc3RhdGU7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgcmV0dXJuIHN0YXRlcztcbn1cblxuXG4vLyBUaGUgZ3JvdXBzIGEgdGlsZSdzICdhbnknIGNvbWJpbmVzLCBpbiBpZCBvcmRlcjogd2hpbGUgdGhlIHNuYXBzaG90J3Ncbi8vIG1hdGNoIGlzICdhbnknLCBldmVyeSBlbGlnaWJsZSBncm91cCB0aGF0IGhvbGRzIGEgdmFsdWUuIEEgZ3JvdXAgdGhlIHRpbGVcbi8vIGhhcyBubyBtZW1iZXIgb2YgaXMgbGlzdGVkIHRvbywgc28gdGhlIHNlcnZlciBjYW4gdGVsbCBhIHRpbGUgdGhhdCBjYW5ub3Rcbi8vIHRlc3QgZXZlcnkgZ3JvdXAgKGl0IHRoZW4gYXBwbGllcyBub25lIG9mIHRoZW0gYW5kIHNheXMgc28pLiBBIHBhZ2UgZ3JvdXBcbi8vIGNvdW50cyBvbmx5IGZvciB0aGUgdGlsZXMgb2YgaXRzIG93biBwYWdlOiBpdCBpcyBpbiB0aGUgcmVwb3J0IGJhciBvZiBub1xuLy8gb3RoZXIgcGFnZS4gQSBoZWFkZXIgb3IgZm9vdGVyIHRpbGUgaXMgYSB0aWxlIG9mIHRoZSBwYWdlIG9uIHNjcmVlbi5cbmZ1bmN0aW9uIHRpbGVNYXRjaEFueUdyb3VwSWRzKHJlcG9ydDogUmVwb3J0IHwgbnVsbCwgY29tcG9uZW50OiBSZXBvcnRDb21wb25lbnQsIHNuYXBzaG90OiBSZXBvcnRWaWV3Q29uZmlnKTogbnVtYmVyW10ge1xuICBpZiAoIXJlcG9ydCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIHJldHVybiBtYXRjaEFueUdyb3VwSWRzT25QYWdlKHJlcG9ydCwgdGlsZVBhZ2VJZChyZXBvcnQsIGNvbXBvbmVudCwgc25hcHNob3QpLCBzbmFwc2hvdCk7XG59XG5cblxuLy8gVGhlIGdyb3VwcyBhIGxheWVyJ3MgaW5saW5lIHZhbHVlcyBjb21iaW5lICh0aGUgcGFnZSB2YWx1ZXMgcmVxdWVzdCdzXG4vLyBtYXRjaEFueUdyb3VwSWRzKSwgYnkgdGhlIHRpbGUgcnVsZSAodGlsZURhdGFTdGF0ZSk6IHdoaWxlIHRoZSBzbmFwc2hvdCdzXG4vLyBtYXRjaCBpcyAnYW55JywgZXZlcnkgZWxpZ2libGUgZ3JvdXAgdGhhdCBob2xkcyBhIHZhbHVlLCBpbiBpZCBvcmRlci4gQVxuLy8gdmFsdWUgaGFzIG5vIG1lbWJlciBvZiBzb21lIG9mIHRoZW0sIGFuZCB0aGUgc2VydmVyIHRoZW4gYXBwbGllcyBub25lIG9mXG4vLyB0aGVtIHRvIGl0LCBhcyBpdCBkb2VzIGZvciBzdWNoIGEgdGlsZS4gYGxheWVySWRgIGlzIHRoZSBwYWdlIHRoZSB2YWx1ZXNcbi8vIHNpdCBvbjsgdGhlIGhlYWRlciBhbmQgZm9vdGVyJ3MgdmFsdWVzIChhbnkgb3RoZXIgaWQpIGFyZSB2YWx1ZXMgb2YgdGhlXG4vLyBwYWdlIG9uIHNjcmVlbiwgYXMgYSBoZWFkZXIgb3IgZm9vdGVyIHRpbGUgaXMuXG5leHBvcnQgZnVuY3Rpb24gdmFsdWVzTWF0Y2hBbnlHcm91cElkcyhcbiAgcmVwb3J0OiBSZXBvcnQgfCBudWxsLFxuICBsYXllcklkOiBudW1iZXIgfCBudWxsLFxuICBzbmFwc2hvdDogUmVwb3J0Vmlld0NvbmZpZyxcbik6IG51bWJlcltdIHtcbiAgaWYgKCFyZXBvcnQpIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCBwYWdlID0gKHJlcG9ydC5wYWdlcyA/PyBbXSkuZmluZCgoY2FuZGlkYXRlKSA9PiBjYW5kaWRhdGUuaWQgPT09IGxheWVySWQpO1xuXG4gIHJldHVybiBtYXRjaEFueUdyb3VwSWRzT25QYWdlKHJlcG9ydCwgcGFnZT8uaWQgPz8gc25hcHNob3QucGFnZUlkID8/IG51bGwsIHNuYXBzaG90KTtcbn1cblxuXG4vLyBXaGlsZSB0aGUgc25hcHNob3QncyBtYXRjaCBpcyAnYW55JzogdGhlIGVsaWdpYmxlIGdyb3VwcyBvZiB0aGUgcmVwb3J0IGJhclxuLy8gb24gYHBhZ2VJZGAgdGhhdCBob2xkIGEgdmFsdWUsIGluIGlkIG9yZGVyLlxuZnVuY3Rpb24gbWF0Y2hBbnlHcm91cElkc09uUGFnZShyZXBvcnQ6IFJlcG9ydCwgcGFnZUlkOiBudW1iZXIgfCBudWxsLCBzbmFwc2hvdDogUmVwb3J0Vmlld0NvbmZpZyk6IG51bWJlcltdIHtcbiAgaWYgKHNuYXBzaG90Lm1hdGNoICE9PSAnYW55Jykge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIHJldHVybiAocmVwb3J0LmZpbHRlckdyb3VwcyA/PyBbXSlcbiAgICAuZmlsdGVyKChncm91cCkgPT4gaXNNYXRjaEFueUdyb3VwKGdyb3VwLCBwYWdlSWQpICYmIGhvbGRzVmFsdWUoc25hcHNob3QuZ3JvdXBzPy5bZ3JvdXAuaWRdKSlcbiAgICAubWFwKChncm91cCkgPT4gZ3JvdXAuaWQpXG4gICAgLnNvcnQoKGEsIGIpID0+IGEgLSBiKTtcbn1cblxuXG4vLyBUaGUgcGFnZSBhIHRpbGUgaXMgZHJhd24gb246IGl0cyBvd24gcGFnZSwgb3IsIGZvciBhIGhlYWRlciBvciBmb290ZXJcbi8vIHRpbGUsIHRoZSBwYWdlIG9uIHNjcmVlbi4gTnVsbCB3aGVuIG5laXRoZXIgaXMga25vd24uIEFuIGlubGluZSB2YWx1ZSdzXG4vLyBwYWdlIGlzIHRoZSBwYWdlIHdob3NlIHZhbHVlcyBob2xkIGl0LCB0aGUgc2FtZSB3YXkuXG5leHBvcnQgZnVuY3Rpb24gdGlsZVBhZ2VJZChyZXBvcnQ6IFJlcG9ydCwgY29tcG9uZW50OiBSZXBvcnRDb21wb25lbnQsIHNuYXBzaG90OiBSZXBvcnRWaWV3Q29uZmlnKTogbnVtYmVyIHwgbnVsbCB7XG4gIGNvbnN0IHBhZ2UgPSAocmVwb3J0LnBhZ2VzID8/IFtdKVxuICAgIC5maW5kKChjYW5kaWRhdGUpID0+IFsuLi4oY2FuZGlkYXRlLmNvbXBvbmVudHMgPz8gW10pLCAuLi4oY2FuZGlkYXRlLnZhbHVlcyA/PyBbXSldXG4gICAgICAuc29tZSgoaXRlbSkgPT4gaXRlbS5pZCA9PT0gY29tcG9uZW50LmlkKSk7XG5cbiAgcmV0dXJuIHBhZ2U/LmlkID8/IHNuYXBzaG90LnBhZ2VJZCA/PyBudWxsO1xufVxuXG5cbi8vIFdoZXRoZXIgYSBncm91cCdzIHN0b3JlZCB2YWx1ZSBob2xkcyBzb21ldGhpbmcgYSByZXF1ZXN0IHNlbmRzOiBwaWNrcyB0b1xuLy8ga2VlcCBvciBsZWF2ZSBvdXQsIHRleHQsIG9yIGEgbnVtYmVyIHJhbmdlIGVuZCAoMCBpcyBhbiBlbmQpLlxuZnVuY3Rpb24gaG9sZHNWYWx1ZSh2YWx1ZTogRmlsdGVyR3JvdXBEZWZhdWx0IHwgbnVsbCB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICBpZiAoIXZhbHVlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuICEhdmFsdWUudmFsdWVzPy5sZW5ndGhcbiAgICB8fCAhIXZhbHVlLmV4Y2x1ZGVWYWx1ZXM/Lmxlbmd0aFxuICAgIHx8ICh0eXBlb2YgdmFsdWUudmFsdWUgPT09ICdzdHJpbmcnICYmICEhdmFsdWUudmFsdWUudHJpbSgpKVxuICAgIHx8IE51bWJlci5pc0Zpbml0ZSh2YWx1ZS5taW4pXG4gICAgfHwgTnVtYmVyLmlzRmluaXRlKHZhbHVlLm1heCk7XG59XG4iXX0=