@lifeintelligencegroup/ngx-lig-ari
Version:
Life Intelligence Group Artificial Intelligence
393 lines • 51.2 kB
JavaScript
import { Injectable, Inject } from '@angular/core';
import { HttpHeaders } from '@angular/common/http';
import { Subject, BehaviorSubject, timer, } from 'rxjs';
import { map, takeUntil, catchError, startWith, switchMap, } from 'rxjs/operators';
import { AriConfigService } from '../model/ari-bot.mode';
import 'moment-timezone';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common/http";
import * as i2 from "./pubsub.service";
import * as i3 from "./common.service";
const baseUrl = 'https://directline.botframework.com/v3/directline/conversations';
// const baseUrl =
// 'http://localhost:62114/api/messages';
export class AriBotService {
constructor(httpClient, pubsub, commonService, config) {
this.httpClient = httpClient;
this.pubsub = pubsub;
this.commonService = commonService;
this.config = config;
this.unsubscribe$ = new Subject();
this.ariCreds$ = new Subject();
// tslint:disable-next-line: variable-name
this._botResponse$ = new BehaviorSubject(null);
this.hasInitializedConversation = false;
this.hasConversations = false;
this.reset$ = new Subject();
this.initMessage = {};
this.assistantName = 'Ari';
this.locationAccess$ = new Subject();
if (config.settings) {
this.assistantName = config.settings.assistantName;
this.auth = config.settings.auth;
this.project = config.settings.project;
this.baseUrlproject = config.settings.baseUrl;
}
this.ariCreds$.pipe(takeUntil(this.unsubscribe$)).subscribe((creds) => {
if (creds) {
this.subscribeToConversations();
}
});
}
get locationStatusChanged() {
return this.locationAccess$.asObservable();
}
botResponse$() {
return this._botResponse$.asObservable();
}
ariTimeout() {
this.timer$ = this.reset$.pipe(startWith(0), switchMap(() => timer(0, 1000)) // 1000 = 1sec
);
this.subscription = this.timer$.subscribe((i) => {
/// 5 Minutes reset the timer and close ari and show "I have not heard from you for a while so I presume that you are busy. Call me again when you are ready. Goodbye."
if (i == 600) {
// 300 secs = 5 minutes
this.subscription.unsubscribe();
this.pubsub.$pub('ARI-TIMEOUT', true);
}
});
}
refreshTimer() {
this.reset$.next(0);
}
stopTimer() {
this.subscription.unsubscribe();
}
subscribeToConversations() {
let emptyConversationId;
let hasEmptyConversation = false;
this.hasConversations = true;
return this.getConversations()
.pipe(map((conversations) => {
const { activities } = conversations;
conversations.activities = activities.filter((activity) => {
if (activity.from.Token && activity.from.RefreshToken) {
this.commonService.updateUserObject(activity.from.Token, activity.from.RefreshToken);
}
if ((activity.text || activity.replyToId !== emptyConversationId) &&
hasEmptyConversation === false) {
return activity;
}
if (!activity.text) {
emptyConversationId = activity.id;
hasEmptyConversation = true;
activity.hasEmptyConversation = true;
}
else {
hasEmptyConversation = false;
activity.hasEmptyConversation = false;
}
});
return conversations;
}), catchError((error) => {
this.pubsub.$pub('ARI-ERROR', error);
this.pubsub.$pub('ARI-LOADING-DONE');
return error.error;
}), takeUntil(this.unsubscribe$))
.subscribe((response) => {
if (response) {
const getAllActivities = this.initMessage.activities
? this.initMessage.activities.concat(response.activities)
: response.activities;
const validActivities = getAllActivities.filter((item) => {
if (item.id) {
return item;
}
});
const dataResponse = {
activities: validActivities,
watermark: response.watermark,
};
this._botResponse$.next(dataResponse);
}
});
}
getConversations() {
const { conversationId } = this.ariCreds;
const url = `${baseUrl}/${conversationId}/activities`;
const headers = this.conversationHeader;
return this.httpClient.get(url, {
headers,
});
}
paginateTasks(params) {
const url = `${this.baseUrlproject}/api/ari/tasks`;
const header = this.commonStateChangeHeaders();
return this.httpClient.get(url, {
headers: header,
params: params,
});
}
getInitialWelcomeMessage() {
const auth = JSON.parse(localStorage.getItem(this.auth));
let params = {};
if (auth) {
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
params = {
RefreshToken: auth.RefreshToken,
TimeZone: auth.timeZone ? auth.timeZone : timeZone,
Project: this.project,
Location: auth.location
? auth.location
: timeZone.substring(timeZone.indexOf('/') + 1, timeZone.length),
};
// if (auth.lat || auth.long) {
// params.Lat = auth.lat;
// params.Long = auth.long;
// }
}
else {
params = {
...JSON.parse(localStorage.getItem('temp_user')),
};
}
const url = `${this.baseUrlproject}/api/ari/welcome`;
const header = this.commonStateChangeHeaders();
return this.httpClient.get(url, {
headers: header,
params: params,
});
}
commonStateChangeHeaders() {
let headers;
if (JSON.parse(localStorage.getItem(this.auth))) {
headers = {
'Content-Type': 'application/json',
Accept: 'application/json',
Authorization: `Bearer ${JSON.parse(localStorage.getItem(this.auth)).Token}`,
};
}
else {
headers = {
'Content-Type': 'application/json',
Accept: 'application/json',
};
}
return new HttpHeaders(headers);
}
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
// INIT CONVERSATION
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
get initHeaders() {
return new HttpHeaders({
'Content-Type': 'application/json',
Accept: 'application/json',
Authorization: `Bearer ${this.config.apiSecret}`,
});
}
getWelcomeMessage(locationPermission) {
// -------------------------------------------
// To get user current location (long and lat) conditionally then call welcome message
const oldAuthStorage = JSON.parse(localStorage.getItem(this.auth ? this.auth : 'temp_user'));
const addToAuthStorage = {
...oldAuthStorage,
};
const callWelcomeMessage = () => {
this.getInitialWelcomeMessage().subscribe((res) => {
if (res) {
this.initMessage = res;
this._botResponse$.next(res);
}
});
};
if (locationPermission) {
// If Location access is allowed ( Completely remove for now )
const success = (pos) => {
this.currentLocation = {
long: pos.coords.longitude,
lat: pos.coords.latitude,
};
if (this.currentLocation) {
addToAuthStorage.lat = this.currentLocation.lat;
addToAuthStorage.long = this.currentLocation.long;
}
localStorage.setItem(this.auth ? this.auth : 'temp_user', JSON.stringify(addToAuthStorage));
callWelcomeMessage();
};
navigator.geolocation.getCurrentPosition(success);
}
else {
// if Location access is not allowed
delete addToAuthStorage.lat;
delete addToAuthStorage.long;
localStorage.setItem(this.auth ? this.auth : 'temp_user', JSON.stringify(addToAuthStorage));
callWelcomeMessage();
}
}
initConversation() {
this.pubsub.$pub('ARI-LOADING');
// GET INITIAL MESSAGE FROM PROJECT API
const headers = this.initHeaders;
this.httpClient.post(baseUrl, {}, { headers }).subscribe((response) => {
this.ariCreds = response;
this.ariBotConversationId = this.ariCreds.conversationId;
const oldAuthStorage = JSON.parse(localStorage.getItem(this.auth ? this.auth : 'temp_user'));
const addToAuthStorage = {
...oldAuthStorage,
conversationId: this.ariBotConversationId,
conversionToken: this.ariCreds.token,
};
localStorage.setItem(this.auth ? this.auth : 'temp_user', JSON.stringify(addToAuthStorage));
localStorage.setItem('AriCreds', JSON.stringify(response));
this.pubsub.$pub('ARI-LOADING-DONE');
this.hasInitializedConversation = true;
this.getWelcomeMessage(false);
}, (error) => {
console.error('AriBot Error: ', error);
this.pubsub.$pub('ARI-ERROR', error);
this.pubsub.$pub('ARI-LOADING-DONE');
});
}
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
// SEND MESSAGE
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
get conversationHeader() {
if (!this.ariCreds) {
this.ariCreds = localStorage.getItem('AriCreds');
this.ariCreds$.next(this.ariCreds);
}
const { token } = this.ariCreds;
return new HttpHeaders({
'Content-Type': 'application/json',
Accept: 'application/json',
Authorization: `Bearer ${token}`,
});
}
sendMessage(message) {
const { type } = message;
const { from, text } = message;
const body = {
type: type || 'message',
from,
text,
};
this.pubsub.$pub('ARI-LOADING');
if (this.ariCreds) {
const { conversationId } = this.ariCreds;
const headers = this.conversationHeader;
const url = `${baseUrl}/${conversationId}/activities`;
this.httpClient.post(url, body, { headers }).subscribe((response) => {
if (response) {
this.subscribeToConversations();
this.pubsub.$pub('ARI-LOADING-DONE');
}
}, (error) => {
console.error('AriBot Error: ', error);
this.pubsub.$pub('ARI-ERROR', error);
this.pubsub.$pub('ARI-LOADING-DONE');
});
}
else {
this.pubsub.$pub('ARI-LOADING-DONE');
}
}
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
// TASK ACTIONS
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
taskActionMoveTo(payload) {
const params = {
...payload,
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
};
const url = `${this.baseUrlproject}/api/tasks/move`;
const header = this.commonStateChangeHeaders();
return this.httpClient.put(url, params, {
headers: header,
});
}
taskMoveTo(payload) {
return new Promise((resolve, reject) => {
this.taskActionMoveTo(payload).subscribe((res) => {
resolve(res ? res : null);
}, (err) => {
resolve(err.error);
});
});
}
taskActionTrash(id) {
const url = `${this.baseUrlproject}/api/tasks/${id}`;
const header = this.commonStateChangeHeaders();
return this.httpClient.delete(url, {
headers: header,
});
}
taskTrash(id) {
return new Promise((resolve, reject) => {
this.taskActionTrash(id).subscribe((res) => {
resolve(true);
}, (err) => {
resolve(false);
});
});
}
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
// RESET
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
// -----------------------------------
resetConversation() {
this._botResponse$.next(null);
}
ngOnDestroy() {
this.resetConversation();
this.unsubscribe$.next();
this.unsubscribe$.complete();
}
}
AriBotService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.4", ngImport: i0, type: AriBotService, deps: [{ token: i1.HttpClient }, { token: i2.PubsubService }, { token: i3.CommonService }, { token: AriConfigService }], target: i0.ɵɵFactoryTarget.Injectable });
AriBotService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.4", ngImport: i0, type: AriBotService, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.4", ngImport: i0, type: AriBotService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: i2.PubsubService }, { type: i3.CommonService }, { type: undefined, decorators: [{
type: Inject,
args: [AriConfigService]
}] }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJpLWJvdC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWxpZy1hcmkvc3JjL2xpYi9zZXJ2aWNlcy9hcmktYm90LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBYSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDOUQsT0FBTyxFQUFjLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQy9ELE9BQU8sRUFDTCxPQUFPLEVBRVAsZUFBZSxFQUNmLEtBQUssR0FFTixNQUFNLE1BQU0sQ0FBQztBQUtkLE9BQU8sRUFDTCxHQUFHLEVBQ0gsU0FBUyxFQUNULFVBQVUsRUFDVixTQUFTLEVBQ1QsU0FBUyxHQUNWLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUFhLGdCQUFnQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFcEUsT0FBTyxpQkFBaUIsQ0FBQzs7Ozs7QUFJekIsTUFBTSxPQUFPLEdBQ1gsaUVBQWlFLENBQUM7QUFDcEUsa0JBQWtCO0FBQ2xCLDJDQUEyQztBQUszQyxNQUFNLE9BQU8sYUFBYTtJQXVCeEIsWUFDVSxVQUFzQixFQUN0QixNQUFxQixFQUNyQixhQUE0QixFQUNGLE1BQWlCO1FBSDNDLGVBQVUsR0FBVixVQUFVLENBQVk7UUFDdEIsV0FBTSxHQUFOLE1BQU0sQ0FBZTtRQUNyQixrQkFBYSxHQUFiLGFBQWEsQ0FBZTtRQUNGLFdBQU0sR0FBTixNQUFNLENBQVc7UUExQjdDLGlCQUFZLEdBQUcsSUFBSSxPQUFPLEVBQU8sQ0FBQztRQUdsQyxjQUFTLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUNsQywwQ0FBMEM7UUFDbEMsa0JBQWEsR0FBeUIsSUFBSSxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDeEUsK0JBQTBCLEdBQUcsS0FBSyxDQUFDO1FBQ25DLHFCQUFnQixHQUFHLEtBQUssQ0FBQztRQUNqQixXQUFNLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQU0vQixnQkFBVyxHQUFRLEVBQUUsQ0FBQztRQUN0QixrQkFBYSxHQUFHLEtBQUssQ0FBQztRQUdmLG9CQUFlLEdBQUcsSUFBSSxPQUFPLEVBQVcsQ0FBQztRQVU5QyxJQUFJLE1BQU0sQ0FBQyxRQUFRLEVBQUU7WUFDbkIsSUFBSSxDQUFDLGFBQWEsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQztZQUNuRCxJQUFJLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDO1lBQ2pDLElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7WUFDdkMsSUFBSSxDQUFDLGNBQWMsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQztTQUMvQztRQUNELElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUNwRSxJQUFJLEtBQUssRUFBRTtnQkFDVCxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQzthQUNqQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQXBCRCxJQUFJLHFCQUFxQjtRQUN2QixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDN0MsQ0FBQztJQW9CRCxZQUFZO1FBQ1YsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQzNDLENBQUM7SUFDRCxVQUFVO1FBQ1IsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FDNUIsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUNaLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsY0FBYztTQUMvQyxDQUFDO1FBQ0YsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO1lBQzlDLHVLQUF1SztZQUN2SyxJQUFJLENBQUMsSUFBSSxHQUFHLEVBQUU7Z0JBQ1osdUJBQXVCO2dCQUN2QixJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNoQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLENBQUM7YUFDdkM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFDRCxZQUFZO1FBQ1YsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdEIsQ0FBQztJQUNELFNBQVM7UUFDUCxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ2xDLENBQUM7SUFDRCx3QkFBd0I7UUFDdEIsSUFBSSxtQkFBbUIsQ0FBQztRQUN4QixJQUFJLG9CQUFvQixHQUFHLEtBQUssQ0FBQztRQUNqQyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO1FBRTdCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixFQUFFO2FBQzNCLElBQUksQ0FDSCxHQUFHLENBQUMsQ0FBQyxhQUFhLEVBQUUsRUFBRTtZQUNwQixNQUFNLEVBQUUsVUFBVSxFQUFFLEdBQUcsYUFBYSxDQUFDO1lBQ3JDLGFBQWEsQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDLFFBQWEsRUFBRSxFQUFFO2dCQUU3RCxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFO29CQUNyRCxJQUFJLENBQUMsYUFBYSxDQUFDLGdCQUFnQixDQUNqQyxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssRUFDbkIsUUFBUSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQzNCLENBQUM7aUJBQ0g7Z0JBQ0QsSUFDRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLElBQUksUUFBUSxDQUFDLFNBQVMsS0FBSyxtQkFBbUIsQ0FBQztvQkFDN0Qsb0JBQW9CLEtBQUssS0FBSyxFQUM5QjtvQkFDQSxPQUFPLFFBQVEsQ0FBQztpQkFDakI7Z0JBRUQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUU7b0JBQ2xCLG1CQUFtQixHQUFHLFFBQVEsQ0FBQyxFQUFFLENBQUM7b0JBQ2xDLG9CQUFvQixHQUFHLElBQUksQ0FBQztvQkFDNUIsUUFBUSxDQUFDLG9CQUFvQixHQUFHLElBQUksQ0FBQztpQkFDdEM7cUJBQU07b0JBQ0wsb0JBQW9CLEdBQUcsS0FBSyxDQUFDO29CQUM3QixRQUFRLENBQUMsb0JBQW9CLEdBQUcsS0FBSyxDQUFDO2lCQUN2QztZQUNILENBQUMsQ0FBQyxDQUFDO1lBQ0gsT0FBTyxhQUFhLENBQUM7UUFDdkIsQ0FBQyxDQUFDLEVBQ0YsVUFBVSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDbkIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3JDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUM7WUFDckMsT0FBTyxLQUFLLENBQUMsS0FBSyxDQUFDO1FBQ3JCLENBQUMsQ0FBQyxFQUNGLFNBQVMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQzdCO2FBQ0EsU0FBUyxDQUFDLENBQUMsUUFBYSxFQUFFLEVBQUU7WUFDM0IsSUFBSSxRQUFRLEVBQUU7Z0JBQ1osTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLFVBQVU7b0JBQ2xELENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQztvQkFDekQsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUM7Z0JBQ3hCLE1BQU0sZUFBZSxHQUFHLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO29CQUN2RCxJQUFJLElBQUksQ0FBQyxFQUFFLEVBQUU7d0JBQ1gsT0FBTyxJQUFJLENBQUM7cUJBQ2I7Z0JBQ0gsQ0FBQyxDQUFDLENBQUM7Z0JBQ0gsTUFBTSxZQUFZLEdBQUc7b0JBQ25CLFVBQVUsRUFBRSxlQUFlO29CQUMzQixTQUFTLEVBQUUsUUFBUSxDQUFDLFNBQVM7aUJBQzlCLENBQUM7Z0JBQ0YsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7YUFDdkM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFTyxnQkFBZ0I7UUFDdEIsTUFBTSxFQUFFLGNBQWMsRUFBRSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7UUFDekMsTUFBTSxHQUFHLEdBQUcsR0FBRyxPQUFPLElBQUksY0FBYyxhQUFhLENBQUM7UUFDdEQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDO1FBRXhDLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQTBCLEdBQUcsRUFBRTtZQUN2RCxPQUFPO1NBQ1IsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLGFBQWEsQ0FBQyxNQUFXO1FBQzlCLE1BQU0sR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLGNBQWMsZ0JBQWdCLENBQUM7UUFDbkQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLHdCQUF3QixFQUFFLENBQUM7UUFDL0MsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUU7WUFDOUIsT0FBTyxFQUFFLE1BQU07WUFDZixNQUFNLEVBQUUsTUFBTTtTQUNmLENBQUMsQ0FBQztJQUNMLENBQUM7SUFDTyx3QkFBd0I7UUFDOUIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBRXpELElBQUksTUFBTSxHQUFRLEVBQUUsQ0FBQztRQUNyQixJQUFJLElBQUksRUFBRTtZQUNSLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxRQUFRLENBQUM7WUFDbEUsTUFBTSxHQUFHO2dCQUNQLFlBQVksRUFBRSxJQUFJLENBQUMsWUFBWTtnQkFDL0IsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVE7Z0JBQ2xELE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTztnQkFDckIsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRO29CQUNyQixDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVE7b0JBQ2YsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsUUFBUSxDQUFDLE1BQU0sQ0FBQzthQUNuRSxDQUFDO1lBQ0YsK0JBQStCO1lBQy9CLDJCQUEyQjtZQUMzQiw2QkFBNkI7WUFDN0IsSUFBSTtTQUNMO2FBQU07WUFDTCxNQUFNLEdBQUc7Z0JBQ1AsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7YUFDakQsQ0FBQztTQUNIO1FBQ0QsTUFBTSxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUMsY0FBYyxrQkFBa0IsQ0FBQztRQUNyRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztRQUMvQyxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRTtZQUM5QixPQUFPLEVBQUUsTUFBTTtZQUNmLE1BQU0sRUFBRSxNQUFNO1NBQ2YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVTLHdCQUF3QjtRQUNoQyxJQUFJLE9BQVksQ0FBQztRQUNqQixJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRTtZQUMvQyxPQUFPLEdBQUc7Z0JBQ1IsY0FBYyxFQUFFLGtCQUFrQjtnQkFDbEMsTUFBTSxFQUFFLGtCQUFrQjtnQkFDMUIsYUFBYSxFQUFFLFVBQVUsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQ25FLEVBQUU7YUFDTCxDQUFDO1NBQ0g7YUFBTTtZQUNMLE9BQU8sR0FBRztnQkFDUixjQUFjLEVBQUUsa0JBQWtCO2dCQUNsQyxNQUFNLEVBQUUsa0JBQWtCO2FBQzNCLENBQUM7U0FDSDtRQUNELE9BQU8sSUFBSSxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDbEMsQ0FBQztJQUVELHNDQUFzQztJQUN0QyxzQ0FBc0M7SUFDdEMsc0NBQXNDO0lBQ3RDLHNDQUFzQztJQUN0QyxzQ0FBc0M7SUFDdEMsc0NBQXNDO0lBQ3RDLG9CQUFvQjtJQUNwQixzQ0FBc0M7SUFDdEMsc0NBQXNDO0lBQ3RDLHNDQUFzQztJQUN0QyxzQ0FBc0M7SUFDdEMsc0NBQXNDO0lBQ3RDLHNDQUFzQztJQUN0QyxJQUFJLFdBQVc7UUFDYixPQUFPLElBQUksV0FBVyxDQUFDO1lBQ3JCLGNBQWMsRUFBRSxrQkFBa0I7WUFDbEMsTUFBTSxFQUFFLGtCQUFrQjtZQUMxQixhQUFhLEVBQUUsVUFBVSxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRTtTQUNqRCxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsaUJBQWlCLENBQUMsa0JBQTRCO1FBQzVDLDhDQUE4QztRQUM5QyxzRkFBc0Y7UUFDdEYsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FDL0IsWUFBWSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FDMUQsQ0FBQztRQUNGLE1BQU0sZ0JBQWdCLEdBQUc7WUFDdkIsR0FBRyxjQUFjO1NBQ2xCLENBQUM7UUFFRixNQUFNLGtCQUFrQixHQUFHLEdBQUcsRUFBRTtZQUM5QixJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxHQUFRLEVBQUUsRUFBRTtnQkFDckQsSUFBSSxHQUFHLEVBQUU7b0JBQ1AsSUFBSSxDQUFDLFdBQVcsR0FBRyxHQUFHLENBQUM7b0JBQ3ZCLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2lCQUM5QjtZQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDO1FBQ0YsSUFBSSxrQkFBa0IsRUFBRTtZQUN0Qiw4REFBOEQ7WUFDOUQsTUFBTSxPQUFPLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRTtnQkFDdEIsSUFBSSxDQUFDLGVBQWUsR0FBRztvQkFDckIsSUFBSSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsU0FBUztvQkFDMUIsR0FBRyxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsUUFBUTtpQkFDekIsQ0FBQztnQkFDRixJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUU7b0JBQ3hCLGdCQUFnQixDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQztvQkFDaEQsZ0JBQWdCLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDO2lCQUNuRDtnQkFDRCxZQUFZLENBQUMsT0FBTyxDQUNsQixJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQ25DLElBQUksQ0FBQyxTQUFTLENBQUMsZ0JBQWdCLENBQUMsQ0FDakMsQ0FBQztnQkFDRixrQkFBa0IsRUFBRSxDQUFDO1lBQ3ZCLENBQUMsQ0FBQztZQUNGLFNBQVMsQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUM7U0FDbkQ7YUFBTTtZQUNMLG9DQUFvQztZQUNwQyxPQUFPLGdCQUFnQixDQUFDLEdBQUcsQ0FBQztZQUM1QixPQUFPLGdCQUFnQixDQUFDLElBQUksQ0FBQztZQUM3QixZQUFZLENBQUMsT0FBTyxDQUNsQixJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQ25DLElBQUksQ0FBQyxTQUFTLENBQUMsZ0JBQWdCLENBQUMsQ0FDakMsQ0FBQztZQUNGLGtCQUFrQixFQUFFLENBQUM7U0FDdEI7SUFDSCxDQUFDO0lBQ0QsZ0JBQWdCO1FBQ2QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDaEMsdUNBQXVDO1FBQ3ZDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7UUFDakMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUMsU0FBUyxDQUN0RCxDQUFDLFFBQWEsRUFBRSxFQUFFO1lBQ2hCLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO1lBQ3pCLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQztZQUN6RCxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUMvQixZQUFZLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUMxRCxDQUFDO1lBQ0YsTUFBTSxnQkFBZ0IsR0FBRztnQkFDdkIsR0FBRyxjQUFjO2dCQUNqQixjQUFjLEVBQUUsSUFBSSxDQUFDLG9CQUFvQjtnQkFDekMsZUFBZSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSzthQUNyQyxDQUFDO1lBQ0YsWUFBWSxDQUFDLE9BQU8sQ0FDbEIsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUNuQyxJQUFJLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLENBQ2pDLENBQUM7WUFDRixZQUFZLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFDM0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQztZQUNyQyxJQUFJLENBQUMsMEJBQTBCLEdBQUcsSUFBSSxDQUFDO1lBRXZDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNoQyxDQUFDLEVBQ0QsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUNSLE9BQU8sQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDdkMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3JDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDdkMsQ0FBQyxDQUNGLENBQUM7SUFDSixDQUFDO0lBQ0Qsc0NBQXNDO0lBQ3RDLHNDQUFzQztJQUN0QyxzQ0FBc0M7SUFDdEMsc0NBQXNDO0lBQ3RDLHNDQUFzQztJQUN0QyxzQ0FBc0M7SUFDdEMsZUFBZTtJQUNmLHNDQUFzQztJQUN0QyxzQ0FBc0M7SUFDdEMsc0NBQXNDO0lBQ3RDLHNDQUFzQztJQUN0QyxzQ0FBc0M7SUFFdEMsSUFBSSxrQkFBa0I7UUFDcEIsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxZQUFZLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ2pELElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztTQUNwQztRQUNELE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQ2hDLE9BQU8sSUFBSSxXQUFXLENBQUM7WUFDckIsY0FBYyxFQUFFLGtCQUFrQjtZQUNsQyxNQUFNLEVBQUUsa0JBQWtCO1lBQzFCLGFBQWEsRUFBRSxVQUFVLEtBQUssRUFBRTtTQUNqQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBQ0QsV0FBVyxDQUFDLE9BQXlCO1FBQ25DLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUM7UUFDekIsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUM7UUFDL0IsTUFBTSxJQUFJLEdBQUc7WUFDWCxJQUFJLEVBQUUsSUFBSSxJQUFJLFNBQVM7WUFDdkIsSUFBSTtZQUNKLElBQUk7U0FDTCxDQUFDO1FBQ0YsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDaEMsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2pCLE1BQU0sRUFBRSxjQUFjLEVBQUUsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1lBQ3pDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQztZQUN4QyxNQUFNLEdBQUcsR0FBRyxHQUFHLE9BQU8sSUFBSSxjQUFjLGFBQWEsQ0FBQztZQUV0RCxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQ3BELENBQUMsUUFBUSxFQUFFLEVBQUU7Z0JBQ1gsSUFBSSxRQUFRLEVBQUU7b0JBQ1osSUFBSSxDQUFDLHdCQUF3QixFQUFFLENBQUM7b0JBQ2hDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUM7aUJBQ3RDO1lBQ0gsQ0FBQyxFQUNELENBQUMsS0FBSyxFQUFFLEVBQUU7Z0JBQ1IsT0FBTyxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDdkMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUNyQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1lBQ3ZDLENBQUMsQ0FDRixDQUFDO1NBQ0g7YUFBTTtZQUNMLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUM7U0FDdEM7SUFDSCxDQUFDO0lBRUQsc0NBQXNDO0lBQ3RDLHNDQUFzQztJQUN0QyxzQ0FBc0M7SUFDdEMsc0NBQXNDO0lBQ3RDLHNDQUFzQztJQUN0QyxzQ0FBc0M7SUFDdEMsZUFBZTtJQUNmLHNDQUFzQztJQUN0QyxzQ0FBc0M7SUFDdEMsc0NBQXNDO0lBQ3RDLHNDQUFzQztJQUN0QyxzQ0FBc0M7SUFFOUIsZ0JBQWdCLENBQUMsT0FBWTtRQUNuQyxNQUFNLE1BQU0sR0FBRztZQUNiLEdBQUcsT0FBTztZQUNWLFFBQVEsRUFBRSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsZUFBZSxFQUFFLENBQUMsUUFBUTtTQUMzRCxDQUFDO1FBQ0YsTUFBTSxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUMsY0FBYyxpQkFBaUIsQ0FBQztRQUNwRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztRQUMvQyxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxNQUFNLEVBQUU7WUFDdEMsT0FBTyxFQUFFLE1BQU07U0FDaEIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUNELFVBQVUsQ0FBQyxPQUFZO1FBQ3JCLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDckMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDLFNBQVMsQ0FDdEMsQ0FBQyxHQUFRLEVBQUUsRUFBRTtnQkFDWCxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzVCLENBQUMsRUFDRCxDQUFDLEdBQVEsRUFBRSxFQUFFO2dCQUNYLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDckIsQ0FBQyxDQUNGLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFDTyxlQUFlLENBQUMsRUFBTztRQUM3QixNQUFNLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxjQUFjLGNBQWMsRUFBRSxFQUFFLENBQUM7UUFDckQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLHdCQUF3QixFQUFFLENBQUM7UUFDL0MsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUU7WUFDakMsT0FBTyxFQUFFLE1BQU07U0FDaEIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUNELFNBQVMsQ0FBQyxFQUFPO1FBQ2YsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNyQyxJQUFJLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FDaEMsQ0FBQyxHQUFRLEVBQUUsRUFBRTtnQkFDWCxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDaEIsQ0FBQyxFQUNELENBQUMsR0FBUSxFQUFFLEVBQUU7Z0JBQ1gsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2pCLENBQUMsQ0FDRixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBQ0Qsc0NBQXNDO0lBQ3RDLHNDQUFzQztJQUN0QyxzQ0FBc0M7SUFDdEMsc0NBQXNDO0lBQ3RDLHNDQUFzQztJQUN0QyxzQ0FBc0M7SUFDdEMsUUFBUTtJQUNSLHNDQUFzQztJQUN0QyxzQ0FBc0M7SUFDdEMsc0NBQXNDO0lBQ3RDLHNDQUFzQztJQUN0QyxzQ0FBc0M7SUFDdEMsaUJBQWlCO1FBQ2YsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUV6QixJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDL0IsQ0FBQzs7MEdBM2FVLGFBQWEsc0dBMkJkLGdCQUFnQjs4R0EzQmYsYUFBYSxjQUZaLE1BQU07MkZBRVAsYUFBYTtrQkFIekIsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkI7OzBCQTRCSSxNQUFNOzJCQUFDLGdCQUFnQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIE9uRGVzdHJveSwgSW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBIdHRwQ2xpZW50LCBIdHRwSGVhZGVycyB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7XG4gIFN1YmplY3QsXG4gIE9ic2VydmFibGUsXG4gIEJlaGF2aW9yU3ViamVjdCxcbiAgdGltZXIsXG4gIFN1YnNjcmlwdGlvbixcbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge1xuICBJQ29udmVyc2F0aW9uQWN0aXZpdGllcyxcbiAgSU1lc3NhZ2VBY3Rpdml0eSxcbn0gZnJvbSAnLi4vbW9kZWwvY29udmVyc2F0aW9uLm1vZGVsJztcbmltcG9ydCB7XG4gIG1hcCxcbiAgdGFrZVVudGlsLFxuICBjYXRjaEVycm9yLFxuICBzdGFydFdpdGgsXG4gIHN3aXRjaE1hcCxcbn0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQXJpQ29uZmlnLCBBcmlDb25maWdTZXJ2aWNlIH0gZnJvbSAnLi4vbW9kZWwvYXJpLWJvdC5tb2RlJztcbmltcG9ydCB7IFB1YnN1YlNlcnZpY2UgfSBmcm9tICcuL3B1YnN1Yi5zZXJ2aWNlJztcbmltcG9ydCAnbW9tZW50LXRpbWV6b25lJztcbmltcG9ydCB7IENvbW1vblNlcnZpY2UgfSBmcm9tICcuL2NvbW1vbi5zZXJ2aWNlJztcbmltcG9ydCAqIGFzIG1vbWVudCBmcm9tICdtb21lbnQnO1xuXG5jb25zdCBiYXNlVXJsID1cbiAgJ2h0dHBzOi8vZGlyZWN0bGluZS5ib3RmcmFtZXdvcmsuY29tL3YzL2RpcmVjdGxpbmUvY29udmVyc2F0aW9ucyc7XG4vLyBjb25zdCBiYXNlVXJsID1cbi8vICAgJ2h0dHA6Ly9sb2NhbGhvc3Q6NjIxMTQvYXBpL21lc3NhZ2VzJztcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIEFyaUJvdFNlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICBwcml2YXRlIHVuc3Vic2NyaWJlJCA9IG5ldyBTdWJqZWN0PGFueT4oKTtcblxuICBwcml2YXRlIGFyaUNyZWRzOiBhbnk7XG4gIHByaXZhdGUgYXJpQ3JlZHMkID0gbmV3IFN1YmplY3QoKTtcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOiB2YXJpYWJsZS1uYW1lXG4gIHByaXZhdGUgX2JvdFJlc3BvbnNlJDogQmVoYXZpb3JTdWJqZWN0PGFueT4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0KG51bGwpO1xuICBoYXNJbml0aWFsaXplZENvbnZlcnNhdGlvbiA9IGZhbHNlO1xuICBoYXNDb252ZXJzYXRpb25zID0gZmFsc2U7XG4gIHByaXZhdGUgcmVzZXQkID0gbmV3IFN1YmplY3QoKTtcbiAgdGltZXIkOiBPYnNlcnZhYmxlPGFueT47XG4gIHN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xuICBhdXRoOiBhbnk7XG4gIGJhc2VVcmxwcm9qZWN0OiBhbnk7XG4gIHByb2plY3Q6IG51bWJlcjtcbiAgaW5pdE1lc3NhZ2U6IGFueSA9IHt9O1xuICBhc3Npc3RhbnROYW1lID0gJ0FyaSc7XG4gIGFyaUJvdENvbnZlcnNhdGlvbklkOiBzdHJpbmc7XG4gIGN1cnJlbnRMb2NhdGlvbjogYW55O1xuICBwdWJsaWMgbG9jYXRpb25BY2Nlc3MkID0gbmV3IFN1YmplY3Q8Ym9vbGVhbj4oKTtcbiAgZ2V0IGxvY2F0aW9uU3RhdHVzQ2hhbmdlZCgpOiBPYnNlcnZhYmxlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gdGhpcy5sb2NhdGlvbkFjY2VzcyQuYXNPYnNlcnZhYmxlKCk7XG4gIH1cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBodHRwQ2xpZW50OiBIdHRwQ2xpZW50LFxuICAgIHByaXZhdGUgcHVic3ViOiBQdWJzdWJTZXJ2aWNlLFxuICAgIHByaXZhdGUgY29tbW9uU2VydmljZTogQ29tbW9uU2VydmljZSxcbiAgICBASW5qZWN0KEFyaUNvbmZpZ1NlcnZpY2UpIHByaXZhdGUgY29uZmlnOiBBcmlDb25maWdcbiAgKSB7XG4gICAgaWYgKGNvbmZpZy5zZXR0aW5ncykge1xuICAgICAgdGhpcy5hc3Npc3RhbnROYW1lID0gY29uZmlnLnNldHRpbmdzLmFzc2lzdGFudE5hbWU7XG4gICAgICB0aGlzLmF1dGggPSBjb25maWcuc2V0dGluZ3MuYXV0aDtcbiAgICAgIHRoaXMucHJvamVjdCA9IGNvbmZpZy5zZXR0aW5ncy5wcm9qZWN0O1xuICAgICAgdGhpcy5iYXNlVXJscHJvamVjdCA9IGNvbmZpZy5zZXR0aW5ncy5iYXNlVXJsO1xuICAgIH1cbiAgICB0aGlzLmFyaUNyZWRzJC5waXBlKHRha2VVbnRpbCh0aGlzLnVuc3Vic2NyaWJlJCkpLnN1YnNjcmliZSgoY3JlZHMpID0+IHtcbiAgICAgIGlmIChjcmVkcykge1xuICAgICAgICB0aGlzLnN1YnNjcmliZVRvQ29udmVyc2F0aW9ucygpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgYm90UmVzcG9uc2UkKCk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgcmV0dXJuIHRoaXMuX2JvdFJlc3BvbnNlJC5hc09ic2VydmFibGUoKTtcbiAgfVxuICBhcmlUaW1lb3V0KCkge1xuICAgIHRoaXMudGltZXIkID0gdGhpcy5yZXNldCQucGlwZShcbiAgICAgIHN0YXJ0V2l0aCgwKSxcbiAgICAgIHN3aXRjaE1hcCgoKSA9PiB0aW1lcigwLCAxMDAwKSkgLy8gMTAwMCA9IDFzZWNcbiAgICApO1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uID0gdGhpcy50aW1lciQuc3Vic2NyaWJlKChpKSA9PiB7XG4gICAgICAvLy8gNSBNaW51dGVzIHJlc2V0IHRoZSB0aW1lciBhbmQgY2xvc2UgYXJpIGFuZCBzaG93IFwiSSBoYXZlIG5vdCBoZWFyZCBmcm9tIHlvdSBmb3IgYSB3aGlsZSBzbyBJIHByZXN1bWUgdGhhdCB5b3UgYXJlIGJ1c3kuIENhbGwgbWUgYWdhaW4gd2hlbiB5b3UgYXJlIHJlYWR5LiBHb29kYnllLlwiXG4gICAgICBpZiAoaSA9PSA2MDApIHtcbiAgICAgICAgLy8gMzAwIHNlY3MgPSA1IG1pbnV0ZXNcbiAgICAgICAgdGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgdGhpcy5wdWJzdWIuJHB1YignQVJJLVRJTUVPVVQnLCB0cnVlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuICByZWZyZXNoVGltZXIoKTogdm9pZCB7XG4gICAgdGhpcy5yZXNldCQubmV4dCgwKTtcbiAgfVxuICBzdG9wVGltZXIoKSB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgfVxuICBzdWJzY3JpYmVUb0NvbnZlcnNhdGlvbnMoKSB7XG4gICAgbGV0IGVtcHR5Q29udmVyc2F0aW9uSWQ7XG4gICAgbGV0IGhhc0VtcHR5Q29udmVyc2F0aW9uID0gZmFsc2U7XG4gICAgdGhpcy5oYXNDb252ZXJzYXRpb25zID0gdHJ1ZTtcblxuICAgIHJldHVybiB0aGlzLmdldENvbnZlcnNhdGlvbnMoKVxuICAgICAgLnBpcGUoXG4gICAgICAgIG1hcCgoY29udmVyc2F0aW9ucykgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgYWN0aXZpdGllcyB9ID0gY29udmVyc2F0aW9ucztcbiAgICAgICAgICBjb252ZXJzYXRpb25zLmFjdGl2aXRpZXMgPSBhY3Rpdml0aWVzLmZpbHRlcigoYWN0aXZpdHk6IGFueSkgPT4ge1xuXG4gICAgICAgICAgICBpZiAoYWN0aXZpdHkuZnJvbS5Ub2tlbiAmJiBhY3Rpdml0eS5mcm9tLlJlZnJlc2hUb2tlbikge1xuICAgICAgICAgICAgICB0aGlzLmNvbW1vblNlcnZpY2UudXBkYXRlVXNlck9iamVjdChcbiAgICAgICAgICAgICAgICBhY3Rpdml0eS5mcm9tLlRva2VuLFxuICAgICAgICAgICAgICAgIGFjdGl2aXR5LmZyb20uUmVmcmVzaFRva2VuXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgIChhY3Rpdml0eS50ZXh0IHx8IGFjdGl2aXR5LnJlcGx5VG9JZCAhPT0gZW1wdHlDb252ZXJzYXRpb25JZCkgJiZcbiAgICAgICAgICAgICAgaGFzRW1wdHlDb252ZXJzYXRpb24gPT09IGZhbHNlXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGFjdGl2aXR5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWFjdGl2aXR5LnRleHQpIHtcbiAgICAgICAgICAgICAgZW1wdHlDb252ZXJzYXRpb25JZCA9IGFjdGl2aXR5LmlkO1xuICAgICAgICAgICAgICBoYXNFbXB0eUNvbnZlcnNhdGlvbiA9IHRydWU7XG4gICAgICAgICAgICAgIGFjdGl2aXR5Lmhhc0VtcHR5Q29udmVyc2F0aW9uID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGhhc0VtcHR5Q29udmVyc2F0aW9uID0gZmFsc2U7XG4gICAgICAgICAgICAgIGFjdGl2aXR5Lmhhc0VtcHR5Q29udmVyc2F0aW9uID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIGNvbnZlcnNhdGlvbnM7XG4gICAgICAgIH0pLFxuICAgICAgICBjYXRjaEVycm9yKChlcnJvcikgPT4ge1xuICAgICAgICAgIHRoaXMucHVic3ViLiRwdWIoJ0FSSS1FUlJPUicsIGVycm9yKTtcbiAgICAgICAgICB0aGlzLnB1YnN1Yi4kcHViKCdBUkktTE9BRElORy1ET05FJyk7XG4gICAgICAgICAgcmV0dXJuIGVycm9yLmVycm9yO1xuICAgICAgICB9KSxcbiAgICAgICAgdGFrZVVudGlsKHRoaXMudW5zdWJzY3JpYmUkKVxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgocmVzcG9uc2U6IGFueSkgPT4ge1xuICAgICAgICBpZiAocmVzcG9uc2UpIHtcbiAgICAgICAgICBjb25zdCBnZXRBbGxBY3Rpdml0aWVzID0gdGhpcy5pbml0TWVzc2FnZS5hY3Rpdml0aWVzXG4gICAgICAgICAgICA/IHRoaXMuaW5pdE1lc3NhZ2UuYWN0aXZpdGllcy5jb25jYXQocmVzcG9uc2UuYWN0aXZpdGllcylcbiAgICAgICAgICAgIDogcmVzcG9uc2UuYWN0aXZpdGllcztcbiAgICAgICAgICBjb25zdCB2YWxpZEFjdGl2aXRpZXMgPSBnZXRBbGxBY3Rpdml0aWVzLmZpbHRlcigoaXRlbSkgPT4ge1xuICAgICAgICAgICAgaWYgKGl0ZW0uaWQpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGl0ZW07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgY29uc3QgZGF0YVJlc3BvbnNlID0ge1xuICAgICAgICAgICAgYWN0aXZpdGllczogdmFsaWRBY3Rpdml0aWVzLFxuICAgICAgICAgICAgd2F0ZXJtYXJrOiByZXNwb25zZS53YXRlcm1hcmssXG4gICAgICAgICAgfTtcbiAgICAgICAgICB0aGlzLl9ib3RSZXNwb25zZSQubmV4dChkYXRhUmVzcG9uc2UpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Q29udmVyc2F0aW9ucygpOiBPYnNlcnZhYmxlPElDb252ZXJzYXRpb25BY3Rpdml0aWVzPiB7XG4gICAgY29uc3QgeyBjb252ZXJzYXRpb25JZCB9ID0gdGhpcy5hcmlDcmVkcztcbiAgICBjb25zdCB1cmwgPSBgJHtiYXNlVXJsfS8ke2NvbnZlcnNhdGlvbklkfS9hY3Rpdml0aWVzYDtcbiAgICBjb25zdCBoZWFkZXJzID0gdGhpcy5jb252ZXJzYXRpb25IZWFkZXI7XG5cbiAgICByZXR1cm4gdGhpcy5odHRwQ2xpZW50LmdldDxJQ29udmVyc2F0aW9uQWN0aXZpdGllcz4odXJsLCB7XG4gICAgICBoZWFkZXJzLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIHBhZ2luYXRlVGFza3MocGFyYW1zOiBhbnkpOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgIGNvbnN0IHVybCA9IGAke3RoaXMuYmFzZVVybHByb2plY3R9L2FwaS9hcmkvdGFza3NgO1xuICAgIGNvbnN0IGhlYWRlciA9IHRoaXMuY29tbW9uU3RhdGVDaGFuZ2VIZWFkZXJzKCk7XG4gICAgcmV0dXJuIHRoaXMuaHR0cENsaWVudC5nZXQodXJsLCB7XG4gICAgICBoZWFkZXJzOiBoZWFkZXIsXG4gICAgICBwYXJhbXM6IHBhcmFtcyxcbiAgICB9KTtcbiAgfVxuICBwcml2YXRlIGdldEluaXRpYWxXZWxjb21lTWVzc2FnZSgpOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgIGNvbnN0IGF1dGggPSBKU09OLnBhcnNlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKHRoaXMuYXV0aCkpO1xuXG4gICAgbGV0IHBhcmFtczogYW55ID0ge307XG4gICAgaWYgKGF1dGgpIHtcbiAgICAgIGNvbnN0IHRpbWVab25lID0gSW50bC5EYXRlVGltZUZvcm1hdCgpLnJlc29sdmVkT3B0aW9ucygpLnRpbWVab25lO1xuICAgICAgcGFyYW1zID0ge1xuICAgICAgICBSZWZyZXNoVG9rZW46IGF1dGguUmVmcmVzaFRva2VuLFxuICAgICAgICBUaW1lWm9uZTogYXV0aC50aW1lWm9uZSA/IGF1dGgudGltZVpvbmUgOiB0aW1lWm9uZSxcbiAgICAgICAgUHJvamVjdDogdGhpcy5wcm9qZWN0LFxuICAgICAgICBMb2NhdGlvbjogYXV0aC5sb2NhdGlvblxuICAgICAgICAgID8gYXV0aC5sb2NhdGlvblxuICAgICAgICAgIDogdGltZVpvbmUuc3Vic3RyaW5nKHRpbWVab25lLmluZGV4T2YoJy8nKSArIDEsIHRpbWVab25lLmxlbmd0aCksXG4gICAgICB9O1xuICAgICAgLy8gaWYgKGF1dGgubGF0IHx8IGF1dGgubG9uZykge1xuICAgICAgLy8gICBwYXJhbXMuTGF0ID0gYXV0aC5sYXQ7XG4gICAgICAvLyAgIHBhcmFtcy5Mb25nID0gYXV0aC5sb25nO1xuICAgICAgLy8gfVxuICAgIH0gZWxzZSB7XG4gICAgICBwYXJhbXMgPSB7XG4gICAgICAgIC4uLkpTT04ucGFyc2UobG9jYWxTdG9yYWdlLmdldEl0ZW0oJ3RlbXBfdXNlcicpKSxcbiAgICAgIH07XG4gICAgfVxuICAgIGNvbnN0IHVybCA9IGAke3RoaXMuYmFzZVVybHByb2plY3R9L2FwaS9hcmkvd2VsY29tZWA7XG4gICAgY29uc3QgaGVhZGVyID0gdGhpcy5jb21tb25TdGF0ZUNoYW5nZUhlYWRlcnMoKTtcbiAgICByZXR1cm4gdGhpcy5odHRwQ2xpZW50LmdldCh1cmwsIHtcbiAgICAgIGhlYWRlcnM6IGhlYWRlcixcbiAgICAgIHBhcmFtczogcGFyYW1zLFxuICAgIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNvbW1vblN0YXRlQ2hhbmdlSGVhZGVycygpOiBhbnkge1xuICAgIGxldCBoZWFkZXJzOiBhbnk7XG4gICAgaWYgKEpTT04ucGFyc2UobG9jYWxTdG9yYWdlLmdldEl0ZW0odGhpcy5hdXRoKSkpIHtcbiAgICAgIGhlYWRlcnMgPSB7XG4gICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgIEFjY2VwdDogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7SlNPTi5wYXJzZShsb2NhbFN0b3JhZ2UuZ2V0SXRlbSh0aGlzLmF1dGgpKS5Ub2tlblxuICAgICAgICAgIH1gLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgaGVhZGVycyA9IHtcbiAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgQWNjZXB0OiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gbmV3IEh0dHBIZWFkZXJzKGhlYWRlcnMpO1xuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gSU5JVCBDT05WRVJTQVRJT05cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgZ2V0IGluaXRIZWFkZXJzKCk6IEh0dHBIZWFkZXJzIHtcbiAgICByZXR1cm4gbmV3IEh0dHBIZWFkZXJzKHtcbiAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICBBY2NlcHQ6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgIEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHt0aGlzLmNvbmZpZy5hcGlTZWNyZXR9YCxcbiAgICB9KTtcbiAgfVxuXG4gIGdldFdlbGNvbWVNZXNzYWdlKGxvY2F0aW9uUGVybWlzc2lvbj86IGJvb2xlYW4pIHtcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gVG8gZ2V0IHVzZXIgY3VycmVudCBsb2NhdGlvbiAobG9uZyBhbmQgbGF0KSBjb25kaXRpb25hbGx5IHRoZW4gY2FsbCB3ZWxjb21lIG1lc3NhZ2VcbiAgICBjb25zdCBvbGRBdXRoU3RvcmFnZSA9IEpTT04ucGFyc2UoXG4gICAgICBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSh0aGlzLmF1dGggPyB0aGlzLmF1dGggOiAndGVtcF91c2VyJylcbiAgICApO1xuICAgIGNvbnN0IGFkZFRvQXV0aFN0b3JhZ2UgPSB7XG4gICAgICAuLi5vbGRBdXRoU3RvcmFnZSxcbiAgICB9O1xuXG4gICAgY29uc3QgY2FsbFdlbGNvbWVNZXNzYWdlID0gKCkgPT4ge1xuICAgICAgdGhpcy5nZXRJbml0aWFsV2VsY29tZU1lc3NhZ2UoKS5zdWJzY3JpYmUoKHJlczogYW55KSA9PiB7XG4gICAgICAgIGlmIChyZXMpIHtcbiAgICAgICAgICB0aGlzLmluaXRNZXNzYWdlID0gcmVzO1xuICAgICAgICAgIHRoaXMuX2JvdFJlc3BvbnNlJC5uZXh0KHJlcyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG4gICAgaWYgKGxvY2F0aW9uUGVybWlzc2lvbikge1xuICAgICAgLy8gSWYgTG9jYXRpb24gYWNjZXNzIGlzIGFsbG93ZWQgKCBDb21wbGV0ZWx5IHJlbW92ZSBmb3Igbm93IClcbiAgICAgIGNvbnN0IHN1Y2Nlc3MgPSAocG9zKSA9PiB7XG4gICAgICAgIHRoaXMuY3VycmVudExvY2F0aW9uID0ge1xuICAgICAgICAgIGxvbmc6IHBvcy5jb29yZHMubG9uZ2l0dWRlLFxuICAgICAgICAgIGxhdDogcG9zLmNvb3Jkcy5sYXRpdHVkZSxcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHRoaXMuY3VycmVudExvY2F0aW9uKSB7XG4gICAgICAgICAgYWRkVG9BdXRoU3RvcmFnZS5sYXQgPSB0aGlzLmN1cnJlbnRMb2NhdGlvbi5sYXQ7XG4gICAgICAgICAgYWRkVG9BdXRoU3RvcmFnZS5sb25nID0gdGhpcy5jdXJyZW50TG9jYXRpb24ubG9uZztcbiAgICAgICAgfVxuICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShcbiAgICAgICAgICB0aGlzLmF1dGggPyB0aGlzLmF1dGggOiAndGVtcF91c2VyJyxcbiAgICAgICAgICBKU09OLnN0cmluZ2lmeShhZGRUb0F1dGhTdG9yYWdlKVxuICAgICAgICApO1xuICAgICAgICBjYWxsV2VsY29tZU1lc3NhZ2UoKTtcbiAgICAgIH07XG4gICAgICBuYXZpZ2F0b3IuZ2VvbG9jYXRpb24uZ2V0Q3VycmVudFBvc2l0aW9uKHN1Y2Nlc3MpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBpZiBMb2NhdGlvbiBhY2Nlc3MgaXMgbm90IGFsbG93ZWRcbiAgICAgIGRlbGV0ZSBhZGRUb0F1dGhTdG9yYWdlLmxhdDtcbiAgICAgIGRlbGV0ZSBhZGRUb0F1dGhTdG9yYWdlLmxvbmc7XG4gICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShcbiAgICAgICAgdGhpcy5hdXRoID8gdGhpcy5hdXRoIDogJ3RlbXBfdXNlcicsXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KGFkZFRvQXV0aFN0b3JhZ2UpXG4gICAgICApO1xuICAgICAgY2FsbFdlbGNvbWVNZXNzYWdlKCk7XG4gICAgfVxuICB9XG4gIGluaXRDb252ZXJzYXRpb24oKSB7XG4gICAgdGhpcy5wdWJzdWIuJHB1YignQVJJLUxPQURJTkcnKTtcbiAgICAvLyBHRVQgSU5JVElBTCBNRVNTQUdFIEZST00gUFJPSkVDVCBBUElcbiAgICBjb25zdCBoZWFkZXJzID0gdGhpcy5pbml0SGVhZGVycztcbiAgICB0aGlzLmh0dHBDbGllbnQucG9zdChiYXNlVXJsLCB7fSwgeyBoZWFkZXJzIH0pLnN1YnNjcmliZShcbiAgICAgIChyZXNwb25zZTogYW55KSA9PiB7XG4gICAgICAgIHRoaXMuYXJpQ3JlZHMgPSByZXNwb25zZTtcbiAgICAgICAgdGhpcy5hcmlCb3RDb252ZXJzYXRpb25JZCA9IHRoaXMuYXJpQ3JlZHMuY29udmVyc2F0aW9uSWQ7XG4gICAgICAgIGNvbnN0IG9sZEF1dGhTdG9yYWdlID0gSlNPTi5wYXJzZShcbiAgICAgICAgICBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSh0aGlzLmF1dGggPyB0aGlzLmF1dGggOiAndGVtcF91c2VyJylcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgYWRkVG9BdXRoU3RvcmFnZSA9IHtcbiAgICAgICAgICAuLi5vbGRBdXRoU3RvcmFnZSxcbiAgICAgICAgICBjb252ZXJzYXRpb25JZDogdGhpcy5hcmlCb3RDb252ZXJzYXRpb25JZCxcbiAgICAgICAgICBjb252ZXJzaW9uVG9rZW46IHRoaXMuYXJpQ3JlZHMudG9rZW4sXG4gICAgICAgIH07XG4gICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKFxuICAgICAgICAgIHRoaXMuYXV0aCA/IHRoaXMuYXV0aCA6ICd0ZW1wX3VzZXInLFxuICAgICAgICAgIEpTT04uc3RyaW5naWZ5KGFkZFRvQXV0aFN0b3JhZ2UpXG4gICAgICAgICk7XG4gICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKCdBcmlDcmVkcycsIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKSk7XG4gICAgICAgIHRoaXMucHVic3ViLiRwdWIoJ0FSSS1MT0FESU5HLURPTkUnKTtcbiAgICAgICAgdGhpcy5oYXNJbml0aWFsaXplZENvbnZlcnNhdGlvbiA9IHRydWU7XG5cbiAgICAgICAgdGhpcy5nZXRXZWxjb21lTWVzc2FnZShmYWxzZSk7XG4gICAgICB9LFxuICAgICAgKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FyaUJvdCBFcnJvcjogJywgZXJyb3IpO1xuICAgICAgICB0aGlzLnB1YnN1Yi4kcHViKCdBUkktRVJST1InLCBlcnJvcik7XG4gICAgICAgIHRoaXMucHVic3ViLiRwdWIoJ0FSSS1MT0FESU5HLURPTkUnKTtcbiAgICAgIH1cbiAgICApO1xuICB9XG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIFNFTkQgTUVTU0FHRVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIGdldCBjb252ZXJzYXRpb25IZWFkZXIoKTogSHR0cEhlYWRlcnMge1xuICAgIGlmICghdGhpcy5hcmlDcmVkcykge1xuICAgICAgdGhpcy5hcmlDcmVkcyA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdBcmlDcmVkcycpO1xuICAgICAgdGhpcy5hcmlDcmVkcyQubmV4dCh0aGlzLmFyaUNyZWRzKTtcbiAgICB9XG4gICAgY29uc3QgeyB0b2tlbiB9ID0gdGhpcy5hcmlDcmVkcztcbiAgICByZXR1cm4gbmV3IEh0dHBIZWFkZXJzKHtcbiAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICBBY2NlcHQ6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgIEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHt0b2tlbn1gLFxuICAgIH0pO1xuICB9XG4gIHNlbmRNZXNzYWdlKG1lc3NhZ2U6IElNZXNzYWdlQWN0aXZpdHkpIHtcbiAgICBjb25zdCB7IHR5cGUgfSA9IG1lc3NhZ2U7XG4gICAgY29uc3QgeyBmcm9tLCB0ZXh0IH0gPSBtZXNzYWdlO1xuICAgIGNvbnN0IGJvZHkgPSB7XG4gICAgICB0eXBlOiB0eXBlIHx8ICdtZXNzYWdlJyxcbiAgICAgIGZyb20sXG4gICAgICB0ZXh0LFxuICAgIH07XG4gICAgdGhpcy5wdWJzdWIuJHB1YignQVJJLUxPQURJTkcnKTtcbiAgICBpZiAodGhpcy5hcmlDcmVkcykge1xuICAgICAgY29uc3QgeyBjb252ZXJzYXRpb25JZCB9ID0gdGhpcy5hcmlDcmVkcztcbiAgICAgIGNvbnN0IGhlYWRlcnMgPSB0aGlzLmNvbnZlcnNhdGlvbkhlYWRlcjtcbiAgICAgIGNvbnN0IHVybCA9IGAke2Jhc2VVcmx9LyR7Y29udmVyc2F0aW9uSWR9L2FjdGl2aXRpZXNgO1xuXG4gICAgICB0aGlzLmh0dHBDbGllbnQucG9zdCh1cmwsIGJvZHksIHsgaGVhZGVycyB9KS5zdWJzY3JpYmUoXG4gICAgICAgIChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGlmIChyZXNwb25zZSkge1xuICAgICAgICAgICAgdGhpcy5zdWJzY3JpYmVUb0NvbnZlcnNhdGlvbnMoKTtcbiAgICAgICAgICAgIHRoaXMucHVic3ViLiRwdWIoJ0FSSS1MT0FESU5HLURPTkUnKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIChlcnJvcikgPT4ge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FyaUJvdCBFcnJvcjogJywgZXJyb3IpO1xuICAgICAgICAgIHRoaXMucHVic3ViLiRwdWIoJ0FSSS1FUlJPUicsIGVycm9yKTtcbiAgICAgICAgICB0aGlzLnB1YnN1Yi4kcHViKCdBUkktTE9BRElORy1ET05FJyk7XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucHVic3ViLiRwdWIoJ0FSSS1MT0FESU5HLURPTkUnKTtcbiAgICB9XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyBUQVNLIEFDVElPTlNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBwcml2YXRlIHRhc2tBY3Rpb25Nb3ZlVG8ocGF5bG9hZDogYW55KTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAuLi5wYXlsb2FkLFxuICAgICAgdGltZVpvbmU6IEludGwuRGF0ZVRpbWVGb3JtYXQoKS5yZXNvbHZlZE9wdGlvbnMoKS50aW1lWm9uZSxcbiAgICB9O1xuICAgIGNvbnN0IHVybCA9IGAke3RoaXMuYmFzZVVybHByb2plY3R9L2FwaS90YXNrcy9tb3ZlYDtcbiAgICBjb25zdCBoZWFkZXIgPSB0aGlzLmNvbW1vblN0YXRlQ2hhbmdlSGVhZGVycygpO1xuICAgIHJldHVybiB0aGlzLmh0dHBDbGllbnQucHV0KHVybCwgcGFyYW1zLCB7XG4gICAgICBoZWFkZXJzOiBoZWFkZXIsXG4gICAgfSk7XG4gIH1cbiAgdGFza01vdmVUbyhwYXlsb2FkOiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLnRhc2tBY3Rpb25Nb3ZlVG8ocGF5bG9hZCkuc3Vic2NyaWJlKFxuICAgICAgICAocmVzOiBhbnkpID0+IHtcbiAgICAgICAgICByZXNvbHZlKHJlcyA/IHJlcyA6IG51bGwpO1xuICAgICAgICB9LFxuICAgICAgICAoZXJyOiBhbnkpID0+IHtcbiAgICAgICAgICByZXNvbHZlKGVyci5lcnJvcik7XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSk7XG4gIH1cbiAgcHJpdmF0ZSB0YXNrQWN0aW9uVHJhc2goaWQ6IGFueSk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgY29uc3QgdXJsID0gYCR7dGhpcy5iYXNlVXJscHJvamVjdH0vYXBpL3Rhc2tzLyR7aWR9YDtcbiAgICBjb25zdCBoZWFkZXIgPSB0aGlzLmNvbW1vblN0YXRlQ2hhbmdlSGVhZGVycygpO1xuICAgIHJldHVybiB0aGlzLmh0dHBDbGllbnQuZGVsZXRlKHVybCwge1xuICAgICAgaGVhZGVyczogaGVhZGVyLFxuICAgIH0pO1xuICB9XG4gIHRhc2tUcmFzaChpZDogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT