@hpe/angular-toolkit
Version:
Hewlett-Packard Enterprise : Angular toolkit for rapid project development
965 lines (948 loc) • 101 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@hpe/angular-toolkit/model'), require('@angular/common/http'), require('@angular/platform-browser'), require('rxjs'), require('rxjs/operators'), require('primeng/components/common/messageservice'), require('@angular/common'), require('primeng/api')) :
typeof define === 'function' && define.amd ? define('@hpe/angular-toolkit/service', ['exports', '@angular/core', '@hpe/angular-toolkit/model', '@angular/common/http', '@angular/platform-browser', 'rxjs', 'rxjs/operators', 'primeng/components/common/messageservice', '@angular/common', 'primeng/api'], factory) :
(factory((global.hpe = global.hpe || {}, global.hpe['angular-toolkit'] = global.hpe['angular-toolkit'] || {}, global.hpe['angular-toolkit'].service = {}),global.ng.core,global.hpe['angular-toolkit'].model,global.ng.common.http,global.ng.platformBrowser,global.rxjs,global.rxjs.operators,null,global.ng.common,null));
}(this, (function (exports,core,model,http,platformBrowser,rxjs,operators,messageservice,common,api) { 'use strict';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b)
if (b.hasOwnProperty(p))
d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
//=============================================================================
//===
//=== (C) Copyright 2018 Hewlett Packard Enterprise Development LP.
//===
//=== Use of this source code is governed by an MIT-style license that can be
//=== found in the LICENSE file
//=============================================================================
var AbstractSubscriber = (function () {
//-------------------------------------------------------------------------
//---
//--- Constructor
//---
//-------------------------------------------------------------------------
function AbstractSubscriber(eventBusService) {
this.eventBusService = eventBusService;
this.subscriptions = [];
}
/**
* @return {?}
*/
AbstractSubscriber.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
this.subscriptions.forEach(function (s) { return s.unsubscribe(); });
};
//-------------------------------------------------------------------------
//---
//--- API methods
//---
//-------------------------------------------------------------------------
/**
* @param {?} eventCode
* @param {?} handler
* @return {?}
*/
AbstractSubscriber.prototype.subscribeToApp = /**
* @param {?} eventCode
* @param {?} handler
* @return {?}
*/
function (eventCode, handler) {
var /** @type {?} */ s = this.eventBusService.subscribeToApp(eventCode, handler);
this.subscriptions.push(s);
return s;
};
//-------------------------------------------------------------------------
/**
* @param {?} event
* @return {?}
*/
AbstractSubscriber.prototype.emitToApp = /**
* @param {?} event
* @return {?}
*/
function (event) {
this.eventBusService.emitToApp(event);
};
//-------------------------------------------------------------------------
/**
* @param {?} handler
* @return {?}
*/
AbstractSubscriber.prototype.subscribeToError = /**
* @param {?} handler
* @return {?}
*/
function (handler) {
var /** @type {?} */ s = this.eventBusService.subscribeToError(handler);
this.subscriptions.push(s);
return s;
};
//-------------------------------------------------------------------------
/**
* @param {?} event
* @return {?}
*/
AbstractSubscriber.prototype.emitToError = /**
* @param {?} event
* @return {?}
*/
function (event) {
this.eventBusService.emitToError(event);
};
return AbstractSubscriber;
}());
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var EventBusService = (function () {
//-------------------------------------------------------------------------
//---
//--- Constructor
//---
//-------------------------------------------------------------------------
function EventBusService() {
this.eventEmitterMap = new Map();
this.errorEvents = new core.EventEmitter();
}
/**
* @param {?} eventCode
* @param {?} handler
* @return {?}
*/
EventBusService.prototype.subscribeToApp = /**
* @param {?} eventCode
* @param {?} handler
* @return {?}
*/
function (eventCode, handler) {
var /** @type {?} */ emitter = this.eventEmitterMap.get(eventCode);
if (emitter == null) {
emitter = new core.EventEmitter();
this.eventEmitterMap.set(eventCode, emitter);
}
return emitter.subscribe(handler, null, null);
};
/**
* @param {?} event
* @return {?}
*/
EventBusService.prototype.emitToApp = /**
* @param {?} event
* @return {?}
*/
function (event) {
var /** @type {?} */ emitter = this.eventEmitterMap.get(event.code);
if (emitter != null) {
console.log("Emitting event : " + JSON.stringify(event));
emitter.emit(event);
}
else {
console.log("WARNING : Emitting an event without any handler : " + JSON.stringify(event));
}
//--- Emitting to global handlers
emitter = this.eventEmitterMap.get(model.AppEvent.ANY);
if (emitter != null) {
emitter.emit(event);
}
};
/**
* @param {?} handler
* @return {?}
*/
EventBusService.prototype.subscribeToError = /**
* @param {?} handler
* @return {?}
*/
function (handler) {
return this.errorEvents.subscribe(handler, null, null);
};
/**
* @param {?} event
* @return {?}
*/
EventBusService.prototype.emitToError = /**
* @param {?} event
* @return {?}
*/
function (event) {
console.log("Emitting error event : " + JSON.stringify(event));
this.errorEvents.emit(event);
};
EventBusService.decorators = [
{ type: core.Injectable },
];
/** @nocollapse */
EventBusService.ctorParameters = function () { return []; };
return EventBusService;
}());
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/** @enum {number} */
var Status = {
LOGIN: 0,
LOADING: 1,
READY: 2,
};
Status[Status.LOGIN] = "LOGIN";
Status[Status.LOADING] = "LOADING";
Status[Status.READY] = "READY";
var ApplicationService = (function (_super) {
__extends(ApplicationService, _super);
//-------------------------------------------------------------------------
//---
//--- Constructor
//---
//-------------------------------------------------------------------------
function ApplicationService(eventBusService) {
var _this = _super.call(this, eventBusService) || this;
_this.status = Status.LOGIN;
_super.prototype.subscribeToApp.call(_this, model.AppEvent.LOGIN_SUCCESS, function (event) { return _this.onLoginSuccess(event); });
_super.prototype.subscribeToApp.call(_this, model.AppEvent.LOGIN_FAILED, function (event) { return _this.onLoginFailed(event); });
_super.prototype.subscribeToApp.call(_this, model.AppEvent.LOGOUT_SUCCESS, function (event) { return _this.onLogoutSuccess(event); });
_super.prototype.subscribeToApp.call(_this, model.AppEvent.LOGOUT_FAILED, function (event) { return _this.onLogoutFailed(event); });
_super.prototype.subscribeToApp.call(_this, model.AppEvent.INVALID_TOKEN, function (event) { return _this.onInvalidToken(event); });
_super.prototype.subscribeToApp.call(_this, model.AppEvent.APPLICATION_READY, function (event) { return _this.onApplicationReady(event); });
return _this;
}
/**
* @return {?}
*/
ApplicationService.prototype.isStatusLogin = /**
* @return {?}
*/
function () {
return this.status == Status.LOGIN;
};
/**
* @return {?}
*/
ApplicationService.prototype.isStatusLoading = /**
* @return {?}
*/
function () {
return this.status == Status.LOADING;
};
/**
* @return {?}
*/
ApplicationService.prototype.isStatusReady = /**
* @return {?}
*/
function () {
return this.status == Status.READY;
};
/**
* @param {?} event
* @return {?}
*/
ApplicationService.prototype.onLoginSuccess = /**
* @param {?} event
* @return {?}
*/
function (event) {
this.status = Status.LOADING;
};
/**
* @param {?} event
* @return {?}
*/
ApplicationService.prototype.onLoginFailed = /**
* @param {?} event
* @return {?}
*/
function (event) {
this.status = Status.LOGIN;
};
/**
* @param {?} event
* @return {?}
*/
ApplicationService.prototype.onLogoutSuccess = /**
* @param {?} event
* @return {?}
*/
function (event) {
this.status = Status.LOGIN;
};
/**
* @param {?} event
* @return {?}
*/
ApplicationService.prototype.onLogoutFailed = /**
* @param {?} event
* @return {?}
*/
function (event) {
this.status = Status.LOGIN;
};
/**
* @param {?} event
* @return {?}
*/
ApplicationService.prototype.onInvalidToken = /**
* @param {?} event
* @return {?}
*/
function (event) {
this.status = Status.LOGIN;
};
/**
* @param {?} event
* @return {?}
*/
ApplicationService.prototype.onApplicationReady = /**
* @param {?} event
* @return {?}
*/
function (event) {
this.status = Status.READY;
};
ApplicationService.decorators = [
{ type: core.Injectable },
];
/** @nocollapse */
ApplicationService.ctorParameters = function () {
return [
{ type: EventBusService, },
];
};
return ApplicationService;
}(AbstractSubscriber));
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var HttpService = (function () {
//-------------------------------------------------------------------------
//---
//--- Constructor
//---
//-------------------------------------------------------------------------
function HttpService(httpClient, eventBusService, domSanitizer) {
this.httpClient = httpClient;
this.eventBusService = eventBusService;
this.domSanitizer = domSanitizer;
this.openRequests = 0;
}
Object.defineProperty(HttpService.prototype, "loading", {
get: /**
* @return {?}
*/ function () {
return (this.openRequests > 0);
},
enumerable: true,
configurable: true
});
/**
* @param {?} url
* @param {?=} options
* @return {?}
*/
HttpService.prototype.getObject = /**
* @param {?} url
* @param {?=} options
* @return {?}
*/
function (url, options) {
var _this = this;
this.showLoader();
//--- "Pragma": "no-cache" for IE 11
var /** @type {?} */ header = {
"Pragma": "no-cache",
"Cache-Control": "no-cache",
"Expires": "0"
};
return this.httpClient.get(url, { params: options, headers: header }).pipe(operators.catchError(function (error) { return _this.handleError(error); }), operators.finalize(function () { return _this.hideLoader(); }));
};
/**
* @param {?} url
* @param {?=} options
* @return {?}
*/
HttpService.prototype.getBlob = /**
* @param {?} url
* @param {?=} options
* @return {?}
*/
function (url, options) {
var _this = this;
this.showLoader();
//--- Add timestamp to change static url to dynamic for IE 11
if (options != null) {
options.ts = Date.now();
}
return this.httpClient.get(url, { params: options, responseType: 'blob' }).pipe(operators.map(function (e) { return _this.getSanitizedUrl(URL.createObjectURL(e)); }), operators.catchError(function (error) { return _this.handleError(error); }), operators.finalize(function () { return _this.hideLoader(); }));
};
/**
* @param {?} url
* @param {?} object
* @param {?=} options
* @return {?}
*/
HttpService.prototype.postObject = /**
* @param {?} url
* @param {?} object
* @param {?=} options
* @return {?}
*/
function (url, object, options) {
var _this = this;
this.showLoader();
return this.httpClient.post(url, object, options).pipe(operators.catchError(function (error) { return _this.handleError(error); }), operators.finalize(function () { return _this.hideLoader(); }));
};
/**
* @param {?} url
* @return {?}
*/
HttpService.prototype.getSanitizedUrl = /**
* @param {?} url
* @return {?}
*/
function (url) {
return this.domSanitizer.bypassSecurityTrustResourceUrl(url);
};
/**
* @param {?} response
* @return {?}
*/
HttpService.prototype.handleError = /**
* @param {?} response
* @return {?}
*/
function (response) {
console.log("Got the following HTTP error : " + JSON.stringify(response));
var /** @type {?} */ error;
if (response.status == 422) {
//--- Unprocessable entity
error = response.error;
}
else {
error = {
code: response.status.toString(),
error: response.error.toString()
};
}
this.eventBusService.emitToError(error);
return rxjs.throwError(error);
};
/**
* @return {?}
*/
HttpService.prototype.showLoader = /**
* @return {?}
*/
function () {
if (++this.openRequests == 1) {
this.eventBusService.emitToApp(new model.AppEvent(model.AppEvent.SUBMIT_START));
}
};
/**
* @return {?}
*/
HttpService.prototype.hideLoader = /**
* @return {?}
*/
function () {
if (--this.openRequests == 0) {
this.eventBusService.emitToApp(new model.AppEvent(model.AppEvent.SUBMIT_END));
}
};
HttpService.decorators = [
{ type: core.Injectable },
];
/** @nocollapse */
HttpService.ctorParameters = function () {
return [
{ type: http.HttpClient, },
{ type: EventBusService, },
{ type: platformBrowser.DomSanitizer, },
];
};
return HttpService;
}());
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var LabelService = (function () {
//-------------------------------------------------------------------------
//---
//--- Constructor
//---
//-------------------------------------------------------------------------
function LabelService(httpService) {
var _this = this;
this.httpService = httpService;
this.languages = ["en", "it"];
this.labelSet = new Map();
this.language = "en";
//--- Load language files
this.languages.forEach(function (language) {
_this.initLanguage(language);
});
}
/**
* @param {?} language
* @return {?}
*/
LabelService.prototype.setLanguage = /**
* @param {?} language
* @return {?}
*/
function (language) {
this.language = language;
};
/**
* @param {?} entity
* @param {?} code
* @return {?}
*/
LabelService.prototype.getLabel = /**
* @param {?} entity
* @param {?} code
* @return {?}
*/
function (entity, code) {
if (code == null) {
return null;
}
var /** @type {?} */ entitySet = this.getMapping(entity);
if (entitySet == null) {
return "?" + entity + "?";
}
var /** @type {?} */ label = entitySet[code];
if (label == null) {
return entity + ".?" + code + "?";
}
return label;
};
/**
* @param {?} entity
* @return {?}
*/
LabelService.prototype.getMapping = /**
* @param {?} entity
* @return {?}
*/
function (entity) {
var /** @type {?} */ labels = this.labelSet.get(this.language);
if (labels != null) {
return labels.get(entity);
}
//--- Probably, we are still loading data
return null;
};
/**
* @param {?} language
* @return {?}
*/
LabelService.prototype.initLanguage = /**
* @param {?} language
* @return {?}
*/
function (language) {
this.loadLanguageFile(language, LabelService.TOOLKIT_FILE);
this.loadLanguageFile(language, LabelService.APPLICATION_FILE);
};
/**
* @param {?} language
* @param {?} name
* @return {?}
*/
LabelService.prototype.loadLanguageFile = /**
* @param {?} language
* @param {?} name
* @return {?}
*/
function (language, name) {
var _this = this;
var /** @type {?} */ file = name + "-" + language + ".json";
this.httpService.getObject("asset/lang/" + file)
.subscribe(function (result) { return _this.processFile(language, file, result); }, function (error) { return console.log("Cannot load labels file : " + file); });
};
/**
* @param {?} language
* @param {?} file
* @param {?} data
* @return {?}
*/
LabelService.prototype.processFile = /**
* @param {?} language
* @param {?} file
* @param {?} data
* @return {?}
*/
function (language, file, data) {
console.log("Loaded labels file : " + file);
var /** @type {?} */ labels = this.labelSet.get(language);
if (labels == null) {
labels = new Map();
this.labelSet.set(language, labels);
}
for (var /** @type {?} */ key in data) {
labels.set(key, data[key]);
}
};
LabelService.TOOLKIT_FILE = "toolkit";
LabelService.APPLICATION_FILE = "application";
LabelService.decorators = [
{ type: core.Injectable },
];
/** @nocollapse */
LabelService.ctorParameters = function () {
return [
{ type: HttpService, },
];
};
return LabelService;
}());
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var NotificationService = (function () {
//-------------------------------------------------------------------------
//---
//--- Constructor
//---
//-------------------------------------------------------------------------
function NotificationService(messageService) {
this.messageService = messageService;
}
/**
* @param {?} title
* @param {?} message
* @return {?}
*/
NotificationService.prototype.showSuccess = /**
* @param {?} title
* @param {?} message
* @return {?}
*/
function (title, message) {
this.show('success', title, message);
};
/**
* @param {?} title
* @param {?} message
* @return {?}
*/
NotificationService.prototype.showInfo = /**
* @param {?} title
* @param {?} message
* @return {?}
*/
function (title, message) {
this.show('info', title, message);
};
/**
* @param {?} title
* @param {?} message
* @return {?}
*/
NotificationService.prototype.showWarn = /**
* @param {?} title
* @param {?} message
* @return {?}
*/
function (title, message) {
this.show('warn', title, message);
};
/**
* @param {?} title
* @param {?} message
* @return {?}
*/
NotificationService.prototype.showError = /**
* @param {?} title
* @param {?} message
* @return {?}
*/
function (title, message) {
this.show('error', title, message);
};
/**
* @param {?} severity
* @param {?} title
* @param {?} message
* @return {?}
*/
NotificationService.prototype.show = /**
* @param {?} severity
* @param {?} title
* @param {?} message
* @return {?}
*/
function (severity, title, message) {
this.messageService.add({
severity: severity,
summary: title,
detail: message
});
};
NotificationService.decorators = [
{ type: core.Injectable },
];
/** @nocollapse */
NotificationService.ctorParameters = function () {
return [
{ type: messageservice.MessageService, },
];
};
return NotificationService;
}());
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var SessionService = (function (_super) {
__extends(SessionService, _super);
//-------------------------------------------------------------------------
//---
//--- Constructor
//---
//-------------------------------------------------------------------------
function SessionService(eventBusService, httpService) {
var _this = _super.call(this, eventBusService) || this;
_this.httpService = httpService;
_this.clearSession();
_super.prototype.subscribeToApp.call(_this, model.AppEvent.INVALID_TOKEN, function (event) { return _this.onInvalidToken(event); });
return _this;
}
/**
* @param {?} cred
* @return {?}
*/
SessionService.prototype.login = /**
* @param {?} cred
* @return {?}
*/
function (cred) {
var _this = this;
console.log("SessionService.login : Logging in user='" + cred.username + "'");
//--- Loads user profile from server
this.httpService.postObject("/api/session/login", cred)
.subscribe(function (result) { return _this.loginSuccess(result); }, function (error) { return _this.loginError(error); });
};
/**
* @return {?}
*/
SessionService.prototype.logout = /**
* @return {?}
*/
function () {
var _this = this;
console.log("SessionService.logout : Logging out user='" + (this.user || "???") + "'");
this.httpService.postObject("/api/session/logout", { token: this.token })
.subscribe(function (result) { return _this.logoutSuccess(); }, function (error) { return _this.logoutError(error); });
};
/**
* @return {?}
*/
SessionService.prototype.clearSession = /**
* @return {?}
*/
function () {
console.log("SessionService.clearSession: Resetting session...");
this.session = null;
this.token = null;
this.user = null;
this.profile = null;
this.permissions = new Map();
};
Object.defineProperty(SessionService.prototype, "homePage", {
get: /**
* @return {?}
*/ function () {
return (this.profile)
? this.profile.homePage
: null;
},
enumerable: true,
configurable: true
});
/**
* @param {?} name
* @return {?}
*/
SessionService.prototype.hasPermission = /**
* @param {?} name
* @return {?}
*/
function (name) {
return (this.permissions.get(name));
};
/**
* @param {?} session
* @return {?}
*/
SessionService.prototype.loginSuccess = /**
* @param {?} session
* @return {?}
*/
function (session) {
this.session = session;
this.token = session.token;
this.user = session.user;
this.profile = session.profile;
this.permissions = this.setupPermissionMap(this.profile.permissions);
_super.prototype.emitToApp.call(this, new model.AppEvent(model.AppEvent.LOGIN_SUCCESS, session));
console.log("Login successful for user=" + this.user.username);
};
/**
* @param {?} response
* @return {?}
*/
SessionService.prototype.loginError = /**
* @param {?} response
* @return {?}
*/
function (response) {
_super.prototype.emitToApp.call(this, new model.AppEvent(model.AppEvent.LOGIN_FAILED, response));
};
/**
* @return {?}
*/
SessionService.prototype.logoutSuccess = /**
* @return {?}
*/
function () {
var /** @type {?} */ username = this.user.username;
this.clearSession();
_super.prototype.emitToApp.call(this, new model.AppEvent(model.AppEvent.LOGOUT_SUCCESS, username));
console.log("Logout successful for user=" + username);
};
/**
* @param {?} response
* @return {?}
*/
SessionService.prototype.logoutError = /**
* @param {?} response
* @return {?}
*/
function (response) {
this.clearSession();
_super.prototype.emitToApp.call(this, new model.AppEvent(model.AppEvent.LOGOUT_FAILED));
};
/**
* @param {?} permissions
* @return {?}
*/
SessionService.prototype.setupPermissionMap = /**
* @param {?} permissions
* @return {?}
*/
function (permissions) {
var /** @type {?} */ map = new Map();
permissions.forEach(function (p) { return map.set(p, true); });
return map;
};
/**
* @param {?} event
* @return {?}
*/
SessionService.prototype.onInvalidToken = /**
* @param {?} event
* @return {?}
*/
function (event) {
this.clearSession();
};
SessionService.decorators = [
{ type: core.Injectable },
];
/** @nocollapse */
SessionService.ctorParameters = function () {
return [
{ type: EventBusService, },
{ type: HttpService, },
];
};
return SessionService;
}(AbstractSubscriber));
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var HpeServiceModule = (function () {
function HpeServiceModule() {
}
HpeServiceModule.decorators = [
{ type: core.NgModule, args: [{
imports: [
common.CommonModule
],
declarations: [],
exports: [],
providers: [
ApplicationService,
EventBusService,
HttpService,
LabelService,
NotificationService,
SessionService,
api.MessageService
],
},] },
];
return HpeServiceModule;
}());
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
exports.HpeServiceModule = HpeServiceModule;
exports.AbstractSubscriber = AbstractSubscriber;
exports.ApplicationService = ApplicationService;
exports.EventBusService = EventBusService;
exports.HttpService = HttpService;
exports.LabelService = LabelService;
exports.NotificationService = NotificationService;
exports.SessionService = SessionService;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHBlLWFuZ3VsYXItdG9vbGtpdC1zZXJ2aWNlLnVtZC5qcy5tYXAiLCJzb3VyY2VzIjpbbnVsbCwibmc6Ly9AaHBlL2FuZ3VsYXItdG9vbGtpdC9zZXJ2aWNlL2Fic3RyYWN0LXN1YnNjcmliZXIudHMiLCJuZzovL0BocGUvYW5ndWxhci10b29sa2l0L3NlcnZpY2UvZXZlbnRidXMtc2VydmljZS50cyIsIm5nOi8vQGhwZS9hbmd1bGFyLXRvb2xraXQvc2VydmljZS9hcHBsaWNhdGlvbi1zZXJ2aWNlLnRzIiwibmc6Ly9AaHBlL2FuZ3VsYXItdG9vbGtpdC9zZXJ2aWNlL2h0dHAtc2VydmljZS50cyIsIm5nOi8vQGhwZS9hbmd1bGFyLXRvb2xraXQvc2VydmljZS9sYWJlbC1zZXJ2aWNlLnRzIiwibmc6Ly9AaHBlL2FuZ3VsYXItdG9vbGtpdC9zZXJ2aWNlL25vdGlmaWNhdGlvbi1zZXJ2aWNlLnRzIiwibmc6Ly9AaHBlL2FuZ3VsYXItdG9vbGtpdC9zZXJ2aWNlL3Nlc3Npb24tc2VydmljZS50cyIsIm5nOi8vQGhwZS9hbmd1bGFyLXRvb2xraXQvc2VydmljZS9tb2R1bGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyohICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbkNvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpOyB5b3UgbWF5IG5vdCB1c2VcclxudGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGVcclxuTGljZW5zZSBhdCBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcclxuXHJcblRISVMgQ09ERSBJUyBQUk9WSURFRCBPTiBBTiAqQVMgSVMqIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTllcclxuS0lORCwgRUlUSEVSIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIFdJVEhPVVQgTElNSVRBVElPTiBBTlkgSU1QTElFRFxyXG5XQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgVElUTEUsIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLFxyXG5NRVJDSEFOVEFCTElUWSBPUiBOT04tSU5GUklOR0VNRU5ULlxyXG5cclxuU2VlIHRoZSBBcGFjaGUgVmVyc2lvbiAyLjAgTGljZW5zZSBmb3Igc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zXHJcbmFuZCBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cclxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cclxuLyogZ2xvYmFsIFJlZmxlY3QsIFByb21pc2UgKi9cclxuXHJcbnZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24oZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcclxuICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcclxuICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXh0ZW5kcyhkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG4gICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XHJcbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XHJcbn1cclxuXHJcbmV4cG9ydCB2YXIgX19hc3NpZ24gPSBmdW5jdGlvbigpIHtcclxuICAgIF9fYXNzaWduID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiBfX2Fzc2lnbih0KSB7XHJcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XHJcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XHJcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSkgdFtwXSA9IHNbcF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0O1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIF9fYXNzaWduLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3Jlc3QocywgZSkge1xyXG4gICAgdmFyIHQgPSB7fTtcclxuICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKVxyXG4gICAgICAgIHRbcF0gPSBzW3BdO1xyXG4gICAgaWYgKHMgIT0gbnVsbCAmJiB0eXBlb2YgT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyA9PT0gXCJmdW5jdGlvblwiKVxyXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBwID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhzKTsgaSA8IHAubGVuZ3RoOyBpKyspIGlmIChlLmluZGV4T2YocFtpXSkgPCAwKVxyXG4gICAgICAgICAgICB0W3BbaV1dID0gc1twW2ldXTtcclxuICAgIHJldHVybiB0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xyXG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XHJcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xyXG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcGFyYW0ocGFyYW1JbmRleCwgZGVjb3JhdG9yKSB7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fbWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpIHtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5tZXRhZGF0YSA9PT0gXCJmdW5jdGlvblwiKSByZXR1cm4gUmVmbGVjdC5tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2F3YWl0ZXIodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XHJcbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHJlc3VsdC52YWx1ZSk7IH0pLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cclxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZ2VuZXJhdG9yKHRoaXNBcmcsIGJvZHkpIHtcclxuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XHJcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xyXG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcclxuICAgICAgICB3aGlsZSAoXykgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xyXG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XHJcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxyXG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHBvcnRTdGFyKG0sIGV4cG9ydHMpIHtcclxuICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKCFleHBvcnRzLmhhc093blByb3BlcnR5KHApKSBleHBvcnRzW3BdID0gbVtwXTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fdmFsdWVzKG8pIHtcclxuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXSwgaSA9IDA7XHJcbiAgICBpZiAobSkgcmV0dXJuIG0uY2FsbChvKTtcclxuICAgIHJldHVybiB7XHJcbiAgICAgICAgbmV4dDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAobyAmJiBpID49IG8ubGVuZ3RoKSBvID0gdm9pZCAwO1xyXG4gICAgICAgICAgICByZXR1cm4geyB2YWx1ZTogbyAmJiBvW2krK10sIGRvbmU6ICFvIH07XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVhZChvLCBuKSB7XHJcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07XHJcbiAgICBpZiAoIW0pIHJldHVybiBvO1xyXG4gICAgdmFyIGkgPSBtLmNhbGwobyksIHIsIGFyID0gW10sIGU7XHJcbiAgICB0cnkge1xyXG4gICAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xyXG4gICAgfVxyXG4gICAgY2F0Y2ggKGVycm9yKSB7IGUgPSB7IGVycm9yOiBlcnJvciB9OyB9XHJcbiAgICBmaW5hbGx5IHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVtcInJldHVyblwiXSkpIG0uY2FsbChpKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZmluYWxseSB7IGlmIChlKSB0aHJvdyBlLmVycm9yOyB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gYXI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZCgpIHtcclxuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKVxyXG4gICAgICAgIGFyID0gYXIuY29uY2F0KF9fcmVhZChhcmd1bWVudHNbaV0pKTtcclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXQodikge1xyXG4gICAgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBfX2F3YWl0ID8gKHRoaXMudiA9IHYsIHRoaXMpIDogbmV3IF9fYXdhaXQodik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jR2VuZXJhdG9yKHRoaXNBcmcsIF9hcmd1bWVudHMsIGdlbmVyYXRvcikge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBnID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pLCBpLCBxID0gW107XHJcbiAgICByZXR1cm4gaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgaWYgKGdbbl0pIGlbbl0gPSBmdW5jdGlvbiAodikgeyByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKGEsIGIpIHsgcS5wdXNoKFtuLCB2LCBhLCBiXSkgPiAxIHx8IHJlc3VtZShuLCB2KTsgfSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHJlc3VtZShuLCB2KSB7IHRyeSB7IHN0ZXAoZ1tuXSh2KSk7IH0gY2F0Y2ggKGUpIHsgc2V0dGxlKHFbMF1bM10sIGUpOyB9IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAocikgeyByLnZhbHVlIGluc3RhbmNlb2YgX19hd2FpdCA/IFByb21pc2UucmVzb2x2ZShyLnZhbHVlLnYpLnRoZW4oZnVsZmlsbCwgcmVqZWN0KSA6IHNldHRsZShxWzBdWzJdLCByKTsgfVxyXG4gICAgZnVuY3Rpb24gZnVsZmlsbCh2YWx1ZSkgeyByZXN1bWUoXCJuZXh0XCIsIHZhbHVlKTsgfVxyXG4gICAgZnVuY3Rpb24gcmVqZWN0KHZhbHVlKSB7IHJlc3VtZShcInRocm93XCIsIHZhbHVlKTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKGYsIHYpIHsgaWYgKGYodiksIHEuc2hpZnQoKSwgcS5sZW5ndGgpIHJlc3VtZShxWzBdWzBdLCBxWzBdWzFdKTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY0RlbGVnYXRvcihvKSB7XHJcbiAgICB2YXIgaSwgcDtcclxuICAgIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiwgZnVuY3Rpb24gKGUpIHsgdGhyb3cgZTsgfSksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4sIGYpIHsgaVtuXSA9IG9bbl0gPyBmdW5jdGlvbiAodikgeyByZXR1cm4gKHAgPSAhcCkgPyB7IHZhbHVlOiBfX2F3YWl0KG9bbl0odikpLCBkb25lOiBuID09PSBcInJldHVyblwiIH0gOiBmID8gZih2KSA6IHY7IH0gOiBmOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jVmFsdWVzKG8pIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICB2YXIgbSA9IG9bU3ltYm9sLmFzeW5jSXRlcmF0b3JdLCBpO1xyXG4gICAgcmV0dXJuIG0gPyBtLmNhbGwobykgOiAobyA9IHR5cGVvZiBfX3ZhbHVlcyA9PT0gXCJmdW5jdGlvblwiID8gX192YWx1ZXMobykgOiBvW1N5bWJvbC5pdGVyYXRvcl0oKSwgaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGkpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IGlbbl0gPSBvW25dICYmIGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7IHYgPSBvW25dKHYpLCBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCB2LmRvbmUsIHYudmFsdWUpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgZCwgdikgeyBQcm9taXNlLnJlc29sdmUodikudGhlbihmdW5jdGlvbih2KSB7IHJlc29sdmUoeyB2YWx1ZTogdiwgZG9uZTogZCB9KTsgfSwgcmVqZWN0KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tYWtlVGVtcGxhdGVPYmplY3QoY29va2VkLCByYXcpIHtcclxuICAgIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIHsgT2JqZWN0LmRlZmluZVByb3BlcnR5KGNvb2tlZCwgXCJyYXdcIiwgeyB2YWx1ZTogcmF3IH0pOyB9IGVsc2UgeyBjb29rZWQucmF3ID0gcmF3OyB9XHJcbiAgICByZXR1cm4gY29va2VkO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9faW1wb3J0U3Rhcihtb2QpIHtcclxuICAgIGlmIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpIHJldHVybiBtb2Q7XHJcbiAgICB2YXIgcmVzdWx0ID0ge307XHJcbiAgICBpZiAobW9kICE9IG51bGwpIGZvciAodmFyIGsgaW4gbW9kKSBpZiAoT2JqZWN0Lmhhc093blByb3BlcnR5LmNhbGwobW9kLCBrKSkgcmVzdWx0W2tdID0gbW9kW2tdO1xyXG4gICAgcmVzdWx0LmRlZmF1bHQgPSBtb2Q7XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnREZWZhdWx0KG1vZCkge1xyXG4gICAgcmV0dXJuIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpID8gbW9kIDogeyBkZWZhdWx0OiBtb2QgfTtcclxufVxyXG4iLCIvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLz09PVxuLy89PT0gKEMpIENvcHlyaWdodCAyMDE4IEhld2xldHQgUGFja2FyZCBFbnRlcnByaXNlIERldmVsb3BtZW50IExQLlxuLy89PT1cbi8vPT09IFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4vLz09PSBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmltcG9ydCB7T25EZXN0cm95fSAgICBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHtTdWJzY3JpcHRpb259IGZyb20gXCJyeGpzXCI7XG5cbmltcG9ydCB7RXZlbnRIYW5kbGVyLCBFcnJvckhhbmRsZXIsIEFwcEV2ZW50LCBFcnJvckV2ZW50fSBmcm9tIFwiQGhwZS9hbmd1bGFyLXRvb2xraXQvbW9kZWxcIjtcblxuaW1wb3J0IHtFdmVudEJ1c1NlcnZpY2V9IGZyb20gXCIuL2V2ZW50YnVzLXNlcnZpY2VcIjtcblxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgY2xhc3MgQWJzdHJhY3RTdWJzY3JpYmVyIGltcGxlbWVudHMgT25EZXN0cm95IHtcblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8tLS1cblx0Ly8tLS0gVmFyaWFibGVzXG5cdC8vLS0tXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHByaXZhdGUgc3Vic2NyaXB0aW9uczogU3Vic2NyaXB0aW9uW10gPSBbXTtcblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8tLS1cblx0Ly8tLS0gQ29uc3RydWN0b3Jcblx0Ly8tLS1cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0Y29uc3RydWN0b3IocHJpdmF0ZSBldmVudEJ1c1NlcnZpY2UgOiBFdmVudEJ1c1NlcnZpY2UpIHt9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIExpZmVjeWNsZSBtZXRob2RzXG5cdC8vLS0tXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHB1YmxpYyBuZ09uRGVzdHJveSgpIHtcblx0XHR0aGlzLnN1YnNjcmlwdGlvbnMuZm9yRWFjaCggKHMgOiBTdWJzY3JpcHRpb24pID0+IHMudW5zdWJzY3JpYmUoKSk7XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8tLS1cblx0Ly8tLS0gQVBJIG1ldGhvZHNcblx0Ly8tLS