@nowzoo/ngx-firebase-auth
Version:
Angular components for Firebase email-first sign in and out-of-band (oob) actions (reset password, etc).
2,368 lines • 206 kB
JavaScript
import { trigger, state, style, animate, transition } from '@angular/animations';
import { Injectable, Component, Input, Output, EventEmitter, ViewChild, NgZone, NgModule, defineInjectable, inject } from '@angular/core';
import { AngularFireAuth } from 'angularfire2/auth';
import { auth } from 'firebase/app';
import { Router, ActivatedRoute, RouterModule } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil, take, debounceTime } from 'rxjs/operators';
import { FormControl, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
/** @type {?} */
const fadeInOutAnimation = trigger('fadeInOut', [
state('in', style({ opacity: 1, display: 'block' })),
transition('void => *', [
style({ opacity: 0 }),
animate(300)
]),
transition('* => void', [
animate(300, style({ opacity: 0 }))
])
]);
/** @type {?} */
const screenAnimation = trigger('screen', [
state('in', style({ opacity: 1 })),
transition('void => *', [
style({ opacity: 0 }),
animate(300)
]),
transition('* => void', [
animate(0, style({ opacity: 0 }))
])
]);
/** @type {?} */
const getOAuthProviderName = (id) => {
switch (id) {
case 'twitter.com': return 'Twitter';
case 'facebook.com': return 'Facebook';
case 'google.com': return 'Google';
case 'github.com': return 'GitHub';
default: return id;
}
};
/** @type {?} */
const getOAuthProviderIcon = (id) => {
switch (id) {
case 'twitter.com':
case 'facebook.com':
case 'google.com':
case 'github.com':
return 'fab fa-fw fa-' + id.replace('.com', '');
default: return 'fas fa-fw fa-sign-in-alt';
}
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class NgxFirebaseAuthService {
/**
* @param {?} _afAuth
*/
constructor(_afAuth) {
this._afAuth = _afAuth;
}
/**
* @return {?}
*/
get auth() {
return this._afAuth.auth;
}
/**
* @return {?}
*/
get storage() {
return window.localStorage;
}
/**
* @return {?}
*/
getRemembered() {
/** @type {?} */
const str = this.storage.getItem(NgxFirebaseAuthService.rememberKey);
if (str) {
try {
return JSON.parse(str);
}
catch (e) {
return { email: '', remember: true };
}
}
return { email: '', remember: true };
}
/**
* @param {?} remember
* @param {?} email
* @return {?}
*/
setRemembered(remember, email) {
/** @type {?} */
const persistence = remember ?
auth.Auth.Persistence.LOCAL : auth.Auth.Persistence.SESSION;
return this.auth.setPersistence(persistence)
.then(() => {
/** @type {?} */
const o = {
email: remember ? email : '',
remember: remember
};
/** @type {?} */
const str = JSON.stringify(o);
this.storage.setItem(NgxFirebaseAuthService.rememberKey, str);
return o;
});
}
}
NgxFirebaseAuthService.rememberKey = 'ngx-firebase-auth-remember';
NgxFirebaseAuthService.decorators = [
{ type: Injectable, args: [{
providedIn: 'root'
},] },
];
/** @nocollapse */
NgxFirebaseAuthService.ctorParameters = () => [
{ type: AngularFireAuth }
];
/** @nocollapse */ NgxFirebaseAuthService.ngInjectableDef = defineInjectable({ factory: function NgxFirebaseAuthService_Factory() { return new NgxFirebaseAuthService(inject(AngularFireAuth)); }, token: NgxFirebaseAuthService, providedIn: "root" });
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class SignInComponent {
/**
* @param {?} _afAuth
* @param {?} _svc
* @param {?} _route
* @param {?} _router
*/
constructor(_afAuth, _svc, _route, _router) {
this._afAuth = _afAuth;
this._svc = _svc;
this._route = _route;
this._router = _router;
this.ngUnsubscribe = new Subject();
this.tosTemplate = null;
this.success = new EventEmitter();
this.mode = new EventEmitter();
this.initialOAuthError = null;
this.signedOut = false;
this.oAuthProviderId = null;
this.cred = null;
this.unhandledError = null;
this.screen = 'wait';
}
/**
* @return {?}
*/
get auth() {
return this._afAuth.auth;
}
/**
* @return {?}
*/
get authService() {
return this._svc;
}
/**
* @return {?}
*/
get router() {
return this._router;
}
/**
* @return {?}
*/
get route() {
return this._route;
}
/**
* @return {?}
*/
get queryParams() {
return this.route.queryParams;
}
/**
* @return {?}
*/
get snapshotQueryParams() {
return this.route.snapshot.queryParams;
}
/**
* @return {?}
*/
ngOnInit() {
this.init();
}
/**
* @return {?}
*/
ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
/**
* @return {?}
*/
init() {
/** @type {?} */
const rememberRecord = this.authService.getRemembered();
this.remember = rememberRecord.remember;
this.email = rememberRecord.email;
return this.onInitHandleSignOut()
.then((handled) => {
if (handled) {
return handled;
}
return this.onInitHandleOAuthRedirect();
})
.then((handled) => {
if (!handled) {
this.showSignIn();
}
this.queryParams.pipe(takeUntil(this.ngUnsubscribe)).subscribe(params => {
/** @type {?} */
const action = params["action"] || null;
switch (action) {
case 'signOut':
this.showSignOut();
break;
case 'resetPassword':
this.showResetPassword();
break;
case 'signIn':
this.showSignIn();
break;
case 'signInPassword':
this.showSignInPassword();
break;
case 'signUpPassword':
this.showSignUpPassword();
break;
case 'signInOAuth':
this.showSignInOAuth(params["providerId"], null);
break;
}
});
});
}
/**
* @return {?}
*/
onInitHandleSignOut() {
if (this.snapshotQueryParams["action"] !== 'signOut') {
return Promise.resolve(false);
}
return this.showSignOut().then(() => true);
}
/**
* @return {?}
*/
onInitHandleOAuthRedirect() {
return new Promise(resolve => {
/** @type {?} */
const remember = this.route.snapshot.queryParams["remember"] === 'true';
return this.auth.getRedirectResult()
.then((cred) => {
if (this.auth.currentUser && cred.user) {
this.authService.setRemembered(remember, cred.user.email)
.then(() => {
this.showSignInSuccess(cred);
resolve(true);
});
}
else {
resolve(false);
}
})
.catch((error) => {
this.showSignInOAuth(null, error);
resolve(true);
});
});
}
/**
* @return {?}
*/
showSignOut() {
this.signedOut = false;
this.screen = 'wait';
return this.auth.signOut()
.then(() => {
this.showSignIn(true);
});
}
/**
* @param {?=} signedOut
* @return {?}
*/
showSignIn(signedOut) {
this.mode.emit('signIn');
this.signedOut = signedOut === true;
this.screen = 'signIn';
}
/**
* @return {?}
*/
showSignInPassword() {
this.mode.emit('signIn');
this.signedOut = false;
this.screen = 'signInPassword';
}
/**
* @return {?}
*/
showSignUpPassword() {
this.mode.emit('signIn');
this.signedOut = false;
this.screen = 'signUpPassword';
}
/**
* @param {?} oAuthProviderId
* @param {?} error
* @return {?}
*/
showSignInOAuth(oAuthProviderId, error) {
this.mode.emit('signIn');
this.signedOut = false;
this.oAuthProviderId = oAuthProviderId;
this.initialOAuthError = error;
this.screen = 'signInOAuth';
}
/**
* @param {?} cred
* @return {?}
*/
showSignInSuccess(cred) {
this.mode.emit('signIn');
this.signedOut = false;
this.cred = cred;
this.screen = 'signInSuccess';
this.success.emit(cred);
}
/**
* @return {?}
*/
showResetPassword() {
this.mode.emit('resetPassword');
this.signedOut = false;
this.screen = 'resetPassword';
}
/**
* @param {?} error
* @return {?}
*/
showUnhandledError(error) {
this.signedOut = false;
this.unhandledError = error;
this.screen = 'unhandledError';
}
}
SignInComponent.decorators = [
{ type: Component, args: [{
selector: 'ngx-firebase-auth-sign-in',
template: `<div *ngIf="'wait' === screen" [@screen]="'in'">
<div class="alert alert-secondary">
<i class="fas fa-spin fa-spinner fa-fw" aria-hidden="true"></i>
Please wait...
</div>
</div>
<div *ngIf="'unhandledError' === screen" [@screen]="'in'">
<div class="alert alert-danger">
<i class="fas fa-exclamation-triangle fa-fw text-danger" aria-hidden="true"></i>
<strong>Woops!</strong> An unexpected error occurred.
</div>
<p class="text-muted">
Code: {{unhandledError.code}}. Message: {{unhandledError.message}}
</p>
<p>
<a routerLink="." [queryParams]="{action: 'signIn'}">Start Over</a>
</p>
</div>
<div *ngIf="'signInSuccess' === screen" [@screen]="'in'">
<div class="alert alert-success">
<i class="fas fa-check fa-fw" aria-hidden="true"></i>
Welcome, {{cred.user.displayName}}!
</div>
</div>
<div *ngIf="'signIn' === screen" [@screen]="'in'">
<div class="alert alert-success" *ngIf="signedOut">
<i class="fas fa-check fa-fw" aria-hidden="true"></i>
You’re signed out.
</div>
<ngx-firebase-auth-sign-in-methods-form
[(email)]="email"
[(remember)]="remember"
[oAuthProviderIds]="oAuthProviderIds"
(error)="showUnhandledError($event)"
(success)="showSignInSuccess($event)"></ngx-firebase-auth-sign-in-methods-form>
<small class="text-center text-muted my-2 form-text">
<ng-container *ngTemplateOutlet="tosTemplate"></ng-container>
</small>
</div>
<div *ngIf="'signInPassword' === screen" [@screen]="'in'">
<ngx-firebase-auth-sign-in-form
[email]="email"
[(remember)]="remember"
(error)="showUnhandledError($event)"
(success)="showSignInSuccess($event)"></ngx-firebase-auth-sign-in-form>
<small class="text-center text-muted my-2 form-text">
<ng-container *ngTemplateOutlet="tosTemplate"></ng-container>
</small>
</div>
<div *ngIf="'signUpPassword' === screen" [@screen]="'in'">
<ngx-firebase-auth-sign-up-form
[email]="email"
[(remember)]="remember"
(error)="showUnhandledError($event)"
(success)="showSignInSuccess($event)"></ngx-firebase-auth-sign-up-form>
<small class="text-center text-muted my-2 form-text">
<ng-container *ngTemplateOutlet="tosTemplate"></ng-container>
</small>
</div>
<div *ngIf="'signInOAuth' === screen" [@screen]="'in'">
<ngx-firebase-auth-sign-in-oauth
[providerId]="oAuthProviderId"
[initialError]="initialOAuthError"
[useOAuthPopup]="useOAuthPopup"
[oAuthProviderFactory]="oAuthProviderFactory"
[(email)]="email"
[(remember)]="remember"
(error)="showUnhandledError($event)"
(success)="showSignInSuccess($event)"></ngx-firebase-auth-sign-in-oauth>
<small class="text-center text-muted my-2 form-text">
<ng-container *ngTemplateOutlet="tosTemplate"></ng-container>
</small>
</div>
<div *ngIf="'resetPassword' === screen" [@screen]="'in'">
<h6>Reset Password</h6>
<ngx-firebase-auth-reset-password-send-form
[(email)]="email"
(error)="showUnhandledError($event)"></ngx-firebase-auth-reset-password-send-form>
</div>
`,
styles: [``],
animations: [screenAnimation]
},] },
];
/** @nocollapse */
SignInComponent.ctorParameters = () => [
{ type: AngularFireAuth },
{ type: NgxFirebaseAuthService },
{ type: ActivatedRoute },
{ type: Router }
];
SignInComponent.propDecorators = {
oAuthProviderIds: [{ type: Input }],
useOAuthPopup: [{ type: Input }],
oAuthProviderFactory: [{ type: Input }],
tosTemplate: [{ type: Input }],
success: [{ type: Output }],
mode: [{ type: Output }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class OobComponent {
/**
* @param {?} _route
*/
constructor(_route) {
this._route = _route;
this.screen = null;
this.mode = new EventEmitter();
this.navigationError = new EventEmitter();
this.success = new EventEmitter();
}
/**
* @return {?}
*/
get queryParams() {
return this._route.snapshot.queryParams;
}
/**
* @return {?}
*/
ngOnInit() {
this.oobCode = this.queryParams["oobCode"] || null;
if (!this.oobCode) {
this.navigationError.emit();
return;
}
switch (this.queryParams["mode"]) {
case 'resetPassword':
case 'verifyEmail':
case 'recoverEmail':
this.screen = this.queryParams["mode"];
this.mode.emit(this.queryParams["mode"]);
break;
default:
this.navigationError.emit();
break;
}
}
}
OobComponent.decorators = [
{ type: Component, args: [{
selector: 'ngx-firebase-auth-oob',
template: `<div *ngIf="'resetPassword' === screen" [@screen]="'in'">
<ngx-firebase-auth-oob-reset-password
[oobCode]="oobCode"
(success)="success.emit($event)"></ngx-firebase-auth-oob-reset-password>
</div>
<div *ngIf="'verifyEmail' === screen" [@screen]="'in'">
<ngx-firebase-auth-oob-verify-email
[oobCode]="oobCode"
(success)="success.emit($event)"></ngx-firebase-auth-oob-verify-email>
</div>
<div *ngIf="'recoverEmail' === screen" [@screen]="'in'">
<ngx-firebase-auth-oob-recover-email
[oobCode]="oobCode"
(success)="success.emit($event)"></ngx-firebase-auth-oob-recover-email>
</div>
`,
styles: [``],
animations: [screenAnimation]
},] },
];
/** @nocollapse */
OobComponent.ctorParameters = () => [
{ type: ActivatedRoute }
];
OobComponent.propDecorators = {
mode: [{ type: Output }],
navigationError: [{ type: Output }],
success: [{ type: Output }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class NgxFirebaseAuthFormHelper {
/**
* @param {?} fc
* @param {?} key
* @param {?=} value
* @return {?}
*/
static setErrorUntilChanged(fc, key, value = true) {
/** @type {?} */
const error = {};
error[key] = value;
fc.setErrors(error);
fc.valueChanges.pipe(take(1)).subscribe(() => {
NgxFirebaseAuthFormHelper.clearError(fc, key);
});
}
/**
* @param {?} fc
* @param {?} key
* @return {?}
*/
static clearError(fc, key) {
/** @type {?} */
const errors = {};
if (!fc.errors) {
return;
}
Object.keys(fc.errors).forEach((k) => {
if (k !== key) {
errors[k] = fc.errors[k];
}
});
if (Object.keys(errors).length === 0) {
fc.setErrors(null);
}
else {
fc.setErrors(errors);
}
}
/**
* @param {?} fc
* @return {?}
*/
static requiredNonEmpty(fc) {
/** @type {?} */
const value = fc.value;
if (typeof value !== 'string') {
return null;
}
return value.trim().length === 0 ? { required: true } : null;
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class SignInMethodsFormComponent {
/**
* @param {?} _afAuth
* @param {?} _authService
* @param {?} _ngZone
*/
constructor(_afAuth, _authService, _ngZone) {
this._afAuth = _afAuth;
this._authService = _authService;
this._ngZone = _ngZone;
this.oAuthProviderIds = [];
this.emailChange = new EventEmitter();
this.rememberChange = new EventEmitter();
this.success = new EventEmitter();
this.error = new EventEmitter();
this.formId = 'ngx-firebase-auth-sign-in-methods-form-';
this.submitting = false;
this.getOAuthProviderIcon = getOAuthProviderIcon;
this.getOAuthProviderName = getOAuthProviderName;
this.methodsForEmail = { status: 'unfetched', methods: [], email: null };
}
/**
* @return {?}
*/
get auth() {
return this._afAuth.auth;
}
/**
* @return {?}
*/
get authService() {
return this._authService;
}
/**
* @return {?}
*/
get methods() {
return this.methodsForEmail.methods;
}
/**
* @return {?}
*/
get fetchStatus() {
return this.methodsForEmail.status;
}
/**
* @return {?}
*/
get methodsFetched() {
return this.methodsForEmail.status === 'fetched';
}
/**
* @return {?}
*/
get accountIsNew() {
return this.methodsFetched && this.methods.length === 0;
}
/**
* @return {?}
*/
get accountExists() {
return this.methodsFetched && this.methods.length > 0;
}
/**
* @return {?}
*/
get accountHasPassword() {
return this.accountExists && this.methods.indexOf('password') !== -1;
}
/**
* @return {?}
*/
get accountOAuthMethods() {
if (!this.accountExists) {
return [];
}
return this.methods.filter(id => id !== 'password');
}
/**
* @return {?}
*/
ngOnInit() {
this.emailFc = new FormControl(this.email, { validators: [Validators.required, Validators.email] });
this.rememberFc = new FormControl(this.remember);
this.rememberFc.valueChanges.subscribe(() => this.rememberChange.emit(this.rememberFc.value));
this.fg = new FormGroup({ email: this.emailFc, remember: this.rememberFc });
this.emailFc.valueChanges.subscribe(() => this.emailChange.emit(this.emailFc.value.trim()));
this.emailFc.valueChanges.pipe(debounceTime(500)).subscribe(() => this.fetch());
this.fetch();
}
/**
* @return {?}
*/
ngAfterViewInit() {
this.emailInput.nativeElement.focus();
}
/**
* @return {?}
*/
fetch() {
/** @type {?} */
const email = this.emailFc.value.trim();
if (email === this.methodsForEmail.email) {
return;
}
if ('fetching' === this.methodsForEmail.status) {
return;
}
this.methodsForEmail = { status: 'fetching', methods: [], email: email };
if (this.emailFc.invalid) {
this.methodsForEmail = { status: 'unfetched', methods: [], email: email };
return;
}
this.auth.fetchSignInMethodsForEmail(email)
.then(results => {
this.methodsForEmail = { status: 'fetched', methods: results, email: email };
})
.catch((error) => {
this.emailFc.markAsDirty();
this.emailFc.markAsTouched();
switch (error.code) {
case 'auth/invalid-email':
NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.emailFc, error.code);
break;
}
this.methodsForEmail = { email: this.email, status: 'unfetched', methods: [] };
});
}
}
SignInMethodsFormComponent.decorators = [
{ type: Component, args: [{
selector: 'ngx-firebase-auth-sign-in-methods-form',
template: `<form [formGroup]="fg">
<div class="form-group">
<label [attr.for]="formId + 'email'">Email Address</label>
<input
#emailInput
[attr.id]="formId + 'email'"
[attr.aria-describedby]="formId + 'email'"
type="email"
autocomplete="email"
placeholder="Email Address"
formControlName="email"
(blur)="fetch()"
(keyup.enter)="emailInput.blur()"
class="form-control"
[class.is-invalid]="emailFc.touched && emailFc.invalid">
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="emailFc.touched && emailFc.hasError('required')">
Required.
</div>
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="emailFc.touched && emailFc.hasError('email')">
Invalid email.
</div>
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="emailFc.touched && emailFc.hasError('auth/invalid-email')">
Invalid email.
</div>
<small class="text-muted form-text" [attr.id]="formId + 'email'" [ngSwitch]="fetchStatus">
<span *ngSwitchCase="'unfetched'" [@fadeInOut]="'in'">
To get started, enter your email address.
If you don’t yet have an account we’ll create one for you.
</span>
<span *ngSwitchCase="'fetching'" [@fadeInOut]="'in'">
<i class="fas fa-spin fa-spinner fa-fw" aria-hidden="true"></i>
Looking up account...
</span>
<span *ngSwitchCase="'fetched'" [@fadeInOut]="'in'">
<i class="fas fa-check fa-fw text-success" aria-hidden="true"></i>
<span *ngIf="accountExists">Account found.</span>
<span *ngIf="accountIsNew">We'll create an account.</span>
</span>
</small>
</div>
<div class="form-group">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
[value]="true"
formControlName="remember"
[attr.id]="formId + 'remember'">
<label class="form-check-label" [attr.for]="formId + 'remember'">
Remember me on this device.
</label>
</div>
</div>
</form>
<div *ngIf="methodsFetched && accountExists" [@screen]="'in'">
<small class="text-muted mb-1 form-text">
<span *ngIf="accountHasPassword">
<span *ngIf="accountOAuthMethods.length === 0">
Please sign in with your password...
</span>
<span *ngIf="accountOAuthMethods.length === 1">
Please sign in with your password or your
linked {{getOAuthProviderName(accountOAuthMethods[0])}} account...
</span>
<span *ngIf="accountOAuthMethods.length > 1">
Please sign in with your password or one of your linked accounts...
</span>
</span>
<span *ngIf="!accountHasPassword">
<span *ngIf="accountOAuthMethods.length === 1">
Please sign in with your
linked {{getOAuthProviderName(accountOAuthMethods[0])}} account...
</span>
<span *ngIf="accountOAuthMethods.length > 1">
Please sign in with one of your linked accounts...
</span>
</span>
</small>
<div class="list-group">
<a
*ngIf="accountHasPassword"
routerLink="."
[queryParams]="{action: 'signInPassword'}"
class="list-group-item list-group-item-action">
<i class="fas fa-lock fa-fw" aria-hidden="true"></i>
<span class="ml-2">
Sign In with Your Password
</span>
</a>
<a
*ngFor="let id of accountOAuthMethods"
routerLink="."
[queryParams]="{action: 'signInOAuth', providerId: id}"
class="list-group-item list-group-item-action">
<i [attr.class]="getOAuthProviderIcon(id)" aria-hidden="true"></i>
<span class="ml-2">
Sign In with {{getOAuthProviderName(id)}}
</span>
</a>
</div>
</div>
<div *ngIf="methodsFetched && accountIsNew" [@screen]="'in'">
<small class="text-muted mb-1 form-text">
<span *ngIf="oAuthProviderIds.length === 0">
Please create an account...
</span>
<span *ngIf="oAuthProviderIds.length === 1">
Please sign up with your
{{getOAuthProviderName(oAuthProviderIds[0])}} account,
or create a separate account with a password....
</span>
<span *ngIf="oAuthProviderIds.length >1">
Please sign up with one of the services listed below,
or create a separate account with a password....
</span>
</small>
<div class="list-group">
<a
*ngFor="let id of oAuthProviderIds"
routerLink="."
[queryParams]="{action: 'signInOAuth', providerId: id}"
class="list-group-item list-group-item-action">
<i [attr.class]="getOAuthProviderIcon(id)" aria-hidden="true"></i>
<span class="ml-2">
Sign Up with {{getOAuthProviderName(id)}}
</span>
</a>
<a
routerLink="."
[queryParams]="{action: 'signUpPassword'}"
class="list-group-item list-group-item-action">
<i class="fas fa-lock fa-fw" aria-hidden="true"></i>
<span class="ml-2">
Create
<span *ngIf="oAuthProviderIds.length > 0">
a Separate
</span>
Account
</span>
</a>
</div>
</div>
`,
styles: [``],
animations: [fadeInOutAnimation, screenAnimation]
},] },
];
/** @nocollapse */
SignInMethodsFormComponent.ctorParameters = () => [
{ type: AngularFireAuth },
{ type: NgxFirebaseAuthService },
{ type: NgZone }
];
SignInMethodsFormComponent.propDecorators = {
emailInput: [{ type: ViewChild, args: ['emailInput',] }],
email: [{ type: Input }],
remember: [{ type: Input }],
oAuthProviderIds: [{ type: Input }],
emailChange: [{ type: Output }],
rememberChange: [{ type: Output }],
success: [{ type: Output }],
error: [{ type: Output }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class SignInFormComponent {
/**
* @param {?} _afAuth
* @param {?} _authService
*/
constructor(_afAuth, _authService) {
this._afAuth = _afAuth;
this._authService = _authService;
this.rememberChange = new EventEmitter();
this.success = new EventEmitter();
this.error = new EventEmitter();
this.formId = 'ngx-firebase-auth-sign-in-form-';
this.submitting = false;
this.methodsForEmail = [];
this.getOAuthProviderIcon = getOAuthProviderIcon;
this.getOAuthProviderName = getOAuthProviderName;
}
/**
* @return {?}
*/
get auth() {
return this._afAuth.auth;
}
/**
* @return {?}
*/
get authService() {
return this._authService;
}
/**
* @return {?}
*/
ngOnInit() {
this.emailFc = new FormControl(this.email, { validators: [Validators.required, Validators.email] });
this.passwordFc = new FormControl('', { validators: [Validators.required] });
this.rememberFc = new FormControl(this.remember);
this.rememberFc.valueChanges.subscribe(val => this.rememberChange.emit(val));
this.fg = new FormGroup({
email: this.emailFc,
password: this.passwordFc,
remember: this.rememberFc
});
}
/**
* @return {?}
*/
ngAfterViewInit() {
this.passwordInput.nativeElement.focus();
}
/**
* @return {?}
*/
submit() {
/** @type {?} */
const email = this.emailFc.value.trim();
this.submitting = true;
this.methodsForEmail = [];
/** @type {?} */
let cred;
this.auth.fetchSignInMethodsForEmail(email)
.then(results => {
this.methodsForEmail = results;
if (results.length === 0) {
return Promise.reject({
code: 'auth/user-not-found'
});
}
if (results.indexOf('password') === -1) {
return Promise.reject({
code: 'ngx-firebase-auth/no-password',
});
}
return this.auth.signInWithEmailAndPassword(email, this.passwordFc.value);
})
.then(result => {
cred = result;
return this.authService.setRemembered(this.rememberFc.value === true, email);
})
.then(() => {
this.success.emit(cred);
})
.catch(error => {
this.submitting = false;
this.emailFc.markAsDirty();
this.emailFc.markAsTouched();
this.passwordFc.markAsDirty();
this.passwordFc.markAsTouched();
switch (error.code) {
case 'auth/invalid-email':
case 'auth/user-not-found':
case 'auth/user-disabled':
case 'ngx-firebase-auth/no-password':
NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.emailFc, error.code);
break;
case 'auth/wrong-password':
NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.passwordFc, error.code);
break;
default:
this.error.emit(error);
break;
}
});
}
}
SignInFormComponent.decorators = [
{ type: Component, args: [{
selector: 'ngx-firebase-auth-sign-in-form',
template: `<form [formGroup]="fg" (ngSubmit)="submit()">
<div class="form-group">
<label [attr.for]="formId + 'email'">Email Address</label>
<input
readonly
#emailInput
[attr.id]="formId + 'email'"
[attr.aria-describedby]="formId + 'email'"
type="email"
autocomplete="email"
placeholder="Email Address"
formControlName="email"
class="form-control">
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="emailFc.hasError('required')">
Required.
</div>
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="emailFc.hasError('email')">
Invalid email.
</div>
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="emailFc.hasError('auth/invalid-email')">
Invalid email.
</div>
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="emailFc.hasError('auth/user-not-found')">
We could not find an account with that email address.
<a routerLink="." [queryParams]="{action: 'signIn'}">Create Account</a>
</div>
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="emailFc.hasError('auth/user-disabled')">
The account with that email address has been disabled.
</div>
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="emailFc.hasError('ngx-firebase-auth/no-password')">
The account with that email address does not have a password.
Please sign in using:
<span *ngFor="let id of methodsForEmail; let isLast = last">
<a routerLink="." [queryParams]="{action: 'signInOAuth', providerId: id}">{{getOAuthProviderName(id)}}</a>
<span *ngIf="!isLast">
|
</span>
</span>
</div>
<small class="text-muted form-text" [attr.id]="formId + 'email'" >
Not your email address?
<a routerLink="." [queryParams]="{action: 'signIn'}">Start Over</a>
</small>
</div>
<div class="form-group">
<div class="d-flex justify-content-between align-items-end">
<label [attr.for]="formId + 'password'">Password</label>
<small>
<a (click)="$event.preventDefault(); passwordInput.type = 'password' === passwordInput.type ? 'text' : 'password'"
href="#" tabindex="-1" class="d-inline-block">
<span *ngIf="'password' === passwordInput.type">Show</span>
<span *ngIf="'text' === passwordInput.type">Hide</span>
</a>
</small>
</div>
<input
#passwordInput
[attr.id]="formId + 'password'"
[attr.aria-describedby]="formId + 'password-help'"
type="password"
formControlName="password"
placeholder="Password"
autocomplete="password"
class="form-control"
[class.is-invalid]="passwordFc.touched && passwordFc.invalid">
<div class="invalid-feedback"
*ngIf="passwordFc.touched && passwordFc.hasError('required')"
[@fadeInOut]="'in'">
Required.
</div>
<div class="invalid-feedback"
*ngIf="passwordFc.touched && passwordFc.hasError('auth/wrong-password')"
[@fadeInOut]="'in'">
Wrong password.
</div>
<small [attr.id]="formId + 'password-help'" class="form-text text-muted">
Forgot? <a routerLink="." [queryParams]="{action: 'resetPassword'}">Reset Password</a>
</small>
</div>
<div class="form-group">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
[value]="true"
formControlName="remember"
[attr.id]="formId + 'remember'">
<label class="form-check-label" [attr.for]="formId + 'remember'">
Remember me on this device.
</label>
</div>
</div>
<div class="form-group">
<button type="submit"
class="btn btn-success btn-block"
[disabled]="fg.invalid || submitting">
<i class="fas fa-lock fa-fw" aria-hidden="true"></i>
Sign In
</button>
</div>
</form>
`,
styles: [``],
animations: [fadeInOutAnimation]
},] },
];
/** @nocollapse */
SignInFormComponent.ctorParameters = () => [
{ type: AngularFireAuth },
{ type: NgxFirebaseAuthService }
];
SignInFormComponent.propDecorators = {
passwordInput: [{ type: ViewChild, args: ['passwordInput',] }],
email: [{ type: Input }],
remember: [{ type: Input }],
rememberChange: [{ type: Output }],
success: [{ type: Output }],
error: [{ type: Output }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class SignUpFormComponent {
/**
* @param {?} _afAuth
* @param {?} _authService
*/
constructor(_afAuth, _authService) {
this._afAuth = _afAuth;
this._authService = _authService;
this.rememberChange = new EventEmitter();
this.success = new EventEmitter();
this.error = new EventEmitter();
this.formId = 'ngx-firebase-auth-sign-up-form-';
this.submitting = false;
}
/**
* @return {?}
*/
get auth() {
return this._afAuth.auth;
}
/**
* @return {?}
*/
get authService() {
return this._authService;
}
/**
* @return {?}
*/
ngOnInit() {
this.emailFc = new FormControl(this.email, { validators: [Validators.required, Validators.email] });
this.passwordFc = new FormControl('', { validators: [Validators.required] });
this.nameFc = new FormControl('', { validators: [Validators.required, NgxFirebaseAuthFormHelper.requiredNonEmpty] });
this.rememberFc = new FormControl(this.remember);
this.rememberFc.valueChanges.subscribe(val => this.rememberChange.emit(val));
this.fg = new FormGroup({
email: this.emailFc,
password: this.passwordFc,
name: this.nameFc,
remember: this.rememberFc
});
}
/**
* @return {?}
*/
ngAfterViewInit() {
this.passwordInput.nativeElement.focus();
}
/**
* @return {?}
*/
submit() {
this.submitting = true;
/** @type {?} */
let cred;
this.auth.fetchSignInMethodsForEmail(this.email)
.then((results) => {
if (results.length > 0) {
return Promise.reject({
code: 'ngx-firebase-auth/account-exists'
});
}
return this.auth.createUserWithEmailAndPassword(this.email, this.passwordFc.value);
})
.then(result => {
cred = result;
return cred.user.updateProfile({ displayName: this.nameFc.value.trim(), photoURL: null });
})
.then(() => {
return this.authService.setRemembered(this.rememberFc.value === true, this.email);
})
.then(() => {
this.success.emit(cred);
})
.catch(error => {
this.submitting = false;
this.emailFc.markAsDirty();
this.emailFc.markAsTouched();
this.passwordFc.markAsDirty();
this.passwordFc.markAsTouched();
switch (error.code) {
case 'auth/invalid-email':
case 'ngx-firebase-auth/account-exists':
NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.emailFc, error.code);
break;
case 'auth/weak-password':
NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.passwordFc, error.code);
break;
default:
this.error.emit(error);
break;
}
});
}
}
SignUpFormComponent.decorators = [
{ type: Component, args: [{
selector: 'ngx-firebase-auth-sign-up-form',
template: `<form [formGroup]="fg" (ngSubmit)="submit()">
<div class="form-group">
<label [attr.for]="formId + 'email'">Email Address</label>
<input
readonly
#emailInput
[attr.id]="formId + 'email'"
[attr.aria-describedby]="formId + 'email'"
type="email"
autocomplete="email"
placeholder="Email Address"
formControlName="email"
class="form-control">
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="emailFc.hasError('required')">
Required.
</div>
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="emailFc.hasError('email')">
Invalid email.
</div>
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="emailFc.hasError('auth/invalid-email')">
Invalid email.
</div>
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="emailFc.hasError('ngx-firebase-auth/account-exists')">
We found an account with that email address.
<a routerLink="." [queryParams]="{action: 'signIn'}">Sign In</a>
</div>
<small class="text-muted form-text" [attr.id]="formId + 'email'" >
Not your email address?
<a routerLink="." [queryParams]="{action: 'signIn'}">Go Back</a>
</small>
</div>
<div class="form-group">
<div class="d-flex justify-content-between align-items-end">
<label [attr.for]="formId + 'password'">Choose Password</label>
<small>
<a (click)="$event.preventDefault(); passwordInput.type = 'password' === passwordInput.type ? 'text' : 'password'"
href="#" tabindex="-1" class="d-inline-block">
<span *ngIf="'password' === passwordInput.type">Show</span>
<span *ngIf="'text' === passwordInput.type">Hide</span>
</a>
</small>
</div>
<input
#passwordInput
[attr.id]="formId + 'password'"
[attr.aria-describedby]="formId + 'password-help'"
type="password"
formControlName="password"
placeholder="Choose Password"
autocomplete="password"
class="form-control"
[class.is-invalid]="passwordFc.touched && passwordFc.invalid">
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="passwordFc.touched && passwordFc.hasError('required')">
Required.
</div>
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="passwordFc.touched && passwordFc.hasError('auth/wrong-password')">
Wrong password.
</div>
<small [attr.id]="formId + 'password-help'" class="form-text text-muted">
Please choose a strong password.
</small>
</div>
<div class="form-group">
<label [attr.for]="formId + 'name'">Your Name</label>
<input
[attr.id]="formId + 'name'"
type="text"
formControlName="name"
placeholder="Your Name"
class="form-control"
[class.is-invalid]="nameFc.touched && nameFc.invalid">
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="nameFc.touched && nameFc.hasError('required')">
Required.
</div>
</div>
<div class="form-group">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
[value]="true"
formControlName="remember"
[attr.id]="formId + 'remember'">
<label class="form-check-label" [attr.for]="formId + 'remember'">
Remember me on this device.
</label>
</div>
</div>
<div class="form-group">
<button type="submit"
class="btn btn-success btn-block"
[disabled]="fg.invalid || submitting">
<i class="fas fa-lock fa-fw" aria-hidden="true"></i>
Create Account
</button>
</div>
</form>
`,
styles: [``],
animations: [fadeInOutAnimation]
},] },
];
/** @nocollapse */
SignUpFormComponent.ctorParameters = () => [
{ type: AngularFireAuth },
{ type: NgxFirebaseAuthService }
];
SignUpFormComponent.propDecorators = {
passwordInput: [{ type: ViewChild, args: ['passwordInput',] }],
email: [{ type: Input }],
remember: [{ type: Input }],
rememberChange: [{ type: Output }],
success: [{ type: Output }],
error: [{ type: Output }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class ResetPasswordSendFormComponent {
/**
* @param {?} _afAuth
*/
constructor(_afAuth) {
this._afAuth = _afAuth;
this.emailChange = new EventEmitter();
this.error = new EventEmitter();
this.formId = 'ngx-firebase-auth-reset-password-send-form-';
this.submitting = false;
this.sent = null;
}
/**
* @return {?}
*/
get auth() {
return this._afAuth.auth;
}
/**
* @return {?}
*/
ngOnInit() {
this.emailFc = new FormControl(this.email, { validators: [Validators.required, Validators.email] });
this.emailFc.valueChanges.subscribe(() => this.emailChange.emit(this.emailFc.value.trim()));
this.fg = new FormGroup({ email: this.emailFc });
}
/**
* @return {?}
*/
ngAfterViewInit() {
this.emailInput.nativeElement.focus();
}
/**
* @return {?}
*/
submit() {
/** @type {?} */
const email = this.emailFc.value.trim();
this.submitting = true;
this.sent = null;
this.auth.sendPasswordResetEmail(email)
.then(() => {
this.submitting = false;
this.sent = email;
})
.catch((error) => {
this.submitting = false;
this.emailFc.markAsTouched();
this.emailFc.markAsDirty();
switch (error.code) {
case 'auth/invalid-email':
case 'auth/user-not-found':
NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.emailFc, error.code);
break;
default:
this.error.emit(error);
break;
}
});
}
}
ResetPasswordSendFormComponent.decorators = [
{ type: Component, args: [{
selector: 'ngx-firebase-auth-reset-password-send-form',
template: `<form [formGroup]="fg" (ngSubmit)="submit()">
<div *ngIf="sent" [@fadeInOut]="'in'">
<div class="alert alert-success">
<i class="fas fa-check fa-fw" aria-hidden="true"></i>
We’ve sent a reset password link to {{sent}}.
Please allow a few moments for the email to arrive.
</div>
</div>
<div class="form-group">
<label [attr.for]="formId + 'email'">Email Address</label>
<input
#emailInput
[attr.id]="formId + 'email'"
[attr.aria-describedby]="formId + 'email-help'"
type="email"
formControlName="email"
class="form-control"
[class.is-invalid]="emailFc.touched && emailFc.invalid">
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="emailFc.touched && emailFc.hasError('required')">
Required.
</div>
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="emailFc.touched && emailFc.hasError('auth/user-not-found')">
We could not find an account with that email address.
Please <a routerLink="." [queryParams]="{action: 'signIUpPassword'}">sign up</a>.
</div>
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="emailFc.touched && emailFc.hasError('email')">
Invalid email.
</div>
<div class="invalid-feedback" [@fadeInOut]="'in'"
*ngIf="emailFc.touched && emailFc.hasError('auth/invalid-email')">
Invalid email.
</div>
<small [attr.id]="formId + 'email-help'" class="form-text text-muted">
Enter the email address you used to sign up. We’ll
send a reset password link to that address.
</small>
</div>
<div class="form-group">
<button type="submit"
class="btn btn-block btn-success"
[disabled]="fg.invalid || submitting">
<i class="fas fa-fw fa-envelope" aria-hidden="true"></i>
Send Link
</button>
</div>
</form>
`,
styles: [``],
animations: [fadeInOutAnimation]
},] },
];
/** @nocollapse */
ResetPasswordSendFormComponent.ctorParameters = () => [
{ type: AngularFireAuth }
];
ResetPasswordSendFormComponent.propDecorators = {
emailInput: [{ type: ViewChild, args: ['emailInput',] }],
email: [{ type: Input }],
emailChange: [{ type: Output }],
error: [{ type: Output }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class SignInOauthComponent {
/**
* @param {?} _afAuth
* @param {?} _svc
* @param {?} _route
* @param {?} _router
*/
constructor(_afAuth, _svc, _route, _router) {
this._afAuth = _afAuth;
this._svc = _svc;
this._route = _route;
this._router = _router;
this.success = new EventEmitter();
this.emailChange = new EventEmitter();
this.rememberChange = new EventEmitter();
this.error = new EventEmitter();
this.screen = 'wait';
this.methodError = null;
this.getOAuthProviderIcon = getOAuthProviderIcon;
this.getOAuthProviderName = getOAuthProviderName;
this.formId = 'ngx-firebase-auth-sign-in-oauth-';
}
/**
* @return {?}
*/
get auth() {
return this._afAuth.auth;
}
/**
* @return {?}
*/
get authService() {
return this._svc;
}
/**
* @return {?}
*/
get route() {
return this._route;
}
/**
* @return {?}
*/
get router() {
return this._router;
}
/**
* @return {?}
*/
ngOnInit() {
this.rememberFc = new FormControl(this.remember);
this.rememberFc.valueChanges.subscribe(val => this.rememberChange.emit(val));
this.fg = new FormGroup({
remember: this.rememberFc
});
if (this.initialError) {
this.handleOAuthError(this.initialError);
}
else {
this.oAuthSignIn(this.providerId);
}
}
/**
* @param {?} id
* @param {?=} forceRedirect
* @return {?}
*/
oAuthSignIn(id, forceRedirect) {
this.methodError = null;
/** @type {?} */
let cred;
if (this.useOAuthPopup && forceRedirect !== true) {
this.getOAuthProvider(id)
.then(provider => {
return this.auth.signInWithPopup(provider);
})
.then((result) => {
cred = result;
return this.authService.setRemembered(this.rememberFc.value === true, result.user.email);
})
.then(() => {
this.success.emit(cred);
})
.catch(error => this.handleOAuthError(error, id));
}
else {
this.router.navigate(['.'], { relativeTo: this.route, queryParams: { remember: this.rememberFc.value === true } })
.then(() => {
return this.getOAuthProvider(id);
})
.then(provider => {
return this.auth.signInWithRedirect(provider);
})
.catch(error => this.handleOAuthError(error, id));
}
}
/**
* @param {?} error
* @param {?=} providerId
* @return {?}
*/
handleOAuthError(error, providerId) {
if (error['email'] && error['credential']) {
this.emailChange.emit(error['email']);
this.auth.fetchSignInMethodsForEmail(error['email'])
.then(results => {
error['methods'] = results;
error['accountHasPassword'] = results.indexOf('password') !== -1;
error['accountOAuthMethods'] = results.filter(id => id !== 'password');
this.methodError = error;
this.screen = 'methodError';
});
return;
}
switch (error.code) {
case 'auth/cancelled-popup-request':
case 'auth/popup-closed-by-user':
this.screen = 'retry';
break;
case 'auth/popup-blocked':
this.oAuthSignIn(providerId, true);
break;
default:
this.error.emit(error);
break;
}
}
/**
* @param {?} id
* @return {?}
*/
getOAuthProvider(id) {
/** @type {?} */
let provider = null;
if (this.oAuthProviderFactory) {
provider = this.oAuthProviderFactory(id);
}
if (!provider) {
switch (id) {
case 'twitter.com':
provider = new auth.TwitterAuthProvider();
break;
case 'facebook.com':
provider = new auth.FacebookAuthProvider();
break;
case 'google.com':
provider = new auth.GoogleAuthProvider();
break;
case 'github.com':
provider = new auth.GithubAuthProvider();
break;
}
}
if (provider) {
return Promise.resolve(provider);
}
else {
return Promise.reject({
code: 'ngx-firebase-auth/no-provider-found',
message: `We could not create an OAuth provider for provider id "${id}".`
});
}
}
}
SignInOauthComponent.decorators = [
{ type: Component, args: [{
selector: 'ngx-firebase-auth-sign-in-oauth',
template: `<div *ngIf="'wait' === screen" [@screen]="'in'">
<div class="alert alert-secondary">
<i class="fas fa-spin fa-spinner fa-fw" aria-hidden="true"></i>
Please wait...
</div>
</div>
<div *ngIf="'methodError' === screen" [@screen]="'in'">
<div class="alert alert-danger">
<i class="fas fa-exclamation-triangle fa-fw" aria-hidden="true"></i>
We could not sign you in with {{methodError.credential.providerId}}.
</div>
<p class="text-muted">
Please sign in with one of the methods associated with
{{methodError.email}}:
</p>
<div class="list-group">
<a
*ngIf="methodError.accountHasPassword"
routerLink="."
[queryParams]="{action: 'signInPassword'}"
class="list-group-item list-group-item-action">
<i class="fas fa-unlock" aria-hidden="true"></i>
<span class="ml-2">Sign In with Your Password</span>
</a>
<button
*ngFor="let id of methodError.accountOAuthMethods"
(click)="oAuthSignIn(id)"
class="list-group-item list-group-item-action">
<i [attr.class]="getOAuthProviderIcon(id)" aria-hidden="true"></i>
<span class="ml-2">Sign In with {{getOAuthProviderName(id)}}</span>
</button>
</div>
<form [formGroup]="fg">
<div class="form-group">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
[value]="true"
formControlName="remember"
[attr.id]="formId + 'remember'">
<label class="form-check-label" [attr.for]="formId + 'remember'">
Remember me on this device.
</label>
</div>
</div>
</form>
<p class="text-muted">
Is {{methodError.email}} not your email address?
<a routerLink="." [queryParams]="{action: 'signIn'}">Start Over</a>
</p>
</div>
<div *ngIf="'retry' === screen" [@screen]="'in'">
<div class="alert alert-danger">
<i class="fas fa-exclamation-triangle fa-fw" aria-hidden="true"></i>
It looks like you cancelled signing in with
{{getOAuthProviderName(providerId)}}. Try again:
</div>
<div class="list-group">
<button
(click)="oAuthSignIn(providerId)"
class="list-group-item list-group-item-action">
<i [attr.class]="getOAuthProviderIcon(providerId)" aria-hidden="true"></i>
<span class="ml-2">Sign In with {{getOAuthProviderName(providerId)}}</span>
</button>
</div>
<form [formGroup]="fg">
<div class="form-group">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
[value]="true"
formControlName="remember"
[attr.id]="formId + 'remember'">
<label class="form-check-label" [attr.for]="formId + 'remember'">
Remember me on this device.
</label>
</div>
</div>
</form>
<p class="text-muted">
<a routerLink="." [queryParams]="{action: 'signIn'}">Start Over</a>
</p>
</div>
`,
styles: [``],
animations: [screenAnimation]
},] },
];
/** @nocollapse */
SignInOauthComponent.ctorParameters = () => [
{ type: AngularFireAuth },
{ type: NgxFirebaseAuthService },
{ type: ActivatedRoute },
{ type: Router }
];
SignInOauthComponent.propDecorators = {
providerId: [{ type: Input }],
initialError: [{ type: Input }],
useOAuthPopup: [{ type: Input }],
oAuthProviderFactory: [{ type: Input }],
email: [{ type: Input }],
remember: [{ type: Input }],
success: [{ type: Output }],
emailChange: [{ type: Output }],
rememberChange: [{ type: Output }],
error: [{ type: Output }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class NgxFirebaseAuthModule {
}
NgxFirebaseAuthModule.decorators = [
{ type: NgModule, args: [{
imports: [
CommonModule
],
providers: [
NgxFirebaseAuthService
]
},] },
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class NgxFirebaseAuthSignInModule {
}
NgxFirebaseAuthSignInModule.decorators = [
{ type: NgModule, args: [{
imports: [
CommonModule,
ReactiveFormsModule,
RouterModule,
NgxFirebaseAuthModule
],
declarations: [
SignInComponent,
SignInMethodsFormComponent,
SignInFormComponent,
SignUpFormComponent,
ResetPasswordSendFormComponent,
SignInOauthComponent,
],
exports: [
SignInComponent,
]
},] },
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class OobResetPasswordComponent {
/**
* @param {?} _afAuth
* @param {?} _authService
*/
constructor(_afAuth, _authService) {
this._afAuth = _afAuth;
this._authService = _authService;
this.success = new EventEmitter();
this.screen = 'wait';
this.submitting = false;
this.formId = 'ngx-firebase-auth-oob-reset-password-';
this.unhandledError = null;
this.cred = null;
}
/**
* @return {?}
*/
get auth() {
return this._afAuth.auth;
}
/**
* @return {?}
*/
get authService() {
return this._authService;
}
/**
* @return {?}
*/
ngOnInit() {
/** @type {?} */
const remembered = this.authService.getRemembered();
this.emailFc = new FormControl('');
this.passwordFc = new FormControl('', { validators: [Validators.required] });
this.rememberFc = new FormControl(remembered.remember);
this.fg = new FormGroup({ email: this.emailFc, password: this.passwordFc, remember: this.rememberFc });
this.auth.checkActionCode(this.oobCode)
.then((result) => {
this.info = result;
this.emailFc.setValue(result.data.email);
this.screen = 'form';
})
.catch((error) => {
this.unhandledError = error;
this.screen = 'error';
});
}
/**
* @return {?}
*/
submit() {
this.submitting = true;
this.auth.confirmPasswordReset(this.oobCode, this.passwordFc.value)
.then(() => {
return this.auth.signInWithEmailAndPassword(this.info.data.email, this.passwordFc.value);
})
.then((cred) => {
this.cred = cred;
return this.authService.setRemembered(this.rememberFc.value === true, this.info.data.email);
})
.then(() => {
this.screen = 'success';
this.success.emit({
mode: 'resetPassword',
info: this.info,
cred: this.cred,
user: this.cred.user
});
})
.catch((error) => {
this.submitting = false;
this.passwordFc.markAsDirty();
this.passwordFc.markAsTouched();
switch (error.code) {
case 'auth/weak-password':
NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.passwordFc, error.code);
break;
default:
this.unhandledError = error;
this.screen = 'error';
break;
}
});
}
}
OobResetPasswordComponent.decorators = [
{ type: Component, args: [{
selector: 'ngx-firebase-auth-oob-reset-password',
template: `<div *ngIf="'wait' === screen" [@screen]="'in'">
<div class="alert alert-secondary">
<i class="fas fa-spin fa-spinner fa-fw" aria-hidden="true"></i>
Please wait...
</div>
</div>
<div *ngIf="'success' === screen" [@screen]="'in'">
<div class="alert alert-success">
<i class="fas fa-check fa-fw" aria-hidden="true"></i>
Welcome, {{cred.user.displayName}}!
Your new password has been saved and you are signed in.
</div>
</div>
<div *ngIf="screen === 'error'" [@screen]="'in'">
<div class="alert alert-danger">
<p>
<i class="fas fa-exclamation-triangle fa-fw" aria-hidden="true"></i>
Woops! An error occurred.
</p>
<div [ngSwitch]="unhandledError.code">
<p class="mb-0" *ngSwitchCase="'auth/expired-action-code'">
The reset password link you used has expired.
</p>
<p class="mb-0" *ngSwitchCase="'auth/invalid-action-code'">
The reset password link you used is not valid. This may be because it
has already been used.
</p>
<p class="mb-0" *ngSwitchCase="'auth/user-disabled'">
The account associated with the reset password link you used has been disabled.
</p>
<p class="mb-0" *ngSwitchCase="'auth/user-not-found'">
The account associated with the reset password link you used has been removed.
</p>
<div *ngSwitchDefault>
<p>Code: {{unhandledError.code}}</p>
<p class="mb-0">
Message: {{unhandledError.message}}
</p>
</div>
</div>
</div>
</div>
<div *ngIf="'form' === screen" [@screen]="'in'">
<form [formGroup]="fg" (ngSubmit)="submit()">
<div class="form-group">
<label [attr.for]="formId + 'email'">Email Address</label>
<input
readonly
#emailInput
[attr.id]="formId + 'email'"
[attr.aria-describedby]="formId + 'email'"
type="email"
autocomplete="email"
placeholder="Email Address"
formControlName="email"
class="form-control">
<small class="text-muted form-text" [attr.id]="formId + 'email'" >
You are resetting the password for {{emailFc.value}}.
</small>
</div>
<div class="form-group">
<div class="d-flex justify-content-between align-items-end">
<label [attr.for]="formId + 'password'">Password</label>
<small>
<a (click)="$event.preventDefault(); passwordInput.type = 'password' === passwordInput.type ? 'text' : 'password'"
href="#" tabindex="-1" class="d-inline-block">
<span *ngIf="'password' === passwordInput.type">Show</span>
<span *ngIf="'text' === passwordInput.type">Hide</span>
</a>
</small>
</div>
<input
#passwordInput
[attr.id]="formId + 'password'"
[attr.aria-describedby]="formId + 'password-help'"
type="password"
formControlName="password"
placeholder="Password"
autocomplete="password"
class="form-control"
[class.is-invalid]="passwordFc.touched && passwordFc.invalid">
<div class="invalid-feedback" *ngIf="passwordFc.touched && passwordFc.hasError('required')">
Required.
</div>
<div class="invalid-feedback" *ngIf="passwordFc.touched && passwordFc.hasError('auth/weak-password')">
That password is too weak.
</div>
<small [attr.id]="formId + 'password-help'" class="form-text text-muted">
Please choose a strong password.
</small>
</div>
<div class="form-group">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
[value]="true"
formControlName="remember"
[attr.id]="formId + 'remember'">
<label class="form-check-label" [attr.for]="formId + 'remember'">
Remember me on this device.
</label>
</div>
</div>
<div class="form-group">
<button type="submit"
class="btn btn-success btn-block"
[disabled]="fg.invalid || submitting">
<i class="fas fa-save fa-fw" aria-hidden="true"></i>
Save Password and Sign In
</button>
</div>
</form>
</div>
`,
styles: [``],
animations: [screenAnimation]
},] },
];
/** @nocollapse */
OobResetPasswordComponent.ctorParameters = () => [
{ type: AngularFireAuth },
{ type: NgxFirebaseAuthService }
];
OobResetPasswordComponent.propDecorators = {
oobCode: [{ type: Input }],
success: [{ type: Output }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class OobRecoverEmailComponent {
/**
* @param {?} _afAuth
*/
constructor(_afAuth) {
this._afAuth = _afAuth;
this.success = new EventEmitter();
this.screen = 'wait';
this.submitting = false;
}
/**
* @return {?}
*/
get auth() {
return this._afAuth.auth;
}
/**
* @return {?}
*/
ngOnInit() {
this.auth.checkActionCode(this.oobCode)
.then((result) => {
this.info = result;
this.screen = 'form';
})
.catch((error) => {
this.unhandledError = error;
this.screen = 'error';
});
}
/**
* @return {?}
*/
submit() {
this.auth.applyActionCode(this.oobCode)
.then(() => {
this.screen = 'success';
this.success.emit({
mode: 'recoverEmail',
info: this.info,
user: this.auth.currentUser
});
})
.catch((error) => {
this.unhandledError = error;
this.screen = 'error';
});
}
}
OobRecoverEmailComponent.decorators = [
{ type: Component, args: [{
selector: 'ngx-firebase-auth-oob-recover-email',
template: `
<div *ngIf="'wait' === screen" [@screen]="'in'">
<div class="alert alert-secondary">
<i class="fas fa-spin fa-spinner fa-fw" aria-hidden="true"></i>
Please wait...
</div>
</div>
<div *ngIf="'success' === screen" [@screen]="'in'">
<div class="alert alert-success">
<i class="fas fa-check fa-fw" aria-hidden="true"></i>
Your email has been changed back to {{info.data.email}};
</div>
</div>
<div *ngIf="screen === 'form'" [@screen]="'in'">
<div class="form-group">
<p>
Are you sure you want to change your email back to
{{info.data.email}} from {{info.data.fromEmail}}?
</p>
<button
type="button"
[disabled]="submitting"
(click)="submit()"
class="btn btn-block btn-success">
<i class="fas fa-save fa-fw" aria-hidden="true"></i>
Yes, Continue
</button>
</div>
</div>
<div *ngIf="screen === 'error'" [@screen]="'in'">
<div class="alert alert-danger">
<p>
<i class="fas fa-exclamation-triangle fa-fw" aria-hidden="true"></i>
Woops! An error occurred.
</p>
<div [ngSwitch]="unhandledError.code">
<p class="mb-0" *ngSwitchCase="'auth/expired-action-code'">
The recover email link you used has expired.
</p>
<p class="mb-0" *ngSwitchCase="'auth/invalid-action-code'">
The recover email link you used is not valid. This may be because it
has already been used.
</p>
<p class="mb-0" *ngSwitchCase="'auth/user-disabled'">
The account associated with the recover email link you used has been disabled.
</p>
<p class="mb-0" *ngSwitchCase="'auth/user-not-found'">
The account associated with the recover email link you used has been removed.
</p>
<div *ngSwitchDefault>
<p>Code: {{unhandledError.code}}</p>
<p class="mb-0">
Message: {{unhandledError.message}}
</p>
</div>
</div>
</div>
</div>
`,
styles: [``],
animations: [screenAnimation]
},] },
];
/** @nocollapse */
OobRecoverEmailComponent.ctorParameters = () => [
{ type: AngularFireAuth }
];
OobRecoverEmailComponent.propDecorators = {
oobCode: [{ type: Input }],
success: [{ type: Output }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class OobVerifyEmailComponent {
/**
* @param {?} _afAuth
*/
constructor(_afAuth) {
this._afAuth = _afAuth;
this.success = new EventEmitter();
this.screen = 'wait';
this.submitting = false;
}
/**
* @return {?}
*/
get auth() {
return this._afAuth.auth;
}
/**
* @return {?}
*/
ngOnInit() {
this.auth.checkActionCode(this.oobCode)
.then((result) => {
this.info = result;
return this.auth.applyActionCode(this.oobCode);
})
.then(() => {
this.screen = 'success';
this.success.emit({
mode: 'verifyEmail',
info: this.info,
user: this.auth.currentUser
});
})
.catch((error) => {
this.unhandledError = error;
this.screen = 'error';
});
}
}
OobVerifyEmailComponent.decorators = [
{ type: Component, args: [{
selector: 'ngx-firebase-auth-oob-verify-email',
template: `<div *ngIf="'wait' === screen" [@screen]="'in'">
<div class="alert alert-secondary">
<i class="fas fa-spin fa-spinner fa-fw" aria-hidden="true"></i>
Please wait...
</div>
</div>
<div *ngIf="'success' === screen" [@screen]="'in'">
<div class="alert alert-success">
<i class="fas fa-check fa-fw" aria-hidden="true"></i>
The email {{info.data.email}} has been verified.
</div>
</div>
<div *ngIf="screen === 'error'" [@screen]="'in'">
<div class="alert alert-danger">
<p>
<i class="fas fa-exclamation-triangle fa-fw" aria-hidden="true"></i>
Woops! An error occurred.
</p>
<div [ngSwitch]="unhandledError.code">
<p class="mb-0" *ngSwitchCase="'auth/expired-action-code'">
The verify email link you used has expired.
</p>
<p class="mb-0" *ngSwitchCase="'auth/invalid-action-code'">
The verify email link you used is not valid. This may be because it
has already been used.
</p>
<p class="mb-0" *ngSwitchCase="'auth/user-disabled'">
The account associated with the verify email link you used has been disabled.
</p>
<p class="mb-0" *ngSwitchCase="'auth/user-not-found'">
The account associated with the verify email link you used has been removed.
</p>
<div *ngSwitchDefault>
<p>Code: {{unhandledError.code}}</p>
<p class="mb-0">
Message: {{unhandledError.message}}
</p>
</div>
</div>
</div>
</div>
`,
styles: [``],
animations: [screenAnimation]
},] },
];
/** @nocollapse */
OobVerifyEmailComponent.ctorParameters = () => [
{ type: AngularFireAuth }
];
OobVerifyEmailComponent.propDecorators = {
oobCode: [{ type: Input }],
success: [{ type: Output }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class NgxFirebaseAuthOobModule {
}
NgxFirebaseAuthOobModule.decorators = [
{ type: NgModule, args: [{
imports: [
CommonModule,
ReactiveFormsModule,
RouterModule,
NgxFirebaseAuthModule
],
declarations: [
OobComponent,
OobRecoverEmailComponent,
OobResetPasswordComponent,
OobVerifyEmailComponent
],
exports: [
OobComponent,
]
},] },
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
export { fadeInOutAnimation, screenAnimation, getOAuthProviderName, getOAuthProviderIcon, NgxFirebaseAuthService, SignInComponent, OobComponent, NgxFirebaseAuthSignInModule, NgxFirebaseAuthOobModule, NgxFirebaseAuthModule, OobRecoverEmailComponent as ɵf, OobResetPasswordComponent as ɵg, OobVerifyEmailComponent as ɵh, ResetPasswordSendFormComponent as ɵd, SignInFormComponent as ɵb, SignInMethodsFormComponent as ɵa, SignInOauthComponent as ɵe, SignUpFormComponent as ɵc };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm93em9vLW5neC1maXJlYmFzZS1hdXRoLmpzLm1hcCIsInNvdXJjZXMiOlsibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9zaGFyZWQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL3NpZ24taW4vc2lnbi1pbi5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL29vYi9vb2IuY29tcG9uZW50LnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9mb3JtLWhlbHBlci50cyIsIm5nOi8vQG5vd3pvby9uZ3gtZmlyZWJhc2UtYXV0aC9saWIvc2lnbi1pbi9zaWduLWluLW1ldGhvZHMtZm9ybS9zaWduLWluLW1ldGhvZHMtZm9ybS5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL3NpZ24taW4vc2lnbi1pbi1mb3JtL3NpZ24taW4tZm9ybS5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL3NpZ24taW4vc2lnbi11cC1mb3JtL3NpZ24tdXAtZm9ybS5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL3NpZ24taW4vcmVzZXQtcGFzc3dvcmQtc2VuZC1mb3JtL3Jlc2V0LXBhc3N3b3JkLXNlbmQtZm9ybS5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL3NpZ24taW4vc2lnbi1pbi1vYXV0aC9zaWduLWluLW9hdXRoLmNvbXBvbmVudC50cyIsIm5nOi8vQG5vd3pvby9uZ3gtZmlyZWJhc2UtYXV0aC9saWIvbmd4LWZpcmViYXNlLWF1dGgubW9kdWxlLnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9zaWduLWluL25neC1maXJlYmFzZS1hdXRoLXNpZ24taW4ubW9kdWxlLnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9vb2Ivb29iLXJlc2V0LXBhc3N3b3JkL29vYi1yZXNldC1wYXNzd29yZC5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL29vYi9vb2ItcmVjb3Zlci1lbWFpbC9vb2ItcmVjb3Zlci1lbWFpbC5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL29vYi9vb2ItdmVyaWZ5LWVtYWlsL29vYi12ZXJpZnktZW1haWwuY29tcG9uZW50LnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9vb2Ivbmd4LWZpcmViYXNlLWF1dGgtb29iLm1vZHVsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBbmltYXRpb25UcmlnZ2VyTWV0YWRhdGEsIHRyaWdnZXIsIHN0YXRlLCBzdHlsZSwgYW5pbWF0ZSwgdHJhbnNpdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2FuaW1hdGlvbnMnO1xuaW1wb3J0IHsgYXV0aCwgVXNlciB9IGZyb20gJ2ZpcmViYXNlL2FwcCc7XG5cblxuZXhwb3J0IGludGVyZmFjZSBJU2lnbkluTWV0aG9kc0ZvckVtYWlsUmVzdWx0IHtcbiAgZW1haWw6IHN0cmluZztcbiAgbWV0aG9kczogc3RyaW5nW107XG4gIHN0YXR1czogJ3VuZmV0Y2hlZCcgfCAnZmV0Y2hpbmcnIHwgJ2ZldGNoZWQnO1xufVxuXG5cbmV4cG9ydCBpbnRlcmZhY2UgSU5neEZpcmViYXNlQXV0aFJlbWVtYmVyUmVjb3JkIHtcbiAgcmVtZW1iZXI6IGJvb2xlYW47XG4gIGVtYWlsOiBzdHJpbmc7XG59XG5cblxuZXhwb3J0IGNvbnN0IGZhZGVJbk91dEFuaW1hdGlvbjogQW5pbWF0aW9uVHJpZ2dlck1ldGFkYXRhID0gdHJpZ2dlcignZmFkZUluT3V0JywgW1xuICBzdGF0ZSgnaW4nLCBzdHlsZSh7b3BhY2l0eTogMSwgZGlzcGxheTogJ2Jsb2NrJ30pKSxcbiAgdHJhbnNpdGlvbigndm9pZCA9PiAqJywgW1xuICAgIHN0eWxlKHtvcGFjaXR5OiAwfSksXG4gICAgYW5pbWF0ZSgzMDApXG4gIF0pLFxuICB0cmFuc2l0aW9uKCcqID0+IHZvaWQnLCBbXG4gICAgYW5pbWF0ZSgzMDAsIHN0eWxlKHtvcGFjaXR5OiAwfSkpXG4gIF0pXG5dKTtcblxuZXhwb3J0IGNvbnN0IHNjcmVlbkFuaW1hdGlvbjogQW5pbWF0aW9uVHJpZ2dlck1ldGFkYXRhID0gdHJpZ2dlcignc2NyZWVuJywgW1xuICBzdGF0ZSgnaW4nLCBzdHlsZSh7b3BhY2l0eTogMX0pKSxcbiAgdHJhbnNpdGlvbigndm9pZCA9PiAqJywgW1xuICAgIHN0eWxlKHtvcGFjaXR5OiAwfSksXG4gICAgYW5pbWF0ZSgzMDApXG4gIF0pLFxuICB0cmFuc2l0aW9uKCcqID0+IHZvaWQnLCBbXG4gICAgYW5pbWF0ZSgwLCBzdHlsZSh7b3BhY2l0eTogMH0pKVxuICBdKVxuXSk7XG5cbmV4cG9ydCBjb25zdCBnZXRPQXV0aFByb3ZpZGVyTmFtZSA9IChpZDogc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgc3dpdGNoIChpZCkge1xuICAgIGNhc2UgJ3R3aXR0ZXIuY29tJzogcmV0dXJuICdUd2l0dGVyJztcbiAgICBjYXNlICdmYWNlYm9vay5jb20nOiByZXR1cm4gJ0ZhY2Vib29rJztcbiAgICBjYXNlICdnb29nbGUuY29tJzogcmV0dXJuICdHb29nbGUnO1xuICAgIGNhc2UgJ2dpdGh1Yi5jb20nOiByZXR1cm4gJ0dpdEh1Yic7XG4gICAgZGVmYXVsdDogcmV0dXJuIGlkO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0T0F1dGhQcm92aWRlckljb24gPSAoaWQ6IHN0cmluZyk6IHN0cmluZyAgPT4ge1xuICBzd2l0Y2ggKGlkKSB7XG4gICAgY2FzZSAndHdpdHRlci5jb20nOlxuICAgIGNhc2UgJ2ZhY2Vib29rLmNvbSc6XG4gICAgY2FzZSAnZ29vZ2xlLmNvbSc6XG4gICAgY2FzZSAnZ2l0aHViLmNvbSc6XG4gICAgICByZXR1cm4gJ2ZhYiBmYS1mdyBmYS0nICsgaWQucmVwbGFjZSgnLmNvbScsICcnKTtcbiAgICBkZWZhdWx0OiByZXR1cm4gJ2ZhcyBmYS1mdyBmYS1zaWduLWluLWFsdCc7XG4gIH1cbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgSU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3Mge1xuICBtb2RlOiAncmVzZXRQYXNzd29yZCcgfCAndmVyaWZ5RW1haWwnIHwgJ3JlY292ZXJFbWFpbCc7XG4gIGluZm86IGF1dGguQWN0aW9uQ29kZUluZm87XG4gIGNyZWQ/OiBhdXRoLlVzZXJDcmVkZW50aWFsO1xuICB1c2VyPzogVXNlcjtcbn1cbiIsImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IGF1dGgsIFVzZXIgfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgSU5neEZpcmViYXNlQXV0aFJlbWVtYmVyUmVjb3JkIH0gZnJvbSAnLi9zaGFyZWQnO1xuXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290J1xufSlcbmV4cG9ydCBjbGFzcyBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIHtcbiAgc3RhdGljIHJlbWVtYmVyS2V5ID0gJ25neC1maXJlYmFzZS1hdXRoLXJlbWVtYmVyJztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aFxuICApIHsgfVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG4gIGdldCBzdG9yYWdlKCk6IFN0b3JhZ2Uge1xuICAgIHJldHVybiB3aW5kb3cubG9jYWxTdG9yYWdlO1xuICB9XG5cbiAgZ2V0UmVtZW1iZXJlZCgpOiBJTmd4RmlyZWJhc2VBdXRoUmVtZW1iZXJSZWNvcmQge1xuICAgIGNvbnN0IHN0ciA9IHRoaXMuc3RvcmFnZS5nZXRJdGVtKE5neEZpcmViYXNlQXV0aFNlcnZpY2UucmVtZW1iZXJLZXkpO1xuICAgIGlmIChzdHIpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBKU09OLnBhcnNlKHN0cik7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiB7ZW1haWw6ICcnLCByZW1lbWJlcjogdHJ1ZX07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7ZW1haWw6ICcnLCByZW1lbWJlcjogdHJ1ZX07XG4gIH1cblxuICBzZXRSZW1lbWJlcmVkKHJlbWVtYmVyOiBib29sZWFuLCBlbWFpbDogc3RyaW5nKTogUHJvbWlzZTxJTmd4RmlyZWJhc2VBdXRoUmVtZW1iZXJSZWNvcmQ+IHtcbiAgICBjb25zdCBwZXJzaXN0ZW5jZTogYXV0aC5BdXRoLlBlcnNpc3RlbmNlID0gcmVtZW1iZXIgP1xuICAgICAgYXV0aC5BdXRoLlBlcnNpc3RlbmNlLkxPQ0FMIDogYXV0aC5BdXRoLlBlcnNpc3RlbmNlLlNFU1NJT047XG4gICAgcmV0dXJuIHRoaXMuYXV0aC5zZXRQZXJzaXN0ZW5jZShwZXJzaXN0ZW5jZSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgY29uc3QgbzogSU5neEZpcmViYXNlQXV0aFJlbWVtYmVyUmVjb3JkID0ge1xuICAgICAgICAgIGVtYWlsOiByZW1lbWJlciA/IGVtYWlsIDogJycsXG4gICAgICAgICAgcmVtZW1iZXI6IHJlbWVtYmVyXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHN0ciA9IEpTT04uc3RyaW5naWZ5KG8pO1xuICAgICAgICB0aGlzLnN0b3JhZ2Uuc2V0SXRlbShOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlLnJlbWVtYmVyS2V5LCBzdHIpO1xuICAgICAgICByZXR1cm4gbztcbiAgICAgIH0pO1xuICB9XG5cblxuXG59XG4iLCJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgT25EZXN0cm95LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIFRlbXBsYXRlUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBSb3V0ZXIsIEFjdGl2YXRlZFJvdXRlIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IEZvcm1Hcm91cCwgRm9ybUNvbnRyb2wsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBTdWJqZWN0LCBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdhbmd1bGFyZmlyZTIvYXV0aCc7XG5pbXBvcnQgeyBhdXRoLCBVc2VyIH0gZnJvbSAnZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IHNjcmVlbkFuaW1hdGlvbiB9IGZyb20gJy4uL3NoYXJlZCc7XG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyIH0gZnJvbSAnLi4vZm9ybS1oZWxwZXInO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoU2VydmljZSB9IGZyb20gJy4uL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UnO1xuXG5cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWZpcmViYXNlLWF1dGgtc2lnbi1pbicsXG4gIHRlbXBsYXRlOiBgPGRpdiAqbmdJZj1cIid3YWl0JyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc2Vjb25kYXJ5XCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtc3BpbiBmYS1zcGlubmVyIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFBsZWFzZSB3YWl0Li4uXG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCIndW5oYW5kbGVkRXJyb3InID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIj5cbiAgICA8aSBjbGFzcz1cImZhcyBmYS1leGNsYW1hdGlvbi10cmlhbmdsZSBmYS1mdyB0ZXh0LWRhbmdlclwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICA8c3Ryb25nPldvb3BzITwvc3Ryb25nPiBBbiB1bmV4cGVjdGVkIGVycm9yIG9jY3VycmVkLlxuICA8L2Rpdj5cbiAgPHAgY2xhc3M9XCJ0ZXh0LW11dGVkXCI+XG4gICAgQ29kZToge3t1bmhhbmRsZWRFcnJvci5jb2RlfX0uIE1lc3NhZ2U6IHt7dW5oYW5kbGVkRXJyb3IubWVzc2FnZX19XG4gIDwvcD5cbiAgPHA+XG4gICAgPGEgcm91dGVyTGluaz1cIi5cIiBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbid9XCI+U3RhcnQgT3ZlcjwvYT5cbiAgPC9wPlxuPC9kaXY+XG5cblxuPGRpdiAqbmdJZj1cIidzaWduSW5TdWNjZXNzJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc3VjY2Vzc1wiPlxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLWNoZWNrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFdlbGNvbWUsIHt7Y3JlZC51c2VyLmRpc3BsYXlOYW1lfX0hXG4gIDwvZGl2PlxuPC9kaXY+XG5cblxuXG5cbjxkaXYgKm5nSWY9XCInc2lnbkluJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc3VjY2Vzc1wiICpuZ0lmPVwic2lnbmVkT3V0XCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtY2hlY2sgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgWW91w6LCgMKZcmUgc2lnbmVkIG91dC5cbiAgPC9kaXY+XG4gIDxuZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW1ldGhvZHMtZm9ybVxuICAgIFsoZW1haWwpXT1cImVtYWlsXCJcbiAgICBbKHJlbWVtYmVyKV09XCJyZW1lbWJlclwiXG4gICAgW29BdXRoUHJvdmlkZXJJZHNdPVwib0F1dGhQcm92aWRlcklkc1wiXG4gICAgKGVycm9yKT1cInNob3dVbmhhbmRsZWRFcnJvcigkZXZlbnQpXCJcbiAgICAoc3VjY2Vzcyk9XCJzaG93U2lnbkluU3VjY2VzcygkZXZlbnQpXCI+PC9uZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW1ldGhvZHMtZm9ybT5cbiAgPHNtYWxsIGNsYXNzPVwidGV4dC1jZW50ZXIgdGV4dC1tdXRlZCBteS0yIGZvcm0tdGV4dFwiPlxuICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ0b3NUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxuICA8L3NtYWxsPlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCInc2lnbkluUGFzc3dvcmQnID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxuZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLWZvcm1cbiAgICBbZW1haWxdPVwiZW1haWxcIlxuICAgIFsocmVtZW1iZXIpXT1cInJlbWVtYmVyXCJcbiAgICAoZXJyb3IpPVwic2hvd1VuaGFuZGxlZEVycm9yKCRldmVudClcIlxuICAgIChzdWNjZXNzKT1cInNob3dTaWduSW5TdWNjZXNzKCRldmVudClcIj48L25neC1maXJlYmFzZS1hdXRoLXNpZ24taW4tZm9ybT5cbiAgPHNtYWxsIGNsYXNzPVwidGV4dC1jZW50ZXIgdGV4dC1tdXRlZCBteS0yIGZvcm0tdGV4dFwiPlxuICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ0b3NUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxuICA8L3NtYWxsPlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCInc2lnblVwUGFzc3dvcmQnID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxuZ3gtZmlyZWJhc2UtYXV0aC1zaWduLXVwLWZvcm1cbiAgICBbZW1haWxdPVwiZW1haWxcIlxuICAgIFsocmVtZW1iZXIpXT1cInJlbWVtYmVyXCJcbiAgICAoZXJyb3IpPVwic2hvd1VuaGFuZGxlZEVycm9yKCRldmVudClcIlxuICAgIChzdWNjZXNzKT1cInNob3dTaWduSW5TdWNjZXNzKCRldmVudClcIj48L25neC1maXJlYmFzZS1hdXRoLXNpZ24tdXAtZm9ybT5cbiAgPHNtYWxsIGNsYXNzPVwidGV4dC1jZW50ZXIgdGV4dC1tdXRlZCBteS0yIGZvcm0tdGV4dFwiPlxuICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ0b3NUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxuICA8L3NtYWxsPlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCInc2lnbkluT0F1dGgnID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxuZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW9hdXRoXG4gICAgW3Byb3ZpZGVySWRdPVwib0F1dGhQcm92aWRlcklkXCJcbiAgICBbaW5pdGlhbEVycm9yXT1cImluaXRpYWxPQXV0aEVycm9yXCJcbiAgICBbdXNlT0F1dGhQb3B1cF09XCJ1c2VPQXV0aFBvcHVwXCJcbiAgICBbb0F1dGhQcm92aWRlckZhY3RvcnldPVwib0F1dGhQcm92aWRlckZhY3RvcnlcIlxuICAgIFsoZW1haWwpXT1cImVtYWlsXCJcbiAgICBbKHJlbWVtYmVyKV09XCJyZW1lbWJlclwiXG4gICAgKGVycm9yKT1cInNob3dVbmhhbmRsZWRFcnJvcigkZXZlbnQpXCJcbiAgICAoc3VjY2Vzcyk9XCJzaG93U2lnbkluU3VjY2VzcygkZXZlbnQpXCI+PC9uZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW9hdXRoPlxuICA8c21hbGwgY2xhc3M9XCJ0ZXh0LWNlbnRlciB0ZXh0LW11dGVkIG15LTIgZm9ybS10ZXh0XCI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInRvc1RlbXBsYXRlXCI+PC9uZy1jb250YWluZXI+XG4gIDwvc21hbGw+XG48L2Rpdj5cblxuXG5cbjxkaXYgKm5nSWY9XCIncmVzZXRQYXNzd29yZCcgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGg2PlJlc2V0IFBhc3N3b3JkPC9oNj5cbiAgPG5neC1maXJlYmFzZS1hdXRoLXJlc2V0LXBhc3N3b3JkLXNlbmQtZm9ybVxuICAgIFsoZW1haWwpXT1cImVtYWlsXCJcbiAgICAoZXJyb3IpPVwic2hvd1VuaGFuZGxlZEVycm9yKCRldmVudClcIj48L25neC1maXJlYmFzZS1hdXRoLXJlc2V0LXBhc3N3b3JkLXNlbmQtZm9ybT5cbjwvZGl2PlxuYCxcbiAgc3R5bGVzOiBbYGBdLFxuICBhbmltYXRpb25zOiBbc2NyZWVuQW5pbWF0aW9uXVxufSlcbmV4cG9ydCBjbGFzcyBTaWduSW5Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIHByaXZhdGUgbmdVbnN1YnNjcmliZTogU3ViamVjdDx2b2lkPiA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gIEBJbnB1dCgpIG9BdXRoUHJvdmlkZXJJZHM6IHN0cmluZ1tdO1xuICBASW5wdXQoKSB1c2VPQXV0aFBvcHVwOiBib29sZWFuO1xuICBASW5wdXQoKSBvQXV0aFByb3ZpZGVyRmFjdG9yeTogKHByb3ZpZGVySWQ6IHN0cmluZykgPT4gYXV0aC5BdXRoUHJvdmlkZXI7XG4gIEBJbnB1dCgpIHRvc1RlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+ID0gbnVsbDtcbiAgQE91dHB1dCgpIHN1Y2Nlc3M6IEV2ZW50RW1pdHRlcjxhdXRoLlVzZXJDcmVkZW50aWFsPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIG1vZGU6IEV2ZW50RW1pdHRlcjwnc2lnbkluJyB8ICdyZXNldFBhc3N3b3JkJz4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgcmVtZW1iZXI6IGJvb2xlYW47XG4gIGVtYWlsOiBzdHJpbmc7XG4gIGluaXRpYWxPQXV0aEVycm9yOiBhdXRoLkVycm9yID0gbnVsbDtcbiAgc2lnbmVkT3V0ID0gZmFsc2U7XG4gIG9BdXRoUHJvdmlkZXJJZDogc3RyaW5nID0gbnVsbDtcbiAgY3JlZDogYXV0aC5Vc2VyQ3JlZGVudGlhbCA9IG51bGw7XG4gIHVuaGFuZGxlZEVycm9yOiBhdXRoLkVycm9yID0gbnVsbDtcblxuICBzY3JlZW46ICd3YWl0JyB8XG4gICAgJ3NpZ25JbicgfCAnc2lnbkluUGFzc3dvcmQnIHwgJ3NpZ25VcFBhc3N3b3JkJyB8ICdzaWduSW5PQXV0aCcgfCAnc2lnbkluU3VjY2VzcycgfFxuICAgICdyZXNldFBhc3N3b3JkJyB8ICd1bmhhbmRsZWRFcnJvcicgPSAnd2FpdCc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICAgcHJpdmF0ZSBfc3ZjOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlLFxuICAgIHByaXZhdGUgX3JvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgICBwcml2YXRlIF9yb3V0ZXI6IFJvdXRlcixcbiAgKSB7fVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG5cbiAgZ2V0IGF1dGhTZXJ2aWNlKCk6IE5neEZpcmViYXNlQXV0aFNlcnZpY2Uge1xuICAgIHJldHVybiB0aGlzLl9zdmM7XG4gIH1cblxuICBnZXQgcm91dGVyKCk6IFJvdXRlciB7XG4gICAgcmV0dXJuIHRoaXMuX3JvdXRlcjtcbiAgfVxuXG4gIGdldCByb3V0ZSgpOiBBY3RpdmF0ZWRSb3V0ZSB7XG4gICAgcmV0dXJuIHRoaXMuX3JvdXRlO1xuICB9XG5cbiAgZ2V0IHF1ZXJ5UGFyYW1zKCk6IE9ic2VydmFibGU8e1trZXk6IHN0cmluZ106IGFueX0+IHtcbiAgICByZXR1cm4gdGhpcy5yb3V0ZS5xdWVyeVBhcmFtcztcbiAgfVxuXG4gIGdldCBzbmFwc2hvdFF1ZXJ5UGFyYW1zKCk6IHtba2V5OiBzdHJpbmddOiBhbnl9IHtcbiAgICByZXR1cm4gdGhpcy5yb3V0ZS5zbmFwc2hvdC5xdWVyeVBhcmFtcztcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuaW5pdCgpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5uZ1Vuc3Vic2NyaWJlLm5leHQoKTtcbiAgICB0aGlzLm5nVW5zdWJzY3JpYmUuY29tcGxldGUoKTtcbiAgfVxuXG4gIGluaXQoKSB7XG4gICAgY29uc3QgcmVtZW1iZXJSZWNvcmQgPSB0aGlzLmF1dGhTZXJ2aWNlLmdldFJlbWVtYmVyZWQoKTtcbiAgICB0aGlzLnJlbWVtYmVyID0gcmVtZW1iZXJSZWNvcmQucmVtZW1iZXI7XG4gICAgdGhpcy5lbWFpbCA9IHJlbWVtYmVyUmVjb3JkLmVtYWlsO1xuICAgIHJldHVybiB0aGlzLm9uSW5pdEhhbmRsZVNpZ25PdXQoKVxuICAgICAgLnRoZW4oKGhhbmRsZWQ6IGJvb2xlYW4pID0+IHtcbiAgICAgICAgaWYgKGhhbmRsZWQpIHtcbiAgICAgICAgICByZXR1cm4gaGFuZGxlZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5vbkluaXRIYW5kbGVPQXV0aFJlZGlyZWN0KCk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKGhhbmRsZWQ6IGJvb2xlYW4pID0+IHtcbiAgICAgICAgaWYgKCEgaGFuZGxlZCkge1xuICAgICAgICAgIHRoaXMuc2hvd1NpZ25JbigpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucXVlcnlQYXJhbXMucGlwZSh0YWtlVW50aWwodGhpcy5uZ1Vuc3Vic2NyaWJlKSkuc3Vic2NyaWJlKHBhcmFtcyA9PiB7XG4gICAgICAgICAgY29uc3QgYWN0aW9uID0gcGFyYW1zLmFjdGlvbiB8fCBudWxsO1xuICAgICAgICAgIHN3aXRjaCAoYWN0aW9uKSB7XG4gICAgICAgICAgICBjYXNlICdzaWduT3V0JzpcbiAgICAgICAgICAgICAgdGhpcy5zaG93U2lnbk91dCgpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3Jlc2V0UGFzc3dvcmQnOlxuICAgICAgICAgICAgICB0aGlzLnNob3dSZXNldFBhc3N3b3JkKCk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnc2lnbkluJzpcbiAgICAgICAgICAgICAgdGhpcy5zaG93U2lnbkluKCk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnc2lnbkluUGFzc3dvcmQnOlxuICAgICAgICAgICAgICB0aGlzLnNob3dTaWduSW5QYXNzd29yZCgpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3NpZ25VcFBhc3N3b3JkJzpcbiAgICAgICAgICAgICAgdGhpcy5zaG93U2lnblVwUGFzc3dvcmQoKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdzaWduSW5PQXV0aCc6XG4gICAgICAgICAgICAgIHRoaXMuc2hvd1NpZ25Jbk9BdXRoKHBhcmFtcy5wcm92aWRlcklkLCBudWxsKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICB9XG5cbiAgb25Jbml0SGFuZGxlU2lnbk91dCgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAodGhpcy5zbmFwc2hvdFF1ZXJ5UGFyYW1zLmFjdGlvbiAhPT0gJ3NpZ25PdXQnKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGZhbHNlKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2hvd1NpZ25PdXQoKS50aGVuKCgpID0+IHRydWUpO1xuICB9XG4gIG9uSW5pdEhhbmRsZU9BdXRoUmVkaXJlY3QoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgY29uc3QgcmVtZW1iZXI6IGJvb2xlYW4gPSB0aGlzLnJvdXRlLnNuYXBzaG90LnF1ZXJ5UGFyYW1zLnJlbWVtYmVyID09PSAndHJ1ZSc7XG4gICAgICByZXR1cm4gdGhpcy5hdXRoLmdldFJlZGlyZWN0UmVzdWx0KClcbiAgICAgICAgLnRoZW4oKGNyZWQ6IGF1dGguVXNlckNyZWRlbnRpYWwpID0+IHtcbiAgICAgICAgICBpZiAodGhpcy5hdXRoLmN1cnJlbnRVc2VyICYmIGNyZWQudXNlcikge1xuICAgICAgICAgICAgdGhpcy5hdXRoU2VydmljZS5zZXRSZW1lbWJlcmVkKHJlbWVtYmVyLCBjcmVkLnVzZXIuZW1haWwpXG4gICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3dTaWduSW5TdWNjZXNzKGNyZWQpO1xuICAgICAgICAgICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXNvbHZlKGZhbHNlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaCgoZXJyb3I6IGF1dGguRXJyb3IpID0+IHtcbiAgICAgICAgICB0aGlzLnNob3dTaWduSW5PQXV0aChudWxsLCBlcnJvciApO1xuICAgICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cblxuXG5cbiAgc2hvd1NpZ25PdXQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICB0aGlzLnNpZ25lZE91dCA9IGZhbHNlO1xuICAgIHRoaXMuc2NyZWVuID0gJ3dhaXQnO1xuICAgIHJldHVybiB0aGlzLmF1dGguc2lnbk91dCgpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMuc2hvd1NpZ25Jbih0cnVlKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgc2hvd1NpZ25JbihzaWduZWRPdXQ/OiBib29sZWFuKSB7XG4gICAgdGhpcy5tb2RlLmVtaXQoJ3NpZ25JbicpO1xuICAgIHRoaXMuc2lnbmVkT3V0ID0gc2lnbmVkT3V0ID09PSB0cnVlO1xuICAgIHRoaXMuc2NyZWVuID0gJ3NpZ25Jbic7XG4gIH1cblxuICBzaG93U2lnbkluUGFzc3dvcmQoKSB7XG4gICAgdGhpcy5tb2RlLmVtaXQoJ3NpZ25JbicpO1xuICAgIHRoaXMuc2lnbmVkT3V0ID0gZmFsc2U7XG4gICAgdGhpcy5zY3JlZW4gPSAnc2lnbkluUGFzc3dvcmQnO1xuICB9XG5cbiAgc2hvd1NpZ25VcFBhc3N3b3JkKCkge1xuICAgIHRoaXMubW9kZS5lbWl0KCdzaWduSW4nKTtcbiAgICB0aGlzLnNpZ25lZE91dCA9IGZhbHNlO1xuICAgIHRoaXMuc2NyZWVuID0gJ3NpZ25VcFBhc3N3b3JkJztcblxuICB9XG5cbiAgc2hvd1NpZ25Jbk9BdXRoKG9BdXRoUHJvdmlkZXJJZDogc3RyaW5nLCBlcnJvcjogYXV0aC5FcnJvcikge1xuICAgIHRoaXMubW9kZS5lbWl0KCdzaWduSW4nKTtcbiAgICB0aGlzLnNpZ25lZE91dCA9IGZhbHNlO1xuICAgIHRoaXMub0F1dGhQcm92aWRlcklkID0gb0F1dGhQcm92aWRlcklkO1xuICAgIHRoaXMuaW5pdGlhbE9BdXRoRXJyb3IgPSBlcnJvcjtcbiAgICB0aGlzLnNjcmVlbiA9ICdzaWduSW5PQXV0aCc7XG4gIH1cblxuICBzaG93U2lnbkluU3VjY2VzcyhjcmVkOiBhdXRoLlVzZXJDcmVkZW50aWFsKSB7XG4gICAgdGhpcy5tb2RlLmVtaXQoJ3NpZ25JbicpO1xuICAgIHRoaXMuc2lnbmVkT3V0ID0gZmFsc2U7XG4gICAgdGhpcy5jcmVkID0gY3JlZDtcbiAgICB0aGlzLnNjcmVlbiA9ICdzaWduSW5TdWNjZXNzJztcbiAgICB0aGlzLnN1Y2Nlc3MuZW1pdChjcmVkKTtcbiAgfVxuXG4gIHNob3dSZXNldFBhc3N3b3JkKCkge1xuICAgIHRoaXMubW9kZS5lbWl0KCdyZXNldFBhc3N3b3JkJyk7XG4gICAgdGhpcy5zaWduZWRPdXQgPSBmYWxzZTtcbiAgICB0aGlzLnNjcmVlbiA9ICdyZXNldFBhc3N3b3JkJztcbiAgfVxuXG4gIHNob3dVbmhhbmRsZWRFcnJvcihlcnJvcjogYXV0aC5FcnJvcikge1xuICAgIHRoaXMuc2lnbmVkT3V0ID0gZmFsc2U7XG4gICAgdGhpcy51bmhhbmRsZWRFcnJvciA9IGVycm9yO1xuICAgIHRoaXMuc2NyZWVuID0gJ3VuaGFuZGxlZEVycm9yJztcbiAgfVxufVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBzY3JlZW5BbmltYXRpb24gfSBmcm9tICcuLi9zaGFyZWQnO1xuaW1wb3J0IHsgSU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3MgfSBmcm9tICcuLi9zaGFyZWQnO1xuXG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLW9vYicsXG4gIHRlbXBsYXRlOiBgPGRpdiAqbmdJZj1cIidyZXNldFBhc3N3b3JkJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8bmd4LWZpcmViYXNlLWF1dGgtb29iLXJlc2V0LXBhc3N3b3JkXG4gICAgW29vYkNvZGVdPVwib29iQ29kZVwiXG4gICAgKHN1Y2Nlc3MpPVwic3VjY2Vzcy5lbWl0KCRldmVudClcIj48L25neC1maXJlYmFzZS1hdXRoLW9vYi1yZXNldC1wYXNzd29yZD5cbjwvZGl2PlxuXG48ZGl2ICpuZ0lmPVwiJ3ZlcmlmeUVtYWlsJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8bmd4LWZpcmViYXNlLWF1dGgtb29iLXZlcmlmeS1lbWFpbFxuICAgIFtvb2JDb2RlXT1cIm9vYkNvZGVcIlxuICAgIChzdWNjZXNzKT1cInN1Y2Nlc3MuZW1pdCgkZXZlbnQpXCI+PC9uZ3gtZmlyZWJhc2UtYXV0aC1vb2ItdmVyaWZ5LWVtYWlsPlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCIncmVjb3ZlckVtYWlsJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8bmd4LWZpcmViYXNlLWF1dGgtb29iLXJlY292ZXItZW1haWxcbiAgICBbb29iQ29kZV09XCJvb2JDb2RlXCJcbiAgICAoc3VjY2Vzcyk9XCJzdWNjZXNzLmVtaXQoJGV2ZW50KVwiPjwvbmd4LWZpcmViYXNlLWF1dGgtb29iLXJlY292ZXItZW1haWw+XG48L2Rpdj5cbmAsXG4gIHN0eWxlczogW2BgXSxcbiAgYW5pbWF0aW9uczogW3NjcmVlbkFuaW1hdGlvbl1cbn0pXG5leHBvcnQgY2xhc3MgT29iQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBvb2JDb2RlOiBzdHJpbmc7XG4gIHNjcmVlbjogJ3Jlc2V0UGFzc3dvcmQnIHwgJ3ZlcmlmeUVtYWlsJyB8ICdyZWNvdmVyRW1haWwnID0gbnVsbDtcblxuICBAT3V0cHV0KCkgbW9kZTogRXZlbnRFbWl0dGVyPCdyZXNldFBhc3N3b3JkJyB8ICd2ZXJpZnlFbWFpbCcgfCAncmVjb3ZlckVtYWlsJz4gID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgbmF2aWdhdGlvbkVycm9yOiBFdmVudEVtaXR0ZXI8dm9pZD4gID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgc3VjY2VzczogRXZlbnRFbWl0dGVyPElOZ3hGaXJlYmFzZUF1dGhPb2JTdWNjZXNzPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgX3JvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgKSB7IH1cblxuXG4gIGdldCBxdWVyeVBhcmFtcygpOiB7W2tleTogc3RyaW5nXTogYW55fSB7XG4gICAgcmV0dXJuIHRoaXMuX3JvdXRlLnNuYXBzaG90LnF1ZXJ5UGFyYW1zO1xuICB9XG5cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLm9vYkNvZGUgPSB0aGlzLnF1ZXJ5UGFyYW1zLm9vYkNvZGUgfHwgbnVsbDtcbiAgICBpZiAoISB0aGlzLm9vYkNvZGUpIHtcbiAgICAgIHRoaXMubmF2aWdhdGlvbkVycm9yLmVtaXQoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgc3dpdGNoICh0aGlzLnF1ZXJ5UGFyYW1zLm1vZGUpIHtcbiAgICAgIGNhc2UgJ3Jlc2V0UGFzc3dvcmQnOlxuICAgICAgY2FzZSAndmVyaWZ5RW1haWwnOlxuICAgICAgY2FzZSAncmVjb3ZlckVtYWlsJzpcbiAgICAgICAgdGhpcy5zY3JlZW4gPSB0aGlzLnF1ZXJ5UGFyYW1zLm1vZGU7XG4gICAgICAgIHRoaXMubW9kZS5lbWl0KHRoaXMucXVlcnlQYXJhbXMubW9kZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhpcy5uYXZpZ2F0aW9uRXJyb3IuZW1pdCgpO1xuICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgfVxufVxuIiwiaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgdGFrZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmV4cG9ydCBjbGFzcyBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyIHtcbiAgc3RhdGljIHNldEVycm9yVW50aWxDaGFuZ2VkKGZjOiBBYnN0cmFjdENvbnRyb2wsIGtleTogc3RyaW5nLCB2YWx1ZTogYW55ID0gdHJ1ZSkge1xuICAgIGNvbnN0IGVycm9yID0ge307XG4gICAgZXJyb3Jba2V5XSA9IHZhbHVlO1xuICAgIGZjLnNldEVycm9ycyhlcnJvcik7XG4gICAgZmMudmFsdWVDaGFuZ2VzLnBpcGUodGFrZSgxKSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIuY2xlYXJFcnJvcihmYywga2V5KTtcbiAgICB9KTtcblxuICB9XG5cbiAgc3RhdGljIGNsZWFyRXJyb3IoZmM6IEFic3RyYWN0Q29udHJvbCwga2V5OiBzdHJpbmcpIHtcbiAgICBjb25zdCBlcnJvcnMgPSB7fTtcbiAgICBpZiAoISBmYy5lcnJvcnMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgT2JqZWN0LmtleXMoZmMuZXJyb3JzKS5mb3JFYWNoKChrKSA9PiB7XG4gICAgICBpZiAoayAhPT0ga2V5KSB7XG4gICAgICAgIGVycm9yc1trXSA9IGZjLmVycm9yc1trXTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBpZiAoT2JqZWN0LmtleXMoZXJyb3JzKS5sZW5ndGggPT09IDApIHtcbiAgICAgIGZjLnNldEVycm9ycyhudWxsKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZmMuc2V0RXJyb3JzKGVycm9ycyk7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIHJlcXVpcmVkTm9uRW1wdHkoZmM6IEFic3RyYWN0Q29udHJvbCkge1xuICAgIGNvbnN0IHZhbHVlID0gZmMudmFsdWU7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWUudHJpbSgpLmxlbmd0aCA9PT0gMCA/IHtyZXF1aXJlZDogdHJ1ZX0gOiBudWxsO1xuICB9XG5cblxufVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIEFmdGVyVmlld0luaXQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgTmdab25lLCBWaWV3Q2hpbGQsIEVsZW1lbnRSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Db250cm9sLCBGb3JtR3JvdXAsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdhbmd1bGFyZmlyZTIvYXV0aCc7XG5pbXBvcnQgeyBhdXRoIH0gZnJvbSAnZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IGRlYm91bmNlVGltZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IElTaWduSW5NZXRob2RzRm9yRW1haWxSZXN1bHQsIGdldE9BdXRoUHJvdmlkZXJJY29uLCBnZXRPQXV0aFByb3ZpZGVyTmFtZSB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyIH0gZnJvbSAnLi4vLi4vZm9ybS1oZWxwZXInO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoU2VydmljZSB9IGZyb20gJy4uLy4uL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UnO1xuaW1wb3J0IHsgZmFkZUluT3V0QW5pbWF0aW9uLCBzY3JlZW5BbmltYXRpb24gfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW1ldGhvZHMtZm9ybScsXG4gIHRlbXBsYXRlOiBgPGZvcm0gW2Zvcm1Hcm91cF09XCJmZ1wiPlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiPkVtYWlsIEFkZHJlc3M8L2xhYmVsPlxuICAgIDxpbnB1dFxuICAgICAgI2VtYWlsSW5wdXRcbiAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdlbWFpbCdcIlxuICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJmb3JtSWQgKyAnZW1haWwnXCJcbiAgICAgIHR5cGU9XCJlbWFpbFwiXG4gICAgICBhdXRvY29tcGxldGU9XCJlbWFpbFwiXG4gICAgICBwbGFjZWhvbGRlcj1cIkVtYWlsIEFkZHJlc3NcIlxuICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiZW1haWxcIlxuICAgICAgKGJsdXIpPVwiZmV0Y2goKVwiXG4gICAgICAoa2V5dXAuZW50ZXIpPVwiZW1haWxJbnB1dC5ibHVyKClcIlxuICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwiZW1haWxGYy50b3VjaGVkICYmIGVtYWlsRmMuaW52YWxpZFwiPlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMudG91Y2hlZCAmJiBlbWFpbEZjLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCI+XG4gICAgICBSZXF1aXJlZC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLnRvdWNoZWQgJiYgZW1haWxGYy5oYXNFcnJvcignZW1haWwnKVwiPlxuICAgICAgSW52YWxpZCBlbWFpbC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLnRvdWNoZWQgJiYgZW1haWxGYy5oYXNFcnJvcignYXV0aC9pbnZhbGlkLWVtYWlsJylcIj5cbiAgICAgIEludmFsaWQgZW1haWwuXG4gICAgPC9kaXY+XG4gICAgPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZCBmb3JtLXRleHRcIiBbYXR0ci5pZF09XCJmb3JtSWQgKyAnZW1haWwnXCIgW25nU3dpdGNoXT1cImZldGNoU3RhdHVzXCI+XG4gICAgICA8c3BhbiAqbmdTd2l0Y2hDYXNlPVwiJ3VuZmV0Y2hlZCdcIiBbQGZhZGVJbk91dF09XCInaW4nXCI+XG4gICAgICAgIFRvIGdldCBzdGFydGVkLCBlbnRlciB5b3VyIGVtYWlsIGFkZHJlc3MuXG4gICAgICAgIElmIHlvdSBkb27DosKAwpl0IHlldCBoYXZlIGFuIGFjY291bnQgd2XDosKAwplsbCBjcmVhdGUgb25lIGZvciB5b3UuXG4gICAgICA8L3NwYW4+XG4gICAgICA8c3BhbiAqbmdTd2l0Y2hDYXNlPVwiJ2ZldGNoaW5nJ1wiIFtAZmFkZUluT3V0XT1cIidpbidcIj5cbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtc3BpbiBmYS1zcGlubmVyIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgICBMb29raW5nIHVwIGFjY291bnQuLi5cbiAgICAgIDwvc3Bhbj5cbiAgICAgIDxzcGFuICpuZ1N3aXRjaENhc2U9XCInZmV0Y2hlZCdcIiBbQGZhZGVJbk91dF09XCInaW4nXCI+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWNoZWNrIGZhLWZ3IHRleHQtc3VjY2Vzc1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgICAgPHNwYW4gKm5nSWY9XCJhY2NvdW50RXhpc3RzXCI+QWNjb3VudCBmb3VuZC48L3NwYW4+XG4gICAgICAgIDxzcGFuICpuZ0lmPVwiYWNjb3VudElzTmV3XCI+V2UnbGwgY3JlYXRlIGFuIGFjY291bnQuPC9zcGFuPlxuICAgICAgPC9zcGFuPlxuICAgIDwvc21hbGw+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrXCI+XG4gICAgICA8aW5wdXRcbiAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCJcbiAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgW3ZhbHVlXT1cInRydWVcIlxuICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZW1lbWJlclwiXG4gICAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWxcIiBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgICBSZW1lbWJlciBtZSBvbiB0aGlzIGRldmljZS5cbiAgICAgIDwvbGFiZWw+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9mb3JtPlxuPGRpdiAqbmdJZj1cIm1ldGhvZHNGZXRjaGVkICYmIGFjY291bnRFeGlzdHNcIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxzbWFsbCBjbGFzcz1cInRleHQtbXV0ZWQgbWItMSBmb3JtLXRleHRcIj5cbiAgICA8c3BhbiAqbmdJZj1cImFjY291bnRIYXNQYXNzd29yZFwiPlxuICAgICAgPHNwYW4gKm5nSWY9XCJhY2NvdW50T0F1dGhNZXRob2RzLmxlbmd0aCA9PT0gMFwiPlxuICAgICAgICBQbGVhc2Ugc2lnbiBpbiB3aXRoIHlvdXIgcGFzc3dvcmQuLi5cbiAgICAgIDwvc3Bhbj5cbiAgICAgIDxzcGFuICpuZ0lmPVwiYWNjb3VudE9BdXRoTWV0aG9kcy5sZW5ndGggPT09IDFcIj5cbiAgICAgICAgUGxlYXNlIHNpZ24gaW4gd2l0aCB5b3VyIHBhc3N3b3JkIG9yIHlvdXJcbiAgICAgICAgbGlua2VkIHt7Z2V0T0F1dGhQcm92aWRlck5hbWUoYWNjb3VudE9BdXRoTWV0aG9kc1swXSl9fSBhY2NvdW50Li4uXG4gICAgICA8L3NwYW4+XG4gICAgICA8c3BhbiAqbmdJZj1cImFjY291bnRPQXV0aE1ldGhvZHMubGVuZ3RoID4gMVwiPlxuICAgICAgICBQbGVhc2Ugc2lnbiBpbiB3aXRoIHlvdXIgcGFzc3dvcmQgb3Igb25lIG9mIHlvdXIgbGlua2VkIGFjY291bnRzLi4uXG4gICAgICA8L3NwYW4+XG4gICAgPC9zcGFuPlxuICAgIDxzcGFuICpuZ0lmPVwiIWFjY291bnRIYXNQYXNzd29yZFwiPlxuICAgICAgPHNwYW4gKm5nSWY9XCJhY2NvdW50T0F1dGhNZXRob2RzLmxlbmd0aCA9PT0gMVwiPlxuICAgICAgICBQbGVhc2Ugc2lnbiBpbiB3aXRoIHlvdXJcbiAgICAgICAgbGlua2VkIHt7Z2V0T0F1dGhQcm92aWRlck5hbWUoYWNjb3VudE9BdXRoTWV0aG9kc1swXSl9fSBhY2NvdW50Li4uXG4gICAgICA8L3NwYW4+XG4gICAgICA8c3BhbiAqbmdJZj1cImFjY291bnRPQXV0aE1ldGhvZHMubGVuZ3RoID4gMVwiPlxuICAgICAgICBQbGVhc2Ugc2lnbiBpbiB3aXRoIG9uZSBvZiB5b3VyIGxpbmtlZCBhY2NvdW50cy4uLlxuICAgICAgPC9zcGFuPlxuICAgIDwvc3Bhbj5cblxuICA8L3NtYWxsPlxuXG4gIDxkaXYgY2xhc3M9XCJsaXN0LWdyb3VwXCI+XG4gICAgPGFcbiAgICAgICpuZ0lmPVwiYWNjb3VudEhhc1Bhc3N3b3JkXCJcbiAgICAgIHJvdXRlckxpbms9XCIuXCJcbiAgICAgIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluUGFzc3dvcmQnfVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBjbGFzcz1cImZhcyBmYS1sb2NrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgPHNwYW4gY2xhc3M9XCJtbC0yXCI+XG4gICAgICAgIFNpZ24gSW4gd2l0aCBZb3VyIFBhc3N3b3JkXG4gICAgICA8L3NwYW4+XG4gICAgPC9hPlxuICAgIDxhXG4gICAgICAqbmdGb3I9XCJsZXQgaWQgb2YgYWNjb3VudE9BdXRoTWV0aG9kc1wiXG4gICAgICByb3V0ZXJMaW5rPVwiLlwiXG4gICAgICBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbk9BdXRoJywgcHJvdmlkZXJJZDogaWR9XCJcbiAgICAgIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGxpc3QtZ3JvdXAtaXRlbS1hY3Rpb25cIj5cbiAgICAgIDxpIFthdHRyLmNsYXNzXT1cImdldE9BdXRoUHJvdmlkZXJJY29uKGlkKVwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIDxzcGFuIGNsYXNzPVwibWwtMlwiPlxuICAgICAgICBTaWduIEluIHdpdGgge3tnZXRPQXV0aFByb3ZpZGVyTmFtZShpZCl9fVxuICAgICAgPC9zcGFuPlxuICAgIDwvYT5cbiAgPC9kaXY+XG48L2Rpdj5cblxuPGRpdiAqbmdJZj1cIm1ldGhvZHNGZXRjaGVkICYmIGFjY291bnRJc05ld1wiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZCBtYi0xIGZvcm0tdGV4dFwiPlxuICAgIDxzcGFuICpuZ0lmPVwib0F1dGhQcm92aWRlcklkcy5sZW5ndGggPT09IDBcIj5cbiAgICAgIFBsZWFzZSBjcmVhdGUgYW4gYWNjb3VudC4uLlxuICAgIDwvc3Bhbj5cbiAgICA8c3BhbiAqbmdJZj1cIm9BdXRoUHJvdmlkZXJJZHMubGVuZ3RoID09PSAxXCI+XG4gICAgICBQbGVhc2Ugc2lnbiB1cCB3aXRoIHlvdXJcbiAgICAgIHt7Z2V0T0F1dGhQcm92aWRlck5hbWUob0F1dGhQcm92aWRlcklkc1swXSl9fSBhY2NvdW50LFxuICAgICAgb3IgY3JlYXRlIGEgc2VwYXJhdGUgYWNjb3VudCB3aXRoIGEgcGFzc3dvcmQuLi4uXG4gICAgPC9zcGFuPlxuICAgIDxzcGFuICpuZ0lmPVwib0F1dGhQcm92aWRlcklkcy5sZW5ndGggPjFcIj5cbiAgICAgIFBsZWFzZSBzaWduIHVwIHdpdGggb25lIG9mIHRoZSBzZXJ2aWNlcyBsaXN0ZWQgYmVsb3csXG4gICAgICBvciBjcmVhdGUgYSBzZXBhcmF0ZSBhY2NvdW50IHdpdGggYSBwYXNzd29yZC4uLi5cbiAgICA8L3NwYW4+XG4gIDwvc21hbGw+XG4gIDxkaXYgY2xhc3M9XCJsaXN0LWdyb3VwXCI+XG5cbiAgICA8YVxuICAgICAgKm5nRm9yPVwibGV0IGlkIG9mIG9BdXRoUHJvdmlkZXJJZHNcIlxuICAgICAgcm91dGVyTGluaz1cIi5cIlxuICAgICAgW3F1ZXJ5UGFyYW1zXT1cInthY3Rpb246ICdzaWduSW5PQXV0aCcsIHByb3ZpZGVySWQ6IGlkfVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBbYXR0ci5jbGFzc109XCJnZXRPQXV0aFByb3ZpZGVySWNvbihpZClcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICA8c3BhbiBjbGFzcz1cIm1sLTJcIj5cbiAgICAgICAgU2lnbiBVcCB3aXRoIHt7Z2V0T0F1dGhQcm92aWRlck5hbWUoaWQpfX1cbiAgICAgIDwvc3Bhbj5cbiAgICA8L2E+XG4gICAgPGFcbiAgICAgIHJvdXRlckxpbms9XCIuXCJcbiAgICAgIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnblVwUGFzc3dvcmQnfVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBjbGFzcz1cImZhcyBmYS1sb2NrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgPHNwYW4gY2xhc3M9XCJtbC0yXCI+XG4gICAgICAgIENyZWF0ZVxuICAgICAgICA8c3BhbiAqbmdJZj1cIm9BdXRoUHJvdmlkZXJJZHMubGVuZ3RoID4gMFwiPlxuICAgICAgICAgIGEgU2VwYXJhdGVcbiAgICAgICAgPC9zcGFuPlxuICAgICAgICBBY2NvdW50XG4gICAgICA8L3NwYW4+XG4gICAgPC9hPlxuICA8L2Rpdj5cbjwvZGl2PlxuYCxcbiAgc3R5bGVzOiBbYGBdLFxuICBhbmltYXRpb25zOiBbZmFkZUluT3V0QW5pbWF0aW9uLCBzY3JlZW5BbmltYXRpb25dXG59KVxuZXhwb3J0IGNsYXNzIFNpZ25Jbk1ldGhvZHNGb3JtQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0IHtcblxuXG4gIEBWaWV3Q2hpbGQoJ2VtYWlsSW5wdXQnKSBlbWFpbElucHV0OiBFbGVtZW50UmVmO1xuICBASW5wdXQoKSBlbWFpbDogc3RyaW5nO1xuICBASW5wdXQoKSByZW1lbWJlcjogYm9vbGVhbjtcbiAgQElucHV0KCkgb0F1dGhQcm92aWRlcklkczogc3RyaW5nW10gPSBbXTtcbiAgQE91dHB1dCgpIGVtYWlsQ2hhbmdlOiBFdmVudEVtaXR0ZXI8c3RyaW5nPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHJlbWVtYmVyQ2hhbmdlOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBzdWNjZXNzOiBFdmVudEVtaXR0ZXI8YXV0aC5Vc2VyQ3JlZGVudGlhbD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBlcnJvcjogRXZlbnRFbWl0dGVyPGF1dGguRXJyb3I+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG5cbiAgZm9ybUlkID0gJ25neC1maXJlYmFzZS1hdXRoLXNpZ24taW4tbWV0aG9kcy1mb3JtLSc7XG4gIHN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgZmc6IEZvcm1Hcm91cDtcbiAgZW1haWxGYzogRm9ybUNvbnRyb2w7XG4gIHJlbWVtYmVyRmM6IEZvcm1Db250cm9sO1xuICBnZXRPQXV0aFByb3ZpZGVySWNvbiA9IGdldE9BdXRoUHJvdmlkZXJJY29uO1xuICBnZXRPQXV0aFByb3ZpZGVyTmFtZSA9IGdldE9BdXRoUHJvdmlkZXJOYW1lO1xuICBtZXRob2RzRm9yRW1haWw6IElTaWduSW5NZXRob2RzRm9yRW1haWxSZXN1bHQgPSB7c3RhdHVzOiAndW5mZXRjaGVkJywgbWV0aG9kczogW10sIGVtYWlsOiBudWxsfTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgICBwcml2YXRlIF9hdXRoU2VydmljZTogTmd4RmlyZWJhc2VBdXRoU2VydmljZSxcbiAgICBwcml2YXRlIF9uZ1pvbmU6IE5nWm9uZVxuICApIHsgfVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG4gIGdldCBhdXRoU2VydmljZSgpOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIHtcbiAgICByZXR1cm4gdGhpcy5fYXV0aFNlcnZpY2U7XG4gIH1cblxuXG4gIGdldCBtZXRob2RzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5tZXRob2RzRm9yRW1haWwubWV0aG9kcztcbiAgfVxuXG4gIGdldCBmZXRjaFN0YXR1cygpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLm1ldGhvZHNGb3JFbWFpbC5zdGF0dXM7XG4gIH1cblxuICBnZXQgbWV0aG9kc0ZldGNoZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubWV0aG9kc0ZvckVtYWlsLnN0YXR1cyA9PT0gJ2ZldGNoZWQnO1xuICB9XG5cbiAgZ2V0IGFjY291bnRJc05ldygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5tZXRob2RzRmV0Y2hlZCAmJiB0aGlzLm1ldGhvZHMubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgZ2V0IGFjY291bnRFeGlzdHMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubWV0aG9kc0ZldGNoZWQgJiYgdGhpcy5tZXRob2RzLmxlbmd0aCA+IDA7XG4gIH1cblxuICBnZXQgYWNjb3VudEhhc1Bhc3N3b3JkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmFjY291bnRFeGlzdHMgJiYgdGhpcy5tZXRob2RzLmluZGV4T2YoJ3Bhc3N3b3JkJykgIT09IC0xO1xuICB9XG5cbiAgZ2V0IGFjY291bnRPQXV0aE1ldGhvZHMoKTogc3RyaW5nW10ge1xuICAgIGlmICghIHRoaXMuYWNjb3VudEV4aXN0cykge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5tZXRob2RzLmZpbHRlcihpZCA9PiBpZCAhPT0gJ3Bhc3N3b3JkJyk7XG4gIH1cblxuXG5cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmVtYWlsRmMgPSBuZXcgRm9ybUNvbnRyb2woXG4gICAgICB0aGlzLmVtYWlsLFxuICAgICAge3ZhbGlkYXRvcnM6IFtWYWxpZGF0b3JzLnJlcXVpcmVkLCBWYWxpZGF0b3JzLmVtYWlsXX1cbiAgICApO1xuICAgIHRoaXMucmVtZW1iZXJGYyA9IG5ldyBGb3JtQ29udHJvbCh0aGlzLnJlbWVtYmVyKTtcbiAgICB0aGlzLnJlbWVtYmVyRmMudmFsdWVDaGFuZ2VzLnN1YnNjcmliZSgoKSA9PiB0aGlzLnJlbWVtYmVyQ2hhbmdlLmVtaXQodGhpcy5yZW1lbWJlckZjLnZhbHVlKSk7XG4gICAgdGhpcy5mZyA9IG5ldyBGb3JtR3JvdXAoe2VtYWlsOiB0aGlzLmVtYWlsRmMsIHJlbWVtYmVyOiB0aGlzLnJlbWVtYmVyRmN9KTtcbiAgICB0aGlzLmVtYWlsRmMudmFsdWVDaGFuZ2VzLnN1YnNjcmliZSgoKSA9PiB0aGlzLmVtYWlsQ2hhbmdlLmVtaXQodGhpcy5lbWFpbEZjLnZhbHVlLnRyaW0oKSkpO1xuICAgIHRoaXMuZW1haWxGYy52YWx1ZUNoYW5nZXMucGlwZShkZWJvdW5jZVRpbWUoNTAwKSkuc3Vic2NyaWJlKCgpID0+IHRoaXMuZmV0Y2goKSk7XG4gICAgdGhpcy5mZXRjaCgpO1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIHRoaXMuZW1haWxJbnB1dC5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG5cbiAgfVxuXG5cbiAgZmV0Y2goKSB7XG4gICAgY29uc3QgZW1haWwgPSB0aGlzLmVtYWlsRmMudmFsdWUudHJpbSgpO1xuICAgIGlmIChlbWFpbCA9PT0gdGhpcy5tZXRob2RzRm9yRW1haWwuZW1haWwpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKCdmZXRjaGluZycgPT09IHRoaXMubWV0aG9kc0ZvckVtYWlsLnN0YXR1cykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLm1ldGhvZHNGb3JFbWFpbCA9IHtzdGF0dXM6ICdmZXRjaGluZycsIG1ldGhvZHM6IFtdLCBlbWFpbDogZW1haWx9O1xuICAgIGlmICh0aGlzLmVtYWlsRmMuaW52YWxpZCkge1xuICAgICAgdGhpcy5tZXRob2RzRm9yRW1haWwgPSB7c3RhdHVzOiAndW5mZXRjaGVkJywgbWV0aG9kczogW10sIGVtYWlsOiBlbWFpbH07XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuYXV0aC5mZXRjaFNpZ25Jbk1ldGhvZHNGb3JFbWFpbChlbWFpbClcbiAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICB0aGlzLm1ldGhvZHNGb3JFbWFpbCA9IHtzdGF0dXM6ICdmZXRjaGVkJywgbWV0aG9kczogcmVzdWx0cywgZW1haWw6IGVtYWlsfTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKGVycm9yOiBhdXRoLkVycm9yKSA9PiB7XG4gICAgICAgIHRoaXMuZW1haWxGYy5tYXJrQXNEaXJ0eSgpO1xuICAgICAgICB0aGlzLmVtYWlsRmMubWFya0FzVG91Y2hlZCgpO1xuICAgICAgICBzd2l0Y2ggKGVycm9yLmNvZGUpIHtcbiAgICAgICAgICBjYXNlICdhdXRoL2ludmFsaWQtZW1haWwnOlxuICAgICAgICAgICAgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlci5zZXRFcnJvclVudGlsQ2hhbmdlZCh0aGlzLmVtYWlsRmMsIGVycm9yLmNvZGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5tZXRob2RzRm9yRW1haWwgPSB7ZW1haWw6IHRoaXMuZW1haWwsIHN0YXR1czogJ3VuZmV0Y2hlZCcsIG1ldGhvZHM6IFtdfTtcbiAgICAgIH0pO1xuICB9XG5cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBBZnRlclZpZXdJbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIFZpZXdDaGlsZCwgRWxlbWVudFJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IGF1dGggfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuXG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyIH0gZnJvbSAnLi4vLi4vZm9ybS1oZWxwZXInO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoU2VydmljZSB9IGZyb20gJy4uLy4uL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UnO1xuaW1wb3J0IHsgZ2V0T0F1dGhQcm92aWRlckljb24sIGdldE9BdXRoUHJvdmlkZXJOYW1lLCBmYWRlSW5PdXRBbmltYXRpb24gfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuXG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLXNpZ24taW4tZm9ybScsXG4gIHRlbXBsYXRlOiBgPGZvcm0gW2Zvcm1Hcm91cF09XCJmZ1wiIChuZ1N1Ym1pdCk9XCJzdWJtaXQoKVwiPlxuXG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGxhYmVsIFthdHRyLmZvcl09XCJmb3JtSWQgKyAnZW1haWwnXCI+RW1haWwgQWRkcmVzczwvbGFiZWw+XG5cbiAgICA8aW5wdXRcbiAgICAgIHJlYWRvbmx5XG4gICAgICAjZW1haWxJbnB1dFxuICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiXG4gICAgICBbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XT1cImZvcm1JZCArICdlbWFpbCdcIlxuICAgICAgdHlwZT1cImVtYWlsXCJcbiAgICAgIGF1dG9jb21wbGV0ZT1cImVtYWlsXCJcbiAgICAgIHBsYWNlaG9sZGVyPVwiRW1haWwgQWRkcmVzc1wiXG4gICAgICBmb3JtQ29udHJvbE5hbWU9XCJlbWFpbFwiXG4gICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiPlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ3JlcXVpcmVkJylcIj5cbiAgICAgIFJlcXVpcmVkLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ2VtYWlsJylcIj5cbiAgICAgIEludmFsaWQgZW1haWwuXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy5oYXNFcnJvcignYXV0aC9pbnZhbGlkLWVtYWlsJylcIj5cbiAgICAgIEludmFsaWQgZW1haWwuXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy5oYXNFcnJvcignYXV0aC91c2VyLW5vdC1mb3VuZCcpXCI+XG4gICAgICBXZSBjb3VsZCBub3QgZmluZCBhbiBhY2NvdW50IHdpdGggdGhhdCBlbWFpbCBhZGRyZXNzLlxuICAgICAgPGEgcm91dGVyTGluaz1cIi5cIiBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbid9XCI+Q3JlYXRlIEFjY291bnQ8L2E+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy5oYXNFcnJvcignYXV0aC91c2VyLWRpc2FibGVkJylcIj5cbiAgICAgIFRoZSBhY2NvdW50IHdpdGggdGhhdCBlbWFpbCBhZGRyZXNzIGhhcyBiZWVuIGRpc2FibGVkLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ25neC1maXJlYmFzZS1hdXRoL25vLXBhc3N3b3JkJylcIj5cbiAgICAgIFRoZSBhY2NvdW50IHdpdGggdGhhdCBlbWFpbCBhZGRyZXNzIGRvZXMgbm90IGhhdmUgYSBwYXNzd29yZC5cbiAgICAgIFBsZWFzZSBzaWduIGluIHVzaW5nOlxuICAgICAgPHNwYW4gKm5nRm9yPVwibGV0IGlkIG9mIG1ldGhvZHNGb3JFbWFpbDsgbGV0IGlzTGFzdCA9IGxhc3RcIj5cbiAgICAgICAgPGEgcm91dGVyTGluaz1cIi5cIiBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbk9BdXRoJywgcHJvdmlkZXJJZDogaWR9XCI+e3tnZXRPQXV0aFByb3ZpZGVyTmFtZShpZCl9fTwvYT5cbiAgICAgICAgPHNwYW4gKm5nSWY9XCIhaXNMYXN0XCI+XG4gICAgICAgICAgfFxuICAgICAgICA8L3NwYW4+XG4gICAgICA8L3NwYW4+XG4gICAgPC9kaXY+XG5cbiAgICA8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkIGZvcm0tdGV4dFwiIFthdHRyLmlkXT1cImZvcm1JZCArICdlbWFpbCdcIiA+XG4gICAgICBOb3QgeW91ciBlbWFpbCBhZGRyZXNzP1xuICAgICAgPGEgcm91dGVyTGluaz1cIi5cIiBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbid9XCI+U3RhcnQgT3ZlcjwvYT5cbiAgICA8L3NtYWxsPlxuICA8L2Rpdj5cblxuXG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBhbGlnbi1pdGVtcy1lbmRcIj5cbiAgICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkJ1wiPlBhc3N3b3JkPC9sYWJlbD5cbiAgICAgIDxzbWFsbD5cbiAgICAgICAgPGEgKGNsaWNrKT1cIiRldmVudC5wcmV2ZW50RGVmYXVsdCgpOyBwYXNzd29yZElucHV0LnR5cGUgPSAncGFzc3dvcmQnID09PSBwYXNzd29yZElucHV0LnR5cGUgID8gJ3RleHQnIDogJ3Bhc3N3b3JkJ1wiXG4gICAgICAgICAgaHJlZj1cIiNcIiB0YWJpbmRleD1cIi0xXCIgY2xhc3M9XCJkLWlubGluZS1ibG9ja1wiPlxuICAgICAgICAgIDxzcGFuICpuZ0lmPVwiJ3Bhc3N3b3JkJyA9PT0gcGFzc3dvcmRJbnB1dC50eXBlXCI+U2hvdzwvc3Bhbj5cbiAgICAgICAgICA8c3BhbiAqbmdJZj1cIid0ZXh0JyA9PT0gcGFzc3dvcmRJbnB1dC50eXBlXCI+SGlkZTwvc3Bhbj5cbiAgICAgICAgPC9hPlxuICAgICAgPC9zbWFsbD5cbiAgICA8L2Rpdj5cbiAgICA8aW5wdXRcbiAgICAgICNwYXNzd29yZElucHV0XG4gICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAncGFzc3dvcmQnXCJcbiAgICAgIFthdHRyLmFyaWEtZGVzY3JpYmVkYnldPVwiZm9ybUlkICsgJ3Bhc3N3b3JkLWhlbHAnXCJcbiAgICAgIHR5cGU9XCJwYXNzd29yZFwiXG4gICAgICBmb3JtQ29udHJvbE5hbWU9XCJwYXNzd29yZFwiXG4gICAgICBwbGFjZWhvbGRlcj1cIlBhc3N3b3JkXCJcbiAgICAgIGF1dG9jb21wbGV0ZT1cInBhc3N3b3JkXCJcbiAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgIFtjbGFzcy5pcy1pbnZhbGlkXT1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmludmFsaWRcIj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiXG4gICAgICAqbmdJZj1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCJcbiAgICAgIFtAZmFkZUluT3V0XT1cIidpbidcIj5cbiAgICAgIFJlcXVpcmVkLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCJcbiAgICAgICpuZ0lmPVwicGFzc3dvcmRGYy50b3VjaGVkICYmIHBhc3N3b3JkRmMuaGFzRXJyb3IoJ2F1dGgvd3JvbmctcGFzc3dvcmQnKVwiXG4gICAgICBbQGZhZGVJbk91dF09XCInaW4nXCI+XG4gICAgICBXcm9uZyBwYXNzd29yZC5cbiAgICA8L2Rpdj5cbiAgICA8c21hbGwgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkLWhlbHAnXCIgY2xhc3M9XCJmb3JtLXRleHQgdGV4dC1tdXRlZFwiPlxuICAgICAgRm9yZ290PyA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAncmVzZXRQYXNzd29yZCd9XCI+UmVzZXQgUGFzc3dvcmQ8L2E+XG4gICAgPC9zbWFsbD5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2tcIj5cbiAgICAgIDxpbnB1dFxuICAgICAgICBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIlxuICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICBbdmFsdWVdPVwidHJ1ZVwiXG4gICAgICAgIGZvcm1Db250cm9sTmFtZT1cInJlbWVtYmVyXCJcbiAgICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbFwiIFthdHRyLmZvcl09XCJmb3JtSWQgKyAncmVtZW1iZXInXCI+XG4gICAgICAgIFJlbWVtYmVyIG1lIG9uIHRoaXMgZGV2aWNlLlxuICAgICAgPC9sYWJlbD5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGJ1dHRvbiB0eXBlPVwic3VibWl0XCJcbiAgICAgIGNsYXNzPVwiYnRuIGJ0bi1zdWNjZXNzIGJ0bi1ibG9ja1wiXG4gICAgICBbZGlzYWJsZWRdPVwiZmcuaW52YWxpZCB8fCBzdWJtaXR0aW5nXCI+XG4gICAgICA8aSBjbGFzcz1cImZhcyBmYS1sb2NrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgU2lnbiBJblxuICAgIDwvYnV0dG9uPlxuICA8L2Rpdj5cbjwvZm9ybT5cbmAsXG4gIHN0eWxlczogW2BgXSxcbiAgYW5pbWF0aW9uczogW2ZhZGVJbk91dEFuaW1hdGlvbl1cbn0pXG5leHBvcnQgY2xhc3MgU2lnbkluRm9ybUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XG5cbiAgQFZpZXdDaGlsZCgncGFzc3dvcmRJbnB1dCcpIHBhc3N3b3JkSW5wdXQ6IEVsZW1lbnRSZWY7XG4gIEBJbnB1dCgpIGVtYWlsOiBzdHJpbmc7XG4gIEBJbnB1dCgpIHJlbWVtYmVyOiBib29sZWFuO1xuICBAT3V0cHV0KCkgcmVtZW1iZXJDaGFuZ2U6IEV2ZW50RW1pdHRlcjxib29sZWFuPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHN1Y2Nlc3M6IEV2ZW50RW1pdHRlcjxhdXRoLlVzZXJDcmVkZW50aWFsPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIGVycm9yOiBFdmVudEVtaXR0ZXI8YXV0aC5FcnJvcj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgZm9ybUlkID0gJ25neC1maXJlYmFzZS1hdXRoLXNpZ24taW4tZm9ybS0nO1xuICBzdWJtaXR0aW5nID0gZmFsc2U7XG4gIGZnOiBGb3JtR3JvdXA7XG4gIGVtYWlsRmM6IEZvcm1Db250cm9sO1xuICBwYXNzd29yZEZjOiBGb3JtQ29udHJvbDtcbiAgcmVtZW1iZXJGYzogRm9ybUNvbnRyb2w7XG4gIG1ldGhvZHNGb3JFbWFpbDogc3RyaW5nW10gPSBbXTtcbiAgZ2V0T0F1dGhQcm92aWRlckljb24gPSBnZXRPQXV0aFByb3ZpZGVySWNvbjtcbiAgZ2V0T0F1dGhQcm92aWRlck5hbWUgPSBnZXRPQXV0aFByb3ZpZGVyTmFtZTtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICAgcHJpdmF0ZSBfYXV0aFNlcnZpY2U6IE5neEZpcmViYXNlQXV0aFNlcnZpY2VcbiAgKSB7IH1cblxuICBnZXQgYXV0aCgpOiBhdXRoLkF1dGgge1xuICAgIHJldHVybiB0aGlzLl9hZkF1dGguYXV0aDtcbiAgfVxuXG4gIGdldCBhdXRoU2VydmljZSgpOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIHtcbiAgICByZXR1cm4gdGhpcy5fYXV0aFNlcnZpY2U7XG4gIH1cblxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuZW1haWxGYyA9IG5ldyBGb3JtQ29udHJvbChcbiAgICAgIHRoaXMuZW1haWwsXG4gICAgICB7dmFsaWRhdG9yczogW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMuZW1haWxdfVxuICAgICk7XG4gICAgdGhpcy5wYXNzd29yZEZjID0gbmV3IEZvcm1Db250cm9sKCcnLCB7dmFsaWRhdG9yczogW1ZhbGlkYXRvcnMucmVxdWlyZWRdfSk7XG4gICAgdGhpcy5yZW1lbWJlckZjID0gbmV3IEZvcm1Db250cm9sKHRoaXMucmVtZW1iZXIpO1xuICAgIHRoaXMucmVtZW1iZXJGYy52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKHZhbCA9PiB0aGlzLnJlbWVtYmVyQ2hhbmdlLmVtaXQodmFsKSk7XG4gICAgdGhpcy5mZyA9IG5ldyBGb3JtR3JvdXAoe1xuICAgICAgZW1haWw6IHRoaXMuZW1haWxGYyxcbiAgICAgIHBhc3N3b3JkOiB0aGlzLnBhc3N3b3JkRmMsXG4gICAgICByZW1lbWJlcjogdGhpcy5yZW1lbWJlckZjXG4gICAgfSk7XG4gIH1cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIHRoaXMucGFzc3dvcmRJbnB1dC5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gIH1cblxuXG5cbiAgc3VibWl0KCkge1xuICAgIGNvbnN0IGVtYWlsID0gdGhpcy5lbWFpbEZjLnZhbHVlLnRyaW0oKTtcbiAgICB0aGlzLnN1Ym1pdHRpbmcgPSB0cnVlO1xuICAgIHRoaXMubWV0aG9kc0ZvckVtYWlsID0gW107XG4gICAgbGV0IGNyZWQ6IGF1dGguVXNlckNyZWRlbnRpYWw7XG4gICAgdGhpcy5hdXRoLmZldGNoU2lnbkluTWV0aG9kc0ZvckVtYWlsKGVtYWlsKVxuICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgIHRoaXMubWV0aG9kc0ZvckVtYWlsID0gcmVzdWx0cztcbiAgICAgICAgaWYgKHJlc3VsdHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHtcbiAgICAgICAgICAgIGNvZGU6ICdhdXRoL3VzZXItbm90LWZvdW5kJ1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZXN1bHRzLmluZGV4T2YoJ3Bhc3N3b3JkJykgPT09IC0xKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHtcbiAgICAgICAgICAgIGNvZGU6ICduZ3gtZmlyZWJhc2UtYXV0aC9uby1wYXNzd29yZCcsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aC5zaWduSW5XaXRoRW1haWxBbmRQYXNzd29yZChlbWFpbCwgdGhpcy5wYXNzd29yZEZjLnZhbHVlKTtcbiAgICAgIH0pXG4gICAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICBjcmVkID0gcmVzdWx0O1xuICAgICAgICByZXR1cm4gdGhpcy5hdXRoU2VydmljZS5zZXRSZW1lbWJlcmVkKHRoaXMucmVtZW1iZXJGYy52YWx1ZSA9PT0gdHJ1ZSwgZW1haWwpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgdGhpcy5zdWNjZXNzLmVtaXQoY3JlZCk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgdGhpcy5zdWJtaXR0aW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZW1haWxGYy5tYXJrQXNEaXJ0eSgpO1xuICAgICAgICB0aGlzLmVtYWlsRmMubWFya0FzVG91Y2hlZCgpO1xuICAgICAgICB0aGlzLnBhc3N3b3JkRmMubWFya0FzRGlydHkoKTtcbiAgICAgICAgdGhpcy5wYXNzd29yZEZjLm1hcmtBc1RvdWNoZWQoKTtcbiAgICAgICAgc3dpdGNoIChlcnJvci5jb2RlKSB7XG4gICAgICAgICAgY2FzZSAnYXV0aC9pbnZhbGlkLWVtYWlsJzpcbiAgICAgICAgICBjYXNlICdhdXRoL3VzZXItbm90LWZvdW5kJzpcbiAgICAgICAgICBjYXNlICdhdXRoL3VzZXItZGlzYWJsZWQnOlxuICAgICAgICAgIGNhc2UgJ25neC1maXJlYmFzZS1hdXRoL25vLXBhc3N3b3JkJzpcbiAgICAgICAgICAgIE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIuc2V0RXJyb3JVbnRpbENoYW5nZWQodGhpcy5lbWFpbEZjLCBlcnJvci5jb2RlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ2F1dGgvd3JvbmctcGFzc3dvcmQnOlxuICAgICAgICAgICAgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlci5zZXRFcnJvclVudGlsQ2hhbmdlZCh0aGlzLnBhc3N3b3JkRmMsIGVycm9yLmNvZGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRoaXMuZXJyb3IuZW1pdChlcnJvcik7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxufVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIEFmdGVyVmlld0luaXQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgVmlld0NoaWxkLCBFbGVtZW50UmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtQ29udHJvbCwgRm9ybUdyb3VwLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgQW5ndWxhckZpcmVBdXRoIH0gZnJvbSAnYW5ndWxhcmZpcmUyL2F1dGgnO1xuaW1wb3J0IHsgYXV0aCB9IGZyb20gJ2ZpcmViYXNlL2FwcCc7XG5cbmltcG9ydCB7IGZhZGVJbk91dEFuaW1hdGlvbiB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyIH0gZnJvbSAnLi4vLi4vZm9ybS1oZWxwZXInO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoU2VydmljZSB9IGZyb20gJy4uLy4uL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UnO1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWZpcmViYXNlLWF1dGgtc2lnbi11cC1mb3JtJyxcbiAgdGVtcGxhdGU6IGA8Zm9ybSBbZm9ybUdyb3VwXT1cImZnXCIgKG5nU3VibWl0KT1cInN1Ym1pdCgpXCI+XG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGxhYmVsIFthdHRyLmZvcl09XCJmb3JtSWQgKyAnZW1haWwnXCI+RW1haWwgQWRkcmVzczwvbGFiZWw+XG4gICAgPGlucHV0XG4gICAgICByZWFkb25seVxuICAgICAgI2VtYWlsSW5wdXRcbiAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdlbWFpbCdcIlxuICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJmb3JtSWQgKyAnZW1haWwnXCJcbiAgICAgIHR5cGU9XCJlbWFpbFwiXG4gICAgICBhdXRvY29tcGxldGU9XCJlbWFpbFwiXG4gICAgICBwbGFjZWhvbGRlcj1cIkVtYWlsIEFkZHJlc3NcIlxuICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiZW1haWxcIlxuICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCI+XG4gICAgICBSZXF1aXJlZC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLmhhc0Vycm9yKCdlbWFpbCcpXCI+XG4gICAgICBJbnZhbGlkIGVtYWlsLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ2F1dGgvaW52YWxpZC1lbWFpbCcpXCI+XG4gICAgICBJbnZhbGlkIGVtYWlsLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ25neC1maXJlYmFzZS1hdXRoL2FjY291bnQtZXhpc3RzJylcIj5cbiAgICAgIFdlIGZvdW5kIGFuIGFjY291bnQgd2l0aCB0aGF0IGVtYWlsIGFkZHJlc3MuXG4gICAgICA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluJ31cIj5TaWduIEluPC9hPlxuICAgIDwvZGl2PlxuICAgIDxzbWFsbCBjbGFzcz1cInRleHQtbXV0ZWQgZm9ybS10ZXh0XCIgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiID5cbiAgICAgIE5vdCB5b3VyIGVtYWlsIGFkZHJlc3M/XG4gICAgICA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluJ31cIj5HbyBCYWNrPC9hPlxuICAgIDwvc21hbGw+XG4gIDwvZGl2PlxuXG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBhbGlnbi1pdGVtcy1lbmRcIj5cbiAgICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkJ1wiPkNob29zZSBQYXNzd29yZDwvbGFiZWw+XG4gICAgICA8c21hbGw+XG4gICAgICAgIDxhIChjbGljayk9XCIkZXZlbnQucHJldmVudERlZmF1bHQoKTsgcGFzc3dvcmRJbnB1dC50eXBlID0gJ3Bhc3N3b3JkJyA9PT0gcGFzc3dvcmRJbnB1dC50eXBlICA/ICd0ZXh0JyA6ICdwYXNzd29yZCdcIlxuICAgICAgICAgIGhyZWY9XCIjXCIgdGFiaW5kZXg9XCItMVwiIGNsYXNzPVwiZC1pbmxpbmUtYmxvY2tcIj5cbiAgICAgICAgICA8c3BhbiAqbmdJZj1cIidwYXNzd29yZCcgPT09IHBhc3N3b3JkSW5wdXQudHlwZVwiPlNob3c8L3NwYW4+XG4gICAgICAgICAgPHNwYW4gKm5nSWY9XCIndGV4dCcgPT09IHBhc3N3b3JkSW5wdXQudHlwZVwiPkhpZGU8L3NwYW4+XG4gICAgICAgIDwvYT5cbiAgICAgIDwvc21hbGw+XG4gICAgPC9kaXY+XG4gICAgPGlucHV0XG4gICAgICAjcGFzc3dvcmRJbnB1dFxuICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkJ1wiXG4gICAgICBbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XT1cImZvcm1JZCArICdwYXNzd29yZC1oZWxwJ1wiXG4gICAgICB0eXBlPVwicGFzc3dvcmRcIlxuICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicGFzc3dvcmRcIlxuICAgICAgcGxhY2Vob2xkZXI9XCJDaG9vc2UgUGFzc3dvcmRcIlxuICAgICAgYXV0b2NvbXBsZXRlPVwicGFzc3dvcmRcIlxuICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwicGFzc3dvcmRGYy50b3VjaGVkICYmIHBhc3N3b3JkRmMuaW52YWxpZFwiPlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCI+XG4gICAgICBSZXF1aXJlZC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJwYXNzd29yZEZjLnRvdWNoZWQgJiYgcGFzc3dvcmRGYy5oYXNFcnJvcignYXV0aC93cm9uZy1wYXNzd29yZCcpXCI+XG4gICAgICBXcm9uZyBwYXNzd29yZC5cbiAgICA8L2Rpdj5cbiAgICA8c21hbGwgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkLWhlbHAnXCIgY2xhc3M9XCJmb3JtLXRleHQgdGV4dC1tdXRlZFwiPlxuICAgICAgUGxlYXNlIGNob29zZSBhIHN0cm9uZyBwYXNzd29yZC5cbiAgICA8L3NtYWxsPlxuICA8L2Rpdj5cbiAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8bGFiZWwgW2F0dHIuZm9yXT1cImZvcm1JZCArICduYW1lJ1wiPllvdXIgTmFtZTwvbGFiZWw+XG4gICAgPGlucHV0XG4gICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAnbmFtZSdcIlxuICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgZm9ybUNvbnRyb2xOYW1lPVwibmFtZVwiXG4gICAgICBwbGFjZWhvbGRlcj1cIllvdXIgTmFtZVwiXG4gICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICBbY2xhc3MuaXMtaW52YWxpZF09XCJuYW1lRmMudG91Y2hlZCAmJiBuYW1lRmMuaW52YWxpZFwiPlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cIm5hbWVGYy50b3VjaGVkICYmIG5hbWVGYy5oYXNFcnJvcigncmVxdWlyZWQnKVwiPlxuICAgICAgUmVxdWlyZWQuXG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrXCI+XG4gICAgICA8aW5wdXRcbiAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCJcbiAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgW3ZhbHVlXT1cInRydWVcIlxuICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZW1lbWJlclwiXG4gICAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWxcIiBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgICBSZW1lbWJlciBtZSBvbiB0aGlzIGRldmljZS5cbiAgICAgIDwvbGFiZWw+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxidXR0b24gdHlwZT1cInN1Ym1pdFwiXG4gICAgICBjbGFzcz1cImJ0biBidG4tc3VjY2VzcyBidG4tYmxvY2tcIlxuICAgICAgW2Rpc2FibGVkXT1cImZnLmludmFsaWQgfHwgc3VibWl0dGluZ1wiPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtbG9jayBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIENyZWF0ZSBBY2NvdW50XG4gICAgPC9idXR0b24+XG4gIDwvZGl2PlxuPC9mb3JtPlxuYCxcbiAgc3R5bGVzOiBbYGBdLFxuICBhbmltYXRpb25zOiBbIGZhZGVJbk91dEFuaW1hdGlvbiBdXG59KVxuZXhwb3J0IGNsYXNzIFNpZ25VcEZvcm1Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQge1xuXG4gIEBWaWV3Q2hpbGQoJ3Bhc3N3b3JkSW5wdXQnKSBwYXNzd29yZElucHV0OiBFbGVtZW50UmVmO1xuICBASW5wdXQoKSBlbWFpbDogc3RyaW5nO1xuICBASW5wdXQoKSByZW1lbWJlcjogYm9vbGVhbjtcbiAgQE91dHB1dCgpIHJlbWVtYmVyQ2hhbmdlOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBzdWNjZXNzOiBFdmVudEVtaXR0ZXI8YXV0aC5Vc2VyQ3JlZGVudGlhbD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBlcnJvcjogRXZlbnRFbWl0dGVyPGF1dGguRXJyb3I+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIGZvcm1JZCA9ICduZ3gtZmlyZWJhc2UtYXV0aC1zaWduLXVwLWZvcm0tJztcbiAgc3VibWl0dGluZyA9IGZhbHNlO1xuICBmZzogRm9ybUdyb3VwO1xuICBlbWFpbEZjOiBGb3JtQ29udHJvbDtcbiAgcGFzc3dvcmRGYzogRm9ybUNvbnRyb2w7XG4gIG5hbWVGYzogRm9ybUNvbnRyb2w7XG4gIHJlbWVtYmVyRmM6IEZvcm1Db250cm9sO1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgICBwcml2YXRlIF9hdXRoU2VydmljZTogTmd4RmlyZWJhc2VBdXRoU2VydmljZVxuICApIHsgfVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG5cbiAgZ2V0IGF1dGhTZXJ2aWNlKCk6IE5neEZpcmViYXNlQXV0aFNlcnZpY2Uge1xuICAgIHJldHVybiB0aGlzLl9hdXRoU2VydmljZTtcbiAgfVxuXG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5lbWFpbEZjID0gbmV3IEZvcm1Db250cm9sKFxuICAgICAgdGhpcy5lbWFpbCxcbiAgICAgIHt2YWxpZGF0b3JzOiBbVmFsaWRhdG9ycy5yZXF1aXJlZCwgVmFsaWRhdG9ycy5lbWFpbF19XG4gICAgKTtcbiAgICB0aGlzLnBhc3N3b3JkRmMgPSBuZXcgRm9ybUNvbnRyb2woJycsIHt2YWxpZGF0b3JzOiBbVmFsaWRhdG9ycy5yZXF1aXJlZF19KTtcbiAgICB0aGlzLm5hbWVGYyA9IG5ldyBGb3JtQ29udHJvbCgnJywge3ZhbGlkYXRvcnM6IFtWYWxpZGF0b3JzLnJlcXVpcmVkLCBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyLnJlcXVpcmVkTm9uRW1wdHldfSk7XG4gICAgdGhpcy5yZW1lbWJlckZjID0gbmV3IEZvcm1Db250cm9sKHRoaXMucmVtZW1iZXIpO1xuICAgIHRoaXMucmVtZW1iZXJGYy52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKHZhbCA9PiB0aGlzLnJlbWVtYmVyQ2hhbmdlLmVtaXQodmFsKSk7XG4gICAgdGhpcy5mZyA9IG5ldyBGb3JtR3JvdXAoe1xuICAgICAgZW1haWw6IHRoaXMuZW1haWxGYyxcbiAgICAgIHBhc3N3b3JkOiB0aGlzLnBhc3N3b3JkRmMsXG4gICAgICBuYW1lOiB0aGlzLm5hbWVGYyxcbiAgICAgIHJlbWVtYmVyOiB0aGlzLnJlbWVtYmVyRmNcbiAgICB9KTtcbiAgfVxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgdGhpcy5wYXNzd29yZElucHV0Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgfVxuXG4gIHN1Ym1pdCgpIHtcblxuICAgIHRoaXMuc3VibWl0dGluZyA9IHRydWU7XG4gICAgbGV0IGNyZWQ6IGF1dGguVXNlckNyZWRlbnRpYWw7XG4gICAgdGhpcy5hdXRoLmZldGNoU2lnbkluTWV0aG9kc0ZvckVtYWlsKHRoaXMuZW1haWwpXG4gICAgICAudGhlbigocmVzdWx0cykgPT4ge1xuICAgICAgICBpZiAocmVzdWx0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHtcbiAgICAgICAgICAgIGNvZGU6ICduZ3gtZmlyZWJhc2UtYXV0aC9hY2NvdW50LWV4aXN0cydcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5hdXRoLmNyZWF0ZVVzZXJXaXRoRW1haWxBbmRQYXNzd29yZCh0aGlzLmVtYWlsLCB0aGlzLnBhc3N3b3JkRmMudmFsdWUpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKHJlc3VsdCA9PiB7XG4gICAgICAgIGNyZWQgPSByZXN1bHQ7XG4gICAgICAgIHJldHVybiBjcmVkLnVzZXIudXBkYXRlUHJvZmlsZSh7ZGlzcGxheU5hbWU6IHRoaXMubmFtZUZjLnZhbHVlLnRyaW0oKSwgcGhvdG9VUkw6IG51bGx9KTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmF1dGhTZXJ2aWNlLnNldFJlbWVtYmVyZWQodGhpcy5yZW1lbWJlckZjLnZhbHVlID09PSB0cnVlLCB0aGlzLmVtYWlsKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMuc3VjY2Vzcy5lbWl0KGNyZWQpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIHRoaXMuc3VibWl0dGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmVtYWlsRmMubWFya0FzRGlydHkoKTtcbiAgICAgICAgdGhpcy5lbWFpbEZjLm1hcmtBc1RvdWNoZWQoKTtcbiAgICAgICAgdGhpcy5wYXNzd29yZEZjLm1hcmtBc0RpcnR5KCk7XG4gICAgICAgIHRoaXMucGFzc3dvcmRGYy5tYXJrQXNUb3VjaGVkKCk7XG4gICAgICAgIHN3aXRjaCAoZXJyb3IuY29kZSkge1xuICAgICAgICAgIGNhc2UgJ2F1dGgvaW52YWxpZC1lbWFpbCc6XG4gICAgICAgICAgY2FzZSAnbmd4LWZpcmViYXNlLWF1dGgvYWNjb3VudC1leGlzdHMnOlxuICAgICAgICAgICAgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlci5zZXRFcnJvclVudGlsQ2hhbmdlZCh0aGlzLmVtYWlsRmMsIGVycm9yLmNvZGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnYXV0aC93ZWFrLXBhc3N3b3JkJzpcbiAgICAgICAgICAgIE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIuc2V0RXJyb3JVbnRpbENoYW5nZWQodGhpcy5wYXNzd29yZEZjLCBlcnJvci5jb2RlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0aGlzLmVycm9yLmVtaXQoZXJyb3IpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBBZnRlclZpZXdJbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIFZpZXdDaGlsZCwgRWxlbWVudFJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IGF1dGggfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlciB9IGZyb20gJy4uLy4uL2Zvcm0taGVscGVyJztcbmltcG9ydCB7IGZhZGVJbk91dEFuaW1hdGlvbiB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLXJlc2V0LXBhc3N3b3JkLXNlbmQtZm9ybScsXG4gIHRlbXBsYXRlOiBgPGZvcm0gW2Zvcm1Hcm91cF09XCJmZ1wiIChuZ1N1Ym1pdCk9XCJzdWJtaXQoKVwiPlxuICA8ZGl2ICpuZ0lmPVwic2VudFwiIFtAZmFkZUluT3V0XT1cIidpbidcIj5cbiAgICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc3VjY2Vzc1wiPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtY2hlY2sgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICBXZcOiwoDCmXZlIHNlbnQgYSByZXNldCBwYXNzd29yZCBsaW5rIHRvIHt7c2VudH19LlxuICAgICAgUGxlYXNlIGFsbG93IGEgZmV3IG1vbWVudHMgZm9yIHRoZSBlbWFpbCB0byBhcnJpdmUuXG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuXG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGxhYmVsIFthdHRyLmZvcl09XCJmb3JtSWQgKyAnZW1haWwnXCI+RW1haWwgQWRkcmVzczwvbGFiZWw+XG4gICAgPGlucHV0XG4gICAgICAjZW1haWxJbnB1dFxuICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiXG4gICAgICBbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XT1cImZvcm1JZCArICdlbWFpbC1oZWxwJ1wiXG4gICAgICB0eXBlPVwiZW1haWxcIlxuICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiZW1haWxcIlxuICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwiZW1haWxGYy50b3VjaGVkICYmIGVtYWlsRmMuaW52YWxpZFwiPlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMudG91Y2hlZCAmJiBlbWFpbEZjLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCI+XG4gICAgICBSZXF1aXJlZC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLnRvdWNoZWQgJiYgZW1haWxGYy5oYXNFcnJvcignYXV0aC91c2VyLW5vdC1mb3VuZCcpXCI+XG4gICAgICBXZSBjb3VsZCBub3QgZmluZCBhbiBhY2NvdW50IHdpdGggdGhhdCBlbWFpbCBhZGRyZXNzLlxuICAgICAgUGxlYXNlIDxhIHJvdXRlckxpbms9XCIuXCIgW3F1ZXJ5UGFyYW1zXT1cInthY3Rpb246ICdzaWduSVVwUGFzc3dvcmQnfVwiPnNpZ24gdXA8L2E+LlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMudG91Y2hlZCAmJiBlbWFpbEZjLmhhc0Vycm9yKCdlbWFpbCcpXCI+XG4gICAgICBJbnZhbGlkIGVtYWlsLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMudG91Y2hlZCAmJiBlbWFpbEZjLmhhc0Vycm9yKCdhdXRoL2ludmFsaWQtZW1haWwnKVwiPlxuICAgICAgSW52YWxpZCBlbWFpbC5cbiAgICA8L2Rpdj5cbiAgICA8c21hbGwgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsLWhlbHAnXCIgY2xhc3M9XCJmb3JtLXRleHQgdGV4dC1tdXRlZFwiPlxuICAgICAgRW50ZXIgdGhlIGVtYWlsIGFkZHJlc3MgeW91IHVzZWQgdG8gc2lnbiB1cC4gV2XDosKAwplsbFxuICAgICAgc2VuZCBhIHJlc2V0IHBhc3N3b3JkIGxpbmsgdG8gdGhhdCBhZGRyZXNzLlxuICAgIDwvc21hbGw+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxidXR0b24gdHlwZT1cInN1Ym1pdFwiXG4gICAgICBjbGFzcz1cImJ0biBidG4tYmxvY2sgYnRuLXN1Y2Nlc3NcIlxuICAgICAgW2Rpc2FibGVkXT1cImZnLmludmFsaWQgfHwgc3VibWl0dGluZ1wiPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtZncgZmEtZW52ZWxvcGVcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICBTZW5kIExpbmtcbiAgICA8L2J1dHRvbj5cbiAgPC9kaXY+XG48L2Zvcm0+XG5gLFxuICBzdHlsZXM6IFtgYF0sXG4gIGFuaW1hdGlvbnM6IFtmYWRlSW5PdXRBbmltYXRpb25dXG59KVxuZXhwb3J0IGNsYXNzIFJlc2V0UGFzc3dvcmRTZW5kRm9ybUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XG5cbiAgQFZpZXdDaGlsZCgnZW1haWxJbnB1dCcpIGVtYWlsSW5wdXQ6IEVsZW1lbnRSZWY7XG4gIEBJbnB1dCgpIGVtYWlsOiBzdHJpbmc7XG4gIEBPdXRwdXQoKSBlbWFpbENoYW5nZTogRXZlbnRFbWl0dGVyPHN0cmluZz4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBlcnJvcjogRXZlbnRFbWl0dGVyPGF1dGguRXJyb3I+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIGZvcm1JZCA9ICduZ3gtZmlyZWJhc2UtYXV0aC1yZXNldC1wYXNzd29yZC1zZW5kLWZvcm0tJztcbiAgZmc6IEZvcm1Hcm91cDtcbiAgZW1haWxGYzogRm9ybUNvbnRyb2w7XG4gIHN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgc2VudDogc3RyaW5nID0gbnVsbDtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICkgeyB9XG5cbiAgZ2V0IGF1dGgoKTogYXV0aC5BdXRoIHtcbiAgICByZXR1cm4gdGhpcy5fYWZBdXRoLmF1dGg7XG4gIH1cblxuXG5cblxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuZW1haWxGYyA9IG5ldyBGb3JtQ29udHJvbChcbiAgICAgIHRoaXMuZW1haWwsXG4gICAgICB7dmFsaWRhdG9yczogW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMuZW1haWxdfVxuICAgICk7XG4gICAgdGhpcy5lbWFpbEZjLnZhbHVlQ2hhbmdlcy5zdWJzY3JpYmUoKCkgPT4gdGhpcy5lbWFpbENoYW5nZS5lbWl0KHRoaXMuZW1haWxGYy52YWx1ZS50cmltKCkpKTtcbiAgICB0aGlzLmZnID0gbmV3IEZvcm1Hcm91cCh7ZW1haWw6IHRoaXMuZW1haWxGY30pO1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIHRoaXMuZW1haWxJbnB1dC5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gIH1cblxuXG4gIHN1Ym1pdCgpIHtcbiAgICBjb25zdCBlbWFpbCA9IHRoaXMuZW1haWxGYy52YWx1ZS50cmltKCk7XG4gICAgdGhpcy5zdWJtaXR0aW5nID0gdHJ1ZTtcbiAgICB0aGlzLnNlbnQgPSBudWxsO1xuICAgIHRoaXMuYXV0aC5zZW5kUGFzc3dvcmRSZXNldEVtYWlsKGVtYWlsKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLnN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5zZW50ID0gZW1haWw7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcjogYXV0aC5FcnJvcikgPT4ge1xuICAgICAgICB0aGlzLnN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5lbWFpbEZjLm1hcmtBc1RvdWNoZWQoKTtcbiAgICAgICAgdGhpcy5lbWFpbEZjLm1hcmtBc0RpcnR5KCk7XG4gICAgICAgIHN3aXRjaCAoZXJyb3IuY29kZSkge1xuICAgICAgICAgIGNhc2UgJ2F1dGgvaW52YWxpZC1lbWFpbCc6XG4gICAgICAgICAgY2FzZSAnYXV0aC91c2VyLW5vdC1mb3VuZCc6XG4gICAgICAgICAgICBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyLnNldEVycm9yVW50aWxDaGFuZ2VkKHRoaXMuZW1haWxGYywgZXJyb3IuY29kZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhpcy5lcnJvci5lbWl0KGVycm9yKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuXG4gIH1cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlLCBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgYXV0aCB9IGZyb20gJ2ZpcmViYXNlL2FwcCc7XG5pbXBvcnQgeyBGb3JtR3JvdXAsIEZvcm1Db250cm9sIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBnZXRPQXV0aFByb3ZpZGVySWNvbiwgZ2V0T0F1dGhQcm92aWRlck5hbWUgfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoU2VydmljZSB9IGZyb20gJy4uLy4uL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UnO1xuaW1wb3J0IHsgc2NyZWVuQW5pbWF0aW9uIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcblxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW9hdXRoJyxcbiAgdGVtcGxhdGU6IGA8ZGl2ICpuZ0lmPVwiJ3dhaXQnID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1zZWNvbmRhcnlcIj5cbiAgICA8aSBjbGFzcz1cImZhcyBmYS1zcGluIGZhLXNwaW5uZXIgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgUGxlYXNlIHdhaXQuLi5cbiAgPC9kaXY+XG48L2Rpdj5cblxuPGRpdiAqbmdJZj1cIidtZXRob2RFcnJvcicgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWRhbmdlclwiPlxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFdlIGNvdWxkIG5vdCBzaWduIHlvdSBpbiB3aXRoIHt7bWV0aG9kRXJyb3IuY3JlZGVudGlhbC5wcm92aWRlcklkfX0uXG4gIDwvZGl2PlxuXG4gIDxwIGNsYXNzPVwidGV4dC1tdXRlZFwiPlxuICAgIFBsZWFzZSBzaWduIGluIHdpdGggb25lIG9mIHRoZSBtZXRob2RzIGFzc29jaWF0ZWQgd2l0aFxuICAgIHt7bWV0aG9kRXJyb3IuZW1haWx9fTpcbiAgPC9wPlxuXG4gIDxkaXYgY2xhc3M9XCJsaXN0LWdyb3VwXCI+XG4gICAgPGFcbiAgICAgICpuZ0lmPVwibWV0aG9kRXJyb3IuYWNjb3VudEhhc1Bhc3N3b3JkXCJcbiAgICAgIHJvdXRlckxpbms9XCIuXCJcbiAgICAgIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluUGFzc3dvcmQnfVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBjbGFzcz1cImZhcyBmYS11bmxvY2tcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICA8c3BhbiBjbGFzcz1cIm1sLTJcIj5TaWduIEluIHdpdGggWW91ciBQYXNzd29yZDwvc3Bhbj5cbiAgICA8L2E+XG4gICAgPGJ1dHRvblxuICAgICAgKm5nRm9yPVwibGV0IGlkIG9mIG1ldGhvZEVycm9yLmFjY291bnRPQXV0aE1ldGhvZHNcIlxuICAgICAgKGNsaWNrKT1cIm9BdXRoU2lnbkluKGlkKVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBbYXR0ci5jbGFzc109XCJnZXRPQXV0aFByb3ZpZGVySWNvbihpZClcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICA8c3BhbiBjbGFzcz1cIm1sLTJcIj5TaWduIEluIHdpdGgge3tnZXRPQXV0aFByb3ZpZGVyTmFtZShpZCl9fTwvc3Bhbj5cbiAgICA8L2J1dHRvbj5cbiAgPC9kaXY+XG5cbiAgPGZvcm0gW2Zvcm1Hcm91cF09XCJmZ1wiPlxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1jaGVja1wiPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIlxuICAgICAgICAgIHR5cGU9XCJjaGVja2JveFwiXG4gICAgICAgICAgW3ZhbHVlXT1cInRydWVcIlxuICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInJlbWVtYmVyXCJcbiAgICAgICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAncmVtZW1iZXInXCI+XG4gICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWxcIiBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgICAgIFJlbWVtYmVyIG1lIG9uIHRoaXMgZGV2aWNlLlxuICAgICAgICA8L2xhYmVsPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZm9ybT5cblxuICA8cCBjbGFzcz1cInRleHQtbXV0ZWRcIj5cbiAgICBJcyB7e21ldGhvZEVycm9yLmVtYWlsfX0gbm90IHlvdXIgZW1haWwgYWRkcmVzcz9cbiAgICA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluJ31cIj5TdGFydCBPdmVyPC9hPlxuICA8L3A+XG5cbjwvZGl2PlxuXG48ZGl2ICpuZ0lmPVwiJ3JldHJ5JyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtZGFuZ2VyXCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGUgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgSXQgbG9va3MgbGlrZSB5b3UgY2FuY2VsbGVkIHNpZ25pbmcgaW4gd2l0aFxuICAgIHt7Z2V0T0F1dGhQcm92aWRlck5hbWUocHJvdmlkZXJJZCl9fS4gVHJ5IGFnYWluOlxuICA8L2Rpdj5cblxuICA8ZGl2IGNsYXNzPVwibGlzdC1ncm91cFwiPlxuICAgIDxidXR0b25cbiAgICAgIChjbGljayk9XCJvQXV0aFNpZ25Jbihwcm92aWRlcklkKVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBbYXR0ci5jbGFzc109XCJnZXRPQXV0aFByb3ZpZGVySWNvbihwcm92aWRlcklkKVwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIDxzcGFuIGNsYXNzPVwibWwtMlwiPlNpZ24gSW4gd2l0aCB7e2dldE9BdXRoUHJvdmlkZXJOYW1lKHByb3ZpZGVySWQpfX08L3NwYW4+XG4gICAgPC9idXR0b24+XG4gIDwvZGl2PlxuXG4gIDxmb3JtIFtmb3JtR3JvdXBdPVwiZmdcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2tcIj5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCJcbiAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAgIFt2YWx1ZV09XCJ0cnVlXCJcbiAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZW1lbWJlclwiXG4gICAgICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWNoZWNrLWxhYmVsXCIgW2F0dHIuZm9yXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgICAgICBSZW1lbWJlciBtZSBvbiB0aGlzIGRldmljZS5cbiAgICAgICAgPC9sYWJlbD5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L2Zvcm0+XG5cblxuICA8cCBjbGFzcz1cInRleHQtbXV0ZWRcIj5cbiAgICA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluJ31cIj5TdGFydCBPdmVyPC9hPlxuICA8L3A+XG5cbjwvZGl2PlxuYCxcbiAgc3R5bGVzOiBbYGBdLFxuICBhbmltYXRpb25zOiBbIHNjcmVlbkFuaW1hdGlvbiBdXG59KVxuZXhwb3J0IGNsYXNzIFNpZ25Jbk9hdXRoQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBASW5wdXQoKSBwcm92aWRlcklkOiBzdHJpbmc7XG4gIEBJbnB1dCgpIGluaXRpYWxFcnJvcjogYXV0aC5FcnJvcjtcbiAgQElucHV0KCkgdXNlT0F1dGhQb3B1cDogYm9vbGVhbjtcbiAgQElucHV0KCkgb0F1dGhQcm92aWRlckZhY3Rvcnk6IChwcm92aWRlcklkOiBzdHJpbmcpID0+IGF1dGguQXV0aFByb3ZpZGVyO1xuICBASW5wdXQoKSBlbWFpbDogc3RyaW5nO1xuICBASW5wdXQoKSByZW1lbWJlcjogYm9vbGVhbjtcbiAgQE91dHB1dCgpIHN1Y2Nlc3M6IEV2ZW50RW1pdHRlcjxhdXRoLlVzZXJDcmVkZW50aWFsPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIGVtYWlsQ2hhbmdlOiBFdmVudEVtaXR0ZXI8c3RyaW5nPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHJlbWVtYmVyQ2hhbmdlOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBlcnJvcjogRXZlbnRFbWl0dGVyPGF1dGguRXJyb3I+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG5cbiAgc2NyZWVuOiAnd2FpdCcgfCAnbWV0aG9kRXJyb3InIHwgJ3JldHJ5JyA9ICd3YWl0JztcbiAgbWV0aG9kRXJyb3I6IGF1dGguRXJyb3J8YW55ID0gbnVsbDtcbiAgZ2V0T0F1dGhQcm92aWRlckljb24gPSBnZXRPQXV0aFByb3ZpZGVySWNvbjtcbiAgZ2V0T0F1dGhQcm92aWRlck5hbWUgPSBnZXRPQXV0aFByb3ZpZGVyTmFtZTtcbiAgZmc6IEZvcm1Hcm91cDtcbiAgcmVtZW1iZXJGYzogRm9ybUNvbnRyb2w7XG4gIGZvcm1JZCA9ICduZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW9hdXRoLSc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICAgcHJpdmF0ZSBfc3ZjOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlLFxuICAgIHByaXZhdGUgX3JvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgICBwcml2YXRlIF9yb3V0ZXI6IFJvdXRlclxuICApIHsgfVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG5cbiAgZ2V0IGF1dGhTZXJ2aWNlKCk6IE5neEZpcmViYXNlQXV0aFNlcnZpY2Uge1xuICAgIHJldHVybiB0aGlzLl9zdmM7XG4gIH1cblxuICBnZXQgcm91dGUoKTogQWN0aXZhdGVkUm91dGUge1xuICAgIHJldHVybiB0aGlzLl9yb3V0ZTtcbiAgfVxuXG4gIGdldCByb3V0ZXIoKTogUm91dGVyIHtcbiAgICByZXR1cm4gdGhpcy5fcm91dGVyO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5yZW1lbWJlckZjID0gbmV3IEZvcm1Db250cm9sKHRoaXMucmVtZW1iZXIpO1xuICAgIHRoaXMucmVtZW1iZXJGYy52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKHZhbCA9PiB0aGlzLnJlbWVtYmVyQ2hhbmdlLmVtaXQodmFsKSk7XG4gICAgdGhpcy5mZyA9IG5ldyBGb3JtR3JvdXAoe1xuICAgICAgcmVtZW1iZXI6IHRoaXMucmVtZW1iZXJGY1xuICAgIH0pO1xuICAgIGlmICh0aGlzLmluaXRpYWxFcnJvcikge1xuICAgICAgdGhpcy5oYW5kbGVPQXV0aEVycm9yKHRoaXMuaW5pdGlhbEVycm9yKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5vQXV0aFNpZ25Jbih0aGlzLnByb3ZpZGVySWQpO1xuICAgIH1cbiAgfVxuXG5cbiAgb0F1dGhTaWduSW4oaWQ6IHN0cmluZywgZm9yY2VSZWRpcmVjdD86IGJvb2xlYW4pIHtcbiAgICB0aGlzLm1ldGhvZEVycm9yID0gbnVsbDtcbiAgICBsZXQgY3JlZDogYXV0aC5Vc2VyQ3JlZGVudGlhbDtcbiAgICBpZiAodGhpcy51c2VPQXV0aFBvcHVwICAmJiBmb3JjZVJlZGlyZWN0ICE9PSB0cnVlKSB7XG4gICAgICB0aGlzLmdldE9BdXRoUHJvdmlkZXIoaWQpXG4gICAgICAgIC50aGVuKHByb3ZpZGVyID0+IHtcbiAgICAgICAgICByZXR1cm4gdGhpcy5hdXRoLnNpZ25JbldpdGhQb3B1cChwcm92aWRlcik7XG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKChyZXN1bHQ6IGF1dGguVXNlckNyZWRlbnRpYWwpID0+IHtcbiAgICAgICAgICBjcmVkID0gcmVzdWx0O1xuICAgICAgICAgIHJldHVybiB0aGlzLmF1dGhTZXJ2aWNlLnNldFJlbWVtYmVyZWQodGhpcy5yZW1lbWJlckZjLnZhbHVlID09PSB0cnVlLCByZXN1bHQudXNlci5lbWFpbCk7XG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICB0aGlzLnN1Y2Nlc3MuZW1pdChjcmVkKTtcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHRoaXMuaGFuZGxlT0F1dGhFcnJvcihlcnJvciwgaWQpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoWycuJ10sIHtyZWxhdGl2ZVRvOiB0aGlzLnJvdXRlLCBxdWVyeVBhcmFtczoge3JlbWVtYmVyOiB0aGlzLnJlbWVtYmVyRmMudmFsdWUgPT09IHRydWV9fSlcbiAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHJldHVybiB0aGlzLmdldE9BdXRoUHJvdmlkZXIoaWQpO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbihwcm92aWRlciA9PiB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuYXV0aC5zaWduSW5XaXRoUmVkaXJlY3QocHJvdmlkZXIpO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4gdGhpcy5oYW5kbGVPQXV0aEVycm9yKGVycm9yLCBpZCkpO1xuICAgIH1cbiAgfVxuXG4gIGhhbmRsZU9BdXRoRXJyb3IoZXJyb3I6IGF1dGguRXJyb3IsIHByb3ZpZGVySWQ/OiBzdHJpbmcpIHtcbiAgICBpZiAoZXJyb3JbJ2VtYWlsJ10gJiYgZXJyb3JbJ2NyZWRlbnRpYWwnXSkge1xuICAgICAgdGhpcy5lbWFpbENoYW5nZS5lbWl0KGVycm9yWydlbWFpbCddKTtcbiAgICAgIHRoaXMuYXV0aC5mZXRjaFNpZ25Jbk1ldGhvZHNGb3JFbWFpbChlcnJvclsnZW1haWwnXSlcbiAgICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgICAgZXJyb3JbJ21ldGhvZHMnXSA9IHJlc3VsdHM7XG4gICAgICAgICAgZXJyb3JbJ2FjY291bnRIYXNQYXNzd29yZCddID0gcmVzdWx0cy5pbmRleE9mKCdwYXNzd29yZCcpICE9PSAtMTtcbiAgICAgICAgICBlcnJvclsnYWNjb3VudE9BdXRoTWV0aG9kcyddID0gcmVzdWx0cy5maWx0ZXIoaWQgPT4gaWQgIT09ICdwYXNzd29yZCcpO1xuICAgICAgICAgIHRoaXMubWV0aG9kRXJyb3IgPSBlcnJvcjtcbiAgICAgICAgICB0aGlzLnNjcmVlbiA9ICdtZXRob2RFcnJvcic7XG4gICAgICAgIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBzd2l0Y2ggKGVycm9yLmNvZGUpIHtcbiAgICAgIGNhc2UgJ2F1dGgvY2FuY2VsbGVkLXBvcHVwLXJlcXVlc3QnOlxuICAgICAgY2FzZSAnYXV0aC9wb3B1cC1jbG9zZWQtYnktdXNlcic6XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ3JldHJ5JztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdhdXRoL3BvcHVwLWJsb2NrZWQnOlxuICAgICAgICB0aGlzLm9BdXRoU2lnbkluKHByb3ZpZGVySWQsIHRydWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRoaXMuZXJyb3IuZW1pdChlcnJvcik7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIGdldE9BdXRoUHJvdmlkZXIoaWQ6IHN0cmluZyk6IFByb21pc2U8YXV0aC5BdXRoUHJvdmlkZXI+IHtcbiAgICBsZXQgcHJvdmlkZXI6IGF1dGguQXV0aFByb3ZpZGVyID0gbnVsbDtcbiAgICBpZiAodGhpcy5vQXV0aFByb3ZpZGVyRmFjdG9yeSkge1xuICAgICAgcHJvdmlkZXIgPSB0aGlzLm9BdXRoUHJvdmlkZXJGYWN0b3J5KGlkKTtcbiAgICB9XG4gICAgaWYgKCEgcHJvdmlkZXIpIHtcbiAgICAgIHN3aXRjaCAoaWQpIHtcbiAgICAgICAgY2FzZSAndHdpdHRlci5jb20nOlxuICAgICAgICAgIHByb3ZpZGVyID0gbmV3IGF1dGguVHdpdHRlckF1dGhQcm92aWRlcigpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdmYWNlYm9vay5jb20nOlxuICAgICAgICAgIHByb3ZpZGVyID0gbmV3IGF1dGguRmFjZWJvb2tBdXRoUHJvdmlkZXIoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnZ29vZ2xlLmNvbSc6XG4gICAgICAgICAgcHJvdmlkZXIgPSBuZXcgYXV0aC5Hb29nbGVBdXRoUHJvdmlkZXIoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnZ2l0aHViLmNvbSc6XG4gICAgICAgICAgcHJvdmlkZXIgPSBuZXcgYXV0aC5HaXRodWJBdXRoUHJvdmlkZXIoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHByb3ZpZGVyKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHByb3ZpZGVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHtcbiAgICAgICAgY29kZTogJ25neC1maXJlYmFzZS1hdXRoL25vLXByb3ZpZGVyLWZvdW5kJyxcbiAgICAgICAgbWVzc2FnZTogYFdlIGNvdWxkIG5vdCBjcmVhdGUgYW4gT0F1dGggcHJvdmlkZXIgZm9yIHByb3ZpZGVyIGlkIFwiJHtpZH1cIi5gXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxufVxuIiwiaW1wb3J0IHsgTmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIH0gZnJvbSAnLi9uZ3gtZmlyZWJhc2UtYXV0aC5zZXJ2aWNlJztcblxuXG5cblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZVxuICBdLFxuICBwcm92aWRlcnM6IFtcbiAgICBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgTmd4RmlyZWJhc2VBdXRoTW9kdWxlIHsgfVxuIiwiaW1wb3J0IHsgTmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBSb3V0ZXJNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgUmVhY3RpdmVGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IFNpZ25JbkNvbXBvbmVudCB9IGZyb20gJy4vc2lnbi1pbi5jb21wb25lbnQnO1xuaW1wb3J0IHsgU2lnbkluTWV0aG9kc0Zvcm1Db21wb25lbnQgfSBmcm9tICcuL3NpZ24taW4tbWV0aG9kcy1mb3JtL3NpZ24taW4tbWV0aG9kcy1mb3JtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBTaWduSW5Gb3JtQ29tcG9uZW50IH0gZnJvbSAnLi9zaWduLWluLWZvcm0vc2lnbi1pbi1mb3JtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBTaWduVXBGb3JtQ29tcG9uZW50IH0gZnJvbSAnLi9zaWduLXVwLWZvcm0vc2lnbi11cC1mb3JtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBSZXNldFBhc3N3b3JkU2VuZEZvcm1Db21wb25lbnQgfSBmcm9tICcuL3Jlc2V0LXBhc3N3b3JkLXNlbmQtZm9ybS9yZXNldC1wYXNzd29yZC1zZW5kLWZvcm0uY29tcG9uZW50JztcbmltcG9ydCB7IFNpZ25Jbk9hdXRoQ29tcG9uZW50IH0gZnJvbSAnLi9zaWduLWluLW9hdXRoL3NpZ24taW4tb2F1dGguY29tcG9uZW50JztcblxuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoTW9kdWxlIH0gZnJvbSAnLi4vbmd4LWZpcmViYXNlLWF1dGgubW9kdWxlJztcblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZSxcbiAgICBSZWFjdGl2ZUZvcm1zTW9kdWxlLFxuICAgIFJvdXRlck1vZHVsZSxcbiAgICBOZ3hGaXJlYmFzZUF1dGhNb2R1bGVcbiAgXSxcbiAgZGVjbGFyYXRpb25zOiBbXG4gICAgU2lnbkluQ29tcG9uZW50LFxuICAgIFNpZ25Jbk1ldGhvZHNGb3JtQ29tcG9uZW50LFxuICAgIFNpZ25JbkZvcm1Db21wb25lbnQsXG4gICAgU2lnblVwRm9ybUNvbXBvbmVudCxcbiAgICBSZXNldFBhc3N3b3JkU2VuZEZvcm1Db21wb25lbnQsXG4gICAgU2lnbkluT2F1dGhDb21wb25lbnQsXG4gIF0sXG4gIGV4cG9ydHM6IFtcbiAgICBTaWduSW5Db21wb25lbnQsXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgTmd4RmlyZWJhc2VBdXRoU2lnbkluTW9kdWxlIHsgfVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUdyb3VwLCBGb3JtQ29udHJvbCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IGF1dGgsIFVzZXIgfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgSU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3MgfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlciB9IGZyb20gJy4uLy4uL2Zvcm0taGVscGVyJztcbmltcG9ydCB7IE5neEZpcmViYXNlQXV0aFNlcnZpY2UgfSBmcm9tICcuLi8uLi9uZ3gtZmlyZWJhc2UtYXV0aC5zZXJ2aWNlJztcbmltcG9ydCB7IHNjcmVlbkFuaW1hdGlvbiB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLW9vYi1yZXNldC1wYXNzd29yZCcsXG4gIHRlbXBsYXRlOiBgPGRpdiAqbmdJZj1cIid3YWl0JyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc2Vjb25kYXJ5XCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtc3BpbiBmYS1zcGlubmVyIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFBsZWFzZSB3YWl0Li4uXG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCInc3VjY2VzcycgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXN1Y2Nlc3NcIj5cbiAgICA8aSBjbGFzcz1cImZhcyBmYS1jaGVjayBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICBXZWxjb21lLCB7e2NyZWQudXNlci5kaXNwbGF5TmFtZX19IVxuICAgIFlvdXIgbmV3IHBhc3N3b3JkIGhhcyBiZWVuIHNhdmVkIGFuZCB5b3UgYXJlIHNpZ25lZCBpbi5cbiAgPC9kaXY+XG48L2Rpdj5cblxuPGRpdiAqbmdJZj1cInNjcmVlbiA9PT0gJ2Vycm9yJ1wiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWRhbmdlclwiPlxuICAgIDxwPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGUgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICBXb29wcyEgQW4gZXJyb3Igb2NjdXJyZWQuXG4gICAgPC9wPlxuICAgIDxkaXYgW25nU3dpdGNoXT1cInVuaGFuZGxlZEVycm9yLmNvZGVcIj5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC9leHBpcmVkLWFjdGlvbi1jb2RlJ1wiPlxuICAgICAgICBUaGUgcmVzZXQgcGFzc3dvcmQgbGluayB5b3UgdXNlZCBoYXMgZXhwaXJlZC5cbiAgICAgIDwvcD5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC9pbnZhbGlkLWFjdGlvbi1jb2RlJ1wiPlxuICAgICAgICBUaGUgcmVzZXQgcGFzc3dvcmQgbGluayB5b3UgdXNlZCBpcyBub3QgdmFsaWQuIFRoaXMgbWF5IGJlIGJlY2F1c2UgaXRcbiAgICAgICAgaGFzIGFscmVhZHkgYmVlbiB1c2VkLlxuICAgICAgPC9wPlxuICAgICAgPHAgY2xhc3M9XCJtYi0wXCIgKm5nU3dpdGNoQ2FzZT1cIidhdXRoL3VzZXItZGlzYWJsZWQnXCI+XG4gICAgICAgIFRoZSBhY2NvdW50IGFzc29jaWF0ZWQgd2l0aCB0aGUgcmVzZXQgcGFzc3dvcmQgbGluayB5b3UgdXNlZCBoYXMgYmVlbiBkaXNhYmxlZC5cbiAgICAgIDwvcD5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC91c2VyLW5vdC1mb3VuZCdcIj5cbiAgICAgICAgVGhlIGFjY291bnQgYXNzb2NpYXRlZCB3aXRoIHRoZSByZXNldCBwYXNzd29yZCBsaW5rIHlvdSB1c2VkIGhhcyBiZWVuIHJlbW92ZWQuXG4gICAgICA8L3A+XG4gICAgICA8ZGl2ICpuZ1N3aXRjaERlZmF1bHQ+XG4gICAgICAgIDxwPkNvZGU6IHt7dW5oYW5kbGVkRXJyb3IuY29kZX19PC9wPlxuICAgICAgICA8cCBjbGFzcz1cIm1iLTBcIj5cbiAgICAgICAgICBNZXNzYWdlOiB7e3VuaGFuZGxlZEVycm9yLm1lc3NhZ2V9fVxuICAgICAgICA8L3A+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj5cblxuXG48ZGl2ICpuZ0lmPVwiJ2Zvcm0nID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxmb3JtIFtmb3JtR3JvdXBdPVwiZmdcIiAobmdTdWJtaXQpPVwic3VibWl0KClcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgPGxhYmVsIFthdHRyLmZvcl09XCJmb3JtSWQgKyAnZW1haWwnXCI+RW1haWwgQWRkcmVzczwvbGFiZWw+XG5cbiAgICAgIDxpbnB1dFxuICAgICAgICByZWFkb25seVxuICAgICAgICAjZW1haWxJbnB1dFxuICAgICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAnZW1haWwnXCJcbiAgICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJmb3JtSWQgKyAnZW1haWwnXCJcbiAgICAgICAgdHlwZT1cImVtYWlsXCJcbiAgICAgICAgYXV0b2NvbXBsZXRlPVwiZW1haWxcIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIkVtYWlsIEFkZHJlc3NcIlxuICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJlbWFpbFwiXG4gICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCI+XG4gICAgICA8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkIGZvcm0tdGV4dFwiIFthdHRyLmlkXT1cImZvcm1JZCArICdlbWFpbCdcIiA+XG4gICAgICAgIFlvdSBhcmUgcmVzZXR0aW5nIHRoZSBwYXNzd29yZCBmb3Ige3tlbWFpbEZjLnZhbHVlfX0uXG4gICAgICA8L3NtYWxsPlxuICAgIDwvZGl2PlxuXG4gICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXgganVzdGlmeS1jb250ZW50LWJldHdlZW4gYWxpZ24taXRlbXMtZW5kXCI+XG4gICAgICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkJ1wiPlBhc3N3b3JkPC9sYWJlbD5cbiAgICAgICAgPHNtYWxsPlxuICAgICAgICAgIDxhIChjbGljayk9XCIkZXZlbnQucHJldmVudERlZmF1bHQoKTsgcGFzc3dvcmRJbnB1dC50eXBlID0gJ3Bhc3N3b3JkJyA9PT0gcGFzc3dvcmRJbnB1dC50eXBlICA/ICd0ZXh0JyA6ICdwYXNzd29yZCdcIlxuICAgICAgICAgICAgaHJlZj1cIiNcIiB0YWJpbmRleD1cIi0xXCIgY2xhc3M9XCJkLWlubGluZS1ibG9ja1wiPlxuICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCIncGFzc3dvcmQnID09PSBwYXNzd29yZElucHV0LnR5cGVcIj5TaG93PC9zcGFuPlxuICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCIndGV4dCcgPT09IHBhc3N3b3JkSW5wdXQudHlwZVwiPkhpZGU8L3NwYW4+XG4gICAgICAgICAgPC9hPlxuICAgICAgICA8L3NtYWxsPlxuICAgICAgPC9kaXY+XG4gICAgICA8aW5wdXRcbiAgICAgICAgI3Bhc3N3b3JkSW5wdXRcbiAgICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkJ1wiXG4gICAgICAgIFthdHRyLmFyaWEtZGVzY3JpYmVkYnldPVwiZm9ybUlkICsgJ3Bhc3N3b3JkLWhlbHAnXCJcbiAgICAgICAgdHlwZT1cInBhc3N3b3JkXCJcbiAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicGFzc3dvcmRcIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIlBhc3N3b3JkXCJcbiAgICAgICAgYXV0b2NvbXBsZXRlPVwicGFzc3dvcmRcIlxuICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgIFtjbGFzcy5pcy1pbnZhbGlkXT1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmludmFsaWRcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgKm5nSWY9XCJwYXNzd29yZEZjLnRvdWNoZWQgJiYgcGFzc3dvcmRGYy5oYXNFcnJvcigncmVxdWlyZWQnKVwiPlxuICAgICAgICBSZXF1aXJlZC5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiAqbmdJZj1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmhhc0Vycm9yKCdhdXRoL3dlYWstcGFzc3dvcmQnKVwiPlxuICAgICAgICBUaGF0IHBhc3N3b3JkIGlzIHRvbyB3ZWFrLlxuICAgICAgPC9kaXY+XG4gICAgICA8c21hbGwgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkLWhlbHAnXCIgY2xhc3M9XCJmb3JtLXRleHQgdGV4dC1tdXRlZFwiPlxuICAgICAgICBQbGVhc2UgY2hvb3NlIGEgc3Ryb25nIHBhc3N3b3JkLlxuICAgICAgPC9zbWFsbD5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2tcIj5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCJcbiAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAgIFt2YWx1ZV09XCJ0cnVlXCJcbiAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZW1lbWJlclwiXG4gICAgICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWNoZWNrLWxhYmVsXCIgW2F0dHIuZm9yXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgICAgICBSZW1lbWJlciBtZSBvbiB0aGlzIGRldmljZS5cbiAgICAgICAgPC9sYWJlbD5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgICA8YnV0dG9uIHR5cGU9XCJzdWJtaXRcIlxuICAgICAgICBjbGFzcz1cImJ0biBidG4tc3VjY2VzcyBidG4tYmxvY2tcIlxuICAgICAgICBbZGlzYWJsZWRdPVwiZmcuaW52YWxpZCB8fCBzdWJtaXR0aW5nXCI+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLXNhdmUgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICAgIFNhdmUgUGFzc3dvcmQgYW5kIFNpZ24gSW5cbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICA8L2Zvcm0+XG48L2Rpdj5cbmAsXG4gIHN0eWxlczogW2BgXSxcbiAgYW5pbWF0aW9uczogW3NjcmVlbkFuaW1hdGlvbl1cbn0pXG5leHBvcnQgY2xhc3MgT29iUmVzZXRQYXNzd29yZENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgQElucHV0KCkgb29iQ29kZTogc3RyaW5nO1xuICBAT3V0cHV0KCkgc3VjY2VzczogRXZlbnRFbWl0dGVyPElOZ3hGaXJlYmFzZUF1dGhPb2JTdWNjZXNzPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBzY3JlZW46ICd3YWl0JyB8ICdmb3JtJyB8ICdlcnJvcicgfCAnc3VjY2VzcycgPSAnd2FpdCc7XG4gIGluZm86IGF1dGguQWN0aW9uQ29kZUluZm87XG4gIHN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgZm9ybUlkID0gJ25neC1maXJlYmFzZS1hdXRoLW9vYi1yZXNldC1wYXNzd29yZC0nO1xuICBmZzogRm9ybUdyb3VwO1xuICBlbWFpbEZjOiBGb3JtQ29udHJvbDtcbiAgcGFzc3dvcmRGYzogRm9ybUNvbnRyb2w7XG4gIHJlbWVtYmVyRmM6IEZvcm1Db250cm9sO1xuICB1bmhhbmRsZWRFcnJvcjogYXV0aC5FcnJvciA9IG51bGw7XG4gIGNyZWQ6IGF1dGguVXNlckNyZWRlbnRpYWwgPSBudWxsO1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgICAgIHByaXZhdGUgX2F1dGhTZXJ2aWNlOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlLFxuICApIHsgfVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG4gIGdldCBhdXRoU2VydmljZSgpOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIHtcbiAgICByZXR1cm4gdGhpcy5fYXV0aFNlcnZpY2U7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICBjb25zdCByZW1lbWJlcmVkID0gdGhpcy5hdXRoU2VydmljZS5nZXRSZW1lbWJlcmVkKCk7XG4gICAgdGhpcy5lbWFpbEZjID0gbmV3IEZvcm1Db250cm9sKCcnKTtcbiAgICB0aGlzLnBhc3N3b3JkRmMgPSBuZXcgRm9ybUNvbnRyb2woJycsIHt2YWxpZGF0b3JzOiBbVmFsaWRhdG9ycy5yZXF1aXJlZF19KTtcbiAgICB0aGlzLnJlbWVtYmVyRmMgPSBuZXcgRm9ybUNvbnRyb2wocmVtZW1iZXJlZC5yZW1lbWJlcik7XG4gICAgdGhpcy5mZyA9IG5ldyBGb3JtR3JvdXAoe2VtYWlsOiB0aGlzLmVtYWlsRmMsIHBhc3N3b3JkOiB0aGlzLnBhc3N3b3JkRmMsIHJlbWVtYmVyOiB0aGlzLnJlbWVtYmVyRmN9KTtcbiAgICB0aGlzLmF1dGguY2hlY2tBY3Rpb25Db2RlKHRoaXMub29iQ29kZSlcbiAgICAgIC50aGVuKChyZXN1bHQ6IGF1dGguQWN0aW9uQ29kZUluZm8pID0+IHtcbiAgICAgICAgdGhpcy5pbmZvID0gcmVzdWx0O1xuICAgICAgICB0aGlzLmVtYWlsRmMuc2V0VmFsdWUocmVzdWx0LmRhdGEuZW1haWwpO1xuICAgICAgICB0aGlzLnNjcmVlbiA9ICdmb3JtJztcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKGVycm9yOiBhdXRoLkVycm9yKSA9PiB7XG4gICAgICAgIHRoaXMudW5oYW5kbGVkRXJyb3IgPSBlcnJvcjtcbiAgICAgICAgdGhpcy5zY3JlZW4gPSAnZXJyb3InO1xuICAgICAgfSk7XG4gIH1cblxuICBzdWJtaXQoKSB7XG4gICAgdGhpcy5zdWJtaXR0aW5nID0gdHJ1ZTtcbiAgICB0aGlzLmF1dGguY29uZmlybVBhc3N3b3JkUmVzZXQodGhpcy5vb2JDb2RlLCB0aGlzLnBhc3N3b3JkRmMudmFsdWUpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmF1dGguc2lnbkluV2l0aEVtYWlsQW5kUGFzc3dvcmQodGhpcy5pbmZvLmRhdGEuZW1haWwsIHRoaXMucGFzc3dvcmRGYy52YWx1ZSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKGNyZWQ6IGF1dGguVXNlckNyZWRlbnRpYWwpID0+IHtcbiAgICAgICAgdGhpcy5jcmVkID0gY3JlZDtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aFNlcnZpY2Uuc2V0UmVtZW1iZXJlZCh0aGlzLnJlbWVtYmVyRmMudmFsdWUgPT09IHRydWUsIHRoaXMuaW5mby5kYXRhLmVtYWlsKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ3N1Y2Nlc3MnO1xuICAgICAgICB0aGlzLnN1Y2Nlc3MuZW1pdCh7XG4gICAgICAgICAgbW9kZTogJ3Jlc2V0UGFzc3dvcmQnLFxuICAgICAgICAgIGluZm86IHRoaXMuaW5mbyxcbiAgICAgICAgICBjcmVkOiB0aGlzLmNyZWQsXG4gICAgICAgICAgdXNlcjogdGhpcy5jcmVkLnVzZXJcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcjogYXV0aC5FcnJvcikgPT4ge1xuICAgICAgICB0aGlzLnN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5wYXNzd29yZEZjLm1hcmtBc0RpcnR5KCk7XG4gICAgICAgIHRoaXMucGFzc3dvcmRGYy5tYXJrQXNUb3VjaGVkKCk7XG4gICAgICAgIHN3aXRjaCAoZXJyb3IuY29kZSkge1xuICAgICAgICAgIGNhc2UgJ2F1dGgvd2Vhay1wYXNzd29yZCc6XG4gICAgICAgICAgICBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyLnNldEVycm9yVW50aWxDaGFuZ2VkKHRoaXMucGFzc3dvcmRGYywgZXJyb3IuY29kZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhpcy51bmhhbmRsZWRFcnJvciA9IGVycm9yO1xuICAgICAgICAgICAgdGhpcy5zY3JlZW4gPSAnZXJyb3InO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Hcm91cCwgRm9ybUNvbnRyb2wsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdhbmd1bGFyZmlyZTIvYXV0aCc7XG5pbXBvcnQgeyBhdXRoLCBVc2VyIH0gZnJvbSAnZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IElOZ3hGaXJlYmFzZUF1dGhPb2JTdWNjZXNzIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcbmltcG9ydCB7IHNjcmVlbkFuaW1hdGlvbiB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLW9vYi1yZWNvdmVyLWVtYWlsJyxcbiAgdGVtcGxhdGU6IGBcblxuPGRpdiAqbmdJZj1cIid3YWl0JyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc2Vjb25kYXJ5XCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtc3BpbiBmYS1zcGlubmVyIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFBsZWFzZSB3YWl0Li4uXG4gIDwvZGl2PlxuPC9kaXY+XG5cblxuPGRpdiAqbmdJZj1cIidzdWNjZXNzJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc3VjY2Vzc1wiPlxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLWNoZWNrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFlvdXIgZW1haWwgaGFzIGJlZW4gY2hhbmdlZCBiYWNrIHRvIHt7aW5mby5kYXRhLmVtYWlsfX07XG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCJzY3JlZW4gPT09ICdmb3JtJ1wiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8cD5cbiAgICAgIEFyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byBjaGFuZ2UgeW91ciBlbWFpbCBiYWNrIHRvXG4gICAgICB7e2luZm8uZGF0YS5lbWFpbH19IGZyb20ge3tpbmZvLmRhdGEuZnJvbUVtYWlsfX0/XG4gICAgPC9wPlxuICAgIDxidXR0b25cbiAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgW2Rpc2FibGVkXT1cInN1Ym1pdHRpbmdcIlxuICAgICAgKGNsaWNrKT1cInN1Ym1pdCgpXCJcbiAgICAgIGNsYXNzPVwiYnRuIGJ0bi1ibG9jayBidG4tc3VjY2Vzc1wiPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtc2F2ZSBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIFllcywgQ29udGludWVcbiAgICA8L2J1dHRvbj5cbiAgPC9kaXY+XG48L2Rpdj5cblxuXG5cbjxkaXYgKm5nSWY9XCJzY3JlZW4gPT09ICdlcnJvcidcIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIj5cbiAgICA8cD5cbiAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgV29vcHMhIEFuIGVycm9yIG9jY3VycmVkLlxuICAgIDwvcD5cbiAgICA8ZGl2IFtuZ1N3aXRjaF09XCJ1bmhhbmRsZWRFcnJvci5jb2RlXCI+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvZXhwaXJlZC1hY3Rpb24tY29kZSdcIj5cbiAgICAgICAgVGhlIHJlY292ZXIgZW1haWwgbGluayB5b3UgdXNlZCBoYXMgZXhwaXJlZC5cbiAgICAgIDwvcD5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC9pbnZhbGlkLWFjdGlvbi1jb2RlJ1wiPlxuICAgICAgICBUaGUgcmVjb3ZlciBlbWFpbCBsaW5rIHlvdSB1c2VkIGlzIG5vdCB2YWxpZC4gVGhpcyBtYXkgYmUgYmVjYXVzZSBpdFxuICAgICAgICBoYXMgYWxyZWFkeSBiZWVuIHVzZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvdXNlci1kaXNhYmxlZCdcIj5cbiAgICAgICAgVGhlIGFjY291bnQgYXNzb2NpYXRlZCB3aXRoIHRoZSByZWNvdmVyIGVtYWlsIGxpbmsgeW91IHVzZWQgaGFzIGJlZW4gZGlzYWJsZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvdXNlci1ub3QtZm91bmQnXCI+XG4gICAgICAgIFRoZSBhY2NvdW50IGFzc29jaWF0ZWQgd2l0aCB0aGUgcmVjb3ZlciBlbWFpbCBsaW5rIHlvdSB1c2VkIGhhcyBiZWVuIHJlbW92ZWQuXG4gICAgICA8L3A+XG4gICAgICA8ZGl2ICpuZ1N3aXRjaERlZmF1bHQ+XG4gICAgICAgIDxwPkNvZGU6IHt7dW5oYW5kbGVkRXJyb3IuY29kZX19PC9wPlxuICAgICAgICA8cCBjbGFzcz1cIm1iLTBcIj5cbiAgICAgICAgICBNZXNzYWdlOiB7e3VuaGFuZGxlZEVycm9yLm1lc3NhZ2V9fVxuICAgICAgICA8L3A+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj5cbmAsXG4gIHN0eWxlczogW2BgXSxcbiAgYW5pbWF0aW9uczogW3NjcmVlbkFuaW1hdGlvbl1cbn0pXG5leHBvcnQgY2xhc3MgT29iUmVjb3ZlckVtYWlsQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBASW5wdXQoKSBvb2JDb2RlOiBzdHJpbmc7XG4gIEBPdXRwdXQoKSBzdWNjZXNzOiBFdmVudEVtaXR0ZXI8SU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3M+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIHNjcmVlbjogJ3dhaXQnIHwgJ2Zvcm0nIHwgJ2Vycm9yJyB8ICdzdWNjZXNzJyA9ICd3YWl0JztcbiAgaW5mbzogYXV0aC5BY3Rpb25Db2RlSW5mbztcbiAgc3VibWl0dGluZyA9IGZhbHNlO1xuICB1bmhhbmRsZWRFcnJvcjogYXV0aC5FcnJvcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgKSB7IH1cblxuICBnZXQgYXV0aCgpOiBhdXRoLkF1dGgge1xuICAgIHJldHVybiB0aGlzLl9hZkF1dGguYXV0aDtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuXG4gICAgdGhpcy5hdXRoLmNoZWNrQWN0aW9uQ29kZSh0aGlzLm9vYkNvZGUpXG4gICAgICAudGhlbigocmVzdWx0OiBhdXRoLkFjdGlvbkNvZGVJbmZvKSA9PiB7XG4gICAgICAgIHRoaXMuaW5mbyA9IHJlc3VsdDtcbiAgICAgICAgdGhpcy5zY3JlZW4gPSAnZm9ybSc7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcjogYXV0aC5FcnJvcikgPT4ge1xuICAgICAgICB0aGlzLnVuaGFuZGxlZEVycm9yID0gZXJyb3I7XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ2Vycm9yJztcbiAgICAgIH0pO1xuICB9XG5cbiAgc3VibWl0KCkge1xuICAgIHRoaXMuYXV0aC5hcHBseUFjdGlvbkNvZGUodGhpcy5vb2JDb2RlKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLnNjcmVlbiA9ICdzdWNjZXNzJztcbiAgICAgICAgdGhpcy5zdWNjZXNzLmVtaXQoe1xuICAgICAgICAgIG1vZGU6ICdyZWNvdmVyRW1haWwnLFxuICAgICAgICAgIGluZm86IHRoaXMuaW5mbyxcbiAgICAgICAgICB1c2VyOiB0aGlzLmF1dGguY3VycmVudFVzZXJcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcjogYXV0aC5FcnJvcikgPT4ge1xuICAgICAgICB0aGlzLnVuaGFuZGxlZEVycm9yID0gZXJyb3I7XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ2Vycm9yJztcbiAgICAgIH0pO1xuICB9XG5cblxufVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUdyb3VwLCBGb3JtQ29udHJvbCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IGF1dGgsIFVzZXIgfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgSU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3MgfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuaW1wb3J0IHsgc2NyZWVuQW5pbWF0aW9uIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWZpcmViYXNlLWF1dGgtb29iLXZlcmlmeS1lbWFpbCcsXG4gIHRlbXBsYXRlOiBgPGRpdiAqbmdJZj1cIid3YWl0JyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc2Vjb25kYXJ5XCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtc3BpbiBmYS1zcGlubmVyIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFBsZWFzZSB3YWl0Li4uXG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCInc3VjY2VzcycgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXN1Y2Nlc3NcIj5cbiAgICA8aSBjbGFzcz1cImZhcyBmYS1jaGVjayBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICBUaGUgZW1haWwge3tpbmZvLmRhdGEuZW1haWx9fSBoYXMgYmVlbiB2ZXJpZmllZC5cbiAgPC9kaXY+XG48L2Rpdj5cblxuPGRpdiAqbmdJZj1cInNjcmVlbiA9PT0gJ2Vycm9yJ1wiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWRhbmdlclwiPlxuICAgIDxwPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGUgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICBXb29wcyEgQW4gZXJyb3Igb2NjdXJyZWQuXG4gICAgPC9wPlxuICAgIDxkaXYgW25nU3dpdGNoXT1cInVuaGFuZGxlZEVycm9yLmNvZGVcIj5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC9leHBpcmVkLWFjdGlvbi1jb2RlJ1wiPlxuICAgICAgICBUaGUgdmVyaWZ5IGVtYWlsIGxpbmsgeW91IHVzZWQgaGFzIGV4cGlyZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvaW52YWxpZC1hY3Rpb24tY29kZSdcIj5cbiAgICAgICAgVGhlIHZlcmlmeSBlbWFpbCBsaW5rIHlvdSB1c2VkIGlzIG5vdCB2YWxpZC4gVGhpcyBtYXkgYmUgYmVjYXVzZSBpdFxuICAgICAgICBoYXMgYWxyZWFkeSBiZWVuIHVzZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvdXNlci1kaXNhYmxlZCdcIj5cbiAgICAgICAgVGhlIGFjY291bnQgYXNzb2NpYXRlZCB3aXRoIHRoZSB2ZXJpZnkgZW1haWwgbGluayB5b3UgdXNlZCBoYXMgYmVlbiBkaXNhYmxlZC5cbiAgICAgIDwvcD5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC91c2VyLW5vdC1mb3VuZCdcIj5cbiAgICAgICAgVGhlIGFjY291bnQgYXNzb2NpYXRlZCB3aXRoIHRoZSB2ZXJpZnkgZW1haWwgbGluayB5b3UgdXNlZCBoYXMgYmVlbiByZW1vdmVkLlxuICAgICAgPC9wPlxuICAgICAgPGRpdiAqbmdTd2l0Y2hEZWZhdWx0PlxuICAgICAgICA8cD5Db2RlOiB7e3VuaGFuZGxlZEVycm9yLmNvZGV9fTwvcD5cbiAgICAgICAgPHAgY2xhc3M9XCJtYi0wXCI+XG4gICAgICAgICAgTWVzc2FnZToge3t1bmhhbmRsZWRFcnJvci5tZXNzYWdlfX1cbiAgICAgICAgPC9wPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9kaXY+XG5gLFxuICBzdHlsZXM6IFtgYF0sXG4gIGFuaW1hdGlvbnM6IFtzY3JlZW5BbmltYXRpb25dXG59KVxuZXhwb3J0IGNsYXNzIE9vYlZlcmlmeUVtYWlsQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBASW5wdXQoKSBvb2JDb2RlOiBzdHJpbmc7XG4gIEBPdXRwdXQoKSBzdWNjZXNzOiBFdmVudEVtaXR0ZXI8SU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3M+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIHNjcmVlbjogJ3dhaXQnIHwgJ2Vycm9yJyB8ICdzdWNjZXNzJyA9ICd3YWl0JztcbiAgaW5mbzogYXV0aC5BY3Rpb25Db2RlSW5mbztcbiAgc3VibWl0dGluZyA9IGZhbHNlO1xuICB1bmhhbmRsZWRFcnJvcjogYXV0aC5FcnJvcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgKSB7IH1cblxuICBnZXQgYXV0aCgpOiBhdXRoLkF1dGgge1xuICAgIHJldHVybiB0aGlzLl9hZkF1dGguYXV0aDtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuXG4gICAgdGhpcy5hdXRoLmNoZWNrQWN0aW9uQ29kZSh0aGlzLm9vYkNvZGUpXG4gICAgICAudGhlbigocmVzdWx0OiBhdXRoLkFjdGlvbkNvZGVJbmZvKSA9PiB7XG4gICAgICAgIHRoaXMuaW5mbyA9IHJlc3VsdDtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aC5hcHBseUFjdGlvbkNvZGUodGhpcy5vb2JDb2RlKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ3N1Y2Nlc3MnO1xuICAgICAgICB0aGlzLnN1Y2Nlc3MuZW1pdCh7XG4gICAgICAgICAgbW9kZTogJ3ZlcmlmeUVtYWlsJyxcbiAgICAgICAgICBpbmZvOiB0aGlzLmluZm8sXG4gICAgICAgICAgdXNlcjogdGhpcy5hdXRoLmN1cnJlbnRVc2VyXG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyb3I6IGF1dGguRXJyb3IpID0+IHtcbiAgICAgICAgdGhpcy51bmhhbmRsZWRFcnJvciA9IGVycm9yO1xuICAgICAgICB0aGlzLnNjcmVlbiA9ICdlcnJvcic7XG4gICAgICB9KTtcbiAgfVxuXG59XG4iLCJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IFJvdXRlck1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBSZWFjdGl2ZUZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBPb2JDb21wb25lbnQgfSBmcm9tICcuL29vYi5jb21wb25lbnQnO1xuaW1wb3J0IHsgT29iUmVzZXRQYXNzd29yZENvbXBvbmVudCB9IGZyb20gJy4vb29iLXJlc2V0LXBhc3N3b3JkL29vYi1yZXNldC1wYXNzd29yZC5jb21wb25lbnQnO1xuaW1wb3J0IHsgT29iUmVjb3ZlckVtYWlsQ29tcG9uZW50IH0gZnJvbSAnLi9vb2ItcmVjb3Zlci1lbWFpbC9vb2ItcmVjb3Zlci1lbWFpbC5jb21wb25lbnQnO1xuaW1wb3J0IHsgT29iVmVyaWZ5RW1haWxDb21wb25lbnQgfSBmcm9tICcuL29vYi12ZXJpZnktZW1haWwvb29iLXZlcmlmeS1lbWFpbC5jb21wb25lbnQnO1xuXG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhNb2R1bGUgfSBmcm9tICcuLi9uZ3gtZmlyZWJhc2UtYXV0aC5tb2R1bGUnO1xuXG5ATmdNb2R1bGUoe1xuICBpbXBvcnRzOiBbXG4gICAgQ29tbW9uTW9kdWxlLFxuICAgIFJlYWN0aXZlRm9ybXNNb2R1bGUsXG4gICAgUm91dGVyTW9kdWxlLFxuICAgIE5neEZpcmViYXNlQXV0aE1vZHVsZVxuICBdLFxuICBkZWNsYXJhdGlvbnM6IFtcbiAgICBPb2JDb21wb25lbnQsXG4gICAgT29iUmVjb3ZlckVtYWlsQ29tcG9uZW50LFxuICAgIE9vYlJlc2V0UGFzc3dvcmRDb21wb25lbnQsXG4gICAgT29iVmVyaWZ5RW1haWxDb21wb25lbnRcbiAgXSxcbiAgZXhwb3J0czogW1xuICAgIE9vYkNvbXBvbmVudCxcbiAgXVxufSlcbmV4cG9ydCBjbGFzcyBOZ3hGaXJlYmFzZUF1dGhPb2JNb2R1bGUgeyB9XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQWlCQSxNQUFhLGtCQUFrQixHQUE2QixPQUFPLENBQUMsV0FBVyxFQUFFO0lBQy9FLEtBQUssQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLEVBQUMsT0FBTyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFDLENBQUMsQ0FBQztJQUNsRCxVQUFVLENBQUMsV0FBVyxFQUFFO1FBQ3RCLEtBQUssQ0FBQyxFQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUMsQ0FBQztRQUNuQixPQUFPLENBQUMsR0FBRyxDQUFDO0tBQ2IsQ0FBQztJQUNGLFVBQVUsQ0FBQyxXQUFXLEVBQUU7UUFDdEIsT0FBTyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsRUFBQyxPQUFPLEVBQUUsQ0FBQyxFQUFDLENBQUMsQ0FBQztLQUNsQyxDQUFDO0NBQ0gsQ0FBQyxDQUFDOztBQUVILE1BQWEsZUFBZSxHQUE2QixPQUFPLENBQUMsUUFBUSxFQUFFO0lBQ3pFLEtBQUssQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLEVBQUMsT0FBTyxFQUFFLENBQUMsRUFBQyxDQUFDLENBQUM7SUFDaEMsVUFBVSxDQUFDLFdBQVcsRUFBRTtRQUN0QixLQUFLLENBQUMsRUFBQyxPQUFPLEVBQUUsQ0FBQyxFQUFDLENBQUM7UUFDbkIsT0FBTyxDQUFDLEdBQUcsQ0FBQztLQUNiLENBQUM7SUFDRixVQUFVLENBQUMsV0FBVyxFQUFFO1FBQ3RCLE9BQU8sQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUMsT0FBTyxFQUFFLENBQUMsRUFBQyxDQUFDLENBQUM7S0FDaEMsQ0FBQztDQUNILENBQUMsQ0FBQzs7QUFFSCxNQUFhLG9CQUFvQixHQUFHLENBQUMsRUFBVTtJQUM3QyxRQUFRLEVBQUU7UUFDUixLQUFLLGFBQWEsRUFBRSxPQUFPLFNBQVMsQ0FBQztRQUNyQyxLQUFLLGNBQWMsRUFBRSxPQUFPLFVBQVUsQ0FBQztRQUN2QyxLQUFLLFlBQVksRUFBRSxPQUFPLFFBQVEsQ0FBQztRQUNuQyxLQUFLLFlBQVksRUFBRSxPQUFPLFFBQVEsQ0FBQztRQUNuQyxTQUFTLE9BQU8sRUFBRSxDQUFDO0tBQ3BCO0NBQ0YsQ0FBQzs7QUFFRixNQUFhLG9CQUFvQixHQUFHLENBQUMsRUFBVTtJQUM3QyxRQUFRLEVBQUU7UUFDUixLQUFLLGFBQWEsQ0FBQztRQUNuQixLQUFLLGNBQWMsQ0FBQztRQUNwQixLQUFLLFlBQVksQ0FBQztRQUNsQixLQUFLLFlBQVk7WUFDZixPQUFPLGVBQWUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNsRCxTQUFTLE9BQU8sMEJBQTBCLENBQUM7S0FDNUM7Q0FDRjs7Ozs7O0FDMUREOzs7O0lBV0UsWUFDVTtRQUFBLFlBQU8sR0FBUCxPQUFPO0tBQ1o7Ozs7SUFFTCxJQUFJLElBQUk7UUFDTixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO0tBQzFCOzs7O0lBQ0QsSUFBSSxPQUFPO1FBQ1QsT0FBTyxNQUFNLENBQUMsWUFBWSxDQUFDO0tBQzVCOzs7O0lBRUQsYUFBYTs7UUFDWCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNyRSxJQUFJLEdBQUcsRUFBRTtZQUNQLElBQUk7Z0JBQ0YsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2FBQ3hCO1lBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQ1YsT0FBTyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBQyxDQUFDO2FBQ3BDO1NBQ0Y7UUFDRCxPQUFPLEVBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFDLENBQUM7S0FDcEM7Ozs7OztJQUVELGFBQWEsQ0FBQyxRQUFpQixFQUFFLEtBQWE7O1FBQzVDLE1BQU0sV0FBVyxHQUEwQixRQUFRO1lBQ2pELElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUM7UUFDOUQsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxXQUFXLENBQUM7YUFDekMsSUFBSSxDQUFDOztZQUNKLE1BQU0sQ0FBQyxHQUFtQztnQkFDeEMsS0FBSyxFQUFFLFFBQVEsR0FBRyxLQUFLLEdBQUcsRUFBRTtnQkFDNUIsUUFBUSxFQUFFLFFBQVE7YUFDbkIsQ0FBQzs7WUFDRixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzlCLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLHNCQUFzQixDQUFDLFdBQVcsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUM5RCxPQUFPLENBQUMsQ0FBQztTQUNWLENBQUMsQ0FBQztLQUNOOztxQ0F0Q29CLDRCQUE0Qjs7WUFKbEQsVUFBVSxTQUFDO2dCQUNWLFVBQVUsRUFBRSxNQUFNO2FBQ25COzs7O1lBTlEsZUFBZTs7Ozs7Ozs7QUNEeEI7Ozs7Ozs7SUFvSUUsWUFDVSxTQUNBLE1BQ0EsUUFDQTtRQUhBLFlBQU8sR0FBUCxPQUFPO1FBQ1AsU0FBSSxHQUFKLElBQUk7UUFDSixXQUFNLEdBQU4sTUFBTTtRQUNOLFlBQU8sR0FBUCxPQUFPOzZCQXhCc0IsSUFBSSxPQUFPLEVBQVE7MkJBSWpCLElBQUk7dUJBQ1UsSUFBSSxZQUFZLEVBQUU7b0JBQ2QsSUFBSSxZQUFZLEVBQUU7aUNBSTdDLElBQUk7eUJBQ3hCLEtBQUs7K0JBQ1MsSUFBSTtvQkFDRixJQUFJOzhCQUNILElBQUk7c0JBSU0sTUFBTTtLQU96Qzs7OztJQUVKLElBQUksSUFBSTtRQUNOLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7S0FDMUI7Ozs7SUFFRCxJQUFJLFdBQVc7UUFDYixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUM7S0FDbEI7Ozs7SUFFRCxJQUFJLE1BQU07UUFDUixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7S0FDckI7Ozs7SUFFRCxJQUFJLEtBQUs7UUFDUCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUM7S0FDcEI7Ozs7SUFFRCxJQUFJLFdBQVc7UUFDYixPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDO0tBQy9COzs7O0lBRUQsSUFBSSxtQkFBbUI7UUFDckIsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUM7S0FDeEM7Ozs7SUFFRCxRQUFRO1FBQ04sSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0tBQ2I7Ozs7SUFFRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUMxQixJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDO0tBQy9COzs7O0lBRUQsSUFBSTs7UUFDRixNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ3hELElBQUksQ0FBQyxRQUFRLEdBQUcsY0FBYyxDQUFDLFFBQVEsQ0FBQztRQUN4QyxJQUFJLENBQUMsS0FBSyxHQUFHLGNBQWMsQ0FBQyxLQUFLLENBQUM7UUFDbEMsT0FBTyxJQUFJLENBQUMsbUJBQW1CLEVBQUU7YUFDOUIsSUFBSSxDQUFDLENBQUMsT0FBZ0I7WUFDckIsSUFBSSxPQUFPLEVBQUU7Z0JBQ1gsT0FBTyxPQUFPLENBQUM7YUFDaEI7WUFDRCxPQUFPLElBQUksQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO1NBQ3pDLENBQUM7YUFDRCxJQUFJLENBQUMsQ0FBQyxPQUFnQjtZQUNyQixJQUFJLENBQUUsT0FBTyxFQUFFO2dCQUNiLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQzthQUNuQjtZQUNELElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTTs7Z0JBQ25FLE1BQU0sTUFBTSxHQUFHLE1BQU0sY0FBVyxJQUFJLENBQUM7Z0JBQ3JDLFFBQVEsTUFBTTtvQkFDWixLQUFLLFNBQVM7d0JBQ1osSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO3dCQUNuQixNQUFNO29CQUNSLEtBQUssZUFBZTt3QkFDbEIsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7d0JBQ3pCLE1BQU07b0JBQ1IsS0FBSyxRQUFRO3dCQUNYLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQzt3QkFDbEIsTUFBTTtvQkFDUixLQUFLLGdCQUFnQjt3QkFDbkIsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7d0JBQzFCLE1BQU07b0JBQ1IsS0FBSyxnQkFBZ0I7d0JBQ25CLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO3dCQUMxQixNQUFNO29CQUNSLEtBQUssYUFBYTt3QkFDaEIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLGdCQUFhLElBQUksQ0FBQyxDQUFDO3dCQUM5QyxNQUFNO2lCQUNUO2FBQ0YsQ0FBQyxDQUFDO1NBQ0osQ0FBQyxDQUFDO0tBQ047Ozs7SUFFRCxtQkFBbUI7UUFDakIsSUFBSSxJQUFJLENBQUMsbUJBQW1CLGVBQVksU0FBUyxFQUFFO1lBQ2pELE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUMvQjtRQUNELE9BQU8sSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDO0tBQzVDOzs7O0lBQ0QseUJBQXlCO1FBQ3ZCLE9BQU8sSUFBSSxPQUFPLENBQUMsT0FBTzs7WUFDeEIsTUFBTSxRQUFRLEdBQVksSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsV0FBVyxpQkFBYyxNQUFNLENBQUM7WUFDOUUsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFpQixFQUFFO2lCQUNqQyxJQUFJLENBQUMsQ0FBQyxJQUF5QjtnQkFDOUIsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFO29CQUN0QyxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7eUJBQ3RELElBQUksQ0FBQzt3QkFDSixJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUM7d0JBQzdCLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztxQkFDZixDQUFDLENBQUM7aUJBQ047cUJBQU07b0JBQ0wsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO2lCQUNoQjthQUNGLENBQUM7aUJBQ0QsS0FBSyxDQUFDLENBQUMsS0FBaUI7Z0JBQ3ZCLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBRSxDQUFDO2dCQUNuQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDZixDQUFDLENBQUM7U0FDTixDQUFDLENBQUM7S0FDSjs7OztJQUtELFdBQVc7UUFDVCxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztRQUN2QixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFO2FBQ3ZCLElBQUksQ0FBQztZQUNKLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDdkIsQ0FBQyxDQUFDO0tBQ047Ozs7O0lBRUQsVUFBVSxDQUFDLFNBQW1CO1FBQzVCLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxLQUFLLElBQUksQ0FBQztRQUNwQyxJQUFJLENBQUMsTUFBTSxHQUFHLFFBQVEsQ0FBQztLQUN4Qjs7OztJQUVELGtCQUFrQjtRQUNoQixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN6QixJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztRQUN2QixJQUFJLENBQUMsTUFBTSxHQUFHLGdCQUFnQixDQUFDO0tBQ2hDOzs7O0lBRUQsa0JBQWtCO1FBQ2hCLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxNQUFNLEdBQUcsZ0JBQWdCLENBQUM7S0FFaEM7Ozs7OztJQUVELGVBQWUsQ0FBQyxlQUF1QixFQUFFLEtBQWlCO1FBQ3hELElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxlQUFlLEdBQUcsZUFBZSxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxLQUFLLENBQUM7UUFDL0IsSUFBSSxDQUFDLE1BQU0sR0FBRyxhQUFhLENBQUM7S0FDN0I7Ozs7O0lBRUQsaUJBQWlCLENBQUMsSUFBeUI7UUFDekMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDekIsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7UUFDdkIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLE1BQU0sR0FBRyxlQUFlLENBQUM7UUFDOUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDekI7Ozs7SUFFRCxpQkFBaUI7UUFDZixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUNoQyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztRQUN2QixJQUFJLENBQUMsTUFBTSxHQUFHLGVBQWUsQ0FBQztLQUMvQjs7Ozs7SUFFRCxrQkFBa0IsQ0FBQyxLQUFpQjtRQUNsQyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztRQUN2QixJQUFJLENBQUMsY0FBYyxHQUFHLEtBQUssQ0FBQztRQUM1QixJQUFJLENBQUMsTUFBTSxHQUFHLGdCQUFnQixDQUFDO0tBQ2hDOzs7WUE3UkYsU0FBUyxTQUFDO2dCQUNULFFBQVEsRUFBRSwyQkFBMkI7Z0JBQ3JDLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0E0Rlg7Z0JBQ0MsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDO2dCQUNaLFVBQVUsRUFBRSxDQUFDLGVBQWUsQ0FBQzthQUM5Qjs7OztZQXpHUSxlQUFlO1lBSWYsc0JBQXNCO1lBUmQsY0FBYztZQUF0QixNQUFNOzs7K0JBZ0haLEtBQUs7NEJBQ0wsS0FBSzttQ0FDTCxLQUFLOzBCQUNMLEtBQUs7c0JBQ0wsTUFBTTttQkFDTixNQUFNOzs7Ozs7O0FDdEhUOzs7O0lBdUNFLFlBQ1U7UUFBQSxXQUFNLEdBQU4sTUFBTTtzQkFSMkMsSUFBSTtvQkFFbUIsSUFBSSxZQUFZLEVBQUU7K0JBQ25ELElBQUksWUFBWSxFQUFFO3VCQUNMLElBQUksWUFBWSxFQUFFO0tBSzNFOzs7O0lBR0wsSUFBSSxXQUFXO1FBQ2IsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUM7S0FDekM7Ozs7SUFHRCxRQUFRO1FBQ04sSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsV0FBVyxlQUFZLElBQUksQ0FBQztRQUNoRCxJQUFJLENBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNsQixJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzVCLE9BQU87U0FDUjtRQUNELFFBQVEsSUFBSSxDQUFDLFdBQVc7WUFDdEIsS0FBSyxlQUFlLENBQUM7WUFDckIsS0FBSyxhQUFhLENBQUM7WUFDbkIsS0FBSyxjQUFjO2dCQUNqQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxXQUFXLFFBQUssQ0FBQztnQkFDcEMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsU0FBTSxDQUFDO2dCQUN0QyxNQUFNO1lBQ1I7Z0JBQ0UsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDNUIsTUFBTTtTQUNUO0tBRUY7OztZQTdERixTQUFTLFNBQUM7Z0JBQ1QsUUFBUSxFQUFFLHVCQUF1QjtnQkFDakMsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7OztDQWlCWDtnQkFDQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQ1osVUFBVSxFQUFFLENBQUMsZUFBZSxDQUFDO2FBQzlCOzs7O1lBM0JRLGNBQWM7OzttQkFpQ3BCLE1BQU07OEJBQ04sTUFBTTtzQkFDTixNQUFNOzs7Ozs7O0FDbkNUOzs7Ozs7O0lBRUUsT0FBTyxvQkFBb0IsQ0FBQyxFQUFtQixFQUFFLEdBQVcsRUFBRSxRQUFhLElBQUk7O1FBQzdFLE1BQU0sS0FBSyxHQUFHLEVBQUUsQ0FBQztRQUNqQixLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsS0FBSyxDQUFDO1FBQ25CLEVBQUUsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDcEIsRUFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1lBQ3RDLHlCQUF5QixDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUM7U0FDL0MsQ0FBQyxDQUFDO0tBRUo7Ozs7OztJQUVELE9BQU8sVUFBVSxDQUFDLEVBQW1CLEVBQUUsR0FBVzs7UUFDaEQsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDO1FBQ2xCLElBQUksQ0FBRSxFQUFFLENBQUMsTUFBTSxFQUFFO1lBQ2YsT0FBTztTQUNSO1FBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUMvQixJQUFJLENBQUMsS0FBSyxHQUFHLEVBQUU7Z0JBQ2IsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDMUI7U0FDRixDQUFDLENBQUM7UUFDSCxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUNwQyxFQUFFLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ3BCO2FBQU07WUFDTCxFQUFFLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1NBQ3RCO0tBQ0Y7Ozs7O0lBRUQsT0FBTyxnQkFBZ0IsQ0FBQyxFQUFtQjs7UUFDekMsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQztRQUN2QixJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRTtZQUM3QixPQUFPLElBQUksQ0FBQztTQUNiO1FBQ0QsT0FBTyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsTUFBTSxLQUFLLENBQUMsR0FBRyxFQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUMsR0FBRyxJQUFJLENBQUM7S0FDNUQ7Q0FHRjs7Ozs7O0FDdkNEOzs7Ozs7SUEyTEUsWUFDVSxTQUNBLGNBQ0E7UUFGQSxZQUFPLEdBQVAsT0FBTztRQUNQLGlCQUFZLEdBQVosWUFBWTtRQUNaLFlBQU8sR0FBUCxPQUFPO2dDQW5CcUIsRUFBRTsyQkFDTSxJQUFJLFlBQVksRUFBRTs4QkFDZCxJQUFJLFlBQVksRUFBRTt1QkFDYixJQUFJLFlBQVksRUFBRTtxQkFDN0IsSUFBSSxZQUFZLEVBQUU7c0JBR3JELHlDQUF5QzswQkFDckMsS0FBSztvQ0FJSyxvQkFBb0I7b0NBQ3BCLG9CQUFvQjsrQkFDSyxFQUFDLE1BQU0sRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFDO0tBTTFGOzs7O0lBRUwsSUFBSSxJQUFJO1FBQ04sT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztLQUMxQjs7OztJQUNELElBQUksV0FBVztRQUNiLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQztLQUMxQjs7OztJQUdELElBQUksT0FBTztRQUNULE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUM7S0FDckM7Ozs7SUFFRCxJQUFJLFdBQVc7UUFDYixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDO0tBQ3BDOzs7O0lBRUQsSUFBSSxjQUFjO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLEtBQUssU0FBUyxDQUFDO0tBQ2xEOzs7O0lBRUQsSUFBSSxZQUFZO1FBQ2QsT0FBTyxJQUFJLENBQUMsY0FBYyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQztLQUN6RDs7OztJQUVELElBQUksYUFBYTtRQUNmLE9BQU8sSUFBSSxDQUFDLGNBQWMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7S0FDdkQ7Ozs7SUFFRCxJQUFJLGtCQUFrQjtRQUNwQixPQUFPLElBQUksQ0FBQyxhQUFhLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7S0FDdEU7Ozs7SUFFRCxJQUFJLG1CQUFtQjtRQUNyQixJQUFJLENBQUUsSUFBSSxDQUFDLGFBQWEsRUFBRTtZQUN4QixPQUFPLEVBQUUsQ0FBQztTQUNYO1FBQ0QsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksRUFBRSxLQUFLLFVBQVUsQ0FBQyxDQUFDO0tBQ3JEOzs7O0lBS0QsUUFBUTtRQUNOLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxXQUFXLENBQzVCLElBQUksQ0FBQyxLQUFLLEVBQ1YsRUFBQyxVQUFVLEVBQUUsQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsRUFBQyxDQUN0RCxDQUFDO1FBQ0YsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLFdBQVcsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQzlGLElBQUksQ0FBQyxFQUFFLEdBQUcsSUFBSSxTQUFTLENBQUMsRUFBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBQyxDQUFDLENBQUM7UUFDMUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzVGLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUNoRixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7S0FDZDs7OztJQUVELGVBQWU7UUFDYixJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztLQUV2Qzs7OztJQUdELEtBQUs7O1FBQ0gsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDeEMsSUFBSSxLQUFLLEtBQUssSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUU7WUFDeEMsT0FBTztTQUNSO1FBQ0QsSUFBSSxVQUFVLEtBQUssSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUU7WUFDOUMsT0FBTztTQUNSO1FBQ0QsSUFBSSxDQUFDLGVBQWUsR0FBRyxFQUFDLE1BQU0sRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFDLENBQUM7UUFDdkUsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRTtZQUN4QixJQUFJLENBQUMsZUFBZSxHQUFHLEVBQUMsTUFBTSxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUMsQ0FBQztZQUN4RSxPQUFPO1NBQ1I7UUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLDBCQUEwQixDQUFDLEtBQUssQ0FBQzthQUN4QyxJQUFJLENBQUMsT0FBTztZQUNYLElBQUksQ0FBQyxlQUFlLEdBQUcsRUFBQyxNQUFNLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBQyxDQUFDO1NBQzVFLENBQUM7YUFDRCxLQUFLLENBQUMsQ0FBQyxLQUFpQjtZQUN2QixJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzNCLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDN0IsUUFBUSxLQUFLLENBQUMsSUFBSTtnQkFDaEIsS0FBSyxvQkFBb0I7b0JBQ3ZCLHlCQUF5QixDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO29CQUN6RSxNQUFNO2FBQ1Q7WUFDRCxJQUFJLENBQUMsZUFBZSxHQUFHLEVBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFDLENBQUM7U0FDOUUsQ0FBQyxDQUFDO0tBQ047OztZQS9RRixTQUFTLFNBQUM7Z0JBQ1QsUUFBUSxFQUFFLHdDQUF3QztnQkFDbEQsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQXFKWDtnQkFDQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQ1osVUFBVSxFQUFFLENBQUMsa0JBQWtCLEVBQUUsZUFBZSxDQUFDO2FBQ2xEOzs7O1lBbEtRLGVBQWU7WUFLZixzQkFBc0I7WUFQeUMsTUFBTTs7O3lCQXdLM0UsU0FBUyxTQUFDLFlBQVk7b0JBQ3RCLEtBQUs7dUJBQ0wsS0FBSzsrQkFDTCxLQUFLOzBCQUNMLE1BQU07NkJBQ04sTUFBTTtzQkFDTixNQUFNO29CQUNOLE1BQU07Ozs7Ozs7QUMvS1Q7Ozs7O0lBa0pFLFlBQ1UsU0FDQTtRQURBLFlBQU8sR0FBUCxPQUFPO1FBQ1AsaUJBQVksR0FBWixZQUFZOzhCQWY0QixJQUFJLFlBQVksRUFBRTt1QkFDYixJQUFJLFlBQVksRUFBRTtxQkFDN0IsSUFBSSxZQUFZLEVBQUU7c0JBRXJELGlDQUFpQzswQkFDN0IsS0FBSzsrQkFLVSxFQUFFO29DQUNQLG9CQUFvQjtvQ0FDcEIsb0JBQW9CO0tBSXRDOzs7O0lBRUwsSUFBSSxJQUFJO1FBQ04sT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztLQUMxQjs7OztJQUVELElBQUksV0FBVztRQUNiLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQztLQUMxQjs7OztJQUdELFFBQVE7UUFDTixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksV0FBVyxDQUM1QixJQUFJLENBQUMsS0FBSyxFQUNWLEVBQUMsVUFBVSxFQUFFLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUMsQ0FDdEQsQ0FBQztRQUNGLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxXQUFXLENBQUMsRUFBRSxFQUFFLEVBQUMsVUFBVSxFQUFFLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxFQUFDLENBQUMsQ0FBQztRQUMzRSxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNqRCxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDN0UsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLFNBQVMsQ0FBQztZQUN0QixLQUFLLEVBQUUsSUFBSSxDQUFDLE9BQU87WUFDbkIsUUFBUSxFQUFFLElBQUksQ0FBQyxVQUFVO1lBQ3pCLFFBQVEsRUFBRSxJQUFJLENBQUMsVUFBVTtTQUMxQixDQUFDLENBQUM7S0FDSjs7OztJQUNELGVBQWU7UUFDYixJQUFJLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztLQUMxQzs7OztJQUlELE1BQU07O1FBQ0osTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDeEMsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7UUFDdkIsSUFBSSxDQUFDLGVBQWUsR0FBRyxFQUFFLENBQUM7O1FBQzFCLElBQUksSUFBSSxDQUFzQjtRQUM5QixJQUFJLENBQUMsSUFBSSxDQUFDLDBCQUEwQixDQUFDLEtBQUssQ0FBQzthQUN4QyxJQUFJLENBQUMsT0FBTztZQUNYLElBQUksQ0FBQyxlQUFlLEdBQUcsT0FBTyxDQUFDO1lBQy9CLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7Z0JBQ3hCLE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQztvQkFDcEIsSUFBSSxFQUFFLHFCQUFxQjtpQkFDNUIsQ0FBQyxDQUFDO2FBQ0o7WUFDRCxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUU7Z0JBQ3RDLE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQztvQkFDcEIsSUFBSSxFQUFFLCtCQUErQjtpQkFDdEMsQ0FBQyxDQUFDO2FBQ0o7WUFDRCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDM0UsQ0FBQzthQUNELElBQUksQ0FBQyxNQUFNO1lBQ1YsSUFBSSxHQUFHLE1BQU0sQ0FBQztZQUNkLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEtBQUssSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQzlFLENBQUM7YUFDRCxJQUFJLENBQUM7WUFDSixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUN6QixDQUFDO2FBQ0QsS0FBSyxDQUFDLEtBQUs7WUFDVixJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztZQUN4QixJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzNCLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDN0IsSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUM5QixJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ2hDLFFBQVEsS0FBSyxDQUFDLElBQUk7Z0JBQ2hCLEtBQUssb0JBQW9CLENBQUM7Z0JBQzFCLEtBQUsscUJBQXFCLENBQUM7Z0JBQzNCLEtBQUssb0JBQW9CLENBQUM7Z0JBQzFCLEtBQUssK0JBQStCO29CQUNsQyx5QkFBeUIsQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztvQkFDekUsTUFBTTtnQkFDUixLQUFLLHFCQUFxQjtvQkFDeEIseUJBQXlCLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7b0JBQzVFLE1BQU07Z0JBQ1I7b0JBQ0UsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBQ3ZCLE1BQU07YUFDVDtTQUNGLENBQUMsQ0FBQztLQUNOOzs7WUExTkYsU0FBUyxTQUFDO2dCQUNULFFBQVEsRUFBRSxnQ0FBZ0M7Z0JBQzFDLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQWdIWDtnQkFDQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQ1osVUFBVSxFQUFFLENBQUMsa0JBQWtCLENBQUM7YUFDakM7Ozs7WUE3SFEsZUFBZTtZQUlmLHNCQUFzQjs7OzRCQTRINUIsU0FBUyxTQUFDLGVBQWU7b0JBQ3pCLEtBQUs7dUJBQ0wsS0FBSzs2QkFDTCxNQUFNO3NCQUNOLE1BQU07b0JBQ04sTUFBTTs7Ozs7OztBQ3ZJVDs7Ozs7SUF1SUUsWUFDVSxTQUNBO1FBREEsWUFBTyxHQUFQLE9BQU87UUFDUCxpQkFBWSxHQUFaLFlBQVk7OEJBYjRCLElBQUksWUFBWSxFQUFFO3VCQUNiLElBQUksWUFBWSxFQUFFO3FCQUM3QixJQUFJLFlBQVksRUFBRTtzQkFFckQsaUNBQWlDOzBCQUM3QixLQUFLO0tBU2I7Ozs7SUFFTCxJQUFJLElBQUk7UUFDTixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO0tBQzFCOzs7O0lBRUQsSUFBSSxXQUFXO1FBQ2IsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO0tBQzFCOzs7O0lBR0QsUUFBUTtRQUNOLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxXQUFXLENBQzVCLElBQUksQ0FBQyxLQUFLLEVBQ1YsRUFBQyxVQUFVLEVBQUUsQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsRUFBQyxDQUN0RCxDQUFDO1FBQ0YsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLFdBQVcsQ0FBQyxFQUFFLEVBQUUsRUFBQyxVQUFVLEVBQUUsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLEVBQUMsQ0FBQyxDQUFDO1FBQzNFLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxXQUFXLENBQUMsRUFBRSxFQUFFLEVBQUMsVUFBVSxFQUFFLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSx5QkFBeUIsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFDLENBQUMsQ0FBQztRQUNuSCxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNqRCxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDN0UsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLFNBQVMsQ0FBQztZQUN0QixLQUFLLEVBQUUsSUFBSSxDQUFDLE9BQU87WUFDbkIsUUFBUSxFQUFFLElBQUksQ0FBQyxVQUFVO1lBQ3pCLElBQUksRUFBRSxJQUFJLENBQUMsTUFBTTtZQUNqQixRQUFRLEVBQUUsSUFBSSxDQUFDLFVBQVU7U0FDMUIsQ0FBQyxDQUFDO0tBQ0o7Ozs7SUFDRCxlQUFlO1FBQ2IsSUFBSSxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7S0FDMUM7Ozs7SUFFRCxNQUFNO1FBRUosSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7O1FBQ3ZCLElBQUksSUFBSSxDQUFzQjtRQUM5QixJQUFJLENBQUMsSUFBSSxDQUFDLDBCQUEwQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7YUFDN0MsSUFBSSxDQUFDLENBQUMsT0FBTztZQUNaLElBQUksT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7Z0JBQ3RCLE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQztvQkFDcEIsSUFBSSxFQUFFLGtDQUFrQztpQkFDekMsQ0FBQyxDQUFDO2FBQ0o7WUFDRCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsOEJBQThCLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQ3BGLENBQUM7YUFDRCxJQUFJLENBQUMsTUFBTTtZQUNWLElBQUksR0FBRyxNQUFNLENBQUM7WUFDZCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLEVBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFDO1NBQ3pGLENBQUM7YUFDRCxJQUFJLENBQUM7WUFDSixPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxLQUFLLElBQUksRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDbkYsQ0FBQzthQUNELElBQUksQ0FBQztZQUNKLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ3pCLENBQUM7YUFDRCxLQUFLLENBQUMsS0FBSztZQUNWLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO1lBQ3hCLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDM0IsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUM3QixJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzlCLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDaEMsUUFBUSxLQUFLLENBQUMsSUFBSTtnQkFDaEIsS0FBSyxvQkFBb0IsQ0FBQztnQkFDMUIsS0FBSyxrQ0FBa0M7b0JBQ3JDLHlCQUF5QixDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO29CQUN6RSxNQUFNO2dCQUNSLEtBQUssb0JBQW9CO29CQUN2Qix5QkFBeUIsQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztvQkFDNUUsTUFBTTtnQkFDUjtvQkFDRSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDdkIsTUFBTTthQUNUO1NBQ0YsQ0FBQyxDQUFDO0tBQ047OztZQTNNRixTQUFTLFNBQUM7Z0JBQ1QsUUFBUSxFQUFFLGdDQUFnQztnQkFDMUMsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0F5R1g7Z0JBQ0MsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDO2dCQUNaLFVBQVUsRUFBRSxDQUFFLGtCQUFrQixDQUFFO2FBQ25DOzs7O1lBcEhRLGVBQWU7WUFLZixzQkFBc0I7Ozs0QkFrSDVCLFNBQVMsU0FBQyxlQUFlO29CQUN6QixLQUFLO3VCQUNMLEtBQUs7NkJBQ0wsTUFBTTtzQkFDTixNQUFNO29CQUNOLE1BQU07Ozs7Ozs7QUM5SFQ7Ozs7SUEyRUUsWUFDVTtRQUFBLFlBQU8sR0FBUCxPQUFPOzJCQVQ2QixJQUFJLFlBQVksRUFBRTtxQkFDcEIsSUFBSSxZQUFZLEVBQUU7c0JBRXJELDZDQUE2QzswQkFHekMsS0FBSztvQkFDSCxJQUFJO0tBR2Q7Ozs7SUFFTCxJQUFJLElBQUk7UUFDTixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO0tBQzFCOzs7O0lBTUQsUUFBUTtRQUNOLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxXQUFXLENBQzVCLElBQUksQ0FBQyxLQUFLLEVBQ1YsRUFBQyxVQUFVLEVBQUUsQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsRUFBQyxDQUN0RCxDQUFDO1FBQ0YsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzVGLElBQUksQ0FBQyxFQUFFLEdBQUcsSUFBSSxTQUFTLENBQUMsRUFBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBQyxDQUFDLENBQUM7S0FDaEQ7Ozs7SUFFRCxlQUFlO1FBQ2IsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7S0FDdkM7Ozs7SUFHRCxNQUFNOztRQUNKLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3hDLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsS0FBSyxDQUFDO2FBQ3BDLElBQUksQ0FBQztZQUNKLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO1lBQ3hCLElBQUksQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDO1NBQ25CLENBQUM7YUFDRCxLQUFLLENBQUMsQ0FBQyxLQUFpQjtZQUN2QixJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztZQUN4QixJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzdCLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDM0IsUUFBUSxLQUFLLENBQUMsSUFBSTtnQkFDaEIsS0FBSyxvQkFBb0IsQ0FBQztnQkFDMUIsS0FBSyxxQkFBcUI7b0JBQ3hCLHlCQUF5QixDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO29CQUN6RSxNQUFNO2dCQUNSO29CQUNFLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUN2QixNQUFNO2FBQ1Q7U0FDRixDQUFDLENBQUM7S0FHTjs7O1lBdkhGLFNBQVMsU0FBQztnQkFDVCxRQUFRLEVBQUUsNENBQTRDO2dCQUN0RCxRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBa0RYO2dCQUNDLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDWixVQUFVLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQzthQUNqQzs7OztZQTVEUSxlQUFlOzs7eUJBK0RyQixTQUFTLFNBQUMsWUFBWTtvQkFDdEIsS0FBSzswQkFDTCxNQUFNO29CQUNOLE1BQU07Ozs7Ozs7QUNwRVQ7Ozs7Ozs7SUF3SUUsWUFDVSxTQUNBLE1BQ0EsUUFDQTtRQUhBLFlBQU8sR0FBUCxPQUFPO1FBQ1AsU0FBSSxHQUFKLElBQUk7UUFDSixXQUFNLEdBQU4sTUFBTTtRQUNOLFlBQU8sR0FBUCxPQUFPO3VCQWxCc0MsSUFBSSxZQUFZLEVBQUU7MkJBQzNCLElBQUksWUFBWSxFQUFFOzhCQUNkLElBQUksWUFBWSxFQUFFO3FCQUN4QixJQUFJLFlBQVksRUFBRTtzQkFHbkIsTUFBTTsyQkFDbkIsSUFBSTtvQ0FDWCxvQkFBb0I7b0NBQ3BCLG9CQUFvQjtzQkFHbEMsa0NBQWtDO0tBT3RDOzs7O0lBRUwsSUFBSSxJQUFJO1FBQ04sT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztLQUMxQjs7OztJQUVELElBQUksV0FBVztRQUNiLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQztLQUNsQjs7OztJQUVELElBQUksS0FBSztRQUNQLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztLQUNwQjs7OztJQUVELElBQUksTUFBTTtRQUNSLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQztLQUNyQjs7OztJQUVELFFBQVE7UUFDTixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNqRCxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDN0UsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLFNBQVMsQ0FBQztZQUN0QixRQUFRLEVBQUUsSUFBSSxDQUFDLFVBQVU7U0FDMUIsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQ3JCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7U0FDMUM7YUFBTTtZQUNMLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1NBQ25DO0tBQ0Y7Ozs7OztJQUdELFdBQVcsQ0FBQyxFQUFVLEVBQUUsYUFBdUI7UUFDN0MsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUM7O1FBQ3hCLElBQUksSUFBSSxDQUFzQjtRQUM5QixJQUFJLElBQUksQ0FBQyxhQUFhLElBQUssYUFBYSxLQUFLLElBQUksRUFBRTtZQUNqRCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDO2lCQUN0QixJQUFJLENBQUMsUUFBUTtnQkFDWixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2FBQzVDLENBQUM7aUJBQ0QsSUFBSSxDQUFDLENBQUMsTUFBMkI7Z0JBQ2hDLElBQUksR0FBRyxNQUFNLENBQUM7Z0JBQ2QsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssS0FBSyxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUMxRixDQUFDO2lCQUNELElBQUksQ0FBQztnQkFDSixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQzthQUN6QixDQUFDO2lCQUNELEtBQUssQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1NBQ3JEO2FBQU07WUFDTCxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsV0FBVyxFQUFFLEVBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxLQUFLLElBQUksRUFBQyxFQUFDLENBQUM7aUJBQzNHLElBQUksQ0FBQztnQkFDSixPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUMsQ0FBQzthQUNsQyxDQUFDO2lCQUNELElBQUksQ0FBQyxRQUFRO2dCQUNaLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsQ0FBQzthQUMvQyxDQUFDO2lCQUNELEtBQUssQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1NBQ3JEO0tBQ0Y7Ozs7OztJQUVELGdCQUFnQixDQUFDLEtBQWlCLEVBQUUsVUFBbUI7UUFDckQsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksS0FBSyxDQUFDLFlBQVksQ0FBQyxFQUFFO1lBQ3pDLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQ3RDLElBQUksQ0FBQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO2lCQUNqRCxJQUFJLENBQUMsT0FBTztnQkFDWCxLQUFLLENBQUMsU0FBUyxDQUFDLEdBQUcsT0FBTyxDQUFDO2dCQUMzQixLQUFLLENBQUMsb0JBQW9CLENBQUMsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO2dCQUNqRSxLQUFLLENBQUMscUJBQXFCLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxFQUFFLEtBQUssVUFBVSxDQUFDLENBQUM7Z0JBQ3ZFLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO2dCQUN6QixJQUFJLENBQUMsTUFBTSxHQUFHLGFBQWEsQ0FBQzthQUM3QixDQUFDLENBQUM7WUFDTCxPQUFPO1NBQ1I7UUFDRCxRQUFRLEtBQUssQ0FBQyxJQUFJO1lBQ2hCLEtBQUssOEJBQThCLENBQUM7WUFDcEMsS0FBSywyQkFBMkI7Z0JBQzlCLElBQUksQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDO2dCQUN0QixNQUFNO1lBQ1IsS0FBSyxvQkFBb0I7Z0JBQ3ZCLElBQUksQ0FBQyxXQUFXLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUNuQyxNQUFNO1lBQ1I7Z0JBQ0UsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ3ZCLE1BQU07U0FDVDtLQUNGOzs7OztJQUVELGdCQUFnQixDQUFDLEVBQVU7O1FBQ3pCLElBQUksUUFBUSxHQUFzQixJQUFJLENBQUM7UUFDdkMsSUFBSSxJQUFJLENBQUMsb0JBQW9CLEVBQUU7WUFDN0IsUUFBUSxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxFQUFFLENBQUMsQ0FBQztTQUMxQztRQUNELElBQUksQ0FBRSxRQUFRLEVBQUU7WUFDZCxRQUFRLEVBQUU7Z0JBQ1IsS0FBSyxhQUFhO29CQUNoQixRQUFRLEdBQUcsSUFBSSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztvQkFDMUMsTUFBTTtnQkFDUixLQUFLLGNBQWM7b0JBQ2pCLFFBQVEsR0FBRyxJQUFJLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO29CQUMzQyxNQUFNO2dCQUNSLEtBQUssWUFBWTtvQkFDZixRQUFRLEdBQUcsSUFBSSxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztvQkFDekMsTUFBTTtnQkFDUixLQUFLLFlBQVk7b0JBQ2YsUUFBUSxHQUFHLElBQUksSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7b0JBQ3pDLE1BQU07YUFDVDtTQUNGO1FBQ0QsSUFBSSxRQUFRLEVBQUU7WUFDWixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7U0FDbEM7YUFBTTtZQUNMLE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQztnQkFDcEIsSUFBSSxFQUFFLHFDQUFxQztnQkFDM0MsT0FBTyxFQUFFLDBEQUEwRCxFQUFFLElBQUk7YUFDMUUsQ0FBQyxDQUFDO1NBQ0o7S0FDRjs7O1lBdFBGLFNBQVMsU0FBQztnQkFDVCxRQUFRLEVBQUUsaUNBQWlDO2dCQUMzQyxRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0FpR1g7Z0JBQ0MsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDO2dCQUNaLFVBQVUsRUFBRSxDQUFFLGVBQWUsQ0FBRTthQUNoQzs7OztZQWhIUSxlQUFlO1lBTWYsc0JBQXNCO1lBTHRCLGNBQWM7WUFBRSxNQUFNOzs7eUJBa0g1QixLQUFLOzJCQUNMLEtBQUs7NEJBQ0wsS0FBSzttQ0FDTCxLQUFLO29CQUNMLEtBQUs7dUJBQ0wsS0FBSztzQkFDTCxNQUFNOzBCQUNOLE1BQU07NkJBQ04sTUFBTTtvQkFDTixNQUFNOzs7Ozs7O0FDN0hUOzs7WUFPQyxRQUFRLFNBQUM7Z0JBQ1IsT0FBTyxFQUFFO29CQUNQLFlBQVk7aUJBQ2I7Z0JBQ0QsU0FBUyxFQUFFO29CQUNULHNCQUFzQjtpQkFDdkI7YUFDRjs7Ozs7OztBQ2REOzs7WUFhQyxRQUFRLFNBQUM7Z0JBQ1IsT0FBTyxFQUFFO29CQUNQLFlBQVk7b0JBQ1osbUJBQW1CO29CQUNuQixZQUFZO29CQUNaLHFCQUFxQjtpQkFDdEI7Z0JBQ0QsWUFBWSxFQUFFO29CQUNaLGVBQWU7b0JBQ2YsMEJBQTBCO29CQUMxQixtQkFBbUI7b0JBQ25CLG1CQUFtQjtvQkFDbkIsOEJBQThCO29CQUM5QixvQkFBb0I7aUJBQ3JCO2dCQUNELE9BQU8sRUFBRTtvQkFDUCxlQUFlO2lCQUNoQjthQUNGOzs7Ozs7O0FDL0JEOzs7OztJQXNKRSxZQUNVLFNBQ0U7UUFERixZQUFPLEdBQVAsT0FBTztRQUNMLGlCQUFZLEdBQVosWUFBWTt1QkFkc0MsSUFBSSxZQUFZLEVBQUU7c0JBRWhDLE1BQU07MEJBRXpDLEtBQUs7c0JBQ1QsdUNBQXVDOzhCQUtuQixJQUFJO29CQUNMLElBQUk7S0FJM0I7Ozs7SUFFTCxJQUFJLElBQUk7UUFDTixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO0tBQzFCOzs7O0lBQ0QsSUFBSSxXQUFXO1FBQ2IsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO0tBQzFCOzs7O0lBRUQsUUFBUTs7UUFDTixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ3BELElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDbkMsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLFdBQVcsQ0FBQyxFQUFFLEVBQUUsRUFBQyxVQUFVLEVBQUUsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLEVBQUMsQ0FBQyxDQUFDO1FBQzNFLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxXQUFXLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3ZELElBQUksQ0FBQyxFQUFFLEdBQUcsSUFBSSxTQUFTLENBQUMsRUFBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQzthQUNwQyxJQUFJLENBQUMsQ0FBQyxNQUEyQjtZQUNoQyxJQUFJLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQztZQUNuQixJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3pDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1NBQ3RCLENBQUM7YUFDRCxLQUFLLENBQUMsQ0FBQyxLQUFpQjtZQUN2QixJQUFJLENBQUMsY0FBYyxHQUFHLEtBQUssQ0FBQztZQUM1QixJQUFJLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQztTQUN2QixDQUFDLENBQUM7S0FDTjs7OztJQUVELE1BQU07UUFDSixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztRQUN2QixJQUFJLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUM7YUFDaEUsSUFBSSxDQUFDO1lBQ0osT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLDBCQUEwQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQzFGLENBQUM7YUFDRCxJQUFJLENBQUMsQ0FBQyxJQUF5QjtZQUM5QixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztZQUNqQixPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxLQUFLLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUM3RixDQUFDO2FBQ0QsSUFBSSxDQUFDO1lBQ0osSUFBSSxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUM7WUFDeEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7Z0JBQ2hCLElBQUksRUFBRSxlQUFlO2dCQUNyQixJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUk7Z0JBQ2YsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO2dCQUNmLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUk7YUFDckIsQ0FBQyxDQUFDO1NBQ0osQ0FBQzthQUNELEtBQUssQ0FBQyxDQUFDLEtBQWlCO1lBQ3ZCLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO1lBQ3hCLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDOUIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUNoQyxRQUFRLEtBQUssQ0FBQyxJQUFJO2dCQUNoQixLQUFLLG9CQUFvQjtvQkFDdkIseUJBQXlCLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7b0JBQzVFLE1BQU07Z0JBQ1I7b0JBQ0UsSUFBSSxDQUFDLGNBQWMsR0FBRyxLQUFLLENBQUM7b0JBQzVCLElBQUksQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDO29CQUN0QixNQUFNO2FBQ1Q7U0FDRixDQUFDLENBQUM7S0FDTjs7O1lBNU1GLFNBQVMsU0FBQztnQkFDVCxRQUFRLEVBQUUsc0NBQXNDO2dCQUNoRCxRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQXdIWDtnQkFDQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQ1osVUFBVSxFQUFFLENBQUMsZUFBZSxDQUFDO2FBQzlCOzs7O1lBcElRLGVBQWU7WUFJZixzQkFBc0I7OztzQkFtSTVCLEtBQUs7c0JBQ0wsTUFBTTs7Ozs7OztBQzFJVDs7OztJQXdGRSxZQUNVO1FBQUEsWUFBTyxHQUFQLE9BQU87dUJBUjZDLElBQUksWUFBWSxFQUFFO3NCQUVoQyxNQUFNOzBCQUV6QyxLQUFLO0tBS2I7Ozs7SUFFTCxJQUFJLElBQUk7UUFDTixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO0tBQzFCOzs7O0lBRUQsUUFBUTtRQUVOLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7YUFDcEMsSUFBSSxDQUFDLENBQUMsTUFBMkI7WUFDaEMsSUFBSSxDQUFDLElBQUksR0FBRyxNQUFNLENBQUM7WUFDbkIsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7U0FDdEIsQ0FBQzthQUNELEtBQUssQ0FBQyxDQUFDLEtBQWlCO1lBQ3ZCLElBQUksQ0FBQyxjQUFjLEdBQUcsS0FBSyxDQUFDO1lBQzVCLElBQUksQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDO1NBQ3ZCLENBQUMsQ0FBQztLQUNOOzs7O0lBRUQsTUFBTTtRQUNKLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7YUFDcEMsSUFBSSxDQUFDO1lBQ0osSUFBSSxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUM7WUFDeEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7Z0JBQ2hCLElBQUksRUFBRSxjQUFjO2dCQUNwQixJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUk7Z0JBQ2YsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVzthQUM1QixDQUFDLENBQUM7U0FDSixDQUFDO2FBQ0QsS0FBSyxDQUFDLENBQUMsS0FBaUI7WUFDdkIsSUFBSSxDQUFDLGNBQWMsR0FBRyxLQUFLLENBQUM7WUFDNUIsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUM7U0FDdkIsQ0FBQyxDQUFDO0tBQ047OztZQXBIRixTQUFTLFNBQUM7Z0JBQ1QsUUFBUSxFQUFFLHFDQUFxQztnQkFDL0MsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQWlFWDtnQkFDQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQ1osVUFBVSxFQUFFLENBQUMsZUFBZSxDQUFDO2FBQzlCOzs7O1lBM0VRLGVBQWU7OztzQkE4RXJCLEtBQUs7c0JBQ0wsTUFBTTs7Ozs7OztBQ2pGVDs7OztJQWtFRSxZQUNVO1FBQUEsWUFBTyxHQUFQLE9BQU87dUJBUjZDLElBQUksWUFBWSxFQUFFO3NCQUV6QyxNQUFNOzBCQUVoQyxLQUFLO0tBS2I7Ozs7SUFFTCxJQUFJLElBQUk7UUFDTixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO0tBQzFCOzs7O0lBRUQsUUFBUTtRQUVOLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7YUFDcEMsSUFBSSxDQUFDLENBQUMsTUFBMkI7WUFDaEMsSUFBSSxDQUFDLElBQUksR0FBRyxNQUFNLENBQUM7WUFDbkIsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7U0FDaEQsQ0FBQzthQUNELElBQUksQ0FBQztZQUNKLElBQUksQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDO1lBQ3hCLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO2dCQUNoQixJQUFJLEVBQUUsYUFBYTtnQkFDbkIsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO2dCQUNmLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVc7YUFDNUIsQ0FBQyxDQUFDO1NBQ0osQ0FBQzthQUNELEtBQUssQ0FBQyxDQUFDLEtBQWlCO1lBQ3ZCLElBQUksQ0FBQyxjQUFjLEdBQUcsS0FBSyxDQUFDO1lBQzVCLElBQUksQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDO1NBQ3ZCLENBQUMsQ0FBQztLQUNOOzs7WUF0RkYsU0FBUyxTQUFDO2dCQUNULFFBQVEsRUFBRSxvQ0FBb0M7Z0JBQzlDLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQTJDWDtnQkFDQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQ1osVUFBVSxFQUFFLENBQUMsZUFBZSxDQUFDO2FBQzlCOzs7O1lBckRRLGVBQWU7OztzQkF3RHJCLEtBQUs7c0JBQ0wsTUFBTTs7Ozs7OztBQzNEVDs7O1lBWUMsUUFBUSxTQUFDO2dCQUNSLE9BQU8sRUFBRTtvQkFDUCxZQUFZO29CQUNaLG1CQUFtQjtvQkFDbkIsWUFBWTtvQkFDWixxQkFBcUI7aUJBQ3RCO2dCQUNELFlBQVksRUFBRTtvQkFDWixZQUFZO29CQUNaLHdCQUF3QjtvQkFDeEIseUJBQXlCO29CQUN6Qix1QkFBdUI7aUJBQ3hCO2dCQUNELE9BQU8sRUFBRTtvQkFDUCxZQUFZO2lCQUNiO2FBQ0Y7Ozs7Ozs7Ozs7Ozs7OzsifQ==