mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-27 10:26:23 +00:00
c9ce5094c8
So remove the redundant naming
4342 lines
341 KiB
JavaScript
4342 lines
341 KiB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||
var $ = require("jquery");
|
||
|
||
var ActionTypes = {
|
||
// Connection
|
||
CONNECTION_OPEN: "connection_open",
|
||
CONNECTION_CLOSE: "connection_close",
|
||
CONNECTION_ERROR: "connection_error",
|
||
|
||
// Stores
|
||
SETTINGS_STORE: "settings",
|
||
EVENT_STORE: "events",
|
||
FLOW_STORE: "flows",
|
||
};
|
||
|
||
var StoreCmds = {
|
||
ADD: "add",
|
||
UPDATE: "update",
|
||
REMOVE: "remove",
|
||
RESET: "reset"
|
||
};
|
||
|
||
var ConnectionActions = {
|
||
open: function () {
|
||
AppDispatcher.dispatchViewAction({
|
||
type: ActionTypes.CONNECTION_OPEN
|
||
});
|
||
},
|
||
close: function () {
|
||
AppDispatcher.dispatchViewAction({
|
||
type: ActionTypes.CONNECTION_CLOSE
|
||
});
|
||
},
|
||
error: function () {
|
||
AppDispatcher.dispatchViewAction({
|
||
type: ActionTypes.CONNECTION_ERROR
|
||
});
|
||
}
|
||
};
|
||
|
||
var SettingsActions = {
|
||
update: function (settings) {
|
||
|
||
$.ajax({
|
||
type: "PUT",
|
||
url: "/settings",
|
||
data: settings
|
||
});
|
||
|
||
/*
|
||
//Facebook Flux: We do an optimistic update on the client already.
|
||
AppDispatcher.dispatchViewAction({
|
||
type: ActionTypes.SETTINGS_STORE,
|
||
cmd: StoreCmds.UPDATE,
|
||
data: settings
|
||
});
|
||
*/
|
||
}
|
||
};
|
||
|
||
var EventLogActions_event_id = 0;
|
||
var EventLogActions = {
|
||
add_event: function (message) {
|
||
AppDispatcher.dispatchViewAction({
|
||
type: ActionTypes.EVENT_STORE,
|
||
cmd: StoreCmds.ADD,
|
||
data: {
|
||
message: message,
|
||
level: "web",
|
||
id: "viewAction-" + EventLogActions_event_id++
|
||
}
|
||
});
|
||
}
|
||
};
|
||
|
||
var FlowActions = {
|
||
accept: function (flow) {
|
||
$.post("/flows/" + flow.id + "/accept");
|
||
},
|
||
accept_all: function(){
|
||
$.post("/flows/accept");
|
||
},
|
||
"delete": function(flow){
|
||
$.ajax({
|
||
type:"DELETE",
|
||
url: "/flows/" + flow.id
|
||
});
|
||
},
|
||
duplicate: function(flow){
|
||
$.post("/flows/" + flow.id + "/duplicate");
|
||
},
|
||
replay: function(flow){
|
||
$.post("/flows/" + flow.id + "/replay");
|
||
},
|
||
revert: function(flow){
|
||
$.post("/flows/" + flow.id + "/revert");
|
||
},
|
||
update: function (flow) {
|
||
AppDispatcher.dispatchViewAction({
|
||
type: ActionTypes.FLOW_STORE,
|
||
cmd: StoreCmds.UPDATE,
|
||
data: flow
|
||
});
|
||
},
|
||
clear: function(){
|
||
$.post("/clear");
|
||
}
|
||
};
|
||
|
||
Query = {
|
||
FILTER: "f",
|
||
HIGHLIGHT: "h",
|
||
SHOW_EVENTLOG: "e"
|
||
};
|
||
|
||
module.exports = {
|
||
ActionTypes: ActionTypes,
|
||
ConnectionActions: ConnectionActions,
|
||
FlowActions: FlowActions,
|
||
StoreCmds: StoreCmds
|
||
|
||
|
||
};
|
||
},{"jquery":"jquery"}],2:[function(require,module,exports){
|
||
|
||
var React = require("react");
|
||
var ReactRouter = require("react-router");
|
||
var $ = require("jquery");
|
||
|
||
var Connection = require("./connection");
|
||
var proxyapp = require("./components/proxyapp.js");
|
||
|
||
$(function () {
|
||
window.ws = new Connection("/updates");
|
||
|
||
ReactRouter.run(proxyapp.routes, function (Handler) {
|
||
React.render(React.createElement(Handler, null), document.body);
|
||
});
|
||
});
|
||
},{"./components/proxyapp.js":10,"./connection":13,"jquery":"jquery","react":"react","react-router":"react-router"}],3:[function(require,module,exports){
|
||
var React = require("react");
|
||
var utils = require("./utils.js");
|
||
var VirtualScrollMixin = require("./virtualscroll.js");
|
||
var views = require("../store/view.js");
|
||
|
||
var LogMessage = React.createClass({displayName: "LogMessage",
|
||
render: function () {
|
||
var entry = this.props.entry;
|
||
var indicator;
|
||
switch (entry.level) {
|
||
case "web":
|
||
indicator = React.createElement("i", {className: "fa fa-fw fa-html5"});
|
||
break;
|
||
case "debug":
|
||
indicator = React.createElement("i", {className: "fa fa-fw fa-bug"});
|
||
break;
|
||
default:
|
||
indicator = React.createElement("i", {className: "fa fa-fw fa-info"});
|
||
}
|
||
return (
|
||
React.createElement("div", null,
|
||
indicator, " ", entry.message
|
||
)
|
||
);
|
||
},
|
||
shouldComponentUpdate: function () {
|
||
return false; // log entries are immutable.
|
||
}
|
||
});
|
||
|
||
var EventLogContents = React.createClass({displayName: "EventLogContents",
|
||
mixins: [utils.AutoScrollMixin, VirtualScrollMixin],
|
||
getInitialState: function () {
|
||
return {
|
||
log: []
|
||
};
|
||
},
|
||
componentWillMount: function () {
|
||
this.openView(this.props.eventStore);
|
||
},
|
||
componentWillUnmount: function () {
|
||
this.closeView();
|
||
},
|
||
openView: function (store) {
|
||
var view = new views.StoreView(store, function (entry) {
|
||
return this.props.filter[entry.level];
|
||
}.bind(this));
|
||
this.setState({
|
||
view: view
|
||
});
|
||
|
||
view.addListener("add recalculate", this.onEventLogChange);
|
||
},
|
||
closeView: function () {
|
||
this.state.view.close();
|
||
},
|
||
onEventLogChange: function () {
|
||
this.setState({
|
||
log: this.state.view.list
|
||
});
|
||
},
|
||
componentWillReceiveProps: function (nextProps) {
|
||
if (nextProps.filter !== this.props.filter) {
|
||
this.props.filter = nextProps.filter; // Dirty: Make sure that view filter sees the update.
|
||
this.state.view.recalculate();
|
||
}
|
||
if (nextProps.eventStore !== this.props.eventStore) {
|
||
this.closeView();
|
||
this.openView(nextProps.eventStore);
|
||
}
|
||
},
|
||
getDefaultProps: function () {
|
||
return {
|
||
rowHeight: 45,
|
||
rowHeightMin: 15,
|
||
placeholderTagName: "div"
|
||
};
|
||
},
|
||
renderRow: function (elem) {
|
||
return React.createElement(LogMessage, {key: elem.id, entry: elem});
|
||
},
|
||
render: function () {
|
||
var rows = this.renderRows(this.state.log);
|
||
|
||
return React.createElement("pre", {onScroll: this.onScroll},
|
||
this.getPlaceholderTop(this.state.log.length),
|
||
rows,
|
||
this.getPlaceholderBottom(this.state.log.length)
|
||
);
|
||
}
|
||
});
|
||
|
||
var ToggleFilter = React.createClass({displayName: "ToggleFilter",
|
||
toggle: function (e) {
|
||
e.preventDefault();
|
||
return this.props.toggleLevel(this.props.name);
|
||
},
|
||
render: function () {
|
||
var className = "label ";
|
||
if (this.props.active) {
|
||
className += "label-primary";
|
||
} else {
|
||
className += "label-default";
|
||
}
|
||
return (
|
||
React.createElement("a", {
|
||
href: "#",
|
||
className: className,
|
||
onClick: this.toggle},
|
||
this.props.name
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
var EventLog = React.createClass({displayName: "EventLog",
|
||
getInitialState: function () {
|
||
return {
|
||
filter: {
|
||
"debug": false,
|
||
"info": true,
|
||
"web": true
|
||
}
|
||
};
|
||
},
|
||
close: function () {
|
||
var d = {};
|
||
d[Query.SHOW_EVENTLOG] = undefined;
|
||
this.setQuery(d);
|
||
},
|
||
toggleLevel: function (level) {
|
||
var filter = _.extend({}, this.state.filter);
|
||
filter[level] = !filter[level];
|
||
this.setState({filter: filter});
|
||
},
|
||
render: function () {
|
||
return (
|
||
React.createElement("div", {className: "eventlog"},
|
||
React.createElement("div", null,
|
||
"Eventlog",
|
||
React.createElement("div", {className: "pull-right"},
|
||
React.createElement(ToggleFilter, {name: "debug", active: this.state.filter.debug, toggleLevel: this.toggleLevel}),
|
||
React.createElement(ToggleFilter, {name: "info", active: this.state.filter.info, toggleLevel: this.toggleLevel}),
|
||
React.createElement(ToggleFilter, {name: "web", active: this.state.filter.web, toggleLevel: this.toggleLevel}),
|
||
React.createElement("i", {onClick: this.close, className: "fa fa-close"})
|
||
)
|
||
|
||
),
|
||
React.createElement(EventLogContents, {filter: this.state.filter, eventStore: this.props.eventStore})
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
module.exports = EventLog;
|
||
},{"../store/view.js":18,"./utils.js":11,"./virtualscroll.js":12,"react":"react"}],4:[function(require,module,exports){
|
||
var React = require("react");
|
||
var _ = require("lodash");
|
||
|
||
var utils = require("./utils.js");
|
||
var actions = require("../actions.js");
|
||
var flowutils = require("../flow/utils.js");
|
||
var toputils = require("../utils.js");
|
||
|
||
var NavAction = React.createClass({displayName: "NavAction",
|
||
onClick: function (e) {
|
||
e.preventDefault();
|
||
this.props.onClick();
|
||
},
|
||
render: function () {
|
||
return (
|
||
React.createElement("a", {title: this.props.title,
|
||
href: "#",
|
||
className: "nav-action",
|
||
onClick: this.onClick},
|
||
React.createElement("i", {className: "fa fa-fw " + this.props.icon})
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
var FlowDetailNav = React.createClass({displayName: "FlowDetailNav",
|
||
render: function () {
|
||
var flow = this.props.flow;
|
||
|
||
var tabs = this.props.tabs.map(function (e) {
|
||
var str = e.charAt(0).toUpperCase() + e.slice(1);
|
||
var className = this.props.active === e ? "active" : "";
|
||
var onClick = function (event) {
|
||
this.props.selectTab(e);
|
||
event.preventDefault();
|
||
}.bind(this);
|
||
return React.createElement("a", {key: e,
|
||
href: "#",
|
||
className: className,
|
||
onClick: onClick}, str);
|
||
}.bind(this));
|
||
|
||
var acceptButton = null;
|
||
if(flow.intercepted){
|
||
acceptButton = React.createElement(NavAction, {title: "[a]ccept intercepted flow", icon: "fa-play", onClick: actions.FlowActions.accept.bind(null, flow)});
|
||
}
|
||
var revertButton = null;
|
||
if(flow.modified){
|
||
revertButton = React.createElement(NavAction, {title: "revert changes to flow [V]", icon: "fa-history", onClick: actions.FlowActions.revert.bind(null, flow)});
|
||
}
|
||
|
||
return (
|
||
React.createElement("nav", {ref: "head", className: "nav-tabs nav-tabs-sm"},
|
||
tabs,
|
||
React.createElement(NavAction, {title: "[d]elete flow", icon: "fa-trash", onClick: actions.FlowActions.delete.bind(null, flow)}),
|
||
React.createElement(NavAction, {title: "[D]uplicate flow", icon: "fa-copy", onClick: actions.FlowActions.duplicate.bind(null, flow)}),
|
||
React.createElement(NavAction, {disabled: true, title: "[r]eplay flow", icon: "fa-repeat", onClick: actions.FlowActions.replay.bind(null, flow)}),
|
||
acceptButton,
|
||
revertButton
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
var Headers = React.createClass({displayName: "Headers",
|
||
render: function () {
|
||
var rows = this.props.message.headers.map(function (header, i) {
|
||
return (
|
||
React.createElement("tr", {key: i},
|
||
React.createElement("td", {className: "header-name"}, header[0] + ":"),
|
||
React.createElement("td", {className: "header-value"}, header[1])
|
||
)
|
||
);
|
||
});
|
||
return (
|
||
React.createElement("table", {className: "header-table"},
|
||
React.createElement("tbody", null,
|
||
rows
|
||
)
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
var FlowDetailRequest = React.createClass({displayName: "FlowDetailRequest",
|
||
render: function () {
|
||
var flow = this.props.flow;
|
||
var first_line = [
|
||
flow.request.method,
|
||
flowutils.RequestUtils.pretty_url(flow.request),
|
||
"HTTP/" + flow.request.httpversion.join(".")
|
||
].join(" ");
|
||
var content = null;
|
||
if (flow.request.contentLength > 0) {
|
||
content = "Request Content Size: " + toputils.formatSize(flow.request.contentLength);
|
||
} else {
|
||
content = React.createElement("div", {className: "alert alert-info"}, "No Content");
|
||
}
|
||
|
||
//TODO: Styling
|
||
|
||
return (
|
||
React.createElement("section", null,
|
||
React.createElement("div", {className: "first-line"}, first_line ),
|
||
React.createElement(Headers, {message: flow.request}),
|
||
React.createElement("hr", null),
|
||
content
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
var FlowDetailResponse = React.createClass({displayName: "FlowDetailResponse",
|
||
render: function () {
|
||
var flow = this.props.flow;
|
||
var first_line = [
|
||
"HTTP/" + flow.response.httpversion.join("."),
|
||
flow.response.code,
|
||
flow.response.msg
|
||
].join(" ");
|
||
var content = null;
|
||
if (flow.response.contentLength > 0) {
|
||
content = "Response Content Size: " + toputils.formatSize(flow.response.contentLength);
|
||
} else {
|
||
content = React.createElement("div", {className: "alert alert-info"}, "No Content");
|
||
}
|
||
|
||
//TODO: Styling
|
||
|
||
return (
|
||
React.createElement("section", null,
|
||
React.createElement("div", {className: "first-line"}, first_line ),
|
||
React.createElement(Headers, {message: flow.response}),
|
||
React.createElement("hr", null),
|
||
content
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
var FlowDetailError = React.createClass({displayName: "FlowDetailError",
|
||
render: function () {
|
||
var flow = this.props.flow;
|
||
return (
|
||
React.createElement("section", null,
|
||
React.createElement("div", {className: "alert alert-warning"},
|
||
flow.error.msg,
|
||
React.createElement("div", null,
|
||
React.createElement("small", null, toputils.formatTimeStamp(flow.error.timestamp) )
|
||
)
|
||
)
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
var TimeStamp = React.createClass({displayName: "TimeStamp",
|
||
render: function () {
|
||
|
||
if (!this.props.t) {
|
||
//should be return null, but that triggers a React bug.
|
||
return React.createElement("tr", null);
|
||
}
|
||
|
||
var ts = toputils.formatTimeStamp(this.props.t);
|
||
|
||
var delta;
|
||
if (this.props.deltaTo) {
|
||
delta = toputils.formatTimeDelta(1000 * (this.props.t - this.props.deltaTo));
|
||
delta = React.createElement("span", {className: "text-muted"}, "(" + delta + ")");
|
||
} else {
|
||
delta = null;
|
||
}
|
||
|
||
return React.createElement("tr", null,
|
||
React.createElement("td", null, this.props.title + ":"),
|
||
React.createElement("td", null, ts, " ", delta)
|
||
);
|
||
}
|
||
});
|
||
|
||
var ConnectionInfo = React.createClass({displayName: "ConnectionInfo",
|
||
|
||
render: function () {
|
||
var conn = this.props.conn;
|
||
var address = conn.address.address.join(":");
|
||
|
||
var sni = React.createElement("tr", {key: "sni"}); //should be null, but that triggers a React bug.
|
||
if (conn.sni) {
|
||
sni = React.createElement("tr", {key: "sni"},
|
||
React.createElement("td", null,
|
||
React.createElement("abbr", {title: "TLS Server Name Indication"}, "TLS SNI:")
|
||
),
|
||
React.createElement("td", null, conn.sni)
|
||
);
|
||
}
|
||
return (
|
||
React.createElement("table", {className: "connection-table"},
|
||
React.createElement("tbody", null,
|
||
React.createElement("tr", {key: "address"},
|
||
React.createElement("td", null, "Address:"),
|
||
React.createElement("td", null, address)
|
||
),
|
||
sni
|
||
)
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
var CertificateInfo = React.createClass({displayName: "CertificateInfo",
|
||
render: function () {
|
||
//TODO: We should fetch human-readable certificate representation
|
||
// from the server
|
||
var flow = this.props.flow;
|
||
var client_conn = flow.client_conn;
|
||
var server_conn = flow.server_conn;
|
||
|
||
var preStyle = {maxHeight: 100};
|
||
return (
|
||
React.createElement("div", null,
|
||
client_conn.cert ? React.createElement("h4", null, "Client Certificate") : null,
|
||
client_conn.cert ? React.createElement("pre", {style: preStyle}, client_conn.cert) : null,
|
||
|
||
server_conn.cert ? React.createElement("h4", null, "Server Certificate") : null,
|
||
server_conn.cert ? React.createElement("pre", {style: preStyle}, server_conn.cert) : null
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
var Timing = React.createClass({displayName: "Timing",
|
||
render: function () {
|
||
var flow = this.props.flow;
|
||
var sc = flow.server_conn;
|
||
var cc = flow.client_conn;
|
||
var req = flow.request;
|
||
var resp = flow.response;
|
||
|
||
var timestamps = [
|
||
{
|
||
title: "Server conn. initiated",
|
||
t: sc.timestamp_start,
|
||
deltaTo: req.timestamp_start
|
||
}, {
|
||
title: "Server conn. TCP handshake",
|
||
t: sc.timestamp_tcp_setup,
|
||
deltaTo: req.timestamp_start
|
||
}, {
|
||
title: "Server conn. SSL handshake",
|
||
t: sc.timestamp_ssl_setup,
|
||
deltaTo: req.timestamp_start
|
||
}, {
|
||
title: "Client conn. established",
|
||
t: cc.timestamp_start,
|
||
deltaTo: req.timestamp_start
|
||
}, {
|
||
title: "Client conn. SSL handshake",
|
||
t: cc.timestamp_ssl_setup,
|
||
deltaTo: req.timestamp_start
|
||
}, {
|
||
title: "First request byte",
|
||
t: req.timestamp_start,
|
||
}, {
|
||
title: "Request complete",
|
||
t: req.timestamp_end,
|
||
deltaTo: req.timestamp_start
|
||
}
|
||
];
|
||
|
||
if (flow.response) {
|
||
timestamps.push(
|
||
{
|
||
title: "First response byte",
|
||
t: resp.timestamp_start,
|
||
deltaTo: req.timestamp_start
|
||
}, {
|
||
title: "Response complete",
|
||
t: resp.timestamp_end,
|
||
deltaTo: req.timestamp_start
|
||
}
|
||
);
|
||
}
|
||
|
||
//Add unique key for each row.
|
||
timestamps.forEach(function (e) {
|
||
e.key = e.title;
|
||
});
|
||
|
||
timestamps = _.sortBy(timestamps, 't');
|
||
|
||
var rows = timestamps.map(function (e) {
|
||
return React.createElement(TimeStamp, React.__spread({}, e));
|
||
});
|
||
|
||
return (
|
||
React.createElement("div", null,
|
||
React.createElement("h4", null, "Timing"),
|
||
React.createElement("table", {className: "timing-table"},
|
||
React.createElement("tbody", null,
|
||
rows
|
||
)
|
||
)
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
var FlowDetailConnectionInfo = React.createClass({displayName: "FlowDetailConnectionInfo",
|
||
render: function () {
|
||
var flow = this.props.flow;
|
||
var client_conn = flow.client_conn;
|
||
var server_conn = flow.server_conn;
|
||
return (
|
||
React.createElement("section", null,
|
||
|
||
React.createElement("h4", null, "Client Connection"),
|
||
React.createElement(ConnectionInfo, {conn: client_conn}),
|
||
|
||
React.createElement("h4", null, "Server Connection"),
|
||
React.createElement(ConnectionInfo, {conn: server_conn}),
|
||
|
||
React.createElement(CertificateInfo, {flow: flow}),
|
||
|
||
React.createElement(Timing, {flow: flow})
|
||
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
var allTabs = {
|
||
request: FlowDetailRequest,
|
||
response: FlowDetailResponse,
|
||
error: FlowDetailError,
|
||
details: FlowDetailConnectionInfo
|
||
};
|
||
|
||
var FlowDetail = React.createClass({displayName: "FlowDetail",
|
||
mixins: [utils.StickyHeadMixin, utils.Navigation, utils.State],
|
||
getTabs: function (flow) {
|
||
var tabs = [];
|
||
["request", "response", "error"].forEach(function (e) {
|
||
if (flow[e]) {
|
||
tabs.push(e);
|
||
}
|
||
});
|
||
tabs.push("details");
|
||
return tabs;
|
||
},
|
||
nextTab: function (i) {
|
||
var tabs = this.getTabs(this.props.flow);
|
||
var currentIndex = tabs.indexOf(this.getParams().detailTab);
|
||
// JS modulo operator doesn't correct negative numbers, make sure that we are positive.
|
||
var nextIndex = (currentIndex + i + tabs.length) % tabs.length;
|
||
this.selectTab(tabs[nextIndex]);
|
||
},
|
||
selectTab: function (panel) {
|
||
this.replaceWith(
|
||
"flow",
|
||
{
|
||
flowId: this.getParams().flowId,
|
||
detailTab: panel
|
||
}
|
||
);
|
||
},
|
||
render: function () {
|
||
var flow = this.props.flow;
|
||
var tabs = this.getTabs(flow);
|
||
var active = this.getParams().detailTab;
|
||
|
||
if (!_.contains(tabs, active)) {
|
||
if (active === "response" && flow.error) {
|
||
active = "error";
|
||
} else if (active === "error" && flow.response) {
|
||
active = "response";
|
||
} else {
|
||
active = tabs[0];
|
||
}
|
||
this.selectTab(active);
|
||
}
|
||
|
||
var Tab = allTabs[active];
|
||
return (
|
||
React.createElement("div", {className: "flow-detail", onScroll: this.adjustHead},
|
||
React.createElement(FlowDetailNav, {ref: "head",
|
||
flow: flow,
|
||
tabs: tabs,
|
||
active: active,
|
||
selectTab: this.selectTab}),
|
||
React.createElement(Tab, {flow: flow})
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
module.exports = {
|
||
FlowDetail: FlowDetail
|
||
};
|
||
},{"../actions.js":1,"../flow/utils.js":16,"../utils.js":19,"./utils.js":11,"lodash":"lodash","react":"react"}],5:[function(require,module,exports){
|
||
var React = require("react");
|
||
var flowutils = require("../flow/utils.js");
|
||
var utils = require("../utils.js");
|
||
|
||
var TLSColumn = React.createClass({displayName: "TLSColumn",
|
||
statics: {
|
||
renderTitle: function () {
|
||
return React.createElement("th", {key: "tls", className: "col-tls"});
|
||
}
|
||
},
|
||
render: function () {
|
||
var flow = this.props.flow;
|
||
var ssl = (flow.request.scheme == "https");
|
||
var classes;
|
||
if (ssl) {
|
||
classes = "col-tls col-tls-https";
|
||
} else {
|
||
classes = "col-tls col-tls-http";
|
||
}
|
||
return React.createElement("td", {className: classes});
|
||
}
|
||
});
|
||
|
||
|
||
var IconColumn = React.createClass({displayName: "IconColumn",
|
||
statics: {
|
||
renderTitle: function () {
|
||
return React.createElement("th", {key: "icon", className: "col-icon"});
|
||
}
|
||
},
|
||
render: function () {
|
||
var flow = this.props.flow;
|
||
|
||
var icon;
|
||
if (flow.response) {
|
||
var contentType = flowutils.ResponseUtils.getContentType(flow.response);
|
||
|
||
//TODO: We should assign a type to the flow somewhere else.
|
||
if (flow.response.code == 304) {
|
||
icon = "resource-icon-not-modified";
|
||
} else if (300 <= flow.response.code && flow.response.code < 400) {
|
||
icon = "resource-icon-redirect";
|
||
} else if (contentType && contentType.indexOf("image") >= 0) {
|
||
icon = "resource-icon-image";
|
||
} else if (contentType && contentType.indexOf("javascript") >= 0) {
|
||
icon = "resource-icon-js";
|
||
} else if (contentType && contentType.indexOf("css") >= 0) {
|
||
icon = "resource-icon-css";
|
||
} else if (contentType && contentType.indexOf("html") >= 0) {
|
||
icon = "resource-icon-document";
|
||
}
|
||
}
|
||
if (!icon) {
|
||
icon = "resource-icon-plain";
|
||
}
|
||
|
||
|
||
icon += " resource-icon";
|
||
return React.createElement("td", {className: "col-icon"},
|
||
React.createElement("div", {className: icon})
|
||
);
|
||
}
|
||
});
|
||
|
||
var PathColumn = React.createClass({displayName: "PathColumn",
|
||
statics: {
|
||
renderTitle: function () {
|
||
return React.createElement("th", {key: "path", className: "col-path"}, "Path");
|
||
}
|
||
},
|
||
render: function () {
|
||
var flow = this.props.flow;
|
||
return React.createElement("td", {className: "col-path"},
|
||
flow.request.is_replay ? React.createElement("i", {className: "fa fa-fw fa-repeat pull-right"}) : null,
|
||
flow.intercepted ? React.createElement("i", {className: "fa fa-fw fa-pause pull-right"}) : null,
|
||
flow.request.scheme + "://" + flow.request.host + flow.request.path
|
||
);
|
||
}
|
||
});
|
||
|
||
|
||
var MethodColumn = React.createClass({displayName: "MethodColumn",
|
||
statics: {
|
||
renderTitle: function () {
|
||
return React.createElement("th", {key: "method", className: "col-method"}, "Method");
|
||
}
|
||
},
|
||
render: function () {
|
||
var flow = this.props.flow;
|
||
return React.createElement("td", {className: "col-method"}, flow.request.method);
|
||
}
|
||
});
|
||
|
||
|
||
var StatusColumn = React.createClass({displayName: "StatusColumn",
|
||
statics: {
|
||
renderTitle: function () {
|
||
return React.createElement("th", {key: "status", className: "col-status"}, "Status");
|
||
}
|
||
},
|
||
render: function () {
|
||
var flow = this.props.flow;
|
||
var status;
|
||
if (flow.response) {
|
||
status = flow.response.code;
|
||
} else {
|
||
status = null;
|
||
}
|
||
return React.createElement("td", {className: "col-status"}, status);
|
||
}
|
||
});
|
||
|
||
|
||
var SizeColumn = React.createClass({displayName: "SizeColumn",
|
||
statics: {
|
||
renderTitle: function () {
|
||
return React.createElement("th", {key: "size", className: "col-size"}, "Size");
|
||
}
|
||
},
|
||
render: function () {
|
||
var flow = this.props.flow;
|
||
|
||
var total = flow.request.contentLength;
|
||
if (flow.response) {
|
||
total += flow.response.contentLength || 0;
|
||
}
|
||
var size = utils.formatSize(total);
|
||
return React.createElement("td", {className: "col-size"}, size);
|
||
}
|
||
});
|
||
|
||
|
||
var TimeColumn = React.createClass({displayName: "TimeColumn",
|
||
statics: {
|
||
renderTitle: function () {
|
||
return React.createElement("th", {key: "time", className: "col-time"}, "Time");
|
||
}
|
||
},
|
||
render: function () {
|
||
var flow = this.props.flow;
|
||
var time;
|
||
if (flow.response) {
|
||
time = utils.formatTimeDelta(1000 * (flow.response.timestamp_end - flow.request.timestamp_start));
|
||
} else {
|
||
time = "...";
|
||
}
|
||
return React.createElement("td", {className: "col-time"}, time);
|
||
}
|
||
});
|
||
|
||
|
||
var all_columns = [
|
||
TLSColumn,
|
||
IconColumn,
|
||
PathColumn,
|
||
MethodColumn,
|
||
StatusColumn,
|
||
SizeColumn,
|
||
TimeColumn];
|
||
|
||
|
||
module.exports = all_columns;
|
||
|
||
|
||
|
||
},{"../flow/utils.js":16,"../utils.js":19,"react":"react"}],6:[function(require,module,exports){
|
||
var React = require("react");
|
||
var utils = require("./utils.js");
|
||
var VirtualScrollMixin = require("./virtualscroll.js");
|
||
var flowtable_columns = require("./flowtable-columns.js");
|
||
|
||
var FlowRow = React.createClass({displayName: "FlowRow",
|
||
render: function () {
|
||
var flow = this.props.flow;
|
||
var columns = this.props.columns.map(function (Column) {
|
||
return React.createElement(Column, {key: Column.displayName, flow: flow});
|
||
}.bind(this));
|
||
var className = "";
|
||
if (this.props.selected) {
|
||
className += " selected";
|
||
}
|
||
if (this.props.highlighted) {
|
||
className += " highlighted";
|
||
}
|
||
if (flow.intercepted) {
|
||
className += " intercepted";
|
||
}
|
||
if (flow.request) {
|
||
className += " has-request";
|
||
}
|
||
if (flow.response) {
|
||
className += " has-response";
|
||
}
|
||
|
||
return (
|
||
React.createElement("tr", {className: className, onClick: this.props.selectFlow.bind(null, flow)},
|
||
columns
|
||
));
|
||
},
|
||
shouldComponentUpdate: function (nextProps) {
|
||
return true;
|
||
// Further optimization could be done here
|
||
// by calling forceUpdate on flow updates, selection changes and column changes.
|
||
//return (
|
||
//(this.props.columns.length !== nextProps.columns.length) ||
|
||
//(this.props.selected !== nextProps.selected)
|
||
//);
|
||
}
|
||
});
|
||
|
||
var FlowTableHead = React.createClass({displayName: "FlowTableHead",
|
||
render: function () {
|
||
var columns = this.props.columns.map(function (column) {
|
||
return column.renderTitle();
|
||
}.bind(this));
|
||
return React.createElement("thead", null,
|
||
React.createElement("tr", null, columns)
|
||
);
|
||
}
|
||
});
|
||
|
||
|
||
var ROW_HEIGHT = 32;
|
||
|
||
var FlowTable = React.createClass({displayName: "FlowTable",
|
||
mixins: [utils.StickyHeadMixin, utils.AutoScrollMixin, VirtualScrollMixin],
|
||
getInitialState: function () {
|
||
return {
|
||
columns: flowtable_columns
|
||
};
|
||
},
|
||
componentWillMount: function () {
|
||
if (this.props.view) {
|
||
this.props.view.addListener("add update remove recalculate", this.onChange);
|
||
}
|
||
},
|
||
componentWillReceiveProps: function (nextProps) {
|
||
if (nextProps.view !== this.props.view) {
|
||
if (this.props.view) {
|
||
this.props.view.removeListener("add update remove recalculate");
|
||
}
|
||
nextProps.view.addListener("add update remove recalculate", this.onChange);
|
||
}
|
||
},
|
||
getDefaultProps: function () {
|
||
return {
|
||
rowHeight: ROW_HEIGHT
|
||
};
|
||
},
|
||
onScrollFlowTable: function () {
|
||
this.adjustHead();
|
||
this.onScroll();
|
||
},
|
||
onChange: function () {
|
||
this.forceUpdate();
|
||
},
|
||
scrollIntoView: function (flow) {
|
||
this.scrollRowIntoView(
|
||
this.props.view.index(flow),
|
||
this.refs.body.getDOMNode().offsetTop
|
||
);
|
||
},
|
||
renderRow: function (flow) {
|
||
var selected = (flow === this.props.selected);
|
||
var highlighted =
|
||
(
|
||
this.props.view._highlight &&
|
||
this.props.view._highlight[flow.id]
|
||
);
|
||
|
||
return React.createElement(FlowRow, {key: flow.id,
|
||
ref: flow.id,
|
||
flow: flow,
|
||
columns: this.state.columns,
|
||
selected: selected,
|
||
highlighted: highlighted,
|
||
selectFlow: this.props.selectFlow}
|
||
);
|
||
},
|
||
render: function () {
|
||
//console.log("render flowtable", this.state.start, this.state.stop, this.props.selected);
|
||
var flows = this.props.view ? this.props.view.list : [];
|
||
|
||
var rows = this.renderRows(flows);
|
||
|
||
return (
|
||
React.createElement("div", {className: "flow-table", onScroll: this.onScrollFlowTable},
|
||
React.createElement("table", null,
|
||
React.createElement(FlowTableHead, {ref: "head",
|
||
columns: this.state.columns}),
|
||
React.createElement("tbody", {ref: "body"},
|
||
this.getPlaceholderTop(flows.length),
|
||
rows,
|
||
this.getPlaceholderBottom(flows.length)
|
||
)
|
||
)
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
module.exports = FlowTable;
|
||
|
||
},{"./flowtable-columns.js":5,"./utils.js":11,"./virtualscroll.js":12,"react":"react"}],7:[function(require,module,exports){
|
||
var React = require("react");
|
||
|
||
var Footer = React.createClass({displayName: "Footer",
|
||
render: function () {
|
||
var mode = this.props.settings.mode;
|
||
var intercept = this.props.settings.intercept;
|
||
return (
|
||
React.createElement("footer", null,
|
||
mode != "regular" ? React.createElement("span", {className: "label label-success"}, mode, " mode") : null,
|
||
" ",
|
||
intercept ? React.createElement("span", {className: "label label-success"}, "Intercept: ", intercept) : null
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
module.exports = Footer;
|
||
},{"react":"react"}],8:[function(require,module,exports){
|
||
var React = require("react");
|
||
var $ = require("jquery");
|
||
|
||
var utils = require("./utils.js");
|
||
|
||
var FilterDocs = React.createClass({displayName: "FilterDocs",
|
||
statics: {
|
||
xhr: false,
|
||
doc: false
|
||
},
|
||
componentWillMount: function () {
|
||
if (!FilterDocs.doc) {
|
||
FilterDocs.xhr = $.getJSON("/filter-help").done(function (doc) {
|
||
FilterDocs.doc = doc;
|
||
FilterDocs.xhr = false;
|
||
});
|
||
}
|
||
if (FilterDocs.xhr) {
|
||
FilterDocs.xhr.done(function () {
|
||
this.forceUpdate();
|
||
}.bind(this));
|
||
}
|
||
},
|
||
render: function () {
|
||
if (!FilterDocs.doc) {
|
||
return React.createElement("i", {className: "fa fa-spinner fa-spin"});
|
||
} else {
|
||
var commands = FilterDocs.doc.commands.map(function (c) {
|
||
return React.createElement("tr", null,
|
||
React.createElement("td", null, c[0].replace(" ", '\u00a0')),
|
||
React.createElement("td", null, c[1])
|
||
);
|
||
});
|
||
commands.push(React.createElement("tr", null,
|
||
React.createElement("td", {colSpan: "2"},
|
||
React.createElement("a", {href: "https://mitmproxy.org/doc/features/filters.html",
|
||
target: "_blank"},
|
||
React.createElement("i", {className: "fa fa-external-link"}),
|
||
" mitmproxy docs")
|
||
)
|
||
));
|
||
return React.createElement("table", {className: "table table-condensed"},
|
||
React.createElement("tbody", null, commands)
|
||
);
|
||
}
|
||
}
|
||
});
|
||
var FilterInput = React.createClass({displayName: "FilterInput",
|
||
getInitialState: function () {
|
||
// Consider both focus and mouseover for showing/hiding the tooltip,
|
||
// because onBlur of the input is triggered before the click on the tooltip
|
||
// finalized, hiding the tooltip just as the user clicks on it.
|
||
return {
|
||
value: this.props.value,
|
||
focus: false,
|
||
mousefocus: false
|
||
};
|
||
},
|
||
componentWillReceiveProps: function (nextProps) {
|
||
this.setState({value: nextProps.value});
|
||
},
|
||
onChange: function (e) {
|
||
var nextValue = e.target.value;
|
||
this.setState({
|
||
value: nextValue
|
||
});
|
||
// Only propagate valid filters upwards.
|
||
if (this.isValid(nextValue)) {
|
||
this.props.onChange(nextValue);
|
||
}
|
||
},
|
||
isValid: function (filt) {
|
||
try {
|
||
Filt.parse(filt || this.state.value);
|
||
return true;
|
||
} catch (e) {
|
||
return false;
|
||
}
|
||
},
|
||
getDesc: function () {
|
||
var desc;
|
||
try {
|
||
desc = Filt.parse(this.state.value).desc;
|
||
} catch (e) {
|
||
desc = "" + e;
|
||
}
|
||
if (desc !== "true") {
|
||
return desc;
|
||
} else {
|
||
return (
|
||
React.createElement(FilterDocs, null)
|
||
);
|
||
}
|
||
},
|
||
onFocus: function () {
|
||
this.setState({focus: true});
|
||
},
|
||
onBlur: function () {
|
||
this.setState({focus: false});
|
||
},
|
||
onMouseEnter: function () {
|
||
this.setState({mousefocus: true});
|
||
},
|
||
onMouseLeave: function () {
|
||
this.setState({mousefocus: false});
|
||
},
|
||
onKeyDown: function (e) {
|
||
if (e.keyCode === Key.ESC || e.keyCode === Key.ENTER) {
|
||
this.blur();
|
||
// If closed using ESC/ENTER, hide the tooltip.
|
||
this.setState({mousefocus: false});
|
||
}
|
||
},
|
||
blur: function () {
|
||
this.refs.input.getDOMNode().blur();
|
||
},
|
||
focus: function () {
|
||
this.refs.input.getDOMNode().select();
|
||
},
|
||
render: function () {
|
||
var isValid = this.isValid();
|
||
var icon = "fa fa-fw fa-" + this.props.type;
|
||
var groupClassName = "filter-input input-group" + (isValid ? "" : " has-error");
|
||
|
||
var popover;
|
||
if (this.state.focus || this.state.mousefocus) {
|
||
popover = (
|
||
React.createElement("div", {className: "popover bottom", onMouseEnter: this.onMouseEnter, onMouseLeave: this.onMouseLeave},
|
||
React.createElement("div", {className: "arrow"}),
|
||
React.createElement("div", {className: "popover-content"},
|
||
this.getDesc()
|
||
)
|
||
)
|
||
);
|
||
}
|
||
|
||
return (
|
||
React.createElement("div", {className: groupClassName},
|
||
React.createElement("span", {className: "input-group-addon"},
|
||
React.createElement("i", {className: icon, style: {color: this.props.color}})
|
||
),
|
||
React.createElement("input", {type: "text", placeholder: this.props.placeholder, className: "form-control",
|
||
ref: "input",
|
||
onChange: this.onChange,
|
||
onFocus: this.onFocus,
|
||
onBlur: this.onBlur,
|
||
onKeyDown: this.onKeyDown,
|
||
value: this.state.value}),
|
||
popover
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
var MainMenu = React.createClass({displayName: "MainMenu",
|
||
mixins: [utils.Navigation, utils.State],
|
||
statics: {
|
||
title: "Start",
|
||
route: "flows"
|
||
},
|
||
onFilterChange: function (val) {
|
||
var d = {};
|
||
d[Query.FILTER] = val;
|
||
this.setQuery(d);
|
||
},
|
||
onHighlightChange: function (val) {
|
||
var d = {};
|
||
d[Query.HIGHLIGHT] = val;
|
||
this.setQuery(d);
|
||
},
|
||
onInterceptChange: function (val) {
|
||
SettingsActions.update({intercept: val});
|
||
},
|
||
render: function () {
|
||
var filter = this.getQuery()[Query.FILTER] || "";
|
||
var highlight = this.getQuery()[Query.HIGHLIGHT] || "";
|
||
var intercept = this.props.settings.intercept || "";
|
||
|
||
return (
|
||
React.createElement("div", null,
|
||
React.createElement("div", {className: "menu-row"},
|
||
React.createElement(FilterInput, {
|
||
placeholder: "Filter",
|
||
type: "filter",
|
||
color: "black",
|
||
value: filter,
|
||
onChange: this.onFilterChange}),
|
||
React.createElement(FilterInput, {
|
||
placeholder: "Highlight",
|
||
type: "tag",
|
||
color: "hsl(48, 100%, 50%)",
|
||
value: highlight,
|
||
onChange: this.onHighlightChange}),
|
||
React.createElement(FilterInput, {
|
||
placeholder: "Intercept",
|
||
type: "pause",
|
||
color: "hsl(208, 56%, 53%)",
|
||
value: intercept,
|
||
onChange: this.onInterceptChange})
|
||
),
|
||
React.createElement("div", {className: "clearfix"})
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
|
||
var ViewMenu = React.createClass({displayName: "ViewMenu",
|
||
statics: {
|
||
title: "View",
|
||
route: "flows"
|
||
},
|
||
mixins: [utils.Navigation, utils.State],
|
||
toggleEventLog: function () {
|
||
var d = {};
|
||
|
||
if (this.getQuery()[Query.SHOW_EVENTLOG]) {
|
||
d[Query.SHOW_EVENTLOG] = undefined;
|
||
} else {
|
||
d[Query.SHOW_EVENTLOG] = "t"; // any non-false value will do it, keep it short
|
||
}
|
||
|
||
this.setQuery(d);
|
||
},
|
||
render: function () {
|
||
var showEventLog = this.getQuery()[Query.SHOW_EVENTLOG];
|
||
return (
|
||
React.createElement("div", null,
|
||
React.createElement("button", {
|
||
className: "btn " + (showEventLog ? "btn-primary" : "btn-default"),
|
||
onClick: this.toggleEventLog},
|
||
React.createElement("i", {className: "fa fa-database"}),
|
||
" Show Eventlog"
|
||
),
|
||
React.createElement("span", null, " ")
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
|
||
var ReportsMenu = React.createClass({displayName: "ReportsMenu",
|
||
statics: {
|
||
title: "Visualization",
|
||
route: "reports"
|
||
},
|
||
render: function () {
|
||
return React.createElement("div", null, "Reports Menu");
|
||
}
|
||
});
|
||
|
||
var FileMenu = React.createClass({displayName: "FileMenu",
|
||
getInitialState: function () {
|
||
return {
|
||
showFileMenu: false
|
||
};
|
||
},
|
||
handleFileClick: function (e) {
|
||
e.preventDefault();
|
||
if (!this.state.showFileMenu) {
|
||
var close = function () {
|
||
this.setState({showFileMenu: false});
|
||
document.removeEventListener("click", close);
|
||
}.bind(this);
|
||
document.addEventListener("click", close);
|
||
|
||
this.setState({
|
||
showFileMenu: true
|
||
});
|
||
}
|
||
},
|
||
handleNewClick: function (e) {
|
||
e.preventDefault();
|
||
if (confirm("Delete all flows?")) {
|
||
FlowActions.clear();
|
||
}
|
||
},
|
||
handleOpenClick: function (e) {
|
||
e.preventDefault();
|
||
console.error("unimplemented: handleOpenClick");
|
||
},
|
||
handleSaveClick: function (e) {
|
||
e.preventDefault();
|
||
console.error("unimplemented: handleSaveClick");
|
||
},
|
||
handleShutdownClick: function (e) {
|
||
e.preventDefault();
|
||
console.error("unimplemented: handleShutdownClick");
|
||
},
|
||
render: function () {
|
||
var fileMenuClass = "dropdown pull-left" + (this.state.showFileMenu ? " open" : "");
|
||
|
||
return (
|
||
React.createElement("div", {className: fileMenuClass},
|
||
React.createElement("a", {href: "#", className: "special", onClick: this.handleFileClick}, " File "),
|
||
React.createElement("ul", {className: "dropdown-menu", role: "menu"},
|
||
React.createElement("li", null,
|
||
React.createElement("a", {href: "#", onClick: this.handleNewClick},
|
||
React.createElement("i", {className: "fa fa-fw fa-file"}),
|
||
"New"
|
||
)
|
||
),
|
||
React.createElement("li", {role: "presentation", className: "divider"}),
|
||
React.createElement("li", null,
|
||
React.createElement("a", {href: "http://mitm.it/", target: "_blank"},
|
||
React.createElement("i", {className: "fa fa-fw fa-external-link"}),
|
||
"Install Certificates..."
|
||
)
|
||
)
|
||
/*
|
||
<li>
|
||
<a href="#" onClick={this.handleOpenClick}>
|
||
<i className="fa fa-fw fa-folder-open"></i>
|
||
Open
|
||
</a>
|
||
</li>
|
||
<li>
|
||
<a href="#" onClick={this.handleSaveClick}>
|
||
<i className="fa fa-fw fa-save"></i>
|
||
Save
|
||
</a>
|
||
</li>
|
||
<li role="presentation" className="divider"></li>
|
||
<li>
|
||
<a href="#" onClick={this.handleShutdownClick}>
|
||
<i className="fa fa-fw fa-plug"></i>
|
||
Shutdown
|
||
</a>
|
||
</li>
|
||
*/
|
||
)
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
|
||
var header_entries = [MainMenu, ViewMenu /*, ReportsMenu */];
|
||
|
||
|
||
var Header = React.createClass({displayName: "Header",
|
||
mixins: [utils.Navigation],
|
||
getInitialState: function () {
|
||
return {
|
||
active: header_entries[0]
|
||
};
|
||
},
|
||
handleClick: function (active, e) {
|
||
e.preventDefault();
|
||
this.replaceWith(active.route);
|
||
this.setState({active: active});
|
||
},
|
||
render: function () {
|
||
var header = header_entries.map(function (entry, i) {
|
||
var classes = React.addons.classSet({
|
||
active: entry == this.state.active
|
||
});
|
||
return (
|
||
React.createElement("a", {key: i,
|
||
href: "#",
|
||
className: classes,
|
||
onClick: this.handleClick.bind(this, entry)
|
||
},
|
||
entry.title
|
||
)
|
||
);
|
||
}.bind(this));
|
||
|
||
return (
|
||
React.createElement("header", null,
|
||
React.createElement("div", {className: "title-bar"},
|
||
"mitmproxy ", this.props.settings.version
|
||
),
|
||
React.createElement("nav", {className: "nav-tabs nav-tabs-lg"},
|
||
React.createElement(FileMenu, null),
|
||
header
|
||
),
|
||
React.createElement("div", {className: "menu"},
|
||
React.createElement(this.state.active, {settings: this.props.settings})
|
||
)
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
|
||
module.exports = {
|
||
Header: Header
|
||
}
|
||
},{"./utils.js":11,"jquery":"jquery","react":"react"}],9:[function(require,module,exports){
|
||
var React = require("react");
|
||
|
||
var utils = require("./utils.js");
|
||
var toputils = require("../utils.js");
|
||
var views = require("../store/view.js");
|
||
var Filt = require("../filt/filt.js");
|
||
FlowTable = require("./flowtable.js");
|
||
var flowdetail = require("./flowdetail.js");
|
||
|
||
|
||
var MainView = React.createClass({displayName: "MainView",
|
||
mixins: [utils.Navigation, utils.State],
|
||
getInitialState: function () {
|
||
this.onQueryChange(Query.FILTER, function () {
|
||
this.state.view.recalculate(this.getViewFilt(), this.getViewSort());
|
||
}.bind(this));
|
||
this.onQueryChange(Query.HIGHLIGHT, function () {
|
||
this.state.view.recalculate(this.getViewFilt(), this.getViewSort());
|
||
}.bind(this));
|
||
return {
|
||
flows: []
|
||
};
|
||
},
|
||
getViewFilt: function () {
|
||
try {
|
||
var filt = Filt.parse(this.getQuery()[Query.FILTER] || "");
|
||
var highlightStr = this.getQuery()[Query.HIGHLIGHT];
|
||
var highlight = highlightStr ? Filt.parse(highlightStr) : false;
|
||
} catch (e) {
|
||
console.error("Error when processing filter: " + e);
|
||
}
|
||
|
||
return function filter_and_highlight(flow) {
|
||
if (!this._highlight) {
|
||
this._highlight = {};
|
||
}
|
||
this._highlight[flow.id] = highlight && highlight(flow);
|
||
return filt(flow);
|
||
};
|
||
},
|
||
getViewSort: function () {
|
||
},
|
||
componentWillReceiveProps: function (nextProps) {
|
||
if (nextProps.flowStore !== this.props.flowStore) {
|
||
this.closeView();
|
||
this.openView(nextProps.flowStore);
|
||
}
|
||
},
|
||
openView: function (store) {
|
||
var view = new views.StoreView(store, this.getViewFilt(), this.getViewSort());
|
||
this.setState({
|
||
view: view
|
||
});
|
||
|
||
view.addListener("recalculate", this.onRecalculate);
|
||
view.addListener("add update remove", this.onUpdate);
|
||
view.addListener("remove", this.onRemove);
|
||
},
|
||
onRecalculate: function () {
|
||
this.forceUpdate();
|
||
var selected = this.getSelected();
|
||
if (selected) {
|
||
this.refs.flowTable.scrollIntoView(selected);
|
||
}
|
||
},
|
||
onUpdate: function (flow) {
|
||
if (flow.id === this.getParams().flowId) {
|
||
this.forceUpdate();
|
||
}
|
||
},
|
||
onRemove: function (flow_id, index) {
|
||
if (flow_id === this.getParams().flowId) {
|
||
var flow_to_select = this.state.view.list[Math.min(index, this.state.view.list.length -1)];
|
||
this.selectFlow(flow_to_select);
|
||
}
|
||
},
|
||
closeView: function () {
|
||
this.state.view.close();
|
||
},
|
||
componentWillMount: function () {
|
||
this.openView(this.props.flowStore);
|
||
},
|
||
componentWillUnmount: function () {
|
||
this.closeView();
|
||
},
|
||
selectFlow: function (flow) {
|
||
if (flow) {
|
||
this.replaceWith(
|
||
"flow",
|
||
{
|
||
flowId: flow.id,
|
||
detailTab: this.getParams().detailTab || "request"
|
||
}
|
||
);
|
||
this.refs.flowTable.scrollIntoView(flow);
|
||
} else {
|
||
this.replaceWith("flows", {});
|
||
}
|
||
},
|
||
selectFlowRelative: function (shift) {
|
||
var flows = this.state.view.list;
|
||
var index;
|
||
if (!this.getParams().flowId) {
|
||
if (shift > 0) {
|
||
index = flows.length - 1;
|
||
} else {
|
||
index = 0;
|
||
}
|
||
} else {
|
||
var currFlowId = this.getParams().flowId;
|
||
var i = flows.length;
|
||
while (i--) {
|
||
if (flows[i].id === currFlowId) {
|
||
index = i;
|
||
break;
|
||
}
|
||
}
|
||
index = Math.min(
|
||
Math.max(0, index + shift),
|
||
flows.length - 1);
|
||
}
|
||
this.selectFlow(flows[index]);
|
||
},
|
||
onKeyDown: function (e) {
|
||
var flow = this.getSelected();
|
||
if (e.ctrlKey) {
|
||
return;
|
||
}
|
||
switch (e.keyCode) {
|
||
case toputils.Key.K:
|
||
case toputils.Key.UP:
|
||
this.selectFlowRelative(-1);
|
||
break;
|
||
case toputils.Key.J:
|
||
case toputils.Key.DOWN:
|
||
this.selectFlowRelative(+1);
|
||
break;
|
||
case toputils.Key.SPACE:
|
||
case toputils.Key.PAGE_DOWN:
|
||
this.selectFlowRelative(+10);
|
||
break;
|
||
case toputils.Key.PAGE_UP:
|
||
this.selectFlowRelative(-10);
|
||
break;
|
||
case toputils.Key.END:
|
||
this.selectFlowRelative(+1e10);
|
||
break;
|
||
case toputils.Key.HOME:
|
||
this.selectFlowRelative(-1e10);
|
||
break;
|
||
case toputils.Key.ESC:
|
||
this.selectFlow(null);
|
||
break;
|
||
case toputils.Key.H:
|
||
case toputils.Key.LEFT:
|
||
if (this.refs.flowDetails) {
|
||
this.refs.flowDetails.nextTab(-1);
|
||
}
|
||
break;
|
||
case toputils.Key.L:
|
||
case toputils.Key.TAB:
|
||
case toputils.Key.RIGHT:
|
||
if (this.refs.flowDetails) {
|
||
this.refs.flowDetails.nextTab(+1);
|
||
}
|
||
break;
|
||
case toputils.Key.C:
|
||
if (e.shiftKey) {
|
||
FlowActions.clear();
|
||
}
|
||
break;
|
||
case toputils.Key.D:
|
||
if (flow) {
|
||
if (e.shiftKey) {
|
||
FlowActions.duplicate(flow);
|
||
} else {
|
||
FlowActions.delete(flow);
|
||
}
|
||
}
|
||
break;
|
||
case toputils.Key.A:
|
||
if (e.shiftKey) {
|
||
FlowActions.accept_all();
|
||
} else if (flow && flow.intercepted) {
|
||
FlowActions.accept(flow);
|
||
}
|
||
break;
|
||
case toputils.Key.R:
|
||
if (!e.shiftKey && flow) {
|
||
FlowActions.replay(flow);
|
||
}
|
||
break;
|
||
case toputils.Key.V:
|
||
if(e.shiftKey && flow && flow.modified) {
|
||
FlowActions.revert(flow);
|
||
}
|
||
break;
|
||
default:
|
||
console.debug("keydown", e.keyCode);
|
||
return;
|
||
}
|
||
e.preventDefault();
|
||
},
|
||
getSelected: function () {
|
||
return this.props.flowStore.get(this.getParams().flowId);
|
||
},
|
||
render: function () {
|
||
var selected = this.getSelected();
|
||
|
||
var details;
|
||
if (selected) {
|
||
details = [
|
||
React.createElement(utils.Splitter, {key: "splitter"}),
|
||
React.createElement(flowdetail.FlowDetail, {key: "flowDetails", ref: "flowDetails", flow: selected})
|
||
];
|
||
} else {
|
||
details = null;
|
||
}
|
||
|
||
return (
|
||
React.createElement("div", {className: "main-view", onKeyDown: this.onKeyDown, tabIndex: "0"},
|
||
React.createElement(FlowTable, {ref: "flowTable",
|
||
view: this.state.view,
|
||
selectFlow: this.selectFlow,
|
||
selected: selected}),
|
||
details
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
module.exports = MainView;
|
||
|
||
},{"../filt/filt.js":15,"../store/view.js":18,"../utils.js":19,"./flowdetail.js":4,"./flowtable.js":6,"./utils.js":11,"react":"react"}],10:[function(require,module,exports){
|
||
var React = require("react");
|
||
var ReactRouter = require("react-router");
|
||
var _ = require("lodash");
|
||
|
||
var utils = require("./utils.js");
|
||
var MainView = require("./mainview.js");
|
||
var Footer = require("./footer.js");
|
||
var header = require("./header.js");
|
||
var EventLog = require("./eventlog.js");
|
||
var store = require("../store/store.js");
|
||
|
||
|
||
//TODO: Move out of here, just a stub.
|
||
var Reports = React.createClass({displayName: "Reports",
|
||
render: function () {
|
||
return React.createElement("div", null, "ReportEditor");
|
||
}
|
||
});
|
||
|
||
|
||
var ProxyAppMain = React.createClass({displayName: "ProxyAppMain",
|
||
mixins: [utils.State],
|
||
getInitialState: function () {
|
||
var eventStore = new store.EventLogStore();
|
||
var flowStore = new store.FlowStore();
|
||
var settings = new store.SettingsStore();
|
||
|
||
// Default Settings before fetch
|
||
_.extend(settings.dict,{
|
||
});
|
||
return {
|
||
settings: settings,
|
||
flowStore: flowStore,
|
||
eventStore: eventStore
|
||
};
|
||
},
|
||
componentDidMount: function () {
|
||
this.state.settings.addListener("recalculate", this.onSettingsChange);
|
||
window.app = this;
|
||
},
|
||
componentWillUnmount: function () {
|
||
this.state.settings.removeListener("recalculate", this.onSettingsChange);
|
||
},
|
||
onSettingsChange: function(){
|
||
this.setState({
|
||
settings: this.state.settings
|
||
});
|
||
},
|
||
render: function () {
|
||
|
||
var eventlog;
|
||
if (this.getQuery()[Query.SHOW_EVENTLOG]) {
|
||
eventlog = [
|
||
React.createElement(utils.Splitter, {key: "splitter", axis: "y"}),
|
||
React.createElement(EventLog, {key: "eventlog", eventStore: this.state.eventStore})
|
||
];
|
||
} else {
|
||
eventlog = null;
|
||
}
|
||
|
||
return (
|
||
React.createElement("div", {id: "container"},
|
||
React.createElement(header.Header, {settings: this.state.settings.dict}),
|
||
React.createElement(RouteHandler, {settings: this.state.settings.dict, flowStore: this.state.flowStore}),
|
||
eventlog,
|
||
React.createElement(Footer, {settings: this.state.settings.dict})
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
|
||
var Route = ReactRouter.Route;
|
||
var RouteHandler = ReactRouter.RouteHandler;
|
||
var Redirect = ReactRouter.Redirect;
|
||
var DefaultRoute = ReactRouter.DefaultRoute;
|
||
var NotFoundRoute = ReactRouter.NotFoundRoute;
|
||
|
||
|
||
var routes = (
|
||
React.createElement(Route, {path: "/", handler: ProxyAppMain},
|
||
React.createElement(Route, {name: "flows", path: "flows", handler: MainView}),
|
||
React.createElement(Route, {name: "flow", path: "flows/:flowId/:detailTab", handler: MainView}),
|
||
React.createElement(Route, {name: "reports", handler: Reports}),
|
||
React.createElement(Redirect, {path: "/", to: "flows"})
|
||
)
|
||
);
|
||
|
||
module.exports = {
|
||
routes: routes
|
||
};
|
||
|
||
|
||
},{"../store/store.js":17,"./eventlog.js":3,"./footer.js":7,"./header.js":8,"./mainview.js":9,"./utils.js":11,"lodash":"lodash","react":"react","react-router":"react-router"}],11:[function(require,module,exports){
|
||
var React = require("react");
|
||
var ReactRouter = require("react-router");
|
||
var _ = require("lodash");
|
||
|
||
//React utils. For other utilities, see ../utils.js
|
||
|
||
// http://blog.vjeux.com/2013/javascript/scroll-position-with-react.html (also contains inverse example)
|
||
var AutoScrollMixin = {
|
||
componentWillUpdate: function () {
|
||
var node = this.getDOMNode();
|
||
this._shouldScrollBottom = (
|
||
node.scrollTop !== 0 &&
|
||
node.scrollTop + node.clientHeight === node.scrollHeight
|
||
);
|
||
},
|
||
componentDidUpdate: function () {
|
||
if (this._shouldScrollBottom) {
|
||
var node = this.getDOMNode();
|
||
node.scrollTop = node.scrollHeight;
|
||
}
|
||
},
|
||
};
|
||
|
||
|
||
var StickyHeadMixin = {
|
||
adjustHead: function () {
|
||
// Abusing CSS transforms to set the element
|
||
// referenced as head into some kind of position:sticky.
|
||
var head = this.refs.head.getDOMNode();
|
||
head.style.transform = "translate(0," + this.getDOMNode().scrollTop + "px)";
|
||
}
|
||
};
|
||
|
||
|
||
var Navigation = _.extend({}, ReactRouter.Navigation, {
|
||
setQuery: function (dict) {
|
||
var q = this.context.getCurrentQuery();
|
||
for(var i in dict){
|
||
if(dict.hasOwnProperty(i)){
|
||
q[i] = dict[i] || undefined; //falsey values shall be removed.
|
||
}
|
||
}
|
||
q._ = "_"; // workaround for https://github.com/rackt/react-router/pull/599
|
||
this.replaceWith(this.context.getCurrentPath(), this.context.getCurrentParams(), q);
|
||
},
|
||
replaceWith: function(routeNameOrPath, params, query) {
|
||
if(routeNameOrPath === undefined){
|
||
routeNameOrPath = this.context.getCurrentPath();
|
||
}
|
||
if(params === undefined){
|
||
params = this.context.getCurrentParams();
|
||
}
|
||
if(query === undefined){
|
||
query = this.context.getCurrentQuery();
|
||
}
|
||
ReactRouter.Navigation.replaceWith.call(this, routeNameOrPath, params, query);
|
||
}
|
||
});
|
||
_.extend(Navigation.contextTypes, ReactRouter.State.contextTypes);
|
||
|
||
var State = _.extend({}, ReactRouter.State, {
|
||
getInitialState: function () {
|
||
this._query = this.context.getCurrentQuery();
|
||
this._queryWatches = [];
|
||
return null;
|
||
},
|
||
onQueryChange: function (key, callback) {
|
||
this._queryWatches.push({
|
||
key: key,
|
||
callback: callback
|
||
});
|
||
},
|
||
componentWillReceiveProps: function (nextProps, nextState) {
|
||
var q = this.context.getCurrentQuery();
|
||
for (var i = 0; i < this._queryWatches.length; i++) {
|
||
var watch = this._queryWatches[i];
|
||
if (this._query[watch.key] !== q[watch.key]) {
|
||
watch.callback(this._query[watch.key], q[watch.key], watch.key);
|
||
}
|
||
}
|
||
this._query = q;
|
||
}
|
||
});
|
||
|
||
var Splitter = React.createClass({displayName: "Splitter",
|
||
getDefaultProps: function () {
|
||
return {
|
||
axis: "x"
|
||
};
|
||
},
|
||
getInitialState: function () {
|
||
return {
|
||
applied: false,
|
||
startX: false,
|
||
startY: false
|
||
};
|
||
},
|
||
onMouseDown: function (e) {
|
||
this.setState({
|
||
startX: e.pageX,
|
||
startY: e.pageY
|
||
});
|
||
window.addEventListener("mousemove", this.onMouseMove);
|
||
window.addEventListener("mouseup", this.onMouseUp);
|
||
// Occasionally, only a dragEnd event is triggered, but no mouseUp.
|
||
window.addEventListener("dragend", this.onDragEnd);
|
||
},
|
||
onDragEnd: function () {
|
||
this.getDOMNode().style.transform = "";
|
||
window.removeEventListener("dragend", this.onDragEnd);
|
||
window.removeEventListener("mouseup", this.onMouseUp);
|
||
window.removeEventListener("mousemove", this.onMouseMove);
|
||
},
|
||
onMouseUp: function (e) {
|
||
this.onDragEnd();
|
||
|
||
var node = this.getDOMNode();
|
||
var prev = node.previousElementSibling;
|
||
var next = node.nextElementSibling;
|
||
|
||
var dX = e.pageX - this.state.startX;
|
||
var dY = e.pageY - this.state.startY;
|
||
var flexBasis;
|
||
if (this.props.axis === "x") {
|
||
flexBasis = prev.offsetWidth + dX;
|
||
} else {
|
||
flexBasis = prev.offsetHeight + dY;
|
||
}
|
||
|
||
prev.style.flex = "0 0 " + Math.max(0, flexBasis) + "px";
|
||
next.style.flex = "1 1 auto";
|
||
|
||
this.setState({
|
||
applied: true
|
||
});
|
||
this.onResize();
|
||
},
|
||
onMouseMove: function (e) {
|
||
var dX = 0, dY = 0;
|
||
if (this.props.axis === "x") {
|
||
dX = e.pageX - this.state.startX;
|
||
} else {
|
||
dY = e.pageY - this.state.startY;
|
||
}
|
||
this.getDOMNode().style.transform = "translate(" + dX + "px," + dY + "px)";
|
||
},
|
||
onResize: function () {
|
||
// Trigger a global resize event. This notifies components that employ virtual scrolling
|
||
// that their viewport may have changed.
|
||
window.setTimeout(function () {
|
||
window.dispatchEvent(new CustomEvent("resize"));
|
||
}, 1);
|
||
},
|
||
reset: function (willUnmount) {
|
||
if (!this.state.applied) {
|
||
return;
|
||
}
|
||
var node = this.getDOMNode();
|
||
var prev = node.previousElementSibling;
|
||
var next = node.nextElementSibling;
|
||
|
||
prev.style.flex = "";
|
||
next.style.flex = "";
|
||
|
||
if (!willUnmount) {
|
||
this.setState({
|
||
applied: false
|
||
});
|
||
}
|
||
this.onResize();
|
||
},
|
||
componentWillUnmount: function () {
|
||
this.reset(true);
|
||
},
|
||
render: function () {
|
||
var className = "splitter";
|
||
if (this.props.axis === "x") {
|
||
className += " splitter-x";
|
||
} else {
|
||
className += " splitter-y";
|
||
}
|
||
return (
|
||
React.createElement("div", {className: className},
|
||
React.createElement("div", {onMouseDown: this.onMouseDown, draggable: "true"})
|
||
)
|
||
);
|
||
}
|
||
});
|
||
|
||
module.exports = {
|
||
State: State,
|
||
Navigation: Navigation,
|
||
StickyHeadMixin: StickyHeadMixin,
|
||
AutoScrollMixin: AutoScrollMixin,
|
||
Splitter: Splitter
|
||
}
|
||
},{"lodash":"lodash","react":"react","react-router":"react-router"}],12:[function(require,module,exports){
|
||
var React = require("react");
|
||
|
||
var VirtualScrollMixin = {
|
||
getInitialState: function () {
|
||
return {
|
||
start: 0,
|
||
stop: 0
|
||
};
|
||
},
|
||
componentWillMount: function () {
|
||
if (!this.props.rowHeight) {
|
||
console.warn("VirtualScrollMixin: No rowHeight specified", this);
|
||
}
|
||
},
|
||
getPlaceholderTop: function (total) {
|
||
var Tag = this.props.placeholderTagName || "tr";
|
||
// When a large trunk of elements is removed from the button, start may be far off the viewport.
|
||
// To make this issue less severe, limit the top placeholder to the total number of rows.
|
||
var style = {
|
||
height: Math.min(this.state.start, total) * this.props.rowHeight
|
||
};
|
||
var spacer = React.createElement(Tag, {key: "placeholder-top", style: style});
|
||
|
||
if (this.state.start % 2 === 1) {
|
||
// fix even/odd rows
|
||
return [spacer, React.createElement(Tag, {key: "placeholder-top-2"})];
|
||
} else {
|
||
return spacer;
|
||
}
|
||
},
|
||
getPlaceholderBottom: function (total) {
|
||
var Tag = this.props.placeholderTagName || "tr";
|
||
var style = {
|
||
height: Math.max(0, total - this.state.stop) * this.props.rowHeight
|
||
};
|
||
return React.createElement(Tag, {key: "placeholder-bottom", style: style});
|
||
},
|
||
componentDidMount: function () {
|
||
this.onScroll();
|
||
window.addEventListener('resize', this.onScroll);
|
||
},
|
||
componentWillUnmount: function(){
|
||
window.removeEventListener('resize', this.onScroll);
|
||
},
|
||
onScroll: function () {
|
||
var viewport = this.getDOMNode();
|
||
var top = viewport.scrollTop;
|
||
var height = viewport.offsetHeight;
|
||
var start = Math.floor(top / this.props.rowHeight);
|
||
var stop = start + Math.ceil(height / (this.props.rowHeightMin || this.props.rowHeight));
|
||
|
||
this.setState({
|
||
start: start,
|
||
stop: stop
|
||
});
|
||
},
|
||
renderRows: function (elems) {
|
||
var rows = [];
|
||
var max = Math.min(elems.length, this.state.stop);
|
||
|
||
for (var i = this.state.start; i < max; i++) {
|
||
var elem = elems[i];
|
||
rows.push(this.renderRow(elem));
|
||
}
|
||
return rows;
|
||
},
|
||
scrollRowIntoView: function (index, head_height) {
|
||
|
||
var row_top = (index * this.props.rowHeight) + head_height;
|
||
var row_bottom = row_top + this.props.rowHeight;
|
||
|
||
var viewport = this.getDOMNode();
|
||
var viewport_top = viewport.scrollTop;
|
||
var viewport_bottom = viewport_top + viewport.offsetHeight;
|
||
|
||
// Account for pinned thead
|
||
if (row_top - head_height < viewport_top) {
|
||
viewport.scrollTop = row_top - head_height;
|
||
} else if (row_bottom > viewport_bottom) {
|
||
viewport.scrollTop = row_bottom - viewport.offsetHeight;
|
||
}
|
||
},
|
||
};
|
||
|
||
module.exports = VirtualScrollMixin;
|
||
},{"react":"react"}],13:[function(require,module,exports){
|
||
|
||
var actions = require("./actions.js");
|
||
|
||
function Connection(url) {
|
||
if (url[0] === "/") {
|
||
url = location.origin.replace("http", "ws") + url;
|
||
}
|
||
|
||
var ws = new WebSocket(url);
|
||
ws.onopen = function () {
|
||
actions.ConnectionActions.open();
|
||
};
|
||
ws.onmessage = function (message) {
|
||
var m = JSON.parse(message.data);
|
||
AppDispatcher.dispatchServerAction(m);
|
||
};
|
||
ws.onerror = function () {
|
||
actions.ConnectionActions.error();
|
||
EventLogActions.add_event("WebSocket connection error.");
|
||
};
|
||
ws.onclose = function () {
|
||
actions.ConnectionActions.close();
|
||
EventLogActions.add_event("WebSocket connection closed.");
|
||
};
|
||
return ws;
|
||
}
|
||
|
||
module.exports = Connection;
|
||
},{"./actions.js":1}],14:[function(require,module,exports){
|
||
const PayloadSources = {
|
||
VIEW: "view",
|
||
SERVER: "server"
|
||
};
|
||
|
||
|
||
function Dispatcher() {
|
||
this.callbacks = [];
|
||
}
|
||
Dispatcher.prototype.register = function (callback) {
|
||
this.callbacks.push(callback);
|
||
};
|
||
Dispatcher.prototype.unregister = function (callback) {
|
||
var index = this.callbacks.indexOf(callback);
|
||
if (index >= 0) {
|
||
this.callbacks.splice(index, 1);
|
||
}
|
||
};
|
||
Dispatcher.prototype.dispatch = function (payload) {
|
||
console.debug("dispatch", payload);
|
||
for (var i = 0; i < this.callbacks.length; i++) {
|
||
this.callbacks[i](payload);
|
||
}
|
||
};
|
||
|
||
|
||
AppDispatcher = new Dispatcher();
|
||
AppDispatcher.dispatchViewAction = function (action) {
|
||
action.source = PayloadSources.VIEW;
|
||
this.dispatch(action);
|
||
};
|
||
AppDispatcher.dispatchServerAction = function (action) {
|
||
action.source = PayloadSources.SERVER;
|
||
this.dispatch(action);
|
||
};
|
||
|
||
module.exports = {
|
||
AppDispatcher: AppDispatcher
|
||
};
|
||
},{}],15:[function(require,module,exports){
|
||
/* jshint ignore:start */
|
||
Filt = (function() {
|
||
/*
|
||
* Generated by PEG.js 0.8.0.
|
||
*
|
||
* http://pegjs.majda.cz/
|
||
*/
|
||
|
||
function peg$subclass(child, parent) {
|
||
function ctor() { this.constructor = child; }
|
||
ctor.prototype = parent.prototype;
|
||
child.prototype = new ctor();
|
||
}
|
||
|
||
function SyntaxError(message, expected, found, offset, line, column) {
|
||
this.message = message;
|
||
this.expected = expected;
|
||
this.found = found;
|
||
this.offset = offset;
|
||
this.line = line;
|
||
this.column = column;
|
||
|
||
this.name = "SyntaxError";
|
||
}
|
||
|
||
peg$subclass(SyntaxError, Error);
|
||
|
||
function parse(input) {
|
||
var options = arguments.length > 1 ? arguments[1] : {},
|
||
|
||
peg$FAILED = {},
|
||
|
||
peg$startRuleFunctions = { start: peg$parsestart },
|
||
peg$startRuleFunction = peg$parsestart,
|
||
|
||
peg$c0 = { type: "other", description: "filter expression" },
|
||
peg$c1 = peg$FAILED,
|
||
peg$c2 = function(orExpr) { return orExpr; },
|
||
peg$c3 = [],
|
||
peg$c4 = function() {return trueFilter; },
|
||
peg$c5 = { type: "other", description: "whitespace" },
|
||
peg$c6 = /^[ \t\n\r]/,
|
||
peg$c7 = { type: "class", value: "[ \\t\\n\\r]", description: "[ \\t\\n\\r]" },
|
||
peg$c8 = { type: "other", description: "control character" },
|
||
peg$c9 = /^[|&!()~"]/,
|
||
peg$c10 = { type: "class", value: "[|&!()~\"]", description: "[|&!()~\"]" },
|
||
peg$c11 = { type: "other", description: "optional whitespace" },
|
||
peg$c12 = "|",
|
||
peg$c13 = { type: "literal", value: "|", description: "\"|\"" },
|
||
peg$c14 = function(first, second) { return or(first, second); },
|
||
peg$c15 = "&",
|
||
peg$c16 = { type: "literal", value: "&", description: "\"&\"" },
|
||
peg$c17 = function(first, second) { return and(first, second); },
|
||
peg$c18 = "!",
|
||
peg$c19 = { type: "literal", value: "!", description: "\"!\"" },
|
||
peg$c20 = function(expr) { return not(expr); },
|
||
peg$c21 = "(",
|
||
peg$c22 = { type: "literal", value: "(", description: "\"(\"" },
|
||
peg$c23 = ")",
|
||
peg$c24 = { type: "literal", value: ")", description: "\")\"" },
|
||
peg$c25 = function(expr) { return binding(expr); },
|
||
peg$c26 = "~a",
|
||
peg$c27 = { type: "literal", value: "~a", description: "\"~a\"" },
|
||
peg$c28 = function() { return assetFilter; },
|
||
peg$c29 = "~e",
|
||
peg$c30 = { type: "literal", value: "~e", description: "\"~e\"" },
|
||
peg$c31 = function() { return errorFilter; },
|
||
peg$c32 = "~q",
|
||
peg$c33 = { type: "literal", value: "~q", description: "\"~q\"" },
|
||
peg$c34 = function() { return noResponseFilter; },
|
||
peg$c35 = "~s",
|
||
peg$c36 = { type: "literal", value: "~s", description: "\"~s\"" },
|
||
peg$c37 = function() { return responseFilter; },
|
||
peg$c38 = "true",
|
||
peg$c39 = { type: "literal", value: "true", description: "\"true\"" },
|
||
peg$c40 = function() { return trueFilter; },
|
||
peg$c41 = "false",
|
||
peg$c42 = { type: "literal", value: "false", description: "\"false\"" },
|
||
peg$c43 = function() { return falseFilter; },
|
||
peg$c44 = "~c",
|
||
peg$c45 = { type: "literal", value: "~c", description: "\"~c\"" },
|
||
peg$c46 = function(s) { return responseCode(s); },
|
||
peg$c47 = "~d",
|
||
peg$c48 = { type: "literal", value: "~d", description: "\"~d\"" },
|
||
peg$c49 = function(s) { return domain(s); },
|
||
peg$c50 = "~h",
|
||
peg$c51 = { type: "literal", value: "~h", description: "\"~h\"" },
|
||
peg$c52 = function(s) { return header(s); },
|
||
peg$c53 = "~hq",
|
||
peg$c54 = { type: "literal", value: "~hq", description: "\"~hq\"" },
|
||
peg$c55 = function(s) { return requestHeader(s); },
|
||
peg$c56 = "~hs",
|
||
peg$c57 = { type: "literal", value: "~hs", description: "\"~hs\"" },
|
||
peg$c58 = function(s) { return responseHeader(s); },
|
||
peg$c59 = "~m",
|
||
peg$c60 = { type: "literal", value: "~m", description: "\"~m\"" },
|
||
peg$c61 = function(s) { return method(s); },
|
||
peg$c62 = "~t",
|
||
peg$c63 = { type: "literal", value: "~t", description: "\"~t\"" },
|
||
peg$c64 = function(s) { return contentType(s); },
|
||
peg$c65 = "~tq",
|
||
peg$c66 = { type: "literal", value: "~tq", description: "\"~tq\"" },
|
||
peg$c67 = function(s) { return requestContentType(s); },
|
||
peg$c68 = "~ts",
|
||
peg$c69 = { type: "literal", value: "~ts", description: "\"~ts\"" },
|
||
peg$c70 = function(s) { return responseContentType(s); },
|
||
peg$c71 = "~u",
|
||
peg$c72 = { type: "literal", value: "~u", description: "\"~u\"" },
|
||
peg$c73 = function(s) { return url(s); },
|
||
peg$c74 = { type: "other", description: "integer" },
|
||
peg$c75 = null,
|
||
peg$c76 = /^['"]/,
|
||
peg$c77 = { type: "class", value: "['\"]", description: "['\"]" },
|
||
peg$c78 = /^[0-9]/,
|
||
peg$c79 = { type: "class", value: "[0-9]", description: "[0-9]" },
|
||
peg$c80 = function(digits) { return parseInt(digits.join(""), 10); },
|
||
peg$c81 = { type: "other", description: "string" },
|
||
peg$c82 = "\"",
|
||
peg$c83 = { type: "literal", value: "\"", description: "\"\\\"\"" },
|
||
peg$c84 = function(chars) { return chars.join(""); },
|
||
peg$c85 = "'",
|
||
peg$c86 = { type: "literal", value: "'", description: "\"'\"" },
|
||
peg$c87 = void 0,
|
||
peg$c88 = /^["\\]/,
|
||
peg$c89 = { type: "class", value: "[\"\\\\]", description: "[\"\\\\]" },
|
||
peg$c90 = { type: "any", description: "any character" },
|
||
peg$c91 = function(char) { return char; },
|
||
peg$c92 = "\\",
|
||
peg$c93 = { type: "literal", value: "\\", description: "\"\\\\\"" },
|
||
peg$c94 = /^['\\]/,
|
||
peg$c95 = { type: "class", value: "['\\\\]", description: "['\\\\]" },
|
||
peg$c96 = /^['"\\]/,
|
||
peg$c97 = { type: "class", value: "['\"\\\\]", description: "['\"\\\\]" },
|
||
peg$c98 = "n",
|
||
peg$c99 = { type: "literal", value: "n", description: "\"n\"" },
|
||
peg$c100 = function() { return "\n"; },
|
||
peg$c101 = "r",
|
||
peg$c102 = { type: "literal", value: "r", description: "\"r\"" },
|
||
peg$c103 = function() { return "\r"; },
|
||
peg$c104 = "t",
|
||
peg$c105 = { type: "literal", value: "t", description: "\"t\"" },
|
||
peg$c106 = function() { return "\t"; },
|
||
|
||
peg$currPos = 0,
|
||
peg$reportedPos = 0,
|
||
peg$cachedPos = 0,
|
||
peg$cachedPosDetails = { line: 1, column: 1, seenCR: false },
|
||
peg$maxFailPos = 0,
|
||
peg$maxFailExpected = [],
|
||
peg$silentFails = 0,
|
||
|
||
peg$result;
|
||
|
||
if ("startRule" in options) {
|
||
if (!(options.startRule in peg$startRuleFunctions)) {
|
||
throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
|
||
}
|
||
|
||
peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
|
||
}
|
||
|
||
function text() {
|
||
return input.substring(peg$reportedPos, peg$currPos);
|
||
}
|
||
|
||
function offset() {
|
||
return peg$reportedPos;
|
||
}
|
||
|
||
function line() {
|
||
return peg$computePosDetails(peg$reportedPos).line;
|
||
}
|
||
|
||
function column() {
|
||
return peg$computePosDetails(peg$reportedPos).column;
|
||
}
|
||
|
||
function expected(description) {
|
||
throw peg$buildException(
|
||
null,
|
||
[{ type: "other", description: description }],
|
||
peg$reportedPos
|
||
);
|
||
}
|
||
|
||
function error(message) {
|
||
throw peg$buildException(message, null, peg$reportedPos);
|
||
}
|
||
|
||
function peg$computePosDetails(pos) {
|
||
function advance(details, startPos, endPos) {
|
||
var p, ch;
|
||
|
||
for (p = startPos; p < endPos; p++) {
|
||
ch = input.charAt(p);
|
||
if (ch === "\n") {
|
||
if (!details.seenCR) { details.line++; }
|
||
details.column = 1;
|
||
details.seenCR = false;
|
||
} else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
|
||
details.line++;
|
||
details.column = 1;
|
||
details.seenCR = true;
|
||
} else {
|
||
details.column++;
|
||
details.seenCR = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (peg$cachedPos !== pos) {
|
||
if (peg$cachedPos > pos) {
|
||
peg$cachedPos = 0;
|
||
peg$cachedPosDetails = { line: 1, column: 1, seenCR: false };
|
||
}
|
||
advance(peg$cachedPosDetails, peg$cachedPos, pos);
|
||
peg$cachedPos = pos;
|
||
}
|
||
|
||
return peg$cachedPosDetails;
|
||
}
|
||
|
||
function peg$fail(expected) {
|
||
if (peg$currPos < peg$maxFailPos) { return; }
|
||
|
||
if (peg$currPos > peg$maxFailPos) {
|
||
peg$maxFailPos = peg$currPos;
|
||
peg$maxFailExpected = [];
|
||
}
|
||
|
||
peg$maxFailExpected.push(expected);
|
||
}
|
||
|
||
function peg$buildException(message, expected, pos) {
|
||
function cleanupExpected(expected) {
|
||
var i = 1;
|
||
|
||
expected.sort(function(a, b) {
|
||
if (a.description < b.description) {
|
||
return -1;
|
||
} else if (a.description > b.description) {
|
||
return 1;
|
||
} else {
|
||
return 0;
|
||
}
|
||
});
|
||
|
||
while (i < expected.length) {
|
||
if (expected[i - 1] === expected[i]) {
|
||
expected.splice(i, 1);
|
||
} else {
|
||
i++;
|
||
}
|
||
}
|
||
}
|
||
|
||
function buildMessage(expected, found) {
|
||
function stringEscape(s) {
|
||
function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
|
||
|
||
return s
|
||
.replace(/\\/g, '\\\\')
|
||
.replace(/"/g, '\\"')
|
||
.replace(/\x08/g, '\\b')
|
||
.replace(/\t/g, '\\t')
|
||
.replace(/\n/g, '\\n')
|
||
.replace(/\f/g, '\\f')
|
||
.replace(/\r/g, '\\r')
|
||
.replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
|
||
.replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); })
|
||
.replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); })
|
||
.replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
|
||
}
|
||
|
||
var expectedDescs = new Array(expected.length),
|
||
expectedDesc, foundDesc, i;
|
||
|
||
for (i = 0; i < expected.length; i++) {
|
||
expectedDescs[i] = expected[i].description;
|
||
}
|
||
|
||
expectedDesc = expected.length > 1
|
||
? expectedDescs.slice(0, -1).join(", ")
|
||
+ " or "
|
||
+ expectedDescs[expected.length - 1]
|
||
: expectedDescs[0];
|
||
|
||
foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input";
|
||
|
||
return "Expected " + expectedDesc + " but " + foundDesc + " found.";
|
||
}
|
||
|
||
var posDetails = peg$computePosDetails(pos),
|
||
found = pos < input.length ? input.charAt(pos) : null;
|
||
|
||
if (expected !== null) {
|
||
cleanupExpected(expected);
|
||
}
|
||
|
||
return new SyntaxError(
|
||
message !== null ? message : buildMessage(expected, found),
|
||
expected,
|
||
found,
|
||
pos,
|
||
posDetails.line,
|
||
posDetails.column
|
||
);
|
||
}
|
||
|
||
function peg$parsestart() {
|
||
var s0, s1, s2, s3;
|
||
|
||
peg$silentFails++;
|
||
s0 = peg$currPos;
|
||
s1 = peg$parse__();
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = peg$parseOrExpr();
|
||
if (s2 !== peg$FAILED) {
|
||
s3 = peg$parse__();
|
||
if (s3 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c2(s2);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
s1 = [];
|
||
if (s1 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c4();
|
||
}
|
||
s0 = s1;
|
||
}
|
||
peg$silentFails--;
|
||
if (s0 === peg$FAILED) {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c0); }
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
function peg$parsews() {
|
||
var s0, s1;
|
||
|
||
peg$silentFails++;
|
||
if (peg$c6.test(input.charAt(peg$currPos))) {
|
||
s0 = input.charAt(peg$currPos);
|
||
peg$currPos++;
|
||
} else {
|
||
s0 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c7); }
|
||
}
|
||
peg$silentFails--;
|
||
if (s0 === peg$FAILED) {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c5); }
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
function peg$parsecc() {
|
||
var s0, s1;
|
||
|
||
peg$silentFails++;
|
||
if (peg$c9.test(input.charAt(peg$currPos))) {
|
||
s0 = input.charAt(peg$currPos);
|
||
peg$currPos++;
|
||
} else {
|
||
s0 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c10); }
|
||
}
|
||
peg$silentFails--;
|
||
if (s0 === peg$FAILED) {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c8); }
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
function peg$parse__() {
|
||
var s0, s1;
|
||
|
||
peg$silentFails++;
|
||
s0 = [];
|
||
s1 = peg$parsews();
|
||
while (s1 !== peg$FAILED) {
|
||
s0.push(s1);
|
||
s1 = peg$parsews();
|
||
}
|
||
peg$silentFails--;
|
||
if (s0 === peg$FAILED) {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c11); }
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
function peg$parseOrExpr() {
|
||
var s0, s1, s2, s3, s4, s5;
|
||
|
||
s0 = peg$currPos;
|
||
s1 = peg$parseAndExpr();
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = peg$parse__();
|
||
if (s2 !== peg$FAILED) {
|
||
if (input.charCodeAt(peg$currPos) === 124) {
|
||
s3 = peg$c12;
|
||
peg$currPos++;
|
||
} else {
|
||
s3 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c13); }
|
||
}
|
||
if (s3 !== peg$FAILED) {
|
||
s4 = peg$parse__();
|
||
if (s4 !== peg$FAILED) {
|
||
s5 = peg$parseOrExpr();
|
||
if (s5 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c14(s1, s5);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$parseAndExpr();
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
function peg$parseAndExpr() {
|
||
var s0, s1, s2, s3, s4, s5;
|
||
|
||
s0 = peg$currPos;
|
||
s1 = peg$parseNotExpr();
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = peg$parse__();
|
||
if (s2 !== peg$FAILED) {
|
||
if (input.charCodeAt(peg$currPos) === 38) {
|
||
s3 = peg$c15;
|
||
peg$currPos++;
|
||
} else {
|
||
s3 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c16); }
|
||
}
|
||
if (s3 !== peg$FAILED) {
|
||
s4 = peg$parse__();
|
||
if (s4 !== peg$FAILED) {
|
||
s5 = peg$parseAndExpr();
|
||
if (s5 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c17(s1, s5);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
s1 = peg$parseNotExpr();
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = [];
|
||
s3 = peg$parsews();
|
||
if (s3 !== peg$FAILED) {
|
||
while (s3 !== peg$FAILED) {
|
||
s2.push(s3);
|
||
s3 = peg$parsews();
|
||
}
|
||
} else {
|
||
s2 = peg$c1;
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
s3 = peg$parseAndExpr();
|
||
if (s3 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c17(s1, s3);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$parseNotExpr();
|
||
}
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
function peg$parseNotExpr() {
|
||
var s0, s1, s2, s3;
|
||
|
||
s0 = peg$currPos;
|
||
if (input.charCodeAt(peg$currPos) === 33) {
|
||
s1 = peg$c18;
|
||
peg$currPos++;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c19); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = peg$parse__();
|
||
if (s2 !== peg$FAILED) {
|
||
s3 = peg$parseNotExpr();
|
||
if (s3 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c20(s3);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$parseBindingExpr();
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
function peg$parseBindingExpr() {
|
||
var s0, s1, s2, s3, s4, s5;
|
||
|
||
s0 = peg$currPos;
|
||
if (input.charCodeAt(peg$currPos) === 40) {
|
||
s1 = peg$c21;
|
||
peg$currPos++;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c22); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = peg$parse__();
|
||
if (s2 !== peg$FAILED) {
|
||
s3 = peg$parseOrExpr();
|
||
if (s3 !== peg$FAILED) {
|
||
s4 = peg$parse__();
|
||
if (s4 !== peg$FAILED) {
|
||
if (input.charCodeAt(peg$currPos) === 41) {
|
||
s5 = peg$c23;
|
||
peg$currPos++;
|
||
} else {
|
||
s5 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c24); }
|
||
}
|
||
if (s5 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c25(s3);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$parseExpr();
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
function peg$parseExpr() {
|
||
var s0;
|
||
|
||
s0 = peg$parseNullaryExpr();
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$parseUnaryExpr();
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
function peg$parseNullaryExpr() {
|
||
var s0, s1;
|
||
|
||
s0 = peg$parseBooleanLiteral();
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.substr(peg$currPos, 2) === peg$c26) {
|
||
s1 = peg$c26;
|
||
peg$currPos += 2;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c27); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c28();
|
||
}
|
||
s0 = s1;
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.substr(peg$currPos, 2) === peg$c29) {
|
||
s1 = peg$c29;
|
||
peg$currPos += 2;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c30); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c31();
|
||
}
|
||
s0 = s1;
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.substr(peg$currPos, 2) === peg$c32) {
|
||
s1 = peg$c32;
|
||
peg$currPos += 2;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c33); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c34();
|
||
}
|
||
s0 = s1;
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.substr(peg$currPos, 2) === peg$c35) {
|
||
s1 = peg$c35;
|
||
peg$currPos += 2;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c36); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c37();
|
||
}
|
||
s0 = s1;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
function peg$parseBooleanLiteral() {
|
||
var s0, s1;
|
||
|
||
s0 = peg$currPos;
|
||
if (input.substr(peg$currPos, 4) === peg$c38) {
|
||
s1 = peg$c38;
|
||
peg$currPos += 4;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c39); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c40();
|
||
}
|
||
s0 = s1;
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.substr(peg$currPos, 5) === peg$c41) {
|
||
s1 = peg$c41;
|
||
peg$currPos += 5;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c42); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c43();
|
||
}
|
||
s0 = s1;
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
function peg$parseUnaryExpr() {
|
||
var s0, s1, s2, s3;
|
||
|
||
s0 = peg$currPos;
|
||
if (input.substr(peg$currPos, 2) === peg$c44) {
|
||
s1 = peg$c44;
|
||
peg$currPos += 2;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c45); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = [];
|
||
s3 = peg$parsews();
|
||
if (s3 !== peg$FAILED) {
|
||
while (s3 !== peg$FAILED) {
|
||
s2.push(s3);
|
||
s3 = peg$parsews();
|
||
}
|
||
} else {
|
||
s2 = peg$c1;
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
s3 = peg$parseIntegerLiteral();
|
||
if (s3 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c46(s3);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.substr(peg$currPos, 2) === peg$c47) {
|
||
s1 = peg$c47;
|
||
peg$currPos += 2;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c48); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = [];
|
||
s3 = peg$parsews();
|
||
if (s3 !== peg$FAILED) {
|
||
while (s3 !== peg$FAILED) {
|
||
s2.push(s3);
|
||
s3 = peg$parsews();
|
||
}
|
||
} else {
|
||
s2 = peg$c1;
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
s3 = peg$parseStringLiteral();
|
||
if (s3 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c49(s3);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.substr(peg$currPos, 2) === peg$c50) {
|
||
s1 = peg$c50;
|
||
peg$currPos += 2;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c51); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = [];
|
||
s3 = peg$parsews();
|
||
if (s3 !== peg$FAILED) {
|
||
while (s3 !== peg$FAILED) {
|
||
s2.push(s3);
|
||
s3 = peg$parsews();
|
||
}
|
||
} else {
|
||
s2 = peg$c1;
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
s3 = peg$parseStringLiteral();
|
||
if (s3 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c52(s3);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.substr(peg$currPos, 3) === peg$c53) {
|
||
s1 = peg$c53;
|
||
peg$currPos += 3;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c54); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = [];
|
||
s3 = peg$parsews();
|
||
if (s3 !== peg$FAILED) {
|
||
while (s3 !== peg$FAILED) {
|
||
s2.push(s3);
|
||
s3 = peg$parsews();
|
||
}
|
||
} else {
|
||
s2 = peg$c1;
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
s3 = peg$parseStringLiteral();
|
||
if (s3 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c55(s3);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.substr(peg$currPos, 3) === peg$c56) {
|
||
s1 = peg$c56;
|
||
peg$currPos += 3;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c57); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = [];
|
||
s3 = peg$parsews();
|
||
if (s3 !== peg$FAILED) {
|
||
while (s3 !== peg$FAILED) {
|
||
s2.push(s3);
|
||
s3 = peg$parsews();
|
||
}
|
||
} else {
|
||
s2 = peg$c1;
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
s3 = peg$parseStringLiteral();
|
||
if (s3 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c58(s3);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.substr(peg$currPos, 2) === peg$c59) {
|
||
s1 = peg$c59;
|
||
peg$currPos += 2;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c60); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = [];
|
||
s3 = peg$parsews();
|
||
if (s3 !== peg$FAILED) {
|
||
while (s3 !== peg$FAILED) {
|
||
s2.push(s3);
|
||
s3 = peg$parsews();
|
||
}
|
||
} else {
|
||
s2 = peg$c1;
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
s3 = peg$parseStringLiteral();
|
||
if (s3 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c61(s3);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.substr(peg$currPos, 2) === peg$c62) {
|
||
s1 = peg$c62;
|
||
peg$currPos += 2;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c63); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = [];
|
||
s3 = peg$parsews();
|
||
if (s3 !== peg$FAILED) {
|
||
while (s3 !== peg$FAILED) {
|
||
s2.push(s3);
|
||
s3 = peg$parsews();
|
||
}
|
||
} else {
|
||
s2 = peg$c1;
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
s3 = peg$parseStringLiteral();
|
||
if (s3 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c64(s3);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.substr(peg$currPos, 3) === peg$c65) {
|
||
s1 = peg$c65;
|
||
peg$currPos += 3;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c66); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = [];
|
||
s3 = peg$parsews();
|
||
if (s3 !== peg$FAILED) {
|
||
while (s3 !== peg$FAILED) {
|
||
s2.push(s3);
|
||
s3 = peg$parsews();
|
||
}
|
||
} else {
|
||
s2 = peg$c1;
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
s3 = peg$parseStringLiteral();
|
||
if (s3 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c67(s3);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.substr(peg$currPos, 3) === peg$c68) {
|
||
s1 = peg$c68;
|
||
peg$currPos += 3;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c69); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = [];
|
||
s3 = peg$parsews();
|
||
if (s3 !== peg$FAILED) {
|
||
while (s3 !== peg$FAILED) {
|
||
s2.push(s3);
|
||
s3 = peg$parsews();
|
||
}
|
||
} else {
|
||
s2 = peg$c1;
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
s3 = peg$parseStringLiteral();
|
||
if (s3 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c70(s3);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.substr(peg$currPos, 2) === peg$c71) {
|
||
s1 = peg$c71;
|
||
peg$currPos += 2;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c72); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = [];
|
||
s3 = peg$parsews();
|
||
if (s3 !== peg$FAILED) {
|
||
while (s3 !== peg$FAILED) {
|
||
s2.push(s3);
|
||
s3 = peg$parsews();
|
||
}
|
||
} else {
|
||
s2 = peg$c1;
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
s3 = peg$parseStringLiteral();
|
||
if (s3 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c73(s3);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
s1 = peg$parseStringLiteral();
|
||
if (s1 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c73(s1);
|
||
}
|
||
s0 = s1;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
function peg$parseIntegerLiteral() {
|
||
var s0, s1, s2, s3;
|
||
|
||
peg$silentFails++;
|
||
s0 = peg$currPos;
|
||
if (peg$c76.test(input.charAt(peg$currPos))) {
|
||
s1 = input.charAt(peg$currPos);
|
||
peg$currPos++;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c77); }
|
||
}
|
||
if (s1 === peg$FAILED) {
|
||
s1 = peg$c75;
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = [];
|
||
if (peg$c78.test(input.charAt(peg$currPos))) {
|
||
s3 = input.charAt(peg$currPos);
|
||
peg$currPos++;
|
||
} else {
|
||
s3 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c79); }
|
||
}
|
||
if (s3 !== peg$FAILED) {
|
||
while (s3 !== peg$FAILED) {
|
||
s2.push(s3);
|
||
if (peg$c78.test(input.charAt(peg$currPos))) {
|
||
s3 = input.charAt(peg$currPos);
|
||
peg$currPos++;
|
||
} else {
|
||
s3 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c79); }
|
||
}
|
||
}
|
||
} else {
|
||
s2 = peg$c1;
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
if (peg$c76.test(input.charAt(peg$currPos))) {
|
||
s3 = input.charAt(peg$currPos);
|
||
peg$currPos++;
|
||
} else {
|
||
s3 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c77); }
|
||
}
|
||
if (s3 === peg$FAILED) {
|
||
s3 = peg$c75;
|
||
}
|
||
if (s3 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c80(s2);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
peg$silentFails--;
|
||
if (s0 === peg$FAILED) {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c74); }
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
function peg$parseStringLiteral() {
|
||
var s0, s1, s2, s3;
|
||
|
||
peg$silentFails++;
|
||
s0 = peg$currPos;
|
||
if (input.charCodeAt(peg$currPos) === 34) {
|
||
s1 = peg$c82;
|
||
peg$currPos++;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c83); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = [];
|
||
s3 = peg$parseDoubleStringChar();
|
||
while (s3 !== peg$FAILED) {
|
||
s2.push(s3);
|
||
s3 = peg$parseDoubleStringChar();
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
if (input.charCodeAt(peg$currPos) === 34) {
|
||
s3 = peg$c82;
|
||
peg$currPos++;
|
||
} else {
|
||
s3 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c83); }
|
||
}
|
||
if (s3 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c84(s2);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.charCodeAt(peg$currPos) === 39) {
|
||
s1 = peg$c85;
|
||
peg$currPos++;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c86); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = [];
|
||
s3 = peg$parseSingleStringChar();
|
||
while (s3 !== peg$FAILED) {
|
||
s2.push(s3);
|
||
s3 = peg$parseSingleStringChar();
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
if (input.charCodeAt(peg$currPos) === 39) {
|
||
s3 = peg$c85;
|
||
peg$currPos++;
|
||
} else {
|
||
s3 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c86); }
|
||
}
|
||
if (s3 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c84(s2);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
s1 = peg$currPos;
|
||
peg$silentFails++;
|
||
s2 = peg$parsecc();
|
||
peg$silentFails--;
|
||
if (s2 === peg$FAILED) {
|
||
s1 = peg$c87;
|
||
} else {
|
||
peg$currPos = s1;
|
||
s1 = peg$c1;
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = [];
|
||
s3 = peg$parseUnquotedStringChar();
|
||
if (s3 !== peg$FAILED) {
|
||
while (s3 !== peg$FAILED) {
|
||
s2.push(s3);
|
||
s3 = peg$parseUnquotedStringChar();
|
||
}
|
||
} else {
|
||
s2 = peg$c1;
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c84(s2);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
}
|
||
}
|
||
peg$silentFails--;
|
||
if (s0 === peg$FAILED) {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c81); }
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
function peg$parseDoubleStringChar() {
|
||
var s0, s1, s2;
|
||
|
||
s0 = peg$currPos;
|
||
s1 = peg$currPos;
|
||
peg$silentFails++;
|
||
if (peg$c88.test(input.charAt(peg$currPos))) {
|
||
s2 = input.charAt(peg$currPos);
|
||
peg$currPos++;
|
||
} else {
|
||
s2 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c89); }
|
||
}
|
||
peg$silentFails--;
|
||
if (s2 === peg$FAILED) {
|
||
s1 = peg$c87;
|
||
} else {
|
||
peg$currPos = s1;
|
||
s1 = peg$c1;
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
if (input.length > peg$currPos) {
|
||
s2 = input.charAt(peg$currPos);
|
||
peg$currPos++;
|
||
} else {
|
||
s2 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c90); }
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c91(s2);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.charCodeAt(peg$currPos) === 92) {
|
||
s1 = peg$c92;
|
||
peg$currPos++;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c93); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = peg$parseEscapeSequence();
|
||
if (s2 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c91(s2);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
function peg$parseSingleStringChar() {
|
||
var s0, s1, s2;
|
||
|
||
s0 = peg$currPos;
|
||
s1 = peg$currPos;
|
||
peg$silentFails++;
|
||
if (peg$c94.test(input.charAt(peg$currPos))) {
|
||
s2 = input.charAt(peg$currPos);
|
||
peg$currPos++;
|
||
} else {
|
||
s2 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c95); }
|
||
}
|
||
peg$silentFails--;
|
||
if (s2 === peg$FAILED) {
|
||
s1 = peg$c87;
|
||
} else {
|
||
peg$currPos = s1;
|
||
s1 = peg$c1;
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
if (input.length > peg$currPos) {
|
||
s2 = input.charAt(peg$currPos);
|
||
peg$currPos++;
|
||
} else {
|
||
s2 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c90); }
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c91(s2);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.charCodeAt(peg$currPos) === 92) {
|
||
s1 = peg$c92;
|
||
peg$currPos++;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c93); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
s2 = peg$parseEscapeSequence();
|
||
if (s2 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c91(s2);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
function peg$parseUnquotedStringChar() {
|
||
var s0, s1, s2;
|
||
|
||
s0 = peg$currPos;
|
||
s1 = peg$currPos;
|
||
peg$silentFails++;
|
||
s2 = peg$parsews();
|
||
peg$silentFails--;
|
||
if (s2 === peg$FAILED) {
|
||
s1 = peg$c87;
|
||
} else {
|
||
peg$currPos = s1;
|
||
s1 = peg$c1;
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
if (input.length > peg$currPos) {
|
||
s2 = input.charAt(peg$currPos);
|
||
peg$currPos++;
|
||
} else {
|
||
s2 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c90); }
|
||
}
|
||
if (s2 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c91(s2);
|
||
s0 = s1;
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
} else {
|
||
peg$currPos = s0;
|
||
s0 = peg$c1;
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
function peg$parseEscapeSequence() {
|
||
var s0, s1;
|
||
|
||
if (peg$c96.test(input.charAt(peg$currPos))) {
|
||
s0 = input.charAt(peg$currPos);
|
||
peg$currPos++;
|
||
} else {
|
||
s0 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c97); }
|
||
}
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.charCodeAt(peg$currPos) === 110) {
|
||
s1 = peg$c98;
|
||
peg$currPos++;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c99); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c100();
|
||
}
|
||
s0 = s1;
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.charCodeAt(peg$currPos) === 114) {
|
||
s1 = peg$c101;
|
||
peg$currPos++;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c102); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c103();
|
||
}
|
||
s0 = s1;
|
||
if (s0 === peg$FAILED) {
|
||
s0 = peg$currPos;
|
||
if (input.charCodeAt(peg$currPos) === 116) {
|
||
s1 = peg$c104;
|
||
peg$currPos++;
|
||
} else {
|
||
s1 = peg$FAILED;
|
||
if (peg$silentFails === 0) { peg$fail(peg$c105); }
|
||
}
|
||
if (s1 !== peg$FAILED) {
|
||
peg$reportedPos = s0;
|
||
s1 = peg$c106();
|
||
}
|
||
s0 = s1;
|
||
}
|
||
}
|
||
}
|
||
|
||
return s0;
|
||
}
|
||
|
||
|
||
function or(first, second) {
|
||
// Add explicit function names to ease debugging.
|
||
function orFilter() {
|
||
return first.apply(this, arguments) || second.apply(this, arguments);
|
||
}
|
||
orFilter.desc = first.desc + " or " + second.desc;
|
||
return orFilter;
|
||
}
|
||
function and(first, second) {
|
||
function andFilter() {
|
||
return first.apply(this, arguments) && second.apply(this, arguments);
|
||
}
|
||
andFilter.desc = first.desc + " and " + second.desc;
|
||
return andFilter;
|
||
}
|
||
function not(expr) {
|
||
function notFilter() {
|
||
return !expr.apply(this, arguments);
|
||
}
|
||
notFilter.desc = "not " + expr.desc;
|
||
return notFilter;
|
||
}
|
||
function binding(expr) {
|
||
function bindingFilter() {
|
||
return expr.apply(this, arguments);
|
||
}
|
||
bindingFilter.desc = "(" + expr.desc + ")";
|
||
return bindingFilter;
|
||
}
|
||
function trueFilter(flow) {
|
||
return true;
|
||
}
|
||
trueFilter.desc = "true";
|
||
function falseFilter(flow) {
|
||
return false;
|
||
}
|
||
falseFilter.desc = "false";
|
||
|
||
var ASSET_TYPES = [
|
||
new RegExp("text/javascript"),
|
||
new RegExp("application/x-javascript"),
|
||
new RegExp("application/javascript"),
|
||
new RegExp("text/css"),
|
||
new RegExp("image/.*"),
|
||
new RegExp("application/x-shockwave-flash")
|
||
];
|
||
function assetFilter(flow) {
|
||
if (flow.response) {
|
||
var ct = ResponseUtils.getContentType(flow.response);
|
||
var i = ASSET_TYPES.length;
|
||
while (i--) {
|
||
if (ASSET_TYPES[i].test(ct)) {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
assetFilter.desc = "is asset";
|
||
function responseCode(code){
|
||
function responseCodeFilter(flow){
|
||
return flow.response && flow.response.code === code;
|
||
}
|
||
responseCodeFilter.desc = "resp. code is " + code;
|
||
return responseCodeFilter;
|
||
}
|
||
function domain(regex){
|
||
regex = new RegExp(regex, "i");
|
||
function domainFilter(flow){
|
||
return flow.request && regex.test(flow.request.host);
|
||
}
|
||
domainFilter.desc = "domain matches " + regex;
|
||
return domainFilter;
|
||
}
|
||
function errorFilter(flow){
|
||
return !!flow.error;
|
||
}
|
||
errorFilter.desc = "has error";
|
||
function header(regex){
|
||
regex = new RegExp(regex, "i");
|
||
function headerFilter(flow){
|
||
return (
|
||
(flow.request && RequestUtils.match_header(flow.request, regex))
|
||
||
|
||
(flow.response && ResponseUtils.match_header(flow.response, regex))
|
||
);
|
||
}
|
||
headerFilter.desc = "header matches " + regex;
|
||
return headerFilter;
|
||
}
|
||
function requestHeader(regex){
|
||
regex = new RegExp(regex, "i");
|
||
function requestHeaderFilter(flow){
|
||
return (flow.request && RequestUtils.match_header(flow.request, regex));
|
||
}
|
||
requestHeaderFilter.desc = "req. header matches " + regex;
|
||
return requestHeaderFilter;
|
||
}
|
||
function responseHeader(regex){
|
||
regex = new RegExp(regex, "i");
|
||
function responseHeaderFilter(flow){
|
||
return (flow.response && ResponseUtils.match_header(flow.response, regex));
|
||
}
|
||
responseHeaderFilter.desc = "resp. header matches " + regex;
|
||
return responseHeaderFilter;
|
||
}
|
||
function method(regex){
|
||
regex = new RegExp(regex, "i");
|
||
function methodFilter(flow){
|
||
return flow.request && regex.test(flow.request.method);
|
||
}
|
||
methodFilter.desc = "method matches " + regex;
|
||
return methodFilter;
|
||
}
|
||
function noResponseFilter(flow){
|
||
return flow.request && !flow.response;
|
||
}
|
||
noResponseFilter.desc = "has no response";
|
||
function responseFilter(flow){
|
||
return !!flow.response;
|
||
}
|
||
responseFilter.desc = "has response";
|
||
|
||
function contentType(regex){
|
||
regex = new RegExp(regex, "i");
|
||
function contentTypeFilter(flow){
|
||
return (
|
||
(flow.request && regex.test(RequestUtils.getContentType(flow.request)))
|
||
||
|
||
(flow.response && regex.test(ResponseUtils.getContentType(flow.response)))
|
||
);
|
||
}
|
||
contentTypeFilter.desc = "content type matches " + regex;
|
||
return contentTypeFilter;
|
||
}
|
||
function requestContentType(regex){
|
||
regex = new RegExp(regex, "i");
|
||
function requestContentTypeFilter(flow){
|
||
return flow.request && regex.test(RequestUtils.getContentType(flow.request));
|
||
}
|
||
requestContentTypeFilter.desc = "req. content type matches " + regex;
|
||
return requestContentTypeFilter;
|
||
}
|
||
function responseContentType(regex){
|
||
regex = new RegExp(regex, "i");
|
||
function responseContentTypeFilter(flow){
|
||
return flow.response && regex.test(ResponseUtils.getContentType(flow.response));
|
||
}
|
||
responseContentTypeFilter.desc = "resp. content type matches " + regex;
|
||
return responseContentTypeFilter;
|
||
}
|
||
function url(regex){
|
||
regex = new RegExp(regex, "i");
|
||
function urlFilter(flow){
|
||
return flow.request && regex.test(RequestUtils.pretty_url(flow.request));
|
||
}
|
||
urlFilter.desc = "url matches " + regex;
|
||
return urlFilter;
|
||
}
|
||
|
||
|
||
peg$result = peg$startRuleFunction();
|
||
|
||
if (peg$result !== peg$FAILED && peg$currPos === input.length) {
|
||
return peg$result;
|
||
} else {
|
||
if (peg$result !== peg$FAILED && peg$currPos < input.length) {
|
||
peg$fail({ type: "end", description: "end of input" });
|
||
}
|
||
|
||
throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos);
|
||
}
|
||
}
|
||
|
||
return {
|
||
SyntaxError: SyntaxError,
|
||
parse: parse
|
||
};
|
||
})();
|
||
/* jshint ignore:end */
|
||
|
||
module.exports = Filt;
|
||
|
||
},{}],16:[function(require,module,exports){
|
||
var _ = require("lodash");
|
||
|
||
var _MessageUtils = {
|
||
getContentType: function (message) {
|
||
return this.get_first_header(message, /^Content-Type$/i);
|
||
},
|
||
get_first_header: function (message, regex) {
|
||
//FIXME: Cache Invalidation.
|
||
if (!message._headerLookups)
|
||
Object.defineProperty(message, "_headerLookups", {
|
||
value: {},
|
||
configurable: false,
|
||
enumerable: false,
|
||
writable: false
|
||
});
|
||
if (!(regex in message._headerLookups)) {
|
||
var header;
|
||
for (var i = 0; i < message.headers.length; i++) {
|
||
if (!!message.headers[i][0].match(regex)) {
|
||
header = message.headers[i];
|
||
break;
|
||
}
|
||
}
|
||
message._headerLookups[regex] = header ? header[1] : undefined;
|
||
}
|
||
return message._headerLookups[regex];
|
||
},
|
||
match_header: function (message, regex) {
|
||
var headers = message.headers;
|
||
var i = headers.length;
|
||
while (i--) {
|
||
if (regex.test(headers[i].join(" "))) {
|
||
return headers[i];
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
};
|
||
|
||
var defaultPorts = {
|
||
"http": 80,
|
||
"https": 443
|
||
};
|
||
|
||
var RequestUtils = _.extend(_MessageUtils, {
|
||
pretty_host: function (request) {
|
||
//FIXME: Add hostheader
|
||
return request.host;
|
||
},
|
||
pretty_url: function (request) {
|
||
var port = "";
|
||
if (defaultPorts[request.scheme] !== request.port) {
|
||
port = ":" + request.port;
|
||
}
|
||
return request.scheme + "://" + this.pretty_host(request) + port + request.path;
|
||
}
|
||
});
|
||
|
||
var ResponseUtils = _.extend(_MessageUtils, {});
|
||
|
||
|
||
module.exports = {
|
||
ResponseUtils: ResponseUtils,
|
||
RequestUtils: RequestUtils
|
||
|
||
}
|
||
},{"lodash":"lodash"}],17:[function(require,module,exports){
|
||
|
||
var _ = require("lodash");
|
||
var $ = require("jquery");
|
||
|
||
var utils = require("../utils.js");
|
||
var actions = require("../actions.js");
|
||
var dispatcher = require("../dispatcher.js");
|
||
|
||
|
||
function ListStore() {
|
||
utils.EventEmitter.call(this);
|
||
this.reset();
|
||
}
|
||
_.extend(ListStore.prototype, utils.EventEmitter.prototype, {
|
||
add: function (elem) {
|
||
if (elem.id in this._pos_map) {
|
||
return;
|
||
}
|
||
this._pos_map[elem.id] = this.list.length;
|
||
this.list.push(elem);
|
||
this.emit("add", elem);
|
||
},
|
||
update: function (elem) {
|
||
if (!(elem.id in this._pos_map)) {
|
||
return;
|
||
}
|
||
this.list[this._pos_map[elem.id]] = elem;
|
||
this.emit("update", elem);
|
||
},
|
||
remove: function (elem_id) {
|
||
if (!(elem_id in this._pos_map)) {
|
||
return;
|
||
}
|
||
this.list.splice(this._pos_map[elem_id], 1);
|
||
this._build_map();
|
||
this.emit("remove", elem_id);
|
||
},
|
||
reset: function (elems) {
|
||
this.list = elems || [];
|
||
this._build_map();
|
||
this.emit("recalculate");
|
||
},
|
||
_build_map: function () {
|
||
this._pos_map = {};
|
||
for (var i = 0; i < this.list.length; i++) {
|
||
var elem = this.list[i];
|
||
this._pos_map[elem.id] = i;
|
||
}
|
||
},
|
||
get: function (elem_id) {
|
||
return this.list[this._pos_map[elem_id]];
|
||
},
|
||
index: function (elem_id) {
|
||
return this._pos_map[elem_id];
|
||
}
|
||
});
|
||
|
||
|
||
function DictStore() {
|
||
utils.EventEmitter.call(this);
|
||
this.reset();
|
||
}
|
||
_.extend(DictStore.prototype, utils.EventEmitter.prototype, {
|
||
update: function (dict) {
|
||
_.merge(this.dict, dict);
|
||
this.emit("recalculate");
|
||
},
|
||
reset: function (dict) {
|
||
this.dict = dict || {};
|
||
this.emit("recalculate");
|
||
}
|
||
});
|
||
|
||
function LiveStoreMixin(type) {
|
||
this.type = type;
|
||
|
||
this._updates_before_fetch = undefined;
|
||
this._fetchxhr = false;
|
||
|
||
this.handle = this.handle.bind(this);
|
||
dispatcher.AppDispatcher.register(this.handle);
|
||
|
||
// Avoid double-fetch on startup.
|
||
if (!(window.ws && window.ws.readyState === WebSocket.CONNECTING)) {
|
||
this.fetch();
|
||
}
|
||
}
|
||
_.extend(LiveStoreMixin.prototype, {
|
||
handle: function (event) {
|
||
if (event.type === actions.ActionTypes.CONNECTION_OPEN) {
|
||
return this.fetch();
|
||
}
|
||
if (event.type === this.type) {
|
||
if (event.cmd === actions.StoreCmds.RESET) {
|
||
this.fetch(event.data);
|
||
} else if (this._updates_before_fetch) {
|
||
console.log("defer update", event);
|
||
this._updates_before_fetch.push(event);
|
||
} else {
|
||
this[event.cmd](event.data);
|
||
}
|
||
}
|
||
},
|
||
close: function () {
|
||
dispatcher.AppDispatcher.unregister(this.handle);
|
||
},
|
||
fetch: function (data) {
|
||
console.log("fetch " + this.type);
|
||
if (this._fetchxhr) {
|
||
this._fetchxhr.abort();
|
||
}
|
||
this._updates_before_fetch = []; // (JS: empty array is true)
|
||
if (data) {
|
||
this.handle_fetch(data);
|
||
} else {
|
||
this._fetchxhr = $.getJSON("/" + this.type)
|
||
.done(function (message) {
|
||
this.handle_fetch(message.data);
|
||
}.bind(this))
|
||
.fail(function () {
|
||
EventLogActions.add_event("Could not fetch " + this.type);
|
||
}.bind(this));
|
||
}
|
||
},
|
||
handle_fetch: function (data) {
|
||
this._fetchxhr = false;
|
||
console.log(this.type + " fetched.", this._updates_before_fetch);
|
||
this.reset(data);
|
||
var updates = this._updates_before_fetch;
|
||
this._updates_before_fetch = false;
|
||
for (var i = 0; i < updates.length; i++) {
|
||
this.handle(updates[i]);
|
||
}
|
||
},
|
||
});
|
||
|
||
function LiveListStore(type) {
|
||
ListStore.call(this);
|
||
LiveStoreMixin.call(this, type);
|
||
}
|
||
_.extend(LiveListStore.prototype, ListStore.prototype, LiveStoreMixin.prototype);
|
||
|
||
function LiveDictStore(type) {
|
||
DictStore.call(this);
|
||
LiveStoreMixin.call(this, type);
|
||
}
|
||
_.extend(LiveDictStore.prototype, DictStore.prototype, LiveStoreMixin.prototype);
|
||
|
||
|
||
function FlowStore() {
|
||
return new LiveListStore(actions.ActionTypes.FLOW_STORE);
|
||
}
|
||
|
||
function SettingsStore() {
|
||
return new LiveDictStore(actions.ActionTypes.SETTINGS_STORE);
|
||
}
|
||
|
||
function EventLogStore() {
|
||
LiveListStore.call(this, actions.ActionTypes.EVENT_STORE);
|
||
}
|
||
_.extend(EventLogStore.prototype, LiveListStore.prototype, {
|
||
fetch: function(){
|
||
LiveListStore.prototype.fetch.apply(this, arguments);
|
||
|
||
// Make sure to display updates even if fetching all events failed.
|
||
// This way, we can send "fetch failed" log messages to the log.
|
||
if(this._fetchxhr){
|
||
this._fetchxhr.fail(function(){
|
||
this.handle_fetch(null);
|
||
}.bind(this));
|
||
}
|
||
}
|
||
});
|
||
|
||
|
||
module.exports = {
|
||
EventLogStore: EventLogStore,
|
||
SettingsStore: SettingsStore,
|
||
FlowStore: FlowStore
|
||
};
|
||
},{"../actions.js":1,"../dispatcher.js":14,"../utils.js":19,"jquery":"jquery","lodash":"lodash"}],18:[function(require,module,exports){
|
||
var _ = require("lodash");
|
||
|
||
var utils = require("../utils.js");
|
||
|
||
function SortByStoreOrder(elem) {
|
||
return this.store.index(elem.id);
|
||
}
|
||
|
||
var default_sort = SortByStoreOrder;
|
||
var default_filt = function(elem){
|
||
return true;
|
||
};
|
||
|
||
function StoreView(store, filt, sortfun) {
|
||
utils.EventEmitter.call(this);
|
||
filt = filt || default_filt;
|
||
sortfun = sortfun || default_sort;
|
||
|
||
this.store = store;
|
||
|
||
this.add = this.add.bind(this);
|
||
this.update = this.update.bind(this);
|
||
this.remove = this.remove.bind(this);
|
||
this.recalculate = this.recalculate.bind(this);
|
||
this.store.addListener("add", this.add);
|
||
this.store.addListener("update", this.update);
|
||
this.store.addListener("remove", this.remove);
|
||
this.store.addListener("recalculate", this.recalculate);
|
||
|
||
this.recalculate(filt, sortfun);
|
||
}
|
||
|
||
_.extend(StoreView.prototype, utils.EventEmitter.prototype, {
|
||
close: function () {
|
||
this.store.removeListener("add", this.add);
|
||
this.store.removeListener("update", this.update);
|
||
this.store.removeListener("remove", this.remove);
|
||
this.store.removeListener("recalculate", this.recalculate);
|
||
},
|
||
recalculate: function (filt, sortfun) {
|
||
if (filt) {
|
||
this.filt = filt.bind(this);
|
||
}
|
||
if (sortfun) {
|
||
this.sortfun = sortfun.bind(this);
|
||
}
|
||
|
||
this.list = this.store.list.filter(this.filt);
|
||
this.list.sort(function (a, b) {
|
||
return this.sortfun(a) - this.sortfun(b);
|
||
}.bind(this));
|
||
this.emit("recalculate");
|
||
},
|
||
index: function (elem) {
|
||
return _.sortedIndex(this.list, elem, this.sortfun);
|
||
},
|
||
add: function (elem) {
|
||
if (this.filt(elem)) {
|
||
var idx = this.index(elem);
|
||
if (idx === this.list.length) { //happens often, .push is way faster.
|
||
this.list.push(elem);
|
||
} else {
|
||
this.list.splice(idx, 0, elem);
|
||
}
|
||
this.emit("add", elem, idx);
|
||
}
|
||
},
|
||
update: function (elem) {
|
||
var idx;
|
||
var i = this.list.length;
|
||
// Search from the back, we usually update the latest entries.
|
||
while (i--) {
|
||
if (this.list[i].id === elem.id) {
|
||
idx = i;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (idx === -1) { //not contained in list
|
||
this.add(elem);
|
||
} else if (!this.filt(elem)) {
|
||
this.remove(elem.id);
|
||
} else {
|
||
if (this.sortfun(this.list[idx]) !== this.sortfun(elem)) { //sortpos has changed
|
||
this.remove(this.list[idx]);
|
||
this.add(elem);
|
||
} else {
|
||
this.list[idx] = elem;
|
||
this.emit("update", elem, idx);
|
||
}
|
||
}
|
||
},
|
||
remove: function (elem_id) {
|
||
var idx = this.list.length;
|
||
while (idx--) {
|
||
if (this.list[idx].id === elem_id) {
|
||
this.list.splice(idx, 1);
|
||
this.emit("remove", elem_id, idx);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
});
|
||
|
||
module.exports = {
|
||
StoreView: StoreView
|
||
};
|
||
},{"../utils.js":19,"lodash":"lodash"}],19:[function(require,module,exports){
|
||
var $ = require("jquery");
|
||
|
||
|
||
var Key = {
|
||
UP: 38,
|
||
DOWN: 40,
|
||
PAGE_UP: 33,
|
||
PAGE_DOWN: 34,
|
||
HOME: 36,
|
||
END: 35,
|
||
LEFT: 37,
|
||
RIGHT: 39,
|
||
ENTER: 13,
|
||
ESC: 27,
|
||
TAB: 9,
|
||
SPACE: 32,
|
||
BACKSPACE: 8,
|
||
};
|
||
// Add A-Z
|
||
for (var i = 65; i <= 90; i++) {
|
||
Key[String.fromCharCode(i)] = i;
|
||
}
|
||
|
||
|
||
var formatSize = function (bytes) {
|
||
var size = bytes;
|
||
var prefix = ["B", "KB", "MB", "GB", "TB"];
|
||
var i = 0;
|
||
while (Math.abs(size) >= 1024 && i < prefix.length - 1) {
|
||
i++;
|
||
size = size / 1024;
|
||
}
|
||
return (Math.floor(size * 100) / 100.0).toFixed(2) + prefix[i];
|
||
};
|
||
|
||
|
||
var formatTimeDelta = function (milliseconds) {
|
||
var time = milliseconds;
|
||
var prefix = ["ms", "s", "min", "h"];
|
||
var div = [1000, 60, 60];
|
||
var i = 0;
|
||
while (Math.abs(time) >= div[i] && i < div.length) {
|
||
time = time / div[i];
|
||
i++;
|
||
}
|
||
return Math.round(time) + prefix[i];
|
||
};
|
||
|
||
|
||
var formatTimeStamp = function (seconds) {
|
||
var ts = (new Date(seconds * 1000)).toISOString();
|
||
return ts.replace("T", " ").replace("Z", "");
|
||
};
|
||
|
||
|
||
function EventEmitter() {
|
||
this.listeners = {};
|
||
}
|
||
EventEmitter.prototype.emit = function (event) {
|
||
if (!(event in this.listeners)) {
|
||
return;
|
||
}
|
||
var args = Array.prototype.slice.call(arguments, 1);
|
||
this.listeners[event].forEach(function (listener) {
|
||
listener.apply(this, args);
|
||
}.bind(this));
|
||
};
|
||
EventEmitter.prototype.addListener = function (events, f) {
|
||
events.split(" ").forEach(function (event) {
|
||
this.listeners[event] = this.listeners[event] || [];
|
||
this.listeners[event].push(f);
|
||
}.bind(this));
|
||
};
|
||
EventEmitter.prototype.removeListener = function (events, f) {
|
||
if (!(events in this.listeners)) {
|
||
return false;
|
||
}
|
||
events.split(" ").forEach(function (event) {
|
||
var index = this.listeners[event].indexOf(f);
|
||
if (index >= 0) {
|
||
this.listeners[event].splice(index, 1);
|
||
}
|
||
}.bind(this));
|
||
};
|
||
|
||
|
||
function getCookie(name) {
|
||
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
|
||
return r ? r[1] : undefined;
|
||
}
|
||
var xsrf = $.param({_xsrf: getCookie("_xsrf")});
|
||
|
||
//Tornado XSRF Protection.
|
||
$.ajaxPrefilter(function (options) {
|
||
if (["post", "put", "delete"].indexOf(options.type.toLowerCase()) >= 0 && options.url[0] === "/") {
|
||
if (options.data) {
|
||
options.data += ("&" + xsrf);
|
||
} else {
|
||
options.data = xsrf;
|
||
}
|
||
}
|
||
});
|
||
// Log AJAX Errors
|
||
$(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) {
|
||
var message = jqXHR.responseText;
|
||
console.error(message, arguments);
|
||
EventLogActions.add_event(thrownError + ": " + message);
|
||
window.alert(message);
|
||
});
|
||
|
||
module.exports = {
|
||
EventEmitter: EventEmitter,
|
||
formatSize: formatSize,
|
||
formatTimeDelta: formatTimeDelta,
|
||
formatTimeStamp: formatTimeStamp,
|
||
Key: Key
|
||
};
|
||
},{"jquery":"jquery"}]},{},[2])
|
||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJzcmMvanMvYWN0aW9ucy5qcyIsInNyYy9qcy9hcHAuanMiLCJzcmMvanMvY29tcG9uZW50cy9ldmVudGxvZy5qcyIsInNyYy9qcy9jb21wb25lbnRzL2Zsb3dkZXRhaWwuanMiLCJzcmMvanMvY29tcG9uZW50cy9mbG93dGFibGUtY29sdW1ucy5qcyIsInNyYy9qcy9jb21wb25lbnRzL2Zsb3d0YWJsZS5qcyIsInNyYy9qcy9jb21wb25lbnRzL2Zvb3Rlci5qcyIsInNyYy9qcy9jb21wb25lbnRzL2hlYWRlci5qcyIsInNyYy9qcy9jb21wb25lbnRzL21haW52aWV3LmpzIiwic3JjL2pzL2NvbXBvbmVudHMvcHJveHlhcHAuanMiLCJzcmMvanMvY29tcG9uZW50cy91dGlscy5qcyIsInNyYy9qcy9jb21wb25lbnRzL3ZpcnR1YWxzY3JvbGwuanMiLCJzcmMvanMvY29ubmVjdGlvbi5qcyIsInNyYy9qcy9kaXNwYXRjaGVyLmpzIiwic3JjL2pzL2ZpbHQvZmlsdC5qcyIsInNyYy9qcy9mbG93L3V0aWxzLmpzIiwic3JjL2pzL3N0b3JlL3N0b3JlLmpzIiwic3JjL2pzL3N0b3JlL3ZpZXcuanMiLCJzcmMvanMvdXRpbHMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlZQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeElBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcFlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeE9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbk1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNodkRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25MQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwidmFyICQgPSByZXF1aXJlKFwianF1ZXJ5XCIpO1xuXG52YXIgQWN0aW9uVHlwZXMgPSB7XG4gICAgLy8gQ29ubmVjdGlvblxuICAgIENPTk5FQ1RJT05fT1BFTjogXCJjb25uZWN0aW9uX29wZW5cIixcbiAgICBDT05ORUNUSU9OX0NMT1NFOiBcImNvbm5lY3Rpb25fY2xvc2VcIixcbiAgICBDT05ORUNUSU9OX0VSUk9SOiBcImNvbm5lY3Rpb25fZXJyb3JcIixcblxuICAgIC8vIFN0b3Jlc1xuICAgIFNFVFRJTkdTX1NUT1JFOiBcInNldHRpbmdzXCIsXG4gICAgRVZFTlRfU1RPUkU6IFwiZXZlbnRzXCIsXG4gICAgRkxPV19TVE9SRTogXCJmbG93c1wiLFxufTtcblxudmFyIFN0b3JlQ21kcyA9IHtcbiAgICBBREQ6IFwiYWRkXCIsXG4gICAgVVBEQVRFOiBcInVwZGF0ZVwiLFxuICAgIFJFTU9WRTogXCJyZW1vdmVcIixcbiAgICBSRVNFVDogXCJyZXNldFwiXG59O1xuXG52YXIgQ29ubmVjdGlvbkFjdGlvbnMgPSB7XG4gICAgb3BlbjogZnVuY3Rpb24gKCkge1xuICAgICAgICBBcHBEaXNwYXRjaGVyLmRpc3BhdGNoVmlld0FjdGlvbih7XG4gICAgICAgICAgICB0eXBlOiBBY3Rpb25UeXBlcy5DT05ORUNUSU9OX09QRU5cbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBjbG9zZTogZnVuY3Rpb24gKCkge1xuICAgICAgICBBcHBEaXNwYXRjaGVyLmRpc3BhdGNoVmlld0FjdGlvbih7XG4gICAgICAgICAgICB0eXBlOiBBY3Rpb25UeXBlcy5DT05ORUNUSU9OX0NMT1NFXG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgZXJyb3I6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgQXBwRGlzcGF0Y2hlci5kaXNwYXRjaFZpZXdBY3Rpb24oe1xuICAgICAgICAgICAgdHlwZTogQWN0aW9uVHlwZXMuQ09OTkVDVElPTl9FUlJPUlxuICAgICAgICB9KTtcbiAgICB9XG59O1xuXG52YXIgU2V0dGluZ3NBY3Rpb25zID0ge1xuICAgIHVwZGF0ZTogZnVuY3Rpb24gKHNldHRpbmdzKSB7XG5cbiAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgIHR5cGU6IFwiUFVUXCIsXG4gICAgICAgICAgICB1cmw6IFwiL3NldHRpbmdzXCIsXG4gICAgICAgICAgICBkYXRhOiBzZXR0aW5nc1xuICAgICAgICB9KTtcblxuICAgICAgICAvKlxuICAgICAgICAvL0ZhY2Vib29rIEZsdXg6IFdlIGRvIGFuIG9wdGltaXN0aWMgdXBkYXRlIG9uIHRoZSBjbGllbnQgYWxyZWFkeS5cbiAgICAgICAgQXBwRGlzcGF0Y2hlci5kaXNwYXRjaFZpZXdBY3Rpb24oe1xuICAgICAgICAgICAgdHlwZTogQWN0aW9uVHlwZXMuU0VUVElOR1NfU1RPUkUsXG4gICAgICAgICAgICBjbWQ6IFN0b3JlQ21kcy5VUERBVEUsXG4gICAgICAgICAgICBkYXRhOiBzZXR0aW5nc1xuICAgICAgICB9KTtcbiAgICAgICAgKi9cbiAgICB9XG59O1xuXG52YXIgRXZlbnRMb2dBY3Rpb25zX2V2ZW50X2lkID0gMDtcbnZhciBFdmVudExvZ0FjdGlvbnMgPSB7XG4gICAgYWRkX2V2ZW50OiBmdW5jdGlvbiAobWVzc2FnZSkge1xuICAgICAgICBBcHBEaXNwYXRjaGVyLmRpc3BhdGNoVmlld0FjdGlvbih7XG4gICAgICAgICAgICB0eXBlOiBBY3Rpb25UeXBlcy5FVkVOVF9TVE9SRSxcbiAgICAgICAgICAgIGNtZDogU3RvcmVDbWRzLkFERCxcbiAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBtZXNzYWdlLFxuICAgICAgICAgICAgICAgIGxldmVsOiBcIndlYlwiLFxuICAgICAgICAgICAgICAgIGlkOiBcInZpZXdBY3Rpb24tXCIgKyBFdmVudExvZ0FjdGlvbnNfZXZlbnRfaWQrK1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG59O1xuXG52YXIgRmxvd0FjdGlvbnMgPSB7XG4gICAgYWNjZXB0OiBmdW5jdGlvbiAoZmxvdykge1xuICAgICAgICAkLnBvc3QoXCIvZmxvd3MvXCIgKyBmbG93LmlkICsgXCIvYWNjZXB0XCIpO1xuICAgIH0sXG4gICAgYWNjZXB0X2FsbDogZnVuY3Rpb24oKXtcbiAgICAgICAgJC5wb3N0KFwiL2Zsb3dzL2FjY2VwdFwiKTtcbiAgICB9LFxuICAgIFwiZGVsZXRlXCI6IGZ1bmN0aW9uKGZsb3cpe1xuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgdHlwZTpcIkRFTEVURVwiLFxuICAgICAgICAgICAgdXJsOiBcIi9mbG93cy9cIiArIGZsb3cuaWRcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBkdXBsaWNhdGU6IGZ1bmN0aW9uKGZsb3cpe1xuICAgICAgICAkLnBvc3QoXCIvZmxvd3MvXCIgKyBmbG93LmlkICsgXCIvZHVwbGljYXRlXCIpO1xuICAgIH0sXG4gICAgcmVwbGF5OiBmdW5jdGlvbihmbG93KXtcbiAgICAgICAgJC5wb3N0KFwiL2Zsb3dzL1wiICsgZmxvdy5pZCArIFwiL3JlcGxheVwiKTtcbiAgICB9LFxuICAgIHJldmVydDogZnVuY3Rpb24oZmxvdyl7XG4gICAgICAgICQucG9zdChcIi9mbG93cy9cIiArIGZsb3cuaWQgKyBcIi9yZXZlcnRcIik7XG4gICAgfSxcbiAgICB1cGRhdGU6IGZ1bmN0aW9uIChmbG93KSB7XG4gICAgICAgIEFwcERpc3BhdGNoZXIuZGlzcGF0Y2hWaWV3QWN0aW9uKHtcbiAgICAgICAgICAgIHR5cGU6IEFjdGlvblR5cGVzLkZMT1dfU1RPUkUsXG4gICAgICAgICAgICBjbWQ6IFN0b3JlQ21kcy5VUERBVEUsXG4gICAgICAgICAgICBkYXRhOiBmbG93XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgY2xlYXI6IGZ1bmN0aW9uKCl7XG4gICAgICAgICQucG9zdChcIi9jbGVhclwiKTtcbiAgICB9XG59O1xuXG5RdWVyeSA9IHtcbiAgICBGSUxURVI6IFwiZlwiLFxuICAgIEhJR0hMSUdIVDogXCJoXCIsXG4gICAgU0hPV19FVkVOVExPRzogXCJlXCJcbn07XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIEFjdGlvblR5cGVzOiBBY3Rpb25UeXBlcyxcbiAgICBDb25uZWN0aW9uQWN0aW9uczogQ29ubmVjdGlvbkFjdGlvbnMsXG4gICAgRmxvd0FjdGlvbnM6IEZsb3dBY3Rpb25zLFxuICAgIFN0b3JlQ21kczogU3RvcmVDbWRzXG5cblxufTsiLCJcbnZhciBSZWFjdCA9IHJlcXVpcmUoXCJyZWFjdFwiKTtcbnZhciBSZWFjdFJvdXRlciA9IHJlcXVpcmUoXCJyZWFjdC1yb3V0ZXJcIik7XG52YXIgJCA9IHJlcXVpcmUoXCJqcXVlcnlcIik7XG5cbnZhciBDb25uZWN0aW9uID0gcmVxdWlyZShcIi4vY29ubmVjdGlvblwiKTtcbnZhciBwcm94eWFwcCA9IHJlcXVpcmUoXCIuL2NvbXBvbmVudHMvcHJveHlhcHAuanNcIik7XG5cbiQoZnVuY3Rpb24gKCkge1xuICAgIHdpbmRvdy53cyA9IG5ldyBDb25uZWN0aW9uKFwiL3VwZGF0ZXNcIik7XG5cbiAgICBSZWFjdFJvdXRlci5ydW4ocHJveHlhcHAucm91dGVzLCBmdW5jdGlvbiAoSGFuZGxlcikge1xuICAgICAgICBSZWFjdC5yZW5kZXIoUmVhY3QuY3JlYXRlRWxlbWVudChIYW5kbGVyLCBudWxsKSwgZG9jdW1lbnQuYm9keSk7XG4gICAgfSk7XG59KTsiLCJ2YXIgUmVhY3QgPSByZXF1aXJlKFwicmVhY3RcIik7XG52YXIgdXRpbHMgPSByZXF1aXJlKFwiLi91dGlscy5qc1wiKTtcbnZhciBWaXJ0dWFsU2Nyb2xsTWl4aW4gPSByZXF1aXJlKFwiLi92aXJ0dWFsc2Nyb2xsLmpzXCIpO1xudmFyIHZpZXdzID0gcmVxdWlyZShcIi4uL3N0b3JlL3ZpZXcuanNcIik7XG5cbnZhciBMb2dNZXNzYWdlID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIkxvZ01lc3NhZ2VcIixcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGVudHJ5ID0gdGhpcy5wcm9wcy5lbnRyeTtcbiAgICAgICAgdmFyIGluZGljYXRvcjtcbiAgICAgICAgc3dpdGNoIChlbnRyeS5sZXZlbCkge1xuICAgICAgICAgICAgY2FzZSBcIndlYlwiOlxuICAgICAgICAgICAgICAgIGluZGljYXRvciA9IFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJpXCIsIHtjbGFzc05hbWU6IFwiZmEgZmEtZncgZmEtaHRtbDVcIn0pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcImRlYnVnXCI6XG4gICAgICAgICAgICAgICAgaW5kaWNhdG9yID0gUmVhY3QuY3JlYXRlRWxlbWVudChcImlcIiwge2NsYXNzTmFtZTogXCJmYSBmYS1mdyBmYS1idWdcIn0pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBpbmRpY2F0b3IgPSBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaVwiLCB7Y2xhc3NOYW1lOiBcImZhIGZhLWZ3IGZhLWluZm9cIn0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIG51bGwsIFxuICAgICAgICAgICAgICAgIGluZGljYXRvciwgXCIgXCIsIGVudHJ5Lm1lc3NhZ2VcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9LFxuICAgIHNob3VsZENvbXBvbmVudFVwZGF0ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7IC8vIGxvZyBlbnRyaWVzIGFyZSBpbW11dGFibGUuXG4gICAgfVxufSk7XG5cbnZhciBFdmVudExvZ0NvbnRlbnRzID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIkV2ZW50TG9nQ29udGVudHNcIixcbiAgICBtaXhpbnM6IFt1dGlscy5BdXRvU2Nyb2xsTWl4aW4sIFZpcnR1YWxTY3JvbGxNaXhpbl0sXG4gICAgZ2V0SW5pdGlhbFN0YXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBsb2c6IFtdXG4gICAgICAgIH07XG4gICAgfSxcbiAgICBjb21wb25lbnRXaWxsTW91bnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5vcGVuVmlldyh0aGlzLnByb3BzLmV2ZW50U3RvcmUpO1xuICAgIH0sXG4gICAgY29tcG9uZW50V2lsbFVubW91bnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jbG9zZVZpZXcoKTtcbiAgICB9LFxuICAgIG9wZW5WaWV3OiBmdW5jdGlvbiAoc3RvcmUpIHtcbiAgICAgICAgdmFyIHZpZXcgPSBuZXcgdmlld3MuU3RvcmVWaWV3KHN0b3JlLCBmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnByb3BzLmZpbHRlcltlbnRyeS5sZXZlbF07XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgdmlldzogdmlld1xuICAgICAgICB9KTtcblxuICAgICAgICB2aWV3LmFkZExpc3RlbmVyKFwiYWRkIHJlY2FsY3VsYXRlXCIsIHRoaXMub25FdmVudExvZ0NoYW5nZSk7XG4gICAgfSxcbiAgICBjbG9zZVZpZXc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zdGF0ZS52aWV3LmNsb3NlKCk7XG4gICAgfSxcbiAgICBvbkV2ZW50TG9nQ2hhbmdlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgbG9nOiB0aGlzLnN0YXRlLnZpZXcubGlzdFxuICAgICAgICB9KTtcbiAgICB9LFxuICAgIGNvbXBvbmVudFdpbGxSZWNlaXZlUHJvcHM6IGZ1bmN0aW9uIChuZXh0UHJvcHMpIHtcbiAgICAgICAgaWYgKG5leHRQcm9wcy5maWx0ZXIgIT09IHRoaXMucHJvcHMuZmlsdGVyKSB7XG4gICAgICAgICAgICB0aGlzLnByb3BzLmZpbHRlciA9IG5leHRQcm9wcy5maWx0ZXI7IC8vIERpcnR5OiBNYWtlIHN1cmUgdGhhdCB2aWV3IGZpbHRlciBzZWVzIHRoZSB1cGRhdGUuXG4gICAgICAgICAgICB0aGlzLnN0YXRlLnZpZXcucmVjYWxjdWxhdGUoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobmV4dFByb3BzLmV2ZW50U3RvcmUgIT09IHRoaXMucHJvcHMuZXZlbnRTdG9yZSkge1xuICAgICAgICAgICAgdGhpcy5jbG9zZVZpZXcoKTtcbiAgICAgICAgICAgIHRoaXMub3BlblZpZXcobmV4dFByb3BzLmV2ZW50U3RvcmUpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBnZXREZWZhdWx0UHJvcHM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJvd0hlaWdodDogNDUsXG4gICAgICAgICAgICByb3dIZWlnaHRNaW46IDE1LFxuICAgICAgICAgICAgcGxhY2Vob2xkZXJUYWdOYW1lOiBcImRpdlwiXG4gICAgICAgIH07XG4gICAgfSxcbiAgICByZW5kZXJSb3c6IGZ1bmN0aW9uIChlbGVtKSB7XG4gICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KExvZ01lc3NhZ2UsIHtrZXk6IGVsZW0uaWQsIGVudHJ5OiBlbGVtfSk7XG4gICAgfSxcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJvd3MgPSB0aGlzLnJlbmRlclJvd3ModGhpcy5zdGF0ZS5sb2cpO1xuXG4gICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwicHJlXCIsIHtvblNjcm9sbDogdGhpcy5vblNjcm9sbH0sIFxuICAgICAgICAgICAgIHRoaXMuZ2V0UGxhY2Vob2xkZXJUb3AodGhpcy5zdGF0ZS5sb2cubGVuZ3RoKSwgXG4gICAgICAgICAgICByb3dzLCBcbiAgICAgICAgICAgICB0aGlzLmdldFBsYWNlaG9sZGVyQm90dG9tKHRoaXMuc3RhdGUubG9nLmxlbmd0aCkgXG4gICAgICAgICk7XG4gICAgfVxufSk7XG5cbnZhciBUb2dnbGVGaWx0ZXIgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiVG9nZ2xlRmlsdGVyXCIsXG4gICAgdG9nZ2xlOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHJldHVybiB0aGlzLnByb3BzLnRvZ2dsZUxldmVsKHRoaXMucHJvcHMubmFtZSk7XG4gICAgfSxcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNsYXNzTmFtZSA9IFwibGFiZWwgXCI7XG4gICAgICAgIGlmICh0aGlzLnByb3BzLmFjdGl2ZSkge1xuICAgICAgICAgICAgY2xhc3NOYW1lICs9IFwibGFiZWwtcHJpbWFyeVwiO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2xhc3NOYW1lICs9IFwibGFiZWwtZGVmYXVsdFwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiYVwiLCB7XG4gICAgICAgICAgICAgICAgaHJlZjogXCIjXCIsIFxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZTogY2xhc3NOYW1lLCBcbiAgICAgICAgICAgICAgICBvbkNsaWNrOiB0aGlzLnRvZ2dsZX0sIFxuICAgICAgICAgICAgICAgIHRoaXMucHJvcHMubmFtZVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG52YXIgRXZlbnRMb2cgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiRXZlbnRMb2dcIixcbiAgICBnZXRJbml0aWFsU3RhdGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGZpbHRlcjoge1xuICAgICAgICAgICAgICAgIFwiZGVidWdcIjogZmFsc2UsXG4gICAgICAgICAgICAgICAgXCJpbmZvXCI6IHRydWUsXG4gICAgICAgICAgICAgICAgXCJ3ZWJcIjogdHJ1ZVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH0sXG4gICAgY2xvc2U6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGQgPSB7fTtcbiAgICAgICAgZFtRdWVyeS5TSE9XX0VWRU5UTE9HXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5zZXRRdWVyeShkKTtcbiAgICB9LFxuICAgIHRvZ2dsZUxldmVsOiBmdW5jdGlvbiAobGV2ZWwpIHtcbiAgICAgICAgdmFyIGZpbHRlciA9IF8uZXh0ZW5kKHt9LCB0aGlzLnN0YXRlLmZpbHRlcik7XG4gICAgICAgIGZpbHRlcltsZXZlbF0gPSAhZmlsdGVyW2xldmVsXTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7ZmlsdGVyOiBmaWx0ZXJ9KTtcbiAgICB9LFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBcImV2ZW50bG9nXCJ9LCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIG51bGwsIFxuICAgICAgICAgICAgICAgICAgICBcIkV2ZW50bG9nXCIsIFxuICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtjbGFzc05hbWU6IFwicHVsbC1yaWdodFwifSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFRvZ2dsZUZpbHRlciwge25hbWU6IFwiZGVidWdcIiwgYWN0aXZlOiB0aGlzLnN0YXRlLmZpbHRlci5kZWJ1ZywgdG9nZ2xlTGV2ZWw6IHRoaXMudG9nZ2xlTGV2ZWx9KSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFRvZ2dsZUZpbHRlciwge25hbWU6IFwiaW5mb1wiLCBhY3RpdmU6IHRoaXMuc3RhdGUuZmlsdGVyLmluZm8sIHRvZ2dsZUxldmVsOiB0aGlzLnRvZ2dsZUxldmVsfSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChUb2dnbGVGaWx0ZXIsIHtuYW1lOiBcIndlYlwiLCBhY3RpdmU6IHRoaXMuc3RhdGUuZmlsdGVyLndlYiwgdG9nZ2xlTGV2ZWw6IHRoaXMudG9nZ2xlTGV2ZWx9KSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaVwiLCB7b25DbGljazogdGhpcy5jbG9zZSwgY2xhc3NOYW1lOiBcImZhIGZhLWNsb3NlXCJ9KVxuICAgICAgICAgICAgICAgICAgICApXG5cbiAgICAgICAgICAgICAgICApLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KEV2ZW50TG9nQ29udGVudHMsIHtmaWx0ZXI6IHRoaXMuc3RhdGUuZmlsdGVyLCBldmVudFN0b3JlOiB0aGlzLnByb3BzLmV2ZW50U3RvcmV9KVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50TG9nOyIsInZhciBSZWFjdCA9IHJlcXVpcmUoXCJyZWFjdFwiKTtcbnZhciBfID0gcmVxdWlyZShcImxvZGFzaFwiKTtcblxudmFyIHV0aWxzID0gcmVxdWlyZShcIi4vdXRpbHMuanNcIik7XG52YXIgYWN0aW9ucyA9IHJlcXVpcmUoXCIuLi9hY3Rpb25zLmpzXCIpO1xudmFyIGZsb3d1dGlscyA9IHJlcXVpcmUoXCIuLi9mbG93L3V0aWxzLmpzXCIpO1xudmFyIHRvcHV0aWxzID0gcmVxdWlyZShcIi4uL3V0aWxzLmpzXCIpO1xuXG52YXIgTmF2QWN0aW9uID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIk5hdkFjdGlvblwiLFxuICAgIG9uQ2xpY2s6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdGhpcy5wcm9wcy5vbkNsaWNrKCk7XG4gICAgfSxcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJhXCIsIHt0aXRsZTogdGhpcy5wcm9wcy50aXRsZSwgXG4gICAgICAgICAgICAgICAgaHJlZjogXCIjXCIsIFxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZTogXCJuYXYtYWN0aW9uXCIsIFxuICAgICAgICAgICAgICAgIG9uQ2xpY2s6IHRoaXMub25DbGlja30sIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJpXCIsIHtjbGFzc05hbWU6IFwiZmEgZmEtZncgXCIgKyB0aGlzLnByb3BzLmljb259KVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG52YXIgRmxvd0RldGFpbE5hdiA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJGbG93RGV0YWlsTmF2XCIsXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBmbG93ID0gdGhpcy5wcm9wcy5mbG93O1xuXG4gICAgICAgIHZhciB0YWJzID0gdGhpcy5wcm9wcy50YWJzLm1hcChmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgdmFyIHN0ciA9IGUuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBlLnNsaWNlKDEpO1xuICAgICAgICAgICAgdmFyIGNsYXNzTmFtZSA9IHRoaXMucHJvcHMuYWN0aXZlID09PSBlID8gXCJhY3RpdmVcIiA6IFwiXCI7XG4gICAgICAgICAgICB2YXIgb25DbGljayA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcHMuc2VsZWN0VGFiKGUpO1xuICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICB9LmJpbmQodGhpcyk7XG4gICAgICAgICAgICByZXR1cm4gUmVhY3QuY3JlYXRlRWxlbWVudChcImFcIiwge2tleTogZSwgXG4gICAgICAgICAgICAgICAgaHJlZjogXCIjXCIsIFxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZTogY2xhc3NOYW1lLCBcbiAgICAgICAgICAgICAgICBvbkNsaWNrOiBvbkNsaWNrfSwgc3RyKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcblxuICAgICAgICB2YXIgYWNjZXB0QnV0dG9uID0gbnVsbDtcbiAgICAgICAgaWYoZmxvdy5pbnRlcmNlcHRlZCl7XG4gICAgICAgICAgICBhY2NlcHRCdXR0b24gPSBSZWFjdC5jcmVhdGVFbGVtZW50KE5hdkFjdGlvbiwge3RpdGxlOiBcIlthXWNjZXB0IGludGVyY2VwdGVkIGZsb3dcIiwgaWNvbjogXCJmYS1wbGF5XCIsIG9uQ2xpY2s6IGFjdGlvbnMuRmxvd0FjdGlvbnMuYWNjZXB0LmJpbmQobnVsbCwgZmxvdyl9KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmV2ZXJ0QnV0dG9uID0gbnVsbDtcbiAgICAgICAgaWYoZmxvdy5tb2RpZmllZCl7XG4gICAgICAgICAgICByZXZlcnRCdXR0b24gPSBSZWFjdC5jcmVhdGVFbGVtZW50KE5hdkFjdGlvbiwge3RpdGxlOiBcInJldmVydCBjaGFuZ2VzIHRvIGZsb3cgW1ZdXCIsIGljb246IFwiZmEtaGlzdG9yeVwiLCBvbkNsaWNrOiBhY3Rpb25zLkZsb3dBY3Rpb25zLnJldmVydC5iaW5kKG51bGwsIGZsb3cpfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcIm5hdlwiLCB7cmVmOiBcImhlYWRcIiwgY2xhc3NOYW1lOiBcIm5hdi10YWJzIG5hdi10YWJzLXNtXCJ9LCBcbiAgICAgICAgICAgICAgICB0YWJzLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KE5hdkFjdGlvbiwge3RpdGxlOiBcIltkXWVsZXRlIGZsb3dcIiwgaWNvbjogXCJmYS10cmFzaFwiLCBvbkNsaWNrOiBhY3Rpb25zLkZsb3dBY3Rpb25zLmRlbGV0ZS5iaW5kKG51bGwsIGZsb3cpfSksIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoTmF2QWN0aW9uLCB7dGl0bGU6IFwiW0RddXBsaWNhdGUgZmxvd1wiLCBpY29uOiBcImZhLWNvcHlcIiwgb25DbGljazogYWN0aW9ucy5GbG93QWN0aW9ucy5kdXBsaWNhdGUuYmluZChudWxsLCBmbG93KX0pLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KE5hdkFjdGlvbiwge2Rpc2FibGVkOiB0cnVlLCB0aXRsZTogXCJbcl1lcGxheSBmbG93XCIsIGljb246IFwiZmEtcmVwZWF0XCIsIG9uQ2xpY2s6IGFjdGlvbnMuRmxvd0FjdGlvbnMucmVwbGF5LmJpbmQobnVsbCwgZmxvdyl9KSwgXG4gICAgICAgICAgICAgICAgYWNjZXB0QnV0dG9uLCBcbiAgICAgICAgICAgICAgICByZXZlcnRCdXR0b25cbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxudmFyIEhlYWRlcnMgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiSGVhZGVyc1wiLFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcm93cyA9IHRoaXMucHJvcHMubWVzc2FnZS5oZWFkZXJzLm1hcChmdW5jdGlvbiAoaGVhZGVyLCBpKSB7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0clwiLCB7a2V5OiBpfSwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0ZFwiLCB7Y2xhc3NOYW1lOiBcImhlYWRlci1uYW1lXCJ9LCBoZWFkZXJbMF0gKyBcIjpcIiksIFxuICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGRcIiwge2NsYXNzTmFtZTogXCJoZWFkZXItdmFsdWVcIn0sIGhlYWRlclsxXSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0YWJsZVwiLCB7Y2xhc3NOYW1lOiBcImhlYWRlci10YWJsZVwifSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInRib2R5XCIsIG51bGwsIFxuICAgICAgICAgICAgICAgICAgICByb3dzXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG52YXIgRmxvd0RldGFpbFJlcXVlc3QgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiRmxvd0RldGFpbFJlcXVlc3RcIixcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGZsb3cgPSB0aGlzLnByb3BzLmZsb3c7XG4gICAgICAgIHZhciBmaXJzdF9saW5lID0gW1xuICAgICAgICAgICAgZmxvdy5yZXF1ZXN0Lm1ldGhvZCxcbiAgICAgICAgICAgIGZsb3d1dGlscy5SZXF1ZXN0VXRpbHMucHJldHR5X3VybChmbG93LnJlcXVlc3QpLFxuICAgICAgICAgICAgXCJIVFRQL1wiICsgZmxvdy5yZXF1ZXN0Lmh0dHB2ZXJzaW9uLmpvaW4oXCIuXCIpXG4gICAgICAgIF0uam9pbihcIiBcIik7XG4gICAgICAgIHZhciBjb250ZW50ID0gbnVsbDtcbiAgICAgICAgaWYgKGZsb3cucmVxdWVzdC5jb250ZW50TGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29udGVudCA9IFwiUmVxdWVzdCBDb250ZW50IFNpemU6IFwiICsgdG9wdXRpbHMuZm9ybWF0U2l6ZShmbG93LnJlcXVlc3QuY29udGVudExlbmd0aCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb250ZW50ID0gUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBcImFsZXJ0IGFsZXJ0LWluZm9cIn0sIFwiTm8gQ29udGVudFwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vVE9ETzogU3R5bGluZ1xuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwic2VjdGlvblwiLCBudWxsLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtjbGFzc05hbWU6IFwiZmlyc3QtbGluZVwifSwgZmlyc3RfbGluZSApLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KEhlYWRlcnMsIHttZXNzYWdlOiBmbG93LnJlcXVlc3R9KSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImhyXCIsIG51bGwpLCBcbiAgICAgICAgICAgICAgICBjb250ZW50XG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxufSk7XG5cbnZhciBGbG93RGV0YWlsUmVzcG9uc2UgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiRmxvd0RldGFpbFJlc3BvbnNlXCIsXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBmbG93ID0gdGhpcy5wcm9wcy5mbG93O1xuICAgICAgICB2YXIgZmlyc3RfbGluZSA9IFtcbiAgICAgICAgICAgIFwiSFRUUC9cIiArIGZsb3cucmVzcG9uc2UuaHR0cHZlcnNpb24uam9pbihcIi5cIiksXG4gICAgICAgICAgICBmbG93LnJlc3BvbnNlLmNvZGUsXG4gICAgICAgICAgICBmbG93LnJlc3BvbnNlLm1zZ1xuICAgICAgICBdLmpvaW4oXCIgXCIpO1xuICAgICAgICB2YXIgY29udGVudCA9IG51bGw7XG4gICAgICAgIGlmIChmbG93LnJlc3BvbnNlLmNvbnRlbnRMZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjb250ZW50ID0gXCJSZXNwb25zZSBDb250ZW50IFNpemU6IFwiICsgdG9wdXRpbHMuZm9ybWF0U2l6ZShmbG93LnJlc3BvbnNlLmNvbnRlbnRMZW5ndGgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29udGVudCA9IFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwge2NsYXNzTmFtZTogXCJhbGVydCBhbGVydC1pbmZvXCJ9LCBcIk5vIENvbnRlbnRcIik7XG4gICAgICAgIH1cblxuICAgICAgICAvL1RPRE86IFN0eWxpbmdcblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInNlY3Rpb25cIiwgbnVsbCwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBcImZpcnN0LWxpbmVcIn0sIGZpcnN0X2xpbmUgKSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChIZWFkZXJzLCB7bWVzc2FnZTogZmxvdy5yZXNwb25zZX0pLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaHJcIiwgbnVsbCksIFxuICAgICAgICAgICAgICAgIGNvbnRlbnRcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxudmFyIEZsb3dEZXRhaWxFcnJvciA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJGbG93RGV0YWlsRXJyb3JcIixcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGZsb3cgPSB0aGlzLnByb3BzLmZsb3c7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwic2VjdGlvblwiLCBudWxsLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtjbGFzc05hbWU6IFwiYWxlcnQgYWxlcnQtd2FybmluZ1wifSwgXG4gICAgICAgICAgICAgICAgZmxvdy5lcnJvci5tc2csIFxuICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIG51bGwsIFxuICAgICAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInNtYWxsXCIsIG51bGwsICB0b3B1dGlscy5mb3JtYXRUaW1lU3RhbXAoZmxvdy5lcnJvci50aW1lc3RhbXApIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxudmFyIFRpbWVTdGFtcCA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJUaW1lU3RhbXBcIixcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcblxuICAgICAgICBpZiAoIXRoaXMucHJvcHMudCkge1xuICAgICAgICAgICAgLy9zaG91bGQgYmUgcmV0dXJuIG51bGwsIGJ1dCB0aGF0IHRyaWdnZXJzIGEgUmVhY3QgYnVnLlxuICAgICAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0clwiLCBudWxsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0cyA9IHRvcHV0aWxzLmZvcm1hdFRpbWVTdGFtcCh0aGlzLnByb3BzLnQpO1xuXG4gICAgICAgIHZhciBkZWx0YTtcbiAgICAgICAgaWYgKHRoaXMucHJvcHMuZGVsdGFUbykge1xuICAgICAgICAgICAgZGVsdGEgPSB0b3B1dGlscy5mb3JtYXRUaW1lRGVsdGEoMTAwMCAqICh0aGlzLnByb3BzLnQgLSB0aGlzLnByb3BzLmRlbHRhVG8pKTtcbiAgICAgICAgICAgIGRlbHRhID0gUmVhY3QuY3JlYXRlRWxlbWVudChcInNwYW5cIiwge2NsYXNzTmFtZTogXCJ0ZXh0LW11dGVkXCJ9LCBcIihcIiArIGRlbHRhICsgXCIpXCIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGVsdGEgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0clwiLCBudWxsLCBcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0ZFwiLCBudWxsLCB0aGlzLnByb3BzLnRpdGxlICsgXCI6XCIpLCBcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0ZFwiLCBudWxsLCB0cywgXCIgXCIsIGRlbHRhKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG52YXIgQ29ubmVjdGlvbkluZm8gPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiQ29ubmVjdGlvbkluZm9cIixcblxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY29ubiA9IHRoaXMucHJvcHMuY29ubjtcbiAgICAgICAgdmFyIGFkZHJlc3MgPSBjb25uLmFkZHJlc3MuYWRkcmVzcy5qb2luKFwiOlwiKTtcblxuICAgICAgICB2YXIgc25pID0gUmVhY3QuY3JlYXRlRWxlbWVudChcInRyXCIsIHtrZXk6IFwic25pXCJ9KTsgLy9zaG91bGQgYmUgbnVsbCwgYnV0IHRoYXQgdHJpZ2dlcnMgYSBSZWFjdCBidWcuXG4gICAgICAgIGlmIChjb25uLnNuaSkge1xuICAgICAgICAgICAgc25pID0gUmVhY3QuY3JlYXRlRWxlbWVudChcInRyXCIsIHtrZXk6IFwic25pXCJ9LCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGRcIiwgbnVsbCwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJhYmJyXCIsIHt0aXRsZTogXCJUTFMgU2VydmVyIE5hbWUgSW5kaWNhdGlvblwifSwgXCJUTFMgU05JOlwiKVxuICAgICAgICAgICAgICAgICksIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0ZFwiLCBudWxsLCBjb25uLnNuaSlcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0YWJsZVwiLCB7Y2xhc3NOYW1lOiBcImNvbm5lY3Rpb24tdGFibGVcIn0sIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0Ym9keVwiLCBudWxsLCBcbiAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInRyXCIsIHtrZXk6IFwiYWRkcmVzc1wifSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGRcIiwgbnVsbCwgXCJBZGRyZXNzOlwiKSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGRcIiwgbnVsbCwgYWRkcmVzcylcbiAgICAgICAgICAgICAgICAgICAgKSwgXG4gICAgICAgICAgICAgICAgICAgIHNuaVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxudmFyIENlcnRpZmljYXRlSW5mbyA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJDZXJ0aWZpY2F0ZUluZm9cIixcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy9UT0RPOiBXZSBzaG91bGQgZmV0Y2ggaHVtYW4tcmVhZGFibGUgY2VydGlmaWNhdGUgcmVwcmVzZW50YXRpb25cbiAgICAgICAgLy8gZnJvbSB0aGUgc2VydmVyXG4gICAgICAgIHZhciBmbG93ID0gdGhpcy5wcm9wcy5mbG93O1xuICAgICAgICB2YXIgY2xpZW50X2Nvbm4gPSBmbG93LmNsaWVudF9jb25uO1xuICAgICAgICB2YXIgc2VydmVyX2Nvbm4gPSBmbG93LnNlcnZlcl9jb25uO1xuXG4gICAgICAgIHZhciBwcmVTdHlsZSA9IHttYXhIZWlnaHQ6IDEwMH07XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIG51bGwsIFxuICAgICAgICAgICAgY2xpZW50X2Nvbm4uY2VydCA/IFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJoNFwiLCBudWxsLCBcIkNsaWVudCBDZXJ0aWZpY2F0ZVwiKSA6IG51bGwsIFxuICAgICAgICAgICAgY2xpZW50X2Nvbm4uY2VydCA/IFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJwcmVcIiwge3N0eWxlOiBwcmVTdHlsZX0sIGNsaWVudF9jb25uLmNlcnQpIDogbnVsbCwgXG5cbiAgICAgICAgICAgIHNlcnZlcl9jb25uLmNlcnQgPyBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaDRcIiwgbnVsbCwgXCJTZXJ2ZXIgQ2VydGlmaWNhdGVcIikgOiBudWxsLCBcbiAgICAgICAgICAgIHNlcnZlcl9jb25uLmNlcnQgPyBSZWFjdC5jcmVhdGVFbGVtZW50KFwicHJlXCIsIHtzdHlsZTogcHJlU3R5bGV9LCBzZXJ2ZXJfY29ubi5jZXJ0KSA6IG51bGxcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxudmFyIFRpbWluZyA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJUaW1pbmdcIixcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGZsb3cgPSB0aGlzLnByb3BzLmZsb3c7XG4gICAgICAgIHZhciBzYyA9IGZsb3cuc2VydmVyX2Nvbm47XG4gICAgICAgIHZhciBjYyA9IGZsb3cuY2xpZW50X2Nvbm47XG4gICAgICAgIHZhciByZXEgPSBmbG93LnJlcXVlc3Q7XG4gICAgICAgIHZhciByZXNwID0gZmxvdy5yZXNwb25zZTtcblxuICAgICAgICB2YXIgdGltZXN0YW1wcyA9IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0aXRsZTogXCJTZXJ2ZXIgY29ubi4gaW5pdGlhdGVkXCIsXG4gICAgICAgICAgICAgICAgdDogc2MudGltZXN0YW1wX3N0YXJ0LFxuICAgICAgICAgICAgICAgIGRlbHRhVG86IHJlcS50aW1lc3RhbXBfc3RhcnRcbiAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICB0aXRsZTogXCJTZXJ2ZXIgY29ubi4gVENQIGhhbmRzaGFrZVwiLFxuICAgICAgICAgICAgICAgIHQ6IHNjLnRpbWVzdGFtcF90Y3Bfc2V0dXAsXG4gICAgICAgICAgICAgICAgZGVsdGFUbzogcmVxLnRpbWVzdGFtcF9zdGFydFxuICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgIHRpdGxlOiBcIlNlcnZlciBjb25uLiBTU0wgaGFuZHNoYWtlXCIsXG4gICAgICAgICAgICAgICAgdDogc2MudGltZXN0YW1wX3NzbF9zZXR1cCxcbiAgICAgICAgICAgICAgICBkZWx0YVRvOiByZXEudGltZXN0YW1wX3N0YXJ0XG4gICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgdGl0bGU6IFwiQ2xpZW50IGNvbm4uIGVzdGFibGlzaGVkXCIsXG4gICAgICAgICAgICAgICAgdDogY2MudGltZXN0YW1wX3N0YXJ0LFxuICAgICAgICAgICAgICAgIGRlbHRhVG86IHJlcS50aW1lc3RhbXBfc3RhcnRcbiAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICB0aXRsZTogXCJDbGllbnQgY29ubi4gU1NMIGhhbmRzaGFrZVwiLFxuICAgICAgICAgICAgICAgIHQ6IGNjLnRpbWVzdGFtcF9zc2xfc2V0dXAsXG4gICAgICAgICAgICAgICAgZGVsdGFUbzogcmVxLnRpbWVzdGFtcF9zdGFydFxuICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgIHRpdGxlOiBcIkZpcnN0IHJlcXVlc3QgYnl0ZVwiLFxuICAgICAgICAgICAgICAgIHQ6IHJlcS50aW1lc3RhbXBfc3RhcnQsXG4gICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgdGl0bGU6IFwiUmVxdWVzdCBjb21wbGV0ZVwiLFxuICAgICAgICAgICAgICAgIHQ6IHJlcS50aW1lc3RhbXBfZW5kLFxuICAgICAgICAgICAgICAgIGRlbHRhVG86IHJlcS50aW1lc3RhbXBfc3RhcnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgXTtcblxuICAgICAgICBpZiAoZmxvdy5yZXNwb25zZSkge1xuICAgICAgICAgICAgdGltZXN0YW1wcy5wdXNoKFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdGl0bGU6IFwiRmlyc3QgcmVzcG9uc2UgYnl0ZVwiLFxuICAgICAgICAgICAgICAgICAgICB0OiByZXNwLnRpbWVzdGFtcF9zdGFydCxcbiAgICAgICAgICAgICAgICAgICAgZGVsdGFUbzogcmVxLnRpbWVzdGFtcF9zdGFydFxuICAgICAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICAgICAgdGl0bGU6IFwiUmVzcG9uc2UgY29tcGxldGVcIixcbiAgICAgICAgICAgICAgICAgICAgdDogcmVzcC50aW1lc3RhbXBfZW5kLFxuICAgICAgICAgICAgICAgICAgICBkZWx0YVRvOiByZXEudGltZXN0YW1wX3N0YXJ0XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vQWRkIHVuaXF1ZSBrZXkgZm9yIGVhY2ggcm93LlxuICAgICAgICB0aW1lc3RhbXBzLmZvckVhY2goZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGUua2V5ID0gZS50aXRsZTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGltZXN0YW1wcyA9IF8uc29ydEJ5KHRpbWVzdGFtcHMsICd0Jyk7XG5cbiAgICAgICAgdmFyIHJvd3MgPSB0aW1lc3RhbXBzLm1hcChmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoVGltZVN0YW1wLCBSZWFjdC5fX3NwcmVhZCh7fSwgIGUpKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgbnVsbCwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImg0XCIsIG51bGwsIFwiVGltaW5nXCIpLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGFibGVcIiwge2NsYXNzTmFtZTogXCJ0aW1pbmctdGFibGVcIn0sIFxuICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGJvZHlcIiwgbnVsbCwgXG4gICAgICAgICAgICAgICAgICAgIHJvd3NcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxudmFyIEZsb3dEZXRhaWxDb25uZWN0aW9uSW5mbyA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJGbG93RGV0YWlsQ29ubmVjdGlvbkluZm9cIixcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGZsb3cgPSB0aGlzLnByb3BzLmZsb3c7XG4gICAgICAgIHZhciBjbGllbnRfY29ubiA9IGZsb3cuY2xpZW50X2Nvbm47XG4gICAgICAgIHZhciBzZXJ2ZXJfY29ubiA9IGZsb3cuc2VydmVyX2Nvbm47XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwic2VjdGlvblwiLCBudWxsLCBcblxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJoNFwiLCBudWxsLCBcIkNsaWVudCBDb25uZWN0aW9uXCIpLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KENvbm5lY3Rpb25JbmZvLCB7Y29ubjogY2xpZW50X2Nvbm59KSwgXG5cbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaDRcIiwgbnVsbCwgXCJTZXJ2ZXIgQ29ubmVjdGlvblwiKSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChDb25uZWN0aW9uSW5mbywge2Nvbm46IHNlcnZlcl9jb25ufSksIFxuXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChDZXJ0aWZpY2F0ZUluZm8sIHtmbG93OiBmbG93fSksIFxuXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChUaW1pbmcsIHtmbG93OiBmbG93fSlcblxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG52YXIgYWxsVGFicyA9IHtcbiAgICByZXF1ZXN0OiBGbG93RGV0YWlsUmVxdWVzdCxcbiAgICByZXNwb25zZTogRmxvd0RldGFpbFJlc3BvbnNlLFxuICAgIGVycm9yOiBGbG93RGV0YWlsRXJyb3IsXG4gICAgZGV0YWlsczogRmxvd0RldGFpbENvbm5lY3Rpb25JbmZvXG59O1xuXG52YXIgRmxvd0RldGFpbCA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJGbG93RGV0YWlsXCIsXG4gICAgbWl4aW5zOiBbdXRpbHMuU3RpY2t5SGVhZE1peGluLCB1dGlscy5OYXZpZ2F0aW9uLCB1dGlscy5TdGF0ZV0sXG4gICAgZ2V0VGFiczogZnVuY3Rpb24gKGZsb3cpIHtcbiAgICAgICAgdmFyIHRhYnMgPSBbXTtcbiAgICAgICAgW1wicmVxdWVzdFwiLCBcInJlc3BvbnNlXCIsIFwiZXJyb3JcIl0uZm9yRWFjaChmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgaWYgKGZsb3dbZV0pIHtcbiAgICAgICAgICAgICAgICB0YWJzLnB1c2goZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0YWJzLnB1c2goXCJkZXRhaWxzXCIpO1xuICAgICAgICByZXR1cm4gdGFicztcbiAgICB9LFxuICAgIG5leHRUYWI6IGZ1bmN0aW9uIChpKSB7XG4gICAgICAgIHZhciB0YWJzID0gdGhpcy5nZXRUYWJzKHRoaXMucHJvcHMuZmxvdyk7XG4gICAgICAgIHZhciBjdXJyZW50SW5kZXggPSB0YWJzLmluZGV4T2YodGhpcy5nZXRQYXJhbXMoKS5kZXRhaWxUYWIpO1xuICAgICAgICAvLyBKUyBtb2R1bG8gb3BlcmF0b3IgZG9lc24ndCBjb3JyZWN0IG5lZ2F0aXZlIG51bWJlcnMsIG1ha2Ugc3VyZSB0aGF0IHdlIGFyZSBwb3NpdGl2ZS5cbiAgICAgICAgdmFyIG5leHRJbmRleCA9IChjdXJyZW50SW5kZXggKyBpICsgdGFicy5sZW5ndGgpICUgdGFicy5sZW5ndGg7XG4gICAgICAgIHRoaXMuc2VsZWN0VGFiKHRhYnNbbmV4dEluZGV4XSk7XG4gICAgfSxcbiAgICBzZWxlY3RUYWI6IGZ1bmN0aW9uIChwYW5lbCkge1xuICAgICAgICB0aGlzLnJlcGxhY2VXaXRoKFxuICAgICAgICAgICAgXCJmbG93XCIsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgZmxvd0lkOiB0aGlzLmdldFBhcmFtcygpLmZsb3dJZCxcbiAgICAgICAgICAgICAgICBkZXRhaWxUYWI6IHBhbmVsXG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgfSxcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGZsb3cgPSB0aGlzLnByb3BzLmZsb3c7XG4gICAgICAgIHZhciB0YWJzID0gdGhpcy5nZXRUYWJzKGZsb3cpO1xuICAgICAgICB2YXIgYWN0aXZlID0gdGhpcy5nZXRQYXJhbXMoKS5kZXRhaWxUYWI7XG5cbiAgICAgICAgaWYgKCFfLmNvbnRhaW5zKHRhYnMsIGFjdGl2ZSkpIHtcbiAgICAgICAgICAgIGlmIChhY3RpdmUgPT09IFwicmVzcG9uc2VcIiAmJiBmbG93LmVycm9yKSB7XG4gICAgICAgICAgICAgICAgYWN0aXZlID0gXCJlcnJvclwiO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChhY3RpdmUgPT09IFwiZXJyb3JcIiAmJiBmbG93LnJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgYWN0aXZlID0gXCJyZXNwb25zZVwiO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhY3RpdmUgPSB0YWJzWzBdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zZWxlY3RUYWIoYWN0aXZlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBUYWIgPSBhbGxUYWJzW2FjdGl2ZV07XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtjbGFzc05hbWU6IFwiZmxvdy1kZXRhaWxcIiwgb25TY3JvbGw6IHRoaXMuYWRqdXN0SGVhZH0sIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoRmxvd0RldGFpbE5hdiwge3JlZjogXCJoZWFkXCIsIFxuICAgICAgICAgICAgICAgICAgICBmbG93OiBmbG93LCBcbiAgICAgICAgICAgICAgICAgICAgdGFiczogdGFicywgXG4gICAgICAgICAgICAgICAgICAgIGFjdGl2ZTogYWN0aXZlLCBcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0VGFiOiB0aGlzLnNlbGVjdFRhYn0pLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFRhYiwge2Zsb3c6IGZsb3d9KVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBGbG93RGV0YWlsOiBGbG93RGV0YWlsXG59OyIsInZhciBSZWFjdCA9IHJlcXVpcmUoXCJyZWFjdFwiKTtcbnZhciBmbG93dXRpbHMgPSByZXF1aXJlKFwiLi4vZmxvdy91dGlscy5qc1wiKTtcbnZhciB1dGlscyA9IHJlcXVpcmUoXCIuLi91dGlscy5qc1wiKTtcblxudmFyIFRMU0NvbHVtbiA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJUTFNDb2x1bW5cIixcbiAgICBzdGF0aWNzOiB7XG4gICAgICAgIHJlbmRlclRpdGxlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gUmVhY3QuY3JlYXRlRWxlbWVudChcInRoXCIsIHtrZXk6IFwidGxzXCIsIGNsYXNzTmFtZTogXCJjb2wtdGxzXCJ9KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBmbG93ID0gdGhpcy5wcm9wcy5mbG93O1xuICAgICAgICB2YXIgc3NsID0gKGZsb3cucmVxdWVzdC5zY2hlbWUgPT0gXCJodHRwc1wiKTtcbiAgICAgICAgdmFyIGNsYXNzZXM7XG4gICAgICAgIGlmIChzc2wpIHtcbiAgICAgICAgICAgIGNsYXNzZXMgPSBcImNvbC10bHMgY29sLXRscy1odHRwc1wiO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2xhc3NlcyA9IFwiY29sLXRscyBjb2wtdGxzLWh0dHBcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUmVhY3QuY3JlYXRlRWxlbWVudChcInRkXCIsIHtjbGFzc05hbWU6IGNsYXNzZXN9KTtcbiAgICB9XG59KTtcblxuXG52YXIgSWNvbkNvbHVtbiA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJJY29uQ29sdW1uXCIsXG4gICAgc3RhdGljczoge1xuICAgICAgICByZW5kZXJUaXRsZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0aFwiLCB7a2V5OiBcImljb25cIiwgY2xhc3NOYW1lOiBcImNvbC1pY29uXCJ9KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBmbG93ID0gdGhpcy5wcm9wcy5mbG93O1xuXG4gICAgICAgIHZhciBpY29uO1xuICAgICAgICBpZiAoZmxvdy5yZXNwb25zZSkge1xuICAgICAgICAgICAgdmFyIGNvbnRlbnRUeXBlID0gZmxvd3V0aWxzLlJlc3BvbnNlVXRpbHMuZ2V0Q29udGVudFR5cGUoZmxvdy5yZXNwb25zZSk7XG5cbiAgICAgICAgICAgIC8vVE9ETzogV2Ugc2hvdWxkIGFzc2lnbiBhIHR5cGUgdG8gdGhlIGZsb3cgc29tZXdoZXJlIGVsc2UuXG4gICAgICAgICAgICBpZiAoZmxvdy5yZXNwb25zZS5jb2RlID09IDMwNCkge1xuICAgICAgICAgICAgICAgIGljb24gPSBcInJlc291cmNlLWljb24tbm90LW1vZGlmaWVkXCI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKDMwMCA8PSBmbG93LnJlc3BvbnNlLmNvZGUgJiYgZmxvdy5yZXNwb25zZS5jb2RlIDwgNDAwKSB7XG4gICAgICAgICAgICAgICAgaWNvbiA9IFwicmVzb3VyY2UtaWNvbi1yZWRpcmVjdFwiO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChjb250ZW50VHlwZSAmJiBjb250ZW50VHlwZS5pbmRleE9mKFwiaW1hZ2VcIikgPj0gMCkge1xuICAgICAgICAgICAgICAgIGljb24gPSBcInJlc291cmNlLWljb24taW1hZ2VcIjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY29udGVudFR5cGUgJiYgY29udGVudFR5cGUuaW5kZXhPZihcImphdmFzY3JpcHRcIikgPj0gMCkge1xuICAgICAgICAgICAgICAgIGljb24gPSBcInJlc291cmNlLWljb24tanNcIjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY29udGVudFR5cGUgJiYgY29udGVudFR5cGUuaW5kZXhPZihcImNzc1wiKSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgaWNvbiA9IFwicmVzb3VyY2UtaWNvbi1jc3NcIjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY29udGVudFR5cGUgJiYgY29udGVudFR5cGUuaW5kZXhPZihcImh0bWxcIikgPj0gMCkge1xuICAgICAgICAgICAgICAgIGljb24gPSBcInJlc291cmNlLWljb24tZG9jdW1lbnRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIWljb24pIHtcbiAgICAgICAgICAgIGljb24gPSBcInJlc291cmNlLWljb24tcGxhaW5cIjtcbiAgICAgICAgfVxuXG5cbiAgICAgICAgaWNvbiArPSBcIiByZXNvdXJjZS1pY29uXCI7XG4gICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGRcIiwge2NsYXNzTmFtZTogXCJjb2wtaWNvblwifSwgXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtjbGFzc05hbWU6IGljb259KVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG52YXIgUGF0aENvbHVtbiA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJQYXRoQ29sdW1uXCIsXG4gICAgc3RhdGljczoge1xuICAgICAgICByZW5kZXJUaXRsZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0aFwiLCB7a2V5OiBcInBhdGhcIiwgY2xhc3NOYW1lOiBcImNvbC1wYXRoXCJ9LCBcIlBhdGhcIik7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZmxvdyA9IHRoaXMucHJvcHMuZmxvdztcbiAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0ZFwiLCB7Y2xhc3NOYW1lOiBcImNvbC1wYXRoXCJ9LCBcbiAgICAgICAgICAgIGZsb3cucmVxdWVzdC5pc19yZXBsYXkgPyBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaVwiLCB7Y2xhc3NOYW1lOiBcImZhIGZhLWZ3IGZhLXJlcGVhdCBwdWxsLXJpZ2h0XCJ9KSA6IG51bGwsIFxuICAgICAgICAgICAgZmxvdy5pbnRlcmNlcHRlZCA/IFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJpXCIsIHtjbGFzc05hbWU6IFwiZmEgZmEtZncgZmEtcGF1c2UgcHVsbC1yaWdodFwifSkgOiBudWxsLCBcbiAgICAgICAgICAgIGZsb3cucmVxdWVzdC5zY2hlbWUgKyBcIjovL1wiICsgZmxvdy5yZXF1ZXN0Lmhvc3QgKyBmbG93LnJlcXVlc3QucGF0aFxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG5cbnZhciBNZXRob2RDb2x1bW4gPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiTWV0aG9kQ29sdW1uXCIsXG4gICAgc3RhdGljczoge1xuICAgICAgICByZW5kZXJUaXRsZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0aFwiLCB7a2V5OiBcIm1ldGhvZFwiLCBjbGFzc05hbWU6IFwiY29sLW1ldGhvZFwifSwgXCJNZXRob2RcIik7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZmxvdyA9IHRoaXMucHJvcHMuZmxvdztcbiAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0ZFwiLCB7Y2xhc3NOYW1lOiBcImNvbC1tZXRob2RcIn0sIGZsb3cucmVxdWVzdC5tZXRob2QpO1xuICAgIH1cbn0pO1xuXG5cbnZhciBTdGF0dXNDb2x1bW4gPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiU3RhdHVzQ29sdW1uXCIsXG4gICAgc3RhdGljczoge1xuICAgICAgICByZW5kZXJUaXRsZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0aFwiLCB7a2V5OiBcInN0YXR1c1wiLCBjbGFzc05hbWU6IFwiY29sLXN0YXR1c1wifSwgXCJTdGF0dXNcIik7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZmxvdyA9IHRoaXMucHJvcHMuZmxvdztcbiAgICAgICAgdmFyIHN0YXR1cztcbiAgICAgICAgaWYgKGZsb3cucmVzcG9uc2UpIHtcbiAgICAgICAgICAgIHN0YXR1cyA9IGZsb3cucmVzcG9uc2UuY29kZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN0YXR1cyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0ZFwiLCB7Y2xhc3NOYW1lOiBcImNvbC1zdGF0dXNcIn0sIHN0YXR1cyk7XG4gICAgfVxufSk7XG5cblxudmFyIFNpemVDb2x1bW4gPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiU2l6ZUNvbHVtblwiLFxuICAgIHN0YXRpY3M6IHtcbiAgICAgICAgcmVuZGVyVGl0bGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGhcIiwge2tleTogXCJzaXplXCIsIGNsYXNzTmFtZTogXCJjb2wtc2l6ZVwifSwgXCJTaXplXCIpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGZsb3cgPSB0aGlzLnByb3BzLmZsb3c7XG5cbiAgICAgICAgdmFyIHRvdGFsID0gZmxvdy5yZXF1ZXN0LmNvbnRlbnRMZW5ndGg7XG4gICAgICAgIGlmIChmbG93LnJlc3BvbnNlKSB7XG4gICAgICAgICAgICB0b3RhbCArPSBmbG93LnJlc3BvbnNlLmNvbnRlbnRMZW5ndGggfHwgMDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc2l6ZSA9IHV0aWxzLmZvcm1hdFNpemUodG90YWwpO1xuICAgICAgICByZXR1cm4gUmVhY3QuY3JlYXRlRWxlbWVudChcInRkXCIsIHtjbGFzc05hbWU6IFwiY29sLXNpemVcIn0sIHNpemUpO1xuICAgIH1cbn0pO1xuXG5cbnZhciBUaW1lQ29sdW1uID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIlRpbWVDb2x1bW5cIixcbiAgICBzdGF0aWNzOiB7XG4gICAgICAgIHJlbmRlclRpdGxlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gUmVhY3QuY3JlYXRlRWxlbWVudChcInRoXCIsIHtrZXk6IFwidGltZVwiLCBjbGFzc05hbWU6IFwiY29sLXRpbWVcIn0sIFwiVGltZVwiKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBmbG93ID0gdGhpcy5wcm9wcy5mbG93O1xuICAgICAgICB2YXIgdGltZTtcbiAgICAgICAgaWYgKGZsb3cucmVzcG9uc2UpIHtcbiAgICAgICAgICAgIHRpbWUgPSB1dGlscy5mb3JtYXRUaW1lRGVsdGEoMTAwMCAqIChmbG93LnJlc3BvbnNlLnRpbWVzdGFtcF9lbmQgLSBmbG93LnJlcXVlc3QudGltZXN0YW1wX3N0YXJ0KSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aW1lID0gXCIuLi5cIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUmVhY3QuY3JlYXRlRWxlbWVudChcInRkXCIsIHtjbGFzc05hbWU6IFwiY29sLXRpbWVcIn0sIHRpbWUpO1xuICAgIH1cbn0pO1xuXG5cbnZhciBhbGxfY29sdW1ucyA9IFtcbiAgICBUTFNDb2x1bW4sXG4gICAgSWNvbkNvbHVtbixcbiAgICBQYXRoQ29sdW1uLFxuICAgIE1ldGhvZENvbHVtbixcbiAgICBTdGF0dXNDb2x1bW4sXG4gICAgU2l6ZUNvbHVtbixcbiAgICBUaW1lQ29sdW1uXTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGFsbF9jb2x1bW5zO1xuXG5cbiIsInZhciBSZWFjdCA9IHJlcXVpcmUoXCJyZWFjdFwiKTtcbnZhciB1dGlscyA9IHJlcXVpcmUoXCIuL3V0aWxzLmpzXCIpO1xudmFyIFZpcnR1YWxTY3JvbGxNaXhpbiA9IHJlcXVpcmUoXCIuL3ZpcnR1YWxzY3JvbGwuanNcIik7XG52YXIgZmxvd3RhYmxlX2NvbHVtbnMgPSByZXF1aXJlKFwiLi9mbG93dGFibGUtY29sdW1ucy5qc1wiKTtcblxudmFyIEZsb3dSb3cgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiRmxvd1Jvd1wiLFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZmxvdyA9IHRoaXMucHJvcHMuZmxvdztcbiAgICAgICAgdmFyIGNvbHVtbnMgPSB0aGlzLnByb3BzLmNvbHVtbnMubWFwKGZ1bmN0aW9uIChDb2x1bW4pIHtcbiAgICAgICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KENvbHVtbiwge2tleTogQ29sdW1uLmRpc3BsYXlOYW1lLCBmbG93OiBmbG93fSk7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgICAgIHZhciBjbGFzc05hbWUgPSBcIlwiO1xuICAgICAgICBpZiAodGhpcy5wcm9wcy5zZWxlY3RlZCkge1xuICAgICAgICAgICAgY2xhc3NOYW1lICs9IFwiIHNlbGVjdGVkXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMucHJvcHMuaGlnaGxpZ2h0ZWQpIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcIiBoaWdobGlnaHRlZFwiO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmbG93LmludGVyY2VwdGVkKSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgKz0gXCIgaW50ZXJjZXB0ZWRcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZmxvdy5yZXF1ZXN0KSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgKz0gXCIgaGFzLXJlcXVlc3RcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZmxvdy5yZXNwb25zZSkge1xuICAgICAgICAgICAgY2xhc3NOYW1lICs9IFwiIGhhcy1yZXNwb25zZVwiO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0clwiLCB7Y2xhc3NOYW1lOiBjbGFzc05hbWUsIG9uQ2xpY2s6IHRoaXMucHJvcHMuc2VsZWN0Rmxvdy5iaW5kKG51bGwsIGZsb3cpfSwgXG4gICAgICAgICAgICAgICAgY29sdW1uc1xuICAgICAgICAgICAgKSk7XG4gICAgfSxcbiAgICBzaG91bGRDb21wb25lbnRVcGRhdGU6IGZ1bmN0aW9uIChuZXh0UHJvcHMpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIC8vIEZ1cnRoZXIgb3B0aW1pemF0aW9uIGNvdWxkIGJlIGRvbmUgaGVyZVxuICAgICAgICAvLyBieSBjYWxsaW5nIGZvcmNlVXBkYXRlIG9uIGZsb3cgdXBkYXRlcywgc2VsZWN0aW9uIGNoYW5nZXMgYW5kIGNvbHVtbiBjaGFuZ2VzLlxuICAgICAgICAvL3JldHVybiAoXG4gICAgICAgIC8vKHRoaXMucHJvcHMuY29sdW1ucy5sZW5ndGggIT09IG5leHRQcm9wcy5jb2x1bW5zLmxlbmd0aCkgfHxcbiAgICAgICAgLy8odGhpcy5wcm9wcy5zZWxlY3RlZCAhPT0gbmV4dFByb3BzLnNlbGVjdGVkKVxuICAgICAgICAvLyk7XG4gICAgfVxufSk7XG5cbnZhciBGbG93VGFibGVIZWFkID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIkZsb3dUYWJsZUhlYWRcIixcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNvbHVtbnMgPSB0aGlzLnByb3BzLmNvbHVtbnMubWFwKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgIHJldHVybiBjb2x1bW4ucmVuZGVyVGl0bGUoKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0aGVhZFwiLCBudWxsLCBcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0clwiLCBudWxsLCBjb2x1bW5zKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG5cbnZhciBST1dfSEVJR0hUID0gMzI7XG5cbnZhciBGbG93VGFibGUgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiRmxvd1RhYmxlXCIsXG4gICAgbWl4aW5zOiBbdXRpbHMuU3RpY2t5SGVhZE1peGluLCB1dGlscy5BdXRvU2Nyb2xsTWl4aW4sIFZpcnR1YWxTY3JvbGxNaXhpbl0sXG4gICAgZ2V0SW5pdGlhbFN0YXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjb2x1bW5zOiBmbG93dGFibGVfY29sdW1uc1xuICAgICAgICB9O1xuICAgIH0sXG4gICAgY29tcG9uZW50V2lsbE1vdW50OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnByb3BzLnZpZXcpIHtcbiAgICAgICAgICAgIHRoaXMucHJvcHMudmlldy5hZGRMaXN0ZW5lcihcImFkZCB1cGRhdGUgcmVtb3ZlIHJlY2FsY3VsYXRlXCIsIHRoaXMub25DaGFuZ2UpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjb21wb25lbnRXaWxsUmVjZWl2ZVByb3BzOiBmdW5jdGlvbiAobmV4dFByb3BzKSB7XG4gICAgICAgIGlmIChuZXh0UHJvcHMudmlldyAhPT0gdGhpcy5wcm9wcy52aWV3KSB7XG4gICAgICAgICAgICBpZiAodGhpcy5wcm9wcy52aWV3KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wcy52aWV3LnJlbW92ZUxpc3RlbmVyKFwiYWRkIHVwZGF0ZSByZW1vdmUgcmVjYWxjdWxhdGVcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBuZXh0UHJvcHMudmlldy5hZGRMaXN0ZW5lcihcImFkZCB1cGRhdGUgcmVtb3ZlIHJlY2FsY3VsYXRlXCIsIHRoaXMub25DaGFuZ2UpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBnZXREZWZhdWx0UHJvcHM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJvd0hlaWdodDogUk9XX0hFSUdIVFxuICAgICAgICB9O1xuICAgIH0sXG4gICAgb25TY3JvbGxGbG93VGFibGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5hZGp1c3RIZWFkKCk7XG4gICAgICAgIHRoaXMub25TY3JvbGwoKTtcbiAgICB9LFxuICAgIG9uQ2hhbmdlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZm9yY2VVcGRhdGUoKTtcbiAgICB9LFxuICAgIHNjcm9sbEludG9WaWV3OiBmdW5jdGlvbiAoZmxvdykge1xuICAgICAgICB0aGlzLnNjcm9sbFJvd0ludG9WaWV3KFxuICAgICAgICAgICAgdGhpcy5wcm9wcy52aWV3LmluZGV4KGZsb3cpLFxuICAgICAgICAgICAgdGhpcy5yZWZzLmJvZHkuZ2V0RE9NTm9kZSgpLm9mZnNldFRvcFxuICAgICAgICApO1xuICAgIH0sXG4gICAgcmVuZGVyUm93OiBmdW5jdGlvbiAoZmxvdykge1xuICAgICAgICB2YXIgc2VsZWN0ZWQgPSAoZmxvdyA9PT0gdGhpcy5wcm9wcy5zZWxlY3RlZCk7XG4gICAgICAgIHZhciBoaWdobGlnaHRlZCA9XG4gICAgICAgICAgICAoXG4gICAgICAgICAgICB0aGlzLnByb3BzLnZpZXcuX2hpZ2hsaWdodCAmJlxuICAgICAgICAgICAgdGhpcy5wcm9wcy52aWV3Ll9oaWdobGlnaHRbZmxvdy5pZF1cbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoRmxvd1Jvdywge2tleTogZmxvdy5pZCwgXG4gICAgICAgICAgICByZWY6IGZsb3cuaWQsIFxuICAgICAgICAgICAgZmxvdzogZmxvdywgXG4gICAgICAgICAgICBjb2x1bW5zOiB0aGlzLnN0YXRlLmNvbHVtbnMsIFxuICAgICAgICAgICAgc2VsZWN0ZWQ6IHNlbGVjdGVkLCBcbiAgICAgICAgICAgIGhpZ2hsaWdodGVkOiBoaWdobGlnaHRlZCwgXG4gICAgICAgICAgICBzZWxlY3RGbG93OiB0aGlzLnByb3BzLnNlbGVjdEZsb3d9XG4gICAgICAgICk7XG4gICAgfSxcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy9jb25zb2xlLmxvZyhcInJlbmRlciBmbG93dGFibGVcIiwgdGhpcy5zdGF0ZS5zdGFydCwgdGhpcy5zdGF0ZS5zdG9wLCB0aGlzLnByb3BzLnNlbGVjdGVkKTtcbiAgICAgICAgdmFyIGZsb3dzID0gdGhpcy5wcm9wcy52aWV3ID8gdGhpcy5wcm9wcy52aWV3Lmxpc3QgOiBbXTtcblxuICAgICAgICB2YXIgcm93cyA9IHRoaXMucmVuZGVyUm93cyhmbG93cyk7XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwge2NsYXNzTmFtZTogXCJmbG93LXRhYmxlXCIsIG9uU2Nyb2xsOiB0aGlzLm9uU2Nyb2xsRmxvd1RhYmxlfSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInRhYmxlXCIsIG51bGwsIFxuICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KEZsb3dUYWJsZUhlYWQsIHtyZWY6IFwiaGVhZFwiLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbnM6IHRoaXMuc3RhdGUuY29sdW1uc30pLCBcbiAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInRib2R5XCIsIHtyZWY6IFwiYm9keVwifSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5nZXRQbGFjZWhvbGRlclRvcChmbG93cy5sZW5ndGgpLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvd3MsIFxuICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ2V0UGxhY2Vob2xkZXJCb3R0b20oZmxvd3MubGVuZ3RoKSBcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxubW9kdWxlLmV4cG9ydHMgPSBGbG93VGFibGU7XG4iLCJ2YXIgUmVhY3QgPSByZXF1aXJlKFwicmVhY3RcIik7XG5cbnZhciBGb290ZXIgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiRm9vdGVyXCIsXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBtb2RlID0gdGhpcy5wcm9wcy5zZXR0aW5ncy5tb2RlO1xuICAgICAgICB2YXIgaW50ZXJjZXB0ID0gdGhpcy5wcm9wcy5zZXR0aW5ncy5pbnRlcmNlcHQ7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZm9vdGVyXCIsIG51bGwsIFxuICAgICAgICAgICAgICAgIG1vZGUgIT0gXCJyZWd1bGFyXCIgPyBSZWFjdC5jcmVhdGVFbGVtZW50KFwic3BhblwiLCB7Y2xhc3NOYW1lOiBcImxhYmVsIGxhYmVsLXN1Y2Nlc3NcIn0sIG1vZGUsIFwiIG1vZGVcIikgOiBudWxsLCBcbiAgICAgICAgICAgICAgICBcIsKgXCIsIFxuICAgICAgICAgICAgICAgIGludGVyY2VwdCA/IFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIsIHtjbGFzc05hbWU6IFwibGFiZWwgbGFiZWwtc3VjY2Vzc1wifSwgXCJJbnRlcmNlcHQ6IFwiLCBpbnRlcmNlcHQpIDogbnVsbFxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEZvb3RlcjsiLCJ2YXIgUmVhY3QgPSByZXF1aXJlKFwicmVhY3RcIik7XG52YXIgJCA9IHJlcXVpcmUoXCJqcXVlcnlcIik7XG5cbnZhciB1dGlscyA9IHJlcXVpcmUoXCIuL3V0aWxzLmpzXCIpO1xuXG52YXIgRmlsdGVyRG9jcyA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJGaWx0ZXJEb2NzXCIsXG4gICAgc3RhdGljczoge1xuICAgICAgICB4aHI6IGZhbHNlLFxuICAgICAgICBkb2M6IGZhbHNlXG4gICAgfSxcbiAgICBjb21wb25lbnRXaWxsTW91bnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCFGaWx0ZXJEb2NzLmRvYykge1xuICAgICAgICAgICAgRmlsdGVyRG9jcy54aHIgPSAkLmdldEpTT04oXCIvZmlsdGVyLWhlbHBcIikuZG9uZShmdW5jdGlvbiAoZG9jKSB7XG4gICAgICAgICAgICAgICAgRmlsdGVyRG9jcy5kb2MgPSBkb2M7XG4gICAgICAgICAgICAgICAgRmlsdGVyRG9jcy54aHIgPSBmYWxzZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChGaWx0ZXJEb2NzLnhocikge1xuICAgICAgICAgICAgRmlsdGVyRG9jcy54aHIuZG9uZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5mb3JjZVVwZGF0ZSgpO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghRmlsdGVyRG9jcy5kb2MpIHtcbiAgICAgICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaVwiLCB7Y2xhc3NOYW1lOiBcImZhIGZhLXNwaW5uZXIgZmEtc3BpblwifSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgY29tbWFuZHMgPSBGaWx0ZXJEb2NzLmRvYy5jb21tYW5kcy5tYXAoZnVuY3Rpb24gKGMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gUmVhY3QuY3JlYXRlRWxlbWVudChcInRyXCIsIG51bGwsIFxuICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGRcIiwgbnVsbCwgY1swXS5yZXBsYWNlKFwiIFwiLCAnXFx1MDBhMCcpKSwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0ZFwiLCBudWxsLCBjWzFdKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNvbW1hbmRzLnB1c2goUmVhY3QuY3JlYXRlRWxlbWVudChcInRyXCIsIG51bGwsIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0ZFwiLCB7Y29sU3BhbjogXCIyXCJ9LCBcbiAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImFcIiwge2hyZWY6IFwiaHR0cHM6Ly9taXRtcHJveHkub3JnL2RvYy9mZWF0dXJlcy9maWx0ZXJzLmh0bWxcIiwgXG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQ6IFwiX2JsYW5rXCJ9LCBcbiAgICAgICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJpXCIsIHtjbGFzc05hbWU6IFwiZmEgZmEtZXh0ZXJuYWwtbGlua1wifSksIFxuICAgICAgICAgICAgICAgICAgICBcIsKgIG1pdG1wcm94eSBkb2NzXCIpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSk7XG4gICAgICAgICAgICByZXR1cm4gUmVhY3QuY3JlYXRlRWxlbWVudChcInRhYmxlXCIsIHtjbGFzc05hbWU6IFwidGFibGUgdGFibGUtY29uZGVuc2VkXCJ9LCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGJvZHlcIiwgbnVsbCwgY29tbWFuZHMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxufSk7XG52YXIgRmlsdGVySW5wdXQgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiRmlsdGVySW5wdXRcIixcbiAgICBnZXRJbml0aWFsU3RhdGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gQ29uc2lkZXIgYm90aCBmb2N1cyBhbmQgbW91c2VvdmVyIGZvciBzaG93aW5nL2hpZGluZyB0aGUgdG9vbHRpcCxcbiAgICAgICAgLy8gYmVjYXVzZSBvbkJsdXIgb2YgdGhlIGlucHV0IGlzIHRyaWdnZXJlZCBiZWZvcmUgdGhlIGNsaWNrIG9uIHRoZSB0b29sdGlwXG4gICAgICAgIC8vIGZpbmFsaXplZCwgaGlkaW5nIHRoZSB0b29sdGlwIGp1c3QgYXMgdGhlIHVzZXIgY2xpY2tzIG9uIGl0LlxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdmFsdWU6IHRoaXMucHJvcHMudmFsdWUsXG4gICAgICAgICAgICBmb2N1czogZmFsc2UsXG4gICAgICAgICAgICBtb3VzZWZvY3VzOiBmYWxzZVxuICAgICAgICB9O1xuICAgIH0sXG4gICAgY29tcG9uZW50V2lsbFJlY2VpdmVQcm9wczogZnVuY3Rpb24gKG5leHRQcm9wcykge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHt2YWx1ZTogbmV4dFByb3BzLnZhbHVlfSk7XG4gICAgfSxcbiAgICBvbkNoYW5nZTogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIG5leHRWYWx1ZSA9IGUudGFyZ2V0LnZhbHVlO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHZhbHVlOiBuZXh0VmFsdWVcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIE9ubHkgcHJvcGFnYXRlIHZhbGlkIGZpbHRlcnMgdXB3YXJkcy5cbiAgICAgICAgaWYgKHRoaXMuaXNWYWxpZChuZXh0VmFsdWUpKSB7XG4gICAgICAgICAgICB0aGlzLnByb3BzLm9uQ2hhbmdlKG5leHRWYWx1ZSk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGlzVmFsaWQ6IGZ1bmN0aW9uIChmaWx0KSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBGaWx0LnBhcnNlKGZpbHQgfHwgdGhpcy5zdGF0ZS52YWx1ZSk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBnZXREZXNjOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBkZXNjO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgZGVzYyA9IEZpbHQucGFyc2UodGhpcy5zdGF0ZS52YWx1ZSkuZGVzYztcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgZGVzYyA9IFwiXCIgKyBlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkZXNjICE9PSBcInRydWVcIikge1xuICAgICAgICAgICAgcmV0dXJuIGRlc2M7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoRmlsdGVyRG9jcywgbnVsbClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG9uRm9jdXM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7Zm9jdXM6IHRydWV9KTtcbiAgICB9LFxuICAgIG9uQmx1cjogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtmb2N1czogZmFsc2V9KTtcbiAgICB9LFxuICAgIG9uTW91c2VFbnRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHttb3VzZWZvY3VzOiB0cnVlfSk7XG4gICAgfSxcbiAgICBvbk1vdXNlTGVhdmU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7bW91c2Vmb2N1czogZmFsc2V9KTtcbiAgICB9LFxuICAgIG9uS2V5RG93bjogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKGUua2V5Q29kZSA9PT0gS2V5LkVTQyB8fCBlLmtleUNvZGUgPT09IEtleS5FTlRFUikge1xuICAgICAgICAgICAgdGhpcy5ibHVyKCk7XG4gICAgICAgICAgICAvLyBJZiBjbG9zZWQgdXNpbmcgRVNDL0VOVEVSLCBoaWRlIHRoZSB0b29sdGlwLlxuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7bW91c2Vmb2N1czogZmFsc2V9KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgYmx1cjogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJlZnMuaW5wdXQuZ2V0RE9NTm9kZSgpLmJsdXIoKTtcbiAgICB9LFxuICAgIGZvY3VzOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucmVmcy5pbnB1dC5nZXRET01Ob2RlKCkuc2VsZWN0KCk7XG4gICAgfSxcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGlzVmFsaWQgPSB0aGlzLmlzVmFsaWQoKTtcbiAgICAgICAgdmFyIGljb24gPSBcImZhIGZhLWZ3IGZhLVwiICsgdGhpcy5wcm9wcy50eXBlO1xuICAgICAgICB2YXIgZ3JvdXBDbGFzc05hbWUgPSBcImZpbHRlci1pbnB1dCBpbnB1dC1ncm91cFwiICsgKGlzVmFsaWQgPyBcIlwiIDogXCIgaGFzLWVycm9yXCIpO1xuXG4gICAgICAgIHZhciBwb3BvdmVyO1xuICAgICAgICBpZiAodGhpcy5zdGF0ZS5mb2N1cyB8fCB0aGlzLnN0YXRlLm1vdXNlZm9jdXMpIHtcbiAgICAgICAgICAgIHBvcG92ZXIgPSAoXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBcInBvcG92ZXIgYm90dG9tXCIsIG9uTW91c2VFbnRlcjogdGhpcy5vbk1vdXNlRW50ZXIsIG9uTW91c2VMZWF2ZTogdGhpcy5vbk1vdXNlTGVhdmV9LCBcbiAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBcImFycm93XCJ9KSwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwge2NsYXNzTmFtZTogXCJwb3BvdmVyLWNvbnRlbnRcIn0sIFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmdldERlc2MoKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtjbGFzc05hbWU6IGdyb3VwQ2xhc3NOYW1lfSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInNwYW5cIiwge2NsYXNzTmFtZTogXCJpbnB1dC1ncm91cC1hZGRvblwifSwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJpXCIsIHtjbGFzc05hbWU6IGljb24sIHN0eWxlOiB7Y29sb3I6IHRoaXMucHJvcHMuY29sb3J9fSlcbiAgICAgICAgICAgICAgICApLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaW5wdXRcIiwge3R5cGU6IFwidGV4dFwiLCBwbGFjZWhvbGRlcjogdGhpcy5wcm9wcy5wbGFjZWhvbGRlciwgY2xhc3NOYW1lOiBcImZvcm0tY29udHJvbFwiLCBcbiAgICAgICAgICAgICAgICAgICAgcmVmOiBcImlucHV0XCIsIFxuICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZTogdGhpcy5vbkNoYW5nZSwgXG4gICAgICAgICAgICAgICAgICAgIG9uRm9jdXM6IHRoaXMub25Gb2N1cywgXG4gICAgICAgICAgICAgICAgICAgIG9uQmx1cjogdGhpcy5vbkJsdXIsIFxuICAgICAgICAgICAgICAgICAgICBvbktleURvd246IHRoaXMub25LZXlEb3duLCBcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMuc3RhdGUudmFsdWV9KSwgXG4gICAgICAgICAgICAgICAgcG9wb3ZlclxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG52YXIgTWFpbk1lbnUgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiTWFpbk1lbnVcIixcbiAgICBtaXhpbnM6IFt1dGlscy5OYXZpZ2F0aW9uLCB1dGlscy5TdGF0ZV0sXG4gICAgc3RhdGljczoge1xuICAgICAgICB0aXRsZTogXCJTdGFydFwiLFxuICAgICAgICByb3V0ZTogXCJmbG93c1wiXG4gICAgfSxcbiAgICBvbkZpbHRlckNoYW5nZTogZnVuY3Rpb24gKHZhbCkge1xuICAgICAgICB2YXIgZCA9IHt9O1xuICAgICAgICBkW1F1ZXJ5LkZJTFRFUl0gPSB2YWw7XG4gICAgICAgIHRoaXMuc2V0UXVlcnkoZCk7XG4gICAgfSxcbiAgICBvbkhpZ2hsaWdodENoYW5nZTogZnVuY3Rpb24gKHZhbCkge1xuICAgICAgICB2YXIgZCA9IHt9O1xuICAgICAgICBkW1F1ZXJ5LkhJR0hMSUdIVF0gPSB2YWw7XG4gICAgICAgIHRoaXMuc2V0UXVlcnkoZCk7XG4gICAgfSxcbiAgICBvbkludGVyY2VwdENoYW5nZTogZnVuY3Rpb24gKHZhbCkge1xuICAgICAgICBTZXR0aW5nc0FjdGlvbnMudXBkYXRlKHtpbnRlcmNlcHQ6IHZhbH0pO1xuICAgIH0sXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBmaWx0ZXIgPSB0aGlzLmdldFF1ZXJ5KClbUXVlcnkuRklMVEVSXSB8fCBcIlwiO1xuICAgICAgICB2YXIgaGlnaGxpZ2h0ID0gdGhpcy5nZXRRdWVyeSgpW1F1ZXJ5LkhJR0hMSUdIVF0gfHwgXCJcIjtcbiAgICAgICAgdmFyIGludGVyY2VwdCA9IHRoaXMucHJvcHMuc2V0dGluZ3MuaW50ZXJjZXB0IHx8IFwiXCI7XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgbnVsbCwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBcIm1lbnUtcm93XCJ9LCBcbiAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChGaWx0ZXJJbnB1dCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiRmlsdGVyXCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJmaWx0ZXJcIiwgXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2xvcjogXCJibGFja1wiLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBmaWx0ZXIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U6IHRoaXMub25GaWx0ZXJDaGFuZ2V9KSwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoRmlsdGVySW5wdXQsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBcIkhpZ2hsaWdodFwiLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwidGFnXCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I6IFwiaHNsKDQ4LCAxMDAlLCA1MCUpXCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IGhpZ2hsaWdodCwgXG4gICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZTogdGhpcy5vbkhpZ2hsaWdodENoYW5nZX0pLCBcbiAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChGaWx0ZXJJbnB1dCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiSW50ZXJjZXB0XCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJwYXVzZVwiLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yOiBcImhzbCgyMDgsIDU2JSwgNTMlKVwiLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBpbnRlcmNlcHQsIFxuICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U6IHRoaXMub25JbnRlcmNlcHRDaGFuZ2V9KVxuICAgICAgICAgICAgICAgICksIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwge2NsYXNzTmFtZTogXCJjbGVhcmZpeFwifSlcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxuXG52YXIgVmlld01lbnUgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiVmlld01lbnVcIixcbiAgICBzdGF0aWNzOiB7XG4gICAgICAgIHRpdGxlOiBcIlZpZXdcIixcbiAgICAgICAgcm91dGU6IFwiZmxvd3NcIlxuICAgIH0sXG4gICAgbWl4aW5zOiBbdXRpbHMuTmF2aWdhdGlvbiwgdXRpbHMuU3RhdGVdLFxuICAgIHRvZ2dsZUV2ZW50TG9nOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBkID0ge307XG5cbiAgICAgICAgaWYgKHRoaXMuZ2V0UXVlcnkoKVtRdWVyeS5TSE9XX0VWRU5UTE9HXSkge1xuICAgICAgICAgICAgZFtRdWVyeS5TSE9XX0VWRU5UTE9HXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRbUXVlcnkuU0hPV19FVkVOVExPR10gPSBcInRcIjsgLy8gYW55IG5vbi1mYWxzZSB2YWx1ZSB3aWxsIGRvIGl0LCBrZWVwIGl0IHNob3J0XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnNldFF1ZXJ5KGQpO1xuICAgIH0sXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzaG93RXZlbnRMb2cgPSB0aGlzLmdldFF1ZXJ5KClbUXVlcnkuU0hPV19FVkVOVExPR107XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIG51bGwsIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJidXR0b25cIiwge1xuICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU6IFwiYnRuIFwiICsgKHNob3dFdmVudExvZyA/IFwiYnRuLXByaW1hcnlcIiA6IFwiYnRuLWRlZmF1bHRcIiksIFxuICAgICAgICAgICAgICAgICAgICBvbkNsaWNrOiB0aGlzLnRvZ2dsZUV2ZW50TG9nfSwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJpXCIsIHtjbGFzc05hbWU6IFwiZmEgZmEtZGF0YWJhc2VcIn0pLCBcbiAgICAgICAgICAgICAgICBcIsKgU2hvdyBFdmVudGxvZ1wiXG4gICAgICAgICAgICAgICAgKSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInNwYW5cIiwgbnVsbCwgXCIgXCIpXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxufSk7XG5cblxudmFyIFJlcG9ydHNNZW51ID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIlJlcG9ydHNNZW51XCIsXG4gICAgc3RhdGljczoge1xuICAgICAgICB0aXRsZTogXCJWaXN1YWxpemF0aW9uXCIsXG4gICAgICAgIHJvdXRlOiBcInJlcG9ydHNcIlxuICAgIH0sXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIG51bGwsIFwiUmVwb3J0cyBNZW51XCIpO1xuICAgIH1cbn0pO1xuXG52YXIgRmlsZU1lbnUgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiRmlsZU1lbnVcIixcbiAgICBnZXRJbml0aWFsU3RhdGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHNob3dGaWxlTWVudTogZmFsc2VcbiAgICAgICAgfTtcbiAgICB9LFxuICAgIGhhbmRsZUZpbGVDbGljazogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBpZiAoIXRoaXMuc3RhdGUuc2hvd0ZpbGVNZW51KSB7XG4gICAgICAgICAgICB2YXIgY2xvc2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7c2hvd0ZpbGVNZW51OiBmYWxzZX0pO1xuICAgICAgICAgICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBjbG9zZSk7XG4gICAgICAgICAgICB9LmJpbmQodGhpcyk7XG4gICAgICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgY2xvc2UpO1xuXG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgICBzaG93RmlsZU1lbnU6IHRydWVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBoYW5kbGVOZXdDbGljazogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBpZiAoY29uZmlybShcIkRlbGV0ZSBhbGwgZmxvd3M/XCIpKSB7XG4gICAgICAgICAgICBGbG93QWN0aW9ucy5jbGVhcigpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBoYW5kbGVPcGVuQ2xpY2s6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgY29uc29sZS5lcnJvcihcInVuaW1wbGVtZW50ZWQ6IGhhbmRsZU9wZW5DbGlja1wiKTtcbiAgICB9LFxuICAgIGhhbmRsZVNhdmVDbGljazogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBjb25zb2xlLmVycm9yKFwidW5pbXBsZW1lbnRlZDogaGFuZGxlU2F2ZUNsaWNrXCIpO1xuICAgIH0sXG4gICAgaGFuZGxlU2h1dGRvd25DbGljazogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBjb25zb2xlLmVycm9yKFwidW5pbXBsZW1lbnRlZDogaGFuZGxlU2h1dGRvd25DbGlja1wiKTtcbiAgICB9LFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZmlsZU1lbnVDbGFzcyA9IFwiZHJvcGRvd24gcHVsbC1sZWZ0XCIgKyAodGhpcy5zdGF0ZS5zaG93RmlsZU1lbnUgPyBcIiBvcGVuXCIgOiBcIlwiKTtcblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBmaWxlTWVudUNsYXNzfSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImFcIiwge2hyZWY6IFwiI1wiLCBjbGFzc05hbWU6IFwic3BlY2lhbFwiLCBvbkNsaWNrOiB0aGlzLmhhbmRsZUZpbGVDbGlja30sIFwiIEZpbGUgXCIpLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidWxcIiwge2NsYXNzTmFtZTogXCJkcm9wZG93bi1tZW51XCIsIHJvbGU6IFwibWVudVwifSwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJsaVwiLCBudWxsLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJhXCIsIHtocmVmOiBcIiNcIiwgb25DbGljazogdGhpcy5oYW5kbGVOZXdDbGlja30sIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJpXCIsIHtjbGFzc05hbWU6IFwiZmEgZmEtZncgZmEtZmlsZVwifSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiTmV3XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKSwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJsaVwiLCB7cm9sZTogXCJwcmVzZW50YXRpb25cIiwgY2xhc3NOYW1lOiBcImRpdmlkZXJcIn0pLCBcbiAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImxpXCIsIG51bGwsIFxuICAgICAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImFcIiwge2hyZWY6IFwiaHR0cDovL21pdG0uaXQvXCIsIHRhcmdldDogXCJfYmxhbmtcIn0sIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJpXCIsIHtjbGFzc05hbWU6IFwiZmEgZmEtZncgZmEtZXh0ZXJuYWwtbGlua1wifSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiSW5zdGFsbCBDZXJ0aWZpY2F0ZXMuLi5cIlxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAgICAgPGxpPlxuICAgICAgICAgICAgICAgICA8YSBocmVmPVwiI1wiIG9uQ2xpY2s9e3RoaXMuaGFuZGxlT3BlbkNsaWNrfT5cbiAgICAgICAgICAgICAgICAgPGkgY2xhc3NOYW1lPVwiZmEgZmEtZncgZmEtZm9sZGVyLW9wZW5cIj48L2k+XG4gICAgICAgICAgICAgICAgIE9wZW5cbiAgICAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgICAgICA8L2xpPlxuICAgICAgICAgICAgICAgICA8bGk+XG4gICAgICAgICAgICAgICAgIDxhIGhyZWY9XCIjXCIgb25DbGljaz17dGhpcy5oYW5kbGVTYXZlQ2xpY2t9PlxuICAgICAgICAgICAgICAgICA8aSBjbGFzc05hbWU9XCJmYSBmYS1mdyBmYS1zYXZlXCI+PC9pPlxuICAgICAgICAgICAgICAgICBTYXZlXG4gICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgICAgPC9saT5cbiAgICAgICAgICAgICAgICAgPGxpIHJvbGU9XCJwcmVzZW50YXRpb25cIiBjbGFzc05hbWU9XCJkaXZpZGVyXCI+PC9saT5cbiAgICAgICAgICAgICAgICAgPGxpPlxuICAgICAgICAgICAgICAgICA8YSBocmVmPVwiI1wiIG9uQ2xpY2s9e3RoaXMuaGFuZGxlU2h1dGRvd25DbGlja30+XG4gICAgICAgICAgICAgICAgIDxpIGNsYXNzTmFtZT1cImZhIGZhLWZ3IGZhLXBsdWdcIj48L2k+XG4gICAgICAgICAgICAgICAgIFNodXRkb3duXG4gICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgICAgPC9saT5cbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxufSk7XG5cblxudmFyIGhlYWRlcl9lbnRyaWVzID0gW01haW5NZW51LCBWaWV3TWVudSAvKiwgUmVwb3J0c01lbnUgKi9dO1xuXG5cbnZhciBIZWFkZXIgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiSGVhZGVyXCIsXG4gICAgbWl4aW5zOiBbdXRpbHMuTmF2aWdhdGlvbl0sXG4gICAgZ2V0SW5pdGlhbFN0YXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBhY3RpdmU6IGhlYWRlcl9lbnRyaWVzWzBdXG4gICAgICAgIH07XG4gICAgfSxcbiAgICBoYW5kbGVDbGljazogZnVuY3Rpb24gKGFjdGl2ZSwgZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHRoaXMucmVwbGFjZVdpdGgoYWN0aXZlLnJvdXRlKTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7YWN0aXZlOiBhY3RpdmV9KTtcbiAgICB9LFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaGVhZGVyID0gaGVhZGVyX2VudHJpZXMubWFwKGZ1bmN0aW9uIChlbnRyeSwgaSkge1xuICAgICAgICAgICAgdmFyIGNsYXNzZXMgPSBSZWFjdC5hZGRvbnMuY2xhc3NTZXQoe1xuICAgICAgICAgICAgICAgIGFjdGl2ZTogZW50cnkgPT0gdGhpcy5zdGF0ZS5hY3RpdmVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiYVwiLCB7a2V5OiBpLCBcbiAgICAgICAgICAgICAgICAgICAgaHJlZjogXCIjXCIsIFxuICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU6IGNsYXNzZXMsIFxuICAgICAgICAgICAgICAgICAgICBvbkNsaWNrOiB0aGlzLmhhbmRsZUNsaWNrLmJpbmQodGhpcywgZW50cnkpXG4gICAgICAgICAgICAgICAgfSwgXG4gICAgICAgICAgICAgICAgICAgICBlbnRyeS50aXRsZVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJoZWFkZXJcIiwgbnVsbCwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBcInRpdGxlLWJhclwifSwgXG4gICAgICAgICAgICAgICAgICAgIFwibWl0bXByb3h5IFwiLCAgdGhpcy5wcm9wcy5zZXR0aW5ncy52ZXJzaW9uXG4gICAgICAgICAgICAgICAgKSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcIm5hdlwiLCB7Y2xhc3NOYW1lOiBcIm5hdi10YWJzIG5hdi10YWJzLWxnXCJ9LCBcbiAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChGaWxlTWVudSwgbnVsbCksIFxuICAgICAgICAgICAgICAgICAgICBoZWFkZXJcbiAgICAgICAgICAgICAgICApLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtjbGFzc05hbWU6IFwibWVudVwifSwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQodGhpcy5zdGF0ZS5hY3RpdmUsIHtzZXR0aW5nczogdGhpcy5wcm9wcy5zZXR0aW5nc30pXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIEhlYWRlcjogSGVhZGVyXG59IiwidmFyIFJlYWN0ID0gcmVxdWlyZShcInJlYWN0XCIpO1xuXG52YXIgdXRpbHMgPSByZXF1aXJlKFwiLi91dGlscy5qc1wiKTtcbnZhciB0b3B1dGlscyA9IHJlcXVpcmUoXCIuLi91dGlscy5qc1wiKTtcbnZhciB2aWV3cyA9IHJlcXVpcmUoXCIuLi9zdG9yZS92aWV3LmpzXCIpO1xudmFyIEZpbHQgPSByZXF1aXJlKFwiLi4vZmlsdC9maWx0LmpzXCIpO1xuRmxvd1RhYmxlID0gcmVxdWlyZShcIi4vZmxvd3RhYmxlLmpzXCIpO1xudmFyIGZsb3dkZXRhaWwgPSByZXF1aXJlKFwiLi9mbG93ZGV0YWlsLmpzXCIpO1xuXG5cbnZhciBNYWluVmlldyA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJNYWluVmlld1wiLFxuICAgIG1peGluczogW3V0aWxzLk5hdmlnYXRpb24sIHV0aWxzLlN0YXRlXSxcbiAgICBnZXRJbml0aWFsU3RhdGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5vblF1ZXJ5Q2hhbmdlKFF1ZXJ5LkZJTFRFUiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5zdGF0ZS52aWV3LnJlY2FsY3VsYXRlKHRoaXMuZ2V0Vmlld0ZpbHQoKSwgdGhpcy5nZXRWaWV3U29ydCgpKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5vblF1ZXJ5Q2hhbmdlKFF1ZXJ5LkhJR0hMSUdIVCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5zdGF0ZS52aWV3LnJlY2FsY3VsYXRlKHRoaXMuZ2V0Vmlld0ZpbHQoKSwgdGhpcy5nZXRWaWV3U29ydCgpKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGZsb3dzOiBbXVxuICAgICAgICB9O1xuICAgIH0sXG4gICAgZ2V0Vmlld0ZpbHQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHZhciBmaWx0ID0gRmlsdC5wYXJzZSh0aGlzLmdldFF1ZXJ5KClbUXVlcnkuRklMVEVSXSB8fCBcIlwiKTtcbiAgICAgICAgICAgIHZhciBoaWdobGlnaHRTdHIgPSB0aGlzLmdldFF1ZXJ5KClbUXVlcnkuSElHSExJR0hUXTtcbiAgICAgICAgICAgIHZhciBoaWdobGlnaHQgPSBoaWdobGlnaHRTdHIgPyBGaWx0LnBhcnNlKGhpZ2hsaWdodFN0cikgOiBmYWxzZTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHdoZW4gcHJvY2Vzc2luZyBmaWx0ZXI6IFwiICsgZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZnVuY3Rpb24gZmlsdGVyX2FuZF9oaWdobGlnaHQoZmxvdykge1xuICAgICAgICAgICAgaWYgKCF0aGlzLl9oaWdobGlnaHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9oaWdobGlnaHQgPSB7fTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX2hpZ2hsaWdodFtmbG93LmlkXSA9IGhpZ2hsaWdodCAmJiBoaWdobGlnaHQoZmxvdyk7XG4gICAgICAgICAgICByZXR1cm4gZmlsdChmbG93KTtcbiAgICAgICAgfTtcbiAgICB9LFxuICAgIGdldFZpZXdTb3J0OiBmdW5jdGlvbiAoKSB7XG4gICAgfSxcbiAgICBjb21wb25lbnRXaWxsUmVjZWl2ZVByb3BzOiBmdW5jdGlvbiAobmV4dFByb3BzKSB7XG4gICAgICAgIGlmIChuZXh0UHJvcHMuZmxvd1N0b3JlICE9PSB0aGlzLnByb3BzLmZsb3dTdG9yZSkge1xuICAgICAgICAgICAgdGhpcy5jbG9zZVZpZXcoKTtcbiAgICAgICAgICAgIHRoaXMub3BlblZpZXcobmV4dFByb3BzLmZsb3dTdG9yZSk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG9wZW5WaWV3OiBmdW5jdGlvbiAoc3RvcmUpIHtcbiAgICAgICAgdmFyIHZpZXcgPSBuZXcgdmlld3MuU3RvcmVWaWV3KHN0b3JlLCB0aGlzLmdldFZpZXdGaWx0KCksIHRoaXMuZ2V0Vmlld1NvcnQoKSk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgdmlldzogdmlld1xuICAgICAgICB9KTtcblxuICAgICAgICB2aWV3LmFkZExpc3RlbmVyKFwicmVjYWxjdWxhdGVcIiwgdGhpcy5vblJlY2FsY3VsYXRlKTtcbiAgICAgICAgdmlldy5hZGRMaXN0ZW5lcihcImFkZCB1cGRhdGUgcmVtb3ZlXCIsIHRoaXMub25VcGRhdGUpO1xuICAgICAgICB2aWV3LmFkZExpc3RlbmVyKFwicmVtb3ZlXCIsIHRoaXMub25SZW1vdmUpO1xuICAgIH0sXG4gICAgb25SZWNhbGN1bGF0ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZvcmNlVXBkYXRlKCk7XG4gICAgICAgIHZhciBzZWxlY3RlZCA9IHRoaXMuZ2V0U2VsZWN0ZWQoKTtcbiAgICAgICAgaWYgKHNlbGVjdGVkKSB7XG4gICAgICAgICAgICB0aGlzLnJlZnMuZmxvd1RhYmxlLnNjcm9sbEludG9WaWV3KHNlbGVjdGVkKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgb25VcGRhdGU6IGZ1bmN0aW9uIChmbG93KSB7XG4gICAgICAgIGlmIChmbG93LmlkID09PSB0aGlzLmdldFBhcmFtcygpLmZsb3dJZCkge1xuICAgICAgICAgICAgdGhpcy5mb3JjZVVwZGF0ZSgpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBvblJlbW92ZTogZnVuY3Rpb24gKGZsb3dfaWQsIGluZGV4KSB7XG4gICAgICAgIGlmIChmbG93X2lkID09PSB0aGlzLmdldFBhcmFtcygpLmZsb3dJZCkge1xuICAgICAgICAgICAgdmFyIGZsb3dfdG9fc2VsZWN0ID0gdGhpcy5zdGF0ZS52aWV3Lmxpc3RbTWF0aC5taW4oaW5kZXgsIHRoaXMuc3RhdGUudmlldy5saXN0Lmxlbmd0aCAtMSldO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RGbG93KGZsb3dfdG9fc2VsZWN0KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgY2xvc2VWaWV3OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc3RhdGUudmlldy5jbG9zZSgpO1xuICAgIH0sXG4gICAgY29tcG9uZW50V2lsbE1vdW50OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMub3BlblZpZXcodGhpcy5wcm9wcy5mbG93U3RvcmUpO1xuICAgIH0sXG4gICAgY29tcG9uZW50V2lsbFVubW91bnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jbG9zZVZpZXcoKTtcbiAgICB9LFxuICAgIHNlbGVjdEZsb3c6IGZ1bmN0aW9uIChmbG93KSB7XG4gICAgICAgIGlmIChmbG93KSB7XG4gICAgICAgICAgICB0aGlzLnJlcGxhY2VXaXRoKFxuICAgICAgICAgICAgICAgIFwiZmxvd1wiLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgZmxvd0lkOiBmbG93LmlkLFxuICAgICAgICAgICAgICAgICAgICBkZXRhaWxUYWI6IHRoaXMuZ2V0UGFyYW1zKCkuZGV0YWlsVGFiIHx8IFwicmVxdWVzdFwiXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRoaXMucmVmcy5mbG93VGFibGUuc2Nyb2xsSW50b1ZpZXcoZmxvdyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnJlcGxhY2VXaXRoKFwiZmxvd3NcIiwge30pO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBzZWxlY3RGbG93UmVsYXRpdmU6IGZ1bmN0aW9uIChzaGlmdCkge1xuICAgICAgICB2YXIgZmxvd3MgPSB0aGlzLnN0YXRlLnZpZXcubGlzdDtcbiAgICAgICAgdmFyIGluZGV4O1xuICAgICAgICBpZiAoIXRoaXMuZ2V0UGFyYW1zKCkuZmxvd0lkKSB7XG4gICAgICAgICAgICBpZiAoc2hpZnQgPiAwKSB7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBmbG93cy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbmRleCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgY3VyckZsb3dJZCA9IHRoaXMuZ2V0UGFyYW1zKCkuZmxvd0lkO1xuICAgICAgICAgICAgdmFyIGkgPSBmbG93cy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgaWYgKGZsb3dzW2ldLmlkID09PSBjdXJyRmxvd0lkKSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaW5kZXggPSBNYXRoLm1pbihcbiAgICAgICAgICAgICAgICBNYXRoLm1heCgwLCBpbmRleCArIHNoaWZ0KSxcbiAgICAgICAgICAgICAgICBmbG93cy5sZW5ndGggLSAxKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNlbGVjdEZsb3coZmxvd3NbaW5kZXhdKTtcbiAgICB9LFxuICAgIG9uS2V5RG93bjogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIGZsb3cgPSB0aGlzLmdldFNlbGVjdGVkKCk7XG4gICAgICAgIGlmIChlLmN0cmxLZXkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzd2l0Y2ggKGUua2V5Q29kZSkge1xuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuSzpcbiAgICAgICAgICAgIGNhc2UgdG9wdXRpbHMuS2V5LlVQOlxuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0Rmxvd1JlbGF0aXZlKC0xKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgdG9wdXRpbHMuS2V5Lko6XG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5ET1dOOlxuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0Rmxvd1JlbGF0aXZlKCsxKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgdG9wdXRpbHMuS2V5LlNQQUNFOlxuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuUEFHRV9ET1dOOlxuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0Rmxvd1JlbGF0aXZlKCsxMCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5QQUdFX1VQOlxuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0Rmxvd1JlbGF0aXZlKC0xMCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5FTkQ6XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RGbG93UmVsYXRpdmUoKzFlMTApO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuSE9NRTpcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdEZsb3dSZWxhdGl2ZSgtMWUxMCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5FU0M6XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RGbG93KG51bGwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuSDpcbiAgICAgICAgICAgIGNhc2UgdG9wdXRpbHMuS2V5LkxFRlQ6XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucmVmcy5mbG93RGV0YWlscykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlZnMuZmxvd0RldGFpbHMubmV4dFRhYigtMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuTDpcbiAgICAgICAgICAgIGNhc2UgdG9wdXRpbHMuS2V5LlRBQjpcbiAgICAgICAgICAgIGNhc2UgdG9wdXRpbHMuS2V5LlJJR0hUOlxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlZnMuZmxvd0RldGFpbHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWZzLmZsb3dEZXRhaWxzLm5leHRUYWIoKzEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgdG9wdXRpbHMuS2V5LkM6XG4gICAgICAgICAgICAgICAgaWYgKGUuc2hpZnRLZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgRmxvd0FjdGlvbnMuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5EOlxuICAgICAgICAgICAgICAgIGlmIChmbG93KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlLnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBGbG93QWN0aW9ucy5kdXBsaWNhdGUoZmxvdyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBGbG93QWN0aW9ucy5kZWxldGUoZmxvdyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5BOlxuICAgICAgICAgICAgICAgIGlmIChlLnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIEZsb3dBY3Rpb25zLmFjY2VwdF9hbGwoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGZsb3cgJiYgZmxvdy5pbnRlcmNlcHRlZCkge1xuICAgICAgICAgICAgICAgICAgICBGbG93QWN0aW9ucy5hY2NlcHQoZmxvdyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuUjpcbiAgICAgICAgICAgICAgICBpZiAoIWUuc2hpZnRLZXkgJiYgZmxvdykge1xuICAgICAgICAgICAgICAgICAgICBGbG93QWN0aW9ucy5yZXBsYXkoZmxvdyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuVjpcbiAgICAgICAgICAgICAgICBpZihlLnNoaWZ0S2V5ICYmIGZsb3cgJiYgZmxvdy5tb2RpZmllZCkge1xuICAgICAgICAgICAgICAgICAgICBGbG93QWN0aW9ucy5yZXZlcnQoZmxvdyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKFwia2V5ZG93blwiLCBlLmtleUNvZGUpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfSxcbiAgICBnZXRTZWxlY3RlZDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wcm9wcy5mbG93U3RvcmUuZ2V0KHRoaXMuZ2V0UGFyYW1zKCkuZmxvd0lkKTtcbiAgICB9LFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc2VsZWN0ZWQgPSB0aGlzLmdldFNlbGVjdGVkKCk7XG5cbiAgICAgICAgdmFyIGRldGFpbHM7XG4gICAgICAgIGlmIChzZWxlY3RlZCkge1xuICAgICAgICAgICAgZGV0YWlscyA9IFtcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KHV0aWxzLlNwbGl0dGVyLCB7a2V5OiBcInNwbGl0dGVyXCJ9KSxcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KGZsb3dkZXRhaWwuRmxvd0RldGFpbCwge2tleTogXCJmbG93RGV0YWlsc1wiLCByZWY6IFwiZmxvd0RldGFpbHNcIiwgZmxvdzogc2VsZWN0ZWR9KVxuICAgICAgICAgICAgXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRldGFpbHMgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwge2NsYXNzTmFtZTogXCJtYWluLXZpZXdcIiwgb25LZXlEb3duOiB0aGlzLm9uS2V5RG93biwgdGFiSW5kZXg6IFwiMFwifSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChGbG93VGFibGUsIHtyZWY6IFwiZmxvd1RhYmxlXCIsIFxuICAgICAgICAgICAgICAgICAgICB2aWV3OiB0aGlzLnN0YXRlLnZpZXcsIFxuICAgICAgICAgICAgICAgICAgICBzZWxlY3RGbG93OiB0aGlzLnNlbGVjdEZsb3csIFxuICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZDogc2VsZWN0ZWR9KSwgXG4gICAgICAgICAgICAgICAgZGV0YWlsc1xuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IE1haW5WaWV3O1xuIiwidmFyIFJlYWN0ID0gcmVxdWlyZShcInJlYWN0XCIpO1xudmFyIFJlYWN0Um91dGVyID0gcmVxdWlyZShcInJlYWN0LXJvdXRlclwiKTtcbnZhciBfID0gcmVxdWlyZShcImxvZGFzaFwiKTtcblxudmFyIHV0aWxzID0gcmVxdWlyZShcIi4vdXRpbHMuanNcIik7XG52YXIgTWFpblZpZXcgPSByZXF1aXJlKFwiLi9tYWludmlldy5qc1wiKTtcbnZhciBGb290ZXIgPSByZXF1aXJlKFwiLi9mb290ZXIuanNcIik7XG52YXIgaGVhZGVyID0gcmVxdWlyZShcIi4vaGVhZGVyLmpzXCIpO1xudmFyIEV2ZW50TG9nID0gcmVxdWlyZShcIi4vZXZlbnRsb2cuanNcIik7XG52YXIgc3RvcmUgPSByZXF1aXJlKFwiLi4vc3RvcmUvc3RvcmUuanNcIik7XG5cblxuLy9UT0RPOiBNb3ZlIG91dCBvZiBoZXJlLCBqdXN0IGEgc3R1Yi5cbnZhciBSZXBvcnRzID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIlJlcG9ydHNcIixcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgbnVsbCwgXCJSZXBvcnRFZGl0b3JcIik7XG4gICAgfVxufSk7XG5cblxudmFyIFByb3h5QXBwTWFpbiA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJQcm94eUFwcE1haW5cIixcbiAgICBtaXhpbnM6IFt1dGlscy5TdGF0ZV0sXG4gICAgZ2V0SW5pdGlhbFN0YXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBldmVudFN0b3JlID0gbmV3IHN0b3JlLkV2ZW50TG9nU3RvcmUoKTtcbiAgICAgICAgdmFyIGZsb3dTdG9yZSA9IG5ldyBzdG9yZS5GbG93U3RvcmUoKTtcbiAgICAgICAgdmFyIHNldHRpbmdzID0gbmV3IHN0b3JlLlNldHRpbmdzU3RvcmUoKTtcblxuICAgICAgICAvLyBEZWZhdWx0IFNldHRpbmdzIGJlZm9yZSBmZXRjaFxuICAgICAgICBfLmV4dGVuZChzZXR0aW5ncy5kaWN0LHtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzZXR0aW5nczogc2V0dGluZ3MsXG4gICAgICAgICAgICBmbG93U3RvcmU6IGZsb3dTdG9yZSxcbiAgICAgICAgICAgIGV2ZW50U3RvcmU6IGV2ZW50U3RvcmVcbiAgICAgICAgfTtcbiAgICB9LFxuICAgIGNvbXBvbmVudERpZE1vdW50OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc3RhdGUuc2V0dGluZ3MuYWRkTGlzdGVuZXIoXCJyZWNhbGN1bGF0ZVwiLCB0aGlzLm9uU2V0dGluZ3NDaGFuZ2UpO1xuICAgICAgICB3aW5kb3cuYXBwID0gdGhpcztcbiAgICB9LFxuICAgIGNvbXBvbmVudFdpbGxVbm1vdW50OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc3RhdGUuc2V0dGluZ3MucmVtb3ZlTGlzdGVuZXIoXCJyZWNhbGN1bGF0ZVwiLCB0aGlzLm9uU2V0dGluZ3NDaGFuZ2UpO1xuICAgIH0sXG4gICAgb25TZXR0aW5nc0NoYW5nZTogZnVuY3Rpb24oKXtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBzZXR0aW5nczogdGhpcy5zdGF0ZS5zZXR0aW5nc1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuXG4gICAgICAgIHZhciBldmVudGxvZztcbiAgICAgICAgaWYgKHRoaXMuZ2V0UXVlcnkoKVtRdWVyeS5TSE9XX0VWRU5UTE9HXSkge1xuICAgICAgICAgICAgZXZlbnRsb2cgPSBbXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudCh1dGlscy5TcGxpdHRlciwge2tleTogXCJzcGxpdHRlclwiLCBheGlzOiBcInlcIn0pLFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoRXZlbnRMb2csIHtrZXk6IFwiZXZlbnRsb2dcIiwgZXZlbnRTdG9yZTogdGhpcy5zdGF0ZS5ldmVudFN0b3JlfSlcbiAgICAgICAgICAgIF07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBldmVudGxvZyA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7aWQ6IFwiY29udGFpbmVyXCJ9LCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KGhlYWRlci5IZWFkZXIsIHtzZXR0aW5nczogdGhpcy5zdGF0ZS5zZXR0aW5ncy5kaWN0fSksIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoUm91dGVIYW5kbGVyLCB7c2V0dGluZ3M6IHRoaXMuc3RhdGUuc2V0dGluZ3MuZGljdCwgZmxvd1N0b3JlOiB0aGlzLnN0YXRlLmZsb3dTdG9yZX0pLCBcbiAgICAgICAgICAgICAgICBldmVudGxvZywgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChGb290ZXIsIHtzZXR0aW5nczogdGhpcy5zdGF0ZS5zZXR0aW5ncy5kaWN0fSlcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxuXG52YXIgUm91dGUgPSBSZWFjdFJvdXRlci5Sb3V0ZTtcbnZhciBSb3V0ZUhhbmRsZXIgPSBSZWFjdFJvdXRlci5Sb3V0ZUhhbmRsZXI7XG52YXIgUmVkaXJlY3QgPSBSZWFjdFJvdXRlci5SZWRpcmVjdDtcbnZhciBEZWZhdWx0Um91dGUgPSBSZWFjdFJvdXRlci5EZWZhdWx0Um91dGU7XG52YXIgTm90Rm91bmRSb3V0ZSA9IFJlYWN0Um91dGVyLk5vdEZvdW5kUm91dGU7XG5cblxudmFyIHJvdXRlcyA9IChcbiAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFJvdXRlLCB7cGF0aDogXCIvXCIsIGhhbmRsZXI6IFByb3h5QXBwTWFpbn0sIFxuICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFJvdXRlLCB7bmFtZTogXCJmbG93c1wiLCBwYXRoOiBcImZsb3dzXCIsIGhhbmRsZXI6IE1haW5WaWV3fSksIFxuICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFJvdXRlLCB7bmFtZTogXCJmbG93XCIsIHBhdGg6IFwiZmxvd3MvOmZsb3dJZC86ZGV0YWlsVGFiXCIsIGhhbmRsZXI6IE1haW5WaWV3fSksIFxuICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFJvdXRlLCB7bmFtZTogXCJyZXBvcnRzXCIsIGhhbmRsZXI6IFJlcG9ydHN9KSwgXG4gICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoUmVkaXJlY3QsIHtwYXRoOiBcIi9cIiwgdG86IFwiZmxvd3NcIn0pXG4gICAgKVxuKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgcm91dGVzOiByb3V0ZXNcbn07XG5cbiIsInZhciBSZWFjdCA9IHJlcXVpcmUoXCJyZWFjdFwiKTtcbnZhciBSZWFjdFJvdXRlciA9IHJlcXVpcmUoXCJyZWFjdC1yb3V0ZXJcIik7XG52YXIgXyA9IHJlcXVpcmUoXCJsb2Rhc2hcIik7XG5cbi8vUmVhY3QgdXRpbHMuIEZvciBvdGhlciB1dGlsaXRpZXMsIHNlZSAuLi91dGlscy5qc1xuXG4vLyBodHRwOi8vYmxvZy52amV1eC5jb20vMjAxMy9qYXZhc2NyaXB0L3Njcm9sbC1wb3NpdGlvbi13aXRoLXJlYWN0Lmh0bWwgKGFsc28gY29udGFpbnMgaW52ZXJzZSBleGFtcGxlKVxudmFyIEF1dG9TY3JvbGxNaXhpbiA9IHtcbiAgICBjb21wb25lbnRXaWxsVXBkYXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBub2RlID0gdGhpcy5nZXRET01Ob2RlKCk7XG4gICAgICAgIHRoaXMuX3Nob3VsZFNjcm9sbEJvdHRvbSA9IChcbiAgICAgICAgICAgIG5vZGUuc2Nyb2xsVG9wICE9PSAwICYmXG4gICAgICAgICAgICBub2RlLnNjcm9sbFRvcCArIG5vZGUuY2xpZW50SGVpZ2h0ID09PSBub2RlLnNjcm9sbEhlaWdodFxuICAgICAgICApO1xuICAgIH0sXG4gICAgY29tcG9uZW50RGlkVXBkYXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLl9zaG91bGRTY3JvbGxCb3R0b20pIHtcbiAgICAgICAgICAgIHZhciBub2RlID0gdGhpcy5nZXRET01Ob2RlKCk7XG4gICAgICAgICAgICBub2RlLnNjcm9sbFRvcCA9IG5vZGUuc2Nyb2xsSGVpZ2h0O1xuICAgICAgICB9XG4gICAgfSxcbn07XG5cblxudmFyIFN0aWNreUhlYWRNaXhpbiA9IHtcbiAgICBhZGp1c3RIZWFkOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIEFidXNpbmcgQ1NTIHRyYW5zZm9ybXMgdG8gc2V0IHRoZSBlbGVtZW50XG4gICAgICAgIC8vIHJlZmVyZW5jZWQgYXMgaGVhZCBpbnRvIHNvbWUga2luZCBvZiBwb3NpdGlvbjpzdGlja3kuXG4gICAgICAgIHZhciBoZWFkID0gdGhpcy5yZWZzLmhlYWQuZ2V0RE9NTm9kZSgpO1xuICAgICAgICBoZWFkLnN0eWxlLnRyYW5zZm9ybSA9IFwidHJhbnNsYXRlKDAsXCIgKyB0aGlzLmdldERPTU5vZGUoKS5zY3JvbGxUb3AgKyBcInB4KVwiO1xuICAgIH1cbn07XG5cblxudmFyIE5hdmlnYXRpb24gPSBfLmV4dGVuZCh7fSwgUmVhY3RSb3V0ZXIuTmF2aWdhdGlvbiwge1xuICAgIHNldFF1ZXJ5OiBmdW5jdGlvbiAoZGljdCkge1xuICAgICAgICB2YXIgcSA9IHRoaXMuY29udGV4dC5nZXRDdXJyZW50UXVlcnkoKTtcbiAgICAgICAgZm9yKHZhciBpIGluIGRpY3Qpe1xuICAgICAgICAgICAgaWYoZGljdC5oYXNPd25Qcm9wZXJ0eShpKSl7XG4gICAgICAgICAgICAgICAgcVtpXSA9IGRpY3RbaV0gfHwgdW5kZWZpbmVkOyAvL2ZhbHNleSB2YWx1ZXMgc2hhbGwgYmUgcmVtb3ZlZC5cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBxLl8gPSBcIl9cIjsgLy8gd29ya2Fyb3VuZCBmb3IgaHR0cHM6Ly9naXRodWIuY29tL3JhY2t0L3JlYWN0LXJvdXRlci9wdWxsLzU5OVxuICAgICAgICB0aGlzLnJlcGxhY2VXaXRoKHRoaXMuY29udGV4dC5nZXRDdXJyZW50UGF0aCgpLCB0aGlzLmNvbnRleHQuZ2V0Q3VycmVudFBhcmFtcygpLCBxKTtcbiAgICB9LFxuICAgIHJlcGxhY2VXaXRoOiBmdW5jdGlvbihyb3V0ZU5hbWVPclBhdGgsIHBhcmFtcywgcXVlcnkpIHtcbiAgICAgICAgaWYocm91dGVOYW1lT3JQYXRoID09PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgcm91dGVOYW1lT3JQYXRoID0gdGhpcy5jb250ZXh0LmdldEN1cnJlbnRQYXRoKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYocGFyYW1zID09PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgcGFyYW1zID0gdGhpcy5jb250ZXh0LmdldEN1cnJlbnRQYXJhbXMoKTtcbiAgICAgICAgfVxuICAgICAgICBpZihxdWVyeSA9PT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgIHF1ZXJ5ID0gdGhpcy5jb250ZXh0LmdldEN1cnJlbnRRdWVyeSgpO1xuICAgICAgICB9XG4gICAgICAgIFJlYWN0Um91dGVyLk5hdmlnYXRpb24ucmVwbGFjZVdpdGguY2FsbCh0aGlzLCByb3V0ZU5hbWVPclBhdGgsIHBhcmFtcywgcXVlcnkpO1xuICAgIH1cbn0pO1xuXy5leHRlbmQoTmF2aWdhdGlvbi5jb250ZXh0VHlwZXMsIFJlYWN0Um91dGVyLlN0YXRlLmNvbnRleHRUeXBlcyk7XG5cbnZhciBTdGF0ZSA9IF8uZXh0ZW5kKHt9LCBSZWFjdFJvdXRlci5TdGF0ZSwge1xuICAgIGdldEluaXRpYWxTdGF0ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9xdWVyeSA9IHRoaXMuY29udGV4dC5nZXRDdXJyZW50UXVlcnkoKTtcbiAgICAgICAgdGhpcy5fcXVlcnlXYXRjaGVzID0gW107XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH0sXG4gICAgb25RdWVyeUNoYW5nZTogZnVuY3Rpb24gKGtleSwgY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5fcXVlcnlXYXRjaGVzLnB1c2goe1xuICAgICAgICAgICAga2V5OiBrZXksXG4gICAgICAgICAgICBjYWxsYmFjazogY2FsbGJhY2tcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBjb21wb25lbnRXaWxsUmVjZWl2ZVByb3BzOiBmdW5jdGlvbiAobmV4dFByb3BzLCBuZXh0U3RhdGUpIHtcbiAgICAgICAgdmFyIHEgPSB0aGlzLmNvbnRleHQuZ2V0Q3VycmVudFF1ZXJ5KCk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fcXVlcnlXYXRjaGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgd2F0Y2ggPSB0aGlzLl9xdWVyeVdhdGNoZXNbaV07XG4gICAgICAgICAgICBpZiAodGhpcy5fcXVlcnlbd2F0Y2gua2V5XSAhPT0gcVt3YXRjaC5rZXldKSB7XG4gICAgICAgICAgICAgICAgd2F0Y2guY2FsbGJhY2sodGhpcy5fcXVlcnlbd2F0Y2gua2V5XSwgcVt3YXRjaC5rZXldLCB3YXRjaC5rZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3F1ZXJ5ID0gcTtcbiAgICB9XG59KTtcblxudmFyIFNwbGl0dGVyID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIlNwbGl0dGVyXCIsXG4gICAgZ2V0RGVmYXVsdFByb3BzOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBheGlzOiBcInhcIlxuICAgICAgICB9O1xuICAgIH0sXG4gICAgZ2V0SW5pdGlhbFN0YXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBhcHBsaWVkOiBmYWxzZSxcbiAgICAgICAgICAgIHN0YXJ0WDogZmFsc2UsXG4gICAgICAgICAgICBzdGFydFk6IGZhbHNlXG4gICAgICAgIH07XG4gICAgfSxcbiAgICBvbk1vdXNlRG93bjogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBzdGFydFg6IGUucGFnZVgsXG4gICAgICAgICAgICBzdGFydFk6IGUucGFnZVlcbiAgICAgICAgfSk7XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwibW91c2Vtb3ZlXCIsIHRoaXMub25Nb3VzZU1vdmUpO1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1vdXNldXBcIiwgdGhpcy5vbk1vdXNlVXApO1xuICAgICAgICAvLyBPY2Nhc2lvbmFsbHksIG9ubHkgYSBkcmFnRW5kIGV2ZW50IGlzIHRyaWdnZXJlZCwgYnV0IG5vIG1vdXNlVXAuXG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwiZHJhZ2VuZFwiLCB0aGlzLm9uRHJhZ0VuZCk7XG4gICAgfSxcbiAgICBvbkRyYWdFbmQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5nZXRET01Ob2RlKCkuc3R5bGUudHJhbnNmb3JtID0gXCJcIjtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJkcmFnZW5kXCIsIHRoaXMub25EcmFnRW5kKTtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJtb3VzZXVwXCIsIHRoaXMub25Nb3VzZVVwKTtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJtb3VzZW1vdmVcIiwgdGhpcy5vbk1vdXNlTW92ZSk7XG4gICAgfSxcbiAgICBvbk1vdXNlVXA6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHRoaXMub25EcmFnRW5kKCk7XG5cbiAgICAgICAgdmFyIG5vZGUgPSB0aGlzLmdldERPTU5vZGUoKTtcbiAgICAgICAgdmFyIHByZXYgPSBub2RlLnByZXZpb3VzRWxlbWVudFNpYmxpbmc7XG4gICAgICAgIHZhciBuZXh0ID0gbm9kZS5uZXh0RWxlbWVudFNpYmxpbmc7XG5cbiAgICAgICAgdmFyIGRYID0gZS5wYWdlWCAtIHRoaXMuc3RhdGUuc3RhcnRYO1xuICAgICAgICB2YXIgZFkgPSBlLnBhZ2VZIC0gdGhpcy5zdGF0ZS5zdGFydFk7XG4gICAgICAgIHZhciBmbGV4QmFzaXM7XG4gICAgICAgIGlmICh0aGlzLnByb3BzLmF4aXMgPT09IFwieFwiKSB7XG4gICAgICAgICAgICBmbGV4QmFzaXMgPSBwcmV2Lm9mZnNldFdpZHRoICsgZFg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmbGV4QmFzaXMgPSBwcmV2Lm9mZnNldEhlaWdodCArIGRZO1xuICAgICAgICB9XG5cbiAgICAgICAgcHJldi5zdHlsZS5mbGV4ID0gXCIwIDAgXCIgKyBNYXRoLm1heCgwLCBmbGV4QmFzaXMpICsgXCJweFwiO1xuICAgICAgICBuZXh0LnN0eWxlLmZsZXggPSBcIjEgMSBhdXRvXCI7XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBhcHBsaWVkOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLm9uUmVzaXplKCk7XG4gICAgfSxcbiAgICBvbk1vdXNlTW92ZTogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIGRYID0gMCwgZFkgPSAwO1xuICAgICAgICBpZiAodGhpcy5wcm9wcy5heGlzID09PSBcInhcIikge1xuICAgICAgICAgICAgZFggPSBlLnBhZ2VYIC0gdGhpcy5zdGF0ZS5zdGFydFg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkWSA9IGUucGFnZVkgLSB0aGlzLnN0YXRlLnN0YXJ0WTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmdldERPTU5vZGUoKS5zdHlsZS50cmFuc2Zvcm0gPSBcInRyYW5zbGF0ZShcIiArIGRYICsgXCJweCxcIiArIGRZICsgXCJweClcIjtcbiAgICB9LFxuICAgIG9uUmVzaXplOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIFRyaWdnZXIgYSBnbG9iYWwgcmVzaXplIGV2ZW50LiBUaGlzIG5vdGlmaWVzIGNvbXBvbmVudHMgdGhhdCBlbXBsb3kgdmlydHVhbCBzY3JvbGxpbmdcbiAgICAgICAgLy8gdGhhdCB0aGVpciB2aWV3cG9ydCBtYXkgaGF2ZSBjaGFuZ2VkLlxuICAgICAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB3aW5kb3cuZGlzcGF0Y2hFdmVudChuZXcgQ3VzdG9tRXZlbnQoXCJyZXNpemVcIikpO1xuICAgICAgICB9LCAxKTtcbiAgICB9LFxuICAgIHJlc2V0OiBmdW5jdGlvbiAod2lsbFVubW91bnQpIHtcbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlLmFwcGxpZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbm9kZSA9IHRoaXMuZ2V0RE9NTm9kZSgpO1xuICAgICAgICB2YXIgcHJldiA9IG5vZGUucHJldmlvdXNFbGVtZW50U2libGluZztcbiAgICAgICAgdmFyIG5leHQgPSBub2RlLm5leHRFbGVtZW50U2libGluZztcblxuICAgICAgICBwcmV2LnN0eWxlLmZsZXggPSBcIlwiO1xuICAgICAgICBuZXh0LnN0eWxlLmZsZXggPSBcIlwiO1xuXG4gICAgICAgIGlmICghd2lsbFVubW91bnQpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgIGFwcGxpZWQ6IGZhbHNlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9uUmVzaXplKCk7XG4gICAgfSxcbiAgICBjb21wb25lbnRXaWxsVW5tb3VudDogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJlc2V0KHRydWUpO1xuICAgIH0sXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjbGFzc05hbWUgPSBcInNwbGl0dGVyXCI7XG4gICAgICAgIGlmICh0aGlzLnByb3BzLmF4aXMgPT09IFwieFwiKSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgKz0gXCIgc3BsaXR0ZXIteFwiO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2xhc3NOYW1lICs9IFwiIHNwbGl0dGVyLXlcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBjbGFzc05hbWV9LCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtvbk1vdXNlRG93bjogdGhpcy5vbk1vdXNlRG93biwgZHJhZ2dhYmxlOiBcInRydWVcIn0pXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxufSk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIFN0YXRlOiBTdGF0ZSxcbiAgICBOYXZpZ2F0aW9uOiBOYXZpZ2F0aW9uLFxuICAgIFN0aWNreUhlYWRNaXhpbjogU3RpY2t5SGVhZE1peGluLFxuICAgIEF1dG9TY3JvbGxNaXhpbjogQXV0b1Njcm9sbE1peGluLFxuICAgIFNwbGl0dGVyOiBTcGxpdHRlclxufSIsInZhciBSZWFjdCA9IHJlcXVpcmUoXCJyZWFjdFwiKTtcblxudmFyIFZpcnR1YWxTY3JvbGxNaXhpbiA9IHtcbiAgICBnZXRJbml0aWFsU3RhdGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHN0YXJ0OiAwLFxuICAgICAgICAgICAgc3RvcDogMFxuICAgICAgICB9O1xuICAgIH0sXG4gICAgY29tcG9uZW50V2lsbE1vdW50OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5wcm9wcy5yb3dIZWlnaHQpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlZpcnR1YWxTY3JvbGxNaXhpbjogTm8gcm93SGVpZ2h0IHNwZWNpZmllZFwiLCB0aGlzKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgZ2V0UGxhY2Vob2xkZXJUb3A6IGZ1bmN0aW9uICh0b3RhbCkge1xuICAgICAgICB2YXIgVGFnID0gdGhpcy5wcm9wcy5wbGFjZWhvbGRlclRhZ05hbWUgfHwgXCJ0clwiO1xuICAgICAgICAvLyBXaGVuIGEgbGFyZ2UgdHJ1bmsgb2YgZWxlbWVudHMgaXMgcmVtb3ZlZCBmcm9tIHRoZSBidXR0b24sIHN0YXJ0IG1heSBiZSBmYXIgb2ZmIHRoZSB2aWV3cG9ydC5cbiAgICAgICAgLy8gVG8gbWFrZSB0aGlzIGlzc3VlIGxlc3Mgc2V2ZXJlLCBsaW1pdCB0aGUgdG9wIHBsYWNlaG9sZGVyIHRvIHRoZSB0b3RhbCBudW1iZXIgb2Ygcm93cy5cbiAgICAgICAgdmFyIHN0eWxlID0ge1xuICAgICAgICAgICAgaGVpZ2h0OiBNYXRoLm1pbih0aGlzLnN0YXRlLnN0YXJ0LCB0b3RhbCkgKiB0aGlzLnByb3BzLnJvd0hlaWdodFxuICAgICAgICB9O1xuICAgICAgICB2YXIgc3BhY2VyID0gUmVhY3QuY3JlYXRlRWxlbWVudChUYWcsIHtrZXk6IFwicGxhY2Vob2xkZXItdG9wXCIsIHN0eWxlOiBzdHlsZX0pO1xuXG4gICAgICAgIGlmICh0aGlzLnN0YXRlLnN0YXJ0ICUgMiA9PT0gMSkge1xuICAgICAgICAgICAgLy8gZml4IGV2ZW4vb2RkIHJvd3NcbiAgICAgICAgICAgIHJldHVybiBbc3BhY2VyLCBSZWFjdC5jcmVhdGVFbGVtZW50KFRhZywge2tleTogXCJwbGFjZWhvbGRlci10b3AtMlwifSldO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHNwYWNlcjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgZ2V0UGxhY2Vob2xkZXJCb3R0b206IGZ1bmN0aW9uICh0b3RhbCkge1xuICAgICAgICB2YXIgVGFnID0gdGhpcy5wcm9wcy5wbGFjZWhvbGRlclRhZ05hbWUgfHwgXCJ0clwiO1xuICAgICAgICB2YXIgc3R5bGUgPSB7XG4gICAgICAgICAgICBoZWlnaHQ6IE1hdGgubWF4KDAsIHRvdGFsIC0gdGhpcy5zdGF0ZS5zdG9wKSAqIHRoaXMucHJvcHMucm93SGVpZ2h0XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFRhZywge2tleTogXCJwbGFjZWhvbGRlci1ib3R0b21cIiwgc3R5bGU6IHN0eWxlfSk7XG4gICAgfSxcbiAgICBjb21wb25lbnREaWRNb3VudDogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLm9uU2Nyb2xsKCk7XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCB0aGlzLm9uU2Nyb2xsKTtcbiAgICB9LFxuICAgIGNvbXBvbmVudFdpbGxVbm1vdW50OiBmdW5jdGlvbigpe1xuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5vblNjcm9sbCk7XG4gICAgfSxcbiAgICBvblNjcm9sbDogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdmlld3BvcnQgPSB0aGlzLmdldERPTU5vZGUoKTtcbiAgICAgICAgdmFyIHRvcCA9IHZpZXdwb3J0LnNjcm9sbFRvcDtcbiAgICAgICAgdmFyIGhlaWdodCA9IHZpZXdwb3J0Lm9mZnNldEhlaWdodDtcbiAgICAgICAgdmFyIHN0YXJ0ID0gTWF0aC5mbG9vcih0b3AgLyB0aGlzLnByb3BzLnJvd0hlaWdodCk7XG4gICAgICAgIHZhciBzdG9wID0gc3RhcnQgKyBNYXRoLmNlaWwoaGVpZ2h0IC8gKHRoaXMucHJvcHMucm93SGVpZ2h0TWluIHx8IHRoaXMucHJvcHMucm93SGVpZ2h0KSk7XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBzdGFydDogc3RhcnQsXG4gICAgICAgICAgICBzdG9wOiBzdG9wXG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgcmVuZGVyUm93czogZnVuY3Rpb24gKGVsZW1zKSB7XG4gICAgICAgIHZhciByb3dzID0gW107XG4gICAgICAgIHZhciBtYXggPSBNYXRoLm1pbihlbGVtcy5sZW5ndGgsIHRoaXMuc3RhdGUuc3RvcCk7XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IHRoaXMuc3RhdGUuc3RhcnQ7IGkgPCBtYXg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGVsZW0gPSBlbGVtc1tpXTtcbiAgICAgICAgICAgIHJvd3MucHVzaCh0aGlzLnJlbmRlclJvdyhlbGVtKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJvd3M7XG4gICAgfSxcbiAgICBzY3JvbGxSb3dJbnRvVmlldzogZnVuY3Rpb24gKGluZGV4LCBoZWFkX2hlaWdodCkge1xuXG4gICAgICAgIHZhciByb3dfdG9wID0gKGluZGV4ICogdGhpcy5wcm9wcy5yb3dIZWlnaHQpICsgaGVhZF9oZWlnaHQ7XG4gICAgICAgIHZhciByb3dfYm90dG9tID0gcm93X3RvcCArIHRoaXMucHJvcHMucm93SGVpZ2h0O1xuXG4gICAgICAgIHZhciB2aWV3cG9ydCA9IHRoaXMuZ2V0RE9NTm9kZSgpO1xuICAgICAgICB2YXIgdmlld3BvcnRfdG9wID0gdmlld3BvcnQuc2Nyb2xsVG9wO1xuICAgICAgICB2YXIgdmlld3BvcnRfYm90dG9tID0gdmlld3BvcnRfdG9wICsgdmlld3BvcnQub2Zmc2V0SGVpZ2h0O1xuXG4gICAgICAgIC8vIEFjY291bnQgZm9yIHBpbm5lZCB0aGVhZFxuICAgICAgICBpZiAocm93X3RvcCAtIGhlYWRfaGVpZ2h0IDwgdmlld3BvcnRfdG9wKSB7XG4gICAgICAgICAgICB2aWV3cG9ydC5zY3JvbGxUb3AgPSByb3dfdG9wIC0gaGVhZF9oZWlnaHQ7XG4gICAgICAgIH0gZWxzZSBpZiAocm93X2JvdHRvbSA+IHZpZXdwb3J0X2JvdHRvbSkge1xuICAgICAgICAgICAgdmlld3BvcnQuc2Nyb2xsVG9wID0gcm93X2JvdHRvbSAtIHZpZXdwb3J0Lm9mZnNldEhlaWdodDtcbiAgICAgICAgfVxuICAgIH0sXG59O1xuXG5tb2R1bGUuZXhwb3J0cyAgPSBWaXJ0dWFsU2Nyb2xsTWl4aW47IiwiXG52YXIgYWN0aW9ucyA9IHJlcXVpcmUoXCIuL2FjdGlvbnMuanNcIik7XG5cbmZ1bmN0aW9uIENvbm5lY3Rpb24odXJsKSB7XG4gICAgaWYgKHVybFswXSA9PT0gXCIvXCIpIHtcbiAgICAgICAgdXJsID0gbG9jYXRpb24ub3JpZ2luLnJlcGxhY2UoXCJodHRwXCIsIFwid3NcIikgKyB1cmw7XG4gICAgfVxuXG4gICAgdmFyIHdzID0gbmV3IFdlYlNvY2tldCh1cmwpO1xuICAgIHdzLm9ub3BlbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYWN0aW9ucy5Db25uZWN0aW9uQWN0aW9ucy5vcGVuKCk7XG4gICAgfTtcbiAgICB3cy5vbm1lc3NhZ2UgPSBmdW5jdGlvbiAobWVzc2FnZSkge1xuICAgICAgICB2YXIgbSA9IEpTT04ucGFyc2UobWVzc2FnZS5kYXRhKTtcbiAgICAgICAgQXBwRGlzcGF0Y2hlci5kaXNwYXRjaFNlcnZlckFjdGlvbihtKTtcbiAgICB9O1xuICAgIHdzLm9uZXJyb3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGFjdGlvbnMuQ29ubmVjdGlvbkFjdGlvbnMuZXJyb3IoKTtcbiAgICAgICAgRXZlbnRMb2dBY3Rpb25zLmFkZF9ldmVudChcIldlYlNvY2tldCBjb25uZWN0aW9uIGVycm9yLlwiKTtcbiAgICB9O1xuICAgIHdzLm9uY2xvc2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGFjdGlvbnMuQ29ubmVjdGlvbkFjdGlvbnMuY2xvc2UoKTtcbiAgICAgICAgRXZlbnRMb2dBY3Rpb25zLmFkZF9ldmVudChcIldlYlNvY2tldCBjb25uZWN0aW9uIGNsb3NlZC5cIik7XG4gICAgfTtcbiAgICByZXR1cm4gd3M7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gQ29ubmVjdGlvbjsiLCJjb25zdCBQYXlsb2FkU291cmNlcyA9IHtcbiAgICBWSUVXOiBcInZpZXdcIixcbiAgICBTRVJWRVI6IFwic2VydmVyXCJcbn07XG5cblxuZnVuY3Rpb24gRGlzcGF0Y2hlcigpIHtcbiAgICB0aGlzLmNhbGxiYWNrcyA9IFtdO1xufVxuRGlzcGF0Y2hlci5wcm90b3R5cGUucmVnaXN0ZXIgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICB0aGlzLmNhbGxiYWNrcy5wdXNoKGNhbGxiYWNrKTtcbn07XG5EaXNwYXRjaGVyLnByb3RvdHlwZS51bnJlZ2lzdGVyID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgdmFyIGluZGV4ID0gdGhpcy5jYWxsYmFja3MuaW5kZXhPZihjYWxsYmFjayk7XG4gICAgaWYgKGluZGV4ID49IDApIHtcbiAgICAgICAgdGhpcy5jYWxsYmFja3Muc3BsaWNlKGluZGV4LCAxKTtcbiAgICB9XG59O1xuRGlzcGF0Y2hlci5wcm90b3R5cGUuZGlzcGF0Y2ggPSBmdW5jdGlvbiAocGF5bG9hZCkge1xuICAgIGNvbnNvbGUuZGVidWcoXCJkaXNwYXRjaFwiLCBwYXlsb2FkKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY2FsbGJhY2tzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXMuY2FsbGJhY2tzW2ldKHBheWxvYWQpO1xuICAgIH1cbn07XG5cblxuQXBwRGlzcGF0Y2hlciA9IG5ldyBEaXNwYXRjaGVyKCk7XG5BcHBEaXNwYXRjaGVyLmRpc3BhdGNoVmlld0FjdGlvbiA9IGZ1bmN0aW9uIChhY3Rpb24pIHtcbiAgICBhY3Rpb24uc291cmNlID0gUGF5bG9hZFNvdXJjZXMuVklFVztcbiAgICB0aGlzLmRpc3BhdGNoKGFjdGlvbik7XG59O1xuQXBwRGlzcGF0Y2hlci5kaXNwYXRjaFNlcnZlckFjdGlvbiA9IGZ1bmN0aW9uIChhY3Rpb24pIHtcbiAgICBhY3Rpb24uc291cmNlID0gUGF5bG9hZFNvdXJjZXMuU0VSVkVSO1xuICAgIHRoaXMuZGlzcGF0Y2goYWN0aW9uKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIEFwcERpc3BhdGNoZXI6IEFwcERpc3BhdGNoZXJcbn07IiwiLyoganNoaW50IGlnbm9yZTpzdGFydCAqL1xuRmlsdCA9IChmdW5jdGlvbigpIHtcbiAgLypcbiAgICogR2VuZXJhdGVkIGJ5IFBFRy5qcyAwLjguMC5cbiAgICpcbiAgICogaHR0cDovL3BlZ2pzLm1hamRhLmN6L1xuICAgKi9cblxuICBmdW5jdGlvbiBwZWckc3ViY2xhc3MoY2hpbGQsIHBhcmVudCkge1xuICAgIGZ1bmN0aW9uIGN0b3IoKSB7IHRoaXMuY29uc3RydWN0b3IgPSBjaGlsZDsgfVxuICAgIGN0b3IucHJvdG90eXBlID0gcGFyZW50LnByb3RvdHlwZTtcbiAgICBjaGlsZC5wcm90b3R5cGUgPSBuZXcgY3RvcigpO1xuICB9XG5cbiAgZnVuY3Rpb24gU3ludGF4RXJyb3IobWVzc2FnZSwgZXhwZWN0ZWQsIGZvdW5kLCBvZmZzZXQsIGxpbmUsIGNvbHVtbikge1xuICAgIHRoaXMubWVzc2FnZSAgPSBtZXNzYWdlO1xuICAgIHRoaXMuZXhwZWN0ZWQgPSBleHBlY3RlZDtcbiAgICB0aGlzLmZvdW5kICAgID0gZm91bmQ7XG4gICAgdGhpcy5vZmZzZXQgICA9IG9mZnNldDtcbiAgICB0aGlzLmxpbmUgICAgID0gbGluZTtcbiAgICB0aGlzLmNvbHVtbiAgID0gY29sdW1uO1xuXG4gICAgdGhpcy5uYW1lICAgICA9IFwiU3ludGF4RXJyb3JcIjtcbiAgfVxuXG4gIHBlZyRzdWJjbGFzcyhTeW50YXhFcnJvciwgRXJyb3IpO1xuXG4gIGZ1bmN0aW9uIHBhcnNlKGlucHV0KSB7XG4gICAgdmFyIG9wdGlvbnMgPSBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHt9LFxuXG4gICAgICAgIHBlZyRGQUlMRUQgPSB7fSxcblxuICAgICAgICBwZWckc3RhcnRSdWxlRnVuY3Rpb25zID0geyBzdGFydDogcGVnJHBhcnNlc3RhcnQgfSxcbiAgICAgICAgcGVnJHN0YXJ0UnVsZUZ1bmN0aW9uICA9IHBlZyRwYXJzZXN0YXJ0LFxuXG4gICAgICAgIHBlZyRjMCA9IHsgdHlwZTogXCJvdGhlclwiLCBkZXNjcmlwdGlvbjogXCJmaWx0ZXIgZXhwcmVzc2lvblwiIH0sXG4gICAgICAgIHBlZyRjMSA9IHBlZyRGQUlMRUQsXG4gICAgICAgIHBlZyRjMiA9IGZ1bmN0aW9uKG9yRXhwcikgeyByZXR1cm4gb3JFeHByOyB9LFxuICAgICAgICBwZWckYzMgPSBbXSxcbiAgICAgICAgcGVnJGM0ID0gZnVuY3Rpb24oKSB7cmV0dXJuIHRydWVGaWx0ZXI7IH0sXG4gICAgICAgIHBlZyRjNSA9IHsgdHlwZTogXCJvdGhlclwiLCBkZXNjcmlwdGlvbjogXCJ3aGl0ZXNwYWNlXCIgfSxcbiAgICAgICAgcGVnJGM2ID0gL15bIFxcdFxcblxccl0vLFxuICAgICAgICBwZWckYzcgPSB7IHR5cGU6IFwiY2xhc3NcIiwgdmFsdWU6IFwiWyBcXFxcdFxcXFxuXFxcXHJdXCIsIGRlc2NyaXB0aW9uOiBcIlsgXFxcXHRcXFxcblxcXFxyXVwiIH0sXG4gICAgICAgIHBlZyRjOCA9IHsgdHlwZTogXCJvdGhlclwiLCBkZXNjcmlwdGlvbjogXCJjb250cm9sIGNoYXJhY3RlclwiIH0sXG4gICAgICAgIHBlZyRjOSA9IC9eW3wmISgpflwiXS8sXG4gICAgICAgIHBlZyRjMTAgPSB7IHR5cGU6IFwiY2xhc3NcIiwgdmFsdWU6IFwiW3wmISgpflxcXCJdXCIsIGRlc2NyaXB0aW9uOiBcIlt8JiEoKX5cXFwiXVwiIH0sXG4gICAgICAgIHBlZyRjMTEgPSB7IHR5cGU6IFwib3RoZXJcIiwgZGVzY3JpcHRpb246IFwib3B0aW9uYWwgd2hpdGVzcGFjZVwiIH0sXG4gICAgICAgIHBlZyRjMTIgPSBcInxcIixcbiAgICAgICAgcGVnJGMxMyA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcInxcIiwgZGVzY3JpcHRpb246IFwiXFxcInxcXFwiXCIgfSxcbiAgICAgICAgcGVnJGMxNCA9IGZ1bmN0aW9uKGZpcnN0LCBzZWNvbmQpIHsgcmV0dXJuIG9yKGZpcnN0LCBzZWNvbmQpOyB9LFxuICAgICAgICBwZWckYzE1ID0gXCImXCIsXG4gICAgICAgIHBlZyRjMTYgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCImXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCImXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjMTcgPSBmdW5jdGlvbihmaXJzdCwgc2Vjb25kKSB7IHJldHVybiBhbmQoZmlyc3QsIHNlY29uZCk7IH0sXG4gICAgICAgIHBlZyRjMTggPSBcIiFcIixcbiAgICAgICAgcGVnJGMxOSA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIiFcIiwgZGVzY3JpcHRpb246IFwiXFxcIiFcXFwiXCIgfSxcbiAgICAgICAgcGVnJGMyMCA9IGZ1bmN0aW9uKGV4cHIpIHsgcmV0dXJuIG5vdChleHByKTsgfSxcbiAgICAgICAgcGVnJGMyMSA9IFwiKFwiLFxuICAgICAgICBwZWckYzIyID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwiKFwiLCBkZXNjcmlwdGlvbjogXCJcXFwiKFxcXCJcIiB9LFxuICAgICAgICBwZWckYzIzID0gXCIpXCIsXG4gICAgICAgIHBlZyRjMjQgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCIpXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCIpXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjMjUgPSBmdW5jdGlvbihleHByKSB7IHJldHVybiBiaW5kaW5nKGV4cHIpOyB9LFxuICAgICAgICBwZWckYzI2ID0gXCJ+YVwiLFxuICAgICAgICBwZWckYzI3ID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwifmFcIiwgZGVzY3JpcHRpb246IFwiXFxcIn5hXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjMjggPSBmdW5jdGlvbigpIHsgcmV0dXJuIGFzc2V0RmlsdGVyOyB9LFxuICAgICAgICBwZWckYzI5ID0gXCJ+ZVwiLFxuICAgICAgICBwZWckYzMwID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwifmVcIiwgZGVzY3JpcHRpb246IFwiXFxcIn5lXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjMzEgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGVycm9yRmlsdGVyOyB9LFxuICAgICAgICBwZWckYzMyID0gXCJ+cVwiLFxuICAgICAgICBwZWckYzMzID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwifnFcIiwgZGVzY3JpcHRpb246IFwiXFxcIn5xXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjMzQgPSBmdW5jdGlvbigpIHsgcmV0dXJuIG5vUmVzcG9uc2VGaWx0ZXI7IH0sXG4gICAgICAgIHBlZyRjMzUgPSBcIn5zXCIsXG4gICAgICAgIHBlZyRjMzYgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ+c1wiLCBkZXNjcmlwdGlvbjogXCJcXFwifnNcXFwiXCIgfSxcbiAgICAgICAgcGVnJGMzNyA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gcmVzcG9uc2VGaWx0ZXI7IH0sXG4gICAgICAgIHBlZyRjMzggPSBcInRydWVcIixcbiAgICAgICAgcGVnJGMzOSA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcInRydWVcIiwgZGVzY3JpcHRpb246IFwiXFxcInRydWVcXFwiXCIgfSxcbiAgICAgICAgcGVnJGM0MCA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdHJ1ZUZpbHRlcjsgfSxcbiAgICAgICAgcGVnJGM0MSA9IFwiZmFsc2VcIixcbiAgICAgICAgcGVnJGM0MiA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcImZhbHNlXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJmYWxzZVxcXCJcIiB9LFxuICAgICAgICBwZWckYzQzID0gZnVuY3Rpb24oKSB7IHJldHVybiBmYWxzZUZpbHRlcjsgfSxcbiAgICAgICAgcGVnJGM0NCA9IFwifmNcIixcbiAgICAgICAgcGVnJGM0NSA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIn5jXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJ+Y1xcXCJcIiB9LFxuICAgICAgICBwZWckYzQ2ID0gZnVuY3Rpb24ocykgeyByZXR1cm4gcmVzcG9uc2VDb2RlKHMpOyB9LFxuICAgICAgICBwZWckYzQ3ID0gXCJ+ZFwiLFxuICAgICAgICBwZWckYzQ4ID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwifmRcIiwgZGVzY3JpcHRpb246IFwiXFxcIn5kXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjNDkgPSBmdW5jdGlvbihzKSB7IHJldHVybiBkb21haW4ocyk7IH0sXG4gICAgICAgIHBlZyRjNTAgPSBcIn5oXCIsXG4gICAgICAgIHBlZyRjNTEgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ+aFwiLCBkZXNjcmlwdGlvbjogXCJcXFwifmhcXFwiXCIgfSxcbiAgICAgICAgcGVnJGM1MiA9IGZ1bmN0aW9uKHMpIHsgcmV0dXJuIGhlYWRlcihzKTsgfSxcbiAgICAgICAgcGVnJGM1MyA9IFwifmhxXCIsXG4gICAgICAgIHBlZyRjNTQgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ+aHFcIiwgZGVzY3JpcHRpb246IFwiXFxcIn5ocVxcXCJcIiB9LFxuICAgICAgICBwZWckYzU1ID0gZnVuY3Rpb24ocykgeyByZXR1cm4gcmVxdWVzdEhlYWRlcihzKTsgfSxcbiAgICAgICAgcGVnJGM1NiA9IFwifmhzXCIsXG4gICAgICAgIHBlZyRjNTcgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ+aHNcIiwgZGVzY3JpcHRpb246IFwiXFxcIn5oc1xcXCJcIiB9LFxuICAgICAgICBwZWckYzU4ID0gZnVuY3Rpb24ocykgeyByZXR1cm4gcmVzcG9uc2VIZWFkZXIocyk7IH0sXG4gICAgICAgIHBlZyRjNTkgPSBcIn5tXCIsXG4gICAgICAgIHBlZyRjNjAgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ+bVwiLCBkZXNjcmlwdGlvbjogXCJcXFwifm1cXFwiXCIgfSxcbiAgICAgICAgcGVnJGM2MSA9IGZ1bmN0aW9uKHMpIHsgcmV0dXJuIG1ldGhvZChzKTsgfSxcbiAgICAgICAgcGVnJGM2MiA9IFwifnRcIixcbiAgICAgICAgcGVnJGM2MyA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIn50XCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJ+dFxcXCJcIiB9LFxuICAgICAgICBwZWckYzY0ID0gZnVuY3Rpb24ocykgeyByZXR1cm4gY29udGVudFR5cGUocyk7IH0sXG4gICAgICAgIHBlZyRjNjUgPSBcIn50cVwiLFxuICAgICAgICBwZWckYzY2ID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwifnRxXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJ+dHFcXFwiXCIgfSxcbiAgICAgICAgcGVnJGM2NyA9IGZ1bmN0aW9uKHMpIHsgcmV0dXJuIHJlcXVlc3RDb250ZW50VHlwZShzKTsgfSxcbiAgICAgICAgcGVnJGM2OCA9IFwifnRzXCIsXG4gICAgICAgIHBlZyRjNjkgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ+dHNcIiwgZGVzY3JpcHRpb246IFwiXFxcIn50c1xcXCJcIiB9LFxuICAgICAgICBwZWckYzcwID0gZnVuY3Rpb24ocykgeyByZXR1cm4gcmVzcG9uc2VDb250ZW50VHlwZShzKTsgfSxcbiAgICAgICAgcGVnJGM3MSA9IFwifnVcIixcbiAgICAgICAgcGVnJGM3MiA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIn51XCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJ+dVxcXCJcIiB9LFxuICAgICAgICBwZWckYzczID0gZnVuY3Rpb24ocykgeyByZXR1cm4gdXJsKHMpOyB9LFxuICAgICAgICBwZWckYzc0ID0geyB0eXBlOiBcIm90aGVyXCIsIGRlc2NyaXB0aW9uOiBcImludGVnZXJcIiB9LFxuICAgICAgICBwZWckYzc1ID0gbnVsbCxcbiAgICAgICAgcGVnJGM3NiA9IC9eWydcIl0vLFxuICAgICAgICBwZWckYzc3ID0geyB0eXBlOiBcImNsYXNzXCIsIHZhbHVlOiBcIlsnXFxcIl1cIiwgZGVzY3JpcHRpb246IFwiWydcXFwiXVwiIH0sXG4gICAgICAgIHBlZyRjNzggPSAvXlswLTldLyxcbiAgICAgICAgcGVnJGM3OSA9IHsgdHlwZTogXCJjbGFzc1wiLCB2YWx1ZTogXCJbMC05XVwiLCBkZXNjcmlwdGlvbjogXCJbMC05XVwiIH0sXG4gICAgICAgIHBlZyRjODAgPSBmdW5jdGlvbihkaWdpdHMpIHsgcmV0dXJuIHBhcnNlSW50KGRpZ2l0cy5qb2luKFwiXCIpLCAxMCk7IH0sXG4gICAgICAgIHBlZyRjODEgPSB7IHR5cGU6IFwib3RoZXJcIiwgZGVzY3JpcHRpb246IFwic3RyaW5nXCIgfSxcbiAgICAgICAgcGVnJGM4MiA9IFwiXFxcIlwiLFxuICAgICAgICBwZWckYzgzID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwiXFxcIlwiLCBkZXNjcmlwdGlvbjogXCJcXFwiXFxcXFxcXCJcXFwiXCIgfSxcbiAgICAgICAgcGVnJGM4NCA9IGZ1bmN0aW9uKGNoYXJzKSB7IHJldHVybiBjaGFycy5qb2luKFwiXCIpOyB9LFxuICAgICAgICBwZWckYzg1ID0gXCInXCIsXG4gICAgICAgIHBlZyRjODYgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCInXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCInXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjODcgPSB2b2lkIDAsXG4gICAgICAgIHBlZyRjODggPSAvXltcIlxcXFxdLyxcbiAgICAgICAgcGVnJGM4OSA9IHsgdHlwZTogXCJjbGFzc1wiLCB2YWx1ZTogXCJbXFxcIlxcXFxcXFxcXVwiLCBkZXNjcmlwdGlvbjogXCJbXFxcIlxcXFxcXFxcXVwiIH0sXG4gICAgICAgIHBlZyRjOTAgPSB7IHR5cGU6IFwiYW55XCIsIGRlc2NyaXB0aW9uOiBcImFueSBjaGFyYWN0ZXJcIiB9LFxuICAgICAgICBwZWckYzkxID0gZnVuY3Rpb24oY2hhcikgeyByZXR1cm4gY2hhcjsgfSxcbiAgICAgICAgcGVnJGM5MiA9IFwiXFxcXFwiLFxuICAgICAgICBwZWckYzkzID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwiXFxcXFwiLCBkZXNjcmlwdGlvbjogXCJcXFwiXFxcXFxcXFxcXFwiXCIgfSxcbiAgICAgICAgcGVnJGM5NCA9IC9eWydcXFxcXS8sXG4gICAgICAgIHBlZyRjOTUgPSB7IHR5cGU6IFwiY2xhc3NcIiwgdmFsdWU6IFwiWydcXFxcXFxcXF1cIiwgZGVzY3JpcHRpb246IFwiWydcXFxcXFxcXF1cIiB9LFxuICAgICAgICBwZWckYzk2ID0gL15bJ1wiXFxcXF0vLFxuICAgICAgICBwZWckYzk3ID0geyB0eXBlOiBcImNsYXNzXCIsIHZhbHVlOiBcIlsnXFxcIlxcXFxcXFxcXVwiLCBkZXNjcmlwdGlvbjogXCJbJ1xcXCJcXFxcXFxcXF1cIiB9LFxuICAgICAgICBwZWckYzk4ID0gXCJuXCIsXG4gICAgICAgIHBlZyRjOTkgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJuXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJuXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjMTAwID0gZnVuY3Rpb24oKSB7IHJldHVybiBcIlxcblwiOyB9LFxuICAgICAgICBwZWckYzEwMSA9IFwiclwiLFxuICAgICAgICBwZWckYzEwMiA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcInJcIiwgZGVzY3JpcHRpb246IFwiXFxcInJcXFwiXCIgfSxcbiAgICAgICAgcGVnJGMxMDMgPSBmdW5jdGlvbigpIHsgcmV0dXJuIFwiXFxyXCI7IH0sXG4gICAgICAgIHBlZyRjMTA0ID0gXCJ0XCIsXG4gICAgICAgIHBlZyRjMTA1ID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwidFwiLCBkZXNjcmlwdGlvbjogXCJcXFwidFxcXCJcIiB9LFxuICAgICAgICBwZWckYzEwNiA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gXCJcXHRcIjsgfSxcblxuICAgICAgICBwZWckY3VyclBvcyAgICAgICAgICA9IDAsXG4gICAgICAgIHBlZyRyZXBvcnRlZFBvcyAgICAgID0gMCxcbiAgICAgICAgcGVnJGNhY2hlZFBvcyAgICAgICAgPSAwLFxuICAgICAgICBwZWckY2FjaGVkUG9zRGV0YWlscyA9IHsgbGluZTogMSwgY29sdW1uOiAxLCBzZWVuQ1I6IGZhbHNlIH0sXG4gICAgICAgIHBlZyRtYXhGYWlsUG9zICAgICAgID0gMCxcbiAgICAgICAgcGVnJG1heEZhaWxFeHBlY3RlZCAgPSBbXSxcbiAgICAgICAgcGVnJHNpbGVudEZhaWxzICAgICAgPSAwLFxuXG4gICAgICAgIHBlZyRyZXN1bHQ7XG5cbiAgICBpZiAoXCJzdGFydFJ1bGVcIiBpbiBvcHRpb25zKSB7XG4gICAgICBpZiAoIShvcHRpb25zLnN0YXJ0UnVsZSBpbiBwZWckc3RhcnRSdWxlRnVuY3Rpb25zKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW4ndCBzdGFydCBwYXJzaW5nIGZyb20gcnVsZSBcXFwiXCIgKyBvcHRpb25zLnN0YXJ0UnVsZSArIFwiXFxcIi5cIik7XG4gICAgICB9XG5cbiAgICAgIHBlZyRzdGFydFJ1bGVGdW5jdGlvbiA9IHBlZyRzdGFydFJ1bGVGdW5jdGlvbnNbb3B0aW9ucy5zdGFydFJ1bGVdO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRleHQoKSB7XG4gICAgICByZXR1cm4gaW5wdXQuc3Vic3RyaW5nKHBlZyRyZXBvcnRlZFBvcywgcGVnJGN1cnJQb3MpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9mZnNldCgpIHtcbiAgICAgIHJldHVybiBwZWckcmVwb3J0ZWRQb3M7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGluZSgpIHtcbiAgICAgIHJldHVybiBwZWckY29tcHV0ZVBvc0RldGFpbHMocGVnJHJlcG9ydGVkUG9zKS5saW5lO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvbHVtbigpIHtcbiAgICAgIHJldHVybiBwZWckY29tcHV0ZVBvc0RldGFpbHMocGVnJHJlcG9ydGVkUG9zKS5jb2x1bW47XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZXhwZWN0ZWQoZGVzY3JpcHRpb24pIHtcbiAgICAgIHRocm93IHBlZyRidWlsZEV4Y2VwdGlvbihcbiAgICAgICAgbnVsbCxcbiAgICAgICAgW3sgdHlwZTogXCJvdGhlclwiLCBkZXNjcmlwdGlvbjogZGVzY3JpcHRpb24gfV0sXG4gICAgICAgIHBlZyRyZXBvcnRlZFBvc1xuICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlcnJvcihtZXNzYWdlKSB7XG4gICAgICB0aHJvdyBwZWckYnVpbGRFeGNlcHRpb24obWVzc2FnZSwgbnVsbCwgcGVnJHJlcG9ydGVkUG9zKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckY29tcHV0ZVBvc0RldGFpbHMocG9zKSB7XG4gICAgICBmdW5jdGlvbiBhZHZhbmNlKGRldGFpbHMsIHN0YXJ0UG9zLCBlbmRQb3MpIHtcbiAgICAgICAgdmFyIHAsIGNoO1xuXG4gICAgICAgIGZvciAocCA9IHN0YXJ0UG9zOyBwIDwgZW5kUG9zOyBwKyspIHtcbiAgICAgICAgICBjaCA9IGlucHV0LmNoYXJBdChwKTtcbiAgICAgICAgICBpZiAoY2ggPT09IFwiXFxuXCIpIHtcbiAgICAgICAgICAgIGlmICghZGV0YWlscy5zZWVuQ1IpIHsgZGV0YWlscy5saW5lKys7IH1cbiAgICAgICAgICAgIGRldGFpbHMuY29sdW1uID0gMTtcbiAgICAgICAgICAgIGRldGFpbHMuc2VlbkNSID0gZmFsc2U7XG4gICAgICAgICAgfSBlbHNlIGlmIChjaCA9PT0gXCJcXHJcIiB8fCBjaCA9PT0gXCJcXHUyMDI4XCIgfHwgY2ggPT09IFwiXFx1MjAyOVwiKSB7XG4gICAgICAgICAgICBkZXRhaWxzLmxpbmUrKztcbiAgICAgICAgICAgIGRldGFpbHMuY29sdW1uID0gMTtcbiAgICAgICAgICAgIGRldGFpbHMuc2VlbkNSID0gdHJ1ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGV0YWlscy5jb2x1bW4rKztcbiAgICAgICAgICAgIGRldGFpbHMuc2VlbkNSID0gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChwZWckY2FjaGVkUG9zICE9PSBwb3MpIHtcbiAgICAgICAgaWYgKHBlZyRjYWNoZWRQb3MgPiBwb3MpIHtcbiAgICAgICAgICBwZWckY2FjaGVkUG9zID0gMDtcbiAgICAgICAgICBwZWckY2FjaGVkUG9zRGV0YWlscyA9IHsgbGluZTogMSwgY29sdW1uOiAxLCBzZWVuQ1I6IGZhbHNlIH07XG4gICAgICAgIH1cbiAgICAgICAgYWR2YW5jZShwZWckY2FjaGVkUG9zRGV0YWlscywgcGVnJGNhY2hlZFBvcywgcG9zKTtcbiAgICAgICAgcGVnJGNhY2hlZFBvcyA9IHBvcztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHBlZyRjYWNoZWRQb3NEZXRhaWxzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRmYWlsKGV4cGVjdGVkKSB7XG4gICAgICBpZiAocGVnJGN1cnJQb3MgPCBwZWckbWF4RmFpbFBvcykgeyByZXR1cm47IH1cblxuICAgICAgaWYgKHBlZyRjdXJyUG9zID4gcGVnJG1heEZhaWxQb3MpIHtcbiAgICAgICAgcGVnJG1heEZhaWxQb3MgPSBwZWckY3VyclBvcztcbiAgICAgICAgcGVnJG1heEZhaWxFeHBlY3RlZCA9IFtdO1xuICAgICAgfVxuXG4gICAgICBwZWckbWF4RmFpbEV4cGVjdGVkLnB1c2goZXhwZWN0ZWQpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRidWlsZEV4Y2VwdGlvbihtZXNzYWdlLCBleHBlY3RlZCwgcG9zKSB7XG4gICAgICBmdW5jdGlvbiBjbGVhbnVwRXhwZWN0ZWQoZXhwZWN0ZWQpIHtcbiAgICAgICAgdmFyIGkgPSAxO1xuXG4gICAgICAgIGV4cGVjdGVkLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAgIGlmIChhLmRlc2NyaXB0aW9uIDwgYi5kZXNjcmlwdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICAgIH0gZWxzZSBpZiAoYS5kZXNjcmlwdGlvbiA+IGIuZGVzY3JpcHRpb24pIHtcbiAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHdoaWxlIChpIDwgZXhwZWN0ZWQubGVuZ3RoKSB7XG4gICAgICAgICAgaWYgKGV4cGVjdGVkW2kgLSAxXSA9PT0gZXhwZWN0ZWRbaV0pIHtcbiAgICAgICAgICAgIGV4cGVjdGVkLnNwbGljZShpLCAxKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaSsrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBidWlsZE1lc3NhZ2UoZXhwZWN0ZWQsIGZvdW5kKSB7XG4gICAgICAgIGZ1bmN0aW9uIHN0cmluZ0VzY2FwZShzKSB7XG4gICAgICAgICAgZnVuY3Rpb24gaGV4KGNoKSB7IHJldHVybiBjaC5jaGFyQ29kZUF0KDApLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpOyB9XG5cbiAgICAgICAgICByZXR1cm4gc1xuICAgICAgICAgICAgLnJlcGxhY2UoL1xcXFwvZywgICAnXFxcXFxcXFwnKVxuICAgICAgICAgICAgLnJlcGxhY2UoL1wiL2csICAgICdcXFxcXCInKVxuICAgICAgICAgICAgLnJlcGxhY2UoL1xceDA4L2csICdcXFxcYicpXG4gICAgICAgICAgICAucmVwbGFjZSgvXFx0L2csICAgJ1xcXFx0JylcbiAgICAgICAgICAgIC5yZXBsYWNlKC9cXG4vZywgICAnXFxcXG4nKVxuICAgICAgICAgICAgLnJlcGxhY2UoL1xcZi9nLCAgICdcXFxcZicpXG4gICAgICAgICAgICAucmVwbGFjZSgvXFxyL2csICAgJ1xcXFxyJylcbiAgICAgICAgICAgIC5yZXBsYWNlKC9bXFx4MDAtXFx4MDdcXHgwQlxceDBFXFx4MEZdL2csIGZ1bmN0aW9uKGNoKSB7IHJldHVybiAnXFxcXHgwJyArIGhleChjaCk7IH0pXG4gICAgICAgICAgICAucmVwbGFjZSgvW1xceDEwLVxceDFGXFx4ODAtXFx4RkZdL2csICAgIGZ1bmN0aW9uKGNoKSB7IHJldHVybiAnXFxcXHgnICArIGhleChjaCk7IH0pXG4gICAgICAgICAgICAucmVwbGFjZSgvW1xcdTAxODAtXFx1MEZGRl0vZywgICAgICAgICBmdW5jdGlvbihjaCkgeyByZXR1cm4gJ1xcXFx1MCcgKyBoZXgoY2gpOyB9KVxuICAgICAgICAgICAgLnJlcGxhY2UoL1tcXHUxMDgwLVxcdUZGRkZdL2csICAgICAgICAgZnVuY3Rpb24oY2gpIHsgcmV0dXJuICdcXFxcdScgICsgaGV4KGNoKTsgfSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZXhwZWN0ZWREZXNjcyA9IG5ldyBBcnJheShleHBlY3RlZC5sZW5ndGgpLFxuICAgICAgICAgICAgZXhwZWN0ZWREZXNjLCBmb3VuZERlc2MsIGk7XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGV4cGVjdGVkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgZXhwZWN0ZWREZXNjc1tpXSA9IGV4cGVjdGVkW2ldLmRlc2NyaXB0aW9uO1xuICAgICAgICB9XG5cbiAgICAgICAgZXhwZWN0ZWREZXNjID0gZXhwZWN0ZWQubGVuZ3RoID4gMVxuICAgICAgICAgID8gZXhwZWN0ZWREZXNjcy5zbGljZSgwLCAtMSkuam9pbihcIiwgXCIpXG4gICAgICAgICAgICAgICsgXCIgb3IgXCJcbiAgICAgICAgICAgICAgKyBleHBlY3RlZERlc2NzW2V4cGVjdGVkLmxlbmd0aCAtIDFdXG4gICAgICAgICAgOiBleHBlY3RlZERlc2NzWzBdO1xuXG4gICAgICAgIGZvdW5kRGVzYyA9IGZvdW5kID8gXCJcXFwiXCIgKyBzdHJpbmdFc2NhcGUoZm91bmQpICsgXCJcXFwiXCIgOiBcImVuZCBvZiBpbnB1dFwiO1xuXG4gICAgICAgIHJldHVybiBcIkV4cGVjdGVkIFwiICsgZXhwZWN0ZWREZXNjICsgXCIgYnV0IFwiICsgZm91bmREZXNjICsgXCIgZm91bmQuXCI7XG4gICAgICB9XG5cbiAgICAgIHZhciBwb3NEZXRhaWxzID0gcGVnJGNvbXB1dGVQb3NEZXRhaWxzKHBvcyksXG4gICAgICAgICAgZm91bmQgICAgICA9IHBvcyA8IGlucHV0Lmxlbmd0aCA/IGlucHV0LmNoYXJBdChwb3MpIDogbnVsbDtcblxuICAgICAgaWYgKGV4cGVjdGVkICE9PSBudWxsKSB7XG4gICAgICAgIGNsZWFudXBFeHBlY3RlZChleHBlY3RlZCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBuZXcgU3ludGF4RXJyb3IoXG4gICAgICAgIG1lc3NhZ2UgIT09IG51bGwgPyBtZXNzYWdlIDogYnVpbGRNZXNzYWdlKGV4cGVjdGVkLCBmb3VuZCksXG4gICAgICAgIGV4cGVjdGVkLFxuICAgICAgICBmb3VuZCxcbiAgICAgICAgcG9zLFxuICAgICAgICBwb3NEZXRhaWxzLmxpbmUsXG4gICAgICAgIHBvc0RldGFpbHMuY29sdW1uXG4gICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRwYXJzZXN0YXJ0KCkge1xuICAgICAgdmFyIHMwLCBzMSwgczIsIHMzO1xuXG4gICAgICBwZWckc2lsZW50RmFpbHMrKztcbiAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICBzMSA9IHBlZyRwYXJzZV9fKCk7XG4gICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczIgPSBwZWckcGFyc2VPckV4cHIoKTtcbiAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgczMgPSBwZWckcGFyc2VfXygpO1xuICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICBzMSA9IHBlZyRjMihzMik7XG4gICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgfVxuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgIHMxID0gW107XG4gICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgIHMxID0gcGVnJGM0KCk7XG4gICAgICAgIH1cbiAgICAgICAgczAgPSBzMTtcbiAgICAgIH1cbiAgICAgIHBlZyRzaWxlbnRGYWlscy0tO1xuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzApOyB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2V3cygpIHtcbiAgICAgIHZhciBzMCwgczE7XG5cbiAgICAgIHBlZyRzaWxlbnRGYWlscysrO1xuICAgICAgaWYgKHBlZyRjNi50ZXN0KGlucHV0LmNoYXJBdChwZWckY3VyclBvcykpKSB7XG4gICAgICAgIHMwID0gaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKTtcbiAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHMwID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzcpOyB9XG4gICAgICB9XG4gICAgICBwZWckc2lsZW50RmFpbHMtLTtcbiAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM1KTsgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlY2MoKSB7XG4gICAgICB2YXIgczAsIHMxO1xuXG4gICAgICBwZWckc2lsZW50RmFpbHMrKztcbiAgICAgIGlmIChwZWckYzkudGVzdChpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpKSkge1xuICAgICAgICBzMCA9IGlucHV0LmNoYXJBdChwZWckY3VyclBvcyk7XG4gICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzMCA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGMxMCk7IH1cbiAgICAgIH1cbiAgICAgIHBlZyRzaWxlbnRGYWlscy0tO1xuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzgpOyB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2VfXygpIHtcbiAgICAgIHZhciBzMCwgczE7XG5cbiAgICAgIHBlZyRzaWxlbnRGYWlscysrO1xuICAgICAgczAgPSBbXTtcbiAgICAgIHMxID0gcGVnJHBhcnNld3MoKTtcbiAgICAgIHdoaWxlIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMC5wdXNoKHMxKTtcbiAgICAgICAgczEgPSBwZWckcGFyc2V3cygpO1xuICAgICAgfVxuICAgICAgcGVnJHNpbGVudEZhaWxzLS07XG4gICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjMTEpOyB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2VPckV4cHIoKSB7XG4gICAgICB2YXIgczAsIHMxLCBzMiwgczMsIHM0LCBzNTtcblxuICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgIHMxID0gcGVnJHBhcnNlQW5kRXhwcigpO1xuICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMyID0gcGVnJHBhcnNlX18oKTtcbiAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSAxMjQpIHtcbiAgICAgICAgICAgIHMzID0gcGVnJGMxMjtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHMzID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGMxMyk7IH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBzNCA9IHBlZyRwYXJzZV9fKCk7XG4gICAgICAgICAgICBpZiAoczQgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgczUgPSBwZWckcGFyc2VPckV4cHIoKTtcbiAgICAgICAgICAgICAgaWYgKHM1ICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgICAgczEgPSBwZWckYzE0KHMxLCBzNSk7XG4gICAgICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgIH1cbiAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMCA9IHBlZyRwYXJzZUFuZEV4cHIoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHMwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRwYXJzZUFuZEV4cHIoKSB7XG4gICAgICB2YXIgczAsIHMxLCBzMiwgczMsIHM0LCBzNTtcblxuICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgIHMxID0gcGVnJHBhcnNlTm90RXhwcigpO1xuICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMyID0gcGVnJHBhcnNlX18oKTtcbiAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSAzOCkge1xuICAgICAgICAgICAgczMgPSBwZWckYzE1O1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgczMgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzE2KTsgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHM0ID0gcGVnJHBhcnNlX18oKTtcbiAgICAgICAgICAgIGlmIChzNCAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICBzNSA9IHBlZyRwYXJzZUFuZEV4cHIoKTtcbiAgICAgICAgICAgICAgaWYgKHM1ICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgICAgczEgPSBwZWckYzE3KHMxLCBzNSk7XG4gICAgICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgIH1cbiAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgICBzMSA9IHBlZyRwYXJzZU5vdEV4cHIoKTtcbiAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgczIgPSBbXTtcbiAgICAgICAgICBzMyA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICB3aGlsZSAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgczIucHVzaChzMyk7XG4gICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgczIgPSBwZWckYzE7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgczMgPSBwZWckcGFyc2VBbmRFeHByKCk7XG4gICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgIHMxID0gcGVnJGMxNyhzMSwgczMpO1xuICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBzMCA9IHBlZyRwYXJzZU5vdEV4cHIoKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlTm90RXhwcigpIHtcbiAgICAgIHZhciBzMCwgczEsIHMyLCBzMztcblxuICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgIGlmIChpbnB1dC5jaGFyQ29kZUF0KHBlZyRjdXJyUG9zKSA9PT0gMzMpIHtcbiAgICAgICAgczEgPSBwZWckYzE4O1xuICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjMTkpOyB9XG4gICAgICB9XG4gICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczIgPSBwZWckcGFyc2VfXygpO1xuICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBzMyA9IHBlZyRwYXJzZU5vdEV4cHIoKTtcbiAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgczEgPSBwZWckYzIwKHMzKTtcbiAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICB9XG4gICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczAgPSBwZWckcGFyc2VCaW5kaW5nRXhwcigpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlQmluZGluZ0V4cHIoKSB7XG4gICAgICB2YXIgczAsIHMxLCBzMiwgczMsIHM0LCBzNTtcblxuICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgIGlmIChpbnB1dC5jaGFyQ29kZUF0KHBlZyRjdXJyUG9zKSA9PT0gNDApIHtcbiAgICAgICAgczEgPSBwZWckYzIxO1xuICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjMjIpOyB9XG4gICAgICB9XG4gICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczIgPSBwZWckcGFyc2VfXygpO1xuICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBzMyA9IHBlZyRwYXJzZU9yRXhwcigpO1xuICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgczQgPSBwZWckcGFyc2VfXygpO1xuICAgICAgICAgICAgaWYgKHM0ICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgIGlmIChpbnB1dC5jaGFyQ29kZUF0KHBlZyRjdXJyUG9zKSA9PT0gNDEpIHtcbiAgICAgICAgICAgICAgICBzNSA9IHBlZyRjMjM7XG4gICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzNSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzI0KTsgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChzNSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgICAgIHMxID0gcGVnJGMyNShzMyk7XG4gICAgICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgIH1cbiAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMCA9IHBlZyRwYXJzZUV4cHIoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHMwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRwYXJzZUV4cHIoKSB7XG4gICAgICB2YXIgczA7XG5cbiAgICAgIHMwID0gcGVnJHBhcnNlTnVsbGFyeUV4cHIoKTtcbiAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMCA9IHBlZyRwYXJzZVVuYXJ5RXhwcigpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlTnVsbGFyeUV4cHIoKSB7XG4gICAgICB2YXIgczAsIHMxO1xuXG4gICAgICBzMCA9IHBlZyRwYXJzZUJvb2xlYW5MaXRlcmFsKCk7XG4gICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgaWYgKGlucHV0LnN1YnN0cihwZWckY3VyclBvcywgMikgPT09IHBlZyRjMjYpIHtcbiAgICAgICAgICBzMSA9IHBlZyRjMjY7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzI3KTsgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgIHMxID0gcGVnJGMyOCgpO1xuICAgICAgICB9XG4gICAgICAgIHMwID0gczE7XG4gICAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgICAgaWYgKGlucHV0LnN1YnN0cihwZWckY3VyclBvcywgMikgPT09IHBlZyRjMjkpIHtcbiAgICAgICAgICAgIHMxID0gcGVnJGMyOTtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zICs9IDI7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGMzMCk7IH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgIHMxID0gcGVnJGMzMSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDIpID09PSBwZWckYzMyKSB7XG4gICAgICAgICAgICAgIHMxID0gcGVnJGMzMjtcbiAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzMzKTsgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgICBzMSA9IHBlZyRjMzQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgICAgaWYgKGlucHV0LnN1YnN0cihwZWckY3VyclBvcywgMikgPT09IHBlZyRjMzUpIHtcbiAgICAgICAgICAgICAgICBzMSA9IHBlZyRjMzU7XG4gICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMjtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzM2KTsgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgICAgIHMxID0gcGVnJGMzNygpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2VCb29sZWFuTGl0ZXJhbCgpIHtcbiAgICAgIHZhciBzMCwgczE7XG5cbiAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICBpZiAoaW5wdXQuc3Vic3RyKHBlZyRjdXJyUG9zLCA0KSA9PT0gcGVnJGMzOCkge1xuICAgICAgICBzMSA9IHBlZyRjMzg7XG4gICAgICAgIHBlZyRjdXJyUG9zICs9IDQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGMzOSk7IH1cbiAgICAgIH1cbiAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgczEgPSBwZWckYzQwKCk7XG4gICAgICB9XG4gICAgICBzMCA9IHMxO1xuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDUpID09PSBwZWckYzQxKSB7XG4gICAgICAgICAgczEgPSBwZWckYzQxO1xuICAgICAgICAgIHBlZyRjdXJyUG9zICs9IDU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM0Mik7IH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICBzMSA9IHBlZyRjNDMoKTtcbiAgICAgICAgfVxuICAgICAgICBzMCA9IHMxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlVW5hcnlFeHByKCkge1xuICAgICAgdmFyIHMwLCBzMSwgczIsIHMzO1xuXG4gICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgaWYgKGlucHV0LnN1YnN0cihwZWckY3VyclBvcywgMikgPT09IHBlZyRjNDQpIHtcbiAgICAgICAgczEgPSBwZWckYzQ0O1xuICAgICAgICBwZWckY3VyclBvcyArPSAyO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjNDUpOyB9XG4gICAgICB9XG4gICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczIgPSBbXTtcbiAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICB3aGlsZSAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHMyLnB1c2goczMpO1xuICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBzMyA9IHBlZyRwYXJzZUludGVnZXJMaXRlcmFsKCk7XG4gICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgIHMxID0gcGVnJGM0NihzMyk7XG4gICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgfVxuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDIpID09PSBwZWckYzQ3KSB7XG4gICAgICAgICAgczEgPSBwZWckYzQ3O1xuICAgICAgICAgIHBlZyRjdXJyUG9zICs9IDI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM0OCk7IH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBzMiA9IFtdO1xuICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHdoaWxlIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVN0cmluZ0xpdGVyYWwoKTtcbiAgICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgczEgPSBwZWckYzQ5KHMzKTtcbiAgICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICBpZiAoaW5wdXQuc3Vic3RyKHBlZyRjdXJyUG9zLCAyKSA9PT0gcGVnJGM1MCkge1xuICAgICAgICAgICAgczEgPSBwZWckYzUwO1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzUxKTsgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHMyID0gW107XG4gICAgICAgICAgICBzMyA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgczIucHVzaChzMyk7XG4gICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVN0cmluZ0xpdGVyYWwoKTtcbiAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgICAgczEgPSBwZWckYzUyKHMzKTtcbiAgICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDMpID09PSBwZWckYzUzKSB7XG4gICAgICAgICAgICAgIHMxID0gcGVnJGM1MztcbiAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzU0KTsgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgIHMyID0gW107XG4gICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgczIgPSBwZWckYzE7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2VTdHJpbmdMaXRlcmFsKCk7XG4gICAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgIHMxID0gcGVnJGM1NShzMyk7XG4gICAgICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDMpID09PSBwZWckYzU2KSB7XG4gICAgICAgICAgICAgICAgczEgPSBwZWckYzU2O1xuICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zICs9IDM7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM1Nyk7IH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICBzMiA9IFtdO1xuICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgIHdoaWxlIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVN0cmluZ0xpdGVyYWwoKTtcbiAgICAgICAgICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzU4KHMzKTtcbiAgICAgICAgICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgICAgICBpZiAoaW5wdXQuc3Vic3RyKHBlZyRjdXJyUG9zLCAyKSA9PT0gcGVnJGM1OSkge1xuICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzU5O1xuICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzYwKTsgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgIHMyID0gW107XG4gICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICAgICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgczIucHVzaChzMyk7XG4gICAgICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVN0cmluZ0xpdGVyYWwoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzYxKHMzKTtcbiAgICAgICAgICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDIpID09PSBwZWckYzYyKSB7XG4gICAgICAgICAgICAgICAgICAgIHMxID0gcGVnJGM2MjtcbiAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMjtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzYzKTsgfVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgIHMyID0gW107XG4gICAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgczIgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2VTdHJpbmdMaXRlcmFsKCk7XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHMxID0gcGVnJGM2NChzMyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDMpID09PSBwZWckYzY1KSB7XG4gICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzY1O1xuICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zICs9IDM7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM2Nik7IH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICBzMiA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVN0cmluZ0xpdGVyYWwoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzY3KHMzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXQuc3Vic3RyKHBlZyRjdXJyUG9zLCAzKSA9PT0gcGVnJGM2OCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzY4O1xuICAgICAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMztcbiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzY5KTsgfVxuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHMyID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgczIucHVzaChzMyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVN0cmluZ0xpdGVyYWwoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzcwKHMzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDIpID09PSBwZWckYzcxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMxID0gcGVnJGM3MTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzcyKTsgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMyID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgczIgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2VTdHJpbmdMaXRlcmFsKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMxID0gcGVnJGM3MyhzMyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMxID0gcGVnJHBhcnNlU3RyaW5nTGl0ZXJhbCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzMSA9IHBlZyRjNzMoczEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2VJbnRlZ2VyTGl0ZXJhbCgpIHtcbiAgICAgIHZhciBzMCwgczEsIHMyLCBzMztcblxuICAgICAgcGVnJHNpbGVudEZhaWxzKys7XG4gICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgaWYgKHBlZyRjNzYudGVzdChpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpKSkge1xuICAgICAgICBzMSA9IGlucHV0LmNoYXJBdChwZWckY3VyclBvcyk7XG4gICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM3Nyk7IH1cbiAgICAgIH1cbiAgICAgIGlmIChzMSA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMSA9IHBlZyRjNzU7XG4gICAgICB9XG4gICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczIgPSBbXTtcbiAgICAgICAgaWYgKHBlZyRjNzgudGVzdChpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpKSkge1xuICAgICAgICAgIHMzID0gaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKTtcbiAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMzID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjNzkpOyB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgIGlmIChwZWckYzc4LnRlc3QoaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKSkpIHtcbiAgICAgICAgICAgICAgczMgPSBpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpO1xuICAgICAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgczMgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjNzkpOyB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMyID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIGlmIChwZWckYzc2LnRlc3QoaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKSkpIHtcbiAgICAgICAgICAgIHMzID0gaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKTtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHMzID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM3Nyk7IH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHMzID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBzMyA9IHBlZyRjNzU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICBzMSA9IHBlZyRjODAoczIpO1xuICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgIH1cbiAgICAgIHBlZyRzaWxlbnRGYWlscy0tO1xuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzc0KTsgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlU3RyaW5nTGl0ZXJhbCgpIHtcbiAgICAgIHZhciBzMCwgczEsIHMyLCBzMztcblxuICAgICAgcGVnJHNpbGVudEZhaWxzKys7XG4gICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSAzNCkge1xuICAgICAgICBzMSA9IHBlZyRjODI7XG4gICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM4Myk7IH1cbiAgICAgIH1cbiAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMiA9IFtdO1xuICAgICAgICBzMyA9IHBlZyRwYXJzZURvdWJsZVN0cmluZ0NoYXIoKTtcbiAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgczIucHVzaChzMyk7XG4gICAgICAgICAgczMgPSBwZWckcGFyc2VEb3VibGVTdHJpbmdDaGFyKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSAzNCkge1xuICAgICAgICAgICAgczMgPSBwZWckYzgyO1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgczMgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzgzKTsgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgczEgPSBwZWckYzg0KHMyKTtcbiAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICB9XG4gICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSAzOSkge1xuICAgICAgICAgIHMxID0gcGVnJGM4NTtcbiAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjODYpOyB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgczIgPSBbXTtcbiAgICAgICAgICBzMyA9IHBlZyRwYXJzZVNpbmdsZVN0cmluZ0NoYXIoKTtcbiAgICAgICAgICB3aGlsZSAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHMyLnB1c2goczMpO1xuICAgICAgICAgICAgczMgPSBwZWckcGFyc2VTaW5nbGVTdHJpbmdDaGFyKCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSAzOSkge1xuICAgICAgICAgICAgICBzMyA9IHBlZyRjODU7XG4gICAgICAgICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzMyA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM4Nik7IH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgczEgPSBwZWckYzg0KHMyKTtcbiAgICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICBzMSA9IHBlZyRjdXJyUG9zO1xuICAgICAgICAgIHBlZyRzaWxlbnRGYWlscysrO1xuICAgICAgICAgIHMyID0gcGVnJHBhcnNlY2MoKTtcbiAgICAgICAgICBwZWckc2lsZW50RmFpbHMtLTtcbiAgICAgICAgICBpZiAoczIgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHMxID0gcGVnJGM4NztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMTtcbiAgICAgICAgICAgIHMxID0gcGVnJGMxO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHMyID0gW107XG4gICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVVucXVvdGVkU3RyaW5nQ2hhcigpO1xuICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgIHdoaWxlIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgIHMyLnB1c2goczMpO1xuICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNlVW5xdW90ZWRTdHJpbmdDaGFyKCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHMyID0gcGVnJGMxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgICBzMSA9IHBlZyRjODQoczIpO1xuICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHBlZyRzaWxlbnRGYWlscy0tO1xuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzgxKTsgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlRG91YmxlU3RyaW5nQ2hhcigpIHtcbiAgICAgIHZhciBzMCwgczEsIHMyO1xuXG4gICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgczEgPSBwZWckY3VyclBvcztcbiAgICAgIHBlZyRzaWxlbnRGYWlscysrO1xuICAgICAgaWYgKHBlZyRjODgudGVzdChpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpKSkge1xuICAgICAgICBzMiA9IGlucHV0LmNoYXJBdChwZWckY3VyclBvcyk7XG4gICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzMiA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM4OSk7IH1cbiAgICAgIH1cbiAgICAgIHBlZyRzaWxlbnRGYWlscy0tO1xuICAgICAgaWYgKHMyID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMxID0gcGVnJGM4NztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczE7XG4gICAgICAgIHMxID0gcGVnJGMxO1xuICAgICAgfVxuICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIGlmIChpbnB1dC5sZW5ndGggPiBwZWckY3VyclBvcykge1xuICAgICAgICAgIHMyID0gaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKTtcbiAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMyID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjOTApOyB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgczEgPSBwZWckYzkxKHMyKTtcbiAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgfVxuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgIGlmIChpbnB1dC5jaGFyQ29kZUF0KHBlZyRjdXJyUG9zKSA9PT0gOTIpIHtcbiAgICAgICAgICBzMSA9IHBlZyRjOTI7XG4gICAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzkzKTsgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHMyID0gcGVnJHBhcnNlRXNjYXBlU2VxdWVuY2UoKTtcbiAgICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgczEgPSBwZWckYzkxKHMyKTtcbiAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlU2luZ2xlU3RyaW5nQ2hhcigpIHtcbiAgICAgIHZhciBzMCwgczEsIHMyO1xuXG4gICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgczEgPSBwZWckY3VyclBvcztcbiAgICAgIHBlZyRzaWxlbnRGYWlscysrO1xuICAgICAgaWYgKHBlZyRjOTQudGVzdChpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpKSkge1xuICAgICAgICBzMiA9IGlucHV0LmNoYXJBdChwZWckY3VyclBvcyk7XG4gICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzMiA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM5NSk7IH1cbiAgICAgIH1cbiAgICAgIHBlZyRzaWxlbnRGYWlscy0tO1xuICAgICAgaWYgKHMyID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMxID0gcGVnJGM4NztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczE7XG4gICAgICAgIHMxID0gcGVnJGMxO1xuICAgICAgfVxuICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIGlmIChpbnB1dC5sZW5ndGggPiBwZWckY3VyclBvcykge1xuICAgICAgICAgIHMyID0gaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKTtcbiAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMyID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjOTApOyB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgczEgPSBwZWckYzkxKHMyKTtcbiAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgfVxuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgIGlmIChpbnB1dC5jaGFyQ29kZUF0KHBlZyRjdXJyUG9zKSA9PT0gOTIpIHtcbiAgICAgICAgICBzMSA9IHBlZyRjOTI7XG4gICAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzkzKTsgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHMyID0gcGVnJHBhcnNlRXNjYXBlU2VxdWVuY2UoKTtcbiAgICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgczEgPSBwZWckYzkxKHMyKTtcbiAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlVW5xdW90ZWRTdHJpbmdDaGFyKCkge1xuICAgICAgdmFyIHMwLCBzMSwgczI7XG5cbiAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICBzMSA9IHBlZyRjdXJyUG9zO1xuICAgICAgcGVnJHNpbGVudEZhaWxzKys7XG4gICAgICBzMiA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICBwZWckc2lsZW50RmFpbHMtLTtcbiAgICAgIGlmIChzMiA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMSA9IHBlZyRjODc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwZWckY3VyclBvcyA9IHMxO1xuICAgICAgICBzMSA9IHBlZyRjMTtcbiAgICAgIH1cbiAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBpZiAoaW5wdXQubGVuZ3RoID4gcGVnJGN1cnJQb3MpIHtcbiAgICAgICAgICBzMiA9IGlucHV0LmNoYXJBdChwZWckY3VyclBvcyk7XG4gICAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzMiA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzkwKTsgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgIHMxID0gcGVnJGM5MShzMik7XG4gICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHMwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRwYXJzZUVzY2FwZVNlcXVlbmNlKCkge1xuICAgICAgdmFyIHMwLCBzMTtcblxuICAgICAgaWYgKHBlZyRjOTYudGVzdChpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpKSkge1xuICAgICAgICBzMCA9IGlucHV0LmNoYXJBdChwZWckY3VyclBvcyk7XG4gICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzMCA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM5Nyk7IH1cbiAgICAgIH1cbiAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgICBpZiAoaW5wdXQuY2hhckNvZGVBdChwZWckY3VyclBvcykgPT09IDExMCkge1xuICAgICAgICAgIHMxID0gcGVnJGM5ODtcbiAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjOTkpOyB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgczEgPSBwZWckYzEwMCgpO1xuICAgICAgICB9XG4gICAgICAgIHMwID0gczE7XG4gICAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSAxMTQpIHtcbiAgICAgICAgICAgIHMxID0gcGVnJGMxMDE7XG4gICAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjMTAyKTsgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgczEgPSBwZWckYzEwMygpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgIGlmIChpbnB1dC5jaGFyQ29kZUF0KHBlZyRjdXJyUG9zKSA9PT0gMTE2KSB7XG4gICAgICAgICAgICAgIHMxID0gcGVnJGMxMDQ7XG4gICAgICAgICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGMxMDUpOyB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgIHMxID0gcGVnJGMxMDYoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cblxuICAgIGZ1bmN0aW9uIG9yKGZpcnN0LCBzZWNvbmQpIHtcbiAgICAgICAgLy8gQWRkIGV4cGxpY2l0IGZ1bmN0aW9uIG5hbWVzIHRvIGVhc2UgZGVidWdnaW5nLlxuICAgICAgICBmdW5jdGlvbiBvckZpbHRlcigpIHtcbiAgICAgICAgICAgIHJldHVybiBmaXJzdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHNlY29uZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgICAgIG9yRmlsdGVyLmRlc2MgPSBmaXJzdC5kZXNjICsgXCIgb3IgXCIgKyBzZWNvbmQuZGVzYztcbiAgICAgICAgcmV0dXJuIG9yRmlsdGVyO1xuICAgIH1cbiAgICBmdW5jdGlvbiBhbmQoZmlyc3QsIHNlY29uZCkge1xuICAgICAgICBmdW5jdGlvbiBhbmRGaWx0ZXIoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmlyc3QuYXBwbHkodGhpcywgYXJndW1lbnRzKSAmJiBzZWNvbmQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfVxuICAgICAgICBhbmRGaWx0ZXIuZGVzYyA9IGZpcnN0LmRlc2MgKyBcIiBhbmQgXCIgKyBzZWNvbmQuZGVzYztcbiAgICAgICAgcmV0dXJuIGFuZEZpbHRlcjtcbiAgICB9XG4gICAgZnVuY3Rpb24gbm90KGV4cHIpIHtcbiAgICAgICAgZnVuY3Rpb24gbm90RmlsdGVyKCkge1xuICAgICAgICAgICAgcmV0dXJuICFleHByLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH1cbiAgICAgICAgbm90RmlsdGVyLmRlc2MgPSBcIm5vdCBcIiArIGV4cHIuZGVzYztcbiAgICAgICAgcmV0dXJuIG5vdEZpbHRlcjtcbiAgICB9XG4gICAgZnVuY3Rpb24gYmluZGluZyhleHByKSB7XG4gICAgICAgIGZ1bmN0aW9uIGJpbmRpbmdGaWx0ZXIoKSB7XG4gICAgICAgICAgICByZXR1cm4gZXhwci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgICAgIGJpbmRpbmdGaWx0ZXIuZGVzYyA9IFwiKFwiICsgZXhwci5kZXNjICsgXCIpXCI7XG4gICAgICAgIHJldHVybiBiaW5kaW5nRmlsdGVyO1xuICAgIH1cbiAgICBmdW5jdGlvbiB0cnVlRmlsdGVyKGZsb3cpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHRydWVGaWx0ZXIuZGVzYyA9IFwidHJ1ZVwiO1xuICAgIGZ1bmN0aW9uIGZhbHNlRmlsdGVyKGZsb3cpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmYWxzZUZpbHRlci5kZXNjID0gXCJmYWxzZVwiO1xuXG4gICAgdmFyIEFTU0VUX1RZUEVTID0gW1xuICAgICAgICBuZXcgUmVnRXhwKFwidGV4dC9qYXZhc2NyaXB0XCIpLFxuICAgICAgICBuZXcgUmVnRXhwKFwiYXBwbGljYXRpb24veC1qYXZhc2NyaXB0XCIpLFxuICAgICAgICBuZXcgUmVnRXhwKFwiYXBwbGljYXRpb24vamF2YXNjcmlwdFwiKSxcbiAgICAgICAgbmV3IFJlZ0V4cChcInRleHQvY3NzXCIpLFxuICAgICAgICBuZXcgUmVnRXhwKFwiaW1hZ2UvLipcIiksXG4gICAgICAgIG5ldyBSZWdFeHAoXCJhcHBsaWNhdGlvbi94LXNob2Nrd2F2ZS1mbGFzaFwiKVxuICAgIF07XG4gICAgZnVuY3Rpb24gYXNzZXRGaWx0ZXIoZmxvdykge1xuICAgICAgICBpZiAoZmxvdy5yZXNwb25zZSkge1xuICAgICAgICAgICAgdmFyIGN0ID0gUmVzcG9uc2VVdGlscy5nZXRDb250ZW50VHlwZShmbG93LnJlc3BvbnNlKTtcbiAgICAgICAgICAgIHZhciBpID0gQVNTRVRfVFlQRVMubGVuZ3RoO1xuICAgICAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgICAgIGlmIChBU1NFVF9UWVBFU1tpXS50ZXN0KGN0KSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBhc3NldEZpbHRlci5kZXNjID0gXCJpcyBhc3NldFwiO1xuICAgIGZ1bmN0aW9uIHJlc3BvbnNlQ29kZShjb2RlKXtcbiAgICAgICAgZnVuY3Rpb24gcmVzcG9uc2VDb2RlRmlsdGVyKGZsb3cpe1xuICAgICAgICAgICAgcmV0dXJuIGZsb3cucmVzcG9uc2UgJiYgZmxvdy5yZXNwb25zZS5jb2RlID09PSBjb2RlO1xuICAgICAgICB9XG4gICAgICAgIHJlc3BvbnNlQ29kZUZpbHRlci5kZXNjID0gXCJyZXNwLiBjb2RlIGlzIFwiICsgY29kZTtcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlQ29kZUZpbHRlcjtcbiAgICB9XG4gICAgZnVuY3Rpb24gZG9tYWluKHJlZ2V4KXtcbiAgICAgICAgcmVnZXggPSBuZXcgUmVnRXhwKHJlZ2V4LCBcImlcIik7XG4gICAgICAgIGZ1bmN0aW9uIGRvbWFpbkZpbHRlcihmbG93KXtcbiAgICAgICAgICAgIHJldHVybiBmbG93LnJlcXVlc3QgJiYgcmVnZXgudGVzdChmbG93LnJlcXVlc3QuaG9zdCk7XG4gICAgICAgIH1cbiAgICAgICAgZG9tYWluRmlsdGVyLmRlc2MgPSBcImRvbWFpbiBtYXRjaGVzIFwiICsgcmVnZXg7XG4gICAgICAgIHJldHVybiBkb21haW5GaWx0ZXI7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGVycm9yRmlsdGVyKGZsb3cpe1xuICAgICAgICByZXR1cm4gISFmbG93LmVycm9yO1xuICAgIH1cbiAgICBlcnJvckZpbHRlci5kZXNjID0gXCJoYXMgZXJyb3JcIjtcbiAgICBmdW5jdGlvbiBoZWFkZXIocmVnZXgpe1xuICAgICAgICByZWdleCA9IG5ldyBSZWdFeHAocmVnZXgsIFwiaVwiKTtcbiAgICAgICAgZnVuY3Rpb24gaGVhZGVyRmlsdGVyKGZsb3cpe1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAoZmxvdy5yZXF1ZXN0ICYmIFJlcXVlc3RVdGlscy5tYXRjaF9oZWFkZXIoZmxvdy5yZXF1ZXN0LCByZWdleCkpXG4gICAgICAgICAgICAgICAgfHxcbiAgICAgICAgICAgICAgICAoZmxvdy5yZXNwb25zZSAmJiBSZXNwb25zZVV0aWxzLm1hdGNoX2hlYWRlcihmbG93LnJlc3BvbnNlLCByZWdleCkpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGhlYWRlckZpbHRlci5kZXNjID0gXCJoZWFkZXIgbWF0Y2hlcyBcIiArIHJlZ2V4O1xuICAgICAgICByZXR1cm4gaGVhZGVyRmlsdGVyO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXF1ZXN0SGVhZGVyKHJlZ2V4KXtcbiAgICAgICAgcmVnZXggPSBuZXcgUmVnRXhwKHJlZ2V4LCBcImlcIik7XG4gICAgICAgIGZ1bmN0aW9uIHJlcXVlc3RIZWFkZXJGaWx0ZXIoZmxvdyl7XG4gICAgICAgICAgICByZXR1cm4gKGZsb3cucmVxdWVzdCAmJiBSZXF1ZXN0VXRpbHMubWF0Y2hfaGVhZGVyKGZsb3cucmVxdWVzdCwgcmVnZXgpKTtcbiAgICAgICAgfVxuICAgICAgICByZXF1ZXN0SGVhZGVyRmlsdGVyLmRlc2MgPSBcInJlcS4gaGVhZGVyIG1hdGNoZXMgXCIgKyByZWdleDtcbiAgICAgICAgcmV0dXJuIHJlcXVlc3RIZWFkZXJGaWx0ZXI7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlc3BvbnNlSGVhZGVyKHJlZ2V4KXtcbiAgICAgICAgcmVnZXggPSBuZXcgUmVnRXhwKHJlZ2V4LCBcImlcIik7XG4gICAgICAgIGZ1bmN0aW9uIHJlc3BvbnNlSGVhZGVyRmlsdGVyKGZsb3cpe1xuICAgICAgICAgICAgcmV0dXJuIChmbG93LnJlc3BvbnNlICYmIFJlc3BvbnNlVXRpbHMubWF0Y2hfaGVhZGVyKGZsb3cucmVzcG9uc2UsIHJlZ2V4KSk7XG4gICAgICAgIH1cbiAgICAgICAgcmVzcG9uc2VIZWFkZXJGaWx0ZXIuZGVzYyA9IFwicmVzcC4gaGVhZGVyIG1hdGNoZXMgXCIgKyByZWdleDtcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlSGVhZGVyRmlsdGVyO1xuICAgIH1cbiAgICBmdW5jdGlvbiBtZXRob2QocmVnZXgpe1xuICAgICAgICByZWdleCA9IG5ldyBSZWdFeHAocmVnZXgsIFwiaVwiKTtcbiAgICAgICAgZnVuY3Rpb24gbWV0aG9kRmlsdGVyKGZsb3cpe1xuICAgICAgICAgICAgcmV0dXJuIGZsb3cucmVxdWVzdCAmJiByZWdleC50ZXN0KGZsb3cucmVxdWVzdC5tZXRob2QpO1xuICAgICAgICB9XG4gICAgICAgIG1ldGhvZEZpbHRlci5kZXNjID0gXCJtZXRob2QgbWF0Y2hlcyBcIiArIHJlZ2V4O1xuICAgICAgICByZXR1cm4gbWV0aG9kRmlsdGVyO1xuICAgIH1cbiAgICBmdW5jdGlvbiBub1Jlc3BvbnNlRmlsdGVyKGZsb3cpe1xuICAgICAgICByZXR1cm4gZmxvdy5yZXF1ZXN0ICYmICFmbG93LnJlc3BvbnNlO1xuICAgIH1cbiAgICBub1Jlc3BvbnNlRmlsdGVyLmRlc2MgPSBcImhhcyBubyByZXNwb25zZVwiO1xuICAgIGZ1bmN0aW9uIHJlc3BvbnNlRmlsdGVyKGZsb3cpe1xuICAgICAgICByZXR1cm4gISFmbG93LnJlc3BvbnNlO1xuICAgIH1cbiAgICByZXNwb25zZUZpbHRlci5kZXNjID0gXCJoYXMgcmVzcG9uc2VcIjtcblxuICAgIGZ1bmN0aW9uIGNvbnRlbnRUeXBlKHJlZ2V4KXtcbiAgICAgICAgcmVnZXggPSBuZXcgUmVnRXhwKHJlZ2V4LCBcImlcIik7XG4gICAgICAgIGZ1bmN0aW9uIGNvbnRlbnRUeXBlRmlsdGVyKGZsb3cpe1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAoZmxvdy5yZXF1ZXN0ICYmIHJlZ2V4LnRlc3QoUmVxdWVzdFV0aWxzLmdldENvbnRlbnRUeXBlKGZsb3cucmVxdWVzdCkpKVxuICAgICAgICAgICAgICAgIHx8XG4gICAgICAgICAgICAgICAgKGZsb3cucmVzcG9uc2UgJiYgcmVnZXgudGVzdChSZXNwb25zZVV0aWxzLmdldENvbnRlbnRUeXBlKGZsb3cucmVzcG9uc2UpKSlcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgY29udGVudFR5cGVGaWx0ZXIuZGVzYyA9IFwiY29udGVudCB0eXBlIG1hdGNoZXMgXCIgKyByZWdleDtcbiAgICAgICAgcmV0dXJuIGNvbnRlbnRUeXBlRmlsdGVyO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXF1ZXN0Q29udGVudFR5cGUocmVnZXgpe1xuICAgICAgICByZWdleCA9IG5ldyBSZWdFeHAocmVnZXgsIFwiaVwiKTtcbiAgICAgICAgZnVuY3Rpb24gcmVxdWVzdENvbnRlbnRUeXBlRmlsdGVyKGZsb3cpe1xuICAgICAgICAgICAgcmV0dXJuIGZsb3cucmVxdWVzdCAmJiByZWdleC50ZXN0KFJlcXVlc3RVdGlscy5nZXRDb250ZW50VHlwZShmbG93LnJlcXVlc3QpKTtcbiAgICAgICAgfVxuICAgICAgICByZXF1ZXN0Q29udGVudFR5cGVGaWx0ZXIuZGVzYyA9IFwicmVxLiBjb250ZW50IHR5cGUgbWF0Y2hlcyBcIiArIHJlZ2V4O1xuICAgICAgICByZXR1cm4gcmVxdWVzdENvbnRlbnRUeXBlRmlsdGVyO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXNwb25zZUNvbnRlbnRUeXBlKHJlZ2V4KXtcbiAgICAgICAgcmVnZXggPSBuZXcgUmVnRXhwKHJlZ2V4LCBcImlcIik7XG4gICAgICAgIGZ1bmN0aW9uIHJlc3BvbnNlQ29udGVudFR5cGVGaWx0ZXIoZmxvdyl7XG4gICAgICAgICAgICByZXR1cm4gZmxvdy5yZXNwb25zZSAmJiByZWdleC50ZXN0KFJlc3BvbnNlVXRpbHMuZ2V0Q29udGVudFR5cGUoZmxvdy5yZXNwb25zZSkpO1xuICAgICAgICB9XG4gICAgICAgIHJlc3BvbnNlQ29udGVudFR5cGVGaWx0ZXIuZGVzYyA9IFwicmVzcC4gY29udGVudCB0eXBlIG1hdGNoZXMgXCIgKyByZWdleDtcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlQ29udGVudFR5cGVGaWx0ZXI7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHVybChyZWdleCl7XG4gICAgICAgIHJlZ2V4ID0gbmV3IFJlZ0V4cChyZWdleCwgXCJpXCIpO1xuICAgICAgICBmdW5jdGlvbiB1cmxGaWx0ZXIoZmxvdyl7XG4gICAgICAgICAgICByZXR1cm4gZmxvdy5yZXF1ZXN0ICYmIHJlZ2V4LnRlc3QoUmVxdWVzdFV0aWxzLnByZXR0eV91cmwoZmxvdy5yZXF1ZXN0KSk7XG4gICAgICAgIH1cbiAgICAgICAgdXJsRmlsdGVyLmRlc2MgPSBcInVybCBtYXRjaGVzIFwiICsgcmVnZXg7XG4gICAgICAgIHJldHVybiB1cmxGaWx0ZXI7XG4gICAgfVxuXG5cbiAgICBwZWckcmVzdWx0ID0gcGVnJHN0YXJ0UnVsZUZ1bmN0aW9uKCk7XG5cbiAgICBpZiAocGVnJHJlc3VsdCAhPT0gcGVnJEZBSUxFRCAmJiBwZWckY3VyclBvcyA9PT0gaW5wdXQubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gcGVnJHJlc3VsdDtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHBlZyRyZXN1bHQgIT09IHBlZyRGQUlMRUQgJiYgcGVnJGN1cnJQb3MgPCBpbnB1dC5sZW5ndGgpIHtcbiAgICAgICAgcGVnJGZhaWwoeyB0eXBlOiBcImVuZFwiLCBkZXNjcmlwdGlvbjogXCJlbmQgb2YgaW5wdXRcIiB9KTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgcGVnJGJ1aWxkRXhjZXB0aW9uKG51bGwsIHBlZyRtYXhGYWlsRXhwZWN0ZWQsIHBlZyRtYXhGYWlsUG9zKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIFN5bnRheEVycm9yOiBTeW50YXhFcnJvcixcbiAgICBwYXJzZTogICAgICAgcGFyc2VcbiAgfTtcbn0pKCk7XG4vKiBqc2hpbnQgaWdub3JlOmVuZCAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IEZpbHQ7XG4iLCJ2YXIgXyA9IHJlcXVpcmUoXCJsb2Rhc2hcIik7XG5cbnZhciBfTWVzc2FnZVV0aWxzID0ge1xuICAgIGdldENvbnRlbnRUeXBlOiBmdW5jdGlvbiAobWVzc2FnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRfZmlyc3RfaGVhZGVyKG1lc3NhZ2UsIC9eQ29udGVudC1UeXBlJC9pKTtcbiAgICB9LFxuICAgIGdldF9maXJzdF9oZWFkZXI6IGZ1bmN0aW9uIChtZXNzYWdlLCByZWdleCkge1xuICAgICAgICAvL0ZJWE1FOiBDYWNoZSBJbnZhbGlkYXRpb24uXG4gICAgICAgIGlmICghbWVzc2FnZS5faGVhZGVyTG9va3VwcylcbiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShtZXNzYWdlLCBcIl9oZWFkZXJMb29rdXBzXCIsIHtcbiAgICAgICAgICAgICAgICB2YWx1ZToge30sXG4gICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICB3cml0YWJsZTogZmFsc2VcbiAgICAgICAgICAgIH0pO1xuICAgICAgICBpZiAoIShyZWdleCBpbiBtZXNzYWdlLl9oZWFkZXJMb29rdXBzKSkge1xuICAgICAgICAgICAgdmFyIGhlYWRlcjtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5oZWFkZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEhbWVzc2FnZS5oZWFkZXJzW2ldWzBdLm1hdGNoKHJlZ2V4KSkge1xuICAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBtZXNzYWdlLmhlYWRlcnNbaV07XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1lc3NhZ2UuX2hlYWRlckxvb2t1cHNbcmVnZXhdID0gaGVhZGVyID8gaGVhZGVyWzFdIDogdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZXNzYWdlLl9oZWFkZXJMb29rdXBzW3JlZ2V4XTtcbiAgICB9LFxuICAgIG1hdGNoX2hlYWRlcjogZnVuY3Rpb24gKG1lc3NhZ2UsIHJlZ2V4KSB7XG4gICAgICAgIHZhciBoZWFkZXJzID0gbWVzc2FnZS5oZWFkZXJzO1xuICAgICAgICB2YXIgaSA9IGhlYWRlcnMubGVuZ3RoO1xuICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICBpZiAocmVnZXgudGVzdChoZWFkZXJzW2ldLmpvaW4oXCIgXCIpKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBoZWFkZXJzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG59O1xuXG52YXIgZGVmYXVsdFBvcnRzID0ge1xuICAgIFwiaHR0cFwiOiA4MCxcbiAgICBcImh0dHBzXCI6IDQ0M1xufTtcblxudmFyIFJlcXVlc3RVdGlscyA9IF8uZXh0ZW5kKF9NZXNzYWdlVXRpbHMsIHtcbiAgICBwcmV0dHlfaG9zdDogZnVuY3Rpb24gKHJlcXVlc3QpIHtcbiAgICAgICAgLy9GSVhNRTogQWRkIGhvc3RoZWFkZXJcbiAgICAgICAgcmV0dXJuIHJlcXVlc3QuaG9zdDtcbiAgICB9LFxuICAgIHByZXR0eV91cmw6IGZ1bmN0aW9uIChyZXF1ZXN0KSB7XG4gICAgICAgIHZhciBwb3J0ID0gXCJcIjtcbiAgICAgICAgaWYgKGRlZmF1bHRQb3J0c1tyZXF1ZXN0LnNjaGVtZV0gIT09IHJlcXVlc3QucG9ydCkge1xuICAgICAgICAgICAgcG9ydCA9IFwiOlwiICsgcmVxdWVzdC5wb3J0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXF1ZXN0LnNjaGVtZSArIFwiOi8vXCIgKyB0aGlzLnByZXR0eV9ob3N0KHJlcXVlc3QpICsgcG9ydCArIHJlcXVlc3QucGF0aDtcbiAgICB9XG59KTtcblxudmFyIFJlc3BvbnNlVXRpbHMgPSBfLmV4dGVuZChfTWVzc2FnZVV0aWxzLCB7fSk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgUmVzcG9uc2VVdGlsczogUmVzcG9uc2VVdGlscyxcbiAgICBSZXF1ZXN0VXRpbHM6IFJlcXVlc3RVdGlsc1xuXG59IiwiXG52YXIgXyA9IHJlcXVpcmUoXCJsb2Rhc2hcIik7XG52YXIgJCA9IHJlcXVpcmUoXCJqcXVlcnlcIik7XG5cbnZhciB1dGlscyA9IHJlcXVpcmUoXCIuLi91dGlscy5qc1wiKTtcbnZhciBhY3Rpb25zID0gcmVxdWlyZShcIi4uL2FjdGlvbnMuanNcIik7XG52YXIgZGlzcGF0Y2hlciA9IHJlcXVpcmUoXCIuLi9kaXNwYXRjaGVyLmpzXCIpO1xuXG5cbmZ1bmN0aW9uIExpc3RTdG9yZSgpIHtcbiAgICB1dGlscy5FdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcbiAgICB0aGlzLnJlc2V0KCk7XG59XG5fLmV4dGVuZChMaXN0U3RvcmUucHJvdG90eXBlLCB1dGlscy5FdmVudEVtaXR0ZXIucHJvdG90eXBlLCB7XG4gICAgYWRkOiBmdW5jdGlvbiAoZWxlbSkge1xuICAgICAgICBpZiAoZWxlbS5pZCBpbiB0aGlzLl9wb3NfbWFwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcG9zX21hcFtlbGVtLmlkXSA9IHRoaXMubGlzdC5sZW5ndGg7XG4gICAgICAgIHRoaXMubGlzdC5wdXNoKGVsZW0pO1xuICAgICAgICB0aGlzLmVtaXQoXCJhZGRcIiwgZWxlbSk7XG4gICAgfSxcbiAgICB1cGRhdGU6IGZ1bmN0aW9uIChlbGVtKSB7XG4gICAgICAgIGlmICghKGVsZW0uaWQgaW4gdGhpcy5fcG9zX21hcCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxpc3RbdGhpcy5fcG9zX21hcFtlbGVtLmlkXV0gPSBlbGVtO1xuICAgICAgICB0aGlzLmVtaXQoXCJ1cGRhdGVcIiwgZWxlbSk7XG4gICAgfSxcbiAgICByZW1vdmU6IGZ1bmN0aW9uIChlbGVtX2lkKSB7XG4gICAgICAgIGlmICghKGVsZW1faWQgaW4gdGhpcy5fcG9zX21hcCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxpc3Quc3BsaWNlKHRoaXMuX3Bvc19tYXBbZWxlbV9pZF0sIDEpO1xuICAgICAgICB0aGlzLl9idWlsZF9tYXAoKTtcbiAgICAgICAgdGhpcy5lbWl0KFwicmVtb3ZlXCIsIGVsZW1faWQpO1xuICAgIH0sXG4gICAgcmVzZXQ6IGZ1bmN0aW9uIChlbGVtcykge1xuICAgICAgICB0aGlzLmxpc3QgPSBlbGVtcyB8fCBbXTtcbiAgICAgICAgdGhpcy5fYnVpbGRfbWFwKCk7XG4gICAgICAgIHRoaXMuZW1pdChcInJlY2FsY3VsYXRlXCIpO1xuICAgIH0sXG4gICAgX2J1aWxkX21hcDogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9wb3NfbWFwID0ge307XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5saXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgZWxlbSA9IHRoaXMubGlzdFtpXTtcbiAgICAgICAgICAgIHRoaXMuX3Bvc19tYXBbZWxlbS5pZF0gPSBpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBnZXQ6IGZ1bmN0aW9uIChlbGVtX2lkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RbdGhpcy5fcG9zX21hcFtlbGVtX2lkXV07XG4gICAgfSxcbiAgICBpbmRleDogZnVuY3Rpb24gKGVsZW1faWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3Bvc19tYXBbZWxlbV9pZF07XG4gICAgfVxufSk7XG5cblxuZnVuY3Rpb24gRGljdFN0b3JlKCkge1xuICAgIHV0aWxzLkV2ZW50RW1pdHRlci5jYWxsKHRoaXMpO1xuICAgIHRoaXMucmVzZXQoKTtcbn1cbl8uZXh0ZW5kKERpY3RTdG9yZS5wcm90b3R5cGUsIHV0aWxzLkV2ZW50RW1pdHRlci5wcm90b3R5cGUsIHtcbiAgICB1cGRhdGU6IGZ1bmN0aW9uIChkaWN0KSB7XG4gICAgICAgIF8ubWVyZ2UodGhpcy5kaWN0LCBkaWN0KTtcbiAgICAgICAgdGhpcy5lbWl0KFwicmVjYWxjdWxhdGVcIik7XG4gICAgfSxcbiAgICByZXNldDogZnVuY3Rpb24gKGRpY3QpIHtcbiAgICAgICAgdGhpcy5kaWN0ID0gZGljdCB8fCB7fTtcbiAgICAgICAgdGhpcy5lbWl0KFwicmVjYWxjdWxhdGVcIik7XG4gICAgfVxufSk7XG5cbmZ1bmN0aW9uIExpdmVTdG9yZU1peGluKHR5cGUpIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuXG4gICAgdGhpcy5fdXBkYXRlc19iZWZvcmVfZmV0Y2ggPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fZmV0Y2h4aHIgPSBmYWxzZTtcblxuICAgIHRoaXMuaGFuZGxlID0gdGhpcy5oYW5kbGUuYmluZCh0aGlzKTtcbiAgICBkaXNwYXRjaGVyLkFwcERpc3BhdGNoZXIucmVnaXN0ZXIodGhpcy5oYW5kbGUpO1xuXG4gICAgLy8gQXZvaWQgZG91YmxlLWZldGNoIG9uIHN0YXJ0dXAuXG4gICAgaWYgKCEod2luZG93LndzICYmIHdpbmRvdy53cy5yZWFkeVN0YXRlID09PSBXZWJTb2NrZXQuQ09OTkVDVElORykpIHtcbiAgICAgICAgdGhpcy5mZXRjaCgpO1xuICAgIH1cbn1cbl8uZXh0ZW5kKExpdmVTdG9yZU1peGluLnByb3RvdHlwZSwge1xuICAgIGhhbmRsZTogZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIGlmIChldmVudC50eXBlID09PSBhY3Rpb25zLkFjdGlvblR5cGVzLkNPTk5FQ1RJT05fT1BFTikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmV0Y2goKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXZlbnQudHlwZSA9PT0gdGhpcy50eXBlKSB7XG4gICAgICAgICAgICBpZiAoZXZlbnQuY21kID09PSBhY3Rpb25zLlN0b3JlQ21kcy5SRVNFVCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmV0Y2goZXZlbnQuZGF0YSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX3VwZGF0ZXNfYmVmb3JlX2ZldGNoKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJkZWZlciB1cGRhdGVcIiwgZXZlbnQpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZXNfYmVmb3JlX2ZldGNoLnB1c2goZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzW2V2ZW50LmNtZF0oZXZlbnQuZGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGNsb3NlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGRpc3BhdGNoZXIuQXBwRGlzcGF0Y2hlci51bnJlZ2lzdGVyKHRoaXMuaGFuZGxlKTtcbiAgICB9LFxuICAgIGZldGNoOiBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICBjb25zb2xlLmxvZyhcImZldGNoIFwiICsgdGhpcy50eXBlKTtcbiAgICAgICAgaWYgKHRoaXMuX2ZldGNoeGhyKSB7XG4gICAgICAgICAgICB0aGlzLl9mZXRjaHhoci5hYm9ydCgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3VwZGF0ZXNfYmVmb3JlX2ZldGNoID0gW107IC8vIChKUzogZW1wdHkgYXJyYXkgaXMgdHJ1ZSlcbiAgICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlX2ZldGNoKGRhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fZmV0Y2h4aHIgPSAkLmdldEpTT04oXCIvXCIgKyB0aGlzLnR5cGUpXG4gICAgICAgICAgICAgICAgLmRvbmUoZnVuY3Rpb24gKG1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVfZmV0Y2gobWVzc2FnZS5kYXRhKTtcbiAgICAgICAgICAgICAgICB9LmJpbmQodGhpcykpXG4gICAgICAgICAgICAgICAgLmZhaWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBFdmVudExvZ0FjdGlvbnMuYWRkX2V2ZW50KFwiQ291bGQgbm90IGZldGNoIFwiICsgdGhpcy50eXBlKTtcbiAgICAgICAgICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBoYW5kbGVfZmV0Y2g6IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgIHRoaXMuX2ZldGNoeGhyID0gZmFsc2U7XG4gICAgICAgIGNvbnNvbGUubG9nKHRoaXMudHlwZSArIFwiIGZldGNoZWQuXCIsIHRoaXMuX3VwZGF0ZXNfYmVmb3JlX2ZldGNoKTtcbiAgICAgICAgdGhpcy5yZXNldChkYXRhKTtcbiAgICAgICAgdmFyIHVwZGF0ZXMgPSB0aGlzLl91cGRhdGVzX2JlZm9yZV9mZXRjaDtcbiAgICAgICAgdGhpcy5fdXBkYXRlc19iZWZvcmVfZmV0Y2ggPSBmYWxzZTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB1cGRhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZSh1cGRhdGVzW2ldKTtcbiAgICAgICAgfVxuICAgIH0sXG59KTtcblxuZnVuY3Rpb24gTGl2ZUxpc3RTdG9yZSh0eXBlKSB7XG4gICAgTGlzdFN0b3JlLmNhbGwodGhpcyk7XG4gICAgTGl2ZVN0b3JlTWl4aW4uY2FsbCh0aGlzLCB0eXBlKTtcbn1cbl8uZXh0ZW5kKExpdmVMaXN0U3RvcmUucHJvdG90eXBlLCBMaXN0U3RvcmUucHJvdG90eXBlLCBMaXZlU3RvcmVNaXhpbi5wcm90b3R5cGUpO1xuXG5mdW5jdGlvbiBMaXZlRGljdFN0b3JlKHR5cGUpIHtcbiAgICBEaWN0U3RvcmUuY2FsbCh0aGlzKTtcbiAgICBMaXZlU3RvcmVNaXhpbi5jYWxsKHRoaXMsIHR5cGUpO1xufVxuXy5leHRlbmQoTGl2ZURpY3RTdG9yZS5wcm90b3R5cGUsIERpY3RTdG9yZS5wcm90b3R5cGUsIExpdmVTdG9yZU1peGluLnByb3RvdHlwZSk7XG5cblxuZnVuY3Rpb24gRmxvd1N0b3JlKCkge1xuICAgIHJldHVybiBuZXcgTGl2ZUxpc3RTdG9yZShhY3Rpb25zLkFjdGlvblR5cGVzLkZMT1dfU1RPUkUpO1xufVxuXG5mdW5jdGlvbiBTZXR0aW5nc1N0b3JlKCkge1xuICAgIHJldHVybiBuZXcgTGl2ZURpY3RTdG9yZShhY3Rpb25zLkFjdGlvblR5cGVzLlNFVFRJTkdTX1NUT1JFKTtcbn1cblxuZnVuY3Rpb24gRXZlbnRMb2dTdG9yZSgpIHtcbiAgICBMaXZlTGlzdFN0b3JlLmNhbGwodGhpcywgYWN0aW9ucy5BY3Rpb25UeXBlcy5FVkVOVF9TVE9SRSk7XG59XG5fLmV4dGVuZChFdmVudExvZ1N0b3JlLnByb3RvdHlwZSwgTGl2ZUxpc3RTdG9yZS5wcm90b3R5cGUsIHtcbiAgICBmZXRjaDogZnVuY3Rpb24oKXtcbiAgICAgICAgTGl2ZUxpc3RTdG9yZS5wcm90b3R5cGUuZmV0Y2guYXBwbHkodGhpcywgYXJndW1lbnRzKTtcblxuICAgICAgICAvLyBNYWtlIHN1cmUgdG8gZGlzcGxheSB1cGRhdGVzIGV2ZW4gaWYgZmV0Y2hpbmcgYWxsIGV2ZW50cyBmYWlsZWQuXG4gICAgICAgIC8vIFRoaXMgd2F5LCB3ZSBjYW4gc2VuZCBcImZldGNoIGZhaWxlZFwiIGxvZyBtZXNzYWdlcyB0byB0aGUgbG9nLlxuICAgICAgICBpZih0aGlzLl9mZXRjaHhocil7XG4gICAgICAgICAgICB0aGlzLl9mZXRjaHhoci5mYWlsKGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVfZmV0Y2gobnVsbCk7XG4gICAgICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgICB9XG4gICAgfVxufSk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgRXZlbnRMb2dTdG9yZTogRXZlbnRMb2dTdG9yZSxcbiAgICBTZXR0aW5nc1N0b3JlOiBTZXR0aW5nc1N0b3JlLFxuICAgIEZsb3dTdG9yZTogRmxvd1N0b3JlXG59OyIsInZhciBfID0gcmVxdWlyZShcImxvZGFzaFwiKTtcblxudmFyIHV0aWxzID0gcmVxdWlyZShcIi4uL3V0aWxzLmpzXCIpO1xuXG5mdW5jdGlvbiBTb3J0QnlTdG9yZU9yZGVyKGVsZW0pIHtcbiAgICByZXR1cm4gdGhpcy5zdG9yZS5pbmRleChlbGVtLmlkKTtcbn1cblxudmFyIGRlZmF1bHRfc29ydCA9IFNvcnRCeVN0b3JlT3JkZXI7XG52YXIgZGVmYXVsdF9maWx0ID0gZnVuY3Rpb24oZWxlbSl7XG4gICAgcmV0dXJuIHRydWU7XG59O1xuXG5mdW5jdGlvbiBTdG9yZVZpZXcoc3RvcmUsIGZpbHQsIHNvcnRmdW4pIHtcbiAgICB1dGlscy5FdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcbiAgICBmaWx0ID0gZmlsdCB8fCBkZWZhdWx0X2ZpbHQ7XG4gICAgc29ydGZ1biA9IHNvcnRmdW4gfHwgZGVmYXVsdF9zb3J0O1xuXG4gICAgdGhpcy5zdG9yZSA9IHN0b3JlO1xuXG4gICAgdGhpcy5hZGQgPSB0aGlzLmFkZC5iaW5kKHRoaXMpO1xuICAgIHRoaXMudXBkYXRlID0gdGhpcy51cGRhdGUuYmluZCh0aGlzKTtcbiAgICB0aGlzLnJlbW92ZSA9IHRoaXMucmVtb3ZlLmJpbmQodGhpcyk7XG4gICAgdGhpcy5yZWNhbGN1bGF0ZSA9IHRoaXMucmVjYWxjdWxhdGUuYmluZCh0aGlzKTtcbiAgICB0aGlzLnN0b3JlLmFkZExpc3RlbmVyKFwiYWRkXCIsIHRoaXMuYWRkKTtcbiAgICB0aGlzLnN0b3JlLmFkZExpc3RlbmVyKFwidXBkYXRlXCIsIHRoaXMudXBkYXRlKTtcbiAgICB0aGlzLnN0b3JlLmFkZExpc3RlbmVyKFwicmVtb3ZlXCIsIHRoaXMucmVtb3ZlKTtcbiAgICB0aGlzLnN0b3JlLmFkZExpc3RlbmVyKFwicmVjYWxjdWxhdGVcIiwgdGhpcy5yZWNhbGN1bGF0ZSk7XG5cbiAgICB0aGlzLnJlY2FsY3VsYXRlKGZpbHQsIHNvcnRmdW4pO1xufVxuXG5fLmV4dGVuZChTdG9yZVZpZXcucHJvdG90eXBlLCB1dGlscy5FdmVudEVtaXR0ZXIucHJvdG90eXBlLCB7XG4gICAgY2xvc2U6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zdG9yZS5yZW1vdmVMaXN0ZW5lcihcImFkZFwiLCB0aGlzLmFkZCk7XG4gICAgICAgIHRoaXMuc3RvcmUucmVtb3ZlTGlzdGVuZXIoXCJ1cGRhdGVcIiwgdGhpcy51cGRhdGUpO1xuICAgICAgICB0aGlzLnN0b3JlLnJlbW92ZUxpc3RlbmVyKFwicmVtb3ZlXCIsIHRoaXMucmVtb3ZlKTtcbiAgICAgICAgdGhpcy5zdG9yZS5yZW1vdmVMaXN0ZW5lcihcInJlY2FsY3VsYXRlXCIsIHRoaXMucmVjYWxjdWxhdGUpO1xuICAgICAgICB9LFxuICAgICAgICByZWNhbGN1bGF0ZTogZnVuY3Rpb24gKGZpbHQsIHNvcnRmdW4pIHtcbiAgICAgICAgaWYgKGZpbHQpIHtcbiAgICAgICAgICAgIHRoaXMuZmlsdCA9IGZpbHQuYmluZCh0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc29ydGZ1bikge1xuICAgICAgICAgICAgdGhpcy5zb3J0ZnVuID0gc29ydGZ1bi5iaW5kKHRoaXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5saXN0ID0gdGhpcy5zdG9yZS5saXN0LmZpbHRlcih0aGlzLmZpbHQpO1xuICAgICAgICB0aGlzLmxpc3Quc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc29ydGZ1bihhKSAtIHRoaXMuc29ydGZ1bihiKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5lbWl0KFwicmVjYWxjdWxhdGVcIik7XG4gICAgfSxcbiAgICBpbmRleDogZnVuY3Rpb24gKGVsZW0pIHtcbiAgICAgICAgcmV0dXJuIF8uc29ydGVkSW5kZXgodGhpcy5saXN0LCBlbGVtLCB0aGlzLnNvcnRmdW4pO1xuICAgIH0sXG4gICAgYWRkOiBmdW5jdGlvbiAoZWxlbSkge1xuICAgICAgICBpZiAodGhpcy5maWx0KGVsZW0pKSB7XG4gICAgICAgICAgICB2YXIgaWR4ID0gdGhpcy5pbmRleChlbGVtKTtcbiAgICAgICAgICAgIGlmIChpZHggPT09IHRoaXMubGlzdC5sZW5ndGgpIHsgLy9oYXBwZW5zIG9mdGVuLCAucHVzaCBpcyB3YXkgZmFzdGVyLlxuICAgICAgICAgICAgICAgIHRoaXMubGlzdC5wdXNoKGVsZW0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxpc3Quc3BsaWNlKGlkeCwgMCwgZWxlbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVtaXQoXCJhZGRcIiwgZWxlbSwgaWR4KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgdXBkYXRlOiBmdW5jdGlvbiAoZWxlbSkge1xuICAgICAgICB2YXIgaWR4O1xuICAgICAgICB2YXIgaSA9IHRoaXMubGlzdC5sZW5ndGg7XG4gICAgICAgIC8vIFNlYXJjaCBmcm9tIHRoZSBiYWNrLCB3ZSB1c3VhbGx5IHVwZGF0ZSB0aGUgbGF0ZXN0IGVudHJpZXMuXG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmxpc3RbaV0uaWQgPT09IGVsZW0uaWQpIHtcbiAgICAgICAgICAgICAgICBpZHggPSBpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlkeCA9PT0gLTEpIHsgLy9ub3QgY29udGFpbmVkIGluIGxpc3RcbiAgICAgICAgICAgIHRoaXMuYWRkKGVsZW0pO1xuICAgICAgICB9IGVsc2UgaWYgKCF0aGlzLmZpbHQoZWxlbSkpIHtcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlKGVsZW0uaWQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHRoaXMuc29ydGZ1bih0aGlzLmxpc3RbaWR4XSkgIT09IHRoaXMuc29ydGZ1bihlbGVtKSkgeyAvL3NvcnRwb3MgaGFzIGNoYW5nZWRcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZSh0aGlzLmxpc3RbaWR4XSk7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGQoZWxlbSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMubGlzdFtpZHhdID0gZWxlbTtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXQoXCJ1cGRhdGVcIiwgZWxlbSwgaWR4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sXG4gICAgcmVtb3ZlOiBmdW5jdGlvbiAoZWxlbV9pZCkge1xuICAgICAgICB2YXIgaWR4ID0gdGhpcy5saXN0Lmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGlkeC0tKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5saXN0W2lkeF0uaWQgPT09IGVsZW1faWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxpc3Quc3BsaWNlKGlkeCwgMSk7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0KFwicmVtb3ZlXCIsIGVsZW1faWQsIGlkeCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59KTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgU3RvcmVWaWV3OiBTdG9yZVZpZXdcbn07IiwidmFyICQgPSByZXF1aXJlKFwianF1ZXJ5XCIpO1xuXG5cbnZhciBLZXkgPSB7XG4gICAgVVA6IDM4LFxuICAgIERPV046IDQwLFxuICAgIFBBR0VfVVA6IDMzLFxuICAgIFBBR0VfRE9XTjogMzQsXG4gICAgSE9NRTogMzYsXG4gICAgRU5EOiAzNSxcbiAgICBMRUZUOiAzNyxcbiAgICBSSUdIVDogMzksXG4gICAgRU5URVI6IDEzLFxuICAgIEVTQzogMjcsXG4gICAgVEFCOiA5LFxuICAgIFNQQUNFOiAzMixcbiAgICBCQUNLU1BBQ0U6IDgsXG59O1xuLy8gQWRkIEEtWlxuZm9yICh2YXIgaSA9IDY1OyBpIDw9IDkwOyBpKyspIHtcbiAgICBLZXlbU3RyaW5nLmZyb21DaGFyQ29kZShpKV0gPSBpO1xufVxuXG5cbnZhciBmb3JtYXRTaXplID0gZnVuY3Rpb24gKGJ5dGVzKSB7XG4gICAgdmFyIHNpemUgPSBieXRlcztcbiAgICB2YXIgcHJlZml4ID0gW1wiQlwiLCBcIktCXCIsIFwiTUJcIiwgXCJHQlwiLCBcIlRCXCJdO1xuICAgIHZhciBpID0gMDtcbiAgICB3aGlsZSAoTWF0aC5hYnMoc2l6ZSkgPj0gMTAyNCAmJiBpIDwgcHJlZml4Lmxlbmd0aCAtIDEpIHtcbiAgICAgICAgaSsrO1xuICAgICAgICBzaXplID0gc2l6ZSAvIDEwMjQ7XG4gICAgfVxuICAgIHJldHVybiAoTWF0aC5mbG9vcihzaXplICogMTAwKSAvIDEwMC4wKS50b0ZpeGVkKDIpICsgcHJlZml4W2ldO1xufTtcblxuXG52YXIgZm9ybWF0VGltZURlbHRhID0gZnVuY3Rpb24gKG1pbGxpc2Vjb25kcykge1xuICAgIHZhciB0aW1lID0gbWlsbGlzZWNvbmRzO1xuICAgIHZhciBwcmVmaXggPSBbXCJtc1wiLCBcInNcIiwgXCJtaW5cIiwgXCJoXCJdO1xuICAgIHZhciBkaXYgPSBbMTAwMCwgNjAsIDYwXTtcbiAgICB2YXIgaSA9IDA7XG4gICAgd2hpbGUgKE1hdGguYWJzKHRpbWUpID49IGRpdltpXSAmJiBpIDwgZGl2Lmxlbmd0aCkge1xuICAgICAgICB0aW1lID0gdGltZSAvIGRpdltpXTtcbiAgICAgICAgaSsrO1xuICAgIH1cbiAgICByZXR1cm4gTWF0aC5yb3VuZCh0aW1lKSArIHByZWZpeFtpXTtcbn07XG5cblxudmFyIGZvcm1hdFRpbWVTdGFtcCA9IGZ1bmN0aW9uIChzZWNvbmRzKSB7XG4gICAgdmFyIHRzID0gKG5ldyBEYXRlKHNlY29uZHMgKiAxMDAwKSkudG9JU09TdHJpbmcoKTtcbiAgICByZXR1cm4gdHMucmVwbGFjZShcIlRcIiwgXCIgXCIpLnJlcGxhY2UoXCJaXCIsIFwiXCIpO1xufTtcblxuXG5mdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7XG4gICAgdGhpcy5saXN0ZW5lcnMgPSB7fTtcbn1cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgIGlmICghKGV2ZW50IGluIHRoaXMubGlzdGVuZXJzKSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICB0aGlzLmxpc3RlbmVyc1tldmVudF0uZm9yRWFjaChmdW5jdGlvbiAobGlzdGVuZXIpIHtcbiAgICAgICAgbGlzdGVuZXIuYXBwbHkodGhpcywgYXJncyk7XG4gICAgfS5iaW5kKHRoaXMpKTtcbn07XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyID0gZnVuY3Rpb24gKGV2ZW50cywgZikge1xuICAgIGV2ZW50cy5zcGxpdChcIiBcIikuZm9yRWFjaChmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdGhpcy5saXN0ZW5lcnNbZXZlbnRdID0gdGhpcy5saXN0ZW5lcnNbZXZlbnRdIHx8IFtdO1xuICAgICAgICB0aGlzLmxpc3RlbmVyc1tldmVudF0ucHVzaChmKTtcbiAgICB9LmJpbmQodGhpcykpO1xufTtcbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmVtb3ZlTGlzdGVuZXIgPSBmdW5jdGlvbiAoZXZlbnRzLCBmKSB7XG4gICAgaWYgKCEoZXZlbnRzIGluIHRoaXMubGlzdGVuZXJzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGV2ZW50cy5zcGxpdChcIiBcIikuZm9yRWFjaChmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gdGhpcy5saXN0ZW5lcnNbZXZlbnRdLmluZGV4T2YoZik7XG4gICAgICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICAgICAgICB0aGlzLmxpc3RlbmVyc1tldmVudF0uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgfVxuICAgIH0uYmluZCh0aGlzKSk7XG59O1xuXG5cbmZ1bmN0aW9uIGdldENvb2tpZShuYW1lKSB7XG4gICAgdmFyIHIgPSBkb2N1bWVudC5jb29raWUubWF0Y2goXCJcXFxcYlwiICsgbmFtZSArIFwiPShbXjtdKilcXFxcYlwiKTtcbiAgICByZXR1cm4gciA/IHJbMV0gOiB1bmRlZmluZWQ7XG59XG52YXIgeHNyZiA9ICQucGFyYW0oe194c3JmOiBnZXRDb29raWUoXCJfeHNyZlwiKX0pO1xuXG4vL1Rvcm5hZG8gWFNSRiBQcm90ZWN0aW9uLlxuJC5hamF4UHJlZmlsdGVyKGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgaWYgKFtcInBvc3RcIiwgXCJwdXRcIiwgXCJkZWxldGVcIl0uaW5kZXhPZihvcHRpb25zLnR5cGUudG9Mb3dlckNhc2UoKSkgPj0gMCAmJiBvcHRpb25zLnVybFswXSA9PT0gXCIvXCIpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMuZGF0YSkge1xuICAgICAgICAgICAgb3B0aW9ucy5kYXRhICs9IChcIiZcIiArIHhzcmYpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb3B0aW9ucy5kYXRhID0geHNyZjtcbiAgICAgICAgfVxuICAgIH1cbn0pO1xuLy8gTG9nIEFKQVggRXJyb3JzXG4kKGRvY3VtZW50KS5hamF4RXJyb3IoZnVuY3Rpb24gKGV2ZW50LCBqcVhIUiwgYWpheFNldHRpbmdzLCB0aHJvd25FcnJvcikge1xuICAgIHZhciBtZXNzYWdlID0ganFYSFIucmVzcG9uc2VUZXh0O1xuICAgIGNvbnNvbGUuZXJyb3IobWVzc2FnZSwgYXJndW1lbnRzKTtcbiAgICBFdmVudExvZ0FjdGlvbnMuYWRkX2V2ZW50KHRocm93bkVycm9yICsgXCI6IFwiICsgbWVzc2FnZSk7XG4gICAgd2luZG93LmFsZXJ0KG1lc3NhZ2UpO1xufSk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIEV2ZW50RW1pdHRlcjogRXZlbnRFbWl0dGVyLFxuICAgIGZvcm1hdFNpemU6IGZvcm1hdFNpemUsXG4gICAgZm9ybWF0VGltZURlbHRhOiBmb3JtYXRUaW1lRGVsdGEsXG4gICAgZm9ybWF0VGltZVN0YW1wOiBmb3JtYXRUaW1lU3RhbXAsXG4gICAgS2V5OiBLZXlcbn07Il19
|