@ks89/angular-modal-gallery 8.0.0-beta.5 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +153 -0
- package/CONTRIBUTING.md +20 -38
- package/LICENSE +1 -1
- package/README.md +36 -42
- package/esm2020/ks89-angular-modal-gallery.mjs +5 -0
- package/esm2020/lib/components/accessibility-default.mjs +41 -0
- package/esm2020/lib/components/accessible.component.mjs +130 -0
- package/esm2020/lib/components/carousel/carousel-previews/carousel-previews.component.mjs +462 -0
- package/esm2020/lib/components/carousel/carousel.component.mjs +747 -0
- package/esm2020/lib/components/components.mjs +50 -0
- package/esm2020/lib/components/current-image/current-image.component.mjs +616 -0
- package/esm2020/lib/components/current-image/loading-spinner/loading-spinner.component.mjs +80 -0
- package/esm2020/lib/components/dots/dots.component.mjs +127 -0
- package/esm2020/lib/components/modal-gallery/modal-gallery-ref.mjs +103 -0
- package/esm2020/lib/components/modal-gallery/modal-gallery.component.mjs +523 -0
- package/esm2020/lib/components/modal-gallery/modal-gallery.service.mjs +187 -0
- package/esm2020/lib/components/modal-gallery/modal-gallery.tokens.mjs +26 -0
- package/esm2020/lib/components/plain-gallery/plain-gallery.component.mjs +249 -0
- package/esm2020/lib/components/previews/previews.component.mjs +332 -0
- package/esm2020/lib/components/upper-buttons/upper-buttons-default.mjs +76 -0
- package/esm2020/lib/components/upper-buttons/upper-buttons.component.mjs +249 -0
- package/esm2020/lib/directives/a-tag-bg-image.directive.mjs +78 -0
- package/esm2020/lib/directives/click-outside.directive.mjs +91 -0
- package/esm2020/lib/directives/description.directive.mjs +98 -0
- package/esm2020/lib/directives/direction.directive.mjs +73 -0
- package/esm2020/lib/directives/directives.mjs +49 -0
- package/esm2020/lib/directives/fallback-image.directive.mjs +59 -0
- package/esm2020/lib/directives/keyboard-navigation.directive.mjs +58 -0
- package/esm2020/lib/directives/margin.directive.mjs +84 -0
- package/esm2020/lib/directives/max-size.directive.mjs +75 -0
- package/esm2020/lib/directives/size.directive.mjs +76 -0
- package/{esm2015/lib/directives/size.directive.js → esm2020/lib/directives/wrap.directive.mjs} +23 -22
- package/esm2020/lib/modal-gallery.module.mjs +94 -0
- package/esm2020/lib/model/accessibility.interface.mjs +25 -0
- package/esm2020/lib/model/action.enum.mjs +36 -0
- package/esm2020/lib/model/buttons-config.interface.mjs +62 -0
- package/esm2020/lib/model/carousel-config.interface.mjs +25 -0
- package/esm2020/lib/model/carousel-image-config.interface.mjs +25 -0
- package/esm2020/lib/model/carousel-preview-config.interface.mjs +25 -0
- package/{esm2015/lib/model/keyboard-service-config.interface.js → esm2020/lib/model/current-image-config.interface.mjs} +2 -2
- package/esm2020/lib/model/description.interface.mjs +33 -0
- package/{esm2015/lib/model/preview-config.interface.js → esm2020/lib/model/dots-config.interface.mjs} +2 -2
- package/esm2020/lib/model/image-internal.class.mjs +35 -0
- package/esm2020/lib/model/image.class.mjs +54 -0
- package/esm2020/lib/model/interaction-event.interface.mjs +2 -0
- package/esm2020/lib/model/keyboard-config.interface.mjs +25 -0
- package/esm2020/lib/model/keyboard-service-config.interface.mjs +25 -0
- package/esm2020/lib/model/keyboard.enum.mjs +35 -0
- package/esm2020/lib/model/lib-config.interface.mjs +25 -0
- package/esm2020/lib/model/loading-config.interface.mjs +37 -0
- package/{esm2015/lib/model/dots-config.interface.js → esm2020/lib/model/max-size.interface.mjs} +2 -2
- package/{esm2015/lib/model/carousel-preview-config.interface.js → esm2020/lib/model/modal-gallery-config.interface.mjs} +2 -2
- package/esm2020/lib/model/plain-gallery-config.interface.mjs +55 -0
- package/{esm2015/lib/model/image-internal.class.js → esm2020/lib/model/play-config.interface.mjs} +3 -13
- package/esm2020/lib/model/preview-config.interface.mjs +25 -0
- package/esm2020/lib/model/size.interface.mjs +25 -0
- package/{esm2015/lib/model/carousel-config.interface.js → esm2020/lib/model/slide-config.interface.mjs} +2 -2
- package/esm2020/lib/services/config.service.mjs +396 -0
- package/esm2020/lib/services/id-validator.service.mjs +71 -0
- package/esm2020/lib/services/keyboard.service.mjs +111 -0
- package/esm2020/lib/utils/image.util.mjs +48 -0
- package/esm2020/lib/utils/user-input.util.mjs +104 -0
- package/esm2020/public-api.mjs +42 -0
- package/fesm2015/ks89-angular-modal-gallery.mjs +5782 -0
- package/fesm2015/ks89-angular-modal-gallery.mjs.map +1 -0
- package/{fesm2015/ks89-angular-modal-gallery.js → fesm2020/ks89-angular-modal-gallery.mjs} +3046 -2947
- package/fesm2020/ks89-angular-modal-gallery.mjs.map +1 -0
- package/ks89-angular-modal-gallery.d.ts +1 -24
- package/lib/components/accessible.component.d.ts +5 -2
- package/lib/components/carousel/carousel-previews/carousel-previews.component.d.ts +7 -11
- package/lib/components/carousel/carousel.component.d.ts +28 -67
- package/lib/components/current-image/current-image.component.d.ts +10 -4
- package/lib/components/current-image/loading-spinner/loading-spinner.component.d.ts +3 -0
- package/lib/components/dots/dots.component.d.ts +7 -0
- package/lib/components/modal-gallery/modal-gallery-ref.d.ts +35 -0
- package/lib/components/modal-gallery/modal-gallery.component.d.ts +58 -50
- package/lib/components/modal-gallery/modal-gallery.service.d.ts +60 -1
- package/lib/components/plain-gallery/plain-gallery.component.d.ts +18 -9
- package/lib/components/previews/previews.component.d.ts +9 -0
- package/lib/components/upper-buttons/upper-buttons.component.d.ts +8 -1
- package/lib/directives/a-tag-bg-image.directive.d.ts +3 -0
- package/lib/directives/click-outside.directive.d.ts +3 -0
- package/lib/directives/description.directive.d.ts +3 -0
- package/lib/directives/direction.directive.d.ts +3 -0
- package/lib/directives/fallback-image.directive.d.ts +6 -0
- package/lib/directives/keyboard-navigation.directive.d.ts +4 -1
- package/lib/directives/margin.directive.d.ts +3 -0
- package/lib/directives/max-size.directive.d.ts +3 -0
- package/lib/directives/size.directive.d.ts +5 -2
- package/lib/directives/wrap.directive.d.ts +4 -1
- package/lib/modal-gallery.module.d.ts +28 -0
- package/lib/model/carousel-config.interface.d.ts +0 -1
- package/lib/model/keyboard-config.interface.d.ts +4 -4
- package/lib/model/keyboard.enum.d.ts +11 -8
- package/lib/model/lib-config.interface.d.ts +20 -7
- package/lib/model/modal-gallery-config.interface.d.ts +2 -2
- package/lib/model/plain-gallery-config.interface.d.ts +1 -9
- package/lib/services/config.service.d.ts +3 -0
- package/lib/services/id-validator.service.d.ts +5 -1
- package/lib/services/keyboard.service.d.ts +5 -2
- package/lib/utils/user-input.util.d.ts +35 -26
- package/package.json +28 -16
- package/public-api.d.ts +2 -2
- package/bundles/ks89-angular-modal-gallery.umd.js +0 -5906
- package/bundles/ks89-angular-modal-gallery.umd.js.map +0 -1
- package/bundles/ks89-angular-modal-gallery.umd.min.js +0 -16
- package/bundles/ks89-angular-modal-gallery.umd.min.js.map +0 -1
- package/esm2015/ks89-angular-modal-gallery.js +0 -29
- package/esm2015/lib/components/accessibility-default.js +0 -41
- package/esm2015/lib/components/accessible.component.js +0 -127
- package/esm2015/lib/components/carousel/carousel-previews/carousel-previews.component.js +0 -466
- package/esm2015/lib/components/carousel/carousel.component.js +0 -772
- package/esm2015/lib/components/components.js +0 -50
- package/esm2015/lib/components/current-image/current-image.component.js +0 -590
- package/esm2015/lib/components/current-image/loading-spinner/loading-spinner.component.js +0 -80
- package/esm2015/lib/components/dots/dots.component.js +0 -127
- package/esm2015/lib/components/modal-gallery/modal-gallery-ref.js +0 -45
- package/esm2015/lib/components/modal-gallery/modal-gallery.component.js +0 -534
- package/esm2015/lib/components/modal-gallery/modal-gallery.service.js +0 -135
- package/esm2015/lib/components/modal-gallery/modal-gallery.tokens.js +0 -3
- package/esm2015/lib/components/plain-gallery/plain-gallery.component.js +0 -243
- package/esm2015/lib/components/previews/previews.component.js +0 -331
- package/esm2015/lib/components/upper-buttons/upper-buttons-default.js +0 -76
- package/esm2015/lib/components/upper-buttons/upper-buttons.component.js +0 -256
- package/esm2015/lib/directives/a-tag-bg-image.directive.js +0 -78
- package/esm2015/lib/directives/click-outside.directive.js +0 -85
- package/esm2015/lib/directives/description.directive.js +0 -99
- package/esm2015/lib/directives/direction.directive.js +0 -73
- package/esm2015/lib/directives/directives.js +0 -49
- package/esm2015/lib/directives/fallback-image.directive.js +0 -54
- package/esm2015/lib/directives/keyboard-navigation.directive.js +0 -52
- package/esm2015/lib/directives/margin.directive.js +0 -82
- package/esm2015/lib/directives/max-size.directive.js +0 -76
- package/esm2015/lib/directives/wrap.directive.js +0 -74
- package/esm2015/lib/modal-gallery.module.js +0 -64
- package/esm2015/lib/model/accessibility.interface.js +0 -25
- package/esm2015/lib/model/action.enum.js +0 -36
- package/esm2015/lib/model/buttons-config.interface.js +0 -66
- package/esm2015/lib/model/carousel-image-config.interface.js +0 -25
- package/esm2015/lib/model/current-image-config.interface.js +0 -25
- package/esm2015/lib/model/description.interface.js +0 -33
- package/esm2015/lib/model/image.class.js +0 -54
- package/esm2015/lib/model/interaction-event.interface.js +0 -2
- package/esm2015/lib/model/keyboard-config.interface.js +0 -25
- package/esm2015/lib/model/keyboard.enum.js +0 -35
- package/esm2015/lib/model/lib-config.interface.js +0 -25
- package/esm2015/lib/model/loading-config.interface.js +0 -37
- package/esm2015/lib/model/max-size.interface.js +0 -25
- package/esm2015/lib/model/modal-gallery-config.interface.js +0 -25
- package/esm2015/lib/model/plain-gallery-config.interface.js +0 -64
- package/esm2015/lib/model/play-config.interface.js +0 -25
- package/esm2015/lib/model/size.interface.js +0 -25
- package/esm2015/lib/model/slide-config.interface.js +0 -25
- package/esm2015/lib/services/config.service.js +0 -392
- package/esm2015/lib/services/id-validator.service.js +0 -71
- package/esm2015/lib/services/keyboard.service.js +0 -108
- package/esm2015/lib/utils/image.util.js +0 -48
- package/esm2015/lib/utils/user-input.util.js +0 -95
- package/esm2015/public-api.js +0 -46
- package/fesm2015/ks89-angular-modal-gallery.js.map +0 -1
- package/ks89-angular-modal-gallery.metadata.json +0 -1
|
@@ -1,772 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
The MIT License (MIT)
|
|
3
|
-
|
|
4
|
-
Copyright (c) 2017-2020 Stefano Cappa (Ks89)
|
|
5
|
-
|
|
6
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
-
in the Software without restriction, including without limitation the rights
|
|
9
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
-
furnished to do so, subject to the following conditions:
|
|
12
|
-
|
|
13
|
-
The above copyright notice and this permission notice shall be included in all
|
|
14
|
-
copies or substantial portions of the Software.
|
|
15
|
-
|
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
-
SOFTWARE.
|
|
23
|
-
*/
|
|
24
|
-
// The idea to create a carousel with two Subjects came from ng-bootstrap
|
|
25
|
-
// So a big thank you to the ng-bootstrap team for the interesting implementation that I used here with some customizations.
|
|
26
|
-
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostBinding, HostListener, Inject, Input, NgZone, Output, PLATFORM_ID } from '@angular/core';
|
|
27
|
-
import { isPlatformBrowser } from '@angular/common';
|
|
28
|
-
import { Subject, timer } from 'rxjs';
|
|
29
|
-
import { filter, map, switchMap, takeUntil } from 'rxjs/operators';
|
|
30
|
-
import { AccessibleComponent } from '../accessible.component';
|
|
31
|
-
import { ImageEvent } from '../../model/image.class';
|
|
32
|
-
import { Action } from '../../model/action.enum';
|
|
33
|
-
import { getIndex } from '../../utils/image.util';
|
|
34
|
-
import { NEXT, PREV } from '../../utils/user-input.util';
|
|
35
|
-
import { DescriptionStrategy } from '../../model/description.interface';
|
|
36
|
-
import { KS_DEFAULT_ACCESSIBILITY_CONFIG } from '../accessibility-default';
|
|
37
|
-
import { DomSanitizer } from '@angular/platform-browser';
|
|
38
|
-
import { ConfigService } from '../../services/config.service';
|
|
39
|
-
import { ModalGalleryService } from '../modal-gallery/modal-gallery.service';
|
|
40
|
-
/**
|
|
41
|
-
* Component with configurable inline/plain carousel.
|
|
42
|
-
*/
|
|
43
|
-
export class CarouselComponent extends AccessibleComponent {
|
|
44
|
-
constructor(
|
|
45
|
-
// tslint:disable-next-line:no-any
|
|
46
|
-
platformId, ngZone, modalGalleryService, configService, ref,
|
|
47
|
-
// sanitizer is used only to sanitize style before add it to background property when legacyIE11Mode is enabled
|
|
48
|
-
sanitizer) {
|
|
49
|
-
super();
|
|
50
|
-
this.platformId = platformId;
|
|
51
|
-
this.ngZone = ngZone;
|
|
52
|
-
this.modalGalleryService = modalGalleryService;
|
|
53
|
-
this.configService = configService;
|
|
54
|
-
this.ref = ref;
|
|
55
|
-
this.sanitizer = sanitizer;
|
|
56
|
-
/**
|
|
57
|
-
* Attribute to set ariaLabel of the host component
|
|
58
|
-
*/
|
|
59
|
-
this.ariaLabel = `Carousel`;
|
|
60
|
-
/**
|
|
61
|
-
* Array of `InternalLibImage` that represent the model of this library with all images,
|
|
62
|
-
* thumbs and so on.
|
|
63
|
-
*/
|
|
64
|
-
this.images = [];
|
|
65
|
-
/**
|
|
66
|
-
* boolean to enable/disable infinite sliding. Enabled by default.
|
|
67
|
-
*/
|
|
68
|
-
this.infinite = true;
|
|
69
|
-
/**
|
|
70
|
-
* TODO add description
|
|
71
|
-
*/
|
|
72
|
-
this.disableSsrWorkaround = false;
|
|
73
|
-
/**
|
|
74
|
-
* Output to emit an event when an image is changed.
|
|
75
|
-
*/
|
|
76
|
-
this.showImage = new EventEmitter();
|
|
77
|
-
/**
|
|
78
|
-
* Output to emit an event when the current image is the first one.
|
|
79
|
-
*/
|
|
80
|
-
this.firstImage = new EventEmitter();
|
|
81
|
-
/**
|
|
82
|
-
* Output to emit an event when the current image is the last one.
|
|
83
|
-
*/
|
|
84
|
-
this.lastImage = new EventEmitter();
|
|
85
|
-
/**
|
|
86
|
-
* Object use in template
|
|
87
|
-
*/
|
|
88
|
-
this.configAccessibility = KS_DEFAULT_ACCESSIBILITY_CONFIG;
|
|
89
|
-
/**
|
|
90
|
-
* Enum of type `Action` that represents a mouse click on a button.
|
|
91
|
-
* Declared here to be used inside the template.
|
|
92
|
-
*/
|
|
93
|
-
this.clickAction = Action.CLICK;
|
|
94
|
-
/**
|
|
95
|
-
* Enum of type `Action` that represents a keyboard action.
|
|
96
|
-
* Declared here to be used inside the template.
|
|
97
|
-
*/
|
|
98
|
-
this.keyboardAction = Action.KEYBOARD;
|
|
99
|
-
/**
|
|
100
|
-
* Boolean that it's true when you are watching the first image (currently visible).
|
|
101
|
-
* False by default
|
|
102
|
-
*/
|
|
103
|
-
this.isFirstImage = false;
|
|
104
|
-
/**
|
|
105
|
-
* Boolean that it's true when you are watching the last image (currently visible).
|
|
106
|
-
* False by default
|
|
107
|
-
*/
|
|
108
|
-
this.isLastImage = false;
|
|
109
|
-
/**
|
|
110
|
-
* Subject to play the carousel.
|
|
111
|
-
*/
|
|
112
|
-
this.start$ = new Subject();
|
|
113
|
-
/**
|
|
114
|
-
* Subject to stop the carousel.
|
|
115
|
-
*/
|
|
116
|
-
this.stop$ = new Subject();
|
|
117
|
-
/**
|
|
118
|
-
* Private object without type to define all swipe actions used by hammerjs.
|
|
119
|
-
*/
|
|
120
|
-
this.SWIPE_ACTION = {
|
|
121
|
-
LEFT: 'swipeleft',
|
|
122
|
-
RIGHT: 'swiperight',
|
|
123
|
-
UP: 'swipeup',
|
|
124
|
-
DOWN: 'swipedown'
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Listener to stop the gallery when the mouse pointer is over the current image.
|
|
129
|
-
*/
|
|
130
|
-
onMouseEnter() {
|
|
131
|
-
if (!this.id) {
|
|
132
|
-
throw new Error('Internal library error - id must be defined');
|
|
133
|
-
}
|
|
134
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
135
|
-
if (!libConfig) {
|
|
136
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
137
|
-
}
|
|
138
|
-
if (!libConfig.carouselPlayConfig || !libConfig.carouselPlayConfig.pauseOnHover) {
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
this.stopCarousel();
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Listener to play the gallery when the mouse pointer leave the current image.
|
|
145
|
-
*/
|
|
146
|
-
onMouseLeave() {
|
|
147
|
-
if (!this.id) {
|
|
148
|
-
throw new Error('Internal library error - id must be defined');
|
|
149
|
-
}
|
|
150
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
151
|
-
if (!libConfig) {
|
|
152
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
153
|
-
}
|
|
154
|
-
if (!libConfig.carouselPlayConfig || !libConfig.carouselPlayConfig.pauseOnHover || !libConfig.carouselPlayConfig.autoPlay) {
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
this.playCarousel();
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Listener to navigate carousel images with keyboard (left).
|
|
161
|
-
*/
|
|
162
|
-
onKeyDownLeft() {
|
|
163
|
-
if (!this.id) {
|
|
164
|
-
throw new Error('Internal library error - id must be defined');
|
|
165
|
-
}
|
|
166
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
167
|
-
if (!libConfig) {
|
|
168
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
169
|
-
}
|
|
170
|
-
if (!libConfig.carouselConfig || !libConfig.carouselConfig.keyboardEnable) {
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
this.prevImage();
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Listener to navigate carousel images with keyboard (right).
|
|
177
|
-
*/
|
|
178
|
-
onKeyDownLRight() {
|
|
179
|
-
if (!this.id) {
|
|
180
|
-
throw new Error('Internal library error - id must be defined');
|
|
181
|
-
}
|
|
182
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
183
|
-
if (!libConfig) {
|
|
184
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
185
|
-
}
|
|
186
|
-
if (!libConfig.carouselConfig || !libConfig.carouselConfig.keyboardEnable) {
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
this.nextImage();
|
|
190
|
-
}
|
|
191
|
-
ngOnChanges(changes) {
|
|
192
|
-
if (!this.id) {
|
|
193
|
-
throw new Error('Internal library error - id must be defined');
|
|
194
|
-
}
|
|
195
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
196
|
-
if (!libConfig) {
|
|
197
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
198
|
-
}
|
|
199
|
-
// handle changes of dotsConfig
|
|
200
|
-
const configDotsChange = changes.dotsConfig;
|
|
201
|
-
if (configDotsChange && configDotsChange.currentValue !== configDotsChange.previousValue) {
|
|
202
|
-
this.configService.setConfig(this.id, {
|
|
203
|
-
carouselDotsConfig: configDotsChange.currentValue
|
|
204
|
-
});
|
|
205
|
-
this.configDots = libConfig.carouselDotsConfig;
|
|
206
|
-
}
|
|
207
|
-
// handle changes of carouselConfig
|
|
208
|
-
const carouselConfigChange = changes.carouselConfig;
|
|
209
|
-
if (carouselConfigChange && carouselConfigChange.currentValue !== carouselConfigChange.previousValue) {
|
|
210
|
-
this.configService.setConfig(this.id, {
|
|
211
|
-
carouselConfig: carouselConfigChange.currentValue
|
|
212
|
-
});
|
|
213
|
-
this.configCarousel = carouselConfigChange.currentValue;
|
|
214
|
-
}
|
|
215
|
-
// handle changes of playConfig starting/stopping the carousel accordingly
|
|
216
|
-
const playConfigChange = changes.playConfig;
|
|
217
|
-
if (playConfigChange) {
|
|
218
|
-
const playConfigChangePrev = playConfigChange.previousValue;
|
|
219
|
-
const playConfigChangeCurr = playConfigChange.currentValue;
|
|
220
|
-
if (playConfigChangePrev !== playConfigChangeCurr) {
|
|
221
|
-
this.configService.setConfig(this.id, {
|
|
222
|
-
carouselPlayConfig: playConfigChange.currentValue
|
|
223
|
-
});
|
|
224
|
-
// this.configPlay = playConfigChange.currentValue;
|
|
225
|
-
// if autoplay is enabled, and this is not the
|
|
226
|
-
// first change (to prevent multiple starts at the beginning)
|
|
227
|
-
if (playConfigChangeCurr.autoPlay && !playConfigChange.isFirstChange()) {
|
|
228
|
-
this.start$.next();
|
|
229
|
-
}
|
|
230
|
-
else {
|
|
231
|
-
this.stopCarousel();
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
ngOnInit() {
|
|
237
|
-
if (!this.id) {
|
|
238
|
-
throw new Error('Internal library error - id must be defined');
|
|
239
|
-
}
|
|
240
|
-
if (!this.images) {
|
|
241
|
-
throw new Error('Internal library error - images must be defined');
|
|
242
|
-
}
|
|
243
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
244
|
-
if (!libConfig) {
|
|
245
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
246
|
-
}
|
|
247
|
-
this.currentImage = this.images[0];
|
|
248
|
-
this.configService.setConfig(this.id, {
|
|
249
|
-
carouselConfig: this.carouselConfig,
|
|
250
|
-
carouselImageConfig: this.carouselImageConfig,
|
|
251
|
-
carouselPlayConfig: this.playConfig,
|
|
252
|
-
carouselPreviewsConfig: this.previewConfig,
|
|
253
|
-
carouselDotsConfig: this.dotsConfig,
|
|
254
|
-
accessibilityConfig: this.accessibilityConfig,
|
|
255
|
-
// this custom config with 'disableSsrWorkaround: true' is required in case of SystemJS
|
|
256
|
-
keyboardServiceConfig: {
|
|
257
|
-
shortcuts: ['ctrl+s', 'meta+s'],
|
|
258
|
-
disableSsrWorkaround: this.disableSsrWorkaround
|
|
259
|
-
}
|
|
260
|
-
});
|
|
261
|
-
this.configCarousel = libConfig.carouselConfig;
|
|
262
|
-
this.configCarouselImage = libConfig.carouselImageConfig;
|
|
263
|
-
this.configPlay = libConfig.carouselPlayConfig;
|
|
264
|
-
this.configPreview = libConfig.carouselPreviewsConfig;
|
|
265
|
-
this.configDots = libConfig.carouselDotsConfig;
|
|
266
|
-
this.configAccessibility = libConfig.accessibilityConfig;
|
|
267
|
-
this.manageSlideConfig();
|
|
268
|
-
}
|
|
269
|
-
ngAfterContentInit() {
|
|
270
|
-
// interval doesn't play well with SSR and protractor,
|
|
271
|
-
// so we should run it in the browser and outside Angular
|
|
272
|
-
if (isPlatformBrowser(this.platformId)) {
|
|
273
|
-
if (!this.id) {
|
|
274
|
-
throw new Error('Internal library error - id must be defined');
|
|
275
|
-
}
|
|
276
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
277
|
-
if (!libConfig || !libConfig.carouselPlayConfig) {
|
|
278
|
-
throw new Error('Internal library error - libConfig and carouselPlayConfig must be defined');
|
|
279
|
-
}
|
|
280
|
-
this.ngZone.runOutsideAngular(() => {
|
|
281
|
-
this.start$
|
|
282
|
-
.pipe(map(() => libConfig && libConfig.carouselPlayConfig && libConfig.carouselPlayConfig.interval),
|
|
283
|
-
// tslint:disable-next-line:no-any
|
|
284
|
-
filter((interval) => interval > 0), switchMap(interval => timer(interval).pipe(takeUntil(this.stop$))))
|
|
285
|
-
.subscribe(() => this.ngZone.run(() => {
|
|
286
|
-
if (this.configPlay && this.configPlay.autoPlay) {
|
|
287
|
-
this.nextImage();
|
|
288
|
-
}
|
|
289
|
-
this.ref.markForCheck();
|
|
290
|
-
}));
|
|
291
|
-
this.start$.next();
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
/**
|
|
296
|
-
* Method used in template to sanitize an url when you need legacyIE11Mode.
|
|
297
|
-
* In this way you can set an url as background of a div.
|
|
298
|
-
* @param unsafeStyle is a string and represents the url to sanitize.
|
|
299
|
-
* @param unsafeStyleFallback is a string and represents the fallback url to sanitize.
|
|
300
|
-
* @returns a SafeStyle object that can be used in template without problems.
|
|
301
|
-
*/
|
|
302
|
-
sanitizeUrlBgStyle(unsafeStyle, unsafeStyleFallback) {
|
|
303
|
-
// Method used only to sanitize background-image style before add it to background property when legacyIE11Mode is enabled
|
|
304
|
-
let bg = 'url(' + unsafeStyle + ')';
|
|
305
|
-
if (!!unsafeStyleFallback) {
|
|
306
|
-
// if a fallback image is defined, append it. In this way, it will be used by the browser as fallback.
|
|
307
|
-
bg += ', ' + 'url(' + unsafeStyleFallback + ')';
|
|
308
|
-
}
|
|
309
|
-
return this.sanitizer.bypassSecurityTrustStyle(bg);
|
|
310
|
-
}
|
|
311
|
-
/**
|
|
312
|
-
* Method called when a dot is clicked and used to update the current image.
|
|
313
|
-
* @param number index of the clicked dot
|
|
314
|
-
*/
|
|
315
|
-
onClickDot(index) {
|
|
316
|
-
this.changeCurrentImage(this.images[index], Action.NORMAL);
|
|
317
|
-
}
|
|
318
|
-
/**
|
|
319
|
-
* Method called by events from both keyboard and mouse on a navigation arrow.
|
|
320
|
-
* @param string direction of the navigation that can be either 'next' or 'prev'
|
|
321
|
-
* @param KeyboardEvent | MouseEvent event payload
|
|
322
|
-
* @param Action action that triggered the event or `Action.NORMAL` if not provided
|
|
323
|
-
*/
|
|
324
|
-
onNavigationEvent(direction, event, action = Action.NORMAL) {
|
|
325
|
-
const result = super.handleNavigationEvent(direction, event);
|
|
326
|
-
if (result === NEXT) {
|
|
327
|
-
this.nextImage(action);
|
|
328
|
-
}
|
|
329
|
-
else if (result === PREV) {
|
|
330
|
-
this.prevImage(action);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* Method triggered when you click on the current image.
|
|
335
|
-
* Also, if modalGalleryEnable is true, you can open the modal-gallery.
|
|
336
|
-
*/
|
|
337
|
-
onClickCurrentImage() {
|
|
338
|
-
if (!this.id) {
|
|
339
|
-
throw new Error('Internal library error - id must be defined');
|
|
340
|
-
}
|
|
341
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
342
|
-
if (!libConfig || !libConfig.carouselConfig || !this.currentImage) {
|
|
343
|
-
throw new Error('Internal library error - libConfig, carouselConfig and currentImage must be defined');
|
|
344
|
-
}
|
|
345
|
-
if (!libConfig.carouselConfig.modalGalleryEnable) {
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
const index = getIndex(this.currentImage, this.images);
|
|
349
|
-
this.modalGalleryService.open({
|
|
350
|
-
id: this.id,
|
|
351
|
-
images: this.images,
|
|
352
|
-
currentImage: this.images[index],
|
|
353
|
-
libConfig: {
|
|
354
|
-
// this custom config with 'disableSsrWorkaround: true' is required in case of SystemJS
|
|
355
|
-
keyboardServiceConfig: {
|
|
356
|
-
shortcuts: ['ctrl+s', 'meta+s'],
|
|
357
|
-
disableSsrWorkaround: this.disableSsrWorkaround
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
/**
|
|
363
|
-
* Method to get the image description based on input params.
|
|
364
|
-
* If you provide a full description this will be the visible description, otherwise,
|
|
365
|
-
* it will be built using the `Description` object, concatenating its fields.
|
|
366
|
-
* @param Image image to get its description. If not provided it will be the current image
|
|
367
|
-
* @returns String description of the image (or the current image if not provided)
|
|
368
|
-
* @throws an Error if description isn't available
|
|
369
|
-
*/
|
|
370
|
-
getDescriptionToDisplay(image = this.currentImage) {
|
|
371
|
-
if (!this.id) {
|
|
372
|
-
throw new Error('Internal library error - id must be defined');
|
|
373
|
-
}
|
|
374
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
375
|
-
if (!libConfig) {
|
|
376
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
377
|
-
}
|
|
378
|
-
const configCurrentImageCarousel = libConfig.carouselImageConfig;
|
|
379
|
-
if (!configCurrentImageCarousel || !configCurrentImageCarousel.description) {
|
|
380
|
-
throw new Error('Description input must be a valid object implementing the Description interface');
|
|
381
|
-
}
|
|
382
|
-
if (!image) {
|
|
383
|
-
throw new Error('Internal library error - image must be defined');
|
|
384
|
-
}
|
|
385
|
-
const imageWithoutDescription = !image || !image.modal || !image.modal.description || image.modal.description === '';
|
|
386
|
-
switch (configCurrentImageCarousel.description.strategy) {
|
|
387
|
-
case DescriptionStrategy.HIDE_IF_EMPTY:
|
|
388
|
-
return imageWithoutDescription ? '' : image.modal.description + '';
|
|
389
|
-
case DescriptionStrategy.ALWAYS_HIDDEN:
|
|
390
|
-
return '';
|
|
391
|
-
default:
|
|
392
|
-
// ----------- DescriptionStrategy.ALWAYS_VISIBLE -----------------
|
|
393
|
-
return this.buildTextDescription(image, imageWithoutDescription);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
/**
|
|
397
|
-
* Method used by Hammerjs to support touch gestures (you can also invert the swipe direction with configCurrentImage.invertSwipe).
|
|
398
|
-
* @param action String that represent the direction of the swipe action. 'swiperight' by default.
|
|
399
|
-
*/
|
|
400
|
-
swipe(action = this.SWIPE_ACTION.RIGHT) {
|
|
401
|
-
if (!this.id) {
|
|
402
|
-
throw new Error('Internal library error - id must be defined');
|
|
403
|
-
}
|
|
404
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
405
|
-
if (!libConfig || !libConfig.carouselImageConfig) {
|
|
406
|
-
throw new Error('Internal library error - libConfig and carouselImageConfig must be defined');
|
|
407
|
-
}
|
|
408
|
-
const configCurrentImageCarousel = libConfig.carouselImageConfig;
|
|
409
|
-
switch (action) {
|
|
410
|
-
case this.SWIPE_ACTION.RIGHT:
|
|
411
|
-
if (configCurrentImageCarousel.invertSwipe) {
|
|
412
|
-
this.prevImage(Action.SWIPE);
|
|
413
|
-
}
|
|
414
|
-
else {
|
|
415
|
-
this.nextImage(Action.SWIPE);
|
|
416
|
-
}
|
|
417
|
-
break;
|
|
418
|
-
case this.SWIPE_ACTION.LEFT:
|
|
419
|
-
if (configCurrentImageCarousel.invertSwipe) {
|
|
420
|
-
this.nextImage(Action.SWIPE);
|
|
421
|
-
}
|
|
422
|
-
else {
|
|
423
|
-
this.prevImage(Action.SWIPE);
|
|
424
|
-
}
|
|
425
|
-
break;
|
|
426
|
-
// case this.SWIPE_ACTION.UP:
|
|
427
|
-
// break;
|
|
428
|
-
// case this.SWIPE_ACTION.DOWN:
|
|
429
|
-
// break;
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
/**
|
|
433
|
-
* Method to go back to the previous image.
|
|
434
|
-
* @param action Enum of type `Action` that represents the source
|
|
435
|
-
* action that moved back to the previous image. `Action.NORMAL` by default.
|
|
436
|
-
*/
|
|
437
|
-
prevImage(action = Action.NORMAL) {
|
|
438
|
-
// check if prevImage should be blocked
|
|
439
|
-
if (this.isPreventSliding(0)) {
|
|
440
|
-
return;
|
|
441
|
-
}
|
|
442
|
-
this.changeCurrentImage(this.getPrevImage(), action);
|
|
443
|
-
this.manageSlideConfig();
|
|
444
|
-
this.start$.next();
|
|
445
|
-
}
|
|
446
|
-
/**
|
|
447
|
-
* Method to go back to the previous image.
|
|
448
|
-
* @param action Enum of type `Action` that represents the source
|
|
449
|
-
* action that moved to the next image. `Action.NORMAL` by default.
|
|
450
|
-
*/
|
|
451
|
-
nextImage(action = Action.NORMAL) {
|
|
452
|
-
// check if nextImage should be blocked
|
|
453
|
-
if (this.isPreventSliding(this.images.length - 1)) {
|
|
454
|
-
return;
|
|
455
|
-
}
|
|
456
|
-
this.changeCurrentImage(this.getNextImage(), action);
|
|
457
|
-
this.manageSlideConfig();
|
|
458
|
-
this.start$.next();
|
|
459
|
-
}
|
|
460
|
-
/**
|
|
461
|
-
* Method used in the template to track ids in ngFor.
|
|
462
|
-
* @param number index of the array
|
|
463
|
-
* @param Image item of the array
|
|
464
|
-
* @returns number the id of the item
|
|
465
|
-
*/
|
|
466
|
-
trackById(index, item) {
|
|
467
|
-
return item.id;
|
|
468
|
-
}
|
|
469
|
-
/**
|
|
470
|
-
* Method called when an image preview is clicked and used to update the current image.
|
|
471
|
-
* @param event an ImageEvent object with the relative action and the index of the clicked preview.
|
|
472
|
-
*/
|
|
473
|
-
onClickPreview(event) {
|
|
474
|
-
const imageFound = this.images[event.result];
|
|
475
|
-
if (!!imageFound) {
|
|
476
|
-
this.manageSlideConfig();
|
|
477
|
-
this.changeCurrentImage(imageFound, event.action);
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
/**
|
|
481
|
-
* Method to play carousel.
|
|
482
|
-
*/
|
|
483
|
-
playCarousel() {
|
|
484
|
-
this.start$.next();
|
|
485
|
-
}
|
|
486
|
-
/**
|
|
487
|
-
* Stops the carousel from cycling through items.
|
|
488
|
-
*/
|
|
489
|
-
stopCarousel() {
|
|
490
|
-
this.stop$.next();
|
|
491
|
-
}
|
|
492
|
-
// TODO remove this because duplicated
|
|
493
|
-
/**
|
|
494
|
-
* Method to get `alt attribute`.
|
|
495
|
-
* `alt` specifies an alternate text for an image, if the image cannot be displayed.
|
|
496
|
-
* @param Image image to get its alt description. If not provided it will be the current image
|
|
497
|
-
* @returns String alt description of the image (or the current image if not provided)
|
|
498
|
-
*/
|
|
499
|
-
getAltDescriptionByImage(image = this.currentImage) {
|
|
500
|
-
if (!image) {
|
|
501
|
-
return '';
|
|
502
|
-
}
|
|
503
|
-
return image.modal && image.modal.description ? image.modal.description : `Image ${getIndex(image, this.images) + 1}`;
|
|
504
|
-
}
|
|
505
|
-
// TODO remove this because duplicated
|
|
506
|
-
/**
|
|
507
|
-
* Method to get the title attributes based on descriptions.
|
|
508
|
-
* This is useful to prevent accessibility issues, because if DescriptionStrategy is ALWAYS_HIDDEN,
|
|
509
|
-
* it prevents an empty string as title.
|
|
510
|
-
* @param Image image to get its description. If not provided it will be the current image
|
|
511
|
-
* @returns String title of the image based on descriptions
|
|
512
|
-
* @throws an Error if description isn't available
|
|
513
|
-
*/
|
|
514
|
-
getTitleToDisplay(image = this.currentImage) {
|
|
515
|
-
if (!this.id) {
|
|
516
|
-
throw new Error('Internal library error - id must be defined');
|
|
517
|
-
}
|
|
518
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
519
|
-
if (!libConfig || !libConfig.carouselImageConfig) {
|
|
520
|
-
throw new Error('Internal library error - libConfig and carouselImageConfig must be defined');
|
|
521
|
-
}
|
|
522
|
-
const configCurrentImageCarousel = libConfig.carouselImageConfig;
|
|
523
|
-
if (!configCurrentImageCarousel || !configCurrentImageCarousel.description) {
|
|
524
|
-
throw new Error('Description input must be a valid object implementing the Description interface');
|
|
525
|
-
}
|
|
526
|
-
const imageWithoutDescription = !image || !image.modal || !image.modal.description || image.modal.description === '';
|
|
527
|
-
const description = this.buildTextDescription(image, imageWithoutDescription);
|
|
528
|
-
return description;
|
|
529
|
-
}
|
|
530
|
-
/**
|
|
531
|
-
* Method to reset carousel (force image with index 0 to be the current image and re-init also previews)
|
|
532
|
-
*/
|
|
533
|
-
// temporary removed because never tested
|
|
534
|
-
// reset() {
|
|
535
|
-
// if (this.configPlay && this.configPlay.autoPlay) {
|
|
536
|
-
// this.stopCarousel();
|
|
537
|
-
// }
|
|
538
|
-
// this.currentImage = this.images[0];
|
|
539
|
-
// this.handleBoundaries(0);
|
|
540
|
-
// if (this.configPlay && this.configPlay.autoPlay) {
|
|
541
|
-
// this.playCarousel();
|
|
542
|
-
// }
|
|
543
|
-
// this.ref.markForCheck();
|
|
544
|
-
// }
|
|
545
|
-
/**
|
|
546
|
-
* Method to cleanup resources. In fact, this will stop the carousel.
|
|
547
|
-
* This is an Angular's lifecycle hook that is called when this component is destroyed.
|
|
548
|
-
*/
|
|
549
|
-
ngOnDestroy() {
|
|
550
|
-
this.stopCarousel();
|
|
551
|
-
}
|
|
552
|
-
/**
|
|
553
|
-
* Method to change the current image, receiving the new image as input the relative action.
|
|
554
|
-
* @param image an Image object that represents the new image to set as current.
|
|
555
|
-
* @param action Enum of type `Action` that represents the source action that triggered the change.
|
|
556
|
-
*/
|
|
557
|
-
changeCurrentImage(image, action) {
|
|
558
|
-
if (!this.id) {
|
|
559
|
-
throw new Error('Internal library error - id must be defined');
|
|
560
|
-
}
|
|
561
|
-
this.currentImage = image;
|
|
562
|
-
const index = getIndex(image, this.images);
|
|
563
|
-
// emit first/last event based on newIndex value
|
|
564
|
-
this.emitBoundaryEvent(action, index);
|
|
565
|
-
// emit current visible image index
|
|
566
|
-
this.showImage.emit(new ImageEvent(this.id, action, index + 1));
|
|
567
|
-
}
|
|
568
|
-
/**
|
|
569
|
-
* Private method to get the next index.
|
|
570
|
-
* This is necessary because at the end, when you call next again, you'll go to the first image.
|
|
571
|
-
* That happens because all modal images are shown like in a circle.
|
|
572
|
-
*/
|
|
573
|
-
getNextImage() {
|
|
574
|
-
if (!this.currentImage) {
|
|
575
|
-
throw new Error('Internal library error - currentImage must be defined');
|
|
576
|
-
}
|
|
577
|
-
const currentIndex = getIndex(this.currentImage, this.images);
|
|
578
|
-
let newIndex = 0;
|
|
579
|
-
if (currentIndex >= 0 && currentIndex < this.images.length - 1) {
|
|
580
|
-
newIndex = currentIndex + 1;
|
|
581
|
-
}
|
|
582
|
-
else {
|
|
583
|
-
newIndex = 0; // start from the first index
|
|
584
|
-
}
|
|
585
|
-
return this.images[newIndex];
|
|
586
|
-
}
|
|
587
|
-
/**
|
|
588
|
-
* Private method to get the previous index.
|
|
589
|
-
* This is necessary because at index 0, when you call prev again, you'll go to the last image.
|
|
590
|
-
* That happens because all modal images are shown like in a circle.
|
|
591
|
-
*/
|
|
592
|
-
getPrevImage() {
|
|
593
|
-
if (!this.currentImage) {
|
|
594
|
-
throw new Error('Internal library error - currentImage must be defined');
|
|
595
|
-
}
|
|
596
|
-
const currentIndex = getIndex(this.currentImage, this.images);
|
|
597
|
-
let newIndex = 0;
|
|
598
|
-
if (currentIndex > 0 && currentIndex <= this.images.length - 1) {
|
|
599
|
-
newIndex = currentIndex - 1;
|
|
600
|
-
}
|
|
601
|
-
else {
|
|
602
|
-
newIndex = this.images.length - 1; // start from the last index
|
|
603
|
-
}
|
|
604
|
-
return this.images[newIndex];
|
|
605
|
-
}
|
|
606
|
-
/**
|
|
607
|
-
* Private method to build a text description.
|
|
608
|
-
* This is used also to create titles.
|
|
609
|
-
* @param Image image to get its description. If not provided it will be the current image.
|
|
610
|
-
* @param boolean imageWithoutDescription is a boolean that it's true if the image hasn't a 'modal' description.
|
|
611
|
-
* @returns String description built concatenating image fields with a specific logic.
|
|
612
|
-
*/
|
|
613
|
-
buildTextDescription(image, imageWithoutDescription) {
|
|
614
|
-
if (!this.id) {
|
|
615
|
-
throw new Error('Internal library error - id must be defined');
|
|
616
|
-
}
|
|
617
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
618
|
-
if (!libConfig || !libConfig.carouselImageConfig) {
|
|
619
|
-
throw new Error('Internal library error - libConfig and carouselImageConfig must be defined');
|
|
620
|
-
}
|
|
621
|
-
const configCurrentImageCarousel = libConfig.carouselImageConfig;
|
|
622
|
-
if (!configCurrentImageCarousel || !configCurrentImageCarousel.description) {
|
|
623
|
-
throw new Error('Description input must be a valid object implementing the Description interface');
|
|
624
|
-
}
|
|
625
|
-
if (!image) {
|
|
626
|
-
throw new Error('Internal library error - image must be defined');
|
|
627
|
-
}
|
|
628
|
-
// If customFullDescription use it, otherwise proceed to build a description
|
|
629
|
-
if (configCurrentImageCarousel.description.customFullDescription && configCurrentImageCarousel.description.customFullDescription !== '') {
|
|
630
|
-
return configCurrentImageCarousel.description.customFullDescription;
|
|
631
|
-
}
|
|
632
|
-
const currentIndex = getIndex(image, this.images);
|
|
633
|
-
// If the current image hasn't a description,
|
|
634
|
-
// prevent to write the ' - ' (or this.description.beforeTextDescription)
|
|
635
|
-
const prevDescription = configCurrentImageCarousel.description.imageText ? configCurrentImageCarousel.description.imageText : '';
|
|
636
|
-
const midSeparator = configCurrentImageCarousel.description.numberSeparator ? configCurrentImageCarousel.description.numberSeparator : '';
|
|
637
|
-
const middleDescription = currentIndex + 1 + midSeparator + this.images.length;
|
|
638
|
-
if (imageWithoutDescription) {
|
|
639
|
-
return prevDescription + middleDescription;
|
|
640
|
-
}
|
|
641
|
-
const currImgDescription = image.modal && image.modal.description ? image.modal.description : '';
|
|
642
|
-
const endDescription = configCurrentImageCarousel.description.beforeTextDescription + currImgDescription;
|
|
643
|
-
return prevDescription + middleDescription + endDescription;
|
|
644
|
-
}
|
|
645
|
-
/**
|
|
646
|
-
* Private method to update both `isFirstImage` and `isLastImage` based on
|
|
647
|
-
* the index of the current image.
|
|
648
|
-
* @param number currentIndex is the index of the current image
|
|
649
|
-
*/
|
|
650
|
-
handleBoundaries(currentIndex) {
|
|
651
|
-
if (this.images.length === 1) {
|
|
652
|
-
this.isFirstImage = true;
|
|
653
|
-
this.isLastImage = true;
|
|
654
|
-
return;
|
|
655
|
-
}
|
|
656
|
-
switch (currentIndex) {
|
|
657
|
-
case 0:
|
|
658
|
-
// execute this only if infinite sliding is disabled
|
|
659
|
-
this.isFirstImage = true;
|
|
660
|
-
this.isLastImage = false;
|
|
661
|
-
break;
|
|
662
|
-
case this.images.length - 1:
|
|
663
|
-
// execute this only if infinite sliding is disabled
|
|
664
|
-
this.isFirstImage = false;
|
|
665
|
-
this.isLastImage = true;
|
|
666
|
-
break;
|
|
667
|
-
default:
|
|
668
|
-
this.isFirstImage = false;
|
|
669
|
-
this.isLastImage = false;
|
|
670
|
-
break;
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
/**
|
|
674
|
-
* Private method to manage boundary arrows and sliding.
|
|
675
|
-
* This is based on the slideConfig input to enable/disable 'infinite sliding'.
|
|
676
|
-
* @param number index of the visible image
|
|
677
|
-
*/
|
|
678
|
-
manageSlideConfig() {
|
|
679
|
-
if (!this.currentImage) {
|
|
680
|
-
throw new Error('Internal library error - currentImage must be defined');
|
|
681
|
-
}
|
|
682
|
-
let index;
|
|
683
|
-
try {
|
|
684
|
-
index = getIndex(this.currentImage, this.images);
|
|
685
|
-
}
|
|
686
|
-
catch (err) {
|
|
687
|
-
console.error('Cannot get the current image index in current-image');
|
|
688
|
-
throw err;
|
|
689
|
-
}
|
|
690
|
-
if (this.infinite === true) {
|
|
691
|
-
// enable infinite sliding
|
|
692
|
-
this.isFirstImage = false;
|
|
693
|
-
this.isLastImage = false;
|
|
694
|
-
}
|
|
695
|
-
else {
|
|
696
|
-
this.handleBoundaries(index);
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
/**
|
|
700
|
-
* Private method to emit events when either the last or the first image are visible.
|
|
701
|
-
* @param action Enum of type Action that represents the source of the event that changed the
|
|
702
|
-
* current image to the first one or the last one.
|
|
703
|
-
* @param indexToCheck is the index number of the image (the first or the last one).
|
|
704
|
-
*/
|
|
705
|
-
emitBoundaryEvent(action, indexToCheck) {
|
|
706
|
-
if (!this.id) {
|
|
707
|
-
return;
|
|
708
|
-
}
|
|
709
|
-
// to emit first/last event
|
|
710
|
-
switch (indexToCheck) {
|
|
711
|
-
case 0:
|
|
712
|
-
this.firstImage.emit(new ImageEvent(this.id, action, true));
|
|
713
|
-
break;
|
|
714
|
-
case this.images.length - 1:
|
|
715
|
-
this.lastImage.emit(new ImageEvent(this.id, action, true));
|
|
716
|
-
break;
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
/**
|
|
720
|
-
* Private method to check if next/prev actions should be blocked.
|
|
721
|
-
* It checks if slideConfig.infinite === false and if the image index is equals to the input parameter.
|
|
722
|
-
* If yes, it returns true to say that sliding should be blocked, otherwise not.
|
|
723
|
-
* @param number boundaryIndex that could be either the beginning index (0) or the last index
|
|
724
|
-
* of images (this.images.length - 1).
|
|
725
|
-
* @returns boolean true if slideConfig.infinite === false and the current index is
|
|
726
|
-
* either the first or the last one.
|
|
727
|
-
*/
|
|
728
|
-
isPreventSliding(boundaryIndex) {
|
|
729
|
-
if (!this.currentImage) {
|
|
730
|
-
throw new Error('Internal library error - currentImage must be defined');
|
|
731
|
-
}
|
|
732
|
-
return !this.infinite && getIndex(this.currentImage, this.images) === boundaryIndex;
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
CarouselComponent.decorators = [
|
|
736
|
-
{ type: Component, args: [{
|
|
737
|
-
selector: 'ks-carousel',
|
|
738
|
-
template: "<main id=\"carousel-container\"\n [attr.aria-label]=\"configAccessibility.carouselContainerAriaLabel\"\n [title]=\"configAccessibility.carouselContainerTitle\"\n ksMaxSize [maxSizeConfig]=\"{maxWidth: configCarousel?.maxWidth,\n maxHeight: ''}\">\n\n\n <!-- Workaround to support 2 ng-content in the same template in 2 ngIf (https://github.com/angular/angular/issues/22972) -->\n <ng-template #content><ng-content></ng-content></ng-template>\n\n <!-- Normal figure used by all browsers except for IE11, because\n it doesn't support object-fit cover.-->\n <figure class=\"current-figure\" *ngIf=\"configCarousel?.legacyIE11Mode === false; else legacyMode\"\n ksSize [sizeConfig]=\"{width: configCarousel?.maxWidth,\n height: ''}\">\n\n <a class=\"nav-left\" *ngIf=\"configCarousel?.showArrows\"\n [attr.aria-label]=\"configAccessibility.carouselPrevImageAriaLabel\"\n [tabIndex]=\"isLastImage && !infinite ? -1 : 0\" role=\"button\"\n (click)=\"onNavigationEvent('left', $event, clickAction)\" (keyup)=\"onNavigationEvent('left', $event, keyboardAction)\">\n <div class=\"inside {{(isFirstImage && !infinite) || !configCarousel.showArrows ? 'empty-arrow-image' : 'left-arrow-image'}}\"\n aria-hidden=\"true\"\n [title]=\"configAccessibility.carouselPrevImageTitle\"></div>\n </a>\n\n <ng-container *ngTemplateOutlet=\"content\"></ng-container>\n\n <img id=\"current-image\"\n [style.object-fit]=\"configCarousel?.objectFit\"\n ksMaxSize [maxSizeConfig]=\"{maxWidth: configCarousel?.maxWidth,\n maxHeight: configCarousel?.maxHeight}\"\n [src]=\"currentImage.modal.img\"\n ksFallbackImage [fallbackImg]=\"currentImage.modal.fallbackImg\"\n [attr.aria-label]=\"currentImage.modal.ariaLabel\"\n [title]=\"(currentImage.modal.title || currentImage.modal.title === '') ? currentImage.modal.title : getTitleToDisplay()\"\n alt=\"{{currentImage.modal.alt ? currentImage.modal.alt : getAltDescriptionByImage()}}\"\n [tabIndex]=\"0\" role=\"img\"\n (click)=\"onClickCurrentImage()\"\n (swipeleft)=\"swipe($event.type)\"\n (swiperight)=\"swipe($event.type)\"/>\n\n <figcaption *ngIf=\"getDescriptionToDisplay() !== ''\"\n class=\"description\"\n ksDescription [description]=\"configCarouselImage?.description\"\n [innerHTML]=\"getDescriptionToDisplay()\"></figcaption>\n\n <a class=\"nav-right\" *ngIf=\"configCarousel?.showArrows\"\n [attr.aria-label]=\"configAccessibility.carouselNextImageAriaLabel\"\n [tabIndex]=\"isLastImage && !infinite ? -1 : 0\" role=\"button\"\n (click)=\"onNavigationEvent('right', $event, clickAction)\" (keyup)=\"onNavigationEvent('right', $event, keyboardAction)\">\n <div class=\"inside {{(isLastImage && !infinite) || !configCarousel.showArrows ? 'empty-arrow-image' : 'right-arrow-image'}}\"\n aria-hidden=\"true\"\n [title]=\"configAccessibility.carouselNextImageTitle\"></div>\n </a>\n\n <div id=\"dots\">\n <ks-dots [id]=\"id\"\n [currentImage]=\"currentImage\"\n [images]=\"images\"\n [dotsConfig]=\"dotsConfig\"\n (clickDot)=\"onClickDot($event)\"></ks-dots>\n </div>\n\n </figure>\n\n <!-- Legacy mode to support img cover also on IE11,\n because it doesn't support natively object-fit cover. -->\n <ng-template #legacyMode>\n <div class=\"current-figure\"\n ksSize [sizeConfig]=\"{width: configCarousel?.maxWidth,\n height: ''}\">\n\n <a class=\"nav-left\" *ngIf=\"configCarousel?.showArrows\"\n [attr.aria-label]=\"configAccessibility.carouselPrevImageAriaLabel\"\n [tabindex]=\"isLastImage && !infinite ? -1 : 0\" role=\"button\"\n (click)=\"onNavigationEvent('left', $event, clickAction)\" (keyup)=\"onNavigationEvent('left', $event, keyboardAction)\">\n <div class=\"inside {{(isFirstImage && !infinite) || !configCarousel.showArrows ? 'empty-arrow-image' : 'left-arrow-image'}}\"\n aria-hidden=\"true\"\n [title]=\"configAccessibility.carouselPrevImageTitle\"></div>\n </a>\n\n <ng-container *ngTemplateOutlet=\"content\"></ng-container>\n\n <div id=\"current-image-legacy\"\n [style.background-color]=\"'transparent'\"\n [style.background-image]=\"sanitizeUrlBgStyle(currentImage.modal.img + '', currentImage.modal.fallbackImg + '')\"\n [style.background-position]=\"'center center'\"\n [style.background-size]=\"'cover'\"\n [style.background-repeat]=\"'no-repeat'\"\n [style.background-attachment]=\"'scroll'\"\n ksSize [sizeConfig]=\"{width: '100%',\n height: configCarousel?.maxHeight}\"\n ksMaxSize [maxSizeConfig]=\"{maxWidth: configCarousel?.maxWidth}\"\n [attr.aria-label]=\"currentImage.modal.ariaLabel\"\n [title]=\"(currentImage.modal.title || currentImage.modal.title === '') ? currentImage.modal.title : getTitleToDisplay()\"\n [tabIndex]=\"0\" role=\"img\"\n (click)=\"onClickCurrentImage()\"\n (swipeleft)=\"swipe($event.type)\"\n (swiperight)=\"swipe($event.type)\">\n\n <div *ngIf=\"getDescriptionToDisplay() !== ''\"\n class=\"description-ie11\"\n ksDescription [description]=\"configCarouselImage?.description\"\n [innerHTML]=\"getDescriptionToDisplay()\"></div>\n </div>\n\n <a class=\"nav-right\" *ngIf=\"configCarousel?.showArrows\"\n [attr.aria-label]=\"configAccessibility.carouselNextImageAriaLabel\"\n [tabIndex]=\"isLastImage && !infinite ? -1 : 0\" role=\"button\"\n (click)=\"onNavigationEvent('right', $event, clickAction)\" (keyup)=\"onNavigationEvent('right', $event, keyboardAction)\">\n <div class=\"inside {{(isLastImage && !infinite) || !configCarousel.showArrows ? 'empty-arrow-image' : 'right-arrow-image'}}\"\n aria-hidden=\"true\"\n [title]=\"configAccessibility.carouselNextImageTitle\"></div>\n </a>\n\n <div id=\"dots-ie11\">\n <ks-dots [id]=\"id\"\n [currentImage]=\"currentImage\"\n [images]=\"images\"\n (clickDot)=\"onClickDot($event)\"></ks-dots>\n </div>\n\n </div>\n </ng-template>\n\n</main>\n\n<ks-carousel-previews [id]=\"id\"\n [images]=\"images\"\n [currentImage]=\"currentImage\"\n (clickPreview)=\"onClickPreview($event)\"></ks-carousel-previews>\n",
|
|
739
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
740
|
-
providers: [ConfigService],
|
|
741
|
-
styles: [":host{flex-direction:column;justify-content:flex-start}#carousel-container,:host{align-items:center;display:flex}#carousel-container{flex-direction:row;justify-content:space-between;width:100%}#carousel-container>.current-figure{animation:fadein-visible .8s;margin:0;position:relative;text-align:center}#carousel-container>.current-figure .nav,#carousel-container>.current-figure>.nav-left,#carousel-container>.current-figure>.nav-right{animation:animatezoom 1s;cursor:pointer;position:absolute;top:50%;transition:all .5s}#carousel-container>.current-figure .nav:hover,#carousel-container>.current-figure>.nav-left:hover,#carousel-container>.current-figure>.nav-right:hover{transform:scale(1.1)}#carousel-container>.current-figure>.nav-left{left:5px}#carousel-container>.current-figure>.nav-right{right:5px}#carousel-container>.current-figure>#current-image,#carousel-container>.current-figure>#current-image-legacy{display:block;height:auto;width:100%}#carousel-container>.current-figure>#current-image-legacy>.description-ie11{bottom:0;padding-bottom:10px;padding-top:10px;position:absolute;width:100%}#carousel-container>.current-figure>figcaption{bottom:0;left:0;padding:10px;position:absolute;right:0}#carousel-container>.current-figure>figcaption .description{font-weight:700;text-align:center}#carousel-container>.current-figure>#dots,#carousel-container>.current-figure>#dots-ie11{bottom:20px;position:absolute;width:100%}", ".arrow-image,.empty-arrow-image,.left-arrow-image,.right-arrow-image{background-size:30px;height:30px;width:30px}.empty-arrow-image{background:#000;opacity:0}.left-arrow-image{background-image:url(\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDQ3Ny4xNzUgNDc3LjE3NSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDc3LjE3NSA0NzcuMTc1OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgd2lkdGg9IjUxMnB4IiBoZWlnaHQ9IjUxMnB4Ij48Zz48cGF0aCBkPSJNMTQ1LjE4OCwyMzguNTc1bDIxNS41LTIxNS41YzUuMy01LjMsNS4zLTEzLjgsMC0xOS4xcy0xMy44LTUuMy0xOS4xLDBsLTIyNS4xLDIyNS4xYy01LjMsNS4zLTUuMywxMy44LDAsMTkuMWwyMjUuMSwyMjUgICBjMi42LDIuNiw2LjEsNCw5LjUsNHM2LjktMS4zLDkuNS00YzUuMy01LjMsNS4zLTEzLjgsMC0xOS4xTDE0NS4xODgsMjM4LjU3NXoiIGZpbGw9IiNGRkZGRkYiLz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PC9zdmc+\");opacity:.8;transition:all .5s}.left-arrow-image:hover{transform:scale(1.2)}.right-arrow-image{background-image:url(\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDQ3Ny4xNzUgNDc3LjE3NSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDc3LjE3NSA0NzcuMTc1OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgd2lkdGg9IjUxMnB4IiBoZWlnaHQ9IjUxMnB4Ij48Zz48cGF0aCBkPSJNMzYwLjczMSwyMjkuMDc1bC0yMjUuMS0yMjUuMWMtNS4zLTUuMy0xMy44LTUuMy0xOS4xLDBzLTUuMywxMy44LDAsMTkuMWwyMTUuNSwyMTUuNWwtMjE1LjUsMjE1LjUgICBjLTUuMyw1LjMtNS4zLDEzLjgsMCwxOS4xYzIuNiwyLjYsNi4xLDQsOS41LDRjMy40LDAsNi45LTEuMyw5LjUtNGwyMjUuMS0yMjUuMUMzNjUuOTMxLDI0Mi44NzUsMzY1LjkzMSwyMzQuMjc1LDM2MC43MzEsMjI5LjA3NXogICAiIGZpbGw9IiNGRkZGRkYiLz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PC9zdmc+\");opacity:.8;transition:all .5s}.right-arrow-image:hover{transform:scale(1.2)}"]
|
|
742
|
-
},] }
|
|
743
|
-
];
|
|
744
|
-
CarouselComponent.ctorParameters = () => [
|
|
745
|
-
{ type: undefined, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] },
|
|
746
|
-
{ type: NgZone },
|
|
747
|
-
{ type: ModalGalleryService },
|
|
748
|
-
{ type: ConfigService },
|
|
749
|
-
{ type: ChangeDetectorRef },
|
|
750
|
-
{ type: DomSanitizer }
|
|
751
|
-
];
|
|
752
|
-
CarouselComponent.propDecorators = {
|
|
753
|
-
ariaLabel: [{ type: HostBinding, args: ['attr.aria-label',] }],
|
|
754
|
-
id: [{ type: Input }],
|
|
755
|
-
images: [{ type: Input }],
|
|
756
|
-
carouselConfig: [{ type: Input }],
|
|
757
|
-
playConfig: [{ type: Input }],
|
|
758
|
-
carouselImageConfig: [{ type: Input }],
|
|
759
|
-
previewConfig: [{ type: Input }],
|
|
760
|
-
dotsConfig: [{ type: Input }],
|
|
761
|
-
infinite: [{ type: Input }],
|
|
762
|
-
disableSsrWorkaround: [{ type: Input }],
|
|
763
|
-
accessibilityConfig: [{ type: Input }],
|
|
764
|
-
showImage: [{ type: Output }],
|
|
765
|
-
firstImage: [{ type: Output }],
|
|
766
|
-
lastImage: [{ type: Output }],
|
|
767
|
-
onMouseEnter: [{ type: HostListener, args: ['mouseenter',] }],
|
|
768
|
-
onMouseLeave: [{ type: HostListener, args: ['mouseleave',] }],
|
|
769
|
-
onKeyDownLeft: [{ type: HostListener, args: ['keydown.arrowLeft',] }],
|
|
770
|
-
onKeyDownLRight: [{ type: HostListener, args: ['keydown.arrowRight',] }]
|
|
771
|
-
};
|
|
772
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2Fyb3VzZWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Ii4uLy4uLy4uLy4uL3Byb2plY3RzL2tzODkvYW5ndWxhci1tb2RhbC1nYWxsZXJ5L3NyYy8iLCJzb3VyY2VzIjpbImxpYi9jb21wb25lbnRzL2Nhcm91c2VsL2Nhcm91c2VsLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNCRztBQUVILHlFQUF5RTtBQUN6RSw0SEFBNEg7QUFFNUgsT0FBTyxFQUVMLHVCQUF1QixFQUN2QixpQkFBaUIsRUFDakIsU0FBUyxFQUNULFlBQVksRUFDWixXQUFXLEVBQ1gsWUFBWSxFQUNaLE1BQU0sRUFDTixLQUFLLEVBQ0wsTUFBTSxFQUlOLE1BQU0sRUFDTixXQUFXLEVBR1osTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFcEQsT0FBTyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRW5FLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRzlELE9BQU8sRUFBUyxVQUFVLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDakQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ2xELE9BQU8sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDekQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFFeEUsT0FBTyxFQUFFLCtCQUErQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFJM0UsT0FBTyxFQUFFLFlBQVksRUFBYSxNQUFNLDJCQUEyQixDQUFDO0FBRXBFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUs3RTs7R0FFRztBQVFILE1BQU0sT0FBTyxpQkFBa0IsU0FBUSxtQkFBbUI7SUE4TnhEO0lBQ0Usa0NBQWtDO0lBQ0wsVUFBZSxFQUNwQyxNQUFjLEVBQ2QsbUJBQXdDLEVBQ3hDLGFBQTRCLEVBQzVCLEdBQXNCO0lBQzlCLCtHQUErRztJQUN2RyxTQUF1QjtRQUUvQixLQUFLLEVBQUUsQ0FBQztRQVJxQixlQUFVLEdBQVYsVUFBVSxDQUFLO1FBQ3BDLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDZCx3QkFBbUIsR0FBbkIsbUJBQW1CLENBQXFCO1FBQ3hDLGtCQUFhLEdBQWIsYUFBYSxDQUFlO1FBQzVCLFFBQUcsR0FBSCxHQUFHLENBQW1CO1FBRXRCLGNBQVMsR0FBVCxTQUFTLENBQWM7UUFyT2pDOztXQUVHO1FBRUgsY0FBUyxHQUFHLFVBQVUsQ0FBQztRQU92Qjs7O1dBR0c7UUFFSCxXQUFNLEdBQVksRUFBRSxDQUFDO1FBK0JyQjs7V0FFRztRQUVILGFBQVEsR0FBRyxJQUFJLENBQUM7UUFDaEI7O1dBRUc7UUFFSCx5QkFBb0IsR0FBRyxLQUFLLENBQUM7UUFRN0I7O1dBRUc7UUFFSCxjQUFTLEdBQTZCLElBQUksWUFBWSxFQUFjLENBQUM7UUFDckU7O1dBRUc7UUFFSCxlQUFVLEdBQTZCLElBQUksWUFBWSxFQUFjLENBQUM7UUFDdEU7O1dBRUc7UUFFSCxjQUFTLEdBQTZCLElBQUksWUFBWSxFQUFjLENBQUM7UUFzQnJFOztXQUVHO1FBQ0gsd0JBQW1CLEdBQXdCLCtCQUErQixDQUFDO1FBRTNFOzs7V0FHRztRQUNILGdCQUFXLEdBQVcsTUFBTSxDQUFDLEtBQUssQ0FBQztRQUNuQzs7O1dBR0c7UUFDSCxtQkFBYyxHQUFXLE1BQU0sQ0FBQyxRQUFRLENBQUM7UUFLekM7OztXQUdHO1FBQ0gsaUJBQVksR0FBRyxLQUFLLENBQUM7UUFDckI7OztXQUdHO1FBQ0gsZ0JBQVcsR0FBRyxLQUFLLENBQUM7UUFFcEI7O1dBRUc7UUFDSyxXQUFNLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztRQUNyQzs7V0FFRztRQUNLLFVBQUssR0FBRyxJQUFJLE9BQU8sRUFBUSxDQUFDO1FBRXBDOztXQUVHO1FBQ0ssaUJBQVksR0FBRztZQUNyQixJQUFJLEVBQUUsV0FBVztZQUNqQixLQUFLLEVBQUUsWUFBWTtZQUNuQixFQUFFLEVBQUUsU0FBUztZQUNiLElBQUksRUFBRSxXQUFXO1NBQ2xCLENBQUM7SUFxRkYsQ0FBQztJQW5GRDs7T0FFRztJQUVILFlBQVk7UUFDVixJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRTtZQUNaLE1BQU0sSUFBSSxLQUFLLENBQUMsNkNBQTZDLENBQUMsQ0FBQztTQUNoRTtRQUNELE1BQU0sU0FBUyxHQUEwQixJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDL0UsSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUNkLE1BQU0sSUFBSSxLQUFLLENBQUMsb0RBQW9ELENBQUMsQ0FBQztTQUN2RTtRQUNELElBQUksQ0FBQyxTQUFTLENBQUMsa0JBQWtCLElBQUksQ0FBQyxTQUFTLENBQUMsa0JBQWtCLENBQUMsWUFBWSxFQUFFO1lBQy9FLE9BQU87U0FDUjtRQUNELElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUN0QixDQUFDO0lBRUQ7O09BRUc7SUFFSCxZQUFZO1FBQ1YsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUU7WUFDWixNQUFNLElBQUksS0FBSyxDQUFDLDZDQUE2QyxDQUFDLENBQUM7U0FDaEU7UUFDRCxNQUFNLFNBQVMsR0FBMEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQy9FLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDZCxNQUFNLElBQUksS0FBSyxDQUFDLG9EQUFvRCxDQUFDLENBQUM7U0FDdkU7UUFDRCxJQUFJLENBQUMsU0FBUyxDQUFDLGtCQUFrQixJQUFJLENBQUMsU0FBUyxDQUFDLGtCQUFrQixDQUFDLFlBQVksSUFBSSxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLEVBQUU7WUFDekgsT0FBTztTQUNSO1FBQ0QsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFFRDs7T0FFRztJQUVILGFBQWE7UUFDWCxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRTtZQUNaLE1BQU0sSUFBSSxLQUFLLENBQUMsNkNBQTZDLENBQUMsQ0FBQztTQUNoRTtRQUNELE1BQU0sU0FBUyxHQUEwQixJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDL0UsSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUNkLE1BQU0sSUFBSSxLQUFLLENBQUMsb0RBQW9ELENBQUMsQ0FBQztTQUN2RTtRQUNELElBQUksQ0FBQyxTQUFTLENBQUMsY0FBYyxJQUFJLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxjQUFjLEVBQUU7WUFDekUsT0FBTztTQUNSO1FBQ0QsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQ25CLENBQUM7SUFFRDs7T0FFRztJQUVILGVBQWU7UUFDYixJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRTtZQUNaLE1BQU0sSUFBSSxLQUFLLENBQUMsNkNBQTZDLENBQUMsQ0FBQztTQUNoRTtRQUNELE1BQU0sU0FBUyxHQUEwQixJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDL0UsSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUNkLE1BQU0sSUFBSSxLQUFLLENBQUMsb0RBQW9ELENBQUMsQ0FBQztTQUN2RTtRQUNELElBQUksQ0FBQyxTQUFTLENBQUMsY0FBYyxJQUFJLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxjQUFjLEVBQUU7WUFDekUsT0FBTztTQUNSO1FBQ0QsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQ25CLENBQUM7SUFlRCxXQUFXLENBQUMsT0FBc0I7UUFDaEMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUU7WUFDWixNQUFNLElBQUksS0FBSyxDQUFDLDZDQUE2QyxDQUFDLENBQUM7U0FDaEU7UUFDRCxNQUFNLFNBQVMsR0FBMEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQy9FLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDZCxNQUFNLElBQUksS0FBSyxDQUFDLG9EQUFvRCxDQUFDLENBQUM7U0FDdkU7UUFFRCwrQkFBK0I7UUFDL0IsTUFBTSxnQkFBZ0IsR0FBaUIsT0FBTyxDQUFDLFVBQVUsQ0FBQztRQUMxRCxJQUFJLGdCQUFnQixJQUFJLGdCQUFnQixDQUFDLFlBQVksS0FBSyxnQkFBZ0IsQ0FBQyxhQUFhLEVBQUU7WUFDeEYsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRTtnQkFDcEMsa0JBQWtCLEVBQUUsZ0JBQWdCLENBQUMsWUFBWTthQUNsRCxDQUFDLENBQUM7WUFDSCxJQUFJLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQztTQUNoRDtRQUNELG1DQUFtQztRQUNuQyxNQUFNLG9CQUFvQixHQUFpQixPQUFPLENBQUMsY0FBYyxDQUFDO1FBQ2xFLElBQUksb0JBQW9CLElBQUksb0JBQW9CLENBQUMsWUFBWSxLQUFLLG9CQUFvQixDQUFDLGFBQWEsRUFBRTtZQUNwRyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFO2dCQUNwQyxjQUFjLEVBQUUsb0JBQW9CLENBQUMsWUFBWTthQUNsRCxDQUFDLENBQUM7WUFDSCxJQUFJLENBQUMsY0FBYyxHQUFHLG9CQUFvQixDQUFDLFlBQVksQ0FBQztTQUN6RDtRQUNELDBFQUEwRTtRQUMxRSxNQUFNLGdCQUFnQixHQUFpQixPQUFPLENBQUMsVUFBVSxDQUFDO1FBQzFELElBQUksZ0JBQWdCLEVBQUU7WUFDcEIsTUFBTSxvQkFBb0IsR0FBZSxnQkFBZ0IsQ0FBQyxhQUFhLENBQUM7WUFDeEUsTUFBTSxvQkFBb0IsR0FBZSxnQkFBZ0IsQ0FBQyxZQUFZLENBQUM7WUFDdkUsSUFBSSxvQkFBb0IsS0FBSyxvQkFBb0IsRUFBRTtnQkFDakQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRTtvQkFDcEMsa0JBQWtCLEVBQUUsZ0JBQWdCLENBQUMsWUFBWTtpQkFDbEQsQ0FBQyxDQUFDO2dCQUNILG1EQUFtRDtnQkFDbkQsOENBQThDO2dCQUM5Qyw2REFBNkQ7Z0JBQzdELElBQUksb0JBQW9CLENBQUMsUUFBUSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsYUFBYSxFQUFFLEVBQUU7b0JBQ3RFLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7aUJBQ3BCO3FCQUFNO29CQUNMLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztpQkFDckI7YUFDRjtTQUNGO0lBQ0gsQ0FBQztJQUVELFFBQVE7UUFDTixJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRTtZQUNaLE1BQU0sSUFBSSxLQUFLLENBQUMsNkNBQTZDLENBQUMsQ0FBQztTQUNoRTtRQUNELElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFO1lBQ2hCLE1BQU0sSUFBSSxLQUFLLENBQUMsaURBQWlELENBQUMsQ0FBQztTQUNwRTtRQUNELE1BQU0sU0FBUyxHQUEwQixJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDL0UsSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUNkLE1BQU0sSUFBSSxLQUFLLENBQUMsb0RBQW9ELENBQUMsQ0FBQztTQUN2RTtRQUNELElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUVuQyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFO1lBQ3BDLGNBQWMsRUFBRSxJQUFJLENBQUMsY0FBYztZQUNuQyxtQkFBbUIsRUFBRSxJQUFJLENBQUMsbUJBQW1CO1lBQzdDLGtCQUFrQixFQUFFLElBQUksQ0FBQyxVQUFVO1lBQ25DLHNCQUFzQixFQUFFLElBQUksQ0FBQyxhQUFhO1lBQzFDLGtCQUFrQixFQUFFLElBQUksQ0FBQyxVQUFVO1lBQ25DLG1CQUFtQixFQUFFLElBQUksQ0FBQyxtQkFBbUI7WUFDN0MsdUZBQXVGO1lBQ3ZGLHFCQUFxQixFQUFFO2dCQUNyQixTQUFTLEVBQUUsQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDO2dCQUMvQixvQkFBb0IsRUFBRSxJQUFJLENBQUMsb0JBQW9CO2FBQ2hEO1NBQ0YsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLGNBQWMsR0FBRyxTQUFTLENBQUMsY0FBYyxDQUFDO1FBQy9DLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxTQUFTLENBQUMsbUJBQW1CLENBQUM7UUFDekQsSUFBSSxDQUFDLFVBQVUsR0FBRyxTQUFTLENBQUMsa0JBQWtCLENBQUM7UUFDL0MsSUFBSSxDQUFDLGFBQWEsR0FBRyxTQUFTLENBQUMsc0JBQXNCLENBQUM7UUFDdEQsSUFBSSxDQUFDLFVBQVUsR0FBRyxTQUFTLENBQUMsa0JBQWtCLENBQUM7UUFDL0MsSUFBSSxDQUFDLG1CQUFtQixHQUFHLFNBQVMsQ0FBQyxtQkFBMEMsQ0FBQztRQUNoRixJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQsa0JBQWtCO1FBQ2hCLHNEQUFzRDtRQUN0RCx5REFBeUQ7UUFDekQsSUFBSSxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUU7WUFDdEMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUU7Z0JBQ1osTUFBTSxJQUFJLEtBQUssQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDO2FBQ2hFO1lBQ0QsTUFBTSxTQUFTLEdBQTBCLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUMvRSxJQUFJLENBQUMsU0FBUyxJQUFJLENBQUMsU0FBUyxDQUFDLGtCQUFrQixFQUFFO2dCQUMvQyxNQUFNLElBQUksS0FBSyxDQUFDLDJFQUEyRSxDQUFDLENBQUM7YUFDOUY7WUFDRCxJQUFJLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsRUFBRTtnQkFDakMsSUFBSSxDQUFDLE1BQU07cUJBQ1IsSUFBSSxDQUNILEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLElBQUksU0FBUyxDQUFDLGtCQUFrQixJQUFJLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLENBQUM7Z0JBQzdGLGtDQUFrQztnQkFDbEMsTUFBTSxDQUFDLENBQUMsUUFBYSxFQUFFLEVBQUUsQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDLEVBQ3ZDLFNBQVMsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQ25FO3FCQUNBLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FDZCxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUU7b0JBQ25CLElBQUksSUFBSSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRTt3QkFDL0MsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO3FCQUNsQjtvQkFDRCxJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUMxQixDQUFDLENBQUMsQ0FDSCxDQUFDO2dCQUVKLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDckIsQ0FBQyxDQUFDLENBQUM7U0FDSjtJQUNILENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSCxrQkFBa0IsQ0FBQyxXQUFtQixFQUFFLG1CQUEyQjtRQUNqRSwwSEFBMEg7UUFDMUgsSUFBSSxFQUFFLEdBQVcsTUFBTSxHQUFHLFdBQVcsR0FBRyxHQUFHLENBQUM7UUFDNUMsSUFBSSxDQUFDLENBQUMsbUJBQW1CLEVBQUU7WUFDekIsc0dBQXNHO1lBQ3RHLEVBQUUsSUFBSSxJQUFJLEdBQUcsTUFBTSxHQUFHLG1CQUFtQixHQUFHLEdBQUcsQ0FBQztTQUNqRDtRQUNELE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyx3QkFBd0IsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNyRCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsVUFBVSxDQUFDLEtBQWE7UUFDdEIsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzdELENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILGlCQUFpQixDQUFDLFNBQWlCLEVBQUUsS0FBb0IsRUFBRSxTQUFpQixNQUFNLENBQUMsTUFBTTtRQUN2RixNQUFNLE1BQU0sR0FBVyxLQUFLLENBQUMscUJBQXFCLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3JFLElBQUksTUFBTSxLQUFLLElBQUksRUFBRTtZQUNuQixJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1NBQ3hCO2FBQU0sSUFBSSxNQUFNLEtBQUssSUFBSSxFQUFFO1lBQzFCLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7U0FDeEI7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsbUJBQW1CO1FBQ2pCLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFO1lBQ1osTUFBTSxJQUFJLEtBQUssQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDO1NBQ2hFO1FBQ0QsTUFBTSxTQUFTLEdBQTBCLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMvRSxJQUFJLENBQUMsU0FBUyxJQUFJLENBQUMsU0FBUyxDQUFDLGNBQWMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUU7WUFDakUsTUFBTSxJQUFJLEtBQUssQ0FBQyxxRkFBcUYsQ0FBQyxDQUFDO1NBQ3hHO1FBQ0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsa0JBQWtCLEVBQUU7WUFDaEQsT0FBTztTQUNSO1FBQ0QsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3ZELElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUM7WUFDNUIsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFO1lBQ1gsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO1lBQ25CLFlBQVksRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQztZQUNoQyxTQUFTLEVBQUU7Z0JBQ1QsdUZBQXVGO2dCQUN2RixxQkFBcUIsRUFBRTtvQkFDckIsU0FBUyxFQUFFLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQztvQkFDL0Isb0JBQW9CLEVBQUUsSUFBSSxDQUFDLG9CQUFvQjtpQkFDdkI7YUFDZDtTQUNPLENBQUMsQ0FBQztJQUMzQixDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILHVCQUF1QixDQUFDLFFBQTJCLElBQUksQ0FBQyxZQUFZO1FBQ2xFLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFO1lBQ1osTUFBTSxJQUFJLEtBQUssQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDO1NBQ2hFO1FBQ0QsTUFBTSxTQUFTLEdBQTBCLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMvRSxJQUFJLENBQUMsU0FBUyxFQUFFO1lBQ2QsTUFBTSxJQUFJLEtBQUssQ0FBQyxvREFBb0QsQ0FBQyxDQUFDO1NBQ3ZFO1FBQ0QsTUFBTSwwQkFBMEIsR0FBb0MsU0FBUyxDQUFDLG1CQUFtQixDQUFDO1FBQ2xHLElBQUksQ0FBQywwQkFBMEIsSUFBSSxDQUFDLDBCQUEwQixDQUFDLFdBQVcsRUFBRTtZQUMxRSxNQUFNLElBQUksS0FBSyxDQUFDLGlGQUFpRixDQUFDLENBQUM7U0FDcEc7UUFDRCxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ1YsTUFBTSxJQUFJLEtBQUssQ0FBQyxnREFBZ0QsQ0FBQyxDQUFDO1NBQ25FO1FBQ0QsTUFBTSx1QkFBdUIsR0FBWSxDQUFDLEtBQUssSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsSUFBSSxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsS0FBSyxFQUFFLENBQUM7UUFFOUgsUUFBUSwwQkFBMEIsQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFFO1lBQ3ZELEtBQUssbUJBQW1CLENBQUMsYUFBYTtnQkFDcEMsT0FBTyx1QkFBdUIsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsR0FBRyxFQUFFLENBQUM7WUFDckUsS0FBSyxtQkFBbUIsQ0FBQyxhQUFhO2dCQUNwQyxPQUFPLEVBQUUsQ0FBQztZQUNaO2dCQUNFLG1FQUFtRTtnQkFDbkUsT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUMsS0FBSyxFQUFFLHVCQUF1QixDQUFDLENBQUM7U0FDcEU7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUs7UUFDcEMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUU7WUFDWixNQUFNLElBQUksS0FBSyxDQUFDLDZDQUE2QyxDQUFDLENBQUM7U0FDaEU7UUFDRCxNQUFNLFNBQVMsR0FBMEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQy9FLElBQUksQ0FBQyxTQUFTLElBQUksQ0FBQyxTQUFTLENBQUMsbUJBQW1CLEVBQUU7WUFDaEQsTUFBTSxJQUFJLEtBQUssQ0FBQyw0RUFBNEUsQ0FBQyxDQUFDO1NBQy9GO1FBQ0QsTUFBTSwwQkFBMEIsR0FBd0IsU0FBUyxDQUFDLG1CQUFtQixDQUFDO1FBQ3RGLFFBQVEsTUFBTSxFQUFFO1lBQ2QsS0FBSyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUs7Z0JBQzFCLElBQUksMEJBQTBCLENBQUMsV0FBVyxFQUFFO29CQUMxQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztpQkFDOUI7cUJBQU07b0JBQ0wsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7aUJBQzlCO2dCQUNELE1BQU07WUFDUixLQUFLLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSTtnQkFDekIsSUFBSSwwQkFBMEIsQ0FBQyxXQUFXLEVBQUU7b0JBQzFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO2lCQUM5QjtxQkFBTTtvQkFDTCxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztpQkFDOUI7Z0JBQ0QsTUFBTTtZQUNSLDZCQUE2QjtZQUM3QixXQUFXO1lBQ1gsK0JBQStCO1lBQy9CLFdBQVc7U0FDWjtJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsU0FBUyxDQUFDLFNBQWlCLE1BQU0sQ0FBQyxNQUFNO1FBQ3RDLHVDQUF1QztRQUN2QyxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUM1QixPQUFPO1NBQ1I7UUFDRCxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBRXJELElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBRXpCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDckIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxTQUFTLENBQUMsU0FBaUIsTUFBTSxDQUFDLE1BQU07UUFDdEMsdUNBQXVDO1FBQ3ZDLElBQUksSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxFQUFFO1lBQ2pELE9BQU87U0FDUjtRQUNELElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFckQsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFFekIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNyQixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxTQUFTLENBQUMsS0FBYSxFQUFFLElBQVc7UUFDbEMsT0FBTyxJQUFJLENBQUMsRUFBRSxDQUFDO0lBQ2pCLENBQUM7SUFFRDs7O09BR0c7SUFDSCxjQUFjLENBQUMsS0FBaUI7UUFDOUIsTUFBTSxVQUFVLEdBQVUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBZ0IsQ0FBQyxDQUFDO1FBQzlELElBQUksQ0FBQyxDQUFDLFVBQVUsRUFBRTtZQUNoQixJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsa0JBQWtCLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztTQUNuRDtJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILFlBQVk7UUFDVixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ3JCLENBQUM7SUFFRDs7T0FFRztJQUNILFlBQVk7UUFDVixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ3BCLENBQUM7SUFFRCxzQ0FBc0M7SUFDdEM7Ozs7O09BS0c7SUFDSCx3QkFBd0IsQ0FBQyxRQUEyQixJQUFJLENBQUMsWUFBWTtRQUNuRSxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ1YsT0FBTyxFQUFFLENBQUM7U0FDWDtRQUNELE9BQU8sS0FBSyxDQUFDLEtBQUssSUFBSSxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLFNBQVMsUUFBUSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7SUFDeEgsQ0FBQztJQUVELHNDQUFzQztJQUN0Qzs7Ozs7OztPQU9HO0lBQ0gsaUJBQWlCLENBQUMsUUFBMkIsSUFBSSxDQUFDLFlBQVk7UUFDNUQsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUU7WUFDWixNQUFNLElBQUksS0FBSyxDQUFDLDZDQUE2QyxDQUFDLENBQUM7U0FDaEU7UUFDRCxNQUFNLFNBQVMsR0FBMEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQy9FLElBQUksQ0FBQyxTQUFTLElBQUksQ0FBQyxTQUFTLENBQUMsbUJBQW1CLEVBQUU7WUFDaEQsTUFBTSxJQUFJLEtBQUssQ0FBQyw0RUFBNEUsQ0FBQyxDQUFDO1NBQy9GO1FBQ0QsTUFBTSwwQkFBMEIsR0FBd0IsU0FBUyxDQUFDLG1CQUFtQixDQUFDO1FBQ3RGLElBQUksQ0FBQywwQkFBMEIsSUFBSSxDQUFDLDBCQUEwQixDQUFDLFdBQVcsRUFBRTtZQUMxRSxNQUFNLElBQUksS0FBSyxDQUFDLGlGQUFpRixDQUFDLENBQUM7U0FDcEc7UUFDRCxNQUFNLHVCQUF1QixHQUFZLENBQUMsS0FBSyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsV0FBVyxJQUFJLEtBQUssQ0FBQyxLQUFLLENBQUMsV0FBVyxLQUFLLEVBQUUsQ0FBQztRQUM5SCxNQUFNLFdBQVcsR0FBVyxJQUFJLENBQUMsb0JBQW9CLENBQUMsS0FBSyxFQUFFLHVCQUF1QixDQUFDLENBQUM7UUFDdEYsT0FBTyxXQUFXLENBQUM7SUFDckIsQ0FBQztJQUVEOztPQUVHO0lBQ0gseUNBQXlDO0lBQ3pDLFlBQVk7SUFDWix1REFBdUQ7SUFDdkQsMkJBQTJCO0lBQzNCLE1BQU07SUFDTix3Q0FBd0M7SUFDeEMsOEJBQThCO0lBQzlCLHVEQUF1RDtJQUN2RCwyQkFBMkI7SUFDM0IsTUFBTTtJQUNOLDZCQUE2QjtJQUM3QixJQUFJO0lBRUo7OztPQUdHO0lBQ0gsV0FBVztRQUNULElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUN0QixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLGtCQUFrQixDQUFDLEtBQVksRUFBRSxNQUFjO1FBQ3JELElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFO1lBQ1osTUFBTSxJQUFJLEtBQUssQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDO1NBQ2hFO1FBQ0QsSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDMUIsTUFBTSxLQUFLLEdBQVcsUUFBUSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFbkQsZ0RBQWdEO1FBQ2hELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFdEMsbUNBQW1DO1FBQ25DLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xFLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssWUFBWTtRQUNsQixJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRTtZQUN0QixNQUFNLElBQUksS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUM7U0FDMUU7UUFDRCxNQUFNLFlBQVksR0FBVyxRQUFRLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdEUsSUFBSSxRQUFRLEdBQUcsQ0FBQyxDQUFDO1FBQ2pCLElBQUksWUFBWSxJQUFJLENBQUMsSUFBSSxZQUFZLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1lBQzlELFFBQVEsR0FBRyxZQUFZLEdBQUcsQ0FBQyxDQUFDO1NBQzdCO2FBQU07WUFDTCxRQUFRLEdBQUcsQ0FBQyxDQUFDLENBQUMsNkJBQTZCO1NBQzVDO1FBQ0QsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQy9CLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssWUFBWTtRQUNsQixJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRTtZQUN0QixNQUFNLElBQUksS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUM7U0FDMUU7UUFDRCxNQUFNLFlBQVksR0FBVyxRQUFRLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdEUsSUFBSSxRQUFRLEdBQUcsQ0FBQyxDQUFDO1FBQ2pCLElBQUksWUFBWSxHQUFHLENBQUMsSUFBSSxZQUFZLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1lBQzlELFFBQVEsR0FBRyxZQUFZLEdBQUcsQ0FBQyxDQUFDO1NBQzdCO2FBQU07WUFDTCxRQUFRLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsNEJBQTRCO1NBQ2hFO1FBQ0QsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQy9CLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSyxvQkFBb0IsQ0FBQyxLQUF3QixFQUFFLHVCQUFnQztRQUNyRixJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRTtZQUNaLE1BQU0sSUFBSSxLQUFLLENBQUMsNkNBQTZDLENBQUMsQ0FBQztTQUNoRTtRQUNELE1BQU0sU0FBUyxHQUEwQixJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDL0UsSUFBSSxDQUFDLFNBQVMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsRUFBRTtZQUNoRCxNQUFNLElBQUksS0FBSyxDQUFDLDRFQUE0RSxDQUFDLENBQUM7U0FDL0Y7UUFDRCxNQUFNLDBCQUEwQixHQUFvQyxTQUFTLENBQUMsbUJBQW1CLENBQUM7UUFDbEcsSUFBSSxDQUFDLDBCQUEwQixJQUFJLENBQUMsMEJBQTBCLENBQUMsV0FBVyxFQUFFO1lBQzFFLE1BQU0sSUFBSSxLQUFLLENBQUMsaUZBQWlGLENBQUMsQ0FBQztTQUNwRztRQUNELElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDVixNQUFNLElBQUksS0FBSyxDQUFDLGdEQUFnRCxDQUFDLENBQUM7U0FDbkU7UUFFRCw0RUFBNEU7UUFDNUUsSUFBSSwwQkFBMEIsQ0FBQyxXQUFXLENBQUMscUJBQXFCLElBQUksMEJBQTBCLENBQUMsV0FBVyxDQUFDLHFCQUFxQixLQUFLLEVBQUUsRUFBRTtZQUN2SSxPQUFPLDBCQUEwQixDQUFDLFdBQVcsQ0FBQyxxQkFBcUIsQ0FBQztTQUNyRTtRQUVELE1BQU0sWUFBWSxHQUFXLFFBQVEsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzFELDZDQUE2QztRQUM3Qyx5RUFBeUU7UUFFekUsTUFBTSxlQUFlLEdBQVcsMEJBQTBCLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsMEJBQTBCLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3pJLE1BQU0sWUFBWSxHQUFXLDBCQUEwQixDQUFDLFdBQVcsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLDBCQUEwQixDQUFDLFdBQVcsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUNsSixNQUFNLGlCQUFpQixHQUFXLFlBQVksR0FBRyxDQUFDLEdBQUcsWUFBWSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO1FBRXZGLElBQUksdUJBQXVCLEVBQUU7WUFDM0IsT0FBTyxlQUFlLEdBQUcsaUJBQWlCLENBQUM7U0FDNUM7UUFFRCxNQUFNLGtCQUFrQixHQUFXLEtBQUssQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDekcsTUFBTSxjQUFjLEdBQVcsMEJBQTBCLENBQUMsV0FBVyxDQUFDLHFCQUFxQixHQUFHLGtCQUFrQixDQUFDO1FBQ2pILE9BQU8sZUFBZSxHQUFHLGlCQUFpQixHQUFHLGNBQWMsQ0FBQztJQUM5RCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLGdCQUFnQixDQUFDLFlBQW9CO1FBQzNDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1lBQzVCLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDO1lBQ3pCLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDO1lBQ3hCLE9BQU87U0FDUjtRQUNELFFBQVEsWUFBWSxFQUFFO1lBQ3BCLEtBQUssQ0FBQztnQkFDSixvREFBb0Q7Z0JBQ3BELElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDO2dCQUN6QixJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQztnQkFDekIsTUFBTTtZQUNSLEtBQUssSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQztnQkFDekIsb0RBQW9EO2dCQUNwRCxJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQztnQkFDMUIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUM7Z0JBQ3hCLE1BQU07WUFDUjtnQkFDRSxJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQztnQkFDMUIsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUM7Z0JBQ3pCLE1BQU07U0FDVDtJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssaUJBQWlCO1FBQ3ZCLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQ3RCLE1BQU0sSUFBSSxLQUFLLENBQUMsdURBQXVELENBQUMsQ0FBQztTQUMxRTtRQUNELElBQUksS0FBYSxDQUFDO1FBQ2xCLElBQUk7WUFDRixLQUFLLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1NBQ2xEO1FBQUMsT0FBTyxHQUFHLEVBQUU7WUFDWixPQUFPLENBQUMsS0FBSyxDQUFDLHFEQUFxRCxDQUFDLENBQUM7WUFDckUsTUFBTSxHQUFHLENBQUM7U0FDWDtRQUVELElBQUksSUFBSSxDQUFDLFFBQVEsS0FBSyxJQUFJLEVBQUU7WUFDMUIsMEJBQTBCO1lBQzFCLElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFDO1lBQzFCLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO1NBQzFCO2FBQU07WUFDTCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDOUI7SUFDSCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSyxpQkFBaUIsQ0FBQyxNQUFjLEVBQUUsWUFBb0I7UUFDNUQsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUU7WUFDWixPQUFPO1NBQ1I7UUFDRCwyQkFBMkI7UUFDM0IsUUFBUSxZQUFZLEVBQUU7WUFDcEIsS0FBSyxDQUFDO2dCQUNKLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBQzVELE1BQU07WUFDUixLQUFLLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUM7Z0JBQ3pCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBQzNELE1BQU07U0FDVDtJQUNILENBQUM7SUFFRDs7Ozs7Ozs7T0FRRztJQUNLLGdCQUFnQixDQUFDLGFBQXFCO1FBQzVDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQ3RCLE1BQU0sSUFBSSxLQUFLLENBQUMsdURBQXVELENBQUMsQ0FBQztTQUMxRTtRQUNELE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxhQUFhLENBQUM7SUFDdEYsQ0FBQzs7O1lBdnpCRixTQUFTLFNBQUM7Z0JBQ1QsUUFBUSxFQUFFLGFBQWE7Z0JBRXZCLHNxTkFBNEI7Z0JBQzVCLGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO2dCQUMvQyxTQUFTLEVBQUUsQ0FBQyxhQUFhLENBQUM7O2FBQzNCOzs7NENBaU9JLE1BQU0sU0FBQyxXQUFXO1lBN1FyQixNQUFNO1lBOEJDLG1CQUFtQjtZQURuQixhQUFhO1lBcENwQixpQkFBaUI7WUFrQ1YsWUFBWTs7O3dCQXNCbEIsV0FBVyxTQUFDLGlCQUFpQjtpQkFNN0IsS0FBSztxQkFNTCxLQUFLOzZCQU1MLEtBQUs7eUJBTUwsS0FBSztrQ0FNTCxLQUFLOzRCQU1MLEtBQUs7eUJBTUwsS0FBSzt1QkFLTCxLQUFLO21DQUtMLEtBQUs7a0NBTUwsS0FBSzt3QkFNTCxNQUFNO3lCQUtOLE1BQU07d0JBS04sTUFBTTsyQkEyRU4sWUFBWSxTQUFDLFlBQVk7MkJBa0J6QixZQUFZLFNBQUMsWUFBWTs0QkFrQnpCLFlBQVksU0FBQyxtQkFBbUI7OEJBa0JoQyxZQUFZLFNBQUMsb0JBQW9CIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiBUaGUgTUlUIExpY2Vuc2UgKE1JVClcblxuIENvcHlyaWdodCAoYykgMjAxNy0yMDIwIFN0ZWZhbm8gQ2FwcGEgKEtzODkpXG5cbiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcblxuIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbFxuIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG5cbiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTiBJTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFXG4gU09GVFdBUkUuXG4gKi9cblxuLy8gVGhlIGlkZWEgdG8gY3JlYXRlIGEgY2Fyb3VzZWwgd2l0aCB0d28gU3ViamVjdHMgY2FtZSBmcm9tIG5nLWJvb3RzdHJhcFxuLy8gU28gYSBiaWcgdGhhbmsgeW91IHRvIHRoZSBuZy1ib290c3RyYXAgdGVhbSBmb3IgdGhlIGludGVyZXN0aW5nIGltcGxlbWVudGF0aW9uIHRoYXQgSSB1c2VkIGhlcmUgd2l0aCBzb21lIGN1c3RvbWl6YXRpb25zLlxuXG5pbXBvcnQge1xuICBBZnRlckNvbnRlbnRJbml0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBIb3N0QmluZGluZyxcbiAgSG9zdExpc3RlbmVyLFxuICBJbmplY3QsXG4gIElucHV0LFxuICBOZ1pvbmUsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgUExBVEZPUk1fSUQsXG4gIFNpbXBsZUNoYW5nZSxcbiAgU2ltcGxlQ2hhbmdlc1xufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGlzUGxhdGZvcm1Ccm93c2VyIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcblxuaW1wb3J0IHsgU3ViamVjdCwgdGltZXIgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGZpbHRlciwgbWFwLCBzd2l0Y2hNYXAsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgQWNjZXNzaWJsZUNvbXBvbmVudCB9IGZyb20gJy4uL2FjY2Vzc2libGUuY29tcG9uZW50JztcblxuaW1wb3J0IHsgQWNjZXNzaWJpbGl0eUNvbmZpZyB9IGZyb20gJy4uLy4uL21vZGVsL2FjY2Vzc2liaWxpdHkuaW50ZXJmYWNlJztcbmltcG9ydCB7IEltYWdlLCBJbWFnZUV2ZW50IH0gZnJvbSAnLi4vLi4vbW9kZWwvaW1hZ2UuY2xhc3MnO1xuaW1wb3J0IHsgQWN0aW9uIH0gZnJvbSAnLi4vLi4vbW9kZWwvYWN0aW9uLmVudW0nO1xuaW1wb3J0IHsgZ2V0SW5kZXggfSBmcm9tICcuLi8uLi91dGlscy9pbWFnZS51dGlsJztcbmltcG9ydCB7IE5FWFQsIFBSRVYgfSBmcm9tICcuLi8uLi91dGlscy91c2VyLWlucHV0LnV0aWwnO1xuaW1wb3J0IHsgRGVzY3JpcHRpb25TdHJhdGVneSB9IGZyb20gJy4uLy4uL21vZGVsL2Rlc2NyaXB0aW9uLmludGVyZmFjZSc7XG5pbXBvcnQgeyBEb3RzQ29uZmlnIH0gZnJvbSAnLi4vLi4vbW9kZWwvZG90cy1jb25maWcuaW50ZXJmYWNlJztcbmltcG9ydCB7IEtTX0RFRkFVTFRfQUNDRVNTSUJJTElUWV9DT05GSUcgfSBmcm9tICcuLi9hY2Nlc3NpYmlsaXR5LWRlZmF1bHQnO1xuaW1wb3J0IHsgUGxheUNvbmZpZyB9IGZyb20gJy4uLy4uL21vZGVsL3BsYXktY29uZmlnLmludGVyZmFjZSc7XG5pbXBvcnQgeyBDYXJvdXNlbENvbmZpZyB9IGZyb20gJy4uLy4uL21vZGVsL2Nhcm91c2VsLWNvbmZpZy5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgQ2Fyb3VzZWxJbWFnZUNvbmZpZyB9IGZyb20gJy4uLy4uL21vZGVsL2Nhcm91c2VsLWltYWdlLWNvbmZpZy5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgRG9tU2FuaXRpemVyLCBTYWZlU3R5bGUgfSBmcm9tICdAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyJztcbmltcG9ydCB7IENhcm91c2VsUHJldmlld0NvbmZpZyB9IGZyb20gJy4uLy4uL21vZGVsL2Nhcm91c2VsLXByZXZpZXctY29uZmlnLmludGVyZmFjZSc7XG5pbXBvcnQgeyBDb25maWdTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvY29uZmlnLnNlcnZpY2UnO1xuaW1wb3J0IHsgTW9kYWxHYWxsZXJ5U2VydmljZSB9IGZyb20gJy4uL21vZGFsLWdhbGxlcnkvbW9kYWwtZ2FsbGVyeS5zZXJ2aWNlJztcbmltcG9ydCB7IExpYkNvbmZpZyB9IGZyb20gJy4uLy4uL21vZGVsL2xpYi1jb25maWcuaW50ZXJmYWNlJztcbmltcG9ydCB7IE1vZGFsR2FsbGVyeUNvbmZpZyB9IGZyb20gJy4uLy4uL21vZGVsL21vZGFsLWdhbGxlcnktY29uZmlnLmludGVyZmFjZSc7XG5pbXBvcnQgeyBLZXlib2FyZFNlcnZpY2VDb25maWcgfSBmcm9tICcuLi8uLi9tb2RlbC9rZXlib2FyZC1zZXJ2aWNlLWNvbmZpZy5pbnRlcmZhY2UnO1xuXG4vKipcbiAqIENvbXBvbmVudCB3aXRoIGNvbmZpZ3VyYWJsZSBpbmxpbmUvcGxhaW4gY2Fyb3VzZWwuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2tzLWNhcm91c2VsJyxcbiAgc3R5bGVVcmxzOiBbJ2Nhcm91c2VsLnNjc3MnLCAnLi4vaW1hZ2UtYXJyb3dzLnNjc3MnXSxcbiAgdGVtcGxhdGVVcmw6ICdjYXJvdXNlbC5odG1sJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHByb3ZpZGVyczogW0NvbmZpZ1NlcnZpY2VdXG59KVxuZXhwb3J0IGNsYXNzIENhcm91c2VsQ29tcG9uZW50IGV4dGVuZHMgQWNjZXNzaWJsZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJDb250ZW50SW5pdCwgT25EZXN0cm95LCBPbkNoYW5nZXMge1xuICAvKipcbiAgICogQXR0cmlidXRlIHRvIHNldCBhcmlhTGFiZWwgb2YgdGhlIGhvc3QgY29tcG9uZW50XG4gICAqL1xuICBASG9zdEJpbmRpbmcoJ2F0dHIuYXJpYS1sYWJlbCcpXG4gIGFyaWFMYWJlbCA9IGBDYXJvdXNlbGA7XG4gIC8qKlxuICAgKiBVbmlxdWUgaWQgKD49MCkgb2YgdGhlIGN1cnJlbnQgaW5zdGFuY2Ugb2YgdGhlIGNhcm91c2VsLiBUaGlzIGlzIHVzZWZ1bCB3aGVuIHlvdSBhcmUgdXNpbmdcbiAgICogdGhlIGNhcm91c2VsJ3MgZmVhdHVyZSB0byBvcGVuIG1vZGFsIGdhbGxlcnkuXG4gICAqL1xuICBASW5wdXQoKVxuICBpZDogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICAvKipcbiAgICogQXJyYXkgb2YgYEludGVybmFsTGliSW1hZ2VgIHRoYXQgcmVwcmVzZW50IHRoZSBtb2RlbCBvZiB0aGlzIGxpYnJhcnkgd2l0aCBhbGwgaW1hZ2VzLFxuICAgKiB0aHVtYnMgYW5kIHNvIG9uLlxuICAgKi9cbiAgQElucHV0KClcbiAgaW1hZ2VzOiBJbWFnZVtdID0gW107XG4gIC8qKlxuICAgKiBPYmplY3Qgb2YgdHlwZSBgQ2Fyb3VzZWxDb25maWdgIHRvIGluaXQgQ2Fyb3VzZWxDb21wb25lbnQncyBmZWF0dXJlcy5cbiAgICogRm9yIGluc3RhbmNlLCBpdCBjb250YWlucyBwYXJhbWV0ZXJzIHRvIGNoYW5nZSB0aGUgc3R5bGUsIGhvdyBpdCBuYXZpZ2F0ZXMgYW5kIHNvIG9uLlxuICAgKi9cbiAgQElucHV0KClcbiAgY2Fyb3VzZWxDb25maWc6IENhcm91c2VsQ29uZmlnIHwgdW5kZWZpbmVkO1xuICAvKipcbiAgICogT2JqZWN0IG9mIHR5cGUgYFBsYXlDb25maWdgIHRvIGluaXQgQ2Fyb3VzZWxDb21wb25lbnQncyBmZWF0dXJlcyBhYm91dCBhdXRvLXBsYXkuXG4gICAqIEZvciBpbnN0YW5jZSwgaXQgY29udGFpbnMgcGFyYW1ldGVycyB0byBlbmFibGUvZGlzYWJsZSBhdXRvUGxheSwgaW50ZXJ2YWwgYW5kIHNvIG9uLlxuICAgKi9cbiAgQElucHV0KClcbiAgcGxheUNvbmZpZzogUGxheUNvbmZpZyB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIEludGVyZmFjZSB0byBjb25maWd1cmUgY3VycmVudCBpbWFnZSBpbiBjYXJvdXNlbC5cbiAgICogRm9yIGluc3RhbmNlIHlvdSBjYW4gY2hhbmdlIHRoZSBkZXNjcmlwdGlvbi5cbiAgICovXG4gIEBJbnB1dCgpXG4gIGNhcm91c2VsSW1hZ2VDb25maWc6IENhcm91c2VsSW1hZ2VDb25maWcgfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBPYmplY3Qgb2YgdHlwZSBgQ2Fyb3VzZWxQcmV2aWV3Q29uZmlnYCB0byBpbml0IFByZXZpZXdzQ29tcG9uZW50J3MgZmVhdHVyZXMuXG4gICAqIEZvciBpbnN0YW5jZSwgaXQgY29udGFpbnMgYSBwYXJhbSB0byBzaG93L2hpZGUgcHJldmlld3MsIGNoYW5nZSBzaXplcyBhbmQgc28gb24uXG4gICAqL1xuICBASW5wdXQoKVxuICBwcmV2aWV3Q29uZmlnOiBDYXJvdXNlbFByZXZpZXdDb25maWcgfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBPYmplY3Qgb2YgdHlwZSBgRG90c0NvbmZpZ2AgdG8gaW5pdCBEb3RzQ29tcG9uZW50J3MgZmVhdHVyZXMuXG4gICAqIEZvciBpbnN0YW5jZSwgaXQgY29udGFpbnMgYSBwYXJhbSB0byBzaG93L2hpZGUgdGhpcyBjb21wb25lbnQuXG4gICAqL1xuICBASW5wdXQoKVxuICBkb3RzQ29uZmlnOiBEb3RzQ29uZmlnIHwgdW5kZWZpbmVkO1xuICAvKipcbiAgICogYm9vbGVhbiB0byBlbmFibGUvZGlzYWJsZSBpbmZpbml0ZSBzbGlkaW5nLiBFbmFibGVkIGJ5IGRlZmF1bHQuXG4gICAqL1xuICBASW5wdXQoKVxuICBpbmZpbml0ZSA9IHRydWU7XG4gIC8qKlxuICAgKiBUT0RPIGFkZCBkZXNjcmlwdGlvblxuICAgKi9cbiAgQElucHV0KClcbiAgZGlzYWJsZVNzcldvcmthcm91bmQgPSBmYWxzZTtcbiAgLyoqXG4gICAqIE9iamVjdCBvZiB0eXBlIGBBY2Nlc3NpYmlsaXR5Q29uZmlnYCB0byBpbml0IGN1c3RvbSBhY2Nlc3NpYmlsaXR5IGZlYXR1cmVzLlxuICAgKiBGb3IgaW5zdGFuY2UsIGl0IGNvbnRhaW5zIHRpdGxlcywgYWx0IHRleHRzLCBhcmlhLWxhYmVscyBhbmQgc28gb24uXG4gICAqL1xuICBASW5wdXQoKVxuICBhY2Nlc3NpYmlsaXR5Q29uZmlnOiBBY2Nlc3NpYmlsaXR5Q29uZmlnIHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBPdXRwdXQgdG8gZW1pdCBhbiBldmVudCB3aGVuIGFuIGltYWdlIGlzIGNoYW5nZWQuXG4gICAqL1xuICBAT3V0cHV0KClcbiAgc2hvd0ltYWdlOiBFdmVudEVtaXR0ZXI8SW1hZ2VFdmVudD4gPSBuZXcgRXZlbnRFbWl0dGVyPEltYWdlRXZlbnQ+KCk7XG4gIC8qKlxuICAgKiBPdXRwdXQgdG8gZW1pdCBhbiBldmVudCB3aGVuIHRoZSBjdXJyZW50IGltYWdlIGlzIHRoZSBmaXJzdCBvbmUuXG4gICAqL1xuICBAT3V0cHV0KClcbiAgZmlyc3RJbWFnZTogRXZlbnRFbWl0dGVyPEltYWdlRXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxJbWFnZUV2ZW50PigpO1xuICAvKipcbiAgICogT3V0cHV0IHRvIGVtaXQgYW4gZXZlbnQgd2hlbiB0aGUgY3VycmVudCBpbWFnZSBpcyB0aGUgbGFzdCBvbmUuXG4gICAqL1xuICBAT3V0cHV0KClcbiAgbGFzdEltYWdlOiBFdmVudEVtaXR0ZXI8SW1hZ2VFdmVudD4gPSBuZXcgRXZlbnRFbWl0dGVyPEltYWdlRXZlbnQ+KCk7XG5cbiAgLyoqXG4gICAqIE9iamVjdCB1c2UgaW4gdGVtcGxhdGVcbiAgICovXG4gIGNvbmZpZ0Nhcm91c2VsOiBDYXJvdXNlbENvbmZpZyB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIE9iamVjdCB1c2UgaW4gdGVtcGxhdGVcbiAgICovXG4gIGNvbmZpZ1BsYXk6IFBsYXlDb25maWcgfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBPYmplY3QgdXNlIGluIHRlbXBsYXRlXG4gICAqL1xuICBjb25maWdDYXJvdXNlbEltYWdlOiBDYXJvdXNlbEltYWdlQ29uZmlnIHwgdW5kZWZpbmVkO1xuICAvKipcbiAgICogT2JqZWN0IHVzZSBpbiB0ZW1wbGF0ZVxuICAgKi9cbiAgY29uZmlnUHJldmlldzogQ2Fyb3VzZWxQcmV2aWV3Q29uZmlnIHwgdW5kZWZpbmVkO1xuICAvKipcbiAgICogT2JqZWN0IHVzZSBpbiB0ZW1wbGF0ZVxuICAgKi9cbiAgY29uZmlnRG90czogRG90c0NvbmZpZyB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIE9iamVjdCB1c2UgaW4gdGVtcGxhdGVcbiAgICovXG4gIGNvbmZpZ0FjY2Vzc2liaWxpdHk6IEFjY2Vzc2liaWxpdHlDb25maWcgPSBLU19ERUZBVUxUX0FDQ0VTU0lCSUxJVFlfQ09ORklHO1xuXG4gIC8qKlxuICAgKiBFbnVtIG9mIHR5cGUgYEFjdGlvbmAgdGhhdCByZXByZXNlbnRzIGEgbW91c2UgY2xpY2sgb24gYSBidXR0b24uXG4gICAqIERlY2xhcmVkIGhlcmUgdG8gYmUgdXNlZCBpbnNpZGUgdGhlIHRlbXBsYXRlLlxuICAgKi9cbiAgY2xpY2tBY3Rpb246IEFjdGlvbiA9IEFjdGlvbi5DTElDSztcbiAgLyoqXG4gICAqIEVudW0gb2YgdHlwZSBgQWN0aW9uYCB0aGF0IHJlcHJlc2VudHMgYSBrZXlib2FyZCBhY3Rpb24uXG4gICAqIERlY2xhcmVkIGhlcmUgdG8gYmUgdXNlZCBpbnNpZGUgdGhlIHRlbXBsYXRlLlxuICAgKi9cbiAga2V5Ym9hcmRBY3Rpb246IEFjdGlvbiA9IEFjdGlvbi5LRVlCT0FSRDtcbiAgLyoqXG4gICAqIGBJbWFnZWAgdGhhdCBpcyB2aXNpYmxlIHJpZ2h0IG5vdy5cbiAgICovXG4gIGN1cnJlbnRJbWFnZTogSW1hZ2UgfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBCb29sZWFuIHRoYXQgaXQncyB0cnVlIHdoZW4geW91IGFyZSB3YXRjaGluZyB0aGUgZmlyc3QgaW1hZ2UgKGN1cnJlbnRseSB2aXNpYmxlKS5cbiAgICogRmFsc2UgYnkgZGVmYXVsdFxuICAgKi9cbiAgaXNGaXJzdEltYWdlID0gZmFsc2U7XG4gIC8qKlxuICAgKiBCb29sZWFuIHRoYXQgaXQncyB0cnVlIHdoZW4geW91IGFyZSB3YXRjaGluZyB0aGUgbGFzdCBpbWFnZSAoY3VycmVudGx5IHZpc2libGUpLlxuICAgKiBGYWxzZSBieSBkZWZhdWx0XG4gICAqL1xuICBpc0xhc3RJbWFnZSA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBTdWJqZWN0IHRvIHBsYXkgdGhlIGNhcm91c2VsLlxuICAgKi9cbiAgcHJpdmF0ZSBzdGFydCQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICAvKipcbiAgICogU3ViamVjdCB0byBzdG9wIHRoZSBjYXJvdXNlbC5cbiAgICovXG4gIHByaXZhdGUgc3RvcCQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gIC8qKlxuICAgKiBQcml2YXRlIG9iamVjdCB3aXRob3V0IHR5cGUgdG8gZGVmaW5lIGFsbCBzd2lwZSBhY3Rpb25zIHVzZWQgYnkgaGFtbWVyanMuXG4gICAqL1xuICBwcml2YXRlIFNXSVBFX0FDVElPTiA9IHtcbiAgICBMRUZUOiAnc3dpcGVsZWZ0JyxcbiAgICBSSUdIVDogJ3N3aXBlcmlnaHQnLFxuICAgIFVQOiAnc3dpcGV1cCcsXG4gICAgRE9XTjogJ3N3aXBlZG93bidcbiAgfTtcblxuICAvKipcbiAgICogTGlzdGVuZXIgdG8gc3RvcCB0aGUgZ2FsbGVyeSB3aGVuIHRoZSBtb3VzZSBwb2ludGVyIGlzIG92ZXIgdGhlIGN1cnJlbnQgaW1hZ2UuXG4gICAqL1xuICBASG9zdExpc3RlbmVyKCdtb3VzZWVudGVyJylcbiAgb25Nb3VzZUVudGVyKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5pZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gaWQgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGNvbnN0IGxpYkNvbmZpZzogTGliQ29uZmlnIHwgdW5kZWZpbmVkID0gdGhpcy5jb25maWdTZXJ2aWNlLmdldENvbmZpZyh0aGlzLmlkKTtcbiAgICBpZiAoIWxpYkNvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gbGliQ29uZmlnIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBpZiAoIWxpYkNvbmZpZy5jYXJvdXNlbFBsYXlDb25maWcgfHwgIWxpYkNvbmZpZy5jYXJvdXNlbFBsYXlDb25maWcucGF1c2VPbkhvdmVyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuc3RvcENhcm91c2VsKCk7XG4gIH1cblxuICAvKipcbiAgICogTGlzdGVuZXIgdG8gcGxheSB0aGUgZ2FsbGVyeSB3aGVuIHRoZSBtb3VzZSBwb2ludGVyIGxlYXZlIHRoZSBjdXJyZW50IGltYWdlLlxuICAgKi9cbiAgQEhvc3RMaXN0ZW5lcignbW91c2VsZWF2ZScpXG4gIG9uTW91c2VMZWF2ZSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGlkIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBjb25zdCBsaWJDb25maWc6IExpYkNvbmZpZyB8IHVuZGVmaW5lZCA9IHRoaXMuY29uZmlnU2VydmljZS5nZXRDb25maWcodGhpcy5pZCk7XG4gICAgaWYgKCFsaWJDb25maWcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGxpYkNvbmZpZyBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgaWYgKCFsaWJDb25maWcuY2Fyb3VzZWxQbGF5Q29uZmlnIHx8ICFsaWJDb25maWcuY2Fyb3VzZWxQbGF5Q29uZmlnLnBhdXNlT25Ib3ZlciB8fCAhbGliQ29uZmlnLmNhcm91c2VsUGxheUNvbmZpZy5hdXRvUGxheSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnBsYXlDYXJvdXNlbCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIExpc3RlbmVyIHRvIG5hdmlnYXRlIGNhcm91c2VsIGltYWdlcyB3aXRoIGtleWJvYXJkIChsZWZ0KS5cbiAgICovXG4gIEBIb3N0TGlzdGVuZXIoJ2tleWRvd24uYXJyb3dMZWZ0JylcbiAgb25LZXlEb3duTGVmdCgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGlkIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBjb25zdCBsaWJDb25maWc6IExpYkNvbmZpZyB8IHVuZGVmaW5lZCA9IHRoaXMuY29uZmlnU2VydmljZS5nZXRDb25maWcodGhpcy5pZCk7XG4gICAgaWYgKCFsaWJDb25maWcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGxpYkNvbmZpZyBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgaWYgKCFsaWJDb25maWcuY2Fyb3VzZWxDb25maWcgfHwgIWxpYkNvbmZpZy5jYXJvdXNlbENvbmZpZy5rZXlib2FyZEVuYWJsZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnByZXZJbWFnZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIExpc3RlbmVyIHRvIG5hdmlnYXRlIGNhcm91c2VsIGltYWdlcyB3aXRoIGtleWJvYXJkIChyaWdodCkuXG4gICAqL1xuICBASG9zdExpc3RlbmVyKCdrZXlkb3duLmFycm93UmlnaHQnKVxuICBvbktleURvd25MUmlnaHQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBpZCBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgY29uc3QgbGliQ29uZmlnOiBMaWJDb25maWcgfCB1bmRlZmluZWQgPSB0aGlzLmNvbmZpZ1NlcnZpY2UuZ2V0Q29uZmlnKHRoaXMuaWQpO1xuICAgIGlmICghbGliQ29uZmlnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBsaWJDb25maWcgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGlmICghbGliQ29uZmlnLmNhcm91c2VsQ29uZmlnIHx8ICFsaWJDb25maWcuY2Fyb3VzZWxDb25maWcua2V5Ym9hcmRFbmFibGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5uZXh0SW1hZ2UoKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1hbnlcbiAgICBASW5qZWN0KFBMQVRGT1JNX0lEKSBwcml2YXRlIHBsYXRmb3JtSWQ6IGFueSxcbiAgICBwcml2YXRlIG5nWm9uZTogTmdab25lLFxuICAgIHByaXZhdGUgbW9kYWxHYWxsZXJ5U2VydmljZTogTW9kYWxHYWxsZXJ5U2VydmljZSxcbiAgICBwcml2YXRlIGNvbmZpZ1NlcnZpY2U6IENvbmZpZ1NlcnZpY2UsXG4gICAgcHJpdmF0ZSByZWY6IENoYW5nZURldGVjdG9yUmVmLFxuICAgIC8vIHNhbml0aXplciBpcyB1c2VkIG9ubHkgdG8gc2FuaXRpemUgc3R5bGUgYmVmb3JlIGFkZCBpdCB0byBiYWNrZ3JvdW5kIHByb3BlcnR5IHdoZW4gbGVnYWN5SUUxMU1vZGUgaXMgZW5hYmxlZFxuICAgIHByaXZhdGUgc2FuaXRpemVyOiBEb21TYW5pdGl6ZXJcbiAgKSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGlkIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBjb25zdCBsaWJDb25maWc6IExpYkNvbmZpZyB8IHVuZGVmaW5lZCA9IHRoaXMuY29uZmlnU2VydmljZS5nZXRDb25maWcodGhpcy5pZCk7XG4gICAgaWYgKCFsaWJDb25maWcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGxpYkNvbmZpZyBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG5cbiAgICAvLyBoYW5kbGUgY2hhbmdlcyBvZiBkb3RzQ29uZmlnXG4gICAgY29uc3QgY29uZmlnRG90c0NoYW5nZTogU2ltcGxlQ2hhbmdlID0gY2hhbmdlcy5kb3RzQ29uZmlnO1xuICAgIGlmIChjb25maWdEb3RzQ2hhbmdlICYmIGNvbmZpZ0RvdHNDaGFuZ2UuY3VycmVudFZhbHVlICE9PSBjb25maWdEb3RzQ2hhbmdlLnByZXZpb3VzVmFsdWUpIHtcbiAgICAgIHRoaXMuY29uZmlnU2VydmljZS5zZXRDb25maWcodGhpcy5pZCwge1xuICAgICAgICBjYXJvdXNlbERvdHNDb25maWc6IGNvbmZpZ0RvdHNDaGFuZ2UuY3VycmVudFZhbHVlXG4gICAgICB9KTtcbiAgICAgIHRoaXMuY29uZmlnRG90cyA9IGxpYkNvbmZpZy5jYXJvdXNlbERvdHNDb25maWc7XG4gICAgfVxuICAgIC8vIGhhbmRsZSBjaGFuZ2VzIG9mIGNhcm91c2VsQ29uZmlnXG4gICAgY29uc3QgY2Fyb3VzZWxDb25maWdDaGFuZ2U6IFNpbXBsZUNoYW5nZSA9IGNoYW5nZXMuY2Fyb3VzZWxDb25maWc7XG4gICAgaWYgKGNhcm91c2VsQ29uZmlnQ2hhbmdlICYmIGNhcm91c2VsQ29uZmlnQ2hhbmdlLmN1cnJlbnRWYWx1ZSAhPT0gY2Fyb3VzZWxDb25maWdDaGFuZ2UucHJldmlvdXNWYWx1ZSkge1xuICAgICAgdGhpcy5jb25maWdTZXJ2aWNlLnNldENvbmZpZyh0aGlzLmlkLCB7XG4gICAgICAgIGNhcm91c2VsQ29uZmlnOiBjYXJvdXNlbENvbmZpZ0NoYW5nZS5jdXJyZW50VmFsdWVcbiAgICAgIH0pO1xuICAgICAgdGhpcy5jb25maWdDYXJvdXNlbCA9IGNhcm91c2VsQ29uZmlnQ2hhbmdlLmN1cnJlbnRWYWx1ZTtcbiAgICB9XG4gICAgLy8gaGFuZGxlIGNoYW5nZXMgb2YgcGxheUNvbmZpZyBzdGFydGluZy9zdG9wcGluZyB0aGUgY2Fyb3VzZWwgYWNjb3JkaW5nbHlcbiAgICBjb25zdCBwbGF5Q29uZmlnQ2hhbmdlOiBTaW1wbGVDaGFuZ2UgPSBjaGFuZ2VzLnBsYXlDb25maWc7XG4gICAgaWYgKHBsYXlDb25maWdDaGFuZ2UpIHtcbiAgICAgIGNvbnN0IHBsYXlDb25maWdDaGFuZ2VQcmV2OiBQbGF5Q29uZmlnID0gcGxheUNvbmZpZ0NoYW5nZS5wcmV2aW91c1ZhbHVlO1xuICAgICAgY29uc3QgcGxheUNvbmZpZ0NoYW5nZUN1cnI6IFBsYXlDb25maWcgPSBwbGF5Q29uZmlnQ2hhbmdlLmN1cnJlbnRWYWx1ZTtcbiAgICAgIGlmIChwbGF5Q29uZmlnQ2hhbmdlUHJldiAhPT0gcGxheUNvbmZpZ0NoYW5nZUN1cnIpIHtcbiAgICAgICAgdGhpcy5jb25maWdTZXJ2aWNlLnNldENvbmZpZyh0aGlzLmlkLCB7XG4gICAgICAgICAgY2Fyb3VzZWxQbGF5Q29uZmlnOiBwbGF5Q29uZmlnQ2hhbmdlLmN1cnJlbnRWYWx1ZVxuICAgICAgICB9KTtcbiAgICAgICAgLy8gdGhpcy5jb25maWdQbGF5ID0gcGxheUNvbmZpZ0NoYW5nZS5jdXJyZW50VmFsdWU7XG4gICAgICAgIC8vIGlmIGF1dG9wbGF5IGlzIGVuYWJsZWQsIGFuZCB0aGlzIGlzIG5vdCB0aGVcbiAgICAgICAgLy8gZmlyc3QgY2hhbmdlICh0byBwcmV2ZW50IG11bHRpcGxlIHN0YXJ0cyBhdCB0aGUgYmVnaW5uaW5nKVxuICAgICAgICBpZiAocGxheUNvbmZpZ0NoYW5nZUN1cnIuYXV0b1BsYXkgJiYgIXBsYXlDb25maWdDaGFuZ2UuaXNGaXJzdENoYW5nZSgpKSB7XG4gICAgICAgICAgdGhpcy5zdGFydCQubmV4dCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuc3RvcENhcm91c2VsKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGlkIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuaW1hZ2VzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBpbWFnZXMgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGNvbnN0IGxpYkNvbmZpZzogTGliQ29uZmlnIHwgdW5kZWZpbmVkID0gdGhpcy5jb25maWdTZXJ2aWNlLmdldENvbmZpZyh0aGlzLmlkKTtcbiAgICBpZiAoIWxpYkNvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gbGliQ29uZmlnIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICB0aGlzLmN1cnJlbnRJbWFnZSA9IHRoaXMuaW1hZ2VzWzBdO1xuXG4gICAgdGhpcy5jb25maWdTZXJ2aWNlLnNldENvbmZpZyh0aGlzLmlkLCB7XG4gICAgICBjYXJvdXNlbENvbmZpZzogdGhpcy5jYXJvdXNlbENvbmZpZyxcbiAgICAgIGNhcm91c2VsSW1hZ2VDb25maWc6IHRoaXMuY2Fyb3VzZWxJbWFnZUNvbmZpZyxcbiAgICAgIGNhcm91c2VsUGxheUNvbmZpZzogdGhpcy5wbGF5Q29uZmlnLFxuICAgICAgY2Fyb3VzZWxQcmV2aWV3c0NvbmZpZzogdGhpcy5wcmV2aWV3Q29uZmlnLFxuICAgICAgY2Fyb3VzZWxEb3RzQ29uZmlnOiB0aGlzLmRvdHNDb25maWcsXG4gICAgICBhY2Nlc3NpYmlsaXR5Q29uZmlnOiB0aGlzLmFjY2Vzc2liaWxpdHlDb25maWcsXG4gICAgICAvLyB0aGlzIGN1c3RvbSBjb25maWcgd2l0aCAnZGlzYWJsZVNzcldvcmthcm91bmQ6IHRydWUnIGlzIHJlcXVpcmVkIGluIGNhc2Ugb2YgU3lzdGVtSlNcbiAgICAgIGtleWJvYXJkU2VydmljZUNvbmZpZzoge1xuICAgICAgICBzaG9ydGN1dHM6IFsnY3RybCtzJywgJ21ldGErcyddLFxuICAgICAgICBkaXNhYmxlU3NyV29ya2Fyb3VuZDogdGhpcy5kaXNhYmxlU3NyV29ya2Fyb3VuZFxuICAgICAgfVxuICAgIH0pO1xuICAgIHRoaXMuY29uZmlnQ2Fyb3VzZWwgPSBsaWJDb25maWcuY2Fyb3VzZWxDb25maWc7XG4gICAgdGhpcy5jb25maWdDYXJvdXNlbEltYWdlID0gbGliQ29uZmlnLmNhcm91c2VsSW1hZ2VDb25maWc7XG4gICAgdGhpcy5jb25maWdQbGF5ID0gbGliQ29uZmlnLmNhcm91c2VsUGxheUNvbmZpZztcbiAgICB0aGlzLmNvbmZpZ1ByZXZpZXcgPSBsaWJDb25maWcuY2Fyb3VzZWxQcmV2aWV3c0NvbmZpZztcbiAgICB0aGlzLmNvbmZpZ0RvdHMgPSBsaWJDb25maWcuY2Fyb3VzZWxEb3RzQ29uZmlnO1xuICAgIHRoaXMuY29uZmlnQWNjZXNzaWJpbGl0eSA9IGxpYkNvbmZpZy5hY2Nlc3NpYmlsaXR5Q29uZmlnIGFzIEFjY2Vzc2liaWxpdHlDb25maWc7XG4gICAgdGhpcy5tYW5hZ2VTbGlkZUNvbmZpZygpO1xuICB9XG5cbiAgbmdBZnRlckNvbnRlbnRJbml0KCk6IHZvaWQge1xuICAgIC8vIGludGVydmFsIGRvZXNuJ3QgcGxheSB3ZWxsIHdpdGggU1NSIGFuZCBwcm90cmFjdG9yLFxuICAgIC8vIHNvIHdlIHNob3VsZCBydW4gaXQgaW4gdGhlIGJyb3dzZXIgYW5kIG91dHNpZGUgQW5ndWxhclxuICAgIGlmIChpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtSWQpKSB7XG4gICAgICBpZiAoIXRoaXMuaWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gaWQgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBsaWJDb25maWc6IExpYkNvbmZpZyB8IHVuZGVmaW5lZCA9IHRoaXMuY29uZmlnU2VydmljZS5nZXRDb25maWcodGhpcy5pZCk7XG4gICAgICBpZiAoIWxpYkNvbmZpZyB8fCAhbGliQ29uZmlnLmNhcm91c2VsUGxheUNvbmZpZykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBsaWJDb25maWcgYW5kIGNhcm91c2VsUGxheUNvbmZpZyBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICAgIH1cbiAgICAgIHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgICAgdGhpcy5zdGFydCRcbiAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgIG1hcCgoKSA9PiBsaWJDb25maWcgJiYgbGliQ29uZmlnLmNhcm91c2VsUGxheUNvbmZpZyAmJiBsaWJDb25maWcuY2Fyb3VzZWxQbGF5Q29uZmlnLmludGVydmFsKSxcbiAgICAgICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1hbnlcbiAgICAgICAgICAgIGZpbHRlcigoaW50ZXJ2YWw6IGFueSkgPT4gaW50ZXJ2YWwgPiAwKSxcbiAgICAgICAgICAgIHN3aXRjaE1hcChpbnRlcnZhbCA9PiB0aW1lcihpbnRlcnZhbCkucGlwZSh0YWtlVW50aWwodGhpcy5zdG9wJCkpKVxuICAgICAgICAgIClcbiAgICAgICAgICAuc3Vic2NyaWJlKCgpID0+XG4gICAgICAgICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgICBpZiAodGhpcy5jb25maWdQbGF5ICYmIHRoaXMuY29uZmlnUGxheS5hdXRvUGxheSkge1xuICAgICAgICAgICAgICAgIHRoaXMubmV4dEltYWdlKCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgdGhpcy5yZWYubWFya0ZvckNoZWNrKCk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5zdGFydCQubmV4dCgpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB1c2VkIGluIHRlbXBsYXRlIHRvIHNhbml0aXplIGFuIHVybCB3aGVuIHlvdSBuZWVkIGxlZ2FjeUlFMTFNb2RlLlxuICAgKiBJbiB0aGlzIHdheSB5b3UgY2FuIHNldCBhbiB1cmwgYXMgYmFja2dyb3VuZCBvZiBhIGRpdi5cbiAgICogQHBhcmFtIHVuc2FmZVN0eWxlIGlzIGEgc3RyaW5nIGFuZCByZXByZXNlbnRzIHRoZSB1cmwgdG8gc2FuaXRpemUuXG4gICAqIEBwYXJhbSB1bnNhZmVTdHlsZUZhbGxiYWNrIGlzIGEgc3RyaW5nIGFuZCByZXByZXNlbnRzIHRoZSBmYWxsYmFjayB1cmwgdG8gc2FuaXRpemUuXG4gICAqIEByZXR1cm5zIGEgU2FmZVN0eWxlIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIGluIHRlbXBsYXRlIHdpdGhvdXQgcHJvYmxlbXMuXG4gICAqL1xuICBzYW5pdGl6ZVVybEJnU3R5bGUodW5zYWZlU3R5bGU6IHN0cmluZywgdW5zYWZlU3R5bGVGYWxsYmFjazogc3RyaW5nKTogU2FmZVN0eWxlIHtcbiAgICAvLyBNZXRob2QgdXNlZCBvbmx5IHRvIHNhbml0aXplIGJhY2tncm91bmQtaW1hZ2Ugc3R5bGUgYmVmb3JlIGFkZCBpdCB0byBiYWNrZ3JvdW5kIHByb3BlcnR5IHdoZW4gbGVnYWN5SUUxMU1vZGUgaXMgZW5hYmxlZFxuICAgIGxldCBiZzogc3RyaW5nID0gJ3VybCgnICsgdW5zYWZlU3R5bGUgKyAnKSc7XG4gICAgaWYgKCEhdW5zYWZlU3R5bGVGYWxsYmFjaykge1xuICAgICAgLy8gaWYgYSBmYWxsYmFjayBpbWFnZSBpcyBkZWZpbmVkLCBhcHBlbmQgaXQuIEluIHRoaXMgd2F5LCBpdCB3aWxsIGJlIHVzZWQgYnkgdGhlIGJyb3dzZXIgYXMgZmFsbGJhY2suXG4gICAgICBiZyArPSAnLCAnICsgJ3VybCgnICsgdW5zYWZlU3R5bGVGYWxsYmFjayArICcpJztcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2FuaXRpemVyLmJ5cGFzc1NlY3VyaXR5VHJ1c3RTdHlsZShiZyk7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIGNhbGxlZCB3aGVuIGEgZG90IGlzIGNsaWNrZWQgYW5kIHVzZWQgdG8gdXBkYXRlIHRoZSBjdXJyZW50IGltYWdlLlxuICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4IG9mIHRoZSBjbGlja2VkIGRvdFxuICAgKi9cbiAgb25DbGlja0RvdChpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5jaGFuZ2VDdXJyZW50SW1hZ2UodGhpcy5pbWFnZXNbaW5kZXhdLCBBY3Rpb24uTk9STUFMKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgY2FsbGVkIGJ5IGV2ZW50cyBmcm9tIGJvdGgga2V5Ym9hcmQgYW5kIG1vdXNlIG9uIGEgbmF2aWdhdGlvbiBhcnJvdy5cbiAgICogQHBhcmFtIHN0cmluZyBkaXJlY3Rpb24gb2YgdGhlIG5hdmlnYXRpb24gdGhhdCBjYW4gYmUgZWl0aGVyICduZXh0JyBvciAncHJldidcbiAgICogQHBhcmFtIEtleWJvYXJkRXZlbnQgfCBNb3VzZUV2ZW50IGV2ZW50IHBheWxvYWRcbiAgICogQHBhcmFtIEFjdGlvbiBhY3Rpb24gdGhhdCB0cmlnZ2VyZWQgdGhlIGV2ZW50IG9yIGBBY3Rpb24uTk9STUFMYCBpZiBub3QgcHJvdmlkZWRcbiAgICovXG4gIG9uTmF2aWdhdGlvbkV2ZW50KGRpcmVjdGlvbjogc3RyaW5nLCBldmVudDogS2V5Ym9hcmRFdmVudCwgYWN0aW9uOiBBY3Rpb24gPSBBY3Rpb24uTk9STUFMKTogdm9pZCB7XG4gICAgY29uc3QgcmVzdWx0OiBudW1iZXIgPSBzdXBlci5oYW5kbGVOYXZpZ2F0aW9uRXZlbnQoZGlyZWN0aW9uLCBldmVudCk7XG4gICAgaWYgKHJlc3VsdCA9PT0gTkVYVCkge1xuICAgICAgdGhpcy5uZXh0SW1hZ2UoYWN0aW9uKTtcbiAgICB9IGVsc2UgaWYgKHJlc3VsdCA9PT0gUFJFVikge1xuICAgICAgdGhpcy5wcmV2SW1hZ2UoYWN0aW9uKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRyaWdnZXJlZCB3aGVuIHlvdSBjbGljayBvbiB0aGUgY3VycmVudCBpbWFnZS5cbiAgICogQWxzbywgaWYgbW9kYWxHYWxsZXJ5RW5hYmxlIGlzIHRydWUsIHlvdSBjYW4gb3BlbiB0aGUgbW9kYWwtZ2FsbGVyeS5cbiAgICovXG4gIG9uQ2xpY2tDdXJyZW50SW1hZ2UoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBpZCBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgY29uc3QgbGliQ29uZmlnOiBMaWJDb25maWcgfCB1bmRlZmluZWQgPSB0aGlzLmNvbmZpZ1NlcnZpY2UuZ2V0Q29uZmlnKHRoaXMuaWQpO1xuICAgIGlmICghbGliQ29uZmlnIHx8ICFsaWJDb25maWcuY2Fyb3VzZWxDb25maWcgfHwgIXRoaXMuY3VycmVudEltYWdlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBsaWJDb25maWcsIGNhcm91c2VsQ29uZmlnIGFuZCBjdXJyZW50SW1hZ2UgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGlmICghbGliQ29uZmlnLmNhcm91c2VsQ29uZmlnLm1vZGFsR2FsbGVyeUVuYWJsZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBpbmRleCA9IGdldEluZGV4KHRoaXMuY3VycmVudEltYWdlLCB0aGlzLmltYWdlcyk7XG4gICAgdGhpcy5tb2RhbEdhbGxlcnlTZXJ2aWNlLm9wZW4oe1xuICAgICAgaWQ6IHRoaXMuaWQsXG4gICAgICBpbWFnZXM6IHRoaXMuaW1hZ2VzLFxuICAgICAgY3VycmVudEltYWdlOiB0aGlzLmltYWdlc1tpbmRleF0sXG4gICAgICBsaWJDb25maWc6IHtcbiAgICAgICAgLy8gdGhpcyBjdXN0b20gY29uZmlnIHdpdGggJ2Rpc2FibGVTc3JXb3JrYXJvdW5kOiB0cnVlJyBpcyByZXF1aXJlZCBpbiBjYXNlIG9mIFN5c3RlbUpTXG4gICAgICAgIGtleWJvYXJkU2VydmljZUNvbmZpZzoge1xuICAgICAgICAgIHNob3J0Y3V0czogWydjdHJsK3MnLCAnbWV0YStzJ10sXG4gICAgICAgICAgZGlzYWJsZVNzcldvcmthcm91bmQ6IHRoaXMuZGlzYWJsZVNzcldvcmthcm91bmRcbiAgICAgICAgfSBhcyBLZXlib2FyZFNlcnZpY2VDb25maWdcbiAgICAgIH0gYXMgTGliQ29uZmlnXG4gICAgfSBhcyBNb2RhbEdhbGxlcnlDb25maWcpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB0byBnZXQgdGhlIGltYWdlIGRlc2NyaXB0aW9uIGJhc2VkIG9uIGlucHV0IHBhcmFtcy5cbiAgICogSWYgeW91IHByb3ZpZGUgYSBmdWxsIGRlc2NyaXB0aW9uIHRoaXMgd2lsbCBiZSB0aGUgdmlzaWJsZSBkZXNjcmlwdGlvbiwgb3RoZXJ3aXNlLFxuICAgKiBpdCB3aWxsIGJlIGJ1aWx0IHVzaW5nIHRoZSBgRGVzY3JpcHRpb25gIG9iamVjdCwgY29uY2F0ZW5hdGluZyBpdHMgZmllbGRzLlxuICAgKiBAcGFyYW0gSW1hZ2UgaW1hZ2UgdG8gZ2V0IGl0cyBkZXNjcmlwdGlvbi4gSWYgbm90IHByb3ZpZGVkIGl0IHdpbGwgYmUgdGhlIGN1cnJlbnQgaW1hZ2VcbiAgICogQHJldHVybnMgU3RyaW5nIGRlc2NyaXB0aW9uIG9mIHRoZSBpbWFnZSAob3IgdGhlIGN1cnJlbnQgaW1hZ2UgaWYgbm90IHByb3ZpZGVkKVxuICAgKiBAdGhyb3dzIGFuIEVycm9yIGlmIGRlc2NyaXB0aW9uIGlzbid0IGF2YWlsYWJsZVxuICAgKi9cbiAgZ2V0RGVzY3JpcHRpb25Ub0Rpc3BsYXkoaW1hZ2U6IEltYWdlIHwgdW5kZWZpbmVkID0gdGhpcy5jdXJyZW50SW1hZ2UpOiBzdHJpbmcge1xuICAgIGlmICghdGhpcy5pZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gaWQgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGNvbnN0IGxpYkNvbmZpZzogTGliQ29uZmlnIHwgdW5kZWZpbmVkID0gdGhpcy5jb25maWdTZXJ2aWNlLmdldENvbmZpZyh0aGlzLmlkKTtcbiAgICBpZiAoIWxpYkNvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gbGliQ29uZmlnIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBjb25zdCBjb25maWdDdXJyZW50SW1hZ2VDYXJvdXNlbDogQ2Fyb3VzZWxJbWFnZUNvbmZpZyB8IHVuZGVmaW5lZCA9IGxpYkNvbmZpZy5jYXJvdXNlbEltYWdlQ29uZmlnO1xuICAgIGlmICghY29uZmlnQ3VycmVudEltYWdlQ2Fyb3VzZWwgfHwgIWNvbmZpZ0N1cnJlbnRJbWFnZUNhcm91c2VsLmRlc2NyaXB0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Rlc2NyaXB0aW9uIGlucHV0IG11c3QgYmUgYSB2YWxpZCBvYmplY3QgaW1wbGVtZW50aW5nIHRoZSBEZXNjcmlwdGlvbiBpbnRlcmZhY2UnKTtcbiAgICB9XG4gICAgaWYgKCFpbWFnZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gaW1hZ2UgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGNvbnN0IGltYWdlV2l0aG91dERlc2NyaXB0aW9uOiBib29sZWFuID0gIWltYWdlIHx8ICFpbWFnZS5tb2RhbCB8fCAhaW1hZ2UubW9kYWwuZGVzY3JpcHRpb24gfHwgaW1hZ2UubW9kYWwuZGVzY3JpcHRpb24gPT09ICcnO1xuXG4gICAgc3dpdGNoIChjb25maWdDdXJyZW50SW1hZ2VDYXJvdXNlbC5kZXNjcmlwdGlvbi5zdHJhdGVneSkge1xuICAgICAgY2FzZSBEZXNjcmlwdGlvblN0cmF0ZWd5LkhJREVfSUZfRU1QVFk6XG4gICAgICAgIHJldHVybiBpbWFnZVdpdGhvdXREZXNjcmlwdGlvbiA/ICcnIDogaW1hZ2UubW9kYWwuZGVzY3JpcHRpb24gKyAnJztcbiAgICAgIGNhc2UgRGVzY3JpcHRpb25TdHJhdGVneS5BTFdBWVNfSElEREVOOlxuICAgICAgICByZXR1cm4gJyc7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICAvLyAtLS0tLS0tLS0tLSBEZXNjcmlwdGlvblN0cmF0ZWd5LkFMV0FZU19WSVNJQkxFIC0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkVGV4dERlc2NyaXB0aW9uKGltYWdlLCBpbWFnZVdpdGhvdXREZXNjcmlwdGlvbik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB1c2VkIGJ5IEhhbW1lcmpzIHRvIHN1cHBvcnQgdG91Y2ggZ2VzdHVyZXMgKHlvdSBjYW4gYWxzbyBpbnZlcnQgdGhlIHN3aXBlIGRpcmVjdGlvbiB3aXRoIGNvbmZpZ0N1cnJlbnRJbWFnZS5pbnZlcnRTd2lwZSkuXG4gICAqIEBwYXJhbSBhY3Rpb24gU3RyaW5nIHRoYXQgcmVwcmVzZW50IHRoZSBkaXJlY3Rpb24gb2YgdGhlIHN3aXBlIGFjdGlvbi4gJ3N3aXBlcmlnaHQnIGJ5IGRlZmF1bHQuXG4gICAqL1xuICBzd2lwZShhY3Rpb24gPSB0aGlzLlNXSVBFX0FDVElPTi5SSUdIVCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5pZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gaWQgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGNvbnN0IGxpYkNvbmZpZzogTGliQ29uZmlnIHwgdW5kZWZpbmVkID0gdGhpcy5jb25maWdTZXJ2aWNlLmdldENvbmZpZyh0aGlzLmlkKTtcbiAgICBpZiAoIWxpYkNvbmZpZyB8fCAhbGliQ29uZmlnLmNhcm91c2VsSW1hZ2VDb25maWcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGxpYkNvbmZpZyBhbmQgY2Fyb3VzZWxJbWFnZUNvbmZpZyBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgY29uc3QgY29uZmlnQ3VycmVudEltYWdlQ2Fyb3VzZWw6IENhcm91c2VsSW1hZ2VDb25maWcgPSBsaWJDb25maWcuY2Fyb3VzZWxJbWFnZUNvbmZpZztcbiAgICBzd2l0Y2ggKGFjdGlvbikge1xuICAgICAgY2FzZSB0aGlzLlNXSVBFX0FDVElPTi5SSUdIVDpcbiAgICAgICAgaWYgKGNvbmZpZ0N1cnJlbnRJbWFnZUNhcm91c2VsLmludmVydFN3aXBlKSB7XG4gICAgICAgICAgdGhpcy5wcmV2SW1hZ2UoQWN0aW9uLlNXSVBFKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLm5leHRJbWFnZShBY3Rpb24uU1dJUEUpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSB0aGlzLlNXSVBFX0FDVElPTi5MRUZUOlxuICAgICAgICBpZiAoY29uZmlnQ3VycmVudEltYWdlQ2Fyb3VzZWwuaW52ZXJ0U3dpcGUpIHtcbiAgICAgICAgICB0aGlzLm5leHRJbWFnZShBY3Rpb24uU1dJUEUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMucHJldkltYWdlKEFjdGlvbi5TV0lQRSk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICAvLyBjYXNlIHRoaXMuU1dJUEVfQUNUSU9OLlVQOlxuICAgICAgLy8gICBicmVhaztcbiAgICAgIC8vIGNhc2UgdGhpcy5TV0lQRV9BQ1RJT04uRE9XTjpcbiAgICAgIC8vICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB0byBnbyBiYWNrIHRvIHRoZSBwcmV2aW91cyBpbWFnZS5cbiAgICogQHBhcmFtIGFjdGlvbiBFbnVtIG9mIHR5cGUgYEFjdGlvbmAgdGhhdCByZXByZXNlbnRzIHRoZSBzb3VyY2VcbiAgICogIGFjdGlvbiB0aGF0IG1vdmVkIGJhY2sgdG8gdGhlIHByZXZpb3VzIGltYWdlLiBgQWN0aW9uLk5PUk1BTGAgYnkgZGVmYXVsdC5cbiAgICovXG4gIHByZXZJbWFnZShhY3Rpb246IEFjdGlvbiA9IEFjdGlvbi5OT1JNQUwpOiB2b2lkIHtcbiAgICAvLyBjaGVjayBpZiBwcmV2SW1hZ2Ugc2hvdWxkIGJlIGJsb2NrZWRcbiAgICBpZiAodGhpcy5pc1ByZXZlbnRTbGlkaW5nKDApKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuY2hhbmdlQ3VycmVudEltYWdlKHRoaXMuZ2V0UHJldkltYWdlKCksIGFjdGlvbik7XG5cbiAgICB0aGlzLm1hbmFnZVNsaWRlQ29uZmlnKCk7XG5cbiAgICB0aGlzLnN0YXJ0JC5uZXh0KCk7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRvIGdvIGJhY2sgdG8gdGhlIHByZXZpb3VzIGltYWdlLlxuICAgKiBAcGFyYW0gYWN0aW9uIEVudW0gb2YgdHlwZSBgQWN0aW9uYCB0aGF0IHJlcHJlc2VudHMgdGhlIHNvdXJjZVxuICAgKiAgYWN0aW9uIHRoYXQgbW92ZWQgdG8gdGhlIG5leHQgaW1hZ2UuIGBBY3Rpb24uTk9STUFMYCBieSBkZWZhdWx0LlxuICAgKi9cbiAgbmV4dEltYWdlKGFjdGlvbjogQWN0aW9uID0gQWN0aW9uLk5PUk1BTCk6IHZvaWQge1xuICAgIC8vIGNoZWNrIGlmIG5leHRJbWFnZSBzaG91bGQgYmUgYmxvY2tlZFxuICAgIGlmICh0aGlzLmlzUHJldmVudFNsaWRpbmcodGhpcy5pbWFnZXMubGVuZ3RoIC0gMSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5jaGFuZ2VDdXJyZW50SW1hZ2UodGhpcy5nZXROZXh0SW1hZ2UoKSwgYWN0aW9uKTtcblxuICAgIHRoaXMubWFuYWdlU2xpZGVDb25maWcoKTtcblxuICAgIHRoaXMuc3RhcnQkLm5leHQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgdXNlZCBpbiB0aGUgdGVtcGxhdGUgdG8gdHJhY2sgaWRzIGluIG5nRm9yLlxuICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4IG9mIHRoZSBhcnJheVxuICAgKiBAcGFyYW0gSW1hZ2UgaXRlbSBvZiB0aGUgYXJyYXlcbiAgICogQHJldHVybnMgbnVtYmVyIHRoZSBpZCBvZiB0aGUgaXRlbVxuICAgKi9cbiAgdHJhY2tCeUlkKGluZGV4OiBudW1iZXIsIGl0ZW06IEltYWdlKTogbnVtYmVyIHtcbiAgICByZXR1cm4gaXRlbS5pZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgY2FsbGVkIHdoZW4gYW4gaW1hZ2UgcHJldmlldyBpcyBjbGlja2VkIGFuZCB1c2VkIHRvIHVwZGF0ZSB0aGUgY3VycmVudCBpbWFnZS5cbiAgICogQHBhcmFtIGV2ZW50IGFuIEltYWdlRXZlbnQgb2JqZWN0IHdpdGggdGhlIHJlbGF0aXZlIGFjdGlvbiBhbmQgdGhlIGluZGV4IG9mIHRoZSBjbGlja2VkIHByZXZpZXcuXG4gICAqL1xuICBvbkNsaWNrUHJldmlldyhldmVudDogSW1hZ2VFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IGltYWdlRm91bmQ6IEltYWdlID0gdGhpcy5pbWFnZXNbZXZlbnQucmVzdWx0IGFzIG51bWJlcl07XG4gICAgaWYgKCEhaW1hZ2VGb3VuZCkge1xuICAgICAgdGhpcy5tYW5hZ2VTbGlkZUNvbmZpZygpO1xuICAgICAgdGhpcy5jaGFuZ2VDdXJyZW50SW1hZ2UoaW1hZ2VGb3VuZCwgZXZlbnQuYWN0aW9uKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRvIHBsYXkgY2Fyb3VzZWwuXG4gICAqL1xuICBwbGF5Q2Fyb3VzZWwoKTogdm9pZCB7XG4gICAgdGhpcy5zdGFydCQubmV4dCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0b3BzIHRoZSBjYXJvdXNlbCBmcm9tIGN5Y2xpbmcgdGhyb3VnaCBpdGVtcy5cbiAgICovXG4gIHN0b3BDYXJvdXNlbCgpOiB2b2lkIHtcbiAgICB0aGlzLnN0b3AkLm5leHQoKTtcbiAgfVxuXG4gIC8vIFRPRE8gcmVtb3ZlIHRoaXMgYmVjYXVzZSBkdXBsaWNhdGVkXG4gIC8qKlxuICAgKiBNZXRob2QgdG8gZ2V0IGBhbHQgYXR0cmlidXRlYC5cbiAgICogYGFsdGAgc3BlY2lmaWVzIGFuIGFsdGVybmF0ZSB0ZXh0IGZvciBhbiBpbWFnZSwgaWYgdGhlIGltYWdlIGNhbm5vdCBiZSBkaXNwbGF5ZWQuXG4gICAqIEBwYXJhbSBJbWFnZSBpbWFnZSB0byBnZXQgaXRzIGFsdCBkZXNjcmlwdGlvbi4gSWYgbm90IHByb3ZpZGVkIGl0IHdpbGwgYmUgdGhlIGN1cnJlbnQgaW1hZ2VcbiAgICogQHJldHVybnMgU3RyaW5nIGFsdCBkZXNjcmlwdGlvbiBvZiB0aGUgaW1hZ2UgKG9yIHRoZSBjdXJyZW50IGltYWdlIGlmIG5vdCBwcm92aWRlZClcbiAgICovXG4gIGdldEFsdERlc2NyaXB0aW9uQnlJbWFnZShpbWFnZTogSW1hZ2UgfCB1bmRlZmluZWQgPSB0aGlzLmN1cnJlbnRJbWFnZSk6IHN0cmluZyB7XG4gICAgaWYgKCFpbWFnZSkge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgICByZXR1cm4gaW1hZ2UubW9kYWwgJiYgaW1hZ2UubW9kYWwuZGVzY3JpcHRpb24gPyBpbWFnZS5tb2RhbC5kZXNjcmlwdGlvbiA6IGBJbWFnZSAke2dldEluZGV4KGltYWdlLCB0aGlzLmltYWdlcykgKyAxfWA7XG4gIH1cblxuICAvLyBUT0RPIHJlbW92ZSB0aGlzIGJlY2F1c2UgZHVwbGljYXRlZFxuICAvKipcbiAgICogTWV0aG9kIHRvIGdldCB0aGUgdGl0bGUgYXR0cmlidXRlcyBiYXNlZCBvbiBkZXNjcmlwdGlvbnMuXG4gICAqIFRoaXMgaXMgdXNlZnVsIHRvIHByZXZlbnQgYWNjZXNzaWJpbGl0eSBpc3N1ZXMsIGJlY2F1c2UgaWYgRGVzY3JpcHRpb25TdHJhdGVneSBpcyBBTFdBWVNfSElEREVOLFxuICAgKiBpdCBwcmV2ZW50cyBhbiBlbXB0eSBzdHJpbmcgYXMgdGl0bGUuXG4gICAqIEBwYXJhbSBJbWFnZSBpbWFnZSB0byBnZXQgaXRzIGRlc2NyaXB0aW9uLiBJZiBub3QgcHJvdmlkZWQgaXQgd2lsbCBiZSB0aGUgY3VycmVudCBpbWFnZVxuICAgKiBAcmV0dXJucyBTdHJpbmcgdGl0bGUgb2YgdGhlIGltYWdlIGJhc2VkIG9uIGRlc2NyaXB0aW9uc1xuICAgKiBAdGhyb3dzIGFuIEVycm9yIGlmIGRlc2NyaXB0aW9uIGlzbid0IGF2YWlsYWJsZVxuICAgKi9cbiAgZ2V0VGl0bGVUb0Rpc3BsYXkoaW1hZ2U6IEltYWdlIHwgdW5kZWZpbmVkID0gdGhpcy5jdXJyZW50SW1hZ2UpOiBzdHJpbmcge1xuICAgIGlmICghdGhpcy5pZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gaWQgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGNvbnN0IGxpYkNvbmZpZzogTGliQ29uZmlnIHwgdW5kZWZpbmVkID0gdGhpcy5jb25maWdTZXJ2aWNlLmdldENvbmZpZyh0aGlzLmlkKTtcbiAgICBpZiAoIWxpYkNvbmZpZyB8fCAhbGliQ29uZmlnLmNhcm91c2VsSW1hZ2VDb25maWcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGxpYkNvbmZpZyBhbmQgY2Fyb3VzZWxJbWFnZUNvbmZpZyBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgY29uc3QgY29uZmlnQ3VycmVudEltYWdlQ2Fyb3VzZWw6IENhcm91c2VsSW1hZ2VDb25maWcgPSBsaWJDb25maWcuY2Fyb3VzZWxJbWFnZUNvbmZpZztcbiAgICBpZiAoIWNvbmZpZ0N1cnJlbnRJbWFnZUNhcm91c2VsIHx8ICFjb25maWdDdXJyZW50SW1hZ2VDYXJvdXNlbC5kZXNjcmlwdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdEZXNjcmlwdGlvbiBpbnB1dCBtdXN0IGJlIGEgdmFsaWQgb2JqZWN0IGltcGxlbWVudGluZyB0aGUgRGVzY3JpcHRpb24gaW50ZXJmYWNlJyk7XG4gICAgfVxuICAgIGNvbnN0IGltYWdlV2l0aG91dERlc2NyaXB0aW9uOiBib29sZWFuID0gIWltYWdlIHx8ICFpbWFnZS5tb2RhbCB8fCAhaW1hZ2UubW9kYWwuZGVzY3JpcHRpb24gfHwgaW1hZ2UubW9kYWwuZGVzY3JpcHRpb24gPT09ICcnO1xuICAgIGNvbnN0IGRlc2NyaXB0aW9uOiBzdHJpbmcgPSB0aGlzLmJ1aWxkVGV4dERlc2NyaXB0aW9uKGltYWdlLCBpbWFnZVdpdGhvdXREZXNjcmlwdGlvbik7XG4gICAgcmV0dXJuIGRlc2NyaXB0aW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB0byByZXNldCBjYXJvdXNlbCAoZm9yY2UgaW1hZ2Ugd2l0aCBpbmRleCAwIHRvIGJlIHRoZSBjdXJyZW50IGltYWdlIGFuZCByZS1pbml0IGFsc28gcHJldmlld3MpXG4gICAqL1xuICAvLyB0ZW1wb3JhcnkgcmVtb3ZlZCBiZWNhdXNlIG5ldmVyIHRlc3RlZFxuICAvLyByZXNldCgpIHtcbiAgLy8gICBpZiAodGhpcy5jb25maWdQbGF5ICYmIHRoaXMuY29uZmlnUGxheS5hdXRvUGxheSkge1xuICAvLyAgICAgdGhpcy5zdG9wQ2Fyb3VzZWwoKTtcbiAgLy8gICB9XG4gIC8vICAgdGhpcy5jdXJyZW50SW1hZ2UgPSB0aGlzLmltYWdlc1swXTtcbiAgLy8gICB0aGlzLmhhbmRsZUJvdW5kYXJpZXMoMCk7XG4gIC8vICAgaWYgKHRoaXMuY29uZmlnUGxheSAmJiB0aGlzLmNvbmZpZ1BsYXkuYXV0b1BsYXkpIHtcbiAgLy8gICAgIHRoaXMucGxheUNhcm91c2VsKCk7XG4gIC8vICAgfVxuICAvLyAgIHRoaXMucmVmLm1hcmtGb3JDaGVjaygpO1xuICAvLyB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB0byBjbGVhbnVwIHJlc291cmNlcy4gSW4gZmFjdCwgdGhpcyB3aWxsIHN0b3AgdGhlIGNhcm91c2VsLlxuICAgKiBUaGlzIGlzIGFuIEFuZ3VsYXIncyBsaWZlY3ljbGUgaG9vayB0aGF0IGlzIGNhbGxlZCB3aGVuIHRoaXMgY29tcG9uZW50IGlzIGRlc3Ryb3llZC5cbiAgICovXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuc3RvcENhcm91c2VsKCk7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRvIGNoYW5nZSB0aGUgY3VycmVudCBpbWFnZSwgcmVjZWl2aW5nIHRoZSBuZXcgaW1hZ2UgYXMgaW5wdXQgdGhlIHJlbGF0aXZlIGFjdGlvbi5cbiAgICogQHBhcmFtIGltYWdlIGFuIEltYWdlIG9iamVjdCB0aGF0IHJlcHJlc2VudHMgdGhlIG5ldyBpbWFnZSB0byBzZXQgYXMgY3VycmVudC5cbiAgICogQHBhcmFtIGFjdGlvbiBFbnVtIG9mIHR5cGUgYEFjdGlvbmAgdGhhdCByZXByZXNlbnRzIHRoZSBzb3VyY2UgYWN0aW9uIHRoYXQgdHJpZ2dlcmVkIHRoZSBjaGFuZ2UuXG4gICAqL1xuICBwcml2YXRlIGNoYW5nZUN1cnJlbnRJbWFnZShpbWFnZTogSW1hZ2UsIGFjdGlvbjogQWN0aW9uKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBpZCBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgdGhpcy5jdXJyZW50SW1hZ2UgPSBpbWFnZTtcbiAgICBjb25zdCBpbmRleDogbnVtYmVyID0gZ2V0SW5kZXgoaW1hZ2UsIHRoaXMuaW1hZ2VzKTtcblxuICAgIC8vIGVtaXQgZmlyc3QvbGFzdCBldmVudCBiYXNlZCBvbiBuZXdJbmRleCB2YWx1ZVxuICAgIHRoaXMuZW1pdEJvdW5kYXJ5RXZlbnQoYWN0aW9uLCBpbmRleCk7XG5cbiAgICAvLyBlbWl0IGN1cnJlbnQgdmlzaWJsZSBpbWFnZSBpbmRleFxuICAgIHRoaXMuc2hvd0ltYWdlLmVtaXQobmV3IEltYWdlRXZlbnQodGhpcy5pZCwgYWN0aW9uLCBpbmRleCArIDEpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcml2YXRlIG1ldGhvZCB0byBnZXQgdGhlIG5leHQgaW5kZXguXG4gICAqIFRoaXMgaXMgbmVjZXNzYXJ5IGJlY2F1c2UgYXQgdGhlIGVuZCwgd2hlbiB5b3UgY2FsbCBuZXh0IGFnYWluLCB5b3UnbGwgZ28gdG8gdGhlIGZpcnN0IGltYWdlLlxuICAgKiBUaGF0IGhhcHBlbnMgYmVjYXVzZSBhbGwgbW9kYWwgaW1hZ2VzIGFyZSBzaG93biBsaWtlIGluIGEgY2lyY2xlLlxuICAgKi9cbiAgcHJpdmF0ZSBnZXROZXh0SW1hZ2UoKTogSW1hZ2Uge1xuICAgIGlmICghdGhpcy5jdXJyZW50SW1hZ2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGN1cnJlbnRJbWFnZSBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgY29uc3QgY3VycmVudEluZGV4OiBudW1iZXIgPSBnZXRJbmRleCh0aGlzLmN1cnJlbnRJbWFnZSwgdGhpcy5pbWFnZXMpO1xuICAgIGxldCBuZXdJbmRleCA9IDA7XG4gICAgaWYgKGN1cnJlbnRJbmRleCA+PSAwICYmIGN1cnJlbnRJbmRleCA8IHRoaXMuaW1hZ2VzLmxlbmd0aCAtIDEpIHtcbiAgICAgIG5ld0luZGV4ID0gY3VycmVudEluZGV4ICsgMTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3SW5kZXggPSAwOyAvLyBzdGFydCBmcm9tIHRoZSBmaXJzdCBpbmRleFxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5pbWFnZXNbbmV3SW5kZXhdO1xuICB9XG5cbiAgLyoqXG4gICAqIFByaXZhdGUgbWV0aG9kIHRvIGdldCB0aGUgcHJldmlvdXMgaW5kZXguXG4gICAqIFRoaXMgaXMgbmVjZXNzYXJ5IGJlY2F1c2UgYXQgaW5kZXggMCwgd2hlbiB5b3UgY2FsbCBwcmV2IGFnYWluLCB5b3UnbGwgZ28gdG8gdGhlIGxhc3QgaW1hZ2UuXG4gICAqIFRoYXQgaGFwcGVucyBiZWNhdXNlIGFsbCBtb2RhbCBpbWFnZXMgYXJlIHNob3duIGxpa2UgaW4gYSBjaXJjbGUuXG4gICAqL1xuICBwcml2YXRlIGdldFByZXZJbWFnZSgpOiBJbWFnZSB7XG4gICAgaWYgKCF0aGlzLmN1cnJlbnRJbWFnZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gY3VycmVudEltYWdlIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBjb25zdCBjdXJyZW50SW5kZXg6IG51bWJlciA9IGdldEluZGV4KHRoaXMuY3VycmVudEltYWdlLCB0aGlzLmltYWdlcyk7XG4gICAgbGV0IG5ld0luZGV4ID0gMDtcbiAgICBpZiAoY3VycmVudEluZGV4ID4gMCAmJiBjdXJyZW50SW5kZXggPD0gdGhpcy5pbWFnZXMubGVuZ3RoIC0gMSkge1xuICAgICAgbmV3SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdJbmRleCA9IHRoaXMuaW1hZ2VzLmxlbmd0aCAtIDE7IC8vIHN0YXJ0IGZyb20gdGhlIGxhc3QgaW5kZXhcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuaW1hZ2VzW25ld0luZGV4XTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcml2YXRlIG1ldGhvZCB0byBidWlsZCBhIHRleHQgZGVzY3JpcHRpb24uXG4gICAqIFRoaXMgaXMgdXNlZCBhbHNvIHRvIGNyZWF0ZSB0aXRsZXMuXG4gICAqIEBwYXJhbSBJbWFnZSBpbWFnZSB0byBnZXQgaXRzIGRlc2NyaXB0aW9uLiBJZiBub3QgcHJvdmlkZWQgaXQgd2lsbCBiZSB0aGUgY3VycmVudCBpbWFnZS5cbiAgICogQHBhcmFtIGJvb2xlYW4gaW1hZ2VXaXRob3V0RGVzY3JpcHRpb24gaXMgYSBib29sZWFuIHRoYXQgaXQncyB0cnVlIGlmIHRoZSBpbWFnZSBoYXNuJ3QgYSAnbW9kYWwnIGRlc2NyaXB0aW9uLlxuICAgKiBAcmV0dXJucyBTdHJpbmcgZGVzY3JpcHRpb24gYnVpbHQgY29uY2F0ZW5hdGluZyBpbWFnZSBmaWVsZHMgd2l0aCBhIHNwZWNpZmljIGxvZ2ljLlxuICAgKi9cbiAgcHJpdmF0ZSBidWlsZFRleHREZXNjcmlwdGlvbihpbWFnZTogSW1hZ2UgfCB1bmRlZmluZWQsIGltYWdlV2l0aG91dERlc2NyaXB0aW9uOiBib29sZWFuKTogc3RyaW5nIHtcbiAgICBpZiAoIXRoaXMuaWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGlkIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBjb25zdCBsaWJDb25maWc6IExpYkNvbmZpZyB8IHVuZGVmaW5lZCA9IHRoaXMuY29uZmlnU2VydmljZS5nZXRDb25maWcodGhpcy5pZCk7XG4gICAgaWYgKCFsaWJDb25maWcgfHwgIWxpYkNvbmZpZy5jYXJvdXNlbEltYWdlQ29uZmlnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBsaWJDb25maWcgYW5kIGNhcm91c2VsSW1hZ2VDb25maWcgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGNvbnN0IGNvbmZpZ0N1cnJlbnRJbWFnZUNhcm91c2VsOiBDYXJvdXNlbEltYWdlQ29uZmlnIHwgdW5kZWZpbmVkID0gbGliQ29uZmlnLmNhcm91c2VsSW1hZ2VDb25maWc7XG4gICAgaWYgKCFjb25maWdDdXJyZW50SW1hZ2VDYXJvdXNlbCB8fCAhY29uZmlnQ3VycmVudEltYWdlQ2Fyb3VzZWwuZGVzY3JpcHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRGVzY3JpcHRpb24gaW5wdXQgbXVzdCBiZSBhIHZhbGlkIG9iamVjdCBpbXBsZW1lbnRpbmcgdGhlIERlc2NyaXB0aW9uIGludGVyZmFjZScpO1xuICAgIH1cbiAgICBpZiAoIWltYWdlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBpbWFnZSBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG5cbiAgICAvLyBJZiBjdXN0b21GdWxsRGVzY3JpcHRpb24gdXNlIGl0LCBvdGhlcndpc2UgcHJvY2VlZCB0byBidWlsZCBhIGRlc2NyaXB0aW9uXG4gICAgaWYgKGNvbmZpZ0N1cnJlbnRJbWFnZUNhcm91c2VsLmRlc2NyaXB0aW9uLmN1c3RvbUZ1bGxEZXNjcmlwdGlvbiAmJiBjb25maWdDdXJyZW50SW1hZ2VDYXJvdXNlbC5kZXNjcmlwdGlvbi5jdXN0b21GdWxsRGVzY3JpcHRpb24gIT09ICcnKSB7XG4gICAgICByZXR1cm4gY29uZmlnQ3VycmVudEltYWdlQ2Fyb3VzZWwuZGVzY3JpcHRpb24uY3VzdG9tRnVsbERlc2NyaXB0aW9uO1xuICAgIH1cblxuICAgIGNvbnN0IGN1cnJlbnRJbmRleDogbnVtYmVyID0gZ2V0SW5kZXgoaW1hZ2UsIHRoaXMuaW1hZ2VzKTtcbiAgICAvLyBJZiB0aGUgY3VycmVudCBpbWFnZSBoYXNuJ3QgYSBkZXNjcmlwdGlvbixcbiAgICAvLyBwcmV2ZW50IHRvIHdyaXRlIHRoZSAnIC0gJyAob3IgdGhpcy5kZXNjcmlwdGlvbi5iZWZvcmVUZXh0RGVzY3JpcHRpb24pXG5cbiAgICBjb25zdCBwcmV2RGVzY3JpcHRpb246IHN0cmluZyA9IGNvbmZpZ0N1cnJlbnRJbWFnZUNhcm91c2VsLmRlc2NyaXB0aW9uLmltYWdlVGV4dCA/IGNvbmZpZ0N1cnJlbnRJbWFnZUNhcm91c2VsLmRlc2NyaXB0aW9uLmltYWdlVGV4dCA6ICcnO1xuICAgIGNvbnN0IG1pZFNlcGFyYXRvcjogc3RyaW5nID0gY29uZmlnQ3VycmVudEltYWdlQ2Fyb3VzZWwuZGVzY3JpcHRpb24ubnVtYmVyU2VwYXJhdG9yID8gY29uZmlnQ3VycmVudEltYWdlQ2Fyb3VzZWwuZGVzY3JpcHRpb24ubnVtYmVyU2VwYXJhdG9yIDogJyc7XG4gICAgY29uc3QgbWlkZGxlRGVzY3JpcHRpb246IHN0cmluZyA9IGN1cnJlbnRJbmRleCArIDEgKyBtaWRTZXBhcmF0b3IgKyB0aGlzLmltYWdlcy5sZW5ndGg7XG5cbiAgICBpZiAoaW1hZ2VXaXRob3V0RGVzY3JpcHRpb24pIHtcbiAgICAgIHJldHVybiBwcmV2RGVzY3JpcHRpb24gKyBtaWRkbGVEZXNjcmlwdGlvbjtcbiAgICB9XG5cbiAgICBjb25zdCBjdXJySW1nRGVzY3JpcHRpb246IHN0cmluZyA9IGltYWdlLm1vZGFsICYmIGltYWdlLm1vZGFsLmRlc2NyaXB0aW9uID8gaW1hZ2UubW9kYWwuZGVzY3JpcHRpb24gOiAnJztcbiAgICBjb25zdCBlbmREZXNjcmlwdGlvbjogc3RyaW5nID0gY29uZmlnQ3VycmVudEltYWdlQ2Fyb3VzZWwuZGVzY3JpcHRpb24uYmVmb3JlVGV4dERlc2NyaXB0aW9uICsgY3VyckltZ0Rlc2NyaXB0aW9uO1xuICAgIHJldHVybiBwcmV2RGVzY3JpcHRpb24gKyBtaWRkbGVEZXNjcmlwdGlvbiArIGVuZERlc2NyaXB0aW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIFByaXZhdGUgbWV0aG9kIHRvIHVwZGF0ZSBib3RoIGBpc0ZpcnN0SW1hZ2VgIGFuZCBgaXNMYXN0SW1hZ2VgIGJhc2VkIG9uXG4gICAqIHRoZSBpbmRleCBvZiB0aGUgY3VycmVudCBpbWFnZS5cbiAgICogQHBhcmFtIG51bWJlciBjdXJyZW50SW5kZXggaXMgdGhlIGluZGV4IG9mIHRoZSBjdXJyZW50IGltYWdlXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZUJvdW5kYXJpZXMoY3VycmVudEluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pbWFnZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICB0aGlzLmlzRmlyc3RJbWFnZSA9IHRydWU7XG4gICAgICB0aGlzLmlzTGFzdEltYWdlID0gdHJ1ZTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgc3dpdGNoIChjdXJyZW50SW5kZXgpIHtcbiAgICAgIGNhc2UgMDpcbiAgICAgICAgLy8gZXhlY3V0ZSB0aGlzIG9ubHkgaWYgaW5maW5pdGUgc2xpZGluZyBpcyBkaXNhYmxlZFxuICAgICAgICB0aGlzLmlzRmlyc3RJbWFnZSA9IHRydWU7XG4gICAgICAgIHRoaXMuaXNMYXN0SW1hZ2UgPSBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIHRoaXMuaW1hZ2VzLmxlbmd0aCAtIDE6XG4gICAgICAgIC8vIGV4ZWN1dGUgdGhpcyBvbmx5IGlmIGluZmluaXRlIHNsaWRpbmcgaXMgZGlzYWJsZWRcbiAgICAgICAgdGhpcy5pc0ZpcnN0SW1hZ2UgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5pc0xhc3RJbWFnZSA9IHRydWU7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhpcy5pc0ZpcnN0SW1hZ2UgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5pc0xhc3RJbWFnZSA9IGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJpdmF0ZSBtZXRob2QgdG8gbWFuYWdlIGJvdW5kYXJ5IGFycm93cyBhbmQgc2xpZGluZy5cbiAgICogVGhpcyBpcyBiYXNlZCBvbiB0aGUgc2xpZGVDb25maWcgaW5wdXQgdG8gZW5hYmxlL2Rpc2FibGUgJ2luZmluaXRlIHNsaWRpbmcnLlxuICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4IG9mIHRoZSB2aXNpYmxlIGltYWdlXG4gICAqL1xuICBwcml2YXRlIG1hbmFnZVNsaWRlQ29uZmlnKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jdXJyZW50SW1hZ2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGN1cnJlbnRJbWFnZSBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgbGV0IGluZGV4OiBudW1iZXI7XG4gICAgdHJ5IHtcbiAgICAgIGluZGV4ID0gZ2V0SW5kZXgodGhpcy5jdXJyZW50SW1hZ2UsIHRoaXMuaW1hZ2VzKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0Nhbm5vdCBnZXQgdGhlIGN1cnJlbnQgaW1hZ2UgaW5kZXggaW4gY3VycmVudC1pbWFnZScpO1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmluZmluaXRlID09PSB0cnVlKSB7XG4gICAgICAvLyBlbmFibGUgaW5maW5pdGUgc2xpZGluZ1xuICAgICAgdGhpcy5pc0ZpcnN0SW1hZ2UgPSBmYWxzZTtcbiAgICAgIHRoaXMuaXNMYXN0SW1hZ2UgPSBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5oYW5kbGVCb3VuZGFyaWVzKGluZGV4KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJpdmF0ZSBtZXRob2QgdG8gZW1pdCBldmVudHMgd2hlbiBlaXRoZXIgdGhlIGxhc3Qgb3IgdGhlIGZpcnN0IGltYWdlIGFyZSB2aXNpYmxlLlxuICAgKiBAcGFyYW0gYWN0aW9uIEVudW0gb2YgdHlwZSBBY3Rpb24gdGhhdCByZXByZXNlbnRzIHRoZSBzb3VyY2Ugb2YgdGhlIGV2ZW50IHRoYXQgY2hhbmdlZCB0aGVcbiAgICogIGN1cnJlbnQgaW1hZ2UgdG8gdGhlIGZpcnN0IG9uZSBvciB0aGUgbGFzdCBvbmUuXG4gICAqIEBwYXJhbSBpbmRleFRvQ2hlY2sgaXMgdGhlIGluZGV4IG51bWJlciBvZiB0aGUgaW1hZ2UgKHRoZSBmaXJzdCBvciB0aGUgbGFzdCBvbmUpLlxuICAgKi9cbiAgcHJpdmF0ZSBlbWl0Qm91bmRhcnlFdmVudChhY3Rpb246IEFjdGlvbiwgaW5kZXhUb0NoZWNrOiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gdG8gZW1pdCBmaXJzdC9sYXN0IGV2ZW50XG4gICAgc3dpdGNoIChpbmRleFRvQ2hlY2spIHtcbiAgICAgIGNhc2UgMDpcbiAgICAgICAgdGhpcy5maXJzdEltYWdlLmVtaXQobmV3IEltYWdlRXZlbnQodGhpcy5pZCwgYWN0aW9uLCB0cnVlKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSB0aGlzLmltYWdlcy5sZW5ndGggLSAxOlxuICAgICAgICB0aGlzLmxhc3RJbWFnZS5lbWl0KG5ldyBJbWFnZUV2ZW50KHRoaXMuaWQsIGFjdGlvbiwgdHJ1ZSkpO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJpdmF0ZSBtZXRob2QgdG8gY2hlY2sgaWYgbmV4dC9wcmV2IGFjdGlvbnMgc2hvdWxkIGJlIGJsb2NrZWQuXG4gICAqIEl0IGNoZWNrcyBpZiBzbGlkZUNvbmZpZy5pbmZpbml0ZSA9PT0gZmFsc2UgYW5kIGlmIHRoZSBpbWFnZSBpbmRleCBpcyBlcXVhbHMgdG8gdGhlIGlucHV0IHBhcmFtZXRlci5cbiAgICogSWYgeWVzLCBpdCByZXR1cm5zIHRydWUgdG8gc2F5IHRoYXQgc2xpZGluZyBzaG91bGQgYmUgYmxvY2tlZCwgb3RoZXJ3aXNlIG5vdC5cbiAgICogQHBhcmFtIG51bWJlciBib3VuZGFyeUluZGV4IHRoYXQgY291bGQgYmUgZWl0aGVyIHRoZSBiZWdpbm5pbmcgaW5kZXggKDApIG9yIHRoZSBsYXN0IGluZGV4XG4gICAqICBvZiBpbWFnZXMgKHRoaXMuaW1hZ2VzLmxlbmd0aCAtIDEpLlxuICAgKiBAcmV0dXJucyBib29sZWFuIHRydWUgaWYgc2xpZGVDb25maWcuaW5maW5pdGUgPT09IGZhbHNlIGFuZCB0aGUgY3VycmVudCBpbmRleCBpc1xuICAgKiAgZWl0aGVyIHRoZSBmaXJzdCBvciB0aGUgbGFzdCBvbmUuXG4gICAqL1xuICBwcml2YXRlIGlzUHJldmVudFNsaWRpbmcoYm91bmRhcnlJbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgaWYgKCF0aGlzLmN1cnJlbnRJbWFnZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gY3VycmVudEltYWdlIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICByZXR1cm4gIXRoaXMuaW5maW5pdGUgJiYgZ2V0SW5kZXgodGhpcy5jdXJyZW50SW1hZ2UsIHRoaXMuaW1hZ2VzKSA9PT0gYm91bmRhcnlJbmRleDtcbiAgfVxufVxuIl19
|