@angular/cdk 19.0.0-next.0 → 19.0.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/a11y/index.d.ts +5 -1
- package/drag-drop/index.d.ts +1 -4
- package/fesm2022/a11y.mjs +21 -11
- package/fesm2022/a11y.mjs.map +1 -1
- package/fesm2022/cdk.mjs +1 -1
- package/fesm2022/cdk.mjs.map +1 -1
- package/fesm2022/drag-drop.mjs +17 -26
- package/fesm2022/drag-drop.mjs.map +1 -1
- package/fesm2022/overlay.mjs +20 -1
- package/fesm2022/overlay.mjs.map +1 -1
- package/fesm2022/platform.mjs +5 -8
- package/fesm2022/platform.mjs.map +1 -1
- package/fesm2022/private.mjs +52 -0
- package/fesm2022/private.mjs.map +1 -0
- package/fesm2022/testing/testbed.mjs +3 -2
- package/fesm2022/testing/testbed.mjs.map +1 -1
- package/fesm2022/text-field.mjs +17 -2
- package/fesm2022/text-field.mjs.map +1 -1
- package/fesm2022/tree.mjs +13 -7
- package/fesm2022/tree.mjs.map +1 -1
- package/overlay/_index.scss +15 -13
- package/overlay/index.d.ts +5 -0
- package/overlay-prebuilt.css +1 -1
- package/package.json +5 -55
- package/platform/index.d.ts +2 -1
- package/private/index.d.ts +21 -0
- package/schematics/ng-add/index.js +1 -1
- package/schematics/ng-add/index.mjs +1 -1
- package/text-field/index.d.ts +1 -0
- package/tree/index.d.ts +3 -1
- package/esm2022/a11y/a11y-module.mjs +0 -31
- package/esm2022/a11y/a11y_public_index.mjs +0 -5
- package/esm2022/a11y/aria-describer/aria-describer.mjs +0 -232
- package/esm2022/a11y/aria-describer/aria-reference.mjs +0 -47
- package/esm2022/a11y/fake-event-detection.mjs +0 -29
- package/esm2022/a11y/focus-monitor/focus-monitor.mjs +0 -468
- package/esm2022/a11y/focus-trap/configurable-focus-trap-config.mjs +0 -9
- package/esm2022/a11y/focus-trap/configurable-focus-trap-factory.mjs +0 -54
- package/esm2022/a11y/focus-trap/configurable-focus-trap.mjs +0 -51
- package/esm2022/a11y/focus-trap/event-listener-inert-strategy.mjs +0 -61
- package/esm2022/a11y/focus-trap/focus-trap-inert-strategy.mjs +0 -11
- package/esm2022/a11y/focus-trap/focus-trap-manager.mjs +0 -53
- package/esm2022/a11y/focus-trap/focus-trap.mjs +0 -396
- package/esm2022/a11y/high-contrast-mode/high-contrast-mode-detector.mjs +0 -116
- package/esm2022/a11y/index.mjs +0 -9
- package/esm2022/a11y/input-modality/input-modality-detector.mjs +0 -176
- package/esm2022/a11y/interactivity-checker/interactivity-checker.mjs +0 -238
- package/esm2022/a11y/key-manager/activedescendant-key-manager.mjs +0 -20
- package/esm2022/a11y/key-manager/focus-key-manager.mjs +0 -29
- package/esm2022/a11y/key-manager/list-key-manager.mjs +0 -357
- package/esm2022/a11y/key-manager/noop-tree-key-manager.mjs +0 -94
- package/esm2022/a11y/key-manager/tree-key-manager-strategy.mjs +0 -9
- package/esm2022/a11y/key-manager/tree-key-manager.mjs +0 -345
- package/esm2022/a11y/key-manager/typeahead.mjs +0 -91
- package/esm2022/a11y/live-announcer/live-announcer-tokens.mjs +0 -19
- package/esm2022/a11y/live-announcer/live-announcer.mjs +0 -210
- package/esm2022/a11y/public-api.mjs +0 -30
- package/esm2022/accordion/accordion-item.mjs +0 -162
- package/esm2022/accordion/accordion-module.mjs +0 -24
- package/esm2022/accordion/accordion.mjs +0 -65
- package/esm2022/accordion/accordion_public_index.mjs +0 -5
- package/esm2022/accordion/index.mjs +0 -9
- package/esm2022/accordion/public-api.mjs +0 -11
- package/esm2022/bidi/bidi-module.mjs +0 -23
- package/esm2022/bidi/bidi_public_index.mjs +0 -5
- package/esm2022/bidi/dir-document-token.mjs +0 -33
- package/esm2022/bidi/dir.mjs +0 -70
- package/esm2022/bidi/directionality.mjs +0 -52
- package/esm2022/bidi/index.mjs +0 -9
- package/esm2022/bidi/public-api.mjs +0 -12
- package/esm2022/clipboard/clipboard-module.mjs +0 -23
- package/esm2022/clipboard/clipboard.mjs +0 -53
- package/esm2022/clipboard/clipboard_public_index.mjs +0 -5
- package/esm2022/clipboard/copy-to-clipboard.mjs +0 -100
- package/esm2022/clipboard/index.mjs +0 -9
- package/esm2022/clipboard/pending-copy.mjs +0 -71
- package/esm2022/clipboard/public-api.mjs +0 -12
- package/esm2022/coercion/array.mjs +0 -11
- package/esm2022/coercion/boolean-property.mjs +0 -12
- package/esm2022/coercion/css-pixel-value.mjs +0 -15
- package/esm2022/coercion/element.mjs +0 -16
- package/esm2022/coercion/index.mjs +0 -9
- package/esm2022/coercion/number-property.mjs +0 -24
- package/esm2022/coercion/private/index.mjs +0 -9
- package/esm2022/coercion/private/observable.mjs +0 -19
- package/esm2022/coercion/private/private_public_index.mjs +0 -5
- package/esm2022/coercion/public-api.mjs +0 -14
- package/esm2022/coercion/string-array.mjs +0 -38
- package/esm2022/collections/array-data-source.mjs +0 -21
- package/esm2022/collections/collection-viewer.mjs +0 -9
- package/esm2022/collections/collections_public_index.mjs +0 -5
- package/esm2022/collections/data-source.mjs +0 -19
- package/esm2022/collections/dispose-view-repeater-strategy.mjs +0 -48
- package/esm2022/collections/index.mjs +0 -9
- package/esm2022/collections/public-api.mjs +0 -17
- package/esm2022/collections/recycle-view-repeater-strategy.mjs +0 -129
- package/esm2022/collections/selection-model.mjs +0 -225
- package/esm2022/collections/tree-adapter.mjs +0 -9
- package/esm2022/collections/unique-selection-dispatcher.mjs +0 -55
- package/esm2022/collections/view-repeater.mjs +0 -26
- package/esm2022/dialog/dialog-config.mjs +0 -70
- package/esm2022/dialog/dialog-container.mjs +0 -308
- package/esm2022/dialog/dialog-injectors.mjs +0 -40
- package/esm2022/dialog/dialog-module.mjs +0 -40
- package/esm2022/dialog/dialog-ref.mjs +0 -85
- package/esm2022/dialog/dialog.mjs +0 -303
- package/esm2022/dialog/dialog_public_index.mjs +0 -5
- package/esm2022/dialog/index.mjs +0 -9
- package/esm2022/dialog/public-api.mjs +0 -14
- package/esm2022/drag-drop/directives/assertions.mjs +0 -18
- package/esm2022/drag-drop/directives/config.mjs +0 -14
- package/esm2022/drag-drop/directives/drag-handle.mjs +0 -68
- package/esm2022/drag-drop/directives/drag-placeholder.mjs +0 -43
- package/esm2022/drag-drop/directives/drag-preview.mjs +0 -48
- package/esm2022/drag-drop/directives/drag.mjs +0 -520
- package/esm2022/drag-drop/directives/drop-list-group.mjs +0 -47
- package/esm2022/drag-drop/directives/drop-list.mjs +0 -352
- package/esm2022/drag-drop/dom/clone-node.mjs +0 -65
- package/esm2022/drag-drop/dom/dom-rect.mjs +0 -64
- package/esm2022/drag-drop/dom/parent-position-tracker.mjs +0 -76
- package/esm2022/drag-drop/dom/root-node.mjs +0 -21
- package/esm2022/drag-drop/dom/styling.mjs +0 -89
- package/esm2022/drag-drop/dom/transition-duration.mjs +0 -36
- package/esm2022/drag-drop/drag-drop-module.mjs +0 -49
- package/esm2022/drag-drop/drag-drop-registry.mjs +0 -266
- package/esm2022/drag-drop/drag-drop.mjs +0 -57
- package/esm2022/drag-drop/drag-drop_public_index.mjs +0 -5
- package/esm2022/drag-drop/drag-events.mjs +0 -9
- package/esm2022/drag-drop/drag-parent.mjs +0 -16
- package/esm2022/drag-drop/drag-ref.mjs +0 -1097
- package/esm2022/drag-drop/drag-utils.mjs +0 -60
- package/esm2022/drag-drop/drop-list-ref.mjs +0 -672
- package/esm2022/drag-drop/index.mjs +0 -9
- package/esm2022/drag-drop/preview-ref.mjs +0 -117
- package/esm2022/drag-drop/public-api.mjs +0 -23
- package/esm2022/drag-drop/sorting/drop-list-sort-strategy.mjs +0 -9
- package/esm2022/drag-drop/sorting/mixed-sort-strategy.mjs +0 -246
- package/esm2022/drag-drop/sorting/single-axis-sort-strategy.mjs +0 -343
- package/esm2022/index.mjs +0 -9
- package/esm2022/keycodes/index.mjs +0 -9
- package/esm2022/keycodes/keycodes.mjs +0 -127
- package/esm2022/keycodes/keycodes_public_index.mjs +0 -5
- package/esm2022/keycodes/modifiers.mjs +0 -18
- package/esm2022/keycodes/public-api.mjs +0 -10
- package/esm2022/layout/breakpoints-observer.mjs +0 -105
- package/esm2022/layout/breakpoints.mjs +0 -29
- package/esm2022/layout/index.mjs +0 -9
- package/esm2022/layout/layout-module.mjs +0 -19
- package/esm2022/layout/layout_public_index.mjs +0 -5
- package/esm2022/layout/media-matcher.mjs +0 -94
- package/esm2022/layout/public-api.mjs +0 -12
- package/esm2022/listbox/index.mjs +0 -9
- package/esm2022/listbox/listbox-module.mjs +0 -24
- package/esm2022/listbox/listbox.mjs +0 -888
- package/esm2022/listbox/listbox_public_index.mjs +0 -5
- package/esm2022/listbox/public-api.mjs +0 -10
- package/esm2022/menu/context-menu-trigger.mjs +0 -221
- package/esm2022/menu/event-detection.mjs +0 -28
- package/esm2022/menu/index.mjs +0 -9
- package/esm2022/menu/menu-aim.mjs +0 -204
- package/esm2022/menu/menu-bar.mjs +0 -134
- package/esm2022/menu/menu-base.mjs +0 -192
- package/esm2022/menu/menu-errors.mjs +0 -22
- package/esm2022/menu/menu-group.mjs +0 -31
- package/esm2022/menu/menu-interface.mjs +0 -11
- package/esm2022/menu/menu-item-checkbox.mjs +0 -50
- package/esm2022/menu/menu-item-radio.mjs +0 -72
- package/esm2022/menu/menu-item-selectable.mjs +0 -36
- package/esm2022/menu/menu-item.mjs +0 -270
- package/esm2022/menu/menu-module.mjs +0 -60
- package/esm2022/menu/menu-stack.mjs +0 -163
- package/esm2022/menu/menu-trigger-base.mjs +0 -119
- package/esm2022/menu/menu-trigger.mjs +0 -313
- package/esm2022/menu/menu.mjs +0 -135
- package/esm2022/menu/menu_public_index.mjs +0 -5
- package/esm2022/menu/pointer-focus-tracker.mjs +0 -51
- package/esm2022/menu/public-api.mjs +0 -24
- package/esm2022/observers/index.mjs +0 -9
- package/esm2022/observers/observe-content.mjs +0 -216
- package/esm2022/observers/observers_public_index.mjs +0 -5
- package/esm2022/observers/private/index.mjs +0 -9
- package/esm2022/observers/private/private_public_index.mjs +0 -5
- package/esm2022/observers/private/shared-resize-observer.mjs +0 -125
- package/esm2022/observers/public-api.mjs +0 -9
- package/esm2022/overlay/dispatchers/base-overlay-dispatcher.mjs +0 -52
- package/esm2022/overlay/dispatchers/index.mjs +0 -10
- package/esm2022/overlay/dispatchers/overlay-keyboard-dispatcher.mjs +0 -81
- package/esm2022/overlay/dispatchers/overlay-outside-click-dispatcher.mjs +0 -151
- package/esm2022/overlay/fullscreen-overlay-container.mjs +0 -94
- package/esm2022/overlay/index.mjs +0 -9
- package/esm2022/overlay/overlay-config.mjs +0 -45
- package/esm2022/overlay/overlay-container.mjs +0 -81
- package/esm2022/overlay/overlay-directives.mjs +0 -432
- package/esm2022/overlay/overlay-module.mjs +0 -28
- package/esm2022/overlay/overlay-ref.mjs +0 -437
- package/esm2022/overlay/overlay.mjs +0 -126
- package/esm2022/overlay/overlay_public_index.mjs +0 -5
- package/esm2022/overlay/position/connected-position.mjs +0 -88
- package/esm2022/overlay/position/flexible-connected-position-strategy.mjs +0 -1002
- package/esm2022/overlay/position/global-position-strategy.mjs +0 -237
- package/esm2022/overlay/position/overlay-position-builder.mjs +0 -50
- package/esm2022/overlay/position/position-strategy.mjs +0 -9
- package/esm2022/overlay/position/scroll-clip.mjs +0 -40
- package/esm2022/overlay/public-api.mjs +0 -22
- package/esm2022/overlay/scroll/block-scroll-strategy.mjs +0 -80
- package/esm2022/overlay/scroll/close-scroll-strategy.mjs +0 -65
- package/esm2022/overlay/scroll/index.mjs +0 -14
- package/esm2022/overlay/scroll/noop-scroll-strategy.mjs +0 -17
- package/esm2022/overlay/scroll/reposition-scroll-strategy.mjs +0 -61
- package/esm2022/overlay/scroll/scroll-strategy-options.mjs +0 -55
- package/esm2022/overlay/scroll/scroll-strategy.mjs +0 -14
- package/esm2022/platform/features/input-types.mjs +0 -59
- package/esm2022/platform/features/passive-listeners.mjs +0 -36
- package/esm2022/platform/features/scrolling.mjs +0 -104
- package/esm2022/platform/features/shadow-dom.mjs +0 -54
- package/esm2022/platform/features/test-environment.mjs +0 -24
- package/esm2022/platform/index.mjs +0 -9
- package/esm2022/platform/platform-module.mjs +0 -19
- package/esm2022/platform/platform.mjs +0 -85
- package/esm2022/platform/platform_public_index.mjs +0 -5
- package/esm2022/platform/public-api.mjs +0 -15
- package/esm2022/portal/dom-portal-outlet.mjs +0 -158
- package/esm2022/portal/index.mjs +0 -9
- package/esm2022/portal/portal-directives.mjs +0 -251
- package/esm2022/portal/portal-errors.mjs +0 -51
- package/esm2022/portal/portal-injector.mjs +0 -28
- package/esm2022/portal/portal.mjs +0 -189
- package/esm2022/portal/portal_public_index.mjs +0 -5
- package/esm2022/portal/public-api.mjs +0 -12
- package/esm2022/public-api.mjs +0 -9
- package/esm2022/scrolling/fixed-size-virtual-scroll.mjs +0 -218
- package/esm2022/scrolling/index.mjs +0 -9
- package/esm2022/scrolling/public-api.mjs +0 -20
- package/esm2022/scrolling/scroll-dispatcher.mjs +0 -163
- package/esm2022/scrolling/scrollable.mjs +0 -177
- package/esm2022/scrolling/scrolling-module.mjs +0 -69
- package/esm2022/scrolling/scrolling_public_index.mjs +0 -5
- package/esm2022/scrolling/viewport-ruler.mjs +0 -146
- package/esm2022/scrolling/virtual-for-of.mjs +0 -299
- package/esm2022/scrolling/virtual-scroll-repeater.mjs +0 -9
- package/esm2022/scrolling/virtual-scroll-strategy.mjs +0 -11
- package/esm2022/scrolling/virtual-scroll-viewport.mjs +0 -445
- package/esm2022/scrolling/virtual-scrollable-element.mjs +0 -42
- package/esm2022/scrolling/virtual-scrollable-window.mjs +0 -41
- package/esm2022/scrolling/virtual-scrollable.mjs +0 -40
- package/esm2022/stepper/index.mjs +0 -9
- package/esm2022/stepper/public-api.mjs +0 -13
- package/esm2022/stepper/step-header.mjs +0 -31
- package/esm2022/stepper/step-label.mjs +0 -24
- package/esm2022/stepper/stepper-button.mjs +0 -58
- package/esm2022/stepper/stepper-module.mjs +0 -41
- package/esm2022/stepper/stepper.mjs +0 -452
- package/esm2022/stepper/stepper_public_index.mjs +0 -5
- package/esm2022/table/can-stick.mjs +0 -46
- package/esm2022/table/cell.mjs +0 -245
- package/esm2022/table/coalesced-style-scheduler.mjs +0 -79
- package/esm2022/table/index.mjs +0 -9
- package/esm2022/table/public-api.mjs +0 -20
- package/esm2022/table/row.mjs +0 -317
- package/esm2022/table/sticky-position-listener.mjs +0 -11
- package/esm2022/table/sticky-styler.mjs +0 -347
- package/esm2022/table/table-errors.mjs +0 -67
- package/esm2022/table/table-module.mjs +0 -93
- package/esm2022/table/table.mjs +0 -1148
- package/esm2022/table/table_public_index.mjs +0 -5
- package/esm2022/table/text-column.mjs +0 -154
- package/esm2022/table/tokens.mjs +0 -16
- package/esm2022/testing/change-detection.mjs +0 -102
- package/esm2022/testing/component-harness.mjs +0 -328
- package/esm2022/testing/element-dimensions.mjs +0 -9
- package/esm2022/testing/harness-environment.mjs +0 -220
- package/esm2022/testing/index.mjs +0 -9
- package/esm2022/testing/public-api.mjs +0 -15
- package/esm2022/testing/selenium-webdriver/index.mjs +0 -9
- package/esm2022/testing/selenium-webdriver/public-api.mjs +0 -10
- package/esm2022/testing/selenium-webdriver/selenium-web-driver-element.mjs +0 -216
- package/esm2022/testing/selenium-webdriver/selenium-web-driver-harness-environment.mjs +0 -88
- package/esm2022/testing/selenium-webdriver/selenium-webdriver-keys.mjs +0 -64
- package/esm2022/testing/test-element-errors.mjs +0 -15
- package/esm2022/testing/test-element.mjs +0 -49
- package/esm2022/testing/testbed/fake-events/dispatch-events.mjs +0 -53
- package/esm2022/testing/testbed/fake-events/element-focus.mjs +0 -39
- package/esm2022/testing/testbed/fake-events/event-objects.mjs +0 -127
- package/esm2022/testing/testbed/fake-events/index.mjs +0 -14
- package/esm2022/testing/testbed/fake-events/type-in-element.mjs +0 -97
- package/esm2022/testing/testbed/index.mjs +0 -9
- package/esm2022/testing/testbed/public-api.mjs +0 -10
- package/esm2022/testing/testbed/task-state-zone-interceptor.mjs +0 -82
- package/esm2022/testing/testbed/testbed-harness-environment.mjs +0 -165
- package/esm2022/testing/testbed/unit-test-element.mjs +0 -258
- package/esm2022/testing/text-filtering.mjs +0 -21
- package/esm2022/text-field/autofill.mjs +0 -114
- package/esm2022/text-field/autosize.mjs +0 -309
- package/esm2022/text-field/index.mjs +0 -9
- package/esm2022/text-field/public-api.mjs +0 -11
- package/esm2022/text-field/text-field-module.mjs +0 -24
- package/esm2022/text-field/text-field_public_index.mjs +0 -5
- package/esm2022/tree/control/base-tree-control.mjs +0 -62
- package/esm2022/tree/control/flat-tree-control.mjs +0 -57
- package/esm2022/tree/control/nested-tree-control.mjs +0 -67
- package/esm2022/tree/control/tree-control.mjs +0 -2
- package/esm2022/tree/index.mjs +0 -9
- package/esm2022/tree/nested-node.mjs +0 -103
- package/esm2022/tree/node.mjs +0 -36
- package/esm2022/tree/outlet.mjs +0 -40
- package/esm2022/tree/padding.mjs +0 -129
- package/esm2022/tree/public-api.mjs +0 -20
- package/esm2022/tree/toggle.mjs +0 -51
- package/esm2022/tree/tree-errors.mjs +0 -44
- package/esm2022/tree/tree-module.mjs +0 -49
- package/esm2022/tree/tree.mjs +0 -1123
- package/esm2022/tree/tree_public_index.mjs +0 -5
- package/esm2022/version.mjs +0 -11
|
@@ -1,1097 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright Google LLC All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
-
* found in the LICENSE file at https://angular.io/license
|
|
7
|
-
*/
|
|
8
|
-
import { isFakeMousedownFromScreenReader, isFakeTouchstartFromScreenReader } from '@angular/cdk/a11y';
|
|
9
|
-
import { coerceElement } from '@angular/cdk/coercion';
|
|
10
|
-
import { _getEventTarget, _getShadowRoot, normalizePassiveListenerOptions, } from '@angular/cdk/platform';
|
|
11
|
-
import { signal, } from '@angular/core';
|
|
12
|
-
import { Subject, Subscription } from 'rxjs';
|
|
13
|
-
import { deepCloneNode } from './dom/clone-node';
|
|
14
|
-
import { adjustDomRect, getMutableClientRect } from './dom/dom-rect';
|
|
15
|
-
import { ParentPositionTracker } from './dom/parent-position-tracker';
|
|
16
|
-
import { getRootNode } from './dom/root-node';
|
|
17
|
-
import { combineTransforms, getTransform, toggleNativeDragInteractions, toggleVisibility, } from './dom/styling';
|
|
18
|
-
import { PreviewRef } from './preview-ref';
|
|
19
|
-
/** Options that can be used to bind a passive event listener. */
|
|
20
|
-
const passiveEventListenerOptions = normalizePassiveListenerOptions({ passive: true });
|
|
21
|
-
/** Options that can be used to bind an active event listener. */
|
|
22
|
-
const activeEventListenerOptions = normalizePassiveListenerOptions({ passive: false });
|
|
23
|
-
/** Event options that can be used to bind an active, capturing event. */
|
|
24
|
-
const activeCapturingEventOptions = normalizePassiveListenerOptions({
|
|
25
|
-
passive: false,
|
|
26
|
-
capture: true,
|
|
27
|
-
});
|
|
28
|
-
/**
|
|
29
|
-
* Time in milliseconds for which to ignore mouse events, after
|
|
30
|
-
* receiving a touch event. Used to avoid doing double work for
|
|
31
|
-
* touch devices where the browser fires fake mouse events, in
|
|
32
|
-
* addition to touch events.
|
|
33
|
-
*/
|
|
34
|
-
const MOUSE_EVENT_IGNORE_TIME = 800;
|
|
35
|
-
/** Inline styles to be set as `!important` while dragging. */
|
|
36
|
-
const dragImportantProperties = new Set([
|
|
37
|
-
// Needs to be important, because some `mat-table` sets `position: sticky !important`. See #22781.
|
|
38
|
-
'position',
|
|
39
|
-
]);
|
|
40
|
-
/**
|
|
41
|
-
* Reference to a draggable item. Used to manipulate or dispose of the item.
|
|
42
|
-
*/
|
|
43
|
-
export class DragRef {
|
|
44
|
-
/** Whether starting to drag this element is disabled. */
|
|
45
|
-
get disabled() {
|
|
46
|
-
return this._disabled || !!(this._dropContainer && this._dropContainer.disabled);
|
|
47
|
-
}
|
|
48
|
-
set disabled(value) {
|
|
49
|
-
if (value !== this._disabled) {
|
|
50
|
-
this._disabled = value;
|
|
51
|
-
this._toggleNativeDragInteractions();
|
|
52
|
-
this._handles.forEach(handle => toggleNativeDragInteractions(handle, value));
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
constructor(element, _config, _document, _ngZone, _viewportRuler, _dragDropRegistry) {
|
|
56
|
-
this._config = _config;
|
|
57
|
-
this._document = _document;
|
|
58
|
-
this._ngZone = _ngZone;
|
|
59
|
-
this._viewportRuler = _viewportRuler;
|
|
60
|
-
this._dragDropRegistry = _dragDropRegistry;
|
|
61
|
-
/**
|
|
62
|
-
* CSS `transform` applied to the element when it isn't being dragged. We need a
|
|
63
|
-
* passive transform in order for the dragged element to retain its new position
|
|
64
|
-
* after the user has stopped dragging and because we need to know the relative
|
|
65
|
-
* position in case they start dragging again. This corresponds to `element.style.transform`.
|
|
66
|
-
*/
|
|
67
|
-
this._passiveTransform = { x: 0, y: 0 };
|
|
68
|
-
/** CSS `transform` that is applied to the element while it's being dragged. */
|
|
69
|
-
this._activeTransform = { x: 0, y: 0 };
|
|
70
|
-
/**
|
|
71
|
-
* Whether the dragging sequence has been started. Doesn't
|
|
72
|
-
* necessarily mean that the element has been moved.
|
|
73
|
-
*/
|
|
74
|
-
this._hasStartedDragging = signal(false);
|
|
75
|
-
/** Emits when the item is being moved. */
|
|
76
|
-
this._moveEvents = new Subject();
|
|
77
|
-
/** Subscription to pointer movement events. */
|
|
78
|
-
this._pointerMoveSubscription = Subscription.EMPTY;
|
|
79
|
-
/** Subscription to the event that is dispatched when the user lifts their pointer. */
|
|
80
|
-
this._pointerUpSubscription = Subscription.EMPTY;
|
|
81
|
-
/** Subscription to the viewport being scrolled. */
|
|
82
|
-
this._scrollSubscription = Subscription.EMPTY;
|
|
83
|
-
/** Subscription to the viewport being resized. */
|
|
84
|
-
this._resizeSubscription = Subscription.EMPTY;
|
|
85
|
-
/** Cached reference to the boundary element. */
|
|
86
|
-
this._boundaryElement = null;
|
|
87
|
-
/** Whether the native dragging interactions have been enabled on the root element. */
|
|
88
|
-
this._nativeInteractionsEnabled = true;
|
|
89
|
-
/** Elements that can be used to drag the draggable item. */
|
|
90
|
-
this._handles = [];
|
|
91
|
-
/** Registered handles that are currently disabled. */
|
|
92
|
-
this._disabledHandles = new Set();
|
|
93
|
-
/** Layout direction of the item. */
|
|
94
|
-
this._direction = 'ltr';
|
|
95
|
-
/**
|
|
96
|
-
* Amount of milliseconds to wait after the user has put their
|
|
97
|
-
* pointer down before starting to drag the element.
|
|
98
|
-
*/
|
|
99
|
-
this.dragStartDelay = 0;
|
|
100
|
-
/**
|
|
101
|
-
* If the parent of the dragged element has a `scale` transform, it can throw off the
|
|
102
|
-
* positioning when the user starts dragging. Use this input to notify the CDK of the scale.
|
|
103
|
-
*/
|
|
104
|
-
this.scale = 1;
|
|
105
|
-
this._disabled = false;
|
|
106
|
-
/** Emits as the drag sequence is being prepared. */
|
|
107
|
-
this.beforeStarted = new Subject();
|
|
108
|
-
/** Emits when the user starts dragging the item. */
|
|
109
|
-
this.started = new Subject();
|
|
110
|
-
/** Emits when the user has released a drag item, before any animations have started. */
|
|
111
|
-
this.released = new Subject();
|
|
112
|
-
/** Emits when the user stops dragging an item in the container. */
|
|
113
|
-
this.ended = new Subject();
|
|
114
|
-
/** Emits when the user has moved the item into a new container. */
|
|
115
|
-
this.entered = new Subject();
|
|
116
|
-
/** Emits when the user removes the item its container by dragging it into another container. */
|
|
117
|
-
this.exited = new Subject();
|
|
118
|
-
/** Emits when the user drops the item inside a container. */
|
|
119
|
-
this.dropped = new Subject();
|
|
120
|
-
/**
|
|
121
|
-
* Emits as the user is dragging the item. Use with caution,
|
|
122
|
-
* because this event will fire for every pixel that the user has dragged.
|
|
123
|
-
*/
|
|
124
|
-
this.moved = this._moveEvents;
|
|
125
|
-
/** Handler for the `mousedown`/`touchstart` events. */
|
|
126
|
-
this._pointerDown = (event) => {
|
|
127
|
-
this.beforeStarted.next();
|
|
128
|
-
// Delegate the event based on whether it started from a handle or the element itself.
|
|
129
|
-
if (this._handles.length) {
|
|
130
|
-
const targetHandle = this._getTargetHandle(event);
|
|
131
|
-
if (targetHandle && !this._disabledHandles.has(targetHandle) && !this.disabled) {
|
|
132
|
-
this._initializeDragSequence(targetHandle, event);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
else if (!this.disabled) {
|
|
136
|
-
this._initializeDragSequence(this._rootElement, event);
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
/** Handler that is invoked when the user moves their pointer after they've initiated a drag. */
|
|
140
|
-
this._pointerMove = (event) => {
|
|
141
|
-
const pointerPosition = this._getPointerPositionOnPage(event);
|
|
142
|
-
if (!this._hasStartedDragging()) {
|
|
143
|
-
const distanceX = Math.abs(pointerPosition.x - this._pickupPositionOnPage.x);
|
|
144
|
-
const distanceY = Math.abs(pointerPosition.y - this._pickupPositionOnPage.y);
|
|
145
|
-
const isOverThreshold = distanceX + distanceY >= this._config.dragStartThreshold;
|
|
146
|
-
// Only start dragging after the user has moved more than the minimum distance in either
|
|
147
|
-
// direction. Note that this is preferable over doing something like `skip(minimumDistance)`
|
|
148
|
-
// in the `pointerMove` subscription, because we're not guaranteed to have one move event
|
|
149
|
-
// per pixel of movement (e.g. if the user moves their pointer quickly).
|
|
150
|
-
if (isOverThreshold) {
|
|
151
|
-
const isDelayElapsed = Date.now() >= this._dragStartTime + this._getDragStartDelay(event);
|
|
152
|
-
const container = this._dropContainer;
|
|
153
|
-
if (!isDelayElapsed) {
|
|
154
|
-
this._endDragSequence(event);
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
// Prevent other drag sequences from starting while something in the container is still
|
|
158
|
-
// being dragged. This can happen while we're waiting for the drop animation to finish
|
|
159
|
-
// and can cause errors, because some elements might still be moving around.
|
|
160
|
-
if (!container || (!container.isDragging() && !container.isReceiving())) {
|
|
161
|
-
// Prevent the default action as soon as the dragging sequence is considered as
|
|
162
|
-
// "started" since waiting for the next event can allow the device to begin scrolling.
|
|
163
|
-
if (event.cancelable) {
|
|
164
|
-
event.preventDefault();
|
|
165
|
-
}
|
|
166
|
-
this._hasStartedDragging.set(true);
|
|
167
|
-
this._ngZone.run(() => this._startDragSequence(event));
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
// We prevent the default action down here so that we know that dragging has started. This is
|
|
173
|
-
// important for touch devices where doing this too early can unnecessarily block scrolling,
|
|
174
|
-
// if there's a dragging delay.
|
|
175
|
-
if (event.cancelable) {
|
|
176
|
-
event.preventDefault();
|
|
177
|
-
}
|
|
178
|
-
const constrainedPointerPosition = this._getConstrainedPointerPosition(pointerPosition);
|
|
179
|
-
this._hasMoved = true;
|
|
180
|
-
this._lastKnownPointerPosition = pointerPosition;
|
|
181
|
-
this._updatePointerDirectionDelta(constrainedPointerPosition);
|
|
182
|
-
if (this._dropContainer) {
|
|
183
|
-
this._updateActiveDropContainer(constrainedPointerPosition, pointerPosition);
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
// If there's a position constraint function, we want the element's top/left to be at the
|
|
187
|
-
// specific position on the page. Use the initial position as a reference if that's the case.
|
|
188
|
-
const offset = this.constrainPosition ? this._initialDomRect : this._pickupPositionOnPage;
|
|
189
|
-
const activeTransform = this._activeTransform;
|
|
190
|
-
activeTransform.x = constrainedPointerPosition.x - offset.x + this._passiveTransform.x;
|
|
191
|
-
activeTransform.y = constrainedPointerPosition.y - offset.y + this._passiveTransform.y;
|
|
192
|
-
this._applyRootElementTransform(activeTransform.x, activeTransform.y);
|
|
193
|
-
}
|
|
194
|
-
// Since this event gets fired for every pixel while dragging, we only
|
|
195
|
-
// want to fire it if the consumer opted into it. Also we have to
|
|
196
|
-
// re-enter the zone because we run all of the events on the outside.
|
|
197
|
-
if (this._moveEvents.observers.length) {
|
|
198
|
-
this._ngZone.run(() => {
|
|
199
|
-
this._moveEvents.next({
|
|
200
|
-
source: this,
|
|
201
|
-
pointerPosition: constrainedPointerPosition,
|
|
202
|
-
event,
|
|
203
|
-
distance: this._getDragDistance(constrainedPointerPosition),
|
|
204
|
-
delta: this._pointerDirectionDelta,
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
/** Handler that is invoked when the user lifts their pointer up, after initiating a drag. */
|
|
210
|
-
this._pointerUp = (event) => {
|
|
211
|
-
this._endDragSequence(event);
|
|
212
|
-
};
|
|
213
|
-
/** Handles a native `dragstart` event. */
|
|
214
|
-
this._nativeDragStart = (event) => {
|
|
215
|
-
if (this._handles.length) {
|
|
216
|
-
const targetHandle = this._getTargetHandle(event);
|
|
217
|
-
if (targetHandle && !this._disabledHandles.has(targetHandle) && !this.disabled) {
|
|
218
|
-
event.preventDefault();
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
else if (!this.disabled) {
|
|
222
|
-
// Usually this isn't necessary since the we prevent the default action in `pointerDown`,
|
|
223
|
-
// but some cases like dragging of links can slip through (see #24403).
|
|
224
|
-
event.preventDefault();
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
this.withRootElement(element).withParent(_config.parentDragRef || null);
|
|
228
|
-
this._parentPositions = new ParentPositionTracker(_document);
|
|
229
|
-
_dragDropRegistry.registerDragItem(this);
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
* Returns the element that is being used as a placeholder
|
|
233
|
-
* while the current element is being dragged.
|
|
234
|
-
*/
|
|
235
|
-
getPlaceholderElement() {
|
|
236
|
-
return this._placeholder;
|
|
237
|
-
}
|
|
238
|
-
/** Returns the root draggable element. */
|
|
239
|
-
getRootElement() {
|
|
240
|
-
return this._rootElement;
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Gets the currently-visible element that represents the drag item.
|
|
244
|
-
* While dragging this is the placeholder, otherwise it's the root element.
|
|
245
|
-
*/
|
|
246
|
-
getVisibleElement() {
|
|
247
|
-
return this.isDragging() ? this.getPlaceholderElement() : this.getRootElement();
|
|
248
|
-
}
|
|
249
|
-
/** Registers the handles that can be used to drag the element. */
|
|
250
|
-
withHandles(handles) {
|
|
251
|
-
this._handles = handles.map(handle => coerceElement(handle));
|
|
252
|
-
this._handles.forEach(handle => toggleNativeDragInteractions(handle, this.disabled));
|
|
253
|
-
this._toggleNativeDragInteractions();
|
|
254
|
-
// Delete any lingering disabled handles that may have been destroyed. Note that we re-create
|
|
255
|
-
// the set, rather than iterate over it and filter out the destroyed handles, because while
|
|
256
|
-
// the ES spec allows for sets to be modified while they're being iterated over, some polyfills
|
|
257
|
-
// use an array internally which may throw an error.
|
|
258
|
-
const disabledHandles = new Set();
|
|
259
|
-
this._disabledHandles.forEach(handle => {
|
|
260
|
-
if (this._handles.indexOf(handle) > -1) {
|
|
261
|
-
disabledHandles.add(handle);
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
this._disabledHandles = disabledHandles;
|
|
265
|
-
return this;
|
|
266
|
-
}
|
|
267
|
-
/**
|
|
268
|
-
* Registers the template that should be used for the drag preview.
|
|
269
|
-
* @param template Template that from which to stamp out the preview.
|
|
270
|
-
*/
|
|
271
|
-
withPreviewTemplate(template) {
|
|
272
|
-
this._previewTemplate = template;
|
|
273
|
-
return this;
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* Registers the template that should be used for the drag placeholder.
|
|
277
|
-
* @param template Template that from which to stamp out the placeholder.
|
|
278
|
-
*/
|
|
279
|
-
withPlaceholderTemplate(template) {
|
|
280
|
-
this._placeholderTemplate = template;
|
|
281
|
-
return this;
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* Sets an alternate drag root element. The root element is the element that will be moved as
|
|
285
|
-
* the user is dragging. Passing an alternate root element is useful when trying to enable
|
|
286
|
-
* dragging on an element that you might not have access to.
|
|
287
|
-
*/
|
|
288
|
-
withRootElement(rootElement) {
|
|
289
|
-
const element = coerceElement(rootElement);
|
|
290
|
-
if (element !== this._rootElement) {
|
|
291
|
-
if (this._rootElement) {
|
|
292
|
-
this._removeRootElementListeners(this._rootElement);
|
|
293
|
-
}
|
|
294
|
-
this._ngZone.runOutsideAngular(() => {
|
|
295
|
-
element.addEventListener('mousedown', this._pointerDown, activeEventListenerOptions);
|
|
296
|
-
element.addEventListener('touchstart', this._pointerDown, passiveEventListenerOptions);
|
|
297
|
-
element.addEventListener('dragstart', this._nativeDragStart, activeEventListenerOptions);
|
|
298
|
-
});
|
|
299
|
-
this._initialTransform = undefined;
|
|
300
|
-
this._rootElement = element;
|
|
301
|
-
}
|
|
302
|
-
if (typeof SVGElement !== 'undefined' && this._rootElement instanceof SVGElement) {
|
|
303
|
-
this._ownerSVGElement = this._rootElement.ownerSVGElement;
|
|
304
|
-
}
|
|
305
|
-
return this;
|
|
306
|
-
}
|
|
307
|
-
/**
|
|
308
|
-
* Element to which the draggable's position will be constrained.
|
|
309
|
-
*/
|
|
310
|
-
withBoundaryElement(boundaryElement) {
|
|
311
|
-
this._boundaryElement = boundaryElement ? coerceElement(boundaryElement) : null;
|
|
312
|
-
this._resizeSubscription.unsubscribe();
|
|
313
|
-
if (boundaryElement) {
|
|
314
|
-
this._resizeSubscription = this._viewportRuler
|
|
315
|
-
.change(10)
|
|
316
|
-
.subscribe(() => this._containInsideBoundaryOnResize());
|
|
317
|
-
}
|
|
318
|
-
return this;
|
|
319
|
-
}
|
|
320
|
-
/** Sets the parent ref that the ref is nested in. */
|
|
321
|
-
withParent(parent) {
|
|
322
|
-
this._parentDragRef = parent;
|
|
323
|
-
return this;
|
|
324
|
-
}
|
|
325
|
-
/** Removes the dragging functionality from the DOM element. */
|
|
326
|
-
dispose() {
|
|
327
|
-
this._removeRootElementListeners(this._rootElement);
|
|
328
|
-
// Do this check before removing from the registry since it'll
|
|
329
|
-
// stop being considered as dragged once it is removed.
|
|
330
|
-
if (this.isDragging()) {
|
|
331
|
-
// Since we move out the element to the end of the body while it's being
|
|
332
|
-
// dragged, we have to make sure that it's removed if it gets destroyed.
|
|
333
|
-
this._rootElement?.remove();
|
|
334
|
-
}
|
|
335
|
-
this._anchor?.remove();
|
|
336
|
-
this._destroyPreview();
|
|
337
|
-
this._destroyPlaceholder();
|
|
338
|
-
this._dragDropRegistry.removeDragItem(this);
|
|
339
|
-
this._removeListeners();
|
|
340
|
-
this.beforeStarted.complete();
|
|
341
|
-
this.started.complete();
|
|
342
|
-
this.released.complete();
|
|
343
|
-
this.ended.complete();
|
|
344
|
-
this.entered.complete();
|
|
345
|
-
this.exited.complete();
|
|
346
|
-
this.dropped.complete();
|
|
347
|
-
this._moveEvents.complete();
|
|
348
|
-
this._handles = [];
|
|
349
|
-
this._disabledHandles.clear();
|
|
350
|
-
this._dropContainer = undefined;
|
|
351
|
-
this._resizeSubscription.unsubscribe();
|
|
352
|
-
this._parentPositions.clear();
|
|
353
|
-
this._boundaryElement =
|
|
354
|
-
this._rootElement =
|
|
355
|
-
this._ownerSVGElement =
|
|
356
|
-
this._placeholderTemplate =
|
|
357
|
-
this._previewTemplate =
|
|
358
|
-
this._anchor =
|
|
359
|
-
this._parentDragRef =
|
|
360
|
-
null;
|
|
361
|
-
}
|
|
362
|
-
/** Checks whether the element is currently being dragged. */
|
|
363
|
-
isDragging() {
|
|
364
|
-
return this._hasStartedDragging() && this._dragDropRegistry.isDragging(this);
|
|
365
|
-
}
|
|
366
|
-
/** Resets a standalone drag item to its initial position. */
|
|
367
|
-
reset() {
|
|
368
|
-
this._rootElement.style.transform = this._initialTransform || '';
|
|
369
|
-
this._activeTransform = { x: 0, y: 0 };
|
|
370
|
-
this._passiveTransform = { x: 0, y: 0 };
|
|
371
|
-
}
|
|
372
|
-
/**
|
|
373
|
-
* Sets a handle as disabled. While a handle is disabled, it'll capture and interrupt dragging.
|
|
374
|
-
* @param handle Handle element that should be disabled.
|
|
375
|
-
*/
|
|
376
|
-
disableHandle(handle) {
|
|
377
|
-
if (!this._disabledHandles.has(handle) && this._handles.indexOf(handle) > -1) {
|
|
378
|
-
this._disabledHandles.add(handle);
|
|
379
|
-
toggleNativeDragInteractions(handle, true);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* Enables a handle, if it has been disabled.
|
|
384
|
-
* @param handle Handle element to be enabled.
|
|
385
|
-
*/
|
|
386
|
-
enableHandle(handle) {
|
|
387
|
-
if (this._disabledHandles.has(handle)) {
|
|
388
|
-
this._disabledHandles.delete(handle);
|
|
389
|
-
toggleNativeDragInteractions(handle, this.disabled);
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
/** Sets the layout direction of the draggable item. */
|
|
393
|
-
withDirection(direction) {
|
|
394
|
-
this._direction = direction;
|
|
395
|
-
return this;
|
|
396
|
-
}
|
|
397
|
-
/** Sets the container that the item is part of. */
|
|
398
|
-
_withDropContainer(container) {
|
|
399
|
-
this._dropContainer = container;
|
|
400
|
-
}
|
|
401
|
-
/**
|
|
402
|
-
* Gets the current position in pixels the draggable outside of a drop container.
|
|
403
|
-
*/
|
|
404
|
-
getFreeDragPosition() {
|
|
405
|
-
const position = this.isDragging() ? this._activeTransform : this._passiveTransform;
|
|
406
|
-
return { x: position.x, y: position.y };
|
|
407
|
-
}
|
|
408
|
-
/**
|
|
409
|
-
* Sets the current position in pixels the draggable outside of a drop container.
|
|
410
|
-
* @param value New position to be set.
|
|
411
|
-
*/
|
|
412
|
-
setFreeDragPosition(value) {
|
|
413
|
-
this._activeTransform = { x: 0, y: 0 };
|
|
414
|
-
this._passiveTransform.x = value.x;
|
|
415
|
-
this._passiveTransform.y = value.y;
|
|
416
|
-
if (!this._dropContainer) {
|
|
417
|
-
this._applyRootElementTransform(value.x, value.y);
|
|
418
|
-
}
|
|
419
|
-
return this;
|
|
420
|
-
}
|
|
421
|
-
/**
|
|
422
|
-
* Sets the container into which to insert the preview element.
|
|
423
|
-
* @param value Container into which to insert the preview.
|
|
424
|
-
*/
|
|
425
|
-
withPreviewContainer(value) {
|
|
426
|
-
this._previewContainer = value;
|
|
427
|
-
return this;
|
|
428
|
-
}
|
|
429
|
-
/** Updates the item's sort order based on the last-known pointer position. */
|
|
430
|
-
_sortFromLastPointerPosition() {
|
|
431
|
-
const position = this._lastKnownPointerPosition;
|
|
432
|
-
if (position && this._dropContainer) {
|
|
433
|
-
this._updateActiveDropContainer(this._getConstrainedPointerPosition(position), position);
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
/** Unsubscribes from the global subscriptions. */
|
|
437
|
-
_removeListeners() {
|
|
438
|
-
this._pointerMoveSubscription.unsubscribe();
|
|
439
|
-
this._pointerUpSubscription.unsubscribe();
|
|
440
|
-
this._scrollSubscription.unsubscribe();
|
|
441
|
-
this._getShadowRoot()?.removeEventListener('selectstart', shadowDomSelectStart, activeCapturingEventOptions);
|
|
442
|
-
}
|
|
443
|
-
/** Destroys the preview element and its ViewRef. */
|
|
444
|
-
_destroyPreview() {
|
|
445
|
-
this._preview?.destroy();
|
|
446
|
-
this._preview = null;
|
|
447
|
-
}
|
|
448
|
-
/** Destroys the placeholder element and its ViewRef. */
|
|
449
|
-
_destroyPlaceholder() {
|
|
450
|
-
this._placeholder?.remove();
|
|
451
|
-
this._placeholderRef?.destroy();
|
|
452
|
-
this._placeholder = this._placeholderRef = null;
|
|
453
|
-
}
|
|
454
|
-
/**
|
|
455
|
-
* Clears subscriptions and stops the dragging sequence.
|
|
456
|
-
* @param event Browser event object that ended the sequence.
|
|
457
|
-
*/
|
|
458
|
-
_endDragSequence(event) {
|
|
459
|
-
// Note that here we use `isDragging` from the service, rather than from `this`.
|
|
460
|
-
// The difference is that the one from the service reflects whether a dragging sequence
|
|
461
|
-
// has been initiated, whereas the one on `this` includes whether the user has passed
|
|
462
|
-
// the minimum dragging threshold.
|
|
463
|
-
if (!this._dragDropRegistry.isDragging(this)) {
|
|
464
|
-
return;
|
|
465
|
-
}
|
|
466
|
-
this._removeListeners();
|
|
467
|
-
this._dragDropRegistry.stopDragging(this);
|
|
468
|
-
this._toggleNativeDragInteractions();
|
|
469
|
-
if (this._handles) {
|
|
470
|
-
this._rootElement.style.webkitTapHighlightColor =
|
|
471
|
-
this._rootElementTapHighlight;
|
|
472
|
-
}
|
|
473
|
-
if (!this._hasStartedDragging()) {
|
|
474
|
-
return;
|
|
475
|
-
}
|
|
476
|
-
this.released.next({ source: this, event });
|
|
477
|
-
if (this._dropContainer) {
|
|
478
|
-
// Stop scrolling immediately, instead of waiting for the animation to finish.
|
|
479
|
-
this._dropContainer._stopScrolling();
|
|
480
|
-
this._animatePreviewToPlaceholder().then(() => {
|
|
481
|
-
this._cleanupDragArtifacts(event);
|
|
482
|
-
this._cleanupCachedDimensions();
|
|
483
|
-
this._dragDropRegistry.stopDragging(this);
|
|
484
|
-
});
|
|
485
|
-
}
|
|
486
|
-
else {
|
|
487
|
-
// Convert the active transform into a passive one. This means that next time
|
|
488
|
-
// the user starts dragging the item, its position will be calculated relatively
|
|
489
|
-
// to the new passive transform.
|
|
490
|
-
this._passiveTransform.x = this._activeTransform.x;
|
|
491
|
-
const pointerPosition = this._getPointerPositionOnPage(event);
|
|
492
|
-
this._passiveTransform.y = this._activeTransform.y;
|
|
493
|
-
this._ngZone.run(() => {
|
|
494
|
-
this.ended.next({
|
|
495
|
-
source: this,
|
|
496
|
-
distance: this._getDragDistance(pointerPosition),
|
|
497
|
-
dropPoint: pointerPosition,
|
|
498
|
-
event,
|
|
499
|
-
});
|
|
500
|
-
});
|
|
501
|
-
this._cleanupCachedDimensions();
|
|
502
|
-
this._dragDropRegistry.stopDragging(this);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
/** Starts the dragging sequence. */
|
|
506
|
-
_startDragSequence(event) {
|
|
507
|
-
if (isTouchEvent(event)) {
|
|
508
|
-
this._lastTouchEventTime = Date.now();
|
|
509
|
-
}
|
|
510
|
-
this._toggleNativeDragInteractions();
|
|
511
|
-
// Needs to happen before the root element is moved.
|
|
512
|
-
const shadowRoot = this._getShadowRoot();
|
|
513
|
-
const dropContainer = this._dropContainer;
|
|
514
|
-
if (shadowRoot) {
|
|
515
|
-
// In some browsers the global `selectstart` that we maintain in the `DragDropRegistry`
|
|
516
|
-
// doesn't cross the shadow boundary so we have to prevent it at the shadow root (see #28792).
|
|
517
|
-
this._ngZone.runOutsideAngular(() => {
|
|
518
|
-
shadowRoot.addEventListener('selectstart', shadowDomSelectStart, activeCapturingEventOptions);
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
if (dropContainer) {
|
|
522
|
-
const element = this._rootElement;
|
|
523
|
-
const parent = element.parentNode;
|
|
524
|
-
const placeholder = (this._placeholder = this._createPlaceholderElement());
|
|
525
|
-
const anchor = (this._anchor =
|
|
526
|
-
this._anchor || this._document.createComment(ngDevMode ? 'cdk-drag-anchor' : ''));
|
|
527
|
-
// Insert an anchor node so that we can restore the element's position in the DOM.
|
|
528
|
-
parent.insertBefore(anchor, element);
|
|
529
|
-
// There's no risk of transforms stacking when inside a drop container so
|
|
530
|
-
// we can keep the initial transform up to date any time dragging starts.
|
|
531
|
-
this._initialTransform = element.style.transform || '';
|
|
532
|
-
// Create the preview after the initial transform has
|
|
533
|
-
// been cached, because it can be affected by the transform.
|
|
534
|
-
this._preview = new PreviewRef(this._document, this._rootElement, this._direction, this._initialDomRect, this._previewTemplate || null, this.previewClass || null, this._pickupPositionOnPage, this._initialTransform, this._config.zIndex || 1000);
|
|
535
|
-
this._preview.attach(this._getPreviewInsertionPoint(parent, shadowRoot));
|
|
536
|
-
// We move the element out at the end of the body and we make it hidden, because keeping it in
|
|
537
|
-
// place will throw off the consumer's `:last-child` selectors. We can't remove the element
|
|
538
|
-
// from the DOM completely, because iOS will stop firing all subsequent events in the chain.
|
|
539
|
-
toggleVisibility(element, false, dragImportantProperties);
|
|
540
|
-
this._document.body.appendChild(parent.replaceChild(placeholder, element));
|
|
541
|
-
this.started.next({ source: this, event }); // Emit before notifying the container.
|
|
542
|
-
dropContainer.start();
|
|
543
|
-
this._initialContainer = dropContainer;
|
|
544
|
-
this._initialIndex = dropContainer.getItemIndex(this);
|
|
545
|
-
}
|
|
546
|
-
else {
|
|
547
|
-
this.started.next({ source: this, event });
|
|
548
|
-
this._initialContainer = this._initialIndex = undefined;
|
|
549
|
-
}
|
|
550
|
-
// Important to run after we've called `start` on the parent container
|
|
551
|
-
// so that it has had time to resolve its scrollable parents.
|
|
552
|
-
this._parentPositions.cache(dropContainer ? dropContainer.getScrollableParents() : []);
|
|
553
|
-
}
|
|
554
|
-
/**
|
|
555
|
-
* Sets up the different variables and subscriptions
|
|
556
|
-
* that will be necessary for the dragging sequence.
|
|
557
|
-
* @param referenceElement Element that started the drag sequence.
|
|
558
|
-
* @param event Browser event object that started the sequence.
|
|
559
|
-
*/
|
|
560
|
-
_initializeDragSequence(referenceElement, event) {
|
|
561
|
-
// Stop propagation if the item is inside another
|
|
562
|
-
// draggable so we don't start multiple drag sequences.
|
|
563
|
-
if (this._parentDragRef) {
|
|
564
|
-
event.stopPropagation();
|
|
565
|
-
}
|
|
566
|
-
const isDragging = this.isDragging();
|
|
567
|
-
const isTouchSequence = isTouchEvent(event);
|
|
568
|
-
const isAuxiliaryMouseButton = !isTouchSequence && event.button !== 0;
|
|
569
|
-
const rootElement = this._rootElement;
|
|
570
|
-
const target = _getEventTarget(event);
|
|
571
|
-
const isSyntheticEvent = !isTouchSequence &&
|
|
572
|
-
this._lastTouchEventTime &&
|
|
573
|
-
this._lastTouchEventTime + MOUSE_EVENT_IGNORE_TIME > Date.now();
|
|
574
|
-
const isFakeEvent = isTouchSequence
|
|
575
|
-
? isFakeTouchstartFromScreenReader(event)
|
|
576
|
-
: isFakeMousedownFromScreenReader(event);
|
|
577
|
-
// If the event started from an element with the native HTML drag&drop, it'll interfere
|
|
578
|
-
// with our own dragging (e.g. `img` tags do it by default). Prevent the default action
|
|
579
|
-
// to stop it from happening. Note that preventing on `dragstart` also seems to work, but
|
|
580
|
-
// it's flaky and it fails if the user drags it away quickly. Also note that we only want
|
|
581
|
-
// to do this for `mousedown` since doing the same for `touchstart` will stop any `click`
|
|
582
|
-
// events from firing on touch devices.
|
|
583
|
-
if (target && target.draggable && event.type === 'mousedown') {
|
|
584
|
-
event.preventDefault();
|
|
585
|
-
}
|
|
586
|
-
// Abort if the user is already dragging or is using a mouse button other than the primary one.
|
|
587
|
-
if (isDragging || isAuxiliaryMouseButton || isSyntheticEvent || isFakeEvent) {
|
|
588
|
-
return;
|
|
589
|
-
}
|
|
590
|
-
// If we've got handles, we need to disable the tap highlight on the entire root element,
|
|
591
|
-
// otherwise iOS will still add it, even though all the drag interactions on the handle
|
|
592
|
-
// are disabled.
|
|
593
|
-
if (this._handles.length) {
|
|
594
|
-
const rootStyles = rootElement.style;
|
|
595
|
-
this._rootElementTapHighlight = rootStyles.webkitTapHighlightColor || '';
|
|
596
|
-
rootStyles.webkitTapHighlightColor = 'transparent';
|
|
597
|
-
}
|
|
598
|
-
this._hasMoved = false;
|
|
599
|
-
this._hasStartedDragging.set(this._hasMoved);
|
|
600
|
-
// Avoid multiple subscriptions and memory leaks when multi touch
|
|
601
|
-
// (isDragging check above isn't enough because of possible temporal and/or dimensional delays)
|
|
602
|
-
this._removeListeners();
|
|
603
|
-
this._initialDomRect = this._rootElement.getBoundingClientRect();
|
|
604
|
-
this._pointerMoveSubscription = this._dragDropRegistry.pointerMove.subscribe(this._pointerMove);
|
|
605
|
-
this._pointerUpSubscription = this._dragDropRegistry.pointerUp.subscribe(this._pointerUp);
|
|
606
|
-
this._scrollSubscription = this._dragDropRegistry
|
|
607
|
-
.scrolled(this._getShadowRoot())
|
|
608
|
-
.subscribe(scrollEvent => this._updateOnScroll(scrollEvent));
|
|
609
|
-
if (this._boundaryElement) {
|
|
610
|
-
this._boundaryRect = getMutableClientRect(this._boundaryElement);
|
|
611
|
-
}
|
|
612
|
-
// If we have a custom preview we can't know ahead of time how large it'll be so we position
|
|
613
|
-
// it next to the cursor. The exception is when the consumer has opted into making the preview
|
|
614
|
-
// the same size as the root element, in which case we do know the size.
|
|
615
|
-
const previewTemplate = this._previewTemplate;
|
|
616
|
-
this._pickupPositionInElement =
|
|
617
|
-
previewTemplate && previewTemplate.template && !previewTemplate.matchSize
|
|
618
|
-
? { x: 0, y: 0 }
|
|
619
|
-
: this._getPointerPositionInElement(this._initialDomRect, referenceElement, event);
|
|
620
|
-
const pointerPosition = (this._pickupPositionOnPage =
|
|
621
|
-
this._lastKnownPointerPosition =
|
|
622
|
-
this._getPointerPositionOnPage(event));
|
|
623
|
-
this._pointerDirectionDelta = { x: 0, y: 0 };
|
|
624
|
-
this._pointerPositionAtLastDirectionChange = { x: pointerPosition.x, y: pointerPosition.y };
|
|
625
|
-
this._dragStartTime = Date.now();
|
|
626
|
-
this._dragDropRegistry.startDragging(this, event);
|
|
627
|
-
}
|
|
628
|
-
/** Cleans up the DOM artifacts that were added to facilitate the element being dragged. */
|
|
629
|
-
_cleanupDragArtifacts(event) {
|
|
630
|
-
// Restore the element's visibility and insert it at its old position in the DOM.
|
|
631
|
-
// It's important that we maintain the position, because moving the element around in the DOM
|
|
632
|
-
// can throw off `NgFor` which does smart diffing and re-creates elements only when necessary,
|
|
633
|
-
// while moving the existing elements in all other cases.
|
|
634
|
-
toggleVisibility(this._rootElement, true, dragImportantProperties);
|
|
635
|
-
this._anchor.parentNode.replaceChild(this._rootElement, this._anchor);
|
|
636
|
-
this._destroyPreview();
|
|
637
|
-
this._destroyPlaceholder();
|
|
638
|
-
this._initialDomRect =
|
|
639
|
-
this._boundaryRect =
|
|
640
|
-
this._previewRect =
|
|
641
|
-
this._initialTransform =
|
|
642
|
-
undefined;
|
|
643
|
-
// Re-enter the NgZone since we bound `document` events on the outside.
|
|
644
|
-
this._ngZone.run(() => {
|
|
645
|
-
const container = this._dropContainer;
|
|
646
|
-
const currentIndex = container.getItemIndex(this);
|
|
647
|
-
const pointerPosition = this._getPointerPositionOnPage(event);
|
|
648
|
-
const distance = this._getDragDistance(pointerPosition);
|
|
649
|
-
const isPointerOverContainer = container._isOverContainer(pointerPosition.x, pointerPosition.y);
|
|
650
|
-
this.ended.next({ source: this, distance, dropPoint: pointerPosition, event });
|
|
651
|
-
this.dropped.next({
|
|
652
|
-
item: this,
|
|
653
|
-
currentIndex,
|
|
654
|
-
previousIndex: this._initialIndex,
|
|
655
|
-
container: container,
|
|
656
|
-
previousContainer: this._initialContainer,
|
|
657
|
-
isPointerOverContainer,
|
|
658
|
-
distance,
|
|
659
|
-
dropPoint: pointerPosition,
|
|
660
|
-
event,
|
|
661
|
-
});
|
|
662
|
-
container.drop(this, currentIndex, this._initialIndex, this._initialContainer, isPointerOverContainer, distance, pointerPosition, event);
|
|
663
|
-
this._dropContainer = this._initialContainer;
|
|
664
|
-
});
|
|
665
|
-
}
|
|
666
|
-
/**
|
|
667
|
-
* Updates the item's position in its drop container, or moves it
|
|
668
|
-
* into a new one, depending on its current drag position.
|
|
669
|
-
*/
|
|
670
|
-
_updateActiveDropContainer({ x, y }, { x: rawX, y: rawY }) {
|
|
671
|
-
// Drop container that draggable has been moved into.
|
|
672
|
-
let newContainer = this._initialContainer._getSiblingContainerFromPosition(this, x, y);
|
|
673
|
-
// If we couldn't find a new container to move the item into, and the item has left its
|
|
674
|
-
// initial container, check whether the it's over the initial container. This handles the
|
|
675
|
-
// case where two containers are connected one way and the user tries to undo dragging an
|
|
676
|
-
// item into a new container.
|
|
677
|
-
if (!newContainer &&
|
|
678
|
-
this._dropContainer !== this._initialContainer &&
|
|
679
|
-
this._initialContainer._isOverContainer(x, y)) {
|
|
680
|
-
newContainer = this._initialContainer;
|
|
681
|
-
}
|
|
682
|
-
if (newContainer && newContainer !== this._dropContainer) {
|
|
683
|
-
this._ngZone.run(() => {
|
|
684
|
-
// Notify the old container that the item has left.
|
|
685
|
-
this.exited.next({ item: this, container: this._dropContainer });
|
|
686
|
-
this._dropContainer.exit(this);
|
|
687
|
-
// Notify the new container that the item has entered.
|
|
688
|
-
this._dropContainer = newContainer;
|
|
689
|
-
this._dropContainer.enter(this, x, y, newContainer === this._initialContainer &&
|
|
690
|
-
// If we're re-entering the initial container and sorting is disabled,
|
|
691
|
-
// put item the into its starting index to begin with.
|
|
692
|
-
newContainer.sortingDisabled
|
|
693
|
-
? this._initialIndex
|
|
694
|
-
: undefined);
|
|
695
|
-
this.entered.next({
|
|
696
|
-
item: this,
|
|
697
|
-
container: newContainer,
|
|
698
|
-
currentIndex: newContainer.getItemIndex(this),
|
|
699
|
-
});
|
|
700
|
-
});
|
|
701
|
-
}
|
|
702
|
-
// Dragging may have been interrupted as a result of the events above.
|
|
703
|
-
if (this.isDragging()) {
|
|
704
|
-
this._dropContainer._startScrollingIfNecessary(rawX, rawY);
|
|
705
|
-
this._dropContainer._sortItem(this, x, y, this._pointerDirectionDelta);
|
|
706
|
-
if (this.constrainPosition) {
|
|
707
|
-
this._applyPreviewTransform(x, y);
|
|
708
|
-
}
|
|
709
|
-
else {
|
|
710
|
-
this._applyPreviewTransform(x - this._pickupPositionInElement.x, y - this._pickupPositionInElement.y);
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
/**
|
|
715
|
-
* Animates the preview element from its current position to the location of the drop placeholder.
|
|
716
|
-
* @returns Promise that resolves when the animation completes.
|
|
717
|
-
*/
|
|
718
|
-
_animatePreviewToPlaceholder() {
|
|
719
|
-
// If the user hasn't moved yet, the transitionend event won't fire.
|
|
720
|
-
if (!this._hasMoved) {
|
|
721
|
-
return Promise.resolve();
|
|
722
|
-
}
|
|
723
|
-
const placeholderRect = this._placeholder.getBoundingClientRect();
|
|
724
|
-
// Apply the class that adds a transition to the preview.
|
|
725
|
-
this._preview.addClass('cdk-drag-animating');
|
|
726
|
-
// Move the preview to the placeholder position.
|
|
727
|
-
this._applyPreviewTransform(placeholderRect.left, placeholderRect.top);
|
|
728
|
-
// If the element doesn't have a `transition`, the `transitionend` event won't fire. Since
|
|
729
|
-
// we need to trigger a style recalculation in order for the `cdk-drag-animating` class to
|
|
730
|
-
// apply its style, we take advantage of the available info to figure out whether we need to
|
|
731
|
-
// bind the event in the first place.
|
|
732
|
-
const duration = this._preview.getTransitionDuration();
|
|
733
|
-
if (duration === 0) {
|
|
734
|
-
return Promise.resolve();
|
|
735
|
-
}
|
|
736
|
-
return this._ngZone.runOutsideAngular(() => {
|
|
737
|
-
return new Promise(resolve => {
|
|
738
|
-
const handler = ((event) => {
|
|
739
|
-
if (!event ||
|
|
740
|
-
(this._preview &&
|
|
741
|
-
_getEventTarget(event) === this._preview.element &&
|
|
742
|
-
event.propertyName === 'transform')) {
|
|
743
|
-
this._preview?.removeEventListener('transitionend', handler);
|
|
744
|
-
resolve();
|
|
745
|
-
clearTimeout(timeout);
|
|
746
|
-
}
|
|
747
|
-
});
|
|
748
|
-
// If a transition is short enough, the browser might not fire the `transitionend` event.
|
|
749
|
-
// Since we know how long it's supposed to take, add a timeout with a 50% buffer that'll
|
|
750
|
-
// fire if the transition hasn't completed when it was supposed to.
|
|
751
|
-
const timeout = setTimeout(handler, duration * 1.5);
|
|
752
|
-
this._preview.addEventListener('transitionend', handler);
|
|
753
|
-
});
|
|
754
|
-
});
|
|
755
|
-
}
|
|
756
|
-
/** Creates an element that will be shown instead of the current element while dragging. */
|
|
757
|
-
_createPlaceholderElement() {
|
|
758
|
-
const placeholderConfig = this._placeholderTemplate;
|
|
759
|
-
const placeholderTemplate = placeholderConfig ? placeholderConfig.template : null;
|
|
760
|
-
let placeholder;
|
|
761
|
-
if (placeholderTemplate) {
|
|
762
|
-
this._placeholderRef = placeholderConfig.viewContainer.createEmbeddedView(placeholderTemplate, placeholderConfig.context);
|
|
763
|
-
this._placeholderRef.detectChanges();
|
|
764
|
-
placeholder = getRootNode(this._placeholderRef, this._document);
|
|
765
|
-
}
|
|
766
|
-
else {
|
|
767
|
-
placeholder = deepCloneNode(this._rootElement);
|
|
768
|
-
}
|
|
769
|
-
// Stop pointer events on the preview so the user can't
|
|
770
|
-
// interact with it while the preview is animating.
|
|
771
|
-
placeholder.style.pointerEvents = 'none';
|
|
772
|
-
placeholder.classList.add('cdk-drag-placeholder');
|
|
773
|
-
return placeholder;
|
|
774
|
-
}
|
|
775
|
-
/**
|
|
776
|
-
* Figures out the coordinates at which an element was picked up.
|
|
777
|
-
* @param referenceElement Element that initiated the dragging.
|
|
778
|
-
* @param event Event that initiated the dragging.
|
|
779
|
-
*/
|
|
780
|
-
_getPointerPositionInElement(elementRect, referenceElement, event) {
|
|
781
|
-
const handleElement = referenceElement === this._rootElement ? null : referenceElement;
|
|
782
|
-
const referenceRect = handleElement ? handleElement.getBoundingClientRect() : elementRect;
|
|
783
|
-
const point = isTouchEvent(event) ? event.targetTouches[0] : event;
|
|
784
|
-
const scrollPosition = this._getViewportScrollPosition();
|
|
785
|
-
const x = point.pageX - referenceRect.left - scrollPosition.left;
|
|
786
|
-
const y = point.pageY - referenceRect.top - scrollPosition.top;
|
|
787
|
-
return {
|
|
788
|
-
x: referenceRect.left - elementRect.left + x,
|
|
789
|
-
y: referenceRect.top - elementRect.top + y,
|
|
790
|
-
};
|
|
791
|
-
}
|
|
792
|
-
/** Determines the point of the page that was touched by the user. */
|
|
793
|
-
_getPointerPositionOnPage(event) {
|
|
794
|
-
const scrollPosition = this._getViewportScrollPosition();
|
|
795
|
-
const point = isTouchEvent(event)
|
|
796
|
-
? // `touches` will be empty for start/end events so we have to fall back to `changedTouches`.
|
|
797
|
-
// Also note that on real devices we're guaranteed for either `touches` or `changedTouches`
|
|
798
|
-
// to have a value, but Firefox in device emulation mode has a bug where both can be empty
|
|
799
|
-
// for `touchstart` and `touchend` so we fall back to a dummy object in order to avoid
|
|
800
|
-
// throwing an error. The value returned here will be incorrect, but since this only
|
|
801
|
-
// breaks inside a developer tool and the value is only used for secondary information,
|
|
802
|
-
// we can get away with it. See https://bugzilla.mozilla.org/show_bug.cgi?id=1615824.
|
|
803
|
-
event.touches[0] || event.changedTouches[0] || { pageX: 0, pageY: 0 }
|
|
804
|
-
: event;
|
|
805
|
-
const x = point.pageX - scrollPosition.left;
|
|
806
|
-
const y = point.pageY - scrollPosition.top;
|
|
807
|
-
// if dragging SVG element, try to convert from the screen coordinate system to the SVG
|
|
808
|
-
// coordinate system
|
|
809
|
-
if (this._ownerSVGElement) {
|
|
810
|
-
const svgMatrix = this._ownerSVGElement.getScreenCTM();
|
|
811
|
-
if (svgMatrix) {
|
|
812
|
-
const svgPoint = this._ownerSVGElement.createSVGPoint();
|
|
813
|
-
svgPoint.x = x;
|
|
814
|
-
svgPoint.y = y;
|
|
815
|
-
return svgPoint.matrixTransform(svgMatrix.inverse());
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
return { x, y };
|
|
819
|
-
}
|
|
820
|
-
/** Gets the pointer position on the page, accounting for any position constraints. */
|
|
821
|
-
_getConstrainedPointerPosition(point) {
|
|
822
|
-
const dropContainerLock = this._dropContainer ? this._dropContainer.lockAxis : null;
|
|
823
|
-
let { x, y } = this.constrainPosition
|
|
824
|
-
? this.constrainPosition(point, this, this._initialDomRect, this._pickupPositionInElement)
|
|
825
|
-
: point;
|
|
826
|
-
if (this.lockAxis === 'x' || dropContainerLock === 'x') {
|
|
827
|
-
y =
|
|
828
|
-
this._pickupPositionOnPage.y -
|
|
829
|
-
(this.constrainPosition ? this._pickupPositionInElement.y : 0);
|
|
830
|
-
}
|
|
831
|
-
else if (this.lockAxis === 'y' || dropContainerLock === 'y') {
|
|
832
|
-
x =
|
|
833
|
-
this._pickupPositionOnPage.x -
|
|
834
|
-
(this.constrainPosition ? this._pickupPositionInElement.x : 0);
|
|
835
|
-
}
|
|
836
|
-
if (this._boundaryRect) {
|
|
837
|
-
// If not using a custom constrain we need to account for the pickup position in the element
|
|
838
|
-
// otherwise we do not need to do this, as it has already been accounted for
|
|
839
|
-
const { x: pickupX, y: pickupY } = !this.constrainPosition
|
|
840
|
-
? this._pickupPositionInElement
|
|
841
|
-
: { x: 0, y: 0 };
|
|
842
|
-
const boundaryRect = this._boundaryRect;
|
|
843
|
-
const { width: previewWidth, height: previewHeight } = this._getPreviewRect();
|
|
844
|
-
const minY = boundaryRect.top + pickupY;
|
|
845
|
-
const maxY = boundaryRect.bottom - (previewHeight - pickupY);
|
|
846
|
-
const minX = boundaryRect.left + pickupX;
|
|
847
|
-
const maxX = boundaryRect.right - (previewWidth - pickupX);
|
|
848
|
-
x = clamp(x, minX, maxX);
|
|
849
|
-
y = clamp(y, minY, maxY);
|
|
850
|
-
}
|
|
851
|
-
return { x, y };
|
|
852
|
-
}
|
|
853
|
-
/** Updates the current drag delta, based on the user's current pointer position on the page. */
|
|
854
|
-
_updatePointerDirectionDelta(pointerPositionOnPage) {
|
|
855
|
-
const { x, y } = pointerPositionOnPage;
|
|
856
|
-
const delta = this._pointerDirectionDelta;
|
|
857
|
-
const positionSinceLastChange = this._pointerPositionAtLastDirectionChange;
|
|
858
|
-
// Amount of pixels the user has dragged since the last time the direction changed.
|
|
859
|
-
const changeX = Math.abs(x - positionSinceLastChange.x);
|
|
860
|
-
const changeY = Math.abs(y - positionSinceLastChange.y);
|
|
861
|
-
// Because we handle pointer events on a per-pixel basis, we don't want the delta
|
|
862
|
-
// to change for every pixel, otherwise anything that depends on it can look erratic.
|
|
863
|
-
// To make the delta more consistent, we track how much the user has moved since the last
|
|
864
|
-
// delta change and we only update it after it has reached a certain threshold.
|
|
865
|
-
if (changeX > this._config.pointerDirectionChangeThreshold) {
|
|
866
|
-
delta.x = x > positionSinceLastChange.x ? 1 : -1;
|
|
867
|
-
positionSinceLastChange.x = x;
|
|
868
|
-
}
|
|
869
|
-
if (changeY > this._config.pointerDirectionChangeThreshold) {
|
|
870
|
-
delta.y = y > positionSinceLastChange.y ? 1 : -1;
|
|
871
|
-
positionSinceLastChange.y = y;
|
|
872
|
-
}
|
|
873
|
-
return delta;
|
|
874
|
-
}
|
|
875
|
-
/** Toggles the native drag interactions, based on how many handles are registered. */
|
|
876
|
-
_toggleNativeDragInteractions() {
|
|
877
|
-
if (!this._rootElement || !this._handles) {
|
|
878
|
-
return;
|
|
879
|
-
}
|
|
880
|
-
const shouldEnable = this._handles.length > 0 || !this.isDragging();
|
|
881
|
-
if (shouldEnable !== this._nativeInteractionsEnabled) {
|
|
882
|
-
this._nativeInteractionsEnabled = shouldEnable;
|
|
883
|
-
toggleNativeDragInteractions(this._rootElement, shouldEnable);
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
/** Removes the manually-added event listeners from the root element. */
|
|
887
|
-
_removeRootElementListeners(element) {
|
|
888
|
-
element.removeEventListener('mousedown', this._pointerDown, activeEventListenerOptions);
|
|
889
|
-
element.removeEventListener('touchstart', this._pointerDown, passiveEventListenerOptions);
|
|
890
|
-
element.removeEventListener('dragstart', this._nativeDragStart, activeEventListenerOptions);
|
|
891
|
-
}
|
|
892
|
-
/**
|
|
893
|
-
* Applies a `transform` to the root element, taking into account any existing transforms on it.
|
|
894
|
-
* @param x New transform value along the X axis.
|
|
895
|
-
* @param y New transform value along the Y axis.
|
|
896
|
-
*/
|
|
897
|
-
_applyRootElementTransform(x, y) {
|
|
898
|
-
const scale = 1 / this.scale;
|
|
899
|
-
const transform = getTransform(x * scale, y * scale);
|
|
900
|
-
const styles = this._rootElement.style;
|
|
901
|
-
// Cache the previous transform amount only after the first drag sequence, because
|
|
902
|
-
// we don't want our own transforms to stack on top of each other.
|
|
903
|
-
// Should be excluded none because none + translate3d(x, y, x) is invalid css
|
|
904
|
-
if (this._initialTransform == null) {
|
|
905
|
-
this._initialTransform =
|
|
906
|
-
styles.transform && styles.transform != 'none' ? styles.transform : '';
|
|
907
|
-
}
|
|
908
|
-
// Preserve the previous `transform` value, if there was one. Note that we apply our own
|
|
909
|
-
// transform before the user's, because things like rotation can affect which direction
|
|
910
|
-
// the element will be translated towards.
|
|
911
|
-
styles.transform = combineTransforms(transform, this._initialTransform);
|
|
912
|
-
}
|
|
913
|
-
/**
|
|
914
|
-
* Applies a `transform` to the preview, taking into account any existing transforms on it.
|
|
915
|
-
* @param x New transform value along the X axis.
|
|
916
|
-
* @param y New transform value along the Y axis.
|
|
917
|
-
*/
|
|
918
|
-
_applyPreviewTransform(x, y) {
|
|
919
|
-
// Only apply the initial transform if the preview is a clone of the original element, otherwise
|
|
920
|
-
// it could be completely different and the transform might not make sense anymore.
|
|
921
|
-
const initialTransform = this._previewTemplate?.template ? undefined : this._initialTransform;
|
|
922
|
-
const transform = getTransform(x, y);
|
|
923
|
-
this._preview.setTransform(combineTransforms(transform, initialTransform));
|
|
924
|
-
}
|
|
925
|
-
/**
|
|
926
|
-
* Gets the distance that the user has dragged during the current drag sequence.
|
|
927
|
-
* @param currentPosition Current position of the user's pointer.
|
|
928
|
-
*/
|
|
929
|
-
_getDragDistance(currentPosition) {
|
|
930
|
-
const pickupPosition = this._pickupPositionOnPage;
|
|
931
|
-
if (pickupPosition) {
|
|
932
|
-
return { x: currentPosition.x - pickupPosition.x, y: currentPosition.y - pickupPosition.y };
|
|
933
|
-
}
|
|
934
|
-
return { x: 0, y: 0 };
|
|
935
|
-
}
|
|
936
|
-
/** Cleans up any cached element dimensions that we don't need after dragging has stopped. */
|
|
937
|
-
_cleanupCachedDimensions() {
|
|
938
|
-
this._boundaryRect = this._previewRect = undefined;
|
|
939
|
-
this._parentPositions.clear();
|
|
940
|
-
}
|
|
941
|
-
/**
|
|
942
|
-
* Checks whether the element is still inside its boundary after the viewport has been resized.
|
|
943
|
-
* If not, the position is adjusted so that the element fits again.
|
|
944
|
-
*/
|
|
945
|
-
_containInsideBoundaryOnResize() {
|
|
946
|
-
let { x, y } = this._passiveTransform;
|
|
947
|
-
if ((x === 0 && y === 0) || this.isDragging() || !this._boundaryElement) {
|
|
948
|
-
return;
|
|
949
|
-
}
|
|
950
|
-
// Note: don't use `_clientRectAtStart` here, because we want the latest position.
|
|
951
|
-
const elementRect = this._rootElement.getBoundingClientRect();
|
|
952
|
-
const boundaryRect = this._boundaryElement.getBoundingClientRect();
|
|
953
|
-
// It's possible that the element got hidden away after dragging (e.g. by switching to a
|
|
954
|
-
// different tab). Don't do anything in this case so we don't clear the user's position.
|
|
955
|
-
if ((boundaryRect.width === 0 && boundaryRect.height === 0) ||
|
|
956
|
-
(elementRect.width === 0 && elementRect.height === 0)) {
|
|
957
|
-
return;
|
|
958
|
-
}
|
|
959
|
-
const leftOverflow = boundaryRect.left - elementRect.left;
|
|
960
|
-
const rightOverflow = elementRect.right - boundaryRect.right;
|
|
961
|
-
const topOverflow = boundaryRect.top - elementRect.top;
|
|
962
|
-
const bottomOverflow = elementRect.bottom - boundaryRect.bottom;
|
|
963
|
-
// If the element has become wider than the boundary, we can't
|
|
964
|
-
// do much to make it fit so we just anchor it to the left.
|
|
965
|
-
if (boundaryRect.width > elementRect.width) {
|
|
966
|
-
if (leftOverflow > 0) {
|
|
967
|
-
x += leftOverflow;
|
|
968
|
-
}
|
|
969
|
-
if (rightOverflow > 0) {
|
|
970
|
-
x -= rightOverflow;
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
|
-
else {
|
|
974
|
-
x = 0;
|
|
975
|
-
}
|
|
976
|
-
// If the element has become taller than the boundary, we can't
|
|
977
|
-
// do much to make it fit so we just anchor it to the top.
|
|
978
|
-
if (boundaryRect.height > elementRect.height) {
|
|
979
|
-
if (topOverflow > 0) {
|
|
980
|
-
y += topOverflow;
|
|
981
|
-
}
|
|
982
|
-
if (bottomOverflow > 0) {
|
|
983
|
-
y -= bottomOverflow;
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
else {
|
|
987
|
-
y = 0;
|
|
988
|
-
}
|
|
989
|
-
if (x !== this._passiveTransform.x || y !== this._passiveTransform.y) {
|
|
990
|
-
this.setFreeDragPosition({ y, x });
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
/** Gets the drag start delay, based on the event type. */
|
|
994
|
-
_getDragStartDelay(event) {
|
|
995
|
-
const value = this.dragStartDelay;
|
|
996
|
-
if (typeof value === 'number') {
|
|
997
|
-
return value;
|
|
998
|
-
}
|
|
999
|
-
else if (isTouchEvent(event)) {
|
|
1000
|
-
return value.touch;
|
|
1001
|
-
}
|
|
1002
|
-
return value ? value.mouse : 0;
|
|
1003
|
-
}
|
|
1004
|
-
/** Updates the internal state of the draggable element when scrolling has occurred. */
|
|
1005
|
-
_updateOnScroll(event) {
|
|
1006
|
-
const scrollDifference = this._parentPositions.handleScroll(event);
|
|
1007
|
-
if (scrollDifference) {
|
|
1008
|
-
const target = _getEventTarget(event);
|
|
1009
|
-
// DOMRect dimensions are based on the scroll position of the page and its parent
|
|
1010
|
-
// node so we have to update the cached boundary DOMRect if the user has scrolled.
|
|
1011
|
-
if (this._boundaryRect &&
|
|
1012
|
-
target !== this._boundaryElement &&
|
|
1013
|
-
target.contains(this._boundaryElement)) {
|
|
1014
|
-
adjustDomRect(this._boundaryRect, scrollDifference.top, scrollDifference.left);
|
|
1015
|
-
}
|
|
1016
|
-
this._pickupPositionOnPage.x += scrollDifference.left;
|
|
1017
|
-
this._pickupPositionOnPage.y += scrollDifference.top;
|
|
1018
|
-
// If we're in free drag mode, we have to update the active transform, because
|
|
1019
|
-
// it isn't relative to the viewport like the preview inside a drop list.
|
|
1020
|
-
if (!this._dropContainer) {
|
|
1021
|
-
this._activeTransform.x -= scrollDifference.left;
|
|
1022
|
-
this._activeTransform.y -= scrollDifference.top;
|
|
1023
|
-
this._applyRootElementTransform(this._activeTransform.x, this._activeTransform.y);
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
/** Gets the scroll position of the viewport. */
|
|
1028
|
-
_getViewportScrollPosition() {
|
|
1029
|
-
return (this._parentPositions.positions.get(this._document)?.scrollPosition ||
|
|
1030
|
-
this._parentPositions.getViewportScrollPosition());
|
|
1031
|
-
}
|
|
1032
|
-
/**
|
|
1033
|
-
* Lazily resolves and returns the shadow root of the element. We do this in a function, rather
|
|
1034
|
-
* than saving it in property directly on init, because we want to resolve it as late as possible
|
|
1035
|
-
* in order to ensure that the element has been moved into the shadow DOM. Doing it inside the
|
|
1036
|
-
* constructor might be too early if the element is inside of something like `ngFor` or `ngIf`.
|
|
1037
|
-
*/
|
|
1038
|
-
_getShadowRoot() {
|
|
1039
|
-
if (this._cachedShadowRoot === undefined) {
|
|
1040
|
-
this._cachedShadowRoot = _getShadowRoot(this._rootElement);
|
|
1041
|
-
}
|
|
1042
|
-
return this._cachedShadowRoot;
|
|
1043
|
-
}
|
|
1044
|
-
/** Gets the element into which the drag preview should be inserted. */
|
|
1045
|
-
_getPreviewInsertionPoint(initialParent, shadowRoot) {
|
|
1046
|
-
const previewContainer = this._previewContainer || 'global';
|
|
1047
|
-
if (previewContainer === 'parent') {
|
|
1048
|
-
return initialParent;
|
|
1049
|
-
}
|
|
1050
|
-
if (previewContainer === 'global') {
|
|
1051
|
-
const documentRef = this._document;
|
|
1052
|
-
// We can't use the body if the user is in fullscreen mode,
|
|
1053
|
-
// because the preview will render under the fullscreen element.
|
|
1054
|
-
// TODO(crisbeto): dedupe this with the `FullscreenOverlayContainer` eventually.
|
|
1055
|
-
return (shadowRoot ||
|
|
1056
|
-
documentRef.fullscreenElement ||
|
|
1057
|
-
documentRef.webkitFullscreenElement ||
|
|
1058
|
-
documentRef.mozFullScreenElement ||
|
|
1059
|
-
documentRef.msFullscreenElement ||
|
|
1060
|
-
documentRef.body);
|
|
1061
|
-
}
|
|
1062
|
-
return coerceElement(previewContainer);
|
|
1063
|
-
}
|
|
1064
|
-
/** Lazily resolves and returns the dimensions of the preview. */
|
|
1065
|
-
_getPreviewRect() {
|
|
1066
|
-
// Cache the preview element rect if we haven't cached it already or if
|
|
1067
|
-
// we cached it too early before the element dimensions were computed.
|
|
1068
|
-
if (!this._previewRect || (!this._previewRect.width && !this._previewRect.height)) {
|
|
1069
|
-
this._previewRect = this._preview
|
|
1070
|
-
? this._preview.getBoundingClientRect()
|
|
1071
|
-
: this._initialDomRect;
|
|
1072
|
-
}
|
|
1073
|
-
return this._previewRect;
|
|
1074
|
-
}
|
|
1075
|
-
/** Gets a handle that is the target of an event. */
|
|
1076
|
-
_getTargetHandle(event) {
|
|
1077
|
-
return this._handles.find(handle => {
|
|
1078
|
-
return event.target && (event.target === handle || handle.contains(event.target));
|
|
1079
|
-
});
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
/** Clamps a value between a minimum and a maximum. */
|
|
1083
|
-
function clamp(value, min, max) {
|
|
1084
|
-
return Math.max(min, Math.min(max, value));
|
|
1085
|
-
}
|
|
1086
|
-
/** Determines whether an event is a touch event. */
|
|
1087
|
-
function isTouchEvent(event) {
|
|
1088
|
-
// This function is called for every pixel that the user has dragged so we need it to be
|
|
1089
|
-
// as fast as possible. Since we only bind mouse events and touch events, we can assume
|
|
1090
|
-
// that if the event's name starts with `t`, it's a touch event.
|
|
1091
|
-
return event.type[0] === 't';
|
|
1092
|
-
}
|
|
1093
|
-
/** Callback invoked for `selectstart` events inside the shadow DOM. */
|
|
1094
|
-
function shadowDomSelectStart(event) {
|
|
1095
|
-
event.preventDefault();
|
|
1096
|
-
}
|
|
1097
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJhZy1yZWYuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvY2RrL2RyYWctZHJvcC9kcmFnLXJlZi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEVBQUMsK0JBQStCLEVBQUUsZ0NBQWdDLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUVwRyxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDcEQsT0FBTyxFQUNMLGVBQWUsRUFDZixjQUFjLEVBQ2QsK0JBQStCLEdBQ2hDLE1BQU0sdUJBQXVCLENBQUM7QUFFL0IsT0FBTyxFQU1MLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQWEsT0FBTyxFQUFFLFlBQVksRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUN2RCxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0sa0JBQWtCLENBQUM7QUFDL0MsT0FBTyxFQUFDLGFBQWEsRUFBRSxvQkFBb0IsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQ25FLE9BQU8sRUFBQyxxQkFBcUIsRUFBQyxNQUFNLCtCQUErQixDQUFDO0FBQ3BFLE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUM1QyxPQUFPLEVBRUwsaUJBQWlCLEVBQ2pCLFlBQVksRUFDWiw0QkFBNEIsRUFDNUIsZ0JBQWdCLEdBQ2pCLE1BQU0sZUFBZSxDQUFDO0FBR3ZCLE9BQU8sRUFBc0IsVUFBVSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBdUI5RCxpRUFBaUU7QUFDakUsTUFBTSwyQkFBMkIsR0FBRywrQkFBK0IsQ0FBQyxFQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFDO0FBRXJGLGlFQUFpRTtBQUNqRSxNQUFNLDBCQUEwQixHQUFHLCtCQUErQixDQUFDLEVBQUMsT0FBTyxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUM7QUFFckYseUVBQXlFO0FBQ3pFLE1BQU0sMkJBQTJCLEdBQUcsK0JBQStCLENBQUM7SUFDbEUsT0FBTyxFQUFFLEtBQUs7SUFDZCxPQUFPLEVBQUUsSUFBSTtDQUNkLENBQUMsQ0FBQztBQUVIOzs7OztHQUtHO0FBQ0gsTUFBTSx1QkFBdUIsR0FBRyxHQUFHLENBQUM7QUFrQnBDLDhEQUE4RDtBQUM5RCxNQUFNLHVCQUF1QixHQUFHLElBQUksR0FBRyxDQUFDO0lBQ3RDLGtHQUFrRztJQUNsRyxVQUFVO0NBQ1gsQ0FBQyxDQUFDO0FBZ0JIOztHQUVHO0FBQ0gsTUFBTSxPQUFPLE9BQU87SUErS2xCLHlEQUF5RDtJQUN6RCxJQUFJLFFBQVE7UUFDVixPQUFPLElBQUksQ0FBQyxTQUFTLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGNBQWMsSUFBSSxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ25GLENBQUM7SUFDRCxJQUFJLFFBQVEsQ0FBQyxLQUFjO1FBQ3pCLElBQUksS0FBSyxLQUFLLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUM3QixJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztZQUN2QixJQUFJLENBQUMsNkJBQTZCLEVBQUUsQ0FBQztZQUNyQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLDRCQUE0QixDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQy9FLENBQUM7SUFDSCxDQUFDO0lBbUVELFlBQ0UsT0FBOEMsRUFDdEMsT0FBc0IsRUFDdEIsU0FBbUIsRUFDbkIsT0FBZSxFQUNmLGNBQTZCLEVBQzdCLGlCQUFtQztRQUpuQyxZQUFPLEdBQVAsT0FBTyxDQUFlO1FBQ3RCLGNBQVMsR0FBVCxTQUFTLENBQVU7UUFDbkIsWUFBTyxHQUFQLE9BQU8sQ0FBUTtRQUNmLG1CQUFjLEdBQWQsY0FBYyxDQUFlO1FBQzdCLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBa0I7UUF6TzdDOzs7OztXQUtHO1FBQ0ssc0JBQWlCLEdBQVUsRUFBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUMsQ0FBQztRQUVoRCwrRUFBK0U7UUFDdkUscUJBQWdCLEdBQVUsRUFBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUMsQ0FBQztRQUsvQzs7O1dBR0c7UUFDSyx3QkFBbUIsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFjNUMsMENBQTBDO1FBQ3pCLGdCQUFXLEdBQUcsSUFBSSxPQUFPLEVBTXRDLENBQUM7UUE0QkwsK0NBQStDO1FBQ3ZDLDZCQUF3QixHQUFHLFlBQVksQ0FBQyxLQUFLLENBQUM7UUFFdEQsc0ZBQXNGO1FBQzlFLDJCQUFzQixHQUFHLFlBQVksQ0FBQyxLQUFLLENBQUM7UUFFcEQsbURBQW1EO1FBQzNDLHdCQUFtQixHQUFHLFlBQVksQ0FBQyxLQUFLLENBQUM7UUFFakQsa0RBQWtEO1FBQzFDLHdCQUFtQixHQUFHLFlBQVksQ0FBQyxLQUFLLENBQUM7UUFZakQsZ0RBQWdEO1FBQ3hDLHFCQUFnQixHQUF1QixJQUFJLENBQUM7UUFFcEQsc0ZBQXNGO1FBQzlFLCtCQUEwQixHQUFHLElBQUksQ0FBQztRQWlCMUMsNERBQTREO1FBQ3BELGFBQVEsR0FBa0IsRUFBRSxDQUFDO1FBRXJDLHNEQUFzRDtRQUM5QyxxQkFBZ0IsR0FBRyxJQUFJLEdBQUcsRUFBZSxDQUFDO1FBS2xELG9DQUFvQztRQUM1QixlQUFVLEdBQWMsS0FBSyxDQUFDO1FBZXRDOzs7V0FHRztRQUNILG1CQUFjLEdBQTRDLENBQUMsQ0FBQztRQUs1RDs7O1dBR0c7UUFDSCxVQUFLLEdBQVcsQ0FBQyxDQUFDO1FBYVYsY0FBUyxHQUFHLEtBQUssQ0FBQztRQUUxQixvREFBb0Q7UUFDM0Msa0JBQWEsR0FBRyxJQUFJLE9BQU8sRUFBUSxDQUFDO1FBRTdDLG9EQUFvRDtRQUMzQyxZQUFPLEdBQUcsSUFBSSxPQUFPLEVBQXFELENBQUM7UUFFcEYsd0ZBQXdGO1FBQy9FLGFBQVEsR0FBRyxJQUFJLE9BQU8sRUFBcUQsQ0FBQztRQUVyRixtRUFBbUU7UUFDMUQsVUFBSyxHQUFHLElBQUksT0FBTyxFQUt4QixDQUFDO1FBRUwsbUVBQW1FO1FBQzFELFlBQU8sR0FBRyxJQUFJLE9BQU8sRUFBaUUsQ0FBQztRQUVoRyxnR0FBZ0c7UUFDdkYsV0FBTSxHQUFHLElBQUksT0FBTyxFQUEyQyxDQUFDO1FBRXpFLDZEQUE2RDtRQUNwRCxZQUFPLEdBQUcsSUFBSSxPQUFPLEVBVTFCLENBQUM7UUFFTDs7O1dBR0c7UUFDTSxVQUFLLEdBTVQsSUFBSSxDQUFDLFdBQVcsQ0FBQztRQW1TdEIsdURBQXVEO1FBQy9DLGlCQUFZLEdBQUcsQ0FBQyxLQUE4QixFQUFFLEVBQUU7WUFDeEQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUUxQixzRkFBc0Y7WUFDdEYsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUN6QixNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBRWxELElBQUksWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztvQkFDL0UsSUFBSSxDQUFDLHVCQUF1QixDQUFDLFlBQVksRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDcEQsQ0FBQztZQUNILENBQUM7aUJBQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDMUIsSUFBSSxDQUFDLHVCQUF1QixDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDekQsQ0FBQztRQUNILENBQUMsQ0FBQztRQUVGLGdHQUFnRztRQUN4RixpQkFBWSxHQUFHLENBQUMsS0FBOEIsRUFBRSxFQUFFO1lBQ3hELE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUU5RCxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLEVBQUUsQ0FBQztnQkFDaEMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDN0UsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDN0UsTUFBTSxlQUFlLEdBQUcsU0FBUyxHQUFHLFNBQVMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUFDO2dCQUVqRix3RkFBd0Y7Z0JBQ3hGLDRGQUE0RjtnQkFDNUYseUZBQXlGO2dCQUN6Rix3RUFBd0U7Z0JBQ3hFLElBQUksZUFBZSxFQUFFLENBQUM7b0JBQ3BCLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDMUYsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQztvQkFFdEMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO3dCQUNwQixJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUM7d0JBQzdCLE9BQU87b0JBQ1QsQ0FBQztvQkFFRCx1RkFBdUY7b0JBQ3ZGLHNGQUFzRjtvQkFDdEYsNEVBQTRFO29CQUM1RSxJQUFJLENBQUMsU0FBUyxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFLENBQUMsRUFBRSxDQUFDO3dCQUN4RSwrRUFBK0U7d0JBQy9FLHNGQUFzRjt3QkFDdEYsSUFBSSxLQUFLLENBQUMsVUFBVSxFQUFFLENBQUM7NEJBQ3JCLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQzt3QkFDekIsQ0FBQzt3QkFDRCxJQUFJLENBQUMsbUJBQW1CLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO3dCQUNuQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztvQkFDekQsQ0FBQztnQkFDSCxDQUFDO2dCQUVELE9BQU87WUFDVCxDQUFDO1lBRUQsNkZBQTZGO1lBQzdGLDRGQUE0RjtZQUM1RiwrQkFBK0I7WUFDL0IsSUFBSSxLQUFLLENBQUMsVUFBVSxFQUFFLENBQUM7Z0JBQ3JCLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN6QixDQUFDO1lBRUQsTUFBTSwwQkFBMEIsR0FBRyxJQUFJLENBQUMsOEJBQThCLENBQUMsZUFBZSxDQUFDLENBQUM7WUFDeEYsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7WUFDdEIsSUFBSSxDQUFDLHlCQUF5QixHQUFHLGVBQWUsQ0FBQztZQUNqRCxJQUFJLENBQUMsNEJBQTRCLENBQUMsMEJBQTBCLENBQUMsQ0FBQztZQUU5RCxJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztnQkFDeEIsSUFBSSxDQUFDLDBCQUEwQixDQUFDLDBCQUEwQixFQUFFLGVBQWUsQ0FBQyxDQUFDO1lBQy9FLENBQUM7aUJBQU0sQ0FBQztnQkFDTix5RkFBeUY7Z0JBQ3pGLDZGQUE2RjtnQkFDN0YsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsZUFBZ0IsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDO2dCQUMzRixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUM7Z0JBQzlDLGVBQWUsQ0FBQyxDQUFDLEdBQUcsMEJBQTBCLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQztnQkFDdkYsZUFBZSxDQUFDLENBQUMsR0FBRywwQkFBMEIsQ0FBQyxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO2dCQUN2RixJQUFJLENBQUMsMEJBQTBCLENBQUMsZUFBZSxDQUFDLENBQUMsRUFBRSxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDeEUsQ0FBQztZQUVELHNFQUFzRTtZQUN0RSxpRUFBaUU7WUFDakUscUVBQXFFO1lBQ3JFLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ3RDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRTtvQkFDcEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUM7d0JBQ3BCLE1BQU0sRUFBRSxJQUFJO3dCQUNaLGVBQWUsRUFBRSwwQkFBMEI7d0JBQzNDLEtBQUs7d0JBQ0wsUUFBUSxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQywwQkFBMEIsQ0FBQzt3QkFDM0QsS0FBSyxFQUFFLElBQUksQ0FBQyxzQkFBc0I7cUJBQ25DLENBQUMsQ0FBQztnQkFDTCxDQUFDLENBQUMsQ0FBQztZQUNMLENBQUM7UUFDSCxDQUFDLENBQUM7UUFFRiw2RkFBNkY7UUFDckYsZUFBVSxHQUFHLENBQUMsS0FBOEIsRUFBRSxFQUFFO1lBQ3RELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMvQixDQUFDLENBQUM7UUF1d0JGLDBDQUEwQztRQUNsQyxxQkFBZ0IsR0FBRyxDQUFDLEtBQWdCLEVBQUUsRUFBRTtZQUM5QyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ3pCLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFFbEQsSUFBSSxZQUFZLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO29CQUMvRSxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7Z0JBQ3pCLENBQUM7WUFDSCxDQUFDO2lCQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBQzFCLHlGQUF5RjtnQkFDekYsdUVBQXVFO2dCQUN2RSxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDekIsQ0FBQztRQUNILENBQUMsQ0FBQztRQS9uQ0EsSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLGFBQWEsSUFBSSxJQUFJLENBQUMsQ0FBQztRQUN4RSxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxxQkFBcUIsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM3RCxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gscUJBQXFCO1FBQ25CLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQztJQUMzQixDQUFDO0lBRUQsMENBQTBDO0lBQzFDLGNBQWM7UUFDWixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDM0IsQ0FBQztJQUVEOzs7T0FHRztJQUNILGlCQUFpQjtRQUNmLE9BQU8sSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQ2xGLENBQUM7SUFFRCxrRUFBa0U7SUFDbEUsV0FBVyxDQUFDLE9BQWtEO1FBQzVELElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQzdELElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsNEJBQTRCLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQ3JGLElBQUksQ0FBQyw2QkFBNkIsRUFBRSxDQUFDO1FBRXJDLDZGQUE2RjtRQUM3RiwyRkFBMkY7UUFDM0YsK0ZBQStGO1FBQy9GLG9EQUFvRDtRQUNwRCxNQUFNLGVBQWUsR0FBRyxJQUFJLEdBQUcsRUFBZSxDQUFDO1FBQy9DLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDckMsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUN2QyxlQUFlLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzlCLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxlQUFlLENBQUM7UUFDeEMsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsbUJBQW1CLENBQUMsUUFBb0M7UUFDdEQsSUFBSSxDQUFDLGdCQUFnQixHQUFHLFFBQVEsQ0FBQztRQUNqQyxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7O09BR0c7SUFDSCx1QkFBdUIsQ0FBQyxRQUFtQztRQUN6RCxJQUFJLENBQUMsb0JBQW9CLEdBQUcsUUFBUSxDQUFDO1FBQ3JDLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxlQUFlLENBQUMsV0FBa0Q7UUFDaEUsTUFBTSxPQUFPLEdBQUcsYUFBYSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBRTNDLElBQUksT0FBTyxLQUFLLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNsQyxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDdEIsSUFBSSxDQUFDLDJCQUEyQixDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUN0RCxDQUFDO1lBRUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLEVBQUU7Z0JBQ2xDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLFlBQVksRUFBRSwwQkFBMEIsQ0FBQyxDQUFDO2dCQUNyRixPQUFPLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxZQUFZLEVBQUUsMkJBQTJCLENBQUMsQ0FBQztnQkFDdkYsT0FBTyxDQUFDLGdCQUFnQixDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsMEJBQTBCLENBQUMsQ0FBQztZQUMzRixDQUFDLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxpQkFBaUIsR0FBRyxTQUFTLENBQUM7WUFDbkMsSUFBSSxDQUFDLFlBQVksR0FBRyxPQUFPLENBQUM7UUFDOUIsQ0FBQztRQUVELElBQUksT0FBTyxVQUFVLEtBQUssV0FBVyxJQUFJLElBQUksQ0FBQyxZQUFZLFlBQVksVUFBVSxFQUFFLENBQUM7WUFDakYsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsZUFBZSxDQUFDO1FBQzVELENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7T0FFRztJQUNILG1CQUFtQixDQUFDLGVBQTZEO1FBQy9FLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxlQUFlLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQ2hGLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN2QyxJQUFJLGVBQWUsRUFBRSxDQUFDO1lBQ3BCLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxJQUFJLENBQUMsY0FBYztpQkFDM0MsTUFBTSxDQUFDLEVBQUUsQ0FBQztpQkFDVixTQUFTLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLDhCQUE4QixFQUFFLENBQUMsQ0FBQztRQUM1RCxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsc0RBQXNEO0lBQ3RELFVBQVUsQ0FBQyxNQUErQjtRQUN4QyxJQUFJLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQztRQUM3QixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCwrREFBK0Q7SUFDL0QsT0FBTztRQUNMLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFFcEQsOERBQThEO1FBQzlELHVEQUF1RDtRQUN2RCxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDO1lBQ3RCLHdFQUF3RTtZQUN4RSx3RUFBd0U7WUFDeEUsSUFBSSxDQUFDLFlBQVksRUFBRSxNQUFNLEVBQUUsQ0FBQztRQUM5QixDQUFDO1FBRUQsSUFBSSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQztRQUN2QixJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDdkIsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDM0IsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM1QyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQzlCLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDeEIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUN6QixJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDeEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUN2QixJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDNUIsSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7UUFDbkIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzlCLElBQUksQ0FBQyxjQUFjLEdBQUcsU0FBUyxDQUFDO1FBQ2hDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN2QyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDOUIsSUFBSSxDQUFDLGdCQUFnQjtZQUNuQixJQUFJLENBQUMsWUFBWTtnQkFDakIsSUFBSSxDQUFDLGdCQUFnQjtvQkFDckIsSUFBSSxDQUFDLG9CQUFvQjt3QkFDekIsSUFBSSxDQUFDLGdCQUFnQjs0QkFDckIsSUFBSSxDQUFDLE9BQU87Z0NBQ1osSUFBSSxDQUFDLGNBQWM7b0NBQ2pCLElBQUssQ0FBQztJQUNaLENBQUM7SUFFRCw2REFBNkQ7SUFDN0QsVUFBVTtRQUNSLE9BQU8sSUFBSSxDQUFDLG1CQUFtQixFQUFFLElBQUksSUFBSSxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMvRSxDQUFDO0lBRUQsNkRBQTZEO0lBQzdELEtBQUs7UUFDSCxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixJQUFJLEVBQUUsQ0FBQztRQUNqRSxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsRUFBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUMsQ0FBQztRQUNyQyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsRUFBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUMsQ0FBQztJQUN4QyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsYUFBYSxDQUFDLE1BQW1CO1FBQy9CLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDN0UsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNsQyw0QkFBNEIsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDN0MsQ0FBQztJQUNILENBQUM7SUFFRDs7O09BR0c7SUFDSCxZQUFZLENBQUMsTUFBbUI7UUFDOUIsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDdEMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNyQyw0QkFBNEIsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3RELENBQUM7SUFDSCxDQUFDO0lBRUQsdURBQXVEO0lBQ3ZELGFBQWEsQ0FBQyxTQUFvQjtRQUNoQyxJQUFJLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQztRQUM1QixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxtREFBbUQ7SUFDbkQsa0JBQWtCLENBQUMsU0FBc0I7UUFDdkMsSUFBSSxDQUFDLGNBQWMsR0FBRyxTQUFTLENBQUM7SUFDbEMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsbUJBQW1CO1FBQ2pCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUM7UUFDcEYsT0FBTyxFQUFDLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQyxFQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVEOzs7T0FHRztJQUNILG1CQUFtQixDQUFDLEtBQVk7UUFDOUIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEVBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFDLENBQUM7UUFDckMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ25DLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUVuQyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3pCLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwRCxDQUFDO1FBRUQsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsb0JBQW9CLENBQUMsS0FBdUI7UUFDMUMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEtBQUssQ0FBQztRQUMvQixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCw4RUFBOEU7SUFDOUUsNEJBQTRCO1FBQzFCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyx5QkFBeUIsQ0FBQztRQUVoRCxJQUFJLFFBQVEsSUFBSSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDcEMsSUFBSSxDQUFDLDBCQUEwQixDQUFDLElBQUksQ0FBQyw4QkFBOEIsQ0FBQyxRQUFRLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUMzRixDQUFDO0lBQ0gsQ0FBQztJQUVELGtEQUFrRDtJQUMxQyxnQkFBZ0I7UUFDdEIsSUFBSSxDQUFDLHdCQUF3QixDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzVDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUMxQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDdkMsSUFBSSxDQUFDLGNBQWMsRUFBRSxFQUFFLG1CQUFtQixDQUN4QyxhQUFhLEVBQ2Isb0JBQW9CLEVBQ3BCLDJCQUEyQixDQUM1QixDQUFDO0lBQ0osQ0FBQztJQUVELG9EQUFvRDtJQUM1QyxlQUFlO1FBQ3JCLElBQUksQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7SUFDdkIsQ0FBQztJQUVELHdEQUF3RDtJQUNoRCxtQkFBbUI7UUFDekIsSUFBSSxDQUFDLFlBQVksRUFBRSxNQUFNLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUMsZUFBZSxFQUFFLE9BQU8sRUFBRSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFLLENBQUM7SUFDbkQsQ0FBQztJQXNHRDs7O09BR0c7SUFDSyxnQkFBZ0IsQ0FBQyxLQUE4QjtRQUNyRCxnRkFBZ0Y7UUFDaEYsdUZBQXVGO1FBQ3ZGLHFGQUFxRjtRQUNyRixrQ0FBa0M7UUFDbEMsSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUM3QyxPQUFPO1FBQ1QsQ0FBQztRQUVELElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDMUMsSUFBSSxDQUFDLDZCQUE2QixFQUFFLENBQUM7UUFFckMsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDakIsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFpQyxDQUFDLHVCQUF1QjtnQkFDMUUsSUFBSSxDQUFDLHdCQUF3QixDQUFDO1FBQ2xDLENBQUM7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLEVBQUUsQ0FBQztZQUNoQyxPQUFPO1FBQ1QsQ0FBQztRQUVELElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUMsQ0FBQyxDQUFDO1FBRTFDLElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3hCLDhFQUE4RTtZQUM5RSxJQUFJLENBQUMsY0FBYyxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3JDLElBQUksQ0FBQyw0QkFBNEIsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7Z0JBQzVDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDbEMsSUFBSSxDQUFDLHdCQUF3QixFQUFFLENBQUM7Z0JBQ2hDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDNUMsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO2FBQU0sQ0FBQztZQUNOLDZFQUE2RTtZQUM3RSxnRkFBZ0Y7WUFDaEYsZ0NBQWdDO1lBQ2hDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQztZQUNuRCxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMseUJBQXlCLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDOUQsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDO1lBQ25ELElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRTtnQkFDcEIsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUM7b0JBQ2QsTUFBTSxFQUFFLElBQUk7b0JBQ1osUUFBUSxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxlQUFlLENBQUM7b0JBQ2hELFNBQVMsRUFBRSxlQUFlO29CQUMxQixLQUFLO2lCQUNOLENBQUMsQ0FBQztZQUNMLENBQUMsQ0FBQyxDQUFDO1lBQ0gsSUFBSSxDQUFDLHdCQUF3QixFQUFFLENBQUM7WUFDaEMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM1QyxDQUFDO0lBQ0gsQ0FBQztJQUVELG9DQUFvQztJQUM1QixrQkFBa0IsQ0FBQyxLQUE4QjtRQUN2RCxJQUFJLFlBQVksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3hCLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDeEMsQ0FBQztRQUVELElBQUksQ0FBQyw2QkFBNkIsRUFBRSxDQUFDO1FBRXJDLG9EQUFvRDtRQUNwRCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDekMsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQztRQUUxQyxJQUFJLFVBQVUsRUFBRSxDQUFDO1lBQ2YsdUZBQXVGO1lBQ3ZGLDhGQUE4RjtZQUM5RixJQUFJLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLEdBQUcsRUFBRTtnQkFDbEMsVUFBVSxDQUFDLGdCQUFnQixDQUN6QixhQUFhLEVBQ2Isb0JBQW9CLEVBQ3BCLDJCQUEyQixDQUM1QixDQUFDO1lBQ0osQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsSUFBSSxhQUFhLEVBQUUsQ0FBQztZQUNsQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO1lBQ2xDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxVQUF5QixDQUFDO1lBQ2pELE1BQU0sV0FBVyxHQUFHLENBQUMsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMseUJBQXlCLEVBQUUsQ0FBQyxDQUFDO1lBQzNFLE1BQU0sTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU87Z0JBQzFCLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUVwRixrRkFBa0Y7WUFDbEYsTUFBTSxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFFckMseUVBQXlFO1lBQ3pFLHlFQUF5RTtZQUN6RSxJQUFJLENBQUMsaUJBQWlCLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxTQUFTLElBQUksRUFBRSxDQUFDO1lBRXZELHFEQUFxRDtZQUNyRCw0REFBNEQ7WUFDNUQsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLFVBQVUsQ0FDNUIsSUFBSSxDQUFDLFNBQVMsRUFDZCxJQUFJLENBQUMsWUFBWSxFQUNqQixJQUFJLENBQUMsVUFBVSxFQUNmLElBQUksQ0FBQyxlQUFnQixFQUNyQixJQUFJLENBQUMsZ0JBQWdCLElBQUksSUFBSSxFQUM3QixJQUFJLENBQUMsWUFBWSxJQUFJLElBQUksRUFDekIsSUFBSSxDQUFDLHFCQUFxQixFQUMxQixJQUFJLENBQUMsaUJBQWlCLEVBQ3RCLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxJQUFJLElBQUksQ0FDNUIsQ0FBQztZQUNGLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQztZQUV6RSw4RkFBOEY7WUFDOUYsMkZBQTJGO1lBQzNGLDRGQUE0RjtZQUM1RixnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLHVCQUF1QixDQUFDLENBQUM7WUFDMUQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDM0UsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUMsQ0FBQyx1Q0FBdUM7WUFDakYsYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3RCLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxhQUFhLENBQUM7WUFDdkMsSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3hELENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUM7WUFDekMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQyxhQUFhLEdBQUcsU0FBVSxDQUFDO1FBQzNELENBQUM7UUFFRCxzRUFBc0U7UUFDdEUsNkRBQTZEO1FBQzdELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsb0JBQW9CLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDekYsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ssdUJBQXVCLENBQUMsZ0JBQTZCLEVBQUUsS0FBOEI7UUFDM0YsaURBQWlEO1FBQ2pELHVEQUF1RDtRQUN2RCxJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN4QixLQUFLLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDMUIsQ0FBQztRQUVELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNyQyxNQUFNLGVBQWUsR0FBRyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDNUMsTUFBTSxzQkFBc0IsR0FBRyxDQUFDLGVBQWUsSUFBSyxLQUFvQixDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUM7UUFDdEYsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQztRQUN0QyxNQUFNLE1BQU0sR0FBRyxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdEMsTUFBTSxnQkFBZ0IsR0FDcEIsQ0FBQyxlQUFlO1lBQ2hCLElBQUksQ0FBQyxtQkFBbUI7WUFDeEIsSUFBSSxDQUFDLG1CQUFtQixHQUFHLHVCQUF1QixHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNsRSxNQUFNLFdBQVcsR0FBRyxlQUFlO1lBQ2pDLENBQUMsQ0FBQyxnQ0FBZ0MsQ0FBQyxLQUFtQixDQUFDO1lBQ3ZELENBQUMsQ0FBQywrQkFBK0IsQ0FBQyxLQUFtQixDQUFDLENBQUM7UUFFekQsdUZBQXVGO1FBQ3ZGLHVGQUF1RjtRQUN2Rix5RkFBeUY7UUFDekYseUZBQXlGO1FBQ3pGLHlGQUF5RjtRQUN6Rix1Q0FBdUM7UUFDdkMsSUFBSSxNQUFNLElBQUssTUFBc0IsQ0FBQyxTQUFTLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxXQUFXLEVBQUUsQ0FBQztZQUM5RSxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDekIsQ0FBQztRQUVELCtGQUErRjtRQUMvRixJQUFJLFVBQVUsSUFBSSxzQkFBc0IsSUFBSSxnQkFBZ0IsSUFBSSxXQUFXLEVBQUUsQ0FBQztZQUM1RSxPQUFPO1FBQ1QsQ0FBQztRQUVELHlGQUF5RjtRQUN6Rix1RkFBdUY7UUFDdkYsZ0JBQWdCO1FBQ2hCLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUN6QixNQUFNLFVBQVUsR0FBRyxXQUFXLENBQUMsS0FBZ0MsQ0FBQztZQUNoRSxJQUFJLENBQUMsd0JBQXdCLEdBQUcsVUFBVSxDQUFDLHVCQUF1QixJQUFJLEVBQUUsQ0FBQztZQUN6RSxVQUFVLENBQUMsdUJBQXVCLEdBQUcsYUFBYSxDQUFDO1FBQ3JELENBQUM7UUFFRCxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztRQUN2QixJQUFJLENBQUMsbUJBQW1CLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUU3QyxpRUFBaUU7UUFDakUsK0ZBQStGO1FBQy9GLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBQ2pFLElBQUksQ0FBQyx3QkFBd0IsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDaEcsSUFBSSxDQUFDLHNCQUFzQixHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUMxRixJQUFJLENBQUMsbUJBQW1CLEdBQUcsSUFBSSxDQUFDLGlCQUFpQjthQUM5QyxRQUFRLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO2FBQy9CLFNBQVMsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztRQUUvRCxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQzFCLElBQUksQ0FBQyxhQUFhLEdBQUcsb0JBQW9CLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDbkUsQ0FBQztRQUVELDRGQUE0RjtRQUM1Riw4RkFBOEY7UUFDOUYsd0VBQXdFO1FBQ3hFLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztRQUM5QyxJQUFJLENBQUMsd0JBQXdCO1lBQzNCLGVBQWUsSUFBSSxlQUFlLENBQUMsUUFBUSxJQUFJLENBQUMsZUFBZSxDQUFDLFNBQVM7Z0JBQ3ZFLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBQztnQkFDZCxDQUFDLENBQUMsSUFBSSxDQUFDLDRCQUE0QixDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsZ0JBQWdCLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkYsTUFBTSxlQUFlLEdBQ25CLENBQUMsSUFBSSxDQUFDLHFCQUFxQjtZQUMzQixJQUFJLENBQUMseUJBQXlCO2dCQUM1QixJQUFJLENBQUMseUJBQXlCLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUMzQyxJQUFJLENBQUMsc0JBQXNCLEdBQUcsRUFBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUMsQ0FBQztRQUMzQyxJQUFJLENBQUMscUNBQXFDLEdBQUcsRUFBQyxDQUFDLEVBQUUsZUFBZSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsZUFBZSxDQUFDLENBQUMsRUFBQyxDQUFDO1FBQzFGLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ2pDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3BELENBQUM7SUFFRCwyRkFBMkY7SUFDbkYscUJBQXFCLENBQUMsS0FBOEI7UUFDMUQsaUZBQWlGO1FBQ2pGLDZGQUE2RjtRQUM3Riw4RkFBOEY7UUFDOUYseURBQXlEO1FBQ3pELGdCQUFnQixDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsSUFBSSxFQUFFLHVCQUF1QixDQUFDLENBQUM7UUFDbkUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFXLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXZFLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUN2QixJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztRQUMzQixJQUFJLENBQUMsZUFBZTtZQUNsQixJQUFJLENBQUMsYUFBYTtnQkFDbEIsSUFBSSxDQUFDLFlBQVk7b0JBQ2pCLElBQUksQ0FBQyxpQkFBaUI7d0JBQ3BCLFNBQVMsQ0FBQztRQUVkLHVFQUF1RTtRQUN2RSxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUU7WUFDcEIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGNBQWUsQ0FBQztZQUN2QyxNQUFNLFlBQVksR0FBRyxTQUFTLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2xELE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM5RCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsZUFBZSxDQUFDLENBQUM7WUFDeEQsTUFBTSxzQkFBc0IsR0FBRyxTQUFTLENBQUMsZ0JBQWdCLENBQ3ZELGVBQWUsQ0FBQyxDQUFDLEVBQ2pCLGVBQWUsQ0FBQyxDQUFDLENBQ2xCLENBQUM7WUFFRixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQUUsS0FBSyxFQUFDLENBQUMsQ0FBQztZQUM3RSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztnQkFDaEIsSUFBSSxFQUFFLElBQUk7Z0JBQ1YsWUFBWTtnQkFDWixhQUFhLEVBQUUsSUFBSSxDQUFDLGFBQWE7Z0JBQ2pDLFNBQVMsRUFBRSxTQUFTO2dCQUNwQixpQkFBaUIsRUFBRSxJQUFJLENBQUMsaUJBQWlCO2dCQUN6QyxzQkFBc0I7Z0JBQ3RCLFFBQVE7Z0JBQ1IsU0FBUyxFQUFFLGVBQWU7Z0JBQzFCLEtBQUs7YUFDTixDQUFDLENBQUM7WUFDSCxTQUFTLENBQUMsSUFBSSxDQUNaLElBQUksRUFDSixZQUFZLEVBQ1osSUFBSSxDQUFDLGFBQWEsRUFDbEIsSUFBSSxDQUFDLGlCQUFpQixFQUN0QixzQkFBc0IsRUFDdEIsUUFBUSxFQUNSLGVBQWUsRUFDZixLQUFLLENBQ04sQ0FBQztZQUNGLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDO1FBQy9DLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7T0FHRztJQUNLLDBCQUEwQixDQUFDLEVBQUMsQ0FBQyxFQUFFLENBQUMsRUFBUSxFQUFFLEVBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFRO1FBQ3pFLHFEQUFxRDtRQUNyRCxJQUFJLFlBQVksR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsZ0NBQWdDLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUV2Rix1RkFBdUY7UUFDdkYseUZBQXlGO1FBQ3pGLHlGQUF5RjtRQUN6Riw2QkFBNkI7UUFDN0IsSUFDRSxDQUFDLFlBQVk7WUFDYixJQUFJLENBQUMsY0FBYyxLQUFLLElBQUksQ0FBQyxpQkFBaUI7WUFDOUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFDN0MsQ0FBQztZQUNELFlBQVksR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUM7UUFDeEMsQ0FBQztRQUVELElBQUksWUFBWSxJQUFJLFlBQVksS0FBSyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDekQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFO2dCQUNwQixtREFBbUQ7Z0JBQ25ELElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLGNBQWUsRUFBQyxDQUFDLENBQUM7Z0JBQ2hFLElBQUksQ0FBQyxjQUFlLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNoQyxzREFBc0Q7Z0JBQ3RELElBQUksQ0FBQyxjQUFjLEdBQUcsWUFBYSxDQUFDO2dCQUNwQyxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FDdkIsSUFBSSxFQUNKLENBQUMsRUFDRCxDQUFDLEVBQ0QsWUFBWSxLQUFLLElBQUksQ0FBQyxpQkFBaUI7b0JBQ3JDLHNFQUFzRTtvQkFDdEUsc0RBQXNEO29CQUN0RCxZQUFZLENBQUMsZUFBZTtvQkFDNUIsQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhO29CQUNwQixDQUFDLENBQUMsU0FBUyxDQUNkLENBQUM7Z0JBQ0YsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7b0JBQ2hCLElBQUksRUFBRSxJQUFJO29CQUNWLFNBQVMsRUFBRSxZQUFhO29CQUN4QixZQUFZLEVBQUUsWUFBYSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUM7aUJBQy9DLENBQUMsQ0FBQztZQUNMLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELHNFQUFzRTtRQUN0RSxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDO1lBQ3RCLElBQUksQ0FBQyxjQUFlLENBQUMsMEJBQTBCLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzVELElBQUksQ0FBQyxjQUFlLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1lBRXhFLElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7Z0JBQzNCLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDcEMsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLElBQUksQ0FBQyxzQkFBc0IsQ0FDekIsQ0FBQyxHQUFHLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDLEVBQ25DLENBQUMsR0FBRyxJQUFJLENBQUMsd0JBQXdCLENBQUMsQ0FBQyxDQUNwQyxDQUFDO1lBQ0osQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssNEJBQTRCO1FBQ2xDLG9FQUFvRTtRQUNwRSxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3BCLE9BQU8sT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQzNCLENBQUM7UUFFRCxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFFbEUseURBQXlEO1FBQ3pELElBQUksQ0FBQyxRQUFTLENBQUMsUUFBUSxDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFFOUMsZ0RBQWdEO1FBQ2hELElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUV2RSwwRkFBMEY7UUFDMUYsMEZBQTBGO1FBQzFGLDRGQUE0RjtRQUM1RixxQ0FBcUM7UUFDckMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVMsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBRXhELElBQUksUUFBUSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ25CLE9BQU8sT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQzNCLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsR0FBRyxFQUFFO1lBQ3pDLE9BQU8sSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQzNCLE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQyxLQUFzQixFQUFFLEVBQUU7b0JBQzFDLElBQ0UsQ0FBQyxLQUFLO3dCQUNOLENBQUMsSUFBSSxDQUFDLFFBQVE7NEJBQ1osZUFBZSxDQUFDLEtBQUssQ0FBQyxLQUFLLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTzs0QkFDaEQsS0FBSyxDQUFDLFlBQVksS0FBSyxXQUFXLENBQUMsRUFDckMsQ0FBQzt3QkFDRCxJQUFJLENBQUMsUUFBUSxFQUFFLG1CQUFtQixDQUFDLGVBQWUsRUFBRSxPQUFPLENBQUMsQ0FBQzt3QkFDN0QsT0FBTyxFQUFFLENBQUM7d0JBQ1YsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDO29CQUN4QixDQUFDO2dCQUNILENBQUMsQ0FBdUMsQ0FBQztnQkFFekMseUZBQXlGO2dCQUN6Rix3RkFBd0Y7Z0JBQ3hGLG1FQUFtRTtnQkFDbkUsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDLE9BQW1CLEVBQUUsUUFBUSxHQUFHLEdBQUcsQ0FBQyxDQUFDO2dCQUNoRSxJQUFJLENBQUMsUUFBUyxDQUFDLGdCQUFnQixDQUFDLGVBQWUsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUM1RCxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELDJGQUEyRjtJQUNuRix5QkFBeUI7UUFDL0IsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUM7UUFDcEQsTUFBTSxtQkFBbUIsR0FBRyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDbEYsSUFBSSxXQUF3QixDQUFDO1FBRTdCLElBQUksbUJBQW1CLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsZUFBZSxHQUFHLGlCQUFrQixDQUFDLGFBQWEsQ0FBQyxrQkFBa0IsQ0FDeEUsbUJBQW1CLEVBQ25CLGlCQUFrQixDQUFDLE9BQU8sQ0FDM0IsQ0FBQztZQUNGLElBQUksQ0FBQyxlQUFlLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDckMsV0FBVyxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsZUFBZSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNsRSxDQUFDO2FBQU0sQ0FBQztZQUNOLFdBQVcsR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ2pELENBQUM7UUFFRCx1REFBdUQ7UUFDdkQsbURBQW1EO1FBQ25ELFdBQVcsQ0FBQyxLQUFLLENBQUMsYUFBYSxHQUFHLE1BQU0sQ0FBQztRQUN6QyxXQUFXLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBQ2xELE9BQU8sV0FBVyxDQUFDO0lBQ3JCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssNEJBQTRCLENBQ2xDLFdBQW9CLEVBQ3BCLGdCQUE2QixFQUM3QixLQUE4QjtRQUU5QixNQUFNLGFBQWEsR0FBRyxnQkFBZ0IsS0FBSyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDO1FBQ3ZGLE1BQU0sYUFBYSxHQUFHLGFBQWEsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLHFCQUFxQixFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQztRQUMxRixNQUFNLEtBQUssR0FBRyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztRQUNuRSxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsMEJBQTBCLEVBQUUsQ0FBQztRQUN6RCxNQUFNLENBQUMsR0FBRyxLQUFLLENBQUMsS0FBSyxHQUFHLGFBQWEsQ0FBQyxJQUFJLEdBQUcsY0FBYyxDQUFDLElBQUksQ0FBQztRQUNqRSxNQUFNLENBQUMsR0FBRyxLQUFLLENBQUMsS0FBSyxHQUFHLGFBQWEsQ0FBQyxHQUFHLEdBQUcsY0FBYyxDQUFDLEdBQUcsQ0FBQztRQUUvRCxPQUFPO1lBQ0wsQ0FBQyxFQUFFLGFBQWEsQ0FBQyxJQUFJLEdBQUcsV0FBVyxDQUFDLElBQUksR0FBRyxDQUFDO1lBQzVDLENBQUMsRUFBRSxhQUFhLENBQUMsR0FBRyxHQUFHLFdBQVcsQ0FBQyxHQUFHLEdBQUcsQ0FBQztTQUMzQyxDQUFDO0lBQ0osQ0FBQztJQUVELHFFQUFxRTtJQUM3RCx5QkFBeUIsQ0FBQyxLQUE4QjtRQUM5RCxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsMEJBQTBCLEVBQUUsQ0FBQztRQUN6RCxNQUFNLEtBQUssR0FBRyxZQUFZLENBQUMsS0FBSyxDQUFDO1lBQy9CLENBQUMsQ0FBQyw0RkFBNEY7Z0JBQzVGLDJGQUEyRjtnQkFDM0YsMEZBQTBGO2dCQUMxRixzRkFBc0Y7Z0JBQ3RGLG9GQUFvRjtnQkFDcEYsdUZBQXVGO2dCQUN2RixxRkFBcUY7Z0JBQ3JGLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBQztZQUNyRSxDQUFDLENBQUMsS0FBSyxDQUFDO1FBRVYsTUFBTSxDQUFDLEdBQUcsS0FBSyxDQUFDLEtBQUssR0FBRyxjQUFjLENBQUMsSUFBSSxDQUFDO1FBQzVDLE1BQU0sQ0FBQyxHQUFHLEtBQUssQ0FBQyxLQUFLLEdBQUcsY0FBYyxDQUFDLEdBQUcsQ0FBQztRQUUzQyx1RkFBdUY7UUFDdkYsb0JBQW9CO1FBQ3BCLElBQUksSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDMUIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3ZELElBQUksU0FBUyxFQUFFLENBQUM7Z0JBQ2QsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUN4RCxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDZixRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDZixPQUFPLFFBQVEsQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFDdkQsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLEVBQUMsQ0FBQyxFQUFFLENBQUMsRUFBQyxDQUFDO0lBQ2hCLENBQUM7SUFFRCxzRkFBc0Y7SUFDOUUsOEJBQThCLENBQUMsS0FBWTtRQUNqRCxNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDcEYsSUFBSSxFQUFDLENBQUMsRUFBRSxDQUFDLEVBQUMsR0FBRyxJQUFJLENBQUMsaUJBQWlCO1lBQ2pDLENBQUMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsZUFBZ0IsRUFBRSxJQUFJLENBQUMsd0JBQXdCLENBQUM7WUFDM0YsQ0FBQyxDQUFDLEtBQUssQ0FBQztRQUVWLElBQUksSUFBSSxDQUFDLFFBQVEsS0FBSyxHQUFHLElBQUksaUJBQWlCLEtBQUssR0FBRyxFQUFFLENBQUM7WUFDdkQsQ0FBQztnQkFDQyxJQUFJLENBQUMscUJBQXFCLENBQUMsQ0FBQztvQkFDNUIsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ25FLENBQUM7YUFBTSxJQUFJLElBQUksQ0FBQyxRQUFRLEtBQUssR0FBRyxJQUFJLGlCQUFpQixLQUFLLEdBQUcsRUFBRSxDQUFDO1lBQzlELENBQUM7Z0JBQ0MsSUFBSSxDQUFDLHFCQUFxQixDQUFDLENBQUM7b0JBQzVCLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuRSxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDdkIsNEZBQTRGO1lBQzVGLDRFQUE0RTtZQUM1RSxNQUFNLEVBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsaUJBQWlCO2dCQUN0RCxDQUFDLENBQUMsSUFBSSxDQUFDLHdCQUF3QjtnQkFDL0IsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFDLENBQUM7WUFFakIsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQztZQUN4QyxNQUFNLEVBQUMsS0FBSyxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsYUFBYSxFQUFDLEdBQUcsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQzVFLE1BQU0sSUFBSSxHQUFHLFlBQVksQ0FBQyxHQUFHLEdBQUcsT0FBTyxDQUFDO1lBQ3hDLE1BQU0sSUFBSSxHQUFHLFlBQVksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxhQUFhLEdBQUcsT0FBTyxDQUFDLENBQUM7WUFDN0QsTUFBTSxJQUFJLEdBQUcsWUFBWSxDQUFDLElBQUksR0FBRyxPQUFPLENBQUM7WUFDekMsTUFBTSxJQUFJLEdBQUcsWUFBWSxDQUFDLEtBQUssR0FBRyxDQUFDLFlBQVksR0FBRyxPQUFPLENBQUMsQ0FBQztZQUUzRCxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDekIsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzNCLENBQUM7UUFFRCxPQUFPLEVBQUMsQ0FBQyxFQUFFLENBQUMsRUFBQyxDQUFDO0lBQ2hCLENBQUM7SUFFRCxnR0FBZ0c7SUFDeEYsNEJBQTRCLENBQUMscUJBQTRCO1FBQy9ELE1BQU0sRUFBQyxDQUFDLEVBQUUsQ0FBQyxFQUFDLEdBQUcscUJBQXFCLENBQUM7UUFDckMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLHNCQUFzQixDQUFDO1FBQzFDLE1BQU0sdUJBQXVCLEdBQUcsSUFBSSxDQUFDLHFDQUFxQyxDQUFDO1FBRTNFLG1GQUFtRjtRQUNuRixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyx1QkFBdUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4RCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyx1QkFBdUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUV4RCxpRkFBaUY7UUFDakYscUZBQXFGO1FBQ3JGLHlGQUF5RjtRQUN6RiwrRUFBK0U7UUFDL0UsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQywrQkFBK0IsRUFBRSxDQUFDO1lBQzNELEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLHVCQUF1QixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNqRCx1QkFBdUIsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ2hDLENBQUM7UUFFRCxJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLCtCQUErQixFQUFFLENBQUM7WUFDM0QsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsdUJBQXVCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2pELHVCQUF1QixDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDaEMsQ0FBQztRQUVELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELHNGQUFzRjtJQUM5RSw2QkFBNkI7UUFDbkMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDekMsT0FBTztRQUNULENBQUM7UUFFRCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFFcEUsSUFBSSxZQUFZLEtBQUssSUFBSSxDQUFDLDBCQUEwQixFQUFFLENBQUM7WUFDckQsSUFBSSxDQUFDLDBCQUEwQixHQUFHLFlBQVksQ0FBQztZQUMvQyw0QkFBNEIsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQ2hFLENBQUM7SUFDSCxDQUFDO0lBRUQsd0VBQXdFO0lBQ2hFLDJCQUEyQixDQUFDLE9BQW9CO1FBQ3RELE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLFlBQVksRUFBRSwwQkFBMEIsQ0FBQyxDQUFDO1FBQ3hGLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLFlBQVksRUFBRSwyQkFBMkIsQ0FBQyxDQUFDO1FBQzFGLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixFQUFFLDBCQUEwQixDQUFDLENBQUM7SUFDOUYsQ0FBQztJQUVEOzs7O09BSUc7SUFDSywwQkFBMEIsQ0FBQyxDQUFTLEVBQUUsQ0FBUztRQUNyRCxNQUFNLEtBQUssR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUM3QixNQUFNLFNBQVMsR0FBRyxZQUFZLENBQUMsQ0FBQyxHQUFHLEtBQUssRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUM7UUFDckQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUM7UUFFdkMsa0ZBQWtGO1FBQ2xGLGtFQUFrRTtRQUNsRSw2RUFBNkU7UUFDN0UsSUFBSSxJQUFJLENBQUMsaUJBQWlCLElBQUksSUFBSSxFQUFFLENBQUM7WUFDbkMsSUFBSSxDQUFDLGlCQUFpQjtnQkFDcEIsTUFBTSxDQUFDLFNBQVMsSUFBSSxNQUFNLENBQUMsU0FBUyxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQzNFLENBQUM7UUFFRCx3RkFBd0Y7UUFDeEYsdUZBQXVGO1FBQ3ZGLDBDQUEwQztRQUMxQyxNQUFNLENBQUMsU0FBUyxHQUFHLGlCQUFpQixDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUMxRSxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLHNCQUFzQixDQUFDLENBQVMsRUFBRSxDQUFTO1FBQ2pELGdHQUFnRztRQUNoRyxtRkFBbUY7UUFDbkYsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztRQUM5RixNQUFNLFNBQVMsR0FBRyxZQUFZLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxRQUFTLENBQUMsWUFBWSxDQUFDLGlCQUFpQixDQUFDLFNBQVMsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7SUFDOUUsQ0FBQztJQUVEOzs7T0FHRztJQUNLLGdCQUFnQixDQUFDLGVBQXNCO1FBQzdDLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQztRQUVsRCxJQUFJLGNBQWMsRUFBRSxDQUFDO1lBQ25CLE9BQU8sRUFBQyxDQUFDLEVBQUUsZUFBZSxDQUFDLENBQUMsR0FBRyxjQUFjLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxlQUFlLENBQUMsQ0FBQyxHQUFHLGNBQWMsQ0FBQyxDQUFDLEVBQUMsQ0FBQztRQUM1RixDQUFDO1FBRUQsT0FBTyxFQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBQyxDQUFDO0lBQ3RCLENBQUM7SUFFRCw2RkFBNkY7SUFDckYsd0JBQXdCO1FBQzlCLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLFlBQVksR0FBRyxTQUFTLENBQUM7UUFDbkQsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ2hDLENBQUM7SUFFRDs7O09BR0c7SUFDSyw4QkFBOEI7UUFDcEMsSUFBSSxFQUFDLENBQUMsRUFBRSxDQUFDLEVBQUMsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUM7UUFFcEMsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3hFLE9BQU87UUFDVCxDQUFDO1FBRUQsa0ZBQWtGO1FBQ2xGLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUM5RCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUVuRSx3RkFBd0Y7UUFDeEYsd0ZBQXdGO1FBQ3hGLElBQ0UsQ0FBQyxZQUFZLENBQUMsS0FBSyxLQUFLLENBQUMsSUFBSSxZQUFZLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQztZQUN2RCxDQUFDLFdBQVcsQ0FBQyxLQUFLLEtBQUssQ0FBQyxJQUFJLFdBQVcsQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUFDLEVBQ3JELENBQUM7WUFDRCxPQUFPO1FBQ1QsQ0FBQztRQUVELE1BQU0sWUFBWSxHQUFHLFlBQVksQ0FBQyxJQUFJLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQztRQUMxRCxNQUFNLGFBQWEsR0FBRyxXQUFXLENBQUMsS0FBSyxHQUFHLFlBQVksQ0FBQyxLQUFLLENBQUM7UUFDN0QsTUFBTSxXQUFXLEdBQUcsWUFBWSxDQUFDLEdBQUcsR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDO1FBQ3ZELE1BQU0sY0FBYyxHQUFHLFdBQVcsQ0FBQyxNQUFNLEdBQUcsWUFBWSxDQUFDLE1BQU0sQ0FBQztRQUVoRSw4REFBOEQ7UUFDOUQsMkRBQTJEO1FBQzNELElBQUksWUFBWSxDQUFDLEtBQUssR0FBRyxXQUFXLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDM0MsSUFBSSxZQUFZLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ3JCLENBQUMsSUFBSSxZQUFZLENBQUM7WUFDcEIsQ0FBQztZQUVELElBQUksYUFBYSxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUN0QixDQUFDLElBQUksYUFBYSxDQUFDO1lBQ3JCLENBQUM7UUFDSCxDQUFDO2FBQU0sQ0FBQztZQUNOLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDUixDQUFDO1FBRUQsK0RBQStEO1FBQy9ELDBEQUEwRDtRQUMxRCxJQUFJLFlBQVksQ0FBQyxNQUFNLEdBQUcsV0FBVyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzdDLElBQUksV0FBVyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUNwQixDQUFDLElBQUksV0FBVyxDQUFDO1lBQ25CLENBQUM7WUFFRCxJQUFJLGNBQWMsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDdkIsQ0FBQyxJQUFJLGNBQWMsQ0FBQztZQUN0QixDQUFDO1FBQ0gsQ0FBQzthQUFNLENBQUM7WUFDTixDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ1IsQ0FBQztRQUVELElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNyRSxJQUFJLENBQUMsbUJBQW1CLENBQUMsRUFBQyxDQUFDLEVBQUUsQ0FBQyxFQUFDLENBQUMsQ0FBQztRQUNuQyxDQUFDO0lBQ0gsQ0FBQztJQUVELDBEQUEwRDtJQUNsRCxrQkFBa0IsQ0FBQyxLQUE4QjtRQUN2RCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDO1FBRWxDLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDOUIsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO2FBQU0sSUFBSSxZQUFZLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUMvQixPQUFPLEtBQUssQ0FBQyxLQUFLLENBQUM7UUFDckIsQ0FBQztRQUVELE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDakMsQ0FBQztJQUVELHVGQUF1RjtJQUMvRSxlQUFlLENBQUMsS0FBWTtRQUNsQyxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFbkUsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3JCLE1BQU0sTUFBTSxHQUFHLGVBQWUsQ0FBeUIsS0FBSyxDQUFFLENBQUM7WUFFL0QsaUZBQWlGO1lBQ2pGLGtGQUFrRjtZQUNsRixJQUNFLElBQUksQ0FBQyxhQUFhO2dCQUNsQixNQUFNLEtBQUssSUFBSSxDQUFDLGdCQUFnQjtnQkFDaEMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFDdEMsQ0FBQztnQkFDRCxhQUFhLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxnQkFBZ0IsQ0FBQyxHQUFHLEVBQUUsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDakYsQ0FBQztZQUVELElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLElBQUksZ0JBQWdCLENBQUMsSUFBSSxDQUFDO1lBQ3RELElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLElBQUksZ0JBQWdCLENBQUMsR0FBRyxDQUFDO1lBRXJELDhFQUE4RTtZQUM5RSx5RUFBeUU7WUFDekUsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztnQkFDekIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUMsSUFBSSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUM7Z0JBQ2pELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLElBQUksZ0JBQWdCLENBQUMsR0FBRyxDQUFDO2dCQUNoRCxJQUFJLENBQUMsMEJBQTBCLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDcEYsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsZ0RBQWdEO0lBQ3hDLDBCQUEwQjtRQUNoQyxPQUFPLENBQ0wsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLGNBQWM7WUFDbkUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLHlCQUF5QixFQUFFLENBQ2xELENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSyxjQUFjO1FBQ3BCLElBQUksSUFBSSxDQUFDLGlCQUFpQixLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3pDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxjQUFjLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQzdELENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztJQUNoQyxDQUFDO0lBRUQsdUVBQXVFO0lBQy9ELHlCQUF5QixDQUMvQixhQUEwQixFQUMxQixVQUE2QjtRQUU3QixNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxpQkFBaUIsSUFBSSxRQUFRLENBQUM7UUFFNUQsSUFBSSxnQkFBZ0IsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUNsQyxPQUFPLGFBQWEsQ0FBQztRQUN2QixDQUFDO1FBRUQsSUFBSSxnQkFBZ0IsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUNsQyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO1lBRW5DLDJEQUEyRDtZQUMzRCxnRUFBZ0U7WUFDaEUsZ0ZBQWdGO1lBQ2hGLE9BQU8sQ0FDTCxVQUFVO2dCQUNWLFdBQVcsQ0FBQyxpQkFBaUI7Z0JBQzVCLFdBQW1CLENBQUMsdUJBQXVCO2dCQUMzQyxXQUFtQixDQUFDLG9CQUFvQjtnQkFDeEMsV0FBbUIsQ0FBQyxtQkFBbUI7Z0JBQ3hDLFdBQVcsQ0FBQyxJQUFJLENBQ2pCLENBQUM7UUFDSixDQUFDO1FBRUQsT0FBTyxhQUFhLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUN6QyxDQUFDO0lBRUQsaUVBQWlFO0lBQ3pELGVBQWU7UUFDckIsdUVBQXVFO1FBQ3ZFLHNFQUFzRTtRQUN0RSxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDbEYsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsUUFBUTtnQkFDL0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFTLENBQUMscUJBQXFCLEVBQUU7Z0JBQ3hDLENBQUMsQ0FBQyxJQUFJLENBQUMsZUFBZ0IsQ0FBQztRQUM1QixDQUFDO1FBRUQsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO0lBQzNCLENBQUM7SUFpQkQsb0RBQW9EO0lBQzVDLGdCQUFnQixDQUFDLEtBQVk7UUFDbkMsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRTtZQUNqQyxPQUFPLEtBQUssQ0FBQyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxLQUFLLE1BQU0sSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxNQUFjLENBQUMsQ0FBQyxDQUFDO1FBQzVGLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGO0FBRUQsc0RBQXNEO0FBQ3RELFNBQVMsS0FBSyxDQUFDLEtBQWEsRUFBRSxHQUFXLEVBQUUsR0FBVztJQUNwRCxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFDN0MsQ0FBQztBQUVELG9EQUFvRDtBQUNwRCxTQUFTLFlBQVksQ0FBQyxLQUE4QjtJQUNsRCx3RkFBd0Y7SUFDeEYsdUZBQXVGO0lBQ3ZGLGdFQUFnRTtJQUNoRSxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxDQUFDO0FBQy9CLENBQUM7QUFFRCx1RUFBdUU7QUFDdkUsU0FBUyxvQkFBb0IsQ0FBQyxLQUFZO0lBQ3hDLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztBQUN6QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7aXNGYWtlTW91c2Vkb3duRnJvbVNjcmVlblJlYWRlciwgaXNGYWtlVG91Y2hzdGFydEZyb21TY3JlZW5SZWFkZXJ9IGZyb20gJ0Bhbmd1bGFyL2Nkay9hMTF5JztcbmltcG9ydCB7RGlyZWN0aW9ufSBmcm9tICdAYW5ndWxhci9jZGsvYmlkaSc7XG5pbXBvcnQge2NvZXJjZUVsZW1lbnR9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2VyY2lvbic7XG5pbXBvcnQge1xuICBfZ2V0RXZlbnRUYXJnZXQsXG4gIF9nZXRTaGFkb3dSb290LFxuICBub3JtYWxpemVQYXNzaXZlTGlzdGVuZXJPcHRpb25zLFxufSBmcm9tICdAYW5ndWxhci9jZGsvcGxhdGZvcm0nO1xuaW1wb3J0IHtWaWV3cG9ydFJ1bGVyfSBmcm9tICdAYW5ndWxhci9jZGsvc2Nyb2xsaW5nJztcbmltcG9ydCB7XG4gIEVsZW1lbnRSZWYsXG4gIEVtYmVkZGVkVmlld1JlZixcbiAgTmdab25lLFxuICBUZW1wbGF0ZVJlZixcbiAgVmlld0NvbnRhaW5lclJlZixcbiAgc2lnbmFsLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7T2JzZXJ2YWJsZSwgU3ViamVjdCwgU3Vic2NyaXB0aW9ufSBmcm9tICdyeGpzJztcbmltcG9ydCB7ZGVlcENsb25lTm9kZX0gZnJvbSAnLi9kb20vY2xvbmUtbm9kZSc7XG5pbXBvcnQge2FkanVzdERvbVJlY3QsIGdldE11dGFibGVDbGllbnRSZWN0fSBmcm9tICcuL2RvbS9kb20tcmVjdCc7XG5pbXBvcnQge1BhcmVudFBvc2l0aW9uVHJhY2tlcn0gZnJvbSAnLi9kb20vcGFyZW50LXBvc2l0aW9uLXRyYWNrZXInO1xuaW1wb3J0IHtnZXRSb290Tm9kZX0gZnJvbSAnLi9kb20vcm9vdC1ub2RlJztcbmltcG9ydCB7XG4gIERyYWdDU1NTdHlsZURlY2xhcmF0aW9uLFxuICBjb21iaW5lVHJhbnNmb3JtcyxcbiAgZ2V0VHJhbnNmb3JtLFxuICB0b2dnbGVOYXRpdmVEcmFnSW50ZXJhY3Rpb25zLFxuICB0b2dnbGVWaXNpYmlsaXR5LFxufSBmcm9tICcuL2RvbS9zdHlsaW5nJztcbmltcG9ydCB7RHJhZ0Ryb3BSZWdpc3RyeX0gZnJvbSAnLi9kcmFnLWRyb3AtcmVnaXN0cnknO1xuaW1wb3J0IHR5cGUge0Ryb3BMaXN0UmVmfSBmcm9tICcuL2Ryb3AtbGlzdC1yZWYnO1xuaW1wb3J0IHtEcmFnUHJldmlld1RlbXBsYXRlLCBQcmV2aWV3UmVmfSBmcm9tICcuL3ByZXZpZXctcmVmJztcblxuLyoqIE9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIHRvIGNvbmZpZ3VyZSB0aGUgYmVoYXZpb3Igb2YgRHJhZ1JlZi4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRHJhZ1JlZkNvbmZpZyB7XG4gIC8qKlxuICAgKiBNaW5pbXVtIGFtb3VudCBvZiBwaXhlbHMgdGhhdCB0aGUgdXNlciBzaG91bGRcbiAgICogZHJhZywgYmVmb3JlIHRoZSBDREsgaW5pdGlhdGVzIGEgZHJhZyBzZXF1ZW5jZS5cbiAgICovXG4gIGRyYWdTdGFydFRocmVzaG9sZDogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBBbW91bnQgdGhlIHBpeGVscyB0aGUgdXNlciBzaG91bGQgZHJhZyBiZWZvcmUgdGhlIENES1xuICAgKiBjb25zaWRlcnMgdGhlbSB0byBoYXZlIGNoYW5nZWQgdGhlIGRyYWcgZGlyZWN0aW9uLlxuICAgKi9cbiAgcG9pbnRlckRpcmVjdGlvbkNoYW5nZVRocmVzaG9sZDogbnVtYmVyO1xuXG4gIC8qKiBgei1pbmRleGAgZm9yIHRoZSBhYnNvbHV0ZWx5LXBvc2l0aW9uZWQgZWxlbWVudHMgdGhhdCBhcmUgY3JlYXRlZCBieSB0aGUgZHJhZyBpdGVtLiAqL1xuICB6SW5kZXg/OiBudW1iZXI7XG5cbiAgLyoqIFJlZiB0aGF0IHRoZSBjdXJyZW50IGRyYWcgaXRlbSBpcyBuZXN0ZWQgaW4uICovXG4gIHBhcmVudERyYWdSZWY/OiBEcmFnUmVmO1xufVxuXG4vKiogT3B0aW9ucyB0aGF0IGNhbiBiZSB1c2VkIHRvIGJpbmQgYSBwYXNzaXZlIGV2ZW50IGxpc3RlbmVyLiAqL1xuY29uc3QgcGFzc2l2ZUV2ZW50TGlzdGVuZXJPcHRpb25zID0gbm9ybWFsaXplUGFzc2l2ZUxpc3RlbmVyT3B0aW9ucyh7cGFzc2l2ZTogdHJ1ZX0pO1xuXG4vKiogT3B0aW9ucyB0aGF0IGNhbiBiZSB1c2VkIHRvIGJpbmQgYW4gYWN0aXZlIGV2ZW50IGxpc3RlbmVyLiAqL1xuY29uc3QgYWN0aXZlRXZlbnRMaXN0ZW5lck9wdGlvbnMgPSBub3JtYWxpemVQYXNzaXZlTGlzdGVuZXJPcHRpb25zKHtwYXNzaXZlOiBmYWxzZX0pO1xuXG4vKiogRXZlbnQgb3B0aW9ucyB0aGF0IGNhbiBiZSB1c2VkIHRvIGJpbmQgYW4gYWN0aXZlLCBjYXB0dXJpbmcgZXZlbnQuICovXG5jb25zdCBhY3RpdmVDYXB0dXJpbmdFdmVudE9wdGlvbnMgPSBub3JtYWxpemVQYXNzaXZlTGlzdGVuZXJPcHRpb25zKHtcbiAgcGFzc2l2ZTogZmFsc2UsXG4gIGNhcHR1cmU6IHRydWUsXG59KTtcblxuLyoqXG4gKiBUaW1lIGluIG1pbGxpc2Vjb25kcyBmb3Igd2hpY2ggdG8gaWdub3JlIG1vdXNlIGV2ZW50cywgYWZ0ZXJcbiAqIHJlY2VpdmluZyBhIHRvdWNoIGV2ZW50LiBVc2VkIHRvIGF2b2lkIGRvaW5nIGRvdWJsZSB3b3JrIGZvclxuICogdG91Y2ggZGV2aWNlcyB3aGVyZSB0aGUgYnJvd3NlciBmaXJlcyBmYWtlIG1vdXNlIGV2ZW50cywgaW5cbiAqIGFkZGl0aW9uIHRvIHRvdWNoIGV2ZW50cy5cbiAqL1xuY29uc3QgTU9VU0VfRVZFTlRfSUdOT1JFX1RJTUUgPSA4MDA7XG5cbi8vIFRPRE8oY3Jpc2JldG8pOiBhZGQgYW4gQVBJIGZvciBtb3ZpbmcgYSBkcmFnZ2FibGUgdXAvZG93biB0aGVcbi8vIGxpc3QgcHJvZ3JhbW1hdGljYWxseS4gVXNlZnVsIGZvciBrZXlib2FyZCBjb250cm9scy5cblxuLyoqIFRlbXBsYXRlIHRoYXQgY2FuIGJlIHVzZWQgdG8gY3JlYXRlIGEgZHJhZyBoZWxwZXIgZWxlbWVudCAoZS5nLiBhIHByZXZpZXcgb3IgYSBwbGFjZWhvbGRlcikuICovXG5pbnRlcmZhY2UgRHJhZ0hlbHBlclRlbXBsYXRlPFQgPSBhbnk+IHtcbiAgdGVtcGxhdGU6IFRlbXBsYXRlUmVmPFQ+IHwgbnVsbDtcbiAgdmlld0NvbnRhaW5lcjogVmlld0NvbnRhaW5lclJlZjtcbiAgY29udGV4dDogVDtcbn1cblxuLyoqIFBvaW50IG9uIHRoZSBwYWdlIG9yIHdpdGhpbiBhbiBlbGVtZW50LiAqL1xuZXhwb3J0IGludGVyZmFjZSBQb2ludCB7XG4gIHg6IG51bWJlcjtcbiAgeTogbnVtYmVyO1xufVxuXG4vKiogSW5saW5lIHN0eWxlcyB0byBiZSBzZXQgYXMgYCFpbXBvcnRhbnRgIHdoaWxlIGRyYWdnaW5nLiAqL1xuY29uc3QgZHJhZ0ltcG9ydGFudFByb3BlcnRpZXMgPSBuZXcgU2V0KFtcbiAgLy8gTmVlZHMgdG8gYmUgaW1wb3J0YW50LCBiZWNhdXNlIHNvbWUgYG1hdC10YWJsZWAgc2V0cyBgcG9zaXRpb246IHN0aWNreSAhaW1wb3J0YW50YC4gU2VlICMyMjc4MS5cbiAgJ3Bvc2l0aW9uJyxcbl0pO1xuXG4vKipcbiAqIFBvc3NpYmxlIHBsYWNlcyBpbnRvIHdoaWNoIHRoZSBwcmV2aWV3IG9mIGEgZHJhZyBpdGVtIGNhbiBiZSBpbnNlcnRlZC5cbiAqIC0gYGdsb2JhbGAgLSBQcmV2aWV3IHdpbGwgYmUgaW5zZXJ0ZWQgYXQgdGhlIGJvdHRvbSBvZiB0aGUgYDxib2R5PmAuIFRoZSBhZHZhbnRhZ2UgaXMgdGhhdFxuICogeW91IGRvbid0IGhhdmUgdG8gd29ycnkgYWJvdXQgYG92ZXJmbG93OiBoaWRkZW5gIG9yIGB6LWluZGV4YCwgYnV0IHRoZSBpdGVtIHdvbid0IHJldGFpblxuICogaXRzIGluaGVyaXRlZCBzdHlsZXMuXG4gKiAtIGBwYXJlbnRgIC0gUHJldmlldyB3aWxsIGJlIGluc2VydGVkIGludG8gdGhlIHBhcmVudCBvZiB0aGUgZHJhZyBpdGVtLiBUaGUgYWR2YW50YWdlIGlzIHRoYXRcbiAqIGluaGVyaXRlZCBzdHlsZXMgd2lsbCBiZSBwcmVzZXJ2ZWQsIGJ1dCBpdCBtYXkgYmUgY2xpcHBlZCBieSBgb3ZlcmZsb3c6IGhpZGRlbmAgb3Igbm90IGJlXG4gKiB2aXNpYmxlIGR1ZSB0byBgei1pbmRleGAuIEZ1cnRoZXJtb3JlLCB0aGUgcHJldmlldyBpcyBnb2luZyB0byBoYXZlIGFuIGVmZmVjdCBvdmVyIHNlbGVjdG9yc1xuICogbGlrZSBgOm50aC1jaGlsZGAgYW5kIHNvbWUgZmxleGJveCBjb25maWd1cmF0aW9ucy5cbiAqIC0gYEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+IHwgSFRNTEVsZW1lbnRgIC0gUHJldmlldyB3aWxsIGJlIGluc2VydGVkIGludG8gYSBzcGVjaWZpYyBlbGVtZW50LlxuICogU2FtZSBhZHZhbnRhZ2VzIGFuZCBkaXNhZHZhbnRhZ2VzIGFzIGBwYXJlbnRgLlxuICovXG5leHBvcnQgdHlwZSBQcmV2aWV3Q29udGFpbmVyID0gJ2dsb2JhbCcgfCAncGFyZW50JyB8IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+IHwgSFRNTEVsZW1lbnQ7XG5cbi8qKlxuICogUmVmZXJlbmNlIHRvIGEgZHJhZ2dhYmxlIGl0ZW0uIFVzZWQgdG8gbWFuaXB1bGF0ZSBvciBkaXNwb3NlIG9mIHRoZSBpdGVtLlxuICovXG5leHBvcnQgY2xhc3MgRHJhZ1JlZjxUID0gYW55PiB7XG4gIC8qKiBFbGVtZW50IGRpc3BsYXllZCBuZXh0IHRvIHRoZSB1c2VyJ3MgcG9pbnRlciB3aGlsZSB0aGUgZWxlbWVudCBpcyBkcmFnZ2VkLiAqL1xuICBwcml2YXRlIF9wcmV2aWV3OiBQcmV2aWV3UmVmIHwgbnVsbDtcblxuICAvKiogQ29udGFpbmVyIGludG8gd2hpY2ggdG8gaW5zZXJ0IHRoZSBwcmV2aWV3LiAqL1xuICBwcml2YXRlIF9wcmV2aWV3Q29udGFpbmVyOiBQcmV2aWV3Q29udGFpbmVyIHwgdW5kZWZpbmVkO1xuXG4gIC8qKiBSZWZlcmVuY2UgdG8gdGhlIHZpZXcgb2YgdGhlIHBsYWNlaG9sZGVyIGVsZW1lbnQuICovXG4gIHByaXZhdGUgX3BsYWNlaG9sZGVyUmVmOiBFbWJlZGRlZFZpZXdSZWY8YW55PiB8IG51bGw7XG5cbiAgLyoqIEVsZW1lbnQgdGhhdCBpcyByZW5kZXJlZCBpbnN0ZWFkIG9mIHRoZSBkcmFnZ2FibGUgaXRlbSB3aGlsZSBpdCBpcyBiZWluZyBzb3J0ZWQuICovXG4gIHByaXZhdGUgX3BsYWNlaG9sZGVyOiBIVE1MRWxlbWVudDtcblxuICAvKiogQ29vcmRpbmF0ZXMgd2l0aGluIHRoZSBlbGVtZW50IGF0IHdoaWNoIHRoZSB1c2VyIHBpY2tlZCB1cCB0aGUgZWxlbWVudC4gKi9cbiAgcHJpdmF0ZSBfcGlja3VwUG9zaXRpb25JbkVsZW1lbnQ6IFBvaW50O1xuXG4gIC8qKiBDb29yZGluYXRlcyBvbiB0aGUgcGFnZSBhdCB3aGljaCB0aGUgdXNlciBwaWNrZWQgdXAgdGhlIGVsZW1lbnQuICovXG4gIHByaXZhdGUgX3BpY2t1cFBvc2l0aW9uT25QYWdlOiBQb2ludDtcblxuICAvKipcbiAgICogQW5jaG9yIG5vZGUgdXNlZCB0byBzYXZlIHRoZSBwbGFjZSBpbiB0aGUgRE9NIHdoZXJlIHRoZSBlbGVtZW50IHdhc1xuICAgKiBwaWNrZWQgdXAgc28gdGhhdCBpdCBjYW4gYmUgcmVzdG9yZWQgYXQgdGhlIGVuZCBvZiB0aGUgZHJhZyBzZXF1ZW5jZS5cbiAgICovXG4gIHByaXZhdGUgX2FuY2hvcjogQ29tbWVudDtcblxuICAvKipcbiAgICogQ1NTIGB0cmFuc2Zvcm1gIGFwcGxpZWQgdG8gdGhlIGVsZW1lbnQgd2hlbiBpdCBpc24ndCBiZWluZyBkcmFnZ2VkLiBXZSBuZWVkIGFcbiAgICogcGFzc2l2ZSB0cmFuc2Zvcm0gaW4gb3JkZXIgZm9yIHRoZSBkcmFnZ2VkIGVsZW1lbnQgdG8gcmV0YWluIGl0cyBuZXcgcG9zaXRpb25cbiAgICogYWZ0ZXIgdGhlIHVzZXIgaGFzIHN0b3BwZWQgZHJhZ2dpbmcgYW5kIGJlY2F1c2Ugd2UgbmVlZCB0byBrbm93IHRoZSByZWxhdGl2ZVxuICAgKiBwb3NpdGlvbiBpbiBjYXNlIHRoZXkgc3RhcnQgZHJhZ2dpbmcgYWdhaW4uIFRoaXMgY29ycmVzcG9uZHMgdG8gYGVsZW1lbnQuc3R5bGUudHJhbnNmb3JtYC5cbiAgICovXG4gIHByaXZhdGUgX3Bhc3NpdmVUcmFuc2Zvcm06IFBvaW50ID0ge3g6IDAsIHk6IDB9O1xuXG4gIC8qKiBDU1MgYHRyYW5zZm9ybWAgdGhhdCBpcyBhcHBsaWVkIHRvIHRoZSBlbGVtZW50IHdoaWxlIGl0J3MgYmVpbmcgZHJhZ2dlZC4gKi9cbiAgcHJpdmF0ZSBfYWN0aXZlVHJhbnNmb3JtOiBQb2ludCA9IHt4OiAwLCB5OiAwfTtcblxuICAvKiogSW5saW5lIGB0cmFuc2Zvcm1gIHZhbHVlIHRoYXQgdGhlIGVsZW1lbnQgaGFkIGJlZm9yZSB0aGUgZmlyc3QgZHJhZ2dpbmcgc2VxdWVuY2UuICovXG4gIHByaXZhdGUgX2luaXRpYWxUcmFuc2Zvcm0/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIGRyYWdnaW5nIHNlcXVlbmNlIGhhcyBiZWVuIHN0YXJ0ZWQuIERvZXNuJ3RcbiAgICogbmVjZXNzYXJpbHkgbWVhbiB0aGF0IHRoZSBlbGVtZW50IGhhcyBiZWVuIG1vdmVkLlxuICAgKi9cbiAgcHJpdmF0ZSBfaGFzU3RhcnRlZERyYWdnaW5nID0gc2lnbmFsKGZhbHNlKTtcblxuICAvKiogV2hldGhlciB0aGUgZWxlbWVudCBoYXMgbW92ZWQgc2luY2UgdGhlIHVzZXIgc3RhcnRlZCBkcmFnZ2luZyBpdC4gKi9cbiAgcHJpdmF0ZSBfaGFzTW92ZWQ6IGJvb2xlYW47XG5cbiAgLyoqIERyb3AgY29udGFpbmVyIGluIHdoaWNoIHRoZSBEcmFnUmVmIHJlc2lkZWQgd2hlbiBkcmFnZ2luZyBiZWdhbi4gKi9cbiAgcHJpdmF0ZSBfaW5pdGlhbENvbnRhaW5lcjogRHJvcExpc3RSZWY7XG5cbiAgLyoqIEluZGV4IGF0IHdoaWNoIHRoZSBpdGVtIHN0YXJ0ZWQgaW4gaXRzIGluaXRpYWwgY29udGFpbmVyLiAqL1xuICBwcml2YXRlIF9pbml0aWFsSW5kZXg6IG51bWJlcjtcblxuICAvKiogQ2FjaGVkIHBvc2l0aW9ucyBvZiBzY3JvbGxhYmxlIHBhcmVudCBlbGVtZW50cy4gKi9cbiAgcHJpdmF0ZSBfcGFyZW50UG9zaXRpb25zOiBQYXJlbnRQb3NpdGlvblRyYWNrZXI7XG5cbiAgLyoqIEVtaXRzIHdoZW4gdGhlIGl0ZW0gaXMgYmVpbmcgbW92ZWQuICovXG4gIHByaXZhdGUgcmVhZG9ubHkgX21vdmVFdmVudHMgPSBuZXcgU3ViamVjdDx7XG4gICAgc291cmNlOiBEcmFnUmVmO1xuICAgIHBvaW50ZXJQb3NpdGlvbjoge3g6IG51bWJlcjsgeTogbnVtYmVyfTtcbiAgICBldmVudDogTW91c2VFdmVudCB8IFRvdWNoRXZlbnQ7XG4gICAgZGlzdGFuY2U6IFBvaW50O1xuICAgIGRlbHRhOiB7eDogLTEgfCAwIHwgMTsgeTogLTEgfCAwIHwgMX07XG4gIH0+KCk7XG5cbiAgLyoqIEtlZXBzIHRyYWNrIG9mIHRoZSBkaXJlY3Rpb24gaW4gd2hpY2ggdGhlIHVzZXIgaXMgZHJhZ2dpbmcgYWxvbmcgZWFjaCBheGlzLiAqL1xuICBwcml2YXRlIF9wb2ludGVyRGlyZWN0aW9uRGVsdGE6IHt4OiAtMSB8IDAgfCAxOyB5OiAtMSB8IDAgfCAxfTtcblxuICAvKiogUG9pbnRlciBwb3NpdGlvbiBhdCB3aGljaCB0aGUgbGFzdCBjaGFuZ2UgaW4gdGhlIGRlbHRhIG9jY3VycmVkLiAqL1xuICBwcml2YXRlIF9wb2ludGVyUG9zaXRpb25BdExhc3REaXJlY3Rpb25DaGFuZ2U6IFBvaW50O1xuXG4gIC8qKiBQb3NpdGlvbiBvZiB0aGUgcG9pbnRlciBhdCB0aGUgbGFzdCBwb2ludGVyIGV2ZW50LiAqL1xuICBwcml2YXRlIF9sYXN0S25vd25Qb2ludGVyUG9zaXRpb246IFBvaW50O1xuXG4gIC8qKlxuICAgKiBSb290IERPTSBub2RlIG9mIHRoZSBkcmFnIGluc3RhbmNlLiBUaGlzIGlzIHRoZSBlbGVtZW50IHRoYXQgd2lsbFxuICAgKiBiZSBtb3ZlZCBhcm91bmQgYXMgdGhlIHVzZXIgaXMgZHJhZ2dpbmcuXG4gICAqL1xuICBwcml2YXRlIF9yb290RWxlbWVudDogSFRNTEVsZW1lbnQ7XG5cbiAgLyoqXG4gICAqIE5lYXJlc3QgYW5jZXN0b3IgU1ZHLCByZWxhdGl2ZSB0byB3aGljaCBjb29yZGluYXRlcyBhcmUgY2FsY3VsYXRlZCBpZiBkcmFnZ2luZyBTVkdFbGVtZW50XG4gICAqL1xuICBwcml2YXRlIF9vd25lclNWR0VsZW1lbnQ6IFNWR1NWR0VsZW1lbnQgfCBudWxsO1xuXG4gIC8qKlxuICAgKiBJbmxpbmUgc3R5bGUgdmFsdWUgb2YgYC13ZWJraXQtdGFwLWhpZ2hsaWdodC1jb2xvcmAgYXQgdGhlIHRpbWUgdGhlXG4gICAqIGRyYWdnaW5nIHdhcyBzdGFydGVkLiBVc2VkIHRvIHJlc3RvcmUgdGhlIHZhbHVlIG9uY2Ugd2UncmUgZG9uZSBkcmFnZ2luZy5cbiAgICovXG4gIHByaXZhdGUgX3Jvb3RFbGVtZW50VGFwSGlnaGxpZ2h0OiBzdHJpbmc7XG5cbiAgLyoqIFN1YnNjcmlwdGlvbiB0byBwb2ludGVyIG1vdmVtZW50IGV2ZW50cy4gKi9cbiAgcHJpdmF0ZSBfcG9pbnRlck1vdmVTdWJzY3JpcHRpb24gPSBTdWJzY3JpcHRpb24uRU1QVFk7XG5cbiAgLyoqIFN1YnNjcmlwdGlvbiB0byB0aGUgZXZlbnQgdGhhdCBpcyBkaXNwYXRjaGVkIHdoZW4gdGhlIHVzZXIgbGlmdHMgdGhlaXIgcG9pbnRlci4gKi9cbiAgcHJpdmF0ZSBfcG9pbnRlclVwU3Vic2NyaXB0aW9uID0gU3Vic2NyaXB0aW9uLkVNUFRZO1xuXG4gIC8qKiBTdWJzY3JpcHRpb24gdG8gdGhlIHZpZXdwb3J0IGJlaW5nIHNjcm9sbGVkLiAqL1xuICBwcml2YXRlIF9zY3JvbGxTdWJzY3JpcHRpb24gPSBTdWJzY3JpcHRpb24uRU1QVFk7XG5cbiAgLyoqIFN1YnNjcmlwdGlvbiB0byB0aGUgdmlld3BvcnQgYmVpbmcgcmVzaXplZC4gKi9cbiAgcHJpdmF0ZSBfcmVzaXplU3Vic2NyaXB0aW9uID0gU3Vic2NyaXB0aW9uLkVNUFRZO1xuXG4gIC8qKlxuICAgKiBUaW1lIGF0IHdoaWNoIHRoZSBsYXN0IHRvdWNoIGV2ZW50IG9jY3VycmVkLiBVc2VkIHRvIGF2b2lkIGZpcmluZyB0aGUgc2FtZVxuICAgKiBldmVudHMgbXVsdGlwbGUgdGltZXMgb24gdG91Y2ggZGV2aWNlcyB3aGVyZSB0aGUgYnJvd3NlciB3aWxsIGZpcmUgYSBmYWtlXG4gICAqIG1vdXNlIGV2ZW50IGZvciBlYWNoIHRvdWNoIGV2ZW50LCBhZnRlciBhIGNlcnRhaW4gdGltZS5cbiAgICovXG4gIHByaXZhdGUgX2xhc3RUb3VjaEV2ZW50VGltZTogbnVtYmVyO1xuXG4gIC8qKiBUaW1lIGF0IHdoaWNoIHRoZSBsYXN0IGRyYWdnaW5nIHNlcXVlbmNlIHdhcyBzdGFydGVkLiAqL1xuICBwcml2YXRlIF9kcmFnU3RhcnRUaW1lOiBudW1iZXI7XG5cbiAgLyoqIENhY2hlZCByZWZlcmVuY2UgdG8gdGhlIGJvdW5kYXJ5IGVsZW1lbnQuICovXG4gIHByaXZhdGUgX2JvdW5kYXJ5RWxlbWVudDogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcblxuICAvKiogV2hldGhlciB0aGUgbmF0aXZlIGRyYWdnaW5nIGludGVyYWN0aW9ucyBoYXZlIGJlZW4gZW5hYmxlZCBvbiB0aGUgcm9vdCBlbGVtZW50LiAqL1xuICBwcml2YXRlIF9uYXRpdmVJbnRlcmFjdGlvbnNFbmFibGVkID0gdHJ1ZTtcblxuICAvKiogQ2xpZW50IHJlY3Qgb2YgdGhlIHJvb3QgZWxlbWVudCB3aGVuIHRoZSBkcmFnZ2luZyBzZXF1ZW5jZSBoYXMgc3RhcnRlZC4gKi9cbiAgcHJpdmF0ZSBfaW5pdGlhbERvbVJlY3Q/OiBET01SZWN0O1xuXG4gIC8qKiBDYWNoZWQgZGltZW5zaW9ucyBvZiB0aGUgcHJldmlldyBlbGVtZW50LiBTaG91bGQgYmUgcmVhZCB2aWEgYF9nZXRQcmV2aWV3UmVjdGAuICovXG4gIHByaXZhdGUgX3ByZXZpZXdSZWN0PzogRE9NUmVjdDtcblxuICAvKiogQ2FjaGVkIGRpbWVuc2lvbnMgb2YgdGhlIGJvdW5kYXJ5IGVsZW1lbnQuICovXG4gIHByaXZhdGUgX2JvdW5kYXJ5UmVjdD86IERPTVJlY3Q7XG5cbiAgLyoqIEVsZW1lbnQgdGhhdCB3aWxsIGJlIHVzZWQgYXMgYSB0ZW1wbGF0ZSB0byBjcmVhdGUgdGhlIGRyYWdnYWJsZSBpdGVtJ3MgcHJldmlldy4gKi9cbiAgcHJpdmF0ZSBfcHJldmlld1RlbXBsYXRlPzogRHJhZ1ByZXZpZXdUZW1wbGF0ZSB8IG51bGw7XG5cbiAgLyoqIFRlbXBsYXRlIGZvciBwbGFjZWhvbGRlciBlbGVtZW50IHJlbmRlcmVkIHRvIHNob3cgd2hlcmUgYSBkcmFnZ2FibGUgd291bGQgYmUgZHJvcHBlZC4gKi9cbiAgcHJpdmF0ZSBfcGxhY2Vob2xkZXJUZW1wbGF0ZT86IERyYWdIZWxwZXJUZW1wbGF0ZSB8IG51bGw7XG5cbiAgLyoqIEVsZW1lbnRzIHRoYXQgY2FuIGJlIHVzZWQgdG8gZHJhZyB0aGUgZHJhZ2dhYmxlIGl0ZW0uICovXG4gIHByaXZhdGUgX2hhbmRsZXM6IEhUTUxFbGVtZW50W10gPSBbXTtcblxuICAvKiogUmVnaXN0ZXJlZCBoYW5kbGVzIHRoYXQgYXJlIGN1cnJlbnRseSBkaXNhYmxlZC4gKi9cbiAgcHJpdmF0ZSBfZGlzYWJsZWRIYW5kbGVzID0gbmV3IFNldDxIVE1MRWxlbWVudD4oKTtcblxuICAvKiogRHJvcHBhYmxlIGNvbnRhaW5lciB0aGF0IHRoZSBkcmFnZ2FibGUgaXMgYSBwYXJ0IG9mLiAqL1xuICBwcml2YXRlIF9kcm9wQ29udGFpbmVyPzogRHJvcExpc3RSZWY7XG5cbiAgLyoqIExheW91dCBkaXJlY3Rpb24gb2YgdGhlIGl0ZW0uICovXG4gIHByaXZhdGUgX2RpcmVjdGlvbjogRGlyZWN0aW9uID0gJ2x0cic7XG5cbiAgLyoqIFJlZiB0aGF0IHRoZSBjdXJyZW50IGRyYWcgaXRlbSBpcyBuZXN0ZWQgaW4uICovXG4gIHByaXZhdGUgX3BhcmVudERyYWdSZWY6IERyYWdSZWY8dW5rbm93bj4gfCBudWxsO1xuXG4gIC8qKlxuICAgKiBDYWNoZWQgc2hhZG93IHJvb3QgdGhhdCB0aGUgZWxlbWVudCBpcyBwbGFjZWQgaW4uIGBudWxsYCBtZWFucyB0aGF0IHRoZSBlbGVtZW50IGlzbid0IGluXG4gICAqIHRoZSBzaGFkb3cgRE9NIGFuZCBgdW5kZWZpbmVkYCBtZWFucyB0aGF0IGl0IGhhc24ndCBiZWVuIHJlc29sdmVkIHlldC4gU2hvdWxkIGJlIHJlYWQgdmlhXG4gICAqIGBfZ2V0U2hhZG93Um9vdGAsIG5vdCBkaXJlY3RseS5cbiAgICovXG4gIHByaXZhdGUgX2NhY2hlZFNoYWRvd1Jvb3Q6IFNoYWRvd1Jvb3QgfCBudWxsIHwgdW5kZWZpbmVkO1xuXG4gIC8qKiBBeGlzIGFsb25nIHdoaWNoIGRyYWdnaW5nIGlzIGxvY2tlZC4gKi9cbiAgbG9ja0F4aXM6ICd4JyB8ICd5JztcblxuICAvKipcbiAgICogQW1vdW50IG9mIG1pbGxpc2Vjb25kcyB0byB3YWl0IGFmdGVyIHRoZSB1c2VyIGhhcyBwdXQgdGhlaXJcbiAgICogcG9pbnRlciBkb3duIGJlZm9yZSBzdGFydGluZyB0byBkcmFnIHRoZSBlbGVtZW50LlxuICAgKi9cbiAgZHJhZ1N0YXJ0RGVsYXk6IG51bWJlciB8IHt0b3VjaDogbnVtYmVyOyBtb3VzZTogbnVtYmVyfSA9IDA7XG5cbiAgLyoqIENsYXNzIHRvIGJlIGFkZGVkIHRvIHRoZSBwcmV2aWV3IGVsZW1lbnQuICovXG4gIHByZXZpZXdDbGFzczogc3RyaW5nIHwgc3RyaW5nW10gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIElmIHRoZSBwYXJlbnQgb2YgdGhlIGRyYWdnZWQgZWxlbWVudCBoYXMgYSBgc2NhbGVgIHRyYW5zZm9ybSwgaXQgY2FuIHRocm93IG9mZiB0aGVcbiAgICogcG9zaXRpb25pbmcgd2hlbiB0aGUgdXNlciBzdGFydHMgZHJhZ2dpbmcuIFVzZSB0aGlzIGlucHV0IHRvIG5vdGlmeSB0aGUgQ0RLIG9mIHRoZSBzY2FsZS5cbiAgICovXG4gIHNjYWxlOiBudW1iZXIgPSAxO1xuXG4gIC8qKiBXaGV0aGVyIHN0YXJ0aW5nIHRvIGRyYWcgdGhpcyBlbGVtZW50IGlzIGRpc2FibGVkLiAqL1xuICBnZXQgZGlzYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2Rpc2FibGVkIHx8ICEhKHRoaXMuX2Ryb3BDb250YWluZXIgJiYgdGhpcy5fZHJvcENvbnRhaW5lci5kaXNhYmxlZCk7XG4gIH1cbiAgc2V0IGRpc2FibGVkKHZhbHVlOiBib29sZWFuKSB7XG4gICAgaWYgKHZhbHVlICE9PSB0aGlzLl9kaXNhYmxlZCkge1xuICAgICAgdGhpcy5fZGlzYWJsZWQgPSB2YWx1ZTtcbiAgICAgIHRoaXMuX3RvZ2dsZU5hdGl2ZURyYWdJbnRlcmFjdGlvbnMoKTtcbiAgICAgIHRoaXMuX2hhbmRsZXMuZm9yRWFjaChoYW5kbGUgPT4gdG9nZ2xlTmF0aXZlRHJhZ0ludGVyYWN0aW9ucyhoYW5kbGUsIHZhbHVlKSk7XG4gICAgfVxuICB9XG4gIHByaXZhdGUgX2Rpc2FibGVkID0gZmFsc2U7XG5cbiAgLyoqIEVtaXRzIGFzIHRoZSBkcmFnIHNlcXVlbmNlIGlzIGJlaW5nIHByZXBhcmVkLiAqL1xuICByZWFkb25seSBiZWZvcmVTdGFydGVkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAvKiogRW1pdHMgd2hlbiB0aGUgdXNlciBzdGFydHMgZHJhZ2dpbmcgdGhlIGl0ZW0uICovXG4gIHJlYWRvbmx5IHN0YXJ0ZWQgPSBuZXcgU3ViamVjdDx7c291cmNlOiBEcmFnUmVmOyBldmVudDogTW91c2VFdmVudCB8IFRvdWNoRXZlbnR9PigpO1xuXG4gIC8qKiBFbWl0cyB3aGVuIHRoZSB1c2VyIGhhcyByZWxlYXNlZCBhIGRyYWcgaXRlbSwgYmVmb3JlIGFueSBhbmltYXRpb25zIGhhdmUgc3RhcnRlZC4gKi9cbiAgcmVhZG9ubHkgcmVsZWFzZWQgPSBuZXcgU3ViamVjdDx7c291cmNlOiBEcmFnUmVmOyBldmVudDogTW91c2VFdmVudCB8IFRvdWNoRXZlbnR9PigpO1xuXG4gIC8qKiBFbWl0cyB3aGVuIHRoZSB1c2VyIHN0b3BzIGRyYWdnaW5nIGFuIGl0ZW0gaW4gdGhlIGNvbnRhaW5lci4gKi9cbiAgcmVhZG9ubHkgZW5kZWQgPSBuZXcgU3ViamVjdDx7XG4gICAgc291cmNlOiBEcmFnUmVmO1xuICAgIGRpc3RhbmNlOiBQb2ludDtcbiAgICBkcm9wUG9pbnQ6IFBvaW50O1xuICAgIGV2ZW50OiBNb3VzZUV2ZW50IHwgVG91Y2hFdmVudDtcbiAgfT4oKTtcblxuICAvKiogRW1pdHMgd2hlbiB0aGUgdXNlciBoYXMgbW92ZWQgdGhlIGl0ZW0gaW50byBhIG5ldyBjb250YWluZXIuICovXG4gIHJlYWRvbmx5IGVudGVyZWQgPSBuZXcgU3ViamVjdDx7Y29udGFpbmVyOiBEcm9wTGlzdFJlZjsgaXRlbTogRHJhZ1JlZjsgY3VycmVudEluZGV4OiBudW1iZXJ9PigpO1xuXG4gIC8qKiBFbWl0cyB3aGVuIHRoZSB1c2VyIHJlbW92ZXMgdGhlIGl0ZW0gaXRzIGNvbnRhaW5lciBieSBkcmFnZ2luZyBpdCBpbnRvIGFub3RoZXIgY29udGFpbmVyLiAqL1xuICByZWFkb25seSBleGl0ZWQgPSBuZXcgU3ViamVjdDx7Y29udGFpbmVyOiBEcm9wTGlzdFJlZjsgaXRlbTogRHJhZ1JlZn0+KCk7XG5cbiAgLyoqIEVtaXRzIHdoZW4gdGhlIHVzZXIgZHJvcHMgdGhlIGl0ZW0gaW5zaWRlIGEgY29udGFpbmVyLiAqL1xuICByZWFkb25seSBkcm9wcGVkID0gbmV3IFN1YmplY3Q8e1xuICAgIHByZXZpb3VzSW5kZXg6IG51bWJlcjtcbiAgICBjdXJyZW50SW5kZXg6IG51bWJlcjtcbiAgICBpdGVtOiBEcmFnUmVmO1xuICAgIGNvbnRhaW5lcjogRHJvcExpc3RSZWY7XG4gICAgcHJldmlvdXNDb250YWluZXI6IERyb3BMaXN0UmVmO1xuICAgIGRpc3RhbmNlOiBQb2ludDtcbiAgICBkcm9wUG9pbnQ6IFBvaW50O1xuICAgIGlzUG9pbnRlck92ZXJDb250YWluZXI6IGJvb2xlYW47XG4gICAgZXZlbnQ6IE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50O1xuICB9PigpO1xuXG4gIC8qKlxuICAgKiBFbWl0cyBhcyB0aGUgdXNlciBpcyBkcmFnZ2luZyB0aGUgaXRlbS4gVXNlIHdpdGggY2F1dGlvbixcbiAgICogYmVjYXVzZSB0aGlzIGV2ZW50IHdpbGwgZmlyZSBmb3IgZXZlcnkgcGl4ZWwgdGhhdCB0aGUgdXNlciBoYXMgZHJhZ2dlZC5cbiAgICovXG4gIHJlYWRvbmx5IG1vdmVkOiBPYnNlcnZhYmxlPHtcbiAgICBzb3VyY2U6IERyYWdSZWY7XG4gICAgcG9pbnRlclBvc2l0aW9uOiB7eDogbnVtYmVyOyB5OiBudW1iZXJ9O1xuICAgIGV2ZW50OiBNb3VzZUV2ZW50IHwgVG91Y2hFdmVudDtcbiAgICBkaXN0YW5jZTogUG9pbnQ7XG4gICAgZGVsdGE6IHt4OiAtMSB8IDAgfCAxOyB5OiAtMSB8IDAgfCAxfTtcbiAgfT4gPSB0aGlzLl9tb3ZlRXZlbnRzO1xuXG4gIC8qKiBBcmJpdHJhcnkgZGF0YSB0aGF0IGNhbiBiZSBhdHRhY2hlZCB0byB0aGUgZHJhZyBpdGVtLiAqL1xuICBkYXRhOiBUO1xuXG4gIC8qKlxuICAgKiBGdW5jdGlvbiB0aGF0IGNhbiBiZSB1c2VkIHRvIGN1c3RvbWl6ZSB0aGUgbG9naWMgb2YgaG93IHRoZSBwb3NpdGlvbiBvZiB0aGUgZHJhZyBpdGVtXG4gICAqIGlzIGxpbWl0ZWQgd2hpbGUgaXQncyBiZWluZyBkcmFnZ2VkLiBHZXRzIGNhbGxlZCB3aXRoIGEgcG9pbnQgY29udGFpbmluZyB0aGUgY3VycmVudCBwb3NpdGlvblxuICAgKiBvZiB0aGUgdXNlcidzIHBvaW50ZXIgb24gdGhlIHBhZ2UsIGEgcmVmZXJlbmNlIHRvIHRoZSBpdGVtIGJlaW5nIGRyYWdnZWQgYW5kIGl0cyBkaW1lbnNpb25zLlxuICAgKiBTaG91bGQgcmV0dXJuIGEgcG9pbnQgZGVzY3JpYmluZyB3aGVyZSB0aGUgaXRlbSBzaG91bGQgYmUgcmVuZGVyZWQuXG4gICAqL1xuICBjb25zdHJhaW5Qb3NpdGlvbj86IChcbiAgICB1c2VyUG9pbnRlclBvc2l0aW9uOiBQb2ludCxcbiAgICBkcmFnUmVmOiBEcmFnUmVmLFxuICAgIGRpbWVuc2lvbnM6IERPTVJlY3QsXG4gICAgcGlja3VwUG9zaXRpb25JbkVsZW1lbnQ6IFBvaW50LFxuICApID0+IFBvaW50O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGVsZW1lbnQ6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+IHwgSFRNTEVsZW1lbnQsXG4gICAgcHJpdmF0ZSBfY29uZmlnOiBEcmFnUmVmQ29uZmlnLFxuICAgIHByaXZhdGUgX2RvY3VtZW50OiBEb2N1bWVudCxcbiAgICBwcml2YXRlIF9uZ1pvbmU6IE5nWm9uZSxcbiAgICBwcml2YXRlIF92aWV3cG9ydFJ1bGVyOiBWaWV3cG9ydFJ1bGVyLFxuICAgIHByaXZhdGUgX2RyYWdEcm9wUmVnaXN0cnk6IERyYWdEcm9wUmVnaXN0cnksXG4gICkge1xuICAgIHRoaXMud2l0aFJvb3RFbGVtZW50KGVsZW1lbnQpLndpdGhQYXJlbnQoX2NvbmZpZy5wYXJlbnREcmFnUmVmIHx8IG51bGwpO1xuICAgIHRoaXMuX3BhcmVudFBvc2l0aW9ucyA9IG5ldyBQYXJlbnRQb3NpdGlvblRyYWNrZXIoX2RvY3VtZW50KTtcbiAgICBfZHJhZ0Ryb3BSZWdpc3RyeS5yZWdpc3RlckRyYWdJdGVtKHRoaXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGVsZW1lbnQgdGhhdCBpcyBiZWluZyB1c2VkIGFzIGEgcGxhY2Vob2xkZXJcbiAgICogd2hpbGUgdGhlIGN1cnJlbnQgZWxlbWVudCBpcyBiZWluZyBkcmFnZ2VkLlxuICAgKi9cbiAgZ2V0UGxhY2Vob2xkZXJFbGVtZW50KCk6IEhUTUxFbGVtZW50IHtcbiAgICByZXR1cm4gdGhpcy5fcGxhY2Vob2xkZXI7XG4gIH1cblxuICAvKiogUmV0dXJucyB0aGUgcm9vdCBkcmFnZ2FibGUgZWxlbWVudC4gKi9cbiAgZ2V0Um9vdEVsZW1lbnQoKTogSFRNTEVsZW1lbnQge1xuICAgIHJldHVybiB0aGlzLl9yb290RWxlbWVudDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBjdXJyZW50bHktdmlzaWJsZSBlbGVtZW50IHRoYXQgcmVwcmVzZW50cyB0aGUgZHJhZyBpdGVtLlxuICAgKiBXaGlsZSBkcmFnZ2luZyB0aGlzIGlzIHRoZSBwbGFjZWhvbGRlciwgb3RoZXJ3aXNlIGl0J3MgdGhlIHJvb3QgZWxlbWVudC5cbiAgICovXG4gIGdldFZpc2libGVFbGVtZW50KCk6IEhUTUxFbGVtZW50IHtcbiAgICByZXR1cm4gdGhpcy5pc0RyYWdnaW5nKCkgPyB0aGlzLmdldFBsYWNlaG9sZGVyRWxlbWVudCgpIDogdGhpcy5nZXRSb290RWxlbWVudCgpO1xuICB9XG5cbiAgLyoqIFJlZ2lzdGVycyB0aGUgaGFuZGxlcyB0aGF0IGNhbiBiZSB1c2VkIHRvIGRyYWcgdGhlIGVsZW1lbnQuICovXG4gIHdpdGhIYW5kbGVzKGhhbmRsZXM6IChIVE1MRWxlbWVudCB8IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+KVtdKTogdGhpcyB7XG4gICAgdGhpcy5faGFuZGxlcyA9IGhhbmRsZXMubWFwKGhhbmRsZSA9PiBjb2VyY2VFbGVtZW50KGhhbmRsZSkpO1xuICAgIHRoaXMuX2hhbmRsZXMuZm9yRWFjaChoYW5kbGUgPT4gdG9nZ2xlTmF0aXZlRHJhZ0ludGVyYWN0aW9ucyhoYW5kbGUsIHRoaXMuZGlzYWJsZWQpKTtcbiAgICB0aGlzLl90b2dnbGVOYXRpdmVEcmFnSW50ZXJhY3Rpb25zKCk7XG5cbiAgICAvLyBEZWxldGUgYW55IGxpbmdlcmluZyBkaXNhYmxlZCBoYW5kbGVzIHRoYXQgbWF5IGhhdmUgYmVlbiBkZXN0cm95ZWQuIE5vdGUgdGhhdCB3ZSByZS1jcmVhdGVcbiAgICAvLyB0aGUgc2V0LCByYXRoZXIgdGhhbiBpdGVyYXRlIG92ZXIgaXQgYW5kIGZpbHRlciBvdXQgdGhlIGRlc3Ryb3llZCBoYW5kbGVzLCBiZWNhdXNlIHdoaWxlXG4gICAgLy8gdGhlIEVTIHNwZWMgYWxsb3dzIGZvciBzZXRzIHRvIGJlIG1vZGlmaWVkIHdoaWxlIHRoZXkncmUgYmVpbmcgaXRlcmF0ZWQgb3Zlciwgc29tZSBwb2x5ZmlsbHNcbiAgICAvLyB1c2UgYW4gYXJyYXkgaW50ZXJuYWxseSB3aGljaCBtYXkgdGhyb3cgYW4gZXJyb3IuXG4gICAgY29uc3QgZGlzYWJsZWRIYW5kbGVzID0gbmV3IFNldDxIVE1MRWxlbWVudD4oKTtcbiAgICB0aGlzLl9kaXNhYmxlZEhhbmRsZXMuZm9yRWFjaChoYW5kbGUgPT4ge1xuICAgICAgaWYgKHRoaXMuX2hhbmRsZXMuaW5kZXhPZihoYW5kbGUpID4gLTEpIHtcbiAgICAgICAgZGlzYWJsZWRIYW5kbGVzLmFkZChoYW5kbGUpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHRoaXMuX2Rpc2FibGVkSGFuZGxlcyA9IGRpc2FibGVkSGFuZGxlcztcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgdGhlIHRlbXBsYXRlIHRoYXQgc2hvdWxkIGJlIHVzZWQgZm9yIHRoZSBkcmFnIHByZXZpZXcuXG4gICAqIEBwYXJhbSB0ZW1wbGF0ZSBUZW1wbGF0ZSB0aGF0IGZyb20gd2hpY2ggdG8gc3RhbXAgb3V0IHRoZSBwcmV2aWV3LlxuICAgKi9cbiAgd2l0aFByZXZpZXdUZW1wbGF0ZSh0ZW1wbGF0ZTogRHJhZ1ByZXZpZXdUZW1wbGF0ZSB8IG51bGwpOiB0aGlzIHtcbiAgICB0aGlzLl9wcmV2aWV3VGVtcGxhdGUgPSB0ZW1wbGF0ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgdGhlIHRlbXBsYXRlIHRoYXQgc2hvdWxkIGJlIHVzZWQgZm9yIHRoZSBkcmFnIHBsYWNlaG9sZGVyLlxuICAgKiBAcGFyYW0gdGVtcGxhdGUgVGVtcGxhdGUgdGhhdCBmcm9tIHdoaWNoIHRvIHN0YW1wIG91dCB0aGUgcGxhY2Vob2xkZXIuXG4gICAqL1xuICB3aXRoUGxhY2Vob2xkZXJUZW1wbGF0ZSh0ZW1wbGF0ZTogRHJhZ0hlbHBlclRlbXBsYXRlIHwgbnVsbCk6IHRoaXMge1xuICAgIHRoaXMuX3BsYWNlaG9sZGVyVGVtcGxhdGUgPSB0ZW1wbGF0ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGFuIGFsdGVybmF0ZSBkcmFnIHJvb3QgZWxlbWVudC4gVGhlIHJvb3QgZWxlbWVudCBpcyB0aGUgZWxlbWVudCB0aGF0IHdpbGwgYmUgbW92ZWQgYXNcbiAgICogdGhlIHVzZXIgaXMgZHJhZ2dpbmcuIFBhc3NpbmcgYW4gYWx0ZXJuYXRlIHJvb3QgZWxlbWVudCBpcyB1c2VmdWwgd2hlbiB0cnlpbmcgdG8gZW5hYmxlXG4gICAqIGRyYWdnaW5nIG9uIGFuIGVsZW1lbnQgdGhhdCB5b3UgbWlnaHQgbm90IGhhdmUgYWNjZXNzIHRvLlxuICAgKi9cbiAgd2l0aFJvb3RFbGVtZW50KHJvb3RFbGVtZW50OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PiB8IEhUTUxFbGVtZW50KTogdGhpcyB7XG4gICAgY29uc3QgZWxlbWVudCA9IGNvZXJjZUVsZW1lbnQocm9vdEVsZW1lbnQpO1xuXG4gICAgaWYgKGVsZW1lbnQgIT09IHRoaXMuX3Jvb3RFbGVtZW50KSB7XG4gICAgICBpZiAodGhpcy5fcm9vdEVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5fcmVtb3ZlUm9vdEVsZW1lbnRMaXN0ZW5lcnModGhpcy5fcm9vdEVsZW1lbnQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuX3BvaW50ZXJEb3duLCBhY3RpdmVFdmVudExpc3RlbmVyT3B0aW9ucyk7XG4gICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRoaXMuX3BvaW50ZXJEb3duLCBwYXNzaXZlRXZlbnRMaXN0ZW5lck9wdGlvbnMpO1xuICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWdzdGFydCcsIHRoaXMuX25hdGl2ZURyYWdTdGFydCwgYWN0aXZlRXZlbnRMaXN0ZW5lck9wdGlvbnMpO1xuICAgICAgfSk7XG4gICAgICB0aGlzLl9pbml0aWFsVHJhbnNmb3JtID0gdW5kZWZpbmVkO1xuICAgICAgdGhpcy5fcm9vdEVsZW1lbnQgPSBlbGVtZW50O1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgU1ZHRWxlbWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgdGhpcy5fcm9vdEVsZW1lbnQgaW5zdGFuY2VvZiBTVkdFbGVtZW50KSB7XG4gICAgICB0aGlzLl9vd25lclNWR0VsZW1lbnQgPSB0aGlzLl9yb290RWxlbWVudC5vd25lclNWR0VsZW1lbnQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogRWxlbWVudCB0byB3aGljaCB0aGUgZHJhZ2dhYmxlJ3MgcG9zaXRpb24gd2lsbCBiZSBjb25zdHJhaW5lZC5cbiAgICovXG4gIHdpdGhCb3VuZGFyeUVsZW1lbnQoYm91bmRhcnlFbGVtZW50OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PiB8IEhUTUxFbGVtZW50IHwgbnVsbCk6IHRoaXMge1xuICAgIHRoaXMuX2JvdW5kYXJ5RWxlbWVudCA9IGJvdW5kYXJ5RWxlbWVudCA/IGNvZXJjZUVsZW1lbnQoYm91bmRhcnlFbGVtZW50KSA6IG51bGw7XG4gICAgdGhpcy5fcmVzaXplU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgaWYgKGJvdW5kYXJ5RWxlbWVudCkge1xuICAgICAgdGhpcy5fcmVzaXplU3Vic2NyaXB0aW9uID0gdGhpcy5fdmlld3BvcnRSdWxlclxuICAgICAgICAuY2hhbmdlKDEwKVxuICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMuX2NvbnRhaW5JbnNpZGVCb3VuZGFyeU9uUmVzaXplKCkpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKiBTZXRzIHRoZSBwYXJlbnQgcmVmIHRoYXQgdGhlIHJlZiBpcyBuZXN0ZWQgaW4uICAqL1xuICB3aXRoUGFyZW50KHBhcmVudDogRHJhZ1JlZjx1bmtub3duPiB8IG51bGwpOiB0aGlzIHtcbiAgICB0aGlzLl9wYXJlbnREcmFnUmVmID0gcGFyZW50O1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqIFJlbW92ZXMgdGhlIGRyYWdnaW5nIGZ1bmN0aW9uYWxpdHkgZnJvbSB0aGUgRE9NIGVsZW1lbnQuICovXG4gIGRpc3Bvc2UoKSB7XG4gICAgdGhpcy5fcmVtb3ZlUm9vdEVsZW1lbnRMaXN0ZW5lcnModGhpcy5fcm9vdEVsZW1lbnQpO1xuXG4gICAgLy8gRG8gdGhpcyBjaGVjayBiZWZvcmUgcmVtb3ZpbmcgZnJvbSB0aGUgcmVnaXN0cnkgc2luY2UgaXQnbGxcbiAgICAvLyBzdG9wIGJlaW5nIGNvbnNpZGVyZWQgYXMgZHJhZ2dlZCBvbmNlIGl0IGlzIHJlbW92ZWQuXG4gICAgaWYgKHRoaXMuaXNEcmFnZ2luZygpKSB7XG4gICAgICAvLyBTaW5jZSB3ZSBtb3ZlIG91dCB0aGUgZWxlbWVudCB0byB0aGUgZW5kIG9mIHRoZSBib2R5IHdoaWxlIGl0J3MgYmVpbmdcbiAgICAgIC8vIGRyYWdnZWQsIHdlIGhhdmUgdG8gbWFrZSBzdXJlIHRoYXQgaXQncyByZW1vdmVkIGlmIGl0IGdldHMgZGVzdHJveWVkLlxuICAgICAgdGhpcy5fcm9vdEVsZW1lbnQ/LnJlbW92ZSgpO1xuICAgIH1cblxuICAgIHRoaXMuX2FuY2hvcj8ucmVtb3ZlKCk7XG4gICAgdGhpcy5fZGVzdHJveVByZXZpZXcoKTtcbiAgICB0aGlzLl9kZXN0cm95UGxhY2Vob2xkZXIoKTtcbiAgICB0aGlzLl9kcmFnRHJvcFJlZ2lzdHJ5LnJlbW92ZURyYWdJdGVtKHRoaXMpO1xuICAgIHRoaXMuX3JlbW92ZUxpc3RlbmVycygpO1xuICAgIHRoaXMuYmVmb3JlU3RhcnRlZC5jb21wbGV0ZSgpO1xuICAgIHRoaXMuc3RhcnRlZC5jb21wbGV0ZSgpO1xuICAgIHRoaXMucmVsZWFzZWQuY29tcGxldGUoKTtcbiAgICB0aGlzLmVuZGVkLmNvbXBsZXRlKCk7XG4gICAgdGhpcy5lbnRlcmVkLmNvbXBsZXRlKCk7XG4gICAgdGhpcy5leGl0ZWQuY29tcGxldGUoKTtcbiAgICB0aGlzLmRyb3BwZWQuY29tcGxldGUoKTtcbiAgICB0aGlzLl9tb3ZlRXZlbnRzLmNvbXBsZXRlKCk7XG4gICAgdGhpcy5faGFuZGxlcyA9IFtdO1xuICAgIHRoaXMuX2Rpc2FibGVkSGFuZGxlcy5jbGVhcigpO1xuICAgIHRoaXMuX2Ryb3BDb250YWluZXIgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fcmVzaXplU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5fcGFyZW50UG9zaXRpb25zLmNsZWFyKCk7XG4gICAgdGhpcy5fYm91bmRhcnlFbGVtZW50ID1cbiAgICAgIHRoaXMuX3Jvb3RFbGVtZW50ID1cbiAgICAgIHRoaXMuX293bmVyU1ZHRWxlbWVudCA9XG4gICAgICB0aGlzLl9wbGFjZWhvbGRlclRlbXBsYXRlID1cbiAgICAgIHRoaXMuX3ByZXZpZXdUZW1wbGF0ZSA9XG4gICAgICB0aGlzLl9hbmNob3IgPVxuICAgICAgdGhpcy5fcGFyZW50RHJhZ1JlZiA9XG4gICAgICAgIG51bGwhO1xuICB9XG5cbiAgLyoqIENoZWNrcyB3aGV0aGVyIHRoZSBlbGVtZW50IGlzIGN1cnJlbnRseSBiZWluZyBkcmFnZ2VkLiAqL1xuICBpc0RyYWdnaW5nKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9oYXNTdGFydGVkRHJhZ2dpbmcoKSAmJiB0aGlzLl9kcmFnRHJvcFJlZ2lzdHJ5LmlzRHJhZ2dpbmcodGhpcyk7XG4gIH1cblxuICAvKiogUmVzZXRzIGEgc3RhbmRhbG9uZSBkcmFnIGl0ZW0gdG8gaXRzIGluaXRpYWwgcG9zaXRpb24uICovXG4gIHJlc2V0KCk6IHZvaWQge1xuICAgIHRoaXMuX3Jvb3RFbGVtZW50LnN0eWxlLnRyYW5zZm9ybSA9IHRoaXMuX2luaXRpYWxUcmFuc2Zvcm0gfHwgJyc7XG4gICAgdGhpcy5fYWN0aXZlVHJhbnNmb3JtID0ge3g6IDAsIHk6IDB9O1xuICAgIHRoaXMuX3Bhc3NpdmVUcmFuc2Zvcm0gPSB7eDogMCwgeTogMH07XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBhIGhhbmRsZSBhcyBkaXNhYmxlZC4gV2hpbGUgYSBoYW5kbGUgaXMgZGlzYWJsZWQsIGl0J2xsIGNhcHR1cmUgYW5kIGludGVycnVwdCBkcmFnZ2luZy5cbiAgICogQHBhcmFtIGhhbmRsZSBIYW5kbGUgZWxlbWVudCB0aGF0IHNob3VsZCBiZSBkaXNhYmxlZC5cbiAgICovXG4gIGRpc2FibGVIYW5kbGUoaGFuZGxlOiBIVE1MRWxlbWVudCkge1xuICAgIGlmICghdGhpcy5fZGlzYWJsZWRIYW5kbGVzLmhhcyhoYW5kbGUpICYmIHRoaXMuX2hhbmRsZXMuaW5kZXhPZihoYW5kbGUpID4gLTEpIHtcbiAgICAgIHRoaXMuX2Rpc2FibGVkSGFuZGxlcy5hZGQoaGFuZGxlKTtcbiAgICAgIHRvZ2dsZU5hdGl2ZURyYWdJbnRlcmFjdGlvbnMoaGFuZGxlLCB0cnVlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRW5hYmxlcyBhIGhhbmRsZSwgaWYgaXQgaGFzIGJlZW4gZGlzYWJsZWQuXG4gICAqIEBwYXJhbSBoYW5kbGUgSGFuZGxlIGVsZW1lbnQgdG8gYmUgZW5hYmxlZC5cbiAgICovXG4gIGVuYWJsZUhhbmRsZShoYW5kbGU6IEhUTUxFbGVtZW50KSB7XG4gICAgaWYgKHRoaXMuX2Rpc2FibGVkSGFuZGxlcy5oYXMoaGFuZGxlKSkge1xuICAgICAgdGhpcy5fZGlzYWJsZWRIYW5kbGVzLmRlbGV0ZShoYW5kbGUpO1xuICAgICAgdG9nZ2xlTmF0aXZlRHJhZ0ludGVyYWN0aW9ucyhoYW5kbGUsIHRoaXMuZGlzYWJsZWQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBTZXRzIHRoZSBsYXlvdXQgZGlyZWN0aW9uIG9mIHRoZSBkcmFnZ2FibGUgaXRlbS4gKi9cbiAgd2l0aERpcmVjdGlvbihkaXJlY3Rpb246IERpcmVjdGlvbik6IHRoaXMge1xuICAgIHRoaXMuX2RpcmVjdGlvbiA9IGRpcmVjdGlvbjtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKiBTZXRzIHRoZSBjb250YWluZXIgdGhhdCB0aGUgaXRlbSBpcyBwYXJ0IG9mLiAqL1xuICBfd2l0aERyb3BDb250YWluZXIoY29udGFpbmVyOiBEcm9wTGlzdFJlZikge1xuICAgIHRoaXMuX2Ryb3BDb250YWluZXIgPSBjb250YWluZXI7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgY3VycmVudCBwb3NpdGlvbiBpbiBwaXhlbHMgdGhlIGRyYWdnYWJsZSBvdXRzaWRlIG9mIGEgZHJvcCBjb250YWluZXIuXG4gICAqL1xuICBnZXRGcmVlRHJhZ1Bvc2l0aW9uKCk6IFJlYWRvbmx5PFBvaW50PiB7XG4gICAgY29uc3QgcG9zaXRpb24gPSB0aGlzLmlzRHJhZ2dpbmcoKSA/IHRoaXMuX2FjdGl2ZVRyYW5zZm9ybSA6IHRoaXMuX3Bhc3NpdmVUcmFuc2Zvcm07XG4gICAgcmV0dXJuIHt4OiBwb3NpdGlvbi54LCB5OiBwb3NpdGlvbi55fTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBjdXJyZW50IHBvc2l0aW9uIGluIHBpeGVscyB0aGUgZHJhZ2dhYmxlIG91dHNpZGUgb2YgYSBkcm9wIGNvbnRhaW5lci5cbiAgICogQHBhcmFtIHZhbHVlIE5ldyBwb3NpdGlvbiB0byBiZSBzZXQuXG4gICAqL1xuICBzZXRGcmVlRHJhZ1Bvc2l0aW9uKHZhbHVlOiBQb2ludCk6IHRoaXMge1xuICAgIHRoaXMuX2FjdGl2ZVRyYW5zZm9ybSA9IHt4OiAwLCB5OiAwfTtcbiAgICB0aGlzLl9wYXNzaXZlVHJhbnNmb3JtLnggPSB2YWx1ZS54O1xuICAgIHRoaXMuX3Bhc3NpdmVUcmFuc2Zvcm0ueSA9IHZhbHVlLnk7XG5cbiAgICBpZiAoIXRoaXMuX2Ryb3BDb250YWluZXIpIHtcbiAgICAgIHRoaXMuX2FwcGx5Um9vdEVsZW1lbnRUcmFuc2Zvcm0odmFsdWUueCwgdmFsdWUueSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgY29udGFpbmVyIGludG8gd2hpY2ggdG8gaW5zZXJ0IHRoZSBwcmV2aWV3IGVsZW1lbnQuXG4gICAqIEBwYXJhbSB2YWx1ZSBDb250YWluZXIgaW50byB3aGljaCB0byBpbnNlcnQgdGhlIHByZXZpZXcuXG4gICAqL1xuICB3aXRoUHJldmlld0NvbnRhaW5lcih2YWx1ZTogUHJldmlld0NvbnRhaW5lcik6IHRoaXMge1xuICAgIHRoaXMuX3ByZXZpZXdDb250YWluZXIgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKiBVcGRhdGVzIHRoZSBpdGVtJ3Mgc29ydCBvcmRlciBiYXNlZCBvbiB0aGUgbGFzdC1rbm93biBwb2ludGVyIHBvc2l0aW9uLiAqL1xuICBfc29ydEZyb21MYXN0UG9pbnRlclBvc2l0aW9uKCkge1xuICAgIGNvbnN0IHBvc2l0aW9uID0gdGhpcy5fbGFzdEtub3duUG9pbnRlclBvc2l0aW9uO1xuXG4gICAgaWYgKHBvc2l0aW9uICYmIHRoaXMuX2Ryb3BDb250YWluZXIpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZUFjdGl2ZURyb3BDb250YWluZXIodGhpcy5fZ2V0Q29uc3RyYWluZWRQb2ludGVyUG9zaXRpb24ocG9zaXRpb24pLCBwb3NpdGlvbik7XG4gICAgfVxuICB9XG5cbiAgLyoqIFVuc3Vic2NyaWJlcyBmcm9tIHRoZSBnbG9iYWwgc3Vic2NyaXB0aW9ucy4gKi9cbiAgcHJpdmF0ZSBfcmVtb3ZlTGlzdGVuZXJzKCkge1xuICAgIHRoaXMuX3BvaW50ZXJNb3ZlU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5fcG9pbnRlclVwU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5fc2Nyb2xsU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5fZ2V0U2hhZG93Um9vdCgpPy5yZW1vdmVFdmVudExpc3RlbmVyKFxuICAgICAgJ3NlbGVjdHN0YXJ0JyxcbiAgICAgIHNoYWRvd0RvbVNlbGVjdFN0YXJ0LFxuICAgICAgYWN0aXZlQ2FwdHVyaW5nRXZlbnRPcHRpb25zLFxuICAgICk7XG4gIH1cblxuICAvKiogRGVzdHJveXMgdGhlIHByZXZpZXcgZWxlbWVudCBhbmQgaXRzIFZpZXdSZWYuICovXG4gIHByaXZhdGUgX2Rlc3Ryb3lQcmV2aWV3KCkge1xuICAgIHRoaXMuX3ByZXZpZXc/LmRlc3Ryb3koKTtcbiAgICB0aGlzLl9wcmV2aWV3ID0gbnVsbDtcbiAgfVxuXG4gIC8qKiBEZXN0cm95cyB0aGUgcGxhY2Vob2xkZXIgZWxlbWVudCBhbmQgaXRzIFZpZXdSZWYuICovXG4gIHByaXZhdGUgX2Rlc3Ryb3lQbGFjZWhvbGRlcigpIHtcbiAgICB0aGlzLl9wbGFjZWhvbGRlcj8ucmVtb3ZlKCk7XG4gICAgdGhpcy5fcGxhY2Vob2xkZXJSZWY/LmRlc3Ryb3koKTtcbiAgICB0aGlzLl9wbGFjZWhvbGRlciA9IHRoaXMuX3BsYWNlaG9sZGVyUmVmID0gbnVsbCE7XG4gIH1cblxuICAvKiogSGFuZGxlciBmb3IgdGhlIGBtb3VzZWRvd25gL2B0b3VjaHN0YXJ0YCBldmVudHMuICovXG4gIHByaXZhdGUgX3BvaW50ZXJEb3duID0gKGV2ZW50OiBNb3VzZUV2ZW50IHwgVG91Y2hFdmVudCkgPT4ge1xuICAgIHRoaXMuYmVmb3JlU3RhcnRlZC5uZXh0KCk7XG5cbiAgICAvLyBEZWxlZ2F0ZSB0aGUgZXZlbnQgYmFzZWQgb24gd2hldGhlciBpdCBzdGFydGVkIGZyb20gYSBoYW5kbGUgb3IgdGhlIGVsZW1lbnQgaXRzZWxmLlxuICAgIGlmICh0aGlzLl9oYW5kbGVzLmxlbmd0aCkge1xuICAgICAgY29uc3QgdGFyZ2V0SGFuZGxlID0gdGhpcy5fZ2V0VGFyZ2V0SGFuZGxlKGV2ZW50KTtcblxuICAgICAgaWYgKHRhcmdldEhhbmRsZSAmJiAhdGhpcy5fZGlzYWJsZWRIYW5kbGVzLmhhcyh0YXJnZXRIYW5kbGUpICYmICF0aGlzLmRpc2FibGVkKSB7XG4gICAgICAgIHRoaXMuX2luaXRpYWxpemVEcmFnU2VxdWVuY2UodGFyZ2V0SGFuZGxlLCBldmVudCk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICghdGhpcy5kaXNhYmxlZCkge1xuICAgICAgdGhpcy5faW5pdGlhbGl6ZURyYWdTZXF1ZW5jZSh0aGlzLl9yb290RWxlbWVudCwgZXZlbnQpO1xuICAgIH1cbiAgfTtcblxuICAvKiogSGFuZGxlciB0aGF0IGlzIGludm9rZWQgd2hlbiB0aGUgdXNlciBtb3ZlcyB0aGVpciBwb2ludGVyIGFmdGVyIHRoZXkndmUgaW5pdGlhdGVkIGEgZHJhZy4gKi9cbiAgcHJpdmF0ZSBfcG9pbnRlck1vdmUgPSAoZXZlbnQ6IE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50KSA9PiB7XG4gICAgY29uc3QgcG9pbnRlclBvc2l0aW9uID0gdGhpcy5fZ2V0UG9pbnRlclBvc2l0aW9uT25QYWdlKGV2ZW50KTtcblxuICAgIGlmICghdGhpcy5faGFzU3RhcnRlZERyYWdnaW5nKCkpIHtcbiAgICAgIGNvbnN0IGRpc3RhbmNlWCA9IE1hdGguYWJzKHBvaW50ZXJQb3NpdGlvbi54IC0gdGhpcy5fcGlja3VwUG9zaXRpb25PblBhZ2UueCk7XG4gICAgICBjb25zdCBkaXN0YW5jZVkgPSBNYXRoLmFicyhwb2ludGVyUG9zaXRpb24ueSAtIHRoaXMuX3BpY2t1cFBvc2l0aW9uT25QYWdlLnkpO1xuICAgICAgY29uc3QgaXNPdmVyVGhyZXNob2xkID0gZGlzdGFuY2VYICsgZGlzdGFuY2VZID49IHRoaXMuX2NvbmZpZy5kcmFnU3RhcnRUaHJlc2hvbGQ7XG5cbiAgICAgIC8vIE9ubHkgc3RhcnQgZHJhZ2dpbmcgYWZ0ZXIgdGhlIHVzZXIgaGFzIG1vdmVkIG1vcmUgdGhhbiB0aGUgbWluaW11bSBkaXN0YW5jZSBpbiBlaXRoZXJcbiAgICAgIC8vIGRpcmVjdGlvbi4gTm90ZSB0aGF0IHRoaXMgaXMgcHJlZmVyYWJsZSBvdmVyIGRvaW5nIHNvbWV0aGluZyBsaWtlIGBza2lwKG1pbmltdW1EaXN0YW5jZSlgXG4gICAgICAvLyBpbiB0aGUgYHBvaW50ZXJNb3ZlYCBzdWJzY3JpcHRpb24sIGJlY2F1c2Ugd2UncmUgbm90IGd1YXJhbnRlZWQgdG8gaGF2ZSBvbmUgbW92ZSBldmVudFxuICAgICAgLy8gcGVyIHBpeGVsIG9mIG1vdmVtZW50IChlLmcuIGlmIHRoZSB1c2VyIG1vdmVzIHRoZWlyIHBvaW50ZXIgcXVpY2tseSkuXG4gICAgICBpZiAoaXNPdmVyVGhyZXNob2xkKSB7XG4gICAgICAgIGNvbnN0IGlzRGVsYXlFbGFwc2VkID0gRGF0ZS5ub3coKSA+PSB0aGlzLl9kcmFnU3RhcnRUaW1lICsgdGhpcy5fZ2V0RHJhZ1N0YXJ0RGVsYXkoZXZlbnQpO1xuICAgICAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLl9kcm9wQ29udGFpbmVyO1xuXG4gICAgICAgIGlmICghaXNEZWxheUVsYXBzZWQpIHtcbiAgICAgICAgICB0aGlzLl9lbmREcmFnU2VxdWVuY2UoZXZlbnQpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFByZXZlbnQgb3RoZXIgZHJhZyBzZXF1ZW5jZXMgZnJvbSBzdGFydGluZyB3aGlsZSBzb21ldGhpbmcgaW4gdGhlIGNvbnRhaW5lciBpcyBzdGlsbFxuICAgICAgICAvLyBiZWluZyBkcmFnZ2VkLiBUaGlzIGNhbiBoYXBwZW4gd2hpbGUgd2UncmUgd2FpdGluZyBmb3IgdGhlIGRyb3AgYW5pbWF0aW9uIHRvIGZpbmlzaFxuICAgICAgICAvLyBhbmQgY2FuIGNhdXNlIGVycm9ycywgYmVjYXVzZSBzb21lIGVsZW1lbnRzIG1pZ2h0IHN0aWxsIGJlIG1vdmluZyBhcm91bmQuXG4gICAgICAgIGlmICghY29udGFpbmVyIHx8ICghY29udGFpbmVyLmlzRHJhZ2dpbmcoKSAmJiAhY29udGFpbmVyLmlzUmVjZWl2aW5nKCkpKSB7XG4gICAgICAgICAgLy8gUHJldmVudCB0aGUgZGVmYXVsdCBhY3Rpb24gYXMgc29vbiBhcyB0aGUgZHJhZ2dpbmcgc2VxdWVuY2UgaXMgY29uc2lkZXJlZCBhc1xuICAgICAgICAgIC8vIFwic3RhcnRlZFwiIHNpbmNlIHdhaXRpbmcgZm9yIHRoZSBuZXh0IGV2ZW50IGNhbiBhbGxvdyB0aGUgZGV2aWNlIHRvIGJlZ2luIHNjcm9sbGluZy5cbiAgICAgICAgICBpZiAoZXZlbnQuY2FuY2VsYWJsZSkge1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5faGFzU3RhcnRlZERyYWdnaW5nLnNldCh0cnVlKTtcbiAgICAgICAgICB0aGlzLl9uZ1pvbmUucnVuKCgpID0+IHRoaXMuX3N0YXJ0RHJhZ1NlcXVlbmNlKGV2ZW50KSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFdlIHByZXZlbnQgdGhlIGRlZmF1bHQgYWN0aW9uIGRvd24gaGVyZSBzbyB0aGF0IHdlIGtub3cgdGhhdCBkcmFnZ2luZyBoYXMgc3RhcnRlZC4gVGhpcyBpc1xuICAgIC8vIGltcG9ydGFudCBmb3IgdG91Y2ggZGV2aWNlcyB3aGVyZSBkb2luZyB0aGlzIHRvbyBlYXJseSBjYW4gdW5uZWNlc3NhcmlseSBibG9jayBzY3JvbGxpbmcsXG4gICAgLy8gaWYgdGhlcmUncyBhIGRyYWdnaW5nIGRlbGF5LlxuICAgIGlmIChldmVudC5jYW5jZWxhYmxlKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbnN0cmFpbmVkUG9pbnRlclBvc2l0aW9uID0gdGhpcy5fZ2V0Q29uc3RyYWluZWRQb2ludGVyUG9zaXRpb24ocG9pbnRlclBvc2l0aW9uKTtcbiAgICB0aGlzLl9oYXNNb3ZlZCA9IHRydWU7XG4gICAgdGhpcy5fbGFzdEtub3duUG9pbnRlclBvc2l0aW9uID0gcG9pbnRlclBvc2l0aW9uO1xuICAgIHRoaXMuX3VwZGF0ZVBvaW50ZXJEaXJlY3Rpb25EZWx0YShjb25zdHJhaW5lZFBvaW50ZXJQb3NpdGlvbik7XG5cbiAgICBpZiAodGhpcy5fZHJvcENvbnRhaW5lcikge1xuICAgICAgdGhpcy5fdXBkYXRlQWN0aXZlRHJvcENvbnRhaW5lcihjb25zdHJhaW5lZFBvaW50ZXJQb3NpdGlvbiwgcG9pbnRlclBvc2l0aW9uKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gSWYgdGhlcmUncyBhIHBvc2l0aW9uIGNvbnN0cmFpbnQgZnVuY3Rpb24sIHdlIHdhbnQgdGhlIGVsZW1lbnQncyB0b3AvbGVmdCB0byBiZSBhdCB0aGVcbiAgICAgIC8vIHNwZWNpZmljIHBvc2l0aW9uIG9uIHRoZSBwYWdlLiBVc2UgdGhlIGluaXRpYWwgcG9zaXRpb24gYXMgYSByZWZlcmVuY2UgaWYgdGhhdCdzIHRoZSBjYXNlLlxuICAgICAgY29uc3Qgb2Zmc2V0ID0gdGhpcy5jb25zdHJhaW5Qb3NpdGlvbiA/IHRoaXMuX2luaXRpYWxEb21SZWN0ISA6IHRoaXMuX3BpY2t1cFBvc2l0aW9uT25QYWdlO1xuICAgICAgY29uc3QgYWN0aXZlVHJhbnNmb3JtID0gdGhpcy5fYWN0aXZlVHJhbnNmb3JtO1xuICAgICAgYWN0aXZlVHJhbnNmb3JtLnggPSBjb25zdHJhaW5lZFBvaW50ZXJQb3NpdGlvbi54IC0gb2Zmc2V0LnggKyB0aGlzLl9wYXNzaXZlVHJhbnNmb3JtLng7XG4gICAgICBhY3RpdmVUcmFuc2Zvcm0ueSA9IGNvbnN0cmFpbmVkUG9pbnRlclBvc2l0aW9uLnkgLSBvZmZzZXQueSArIHRoaXMuX3Bhc3NpdmVUcmFuc2Zvcm0ueTtcbiAgICAgIHRoaXMuX2FwcGx5Um9vdEVsZW1lbnRUcmFuc2Zvcm0oYWN0aXZlVHJhbnNmb3JtLngsIGFjdGl2ZVRyYW5zZm9ybS55KTtcbiAgICB9XG5cbiAgICAvLyBTaW5jZSB0aGlzIGV2ZW50IGdldHMgZmlyZWQgZm9yIGV2ZXJ5IHBpeGVsIHdoaWxlIGRyYWdnaW5nLCB3ZSBvbmx5XG4gICAgLy8gd2FudCB0byBmaXJlIGl0IGlmIHRoZSBjb25zdW1lciBvcHRlZCBpbnRvIGl0LiBBbHNvIHdlIGhhdmUgdG9cbiAgICAvLyByZS1lbnRlciB0aGUgem9uZSBiZWNhdXNlIHdlIHJ1biBhbGwgb2YgdGhlIGV2ZW50cyBvbiB0aGUgb3V0c2lkZS5cbiAgICBpZiAodGhpcy5fbW92ZUV2ZW50cy5vYnNlcnZlcnMubGVuZ3RoKSB7XG4gICAgICB0aGlzLl9uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgdGhpcy5fbW92ZUV2ZW50cy5uZXh0KHtcbiAgICAgICAgICBzb3VyY2U6IHRoaXMsXG4gICAgICAgICAgcG9pbnRlclBvc2l0aW9uOiBjb25zdHJhaW5lZFBvaW50ZXJQb3NpdGlvbixcbiAgICAgICAgICBldmVudCxcbiAgICAgICAgICBkaXN0YW5jZTogdGhpcy5fZ2V0RHJhZ0Rpc3RhbmNlKGNvbnN0cmFpbmVkUG9pbnRlclBvc2l0aW9uKSxcbiAgICAgICAgICBkZWx0YTogdGhpcy5fcG9pbnRlckRpcmVjdGlvbkRlbHRhLFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfTtcblxuICAvKiogSGFuZGxlciB0aGF0IGlzIGludm9rZWQgd2hlbiB0aGUgdXNlciBsaWZ0cyB0aGVpciBwb2ludGVyIHVwLCBhZnRlciBpbml0aWF0aW5nIGEgZHJhZy4gKi9cbiAgcHJpdmF0ZSBfcG9pbnRlclVwID0gKGV2ZW50OiBNb3VzZUV2ZW50IHwgVG91Y2hFdmVudCkgPT4ge1xuICAgIHRoaXMuX2VuZERyYWdTZXF1ZW5jZShldmVudCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIENsZWFycyBzdWJzY3JpcHRpb25zIGFuZCBzdG9wcyB0aGUgZHJhZ2dpbmcgc2VxdWVuY2UuXG4gICAqIEBwYXJhbSBldmVudCBCcm93c2VyIGV2ZW50IG9iamVjdCB0aGF0IGVuZGVkIHRoZSBzZXF1ZW5jZS5cbiAgICovXG4gIHByaXZhdGUgX2VuZERyYWdTZXF1ZW5jZShldmVudDogTW91c2VFdmVudCB8IFRvdWNoRXZlbnQpIHtcbiAgICAvLyBOb3RlIHRoYXQgaGVyZSB3ZSB1c2UgYGlzRHJhZ2dpbmdgIGZyb20gdGhlIHNlcnZpY2UsIHJhdGhlciB0aGFuIGZyb20gYHRoaXNgLlxuICAgIC8vIFRoZSBkaWZmZXJlbmNlIGlzIHRoYXQgdGhlIG9uZSBmcm9tIHRoZSBzZXJ2aWNlIHJlZmxlY3RzIHdoZXRoZXIgYSBkcmFnZ2luZyBzZXF1ZW5jZVxuICAgIC8vIGhhcyBiZWVuIGluaXRpYXRlZCwgd2hlcmVhcyB0aGUgb25lIG9uIGB0aGlzYCBpbmNsdWRlcyB3aGV0aGVyIHRoZSB1c2VyIGhhcyBwYXNzZWRcbiAgICAvLyB0aGUgbWluaW11bSBkcmFnZ2luZyB0aHJlc2hvbGQuXG4gICAgaWYgKCF0aGlzLl9kcmFnRHJvcFJlZ2lzdHJ5LmlzRHJhZ2dpbmcodGhpcykpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9yZW1vdmVMaXN0ZW5lcnMoKTtcbiAgICB0aGlzLl9kcmFnRHJvcFJlZ2lzdHJ5LnN0b3BEcmFnZ2luZyh0aGlzKTtcbiAgICB0aGlzLl90b2dnbGVOYXRpdmVEcmFnSW50ZXJhY3Rpb25zKCk7XG5cbiAgICBpZiAodGhpcy5faGFuZGxlcykge1xuICAgICAgKHRoaXMuX3Jvb3RFbGVtZW50LnN0eWxlIGFzIERyYWdDU1NTdHlsZURlY2xhcmF0aW9uKS53ZWJraXRUYXBIaWdobGlnaHRDb2xvciA9XG4gICAgICAgIHRoaXMuX3Jvb3RFbGVtZW50VGFwSGlnaGxpZ2h0O1xuICAgIH1cblxuICAgIGlmICghdGhpcy5faGFzU3RhcnRlZERyYWdnaW5nKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnJlbGVhc2VkLm5leHQoe3NvdXJjZTogdGhpcywgZXZlbnR9KTtcblxuICAgIGlmICh0aGlzLl9kcm9wQ29udGFpbmVyKSB7XG4gICAgICAvLyBTdG9wIHNjcm9sbGluZyBpbW1lZGlhdGVseSwgaW5zdGVhZCBvZiB3YWl0aW5nIGZvciB0aGUgYW5pbWF0aW9uIHRvIGZpbmlzaC5cbiAgICAgIHRoaXMuX2Ryb3BDb250YWluZXIuX3N0b3BTY3JvbGxpbmcoKTtcbiAgICAgIHRoaXMuX2FuaW1hdGVQcmV2aWV3VG9QbGFjZWhvbGRlcigpLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLl9jbGVhbnVwRHJhZ0FydGlmYWN0cyhldmVudCk7XG4gICAgICAgIHRoaXMuX2NsZWFudXBDYWNoZWREaW1lbnNpb25zKCk7XG4gICAgICAgIHRoaXMuX2RyYWdEcm9wUmVnaXN0cnkuc3RvcERyYWdnaW5nKHRoaXMpO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIENvbnZlcnQgdGhlIGFjdGl2ZSB0cmFuc2Zvcm0gaW50byBhIHBhc3NpdmUgb25lLiBUaGlzIG1lYW5zIHRoYXQgbmV4dCB0aW1lXG4gICAgICAvLyB0aGUgdXNlciBzdGFydHMgZHJhZ2dpbmcgdGhlIGl0ZW0sIGl0cyBwb3NpdGlvbiB3aWxsIGJlIGNhbGN1bGF0ZWQgcmVsYXRpdmVseVxuICAgICAgLy8gdG8gdGhlIG5ldyBwYXNzaXZlIHRyYW5zZm9ybS5cbiAgICAgIHRoaXMuX3Bhc3NpdmVUcmFuc2Zvcm0ueCA9IHRoaXMuX2FjdGl2ZVRyYW5zZm9ybS54O1xuICAgICAgY29uc3QgcG9pbnRlclBvc2l0aW9uID0gdGhpcy5fZ2V0UG9pbnRlclBvc2l0aW9uT25QYWdlKGV2ZW50KTtcbiAgICAgIHRoaXMuX3Bhc3NpdmVUcmFuc2Zvcm0ueSA9IHRoaXMuX2FjdGl2ZVRyYW5zZm9ybS55O1xuICAgICAgdGhpcy5fbmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgIHRoaXMuZW5kZWQubmV4dCh7XG4gICAgICAgICAgc291cmNlOiB0aGlzLFxuICAgICAgICAgIGRpc3RhbmNlOiB0aGlzLl9nZXREcmFnRGlzdGFuY2UocG9pbnRlclBvc2l0aW9uKSxcbiAgICAgICAgICBkcm9wUG9pbnQ6IHBvaW50ZXJQb3NpdGlvbixcbiAgICAgICAgICBldmVudCxcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICAgIHRoaXMuX2NsZWFudXBDYWNoZWREaW1lbnNpb25zKCk7XG4gICAgICB0aGlzLl9kcmFnRHJvcFJlZ2lzdHJ5LnN0b3BEcmFnZ2luZyh0aGlzKTtcbiAgICB9XG4gIH1cblxuICAvKiogU3RhcnRzIHRoZSBkcmFnZ2luZyBzZXF1ZW5jZS4gKi9cbiAgcHJpdmF0ZSBfc3RhcnREcmFnU2VxdWVuY2UoZXZlbnQ6IE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50KSB7XG4gICAgaWYgKGlzVG91Y2hFdmVudChldmVudCkpIHtcbiAgICAgIHRoaXMuX2xhc3RUb3VjaEV2ZW50VGltZSA9IERhdGUubm93KCk7XG4gICAgfVxuXG4gICAgdGhpcy5fdG9nZ2xlTmF0aXZlRHJhZ0ludGVyYWN0aW9ucygpO1xuXG4gICAgLy8gTmVlZHMgdG8gaGFwcGVuIGJlZm9yZSB0aGUgcm9vdCBlbGVtZW50IGlzIG1vdmVkLlxuICAgIGNvbnN0IHNoYWRvd1Jvb3QgPSB0aGlzLl9nZXRTaGFkb3dSb290KCk7XG4gICAgY29uc3QgZHJvcENvbnRhaW5lciA9IHRoaXMuX2Ryb3BDb250YWluZXI7XG5cbiAgICBpZiAoc2hhZG93Um9vdCkge1xuICAgICAgLy8gSW4gc29tZSBicm93c2VycyB0aGUgZ2xvYmFsIGBzZWxlY3RzdGFydGAgdGhhdCB3ZSBtYWludGFpbiBpbiB0aGUgYERyYWdEcm9wUmVnaXN0cnlgXG4gICAgICAvLyBkb2Vzbid0IGNyb3NzIHRoZSBzaGFkb3cgYm91bmRhcnkgc28gd2UgaGF2ZSB0byBwcmV2ZW50IGl0IGF0IHRoZSBzaGFkb3cgcm9vdCAoc2VlICMyODc5MikuXG4gICAgICB0aGlzLl9uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgICBzaGFkb3dSb290LmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgJ3NlbGVjdHN0YXJ0JyxcbiAgICAgICAgICBzaGFkb3dEb21TZWxlY3RTdGFydCxcbiAgICAgICAgICBhY3RpdmVDYXB0dXJpbmdFdmVudE9wdGlvbnMsXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAoZHJvcENvbnRhaW5lcikge1xuICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuX3Jvb3RFbGVtZW50O1xuICAgICAgY29uc3QgcGFyZW50ID0gZWxlbWVudC5wYXJlbnROb2RlIGFzIEhUTUxFbGVtZW50O1xuICAgICAgY29uc3QgcGxhY2Vob2xkZXIgPSAodGhpcy5fcGxhY2Vob2xkZXIgPSB0aGlzLl9jcmVhdGVQbGFjZWhvbGRlckVsZW1lbnQoKSk7XG4gICAgICBjb25zdCBhbmNob3IgPSAodGhpcy5fYW5jaG9yID1cbiAgICAgICAgdGhpcy5fYW5jaG9yIHx8IHRoaXMuX2RvY3VtZW50LmNyZWF0ZUNvbW1lbnQobmdEZXZNb2RlID8gJ2Nkay1kcmFnLWFuY2hvcicgOiAnJykpO1xuXG4gICAgICAvLyBJbnNlcnQgYW4gYW5jaG9yIG5vZGUgc28gdGhhdCB3ZSBjYW4gcmVzdG9yZSB0aGUgZWxlbWVudCdzIHBvc2l0aW9uIGluIHRoZSBET00uXG4gICAgICBwYXJlbnQuaW5zZXJ0QmVmb3JlKGFuY2hvciwgZWxlbWVudCk7XG5cbiAgICAgIC8vIFRoZXJlJ3Mgbm8gcmlzayBvZiB0cmFuc2Zvcm1zIHN0YWNraW5nIHdoZW4gaW5zaWRlIGEgZHJvcCBjb250YWluZXIgc29cbiAgICAgIC8vIHdlIGNhbiBrZWVwIHRoZSBpbml0aWFsIHRyYW5zZm9ybSB1cCB0byBkYXRlIGFueSB0aW1lIGRyYWdnaW5nIHN0YXJ0cy5cbiAgICAgIHRoaXMuX2luaXRpYWxUcmFuc2Zvcm0gPSBlbGVtZW50LnN0eWxlLnRyYW5zZm9ybSB8fCAnJztcblxuICAgICAgLy8gQ3JlYXRlIHRoZSBwcmV2aWV3IGFmdGVyIHRoZSBpbml0aWFsIHRyYW5zZm9ybSBoYXNcbiAgICAgIC8vIGJlZW4gY2FjaGVkLCBiZWNhdXNlIGl0IGNhbiBiZSBhZmZlY3RlZCBieSB0aGUgdHJhbnNmb3JtLlxuICAgICAgdGhpcy5fcHJldmlldyA9IG5ldyBQcmV2aWV3UmVmKFxuICAgICAgICB0aGlzLl9kb2N1bWVudCxcbiAgICAgICAgdGhpcy5fcm9vdEVsZW1lbnQsXG4gICAgICAgIHRoaXMuX2RpcmVjdGlvbixcbiAgICAgICAgdGhpcy5faW5pdGlhbERvbVJlY3QhLFxuICAgICAgICB0aGlzLl9wcmV2aWV3VGVtcGxhdGUgfHwgbnVsbCxcbiAgICAgICAgdGhpcy5wcmV2aWV3Q2xhc3MgfHwgbnVsbCxcbiAgICAgICAgdGhpcy5fcGlja3VwUG9zaXRpb25PblBhZ2UsXG4gICAgICAgIHRoaXMuX2luaXRpYWxUcmFuc2Zvcm0sXG4gICAgICAgIHRoaXMuX2NvbmZpZy56SW5kZXggfHwgMTAwMCxcbiAgICAgICk7XG4gICAgICB0aGlzLl9wcmV2aWV3LmF0dGFjaCh0aGlzLl9nZXRQcmV2aWV3SW5zZXJ0aW9uUG9pbnQocGFyZW50LCBzaGFkb3dSb290KSk7XG5cbiAgICAgIC8vIFdlIG1vdmUgdGhlIGVsZW1lbnQgb3V0IGF0IHRoZSBlbmQgb2YgdGhlIGJvZHkgYW5kIHdlIG1ha2UgaXQgaGlkZGVuLCBiZWNhdXNlIGtlZXBpbmcgaXQgaW5cbiAgICAgIC8vIHBsYWNlIHdpbGwgdGhyb3cgb2ZmIHRoZSBjb25zdW1lcidzIGA6bGFzdC1jaGlsZGAgc2VsZWN0b3JzLiBXZSBjYW4ndCByZW1vdmUgdGhlIGVsZW1lbnRcbiAgICAgIC8vIGZyb20gdGhlIERPTSBjb21wbGV0ZWx5LCBiZWNhdXNlIGlPUyB3aWxsIHN0b3AgZmlyaW5nIGFsbCBzdWJzZXF1ZW50IGV2ZW50cyBpbiB0aGUgY2hhaW4uXG4gICAgICB0b2dnbGVWaXNpYmlsaXR5KGVsZW1lbnQsIGZhbHNlLCBkcmFnSW1wb3J0YW50UHJvcGVydGllcyk7XG4gICAgICB0aGlzLl9kb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHBhcmVudC5yZXBsYWNlQ2hpbGQocGxhY2Vob2xkZXIsIGVsZW1lbnQpKTtcbiAgICAgIHRoaXMuc3RhcnRlZC5uZXh0KHtzb3VyY2U6IHRoaXMsIGV2ZW50fSk7IC8vIEVtaXQgYmVmb3JlIG5vdGlmeWluZyB0aGUgY29udGFpbmVyLlxuICAgICAgZHJvcENvbnRhaW5lci5zdGFydCgpO1xuICAgICAgdGhpcy5faW5pdGlhbENvbnRhaW5lciA9IGRyb3BDb250YWluZXI7XG4gICAgICB0aGlzLl9pbml0aWFsSW5kZXggPSBkcm9wQ29udGFpbmVyLmdldEl0ZW1JbmRleCh0aGlzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zdGFydGVkLm5leHQoe3NvdXJjZTogdGhpcywgZXZlbnR9KTtcbiAgICAgIHRoaXMuX2luaXRpYWxDb250YWluZXIgPSB0aGlzLl9pbml0aWFsSW5kZXggPSB1bmRlZmluZWQhO1xuICAgIH1cblxuICAgIC8vIEltcG9ydGFudCB0byBydW4gYWZ0ZXIgd2UndmUgY2FsbGVkIGBzdGFydGAgb24gdGhlIHBhcmVudCBjb250YWluZXJcbiAgICAvLyBzbyB0aGF0IGl0IGhhcyBoYWQgdGltZSB0byByZXNvbHZlIGl0cyBzY3JvbGxhYmxlIHBhcmVudHMuXG4gICAgdGhpcy5fcGFyZW50UG9zaXRpb25zLmNhY2hlKGRyb3BDb250YWluZXIgPyBkcm9wQ29udGFpbmVyLmdldFNjcm9sbGFibGVQYXJlbnRzKCkgOiBbXSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB1cCB0aGUgZGlmZmVyZW50IHZhcmlhYmxlcyBhbmQgc3Vic2NyaXB0aW9uc1xuICAgKiB0aGF0IHdpbGwgYmUgbmVjZXNzYXJ5IGZvciB0aGUgZHJhZ2dpbmcgc2VxdWVuY2UuXG4gICAqIEBwYXJhbSByZWZlcmVuY2VFbGVtZW50IEVsZW1lbnQgdGhhdCBzdGFydGVkIHRoZSBkcmFnIHNlcXVlbmNlLlxuICAgKiBAcGFyYW0gZXZlbnQgQnJvd3NlciBldmVudCBvYmplY3QgdGhhdCBzdGFydGVkIHRoZSBzZXF1ZW5jZS5cbiAgICovXG4gIHByaXZhdGUgX2luaXRpYWxpemVEcmFnU2VxdWVuY2UocmVmZXJlbmNlRWxlbWVudDogSFRNTEVsZW1lbnQsIGV2ZW50OiBNb3VzZUV2ZW50IHwgVG91Y2hFdmVudCkge1xuICAgIC8vIFN0b3AgcHJvcGFnYXRpb24gaWYgdGhlIGl0ZW0gaXMgaW5zaWRlIGFub3RoZXJcbiAgICAvLyBkcmFnZ2FibGUgc28gd2UgZG9uJ3Qgc3RhcnQgbXVsdGlwbGUgZHJhZyBzZXF1ZW5jZXMuXG4gICAgaWYgKHRoaXMuX3BhcmVudERyYWdSZWYpIHtcbiAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIH1cblxuICAgIGNvbnN0IGlzRHJhZ2dpbmcgPSB0aGlzLmlzRHJhZ2dpbmcoKTtcbiAgICBjb25zdCBpc1RvdWNoU2VxdWVuY2UgPSBpc1RvdWNoRXZlbnQoZXZlbnQpO1xuICAgIGNvbnN0IGlzQXV4aWxpYXJ5TW91c2VCdXR0b24gPSAhaXNUb3VjaFNlcXVlbmNlICYmIChldmVudCBhcyBNb3VzZUV2ZW50KS5idXR0b24gIT09IDA7XG4gICAgY29uc3Qgcm9vdEVsZW1lbnQgPSB0aGlzLl9yb290RWxlbWVudDtcbiAgICBjb25zdCB0YXJnZXQgPSBfZ2V0RXZlbnRUYXJnZXQoZXZlbnQpO1xuICAgIGNvbnN0IGlzU3ludGhldGljRXZlbnQgPVxuICAgICAgIWlzVG91Y2hTZXF1ZW5jZSAmJlxuICAgICAgdGhpcy5fbGFzdFRvdWNoRXZlbnRUaW1lICYmXG4gICAgICB0aGlzLl9sYXN0VG91Y2hFdmVudFRpbWUgKyBNT1VTRV9FVkVOVF9JR05PUkVfVElNRSA+IERhdGUubm93KCk7XG4gICAgY29uc3QgaXNGYWtlRXZlbnQgPSBpc1RvdWNoU2VxdWVuY2VcbiAgICAgID8gaXNGYWtlVG91Y2hzdGFydEZyb21TY3JlZW5SZWFkZXIoZXZlbnQgYXMgVG91Y2hFdmVudClcbiAgICAgIDogaXNGYWtlTW91c2Vkb3duRnJvbVNjcmVlblJlYWRlcihldmVudCBhcyBNb3VzZUV2ZW50KTtcblxuICAgIC8vIElmIHRoZSBldmVudCBzdGFydGVkIGZyb20gYW4gZWxlbWVudCB3aXRoIHRoZSBuYXRpdmUgSFRNTCBkcmFnJmRyb3AsIGl0J2xsIGludGVyZmVyZVxuICAgIC8vIHdpdGggb3VyIG93biBkcmFnZ2luZyAoZS5nLiBgaW1nYCB0YWdzIGRvIGl0IGJ5IGRlZmF1bHQpLiBQcmV2ZW50IHRoZSBkZWZhdWx0IGFjdGlvblxuICAgIC8vIHRvIHN0b3AgaXQgZnJvbSBoYXBwZW5pbmcuIE5vdGUgdGhhdCBwcmV2ZW50aW5nIG9uIGBkcmFnc3RhcnRgIGFsc28gc2VlbXMgdG8gd29yaywgYnV0XG4gICAgLy8gaXQncyBmbGFreSBhbmQgaXQgZmFpbHMgaWYgdGhlIHVzZXIgZHJhZ3MgaXQgYXdheSBxdWlja2x5LiBBbHNvIG5vdGUgdGhhdCB3ZSBvbmx5IHdhbnRcbiAgICAvLyB0byBkbyB0aGlzIGZvciBgbW91c2Vkb3duYCBzaW5jZSBkb2luZyB0aGUgc2FtZSBmb3IgYHRvdWNoc3RhcnRgIHdpbGwgc3RvcCBhbnkgYGNsaWNrYFxuICAgIC8vIGV2ZW50cyBmcm9tIGZpcmluZyBvbiB0b3VjaCBkZXZpY2VzLlxuICAgIGlmICh0YXJnZXQgJiYgKHRhcmdldCBhcyBIVE1MRWxlbWVudCkuZHJhZ2dhYmxlICYmIGV2ZW50LnR5cGUgPT09ICdtb3VzZWRvd24nKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIC8vIEFib3J0IGlmIHRoZSB1c2VyIGlzIGFscmVhZHkgZHJhZ2dpbmcgb3IgaXMgdXNpbmcgYSBtb3VzZSBidXR0b24gb3RoZXIgdGhhbiB0aGUgcHJpbWFyeSBvbmUuXG4gICAgaWYgKGlzRHJhZ2dpbmcgfHwgaXNBdXhpbGlhcnlNb3VzZUJ1dHRvbiB8fCBpc1N5bnRoZXRpY0V2ZW50IHx8IGlzRmFrZUV2ZW50KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gSWYgd2UndmUgZ290IGhhbmRsZXMsIHdlIG5lZWQgdG8gZGlzYWJsZSB0aGUgdGFwIGhpZ2hsaWdodCBvbiB0aGUgZW50aXJlIHJvb3QgZWxlbWVudCxcbiAgICAvLyBvdGhlcndpc2UgaU9TIHdpbGwgc3RpbGwgYWRkIGl0LCBldmVuIHRob3VnaCBhbGwgdGhlIGRyYWcgaW50ZXJhY3Rpb25zIG9uIHRoZSBoYW5kbGVcbiAgICAvLyBhcmUgZGlzYWJsZWQuXG4gICAgaWYgKHRoaXMuX2hhbmRsZXMubGVuZ3RoKSB7XG4gICAgICBjb25zdCByb290U3R5bGVzID0gcm9vdEVsZW1lbnQuc3R5bGUgYXMgRHJhZ0NTU1N0eWxlRGVjbGFyYXRpb247XG4gICAgICB0aGlzLl9yb290RWxlbWVudFRhcEhpZ2hsaWdodCA9IHJvb3RTdHlsZXMud2Via2l0VGFwSGlnaGxpZ2h0Q29sb3IgfHwgJyc7XG4gICAgICByb290U3R5bGVzLndlYmtpdFRhcEhpZ2hsaWdodENvbG9yID0gJ3RyYW5zcGFyZW50JztcbiAgICB9XG5cbiAgICB0aGlzLl9oYXNNb3ZlZCA9IGZhbHNlO1xuICAgIHRoaXMuX2hhc1N0YXJ0ZWREcmFnZ2luZy5zZXQodGhpcy5faGFzTW92ZWQpO1xuXG4gICAgLy8gQXZvaWQgbXVsdGlwbGUgc3Vic2NyaXB0aW9ucyBhbmQgbWVtb3J5IGxlYWtzIHdoZW4gbXVsdGkgdG91Y2hcbiAgICAvLyAoaXNEcmFnZ2luZyBjaGVjayBhYm92ZSBpc24ndCBlbm91Z2ggYmVjYXVzZSBvZiBwb3NzaWJsZSB0ZW1wb3JhbCBhbmQvb3IgZGltZW5zaW9uYWwgZGVsYXlzKVxuICAgIHRoaXMuX3JlbW92ZUxpc3RlbmVycygpO1xuICAgIHRoaXMuX2luaXRpYWxEb21SZWN0ID0gdGhpcy5fcm9vdEVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgdGhpcy5fcG9pbnRlck1vdmVTdWJzY3JpcHRpb24gPSB0aGlzLl9kcmFnRHJvcFJlZ2lzdHJ5LnBvaW50ZXJNb3ZlLnN1YnNjcmliZSh0aGlzLl9wb2ludGVyTW92ZSk7XG4gICAgdGhpcy5fcG9pbnRlclVwU3Vic2NyaXB0aW9uID0gdGhpcy5fZHJhZ0Ryb3BSZWdpc3RyeS5wb2ludGVyVXAuc3Vic2NyaWJlKHRoaXMuX3BvaW50ZXJVcCk7XG4gICAgdGhpcy5fc2Nyb2xsU3Vic2NyaXB0aW9uID0gdGhpcy5fZHJhZ0Ryb3BSZWdpc3RyeVxuICAgICAgLnNjcm9sbGVkKHRoaXMuX2dldFNoYWRvd1Jvb3QoKSlcbiAgICAgIC5zdWJzY3JpYmUoc2Nyb2xsRXZlbnQgPT4gdGhpcy5fdXBkYXRlT25TY3JvbGwoc2Nyb2xsRXZlbnQpKTtcblxuICAgIGlmICh0aGlzLl9ib3VuZGFyeUVsZW1lbnQpIHtcbiAgICAgIHRoaXMuX2JvdW5kYXJ5UmVjdCA9IGdldE11dGFibGVDbGllbnRSZWN0KHRoaXMuX2JvdW5kYXJ5RWxlbWVudCk7XG4gICAgfVxuXG4gICAgLy8gSWYgd2UgaGF2ZSBhIGN1c3RvbSBwcmV2aWV3IHdlIGNhbid0IGtub3cgYWhlYWQgb2YgdGltZSBob3cgbGFyZ2UgaXQnbGwgYmUgc28gd2UgcG9zaXRpb25cbiAgICAvLyBpdCBuZXh0IHRvIHRoZSBjdXJzb3IuIFRoZSBleGNlcHRpb24gaXMgd2hlbiB0aGUgY29uc3VtZXIgaGFzIG9wdGVkIGludG8gbWFraW5nIHRoZSBwcmV2aWV3XG4gICAgLy8gdGhlIHNhbWUgc2l6ZSBhcyB0aGUgcm9vdCBlbGVtZW50LCBpbiB3aGljaCBjYXNlIHdlIGRvIGtub3cgdGhlIHNpemUuXG4gICAgY29uc3QgcHJldmlld1RlbXBsYXRlID0gdGhpcy5fcHJldmlld1RlbXBsYXRlO1xuICAgIHRoaXMuX3BpY2t1cFBvc2l0aW9uSW5FbGVtZW50ID1cbiAgICAgIHByZXZpZXdUZW1wbGF0ZSAmJiBwcmV2aWV3VGVtcGxhdGUudGVtcGxhdGUgJiYgIXByZXZpZXdUZW1wbGF0ZS5tYXRjaFNpemVcbiAgICAgICAgPyB7eDogMCwgeTogMH1cbiAgICAgICAgOiB0aGlzLl9nZXRQb2ludGVyUG9zaXRpb25JbkVsZW1lbnQodGhpcy5faW5pdGlhbERvbVJlY3QsIHJlZmVyZW5jZUVsZW1lbnQsIGV2ZW50KTtcbiAgICBjb25zdCBwb2ludGVyUG9zaXRpb24gPVxuICAgICAgKHRoaXMuX3BpY2t1cFBvc2l0aW9uT25QYWdlID1cbiAgICAgIHRoaXMuX2xhc3RLbm93blBvaW50ZXJQb3NpdGlvbiA9XG4gICAgICAgIHRoaXMuX2dldFBvaW50ZXJQb3NpdGlvbk9uUGFnZShldmVudCkpO1xuICAgIHRoaXMuX3BvaW50ZXJEaXJlY3Rpb25EZWx0YSA9IHt4OiAwLCB5OiAwfTtcbiAgICB0aGlzLl9wb2ludGVyUG9zaXRpb25BdExhc3REaXJlY3Rpb25DaGFuZ2UgPSB7eDogcG9pbnRlclBvc2l0aW9uLngsIHk6IHBvaW50ZXJQb3NpdGlvbi55fTtcbiAgICB0aGlzLl9kcmFnU3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICB0aGlzLl9kcmFnRHJvcFJlZ2lzdHJ5LnN0YXJ0RHJhZ2dpbmcodGhpcywgZXZlbnQpO1xuICB9XG5cbiAgLyoqIENsZWFucyB1cCB0aGUgRE9NIGFydGlmYWN0cyB0aGF0IHdlcmUgYWRkZWQgdG8gZmFjaWxpdGF0ZSB0aGUgZWxlbWVudCBiZWluZyBkcmFnZ2VkLiAqL1xuICBwcml2YXRlIF9jbGVhbnVwRHJhZ0FydGlmYWN0cyhldmVudDogTW91c2VFdmVudCB8IFRvdWNoRXZlbnQpIHtcbiAgICAvLyBSZXN0b3JlIHRoZSBlbGVtZW50J3MgdmlzaWJpbGl0eSBhbmQgaW5zZXJ0IGl0IGF0IGl0cyBvbGQgcG9zaXRpb24gaW4gdGhlIERPTS5cbiAgICAvLyBJdCdzIGltcG9ydGFudCB0aGF0IHdlIG1haW50YWluIHRoZSBwb3NpdGlvbiwgYmVjYXVzZSBtb3ZpbmcgdGhlIGVsZW1lbnQgYXJvdW5kIGluIHRoZSBET01cbiAgICAvLyBjYW4gdGhyb3cgb2ZmIGBOZ0ZvcmAgd2hpY2ggZG9lcyBzbWFydCBkaWZmaW5nIGFuZCByZS1jcmVhdGVzIGVsZW1lbnRzIG9ubHkgd2hlbiBuZWNlc3NhcnksXG4gICAgLy8gd2hpbGUgbW92aW5nIHRoZSBleGlzdGluZyBlbGVtZW50cyBpbiBhbGwgb3RoZXIgY2FzZXMuXG4gICAgdG9nZ2xlVmlzaWJpbGl0eSh0aGlzLl9yb290RWxlbWVudCwgdHJ1ZSwgZHJhZ0ltcG9ydGFudFByb3BlcnRpZXMpO1xuICAgIHRoaXMuX2FuY2hvci5wYXJlbnROb2RlIS5yZXBsYWNlQ2hpbGQodGhpcy5fcm9vdEVsZW1lbnQsIHRoaXMuX2FuY2hvcik7XG5cbiAgICB0aGlzLl9kZXN0cm95UHJldmlldygpO1xuICAgIHRoaXMuX2Rlc3Ryb3lQbGFjZWhvbGRlcigpO1xuICAgIHRoaXMuX2luaXRpYWxEb21SZWN0ID1cbiAgICAgIHRoaXMuX2JvdW5kYXJ5UmVjdCA9XG4gICAgICB0aGlzLl9wcmV2aWV3UmVjdCA9XG4gICAgICB0aGlzLl9pbml0aWFsVHJhbnNmb3JtID1cbiAgICAgICAgdW5kZWZpbmVkO1xuXG4gICAgLy8gUmUtZW50ZXIgdGhlIE5nWm9uZSBzaW5jZSB3ZSBib3VuZCBgZG9jdW1lbnRgIGV2ZW50cyBvbiB0aGUgb3V0c2lkZS5cbiAgICB0aGlzLl9uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgIGNvbnN0IGNvbnRhaW5lciA9IHRoaXMuX2Ryb3BDb250YWluZXIhO1xuICAgICAgY29uc3QgY3VycmVudEluZGV4ID0gY29udGFpbmVyLmdldEl0ZW1JbmRleCh0aGlzKTtcbiAgICAgIGNvbnN0IHBvaW50ZXJQb3NpdGlvbiA9IHRoaXMuX2dldFBvaW50ZXJQb3NpdGlvbk9uUGFnZShldmVudCk7XG4gICAgICBjb25zdCBkaXN0YW5jZSA9IHRoaXMuX2dldERyYWdEaXN0YW5jZShwb2ludGVyUG9zaXRpb24pO1xuICAgICAgY29uc3QgaXNQb2ludGVyT3ZlckNvbnRhaW5lciA9IGNvbnRhaW5lci5faXNPdmVyQ29udGFpbmVyKFxuICAgICAgICBwb2ludGVyUG9zaXRpb24ueCxcbiAgICAgICAgcG9pbnRlclBvc2l0aW9uLnksXG4gICAgICApO1xuXG4gICAgICB0aGlzLmVuZGVkLm5leHQoe3NvdXJjZTogdGhpcywgZGlzdGFuY2UsIGRyb3BQb2ludDogcG9pbnRlclBvc2l0aW9uLCBldmVudH0pO1xuICAgICAgdGhpcy5kcm9wcGVkLm5leHQoe1xuICAgICAgICBpdGVtOiB0aGlzLFxuICAgICAgICBjdXJyZW50SW5kZXgsXG4gICAgICAgIHByZXZpb3VzSW5kZXg6IHRoaXMuX2luaXRpYWxJbmRleCxcbiAgICAgICAgY29udGFpbmVyOiBjb250YWluZXIsXG4gICAgICAgIHByZXZpb3VzQ29udGFpbmVyOiB0aGlzLl9pbml0aWFsQ29udGFpbmVyLFxuICAgICAgICBpc1BvaW50ZXJPdmVyQ29udGFpbmVyLFxuICAgICAgICBkaXN0YW5jZSxcbiAgICAgICAgZHJvcFBvaW50OiBwb2ludGVyUG9zaXRpb24sXG4gICAgICAgIGV2ZW50LFxuICAgICAgfSk7XG4gICAgICBjb250YWluZXIuZHJvcChcbiAgICAgICAgdGhpcyxcbiAgICAgICAgY3VycmVudEluZGV4LFxuICAgICAgICB0aGlzLl9pbml0aWFsSW5kZXgsXG4gICAgICAgIHRoaXMuX2luaXRpYWxDb250YWluZXIsXG4gICAgICAgIGlzUG9pbnRlck92ZXJDb250YWluZXIsXG4gICAgICAgIGRpc3RhbmNlLFxuICAgICAgICBwb2ludGVyUG9zaXRpb24sXG4gICAgICAgIGV2ZW50LFxuICAgICAgKTtcbiAgICAgIHRoaXMuX2Ryb3BDb250YWluZXIgPSB0aGlzLl9pbml0aWFsQ29udGFpbmVyO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZXMgdGhlIGl0ZW0ncyBwb3NpdGlvbiBpbiBpdHMgZHJvcCBjb250YWluZXIsIG9yIG1vdmVzIGl0XG4gICAqIGludG8gYSBuZXcgb25lLCBkZXBlbmRpbmcgb24gaXRzIGN1cnJlbnQgZHJhZyBwb3NpdGlvbi5cbiAgICovXG4gIHByaXZhdGUgX3VwZGF0ZUFjdGl2ZURyb3BDb250YWluZXIoe3gsIHl9OiBQb2ludCwge3g6IHJhd1gsIHk6IHJhd1l9OiBQb2ludCkge1xuICAgIC8vIERyb3AgY29udGFpbmVyIHRoYXQgZHJhZ2dhYmxlIGhhcyBiZWVuIG1vdmVkIGludG8uXG4gICAgbGV0IG5ld0NvbnRhaW5lciA9IHRoaXMuX2luaXRpYWxDb250YWluZXIuX2dldFNpYmxpbmdDb250YWluZXJGcm9tUG9zaXRpb24odGhpcywgeCwgeSk7XG5cbiAgICAvLyBJZiB3ZSBjb3VsZG4ndCBmaW5kIGEgbmV3IGNvbnRhaW5lciB0byBtb3ZlIHRoZSBpdGVtIGludG8sIGFuZCB0aGUgaXRlbSBoYXMgbGVmdCBpdHNcbiAgICAvLyBpbml0aWFsIGNvbnRhaW5lciwgY2hlY2sgd2hldGhlciB0aGUgaXQncyBvdmVyIHRoZSBpbml0aWFsIGNvbnRhaW5lci4gVGhpcyBoYW5kbGVzIHRoZVxuICAgIC8vIGNhc2Ugd2hlcmUgdHdvIGNvbnRhaW5lcnMgYXJlIGNvbm5lY3RlZCBvbmUgd2F5IGFuZCB0aGUgdXNlciB0cmllcyB0byB1bmRvIGRyYWdnaW5nIGFuXG4gICAgLy8gaXRlbSBpbnRvIGEgbmV3IGNvbnRhaW5lci5cbiAgICBpZiAoXG4gICAgICAhbmV3Q29udGFpbmVyICYmXG4gICAgICB0aGlzLl9kcm9wQ29udGFpbmVyICE9PSB0aGlzLl9pbml0aWFsQ29udGFpbmVyICYmXG4gICAgICB0aGlzLl9pbml0aWFsQ29udGFpbmVyLl9pc092ZXJDb250YWluZXIoeCwgeSlcbiAgICApIHtcbiAgICAgIG5ld0NvbnRhaW5lciA9IHRoaXMuX2luaXRpYWxDb250YWluZXI7XG4gICAgfVxuXG4gICAgaWYgKG5ld0NvbnRhaW5lciAmJiBuZXdDb250YWluZXIgIT09IHRoaXMuX2Ryb3BDb250YWluZXIpIHtcbiAgICAgIHRoaXMuX25nWm9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAvLyBOb3RpZnkgdGhlIG9sZCBjb250YWluZXIgdGhhdCB0aGUgaXRlbSBoYXMgbGVmdC5cbiAgICAgICAgdGhpcy5leGl0ZWQubmV4dCh7aXRlbTogdGhpcywgY29udGFpbmVyOiB0aGlzLl9kcm9wQ29udGFpbmVyIX0pO1xuICAgICAgICB0aGlzLl9kcm9wQ29udGFpbmVyIS5leGl0KHRoaXMpO1xuICAgICAgICAvLyBOb3RpZnkgdGhlIG5ldyBjb250YWluZXIgdGhhdCB0aGUgaXRlbSBoYXMgZW50ZXJlZC5cbiAgICAgICAgdGhpcy5fZHJvcENvbnRhaW5lciA9IG5ld0NvbnRhaW5lciE7XG4gICAgICAgIHRoaXMuX2Ryb3BDb250YWluZXIuZW50ZXIoXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICB4LFxuICAgICAgICAgIHksXG4gICAgICAgICAgbmV3Q29udGFpbmVyID09PSB0aGlzLl9pbml0aWFsQ29udGFpbmVyICYmXG4gICAgICAgICAgICAvLyBJZiB3ZSdyZSByZS1lbnRlcmluZyB0aGUgaW5pdGlhbCBjb250YWluZXIgYW5kIHNvcnRpbmcgaXMgZGlzYWJsZWQsXG4gICAgICAgICAgICAvLyBwdXQgaXRlbSB0aGUgaW50byBpdHMgc3RhcnRpbmcgaW5kZXggdG8gYmVnaW4gd2l0aC5cbiAgICAgICAgICAgIG5ld0NvbnRhaW5lci5zb3J0aW5nRGlzYWJsZWRcbiAgICAgICAgICAgID8gdGhpcy5faW5pdGlhbEluZGV4XG4gICAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5lbnRlcmVkLm5leHQoe1xuICAgICAgICAgIGl0ZW06IHRoaXMsXG4gICAgICAgICAgY29udGFpbmVyOiBuZXdDb250YWluZXIhLFxuICAgICAgICAgIGN1cnJlbnRJbmRleDogbmV3Q29udGFpbmVyIS5nZXRJdGVtSW5kZXgodGhpcyksXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gRHJhZ2dpbmcgbWF5IGhhdmUgYmVlbiBpbnRlcnJ1cHRlZCBhcyBhIHJlc3VsdCBvZiB0aGUgZXZlbnRzIGFib3ZlLlxuICAgIGlmICh0aGlzLmlzRHJhZ2dpbmcoKSkge1xuICAgICAgdGhpcy5fZHJvcENvbnRhaW5lciEuX3N0YXJ0U2Nyb2xsaW5nSWZOZWNlc3NhcnkocmF3WCwgcmF3WSk7XG4gICAgICB0aGlzLl9kcm9wQ29udGFpbmVyIS5fc29ydEl0ZW0odGhpcywgeCwgeSwgdGhpcy5fcG9pbnRlckRpcmVjdGlvbkRlbHRhKTtcblxuICAgICAgaWYgKHRoaXMuY29uc3RyYWluUG9zaXRpb24pIHtcbiAgICAgICAgdGhpcy5fYXBwbHlQcmV2aWV3VHJhbnNmb3JtKHgsIHkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fYXBwbHlQcmV2aWV3VHJhbnNmb3JtKFxuICAgICAgICAgIHggLSB0aGlzLl9waWNrdXBQb3NpdGlvbkluRWxlbWVudC54LFxuICAgICAgICAgIHkgLSB0aGlzLl9waWNrdXBQb3NpdGlvbkluRWxlbWVudC55LFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBbmltYXRlcyB0aGUgcHJldmlldyBlbGVtZW50IGZyb20gaXRzIGN1cnJlbnQgcG9zaXRpb24gdG8gdGhlIGxvY2F0aW9uIG9mIHRoZSBkcm9wIHBsYWNlaG9sZGVyLlxuICAgKiBAcmV0dXJucyBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgYW5pbWF0aW9uIGNvbXBsZXRlcy5cbiAgICovXG4gIHByaXZhdGUgX2FuaW1hdGVQcmV2aWV3VG9QbGFjZWhvbGRlcigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBJZiB0aGUgdXNlciBoYXNuJ3QgbW92ZWQgeWV0LCB0aGUgdHJhbnNpdGlvbmVuZCBldmVudCB3b24ndCBmaXJlLlxuICAgIGlmICghdGhpcy5faGFzTW92ZWQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG5cbiAgICBjb25zdCBwbGFjZWhvbGRlclJlY3QgPSB0aGlzLl9wbGFjZWhvbGRlci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgIC8vIEFwcGx5IHRoZSBjbGFzcyB0aGF0IGFkZHMgYSB0cmFuc2l0aW9uIHRvIHRoZSBwcmV2aWV3LlxuICAgIHRoaXMuX3ByZXZpZXchLmFkZENsYXNzKCdjZGstZHJhZy1hbmltYXRpbmcnKTtcblxuICAgIC8vIE1vdmUgdGhlIHByZXZpZXcgdG8gdGhlIHBsYWNlaG9sZGVyIHBvc2l0aW9uLlxuICAgIHRoaXMuX2FwcGx5UHJldmlld1RyYW5zZm9ybShwbGFjZWhvbGRlclJlY3QubGVmdCwgcGxhY2Vob2xkZXJSZWN0LnRvcCk7XG5cbiAgICAvLyBJZiB0aGUgZWxlbWVudCBkb2Vzbid0IGhhdmUgYSBgdHJhbnNpdGlvbmAsIHRoZSBgdHJhbnNpdGlvbmVuZGAgZXZlbnQgd29uJ3QgZmlyZS4gU2luY2VcbiAgICAvLyB3ZSBuZWVkIHRvIHRyaWdnZXIgYSBzdHlsZSByZWNhbGN1bGF0aW9uIGluIG9yZGVyIGZvciB0aGUgYGNkay1kcmFnLWFuaW1hdGluZ2AgY2xhc3MgdG9cbiAgICAvLyBhcHBseSBpdHMgc3R5bGUsIHdlIHRha2UgYWR2YW50YWdlIG9mIHRoZSBhdmFpbGFibGUgaW5mbyB0byBmaWd1cmUgb3V0IHdoZXRoZXIgd2UgbmVlZCB0b1xuICAgIC8vIGJpbmQgdGhlIGV2ZW50IGluIHRoZSBmaXJzdCBwbGFjZS5cbiAgICBjb25zdCBkdXJhdGlvbiA9IHRoaXMuX3ByZXZpZXchLmdldFRyYW5zaXRpb25EdXJhdGlvbigpO1xuXG4gICAgaWYgKGR1cmF0aW9uID09PSAwKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX25nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgIGNvbnN0IGhhbmRsZXIgPSAoKGV2ZW50OiBUcmFuc2l0aW9uRXZlbnQpID0+IHtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAhZXZlbnQgfHxcbiAgICAgICAgICAgICh0aGlzLl9wcmV2aWV3ICYmXG4gICAgICAgICAgICAgIF9nZXRFdmVudFRhcmdldChldmVudCkgPT09IHRoaXMuX3ByZXZpZXcuZWxlbWVudCAmJlxuICAgICAgICAgICAgICBldmVudC5wcm9wZXJ0eU5hbWUgPT09ICd0cmFuc2Zvcm0nKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgdGhpcy5fcHJldmlldz8ucmVtb3ZlRXZlbnRMaXN0ZW5lcigndHJhbnNpdGlvbmVuZCcsIGhhbmRsZXIpO1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkgYXMgRXZlbnRMaXN0ZW5lck9yRXZlbnRMaXN0ZW5lck9iamVjdDtcblxuICAgICAgICAvLyBJZiBhIHRyYW5zaXRpb24gaXMgc2hvcnQgZW5vdWdoLCB0aGUgYnJvd3NlciBtaWdodCBub3QgZmlyZSB0aGUgYHRyYW5zaXRpb25lbmRgIGV2ZW50LlxuICAgICAgICAvLyBTaW5jZSB3ZSBrbm93IGhvdyBsb25nIGl0J3Mgc3VwcG9zZWQgdG8gdGFrZSwgYWRkIGEgdGltZW91dCB3aXRoIGEgNTAlIGJ1ZmZlciB0aGF0J2xsXG4gICAgICAgIC8vIGZpcmUgaWYgdGhlIHRyYW5zaXRpb24gaGFzbid0IGNvbXBsZXRlZCB3aGVuIGl0IHdhcyBzdXBwb3NlZCB0by5cbiAgICAgICAgY29uc3QgdGltZW91dCA9IHNldFRpbWVvdXQoaGFuZGxlciBhcyBGdW5jdGlvbiwgZHVyYXRpb24gKiAxLjUpO1xuICAgICAgICB0aGlzLl9wcmV2aWV3IS5hZGRFdmVudExpc3RlbmVyKCd0cmFuc2l0aW9uZW5kJywgaGFuZGxlcik7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBDcmVhdGVzIGFuIGVsZW1lbnQgdGhhdCB3aWxsIGJlIHNob3duIGluc3RlYWQgb2YgdGhlIGN1cnJlbnQgZWxlbWVudCB3aGlsZSBkcmFnZ2luZy4gKi9cbiAgcHJpdmF0ZSBfY3JlYXRlUGxhY2Vob2xkZXJFbGVtZW50KCk6IEhUTUxFbGVtZW50IHtcbiAgICBjb25zdCBwbGFjZWhvbGRlckNvbmZpZyA9IHRoaXMuX3BsYWNlaG9sZGVyVGVtcGxhdGU7XG4gICAgY29uc3QgcGxhY2Vob2xkZXJUZW1wbGF0ZSA9IHBsYWNlaG9sZGVyQ29uZmlnID8gcGxhY2Vob2xkZXJDb25maWcudGVtcGxhdGUgOiBudWxsO1xuICAgIGxldCBwbGFjZWhvbGRlcjogSFRNTEVsZW1lbnQ7XG5cbiAgICBpZiAocGxhY2Vob2xkZXJUZW1wbGF0ZSkge1xuICAgICAgdGhpcy5fcGxhY2Vob2xkZXJSZWYgPSBwbGFjZWhvbGRlckNvbmZpZyEudmlld0NvbnRhaW5lci5jcmVhdGVFbWJlZGRlZFZpZXcoXG4gICAgICAgIHBsYWNlaG9sZGVyVGVtcGxhdGUsXG4gICAgICAgIHBsYWNlaG9sZGVyQ29uZmlnIS5jb250ZXh0LFxuICAgICAgKTtcbiAgICAgIHRoaXMuX3BsYWNlaG9sZGVyUmVmLmRldGVjdENoYW5nZXMoKTtcbiAgICAgIHBsYWNlaG9sZGVyID0gZ2V0Um9vdE5vZGUodGhpcy5fcGxhY2Vob2xkZXJSZWYsIHRoaXMuX2RvY3VtZW50KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGxhY2Vob2xkZXIgPSBkZWVwQ2xvbmVOb2RlKHRoaXMuX3Jvb3RFbGVtZW50KTtcbiAgICB9XG5cbiAgICAvLyBTdG9wIHBvaW50ZXIgZXZlbnRzIG9uIHRoZSBwcmV2aWV3IHNvIHRoZSB1c2VyIGNhbid0XG4gICAgLy8gaW50ZXJhY3Qgd2l0aCBpdCB3aGlsZSB0aGUgcHJldmlldyBpcyBhbmltYXRpbmcuXG4gICAgcGxhY2Vob2xkZXIuc3R5bGUucG9pbnRlckV2ZW50cyA9ICdub25lJztcbiAgICBwbGFjZWhvbGRlci5jbGFzc0xpc3QuYWRkKCdjZGstZHJhZy1wbGFjZWhvbGRlcicpO1xuICAgIHJldHVybiBwbGFjZWhvbGRlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaWd1cmVzIG91dCB0aGUgY29vcmRpbmF0ZXMgYXQgd2hpY2ggYW4gZWxlbWVudCB3YXMgcGlja2VkIHVwLlxuICAgKiBAcGFyYW0gcmVmZXJlbmNlRWxlbWVudCBFbGVtZW50IHRoYXQgaW5pdGlhdGVkIHRoZSBkcmFnZ2luZy5cbiAgICogQHBhcmFtIGV2ZW50IEV2ZW50IHRoYXQgaW5pdGlhdGVkIHRoZSBkcmFnZ2luZy5cbiAgICovXG4gIHByaXZhdGUgX2dldFBvaW50ZXJQb3NpdGlvbkluRWxlbWVudChcbiAgICBlbGVtZW50UmVjdDogRE9NUmVjdCxcbiAgICByZWZlcmVuY2VFbGVtZW50OiBIVE1MRWxlbWVudCxcbiAgICBldmVudDogTW91c2VFdmVudCB8IFRvdWNoRXZlbnQsXG4gICk6IFBvaW50IHtcbiAgICBjb25zdCBoYW5kbGVFbGVtZW50ID0gcmVmZXJlbmNlRWxlbWVudCA9PT0gdGhpcy5fcm9vdEVsZW1lbnQgPyBudWxsIDogcmVmZXJlbmNlRWxlbWVudDtcbiAgICBjb25zdCByZWZlcmVuY2VSZWN0ID0gaGFuZGxlRWxlbWVudCA/IGhhbmRsZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkgOiBlbGVtZW50UmVjdDtcbiAgICBjb25zdCBwb2ludCA9IGlzVG91Y2hFdmVudChldmVudCkgPyBldmVudC50YXJnZXRUb3VjaGVzWzBdIDogZXZlbnQ7XG4gICAgY29uc3Qgc2Nyb2xsUG9zaXRpb24gPSB0aGlzLl9nZXRWaWV3cG9ydFNjcm9sbFBvc2l0aW9uKCk7XG4gICAgY29uc3QgeCA9IHBvaW50LnBhZ2VYIC0gcmVmZXJlbmNlUmVjdC5sZWZ0IC0gc2Nyb2xsUG9zaXRpb24ubGVmdDtcbiAgICBjb25zdCB5ID0gcG9pbnQucGFnZVkgLSByZWZlcmVuY2VSZWN0LnRvcCAtIHNjcm9sbFBvc2l0aW9uLnRvcDtcblxuICAgIHJldHVybiB7XG4gICAgICB4OiByZWZlcmVuY2VSZWN0LmxlZnQgLSBlbGVtZW50UmVjdC5sZWZ0ICsgeCxcbiAgICAgIHk6IHJlZmVyZW5jZVJlY3QudG9wIC0gZWxlbWVudFJlY3QudG9wICsgeSxcbiAgICB9O1xuICB9XG5cbiAgLyoqIERldGVybWluZXMgdGhlIHBvaW50IG9mIHRoZSBwYWdlIHRoYXQgd2FzIHRvdWNoZWQgYnkgdGhlIHVzZXIuICovXG4gIHByaXZhdGUgX2dldFBvaW50ZXJQb3NpdGlvbk9uUGFnZShldmVudDogTW91c2VFdmVudCB8IFRvdWNoRXZlbnQpOiBQb2ludCB7XG4gICAgY29uc3Qgc2Nyb2xsUG9zaXRpb24gPSB0aGlzLl9nZXRWaWV3cG9ydFNjcm9sbFBvc2l0aW9uKCk7XG4gICAgY29uc3QgcG9pbnQgPSBpc1RvdWNoRXZlbnQoZXZlbnQpXG4gICAgICA/IC8vIGB0b3VjaGVzYCB3aWxsIGJlIGVtcHR5IGZvciBzdGFydC9lbmQgZXZlbnRzIHNvIHdlIGhhdmUgdG8gZmFsbCBiYWNrIHRvIGBjaGFuZ2VkVG91Y2hlc2AuXG4gICAgICAgIC8vIEFsc28gbm90ZSB0aGF0IG9uIHJlYWwgZGV2aWNlcyB3ZSdyZSBndWFyYW50ZWVkIGZvciBlaXRoZXIgYHRvdWNoZXNgIG9yIGBjaGFuZ2VkVG91Y2hlc2BcbiAgICAgICAgLy8gdG8gaGF2ZSBhIHZhbHVlLCBidXQgRmlyZWZveCBpbiBkZXZpY2UgZW11bGF0aW9uIG1vZGUgaGFzIGEgYnVnIHdoZXJlIGJvdGggY2FuIGJlIGVtcHR5XG4gICAgICAgIC8vIGZvciBgdG91Y2hzdGFydGAgYW5kIGB0b3VjaGVuZGAgc28gd2UgZmFsbCBiYWNrIHRvIGEgZHVtbXkgb2JqZWN0IGluIG9yZGVyIHRvIGF2b2lkXG4gICAgICAgIC8vIHRocm93aW5nIGFuIGVycm9yLiBUaGUgdmFsdWUgcmV0dXJuZWQgaGVyZSB3aWxsIGJlIGluY29ycmVjdCwgYnV0IHNpbmNlIHRoaXMgb25seVxuICAgICAgICAvLyBicmVha3MgaW5zaWRlIGEgZGV2ZWxvcGVyIHRvb2wgYW5kIHRoZSB2YWx1ZSBpcyBvbmx5IHVzZWQgZm9yIHNlY29uZGFyeSBpbmZvcm1hdGlvbixcbiAgICAgICAgLy8gd2UgY2FuIGdldCBhd2F5IHdpdGggaXQuIFNlZSBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD0xNjE1ODI0LlxuICAgICAgICBldmVudC50b3VjaGVzWzBdIHx8IGV2ZW50LmNoYW5nZWRUb3VjaGVzWzBdIHx8IHtwYWdlWDogMCwgcGFnZVk6IDB9XG4gICAgICA6IGV2ZW50O1xuXG4gICAgY29uc3QgeCA9IHBvaW50LnBhZ2VYIC0gc2Nyb2xsUG9zaXRpb24ubGVmdDtcbiAgICBjb25zdCB5ID0gcG9pbnQucGFnZVkgLSBzY3JvbGxQb3NpdGlvbi50b3A7XG5cbiAgICAvLyBpZiBkcmFnZ2luZyBTVkcgZWxlbWVudCwgdHJ5IHRvIGNvbnZlcnQgZnJvbSB0aGUgc2NyZWVuIGNvb3JkaW5hdGUgc3lzdGVtIHRvIHRoZSBTVkdcbiAgICAvLyBjb29yZGluYXRlIHN5c3RlbVxuICAgIGlmICh0aGlzLl9vd25lclNWR0VsZW1lbnQpIHtcbiAgICAgIGNvbnN0IHN2Z01hdHJpeCA9IHRoaXMuX293bmVyU1ZHRWxlbWVudC5nZXRTY3JlZW5DVE0oKTtcbiAgICAgIGlmIChzdmdNYXRyaXgpIHtcbiAgICAgICAgY29uc3Qgc3ZnUG9pbnQgPSB0aGlzLl9vd25lclNWR0VsZW1lbnQuY3JlYXRlU1ZHUG9pbnQoKTtcbiAgICAgICAgc3ZnUG9pbnQueCA9IHg7XG4gICAgICAgIHN2Z1BvaW50LnkgPSB5O1xuICAgICAgICByZXR1cm4gc3ZnUG9pbnQubWF0cml4VHJhbnNmb3JtKHN2Z01hdHJpeC5pbnZlcnNlKCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7eCwgeX07XG4gIH1cblxuICAvKiogR2V0cyB0aGUgcG9pbnRlciBwb3NpdGlvbiBvbiB0aGUgcGFnZSwgYWNjb3VudGluZyBmb3IgYW55IHBvc2l0aW9uIGNvbnN0cmFpbnRzLiAqL1xuICBwcml2YXRlIF9nZXRDb25zdHJhaW5lZFBvaW50ZXJQb3NpdGlvbihwb2ludDogUG9pbnQpOiBQb2ludCB7XG4gICAgY29uc3QgZHJvcENvbnRhaW5lckxvY2sgPSB0aGlzLl9kcm9wQ29udGFpbmVyID8gdGhpcy5fZHJvcENvbnRhaW5lci5sb2NrQXhpcyA6IG51bGw7XG4gICAgbGV0IHt4LCB5fSA9IHRoaXMuY29uc3RyYWluUG9zaXRpb25cbiAgICAgID8gdGhpcy5jb25zdHJhaW5Qb3NpdGlvbihwb2ludCwgdGhpcywgdGhpcy5faW5pdGlhbERvbVJlY3QhLCB0aGlzLl9waWNrdXBQb3NpdGlvbkluRWxlbWVudClcbiAgICAgIDogcG9pbnQ7XG5cbiAgICBpZiAodGhpcy5sb2NrQXhpcyA9PT0gJ3gnIHx8IGRyb3BDb250YWluZXJMb2NrID09PSAneCcpIHtcbiAgICAgIHkgPVxuICAgICAgICB0aGlzLl9waWNrdXBQb3NpdGlvbk9uUGFnZS55IC1cbiAgICAgICAgKHRoaXMuY29uc3RyYWluUG9zaXRpb24gPyB0aGlzLl9waWNrdXBQb3NpdGlvbkluRWxlbWVudC55IDogMCk7XG4gICAgfSBlbHNlIGlmICh0aGlzLmxvY2tBeGlzID09PSAneScgfHwgZHJvcENvbnRhaW5lckxvY2sgPT09ICd5Jykge1xuICAgICAgeCA9XG4gICAgICAgIHRoaXMuX3BpY2t1cFBvc2l0aW9uT25QYWdlLnggLVxuICAgICAgICAodGhpcy5jb25zdHJhaW5Qb3NpdGlvbiA/IHRoaXMuX3BpY2t1cFBvc2l0aW9uSW5FbGVtZW50LnggOiAwKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fYm91bmRhcnlSZWN0KSB7XG4gICAgICAvLyBJZiBub3QgdXNpbmcgYSBjdXN0b20gY29uc3RyYWluIHdlIG5lZWQgdG8gYWNjb3VudCBmb3IgdGhlIHBpY2t1cCBwb3NpdGlvbiBpbiB0aGUgZWxlbWVudFxuICAgICAgLy8gb3RoZXJ3aXNlIHdlIGRvIG5vdCBuZWVkIHRvIGRvIHRoaXMsIGFzIGl0IGhhcyBhbHJlYWR5IGJlZW4gYWNjb3VudGVkIGZvclxuICAgICAgY29uc3Qge3g6IHBpY2t1cFgsIHk6IHBpY2t1cFl9ID0gIXRoaXMuY29uc3RyYWluUG9zaXRpb25cbiAgICAgICAgPyB0aGlzLl9waWNrdXBQb3NpdGlvbkluRWxlbWVudFxuICAgICAgICA6IHt4OiAwLCB5OiAwfTtcblxuICAgICAgY29uc3QgYm91bmRhcnlSZWN0ID0gdGhpcy5fYm91bmRhcnlSZWN0O1xuICAgICAgY29uc3Qge3dpZHRoOiBwcmV2aWV3V2lkdGgsIGhlaWdodDogcHJldmlld0hlaWdodH0gPSB0aGlzLl9nZXRQcmV2aWV3UmVjdCgpO1xuICAgICAgY29uc3QgbWluWSA9IGJvdW5kYXJ5UmVjdC50b3AgKyBwaWNrdXBZO1xuICAgICAgY29uc3QgbWF4WSA9IGJvdW5kYXJ5UmVjdC5ib3R0b20gLSAocHJldmlld0hlaWdodCAtIHBpY2t1cFkpO1xuICAgICAgY29uc3QgbWluWCA9IGJvdW5kYXJ5UmVjdC5sZWZ0ICsgcGlja3VwWDtcbiAgICAgIGNvbnN0IG1heFggPSBib3VuZGFyeVJlY3QucmlnaHQgLSAocHJldmlld1dpZHRoIC0gcGlja3VwWCk7XG5cbiAgICAgIHggPSBjbGFtcCh4LCBtaW5YLCBtYXhYKTtcbiAgICAgIHkgPSBjbGFtcCh5LCBtaW5ZLCBtYXhZKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge3gsIHl9O1xuICB9XG5cbiAgLyoqIFVwZGF0ZXMgdGhlIGN1cnJlbnQgZHJhZyBkZWx0YSwgYmFzZWQgb24gdGhlIHVzZXIncyBjdXJyZW50IHBvaW50ZXIgcG9zaXRpb24gb24gdGhlIHBhZ2UuICovXG4gIHByaXZhdGUgX3VwZGF0ZVBvaW50ZXJEaXJlY3Rpb25EZWx0YShwb2ludGVyUG9zaXRpb25PblBhZ2U6IFBvaW50KSB7XG4gICAgY29uc3Qge3gsIHl9ID0gcG9pbnRlclBvc2l0aW9uT25QYWdlO1xuICAgIGNvbnN0IGRlbHRhID0gdGhpcy5fcG9pbnRlckRpcmVjdGlvbkRlbHRhO1xuICAgIGNvbnN0IHBvc2l0aW9uU2luY2VMYXN0Q2hhbmdlID0gdGhpcy5fcG9pbnRlclBvc2l0aW9uQXRMYXN0RGlyZWN0aW9uQ2hhbmdlO1xuXG4gICAgLy8gQW1vdW50IG9mIHBpeGVscyB0aGUgdXNlciBoYXMgZHJhZ2dlZCBzaW5jZSB0aGUgbGFzdCB0aW1lIHRoZSBkaXJlY3Rpb24gY2hhbmdlZC5cbiAgICBjb25zdCBjaGFuZ2VYID0gTWF0aC5hYnMoeCAtIHBvc2l0aW9uU2luY2VMYXN0Q2hhbmdlLngpO1xuICAgIGNvbnN0IGNoYW5nZVkgPSBNYXRoLmFicyh5IC0gcG9zaXRpb25TaW5jZUxhc3RDaGFuZ2UueSk7XG5cbiAgICAvLyBCZWNhdXNlIHdlIGhhbmRsZSBwb2ludGVyIGV2ZW50cyBvbiBhIHBlci1waXhlbCBiYXNpcywgd2UgZG9uJ3Qgd2FudCB0aGUgZGVsdGFcbiAgICAvLyB0byBjaGFuZ2UgZm9yIGV2ZXJ5IHBpeGVsLCBvdGhlcndpc2UgYW55dGhpbmcgdGhhdCBkZXBlbmRzIG9uIGl0IGNhbiBsb29rIGVycmF0aWMuXG4gICAgLy8gVG8gbWFrZSB0aGUgZGVsdGEgbW9yZSBjb25zaXN0ZW50LCB3ZSB0cmFjayBob3cgbXVjaCB0aGUgdXNlciBoYXMgbW92ZWQgc2luY2UgdGhlIGxhc3RcbiAgICAvLyBkZWx0YSBjaGFuZ2UgYW5kIHdlIG9ubHkgdXBkYXRlIGl0IGFmdGVyIGl0IGhhcyByZWFjaGVkIGEgY2VydGFpbiB0aHJlc2hvbGQuXG4gICAgaWYgKGNoYW5nZVggPiB0aGlzLl9jb25maWcucG9pbnRlckRpcmVjdGlvbkNoYW5nZVRocmVzaG9sZCkge1xuICAgICAgZGVsdGEueCA9IHggPiBwb3NpdGlvblNpbmNlTGFzdENoYW5nZS54ID8gMSA6IC0xO1xuICAgICAgcG9zaXRpb25TaW5jZUxhc3RDaGFuZ2UueCA9IHg7XG4gICAgfVxuXG4gICAgaWYgKGNoYW5nZVkgPiB0aGlzLl9jb25maWcucG9pbnRlckRpcmVjdGlvbkNoYW5nZVRocmVzaG9sZCkge1xuICAgICAgZGVsdGEueSA9IHkgPiBwb3NpdGlvblNpbmNlTGFzdENoYW5nZS55ID8gMSA6IC0xO1xuICAgICAgcG9zaXRpb25TaW5jZUxhc3RDaGFuZ2UueSA9IHk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRlbHRhO1xuICB9XG5cbiAgLyoqIFRvZ2dsZXMgdGhlIG5hdGl2ZSBkcmFnIGludGVyYWN0aW9ucywgYmFzZWQgb24gaG93IG1hbnkgaGFuZGxlcyBhcmUgcmVnaXN0ZXJlZC4gKi9cbiAgcHJpdmF0ZSBfdG9nZ2xlTmF0aXZlRHJhZ0ludGVyYWN0aW9ucygpIHtcbiAgICBpZiAoIXRoaXMuX3Jvb3RFbGVtZW50IHx8ICF0aGlzLl9oYW5kbGVzKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgc2hvdWxkRW5hYmxlID0gdGhpcy5faGFuZGxlcy5sZW5ndGggPiAwIHx8ICF0aGlzLmlzRHJhZ2dpbmcoKTtcblxuICAgIGlmIChzaG91bGRFbmFibGUgIT09IHRoaXMuX25hdGl2ZUludGVyYWN0aW9uc0VuYWJsZWQpIHtcbiAgICAgIHRoaXMuX25hdGl2ZUludGVyYWN0aW9uc0VuYWJsZWQgPSBzaG91bGRFbmFibGU7XG4gICAgICB0b2dnbGVOYXRpdmVEcmFnSW50ZXJhY3Rpb25zKHRoaXMuX3Jvb3RFbGVtZW50LCBzaG91bGRFbmFibGUpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBSZW1vdmVzIHRoZSBtYW51YWxseS1hZGRlZCBldmVudCBsaXN0ZW5lcnMgZnJvbSB0aGUgcm9vdCBlbGVtZW50LiAqL1xuICBwcml2YXRlIF9yZW1vdmVSb290RWxlbWVudExpc3RlbmVycyhlbGVtZW50OiBIVE1MRWxlbWVudCkge1xuICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5fcG9pbnRlckRvd24sIGFjdGl2ZUV2ZW50TGlzdGVuZXJPcHRpb25zKTtcbiAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCB0aGlzLl9wb2ludGVyRG93biwgcGFzc2l2ZUV2ZW50TGlzdGVuZXJPcHRpb25zKTtcbiAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2RyYWdzdGFydCcsIHRoaXMuX25hdGl2ZURyYWdTdGFydCwgYWN0aXZlRXZlbnRMaXN0ZW5lck9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFwcGxpZXMgYSBgdHJhbnNmb3JtYCB0byB0aGUgcm9vdCBlbGVtZW50LCB0YWtpbmcgaW50byBhY2NvdW50IGFueSBleGlzdGluZyB0cmFuc2Zvcm1zIG9uIGl0LlxuICAgKiBAcGFyYW0geCBOZXcgdHJhbnNmb3JtIHZhbHVlIGFsb25nIHRoZSBYIGF4aXMuXG4gICAqIEBwYXJhbSB5IE5ldyB0cmFuc2Zvcm0gdmFsdWUgYWxvbmcgdGhlIFkgYXhpcy5cbiAgICovXG4gIHByaXZhdGUgX2FwcGx5Um9vdEVsZW1lbnRUcmFuc2Zvcm0oeDogbnVtYmVyLCB5OiBudW1iZXIpIHtcbiAgICBjb25zdCBzY2FsZSA9IDEgLyB0aGlzLnNjYWxlO1xuICAgIGNvbnN0IHRyYW5zZm9ybSA9IGdldFRyYW5zZm9ybSh4ICogc2NhbGUsIHkgKiBzY2FsZSk7XG4gICAgY29uc3Qgc3R5bGVzID0gdGhpcy5fcm9vdEVsZW1lbnQuc3R5bGU7XG5cbiAgICAvLyBDYWNoZSB0aGUgcHJldmlvdXMgdHJhbnNmb3JtIGFtb3VudCBvbmx5IGFmdGVyIHRoZSBmaXJzdCBkcmFnIHNlcXVlbmNlLCBiZWNhdXNlXG4gICAgLy8gd2UgZG9uJ3Qgd2FudCBvdXIgb3duIHRyYW5zZm9ybXMgdG8gc3RhY2sgb24gdG9wIG9mIGVhY2ggb3RoZXIuXG4gICAgLy8gU2hvdWxkIGJlIGV4Y2x1ZGVkIG5vbmUgYmVjYXVzZSBub25lICsgdHJhbnNsYXRlM2QoeCwgeSwgeCkgaXMgaW52YWxpZCBjc3NcbiAgICBpZiAodGhpcy5faW5pdGlhbFRyYW5zZm9ybSA9PSBudWxsKSB7XG4gICAgICB0aGlzLl9pbml0aWFsVHJhbnNmb3JtID1cbiAgICAgICAgc3R5bGVzLnRyYW5zZm9ybSAmJiBzdHlsZXMudHJhbnNmb3JtICE9ICdub25lJyA/IHN0eWxlcy50cmFuc2Zvcm0gOiAnJztcbiAgICB9XG5cbiAgICAvLyBQcmVzZXJ2ZSB0aGUgcHJldmlvdXMgYHRyYW5zZm9ybWAgdmFsdWUsIGlmIHRoZXJlIHdhcyBvbmUuIE5vdGUgdGhhdCB3ZSBhcHBseSBvdXIgb3duXG4gICAgLy8gdHJhbnNmb3JtIGJlZm9yZSB0aGUgdXNlcidzLCBiZWNhdXNlIHRoaW5ncyBsaWtlIHJvdGF0aW9uIGNhbiBhZmZlY3Qgd2hpY2ggZGlyZWN0aW9uXG4gICAgLy8gdGhlIGVsZW1lbnQgd2lsbCBiZSB0cmFuc2xhdGVkIHRvd2FyZHMuXG4gICAgc3R5bGVzLnRyYW5zZm9ybSA9IGNvbWJpbmVUcmFuc2Zvcm1zKHRyYW5zZm9ybSwgdGhpcy5faW5pdGlhbFRyYW5zZm9ybSk7XG4gIH1cblxuICAvKipcbiAgICogQXBwbGllcyBhIGB0cmFuc2Zvcm1gIHRvIHRoZSBwcmV2aWV3LCB0YWtpbmcgaW50byBhY2NvdW50IGFueSBleGlzdGluZyB0cmFuc2Zvcm1zIG9uIGl0LlxuICAgKiBAcGFyYW0geCBOZXcgdHJhbnNmb3JtIHZhbHVlIGFsb25nIHRoZSBYIGF4aXMuXG4gICAqIEBwYXJhbSB5IE5ldyB0cmFuc2Zvcm0gdmFsdWUgYWxvbmcgdGhlIFkgYXhpcy5cbiAgICovXG4gIHByaXZhdGUgX2FwcGx5UHJldmlld1RyYW5zZm9ybSh4OiBudW1iZXIsIHk6IG51bWJlcikge1xuICAgIC8vIE9ubHkgYXBwbHkgdGhlIGluaXRpYWwgdHJhbnNmb3JtIGlmIHRoZSBwcmV2aWV3IGlzIGEgY2xvbmUgb2YgdGhlIG9yaWdpbmFsIGVsZW1lbnQsIG90aGVyd2lzZVxuICAgIC8vIGl0IGNvdWxkIGJlIGNvbXBsZXRlbHkgZGlmZmVyZW50IGFuZCB0aGUgdHJhbnNmb3JtIG1pZ2h0IG5vdCBtYWtlIHNlbnNlIGFueW1vcmUuXG4gICAgY29uc3QgaW5pdGlhbFRyYW5zZm9ybSA9IHRoaXMuX3ByZXZpZXdUZW1wbGF0ZT8udGVtcGxhdGUgPyB1bmRlZmluZWQgOiB0aGlzLl9pbml0aWFsVHJhbnNmb3JtO1xuICAgIGNvbnN0IHRyYW5zZm9ybSA9IGdldFRyYW5zZm9ybSh4LCB5KTtcbiAgICB0aGlzLl9wcmV2aWV3IS5zZXRUcmFuc2Zvcm0oY29tYmluZVRyYW5zZm9ybXModHJhbnNmb3JtLCBpbml0aWFsVHJhbnNmb3JtKSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgZGlzdGFuY2UgdGhhdCB0aGUgdXNlciBoYXMgZHJhZ2dlZCBkdXJpbmcgdGhlIGN1cnJlbnQgZHJhZyBzZXF1ZW5jZS5cbiAgICogQHBhcmFtIGN1cnJlbnRQb3NpdGlvbiBDdXJyZW50IHBvc2l0aW9uIG9mIHRoZSB1c2VyJ3MgcG9pbnRlci5cbiAgICovXG4gIHByaXZhdGUgX2dldERyYWdEaXN0YW5jZShjdXJyZW50UG9zaXRpb246IFBvaW50KTogUG9pbnQge1xuICAgIGNvbnN0IHBpY2t1cFBvc2l0aW9uID0gdGhpcy5fcGlja3VwUG9zaXRpb25PblBhZ2U7XG5cbiAgICBpZiAocGlja3VwUG9zaXRpb24pIHtcbiAgICAgIHJldHVybiB7eDogY3VycmVudFBvc2l0aW9uLnggLSBwaWNrdXBQb3NpdGlvbi54LCB5OiBjdXJyZW50UG9zaXRpb24ueSAtIHBpY2t1cFBvc2l0aW9uLnl9O1xuICAgIH1cblxuICAgIHJldHVybiB7eDogMCwgeTogMH07XG4gIH1cblxuICAvKiogQ2xlYW5zIHVwIGFueSBjYWNoZWQgZWxlbWVudCBkaW1lbnNpb25zIHRoYXQgd2UgZG9uJ3QgbmVlZCBhZnRlciBkcmFnZ2luZyBoYXMgc3RvcHBlZC4gKi9cbiAgcHJpdmF0ZSBfY2xlYW51cENhY2hlZERpbWVuc2lvbnMoKSB7XG4gICAgdGhpcy5fYm91bmRhcnlSZWN0ID0gdGhpcy5fcHJldmlld1JlY3QgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fcGFyZW50UG9zaXRpb25zLmNsZWFyKCk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIHdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgc3RpbGwgaW5zaWRlIGl0cyBib3VuZGFyeSBhZnRlciB0aGUgdmlld3BvcnQgaGFzIGJlZW4gcmVzaXplZC5cbiAgICogSWYgbm90LCB0aGUgcG9zaXRpb24gaXMgYWRqdXN0ZWQgc28gdGhhdCB0aGUgZWxlbWVudCBmaXRzIGFnYWluLlxuICAgKi9cbiAgcHJpdmF0ZSBfY29udGFpbkluc2lkZUJvdW5kYXJ5T25SZXNpemUoKSB7XG4gICAgbGV0IHt4LCB5fSA9IHRoaXMuX3Bhc3NpdmVUcmFuc2Zvcm07XG5cbiAgICBpZiAoKHggPT09IDAgJiYgeSA9PT0gMCkgfHwgdGhpcy5pc0RyYWdnaW5nKCkgfHwgIXRoaXMuX2JvdW5kYXJ5RWxlbWVudCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIE5vdGU6IGRvbid0IHVzZSBgX2NsaWVudFJlY3RBdFN0YXJ0YCBoZXJlLCBiZWNhdXNlIHdlIHdhbnQgdGhlIGxhdGVzdCBwb3NpdGlvbi5cbiAgICBjb25zdCBlbGVtZW50UmVjdCA9IHRoaXMuX3Jvb3RFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIGNvbnN0IGJvdW5kYXJ5UmVjdCA9IHRoaXMuX2JvdW5kYXJ5RWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgIC8vIEl0J3MgcG9zc2libGUgdGhhdCB0aGUgZWxlbWVudCBnb3QgaGlkZGVuIGF3YXkgYWZ0ZXIgZHJhZ2dpbmcgKGUuZy4gYnkgc3dpdGNoaW5nIHRvIGFcbiAgICAvLyBkaWZmZXJlbnQgdGFiKS4gRG9uJ3QgZG8gYW55dGhpbmcgaW4gdGhpcyBjYXNlIHNvIHdlIGRvbid0IGNsZWFyIHRoZSB1c2VyJ3MgcG9zaXRpb24uXG4gICAgaWYgKFxuICAgICAgKGJvdW5kYXJ5UmVjdC53aWR0aCA9PT0gMCAmJiBib3VuZGFyeVJlY3QuaGVpZ2h0ID09PSAwKSB8fFxuICAgICAgKGVsZW1lbnRSZWN0LndpZHRoID09PSAwICYmIGVsZW1lbnRSZWN0LmhlaWdodCA9PT0gMClcbiAgICApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBsZWZ0T3ZlcmZsb3cgPSBib3VuZGFyeVJlY3QubGVmdCAtIGVsZW1lbnRSZWN0LmxlZnQ7XG4gICAgY29uc3QgcmlnaHRPdmVyZmxvdyA9IGVsZW1lbnRSZWN0LnJpZ2h0IC0gYm91bmRhcnlSZWN0LnJpZ2h0O1xuICAgIGNvbnN0IHRvcE92ZXJmbG93ID0gYm91bmRhcnlSZWN0LnRvcCAtIGVsZW1lbnRSZWN0LnRvcDtcbiAgICBjb25zdCBib3R0b21PdmVyZmxvdyA9IGVsZW1lbnRSZWN0LmJvdHRvbSAtIGJvdW5kYXJ5UmVjdC5ib3R0b207XG5cbiAgICAvLyBJZiB0aGUgZWxlbWVudCBoYXMgYmVjb21lIHdpZGVyIHRoYW4gdGhlIGJvdW5kYXJ5LCB3ZSBjYW4ndFxuICAgIC8vIGRvIG11Y2ggdG8gbWFrZSBpdCBmaXQgc28gd2UganVzdCBhbmNob3IgaXQgdG8gdGhlIGxlZnQuXG4gICAgaWYgKGJvdW5kYXJ5UmVjdC53aWR0aCA+IGVsZW1lbnRSZWN0LndpZHRoKSB7XG4gICAgICBpZiAobGVmdE92ZXJmbG93ID4gMCkge1xuICAgICAgICB4ICs9IGxlZnRPdmVyZmxvdztcbiAgICAgIH1cblxuICAgICAgaWYgKHJpZ2h0T3ZlcmZsb3cgPiAwKSB7XG4gICAgICAgIHggLT0gcmlnaHRPdmVyZmxvdztcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgeCA9IDA7XG4gICAgfVxuXG4gICAgLy8gSWYgdGhlIGVsZW1lbnQgaGFzIGJlY29tZSB0YWxsZXIgdGhhbiB0aGUgYm91bmRhcnksIHdlIGNhbid0XG4gICAgLy8gZG8gbXVjaCB0byBtYWtlIGl0IGZpdCBzbyB3ZSBqdXN0IGFuY2hvciBpdCB0byB0aGUgdG9wLlxuICAgIGlmIChib3VuZGFyeVJlY3QuaGVpZ2h0ID4gZWxlbWVudFJlY3QuaGVpZ2h0KSB7XG4gICAgICBpZiAodG9wT3ZlcmZsb3cgPiAwKSB7XG4gICAgICAgIHkgKz0gdG9wT3ZlcmZsb3c7XG4gICAgICB9XG5cbiAgICAgIGlmIChib3R0b21PdmVyZmxvdyA+IDApIHtcbiAgICAgICAgeSAtPSBib3R0b21PdmVyZmxvdztcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgeSA9IDA7XG4gICAgfVxuXG4gICAgaWYgKHggIT09IHRoaXMuX3Bhc3NpdmVUcmFuc2Zvcm0ueCB8fCB5ICE9PSB0aGlzLl9wYXNzaXZlVHJhbnNmb3JtLnkpIHtcbiAgICAgIHRoaXMuc2V0RnJlZURyYWdQb3NpdGlvbih7eSwgeH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBHZXRzIHRoZSBkcmFnIHN0YXJ0IGRlbGF5LCBiYXNlZCBvbiB0aGUgZXZlbnQgdHlwZS4gKi9cbiAgcHJpdmF0ZSBfZ2V0RHJhZ1N0YXJ0RGVsYXkoZXZlbnQ6IE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50KTogbnVtYmVyIHtcbiAgICBjb25zdCB2YWx1ZSA9IHRoaXMuZHJhZ1N0YXJ0RGVsYXk7XG5cbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH0gZWxzZSBpZiAoaXNUb3VjaEV2ZW50KGV2ZW50KSkge1xuICAgICAgcmV0dXJuIHZhbHVlLnRvdWNoO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZSA/IHZhbHVlLm1vdXNlIDogMDtcbiAgfVxuXG4gIC8qKiBVcGRhdGVzIHRoZSBpbnRlcm5hbCBzdGF0ZSBvZiB0aGUgZHJhZ2dhYmxlIGVsZW1lbnQgd2hlbiBzY3JvbGxpbmcgaGFzIG9jY3VycmVkLiAqL1xuICBwcml2YXRlIF91cGRhdGVPblNjcm9sbChldmVudDogRXZlbnQpIHtcbiAgICBjb25zdCBzY3JvbGxEaWZmZXJlbmNlID0gdGhpcy5fcGFyZW50UG9zaXRpb25zLmhhbmRsZVNjcm9sbChldmVudCk7XG5cbiAgICBpZiAoc2Nyb2xsRGlmZmVyZW5jZSkge1xuICAgICAgY29uc3QgdGFyZ2V0ID0gX2dldEV2ZW50VGFyZ2V0PEhUTUxFbGVtZW50IHwgRG9jdW1lbnQ+KGV2ZW50KSE7XG5cbiAgICAgIC8vIERPTVJlY3QgZGltZW5zaW9ucyBhcmUgYmFzZWQgb24gdGhlIHNjcm9sbCBwb3NpdGlvbiBvZiB0aGUgcGFnZSBhbmQgaXRzIHBhcmVudFxuICAgICAgLy8gbm9kZSBzbyB3ZSBoYXZlIHRvIHVwZGF0ZSB0aGUgY2FjaGVkIGJvdW5kYXJ5IERPTVJlY3QgaWYgdGhlIHVzZXIgaGFzIHNjcm9sbGVkLlxuICAgICAgaWYgKFxuICAgICAgICB0aGlzLl9ib3VuZGFyeVJlY3QgJiZcbiAgICAgICAgdGFyZ2V0ICE9PSB0aGlzLl9ib3VuZGFyeUVsZW1lbnQgJiZcbiAgICAgICAgdGFyZ2V0LmNvbnRhaW5zKHRoaXMuX2JvdW5kYXJ5RWxlbWVudClcbiAgICAgICkge1xuICAgICAgICBhZGp1c3REb21SZWN0KHRoaXMuX2JvdW5kYXJ5UmVjdCwgc2Nyb2xsRGlmZmVyZW5jZS50b3AsIHNjcm9sbERpZmZlcmVuY2UubGVmdCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3BpY2t1cFBvc2l0aW9uT25QYWdlLnggKz0gc2Nyb2xsRGlmZmVyZW5jZS5sZWZ0O1xuICAgICAgdGhpcy5fcGlja3VwUG9zaXRpb25PblBhZ2UueSArPSBzY3JvbGxEaWZmZXJlbmNlLnRvcDtcblxuICAgICAgLy8gSWYgd2UncmUgaW4gZnJlZSBkcmFnIG1vZGUsIHdlIGhhdmUgdG8gdXBkYXRlIHRoZSBhY3RpdmUgdHJhbnNmb3JtLCBiZWNhdXNlXG4gICAgICAvLyBpdCBpc24ndCByZWxhdGl2ZSB0byB0aGUgdmlld3BvcnQgbGlrZSB0aGUgcHJldmlldyBpbnNpZGUgYSBkcm9wIGxpc3QuXG4gICAgICBpZiAoIXRoaXMuX2Ryb3BDb250YWluZXIpIHtcbiAgICAgICAgdGhpcy5fYWN0aXZlVHJhbnNmb3JtLnggLT0gc2Nyb2xsRGlmZmVyZW5jZS5sZWZ0O1xuICAgICAgICB0aGlzLl9hY3RpdmVUcmFuc2Zvcm0ueSAtPSBzY3JvbGxEaWZmZXJlbmNlLnRvcDtcbiAgICAgICAgdGhpcy5fYXBwbHlSb290RWxlbWVudFRyYW5zZm9ybSh0aGlzLl9hY3RpdmVUcmFuc2Zvcm0ueCwgdGhpcy5fYWN0aXZlVHJhbnNmb3JtLnkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKiBHZXRzIHRoZSBzY3JvbGwgcG9zaXRpb24gb2YgdGhlIHZpZXdwb3J0LiAqL1xuICBwcml2YXRlIF9nZXRWaWV3cG9ydFNjcm9sbFBvc2l0aW9uKCkge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLl9wYXJlbnRQb3NpdGlvbnMucG9zaXRpb25zLmdldCh0aGlzLl9kb2N1bWVudCk/LnNjcm9sbFBvc2l0aW9uIHx8XG4gICAgICB0aGlzLl9wYXJlbnRQb3NpdGlvbnMuZ2V0Vmlld3BvcnRTY3JvbGxQb3NpdGlvbigpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMYXppbHkgcmVzb2x2ZXMgYW5kIHJldHVybnMgdGhlIHNoYWRvdyByb290IG9mIHRoZSBlbGVtZW50LiBXZSBkbyB0aGlzIGluIGEgZnVuY3Rpb24sIHJhdGhlclxuICAgKiB0aGFuIHNhdmluZyBpdCBpbiBwcm9wZXJ0eSBkaXJlY3RseSBvbiBpbml0LCBiZWNhdXNlIHdlIHdhbnQgdG8gcmVzb2x2ZSBpdCBhcyBsYXRlIGFzIHBvc3NpYmxlXG4gICAqIGluIG9yZGVyIHRvIGVuc3VyZSB0aGF0IHRoZSBlbGVtZW50IGhhcyBiZWVuIG1vdmVkIGludG8gdGhlIHNoYWRvdyBET00uIERvaW5nIGl0IGluc2lkZSB0aGVcbiAgICogY29uc3RydWN0b3IgbWlnaHQgYmUgdG9vIGVhcmx5IGlmIHRoZSBlbGVtZW50IGlzIGluc2lkZSBvZiBzb21ldGhpbmcgbGlrZSBgbmdGb3JgIG9yIGBuZ0lmYC5cbiAgICovXG4gIHByaXZhdGUgX2dldFNoYWRvd1Jvb3QoKTogU2hhZG93Um9vdCB8IG51bGwge1xuICAgIGlmICh0aGlzLl9jYWNoZWRTaGFkb3dSb290ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuX2NhY2hlZFNoYWRvd1Jvb3QgPSBfZ2V0U2hhZG93Um9vdCh0aGlzLl9yb290RWxlbWVudCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX2NhY2hlZFNoYWRvd1Jvb3Q7XG4gIH1cblxuICAvKiogR2V0cyB0aGUgZWxlbWVudCBpbnRvIHdoaWNoIHRoZSBkcmFnIHByZXZpZXcgc2hvdWxkIGJlIGluc2VydGVkLiAqL1xuICBwcml2YXRlIF9nZXRQcmV2aWV3SW5zZXJ0aW9uUG9pbnQoXG4gICAgaW5pdGlhbFBhcmVudDogSFRNTEVsZW1lbnQsXG4gICAgc2hhZG93Um9vdDogU2hhZG93Um9vdCB8IG51bGwsXG4gICk6IEhUTUxFbGVtZW50IHtcbiAgICBjb25zdCBwcmV2aWV3Q29udGFpbmVyID0gdGhpcy5fcHJldmlld0NvbnRhaW5lciB8fCAnZ2xvYmFsJztcblxuICAgIGlmIChwcmV2aWV3Q29udGFpbmVyID09PSAncGFyZW50Jykge1xuICAgICAgcmV0dXJuIGluaXRpYWxQYXJlbnQ7XG4gICAgfVxuXG4gICAgaWYgKHByZXZpZXdDb250YWluZXIgPT09ICdnbG9iYWwnKSB7XG4gICAgICBjb25zdCBkb2N1bWVudFJlZiA9IHRoaXMuX2RvY3VtZW50O1xuXG4gICAgICAvLyBXZSBjYW4ndCB1c2UgdGhlIGJvZHkgaWYgdGhlIHVzZXIgaXMgaW4gZnVsbHNjcmVlbiBtb2RlLFxuICAgICAgLy8gYmVjYXVzZSB0aGUgcHJldmlldyB3aWxsIHJlbmRlciB1bmRlciB0aGUgZnVsbHNjcmVlbiBlbGVtZW50LlxuICAgICAgLy8gVE9ETyhjcmlzYmV0byk6IGRlZHVwZSB0aGlzIHdpdGggdGhlIGBGdWxsc2NyZWVuT3ZlcmxheUNvbnRhaW5lcmAgZXZlbnR1YWxseS5cbiAgICAgIHJldHVybiAoXG4gICAgICAgIHNoYWRvd1Jvb3QgfHxcbiAgICAgICAgZG9jdW1lbnRSZWYuZnVsbHNjcmVlbkVsZW1lbnQgfHxcbiAgICAgICAgKGRvY3VtZW50UmVmIGFzIGFueSkud2Via2l0RnVsbHNjcmVlbkVsZW1lbnQgfHxcbiAgICAgICAgKGRvY3VtZW50UmVmIGFzIGFueSkubW96RnVsbFNjcmVlbkVsZW1lbnQgfHxcbiAgICAgICAgKGRvY3VtZW50UmVmIGFzIGFueSkubXNGdWxsc2NyZWVuRWxlbWVudCB8fFxuICAgICAgICBkb2N1bWVudFJlZi5ib2R5XG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBjb2VyY2VFbGVtZW50KHByZXZpZXdDb250YWluZXIpO1xuICB9XG5cbiAgLyoqIExhemlseSByZXNvbHZlcyBhbmQgcmV0dXJucyB0aGUgZGltZW5zaW9ucyBvZiB0aGUgcHJldmlldy4gKi9cbiAgcHJpdmF0ZSBfZ2V0UHJldmlld1JlY3QoKTogRE9NUmVjdCB7XG4gICAgLy8gQ2FjaGUgdGhlIHByZXZpZXcgZWxlbWVudCByZWN0IGlmIHdlIGhhdmVuJ3QgY2FjaGVkIGl0IGFscmVhZHkgb3IgaWZcbiAgICAvLyB3ZSBjYWNoZWQgaXQgdG9vIGVhcmx5IGJlZm9yZSB0aGUgZWxlbWVudCBkaW1lbnNpb25zIHdlcmUgY29tcHV0ZWQuXG4gICAgaWYgKCF0aGlzLl9wcmV2aWV3UmVjdCB8fCAoIXRoaXMuX3ByZXZpZXdSZWN0LndpZHRoICYmICF0aGlzLl9wcmV2aWV3UmVjdC5oZWlnaHQpKSB7XG4gICAgICB0aGlzLl9wcmV2aWV3UmVjdCA9IHRoaXMuX3ByZXZpZXdcbiAgICAgICAgPyB0aGlzLl9wcmV2aWV3IS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKVxuICAgICAgICA6IHRoaXMuX2luaXRpYWxEb21SZWN0ITtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fcHJldmlld1JlY3Q7XG4gIH1cblxuICAvKiogSGFuZGxlcyBhIG5hdGl2ZSBgZHJhZ3N0YXJ0YCBldmVudC4gKi9cbiAgcHJpdmF0ZSBfbmF0aXZlRHJhZ1N0YXJ0ID0gKGV2ZW50OiBEcmFnRXZlbnQpID0+IHtcbiAgICBpZiAodGhpcy5faGFuZGxlcy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IHRhcmdldEhhbmRsZSA9IHRoaXMuX2dldFRhcmdldEhhbmRsZShldmVudCk7XG5cbiAgICAgIGlmICh0YXJnZXRIYW5kbGUgJiYgIXRoaXMuX2Rpc2FibGVkSGFuZGxlcy5oYXModGFyZ2V0SGFuZGxlKSAmJiAhdGhpcy5kaXNhYmxlZCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoIXRoaXMuZGlzYWJsZWQpIHtcbiAgICAgIC8vIFVzdWFsbHkgdGhpcyBpc24ndCBuZWNlc3Nhcnkgc2luY2UgdGhlIHdlIHByZXZlbnQgdGhlIGRlZmF1bHQgYWN0aW9uIGluIGBwb2ludGVyRG93bmAsXG4gICAgICAvLyBidXQgc29tZSBjYXNlcyBsaWtlIGRyYWdnaW5nIG9mIGxpbmtzIGNhbiBzbGlwIHRocm91Z2ggKHNlZSAjMjQ0MDMpLlxuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG4gIH07XG5cbiAgLyoqIEdldHMgYSBoYW5kbGUgdGhhdCBpcyB0aGUgdGFyZ2V0IG9mIGFuIGV2ZW50LiAqL1xuICBwcml2YXRlIF9nZXRUYXJnZXRIYW5kbGUoZXZlbnQ6IEV2ZW50KTogSFRNTEVsZW1lbnQgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9oYW5kbGVzLmZpbmQoaGFuZGxlID0+IHtcbiAgICAgIHJldHVybiBldmVudC50YXJnZXQgJiYgKGV2ZW50LnRhcmdldCA9PT0gaGFuZGxlIHx8IGhhbmRsZS5jb250YWlucyhldmVudC50YXJnZXQgYXMgTm9kZSkpO1xuICAgIH0pO1xuICB9XG59XG5cbi8qKiBDbGFtcHMgYSB2YWx1ZSBiZXR3ZWVuIGEgbWluaW11bSBhbmQgYSBtYXhpbXVtLiAqL1xuZnVuY3Rpb24gY2xhbXAodmFsdWU6IG51bWJlciwgbWluOiBudW1iZXIsIG1heDogbnVtYmVyKSB7XG4gIHJldHVybiBNYXRoLm1heChtaW4sIE1hdGgubWluKG1heCwgdmFsdWUpKTtcbn1cblxuLyoqIERldGVybWluZXMgd2hldGhlciBhbiBldmVudCBpcyBhIHRvdWNoIGV2ZW50LiAqL1xuZnVuY3Rpb24gaXNUb3VjaEV2ZW50KGV2ZW50OiBNb3VzZUV2ZW50IHwgVG91Y2hFdmVudCk6IGV2ZW50IGlzIFRvdWNoRXZlbnQge1xuICAvLyBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBmb3IgZXZlcnkgcGl4ZWwgdGhhdCB0aGUgdXNlciBoYXMgZHJhZ2dlZCBzbyB3ZSBuZWVkIGl0IHRvIGJlXG4gIC8vIGFzIGZhc3QgYXMgcG9zc2libGUuIFNpbmNlIHdlIG9ubHkgYmluZCBtb3VzZSBldmVudHMgYW5kIHRvdWNoIGV2ZW50cywgd2UgY2FuIGFzc3VtZVxuICAvLyB0aGF0IGlmIHRoZSBldmVudCdzIG5hbWUgc3RhcnRzIHdpdGggYHRgLCBpdCdzIGEgdG91Y2ggZXZlbnQuXG4gIHJldHVybiBldmVudC50eXBlWzBdID09PSAndCc7XG59XG5cbi8qKiBDYWxsYmFjayBpbnZva2VkIGZvciBgc2VsZWN0c3RhcnRgIGV2ZW50cyBpbnNpZGUgdGhlIHNoYWRvdyBET00uICovXG5mdW5jdGlvbiBzaGFkb3dEb21TZWxlY3RTdGFydChldmVudDogRXZlbnQpIHtcbiAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbn1cbiJdfQ==
|