valtech-components 2.0.989 → 2.0.991

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.
@@ -0,0 +1,1065 @@
1
+ import { Component, computed, effect, inject, Input, isDevMode, signal } from '@angular/core';
2
+ import { ActivatedRoute } from '@angular/router';
3
+ import { firstValueFrom } from 'rxjs';
4
+ import { Firestore, doc, getDoc } from '@angular/fire/firestore';
5
+ import { ButtonComponent } from '../../atoms/button/button.component';
6
+ import { DisplayComponent } from '../../atoms/display/display.component';
7
+ import { TextComponent } from '../../atoms/text/text.component';
8
+ import { TitleComponent } from '../../atoms/title/title.component';
9
+ import { EmptyStateComponent } from '../../molecules/empty-state/empty-state.component';
10
+ import { createErrorStateProps } from '../../molecules/empty-state/factory';
11
+ import { MemberCardComponent } from '../../molecules/member-card/member-card.component';
12
+ import { SkeletonLayoutComponent } from '../skeleton-layout/skeleton-layout.component';
13
+ import { ComponentStates } from '../../types';
14
+ import { HasPermissionDirective } from '../../../directives/has-permission.directive';
15
+ import { AuthService } from '../../../services/auth/auth.service';
16
+ import { I18nService } from '../../../services/i18n';
17
+ import { interpretError } from '../../../services/errors/interpret-error';
18
+ import { ModalService } from '../../../services/modal/modal.service';
19
+ import { NavigationService } from '../../../services/navigation/navigation.service';
20
+ import { OrgService } from '../../../services/org/org.service';
21
+ import { connectPageRefresh } from '../../../services/page-refresh/page-refresh.service';
22
+ import { ToastService } from '../../../services/toast.service';
23
+ import { ValtechErrorService } from '../../../services/errors/valtech-error.service';
24
+ import { ConfirmationDialogService } from '../../../services/confirmation-dialog/confirmation-dialog.service';
25
+ import { EditOrgModalComponent } from '../edit-org-modal/edit-org-modal.component';
26
+ import { InviteMemberModalComponent } from '../invite-member-modal/invite-member-modal.component';
27
+ import { MemberDetailModalComponent } from '../member-detail-modal/member-detail-modal.component';
28
+ import { TransferOwnershipModalComponent } from '../transfer-ownership-modal/transfer-ownership-modal.component';
29
+ import { ORGANIZATION_VIEW_I18N } from './organization-view.i18n';
30
+ import * as i0 from "@angular/core";
31
+ const DEFAULT_NAMESPACE = 'Settings.Organization';
32
+ const DEFAULT_VIEW_PERMISSIONS_ROUTE = '/app/settings/permissions';
33
+ const DEFAULT_LEAVE_REDIRECT_ROUTE = '/app/settings/account';
34
+ /**
35
+ * `val-organization-view` — vista Gestión de organización full-feature
36
+ * autocontenida (organism). Promovida desde `showcase` bajo el proceso de
37
+ * ADR-021. Reúne:
38
+ * - **Información** — nombre, descripción, plan y tipo de la org activa; editar
39
+ * vía modal `val-edit-org-modal` (solo si `canEditOrg()`).
40
+ * - **Miembros** — lista paginada (`val-member-card`) enriquecida con perfiles
41
+ * públicos (Firestore); ver detalle vía `val-member-detail-modal`.
42
+ * - **Roles y permisos** — sección explicativa con CTA a la ruta de permisos.
43
+ * - **Invitar** — CTA que abre `val-invite-member-modal` (gateada por `users:*`).
44
+ * - **Transferir propiedad** — `val-transfer-ownership-modal` (solo owner).
45
+ * - **Salir de la organización** — `OrgService.leaveOrg` con confirmación
46
+ * destructiva.
47
+ *
48
+ * **RBAC interno** (decisión CTO, ADR-021): el gating fino se resuelve dentro de
49
+ * la vista vía `AuthService.hasPermission()` + `*valHasPermission` + computeds
50
+ * `isOwner()`/`canManageMembers()`/`canEditOrg()`. NO se expone como config.
51
+ *
52
+ * **Auto-reload en org-switch**: un `effect` reactiona a `activeOrgId()` y recarga
53
+ * org + miembros cuando el usuario cambia de organización activa mientras la vista
54
+ * está montada. El effect cubre también la carga inicial (sin doble carga).
55
+ *
56
+ * NO renderiza ion-content — vive dentro de val-page-wrapper. `ActivatedRoute` se
57
+ * inyecta `{ optional: true }` solo para leer el route data de config (no-op
58
+ * embebido). Auto-registra sus defaults i18n (es/en) si el consumer no proveyó el
59
+ * namespace (default `Settings.Organization`).
60
+ */
61
+ export class OrganizationViewComponent {
62
+ /** Namespace i18n resuelto (capturado para llamadas no-reactivas). */
63
+ get ns() {
64
+ return this.resolvedConfig().i18nNamespace;
65
+ }
66
+ constructor() {
67
+ this.nav = inject(NavigationService);
68
+ this.i18n = inject(I18nService);
69
+ this.auth = inject(AuthService);
70
+ this.orgService = inject(OrgService);
71
+ this.toast = inject(ToastService);
72
+ this.errors = inject(ValtechErrorService);
73
+ this.modalService = inject(ModalService);
74
+ this.firestore = inject(Firestore);
75
+ this.confirmDialog = inject(ConfirmationDialogService);
76
+ this.route = inject(ActivatedRoute, { optional: true });
77
+ this.isDebug = isDevMode();
78
+ this.resolvedConfig = computed(() => {
79
+ const fromRoute = (this.route?.snapshot.data['organizationConfig'] ?? {});
80
+ const merged = { ...fromRoute, ...(this.config ?? {}) };
81
+ return {
82
+ showInfo: merged.showInfo ?? true,
83
+ showMembers: merged.showMembers ?? true,
84
+ showRoles: merged.showRoles ?? true,
85
+ showInvite: merged.showInvite ?? true,
86
+ showTransferOwnership: merged.showTransferOwnership ?? true,
87
+ showLeave: merged.showLeave ?? true,
88
+ i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE,
89
+ viewPermissionsRoute: merged.viewPermissionsRoute ?? DEFAULT_VIEW_PERMISSIONS_ROUTE,
90
+ leaveRedirectRoute: merged.leaveRedirectRoute ?? DEFAULT_LEAVE_REDIRECT_ROUTE,
91
+ onOrgEdited: merged.onOrgEdited,
92
+ onMemberInvited: merged.onMemberInvited,
93
+ onOwnershipTransferred: merged.onOwnershipTransferred,
94
+ onLeftOrg: merged.onLeftOrg,
95
+ };
96
+ });
97
+ this.org = signal(null);
98
+ this.loading = signal(false);
99
+ this.leaving = signal(false);
100
+ this.orgLoadError = signal(null);
101
+ this.orgErrorState = computed(() => {
102
+ this.i18n.lang();
103
+ const err = this.orgLoadError();
104
+ if (!err)
105
+ return null;
106
+ return createErrorStateProps(err, {
107
+ title: { offline: this.tt('offlineTitle'), error: this.tt('errorTitle') },
108
+ description: {
109
+ offline: this.tt('offlineHint'),
110
+ error: interpretError(err).message,
111
+ },
112
+ retryLabel: this.tt('retry'),
113
+ onRetry: () => this.loadOrg(),
114
+ retrying: this.loading(),
115
+ });
116
+ });
117
+ this.members = signal([]);
118
+ this.membersLoading = signal(false);
119
+ this.membersLoadError = signal(null);
120
+ this.membersNextToken = signal(null);
121
+ this.loadingMoreMembers = signal(false);
122
+ this.showAllMembers = signal(false);
123
+ this.visibleMembers = computed(() => (this.showAllMembers() ? this.members() : this.members().slice(0, 3)));
124
+ this.transferring = signal(false);
125
+ this.availableRoles = signal([
126
+ { id: 'viewer', name: 'viewer' },
127
+ { id: 'editor', name: 'editor' },
128
+ { id: 'admin', name: 'admin' },
129
+ ]);
130
+ this.activeOrgId = computed(() => {
131
+ const u = this.auth.user();
132
+ return u?.activeOrgId ?? u?.activeOrg ?? '';
133
+ });
134
+ this.userId = computed(() => this.auth.user()?.userId ?? '');
135
+ this.isOwner = computed(() => {
136
+ const o = this.org();
137
+ const uid = this.userId();
138
+ return !!o && !!uid && o.ownerId === uid;
139
+ });
140
+ this.canEditOrg = computed(() => this.isOwner() || this.auth.hasPermission('org:manage'));
141
+ this.canManageMembers = computed(() => {
142
+ if (this.isOwner())
143
+ return true;
144
+ const uid = this.userId();
145
+ const me = this.members().find(m => m.userId === uid);
146
+ if (!me)
147
+ return false;
148
+ return me.roles.some(r => r === 'admin' || r === 'super_admin');
149
+ });
150
+ this.pageTitle = computed(() => this.tt('pageTitle'));
151
+ this.pageDescription = computed(() => this.tt('pageDescription'));
152
+ this.planLabel = computed(() => {
153
+ const plan = this.org()?.plan;
154
+ if (plan === 'pro')
155
+ return this.tt('planPro');
156
+ if (plan === 'enterprise')
157
+ return this.tt('planEnterprise');
158
+ return this.tt('planFree');
159
+ });
160
+ this.editButtonProps = computed(() => ({
161
+ text: this.tt('editCta'),
162
+ color: 'primary',
163
+ fill: 'outline',
164
+ size: 'small',
165
+ shape: 'round',
166
+ type: 'button',
167
+ }));
168
+ this.leaveButtonProps = computed(() => ({
169
+ text: this.tt('leaveCta'),
170
+ token: 'org-leave',
171
+ color: 'dark',
172
+ fill: 'outline',
173
+ size: 'default',
174
+ shape: 'round',
175
+ type: 'button',
176
+ state: this.isOwner() || this.leaving() ? ComponentStates.DISABLED : ComponentStates.ENABLED,
177
+ }));
178
+ this.transferableMembers = computed(() => this.members().filter(m => m.userId !== this.userId()));
179
+ this.viewPermissionsButtonProps = computed(() => ({
180
+ text: this.tt('rolesViewPerms'),
181
+ color: 'primary',
182
+ fill: 'outline',
183
+ size: 'default',
184
+ shape: 'round',
185
+ type: 'button',
186
+ token: 'org-view-permissions',
187
+ }));
188
+ this.transferButtonProps = computed(() => ({
189
+ text: this.tt('transferCta'),
190
+ token: 'org-transfer-submit',
191
+ color: 'dark',
192
+ fill: 'outline',
193
+ size: 'default',
194
+ shape: 'round',
195
+ type: 'button',
196
+ state: this.transferring() ? ComponentStates.DISABLED : ComponentStates.ENABLED,
197
+ }));
198
+ this.openInviteButtonProps = computed(() => ({
199
+ text: this.tt('inviteOpen'),
200
+ color: 'primary',
201
+ fill: 'solid',
202
+ size: 'default',
203
+ shape: 'round',
204
+ type: 'button',
205
+ }));
206
+ /** Guarda para detectar el primer disparo del effect (evita doble carga). */
207
+ this.lastLoadedOrgId = null;
208
+ const ns = this.ns;
209
+ if (!this.i18n.hasNamespace(ns)) {
210
+ this.i18n.registerContent(ns, ORGANIZATION_VIEW_I18N);
211
+ }
212
+ this.nav.setBackHeader('pageTitle', ns, { withMenu: true });
213
+ // Auto-reload en org-switch: reacciona a activeOrgId() y recarga org + miembros
214
+ // cuando el usuario cambia de organización activa mientras la vista está
215
+ // montada. Cubre también la carga inicial — `lastLoadedOrgId` evita recargar
216
+ // dos veces el mismo id (p.ej. si el effect re-corre por otra dependencia).
217
+ // `allowSignalWrites` porque las load fns escriben signals síncronamente
218
+ // (loading/error/token) — Angular 18 bloquea writes en effect sin el flag.
219
+ effect(() => {
220
+ const orgId = this.activeOrgId();
221
+ if (orgId === this.lastLoadedOrgId)
222
+ return;
223
+ this.lastLoadedOrgId = orgId;
224
+ this.loadOrg();
225
+ this.loadMembers();
226
+ this.loadRoles();
227
+ }, { allowSignalWrites: true });
228
+ connectPageRefresh(async () => {
229
+ await Promise.all([this.loadOrg(), this.loadMembers()]);
230
+ });
231
+ }
232
+ onEdit() {
233
+ void this.modalService.open({
234
+ component: EditOrgModalComponent,
235
+ componentProps: {
236
+ org: this.org(),
237
+ onSuccess: (updated) => {
238
+ this.org.set(updated);
239
+ this.resolvedConfig().onOrgEdited?.();
240
+ },
241
+ },
242
+ breakpoints: {
243
+ breakpoints: [0, 0.85],
244
+ initialBreakpoint: 0.85,
245
+ showHandle: true,
246
+ },
247
+ backdropDismiss: true,
248
+ });
249
+ }
250
+ async onLeave() {
251
+ if (this.isOwner() || this.leaving())
252
+ return;
253
+ const result = await this.confirmDialog.confirmDestructive({
254
+ title: this.tt('leaveTitle'),
255
+ message: this.tt('leaveConfirm'),
256
+ confirmButton: { text: this.tt('leaveCta') },
257
+ cancelButton: { text: this.tt('cancelCta') },
258
+ });
259
+ if (!result.confirmed)
260
+ return;
261
+ const orgId = this.activeOrgId();
262
+ if (!orgId)
263
+ return;
264
+ this.leaving.set(true);
265
+ try {
266
+ await firstValueFrom(this.orgService.leaveOrg(orgId));
267
+ this.toast.show({
268
+ message: this.tt('leaveSuccess'),
269
+ color: 'dark',
270
+ duration: 3500,
271
+ });
272
+ const cfg = this.resolvedConfig();
273
+ this.nav.navigateByUrl(cfg.leaveRedirectRoute);
274
+ cfg.onLeftOrg?.();
275
+ }
276
+ catch (err) {
277
+ this.errors.handle(err, {
278
+ context: 'organization.leave',
279
+ fallbackKey: 'leaveError',
280
+ i18nNamespace: this.ns,
281
+ });
282
+ }
283
+ finally {
284
+ this.leaving.set(false);
285
+ }
286
+ }
287
+ onOpenInvite() {
288
+ void this.modalService.open({
289
+ component: InviteMemberModalComponent,
290
+ componentProps: {
291
+ orgId: this.activeOrgId(),
292
+ existingMemberIds: this.members().map(m => m.userId),
293
+ onSuccess: () => {
294
+ this.loadMembers();
295
+ this.resolvedConfig().onMemberInvited?.();
296
+ },
297
+ },
298
+ breakpoints: {
299
+ breakpoints: [0, 0.92],
300
+ initialBreakpoint: 0.92,
301
+ showHandle: true,
302
+ },
303
+ backdropDismiss: true,
304
+ });
305
+ }
306
+ onViewPermissions() {
307
+ this.nav.navigateByUrl(this.resolvedConfig().viewPermissionsRoute);
308
+ }
309
+ onOpenTransfer() {
310
+ void this.modalService.open({
311
+ component: TransferOwnershipModalComponent,
312
+ componentProps: {
313
+ members: this.transferableMembers(),
314
+ onConfirm: (newOwnerId) => void this.onTransfer(newOwnerId),
315
+ },
316
+ breakpoints: {
317
+ breakpoints: [0, 0.75],
318
+ initialBreakpoint: 0.75,
319
+ showHandle: true,
320
+ },
321
+ backdropDismiss: true,
322
+ });
323
+ }
324
+ async onTransfer(newOwnerId) {
325
+ if (!newOwnerId || this.transferring())
326
+ return;
327
+ const result = await this.confirmDialog.confirmDestructive({
328
+ title: this.tt('transferTitle'),
329
+ message: this.tt('transferConfirm'),
330
+ confirmButton: { text: this.tt('transferCta') },
331
+ cancelButton: { text: this.tt('cancelCta') },
332
+ });
333
+ if (!result.confirmed)
334
+ return;
335
+ const orgId = this.activeOrgId();
336
+ if (!orgId)
337
+ return;
338
+ this.transferring.set(true);
339
+ try {
340
+ await firstValueFrom(this.orgService.transferOwnership(orgId, newOwnerId));
341
+ this.toast.show({
342
+ message: this.tt('transferSuccess'),
343
+ color: 'dark',
344
+ duration: 3500,
345
+ });
346
+ this.loadOrg();
347
+ this.loadMembers();
348
+ this.resolvedConfig().onOwnershipTransferred?.();
349
+ }
350
+ catch (err) {
351
+ this.errors.handle(err, {
352
+ context: 'organization.transfer',
353
+ fallbackKey: 'transferError',
354
+ i18nNamespace: this.ns,
355
+ });
356
+ }
357
+ finally {
358
+ this.transferring.set(false);
359
+ }
360
+ }
361
+ loadOrg() {
362
+ const orgId = this.activeOrgId();
363
+ if (!orgId)
364
+ return Promise.resolve();
365
+ this.loading.set(true);
366
+ this.orgLoadError.set(null);
367
+ return new Promise(resolve => {
368
+ this.orgService.getOrg(orgId).subscribe({
369
+ next: org => {
370
+ this.org.set(org);
371
+ this.loading.set(false);
372
+ resolve();
373
+ },
374
+ error: err => {
375
+ this.orgLoadError.set(err);
376
+ this.loading.set(false);
377
+ resolve();
378
+ },
379
+ });
380
+ });
381
+ }
382
+ loadMembers() {
383
+ const orgId = this.activeOrgId();
384
+ if (!orgId)
385
+ return Promise.resolve();
386
+ this.membersLoading.set(true);
387
+ this.membersNextToken.set(null);
388
+ this.showAllMembers.set(false);
389
+ return new Promise(resolve => {
390
+ this.orgService.getOrgMembers(orgId, { limit: 20 }).subscribe({
391
+ next: async (res) => {
392
+ const cards = await this.enrichWithProfiles(res.members);
393
+ this.members.set(cards);
394
+ this.membersNextToken.set(res.nextToken ?? null);
395
+ this.membersLoading.set(false);
396
+ resolve();
397
+ },
398
+ error: err => {
399
+ this.membersLoadError.set(err);
400
+ this.membersLoading.set(false);
401
+ resolve();
402
+ },
403
+ });
404
+ });
405
+ }
406
+ loadMoreMembers() {
407
+ const orgId = this.activeOrgId();
408
+ const token = this.membersNextToken();
409
+ if (!orgId || !token || this.loadingMoreMembers())
410
+ return;
411
+ this.loadingMoreMembers.set(true);
412
+ this.orgService.getOrgMembers(orgId, { limit: 20, nextToken: token }).subscribe({
413
+ next: async (res) => {
414
+ const cards = await this.enrichWithProfiles(res.members);
415
+ this.members.update(prev => [...prev, ...cards]);
416
+ this.membersNextToken.set(res.nextToken ?? null);
417
+ this.loadingMoreMembers.set(false);
418
+ },
419
+ error: err => {
420
+ this.errors.handle(err, {
421
+ context: 'organization.loadMoreMembers',
422
+ fallbackKey: 'membersError',
423
+ i18nNamespace: this.ns,
424
+ });
425
+ this.loadingMoreMembers.set(false);
426
+ },
427
+ });
428
+ }
429
+ async enrichWithProfiles(members) {
430
+ const results = await Promise.allSettled(members.map(async (m) => {
431
+ try {
432
+ const snap = await getDoc(doc(this.firestore, `profiles/${m.userId}`));
433
+ const p = snap.exists() ? snap.data() : {};
434
+ return {
435
+ ...m,
436
+ handle: p['handle'],
437
+ avatar: (p['avatarUrl'] ?? p['avatar']),
438
+ name: p['name'] || m.name,
439
+ };
440
+ }
441
+ catch {
442
+ return m;
443
+ }
444
+ }));
445
+ return results.map(r => (r.status === 'fulfilled' ? r.value : {}));
446
+ }
447
+ loadRoles() {
448
+ const orgId = this.activeOrgId();
449
+ if (!orgId)
450
+ return;
451
+ this.orgService.listOrgRoles(orgId).subscribe({
452
+ next: roles => {
453
+ if (roles.length)
454
+ this.availableRoles.set(roles);
455
+ },
456
+ });
457
+ }
458
+ roleLabel(roleIdOrName) {
459
+ // Try to find by id first (UUID), then by name
460
+ const found = this.availableRoles().find(r => r.id === roleIdOrName || r.name === roleIdOrName);
461
+ const name = found?.name ?? roleIdOrName;
462
+ const keyMap = {
463
+ viewer: 'roleViewer',
464
+ editor: 'roleEditor',
465
+ admin: 'roleAdmin',
466
+ super_admin: 'roleSuperAdmin',
467
+ };
468
+ const key = keyMap[name] ?? name;
469
+ const label = this.tt(key);
470
+ return label && !label.startsWith('[') ? label : name;
471
+ }
472
+ permissionLabel(perm) {
473
+ if (perm === '*:*')
474
+ return this.tt('permAll');
475
+ const [resource, action] = perm.split(':');
476
+ const resKey = {
477
+ users: 'permUsers',
478
+ documents: 'permDocuments',
479
+ roles: 'permRoles',
480
+ media: 'permMedia',
481
+ templates: 'permTemplates',
482
+ '*': 'permAll',
483
+ };
484
+ const actKey = {
485
+ read: 'permRead',
486
+ write: 'permWrite',
487
+ create: 'permCreate',
488
+ delete: 'permDelete',
489
+ manage: 'permManage',
490
+ '*': 'permAll',
491
+ };
492
+ const res = this.tt(resKey[resource] ?? resource);
493
+ const act = this.tt(actKey[action] ?? action);
494
+ return `${res}: ${act}`;
495
+ }
496
+ onViewMember(member) {
497
+ void this.modalService.open({
498
+ component: MemberDetailModalComponent,
499
+ componentProps: {
500
+ member,
501
+ orgId: this.activeOrgId(),
502
+ availableRoles: this.availableRoles(),
503
+ canManage: this.canManageMembers() && member.userId !== this.userId(),
504
+ isSelf: member.userId === this.userId(),
505
+ onChanged: () => this.loadMembers(),
506
+ },
507
+ breakpoints: {
508
+ breakpoints: [0, 0.7],
509
+ initialBreakpoint: 0.7,
510
+ showHandle: true,
511
+ },
512
+ backdropDismiss: true,
513
+ });
514
+ }
515
+ tt(key) {
516
+ return this.i18n.t(key, this.ns);
517
+ }
518
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrganizationViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
519
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: OrganizationViewComponent, isStandalone: true, selector: "val-organization-view", inputs: { config: "config" }, ngImport: i0, template: `
520
+ <div class="page">
521
+ <header class="page-header">
522
+ <val-display [props]="{ size: 'small', color: 'dark', content: pageTitle() }" />
523
+ <val-title
524
+ [props]="{
525
+ size: 'large',
526
+ color: 'dark',
527
+ bold: false,
528
+ content: pageDescription(),
529
+ }"
530
+ />
531
+ </header>
532
+
533
+ @if (resolvedConfig().showInfo) {
534
+ <!-- Org Info -->
535
+ <section class="settings-section">
536
+ <div class="section-header-row">
537
+ <val-title
538
+ [props]="{
539
+ size: 'medium',
540
+ color: 'dark',
541
+ bold: true,
542
+ content: tt('infoTitle'),
543
+ }"
544
+ />
545
+ @if (canEditOrg()) {
546
+ <val-button [props]="editButtonProps()" (click)="onEdit()" />
547
+ }
548
+ </div>
549
+
550
+ <div class="section-body">
551
+ @if (loading()) {
552
+ <val-skeleton-layout [props]="{ preset: 'detail', rows: 4 }" />
553
+ } @else if (orgErrorState()) {
554
+ <val-empty-state [props]="orgErrorState()!" />
555
+ } @else {
556
+ @if (org(); as o) {
557
+ <div class="org-info-card">
558
+ <div class="org-info-field org-info-field--full">
559
+ <span class="org-info-label">{{ tt('infoName') }}</span>
560
+ <span class="org-info-value">{{ o.name }}</span>
561
+ </div>
562
+ <div class="org-info-field org-info-field--full">
563
+ <span class="org-info-label">{{ tt('infoDescription') }}</span>
564
+ <span class="org-info-value org-info-value--muted">{{ o.description || '—' }}</span>
565
+ </div>
566
+ <div class="org-info-row">
567
+ <div class="org-info-field">
568
+ <span class="org-info-label">{{ tt('infoPlan') }}</span>
569
+ <span class="plan-badge plan-badge--{{ o.plan }}">{{ planLabel() }}</span>
570
+ </div>
571
+ <div class="org-info-field">
572
+ <span class="org-info-label">{{ tt('infoType') }}</span>
573
+ <span class="org-info-value">{{ o.type }}</span>
574
+ </div>
575
+ </div>
576
+ </div>
577
+ }
578
+ }
579
+ </div>
580
+ </section>
581
+ }
582
+
583
+ @if (resolvedConfig().showMembers) {
584
+ <!-- Members -->
585
+ <section class="settings-section">
586
+ <val-title
587
+ [props]="{
588
+ size: 'medium',
589
+ color: 'dark',
590
+ bold: true,
591
+ content: tt('membersTitle'),
592
+ }"
593
+ />
594
+ <div class="section-body">
595
+ @if (membersLoading()) {
596
+ <val-skeleton-layout [props]="{ preset: 'list', rows: 3 }" />
597
+ } @else if (members().length === 0) {
598
+ <val-text
599
+ [props]="{
600
+ content: tt('membersEmpty'),
601
+ size: 'medium',
602
+ color: 'dark',
603
+ bold: false,
604
+ }"
605
+ />
606
+ } @else {
607
+ <div class="members-list">
608
+ @for (m of visibleMembers(); track m.userId) {
609
+ <val-member-card
610
+ [attr.data-testid]="'org-member-' + m.userId"
611
+ [props]="{
612
+ id: m.userId,
613
+ name: m.name,
614
+ handle: m.handle,
615
+ email: m.email,
616
+ avatarUrl: m.avatar,
617
+ roleLabel: m.roles[0] ? roleLabel(m.roles[0]) : '',
618
+ actionAriaLabel: tt('viewMemberCta'),
619
+ }"
620
+ (onAction)="onViewMember(m)"
621
+ />
622
+ }
623
+ </div>
624
+ @if (!showAllMembers() && members().length > 3) {
625
+ <button class="members-show-more" (click)="showAllMembers.set(true)">
626
+ {{ tt('membersShowMore') }} ({{ members().length - 3 }})
627
+ </button>
628
+ }
629
+ @if (showAllMembers() && membersNextToken()) {
630
+ <button class="members-show-more" [disabled]="loadingMoreMembers()" (click)="loadMoreMembers()">
631
+ {{ loadingMoreMembers() ? '…' : tt('membersShowMore') }}
632
+ </button>
633
+ }
634
+ }
635
+ </div>
636
+ </section>
637
+ }
638
+
639
+ @if (resolvedConfig().showRoles) {
640
+ <!-- Roles y permisos: seccion explicativa, detalle en la ruta de permisos -->
641
+ <section class="settings-section">
642
+ <val-title
643
+ [props]="{
644
+ size: 'medium',
645
+ color: 'dark',
646
+ bold: true,
647
+ content: tt('rolesSectionTitle'),
648
+ }"
649
+ />
650
+ <div class="section-body">
651
+ <val-text
652
+ [props]="{
653
+ content: tt('rolesHint'),
654
+ size: 'medium',
655
+ color: 'dark',
656
+ bold: false,
657
+ }"
658
+ />
659
+ <div class="row-actions">
660
+ <val-button [props]="viewPermissionsButtonProps()" (click)="onViewPermissions()" />
661
+ </div>
662
+ </div>
663
+ </section>
664
+ }
665
+
666
+ @if (resolvedConfig().showInvite) {
667
+ <!-- Invite: solo admin+ (gating RBAC interno) -->
668
+ <section *valHasPermission="'users:*'" class="settings-section" data-testid="org-invite-section">
669
+ <div class="invite-cta">
670
+ <div class="invite-cta__text">
671
+ <val-title
672
+ [props]="{
673
+ size: 'medium',
674
+ color: 'dark',
675
+ bold: true,
676
+ content: tt('inviteCtaTitle'),
677
+ }"
678
+ />
679
+ <val-text
680
+ [props]="{
681
+ size: 'medium',
682
+ color: 'dark',
683
+ bold: false,
684
+ content: tt('inviteCtaHint'),
685
+ }"
686
+ />
687
+ </div>
688
+ <val-button [props]="openInviteButtonProps()" (click)="onOpenInvite()" />
689
+ </div>
690
+ </section>
691
+ }
692
+
693
+ @if (resolvedConfig().showTransferOwnership && isOwner()) {
694
+ <!-- Transfer ownership: solo owner (gating RBAC interno) -->
695
+ <section class="settings-section" data-testid="org-transfer-section">
696
+ <val-title
697
+ [props]="{
698
+ size: 'medium',
699
+ color: 'dark',
700
+ bold: true,
701
+ content: tt('transferTitle'),
702
+ }"
703
+ />
704
+ <div class="section-body">
705
+ <val-text
706
+ [props]="{
707
+ content: tt('transferHint'),
708
+ size: 'medium',
709
+ color: 'dark',
710
+ bold: false,
711
+ }"
712
+ />
713
+ @if (transferableMembers().length > 0) {
714
+ <div class="row-actions">
715
+ <val-button [props]="transferButtonProps()" (click)="onOpenTransfer()" />
716
+ </div>
717
+ } @else {
718
+ <val-text
719
+ [props]="{
720
+ content: tt('membersEmpty'),
721
+ size: 'medium',
722
+ color: 'dark',
723
+ bold: false,
724
+ }"
725
+ />
726
+ }
727
+ </div>
728
+ </section>
729
+ }
730
+
731
+ @if (resolvedConfig().showLeave) {
732
+ <!-- Leave org -->
733
+ <section class="settings-section">
734
+ <val-title
735
+ [props]="{
736
+ size: 'medium',
737
+ color: 'dark',
738
+ bold: true,
739
+ content: tt('leaveTitle'),
740
+ }"
741
+ />
742
+ <div class="section-body">
743
+ <val-text
744
+ [props]="{
745
+ content: isOwner() ? tt('leaveOwnerHint') : tt('leaveHint'),
746
+ size: 'medium',
747
+ color: 'dark',
748
+ bold: false,
749
+ }"
750
+ />
751
+ <div class="row-actions">
752
+ <val-button [props]="leaveButtonProps()" (click)="onLeave()" />
753
+ </div>
754
+ </div>
755
+ </section>
756
+ }
757
+
758
+ @if (isDebug) {
759
+ <section class="settings-section rbac-debug">
760
+ <div class="section-header-row">
761
+ <val-title
762
+ [props]="{
763
+ content: 'RBAC (live)',
764
+ size: 'small',
765
+ color: 'medium',
766
+ bold: false,
767
+ }"
768
+ />
769
+ </div>
770
+ <div class="rbac-debug__body">
771
+ <div class="rbac-debug__row">
772
+ <span class="rbac-debug__label">Roles</span>
773
+ <span class="rbac-debug__value">{{ auth.roles().join(', ') || '—' }}</span>
774
+ </div>
775
+ <div class="rbac-debug__row">
776
+ <span class="rbac-debug__label">Permisos</span>
777
+ <span class="rbac-debug__value rbac-debug__value--perms">{{ auth.permissions().join(', ') || '—' }}</span>
778
+ </div>
779
+ </div>
780
+ </section>
781
+ }
782
+ </div>
783
+ `, isInline: true, styles: [".page{padding:16px 0;max-width:720px;margin:0 auto}.page-header{margin-bottom:16px}.settings-section{padding:16px 0}.settings-section+.settings-section{border-top:1px solid var(--val-border-color, rgba(0, 0, 0, .08))}.section-header-row{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}.section-body{display:flex;flex-direction:column;gap:10px}.row-actions{margin-top:12px}.row-actions--gap{display:flex;gap:8px}.invite-cta{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex-wrap:wrap}.invite-cta__text{display:flex;flex-direction:column;gap:4px;flex:1}.org-info-card{border-radius:14px;background:var(--ion-color-light, #f4f5f8);overflow:hidden}:host-context(body.dark) .org-info-card,:host-context(html.ion-palette-dark) .org-info-card,:host-context([data-theme=\"dark\"]) .org-info-card{background:#ffffff0d}.org-info-field{padding:12px 16px;display:flex;flex-direction:column;gap:4px;border-bottom:1px solid var(--val-border-color, rgba(0, 0, 0, .06))}.org-info-field--full{width:100%}.org-info-field:last-child{border-bottom:none}.org-info-row{display:flex}.org-info-row .org-info-field{flex:1}.org-info-row .org-info-field:first-child{border-right:1px solid var(--val-border-color, rgba(0, 0, 0, .06))}.org-info-label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--ion-color-medium)}.org-info-value{font-size:.95rem;font-weight:500;color:var(--ion-color-dark)}.org-info-value--muted{color:var(--ion-color-medium);font-weight:400}.plan-badge{display:inline-block;font-size:.78rem;font-weight:700;padding:3px 10px;border-radius:20px;width:fit-content}.plan-badge--free{background:var(--ion-color-light-shade, #d7d8da);color:var(--ion-color-dark)}.plan-badge--pro{background:var(--ion-color-primary);color:#fff}.plan-badge--enterprise{background:#f5c542;color:#222}.members-list{display:flex;flex-direction:column;gap:8px}.members-show-more{background:none;border:none;color:var(--ion-color-primary);font-size:14px;font-weight:500;cursor:pointer;padding:8px 0}.rbac-debug{opacity:.7}.rbac-debug__body{display:flex;flex-direction:column;gap:6px;font-family:monospace;font-size:.78rem}.rbac-debug__row{display:flex;gap:8px;align-items:flex-start}.rbac-debug__label{color:var(--ion-color-medium);min-width:72px;flex-shrink:0}.rbac-debug__value{color:var(--ion-color-dark);word-break:break-all}.rbac-debug__value--perms{color:var(--ion-color-medium)}\n"], dependencies: [{ kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: EmptyStateComponent, selector: "val-empty-state", inputs: ["props"] }, { kind: "directive", type: HasPermissionDirective, selector: "[valHasPermission]", inputs: ["valHasPermission"] }, { kind: "component", type: SkeletonLayoutComponent, selector: "val-skeleton-layout", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }, { kind: "component", type: MemberCardComponent, selector: "val-member-card", inputs: ["props"], outputs: ["onAction"] }] }); }
784
+ }
785
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrganizationViewComponent, decorators: [{
786
+ type: Component,
787
+ args: [{ selector: 'val-organization-view', standalone: true, imports: [
788
+ DisplayComponent,
789
+ EmptyStateComponent,
790
+ HasPermissionDirective,
791
+ SkeletonLayoutComponent,
792
+ TitleComponent,
793
+ TextComponent,
794
+ ButtonComponent,
795
+ MemberCardComponent,
796
+ TransferOwnershipModalComponent,
797
+ ], template: `
798
+ <div class="page">
799
+ <header class="page-header">
800
+ <val-display [props]="{ size: 'small', color: 'dark', content: pageTitle() }" />
801
+ <val-title
802
+ [props]="{
803
+ size: 'large',
804
+ color: 'dark',
805
+ bold: false,
806
+ content: pageDescription(),
807
+ }"
808
+ />
809
+ </header>
810
+
811
+ @if (resolvedConfig().showInfo) {
812
+ <!-- Org Info -->
813
+ <section class="settings-section">
814
+ <div class="section-header-row">
815
+ <val-title
816
+ [props]="{
817
+ size: 'medium',
818
+ color: 'dark',
819
+ bold: true,
820
+ content: tt('infoTitle'),
821
+ }"
822
+ />
823
+ @if (canEditOrg()) {
824
+ <val-button [props]="editButtonProps()" (click)="onEdit()" />
825
+ }
826
+ </div>
827
+
828
+ <div class="section-body">
829
+ @if (loading()) {
830
+ <val-skeleton-layout [props]="{ preset: 'detail', rows: 4 }" />
831
+ } @else if (orgErrorState()) {
832
+ <val-empty-state [props]="orgErrorState()!" />
833
+ } @else {
834
+ @if (org(); as o) {
835
+ <div class="org-info-card">
836
+ <div class="org-info-field org-info-field--full">
837
+ <span class="org-info-label">{{ tt('infoName') }}</span>
838
+ <span class="org-info-value">{{ o.name }}</span>
839
+ </div>
840
+ <div class="org-info-field org-info-field--full">
841
+ <span class="org-info-label">{{ tt('infoDescription') }}</span>
842
+ <span class="org-info-value org-info-value--muted">{{ o.description || '—' }}</span>
843
+ </div>
844
+ <div class="org-info-row">
845
+ <div class="org-info-field">
846
+ <span class="org-info-label">{{ tt('infoPlan') }}</span>
847
+ <span class="plan-badge plan-badge--{{ o.plan }}">{{ planLabel() }}</span>
848
+ </div>
849
+ <div class="org-info-field">
850
+ <span class="org-info-label">{{ tt('infoType') }}</span>
851
+ <span class="org-info-value">{{ o.type }}</span>
852
+ </div>
853
+ </div>
854
+ </div>
855
+ }
856
+ }
857
+ </div>
858
+ </section>
859
+ }
860
+
861
+ @if (resolvedConfig().showMembers) {
862
+ <!-- Members -->
863
+ <section class="settings-section">
864
+ <val-title
865
+ [props]="{
866
+ size: 'medium',
867
+ color: 'dark',
868
+ bold: true,
869
+ content: tt('membersTitle'),
870
+ }"
871
+ />
872
+ <div class="section-body">
873
+ @if (membersLoading()) {
874
+ <val-skeleton-layout [props]="{ preset: 'list', rows: 3 }" />
875
+ } @else if (members().length === 0) {
876
+ <val-text
877
+ [props]="{
878
+ content: tt('membersEmpty'),
879
+ size: 'medium',
880
+ color: 'dark',
881
+ bold: false,
882
+ }"
883
+ />
884
+ } @else {
885
+ <div class="members-list">
886
+ @for (m of visibleMembers(); track m.userId) {
887
+ <val-member-card
888
+ [attr.data-testid]="'org-member-' + m.userId"
889
+ [props]="{
890
+ id: m.userId,
891
+ name: m.name,
892
+ handle: m.handle,
893
+ email: m.email,
894
+ avatarUrl: m.avatar,
895
+ roleLabel: m.roles[0] ? roleLabel(m.roles[0]) : '',
896
+ actionAriaLabel: tt('viewMemberCta'),
897
+ }"
898
+ (onAction)="onViewMember(m)"
899
+ />
900
+ }
901
+ </div>
902
+ @if (!showAllMembers() && members().length > 3) {
903
+ <button class="members-show-more" (click)="showAllMembers.set(true)">
904
+ {{ tt('membersShowMore') }} ({{ members().length - 3 }})
905
+ </button>
906
+ }
907
+ @if (showAllMembers() && membersNextToken()) {
908
+ <button class="members-show-more" [disabled]="loadingMoreMembers()" (click)="loadMoreMembers()">
909
+ {{ loadingMoreMembers() ? '…' : tt('membersShowMore') }}
910
+ </button>
911
+ }
912
+ }
913
+ </div>
914
+ </section>
915
+ }
916
+
917
+ @if (resolvedConfig().showRoles) {
918
+ <!-- Roles y permisos: seccion explicativa, detalle en la ruta de permisos -->
919
+ <section class="settings-section">
920
+ <val-title
921
+ [props]="{
922
+ size: 'medium',
923
+ color: 'dark',
924
+ bold: true,
925
+ content: tt('rolesSectionTitle'),
926
+ }"
927
+ />
928
+ <div class="section-body">
929
+ <val-text
930
+ [props]="{
931
+ content: tt('rolesHint'),
932
+ size: 'medium',
933
+ color: 'dark',
934
+ bold: false,
935
+ }"
936
+ />
937
+ <div class="row-actions">
938
+ <val-button [props]="viewPermissionsButtonProps()" (click)="onViewPermissions()" />
939
+ </div>
940
+ </div>
941
+ </section>
942
+ }
943
+
944
+ @if (resolvedConfig().showInvite) {
945
+ <!-- Invite: solo admin+ (gating RBAC interno) -->
946
+ <section *valHasPermission="'users:*'" class="settings-section" data-testid="org-invite-section">
947
+ <div class="invite-cta">
948
+ <div class="invite-cta__text">
949
+ <val-title
950
+ [props]="{
951
+ size: 'medium',
952
+ color: 'dark',
953
+ bold: true,
954
+ content: tt('inviteCtaTitle'),
955
+ }"
956
+ />
957
+ <val-text
958
+ [props]="{
959
+ size: 'medium',
960
+ color: 'dark',
961
+ bold: false,
962
+ content: tt('inviteCtaHint'),
963
+ }"
964
+ />
965
+ </div>
966
+ <val-button [props]="openInviteButtonProps()" (click)="onOpenInvite()" />
967
+ </div>
968
+ </section>
969
+ }
970
+
971
+ @if (resolvedConfig().showTransferOwnership && isOwner()) {
972
+ <!-- Transfer ownership: solo owner (gating RBAC interno) -->
973
+ <section class="settings-section" data-testid="org-transfer-section">
974
+ <val-title
975
+ [props]="{
976
+ size: 'medium',
977
+ color: 'dark',
978
+ bold: true,
979
+ content: tt('transferTitle'),
980
+ }"
981
+ />
982
+ <div class="section-body">
983
+ <val-text
984
+ [props]="{
985
+ content: tt('transferHint'),
986
+ size: 'medium',
987
+ color: 'dark',
988
+ bold: false,
989
+ }"
990
+ />
991
+ @if (transferableMembers().length > 0) {
992
+ <div class="row-actions">
993
+ <val-button [props]="transferButtonProps()" (click)="onOpenTransfer()" />
994
+ </div>
995
+ } @else {
996
+ <val-text
997
+ [props]="{
998
+ content: tt('membersEmpty'),
999
+ size: 'medium',
1000
+ color: 'dark',
1001
+ bold: false,
1002
+ }"
1003
+ />
1004
+ }
1005
+ </div>
1006
+ </section>
1007
+ }
1008
+
1009
+ @if (resolvedConfig().showLeave) {
1010
+ <!-- Leave org -->
1011
+ <section class="settings-section">
1012
+ <val-title
1013
+ [props]="{
1014
+ size: 'medium',
1015
+ color: 'dark',
1016
+ bold: true,
1017
+ content: tt('leaveTitle'),
1018
+ }"
1019
+ />
1020
+ <div class="section-body">
1021
+ <val-text
1022
+ [props]="{
1023
+ content: isOwner() ? tt('leaveOwnerHint') : tt('leaveHint'),
1024
+ size: 'medium',
1025
+ color: 'dark',
1026
+ bold: false,
1027
+ }"
1028
+ />
1029
+ <div class="row-actions">
1030
+ <val-button [props]="leaveButtonProps()" (click)="onLeave()" />
1031
+ </div>
1032
+ </div>
1033
+ </section>
1034
+ }
1035
+
1036
+ @if (isDebug) {
1037
+ <section class="settings-section rbac-debug">
1038
+ <div class="section-header-row">
1039
+ <val-title
1040
+ [props]="{
1041
+ content: 'RBAC (live)',
1042
+ size: 'small',
1043
+ color: 'medium',
1044
+ bold: false,
1045
+ }"
1046
+ />
1047
+ </div>
1048
+ <div class="rbac-debug__body">
1049
+ <div class="rbac-debug__row">
1050
+ <span class="rbac-debug__label">Roles</span>
1051
+ <span class="rbac-debug__value">{{ auth.roles().join(', ') || '—' }}</span>
1052
+ </div>
1053
+ <div class="rbac-debug__row">
1054
+ <span class="rbac-debug__label">Permisos</span>
1055
+ <span class="rbac-debug__value rbac-debug__value--perms">{{ auth.permissions().join(', ') || '—' }}</span>
1056
+ </div>
1057
+ </div>
1058
+ </section>
1059
+ }
1060
+ </div>
1061
+ `, styles: [".page{padding:16px 0;max-width:720px;margin:0 auto}.page-header{margin-bottom:16px}.settings-section{padding:16px 0}.settings-section+.settings-section{border-top:1px solid var(--val-border-color, rgba(0, 0, 0, .08))}.section-header-row{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}.section-body{display:flex;flex-direction:column;gap:10px}.row-actions{margin-top:12px}.row-actions--gap{display:flex;gap:8px}.invite-cta{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex-wrap:wrap}.invite-cta__text{display:flex;flex-direction:column;gap:4px;flex:1}.org-info-card{border-radius:14px;background:var(--ion-color-light, #f4f5f8);overflow:hidden}:host-context(body.dark) .org-info-card,:host-context(html.ion-palette-dark) .org-info-card,:host-context([data-theme=\"dark\"]) .org-info-card{background:#ffffff0d}.org-info-field{padding:12px 16px;display:flex;flex-direction:column;gap:4px;border-bottom:1px solid var(--val-border-color, rgba(0, 0, 0, .06))}.org-info-field--full{width:100%}.org-info-field:last-child{border-bottom:none}.org-info-row{display:flex}.org-info-row .org-info-field{flex:1}.org-info-row .org-info-field:first-child{border-right:1px solid var(--val-border-color, rgba(0, 0, 0, .06))}.org-info-label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--ion-color-medium)}.org-info-value{font-size:.95rem;font-weight:500;color:var(--ion-color-dark)}.org-info-value--muted{color:var(--ion-color-medium);font-weight:400}.plan-badge{display:inline-block;font-size:.78rem;font-weight:700;padding:3px 10px;border-radius:20px;width:fit-content}.plan-badge--free{background:var(--ion-color-light-shade, #d7d8da);color:var(--ion-color-dark)}.plan-badge--pro{background:var(--ion-color-primary);color:#fff}.plan-badge--enterprise{background:#f5c542;color:#222}.members-list{display:flex;flex-direction:column;gap:8px}.members-show-more{background:none;border:none;color:var(--ion-color-primary);font-size:14px;font-weight:500;cursor:pointer;padding:8px 0}.rbac-debug{opacity:.7}.rbac-debug__body{display:flex;flex-direction:column;gap:6px;font-family:monospace;font-size:.78rem}.rbac-debug__row{display:flex;gap:8px;align-items:flex-start}.rbac-debug__label{color:var(--ion-color-medium);min-width:72px;flex-shrink:0}.rbac-debug__value{color:var(--ion-color-dark);word-break:break-all}.rbac-debug__value--perms{color:var(--ion-color-medium)}\n"] }]
1062
+ }], ctorParameters: () => [], propDecorators: { config: [{
1063
+ type: Input
1064
+ }] } });
1065
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JnYW5pemF0aW9uLXZpZXcuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL29yZ2FuaXNtcy9vcmdhbml6YXRpb24tdmlldy9vcmdhbml6YXRpb24tdmlldy5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM5RixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDakQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN0QyxPQUFPLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUVqRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDdEUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDekUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2hFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNuRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxtREFBbUQsQ0FBQztBQUV4RixPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUM1RSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxtREFBbUQsQ0FBQztBQUN4RixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSw4Q0FBOEMsQ0FBQztBQUN2RixPQUFPLEVBQWtCLGVBQWUsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUU5RCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSw4Q0FBOEMsQ0FBQztBQUV0RixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDbEUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwwQ0FBMEMsQ0FBQztBQUMxRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDckUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0saURBQWlELENBQUM7QUFDcEYsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBRS9ELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHFEQUFxRCxDQUFDO0FBQ3pGLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUMvRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxnREFBZ0QsQ0FBQztBQUNyRixPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxtRUFBbUUsQ0FBQztBQUU5RyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSw0Q0FBNEMsQ0FBQztBQUNuRixPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxzREFBc0QsQ0FBQztBQUNsRyxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxzREFBc0QsQ0FBQztBQUVsRyxPQUFPLEVBQUUsK0JBQStCLEVBQUUsTUFBTSxnRUFBZ0UsQ0FBQztBQUdqSCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7QUFFbEUsTUFBTSxpQkFBaUIsR0FBRyx1QkFBdUIsQ0FBQztBQUNsRCxNQUFNLDhCQUE4QixHQUFHLDJCQUEyQixDQUFDO0FBQ25FLE1BQU0sNEJBQTRCLEdBQUcsdUJBQXVCLENBQUM7QUFFN0Q7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMEJHO0FBd2JILE1BQU0sT0FBTyx5QkFBeUI7SUE0Q3BDLHNFQUFzRTtJQUN0RSxJQUFZLEVBQUU7UUFDWixPQUFPLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQyxhQUFhLENBQUM7SUFDN0MsQ0FBQztJQWdJRDtRQTlLUSxRQUFHLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDaEMsU0FBSSxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMxQixTQUFJLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQzVCLGVBQVUsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDaEMsVUFBSyxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUM3QixXQUFNLEdBQUcsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFDckMsaUJBQVksR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDcEMsY0FBUyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM5QixrQkFBYSxHQUFHLE1BQU0sQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO1FBQ2xELFVBQUssR0FBRyxNQUFNLENBQUMsY0FBYyxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFFbEQsWUFBTyxHQUFHLFNBQVMsRUFBRSxDQUFDO1FBU3RCLG1CQUFjLEdBQUcsUUFBUSxDQUdoQyxHQUFHLEVBQUU7WUFDTCxNQUFNLFNBQVMsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsQ0FBMkIsQ0FBQztZQUNwRyxNQUFNLE1BQU0sR0FBMkIsRUFBRSxHQUFHLFNBQVMsRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQ2hGLE9BQU87Z0JBQ0wsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRLElBQUksSUFBSTtnQkFDakMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXLElBQUksSUFBSTtnQkFDdkMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTLElBQUksSUFBSTtnQkFDbkMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxVQUFVLElBQUksSUFBSTtnQkFDckMscUJBQXFCLEVBQUUsTUFBTSxDQUFDLHFCQUFxQixJQUFJLElBQUk7Z0JBQzNELFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxJQUFJLElBQUk7Z0JBQ25DLGFBQWEsRUFBRSxNQUFNLENBQUMsYUFBYSxJQUFJLGlCQUFpQjtnQkFDeEQsb0JBQW9CLEVBQUUsTUFBTSxDQUFDLG9CQUFvQixJQUFJLDhCQUE4QjtnQkFDbkYsa0JBQWtCLEVBQUUsTUFBTSxDQUFDLGtCQUFrQixJQUFJLDRCQUE0QjtnQkFDN0UsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXO2dCQUMvQixlQUFlLEVBQUUsTUFBTSxDQUFDLGVBQWU7Z0JBQ3ZDLHNCQUFzQixFQUFFLE1BQU0sQ0FBQyxzQkFBc0I7Z0JBQ3JELFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUzthQUM1QixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFPTSxRQUFHLEdBQUcsTUFBTSxDQUFzQixJQUFJLENBQUMsQ0FBQztRQUN4QyxZQUFPLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3hCLFlBQU8sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDaEIsaUJBQVksR0FBRyxNQUFNLENBQVUsSUFBSSxDQUFDLENBQUM7UUFFN0Msa0JBQWEsR0FBRyxRQUFRLENBQTRCLEdBQUcsRUFBRTtZQUNoRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2pCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNoQyxJQUFJLENBQUMsR0FBRztnQkFBRSxPQUFPLElBQUksQ0FBQztZQUN0QixPQUFPLHFCQUFxQixDQUFDLEdBQUcsRUFBRTtnQkFDaEMsS0FBSyxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLEVBQUU7Z0JBQ3pFLFdBQVcsRUFBRTtvQkFDWCxPQUFPLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUM7b0JBQy9CLEtBQUssRUFBRSxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTztpQkFDbkM7Z0JBQ0QsVUFBVSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDO2dCQUM1QixPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRTtnQkFDN0IsUUFBUSxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUU7YUFDekIsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7UUFFTSxZQUFPLEdBQUcsTUFBTSxDQUFpQixFQUFFLENBQUMsQ0FBQztRQUNyQyxtQkFBYyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN2QixxQkFBZ0IsR0FBRyxNQUFNLENBQVUsSUFBSSxDQUFDLENBQUM7UUFDakQscUJBQWdCLEdBQUcsTUFBTSxDQUFnQixJQUFJLENBQUMsQ0FBQztRQUMvQyx1QkFBa0IsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbkMsbUJBQWMsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDL0IsbUJBQWMsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3ZHLGlCQUFZLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzdCLG1CQUFjLEdBQUcsTUFBTSxDQUFZO1lBQzFDLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFO1lBQ2hDLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFO1lBQ2hDLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFO1NBQy9CLENBQUMsQ0FBQztRQUVNLGdCQUFXLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRTtZQUNuQyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFHaEIsQ0FBQztZQUNULE9BQU8sQ0FBQyxFQUFFLFdBQVcsSUFBSSxDQUFDLEVBQUUsU0FBUyxJQUFJLEVBQUUsQ0FBQztRQUM5QyxDQUFDLENBQUMsQ0FBQztRQUVNLFdBQU0sR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRSxNQUFNLElBQUksRUFBRSxDQUFDLENBQUM7UUFFeEQsWUFBTyxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUU7WUFDL0IsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ3JCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUMxQixPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsT0FBTyxLQUFLLEdBQUcsQ0FBQztRQUMzQyxDQUFDLENBQUMsQ0FBQztRQUVNLGVBQVUsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUM7UUFFckYscUJBQWdCLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRTtZQUN4QyxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7Z0JBQUUsT0FBTyxJQUFJLENBQUM7WUFDaEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzFCLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDO1lBQ3RELElBQUksQ0FBQyxFQUFFO2dCQUFFLE9BQU8sS0FBSyxDQUFDO1lBQ3RCLE9BQU8sRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssT0FBTyxJQUFJLENBQUMsS0FBSyxhQUFhLENBQUMsQ0FBQztRQUNsRSxDQUFDLENBQUMsQ0FBQztRQUVNLGNBQVMsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO1FBQ2pELG9CQUFlLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO1FBRTdELGNBQVMsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFO1lBQ2pDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsRUFBRSxJQUFJLENBQUM7WUFDOUIsSUFBSSxJQUFJLEtBQUssS0FBSztnQkFBRSxPQUFPLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDOUMsSUFBSSxJQUFJLEtBQUssWUFBWTtnQkFBRSxPQUFPLElBQUksQ0FBQyxFQUFFLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztZQUM1RCxPQUFPLElBQUksQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDN0IsQ0FBQyxDQUFDLENBQUM7UUFFTSxvQkFBZSxHQUFHLFFBQVEsQ0FBMEIsR0FBRyxFQUFFLENBQUMsQ0FBQztZQUNsRSxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUM7WUFDeEIsS0FBSyxFQUFFLFNBQVM7WUFDaEIsSUFBSSxFQUFFLFNBQVM7WUFDZixJQUFJLEVBQUUsT0FBTztZQUNiLEtBQUssRUFBRSxPQUFPO1lBQ2QsSUFBSSxFQUFFLFFBQVE7U0FDZixDQUFDLENBQUMsQ0FBQztRQUVLLHFCQUFnQixHQUFHLFFBQVEsQ0FBMEIsR0FBRyxFQUFFLENBQUMsQ0FBQztZQUNuRSxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUM7WUFDekIsS0FBSyxFQUFFLFdBQVc7WUFDbEIsS0FBSyxFQUFFLE1BQU07WUFDYixJQUFJLEVBQUUsU0FBUztZQUNmLElBQUksRUFBRSxTQUFTO1lBQ2YsS0FBSyxFQUFFLE9BQU87WUFDZCxJQUFJLEVBQUUsUUFBUTtZQUNkLEtBQUssRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxlQUFlLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxlQUFlLENBQUMsT0FBTztTQUM3RixDQUFDLENBQUMsQ0FBQztRQUVLLHdCQUFtQixHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sS0FBSyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRTdGLCtCQUEwQixHQUFHLFFBQVEsQ0FBMEIsR0FBRyxFQUFFLENBQUMsQ0FBQztZQUM3RSxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQztZQUMvQixLQUFLLEVBQUUsU0FBUztZQUNoQixJQUFJLEVBQUUsU0FBUztZQUNmLElBQUksRUFBRSxTQUFTO1lBQ2YsS0FBSyxFQUFFLE9BQU87WUFDZCxJQUFJLEVBQUUsUUFBUTtZQUNkLEtBQUssRUFBRSxzQkFBc0I7U0FDOUIsQ0FBQyxDQUFDLENBQUM7UUFFSyx3QkFBbUIsR0FBRyxRQUFRLENBQTBCLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFDdEUsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDO1lBQzVCLEtBQUssRUFBRSxxQkFBcUI7WUFDNUIsS0FBSyxFQUFFLE1BQU07WUFDYixJQUFJLEVBQUUsU0FBUztZQUNmLElBQUksRUFBRSxTQUFTO1lBQ2YsS0FBSyxFQUFFLE9BQU87WUFDZCxJQUFJLEVBQUUsUUFBUTtZQUNkLEtBQUssRUFBRSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxPQUFPO1NBQ2hGLENBQUMsQ0FBQyxDQUFDO1FBRUssMEJBQXFCLEdBQUcsUUFBUSxDQUEwQixHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBQ3hFLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQztZQUMzQixLQUFLLEVBQUUsU0FBUztZQUNoQixJQUFJLEVBQUUsT0FBTztZQUNiLElBQUksRUFBRSxTQUFTO1lBQ2YsS0FBSyxFQUFFLE9BQU87WUFDZCxJQUFJLEVBQUUsUUFBUTtTQUNmLENBQUMsQ0FBQyxDQUFDO1FBRUosNkVBQTZFO1FBQ3JFLG9CQUFlLEdBQWtCLElBQUksQ0FBQztRQUc1QyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ25CLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLEVBQUUsRUFBRSxzQkFBc0IsQ0FBQyxDQUFDO1FBQ3hELENBQUM7UUFDRCxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxXQUFXLEVBQUUsRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFFNUQsZ0ZBQWdGO1FBQ2hGLHlFQUF5RTtRQUN6RSw2RUFBNkU7UUFDN0UsNEVBQTRFO1FBQzVFLHlFQUF5RTtRQUN6RSwyRUFBMkU7UUFDM0UsTUFBTSxDQUNKLEdBQUcsRUFBRTtZQUNILE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNqQyxJQUFJLEtBQUssS0FBSyxJQUFJLENBQUMsZUFBZTtnQkFBRSxPQUFPO1lBQzNDLElBQUksQ0FBQyxlQUFlLEdBQUcsS0FBSyxDQUFDO1lBQzdCLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNmLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNuQixJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDbkIsQ0FBQyxFQUNELEVBQUUsaUJBQWlCLEVBQUUsSUFBSSxFQUFFLENBQzVCLENBQUM7UUFFRixrQkFBa0IsQ0FBQyxLQUFLLElBQUksRUFBRTtZQUM1QixNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUMxRCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxNQUFNO1FBQ0osS0FBSyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQztZQUMxQixTQUFTLEVBQUUscUJBQXFCO1lBQ2hDLGNBQWMsRUFBRTtnQkFDZCxHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTtnQkFDZixTQUFTLEVBQUUsQ0FBQyxPQUFxQixFQUFFLEVBQUU7b0JBQ25DLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO29CQUN0QixJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQztnQkFDeEMsQ0FBQzthQUNGO1lBQ0QsV0FBVyxFQUFFO2dCQUNYLFdBQVcsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUM7Z0JBQ3RCLGlCQUFpQixFQUFFLElBQUk7Z0JBQ3ZCLFVBQVUsRUFBRSxJQUFJO2FBQ2pCO1lBQ0QsZUFBZSxFQUFFLElBQUk7U0FDdEIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELEtBQUssQ0FBQyxPQUFPO1FBQ1gsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUFFLE9BQU87UUFDN0MsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLGtCQUFrQixDQUFDO1lBQ3pELEtBQUssRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQztZQUM1QixPQUFPLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxjQUFjLENBQUM7WUFDaEMsYUFBYSxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUU7WUFDNUMsWUFBWSxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsV0FBVyxDQUFDLEVBQUU7U0FDN0MsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTO1lBQUUsT0FBTztRQUM5QixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDakMsSUFBSSxDQUFDLEtBQUs7WUFBRSxPQUFPO1FBQ25CLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3ZCLElBQUksQ0FBQztZQUNILE1BQU0sY0FBYyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDdEQsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUM7Z0JBQ2QsT0FBTyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDO2dCQUNoQyxLQUFLLEVBQUUsTUFBTTtnQkFDYixRQUFRLEVBQUUsSUFBSTthQUNmLENBQUMsQ0FBQztZQUNILE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUNsQyxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsQ0FBQztZQUMvQyxHQUFHLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQztRQUNwQixDQUFDO1FBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztZQUNiLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRTtnQkFDdEIsT0FBTyxFQUFFLG9CQUFvQjtnQkFDN0IsV0FBVyxFQUFFLFlBQVk7Z0JBQ3pCLGFBQWEsRUFBRSxJQUFJLENBQUMsRUFBRTthQUN2QixDQUFDLENBQUM7UUFDTCxDQUFDO2dCQUFTLENBQUM7WUFDVCxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMxQixDQUFDO0lBQ0gsQ0FBQztJQUVELFlBQVk7UUFDVixLQUFLLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDO1lBQzFCLFNBQVMsRUFBRSwwQkFBMEI7WUFDckMsY0FBYyxFQUFFO2dCQUNkLEtBQUssRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFO2dCQUN6QixpQkFBaUIsRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztnQkFDcEQsU0FBUyxFQUFFLEdBQUcsRUFBRTtvQkFDZCxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7b0JBQ25CLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQyxlQUFlLEVBQUUsRUFBRSxDQUFDO2dCQUM1QyxDQUFDO2FBQ0Y7WUFDRCxXQUFXLEVBQUU7Z0JBQ1gsV0FBVyxFQUFFLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQztnQkFDdEIsaUJBQWlCLEVBQUUsSUFBSTtnQkFDdkIsVUFBVSxFQUFFLElBQUk7YUFDakI7WUFDRCxlQUFlLEVBQUUsSUFBSTtTQUN0QixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsaUJBQWlCO1FBQ2YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDLG9CQUFvQixDQUFDLENBQUM7SUFDckUsQ0FBQztJQUVELGNBQWM7UUFDWixLQUFLLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDO1lBQzFCLFNBQVMsRUFBRSwrQkFBK0I7WUFDMUMsY0FBYyxFQUFFO2dCQUNkLE9BQU8sRUFBRSxJQUFJLENBQUMsbUJBQW1CLEVBQUU7Z0JBQ25DLFNBQVMsRUFBRSxDQUFDLFVBQWtCLEVBQUUsRUFBRSxDQUFDLEtBQUssSUFBSSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUM7YUFDcEU7WUFDRCxXQUFXLEVBQUU7Z0JBQ1gsV0FBVyxFQUFFLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQztnQkFDdEIsaUJBQWlCLEVBQUUsSUFBSTtnQkFDdkIsVUFBVSxFQUFFLElBQUk7YUFDakI7WUFDRCxlQUFlLEVBQUUsSUFBSTtTQUN0QixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsS0FBSyxDQUFDLFVBQVUsQ0FBQyxVQUFrQjtRQUNqQyxJQUFJLENBQUMsVUFBVSxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUU7WUFBRSxPQUFPO1FBQy9DLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxrQkFBa0IsQ0FBQztZQUN6RCxLQUFLLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxlQUFlLENBQUM7WUFDL0IsT0FBTyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsaUJBQWlCLENBQUM7WUFDbkMsYUFBYSxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDLEVBQUU7WUFDL0MsWUFBWSxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsV0FBVyxDQUFDLEVBQUU7U0FDN0MsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTO1lBQUUsT0FBTztRQUM5QixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDakMsSUFBSSxDQUFDLEtBQUs7WUFBRSxPQUFPO1FBQ25CLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzVCLElBQUksQ0FBQztZQUNILE1BQU0sY0FBYyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsaUJBQWlCLENBQUMsS0FBSyxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUM7WUFDM0UsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUM7Z0JBQ2QsT0FBTyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsaUJBQWlCLENBQUM7Z0JBQ25DLEtBQUssRUFBRSxNQUFNO2dCQUNiLFFBQVEsRUFBRSxJQUFJO2FBQ2YsQ0FBQyxDQUFDO1lBQ0gsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2YsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ25CLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQyxzQkFBc0IsRUFBRSxFQUFFLENBQUM7UUFDbkQsQ0FBQztRQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7WUFDYixJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUU7Z0JBQ3RCLE9BQU8sRUFBRSx1QkFBdUI7Z0JBQ2hDLFdBQVcsRUFBRSxlQUFlO2dCQUM1QixhQUFhLEVBQUUsSUFBSSxDQUFDLEVBQUU7YUFDdkIsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDL0IsQ0FBQztJQUNILENBQUM7SUFFTyxPQUFPO1FBQ2IsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ2pDLElBQUksQ0FBQyxLQUFLO1lBQUUsT0FBTyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDckMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdkIsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDNUIsT0FBTyxJQUFJLE9BQU8sQ0FBTyxPQUFPLENBQUMsRUFBRTtZQUNqQyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxTQUFTLENBQUM7Z0JBQ3RDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRTtvQkFDVixJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztvQkFDbEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBQ3hCLE9BQU8sRUFBRSxDQUFDO2dCQUNaLENBQUM7Z0JBQ0QsS0FBSyxFQUFFLEdBQUcsQ0FBQyxFQUFFO29CQUNYLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUMzQixJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDeEIsT0FBTyxFQUFFLENBQUM7Z0JBQ1osQ0FBQzthQUNGLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELFdBQVc7UUFDVCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDakMsSUFBSSxDQUFDLEtBQUs7WUFBRSxPQUFPLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNyQyxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM5QixJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2hDLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQy9CLE9BQU8sSUFBSSxPQUFPLENBQU8sT0FBTyxDQUFDLEVBQUU7WUFDakMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDO2dCQUM1RCxJQUFJLEVBQUUsS0FBSyxFQUFDLEdBQUcsRUFBQyxFQUFFO29CQUNoQixNQUFNLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7b0JBQ3pELElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUN4QixJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLENBQUM7b0JBQ2pELElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUMvQixPQUFPLEVBQUUsQ0FBQztnQkFDWixDQUFDO2dCQUNELEtBQUssRUFBRSxHQUFHLENBQUMsRUFBRTtvQkFDWCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUMvQixJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDL0IsT0FBTyxFQUFFLENBQUM7Z0JBQ1osQ0FBQzthQUNGLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELGVBQWU7UUFDYixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDakMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDdEMsSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsa0JBQWtCLEVBQUU7WUFBRSxPQUFPO1FBQzFELElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUM7WUFDOUUsSUFBSSxFQUFFLEtBQUssRUFBQyxHQUFHLEVBQUMsRUFBRTtnQkFDaEIsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUN6RCxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxJQUFJLEVBQUUsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDO2dCQUNqRCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLENBQUM7Z0JBQ2pELElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDckMsQ0FBQztZQUNELEtBQUssRUFBRSxHQUFHLENBQUMsRUFBRTtnQkFDWCxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUU7b0JBQ3RCLE9BQU8sRUFBRSw4QkFBOEI7b0JBQ3ZDLFdBQVcsRUFBRSxjQUFjO29CQUMzQixhQUFhLEVBQUUsSUFBSSxDQUFDLEVBQUU7aUJBQ3ZCLENBQUMsQ0FBQztnQkFDSCxJQUFJLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3JDLENBQUM7U0FDRixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sS0FBSyxDQUFDLGtCQUFrQixDQUFDLE9BQW9CO1FBQ25ELE1BQU0sT0FBTyxHQUFHLE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUMsQ0FBQyxFQUFDLEVBQUU7WUFDcEIsSUFBSSxDQUFDO2dCQUNILE1BQU0sSUFBSSxHQUFHLE1BQU0sTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDdkUsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDM0MsT0FBTztvQkFDTCxHQUFHLENBQUM7b0JBQ0osTUFBTSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQXVCO29CQUN6QyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUF1QjtvQkFDN0QsSUFBSSxFQUFHLENBQUMsQ0FBQyxNQUFNLENBQXdCLElBQUksQ0FBQyxDQUFDLElBQUk7aUJBQ2xDLENBQUM7WUFDcEIsQ0FBQztZQUFDLE1BQU0sQ0FBQztnQkFDUCxPQUFPLENBQWlCLENBQUM7WUFDM0IsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUNILENBQUM7UUFDRixPQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLEtBQUssV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBRSxFQUFtQixDQUFDLENBQUMsQ0FBQztJQUN2RixDQUFDO0lBRUQsU0FBUztRQUNQLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNqQyxJQUFJLENBQUMsS0FBSztZQUFFLE9BQU87UUFDbkIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsU0FBUyxDQUFDO1lBQzVDLElBQUksRUFBRSxLQUFLLENBQUMsRUFBRTtnQkFDWixJQUFJLEtBQUssQ0FBQyxNQUFNO29CQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ25ELENBQUM7U0FDRixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsU0FBUyxDQUFDLFlBQW9CO1FBQzVCLCtDQUErQztRQUMvQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxZQUFZLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSyxZQUFZLENBQUMsQ0FBQztRQUNoRyxNQUFNLElBQUksR0FBRyxLQUFLLEVBQUUsSUFBSSxJQUFJLFlBQVksQ0FBQztRQUN6QyxNQUFNLE1BQU0sR0FBMkI7WUFDckMsTUFBTSxFQUFFLFlBQVk7WUFDcEIsTUFBTSxFQUFFLFlBQVk7WUFDcEIsS0FBSyxFQUFFLFdBQVc7WUFDbEIsV0FBVyxFQUFFLGdCQUFnQjtTQUM5QixDQUFDO1FBQ0YsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQztRQUNqQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzNCLE9BQU8sS0FBSyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDeEQsQ0FBQztJQUVELGVBQWUsQ0FBQyxJQUFZO1FBQzFCLElBQUksSUFBSSxLQUFLLEtBQUs7WUFBRSxPQUFPLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDOUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzNDLE1BQU0sTUFBTSxHQUEyQjtZQUNyQyxLQUFLLEVBQUUsV0FBVztZQUNsQixTQUFTLEVBQUUsZUFBZTtZQUMxQixLQUFLLEVBQUUsV0FBVztZQUNsQixLQUFLLEVBQUUsV0FBVztZQUNsQixTQUFTLEVBQUUsZUFBZTtZQUMxQixHQUFHLEVBQUUsU0FBUztTQUNmLENBQUM7UUFDRixNQUFNLE1BQU0sR0FBMkI7WUFDckMsSUFBSSxFQUFFLFVBQVU7WUFDaEIsS0FBSyxFQUFFLFdBQVc7WUFDbEIsTUFBTSxFQUFFLFlBQVk7WUFDcEIsTUFBTSxFQUFFLFlBQVk7WUFDcEIsTUFBTSxFQUFFLFlBQVk7WUFDcEIsR0FBRyxFQUFFLFNBQVM7U0FDZixDQUFDO1FBQ0YsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksUUFBUSxDQUFDLENBQUM7UUFDbEQsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLENBQUM7UUFDOUMsT0FBTyxHQUFHLEdBQUcsS0FBSyxHQUFHLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBRUQsWUFBWSxDQUFDLE1BQW9CO1FBQy9CLEtBQUssSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUM7WUFDMUIsU0FBUyxFQUFFLDBCQUEwQjtZQUNyQyxjQUFjLEVBQUU7Z0JBQ2QsTUFBTTtnQkFDTixLQUFLLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRTtnQkFDekIsY0FBYyxFQUFFLElBQUksQ0FBQyxjQUFjLEVBQUU7Z0JBQ3JDLFNBQVMsRUFBRSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLElBQUksQ0FBQyxNQUFNLEVBQUU7Z0JBQ3JFLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTSxLQUFLLElBQUksQ0FBQyxNQUFNLEVBQUU7Z0JBQ3ZDLFNBQVMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFO2FBQ3BDO1lBQ0QsV0FBVyxFQUFFO2dCQUNYLFdBQVcsRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUM7Z0JBQ3JCLGlCQUFpQixFQUFFLEdBQUc7Z0JBQ3RCLFVBQVUsRUFBRSxJQUFJO2FBQ2pCO1lBQ0QsZUFBZSxFQUFFLElBQUk7U0FDdEIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVTLEVBQUUsQ0FBQyxHQUFXO1FBQ3RCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNuQyxDQUFDOytHQXplVSx5QkFBeUI7bUdBQXpCLHlCQUF5QiwrR0F6YTFCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F3UVQseStFQWxSQyxnQkFBZ0IsMkVBQ2hCLG1CQUFtQiwrRUFDbkIsc0JBQXNCLDZGQUN0Qix1QkFBdUIsbUZBQ3ZCLGNBQWMseUVBQ2QsYUFBYSx3RUFDYixlQUFlLDBHQUNmLG1CQUFtQjs7NEZBNGFWLHlCQUF5QjtrQkF2YnJDLFNBQVM7K0JBQ0UsdUJBQXVCLGNBQ3JCLElBQUksV0FDUDt3QkFDUCxnQkFBZ0I7d0JBQ2hCLG1CQUFtQjt3QkFDbkIsc0JBQXNCO3dCQUN0Qix1QkFBdUI7d0JBQ3ZCLGNBQWM7d0JBQ2QsYUFBYTt3QkFDYixlQUFlO3dCQUNmLG1CQUFtQjt3QkFDbkIsK0JBQStCO3FCQUNoQyxZQUNTOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F3UVQ7d0RBb0xRLE1BQU07c0JBQWQsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgY29tcHV0ZWQsIGVmZmVjdCwgaW5qZWN0LCBJbnB1dCwgaXNEZXZNb2RlLCBzaWduYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IGZpcnN0VmFsdWVGcm9tIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBGaXJlc3RvcmUsIGRvYywgZ2V0RG9jIH0gZnJvbSAnQGFuZ3VsYXIvZmlyZS9maXJlc3RvcmUnO1xuXG5pbXBvcnQgeyBCdXR0b25Db21wb25lbnQgfSBmcm9tICcuLi8uLi9hdG9tcy9idXR0b24vYnV0dG9uLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBEaXNwbGF5Q29tcG9uZW50IH0gZnJvbSAnLi4vLi4vYXRvbXMvZGlzcGxheS9kaXNwbGF5LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBUZXh0Q29tcG9uZW50IH0gZnJvbSAnLi4vLi4vYXRvbXMvdGV4dC90ZXh0LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBUaXRsZUNvbXBvbmVudCB9IGZyb20gJy4uLy4uL2F0b21zL3RpdGxlL3RpdGxlLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBFbXB0eVN0YXRlQ29tcG9uZW50IH0gZnJvbSAnLi4vLi4vbW9sZWN1bGVzL2VtcHR5LXN0YXRlL2VtcHR5LXN0YXRlLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBFbXB0eVN0YXRlTWV0YWRhdGEgfSBmcm9tICcuLi8uLi9tb2xlY3VsZXMvZW1wdHktc3RhdGUvdHlwZXMnO1xuaW1wb3J0IHsgY3JlYXRlRXJyb3JTdGF0ZVByb3BzIH0gZnJvbSAnLi4vLi4vbW9sZWN1bGVzL2VtcHR5LXN0YXRlL2ZhY3RvcnknO1xuaW1wb3J0IHsgTWVtYmVyQ2FyZENvbXBvbmVudCB9IGZyb20gJy4uLy4uL21vbGVjdWxlcy9tZW1iZXItY2FyZC9tZW1iZXItY2FyZC5jb21wb25lbnQnO1xuaW1wb3J0IHsgU2tlbGV0b25MYXlvdXRDb21wb25lbnQgfSBmcm9tICcuLi9za2VsZXRvbi1sYXlvdXQvc2tlbGV0b24tbGF5b3V0LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBCdXR0b25NZXRhZGF0YSwgQ29tcG9uZW50U3RhdGVzIH0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBIYXNQZXJtaXNzaW9uRGlyZWN0aXZlIH0gZnJvbSAnLi4vLi4vLi4vZGlyZWN0aXZlcy9oYXMtcGVybWlzc2lvbi5kaXJlY3RpdmUnO1xuXG5pbXBvcnQgeyBBdXRoU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2F1dGgvYXV0aC5zZXJ2aWNlJztcbmltcG9ydCB7IEkxOG5TZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvaTE4bic7XG5pbXBvcnQgeyBpbnRlcnByZXRFcnJvciB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2Vycm9ycy9pbnRlcnByZXQtZXJyb3InO1xuaW1wb3J0IHsgTW9kYWxTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvbW9kYWwvbW9kYWwuc2VydmljZSc7XG5pbXBvcnQgeyBOYXZpZ2F0aW9uU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL25hdmlnYXRpb24vbmF2aWdhdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7IE9yZ1NlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi9zZXJ2aWNlcy9vcmcvb3JnLnNlcnZpY2UnO1xuaW1wb3J0IHsgT3JnTWVtYmVyLCBPcmdSb2xlLCBPcmdhbml6YXRpb24gfSBmcm9tICcuLi8uLi8uLi9zZXJ2aWNlcy9vcmcvdHlwZXMnO1xuaW1wb3J0IHsgY29ubmVjdFBhZ2VSZWZyZXNoIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvcGFnZS1yZWZyZXNoL3BhZ2UtcmVmcmVzaC5zZXJ2aWNlJztcbmltcG9ydCB7IFRvYXN0U2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL3RvYXN0LnNlcnZpY2UnO1xuaW1wb3J0IHsgVmFsdGVjaEVycm9yU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2Vycm9ycy92YWx0ZWNoLWVycm9yLnNlcnZpY2UnO1xuaW1wb3J0IHsgQ29uZmlybWF0aW9uRGlhbG9nU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2NvbmZpcm1hdGlvbi1kaWFsb2cvY29uZmlybWF0aW9uLWRpYWxvZy5zZXJ2aWNlJztcblxuaW1wb3J0IHsgRWRpdE9yZ01vZGFsQ29tcG9uZW50IH0gZnJvbSAnLi4vZWRpdC1vcmctbW9kYWwvZWRpdC1vcmctbW9kYWwuY29tcG9uZW50JztcbmltcG9ydCB7IEludml0ZU1lbWJlck1vZGFsQ29tcG9uZW50IH0gZnJvbSAnLi4vaW52aXRlLW1lbWJlci1tb2RhbC9pbnZpdGUtbWVtYmVyLW1vZGFsLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBNZW1iZXJEZXRhaWxNb2RhbENvbXBvbmVudCB9IGZyb20gJy4uL21lbWJlci1kZXRhaWwtbW9kYWwvbWVtYmVyLWRldGFpbC1tb2RhbC5jb21wb25lbnQnO1xuaW1wb3J0IHsgTWVtYmVyRGV0YWlsIH0gZnJvbSAnLi4vbWVtYmVyLWRldGFpbC1tb2RhbC90eXBlcyc7XG5pbXBvcnQgeyBUcmFuc2Zlck93bmVyc2hpcE1vZGFsQ29tcG9uZW50IH0gZnJvbSAnLi4vdHJhbnNmZXItb3duZXJzaGlwLW1vZGFsL3RyYW5zZmVyLW93bmVyc2hpcC1tb2RhbC5jb21wb25lbnQnO1xuXG5pbXBvcnQgeyBPcmdhbml6YXRpb25WaWV3Q29uZmlnIH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBPUkdBTklaQVRJT05fVklFV19JMThOIH0gZnJvbSAnLi9vcmdhbml6YXRpb24tdmlldy5pMThuJztcblxuY29uc3QgREVGQVVMVF9OQU1FU1BBQ0UgPSAnU2V0dGluZ3MuT3JnYW5pemF0aW9uJztcbmNvbnN0IERFRkFVTFRfVklFV19QRVJNSVNTSU9OU19ST1VURSA9ICcvYXBwL3NldHRpbmdzL3Blcm1pc3Npb25zJztcbmNvbnN0IERFRkFVTFRfTEVBVkVfUkVESVJFQ1RfUk9VVEUgPSAnL2FwcC9zZXR0aW5ncy9hY2NvdW50JztcblxuLyoqXG4gKiBgdmFsLW9yZ2FuaXphdGlvbi12aWV3YCDigJQgdmlzdGEgR2VzdGnDs24gZGUgb3JnYW5pemFjacOzbiBmdWxsLWZlYXR1cmVcbiAqIGF1dG9jb250ZW5pZGEgKG9yZ2FuaXNtKS4gUHJvbW92aWRhIGRlc2RlIGBzaG93Y2FzZWAgYmFqbyBlbCBwcm9jZXNvIGRlXG4gKiBBRFItMDIxLiBSZcO6bmU6XG4gKiAgLSAqKkluZm9ybWFjacOzbioqIOKAlCBub21icmUsIGRlc2NyaXBjacOzbiwgcGxhbiB5IHRpcG8gZGUgbGEgb3JnIGFjdGl2YTsgZWRpdGFyXG4gKiAgICB2w61hIG1vZGFsIGB2YWwtZWRpdC1vcmctbW9kYWxgIChzb2xvIHNpIGBjYW5FZGl0T3JnKClgKS5cbiAqICAtICoqTWllbWJyb3MqKiDigJQgbGlzdGEgcGFnaW5hZGEgKGB2YWwtbWVtYmVyLWNhcmRgKSBlbnJpcXVlY2lkYSBjb24gcGVyZmlsZXNcbiAqICAgIHDDumJsaWNvcyAoRmlyZXN0b3JlKTsgdmVyIGRldGFsbGUgdsOtYSBgdmFsLW1lbWJlci1kZXRhaWwtbW9kYWxgLlxuICogIC0gKipSb2xlcyB5IHBlcm1pc29zKiog4oCUIHNlY2Npw7NuIGV4cGxpY2F0aXZhIGNvbiBDVEEgYSBsYSBydXRhIGRlIHBlcm1pc29zLlxuICogIC0gKipJbnZpdGFyKiog4oCUIENUQSBxdWUgYWJyZSBgdmFsLWludml0ZS1tZW1iZXItbW9kYWxgIChnYXRlYWRhIHBvciBgdXNlcnM6KmApLlxuICogIC0gKipUcmFuc2ZlcmlyIHByb3BpZWRhZCoqIOKAlCBgdmFsLXRyYW5zZmVyLW93bmVyc2hpcC1tb2RhbGAgKHNvbG8gb3duZXIpLlxuICogIC0gKipTYWxpciBkZSBsYSBvcmdhbml6YWNpw7NuKiog4oCUIGBPcmdTZXJ2aWNlLmxlYXZlT3JnYCBjb24gY29uZmlybWFjacOzblxuICogICAgZGVzdHJ1Y3RpdmEuXG4gKlxuICogKipSQkFDIGludGVybm8qKiAoZGVjaXNpw7NuIENUTywgQURSLTAyMSk6IGVsIGdhdGluZyBmaW5vIHNlIHJlc3VlbHZlIGRlbnRybyBkZVxuICogbGEgdmlzdGEgdsOtYSBgQXV0aFNlcnZpY2UuaGFzUGVybWlzc2lvbigpYCArIGAqdmFsSGFzUGVybWlzc2lvbmAgKyBjb21wdXRlZHNcbiAqIGBpc093bmVyKClgL2BjYW5NYW5hZ2VNZW1iZXJzKClgL2BjYW5FZGl0T3JnKClgLiBOTyBzZSBleHBvbmUgY29tbyBjb25maWcuXG4gKlxuICogKipBdXRvLXJlbG9hZCBlbiBvcmctc3dpdGNoKio6IHVuIGBlZmZlY3RgIHJlYWN0aW9uYSBhIGBhY3RpdmVPcmdJZCgpYCB5IHJlY2FyZ2FcbiAqIG9yZyArIG1pZW1icm9zIGN1YW5kbyBlbCB1c3VhcmlvIGNhbWJpYSBkZSBvcmdhbml6YWNpw7NuIGFjdGl2YSBtaWVudHJhcyBsYSB2aXN0YVxuICogZXN0w6EgbW9udGFkYS4gRWwgZWZmZWN0IGN1YnJlIHRhbWJpw6luIGxhIGNhcmdhIGluaWNpYWwgKHNpbiBkb2JsZSBjYXJnYSkuXG4gKlxuICogTk8gcmVuZGVyaXphIGlvbi1jb250ZW50IOKAlCB2aXZlIGRlbnRybyBkZSB2YWwtcGFnZS13cmFwcGVyLiBgQWN0aXZhdGVkUm91dGVgIHNlXG4gKiBpbnllY3RhIGB7IG9wdGlvbmFsOiB0cnVlIH1gIHNvbG8gcGFyYSBsZWVyIGVsIHJvdXRlIGRhdGEgZGUgY29uZmlnIChuby1vcFxuICogZW1iZWJpZG8pLiBBdXRvLXJlZ2lzdHJhIHN1cyBkZWZhdWx0cyBpMThuIChlcy9lbikgc2kgZWwgY29uc3VtZXIgbm8gcHJvdmV5w7MgZWxcbiAqIG5hbWVzcGFjZSAoZGVmYXVsdCBgU2V0dGluZ3MuT3JnYW5pemF0aW9uYCkuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3ZhbC1vcmdhbml6YXRpb24tdmlldycsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBEaXNwbGF5Q29tcG9uZW50LFxuICAgIEVtcHR5U3RhdGVDb21wb25lbnQsXG4gICAgSGFzUGVybWlzc2lvbkRpcmVjdGl2ZSxcbiAgICBTa2VsZXRvbkxheW91dENvbXBvbmVudCxcbiAgICBUaXRsZUNvbXBvbmVudCxcbiAgICBUZXh0Q29tcG9uZW50LFxuICAgIEJ1dHRvbkNvbXBvbmVudCxcbiAgICBNZW1iZXJDYXJkQ29tcG9uZW50LFxuICAgIFRyYW5zZmVyT3duZXJzaGlwTW9kYWxDb21wb25lbnQsXG4gIF0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cInBhZ2VcIj5cbiAgICAgIDxoZWFkZXIgY2xhc3M9XCJwYWdlLWhlYWRlclwiPlxuICAgICAgICA8dmFsLWRpc3BsYXkgW3Byb3BzXT1cInsgc2l6ZTogJ3NtYWxsJywgY29sb3I6ICdkYXJrJywgY29udGVudDogcGFnZVRpdGxlKCkgfVwiIC8+XG4gICAgICAgIDx2YWwtdGl0bGVcbiAgICAgICAgICBbcHJvcHNdPVwie1xuICAgICAgICAgICAgc2l6ZTogJ2xhcmdlJyxcbiAgICAgICAgICAgIGNvbG9yOiAnZGFyaycsXG4gICAgICAgICAgICBib2xkOiBmYWxzZSxcbiAgICAgICAgICAgIGNvbnRlbnQ6IHBhZ2VEZXNjcmlwdGlvbigpLFxuICAgICAgICAgIH1cIlxuICAgICAgICAvPlxuICAgICAgPC9oZWFkZXI+XG5cbiAgICAgIEBpZiAocmVzb2x2ZWRDb25maWcoKS5zaG93SW5mbykge1xuICAgICAgICA8IS0tIE9yZyBJbmZvIC0tPlxuICAgICAgICA8c2VjdGlvbiBjbGFzcz1cInNldHRpbmdzLXNlY3Rpb25cIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwic2VjdGlvbi1oZWFkZXItcm93XCI+XG4gICAgICAgICAgICA8dmFsLXRpdGxlXG4gICAgICAgICAgICAgIFtwcm9wc109XCJ7XG4gICAgICAgICAgICAgICAgc2l6ZTogJ21lZGl1bScsXG4gICAgICAgICAgICAgICAgY29sb3I6ICdkYXJrJyxcbiAgICAgICAgICAgICAgICBib2xkOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNvbnRlbnQ6IHR0KCdpbmZvVGl0bGUnKSxcbiAgICAgICAgICAgICAgfVwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgQGlmIChjYW5FZGl0T3JnKCkpIHtcbiAgICAgICAgICAgICAgPHZhbC1idXR0b24gW3Byb3BzXT1cImVkaXRCdXR0b25Qcm9wcygpXCIgKGNsaWNrKT1cIm9uRWRpdCgpXCIgLz5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZWN0aW9uLWJvZHlcIj5cbiAgICAgICAgICAgIEBpZiAobG9hZGluZygpKSB7XG4gICAgICAgICAgICAgIDx2YWwtc2tlbGV0b24tbGF5b3V0IFtwcm9wc109XCJ7IHByZXNldDogJ2RldGFpbCcsIHJvd3M6IDQgfVwiIC8+XG4gICAgICAgICAgICB9IEBlbHNlIGlmIChvcmdFcnJvclN0YXRlKCkpIHtcbiAgICAgICAgICAgICAgPHZhbC1lbXB0eS1zdGF0ZSBbcHJvcHNdPVwib3JnRXJyb3JTdGF0ZSgpIVwiIC8+XG4gICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgQGlmIChvcmcoKTsgYXMgbykge1xuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJvcmctaW5mby1jYXJkXCI+XG4gICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwib3JnLWluZm8tZmllbGQgb3JnLWluZm8tZmllbGQtLWZ1bGxcIj5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJvcmctaW5mby1sYWJlbFwiPnt7IHR0KCdpbmZvTmFtZScpIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm9yZy1pbmZvLXZhbHVlXCI+e3sgby5uYW1lIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwib3JnLWluZm8tZmllbGQgb3JnLWluZm8tZmllbGQtLWZ1bGxcIj5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJvcmctaW5mby1sYWJlbFwiPnt7IHR0KCdpbmZvRGVzY3JpcHRpb24nKSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJvcmctaW5mby12YWx1ZSBvcmctaW5mby12YWx1ZS0tbXV0ZWRcIj57eyBvLmRlc2NyaXB0aW9uIHx8ICfigJQnIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwib3JnLWluZm8tcm93XCI+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJvcmctaW5mby1maWVsZFwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwib3JnLWluZm8tbGFiZWxcIj57eyB0dCgnaW5mb1BsYW4nKSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInBsYW4tYmFkZ2UgcGxhbi1iYWRnZS0te3sgby5wbGFuIH19XCI+e3sgcGxhbkxhYmVsKCkgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwib3JnLWluZm8tZmllbGRcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm9yZy1pbmZvLWxhYmVsXCI+e3sgdHQoJ2luZm9UeXBlJykgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJvcmctaW5mby12YWx1ZVwiPnt7IG8udHlwZSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L3NlY3Rpb24+XG4gICAgICB9XG5cbiAgICAgIEBpZiAocmVzb2x2ZWRDb25maWcoKS5zaG93TWVtYmVycykge1xuICAgICAgICA8IS0tIE1lbWJlcnMgLS0+XG4gICAgICAgIDxzZWN0aW9uIGNsYXNzPVwic2V0dGluZ3Mtc2VjdGlvblwiPlxuICAgICAgICAgIDx2YWwtdGl0bGVcbiAgICAgICAgICAgIFtwcm9wc109XCJ7XG4gICAgICAgICAgICAgIHNpemU6ICdtZWRpdW0nLFxuICAgICAgICAgICAgICBjb2xvcjogJ2RhcmsnLFxuICAgICAgICAgICAgICBib2xkOiB0cnVlLFxuICAgICAgICAgICAgICBjb250ZW50OiB0dCgnbWVtYmVyc1RpdGxlJyksXG4gICAgICAgICAgICB9XCJcbiAgICAgICAgICAvPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZWN0aW9uLWJvZHlcIj5cbiAgICAgICAgICAgIEBpZiAobWVtYmVyc0xvYWRpbmcoKSkge1xuICAgICAgICAgICAgICA8dmFsLXNrZWxldG9uLWxheW91dCBbcHJvcHNdPVwieyBwcmVzZXQ6ICdsaXN0Jywgcm93czogMyB9XCIgLz5cbiAgICAgICAgICAgIH0gQGVsc2UgaWYgKG1lbWJlcnMoKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgPHZhbC10ZXh0XG4gICAgICAgICAgICAgICAgW3Byb3BzXT1cIntcbiAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IHR0KCdtZW1iZXJzRW1wdHknKSxcbiAgICAgICAgICAgICAgICAgIHNpemU6ICdtZWRpdW0nLFxuICAgICAgICAgICAgICAgICAgY29sb3I6ICdkYXJrJyxcbiAgICAgICAgICAgICAgICAgIGJvbGQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgIH1cIlxuICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtZW1iZXJzLWxpc3RcIj5cbiAgICAgICAgICAgICAgICBAZm9yIChtIG9mIHZpc2libGVNZW1iZXJzKCk7IHRyYWNrIG0udXNlcklkKSB7XG4gICAgICAgICAgICAgICAgICA8dmFsLW1lbWJlci1jYXJkXG4gICAgICAgICAgICAgICAgICAgIFthdHRyLmRhdGEtdGVzdGlkXT1cIidvcmctbWVtYmVyLScgKyBtLnVzZXJJZFwiXG4gICAgICAgICAgICAgICAgICAgIFtwcm9wc109XCJ7XG4gICAgICAgICAgICAgICAgICAgICAgaWQ6IG0udXNlcklkLFxuICAgICAgICAgICAgICAgICAgICAgIG5hbWU6IG0ubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBoYW5kbGU6IG0uaGFuZGxlLFxuICAgICAgICAgICAgICAgICAgICAgIGVtYWlsOiBtLmVtYWlsLFxuICAgICAgICAgICAgICAgICAgICAgIGF2YXRhclVybDogbS5hdmF0YXIsXG4gICAgICAgICAgICAgICAgICAgICAgcm9sZUxhYmVsOiBtLnJvbGVzWzBdID8gcm9sZUxhYmVsKG0ucm9sZXNbMF0pIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgYWN0aW9uQXJpYUxhYmVsOiB0dCgndmlld01lbWJlckN0YScpLFxuICAgICAgICAgICAgICAgICAgICB9XCJcbiAgICAgICAgICAgICAgICAgICAgKG9uQWN0aW9uKT1cIm9uVmlld01lbWJlcihtKVwiXG4gICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIEBpZiAoIXNob3dBbGxNZW1iZXJzKCkgJiYgbWVtYmVycygpLmxlbmd0aCA+IDMpIHtcbiAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwibWVtYmVycy1zaG93LW1vcmVcIiAoY2xpY2spPVwic2hvd0FsbE1lbWJlcnMuc2V0KHRydWUpXCI+XG4gICAgICAgICAgICAgICAgICB7eyB0dCgnbWVtYmVyc1Nob3dNb3JlJykgfX0gKHt7IG1lbWJlcnMoKS5sZW5ndGggLSAzIH19KVxuICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIEBpZiAoc2hvd0FsbE1lbWJlcnMoKSAmJiBtZW1iZXJzTmV4dFRva2VuKCkpIHtcbiAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwibWVtYmVycy1zaG93LW1vcmVcIiBbZGlzYWJsZWRdPVwibG9hZGluZ01vcmVNZW1iZXJzKClcIiAoY2xpY2spPVwibG9hZE1vcmVNZW1iZXJzKClcIj5cbiAgICAgICAgICAgICAgICAgIHt7IGxvYWRpbmdNb3JlTWVtYmVycygpID8gJ+KApicgOiB0dCgnbWVtYmVyc1Nob3dNb3JlJykgfX1cbiAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L3NlY3Rpb24+XG4gICAgICB9XG5cbiAgICAgIEBpZiAocmVzb2x2ZWRDb25maWcoKS5zaG93Um9sZXMpIHtcbiAgICAgICAgPCEtLSBSb2xlcyB5IHBlcm1pc29zOiBzZWNjaW9uIGV4cGxpY2F0aXZhLCBkZXRhbGxlIGVuIGxhIHJ1dGEgZGUgcGVybWlzb3MgLS0+XG4gICAgICAgIDxzZWN0aW9uIGNsYXNzPVwic2V0dGluZ3Mtc2VjdGlvblwiPlxuICAgICAgICAgIDx2YWwtdGl0bGVcbiAgICAgICAgICAgIFtwcm9wc109XCJ7XG4gICAgICAgICAgICAgIHNpemU6ICdtZWRpdW0nLFxuICAgICAgICAgICAgICBjb2xvcjogJ2RhcmsnLFxuICAgICAgICAgICAgICBib2xkOiB0cnVlLFxuICAgICAgICAgICAgICBjb250ZW50OiB0dCgncm9sZXNTZWN0aW9uVGl0bGUnKSxcbiAgICAgICAgICAgIH1cIlxuICAgICAgICAgIC8+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInNlY3Rpb24tYm9keVwiPlxuICAgICAgICAgICAgPHZhbC10ZXh0XG4gICAgICAgICAgICAgIFtwcm9wc109XCJ7XG4gICAgICAgICAgICAgICAgY29udGVudDogdHQoJ3JvbGVzSGludCcpLFxuICAgICAgICAgICAgICAgIHNpemU6ICdtZWRpdW0nLFxuICAgICAgICAgICAgICAgIGNvbG9yOiAnZGFyaycsXG4gICAgICAgICAgICAgICAgYm9sZDogZmFsc2UsXG4gICAgICAgICAgICAgIH1cIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyb3ctYWN0aW9uc1wiPlxuICAgICAgICAgICAgICA8dmFsLWJ1dHRvbiBbcHJvcHNdPVwidmlld1Blcm1pc3Npb25zQnV0dG9uUHJvcHMoKVwiIChjbGljayk9XCJvblZpZXdQZXJtaXNzaW9ucygpXCIgLz5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L3NlY3Rpb24+XG4gICAgICB9XG5cbiAgICAgIEBpZiAocmVzb2x2ZWRDb25maWcoKS5zaG93SW52aXRlKSB7XG4gICAgICAgIDwhLS0gSW52aXRlOiBzb2xvIGFkbWluKyAoZ2F0aW5nIFJCQUMgaW50ZXJubykgLS0+XG4gICAgICAgIDxzZWN0aW9uICp2YWxIYXNQZXJtaXNzaW9uPVwiJ3VzZXJzOionXCIgY2xhc3M9XCJzZXR0aW5ncy1zZWN0aW9uXCIgZGF0YS10ZXN0aWQ9XCJvcmctaW52aXRlLXNlY3Rpb25cIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiaW52aXRlLWN0YVwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImludml0ZS1jdGFfX3RleHRcIj5cbiAgICAgICAgICAgICAgPHZhbC10aXRsZVxuICAgICAgICAgICAgICAgIFtwcm9wc109XCJ7XG4gICAgICAgICAgICAgICAgICBzaXplOiAnbWVkaXVtJyxcbiAgICAgICAgICAgICAgICAgIGNvbG9yOiAnZGFyaycsXG4gICAgICAgICAgICAgICAgICBib2xkOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgY29udGVudDogdHQoJ2ludml0ZUN0YVRpdGxlJyksXG4gICAgICAgICAgICAgICAgfVwiXG4gICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgIDx2YWwtdGV4dFxuICAgICAgICAgICAgICAgIFtwcm9wc109XCJ7XG4gICAgICAgICAgICAgICAgICBzaXplOiAnbWVkaXVtJyxcbiAgICAgICAgICAgICAgICAgIGNvbG9yOiAnZGFyaycsXG4gICAgICAgICAgICAgICAgICBib2xkOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IHR0KCdpbnZpdGVDdGFIaW50JyksXG4gICAgICAgICAgICAgICAgfVwiXG4gICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDx2YWwtYnV0dG9uIFtwcm9wc109XCJvcGVuSW52aXRlQnV0dG9uUHJvcHMoKVwiIChjbGljayk9XCJvbk9wZW5JbnZpdGUoKVwiIC8+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvc2VjdGlvbj5cbiAgICAgIH1cblxuICAgICAgQGlmIChyZXNvbHZlZENvbmZpZygpLnNob3dUcmFuc2Zlck93bmVyc2hpcCAmJiBpc093bmVyKCkpIHtcbiAgICAgICAgPCEtLSBUcmFuc2ZlciBvd25lcnNoaXA6IHNvbG8gb3duZXIgKGdhdGluZyBSQkFDIGludGVybm8pIC0tPlxuICAgICAgICA8c2VjdGlvbiBjbGFzcz1cInNldHRpbmdzLXNlY3Rpb25cIiBkYXRhLXRlc3RpZD1cIm9yZy10cmFuc2Zlci1zZWN0aW9uXCI+XG4gICAgICAgICAgPHZhbC10aXRsZVxuICAgICAgICAgICAgW3Byb3BzXT1cIntcbiAgICAgICAgICAgICAgc2l6ZTogJ21lZGl1bScsXG4gICAgICAgICAgICAgIGNvbG9yOiAnZGFyaycsXG4gICAgICAgICAgICAgIGJvbGQ6IHRydWUsXG4gICAgICAgICAgICAgIGNvbnRlbnQ6IHR0KCd0cmFuc2ZlclRpdGxlJyksXG4gICAgICAgICAgICB9XCJcbiAgICAgICAgICAvPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZWN0aW9uLWJvZHlcIj5cbiAgICAgICAgICAgIDx2YWwtdGV4dFxuICAgICAgICAgICAgICBbcHJvcHNdPVwie1xuICAgICAgICAgICAgICAgIGNvbnRlbnQ6IHR0KCd0cmFuc2ZlckhpbnQnKSxcbiAgICAgICAgICAgICAgICBzaXplOiAnbWVkaXVtJyxcbiAgICAgICAgICAgICAgICBjb2xvcjogJ2RhcmsnLFxuICAgICAgICAgICAgICAgIGJvbGQ6IGZhbHNlLFxuICAgICAgICAgICAgICB9XCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICBAaWYgKHRyYW5zZmVyYWJsZU1lbWJlcnMoKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyb3ctYWN0aW9uc1wiPlxuICAgICAgICAgICAgICAgIDx2YWwtYnV0dG9uIFtwcm9wc109XCJ0cmFuc2ZlckJ1dHRvblByb3BzKClcIiAoY2xpY2spPVwib25PcGVuVHJhbnNmZXIoKVwiIC8+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgIDx2YWwtdGV4dFxuICAgICAgICAgICAgICAgIFtwcm9wc109XCJ7XG4gICAgICAgICAgICAgICAgICBjb250ZW50OiB0dCgnbWVtYmVyc0VtcHR5JyksXG4gICAgICAgICAgICAgICAgICBzaXplOiAnbWVkaXVtJyxcbiAgICAgICAgICAgICAgICAgIGNvbG9yOiAnZGFyaycsXG4gICAgICAgICAgICAgICAgICBib2xkOiBmYWxzZSxcbiAgICAgICAgICAgICAgICB9XCJcbiAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9zZWN0aW9uPlxuICAgICAgfVxuXG4gICAgICBAaWYgKHJlc29sdmVkQ29uZmlnKCkuc2hvd0xlYXZlKSB7XG4gICAgICAgIDwhLS0gTGVhdmUgb3JnIC0tPlxuICAgICAgICA8c2VjdGlvbiBjbGFzcz1cInNldHRpbmdzLXNlY3Rpb25cIj5cbiAgICAgICAgICA8dmFsLXRpdGxlXG4gICAgICAgICAgICBbcHJvcHNdPVwie1xuICAgICAgICAgICAgICBzaXplOiAnbWVkaXVtJyxcbiAgICAgICAgICAgICAgY29sb3I6ICdkYXJrJyxcbiAgICAgICAgICAgICAgYm9sZDogdHJ1ZSxcbiAgICAgICAgICAgICAgY29udGVudDogdHQoJ2xlYXZlVGl0bGUnKSxcbiAgICAgICAgICAgIH1cIlxuICAgICAgICAgIC8+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInNlY3Rpb24tYm9keVwiPlxuICAgICAgICAgICAgPHZhbC10ZXh0XG4gICAgICAgICAgICAgIFtwcm9wc109XCJ7XG4gICAgICAgICAgICAgICAgY29udGVudDogaXNPd25lcigpID8gdHQoJ2xlYXZlT3duZXJIaW50JykgOiB0dCgnbGVhdmVIaW50JyksXG4gICAgICAgICAgICAgICAgc2l6ZTogJ21lZGl1bScsXG4gICAgICAgICAgICAgICAgY29sb3I6ICdkYXJrJyxcbiAgICAgICAgICAgICAgICBib2xkOiBmYWxzZSxcbiAgICAgICAgICAgICAgfVwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJvdy1hY3Rpb25zXCI+XG4gICAgICAgICAgICAgIDx2YWwtYnV0dG9uIFtwcm9wc109XCJsZWF2ZUJ1dHRvblByb3BzKClcIiAoY2xpY2spPVwib25MZWF2ZSgpXCIgLz5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L3NlY3Rpb24+XG4gICAgICB9XG5cbiAgICAgIEBpZiAoaXNEZWJ1Zykge1xuICAgICAgICA8c2VjdGlvbiBjbGFzcz1cInNldHRpbmdzLXNlY3Rpb24gcmJhYy1kZWJ1Z1wiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZWN0aW9uLWhlYWRlci1yb3dcIj5cbiAgICAgICAgICAgIDx2YWwtdGl0bGVcbiAgICAgICAgICAgICAgW3Byb3BzXT1cIntcbiAgICAgICAgICAgICAgICBjb250ZW50OiAnUkJBQyAobGl2ZSknLFxuICAgICAgICAgICAgICAgIHNpemU6ICdzbWFsbCcsXG4gICAgICAgICAgICAgICAgY29sb3I6ICdtZWRpdW0nLFxuICAgICAgICAgICAgICAgIGJvbGQ6IGZhbHNlLFxuICAgICAgICAgICAgICB9XCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInJiYWMtZGVidWdfX2JvZHlcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyYmFjLWRlYnVnX19yb3dcIj5cbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJyYmFjLWRlYnVnX19sYWJlbFwiPlJvbGVzPC9zcGFuPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInJiYWMtZGVidWdfX3ZhbHVlXCI+e3sgYXV0aC5yb2xlcygpLmpvaW4oJywgJykgfHwgJ+KAlCcgfX08L3NwYW4+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyYmFjLWRlYnVnX19yb3dcIj5cbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJyYmFjLWRlYnVnX19sYWJlbFwiPlBlcm1pc29zPC9zcGFuPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInJiYWMtZGVidWdfX3ZhbHVlIHJiYWMtZGVidWdfX3ZhbHVlLS1wZXJtc1wiPnt7IGF1dGgucGVybWlzc2lvbnMoKS5qb2luKCcsICcpIHx8ICfigJQnIH19PC9zcGFuPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvc2VjdGlvbj5cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVzOiBbXG4gICAgYFxuICAgICAgLnBhZ2Uge1xuICAgICAgICBwYWRkaW5nOiAxNnB4IDA7XG4gICAgICAgIG1heC13aWR0aDogNzIwcHg7XG4gICAgICAgIG1hcmdpbjogMCBhdXRvO1xuICAgICAgfVxuICAgICAgLnBhZ2UtaGVhZGVyIHtcbiAgICAgICAgbWFyZ2luLWJvdHRvbTogMTZweDtcbiAgICAgIH1cbiAgICAgIC5zZXR0aW5ncy1zZWN0aW9uIHtcbiAgICAgICAgcGFkZGluZzogMTZweCAwO1xuICAgICAgfVxuICAgICAgLnNldHRpbmdzLXNlY3Rpb24gKyAuc2V0dGluZ3Mtc2VjdGlvbiB7XG4gICAgICAgIGJvcmRlci10b3A6IDFweCBzb2xpZCB2YXIoLS12YWwtYm9yZGVyLWNvbG9yLCByZ2JhKDAsIDAsIDAsIDAuMDgpKTtcbiAgICAgIH1cbiAgICAgIC5zZWN0aW9uLWhlYWRlci1yb3cge1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gICAgICAgIGdhcDogOHB4O1xuICAgICAgICBtYXJnaW4tYm90dG9tOiA4cHg7XG4gICAgICB9XG4gICAgICAuc2VjdGlvbi1ib2R5IHtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICAgICAgZ2FwOiAxMHB4O1xuICAgICAgfVxuICAgICAgLnJvdy1hY3Rpb25zIHtcbiAgICAgICAgbWFyZ2luLXRvcDogMTJweDtcbiAgICAgIH1cbiAgICAgIC5yb3ctYWN0aW9ucy0tZ2FwIHtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgZ2FwOiA4cHg7XG4gICAgICB9XG4gICAgICAuaW52aXRlLWN0YSB7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGFsaWduLWl0ZW1zOiBmbGV4LXN0YXJ0O1xuICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gICAgICAgIGdhcDogMTZweDtcbiAgICAgICAgZmxleC13cmFwOiB3cmFwO1xuICAgICAgfVxuICAgICAgLmludml0ZS1jdGFfX3RleHQge1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgICAgICBnYXA6IDRweDtcbiAgICAgICAgZmxleDogMTtcbiAgICAgIH1cbiAgICAgIC5vcmctaW5mby1jYXJkIHtcbiAgICAgICAgYm9yZGVyLXJhZGl1czogMTRweDtcbiAgICAgICAgYmFja2dyb3VuZDogdmFyKC0taW9uLWNvbG9yLWxpZ2h0LCAjZjRmNWY4KTtcbiAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgICAgIH1cbiAgICAgIDpob3N0LWNvbnRleHQoYm9keS5kYXJrKSAub3JnLWluZm8tY2FyZCxcbiAgICAgIDpob3N0LWNvbnRleHQoaHRtbC5pb24tcGFsZXR0ZS1kYXJrKSAub3JnLWluZm8tY2FyZCxcbiAgICAgIDpob3N0LWNvbnRleHQoW2RhdGEtdGhlbWU9J2RhcmsnXSkgLm9yZy1pbmZvLWNhcmQge1xuICAgICAgICBiYWNrZ3JvdW5kOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuMDUpO1xuICAgICAgfVxuICAgICAgLm9yZy1pbmZvLWZpZWxkIHtcbiAgICAgICAgcGFkZGluZzogMTJweCAxNnB4O1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgICAgICBnYXA6IDRweDtcbiAgICAgICAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkIHZhcigtLXZhbC1ib3JkZXItY29sb3IsIHJnYmEoMCwgMCwgMCwgMC4wNikpO1xuICAgICAgfVxuICAgICAgLm9yZy1pbmZvLWZpZWxkLS1mdWxsIHtcbiAgICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICB9XG4gICAgICAub3JnLWluZm8tZmllbGQ6bGFzdC1jaGlsZCB7XG4gICAgICAgIGJvcmRlci1ib3R0b206IG5vbmU7XG4gICAgICB9XG4gICAgICAub3JnLWluZm8tcm93IHtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgIH1cbiAgICAgIC5vcmctaW5mby1yb3cgLm9yZy1pbmZvLWZpZWxkIHtcbiAgICAgICAgZmxleDogMTtcbiAgICAgIH1cbiAgICAgIC5vcmctaW5mby1yb3cgLm9yZy1pbmZvLWZpZWxkOmZpcnN0LWNoaWxkIHtcbiAgICAgICAgYm9yZGVyLXJpZ2h0OiAxcHggc29saWQgdmFyKC0tdmFsLWJvcmRlci1jb2xvciwgcmdiYSgwLCAwLCAwLCAwLjA2KSk7XG4gICAgICB9XG4gICAgICAub3JnLWluZm8tbGFiZWwge1xuICAgICAgICBmb250LXNpemU6IDAuNzRyZW07XG4gICAgICAgIGZvbnQtd2VpZ2h0OiA2MDA7XG4gICAgICAgIHRleHQtdHJhbnNmb3JtOiB1cHBlcmNhc2U7XG4gICAgICAgIGxldHRlci1zcGFjaW5nOiAwLjA0ZW07XG4gICAgICAgIGNvbG9yOiB2YXIoLS1pb24tY29sb3ItbWVkaXVtKTtcbiAgICAgIH1cbiAgICAgIC5vcmctaW5mby12YWx1ZSB7XG4gICAgICAgIGZvbnQtc2l6ZTogMC45NXJlbTtcbiAgICAgICAgZm9udC13ZWlnaHQ6IDUwMDtcbiAgICAgICAgY29sb3I6IHZhcigtLWlvbi1jb2xvci1kYXJrKTtcbiAgICAgIH1cbiAgICAgIC5vcmctaW5mby12YWx1ZS0tbXV0ZWQge1xuICAgICAgICBjb2xvcjogdmFyKC0taW9uLWNvbG9yLW1lZGl1bSk7XG4gICAgICAgIGZvbnQtd2VpZ2h0OiA0MDA7XG4gICAgICB9XG4gICAgICAucGxhbi1iYWRnZSB7XG4gICAgICAgIGRpc3BsYXk6IGlubGluZS1ibG9jaztcbiAgICAgICAgZm9udC1zaXplOiAwLjc4cmVtO1xuICAgICAgICBmb250LXdlaWdodDogNzAwO1xuICAgICAgICBwYWRkaW5nOiAzcHggMTBweDtcbiAgICAgICAgYm9yZGVyLXJhZGl1czogMjBweDtcbiAgICAgICAgd2lkdGg6IGZpdC1jb250ZW50O1xuICAgICAgfVxuICAgICAgLnBsYW4tYmFkZ2UtLWZyZWUge1xuICAgICAgICBiYWNrZ3JvdW5kOiB2YXIoLS1pb24tY29sb3ItbGlnaHQtc2hhZGUsICNkN2Q4ZGEpO1xuICAgICAgICBjb2xvcjogdmFyKC0taW9uLWNvbG9yLWRhcmspO1xuICAgICAgfVxuICAgICAgLnBsYW4tYmFkZ2UtLXBybyB7XG4gICAgICAgIGJhY2tncm91bmQ6IHZhcigtLWlvbi1jb2xvci1wcmltYXJ5KTtcbiAgICAgICAgY29sb3I6ICNmZmY7XG4gICAgICB9XG4gICAgICAucGxhbi1iYWRnZS0tZW50ZXJwcmlzZSB7XG4gICAgICAgIGJhY2tncm91bmQ6ICNmNWM1NDI7XG4gICAgICAgIGNvbG9yOiAjMjIyO1xuICAgICAgfVxuICAgICAgLm1lbWJlcnMtbGlzdCB7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgICAgIGdhcDogOHB4O1xuICAgICAgfVxuICAgICAgLm1lbWJlcnMtc2hvdy1tb3JlIHtcbiAgICAgICAgYmFja2dyb3VuZDogbm9uZTtcbiAgICAgICAgYm9yZGVyOiBub25lO1xuICAgICAgICBjb2xvcjogdmFyKC0taW9uLWNvbG9yLXByaW1hcnkpO1xuICAgICAgICBmb250LXNpemU6IDE0cHg7XG4gICAgICAgIGZvbnQtd2VpZ2h0OiA1MDA7XG4gICAgICAgIGN1cnNvcjogcG9pbnRlcjtcbiAgICAgICAgcGFkZGluZzogOHB4IDA7XG4gICAgICB9XG4gICAgICAucmJhYy1kZWJ1ZyB7XG4gICAgICAgIG9wYWNpdHk6IDAuNztcbiAgICAgIH1cbiAgICAgIC5yYmFjLWRlYnVnX19ib2R5IHtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICAgICAgZ2FwOiA2cHg7XG4gICAgICAgIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7XG4gICAgICAgIGZvbnQtc2l6ZTogMC43OHJlbTtcbiAgICAgIH1cbiAgICAgIC5yYmFjLWRlYnVnX19yb3cge1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBnYXA6IDhweDtcbiAgICAgICAgYWxpZ24taXRlbXM6IGZsZXgtc3RhcnQ7XG4gICAgICB9XG4gICAgICAucmJhYy1kZWJ1Z19fbGFiZWwge1xuICAgICAgICBjb2xvcjogdmFyKC0taW9uLWNvbG9yLW1lZGl1bSk7XG4gICAgICAgIG1pbi13aWR0aDogNzJweDtcbiAgICAgICAgZmxleC1zaHJpbms6IDA7XG4gICAgICB9XG4gICAgICAucmJhYy1kZWJ1Z19fdmFsdWUge1xuICAgICAgICBjb2xvcjogdmFyKC0taW9uLWNvbG9yLWRhcmspO1xuICAgICAgICB3b3JkLWJyZWFrOiBicmVhay1hbGw7XG4gICAgICB9XG4gICAgICAucmJhYy1kZWJ1Z19fdmFsdWUtLXBlcm1zIHtcbiAgICAgICAgY29sb3I6IHZhcigtLWlvbi1jb2xvci1tZWRpdW0pO1xuICAgICAgfVxuICAgIGAsXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIE9yZ2FuaXphdGlvblZpZXdDb21wb25lbnQge1xuICBwcml2YXRlIG5hdiA9IGluamVjdChOYXZpZ2F0aW9uU2VydmljZSk7XG4gIHByaXZhdGUgaTE4biA9IGluamVjdChJMThuU2VydmljZSk7XG4gIHJlYWRvbmx5IGF1dGggPSBpbmplY3QoQXV0aFNlcnZpY2UpO1xuICBwcml2YXRlIG9yZ1NlcnZpY2UgPSBpbmplY3QoT3JnU2VydmljZSk7XG4gIHByaXZhdGUgdG9hc3QgPSBpbmplY3QoVG9hc3RTZXJ2aWNlKTtcbiAgcHJpdmF0ZSBlcnJvcnMgPSBpbmplY3QoVmFsdGVjaEVycm9yU2VydmljZSk7XG4gIHByaXZhdGUgbW9kYWxTZXJ2aWNlID0gaW5qZWN0KE1vZGFsU2VydmljZSk7XG4gIHByaXZhdGUgZmlyZXN0b3JlID0gaW5qZWN0KEZpcmVzdG9yZSk7XG4gIHByaXZhdGUgY29uZmlybURpYWxvZyA9IGluamVjdChDb25maXJtYXRpb25EaWFsb2dTZXJ2aWNlKTtcbiAgcHJpdmF0ZSByb3V0ZSA9IGluamVjdChBY3RpdmF0ZWRSb3V0ZSwgeyBvcHRpb25hbDogdHJ1ZSB9KTtcblxuICByZWFkb25seSBpc0RlYnVnID0gaXNEZXZNb2RlKCk7XG5cbiAgLyoqXG4gICAqIENvbmZpZyB2w61hIEBJbnB1dCAob2JqZWN0LWZpcnN0KS4gU2kgbm8gc2UgcGFzYSwgc2UgY2FlIGFsIHJvdXRlIGRhdGFcbiAgICogYG9yZ2FuaXphdGlvbkNvbmZpZ2AgKHBvYmxhZG8gcG9yIGBwcm92aWRlVmFsdGVjaE9yZ2FuaXphdGlvblJvdXRlc2ApLlxuICAgKiBgcmVzb2x2ZWRDb25maWdgIG1lcmdlYSBjb24gbG9zIGRlZmF1bHRzIOKAlCBgQElucHV0YCBnYW5hIHNvYnJlIHJvdXRlIGRhdGEuXG4gICAqL1xuICBASW5wdXQoKSBjb25maWc/OiBPcmdhbml6YXRpb25WaWV3Q29uZmlnO1xuXG4gIHJlYWRvbmx5IHJlc29sdmVkQ29uZmlnID0gY29tcHV0ZWQ8XG4gICAgUmVxdWlyZWQ8T21pdDxPcmdhbml6YXRpb25WaWV3Q29uZmlnLCAnb25PcmdFZGl0ZWQnIHwgJ29uTWVtYmVySW52aXRlZCcgfCAnb25Pd25lcnNoaXBUcmFuc2ZlcnJlZCcgfCAnb25MZWZ0T3JnJz4+ICZcbiAgICAgIFBpY2s8T3JnYW5pemF0aW9uVmlld0NvbmZpZywgJ29uT3JnRWRpdGVkJyB8ICdvbk1lbWJlckludml0ZWQnIHwgJ29uT3duZXJzaGlwVHJhbnNmZXJyZWQnIHwgJ29uTGVmdE9yZyc+XG4gID4oKCkgPT4ge1xuICAgIGNvbnN0IGZyb21Sb3V0ZSA9ICh0aGlzLnJvdXRlPy5zbmFwc2hvdC5kYXRhWydvcmdhbml6YXRpb25Db25maWcnXSA/PyB7fSkgYXMgT3JnYW5pemF0aW9uVmlld0NvbmZpZztcbiAgICBjb25zdCBtZXJnZWQ6IE9yZ2FuaXphdGlvblZpZXdDb25maWcgPSB7IC4uLmZyb21Sb3V0ZSwgLi4uKHRoaXMuY29uZmlnID8/IHt9KSB9O1xuICAgIHJldHVybiB7XG4gICAgICBzaG93SW5mbzogbWVyZ2VkLnNob3dJbmZvID8/IHRydWUsXG4gICAgICBzaG93TWVtYmVyczogbWVyZ2VkLnNob3dNZW1iZXJzID8/IHRydWUsXG4gICAgICBzaG93Um9sZXM6IG1lcmdlZC5zaG93Um9sZXMgPz8gdHJ1ZSxcbiAgICAgIHNob3dJbnZpdGU6IG1lcmdlZC5zaG93SW52aXRlID8/IHRydWUsXG4gICAgICBzaG93VHJhbnNmZXJPd25lcnNoaXA6IG1lcmdlZC5zaG93VHJhbnNmZXJPd25lcnNoaXAgPz8gdHJ1ZSxcbiAgICAgIHNob3dMZWF2ZTogbWVyZ2VkLnNob3dMZWF2ZSA/PyB0cnVlLFxuICAgICAgaTE4bk5hbWVzcGFjZTogbWVyZ2VkLmkxOG5OYW1lc3BhY2UgPz8gREVGQVVMVF9OQU1FU1BBQ0UsXG4gICAgICB2aWV3UGVybWlzc2lvbnNSb3V0ZTogbWVyZ2VkLnZpZXdQZXJtaXNzaW9uc1JvdXRlID8/IERFRkFVTFRfVklFV19QRVJNSVNTSU9OU19ST1VURSxcbiAgICAgIGxlYXZlUmVkaXJlY3RSb3V0ZTogbWVyZ2VkLmxlYXZlUmVkaXJlY3RSb3V0ZSA/PyBERUZBVUxUX0xFQVZFX1JFRElSRUNUX1JPVVRFLFxuICAgICAgb25PcmdFZGl0ZWQ6IG1lcmdlZC5vbk9yZ0VkaXRlZCxcbiAgICAgIG9uTWVtYmVySW52aXRlZDogbWVyZ2VkLm9uTWVtYmVySW52aXRlZCxcbiAgICAgIG9uT3duZXJzaGlwVHJhbnNmZXJyZWQ6IG1lcmdlZC5vbk93bmVyc2hpcFRyYW5zZmVycmVkLFxuICAgICAgb25MZWZ0T3JnOiBtZXJnZWQub25MZWZ0T3JnLFxuICAgIH07XG4gIH0pO1xuXG4gIC8qKiBOYW1lc3BhY2UgaTE4biByZXN1ZWx0byAoY2FwdHVyYWRvIHBhcmEgbGxhbWFkYXMgbm8tcmVhY3RpdmFzKS4gKi9cbiAgcHJpdmF0ZSBnZXQgbnMoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5yZXNvbHZlZENvbmZpZygpLmkxOG5OYW1lc3BhY2U7XG4gIH1cblxuICByZWFkb25seSBvcmcgPSBzaWduYWw8T3JnYW5pemF0aW9uIHwgbnVsbD4obnVsbCk7XG4gIHJlYWRvbmx5IGxvYWRpbmcgPSBzaWduYWwoZmFsc2UpO1xuICByZWFkb25seSBsZWF2aW5nID0gc2lnbmFsKGZhbHNlKTtcbiAgcHJpdmF0ZSByZWFkb25seSBvcmdMb2FkRXJyb3IgPSBzaWduYWw8dW5rbm93bj4obnVsbCk7XG5cbiAgcmVhZG9ubHkgb3JnRXJyb3JTdGF0ZSA9IGNvbXB1dGVkPEVtcHR5U3RhdGVNZXRhZGF0YSB8IG51bGw+KCgpID0+IHtcbiAgICB0aGlzLmkxOG4ubGFuZygpO1xuICAgIGNvbnN0IGVyciA9IHRoaXMub3JnTG9hZEVycm9yKCk7XG4gICAgaWYgKCFlcnIpIHJldHVybiBudWxsO1xuICAgIHJldHVybiBjcmVhdGVFcnJvclN0YXRlUHJvcHMoZXJyLCB7XG4gICAgICB0aXRsZTogeyBvZmZsaW5lOiB0aGlzLnR0KCdvZmZsaW5lVGl0bGUnKSwgZXJyb3I6IHRoaXMudHQoJ2Vycm9yVGl0bGUnKSB9LFxuICAgICAgZGVzY3JpcHRpb246IHtcbiAgICAgICAgb2ZmbGluZTogdGhpcy50dCgnb2ZmbGluZUhpbnQnKSxcbiAgICAgICAgZXJyb3I6IGludGVycHJldEVycm9yKGVycikubWVzc2FnZSxcbiAgICAgIH0sXG4gICAgICByZXRyeUxhYmVsOiB0aGlzLnR0KCdyZXRyeScpLFxuICAgICAgb25SZXRyeTogKCkgPT4gdGhpcy5sb2FkT3JnKCksXG4gICAgICByZXRyeWluZzogdGhpcy5sb2FkaW5nKCksXG4gICAgfSk7XG4gIH0pO1xuXG4gIHJlYWRvbmx5IG1lbWJlcnMgPSBzaWduYWw8TWVtYmVyRGV0YWlsW10+KFtdKTtcbiAgcmVhZG9ubHkgbWVtYmVyc0xvYWRpbmcgPSBzaWduYWwoZmFsc2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IG1lbWJlcnNMb2FkRXJyb3IgPSBzaWduYWw8dW5rbm93bj4obnVsbCk7XG4gIHJlYWRvbmx5IG1lbWJlcnNOZXh0VG9rZW4gPSBzaWduYWw8c3RyaW5nIHwgbnVsbD4obnVsbCk7XG4gIHJlYWRvbmx5IGxvYWRpbmdNb3JlTWVtYmVycyA9IHNpZ25hbChmYWxzZSk7XG4gIHJlYWRvbmx5IHNob3dBbGxNZW1iZXJzID0gc2lnbmFsKGZhbHNlKTtcbiAgcmVhZG9ubHkgdmlzaWJsZU1lbWJlcnMgPSBjb21wdXRlZCgoKSA9PiAodGhpcy5zaG93QWxsTWVtYmVycygpID8gdGhpcy5tZW1iZXJzKCkgOiB0aGlzLm1lbWJlcnMoKS5zbGljZSgwLCAzKSkpO1xuICByZWFkb25seSB0cmFuc2ZlcnJpbmcgPSBzaWduYWwoZmFsc2UpO1xuICByZWFkb25seSBhdmFpbGFibGVSb2xlcyA9IHNpZ25hbDxPcmdSb2xlW10+KFtcbiAgICB7IGlkOiAndmlld2VyJywgbmFtZTogJ3ZpZXdlcicgfSxcbiAgICB7IGlkOiAnZWRpdG9yJywgbmFtZTogJ2VkaXRvcicgfSxcbiAgICB7IGlkOiAnYWRtaW4nLCBuYW1lOiAnYWRtaW4nIH0sXG4gIF0pO1xuXG4gIHJlYWRvbmx5IGFjdGl2ZU9yZ0lkID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IHUgPSB0aGlzLmF1dGgudXNlcigpIGFzIHtcbiAgICAgIGFjdGl2ZU9yZ0lkPzogc3RyaW5nO1xuICAgICAgYWN0aXZlT3JnPzogc3RyaW5nO1xuICAgIH0gfCBudWxsO1xuICAgIHJldHVybiB1Py5hY3RpdmVPcmdJZCA/PyB1Py5hY3RpdmVPcmcgPz8gJyc7XG4gIH0pO1xuXG4gIHJlYWRvbmx5IHVzZXJJZCA9IGNvbXB1dGVkKCgpID0+IHRoaXMuYXV0aC51c2VyKCk/LnVzZXJJZCA/PyAnJyk7XG5cbiAgcmVhZG9ubHkgaXNPd25lciA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBvID0gdGhpcy5vcmcoKTtcbiAgICBjb25zdCB1aWQgPSB0aGlzLnVzZXJJZCgpO1xuICAgIHJldHVybiAhIW8gJiYgISF1aWQgJiYgby5vd25lcklkID09PSB1aWQ7XG4gIH0pO1xuXG4gIHJlYWRvbmx5IGNhbkVkaXRPcmcgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmlzT3duZXIoKSB8fCB0aGlzLmF1dGguaGFzUGVybWlzc2lvbignb3JnOm1hbmFnZScpKTtcblxuICByZWFkb25seSBjYW5NYW5hZ2VNZW1iZXJzID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGlmICh0aGlzLmlzT3duZXIoKSkgcmV0dXJuIHRydWU7XG4gICAgY29uc3QgdWlkID0gdGhpcy51c2VySWQoKTtcbiAgICBjb25zdCBtZSA9IHRoaXMubWVtYmVycygpLmZpbmQobSA9PiBtLnVzZXJJZCA9PT0gdWlkKTtcbiAgICBpZiAoIW1lKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIG1lLnJvbGVzLnNvbWUociA9PiByID09PSAnYWRtaW4nIHx8IHIgPT09ICdzdXBlcl9hZG1pbicpO1xuICB9KTtcblxuICByZWFkb25seSBwYWdlVGl0bGUgPSBjb21wdXRlZCgoKSA9PiB0aGlzLnR0KCdwYWdlVGl0bGUnKSk7XG4gIHJlYWRvbmx5IHBhZ2VEZXNjcmlwdGlvbiA9IGNvbXB1dGVkKCgpID0+IHRoaXMudHQoJ3BhZ2VEZXNjcmlwdGlvbicpKTtcblxuICByZWFkb25seSBwbGFuTGFiZWwgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgcGxhbiA9IHRoaXMub3JnKCk/LnBsYW47XG4gICAgaWYgKHBsYW4gPT09ICdwcm8nKSByZXR1cm4gdGhpcy50dCgncGxhblBybycpO1xuICAgIGlmIChwbGFuID09PSAnZW50ZXJwcmlzZScpIHJldHVybiB0aGlzLnR0KCdwbGFuRW50ZXJwcmlzZScpO1xuICAgIHJldHVybiB0aGlzLnR0KCdwbGFuRnJlZScpO1xuICB9KTtcblxuICByZWFkb25seSBlZGl0QnV0dG9uUHJvcHMgPSBjb21wdXRlZDxQYXJ0aWFsPEJ1dHRvbk1ldGFkYXRhPj4oKCkgPT4gKHtcbiAgICB0ZXh0OiB0aGlzLnR0KCdlZGl0Q3RhJyksXG4gICAgY29sb3I6ICdwcmltYXJ5JyxcbiAgICBmaWxsOiAnb3V0bGluZScsXG4gICAgc2l6ZTogJ3NtYWxsJyxcbiAgICBzaGFwZTogJ3JvdW5kJyxcbiAgICB0eXBlOiAnYnV0dG9uJyxcbiAgfSkpO1xuXG4gIHJlYWRvbmx5IGxlYXZlQnV0dG9uUHJvcHMgPSBjb21wdXRlZDxQYXJ0aWFsPEJ1dHRvbk1ldGFkYXRhPj4oKCkgPT4gKHtcbiAgICB0ZXh0OiB0aGlzLnR0KCdsZWF2ZUN0YScpLFxuICAgIHRva2VuOiAnb3JnLWxlYXZlJyxcbiAgICBjb2xvcjogJ2RhcmsnLFxuICAgIGZpbGw6ICdvdXRsaW5lJyxcbiAgICBzaXplOiAnZGVmYXVsdCcsXG4gICAgc2hhcGU6ICdyb3VuZCcsXG4gICAgdHlwZTogJ2J1dHRvbicsXG4gICAgc3RhdGU6IHRoaXMuaXNPd25lcigpIHx8IHRoaXMubGVhdmluZygpID8gQ29tcG9uZW50U3RhdGVzLkRJU0FCTEVEIDogQ29tcG9uZW50U3RhdGVzLkVOQUJMRUQsXG4gIH0pKTtcblxuICByZWFkb25seSB0cmFuc2ZlcmFibGVNZW1iZXJzID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5tZW1iZXJzKCkuZmlsdGVyKG0gPT4gbS51c2VySWQgIT09IHRoaXMudXNlcklkKCkpKTtcblxuICByZWFkb25seSB2aWV3UGVybWlzc2lvbnNCdXR0b25Qcm9wcyA9IGNvbXB1dGVkPFBhcnRpYWw8QnV0dG9uTWV0YWRhdGE+PigoKSA9PiAoe1xuICAgIHRleHQ6IHRoaXMudHQoJ3JvbGVzVmlld1Blcm1zJyksXG4gICAgY29sb3I6ICdwcmltYXJ5JyxcbiAgICBmaWxsOiAnb3V0bGluZScsXG4gICAgc2l6ZTogJ2RlZmF1bHQnLFxuICAgIHNoYXBlOiAncm91bmQnLFxuICAgIHR5cGU6ICdidXR0b24nLFxuICAgIHRva2VuOiAnb3JnLXZpZXctcGVybWlzc2lvbnMnLFxuICB9KSk7XG5cbiAgcmVhZG9ubHkgdHJhbnNmZXJCdXR0b25Qcm9wcyA9IGNvbXB1dGVkPFBhcnRpYWw8QnV0dG9uTWV0YWRhdGE+PigoKSA9PiAoe1xuICAgIHRleHQ6IHRoaXMudHQoJ3RyYW5zZmVyQ3RhJyksXG4gICAgdG9rZW46ICdvcmctdHJhbnNmZXItc3VibWl0JyxcbiAgICBjb2xvcjogJ2RhcmsnLFxuICAgIGZpbGw6ICdvdXRsaW5lJyxcbiAgICBzaXplOiAnZGVmYXVsdCcsXG4gICAgc2hhcGU6ICdyb3VuZCcsXG4gICAgdHlwZTogJ2J1dHRvbicsXG4gICAgc3RhdGU6IHRoaXMudHJhbnNmZXJyaW5nKCkgPyBDb21wb25lbnRTdGF0ZXMuRElTQUJMRUQgOiBDb21wb25lbnRTdGF0ZXMuRU5BQkxFRCxcbiAgfSkpO1xuXG4gIHJlYWRvbmx5IG9wZW5JbnZpdGVCdXR0b25Qcm9wcyA9IGNvbXB1dGVkPFBhcnRpYWw8QnV0dG9uTWV0YWRhdGE+PigoKSA9PiAoe1xuICAgIHRleHQ6IHRoaXMudHQoJ2ludml0ZU9wZW4nKSxcbiAgICBjb2xvcjogJ3ByaW1hcnknLFxuICAgIGZpbGw6ICdzb2xpZCcsXG4gICAgc2l6ZTogJ2RlZmF1bHQnLFxuICAgIHNoYXBlOiAncm91bmQnLFxuICAgIHR5cGU6ICdidXR0b24nLFxuICB9KSk7XG5cbiAgLyoqIEd1YXJkYSBwYXJhIGRldGVjdGFyIGVsIHByaW1lciBkaXNwYXJvIGRlbCBlZmZlY3QgKGV2aXRhIGRvYmxlIGNhcmdhKS4gKi9cbiAgcHJpdmF0ZSBsYXN0TG9hZGVkT3JnSWQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIGNvbnN0IG5zID0gdGhpcy5ucztcbiAgICBpZiAoIXRoaXMuaTE4bi5oYXNOYW1lc3BhY2UobnMpKSB7XG4gICAgICB0aGlzLmkxOG4ucmVnaXN0ZXJDb250ZW50KG5zLCBPUkdBTklaQVRJT05fVklFV19JMThOKTtcbiAgICB9XG4gICAgdGhpcy5uYXYuc2V0QmFja0hlYWRlcigncGFnZVRpdGxlJywgbnMsIHsgd2l0aE1lbnU6IHRydWUgfSk7XG5cbiAgICAvLyBBdXRvLXJlbG9hZCBlbiBvcmctc3dpdGNoOiByZWFjY2lvbmEgYSBhY3RpdmVPcmdJZCgpIHkgcmVjYXJnYSBvcmcgKyBtaWVtYnJvc1xuICAgIC8vIGN1YW5kbyBlbCB1c3VhcmlvIGNhbWJpYSBkZSBvcmdhbml6YWNpw7NuIGFjdGl2YSBtaWVudHJhcyBsYSB2aXN0YSBlc3TDoVxuICAgIC8vIG1vbnRhZGEuIEN1YnJlIHRhbWJpw6luIGxhIGNhcmdhIGluaWNpYWwg4oCUIGBsYXN0TG9hZGVkT3JnSWRgIGV2aXRhIHJlY2FyZ2FyXG4gICAgLy8gZG9zIHZlY2VzIGVsIG1pc21vIGlkIChwLmVqLiBzaSBlbCBlZmZlY3QgcmUtY29ycmUgcG9yIG90cmEgZGVwZW5kZW5jaWEpLlxuICAgIC8vIGBhbGxvd1NpZ25hbFdyaXRlc2AgcG9ycXVlIGxhcyBsb2FkIGZucyBlc2NyaWJlbiBzaWduYWxzIHPDrW5jcm9uYW1lbnRlXG4gICAgLy8gKGxvYWRpbmcvZXJyb3IvdG9rZW4pIOKAlCBBbmd1bGFyIDE4IGJsb3F1ZWEgd3JpdGVzIGVuIGVmZmVjdCBzaW4gZWwgZmxhZy5cbiAgICBlZmZlY3QoXG4gICAgICAoKSA9PiB7XG4gICAgICAgIGNvbnN0IG9yZ0lkID0gdGhpcy5hY3RpdmVPcmdJZCgpO1xuICAgICAgICBpZiAob3JnSWQgPT09IHRoaXMubGFzdExvYWRlZE9yZ0lkKSByZXR1cm47XG4gICAgICAgIHRoaXMubGFzdExvYWRlZE9yZ0lkID0gb3JnSWQ7XG4gICAgICAgIHRoaXMubG9hZE9yZygpO1xuICAgICAgICB0aGlzLmxvYWRNZW1iZXJzKCk7XG4gICAgICAgIHRoaXMubG9hZFJvbGVzKCk7XG4gICAgICB9LFxuICAgICAgeyBhbGxvd1NpZ25hbFdyaXRlczogdHJ1ZSB9XG4gICAgKTtcblxuICAgIGNvbm5lY3RQYWdlUmVmcmVzaChhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChbdGhpcy5sb2FkT3JnKCksIHRoaXMubG9hZE1lbWJlcnMoKV0pO1xuICAgIH0pO1xuICB9XG5cbiAgb25FZGl0KCk6IHZvaWQge1xuICAgIHZvaWQgdGhpcy5tb2RhbFNlcnZpY2Uub3Blbih7XG4gICAgICBjb21wb25lbnQ6IEVkaXRPcmdNb2RhbENvbXBvbmVudCxcbiAgICAgIGNvbXBvbmVudFByb3BzOiB7XG4gICAgICAgIG9yZzogdGhpcy5vcmcoKSxcbiAgICAgICAgb25TdWNjZXNzOiAodXBkYXRlZDogT3JnYW5pemF0aW9uKSA9PiB7XG4gICAgICAgICAgdGhpcy5vcmcuc2V0KHVwZGF0ZWQpO1xuICAgICAgICAgIHRoaXMucmVzb2x2ZWRDb25maWcoKS5vbk9yZ0VkaXRlZD8uKCk7XG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgYnJlYWtwb2ludHM6IHtcbiAgICAgICAgYnJlYWtwb2ludHM6IFswLCAwLjg1XSxcbiAgICAgICAgaW5pdGlhbEJyZWFrcG9pbnQ6IDAuODUsXG4gICAgICAgIHNob3dIYW5kbGU6IHRydWUsXG4gICAgICB9LFxuICAgICAgYmFja2Ryb3BEaXNtaXNzOiB0cnVlLFxuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgb25MZWF2ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5pc093bmVyKCkgfHwgdGhpcy5sZWF2aW5nKCkpIHJldHVybjtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmNvbmZpcm1EaWFsb2cuY29uZmlybURlc3RydWN0aXZlKHtcbiAgICAgIHRpdGxlOiB0aGlzLnR0KCdsZWF2ZVRpdGxlJyksXG4gICAgICBtZXNzYWdlOiB0aGlzLnR0KCdsZWF2ZUNvbmZpcm0nKSxcbiAgICAgIGNvbmZpcm1CdXR0b246IHsgdGV4dDogdGhpcy50dCgnbGVhdmVDdGEnKSB9LFxuICAgICAgY2FuY2VsQnV0dG9uOiB7IHRleHQ6IHRoaXMudHQoJ2NhbmNlbEN0YScpIH0sXG4gICAgfSk7XG4gICAgaWYgKCFyZXN1bHQuY29uZmlybWVkKSByZXR1cm47XG4gICAgY29uc3Qgb3JnSWQgPSB0aGlzLmFjdGl2ZU9yZ0lkKCk7XG4gICAgaWYgKCFvcmdJZCkgcmV0dXJuO1xuICAgIHRoaXMubGVhdmluZy5zZXQodHJ1ZSk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGZpcnN0VmFsdWVGcm9tKHRoaXMub3JnU2VydmljZS5sZWF2ZU9yZyhvcmdJZCkpO1xuICAgICAgdGhpcy50b2FzdC5zaG93KHtcbiAgICAgICAgbWVzc2FnZTogdGhpcy50dCgnbGVhdmVTdWNjZXNzJyksXG4gICAgICAgIGNvbG9yOiAnZGFyaycsXG4gICAgICAgIGR1cmF0aW9uOiAzNTAwLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBjZmcgPSB0aGlzLnJlc29sdmVkQ29uZmlnKCk7XG4gICAgICB0aGlzLm5hdi5uYXZpZ2F0ZUJ5VXJsKGNmZy5sZWF2ZVJlZGlyZWN0Um91dGUpO1xuICAgICAgY2ZnLm9uTGVmdE9yZz8uKCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aGlzLmVycm9ycy5oYW5kbGUoZXJyLCB7XG4gICAgICAgIGNvbnRleHQ6ICdvcmdhbml6YXRpb24ubGVhdmUnLFxuICAgICAgICBmYWxsYmFja0tleTogJ2xlYXZlRXJyb3InLFxuICAgICAgICBpMThuTmFtZXNwYWNlOiB0aGlzLm5zLFxuICAgICAgfSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMubGVhdmluZy5zZXQoZmFsc2UpO1xuICAgIH1cbiAgfVxuXG4gIG9uT3Blbkludml0ZSgpOiB2b2lkIHtcbiAgICB2b2lkIHRoaXMubW9kYWxTZXJ2aWNlLm9wZW4oe1xuICAgICAgY29tcG9uZW50OiBJbnZpdGVNZW1iZXJNb2RhbENvbXBvbmVudCxcbiAgICAgIGNvbXBvbmVudFByb3BzOiB7XG4gICAgICAgIG9yZ0lkOiB0aGlzLmFjdGl2ZU9yZ0lkKCksXG4gICAgICAgIGV4aXN0aW5nTWVtYmVySWRzOiB0aGlzLm1lbWJlcnMoKS5tYXAobSA9PiBtLnVzZXJJZCksXG4gICAgICAgIG9uU3VjY2VzczogKCkgPT4ge1xuICAgICAgICAgIHRoaXMubG9hZE1lbWJlcnMoKTtcbiAgICAgICAgICB0aGlzLnJlc29sdmVkQ29uZmlnKCkub25NZW1iZXJJbnZpdGVkPy4oKTtcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBicmVha3BvaW50czoge1xuICAgICAgICBicmVha3BvaW50czogWzAsIDAuOTJdLFxuICAgICAgICBpbml0aWFsQnJlYWtwb2ludDogMC45MixcbiAgICAgICAgc2hvd0hhbmRsZTogdHJ1ZSxcbiAgICAgIH0sXG4gICAgICBiYWNrZHJvcERpc21pc3M6IHRydWUsXG4gICAgfSk7XG4gIH1cblxuICBvblZpZXdQZXJtaXNzaW9ucygpOiB2b2lkIHtcbiAgICB0aGlzLm5hdi5uYXZpZ2F0ZUJ5VXJsKHRoaXMucmVzb2x2ZWRDb25maWcoKS52aWV3UGVybWlzc2lvbnNSb3V0ZSk7XG4gIH1cblxuICBvbk9wZW5UcmFuc2ZlcigpOiB2b2lkIHtcbiAgICB2b2lkIHRoaXMubW9kYWxTZXJ2aWNlLm9wZW4oe1xuICAgICAgY29tcG9uZW50OiBUcmFuc2Zlck93bmVyc2hpcE1vZGFsQ29tcG9uZW50LFxuICAgICAgY29tcG9uZW50UHJvcHM6IHtcbiAgICAgICAgbWVtYmVyczogdGhpcy50cmFuc2ZlcmFibGVNZW1iZXJzKCksXG4gICAgICAgIG9uQ29uZmlybTogKG5ld093bmVySWQ6IHN0cmluZykgPT4gdm9pZCB0aGlzLm9uVHJhbnNmZXIobmV3T3duZXJJZCksXG4gICAgICB9LFxuICAgICAgYnJlYWtwb2ludHM6IHtcbiAgICAgICAgYnJlYWtwb2ludHM6IFswLCAwLjc1XSxcbiAgICAgICAgaW5pdGlhbEJyZWFrcG9pbnQ6IDAuNzUsXG4gICAgICAgIHNob3dIYW5kbGU6IHRydWUsXG4gICAgICB9LFxuICAgICAgYmFja2Ryb3BEaXNtaXNzOiB0cnVlLFxuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgb25UcmFuc2ZlcihuZXdPd25lcklkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIW5ld093bmVySWQgfHwgdGhpcy50cmFuc2ZlcnJpbmcoKSkgcmV0dXJuO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuY29uZmlybURpYWxvZy5jb25maXJtRGVzdHJ1Y3RpdmUoe1xuICAgICAgdGl0bGU6IHRoaXMudHQoJ3RyYW5zZmVyVGl0bGUnKSxcbiAgICAgIG1lc3NhZ2U6IHRoaXMudHQoJ3RyYW5zZmVyQ29uZmlybScpLFxuICAgICAgY29uZmlybUJ1dHRvbjogeyB0ZXh0OiB0aGlzLnR0KCd0cmFuc2ZlckN0YScpIH0sXG4gICAgICBjYW5jZWxCdXR0b246IHsgdGV4dDogdGhpcy50dCgnY2FuY2VsQ3RhJykgfSxcbiAgICB9KTtcbiAgICBpZiAoIXJlc3VsdC5jb25maXJtZWQpIHJldHVybjtcbiAgICBjb25zdCBvcmdJZCA9IHRoaXMuYWN0aXZlT3JnSWQoKTtcbiAgICBpZiAoIW9yZ0lkKSByZXR1cm47XG4gICAgdGhpcy50cmFuc2ZlcnJpbmcuc2V0KHRydWUpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBmaXJzdFZhbHVlRnJvbSh0aGlzLm9yZ1NlcnZpY2UudHJhbnNmZXJPd25lcnNoaXAob3JnSWQsIG5ld093bmVySWQpKTtcbiAgICAgIHRoaXMudG9hc3Quc2hvdyh7XG4gICAgICAgIG1lc3NhZ2U6IHRoaXMudHQoJ3RyYW5zZmVyU3VjY2VzcycpLFxuICAgICAgICBjb2xvcjogJ2RhcmsnLFxuICAgICAgICBkdXJhdGlvbjogMzUwMCxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5sb2FkT3JnKCk7XG4gICAgICB0aGlzLmxvYWRNZW1iZXJzKCk7XG4gICAgICB0aGlzLnJlc29sdmVkQ29uZmlnKCkub25Pd25lcnNoaXBUcmFuc2ZlcnJlZD8uKCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aGlzLmVycm9ycy5oYW5kbGUoZXJyLCB7XG4gICAgICAgIGNvbnRleHQ6ICdvcmdhbml6YXRpb24udHJhbnNmZXInLFxuICAgICAgICBmYWxsYmFja0tleTogJ3RyYW5zZmVyRXJyb3InLFxuICAgICAgICBpMThuTmFtZXNwYWNlOiB0aGlzLm5zLFxuICAgICAgfSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMudHJhbnNmZXJyaW5nLnNldChmYWxzZSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBsb2FkT3JnKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG9yZ0lkID0gdGhpcy5hY3RpdmVPcmdJZCgpO1xuICAgIGlmICghb3JnSWQpIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB0aGlzLmxvYWRpbmcuc2V0KHRydWUpO1xuICAgIHRoaXMub3JnTG9hZEVycm9yLnNldChudWxsKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4ocmVzb2x2ZSA9PiB7XG4gICAgICB0aGlzLm9yZ1NlcnZpY2UuZ2V0T3JnKG9yZ0lkKS5zdWJzY3JpYmUoe1xuICAgICAgICBuZXh0OiBvcmcgPT4ge1xuICAgICAgICAgIHRoaXMub3JnLnNldChvcmcpO1xuICAgICAgICAgIHRoaXMubG9hZGluZy5zZXQoZmFsc2UpO1xuICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3I6IGVyciA9PiB7XG4gICAgICAgICAgdGhpcy5vcmdMb2FkRXJyb3Iuc2V0KGVycik7XG4gICAgICAgICAgdGhpcy5sb2FkaW5nLnNldChmYWxzZSk7XG4gICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBsb2FkTWVtYmVycygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBvcmdJZCA9IHRoaXMuYWN0aXZlT3JnSWQoKTtcbiAgICBpZiAoIW9yZ0lkKSByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgdGhpcy5tZW1iZXJzTG9hZGluZy5zZXQodHJ1ZSk7XG4gICAgdGhpcy5tZW1iZXJzTmV4dFRva2VuLnNldChudWxsKTtcbiAgICB0aGlzLnNob3dBbGxNZW1iZXJzLnNldChmYWxzZSk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KHJlc29sdmUgPT4ge1xuICAgICAgdGhpcy5vcmdTZXJ2aWNlLmdldE9yZ01lbWJlcnMob3JnSWQsIHsgbGltaXQ6IDIwIH0pLnN1YnNjcmliZSh7XG4gICAgICAgIG5leHQ6IGFzeW5jIHJlcyA9PiB7XG4gICAgICAgICAgY29uc3QgY2FyZHMgPSBhd2FpdCB0aGlzLmVucmljaFdpdGhQcm9maWxlcyhyZXMubWVtYmVycyk7XG4gICAgICAgICAgdGhpcy5tZW1iZXJzLnNldChjYXJkcyk7XG4gICAgICAgICAgdGhpcy5tZW1iZXJzTmV4dFRva2VuLnNldChyZXMubmV4dFRva2VuID8/IG51bGwpO1xuICAgICAgICAgIHRoaXMubWVtYmVyc0xvYWRpbmcuc2V0KGZhbHNlKTtcbiAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH0sXG4gICAgICAgIGVycm9yOiBlcnIgPT4ge1xuICAgICAgICAgIHRoaXMubWVtYmVyc0xvYWRFcnJvci5zZXQoZXJyKTtcbiAgICAgICAgICB0aGlzLm1lbWJlcnNMb2FkaW5nLnNldChmYWxzZSk7XG4gICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBsb2FkTW9yZU1lbWJlcnMoKTogdm9pZCB7XG4gICAgY29uc3Qgb3JnSWQgPSB0aGlzLmFjdGl2ZU9yZ0lkKCk7XG4gICAgY29uc3QgdG9rZW4gPSB0aGlzLm1lbWJlcnNOZXh0VG9rZW4oKTtcbiAgICBpZiAoIW9yZ0lkIHx8ICF0b2tlbiB8fCB0aGlzLmxvYWRpbmdNb3JlTWVtYmVycygpKSByZXR1cm47XG4gICAgdGhpcy5sb2FkaW5nTW9yZU1lbWJlcnMuc2V0KHRydWUpO1xuICAgIHRoaXMub3JnU2VydmljZS5nZXRPcmdNZW1iZXJzKG9yZ0lkLCB7IGxpbWl0OiAyMCwgbmV4dFRva2VuOiB0b2tlbiB9KS5zdWJzY3JpYmUoe1xuICAgICAgbmV4dDogYXN5bmMgcmVzID0+IHtcbiAgICAgICAgY29uc3QgY2FyZHMgPSBhd2FpdCB0aGlzLmVucmljaFdpdGhQcm9maWxlcyhyZXMubWVtYmVycyk7XG4gICAgICAgIHRoaXMubWVtYmVycy51cGRhdGUocHJldiA9PiBbLi4ucHJldiwgLi4uY2FyZHNdKTtcbiAgICAgICAgdGhpcy5tZW1iZXJzTmV4dFRva2VuLnNldChyZXMubmV4dFRva2VuID8/IG51bGwpO1xuICAgICAgICB0aGlzLmxvYWRpbmdNb3JlTWVtYmVycy5zZXQoZmFsc2UpO1xuICAgICAgfSxcbiAgICAgIGVycm9yOiBlcnIgPT4ge1xuICAgICAgICB0aGlzLmVycm9ycy5oYW5kbGUoZXJyLCB7XG4gICAgICAgICAgY29udGV4dDogJ29yZ2FuaXphdGlvbi5sb2FkTW9yZU1lbWJlcnMnLFxuICAgICAgICAgIGZhbGxiYWNrS2V5OiAnbWVtYmVyc0Vycm9yJyxcbiAgICAgICAgICBpMThuTmFtZXNwYWNlOiB0aGlzLm5zLFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5sb2FkaW5nTW9yZU1lbWJlcnMuc2V0KGZhbHNlKTtcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGVucmljaFdpdGhQcm9maWxlcyhtZW1iZXJzOiBPcmdNZW1iZXJbXSk6IFByb21pc2U8TWVtYmVyRGV0YWlsW10+IHtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFxuICAgICAgbWVtYmVycy5tYXAoYXN5bmMgbSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3Qgc25hcCA9IGF3YWl0IGdldERvYyhkb2ModGhpcy5maXJlc3RvcmUsIGBwcm9maWxlcy8ke20udXNlcklkfWApKTtcbiAgICAgICAgICBjb25zdCBwID0gc25hcC5leGlzdHMoKSA/IHNuYXAuZGF0YSgpIDoge307XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLm0sXG4gICAgICAgICAgICBoYW5kbGU6IHBbJ2hhbmRsZSddIGFzIHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGF2YXRhcjogKHBbJ2F2YXRhclVybCddID8/IHBbJ2F2YXRhciddKSBhcyBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgICAgICAgICBuYW1lOiAocFsnbmFtZSddIGFzIHN0cmluZyB8IHVuZGVmaW5lZCkgfHwgbS5uYW1lLFxuICAgICAgICAgIH0gYXMgTWVtYmVyRGV0YWlsO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICByZXR1cm4gbSBhcyBNZW1iZXJEZXRhaWw7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcbiAgICByZXR1cm4gcmVzdWx0cy5tYXAociA9PiAoci5zdGF0dXMgPT09ICdmdWxmaWxsZWQnID8gci52YWx1ZSA6ICh7fSBhcyBNZW1iZXJEZXRhaWwpKSk7XG4gIH1cblxuICBsb2FkUm9sZXMoKTogdm9pZCB7XG4gICAgY29uc3Qgb3JnSWQgPSB0aGlzLmFjdGl2ZU9yZ0lkKCk7XG4gICAgaWYgKCFvcmdJZCkgcmV0dXJuO1xuICAgIHRoaXMub3JnU2VydmljZS5saXN0T3JnUm9sZXMob3JnSWQpLnN1YnNjcmliZSh7XG4gICAgICBuZXh0OiByb2xlcyA9PiB7XG4gICAgICAgIGlmIChyb2xlcy5sZW5ndGgpIHRoaXMuYXZhaWxhYmxlUm9sZXMuc2V0KHJvbGVzKTtcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICByb2xlTGFiZWwocm9sZUlkT3JOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIC8vIFRyeSB0byBmaW5kIGJ5IGlkIGZpcnN0IChVVUlEKSwgdGhlbiBieSBuYW1lXG4gICAgY29uc3QgZm91bmQgPSB0aGlzLmF2YWlsYWJsZVJvbGVzKCkuZmluZChyID0+IHIuaWQgPT09IHJvbGVJZE9yTmFtZSB8fCByLm5hbWUgPT09IHJvbGVJZE9yTmFtZSk7XG4gICAgY29uc3QgbmFtZSA9IGZvdW5kPy5uYW1lID8/IHJvbGVJZE9yTmFtZTtcbiAgICBjb25zdCBrZXlNYXA6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICB2aWV3ZXI6ICdyb2xlVmlld2VyJyxcbiAgICAgIGVkaXRvcjogJ3JvbGVFZGl0b3InLFxuICAgICAgYWRtaW46ICdyb2xlQWRtaW4nLFxuICAgICAgc3VwZXJfYWRtaW46ICdyb2xlU3VwZXJBZG1pbicsXG4gICAgfTtcbiAgICBjb25zdCBrZXkgPSBrZXlNYXBbbmFtZV0gPz8gbmFtZTtcbiAgICBjb25zdCBsYWJlbCA9IHRoaXMudHQoa2V5KTtcbiAgICByZXR1cm4gbGFiZWwgJiYgIWxhYmVsLnN0YXJ0c1dpdGgoJ1snKSA/IGxhYmVsIDogbmFtZTtcbiAgfVxuXG4gIHBlcm1pc3Npb25MYWJlbChwZXJtOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmIChwZXJtID09PSAnKjoqJykgcmV0dXJuIHRoaXMudHQoJ3Blcm1BbGwnKTtcbiAgICBjb25zdCBbcmVzb3VyY2UsIGFjdGlvbl0gPSBwZXJtLnNwbGl0KCc6Jyk7XG4gICAgY29uc3QgcmVzS2V5OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICAgICAgdXNlcnM6ICdwZXJtVXNlcnMnLFxuICAgICAgZG9jdW1lbnRzOiAncGVybURvY3VtZW50cycsXG4gICAgICByb2xlczogJ3Blcm1Sb2xlcycsXG4gICAgICBtZWRpYTogJ3Blcm1NZWRpYScsXG4gICAgICB0ZW1wbGF0ZXM6ICdwZXJtVGVtcGxhdGVzJyxcbiAgICAgICcqJzogJ3Blcm1BbGwnLFxuICAgIH07XG4gICAgY29uc3QgYWN0S2V5OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICAgICAgcmVhZDogJ3Blcm1SZWFkJyxcbiAgICAgIHdyaXRlOiAncGVybVdyaXRlJyxcbiAgICAgIGNyZWF0ZTogJ3Blcm1DcmVhdGUnLFxuICAgICAgZGVsZXRlOiAncGVybURlbGV0ZScsXG4gICAgICBtYW5hZ2U6ICdwZXJtTWFuYWdlJyxcbiAgICAgICcqJzogJ3Blcm1BbGwnLFxuICAgIH07XG4gICAgY29uc3QgcmVzID0gdGhpcy50dChyZXNLZXlbcmVzb3VyY2VdID8/IHJlc291cmNlKTtcbiAgICBjb25zdCBhY3QgPSB0aGlzLnR0KGFjdEtleVthY3Rpb25dID8/IGFjdGlvbik7XG4gICAgcmV0dXJuIGAke3Jlc306ICR7YWN0fWA7XG4gIH1cblxuICBvblZpZXdNZW1iZXIobWVtYmVyOiBNZW1iZXJEZXRhaWwpOiB2b2lkIHtcbiAgICB2b2lkIHRoaXMubW9kYWxTZXJ2aWNlLm9wZW4oe1xuICAgICAgY29tcG9uZW50OiBNZW1iZXJEZXRhaWxNb2RhbENvbXBvbmVudCxcbiAgICAgIGNvbXBvbmVudFByb3BzOiB7XG4gICAgICAgIG1lbWJlcixcbiAgICAgICAgb3JnSWQ6IHRoaXMuYWN0aXZlT3JnSWQoKSxcbiAgICAgICAgYXZhaWxhYmxlUm9sZXM6IHRoaXMuYXZhaWxhYmxlUm9sZXMoKSxcbiAgICAgICAgY2FuTWFuYWdlOiB0aGlzLmNhbk1hbmFnZU1lbWJlcnMoKSAmJiBtZW1iZXIudXNlcklkICE9PSB0aGlzLnVzZXJJZCgpLFxuICAgICAgICBpc1NlbGY6IG1lbWJlci51c2VySWQgPT09IHRoaXMudXNlcklkKCksXG4gICAgICAgIG9uQ2hhbmdlZDogKCkgPT4gdGhpcy5sb2FkTWVtYmVycygpLFxuICAgICAgfSxcbiAgICAgIGJyZWFrcG9pbnRzOiB7XG4gICAgICAgIGJyZWFrcG9pbnRzOiBbMCwgMC43XSxcbiAgICAgICAgaW5pdGlhbEJyZWFrcG9pbnQ6IDAuNyxcbiAgICAgICAgc2hvd0hhbmRsZTogdHJ1ZSxcbiAgICAgIH0sXG4gICAgICBiYWNrZHJvcERpc21pc3M6IHRydWUsXG4gICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgdHQoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmkxOG4udChrZXksIHRoaXMubnMpO1xuICB9XG59XG4iXX0=