@iwanglang/patient-fhir-helper
Version:
Patient Fhir Helper
576 lines • 115 kB
JavaScript
var q = Object.defineProperty;
var F = (e, r, t) => r in e ? q(e, r, { enumerable: !0, configurable: !0, writable: !0, value: t }) : e[r] = t;
var g = (e, r, t) => (F(e, typeof r != "symbol" ? r + "" : r, t), t);
const _ = globalThis || void 0 || self, M = /"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/, U = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/, k = /^\s*["[{]|^\s*-?\d{1,16}(\.\d{1,17})?([Ee][+-]?\d+)?\s*$/;
function O(e, r) {
if (e === "__proto__" || e === "constructor" && r && typeof r == "object" && "prototype" in r) {
J(e);
return;
}
return r;
}
function J(e) {
console.warn(`[destr] Dropping "${e}" key to prevent prototype pollution.`);
}
function B(e, r = {}) {
if (typeof e != "string")
return e;
const t = e.trim();
if (
// eslint-disable-next-line unicorn/prefer-at
e[0] === '"' && e.endsWith('"') && !e.includes("\\")
)
return t.slice(1, -1);
if (t.length <= 9) {
const o = t.toLowerCase();
if (o === "true")
return !0;
if (o === "false")
return !1;
if (o === "undefined")
return;
if (o === "null")
return null;
if (o === "nan")
return Number.NaN;
if (o === "infinity")
return Number.POSITIVE_INFINITY;
if (o === "-infinity")
return Number.NEGATIVE_INFINITY;
}
if (!k.test(e)) {
if (r.strict)
throw new SyntaxError("[destr] Invalid JSON");
return e;
}
try {
if (M.test(e) || U.test(e)) {
if (r.strict)
throw new Error("[destr] Possible prototype pollution");
return JSON.parse(e, O);
}
return JSON.parse(e);
} catch (o) {
if (r.strict)
throw o;
return e;
}
}
const Q = /#/g, Y = /&/g, v = /\//g, G = /=/g, T = /\+/g, W = /%5e/gi, K = /%60/gi, z = /%7c/gi, V = /%20/gi;
function H(e) {
return encodeURI("" + e).replace(z, "|");
}
function R(e) {
return H(typeof e == "string" ? e : JSON.stringify(e)).replace(T, "%2B").replace(V, "+").replace(Q, "%23").replace(Y, "%26").replace(K, "`").replace(W, "^").replace(v, "%2F");
}
function b(e) {
return R(e).replace(G, "%3D");
}
function p(e = "") {
try {
return decodeURIComponent("" + e);
} catch {
return "" + e;
}
}
function X(e) {
return p(e.replace(T, " "));
}
function Z(e) {
return p(e.replace(T, " "));
}
function x(e = "") {
const r = {};
e[0] === "?" && (e = e.slice(1));
for (const t of e.split("&")) {
const o = t.match(/([^=]+)=?(.*)/) || [];
if (o.length < 2)
continue;
const n = X(o[1]);
if (n === "__proto__" || n === "constructor")
continue;
const i = Z(o[2] || "");
r[n] === void 0 ? r[n] = i : Array.isArray(r[n]) ? r[n].push(i) : r[n] = [r[n], i];
}
return r;
}
function ee(e, r) {
return (typeof r == "number" || typeof r == "boolean") && (r = String(r)), r ? Array.isArray(r) ? r.map((t) => `${b(e)}=${R(t)}`).join("&") : `${b(e)}=${R(r)}` : b(e);
}
function re(e) {
return Object.keys(e).filter((r) => e[r] !== void 0).map((r) => ee(r, e[r])).filter(Boolean).join("&");
}
const te = /^[\s\w\0+.-]{2,}:([/\\]{1,2})/, se = /^[\s\w\0+.-]{2,}:([/\\]{2})?/, oe = /^([/\\]\s*){2,}[^/\\]/, ne = /\/$|\/\?|\/#/, ie = /^\.?\//;
function P(e, r = {}) {
return typeof r == "boolean" && (r = { acceptRelative: r }), r.strict ? te.test(e) : se.test(e) || (r.acceptRelative ? oe.test(e) : !1);
}
function E(e = "", r) {
return r ? ne.test(e) : e.endsWith("/");
}
function ce(e = "", r) {
if (!r)
return (E(e) ? e.slice(0, -1) : e) || "/";
if (!E(e, !0))
return e || "/";
let t = e, o = "";
const n = e.indexOf("#");
n >= 0 && (t = e.slice(0, n), o = e.slice(n));
const [i, ...c] = t.split("?");
return ((i.endsWith("/") ? i.slice(0, -1) : i) || "/") + (c.length > 0 ? `?${c.join("?")}` : "") + o;
}
function ae(e = "", r) {
if (!r)
return e.endsWith("/") ? e : e + "/";
if (E(e, !0))
return e || "/";
let t = e, o = "";
const n = e.indexOf("#");
if (n >= 0 && (t = e.slice(0, n), o = e.slice(n), !t))
return o;
const [i, ...c] = t.split("?");
return i + "/" + (c.length > 0 ? `?${c.join("?")}` : "") + o;
}
function fe(e, r) {
if (ue(r) || P(e))
return e;
const t = ce(r);
return e.startsWith(t) ? e : le(t, e);
}
function he(e, r) {
const t = C(e), o = { ...x(t.search), ...r };
return t.search = re(o), ye(t);
}
function ue(e) {
return !e || e === "/";
}
function de(e) {
return e && e !== "/";
}
function le(e, ...r) {
let t = e || "";
for (const o of r.filter((n) => de(n)))
if (t) {
const n = o.replace(ie, "");
t = ae(t) + n;
} else
t = o;
return t;
}
const $ = Symbol.for("ufo:protocolRelative");
function C(e = "", r) {
const t = e.match(
/^[\s\0]*(blob:|data:|javascript:|vbscript:)(.*)/i
);
if (t) {
const [, u, d = ""] = t;
return {
protocol: u.toLowerCase(),
pathname: d,
href: u + d,
auth: "",
host: "",
search: "",
hash: ""
};
}
if (!P(e, { acceptRelative: !0 }))
return r ? C(r + e) : A(e);
const [, o = "", n, i = ""] = e.replace(/\\/g, "/").match(/^[\s\0]*([\w+.-]{2,}:)?\/\/([^/@]+@)?(.*)/) || [], [, c = "", a = ""] = i.match(/([^#/?]*)(.*)?/) || [], { pathname: h, search: f, hash: s } = A(
a.replace(/\/(?=[A-Za-z]:)/, "")
);
return {
protocol: o.toLowerCase(),
auth: n ? n.slice(0, Math.max(0, n.length - 1)) : "",
host: c,
pathname: h,
search: f,
hash: s,
[$]: !o
};
}
function A(e = "") {
const [r = "", t = "", o = ""] = (e.match(/([^#?]*)(\?[^#]*)?(#.*)?/) || []).splice(1);
return {
pathname: r,
search: t,
hash: o
};
}
function ye(e) {
const r = e.pathname || "", t = e.search ? (e.search.startsWith("?") ? "" : "?") + e.search : "", o = e.hash || "", n = e.auth ? e.auth + "@" : "", i = e.host || "";
return (e.protocol || e[$] ? (e.protocol || "") + "//" : "") + n + i + r + t + o;
}
class N extends Error {
constructor(r, t) {
super(r, t), this.name = "FetchError", t != null && t.cause && !this.cause && (this.cause = t.cause);
}
}
function ge(e) {
var h, f, s, u, d;
const r = ((h = e.error) == null ? void 0 : h.message) || ((f = e.error) == null ? void 0 : f.toString()) || "", t = ((s = e.request) == null ? void 0 : s.method) || ((u = e.options) == null ? void 0 : u.method) || "GET", o = ((d = e.request) == null ? void 0 : d.url) || String(e.request) || "/", n = `[${t}] ${JSON.stringify(o)}`, i = e.response ? `${e.response.status} ${e.response.statusText}` : "<no response>", c = `${n}: ${i}${r ? ` ${r}` : ""}`, a = new N(
c,
e.error ? { cause: e.error } : void 0
);
for (const l of ["request", "options", "response"])
Object.defineProperty(a, l, {
get() {
return e[l];
}
});
for (const [l, y] of [
["data", "_data"],
["status", "status"],
["statusCode", "status"],
["statusText", "statusText"],
["statusMessage", "statusText"]
])
Object.defineProperty(a, l, {
get() {
return e.response && e.response[y];
}
});
return a;
}
const me = new Set(
Object.freeze(["PATCH", "POST", "PUT", "DELETE"])
);
function D(e = "GET") {
return me.has(e.toUpperCase());
}
function be(e) {
if (e === void 0)
return !1;
const r = typeof e;
return r === "string" || r === "number" || r === "boolean" || r === null ? !0 : r !== "object" ? !1 : Array.isArray(e) ? !0 : e.buffer ? !1 : e.constructor && e.constructor.name === "Object" || typeof e.toJSON == "function";
}
const we = /* @__PURE__ */ new Set([
"image/svg",
"application/xml",
"application/xhtml",
"application/html"
]), Re = /^application\/(?:[\w!#$%&*.^`~-]*\+)?json(;.+)?$/i;
function Ee(e = "") {
if (!e)
return "json";
const r = e.split(";").shift() || "";
return Re.test(r) ? "json" : we.has(r) || r.startsWith("text/") ? "text" : "blob";
}
function Te(e, r, t = globalThis.Headers) {
const o = {
...r,
...e
};
if (r != null && r.params && (e != null && e.params) && (o.params = {
...r == null ? void 0 : r.params,
...e == null ? void 0 : e.params
}), r != null && r.query && (e != null && e.query) && (o.query = {
...r == null ? void 0 : r.query,
...e == null ? void 0 : e.query
}), r != null && r.headers && (e != null && e.headers)) {
o.headers = new t((r == null ? void 0 : r.headers) || {});
for (const [n, i] of new t((e == null ? void 0 : e.headers) || {}))
o.headers.set(n, i);
}
return o;
}
const Se = /* @__PURE__ */ new Set([
408,
// Request Timeout
409,
// Conflict
425,
// Too Early
429,
// Too Many Requests
500,
// Internal Server Error
502,
// Bad Gateway
503,
// Service Unavailable
504
// Gateway Timeout
]), _e = /* @__PURE__ */ new Set([101, 204, 205, 304]);
function j(e = {}) {
const {
fetch: r = globalThis.fetch,
Headers: t = globalThis.Headers,
AbortController: o = globalThis.AbortController
} = e;
async function n(a) {
const h = a.error && a.error.name === "AbortError" && !a.options.timeout || !1;
if (a.options.retry !== !1 && !h) {
let s;
typeof a.options.retry == "number" ? s = a.options.retry : s = D(a.options.method) ? 0 : 1;
const u = a.response && a.response.status || 500;
if (s > 0 && (Array.isArray(a.options.retryStatusCodes) ? a.options.retryStatusCodes.includes(u) : Se.has(u))) {
const d = a.options.retryDelay || 0;
return d > 0 && await new Promise((l) => setTimeout(l, d)), i(a.request, {
...a.options,
retry: s - 1
});
}
}
const f = ge(a);
throw Error.captureStackTrace && Error.captureStackTrace(f, i), f;
}
const i = async function(h, f = {}) {
var l;
const s = {
request: h,
options: Te(f, e.defaults, t),
response: void 0,
error: void 0
};
s.options.method = (l = s.options.method) == null ? void 0 : l.toUpperCase(), s.options.onRequest && await s.options.onRequest(s), typeof s.request == "string" && (s.options.baseURL && (s.request = fe(s.request, s.options.baseURL)), (s.options.query || s.options.params) && (s.request = he(s.request, {
...s.options.params,
...s.options.query
}))), s.options.body && D(s.options.method) && (be(s.options.body) ? (s.options.body = typeof s.options.body == "string" ? s.options.body : JSON.stringify(s.options.body), s.options.headers = new t(s.options.headers || {}), s.options.headers.has("content-type") || s.options.headers.set("content-type", "application/json"), s.options.headers.has("accept") || s.options.headers.set("accept", "application/json")) : (
// ReadableStream Body
("pipeTo" in s.options.body && typeof s.options.body.pipeTo == "function" || // Node.js Stream Body
typeof s.options.body.pipe == "function") && ("duplex" in s.options || (s.options.duplex = "half"))
));
let u;
if (!s.options.signal && s.options.timeout) {
const y = new o();
u = setTimeout(
() => y.abort(),
s.options.timeout
), s.options.signal = y.signal;
}
try {
s.response = await r(
s.request,
s.options
);
} catch (y) {
return s.error = y, s.options.onRequestError && await s.options.onRequestError(s), await n(s);
} finally {
u && clearTimeout(u);
}
if (s.response.body && !_e.has(s.response.status) && s.options.method !== "HEAD") {
const y = (s.options.parseResponse ? "json" : s.options.responseType) || Ee(s.response.headers.get("content-type") || "");
switch (y) {
case "json": {
const I = await s.response.text(), L = s.options.parseResponse || B;
s.response._data = L(I);
break;
}
case "stream": {
s.response._data = s.response.body;
break;
}
default:
s.response._data = await s.response[y]();
}
}
return s.options.onResponse && await s.options.onResponse(s), !s.options.ignoreResponseError && s.response.status >= 400 && s.response.status < 600 ? (s.options.onResponseError && await s.options.onResponseError(s), await n(s)) : s.response;
}, c = async function(h, f) {
return (await i(h, f))._data;
};
return c.raw = i, c.native = (...a) => r(...a), c.create = (a = {}) => j({
...e,
defaults: {
...e.defaults,
...a
}
}), c;
}
const S = function() {
if (typeof globalThis < "u")
return globalThis;
if (typeof self < "u")
return self;
if (typeof window < "u")
return window;
if (typeof _ < "u")
return _;
throw new Error("unable to locate global object");
}(), Ae = S.fetch || (() => Promise.reject(new Error("[ofetch] global.fetch is not supported!"))), De = S.Headers, pe = S.AbortController, Pe = j({ fetch: Ae, Headers: De, AbortController: pe });
function $e(e, r) {
var t, o, n, i;
return e instanceof N && Array.isArray((o = (t = e == null ? void 0 : e.response) == null ? void 0 : t._data) == null ? void 0 : o.issue) ? (((i = (n = e == null ? void 0 : e.response) == null ? void 0 : n._data) == null ? void 0 : i.issue) ?? []).flatMap((c) => c.diagnostics).join(", ") : (e == null ? void 0 : e.message) || r || "Internal Server Error";
}
function w(e, r) {
var o, n, i, c, a, h;
if (r && !((o = e == null ? void 0 : e.name) != null && o.some((f) => (f == null ? void 0 : f.use) === r)))
return "";
const t = r ? (n = e == null ? void 0 : e.name) == null ? void 0 : n.find((f) => (f == null ? void 0 : f.use) === r) : (i = e == null ? void 0 : e.name) == null ? void 0 : i.find((f) => {
var s;
return ((s = f.given) == null ? void 0 : s.length) || f.family;
});
return t != null && t.text ? t == null ? void 0 : t.text : (c = t == null ? void 0 : t.given) != null && c.length || t != null && t.family ? [(a = t == null ? void 0 : t.prefix) == null ? void 0 : a.find((f) => !!f), (h = t == null ? void 0 : t.given) == null ? void 0 : h.find((f) => !!f), t == null ? void 0 : t.family].filter((f) => !!f).join(" ") : (t == null ? void 0 : t.text) || "-";
}
function Ce(e, r) {
const { remainingAgeYears: t, remainingAgeMonths: o, remainingAgeDays: n } = m(e, r);
let i = `${t || 0}ปี`;
return o > 0 && (i += ` ${o}เดือน`), n > 0 && (i += ` ${n}วัน`), i;
}
function m(e, r) {
const t = new Date(e), o = r ?? /* @__PURE__ */ new Date();
let n = o.getFullYear() - t.getFullYear(), i = o.getMonth() - t.getMonth(), c = o.getDate() - t.getDate();
return c < 0 && (i--, c += new Date(o.getFullYear(), o.getMonth(), 0).getDate()), i < 0 && (n--, i += 12), {
remainingAgeYears: n,
remainingAgeMonths: i,
remainingAgeDays: c
};
}
function Ne(e, r) {
var n, i;
const t = ((i = (n = e.identifier) == null ? void 0 : n.find((c) => {
var a, h;
return (h = (a = c.type) == null ? void 0 : a.coding) == null ? void 0 : h.find((f) => f.code === "MR" && f.system === "http://terminology.hl7.org/CodeSystem/v2-0203");
})) == null ? void 0 : i.value) ?? null, o = (e.photo ?? []).find((c) => (c == null ? void 0 : c.contentType) && (c == null ? void 0 : c.data));
return {
id: e.id ?? "",
patientReference: `Patient/${e.id}`,
identifier: e.identifier ?? [],
deceasedBoolean: e.deceasedBoolean ?? !1,
hospitalNumber: t,
name: w(e, "official") || w(e, "usual") || w(e),
gender: e.gender ?? "unknown",
birthdate: e.birthDate ?? null,
remainingAge: t && e.birthDate ? Ce(e.birthDate, r == null ? void 0 : r.currentDate) : null,
remainingAgeYears: t && e.birthDate ? m(e.birthDate, r == null ? void 0 : r.currentDate).remainingAgeYears : null,
remainingAgeMonths: t && e.birthDate ? m(e.birthDate, r == null ? void 0 : r.currentDate).remainingAgeMonths : null,
remainingAgeDays: t && e.birthDate ? m(e.birthDate, r == null ? void 0 : r.currentDate).remainingAgeDays : null,
photo: o ? `data:${o.contentType};base64,${o.data}` : void 0
};
}
class Ie {
/**
* Constructor for initializing the FHIR server and token.
*
* @param {string} fhirServer - the URL of the FHIR server
* @param {string} token - the authentication token
*/
constructor(r, t) {
/**
* The URL of the FHIR server.
* @private
*/
g(this, "fhirServer");
/**
* The authentication token.
* @private
*/
g(this, "token");
g(this, "medicalRecordNumber", !0);
g(this, "headers", new Headers());
g(this, "currentDate", /* @__PURE__ */ new Date());
this.fhirServer = r, this.token = t;
}
/**
* Initializes the FHIR server and token for the API.
*
* @param {string} fhirServer - The URL of the FHIR server.
* @param {string} token - The authentication token.
*/
initialisation(r, t) {
this.fhirServer = r, this.token = t;
}
/**
* Sets the token for the class.
*
* @param {string} token - The token to be set.
*/
setToken(r) {
this.token = r;
}
/**
* Sets the option values for the PatientHelper.
*
* @param {PatientHelperOption} option - The options to set for the PatientHelper.
*/
setOption(r) {
r != null && r.medicalRecordNumber && (this.medicalRecordNumber = r.medicalRecordNumber), r != null && r.headers && r.headers instanceof Headers ? this.headers = r.headers : r != null && r.headers && (this.headers = new Headers(r.headers)), r != null && r.currentDate && (this.currentDate = r.currentDate);
}
/**
* Get options for PatientHelper.
*
* This function returns an object that contains the current option values
* for the PatientHelper class. The properties of the returned object are:
*
* - medicalRecordNumber: A boolean value that indicates whether the
* Medical Record Number (MR) should be included in the search results.
* - headers: The headers to be used in the request.
* - currentDate: The current date to be used.
*
* @param {PatientHelperOption} option - An object that contains the option
* values to override the default values.
* @return {PatientHelperOption} The options object.
*/
getOptions(r = {}) {
return {
medicalRecordNumber: (r == null ? void 0 : r.medicalRecordNumber) ?? this.medicalRecordNumber,
headers: r != null && r.headers ? new Headers(r.headers) : this.headers ?? new Headers(),
currentDate: (r == null ? void 0 : r.currentDate) ?? this.currentDate
};
}
/**
* Set the headers for the request.
*
* @param {HeadersInit} headers - the headers to be set
* @return {void}
*/
setHearders(r) {
this.headers = r;
}
/**
* Set the timing using the current date.
*
* @param {Date} currentDate - the current date to set
* @return {void}
*/
setTiming(r) {
this.currentDate = r;
}
/**
* Find a patient by identifier.
*
* @param {string} identifier - The identifier of the patient
* @param {PatientHelperOption} option - An option object to configure the behavior of the function
* @return {Promise<any>} A Promise that resolves with the patient resource if found, otherwise rejects with an error
*/
async findPatientByIdentifier(r, t = {}) {
var o, n;
try {
const { medicalRecordNumber: i, headers: c, currentDate: a } = this.getOptions(t);
if (!this.fhirServer)
throw new Error("FHIR server not set");
this.token && c.append("Authorization", this.token);
const h = new URLSearchParams({
identifier: r
}).toString(), { entry: f } = await Pe(`/Patient?${h}`, {
baseURL: this.fhirServer,
retry: 3,
retryDelay: 500,
method: "GET",
headers: c
}), s = (o = f == null ? void 0 : f.find((u) => {
var d;
return ((d = u.resource) == null ? void 0 : d.resourceType) === "Patient";
})) == null ? void 0 : o.resource;
if (!s)
throw new Error(`Not found patient with identifier ${r}`);
if (!(s != null && s.id))
throw new Error("Patient resource missing id");
if (i && !((n = s == null ? void 0 : s.identifier) != null && n.some((u) => {
var d, l;
return (l = (d = u.type) == null ? void 0 : d.coding) == null ? void 0 : l.find((y) => y.code === "MR" && y.system === "http://terminology.hl7.org/CodeSystem/v2-0203");
})))
throw new Error("Patient resource missing Medical Record Number (MR)");
return Ne(s, { currentDate: a });
} catch (i) {
throw new Error($e(i, `Not found patient with identifier ${r}`));
}
}
}
export {
Ie as PatientFhirHelper,
m as calculateRemainingAge,
Ce as calculateRemainingAgeString,
Ne as patientNormalizationHelper,
w as useFhirHumanName
};
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy92aXRlLXBsdWdpbi1ub2RlLXBvbHlmaWxscy9zaGltcy9nbG9iYWwvZGlzdC9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9kZXN0ci9kaXN0L2luZGV4Lm1qcyIsIi4uL25vZGVfbW9kdWxlcy91Zm8vZGlzdC9pbmRleC5tanMiLCIuLi9ub2RlX21vZHVsZXMvb2ZldGNoL2Rpc3Qvc2hhcmVkL29mZXRjaC4zNzM4NmIwNS5tanMiLCIuLi9ub2RlX21vZHVsZXMvb2ZldGNoL2Rpc3QvaW5kZXgubWpzIiwiLi4vc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImNvbnN0IGdsb2JhbCA9IGdsb2JhbFRoaXMgfHwgdm9pZCAwIHx8IHNlbGY7XG5cbmV4cG9ydCB7IGdsb2JhbCBhcyBkZWZhdWx0LCBnbG9iYWwgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWluZGV4LmpzLm1hcFxuIiwiY29uc3Qgc3VzcGVjdFByb3RvUnggPSAvXCIoPzpffFxcXFx1MHsyfTVbRmZdKXsyfSg/OnB8XFxcXHUwezJ9NzApKD86cnxcXFxcdTB7Mn03MikoPzpvfFxcXFx1MHsyfTZbRmZdKSg/OnR8XFxcXHUwezJ9NzQpKD86b3xcXFxcdTB7Mn02W0ZmXSkoPzpffFxcXFx1MHsyfTVbRmZdKXsyfVwiXFxzKjovO1xuY29uc3Qgc3VzcGVjdENvbnN0cnVjdG9yUnggPSAvXCIoPzpjfFxcXFx1MDA2MykoPzpvfFxcXFx1MDA2W0ZmXSkoPzpufFxcXFx1MDA2W0VlXSkoPzpzfFxcXFx1MDA3MykoPzp0fFxcXFx1MDA3NCkoPzpyfFxcXFx1MDA3MikoPzp1fFxcXFx1MDA3NSkoPzpjfFxcXFx1MDA2MykoPzp0fFxcXFx1MDA3NCkoPzpvfFxcXFx1MDA2W0ZmXSkoPzpyfFxcXFx1MDA3MilcIlxccyo6LztcbmNvbnN0IEpzb25TaWdSeCA9IC9eXFxzKltcIlt7XXxeXFxzKi0/XFxkezEsMTZ9KFxcLlxcZHsxLDE3fSk/KFtFZV1bKy1dP1xcZCspP1xccyokLztcbmZ1bmN0aW9uIGpzb25QYXJzZVRyYW5zZm9ybShrZXksIHZhbHVlKSB7XG4gIGlmIChrZXkgPT09IFwiX19wcm90b19fXCIgfHwga2V5ID09PSBcImNvbnN0cnVjdG9yXCIgJiYgdmFsdWUgJiYgdHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiICYmIFwicHJvdG90eXBlXCIgaW4gdmFsdWUpIHtcbiAgICB3YXJuS2V5RHJvcHBlZChrZXkpO1xuICAgIHJldHVybjtcbiAgfVxuICByZXR1cm4gdmFsdWU7XG59XG5mdW5jdGlvbiB3YXJuS2V5RHJvcHBlZChrZXkpIHtcbiAgY29uc29sZS53YXJuKGBbZGVzdHJdIERyb3BwaW5nIFwiJHtrZXl9XCIga2V5IHRvIHByZXZlbnQgcHJvdG90eXBlIHBvbGx1dGlvbi5gKTtcbn1cbmZ1bmN0aW9uIGRlc3RyKHZhbHVlLCBvcHRpb25zID0ge30pIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gXCJzdHJpbmdcIikge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuICBjb25zdCBfdmFsdWUgPSB2YWx1ZS50cmltKCk7XG4gIGlmIChcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgdW5pY29ybi9wcmVmZXItYXRcbiAgICB2YWx1ZVswXSA9PT0gJ1wiJyAmJiB2YWx1ZS5lbmRzV2l0aCgnXCInKSAmJiAhdmFsdWUuaW5jbHVkZXMoXCJcXFxcXCIpXG4gICkge1xuICAgIHJldHVybiBfdmFsdWUuc2xpY2UoMSwgLTEpO1xuICB9XG4gIGlmIChfdmFsdWUubGVuZ3RoIDw9IDkpIHtcbiAgICBjb25zdCBfbHZhbCA9IF92YWx1ZS50b0xvd2VyQ2FzZSgpO1xuICAgIGlmIChfbHZhbCA9PT0gXCJ0cnVlXCIpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAoX2x2YWwgPT09IFwiZmFsc2VcIikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAoX2x2YWwgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgIHJldHVybiB2b2lkIDA7XG4gICAgfVxuICAgIGlmIChfbHZhbCA9PT0gXCJudWxsXCIpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAoX2x2YWwgPT09IFwibmFuXCIpIHtcbiAgICAgIHJldHVybiBOdW1iZXIuTmFOO1xuICAgIH1cbiAgICBpZiAoX2x2YWwgPT09IFwiaW5maW5pdHlcIikge1xuICAgICAgcmV0dXJuIE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICB9XG4gICAgaWYgKF9sdmFsID09PSBcIi1pbmZpbml0eVwiKSB7XG4gICAgICByZXR1cm4gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZO1xuICAgIH1cbiAgfVxuICBpZiAoIUpzb25TaWdSeC50ZXN0KHZhbHVlKSkge1xuICAgIGlmIChvcHRpb25zLnN0cmljdCkge1xuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiW2Rlc3RyXSBJbnZhbGlkIEpTT05cIik7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuICB0cnkge1xuICAgIGlmIChzdXNwZWN0UHJvdG9SeC50ZXN0KHZhbHVlKSB8fCBzdXNwZWN0Q29uc3RydWN0b3JSeC50ZXN0KHZhbHVlKSkge1xuICAgICAgaWYgKG9wdGlvbnMuc3RyaWN0KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIltkZXN0cl0gUG9zc2libGUgcHJvdG90eXBlIHBvbGx1dGlvblwiKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBKU09OLnBhcnNlKHZhbHVlLCBqc29uUGFyc2VUcmFuc2Zvcm0pO1xuICAgIH1cbiAgICByZXR1cm4gSlNPTi5wYXJzZSh2YWx1ZSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKG9wdGlvbnMuc3RyaWN0KSB7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG59XG5mdW5jdGlvbiBzYWZlRGVzdHIodmFsdWUsIG9wdGlvbnMgPSB7fSkge1xuICByZXR1cm4gZGVzdHIodmFsdWUsIHsgLi4ub3B0aW9ucywgc3RyaWN0OiB0cnVlIH0pO1xufVxuXG5leHBvcnQgeyBkZXN0ciBhcyBkZWZhdWx0LCBkZXN0ciwgc2FmZURlc3RyIH07XG4iLCJjb25zdCBuID0gL1teXFwwLVxceDdFXS87XG5jb25zdCB0ID0gL1tcXHgyRVxcdTMwMDJcXHVGRjBFXFx1RkY2MV0vZztcbmNvbnN0IG8gPSB7XG4gIG92ZXJmbG93OiBcIk92ZXJmbG93IEVycm9yXCIsXG4gIFwibm90LWJhc2ljXCI6IFwiSWxsZWdhbCBJbnB1dFwiLFxuICBcImludmFsaWQtaW5wdXRcIjogXCJJbnZhbGlkIElucHV0XCJcbn07XG5jb25zdCBlID0gTWF0aC5mbG9vcjtcbmNvbnN0IHIgPSBTdHJpbmcuZnJvbUNoYXJDb2RlO1xuZnVuY3Rpb24gcyhuMikge1xuICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihvW24yXSk7XG59XG5jb25zdCBjID0gZnVuY3Rpb24objIsIHQyKSB7XG4gIHJldHVybiBuMiArIDIyICsgNzUgKiAobjIgPCAyNikgLSAoKHQyICE9IDApIDw8IDUpO1xufTtcbmNvbnN0IHUgPSBmdW5jdGlvbihuMiwgdDIsIG8yKSB7XG4gIGxldCByMiA9IDA7XG4gIGZvciAobjIgPSBvMiA/IGUobjIgLyA3MDApIDogbjIgPj4gMSwgbjIgKz0gZShuMiAvIHQyKTsgbjIgPiA0NTU7IHIyICs9IDM2KSB7XG4gICAgbjIgPSBlKG4yIC8gMzUpO1xuICB9XG4gIHJldHVybiBlKHIyICsgMzYgKiBuMiAvIChuMiArIDM4KSk7XG59O1xuZnVuY3Rpb24gdG9BU0NJSShvMikge1xuICByZXR1cm4gZnVuY3Rpb24objIsIG8zKSB7XG4gICAgY29uc3QgZTIgPSBuMi5zcGxpdChcIkBcIik7XG4gICAgbGV0IHIyID0gXCJcIjtcbiAgICBlMi5sZW5ndGggPiAxICYmIChyMiA9IGUyWzBdICsgXCJAXCIsIG4yID0gZTJbMV0pO1xuICAgIGNvbnN0IHMyID0gZnVuY3Rpb24objMsIHQyKSB7XG4gICAgICBjb25zdCBvNCA9IFtdO1xuICAgICAgbGV0IGUzID0gbjMubGVuZ3RoO1xuICAgICAgZm9yICg7IGUzLS07ICkge1xuICAgICAgICBvNFtlM10gPSB0MihuM1tlM10pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG80O1xuICAgIH0oKG4yID0gbjIucmVwbGFjZSh0LCBcIi5cIikpLnNwbGl0KFwiLlwiKSwgbzMpLmpvaW4oXCIuXCIpO1xuICAgIHJldHVybiByMiArIHMyO1xuICB9KG8yLCBmdW5jdGlvbih0Mikge1xuICAgIHJldHVybiBuLnRlc3QodDIpID8gXCJ4bi0tXCIgKyBmdW5jdGlvbihuMikge1xuICAgICAgY29uc3QgdDMgPSBbXTtcbiAgICAgIGNvbnN0IG8zID0gKG4yID0gZnVuY3Rpb24objMpIHtcbiAgICAgICAgY29uc3QgdDQgPSBbXTtcbiAgICAgICAgbGV0IG80ID0gMDtcbiAgICAgICAgY29uc3QgZTIgPSBuMy5sZW5ndGg7XG4gICAgICAgIGZvciAoOyBvNCA8IGUyOyApIHtcbiAgICAgICAgICBjb25zdCByMiA9IG4zLmNoYXJDb2RlQXQobzQrKyk7XG4gICAgICAgICAgaWYgKHIyID49IDU1Mjk2ICYmIHIyIDw9IDU2MzE5ICYmIG80IDwgZTIpIHtcbiAgICAgICAgICAgIGNvbnN0IGUzID0gbjMuY2hhckNvZGVBdChvNCsrKTtcbiAgICAgICAgICAgICg2NDUxMiAmIGUzKSA9PSA1NjMyMCA/IHQ0LnB1c2goKCgxMDIzICYgcjIpIDw8IDEwKSArICgxMDIzICYgZTMpICsgNjU1MzYpIDogKHQ0LnB1c2gocjIpLCBvNC0tKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdDQucHVzaChyMik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0NDtcbiAgICAgIH0objIpKS5sZW5ndGg7XG4gICAgICBsZXQgZiA9IDEyODtcbiAgICAgIGxldCBpID0gMDtcbiAgICAgIGxldCBsID0gNzI7XG4gICAgICBmb3IgKGNvbnN0IG80IG9mIG4yKSB7XG4gICAgICAgIG80IDwgMTI4ICYmIHQzLnB1c2gocihvNCkpO1xuICAgICAgfVxuICAgICAgY29uc3QgaCA9IHQzLmxlbmd0aDtcbiAgICAgIGxldCBwID0gaDtcbiAgICAgIGZvciAoaCAmJiB0My5wdXNoKFwiLVwiKTsgcCA8IG8zOyApIHtcbiAgICAgICAgbGV0IG80ID0gMjE0NzQ4MzY0NztcbiAgICAgICAgZm9yIChjb25zdCB0NCBvZiBuMikge1xuICAgICAgICAgIHQ0ID49IGYgJiYgdDQgPCBvNCAmJiAobzQgPSB0NCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYSA9IHAgKyAxO1xuICAgICAgICBvNCAtIGYgPiBlKCgyMTQ3NDgzNjQ3IC0gaSkgLyBhKSAmJiBzKFwib3ZlcmZsb3dcIiksIGkgKz0gKG80IC0gZikgKiBhLCBmID0gbzQ7XG4gICAgICAgIGZvciAoY29uc3QgbzUgb2YgbjIpIHtcbiAgICAgICAgICBpZiAobzUgPCBmICYmICsraSA+IDIxNDc0ODM2NDcgJiYgcyhcIm92ZXJmbG93XCIpLCBvNSA9PSBmKSB7XG4gICAgICAgICAgICBsZXQgbjMgPSBpO1xuICAgICAgICAgICAgZm9yIChsZXQgbzYgPSAzNjsgOyBvNiArPSAzNikge1xuICAgICAgICAgICAgICBjb25zdCBzMiA9IG82IDw9IGwgPyAxIDogbzYgPj0gbCArIDI2ID8gMjYgOiBvNiAtIGw7XG4gICAgICAgICAgICAgIGlmIChuMyA8IHMyKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY29uc3QgdTIgPSBuMyAtIHMyO1xuICAgICAgICAgICAgICBjb25zdCBmMiA9IDM2IC0gczI7XG4gICAgICAgICAgICAgIHQzLnB1c2gocihjKHMyICsgdTIgJSBmMiwgMCkpKSwgbjMgPSBlKHUyIC8gZjIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdDMucHVzaChyKGMobjMsIDApKSksIGwgPSB1KGksIGEsIHAgPT0gaCksIGkgPSAwLCArK3A7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgICsraSwgKytmO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHQzLmpvaW4oXCJcIik7XG4gICAgfSh0MikgOiB0MjtcbiAgfSk7XG59XG5cbmNvbnN0IEhBU0hfUkUgPSAvIy9nO1xuY29uc3QgQU1QRVJTQU5EX1JFID0gLyYvZztcbmNvbnN0IFNMQVNIX1JFID0gL1xcLy9nO1xuY29uc3QgRVFVQUxfUkUgPSAvPS9nO1xuY29uc3QgSU1fUkUgPSAvXFw/L2c7XG5jb25zdCBQTFVTX1JFID0gL1xcKy9nO1xuY29uc3QgRU5DX0NBUkVUX1JFID0gLyU1ZS9naTtcbmNvbnN0IEVOQ19CQUNLVElDS19SRSA9IC8lNjAvZ2k7XG5jb25zdCBFTkNfQ1VSTFlfT1BFTl9SRSA9IC8lN2IvZ2k7XG5jb25zdCBFTkNfUElQRV9SRSA9IC8lN2MvZ2k7XG5jb25zdCBFTkNfQ1VSTFlfQ0xPU0VfUkUgPSAvJTdkL2dpO1xuY29uc3QgRU5DX1NQQUNFX1JFID0gLyUyMC9naTtcbmNvbnN0IEVOQ19TTEFTSF9SRSA9IC8lMmYvZ2k7XG5jb25zdCBFTkNfRU5DX1NMQVNIX1JFID0gLyUyNTJmL2dpO1xuZnVuY3Rpb24gZW5jb2RlKHRleHQpIHtcbiAgcmV0dXJuIGVuY29kZVVSSShcIlwiICsgdGV4dCkucmVwbGFjZShFTkNfUElQRV9SRSwgXCJ8XCIpO1xufVxuZnVuY3Rpb24gZW5jb2RlSGFzaCh0ZXh0KSB7XG4gIHJldHVybiBlbmNvZGUodGV4dCkucmVwbGFjZShFTkNfQ1VSTFlfT1BFTl9SRSwgXCJ7XCIpLnJlcGxhY2UoRU5DX0NVUkxZX0NMT1NFX1JFLCBcIn1cIikucmVwbGFjZShFTkNfQ0FSRVRfUkUsIFwiXlwiKTtcbn1cbmZ1bmN0aW9uIGVuY29kZVF1ZXJ5VmFsdWUoaW5wdXQpIHtcbiAgcmV0dXJuIGVuY29kZSh0eXBlb2YgaW5wdXQgPT09IFwic3RyaW5nXCIgPyBpbnB1dCA6IEpTT04uc3RyaW5naWZ5KGlucHV0KSkucmVwbGFjZShQTFVTX1JFLCBcIiUyQlwiKS5yZXBsYWNlKEVOQ19TUEFDRV9SRSwgXCIrXCIpLnJlcGxhY2UoSEFTSF9SRSwgXCIlMjNcIikucmVwbGFjZShBTVBFUlNBTkRfUkUsIFwiJTI2XCIpLnJlcGxhY2UoRU5DX0JBQ0tUSUNLX1JFLCBcImBcIikucmVwbGFjZShFTkNfQ0FSRVRfUkUsIFwiXlwiKS5yZXBsYWNlKFNMQVNIX1JFLCBcIiUyRlwiKTtcbn1cbmZ1bmN0aW9uIGVuY29kZVF1ZXJ5S2V5KHRleHQpIHtcbiAgcmV0dXJuIGVuY29kZVF1ZXJ5VmFsdWUodGV4dCkucmVwbGFjZShFUVVBTF9SRSwgXCIlM0RcIik7XG59XG5mdW5jdGlvbiBlbmNvZGVQYXRoKHRleHQpIHtcbiAgcmV0dXJuIGVuY29kZSh0ZXh0KS5yZXBsYWNlKEhBU0hfUkUsIFwiJTIzXCIpLnJlcGxhY2UoSU1fUkUsIFwiJTNGXCIpLnJlcGxhY2UoRU5DX0VOQ19TTEFTSF9SRSwgXCIlMkZcIikucmVwbGFjZShBTVBFUlNBTkRfUkUsIFwiJTI2XCIpLnJlcGxhY2UoUExVU19SRSwgXCIlMkJcIik7XG59XG5mdW5jdGlvbiBlbmNvZGVQYXJhbSh0ZXh0KSB7XG4gIHJldHVybiBlbmNvZGVQYXRoKHRleHQpLnJlcGxhY2UoU0xBU0hfUkUsIFwiJTJGXCIpO1xufVxuZnVuY3Rpb24gZGVjb2RlKHRleHQgPSBcIlwiKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChcIlwiICsgdGV4dCk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBcIlwiICsgdGV4dDtcbiAgfVxufVxuZnVuY3Rpb24gZGVjb2RlUGF0aCh0ZXh0KSB7XG4gIHJldHVybiBkZWNvZGUodGV4dC5yZXBsYWNlKEVOQ19TTEFTSF9SRSwgXCIlMjUyRlwiKSk7XG59XG5mdW5jdGlvbiBkZWNvZGVRdWVyeUtleSh0ZXh0KSB7XG4gIHJldHVybiBkZWNvZGUodGV4dC5yZXBsYWNlKFBMVVNfUkUsIFwiIFwiKSk7XG59XG5mdW5jdGlvbiBkZWNvZGVRdWVyeVZhbHVlKHRleHQpIHtcbiAgcmV0dXJuIGRlY29kZSh0ZXh0LnJlcGxhY2UoUExVU19SRSwgXCIgXCIpKTtcbn1cbmZ1bmN0aW9uIGVuY29kZUhvc3QobmFtZSA9IFwiXCIpIHtcbiAgcmV0dXJuIHRvQVNDSUkobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHBhcnNlUXVlcnkocGFyYW1ldGVyc1N0cmluZyA9IFwiXCIpIHtcbiAgY29uc3Qgb2JqZWN0ID0ge307XG4gIGlmIChwYXJhbWV0ZXJzU3RyaW5nWzBdID09PSBcIj9cIikge1xuICAgIHBhcmFtZXRlcnNTdHJpbmcgPSBwYXJhbWV0ZXJzU3RyaW5nLnNsaWNlKDEpO1xuICB9XG4gIGZvciAoY29uc3QgcGFyYW1ldGVyIG9mIHBhcmFtZXRlcnNTdHJpbmcuc3BsaXQoXCImXCIpKSB7XG4gICAgY29uc3QgcyA9IHBhcmFtZXRlci5tYXRjaCgvKFtePV0rKT0/KC4qKS8pIHx8IFtdO1xuICAgIGlmIChzLmxlbmd0aCA8IDIpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCBrZXkgPSBkZWNvZGVRdWVyeUtleShzWzFdKTtcbiAgICBpZiAoa2V5ID09PSBcIl9fcHJvdG9fX1wiIHx8IGtleSA9PT0gXCJjb25zdHJ1Y3RvclwiKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgY29uc3QgdmFsdWUgPSBkZWNvZGVRdWVyeVZhbHVlKHNbMl0gfHwgXCJcIik7XG4gICAgaWYgKG9iamVjdFtrZXldID09PSB2b2lkIDApIHtcbiAgICAgIG9iamVjdFtrZXldID0gdmFsdWU7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KG9iamVjdFtrZXldKSkge1xuICAgICAgb2JqZWN0W2tleV0ucHVzaCh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG9iamVjdFtrZXldID0gW29iamVjdFtrZXldLCB2YWx1ZV07XG4gICAgfVxuICB9XG4gIHJldHVybiBvYmplY3Q7XG59XG5mdW5jdGlvbiBlbmNvZGVRdWVyeUl0ZW0oa2V5LCB2YWx1ZSkge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiIHx8IHR5cGVvZiB2YWx1ZSA9PT0gXCJib29sZWFuXCIpIHtcbiAgICB2YWx1ZSA9IFN0cmluZyh2YWx1ZSk7XG4gIH1cbiAgaWYgKCF2YWx1ZSkge1xuICAgIHJldHVybiBlbmNvZGVRdWVyeUtleShrZXkpO1xuICB9XG4gIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgIHJldHVybiB2YWx1ZS5tYXAoKF92YWx1ZSkgPT4gYCR7ZW5jb2RlUXVlcnlLZXkoa2V5KX09JHtlbmNvZGVRdWVyeVZhbHVlKF92YWx1ZSl9YCkuam9pbihcIiZcIik7XG4gIH1cbiAgcmV0dXJuIGAke2VuY29kZVF1ZXJ5S2V5KGtleSl9PSR7ZW5jb2RlUXVlcnlWYWx1ZSh2YWx1ZSl9YDtcbn1cbmZ1bmN0aW9uIHN0cmluZ2lmeVF1ZXJ5KHF1ZXJ5KSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhxdWVyeSkuZmlsdGVyKChrKSA9PiBxdWVyeVtrXSAhPT0gdm9pZCAwKS5tYXAoKGspID0+IGVuY29kZVF1ZXJ5SXRlbShrLCBxdWVyeVtrXSkpLmZpbHRlcihCb29sZWFuKS5qb2luKFwiJlwiKTtcbn1cblxuY29uc3QgUFJPVE9DT0xfU1RSSUNUX1JFR0VYID0gL15bXFxzXFx3XFwwKy4tXXsyLH06KFsvXFxcXF17MSwyfSkvO1xuY29uc3QgUFJPVE9DT0xfUkVHRVggPSAvXltcXHNcXHdcXDArLi1dezIsfTooWy9cXFxcXXsyfSk/LztcbmNvbnN0IFBST1RPQ09MX1JFTEFUSVZFX1JFR0VYID0gL14oWy9cXFxcXVxccyopezIsfVteL1xcXFxdLztcbmNvbnN0IFBST1RPQ09MX1NDUklQVF9SRSA9IC9eW1xcc1xcMF0qKGJsb2J8ZGF0YXxqYXZhc2NyaXB0fHZic2NyaXB0KTokL2k7XG5jb25zdCBUUkFJTElOR19TTEFTSF9SRSA9IC9cXC8kfFxcL1xcP3xcXC8jLztcbmNvbnN0IEpPSU5fTEVBRElOR19TTEFTSF9SRSA9IC9eXFwuP1xcLy87XG5mdW5jdGlvbiBpc1JlbGF0aXZlKGlucHV0U3RyaW5nKSB7XG4gIHJldHVybiBbXCIuL1wiLCBcIi4uL1wiXS5zb21lKChzdHJpbmdfKSA9PiBpbnB1dFN0cmluZy5zdGFydHNXaXRoKHN0cmluZ18pKTtcbn1cbmZ1bmN0aW9uIGhhc1Byb3RvY29sKGlucHV0U3RyaW5nLCBvcHRzID0ge30pIHtcbiAgaWYgKHR5cGVvZiBvcHRzID09PSBcImJvb2xlYW5cIikge1xuICAgIG9wdHMgPSB7IGFjY2VwdFJlbGF0aXZlOiBvcHRzIH07XG4gIH1cbiAgaWYgKG9wdHMuc3RyaWN0KSB7XG4gICAgcmV0dXJuIFBST1RPQ09MX1NUUklDVF9SRUdFWC50ZXN0KGlucHV0U3RyaW5nKTtcbiAgfVxuICByZXR1cm4gUFJPVE9DT0xfUkVHRVgudGVzdChpbnB1dFN0cmluZykgfHwgKG9wdHMuYWNjZXB0UmVsYXRpdmUgPyBQUk9UT0NPTF9SRUxBVElWRV9SRUdFWC50ZXN0KGlucHV0U3RyaW5nKSA6IGZhbHNlKTtcbn1cbmZ1bmN0aW9uIGlzU2NyaXB0UHJvdG9jb2wocHJvdG9jb2wpIHtcbiAgcmV0dXJuICEhcHJvdG9jb2wgJiYgUFJPVE9DT0xfU0NSSVBUX1JFLnRlc3QocHJvdG9jb2wpO1xufVxuZnVuY3Rpb24gaGFzVHJhaWxpbmdTbGFzaChpbnB1dCA9IFwiXCIsIHJlc3BlY3RRdWVyeUFuZEZyYWdtZW50KSB7XG4gIGlmICghcmVzcGVjdFF1ZXJ5QW5kRnJhZ21lbnQpIHtcbiAgICByZXR1cm4gaW5wdXQuZW5kc1dpdGgoXCIvXCIpO1xuICB9XG4gIHJldHVybiBUUkFJTElOR19TTEFTSF9SRS50ZXN0KGlucHV0KTtcbn1cbmZ1bmN0aW9uIHdpdGhvdXRUcmFpbGluZ1NsYXNoKGlucHV0ID0gXCJcIiwgcmVzcGVjdFF1ZXJ5QW5kRnJhZ21lbnQpIHtcbiAgaWYgKCFyZXNwZWN0UXVlcnlBbmRGcmFnbWVudCkge1xuICAgIHJldHVybiAoaGFzVHJhaWxpbmdTbGFzaChpbnB1dCkgPyBpbnB1dC5zbGljZSgwLCAtMSkgOiBpbnB1dCkgfHwgXCIvXCI7XG4gIH1cbiAgaWYgKCFoYXNUcmFpbGluZ1NsYXNoKGlucHV0LCB0cnVlKSkge1xuICAgIHJldHVybiBpbnB1dCB8fCBcIi9cIjtcbiAgfVxuICBsZXQgcGF0aCA9IGlucHV0O1xuICBsZXQgZnJhZ21lbnQgPSBcIlwiO1xuICBjb25zdCBmcmFnbWVudEluZGV4ID0gaW5wdXQuaW5kZXhPZihcIiNcIik7XG4gIGlmIChmcmFnbWVudEluZGV4ID49IDApIHtcbiAgICBwYXRoID0gaW5wdXQuc2xpY2UoMCwgZnJhZ21lbnRJbmRleCk7XG4gICAgZnJhZ21lbnQgPSBpbnB1dC5zbGljZShmcmFnbWVudEluZGV4KTtcbiAgfVxuICBjb25zdCBbczAsIC4uLnNdID0gcGF0aC5zcGxpdChcIj9cIik7XG4gIGNvbnN0IGNsZWFuUGF0aCA9IHMwLmVuZHNXaXRoKFwiL1wiKSA/IHMwLnNsaWNlKDAsIC0xKSA6IHMwO1xuICByZXR1cm4gKGNsZWFuUGF0aCB8fCBcIi9cIikgKyAocy5sZW5ndGggPiAwID8gYD8ke3Muam9pbihcIj9cIil9YCA6IFwiXCIpICsgZnJhZ21lbnQ7XG59XG5mdW5jdGlvbiB3aXRoVHJhaWxpbmdTbGFzaChpbnB1dCA9IFwiXCIsIHJlc3BlY3RRdWVyeUFuZEZyYWdtZW50KSB7XG4gIGlmICghcmVzcGVjdFF1ZXJ5QW5kRnJhZ21lbnQpIHtcbiAgICByZXR1cm4gaW5wdXQuZW5kc1dpdGgoXCIvXCIpID8gaW5wdXQgOiBpbnB1dCArIFwiL1wiO1xuICB9XG4gIGlmIChoYXNUcmFpbGluZ1NsYXNoKGlucHV0LCB0cnVlKSkge1xuICAgIHJldHVybiBpbnB1dCB8fCBcIi9cIjtcbiAgfVxuICBsZXQgcGF0aCA9IGlucHV0O1xuICBsZXQgZnJhZ21lbnQgPSBcIlwiO1xuICBjb25zdCBmcmFnbWVudEluZGV4ID0gaW5wdXQuaW5kZXhPZihcIiNcIik7XG4gIGlmIChmcmFnbWVudEluZGV4ID49IDApIHtcbiAgICBwYXRoID0gaW5wdXQuc2xpY2UoMCwgZnJhZ21lbnRJbmRleCk7XG4gICAgZnJhZ21lbnQgPSBpbnB1dC5zbGljZShmcmFnbWVudEluZGV4KTtcbiAgICBpZiAoIXBhdGgpIHtcbiAgICAgIHJldHVybiBmcmFnbWVudDtcbiAgICB9XG4gIH1cbiAgY29uc3QgW3MwLCAuLi5zXSA9IHBhdGguc3BsaXQoXCI/XCIpO1xuICByZXR1cm4gczAgKyBcIi9cIiArIChzLmxlbmd0aCA+IDAgPyBgPyR7cy5qb2luKFwiP1wiKX1gIDogXCJcIikgKyBmcmFnbWVudDtcbn1cbmZ1bmN0aW9uIGhhc0xlYWRpbmdTbGFzaChpbnB1dCA9IFwiXCIpIHtcbiAgcmV0dXJuIGlucHV0LnN0YXJ0c1dpdGgoXCIvXCIpO1xufVxuZnVuY3Rpb24gd2l0aG91dExlYWRpbmdTbGFzaChpbnB1dCA9IFwiXCIpIHtcbiAgcmV0dXJuIChoYXNMZWFkaW5nU2xhc2goaW5wdXQpID8gaW5wdXQuc2xpY2UoMSkgOiBpbnB1dCkgfHwgXCIvXCI7XG59XG5mdW5jdGlvbiB3aXRoTGVhZGluZ1NsYXNoKGlucHV0ID0gXCJcIikge1xuICByZXR1cm4gaGFzTGVhZGluZ1NsYXNoKGlucHV0KSA/IGlucHV0IDogXCIvXCIgKyBpbnB1dDtcbn1cbmZ1bmN0aW9uIGNsZWFuRG91YmxlU2xhc2hlcyhpbnB1dCA9IFwiXCIpIHtcbiAgcmV0dXJuIGlucHV0LnNwbGl0KFwiOi8vXCIpLm1hcCgoc3RyaW5nXykgPT4gc3RyaW5nXy5yZXBsYWNlKC9cXC97Mix9L2csIFwiL1wiKSkuam9pbihcIjovL1wiKTtcbn1cbmZ1bmN0aW9uIHdpdGhCYXNlKGlucHV0LCBiYXNlKSB7XG4gIGlmIChpc0VtcHR5VVJMKGJhc2UpIHx8IGhhc1Byb3RvY29sKGlucHV0KSkge1xuICAgIHJldHVybiBpbnB1dDtcbiAgfVxuICBjb25zdCBfYmFzZSA9IHdpdGhvdXRUcmFpbGluZ1NsYXNoKGJhc2UpO1xuICBpZiAoaW5wdXQuc3RhcnRzV2l0aChfYmFzZSkpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cbiAgcmV0dXJuIGpvaW5VUkwoX2Jhc2UsIGlucHV0KTtcbn1cbmZ1bmN0aW9uIHdpdGhvdXRCYXNlKGlucHV0LCBiYXNlKSB7XG4gIGlmIChpc0VtcHR5VVJMKGJhc2UpKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG4gIGNvbnN0IF9iYXNlID0gd2l0aG91dFRyYWlsaW5nU2xhc2goYmFzZSk7XG4gIGlmICghaW5wdXQuc3RhcnRzV2l0aChfYmFzZSkpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cbiAgY29uc3QgdHJpbW1lZCA9IGlucHV0LnNsaWNlKF9iYXNlLmxlbmd0aCk7XG4gIHJldHVybiB0cmltbWVkWzBdID09PSBcIi9cIiA/IHRyaW1tZWQgOiBcIi9cIiArIHRyaW1tZWQ7XG59XG5mdW5jdGlvbiB3aXRoUXVlcnkoaW5wdXQsIHF1ZXJ5KSB7XG4gIGNvbnN0IHBhcnNlZCA9IHBhcnNlVVJMKGlucHV0KTtcbiAgY29uc3QgbWVyZ2VkUXVlcnkgPSB7IC4uLnBhcnNlUXVlcnkocGFyc2VkLnNlYXJjaCksIC4uLnF1ZXJ5IH07XG4gIHBhcnNlZC5zZWFyY2ggPSBzdHJpbmdpZnlRdWVyeShtZXJnZWRRdWVyeSk7XG4gIHJldHVybiBzdHJpbmdpZnlQYXJzZWRVUkwocGFyc2VkKTtcbn1cbmZ1bmN0aW9uIGdldFF1ZXJ5KGlucHV0KSB7XG4gIHJldHVybiBwYXJzZVF1ZXJ5KHBhcnNlVVJMKGlucHV0KS5zZWFyY2gpO1xufVxuZnVuY3Rpb24gaXNFbXB0eVVSTCh1cmwpIHtcbiAgcmV0dXJuICF1cmwgfHwgdXJsID09PSBcIi9cIjtcbn1cbmZ1bmN0aW9uIGlzTm9uRW1wdHlVUkwodXJsKSB7XG4gIHJldHVybiB1cmwgJiYgdXJsICE9PSBcIi9cIjtcbn1cbmZ1bmN0aW9uIGpvaW5VUkwoYmFzZSwgLi4uaW5wdXQpIHtcbiAgbGV0IHVybCA9IGJhc2UgfHwgXCJcIjtcbiAgZm9yIChjb25zdCBzZWdtZW50IG9mIGlucHV0LmZpbHRlcigodXJsMikgPT4gaXNOb25FbXB0eVVSTCh1cmwyKSkpIHtcbiAgICBpZiAodXJsKSB7XG4gICAgICBjb25zdCBfc2VnbWVudCA9IHNlZ21lbnQucmVwbGFjZShKT0lOX0xFQURJTkdfU0xBU0hfUkUsIFwiXCIpO1xuICAgICAgdXJsID0gd2l0aFRyYWlsaW5nU2xhc2godXJsKSArIF9zZWdtZW50O1xuICAgIH0gZWxzZSB7XG4gICAgICB1cmwgPSBzZWdtZW50O1xuICAgIH1cbiAgfVxuICByZXR1cm4gdXJsO1xufVxuZnVuY3Rpb24gam9pblJlbGF0aXZlVVJMKC4uLl9pbnB1dCkge1xuICBjb25zdCBKT0lOX1NFR01FTlRfU1BMSVRfUkUgPSAvXFwvKD8hXFwvKS87XG4gIGNvbnN0IGlucHV0ID0gX2lucHV0LmZpbHRlcihCb29sZWFuKTtcbiAgY29uc3Qgc2VnbWVudHMgPSBbXTtcbiAgbGV0IHNlZ21lbnRzRGVwdGggPSAwO1xuICBmb3IgKGNvbnN0IGkgb2YgaW5wdXQpIHtcbiAgICBpZiAoIWkgfHwgaSA9PT0gXCIvXCIpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IFtzaW5kZXgsIHNdIG9mIGkuc3BsaXQoSk9JTl9TRUdNRU5UX1NQTElUX1JFKS5lbnRyaWVzKCkpIHtcbiAgICAgIGlmICghcyB8fCBzID09PSBcIi5cIikge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGlmIChzID09PSBcIi4uXCIpIHtcbiAgICAgICAgaWYgKHNlZ21lbnRzLmxlbmd0aCA9PT0gMSAmJiBoYXNQcm90b2NvbChzZWdtZW50c1swXSkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBzZWdtZW50cy5wb3AoKTtcbiAgICAgICAgc2VnbWVudHNEZXB0aC0tO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGlmIChzaW5kZXggPT09IDEgJiYgc2VnbWVudHNbc2VnbWVudHMubGVuZ3RoIC0gMV0/LmVuZHNXaXRoKFwiOi9cIikpIHtcbiAgICAgICAgc2VnbWVudHNbc2VnbWVudHMubGVuZ3RoIC0gMV0gKz0gXCIvXCIgKyBzO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHNlZ21lbnRzLnB1c2gocyk7XG4gICAgICBzZWdtZW50c0RlcHRoKys7XG4gICAgfVxuICB9XG4gIGxldCB1cmwgPSBzZWdtZW50cy5qb2luKFwiL1wiKTtcbiAgaWYgKHNlZ21lbnRzRGVwdGggPj0gMCkge1xuICAgIGlmIChpbnB1dFswXT8uc3RhcnRzV2l0aChcIi9cIikgJiYgIXVybC5zdGFydHNXaXRoKFwiL1wiKSkge1xuICAgICAgdXJsID0gXCIvXCIgKyB1cmw7XG4gICAgfSBlbHNlIGlmIChpbnB1dFswXT8uc3RhcnRzV2l0aChcIi4vXCIpICYmICF1cmwuc3RhcnRzV2l0aChcIi4vXCIpKSB7XG4gICAgICB1cmwgPSBcIi4vXCIgKyB1cmw7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHVybCA9IFwiLi4vXCIucmVwZWF0KC0xICogc2VnbWVudHNEZXB0aCkgKyB1cmw7XG4gIH1cbiAgaWYgKGlucHV0W2lucHV0Lmxlbmd0aCAtIDFdPy5lbmRzV2l0aChcIi9cIikgJiYgIXVybC5lbmRzV2l0aChcIi9cIikpIHtcbiAgICB1cmwgKz0gXCIvXCI7XG4gIH1cbiAgcmV0dXJuIHVybDtcbn1cbmZ1bmN0aW9uIHdpdGhIdHRwKGlucHV0KSB7XG4gIHJldHVybiB3aXRoUHJvdG9jb2woaW5wdXQsIFwiaHR0cDovL1wiKTtcbn1cbmZ1bmN0aW9uIHdpdGhIdHRwcyhpbnB1dCkge1xuICByZXR1cm4gd2l0aFByb3RvY29sKGlucHV0LCBcImh0dHBzOi8vXCIpO1xufVxuZnVuY3Rpb24gd2l0aG91dFByb3RvY29sKGlucHV0KSB7XG4gIHJldHVybiB3aXRoUHJvdG9jb2woaW5wdXQsIFwiXCIpO1xufVxuZnVuY3Rpb24gd2l0aFByb3RvY29sKGlucHV0LCBwcm90b2NvbCkge1xuICBjb25zdCBtYXRjaCA9IGlucHV0Lm1hdGNoKFBST1RPQ09MX1JFR0VYKTtcbiAgaWYgKCFtYXRjaCkge1xuICAgIHJldHVybiBwcm90b2NvbCArIGlucHV0O1xuICB9XG4gIHJldHVybiBwcm90b2NvbCArIGlucHV0LnNsaWNlKG1hdGNoWzBdLmxlbmd0aCk7XG59XG5mdW5jdGlvbiBub3JtYWxpemVVUkwoaW5wdXQpIHtcbiAgY29uc3QgcGFyc2VkID0gcGFyc2VVUkwoaW5wdXQpO1xuICBwYXJzZWQucGF0aG5hbWUgPSBlbmNvZGVQYXRoKGRlY29kZVBhdGgocGFyc2VkLnBhdGhuYW1lKSk7XG4gIHBhcnNlZC5oYXNoID0gZW5jb2RlSGFzaChkZWNvZGUocGFyc2VkLmhhc2gpKTtcbiAgcGFyc2VkLmhvc3QgPSBlbmNvZGVIb3N0KGRlY29kZShwYXJzZWQuaG9zdCkpO1xuICBwYXJzZWQuc2VhcmNoID0gc3RyaW5naWZ5UXVlcnkocGFyc2VRdWVyeShwYXJzZWQuc2VhcmNoKSk7XG4gIHJldHVybiBzdHJpbmdpZnlQYXJzZWRVUkwocGFyc2VkKTtcbn1cbmZ1bmN0aW9uIHJlc29sdmVVUkwoYmFzZSA9IFwiXCIsIC4uLmlucHV0cykge1xuICBpZiAodHlwZW9mIGJhc2UgIT09IFwic3RyaW5nXCIpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgYFVSTCBpbnB1dCBzaG91bGQgYmUgc3RyaW5nIHJlY2VpdmVkICR7dHlwZW9mIGJhc2V9ICgke2Jhc2V9KWBcbiAgICApO1xuICB9XG4gIGNvbnN0IGZpbHRlcmVkSW5wdXRzID0gaW5wdXRzLmZpbHRlcigoaW5wdXQpID0+IGlzTm9uRW1wdHlVUkwoaW5wdXQpKTtcbiAgaWYgKGZpbHRlcmVkSW5wdXRzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBiYXNlO1xuICB9XG4gIGNvbnN0IHVybCA9IHBhcnNlVVJMKGJhc2UpO1xuICBmb3IgKGNvbnN0IGlucHV0U2VnbWVudCBvZiBmaWx0ZXJlZElucHV0cykge1xuICAgIGNvbnN0IHVybFNlZ21lbnQgPSBwYXJzZVVSTChpbnB1dFNlZ21lbnQpO1xuICAgIGlmICh1cmxTZWdtZW50LnBhdGhuYW1lKSB7XG4gICAgICB1cmwucGF0aG5hbWUgPSB3aXRoVHJhaWxpbmdTbGFzaCh1cmwucGF0aG5hbWUpICsgd2l0aG91dExlYWRpbmdTbGFzaCh1cmxTZWdtZW50LnBhdGhuYW1lKTtcbiAgICB9XG4gICAgaWYgKHVybFNlZ21lbnQuaGFzaCAmJiB1cmxTZWdtZW50Lmhhc2ggIT09IFwiI1wiKSB7XG4gICAgICB1cmwuaGFzaCA9IHVybFNlZ21lbnQuaGFzaDtcbiAgICB9XG4gICAgaWYgKHVybFNlZ21lbnQuc2VhcmNoICYmIHVybFNlZ21lbnQuc2VhcmNoICE9PSBcIj9cIikge1xuICAgICAgaWYgKHVybC5zZWFyY2ggJiYgdXJsLnNlYXJjaCAhPT0gXCI/XCIpIHtcbiAgICAgICAgY29uc3QgcXVlcnlTdHJpbmcgPSBzdHJpbmdpZnlRdWVyeSh7XG4gICAgICAgICAgLi4ucGFyc2VRdWVyeSh1cmwuc2VhcmNoKSxcbiAgICAgICAgICAuLi5wYXJzZVF1ZXJ5KHVybFNlZ21lbnQuc2VhcmNoKVxuICAgICAgICB9KTtcbiAgICAgICAgdXJsLnNlYXJjaCA9IHF1ZXJ5U3RyaW5nLmxlbmd0aCA+IDAgPyBcIj9cIiArIHF1ZXJ5U3RyaW5nIDogXCJcIjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHVybC5zZWFyY2ggPSB1cmxTZWdtZW50LnNlYXJjaDtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHN0cmluZ2lmeVBhcnNlZFVSTCh1cmwpO1xufVxuZnVuY3Rpb24gaXNTYW1lUGF0aChwMSwgcDIpIHtcbiAgcmV0dXJuIGRlY29kZSh3aXRob3V0VHJhaWxpbmdTbGFzaChwMSkpID09PSBkZWNvZGUod2l0aG91dFRyYWlsaW5nU2xhc2gocDIpKTtcbn1cbmZ1bmN0aW9uIGlzRXF1YWwoYSwgYiwgb3B0aW9ucyA9IHt9KSB7XG4gIGlmICghb3B0aW9ucy50cmFpbGluZ1NsYXNoKSB7XG4gICAgYSA9IHdpdGhUcmFpbGluZ1NsYXNoKGEpO1xuICAgIGIgPSB3aXRoVHJhaWxpbmdTbGFzaChiKTtcbiAgfVxuICBpZiAoIW9wdGlvbnMubGVhZGluZ1NsYXNoKSB7XG4gICAgYSA9IHdpdGhMZWFkaW5nU2xhc2goYSk7XG4gICAgYiA9IHdpdGhMZWFkaW5nU2xhc2goYik7XG4gIH1cbiAgaWYgKCFvcHRpb25zLmVuY29kaW5nKSB7XG4gICAgYSA9IGRlY29kZShhKTtcbiAgICBiID0gZGVjb2RlKGIpO1xuICB9XG4gIHJldHVybiBhID09PSBiO1xufVxuZnVuY3Rpb24gd2l0aEZyYWdtZW50KGlucHV0LCBoYXNoKSB7XG4gIGlmICghaGFzaCB8fCBoYXNoID09PSBcIiNcIikge1xuICAgIHJldHVybiBpbnB1dDtcbiAgfVxuICBjb25zdCBwYXJzZWQgPSBwYXJzZVVSTChpbnB1dCk7XG4gIHBhcnNlZC5oYXNoID0gaGFzaCA9PT0gXCJcIiA/IFwiXCIgOiBcIiNcIiArIGVuY29kZUhhc2goaGFzaCk7XG4gIHJldHVybiBzdHJpbmdpZnlQYXJzZWRVUkwocGFyc2VkKTtcbn1cbmZ1bmN0aW9uIHdpdGhvdXRGcmFnbWVudChpbnB1dCkge1xuICByZXR1cm4gc3RyaW5naWZ5UGFyc2VkVVJMKHsgLi4ucGFyc2VVUkwoaW5wdXQpLCBoYXNoOiBcIlwiIH0pO1xufVxuZnVuY3Rpb24gd2l0aG91dEhvc3QoaW5wdXQpIHtcbiAgY29uc3QgcGFyc2VkID0gcGFyc2VVUkwoaW5wdXQpO1xuICByZXR1cm4gKHBhcnNlZC5wYXRobmFtZSB8fCBcIi9cIikgKyBwYXJzZWQuc2VhcmNoICsgcGFyc2VkLmhhc2g7XG59XG5cbmNvbnN0IHByb3RvY29sUmVsYXRpdmUgPSBTeW1ib2wuZm9yKFwidWZvOnByb3RvY29sUmVsYXRpdmVcIik7XG5mdW5jdGlvbiBwYXJzZVVSTChpbnB1dCA9IFwiXCIsIGRlZmF1bHRQcm90bykge1xuICBjb25zdCBfc3BlY2lhbFByb3RvTWF0Y2ggPSBpbnB1dC5tYXRjaChcbiAgICAvXltcXHNcXDBdKihibG9iOnxkYXRhOnxqYXZhc2NyaXB0Onx2YnNjcmlwdDopKC4qKS9pXG4gICk7XG4gIGlmIChfc3BlY2lhbFByb3RvTWF0Y2gpIHtcbiAgICBjb25zdCBbLCBfcHJvdG8sIF9wYXRobmFtZSA9IFwiXCJdID0gX3NwZWNpYWxQcm90b01hdGNoO1xuICAgIHJldHVybiB7XG4gICAgICBwcm90b2NvbDogX3Byb3RvLnRvTG93ZXJDYXNlKCksXG4gICAgICBwYXRobmFtZTogX3BhdGhuYW1lLFxuICAgICAgaHJlZjogX3Byb3RvICsgX3BhdGhuYW1lLFxuICAgICAgYXV0aDogXCJcIixcbiAgICAgIGhvc3Q6IFwiXCIsXG4gICAgICBzZWFyY2g6IFwiXCIsXG4gICAgICBoYXNoOiBcIlwiXG4gICAgfTtcbiAgfVxuICBpZiAoIWhhc1Byb3RvY29sKGlucHV0LCB7IGFjY2VwdFJlbGF0aXZlOiB0cnVlIH0pKSB7XG4gICAgcmV0dXJuIGRlZmF1bHRQcm90byA/IHBhcnNlVVJMKGRlZmF1bHRQcm90byArIGlucHV0KSA6IHBhcnNlUGF0aChpbnB1dCk7XG4gIH1cbiAgY29uc3QgWywgcHJvdG9jb2wgPSBcIlwiLCBhdXRoLCBob3N0QW5kUGF0aCA9IFwiXCJdID0gaW5wdXQucmVwbGFjZSgvXFxcXC9nLCBcIi9cIikubWF0Y2goL15bXFxzXFwwXSooW1xcdysuLV17Mix9Oik/XFwvXFwvKFteL0BdK0ApPyguKikvKSB8fCBbXTtcbiAgY29uc3QgWywgaG9zdCA9IFwiXCIsIHBhdGggPSBcIlwiXSA9IGhvc3RBbmRQYXRoLm1hdGNoKC8oW14jLz9dKikoLiopPy8pIHx8IFtdO1xuICBjb25zdCB7IHBhdGhuYW1lLCBzZWFyY2gsIGhhc2ggfSA9IHBhcnNlUGF0aChcbiAgICBwYXRoLnJlcGxhY2UoL1xcLyg/PVtBLVphLXpdOikvLCBcIlwiKVxuICApO1xuICByZXR1cm4ge1xuICAgIHByb3RvY29sOiBwcm90b2NvbC50b0xvd2VyQ2FzZSgpLFxuICAgIGF1dGg6IGF1dGggPyBhdXRoLnNsaWNlKDAsIE1hdGgubWF4KDAsIGF1dGgubGVuZ3RoIC0gMSkpIDogXCJcIixcbiAgICBob3N0LFxuICAgIHBhdGhuYW1lLFxuICAgIHNlYXJjaCxcbiAgICBoYXNoLFxuICAgIFtwcm90b2NvbFJlbGF0aXZlXTogIXByb3RvY29sXG4gIH07XG59XG5mdW5jdGlvbiBwYXJzZVBhdGgoaW5wdXQgPSBcIlwiKSB7XG4gIGNvbnN0IFtwYXRobmFtZSA9IFwiXCIsIHNlYXJjaCA9IFwiXCIsIGhhc2ggPSBcIlwiXSA9IChpbnB1dC5tYXRjaCgvKFteIz9dKikoXFw/W14jXSopPygjLiopPy8pIHx8IFtdKS5zcGxpY2UoMSk7XG4gIHJldHVybiB7XG4gICAgcGF0aG5hbWUsXG4gICAgc2VhcmNoLFxuICAgIGhhc2hcbiAgfTtcbn1cbmZ1bmN0aW9uIHBhcnNlQXV0aChpbnB1dCA9IFwiXCIpIHtcbiAgY29uc3QgW3VzZXJuYW1lLCBwYXNzd29yZF0gPSBpbnB1dC5zcGxpdChcIjpcIik7XG4gIHJldHVybiB7XG4gICAgdXNlcm5hbWU6IGRlY29kZSh1c2VybmFtZSksXG4gICAgcGFzc3dvcmQ6IGRlY29kZShwYXNzd29yZClcbiAgfTtcbn1cbmZ1bmN0aW9uIHBhcnNlSG9zdChpbnB1dCA9IFwiXCIpIHtcbiAgY29uc3QgW2hvc3RuYW1lLCBwb3J0XSA9IChpbnB1dC5tYXRjaCgvKFteLzpdKik6PyhcXGQrKT8vKSB8fCBbXSkuc3BsaWNlKDEpO1xuICByZXR1cm4ge1xuICAgIGhvc3RuYW1lOiBkZWNvZGUoaG9zdG5hbWUpLFxuICAgIHBvcnRcbiAgfTtcbn1cbmZ1bmN0aW9uIHN0cmluZ2lmeVBhcnNlZFVSTChwYXJzZWQpIHtcbiAgY29uc3QgcGF0aG5hbWUgPSBwYXJzZWQucGF0aG5hbWUgfHwgXCJcIjtcbiAgY29uc3Qgc2VhcmNoID0gcGFyc2VkLnNlYXJjaCA/IChwYXJzZWQuc2VhcmNoLnN0YXJ0c1dpdGgoXCI/XCIpID8gXCJcIiA6IFwiP1wiKSArIHBhcnNlZC5zZWFyY2ggOiBcIlwiO1xuICBjb25zdCBoYXNoID0gcGFyc2VkLmhhc2ggfHwgXCJcIjtcbiAgY29uc3QgYXV0aCA9IHBhcnNlZC5hdXRoID8gcGFyc2VkLmF1dGggKyBcIkBcIiA6IFwiXCI7XG4gIGNvbnN0IGhvc3QgPSBwYXJzZWQuaG9zdCB8fCBcIlwiO1xuICBjb25zdCBwcm90byA9IHBhcnNlZC5wcm90b2NvbCB8fCBwYXJzZWRbcHJvdG9jb2xSZWxhdGl2ZV0gPyAocGFyc2VkLnByb3RvY29sIHx8IFwiXCIpICsgXCIvL1wiIDogXCJcIjtcbiAgcmV0dXJuIHByb3RvICsgYXV0aCArIGhvc3QgKyBwYXRobmFtZSArIHNlYXJjaCArIGhhc2g7XG59XG5jb25zdCBGSUxFTkFNRV9TVFJJQ1RfUkVHRVggPSAvXFwvKFteL10rXFwuW14vXSspJC87XG5jb25zdCBGSUxFTkFNRV9SRUdFWCA9IC9cXC8oW14vXSspJC87XG5mdW5jdGlvbiBwYXJzZUZpbGVuYW1lKGlucHV0ID0gXCJcIiwgeyBzdHJpY3QgfSkge1xuICBjb25zdCB7IHBhdGhuYW1lIH0gPSBwYXJzZVVSTChpbnB1dCk7XG4gIGNvbnN0IG1hdGNoZXMgPSBzdHJpY3QgPyBwYXRobmFtZS5tYXRjaChGSUxFTkFNRV9TVFJJQ1RfUkVHRVgpIDogcGF0aG5hbWUubWF0Y2goRklMRU5BTUVfUkVHRVgpO1xuICByZXR1cm4gbWF0Y2hlcyA/IG1hdGNoZXNbMV0gOiB2b2lkIDA7XG59XG5cbnZhciBfX2RlZlByb3AgPSBPYmplY3QuZGVmaW5lUHJvcGVydHk7XG52YXIgX19kZWZOb3JtYWxQcm9wID0gKG9iaiwga2V5LCB2YWx1ZSkgPT4ga2V5IGluIG9iaiA/IF9fZGVmUHJvcChvYmosIGtleSwgeyBlbnVtZXJhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUsIHdyaXRhYmxlOiB0cnVlLCB2YWx1ZSB9KSA6IG9ialtrZXldID0gdmFsdWU7XG52YXIgX19wdWJsaWNGaWVsZCA9IChvYmosIGtleSwgdmFsdWUpID0+IHtcbiAgX19kZWZOb3JtYWxQcm9wKG9iaiwgdHlwZW9mIGtleSAhPT0gXCJzeW1ib2xcIiA/IGtleSArIFwiXCIgOiBrZXksIHZhbHVlKTtcbiAgcmV0dXJuIHZhbHVlO1xufTtcbmNsYXNzICRVUkwge1xuICBjb25zdHJ1Y3RvcihpbnB1dCA9IFwiXCIpIHtcbiAgICBfX3B1YmxpY0ZpZWxkKHRoaXMsIFwicHJvdG9jb2xcIik7XG4gICAgX19wdWJsaWNGaWVsZCh0aGlzLCBcImhvc3RcIik7XG4gICAgX19wdWJsaWNGaWVsZCh0aGlzLCBcImF1dGhcIik7XG4gICAgX19wdWJsaWNGaWVsZCh0aGlzLCBcInBhdGhuYW1lXCIpO1xuICAgIF9fcHVibGljRmllbGQodGhpcywgXCJxdWVyeVwiLCB7fSk7XG4gICAgX19wdWJsaWNGaWVsZCh0aGlzLCBcImhhc2hcIik7XG4gICAgaWYgKHR5cGVvZiBpbnB1dCAhPT0gXCJzdHJpbmdcIikge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICAgYFVSTCBpbnB1dCBzaG91bGQgYmUgc3RyaW5nIHJlY2VpdmVkICR7dHlwZW9mIGlucHV0fSAoJHtpbnB1dH0pYFxuICAgICAgKTtcbiAgICB9XG4gICAgY29uc3QgcGFyc2VkID0gcGFyc2VVUkwoaW5wdXQpO1xuICAgIHRoaXMucHJvdG9jb2wgPSBkZWNvZGUocGFyc2VkLnByb3RvY29sKTtcbiAgICB0aGlzLmhvc3QgPSBkZWNvZGUocGFyc2VkLmhvc3QpO1xuICAgIHRoaXMuYXV0aCA9IGRlY29kZShwYXJzZWQuYXV0aCk7XG4gICAgdGhpcy5wYXRobmFtZSA9IGRlY29kZVBhdGgocGFyc2VkLnBhdGhuYW1lKTtcbiAgICB0aGlzLnF1ZXJ5ID0gcGFyc2VRdWVyeShwYXJzZWQuc2VhcmNoKTtcbiAgICB0aGlzLmhhc2ggPSBkZWNvZGUocGFyc2VkLmhhc2gpO1xuICB9XG4gIGdldCBob3N0bmFtZSgpIHtcbiAgICByZXR1cm4gcGFyc2VIb3N0KHRoaXMuaG9zdCkuaG9zdG5hbWU7XG4gIH1cbiAgZ2V0IHBvcnQoKSB7XG4gICAgcmV0dXJuIHBhcnNlSG9zdCh0aGlzLmhvc3QpLnBvcnQgfHwgXCJcIjtcbiAgfVxuICBnZXQgdXNlcm5hbWUoKSB7XG4gICAgcmV0dXJuIHBhcnNlQXV0aCh0aGlzLmF1dGgpLnVzZXJuYW1lO1xuICB9XG4gIGdldCBwYXNzd29yZCgpIHtcbiAgICByZXR1cm4gcGFyc2VBdXRoKHRoaXMuYXV0aCkucGFzc3dvcmQgfHwgXCJcIjtcbiAgfVxuICBnZXQgaGFzUHJvdG9jb2woKSB7XG4gICAgcmV0dXJuIHRoaXMucHJvdG9jb2wubGVuZ3RoO1xuICB9XG4gIGdldCBpc0Fic29sdXRlKCkge1xuICAgIHJldHVybiB0aGlzLmhhc1Byb3RvY29sIHx8IHRoaXMucGF0aG5hbWVbMF0gPT09IFwiL1wiO1xuICB9XG4gIGdldCBzZWFyY2goKSB7XG4gICAgY29uc3QgcSA9IHN0cmluZ2lmeVF1ZXJ5KHRoaXMucXVlcnkpO1xuICAgIHJldHVybiBxLmxlbmd0aCA+IDAgPyBcIj9cIiArIHEgOiBcIlwiO1xuICB9XG4gIGdldCBzZWFyY2hQYXJhbXMoKSB7XG4gICAgY29uc3QgcCA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoKTtcbiAgICBmb3IgKGNvbnN0IG5hbWUgaW4gdGhpcy5xdWVyeSkge1xuICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLnF1ZXJ5W25hbWVdO1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgIGZvciAoY29uc3QgdiBvZiB2YWx1ZSkge1xuICAgICAgICAgIHAuYXBwZW5kKG5hbWUsIHYpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwLmFwcGVuZChcbiAgICAgICAgICBuYW1lLFxuICAgICAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiA/IHZhbHVlIDogSlNPTi5zdHJpbmdpZnkodmFsdWUpXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwO1xuICB9XG4gIGdldCBvcmlnaW4oKSB7XG4gICAgcmV0dXJuICh0aGlzLnByb3RvY29sID8gdGhpcy5wcm90b2NvbCArIFwiLy9cIiA6IFwiXCIpICsgZW5jb2RlSG9zdCh0aGlzLmhvc3QpO1xuICB9XG4gIGdldCBmdWxscGF0aCgpIHtcbiAgICByZXR1cm4gZW5jb2RlUGF0aCh0aGlzLnBhdGhuYW1lKSArIHRoaXMuc2VhcmNoICsgZW5jb2RlSGFzaCh0aGlzLmhhc2gpO1xuICB9XG4gIGdldCBlbmNvZGVkQXV0aCgpIHtcbiAgICBpZiAoIXRoaXMuYXV0aCkge1xuICAgICAgcmV0dXJuIFwiXCI7XG4gICAgfVxuICAgIGNvbnN0IHsgdXNlcm5