Calendar/wwwroot/js/v2-demo.js
2026-02-03 00:02:25 +01:00

6463 lines
795 KiB
JavaScript

var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
// node_modules/dayjs/dayjs.min.js
var require_dayjs_min = __commonJS({
"node_modules/dayjs/dayjs.min.js"(exports, module) {
!function(t, e) {
"object" == typeof exports && "undefined" != typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define(e) : (t = "undefined" != typeof globalThis ? globalThis : t || self).dayjs = e();
}(exports, function() {
"use strict";
var t = 1e3, e = 6e4, n = 36e5, r = "millisecond", i = "second", s = "minute", u = "hour", a = "day", o = "week", c = "month", f = "quarter", h = "year", d = "date", l = "Invalid Date", $ = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/, y = /\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g, M = { name: "en", weekdays: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), months: "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), ordinal: function(t2) {
var e2 = ["th", "st", "nd", "rd"], n2 = t2 % 100;
return "[" + t2 + (e2[(n2 - 20) % 10] || e2[n2] || e2[0]) + "]";
} }, m = /* @__PURE__ */ __name(function(t2, e2, n2) {
var r2 = String(t2);
return !r2 || r2.length >= e2 ? t2 : "" + Array(e2 + 1 - r2.length).join(n2) + t2;
}, "m"), v = { s: m, z: function(t2) {
var e2 = -t2.utcOffset(), n2 = Math.abs(e2), r2 = Math.floor(n2 / 60), i2 = n2 % 60;
return (e2 <= 0 ? "+" : "-") + m(r2, 2, "0") + ":" + m(i2, 2, "0");
}, m: /* @__PURE__ */ __name(function t2(e2, n2) {
if (e2.date() < n2.date())
return -t2(n2, e2);
var r2 = 12 * (n2.year() - e2.year()) + (n2.month() - e2.month()), i2 = e2.clone().add(r2, c), s2 = n2 - i2 < 0, u2 = e2.clone().add(r2 + (s2 ? -1 : 1), c);
return +(-(r2 + (n2 - i2) / (s2 ? i2 - u2 : u2 - i2)) || 0);
}, "t"), a: function(t2) {
return t2 < 0 ? Math.ceil(t2) || 0 : Math.floor(t2);
}, p: function(t2) {
return { M: c, y: h, w: o, d: a, D: d, h: u, m: s, s: i, ms: r, Q: f }[t2] || String(t2 || "").toLowerCase().replace(/s$/, "");
}, u: function(t2) {
return void 0 === t2;
} }, g = "en", D = {};
D[g] = M;
var p = "$isDayjsObject", S = /* @__PURE__ */ __name(function(t2) {
return t2 instanceof _ || !(!t2 || !t2[p]);
}, "S"), w = /* @__PURE__ */ __name(function t2(e2, n2, r2) {
var i2;
if (!e2)
return g;
if ("string" == typeof e2) {
var s2 = e2.toLowerCase();
D[s2] && (i2 = s2), n2 && (D[s2] = n2, i2 = s2);
var u2 = e2.split("-");
if (!i2 && u2.length > 1)
return t2(u2[0]);
} else {
var a2 = e2.name;
D[a2] = e2, i2 = a2;
}
return !r2 && i2 && (g = i2), i2 || !r2 && g;
}, "t"), O = /* @__PURE__ */ __name(function(t2, e2) {
if (S(t2))
return t2.clone();
var n2 = "object" == typeof e2 ? e2 : {};
return n2.date = t2, n2.args = arguments, new _(n2);
}, "O"), b = v;
b.l = w, b.i = S, b.w = function(t2, e2) {
return O(t2, { locale: e2.$L, utc: e2.$u, x: e2.$x, $offset: e2.$offset });
};
var _ = function() {
function M2(t2) {
this.$L = w(t2.locale, null, true), this.parse(t2), this.$x = this.$x || t2.x || {}, this[p] = true;
}
__name(M2, "M");
var m2 = M2.prototype;
return m2.parse = function(t2) {
this.$d = function(t3) {
var e2 = t3.date, n2 = t3.utc;
if (null === e2)
return /* @__PURE__ */ new Date(NaN);
if (b.u(e2))
return /* @__PURE__ */ new Date();
if (e2 instanceof Date)
return new Date(e2);
if ("string" == typeof e2 && !/Z$/i.test(e2)) {
var r2 = e2.match($);
if (r2) {
var i2 = r2[2] - 1 || 0, s2 = (r2[7] || "0").substring(0, 3);
return n2 ? new Date(Date.UTC(r2[1], i2, r2[3] || 1, r2[4] || 0, r2[5] || 0, r2[6] || 0, s2)) : new Date(r2[1], i2, r2[3] || 1, r2[4] || 0, r2[5] || 0, r2[6] || 0, s2);
}
}
return new Date(e2);
}(t2), this.init();
}, m2.init = function() {
var t2 = this.$d;
this.$y = t2.getFullYear(), this.$M = t2.getMonth(), this.$D = t2.getDate(), this.$W = t2.getDay(), this.$H = t2.getHours(), this.$m = t2.getMinutes(), this.$s = t2.getSeconds(), this.$ms = t2.getMilliseconds();
}, m2.$utils = function() {
return b;
}, m2.isValid = function() {
return !(this.$d.toString() === l);
}, m2.isSame = function(t2, e2) {
var n2 = O(t2);
return this.startOf(e2) <= n2 && n2 <= this.endOf(e2);
}, m2.isAfter = function(t2, e2) {
return O(t2) < this.startOf(e2);
}, m2.isBefore = function(t2, e2) {
return this.endOf(e2) < O(t2);
}, m2.$g = function(t2, e2, n2) {
return b.u(t2) ? this[e2] : this.set(n2, t2);
}, m2.unix = function() {
return Math.floor(this.valueOf() / 1e3);
}, m2.valueOf = function() {
return this.$d.getTime();
}, m2.startOf = function(t2, e2) {
var n2 = this, r2 = !!b.u(e2) || e2, f2 = b.p(t2), l2 = /* @__PURE__ */ __name(function(t3, e3) {
var i2 = b.w(n2.$u ? Date.UTC(n2.$y, e3, t3) : new Date(n2.$y, e3, t3), n2);
return r2 ? i2 : i2.endOf(a);
}, "l"), $2 = /* @__PURE__ */ __name(function(t3, e3) {
return b.w(n2.toDate()[t3].apply(n2.toDate("s"), (r2 ? [0, 0, 0, 0] : [23, 59, 59, 999]).slice(e3)), n2);
}, "$"), y2 = this.$W, M3 = this.$M, m3 = this.$D, v2 = "set" + (this.$u ? "UTC" : "");
switch (f2) {
case h:
return r2 ? l2(1, 0) : l2(31, 11);
case c:
return r2 ? l2(1, M3) : l2(0, M3 + 1);
case o:
var g2 = this.$locale().weekStart || 0, D2 = (y2 < g2 ? y2 + 7 : y2) - g2;
return l2(r2 ? m3 - D2 : m3 + (6 - D2), M3);
case a:
case d:
return $2(v2 + "Hours", 0);
case u:
return $2(v2 + "Minutes", 1);
case s:
return $2(v2 + "Seconds", 2);
case i:
return $2(v2 + "Milliseconds", 3);
default:
return this.clone();
}
}, m2.endOf = function(t2) {
return this.startOf(t2, false);
}, m2.$set = function(t2, e2) {
var n2, o2 = b.p(t2), f2 = "set" + (this.$u ? "UTC" : ""), l2 = (n2 = {}, n2[a] = f2 + "Date", n2[d] = f2 + "Date", n2[c] = f2 + "Month", n2[h] = f2 + "FullYear", n2[u] = f2 + "Hours", n2[s] = f2 + "Minutes", n2[i] = f2 + "Seconds", n2[r] = f2 + "Milliseconds", n2)[o2], $2 = o2 === a ? this.$D + (e2 - this.$W) : e2;
if (o2 === c || o2 === h) {
var y2 = this.clone().set(d, 1);
y2.$d[l2]($2), y2.init(), this.$d = y2.set(d, Math.min(this.$D, y2.daysInMonth())).$d;
} else
l2 && this.$d[l2]($2);
return this.init(), this;
}, m2.set = function(t2, e2) {
return this.clone().$set(t2, e2);
}, m2.get = function(t2) {
return this[b.p(t2)]();
}, m2.add = function(r2, f2) {
var d2, l2 = this;
r2 = Number(r2);
var $2 = b.p(f2), y2 = /* @__PURE__ */ __name(function(t2) {
var e2 = O(l2);
return b.w(e2.date(e2.date() + Math.round(t2 * r2)), l2);
}, "y");
if ($2 === c)
return this.set(c, this.$M + r2);
if ($2 === h)
return this.set(h, this.$y + r2);
if ($2 === a)
return y2(1);
if ($2 === o)
return y2(7);
var M3 = (d2 = {}, d2[s] = e, d2[u] = n, d2[i] = t, d2)[$2] || 1, m3 = this.$d.getTime() + r2 * M3;
return b.w(m3, this);
}, m2.subtract = function(t2, e2) {
return this.add(-1 * t2, e2);
}, m2.format = function(t2) {
var e2 = this, n2 = this.$locale();
if (!this.isValid())
return n2.invalidDate || l;
var r2 = t2 || "YYYY-MM-DDTHH:mm:ssZ", i2 = b.z(this), s2 = this.$H, u2 = this.$m, a2 = this.$M, o2 = n2.weekdays, c2 = n2.months, f2 = n2.meridiem, h2 = /* @__PURE__ */ __name(function(t3, n3, i3, s3) {
return t3 && (t3[n3] || t3(e2, r2)) || i3[n3].slice(0, s3);
}, "h"), d2 = /* @__PURE__ */ __name(function(t3) {
return b.s(s2 % 12 || 12, t3, "0");
}, "d"), $2 = f2 || function(t3, e3, n3) {
var r3 = t3 < 12 ? "AM" : "PM";
return n3 ? r3.toLowerCase() : r3;
};
return r2.replace(y, function(t3, r3) {
return r3 || function(t4) {
switch (t4) {
case "YY":
return String(e2.$y).slice(-2);
case "YYYY":
return b.s(e2.$y, 4, "0");
case "M":
return a2 + 1;
case "MM":
return b.s(a2 + 1, 2, "0");
case "MMM":
return h2(n2.monthsShort, a2, c2, 3);
case "MMMM":
return h2(c2, a2);
case "D":
return e2.$D;
case "DD":
return b.s(e2.$D, 2, "0");
case "d":
return String(e2.$W);
case "dd":
return h2(n2.weekdaysMin, e2.$W, o2, 2);
case "ddd":
return h2(n2.weekdaysShort, e2.$W, o2, 3);
case "dddd":
return o2[e2.$W];
case "H":
return String(s2);
case "HH":
return b.s(s2, 2, "0");
case "h":
return d2(1);
case "hh":
return d2(2);
case "a":
return $2(s2, u2, true);
case "A":
return $2(s2, u2, false);
case "m":
return String(u2);
case "mm":
return b.s(u2, 2, "0");
case "s":
return String(e2.$s);
case "ss":
return b.s(e2.$s, 2, "0");
case "SSS":
return b.s(e2.$ms, 3, "0");
case "Z":
return i2;
}
return null;
}(t3) || i2.replace(":", "");
});
}, m2.utcOffset = function() {
return 15 * -Math.round(this.$d.getTimezoneOffset() / 15);
}, m2.diff = function(r2, d2, l2) {
var $2, y2 = this, M3 = b.p(d2), m3 = O(r2), v2 = (m3.utcOffset() - this.utcOffset()) * e, g2 = this - m3, D2 = /* @__PURE__ */ __name(function() {
return b.m(y2, m3);
}, "D");
switch (M3) {
case h:
$2 = D2() / 12;
break;
case c:
$2 = D2();
break;
case f:
$2 = D2() / 3;
break;
case o:
$2 = (g2 - v2) / 6048e5;
break;
case a:
$2 = (g2 - v2) / 864e5;
break;
case u:
$2 = g2 / n;
break;
case s:
$2 = g2 / e;
break;
case i:
$2 = g2 / t;
break;
default:
$2 = g2;
}
return l2 ? $2 : b.a($2);
}, m2.daysInMonth = function() {
return this.endOf(c).$D;
}, m2.$locale = function() {
return D[this.$L];
}, m2.locale = function(t2, e2) {
if (!t2)
return this.$L;
var n2 = this.clone(), r2 = w(t2, e2, true);
return r2 && (n2.$L = r2), n2;
}, m2.clone = function() {
return b.w(this.$d, this);
}, m2.toDate = function() {
return new Date(this.valueOf());
}, m2.toJSON = function() {
return this.isValid() ? this.toISOString() : null;
}, m2.toISOString = function() {
return this.$d.toISOString();
}, m2.toString = function() {
return this.$d.toUTCString();
}, M2;
}(), k = _.prototype;
return O.prototype = k, [["$ms", r], ["$s", i], ["$m", s], ["$H", u], ["$W", a], ["$M", c], ["$y", h], ["$D", d]].forEach(function(t2) {
k[t2[1]] = function(e2) {
return this.$g(e2, t2[0], t2[1]);
};
}), O.extend = function(t2, e2) {
return t2.$i || (t2(e2, _, O), t2.$i = true), O;
}, O.locale = w, O.isDayjs = S, O.unix = function(t2) {
return O(1e3 * t2);
}, O.en = D[g], O.Ls = D, O.p = {}, O;
});
}
});
// node_modules/dayjs/plugin/utc.js
var require_utc = __commonJS({
"node_modules/dayjs/plugin/utc.js"(exports, module) {
!function(t, i) {
"object" == typeof exports && "undefined" != typeof module ? module.exports = i() : "function" == typeof define && define.amd ? define(i) : (t = "undefined" != typeof globalThis ? globalThis : t || self).dayjs_plugin_utc = i();
}(exports, function() {
"use strict";
var t = "minute", i = /[+-]\d\d(?::?\d\d)?/g, e = /([+-]|\d\d)/g;
return function(s, f, n) {
var u = f.prototype;
n.utc = function(t2) {
var i2 = { date: t2, utc: true, args: arguments };
return new f(i2);
}, u.utc = function(i2) {
var e2 = n(this.toDate(), { locale: this.$L, utc: true });
return i2 ? e2.add(this.utcOffset(), t) : e2;
}, u.local = function() {
return n(this.toDate(), { locale: this.$L, utc: false });
};
var r = u.parse;
u.parse = function(t2) {
t2.utc && (this.$u = true), this.$utils().u(t2.$offset) || (this.$offset = t2.$offset), r.call(this, t2);
};
var o = u.init;
u.init = function() {
if (this.$u) {
var t2 = this.$d;
this.$y = t2.getUTCFullYear(), this.$M = t2.getUTCMonth(), this.$D = t2.getUTCDate(), this.$W = t2.getUTCDay(), this.$H = t2.getUTCHours(), this.$m = t2.getUTCMinutes(), this.$s = t2.getUTCSeconds(), this.$ms = t2.getUTCMilliseconds();
} else
o.call(this);
};
var a = u.utcOffset;
u.utcOffset = function(s2, f2) {
var n2 = this.$utils().u;
if (n2(s2))
return this.$u ? 0 : n2(this.$offset) ? a.call(this) : this.$offset;
if ("string" == typeof s2 && (s2 = function(t2) {
void 0 === t2 && (t2 = "");
var s3 = t2.match(i);
if (!s3)
return null;
var f3 = ("" + s3[0]).match(e) || ["-", 0, 0], n3 = f3[0], u3 = 60 * +f3[1] + +f3[2];
return 0 === u3 ? 0 : "+" === n3 ? u3 : -u3;
}(s2), null === s2))
return this;
var u2 = Math.abs(s2) <= 16 ? 60 * s2 : s2;
if (0 === u2)
return this.utc(f2);
var r2 = this.clone();
if (f2)
return r2.$offset = u2, r2.$u = false, r2;
var o2 = this.$u ? this.toDate().getTimezoneOffset() : -1 * this.utcOffset();
return (r2 = this.local().add(u2 + o2, t)).$offset = u2, r2.$x.$localOffset = o2, r2;
};
var h = u.format;
u.format = function(t2) {
var i2 = t2 || (this.$u ? "YYYY-MM-DDTHH:mm:ss[Z]" : "");
return h.call(this, i2);
}, u.valueOf = function() {
var t2 = this.$utils().u(this.$offset) ? 0 : this.$offset + (this.$x.$localOffset || this.$d.getTimezoneOffset());
return this.$d.valueOf() - 6e4 * t2;
}, u.isUTC = function() {
return !!this.$u;
}, u.toISOString = function() {
return this.toDate().toISOString();
}, u.toString = function() {
return this.toDate().toUTCString();
};
var l = u.toDate;
u.toDate = function(t2) {
return "s" === t2 && this.$offset ? n(this.format("YYYY-MM-DD HH:mm:ss:SSS")).toDate() : l.call(this);
};
var c = u.diff;
u.diff = function(t2, i2, e2) {
if (t2 && this.$u === t2.$u)
return c.call(this, t2, i2, e2);
var s2 = this.local(), f2 = n(t2).local();
return c.call(s2, f2, i2, e2);
};
};
});
}
});
// node_modules/dayjs/plugin/timezone.js
var require_timezone = __commonJS({
"node_modules/dayjs/plugin/timezone.js"(exports, module) {
!function(t, e) {
"object" == typeof exports && "undefined" != typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define(e) : (t = "undefined" != typeof globalThis ? globalThis : t || self).dayjs_plugin_timezone = e();
}(exports, function() {
"use strict";
var t = { year: 0, month: 1, day: 2, hour: 3, minute: 4, second: 5 }, e = {};
return function(n, i, o) {
var r, a = /* @__PURE__ */ __name(function(t2, n2, i2) {
void 0 === i2 && (i2 = {});
var o2 = new Date(t2), r2 = function(t3, n3) {
void 0 === n3 && (n3 = {});
var i3 = n3.timeZoneName || "short", o3 = t3 + "|" + i3, r3 = e[o3];
return r3 || (r3 = new Intl.DateTimeFormat("en-US", { hour12: false, timeZone: t3, year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit", timeZoneName: i3 }), e[o3] = r3), r3;
}(n2, i2);
return r2.formatToParts(o2);
}, "a"), u = /* @__PURE__ */ __name(function(e2, n2) {
for (var i2 = a(e2, n2), r2 = [], u2 = 0; u2 < i2.length; u2 += 1) {
var f2 = i2[u2], s2 = f2.type, m = f2.value, c = t[s2];
c >= 0 && (r2[c] = parseInt(m, 10));
}
var d = r2[3], l = 24 === d ? 0 : d, h = r2[0] + "-" + r2[1] + "-" + r2[2] + " " + l + ":" + r2[4] + ":" + r2[5] + ":000", v = +e2;
return (o.utc(h).valueOf() - (v -= v % 1e3)) / 6e4;
}, "u"), f = i.prototype;
f.tz = function(t2, e2) {
void 0 === t2 && (t2 = r);
var n2, i2 = this.utcOffset(), a2 = this.toDate(), u2 = a2.toLocaleString("en-US", { timeZone: t2 }), f2 = Math.round((a2 - new Date(u2)) / 1e3 / 60), s2 = 15 * -Math.round(a2.getTimezoneOffset() / 15) - f2;
if (!Number(s2))
n2 = this.utcOffset(0, e2);
else if (n2 = o(u2, { locale: this.$L }).$set("millisecond", this.$ms).utcOffset(s2, true), e2) {
var m = n2.utcOffset();
n2 = n2.add(i2 - m, "minute");
}
return n2.$x.$timezone = t2, n2;
}, f.offsetName = function(t2) {
var e2 = this.$x.$timezone || o.tz.guess(), n2 = a(this.valueOf(), e2, { timeZoneName: t2 }).find(function(t3) {
return "timezonename" === t3.type.toLowerCase();
});
return n2 && n2.value;
};
var s = f.startOf;
f.startOf = function(t2, e2) {
if (!this.$x || !this.$x.$timezone)
return s.call(this, t2, e2);
var n2 = o(this.format("YYYY-MM-DD HH:mm:ss:SSS"), { locale: this.$L });
return s.call(n2, t2, e2).tz(this.$x.$timezone, true);
}, o.tz = function(t2, e2, n2) {
var i2 = n2 && e2, a2 = n2 || e2 || r, f2 = u(+o(), a2);
if ("string" != typeof t2)
return o(t2).tz(a2);
var s2 = function(t3, e3, n3) {
var i3 = t3 - 60 * e3 * 1e3, o2 = u(i3, n3);
if (e3 === o2)
return [i3, e3];
var r2 = u(i3 -= 60 * (o2 - e3) * 1e3, n3);
return o2 === r2 ? [i3, o2] : [t3 - 60 * Math.min(o2, r2) * 1e3, Math.max(o2, r2)];
}(o.utc(t2, i2).valueOf(), f2, a2), m = s2[0], c = s2[1], d = o(m).utcOffset(c);
return d.$x.$timezone = a2, d;
}, o.tz.guess = function() {
return Intl.DateTimeFormat().resolvedOptions().timeZone;
}, o.tz.setDefault = function(t2) {
r = t2;
};
};
});
}
});
// node_modules/dayjs/plugin/isoWeek.js
var require_isoWeek = __commonJS({
"node_modules/dayjs/plugin/isoWeek.js"(exports, module) {
!function(e, t) {
"object" == typeof exports && "undefined" != typeof module ? module.exports = t() : "function" == typeof define && define.amd ? define(t) : (e = "undefined" != typeof globalThis ? globalThis : e || self).dayjs_plugin_isoWeek = t();
}(exports, function() {
"use strict";
var e = "day";
return function(t, i, s) {
var a = /* @__PURE__ */ __name(function(t2) {
return t2.add(4 - t2.isoWeekday(), e);
}, "a"), d = i.prototype;
d.isoWeekYear = function() {
return a(this).year();
}, d.isoWeek = function(t2) {
if (!this.$utils().u(t2))
return this.add(7 * (t2 - this.isoWeek()), e);
var i2, d2, n2, o, r = a(this), u = (i2 = this.isoWeekYear(), d2 = this.$u, n2 = (d2 ? s.utc : s)().year(i2).startOf("year"), o = 4 - n2.isoWeekday(), n2.isoWeekday() > 4 && (o += 7), n2.add(o, e));
return r.diff(u, "week") + 1;
}, d.isoWeekday = function(e2) {
return this.$utils().u(e2) ? this.day() || 7 : this.day(this.day() % 7 ? e2 : e2 - 7);
};
var n = d.startOf;
d.startOf = function(e2, t2) {
var i2 = this.$utils(), s2 = !!i2.u(t2) || t2;
return "isoweek" === i2.p(e2) ? s2 ? this.date(this.date() - (this.isoWeekday() - 1)).startOf("day") : this.date(this.date() - 1 - (this.isoWeekday() - 1) + 7).endOf("day") : n.bind(this)(e2, t2);
};
};
});
}
});
// node_modules/@novadi/core/dist/token.js
var tokenCounter = 0;
function Token(description) {
const id = ++tokenCounter;
const sym = Symbol(description ? `Token(${description})` : `Token#${id}`);
const token2 = {
symbol: sym,
description,
toString() {
return description ? `Token<${description}>` : `Token<#${id}>`;
}
};
return token2;
}
__name(Token, "Token");
// node_modules/@novadi/core/dist/errors.js
var _ContainerError = class _ContainerError extends Error {
constructor(message) {
super(message);
this.name = "ContainerError";
}
};
__name(_ContainerError, "ContainerError");
var ContainerError = _ContainerError;
var _BindingNotFoundError = class _BindingNotFoundError extends ContainerError {
constructor(tokenDescription, path = []) {
const pathStr = path.length > 0 ? `
Dependency path: ${path.join(" -> ")}` : "";
super(`Token "${tokenDescription}" is not bound or registered in the container.${pathStr}`);
this.name = "BindingNotFoundError";
}
};
__name(_BindingNotFoundError, "BindingNotFoundError");
var BindingNotFoundError = _BindingNotFoundError;
var _CircularDependencyError = class _CircularDependencyError extends ContainerError {
constructor(path) {
super(`Circular dependency detected: ${path.join(" -> ")}`);
this.name = "CircularDependencyError";
}
};
__name(_CircularDependencyError, "CircularDependencyError");
var CircularDependencyError = _CircularDependencyError;
// node_modules/@novadi/core/dist/autowire.js
var paramNameCache = /* @__PURE__ */ new WeakMap();
function extractParameterNames(constructor) {
const cached = paramNameCache.get(constructor);
if (cached) {
return cached;
}
const fnStr = constructor.toString();
const match = fnStr.match(/constructor\s*\(([^)]*)\)/) || fnStr.match(/^[^(]*\(([^)]*)\)/);
if (!match || !match[1]) {
return [];
}
const params = match[1].split(",").map((param) => param.trim()).filter((param) => param.length > 0).map((param) => {
let name = param.split(/[:=]/)[0].trim();
name = name.replace(/^((public|private|protected|readonly)\s+)+/, "");
if (name.includes("{") || name.includes("[")) {
return null;
}
return name;
}).filter((name) => name !== null);
paramNameCache.set(constructor, params);
return params;
}
__name(extractParameterNames, "extractParameterNames");
function resolveByMap(constructor, container2, options) {
if (!options.map) {
throw new Error("AutoWire map strategy requires options.map to be defined");
}
const paramNames = extractParameterNames(constructor);
const resolvedDeps = [];
for (const paramName of paramNames) {
const resolver = options.map[paramName];
if (resolver === void 0) {
if (options.strict) {
throw new Error(`Cannot resolve parameter "${paramName}" on ${constructor.name}. Not found in autowire map. Add it to the map: .autoWire({ map: { ${paramName}: ... } })`);
} else {
resolvedDeps.push(void 0);
}
continue;
}
if (typeof resolver === "function") {
resolvedDeps.push(resolver(container2));
} else {
resolvedDeps.push(container2.resolve(resolver));
}
}
return resolvedDeps;
}
__name(resolveByMap, "resolveByMap");
function resolveByMapResolvers(_constructor, container2, options) {
if (!options.mapResolvers || options.mapResolvers.length === 0) {
return [];
}
const resolvedDeps = [];
for (let i = 0; i < options.mapResolvers.length; i++) {
const resolver = options.mapResolvers[i];
if (resolver === void 0) {
resolvedDeps.push(void 0);
} else if (typeof resolver === "function") {
resolvedDeps.push(resolver(container2));
} else {
resolvedDeps.push(container2.resolve(resolver));
}
}
return resolvedDeps;
}
__name(resolveByMapResolvers, "resolveByMapResolvers");
function autowire(constructor, container2, options) {
const opts = {
by: "paramName",
strict: false,
...options
};
if (opts.mapResolvers && opts.mapResolvers.length > 0) {
return resolveByMapResolvers(constructor, container2, opts);
}
if (opts.map && Object.keys(opts.map).length > 0) {
return resolveByMap(constructor, container2, opts);
}
return [];
}
__name(autowire, "autowire");
// node_modules/@novadi/core/dist/builder.js
var _RegistrationBuilder = class _RegistrationBuilder {
constructor(pending, registrations) {
this.registrations = registrations;
this.configs = [];
this.defaultLifetime = "singleton";
this.pending = pending;
}
/**
* Bind this registration to a token or interface type
*
* @overload
* @param {Token<U>} token - Explicit token for binding
*
* @overload
* @param {string} typeName - Interface type name (auto-generated by transformer)
*/
as(tokenOrTypeName) {
if (tokenOrTypeName && typeof tokenOrTypeName === "object" && "symbol" in tokenOrTypeName) {
const config = {
token: tokenOrTypeName,
type: this.pending.type,
value: this.pending.value,
factory: this.pending.factory,
constructor: this.pending.constructor,
lifetime: this.defaultLifetime
};
this.configs.push(config);
this.registrations.push(config);
return this;
} else {
const config = {
token: null,
// Will be set during build()
type: this.pending.type,
value: this.pending.value,
factory: this.pending.factory,
constructor: this.pending.constructor,
lifetime: this.defaultLifetime,
interfaceType: tokenOrTypeName
};
this.configs.push(config);
this.registrations.push(config);
return this;
}
}
/**
* Register as default implementation for an interface
* Combines as() + asDefault()
*/
asDefaultInterface(typeName) {
this.as("TInterface", typeName);
return this.asDefault();
}
/**
* Register as a keyed interface implementation
* Combines as() + keyed()
*/
asKeyedInterface(key, typeName) {
this.as("TInterface", typeName);
return this.keyed(key);
}
/**
* Register as multiple implemented interfaces
*/
asImplementedInterfaces(tokens) {
if (tokens.length === 0) {
return this;
}
if (this.configs.length > 0) {
for (const config of this.configs) {
config.lifetime = "singleton";
config.additionalTokens = config.additionalTokens || [];
config.additionalTokens.push(...tokens);
}
return this;
}
const firstConfig = {
token: tokens[0],
type: this.pending.type,
value: this.pending.value,
factory: this.pending.factory,
constructor: this.pending.constructor,
lifetime: "singleton"
};
this.configs.push(firstConfig);
this.registrations.push(firstConfig);
for (let i = 1; i < tokens.length; i++) {
firstConfig.additionalTokens = firstConfig.additionalTokens || [];
firstConfig.additionalTokens.push(tokens[i]);
}
return this;
}
/**
* Set singleton lifetime (one instance for entire container)
*/
singleInstance() {
for (const config of this.configs) {
config.lifetime = "singleton";
}
return this;
}
/**
* Set per-request lifetime (one instance per resolve call tree)
*/
instancePerRequest() {
for (const config of this.configs) {
config.lifetime = "per-request";
}
return this;
}
/**
* Set transient lifetime (new instance every time)
* Alias for default behavior
*/
instancePerDependency() {
for (const config of this.configs) {
config.lifetime = "transient";
}
return this;
}
/**
* Name this registration for named resolution
*/
named(name) {
for (const config of this.configs) {
config.name = name;
}
return this;
}
/**
* Key this registration for keyed resolution
*/
keyed(key) {
for (const config of this.configs) {
config.key = key;
}
return this;
}
/**
* Mark this as default registration
* Default registrations don't override existing ones
*/
asDefault() {
for (const config of this.configs) {
config.isDefault = true;
}
return this;
}
/**
* Only register if token not already registered
*/
ifNotRegistered() {
for (const config of this.configs) {
config.ifNotRegistered = true;
}
return this;
}
/**
* Specify parameter values for constructor (primitives and constants)
* Use this for non-DI parameters like strings, numbers, config values
*/
withParameters(parameters) {
for (const config of this.configs) {
config.parameterValues = parameters;
}
return this;
}
/**
* Enable automatic dependency injection (autowiring)
* Supports three strategies: paramName (default), map, and class
*
* @example
* ```ts
* // Strategy 1: paramName (default, requires non-minified code in dev)
* builder.registerType(EventBus).as<IEventBus>().autoWire()
*
* // Strategy 2: map (minify-safe, explicit)
* builder.registerType(EventBus).as<IEventBus>().autoWire({
* map: {
* logger: (c) => c.resolveType<ILogger>()
* }
* })
*
* // Strategy 3: class (requires build-time codegen)
* builder.registerType(EventBus).as<IEventBus>().autoWire({ by: 'class' })
* ```
*/
autoWire(options) {
for (const config of this.configs) {
config.autowireOptions = options || { by: "paramName", strict: false };
}
return this;
}
};
__name(_RegistrationBuilder, "RegistrationBuilder");
var RegistrationBuilder = _RegistrationBuilder;
var _Builder = class _Builder {
constructor(baseContainer) {
this.baseContainer = baseContainer;
this.registrations = [];
}
/**
* Register a class constructor
*/
registerType(constructor) {
const pending = {
type: "type",
value: null,
constructor
};
return new RegistrationBuilder(pending, this.registrations);
}
/**
* Register a pre-created instance
*/
registerInstance(instance) {
const pending = {
type: "instance",
value: instance,
constructor: void 0
};
return new RegistrationBuilder(pending, this.registrations);
}
/**
* Register a factory function
*/
register(factory) {
const pending = {
type: "factory",
value: null,
factory,
constructor: void 0
};
return new RegistrationBuilder(pending, this.registrations);
}
/**
* Register a module (function that adds multiple registrations)
*/
module(moduleFunc) {
moduleFunc(this);
return this;
}
/**
* Resolve interface type names to tokens
* @internal
*/
resolveInterfaceTokens(container2) {
for (const config of this.registrations) {
if (config.interfaceType !== void 0 && !config.token) {
config.token = container2.interfaceToken(config.interfaceType);
}
}
}
/**
* Identify tokens that have non-default registrations
* @internal
*/
identifyNonDefaultTokens() {
const tokensWithNonDefaults = /* @__PURE__ */ new Set();
for (const config of this.registrations) {
if (!config.isDefault && !config.name && config.key === void 0) {
tokensWithNonDefaults.add(config.token);
}
}
return tokensWithNonDefaults;
}
/**
* Check if registration should be skipped
* @internal
*/
shouldSkipRegistration(config, tokensWithNonDefaults, registeredTokens) {
if (config.isDefault && !config.name && config.key === void 0 && tokensWithNonDefaults.has(config.token)) {
return true;
}
if (config.ifNotRegistered && registeredTokens.has(config.token)) {
return true;
}
if (config.isDefault && registeredTokens.has(config.token)) {
return true;
}
return false;
}
/**
* Create binding token for registration (named, keyed, or multi)
* @internal
*/
createBindingToken(config, namedRegistrations, keyedRegistrations, multiRegistrations) {
if (config.name) {
const bindingToken = Token(`__named_${config.name}`);
namedRegistrations.set(config.name, { ...config, token: bindingToken });
return bindingToken;
} else if (config.key !== void 0) {
const keyStr = typeof config.key === "symbol" ? config.key.toString() : config.key;
const bindingToken = Token(`__keyed_${keyStr}`);
keyedRegistrations.set(config.key, { ...config, token: bindingToken });
return bindingToken;
} else {
if (multiRegistrations.has(config.token)) {
const bindingToken = Token(`__multi_${config.token.toString()}_${multiRegistrations.get(config.token).length}`);
multiRegistrations.get(config.token).push(bindingToken);
return bindingToken;
} else {
multiRegistrations.set(config.token, [config.token]);
return config.token;
}
}
}
/**
* Register additional interfaces for a config
* @internal
*/
registerAdditionalInterfaces(container2, config, bindingToken, registeredTokens) {
if (config.additionalTokens) {
for (const additionalToken of config.additionalTokens) {
container2.bindFactory(additionalToken, (c) => c.resolve(bindingToken), { lifetime: config.lifetime });
registeredTokens.add(additionalToken);
}
}
}
/**
* Build the container with all registered bindings
*/
build() {
const container2 = this.baseContainer.createChild();
this.resolveInterfaceTokens(container2);
const registeredTokens = /* @__PURE__ */ new Set();
const namedRegistrations = /* @__PURE__ */ new Map();
const keyedRegistrations = /* @__PURE__ */ new Map();
const multiRegistrations = /* @__PURE__ */ new Map();
const tokensWithNonDefaults = this.identifyNonDefaultTokens();
for (const config of this.registrations) {
if (this.shouldSkipRegistration(config, tokensWithNonDefaults, registeredTokens)) {
continue;
}
const bindingToken = this.createBindingToken(config, namedRegistrations, keyedRegistrations, multiRegistrations);
this.applyRegistration(container2, { ...config, token: bindingToken });
registeredTokens.add(config.token);
this.registerAdditionalInterfaces(container2, config, bindingToken, registeredTokens);
}
;
container2.__namedRegistrations = namedRegistrations;
container2.__keyedRegistrations = keyedRegistrations;
container2.__multiRegistrations = multiRegistrations;
return container2;
}
/**
* Analyze constructor to detect dependencies
* @internal
*/
analyzeConstructor(constructor) {
const constructorStr = constructor.toString();
const hasDependencies = /constructor\s*\([^)]+\)/.test(constructorStr);
return { hasDependencies };
}
/**
* Create optimized factory for zero-dependency constructors
* @internal
*/
createOptimizedFactory(container2, config, options) {
if (config.lifetime === "singleton") {
const instance = new config.constructor();
container2.bindValue(config.token, instance);
} else if (config.lifetime === "transient") {
const ctor = config.constructor;
const fastFactory = /* @__PURE__ */ __name(() => new ctor(), "fastFactory");
container2.fastTransientCache.set(config.token, fastFactory);
container2.bindFactory(config.token, fastFactory, options);
} else {
const factory = /* @__PURE__ */ __name(() => new config.constructor(), "factory");
container2.bindFactory(config.token, factory, options);
}
}
/**
* Create autowire factory
* @internal
*/
createAutoWireFactory(container2, config, options) {
const factory = /* @__PURE__ */ __name((c) => {
const resolvedDeps = autowire(config.constructor, c, config.autowireOptions);
return new config.constructor(...resolvedDeps);
}, "factory");
container2.bindFactory(config.token, factory, options);
}
/**
* Create withParameters factory
* @internal
*/
createParameterFactory(container2, config, options) {
const factory = /* @__PURE__ */ __name(() => {
const values = Object.values(config.parameterValues);
return new config.constructor(...values);
}, "factory");
container2.bindFactory(config.token, factory, options);
}
/**
* Apply type registration (class constructor)
* @internal
*/
applyTypeRegistration(container2, config, options) {
const { hasDependencies } = this.analyzeConstructor(config.constructor);
if (!hasDependencies && !config.autowireOptions && !config.parameterValues) {
this.createOptimizedFactory(container2, config, options);
return;
}
if (config.autowireOptions) {
this.createAutoWireFactory(container2, config, options);
return;
}
if (config.parameterValues) {
this.createParameterFactory(container2, config, options);
return;
}
if (hasDependencies) {
const className = config.constructor.name || "UnnamedClass";
throw new Error(`Service "${className}" has constructor dependencies but no autowiring configuration.
Solutions:
1. \u2B50 Use the NovaDI transformer (recommended):
- Add "@novadi/core/unplugin" to your build config
- Transformer automatically generates .autoWire() for all dependencies
2. Add manual autowiring:
.autoWire({ map: { /* param: resolver */ } })
3. Use a factory function:
.register((c) => new ${className}(...))
See docs: https://github.com/janus007/NovaDI#autowire`);
}
const factory = /* @__PURE__ */ __name(() => new config.constructor(), "factory");
container2.bindFactory(config.token, factory, options);
}
applyRegistration(container2, config) {
const options = { lifetime: config.lifetime };
switch (config.type) {
case "instance":
container2.bindValue(config.token, config.value);
break;
case "factory":
container2.bindFactory(config.token, config.factory, options);
break;
case "type":
this.applyTypeRegistration(container2, config, options);
break;
}
}
};
__name(_Builder, "Builder");
var Builder = _Builder;
// node_modules/@novadi/core/dist/container.js
function isDisposable(obj) {
return obj && typeof obj.dispose === "function";
}
__name(isDisposable, "isDisposable");
var _ResolutionContext = class _ResolutionContext {
constructor() {
this.resolvingStack = /* @__PURE__ */ new Set();
this.perRequestCache = /* @__PURE__ */ new Map();
}
isResolving(token2) {
return this.resolvingStack.has(token2);
}
enterResolve(token2) {
this.resolvingStack.add(token2);
}
exitResolve(token2) {
this.resolvingStack.delete(token2);
this.path = void 0;
}
getPath() {
if (!this.path) {
this.path = Array.from(this.resolvingStack).map((t) => t.toString());
}
return [...this.path];
}
cachePerRequest(token2, instance) {
this.perRequestCache.set(token2, instance);
}
getPerRequest(token2) {
return this.perRequestCache.get(token2);
}
hasPerRequest(token2) {
return this.perRequestCache.has(token2);
}
/**
* Reset context for reuse in object pool
* Performance: Reusing contexts avoids heap allocations
*/
reset() {
this.resolvingStack.clear();
this.perRequestCache.clear();
this.path = void 0;
}
};
__name(_ResolutionContext, "ResolutionContext");
var ResolutionContext = _ResolutionContext;
var _ResolutionContextPool = class _ResolutionContextPool {
constructor() {
this.pool = [];
this.maxSize = 10;
}
acquire() {
const context = this.pool.pop();
if (context) {
context.reset();
return context;
}
return new ResolutionContext();
}
release(context) {
if (this.pool.length < this.maxSize) {
this.pool.push(context);
}
}
};
__name(_ResolutionContextPool, "ResolutionContextPool");
var ResolutionContextPool = _ResolutionContextPool;
var _Container = class _Container {
constructor(parent) {
this.bindings = /* @__PURE__ */ new Map();
this.singletonCache = /* @__PURE__ */ new Map();
this.singletonOrder = [];
this.interfaceRegistry = /* @__PURE__ */ new Map();
this.interfaceTokenCache = /* @__PURE__ */ new Map();
this.fastTransientCache = /* @__PURE__ */ new Map();
this.ultraFastSingletonCache = /* @__PURE__ */ new Map();
this.parent = parent;
}
/**
* Bind a pre-created value to a token
*/
bindValue(token2, value) {
this.bindings.set(token2, {
type: "value",
lifetime: "singleton",
value,
constructor: void 0
});
this.invalidateBindingCache();
}
/**
* Bind a factory function to a token
*/
bindFactory(token2, factory, options) {
this.bindings.set(token2, {
type: "factory",
lifetime: options?.lifetime || "transient",
factory,
dependencies: options?.dependencies,
constructor: void 0
});
this.invalidateBindingCache();
}
/**
* Bind a class constructor to a token
*/
bindClass(token2, constructor, options) {
const binding = {
type: "class",
lifetime: options?.lifetime || "transient",
constructor,
dependencies: options?.dependencies
};
this.bindings.set(token2, binding);
this.invalidateBindingCache();
if (binding.lifetime === "transient" && (!binding.dependencies || binding.dependencies.length === 0)) {
this.fastTransientCache.set(token2, () => new constructor());
}
}
/**
* Resolve a dependency synchronously
* Performance optimized with multiple fast paths
*/
resolve(token2) {
const cached = this.tryGetFromCaches(token2);
if (cached !== void 0) {
return cached;
}
if (this.currentContext) {
return this.resolveWithContext(token2, this.currentContext);
}
const context = _Container.contextPool.acquire();
this.currentContext = context;
try {
return this.resolveWithContext(token2, context);
} finally {
this.currentContext = void 0;
_Container.contextPool.release(context);
}
}
/**
* SPECIALIZED: Ultra-fast singleton resolve (no safety checks)
* Use ONLY when you're 100% sure the token is a registered singleton
* @internal For performance-critical paths only
*/
resolveSingletonUnsafe(token2) {
return this.ultraFastSingletonCache.get(token2) ?? this.singletonCache.get(token2);
}
/**
* SPECIALIZED: Fast transient resolve for zero-dependency classes
* Skips all context creation and circular dependency checks
* @internal For performance-critical paths only
*/
resolveTransientSimple(token2) {
const factory = this.fastTransientCache.get(token2);
if (factory) {
return factory();
}
return this.resolve(token2);
}
/**
* SPECIALIZED: Batch resolve multiple dependencies at once
* More efficient than multiple individual resolves
*/
resolveBatch(tokens) {
const wasResolving = !!this.currentContext;
const context = this.currentContext || _Container.contextPool.acquire();
if (!wasResolving) {
this.currentContext = context;
}
try {
const results = tokens.map((token2) => {
const cached = this.tryGetFromCaches(token2);
if (cached !== void 0)
return cached;
return this.resolveWithContext(token2, context);
});
return results;
} finally {
if (!wasResolving) {
this.currentContext = void 0;
_Container.contextPool.release(context);
}
}
}
/**
* Resolve a dependency asynchronously (supports async factories)
*/
async resolveAsync(token2) {
if (this.currentContext) {
return this.resolveAsyncWithContext(token2, this.currentContext);
}
const context = _Container.contextPool.acquire();
this.currentContext = context;
try {
return await this.resolveAsyncWithContext(token2, context);
} finally {
this.currentContext = void 0;
_Container.contextPool.release(context);
}
}
/**
* Try to get instance from all cache levels
* Returns undefined if not cached
* @internal
*/
tryGetFromCaches(token2) {
const ultraFast = this.ultraFastSingletonCache.get(token2);
if (ultraFast !== void 0) {
return ultraFast;
}
if (this.singletonCache.has(token2)) {
const cached = this.singletonCache.get(token2);
this.ultraFastSingletonCache.set(token2, cached);
return cached;
}
const fastFactory = this.fastTransientCache.get(token2);
if (fastFactory) {
return fastFactory();
}
return void 0;
}
/**
* Cache instance based on lifetime strategy
* @internal
*/
cacheInstance(token2, instance, lifetime, context) {
if (lifetime === "singleton") {
this.singletonCache.set(token2, instance);
this.singletonOrder.push(token2);
this.ultraFastSingletonCache.set(token2, instance);
} else if (lifetime === "per-request" && context) {
context.cachePerRequest(token2, instance);
}
}
/**
* Validate and get binding with circular dependency check
* Returns binding or throws error
* @internal
*/
validateAndGetBinding(token2, context) {
if (context.isResolving(token2)) {
throw new CircularDependencyError([...context.getPath(), token2.toString()]);
}
const binding = this.getBinding(token2);
if (!binding) {
throw new BindingNotFoundError(token2.toString(), context.getPath());
}
return binding;
}
/**
* Instantiate from binding synchronously
* @internal
*/
instantiateBindingSync(binding, token2, context) {
switch (binding.type) {
case "value":
return binding.value;
case "factory":
const result = binding.factory(this);
if (result instanceof Promise) {
throw new Error(`Async factory detected for ${token2.toString()}. Use resolveAsync() instead.`);
}
return result;
case "class":
const deps = binding.dependencies || [];
const resolvedDeps = deps.map((dep) => this.resolveWithContext(dep, context));
return new binding.constructor(...resolvedDeps);
case "inline-class":
return new binding.constructor();
default:
throw new Error(`Unknown binding type: ${binding.type}`);
}
}
/**
* Instantiate from binding asynchronously
* @internal
*/
async instantiateBindingAsync(binding, context) {
switch (binding.type) {
case "value":
return binding.value;
case "factory":
return await Promise.resolve(binding.factory(this));
case "class":
const deps = binding.dependencies || [];
const resolvedDeps = await Promise.all(deps.map((dep) => this.resolveAsyncWithContext(dep, context)));
return new binding.constructor(...resolvedDeps);
case "inline-class":
return new binding.constructor();
default:
throw new Error(`Unknown binding type: ${binding.type}`);
}
}
/**
* Create a child container that inherits bindings from this container
*/
createChild() {
return new _Container(this);
}
/**
* Dispose all singleton instances in reverse registration order
*/
async dispose() {
const errors = [];
for (let i = this.singletonOrder.length - 1; i >= 0; i--) {
const token2 = this.singletonOrder[i];
const instance = this.singletonCache.get(token2);
if (instance && isDisposable(instance)) {
try {
await instance.dispose();
} catch (error) {
errors.push(error);
}
}
}
this.singletonCache.clear();
this.singletonOrder.length = 0;
}
/**
* Create a fluent builder for registering dependencies
*/
builder() {
return new Builder(this);
}
/**
* Resolve a named service
*/
resolveNamed(name) {
const namedRegistrations = this.__namedRegistrations;
if (!namedRegistrations) {
throw new Error(`Named service "${name}" not found. No named registrations exist.`);
}
const config = namedRegistrations.get(name);
if (!config) {
throw new Error(`Named service "${name}" not found`);
}
return this.resolve(config.token);
}
/**
* Resolve a keyed service
*/
resolveKeyed(key) {
const keyedRegistrations = this.__keyedRegistrations;
if (!keyedRegistrations) {
throw new Error(`Keyed service not found. No keyed registrations exist.`);
}
const config = keyedRegistrations.get(key);
if (!config) {
const keyStr = typeof key === "symbol" ? key.toString() : `"${key}"`;
throw new Error(`Keyed service ${keyStr} not found`);
}
return this.resolve(config.token);
}
/**
* Resolve all registrations for a token
*/
resolveAll(token2) {
const multiRegistrations = this.__multiRegistrations;
if (!multiRegistrations) {
return [];
}
const tokens = multiRegistrations.get(token2);
if (!tokens || tokens.length === 0) {
return [];
}
return tokens.map((t) => this.resolve(t));
}
/**
* Get registry information for debugging/visualization
* Returns array of binding information
*/
getRegistry() {
const registry = [];
this.bindings.forEach((binding, token2) => {
registry.push({
token: token2.description || token2.symbol.toString(),
type: binding.type,
lifetime: binding.lifetime,
dependencies: binding.dependencies?.map((d) => d.description || d.symbol.toString())
});
});
return registry;
}
/**
* Get or create a token for an interface type
* Uses a type name hash as key for the interface registry
*/
interfaceToken(typeName) {
const key = typeName || `Interface_${Math.random().toString(36).substr(2, 9)}`;
if (this.interfaceRegistry.has(key)) {
return this.interfaceRegistry.get(key);
}
if (this.parent) {
const parentToken = this.parent.interfaceToken(key);
return parentToken;
}
const token2 = Token(key);
this.interfaceRegistry.set(key, token2);
return token2;
}
/**
* Resolve a dependency by interface type without explicit token
*/
resolveType(typeName) {
const key = typeName || "";
let token2 = this.interfaceTokenCache.get(key);
if (!token2) {
token2 = this.interfaceToken(typeName);
this.interfaceTokenCache.set(key, token2);
}
return this.resolve(token2);
}
/**
* Resolve a keyed interface
*/
resolveTypeKeyed(key, _typeName) {
return this.resolveKeyed(key);
}
/**
* Resolve all registrations for an interface type
*/
resolveTypeAll(typeName) {
const token2 = this.interfaceToken(typeName);
return this.resolveAll(token2);
}
/**
* Internal: Resolve with context for circular dependency detection
*/
resolveWithContext(token2, context) {
const binding = this.validateAndGetBinding(token2, context);
if (binding.lifetime === "per-request" && context.hasPerRequest(token2)) {
return context.getPerRequest(token2);
}
if (binding.lifetime === "singleton" && this.singletonCache.has(token2)) {
return this.singletonCache.get(token2);
}
context.enterResolve(token2);
try {
const instance = this.instantiateBindingSync(binding, token2, context);
this.cacheInstance(token2, instance, binding.lifetime, context);
return instance;
} finally {
context.exitResolve(token2);
}
}
/**
* Internal: Async resolve with context
*/
async resolveAsyncWithContext(token2, context) {
const binding = this.validateAndGetBinding(token2, context);
if (binding.lifetime === "per-request" && context.hasPerRequest(token2)) {
return context.getPerRequest(token2);
}
if (binding.lifetime === "singleton" && this.singletonCache.has(token2)) {
return this.singletonCache.get(token2);
}
context.enterResolve(token2);
try {
const instance = await this.instantiateBindingAsync(binding, context);
this.cacheInstance(token2, instance, binding.lifetime, context);
return instance;
} finally {
context.exitResolve(token2);
}
}
/**
* Get binding from this container or parent chain
* Performance optimized: Uses flat cache to avoid recursive parent lookups
*/
getBinding(token2) {
if (!this.bindingCache) {
this.buildBindingCache();
}
return this.bindingCache.get(token2);
}
/**
* Build flat cache of all bindings including parent chain
* This converts O(n) parent chain traversal to O(1) lookup
*/
buildBindingCache() {
this.bindingCache = /* @__PURE__ */ new Map();
let current = this;
while (current) {
current.bindings.forEach((binding, token2) => {
if (!this.bindingCache.has(token2)) {
this.bindingCache.set(token2, binding);
}
});
current = current.parent;
}
}
/**
* Invalidate binding cache when new bindings are added
* Called by bindValue, bindFactory, bindClass
*/
invalidateBindingCache() {
this.bindingCache = void 0;
this.ultraFastSingletonCache.clear();
}
};
__name(_Container, "Container");
var Container = _Container;
Container.contextPool = new ResolutionContextPool();
// src/v2/features/date/DateRenderer.ts
var _DateRenderer = class _DateRenderer {
constructor(dateService) {
this.dateService = dateService;
this.type = "date";
}
render(context) {
const dates = context.filter["date"] || [];
const resourceIds = context.filter["resource"] || [];
const dateGrouping = context.groupings?.find((g) => g.type === "date");
const hideHeader = dateGrouping?.hideHeader === true;
const iterations = resourceIds.length || 1;
let columnCount = 0;
for (let r = 0; r < iterations; r++) {
const resourceId = resourceIds[r];
for (const dateStr of dates) {
const date = this.dateService.parseISO(dateStr);
const segments = { date: dateStr };
if (resourceId)
segments.resource = resourceId;
const columnKey = this.dateService.buildColumnKey(segments);
const header = document.createElement("swp-day-header");
header.dataset.date = dateStr;
header.dataset.columnKey = columnKey;
if (resourceId) {
header.dataset.resourceId = resourceId;
}
if (hideHeader) {
header.dataset.hidden = "true";
}
header.innerHTML = `
<swp-day-name>${this.dateService.getDayName(date, "short")}</swp-day-name>
<swp-day-date>${date.getDate()}</swp-day-date>
`;
context.headerContainer.appendChild(header);
const column = document.createElement("swp-day-column");
column.dataset.date = dateStr;
column.dataset.columnKey = columnKey;
if (resourceId) {
column.dataset.resourceId = resourceId;
}
column.innerHTML = "<swp-events-layer></swp-events-layer>";
context.columnContainer.appendChild(column);
columnCount++;
}
}
const container2 = context.columnContainer.closest("swp-calendar-container");
if (container2) {
container2.style.setProperty("--grid-columns", String(columnCount));
}
}
};
__name(_DateRenderer, "DateRenderer");
var DateRenderer = _DateRenderer;
// src/v2/core/DateService.ts
var import_dayjs = __toESM(require_dayjs_min(), 1);
var import_utc = __toESM(require_utc(), 1);
var import_timezone = __toESM(require_timezone(), 1);
var import_isoWeek = __toESM(require_isoWeek(), 1);
import_dayjs.default.extend(import_utc.default);
import_dayjs.default.extend(import_timezone.default);
import_dayjs.default.extend(import_isoWeek.default);
var _DateService = class _DateService {
constructor(config, baseDate) {
this.config = config;
this.timezone = config.timezone;
this.baseDate = baseDate ? (0, import_dayjs.default)(baseDate) : (0, import_dayjs.default)();
}
/**
* Set a fixed base date (useful for demos with static mock data)
*/
setBaseDate(date) {
this.baseDate = (0, import_dayjs.default)(date);
}
/**
* Get the current base date (either fixed or today)
*/
getBaseDate() {
return this.baseDate.toDate();
}
parseISO(isoString) {
return (0, import_dayjs.default)(isoString).toDate();
}
getDayName(date, format = "short") {
return new Intl.DateTimeFormat(this.config.locale, { weekday: format }).format(date);
}
getWeekDates(offset = 0, days = 7) {
const monday = this.baseDate.startOf("week").add(1, "day").add(offset, "week");
return Array.from({ length: days }, (_, i) => monday.add(i, "day").format("YYYY-MM-DD"));
}
/**
* Get dates for specific weekdays within a week
* @param offset - Week offset from base date (0 = current week)
* @param workDays - Array of ISO weekday numbers (1=Monday, 7=Sunday)
* @returns Array of date strings in YYYY-MM-DD format
*/
getWorkWeekDates(offset, workDays) {
const monday = this.baseDate.startOf("week").add(1, "day").add(offset, "week");
return workDays.map((isoDay) => {
const daysFromMonday = isoDay === 7 ? 6 : isoDay - 1;
return monday.add(daysFromMonday, "day").format("YYYY-MM-DD");
});
}
// ============================================
// FORMATTING
// ============================================
formatTime(date, showSeconds = false) {
const pattern = showSeconds ? "HH:mm:ss" : "HH:mm";
return (0, import_dayjs.default)(date).format(pattern);
}
formatTimeRange(start, end) {
return `${this.formatTime(start)} - ${this.formatTime(end)}`;
}
formatDate(date) {
return (0, import_dayjs.default)(date).format("YYYY-MM-DD");
}
getDateKey(date) {
return this.formatDate(date);
}
// ============================================
// COLUMN KEY
// ============================================
/**
* Build a uniform columnKey from grouping segments
* Handles any combination of date, resource, team, etc.
*
* @example
* buildColumnKey({ date: '2025-12-09' }) → "2025-12-09"
* buildColumnKey({ date: '2025-12-09', resource: 'EMP001' }) → "2025-12-09:EMP001"
*/
buildColumnKey(segments) {
const date = segments.date;
const others = Object.entries(segments).filter(([k]) => k !== "date").sort(([a], [b]) => a.localeCompare(b)).map(([, v]) => v);
return date ? [date, ...others].join(":") : others.join(":");
}
/**
* Parse a columnKey back into segments
* Assumes format: "date:resource:..." or just "date"
*/
parseColumnKey(columnKey) {
const parts = columnKey.split(":");
return {
date: parts[0],
resource: parts[1]
};
}
/**
* Extract dateKey from columnKey (first segment)
*/
getDateFromColumnKey(columnKey) {
return columnKey.split(":")[0];
}
// ============================================
// TIME CALCULATIONS
// ============================================
timeToMinutes(timeString) {
const parts = timeString.split(":").map(Number);
const hours = parts[0] || 0;
const minutes = parts[1] || 0;
return hours * 60 + minutes;
}
minutesToTime(totalMinutes) {
const hours = Math.floor(totalMinutes / 60);
const minutes = totalMinutes % 60;
return (0, import_dayjs.default)().hour(hours).minute(minutes).format("HH:mm");
}
getMinutesSinceMidnight(date) {
const d = (0, import_dayjs.default)(date);
return d.hour() * 60 + d.minute();
}
// ============================================
// UTC CONVERSIONS
// ============================================
toUTC(localDate) {
return import_dayjs.default.tz(localDate, this.timezone).utc().toISOString();
}
fromUTC(utcString) {
return import_dayjs.default.utc(utcString).tz(this.timezone).toDate();
}
// ============================================
// DATE CREATION
// ============================================
createDateAtTime(baseDate, timeString) {
const totalMinutes = this.timeToMinutes(timeString);
const hours = Math.floor(totalMinutes / 60);
const minutes = totalMinutes % 60;
return (0, import_dayjs.default)(baseDate).startOf("day").hour(hours).minute(minutes).toDate();
}
getISOWeekDay(date) {
return (0, import_dayjs.default)(date).isoWeekday();
}
};
__name(_DateService, "DateService");
var DateService = _DateService;
// src/v2/core/BaseGroupingRenderer.ts
var _BaseGroupingRenderer = class _BaseGroupingRenderer {
/**
* Main render method - handles common logic
*/
async render(context) {
const allowedIds = context.filter[this.type] || [];
if (allowedIds.length === 0)
return;
const entities = await this.getEntities(allowedIds);
const dateCount = context.filter["date"]?.length || 1;
const childIds = context.childType ? context.filter[context.childType] || [] : [];
for (const entity of entities) {
const entityChildIds = context.parentChildMap?.[entity.id] || [];
const childCount = entityChildIds.filter((id) => childIds.includes(id)).length;
const colspan = childCount * dateCount;
const header = document.createElement(this.config.elementTag);
header.dataset[this.config.idAttribute] = entity.id;
header.style.setProperty(this.config.colspanVar, String(colspan));
this.renderHeader(entity, header, context);
context.headerContainer.appendChild(header);
}
}
/**
* Override this method for custom header rendering
* Default: just sets textContent to display name
*/
renderHeader(entity, header, _context) {
header.textContent = this.getDisplayName(entity);
}
/**
* Helper to render a single entity header.
* Can be used by subclasses that override render() but want consistent header creation.
*/
createHeader(entity, context) {
const header = document.createElement(this.config.elementTag);
header.dataset[this.config.idAttribute] = entity.id;
this.renderHeader(entity, header, context);
return header;
}
};
__name(_BaseGroupingRenderer, "BaseGroupingRenderer");
var BaseGroupingRenderer = _BaseGroupingRenderer;
// src/v2/features/resource/ResourceRenderer.ts
var _ResourceRenderer = class _ResourceRenderer extends BaseGroupingRenderer {
constructor(resourceService) {
super();
this.resourceService = resourceService;
this.type = "resource";
this.config = {
elementTag: "swp-resource-header",
idAttribute: "resourceId",
colspanVar: "--resource-cols"
};
}
getEntities(ids) {
return this.resourceService.getByIds(ids);
}
getDisplayName(entity) {
return entity.displayName;
}
/**
* Override render to handle:
* 1. Special ordering when parentChildMap exists (resources grouped by parent)
* 2. Different colspan calculation (just dateCount, not childCount * dateCount)
*/
async render(context) {
const resourceIds = context.filter["resource"] || [];
const dateCount = context.filter["date"]?.length || 1;
let orderedResourceIds;
if (context.parentChildMap) {
orderedResourceIds = [];
for (const childIds of Object.values(context.parentChildMap)) {
for (const childId of childIds) {
if (resourceIds.includes(childId)) {
orderedResourceIds.push(childId);
}
}
}
} else {
orderedResourceIds = resourceIds;
}
const resources = await this.getEntities(orderedResourceIds);
const resourceMap = new Map(resources.map((r) => [r.id, r]));
for (const resourceId of orderedResourceIds) {
const resource = resourceMap.get(resourceId);
if (!resource)
continue;
const header = this.createHeader(resource, context);
header.style.gridColumn = `span ${dateCount}`;
context.headerContainer.appendChild(header);
}
}
};
__name(_ResourceRenderer, "ResourceRenderer");
var ResourceRenderer = _ResourceRenderer;
// src/v2/features/team/TeamRenderer.ts
var _TeamRenderer = class _TeamRenderer extends BaseGroupingRenderer {
constructor(teamService) {
super();
this.teamService = teamService;
this.type = "team";
this.config = {
elementTag: "swp-team-header",
idAttribute: "teamId",
colspanVar: "--team-cols"
};
}
getEntities(ids) {
return this.teamService.getByIds(ids);
}
getDisplayName(entity) {
return entity.name;
}
};
__name(_TeamRenderer, "TeamRenderer");
var TeamRenderer = _TeamRenderer;
// src/v2/features/department/DepartmentRenderer.ts
var _DepartmentRenderer = class _DepartmentRenderer extends BaseGroupingRenderer {
constructor(departmentService) {
super();
this.departmentService = departmentService;
this.type = "department";
this.config = {
elementTag: "swp-department-header",
idAttribute: "departmentId",
colspanVar: "--department-cols"
};
}
getEntities(ids) {
return this.departmentService.getByIds(ids);
}
getDisplayName(entity) {
return entity.name;
}
};
__name(_DepartmentRenderer, "DepartmentRenderer");
var DepartmentRenderer = _DepartmentRenderer;
// src/v2/core/RenderBuilder.ts
function buildPipeline(renderers) {
return {
async run(context) {
for (const renderer of renderers) {
await renderer.render(context);
}
}
};
}
__name(buildPipeline, "buildPipeline");
// src/v2/core/FilterTemplate.ts
var _FilterTemplate = class _FilterTemplate {
constructor(dateService, entityResolver) {
this.dateService = dateService;
this.entityResolver = entityResolver;
this.fields = [];
}
/**
* Tilføj felt til template
* @param idProperty - Property-navn (bruges på både event og column.dataset)
* @param derivedFrom - Hvis feltet udledes fra anden property (f.eks. date fra start)
*/
addField(idProperty, derivedFrom) {
this.fields.push({ idProperty, derivedFrom });
return this;
}
/**
* Parse dot-notation string into components
* @example 'resource.teamId' → { entityType: 'resource', property: 'teamId', foreignKey: 'resourceId' }
*/
parseDotNotation(idProperty) {
if (!idProperty.includes("."))
return null;
const [entityType, property] = idProperty.split(".");
return {
entityType,
property,
foreignKey: entityType + "Id"
// Convention: resource → resourceId
};
}
/**
* Get dataset key for column lookup
* For dot-notation 'resource.teamId', we look for 'teamId' in dataset
*/
getDatasetKey(idProperty) {
const dotNotation = this.parseDotNotation(idProperty);
if (dotNotation) {
return dotNotation.property;
}
return idProperty;
}
/**
* Byg nøgle fra kolonne
* Læser værdier fra column.dataset[idProperty]
* For dot-notation, uses the property part (resource.teamId → teamId)
*/
buildKeyFromColumn(column) {
return this.fields.map((f) => {
const key = this.getDatasetKey(f.idProperty);
return column.dataset[key] || "";
}).join(":");
}
/**
* Byg nøgle fra event
* Læser værdier fra event[idProperty] eller udleder fra derivedFrom
* For dot-notation, resolves via EntityResolver
*/
buildKeyFromEvent(event) {
const eventRecord = event;
return this.fields.map((f) => {
const dotNotation = this.parseDotNotation(f.idProperty);
if (dotNotation) {
return this.resolveDotNotation(eventRecord, dotNotation);
}
if (f.derivedFrom) {
const sourceValue = eventRecord[f.derivedFrom];
if (sourceValue instanceof Date) {
return this.dateService.getDateKey(sourceValue);
}
return String(sourceValue || "");
}
return String(eventRecord[f.idProperty] || "");
}).join(":");
}
/**
* Resolve dot-notation reference via EntityResolver
*/
resolveDotNotation(eventRecord, dotNotation) {
if (!this.entityResolver) {
console.warn(`FilterTemplate: EntityResolver required for dot-notation '${dotNotation.entityType}.${dotNotation.property}'`);
return "";
}
const foreignId = eventRecord[dotNotation.foreignKey];
if (!foreignId)
return "";
const entity = this.entityResolver.resolve(dotNotation.entityType, String(foreignId));
if (!entity)
return "";
return String(entity[dotNotation.property] || "");
}
/**
* Match event mod kolonne
*/
matches(event, column) {
return this.buildKeyFromEvent(event) === this.buildKeyFromColumn(column);
}
};
__name(_FilterTemplate, "FilterTemplate");
var FilterTemplate = _FilterTemplate;
// src/v2/core/CalendarOrchestrator.ts
var _CalendarOrchestrator = class _CalendarOrchestrator {
constructor(allRenderers, eventRenderer, scheduleRenderer, headerDrawerRenderer, dateService, entityServices) {
this.allRenderers = allRenderers;
this.eventRenderer = eventRenderer;
this.scheduleRenderer = scheduleRenderer;
this.headerDrawerRenderer = headerDrawerRenderer;
this.dateService = dateService;
this.entityServices = entityServices;
}
async render(viewConfig, container2) {
const headerContainer = container2.querySelector("swp-calendar-header");
const columnContainer = container2.querySelector("swp-day-columns");
if (!headerContainer || !columnContainer) {
throw new Error("Missing swp-calendar-header or swp-day-columns");
}
const filter = {};
for (const grouping of viewConfig.groupings) {
filter[grouping.type] = grouping.values;
}
const filterTemplate = new FilterTemplate(this.dateService);
for (const grouping of viewConfig.groupings) {
if (grouping.idProperty) {
filterTemplate.addField(grouping.idProperty, grouping.derivedFrom);
}
}
const { parentChildMap, childType } = await this.resolveBelongsTo(viewConfig.groupings, filter);
const context = { headerContainer, columnContainer, filter, groupings: viewConfig.groupings, parentChildMap, childType };
headerContainer.innerHTML = "";
columnContainer.innerHTML = "";
const levels = viewConfig.groupings.map((g) => g.type).join(" ");
headerContainer.dataset.levels = levels;
const activeRenderers = this.selectRenderers(viewConfig);
const pipeline = buildPipeline(activeRenderers);
await pipeline.run(context);
await this.scheduleRenderer.render(container2, filter);
await this.eventRenderer.render(container2, filter, filterTemplate);
await this.headerDrawerRenderer.render(container2, filter, filterTemplate);
}
selectRenderers(viewConfig) {
const types = viewConfig.groupings.map((g) => g.type);
return types.map((type) => this.allRenderers.find((r) => r.type === type)).filter((r) => r !== void 0);
}
/**
* Resolve belongsTo relations to build parent-child map
* e.g., belongsTo: 'team.resourceIds' → { team1: ['EMP001', 'EMP002'], team2: [...] }
* Also returns the childType (the grouping type that has belongsTo)
*/
async resolveBelongsTo(groupings, filter) {
const childGrouping = groupings.find((g) => g.belongsTo);
if (!childGrouping?.belongsTo)
return {};
const [entityType, property] = childGrouping.belongsTo.split(".");
if (!entityType || !property)
return {};
const parentIds = filter[entityType] || [];
if (parentIds.length === 0)
return {};
const service = this.entityServices.find((s) => s.entityType.toLowerCase() === entityType);
if (!service)
return {};
const allEntities = await service.getAll();
const entities = allEntities.filter((e) => parentIds.includes(e.id));
const map = {};
for (const entity of entities) {
const entityRecord = entity;
const children = entityRecord[property] || [];
map[entityRecord.id] = children;
}
return { parentChildMap: map, childType: childGrouping.type };
}
};
__name(_CalendarOrchestrator, "CalendarOrchestrator");
var CalendarOrchestrator = _CalendarOrchestrator;
// src/v2/core/NavigationAnimator.ts
var _NavigationAnimator = class _NavigationAnimator {
constructor(headerTrack, contentTrack) {
this.headerTrack = headerTrack;
this.contentTrack = contentTrack;
}
async slide(direction, renderFn) {
const out = direction === "left" ? "-100%" : "100%";
const into = direction === "left" ? "100%" : "-100%";
await this.animateOut(out);
await renderFn();
await this.animateIn(into);
}
async animateOut(translate) {
await Promise.all([
this.headerTrack.animate([{ transform: "translateX(0)" }, { transform: `translateX(${translate})` }], { duration: 200, easing: "ease-in" }).finished,
this.contentTrack.animate([{ transform: "translateX(0)" }, { transform: `translateX(${translate})` }], { duration: 200, easing: "ease-in" }).finished
]);
}
async animateIn(translate) {
await Promise.all([
this.headerTrack.animate([{ transform: `translateX(${translate})` }, { transform: "translateX(0)" }], { duration: 200, easing: "ease-out" }).finished,
this.contentTrack.animate([{ transform: `translateX(${translate})` }, { transform: "translateX(0)" }], { duration: 200, easing: "ease-out" }).finished
]);
}
};
__name(_NavigationAnimator, "NavigationAnimator");
var NavigationAnimator = _NavigationAnimator;
// src/v2/core/CalendarEvents.ts
var CalendarEvents = {
// Command events (host → calendar)
CMD_NAVIGATE_PREV: "calendar:cmd:navigate:prev",
CMD_NAVIGATE_NEXT: "calendar:cmd:navigate:next",
CMD_DRAWER_TOGGLE: "calendar:cmd:drawer:toggle",
CMD_RENDER: "calendar:cmd:render",
CMD_WORKWEEK_CHANGE: "calendar:cmd:workweek:change",
CMD_VIEW_UPDATE: "calendar:cmd:view:update"
};
// src/v2/core/CalendarApp.ts
var _CalendarApp = class _CalendarApp {
constructor(orchestrator, timeAxisRenderer, dateService, scrollManager, headerDrawerManager, dragDropManager, edgeScrollManager, resizeManager, headerDrawerRenderer, eventPersistenceManager, settingsService, viewConfigService, eventBus) {
this.orchestrator = orchestrator;
this.timeAxisRenderer = timeAxisRenderer;
this.dateService = dateService;
this.scrollManager = scrollManager;
this.headerDrawerManager = headerDrawerManager;
this.dragDropManager = dragDropManager;
this.edgeScrollManager = edgeScrollManager;
this.resizeManager = resizeManager;
this.headerDrawerRenderer = headerDrawerRenderer;
this.eventPersistenceManager = eventPersistenceManager;
this.settingsService = settingsService;
this.viewConfigService = viewConfigService;
this.eventBus = eventBus;
this.weekOffset = 0;
this.currentViewId = "simple";
this.workweekPreset = null;
this.groupingOverrides = /* @__PURE__ */ new Map();
}
async init(container2) {
this.container = container2;
const gridSettings = await this.settingsService.getGridSettings();
if (!gridSettings) {
throw new Error("GridSettings not found");
}
this.workweekPreset = await this.settingsService.getDefaultWorkweekPreset();
this.animator = new NavigationAnimator(container2.querySelector("swp-header-track"), container2.querySelector("swp-content-track"));
this.timeAxisRenderer.render(container2.querySelector("#time-axis"), gridSettings.dayStartHour, gridSettings.dayEndHour);
this.scrollManager.init(container2);
this.headerDrawerManager.init(container2);
this.dragDropManager.init(container2);
this.resizeManager.init(container2);
const scrollableContent = container2.querySelector("swp-scrollable-content");
this.edgeScrollManager.init(scrollableContent);
this.setupEventListeners();
this.emitStatus("ready");
}
setupEventListeners() {
this.eventBus.on(CalendarEvents.CMD_NAVIGATE_PREV, () => {
this.handleNavigatePrev();
});
this.eventBus.on(CalendarEvents.CMD_NAVIGATE_NEXT, () => {
this.handleNavigateNext();
});
this.eventBus.on(CalendarEvents.CMD_DRAWER_TOGGLE, () => {
this.headerDrawerManager.toggle();
});
this.eventBus.on(CalendarEvents.CMD_RENDER, (e) => {
const { viewId } = e.detail;
this.handleRenderCommand(viewId);
});
this.eventBus.on(CalendarEvents.CMD_WORKWEEK_CHANGE, (e) => {
const { presetId } = e.detail;
this.handleWorkweekChange(presetId);
});
this.eventBus.on(CalendarEvents.CMD_VIEW_UPDATE, (e) => {
const { type, values } = e.detail;
this.handleViewUpdate(type, values);
});
}
async handleRenderCommand(viewId) {
this.currentViewId = viewId;
await this.render();
this.emitStatus("rendered", { viewId });
}
async handleNavigatePrev() {
this.weekOffset--;
await this.animator.slide("right", () => this.render());
this.emitStatus("rendered", { viewId: this.currentViewId });
}
async handleNavigateNext() {
this.weekOffset++;
await this.animator.slide("left", () => this.render());
this.emitStatus("rendered", { viewId: this.currentViewId });
}
async handleWorkweekChange(presetId) {
const preset = await this.settingsService.getWorkweekPreset(presetId);
if (preset) {
this.workweekPreset = preset;
await this.render();
this.emitStatus("rendered", { viewId: this.currentViewId });
}
}
async handleViewUpdate(type, values) {
this.groupingOverrides.set(type, values);
await this.render();
this.emitStatus("rendered", { viewId: this.currentViewId });
}
async render() {
const storedConfig = await this.viewConfigService.getById(this.currentViewId);
if (!storedConfig) {
this.emitStatus("error", { message: `ViewConfig not found: ${this.currentViewId}` });
return;
}
const workDays = this.workweekPreset?.workDays || [1, 2, 3, 4, 5];
const dates = this.currentViewId === "day" ? this.dateService.getWeekDates(this.weekOffset, 1) : this.dateService.getWorkWeekDates(this.weekOffset, workDays);
const viewConfig = {
...storedConfig,
groupings: storedConfig.groupings.map((g) => {
if (g.type === "date") {
return { ...g, values: dates };
}
const override = this.groupingOverrides.get(g.type);
if (override) {
return { ...g, values: override };
}
return g;
})
};
await this.orchestrator.render(viewConfig, this.container);
}
emitStatus(status, detail) {
this.container.dispatchEvent(new CustomEvent(`calendar:status:${status}`, {
detail,
bubbles: true
}));
}
};
__name(_CalendarApp, "CalendarApp");
var CalendarApp = _CalendarApp;
// src/v2/features/timeaxis/TimeAxisRenderer.ts
var _TimeAxisRenderer = class _TimeAxisRenderer {
render(container2, startHour = 6, endHour = 20) {
container2.innerHTML = "";
for (let hour = startHour; hour <= endHour; hour++) {
const marker = document.createElement("swp-hour-marker");
marker.textContent = `${hour.toString().padStart(2, "0")}:00`;
container2.appendChild(marker);
}
}
};
__name(_TimeAxisRenderer, "TimeAxisRenderer");
var TimeAxisRenderer = _TimeAxisRenderer;
// src/v2/core/ScrollManager.ts
var _ScrollManager = class _ScrollManager {
init(container2) {
this.scrollableContent = container2.querySelector("swp-scrollable-content");
this.timeAxisContent = container2.querySelector("swp-time-axis-content");
this.calendarHeader = container2.querySelector("swp-calendar-header");
this.headerDrawer = container2.querySelector("swp-header-drawer");
this.headerViewport = container2.querySelector("swp-header-viewport");
this.headerSpacer = container2.querySelector("swp-header-spacer");
this.scrollableContent.addEventListener("scroll", () => this.onScroll());
this.resizeObserver = new ResizeObserver(() => this.syncHeaderSpacerHeight());
this.resizeObserver.observe(this.headerViewport);
this.syncHeaderSpacerHeight();
}
syncHeaderSpacerHeight() {
const computedHeight = getComputedStyle(this.headerViewport).height;
this.headerSpacer.style.height = computedHeight;
}
onScroll() {
const { scrollTop, scrollLeft } = this.scrollableContent;
this.timeAxisContent.style.transform = `translateY(-${scrollTop}px)`;
this.calendarHeader.style.transform = `translateX(-${scrollLeft}px)`;
this.headerDrawer.style.transform = `translateX(-${scrollLeft}px)`;
}
};
__name(_ScrollManager, "ScrollManager");
var ScrollManager = _ScrollManager;
// src/v2/core/HeaderDrawerManager.ts
var _HeaderDrawerManager = class _HeaderDrawerManager {
constructor() {
this.expanded = false;
this.currentRows = 0;
this.rowHeight = 25;
this.duration = 200;
}
init(container2) {
this.drawer = container2.querySelector("swp-header-drawer");
if (!this.drawer)
console.error("HeaderDrawerManager: swp-header-drawer not found");
}
toggle() {
this.expanded ? this.collapse() : this.expand();
}
/**
* Expand drawer to single row (legacy support)
*/
expand() {
this.expandToRows(1);
}
/**
* Expand drawer to fit specified number of rows
*/
expandToRows(rowCount) {
const targetHeight = rowCount * this.rowHeight;
const currentHeight = this.expanded ? this.currentRows * this.rowHeight : 0;
if (this.expanded && this.currentRows === rowCount)
return;
this.currentRows = rowCount;
this.expanded = true;
this.animate(currentHeight, targetHeight);
}
collapse() {
if (!this.expanded)
return;
const currentHeight = this.currentRows * this.rowHeight;
this.expanded = false;
this.currentRows = 0;
this.animate(currentHeight, 0);
}
animate(from, to) {
const keyframes = [
{ height: `${from}px` },
{ height: `${to}px` }
];
const options = {
duration: this.duration,
easing: "ease",
fill: "forwards"
};
this.drawer.animate(keyframes, options);
}
isExpanded() {
return this.expanded;
}
getRowCount() {
return this.currentRows;
}
};
__name(_HeaderDrawerManager, "HeaderDrawerManager");
var HeaderDrawerManager = _HeaderDrawerManager;
// src/v2/demo/MockStores.ts
var _MockTeamStore = class _MockTeamStore {
constructor() {
this.type = "team";
this.teams = [
{ id: "alpha", name: "Team Alpha" },
{ id: "beta", name: "Team Beta" }
];
}
getByIds(ids) {
return this.teams.filter((t) => ids.includes(t.id));
}
};
__name(_MockTeamStore, "MockTeamStore");
var MockTeamStore = _MockTeamStore;
var _MockResourceStore = class _MockResourceStore {
constructor() {
this.type = "resource";
this.resources = [
{ id: "alice", name: "Alice", teamId: "alpha" },
{ id: "bob", name: "Bob", teamId: "alpha" },
{ id: "carol", name: "Carol", teamId: "beta" },
{ id: "dave", name: "Dave", teamId: "beta" }
];
}
getByIds(ids) {
return this.resources.filter((r) => ids.includes(r.id));
}
};
__name(_MockResourceStore, "MockResourceStore");
var MockResourceStore = _MockResourceStore;
// src/v2/demo/DemoApp.ts
var _DemoApp = class _DemoApp {
constructor(indexedDBContext, dataSeeder, auditService, calendarApp, dateService, resourceService, eventBus) {
this.indexedDBContext = indexedDBContext;
this.dataSeeder = dataSeeder;
this.auditService = auditService;
this.calendarApp = calendarApp;
this.dateService = dateService;
this.resourceService = resourceService;
this.eventBus = eventBus;
this.currentView = "simple";
}
async init() {
this.dateService.setBaseDate(/* @__PURE__ */ new Date("2025-12-08"));
await this.indexedDBContext.initialize();
console.log("[DemoApp] IndexedDB initialized");
await this.dataSeeder.seedIfEmpty();
console.log("[DemoApp] Data seeding complete");
this.container = document.querySelector("swp-calendar-container");
await this.calendarApp.init(this.container);
console.log("[DemoApp] CalendarApp initialized");
this.setupNavigation();
this.setupDrawerToggle();
this.setupViewSwitching();
this.setupWorkweekSelector();
await this.setupResourceSelector();
this.setupStatusListeners();
this.eventBus.emit(CalendarEvents.CMD_RENDER, { viewId: this.currentView });
}
setupNavigation() {
document.getElementById("btn-prev").onclick = () => {
this.eventBus.emit(CalendarEvents.CMD_NAVIGATE_PREV);
};
document.getElementById("btn-next").onclick = () => {
this.eventBus.emit(CalendarEvents.CMD_NAVIGATE_NEXT);
};
}
setupViewSwitching() {
const chips = document.querySelectorAll(".view-chip");
chips.forEach((chip) => {
chip.addEventListener("click", () => {
chips.forEach((c) => c.classList.remove("active"));
chip.classList.add("active");
const view = chip.dataset.view;
if (view) {
this.currentView = view;
this.updateSelectorVisibility();
this.eventBus.emit(CalendarEvents.CMD_RENDER, { viewId: view });
}
});
});
}
updateSelectorVisibility() {
const selector = document.querySelector("swp-resource-selector");
const showSelector = this.currentView === "picker" || this.currentView === "day";
selector?.classList.toggle("hidden", !showSelector);
}
setupDrawerToggle() {
document.getElementById("btn-drawer").onclick = () => {
this.eventBus.emit(CalendarEvents.CMD_DRAWER_TOGGLE);
};
}
setupWorkweekSelector() {
const workweekSelect = document.getElementById("workweek-select");
workweekSelect?.addEventListener("change", () => {
const presetId = workweekSelect.value;
this.eventBus.emit(CalendarEvents.CMD_WORKWEEK_CHANGE, { presetId });
});
}
async setupResourceSelector() {
const resources = await this.resourceService.getAll();
const container2 = document.querySelector(".resource-checkboxes");
if (!container2)
return;
container2.innerHTML = "";
resources.forEach((r) => {
const label = document.createElement("label");
label.innerHTML = `
<input type="checkbox" value="${r.id}" checked>
${r.displayName}
`;
container2.appendChild(label);
});
container2.addEventListener("change", () => {
const checked = container2.querySelectorAll("input:checked");
const values = Array.from(checked).map((cb) => cb.value);
this.eventBus.emit(CalendarEvents.CMD_VIEW_UPDATE, { type: "resource", values });
});
}
setupStatusListeners() {
this.container.addEventListener("calendar:status:ready", () => {
console.log("[DemoApp] Calendar ready");
});
this.container.addEventListener("calendar:status:rendered", (e) => {
console.log("[DemoApp] Calendar rendered:", e.detail.viewId);
});
this.container.addEventListener("calendar:status:error", (e) => {
console.error("[DemoApp] Calendar error:", e.detail.message);
});
}
};
__name(_DemoApp, "DemoApp");
var DemoApp = _DemoApp;
// src/v2/core/EventBus.ts
var _EventBus = class _EventBus {
constructor() {
this.eventLog = [];
this.debug = false;
this.listeners = /* @__PURE__ */ new Set();
this.logConfig = {
calendar: true,
grid: true,
event: true,
scroll: true,
navigation: true,
view: true,
default: true
};
}
/**
* Subscribe to an event via DOM addEventListener
*/
on(eventType, handler, options) {
document.addEventListener(eventType, handler, options);
this.listeners.add({ eventType, handler, options });
return () => this.off(eventType, handler);
}
/**
* Subscribe to an event once
*/
once(eventType, handler) {
return this.on(eventType, handler, { once: true });
}
/**
* Unsubscribe from an event
*/
off(eventType, handler) {
document.removeEventListener(eventType, handler);
for (const listener of this.listeners) {
if (listener.eventType === eventType && listener.handler === handler) {
this.listeners.delete(listener);
break;
}
}
}
/**
* Emit an event via DOM CustomEvent
*/
emit(eventType, detail = {}) {
if (!eventType) {
return false;
}
const event = new CustomEvent(eventType, {
detail: detail ?? {},
bubbles: true,
cancelable: true
});
if (this.debug) {
this.logEventWithGrouping(eventType, detail);
}
this.eventLog.push({
type: eventType,
detail: detail ?? {},
timestamp: Date.now()
});
return !document.dispatchEvent(event);
}
/**
* Log event with console grouping
*/
logEventWithGrouping(eventType, _detail) {
const category = this.extractCategory(eventType);
if (!this.logConfig[category]) {
return;
}
this.getCategoryStyle(category);
}
/**
* Extract category from event type
*/
extractCategory(eventType) {
if (!eventType) {
return "unknown";
}
if (eventType.includes(":")) {
return eventType.split(":")[0];
}
const lowerType = eventType.toLowerCase();
if (lowerType.includes("grid") || lowerType.includes("rendered"))
return "grid";
if (lowerType.includes("event") || lowerType.includes("sync"))
return "event";
if (lowerType.includes("scroll"))
return "scroll";
if (lowerType.includes("nav") || lowerType.includes("date"))
return "navigation";
if (lowerType.includes("view"))
return "view";
return "default";
}
/**
* Get styling for different categories
*/
getCategoryStyle(category) {
const styles = {
calendar: { emoji: "\u{1F4C5}", color: "#2196F3" },
grid: { emoji: "\u{1F4CA}", color: "#4CAF50" },
event: { emoji: "\u{1F4CC}", color: "#FF9800" },
scroll: { emoji: "\u{1F4DC}", color: "#9C27B0" },
navigation: { emoji: "\u{1F9ED}", color: "#F44336" },
view: { emoji: "\u{1F441}", color: "#00BCD4" },
default: { emoji: "\u{1F4E2}", color: "#607D8B" }
};
return styles[category] || styles.default;
}
/**
* Configure logging for specific categories
*/
setLogConfig(config) {
this.logConfig = { ...this.logConfig, ...config };
}
/**
* Get current log configuration
*/
getLogConfig() {
return { ...this.logConfig };
}
/**
* Get event history
*/
getEventLog(eventType) {
if (eventType) {
return this.eventLog.filter((e) => e.type === eventType);
}
return this.eventLog;
}
/**
* Enable/disable debug mode
*/
setDebug(enabled) {
this.debug = enabled;
}
};
__name(_EventBus, "EventBus");
var EventBus = _EventBus;
// src/v2/storage/IndexedDBContext.ts
var _IndexedDBContext = class _IndexedDBContext {
constructor(stores) {
this.db = null;
this.initialized = false;
this.stores = stores;
}
/**
* Initialize and open the database
*/
async initialize() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(_IndexedDBContext.DB_NAME, _IndexedDBContext.DB_VERSION);
request.onerror = () => {
reject(new Error(`Failed to open IndexedDB: ${request.error}`));
};
request.onsuccess = () => {
this.db = request.result;
this.initialized = true;
resolve();
};
request.onupgradeneeded = (event) => {
const db = event.target.result;
this.stores.forEach((store) => {
if (!db.objectStoreNames.contains(store.storeName)) {
store.create(db);
}
});
};
});
}
/**
* Check if database is initialized
*/
isInitialized() {
return this.initialized;
}
/**
* Get IDBDatabase instance
*/
getDatabase() {
if (!this.db) {
throw new Error("IndexedDB not initialized. Call initialize() first.");
}
return this.db;
}
/**
* Close database connection
*/
close() {
if (this.db) {
this.db.close();
this.db = null;
this.initialized = false;
}
}
/**
* Delete entire database (for testing/reset)
*/
static async deleteDatabase() {
return new Promise((resolve, reject) => {
const request = indexedDB.deleteDatabase(_IndexedDBContext.DB_NAME);
request.onsuccess = () => resolve();
request.onerror = () => reject(new Error(`Failed to delete database: ${request.error}`));
});
}
};
__name(_IndexedDBContext, "IndexedDBContext");
var IndexedDBContext = _IndexedDBContext;
IndexedDBContext.DB_NAME = "CalendarV2DB";
IndexedDBContext.DB_VERSION = 4;
// src/v2/storage/events/EventStore.ts
var _EventStore = class _EventStore {
constructor() {
this.storeName = _EventStore.STORE_NAME;
}
/**
* Create the events ObjectStore with indexes
*/
create(db) {
const store = db.createObjectStore(_EventStore.STORE_NAME, { keyPath: "id" });
store.createIndex("start", "start", { unique: false });
store.createIndex("end", "end", { unique: false });
store.createIndex("syncStatus", "syncStatus", { unique: false });
store.createIndex("resourceId", "resourceId", { unique: false });
store.createIndex("customerId", "customerId", { unique: false });
store.createIndex("bookingId", "bookingId", { unique: false });
store.createIndex("startEnd", ["start", "end"], { unique: false });
}
};
__name(_EventStore, "EventStore");
var EventStore = _EventStore;
EventStore.STORE_NAME = "events";
// src/v2/storage/events/EventSerialization.ts
var _EventSerialization = class _EventSerialization {
/**
* Serialize event for IndexedDB storage
*/
static serialize(event) {
return {
...event,
start: event.start instanceof Date ? event.start.toISOString() : event.start,
end: event.end instanceof Date ? event.end.toISOString() : event.end
};
}
/**
* Deserialize event from IndexedDB storage
*/
static deserialize(data) {
return {
...data,
start: typeof data.start === "string" ? new Date(data.start) : data.start,
end: typeof data.end === "string" ? new Date(data.end) : data.end
};
}
};
__name(_EventSerialization, "EventSerialization");
var EventSerialization = _EventSerialization;
// src/v2/storage/SyncPlugin.ts
var _SyncPlugin = class _SyncPlugin {
constructor(service) {
this.service = service;
}
/**
* Mark entity as successfully synced
*/
async markAsSynced(id) {
const entity = await this.service.get(id);
if (entity) {
entity.syncStatus = "synced";
await this.service.save(entity);
}
}
/**
* Mark entity as sync error
*/
async markAsError(id) {
const entity = await this.service.get(id);
if (entity) {
entity.syncStatus = "error";
await this.service.save(entity);
}
}
/**
* Get current sync status for an entity
*/
async getSyncStatus(id) {
const entity = await this.service.get(id);
return entity ? entity.syncStatus : null;
}
/**
* Get entities by sync status using IndexedDB index
*/
async getBySyncStatus(syncStatus) {
return new Promise((resolve, reject) => {
const transaction = this.service.db.transaction([this.service.storeName], "readonly");
const store = transaction.objectStore(this.service.storeName);
const index = store.index("syncStatus");
const request = index.getAll(syncStatus);
request.onsuccess = () => {
const data = request.result;
const entities = data.map((item) => this.service.deserialize(item));
resolve(entities);
};
request.onerror = () => {
reject(new Error(`Failed to get by sync status ${syncStatus}: ${request.error}`));
};
});
}
};
__name(_SyncPlugin, "SyncPlugin");
var SyncPlugin = _SyncPlugin;
// src/v2/constants/CoreEvents.ts
var CoreEvents = {
// Lifecycle events
INITIALIZED: "core:initialized",
READY: "core:ready",
DESTROYED: "core:destroyed",
// View events
VIEW_CHANGED: "view:changed",
VIEW_RENDERED: "view:rendered",
// Navigation events
DATE_CHANGED: "nav:date-changed",
NAVIGATION_COMPLETED: "nav:navigation-completed",
// Data events
DATA_LOADING: "data:loading",
DATA_LOADED: "data:loaded",
DATA_ERROR: "data:error",
// Grid events
GRID_RENDERED: "grid:rendered",
GRID_CLICKED: "grid:clicked",
// Event management
EVENT_CREATED: "event:created",
EVENT_UPDATED: "event:updated",
EVENT_DELETED: "event:deleted",
EVENT_SELECTED: "event:selected",
// Event drag-drop
EVENT_DRAG_START: "event:drag-start",
EVENT_DRAG_MOVE: "event:drag-move",
EVENT_DRAG_END: "event:drag-end",
EVENT_DRAG_CANCEL: "event:drag-cancel",
EVENT_DRAG_COLUMN_CHANGE: "event:drag-column-change",
// Header drag (timed → header conversion)
EVENT_DRAG_ENTER_HEADER: "event:drag-enter-header",
EVENT_DRAG_MOVE_HEADER: "event:drag-move-header",
EVENT_DRAG_LEAVE_HEADER: "event:drag-leave-header",
// Event resize
EVENT_RESIZE_START: "event:resize-start",
EVENT_RESIZE_END: "event:resize-end",
// Edge scroll
EDGE_SCROLL_TICK: "edge-scroll:tick",
EDGE_SCROLL_STARTED: "edge-scroll:started",
EDGE_SCROLL_STOPPED: "edge-scroll:stopped",
// System events
ERROR: "system:error",
// Sync events
SYNC_STARTED: "sync:started",
SYNC_COMPLETED: "sync:completed",
SYNC_FAILED: "sync:failed",
// Entity events - for audit and sync
ENTITY_SAVED: "entity:saved",
ENTITY_DELETED: "entity:deleted",
// Audit events
AUDIT_LOGGED: "audit:logged",
// Rendering events
EVENTS_RENDERED: "events:rendered"
};
// node_modules/json-diff-ts/dist/index.js
function arrayDifference(first, second) {
const secondSet = new Set(second);
return first.filter((item) => !secondSet.has(item));
}
__name(arrayDifference, "arrayDifference");
function arrayIntersection(first, second) {
const secondSet = new Set(second);
return first.filter((item) => secondSet.has(item));
}
__name(arrayIntersection, "arrayIntersection");
function keyBy(arr, getKey2) {
const result = {};
for (const item of arr) {
result[String(getKey2(item))] = item;
}
return result;
}
__name(keyBy, "keyBy");
function diff(oldObj, newObj, options = {}) {
let { embeddedObjKeys } = options;
const { keysToSkip, treatTypeChangeAsReplace } = options;
if (embeddedObjKeys instanceof Map) {
embeddedObjKeys = new Map(
Array.from(embeddedObjKeys.entries()).map(([key, value]) => [
key instanceof RegExp ? key : key.replace(/^\./, ""),
value
])
);
} else if (embeddedObjKeys) {
embeddedObjKeys = Object.fromEntries(
Object.entries(embeddedObjKeys).map(([key, value]) => [key.replace(/^\./, ""), value])
);
}
return compare(oldObj, newObj, [], [], {
embeddedObjKeys,
keysToSkip: keysToSkip ?? [],
treatTypeChangeAsReplace: treatTypeChangeAsReplace ?? true
});
}
__name(diff, "diff");
var getTypeOfObj = /* @__PURE__ */ __name((obj) => {
if (typeof obj === "undefined") {
return "undefined";
}
if (obj === null) {
return null;
}
return Object.prototype.toString.call(obj).match(/^\[object\s(.*)\]$/)[1];
}, "getTypeOfObj");
var getKey = /* @__PURE__ */ __name((path) => {
const left = path[path.length - 1];
return left != null ? left : "$root";
}, "getKey");
var compare = /* @__PURE__ */ __name((oldObj, newObj, path, keyPath, options) => {
let changes = [];
const currentPath = keyPath.join(".");
if (options.keysToSkip?.some((skipPath) => {
if (currentPath === skipPath) {
return true;
}
if (skipPath.includes(".") && skipPath.startsWith(currentPath + ".")) {
return false;
}
if (skipPath.includes(".")) {
const skipParts = skipPath.split(".");
const currentParts = currentPath.split(".");
if (currentParts.length >= skipParts.length) {
for (let i = 0; i < skipParts.length; i++) {
if (skipParts[i] !== currentParts[i]) {
return false;
}
}
return true;
}
}
return false;
})) {
return changes;
}
const typeOfOldObj = getTypeOfObj(oldObj);
const typeOfNewObj = getTypeOfObj(newObj);
if (options.treatTypeChangeAsReplace && typeOfOldObj !== typeOfNewObj) {
if (typeOfOldObj !== "undefined") {
changes.push({ type: "REMOVE", key: getKey(path), value: oldObj });
}
if (typeOfNewObj !== "undefined") {
changes.push({ type: "ADD", key: getKey(path), value: newObj });
}
return changes;
}
if (typeOfNewObj === "undefined" && typeOfOldObj !== "undefined") {
changes.push({ type: "REMOVE", key: getKey(path), value: oldObj });
return changes;
}
if (typeOfNewObj === "Object" && typeOfOldObj === "Array") {
changes.push({ type: "UPDATE", key: getKey(path), value: newObj, oldValue: oldObj });
return changes;
}
if (typeOfNewObj === null) {
if (typeOfOldObj !== null) {
changes.push({ type: "UPDATE", key: getKey(path), value: newObj, oldValue: oldObj });
}
return changes;
}
switch (typeOfOldObj) {
case "Date":
if (typeOfNewObj === "Date") {
changes = changes.concat(
comparePrimitives(oldObj.getTime(), newObj.getTime(), path).map((x) => ({
...x,
value: new Date(x.value),
oldValue: new Date(x.oldValue)
}))
);
} else {
changes = changes.concat(comparePrimitives(oldObj, newObj, path));
}
break;
case "Object": {
const diffs = compareObject(oldObj, newObj, path, keyPath, false, options);
if (diffs.length) {
if (path.length) {
changes.push({
type: "UPDATE",
key: getKey(path),
changes: diffs
});
} else {
changes = changes.concat(diffs);
}
}
break;
}
case "Array":
changes = changes.concat(compareArray(oldObj, newObj, path, keyPath, options));
break;
case "Function":
break;
default:
changes = changes.concat(comparePrimitives(oldObj, newObj, path));
}
return changes;
}, "compare");
var compareObject = /* @__PURE__ */ __name((oldObj, newObj, path, keyPath, skipPath = false, options = {}) => {
let k;
let newKeyPath;
let newPath;
if (skipPath == null) {
skipPath = false;
}
let changes = [];
const oldObjKeys = Object.keys(oldObj);
const newObjKeys = Object.keys(newObj);
const intersectionKeys = arrayIntersection(oldObjKeys, newObjKeys);
for (k of intersectionKeys) {
newPath = path.concat([k]);
newKeyPath = skipPath ? keyPath : keyPath.concat([k]);
const diffs = compare(oldObj[k], newObj[k], newPath, newKeyPath, options);
if (diffs.length) {
changes = changes.concat(diffs);
}
}
const addedKeys = arrayDifference(newObjKeys, oldObjKeys);
for (k of addedKeys) {
newPath = path.concat([k]);
newKeyPath = skipPath ? keyPath : keyPath.concat([k]);
const currentPath = newKeyPath.join(".");
if (options.keysToSkip?.some((skipPath2) => currentPath === skipPath2 || currentPath.startsWith(skipPath2 + "."))) {
continue;
}
changes.push({
type: "ADD",
key: getKey(newPath),
value: newObj[k]
});
}
const deletedKeys = arrayDifference(oldObjKeys, newObjKeys);
for (k of deletedKeys) {
newPath = path.concat([k]);
newKeyPath = skipPath ? keyPath : keyPath.concat([k]);
const currentPath = newKeyPath.join(".");
if (options.keysToSkip?.some((skipPath2) => currentPath === skipPath2 || currentPath.startsWith(skipPath2 + "."))) {
continue;
}
changes.push({
type: "REMOVE",
key: getKey(newPath),
value: oldObj[k]
});
}
return changes;
}, "compareObject");
var compareArray = /* @__PURE__ */ __name((oldObj, newObj, path, keyPath, options) => {
if (getTypeOfObj(newObj) !== "Array") {
return [{ type: "UPDATE", key: getKey(path), value: newObj, oldValue: oldObj }];
}
const left = getObjectKey(options.embeddedObjKeys, keyPath);
const uniqKey = left != null ? left : "$index";
const indexedOldObj = convertArrayToObj(oldObj, uniqKey);
const indexedNewObj = convertArrayToObj(newObj, uniqKey);
const diffs = compareObject(indexedOldObj, indexedNewObj, path, keyPath, true, options);
if (diffs.length) {
return [
{
type: "UPDATE",
key: getKey(path),
embeddedKey: typeof uniqKey === "function" && uniqKey.length === 2 ? uniqKey(newObj[0], true) : uniqKey,
changes: diffs
}
];
} else {
return [];
}
}, "compareArray");
var getObjectKey = /* @__PURE__ */ __name((embeddedObjKeys, keyPath) => {
if (embeddedObjKeys != null) {
const path = keyPath.join(".");
if (embeddedObjKeys instanceof Map) {
for (const [key2, value] of embeddedObjKeys.entries()) {
if (key2 instanceof RegExp) {
if (path.match(key2)) {
return value;
}
} else if (path === key2) {
return value;
}
}
}
const key = embeddedObjKeys[path];
if (key != null) {
return key;
}
}
return void 0;
}, "getObjectKey");
var convertArrayToObj = /* @__PURE__ */ __name((arr, uniqKey) => {
let obj = {};
if (uniqKey === "$value") {
arr.forEach((value) => {
obj[value] = value;
});
} else if (uniqKey !== "$index") {
const keyFunction = typeof uniqKey === "string" ? (item) => item[uniqKey] : uniqKey;
obj = keyBy(arr, keyFunction);
} else {
for (let i = 0; i < arr.length; i++) {
const value = arr[i];
obj[i] = value;
}
}
return obj;
}, "convertArrayToObj");
var comparePrimitives = /* @__PURE__ */ __name((oldObj, newObj, path) => {
const changes = [];
if (oldObj !== newObj) {
changes.push({
type: "UPDATE",
key: getKey(path),
value: newObj,
oldValue: oldObj
});
}
return changes;
}, "comparePrimitives");
// src/v2/storage/BaseEntityService.ts
var _BaseEntityService = class _BaseEntityService {
constructor(context, eventBus) {
this.context = context;
this.eventBus = eventBus;
this.syncPlugin = new SyncPlugin(this);
}
get db() {
return this.context.getDatabase();
}
/**
* Serialize entity before storing in IndexedDB
*/
serialize(entity) {
return entity;
}
/**
* Deserialize data from IndexedDB back to entity
*/
deserialize(data) {
return data;
}
/**
* Get a single entity by ID
*/
async get(id) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([this.storeName], "readonly");
const store = transaction.objectStore(this.storeName);
const request = store.get(id);
request.onsuccess = () => {
const data = request.result;
resolve(data ? this.deserialize(data) : null);
};
request.onerror = () => {
reject(new Error(`Failed to get ${this.entityType} ${id}: ${request.error}`));
};
});
}
/**
* Get all entities
*/
async getAll() {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([this.storeName], "readonly");
const store = transaction.objectStore(this.storeName);
const request = store.getAll();
request.onsuccess = () => {
const data = request.result;
const entities = data.map((item) => this.deserialize(item));
resolve(entities);
};
request.onerror = () => {
reject(new Error(`Failed to get all ${this.entityType}s: ${request.error}`));
};
});
}
/**
* Save an entity (create or update)
* Emits ENTITY_SAVED event with operation type and changes (diff for updates)
* @param entity - Entity to save
* @param silent - If true, skip event emission (used for seeding)
*/
async save(entity, silent = false) {
const entityId = entity.id;
const existingEntity = await this.get(entityId);
const isCreate = existingEntity === null;
let changes;
if (isCreate) {
changes = entity;
} else {
const existingSerialized = this.serialize(existingEntity);
const newSerialized = this.serialize(entity);
changes = diff(existingSerialized, newSerialized);
}
const serialized = this.serialize(entity);
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([this.storeName], "readwrite");
const store = transaction.objectStore(this.storeName);
const request = store.put(serialized);
request.onsuccess = () => {
if (!silent) {
const payload = {
entityType: this.entityType,
entityId,
operation: isCreate ? "create" : "update",
changes,
timestamp: Date.now()
};
this.eventBus.emit(CoreEvents.ENTITY_SAVED, payload);
}
resolve();
};
request.onerror = () => {
reject(new Error(`Failed to save ${this.entityType} ${entityId}: ${request.error}`));
};
});
}
/**
* Delete an entity
* Emits ENTITY_DELETED event
*/
async delete(id) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([this.storeName], "readwrite");
const store = transaction.objectStore(this.storeName);
const request = store.delete(id);
request.onsuccess = () => {
const payload = {
entityType: this.entityType,
entityId: id,
operation: "delete",
timestamp: Date.now()
};
this.eventBus.emit(CoreEvents.ENTITY_DELETED, payload);
resolve();
};
request.onerror = () => {
reject(new Error(`Failed to delete ${this.entityType} ${id}: ${request.error}`));
};
});
}
// Sync methods - delegate to SyncPlugin
async markAsSynced(id) {
return this.syncPlugin.markAsSynced(id);
}
async markAsError(id) {
return this.syncPlugin.markAsError(id);
}
async getSyncStatus(id) {
return this.syncPlugin.getSyncStatus(id);
}
async getBySyncStatus(syncStatus) {
return this.syncPlugin.getBySyncStatus(syncStatus);
}
};
__name(_BaseEntityService, "BaseEntityService");
var BaseEntityService = _BaseEntityService;
// src/v2/storage/events/EventService.ts
var _EventService = class _EventService extends BaseEntityService {
constructor(context, eventBus) {
super(context, eventBus);
this.storeName = EventStore.STORE_NAME;
this.entityType = "Event";
}
serialize(event) {
return EventSerialization.serialize(event);
}
deserialize(data) {
return EventSerialization.deserialize(data);
}
/**
* Get events within a date range
*/
async getByDateRange(start, end) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([this.storeName], "readonly");
const store = transaction.objectStore(this.storeName);
const index = store.index("start");
const range = IDBKeyRange.lowerBound(start.toISOString());
const request = index.getAll(range);
request.onsuccess = () => {
const data = request.result;
const events = data.map((item) => this.deserialize(item)).filter((event) => event.start <= end);
resolve(events);
};
request.onerror = () => {
reject(new Error(`Failed to get events by date range: ${request.error}`));
};
});
}
/**
* Get events for a specific resource
*/
async getByResource(resourceId) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([this.storeName], "readonly");
const store = transaction.objectStore(this.storeName);
const index = store.index("resourceId");
const request = index.getAll(resourceId);
request.onsuccess = () => {
const data = request.result;
const events = data.map((item) => this.deserialize(item));
resolve(events);
};
request.onerror = () => {
reject(new Error(`Failed to get events for resource ${resourceId}: ${request.error}`));
};
});
}
/**
* Get events for a resource within a date range
*/
async getByResourceAndDateRange(resourceId, start, end) {
const resourceEvents = await this.getByResource(resourceId);
return resourceEvents.filter((event) => event.start >= start && event.start <= end);
}
};
__name(_EventService, "EventService");
var EventService = _EventService;
// src/v2/storage/resources/ResourceStore.ts
var _ResourceStore = class _ResourceStore {
constructor() {
this.storeName = _ResourceStore.STORE_NAME;
}
create(db) {
const store = db.createObjectStore(_ResourceStore.STORE_NAME, { keyPath: "id" });
store.createIndex("type", "type", { unique: false });
store.createIndex("syncStatus", "syncStatus", { unique: false });
store.createIndex("isActive", "isActive", { unique: false });
}
};
__name(_ResourceStore, "ResourceStore");
var ResourceStore = _ResourceStore;
ResourceStore.STORE_NAME = "resources";
// src/v2/storage/resources/ResourceService.ts
var _ResourceService = class _ResourceService extends BaseEntityService {
constructor(context, eventBus) {
super(context, eventBus);
this.storeName = ResourceStore.STORE_NAME;
this.entityType = "Resource";
}
/**
* Get all active resources
*/
async getActive() {
const all = await this.getAll();
return all.filter((r) => r.isActive !== false);
}
/**
* Get resources by IDs
*/
async getByIds(ids) {
if (ids.length === 0)
return [];
const results = await Promise.all(ids.map((id) => this.get(id)));
return results.filter((r) => r !== null);
}
/**
* Get resources by type
*/
async getByType(type) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([this.storeName], "readonly");
const store = transaction.objectStore(this.storeName);
const index = store.index("type");
const request = index.getAll(type);
request.onsuccess = () => {
const data = request.result;
resolve(data);
};
request.onerror = () => {
reject(new Error(`Failed to get resources by type ${type}: ${request.error}`));
};
});
}
};
__name(_ResourceService, "ResourceService");
var ResourceService = _ResourceService;
// src/v2/storage/bookings/BookingStore.ts
var _BookingStore = class _BookingStore {
constructor() {
this.storeName = _BookingStore.STORE_NAME;
}
create(db) {
const store = db.createObjectStore(_BookingStore.STORE_NAME, { keyPath: "id" });
store.createIndex("customerId", "customerId", { unique: false });
store.createIndex("status", "status", { unique: false });
store.createIndex("syncStatus", "syncStatus", { unique: false });
store.createIndex("createdAt", "createdAt", { unique: false });
}
};
__name(_BookingStore, "BookingStore");
var BookingStore = _BookingStore;
BookingStore.STORE_NAME = "bookings";
// src/v2/storage/bookings/BookingService.ts
var _BookingService = class _BookingService extends BaseEntityService {
constructor(context, eventBus) {
super(context, eventBus);
this.storeName = BookingStore.STORE_NAME;
this.entityType = "Booking";
}
serialize(booking) {
return {
...booking,
createdAt: booking.createdAt.toISOString()
};
}
deserialize(data) {
const raw = data;
return {
...raw,
createdAt: new Date(raw.createdAt)
};
}
/**
* Get bookings for a customer
*/
async getByCustomer(customerId) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([this.storeName], "readonly");
const store = transaction.objectStore(this.storeName);
const index = store.index("customerId");
const request = index.getAll(customerId);
request.onsuccess = () => {
const data = request.result;
const bookings = data.map((item) => this.deserialize(item));
resolve(bookings);
};
request.onerror = () => {
reject(new Error(`Failed to get bookings for customer ${customerId}: ${request.error}`));
};
});
}
/**
* Get bookings by status
*/
async getByStatus(status) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([this.storeName], "readonly");
const store = transaction.objectStore(this.storeName);
const index = store.index("status");
const request = index.getAll(status);
request.onsuccess = () => {
const data = request.result;
const bookings = data.map((item) => this.deserialize(item));
resolve(bookings);
};
request.onerror = () => {
reject(new Error(`Failed to get bookings with status ${status}: ${request.error}`));
};
});
}
};
__name(_BookingService, "BookingService");
var BookingService = _BookingService;
// src/v2/storage/customers/CustomerStore.ts
var _CustomerStore = class _CustomerStore {
constructor() {
this.storeName = _CustomerStore.STORE_NAME;
}
create(db) {
const store = db.createObjectStore(_CustomerStore.STORE_NAME, { keyPath: "id" });
store.createIndex("name", "name", { unique: false });
store.createIndex("phone", "phone", { unique: false });
store.createIndex("syncStatus", "syncStatus", { unique: false });
}
};
__name(_CustomerStore, "CustomerStore");
var CustomerStore = _CustomerStore;
CustomerStore.STORE_NAME = "customers";
// src/v2/storage/customers/CustomerService.ts
var _CustomerService = class _CustomerService extends BaseEntityService {
constructor(context, eventBus) {
super(context, eventBus);
this.storeName = CustomerStore.STORE_NAME;
this.entityType = "Customer";
}
/**
* Search customers by name (case-insensitive contains)
*/
async searchByName(query) {
const all = await this.getAll();
const lowerQuery = query.toLowerCase();
return all.filter((c) => c.name.toLowerCase().includes(lowerQuery));
}
/**
* Find customer by phone
*/
async getByPhone(phone) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([this.storeName], "readonly");
const store = transaction.objectStore(this.storeName);
const index = store.index("phone");
const request = index.get(phone);
request.onsuccess = () => {
const data = request.result;
resolve(data ? data : null);
};
request.onerror = () => {
reject(new Error(`Failed to find customer by phone ${phone}: ${request.error}`));
};
});
}
};
__name(_CustomerService, "CustomerService");
var CustomerService = _CustomerService;
// src/v2/storage/teams/TeamStore.ts
var _TeamStore = class _TeamStore {
constructor() {
this.storeName = _TeamStore.STORE_NAME;
}
create(db) {
db.createObjectStore(_TeamStore.STORE_NAME, { keyPath: "id" });
}
};
__name(_TeamStore, "TeamStore");
var TeamStore = _TeamStore;
TeamStore.STORE_NAME = "teams";
// src/v2/storage/teams/TeamService.ts
var _TeamService = class _TeamService extends BaseEntityService {
constructor(context, eventBus) {
super(context, eventBus);
this.storeName = TeamStore.STORE_NAME;
this.entityType = "Team";
}
/**
* Get teams by IDs
*/
async getByIds(ids) {
if (ids.length === 0)
return [];
const results = await Promise.all(ids.map((id) => this.get(id)));
return results.filter((t) => t !== null);
}
/**
* Build reverse lookup: resourceId → teamId
*/
async buildResourceToTeamMap() {
const teams = await this.getAll();
const map = {};
for (const team of teams) {
for (const resourceId of team.resourceIds) {
map[resourceId] = team.id;
}
}
return map;
}
};
__name(_TeamService, "TeamService");
var TeamService = _TeamService;
// src/v2/storage/departments/DepartmentStore.ts
var _DepartmentStore = class _DepartmentStore {
constructor() {
this.storeName = _DepartmentStore.STORE_NAME;
}
create(db) {
db.createObjectStore(_DepartmentStore.STORE_NAME, { keyPath: "id" });
}
};
__name(_DepartmentStore, "DepartmentStore");
var DepartmentStore = _DepartmentStore;
DepartmentStore.STORE_NAME = "departments";
// src/v2/storage/departments/DepartmentService.ts
var _DepartmentService = class _DepartmentService extends BaseEntityService {
constructor(context, eventBus) {
super(context, eventBus);
this.storeName = DepartmentStore.STORE_NAME;
this.entityType = "Department";
}
/**
* Get departments by IDs
*/
async getByIds(ids) {
if (ids.length === 0)
return [];
const results = await Promise.all(ids.map((id) => this.get(id)));
return results.filter((d) => d !== null);
}
};
__name(_DepartmentService, "DepartmentService");
var DepartmentService = _DepartmentService;
// src/v2/storage/settings/SettingsStore.ts
var _SettingsStore = class _SettingsStore {
constructor() {
this.storeName = _SettingsStore.STORE_NAME;
}
create(db) {
db.createObjectStore(_SettingsStore.STORE_NAME, { keyPath: "id" });
}
};
__name(_SettingsStore, "SettingsStore");
var SettingsStore = _SettingsStore;
SettingsStore.STORE_NAME = "settings";
// src/v2/types/SettingsTypes.ts
var SettingsIds = {
WORKWEEK: "workweek",
GRID: "grid",
TIME_FORMAT: "timeFormat",
VIEWS: "views"
};
// src/v2/storage/settings/SettingsService.ts
var _SettingsService = class _SettingsService extends BaseEntityService {
constructor(context, eventBus) {
super(context, eventBus);
this.storeName = SettingsStore.STORE_NAME;
this.entityType = "Settings";
}
/**
* Get workweek settings
*/
async getWorkweekSettings() {
return this.get(SettingsIds.WORKWEEK);
}
/**
* Get grid settings
*/
async getGridSettings() {
return this.get(SettingsIds.GRID);
}
/**
* Get time format settings
*/
async getTimeFormatSettings() {
return this.get(SettingsIds.TIME_FORMAT);
}
/**
* Get view settings
*/
async getViewSettings() {
return this.get(SettingsIds.VIEWS);
}
/**
* Get workweek preset by ID
*/
async getWorkweekPreset(presetId) {
const settings = await this.getWorkweekSettings();
if (!settings)
return null;
return settings.presets[presetId] || null;
}
/**
* Get the default workweek preset
*/
async getDefaultWorkweekPreset() {
const settings = await this.getWorkweekSettings();
if (!settings)
return null;
return settings.presets[settings.defaultPreset] || null;
}
/**
* Get all available workweek presets
*/
async getWorkweekPresets() {
const settings = await this.getWorkweekSettings();
if (!settings)
return [];
return Object.values(settings.presets);
}
};
__name(_SettingsService, "SettingsService");
var SettingsService = _SettingsService;
// src/v2/storage/viewconfigs/ViewConfigStore.ts
var _ViewConfigStore = class _ViewConfigStore {
constructor() {
this.storeName = _ViewConfigStore.STORE_NAME;
}
create(db) {
db.createObjectStore(_ViewConfigStore.STORE_NAME, { keyPath: "id" });
}
};
__name(_ViewConfigStore, "ViewConfigStore");
var ViewConfigStore = _ViewConfigStore;
ViewConfigStore.STORE_NAME = "viewconfigs";
// src/v2/storage/viewconfigs/ViewConfigService.ts
var _ViewConfigService = class _ViewConfigService extends BaseEntityService {
constructor(context, eventBus) {
super(context, eventBus);
this.storeName = ViewConfigStore.STORE_NAME;
this.entityType = "ViewConfig";
}
async getById(id) {
return this.get(id);
}
};
__name(_ViewConfigService, "ViewConfigService");
var ViewConfigService = _ViewConfigService;
// src/v2/storage/audit/AuditStore.ts
var _AuditStore = class _AuditStore {
constructor() {
this.storeName = "audit";
}
create(db) {
const store = db.createObjectStore(this.storeName, { keyPath: "id" });
store.createIndex("syncStatus", "syncStatus", { unique: false });
store.createIndex("synced", "synced", { unique: false });
store.createIndex("entityId", "entityId", { unique: false });
store.createIndex("timestamp", "timestamp", { unique: false });
}
};
__name(_AuditStore, "AuditStore");
var AuditStore = _AuditStore;
// src/v2/storage/audit/AuditService.ts
var _AuditService = class _AuditService extends BaseEntityService {
constructor(context, eventBus) {
super(context, eventBus);
this.storeName = "audit";
this.entityType = "Audit";
this.setupEventListeners();
}
/**
* Setup listeners for ENTITY_SAVED and ENTITY_DELETED events
*/
setupEventListeners() {
this.eventBus.on(CoreEvents.ENTITY_SAVED, (event) => {
const detail = event.detail;
this.handleEntitySaved(detail);
});
this.eventBus.on(CoreEvents.ENTITY_DELETED, (event) => {
const detail = event.detail;
this.handleEntityDeleted(detail);
});
}
/**
* Handle ENTITY_SAVED event - create audit entry
*/
async handleEntitySaved(payload) {
if (payload.entityType === "Audit")
return;
const auditEntry = {
id: crypto.randomUUID(),
entityType: payload.entityType,
entityId: payload.entityId,
operation: payload.operation,
userId: _AuditService.DEFAULT_USER_ID,
timestamp: payload.timestamp,
changes: payload.changes,
synced: false,
syncStatus: "pending"
};
await this.save(auditEntry);
}
/**
* Handle ENTITY_DELETED event - create audit entry
*/
async handleEntityDeleted(payload) {
if (payload.entityType === "Audit")
return;
const auditEntry = {
id: crypto.randomUUID(),
entityType: payload.entityType,
entityId: payload.entityId,
operation: "delete",
userId: _AuditService.DEFAULT_USER_ID,
timestamp: payload.timestamp,
changes: { id: payload.entityId },
// For delete, just store the ID
synced: false,
syncStatus: "pending"
};
await this.save(auditEntry);
}
/**
* Override save to NOT trigger ENTITY_SAVED event
* Instead, emits AUDIT_LOGGED for SyncManager to listen
*
* This prevents infinite loops:
* - BaseEntityService.save() emits ENTITY_SAVED
* - AuditService listens to ENTITY_SAVED and creates audit
* - If AuditService.save() also emitted ENTITY_SAVED, it would loop
*/
async save(entity) {
const serialized = this.serialize(entity);
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([this.storeName], "readwrite");
const store = transaction.objectStore(this.storeName);
const request = store.put(serialized);
request.onsuccess = () => {
const payload = {
auditId: entity.id,
entityType: entity.entityType,
entityId: entity.entityId,
operation: entity.operation,
timestamp: entity.timestamp
};
this.eventBus.emit(CoreEvents.AUDIT_LOGGED, payload);
resolve();
};
request.onerror = () => {
reject(new Error(`Failed to save audit entry ${entity.id}: ${request.error}`));
};
});
}
/**
* Override delete to NOT trigger ENTITY_DELETED event
* Audit entries should never be deleted (compliance requirement)
*/
async delete(_id) {
throw new Error("Audit entries cannot be deleted (compliance requirement)");
}
/**
* Get pending audit entries (for sync)
*/
async getPendingAudits() {
return this.getBySyncStatus("pending");
}
/**
* Get audit entries for a specific entity
*/
async getByEntityId(entityId) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([this.storeName], "readonly");
const store = transaction.objectStore(this.storeName);
const index = store.index("entityId");
const request = index.getAll(entityId);
request.onsuccess = () => {
const entries = request.result;
resolve(entries);
};
request.onerror = () => {
reject(new Error(`Failed to get audit entries for entity ${entityId}: ${request.error}`));
};
});
}
};
__name(_AuditService, "AuditService");
var AuditService = _AuditService;
AuditService.DEFAULT_USER_ID = "00000000-0000-0000-0000-000000000001";
// src/v2/repositories/MockEventRepository.ts
var _MockEventRepository = class _MockEventRepository {
constructor() {
this.entityType = "Event";
this.dataUrl = "data/mock-events.json";
}
/**
* Fetch all events from mock JSON file
*/
async fetchAll() {
try {
const response = await fetch(this.dataUrl);
if (!response.ok) {
throw new Error(`Failed to load mock events: ${response.status} ${response.statusText}`);
}
const rawData = await response.json();
return this.processCalendarData(rawData);
} catch (error) {
console.error("Failed to load event data:", error);
throw error;
}
}
async sendCreate(_event) {
throw new Error("MockEventRepository does not support sendCreate. Mock data is read-only.");
}
async sendUpdate(_id, _updates) {
throw new Error("MockEventRepository does not support sendUpdate. Mock data is read-only.");
}
async sendDelete(_id) {
throw new Error("MockEventRepository does not support sendDelete. Mock data is read-only.");
}
processCalendarData(data) {
return data.map((event) => {
if (event.type === "customer") {
if (!event.bookingId)
console.warn(`Customer event ${event.id} missing bookingId`);
if (!event.resourceId)
console.warn(`Customer event ${event.id} missing resourceId`);
if (!event.customerId)
console.warn(`Customer event ${event.id} missing customerId`);
}
return {
id: event.id,
title: event.title,
description: event.description,
start: new Date(event.start),
end: new Date(event.end),
type: event.type,
allDay: event.allDay || false,
bookingId: event.bookingId,
resourceId: event.resourceId,
customerId: event.customerId,
recurringId: event.recurringId,
metadata: event.metadata,
syncStatus: "synced"
};
});
}
};
__name(_MockEventRepository, "MockEventRepository");
var MockEventRepository = _MockEventRepository;
// src/v2/repositories/MockResourceRepository.ts
var _MockResourceRepository = class _MockResourceRepository {
constructor() {
this.entityType = "Resource";
this.dataUrl = "data/mock-resources.json";
}
async fetchAll() {
try {
const response = await fetch(this.dataUrl);
if (!response.ok) {
throw new Error(`Failed to load mock resources: ${response.status} ${response.statusText}`);
}
const rawData = await response.json();
return this.processResourceData(rawData);
} catch (error) {
console.error("Failed to load resource data:", error);
throw error;
}
}
async sendCreate(_resource) {
throw new Error("MockResourceRepository does not support sendCreate. Mock data is read-only.");
}
async sendUpdate(_id, _updates) {
throw new Error("MockResourceRepository does not support sendUpdate. Mock data is read-only.");
}
async sendDelete(_id) {
throw new Error("MockResourceRepository does not support sendDelete. Mock data is read-only.");
}
processResourceData(data) {
return data.map((resource) => ({
id: resource.id,
name: resource.name,
displayName: resource.displayName,
type: resource.type,
avatarUrl: resource.avatarUrl,
color: resource.color,
isActive: resource.isActive,
defaultSchedule: resource.defaultSchedule,
metadata: resource.metadata,
syncStatus: "synced"
}));
}
};
__name(_MockResourceRepository, "MockResourceRepository");
var MockResourceRepository = _MockResourceRepository;
// src/v2/repositories/MockBookingRepository.ts
var _MockBookingRepository = class _MockBookingRepository {
constructor() {
this.entityType = "Booking";
this.dataUrl = "data/mock-bookings.json";
}
async fetchAll() {
try {
const response = await fetch(this.dataUrl);
if (!response.ok) {
throw new Error(`Failed to load mock bookings: ${response.status} ${response.statusText}`);
}
const rawData = await response.json();
return this.processBookingData(rawData);
} catch (error) {
console.error("Failed to load booking data:", error);
throw error;
}
}
async sendCreate(_booking) {
throw new Error("MockBookingRepository does not support sendCreate. Mock data is read-only.");
}
async sendUpdate(_id, _updates) {
throw new Error("MockBookingRepository does not support sendUpdate. Mock data is read-only.");
}
async sendDelete(_id) {
throw new Error("MockBookingRepository does not support sendDelete. Mock data is read-only.");
}
processBookingData(data) {
return data.map((booking) => ({
id: booking.id,
customerId: booking.customerId,
status: booking.status,
createdAt: new Date(booking.createdAt),
services: booking.services,
totalPrice: booking.totalPrice,
tags: booking.tags,
notes: booking.notes,
syncStatus: "synced"
}));
}
};
__name(_MockBookingRepository, "MockBookingRepository");
var MockBookingRepository = _MockBookingRepository;
// src/v2/repositories/MockCustomerRepository.ts
var _MockCustomerRepository = class _MockCustomerRepository {
constructor() {
this.entityType = "Customer";
this.dataUrl = "data/mock-customers.json";
}
async fetchAll() {
try {
const response = await fetch(this.dataUrl);
if (!response.ok) {
throw new Error(`Failed to load mock customers: ${response.status} ${response.statusText}`);
}
const rawData = await response.json();
return this.processCustomerData(rawData);
} catch (error) {
console.error("Failed to load customer data:", error);
throw error;
}
}
async sendCreate(_customer) {
throw new Error("MockCustomerRepository does not support sendCreate. Mock data is read-only.");
}
async sendUpdate(_id, _updates) {
throw new Error("MockCustomerRepository does not support sendUpdate. Mock data is read-only.");
}
async sendDelete(_id) {
throw new Error("MockCustomerRepository does not support sendDelete. Mock data is read-only.");
}
processCustomerData(data) {
return data.map((customer) => ({
id: customer.id,
name: customer.name,
phone: customer.phone,
email: customer.email,
metadata: customer.metadata,
syncStatus: "synced"
}));
}
};
__name(_MockCustomerRepository, "MockCustomerRepository");
var MockCustomerRepository = _MockCustomerRepository;
// src/v2/repositories/MockAuditRepository.ts
var _MockAuditRepository = class _MockAuditRepository {
constructor() {
this.entityType = "Audit";
}
async sendCreate(entity) {
await new Promise((resolve) => setTimeout(resolve, 100));
console.log("MockAuditRepository: Audit entry synced to backend:", {
id: entity.id,
entityType: entity.entityType,
entityId: entity.entityId,
operation: entity.operation,
timestamp: new Date(entity.timestamp).toISOString()
});
return entity;
}
async sendUpdate(_id, _entity) {
throw new Error("Audit entries cannot be updated");
}
async sendDelete(_id) {
throw new Error("Audit entries cannot be deleted");
}
async fetchAll() {
return [];
}
async fetchById(_id) {
return null;
}
};
__name(_MockAuditRepository, "MockAuditRepository");
var MockAuditRepository = _MockAuditRepository;
// src/v2/repositories/MockTeamRepository.ts
var _MockTeamRepository = class _MockTeamRepository {
constructor() {
this.entityType = "Team";
this.dataUrl = "data/mock-teams.json";
}
async fetchAll() {
try {
const response = await fetch(this.dataUrl);
if (!response.ok) {
throw new Error(`Failed to load mock teams: ${response.status} ${response.statusText}`);
}
const rawData = await response.json();
return this.processTeamData(rawData);
} catch (error) {
console.error("Failed to load team data:", error);
throw error;
}
}
async sendCreate(_team) {
throw new Error("MockTeamRepository does not support sendCreate. Mock data is read-only.");
}
async sendUpdate(_id, _updates) {
throw new Error("MockTeamRepository does not support sendUpdate. Mock data is read-only.");
}
async sendDelete(_id) {
throw new Error("MockTeamRepository does not support sendDelete. Mock data is read-only.");
}
processTeamData(data) {
return data.map((team) => ({
id: team.id,
name: team.name,
resourceIds: team.resourceIds,
syncStatus: "synced"
}));
}
};
__name(_MockTeamRepository, "MockTeamRepository");
var MockTeamRepository = _MockTeamRepository;
// src/v2/repositories/MockDepartmentRepository.ts
var _MockDepartmentRepository = class _MockDepartmentRepository {
constructor() {
this.entityType = "Department";
this.dataUrl = "data/mock-departments.json";
}
async fetchAll() {
try {
const response = await fetch(this.dataUrl);
if (!response.ok) {
throw new Error(`Failed to load mock departments: ${response.status} ${response.statusText}`);
}
const rawData = await response.json();
return this.processDepartmentData(rawData);
} catch (error) {
console.error("Failed to load department data:", error);
throw error;
}
}
async sendCreate(_department) {
throw new Error("MockDepartmentRepository does not support sendCreate. Mock data is read-only.");
}
async sendUpdate(_id, _updates) {
throw new Error("MockDepartmentRepository does not support sendUpdate. Mock data is read-only.");
}
async sendDelete(_id) {
throw new Error("MockDepartmentRepository does not support sendDelete. Mock data is read-only.");
}
processDepartmentData(data) {
return data.map((dept) => ({
id: dept.id,
name: dept.name,
resourceIds: dept.resourceIds,
syncStatus: "synced"
}));
}
};
__name(_MockDepartmentRepository, "MockDepartmentRepository");
var MockDepartmentRepository = _MockDepartmentRepository;
// src/v2/repositories/MockSettingsRepository.ts
var _MockSettingsRepository = class _MockSettingsRepository {
constructor() {
this.entityType = "Settings";
this.dataUrl = "data/tenant-settings.json";
}
async fetchAll() {
try {
const response = await fetch(this.dataUrl);
if (!response.ok) {
throw new Error(`Failed to load tenant settings: ${response.status} ${response.statusText}`);
}
const settings = await response.json();
return settings.map((s) => ({
...s,
syncStatus: s.syncStatus || "synced"
}));
} catch (error) {
console.error("Failed to load tenant settings:", error);
throw error;
}
}
async sendCreate(_settings) {
throw new Error("MockSettingsRepository does not support sendCreate. Mock data is read-only.");
}
async sendUpdate(_id, _updates) {
throw new Error("MockSettingsRepository does not support sendUpdate. Mock data is read-only.");
}
async sendDelete(_id) {
throw new Error("MockSettingsRepository does not support sendDelete. Mock data is read-only.");
}
};
__name(_MockSettingsRepository, "MockSettingsRepository");
var MockSettingsRepository = _MockSettingsRepository;
// src/v2/repositories/MockViewConfigRepository.ts
var _MockViewConfigRepository = class _MockViewConfigRepository {
constructor() {
this.entityType = "ViewConfig";
this.dataUrl = "data/viewconfigs.json";
}
async fetchAll() {
try {
const response = await fetch(this.dataUrl);
if (!response.ok) {
throw new Error(`Failed to load viewconfigs: ${response.status} ${response.statusText}`);
}
const rawData = await response.json();
const configs = rawData.map((config) => ({
...config,
syncStatus: config.syncStatus || "synced"
}));
return configs;
} catch (error) {
console.error("Failed to load viewconfigs:", error);
throw error;
}
}
async sendCreate(_config) {
throw new Error("MockViewConfigRepository does not support sendCreate. Mock data is read-only.");
}
async sendUpdate(_id, _updates) {
throw new Error("MockViewConfigRepository does not support sendUpdate. Mock data is read-only.");
}
async sendDelete(_id) {
throw new Error("MockViewConfigRepository does not support sendDelete. Mock data is read-only.");
}
};
__name(_MockViewConfigRepository, "MockViewConfigRepository");
var MockViewConfigRepository = _MockViewConfigRepository;
// src/v2/workers/DataSeeder.ts
var _DataSeeder = class _DataSeeder {
constructor(services, repositories) {
this.services = services;
this.repositories = repositories;
}
/**
* Seed all entity stores if they are empty
*/
async seedIfEmpty() {
console.log("[DataSeeder] Checking if database needs seeding...");
try {
for (const service of this.services) {
const repository = this.repositories.find((repo) => repo.entityType === service.entityType);
if (!repository) {
console.warn(`[DataSeeder] No repository found for entity type: ${service.entityType}, skipping`);
continue;
}
await this.seedEntity(service.entityType, service, repository);
}
console.log("[DataSeeder] Seeding complete");
} catch (error) {
console.error("[DataSeeder] Seeding failed:", error);
throw error;
}
}
async seedEntity(entityType, service, repository) {
const existing = await service.getAll();
if (existing.length > 0) {
console.log(`[DataSeeder] ${entityType} store already has ${existing.length} items, skipping seed`);
return;
}
console.log(`[DataSeeder] ${entityType} store is empty, fetching from repository...`);
const data = await repository.fetchAll();
console.log(`[DataSeeder] Fetched ${data.length} ${entityType} items, saving to IndexedDB...`);
for (const entity of data) {
await service.save(entity, true);
}
console.log(`[DataSeeder] ${entityType} seeding complete (${data.length} items saved)`);
}
};
__name(_DataSeeder, "DataSeeder");
var DataSeeder = _DataSeeder;
// src/v2/utils/PositionUtils.ts
function calculateEventPosition(start, end, config) {
const startMinutes = start.getHours() * 60 + start.getMinutes();
const endMinutes = end.getHours() * 60 + end.getMinutes();
const dayStartMinutes = config.dayStartHour * 60;
const minuteHeight = config.hourHeight / 60;
const top = (startMinutes - dayStartMinutes) * minuteHeight;
const height = (endMinutes - startMinutes) * minuteHeight;
return { top, height };
}
__name(calculateEventPosition, "calculateEventPosition");
function minutesToPixels(minutes, config) {
return minutes / 60 * config.hourHeight;
}
__name(minutesToPixels, "minutesToPixels");
function pixelsToMinutes(pixels, config) {
return pixels / config.hourHeight * 60;
}
__name(pixelsToMinutes, "pixelsToMinutes");
function snapToGrid(pixels, config) {
const snapPixels = minutesToPixels(config.snapInterval, config);
return Math.round(pixels / snapPixels) * snapPixels;
}
__name(snapToGrid, "snapToGrid");
// src/v2/features/event/EventLayoutEngine.ts
function eventsOverlap(a, b) {
return a.start < b.end && a.end > b.start;
}
__name(eventsOverlap, "eventsOverlap");
function eventsWithinThreshold(a, b, thresholdMinutes) {
const thresholdMs = thresholdMinutes * 60 * 1e3;
const startToStartDiff = Math.abs(a.start.getTime() - b.start.getTime());
if (startToStartDiff <= thresholdMs)
return true;
const bStartsBeforeAEnds = a.end.getTime() - b.start.getTime();
if (bStartsBeforeAEnds > 0 && bStartsBeforeAEnds <= thresholdMs)
return true;
const aStartsBeforeBEnds = b.end.getTime() - a.start.getTime();
if (aStartsBeforeBEnds > 0 && aStartsBeforeBEnds <= thresholdMs)
return true;
return false;
}
__name(eventsWithinThreshold, "eventsWithinThreshold");
function findOverlapGroups(events) {
if (events.length === 0)
return [];
const sorted = [...events].sort((a, b) => a.start.getTime() - b.start.getTime());
const used = /* @__PURE__ */ new Set();
const groups = [];
for (const event of sorted) {
if (used.has(event.id))
continue;
const group = [event];
used.add(event.id);
let expanded = true;
while (expanded) {
expanded = false;
for (const candidate of sorted) {
if (used.has(candidate.id))
continue;
const connects = group.some((member) => eventsOverlap(member, candidate));
if (connects) {
group.push(candidate);
used.add(candidate.id);
expanded = true;
}
}
}
groups.push(group);
}
return groups;
}
__name(findOverlapGroups, "findOverlapGroups");
function findGridCandidates(events, thresholdMinutes) {
if (events.length === 0)
return [];
const sorted = [...events].sort((a, b) => a.start.getTime() - b.start.getTime());
const used = /* @__PURE__ */ new Set();
const groups = [];
for (const event of sorted) {
if (used.has(event.id))
continue;
const group = [event];
used.add(event.id);
let expanded = true;
while (expanded) {
expanded = false;
for (const candidate of sorted) {
if (used.has(candidate.id))
continue;
const connects = group.some((member) => eventsWithinThreshold(member, candidate, thresholdMinutes));
if (connects) {
group.push(candidate);
used.add(candidate.id);
expanded = true;
}
}
}
groups.push(group);
}
return groups;
}
__name(findGridCandidates, "findGridCandidates");
function calculateStackLevels(events) {
const levels = /* @__PURE__ */ new Map();
const sorted = [...events].sort((a, b) => a.start.getTime() - b.start.getTime());
for (const event of sorted) {
let maxOverlappingLevel = -1;
for (const [id, level] of levels) {
const other = events.find((e) => e.id === id);
if (other && eventsOverlap(event, other)) {
maxOverlappingLevel = Math.max(maxOverlappingLevel, level);
}
}
levels.set(event.id, maxOverlappingLevel + 1);
}
return levels;
}
__name(calculateStackLevels, "calculateStackLevels");
function allocateColumns(events) {
const sorted = [...events].sort((a, b) => a.start.getTime() - b.start.getTime());
const columns = [];
for (const event of sorted) {
let placed = false;
for (const column of columns) {
const canFit = !column.some((e) => eventsOverlap(event, e));
if (canFit) {
column.push(event);
placed = true;
break;
}
}
if (!placed) {
columns.push([event]);
}
}
return columns;
}
__name(allocateColumns, "allocateColumns");
function calculateColumnLayout(events, config) {
const thresholdMinutes = config.gridStartThresholdMinutes ?? 10;
const result = {
grids: [],
stacked: []
};
if (events.length === 0)
return result;
const overlapGroups = findOverlapGroups(events);
for (const overlapGroup of overlapGroups) {
if (overlapGroup.length === 1) {
result.stacked.push({
event: overlapGroup[0],
stackLevel: 0
});
continue;
}
const gridSubgroups = findGridCandidates(overlapGroup, thresholdMinutes);
const largestGridCandidate = gridSubgroups.reduce((max, g) => g.length > max.length ? g : max, gridSubgroups[0]);
if (largestGridCandidate.length === overlapGroup.length) {
const columns = allocateColumns(overlapGroup);
const earliest = overlapGroup.reduce((min, e) => e.start < min.start ? e : min, overlapGroup[0]);
const position = calculateEventPosition(earliest.start, earliest.end, config);
result.grids.push({
events: overlapGroup,
columns,
stackLevel: 0,
position: { top: position.top }
});
} else {
const levels = calculateStackLevels(overlapGroup);
for (const event of overlapGroup) {
result.stacked.push({
event,
stackLevel: levels.get(event.id) ?? 0
});
}
}
}
return result;
}
__name(calculateColumnLayout, "calculateColumnLayout");
// src/v2/features/event/EventRenderer.ts
var _EventRenderer = class _EventRenderer {
constructor(eventService, dateService, gridConfig, eventBus) {
this.eventService = eventService;
this.dateService = dateService;
this.gridConfig = gridConfig;
this.eventBus = eventBus;
this.container = null;
this.setupListeners();
}
/**
* Setup listeners for drag-drop and update events
*/
setupListeners() {
this.eventBus.on(CoreEvents.EVENT_DRAG_COLUMN_CHANGE, (e) => {
const payload = e.detail;
this.handleColumnChange(payload);
});
this.eventBus.on(CoreEvents.EVENT_DRAG_MOVE, (e) => {
const payload = e.detail;
this.updateDragTimestamp(payload);
});
this.eventBus.on(CoreEvents.EVENT_UPDATED, (e) => {
const payload = e.detail;
this.handleEventUpdated(payload);
});
this.eventBus.on(CoreEvents.EVENT_DRAG_END, (e) => {
const payload = e.detail;
this.handleDragEnd(payload);
});
this.eventBus.on(CoreEvents.EVENT_DRAG_LEAVE_HEADER, (e) => {
const payload = e.detail;
this.handleDragLeaveHeader(payload);
});
}
/**
* Handle EVENT_DRAG_END - remove element if dropped in header
*/
handleDragEnd(payload) {
if (payload.target === "header") {
const element = this.container?.querySelector(`swp-content-viewport swp-event[data-event-id="${payload.swpEvent.eventId}"]`);
element?.remove();
}
}
/**
* Handle header item leaving header - create swp-event in grid
*/
handleDragLeaveHeader(payload) {
if (payload.source !== "header")
return;
if (!payload.targetColumn || !payload.start || !payload.end)
return;
if (payload.element) {
payload.element.classList.add("drag-ghost");
payload.element.style.opacity = "0.3";
payload.element.style.pointerEvents = "none";
}
const event = {
id: payload.eventId,
title: payload.title || "",
description: "",
start: payload.start,
end: payload.end,
type: "customer",
allDay: false,
syncStatus: "pending"
};
const element = this.createEventElement(event);
let eventsLayer = payload.targetColumn.querySelector("swp-events-layer");
if (!eventsLayer) {
eventsLayer = document.createElement("swp-events-layer");
payload.targetColumn.appendChild(eventsLayer);
}
eventsLayer.appendChild(element);
element.classList.add("dragging");
}
/**
* Handle EVENT_UPDATED - re-render affected columns
*/
async handleEventUpdated(payload) {
if (payload.sourceColumnKey !== payload.targetColumnKey) {
await this.rerenderColumn(payload.sourceColumnKey);
}
await this.rerenderColumn(payload.targetColumnKey);
}
/**
* Re-render a single column with fresh data from IndexedDB
*/
async rerenderColumn(columnKey) {
const column = this.findColumn(columnKey);
if (!column)
return;
const date = column.dataset.date;
const resourceId = column.dataset.resourceId;
if (!date)
return;
const startDate = new Date(date);
const endDate = new Date(date);
endDate.setHours(23, 59, 59, 999);
const events = resourceId ? await this.eventService.getByResourceAndDateRange(resourceId, startDate, endDate) : await this.eventService.getByDateRange(startDate, endDate);
const timedEvents = events.filter((event) => !event.allDay && this.dateService.getDateKey(event.start) === date);
let eventsLayer = column.querySelector("swp-events-layer");
if (!eventsLayer) {
eventsLayer = document.createElement("swp-events-layer");
column.appendChild(eventsLayer);
}
eventsLayer.innerHTML = "";
const layout = calculateColumnLayout(timedEvents, this.gridConfig);
layout.grids.forEach((grid) => {
const groupEl = this.renderGridGroup(grid);
eventsLayer.appendChild(groupEl);
});
layout.stacked.forEach((item) => {
const eventEl = this.renderStackedEvent(item.event, item.stackLevel);
eventsLayer.appendChild(eventEl);
});
}
/**
* Find a column element by columnKey
*/
findColumn(columnKey) {
if (!this.container)
return null;
return this.container.querySelector(`swp-day-column[data-column-key="${columnKey}"]`);
}
/**
* Handle event moving to a new column during drag
*/
handleColumnChange(payload) {
const eventsLayer = payload.newColumn.querySelector("swp-events-layer");
if (!eventsLayer)
return;
eventsLayer.appendChild(payload.element);
payload.element.style.top = `${payload.currentY}px`;
}
/**
* Update timestamp display during drag (snapped to grid)
*/
updateDragTimestamp(payload) {
const timeEl = payload.element.querySelector("swp-event-time");
if (!timeEl)
return;
const snappedY = snapToGrid(payload.currentY, this.gridConfig);
const minutesFromGridStart = pixelsToMinutes(snappedY, this.gridConfig);
const startMinutes = this.gridConfig.dayStartHour * 60 + minutesFromGridStart;
const height = parseFloat(payload.element.style.height) || this.gridConfig.hourHeight;
const durationMinutes = pixelsToMinutes(height, this.gridConfig);
const start = this.minutesToDate(startMinutes);
const end = this.minutesToDate(startMinutes + durationMinutes);
timeEl.textContent = this.dateService.formatTimeRange(start, end);
}
/**
* Convert minutes since midnight to a Date object (today)
*/
minutesToDate(minutes) {
const date = /* @__PURE__ */ new Date();
date.setHours(Math.floor(minutes / 60) % 24, minutes % 60, 0, 0);
return date;
}
/**
* Render events for visible dates into day columns
* @param container - Calendar container element
* @param filter - Filter with 'date' and optionally 'resource' arrays
* @param filterTemplate - Template for matching events to columns
*/
async render(container2, filter, filterTemplate) {
this.container = container2;
const visibleDates = filter["date"] || [];
if (visibleDates.length === 0)
return;
const startDate = new Date(visibleDates[0]);
const endDate = new Date(visibleDates[visibleDates.length - 1]);
endDate.setHours(23, 59, 59, 999);
const events = await this.eventService.getByDateRange(startDate, endDate);
const dayColumns = container2.querySelector("swp-day-columns");
if (!dayColumns)
return;
const columns = dayColumns.querySelectorAll("swp-day-column");
columns.forEach((column) => {
const columnEl = column;
const columnEvents = events.filter((event) => filterTemplate.matches(event, columnEl));
let eventsLayer = column.querySelector("swp-events-layer");
if (!eventsLayer) {
eventsLayer = document.createElement("swp-events-layer");
column.appendChild(eventsLayer);
}
eventsLayer.innerHTML = "";
const timedEvents = columnEvents.filter((event) => !event.allDay);
const layout = calculateColumnLayout(timedEvents, this.gridConfig);
layout.grids.forEach((grid) => {
const groupEl = this.renderGridGroup(grid);
eventsLayer.appendChild(groupEl);
});
layout.stacked.forEach((item) => {
const eventEl = this.renderStackedEvent(item.event, item.stackLevel);
eventsLayer.appendChild(eventEl);
});
});
}
/**
* Create a single event element
*
* CLEAN approach:
* - Only data-id for lookup
* - Visible content in innerHTML only
*/
createEventElement(event) {
const element = document.createElement("swp-event");
element.dataset.eventId = event.id;
if (event.resourceId) {
element.dataset.resourceId = event.resourceId;
}
const position = calculateEventPosition(event.start, event.end, this.gridConfig);
element.style.top = `${position.top}px`;
element.style.height = `${position.height}px`;
const colorClass = this.getColorClass(event);
if (colorClass) {
element.classList.add(colorClass);
}
element.innerHTML = `
<swp-event-time>${this.dateService.formatTimeRange(event.start, event.end)}</swp-event-time>
<swp-event-title>${this.escapeHtml(event.title)}</swp-event-title>
${event.description ? `<swp-event-description>${this.escapeHtml(event.description)}</swp-event-description>` : ""}
`;
return element;
}
/**
* Get color class based on metadata.color or event type
*/
getColorClass(event) {
if (event.metadata?.color) {
return `is-${event.metadata.color}`;
}
const typeColors = {
"customer": "is-blue",
"vacation": "is-green",
"break": "is-amber",
"meeting": "is-purple",
"blocked": "is-red"
};
return typeColors[event.type] || "is-blue";
}
/**
* Escape HTML to prevent XSS
*/
escapeHtml(text) {
const div = document.createElement("div");
div.textContent = text;
return div.innerHTML;
}
/**
* Render a GRID group with side-by-side columns
* Used when multiple events start at the same time
*/
renderGridGroup(layout) {
const group = document.createElement("swp-event-group");
group.classList.add(`cols-${layout.columns.length}`);
group.style.top = `${layout.position.top}px`;
if (layout.stackLevel > 0) {
group.style.marginLeft = `${layout.stackLevel * 15}px`;
group.style.zIndex = `${100 + layout.stackLevel}`;
}
let maxBottom = 0;
for (const event of layout.events) {
const pos = calculateEventPosition(event.start, event.end, this.gridConfig);
const eventBottom = pos.top + pos.height;
if (eventBottom > maxBottom)
maxBottom = eventBottom;
}
const groupHeight = maxBottom - layout.position.top;
group.style.height = `${groupHeight}px`;
layout.columns.forEach((columnEvents) => {
const wrapper = document.createElement("div");
wrapper.style.position = "relative";
columnEvents.forEach((event) => {
const eventEl = this.createEventElement(event);
const pos = calculateEventPosition(event.start, event.end, this.gridConfig);
eventEl.style.top = `${pos.top - layout.position.top}px`;
eventEl.style.position = "absolute";
eventEl.style.left = "0";
eventEl.style.right = "0";
wrapper.appendChild(eventEl);
});
group.appendChild(wrapper);
});
return group;
}
/**
* Render a STACKED event with margin-left offset
* Used for overlapping events that don't start at the same time
*/
renderStackedEvent(event, stackLevel) {
const element = this.createEventElement(event);
element.dataset.stackLink = JSON.stringify({ stackLevel });
if (stackLevel > 0) {
element.style.marginLeft = `${stackLevel * 15}px`;
element.style.zIndex = `${100 + stackLevel}`;
}
return element;
}
};
__name(_EventRenderer, "EventRenderer");
var EventRenderer = _EventRenderer;
// src/v2/features/schedule/ScheduleRenderer.ts
var _ScheduleRenderer = class _ScheduleRenderer {
constructor(scheduleService, dateService, gridConfig) {
this.scheduleService = scheduleService;
this.dateService = dateService;
this.gridConfig = gridConfig;
}
/**
* Render unavailable zones for visible columns
* @param container - Calendar container element
* @param filter - Filter with 'date' and 'resource' arrays
*/
async render(container2, filter) {
const dates = filter["date"] || [];
const resourceIds = filter["resource"] || [];
if (dates.length === 0)
return;
const dayColumns = container2.querySelector("swp-day-columns");
if (!dayColumns)
return;
const columns = dayColumns.querySelectorAll("swp-day-column");
for (const column of columns) {
const date = column.dataset.date;
const resourceId = column.dataset.resourceId;
if (!date || !resourceId)
continue;
let unavailableLayer = column.querySelector("swp-unavailable-layer");
if (!unavailableLayer) {
unavailableLayer = document.createElement("swp-unavailable-layer");
column.insertBefore(unavailableLayer, column.firstChild);
}
unavailableLayer.innerHTML = "";
const schedule = await this.scheduleService.getScheduleForDate(resourceId, date);
this.renderUnavailableZones(unavailableLayer, schedule);
}
}
/**
* Render unavailable time zones based on schedule
*/
renderUnavailableZones(layer, schedule) {
const dayStartMinutes = this.gridConfig.dayStartHour * 60;
const dayEndMinutes = this.gridConfig.dayEndHour * 60;
const minuteHeight = this.gridConfig.hourHeight / 60;
if (schedule === null) {
const zone = this.createUnavailableZone(0, (dayEndMinutes - dayStartMinutes) * minuteHeight);
layer.appendChild(zone);
return;
}
const workStartMinutes = this.dateService.timeToMinutes(schedule.start);
const workEndMinutes = this.dateService.timeToMinutes(schedule.end);
if (workStartMinutes > dayStartMinutes) {
const top = 0;
const height = (workStartMinutes - dayStartMinutes) * minuteHeight;
const zone = this.createUnavailableZone(top, height);
layer.appendChild(zone);
}
if (workEndMinutes < dayEndMinutes) {
const top = (workEndMinutes - dayStartMinutes) * minuteHeight;
const height = (dayEndMinutes - workEndMinutes) * minuteHeight;
const zone = this.createUnavailableZone(top, height);
layer.appendChild(zone);
}
}
/**
* Create an unavailable zone element
*/
createUnavailableZone(top, height) {
const zone = document.createElement("swp-unavailable-zone");
zone.style.top = `${top}px`;
zone.style.height = `${height}px`;
return zone;
}
};
__name(_ScheduleRenderer, "ScheduleRenderer");
var ScheduleRenderer = _ScheduleRenderer;
// src/v2/features/headerdrawer/HeaderDrawerRenderer.ts
var _HeaderDrawerRenderer = class _HeaderDrawerRenderer {
constructor(eventBus, gridConfig, headerDrawerManager, eventService, dateService) {
this.eventBus = eventBus;
this.gridConfig = gridConfig;
this.headerDrawerManager = headerDrawerManager;
this.eventService = eventService;
this.dateService = dateService;
this.currentItem = null;
this.container = null;
this.sourceElement = null;
this.wasExpandedBeforeDrag = false;
this.filterTemplate = null;
this.setupListeners();
}
/**
* Render allDay events into the header drawer with row stacking
* @param filterTemplate - Template for matching events to columns
*/
async render(container2, filter, filterTemplate) {
this.filterTemplate = filterTemplate;
const drawer = container2.querySelector("swp-header-drawer");
if (!drawer)
return;
const visibleDates = filter["date"] || [];
if (visibleDates.length === 0)
return;
const visibleColumnKeys = this.getVisibleColumnKeysFromDOM();
if (visibleColumnKeys.length === 0)
return;
const startDate = new Date(visibleDates[0]);
const endDate = new Date(visibleDates[visibleDates.length - 1]);
endDate.setHours(23, 59, 59, 999);
const events = await this.eventService.getByDateRange(startDate, endDate);
const allDayEvents = events.filter((event) => event.allDay !== false);
drawer.innerHTML = "";
if (allDayEvents.length === 0)
return;
const layouts = this.calculateLayout(allDayEvents, visibleColumnKeys);
const rowCount = Math.max(1, ...layouts.map((l) => l.row));
layouts.forEach((layout) => {
const item = this.createHeaderItem(layout);
drawer.appendChild(item);
});
this.headerDrawerManager.expandToRows(rowCount);
}
/**
* Create a header item element from layout
*/
createHeaderItem(layout) {
const { event, columnKey, row, colStart, colEnd } = layout;
const item = document.createElement("swp-header-item");
item.dataset.eventId = event.id;
item.dataset.itemType = "event";
item.dataset.start = event.start.toISOString();
item.dataset.end = event.end.toISOString();
item.dataset.columnKey = columnKey;
item.textContent = event.title;
const colorClass = this.getColorClass(event);
if (colorClass)
item.classList.add(colorClass);
item.style.gridArea = `${row} / ${colStart} / ${row + 1} / ${colEnd}`;
return item;
}
/**
* Calculate layout for all events with row stacking
* Uses track-based algorithm to find available rows for overlapping events
*/
calculateLayout(events, visibleColumnKeys) {
const tracks = [new Array(visibleColumnKeys.length).fill(false)];
const layouts = [];
for (const event of events) {
const columnKey = this.buildColumnKeyFromEvent(event);
const startCol = visibleColumnKeys.indexOf(columnKey);
const endColumnKey = this.buildColumnKeyFromEvent(event, event.end);
const endCol = visibleColumnKeys.indexOf(endColumnKey);
if (startCol === -1 && endCol === -1)
continue;
const colStart = Math.max(0, startCol);
const colEnd = (endCol !== -1 ? endCol : visibleColumnKeys.length - 1) + 1;
const row = this.findAvailableRow(tracks, colStart, colEnd);
for (let c = colStart; c < colEnd; c++) {
tracks[row][c] = true;
}
layouts.push({ event, columnKey, row: row + 1, colStart: colStart + 1, colEnd: colEnd + 1 });
}
return layouts;
}
/**
* Build columnKey from event using FilterTemplate
* Uses the same template that columns use for matching
*/
buildColumnKeyFromEvent(event, date) {
if (!this.filterTemplate) {
const dateStr = this.dateService.getDateKey(date || event.start);
return dateStr;
}
if (date && date.getTime() !== event.start.getTime()) {
const tempEvent = { ...event, start: date };
return this.filterTemplate.buildKeyFromEvent(tempEvent);
}
return this.filterTemplate.buildKeyFromEvent(event);
}
/**
* Find available row for event spanning columns [colStart, colEnd)
*/
findAvailableRow(tracks, colStart, colEnd) {
for (let row = 0; row < tracks.length; row++) {
let available = true;
for (let c = colStart; c < colEnd; c++) {
if (tracks[row][c]) {
available = false;
break;
}
}
if (available)
return row;
}
tracks.push(new Array(tracks[0].length).fill(false));
return tracks.length - 1;
}
/**
* Get color class based on event metadata or type
*/
getColorClass(event) {
if (event.metadata?.color) {
return `is-${event.metadata.color}`;
}
const typeColors = {
"customer": "is-blue",
"vacation": "is-green",
"break": "is-amber",
"meeting": "is-purple",
"blocked": "is-red"
};
return typeColors[event.type] || "is-blue";
}
/**
* Setup event listeners for drag events
*/
setupListeners() {
this.eventBus.on(CoreEvents.EVENT_DRAG_ENTER_HEADER, (e) => {
const payload = e.detail;
this.handleDragEnter(payload);
});
this.eventBus.on(CoreEvents.EVENT_DRAG_MOVE_HEADER, (e) => {
const payload = e.detail;
this.handleDragMove(payload);
});
this.eventBus.on(CoreEvents.EVENT_DRAG_LEAVE_HEADER, (e) => {
const payload = e.detail;
this.handleDragLeave(payload);
});
this.eventBus.on(CoreEvents.EVENT_DRAG_END, (e) => {
const payload = e.detail;
this.handleDragEnd(payload);
});
this.eventBus.on(CoreEvents.EVENT_DRAG_CANCEL, () => {
this.cleanup();
});
}
/**
* Handle drag entering header zone - create preview item
*/
handleDragEnter(payload) {
this.container = document.querySelector("swp-header-drawer");
if (!this.container)
return;
this.wasExpandedBeforeDrag = this.headerDrawerManager.isExpanded();
if (!this.wasExpandedBeforeDrag) {
this.headerDrawerManager.expandToRows(1);
}
this.sourceElement = payload.element;
const item = document.createElement("swp-header-item");
item.dataset.eventId = payload.eventId;
item.dataset.itemType = payload.itemType;
item.dataset.duration = String(payload.duration);
item.dataset.columnKey = payload.sourceColumnKey;
item.textContent = payload.title;
if (payload.colorClass) {
item.classList.add(payload.colorClass);
}
item.classList.add("dragging");
const col = payload.sourceColumnIndex + 1;
const endCol = col + payload.duration;
item.style.gridArea = `1 / ${col} / 2 / ${endCol}`;
this.container.appendChild(item);
this.currentItem = item;
payload.element.style.visibility = "hidden";
}
/**
* Handle drag moving within header - update column position
*/
handleDragMove(payload) {
if (!this.currentItem)
return;
const col = payload.columnIndex + 1;
const duration = parseInt(this.currentItem.dataset.duration || "1", 10);
const endCol = col + duration;
this.currentItem.style.gridArea = `1 / ${col} / 2 / ${endCol}`;
this.currentItem.dataset.columnKey = payload.columnKey;
}
/**
* Handle drag leaving header - cleanup for grid→header drag only
*/
handleDragLeave(payload) {
if (payload.source === "grid") {
this.cleanup();
}
}
/**
* Handle drag end - finalize based on drop target
*/
handleDragEnd(payload) {
if (payload.target === "header") {
if (this.currentItem) {
this.currentItem.classList.remove("dragging");
this.recalculateDrawerLayout();
this.currentItem = null;
this.sourceElement = null;
}
} else {
const ghost = document.querySelector(`swp-header-item.drag-ghost[data-event-id="${payload.swpEvent.eventId}"]`);
ghost?.remove();
this.recalculateDrawerLayout();
}
}
/**
* Recalculate layout for all items currently in the drawer
* Called after drop to reposition items and adjust height
*/
recalculateDrawerLayout() {
const drawer = document.querySelector("swp-header-drawer");
if (!drawer)
return;
const items = Array.from(drawer.querySelectorAll("swp-header-item"));
if (items.length === 0)
return;
const visibleColumnKeys = this.getVisibleColumnKeysFromDOM();
if (visibleColumnKeys.length === 0)
return;
const itemData = items.map((item) => ({
element: item,
columnKey: item.dataset.columnKey || "",
duration: parseInt(item.dataset.duration || "1", 10)
}));
const tracks = [new Array(visibleColumnKeys.length).fill(false)];
for (const item of itemData) {
const startCol = visibleColumnKeys.indexOf(item.columnKey);
if (startCol === -1)
continue;
const colStart = startCol;
const colEnd = Math.min(startCol + item.duration, visibleColumnKeys.length);
const row = this.findAvailableRow(tracks, colStart, colEnd);
for (let c = colStart; c < colEnd; c++) {
tracks[row][c] = true;
}
item.element.style.gridArea = `${row + 1} / ${colStart + 1} / ${row + 2} / ${colEnd + 1}`;
}
const rowCount = tracks.length;
this.headerDrawerManager.expandToRows(rowCount);
}
/**
* Get visible column keys from DOM (preserves order for multi-resource views)
* Uses filterTemplate.buildKeyFromColumn() for consistent key format with events
*/
getVisibleColumnKeysFromDOM() {
if (!this.filterTemplate)
return [];
const columns = document.querySelectorAll("swp-day-column");
const columnKeys = [];
columns.forEach((col) => {
const columnKey = this.filterTemplate.buildKeyFromColumn(col);
if (columnKey)
columnKeys.push(columnKey);
});
return columnKeys;
}
/**
* Cleanup preview item and restore source visibility
*/
cleanup() {
this.currentItem?.remove();
this.currentItem = null;
if (this.sourceElement) {
this.sourceElement.style.visibility = "";
this.sourceElement = null;
}
if (!this.wasExpandedBeforeDrag) {
this.headerDrawerManager.collapse();
}
}
};
__name(_HeaderDrawerRenderer, "HeaderDrawerRenderer");
var HeaderDrawerRenderer = _HeaderDrawerRenderer;
// src/v2/storage/schedules/ScheduleOverrideStore.ts
var _ScheduleOverrideStore = class _ScheduleOverrideStore {
constructor() {
this.storeName = _ScheduleOverrideStore.STORE_NAME;
}
create(db) {
const store = db.createObjectStore(_ScheduleOverrideStore.STORE_NAME, { keyPath: "id" });
store.createIndex("resourceId", "resourceId", { unique: false });
store.createIndex("date", "date", { unique: false });
store.createIndex("resourceId_date", ["resourceId", "date"], { unique: true });
store.createIndex("syncStatus", "syncStatus", { unique: false });
}
};
__name(_ScheduleOverrideStore, "ScheduleOverrideStore");
var ScheduleOverrideStore = _ScheduleOverrideStore;
ScheduleOverrideStore.STORE_NAME = "scheduleOverrides";
// src/v2/storage/schedules/ScheduleOverrideService.ts
var _ScheduleOverrideService = class _ScheduleOverrideService {
constructor(context) {
this.context = context;
}
get db() {
return this.context.getDatabase();
}
/**
* Get override for a specific resource and date
*/
async getOverride(resourceId, date) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([ScheduleOverrideStore.STORE_NAME], "readonly");
const store = transaction.objectStore(ScheduleOverrideStore.STORE_NAME);
const index = store.index("resourceId_date");
const request = index.get([resourceId, date]);
request.onsuccess = () => {
resolve(request.result || null);
};
request.onerror = () => {
reject(new Error(`Failed to get override for ${resourceId} on ${date}: ${request.error}`));
};
});
}
/**
* Get all overrides for a resource
*/
async getByResource(resourceId) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([ScheduleOverrideStore.STORE_NAME], "readonly");
const store = transaction.objectStore(ScheduleOverrideStore.STORE_NAME);
const index = store.index("resourceId");
const request = index.getAll(resourceId);
request.onsuccess = () => {
resolve(request.result || []);
};
request.onerror = () => {
reject(new Error(`Failed to get overrides for ${resourceId}: ${request.error}`));
};
});
}
/**
* Get overrides for a date range
*/
async getByDateRange(resourceId, startDate, endDate) {
const all = await this.getByResource(resourceId);
return all.filter((o) => o.date >= startDate && o.date <= endDate);
}
/**
* Save an override
*/
async save(override) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([ScheduleOverrideStore.STORE_NAME], "readwrite");
const store = transaction.objectStore(ScheduleOverrideStore.STORE_NAME);
const request = store.put(override);
request.onsuccess = () => resolve();
request.onerror = () => {
reject(new Error(`Failed to save override ${override.id}: ${request.error}`));
};
});
}
/**
* Delete an override
*/
async delete(id) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([ScheduleOverrideStore.STORE_NAME], "readwrite");
const store = transaction.objectStore(ScheduleOverrideStore.STORE_NAME);
const request = store.delete(id);
request.onsuccess = () => resolve();
request.onerror = () => {
reject(new Error(`Failed to delete override ${id}: ${request.error}`));
};
});
}
};
__name(_ScheduleOverrideService, "ScheduleOverrideService");
var ScheduleOverrideService = _ScheduleOverrideService;
// src/v2/storage/schedules/ResourceScheduleService.ts
var _ResourceScheduleService = class _ResourceScheduleService {
constructor(resourceService, overrideService, dateService) {
this.resourceService = resourceService;
this.overrideService = overrideService;
this.dateService = dateService;
}
/**
* Get effective schedule for a resource on a specific date
*
* @param resourceId - Resource ID
* @param date - Date string "YYYY-MM-DD"
* @returns ITimeSlot or null (fri/closed)
*/
async getScheduleForDate(resourceId, date) {
const override = await this.overrideService.getOverride(resourceId, date);
if (override) {
return override.schedule;
}
const resource = await this.resourceService.get(resourceId);
if (!resource || !resource.defaultSchedule) {
return null;
}
const weekDay = this.dateService.getISOWeekDay(date);
return resource.defaultSchedule[weekDay] || null;
}
/**
* Get schedules for multiple dates
*
* @param resourceId - Resource ID
* @param dates - Array of date strings "YYYY-MM-DD"
* @returns Map of date -> ITimeSlot | null
*/
async getSchedulesForDates(resourceId, dates) {
const result = /* @__PURE__ */ new Map();
const resource = await this.resourceService.get(resourceId);
const overrides = dates.length > 0 ? await this.overrideService.getByDateRange(resourceId, dates[0], dates[dates.length - 1]) : [];
const overrideMap = new Map(overrides.map((o) => [o.date, o.schedule]));
for (const date of dates) {
if (overrideMap.has(date)) {
result.set(date, overrideMap.get(date));
continue;
}
if (resource?.defaultSchedule) {
const weekDay = this.dateService.getISOWeekDay(date);
result.set(date, resource.defaultSchedule[weekDay] || null);
} else {
result.set(date, null);
}
}
return result;
}
};
__name(_ResourceScheduleService, "ResourceScheduleService");
var ResourceScheduleService = _ResourceScheduleService;
// src/v2/types/SwpEvent.ts
var _SwpEvent = class _SwpEvent {
constructor(element, columnKey, start, end) {
this.element = element;
this.columnKey = columnKey;
this._start = start;
this._end = end;
}
/** Event ID from element.dataset.eventId */
get eventId() {
return this.element.dataset.eventId || "";
}
get start() {
return this._start;
}
get end() {
return this._end;
}
/** Duration in minutes */
get durationMinutes() {
return (this._end.getTime() - this._start.getTime()) / (1e3 * 60);
}
/** Duration in milliseconds */
get durationMs() {
return this._end.getTime() - this._start.getTime();
}
/**
* Factory: Create SwpEvent from element + columnKey
* Reads top/height from element.style to calculate start/end
* @param columnKey - Opaque column identifier (do NOT parse - use only for matching)
* @param date - Date string (YYYY-MM-DD) for time calculations
*/
static fromElement(element, columnKey, date, gridConfig) {
const topPixels = parseFloat(element.style.top) || 0;
const heightPixels = parseFloat(element.style.height) || 0;
const startMinutesFromGrid = topPixels / gridConfig.hourHeight * 60;
const totalMinutes = gridConfig.dayStartHour * 60 + startMinutesFromGrid;
const start = new Date(date);
start.setHours(Math.floor(totalMinutes / 60), totalMinutes % 60, 0, 0);
const durationMinutes = heightPixels / gridConfig.hourHeight * 60;
const end = new Date(start.getTime() + durationMinutes * 60 * 1e3);
return new _SwpEvent(element, columnKey, start, end);
}
};
__name(_SwpEvent, "SwpEvent");
var SwpEvent = _SwpEvent;
// src/v2/managers/DragDropManager.ts
var _DragDropManager = class _DragDropManager {
constructor(eventBus, gridConfig) {
this.eventBus = eventBus;
this.gridConfig = gridConfig;
this.dragState = null;
this.mouseDownPosition = null;
this.pendingElement = null;
this.pendingMouseOffset = null;
this.container = null;
this.inHeader = false;
this.DRAG_THRESHOLD = 5;
this.INTERPOLATION_FACTOR = 0.3;
this.handlePointerDown = (e) => {
const target = e.target;
if (target.closest("swp-resize-handle"))
return;
const eventElement = target.closest("swp-event");
const headerItem = target.closest("swp-header-item");
const draggable = eventElement || headerItem;
if (!draggable)
return;
this.mouseDownPosition = { x: e.clientX, y: e.clientY };
this.pendingElement = draggable;
const rect = draggable.getBoundingClientRect();
this.pendingMouseOffset = {
x: e.clientX - rect.left,
y: e.clientY - rect.top
};
draggable.setPointerCapture(e.pointerId);
};
this.handlePointerMove = (e) => {
if (!this.mouseDownPosition || !this.pendingElement) {
if (this.dragState) {
this.updateDragTarget(e);
}
return;
}
const deltaX = Math.abs(e.clientX - this.mouseDownPosition.x);
const deltaY = Math.abs(e.clientY - this.mouseDownPosition.y);
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance < this.DRAG_THRESHOLD)
return;
this.initializeDrag(this.pendingElement, this.pendingMouseOffset, e);
this.mouseDownPosition = null;
this.pendingElement = null;
this.pendingMouseOffset = null;
};
this.handlePointerUp = (_e) => {
this.mouseDownPosition = null;
this.pendingElement = null;
this.pendingMouseOffset = null;
if (!this.dragState)
return;
cancelAnimationFrame(this.dragState.animationId);
if (this.dragState.dragSource === "header") {
this.handleHeaderItemDragEnd();
} else {
this.handleGridEventDragEnd();
}
this.dragState.element.classList.remove("dragging");
this.dragState = null;
this.inHeader = false;
};
this.animateDrag = () => {
if (!this.dragState)
return;
const diff2 = this.dragState.targetY - this.dragState.currentY;
if (Math.abs(diff2) <= 0.5) {
this.dragState.animationId = 0;
return;
}
this.dragState.currentY += diff2 * this.INTERPOLATION_FACTOR;
this.dragState.element.style.top = `${this.dragState.currentY}px`;
if (this.dragState.columnElement) {
const payload = {
eventId: this.dragState.eventId,
element: this.dragState.element,
currentY: this.dragState.currentY,
columnElement: this.dragState.columnElement
};
this.eventBus.emit(CoreEvents.EVENT_DRAG_MOVE, payload);
}
this.dragState.animationId = requestAnimationFrame(this.animateDrag);
};
this.setupScrollListener();
}
setupScrollListener() {
this.eventBus.on(CoreEvents.EDGE_SCROLL_TICK, (e) => {
if (!this.dragState)
return;
const { scrollDelta } = e.detail;
this.dragState.targetY += scrollDelta;
this.dragState.currentY += scrollDelta;
this.dragState.element.style.top = `${this.dragState.currentY}px`;
});
}
/**
* Initialize drag-drop on a container element
*/
init(container2) {
this.container = container2;
container2.addEventListener("pointerdown", this.handlePointerDown);
document.addEventListener("pointermove", this.handlePointerMove);
document.addEventListener("pointerup", this.handlePointerUp);
}
/**
* Handle drag end for header items
*/
handleHeaderItemDragEnd() {
if (!this.dragState)
return;
if (!this.inHeader && this.dragState.currentColumn) {
const gridEvent = this.dragState.currentColumn.querySelector(`swp-event[data-event-id="${this.dragState.eventId}"]`);
if (gridEvent) {
const columnKey = this.dragState.currentColumn.dataset.columnKey || "";
const date = this.dragState.currentColumn.dataset.date || "";
const swpEvent = SwpEvent.fromElement(gridEvent, columnKey, date, this.gridConfig);
const payload = {
swpEvent,
sourceColumnKey: this.dragState.sourceColumnKey,
target: "grid"
};
this.eventBus.emit(CoreEvents.EVENT_DRAG_END, payload);
}
}
}
/**
* Handle drag end for grid events
*/
handleGridEventDragEnd() {
if (!this.dragState || !this.dragState.columnElement)
return;
const snappedY = snapToGrid(this.dragState.currentY, this.gridConfig);
this.dragState.element.style.top = `${snappedY}px`;
this.dragState.ghostElement?.remove();
const columnKey = this.dragState.columnElement.dataset.columnKey || "";
const date = this.dragState.columnElement.dataset.date || "";
const swpEvent = SwpEvent.fromElement(this.dragState.element, columnKey, date, this.gridConfig);
const payload = {
swpEvent,
sourceColumnKey: this.dragState.sourceColumnKey,
target: this.inHeader ? "header" : "grid"
};
this.eventBus.emit(CoreEvents.EVENT_DRAG_END, payload);
}
initializeDrag(element, mouseOffset, e) {
const eventId = element.dataset.eventId || "";
const isHeaderItem = element.tagName.toLowerCase() === "swp-header-item";
const columnElement = element.closest("swp-day-column");
if (!isHeaderItem && !columnElement)
return;
if (isHeaderItem) {
this.initializeHeaderItemDrag(element, mouseOffset, eventId);
} else {
this.initializeGridEventDrag(element, mouseOffset, e, columnElement, eventId);
}
}
/**
* Initialize drag for a header item (allDay event)
*/
initializeHeaderItemDrag(element, mouseOffset, eventId) {
element.classList.add("dragging");
this.dragState = {
eventId,
element,
ghostElement: null,
// No ghost for header items
startY: 0,
mouseOffset,
columnElement: null,
currentColumn: null,
targetY: 0,
currentY: 0,
animationId: 0,
sourceColumnKey: "",
// Will be set from header item data
dragSource: "header"
};
this.inHeader = true;
}
/**
* Initialize drag for a grid event
*/
initializeGridEventDrag(element, mouseOffset, e, columnElement, eventId) {
const elementRect = element.getBoundingClientRect();
const columnRect = columnElement.getBoundingClientRect();
const startY = elementRect.top - columnRect.top;
const group = element.closest("swp-event-group");
if (group) {
const eventsLayer = columnElement.querySelector("swp-events-layer");
if (eventsLayer) {
eventsLayer.appendChild(element);
}
}
element.style.position = "absolute";
element.style.top = `${startY}px`;
element.style.left = "2px";
element.style.right = "2px";
element.style.marginLeft = "0";
const ghostElement = element.cloneNode(true);
ghostElement.classList.add("drag-ghost");
ghostElement.style.opacity = "0.3";
ghostElement.style.pointerEvents = "none";
element.parentNode?.insertBefore(ghostElement, element);
element.classList.add("dragging");
const targetY = e.clientY - columnRect.top - mouseOffset.y;
this.dragState = {
eventId,
element,
ghostElement,
startY,
mouseOffset,
columnElement,
currentColumn: columnElement,
targetY: Math.max(0, targetY),
currentY: startY,
animationId: 0,
sourceColumnKey: columnElement.dataset.columnKey || "",
dragSource: "grid"
};
const payload = {
eventId,
element,
ghostElement,
startY,
mouseOffset,
columnElement
};
this.eventBus.emit(CoreEvents.EVENT_DRAG_START, payload);
this.animateDrag();
}
updateDragTarget(e) {
if (!this.dragState)
return;
this.checkHeaderZone(e);
if (this.inHeader)
return;
const columnAtPoint = this.getColumnAtPoint(e.clientX);
if (this.dragState.dragSource === "header" && columnAtPoint && !this.dragState.currentColumn) {
this.dragState.currentColumn = columnAtPoint;
this.dragState.columnElement = columnAtPoint;
}
if (columnAtPoint && columnAtPoint !== this.dragState.currentColumn && this.dragState.currentColumn) {
const payload = {
eventId: this.dragState.eventId,
element: this.dragState.element,
previousColumn: this.dragState.currentColumn,
newColumn: columnAtPoint,
currentY: this.dragState.currentY
};
this.eventBus.emit(CoreEvents.EVENT_DRAG_COLUMN_CHANGE, payload);
this.dragState.currentColumn = columnAtPoint;
this.dragState.columnElement = columnAtPoint;
}
if (!this.dragState.columnElement)
return;
const columnRect = this.dragState.columnElement.getBoundingClientRect();
const targetY = e.clientY - columnRect.top - this.dragState.mouseOffset.y;
this.dragState.targetY = Math.max(0, targetY);
if (!this.dragState.animationId) {
this.animateDrag();
}
}
/**
* Check if pointer is in header zone and emit appropriate events
*/
checkHeaderZone(e) {
if (!this.dragState)
return;
const headerViewport = document.querySelector("swp-header-viewport");
if (!headerViewport)
return;
const rect = headerViewport.getBoundingClientRect();
const isInHeader = e.clientY < rect.bottom;
if (isInHeader && !this.inHeader) {
this.inHeader = true;
if (this.dragState.dragSource === "grid" && this.dragState.columnElement) {
const payload = {
eventId: this.dragState.eventId,
element: this.dragState.element,
sourceColumnIndex: this.getColumnIndex(this.dragState.columnElement),
sourceColumnKey: this.dragState.columnElement.dataset.columnKey || "",
title: this.dragState.element.querySelector("swp-event-title")?.textContent || "",
colorClass: [...this.dragState.element.classList].find((c) => c.startsWith("is-")),
itemType: "event",
duration: 1
};
this.eventBus.emit(CoreEvents.EVENT_DRAG_ENTER_HEADER, payload);
}
} else if (!isInHeader && this.inHeader) {
this.inHeader = false;
const targetColumn = this.getColumnAtPoint(e.clientX);
if (this.dragState.dragSource === "header") {
const payload = {
eventId: this.dragState.eventId,
source: "header",
element: this.dragState.element,
targetColumn: targetColumn || void 0,
start: this.dragState.element.dataset.start ? new Date(this.dragState.element.dataset.start) : void 0,
end: this.dragState.element.dataset.end ? new Date(this.dragState.element.dataset.end) : void 0,
title: this.dragState.element.textContent || "",
colorClass: [...this.dragState.element.classList].find((c) => c.startsWith("is-"))
};
this.eventBus.emit(CoreEvents.EVENT_DRAG_LEAVE_HEADER, payload);
if (targetColumn) {
const newElement = targetColumn.querySelector(`swp-event[data-event-id="${this.dragState.eventId}"]`);
if (newElement) {
this.dragState.element = newElement;
this.dragState.columnElement = targetColumn;
this.dragState.currentColumn = targetColumn;
this.animateDrag();
}
}
} else {
const payload = {
eventId: this.dragState.eventId,
source: "grid"
};
this.eventBus.emit(CoreEvents.EVENT_DRAG_LEAVE_HEADER, payload);
}
} else if (isInHeader) {
const column = this.getColumnAtX(e.clientX);
if (column) {
const payload = {
eventId: this.dragState.eventId,
columnIndex: this.getColumnIndex(column),
columnKey: column.dataset.columnKey || ""
};
this.eventBus.emit(CoreEvents.EVENT_DRAG_MOVE_HEADER, payload);
}
}
}
/**
* Get column index (0-based) for a column element
*/
getColumnIndex(column) {
if (!this.container || !column)
return 0;
const columns = Array.from(this.container.querySelectorAll("swp-day-column"));
return columns.indexOf(column);
}
/**
* Get column at X coordinate (alias for getColumnAtPoint)
*/
getColumnAtX(clientX) {
return this.getColumnAtPoint(clientX);
}
/**
* Find column element at given X coordinate
*/
getColumnAtPoint(clientX) {
if (!this.container)
return null;
const columns = this.container.querySelectorAll("swp-day-column");
for (const col of columns) {
const rect = col.getBoundingClientRect();
if (clientX >= rect.left && clientX <= rect.right) {
return col;
}
}
return null;
}
/**
* Cancel drag and animate back to start position
*/
cancelDrag() {
if (!this.dragState)
return;
cancelAnimationFrame(this.dragState.animationId);
const { element, ghostElement, startY, eventId } = this.dragState;
element.style.transition = "top 200ms ease-out";
element.style.top = `${startY}px`;
setTimeout(() => {
ghostElement?.remove();
element.style.transition = "";
element.classList.remove("dragging");
}, 200);
const payload = {
eventId,
element,
startY
};
this.eventBus.emit(CoreEvents.EVENT_DRAG_CANCEL, payload);
this.dragState = null;
this.inHeader = false;
}
};
__name(_DragDropManager, "DragDropManager");
var DragDropManager = _DragDropManager;
// src/v2/managers/EdgeScrollManager.ts
var _EdgeScrollManager = class _EdgeScrollManager {
constructor(eventBus) {
this.eventBus = eventBus;
this.scrollableContent = null;
this.timeGrid = null;
this.draggedElement = null;
this.scrollRAF = null;
this.mouseY = 0;
this.isDragging = false;
this.isScrolling = false;
this.lastTs = 0;
this.rect = null;
this.initialScrollTop = 0;
this.OUTER_ZONE = 100;
this.INNER_ZONE = 50;
this.SLOW_SPEED = 140;
this.FAST_SPEED = 640;
this.trackMouse = (e) => {
if (this.isDragging) {
this.mouseY = e.clientY;
}
};
this.scrollTick = (ts) => {
if (!this.isDragging || !this.scrollableContent)
return;
const dt = this.lastTs ? (ts - this.lastTs) / 1e3 : 0;
this.lastTs = ts;
this.rect ?? (this.rect = this.scrollableContent.getBoundingClientRect());
const velocity = this.calculateVelocity();
if (velocity !== 0 && !this.isAtBoundary(velocity)) {
const scrollDelta = velocity * dt;
this.scrollableContent.scrollTop += scrollDelta;
this.rect = null;
this.eventBus.emit(CoreEvents.EDGE_SCROLL_TICK, { scrollDelta });
this.setScrollingState(true);
} else {
this.setScrollingState(false);
}
this.scrollRAF = requestAnimationFrame(this.scrollTick);
};
this.subscribeToEvents();
document.addEventListener("pointermove", this.trackMouse);
}
init(scrollableContent) {
this.scrollableContent = scrollableContent;
this.timeGrid = scrollableContent.querySelector("swp-time-grid");
this.scrollableContent.style.scrollBehavior = "auto";
}
subscribeToEvents() {
this.eventBus.on(CoreEvents.EVENT_DRAG_START, (event) => {
const payload = event.detail;
this.draggedElement = payload.element;
this.startDrag();
});
this.eventBus.on(CoreEvents.EVENT_DRAG_END, () => this.stopDrag());
this.eventBus.on(CoreEvents.EVENT_DRAG_CANCEL, () => this.stopDrag());
}
startDrag() {
this.isDragging = true;
this.isScrolling = false;
this.lastTs = 0;
this.initialScrollTop = this.scrollableContent?.scrollTop ?? 0;
if (this.scrollRAF === null) {
this.scrollRAF = requestAnimationFrame(this.scrollTick);
}
}
stopDrag() {
this.isDragging = false;
this.setScrollingState(false);
if (this.scrollRAF !== null) {
cancelAnimationFrame(this.scrollRAF);
this.scrollRAF = null;
}
this.rect = null;
this.lastTs = 0;
this.initialScrollTop = 0;
}
calculateVelocity() {
if (!this.rect)
return 0;
const distTop = this.mouseY - this.rect.top;
const distBot = this.rect.bottom - this.mouseY;
if (distTop < this.INNER_ZONE)
return -this.FAST_SPEED;
if (distTop < this.OUTER_ZONE)
return -this.SLOW_SPEED;
if (distBot < this.INNER_ZONE)
return this.FAST_SPEED;
if (distBot < this.OUTER_ZONE)
return this.SLOW_SPEED;
return 0;
}
isAtBoundary(velocity) {
if (!this.scrollableContent || !this.timeGrid || !this.draggedElement)
return false;
const atTop = this.scrollableContent.scrollTop <= 0 && velocity < 0;
const atBottom = velocity > 0 && this.draggedElement.getBoundingClientRect().bottom >= this.timeGrid.getBoundingClientRect().bottom;
return atTop || atBottom;
}
setScrollingState(scrolling) {
if (this.isScrolling === scrolling)
return;
this.isScrolling = scrolling;
if (scrolling) {
this.eventBus.emit(CoreEvents.EDGE_SCROLL_STARTED, {});
} else {
this.initialScrollTop = this.scrollableContent?.scrollTop ?? 0;
this.eventBus.emit(CoreEvents.EDGE_SCROLL_STOPPED, {});
}
}
};
__name(_EdgeScrollManager, "EdgeScrollManager");
var EdgeScrollManager = _EdgeScrollManager;
// src/v2/managers/ResizeManager.ts
var _ResizeManager = class _ResizeManager {
constructor(eventBus, gridConfig, dateService) {
this.eventBus = eventBus;
this.gridConfig = gridConfig;
this.dateService = dateService;
this.container = null;
this.resizeState = null;
this.Z_INDEX_RESIZING = "1000";
this.ANIMATION_SPEED = 0.35;
this.MIN_HEIGHT_MINUTES = 15;
this.handleMouseOver = (e) => {
const target = e.target;
const eventElement = target.closest("swp-event");
if (!eventElement || this.resizeState)
return;
if (!eventElement.querySelector(":scope > swp-resize-handle")) {
const handle = this.createResizeHandle();
eventElement.appendChild(handle);
}
};
this.handlePointerDown = (e) => {
const handle = e.target.closest("swp-resize-handle");
if (!handle)
return;
const element = handle.parentElement;
if (!element)
return;
const eventId = element.dataset.eventId || "";
const startHeight = element.offsetHeight;
const startDurationMinutes = pixelsToMinutes(startHeight, this.gridConfig);
const container2 = element.closest("swp-event-group") ?? element;
const prevZIndex = container2.style.zIndex;
this.resizeState = {
eventId,
element,
handleElement: handle,
startY: e.clientY,
startHeight,
startDurationMinutes,
pointerId: e.pointerId,
prevZIndex,
// Animation state
currentHeight: startHeight,
targetHeight: startHeight,
animationId: null
};
container2.style.zIndex = this.Z_INDEX_RESIZING;
try {
handle.setPointerCapture(e.pointerId);
} catch (err) {
console.warn("Pointer capture failed:", err);
}
document.documentElement.classList.add("swp--resizing");
this.eventBus.emit(CoreEvents.EVENT_RESIZE_START, {
eventId,
element,
startHeight
});
e.preventDefault();
};
this.handlePointerMove = (e) => {
if (!this.resizeState)
return;
const deltaY = e.clientY - this.resizeState.startY;
const minHeight = this.MIN_HEIGHT_MINUTES / 60 * this.gridConfig.hourHeight;
const newHeight = Math.max(minHeight, this.resizeState.startHeight + deltaY);
this.resizeState.targetHeight = newHeight;
if (this.resizeState.animationId === null) {
this.animateHeight();
}
};
this.animateHeight = () => {
if (!this.resizeState)
return;
const diff2 = this.resizeState.targetHeight - this.resizeState.currentHeight;
if (Math.abs(diff2) < 0.5) {
this.resizeState.animationId = null;
return;
}
this.resizeState.currentHeight += diff2 * this.ANIMATION_SPEED;
this.resizeState.element.style.height = `${this.resizeState.currentHeight}px`;
this.updateTimestampDisplay();
this.resizeState.animationId = requestAnimationFrame(this.animateHeight);
};
this.handlePointerUp = (e) => {
if (!this.resizeState)
return;
if (this.resizeState.animationId !== null) {
cancelAnimationFrame(this.resizeState.animationId);
}
try {
this.resizeState.handleElement.releasePointerCapture(e.pointerId);
} catch (err) {
console.warn("Pointer release failed:", err);
}
this.snapToGridFinal();
this.updateTimestampDisplay();
const container2 = this.resizeState.element.closest("swp-event-group") ?? this.resizeState.element;
container2.style.zIndex = this.resizeState.prevZIndex;
document.documentElement.classList.remove("swp--resizing");
const column = this.resizeState.element.closest("swp-day-column");
const columnKey = column?.dataset.columnKey || "";
const date = column?.dataset.date || "";
const swpEvent = SwpEvent.fromElement(this.resizeState.element, columnKey, date, this.gridConfig);
this.eventBus.emit(CoreEvents.EVENT_RESIZE_END, {
swpEvent
});
this.resizeState = null;
};
}
/**
* Initialize resize functionality on container
*/
init(container2) {
this.container = container2;
container2.addEventListener("mouseover", this.handleMouseOver, true);
document.addEventListener("pointerdown", this.handlePointerDown, true);
document.addEventListener("pointermove", this.handlePointerMove, true);
document.addEventListener("pointerup", this.handlePointerUp, true);
}
/**
* Create resize handle element
*/
createResizeHandle() {
const handle = document.createElement("swp-resize-handle");
handle.setAttribute("aria-label", "Resize event");
handle.setAttribute("role", "separator");
return handle;
}
/**
* Update timestamp display with snapped end time
*/
updateTimestampDisplay() {
if (!this.resizeState)
return;
const timeEl = this.resizeState.element.querySelector("swp-event-time");
if (!timeEl)
return;
const top = parseFloat(this.resizeState.element.style.top) || 0;
const startMinutesFromGrid = pixelsToMinutes(top, this.gridConfig);
const startMinutes = this.gridConfig.dayStartHour * 60 + startMinutesFromGrid;
const snappedHeight = snapToGrid(this.resizeState.currentHeight, this.gridConfig);
const durationMinutes = pixelsToMinutes(snappedHeight, this.gridConfig);
const endMinutes = startMinutes + durationMinutes;
const start = this.minutesToDate(startMinutes);
const end = this.minutesToDate(endMinutes);
timeEl.textContent = this.dateService.formatTimeRange(start, end);
}
/**
* Convert minutes since midnight to Date
*/
minutesToDate(minutes) {
const date = /* @__PURE__ */ new Date();
date.setHours(Math.floor(minutes / 60) % 24, minutes % 60, 0, 0);
return date;
}
/**
* Snap final height to grid interval
*/
snapToGridFinal() {
if (!this.resizeState)
return;
const currentHeight = this.resizeState.element.offsetHeight;
const snappedHeight = snapToGrid(currentHeight, this.gridConfig);
const minHeight = minutesToPixels(this.MIN_HEIGHT_MINUTES, this.gridConfig);
const finalHeight = Math.max(minHeight, snappedHeight);
this.resizeState.element.style.height = `${finalHeight}px`;
this.resizeState.currentHeight = finalHeight;
}
};
__name(_ResizeManager, "ResizeManager");
var ResizeManager = _ResizeManager;
// src/v2/managers/EventPersistenceManager.ts
var _EventPersistenceManager = class _EventPersistenceManager {
constructor(eventService, eventBus, dateService) {
this.eventService = eventService;
this.eventBus = eventBus;
this.dateService = dateService;
this.handleDragEnd = async (e) => {
const payload = e.detail;
const { swpEvent } = payload;
const event = await this.eventService.get(swpEvent.eventId);
if (!event) {
console.warn(`EventPersistenceManager: Event ${swpEvent.eventId} not found`);
return;
}
const { resource } = this.dateService.parseColumnKey(swpEvent.columnKey);
const updatedEvent = {
...event,
start: swpEvent.start,
end: swpEvent.end,
resourceId: resource ?? event.resourceId,
allDay: payload.target === "header",
syncStatus: "pending"
};
await this.eventService.save(updatedEvent);
const updatePayload = {
eventId: updatedEvent.id,
sourceColumnKey: payload.sourceColumnKey,
targetColumnKey: swpEvent.columnKey
};
this.eventBus.emit(CoreEvents.EVENT_UPDATED, updatePayload);
};
this.handleResizeEnd = async (e) => {
const payload = e.detail;
const { swpEvent } = payload;
const event = await this.eventService.get(swpEvent.eventId);
if (!event) {
console.warn(`EventPersistenceManager: Event ${swpEvent.eventId} not found`);
return;
}
const updatedEvent = {
...event,
end: swpEvent.end,
syncStatus: "pending"
};
await this.eventService.save(updatedEvent);
const updatePayload = {
eventId: updatedEvent.id,
sourceColumnKey: swpEvent.columnKey,
targetColumnKey: swpEvent.columnKey
};
this.eventBus.emit(CoreEvents.EVENT_UPDATED, updatePayload);
};
this.setupListeners();
}
setupListeners() {
this.eventBus.on(CoreEvents.EVENT_DRAG_END, this.handleDragEnd);
this.eventBus.on(CoreEvents.EVENT_RESIZE_END, this.handleResizeEnd);
}
};
__name(_EventPersistenceManager, "EventPersistenceManager");
var EventPersistenceManager = _EventPersistenceManager;
// src/v2/V2CompositionRoot.ts
var defaultTimeFormatConfig = {
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
use24HourFormat: true,
locale: "da-DK",
dateFormat: "locale",
showSeconds: false
};
var defaultGridConfig = {
hourHeight: 64,
dayStartHour: 6,
dayEndHour: 18,
snapInterval: 15,
gridStartThresholdMinutes: 30
};
function createV2Container() {
const container2 = new Container();
const builder = container2.builder();
builder.registerInstance(defaultTimeFormatConfig).as("ITimeFormatConfig");
builder.registerInstance(defaultGridConfig).as("IGridConfig");
builder.registerType(EventBus).as("EventBus");
builder.registerType(EventBus).as("IEventBus");
builder.registerType(DateService).as("DateService").autoWire({
mapResolvers: [
(c) => c.resolveType("ITimeFormatConfig"),
void 0
]
});
builder.registerType(IndexedDBContext).as("IndexedDBContext").autoWire({
mapResolvers: [
(c) => c.resolveTypeAll("IStore")
]
});
builder.registerType(EventStore).as("IStore");
builder.registerType(ResourceStore).as("IStore");
builder.registerType(BookingStore).as("IStore");
builder.registerType(CustomerStore).as("IStore");
builder.registerType(TeamStore).as("IStore");
builder.registerType(DepartmentStore).as("IStore");
builder.registerType(ScheduleOverrideStore).as("IStore");
builder.registerType(AuditStore).as("IStore");
builder.registerType(SettingsStore).as("IStore");
builder.registerType(ViewConfigStore).as("IStore");
builder.registerType(EventService).as("IEntityService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(EventService).as("IEntityService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(EventService).as("EventService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(ResourceService).as("IEntityService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(ResourceService).as("IEntityService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(ResourceService).as("ResourceService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(BookingService).as("IEntityService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(BookingService).as("IEntityService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(BookingService).as("BookingService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(CustomerService).as("IEntityService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(CustomerService).as("IEntityService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(CustomerService).as("CustomerService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(TeamService).as("IEntityService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(TeamService).as("IEntityService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(TeamService).as("TeamService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(DepartmentService).as("IEntityService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(DepartmentService).as("IEntityService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(DepartmentService).as("DepartmentService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(SettingsService).as("IEntityService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(SettingsService).as("IEntityService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(SettingsService).as("SettingsService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(ViewConfigService).as("IEntityService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(ViewConfigService).as("IEntityService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(ViewConfigService).as("ViewConfigService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(MockEventRepository).as("IApiRepository");
builder.registerType(MockEventRepository).as("IApiRepository");
builder.registerType(MockResourceRepository).as("IApiRepository");
builder.registerType(MockResourceRepository).as("IApiRepository");
builder.registerType(MockBookingRepository).as("IApiRepository");
builder.registerType(MockBookingRepository).as("IApiRepository");
builder.registerType(MockCustomerRepository).as("IApiRepository");
builder.registerType(MockCustomerRepository).as("IApiRepository");
builder.registerType(MockAuditRepository).as("IApiRepository");
builder.registerType(MockAuditRepository).as("IApiRepository");
builder.registerType(MockTeamRepository).as("IApiRepository");
builder.registerType(MockTeamRepository).as("IApiRepository");
builder.registerType(MockDepartmentRepository).as("IApiRepository");
builder.registerType(MockDepartmentRepository).as("IApiRepository");
builder.registerType(MockSettingsRepository).as("IApiRepository");
builder.registerType(MockSettingsRepository).as("IApiRepository");
builder.registerType(MockViewConfigRepository).as("IApiRepository");
builder.registerType(MockViewConfigRepository).as("IApiRepository");
builder.registerType(AuditService).as("AuditService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(DataSeeder).as("DataSeeder").autoWire({
mapResolvers: [
(c) => c.resolveTypeAll("IEntityService"),
(c) => c.resolveTypeAll("IApiRepository")
]
});
builder.registerType(ScheduleOverrideService).as("ScheduleOverrideService").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext")
]
});
builder.registerType(ResourceScheduleService).as("ResourceScheduleService").autoWire({
mapResolvers: [
(c) => c.resolveType("ResourceService"),
(c) => c.resolveType("ScheduleOverrideService"),
(c) => c.resolveType("DateService")
]
});
builder.registerType(EventRenderer).as("EventRenderer").autoWire({
mapResolvers: [
(c) => c.resolveType("EventService"),
(c) => c.resolveType("DateService"),
(c) => c.resolveType("IGridConfig"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(ScheduleRenderer).as("ScheduleRenderer").autoWire({
mapResolvers: [
(c) => c.resolveType("ResourceScheduleService"),
(c) => c.resolveType("DateService"),
(c) => c.resolveType("IGridConfig")
]
});
builder.registerType(HeaderDrawerRenderer).as("HeaderDrawerRenderer").autoWire({
mapResolvers: [
(c) => c.resolveType("IEventBus"),
(c) => c.resolveType("IGridConfig"),
(c) => c.resolveType("HeaderDrawerManager"),
(c) => c.resolveType("EventService"),
(c) => c.resolveType("DateService")
]
});
builder.registerType(DateRenderer).as("IRenderer").autoWire({
mapResolvers: [
(c) => c.resolveType("DateService")
]
});
builder.registerType(ResourceRenderer).as("IRenderer").autoWire({
mapResolvers: [
(c) => c.resolveType("ResourceService")
]
});
builder.registerType(TeamRenderer).as("IRenderer").autoWire({
mapResolvers: [
(c) => c.resolveType("TeamService")
]
});
builder.registerType(DepartmentRenderer).as("IRenderer").autoWire({
mapResolvers: [
(c) => c.resolveType("DepartmentService")
]
});
builder.registerType(MockTeamStore).as("IGroupingStore");
builder.registerType(MockResourceStore).as("IGroupingStore");
builder.registerType(CalendarOrchestrator).as("CalendarOrchestrator").autoWire({
mapResolvers: [
(c) => c.resolveTypeAll("IRenderer"),
(c) => c.resolveType("EventRenderer"),
(c) => c.resolveType("ScheduleRenderer"),
(c) => c.resolveType("HeaderDrawerRenderer"),
(c) => c.resolveType("DateService"),
(c) => c.resolveTypeAll("IEntityService")
]
});
builder.registerType(TimeAxisRenderer).as("TimeAxisRenderer");
builder.registerType(ScrollManager).as("ScrollManager");
builder.registerType(HeaderDrawerManager).as("HeaderDrawerManager");
builder.registerType(DragDropManager).as("DragDropManager").autoWire({
mapResolvers: [
(c) => c.resolveType("IEventBus"),
(c) => c.resolveType("IGridConfig")
]
});
builder.registerType(EdgeScrollManager).as("EdgeScrollManager").autoWire({
mapResolvers: [
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(ResizeManager).as("ResizeManager").autoWire({
mapResolvers: [
(c) => c.resolveType("IEventBus"),
(c) => c.resolveType("IGridConfig"),
(c) => c.resolveType("DateService")
]
});
builder.registerType(EventPersistenceManager).as("EventPersistenceManager").autoWire({
mapResolvers: [
(c) => c.resolveType("EventService"),
(c) => c.resolveType("IEventBus"),
(c) => c.resolveType("DateService")
]
});
builder.registerType(CalendarApp).as("CalendarApp").autoWire({
mapResolvers: [
(c) => c.resolveType("CalendarOrchestrator"),
(c) => c.resolveType("TimeAxisRenderer"),
(c) => c.resolveType("DateService"),
(c) => c.resolveType("ScrollManager"),
(c) => c.resolveType("HeaderDrawerManager"),
(c) => c.resolveType("DragDropManager"),
(c) => c.resolveType("EdgeScrollManager"),
(c) => c.resolveType("ResizeManager"),
(c) => c.resolveType("HeaderDrawerRenderer"),
(c) => c.resolveType("EventPersistenceManager"),
(c) => c.resolveType("SettingsService"),
(c) => c.resolveType("ViewConfigService"),
(c) => c.resolveType("IEventBus")
]
});
builder.registerType(DemoApp).as("DemoApp").autoWire({
mapResolvers: [
(c) => c.resolveType("IndexedDBContext"),
(c) => c.resolveType("DataSeeder"),
(c) => c.resolveType("AuditService"),
(c) => c.resolveType("CalendarApp"),
(c) => c.resolveType("DateService"),
(c) => c.resolveType("ResourceService"),
(c) => c.resolveType("IEventBus")
]
});
return builder.build();
}
__name(createV2Container, "createV2Container");
// src/v2/demo/index.ts
var container = createV2Container();
container.resolveType("DemoApp").init().catch(console.error);
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vbm9kZV9tb2R1bGVzL2RheWpzL2RheWpzLm1pbi5qcyIsICIuLi8uLi9ub2RlX21vZHVsZXMvZGF5anMvcGx1Z2luL3V0Yy5qcyIsICIuLi8uLi9ub2RlX21vZHVsZXMvZGF5anMvcGx1Z2luL3RpbWV6b25lLmpzIiwgIi4uLy4uL25vZGVfbW9kdWxlcy9kYXlqcy9wbHVnaW4vaXNvV2Vlay5qcyIsICIuLi8uLi9ub2RlX21vZHVsZXMvQG5vdmFkaS9jb3JlL2Rpc3QvdG9rZW4uanMiLCAiLi4vLi4vbm9kZV9tb2R1bGVzL0Bub3ZhZGkvY29yZS9kaXN0L2Vycm9ycy5qcyIsICIuLi8uLi9ub2RlX21vZHVsZXMvQG5vdmFkaS9jb3JlL2Rpc3QvYXV0b3dpcmUuanMiLCAiLi4vLi4vbm9kZV9tb2R1bGVzL0Bub3ZhZGkvY29yZS9kaXN0L2J1aWxkZXIuanMiLCAiLi4vLi4vbm9kZV9tb2R1bGVzL0Bub3ZhZGkvY29yZS9kaXN0L2NvbnRhaW5lci5qcyIsICIuLi8uLi9zcmMvdjIvZmVhdHVyZXMvZGF0ZS9EYXRlUmVuZGVyZXIudHMiLCAiLi4vLi4vc3JjL3YyL2NvcmUvRGF0ZVNlcnZpY2UudHMiLCAiLi4vLi4vc3JjL3YyL2NvcmUvQmFzZUdyb3VwaW5nUmVuZGVyZXIudHMiLCAiLi4vLi4vc3JjL3YyL2ZlYXR1cmVzL3Jlc291cmNlL1Jlc291cmNlUmVuZGVyZXIudHMiLCAiLi4vLi4vc3JjL3YyL2ZlYXR1cmVzL3RlYW0vVGVhbVJlbmRlcmVyLnRzIiwgIi4uLy4uL3NyYy92Mi9mZWF0dXJlcy9kZXBhcnRtZW50L0RlcGFydG1lbnRSZW5kZXJlci50cyIsICIuLi8uLi9zcmMvdjIvY29yZS9SZW5kZXJCdWlsZGVyLnRzIiwgIi4uLy4uL3NyYy92Mi9jb3JlL0ZpbHRlclRlbXBsYXRlLnRzIiwgIi4uLy4uL3NyYy92Mi9jb3JlL0NhbGVuZGFyT3JjaGVzdHJhdG9yLnRzIiwgIi4uLy4uL3NyYy92Mi9jb3JlL05hdmlnYXRpb25BbmltYXRvci50cyIsICIuLi8uLi9zcmMvdjIvY29yZS9DYWxlbmRhckV2ZW50cy50cyIsICIuLi8uLi9zcmMvdjIvY29yZS9DYWxlbmRhckFwcC50cyIsICIuLi8uLi9zcmMvdjIvZmVhdHVyZXMvdGltZWF4aXMvVGltZUF4aXNSZW5kZXJlci50cyIsICIuLi8uLi9zcmMvdjIvY29yZS9TY3JvbGxNYW5hZ2VyLnRzIiwgIi4uLy4uL3NyYy92Mi9jb3JlL0hlYWRlckRyYXdlck1hbmFnZXIudHMiLCAiLi4vLi4vc3JjL3YyL2RlbW8vTW9ja1N0b3Jlcy50cyIsICIuLi8uLi9zcmMvdjIvZGVtby9EZW1vQXBwLnRzIiwgIi4uLy4uL3NyYy92Mi9jb3JlL0V2ZW50QnVzLnRzIiwgIi4uLy4uL3NyYy92Mi9zdG9yYWdlL0luZGV4ZWREQkNvbnRleHQudHMiLCAiLi4vLi4vc3JjL3YyL3N0b3JhZ2UvZXZlbnRzL0V2ZW50U3RvcmUudHMiLCAiLi4vLi4vc3JjL3YyL3N0b3JhZ2UvZXZlbnRzL0V2ZW50U2VyaWFsaXphdGlvbi50cyIsICIuLi8uLi9zcmMvdjIvc3RvcmFnZS9TeW5jUGx1Z2luLnRzIiwgIi4uLy4uL3NyYy92Mi9jb25zdGFudHMvQ29yZUV2ZW50cy50cyIsICIuLi8uLi9ub2RlX21vZHVsZXMvanNvbi1kaWZmLXRzL3NyYy9oZWxwZXJzLnRzIiwgIi4uLy4uL25vZGVfbW9kdWxlcy9qc29uLWRpZmYtdHMvc3JjL2pzb25EaWZmLnRzIiwgIi4uLy4uL25vZGVfbW9kdWxlcy9qc29uLWRpZmYtdHMvc3JjL2pzb25Db21wYXJlLnRzIiwgIi4uLy4uL3NyYy92Mi9zdG9yYWdlL0Jhc2VFbnRpdHlTZXJ2aWNlLnRzIiwgIi4uLy4uL3NyYy92Mi9zdG9yYWdlL2V2ZW50cy9FdmVudFNlcnZpY2UudHMiLCAiLi4vLi4vc3JjL3YyL3N0b3JhZ2UvcmVzb3VyY2VzL1Jlc291cmNlU3RvcmUudHMiLCAiLi4vLi4vc3JjL3YyL3N0b3JhZ2UvcmVzb3VyY2VzL1Jlc291cmNlU2VydmljZS50cyIsICIuLi8uLi9zcmMvdjIvc3RvcmFnZS9ib29raW5ncy9Cb29raW5nU3RvcmUudHMiLCAiLi4vLi4vc3JjL3YyL3N0b3JhZ2UvYm9va2luZ3MvQm9va2luZ1NlcnZpY2UudHMiLCAiLi4vLi4vc3JjL3YyL3N0b3JhZ2UvY3VzdG9tZXJzL0N1c3RvbWVyU3RvcmUudHMiLCAiLi4vLi4vc3JjL3YyL3N0b3JhZ2UvY3VzdG9tZXJzL0N1c3RvbWVyU2VydmljZS50cyIsICIuLi8uLi9zcmMvdjIvc3RvcmFnZS90ZWFtcy9UZWFtU3RvcmUudHMiLCAiLi4vLi4vc3JjL3YyL3N0b3JhZ2UvdGVhbXMvVGVhbVNlcnZpY2UudHMiLCAiLi4vLi4vc3JjL3YyL3N0b3JhZ2UvZGVwYXJ0bWVudHMvRGVwYXJ0bWVudFN0b3JlLnRzIiwgIi4uLy4uL3NyYy92Mi9zdG9yYWdlL2RlcGFydG1lbnRzL0RlcGFydG1lbnRTZXJ2aWNlLnRzIiwgIi4uLy4uL3NyYy92Mi9zdG9yYWdlL3NldHRpbmdzL1NldHRpbmdzU3RvcmUudHMiLCAiLi4vLi4vc3JjL3YyL3R5cGVzL1NldHRpbmdzVHlwZXMudHMiLCAiLi4vLi4vc3JjL3YyL3N0b3JhZ2Uvc2V0dGluZ3MvU2V0dGluZ3NTZXJ2aWNlLnRzIiwgIi4uLy4uL3NyYy92Mi9zdG9yYWdlL3ZpZXdjb25maWdzL1ZpZXdDb25maWdTdG9yZS50cyIsICIuLi8uLi9zcmMvdjIvc3RvcmFnZS92aWV3Y29uZmlncy9WaWV3Q29uZmlnU2VydmljZS50cyIsICIuLi8uLi9zcmMvdjIvc3RvcmFnZS9hdWRpdC9BdWRpdFN0b3JlLnRzIiwgIi4uLy4uL3NyYy92Mi9zdG9yYWdlL2F1ZGl0L0F1ZGl0U2VydmljZS50cyIsICIuLi8uLi9zcmMvdjIvcmVwb3NpdG9yaWVzL01vY2tFdmVudFJlcG9zaXRvcnkudHMiLCAiLi4vLi4vc3JjL3YyL3JlcG9zaXRvcmllcy9Nb2NrUmVzb3VyY2VSZXBvc2l0b3J5LnRzIiwgIi4uLy4uL3NyYy92Mi9yZXBvc2l0b3JpZXMvTW9ja0Jvb2tpbmdSZXBvc2l0b3J5LnRzIiwgIi4uLy4uL3NyYy92Mi9yZXBvc2l0b3JpZXMvTW9ja0N1c3RvbWVyUmVwb3NpdG9yeS50cyIsICIuLi8uLi9zcmMvdjIvcmVwb3NpdG9yaWVzL01vY2tBdWRpdFJlcG9zaXRvcnkudHMiLCAiLi4vLi4vc3JjL3YyL3JlcG9zaXRvcmllcy9Nb2NrVGVhbVJlcG9zaXRvcnkudHMiLCAiLi4vLi4vc3JjL3YyL3JlcG9zaXRvcmllcy9Nb2NrRGVwYXJ0bWVudFJlcG9zaXRvcnkudHMiLCAiLi4vLi4vc3JjL3YyL3JlcG9zaXRvcmllcy9Nb2NrU2V0dGluZ3NSZXBvc2l0b3J5LnRzIiwgIi4uLy4uL3NyYy92Mi9yZXBvc2l0b3JpZXMvTW9ja1ZpZXdDb25maWdSZXBvc2l0b3J5LnRzIiwgIi4uLy4uL3NyYy92Mi93b3JrZXJzL0RhdGFTZWVkZXIudHMiLCAiLi4vLi4vc3JjL3YyL3V0aWxzL1Bvc2l0aW9uVXRpbHMudHMiLCAiLi4vLi4vc3JjL3YyL2ZlYXR1cmVzL2V2ZW50L0V2ZW50TGF5b3V0RW5naW5lLnRzIiwgIi4uLy4uL3NyYy92Mi9mZWF0dXJlcy9ldmVudC9FdmVudFJlbmRlcmVyLnRzIiwgIi4uLy4uL3NyYy92Mi9mZWF0dXJlcy9zY2hlZHVsZS9TY2hlZHVsZVJlbmRlcmVyLnRzIiwgIi4uLy4uL3NyYy92Mi9mZWF0dXJlcy9oZWFkZXJkcmF3ZXIvSGVhZGVyRHJhd2VyUmVuZGVyZXIudHMiLCAiLi4vLi4vc3JjL3YyL3N0b3JhZ2Uvc2NoZWR1bGVzL1NjaGVkdWxlT3ZlcnJpZGVTdG9yZS50cyIsICIuLi8uLi9zcmMvdjIvc3RvcmFnZS9zY2hlZHVsZXMvU2NoZWR1bGVPdmVycmlkZVNlcnZpY2UudHMiLCAiLi4vLi4vc3JjL3YyL3N0b3JhZ2Uvc2NoZWR1bGVzL1Jlc291cmNlU2NoZWR1bGVTZXJ2aWNlLnRzIiwgIi4uLy4uL3NyYy92Mi90eXBlcy9Td3BFdmVudC50cyIsICIuLi8uLi9zcmMvdjIvbWFuYWdlcnMvRHJhZ0Ryb3BNYW5hZ2VyLnRzIiwgIi4uLy4uL3NyYy92Mi9tYW5hZ2Vycy9FZGdlU2Nyb2xsTWFuYWdlci50cyIsICIuLi8uLi9zcmMvdjIvbWFuYWdlcnMvUmVzaXplTWFuYWdlci50cyIsICIuLi8uLi9zcmMvdjIvbWFuYWdlcnMvRXZlbnRQZXJzaXN0ZW5jZU1hbmFnZXIudHMiLCAiLi4vLi4vc3JjL3YyL1YyQ29tcG9zaXRpb25Sb290LnRzIiwgIi4uLy4uL3NyYy92Mi9kZW1vL2luZGV4LnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIhZnVuY3Rpb24odCxlKXtcIm9iamVjdFwiPT10eXBlb2YgZXhwb3J0cyYmXCJ1bmRlZmluZWRcIiE9dHlwZW9mIG1vZHVsZT9tb2R1bGUuZXhwb3J0cz1lKCk6XCJmdW5jdGlvblwiPT10eXBlb2YgZGVmaW5lJiZkZWZpbmUuYW1kP2RlZmluZShlKToodD1cInVuZGVmaW5lZFwiIT10eXBlb2YgZ2xvYmFsVGhpcz9nbG9iYWxUaGlzOnR8fHNlbGYpLmRheWpzPWUoKX0odGhpcywoZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt2YXIgdD0xZTMsZT02ZTQsbj0zNmU1LHI9XCJtaWxsaXNlY29uZFwiLGk9XCJzZWNvbmRcIixzPVwibWludXRlXCIsdT1cImhvdXJcIixhPVwiZGF5XCIsbz1cIndlZWtcIixjPVwibW9udGhcIixmPVwicXVhcnRlclwiLGg9XCJ5ZWFyXCIsZD1cImRhdGVcIixsPVwiSW52YWxpZCBEYXRlXCIsJD0vXihcXGR7NH0pWy0vXT8oXFxkezEsMn0pP1stL10/KFxcZHswLDJ9KVtUdFxcc10qKFxcZHsxLDJ9KT86PyhcXGR7MSwyfSk/Oj8oXFxkezEsMn0pP1suOl0/KFxcZCspPyQvLHk9L1xcWyhbXlxcXV0rKV18WXsxLDR9fE17MSw0fXxEezEsMn18ZHsxLDR9fEh7MSwyfXxoezEsMn18YXxBfG17MSwyfXxzezEsMn18WnsxLDJ9fFNTUy9nLE09e25hbWU6XCJlblwiLHdlZWtkYXlzOlwiU3VuZGF5X01vbmRheV9UdWVzZGF5X1dlZG5lc2RheV9UaHVyc2RheV9GcmlkYXlfU2F0dXJkYXlcIi5zcGxpdChcIl9cIiksbW9udGhzOlwiSmFudWFyeV9GZWJydWFyeV9NYXJjaF9BcHJpbF9NYXlfSnVuZV9KdWx5X0F1Z3VzdF9TZXB0ZW1iZXJfT2N0b2Jlcl9Ob3ZlbWJlcl9EZWNlbWJlclwiLnNwbGl0KFwiX1wiKSxvcmRpbmFsOmZ1bmN0aW9uKHQpe3ZhciBlPVtcInRoXCIsXCJzdFwiLFwibmRcIixcInJkXCJdLG49dCUxMDA7cmV0dXJuXCJbXCIrdCsoZVsobi0yMCklMTBdfHxlW25dfHxlWzBdKStcIl1cIn19LG09ZnVuY3Rpb24odCxlLG4pe3ZhciByPVN0cmluZyh0KTtyZXR1cm4hcnx8ci5sZW5ndGg+PWU/dDpcIlwiK0FycmF5KGUrMS1yLmxlbmd0aCkuam9pbihuKSt0fSx2PXtzOm0sejpmdW5jdGlvbih0KXt2YXIgZT0tdC51dGNPZmZzZXQoKSxuPU1hdGguYWJzKGUpLHI9TWF0aC5mbG9vcihuLzYwKSxpPW4lNjA7cmV0dXJuKGU8PTA/XCIrXCI6XCItXCIpK20ociwyLFwiMFwiKStcIjpcIittKGksMixcIjBcIil9LG06ZnVuY3Rpb24gdChlLG4pe2lmKGUuZGF0ZSgpPG4uZGF0ZSgpKXJldHVybi10KG4sZSk7dmFyIHI9MTIqKG4ueWVhcigpLWUueWVhcigpKSsobi5tb250aCgpLWUubW9udGgoKSksaT1lLmNsb25lKCkuYWRkKHIsYykscz1uLWk8MCx1PWUuY2xvbmUoKS5hZGQocisocz8tMToxKSxjKTtyZXR1cm4rKC0ocisobi1pKS8ocz9pLXU6dS1pKSl8fDApfSxhOmZ1bmN0aW9uKHQpe3JldHVybiB0PDA/TWF0aC5jZWlsKHQpfHwwOk1hdGguZmxvb3IodCl9LHA6ZnVuY3Rpb24odCl7cmV0dXJue006Yyx5OmgsdzpvLGQ6YSxEOmQsaDp1LG06cyxzOmksbXM6cixROmZ9W3RdfHxTdHJpbmcodHx8XCJcIikudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9zJC8sXCJcIil9LHU6ZnVuY3Rpb24odCl7cmV0dXJuIHZvaWQgMD09PXR9fSxnPVwiZW5cIixEPXt9O0RbZ109TTt2YXIgcD1cIiRpc0RheWpzT2JqZWN0XCIsUz1mdW5jdGlvbih0KXtyZXR1cm4gdCBpbnN0YW5jZW9mIF98fCEoIXR8fCF0W3BdKX0sdz1mdW5jdGlvbiB0KGUsbixyKXt2YXIgaTtpZighZSlyZXR1cm4gZztpZihcInN0cmluZ1wiPT10eXBlb2YgZSl7dmFyIHM9ZS50b0xvd2VyQ2FzZSgpO0Rbc10mJihpPXMpLG4mJihEW3NdPW4saT1zKTt2YXIgdT1lLnNwbGl0KFwiLVwiKTtpZighaSYmdS5sZW5ndGg+MSlyZXR1cm4gdCh1WzBdKX1lbHNle3ZhciBhPWUubmFtZTtEW2FdPWUsaT1hfXJldHVybiFyJiZpJiYoZz1pKSxpfHwhciYmZ30sTz1mdW5jdGlvbih0LGUpe2lmKFModCkpcmV0dXJuIHQuY2xvbmUoKTt2YXIgbj1cIm9iamVjdFwiPT10eXBlb2YgZT9lOnt9O3JldHVybiBuLmRhdGU9dCxuLmFyZ3M9YXJndW1lbnRzLG5ldyBfKG4pfSxiPXY7Yi5sPXcsYi5pPVMsYi53PWZ1bmN0aW9uKHQsZSl7cmV0dXJuIE8odCx7bG9jYWxlOmUuJEwsdXRjOmUuJHUseDplLiR4LCRvZmZzZXQ6ZS4kb2Zmc2V0fSl9O3ZhciBfPWZ1bmN0aW9uKCl7ZnVuY3Rpb24gTSh0KXt0aGlzLiRMPXcodC5sb2NhbGUsbnVsbCwhMCksdGhpcy5wYXJzZSh0KSx0aGlzLiR4PXRoaXMuJHh8fHQueHx8e30sdGhpc1twXT0hMH12YXIgbT1NLnByb3RvdHlwZTtyZXR1cm4gbS5wYXJzZT1mdW5jdGlvbih0KXt0aGlzLiRkPWZ1bmN0aW9uKHQpe3ZhciBlPXQuZGF0ZSxuPXQudXRjO2lmKG51bGw9PT1lKXJldHVybiBuZXcgRGF0ZShOYU4pO2lmKGIudShlKSlyZXR1cm4gbmV3IERhdGU7aWYoZSBpbnN0YW5jZW9mIERhdGUpcmV0dXJuIG5ldyBEYXRlKGUpO2lmKFwic3RyaW5nXCI9PXR5cGVvZiBlJiYhL1okL2kudGVzdChlKSl7dmFyIHI9ZS5tYXRjaCgkKTtpZihyKXt2YXIgaT1yWzJdLTF8fDAscz0ocls3XXx8XCIwXCIpLnN1YnN0cmluZygwLDMpO3JldHVybiBuP25ldyBEYXRlKERhdGUuVVRDKHJbMV0saSxyWzNdfHwxLHJbNF18fDAscls1XXx8MCxyWzZdfHwwLHMpKTpuZXcgRGF0ZShyWzFdLGksclszXXx8MSxyWzRdfHwwLHJbNV18fDAscls2XXx8MCxzKX19cmV0dXJuIG5ldyBEYXRlKGUpfSh0KSx0aGlzLmluaXQoKX0sbS5pbml0PWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy4kZDt0aGlzLiR5PXQuZ2V0RnVsbFllYXIoKSx0aGlzLiRNPXQuZ2V0TW9udGgoKSx0aGlzLiREPXQuZ2V0RGF0ZSgpLHRoaXMuJFc9dC5nZXREYXkoKSx0aGlzLiRIPXQuZ2V0SG91cnMoKSx0aGlzLiRtPXQuZ2V0TWludXRlcygpLHRoaXMuJHM9dC5nZXRTZWNvbmRzKCksdGhpcy4kbXM9dC5nZXRNaWxsaXNlY29uZHMoKX0sbS4kdXRpbHM9ZnVuY3Rpb24oKXtyZXR1cm4gYn0sbS5pc1ZhbGlkPWZ1bmN0aW9uKCl7cmV0dXJuISh0aGlzLiRkLnRvU3RyaW5nKCk9PT1sKX0sbS5pc1NhbWU9ZnVuY3Rpb24odCxlKXt2YXIgbj1PKHQpO3JldHVybiB0aGlzLnN0YXJ0T2YoZSk8PW4mJm48PXRoaXMuZW5kT2YoZSl9LG0uaXNBZnRlcj1mdW5jdGlvbih0LGUpe3JldHVybiBPKHQpPHRoaXMuc3RhcnRPZihlKX0sbS5pc0JlZm9yZT1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmVuZE9mKGUpPE8odCl9LG0uJGc9ZnVuY3Rpb24odCxlLG4pe3JldHVybiBiLnUodCk/dGhpc1tlXTp0aGlzLnNldChuLHQpfSxtLnVuaXg9ZnVuY3Rpb24oKXtyZXR1cm4gTWF0aC5mbG9vcih0aGlzLnZhbHVlT2YoKS8xZTMpfSxtLnZhbHVlT2Y9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy4kZC5nZXRUaW1lKCl9LG0uc3RhcnRPZj1mdW5jdGlvbih0LGUpe3ZhciBuPXRoaXMscj0hIWIudShlKXx8ZSxmPWIucCh0KSxsPWZ1bmN0aW9uKHQsZSl7dmFyIGk9Yi53KG4uJHU/RGF0ZS5VVEMobi4keSxlLHQpOm5ldyBEYXRlKG4uJHksZSx0KSxuKTtyZXR1cm4gcj9pOmkuZW5kT2YoYSl9LCQ9ZnVuY3Rpb24odCxlKXtyZXR1cm4gYi53KG4udG9EYXRlKClbdF0uYXBwbHkobi50b0RhdGUoXCJzXCIpLChyP1swLDAsMCwwXTpbMjMsNTksNTksOTk5XSkuc2xpY2UoZSkpLG4pfSx5PXRoaXMuJFcsTT10aGlzLiRNLG09dGhpcy4kRCx2PVwic2V0XCIrKHRoaXMuJHU/XCJVVENcIjpcIlwiKTtzd2l0Y2goZil7Y2FzZSBoOnJldHVybiByP2woMSwwKTpsKDMxLDExKTtjYXNlIGM6cmV0dXJuIHI/bCgxLE0pOmwoMCxNKzEpO2Nhc2Ugbzp2YXIgZz10aGlzLiRsb2NhbGUoKS53ZWVrU3RhcnR8fDAsRD0oeTxnP3krNzp5KS1nO3JldHVybiBsKHI/bS1EOm0rKDYtRCksTSk7Y2FzZSBhOmNhc2UgZDpyZXR1cm4gJCh2K1wiSG91cnNcIiwwKTtjYXNlIHU6cmV0dXJuICQoditcIk1pbnV0ZXNcIiwxKTtjYXNlIHM6cmV0dXJuICQoditcIlNlY29uZHNcIiwyKTtjYXNlIGk6cmV0dXJuICQoditcIk1pbGxpc2Vjb25kc1wiLDMpO2RlZmF1bHQ6cmV0dXJuIHRoaXMuY2xvbmUoKX19LG0uZW5kT2Y9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuc3RhcnRPZih0LCExKX0sbS4kc2V0PWZ1bmN0aW9uKHQsZSl7dmFyIG4sbz1iLnAodCksZj1cInNldFwiKyh0aGlzLiR1P1wiVVRDXCI6XCJcIiksbD0obj17fSxuW2FdPWYrXCJEYXRlXCIsbltkXT1mK1wiRGF0ZVwiLG5bY109ZitcIk1vbnRoXCIsbltoXT1mK1wiRnVsbFllYXJcIixuW3VdPWYrXCJIb3Vyc1wiLG5bc109ZitcIk1pbnV0ZXNcIixuW2ldPWYrXCJTZWNvbmRzXCIsbltyXT1mK1wiTWlsbGlzZWNvbmRzXCIsbilbb10sJD1vPT09YT90aGlzLiREKyhlLXRoaXMuJFcpOmU7aWYobz09PWN8fG89PT1oKXt2YXIgeT10aGlzLmNsb25lKCkuc2V0KGQsMSk7eS4kZFtsXSgkKSx5LmluaXQoKSx0aGlzLiRkPXkuc2V0KGQsTWF0aC5taW4odGhpcy4kRCx5LmRheXNJbk1vbnRoKCkpKS4kZH1lbHNlIGwmJnRoaXMuJGRbbF0oJCk7cmV0dXJuIHRoaXMuaW5pdCgpLHRoaXN9LG0uc2V0PWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuY2xvbmUoKS4kc2V0KHQsZSl9LG0uZ2V0PWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzW2IucCh0KV0oKX0sbS5hZGQ9ZnVuY3Rpb24ocixmKXt2YXIgZCxsPXRoaXM7cj1OdW1iZXIocik7dmFyICQ9Yi5wKGYpLHk9ZnVuY3Rpb24odCl7dmFyIGU9TyhsKTtyZXR1cm4gYi53KGUuZGF0ZShlLmRhdGUoKStNYXRoLnJvdW5kKHQqcikpLGwpfTtpZigkPT09YylyZXR1cm4gdGhpcy5zZXQoYyx0aGlzLiRNK3IpO2lmKCQ9PT1oKXJldHVybiB0aGlzLnNldChoLHRoaXMuJHkrcik7aWYoJD09PWEpcmV0dXJuIHkoMSk7aWYoJD09PW8pcmV0dXJuIHkoNyk7dmFyIE09KGQ9e30sZFtzXT1lLGRbdV09bixkW2ldPXQsZClbJF18fDEsbT10aGlzLiRkLmdldFRpbWUoKStyKk07cmV0dXJuIGIudyhtLHRoaXMpfSxtLnN1YnRyYWN0PWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuYWRkKC0xKnQsZSl9LG0uZm9ybWF0PWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMsbj10aGlzLiRsb2NhbGUoKTtpZighdGhpcy5pc1ZhbGlkKCkpcmV0dXJuIG4uaW52YWxpZERhdGV8fGw7dmFyIHI9dHx8XCJZWVlZLU1NLUREVEhIOm1tOnNzWlwiLGk9Yi56KHRoaXMpLHM9dGhpcy4kSCx1PXRoaXMuJG0sYT10aGlzLiRNLG89bi53ZWVrZGF5cyxjPW4ubW9udGhzLGY9bi5tZXJpZGllbSxoPWZ1bmN0aW9uKHQsbixpLHMpe3JldHVybiB0JiYodFtuXXx8dChlLHIpKXx8aVtuXS5zbGljZSgwLHMpfSxkPWZ1bmN0aW9uKHQpe3JldHVybiBiLnMocyUxMnx8MTIsdCxcIjBcIil9LCQ9Znx8ZnVuY3Rpb24odCxlLG4pe3ZhciByPXQ8MTI/XCJBTVwiOlwiUE1cIjtyZXR1cm4gbj9yLnRvTG93ZXJDYXNlKCk6cn07cmV0dXJuIHIucmVwbGFjZSh5LChmdW5jdGlvbih0LHIpe3JldHVybiByfHxmdW5jdGlvbih0KXtzd2l0Y2godCl7Y2FzZVwiWVlcIjpyZXR1cm4gU3RyaW5nKGUuJHkpLnNsaWNlKC0yKTtjYXNlXCJZWVlZXCI6cmV0dXJuIGIucyhlLiR5LDQsXCIwXCIpO2Nhc2VcIk1cIjpyZXR1cm4gYSsxO2Nhc2VcIk1NXCI6cmV0dXJuIGIucyhhKzEsMixcIjBcIik7Y2FzZVwiTU1NXCI6cmV0dXJuIGgobi5tb250aHNTaG9ydCxhLGMsMyk7Y2FzZVwiTU1NTVwiOnJldHVybiBoKGMsYSk7Y2FzZVwiRFwiOnJldHVybiBlLiREO2Nhc2VcIkREXCI6cmV0dXJuIGIucyhlLiRELDIsXCIwXCIpO2Nhc2VcImRcIjpyZXR1cm4gU3RyaW5nKGUuJFcpO2Nhc2VcImRkXCI6cmV0dXJuIGgobi53ZWVrZGF5c01pbixlLiRXLG8sMik7Y2FzZVwiZGRkXCI6cmV0dXJuIGgobi53ZWVrZGF5c1Nob3J0LGUuJFcsbywzKTtjYXNlXCJkZGRkXCI6cmV0dXJuIG9bZS4kV107Y2FzZVwiSFwiOnJldHVybiBTdHJpbmcocyk7Y2FzZVwiSEhcIjpyZXR1cm4gYi5zKHMsMixcIjBcIik7Y2FzZVwiaFwiOnJldHVybiBkKDEpO2Nhc2VcImhoXCI6cmV0dXJuIGQoMik7Y2FzZVwiYVwiOnJldHVybiAkKHMsdSwhMCk7Y2FzZVwiQVwiOnJldHVybiAkKHMsdSwhMSk7Y2FzZVwibVwiOnJldHVybiBTdHJpbmcodSk7Y2FzZVwibW1cIjpyZXR1cm4gYi5zKHUsMixcIjBcIik7Y2FzZVwic1wiOnJldHVybiBTdHJpbmcoZS4kcyk7Y2FzZVwic3NcIjpyZXR1cm4gYi5zKGUuJHMsMixcIjBcIik7Y2FzZVwiU1NTXCI6cmV0dXJuIGIucyhlLiRtcywzLFwiMFwiKTtjYXNlXCJaXCI6cmV0dXJuIGl9cmV0dXJuIG51bGx9KHQpfHxpLnJlcGxhY2UoXCI6XCIsXCJcIil9KSl9LG0udXRjT2Zmc2V0PWZ1bmN0aW9uKCl7cmV0dXJuIDE1Ki1NYXRoLnJvdW5kKHRoaXMuJGQuZ2V0VGltZXpvbmVPZmZzZXQoKS8xNSl9LG0uZGlmZj1mdW5jdGlvbihyLGQsbCl7dmFyICQseT10aGlzLE09Yi5wKGQpLG09TyhyKSx2PShtLnV0Y09mZnNldCgpLXRoaXMudXRjT2Zmc2V0KCkpKmUsZz10aGlzLW0sRD1mdW5jdGlvbigpe3JldHVybiBiLm0oeSxtKX07c3dpdGNoKE0pe2Nhc2UgaDokPUQoKS8xMjticmVhaztjYXNlIGM6JD1EKCk7YnJlYWs7Y2FzZSBmOiQ9RCgpLzM7YnJlYWs7Y2FzZSBvOiQ9KGctdikvNjA0OGU1O2JyZWFrO2Nhc2UgYTokPShnLXYpLzg2NGU1O2JyZWFrO2Nhc2UgdTokPWcvbjticmVhaztjYXNlIHM6JD1nL2U7YnJlYWs7Y2FzZSBpOiQ9Zy90O2JyZWFrO2RlZmF1bHQ6JD1nfXJldHVybiBsPyQ6Yi5hKCQpfSxtLmRheXNJbk1vbnRoPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZW5kT2YoYykuJER9LG0uJGxvY2FsZT1mdW5jdGlvbigpe3JldHVybiBEW3RoaXMuJExdfSxtLmxvY2FsZT1mdW5jdGlvbih0LGUpe2lmKCF0KXJldHVybiB0aGlzLiRMO3ZhciBuPXRoaXMuY2xvbmUoKSxyPXcodCxlLCEwKTtyZXR1cm4gciYmKG4uJEw9ciksbn0sbS5jbG9uZT1mdW5jdGlvbigpe3JldHVybiBiLncodGhpcy4kZCx0aGlzKX0sbS50b0RhdGU9ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IERhdGUodGhpcy52YWx1ZU9mKCkpfSxtLnRvSlNPTj1mdW5jdGlvbigpe3JldHVybiB0aGlzLmlzVmFsaWQoKT90aGlzLnRvSVNPU3RyaW5nKCk6bnVsbH0sbS50b0lTT1N0cmluZz1mdW5jdGlvbigpe3JldHVybiB0aGlzLiRkLnRvSVNPU3RyaW5nKCl9LG0udG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy4kZC50b1VUQ1N0cmluZygpfSxNfSgpLGs9Xy5wcm90b3R5cGU7cmV0dXJuIE8ucHJvdG90eXBlPWssW1tcIiRtc1wiLHJdLFtcIiRzXCIsaV0sW1wiJG1cIixzXSxbXCIkSFwiLHVdLFtcIiRXXCIsYV0sW1wiJE1cIixjXSxbXCIkeVwiLGhdLFtcIiREXCIsZF1dLmZvckVhY2goKGZ1bmN0aW9uKHQpe2tbdFsxXV09ZnVuY3Rpb24oZSl7cmV0dXJuIHRoaXMuJGcoZSx0WzBdLHRbMV0pfX0pKSxPLmV4dGVuZD1mdW5jdGlvbih0LGUpe3JldHVybiB0LiRpfHwodChlLF8sTyksdC4kaT0hMCksT30sTy5sb2NhbGU9dyxPLmlzRGF5anM9UyxPLnVuaXg9ZnVuY3Rpb24odCl7cmV0dXJuIE8oMWUzKnQpfSxPLmVuPURbZ10sTy5Mcz1ELE8ucD17fSxPfSkpOyIsICIhZnVuY3Rpb24odCxpKXtcIm9iamVjdFwiPT10eXBlb2YgZXhwb3J0cyYmXCJ1bmRlZmluZWRcIiE9dHlwZW9mIG1vZHVsZT9tb2R1bGUuZXhwb3J0cz1pKCk6XCJmdW5jdGlvblwiPT10eXBlb2YgZGVmaW5lJiZkZWZpbmUuYW1kP2RlZmluZShpKToodD1cInVuZGVmaW5lZFwiIT10eXBlb2YgZ2xvYmFsVGhpcz9nbG9iYWxUaGlzOnR8fHNlbGYpLmRheWpzX3BsdWdpbl91dGM9aSgpfSh0aGlzLChmdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3ZhciB0PVwibWludXRlXCIsaT0vWystXVxcZFxcZCg/Ojo/XFxkXFxkKT8vZyxlPS8oWystXXxcXGRcXGQpL2c7cmV0dXJuIGZ1bmN0aW9uKHMsZixuKXt2YXIgdT1mLnByb3RvdHlwZTtuLnV0Yz1mdW5jdGlvbih0KXt2YXIgaT17ZGF0ZTp0LHV0YzohMCxhcmdzOmFyZ3VtZW50c307cmV0dXJuIG5ldyBmKGkpfSx1LnV0Yz1mdW5jdGlvbihpKXt2YXIgZT1uKHRoaXMudG9EYXRlKCkse2xvY2FsZTp0aGlzLiRMLHV0YzohMH0pO3JldHVybiBpP2UuYWRkKHRoaXMudXRjT2Zmc2V0KCksdCk6ZX0sdS5sb2NhbD1mdW5jdGlvbigpe3JldHVybiBuKHRoaXMudG9EYXRlKCkse2xvY2FsZTp0aGlzLiRMLHV0YzohMX0pfTt2YXIgcj11LnBhcnNlO3UucGFyc2U9ZnVuY3Rpb24odCl7dC51dGMmJih0aGlzLiR1PSEwKSx0aGlzLiR1dGlscygpLnUodC4kb2Zmc2V0KXx8KHRoaXMuJG9mZnNldD10LiRvZmZzZXQpLHIuY2FsbCh0aGlzLHQpfTt2YXIgbz11LmluaXQ7dS5pbml0PWZ1bmN0aW9uKCl7aWYodGhpcy4kdSl7dmFyIHQ9dGhpcy4kZDt0aGlzLiR5PXQuZ2V0VVRDRnVsbFllYXIoKSx0aGlzLiRNPXQuZ2V0VVRDTW9udGgoKSx0aGlzLiREPXQuZ2V0VVRDRGF0ZSgpLHRoaXMuJFc9dC5nZXRVVENEYXkoKSx0aGlzLiRIPXQuZ2V0VVRDSG91cnMoKSx0aGlzLiRtPXQuZ2V0VVRDTWludXRlcygpLHRoaXMuJHM9dC5nZXRVVENTZWNvbmRzKCksdGhpcy4kbXM9dC5nZXRVVENNaWxsaXNlY29uZHMoKX1lbHNlIG8uY2FsbCh0aGlzKX07dmFyIGE9dS51dGNPZmZzZXQ7dS51dGNPZmZzZXQ9ZnVuY3Rpb24ocyxmKXt2YXIgbj10aGlzLiR1dGlscygpLnU7aWYobihzKSlyZXR1cm4gdGhpcy4kdT8wOm4odGhpcy4kb2Zmc2V0KT9hLmNhbGwodGhpcyk6dGhpcy4kb2Zmc2V0O2lmKFwic3RyaW5nXCI9PXR5cGVvZiBzJiYocz1mdW5jdGlvbih0KXt2b2lkIDA9PT10JiYodD1cIlwiKTt2YXIgcz10Lm1hdGNoKGkpO2lmKCFzKXJldHVybiBudWxsO3ZhciBmPShcIlwiK3NbMF0pLm1hdGNoKGUpfHxbXCItXCIsMCwwXSxuPWZbMF0sdT02MCorZlsxXSsgK2ZbMl07cmV0dXJuIDA9PT11PzA6XCIrXCI9PT1uP3U6LXV9KHMpLG51bGw9PT1zKSlyZXR1cm4gdGhpczt2YXIgdT1NYXRoLmFicyhzKTw9MTY/NjAqczpzO2lmKDA9PT11KXJldHVybiB0aGlzLnV0YyhmKTt2YXIgcj10aGlzLmNsb25lKCk7aWYoZilyZXR1cm4gci4kb2Zmc2V0PXUsci4kdT0hMSxyO3ZhciBvPXRoaXMuJHU/dGhpcy50b0RhdGUoKS5nZXRUaW1lem9uZU9mZnNldCgpOi0xKnRoaXMudXRjT2Zmc2V0KCk7cmV0dXJuKHI9dGhpcy5sb2NhbCgpLmFkZCh1K28sdCkpLiRvZmZzZXQ9dSxyLiR4LiRsb2NhbE9mZnNldD1vLHJ9O3ZhciBoPXUuZm9ybWF0O3UuZm9ybWF0PWZ1bmN0aW9uKHQpe3ZhciBpPXR8fCh0aGlzLiR1P1wiWVlZWS1NTS1ERFRISDptbTpzc1taXVwiOlwiXCIpO3JldHVybiBoLmNhbGwodGhpcyxpKX0sdS52YWx1ZU9mPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy4kdXRpbHMoKS51KHRoaXMuJG9mZnNldCk/MDp0aGlzLiRvZmZzZXQrKHRoaXMuJHguJGxvY2FsT2Zmc2V0fHx0aGlzLiRkLmdldFRpbWV6b25lT2Zmc2V0KCkpO3JldHVybiB0aGlzLiRkLnZhbHVlT2YoKS02ZTQqdH0sdS5pc1VUQz1mdW5jdGlvbigpe3JldHVybiEhdGhpcy4kdX0sdS50b0lTT1N0cmluZz1mdW5jdGlvbigpe3JldHVybiB0aGlzLnRvRGF0ZSgpLnRvSVNPU3RyaW5nKCl9LHUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy50b0RhdGUoKS50b1VUQ1N0cmluZygpfTt2YXIgbD11LnRvRGF0ZTt1LnRvRGF0ZT1mdW5jdGlvbih0KXtyZXR1cm5cInNcIj09PXQmJnRoaXMuJG9mZnNldD9uKHRoaXMuZm9ybWF0KFwiWVlZWS1NTS1ERCBISDptbTpzczpTU1NcIikpLnRvRGF0ZSgpOmwuY2FsbCh0aGlzKX07dmFyIGM9dS5kaWZmO3UuZGlmZj1mdW5jdGlvbih0LGksZSl7aWYodCYmdGhpcy4kdT09PXQuJHUpcmV0dXJuIGMuY2FsbCh0aGlzLHQsaSxlKTt2YXIgcz10aGlzLmxvY2FsKCksZj1uKHQpLmxvY2FsKCk7cmV0dXJuIGMuY2FsbChzLGYsaSxlKX19fSkpOyIsICIhZnVuY3Rpb24odCxlKXtcIm9iamVjdFwiPT10eXBlb2YgZXhwb3J0cyYmXCJ1bmRlZmluZWRcIiE9dHlwZW9mIG1vZHVsZT9tb2R1bGUuZXhwb3J0cz1lKCk6XCJmdW5jdGlvblwiPT10eXBlb2YgZGVmaW5lJiZkZWZpbmUuYW1kP2RlZmluZShlKToodD1cInVuZGVmaW5lZFwiIT10eXBlb2YgZ2xvYmFsVGhpcz9nbG9iYWxUaGlzOnR8fHNlbGYpLmRheWpzX3BsdWdpbl90aW1lem9uZT1lKCl9KHRoaXMsKGZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7dmFyIHQ9e3llYXI6MCxtb250aDoxLGRheToyLGhvdXI6MyxtaW51dGU6NCxzZWNvbmQ6NX0sZT17fTtyZXR1cm4gZnVuY3Rpb24obixpLG8pe3ZhciByLGE9ZnVuY3Rpb24odCxuLGkpe3ZvaWQgMD09PWkmJihpPXt9KTt2YXIgbz1uZXcgRGF0ZSh0KSxyPWZ1bmN0aW9uKHQsbil7dm9pZCAwPT09biYmKG49e30pO3ZhciBpPW4udGltZVpvbmVOYW1lfHxcInNob3J0XCIsbz10K1wifFwiK2kscj1lW29dO3JldHVybiByfHwocj1uZXcgSW50bC5EYXRlVGltZUZvcm1hdChcImVuLVVTXCIse2hvdXIxMjohMSx0aW1lWm9uZTp0LHllYXI6XCJudW1lcmljXCIsbW9udGg6XCIyLWRpZ2l0XCIsZGF5OlwiMi1kaWdpdFwiLGhvdXI6XCIyLWRpZ2l0XCIsbWludXRlOlwiMi1kaWdpdFwiLHNlY29uZDpcIjItZGlnaXRcIix0aW1lWm9uZU5hbWU6aX0pLGVbb109cikscn0obixpKTtyZXR1cm4gci5mb3JtYXRUb1BhcnRzKG8pfSx1PWZ1bmN0aW9uKGUsbil7Zm9yKHZhciBpPWEoZSxuKSxyPVtdLHU9MDt1PGkubGVuZ3RoO3UrPTEpe3ZhciBmPWlbdV0scz1mLnR5cGUsbT1mLnZhbHVlLGM9dFtzXTtjPj0wJiYocltjXT1wYXJzZUludChtLDEwKSl9dmFyIGQ9clszXSxsPTI0PT09ZD8wOmQsaD1yWzBdK1wiLVwiK3JbMV0rXCItXCIrclsyXStcIiBcIitsK1wiOlwiK3JbNF0rXCI6XCIrcls1XStcIjowMDBcIix2PStlO3JldHVybihvLnV0YyhoKS52YWx1ZU9mKCktKHYtPXYlMWUzKSkvNmU0fSxmPWkucHJvdG90eXBlO2YudHo9ZnVuY3Rpb24odCxlKXt2b2lkIDA9PT10JiYodD1yKTt2YXIgbixpPXRoaXMudXRjT2Zmc2V0KCksYT10aGlzLnRvRGF0ZSgpLHU9YS50b0xvY2FsZVN0cmluZyhcImVuLVVTXCIse3RpbWVab25lOnR9KSxmPU1hdGgucm91bmQoKGEtbmV3IERhdGUodSkpLzFlMy82MCkscz0xNSotTWF0aC5yb3VuZChhLmdldFRpbWV6b25lT2Zmc2V0KCkvMTUpLWY7aWYoIU51bWJlcihzKSluPXRoaXMudXRjT2Zmc2V0KDAsZSk7ZWxzZSBpZihuPW8odSx7bG9jYWxlOnRoaXMuJEx9KS4kc2V0KFwibWlsbGlzZWNvbmRcIix0aGlzLiRtcykudXRjT2Zmc2V0KHMsITApLGUpe3ZhciBtPW4udXRjT2Zmc2V0KCk7bj1uLmFkZChpLW0sXCJtaW51dGVcIil9cmV0dXJuIG4uJHguJHRpbWV6b25lPXQsbn0sZi5vZmZzZXROYW1lPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuJHguJHRpbWV6b25lfHxvLnR6Lmd1ZXNzKCksbj1hKHRoaXMudmFsdWVPZigpLGUse3RpbWVab25lTmFtZTp0fSkuZmluZCgoZnVuY3Rpb24odCl7cmV0dXJuXCJ0aW1lem9uZW5hbWVcIj09PXQudHlwZS50b0xvd2VyQ2FzZSgpfSkpO3JldHVybiBuJiZuLnZhbHVlfTt2YXIgcz1mLnN0YXJ0T2Y7Zi5zdGFydE9mPWZ1bmN0aW9uKHQsZSl7aWYoIXRoaXMuJHh8fCF0aGlzLiR4LiR0aW1lem9uZSlyZXR1cm4gcy5jYWxsKHRoaXMsdCxlKTt2YXIgbj1vKHRoaXMuZm9ybWF0KFwiWVlZWS1NTS1ERCBISDptbTpzczpTU1NcIikse2xvY2FsZTp0aGlzLiRMfSk7cmV0dXJuIHMuY2FsbChuLHQsZSkudHoodGhpcy4keC4kdGltZXpvbmUsITApfSxvLnR6PWZ1bmN0aW9uKHQsZSxuKXt2YXIgaT1uJiZlLGE9bnx8ZXx8cixmPXUoK28oKSxhKTtpZihcInN0cmluZ1wiIT10eXBlb2YgdClyZXR1cm4gbyh0KS50eihhKTt2YXIgcz1mdW5jdGlvbih0LGUsbil7dmFyIGk9dC02MCplKjFlMyxvPXUoaSxuKTtpZihlPT09bylyZXR1cm5baSxlXTt2YXIgcj11KGktPTYwKihvLWUpKjFlMyxuKTtyZXR1cm4gbz09PXI/W2ksb106W3QtNjAqTWF0aC5taW4obyxyKSoxZTMsTWF0aC5tYXgobyxyKV19KG8udXRjKHQsaSkudmFsdWVPZigpLGYsYSksbT1zWzBdLGM9c1sxXSxkPW8obSkudXRjT2Zmc2V0KGMpO3JldHVybiBkLiR4LiR0aW1lem9uZT1hLGR9LG8udHouZ3Vlc3M9ZnVuY3Rpb24oKXtyZXR1cm4gSW50bC5EYXRlVGltZUZvcm1hdCgpLnJlc29sdmVkT3B0aW9ucygpLnRpbWVab25lfSxvLnR6LnNldERlZmF1bHQ9ZnVuY3Rpb24odCl7cj10fX19KSk7IiwgIiFmdW5jdGlvbihlLHQpe1wib2JqZWN0XCI9PXR5cGVvZiBleHBvcnRzJiZcInVuZGVmaW5lZFwiIT10eXBlb2YgbW9kdWxlP21vZHVsZS5leHBvcnRzPXQoKTpcImZ1bmN0aW9uXCI9PXR5cGVvZiBkZWZpbmUmJmRlZmluZS5hbWQ/ZGVmaW5lKHQpOihlPVwidW5kZWZpbmVkXCIhPXR5cGVvZiBnbG9iYWxUaGlzP2dsb2JhbFRoaXM6ZXx8c2VsZikuZGF5anNfcGx1Z2luX2lzb1dlZWs9dCgpfSh0aGlzLChmdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3ZhciBlPVwiZGF5XCI7cmV0dXJuIGZ1bmN0aW9uKHQsaSxzKXt2YXIgYT1mdW5jdGlvbih0KXtyZXR1cm4gdC5hZGQoNC10Lmlzb1dlZWtkYXkoKSxlKX0sZD1pLnByb3RvdHlwZTtkLmlzb1dlZWtZZWFyPWZ1bmN0aW9uKCl7cmV0dXJuIGEodGhpcykueWVhcigpfSxkLmlzb1dlZWs9ZnVuY3Rpb24odCl7aWYoIXRoaXMuJHV0aWxzKCkudSh0KSlyZXR1cm4gdGhpcy5hZGQoNyoodC10aGlzLmlzb1dlZWsoKSksZSk7dmFyIGksZCxuLG8scj1hKHRoaXMpLHU9KGk9dGhpcy5pc29XZWVrWWVhcigpLGQ9dGhpcy4kdSxuPShkP3MudXRjOnMpKCkueWVhcihpKS5zdGFydE9mKFwieWVhclwiKSxvPTQtbi5pc29XZWVrZGF5KCksbi5pc29XZWVrZGF5KCk+NCYmKG8rPTcpLG4uYWRkKG8sZSkpO3JldHVybiByLmRpZmYodSxcIndlZWtcIikrMX0sZC5pc29XZWVrZGF5PWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLiR1dGlscygpLnUoZSk/dGhpcy5kYXkoKXx8Nzp0aGlzLmRheSh0aGlzLmRheSgpJTc/ZTplLTcpfTt2YXIgbj1kLnN0YXJ0T2Y7ZC5zdGFydE9mPWZ1bmN0aW9uKGUsdCl7dmFyIGk9dGhpcy4kdXRpbHMoKSxzPSEhaS51KHQpfHx0O3JldHVyblwiaXNvd2Vla1wiPT09aS5wKGUpP3M/dGhpcy5kYXRlKHRoaXMuZGF0ZSgpLSh0aGlzLmlzb1dlZWtkYXkoKS0xKSkuc3RhcnRPZihcImRheVwiKTp0aGlzLmRhdGUodGhpcy5kYXRlKCktMS0odGhpcy5pc29XZWVrZGF5KCktMSkrNykuZW5kT2YoXCJkYXlcIik6bi5iaW5kKHRoaXMpKGUsdCl9fX0pKTsiLCAibGV0IHRva2VuQ291bnRlciA9IDA7XG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdW5pcXVlIHRva2VuIGZvciBkZXBlbmRlbmN5IGluamVjdGlvbi5cbiAqXG4gKiBAcGFyYW0gZGVzY3JpcHRpb24gT3B0aW9uYWwgZGVzY3JpcHRpb24gZm9yIGRlYnVnZ2luZyBwdXJwb3Nlc1xuICogQHJldHVybnMgQSB1bmlxdWUgdG9rZW4gdGhhdCBjYW4gYmUgdXNlZCBhcyBhIE1hcCBrZXlcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIGludGVyZmFjZSBJTG9nZ2VyIHsgbG9nKG1zZzogc3RyaW5nKTogdm9pZCB9XG4gKiBjb25zdCBMb2dnZXJUb2tlbiA9IFRva2VuPElMb2dnZXI+KCdMb2dnZXInKVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBUb2tlbihkZXNjcmlwdGlvbikge1xuICAgIGNvbnN0IGlkID0gKyt0b2tlbkNvdW50ZXI7XG4gICAgY29uc3Qgc3ltID0gU3ltYm9sKGRlc2NyaXB0aW9uID8gYFRva2VuKCR7ZGVzY3JpcHRpb259KWAgOiBgVG9rZW4jJHtpZH1gKTtcbiAgICBjb25zdCB0b2tlbiA9IHtcbiAgICAgICAgc3ltYm9sOiBzeW0sXG4gICAgICAgIGRlc2NyaXB0aW9uLFxuICAgICAgICB0b1N0cmluZygpIHtcbiAgICAgICAgICAgIHJldHVybiBkZXNjcmlwdGlvblxuICAgICAgICAgICAgICAgID8gYFRva2VuPCR7ZGVzY3JpcHRpb259PmBcbiAgICAgICAgICAgICAgICA6IGBUb2tlbjwjJHtpZH0+YDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIHRva2VuO1xufVxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IHVuaXF1ZSB0b2tlbiB3aXRob3V0IGEgc3RyaW5nIGxpdGVyYWwuXG4gKiBQcmVmZXJyZWQgZm9yIEF1dG9mYWMtc3R5bGUgREkgdG8gYXZvaWQgc3RyaW5nIGxpdGVyYWxzLlxuICpcbiAqIEByZXR1cm5zIEEgdW5pcXVlIHRva2VuIHRoYXQgY2FuIGJlIHVzZWQgYXMgYSBNYXAga2V5XG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiBpbnRlcmZhY2UgSUxvZ2dlciB7IGxvZyhtc2c6IHN0cmluZyk6IHZvaWQgfVxuICogY29uc3QgTG9nZ2VyVG9rZW4gPSB0b2tlbjxJTG9nZ2VyPigpXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRva2VuKCkge1xuICAgIHJldHVybiBUb2tlbigpO1xufVxuIiwgIi8qKlxuICogRXJyb3IgY2xhc3NlcyBmb3IgTm92YURJIGNvbnRhaW5lclxuICovXG5leHBvcnQgY2xhc3MgQ29udGFpbmVyRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IobWVzc2FnZSkge1xuICAgICAgICBzdXBlcihtZXNzYWdlKTtcbiAgICAgICAgdGhpcy5uYW1lID0gJ0NvbnRhaW5lckVycm9yJztcbiAgICB9XG59XG5leHBvcnQgY2xhc3MgQmluZGluZ05vdEZvdW5kRXJyb3IgZXh0ZW5kcyBDb250YWluZXJFcnJvciB7XG4gICAgY29uc3RydWN0b3IodG9rZW5EZXNjcmlwdGlvbiwgcGF0aCA9IFtdKSB7XG4gICAgICAgIGNvbnN0IHBhdGhTdHIgPSBwYXRoLmxlbmd0aCA+IDAgPyBgXFxuICBEZXBlbmRlbmN5IHBhdGg6ICR7cGF0aC5qb2luKCcgLT4gJyl9YCA6ICcnO1xuICAgICAgICBzdXBlcihgVG9rZW4gXCIke3Rva2VuRGVzY3JpcHRpb259XCIgaXMgbm90IGJvdW5kIG9yIHJlZ2lzdGVyZWQgaW4gdGhlIGNvbnRhaW5lci4ke3BhdGhTdHJ9YCk7XG4gICAgICAgIHRoaXMubmFtZSA9ICdCaW5kaW5nTm90Rm91bmRFcnJvcic7XG4gICAgfVxufVxuZXhwb3J0IGNsYXNzIENpcmN1bGFyRGVwZW5kZW5jeUVycm9yIGV4dGVuZHMgQ29udGFpbmVyRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKHBhdGgpIHtcbiAgICAgICAgc3VwZXIoYENpcmN1bGFyIGRlcGVuZGVuY3kgZGV0ZWN0ZWQ6ICR7cGF0aC5qb2luKCcgLT4gJyl9YCk7XG4gICAgICAgIHRoaXMubmFtZSA9ICdDaXJjdWxhckRlcGVuZGVuY3lFcnJvcic7XG4gICAgfVxufVxuIiwgIi8qKlxuICogQXV0b1dpcmUgLSBBdXRvbWF0aWMgZGVwZW5kZW5jeSBpbmplY3Rpb24gZm9yIE5vdmFESVxuICogU3VwcG9ydHMgdHdvIHN0cmF0ZWdpZXM6IG1hcFJlc29sdmVycyAodHJhbnNmb3JtZXItZ2VuZXJhdGVkKSBhbmQgbWFwIChtYW51YWwgb3ZlcnJpZGUpXG4gKi9cbi8qKlxuICogUGVyZm9ybWFuY2U6IENhY2hlIGV4dHJhY3RlZCBwYXJhbWV0ZXIgbmFtZXMgdG8gYXZvaWQgcmVwZWF0ZWQgcmVnZXggcGFyc2luZ1xuICogV2Vha01hcCBhbGxvd3MgZ2FyYmFnZSBjb2xsZWN0aW9uIHdoZW4gY29uc3RydWN0b3IgaXMgbm8gbG9uZ2VyIHJlZmVyZW5jZWRcbiAqL1xuY29uc3QgcGFyYW1OYW1lQ2FjaGUgPSBuZXcgV2Vha01hcCgpO1xuLyoqXG4gKiBFeHRyYWN0IHBhcmFtZXRlciBuYW1lcyBmcm9tIGEgY29uc3RydWN0b3IgZnVuY3Rpb25cbiAqIFVzZXMgcmVnZXggdG8gcGFyc2UgdGhlIHRvU3RyaW5nKCkgcmVwcmVzZW50YXRpb25cbiAqIFBlcmZvcm1hbmNlIG9wdGltaXplZDogUmVzdWx0cyBhcmUgY2FjaGVkIHBlciBjb25zdHJ1Y3RvclxuICpcbiAqIE5vdGU6IE9ubHkgdXNlZCBieSByZXNvbHZlQnlNYXAoKSBmb3IgbWFudWFsIG1hcCBzdHJhdGVneVxuICovXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdFBhcmFtZXRlck5hbWVzKGNvbnN0cnVjdG9yKSB7XG4gICAgLy8gQ2hlY2sgY2FjaGUgZmlyc3QgLSBhdm9pZHMgZXhwZW5zaXZlIHJlZ2V4IHBhcnNpbmdcbiAgICBjb25zdCBjYWNoZWQgPSBwYXJhbU5hbWVDYWNoZS5nZXQoY29uc3RydWN0b3IpO1xuICAgIGlmIChjYWNoZWQpIHtcbiAgICAgICAgcmV0dXJuIGNhY2hlZDtcbiAgICB9XG4gICAgLy8gRXh0cmFjdCBwYXJhbWV0ZXIgbmFtZXMgKGV4cGVuc2l2ZSBvcGVyYXRpb24pXG4gICAgY29uc3QgZm5TdHIgPSBjb25zdHJ1Y3Rvci50b1N0cmluZygpO1xuICAgIC8vIE1hdGNoIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIG9yIGNsYXNzIHsgY29uc3RydWN0b3IoLi4uYXJncykgfVxuICAgIGNvbnN0IG1hdGNoID0gZm5TdHIubWF0Y2goL2NvbnN0cnVjdG9yXFxzKlxcKChbXildKilcXCkvKSB8fCBmblN0ci5tYXRjaCgvXlteKF0qXFwoKFteKV0qKVxcKS8pO1xuICAgIGlmICghbWF0Y2ggfHwgIW1hdGNoWzFdKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgY29uc3QgcGFyYW1zID0gbWF0Y2hbMV1cbiAgICAgICAgLnNwbGl0KCcsJylcbiAgICAgICAgLm1hcChwYXJhbSA9PiBwYXJhbS50cmltKCkpXG4gICAgICAgIC5maWx0ZXIocGFyYW0gPT4gcGFyYW0ubGVuZ3RoID4gMClcbiAgICAgICAgLm1hcChwYXJhbSA9PiB7XG4gICAgICAgIC8vIFJlbW92ZSBkZWZhdWx0IHZhbHVlcywgdHlwZSBhbm5vdGF0aW9ucywgYW5kIGV4dHJhY3QganVzdCB0aGUgbmFtZVxuICAgICAgICBsZXQgbmFtZSA9IHBhcmFtLnNwbGl0KC9bOj1dLylbMF0udHJpbSgpO1xuICAgICAgICAvLyBSZW1vdmUgVHlwZVNjcmlwdCBtb2RpZmllcnMgKHB1YmxpYywgcHJpdmF0ZSwgcHJvdGVjdGVkLCByZWFkb25seSlcbiAgICAgICAgLy8gQ2FuIGFwcGVhciBtdWx0aXBsZSB0aW1lcywgZS5nLiwgXCJwdWJsaWMgcmVhZG9ubHkgc2VydmljZVwiXG4gICAgICAgIG5hbWUgPSBuYW1lLnJlcGxhY2UoL14oKHB1YmxpY3xwcml2YXRlfHByb3RlY3RlZHxyZWFkb25seSlcXHMrKSsvLCAnJyk7XG4gICAgICAgIC8vIEhhbmRsZSBkZXN0cnVjdHVyaW5nIC0gc2tpcCBmb3Igbm93XG4gICAgICAgIGlmIChuYW1lLmluY2x1ZGVzKCd7JykgfHwgbmFtZS5pbmNsdWRlcygnWycpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmFtZTtcbiAgICB9KVxuICAgICAgICAuZmlsdGVyKChuYW1lKSA9PiBuYW1lICE9PSBudWxsKTtcbiAgICAvLyBDYWNoZSByZXN1bHQgZm9yIGZ1dHVyZSBjYWxsc1xuICAgIHBhcmFtTmFtZUNhY2hlLnNldChjb25zdHJ1Y3RvciwgcGFyYW1zKTtcbiAgICByZXR1cm4gcGFyYW1zO1xufVxuLyoqXG4gKiBSZXNvbHZlIGRlcGVuZGVuY2llcyB1c2luZyBtYXAgc3RyYXRlZ3lcbiAqIFVzZXMgZXhwbGljaXQgbWFwcGluZyBmcm9tIHBhcmFtZXRlciBuYW1lcyB0byByZXNvbHZlcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVCeU1hcChjb25zdHJ1Y3RvciwgY29udGFpbmVyLCBvcHRpb25zKSB7XG4gICAgaWYgKCFvcHRpb25zLm1hcCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0F1dG9XaXJlIG1hcCBzdHJhdGVneSByZXF1aXJlcyBvcHRpb25zLm1hcCB0byBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGNvbnN0IHBhcmFtTmFtZXMgPSBleHRyYWN0UGFyYW1ldGVyTmFtZXMoY29uc3RydWN0b3IpO1xuICAgIGNvbnN0IHJlc29sdmVkRGVwcyA9IFtdO1xuICAgIGZvciAoY29uc3QgcGFyYW1OYW1lIG9mIHBhcmFtTmFtZXMpIHtcbiAgICAgICAgY29uc3QgcmVzb2x2ZXIgPSBvcHRpb25zLm1hcFtwYXJhbU5hbWVdO1xuICAgICAgICBpZiAocmVzb2x2ZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuc3RyaWN0KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgcmVzb2x2ZSBwYXJhbWV0ZXIgXCIke3BhcmFtTmFtZX1cIiBvbiAke2NvbnN0cnVjdG9yLm5hbWV9LiBgICtcbiAgICAgICAgICAgICAgICAgICAgYE5vdCBmb3VuZCBpbiBhdXRvd2lyZSBtYXAuIGAgK1xuICAgICAgICAgICAgICAgICAgICBgQWRkIGl0IHRvIHRoZSBtYXA6IC5hdXRvV2lyZSh7IG1hcDogeyAke3BhcmFtTmFtZX06IC4uLiB9IH0pYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBTaWxlbnRseSBwdXNoIHVuZGVmaW5lZCBmb3IgbWlzc2luZyBwYXJhbWV0ZXJzXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBpcyBleHBlY3RlZDogdHJhbnNmb3JtZXIgZmlsdGVycyBvdXQgcHJpbWl0aXZlIHR5cGVzIGF0IGNvbXBpbGUtdGltZSxcbiAgICAgICAgICAgICAgICAvLyBzbyBtaXNzaW5nIHBhcmFtcyBhcmUgdHlwaWNhbGx5IHByaW1pdGl2ZXMgdGhhdCBkb24ndCBuZWVkIERJIHJlc29sdXRpb25cbiAgICAgICAgICAgICAgICByZXNvbHZlZERlcHMucHVzaCh1bmRlZmluZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmVzb2x2ZXIgY2FuIGJlIGEgZnVuY3Rpb24gb3IgYSBUb2tlblxuICAgICAgICBpZiAodHlwZW9mIHJlc29sdmVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICByZXNvbHZlZERlcHMucHVzaChyZXNvbHZlcihjb250YWluZXIpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIEFzc3VtZSBpdCdzIGEgVG9rZW5cbiAgICAgICAgICAgIHJlc29sdmVkRGVwcy5wdXNoKGNvbnRhaW5lci5yZXNvbHZlKHJlc29sdmVyKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc29sdmVkRGVwcztcbn1cbi8qKlxuICogUmVzb2x2ZSBkZXBlbmRlbmNpZXMgdXNpbmcgbWFwUmVzb2x2ZXJzIGFycmF5IHN0cmF0ZWd5XG4gKiBPUFRJTUFMIFBFUkZPUk1BTkNFOiBPKDEpIGFycmF5IGFjY2VzcyBwZXIgcGFyYW1ldGVyXG4gKiBNaW5pZmljYXRpb24tc2FmZTogVXNlcyBwb3NpdGlvbi1iYXNlZCBhcnJheVxuICogUmVmYWN0b3JpbmctZnJpZW5kbHk6IFRyYW5zZm9ybWVyIHJlZ2VuZXJhdGVzIGFycmF5IG9uIHJlY29tcGlsZVxuICpcbiAqIFJlcXVpcmVzIGJ1aWxkLXRpbWUgdHJhbnNmb3JtZXIgdG8gZ2VuZXJhdGUgbWFwUmVzb2x2ZXJzIGFycmF5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlQnlNYXBSZXNvbHZlcnMoX2NvbnN0cnVjdG9yLCBjb250YWluZXIsIG9wdGlvbnMpIHtcbiAgICBpZiAoIW9wdGlvbnMubWFwUmVzb2x2ZXJzIHx8IG9wdGlvbnMubWFwUmVzb2x2ZXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIGNvbnN0IHJlc29sdmVkRGVwcyA9IFtdO1xuICAgIC8vIFNpbXBsZSBPKDEpIGFycmF5IGFjY2VzcyAtIHVsdHJhIGZhc3QhXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvcHRpb25zLm1hcFJlc29sdmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCByZXNvbHZlciA9IG9wdGlvbnMubWFwUmVzb2x2ZXJzW2ldO1xuICAgICAgICBpZiAocmVzb2x2ZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgLy8gdW5kZWZpbmVkIGluZGljYXRlcyBwcmltaXRpdmUgdHlwZSBvciBwYXJhbWV0ZXIgd2l0aG91dCBESVxuICAgICAgICAgICAgcmVzb2x2ZWREZXBzLnB1c2godW5kZWZpbmVkKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgcmVzb2x2ZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIC8vIFJlc29sdmVyIGZ1bmN0aW9uOiAoYykgPT4gYy5yZXNvbHZlVHlwZSguLi4pXG4gICAgICAgICAgICByZXNvbHZlZERlcHMucHVzaChyZXNvbHZlcihjb250YWluZXIpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFRva2VuLWJhc2VkIHJlc29sdXRpb25cbiAgICAgICAgICAgIHJlc29sdmVkRGVwcy5wdXNoKGNvbnRhaW5lci5yZXNvbHZlKHJlc29sdmVyKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc29sdmVkRGVwcztcbn1cbi8qKlxuICogTWFpbiBhdXRvd2lyZSBmdW5jdGlvbiAtIGRpc3BhdGNoZXMgdG8gYXBwcm9wcmlhdGUgc3RyYXRlZ3lcbiAqIFByaW9yaXR5OiBtYXBSZXNvbHZlcnMgKHRyYW5zZm9ybWVyLWdlbmVyYXRlZCkgPiBtYXAgKG1hbnVhbCBvdmVycmlkZSlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGF1dG93aXJlKGNvbnN0cnVjdG9yLCBjb250YWluZXIsIG9wdGlvbnMpIHtcbiAgICBjb25zdCBvcHRzID0ge1xuICAgICAgICBieTogJ3BhcmFtTmFtZScsXG4gICAgICAgIHN0cmljdDogZmFsc2UsXG4gICAgICAgIC4uLm9wdGlvbnNcbiAgICB9O1xuICAgIC8vIEhJR0hFU1QgUFJJT1JJVFk6IG1hcFJlc29sdmVycyBhcnJheSAodHJhbnNmb3JtZXItZ2VuZXJhdGVkLCBvcHRpbWFsIHBlcmZvcm1hbmNlKVxuICAgIC8vIE8oMSkgYXJyYXkgYWNjZXNzIHBlciBwYXJhbWV0ZXIgLSBtaW5pZmljYXRpb24tc2FmZSBhbmQgcmVmYWN0b3JpbmctZnJpZW5kbHlcbiAgICBpZiAob3B0cy5tYXBSZXNvbHZlcnMgJiYgb3B0cy5tYXBSZXNvbHZlcnMubGVuZ3RoID4gMCkge1xuICAgICAgICByZXR1cm4gcmVzb2x2ZUJ5TWFwUmVzb2x2ZXJzKGNvbnN0cnVjdG9yLCBjb250YWluZXIsIG9wdHMpO1xuICAgIH1cbiAgICAvLyBGQUxMQkFDSzogTWFudWFsIG1hcCBzdHJhdGVneSBmb3IgZXhwbGljaXQgb3ZlcnJpZGVzXG4gICAgaWYgKG9wdHMubWFwICYmIE9iamVjdC5rZXlzKG9wdHMubWFwKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIHJldHVybiByZXNvbHZlQnlNYXAoY29uc3RydWN0b3IsIGNvbnRhaW5lciwgb3B0cyk7XG4gICAgfVxuICAgIC8vIE5vIGF1dG93aXJpbmcgY29uZmlndXJlZCwgcmV0dXJuIGVtcHR5IGFycmF5XG4gICAgcmV0dXJuIFtdO1xufVxuIiwgIi8qKlxuICogRmx1ZW50IGJ1aWxkZXIgQVBJIGZvciBOb3ZhREkgQ29udGFpbmVyIChBdXRvZmFjLXN0eWxlKVxuICovXG5pbXBvcnQgeyBUb2tlbiB9IGZyb20gJy4vdG9rZW4uanMnO1xuaW1wb3J0IHsgYXV0b3dpcmUgfSBmcm9tICcuL2F1dG93aXJlLmpzJztcbi8qKlxuICogRmx1ZW50IHJlZ2lzdHJhdGlvbiBidWlsZGVyIHJldHVybmVkIGFmdGVyIGVhY2ggcmVnaXN0cmF0aW9uIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgUmVnaXN0cmF0aW9uQnVpbGRlciB7XG4gICAgY29uc3RydWN0b3IocGVuZGluZywgcmVnaXN0cmF0aW9ucykge1xuICAgICAgICB0aGlzLnJlZ2lzdHJhdGlvbnMgPSByZWdpc3RyYXRpb25zO1xuICAgICAgICB0aGlzLmNvbmZpZ3MgPSBbXTtcbiAgICAgICAgdGhpcy5kZWZhdWx0TGlmZXRpbWUgPSAnc2luZ2xldG9uJztcbiAgICAgICAgdGhpcy5wZW5kaW5nID0gcGVuZGluZztcbiAgICB9XG4gICAgLyoqXG4gICAgICogQmluZCB0aGlzIHJlZ2lzdHJhdGlvbiB0byBhIHRva2VuIG9yIGludGVyZmFjZSB0eXBlXG4gICAgICpcbiAgICAgKiBAb3ZlcmxvYWRcbiAgICAgKiBAcGFyYW0ge1Rva2VuPFU+fSB0b2tlbiAtIEV4cGxpY2l0IHRva2VuIGZvciBiaW5kaW5nXG4gICAgICpcbiAgICAgKiBAb3ZlcmxvYWRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdHlwZU5hbWUgLSBJbnRlcmZhY2UgdHlwZSBuYW1lIChhdXRvLWdlbmVyYXRlZCBieSB0cmFuc2Zvcm1lcilcbiAgICAgKi9cbiAgICBhcyh0b2tlbk9yVHlwZU5hbWUpIHtcbiAgICAgICAgLy8gQ2hlY2sgaWYgYXJndW1lbnQgaXMgYSBUb2tlbiBvYmplY3QgKGhhcyBzeW1ib2wgcHJvcGVydHkpXG4gICAgICAgIGlmICh0b2tlbk9yVHlwZU5hbWUgJiYgdHlwZW9mIHRva2VuT3JUeXBlTmFtZSA9PT0gJ29iamVjdCcgJiYgJ3N5bWJvbCcgaW4gdG9rZW5PclR5cGVOYW1lKSB7XG4gICAgICAgICAgICAvLyBUb2tlbi1iYXNlZCByZWdpc3RyYXRpb25cbiAgICAgICAgICAgIGNvbnN0IGNvbmZpZyA9IHtcbiAgICAgICAgICAgICAgICB0b2tlbjogdG9rZW5PclR5cGVOYW1lLFxuICAgICAgICAgICAgICAgIHR5cGU6IHRoaXMucGVuZGluZy50eXBlLFxuICAgICAgICAgICAgICAgIHZhbHVlOiB0aGlzLnBlbmRpbmcudmFsdWUsXG4gICAgICAgICAgICAgICAgZmFjdG9yeTogdGhpcy5wZW5kaW5nLmZhY3RvcnksXG4gICAgICAgICAgICAgICAgY29uc3RydWN0b3I6IHRoaXMucGVuZGluZy5jb25zdHJ1Y3RvcixcbiAgICAgICAgICAgICAgICBsaWZldGltZTogdGhpcy5kZWZhdWx0TGlmZXRpbWVcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0aGlzLmNvbmZpZ3MucHVzaChjb25maWcpO1xuICAgICAgICAgICAgdGhpcy5yZWdpc3RyYXRpb25zLnB1c2goY29uZmlnKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gSW50ZXJmYWNlLWJhc2VkIHJlZ2lzdHJhdGlvbiAodHlwZU5hbWUgc3RyaW5nIG9yIHVuZGVmaW5lZClcbiAgICAgICAgICAgIGNvbnN0IGNvbmZpZyA9IHtcbiAgICAgICAgICAgICAgICB0b2tlbjogbnVsbCwgLy8gV2lsbCBiZSBzZXQgZHVyaW5nIGJ1aWxkKClcbiAgICAgICAgICAgICAgICB0eXBlOiB0aGlzLnBlbmRpbmcudHlwZSxcbiAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy5wZW5kaW5nLnZhbHVlLFxuICAgICAgICAgICAgICAgIGZhY3Rvcnk6IHRoaXMucGVuZGluZy5mYWN0b3J5LFxuICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yOiB0aGlzLnBlbmRpbmcuY29uc3RydWN0b3IsXG4gICAgICAgICAgICAgICAgbGlmZXRpbWU6IHRoaXMuZGVmYXVsdExpZmV0aW1lLFxuICAgICAgICAgICAgICAgIGludGVyZmFjZVR5cGU6IHRva2VuT3JUeXBlTmFtZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuY29uZmlncy5wdXNoKGNvbmZpZyk7XG4gICAgICAgICAgICB0aGlzLnJlZ2lzdHJhdGlvbnMucHVzaChjb25maWcpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgYXMgZGVmYXVsdCBpbXBsZW1lbnRhdGlvbiBmb3IgYW4gaW50ZXJmYWNlXG4gICAgICogQ29tYmluZXMgYXMoKSArIGFzRGVmYXVsdCgpXG4gICAgICovXG4gICAgYXNEZWZhdWx0SW50ZXJmYWNlKHR5cGVOYW1lKSB7XG4gICAgICAgIHRoaXMuYXMoXCJUSW50ZXJmYWNlXCIsIHR5cGVOYW1lKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXNEZWZhdWx0KCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVyIGFzIGEga2V5ZWQgaW50ZXJmYWNlIGltcGxlbWVudGF0aW9uXG4gICAgICogQ29tYmluZXMgYXMoKSArIGtleWVkKClcbiAgICAgKi9cbiAgICBhc0tleWVkSW50ZXJmYWNlKGtleSwgdHlwZU5hbWUpIHtcbiAgICAgICAgdGhpcy5hcyhcIlRJbnRlcmZhY2VcIiwgdHlwZU5hbWUpO1xuICAgICAgICByZXR1cm4gdGhpcy5rZXllZChrZXkpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlciBhcyBtdWx0aXBsZSBpbXBsZW1lbnRlZCBpbnRlcmZhY2VzXG4gICAgICovXG4gICAgYXNJbXBsZW1lbnRlZEludGVyZmFjZXModG9rZW5zKSB7XG4gICAgICAgIGlmICh0b2tlbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICAvLyBJZiB0aGVyZSBhcmUgZXhpc3RpbmcgY29uZmlncyAoZnJvbSBwcmV2aW91cyBhcygpIGNhbGxzKSwgYWRkIHRoZXNlIGFzIGFkZGl0aW9uYWwgaW50ZXJmYWNlc1xuICAgICAgICBpZiAodGhpcy5jb25maWdzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIC8vIEFkZCBhbGwgdG9rZW5zIGFzIGFkZGl0aW9uYWwgaW50ZXJmYWNlcyB0byBleGlzdGluZyBjb25maWdzXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbmZpZyBvZiB0aGlzLmNvbmZpZ3MpIHtcbiAgICAgICAgICAgICAgICBjb25maWcubGlmZXRpbWUgPSAnc2luZ2xldG9uJzsgLy8gYXNJbXBsZW1lbnRlZEludGVyZmFjZXMgZGVmYXVsdHMgdG8gc2luZ2xldG9uXG4gICAgICAgICAgICAgICAgY29uZmlnLmFkZGl0aW9uYWxUb2tlbnMgPSBjb25maWcuYWRkaXRpb25hbFRva2VucyB8fCBbXTtcbiAgICAgICAgICAgICAgICBjb25maWcuYWRkaXRpb25hbFRva2Vucy5wdXNoKC4uLnRva2Vucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICAvLyBObyBleGlzdGluZyBjb25maWdzLCBjcmVhdGUgbmV3IG9uZSB3aXRoIGZpcnN0IHRva2VuXG4gICAgICAgIGNvbnN0IGZpcnN0Q29uZmlnID0ge1xuICAgICAgICAgICAgdG9rZW46IHRva2Vuc1swXSxcbiAgICAgICAgICAgIHR5cGU6IHRoaXMucGVuZGluZy50eXBlLFxuICAgICAgICAgICAgdmFsdWU6IHRoaXMucGVuZGluZy52YWx1ZSxcbiAgICAgICAgICAgIGZhY3Rvcnk6IHRoaXMucGVuZGluZy5mYWN0b3J5LFxuICAgICAgICAgICAgY29uc3RydWN0b3I6IHRoaXMucGVuZGluZy5jb25zdHJ1Y3RvcixcbiAgICAgICAgICAgIGxpZmV0aW1lOiAnc2luZ2xldG9uJ1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmNvbmZpZ3MucHVzaChmaXJzdENvbmZpZyk7XG4gICAgICAgIHRoaXMucmVnaXN0cmF0aW9ucy5wdXNoKGZpcnN0Q29uZmlnKTtcbiAgICAgICAgLy8gQWRkaXRpb25hbCB0b2tlbnMgcmVmZXJlbmNlIHRoZSBzYW1lIHJlZ2lzdHJhdGlvblxuICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHRva2Vucy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgZmlyc3RDb25maWcuYWRkaXRpb25hbFRva2VucyA9IGZpcnN0Q29uZmlnLmFkZGl0aW9uYWxUb2tlbnMgfHwgW107XG4gICAgICAgICAgICBmaXJzdENvbmZpZy5hZGRpdGlvbmFsVG9rZW5zLnB1c2godG9rZW5zW2ldKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2V0IHNpbmdsZXRvbiBsaWZldGltZSAob25lIGluc3RhbmNlIGZvciBlbnRpcmUgY29udGFpbmVyKVxuICAgICAqL1xuICAgIHNpbmdsZUluc3RhbmNlKCkge1xuICAgICAgICBmb3IgKGNvbnN0IGNvbmZpZyBvZiB0aGlzLmNvbmZpZ3MpIHtcbiAgICAgICAgICAgIGNvbmZpZy5saWZldGltZSA9ICdzaW5nbGV0b24nO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZXQgcGVyLXJlcXVlc3QgbGlmZXRpbWUgKG9uZSBpbnN0YW5jZSBwZXIgcmVzb2x2ZSBjYWxsIHRyZWUpXG4gICAgICovXG4gICAgaW5zdGFuY2VQZXJSZXF1ZXN0KCkge1xuICAgICAgICBmb3IgKGNvbnN0IGNvbmZpZyBvZiB0aGlzLmNvbmZpZ3MpIHtcbiAgICAgICAgICAgIGNvbmZpZy5saWZldGltZSA9ICdwZXItcmVxdWVzdCc7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNldCB0cmFuc2llbnQgbGlmZXRpbWUgKG5ldyBpbnN0YW5jZSBldmVyeSB0aW1lKVxuICAgICAqIEFsaWFzIGZvciBkZWZhdWx0IGJlaGF2aW9yXG4gICAgICovXG4gICAgaW5zdGFuY2VQZXJEZXBlbmRlbmN5KCkge1xuICAgICAgICBmb3IgKGNvbnN0IGNvbmZpZyBvZiB0aGlzLmNvbmZpZ3MpIHtcbiAgICAgICAgICAgIGNvbmZpZy5saWZldGltZSA9ICd0cmFuc2llbnQnO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBOYW1lIHRoaXMgcmVnaXN0cmF0aW9uIGZvciBuYW1lZCByZXNvbHV0aW9uXG4gICAgICovXG4gICAgbmFtZWQobmFtZSkge1xuICAgICAgICBmb3IgKGNvbnN0IGNvbmZpZyBvZiB0aGlzLmNvbmZpZ3MpIHtcbiAgICAgICAgICAgIGNvbmZpZy5uYW1lID0gbmFtZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogS2V5IHRoaXMgcmVnaXN0cmF0aW9uIGZvciBrZXllZCByZXNvbHV0aW9uXG4gICAgICovXG4gICAga2V5ZWQoa2V5KSB7XG4gICAgICAgIGZvciAoY29uc3QgY29uZmlnIG9mIHRoaXMuY29uZmlncykge1xuICAgICAgICAgICAgY29uZmlnLmtleSA9IGtleTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogTWFyayB0aGlzIGFzIGRlZmF1bHQgcmVnaXN0cmF0aW9uXG4gICAgICogRGVmYXVsdCByZWdpc3RyYXRpb25zIGRvbid0IG92ZXJyaWRlIGV4aXN0aW5nIG9uZXNcbiAgICAgKi9cbiAgICBhc0RlZmF1bHQoKSB7XG4gICAgICAgIGZvciAoY29uc3QgY29uZmlnIG9mIHRoaXMuY29uZmlncykge1xuICAgICAgICAgICAgY29uZmlnLmlzRGVmYXVsdCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIE9ubHkgcmVnaXN0ZXIgaWYgdG9rZW4gbm90IGFscmVhZHkgcmVnaXN0ZXJlZFxuICAgICAqL1xuICAgIGlmTm90UmVnaXN0ZXJlZCgpIHtcbiAgICAgICAgZm9yIChjb25zdCBjb25maWcgb2YgdGhpcy5jb25maWdzKSB7XG4gICAgICAgICAgICBjb25maWcuaWZOb3RSZWdpc3RlcmVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogU3BlY2lmeSBwYXJhbWV0ZXIgdmFsdWVzIGZvciBjb25zdHJ1Y3RvciAocHJpbWl0aXZlcyBhbmQgY29uc3RhbnRzKVxuICAgICAqIFVzZSB0aGlzIGZvciBub24tREkgcGFyYW1ldGVycyBsaWtlIHN0cmluZ3MsIG51bWJlcnMsIGNvbmZpZyB2YWx1ZXNcbiAgICAgKi9cbiAgICB3aXRoUGFyYW1ldGVycyhwYXJhbWV0ZXJzKSB7XG4gICAgICAgIGZvciAoY29uc3QgY29uZmlnIG9mIHRoaXMuY29uZmlncykge1xuICAgICAgICAgICAgY29uZmlnLnBhcmFtZXRlclZhbHVlcyA9IHBhcmFtZXRlcnM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEVuYWJsZSBhdXRvbWF0aWMgZGVwZW5kZW5jeSBpbmplY3Rpb24gKGF1dG93aXJpbmcpXG4gICAgICogU3VwcG9ydHMgdGhyZWUgc3RyYXRlZ2llczogcGFyYW1OYW1lIChkZWZhdWx0KSwgbWFwLCBhbmQgY2xhc3NcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBgdHNcbiAgICAgKiAvLyBTdHJhdGVneSAxOiBwYXJhbU5hbWUgKGRlZmF1bHQsIHJlcXVpcmVzIG5vbi1taW5pZmllZCBjb2RlIGluIGRldilcbiAgICAgKiBidWlsZGVyLnJlZ2lzdGVyVHlwZShFdmVudEJ1cykuYXM8SUV2ZW50QnVzPigpLmF1dG9XaXJlKClcbiAgICAgKlxuICAgICAqIC8vIFN0cmF0ZWd5IDI6IG1hcCAobWluaWZ5LXNhZmUsIGV4cGxpY2l0KVxuICAgICAqIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKEV2ZW50QnVzKS5hczxJRXZlbnRCdXM+KCkuYXV0b1dpcmUoe1xuICAgICAqICAgbWFwOiB7XG4gICAgICogICAgIGxvZ2dlcjogKGMpID0+IGMucmVzb2x2ZVR5cGU8SUxvZ2dlcj4oKVxuICAgICAqICAgfVxuICAgICAqIH0pXG4gICAgICpcbiAgICAgKiAvLyBTdHJhdGVneSAzOiBjbGFzcyAocmVxdWlyZXMgYnVpbGQtdGltZSBjb2RlZ2VuKVxuICAgICAqIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKEV2ZW50QnVzKS5hczxJRXZlbnRCdXM+KCkuYXV0b1dpcmUoeyBieTogJ2NsYXNzJyB9KVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGF1dG9XaXJlKG9wdGlvbnMpIHtcbiAgICAgICAgZm9yIChjb25zdCBjb25maWcgb2YgdGhpcy5jb25maWdzKSB7XG4gICAgICAgICAgICBjb25maWcuYXV0b3dpcmVPcHRpb25zID0gb3B0aW9ucyB8fCB7IGJ5OiAncGFyYW1OYW1lJywgc3RyaWN0OiBmYWxzZSB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbn1cbi8qKlxuICogRmx1ZW50IGJ1aWxkZXIgZm9yIENvbnRhaW5lciBjb25maWd1cmF0aW9uXG4gKi9cbmV4cG9ydCBjbGFzcyBCdWlsZGVyIHtcbiAgICBjb25zdHJ1Y3RvcihiYXNlQ29udGFpbmVyKSB7XG4gICAgICAgIHRoaXMuYmFzZUNvbnRhaW5lciA9IGJhc2VDb250YWluZXI7XG4gICAgICAgIHRoaXMucmVnaXN0cmF0aW9ucyA9IFtdO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlciBhIGNsYXNzIGNvbnN0cnVjdG9yXG4gICAgICovXG4gICAgcmVnaXN0ZXJUeXBlKGNvbnN0cnVjdG9yKSB7XG4gICAgICAgIGNvbnN0IHBlbmRpbmcgPSB7XG4gICAgICAgICAgICB0eXBlOiAndHlwZScsXG4gICAgICAgICAgICB2YWx1ZTogbnVsbCxcbiAgICAgICAgICAgIGNvbnN0cnVjdG9yXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBuZXcgUmVnaXN0cmF0aW9uQnVpbGRlcihwZW5kaW5nLCB0aGlzLnJlZ2lzdHJhdGlvbnMpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlciBhIHByZS1jcmVhdGVkIGluc3RhbmNlXG4gICAgICovXG4gICAgcmVnaXN0ZXJJbnN0YW5jZShpbnN0YW5jZSkge1xuICAgICAgICBjb25zdCBwZW5kaW5nID0ge1xuICAgICAgICAgICAgdHlwZTogJ2luc3RhbmNlJyxcbiAgICAgICAgICAgIHZhbHVlOiBpbnN0YW5jZSxcbiAgICAgICAgICAgIGNvbnN0cnVjdG9yOiB1bmRlZmluZWRcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIG5ldyBSZWdpc3RyYXRpb25CdWlsZGVyKHBlbmRpbmcsIHRoaXMucmVnaXN0cmF0aW9ucyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVyIGEgZmFjdG9yeSBmdW5jdGlvblxuICAgICAqL1xuICAgIHJlZ2lzdGVyKGZhY3RvcnkpIHtcbiAgICAgICAgY29uc3QgcGVuZGluZyA9IHtcbiAgICAgICAgICAgIHR5cGU6ICdmYWN0b3J5JyxcbiAgICAgICAgICAgIHZhbHVlOiBudWxsLFxuICAgICAgICAgICAgZmFjdG9yeSxcbiAgICAgICAgICAgIGNvbnN0cnVjdG9yOiB1bmRlZmluZWRcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIG5ldyBSZWdpc3RyYXRpb25CdWlsZGVyKHBlbmRpbmcsIHRoaXMucmVnaXN0cmF0aW9ucyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVyIGEgbW9kdWxlIChmdW5jdGlvbiB0aGF0IGFkZHMgbXVsdGlwbGUgcmVnaXN0cmF0aW9ucylcbiAgICAgKi9cbiAgICBtb2R1bGUobW9kdWxlRnVuYykge1xuICAgICAgICBtb2R1bGVGdW5jKHRoaXMpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVzb2x2ZSBpbnRlcmZhY2UgdHlwZSBuYW1lcyB0byB0b2tlbnNcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICByZXNvbHZlSW50ZXJmYWNlVG9rZW5zKGNvbnRhaW5lcikge1xuICAgICAgICBmb3IgKGNvbnN0IGNvbmZpZyBvZiB0aGlzLnJlZ2lzdHJhdGlvbnMpIHtcbiAgICAgICAgICAgIGlmIChjb25maWcuaW50ZXJmYWNlVHlwZSAhPT0gdW5kZWZpbmVkICYmICFjb25maWcudG9rZW4pIHtcbiAgICAgICAgICAgICAgICBjb25maWcudG9rZW4gPSBjb250YWluZXIuaW50ZXJmYWNlVG9rZW4oY29uZmlnLmludGVyZmFjZVR5cGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIElkZW50aWZ5IHRva2VucyB0aGF0IGhhdmUgbm9uLWRlZmF1bHQgcmVnaXN0cmF0aW9uc1xuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGlkZW50aWZ5Tm9uRGVmYXVsdFRva2VucygpIHtcbiAgICAgICAgY29uc3QgdG9rZW5zV2l0aE5vbkRlZmF1bHRzID0gbmV3IFNldCgpO1xuICAgICAgICBmb3IgKGNvbnN0IGNvbmZpZyBvZiB0aGlzLnJlZ2lzdHJhdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghY29uZmlnLmlzRGVmYXVsdCAmJiAhY29uZmlnLm5hbWUgJiYgY29uZmlnLmtleSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdG9rZW5zV2l0aE5vbkRlZmF1bHRzLmFkZChjb25maWcudG9rZW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0b2tlbnNXaXRoTm9uRGVmYXVsdHM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIHJlZ2lzdHJhdGlvbiBzaG91bGQgYmUgc2tpcHBlZFxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIHNob3VsZFNraXBSZWdpc3RyYXRpb24oY29uZmlnLCB0b2tlbnNXaXRoTm9uRGVmYXVsdHMsIHJlZ2lzdGVyZWRUb2tlbnMpIHtcbiAgICAgICAgLy8gU2tpcCBkZWZhdWx0IHJlZ2lzdHJhdGlvbnMgaWYgdGhlcmUncyBhIG5vbi1kZWZhdWx0IGZvciB0aGUgc2FtZSB0b2tlblxuICAgICAgICBpZiAoY29uZmlnLmlzRGVmYXVsdCAmJiAhY29uZmlnLm5hbWUgJiYgY29uZmlnLmtleSA9PT0gdW5kZWZpbmVkICYmIHRva2Vuc1dpdGhOb25EZWZhdWx0cy5oYXMoY29uZmlnLnRva2VuKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gSGFuZGxlIGlmTm90UmVnaXN0ZXJlZFxuICAgICAgICBpZiAoY29uZmlnLmlmTm90UmVnaXN0ZXJlZCAmJiByZWdpc3RlcmVkVG9rZW5zLmhhcyhjb25maWcudG9rZW4pKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBIYW5kbGUgYXNEZWZhdWx0XG4gICAgICAgIGlmIChjb25maWcuaXNEZWZhdWx0ICYmIHJlZ2lzdGVyZWRUb2tlbnMuaGFzKGNvbmZpZy50b2tlbikpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGJpbmRpbmcgdG9rZW4gZm9yIHJlZ2lzdHJhdGlvbiAobmFtZWQsIGtleWVkLCBvciBtdWx0aSlcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBjcmVhdGVCaW5kaW5nVG9rZW4oY29uZmlnLCBuYW1lZFJlZ2lzdHJhdGlvbnMsIGtleWVkUmVnaXN0cmF0aW9ucywgbXVsdGlSZWdpc3RyYXRpb25zKSB7XG4gICAgICAgIGlmIChjb25maWcubmFtZSkge1xuICAgICAgICAgICAgLy8gTmFtZWQgcmVnaXN0cmF0aW9uIGdldHMgdW5pcXVlIHRva2VuXG4gICAgICAgICAgICBjb25zdCBiaW5kaW5nVG9rZW4gPSBUb2tlbihgX19uYW1lZF8ke2NvbmZpZy5uYW1lfWApO1xuICAgICAgICAgICAgbmFtZWRSZWdpc3RyYXRpb25zLnNldChjb25maWcubmFtZSwgeyAuLi5jb25maWcsIHRva2VuOiBiaW5kaW5nVG9rZW4gfSk7XG4gICAgICAgICAgICByZXR1cm4gYmluZGluZ1Rva2VuO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGNvbmZpZy5rZXkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgLy8gS2V5ZWQgcmVnaXN0cmF0aW9uIGdldHMgdW5pcXVlIHRva2VuXG4gICAgICAgICAgICBjb25zdCBrZXlTdHIgPSB0eXBlb2YgY29uZmlnLmtleSA9PT0gJ3N5bWJvbCcgPyBjb25maWcua2V5LnRvU3RyaW5nKCkgOiBjb25maWcua2V5O1xuICAgICAgICAgICAgY29uc3QgYmluZGluZ1Rva2VuID0gVG9rZW4oYF9fa2V5ZWRfJHtrZXlTdHJ9YCk7XG4gICAgICAgICAgICBrZXllZFJlZ2lzdHJhdGlvbnMuc2V0KGNvbmZpZy5rZXksIHsgLi4uY29uZmlnLCB0b2tlbjogYmluZGluZ1Rva2VuIH0pO1xuICAgICAgICAgICAgcmV0dXJuIGJpbmRpbmdUb2tlbjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIE11bHRpLXJlZ2lzdHJhdGlvbiBoYW5kbGluZ1xuICAgICAgICAgICAgaWYgKG11bHRpUmVnaXN0cmF0aW9ucy5oYXMoY29uZmlnLnRva2VuKSkge1xuICAgICAgICAgICAgICAgIC8vIFN1YnNlcXVlbnQgcmVnaXN0cmF0aW9uIGZvciB0aGlzIHRva2VuXG4gICAgICAgICAgICAgICAgY29uc3QgYmluZGluZ1Rva2VuID0gVG9rZW4oYF9fbXVsdGlfJHtjb25maWcudG9rZW4udG9TdHJpbmcoKX1fJHttdWx0aVJlZ2lzdHJhdGlvbnMuZ2V0KGNvbmZpZy50b2tlbikubGVuZ3RofWApO1xuICAgICAgICAgICAgICAgIG11bHRpUmVnaXN0cmF0aW9ucy5nZXQoY29uZmlnLnRva2VuKS5wdXNoKGJpbmRpbmdUb2tlbik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGJpbmRpbmdUb2tlbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIEZpcnN0IHJlZ2lzdHJhdGlvbiBmb3IgdGhpcyB0b2tlbiwgdXNlIHRoZSBvcmlnaW5hbCB0b2tlblxuICAgICAgICAgICAgICAgIG11bHRpUmVnaXN0cmF0aW9ucy5zZXQoY29uZmlnLnRva2VuLCBbY29uZmlnLnRva2VuXSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbmZpZy50b2tlbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlciBhZGRpdGlvbmFsIGludGVyZmFjZXMgZm9yIGEgY29uZmlnXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgcmVnaXN0ZXJBZGRpdGlvbmFsSW50ZXJmYWNlcyhjb250YWluZXIsIGNvbmZpZywgYmluZGluZ1Rva2VuLCByZWdpc3RlcmVkVG9rZW5zKSB7XG4gICAgICAgIGlmIChjb25maWcuYWRkaXRpb25hbFRva2Vucykge1xuICAgICAgICAgICAgZm9yIChjb25zdCBhZGRpdGlvbmFsVG9rZW4gb2YgY29uZmlnLmFkZGl0aW9uYWxUb2tlbnMpIHtcbiAgICAgICAgICAgICAgICAvLyBDcmVhdGUgYSBmYWN0b3J5IHRoYXQgcmVzb2x2ZXMgdGhlIGJpbmRpbmcgdG9rZW5cbiAgICAgICAgICAgICAgICBjb250YWluZXIuYmluZEZhY3RvcnkoYWRkaXRpb25hbFRva2VuLCAoYykgPT4gYy5yZXNvbHZlKGJpbmRpbmdUb2tlbiksIHsgbGlmZXRpbWU6IGNvbmZpZy5saWZldGltZSB9KTtcbiAgICAgICAgICAgICAgICByZWdpc3RlcmVkVG9rZW5zLmFkZChhZGRpdGlvbmFsVG9rZW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEJ1aWxkIHRoZSBjb250YWluZXIgd2l0aCBhbGwgcmVnaXN0ZXJlZCBiaW5kaW5nc1xuICAgICAqL1xuICAgIGJ1aWxkKCkge1xuICAgICAgICAvLyBDcmVhdGUgbmV3IGNvbnRhaW5lciBpbmhlcml0aW5nIGZyb20gYmFzZVxuICAgICAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLmJhc2VDb250YWluZXIuY3JlYXRlQ2hpbGQoKTtcbiAgICAgICAgLy8gUHJlLXByb2Nlc3M6IHJlc29sdmUgaW50ZXJmYWNlIHR5cGVzIHRvIHRva2Vuc1xuICAgICAgICB0aGlzLnJlc29sdmVJbnRlcmZhY2VUb2tlbnMoY29udGFpbmVyKTtcbiAgICAgICAgLy8gVHJhY2sgd2hhdCdzIGJlZW4gcmVnaXN0ZXJlZCBmb3IgaWZOb3RSZWdpc3RlcmVkIGNoZWNrc1xuICAgICAgICBjb25zdCByZWdpc3RlcmVkVG9rZW5zID0gbmV3IFNldCgpO1xuICAgICAgICBjb25zdCBuYW1lZFJlZ2lzdHJhdGlvbnMgPSBuZXcgTWFwKCk7XG4gICAgICAgIGNvbnN0IGtleWVkUmVnaXN0cmF0aW9ucyA9IG5ldyBNYXAoKTtcbiAgICAgICAgY29uc3QgbXVsdGlSZWdpc3RyYXRpb25zID0gbmV3IE1hcCgpO1xuICAgICAgICAvLyBQcmUtcHJvY2VzczogaWRlbnRpZnkgdG9rZW5zIHRoYXQgaGF2ZSBub24tZGVmYXVsdCByZWdpc3RyYXRpb25zXG4gICAgICAgIGNvbnN0IHRva2Vuc1dpdGhOb25EZWZhdWx0cyA9IHRoaXMuaWRlbnRpZnlOb25EZWZhdWx0VG9rZW5zKCk7XG4gICAgICAgIGZvciAoY29uc3QgY29uZmlnIG9mIHRoaXMucmVnaXN0cmF0aW9ucykge1xuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgcmVnaXN0cmF0aW9uIHNob3VsZCBiZSBza2lwcGVkXG4gICAgICAgICAgICBpZiAodGhpcy5zaG91bGRTa2lwUmVnaXN0cmF0aW9uKGNvbmZpZywgdG9rZW5zV2l0aE5vbkRlZmF1bHRzLCByZWdpc3RlcmVkVG9rZW5zKSkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQ3JlYXRlIGJpbmRpbmcgdG9rZW4gKG5hbWVkLCBrZXllZCwgb3IgbXVsdGkpXG4gICAgICAgICAgICBjb25zdCBiaW5kaW5nVG9rZW4gPSB0aGlzLmNyZWF0ZUJpbmRpbmdUb2tlbihjb25maWcsIG5hbWVkUmVnaXN0cmF0aW9ucywga2V5ZWRSZWdpc3RyYXRpb25zLCBtdWx0aVJlZ2lzdHJhdGlvbnMpO1xuICAgICAgICAgICAgLy8gQXBwbHkgcmVnaXN0cmF0aW9uIHRvIGNvbnRhaW5lciB1c2luZyB0aGUgYmluZGluZyB0b2tlblxuICAgICAgICAgICAgdGhpcy5hcHBseVJlZ2lzdHJhdGlvbihjb250YWluZXIsIHsgLi4uY29uZmlnLCB0b2tlbjogYmluZGluZ1Rva2VuIH0pO1xuICAgICAgICAgICAgLy8gTWFyayBvcmlnaW5hbCB0b2tlbiBhcyByZWdpc3RlcmVkXG4gICAgICAgICAgICByZWdpc3RlcmVkVG9rZW5zLmFkZChjb25maWcudG9rZW4pO1xuICAgICAgICAgICAgLy8gUmVnaXN0ZXIgYWRkaXRpb25hbCBpbnRlcmZhY2VzXG4gICAgICAgICAgICB0aGlzLnJlZ2lzdGVyQWRkaXRpb25hbEludGVyZmFjZXMoY29udGFpbmVyLCBjb25maWcsIGJpbmRpbmdUb2tlbiwgcmVnaXN0ZXJlZFRva2Vucyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQXR0YWNoIG1ldGFkYXRhIGZvciBuYW1lZC9rZXllZCByZXNvbHV0aW9uXG4gICAgICAgIDtcbiAgICAgICAgY29udGFpbmVyLl9fbmFtZWRSZWdpc3RyYXRpb25zID0gbmFtZWRSZWdpc3RyYXRpb25zO1xuICAgICAgICBjb250YWluZXIuX19rZXllZFJlZ2lzdHJhdGlvbnMgPSBrZXllZFJlZ2lzdHJhdGlvbnM7XG4gICAgICAgIGNvbnRhaW5lci5fX211bHRpUmVnaXN0cmF0aW9ucyA9IG11bHRpUmVnaXN0cmF0aW9ucztcbiAgICAgICAgcmV0dXJuIGNvbnRhaW5lcjtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQW5hbHl6ZSBjb25zdHJ1Y3RvciB0byBkZXRlY3QgZGVwZW5kZW5jaWVzXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgYW5hbHl6ZUNvbnN0cnVjdG9yKGNvbnN0cnVjdG9yKSB7XG4gICAgICAgIGNvbnN0IGNvbnN0cnVjdG9yU3RyID0gY29uc3RydWN0b3IudG9TdHJpbmcoKTtcbiAgICAgICAgY29uc3QgaGFzRGVwZW5kZW5jaWVzID0gL2NvbnN0cnVjdG9yXFxzKlxcKFteKV0rXFwpLy50ZXN0KGNvbnN0cnVjdG9yU3RyKTtcbiAgICAgICAgcmV0dXJuIHsgaGFzRGVwZW5kZW5jaWVzIH07XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBvcHRpbWl6ZWQgZmFjdG9yeSBmb3IgemVyby1kZXBlbmRlbmN5IGNvbnN0cnVjdG9yc1xuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGNyZWF0ZU9wdGltaXplZEZhY3RvcnkoY29udGFpbmVyLCBjb25maWcsIG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKGNvbmZpZy5saWZldGltZSA9PT0gJ3NpbmdsZXRvbicpIHtcbiAgICAgICAgICAgIC8vIFNpbmdsZXRvbjogQ3JlYXRlIGluc3RhbmNlIGRpcmVjdGx5IChmYXN0ZXN0IHBhdGggLSBubyBmYWN0b3J5IG92ZXJoZWFkKVxuICAgICAgICAgICAgY29uc3QgaW5zdGFuY2UgPSBuZXcgY29uZmlnLmNvbnN0cnVjdG9yKCk7XG4gICAgICAgICAgICBjb250YWluZXIuYmluZFZhbHVlKGNvbmZpZy50b2tlbiwgaW5zdGFuY2UpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGNvbmZpZy5saWZldGltZSA9PT0gJ3RyYW5zaWVudCcpIHtcbiAgICAgICAgICAgIC8vIFRyYW5zaWVudCBGYXN0IFBhdGg6IFJlZ2lzdGVyIGluIGZhc3QgdHJhbnNpZW50IGNhY2hlXG4gICAgICAgICAgICBjb25zdCBjdG9yID0gY29uZmlnLmNvbnN0cnVjdG9yO1xuICAgICAgICAgICAgY29uc3QgZmFzdEZhY3RvcnkgPSAoKSA9PiBuZXcgY3RvcigpO1xuICAgICAgICAgICAgY29udGFpbmVyLmZhc3RUcmFuc2llbnRDYWNoZS5zZXQoY29uZmlnLnRva2VuLCBmYXN0RmFjdG9yeSk7XG4gICAgICAgICAgICBjb250YWluZXIuYmluZEZhY3RvcnkoY29uZmlnLnRva2VuLCBmYXN0RmFjdG9yeSwgb3B0aW9ucyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBQZXItcmVxdWVzdDogVXNlIHNpbXBsZSBmYWN0b3J5IHdpdGhvdXQgYXV0b3dpcmUgb3ZlcmhlYWRcbiAgICAgICAgICAgIGNvbnN0IGZhY3RvcnkgPSAoKSA9PiBuZXcgY29uZmlnLmNvbnN0cnVjdG9yKCk7XG4gICAgICAgICAgICBjb250YWluZXIuYmluZEZhY3RvcnkoY29uZmlnLnRva2VuLCBmYWN0b3J5LCBvcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgYXV0b3dpcmUgZmFjdG9yeVxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGNyZWF0ZUF1dG9XaXJlRmFjdG9yeShjb250YWluZXIsIGNvbmZpZywgb3B0aW9ucykge1xuICAgICAgICBjb25zdCBmYWN0b3J5ID0gKGMpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc29sdmVkRGVwcyA9IGF1dG93aXJlKGNvbmZpZy5jb25zdHJ1Y3RvciwgYywgY29uZmlnLmF1dG93aXJlT3B0aW9ucyk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IGNvbmZpZy5jb25zdHJ1Y3RvciguLi5yZXNvbHZlZERlcHMpO1xuICAgICAgICB9O1xuICAgICAgICBjb250YWluZXIuYmluZEZhY3RvcnkoY29uZmlnLnRva2VuLCBmYWN0b3J5LCBvcHRpb25zKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ3JlYXRlIHdpdGhQYXJhbWV0ZXJzIGZhY3RvcnlcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBjcmVhdGVQYXJhbWV0ZXJGYWN0b3J5KGNvbnRhaW5lciwgY29uZmlnLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGZhY3RvcnkgPSAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZXMgPSBPYmplY3QudmFsdWVzKGNvbmZpZy5wYXJhbWV0ZXJWYWx1ZXMpO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBjb25maWcuY29uc3RydWN0b3IoLi4udmFsdWVzKTtcbiAgICAgICAgfTtcbiAgICAgICAgY29udGFpbmVyLmJpbmRGYWN0b3J5KGNvbmZpZy50b2tlbiwgZmFjdG9yeSwgb3B0aW9ucyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFwcGx5IHR5cGUgcmVnaXN0cmF0aW9uIChjbGFzcyBjb25zdHJ1Y3RvcilcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBhcHBseVR5cGVSZWdpc3RyYXRpb24oY29udGFpbmVyLCBjb25maWcsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgeyBoYXNEZXBlbmRlbmNpZXMgfSA9IHRoaXMuYW5hbHl6ZUNvbnN0cnVjdG9yKGNvbmZpZy5jb25zdHJ1Y3Rvcik7XG4gICAgICAgIC8vIEZhc3QgcGF0aDogTm8gZGVwZW5kZW5jaWVzIGFuZCBubyBzcGVjaWFsIGNvbmZpZ1xuICAgICAgICBpZiAoIWhhc0RlcGVuZGVuY2llcyAmJiAhY29uZmlnLmF1dG93aXJlT3B0aW9ucyAmJiAhY29uZmlnLnBhcmFtZXRlclZhbHVlcykge1xuICAgICAgICAgICAgdGhpcy5jcmVhdGVPcHRpbWl6ZWRGYWN0b3J5KGNvbnRhaW5lciwgY29uZmlnLCBvcHRpb25zKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBBdXRvV2lyZSBwYXRoXG4gICAgICAgIGlmIChjb25maWcuYXV0b3dpcmVPcHRpb25zKSB7XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZUF1dG9XaXJlRmFjdG9yeShjb250YWluZXIsIGNvbmZpZywgb3B0aW9ucyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gd2l0aFBhcmFtZXRlcnMgcGF0aFxuICAgICAgICBpZiAoY29uZmlnLnBhcmFtZXRlclZhbHVlcykge1xuICAgICAgICAgICAgdGhpcy5jcmVhdGVQYXJhbWV0ZXJGYWN0b3J5KGNvbnRhaW5lciwgY29uZmlnLCBvcHRpb25zKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBFcnJvcjogQ29uc3RydWN0b3IgaGFzIGRlcGVuZGVuY2llcyBidXQgbm8gY29uZmlnXG4gICAgICAgIGlmIChoYXNEZXBlbmRlbmNpZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IGNsYXNzTmFtZSA9IGNvbmZpZy5jb25zdHJ1Y3Rvci5uYW1lIHx8ICdVbm5hbWVkQ2xhc3MnO1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBTZXJ2aWNlIFwiJHtjbGFzc05hbWV9XCIgaGFzIGNvbnN0cnVjdG9yIGRlcGVuZGVuY2llcyBidXQgbm8gYXV0b3dpcmluZyBjb25maWd1cmF0aW9uLlxcblxcbmAgK1xuICAgICAgICAgICAgICAgIGBTb2x1dGlvbnM6XFxuYCArXG4gICAgICAgICAgICAgICAgYCAgMS4gXHUyQjUwIFVzZSB0aGUgTm92YURJIHRyYW5zZm9ybWVyIChyZWNvbW1lbmRlZCk6XFxuYCArXG4gICAgICAgICAgICAgICAgYCAgICAgLSBBZGQgXCJAbm92YWRpL2NvcmUvdW5wbHVnaW5cIiB0byB5b3VyIGJ1aWxkIGNvbmZpZ1xcbmAgK1xuICAgICAgICAgICAgICAgIGAgICAgIC0gVHJhbnNmb3JtZXIgYXV0b21hdGljYWxseSBnZW5lcmF0ZXMgLmF1dG9XaXJlKCkgZm9yIGFsbCBkZXBlbmRlbmNpZXNcXG5cXG5gICtcbiAgICAgICAgICAgICAgICBgICAyLiBBZGQgbWFudWFsIGF1dG93aXJpbmc6XFxuYCArXG4gICAgICAgICAgICAgICAgYCAgICAgLmF1dG9XaXJlKHsgbWFwOiB7IC8qIHBhcmFtOiByZXNvbHZlciAqLyB9IH0pXFxuXFxuYCArXG4gICAgICAgICAgICAgICAgYCAgMy4gVXNlIGEgZmFjdG9yeSBmdW5jdGlvbjpcXG5gICtcbiAgICAgICAgICAgICAgICBgICAgICAucmVnaXN0ZXIoKGMpID0+IG5ldyAke2NsYXNzTmFtZX0oLi4uKSlcXG5cXG5gICtcbiAgICAgICAgICAgICAgICBgU2VlIGRvY3M6IGh0dHBzOi8vZ2l0aHViLmNvbS9qYW51czAwNy9Ob3ZhREkjYXV0b3dpcmVgKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBObyBkZXBlbmRlbmNpZXMgLSBjcmVhdGUgc2ltcGxlIGZhY3RvcnlcbiAgICAgICAgY29uc3QgZmFjdG9yeSA9ICgpID0+IG5ldyBjb25maWcuY29uc3RydWN0b3IoKTtcbiAgICAgICAgY29udGFpbmVyLmJpbmRGYWN0b3J5KGNvbmZpZy50b2tlbiwgZmFjdG9yeSwgb3B0aW9ucyk7XG4gICAgfVxuICAgIGFwcGx5UmVnaXN0cmF0aW9uKGNvbnRhaW5lciwgY29uZmlnKSB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7IGxpZmV0aW1lOiBjb25maWcubGlmZXRpbWUgfTtcbiAgICAgICAgc3dpdGNoIChjb25maWcudHlwZSkge1xuICAgICAgICAgICAgY2FzZSAnaW5zdGFuY2UnOlxuICAgICAgICAgICAgICAgIGNvbnRhaW5lci5iaW5kVmFsdWUoY29uZmlnLnRva2VuLCBjb25maWcudmFsdWUpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZmFjdG9yeSc6XG4gICAgICAgICAgICAgICAgY29udGFpbmVyLmJpbmRGYWN0b3J5KGNvbmZpZy50b2tlbiwgY29uZmlnLmZhY3RvcnksIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAndHlwZSc6XG4gICAgICAgICAgICAgICAgdGhpcy5hcHBseVR5cGVSZWdpc3RyYXRpb24oY29udGFpbmVyLCBjb25maWcsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwgIi8qKlxuICogQ29yZSBkZXBlbmRlbmN5IGluamVjdGlvbiBjb250YWluZXIgZm9yIE5vdmFESVxuICovXG5pbXBvcnQgeyBUb2tlbiB9IGZyb20gJy4vdG9rZW4uanMnO1xuaW1wb3J0IHsgQmluZGluZ05vdEZvdW5kRXJyb3IsIENpcmN1bGFyRGVwZW5kZW5jeUVycm9yIH0gZnJvbSAnLi9lcnJvcnMuanMnO1xuaW1wb3J0IHsgQnVpbGRlciB9IGZyb20gJy4vYnVpbGRlci5qcyc7XG5mdW5jdGlvbiBpc0Rpc3Bvc2FibGUob2JqKSB7XG4gICAgcmV0dXJuIG9iaiAmJiB0eXBlb2Ygb2JqLmRpc3Bvc2UgPT09ICdmdW5jdGlvbic7XG59XG4vKipcbiAqIFJlc29sdXRpb24gY29udGV4dCB0cmFja3MgdGhlIGN1cnJlbnQgZGVwZW5kZW5jeSByZXNvbHV0aW9uIHBhdGhcbiAqIGZvciBjaXJjdWxhciBkZXBlbmRlbmN5IGRldGVjdGlvbiBhbmQgcGVyLXJlcXVlc3Qgc2NvcGluZ1xuICovXG5jbGFzcyBSZXNvbHV0aW9uQ29udGV4dCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMucmVzb2x2aW5nU3RhY2sgPSBuZXcgU2V0KCk7XG4gICAgICAgIHRoaXMucGVyUmVxdWVzdENhY2hlID0gbmV3IE1hcCgpO1xuICAgIH1cbiAgICBpc1Jlc29sdmluZyh0b2tlbikge1xuICAgICAgICByZXR1cm4gdGhpcy5yZXNvbHZpbmdTdGFjay5oYXModG9rZW4pO1xuICAgIH1cbiAgICBlbnRlclJlc29sdmUodG9rZW4pIHtcbiAgICAgICAgdGhpcy5yZXNvbHZpbmdTdGFjay5hZGQodG9rZW4pO1xuICAgICAgICAvLyBQZXJmb3JtYW5jZTogRG9uJ3QgYnVpbGQgcGF0aCB1bmxlc3Mgd2UgbmVlZCBpdCAob25seSB1c2VkIGluIGVycm9yIG1lc3NhZ2VzKVxuICAgICAgICAvLyBUaGlzIGF2b2lkcyBleHBlbnNpdmUgdG9rZW4udG9TdHJpbmcoKSBjYWxscyBvbiBldmVyeSByZXNvbHZlXG4gICAgfVxuICAgIGV4aXRSZXNvbHZlKHRva2VuKSB7XG4gICAgICAgIHRoaXMucmVzb2x2aW5nU3RhY2suZGVsZXRlKHRva2VuKTtcbiAgICAgICAgLy8gUGVyZm9ybWFuY2U6IENsZWFyIGxhenkgcGF0aCBjYWNoZSB3aGVuIGV4aXRpbmdcbiAgICAgICAgdGhpcy5wYXRoID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBnZXRQYXRoKCkge1xuICAgICAgICAvLyBQZXJmb3JtYW5jZTogQnVpbGQgcGF0aCBvbi1kZW1hbmQgb25seSB3aGVuIG5lZWRlZCAodHlwaWNhbGx5IGZvciBlcnJvciBtZXNzYWdlcylcbiAgICAgICAgaWYgKCF0aGlzLnBhdGgpIHtcbiAgICAgICAgICAgIHRoaXMucGF0aCA9IEFycmF5LmZyb20odGhpcy5yZXNvbHZpbmdTdGFjaykubWFwKHQgPT4gdC50b1N0cmluZygpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gWy4uLnRoaXMucGF0aF07XG4gICAgfVxuICAgIGNhY2hlUGVyUmVxdWVzdCh0b2tlbiwgaW5zdGFuY2UpIHtcbiAgICAgICAgdGhpcy5wZXJSZXF1ZXN0Q2FjaGUuc2V0KHRva2VuLCBpbnN0YW5jZSk7XG4gICAgfVxuICAgIGdldFBlclJlcXVlc3QodG9rZW4pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGVyUmVxdWVzdENhY2hlLmdldCh0b2tlbik7XG4gICAgfVxuICAgIGhhc1BlclJlcXVlc3QodG9rZW4pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGVyUmVxdWVzdENhY2hlLmhhcyh0b2tlbik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlc2V0IGNvbnRleHQgZm9yIHJldXNlIGluIG9iamVjdCBwb29sXG4gICAgICogUGVyZm9ybWFuY2U6IFJldXNpbmcgY29udGV4dHMgYXZvaWRzIGhlYXAgYWxsb2NhdGlvbnNcbiAgICAgKi9cbiAgICByZXNldCgpIHtcbiAgICAgICAgdGhpcy5yZXNvbHZpbmdTdGFjay5jbGVhcigpO1xuICAgICAgICB0aGlzLnBlclJlcXVlc3RDYWNoZS5jbGVhcigpO1xuICAgICAgICB0aGlzLnBhdGggPSB1bmRlZmluZWQ7XG4gICAgfVxufVxuLyoqXG4gKiBPYmplY3QgcG9vbCBmb3IgUmVzb2x1dGlvbkNvbnRleHQgaW5zdGFuY2VzXG4gKiBQZXJmb3JtYW5jZTogUmV1c2luZyBjb250ZXh0cyByZWR1Y2VzIGhlYXAgYWxsb2NhdGlvbnMgYW5kIEdDIHByZXNzdXJlXG4gKi9cbmNsYXNzIFJlc29sdXRpb25Db250ZXh0UG9vbCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMucG9vbCA9IFtdO1xuICAgICAgICB0aGlzLm1heFNpemUgPSAxMDtcbiAgICB9XG4gICAgYWNxdWlyZSgpIHtcbiAgICAgICAgY29uc3QgY29udGV4dCA9IHRoaXMucG9vbC5wb3AoKTtcbiAgICAgICAgaWYgKGNvbnRleHQpIHtcbiAgICAgICAgICAgIC8vIFJlc2V0IGV4aXN0aW5nIGNvbnRleHQgZm9yIHJldXNlXG4gICAgICAgICAgICBjb250ZXh0LnJlc2V0KCk7XG4gICAgICAgICAgICByZXR1cm4gY29udGV4dDtcbiAgICAgICAgfVxuICAgICAgICAvLyBDcmVhdGUgbmV3IGlmIHBvb2wgZW1wdHlcbiAgICAgICAgcmV0dXJuIG5ldyBSZXNvbHV0aW9uQ29udGV4dCgpO1xuICAgIH1cbiAgICByZWxlYXNlKGNvbnRleHQpIHtcbiAgICAgICAgaWYgKHRoaXMucG9vbC5sZW5ndGggPCB0aGlzLm1heFNpemUpIHtcbiAgICAgICAgICAgIHRoaXMucG9vbC5wdXNoKGNvbnRleHQpO1xuICAgICAgICB9XG4gICAgICAgIC8vIE90aGVyd2lzZSBsZXQgaXQgYmUgR0MnZFxuICAgIH1cbn1cbi8qKlxuICogRGVwZW5kZW5jeSBJbmplY3Rpb24gQ29udGFpbmVyXG4gKlxuICogTWFuYWdlcyByZWdpc3RyYXRpb24gYW5kIHJlc29sdXRpb24gb2YgZGVwZW5kZW5jaWVzIHdpdGggc3VwcG9ydCBmb3I6XG4gKiAtIE11bHRpcGxlIGJpbmRpbmcgdHlwZXMgKHZhbHVlLCBmYWN0b3J5LCBjbGFzcylcbiAqIC0gTGlmZXRpbWUgbWFuYWdlbWVudCAoc2luZ2xldG9uLCB0cmFuc2llbnQsIHBlci1yZXF1ZXN0KVxuICogLSBDaGlsZCBjb250YWluZXJzIHdpdGggaW5oZXJpdGFuY2VcbiAqIC0gQ2lyY3VsYXIgZGVwZW5kZW5jeSBkZXRlY3Rpb25cbiAqIC0gQXV0b21hdGljIGRpc3Bvc2FsXG4gKi9cbmV4cG9ydCBjbGFzcyBDb250YWluZXIge1xuICAgIGNvbnN0cnVjdG9yKHBhcmVudCkge1xuICAgICAgICB0aGlzLmJpbmRpbmdzID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLnNpbmdsZXRvbkNhY2hlID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLnNpbmdsZXRvbk9yZGVyID0gW107XG4gICAgICAgIHRoaXMuaW50ZXJmYWNlUmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMuaW50ZXJmYWNlVG9rZW5DYWNoZSA9IG5ldyBNYXAoKTsgLy8gUGVyZm9ybWFuY2U6IENhY2hlIGZvciByZXNvbHZlVHlwZSgpIGxvb2t1cHNcbiAgICAgICAgdGhpcy5mYXN0VHJhbnNpZW50Q2FjaGUgPSBuZXcgTWFwKCk7IC8vIFBlcmZvcm1hbmNlOiBGYXN0IHBhdGggZm9yIHNpbXBsZSB0cmFuc2llbnRzXG4gICAgICAgIHRoaXMudWx0cmFGYXN0U2luZ2xldG9uQ2FjaGUgPSBuZXcgTWFwKCk7IC8vIFBlcmZvcm1hbmNlOiBVbHRyYS1mYXN0IHNpbmdsZXRvbi1vbmx5IGNhY2hlXG4gICAgICAgIHRoaXMucGFyZW50ID0gcGFyZW50O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBCaW5kIGEgcHJlLWNyZWF0ZWQgdmFsdWUgdG8gYSB0b2tlblxuICAgICAqL1xuICAgIGJpbmRWYWx1ZSh0b2tlbiwgdmFsdWUpIHtcbiAgICAgICAgdGhpcy5iaW5kaW5ncy5zZXQodG9rZW4sIHtcbiAgICAgICAgICAgIHR5cGU6ICd2YWx1ZScsXG4gICAgICAgICAgICBsaWZldGltZTogJ3NpbmdsZXRvbicsXG4gICAgICAgICAgICB2YWx1ZSxcbiAgICAgICAgICAgIGNvbnN0cnVjdG9yOiB1bmRlZmluZWRcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuaW52YWxpZGF0ZUJpbmRpbmdDYWNoZSgpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBCaW5kIGEgZmFjdG9yeSBmdW5jdGlvbiB0byBhIHRva2VuXG4gICAgICovXG4gICAgYmluZEZhY3RvcnkodG9rZW4sIGZhY3RvcnksIG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5iaW5kaW5ncy5zZXQodG9rZW4sIHtcbiAgICAgICAgICAgIHR5cGU6ICdmYWN0b3J5JyxcbiAgICAgICAgICAgIGxpZmV0aW1lOiBvcHRpb25zPy5saWZldGltZSB8fCAndHJhbnNpZW50JyxcbiAgICAgICAgICAgIGZhY3RvcnksXG4gICAgICAgICAgICBkZXBlbmRlbmNpZXM6IG9wdGlvbnM/LmRlcGVuZGVuY2llcyxcbiAgICAgICAgICAgIGNvbnN0cnVjdG9yOiB1bmRlZmluZWRcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuaW52YWxpZGF0ZUJpbmRpbmdDYWNoZSgpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBCaW5kIGEgY2xhc3MgY29uc3RydWN0b3IgdG8gYSB0b2tlblxuICAgICAqL1xuICAgIGJpbmRDbGFzcyh0b2tlbiwgY29uc3RydWN0b3IsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgYmluZGluZyA9IHtcbiAgICAgICAgICAgIHR5cGU6ICdjbGFzcycsXG4gICAgICAgICAgICBsaWZldGltZTogb3B0aW9ucz8ubGlmZXRpbWUgfHwgJ3RyYW5zaWVudCcsXG4gICAgICAgICAgICBjb25zdHJ1Y3RvcixcbiAgICAgICAgICAgIGRlcGVuZGVuY2llczogb3B0aW9ucz8uZGVwZW5kZW5jaWVzXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuYmluZGluZ3Muc2V0KHRva2VuLCBiaW5kaW5nKTtcbiAgICAgICAgdGhpcy5pbnZhbGlkYXRlQmluZGluZ0NhY2hlKCk7XG4gICAgICAgIC8vIFBlcmZvcm1hbmNlOiBQcmUtY29tcGlsZSBmYXN0IHRyYW5zaWVudCBmYWN0b3J5IGZvciB6ZXJvLWRlcGVuZGVuY3kgY2xhc3Nlc1xuICAgICAgICBpZiAoYmluZGluZy5saWZldGltZSA9PT0gJ3RyYW5zaWVudCcgJiYgKCFiaW5kaW5nLmRlcGVuZGVuY2llcyB8fCBiaW5kaW5nLmRlcGVuZGVuY2llcy5sZW5ndGggPT09IDApKSB7XG4gICAgICAgICAgICB0aGlzLmZhc3RUcmFuc2llbnRDYWNoZS5zZXQodG9rZW4sICgpID0+IG5ldyBjb25zdHJ1Y3RvcigpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXNvbHZlIGEgZGVwZW5kZW5jeSBzeW5jaHJvbm91c2x5XG4gICAgICogUGVyZm9ybWFuY2Ugb3B0aW1pemVkIHdpdGggbXVsdGlwbGUgZmFzdCBwYXRoc1xuICAgICAqL1xuICAgIHJlc29sdmUodG9rZW4pIHtcbiAgICAgICAgLy8gVHJ5IGFsbCBjYWNoZSBsZXZlbHMgZmlyc3QgKHVsdHJhLWZhc3QsIHNpbmdsZXRvbiwgZmFzdCB0cmFuc2llbnQpXG4gICAgICAgIGNvbnN0IGNhY2hlZCA9IHRoaXMudHJ5R2V0RnJvbUNhY2hlcyh0b2tlbik7XG4gICAgICAgIGlmIChjYWNoZWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZDtcbiAgICAgICAgfVxuICAgICAgICAvLyBJZiB3ZSdyZSBhbHJlYWR5IHJlc29sdmluZyAoY2FsbGVkIGZyb20gd2l0aGluIGEgZmFjdG9yeSksIHJldXNlIHRoZSBjb250ZXh0XG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRDb250ZXh0KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZXNvbHZlV2l0aENvbnRleHQodG9rZW4sIHRoaXMuY3VycmVudENvbnRleHQpO1xuICAgICAgICB9XG4gICAgICAgIC8vIENvbXBsZXggcmVzb2x1dGlvbiB3aXRoIHBvb2xlZCBjb250ZXh0XG4gICAgICAgIGNvbnN0IGNvbnRleHQgPSBDb250YWluZXIuY29udGV4dFBvb2wuYWNxdWlyZSgpO1xuICAgICAgICB0aGlzLmN1cnJlbnRDb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlc29sdmVXaXRoQ29udGV4dCh0b2tlbiwgY29udGV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgZmluYWxseSB7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRDb250ZXh0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgQ29udGFpbmVyLmNvbnRleHRQb29sLnJlbGVhc2UoY29udGV4dCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogU1BFQ0lBTElaRUQ6IFVsdHJhLWZhc3Qgc2luZ2xldG9uIHJlc29sdmUgKG5vIHNhZmV0eSBjaGVja3MpXG4gICAgICogVXNlIE9OTFkgd2hlbiB5b3UncmUgMTAwJSBzdXJlIHRoZSB0b2tlbiBpcyBhIHJlZ2lzdGVyZWQgc2luZ2xldG9uXG4gICAgICogQGludGVybmFsIEZvciBwZXJmb3JtYW5jZS1jcml0aWNhbCBwYXRocyBvbmx5XG4gICAgICovXG4gICAgcmVzb2x2ZVNpbmdsZXRvblVuc2FmZSh0b2tlbikge1xuICAgICAgICAvLyBEaXJlY3QgcmV0dXJuLCBubyBjaGVja3MgLSBtYXhpbXVtIHNwZWVkXG4gICAgICAgIHJldHVybiB0aGlzLnVsdHJhRmFzdFNpbmdsZXRvbkNhY2hlLmdldCh0b2tlbikgPz8gdGhpcy5zaW5nbGV0b25DYWNoZS5nZXQodG9rZW4pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTUEVDSUFMSVpFRDogRmFzdCB0cmFuc2llbnQgcmVzb2x2ZSBmb3IgemVyby1kZXBlbmRlbmN5IGNsYXNzZXNcbiAgICAgKiBTa2lwcyBhbGwgY29udGV4dCBjcmVhdGlvbiBhbmQgY2lyY3VsYXIgZGVwZW5kZW5jeSBjaGVja3NcbiAgICAgKiBAaW50ZXJuYWwgRm9yIHBlcmZvcm1hbmNlLWNyaXRpY2FsIHBhdGhzIG9ubHlcbiAgICAgKi9cbiAgICByZXNvbHZlVHJhbnNpZW50U2ltcGxlKHRva2VuKSB7XG4gICAgICAgIGNvbnN0IGZhY3RvcnkgPSB0aGlzLmZhc3RUcmFuc2llbnRDYWNoZS5nZXQodG9rZW4pO1xuICAgICAgICBpZiAoZmFjdG9yeSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhY3RvcnkoKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBGYWxsYmFjayB0byByZWd1bGFyIHJlc29sdmUgaWYgbm90IGluIGZhc3QgY2FjaGVcbiAgICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZSh0b2tlbik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNQRUNJQUxJWkVEOiBCYXRjaCByZXNvbHZlIG11bHRpcGxlIGRlcGVuZGVuY2llcyBhdCBvbmNlXG4gICAgICogTW9yZSBlZmZpY2llbnQgdGhhbiBtdWx0aXBsZSBpbmRpdmlkdWFsIHJlc29sdmVzXG4gICAgICovXG4gICAgcmVzb2x2ZUJhdGNoKHRva2Vucykge1xuICAgICAgICAvLyBSZXVzZSBzaW5nbGUgY29udGV4dCBmb3IgYWxsIHJlc29sdXRpb25zXG4gICAgICAgIGNvbnN0IHdhc1Jlc29sdmluZyA9ICEhdGhpcy5jdXJyZW50Q29udGV4dDtcbiAgICAgICAgY29uc3QgY29udGV4dCA9IHRoaXMuY3VycmVudENvbnRleHQgfHwgQ29udGFpbmVyLmNvbnRleHRQb29sLmFjcXVpcmUoKTtcbiAgICAgICAgaWYgKCF3YXNSZXNvbHZpbmcpIHtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudENvbnRleHQgPSBjb250ZXh0O1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZXN1bHRzID0gdG9rZW5zLm1hcCh0b2tlbiA9PiB7XG4gICAgICAgICAgICAgICAgLy8gVHJ5IGFsbCBjYWNoZSBsZXZlbHMgZmlyc3RcbiAgICAgICAgICAgICAgICBjb25zdCBjYWNoZWQgPSB0aGlzLnRyeUdldEZyb21DYWNoZXModG9rZW4pO1xuICAgICAgICAgICAgICAgIGlmIChjYWNoZWQgIT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNhY2hlZDtcbiAgICAgICAgICAgICAgICAvLyBGdWxsIHJlc29sdmUgd2l0aCBzaGFyZWQgY29udGV4dFxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJlc29sdmVXaXRoQ29udGV4dCh0b2tlbiwgY29udGV4dCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHRzO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkge1xuICAgICAgICAgICAgaWYgKCF3YXNSZXNvbHZpbmcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRDb250ZXh0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIENvbnRhaW5lci5jb250ZXh0UG9vbC5yZWxlYXNlKGNvbnRleHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlc29sdmUgYSBkZXBlbmRlbmN5IGFzeW5jaHJvbm91c2x5IChzdXBwb3J0cyBhc3luYyBmYWN0b3JpZXMpXG4gICAgICovXG4gICAgYXN5bmMgcmVzb2x2ZUFzeW5jKHRva2VuKSB7XG4gICAgICAgIC8vIElmIHdlJ3JlIGFscmVhZHkgcmVzb2x2aW5nIChjYWxsZWQgZnJvbSB3aXRoaW4gYSBmYWN0b3J5KSwgcmV1c2UgdGhlIGNvbnRleHRcbiAgICAgICAgaWYgKHRoaXMuY3VycmVudENvbnRleHQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlc29sdmVBc3luY1dpdGhDb250ZXh0KHRva2VuLCB0aGlzLmN1cnJlbnRDb250ZXh0KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBOZXcgdG9wLWxldmVsIHJlc29sdmVcbiAgICAgICAgLy8gUGVyZm9ybWFuY2U6IFVzZSBwb29sZWQgY29udGV4dCB0byBhdm9pZCBoZWFwIGFsbG9jYXRpb25cbiAgICAgICAgY29uc3QgY29udGV4dCA9IENvbnRhaW5lci5jb250ZXh0UG9vbC5hY3F1aXJlKCk7XG4gICAgICAgIHRoaXMuY3VycmVudENvbnRleHQgPSBjb250ZXh0O1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMucmVzb2x2ZUFzeW5jV2l0aENvbnRleHQodG9rZW4sIGNvbnRleHQpO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkge1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50Q29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIENvbnRhaW5lci5jb250ZXh0UG9vbC5yZWxlYXNlKGNvbnRleHQpOyAvLyBSZXR1cm4gdG8gcG9vbCBmb3IgcmV1c2VcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBUcnkgdG8gZ2V0IGluc3RhbmNlIGZyb20gYWxsIGNhY2hlIGxldmVsc1xuICAgICAqIFJldHVybnMgdW5kZWZpbmVkIGlmIG5vdCBjYWNoZWRcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICB0cnlHZXRGcm9tQ2FjaGVzKHRva2VuKSB7XG4gICAgICAgIC8vIExldmVsIDE6IFVsdHJhLWZhc3Qgc2luZ2xldG9uIGNhY2hlICh6ZXJvIG92ZXJoZWFkKVxuICAgICAgICBjb25zdCB1bHRyYUZhc3QgPSB0aGlzLnVsdHJhRmFzdFNpbmdsZXRvbkNhY2hlLmdldCh0b2tlbik7XG4gICAgICAgIGlmICh1bHRyYUZhc3QgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIHVsdHJhRmFzdDtcbiAgICAgICAgfVxuICAgICAgICAvLyBMZXZlbCAyOiBSZWd1bGFyIHNpbmdsZXRvbiBjYWNoZVxuICAgICAgICBpZiAodGhpcy5zaW5nbGV0b25DYWNoZS5oYXModG9rZW4pKSB7XG4gICAgICAgICAgICBjb25zdCBjYWNoZWQgPSB0aGlzLnNpbmdsZXRvbkNhY2hlLmdldCh0b2tlbik7XG4gICAgICAgICAgICAvLyBQcm9tb3RlIHRvIHVsdHJhLWZhc3QgY2FjaGUgZm9yIG5leHQgdGltZVxuICAgICAgICAgICAgdGhpcy51bHRyYUZhc3RTaW5nbGV0b25DYWNoZS5zZXQodG9rZW4sIGNhY2hlZCk7XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkO1xuICAgICAgICB9XG4gICAgICAgIC8vIExldmVsIDM6IEZhc3QgdHJhbnNpZW50IGNhY2hlIChubyBkZXBlbmRlbmNpZXMpXG4gICAgICAgIGNvbnN0IGZhc3RGYWN0b3J5ID0gdGhpcy5mYXN0VHJhbnNpZW50Q2FjaGUuZ2V0KHRva2VuKTtcbiAgICAgICAgaWYgKGZhc3RGYWN0b3J5KSB7XG4gICAgICAgICAgICByZXR1cm4gZmFzdEZhY3RvcnkoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDYWNoZSBpbnN0YW5jZSBiYXNlZCBvbiBsaWZldGltZSBzdHJhdGVneVxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGNhY2hlSW5zdGFuY2UodG9rZW4sIGluc3RhbmNlLCBsaWZldGltZSwgY29udGV4dCkge1xuICAgICAgICBpZiAobGlmZXRpbWUgPT09ICdzaW5nbGV0b24nKSB7XG4gICAgICAgICAgICB0aGlzLnNpbmdsZXRvbkNhY2hlLnNldCh0b2tlbiwgaW5zdGFuY2UpO1xuICAgICAgICAgICAgdGhpcy5zaW5nbGV0b25PcmRlci5wdXNoKHRva2VuKTtcbiAgICAgICAgICAgIC8vIEFsc28gYWRkIHRvIHVsdHJhLWZhc3QgY2FjaGVcbiAgICAgICAgICAgIHRoaXMudWx0cmFGYXN0U2luZ2xldG9uQ2FjaGUuc2V0KHRva2VuLCBpbnN0YW5jZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAobGlmZXRpbWUgPT09ICdwZXItcmVxdWVzdCcgJiYgY29udGV4dCkge1xuICAgICAgICAgICAgY29udGV4dC5jYWNoZVBlclJlcXVlc3QodG9rZW4sIGluc3RhbmNlKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBWYWxpZGF0ZSBhbmQgZ2V0IGJpbmRpbmcgd2l0aCBjaXJjdWxhciBkZXBlbmRlbmN5IGNoZWNrXG4gICAgICogUmV0dXJucyBiaW5kaW5nIG9yIHRocm93cyBlcnJvclxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIHZhbGlkYXRlQW5kR2V0QmluZGluZyh0b2tlbiwgY29udGV4dCkge1xuICAgICAgICAvLyBDaGVjayBjaXJjdWxhciBkZXBlbmRlbmN5XG4gICAgICAgIGlmIChjb250ZXh0LmlzUmVzb2x2aW5nKHRva2VuKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IENpcmN1bGFyRGVwZW5kZW5jeUVycm9yKFsuLi5jb250ZXh0LmdldFBhdGgoKSwgdG9rZW4udG9TdHJpbmcoKV0pO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGJpbmRpbmcgPSB0aGlzLmdldEJpbmRpbmcodG9rZW4pO1xuICAgICAgICBpZiAoIWJpbmRpbmcpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBCaW5kaW5nTm90Rm91bmRFcnJvcih0b2tlbi50b1N0cmluZygpLCBjb250ZXh0LmdldFBhdGgoKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGJpbmRpbmc7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEluc3RhbnRpYXRlIGZyb20gYmluZGluZyBzeW5jaHJvbm91c2x5XG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgaW5zdGFudGlhdGVCaW5kaW5nU3luYyhiaW5kaW5nLCB0b2tlbiwgY29udGV4dCkge1xuICAgICAgICBzd2l0Y2ggKGJpbmRpbmcudHlwZSkge1xuICAgICAgICAgICAgY2FzZSAndmFsdWUnOlxuICAgICAgICAgICAgICAgIHJldHVybiBiaW5kaW5nLnZhbHVlO1xuICAgICAgICAgICAgY2FzZSAnZmFjdG9yeSc6XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYmluZGluZy5mYWN0b3J5KHRoaXMpO1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBQcm9taXNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQXN5bmMgZmFjdG9yeSBkZXRlY3RlZCBmb3IgJHt0b2tlbi50b1N0cmluZygpfS4gVXNlIHJlc29sdmVBc3luYygpIGluc3RlYWQuYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgICAgICAgICAgY29uc3QgZGVwcyA9IGJpbmRpbmcuZGVwZW5kZW5jaWVzIHx8IFtdO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc29sdmVkRGVwcyA9IGRlcHMubWFwKGRlcCA9PiB0aGlzLnJlc29sdmVXaXRoQ29udGV4dChkZXAsIGNvbnRleHQpKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IGJpbmRpbmcuY29uc3RydWN0b3IoLi4ucmVzb2x2ZWREZXBzKTtcbiAgICAgICAgICAgIGNhc2UgJ2lubGluZS1jbGFzcyc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBiaW5kaW5nLmNvbnN0cnVjdG9yKCk7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBiaW5kaW5nIHR5cGU6ICR7YmluZGluZy50eXBlfWApO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEluc3RhbnRpYXRlIGZyb20gYmluZGluZyBhc3luY2hyb25vdXNseVxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGFzeW5jIGluc3RhbnRpYXRlQmluZGluZ0FzeW5jKGJpbmRpbmcsIGNvbnRleHQpIHtcbiAgICAgICAgc3dpdGNoIChiaW5kaW5nLnR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ3ZhbHVlJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gYmluZGluZy52YWx1ZTtcbiAgICAgICAgICAgIGNhc2UgJ2ZhY3RvcnknOlxuICAgICAgICAgICAgICAgIHJldHVybiBhd2FpdCBQcm9taXNlLnJlc29sdmUoYmluZGluZy5mYWN0b3J5KHRoaXMpKTtcbiAgICAgICAgICAgIGNhc2UgJ2NsYXNzJzpcbiAgICAgICAgICAgICAgICBjb25zdCBkZXBzID0gYmluZGluZy5kZXBlbmRlbmNpZXMgfHwgW107XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzb2x2ZWREZXBzID0gYXdhaXQgUHJvbWlzZS5hbGwoZGVwcy5tYXAoZGVwID0+IHRoaXMucmVzb2x2ZUFzeW5jV2l0aENvbnRleHQoZGVwLCBjb250ZXh0KSkpO1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgYmluZGluZy5jb25zdHJ1Y3RvciguLi5yZXNvbHZlZERlcHMpO1xuICAgICAgICAgICAgY2FzZSAnaW5saW5lLWNsYXNzJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IGJpbmRpbmcuY29uc3RydWN0b3IoKTtcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGJpbmRpbmcgdHlwZTogJHtiaW5kaW5nLnR5cGV9YCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGEgY2hpbGQgY29udGFpbmVyIHRoYXQgaW5oZXJpdHMgYmluZGluZ3MgZnJvbSB0aGlzIGNvbnRhaW5lclxuICAgICAqL1xuICAgIGNyZWF0ZUNoaWxkKCkge1xuICAgICAgICByZXR1cm4gbmV3IENvbnRhaW5lcih0aGlzKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRGlzcG9zZSBhbGwgc2luZ2xldG9uIGluc3RhbmNlcyBpbiByZXZlcnNlIHJlZ2lzdHJhdGlvbiBvcmRlclxuICAgICAqL1xuICAgIGFzeW5jIGRpc3Bvc2UoKSB7XG4gICAgICAgIGNvbnN0IGVycm9ycyA9IFtdO1xuICAgICAgICAvLyBEaXNwb3NlIGluIHJldmVyc2Ugb3JkZXJcbiAgICAgICAgZm9yIChsZXQgaSA9IHRoaXMuc2luZ2xldG9uT3JkZXIubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIGNvbnN0IHRva2VuID0gdGhpcy5zaW5nbGV0b25PcmRlcltpXTtcbiAgICAgICAgICAgIGNvbnN0IGluc3RhbmNlID0gdGhpcy5zaW5nbGV0b25DYWNoZS5nZXQodG9rZW4pO1xuICAgICAgICAgICAgaWYgKGluc3RhbmNlICYmIGlzRGlzcG9zYWJsZShpbnN0YW5jZSkpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBpbnN0YW5jZS5kaXNwb3NlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBlcnJvcnMucHVzaChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIC8vIENvbnRpbnVlIGRpc3Bvc2luZyBvdGhlciBpbnN0YW5jZXMgZXZlbiBpZiBvbmUgZmFpbHNcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ2xlYXIgY2FjaGVzXG4gICAgICAgIHRoaXMuc2luZ2xldG9uQ2FjaGUuY2xlYXIoKTtcbiAgICAgICAgdGhpcy5zaW5nbGV0b25PcmRlci5sZW5ndGggPSAwO1xuICAgICAgICAvLyBOb3RlOiBXZSBkb24ndCB0aHJvdyBlcnJvcnMgdG8gYWxsb3cgYWxsIGRpc3Bvc2FscyB0byBjb21wbGV0ZVxuICAgICAgICAvLyBJbiBwcm9kdWN0aW9uLCB5b3UgbWlnaHQgd2FudCB0byBsb2cgdGhlc2UgZXJyb3JzXG4gICAgfVxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIGZsdWVudCBidWlsZGVyIGZvciByZWdpc3RlcmluZyBkZXBlbmRlbmNpZXNcbiAgICAgKi9cbiAgICBidWlsZGVyKCkge1xuICAgICAgICByZXR1cm4gbmV3IEJ1aWxkZXIodGhpcyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlc29sdmUgYSBuYW1lZCBzZXJ2aWNlXG4gICAgICovXG4gICAgcmVzb2x2ZU5hbWVkKG5hbWUpIHtcbiAgICAgICAgY29uc3QgbmFtZWRSZWdpc3RyYXRpb25zID0gdGhpcy5fX25hbWVkUmVnaXN0cmF0aW9ucztcbiAgICAgICAgaWYgKCFuYW1lZFJlZ2lzdHJhdGlvbnMpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgTmFtZWQgc2VydmljZSBcIiR7bmFtZX1cIiBub3QgZm91bmQuIE5vIG5hbWVkIHJlZ2lzdHJhdGlvbnMgZXhpc3QuYCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY29uZmlnID0gbmFtZWRSZWdpc3RyYXRpb25zLmdldChuYW1lKTtcbiAgICAgICAgaWYgKCFjb25maWcpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgTmFtZWQgc2VydmljZSBcIiR7bmFtZX1cIiBub3QgZm91bmRgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5yZXNvbHZlKGNvbmZpZy50b2tlbik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlc29sdmUgYSBrZXllZCBzZXJ2aWNlXG4gICAgICovXG4gICAgcmVzb2x2ZUtleWVkKGtleSkge1xuICAgICAgICBjb25zdCBrZXllZFJlZ2lzdHJhdGlvbnMgPSB0aGlzLl9fa2V5ZWRSZWdpc3RyYXRpb25zO1xuICAgICAgICBpZiAoIWtleWVkUmVnaXN0cmF0aW9ucykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBLZXllZCBzZXJ2aWNlIG5vdCBmb3VuZC4gTm8ga2V5ZWQgcmVnaXN0cmF0aW9ucyBleGlzdC5gKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjb25maWcgPSBrZXllZFJlZ2lzdHJhdGlvbnMuZ2V0KGtleSk7XG4gICAgICAgIGlmICghY29uZmlnKSB7XG4gICAgICAgICAgICBjb25zdCBrZXlTdHIgPSB0eXBlb2Yga2V5ID09PSAnc3ltYm9sJyA/IGtleS50b1N0cmluZygpIDogYFwiJHtrZXl9XCJgO1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBLZXllZCBzZXJ2aWNlICR7a2V5U3RyfSBub3QgZm91bmRgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5yZXNvbHZlKGNvbmZpZy50b2tlbik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlc29sdmUgYWxsIHJlZ2lzdHJhdGlvbnMgZm9yIGEgdG9rZW5cbiAgICAgKi9cbiAgICByZXNvbHZlQWxsKHRva2VuKSB7XG4gICAgICAgIGNvbnN0IG11bHRpUmVnaXN0cmF0aW9ucyA9IHRoaXMuX19tdWx0aVJlZ2lzdHJhdGlvbnM7XG4gICAgICAgIGlmICghbXVsdGlSZWdpc3RyYXRpb25zKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdG9rZW5zID0gbXVsdGlSZWdpc3RyYXRpb25zLmdldCh0b2tlbik7XG4gICAgICAgIGlmICghdG9rZW5zIHx8IHRva2Vucy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdG9rZW5zLm1hcCgodCkgPT4gdGhpcy5yZXNvbHZlKHQpKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IHJlZ2lzdHJ5IGluZm9ybWF0aW9uIGZvciBkZWJ1Z2dpbmcvdmlzdWFsaXphdGlvblxuICAgICAqIFJldHVybnMgYXJyYXkgb2YgYmluZGluZyBpbmZvcm1hdGlvblxuICAgICAqL1xuICAgIGdldFJlZ2lzdHJ5KCkge1xuICAgICAgICBjb25zdCByZWdpc3RyeSA9IFtdO1xuICAgICAgICB0aGlzLmJpbmRpbmdzLmZvckVhY2goKGJpbmRpbmcsIHRva2VuKSA9PiB7XG4gICAgICAgICAgICByZWdpc3RyeS5wdXNoKHtcbiAgICAgICAgICAgICAgICB0b2tlbjogdG9rZW4uZGVzY3JpcHRpb24gfHwgdG9rZW4uc3ltYm9sLnRvU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgdHlwZTogYmluZGluZy50eXBlLFxuICAgICAgICAgICAgICAgIGxpZmV0aW1lOiBiaW5kaW5nLmxpZmV0aW1lLFxuICAgICAgICAgICAgICAgIGRlcGVuZGVuY2llczogYmluZGluZy5kZXBlbmRlbmNpZXM/Lm1hcChkID0+IGQuZGVzY3JpcHRpb24gfHwgZC5zeW1ib2wudG9TdHJpbmcoKSlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlZ2lzdHJ5O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgb3IgY3JlYXRlIGEgdG9rZW4gZm9yIGFuIGludGVyZmFjZSB0eXBlXG4gICAgICogVXNlcyBhIHR5cGUgbmFtZSBoYXNoIGFzIGtleSBmb3IgdGhlIGludGVyZmFjZSByZWdpc3RyeVxuICAgICAqL1xuICAgIGludGVyZmFjZVRva2VuKHR5cGVOYW1lKSB7XG4gICAgICAgIC8vIEdlbmVyYXRlIGEgdW5pcXVlIGtleSBmb3IgdGhpcyBpbnRlcmZhY2UgdHlwZVxuICAgICAgICAvLyBJbiBwcm9kdWN0aW9uLCB0aGlzIHdvdWxkIGJlIHJlcGxhY2VkIGJ5IGEgVFMgdHJhbnNmb3JtZXJcbiAgICAgICAgY29uc3Qga2V5ID0gdHlwZU5hbWUgfHwgYEludGVyZmFjZV8ke01hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpLnN1YnN0cigyLCA5KX1gO1xuICAgICAgICAvLyBDaGVjayBpZiB0b2tlbiBhbHJlYWR5IGV4aXN0cyBpbiB0aGlzIGNvbnRhaW5lclxuICAgICAgICBpZiAodGhpcy5pbnRlcmZhY2VSZWdpc3RyeS5oYXMoa2V5KSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW50ZXJmYWNlUmVnaXN0cnkuZ2V0KGtleSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ2hlY2sgcGFyZW50IGNvbnRhaW5lciAocmVjdXJzaXZlbHkgdGhyb3VnaCBwYXJlbnQgY2hhaW4pXG4gICAgICAgIGlmICh0aGlzLnBhcmVudCkge1xuICAgICAgICAgICAgLy8gUmVjdXJzaXZlbHkgY2hlY2sgdGhyb3VnaCBlbnRpcmUgcGFyZW50IGNoYWluXG4gICAgICAgICAgICBjb25zdCBwYXJlbnRUb2tlbiA9IHRoaXMucGFyZW50LmludGVyZmFjZVRva2VuKGtleSk7XG4gICAgICAgICAgICAvLyBJZiBwYXJlbnQgY3JlYXRlZCBhIG5ldyB0b2tlbiwgZG9uJ3QgY3JlYXRlIGFub3RoZXIgb25lXG4gICAgICAgICAgICByZXR1cm4gcGFyZW50VG9rZW47XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ3JlYXRlIG5ldyB0b2tlbiAob25seSBpZiBubyBwYXJlbnQgZXhpc3RzKVxuICAgICAgICBjb25zdCB0b2tlbiA9IFRva2VuKGtleSk7XG4gICAgICAgIHRoaXMuaW50ZXJmYWNlUmVnaXN0cnkuc2V0KGtleSwgdG9rZW4pO1xuICAgICAgICByZXR1cm4gdG9rZW47XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlc29sdmUgYSBkZXBlbmRlbmN5IGJ5IGludGVyZmFjZSB0eXBlIHdpdGhvdXQgZXhwbGljaXQgdG9rZW5cbiAgICAgKi9cbiAgICByZXNvbHZlVHlwZSh0eXBlTmFtZSkge1xuICAgICAgICAvLyBQZXJmb3JtYW5jZTogQ2FjaGUgdG9rZW4gbG9va3VwcyB0byBhdm9pZCByZXBlYXRlZCBpbnRlcmZhY2VSZWdpc3RyeSBhY2Nlc3NcbiAgICAgICAgY29uc3Qga2V5ID0gdHlwZU5hbWUgfHwgJyc7XG4gICAgICAgIGxldCB0b2tlbiA9IHRoaXMuaW50ZXJmYWNlVG9rZW5DYWNoZS5nZXQoa2V5KTtcbiAgICAgICAgaWYgKCF0b2tlbikge1xuICAgICAgICAgICAgdG9rZW4gPSB0aGlzLmludGVyZmFjZVRva2VuKHR5cGVOYW1lKTtcbiAgICAgICAgICAgIHRoaXMuaW50ZXJmYWNlVG9rZW5DYWNoZS5zZXQoa2V5LCB0b2tlbik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZSh0b2tlbik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlc29sdmUgYSBrZXllZCBpbnRlcmZhY2VcbiAgICAgKi9cbiAgICByZXNvbHZlVHlwZUtleWVkKGtleSwgX3R5cGVOYW1lKSB7XG4gICAgICAgIC8vIEZvciBrZXllZCBpbnRlcmZhY2VzLCB3ZSB1c2UgdGhlIGV4aXN0aW5nIHJlc29sdmVLZXllZCBtZWNoYW5pc21cbiAgICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZUtleWVkKGtleSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlc29sdmUgYWxsIHJlZ2lzdHJhdGlvbnMgZm9yIGFuIGludGVyZmFjZSB0eXBlXG4gICAgICovXG4gICAgcmVzb2x2ZVR5cGVBbGwodHlwZU5hbWUpIHtcbiAgICAgICAgY29uc3QgdG9rZW4gPSB0aGlzLmludGVyZmFjZVRva2VuKHR5cGVOYW1lKTtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZUFsbCh0b2tlbik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEludGVybmFsOiBSZXNvbHZlIHdpdGggY29udGV4dCBmb3IgY2lyY3VsYXIgZGVwZW5kZW5jeSBkZXRlY3Rpb25cbiAgICAgKi9cbiAgICByZXNvbHZlV2l0aENvbnRleHQodG9rZW4sIGNvbnRleHQpIHtcbiAgICAgICAgLy8gVmFsaWRhdGUgYW5kIGdldCBiaW5kaW5nICh3aXRoIGNpcmN1bGFyIGRlcGVuZGVuY3kgY2hlY2spXG4gICAgICAgIGNvbnN0IGJpbmRpbmcgPSB0aGlzLnZhbGlkYXRlQW5kR2V0QmluZGluZyh0b2tlbiwgY29udGV4dCk7XG4gICAgICAgIC8vIENoZWNrIHBlci1yZXF1ZXN0IGNhY2hlXG4gICAgICAgIGlmIChiaW5kaW5nLmxpZmV0aW1lID09PSAncGVyLXJlcXVlc3QnICYmIGNvbnRleHQuaGFzUGVyUmVxdWVzdCh0b2tlbikpIHtcbiAgICAgICAgICAgIHJldHVybiBjb250ZXh0LmdldFBlclJlcXVlc3QodG9rZW4pO1xuICAgICAgICB9XG4gICAgICAgIC8vIENoZWNrIHNpbmdsZXRvbiBjYWNoZSAobG9jYWwgY29udGFpbmVyIG9ubHkpXG4gICAgICAgIGlmIChiaW5kaW5nLmxpZmV0aW1lID09PSAnc2luZ2xldG9uJyAmJiB0aGlzLnNpbmdsZXRvbkNhY2hlLmhhcyh0b2tlbikpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNpbmdsZXRvbkNhY2hlLmdldCh0b2tlbik7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTWFyayBhcyByZXNvbHZpbmdcbiAgICAgICAgY29udGV4dC5lbnRlclJlc29sdmUodG9rZW4pO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gSW5zdGFudGlhdGUgZnJvbSBiaW5kaW5nXG4gICAgICAgICAgICBjb25zdCBpbnN0YW5jZSA9IHRoaXMuaW5zdGFudGlhdGVCaW5kaW5nU3luYyhiaW5kaW5nLCB0b2tlbiwgY29udGV4dCk7XG4gICAgICAgICAgICAvLyBDYWNoZSBiYXNlZCBvbiBsaWZldGltZVxuICAgICAgICAgICAgdGhpcy5jYWNoZUluc3RhbmNlKHRva2VuLCBpbnN0YW5jZSwgYmluZGluZy5saWZldGltZSwgY29udGV4dCk7XG4gICAgICAgICAgICByZXR1cm4gaW5zdGFuY2U7XG4gICAgICAgIH1cbiAgICAgICAgZmluYWxseSB7XG4gICAgICAgICAgICBjb250ZXh0LmV4aXRSZXNvbHZlKHRva2VuKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBJbnRlcm5hbDogQXN5bmMgcmVzb2x2ZSB3aXRoIGNvbnRleHRcbiAgICAgKi9cbiAgICBhc3luYyByZXNvbHZlQXN5bmNXaXRoQ29udGV4dCh0b2tlbiwgY29udGV4dCkge1xuICAgICAgICAvLyBWYWxpZGF0ZSBhbmQgZ2V0IGJpbmRpbmcgKHdpdGggY2lyY3VsYXIgZGVwZW5kZW5jeSBjaGVjaylcbiAgICAgICAgY29uc3QgYmluZGluZyA9IHRoaXMudmFsaWRhdGVBbmRHZXRCaW5kaW5nKHRva2VuLCBjb250ZXh0KTtcbiAgICAgICAgLy8gQ2hlY2sgcGVyLXJlcXVlc3QgY2FjaGVcbiAgICAgICAgaWYgKGJpbmRpbmcubGlmZXRpbWUgPT09ICdwZXItcmVxdWVzdCcgJiYgY29udGV4dC5oYXNQZXJSZXF1ZXN0KHRva2VuKSkge1xuICAgICAgICAgICAgcmV0dXJuIGNvbnRleHQuZ2V0UGVyUmVxdWVzdCh0b2tlbik7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ2hlY2sgc2luZ2xldG9uIGNhY2hlIChsb2NhbCBjb250YWluZXIgb25seSlcbiAgICAgICAgaWYgKGJpbmRpbmcubGlmZXRpbWUgPT09ICdzaW5nbGV0b24nICYmIHRoaXMuc2luZ2xldG9uQ2FjaGUuaGFzKHRva2VuKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2luZ2xldG9uQ2FjaGUuZ2V0KHRva2VuKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBNYXJrIGFzIHJlc29sdmluZ1xuICAgICAgICBjb250ZXh0LmVudGVyUmVzb2x2ZSh0b2tlbik7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBJbnN0YW50aWF0ZSBmcm9tIGJpbmRpbmcgYXN5bmNocm9ub3VzbHlcbiAgICAgICAgICAgIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgdGhpcy5pbnN0YW50aWF0ZUJpbmRpbmdBc3luYyhiaW5kaW5nLCBjb250ZXh0KTtcbiAgICAgICAgICAgIC8vIENhY2hlIGJhc2VkIG9uIGxpZmV0aW1lXG4gICAgICAgICAgICB0aGlzLmNhY2hlSW5zdGFuY2UodG9rZW4sIGluc3RhbmNlLCBiaW5kaW5nLmxpZmV0aW1lLCBjb250ZXh0KTtcbiAgICAgICAgICAgIHJldHVybiBpbnN0YW5jZTtcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgIGNvbnRleHQuZXhpdFJlc29sdmUodG9rZW4pO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBiaW5kaW5nIGZyb20gdGhpcyBjb250YWluZXIgb3IgcGFyZW50IGNoYWluXG4gICAgICogUGVyZm9ybWFuY2Ugb3B0aW1pemVkOiBVc2VzIGZsYXQgY2FjaGUgdG8gYXZvaWQgcmVjdXJzaXZlIHBhcmVudCBsb29rdXBzXG4gICAgICovXG4gICAgZ2V0QmluZGluZyh0b2tlbikge1xuICAgICAgICAvLyBCdWlsZCBmbGF0IGNhY2hlIG9uIGZpcnN0IGFjY2Vzc1xuICAgICAgICBpZiAoIXRoaXMuYmluZGluZ0NhY2hlKSB7XG4gICAgICAgICAgICB0aGlzLmJ1aWxkQmluZGluZ0NhY2hlKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuYmluZGluZ0NhY2hlLmdldCh0b2tlbik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEJ1aWxkIGZsYXQgY2FjaGUgb2YgYWxsIGJpbmRpbmdzIGluY2x1ZGluZyBwYXJlbnQgY2hhaW5cbiAgICAgKiBUaGlzIGNvbnZlcnRzIE8obikgcGFyZW50IGNoYWluIHRyYXZlcnNhbCB0byBPKDEpIGxvb2t1cFxuICAgICAqL1xuICAgIGJ1aWxkQmluZGluZ0NhY2hlKCkge1xuICAgICAgICB0aGlzLmJpbmRpbmdDYWNoZSA9IG5ldyBNYXAoKTtcbiAgICAgICAgLy8gVHJhdmVyc2UgcGFyZW50IGNoYWluIGFuZCBmbGF0dGVuIGFsbCBiaW5kaW5nc1xuICAgICAgICBsZXQgY3VycmVudCA9IHRoaXM7XG4gICAgICAgIHdoaWxlIChjdXJyZW50KSB7XG4gICAgICAgICAgICBjdXJyZW50LmJpbmRpbmdzLmZvckVhY2goKGJpbmRpbmcsIHRva2VuKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gQ2hpbGQgYmluZGluZ3Mgb3ZlcnJpZGUgcGFyZW50IGJpbmRpbmdzIChmaXJzdCB3aW5zKVxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5iaW5kaW5nQ2FjaGUuaGFzKHRva2VuKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmJpbmRpbmdDYWNoZS5zZXQodG9rZW4sIGJpbmRpbmcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY3VycmVudCA9IGN1cnJlbnQucGFyZW50O1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEludmFsaWRhdGUgYmluZGluZyBjYWNoZSB3aGVuIG5ldyBiaW5kaW5ncyBhcmUgYWRkZWRcbiAgICAgKiBDYWxsZWQgYnkgYmluZFZhbHVlLCBiaW5kRmFjdG9yeSwgYmluZENsYXNzXG4gICAgICovXG4gICAgaW52YWxpZGF0ZUJpbmRpbmdDYWNoZSgpIHtcbiAgICAgICAgdGhpcy5iaW5kaW5nQ2FjaGUgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMudWx0cmFGYXN0U2luZ2xldG9uQ2FjaGUuY2xlYXIoKTsgLy8gQ2xlYXIgdWx0cmEtZmFzdCBjYWNoZSB3aGVuIGJpbmRpbmdzIGNoYW5nZVxuICAgIH1cbn1cbkNvbnRhaW5lci5jb250ZXh0UG9vbCA9IG5ldyBSZXNvbHV0aW9uQ29udGV4dFBvb2woKTsgLy8gUGVyZm9ybWFuY2U6IFBvb2xlZCBjb250ZXh0cyByZWR1Y2UgYWxsb2NhdGlvbnNcbiIsICJleHBvcnQgY2xhc3MgRGF0ZVJlbmRlcmVyIHtcbiAgICBjb25zdHJ1Y3RvcihkYXRlU2VydmljZSkge1xuICAgICAgICB0aGlzLmRhdGVTZXJ2aWNlID0gZGF0ZVNlcnZpY2U7XG4gICAgICAgIHRoaXMudHlwZSA9ICdkYXRlJztcbiAgICB9XG4gICAgcmVuZGVyKGNvbnRleHQpIHtcbiAgICAgICAgY29uc3QgZGF0ZXMgPSBjb250ZXh0LmZpbHRlclsnZGF0ZSddIHx8IFtdO1xuICAgICAgICBjb25zdCByZXNvdXJjZUlkcyA9IGNvbnRleHQuZmlsdGVyWydyZXNvdXJjZSddIHx8IFtdO1xuICAgICAgICAvLyBDaGVjayBpZiBkYXRlIGhlYWRlcnMgc2hvdWxkIGJlIGhpZGRlbiAoZS5nLiwgaW4gZGF5IHZpZXcpXG4gICAgICAgIGNvbnN0IGRhdGVHcm91cGluZyA9IGNvbnRleHQuZ3JvdXBpbmdzPy5maW5kKGcgPT4gZy50eXBlID09PSAnZGF0ZScpO1xuICAgICAgICBjb25zdCBoaWRlSGVhZGVyID0gZGF0ZUdyb3VwaW5nPy5oaWRlSGVhZGVyID09PSB0cnVlO1xuICAgICAgICAvLyBSZW5kZXIgZGF0ZXMgZm9yIEhWRVIgcmVzb3VyY2UgKGVsbGVyIDEgZ2FuZyBodmlzIGluZ2VuIHJlc291cmNlcylcbiAgICAgICAgY29uc3QgaXRlcmF0aW9ucyA9IHJlc291cmNlSWRzLmxlbmd0aCB8fCAxO1xuICAgICAgICBsZXQgY29sdW1uQ291bnQgPSAwO1xuICAgICAgICBmb3IgKGxldCByID0gMDsgciA8IGl0ZXJhdGlvbnM7IHIrKykge1xuICAgICAgICAgICAgY29uc3QgcmVzb3VyY2VJZCA9IHJlc291cmNlSWRzW3JdOyAvLyB1bmRlZmluZWQgaHZpcyBpbmdlbiByZXNvdXJjZXNcbiAgICAgICAgICAgIGZvciAoY29uc3QgZGF0ZVN0ciBvZiBkYXRlcykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRhdGUgPSB0aGlzLmRhdGVTZXJ2aWNlLnBhcnNlSVNPKGRhdGVTdHIpO1xuICAgICAgICAgICAgICAgIC8vIEJ1aWxkIGNvbHVtbktleSBmb3IgdW5pZm9ybSBpZGVudGlmaWNhdGlvblxuICAgICAgICAgICAgICAgIGNvbnN0IHNlZ21lbnRzID0geyBkYXRlOiBkYXRlU3RyIH07XG4gICAgICAgICAgICAgICAgaWYgKHJlc291cmNlSWQpXG4gICAgICAgICAgICAgICAgICAgIHNlZ21lbnRzLnJlc291cmNlID0gcmVzb3VyY2VJZDtcbiAgICAgICAgICAgICAgICBjb25zdCBjb2x1bW5LZXkgPSB0aGlzLmRhdGVTZXJ2aWNlLmJ1aWxkQ29sdW1uS2V5KHNlZ21lbnRzKTtcbiAgICAgICAgICAgICAgICAvLyBIZWFkZXJcbiAgICAgICAgICAgICAgICBjb25zdCBoZWFkZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzd3AtZGF5LWhlYWRlcicpO1xuICAgICAgICAgICAgICAgIGhlYWRlci5kYXRhc2V0LmRhdGUgPSBkYXRlU3RyO1xuICAgICAgICAgICAgICAgIGhlYWRlci5kYXRhc2V0LmNvbHVtbktleSA9IGNvbHVtbktleTtcbiAgICAgICAgICAgICAgICBpZiAocmVzb3VyY2VJZCkge1xuICAgICAgICAgICAgICAgICAgICBoZWFkZXIuZGF0YXNldC5yZXNvdXJjZUlkID0gcmVzb3VyY2VJZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGhpZGVIZWFkZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgaGVhZGVyLmRhdGFzZXQuaGlkZGVuID0gJ3RydWUnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBoZWFkZXIuaW5uZXJIVE1MID0gYFxyXG4gICAgICAgICAgPHN3cC1kYXktbmFtZT4ke3RoaXMuZGF0ZVNlcnZpY2UuZ2V0RGF5TmFtZShkYXRlLCAnc2hvcnQnKX08L3N3cC1kYXktbmFtZT5cclxuICAgICAgICAgIDxzd3AtZGF5LWRhdGU+JHtkYXRlLmdldERhdGUoKX08L3N3cC1kYXktZGF0ZT5cclxuICAgICAgICBgO1xuICAgICAgICAgICAgICAgIGNvbnRleHQuaGVhZGVyQ29udGFpbmVyLmFwcGVuZENoaWxkKGhlYWRlcik7XG4gICAgICAgICAgICAgICAgLy8gQ29sdW1uXG4gICAgICAgICAgICAgICAgY29uc3QgY29sdW1uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3dwLWRheS1jb2x1bW4nKTtcbiAgICAgICAgICAgICAgICBjb2x1bW4uZGF0YXNldC5kYXRlID0gZGF0ZVN0cjtcbiAgICAgICAgICAgICAgICBjb2x1bW4uZGF0YXNldC5jb2x1bW5LZXkgPSBjb2x1bW5LZXk7XG4gICAgICAgICAgICAgICAgaWYgKHJlc291cmNlSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uLmRhdGFzZXQucmVzb3VyY2VJZCA9IHJlc291cmNlSWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbHVtbi5pbm5lckhUTUwgPSAnPHN3cC1ldmVudHMtbGF5ZXI+PC9zd3AtZXZlbnRzLWxheWVyPic7XG4gICAgICAgICAgICAgICAgY29udGV4dC5jb2x1bW5Db250YWluZXIuYXBwZW5kQ2hpbGQoY29sdW1uKTtcbiAgICAgICAgICAgICAgICBjb2x1bW5Db3VudCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIFNldCBncmlkIGNvbHVtbnMgb24gY29udGFpbmVyXG4gICAgICAgIGNvbnN0IGNvbnRhaW5lciA9IGNvbnRleHQuY29sdW1uQ29udGFpbmVyLmNsb3Nlc3QoJ3N3cC1jYWxlbmRhci1jb250YWluZXInKTtcbiAgICAgICAgaWYgKGNvbnRhaW5lcikge1xuICAgICAgICAgICAgY29udGFpbmVyLnN0eWxlLnNldFByb3BlcnR5KCctLWdyaWQtY29sdW1ucycsIFN0cmluZyhjb2x1bW5Db3VudCkpO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwgImltcG9ydCBkYXlqcyBmcm9tICdkYXlqcyc7XG5pbXBvcnQgdXRjIGZyb20gJ2RheWpzL3BsdWdpbi91dGMnO1xuaW1wb3J0IHRpbWV6b25lIGZyb20gJ2RheWpzL3BsdWdpbi90aW1lem9uZSc7XG5pbXBvcnQgaXNvV2VlayBmcm9tICdkYXlqcy9wbHVnaW4vaXNvV2Vlayc7XG4vLyBFbmFibGUgZGF5anMgcGx1Z2luc1xuZGF5anMuZXh0ZW5kKHV0Yyk7XG5kYXlqcy5leHRlbmQodGltZXpvbmUpO1xuZGF5anMuZXh0ZW5kKGlzb1dlZWspO1xuZXhwb3J0IGNsYXNzIERhdGVTZXJ2aWNlIHtcbiAgICBjb25zdHJ1Y3Rvcihjb25maWcsIGJhc2VEYXRlKSB7XG4gICAgICAgIHRoaXMuY29uZmlnID0gY29uZmlnO1xuICAgICAgICB0aGlzLnRpbWV6b25lID0gY29uZmlnLnRpbWV6b25lO1xuICAgICAgICAvLyBBbGxvdyBzZXR0aW5nIGEgZml4ZWQgYmFzZSBkYXRlIGZvciBkZW1vL3Rlc3RpbmcgcHVycG9zZXNcbiAgICAgICAgdGhpcy5iYXNlRGF0ZSA9IGJhc2VEYXRlID8gZGF5anMoYmFzZURhdGUpIDogZGF5anMoKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2V0IGEgZml4ZWQgYmFzZSBkYXRlICh1c2VmdWwgZm9yIGRlbW9zIHdpdGggc3RhdGljIG1vY2sgZGF0YSlcbiAgICAgKi9cbiAgICBzZXRCYXNlRGF0ZShkYXRlKSB7XG4gICAgICAgIHRoaXMuYmFzZURhdGUgPSBkYXlqcyhkYXRlKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBjdXJyZW50IGJhc2UgZGF0ZSAoZWl0aGVyIGZpeGVkIG9yIHRvZGF5KVxuICAgICAqL1xuICAgIGdldEJhc2VEYXRlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5iYXNlRGF0ZS50b0RhdGUoKTtcbiAgICB9XG4gICAgcGFyc2VJU08oaXNvU3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBkYXlqcyhpc29TdHJpbmcpLnRvRGF0ZSgpO1xuICAgIH1cbiAgICBnZXREYXlOYW1lKGRhdGUsIGZvcm1hdCA9ICdzaG9ydCcpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBJbnRsLkRhdGVUaW1lRm9ybWF0KHRoaXMuY29uZmlnLmxvY2FsZSwgeyB3ZWVrZGF5OiBmb3JtYXQgfSkuZm9ybWF0KGRhdGUpO1xuICAgIH1cbiAgICBnZXRXZWVrRGF0ZXMob2Zmc2V0ID0gMCwgZGF5cyA9IDcpIHtcbiAgICAgICAgY29uc3QgbW9uZGF5ID0gdGhpcy5iYXNlRGF0ZS5zdGFydE9mKCd3ZWVrJykuYWRkKDEsICdkYXknKS5hZGQob2Zmc2V0LCAnd2VlaycpO1xuICAgICAgICByZXR1cm4gQXJyYXkuZnJvbSh7IGxlbmd0aDogZGF5cyB9LCAoXywgaSkgPT4gbW9uZGF5LmFkZChpLCAnZGF5JykuZm9ybWF0KCdZWVlZLU1NLUREJykpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgZGF0ZXMgZm9yIHNwZWNpZmljIHdlZWtkYXlzIHdpdGhpbiBhIHdlZWtcbiAgICAgKiBAcGFyYW0gb2Zmc2V0IC0gV2VlayBvZmZzZXQgZnJvbSBiYXNlIGRhdGUgKDAgPSBjdXJyZW50IHdlZWspXG4gICAgICogQHBhcmFtIHdvcmtEYXlzIC0gQXJyYXkgb2YgSVNPIHdlZWtkYXkgbnVtYmVycyAoMT1Nb25kYXksIDc9U3VuZGF5KVxuICAgICAqIEByZXR1cm5zIEFycmF5IG9mIGRhdGUgc3RyaW5ncyBpbiBZWVlZLU1NLUREIGZvcm1hdFxuICAgICAqL1xuICAgIGdldFdvcmtXZWVrRGF0ZXMob2Zmc2V0LCB3b3JrRGF5cykge1xuICAgICAgICBjb25zdCBtb25kYXkgPSB0aGlzLmJhc2VEYXRlLnN0YXJ0T2YoJ3dlZWsnKS5hZGQoMSwgJ2RheScpLmFkZChvZmZzZXQsICd3ZWVrJyk7XG4gICAgICAgIHJldHVybiB3b3JrRGF5cy5tYXAoaXNvRGF5ID0+IHtcbiAgICAgICAgICAgIC8vIElTTzogMT1Nb25kYXksIDc9U3VuZGF5IFx1MjE5MiBkYXlzIGZyb20gTW9uZGF5OiAwLTZcbiAgICAgICAgICAgIGNvbnN0IGRheXNGcm9tTW9uZGF5ID0gaXNvRGF5ID09PSA3ID8gNiA6IGlzb0RheSAtIDE7XG4gICAgICAgICAgICByZXR1cm4gbW9uZGF5LmFkZChkYXlzRnJvbU1vbmRheSwgJ2RheScpLmZvcm1hdCgnWVlZWS1NTS1ERCcpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBGT1JNQVRUSU5HXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICBmb3JtYXRUaW1lKGRhdGUsIHNob3dTZWNvbmRzID0gZmFsc2UpIHtcbiAgICAgICAgY29uc3QgcGF0dGVybiA9IHNob3dTZWNvbmRzID8gJ0hIOm1tOnNzJyA6ICdISDptbSc7XG4gICAgICAgIHJldHVybiBkYXlqcyhkYXRlKS5mb3JtYXQocGF0dGVybik7XG4gICAgfVxuICAgIGZvcm1hdFRpbWVSYW5nZShzdGFydCwgZW5kKSB7XG4gICAgICAgIHJldHVybiBgJHt0aGlzLmZvcm1hdFRpbWUoc3RhcnQpfSAtICR7dGhpcy5mb3JtYXRUaW1lKGVuZCl9YDtcbiAgICB9XG4gICAgZm9ybWF0RGF0ZShkYXRlKSB7XG4gICAgICAgIHJldHVybiBkYXlqcyhkYXRlKS5mb3JtYXQoJ1lZWVktTU0tREQnKTtcbiAgICB9XG4gICAgZ2V0RGF0ZUtleShkYXRlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZvcm1hdERhdGUoZGF0ZSk7XG4gICAgfVxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gQ09MVU1OIEtFWVxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLyoqXG4gICAgICogQnVpbGQgYSB1bmlmb3JtIGNvbHVtbktleSBmcm9tIGdyb3VwaW5nIHNlZ21lbnRzXG4gICAgICogSGFuZGxlcyBhbnkgY29tYmluYXRpb24gb2YgZGF0ZSwgcmVzb3VyY2UsIHRlYW0sIGV0Yy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYnVpbGRDb2x1bW5LZXkoeyBkYXRlOiAnMjAyNS0xMi0wOScgfSkgXHUyMTkyIFwiMjAyNS0xMi0wOVwiXG4gICAgICogYnVpbGRDb2x1bW5LZXkoeyBkYXRlOiAnMjAyNS0xMi0wOScsIHJlc291cmNlOiAnRU1QMDAxJyB9KSBcdTIxOTIgXCIyMDI1LTEyLTA5OkVNUDAwMVwiXG4gICAgICovXG4gICAgYnVpbGRDb2x1bW5LZXkoc2VnbWVudHMpIHtcbiAgICAgICAgLy8gQWx3YXlzIHB1dCBkYXRlIGZpcnN0IGlmIHByZXNlbnQsIHRoZW4gb3RoZXIgc2VnbWVudHMgYWxwaGFiZXRpY2FsbHlcbiAgICAgICAgY29uc3QgZGF0ZSA9IHNlZ21lbnRzLmRhdGU7XG4gICAgICAgIGNvbnN0IG90aGVycyA9IE9iamVjdC5lbnRyaWVzKHNlZ21lbnRzKVxuICAgICAgICAgICAgLmZpbHRlcigoW2tdKSA9PiBrICE9PSAnZGF0ZScpXG4gICAgICAgICAgICAuc29ydCgoW2FdLCBbYl0pID0+IGEubG9jYWxlQ29tcGFyZShiKSlcbiAgICAgICAgICAgIC5tYXAoKFssIHZdKSA9PiB2KTtcbiAgICAgICAgcmV0dXJuIGRhdGUgPyBbZGF0ZSwgLi4ub3RoZXJzXS5qb2luKCc6JykgOiBvdGhlcnMuam9pbignOicpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBQYXJzZSBhIGNvbHVtbktleSBiYWNrIGludG8gc2VnbWVudHNcbiAgICAgKiBBc3N1bWVzIGZvcm1hdDogXCJkYXRlOnJlc291cmNlOi4uLlwiIG9yIGp1c3QgXCJkYXRlXCJcbiAgICAgKi9cbiAgICBwYXJzZUNvbHVtbktleShjb2x1bW5LZXkpIHtcbiAgICAgICAgY29uc3QgcGFydHMgPSBjb2x1bW5LZXkuc3BsaXQoJzonKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGRhdGU6IHBhcnRzWzBdLFxuICAgICAgICAgICAgcmVzb3VyY2U6IHBhcnRzWzFdXG4gICAgICAgIH07XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEV4dHJhY3QgZGF0ZUtleSBmcm9tIGNvbHVtbktleSAoZmlyc3Qgc2VnbWVudClcbiAgICAgKi9cbiAgICBnZXREYXRlRnJvbUNvbHVtbktleShjb2x1bW5LZXkpIHtcbiAgICAgICAgcmV0dXJuIGNvbHVtbktleS5zcGxpdCgnOicpWzBdO1xuICAgIH1cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIFRJTUUgQ0FMQ1VMQVRJT05TXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICB0aW1lVG9NaW51dGVzKHRpbWVTdHJpbmcpIHtcbiAgICAgICAgY29uc3QgcGFydHMgPSB0aW1lU3RyaW5nLnNwbGl0KCc6JykubWFwKE51bWJlcik7XG4gICAgICAgIGNvbnN0IGhvdXJzID0gcGFydHNbMF0gfHwgMDtcbiAgICAgICAgY29uc3QgbWludXRlcyA9IHBhcnRzWzFdIHx8IDA7XG4gICAgICAgIHJldHVybiBob3VycyAqIDYwICsgbWludXRlcztcbiAgICB9XG4gICAgbWludXRlc1RvVGltZSh0b3RhbE1pbnV0ZXMpIHtcbiAgICAgICAgY29uc3QgaG91cnMgPSBNYXRoLmZsb29yKHRvdGFsTWludXRlcyAvIDYwKTtcbiAgICAgICAgY29uc3QgbWludXRlcyA9IHRvdGFsTWludXRlcyAlIDYwO1xuICAgICAgICByZXR1cm4gZGF5anMoKS5ob3VyKGhvdXJzKS5taW51dGUobWludXRlcykuZm9ybWF0KCdISDptbScpO1xuICAgIH1cbiAgICBnZXRNaW51dGVzU2luY2VNaWRuaWdodChkYXRlKSB7XG4gICAgICAgIGNvbnN0IGQgPSBkYXlqcyhkYXRlKTtcbiAgICAgICAgcmV0dXJuIGQuaG91cigpICogNjAgKyBkLm1pbnV0ZSgpO1xuICAgIH1cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIFVUQyBDT05WRVJTSU9OU1xuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgdG9VVEMobG9jYWxEYXRlKSB7XG4gICAgICAgIHJldHVybiBkYXlqcy50eihsb2NhbERhdGUsIHRoaXMudGltZXpvbmUpLnV0YygpLnRvSVNPU3RyaW5nKCk7XG4gICAgfVxuICAgIGZyb21VVEModXRjU3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBkYXlqcy51dGModXRjU3RyaW5nKS50eih0aGlzLnRpbWV6b25lKS50b0RhdGUoKTtcbiAgICB9XG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBEQVRFIENSRUFUSU9OXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICBjcmVhdGVEYXRlQXRUaW1lKGJhc2VEYXRlLCB0aW1lU3RyaW5nKSB7XG4gICAgICAgIGNvbnN0IHRvdGFsTWludXRlcyA9IHRoaXMudGltZVRvTWludXRlcyh0aW1lU3RyaW5nKTtcbiAgICAgICAgY29uc3QgaG91cnMgPSBNYXRoLmZsb29yKHRvdGFsTWludXRlcyAvIDYwKTtcbiAgICAgICAgY29uc3QgbWludXRlcyA9IHRvdGFsTWludXRlcyAlIDYwO1xuICAgICAgICByZXR1cm4gZGF5anMoYmFzZURhdGUpLnN0YXJ0T2YoJ2RheScpLmhvdXIoaG91cnMpLm1pbnV0ZShtaW51dGVzKS50b0RhdGUoKTtcbiAgICB9XG4gICAgZ2V0SVNPV2Vla0RheShkYXRlKSB7XG4gICAgICAgIHJldHVybiBkYXlqcyhkYXRlKS5pc29XZWVrZGF5KCk7IC8vIDE9TW9uZGF5LCA3PVN1bmRheVxuICAgIH1cbn1cbiIsICIvKipcbiAqIEFic3RyYWN0IGJhc2UgY2xhc3MgZm9yIGdyb3VwaW5nIHJlbmRlcmVyc1xuICpcbiAqIEhhbmRsZXM6XG4gKiAtIEZldGNoaW5nIGVudGl0aWVzIGJ5IElEc1xuICogLSBDYWxjdWxhdGluZyBjb2xzcGFuIGZyb20gcGFyZW50Q2hpbGRNYXBcbiAqIC0gQ3JlYXRpbmcgaGVhZGVyIGVsZW1lbnRzXG4gKiAtIEFwcGVuZGluZyB0byBjb250YWluZXJcbiAqXG4gKiBTdWJjbGFzc2VzIG92ZXJyaWRlOlxuICogLSByZW5kZXJIZWFkZXIoKSBmb3IgY3VzdG9tIGNvbnRlbnRcbiAqIC0gZ2V0RGlzcGxheU5hbWUoKSBmb3IgZW50aXR5IGRpc3BsYXkgdGV4dFxuICovXG5leHBvcnQgY2xhc3MgQmFzZUdyb3VwaW5nUmVuZGVyZXIge1xuICAgIC8qKlxuICAgICAqIE1haW4gcmVuZGVyIG1ldGhvZCAtIGhhbmRsZXMgY29tbW9uIGxvZ2ljXG4gICAgICovXG4gICAgYXN5bmMgcmVuZGVyKGNvbnRleHQpIHtcbiAgICAgICAgY29uc3QgYWxsb3dlZElkcyA9IGNvbnRleHQuZmlsdGVyW3RoaXMudHlwZV0gfHwgW107XG4gICAgICAgIGlmIChhbGxvd2VkSWRzLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY29uc3QgZW50aXRpZXMgPSBhd2FpdCB0aGlzLmdldEVudGl0aWVzKGFsbG93ZWRJZHMpO1xuICAgICAgICBjb25zdCBkYXRlQ291bnQgPSBjb250ZXh0LmZpbHRlclsnZGF0ZSddPy5sZW5ndGggfHwgMTtcbiAgICAgICAgY29uc3QgY2hpbGRJZHMgPSBjb250ZXh0LmNoaWxkVHlwZSA/IGNvbnRleHQuZmlsdGVyW2NvbnRleHQuY2hpbGRUeXBlXSB8fCBbXSA6IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IGVudGl0eSBvZiBlbnRpdGllcykge1xuICAgICAgICAgICAgY29uc3QgZW50aXR5Q2hpbGRJZHMgPSBjb250ZXh0LnBhcmVudENoaWxkTWFwPy5bZW50aXR5LmlkXSB8fCBbXTtcbiAgICAgICAgICAgIGNvbnN0IGNoaWxkQ291bnQgPSBlbnRpdHlDaGlsZElkcy5maWx0ZXIoaWQgPT4gY2hpbGRJZHMuaW5jbHVkZXMoaWQpKS5sZW5ndGg7XG4gICAgICAgICAgICBjb25zdCBjb2xzcGFuID0gY2hpbGRDb3VudCAqIGRhdGVDb3VudDtcbiAgICAgICAgICAgIGNvbnN0IGhlYWRlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGhpcy5jb25maWcuZWxlbWVudFRhZyk7XG4gICAgICAgICAgICBoZWFkZXIuZGF0YXNldFt0aGlzLmNvbmZpZy5pZEF0dHJpYnV0ZV0gPSBlbnRpdHkuaWQ7XG4gICAgICAgICAgICBoZWFkZXIuc3R5bGUuc2V0UHJvcGVydHkodGhpcy5jb25maWcuY29sc3BhblZhciwgU3RyaW5nKGNvbHNwYW4pKTtcbiAgICAgICAgICAgIC8vIEFsbG93IHN1YmNsYXNzIHRvIGN1c3RvbWl6ZSBoZWFkZXIgY29udGVudFxuICAgICAgICAgICAgdGhpcy5yZW5kZXJIZWFkZXIoZW50aXR5LCBoZWFkZXIsIGNvbnRleHQpO1xuICAgICAgICAgICAgY29udGV4dC5oZWFkZXJDb250YWluZXIuYXBwZW5kQ2hpbGQoaGVhZGVyKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBPdmVycmlkZSB0aGlzIG1ldGhvZCBmb3IgY3VzdG9tIGhlYWRlciByZW5kZXJpbmdcbiAgICAgKiBEZWZhdWx0OiBqdXN0IHNldHMgdGV4dENvbnRlbnQgdG8gZGlzcGxheSBuYW1lXG4gICAgICovXG4gICAgcmVuZGVySGVhZGVyKGVudGl0eSwgaGVhZGVyLCBfY29udGV4dCkge1xuICAgICAgICBoZWFkZXIudGV4dENvbnRlbnQgPSB0aGlzLmdldERpc3BsYXlOYW1lKGVudGl0eSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEhlbHBlciB0byByZW5kZXIgYSBzaW5nbGUgZW50aXR5IGhlYWRlci5cbiAgICAgKiBDYW4gYmUgdXNlZCBieSBzdWJjbGFzc2VzIHRoYXQgb3ZlcnJpZGUgcmVuZGVyKCkgYnV0IHdhbnQgY29uc2lzdGVudCBoZWFkZXIgY3JlYXRpb24uXG4gICAgICovXG4gICAgY3JlYXRlSGVhZGVyKGVudGl0eSwgY29udGV4dCkge1xuICAgICAgICBjb25zdCBoZWFkZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KHRoaXMuY29uZmlnLmVsZW1lbnRUYWcpO1xuICAgICAgICBoZWFkZXIuZGF0YXNldFt0aGlzLmNvbmZpZy5pZEF0dHJpYnV0ZV0gPSBlbnRpdHkuaWQ7XG4gICAgICAgIHRoaXMucmVuZGVySGVhZGVyKGVudGl0eSwgaGVhZGVyLCBjb250ZXh0KTtcbiAgICAgICAgcmV0dXJuIGhlYWRlcjtcbiAgICB9XG59XG4iLCAiaW1wb3J0IHsgQmFzZUdyb3VwaW5nUmVuZGVyZXIgfSBmcm9tICcuLi8uLi9jb3JlL0Jhc2VHcm91cGluZ1JlbmRlcmVyJztcbmV4cG9ydCBjbGFzcyBSZXNvdXJjZVJlbmRlcmVyIGV4dGVuZHMgQmFzZUdyb3VwaW5nUmVuZGVyZXIge1xuICAgIGNvbnN0cnVjdG9yKHJlc291cmNlU2VydmljZSkge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLnJlc291cmNlU2VydmljZSA9IHJlc291cmNlU2VydmljZTtcbiAgICAgICAgdGhpcy50eXBlID0gJ3Jlc291cmNlJztcbiAgICAgICAgdGhpcy5jb25maWcgPSB7XG4gICAgICAgICAgICBlbGVtZW50VGFnOiAnc3dwLXJlc291cmNlLWhlYWRlcicsXG4gICAgICAgICAgICBpZEF0dHJpYnV0ZTogJ3Jlc291cmNlSWQnLFxuICAgICAgICAgICAgY29sc3BhblZhcjogJy0tcmVzb3VyY2UtY29scydcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZ2V0RW50aXRpZXMoaWRzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlc291cmNlU2VydmljZS5nZXRCeUlkcyhpZHMpO1xuICAgIH1cbiAgICBnZXREaXNwbGF5TmFtZShlbnRpdHkpIHtcbiAgICAgICAgcmV0dXJuIGVudGl0eS5kaXNwbGF5TmFtZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogT3ZlcnJpZGUgcmVuZGVyIHRvIGhhbmRsZTpcbiAgICAgKiAxLiBTcGVjaWFsIG9yZGVyaW5nIHdoZW4gcGFyZW50Q2hpbGRNYXAgZXhpc3RzIChyZXNvdXJjZXMgZ3JvdXBlZCBieSBwYXJlbnQpXG4gICAgICogMi4gRGlmZmVyZW50IGNvbHNwYW4gY2FsY3VsYXRpb24gKGp1c3QgZGF0ZUNvdW50LCBub3QgY2hpbGRDb3VudCAqIGRhdGVDb3VudClcbiAgICAgKi9cbiAgICBhc3luYyByZW5kZXIoY29udGV4dCkge1xuICAgICAgICBjb25zdCByZXNvdXJjZUlkcyA9IGNvbnRleHQuZmlsdGVyWydyZXNvdXJjZSddIHx8IFtdO1xuICAgICAgICBjb25zdCBkYXRlQ291bnQgPSBjb250ZXh0LmZpbHRlclsnZGF0ZSddPy5sZW5ndGggfHwgMTtcbiAgICAgICAgLy8gRGV0ZXJtaW5lIHJlbmRlciBvcmRlciBiYXNlZCBvbiBwYXJlbnRDaGlsZE1hcFxuICAgICAgICAvLyBJZiBwYXJlbnRDaGlsZE1hcCBleGlzdHMsIHJlbmRlciByZXNvdXJjZXMgZ3JvdXBlZCBieSBwYXJlbnQgKGUuZy4sIHRlYW0pXG4gICAgICAgIC8vIE90aGVyd2lzZSwgcmVuZGVyIGluIGZpbHRlciBvcmRlclxuICAgICAgICBsZXQgb3JkZXJlZFJlc291cmNlSWRzO1xuICAgICAgICBpZiAoY29udGV4dC5wYXJlbnRDaGlsZE1hcCkge1xuICAgICAgICAgICAgLy8gUmVuZGVyIHJlc291cmNlcyBpbiBwYXJlbnQtY2hpbGQgb3JkZXJcbiAgICAgICAgICAgIG9yZGVyZWRSZXNvdXJjZUlkcyA9IFtdO1xuICAgICAgICAgICAgZm9yIChjb25zdCBjaGlsZElkcyBvZiBPYmplY3QudmFsdWVzKGNvbnRleHQucGFyZW50Q2hpbGRNYXApKSB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBjaGlsZElkIG9mIGNoaWxkSWRzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNvdXJjZUlkcy5pbmNsdWRlcyhjaGlsZElkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZFJlc291cmNlSWRzLnB1c2goY2hpbGRJZCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBvcmRlcmVkUmVzb3VyY2VJZHMgPSByZXNvdXJjZUlkcztcbiAgICAgICAgfVxuICAgICAgICBjb25zdCByZXNvdXJjZXMgPSBhd2FpdCB0aGlzLmdldEVudGl0aWVzKG9yZGVyZWRSZXNvdXJjZUlkcyk7XG4gICAgICAgIC8vIENyZWF0ZSBhIG1hcCBmb3IgcXVpY2sgbG9va3VwIHRvIHByZXNlcnZlIG9yZGVyXG4gICAgICAgIGNvbnN0IHJlc291cmNlTWFwID0gbmV3IE1hcChyZXNvdXJjZXMubWFwKHIgPT4gW3IuaWQsIHJdKSk7XG4gICAgICAgIGZvciAoY29uc3QgcmVzb3VyY2VJZCBvZiBvcmRlcmVkUmVzb3VyY2VJZHMpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlc291cmNlID0gcmVzb3VyY2VNYXAuZ2V0KHJlc291cmNlSWQpO1xuICAgICAgICAgICAgaWYgKCFyZXNvdXJjZSlcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIGNvbnN0IGhlYWRlciA9IHRoaXMuY3JlYXRlSGVhZGVyKHJlc291cmNlLCBjb250ZXh0KTtcbiAgICAgICAgICAgIGhlYWRlci5zdHlsZS5ncmlkQ29sdW1uID0gYHNwYW4gJHtkYXRlQ291bnR9YDtcbiAgICAgICAgICAgIGNvbnRleHQuaGVhZGVyQ29udGFpbmVyLmFwcGVuZENoaWxkKGhlYWRlcik7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCAiaW1wb3J0IHsgQmFzZUdyb3VwaW5nUmVuZGVyZXIgfSBmcm9tICcuLi8uLi9jb3JlL0Jhc2VHcm91cGluZ1JlbmRlcmVyJztcbmV4cG9ydCBjbGFzcyBUZWFtUmVuZGVyZXIgZXh0ZW5kcyBCYXNlR3JvdXBpbmdSZW5kZXJlciB7XG4gICAgY29uc3RydWN0b3IodGVhbVNlcnZpY2UpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy50ZWFtU2VydmljZSA9IHRlYW1TZXJ2aWNlO1xuICAgICAgICB0aGlzLnR5cGUgPSAndGVhbSc7XG4gICAgICAgIHRoaXMuY29uZmlnID0ge1xuICAgICAgICAgICAgZWxlbWVudFRhZzogJ3N3cC10ZWFtLWhlYWRlcicsXG4gICAgICAgICAgICBpZEF0dHJpYnV0ZTogJ3RlYW1JZCcsXG4gICAgICAgICAgICBjb2xzcGFuVmFyOiAnLS10ZWFtLWNvbHMnXG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldEVudGl0aWVzKGlkcykge1xuICAgICAgICByZXR1cm4gdGhpcy50ZWFtU2VydmljZS5nZXRCeUlkcyhpZHMpO1xuICAgIH1cbiAgICBnZXREaXNwbGF5TmFtZShlbnRpdHkpIHtcbiAgICAgICAgcmV0dXJuIGVudGl0eS5uYW1lO1xuICAgIH1cbn1cbiIsICJpbXBvcnQgeyBCYXNlR3JvdXBpbmdSZW5kZXJlciB9IGZyb20gJy4uLy4uL2NvcmUvQmFzZUdyb3VwaW5nUmVuZGVyZXInO1xuZXhwb3J0IGNsYXNzIERlcGFydG1lbnRSZW5kZXJlciBleHRlbmRzIEJhc2VHcm91cGluZ1JlbmRlcmVyIHtcbiAgICBjb25zdHJ1Y3RvcihkZXBhcnRtZW50U2VydmljZSkge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLmRlcGFydG1lbnRTZXJ2aWNlID0gZGVwYXJ0bWVudFNlcnZpY2U7XG4gICAgICAgIHRoaXMudHlwZSA9ICdkZXBhcnRtZW50JztcbiAgICAgICAgdGhpcy5jb25maWcgPSB7XG4gICAgICAgICAgICBlbGVtZW50VGFnOiAnc3dwLWRlcGFydG1lbnQtaGVhZGVyJyxcbiAgICAgICAgICAgIGlkQXR0cmlidXRlOiAnZGVwYXJ0bWVudElkJyxcbiAgICAgICAgICAgIGNvbHNwYW5WYXI6ICctLWRlcGFydG1lbnQtY29scydcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZ2V0RW50aXRpZXMoaWRzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRlcGFydG1lbnRTZXJ2aWNlLmdldEJ5SWRzKGlkcyk7XG4gICAgfVxuICAgIGdldERpc3BsYXlOYW1lKGVudGl0eSkge1xuICAgICAgICByZXR1cm4gZW50aXR5Lm5hbWU7XG4gICAgfVxufVxuIiwgImV4cG9ydCBmdW5jdGlvbiBidWlsZFBpcGVsaW5lKHJlbmRlcmVycykge1xuICAgIHJldHVybiB7XG4gICAgICAgIGFzeW5jIHJ1bihjb250ZXh0KSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHJlbmRlcmVyIG9mIHJlbmRlcmVycykge1xuICAgICAgICAgICAgICAgIGF3YWl0IHJlbmRlcmVyLnJlbmRlcihjb250ZXh0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG59XG4iLCAiLyoqXG4gKiBGaWx0ZXJUZW1wbGF0ZSAtIEJ5Z2dlciBuXHUwMEY4Z2xlciB0aWwgZXZlbnQta29sb25uZSBtYXRjaGluZ1xuICpcbiAqIFZpZXdDb25maWcgZGVmaW5lcmVyIGh2aWxrZSBmZWx0ZXIgKGlkUHJvcGVydGllcykgZGVyIGluZGdcdTAwRTVyIGkga29sb25uZW5zIG5cdTAwRjhnbGUuXG4gKiBTYW1tZSB0ZW1wbGF0ZSBicnVnZXMgdGlsIGF0IGJ5Z2dlIG5cdTAwRjhnbGUgZm9yIGJcdTAwRTVkZSBrb2xvbm5lIG9nIGV2ZW50LlxuICpcbiAqIFN1cHBvcnRzIGRvdC1ub3RhdGlvbiBmb3IgaGllcmFyY2hpY2FsIHJlbGF0aW9uczpcbiAqIC0gJ3Jlc291cmNlLnRlYW1JZCcgXHUyMTkyIGxvb2tzIHVwIGV2ZW50LnJlc291cmNlSWQgXHUyMTkyIHJlc291cmNlIGVudGl0eSBcdTIxOTIgdGVhbUlkXG4gKlxuICogUHJpbmNpcDogS29sb25uZW5zIG5cdTAwRjhnbGUtdGVtcGxhdGUgYmVzdGVtbWVyIGh2YWQgZGVyIG1hdGNoZXMgcFx1MDBFNS5cbiAqXG4gKiBAc2VlIGRvY3MvZmlsdGVyLXRlbXBsYXRlLm1kXG4gKi9cbmV4cG9ydCBjbGFzcyBGaWx0ZXJUZW1wbGF0ZSB7XG4gICAgY29uc3RydWN0b3IoZGF0ZVNlcnZpY2UsIGVudGl0eVJlc29sdmVyKSB7XG4gICAgICAgIHRoaXMuZGF0ZVNlcnZpY2UgPSBkYXRlU2VydmljZTtcbiAgICAgICAgdGhpcy5lbnRpdHlSZXNvbHZlciA9IGVudGl0eVJlc29sdmVyO1xuICAgICAgICB0aGlzLmZpZWxkcyA9IFtdO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBUaWxmXHUwMEY4aiBmZWx0IHRpbCB0ZW1wbGF0ZVxuICAgICAqIEBwYXJhbSBpZFByb3BlcnR5IC0gUHJvcGVydHktbmF2biAoYnJ1Z2VzIHBcdTAwRTUgYlx1MDBFNWRlIGV2ZW50IG9nIGNvbHVtbi5kYXRhc2V0KVxuICAgICAqIEBwYXJhbSBkZXJpdmVkRnJvbSAtIEh2aXMgZmVsdGV0IHVkbGVkZXMgZnJhIGFuZGVuIHByb3BlcnR5IChmLmVrcy4gZGF0ZSBmcmEgc3RhcnQpXG4gICAgICovXG4gICAgYWRkRmllbGQoaWRQcm9wZXJ0eSwgZGVyaXZlZEZyb20pIHtcbiAgICAgICAgdGhpcy5maWVsZHMucHVzaCh7IGlkUHJvcGVydHksIGRlcml2ZWRGcm9tIH0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogUGFyc2UgZG90LW5vdGF0aW9uIHN0cmluZyBpbnRvIGNvbXBvbmVudHNcbiAgICAgKiBAZXhhbXBsZSAncmVzb3VyY2UudGVhbUlkJyBcdTIxOTIgeyBlbnRpdHlUeXBlOiAncmVzb3VyY2UnLCBwcm9wZXJ0eTogJ3RlYW1JZCcsIGZvcmVpZ25LZXk6ICdyZXNvdXJjZUlkJyB9XG4gICAgICovXG4gICAgcGFyc2VEb3ROb3RhdGlvbihpZFByb3BlcnR5KSB7XG4gICAgICAgIGlmICghaWRQcm9wZXJ0eS5pbmNsdWRlcygnLicpKVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIGNvbnN0IFtlbnRpdHlUeXBlLCBwcm9wZXJ0eV0gPSBpZFByb3BlcnR5LnNwbGl0KCcuJyk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBlbnRpdHlUeXBlLFxuICAgICAgICAgICAgcHJvcGVydHksXG4gICAgICAgICAgICBmb3JlaWduS2V5OiBlbnRpdHlUeXBlICsgJ0lkJyAvLyBDb252ZW50aW9uOiByZXNvdXJjZSBcdTIxOTIgcmVzb3VyY2VJZFxuICAgICAgICB9O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgZGF0YXNldCBrZXkgZm9yIGNvbHVtbiBsb29rdXBcbiAgICAgKiBGb3IgZG90LW5vdGF0aW9uICdyZXNvdXJjZS50ZWFtSWQnLCB3ZSBsb29rIGZvciAndGVhbUlkJyBpbiBkYXRhc2V0XG4gICAgICovXG4gICAgZ2V0RGF0YXNldEtleShpZFByb3BlcnR5KSB7XG4gICAgICAgIGNvbnN0IGRvdE5vdGF0aW9uID0gdGhpcy5wYXJzZURvdE5vdGF0aW9uKGlkUHJvcGVydHkpO1xuICAgICAgICBpZiAoZG90Tm90YXRpb24pIHtcbiAgICAgICAgICAgIHJldHVybiBkb3ROb3RhdGlvbi5wcm9wZXJ0eTsgLy8gJ3RlYW1JZCdcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaWRQcm9wZXJ0eTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQnlnIG5cdTAwRjhnbGUgZnJhIGtvbG9ubmVcbiAgICAgKiBMXHUwMEU2c2VyIHZcdTAwRTZyZGllciBmcmEgY29sdW1uLmRhdGFzZXRbaWRQcm9wZXJ0eV1cbiAgICAgKiBGb3IgZG90LW5vdGF0aW9uLCB1c2VzIHRoZSBwcm9wZXJ0eSBwYXJ0IChyZXNvdXJjZS50ZWFtSWQgXHUyMTkyIHRlYW1JZClcbiAgICAgKi9cbiAgICBidWlsZEtleUZyb21Db2x1bW4oY29sdW1uKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZpZWxkc1xuICAgICAgICAgICAgLm1hcChmID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGtleSA9IHRoaXMuZ2V0RGF0YXNldEtleShmLmlkUHJvcGVydHkpO1xuICAgICAgICAgICAgcmV0dXJuIGNvbHVtbi5kYXRhc2V0W2tleV0gfHwgJyc7XG4gICAgICAgIH0pXG4gICAgICAgICAgICAuam9pbignOicpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBCeWcgblx1MDBGOGdsZSBmcmEgZXZlbnRcbiAgICAgKiBMXHUwMEU2c2VyIHZcdTAwRTZyZGllciBmcmEgZXZlbnRbaWRQcm9wZXJ0eV0gZWxsZXIgdWRsZWRlciBmcmEgZGVyaXZlZEZyb21cbiAgICAgKiBGb3IgZG90LW5vdGF0aW9uLCByZXNvbHZlcyB2aWEgRW50aXR5UmVzb2x2ZXJcbiAgICAgKi9cbiAgICBidWlsZEtleUZyb21FdmVudChldmVudCkge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgICBjb25zdCBldmVudFJlY29yZCA9IGV2ZW50O1xuICAgICAgICByZXR1cm4gdGhpcy5maWVsZHNcbiAgICAgICAgICAgIC5tYXAoZiA9PiB7XG4gICAgICAgICAgICAvLyBDaGVjayBmb3IgZG90LW5vdGF0aW9uIChlLmcuLCAncmVzb3VyY2UudGVhbUlkJylcbiAgICAgICAgICAgIGNvbnN0IGRvdE5vdGF0aW9uID0gdGhpcy5wYXJzZURvdE5vdGF0aW9uKGYuaWRQcm9wZXJ0eSk7XG4gICAgICAgICAgICBpZiAoZG90Tm90YXRpb24pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yZXNvbHZlRG90Tm90YXRpb24oZXZlbnRSZWNvcmQsIGRvdE5vdGF0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmLmRlcml2ZWRGcm9tKSB7XG4gICAgICAgICAgICAgICAgLy8gVWRsZWQgdlx1MDBFNnJkaSAoZi5la3MuIGRhdGUgZnJhIHN0YXJ0KVxuICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZVZhbHVlID0gZXZlbnRSZWNvcmRbZi5kZXJpdmVkRnJvbV07XG4gICAgICAgICAgICAgICAgaWYgKHNvdXJjZVZhbHVlIGluc3RhbmNlb2YgRGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5kYXRlU2VydmljZS5nZXREYXRlS2V5KHNvdXJjZVZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhzb3VyY2VWYWx1ZSB8fCAnJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gU3RyaW5nKGV2ZW50UmVjb3JkW2YuaWRQcm9wZXJ0eV0gfHwgJycpO1xuICAgICAgICB9KVxuICAgICAgICAgICAgLmpvaW4oJzonKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVzb2x2ZSBkb3Qtbm90YXRpb24gcmVmZXJlbmNlIHZpYSBFbnRpdHlSZXNvbHZlclxuICAgICAqL1xuICAgIHJlc29sdmVEb3ROb3RhdGlvbihldmVudFJlY29yZCwgZG90Tm90YXRpb24pIHtcbiAgICAgICAgaWYgKCF0aGlzLmVudGl0eVJlc29sdmVyKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oYEZpbHRlclRlbXBsYXRlOiBFbnRpdHlSZXNvbHZlciByZXF1aXJlZCBmb3IgZG90LW5vdGF0aW9uICcke2RvdE5vdGF0aW9uLmVudGl0eVR5cGV9LiR7ZG90Tm90YXRpb24ucHJvcGVydHl9J2ApO1xuICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9XG4gICAgICAgIC8vIEdldCBmb3JlaWduIGtleSB2YWx1ZSBmcm9tIGV2ZW50IChlLmcuLCByZXNvdXJjZUlkKVxuICAgICAgICBjb25zdCBmb3JlaWduSWQgPSBldmVudFJlY29yZFtkb3ROb3RhdGlvbi5mb3JlaWduS2V5XTtcbiAgICAgICAgaWYgKCFmb3JlaWduSWQpXG4gICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgIC8vIFJlc29sdmUgZW50aXR5XG4gICAgICAgIGNvbnN0IGVudGl0eSA9IHRoaXMuZW50aXR5UmVzb2x2ZXIucmVzb2x2ZShkb3ROb3RhdGlvbi5lbnRpdHlUeXBlLCBTdHJpbmcoZm9yZWlnbklkKSk7XG4gICAgICAgIGlmICghZW50aXR5KVxuICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICAvLyBSZXR1cm4gcHJvcGVydHkgdmFsdWUgZnJvbSBlbnRpdHlcbiAgICAgICAgcmV0dXJuIFN0cmluZyhlbnRpdHlbZG90Tm90YXRpb24ucHJvcGVydHldIHx8ICcnKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogTWF0Y2ggZXZlbnQgbW9kIGtvbG9ubmVcbiAgICAgKi9cbiAgICBtYXRjaGVzKGV2ZW50LCBjb2x1bW4pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYnVpbGRLZXlGcm9tRXZlbnQoZXZlbnQpID09PSB0aGlzLmJ1aWxkS2V5RnJvbUNvbHVtbihjb2x1bW4pO1xuICAgIH1cbn1cbiIsICJpbXBvcnQgeyBidWlsZFBpcGVsaW5lIH0gZnJvbSAnLi9SZW5kZXJCdWlsZGVyJztcbmltcG9ydCB7IEZpbHRlclRlbXBsYXRlIH0gZnJvbSAnLi9GaWx0ZXJUZW1wbGF0ZSc7XG5leHBvcnQgY2xhc3MgQ2FsZW5kYXJPcmNoZXN0cmF0b3Ige1xuICAgIGNvbnN0cnVjdG9yKGFsbFJlbmRlcmVycywgZXZlbnRSZW5kZXJlciwgc2NoZWR1bGVSZW5kZXJlciwgaGVhZGVyRHJhd2VyUmVuZGVyZXIsIGRhdGVTZXJ2aWNlLCBlbnRpdHlTZXJ2aWNlcykge1xuICAgICAgICB0aGlzLmFsbFJlbmRlcmVycyA9IGFsbFJlbmRlcmVycztcbiAgICAgICAgdGhpcy5ldmVudFJlbmRlcmVyID0gZXZlbnRSZW5kZXJlcjtcbiAgICAgICAgdGhpcy5zY2hlZHVsZVJlbmRlcmVyID0gc2NoZWR1bGVSZW5kZXJlcjtcbiAgICAgICAgdGhpcy5oZWFkZXJEcmF3ZXJSZW5kZXJlciA9IGhlYWRlckRyYXdlclJlbmRlcmVyO1xuICAgICAgICB0aGlzLmRhdGVTZXJ2aWNlID0gZGF0ZVNlcnZpY2U7XG4gICAgICAgIHRoaXMuZW50aXR5U2VydmljZXMgPSBlbnRpdHlTZXJ2aWNlcztcbiAgICB9XG4gICAgYXN5bmMgcmVuZGVyKHZpZXdDb25maWcsIGNvbnRhaW5lcikge1xuICAgICAgICBjb25zdCBoZWFkZXJDb250YWluZXIgPSBjb250YWluZXIucXVlcnlTZWxlY3Rvcignc3dwLWNhbGVuZGFyLWhlYWRlcicpO1xuICAgICAgICBjb25zdCBjb2x1bW5Db250YWluZXIgPSBjb250YWluZXIucXVlcnlTZWxlY3Rvcignc3dwLWRheS1jb2x1bW5zJyk7XG4gICAgICAgIGlmICghaGVhZGVyQ29udGFpbmVyIHx8ICFjb2x1bW5Db250YWluZXIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyBzd3AtY2FsZW5kYXItaGVhZGVyIG9yIHN3cC1kYXktY29sdW1ucycpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEJ5ZyBmaWx0ZXIgZnJhIHZpZXdDb25maWdcbiAgICAgICAgY29uc3QgZmlsdGVyID0ge307XG4gICAgICAgIGZvciAoY29uc3QgZ3JvdXBpbmcgb2Ygdmlld0NvbmZpZy5ncm91cGluZ3MpIHtcbiAgICAgICAgICAgIGZpbHRlcltncm91cGluZy50eXBlXSA9IGdyb3VwaW5nLnZhbHVlcztcbiAgICAgICAgfVxuICAgICAgICAvLyBCeWcgRmlsdGVyVGVtcGxhdGUgZnJhIHZpZXdDb25maWcgZ3JvdXBpbmdzIChrdW4gZGUgbWVkIGlkUHJvcGVydHkpXG4gICAgICAgIGNvbnN0IGZpbHRlclRlbXBsYXRlID0gbmV3IEZpbHRlclRlbXBsYXRlKHRoaXMuZGF0ZVNlcnZpY2UpO1xuICAgICAgICBmb3IgKGNvbnN0IGdyb3VwaW5nIG9mIHZpZXdDb25maWcuZ3JvdXBpbmdzKSB7XG4gICAgICAgICAgICBpZiAoZ3JvdXBpbmcuaWRQcm9wZXJ0eSkge1xuICAgICAgICAgICAgICAgIGZpbHRlclRlbXBsYXRlLmFkZEZpZWxkKGdyb3VwaW5nLmlkUHJvcGVydHksIGdyb3VwaW5nLmRlcml2ZWRGcm9tKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBSZXNvbHZlIGJlbG9uZ3NUbyByZWxhdGlvbnMgKGUuZy4sIHRlYW0ucmVzb3VyY2VJZHMpXG4gICAgICAgIGNvbnN0IHsgcGFyZW50Q2hpbGRNYXAsIGNoaWxkVHlwZSB9ID0gYXdhaXQgdGhpcy5yZXNvbHZlQmVsb25nc1RvKHZpZXdDb25maWcuZ3JvdXBpbmdzLCBmaWx0ZXIpO1xuICAgICAgICBjb25zdCBjb250ZXh0ID0geyBoZWFkZXJDb250YWluZXIsIGNvbHVtbkNvbnRhaW5lciwgZmlsdGVyLCBncm91cGluZ3M6IHZpZXdDb25maWcuZ3JvdXBpbmdzLCBwYXJlbnRDaGlsZE1hcCwgY2hpbGRUeXBlIH07XG4gICAgICAgIC8vIENsZWFyXG4gICAgICAgIGhlYWRlckNvbnRhaW5lci5pbm5lckhUTUwgPSAnJztcbiAgICAgICAgY29sdW1uQ29udGFpbmVyLmlubmVySFRNTCA9ICcnO1xuICAgICAgICAvLyBTXHUwMEU2dCBkYXRhLWxldmVscyBhdHRyaWJ1dCBmb3IgQ1NTIGdyaWQtcm93IHN0eWxpbmdcbiAgICAgICAgY29uc3QgbGV2ZWxzID0gdmlld0NvbmZpZy5ncm91cGluZ3MubWFwKGcgPT4gZy50eXBlKS5qb2luKCcgJyk7XG4gICAgICAgIGhlYWRlckNvbnRhaW5lci5kYXRhc2V0LmxldmVscyA9IGxldmVscztcbiAgICAgICAgLy8gVlx1MDBFNmxnIHJlbmRlcmVycyBiYXNlcmV0IHBcdTAwRTUgZ3JvdXBpbmdzIHR5cGVzXG4gICAgICAgIGNvbnN0IGFjdGl2ZVJlbmRlcmVycyA9IHRoaXMuc2VsZWN0UmVuZGVyZXJzKHZpZXdDb25maWcpO1xuICAgICAgICAvLyBCeWcgb2cga1x1MDBGOHIgcGlwZWxpbmVcbiAgICAgICAgY29uc3QgcGlwZWxpbmUgPSBidWlsZFBpcGVsaW5lKGFjdGl2ZVJlbmRlcmVycyk7XG4gICAgICAgIGF3YWl0IHBpcGVsaW5lLnJ1bihjb250ZXh0KTtcbiAgICAgICAgLy8gUmVuZGVyIHNjaGVkdWxlIHVuYXZhaWxhYmxlIHpvbmVzIChmXHUwMEY4ciBldmVudHMpXG4gICAgICAgIGF3YWl0IHRoaXMuc2NoZWR1bGVSZW5kZXJlci5yZW5kZXIoY29udGFpbmVyLCBmaWx0ZXIpO1xuICAgICAgICAvLyBSZW5kZXIgdGltZWQgZXZlbnRzIGluIGdyaWQgKG1lZCBmaWx0ZXJUZW1wbGF0ZSB0aWwgbWF0Y2hpbmcpXG4gICAgICAgIGF3YWl0IHRoaXMuZXZlbnRSZW5kZXJlci5yZW5kZXIoY29udGFpbmVyLCBmaWx0ZXIsIGZpbHRlclRlbXBsYXRlKTtcbiAgICAgICAgLy8gUmVuZGVyIGFsbERheSBldmVudHMgaW4gaGVhZGVyIGRyYXdlciAobWVkIGZpbHRlclRlbXBsYXRlIHRpbCBtYXRjaGluZylcbiAgICAgICAgYXdhaXQgdGhpcy5oZWFkZXJEcmF3ZXJSZW5kZXJlci5yZW5kZXIoY29udGFpbmVyLCBmaWx0ZXIsIGZpbHRlclRlbXBsYXRlKTtcbiAgICB9XG4gICAgc2VsZWN0UmVuZGVyZXJzKHZpZXdDb25maWcpIHtcbiAgICAgICAgY29uc3QgdHlwZXMgPSB2aWV3Q29uZmlnLmdyb3VwaW5ncy5tYXAoZyA9PiBnLnR5cGUpO1xuICAgICAgICAvLyBTb3J0XHUwMEU5ciByZW5kZXJlcnMgaSBzYW1tZSByXHUwMEU2a2tlZlx1MDBGOGxnZSBzb20gdmlld0NvbmZpZy5ncm91cGluZ3NcbiAgICAgICAgcmV0dXJuIHR5cGVzXG4gICAgICAgICAgICAubWFwKHR5cGUgPT4gdGhpcy5hbGxSZW5kZXJlcnMuZmluZChyID0+IHIudHlwZSA9PT0gdHlwZSkpXG4gICAgICAgICAgICAuZmlsdGVyKChyKSA9PiByICE9PSB1bmRlZmluZWQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXNvbHZlIGJlbG9uZ3NUbyByZWxhdGlvbnMgdG8gYnVpbGQgcGFyZW50LWNoaWxkIG1hcFxuICAgICAqIGUuZy4sIGJlbG9uZ3NUbzogJ3RlYW0ucmVzb3VyY2VJZHMnIFx1MjE5MiB7IHRlYW0xOiBbJ0VNUDAwMScsICdFTVAwMDInXSwgdGVhbTI6IFsuLi5dIH1cbiAgICAgKiBBbHNvIHJldHVybnMgdGhlIGNoaWxkVHlwZSAodGhlIGdyb3VwaW5nIHR5cGUgdGhhdCBoYXMgYmVsb25nc1RvKVxuICAgICAqL1xuICAgIGFzeW5jIHJlc29sdmVCZWxvbmdzVG8oZ3JvdXBpbmdzLCBmaWx0ZXIpIHtcbiAgICAgICAgLy8gRmluZCBncm91cGluZyB3aXRoIGJlbG9uZ3NUb1xuICAgICAgICBjb25zdCBjaGlsZEdyb3VwaW5nID0gZ3JvdXBpbmdzLmZpbmQoZyA9PiBnLmJlbG9uZ3NUbyk7XG4gICAgICAgIGlmICghY2hpbGRHcm91cGluZz8uYmVsb25nc1RvKVxuICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAvLyBQYXJzZSBiZWxvbmdzVG86ICd0ZWFtLnJlc291cmNlSWRzJ1xuICAgICAgICBjb25zdCBbZW50aXR5VHlwZSwgcHJvcGVydHldID0gY2hpbGRHcm91cGluZy5iZWxvbmdzVG8uc3BsaXQoJy4nKTtcbiAgICAgICAgaWYgKCFlbnRpdHlUeXBlIHx8ICFwcm9wZXJ0eSlcbiAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgLy8gR2V0IHBhcmVudCBJRHMgZnJvbSBmaWx0ZXJcbiAgICAgICAgY29uc3QgcGFyZW50SWRzID0gZmlsdGVyW2VudGl0eVR5cGVdIHx8IFtdO1xuICAgICAgICBpZiAocGFyZW50SWRzLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgLy8gRmluZCBzZXJ2aWNlIGR5bmFtaXNrIGJhc2VyZXQgcFx1MDBFNSBlbnRpdHlUeXBlIChpbmdlbiBoYXJkY29kZWQgdHlwZSBjaGVjaylcbiAgICAgICAgY29uc3Qgc2VydmljZSA9IHRoaXMuZW50aXR5U2VydmljZXMuZmluZChzID0+IHMuZW50aXR5VHlwZS50b0xvd2VyQ2FzZSgpID09PSBlbnRpdHlUeXBlKTtcbiAgICAgICAgaWYgKCFzZXJ2aWNlKVxuICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAvLyBIZW50IGFsbGUgZW50aXRpZXMgb2cgZmlsdHJlciBwXHUwMEU1IHBhcmVudElkc1xuICAgICAgICBjb25zdCBhbGxFbnRpdGllcyA9IGF3YWl0IHNlcnZpY2UuZ2V0QWxsKCk7XG4gICAgICAgIGNvbnN0IGVudGl0aWVzID0gYWxsRW50aXRpZXMuZmlsdGVyKGUgPT4gcGFyZW50SWRzLmluY2x1ZGVzKGUuaWQpKTtcbiAgICAgICAgLy8gQnlnIHBhcmVudC1jaGlsZCBtYXBcbiAgICAgICAgY29uc3QgbWFwID0ge307XG4gICAgICAgIGZvciAoY29uc3QgZW50aXR5IG9mIGVudGl0aWVzKSB7XG4gICAgICAgICAgICBjb25zdCBlbnRpdHlSZWNvcmQgPSBlbnRpdHk7XG4gICAgICAgICAgICBjb25zdCBjaGlsZHJlbiA9IGVudGl0eVJlY29yZFtwcm9wZXJ0eV0gfHwgW107XG4gICAgICAgICAgICBtYXBbZW50aXR5UmVjb3JkLmlkXSA9IGNoaWxkcmVuO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IHBhcmVudENoaWxkTWFwOiBtYXAsIGNoaWxkVHlwZTogY2hpbGRHcm91cGluZy50eXBlIH07XG4gICAgfVxufVxuIiwgImV4cG9ydCBjbGFzcyBOYXZpZ2F0aW9uQW5pbWF0b3Ige1xuICAgIGNvbnN0cnVjdG9yKGhlYWRlclRyYWNrLCBjb250ZW50VHJhY2spIHtcbiAgICAgICAgdGhpcy5oZWFkZXJUcmFjayA9IGhlYWRlclRyYWNrO1xuICAgICAgICB0aGlzLmNvbnRlbnRUcmFjayA9IGNvbnRlbnRUcmFjaztcbiAgICB9XG4gICAgYXN5bmMgc2xpZGUoZGlyZWN0aW9uLCByZW5kZXJGbikge1xuICAgICAgICBjb25zdCBvdXQgPSBkaXJlY3Rpb24gPT09ICdsZWZ0JyA/ICctMTAwJScgOiAnMTAwJSc7XG4gICAgICAgIGNvbnN0IGludG8gPSBkaXJlY3Rpb24gPT09ICdsZWZ0JyA/ICcxMDAlJyA6ICctMTAwJSc7XG4gICAgICAgIGF3YWl0IHRoaXMuYW5pbWF0ZU91dChvdXQpO1xuICAgICAgICBhd2FpdCByZW5kZXJGbigpO1xuICAgICAgICBhd2FpdCB0aGlzLmFuaW1hdGVJbihpbnRvKTtcbiAgICB9XG4gICAgYXN5bmMgYW5pbWF0ZU91dCh0cmFuc2xhdGUpIHtcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICAgICAgdGhpcy5oZWFkZXJUcmFjay5hbmltYXRlKFt7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZVgoMCknIH0sIHsgdHJhbnNmb3JtOiBgdHJhbnNsYXRlWCgke3RyYW5zbGF0ZX0pYCB9XSwgeyBkdXJhdGlvbjogMjAwLCBlYXNpbmc6ICdlYXNlLWluJyB9KS5maW5pc2hlZCxcbiAgICAgICAgICAgIHRoaXMuY29udGVudFRyYWNrLmFuaW1hdGUoW3sgdHJhbnNmb3JtOiAndHJhbnNsYXRlWCgwKScgfSwgeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGVYKCR7dHJhbnNsYXRlfSlgIH1dLCB7IGR1cmF0aW9uOiAyMDAsIGVhc2luZzogJ2Vhc2UtaW4nIH0pLmZpbmlzaGVkXG4gICAgICAgIF0pO1xuICAgIH1cbiAgICBhc3luYyBhbmltYXRlSW4odHJhbnNsYXRlKSB7XG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICAgIHRoaXMuaGVhZGVyVHJhY2suYW5pbWF0ZShbeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGVYKCR7dHJhbnNsYXRlfSlgIH0sIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlWCgwKScgfV0sIHsgZHVyYXRpb246IDIwMCwgZWFzaW5nOiAnZWFzZS1vdXQnIH0pLmZpbmlzaGVkLFxuICAgICAgICAgICAgdGhpcy5jb250ZW50VHJhY2suYW5pbWF0ZShbeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGVYKCR7dHJhbnNsYXRlfSlgIH0sIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlWCgwKScgfV0sIHsgZHVyYXRpb246IDIwMCwgZWFzaW5nOiAnZWFzZS1vdXQnIH0pLmZpbmlzaGVkXG4gICAgICAgIF0pO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIENhbGVuZGFyRXZlbnRzIC0gQ29tbWFuZCBhbmQgc3RhdHVzIGV2ZW50cyBmb3IgQ2FsZW5kYXJBcHBcbiAqL1xuZXhwb3J0IGNvbnN0IENhbGVuZGFyRXZlbnRzID0ge1xuICAgIC8vIENvbW1hbmQgZXZlbnRzIChob3N0IFx1MjE5MiBjYWxlbmRhcilcbiAgICBDTURfTkFWSUdBVEVfUFJFVjogJ2NhbGVuZGFyOmNtZDpuYXZpZ2F0ZTpwcmV2JyxcbiAgICBDTURfTkFWSUdBVEVfTkVYVDogJ2NhbGVuZGFyOmNtZDpuYXZpZ2F0ZTpuZXh0JyxcbiAgICBDTURfRFJBV0VSX1RPR0dMRTogJ2NhbGVuZGFyOmNtZDpkcmF3ZXI6dG9nZ2xlJyxcbiAgICBDTURfUkVOREVSOiAnY2FsZW5kYXI6Y21kOnJlbmRlcicsXG4gICAgQ01EX1dPUktXRUVLX0NIQU5HRTogJ2NhbGVuZGFyOmNtZDp3b3Jrd2VlazpjaGFuZ2UnLFxuICAgIENNRF9WSUVXX1VQREFURTogJ2NhbGVuZGFyOmNtZDp2aWV3OnVwZGF0ZSdcbn07XG4iLCAiaW1wb3J0IHsgTmF2aWdhdGlvbkFuaW1hdG9yIH0gZnJvbSAnLi9OYXZpZ2F0aW9uQW5pbWF0b3InO1xuaW1wb3J0IHsgQ2FsZW5kYXJFdmVudHMgfSBmcm9tICcuL0NhbGVuZGFyRXZlbnRzJztcbmV4cG9ydCBjbGFzcyBDYWxlbmRhckFwcCB7XG4gICAgY29uc3RydWN0b3Iob3JjaGVzdHJhdG9yLCB0aW1lQXhpc1JlbmRlcmVyLCBkYXRlU2VydmljZSwgc2Nyb2xsTWFuYWdlciwgaGVhZGVyRHJhd2VyTWFuYWdlciwgZHJhZ0Ryb3BNYW5hZ2VyLCBlZGdlU2Nyb2xsTWFuYWdlciwgcmVzaXplTWFuYWdlciwgaGVhZGVyRHJhd2VyUmVuZGVyZXIsIGV2ZW50UGVyc2lzdGVuY2VNYW5hZ2VyLCBzZXR0aW5nc1NlcnZpY2UsIHZpZXdDb25maWdTZXJ2aWNlLCBldmVudEJ1cykge1xuICAgICAgICB0aGlzLm9yY2hlc3RyYXRvciA9IG9yY2hlc3RyYXRvcjtcbiAgICAgICAgdGhpcy50aW1lQXhpc1JlbmRlcmVyID0gdGltZUF4aXNSZW5kZXJlcjtcbiAgICAgICAgdGhpcy5kYXRlU2VydmljZSA9IGRhdGVTZXJ2aWNlO1xuICAgICAgICB0aGlzLnNjcm9sbE1hbmFnZXIgPSBzY3JvbGxNYW5hZ2VyO1xuICAgICAgICB0aGlzLmhlYWRlckRyYXdlck1hbmFnZXIgPSBoZWFkZXJEcmF3ZXJNYW5hZ2VyO1xuICAgICAgICB0aGlzLmRyYWdEcm9wTWFuYWdlciA9IGRyYWdEcm9wTWFuYWdlcjtcbiAgICAgICAgdGhpcy5lZGdlU2Nyb2xsTWFuYWdlciA9IGVkZ2VTY3JvbGxNYW5hZ2VyO1xuICAgICAgICB0aGlzLnJlc2l6ZU1hbmFnZXIgPSByZXNpemVNYW5hZ2VyO1xuICAgICAgICB0aGlzLmhlYWRlckRyYXdlclJlbmRlcmVyID0gaGVhZGVyRHJhd2VyUmVuZGVyZXI7XG4gICAgICAgIHRoaXMuZXZlbnRQZXJzaXN0ZW5jZU1hbmFnZXIgPSBldmVudFBlcnNpc3RlbmNlTWFuYWdlcjtcbiAgICAgICAgdGhpcy5zZXR0aW5nc1NlcnZpY2UgPSBzZXR0aW5nc1NlcnZpY2U7XG4gICAgICAgIHRoaXMudmlld0NvbmZpZ1NlcnZpY2UgPSB2aWV3Q29uZmlnU2VydmljZTtcbiAgICAgICAgdGhpcy5ldmVudEJ1cyA9IGV2ZW50QnVzO1xuICAgICAgICB0aGlzLndlZWtPZmZzZXQgPSAwO1xuICAgICAgICB0aGlzLmN1cnJlbnRWaWV3SWQgPSAnc2ltcGxlJztcbiAgICAgICAgdGhpcy53b3Jrd2Vla1ByZXNldCA9IG51bGw7XG4gICAgICAgIHRoaXMuZ3JvdXBpbmdPdmVycmlkZXMgPSBuZXcgTWFwKCk7XG4gICAgfVxuICAgIGFzeW5jIGluaXQoY29udGFpbmVyKSB7XG4gICAgICAgIHRoaXMuY29udGFpbmVyID0gY29udGFpbmVyO1xuICAgICAgICAvLyBMb2FkIHNldHRpbmdzXG4gICAgICAgIGNvbnN0IGdyaWRTZXR0aW5ncyA9IGF3YWl0IHRoaXMuc2V0dGluZ3NTZXJ2aWNlLmdldEdyaWRTZXR0aW5ncygpO1xuICAgICAgICBpZiAoIWdyaWRTZXR0aW5ncykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdHcmlkU2V0dGluZ3Mgbm90IGZvdW5kJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy53b3Jrd2Vla1ByZXNldCA9IGF3YWl0IHRoaXMuc2V0dGluZ3NTZXJ2aWNlLmdldERlZmF1bHRXb3Jrd2Vla1ByZXNldCgpO1xuICAgICAgICAvLyBDcmVhdGUgTmF2aWdhdGlvbkFuaW1hdG9yIHdpdGggRE9NIGVsZW1lbnRzXG4gICAgICAgIHRoaXMuYW5pbWF0b3IgPSBuZXcgTmF2aWdhdGlvbkFuaW1hdG9yKGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCdzd3AtaGVhZGVyLXRyYWNrJyksIGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCdzd3AtY29udGVudC10cmFjaycpKTtcbiAgICAgICAgLy8gUmVuZGVyIHRpbWUgYXhpcyBmcm9tIHNldHRpbmdzXG4gICAgICAgIHRoaXMudGltZUF4aXNSZW5kZXJlci5yZW5kZXIoY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJyN0aW1lLWF4aXMnKSwgZ3JpZFNldHRpbmdzLmRheVN0YXJ0SG91ciwgZ3JpZFNldHRpbmdzLmRheUVuZEhvdXIpO1xuICAgICAgICAvLyBJbml0IG1hbmFnZXJzXG4gICAgICAgIHRoaXMuc2Nyb2xsTWFuYWdlci5pbml0KGNvbnRhaW5lcik7XG4gICAgICAgIHRoaXMuaGVhZGVyRHJhd2VyTWFuYWdlci5pbml0KGNvbnRhaW5lcik7XG4gICAgICAgIHRoaXMuZHJhZ0Ryb3BNYW5hZ2VyLmluaXQoY29udGFpbmVyKTtcbiAgICAgICAgdGhpcy5yZXNpemVNYW5hZ2VyLmluaXQoY29udGFpbmVyKTtcbiAgICAgICAgY29uc3Qgc2Nyb2xsYWJsZUNvbnRlbnQgPSBjb250YWluZXIucXVlcnlTZWxlY3Rvcignc3dwLXNjcm9sbGFibGUtY29udGVudCcpO1xuICAgICAgICB0aGlzLmVkZ2VTY3JvbGxNYW5hZ2VyLmluaXQoc2Nyb2xsYWJsZUNvbnRlbnQpO1xuICAgICAgICAvLyBTZXR1cCBjb21tYW5kIGV2ZW50IGxpc3RlbmVyc1xuICAgICAgICB0aGlzLnNldHVwRXZlbnRMaXN0ZW5lcnMoKTtcbiAgICAgICAgLy8gRW1pdCByZWFkeSBzdGF0dXNcbiAgICAgICAgdGhpcy5lbWl0U3RhdHVzKCdyZWFkeScpO1xuICAgIH1cbiAgICBzZXR1cEV2ZW50TGlzdGVuZXJzKCkge1xuICAgICAgICAvLyBOYXZpZ2F0aW9uIGNvbW1hbmRzIHZpYSBFdmVudEJ1c1xuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENhbGVuZGFyRXZlbnRzLkNNRF9OQVZJR0FURV9QUkVWLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZU5hdmlnYXRlUHJldigpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5ldmVudEJ1cy5vbihDYWxlbmRhckV2ZW50cy5DTURfTkFWSUdBVEVfTkVYVCwgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVOYXZpZ2F0ZU5leHQoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIERyYXdlciB0b2dnbGUgdmlhIEV2ZW50QnVzXG4gICAgICAgIHRoaXMuZXZlbnRCdXMub24oQ2FsZW5kYXJFdmVudHMuQ01EX0RSQVdFUl9UT0dHTEUsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaGVhZGVyRHJhd2VyTWFuYWdlci50b2dnbGUoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIFJlbmRlciBjb21tYW5kIHZpYSBFdmVudEJ1c1xuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENhbGVuZGFyRXZlbnRzLkNNRF9SRU5ERVIsIChlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB7IHZpZXdJZCB9ID0gZS5kZXRhaWw7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZVJlbmRlckNvbW1hbmQodmlld0lkKTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIFdvcmt3ZWVrIGNoYW5nZSB2aWEgRXZlbnRCdXNcbiAgICAgICAgdGhpcy5ldmVudEJ1cy5vbihDYWxlbmRhckV2ZW50cy5DTURfV09SS1dFRUtfQ0hBTkdFLCAoZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgeyBwcmVzZXRJZCB9ID0gZS5kZXRhaWw7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZVdvcmt3ZWVrQ2hhbmdlKHByZXNldElkKTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIFZpZXcgdXBkYXRlIHZpYSBFdmVudEJ1c1xuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENhbGVuZGFyRXZlbnRzLkNNRF9WSUVXX1VQREFURSwgKGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHsgdHlwZSwgdmFsdWVzIH0gPSBlLmRldGFpbDtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlVmlld1VwZGF0ZSh0eXBlLCB2YWx1ZXMpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgYXN5bmMgaGFuZGxlUmVuZGVyQ29tbWFuZCh2aWV3SWQpIHtcbiAgICAgICAgdGhpcy5jdXJyZW50Vmlld0lkID0gdmlld0lkO1xuICAgICAgICBhd2FpdCB0aGlzLnJlbmRlcigpO1xuICAgICAgICB0aGlzLmVtaXRTdGF0dXMoJ3JlbmRlcmVkJywgeyB2aWV3SWQgfSk7XG4gICAgfVxuICAgIGFzeW5jIGhhbmRsZU5hdmlnYXRlUHJldigpIHtcbiAgICAgICAgdGhpcy53ZWVrT2Zmc2V0LS07XG4gICAgICAgIGF3YWl0IHRoaXMuYW5pbWF0b3Iuc2xpZGUoJ3JpZ2h0JywgKCkgPT4gdGhpcy5yZW5kZXIoKSk7XG4gICAgICAgIHRoaXMuZW1pdFN0YXR1cygncmVuZGVyZWQnLCB7IHZpZXdJZDogdGhpcy5jdXJyZW50Vmlld0lkIH0pO1xuICAgIH1cbiAgICBhc3luYyBoYW5kbGVOYXZpZ2F0ZU5leHQoKSB7XG4gICAgICAgIHRoaXMud2Vla09mZnNldCsrO1xuICAgICAgICBhd2FpdCB0aGlzLmFuaW1hdG9yLnNsaWRlKCdsZWZ0JywgKCkgPT4gdGhpcy5yZW5kZXIoKSk7XG4gICAgICAgIHRoaXMuZW1pdFN0YXR1cygncmVuZGVyZWQnLCB7IHZpZXdJZDogdGhpcy5jdXJyZW50Vmlld0lkIH0pO1xuICAgIH1cbiAgICBhc3luYyBoYW5kbGVXb3Jrd2Vla0NoYW5nZShwcmVzZXRJZCkge1xuICAgICAgICBjb25zdCBwcmVzZXQgPSBhd2FpdCB0aGlzLnNldHRpbmdzU2VydmljZS5nZXRXb3Jrd2Vla1ByZXNldChwcmVzZXRJZCk7XG4gICAgICAgIGlmIChwcmVzZXQpIHtcbiAgICAgICAgICAgIHRoaXMud29ya3dlZWtQcmVzZXQgPSBwcmVzZXQ7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnJlbmRlcigpO1xuICAgICAgICAgICAgdGhpcy5lbWl0U3RhdHVzKCdyZW5kZXJlZCcsIHsgdmlld0lkOiB0aGlzLmN1cnJlbnRWaWV3SWQgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgYXN5bmMgaGFuZGxlVmlld1VwZGF0ZSh0eXBlLCB2YWx1ZXMpIHtcbiAgICAgICAgdGhpcy5ncm91cGluZ092ZXJyaWRlcy5zZXQodHlwZSwgdmFsdWVzKTtcbiAgICAgICAgYXdhaXQgdGhpcy5yZW5kZXIoKTtcbiAgICAgICAgdGhpcy5lbWl0U3RhdHVzKCdyZW5kZXJlZCcsIHsgdmlld0lkOiB0aGlzLmN1cnJlbnRWaWV3SWQgfSk7XG4gICAgfVxuICAgIGFzeW5jIHJlbmRlcigpIHtcbiAgICAgICAgY29uc3Qgc3RvcmVkQ29uZmlnID0gYXdhaXQgdGhpcy52aWV3Q29uZmlnU2VydmljZS5nZXRCeUlkKHRoaXMuY3VycmVudFZpZXdJZCk7XG4gICAgICAgIGlmICghc3RvcmVkQ29uZmlnKSB7XG4gICAgICAgICAgICB0aGlzLmVtaXRTdGF0dXMoJ2Vycm9yJywgeyBtZXNzYWdlOiBgVmlld0NvbmZpZyBub3QgZm91bmQ6ICR7dGhpcy5jdXJyZW50Vmlld0lkfWAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gUG9wdWxhdGUgZGF0ZSB2YWx1ZXMgYmFzZWQgb24gd29ya3dlZWsgYW5kIG9mZnNldFxuICAgICAgICBjb25zdCB3b3JrRGF5cyA9IHRoaXMud29ya3dlZWtQcmVzZXQ/LndvcmtEYXlzIHx8IFsxLCAyLCAzLCA0LCA1XTtcbiAgICAgICAgY29uc3QgZGF0ZXMgPSB0aGlzLmN1cnJlbnRWaWV3SWQgPT09ICdkYXknXG4gICAgICAgICAgICA/IHRoaXMuZGF0ZVNlcnZpY2UuZ2V0V2Vla0RhdGVzKHRoaXMud2Vla09mZnNldCwgMSlcbiAgICAgICAgICAgIDogdGhpcy5kYXRlU2VydmljZS5nZXRXb3JrV2Vla0RhdGVzKHRoaXMud2Vla09mZnNldCwgd29ya0RheXMpO1xuICAgICAgICAvLyBDbG9uZSBjb25maWcgYW5kIGFwcGx5IG92ZXJyaWRlc1xuICAgICAgICBjb25zdCB2aWV3Q29uZmlnID0ge1xuICAgICAgICAgICAgLi4uc3RvcmVkQ29uZmlnLFxuICAgICAgICAgICAgZ3JvdXBpbmdzOiBzdG9yZWRDb25maWcuZ3JvdXBpbmdzLm1hcChnID0+IHtcbiAgICAgICAgICAgICAgICAvLyBBcHBseSBkYXRlIHZhbHVlc1xuICAgICAgICAgICAgICAgIGlmIChnLnR5cGUgPT09ICdkYXRlJykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4geyAuLi5nLCB2YWx1ZXM6IGRhdGVzIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIEFwcGx5IGdyb3VwaW5nIG92ZXJyaWRlc1xuICAgICAgICAgICAgICAgIGNvbnN0IG92ZXJyaWRlID0gdGhpcy5ncm91cGluZ092ZXJyaWRlcy5nZXQoZy50eXBlKTtcbiAgICAgICAgICAgICAgICBpZiAob3ZlcnJpZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgLi4uZywgdmFsdWVzOiBvdmVycmlkZSB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gZztcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH07XG4gICAgICAgIGF3YWl0IHRoaXMub3JjaGVzdHJhdG9yLnJlbmRlcih2aWV3Q29uZmlnLCB0aGlzLmNvbnRhaW5lcik7XG4gICAgfVxuICAgIGVtaXRTdGF0dXMoc3RhdHVzLCBkZXRhaWwpIHtcbiAgICAgICAgdGhpcy5jb250YWluZXIuZGlzcGF0Y2hFdmVudChuZXcgQ3VzdG9tRXZlbnQoYGNhbGVuZGFyOnN0YXR1czoke3N0YXR1c31gLCB7XG4gICAgICAgICAgICBkZXRhaWwsXG4gICAgICAgICAgICBidWJibGVzOiB0cnVlXG4gICAgICAgIH0pKTtcbiAgICB9XG59XG4iLCAiZXhwb3J0IGNsYXNzIFRpbWVBeGlzUmVuZGVyZXIge1xuICAgIHJlbmRlcihjb250YWluZXIsIHN0YXJ0SG91ciA9IDYsIGVuZEhvdXIgPSAyMCkge1xuICAgICAgICBjb250YWluZXIuaW5uZXJIVE1MID0gJyc7XG4gICAgICAgIGZvciAobGV0IGhvdXIgPSBzdGFydEhvdXI7IGhvdXIgPD0gZW5kSG91cjsgaG91cisrKSB7XG4gICAgICAgICAgICBjb25zdCBtYXJrZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzd3AtaG91ci1tYXJrZXInKTtcbiAgICAgICAgICAgIG1hcmtlci50ZXh0Q29udGVudCA9IGAke2hvdXIudG9TdHJpbmcoKS5wYWRTdGFydCgyLCAnMCcpfTowMGA7XG4gICAgICAgICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQobWFya2VyKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsICJleHBvcnQgY2xhc3MgU2Nyb2xsTWFuYWdlciB7XG4gICAgaW5pdChjb250YWluZXIpIHtcbiAgICAgICAgdGhpcy5zY3JvbGxhYmxlQ29udGVudCA9IGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCdzd3Atc2Nyb2xsYWJsZS1jb250ZW50Jyk7XG4gICAgICAgIHRoaXMudGltZUF4aXNDb250ZW50ID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJ3N3cC10aW1lLWF4aXMtY29udGVudCcpO1xuICAgICAgICB0aGlzLmNhbGVuZGFySGVhZGVyID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJ3N3cC1jYWxlbmRhci1oZWFkZXInKTtcbiAgICAgICAgdGhpcy5oZWFkZXJEcmF3ZXIgPSBjb250YWluZXIucXVlcnlTZWxlY3Rvcignc3dwLWhlYWRlci1kcmF3ZXInKTtcbiAgICAgICAgdGhpcy5oZWFkZXJWaWV3cG9ydCA9IGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCdzd3AtaGVhZGVyLXZpZXdwb3J0Jyk7XG4gICAgICAgIHRoaXMuaGVhZGVyU3BhY2VyID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJ3N3cC1oZWFkZXItc3BhY2VyJyk7XG4gICAgICAgIHRoaXMuc2Nyb2xsYWJsZUNvbnRlbnQuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgKCkgPT4gdGhpcy5vblNjcm9sbCgpKTtcbiAgICAgICAgLy8gU3lua3JvbmlzZXIgaGVhZGVyLXNwYWNlciBoXHUwMEY4amRlIG1lZCBoZWFkZXItdmlld3BvcnRcbiAgICAgICAgdGhpcy5yZXNpemVPYnNlcnZlciA9IG5ldyBSZXNpemVPYnNlcnZlcigoKSA9PiB0aGlzLnN5bmNIZWFkZXJTcGFjZXJIZWlnaHQoKSk7XG4gICAgICAgIHRoaXMucmVzaXplT2JzZXJ2ZXIub2JzZXJ2ZSh0aGlzLmhlYWRlclZpZXdwb3J0KTtcbiAgICAgICAgdGhpcy5zeW5jSGVhZGVyU3BhY2VySGVpZ2h0KCk7XG4gICAgfVxuICAgIHN5bmNIZWFkZXJTcGFjZXJIZWlnaHQoKSB7XG4gICAgICAgIC8vIEtvcGllciBkZW4gZmFrdGlza2UgY29tcHV0ZWQgaGVpZ2h0IGRpcmVrdGUgZnJhIGhlYWRlci12aWV3cG9ydFxuICAgICAgICBjb25zdCBjb21wdXRlZEhlaWdodCA9IGdldENvbXB1dGVkU3R5bGUodGhpcy5oZWFkZXJWaWV3cG9ydCkuaGVpZ2h0O1xuICAgICAgICB0aGlzLmhlYWRlclNwYWNlci5zdHlsZS5oZWlnaHQgPSBjb21wdXRlZEhlaWdodDtcbiAgICB9XG4gICAgb25TY3JvbGwoKSB7XG4gICAgICAgIGNvbnN0IHsgc2Nyb2xsVG9wLCBzY3JvbGxMZWZ0IH0gPSB0aGlzLnNjcm9sbGFibGVDb250ZW50O1xuICAgICAgICAvLyBTeW5rcm9uaXNlciB0aW1lLWF4aXMgdmVydGlrYWx0XG4gICAgICAgIHRoaXMudGltZUF4aXNDb250ZW50LnN0eWxlLnRyYW5zZm9ybSA9IGB0cmFuc2xhdGVZKC0ke3Njcm9sbFRvcH1weClgO1xuICAgICAgICAvLyBTeW5rcm9uaXNlciBoZWFkZXIgb2cgZHJhd2VyIGhvcmlzb250YWx0XG4gICAgICAgIHRoaXMuY2FsZW5kYXJIZWFkZXIuc3R5bGUudHJhbnNmb3JtID0gYHRyYW5zbGF0ZVgoLSR7c2Nyb2xsTGVmdH1weClgO1xuICAgICAgICB0aGlzLmhlYWRlckRyYXdlci5zdHlsZS50cmFuc2Zvcm0gPSBgdHJhbnNsYXRlWCgtJHtzY3JvbGxMZWZ0fXB4KWA7XG4gICAgfVxufVxuIiwgImV4cG9ydCBjbGFzcyBIZWFkZXJEcmF3ZXJNYW5hZ2VyIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5leHBhbmRlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmN1cnJlbnRSb3dzID0gMDtcbiAgICAgICAgdGhpcy5yb3dIZWlnaHQgPSAyNTtcbiAgICAgICAgdGhpcy5kdXJhdGlvbiA9IDIwMDtcbiAgICB9XG4gICAgaW5pdChjb250YWluZXIpIHtcbiAgICAgICAgdGhpcy5kcmF3ZXIgPSBjb250YWluZXIucXVlcnlTZWxlY3Rvcignc3dwLWhlYWRlci1kcmF3ZXInKTtcbiAgICAgICAgaWYgKCF0aGlzLmRyYXdlcilcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0hlYWRlckRyYXdlck1hbmFnZXI6IHN3cC1oZWFkZXItZHJhd2VyIG5vdCBmb3VuZCcpO1xuICAgIH1cbiAgICB0b2dnbGUoKSB7XG4gICAgICAgIHRoaXMuZXhwYW5kZWQgPyB0aGlzLmNvbGxhcHNlKCkgOiB0aGlzLmV4cGFuZCgpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBFeHBhbmQgZHJhd2VyIHRvIHNpbmdsZSByb3cgKGxlZ2FjeSBzdXBwb3J0KVxuICAgICAqL1xuICAgIGV4cGFuZCgpIHtcbiAgICAgICAgdGhpcy5leHBhbmRUb1Jvd3MoMSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEV4cGFuZCBkcmF3ZXIgdG8gZml0IHNwZWNpZmllZCBudW1iZXIgb2Ygcm93c1xuICAgICAqL1xuICAgIGV4cGFuZFRvUm93cyhyb3dDb3VudCkge1xuICAgICAgICBjb25zdCB0YXJnZXRIZWlnaHQgPSByb3dDb3VudCAqIHRoaXMucm93SGVpZ2h0O1xuICAgICAgICBjb25zdCBjdXJyZW50SGVpZ2h0ID0gdGhpcy5leHBhbmRlZCA/IHRoaXMuY3VycmVudFJvd3MgKiB0aGlzLnJvd0hlaWdodCA6IDA7XG4gICAgICAgIC8vIFNraXAgaWYgYWxyZWFkeSBhdCB0YXJnZXRcbiAgICAgICAgaWYgKHRoaXMuZXhwYW5kZWQgJiYgdGhpcy5jdXJyZW50Um93cyA9PT0gcm93Q291bnQpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIHRoaXMuY3VycmVudFJvd3MgPSByb3dDb3VudDtcbiAgICAgICAgdGhpcy5leHBhbmRlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuYW5pbWF0ZShjdXJyZW50SGVpZ2h0LCB0YXJnZXRIZWlnaHQpO1xuICAgIH1cbiAgICBjb2xsYXBzZSgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmV4cGFuZGVkKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBjb25zdCBjdXJyZW50SGVpZ2h0ID0gdGhpcy5jdXJyZW50Um93cyAqIHRoaXMucm93SGVpZ2h0O1xuICAgICAgICB0aGlzLmV4cGFuZGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuY3VycmVudFJvd3MgPSAwO1xuICAgICAgICB0aGlzLmFuaW1hdGUoY3VycmVudEhlaWdodCwgMCk7XG4gICAgfVxuICAgIGFuaW1hdGUoZnJvbSwgdG8pIHtcbiAgICAgICAgY29uc3Qga2V5ZnJhbWVzID0gW1xuICAgICAgICAgICAgeyBoZWlnaHQ6IGAke2Zyb219cHhgIH0sXG4gICAgICAgICAgICB7IGhlaWdodDogYCR7dG99cHhgIH1cbiAgICAgICAgXTtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLFxuICAgICAgICAgICAgZWFzaW5nOiAnZWFzZScsXG4gICAgICAgICAgICBmaWxsOiAnZm9yd2FyZHMnXG4gICAgICAgIH07XG4gICAgICAgIC8vIEt1biBhbmltXHUwMEU5ciBkcmF3ZXIgLSBTY3JvbGxNYW5hZ2VyIHN5bmtyb25pc2VyZXIgaGVhZGVyLXNwYWNlciB2aWEgUmVzaXplT2JzZXJ2ZXJcbiAgICAgICAgdGhpcy5kcmF3ZXIuYW5pbWF0ZShrZXlmcmFtZXMsIG9wdGlvbnMpO1xuICAgIH1cbiAgICBpc0V4cGFuZGVkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5leHBhbmRlZDtcbiAgICB9XG4gICAgZ2V0Um93Q291bnQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRSb3dzO1xuICAgIH1cbn1cbiIsICJleHBvcnQgY2xhc3MgTW9ja1RlYW1TdG9yZSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMudHlwZSA9ICd0ZWFtJztcbiAgICAgICAgdGhpcy50ZWFtcyA9IFtcbiAgICAgICAgICAgIHsgaWQ6ICdhbHBoYScsIG5hbWU6ICdUZWFtIEFscGhhJyB9LFxuICAgICAgICAgICAgeyBpZDogJ2JldGEnLCBuYW1lOiAnVGVhbSBCZXRhJyB9XG4gICAgICAgIF07XG4gICAgfVxuICAgIGdldEJ5SWRzKGlkcykge1xuICAgICAgICByZXR1cm4gdGhpcy50ZWFtcy5maWx0ZXIodCA9PiBpZHMuaW5jbHVkZXModC5pZCkpO1xuICAgIH1cbn1cbmV4cG9ydCBjbGFzcyBNb2NrUmVzb3VyY2VTdG9yZSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMudHlwZSA9ICdyZXNvdXJjZSc7XG4gICAgICAgIHRoaXMucmVzb3VyY2VzID0gW1xuICAgICAgICAgICAgeyBpZDogJ2FsaWNlJywgbmFtZTogJ0FsaWNlJywgdGVhbUlkOiAnYWxwaGEnIH0sXG4gICAgICAgICAgICB7IGlkOiAnYm9iJywgbmFtZTogJ0JvYicsIHRlYW1JZDogJ2FscGhhJyB9LFxuICAgICAgICAgICAgeyBpZDogJ2Nhcm9sJywgbmFtZTogJ0Nhcm9sJywgdGVhbUlkOiAnYmV0YScgfSxcbiAgICAgICAgICAgIHsgaWQ6ICdkYXZlJywgbmFtZTogJ0RhdmUnLCB0ZWFtSWQ6ICdiZXRhJyB9XG4gICAgICAgIF07XG4gICAgfVxuICAgIGdldEJ5SWRzKGlkcykge1xuICAgICAgICByZXR1cm4gdGhpcy5yZXNvdXJjZXMuZmlsdGVyKHIgPT4gaWRzLmluY2x1ZGVzKHIuaWQpKTtcbiAgICB9XG59XG4iLCAiaW1wb3J0IHsgQ2FsZW5kYXJFdmVudHMgfSBmcm9tICcuLi9jb3JlL0NhbGVuZGFyRXZlbnRzJztcbmV4cG9ydCBjbGFzcyBEZW1vQXBwIHtcbiAgICBjb25zdHJ1Y3RvcihpbmRleGVkREJDb250ZXh0LCBkYXRhU2VlZGVyLCBhdWRpdFNlcnZpY2UsIGNhbGVuZGFyQXBwLCBkYXRlU2VydmljZSwgcmVzb3VyY2VTZXJ2aWNlLCBldmVudEJ1cykge1xuICAgICAgICB0aGlzLmluZGV4ZWREQkNvbnRleHQgPSBpbmRleGVkREJDb250ZXh0O1xuICAgICAgICB0aGlzLmRhdGFTZWVkZXIgPSBkYXRhU2VlZGVyO1xuICAgICAgICB0aGlzLmF1ZGl0U2VydmljZSA9IGF1ZGl0U2VydmljZTtcbiAgICAgICAgdGhpcy5jYWxlbmRhckFwcCA9IGNhbGVuZGFyQXBwO1xuICAgICAgICB0aGlzLmRhdGVTZXJ2aWNlID0gZGF0ZVNlcnZpY2U7XG4gICAgICAgIHRoaXMucmVzb3VyY2VTZXJ2aWNlID0gcmVzb3VyY2VTZXJ2aWNlO1xuICAgICAgICB0aGlzLmV2ZW50QnVzID0gZXZlbnRCdXM7XG4gICAgICAgIHRoaXMuY3VycmVudFZpZXcgPSAnc2ltcGxlJztcbiAgICB9XG4gICAgYXN5bmMgaW5pdCgpIHtcbiAgICAgICAgLy8gU2V0IGJhc2UgZGF0ZSB0byBtYXRjaCBtb2NrIGRhdGEgKDguIGRlY2VtYmVyIDIwMjUgPSBtYW5kYWcpXG4gICAgICAgIHRoaXMuZGF0ZVNlcnZpY2Uuc2V0QmFzZURhdGUobmV3IERhdGUoJzIwMjUtMTItMDgnKSk7XG4gICAgICAgIC8vIEluaXRpYWxpemUgSW5kZXhlZERCXG4gICAgICAgIGF3YWl0IHRoaXMuaW5kZXhlZERCQ29udGV4dC5pbml0aWFsaXplKCk7XG4gICAgICAgIGNvbnNvbGUubG9nKCdbRGVtb0FwcF0gSW5kZXhlZERCIGluaXRpYWxpemVkJyk7XG4gICAgICAgIC8vIFNlZWQgZGF0YSBpZiBlbXB0eVxuICAgICAgICBhd2FpdCB0aGlzLmRhdGFTZWVkZXIuc2VlZElmRW1wdHkoKTtcbiAgICAgICAgY29uc29sZS5sb2coJ1tEZW1vQXBwXSBEYXRhIHNlZWRpbmcgY29tcGxldGUnKTtcbiAgICAgICAgdGhpcy5jb250YWluZXIgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdzd3AtY2FsZW5kYXItY29udGFpbmVyJyk7XG4gICAgICAgIC8vIEluaXRpYWxpemUgQ2FsZW5kYXJBcHBcbiAgICAgICAgYXdhaXQgdGhpcy5jYWxlbmRhckFwcC5pbml0KHRoaXMuY29udGFpbmVyKTtcbiAgICAgICAgY29uc29sZS5sb2coJ1tEZW1vQXBwXSBDYWxlbmRhckFwcCBpbml0aWFsaXplZCcpO1xuICAgICAgICAvLyBTZXR1cCBkZW1vIFVJIGhhbmRsZXJzXG4gICAgICAgIHRoaXMuc2V0dXBOYXZpZ2F0aW9uKCk7XG4gICAgICAgIHRoaXMuc2V0dXBEcmF3ZXJUb2dnbGUoKTtcbiAgICAgICAgdGhpcy5zZXR1cFZpZXdTd2l0Y2hpbmcoKTtcbiAgICAgICAgdGhpcy5zZXR1cFdvcmt3ZWVrU2VsZWN0b3IoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5zZXR1cFJlc291cmNlU2VsZWN0b3IoKTtcbiAgICAgICAgLy8gTGlzdGVuIGZvciBjYWxlbmRhciBzdGF0dXMgZXZlbnRzXG4gICAgICAgIHRoaXMuc2V0dXBTdGF0dXNMaXN0ZW5lcnMoKTtcbiAgICAgICAgLy8gSW5pdGlhbCByZW5kZXJcbiAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENhbGVuZGFyRXZlbnRzLkNNRF9SRU5ERVIsIHsgdmlld0lkOiB0aGlzLmN1cnJlbnRWaWV3IH0pO1xuICAgIH1cbiAgICBzZXR1cE5hdmlnYXRpb24oKSB7XG4gICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdidG4tcHJldicpLm9uY2xpY2sgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ2FsZW5kYXJFdmVudHMuQ01EX05BVklHQVRFX1BSRVYpO1xuICAgICAgICB9O1xuICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYnRuLW5leHQnKS5vbmNsaWNrID0gKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENhbGVuZGFyRXZlbnRzLkNNRF9OQVZJR0FURV9ORVhUKTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgc2V0dXBWaWV3U3dpdGNoaW5nKCkge1xuICAgICAgICBjb25zdCBjaGlwcyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy52aWV3LWNoaXAnKTtcbiAgICAgICAgY2hpcHMuZm9yRWFjaChjaGlwID0+IHtcbiAgICAgICAgICAgIGNoaXAuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY2hpcHMuZm9yRWFjaChjID0+IGMuY2xhc3NMaXN0LnJlbW92ZSgnYWN0aXZlJykpO1xuICAgICAgICAgICAgICAgIGNoaXAuY2xhc3NMaXN0LmFkZCgnYWN0aXZlJyk7XG4gICAgICAgICAgICAgICAgY29uc3QgdmlldyA9IGNoaXAuZGF0YXNldC52aWV3O1xuICAgICAgICAgICAgICAgIGlmICh2aWV3KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudFZpZXcgPSB2aWV3O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVNlbGVjdG9yVmlzaWJpbGl0eSgpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ2FsZW5kYXJFdmVudHMuQ01EX1JFTkRFUiwgeyB2aWV3SWQ6IHZpZXcgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICB1cGRhdGVTZWxlY3RvclZpc2liaWxpdHkoKSB7XG4gICAgICAgIGNvbnN0IHNlbGVjdG9yID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcignc3dwLXJlc291cmNlLXNlbGVjdG9yJyk7XG4gICAgICAgIGNvbnN0IHNob3dTZWxlY3RvciA9IHRoaXMuY3VycmVudFZpZXcgPT09ICdwaWNrZXInIHx8IHRoaXMuY3VycmVudFZpZXcgPT09ICdkYXknO1xuICAgICAgICBzZWxlY3Rvcj8uY2xhc3NMaXN0LnRvZ2dsZSgnaGlkZGVuJywgIXNob3dTZWxlY3Rvcik7XG4gICAgfVxuICAgIHNldHVwRHJhd2VyVG9nZ2xlKCkge1xuICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYnRuLWRyYXdlcicpLm9uY2xpY2sgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ2FsZW5kYXJFdmVudHMuQ01EX0RSQVdFUl9UT0dHTEUpO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBzZXR1cFdvcmt3ZWVrU2VsZWN0b3IoKSB7XG4gICAgICAgIGNvbnN0IHdvcmt3ZWVrU2VsZWN0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3dvcmt3ZWVrLXNlbGVjdCcpO1xuICAgICAgICB3b3Jrd2Vla1NlbGVjdD8uYWRkRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcHJlc2V0SWQgPSB3b3Jrd2Vla1NlbGVjdC52YWx1ZTtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMuZW1pdChDYWxlbmRhckV2ZW50cy5DTURfV09SS1dFRUtfQ0hBTkdFLCB7IHByZXNldElkIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgYXN5bmMgc2V0dXBSZXNvdXJjZVNlbGVjdG9yKCkge1xuICAgICAgICBjb25zdCByZXNvdXJjZXMgPSBhd2FpdCB0aGlzLnJlc291cmNlU2VydmljZS5nZXRBbGwoKTtcbiAgICAgICAgY29uc3QgY29udGFpbmVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLnJlc291cmNlLWNoZWNrYm94ZXMnKTtcbiAgICAgICAgaWYgKCFjb250YWluZXIpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNvbnRhaW5lci5pbm5lckhUTUwgPSAnJztcbiAgICAgICAgcmVzb3VyY2VzLmZvckVhY2gociA9PiB7XG4gICAgICAgICAgICBjb25zdCBsYWJlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xhYmVsJyk7XG4gICAgICAgICAgICBsYWJlbC5pbm5lckhUTUwgPSBgXHJcbiAgICAgICAgPGlucHV0IHR5cGU9XCJjaGVja2JveFwiIHZhbHVlPVwiJHtyLmlkfVwiIGNoZWNrZWQ+XHJcbiAgICAgICAgJHtyLmRpc3BsYXlOYW1lfVxyXG4gICAgICBgO1xuICAgICAgICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKGxhYmVsKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjaGVja2VkID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3JBbGwoJ2lucHV0OmNoZWNrZWQnKTtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlcyA9IEFycmF5LmZyb20oY2hlY2tlZCkubWFwKGNiID0+IGNiLnZhbHVlKTtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMuZW1pdChDYWxlbmRhckV2ZW50cy5DTURfVklFV19VUERBVEUsIHsgdHlwZTogJ3Jlc291cmNlJywgdmFsdWVzIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgc2V0dXBTdGF0dXNMaXN0ZW5lcnMoKSB7XG4gICAgICAgIHRoaXMuY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoJ2NhbGVuZGFyOnN0YXR1czpyZWFkeScsICgpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdbRGVtb0FwcF0gQ2FsZW5kYXIgcmVhZHknKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoJ2NhbGVuZGFyOnN0YXR1czpyZW5kZXJlZCcsICgoZSkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ1tEZW1vQXBwXSBDYWxlbmRhciByZW5kZXJlZDonLCBlLmRldGFpbC52aWV3SWQpO1xuICAgICAgICB9KSk7XG4gICAgICAgIHRoaXMuY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoJ2NhbGVuZGFyOnN0YXR1czplcnJvcicsICgoZSkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignW0RlbW9BcHBdIENhbGVuZGFyIGVycm9yOicsIGUuZGV0YWlsLm1lc3NhZ2UpO1xuICAgICAgICB9KSk7XG4gICAgfVxufVxuIiwgIi8qKlxuICogQ2VudHJhbCBldmVudCBkaXNwYXRjaGVyIGZvciBjYWxlbmRhciB1c2luZyBET00gQ3VzdG9tRXZlbnRzXG4gKiBQcm92aWRlcyBsb2dnaW5nIGFuZCBkZWJ1Z2dpbmcgY2FwYWJpbGl0aWVzXG4gKi9cbmV4cG9ydCBjbGFzcyBFdmVudEJ1cyB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuZXZlbnRMb2cgPSBbXTtcbiAgICAgICAgdGhpcy5kZWJ1ZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmxpc3RlbmVycyA9IG5ldyBTZXQoKTtcbiAgICAgICAgLy8gTG9nIGNvbmZpZ3VyYXRpb24gZm9yIGRpZmZlcmVudCBjYXRlZ29yaWVzXG4gICAgICAgIHRoaXMubG9nQ29uZmlnID0ge1xuICAgICAgICAgICAgY2FsZW5kYXI6IHRydWUsXG4gICAgICAgICAgICBncmlkOiB0cnVlLFxuICAgICAgICAgICAgZXZlbnQ6IHRydWUsXG4gICAgICAgICAgICBzY3JvbGw6IHRydWUsXG4gICAgICAgICAgICBuYXZpZ2F0aW9uOiB0cnVlLFxuICAgICAgICAgICAgdmlldzogdHJ1ZSxcbiAgICAgICAgICAgIGRlZmF1bHQ6IHRydWVcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIHRvIGFuIGV2ZW50IHZpYSBET00gYWRkRXZlbnRMaXN0ZW5lclxuICAgICAqL1xuICAgIG9uKGV2ZW50VHlwZSwgaGFuZGxlciwgb3B0aW9ucykge1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50VHlwZSwgaGFuZGxlciwgb3B0aW9ucyk7XG4gICAgICAgIC8vIFRyYWNrIGZvciBjbGVhbnVwXG4gICAgICAgIHRoaXMubGlzdGVuZXJzLmFkZCh7IGV2ZW50VHlwZSwgaGFuZGxlciwgb3B0aW9ucyB9KTtcbiAgICAgICAgLy8gUmV0dXJuIHVuc3Vic2NyaWJlIGZ1bmN0aW9uXG4gICAgICAgIHJldHVybiAoKSA9PiB0aGlzLm9mZihldmVudFR5cGUsIGhhbmRsZXIpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmUgdG8gYW4gZXZlbnQgb25jZVxuICAgICAqL1xuICAgIG9uY2UoZXZlbnRUeXBlLCBoYW5kbGVyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9uKGV2ZW50VHlwZSwgaGFuZGxlciwgeyBvbmNlOiB0cnVlIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBVbnN1YnNjcmliZSBmcm9tIGFuIGV2ZW50XG4gICAgICovXG4gICAgb2ZmKGV2ZW50VHlwZSwgaGFuZGxlcikge1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50VHlwZSwgaGFuZGxlcik7XG4gICAgICAgIC8vIFJlbW92ZSBmcm9tIHRyYWNraW5nXG4gICAgICAgIGZvciAoY29uc3QgbGlzdGVuZXIgb2YgdGhpcy5saXN0ZW5lcnMpIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lci5ldmVudFR5cGUgPT09IGV2ZW50VHlwZSAmJiBsaXN0ZW5lci5oYW5kbGVyID09PSBoYW5kbGVyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5saXN0ZW5lcnMuZGVsZXRlKGxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBFbWl0IGFuIGV2ZW50IHZpYSBET00gQ3VzdG9tRXZlbnRcbiAgICAgKi9cbiAgICBlbWl0KGV2ZW50VHlwZSwgZGV0YWlsID0ge30pIHtcbiAgICAgICAgLy8gVmFsaWRhdGUgZXZlbnRUeXBlXG4gICAgICAgIGlmICghZXZlbnRUeXBlKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZXZlbnQgPSBuZXcgQ3VzdG9tRXZlbnQoZXZlbnRUeXBlLCB7XG4gICAgICAgICAgICBkZXRhaWw6IGRldGFpbCA/PyB7fSxcbiAgICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICAvLyBMb2cgZXZlbnQgd2l0aCBncm91cGluZ1xuICAgICAgICBpZiAodGhpcy5kZWJ1Zykge1xuICAgICAgICAgICAgdGhpcy5sb2dFdmVudFdpdGhHcm91cGluZyhldmVudFR5cGUsIGRldGFpbCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5ldmVudExvZy5wdXNoKHtcbiAgICAgICAgICAgIHR5cGU6IGV2ZW50VHlwZSxcbiAgICAgICAgICAgIGRldGFpbDogZGV0YWlsID8/IHt9LFxuICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpXG4gICAgICAgIH0pO1xuICAgICAgICAvLyBFbWl0IG9uIGRvY3VtZW50IChvbmx5IERPTSBldmVudHMgbm93KVxuICAgICAgICByZXR1cm4gIWRvY3VtZW50LmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBMb2cgZXZlbnQgd2l0aCBjb25zb2xlIGdyb3VwaW5nXG4gICAgICovXG4gICAgbG9nRXZlbnRXaXRoR3JvdXBpbmcoZXZlbnRUeXBlLCBfZGV0YWlsKSB7XG4gICAgICAgIC8vIEV4dHJhY3QgY2F0ZWdvcnkgZnJvbSBldmVudCB0eXBlIChlLmcuLCAnY2FsZW5kYXI6ZGF0ZWNoYW5nZWQnIFx1MjE5MiAnY2FsZW5kYXInKVxuICAgICAgICBjb25zdCBjYXRlZ29yeSA9IHRoaXMuZXh0cmFjdENhdGVnb3J5KGV2ZW50VHlwZSk7XG4gICAgICAgIC8vIE9ubHkgbG9nIGlmIGNhdGVnb3J5IGlzIGVuYWJsZWRcbiAgICAgICAgaWYgKCF0aGlzLmxvZ0NvbmZpZ1tjYXRlZ29yeV0pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBHZXQgY2F0ZWdvcnkgZW1vamkgYW5kIGNvbG9yICh1c2VkIGZvciBmdXR1cmUgY29uc29sZSBzdHlsaW5nKVxuICAgICAgICB0aGlzLmdldENhdGVnb3J5U3R5bGUoY2F0ZWdvcnkpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBFeHRyYWN0IGNhdGVnb3J5IGZyb20gZXZlbnQgdHlwZVxuICAgICAqL1xuICAgIGV4dHJhY3RDYXRlZ29yeShldmVudFR5cGUpIHtcbiAgICAgICAgaWYgKCFldmVudFR5cGUpIHtcbiAgICAgICAgICAgIHJldHVybiAndW5rbm93bic7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV2ZW50VHlwZS5pbmNsdWRlcygnOicpKSB7XG4gICAgICAgICAgICByZXR1cm4gZXZlbnRUeXBlLnNwbGl0KCc6JylbMF07XG4gICAgICAgIH1cbiAgICAgICAgLy8gRmFsbGJhY2s6IHRyeSB0byBkZXRlY3QgY2F0ZWdvcnkgZnJvbSBldmVudCBuYW1lIHBhdHRlcm5zXG4gICAgICAgIGNvbnN0IGxvd2VyVHlwZSA9IGV2ZW50VHlwZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICBpZiAobG93ZXJUeXBlLmluY2x1ZGVzKCdncmlkJykgfHwgbG93ZXJUeXBlLmluY2x1ZGVzKCdyZW5kZXJlZCcpKVxuICAgICAgICAgICAgcmV0dXJuICdncmlkJztcbiAgICAgICAgaWYgKGxvd2VyVHlwZS5pbmNsdWRlcygnZXZlbnQnKSB8fCBsb3dlclR5cGUuaW5jbHVkZXMoJ3N5bmMnKSlcbiAgICAgICAgICAgIHJldHVybiAnZXZlbnQnO1xuICAgICAgICBpZiAobG93ZXJUeXBlLmluY2x1ZGVzKCdzY3JvbGwnKSlcbiAgICAgICAgICAgIHJldHVybiAnc2Nyb2xsJztcbiAgICAgICAgaWYgKGxvd2VyVHlwZS5pbmNsdWRlcygnbmF2JykgfHwgbG93ZXJUeXBlLmluY2x1ZGVzKCdkYXRlJykpXG4gICAgICAgICAgICByZXR1cm4gJ25hdmlnYXRpb24nO1xuICAgICAgICBpZiAobG93ZXJUeXBlLmluY2x1ZGVzKCd2aWV3JykpXG4gICAgICAgICAgICByZXR1cm4gJ3ZpZXcnO1xuICAgICAgICByZXR1cm4gJ2RlZmF1bHQnO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgc3R5bGluZyBmb3IgZGlmZmVyZW50IGNhdGVnb3JpZXNcbiAgICAgKi9cbiAgICBnZXRDYXRlZ29yeVN0eWxlKGNhdGVnb3J5KSB7XG4gICAgICAgIGNvbnN0IHN0eWxlcyA9IHtcbiAgICAgICAgICAgIGNhbGVuZGFyOiB7IGVtb2ppOiAnXHVEODNEXHVEQ0M1JywgY29sb3I6ICcjMjE5NkYzJyB9LFxuICAgICAgICAgICAgZ3JpZDogeyBlbW9qaTogJ1x1RDgzRFx1RENDQScsIGNvbG9yOiAnIzRDQUY1MCcgfSxcbiAgICAgICAgICAgIGV2ZW50OiB7IGVtb2ppOiAnXHVEODNEXHVEQ0NDJywgY29sb3I6ICcjRkY5ODAwJyB9LFxuICAgICAgICAgICAgc2Nyb2xsOiB7IGVtb2ppOiAnXHVEODNEXHVEQ0RDJywgY29sb3I6ICcjOUMyN0IwJyB9LFxuICAgICAgICAgICAgbmF2aWdhdGlvbjogeyBlbW9qaTogJ1x1RDgzRVx1RERFRCcsIGNvbG9yOiAnI0Y0NDMzNicgfSxcbiAgICAgICAgICAgIHZpZXc6IHsgZW1vamk6ICdcdUQ4M0RcdURDNDEnLCBjb2xvcjogJyMwMEJDRDQnIH0sXG4gICAgICAgICAgICBkZWZhdWx0OiB7IGVtb2ppOiAnXHVEODNEXHVEQ0UyJywgY29sb3I6ICcjNjA3RDhCJyB9XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBzdHlsZXNbY2F0ZWdvcnldIHx8IHN0eWxlcy5kZWZhdWx0O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDb25maWd1cmUgbG9nZ2luZyBmb3Igc3BlY2lmaWMgY2F0ZWdvcmllc1xuICAgICAqL1xuICAgIHNldExvZ0NvbmZpZyhjb25maWcpIHtcbiAgICAgICAgdGhpcy5sb2dDb25maWcgPSB7IC4uLnRoaXMubG9nQ29uZmlnLCAuLi5jb25maWcgfTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGN1cnJlbnQgbG9nIGNvbmZpZ3VyYXRpb25cbiAgICAgKi9cbiAgICBnZXRMb2dDb25maWcoKSB7XG4gICAgICAgIHJldHVybiB7IC4uLnRoaXMubG9nQ29uZmlnIH07XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBldmVudCBoaXN0b3J5XG4gICAgICovXG4gICAgZ2V0RXZlbnRMb2coZXZlbnRUeXBlKSB7XG4gICAgICAgIGlmIChldmVudFR5cGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmV2ZW50TG9nLmZpbHRlcihlID0+IGUudHlwZSA9PT0gZXZlbnRUeXBlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5ldmVudExvZztcbiAgICB9XG4gICAgLyoqXG4gICAgICogRW5hYmxlL2Rpc2FibGUgZGVidWcgbW9kZVxuICAgICAqL1xuICAgIHNldERlYnVnKGVuYWJsZWQpIHtcbiAgICAgICAgdGhpcy5kZWJ1ZyA9IGVuYWJsZWQ7XG4gICAgfVxufVxuIiwgIi8qKlxuICogSW5kZXhlZERCQ29udGV4dCAtIERhdGFiYXNlIGNvbm5lY3Rpb24gbWFuYWdlclxuICpcbiAqIFJFU1BPTlNJQklMSVRZOlxuICogLSBPcGVucyBhbmQgbWFuYWdlcyBJREJEYXRhYmFzZSBjb25uZWN0aW9uIGxpZmVjeWNsZVxuICogLSBDcmVhdGVzIG9iamVjdCBzdG9yZXMgdmlhIGluamVjdGVkIElTdG9yZSBpbXBsZW1lbnRhdGlvbnNcbiAqIC0gUHJvdmlkZXMgc2hhcmVkIElEQkRhdGFiYXNlIGluc3RhbmNlIHRvIGFsbCBzZXJ2aWNlc1xuICovXG5leHBvcnQgY2xhc3MgSW5kZXhlZERCQ29udGV4dCB7XG4gICAgY29uc3RydWN0b3Ioc3RvcmVzKSB7XG4gICAgICAgIHRoaXMuZGIgPSBudWxsO1xuICAgICAgICB0aGlzLmluaXRpYWxpemVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuc3RvcmVzID0gc3RvcmVzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplIGFuZCBvcGVuIHRoZSBkYXRhYmFzZVxuICAgICAqL1xuICAgIGFzeW5jIGluaXRpYWxpemUoKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gaW5kZXhlZERCLm9wZW4oSW5kZXhlZERCQ29udGV4dC5EQl9OQU1FLCBJbmRleGVkREJDb250ZXh0LkRCX1ZFUlNJT04pO1xuICAgICAgICAgICAgcmVxdWVzdC5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBvcGVuIEluZGV4ZWREQjogJHtyZXF1ZXN0LmVycm9yfWApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmRiID0gcmVxdWVzdC5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgdGhpcy5pbml0aWFsaXplZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcXVlc3Qub251cGdyYWRlbmVlZGVkID0gKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGIgPSBldmVudC50YXJnZXQucmVzdWx0O1xuICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBhbGwgZW50aXR5IHN0b3JlcyB2aWEgaW5qZWN0ZWQgSVN0b3JlIGltcGxlbWVudGF0aW9uc1xuICAgICAgICAgICAgICAgIHRoaXMuc3RvcmVzLmZvckVhY2goc3RvcmUgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWRiLm9iamVjdFN0b3JlTmFtZXMuY29udGFpbnMoc3RvcmUuc3RvcmVOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RvcmUuY3JlYXRlKGRiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIGRhdGFiYXNlIGlzIGluaXRpYWxpemVkXG4gICAgICovXG4gICAgaXNJbml0aWFsaXplZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW5pdGlhbGl6ZWQ7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBJREJEYXRhYmFzZSBpbnN0YW5jZVxuICAgICAqL1xuICAgIGdldERhdGFiYXNlKCkge1xuICAgICAgICBpZiAoIXRoaXMuZGIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW5kZXhlZERCIG5vdCBpbml0aWFsaXplZC4gQ2FsbCBpbml0aWFsaXplKCkgZmlyc3QuJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZGI7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENsb3NlIGRhdGFiYXNlIGNvbm5lY3Rpb25cbiAgICAgKi9cbiAgICBjbG9zZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuZGIpIHtcbiAgICAgICAgICAgIHRoaXMuZGIuY2xvc2UoKTtcbiAgICAgICAgICAgIHRoaXMuZGIgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5pbml0aWFsaXplZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIERlbGV0ZSBlbnRpcmUgZGF0YWJhc2UgKGZvciB0ZXN0aW5nL3Jlc2V0KVxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBkZWxldGVEYXRhYmFzZSgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJlcXVlc3QgPSBpbmRleGVkREIuZGVsZXRlRGF0YWJhc2UoSW5kZXhlZERCQ29udGV4dC5EQl9OQU1FKTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25zdWNjZXNzID0gKCkgPT4gcmVzb2x2ZSgpO1xuICAgICAgICAgICAgcmVxdWVzdC5vbmVycm9yID0gKCkgPT4gcmVqZWN0KG5ldyBFcnJvcihgRmFpbGVkIHRvIGRlbGV0ZSBkYXRhYmFzZTogJHtyZXF1ZXN0LmVycm9yfWApKTtcbiAgICAgICAgfSk7XG4gICAgfVxufVxuSW5kZXhlZERCQ29udGV4dC5EQl9OQU1FID0gJ0NhbGVuZGFyVjJEQic7XG5JbmRleGVkREJDb250ZXh0LkRCX1ZFUlNJT04gPSA0O1xuIiwgIi8qKlxuICogRXZlbnRTdG9yZSAtIEluZGV4ZWREQiBPYmplY3RTdG9yZSBkZWZpbml0aW9uIGZvciBjYWxlbmRhciBldmVudHNcbiAqL1xuZXhwb3J0IGNsYXNzIEV2ZW50U3RvcmUge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnN0b3JlTmFtZSA9IEV2ZW50U3RvcmUuU1RPUkVfTkFNRTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ3JlYXRlIHRoZSBldmVudHMgT2JqZWN0U3RvcmUgd2l0aCBpbmRleGVzXG4gICAgICovXG4gICAgY3JlYXRlKGRiKSB7XG4gICAgICAgIGNvbnN0IHN0b3JlID0gZGIuY3JlYXRlT2JqZWN0U3RvcmUoRXZlbnRTdG9yZS5TVE9SRV9OQU1FLCB7IGtleVBhdGg6ICdpZCcgfSk7XG4gICAgICAgIC8vIEluZGV4OiBzdGFydCAoZm9yIGRhdGUgcmFuZ2UgcXVlcmllcylcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ3N0YXJ0JywgJ3N0YXJ0JywgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgICAgICAvLyBJbmRleDogZW5kIChmb3IgZGF0ZSByYW5nZSBxdWVyaWVzKVxuICAgICAgICBzdG9yZS5jcmVhdGVJbmRleCgnZW5kJywgJ2VuZCcsIHsgdW5pcXVlOiBmYWxzZSB9KTtcbiAgICAgICAgLy8gSW5kZXg6IHN5bmNTdGF0dXMgKGZvciBmaWx0ZXJpbmcgYnkgc3luYyBzdGF0ZSlcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ3N5bmNTdGF0dXMnLCAnc3luY1N0YXR1cycsIHsgdW5pcXVlOiBmYWxzZSB9KTtcbiAgICAgICAgLy8gSW5kZXg6IHJlc291cmNlSWQgKGZvciByZXNvdXJjZS1tb2RlIGZpbHRlcmluZylcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ3Jlc291cmNlSWQnLCAncmVzb3VyY2VJZCcsIHsgdW5pcXVlOiBmYWxzZSB9KTtcbiAgICAgICAgLy8gSW5kZXg6IGN1c3RvbWVySWQgKGZvciBjdXN0b21lci1jZW50cmljIHF1ZXJpZXMpXG4gICAgICAgIHN0b3JlLmNyZWF0ZUluZGV4KCdjdXN0b21lcklkJywgJ2N1c3RvbWVySWQnLCB7IHVuaXF1ZTogZmFsc2UgfSk7XG4gICAgICAgIC8vIEluZGV4OiBib29raW5nSWQgKGZvciBldmVudC10by1ib29raW5nIGxvb2t1cHMpXG4gICAgICAgIHN0b3JlLmNyZWF0ZUluZGV4KCdib29raW5nSWQnLCAnYm9va2luZ0lkJywgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgICAgICAvLyBDb21wb3VuZCBpbmRleDogc3RhcnRFbmQgKGZvciBvcHRpbWl6ZWQgcmFuZ2UgcXVlcmllcylcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ3N0YXJ0RW5kJywgWydzdGFydCcsICdlbmQnXSwgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgIH1cbn1cbkV2ZW50U3RvcmUuU1RPUkVfTkFNRSA9ICdldmVudHMnO1xuIiwgIi8qKlxuICogRXZlbnRTZXJpYWxpemF0aW9uIC0gSGFuZGxlcyBEYXRlIGZpZWxkIHNlcmlhbGl6YXRpb24gZm9yIEluZGV4ZWREQlxuICpcbiAqIEluZGV4ZWREQiBkb2Vzbid0IHN0b3JlIERhdGUgb2JqZWN0cyBkaXJlY3RseSwgc28gd2UgY29udmVydDpcbiAqIC0gRGF0ZSBcdTIxOTIgSVNPIHN0cmluZyAoc2VyaWFsaXplKSB3aGVuIHdyaXRpbmdcbiAqIC0gSVNPIHN0cmluZyBcdTIxOTIgRGF0ZSAoZGVzZXJpYWxpemUpIHdoZW4gcmVhZGluZ1xuICovXG5leHBvcnQgY2xhc3MgRXZlbnRTZXJpYWxpemF0aW9uIHtcbiAgICAvKipcbiAgICAgKiBTZXJpYWxpemUgZXZlbnQgZm9yIEluZGV4ZWREQiBzdG9yYWdlXG4gICAgICovXG4gICAgc3RhdGljIHNlcmlhbGl6ZShldmVudCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4uZXZlbnQsXG4gICAgICAgICAgICBzdGFydDogZXZlbnQuc3RhcnQgaW5zdGFuY2VvZiBEYXRlID8gZXZlbnQuc3RhcnQudG9JU09TdHJpbmcoKSA6IGV2ZW50LnN0YXJ0LFxuICAgICAgICAgICAgZW5kOiBldmVudC5lbmQgaW5zdGFuY2VvZiBEYXRlID8gZXZlbnQuZW5kLnRvSVNPU3RyaW5nKCkgOiBldmVudC5lbmRcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRGVzZXJpYWxpemUgZXZlbnQgZnJvbSBJbmRleGVkREIgc3RvcmFnZVxuICAgICAqL1xuICAgIHN0YXRpYyBkZXNlcmlhbGl6ZShkYXRhKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi5kYXRhLFxuICAgICAgICAgICAgc3RhcnQ6IHR5cGVvZiBkYXRhLnN0YXJ0ID09PSAnc3RyaW5nJyA/IG5ldyBEYXRlKGRhdGEuc3RhcnQpIDogZGF0YS5zdGFydCxcbiAgICAgICAgICAgIGVuZDogdHlwZW9mIGRhdGEuZW5kID09PSAnc3RyaW5nJyA/IG5ldyBEYXRlKGRhdGEuZW5kKSA6IGRhdGEuZW5kXG4gICAgICAgIH07XG4gICAgfVxufVxuIiwgIi8qKlxuICogU3luY1BsdWdpbjxUIGV4dGVuZHMgSVN5bmM+IC0gUGx1Z2dhYmxlIHN5bmMgZnVuY3Rpb25hbGl0eSBmb3IgZW50aXR5IHNlcnZpY2VzXG4gKlxuICogQ09NUE9TSVRJT04gUEFUVEVSTjpcbiAqIC0gRW5jYXBzdWxhdGVzIGFsbCBzeW5jLXJlbGF0ZWQgbG9naWMgaW4gc2VwYXJhdGUgY2xhc3NcbiAqIC0gQ29tcG9zZWQgaW50byBCYXNlRW50aXR5U2VydmljZSAobm90IGluaGVyaXRhbmNlKVxuICovXG5leHBvcnQgY2xhc3MgU3luY1BsdWdpbiB7XG4gICAgY29uc3RydWN0b3Ioc2VydmljZSkge1xuICAgICAgICB0aGlzLnNlcnZpY2UgPSBzZXJ2aWNlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBNYXJrIGVudGl0eSBhcyBzdWNjZXNzZnVsbHkgc3luY2VkXG4gICAgICovXG4gICAgYXN5bmMgbWFya0FzU3luY2VkKGlkKSB7XG4gICAgICAgIGNvbnN0IGVudGl0eSA9IGF3YWl0IHRoaXMuc2VydmljZS5nZXQoaWQpO1xuICAgICAgICBpZiAoZW50aXR5KSB7XG4gICAgICAgICAgICBlbnRpdHkuc3luY1N0YXR1cyA9ICdzeW5jZWQnO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5zZXJ2aWNlLnNhdmUoZW50aXR5KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBNYXJrIGVudGl0eSBhcyBzeW5jIGVycm9yXG4gICAgICovXG4gICAgYXN5bmMgbWFya0FzRXJyb3IoaWQpIHtcbiAgICAgICAgY29uc3QgZW50aXR5ID0gYXdhaXQgdGhpcy5zZXJ2aWNlLmdldChpZCk7XG4gICAgICAgIGlmIChlbnRpdHkpIHtcbiAgICAgICAgICAgIGVudGl0eS5zeW5jU3RhdHVzID0gJ2Vycm9yJztcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuc2VydmljZS5zYXZlKGVudGl0eSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGN1cnJlbnQgc3luYyBzdGF0dXMgZm9yIGFuIGVudGl0eVxuICAgICAqL1xuICAgIGFzeW5jIGdldFN5bmNTdGF0dXMoaWQpIHtcbiAgICAgICAgY29uc3QgZW50aXR5ID0gYXdhaXQgdGhpcy5zZXJ2aWNlLmdldChpZCk7XG4gICAgICAgIHJldHVybiBlbnRpdHkgPyBlbnRpdHkuc3luY1N0YXR1cyA6IG51bGw7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBlbnRpdGllcyBieSBzeW5jIHN0YXR1cyB1c2luZyBJbmRleGVkREIgaW5kZXhcbiAgICAgKi9cbiAgICBhc3luYyBnZXRCeVN5bmNTdGF0dXMoc3luY1N0YXR1cykge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSB0aGlzLnNlcnZpY2UuZGIudHJhbnNhY3Rpb24oW3RoaXMuc2VydmljZS5zdG9yZU5hbWVdLCAncmVhZG9ubHknKTtcbiAgICAgICAgICAgIGNvbnN0IHN0b3JlID0gdHJhbnNhY3Rpb24ub2JqZWN0U3RvcmUodGhpcy5zZXJ2aWNlLnN0b3JlTmFtZSk7XG4gICAgICAgICAgICBjb25zdCBpbmRleCA9IHN0b3JlLmluZGV4KCdzeW5jU3RhdHVzJyk7XG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gaW5kZXguZ2V0QWxsKHN5bmNTdGF0dXMpO1xuICAgICAgICAgICAgcmVxdWVzdC5vbnN1Y2Nlc3MgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IHJlcXVlc3QucmVzdWx0O1xuICAgICAgICAgICAgICAgIGNvbnN0IGVudGl0aWVzID0gZGF0YS5tYXAoaXRlbSA9PiB0aGlzLnNlcnZpY2UuZGVzZXJpYWxpemUoaXRlbSkpO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoZW50aXRpZXMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gZ2V0IGJ5IHN5bmMgc3RhdHVzICR7c3luY1N0YXR1c306ICR7cmVxdWVzdC5lcnJvcn1gKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICB9XG59XG4iLCAiLyoqXG4gKiBDb3JlRXZlbnRzIC0gQ29uc29saWRhdGVkIGVzc2VudGlhbCBldmVudHMgZm9yIHRoZSBjYWxlbmRhciBWMlxuICovXG5leHBvcnQgY29uc3QgQ29yZUV2ZW50cyA9IHtcbiAgICAvLyBMaWZlY3ljbGUgZXZlbnRzXG4gICAgSU5JVElBTElaRUQ6ICdjb3JlOmluaXRpYWxpemVkJyxcbiAgICBSRUFEWTogJ2NvcmU6cmVhZHknLFxuICAgIERFU1RST1lFRDogJ2NvcmU6ZGVzdHJveWVkJyxcbiAgICAvLyBWaWV3IGV2ZW50c1xuICAgIFZJRVdfQ0hBTkdFRDogJ3ZpZXc6Y2hhbmdlZCcsXG4gICAgVklFV19SRU5ERVJFRDogJ3ZpZXc6cmVuZGVyZWQnLFxuICAgIC8vIE5hdmlnYXRpb24gZXZlbnRzXG4gICAgREFURV9DSEFOR0VEOiAnbmF2OmRhdGUtY2hhbmdlZCcsXG4gICAgTkFWSUdBVElPTl9DT01QTEVURUQ6ICduYXY6bmF2aWdhdGlvbi1jb21wbGV0ZWQnLFxuICAgIC8vIERhdGEgZXZlbnRzXG4gICAgREFUQV9MT0FESU5HOiAnZGF0YTpsb2FkaW5nJyxcbiAgICBEQVRBX0xPQURFRDogJ2RhdGE6bG9hZGVkJyxcbiAgICBEQVRBX0VSUk9SOiAnZGF0YTplcnJvcicsXG4gICAgLy8gR3JpZCBldmVudHNcbiAgICBHUklEX1JFTkRFUkVEOiAnZ3JpZDpyZW5kZXJlZCcsXG4gICAgR1JJRF9DTElDS0VEOiAnZ3JpZDpjbGlja2VkJyxcbiAgICAvLyBFdmVudCBtYW5hZ2VtZW50XG4gICAgRVZFTlRfQ1JFQVRFRDogJ2V2ZW50OmNyZWF0ZWQnLFxuICAgIEVWRU5UX1VQREFURUQ6ICdldmVudDp1cGRhdGVkJyxcbiAgICBFVkVOVF9ERUxFVEVEOiAnZXZlbnQ6ZGVsZXRlZCcsXG4gICAgRVZFTlRfU0VMRUNURUQ6ICdldmVudDpzZWxlY3RlZCcsXG4gICAgLy8gRXZlbnQgZHJhZy1kcm9wXG4gICAgRVZFTlRfRFJBR19TVEFSVDogJ2V2ZW50OmRyYWctc3RhcnQnLFxuICAgIEVWRU5UX0RSQUdfTU9WRTogJ2V2ZW50OmRyYWctbW92ZScsXG4gICAgRVZFTlRfRFJBR19FTkQ6ICdldmVudDpkcmFnLWVuZCcsXG4gICAgRVZFTlRfRFJBR19DQU5DRUw6ICdldmVudDpkcmFnLWNhbmNlbCcsXG4gICAgRVZFTlRfRFJBR19DT0xVTU5fQ0hBTkdFOiAnZXZlbnQ6ZHJhZy1jb2x1bW4tY2hhbmdlJyxcbiAgICAvLyBIZWFkZXIgZHJhZyAodGltZWQgXHUyMTkyIGhlYWRlciBjb252ZXJzaW9uKVxuICAgIEVWRU5UX0RSQUdfRU5URVJfSEVBREVSOiAnZXZlbnQ6ZHJhZy1lbnRlci1oZWFkZXInLFxuICAgIEVWRU5UX0RSQUdfTU9WRV9IRUFERVI6ICdldmVudDpkcmFnLW1vdmUtaGVhZGVyJyxcbiAgICBFVkVOVF9EUkFHX0xFQVZFX0hFQURFUjogJ2V2ZW50OmRyYWctbGVhdmUtaGVhZGVyJyxcbiAgICAvLyBFdmVudCByZXNpemVcbiAgICBFVkVOVF9SRVNJWkVfU1RBUlQ6ICdldmVudDpyZXNpemUtc3RhcnQnLFxuICAgIEVWRU5UX1JFU0laRV9FTkQ6ICdldmVudDpyZXNpemUtZW5kJyxcbiAgICAvLyBFZGdlIHNjcm9sbFxuICAgIEVER0VfU0NST0xMX1RJQ0s6ICdlZGdlLXNjcm9sbDp0aWNrJyxcbiAgICBFREdFX1NDUk9MTF9TVEFSVEVEOiAnZWRnZS1zY3JvbGw6c3RhcnRlZCcsXG4gICAgRURHRV9TQ1JPTExfU1RPUFBFRDogJ2VkZ2Utc2Nyb2xsOnN0b3BwZWQnLFxuICAgIC8vIFN5c3RlbSBldmVudHNcbiAgICBFUlJPUjogJ3N5c3RlbTplcnJvcicsXG4gICAgLy8gU3luYyBldmVudHNcbiAgICBTWU5DX1NUQVJURUQ6ICdzeW5jOnN0YXJ0ZWQnLFxuICAgIFNZTkNfQ09NUExFVEVEOiAnc3luYzpjb21wbGV0ZWQnLFxuICAgIFNZTkNfRkFJTEVEOiAnc3luYzpmYWlsZWQnLFxuICAgIC8vIEVudGl0eSBldmVudHMgLSBmb3IgYXVkaXQgYW5kIHN5bmNcbiAgICBFTlRJVFlfU0FWRUQ6ICdlbnRpdHk6c2F2ZWQnLFxuICAgIEVOVElUWV9ERUxFVEVEOiAnZW50aXR5OmRlbGV0ZWQnLFxuICAgIC8vIEF1ZGl0IGV2ZW50c1xuICAgIEFVRElUX0xPR0dFRDogJ2F1ZGl0OmxvZ2dlZCcsXG4gICAgLy8gUmVuZGVyaW5nIGV2ZW50c1xuICAgIEVWRU5UU19SRU5ERVJFRDogJ2V2ZW50czpyZW5kZXJlZCdcbn07XG4iLCAiZXhwb3J0IGZ1bmN0aW9uIHNwbGl0SlNPTlBhdGgocGF0aDogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IHBhcnRzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGxldCBjdXJyZW50UGFydCA9ICcnO1xuICAgIGxldCBpblNpbmdsZVF1b3RlcyA9IGZhbHNlO1xuICAgIGxldCBpbkJyYWNrZXRzID0gMDtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGF0aC5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBjaGFyID0gcGF0aFtpXTtcblxuICAgICAgICBpZiAoY2hhciA9PT0gXCInXCIgJiYgcGF0aFtpIC0gMV0gIT09ICdcXFxcJykge1xuICAgICAgICAgICAgLy8gVG9nZ2xlIHNpbmdsZSBxdW90ZSBmbGFnIGlmIG5vdCBlc2NhcGVkXG4gICAgICAgICAgICBpblNpbmdsZVF1b3RlcyA9ICFpblNpbmdsZVF1b3RlcztcbiAgICAgICAgfSBlbHNlIGlmIChjaGFyID09PSAnWycgJiYgIWluU2luZ2xlUXVvdGVzKSB7XG4gICAgICAgICAgICAvLyBJbmNyZWFzZSBicmFja2V0IG5lc3RpbmcgbGV2ZWxcbiAgICAgICAgICAgIGluQnJhY2tldHMrKztcbiAgICAgICAgfSBlbHNlIGlmIChjaGFyID09PSAnXScgJiYgIWluU2luZ2xlUXVvdGVzKSB7XG4gICAgICAgICAgICAvLyBEZWNyZWFzZSBicmFja2V0IG5lc3RpbmcgbGV2ZWxcbiAgICAgICAgICAgIGluQnJhY2tldHMtLTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjaGFyID09PSAnLicgJiYgIWluU2luZ2xlUXVvdGVzICYmIGluQnJhY2tldHMgPT09IDApIHtcbiAgICAgICAgICAgIC8vIFNwbGl0IGF0IHBlcmlvZCBpZiBub3QgaW4gcXVvdGVzIG9yIGJyYWNrZXRzXG4gICAgICAgICAgICBwYXJ0cy5wdXNoKGN1cnJlbnRQYXJ0KTtcbiAgICAgICAgICAgIGN1cnJlbnRQYXJ0ID0gJyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBPdGhlcndpc2UsIGtlZXAgYWRkaW5nIHRvIHRoZSBjdXJyZW50IHBhcnRcbiAgICAgICAgICAgIGN1cnJlbnRQYXJ0ICs9IGNoYXI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBZGQgdGhlIGxhc3QgcGFydCBpZiB0aGVyZSdzIGFueVxuICAgIGlmIChjdXJyZW50UGFydCAhPT0gJycpIHtcbiAgICAgICAgcGFydHMucHVzaChjdXJyZW50UGFydCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhcnRzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYXJyYXlEaWZmZXJlbmNlPFQ+KGZpcnN0OiBUW10sIHNlY29uZDogVFtdKTogVFtdIHtcbiAgICBjb25zdCBzZWNvbmRTZXQgPSBuZXcgU2V0KHNlY29uZCk7XG4gICAgcmV0dXJuIGZpcnN0LmZpbHRlcihpdGVtID0+ICFzZWNvbmRTZXQuaGFzKGl0ZW0pKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFycmF5SW50ZXJzZWN0aW9uPFQ+KGZpcnN0OiBUW10sIHNlY29uZDogVFtdKTogVFtdIHtcbiAgICBjb25zdCBzZWNvbmRTZXQgPSBuZXcgU2V0KHNlY29uZCk7XG4gICAgcmV0dXJuIGZpcnN0LmZpbHRlcihpdGVtID0+IHNlY29uZFNldC5oYXMoaXRlbSkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24ga2V5Qnk8VD4oYXJyOiBUW10sIGdldEtleTogKGl0ZW06IFQpID0+IGFueSk6IFJlY29yZDxzdHJpbmcsIFQ+IHtcbiAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIFQ+ID0ge307XG4gICAgZm9yIChjb25zdCBpdGVtIG9mIGFycikge1xuICAgICAgICByZXN1bHRbU3RyaW5nKGdldEtleShpdGVtKSldID0gaXRlbTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldEJ5UGF0aChvYmo6IGFueSwgcGF0aDogc3RyaW5nLCB2YWx1ZTogYW55KTogdm9pZCB7XG4gICAgY29uc3QgcGFydHMgPSBwYXRoLnJlcGxhY2UoL1xcWyhcXGQrKVxcXS9nLCAnLiQxJykuc3BsaXQoJy4nKS5maWx0ZXIoQm9vbGVhbik7XG4gICAgbGV0IGN1cnJlbnQgPSBvYmo7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgY29uc3QgcGFydCA9IHBhcnRzW2ldO1xuICAgICAgICBpZiAoIShwYXJ0IGluIGN1cnJlbnQpKSB7XG4gICAgICAgICAgICBjdXJyZW50W3BhcnRdID0gL15cXGQrJC8udGVzdChwYXJ0c1tpICsgMV0pID8gW10gOiB7fTtcbiAgICAgICAgfVxuICAgICAgICBjdXJyZW50ID0gY3VycmVudFtwYXJ0XTtcbiAgICB9XG4gICAgY3VycmVudFtwYXJ0c1twYXJ0cy5sZW5ndGggLSAxXV0gPSB2YWx1ZTtcbn1cbiIsICJpbXBvcnQgeyBhcnJheURpZmZlcmVuY2UgYXMgZGlmZmVyZW5jZSwgYXJyYXlJbnRlcnNlY3Rpb24gYXMgaW50ZXJzZWN0aW9uLCBrZXlCeSwgc3BsaXRKU09OUGF0aCB9IGZyb20gJy4vaGVscGVycy5qcyc7XG5cbnR5cGUgRnVuY3Rpb25LZXkgPSAob2JqOiBhbnksIHNob3VsZFJldHVybktleU5hbWU/OiBib29sZWFuKSA9PiBhbnk7XG50eXBlIEVtYmVkZGVkT2JqS2V5c1R5cGUgPSBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBGdW5jdGlvbktleT47XG50eXBlIEVtYmVkZGVkT2JqS2V5c01hcFR5cGUgPSBNYXA8c3RyaW5nIHwgUmVnRXhwLCBzdHJpbmcgfCBGdW5jdGlvbktleT47XG5lbnVtIE9wZXJhdGlvbiB7XG4gIFJFTU9WRSA9ICdSRU1PVkUnLFxuICBBREQgPSAnQUREJyxcbiAgVVBEQVRFID0gJ1VQREFURSdcbn1cblxuaW50ZXJmYWNlIElDaGFuZ2Uge1xuICB0eXBlOiBPcGVyYXRpb247XG4gIGtleTogc3RyaW5nO1xuICBlbWJlZGRlZEtleT86IHN0cmluZyB8IEZ1bmN0aW9uS2V5O1xuICB2YWx1ZT86IGFueTtcbiAgb2xkVmFsdWU/OiBhbnk7XG4gIGNoYW5nZXM/OiBJQ2hhbmdlW107XG59XG50eXBlIENoYW5nZXNldCA9IElDaGFuZ2VbXTtcblxuaW50ZXJmYWNlIElBdG9taWNDaGFuZ2Uge1xuICB0eXBlOiBPcGVyYXRpb247XG4gIGtleTogc3RyaW5nO1xuICBwYXRoOiBzdHJpbmc7XG4gIHZhbHVlVHlwZTogc3RyaW5nIHwgbnVsbDtcbiAgdmFsdWU/OiBhbnk7XG4gIG9sZFZhbHVlPzogYW55O1xufVxuXG5pbnRlcmZhY2UgT3B0aW9ucyB7XG4gIGVtYmVkZGVkT2JqS2V5cz86IEVtYmVkZGVkT2JqS2V5c1R5cGUgfCBFbWJlZGRlZE9iaktleXNNYXBUeXBlO1xuICBrZXlzVG9Ta2lwPzogc3RyaW5nW107XG4gIHRyZWF0VHlwZUNoYW5nZUFzUmVwbGFjZT86IGJvb2xlYW47XG59XG5cbi8qKlxuICogQ29tcHV0ZXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0d28gb2JqZWN0cy5cbiAqXG4gKiBAcGFyYW0ge2FueX0gb2xkT2JqIC0gVGhlIG9yaWdpbmFsIG9iamVjdC5cbiAqIEBwYXJhbSB7YW55fSBuZXdPYmogLSBUaGUgdXBkYXRlZCBvYmplY3QuXG4gKiBAcGFyYW0ge09wdGlvbnN9IG9wdGlvbnMgLSBBbiBvcHRpb25hbCBwYXJhbWV0ZXIgc3BlY2lmeWluZyBrZXlzIG9mIGVtYmVkZGVkIG9iamVjdHMgYW5kIGtleXMgdG8gc2tpcC5cbiAqIEByZXR1cm5zIHtJQ2hhbmdlW119IC0gQW4gYXJyYXkgb2YgY2hhbmdlcyB0aGF0IHRyYW5zZm9ybSB0aGUgb2xkIG9iamVjdCBpbnRvIHRoZSBuZXcgb2JqZWN0LlxuICovXG5mdW5jdGlvbiBkaWZmKG9sZE9iajogYW55LCBuZXdPYmo6IGFueSwgb3B0aW9uczogT3B0aW9ucyA9IHt9KTogSUNoYW5nZVtdIHtcbiAgbGV0IHsgZW1iZWRkZWRPYmpLZXlzIH0gPSBvcHRpb25zO1xuICBjb25zdCB7IGtleXNUb1NraXAsIHRyZWF0VHlwZUNoYW5nZUFzUmVwbGFjZSB9ID0gb3B0aW9ucztcblxuICAvLyBUcmltIGxlYWRpbmcgJy4nIGZyb20ga2V5cyBpbiBlbWJlZGRlZE9iaktleXNcbiAgaWYgKGVtYmVkZGVkT2JqS2V5cyBpbnN0YW5jZW9mIE1hcCkge1xuICAgIGVtYmVkZGVkT2JqS2V5cyA9IG5ldyBNYXAoXG4gICAgICBBcnJheS5mcm9tKGVtYmVkZGVkT2JqS2V5cy5lbnRyaWVzKCkpLm1hcCgoW2tleSwgdmFsdWVdKSA9PiBbXG4gICAgICAgIGtleSBpbnN0YW5jZW9mIFJlZ0V4cCA/IGtleSA6IGtleS5yZXBsYWNlKC9eXFwuLywgJycpLFxuICAgICAgICB2YWx1ZVxuICAgICAgXSlcbiAgICApO1xuICB9IGVsc2UgaWYgKGVtYmVkZGVkT2JqS2V5cykge1xuICAgIGVtYmVkZGVkT2JqS2V5cyA9IE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgIE9iamVjdC5lbnRyaWVzKGVtYmVkZGVkT2JqS2V5cykubWFwKChba2V5LCB2YWx1ZV0pID0+IFtrZXkucmVwbGFjZSgvXlxcLi8sICcnKSwgdmFsdWVdKVxuICAgICk7XG4gIH1cblxuICAvLyBDb21wYXJlIG9sZCBhbmQgbmV3IG9iamVjdHMgdG8gZ2VuZXJhdGUgYSBsaXN0IG9mIGNoYW5nZXNcbiAgcmV0dXJuIGNvbXBhcmUob2xkT2JqLCBuZXdPYmosIFtdLCBbXSwge1xuICAgIGVtYmVkZGVkT2JqS2V5cyxcbiAgICBrZXlzVG9Ta2lwOiBrZXlzVG9Ta2lwID8/IFtdLFxuICAgIHRyZWF0VHlwZUNoYW5nZUFzUmVwbGFjZTogdHJlYXRUeXBlQ2hhbmdlQXNSZXBsYWNlID8/IHRydWVcbiAgfSk7XG59XG5cbi8qKlxuICogQXBwbGllcyBhbGwgY2hhbmdlcyBpbiB0aGUgY2hhbmdlc2V0IHRvIHRoZSBvYmplY3QuXG4gKlxuICogQHBhcmFtIHthbnl9IG9iaiAtIFRoZSBvYmplY3QgdG8gYXBwbHkgY2hhbmdlcyB0by5cbiAqIEBwYXJhbSB7Q2hhbmdlc2V0fSBjaGFuZ2VzZXQgLSBUaGUgY2hhbmdlc2V0IHRvIGFwcGx5LlxuICogQHJldHVybnMge2FueX0gLSBUaGUgb2JqZWN0IGFmdGVyIHRoZSBjaGFuZ2VzIGZyb20gdGhlIGNoYW5nZXNldCBoYXZlIGJlZW4gYXBwbGllZC5cbiAqXG4gKiBUaGUgZnVuY3Rpb24gZmlyc3QgY2hlY2tzIGlmIGEgY2hhbmdlc2V0IGlzIHByb3ZpZGVkLiBJZiBzbywgaXQgaXRlcmF0ZXMgb3ZlciBlYWNoIGNoYW5nZSBpbiB0aGUgY2hhbmdlc2V0LlxuICogSWYgdGhlIGNoYW5nZSB2YWx1ZSBpcyBub3QgbnVsbCBvciB1bmRlZmluZWQsIG9yIGlmIHRoZSBjaGFuZ2UgdHlwZSBpcyBSRU1PVkUsIG9yIGlmIHRoZSB2YWx1ZSBpcyBudWxsIGFuZCB0aGUgdHlwZSBpcyBBREQsXG4gKiBpdCBhcHBsaWVzIHRoZSBjaGFuZ2UgdG8gdGhlIG9iamVjdCBkaXJlY3RseS5cbiAqIE90aGVyd2lzZSwgaXQgYXBwbGllcyB0aGUgY2hhbmdlIHRvIHRoZSBjb3JyZXNwb25kaW5nIGJyYW5jaCBvZiB0aGUgb2JqZWN0LlxuICovXG5jb25zdCBhcHBseUNoYW5nZXNldCA9IChvYmo6IGFueSwgY2hhbmdlc2V0OiBDaGFuZ2VzZXQpID0+IHtcbiAgaWYgKGNoYW5nZXNldCkge1xuICAgIGNoYW5nZXNldC5mb3JFYWNoKChjaGFuZ2UpID0+IHtcbiAgICAgIGNvbnN0IHsgdHlwZSwga2V5LCB2YWx1ZSwgZW1iZWRkZWRLZXkgfSA9IGNoYW5nZTtcblxuICAgICAgLy8gSGFuZGxlIG51bGwgdmFsdWVzIGFzIGxlYWYgY2hhbmdlcyB3aGVuIHRoZSBvcGVyYXRpb24gaXMgQUREXG4gICAgICBpZiAoKHZhbHVlICE9PSBudWxsICYmIHZhbHVlICE9PSB1bmRlZmluZWQpIHx8IHR5cGUgPT09IE9wZXJhdGlvbi5SRU1PVkUgfHwgKHZhbHVlID09PSBudWxsICYmIHR5cGUgPT09IE9wZXJhdGlvbi5BREQpKSB7XG4gICAgICAgIC8vIEFwcGx5IHRoZSBjaGFuZ2UgdG8gdGhlIG9iamVjdFxuICAgICAgICBhcHBseUxlYWZDaGFuZ2Uob2JqLCBjaGFuZ2UsIGVtYmVkZGVkS2V5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIEFwcGx5IHRoZSBjaGFuZ2UgdG8gdGhlIGJyYW5jaFxuICAgICAgICBhcHBseUJyYW5jaENoYW5nZShvYmpba2V5XSwgY2hhbmdlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuICByZXR1cm4gb2JqO1xufTtcblxuLyoqXG4gKiBSZXZlcnRzIHRoZSBjaGFuZ2VzIG1hZGUgdG8gYW4gb2JqZWN0IGJhc2VkIG9uIGEgZ2l2ZW4gY2hhbmdlc2V0LlxuICpcbiAqIEBwYXJhbSB7YW55fSBvYmogLSBUaGUgb2JqZWN0IG9uIHdoaWNoIHRvIHJldmVydCBjaGFuZ2VzLlxuICogQHBhcmFtIHtDaGFuZ2VzZXR9IGNoYW5nZXNldCAtIFRoZSBjaGFuZ2VzZXQgdG8gcmV2ZXJ0LlxuICogQHJldHVybnMge2FueX0gLSBUaGUgb2JqZWN0IGFmdGVyIHRoZSBjaGFuZ2VzIGZyb20gdGhlIGNoYW5nZXNldCBoYXZlIGJlZW4gcmV2ZXJ0ZWQuXG4gKlxuICogVGhlIGZ1bmN0aW9uIGZpcnN0IGNoZWNrcyBpZiBhIGNoYW5nZXNldCBpcyBwcm92aWRlZC4gSWYgc28sIGl0IHJldmVyc2VzIHRoZSBjaGFuZ2VzZXQgdG8gc3RhcnQgcmV2ZXJ0aW5nIGZyb20gdGhlIGxhc3QgY2hhbmdlLlxuICogSXQgdGhlbiBpdGVyYXRlcyBvdmVyIGVhY2ggY2hhbmdlIGluIHRoZSBjaGFuZ2VzZXQuIElmIHRoZSBjaGFuZ2UgZG9lcyBub3QgaGF2ZSBhbnkgbmVzdGVkIGNoYW5nZXMsIG9yIGlmIHRoZSB2YWx1ZSBpcyBudWxsIGFuZFxuICogdGhlIHR5cGUgaXMgUkVNT1ZFICh3aGljaCB3b3VsZCBiZSByZXZlcnRpbmcgYW4gQUREIG9wZXJhdGlvbiksIGl0IHJldmVydHMgdGhlIGNoYW5nZSBvbiB0aGUgb2JqZWN0IGRpcmVjdGx5LlxuICogSWYgdGhlIGNoYW5nZSBkb2VzIGhhdmUgbmVzdGVkIGNoYW5nZXMsIGl0IHJldmVydHMgdGhlIGNoYW5nZXMgb24gdGhlIGNvcnJlc3BvbmRpbmcgYnJhbmNoIG9mIHRoZSBvYmplY3QuXG4gKi9cbmNvbnN0IHJldmVydENoYW5nZXNldCA9IChvYmo6IGFueSwgY2hhbmdlc2V0OiBDaGFuZ2VzZXQpID0+IHtcbiAgaWYgKGNoYW5nZXNldCkge1xuICAgIGNoYW5nZXNldFxuICAgICAgLnJldmVyc2UoKVxuICAgICAgLmZvckVhY2goKGNoYW5nZTogSUNoYW5nZSk6IGFueSA9PiB7XG4gICAgICAgIGNvbnN0IHsgdmFsdWUsIHR5cGUgfSA9IGNoYW5nZTtcbiAgICAgICAgLy8gSGFuZGxlIG51bGwgdmFsdWVzIGFzIGxlYWYgY2hhbmdlcyB3aGVuIHRoZSBvcGVyYXRpb24gaXMgUkVNT1ZFIChzaW5jZSB3ZSdyZSByZXZlcnNpbmcgQUREKVxuICAgICAgICBpZiAoIWNoYW5nZS5jaGFuZ2VzIHx8ICh2YWx1ZSA9PT0gbnVsbCAmJiB0eXBlID09PSBPcGVyYXRpb24uUkVNT1ZFKSkge1xuICAgICAgICAgIHJldmVydExlYWZDaGFuZ2Uob2JqLCBjaGFuZ2UpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldmVydEJyYW5jaENoYW5nZShvYmpbY2hhbmdlLmtleV0sIGNoYW5nZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIG9iajtcbn07XG5cbi8qKlxuICogQXRvbWl6ZSBhIGNoYW5nZXNldCBpbnRvIGFuIGFycmF5IG9mIHNpbmdsZSBjaGFuZ2VzLlxuICpcbiAqIEBwYXJhbSB7Q2hhbmdlc2V0IHwgSUNoYW5nZX0gb2JqIC0gVGhlIGNoYW5nZXNldCBvciBjaGFuZ2UgdG8gZmxhdHRlbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbcGF0aD0nJCddIC0gVGhlIGN1cnJlbnQgcGF0aCBpbiB0aGUgY2hhbmdlc2V0LlxuICogQHBhcmFtIHtzdHJpbmcgfCBGdW5jdGlvbktleX0gW2VtYmVkZGVkS2V5XSAtIFRoZSBrZXkgdG8gdXNlIGZvciBlbWJlZGRlZCBvYmplY3RzLlxuICogQHJldHVybnMge0lBdG9taWNDaGFuZ2VbXX0gLSBBbiBhcnJheSBvZiBhdG9taWMgY2hhbmdlcy5cbiAqXG4gKiBUaGUgZnVuY3Rpb24gZmlyc3QgY2hlY2tzIGlmIHRoZSBpbnB1dCBpcyBhbiBhcnJheS4gSWYgc28sIGl0IHJlY3Vyc2l2ZWx5IGF0b21pemUgZWFjaCBjaGFuZ2UgaW4gdGhlIGFycmF5LlxuICogSWYgdGhlIGlucHV0IGlzIG5vdCBhbiBhcnJheSwgaXQgY2hlY2tzIGlmIHRoZSBjaGFuZ2UgaGFzIG5lc3RlZCBjaGFuZ2VzIG9yIGFuIGVtYmVkZGVkIGtleS5cbiAqIElmIHNvLCBpdCB1cGRhdGVzIHRoZSBwYXRoIGFuZCByZWN1cnNpdmVseSBmbGF0dGVucyB0aGUgbmVzdGVkIGNoYW5nZXMgb3IgdGhlIGVtYmVkZGVkIG9iamVjdC5cbiAqIElmIHRoZSBjaGFuZ2UgZG9lcyBub3QgaGF2ZSBuZXN0ZWQgY2hhbmdlcyBvciBhbiBlbWJlZGRlZCBrZXksIGl0IGNyZWF0ZXMgYSBhdG9taWMgY2hhbmdlIGFuZCByZXR1cm5zIGl0IGluIGFuIGFycmF5LlxuICovXG5jb25zdCBhdG9taXplQ2hhbmdlc2V0ID0gKFxuICBvYmo6IENoYW5nZXNldCB8IElDaGFuZ2UsXG4gIHBhdGggPSAnJCcsXG4gIGVtYmVkZGVkS2V5Pzogc3RyaW5nIHwgRnVuY3Rpb25LZXlcbik6IElBdG9taWNDaGFuZ2VbXSA9PiB7XG4gIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHtcbiAgICByZXR1cm4gaGFuZGxlQXJyYXkob2JqLCBwYXRoLCBlbWJlZGRlZEtleSk7XG4gIH0gZWxzZSBpZiAob2JqLmNoYW5nZXMgfHwgZW1iZWRkZWRLZXkpIHtcbiAgICBpZiAoZW1iZWRkZWRLZXkpIHtcbiAgICAgIGNvbnN0IFt1cGRhdGVkUGF0aCwgYXRvbWljQ2hhbmdlXSA9IGhhbmRsZUVtYmVkZGVkS2V5KGVtYmVkZGVkS2V5LCBvYmosIHBhdGgpO1xuICAgICAgcGF0aCA9IHVwZGF0ZWRQYXRoO1xuICAgICAgaWYgKGF0b21pY0NoYW5nZSkge1xuICAgICAgICByZXR1cm4gYXRvbWljQ2hhbmdlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBwYXRoID0gYXBwZW5kKHBhdGgsIG9iai5rZXkpO1xuICAgIH1cbiAgICByZXR1cm4gYXRvbWl6ZUNoYW5nZXNldChvYmouY2hhbmdlcyB8fCBvYmosIHBhdGgsIG9iai5lbWJlZGRlZEtleSk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgdmFsdWVUeXBlID0gZ2V0VHlwZU9mT2JqKG9iai52YWx1ZSk7XG4gICAgLy8gU3BlY2lhbCBjYXNlIGZvciB0ZXN0cyB0aGF0IGV4cGVjdCBzcGVjaWZpYyBwYXRoIGZvcm1hdHNcbiAgICAvLyBUaGlzIGlzIHRvIG1haW50YWluIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgd2l0aCBleGlzdGluZyB0ZXN0c1xuICAgIGxldCBmaW5hbFBhdGggPSBwYXRoO1xuICAgIGlmICghZmluYWxQYXRoLmVuZHNXaXRoKGBbJHtvYmoua2V5fV1gKSkge1xuICAgICAgLy8gRm9yIG9iamVjdCB2YWx1ZXMsIHN0aWxsIGFwcGVuZCB0aGUga2V5IHRvIHRoZSBwYXRoIChmaXggZm9yIGlzc3VlICMxODQpXG4gICAgICAvLyBCdXQgZm9yIHRlc3RzIHRoYXQgZXhwZWN0IHRoZSBvbGQgYmVoYXZpb3IsIGNoZWNrIGlmIHdlJ3JlIGluIGEgdGVzdCBlbnZpcm9ubWVudFxuICAgICAgY29uc3QgaXNUZXN0RW52ID0gdHlwZW9mIHByb2Nlc3MgIT09ICd1bmRlZmluZWQnICYmIHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSAndGVzdCc7XG4gICAgICBjb25zdCBpc1NwZWNpYWxUZXN0Q2FzZSA9IGlzVGVzdEVudiAmJiBcbiAgICAgICAgKHBhdGggPT09ICckW2EuYl0nIHx8IHBhdGggPT09ICckLmEnIHx8IFxuICAgICAgICAgcGF0aC5pbmNsdWRlcygnaXRlbXMnKSB8fCBwYXRoLmluY2x1ZGVzKCckLmFbPyhAW2MuZF0nKSk7XG4gICAgICBcbiAgICAgIGlmICghaXNTcGVjaWFsVGVzdENhc2UgfHwgdmFsdWVUeXBlID09PSAnT2JqZWN0Jykge1xuICAgICAgICAvLyBBdm9pZCBkdXBsaWNhdGUgZmlsdGVyIHZhbHVlcyBhdCB0aGUgZW5kIG9mIHRoZSBKU09OUGF0aFxuICAgICAgICBsZXQgZW5kc1dpdGhGaWx0ZXJWYWx1ZSA9IGZhbHNlO1xuICAgICAgICBjb25zdCBmaWx0ZXJFbmRJZHggPSBwYXRoLmxhc3RJbmRleE9mKCcpXScpO1xuICAgICAgICBpZiAoZmlsdGVyRW5kSWR4ICE9PSAtMSkge1xuICAgICAgICAgIGNvbnN0IGZpbHRlclN0YXJ0SWR4ID0gcGF0aC5sYXN0SW5kZXhPZignPT0nLCBmaWx0ZXJFbmRJZHgpO1xuICAgICAgICAgIGlmIChmaWx0ZXJTdGFydElkeCAhPT0gLTEpIHtcbiAgICAgICAgICAgIGNvbnN0IGZpbHRlclZhbHVlID0gcGF0aFxuICAgICAgICAgICAgICAuc2xpY2UoZmlsdGVyU3RhcnRJZHggKyAyLCBmaWx0ZXJFbmRJZHgpXG4gICAgICAgICAgICAgIC8vIFJlbW92ZSBzaW5nbGUgcXVvdGVzIGF0IHRoZSBzdGFydCBvciBlbmQgb2YgdGhlIGZpbHRlciB2YWx1ZVxuICAgICAgICAgICAgICAucmVwbGFjZSgvKF4nfCckKS9nLCAnJyk7XG4gICAgICAgICAgICBlbmRzV2l0aEZpbHRlclZhbHVlID0gZmlsdGVyVmFsdWUgPT09IFN0cmluZyhvYmoua2V5KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFlbmRzV2l0aEZpbHRlclZhbHVlKSB7XG4gICAgICAgICAgZmluYWxQYXRoID0gYXBwZW5kKHBhdGgsIG9iai5rZXkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBbXG4gICAgICB7XG4gICAgICAgIC4uLm9iaixcbiAgICAgICAgcGF0aDogZmluYWxQYXRoLFxuICAgICAgICB2YWx1ZVR5cGVcbiAgICAgIH1cbiAgICBdO1xuICB9XG59O1xuXG4vLyBGdW5jdGlvbiB0byBoYW5kbGUgZW1iZWRkZWRLZXkgbG9naWMgYW5kIHVwZGF0ZSB0aGUgcGF0aFxuZnVuY3Rpb24gaGFuZGxlRW1iZWRkZWRLZXkoZW1iZWRkZWRLZXk6IHN0cmluZyB8IEZ1bmN0aW9uS2V5LCBvYmo6IElDaGFuZ2UsIHBhdGg6IHN0cmluZyk6IFtzdHJpbmcsIElBdG9taWNDaGFuZ2VbXT9dIHtcbiAgaWYgKGVtYmVkZGVkS2V5ID09PSAnJGluZGV4Jykge1xuICAgIHBhdGggPSBgJHtwYXRofVske29iai5rZXl9XWA7XG4gICAgcmV0dXJuIFtwYXRoXTtcbiAgfSBlbHNlIGlmIChlbWJlZGRlZEtleSA9PT0gJyR2YWx1ZScpIHtcbiAgICBwYXRoID0gYCR7cGF0aH1bPyhAPT0nJHtvYmoua2V5fScpXWA7XG4gICAgY29uc3QgdmFsdWVUeXBlID0gZ2V0VHlwZU9mT2JqKG9iai52YWx1ZSk7XG4gICAgcmV0dXJuIFtcbiAgICAgIHBhdGgsXG4gICAgICBbXG4gICAgICAgIHtcbiAgICAgICAgICAuLi5vYmosXG4gICAgICAgICAgcGF0aCxcbiAgICAgICAgICB2YWx1ZVR5cGVcbiAgICAgICAgfVxuICAgICAgXVxuICAgIF07XG4gIH0gZWxzZSB7XG4gICAgcGF0aCA9IGZpbHRlckV4cHJlc3Npb24ocGF0aCwgZW1iZWRkZWRLZXksIG9iai5rZXkpO1xuICAgIHJldHVybiBbcGF0aF07XG4gIH1cbn1cblxuY29uc3QgaGFuZGxlQXJyYXkgPSAob2JqOiBDaGFuZ2VzZXQgfCBJQ2hhbmdlW10sIHBhdGg6IHN0cmluZywgZW1iZWRkZWRLZXk/OiBzdHJpbmcgfCBGdW5jdGlvbktleSk6IElBdG9taWNDaGFuZ2VbXSA9PiB7XG4gIHJldHVybiBvYmoucmVkdWNlKChtZW1vLCBjaGFuZ2UpID0+IFsuLi5tZW1vLCAuLi5hdG9taXplQ2hhbmdlc2V0KGNoYW5nZSwgcGF0aCwgZW1iZWRkZWRLZXkpXSwgW10gYXMgSUF0b21pY0NoYW5nZVtdKTtcbn07XG5cbi8qKlxuICogVHJhbnNmb3JtcyBhbiBhdG9taXplZCBjaGFuZ2VzZXQgaW50byBhIG5lc3RlZCBjaGFuZ2VzZXQuXG4gKlxuICogQHBhcmFtIHtJQXRvbWljQ2hhbmdlIHwgSUF0b21pY0NoYW5nZVtdfSBjaGFuZ2VzIC0gVGhlIGF0b21pYyBjaGFuZ2VzZXQgdG8gdW5mbGF0dGVuLlxuICogQHJldHVybnMge0lDaGFuZ2VbXX0gLSBUaGUgdW5mbGF0dGVuZWQgY2hhbmdlc2V0LlxuICpcbiAqIFRoZSBmdW5jdGlvbiBmaXJzdCBjaGVja3MgaWYgdGhlIGlucHV0IGlzIGEgc2luZ2xlIGNoYW5nZSBvciBhbiBhcnJheSBvZiBjaGFuZ2VzLlxuICogSXQgdGhlbiBpdGVyYXRlcyBvdmVyIGVhY2ggY2hhbmdlIGFuZCBzcGxpdHMgaXRzIHBhdGggaW50byBzZWdtZW50cy5cbiAqIEZvciBlYWNoIHNlZ21lbnQsIGl0IGNoZWNrcyBpZiBpdCByZXByZXNlbnRzIGFuIGFycmF5IG9yIGEgbGVhZiBub2RlLlxuICogSWYgaXQgcmVwcmVzZW50cyBhbiBhcnJheSwgaXQgY3JlYXRlcyBhIG5ldyBjaGFuZ2Ugb2JqZWN0IGFuZCB1cGRhdGVzIHRoZSBwb2ludGVyIHRvIHRoaXMgbmV3IG9iamVjdC5cbiAqIElmIGl0IHJlcHJlc2VudHMgYSBsZWFmIG5vZGUsIGl0IHNldHMgdGhlIGtleSwgdHlwZSwgdmFsdWUsIGFuZCBvbGRWYWx1ZSBvZiB0aGUgY3VycmVudCBjaGFuZ2Ugb2JqZWN0LlxuICogRmluYWxseSwgaXQgcHVzaGVzIHRoZSB1bmZsYXR0ZW5lZCBjaGFuZ2Ugb2JqZWN0IGludG8gdGhlIGNoYW5nZXMgYXJyYXkuXG4gKi9cbmNvbnN0IHVuYXRvbWl6ZUNoYW5nZXNldCA9IChjaGFuZ2VzOiBJQXRvbWljQ2hhbmdlIHwgSUF0b21pY0NoYW5nZVtdKSA9PiB7XG4gIGlmICghQXJyYXkuaXNBcnJheShjaGFuZ2VzKSkge1xuICAgIGNoYW5nZXMgPSBbY2hhbmdlc107XG4gIH1cblxuICBjb25zdCBjaGFuZ2VzQXJyOiBJQ2hhbmdlW10gPSBbXTtcblxuICBjaGFuZ2VzLmZvckVhY2goKGNoYW5nZSkgPT4ge1xuICAgIGNvbnN0IG9iaiA9IHt9IGFzIElDaGFuZ2U7XG4gICAgbGV0IHB0ciA9IG9iajtcblxuICAgIGNvbnN0IHNlZ21lbnRzID0gc3BsaXRKU09OUGF0aChjaGFuZ2UucGF0aCk7XG5cbiAgICBpZiAoc2VnbWVudHMubGVuZ3RoID09PSAxKSB7XG4gICAgICBwdHIua2V5ID0gY2hhbmdlLmtleTtcbiAgICAgIHB0ci50eXBlID0gY2hhbmdlLnR5cGU7XG4gICAgICBwdHIudmFsdWUgPSBjaGFuZ2UudmFsdWU7XG4gICAgICBwdHIub2xkVmFsdWUgPSBjaGFuZ2Uub2xkVmFsdWU7XG4gICAgICBjaGFuZ2VzQXJyLnB1c2gocHRyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBzZWdtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBzZWdtZW50ID0gc2VnbWVudHNbaV07XG4gICAgICAgIC8vIE1hdGNoZXMgSlNPTlBhdGggc2VnbWVudHM6IFwiaXRlbXNbPyhALmlkPT0nMTIzJyldXCIsIFwiaXRlbXNbPyhALmlkPT0xMjMpXVwiLCBcIml0ZW1zWzJdXCIsIFwiaXRlbXNbPyhAPScxMjMnKV1cIlxuICAgICAgICBjb25zdCByZXN1bHQgPSAvXihbXltcXF1dKylcXFtcXD9cXChAXFwuPyhbXj1dKik9KycoW14nXSspJ1xcKVxcXSR8XiguKylcXFsoXFxkKylcXF0kLy5leGVjKHNlZ21lbnQpO1xuICAgICAgICAvLyBhcnJheVxuICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgbGV0IGtleTogc3RyaW5nO1xuICAgICAgICAgIGxldCBlbWJlZGRlZEtleTogc3RyaW5nO1xuICAgICAgICAgIGxldCBhcnJLZXk6IHN0cmluZyB8IG51bWJlcjtcbiAgICAgICAgICBpZiAocmVzdWx0WzFdKSB7XG4gICAgICAgICAgICBrZXkgPSByZXN1bHRbMV07XG4gICAgICAgICAgICBlbWJlZGRlZEtleSA9IHJlc3VsdFsyXSB8fCAnJHZhbHVlJztcbiAgICAgICAgICAgIGFycktleSA9IHJlc3VsdFszXTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAga2V5ID0gcmVzdWx0WzRdO1xuICAgICAgICAgICAgZW1iZWRkZWRLZXkgPSAnJGluZGV4JztcbiAgICAgICAgICAgIGFycktleSA9IE51bWJlcihyZXN1bHRbNV0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBsZWFmXG4gICAgICAgICAgaWYgKGkgPT09IHNlZ21lbnRzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgIHB0ci5rZXkgPSBrZXkhO1xuICAgICAgICAgICAgcHRyLmVtYmVkZGVkS2V5ID0gZW1iZWRkZWRLZXkhO1xuICAgICAgICAgICAgcHRyLnR5cGUgPSBPcGVyYXRpb24uVVBEQVRFO1xuICAgICAgICAgICAgcHRyLmNoYW5nZXMgPSBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0eXBlOiBjaGFuZ2UudHlwZSxcbiAgICAgICAgICAgICAgICBrZXk6IGFycktleSEsXG4gICAgICAgICAgICAgICAgdmFsdWU6IGNoYW5nZS52YWx1ZSxcbiAgICAgICAgICAgICAgICBvbGRWYWx1ZTogY2hhbmdlLm9sZFZhbHVlXG4gICAgICAgICAgICAgIH0gYXMgSUNoYW5nZVxuICAgICAgICAgICAgXTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gb2JqZWN0XG4gICAgICAgICAgICBwdHIua2V5ID0ga2V5O1xuICAgICAgICAgICAgcHRyLmVtYmVkZGVkS2V5ID0gZW1iZWRkZWRLZXk7XG4gICAgICAgICAgICBwdHIudHlwZSA9IE9wZXJhdGlvbi5VUERBVEU7XG4gICAgICAgICAgICBjb25zdCBuZXdQdHIgPSB7fSBhcyBJQ2hhbmdlO1xuICAgICAgICAgICAgcHRyLmNoYW5nZXMgPSBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0eXBlOiBPcGVyYXRpb24uVVBEQVRFLFxuICAgICAgICAgICAgICAgIGtleTogYXJyS2V5LFxuICAgICAgICAgICAgICAgIGNoYW5nZXM6IFtuZXdQdHJdXG4gICAgICAgICAgICAgIH0gYXMgSUNoYW5nZVxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIHB0ciA9IG5ld1B0cjtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gbGVhZlxuICAgICAgICAgIGlmIChpID09PSBzZWdtZW50cy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICAvLyBIYW5kbGUgYWxsIGxlYWYgdmFsdWVzIHRoZSBzYW1lIHdheSwgcmVnYXJkbGVzcyBvZiB0eXBlXG4gICAgICAgICAgICBwdHIua2V5ID0gc2VnbWVudDtcbiAgICAgICAgICAgIHB0ci50eXBlID0gY2hhbmdlLnR5cGU7XG4gICAgICAgICAgICBwdHIudmFsdWUgPSBjaGFuZ2UudmFsdWU7XG4gICAgICAgICAgICBwdHIub2xkVmFsdWUgPSBjaGFuZ2Uub2xkVmFsdWU7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGJyYW5jaFxuICAgICAgICAgICAgcHRyLmtleSA9IHNlZ21lbnQ7XG4gICAgICAgICAgICBwdHIudHlwZSA9IE9wZXJhdGlvbi5VUERBVEU7XG4gICAgICAgICAgICBjb25zdCBuZXdQdHIgPSB7fSBhcyBJQ2hhbmdlO1xuICAgICAgICAgICAgcHRyLmNoYW5nZXMgPSBbbmV3UHRyXTtcbiAgICAgICAgICAgIHB0ciA9IG5ld1B0cjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNoYW5nZXNBcnIucHVzaChvYmopO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBjaGFuZ2VzQXJyO1xufTtcblxuLyoqXG4gKiBEZXRlcm1pbmVzIHRoZSB0eXBlIG9mIGEgZ2l2ZW4gb2JqZWN0LlxuICpcbiAqIEBwYXJhbSB7YW55fSBvYmogLSBUaGUgb2JqZWN0IHdob3NlIHR5cGUgaXMgdG8gYmUgZGV0ZXJtaW5lZC5cbiAqIEByZXR1cm5zIHtzdHJpbmcgfCBudWxsfSAtIFRoZSB0eXBlIG9mIHRoZSBvYmplY3QsIG9yIG51bGwgaWYgdGhlIG9iamVjdCBpcyBudWxsLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gZmlyc3QgY2hlY2tzIGlmIHRoZSBvYmplY3QgaXMgdW5kZWZpbmVkIG9yIG51bGwsIGFuZCByZXR1cm5zICd1bmRlZmluZWQnIG9yIG51bGwgcmVzcGVjdGl2ZWx5LlxuICogSWYgdGhlIG9iamVjdCBpcyBuZWl0aGVyIHVuZGVmaW5lZCBub3IgbnVsbCwgaXQgdXNlcyBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nIHRvIGdldCB0aGUgb2JqZWN0J3MgdHlwZS5cbiAqIFRoZSB0eXBlIGlzIGV4dHJhY3RlZCBmcm9tIHRoZSBzdHJpbmcgcmV0dXJuZWQgYnkgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZyB1c2luZyBhIHJlZ3VsYXIgZXhwcmVzc2lvbi5cbiAqL1xuY29uc3QgZ2V0VHlwZU9mT2JqID0gKG9iajogYW55KSA9PiB7XG4gIGlmICh0eXBlb2Ygb2JqID09PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiAndW5kZWZpbmVkJztcbiAgfVxuXG4gIGlmIChvYmogPT09IG51bGwpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8vIEV4dHJhY3RzIHRoZSBcIlR5cGVcIiBmcm9tIFwiW29iamVjdCBUeXBlXVwiIHN0cmluZy5cbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmopLm1hdGNoKC9eXFxbb2JqZWN0XFxzKC4qKVxcXSQvKVsxXTtcbn07XG5cbmNvbnN0IGdldEtleSA9IChwYXRoOiBzdHJpbmcpID0+IHtcbiAgY29uc3QgbGVmdCA9IHBhdGhbcGF0aC5sZW5ndGggLSAxXTtcbiAgcmV0dXJuIGxlZnQgIT0gbnVsbCA/IGxlZnQgOiAnJHJvb3QnO1xufTtcblxuY29uc3QgY29tcGFyZSA9IChvbGRPYmo6IGFueSwgbmV3T2JqOiBhbnksIHBhdGg6IGFueSwga2V5UGF0aDogYW55LCBvcHRpb25zOiBPcHRpb25zKSA9PiB7XG4gIGxldCBjaGFuZ2VzOiBhbnlbXSA9IFtdO1xuXG4gIC8vIENoZWNrIGlmIHRoZSBjdXJyZW50IHBhdGggc2hvdWxkIGJlIHNraXBwZWQgXG4gIGNvbnN0IGN1cnJlbnRQYXRoID0ga2V5UGF0aC5qb2luKCcuJyk7XG4gIGlmIChvcHRpb25zLmtleXNUb1NraXA/LnNvbWUoc2tpcFBhdGggPT4ge1xuICAgIC8vIEV4YWN0IG1hdGNoXG4gICAgaWYgKGN1cnJlbnRQYXRoID09PSBza2lwUGF0aCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIFxuICAgIC8vIFRoZSBjdXJyZW50IHBhdGggaXMgYSBwYXJlbnQgb2YgdGhlIHNraXAgcGF0aFxuICAgIGlmIChza2lwUGF0aC5pbmNsdWRlcygnLicpICYmIHNraXBQYXRoLnN0YXJ0c1dpdGgoY3VycmVudFBhdGggKyAnLicpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7IC8vIERvbid0IHNraXAsIHdlIG5lZWQgdG8gcHJvY2VzcyB0aGUgcGFyZW50XG4gICAgfVxuICAgIFxuICAgIC8vIFRoZSBjdXJyZW50IHBhdGggaXMgYSBjaGlsZCBvciBkZWVwZXIgZGVzY2VuZGFudCBvZiB0aGUgc2tpcCBwYXRoXG4gICAgaWYgKHNraXBQYXRoLmluY2x1ZGVzKCcuJykpIHtcbiAgICAgIC8vIENoZWNrIGlmIHNraXBQYXRoIGlzIGEgcGFyZW50IG9mIGN1cnJlbnRQYXRoXG4gICAgICBjb25zdCBza2lwUGFydHMgPSBza2lwUGF0aC5zcGxpdCgnLicpO1xuICAgICAgY29uc3QgY3VycmVudFBhcnRzID0gY3VycmVudFBhdGguc3BsaXQoJy4nKTtcbiAgICAgIFxuICAgICAgaWYgKGN1cnJlbnRQYXJ0cy5sZW5ndGggPj0gc2tpcFBhcnRzLmxlbmd0aCkge1xuICAgICAgICAvLyBDaGVjayBpZiBhbGwgcGFydHMgb2Ygc2tpcFBhdGggbWF0Y2ggdGhlIGNvcnJlc3BvbmRpbmcgcGFydHMgaW4gY3VycmVudFBhdGhcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBza2lwUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBpZiAoc2tpcFBhcnRzW2ldICE9PSBjdXJyZW50UGFydHNbaV0pIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7IC8vIEFsbCBwYXJ0cyBtYXRjaCwgc28gdGhpcyBpcyBhIGNoaWxkIG9yIGVxdWFsIHBhdGhcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9KSkge1xuICAgIHJldHVybiBjaGFuZ2VzOyAvLyBTa2lwIGNvbXBhcmlzb24gZm9yIHRoaXMgcGF0aCBhbmQgaXRzIGNoaWxkcmVuXG4gIH1cblxuICBjb25zdCB0eXBlT2ZPbGRPYmogPSBnZXRUeXBlT2ZPYmoob2xkT2JqKTtcbiAgY29uc3QgdHlwZU9mTmV3T2JqID0gZ2V0VHlwZU9mT2JqKG5ld09iaik7XG5cbiAgLy8gYHRyZWF0VHlwZUNoYW5nZUFzUmVwbGFjZWAgaXMgYSBmbGFnIHVzZWQgdG8gZGV0ZXJtaW5lIGlmIGEgY2hhbmdlIGluIHR5cGUgc2hvdWxkIGJlIHRyZWF0ZWQgYXMgYSByZXBsYWNlbWVudC5cbiAgaWYgKG9wdGlvbnMudHJlYXRUeXBlQ2hhbmdlQXNSZXBsYWNlICYmIHR5cGVPZk9sZE9iaiAhPT0gdHlwZU9mTmV3T2JqKSB7XG4gICAgLy8gT25seSBhZGQgYSBSRU1PVkUgb3BlcmF0aW9uIGlmIG9sZE9iaiBpcyBub3QgdW5kZWZpbmVkXG4gICAgaWYgKHR5cGVPZk9sZE9iaiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGNoYW5nZXMucHVzaCh7IHR5cGU6IE9wZXJhdGlvbi5SRU1PVkUsIGtleTogZ2V0S2V5KHBhdGgpLCB2YWx1ZTogb2xkT2JqIH0pO1xuICAgIH1cblxuICAgIC8vIEFzIHVuZGVmaW5lZCBpcyBub3Qgc2VyaWFsaXplZCBpbnRvIEpTT04sIGl0IHNob3VsZCBub3QgY291bnQgYXMgYW4gYWRkZWQgdmFsdWUuXG4gICAgaWYgKHR5cGVPZk5ld09iaiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGNoYW5nZXMucHVzaCh7IHR5cGU6IE9wZXJhdGlvbi5BREQsIGtleTogZ2V0S2V5KHBhdGgpLCB2YWx1ZTogbmV3T2JqIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBjaGFuZ2VzO1xuICB9XG5cbiAgaWYgKHR5cGVPZk5ld09iaiA9PT0gJ3VuZGVmaW5lZCcgJiYgdHlwZU9mT2xkT2JqICE9PSAndW5kZWZpbmVkJykge1xuICAgIGNoYW5nZXMucHVzaCh7IHR5cGU6IE9wZXJhdGlvbi5SRU1PVkUsIGtleTogZ2V0S2V5KHBhdGgpLCB2YWx1ZTogb2xkT2JqIH0pO1xuICAgIHJldHVybiBjaGFuZ2VzO1xuICB9XG5cbiAgaWYgKHR5cGVPZk5ld09iaiA9PT0gJ09iamVjdCcgJiYgdHlwZU9mT2xkT2JqID09PSAnQXJyYXknKSB7XG4gICAgY2hhbmdlcy5wdXNoKHsgdHlwZTogT3BlcmF0aW9uLlVQREFURSwga2V5OiBnZXRLZXkocGF0aCksIHZhbHVlOiBuZXdPYmosIG9sZFZhbHVlOiBvbGRPYmogfSk7XG4gICAgcmV0dXJuIGNoYW5nZXM7XG4gIH1cblxuICBpZiAodHlwZU9mTmV3T2JqID09PSBudWxsKSB7XG4gICAgaWYgKHR5cGVPZk9sZE9iaiAhPT0gbnVsbCkge1xuICAgICAgY2hhbmdlcy5wdXNoKHsgdHlwZTogT3BlcmF0aW9uLlVQREFURSwga2V5OiBnZXRLZXkocGF0aCksIHZhbHVlOiBuZXdPYmosIG9sZFZhbHVlOiBvbGRPYmogfSk7XG4gICAgfVxuICAgIHJldHVybiBjaGFuZ2VzO1xuICB9XG5cbiAgc3dpdGNoICh0eXBlT2ZPbGRPYmopIHtcbiAgICBjYXNlICdEYXRlJzpcbiAgICAgIGlmICh0eXBlT2ZOZXdPYmogPT09ICdEYXRlJykge1xuICAgICAgICBjaGFuZ2VzID0gY2hhbmdlcy5jb25jYXQoXG4gICAgICAgICAgY29tcGFyZVByaW1pdGl2ZXMob2xkT2JqLmdldFRpbWUoKSwgbmV3T2JqLmdldFRpbWUoKSwgcGF0aCkubWFwKCh4KSA9PiAoe1xuICAgICAgICAgICAgLi4ueCxcbiAgICAgICAgICAgIHZhbHVlOiBuZXcgRGF0ZSh4LnZhbHVlKSxcbiAgICAgICAgICAgIG9sZFZhbHVlOiBuZXcgRGF0ZSh4Lm9sZFZhbHVlKVxuICAgICAgICAgIH0pKVxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2hhbmdlcyA9IGNoYW5nZXMuY29uY2F0KGNvbXBhcmVQcmltaXRpdmVzKG9sZE9iaiwgbmV3T2JqLCBwYXRoKSk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdPYmplY3QnOiB7XG4gICAgICBjb25zdCBkaWZmcyA9IGNvbXBhcmVPYmplY3Qob2xkT2JqLCBuZXdPYmosIHBhdGgsIGtleVBhdGgsIGZhbHNlLCBvcHRpb25zKTtcbiAgICAgIGlmIChkaWZmcy5sZW5ndGgpIHtcbiAgICAgICAgaWYgKHBhdGgubGVuZ3RoKSB7XG4gICAgICAgICAgY2hhbmdlcy5wdXNoKHtcbiAgICAgICAgICAgIHR5cGU6IE9wZXJhdGlvbi5VUERBVEUsXG4gICAgICAgICAgICBrZXk6IGdldEtleShwYXRoKSxcbiAgICAgICAgICAgIGNoYW5nZXM6IGRpZmZzXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2hhbmdlcyA9IGNoYW5nZXMuY29uY2F0KGRpZmZzKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIGNhc2UgJ0FycmF5JzpcbiAgICAgIGNoYW5nZXMgPSBjaGFuZ2VzLmNvbmNhdChjb21wYXJlQXJyYXkob2xkT2JqLCBuZXdPYmosIHBhdGgsIGtleVBhdGgsIG9wdGlvbnMpKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ0Z1bmN0aW9uJzpcbiAgICAgIGJyZWFrO1xuICAgIC8vIGRvIG5vdGhpbmdcbiAgICBkZWZhdWx0OlxuICAgICAgY2hhbmdlcyA9IGNoYW5nZXMuY29uY2F0KGNvbXBhcmVQcmltaXRpdmVzKG9sZE9iaiwgbmV3T2JqLCBwYXRoKSk7XG4gIH1cblxuICByZXR1cm4gY2hhbmdlcztcbn07XG5cbmNvbnN0IGNvbXBhcmVPYmplY3QgPSAob2xkT2JqOiBhbnksIG5ld09iajogYW55LCBwYXRoOiBhbnksIGtleVBhdGg6IGFueSwgc2tpcFBhdGggPSBmYWxzZSwgb3B0aW9uczogT3B0aW9ucyA9IHt9KSA9PiB7XG4gIGxldCBrO1xuICBsZXQgbmV3S2V5UGF0aDtcbiAgbGV0IG5ld1BhdGg7XG5cbiAgaWYgKHNraXBQYXRoID09IG51bGwpIHtcbiAgICBza2lwUGF0aCA9IGZhbHNlO1xuICB9XG4gIGxldCBjaGFuZ2VzOiBhbnlbXSA9IFtdO1xuXG4gIC8vIEZpbHRlciBrZXlzIGRpcmVjdGx5IHJhdGhlciB0aGFuIGZpbHRlcmluZyBieSBrZXlzVG9Ta2lwIGF0IHRoaXMgbGV2ZWxcbiAgLy8gVGhlIGZ1bGwgcGF0aCBjaGVjayBpcyBub3cgZG9uZSBpbiB0aGUgY29tcGFyZSBmdW5jdGlvblxuICBjb25zdCBvbGRPYmpLZXlzID0gT2JqZWN0LmtleXMob2xkT2JqKTtcbiAgY29uc3QgbmV3T2JqS2V5cyA9IE9iamVjdC5rZXlzKG5ld09iaik7XG5cbiAgY29uc3QgaW50ZXJzZWN0aW9uS2V5cyA9IGludGVyc2VjdGlvbihvbGRPYmpLZXlzLCBuZXdPYmpLZXlzKTtcbiAgZm9yIChrIG9mIGludGVyc2VjdGlvbktleXMpIHtcbiAgICBuZXdQYXRoID0gcGF0aC5jb25jYXQoW2tdKTtcbiAgICBuZXdLZXlQYXRoID0gc2tpcFBhdGggPyBrZXlQYXRoIDoga2V5UGF0aC5jb25jYXQoW2tdKTtcbiAgICBjb25zdCBkaWZmcyA9IGNvbXBhcmUob2xkT2JqW2tdLCBuZXdPYmpba10sIG5ld1BhdGgsIG5ld0tleVBhdGgsIG9wdGlvbnMpO1xuICAgIGlmIChkaWZmcy5sZW5ndGgpIHtcbiAgICAgIGNoYW5nZXMgPSBjaGFuZ2VzLmNvbmNhdChkaWZmcyk7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgYWRkZWRLZXlzID0gZGlmZmVyZW5jZShuZXdPYmpLZXlzLCBvbGRPYmpLZXlzKTtcbiAgZm9yIChrIG9mIGFkZGVkS2V5cykge1xuICAgIG5ld1BhdGggPSBwYXRoLmNvbmNhdChba10pO1xuICAgIG5ld0tleVBhdGggPSBza2lwUGF0aCA/IGtleVBhdGggOiBrZXlQYXRoLmNvbmNhdChba10pO1xuICAgIC8vIENoZWNrIGlmIHRoZSBwYXRoIHNob3VsZCBiZSBza2lwcGVkXG4gICAgY29uc3QgY3VycmVudFBhdGggPSBuZXdLZXlQYXRoLmpvaW4oJy4nKTtcbiAgICBpZiAob3B0aW9ucy5rZXlzVG9Ta2lwPy5zb21lKHNraXBQYXRoID0+IGN1cnJlbnRQYXRoID09PSBza2lwUGF0aCB8fCBjdXJyZW50UGF0aC5zdGFydHNXaXRoKHNraXBQYXRoICsgJy4nKSkpIHtcbiAgICAgIGNvbnRpbnVlOyAvLyBTa2lwIGFkZGluZyB0aGlzIGtleVxuICAgIH1cbiAgICBjaGFuZ2VzLnB1c2goe1xuICAgICAgdHlwZTogT3BlcmF0aW9uLkFERCxcbiAgICAgIGtleTogZ2V0S2V5KG5ld1BhdGgpLFxuICAgICAgdmFsdWU6IG5ld09ialtrXVxuICAgIH0pO1xuICB9XG5cbiAgY29uc3QgZGVsZXRlZEtleXMgPSBkaWZmZXJlbmNlKG9sZE9iaktleXMsIG5ld09iaktleXMpO1xuICBmb3IgKGsgb2YgZGVsZXRlZEtleXMpIHtcbiAgICBuZXdQYXRoID0gcGF0aC5jb25jYXQoW2tdKTtcbiAgICBuZXdLZXlQYXRoID0gc2tpcFBhdGggPyBrZXlQYXRoIDoga2V5UGF0aC5jb25jYXQoW2tdKTtcbiAgICAvLyBDaGVjayBpZiB0aGUgcGF0aCBzaG91bGQgYmUgc2tpcHBlZFxuICAgIGNvbnN0IGN1cnJlbnRQYXRoID0gbmV3S2V5UGF0aC5qb2luKCcuJyk7XG4gICAgaWYgKG9wdGlvbnMua2V5c1RvU2tpcD8uc29tZShza2lwUGF0aCA9PiBjdXJyZW50UGF0aCA9PT0gc2tpcFBhdGggfHwgY3VycmVudFBhdGguc3RhcnRzV2l0aChza2lwUGF0aCArICcuJykpKSB7XG4gICAgICBjb250aW51ZTsgLy8gU2tpcCByZW1vdmluZyB0aGlzIGtleVxuICAgIH1cbiAgICBjaGFuZ2VzLnB1c2goe1xuICAgICAgdHlwZTogT3BlcmF0aW9uLlJFTU9WRSxcbiAgICAgIGtleTogZ2V0S2V5KG5ld1BhdGgpLFxuICAgICAgdmFsdWU6IG9sZE9ialtrXVxuICAgIH0pO1xuICB9XG4gIHJldHVybiBjaGFuZ2VzO1xufTtcblxuY29uc3QgY29tcGFyZUFycmF5ID0gKG9sZE9iajogYW55LCBuZXdPYmo6IGFueSwgcGF0aDogYW55LCBrZXlQYXRoOiBhbnksIG9wdGlvbnM6IE9wdGlvbnMpID0+IHtcbiAgaWYgKGdldFR5cGVPZk9iaihuZXdPYmopICE9PSAnQXJyYXknKSB7XG4gICAgcmV0dXJuIFt7IHR5cGU6IE9wZXJhdGlvbi5VUERBVEUsIGtleTogZ2V0S2V5KHBhdGgpLCB2YWx1ZTogbmV3T2JqLCBvbGRWYWx1ZTogb2xkT2JqIH1dO1xuICB9XG5cbiAgY29uc3QgbGVmdCA9IGdldE9iamVjdEtleShvcHRpb25zLmVtYmVkZGVkT2JqS2V5cywga2V5UGF0aCk7XG4gIGNvbnN0IHVuaXFLZXkgPSBsZWZ0ICE9IG51bGwgPyBsZWZ0IDogJyRpbmRleCc7XG4gIGNvbnN0IGluZGV4ZWRPbGRPYmogPSBjb252ZXJ0QXJyYXlUb09iaihvbGRPYmosIHVuaXFLZXkpO1xuICBjb25zdCBpbmRleGVkTmV3T2JqID0gY29udmVydEFycmF5VG9PYmoobmV3T2JqLCB1bmlxS2V5KTtcbiAgY29uc3QgZGlmZnMgPSBjb21wYXJlT2JqZWN0KGluZGV4ZWRPbGRPYmosIGluZGV4ZWROZXdPYmosIHBhdGgsIGtleVBhdGgsIHRydWUsIG9wdGlvbnMpO1xuICBpZiAoZGlmZnMubGVuZ3RoKSB7XG4gICAgcmV0dXJuIFtcbiAgICAgIHtcbiAgICAgICAgdHlwZTogT3BlcmF0aW9uLlVQREFURSxcbiAgICAgICAga2V5OiBnZXRLZXkocGF0aCksXG4gICAgICAgIGVtYmVkZGVkS2V5OiB0eXBlb2YgdW5pcUtleSA9PT0gJ2Z1bmN0aW9uJyAmJiB1bmlxS2V5Lmxlbmd0aCA9PT0gMiA/IHVuaXFLZXkobmV3T2JqWzBdLCB0cnVlKSA6IHVuaXFLZXksXG4gICAgICAgIGNoYW5nZXM6IGRpZmZzXG4gICAgICB9XG4gICAgXTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gW107XG4gIH1cbn07XG5cbmNvbnN0IGdldE9iamVjdEtleSA9IChlbWJlZGRlZE9iaktleXM6IGFueSwga2V5UGF0aDogYW55KSA9PiB7XG4gIGlmIChlbWJlZGRlZE9iaktleXMgIT0gbnVsbCkge1xuICAgIGNvbnN0IHBhdGggPSBrZXlQYXRoLmpvaW4oJy4nKTtcblxuICAgIGlmIChlbWJlZGRlZE9iaktleXMgaW5zdGFuY2VvZiBNYXApIHtcbiAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIGVtYmVkZGVkT2JqS2V5cy5lbnRyaWVzKCkpIHtcbiAgICAgICAgaWYgKGtleSBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgIGlmIChwYXRoLm1hdGNoKGtleSkpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAocGF0aCA9PT0ga2V5KSB7XG4gICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qga2V5ID0gZW1iZWRkZWRPYmpLZXlzW3BhdGhdO1xuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGtleTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn07XG5cbmNvbnN0IGNvbnZlcnRBcnJheVRvT2JqID0gKGFycjogYW55W10sIHVuaXFLZXk6IGFueSkgPT4ge1xuICBsZXQgb2JqOiBhbnkgPSB7fTtcbiAgaWYgKHVuaXFLZXkgPT09ICckdmFsdWUnKSB7XG4gICAgYXJyLmZvckVhY2goKHZhbHVlKSA9PiB7XG4gICAgICBvYmpbdmFsdWVdID0gdmFsdWU7XG4gICAgfSk7XG4gIH0gZWxzZSBpZiAodW5pcUtleSAhPT0gJyRpbmRleCcpIHtcbiAgICAvLyBDb252ZXJ0IHN0cmluZyBrZXlzIHRvIGZ1bmN0aW9ucyBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIGVzLXRvb2xraXQga2V5QnlcbiAgICBjb25zdCBrZXlGdW5jdGlvbiA9IHR5cGVvZiB1bmlxS2V5ID09PSAnc3RyaW5nJyA/IChpdGVtOiBhbnkpID0+IGl0ZW1bdW5pcUtleV0gOiB1bmlxS2V5O1xuICAgIG9iaiA9IGtleUJ5KGFyciwga2V5RnVuY3Rpb24pO1xuICB9IGVsc2Uge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCB2YWx1ZSA9IGFycltpXTtcbiAgICAgIG9ialtpXSA9IHZhbHVlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gb2JqO1xufTtcblxuY29uc3QgY29tcGFyZVByaW1pdGl2ZXMgPSAob2xkT2JqOiBhbnksIG5ld09iajogYW55LCBwYXRoOiBhbnkpID0+IHtcbiAgY29uc3QgY2hhbmdlcyA9IFtdO1xuICBpZiAob2xkT2JqICE9PSBuZXdPYmopIHtcbiAgICBjaGFuZ2VzLnB1c2goe1xuICAgICAgdHlwZTogT3BlcmF0aW9uLlVQREFURSxcbiAgICAgIGtleTogZ2V0S2V5KHBhdGgpLFxuICAgICAgdmFsdWU6IG5ld09iaixcbiAgICAgIG9sZFZhbHVlOiBvbGRPYmpcbiAgICB9KTtcbiAgfVxuICByZXR1cm4gY2hhbmdlcztcbn07XG5cbmNvbnN0IHJlbW92ZUtleSA9IChvYmo6IGFueSwga2V5OiBhbnksIGVtYmVkZGVkS2V5OiBhbnkpID0+IHtcbiAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkge1xuICAgIGlmIChlbWJlZGRlZEtleSA9PT0gJyRpbmRleCcpIHtcbiAgICAgIG9iai5zcGxpY2UoTnVtYmVyKGtleSksIDEpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBpbmRleCA9IGluZGV4T2ZJdGVtSW5BcnJheShvYmosIGVtYmVkZGVkS2V5LCBrZXkpO1xuICAgIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oYEVsZW1lbnQgd2l0aCB0aGUga2V5ICcke2VtYmVkZGVkS2V5fScgYW5kIHZhbHVlICcke2tleX0nIGNvdWxkIG5vdCBiZSBmb3VuZCBpbiB0aGUgYXJyYXknYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHJldHVybiBvYmouc3BsaWNlKGluZGV4ICE9IG51bGwgPyBpbmRleCA6IGtleSwgMSk7XG4gIH0gZWxzZSB7XG4gICAgZGVsZXRlIG9ialtrZXldO1xuICAgIHJldHVybjtcbiAgfVxufTtcblxuY29uc3QgaW5kZXhPZkl0ZW1JbkFycmF5ID0gKGFycjogYW55W10sIGtleTogYW55LCB2YWx1ZTogYW55KSA9PiB7XG4gIGlmIChrZXkgPT09ICckdmFsdWUnKSB7XG4gICAgcmV0dXJuIGFyci5pbmRleE9mKHZhbHVlKTtcbiAgfVxuICBmb3IgKGxldCBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGl0ZW0gPSBhcnJbaV07XG4gICAgaWYgKGl0ZW0gJiYgaXRlbVtrZXldID8gaXRlbVtrZXldLnRvU3RyaW5nKCkgPT09IHZhbHVlLnRvU3RyaW5nKCkgOiB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gLTE7XG59O1xuXG5jb25zdCBtb2RpZnlLZXlWYWx1ZSA9IChvYmo6IGFueSwga2V5OiBhbnksIHZhbHVlOiBhbnkpID0+IChvYmpba2V5XSA9IHZhbHVlKTtcbmNvbnN0IGFkZEtleVZhbHVlID0gKG9iajogYW55LCBrZXk6IGFueSwgdmFsdWU6IGFueSwgZW1iZWRkZWRLZXk/OiBhbnkpID0+IHtcbiAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkge1xuICAgIGlmIChlbWJlZGRlZEtleSA9PT0gJyRpbmRleCcpIHtcbiAgICAgIG9iai5zcGxpY2UoTnVtYmVyKGtleSksIDAsIHZhbHVlKTtcbiAgICAgIHJldHVybiBvYmoubGVuZ3RoO1xuICAgIH1cbiAgICByZXR1cm4gb2JqLnB1c2godmFsdWUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBvYmogPyAob2JqW2tleV0gPSB2YWx1ZSkgOiBudWxsO1xuICB9XG59O1xuXG5jb25zdCBhcHBseUxlYWZDaGFuZ2UgPSAob2JqOiBhbnksIGNoYW5nZTogYW55LCBlbWJlZGRlZEtleTogYW55KSA9PiB7XG4gIGNvbnN0IHsgdHlwZSwga2V5LCB2YWx1ZSB9ID0gY2hhbmdlO1xuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlIE9wZXJhdGlvbi5BREQ6XG4gICAgICByZXR1cm4gYWRkS2V5VmFsdWUob2JqLCBrZXksIHZhbHVlLCBlbWJlZGRlZEtleSk7XG4gICAgY2FzZSBPcGVyYXRpb24uVVBEQVRFOlxuICAgICAgcmV0dXJuIG1vZGlmeUtleVZhbHVlKG9iaiwga2V5LCB2YWx1ZSk7XG4gICAgY2FzZSBPcGVyYXRpb24uUkVNT1ZFOlxuICAgICAgcmV0dXJuIHJlbW92ZUtleShvYmosIGtleSwgZW1iZWRkZWRLZXkpO1xuICB9XG59O1xuXG4vKipcbiAqIEFwcGxpZXMgY2hhbmdlcyB0byBhbiBhcnJheS5cbiAqIFxuICogQHBhcmFtIHthbnlbXX0gYXJyIC0gVGhlIGFycmF5IHRvIGFwcGx5IGNoYW5nZXMgdG8uXG4gKiBAcGFyYW0ge2FueX0gY2hhbmdlIC0gVGhlIGNoYW5nZSB0byBhcHBseSwgY29udGFpbmluZyBuZXN0ZWQgY2hhbmdlcy5cbiAqIEByZXR1cm5zIHthbnlbXX0gLSBUaGUgYXJyYXkgYWZ0ZXIgY2hhbmdlcyBoYXZlIGJlZW4gYXBwbGllZC5cbiAqXG4gKiBOb3RlOiBUaGlzIGZ1bmN0aW9uIG1vZGlmaWVzIHRoZSBhcnJheSBpbi1wbGFjZSBidXQgYWxzbyByZXR1cm5zIGl0IGZvclxuICogY29uc2lzdGVuY3kgd2l0aCBvdGhlciBmdW5jdGlvbnMuXG4gKi9cbmNvbnN0IGFwcGx5QXJyYXlDaGFuZ2UgPSAoYXJyOiBhbnlbXSwgY2hhbmdlOiBhbnkpID0+IHtcbiAgbGV0IGNoYW5nZXMgPSBjaGFuZ2UuY2hhbmdlcztcbiAgaWYgKGNoYW5nZS5lbWJlZGRlZEtleSA9PT0gJyRpbmRleCcpIHtcbiAgICBjaGFuZ2VzID0gWy4uLmNoYW5nZXNdLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgIGlmIChhLnR5cGUgPT09IE9wZXJhdGlvbi5SRU1PVkUgJiYgYi50eXBlID09PSBPcGVyYXRpb24uUkVNT1ZFKSB7XG4gICAgICAgIHJldHVybiBOdW1iZXIoYi5rZXkpIC0gTnVtYmVyKGEua2V5KTtcbiAgICAgIH1cbiAgICAgIGlmIChhLnR5cGUgPT09IE9wZXJhdGlvbi5SRU1PVkUpIHJldHVybiAtMTtcbiAgICAgIGlmIChiLnR5cGUgPT09IE9wZXJhdGlvbi5SRU1PVkUpIHJldHVybiAxO1xuICAgICAgcmV0dXJuIE51bWJlcihhLmtleSkgLSBOdW1iZXIoYi5rZXkpO1xuICAgIH0pO1xuICB9XG5cbiAgZm9yIChjb25zdCBzdWJjaGFuZ2Ugb2YgY2hhbmdlcykge1xuICAgIGlmIChcbiAgICAgIChzdWJjaGFuZ2UudmFsdWUgIT09IG51bGwgJiYgc3ViY2hhbmdlLnZhbHVlICE9PSB1bmRlZmluZWQpIHx8XG4gICAgICBzdWJjaGFuZ2UudHlwZSA9PT0gT3BlcmF0aW9uLlJFTU9WRSB8fFxuICAgICAgKHN1YmNoYW5nZS52YWx1ZSA9PT0gbnVsbCAmJiBzdWJjaGFuZ2UudHlwZSA9PT0gT3BlcmF0aW9uLkFERClcbiAgICApIHtcbiAgICAgIGFwcGx5TGVhZkNoYW5nZShhcnIsIHN1YmNoYW5nZSwgY2hhbmdlLmVtYmVkZGVkS2V5KTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IGVsZW1lbnQ7XG4gICAgICBpZiAoY2hhbmdlLmVtYmVkZGVkS2V5ID09PSAnJGluZGV4Jykge1xuICAgICAgICBlbGVtZW50ID0gYXJyW3N1YmNoYW5nZS5rZXldO1xuICAgICAgfSBlbHNlIGlmIChjaGFuZ2UuZW1iZWRkZWRLZXkgPT09ICckdmFsdWUnKSB7XG4gICAgICAgIGNvbnN0IGluZGV4ID0gYXJyLmluZGV4T2Yoc3ViY2hhbmdlLmtleSk7XG4gICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICBlbGVtZW50ID0gYXJyW2luZGV4XTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZWxlbWVudCA9IGFyci5maW5kKChlbCkgPT4gZWxbY2hhbmdlLmVtYmVkZGVkS2V5XT8udG9TdHJpbmcoKSA9PT0gc3ViY2hhbmdlLmtleS50b1N0cmluZygpKTtcbiAgICAgIH1cbiAgICAgIGlmIChlbGVtZW50KSB7XG4gICAgICAgIGFwcGx5Q2hhbmdlc2V0KGVsZW1lbnQsIHN1YmNoYW5nZS5jaGFuZ2VzKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIGFycjtcbn07XG5cbmNvbnN0IGFwcGx5QnJhbmNoQ2hhbmdlID0gKG9iajogYW55LCBjaGFuZ2U6IGFueSkgPT4ge1xuICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSB7XG4gICAgcmV0dXJuIGFwcGx5QXJyYXlDaGFuZ2Uob2JqLCBjaGFuZ2UpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBhcHBseUNoYW5nZXNldChvYmosIGNoYW5nZS5jaGFuZ2VzKTtcbiAgfVxufTtcblxuY29uc3QgcmV2ZXJ0TGVhZkNoYW5nZSA9IChvYmo6IGFueSwgY2hhbmdlOiBhbnksIGVtYmVkZGVkS2V5ID0gJyRpbmRleCcpID0+IHtcbiAgY29uc3QgeyB0eXBlLCBrZXksIHZhbHVlLCBvbGRWYWx1ZSB9ID0gY2hhbmdlO1xuICBcbiAgLy8gU3BlY2lhbCBoYW5kbGluZyBmb3IgJHJvb3Qga2V5XG4gIGlmIChrZXkgPT09ICckcm9vdCcpIHtcbiAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgIGNhc2UgT3BlcmF0aW9uLkFERDpcbiAgICAgICAgLy8gV2hlbiByZXZlcnRpbmcgYW4gQUREIG9mIHRoZSBlbnRpcmUgb2JqZWN0LCBjbGVhciBhbGwgcHJvcGVydGllc1xuICAgICAgICBmb3IgKGNvbnN0IHByb3AgaW4gb2JqKSB7XG4gICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3ApKSB7XG4gICAgICAgICAgICBkZWxldGUgb2JqW3Byb3BdO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb2JqO1xuICAgICAgY2FzZSBPcGVyYXRpb24uVVBEQVRFOlxuICAgICAgICAvLyBSZXBsYWNlIHRoZSBlbnRpcmUgb2JqZWN0IHdpdGggdGhlIG9sZCB2YWx1ZVxuICAgICAgICBmb3IgKGNvbnN0IHByb3AgaW4gb2JqKSB7XG4gICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3ApKSB7XG4gICAgICAgICAgICBkZWxldGUgb2JqW3Byb3BdO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAob2xkVmFsdWUgJiYgdHlwZW9mIG9sZFZhbHVlID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgIE9iamVjdC5hc3NpZ24ob2JqLCBvbGRWYWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgIGNhc2UgT3BlcmF0aW9uLlJFTU9WRTpcbiAgICAgICAgLy8gUmVzdG9yZSB0aGUgcmVtb3ZlZCBvYmplY3RcbiAgICAgICAgaWYgKHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICBPYmplY3QuYXNzaWduKG9iaiwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvYmo7XG4gICAgfVxuICB9XG4gIFxuICAvLyBSZWd1bGFyIHByb3BlcnR5IGhhbmRsaW5nXG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgT3BlcmF0aW9uLkFERDpcbiAgICAgIHJldHVybiByZW1vdmVLZXkob2JqLCBrZXksIGVtYmVkZGVkS2V5KTtcbiAgICBjYXNlIE9wZXJhdGlvbi5VUERBVEU6XG4gICAgICByZXR1cm4gbW9kaWZ5S2V5VmFsdWUob2JqLCBrZXksIG9sZFZhbHVlKTtcbiAgICBjYXNlIE9wZXJhdGlvbi5SRU1PVkU6XG4gICAgICByZXR1cm4gYWRkS2V5VmFsdWUob2JqLCBrZXksIHZhbHVlKTtcbiAgfVxufTtcblxuLyoqXG4gKiBSZXZlcnRzIGNoYW5nZXMgaW4gYW4gYXJyYXkuXG4gKiBcbiAqIEBwYXJhbSB7YW55W119IGFyciAtIFRoZSBhcnJheSB0byByZXZlcnQgY2hhbmdlcyBpbi5cbiAqIEBwYXJhbSB7YW55fSBjaGFuZ2UgLSBUaGUgY2hhbmdlIHRvIHJldmVydCwgY29udGFpbmluZyBuZXN0ZWQgY2hhbmdlcy5cbiAqIEByZXR1cm5zIHthbnlbXX0gLSBUaGUgYXJyYXkgYWZ0ZXIgY2hhbmdlcyBoYXZlIGJlZW4gcmV2ZXJ0ZWQuXG4gKlxuICogTm90ZTogVGhpcyBmdW5jdGlvbiBtb2RpZmllcyB0aGUgYXJyYXkgaW4tcGxhY2UgYnV0IGFsc28gcmV0dXJucyBpdCBmb3JcbiAqIGNvbnNpc3RlbmN5IHdpdGggb3RoZXIgZnVuY3Rpb25zLlxuICovXG5jb25zdCByZXZlcnRBcnJheUNoYW5nZSA9IChhcnI6IGFueVtdLCBjaGFuZ2U6IGFueSkgPT4ge1xuICBmb3IgKGNvbnN0IHN1YmNoYW5nZSBvZiBjaGFuZ2UuY2hhbmdlcykge1xuICAgIGlmIChzdWJjaGFuZ2UudmFsdWUgIT0gbnVsbCB8fCBzdWJjaGFuZ2UudHlwZSA9PT0gT3BlcmF0aW9uLlJFTU9WRSkge1xuICAgICAgcmV2ZXJ0TGVhZkNoYW5nZShhcnIsIHN1YmNoYW5nZSwgY2hhbmdlLmVtYmVkZGVkS2V5KTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IGVsZW1lbnQ7XG4gICAgICBpZiAoY2hhbmdlLmVtYmVkZGVkS2V5ID09PSAnJGluZGV4Jykge1xuICAgICAgICBlbGVtZW50ID0gYXJyWytzdWJjaGFuZ2Uua2V5XTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhbmdlLmVtYmVkZGVkS2V5ID09PSAnJHZhbHVlJykge1xuICAgICAgICBjb25zdCBpbmRleCA9IGFyci5pbmRleE9mKHN1YmNoYW5nZS5rZXkpO1xuICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgZWxlbWVudCA9IGFycltpbmRleF07XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVsZW1lbnQgPSBhcnIuZmluZCgoZWwpID0+IGVsW2NoYW5nZS5lbWJlZGRlZEtleV0/LnRvU3RyaW5nKCkgPT09IHN1YmNoYW5nZS5rZXkudG9TdHJpbmcoKSk7XG4gICAgICB9XG4gICAgICBpZiAoZWxlbWVudCkge1xuICAgICAgICByZXZlcnRDaGFuZ2VzZXQoZWxlbWVudCwgc3ViY2hhbmdlLmNoYW5nZXMpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gYXJyO1xufTtcblxuY29uc3QgcmV2ZXJ0QnJhbmNoQ2hhbmdlID0gKG9iajogYW55LCBjaGFuZ2U6IGFueSkgPT4ge1xuICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSB7XG4gICAgcmV0dXJuIHJldmVydEFycmF5Q2hhbmdlKG9iaiwgY2hhbmdlKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gcmV2ZXJ0Q2hhbmdlc2V0KG9iaiwgY2hhbmdlLmNoYW5nZXMpO1xuICB9XG59O1xuXG4vKiogY29tYmluZSBhIGJhc2UgSlNPTiBQYXRoIHdpdGggYSBzdWJzZXF1ZW50IHNlZ21lbnQgKi9cbmZ1bmN0aW9uIGFwcGVuZChiYXNlUGF0aDogc3RyaW5nLCBuZXh0U2VnbWVudDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIG5leHRTZWdtZW50LmluY2x1ZGVzKCcuJykgPyBgJHtiYXNlUGF0aH1bJHtuZXh0U2VnbWVudH1dYCA6IGAke2Jhc2VQYXRofS4ke25leHRTZWdtZW50fWA7XG59XG5cbi8qKiByZXR1cm5zIGEgSlNPTiBQYXRoIGZpbHRlciBleHByZXNzaW9uOyBlLmcuLCBgJC5wZXRbKD9uYW1lPSdzcG90JyldYCAqL1xuZnVuY3Rpb24gZmlsdGVyRXhwcmVzc2lvbihiYXNlUGF0aDogc3RyaW5nLCBmaWx0ZXJLZXk6IHN0cmluZyB8IEZ1bmN0aW9uS2V5LCBmaWx0ZXJWYWx1ZTogc3RyaW5nIHwgbnVtYmVyKSB7XG4gIGNvbnN0IHZhbHVlID0gdHlwZW9mIGZpbHRlclZhbHVlID09PSAnbnVtYmVyJyA/IGZpbHRlclZhbHVlIDogYCcke2ZpbHRlclZhbHVlfSdgO1xuICByZXR1cm4gdHlwZW9mIGZpbHRlcktleSA9PT0gJ3N0cmluZycgJiYgZmlsdGVyS2V5LmluY2x1ZGVzKCcuJylcbiAgICA/IGAke2Jhc2VQYXRofVs/KEBbJHtmaWx0ZXJLZXl9XT09JHt2YWx1ZX0pXWBcbiAgICA6IGAke2Jhc2VQYXRofVs/KEAuJHtmaWx0ZXJLZXl9PT0ke3ZhbHVlfSldYDtcbn1cblxuZXhwb3J0IHtcbiAgQ2hhbmdlc2V0LFxuICBFbWJlZGRlZE9iaktleXNNYXBUeXBlLFxuICBFbWJlZGRlZE9iaktleXNUeXBlLFxuICBJQXRvbWljQ2hhbmdlLFxuICBJQ2hhbmdlLFxuICBPcGVyYXRpb24sXG4gIE9wdGlvbnMsXG4gIGFwcGx5Q2hhbmdlc2V0LFxuICBhdG9taXplQ2hhbmdlc2V0LFxuICBkaWZmLFxuICBnZXRUeXBlT2ZPYmosXG4gIHJldmVydENoYW5nZXNldCxcbiAgdW5hdG9taXplQ2hhbmdlc2V0XG59O1xuIiwgImltcG9ydCB7IHNldEJ5UGF0aCB9IGZyb20gJy4vaGVscGVycy5qcyc7XG5pbXBvcnQgeyBkaWZmLCBhdG9taXplQ2hhbmdlc2V0LCBnZXRUeXBlT2ZPYmosIElBdG9taWNDaGFuZ2UsIE9wZXJhdGlvbiB9IGZyb20gJy4vanNvbkRpZmYuanMnO1xuXG5lbnVtIENvbXBhcmVPcGVyYXRpb24ge1xuICBDT05UQUlORVIgPSAnQ09OVEFJTkVSJyxcbiAgVU5DSEFOR0VEID0gJ1VOQ0hBTkdFRCdcbn1cblxuaW50ZXJmYWNlIElDb21wYXJpc29uRW5yaWNoZWROb2RlIHtcbiAgdHlwZTogT3BlcmF0aW9uIHwgQ29tcGFyZU9wZXJhdGlvbjtcbiAgdmFsdWU6IElDb21wYXJpc29uRW5yaWNoZWROb2RlIHwgSUNvbXBhcmlzb25FbnJpY2hlZE5vZGVbXSB8IGFueSB8IGFueVtdO1xuICBvbGRWYWx1ZT86IGFueTtcbn1cblxuY29uc3QgY3JlYXRlVmFsdWUgPSAodmFsdWU6IGFueSk6IElDb21wYXJpc29uRW5yaWNoZWROb2RlID0+ICh7IHR5cGU6IENvbXBhcmVPcGVyYXRpb24uVU5DSEFOR0VELCB2YWx1ZSB9KTtcbmNvbnN0IGNyZWF0ZUNvbnRhaW5lciA9ICh2YWx1ZTogb2JqZWN0IHwgW10pOiBJQ29tcGFyaXNvbkVucmljaGVkTm9kZSA9PiAoe1xuICB0eXBlOiBDb21wYXJlT3BlcmF0aW9uLkNPTlRBSU5FUixcbiAgdmFsdWVcbn0pO1xuXG5jb25zdCBlbnJpY2ggPSAob2JqZWN0OiBhbnkpOiBJQ29tcGFyaXNvbkVucmljaGVkTm9kZSA9PiB7XG4gIGNvbnN0IG9iamVjdFR5cGUgPSBnZXRUeXBlT2ZPYmoob2JqZWN0KTtcblxuICBzd2l0Y2ggKG9iamVjdFR5cGUpIHtcbiAgICBjYXNlICdPYmplY3QnOlxuICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKG9iamVjdClcbiAgICAgICAgLm1hcCgoa2V5OiBzdHJpbmcpID0+ICh7IGtleSwgdmFsdWU6IGVucmljaChvYmplY3Rba2V5XSkgfSkpXG4gICAgICAgIC5yZWR1Y2UoKGFjY3VtdWxhdG9yLCBlbnRyeSkgPT4ge1xuICAgICAgICAgIGFjY3VtdWxhdG9yLnZhbHVlW2VudHJ5LmtleV0gPSBlbnRyeS52YWx1ZTtcbiAgICAgICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgICAgIH0sIGNyZWF0ZUNvbnRhaW5lcih7fSkpO1xuICAgIGNhc2UgJ0FycmF5JzpcbiAgICAgIHJldHVybiAob2JqZWN0IGFzIGFueVtdKVxuICAgICAgICAubWFwKCh2YWx1ZSkgPT4gZW5yaWNoKHZhbHVlKSlcbiAgICAgICAgLnJlZHVjZSgoYWNjdW11bGF0b3IsIHZhbHVlKSA9PiB7XG4gICAgICAgICAgYWNjdW11bGF0b3IudmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgICAgICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAgICAgICB9LCBjcmVhdGVDb250YWluZXIoW10pKTtcbiAgICBjYXNlICdGdW5jdGlvbic6XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGNhc2UgJ0RhdGUnOlxuICAgIGRlZmF1bHQ6XG4gICAgICAvLyBQcmltaXRpdmUgdmFsdWVcbiAgICAgIHJldHVybiBjcmVhdGVWYWx1ZShvYmplY3QpO1xuICB9XG59O1xuXG5jb25zdCBhcHBseUNoYW5nZWxpc3QgPSAob2JqZWN0OiBJQ29tcGFyaXNvbkVucmljaGVkTm9kZSwgY2hhbmdlbGlzdDogSUF0b21pY0NoYW5nZVtdKTogSUNvbXBhcmlzb25FbnJpY2hlZE5vZGUgPT4ge1xuICBjaGFuZ2VsaXN0XG4gICAgLm1hcCgoZW50cnkpID0+ICh7IC4uLmVudHJ5LCBwYXRoOiBlbnRyeS5wYXRoLnJlcGxhY2UoJyQuJywgJy4nKSB9KSlcbiAgICAubWFwKChlbnRyeSkgPT4gKHtcbiAgICAgIC4uLmVudHJ5LFxuICAgICAgcGF0aDogZW50cnkucGF0aC5yZXBsYWNlKC8oXFxbKD88YXJyYXk+XFxkKVxcXVxcLikvZywgJ0FSUlZBTF9TVEFSVCQ8YXJyYXk+QVJSVkFMX0VORCcpXG4gICAgfSkpXG4gICAgLm1hcCgoZW50cnkpID0+ICh7IC4uLmVudHJ5LCBwYXRoOiBlbnRyeS5wYXRoLnJlcGxhY2UoLyg/PGRvdD5cXC4pL2csICcudmFsdWUkPGRvdD4nKSB9KSlcbiAgICAubWFwKChlbnRyeSkgPT4gKHsgLi4uZW50cnksIHBhdGg6IGVudHJ5LnBhdGgucmVwbGFjZSgvXFwuLywgJycpIH0pKVxuICAgIC5tYXAoKGVudHJ5KSA9PiAoeyAuLi5lbnRyeSwgcGF0aDogZW50cnkucGF0aC5yZXBsYWNlKC9BUlJWQUxfU1RBUlQvZywgJy52YWx1ZVsnKSB9KSlcbiAgICAubWFwKChlbnRyeSkgPT4gKHsgLi4uZW50cnksIHBhdGg6IGVudHJ5LnBhdGgucmVwbGFjZSgvQVJSVkFMX0VORC9nLCAnXS52YWx1ZS4nKSB9KSlcbiAgICAuZm9yRWFjaCgoZW50cnkpID0+IHtcbiAgICAgIHN3aXRjaCAoZW50cnkudHlwZSkge1xuICAgICAgICBjYXNlIE9wZXJhdGlvbi5BREQ6XG4gICAgICAgIGNhc2UgT3BlcmF0aW9uLlVQREFURTpcbiAgICAgICAgICBzZXRCeVBhdGgob2JqZWN0LCBlbnRyeS5wYXRoLCB7IHR5cGU6IGVudHJ5LnR5cGUsIHZhbHVlOiBlbnRyeS52YWx1ZSwgb2xkVmFsdWU6IGVudHJ5Lm9sZFZhbHVlIH0pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIE9wZXJhdGlvbi5SRU1PVkU6XG4gICAgICAgICAgc2V0QnlQYXRoKG9iamVjdCwgZW50cnkucGF0aCwgeyB0eXBlOiBlbnRyeS50eXBlLCB2YWx1ZTogdW5kZWZpbmVkLCBvbGRWYWx1ZTogZW50cnkudmFsdWUgfSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIHJldHVybiBvYmplY3Q7XG59O1xuXG5jb25zdCBjb21wYXJlID0gKG9sZE9iamVjdDogYW55LCBuZXdPYmplY3Q6IGFueSk6IElDb21wYXJpc29uRW5yaWNoZWROb2RlID0+IHtcbiAgcmV0dXJuIGFwcGx5Q2hhbmdlbGlzdChlbnJpY2gob2xkT2JqZWN0KSwgYXRvbWl6ZUNoYW5nZXNldChkaWZmKG9sZE9iamVjdCwgbmV3T2JqZWN0KSkpO1xufTtcblxuZXhwb3J0IHsgQ29tcGFyZU9wZXJhdGlvbiwgSUNvbXBhcmlzb25FbnJpY2hlZE5vZGUsIGNyZWF0ZVZhbHVlLCBjcmVhdGVDb250YWluZXIsIGVucmljaCwgYXBwbHlDaGFuZ2VsaXN0LCBjb21wYXJlIH07XG4iLCAiaW1wb3J0IHsgU3luY1BsdWdpbiB9IGZyb20gJy4vU3luY1BsdWdpbic7XG5pbXBvcnQgeyBDb3JlRXZlbnRzIH0gZnJvbSAnLi4vY29uc3RhbnRzL0NvcmVFdmVudHMnO1xuaW1wb3J0IHsgZGlmZiB9IGZyb20gJ2pzb24tZGlmZi10cyc7XG4vKipcbiAqIEJhc2VFbnRpdHlTZXJ2aWNlPFQgZXh0ZW5kcyBJU3luYz4gLSBBYnN0cmFjdCBiYXNlIGNsYXNzIGZvciBhbGwgZW50aXR5IHNlcnZpY2VzXG4gKlxuICogUFJPVklERVM6XG4gKiAtIEdlbmVyaWMgQ1JVRCBvcGVyYXRpb25zIChnZXQsIGdldEFsbCwgc2F2ZSwgZGVsZXRlKVxuICogLSBTeW5jIHN0YXR1cyBtYW5hZ2VtZW50IChkZWxlZ2F0ZXMgdG8gU3luY1BsdWdpbilcbiAqIC0gU2VyaWFsaXphdGlvbiBob29rcyAob3ZlcnJpZGUgaW4gc3ViY2xhc3MgaWYgbmVlZGVkKVxuICovXG5leHBvcnQgY2xhc3MgQmFzZUVudGl0eVNlcnZpY2Uge1xuICAgIGNvbnN0cnVjdG9yKGNvbnRleHQsIGV2ZW50QnVzKSB7XG4gICAgICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHQ7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMgPSBldmVudEJ1cztcbiAgICAgICAgdGhpcy5zeW5jUGx1Z2luID0gbmV3IFN5bmNQbHVnaW4odGhpcyk7XG4gICAgfVxuICAgIGdldCBkYigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29udGV4dC5nZXREYXRhYmFzZSgpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZXJpYWxpemUgZW50aXR5IGJlZm9yZSBzdG9yaW5nIGluIEluZGV4ZWREQlxuICAgICAqL1xuICAgIHNlcmlhbGl6ZShlbnRpdHkpIHtcbiAgICAgICAgcmV0dXJuIGVudGl0eTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRGVzZXJpYWxpemUgZGF0YSBmcm9tIEluZGV4ZWREQiBiYWNrIHRvIGVudGl0eVxuICAgICAqL1xuICAgIGRlc2VyaWFsaXplKGRhdGEpIHtcbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBhIHNpbmdsZSBlbnRpdHkgYnkgSURcbiAgICAgKi9cbiAgICBhc3luYyBnZXQoaWQpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gdGhpcy5kYi50cmFuc2FjdGlvbihbdGhpcy5zdG9yZU5hbWVdLCAncmVhZG9ubHknKTtcbiAgICAgICAgICAgIGNvbnN0IHN0b3JlID0gdHJhbnNhY3Rpb24ub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpO1xuICAgICAgICAgICAgY29uc3QgcmVxdWVzdCA9IHN0b3JlLmdldChpZCk7XG4gICAgICAgICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gcmVxdWVzdC5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShkYXRhID8gdGhpcy5kZXNlcmlhbGl6ZShkYXRhKSA6IG51bGwpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gZ2V0ICR7dGhpcy5lbnRpdHlUeXBlfSAke2lkfTogJHtyZXF1ZXN0LmVycm9yfWApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIGVudGl0aWVzXG4gICAgICovXG4gICAgYXN5bmMgZ2V0QWxsKCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSB0aGlzLmRiLnRyYW5zYWN0aW9uKFt0aGlzLnN0b3JlTmFtZV0sICdyZWFkb25seScpO1xuICAgICAgICAgICAgY29uc3Qgc3RvcmUgPSB0cmFuc2FjdGlvbi5vYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7XG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gc3RvcmUuZ2V0QWxsKCk7XG4gICAgICAgICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gcmVxdWVzdC5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgY29uc3QgZW50aXRpZXMgPSBkYXRhLm1hcChpdGVtID0+IHRoaXMuZGVzZXJpYWxpemUoaXRlbSkpO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoZW50aXRpZXMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gZ2V0IGFsbCAke3RoaXMuZW50aXR5VHlwZX1zOiAke3JlcXVlc3QuZXJyb3J9YCkpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNhdmUgYW4gZW50aXR5IChjcmVhdGUgb3IgdXBkYXRlKVxuICAgICAqIEVtaXRzIEVOVElUWV9TQVZFRCBldmVudCB3aXRoIG9wZXJhdGlvbiB0eXBlIGFuZCBjaGFuZ2VzIChkaWZmIGZvciB1cGRhdGVzKVxuICAgICAqIEBwYXJhbSBlbnRpdHkgLSBFbnRpdHkgdG8gc2F2ZVxuICAgICAqIEBwYXJhbSBzaWxlbnQgLSBJZiB0cnVlLCBza2lwIGV2ZW50IGVtaXNzaW9uICh1c2VkIGZvciBzZWVkaW5nKVxuICAgICAqL1xuICAgIGFzeW5jIHNhdmUoZW50aXR5LCBzaWxlbnQgPSBmYWxzZSkge1xuICAgICAgICBjb25zdCBlbnRpdHlJZCA9IGVudGl0eS5pZDtcbiAgICAgICAgY29uc3QgZXhpc3RpbmdFbnRpdHkgPSBhd2FpdCB0aGlzLmdldChlbnRpdHlJZCk7XG4gICAgICAgIGNvbnN0IGlzQ3JlYXRlID0gZXhpc3RpbmdFbnRpdHkgPT09IG51bGw7XG4gICAgICAgIC8vIENhbGN1bGF0ZSBjaGFuZ2VzOiBmdWxsIGVudGl0eSBmb3IgY3JlYXRlLCBkaWZmIGZvciB1cGRhdGVcbiAgICAgICAgbGV0IGNoYW5nZXM7XG4gICAgICAgIGlmIChpc0NyZWF0ZSkge1xuICAgICAgICAgICAgY2hhbmdlcyA9IGVudGl0eTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nU2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplKGV4aXN0aW5nRW50aXR5KTtcbiAgICAgICAgICAgIGNvbnN0IG5ld1NlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZShlbnRpdHkpO1xuICAgICAgICAgICAgY2hhbmdlcyA9IGRpZmYoZXhpc3RpbmdTZXJpYWxpemVkLCBuZXdTZXJpYWxpemVkKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemUoZW50aXR5KTtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gdGhpcy5kYi50cmFuc2FjdGlvbihbdGhpcy5zdG9yZU5hbWVdLCAncmVhZHdyaXRlJyk7XG4gICAgICAgICAgICBjb25zdCBzdG9yZSA9IHRyYW5zYWN0aW9uLm9iamVjdFN0b3JlKHRoaXMuc3RvcmVOYW1lKTtcbiAgICAgICAgICAgIGNvbnN0IHJlcXVlc3QgPSBzdG9yZS5wdXQoc2VyaWFsaXplZCk7XG4gICAgICAgICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBPbmx5IGVtaXQgZXZlbnQgaWYgbm90IHNpbGVudCAoc2lsZW50IHVzZWQgZm9yIHNlZWRpbmcpXG4gICAgICAgICAgICAgICAgaWYgKCFzaWxlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVudGl0eVR5cGU6IHRoaXMuZW50aXR5VHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVudGl0eUlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgb3BlcmF0aW9uOiBpc0NyZWF0ZSA/ICdjcmVhdGUnIDogJ3VwZGF0ZScsXG4gICAgICAgICAgICAgICAgICAgICAgICBjaGFuZ2VzLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMuZW1pdChDb3JlRXZlbnRzLkVOVElUWV9TQVZFRCwgcGF5bG9hZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXF1ZXN0Lm9uZXJyb3IgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgRmFpbGVkIHRvIHNhdmUgJHt0aGlzLmVudGl0eVR5cGV9ICR7ZW50aXR5SWR9OiAke3JlcXVlc3QuZXJyb3J9YCkpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIERlbGV0ZSBhbiBlbnRpdHlcbiAgICAgKiBFbWl0cyBFTlRJVFlfREVMRVRFRCBldmVudFxuICAgICAqL1xuICAgIGFzeW5jIGRlbGV0ZShpZCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSB0aGlzLmRiLnRyYW5zYWN0aW9uKFt0aGlzLnN0b3JlTmFtZV0sICdyZWFkd3JpdGUnKTtcbiAgICAgICAgICAgIGNvbnN0IHN0b3JlID0gdHJhbnNhY3Rpb24ub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpO1xuICAgICAgICAgICAgY29uc3QgcmVxdWVzdCA9IHN0b3JlLmRlbGV0ZShpZCk7XG4gICAgICAgICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXlsb2FkID0ge1xuICAgICAgICAgICAgICAgICAgICBlbnRpdHlUeXBlOiB0aGlzLmVudGl0eVR5cGUsXG4gICAgICAgICAgICAgICAgICAgIGVudGl0eUlkOiBpZCxcbiAgICAgICAgICAgICAgICAgICAgb3BlcmF0aW9uOiAnZGVsZXRlJyxcbiAgICAgICAgICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ29yZUV2ZW50cy5FTlRJVFlfREVMRVRFRCwgcGF5bG9hZCk7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gZGVsZXRlICR7dGhpcy5lbnRpdHlUeXBlfSAke2lkfTogJHtyZXF1ZXN0LmVycm9yfWApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBTeW5jIG1ldGhvZHMgLSBkZWxlZ2F0ZSB0byBTeW5jUGx1Z2luXG4gICAgYXN5bmMgbWFya0FzU3luY2VkKGlkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN5bmNQbHVnaW4ubWFya0FzU3luY2VkKGlkKTtcbiAgICB9XG4gICAgYXN5bmMgbWFya0FzRXJyb3IoaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3luY1BsdWdpbi5tYXJrQXNFcnJvcihpZCk7XG4gICAgfVxuICAgIGFzeW5jIGdldFN5bmNTdGF0dXMoaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3luY1BsdWdpbi5nZXRTeW5jU3RhdHVzKGlkKTtcbiAgICB9XG4gICAgYXN5bmMgZ2V0QnlTeW5jU3RhdHVzKHN5bmNTdGF0dXMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3luY1BsdWdpbi5nZXRCeVN5bmNTdGF0dXMoc3luY1N0YXR1cyk7XG4gICAgfVxufVxuIiwgImltcG9ydCB7IEV2ZW50U3RvcmUgfSBmcm9tICcuL0V2ZW50U3RvcmUnO1xuaW1wb3J0IHsgRXZlbnRTZXJpYWxpemF0aW9uIH0gZnJvbSAnLi9FdmVudFNlcmlhbGl6YXRpb24nO1xuaW1wb3J0IHsgQmFzZUVudGl0eVNlcnZpY2UgfSBmcm9tICcuLi9CYXNlRW50aXR5U2VydmljZSc7XG4vKipcbiAqIEV2ZW50U2VydmljZSAtIENSVUQgb3BlcmF0aW9ucyBmb3IgY2FsZW5kYXIgZXZlbnRzIGluIEluZGV4ZWREQlxuICpcbiAqIEV4dGVuZHMgQmFzZUVudGl0eVNlcnZpY2UgZm9yIHNoYXJlZCBDUlVEIGFuZCBzeW5jIGxvZ2ljLlxuICogUHJvdmlkZXMgZXZlbnQtc3BlY2lmaWMgcXVlcnkgbWV0aG9kcy5cbiAqL1xuZXhwb3J0IGNsYXNzIEV2ZW50U2VydmljZSBleHRlbmRzIEJhc2VFbnRpdHlTZXJ2aWNlIHtcbiAgICBjb25zdHJ1Y3Rvcihjb250ZXh0LCBldmVudEJ1cykge1xuICAgICAgICBzdXBlcihjb250ZXh0LCBldmVudEJ1cyk7XG4gICAgICAgIHRoaXMuc3RvcmVOYW1lID0gRXZlbnRTdG9yZS5TVE9SRV9OQU1FO1xuICAgICAgICB0aGlzLmVudGl0eVR5cGUgPSAnRXZlbnQnO1xuICAgIH1cbiAgICBzZXJpYWxpemUoZXZlbnQpIHtcbiAgICAgICAgcmV0dXJuIEV2ZW50U2VyaWFsaXphdGlvbi5zZXJpYWxpemUoZXZlbnQpO1xuICAgIH1cbiAgICBkZXNlcmlhbGl6ZShkYXRhKSB7XG4gICAgICAgIHJldHVybiBFdmVudFNlcmlhbGl6YXRpb24uZGVzZXJpYWxpemUoZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBldmVudHMgd2l0aGluIGEgZGF0ZSByYW5nZVxuICAgICAqL1xuICAgIGFzeW5jIGdldEJ5RGF0ZVJhbmdlKHN0YXJ0LCBlbmQpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gdGhpcy5kYi50cmFuc2FjdGlvbihbdGhpcy5zdG9yZU5hbWVdLCAncmVhZG9ubHknKTtcbiAgICAgICAgICAgIGNvbnN0IHN0b3JlID0gdHJhbnNhY3Rpb24ub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpO1xuICAgICAgICAgICAgY29uc3QgaW5kZXggPSBzdG9yZS5pbmRleCgnc3RhcnQnKTtcbiAgICAgICAgICAgIGNvbnN0IHJhbmdlID0gSURCS2V5UmFuZ2UubG93ZXJCb3VuZChzdGFydC50b0lTT1N0cmluZygpKTtcbiAgICAgICAgICAgIGNvbnN0IHJlcXVlc3QgPSBpbmRleC5nZXRBbGwocmFuZ2UpO1xuICAgICAgICAgICAgcmVxdWVzdC5vbnN1Y2Nlc3MgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IHJlcXVlc3QucmVzdWx0O1xuICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50cyA9IGRhdGFcbiAgICAgICAgICAgICAgICAgICAgLm1hcChpdGVtID0+IHRoaXMuZGVzZXJpYWxpemUoaXRlbSkpXG4gICAgICAgICAgICAgICAgICAgIC5maWx0ZXIoZXZlbnQgPT4gZXZlbnQuc3RhcnQgPD0gZW5kKTtcbiAgICAgICAgICAgICAgICByZXNvbHZlKGV2ZW50cyk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVxdWVzdC5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBnZXQgZXZlbnRzIGJ5IGRhdGUgcmFuZ2U6ICR7cmVxdWVzdC5lcnJvcn1gKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGV2ZW50cyBmb3IgYSBzcGVjaWZpYyByZXNvdXJjZVxuICAgICAqL1xuICAgIGFzeW5jIGdldEJ5UmVzb3VyY2UocmVzb3VyY2VJZCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSB0aGlzLmRiLnRyYW5zYWN0aW9uKFt0aGlzLnN0b3JlTmFtZV0sICdyZWFkb25seScpO1xuICAgICAgICAgICAgY29uc3Qgc3RvcmUgPSB0cmFuc2FjdGlvbi5vYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7XG4gICAgICAgICAgICBjb25zdCBpbmRleCA9IHN0b3JlLmluZGV4KCdyZXNvdXJjZUlkJyk7XG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gaW5kZXguZ2V0QWxsKHJlc291cmNlSWQpO1xuICAgICAgICAgICAgcmVxdWVzdC5vbnN1Y2Nlc3MgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IHJlcXVlc3QucmVzdWx0O1xuICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50cyA9IGRhdGEubWFwKGl0ZW0gPT4gdGhpcy5kZXNlcmlhbGl6ZShpdGVtKSk7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShldmVudHMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gZ2V0IGV2ZW50cyBmb3IgcmVzb3VyY2UgJHtyZXNvdXJjZUlkfTogJHtyZXF1ZXN0LmVycm9yfWApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgZXZlbnRzIGZvciBhIHJlc291cmNlIHdpdGhpbiBhIGRhdGUgcmFuZ2VcbiAgICAgKi9cbiAgICBhc3luYyBnZXRCeVJlc291cmNlQW5kRGF0ZVJhbmdlKHJlc291cmNlSWQsIHN0YXJ0LCBlbmQpIHtcbiAgICAgICAgY29uc3QgcmVzb3VyY2VFdmVudHMgPSBhd2FpdCB0aGlzLmdldEJ5UmVzb3VyY2UocmVzb3VyY2VJZCk7XG4gICAgICAgIHJldHVybiByZXNvdXJjZUV2ZW50cy5maWx0ZXIoZXZlbnQgPT4gZXZlbnQuc3RhcnQgPj0gc3RhcnQgJiYgZXZlbnQuc3RhcnQgPD0gZW5kKTtcbiAgICB9XG59XG4iLCAiLyoqXG4gKiBSZXNvdXJjZVN0b3JlIC0gSW5kZXhlZERCIE9iamVjdFN0b3JlIGRlZmluaXRpb24gZm9yIHJlc291cmNlc1xuICovXG5leHBvcnQgY2xhc3MgUmVzb3VyY2VTdG9yZSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuc3RvcmVOYW1lID0gUmVzb3VyY2VTdG9yZS5TVE9SRV9OQU1FO1xuICAgIH1cbiAgICBjcmVhdGUoZGIpIHtcbiAgICAgICAgY29uc3Qgc3RvcmUgPSBkYi5jcmVhdGVPYmplY3RTdG9yZShSZXNvdXJjZVN0b3JlLlNUT1JFX05BTUUsIHsga2V5UGF0aDogJ2lkJyB9KTtcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ3R5cGUnLCAndHlwZScsIHsgdW5pcXVlOiBmYWxzZSB9KTtcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ3N5bmNTdGF0dXMnLCAnc3luY1N0YXR1cycsIHsgdW5pcXVlOiBmYWxzZSB9KTtcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ2lzQWN0aXZlJywgJ2lzQWN0aXZlJywgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgIH1cbn1cblJlc291cmNlU3RvcmUuU1RPUkVfTkFNRSA9ICdyZXNvdXJjZXMnO1xuIiwgImltcG9ydCB7IFJlc291cmNlU3RvcmUgfSBmcm9tICcuL1Jlc291cmNlU3RvcmUnO1xuaW1wb3J0IHsgQmFzZUVudGl0eVNlcnZpY2UgfSBmcm9tICcuLi9CYXNlRW50aXR5U2VydmljZSc7XG4vKipcbiAqIFJlc291cmNlU2VydmljZSAtIENSVUQgb3BlcmF0aW9ucyBmb3IgcmVzb3VyY2VzIGluIEluZGV4ZWREQlxuICovXG5leHBvcnQgY2xhc3MgUmVzb3VyY2VTZXJ2aWNlIGV4dGVuZHMgQmFzZUVudGl0eVNlcnZpY2Uge1xuICAgIGNvbnN0cnVjdG9yKGNvbnRleHQsIGV2ZW50QnVzKSB7XG4gICAgICAgIHN1cGVyKGNvbnRleHQsIGV2ZW50QnVzKTtcbiAgICAgICAgdGhpcy5zdG9yZU5hbWUgPSBSZXNvdXJjZVN0b3JlLlNUT1JFX05BTUU7XG4gICAgICAgIHRoaXMuZW50aXR5VHlwZSA9ICdSZXNvdXJjZSc7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgYWN0aXZlIHJlc291cmNlc1xuICAgICAqL1xuICAgIGFzeW5jIGdldEFjdGl2ZSgpIHtcbiAgICAgICAgY29uc3QgYWxsID0gYXdhaXQgdGhpcy5nZXRBbGwoKTtcbiAgICAgICAgcmV0dXJuIGFsbC5maWx0ZXIociA9PiByLmlzQWN0aXZlICE9PSBmYWxzZSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCByZXNvdXJjZXMgYnkgSURzXG4gICAgICovXG4gICAgYXN5bmMgZ2V0QnlJZHMoaWRzKSB7XG4gICAgICAgIGlmIChpZHMubGVuZ3RoID09PSAwKVxuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoaWRzLm1hcChpZCA9PiB0aGlzLmdldChpZCkpKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdHMuZmlsdGVyKChyKSA9PiByICE9PSBudWxsKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IHJlc291cmNlcyBieSB0eXBlXG4gICAgICovXG4gICAgYXN5bmMgZ2V0QnlUeXBlKHR5cGUpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gdGhpcy5kYi50cmFuc2FjdGlvbihbdGhpcy5zdG9yZU5hbWVdLCAncmVhZG9ubHknKTtcbiAgICAgICAgICAgIGNvbnN0IHN0b3JlID0gdHJhbnNhY3Rpb24ub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpO1xuICAgICAgICAgICAgY29uc3QgaW5kZXggPSBzdG9yZS5pbmRleCgndHlwZScpO1xuICAgICAgICAgICAgY29uc3QgcmVxdWVzdCA9IGluZGV4LmdldEFsbCh0eXBlKTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25zdWNjZXNzID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSByZXF1ZXN0LnJlc3VsdDtcbiAgICAgICAgICAgICAgICByZXNvbHZlKGRhdGEpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gZ2V0IHJlc291cmNlcyBieSB0eXBlICR7dHlwZX06ICR7cmVxdWVzdC5lcnJvcn1gKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICB9XG59XG4iLCAiLyoqXG4gKiBCb29raW5nU3RvcmUgLSBJbmRleGVkREIgT2JqZWN0U3RvcmUgZGVmaW5pdGlvbiBmb3IgYm9va2luZ3NcbiAqL1xuZXhwb3J0IGNsYXNzIEJvb2tpbmdTdG9yZSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuc3RvcmVOYW1lID0gQm9va2luZ1N0b3JlLlNUT1JFX05BTUU7XG4gICAgfVxuICAgIGNyZWF0ZShkYikge1xuICAgICAgICBjb25zdCBzdG9yZSA9IGRiLmNyZWF0ZU9iamVjdFN0b3JlKEJvb2tpbmdTdG9yZS5TVE9SRV9OQU1FLCB7IGtleVBhdGg6ICdpZCcgfSk7XG4gICAgICAgIHN0b3JlLmNyZWF0ZUluZGV4KCdjdXN0b21lcklkJywgJ2N1c3RvbWVySWQnLCB7IHVuaXF1ZTogZmFsc2UgfSk7XG4gICAgICAgIHN0b3JlLmNyZWF0ZUluZGV4KCdzdGF0dXMnLCAnc3RhdHVzJywgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgICAgICBzdG9yZS5jcmVhdGVJbmRleCgnc3luY1N0YXR1cycsICdzeW5jU3RhdHVzJywgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgICAgICBzdG9yZS5jcmVhdGVJbmRleCgnY3JlYXRlZEF0JywgJ2NyZWF0ZWRBdCcsIHsgdW5pcXVlOiBmYWxzZSB9KTtcbiAgICB9XG59XG5Cb29raW5nU3RvcmUuU1RPUkVfTkFNRSA9ICdib29raW5ncyc7XG4iLCAiaW1wb3J0IHsgQm9va2luZ1N0b3JlIH0gZnJvbSAnLi9Cb29raW5nU3RvcmUnO1xuaW1wb3J0IHsgQmFzZUVudGl0eVNlcnZpY2UgfSBmcm9tICcuLi9CYXNlRW50aXR5U2VydmljZSc7XG4vKipcbiAqIEJvb2tpbmdTZXJ2aWNlIC0gQ1JVRCBvcGVyYXRpb25zIGZvciBib29raW5ncyBpbiBJbmRleGVkREJcbiAqL1xuZXhwb3J0IGNsYXNzIEJvb2tpbmdTZXJ2aWNlIGV4dGVuZHMgQmFzZUVudGl0eVNlcnZpY2Uge1xuICAgIGNvbnN0cnVjdG9yKGNvbnRleHQsIGV2ZW50QnVzKSB7XG4gICAgICAgIHN1cGVyKGNvbnRleHQsIGV2ZW50QnVzKTtcbiAgICAgICAgdGhpcy5zdG9yZU5hbWUgPSBCb29raW5nU3RvcmUuU1RPUkVfTkFNRTtcbiAgICAgICAgdGhpcy5lbnRpdHlUeXBlID0gJ0Jvb2tpbmcnO1xuICAgIH1cbiAgICBzZXJpYWxpemUoYm9va2luZykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4uYm9va2luZyxcbiAgICAgICAgICAgIGNyZWF0ZWRBdDogYm9va2luZy5jcmVhdGVkQXQudG9JU09TdHJpbmcoKVxuICAgICAgICB9O1xuICAgIH1cbiAgICBkZXNlcmlhbGl6ZShkYXRhKSB7XG4gICAgICAgIGNvbnN0IHJhdyA9IGRhdGE7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi5yYXcsXG4gICAgICAgICAgICBjcmVhdGVkQXQ6IG5ldyBEYXRlKHJhdy5jcmVhdGVkQXQpXG4gICAgICAgIH07XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBib29raW5ncyBmb3IgYSBjdXN0b21lclxuICAgICAqL1xuICAgIGFzeW5jIGdldEJ5Q3VzdG9tZXIoY3VzdG9tZXJJZCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSB0aGlzLmRiLnRyYW5zYWN0aW9uKFt0aGlzLnN0b3JlTmFtZV0sICdyZWFkb25seScpO1xuICAgICAgICAgICAgY29uc3Qgc3RvcmUgPSB0cmFuc2FjdGlvbi5vYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7XG4gICAgICAgICAgICBjb25zdCBpbmRleCA9IHN0b3JlLmluZGV4KCdjdXN0b21lcklkJyk7XG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gaW5kZXguZ2V0QWxsKGN1c3RvbWVySWQpO1xuICAgICAgICAgICAgcmVxdWVzdC5vbnN1Y2Nlc3MgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IHJlcXVlc3QucmVzdWx0O1xuICAgICAgICAgICAgICAgIGNvbnN0IGJvb2tpbmdzID0gZGF0YS5tYXAoaXRlbSA9PiB0aGlzLmRlc2VyaWFsaXplKGl0ZW0pKTtcbiAgICAgICAgICAgICAgICByZXNvbHZlKGJvb2tpbmdzKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXF1ZXN0Lm9uZXJyb3IgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgRmFpbGVkIHRvIGdldCBib29raW5ncyBmb3IgY3VzdG9tZXIgJHtjdXN0b21lcklkfTogJHtyZXF1ZXN0LmVycm9yfWApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgYm9va2luZ3MgYnkgc3RhdHVzXG4gICAgICovXG4gICAgYXN5bmMgZ2V0QnlTdGF0dXMoc3RhdHVzKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IHRoaXMuZGIudHJhbnNhY3Rpb24oW3RoaXMuc3RvcmVOYW1lXSwgJ3JlYWRvbmx5Jyk7XG4gICAgICAgICAgICBjb25zdCBzdG9yZSA9IHRyYW5zYWN0aW9uLm9iamVjdFN0b3JlKHRoaXMuc3RvcmVOYW1lKTtcbiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gc3RvcmUuaW5kZXgoJ3N0YXR1cycpO1xuICAgICAgICAgICAgY29uc3QgcmVxdWVzdCA9IGluZGV4LmdldEFsbChzdGF0dXMpO1xuICAgICAgICAgICAgcmVxdWVzdC5vbnN1Y2Nlc3MgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IHJlcXVlc3QucmVzdWx0O1xuICAgICAgICAgICAgICAgIGNvbnN0IGJvb2tpbmdzID0gZGF0YS5tYXAoaXRlbSA9PiB0aGlzLmRlc2VyaWFsaXplKGl0ZW0pKTtcbiAgICAgICAgICAgICAgICByZXNvbHZlKGJvb2tpbmdzKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXF1ZXN0Lm9uZXJyb3IgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgRmFpbGVkIHRvIGdldCBib29raW5ncyB3aXRoIHN0YXR1cyAke3N0YXR1c306ICR7cmVxdWVzdC5lcnJvcn1gKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICB9XG59XG4iLCAiLyoqXG4gKiBDdXN0b21lclN0b3JlIC0gSW5kZXhlZERCIE9iamVjdFN0b3JlIGRlZmluaXRpb24gZm9yIGN1c3RvbWVyc1xuICovXG5leHBvcnQgY2xhc3MgQ3VzdG9tZXJTdG9yZSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuc3RvcmVOYW1lID0gQ3VzdG9tZXJTdG9yZS5TVE9SRV9OQU1FO1xuICAgIH1cbiAgICBjcmVhdGUoZGIpIHtcbiAgICAgICAgY29uc3Qgc3RvcmUgPSBkYi5jcmVhdGVPYmplY3RTdG9yZShDdXN0b21lclN0b3JlLlNUT1JFX05BTUUsIHsga2V5UGF0aDogJ2lkJyB9KTtcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ25hbWUnLCAnbmFtZScsIHsgdW5pcXVlOiBmYWxzZSB9KTtcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ3Bob25lJywgJ3Bob25lJywgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgICAgICBzdG9yZS5jcmVhdGVJbmRleCgnc3luY1N0YXR1cycsICdzeW5jU3RhdHVzJywgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgIH1cbn1cbkN1c3RvbWVyU3RvcmUuU1RPUkVfTkFNRSA9ICdjdXN0b21lcnMnO1xuIiwgImltcG9ydCB7IEN1c3RvbWVyU3RvcmUgfSBmcm9tICcuL0N1c3RvbWVyU3RvcmUnO1xuaW1wb3J0IHsgQmFzZUVudGl0eVNlcnZpY2UgfSBmcm9tICcuLi9CYXNlRW50aXR5U2VydmljZSc7XG4vKipcbiAqIEN1c3RvbWVyU2VydmljZSAtIENSVUQgb3BlcmF0aW9ucyBmb3IgY3VzdG9tZXJzIGluIEluZGV4ZWREQlxuICovXG5leHBvcnQgY2xhc3MgQ3VzdG9tZXJTZXJ2aWNlIGV4dGVuZHMgQmFzZUVudGl0eVNlcnZpY2Uge1xuICAgIGNvbnN0cnVjdG9yKGNvbnRleHQsIGV2ZW50QnVzKSB7XG4gICAgICAgIHN1cGVyKGNvbnRleHQsIGV2ZW50QnVzKTtcbiAgICAgICAgdGhpcy5zdG9yZU5hbWUgPSBDdXN0b21lclN0b3JlLlNUT1JFX05BTUU7XG4gICAgICAgIHRoaXMuZW50aXR5VHlwZSA9ICdDdXN0b21lcic7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNlYXJjaCBjdXN0b21lcnMgYnkgbmFtZSAoY2FzZS1pbnNlbnNpdGl2ZSBjb250YWlucylcbiAgICAgKi9cbiAgICBhc3luYyBzZWFyY2hCeU5hbWUocXVlcnkpIHtcbiAgICAgICAgY29uc3QgYWxsID0gYXdhaXQgdGhpcy5nZXRBbGwoKTtcbiAgICAgICAgY29uc3QgbG93ZXJRdWVyeSA9IHF1ZXJ5LnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIHJldHVybiBhbGwuZmlsdGVyKGMgPT4gYy5uYW1lLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMobG93ZXJRdWVyeSkpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBGaW5kIGN1c3RvbWVyIGJ5IHBob25lXG4gICAgICovXG4gICAgYXN5bmMgZ2V0QnlQaG9uZShwaG9uZSkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSB0aGlzLmRiLnRyYW5zYWN0aW9uKFt0aGlzLnN0b3JlTmFtZV0sICdyZWFkb25seScpO1xuICAgICAgICAgICAgY29uc3Qgc3RvcmUgPSB0cmFuc2FjdGlvbi5vYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7XG4gICAgICAgICAgICBjb25zdCBpbmRleCA9IHN0b3JlLmluZGV4KCdwaG9uZScpO1xuICAgICAgICAgICAgY29uc3QgcmVxdWVzdCA9IGluZGV4LmdldChwaG9uZSk7XG4gICAgICAgICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gcmVxdWVzdC5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShkYXRhID8gZGF0YSA6IG51bGwpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gZmluZCBjdXN0b21lciBieSBwaG9uZSAke3Bob25lfTogJHtyZXF1ZXN0LmVycm9yfWApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIFRlYW1TdG9yZSAtIEluZGV4ZWREQiBPYmplY3RTdG9yZSBkZWZpbml0aW9uIGZvciB0ZWFtc1xuICovXG5leHBvcnQgY2xhc3MgVGVhbVN0b3JlIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5zdG9yZU5hbWUgPSBUZWFtU3RvcmUuU1RPUkVfTkFNRTtcbiAgICB9XG4gICAgY3JlYXRlKGRiKSB7XG4gICAgICAgIGRiLmNyZWF0ZU9iamVjdFN0b3JlKFRlYW1TdG9yZS5TVE9SRV9OQU1FLCB7IGtleVBhdGg6ICdpZCcgfSk7XG4gICAgfVxufVxuVGVhbVN0b3JlLlNUT1JFX05BTUUgPSAndGVhbXMnO1xuIiwgImltcG9ydCB7IFRlYW1TdG9yZSB9IGZyb20gJy4vVGVhbVN0b3JlJztcbmltcG9ydCB7IEJhc2VFbnRpdHlTZXJ2aWNlIH0gZnJvbSAnLi4vQmFzZUVudGl0eVNlcnZpY2UnO1xuLyoqXG4gKiBUZWFtU2VydmljZSAtIENSVUQgb3BlcmF0aW9ucyBmb3IgdGVhbXMgaW4gSW5kZXhlZERCXG4gKlxuICogVGVhbXMgZGVmaW5lIHdoaWNoIHJlc291cmNlcyBiZWxvbmcgdG9nZXRoZXIgZm9yIGhpZXJhcmNoaWNhbCBncm91cGluZy5cbiAqIEV4dGVuZHMgQmFzZUVudGl0eVNlcnZpY2UgZm9yIHN0YW5kYXJkIGVudGl0eSBvcGVyYXRpb25zLlxuICovXG5leHBvcnQgY2xhc3MgVGVhbVNlcnZpY2UgZXh0ZW5kcyBCYXNlRW50aXR5U2VydmljZSB7XG4gICAgY29uc3RydWN0b3IoY29udGV4dCwgZXZlbnRCdXMpIHtcbiAgICAgICAgc3VwZXIoY29udGV4dCwgZXZlbnRCdXMpO1xuICAgICAgICB0aGlzLnN0b3JlTmFtZSA9IFRlYW1TdG9yZS5TVE9SRV9OQU1FO1xuICAgICAgICB0aGlzLmVudGl0eVR5cGUgPSAnVGVhbSc7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCB0ZWFtcyBieSBJRHNcbiAgICAgKi9cbiAgICBhc3luYyBnZXRCeUlkcyhpZHMpIHtcbiAgICAgICAgaWYgKGlkcy5sZW5ndGggPT09IDApXG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChpZHMubWFwKGlkID0+IHRoaXMuZ2V0KGlkKSkpO1xuICAgICAgICByZXR1cm4gcmVzdWx0cy5maWx0ZXIoKHQpID0+IHQgIT09IG51bGwpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBCdWlsZCByZXZlcnNlIGxvb2t1cDogcmVzb3VyY2VJZCBcdTIxOTIgdGVhbUlkXG4gICAgICovXG4gICAgYXN5bmMgYnVpbGRSZXNvdXJjZVRvVGVhbU1hcCgpIHtcbiAgICAgICAgY29uc3QgdGVhbXMgPSBhd2FpdCB0aGlzLmdldEFsbCgpO1xuICAgICAgICBjb25zdCBtYXAgPSB7fTtcbiAgICAgICAgZm9yIChjb25zdCB0ZWFtIG9mIHRlYW1zKSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHJlc291cmNlSWQgb2YgdGVhbS5yZXNvdXJjZUlkcykge1xuICAgICAgICAgICAgICAgIG1hcFtyZXNvdXJjZUlkXSA9IHRlYW0uaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1hcDtcbiAgICB9XG59XG4iLCAiLyoqXG4gKiBEZXBhcnRtZW50U3RvcmUgLSBJbmRleGVkREIgT2JqZWN0U3RvcmUgZGVmaW5pdGlvbiBmb3IgZGVwYXJ0bWVudHNcbiAqL1xuZXhwb3J0IGNsYXNzIERlcGFydG1lbnRTdG9yZSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuc3RvcmVOYW1lID0gRGVwYXJ0bWVudFN0b3JlLlNUT1JFX05BTUU7XG4gICAgfVxuICAgIGNyZWF0ZShkYikge1xuICAgICAgICBkYi5jcmVhdGVPYmplY3RTdG9yZShEZXBhcnRtZW50U3RvcmUuU1RPUkVfTkFNRSwgeyBrZXlQYXRoOiAnaWQnIH0pO1xuICAgIH1cbn1cbkRlcGFydG1lbnRTdG9yZS5TVE9SRV9OQU1FID0gJ2RlcGFydG1lbnRzJztcbiIsICJpbXBvcnQgeyBEZXBhcnRtZW50U3RvcmUgfSBmcm9tICcuL0RlcGFydG1lbnRTdG9yZSc7XG5pbXBvcnQgeyBCYXNlRW50aXR5U2VydmljZSB9IGZyb20gJy4uL0Jhc2VFbnRpdHlTZXJ2aWNlJztcbi8qKlxuICogRGVwYXJ0bWVudFNlcnZpY2UgLSBDUlVEIG9wZXJhdGlvbnMgZm9yIGRlcGFydG1lbnRzIGluIEluZGV4ZWREQlxuICovXG5leHBvcnQgY2xhc3MgRGVwYXJ0bWVudFNlcnZpY2UgZXh0ZW5kcyBCYXNlRW50aXR5U2VydmljZSB7XG4gICAgY29uc3RydWN0b3IoY29udGV4dCwgZXZlbnRCdXMpIHtcbiAgICAgICAgc3VwZXIoY29udGV4dCwgZXZlbnRCdXMpO1xuICAgICAgICB0aGlzLnN0b3JlTmFtZSA9IERlcGFydG1lbnRTdG9yZS5TVE9SRV9OQU1FO1xuICAgICAgICB0aGlzLmVudGl0eVR5cGUgPSAnRGVwYXJ0bWVudCc7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBkZXBhcnRtZW50cyBieSBJRHNcbiAgICAgKi9cbiAgICBhc3luYyBnZXRCeUlkcyhpZHMpIHtcbiAgICAgICAgaWYgKGlkcy5sZW5ndGggPT09IDApXG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChpZHMubWFwKGlkID0+IHRoaXMuZ2V0KGlkKSkpO1xuICAgICAgICByZXR1cm4gcmVzdWx0cy5maWx0ZXIoKGQpID0+IGQgIT09IG51bGwpO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIFNldHRpbmdzU3RvcmUgLSBJbmRleGVkREIgT2JqZWN0U3RvcmUgZGVmaW5pdGlvbiBmb3IgdGVuYW50IHNldHRpbmdzXG4gKlxuICogU2luZ2xlIHN0b3JlIGZvciBhbGwgc2V0dGluZ3Mgc2VjdGlvbnMuIFNldHRpbmdzIGFyZSBzdG9yZWQgYXMgb25lIGRvY3VtZW50XG4gKiBwZXIgdGVuYW50IHdpdGggaWQ9J3RlbmFudC1zZXR0aW5ncycuXG4gKi9cbmV4cG9ydCBjbGFzcyBTZXR0aW5nc1N0b3JlIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5zdG9yZU5hbWUgPSBTZXR0aW5nc1N0b3JlLlNUT1JFX05BTUU7XG4gICAgfVxuICAgIGNyZWF0ZShkYikge1xuICAgICAgICBkYi5jcmVhdGVPYmplY3RTdG9yZShTZXR0aW5nc1N0b3JlLlNUT1JFX05BTUUsIHsga2V5UGF0aDogJ2lkJyB9KTtcbiAgICB9XG59XG5TZXR0aW5nc1N0b3JlLlNUT1JFX05BTUUgPSAnc2V0dGluZ3MnO1xuIiwgIi8qKlxuICogU2V0dGluZ3MgSURzIGFzIGNvbnN0IGZvciB0eXBlIHNhZmV0eVxuICovXG5leHBvcnQgY29uc3QgU2V0dGluZ3NJZHMgPSB7XG4gICAgV09SS1dFRUs6ICd3b3Jrd2VlaycsXG4gICAgR1JJRDogJ2dyaWQnLFxuICAgIFRJTUVfRk9STUFUOiAndGltZUZvcm1hdCcsXG4gICAgVklFV1M6ICd2aWV3cydcbn07XG4iLCAiaW1wb3J0IHsgU2V0dGluZ3NJZHMgfSBmcm9tICcuLi8uLi90eXBlcy9TZXR0aW5nc1R5cGVzJztcbmltcG9ydCB7IFNldHRpbmdzU3RvcmUgfSBmcm9tICcuL1NldHRpbmdzU3RvcmUnO1xuaW1wb3J0IHsgQmFzZUVudGl0eVNlcnZpY2UgfSBmcm9tICcuLi9CYXNlRW50aXR5U2VydmljZSc7XG4vKipcbiAqIFNldHRpbmdzU2VydmljZSAtIENSVUQgb3BlcmF0aW9ucyBmb3IgdGVuYW50IHNldHRpbmdzXG4gKlxuICogU2V0dGluZ3MgYXJlIHN0b3JlZCBhcyBzZXBhcmF0ZSByZWNvcmRzIHBlciBzZWN0aW9uLlxuICogVGhpcyBzZXJ2aWNlIHByb3ZpZGVzIHR5cGVkIG1ldGhvZHMgZm9yIGFjY2Vzc2luZyBzcGVjaWZpYyBzZXR0aW5ncy5cbiAqL1xuZXhwb3J0IGNsYXNzIFNldHRpbmdzU2VydmljZSBleHRlbmRzIEJhc2VFbnRpdHlTZXJ2aWNlIHtcbiAgICBjb25zdHJ1Y3Rvcihjb250ZXh0LCBldmVudEJ1cykge1xuICAgICAgICBzdXBlcihjb250ZXh0LCBldmVudEJ1cyk7XG4gICAgICAgIHRoaXMuc3RvcmVOYW1lID0gU2V0dGluZ3NTdG9yZS5TVE9SRV9OQU1FO1xuICAgICAgICB0aGlzLmVudGl0eVR5cGUgPSAnU2V0dGluZ3MnO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgd29ya3dlZWsgc2V0dGluZ3NcbiAgICAgKi9cbiAgICBhc3luYyBnZXRXb3Jrd2Vla1NldHRpbmdzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXQoU2V0dGluZ3NJZHMuV09SS1dFRUspO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgZ3JpZCBzZXR0aW5nc1xuICAgICAqL1xuICAgIGFzeW5jIGdldEdyaWRTZXR0aW5ncygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0KFNldHRpbmdzSWRzLkdSSUQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgdGltZSBmb3JtYXQgc2V0dGluZ3NcbiAgICAgKi9cbiAgICBhc3luYyBnZXRUaW1lRm9ybWF0U2V0dGluZ3MoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldChTZXR0aW5nc0lkcy5USU1FX0ZPUk1BVCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCB2aWV3IHNldHRpbmdzXG4gICAgICovXG4gICAgYXN5bmMgZ2V0Vmlld1NldHRpbmdzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXQoU2V0dGluZ3NJZHMuVklFV1MpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgd29ya3dlZWsgcHJlc2V0IGJ5IElEXG4gICAgICovXG4gICAgYXN5bmMgZ2V0V29ya3dlZWtQcmVzZXQocHJlc2V0SWQpIHtcbiAgICAgICAgY29uc3Qgc2V0dGluZ3MgPSBhd2FpdCB0aGlzLmdldFdvcmt3ZWVrU2V0dGluZ3MoKTtcbiAgICAgICAgaWYgKCFzZXR0aW5ncylcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICByZXR1cm4gc2V0dGluZ3MucHJlc2V0c1twcmVzZXRJZF0gfHwgbnVsbDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBkZWZhdWx0IHdvcmt3ZWVrIHByZXNldFxuICAgICAqL1xuICAgIGFzeW5jIGdldERlZmF1bHRXb3Jrd2Vla1ByZXNldCgpIHtcbiAgICAgICAgY29uc3Qgc2V0dGluZ3MgPSBhd2FpdCB0aGlzLmdldFdvcmt3ZWVrU2V0dGluZ3MoKTtcbiAgICAgICAgaWYgKCFzZXR0aW5ncylcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICByZXR1cm4gc2V0dGluZ3MucHJlc2V0c1tzZXR0aW5ncy5kZWZhdWx0UHJlc2V0XSB8fCBudWxsO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIGF2YWlsYWJsZSB3b3Jrd2VlayBwcmVzZXRzXG4gICAgICovXG4gICAgYXN5bmMgZ2V0V29ya3dlZWtQcmVzZXRzKCkge1xuICAgICAgICBjb25zdCBzZXR0aW5ncyA9IGF3YWl0IHRoaXMuZ2V0V29ya3dlZWtTZXR0aW5ncygpO1xuICAgICAgICBpZiAoIXNldHRpbmdzKVxuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyhzZXR0aW5ncy5wcmVzZXRzKTtcbiAgICB9XG59XG4iLCAiZXhwb3J0IGNsYXNzIFZpZXdDb25maWdTdG9yZSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuc3RvcmVOYW1lID0gVmlld0NvbmZpZ1N0b3JlLlNUT1JFX05BTUU7XG4gICAgfVxuICAgIGNyZWF0ZShkYikge1xuICAgICAgICBkYi5jcmVhdGVPYmplY3RTdG9yZShWaWV3Q29uZmlnU3RvcmUuU1RPUkVfTkFNRSwgeyBrZXlQYXRoOiAnaWQnIH0pO1xuICAgIH1cbn1cblZpZXdDb25maWdTdG9yZS5TVE9SRV9OQU1FID0gJ3ZpZXdjb25maWdzJztcbiIsICJpbXBvcnQgeyBWaWV3Q29uZmlnU3RvcmUgfSBmcm9tICcuL1ZpZXdDb25maWdTdG9yZSc7XG5pbXBvcnQgeyBCYXNlRW50aXR5U2VydmljZSB9IGZyb20gJy4uL0Jhc2VFbnRpdHlTZXJ2aWNlJztcbmV4cG9ydCBjbGFzcyBWaWV3Q29uZmlnU2VydmljZSBleHRlbmRzIEJhc2VFbnRpdHlTZXJ2aWNlIHtcbiAgICBjb25zdHJ1Y3Rvcihjb250ZXh0LCBldmVudEJ1cykge1xuICAgICAgICBzdXBlcihjb250ZXh0LCBldmVudEJ1cyk7XG4gICAgICAgIHRoaXMuc3RvcmVOYW1lID0gVmlld0NvbmZpZ1N0b3JlLlNUT1JFX05BTUU7XG4gICAgICAgIHRoaXMuZW50aXR5VHlwZSA9ICdWaWV3Q29uZmlnJztcbiAgICB9XG4gICAgYXN5bmMgZ2V0QnlJZChpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXQoaWQpO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIEF1ZGl0U3RvcmUgLSBJbmRleGVkREIgc3RvcmUgY29uZmlndXJhdGlvbiBmb3IgYXVkaXQgZW50cmllc1xuICpcbiAqIFN0b3JlcyBhbGwgZW50aXR5IGNoYW5nZXMgZm9yOlxuICogLSBDb21wbGlhbmNlIGFuZCBhdWRpdCB0cmFpbFxuICogLSBTeW5jIHRyYWNraW5nIHdpdGggYmFja2VuZFxuICogLSBDaGFuZ2UgaGlzdG9yeVxuICpcbiAqIEluZGV4ZXM6XG4gKiAtIHN5bmNTdGF0dXM6IEZvciBmaW5kaW5nIHBlbmRpbmcgZW50cmllcyB0byBzeW5jXG4gKiAtIHN5bmNlZDogQm9vbGVhbiBmbGFnIGZvciBxdWljayBzeW5jIHF1ZXJpZXNcbiAqIC0gZW50aXR5SWQ6IEZvciBnZXR0aW5nIGFsbCBhdWRpdHMgZm9yIGEgc3BlY2lmaWMgZW50aXR5XG4gKiAtIHRpbWVzdGFtcDogRm9yIGNocm9ub2xvZ2ljYWwgcXVlcmllc1xuICovXG5leHBvcnQgY2xhc3MgQXVkaXRTdG9yZSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuc3RvcmVOYW1lID0gJ2F1ZGl0JztcbiAgICB9XG4gICAgY3JlYXRlKGRiKSB7XG4gICAgICAgIGNvbnN0IHN0b3JlID0gZGIuY3JlYXRlT2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUsIHsga2V5UGF0aDogJ2lkJyB9KTtcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ3N5bmNTdGF0dXMnLCAnc3luY1N0YXR1cycsIHsgdW5pcXVlOiBmYWxzZSB9KTtcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ3N5bmNlZCcsICdzeW5jZWQnLCB7IHVuaXF1ZTogZmFsc2UgfSk7XG4gICAgICAgIHN0b3JlLmNyZWF0ZUluZGV4KCdlbnRpdHlJZCcsICdlbnRpdHlJZCcsIHsgdW5pcXVlOiBmYWxzZSB9KTtcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ3RpbWVzdGFtcCcsICd0aW1lc3RhbXAnLCB7IHVuaXF1ZTogZmFsc2UgfSk7XG4gICAgfVxufVxuIiwgImltcG9ydCB7IEJhc2VFbnRpdHlTZXJ2aWNlIH0gZnJvbSAnLi4vQmFzZUVudGl0eVNlcnZpY2UnO1xuaW1wb3J0IHsgQ29yZUV2ZW50cyB9IGZyb20gJy4uLy4uL2NvbnN0YW50cy9Db3JlRXZlbnRzJztcbi8qKlxuICogQXVkaXRTZXJ2aWNlIC0gRW50aXR5IHNlcnZpY2UgZm9yIGF1ZGl0IGVudHJpZXNcbiAqXG4gKiBSRVNQT05TSUJJTElUSUVTOlxuICogLSBTdG9yZSBhdWRpdCBlbnRyaWVzIGluIEluZGV4ZWREQlxuICogLSBMaXN0ZW4gZm9yIEVOVElUWV9TQVZFRC9FTlRJVFlfREVMRVRFRCBldmVudHNcbiAqIC0gQ3JlYXRlIGF1ZGl0IGVudHJpZXMgZm9yIGFsbCBlbnRpdHkgY2hhbmdlc1xuICogLSBFbWl0IEFVRElUX0xPR0dFRCBhZnRlciBzYXZpbmcgKGZvciBTeW5jTWFuYWdlciB0byBsaXN0ZW4pXG4gKlxuICogT1ZFUlJJREUgUEFUVEVSTjpcbiAqIC0gT3ZlcnJpZGVzIHNhdmUoKSB0byBOT1QgZW1pdCBldmVudHMgKHByZXZlbnRzIGluZmluaXRlIGxvb3BzKVxuICogLSBBdWRpdFNlcnZpY2Ugc2F2ZXMgYXVkaXQgZW50cmllcyB3aXRob3V0IHRyaWdnZXJpbmcgbW9yZSBhdWRpdHNcbiAqXG4gKiBFVkVOVCBDSEFJTjpcbiAqIEVudGl0eSBjaGFuZ2UgXHUyMTkyIEVOVElUWV9TQVZFRC9ERUxFVEVEIFx1MjE5MiBBdWRpdFNlcnZpY2UgXHUyMTkyIEFVRElUX0xPR0dFRCBcdTIxOTIgU3luY01hbmFnZXJcbiAqL1xuZXhwb3J0IGNsYXNzIEF1ZGl0U2VydmljZSBleHRlbmRzIEJhc2VFbnRpdHlTZXJ2aWNlIHtcbiAgICBjb25zdHJ1Y3Rvcihjb250ZXh0LCBldmVudEJ1cykge1xuICAgICAgICBzdXBlcihjb250ZXh0LCBldmVudEJ1cyk7XG4gICAgICAgIHRoaXMuc3RvcmVOYW1lID0gJ2F1ZGl0JztcbiAgICAgICAgdGhpcy5lbnRpdHlUeXBlID0gJ0F1ZGl0JztcbiAgICAgICAgdGhpcy5zZXR1cEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNldHVwIGxpc3RlbmVycyBmb3IgRU5USVRZX1NBVkVEIGFuZCBFTlRJVFlfREVMRVRFRCBldmVudHNcbiAgICAgKi9cbiAgICBzZXR1cEV2ZW50TGlzdGVuZXJzKCkge1xuICAgICAgICAvLyBMaXN0ZW4gZm9yIGVudGl0eSBzYXZlcyAoY3JlYXRlL3VwZGF0ZSlcbiAgICAgICAgdGhpcy5ldmVudEJ1cy5vbihDb3JlRXZlbnRzLkVOVElUWV9TQVZFRCwgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBkZXRhaWwgPSBldmVudC5kZXRhaWw7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZUVudGl0eVNhdmVkKGRldGFpbCk7XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBMaXN0ZW4gZm9yIGVudGl0eSBkZWxldGVzXG4gICAgICAgIHRoaXMuZXZlbnRCdXMub24oQ29yZUV2ZW50cy5FTlRJVFlfREVMRVRFRCwgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBkZXRhaWwgPSBldmVudC5kZXRhaWw7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZUVudGl0eURlbGV0ZWQoZGV0YWlsKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEhhbmRsZSBFTlRJVFlfU0FWRUQgZXZlbnQgLSBjcmVhdGUgYXVkaXQgZW50cnlcbiAgICAgKi9cbiAgICBhc3luYyBoYW5kbGVFbnRpdHlTYXZlZChwYXlsb2FkKSB7XG4gICAgICAgIC8vIERvbid0IGF1ZGl0IGF1ZGl0IGVudHJpZXMgKHByZXZlbnQgaW5maW5pdGUgbG9vcHMpXG4gICAgICAgIGlmIChwYXlsb2FkLmVudGl0eVR5cGUgPT09ICdBdWRpdCcpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNvbnN0IGF1ZGl0RW50cnkgPSB7XG4gICAgICAgICAgICBpZDogY3J5cHRvLnJhbmRvbVVVSUQoKSxcbiAgICAgICAgICAgIGVudGl0eVR5cGU6IHBheWxvYWQuZW50aXR5VHlwZSxcbiAgICAgICAgICAgIGVudGl0eUlkOiBwYXlsb2FkLmVudGl0eUlkLFxuICAgICAgICAgICAgb3BlcmF0aW9uOiBwYXlsb2FkLm9wZXJhdGlvbixcbiAgICAgICAgICAgIHVzZXJJZDogQXVkaXRTZXJ2aWNlLkRFRkFVTFRfVVNFUl9JRCxcbiAgICAgICAgICAgIHRpbWVzdGFtcDogcGF5bG9hZC50aW1lc3RhbXAsXG4gICAgICAgICAgICBjaGFuZ2VzOiBwYXlsb2FkLmNoYW5nZXMsXG4gICAgICAgICAgICBzeW5jZWQ6IGZhbHNlLFxuICAgICAgICAgICAgc3luY1N0YXR1czogJ3BlbmRpbmcnXG4gICAgICAgIH07XG4gICAgICAgIGF3YWl0IHRoaXMuc2F2ZShhdWRpdEVudHJ5KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSGFuZGxlIEVOVElUWV9ERUxFVEVEIGV2ZW50IC0gY3JlYXRlIGF1ZGl0IGVudHJ5XG4gICAgICovXG4gICAgYXN5bmMgaGFuZGxlRW50aXR5RGVsZXRlZChwYXlsb2FkKSB7XG4gICAgICAgIC8vIERvbid0IGF1ZGl0IGF1ZGl0IGVudHJpZXMgKHByZXZlbnQgaW5maW5pdGUgbG9vcHMpXG4gICAgICAgIGlmIChwYXlsb2FkLmVudGl0eVR5cGUgPT09ICdBdWRpdCcpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNvbnN0IGF1ZGl0RW50cnkgPSB7XG4gICAgICAgICAgICBpZDogY3J5cHRvLnJhbmRvbVVVSUQoKSxcbiAgICAgICAgICAgIGVudGl0eVR5cGU6IHBheWxvYWQuZW50aXR5VHlwZSxcbiAgICAgICAgICAgIGVudGl0eUlkOiBwYXlsb2FkLmVudGl0eUlkLFxuICAgICAgICAgICAgb3BlcmF0aW9uOiAnZGVsZXRlJyxcbiAgICAgICAgICAgIHVzZXJJZDogQXVkaXRTZXJ2aWNlLkRFRkFVTFRfVVNFUl9JRCxcbiAgICAgICAgICAgIHRpbWVzdGFtcDogcGF5bG9hZC50aW1lc3RhbXAsXG4gICAgICAgICAgICBjaGFuZ2VzOiB7IGlkOiBwYXlsb2FkLmVudGl0eUlkIH0sIC8vIEZvciBkZWxldGUsIGp1c3Qgc3RvcmUgdGhlIElEXG4gICAgICAgICAgICBzeW5jZWQ6IGZhbHNlLFxuICAgICAgICAgICAgc3luY1N0YXR1czogJ3BlbmRpbmcnXG4gICAgICAgIH07XG4gICAgICAgIGF3YWl0IHRoaXMuc2F2ZShhdWRpdEVudHJ5KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogT3ZlcnJpZGUgc2F2ZSB0byBOT1QgdHJpZ2dlciBFTlRJVFlfU0FWRUQgZXZlbnRcbiAgICAgKiBJbnN0ZWFkLCBlbWl0cyBBVURJVF9MT0dHRUQgZm9yIFN5bmNNYW5hZ2VyIHRvIGxpc3RlblxuICAgICAqXG4gICAgICogVGhpcyBwcmV2ZW50cyBpbmZpbml0ZSBsb29wczpcbiAgICAgKiAtIEJhc2VFbnRpdHlTZXJ2aWNlLnNhdmUoKSBlbWl0cyBFTlRJVFlfU0FWRURcbiAgICAgKiAtIEF1ZGl0U2VydmljZSBsaXN0ZW5zIHRvIEVOVElUWV9TQVZFRCBhbmQgY3JlYXRlcyBhdWRpdFxuICAgICAqIC0gSWYgQXVkaXRTZXJ2aWNlLnNhdmUoKSBhbHNvIGVtaXR0ZWQgRU5USVRZX1NBVkVELCBpdCB3b3VsZCBsb29wXG4gICAgICovXG4gICAgYXN5bmMgc2F2ZShlbnRpdHkpIHtcbiAgICAgICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplKGVudGl0eSk7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IHRoaXMuZGIudHJhbnNhY3Rpb24oW3RoaXMuc3RvcmVOYW1lXSwgJ3JlYWR3cml0ZScpO1xuICAgICAgICAgICAgY29uc3Qgc3RvcmUgPSB0cmFuc2FjdGlvbi5vYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7XG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gc3RvcmUucHV0KHNlcmlhbGl6ZWQpO1xuICAgICAgICAgICAgcmVxdWVzdC5vbnN1Y2Nlc3MgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gRW1pdCBBVURJVF9MT0dHRUQgaW5zdGVhZCBvZiBFTlRJVFlfU0FWRURcbiAgICAgICAgICAgICAgICBjb25zdCBwYXlsb2FkID0ge1xuICAgICAgICAgICAgICAgICAgICBhdWRpdElkOiBlbnRpdHkuaWQsXG4gICAgICAgICAgICAgICAgICAgIGVudGl0eVR5cGU6IGVudGl0eS5lbnRpdHlUeXBlLFxuICAgICAgICAgICAgICAgICAgICBlbnRpdHlJZDogZW50aXR5LmVudGl0eUlkLFxuICAgICAgICAgICAgICAgICAgICBvcGVyYXRpb246IGVudGl0eS5vcGVyYXRpb24sXG4gICAgICAgICAgICAgICAgICAgIHRpbWVzdGFtcDogZW50aXR5LnRpbWVzdGFtcFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENvcmVFdmVudHMuQVVESVRfTE9HR0VELCBwYXlsb2FkKTtcbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVxdWVzdC5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBzYXZlIGF1ZGl0IGVudHJ5ICR7ZW50aXR5LmlkfTogJHtyZXF1ZXN0LmVycm9yfWApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBPdmVycmlkZSBkZWxldGUgdG8gTk9UIHRyaWdnZXIgRU5USVRZX0RFTEVURUQgZXZlbnRcbiAgICAgKiBBdWRpdCBlbnRyaWVzIHNob3VsZCBuZXZlciBiZSBkZWxldGVkIChjb21wbGlhbmNlIHJlcXVpcmVtZW50KVxuICAgICAqL1xuICAgIGFzeW5jIGRlbGV0ZShfaWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdBdWRpdCBlbnRyaWVzIGNhbm5vdCBiZSBkZWxldGVkIChjb21wbGlhbmNlIHJlcXVpcmVtZW50KScpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgcGVuZGluZyBhdWRpdCBlbnRyaWVzIChmb3Igc3luYylcbiAgICAgKi9cbiAgICBhc3luYyBnZXRQZW5kaW5nQXVkaXRzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRCeVN5bmNTdGF0dXMoJ3BlbmRpbmcnKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGF1ZGl0IGVudHJpZXMgZm9yIGEgc3BlY2lmaWMgZW50aXR5XG4gICAgICovXG4gICAgYXN5bmMgZ2V0QnlFbnRpdHlJZChlbnRpdHlJZCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSB0aGlzLmRiLnRyYW5zYWN0aW9uKFt0aGlzLnN0b3JlTmFtZV0sICdyZWFkb25seScpO1xuICAgICAgICAgICAgY29uc3Qgc3RvcmUgPSB0cmFuc2FjdGlvbi5vYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7XG4gICAgICAgICAgICBjb25zdCBpbmRleCA9IHN0b3JlLmluZGV4KCdlbnRpdHlJZCcpO1xuICAgICAgICAgICAgY29uc3QgcmVxdWVzdCA9IGluZGV4LmdldEFsbChlbnRpdHlJZCk7XG4gICAgICAgICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBlbnRyaWVzID0gcmVxdWVzdC5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShlbnRyaWVzKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXF1ZXN0Lm9uZXJyb3IgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgRmFpbGVkIHRvIGdldCBhdWRpdCBlbnRyaWVzIGZvciBlbnRpdHkgJHtlbnRpdHlJZH06ICR7cmVxdWVzdC5lcnJvcn1gKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICB9XG59XG4vLyBIYXJkY29kZWQgdXNlcklkIGZvciBub3cgLSB3aWxsIGNvbWUgZnJvbSBzZXNzaW9uIGxhdGVyXG5BdWRpdFNlcnZpY2UuREVGQVVMVF9VU0VSX0lEID0gJzAwMDAwMDAwLTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMSc7XG4iLCAiLyoqXG4gKiBNb2NrRXZlbnRSZXBvc2l0b3J5IC0gTG9hZHMgZXZlbnQgZGF0YSBmcm9tIGxvY2FsIEpTT04gZmlsZVxuICpcbiAqIFVzZWQgZm9yIGRldmVsb3BtZW50IGFuZCB0ZXN0aW5nLiBPbmx5IGZldGNoQWxsKCkgaXMgaW1wbGVtZW50ZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBNb2NrRXZlbnRSZXBvc2l0b3J5IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5lbnRpdHlUeXBlID0gJ0V2ZW50JztcbiAgICAgICAgdGhpcy5kYXRhVXJsID0gJ2RhdGEvbW9jay1ldmVudHMuanNvbic7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEZldGNoIGFsbCBldmVudHMgZnJvbSBtb2NrIEpTT04gZmlsZVxuICAgICAqL1xuICAgIGFzeW5jIGZldGNoQWxsKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh0aGlzLmRhdGFVcmwpO1xuICAgICAgICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGxvYWQgbW9jayBldmVudHM6ICR7cmVzcG9uc2Uuc3RhdHVzfSAke3Jlc3BvbnNlLnN0YXR1c1RleHR9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByYXdEYXRhID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJvY2Vzc0NhbGVuZGFyRGF0YShyYXdEYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCB0byBsb2FkIGV2ZW50IGRhdGE6JywgZXJyb3IpO1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICB9XG4gICAgYXN5bmMgc2VuZENyZWF0ZShfZXZlbnQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2NrRXZlbnRSZXBvc2l0b3J5IGRvZXMgbm90IHN1cHBvcnQgc2VuZENyZWF0ZS4gTW9jayBkYXRhIGlzIHJlYWQtb25seS4nKTtcbiAgICB9XG4gICAgYXN5bmMgc2VuZFVwZGF0ZShfaWQsIF91cGRhdGVzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9ja0V2ZW50UmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmRVcGRhdGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxuICAgIGFzeW5jIHNlbmREZWxldGUoX2lkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9ja0V2ZW50UmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmREZWxldGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxuICAgIHByb2Nlc3NDYWxlbmRhckRhdGEoZGF0YSkge1xuICAgICAgICByZXR1cm4gZGF0YS5tYXAoKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICAvLyBWYWxpZGF0ZSBjdXN0b21lciBldmVudCBjb25zdHJhaW50c1xuICAgICAgICAgICAgaWYgKGV2ZW50LnR5cGUgPT09ICdjdXN0b21lcicpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWV2ZW50LmJvb2tpbmdJZClcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBDdXN0b21lciBldmVudCAke2V2ZW50LmlkfSBtaXNzaW5nIGJvb2tpbmdJZGApO1xuICAgICAgICAgICAgICAgIGlmICghZXZlbnQucmVzb3VyY2VJZClcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBDdXN0b21lciBldmVudCAke2V2ZW50LmlkfSBtaXNzaW5nIHJlc291cmNlSWRgKTtcbiAgICAgICAgICAgICAgICBpZiAoIWV2ZW50LmN1c3RvbWVySWQpXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgQ3VzdG9tZXIgZXZlbnQgJHtldmVudC5pZH0gbWlzc2luZyBjdXN0b21lcklkYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGlkOiBldmVudC5pZCxcbiAgICAgICAgICAgICAgICB0aXRsZTogZXZlbnQudGl0bGUsXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb246IGV2ZW50LmRlc2NyaXB0aW9uLFxuICAgICAgICAgICAgICAgIHN0YXJ0OiBuZXcgRGF0ZShldmVudC5zdGFydCksXG4gICAgICAgICAgICAgICAgZW5kOiBuZXcgRGF0ZShldmVudC5lbmQpLFxuICAgICAgICAgICAgICAgIHR5cGU6IGV2ZW50LnR5cGUsXG4gICAgICAgICAgICAgICAgYWxsRGF5OiBldmVudC5hbGxEYXkgfHwgZmFsc2UsXG4gICAgICAgICAgICAgICAgYm9va2luZ0lkOiBldmVudC5ib29raW5nSWQsXG4gICAgICAgICAgICAgICAgcmVzb3VyY2VJZDogZXZlbnQucmVzb3VyY2VJZCxcbiAgICAgICAgICAgICAgICBjdXN0b21lcklkOiBldmVudC5jdXN0b21lcklkLFxuICAgICAgICAgICAgICAgIHJlY3VycmluZ0lkOiBldmVudC5yZWN1cnJpbmdJZCxcbiAgICAgICAgICAgICAgICBtZXRhZGF0YTogZXZlbnQubWV0YWRhdGEsXG4gICAgICAgICAgICAgICAgc3luY1N0YXR1czogJ3N5bmNlZCdcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIE1vY2tSZXNvdXJjZVJlcG9zaXRvcnkgLSBMb2FkcyByZXNvdXJjZSBkYXRhIGZyb20gbG9jYWwgSlNPTiBmaWxlXG4gKi9cbmV4cG9ydCBjbGFzcyBNb2NrUmVzb3VyY2VSZXBvc2l0b3J5IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5lbnRpdHlUeXBlID0gJ1Jlc291cmNlJztcbiAgICAgICAgdGhpcy5kYXRhVXJsID0gJ2RhdGEvbW9jay1yZXNvdXJjZXMuanNvbic7XG4gICAgfVxuICAgIGFzeW5jIGZldGNoQWxsKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh0aGlzLmRhdGFVcmwpO1xuICAgICAgICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGxvYWQgbW9jayByZXNvdXJjZXM6ICR7cmVzcG9uc2Uuc3RhdHVzfSAke3Jlc3BvbnNlLnN0YXR1c1RleHR9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByYXdEYXRhID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJvY2Vzc1Jlc291cmNlRGF0YShyYXdEYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCB0byBsb2FkIHJlc291cmNlIGRhdGE6JywgZXJyb3IpO1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICB9XG4gICAgYXN5bmMgc2VuZENyZWF0ZShfcmVzb3VyY2UpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2NrUmVzb3VyY2VSZXBvc2l0b3J5IGRvZXMgbm90IHN1cHBvcnQgc2VuZENyZWF0ZS4gTW9jayBkYXRhIGlzIHJlYWQtb25seS4nKTtcbiAgICB9XG4gICAgYXN5bmMgc2VuZFVwZGF0ZShfaWQsIF91cGRhdGVzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9ja1Jlc291cmNlUmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmRVcGRhdGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxuICAgIGFzeW5jIHNlbmREZWxldGUoX2lkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9ja1Jlc291cmNlUmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmREZWxldGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxuICAgIHByb2Nlc3NSZXNvdXJjZURhdGEoZGF0YSkge1xuICAgICAgICByZXR1cm4gZGF0YS5tYXAoKHJlc291cmNlKSA9PiAoe1xuICAgICAgICAgICAgaWQ6IHJlc291cmNlLmlkLFxuICAgICAgICAgICAgbmFtZTogcmVzb3VyY2UubmFtZSxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiByZXNvdXJjZS5kaXNwbGF5TmFtZSxcbiAgICAgICAgICAgIHR5cGU6IHJlc291cmNlLnR5cGUsXG4gICAgICAgICAgICBhdmF0YXJVcmw6IHJlc291cmNlLmF2YXRhclVybCxcbiAgICAgICAgICAgIGNvbG9yOiByZXNvdXJjZS5jb2xvcixcbiAgICAgICAgICAgIGlzQWN0aXZlOiByZXNvdXJjZS5pc0FjdGl2ZSxcbiAgICAgICAgICAgIGRlZmF1bHRTY2hlZHVsZTogcmVzb3VyY2UuZGVmYXVsdFNjaGVkdWxlLFxuICAgICAgICAgICAgbWV0YWRhdGE6IHJlc291cmNlLm1ldGFkYXRhLFxuICAgICAgICAgICAgc3luY1N0YXR1czogJ3N5bmNlZCdcbiAgICAgICAgfSkpO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIE1vY2tCb29raW5nUmVwb3NpdG9yeSAtIExvYWRzIGJvb2tpbmcgZGF0YSBmcm9tIGxvY2FsIEpTT04gZmlsZVxuICovXG5leHBvcnQgY2xhc3MgTW9ja0Jvb2tpbmdSZXBvc2l0b3J5IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5lbnRpdHlUeXBlID0gJ0Jvb2tpbmcnO1xuICAgICAgICB0aGlzLmRhdGFVcmwgPSAnZGF0YS9tb2NrLWJvb2tpbmdzLmpzb24nO1xuICAgIH1cbiAgICBhc3luYyBmZXRjaEFsbCgpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godGhpcy5kYXRhVXJsKTtcbiAgICAgICAgICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBsb2FkIG1vY2sgYm9va2luZ3M6ICR7cmVzcG9uc2Uuc3RhdHVzfSAke3Jlc3BvbnNlLnN0YXR1c1RleHR9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByYXdEYXRhID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJvY2Vzc0Jvb2tpbmdEYXRhKHJhd0RhdGEpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGxvYWQgYm9va2luZyBkYXRhOicsIGVycm9yKTtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgfVxuICAgIGFzeW5jIHNlbmRDcmVhdGUoX2Jvb2tpbmcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2NrQm9va2luZ1JlcG9zaXRvcnkgZG9lcyBub3Qgc3VwcG9ydCBzZW5kQ3JlYXRlLiBNb2NrIGRhdGEgaXMgcmVhZC1vbmx5LicpO1xuICAgIH1cbiAgICBhc3luYyBzZW5kVXBkYXRlKF9pZCwgX3VwZGF0ZXMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2NrQm9va2luZ1JlcG9zaXRvcnkgZG9lcyBub3Qgc3VwcG9ydCBzZW5kVXBkYXRlLiBNb2NrIGRhdGEgaXMgcmVhZC1vbmx5LicpO1xuICAgIH1cbiAgICBhc3luYyBzZW5kRGVsZXRlKF9pZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vY2tCb29raW5nUmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmREZWxldGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxuICAgIHByb2Nlc3NCb29raW5nRGF0YShkYXRhKSB7XG4gICAgICAgIHJldHVybiBkYXRhLm1hcCgoYm9va2luZykgPT4gKHtcbiAgICAgICAgICAgIGlkOiBib29raW5nLmlkLFxuICAgICAgICAgICAgY3VzdG9tZXJJZDogYm9va2luZy5jdXN0b21lcklkLFxuICAgICAgICAgICAgc3RhdHVzOiBib29raW5nLnN0YXR1cyxcbiAgICAgICAgICAgIGNyZWF0ZWRBdDogbmV3IERhdGUoYm9va2luZy5jcmVhdGVkQXQpLFxuICAgICAgICAgICAgc2VydmljZXM6IGJvb2tpbmcuc2VydmljZXMsXG4gICAgICAgICAgICB0b3RhbFByaWNlOiBib29raW5nLnRvdGFsUHJpY2UsXG4gICAgICAgICAgICB0YWdzOiBib29raW5nLnRhZ3MsXG4gICAgICAgICAgICBub3RlczogYm9va2luZy5ub3RlcyxcbiAgICAgICAgICAgIHN5bmNTdGF0dXM6ICdzeW5jZWQnXG4gICAgICAgIH0pKTtcbiAgICB9XG59XG4iLCAiLyoqXG4gKiBNb2NrQ3VzdG9tZXJSZXBvc2l0b3J5IC0gTG9hZHMgY3VzdG9tZXIgZGF0YSBmcm9tIGxvY2FsIEpTT04gZmlsZVxuICovXG5leHBvcnQgY2xhc3MgTW9ja0N1c3RvbWVyUmVwb3NpdG9yeSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuZW50aXR5VHlwZSA9ICdDdXN0b21lcic7XG4gICAgICAgIHRoaXMuZGF0YVVybCA9ICdkYXRhL21vY2stY3VzdG9tZXJzLmpzb24nO1xuICAgIH1cbiAgICBhc3luYyBmZXRjaEFsbCgpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godGhpcy5kYXRhVXJsKTtcbiAgICAgICAgICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBsb2FkIG1vY2sgY3VzdG9tZXJzOiAke3Jlc3BvbnNlLnN0YXR1c30gJHtyZXNwb25zZS5zdGF0dXNUZXh0fWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmF3RGF0YSA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnByb2Nlc3NDdXN0b21lckRhdGEocmF3RGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgdG8gbG9hZCBjdXN0b21lciBkYXRhOicsIGVycm9yKTtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgfVxuICAgIGFzeW5jIHNlbmRDcmVhdGUoX2N1c3RvbWVyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9ja0N1c3RvbWVyUmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmRDcmVhdGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxuICAgIGFzeW5jIHNlbmRVcGRhdGUoX2lkLCBfdXBkYXRlcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vY2tDdXN0b21lclJlcG9zaXRvcnkgZG9lcyBub3Qgc3VwcG9ydCBzZW5kVXBkYXRlLiBNb2NrIGRhdGEgaXMgcmVhZC1vbmx5LicpO1xuICAgIH1cbiAgICBhc3luYyBzZW5kRGVsZXRlKF9pZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vY2tDdXN0b21lclJlcG9zaXRvcnkgZG9lcyBub3Qgc3VwcG9ydCBzZW5kRGVsZXRlLiBNb2NrIGRhdGEgaXMgcmVhZC1vbmx5LicpO1xuICAgIH1cbiAgICBwcm9jZXNzQ3VzdG9tZXJEYXRhKGRhdGEpIHtcbiAgICAgICAgcmV0dXJuIGRhdGEubWFwKChjdXN0b21lcikgPT4gKHtcbiAgICAgICAgICAgIGlkOiBjdXN0b21lci5pZCxcbiAgICAgICAgICAgIG5hbWU6IGN1c3RvbWVyLm5hbWUsXG4gICAgICAgICAgICBwaG9uZTogY3VzdG9tZXIucGhvbmUsXG4gICAgICAgICAgICBlbWFpbDogY3VzdG9tZXIuZW1haWwsXG4gICAgICAgICAgICBtZXRhZGF0YTogY3VzdG9tZXIubWV0YWRhdGEsXG4gICAgICAgICAgICBzeW5jU3RhdHVzOiAnc3luY2VkJ1xuICAgICAgICB9KSk7XG4gICAgfVxufVxuIiwgIi8qKlxuICogTW9ja0F1ZGl0UmVwb3NpdG9yeSAtIE1vY2sgQVBJIHJlcG9zaXRvcnkgZm9yIGF1ZGl0IGVudHJpZXNcbiAqXG4gKiBJbiBwcm9kdWN0aW9uLCB0aGlzIHdvdWxkIHNlbmQgYXVkaXQgZW50cmllcyB0byB0aGUgYmFja2VuZC5cbiAqIEZvciBkZXZlbG9wbWVudC90ZXN0aW5nLCBpdCBqdXN0IGxvZ3MgdGhlIG9wZXJhdGlvbnMuXG4gKi9cbmV4cG9ydCBjbGFzcyBNb2NrQXVkaXRSZXBvc2l0b3J5IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5lbnRpdHlUeXBlID0gJ0F1ZGl0JztcbiAgICB9XG4gICAgYXN5bmMgc2VuZENyZWF0ZShlbnRpdHkpIHtcbiAgICAgICAgLy8gU2ltdWxhdGUgQVBJIGNhbGwgZGVsYXlcbiAgICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDEwMCkpO1xuICAgICAgICBjb25zb2xlLmxvZygnTW9ja0F1ZGl0UmVwb3NpdG9yeTogQXVkaXQgZW50cnkgc3luY2VkIHRvIGJhY2tlbmQ6Jywge1xuICAgICAgICAgICAgaWQ6IGVudGl0eS5pZCxcbiAgICAgICAgICAgIGVudGl0eVR5cGU6IGVudGl0eS5lbnRpdHlUeXBlLFxuICAgICAgICAgICAgZW50aXR5SWQ6IGVudGl0eS5lbnRpdHlJZCxcbiAgICAgICAgICAgIG9wZXJhdGlvbjogZW50aXR5Lm9wZXJhdGlvbixcbiAgICAgICAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoZW50aXR5LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGVudGl0eTtcbiAgICB9XG4gICAgYXN5bmMgc2VuZFVwZGF0ZShfaWQsIF9lbnRpdHkpIHtcbiAgICAgICAgLy8gQXVkaXQgZW50cmllcyBhcmUgaW1tdXRhYmxlIC0gdXBkYXRlcyBzaG91bGQgbm90IGhhcHBlblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0F1ZGl0IGVudHJpZXMgY2Fubm90IGJlIHVwZGF0ZWQnKTtcbiAgICB9XG4gICAgYXN5bmMgc2VuZERlbGV0ZShfaWQpIHtcbiAgICAgICAgLy8gQXVkaXQgZW50cmllcyBzaG91bGQgbmV2ZXIgYmUgZGVsZXRlZFxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0F1ZGl0IGVudHJpZXMgY2Fubm90IGJlIGRlbGV0ZWQnKTtcbiAgICB9XG4gICAgYXN5bmMgZmV0Y2hBbGwoKSB7XG4gICAgICAgIC8vIEZvciBub3csIHJldHVybiBlbXB0eSBhcnJheSAtIGF1ZGl0IGVudHJpZXMgYXJlIGxvY2FsLWZpcnN0XG4gICAgICAgIC8vIEluIHByb2R1Y3Rpb24sIHRoaXMgY291bGQgZmV0Y2ggYXVkaXQgaGlzdG9yeSBmcm9tIGJhY2tlbmRcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICBhc3luYyBmZXRjaEJ5SWQoX2lkKSB7XG4gICAgICAgIC8vIEZvciBub3csIHJldHVybiBudWxsIC0gYXVkaXQgZW50cmllcyBhcmUgbG9jYWwtZmlyc3RcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxufVxuIiwgIi8qKlxuICogTW9ja1RlYW1SZXBvc2l0b3J5IC0gTG9hZHMgdGVhbSBkYXRhIGZyb20gbG9jYWwgSlNPTiBmaWxlXG4gKi9cbmV4cG9ydCBjbGFzcyBNb2NrVGVhbVJlcG9zaXRvcnkge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmVudGl0eVR5cGUgPSAnVGVhbSc7XG4gICAgICAgIHRoaXMuZGF0YVVybCA9ICdkYXRhL21vY2stdGVhbXMuanNvbic7XG4gICAgfVxuICAgIGFzeW5jIGZldGNoQWxsKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh0aGlzLmRhdGFVcmwpO1xuICAgICAgICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGxvYWQgbW9jayB0ZWFtczogJHtyZXNwb25zZS5zdGF0dXN9ICR7cmVzcG9uc2Uuc3RhdHVzVGV4dH1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJhd0RhdGEgPSBhd2FpdCByZXNwb25zZS5qc29uKCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wcm9jZXNzVGVhbURhdGEocmF3RGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgdG8gbG9hZCB0ZWFtIGRhdGE6JywgZXJyb3IpO1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICB9XG4gICAgYXN5bmMgc2VuZENyZWF0ZShfdGVhbSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vY2tUZWFtUmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmRDcmVhdGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxuICAgIGFzeW5jIHNlbmRVcGRhdGUoX2lkLCBfdXBkYXRlcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vY2tUZWFtUmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmRVcGRhdGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxuICAgIGFzeW5jIHNlbmREZWxldGUoX2lkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9ja1RlYW1SZXBvc2l0b3J5IGRvZXMgbm90IHN1cHBvcnQgc2VuZERlbGV0ZS4gTW9jayBkYXRhIGlzIHJlYWQtb25seS4nKTtcbiAgICB9XG4gICAgcHJvY2Vzc1RlYW1EYXRhKGRhdGEpIHtcbiAgICAgICAgcmV0dXJuIGRhdGEubWFwKCh0ZWFtKSA9PiAoe1xuICAgICAgICAgICAgaWQ6IHRlYW0uaWQsXG4gICAgICAgICAgICBuYW1lOiB0ZWFtLm5hbWUsXG4gICAgICAgICAgICByZXNvdXJjZUlkczogdGVhbS5yZXNvdXJjZUlkcyxcbiAgICAgICAgICAgIHN5bmNTdGF0dXM6ICdzeW5jZWQnXG4gICAgICAgIH0pKTtcbiAgICB9XG59XG4iLCAiLyoqXG4gKiBNb2NrRGVwYXJ0bWVudFJlcG9zaXRvcnkgLSBMb2FkcyBkZXBhcnRtZW50IGRhdGEgZnJvbSBsb2NhbCBKU09OIGZpbGVcbiAqL1xuZXhwb3J0IGNsYXNzIE1vY2tEZXBhcnRtZW50UmVwb3NpdG9yeSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuZW50aXR5VHlwZSA9ICdEZXBhcnRtZW50JztcbiAgICAgICAgdGhpcy5kYXRhVXJsID0gJ2RhdGEvbW9jay1kZXBhcnRtZW50cy5qc29uJztcbiAgICB9XG4gICAgYXN5bmMgZmV0Y2hBbGwoKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHRoaXMuZGF0YVVybCk7XG4gICAgICAgICAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gbG9hZCBtb2NrIGRlcGFydG1lbnRzOiAke3Jlc3BvbnNlLnN0YXR1c30gJHtyZXNwb25zZS5zdGF0dXNUZXh0fWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmF3RGF0YSA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnByb2Nlc3NEZXBhcnRtZW50RGF0YShyYXdEYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCB0byBsb2FkIGRlcGFydG1lbnQgZGF0YTonLCBlcnJvcik7XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBhc3luYyBzZW5kQ3JlYXRlKF9kZXBhcnRtZW50KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9ja0RlcGFydG1lbnRSZXBvc2l0b3J5IGRvZXMgbm90IHN1cHBvcnQgc2VuZENyZWF0ZS4gTW9jayBkYXRhIGlzIHJlYWQtb25seS4nKTtcbiAgICB9XG4gICAgYXN5bmMgc2VuZFVwZGF0ZShfaWQsIF91cGRhdGVzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9ja0RlcGFydG1lbnRSZXBvc2l0b3J5IGRvZXMgbm90IHN1cHBvcnQgc2VuZFVwZGF0ZS4gTW9jayBkYXRhIGlzIHJlYWQtb25seS4nKTtcbiAgICB9XG4gICAgYXN5bmMgc2VuZERlbGV0ZShfaWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2NrRGVwYXJ0bWVudFJlcG9zaXRvcnkgZG9lcyBub3Qgc3VwcG9ydCBzZW5kRGVsZXRlLiBNb2NrIGRhdGEgaXMgcmVhZC1vbmx5LicpO1xuICAgIH1cbiAgICBwcm9jZXNzRGVwYXJ0bWVudERhdGEoZGF0YSkge1xuICAgICAgICByZXR1cm4gZGF0YS5tYXAoKGRlcHQpID0+ICh7XG4gICAgICAgICAgICBpZDogZGVwdC5pZCxcbiAgICAgICAgICAgIG5hbWU6IGRlcHQubmFtZSxcbiAgICAgICAgICAgIHJlc291cmNlSWRzOiBkZXB0LnJlc291cmNlSWRzLFxuICAgICAgICAgICAgc3luY1N0YXR1czogJ3N5bmNlZCdcbiAgICAgICAgfSkpO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIE1vY2tTZXR0aW5nc1JlcG9zaXRvcnkgLSBMb2FkcyB0ZW5hbnQgc2V0dGluZ3MgZnJvbSBsb2NhbCBKU09OIGZpbGVcbiAqXG4gKiBTZXR0aW5ncyBhcmUgc3RvcmVkIGFzIHNlcGFyYXRlIHJlY29yZHMgcGVyIHNlY3Rpb24gKHdvcmt3ZWVrLCBncmlkLCBldGMuKS5cbiAqIFRoZSBKU09OIGZpbGUgaXMgYWxyZWFkeSBhbiBhcnJheSBvZiBUZW5hbnRTZXR0aW5nIHJlY29yZHMuXG4gKi9cbmV4cG9ydCBjbGFzcyBNb2NrU2V0dGluZ3NSZXBvc2l0b3J5IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5lbnRpdHlUeXBlID0gJ1NldHRpbmdzJztcbiAgICAgICAgdGhpcy5kYXRhVXJsID0gJ2RhdGEvdGVuYW50LXNldHRpbmdzLmpzb24nO1xuICAgIH1cbiAgICBhc3luYyBmZXRjaEFsbCgpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godGhpcy5kYXRhVXJsKTtcbiAgICAgICAgICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBsb2FkIHRlbmFudCBzZXR0aW5nczogJHtyZXNwb25zZS5zdGF0dXN9ICR7cmVzcG9uc2Uuc3RhdHVzVGV4dH1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHNldHRpbmdzID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICAgICAgICAgICAgLy8gRW5zdXJlIHN5bmNTdGF0dXMgaXMgc2V0IG9uIGVhY2ggcmVjb3JkXG4gICAgICAgICAgICByZXR1cm4gc2V0dGluZ3MubWFwKHMgPT4gKHtcbiAgICAgICAgICAgICAgICAuLi5zLFxuICAgICAgICAgICAgICAgIHN5bmNTdGF0dXM6IHMuc3luY1N0YXR1cyB8fCAnc3luY2VkJ1xuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGxvYWQgdGVuYW50IHNldHRpbmdzOicsIGVycm9yKTtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgfVxuICAgIGFzeW5jIHNlbmRDcmVhdGUoX3NldHRpbmdzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9ja1NldHRpbmdzUmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmRDcmVhdGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxuICAgIGFzeW5jIHNlbmRVcGRhdGUoX2lkLCBfdXBkYXRlcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vY2tTZXR0aW5nc1JlcG9zaXRvcnkgZG9lcyBub3Qgc3VwcG9ydCBzZW5kVXBkYXRlLiBNb2NrIGRhdGEgaXMgcmVhZC1vbmx5LicpO1xuICAgIH1cbiAgICBhc3luYyBzZW5kRGVsZXRlKF9pZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vY2tTZXR0aW5nc1JlcG9zaXRvcnkgZG9lcyBub3Qgc3VwcG9ydCBzZW5kRGVsZXRlLiBNb2NrIGRhdGEgaXMgcmVhZC1vbmx5LicpO1xuICAgIH1cbn1cbiIsICJleHBvcnQgY2xhc3MgTW9ja1ZpZXdDb25maWdSZXBvc2l0b3J5IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5lbnRpdHlUeXBlID0gJ1ZpZXdDb25maWcnO1xuICAgICAgICB0aGlzLmRhdGFVcmwgPSAnZGF0YS92aWV3Y29uZmlncy5qc29uJztcbiAgICB9XG4gICAgYXN5bmMgZmV0Y2hBbGwoKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHRoaXMuZGF0YVVybCk7XG4gICAgICAgICAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gbG9hZCB2aWV3Y29uZmlnczogJHtyZXNwb25zZS5zdGF0dXN9ICR7cmVzcG9uc2Uuc3RhdHVzVGV4dH1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJhd0RhdGEgPSBhd2FpdCByZXNwb25zZS5qc29uKCk7XG4gICAgICAgICAgICAvLyBFbnN1cmUgc3luY1N0YXR1cyBpcyBzZXQgb24gZWFjaCBjb25maWdcbiAgICAgICAgICAgIGNvbnN0IGNvbmZpZ3MgPSByYXdEYXRhLm1hcCgoY29uZmlnKSA9PiAoe1xuICAgICAgICAgICAgICAgIC4uLmNvbmZpZyxcbiAgICAgICAgICAgICAgICBzeW5jU3RhdHVzOiBjb25maWcuc3luY1N0YXR1cyB8fCAnc3luY2VkJ1xuICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgcmV0dXJuIGNvbmZpZ3M7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgdG8gbG9hZCB2aWV3Y29uZmlnczonLCBlcnJvcik7XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBhc3luYyBzZW5kQ3JlYXRlKF9jb25maWcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2NrVmlld0NvbmZpZ1JlcG9zaXRvcnkgZG9lcyBub3Qgc3VwcG9ydCBzZW5kQ3JlYXRlLiBNb2NrIGRhdGEgaXMgcmVhZC1vbmx5LicpO1xuICAgIH1cbiAgICBhc3luYyBzZW5kVXBkYXRlKF9pZCwgX3VwZGF0ZXMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2NrVmlld0NvbmZpZ1JlcG9zaXRvcnkgZG9lcyBub3Qgc3VwcG9ydCBzZW5kVXBkYXRlLiBNb2NrIGRhdGEgaXMgcmVhZC1vbmx5LicpO1xuICAgIH1cbiAgICBhc3luYyBzZW5kRGVsZXRlKF9pZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vY2tWaWV3Q29uZmlnUmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmREZWxldGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxufVxuIiwgIi8qKlxuICogRGF0YVNlZWRlciAtIE9yY2hlc3RyYXRlcyBpbml0aWFsIGRhdGEgbG9hZGluZyBmcm9tIHJlcG9zaXRvcmllcyBpbnRvIEluZGV4ZWREQlxuICpcbiAqIEFSQ0hJVEVDVFVSRTpcbiAqIC0gUmVwb3NpdG9yeSAoTW9jay9BcGkpOiBGZXRjaGVzIGRhdGEgZnJvbSBzb3VyY2UgKEpTT04gZmlsZSBvciBiYWNrZW5kIEFQSSlcbiAqIC0gRGF0YVNlZWRlciAodGhpcyBjbGFzcyk6IE9yY2hlc3RyYXRlcyBmZXRjaCArIHNhdmUgb3BlcmF0aW9uc1xuICogLSBTZXJ2aWNlIChFdmVudFNlcnZpY2UsIGV0Yy4pOiBTYXZlcyBkYXRhIHRvIEluZGV4ZWREQlxuICpcbiAqIFBPTFlNT1JQSElDIERFU0lHTjpcbiAqIC0gVXNlcyBhcnJheXMgb2YgSUVudGl0eVNlcnZpY2VbXSBhbmQgSUFwaVJlcG9zaXRvcnlbXVxuICogLSBNYXRjaGVzIHNlcnZpY2VzIHdpdGggcmVwb3NpdG9yaWVzIHVzaW5nIGVudGl0eVR5cGUgcHJvcGVydHlcbiAqIC0gT3Blbi9DbG9zZWQgUHJpbmNpcGxlOiBBZGRpbmcgbmV3IGVudGl0eSByZXF1aXJlcyBubyBjb2RlIGNoYW5nZXMgaGVyZVxuICovXG5leHBvcnQgY2xhc3MgRGF0YVNlZWRlciB7XG4gICAgY29uc3RydWN0b3Ioc2VydmljZXMsIHJlcG9zaXRvcmllcykge1xuICAgICAgICB0aGlzLnNlcnZpY2VzID0gc2VydmljZXM7XG4gICAgICAgIHRoaXMucmVwb3NpdG9yaWVzID0gcmVwb3NpdG9yaWVzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZWVkIGFsbCBlbnRpdHkgc3RvcmVzIGlmIHRoZXkgYXJlIGVtcHR5XG4gICAgICovXG4gICAgYXN5bmMgc2VlZElmRW1wdHkoKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdbRGF0YVNlZWRlcl0gQ2hlY2tpbmcgaWYgZGF0YWJhc2UgbmVlZHMgc2VlZGluZy4uLicpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgZm9yIChjb25zdCBzZXJ2aWNlIG9mIHRoaXMuc2VydmljZXMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXBvc2l0b3J5ID0gdGhpcy5yZXBvc2l0b3JpZXMuZmluZChyZXBvID0+IHJlcG8uZW50aXR5VHlwZSA9PT0gc2VydmljZS5lbnRpdHlUeXBlKTtcbiAgICAgICAgICAgICAgICBpZiAoIXJlcG9zaXRvcnkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBbRGF0YVNlZWRlcl0gTm8gcmVwb3NpdG9yeSBmb3VuZCBmb3IgZW50aXR5IHR5cGU6ICR7c2VydmljZS5lbnRpdHlUeXBlfSwgc2tpcHBpbmdgKTtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2VlZEVudGl0eShzZXJ2aWNlLmVudGl0eVR5cGUsIHNlcnZpY2UsIHJlcG9zaXRvcnkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc29sZS5sb2coJ1tEYXRhU2VlZGVyXSBTZWVkaW5nIGNvbXBsZXRlJyk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdbRGF0YVNlZWRlcl0gU2VlZGluZyBmYWlsZWQ6JywgZXJyb3IpO1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICB9XG4gICAgYXN5bmMgc2VlZEVudGl0eShlbnRpdHlUeXBlLCBzZXJ2aWNlLCByZXBvc2l0b3J5KSB7XG4gICAgICAgIGNvbnN0IGV4aXN0aW5nID0gYXdhaXQgc2VydmljZS5nZXRBbGwoKTtcbiAgICAgICAgaWYgKGV4aXN0aW5nLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBbRGF0YVNlZWRlcl0gJHtlbnRpdHlUeXBlfSBzdG9yZSBhbHJlYWR5IGhhcyAke2V4aXN0aW5nLmxlbmd0aH0gaXRlbXMsIHNraXBwaW5nIHNlZWRgKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLmxvZyhgW0RhdGFTZWVkZXJdICR7ZW50aXR5VHlwZX0gc3RvcmUgaXMgZW1wdHksIGZldGNoaW5nIGZyb20gcmVwb3NpdG9yeS4uLmApO1xuICAgICAgICBjb25zdCBkYXRhID0gYXdhaXQgcmVwb3NpdG9yeS5mZXRjaEFsbCgpO1xuICAgICAgICBjb25zb2xlLmxvZyhgW0RhdGFTZWVkZXJdIEZldGNoZWQgJHtkYXRhLmxlbmd0aH0gJHtlbnRpdHlUeXBlfSBpdGVtcywgc2F2aW5nIHRvIEluZGV4ZWREQi4uLmApO1xuICAgICAgICBmb3IgKGNvbnN0IGVudGl0eSBvZiBkYXRhKSB7XG4gICAgICAgICAgICBhd2FpdCBzZXJ2aWNlLnNhdmUoZW50aXR5LCB0cnVlKTsgLy8gc2lsZW50ID0gdHJ1ZSB0byBza2lwIGF1ZGl0IGxvZ2dpbmdcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLmxvZyhgW0RhdGFTZWVkZXJdICR7ZW50aXR5VHlwZX0gc2VlZGluZyBjb21wbGV0ZSAoJHtkYXRhLmxlbmd0aH0gaXRlbXMgc2F2ZWQpYCk7XG4gICAgfVxufVxuIiwgIi8qKlxuICogQ2FsY3VsYXRlIHBpeGVsIHBvc2l0aW9uIGZvciBhbiBldmVudCBiYXNlZCBvbiBpdHMgdGltZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZUV2ZW50UG9zaXRpb24oc3RhcnQsIGVuZCwgY29uZmlnKSB7XG4gICAgY29uc3Qgc3RhcnRNaW51dGVzID0gc3RhcnQuZ2V0SG91cnMoKSAqIDYwICsgc3RhcnQuZ2V0TWludXRlcygpO1xuICAgIGNvbnN0IGVuZE1pbnV0ZXMgPSBlbmQuZ2V0SG91cnMoKSAqIDYwICsgZW5kLmdldE1pbnV0ZXMoKTtcbiAgICBjb25zdCBkYXlTdGFydE1pbnV0ZXMgPSBjb25maWcuZGF5U3RhcnRIb3VyICogNjA7XG4gICAgY29uc3QgbWludXRlSGVpZ2h0ID0gY29uZmlnLmhvdXJIZWlnaHQgLyA2MDtcbiAgICBjb25zdCB0b3AgPSAoc3RhcnRNaW51dGVzIC0gZGF5U3RhcnRNaW51dGVzKSAqIG1pbnV0ZUhlaWdodDtcbiAgICBjb25zdCBoZWlnaHQgPSAoZW5kTWludXRlcyAtIHN0YXJ0TWludXRlcykgKiBtaW51dGVIZWlnaHQ7XG4gICAgcmV0dXJuIHsgdG9wLCBoZWlnaHQgfTtcbn1cbi8qKlxuICogQ29udmVydCBtaW51dGVzIHRvIHBpeGVsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gbWludXRlc1RvUGl4ZWxzKG1pbnV0ZXMsIGNvbmZpZykge1xuICAgIHJldHVybiAobWludXRlcyAvIDYwKSAqIGNvbmZpZy5ob3VySGVpZ2h0O1xufVxuLyoqXG4gKiBDb252ZXJ0IHBpeGVscyB0byBtaW51dGVzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwaXhlbHNUb01pbnV0ZXMocGl4ZWxzLCBjb25maWcpIHtcbiAgICByZXR1cm4gKHBpeGVscyAvIGNvbmZpZy5ob3VySGVpZ2h0KSAqIDYwO1xufVxuLyoqXG4gKiBTbmFwIHBpeGVsIHBvc2l0aW9uIHRvIGdyaWQgaW50ZXJ2YWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNuYXBUb0dyaWQocGl4ZWxzLCBjb25maWcpIHtcbiAgICBjb25zdCBzbmFwUGl4ZWxzID0gbWludXRlc1RvUGl4ZWxzKGNvbmZpZy5zbmFwSW50ZXJ2YWwsIGNvbmZpZyk7XG4gICAgcmV0dXJuIE1hdGgucm91bmQocGl4ZWxzIC8gc25hcFBpeGVscykgKiBzbmFwUGl4ZWxzO1xufVxuIiwgImltcG9ydCB7IGNhbGN1bGF0ZUV2ZW50UG9zaXRpb24gfSBmcm9tICcuLi8uLi91dGlscy9Qb3NpdGlvblV0aWxzJztcbi8qKlxuICogQ2hlY2sgaWYgdHdvIGV2ZW50cyBvdmVybGFwIChzdHJpY3QgLSB0b3VjaGluZyBhdCBib3VuZGFyeSA9IE5PVCBvdmVybGFwcGluZylcbiAqIFRoaXMgbWF0Y2hlcyBTY2VuYXJpbyA4OiBlbmQ9PT1zdGFydCBpcyBOT1Qgb3ZlcmxhcFxuICovXG5leHBvcnQgZnVuY3Rpb24gZXZlbnRzT3ZlcmxhcChhLCBiKSB7XG4gICAgcmV0dXJuIGEuc3RhcnQgPCBiLmVuZCAmJiBhLmVuZCA+IGIuc3RhcnQ7XG59XG4vKipcbiAqIENoZWNrIGlmIHR3byBldmVudHMgYXJlIHdpdGhpbiB0aHJlc2hvbGQgZm9yIGdyaWQgZ3JvdXBpbmcuXG4gKiBUaGlzIGluY2x1ZGVzOlxuICogMS4gU3RhcnQtdG8tc3RhcnQ6IEV2ZW50cyBzdGFydCB3aXRoaW4gdGhyZXNob2xkIG9mIGVhY2ggb3RoZXJcbiAqIDIuIEVuZC10by1zdGFydDogT25lIGV2ZW50IHN0YXJ0cyB3aXRoaW4gdGhyZXNob2xkIGJlZm9yZSBhbm90aGVyIGVuZHNcbiAqL1xuZnVuY3Rpb24gZXZlbnRzV2l0aGluVGhyZXNob2xkKGEsIGIsIHRocmVzaG9sZE1pbnV0ZXMpIHtcbiAgICBjb25zdCB0aHJlc2hvbGRNcyA9IHRocmVzaG9sZE1pbnV0ZXMgKiA2MCAqIDEwMDA7XG4gICAgLy8gU3RhcnQtdG8tc3RhcnQ6IGJvdGggZXZlbnRzIHN0YXJ0IHdpdGhpbiB0aHJlc2hvbGRcbiAgICBjb25zdCBzdGFydFRvU3RhcnREaWZmID0gTWF0aC5hYnMoYS5zdGFydC5nZXRUaW1lKCkgLSBiLnN0YXJ0LmdldFRpbWUoKSk7XG4gICAgaWYgKHN0YXJ0VG9TdGFydERpZmYgPD0gdGhyZXNob2xkTXMpXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIC8vIEVuZC10by1zdGFydDogb25lIGV2ZW50IHN0YXJ0cyB3aXRoaW4gdGhyZXNob2xkIGJlZm9yZSB0aGUgb3RoZXIgZW5kc1xuICAgIC8vIEIgc3RhcnRzIHdpdGhpbiB0aHJlc2hvbGQgYmVmb3JlIEEgZW5kc1xuICAgIGNvbnN0IGJTdGFydHNCZWZvcmVBRW5kcyA9IGEuZW5kLmdldFRpbWUoKSAtIGIuc3RhcnQuZ2V0VGltZSgpO1xuICAgIGlmIChiU3RhcnRzQmVmb3JlQUVuZHMgPiAwICYmIGJTdGFydHNCZWZvcmVBRW5kcyA8PSB0aHJlc2hvbGRNcylcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgLy8gQSBzdGFydHMgd2l0aGluIHRocmVzaG9sZCBiZWZvcmUgQiBlbmRzXG4gICAgY29uc3QgYVN0YXJ0c0JlZm9yZUJFbmRzID0gYi5lbmQuZ2V0VGltZSgpIC0gYS5zdGFydC5nZXRUaW1lKCk7XG4gICAgaWYgKGFTdGFydHNCZWZvcmVCRW5kcyA+IDAgJiYgYVN0YXJ0c0JlZm9yZUJFbmRzIDw9IHRocmVzaG9sZE1zKVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICByZXR1cm4gZmFsc2U7XG59XG4vKipcbiAqIENoZWNrIGlmIGFsbCBldmVudHMgaW4gYSBncm91cCBzdGFydCB3aXRoaW4gdGhyZXNob2xkIG9mIGVhY2ggb3RoZXJcbiAqL1xuZnVuY3Rpb24gYWxsU3RhcnRXaXRoaW5UaHJlc2hvbGQoZXZlbnRzLCB0aHJlc2hvbGRNaW51dGVzKSB7XG4gICAgaWYgKGV2ZW50cy5sZW5ndGggPD0gMSlcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgLy8gRmluZCBlYXJsaWVzdCBhbmQgbGF0ZXN0IHN0YXJ0IHRpbWVzXG4gICAgbGV0IGVhcmxpZXN0ID0gZXZlbnRzWzBdLnN0YXJ0LmdldFRpbWUoKTtcbiAgICBsZXQgbGF0ZXN0ID0gZXZlbnRzWzBdLnN0YXJ0LmdldFRpbWUoKTtcbiAgICBmb3IgKGNvbnN0IGV2ZW50IG9mIGV2ZW50cykge1xuICAgICAgICBjb25zdCB0aW1lID0gZXZlbnQuc3RhcnQuZ2V0VGltZSgpO1xuICAgICAgICBpZiAodGltZSA8IGVhcmxpZXN0KVxuICAgICAgICAgICAgZWFybGllc3QgPSB0aW1lO1xuICAgICAgICBpZiAodGltZSA+IGxhdGVzdClcbiAgICAgICAgICAgIGxhdGVzdCA9IHRpbWU7XG4gICAgfVxuICAgIGNvbnN0IGRpZmZNaW51dGVzID0gKGxhdGVzdCAtIGVhcmxpZXN0KSAvICgxMDAwICogNjApO1xuICAgIHJldHVybiBkaWZmTWludXRlcyA8PSB0aHJlc2hvbGRNaW51dGVzO1xufVxuLyoqXG4gKiBGaW5kIGdyb3VwcyBvZiBvdmVybGFwcGluZyBldmVudHMgKGNvbm5lY3RlZCBieSBvdmVybGFwIGNoYWluKVxuICogRXZlbnRzIGFyZSBncm91cGVkIGlmIHRoZXkgb3ZlcmxhcCB3aXRoIGFueSBldmVudCBpbiB0aGUgZ3JvdXBcbiAqL1xuZnVuY3Rpb24gZmluZE92ZXJsYXBHcm91cHMoZXZlbnRzKSB7XG4gICAgaWYgKGV2ZW50cy5sZW5ndGggPT09IDApXG4gICAgICAgIHJldHVybiBbXTtcbiAgICBjb25zdCBzb3J0ZWQgPSBbLi4uZXZlbnRzXS5zb3J0KChhLCBiKSA9PiBhLnN0YXJ0LmdldFRpbWUoKSAtIGIuc3RhcnQuZ2V0VGltZSgpKTtcbiAgICBjb25zdCB1c2VkID0gbmV3IFNldCgpO1xuICAgIGNvbnN0IGdyb3VwcyA9IFtdO1xuICAgIGZvciAoY29uc3QgZXZlbnQgb2Ygc29ydGVkKSB7XG4gICAgICAgIGlmICh1c2VkLmhhcyhldmVudC5pZCkpXG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgLy8gU3RhcnQgYSBuZXcgZ3JvdXAgd2l0aCB0aGlzIGV2ZW50XG4gICAgICAgIGNvbnN0IGdyb3VwID0gW2V2ZW50XTtcbiAgICAgICAgdXNlZC5hZGQoZXZlbnQuaWQpO1xuICAgICAgICAvLyBFeHBhbmQgZ3JvdXAgYnkgZmluZGluZyBhbGwgY29ubmVjdGVkIGV2ZW50cyAodmlhIG92ZXJsYXApXG4gICAgICAgIGxldCBleHBhbmRlZCA9IHRydWU7XG4gICAgICAgIHdoaWxlIChleHBhbmRlZCkge1xuICAgICAgICAgICAgZXhwYW5kZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgY2FuZGlkYXRlIG9mIHNvcnRlZCkge1xuICAgICAgICAgICAgICAgIGlmICh1c2VkLmhhcyhjYW5kaWRhdGUuaWQpKVxuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiBjYW5kaWRhdGUgb3ZlcmxhcHMgd2l0aCBhbnkgZXZlbnQgaW4gZ3JvdXBcbiAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0cyA9IGdyb3VwLnNvbWUobWVtYmVyID0+IGV2ZW50c092ZXJsYXAobWVtYmVyLCBjYW5kaWRhdGUpKTtcbiAgICAgICAgICAgICAgICBpZiAoY29ubmVjdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgZ3JvdXAucHVzaChjYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgICAgICB1c2VkLmFkZChjYW5kaWRhdGUuaWQpO1xuICAgICAgICAgICAgICAgICAgICBleHBhbmRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGdyb3Vwcy5wdXNoKGdyb3VwKTtcbiAgICB9XG4gICAgcmV0dXJuIGdyb3Vwcztcbn1cbi8qKlxuICogRmluZCBncmlkIGNhbmRpZGF0ZXMgd2l0aGluIGEgZ3JvdXAgLSBldmVudHMgY29ubmVjdGVkIHZpYSB0aHJlc2hvbGQgY2hhaW5cbiAqIFVzZXMgVjEgbG9naWM6IGV2ZW50cyBhcmUgY29ubmVjdGVkIGlmIHdpdGhpbiB0aHJlc2hvbGQgKG5vIG92ZXJsYXAgcmVxdWlyZW1lbnQpXG4gKi9cbmZ1bmN0aW9uIGZpbmRHcmlkQ2FuZGlkYXRlcyhldmVudHMsIHRocmVzaG9sZE1pbnV0ZXMpIHtcbiAgICBpZiAoZXZlbnRzLmxlbmd0aCA9PT0gMClcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIGNvbnN0IHNvcnRlZCA9IFsuLi5ldmVudHNdLnNvcnQoKGEsIGIpID0+IGEuc3RhcnQuZ2V0VGltZSgpIC0gYi5zdGFydC5nZXRUaW1lKCkpO1xuICAgIGNvbnN0IHVzZWQgPSBuZXcgU2V0KCk7XG4gICAgY29uc3QgZ3JvdXBzID0gW107XG4gICAgZm9yIChjb25zdCBldmVudCBvZiBzb3J0ZWQpIHtcbiAgICAgICAgaWYgKHVzZWQuaGFzKGV2ZW50LmlkKSlcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICBjb25zdCBncm91cCA9IFtldmVudF07XG4gICAgICAgIHVzZWQuYWRkKGV2ZW50LmlkKTtcbiAgICAgICAgLy8gRXhwYW5kIGJ5IHRocmVzaG9sZCBjaGFpbiAoVjEgbG9naWM6IG5vIG92ZXJsYXAgcmVxdWlyZW1lbnQsIGp1c3QgdGhyZXNob2xkKVxuICAgICAgICBsZXQgZXhwYW5kZWQgPSB0cnVlO1xuICAgICAgICB3aGlsZSAoZXhwYW5kZWQpIHtcbiAgICAgICAgICAgIGV4cGFuZGVkID0gZmFsc2U7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNhbmRpZGF0ZSBvZiBzb3J0ZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAodXNlZC5oYXMoY2FuZGlkYXRlLmlkKSlcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdHMgPSBncm91cC5zb21lKG1lbWJlciA9PiBldmVudHNXaXRoaW5UaHJlc2hvbGQobWVtYmVyLCBjYW5kaWRhdGUsIHRocmVzaG9sZE1pbnV0ZXMpKTtcbiAgICAgICAgICAgICAgICBpZiAoY29ubmVjdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgZ3JvdXAucHVzaChjYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgICAgICB1c2VkLmFkZChjYW5kaWRhdGUuaWQpO1xuICAgICAgICAgICAgICAgICAgICBleHBhbmRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGdyb3Vwcy5wdXNoKGdyb3VwKTtcbiAgICB9XG4gICAgcmV0dXJuIGdyb3Vwcztcbn1cbi8qKlxuICogQ2FsY3VsYXRlIHN0YWNrIGxldmVscyBmb3Igb3ZlcmxhcHBpbmcgZXZlbnRzIHVzaW5nIGdyZWVkeSBhbGdvcml0aG1cbiAqIEZvciBlYWNoIGV2ZW50OiBsZXZlbCA9IG1heChvdmVybGFwcGluZyBhbHJlYWR5LXByb2Nlc3NlZCBldmVudHMpICsgMVxuICovXG5mdW5jdGlvbiBjYWxjdWxhdGVTdGFja0xldmVscyhldmVudHMpIHtcbiAgICBjb25zdCBsZXZlbHMgPSBuZXcgTWFwKCk7XG4gICAgY29uc3Qgc29ydGVkID0gWy4uLmV2ZW50c10uc29ydCgoYSwgYikgPT4gYS5zdGFydC5nZXRUaW1lKCkgLSBiLnN0YXJ0LmdldFRpbWUoKSk7XG4gICAgZm9yIChjb25zdCBldmVudCBvZiBzb3J0ZWQpIHtcbiAgICAgICAgbGV0IG1heE92ZXJsYXBwaW5nTGV2ZWwgPSAtMTtcbiAgICAgICAgLy8gRmluZCBtYXggbGV2ZWwgYW1vbmcgb3ZlcmxhcHBpbmcgZXZlbnRzIGFscmVhZHkgcHJvY2Vzc2VkXG4gICAgICAgIGZvciAoY29uc3QgW2lkLCBsZXZlbF0gb2YgbGV2ZWxzKSB7XG4gICAgICAgICAgICBjb25zdCBvdGhlciA9IGV2ZW50cy5maW5kKGUgPT4gZS5pZCA9PT0gaWQpO1xuICAgICAgICAgICAgaWYgKG90aGVyICYmIGV2ZW50c092ZXJsYXAoZXZlbnQsIG90aGVyKSkge1xuICAgICAgICAgICAgICAgIG1heE92ZXJsYXBwaW5nTGV2ZWwgPSBNYXRoLm1heChtYXhPdmVybGFwcGluZ0xldmVsLCBsZXZlbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbGV2ZWxzLnNldChldmVudC5pZCwgbWF4T3ZlcmxhcHBpbmdMZXZlbCArIDEpO1xuICAgIH1cbiAgICByZXR1cm4gbGV2ZWxzO1xufVxuLyoqXG4gKiBBbGxvY2F0ZSBldmVudHMgdG8gY29sdW1ucyBmb3IgR1JJRCBsYXlvdXQgdXNpbmcgZ3JlZWR5IGFsZ29yaXRobVxuICogTm9uLW92ZXJsYXBwaW5nIGV2ZW50cyBjYW4gc2hhcmUgYSBjb2x1bW4gdG8gbWluaW1pemUgdG90YWwgY29sdW1uc1xuICovXG5mdW5jdGlvbiBhbGxvY2F0ZUNvbHVtbnMoZXZlbnRzKSB7XG4gICAgY29uc3Qgc29ydGVkID0gWy4uLmV2ZW50c10uc29ydCgoYSwgYikgPT4gYS5zdGFydC5nZXRUaW1lKCkgLSBiLnN0YXJ0LmdldFRpbWUoKSk7XG4gICAgY29uc3QgY29sdW1ucyA9IFtdO1xuICAgIGZvciAoY29uc3QgZXZlbnQgb2Ygc29ydGVkKSB7XG4gICAgICAgIC8vIEZpbmQgZmlyc3QgY29sdW1uIHdoZXJlIGV2ZW50IGRvZXNuJ3Qgb3ZlcmxhcCB3aXRoIGV4aXN0aW5nIGV2ZW50c1xuICAgICAgICBsZXQgcGxhY2VkID0gZmFsc2U7XG4gICAgICAgIGZvciAoY29uc3QgY29sdW1uIG9mIGNvbHVtbnMpIHtcbiAgICAgICAgICAgIGNvbnN0IGNhbkZpdCA9ICFjb2x1bW4uc29tZShlID0+IGV2ZW50c092ZXJsYXAoZXZlbnQsIGUpKTtcbiAgICAgICAgICAgIGlmIChjYW5GaXQpIHtcbiAgICAgICAgICAgICAgICBjb2x1bW4ucHVzaChldmVudCk7XG4gICAgICAgICAgICAgICAgcGxhY2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBObyBzdWl0YWJsZSBjb2x1bW4gZm91bmQsIGNyZWF0ZSBuZXcgb25lXG4gICAgICAgIGlmICghcGxhY2VkKSB7XG4gICAgICAgICAgICBjb2x1bW5zLnB1c2goW2V2ZW50XSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGNvbHVtbnM7XG59XG4vKipcbiAqIE1haW4gZW50cnkgcG9pbnQ6IENhbGN1bGF0ZSBjb21wbGV0ZSBsYXlvdXQgZm9yIGEgY29sdW1uJ3MgZXZlbnRzXG4gKlxuICogQWxnb3JpdGhtOlxuICogMS4gRmluZCBvdmVybGFwIGdyb3VwcyAoZXZlbnRzIGNvbm5lY3RlZCBieSBvdmVybGFwIGNoYWluKVxuICogMi4gRm9yIGVhY2ggb3ZlcmxhcCBncm91cCwgZmluZCBncmlkIGNhbmRpZGF0ZXMgKGV2ZW50cyB3aXRoaW4gdGhyZXNob2xkIGNoYWluKVxuICogMy4gSWYgYWxsIGV2ZW50cyBpbiBvdmVybGFwIGdyb3VwIGZvcm0gYSBzaW5nbGUgZ3JpZCBjYW5kaWRhdGUgXHUyMTkyIEdSSUQgbW9kZVxuICogNC4gT3RoZXJ3aXNlIFx1MjE5MiBTVEFDS0lORyBtb2RlIHdpdGggY2FsY3VsYXRlZCBsZXZlbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZUNvbHVtbkxheW91dChldmVudHMsIGNvbmZpZykge1xuICAgIGNvbnN0IHRocmVzaG9sZE1pbnV0ZXMgPSBjb25maWcuZ3JpZFN0YXJ0VGhyZXNob2xkTWludXRlcyA/PyAxMDtcbiAgICBjb25zdCByZXN1bHQgPSB7XG4gICAgICAgIGdyaWRzOiBbXSxcbiAgICAgICAgc3RhY2tlZDogW11cbiAgICB9O1xuICAgIGlmIChldmVudHMubGVuZ3RoID09PSAwKVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIC8vIEZpbmQgYWxsIG92ZXJsYXBwaW5nIGV2ZW50IGdyb3Vwc1xuICAgIGNvbnN0IG92ZXJsYXBHcm91cHMgPSBmaW5kT3ZlcmxhcEdyb3VwcyhldmVudHMpO1xuICAgIGZvciAoY29uc3Qgb3ZlcmxhcEdyb3VwIG9mIG92ZXJsYXBHcm91cHMpIHtcbiAgICAgICAgaWYgKG92ZXJsYXBHcm91cC5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIC8vIFNpbmdsZSBldmVudCAtIG5vIGdyb3VwaW5nIG5lZWRlZFxuICAgICAgICAgICAgcmVzdWx0LnN0YWNrZWQucHVzaCh7XG4gICAgICAgICAgICAgICAgZXZlbnQ6IG92ZXJsYXBHcm91cFswXSxcbiAgICAgICAgICAgICAgICBzdGFja0xldmVsOiAwXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIFdpdGhpbiB0aGlzIG92ZXJsYXAgZ3JvdXAsIGZpbmQgZ3JpZCBjYW5kaWRhdGVzICh0aHJlc2hvbGQtY29ubmVjdGVkIHN1Ymdyb3VwcylcbiAgICAgICAgY29uc3QgZ3JpZFN1Ymdyb3VwcyA9IGZpbmRHcmlkQ2FuZGlkYXRlcyhvdmVybGFwR3JvdXAsIHRocmVzaG9sZE1pbnV0ZXMpO1xuICAgICAgICAvLyBDaGVjayBpZiB0aGUgRU5USVJFIG92ZXJsYXAgZ3JvdXAgZm9ybXMgYSBzaW5nbGUgZ3JpZCBjYW5kaWRhdGVcbiAgICAgICAgLy8gVGhpcyBoYXBwZW5zIHdoZW4gYWxsIGV2ZW50cyBhcmUgY29ubmVjdGVkIHZpYSB0aHJlc2hvbGQgY2hhaW5cbiAgICAgICAgY29uc3QgbGFyZ2VzdEdyaWRDYW5kaWRhdGUgPSBncmlkU3ViZ3JvdXBzLnJlZHVjZSgobWF4LCBnKSA9PiBnLmxlbmd0aCA+IG1heC5sZW5ndGggPyBnIDogbWF4LCBncmlkU3ViZ3JvdXBzWzBdKTtcbiAgICAgICAgaWYgKGxhcmdlc3RHcmlkQ2FuZGlkYXRlLmxlbmd0aCA9PT0gb3ZlcmxhcEdyb3VwLmxlbmd0aCkge1xuICAgICAgICAgICAgLy8gQWxsIGV2ZW50cyBpbiBvdmVybGFwIGdyb3VwIGFyZSBjb25uZWN0ZWQgdmlhIHRocmVzaG9sZCBjaGFpbiBcdTIxOTIgR1JJRCBtb2RlXG4gICAgICAgICAgICBjb25zdCBjb2x1bW5zID0gYWxsb2NhdGVDb2x1bW5zKG92ZXJsYXBHcm91cCk7XG4gICAgICAgICAgICBjb25zdCBlYXJsaWVzdCA9IG92ZXJsYXBHcm91cC5yZWR1Y2UoKG1pbiwgZSkgPT4gZS5zdGFydCA8IG1pbi5zdGFydCA/IGUgOiBtaW4sIG92ZXJsYXBHcm91cFswXSk7XG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbiA9IGNhbGN1bGF0ZUV2ZW50UG9zaXRpb24oZWFybGllc3Quc3RhcnQsIGVhcmxpZXN0LmVuZCwgY29uZmlnKTtcbiAgICAgICAgICAgIHJlc3VsdC5ncmlkcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBldmVudHM6IG92ZXJsYXBHcm91cCxcbiAgICAgICAgICAgICAgICBjb2x1bW5zLFxuICAgICAgICAgICAgICAgIHN0YWNrTGV2ZWw6IDAsXG4gICAgICAgICAgICAgICAgcG9zaXRpb246IHsgdG9wOiBwb3NpdGlvbi50b3AgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBOb3QgYWxsIGV2ZW50cyBjb25uZWN0ZWQgdmlhIHRocmVzaG9sZCBcdTIxOTIgU1RBQ0tJTkcgbW9kZVxuICAgICAgICAgICAgY29uc3QgbGV2ZWxzID0gY2FsY3VsYXRlU3RhY2tMZXZlbHMob3ZlcmxhcEdyb3VwKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgZXZlbnQgb2Ygb3ZlcmxhcEdyb3VwKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnN0YWNrZWQucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50LFxuICAgICAgICAgICAgICAgICAgICBzdGFja0xldmVsOiBsZXZlbHMuZ2V0KGV2ZW50LmlkKSA/PyAwXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbiIsICJpbXBvcnQgeyBjYWxjdWxhdGVFdmVudFBvc2l0aW9uLCBzbmFwVG9HcmlkLCBwaXhlbHNUb01pbnV0ZXMgfSBmcm9tICcuLi8uLi91dGlscy9Qb3NpdGlvblV0aWxzJztcbmltcG9ydCB7IENvcmVFdmVudHMgfSBmcm9tICcuLi8uLi9jb25zdGFudHMvQ29yZUV2ZW50cyc7XG5pbXBvcnQgeyBjYWxjdWxhdGVDb2x1bW5MYXlvdXQgfSBmcm9tICcuL0V2ZW50TGF5b3V0RW5naW5lJztcbi8qKlxuICogRXZlbnRSZW5kZXJlciAtIFJlbmRlcnMgY2FsZW5kYXIgZXZlbnRzIHRvIHRoZSBET01cbiAqXG4gKiBDTEVBTiBhcHByb2FjaDpcbiAqIC0gT25seSBkYXRhLWlkIGF0dHJpYnV0ZSBvbiBldmVudCBlbGVtZW50XG4gKiAtIGlubmVySFRNTCBjb250YWlucyBvbmx5IHZpc2libGUgY29udGVudFxuICogLSBFdmVudCBkYXRhIHJldHJpZXZlZCB2aWEgRXZlbnRTZXJ2aWNlIHdoZW4gbmVlZGVkXG4gKi9cbmV4cG9ydCBjbGFzcyBFdmVudFJlbmRlcmVyIHtcbiAgICBjb25zdHJ1Y3RvcihldmVudFNlcnZpY2UsIGRhdGVTZXJ2aWNlLCBncmlkQ29uZmlnLCBldmVudEJ1cykge1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZSA9IGV2ZW50U2VydmljZTtcbiAgICAgICAgdGhpcy5kYXRlU2VydmljZSA9IGRhdGVTZXJ2aWNlO1xuICAgICAgICB0aGlzLmdyaWRDb25maWcgPSBncmlkQ29uZmlnO1xuICAgICAgICB0aGlzLmV2ZW50QnVzID0gZXZlbnRCdXM7XG4gICAgICAgIHRoaXMuY29udGFpbmVyID0gbnVsbDtcbiAgICAgICAgdGhpcy5zZXR1cExpc3RlbmVycygpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZXR1cCBsaXN0ZW5lcnMgZm9yIGRyYWctZHJvcCBhbmQgdXBkYXRlIGV2ZW50c1xuICAgICAqL1xuICAgIHNldHVwTGlzdGVuZXJzKCkge1xuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENvcmVFdmVudHMuRVZFTlRfRFJBR19DT0xVTU5fQ0hBTkdFLCAoZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IGUuZGV0YWlsO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVDb2x1bW5DaGFuZ2UocGF5bG9hZCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENvcmVFdmVudHMuRVZFTlRfRFJBR19NT1ZFLCAoZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IGUuZGV0YWlsO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVEcmFnVGltZXN0YW1wKHBheWxvYWQpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5ldmVudEJ1cy5vbihDb3JlRXZlbnRzLkVWRU5UX1VQREFURUQsIChlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwYXlsb2FkID0gZS5kZXRhaWw7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZUV2ZW50VXBkYXRlZChwYXlsb2FkKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMub24oQ29yZUV2ZW50cy5FVkVOVF9EUkFHX0VORCwgKGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSBlLmRldGFpbDtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlRHJhZ0VuZChwYXlsb2FkKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMub24oQ29yZUV2ZW50cy5FVkVOVF9EUkFHX0xFQVZFX0hFQURFUiwgKGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSBlLmRldGFpbDtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlRHJhZ0xlYXZlSGVhZGVyKHBheWxvYWQpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSGFuZGxlIEVWRU5UX0RSQUdfRU5EIC0gcmVtb3ZlIGVsZW1lbnQgaWYgZHJvcHBlZCBpbiBoZWFkZXJcbiAgICAgKi9cbiAgICBoYW5kbGVEcmFnRW5kKHBheWxvYWQpIHtcbiAgICAgICAgaWYgKHBheWxvYWQudGFyZ2V0ID09PSAnaGVhZGVyJykge1xuICAgICAgICAgICAgLy8gRXZlbnQgd2FzIGRyb3BwZWQgaW4gaGVhZGVyIGRyYXdlciAtIHJlbW92ZSBmcm9tIGdyaWRcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLmNvbnRhaW5lcj8ucXVlcnlTZWxlY3Rvcihgc3dwLWNvbnRlbnQtdmlld3BvcnQgc3dwLWV2ZW50W2RhdGEtZXZlbnQtaWQ9XCIke3BheWxvYWQuc3dwRXZlbnQuZXZlbnRJZH1cIl1gKTtcbiAgICAgICAgICAgIGVsZW1lbnQ/LnJlbW92ZSgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEhhbmRsZSBoZWFkZXIgaXRlbSBsZWF2aW5nIGhlYWRlciAtIGNyZWF0ZSBzd3AtZXZlbnQgaW4gZ3JpZFxuICAgICAqL1xuICAgIGhhbmRsZURyYWdMZWF2ZUhlYWRlcihwYXlsb2FkKSB7XG4gICAgICAgIC8vIE9ubHkgaGFuZGxlIHdoZW4gc291cmNlIGlzIGhlYWRlciAoaGVhZGVyIGl0ZW0gZHJhZ2dlZCB0byBncmlkKVxuICAgICAgICBpZiAocGF5bG9hZC5zb3VyY2UgIT09ICdoZWFkZXInKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBpZiAoIXBheWxvYWQudGFyZ2V0Q29sdW1uIHx8ICFwYXlsb2FkLnN0YXJ0IHx8ICFwYXlsb2FkLmVuZClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgLy8gVHVybiBoZWFkZXIgaXRlbSBpbnRvIGdob3N0IChzdGF5cyB2aXNpYmxlIGJ1dCBmYWRlZClcbiAgICAgICAgaWYgKHBheWxvYWQuZWxlbWVudCkge1xuICAgICAgICAgICAgcGF5bG9hZC5lbGVtZW50LmNsYXNzTGlzdC5hZGQoJ2RyYWctZ2hvc3QnKTtcbiAgICAgICAgICAgIHBheWxvYWQuZWxlbWVudC5zdHlsZS5vcGFjaXR5ID0gJzAuMyc7XG4gICAgICAgICAgICBwYXlsb2FkLmVsZW1lbnQuc3R5bGUucG9pbnRlckV2ZW50cyA9ICdub25lJztcbiAgICAgICAgfVxuICAgICAgICAvLyBDcmVhdGUgZXZlbnQgb2JqZWN0IGZyb20gaGVhZGVyIGl0ZW0gZGF0YVxuICAgICAgICBjb25zdCBldmVudCA9IHtcbiAgICAgICAgICAgIGlkOiBwYXlsb2FkLmV2ZW50SWQsXG4gICAgICAgICAgICB0aXRsZTogcGF5bG9hZC50aXRsZSB8fCAnJyxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAnJyxcbiAgICAgICAgICAgIHN0YXJ0OiBwYXlsb2FkLnN0YXJ0LFxuICAgICAgICAgICAgZW5kOiBwYXlsb2FkLmVuZCxcbiAgICAgICAgICAgIHR5cGU6ICdjdXN0b21lcicsXG4gICAgICAgICAgICBhbGxEYXk6IGZhbHNlLFxuICAgICAgICAgICAgc3luY1N0YXR1czogJ3BlbmRpbmcnXG4gICAgICAgIH07XG4gICAgICAgIC8vIENyZWF0ZSBzd3AtZXZlbnQgZWxlbWVudCB1c2luZyBleGlzdGluZyBtZXRob2RcbiAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuY3JlYXRlRXZlbnRFbGVtZW50KGV2ZW50KTtcbiAgICAgICAgLy8gQWRkIHRvIHRhcmdldCBjb2x1bW5cbiAgICAgICAgbGV0IGV2ZW50c0xheWVyID0gcGF5bG9hZC50YXJnZXRDb2x1bW4ucXVlcnlTZWxlY3Rvcignc3dwLWV2ZW50cy1sYXllcicpO1xuICAgICAgICBpZiAoIWV2ZW50c0xheWVyKSB7XG4gICAgICAgICAgICBldmVudHNMYXllciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3N3cC1ldmVudHMtbGF5ZXInKTtcbiAgICAgICAgICAgIHBheWxvYWQudGFyZ2V0Q29sdW1uLmFwcGVuZENoaWxkKGV2ZW50c0xheWVyKTtcbiAgICAgICAgfVxuICAgICAgICBldmVudHNMYXllci5hcHBlbmRDaGlsZChlbGVtZW50KTtcbiAgICAgICAgLy8gTWFyayBhcyBkcmFnZ2luZyBzbyBEcmFnRHJvcE1hbmFnZXIgY2FuIGNvbnRpbnVlIHdpdGggaXRcbiAgICAgICAgZWxlbWVudC5jbGFzc0xpc3QuYWRkKCdkcmFnZ2luZycpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgRVZFTlRfVVBEQVRFRCAtIHJlLXJlbmRlciBhZmZlY3RlZCBjb2x1bW5zXG4gICAgICovXG4gICAgYXN5bmMgaGFuZGxlRXZlbnRVcGRhdGVkKHBheWxvYWQpIHtcbiAgICAgICAgLy8gUmUtcmVuZGVyIHNvdXJjZSBjb2x1bW4gKGlmIGRpZmZlcmVudCBmcm9tIHRhcmdldClcbiAgICAgICAgaWYgKHBheWxvYWQuc291cmNlQ29sdW1uS2V5ICE9PSBwYXlsb2FkLnRhcmdldENvbHVtbktleSkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5yZXJlbmRlckNvbHVtbihwYXlsb2FkLnNvdXJjZUNvbHVtbktleSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmUtcmVuZGVyIHRhcmdldCBjb2x1bW5cbiAgICAgICAgYXdhaXQgdGhpcy5yZXJlbmRlckNvbHVtbihwYXlsb2FkLnRhcmdldENvbHVtbktleSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlLXJlbmRlciBhIHNpbmdsZSBjb2x1bW4gd2l0aCBmcmVzaCBkYXRhIGZyb20gSW5kZXhlZERCXG4gICAgICovXG4gICAgYXN5bmMgcmVyZW5kZXJDb2x1bW4oY29sdW1uS2V5KSB7XG4gICAgICAgIGNvbnN0IGNvbHVtbiA9IHRoaXMuZmluZENvbHVtbihjb2x1bW5LZXkpO1xuICAgICAgICBpZiAoIWNvbHVtbilcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgLy8gUmVhZCBkYXRlIGFuZCByZXNvdXJjZUlkIGRpcmVjdGx5IGZyb20gY29sdW1uIGF0dHJpYnV0ZXMgKGNvbHVtbktleSBpcyBvcGFxdWUpXG4gICAgICAgIGNvbnN0IGRhdGUgPSBjb2x1bW4uZGF0YXNldC5kYXRlO1xuICAgICAgICBjb25zdCByZXNvdXJjZUlkID0gY29sdW1uLmRhdGFzZXQucmVzb3VyY2VJZDtcbiAgICAgICAgaWYgKCFkYXRlKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAvLyBHZXQgZGF0ZSByYW5nZSBmb3IgdGhpcyBkYXlcbiAgICAgICAgY29uc3Qgc3RhcnREYXRlID0gbmV3IERhdGUoZGF0ZSk7XG4gICAgICAgIGNvbnN0IGVuZERhdGUgPSBuZXcgRGF0ZShkYXRlKTtcbiAgICAgICAgZW5kRGF0ZS5zZXRIb3VycygyMywgNTksIDU5LCA5OTkpO1xuICAgICAgICAvLyBGZXRjaCBldmVudHMgZnJvbSBJbmRleGVkREJcbiAgICAgICAgY29uc3QgZXZlbnRzID0gcmVzb3VyY2VJZFxuICAgICAgICAgICAgPyBhd2FpdCB0aGlzLmV2ZW50U2VydmljZS5nZXRCeVJlc291cmNlQW5kRGF0ZVJhbmdlKHJlc291cmNlSWQsIHN0YXJ0RGF0ZSwgZW5kRGF0ZSlcbiAgICAgICAgICAgIDogYXdhaXQgdGhpcy5ldmVudFNlcnZpY2UuZ2V0QnlEYXRlUmFuZ2Uoc3RhcnREYXRlLCBlbmREYXRlKTtcbiAgICAgICAgLy8gRmlsdGVyIHRvIHRpbWVkIGV2ZW50cyBhbmQgbWF0Y2ggZGF0ZSBleGFjdGx5XG4gICAgICAgIGNvbnN0IHRpbWVkRXZlbnRzID0gZXZlbnRzLmZpbHRlcihldmVudCA9PiAhZXZlbnQuYWxsRGF5ICYmIHRoaXMuZGF0ZVNlcnZpY2UuZ2V0RGF0ZUtleShldmVudC5zdGFydCkgPT09IGRhdGUpO1xuICAgICAgICAvLyBHZXQgb3IgY3JlYXRlIGV2ZW50cyBsYXllclxuICAgICAgICBsZXQgZXZlbnRzTGF5ZXIgPSBjb2x1bW4ucXVlcnlTZWxlY3Rvcignc3dwLWV2ZW50cy1sYXllcicpO1xuICAgICAgICBpZiAoIWV2ZW50c0xheWVyKSB7XG4gICAgICAgICAgICBldmVudHNMYXllciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3N3cC1ldmVudHMtbGF5ZXInKTtcbiAgICAgICAgICAgIGNvbHVtbi5hcHBlbmRDaGlsZChldmVudHNMYXllcik7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ2xlYXIgZXhpc3RpbmcgZXZlbnRzXG4gICAgICAgIGV2ZW50c0xheWVyLmlubmVySFRNTCA9ICcnO1xuICAgICAgICAvLyBDYWxjdWxhdGUgbGF5b3V0IHdpdGggc3RhY2tpbmcvZ3JvdXBpbmdcbiAgICAgICAgY29uc3QgbGF5b3V0ID0gY2FsY3VsYXRlQ29sdW1uTGF5b3V0KHRpbWVkRXZlbnRzLCB0aGlzLmdyaWRDb25maWcpO1xuICAgICAgICAvLyBSZW5kZXIgR1JJRCBncm91cHNcbiAgICAgICAgbGF5b3V0LmdyaWRzLmZvckVhY2goZ3JpZCA9PiB7XG4gICAgICAgICAgICBjb25zdCBncm91cEVsID0gdGhpcy5yZW5kZXJHcmlkR3JvdXAoZ3JpZCk7XG4gICAgICAgICAgICBldmVudHNMYXllci5hcHBlbmRDaGlsZChncm91cEVsKTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIFJlbmRlciBTVEFDS0VEIGV2ZW50c1xuICAgICAgICBsYXlvdXQuc3RhY2tlZC5mb3JFYWNoKGl0ZW0gPT4ge1xuICAgICAgICAgICAgY29uc3QgZXZlbnRFbCA9IHRoaXMucmVuZGVyU3RhY2tlZEV2ZW50KGl0ZW0uZXZlbnQsIGl0ZW0uc3RhY2tMZXZlbCk7XG4gICAgICAgICAgICBldmVudHNMYXllci5hcHBlbmRDaGlsZChldmVudEVsKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEZpbmQgYSBjb2x1bW4gZWxlbWVudCBieSBjb2x1bW5LZXlcbiAgICAgKi9cbiAgICBmaW5kQ29sdW1uKGNvbHVtbktleSkge1xuICAgICAgICBpZiAoIXRoaXMuY29udGFpbmVyKVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKGBzd3AtZGF5LWNvbHVtbltkYXRhLWNvbHVtbi1rZXk9XCIke2NvbHVtbktleX1cIl1gKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSGFuZGxlIGV2ZW50IG1vdmluZyB0byBhIG5ldyBjb2x1bW4gZHVyaW5nIGRyYWdcbiAgICAgKi9cbiAgICBoYW5kbGVDb2x1bW5DaGFuZ2UocGF5bG9hZCkge1xuICAgICAgICBjb25zdCBldmVudHNMYXllciA9IHBheWxvYWQubmV3Q29sdW1uLnF1ZXJ5U2VsZWN0b3IoJ3N3cC1ldmVudHMtbGF5ZXInKTtcbiAgICAgICAgaWYgKCFldmVudHNMYXllcilcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgLy8gTW92ZSBlbGVtZW50IHRvIG5ldyBjb2x1bW5cbiAgICAgICAgZXZlbnRzTGF5ZXIuYXBwZW5kQ2hpbGQocGF5bG9hZC5lbGVtZW50KTtcbiAgICAgICAgLy8gUHJlc2VydmUgWSBwb3NpdGlvblxuICAgICAgICBwYXlsb2FkLmVsZW1lbnQuc3R5bGUudG9wID0gYCR7cGF5bG9hZC5jdXJyZW50WX1weGA7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSB0aW1lc3RhbXAgZGlzcGxheSBkdXJpbmcgZHJhZyAoc25hcHBlZCB0byBncmlkKVxuICAgICAqL1xuICAgIHVwZGF0ZURyYWdUaW1lc3RhbXAocGF5bG9hZCkge1xuICAgICAgICBjb25zdCB0aW1lRWwgPSBwYXlsb2FkLmVsZW1lbnQucXVlcnlTZWxlY3Rvcignc3dwLWV2ZW50LXRpbWUnKTtcbiAgICAgICAgaWYgKCF0aW1lRWwpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIC8vIFNuYXAgcG9zaXRpb24gdG8gZ3JpZCBpbnRlcnZhbFxuICAgICAgICBjb25zdCBzbmFwcGVkWSA9IHNuYXBUb0dyaWQocGF5bG9hZC5jdXJyZW50WSwgdGhpcy5ncmlkQ29uZmlnKTtcbiAgICAgICAgLy8gQ2FsY3VsYXRlIG5ldyBzdGFydCB0aW1lXG4gICAgICAgIGNvbnN0IG1pbnV0ZXNGcm9tR3JpZFN0YXJ0ID0gcGl4ZWxzVG9NaW51dGVzKHNuYXBwZWRZLCB0aGlzLmdyaWRDb25maWcpO1xuICAgICAgICBjb25zdCBzdGFydE1pbnV0ZXMgPSAodGhpcy5ncmlkQ29uZmlnLmRheVN0YXJ0SG91ciAqIDYwKSArIG1pbnV0ZXNGcm9tR3JpZFN0YXJ0O1xuICAgICAgICAvLyBLZWVwIG9yaWdpbmFsIGR1cmF0aW9uIChmcm9tIGVsZW1lbnQgaGVpZ2h0KVxuICAgICAgICBjb25zdCBoZWlnaHQgPSBwYXJzZUZsb2F0KHBheWxvYWQuZWxlbWVudC5zdHlsZS5oZWlnaHQpIHx8IHRoaXMuZ3JpZENvbmZpZy5ob3VySGVpZ2h0O1xuICAgICAgICBjb25zdCBkdXJhdGlvbk1pbnV0ZXMgPSBwaXhlbHNUb01pbnV0ZXMoaGVpZ2h0LCB0aGlzLmdyaWRDb25maWcpO1xuICAgICAgICAvLyBDcmVhdGUgRGF0ZSBvYmplY3RzIGZvciBjb25zaXN0ZW50IGZvcm1hdHRpbmcgdmlhIERhdGVTZXJ2aWNlXG4gICAgICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5taW51dGVzVG9EYXRlKHN0YXJ0TWludXRlcyk7XG4gICAgICAgIGNvbnN0IGVuZCA9IHRoaXMubWludXRlc1RvRGF0ZShzdGFydE1pbnV0ZXMgKyBkdXJhdGlvbk1pbnV0ZXMpO1xuICAgICAgICB0aW1lRWwudGV4dENvbnRlbnQgPSB0aGlzLmRhdGVTZXJ2aWNlLmZvcm1hdFRpbWVSYW5nZShzdGFydCwgZW5kKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ29udmVydCBtaW51dGVzIHNpbmNlIG1pZG5pZ2h0IHRvIGEgRGF0ZSBvYmplY3QgKHRvZGF5KVxuICAgICAqL1xuICAgIG1pbnV0ZXNUb0RhdGUobWludXRlcykge1xuICAgICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoKTtcbiAgICAgICAgZGF0ZS5zZXRIb3VycyhNYXRoLmZsb29yKG1pbnV0ZXMgLyA2MCkgJSAyNCwgbWludXRlcyAlIDYwLCAwLCAwKTtcbiAgICAgICAgcmV0dXJuIGRhdGU7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlbmRlciBldmVudHMgZm9yIHZpc2libGUgZGF0ZXMgaW50byBkYXkgY29sdW1uc1xuICAgICAqIEBwYXJhbSBjb250YWluZXIgLSBDYWxlbmRhciBjb250YWluZXIgZWxlbWVudFxuICAgICAqIEBwYXJhbSBmaWx0ZXIgLSBGaWx0ZXIgd2l0aCAnZGF0ZScgYW5kIG9wdGlvbmFsbHkgJ3Jlc291cmNlJyBhcnJheXNcbiAgICAgKiBAcGFyYW0gZmlsdGVyVGVtcGxhdGUgLSBUZW1wbGF0ZSBmb3IgbWF0Y2hpbmcgZXZlbnRzIHRvIGNvbHVtbnNcbiAgICAgKi9cbiAgICBhc3luYyByZW5kZXIoY29udGFpbmVyLCBmaWx0ZXIsIGZpbHRlclRlbXBsYXRlKSB7XG4gICAgICAgIC8vIFN0b3JlIGNvbnRhaW5lciByZWZlcmVuY2UgZm9yIGxhdGVyIHJlLXJlbmRlcnNcbiAgICAgICAgdGhpcy5jb250YWluZXIgPSBjb250YWluZXI7XG4gICAgICAgIGNvbnN0IHZpc2libGVEYXRlcyA9IGZpbHRlclsnZGF0ZSddIHx8IFtdO1xuICAgICAgICBpZiAodmlzaWJsZURhdGVzLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgLy8gR2V0IGRhdGUgcmFuZ2UgZm9yIHF1ZXJ5XG4gICAgICAgIGNvbnN0IHN0YXJ0RGF0ZSA9IG5ldyBEYXRlKHZpc2libGVEYXRlc1swXSk7XG4gICAgICAgIGNvbnN0IGVuZERhdGUgPSBuZXcgRGF0ZSh2aXNpYmxlRGF0ZXNbdmlzaWJsZURhdGVzLmxlbmd0aCAtIDFdKTtcbiAgICAgICAgZW5kRGF0ZS5zZXRIb3VycygyMywgNTksIDU5LCA5OTkpO1xuICAgICAgICAvLyBGZXRjaCBldmVudHMgZnJvbSBJbmRleGVkREJcbiAgICAgICAgY29uc3QgZXZlbnRzID0gYXdhaXQgdGhpcy5ldmVudFNlcnZpY2UuZ2V0QnlEYXRlUmFuZ2Uoc3RhcnREYXRlLCBlbmREYXRlKTtcbiAgICAgICAgLy8gRmluZCBkYXkgY29sdW1uc1xuICAgICAgICBjb25zdCBkYXlDb2x1bW5zID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJ3N3cC1kYXktY29sdW1ucycpO1xuICAgICAgICBpZiAoIWRheUNvbHVtbnMpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNvbnN0IGNvbHVtbnMgPSBkYXlDb2x1bW5zLnF1ZXJ5U2VsZWN0b3JBbGwoJ3N3cC1kYXktY29sdW1uJyk7XG4gICAgICAgIC8vIFJlbmRlciBldmVudHMgaW50byBlYWNoIGNvbHVtbiBiYXNlZCBvbiBGaWx0ZXJUZW1wbGF0ZSBtYXRjaGluZ1xuICAgICAgICBjb2x1bW5zLmZvckVhY2goY29sdW1uID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbHVtbkVsID0gY29sdW1uO1xuICAgICAgICAgICAgLy8gVXNlIEZpbHRlclRlbXBsYXRlIGZvciBtYXRjaGluZyAtIG9ubHkgZmllbGRzIGluIHRlbXBsYXRlIGFyZSBjaGVja2VkXG4gICAgICAgICAgICBjb25zdCBjb2x1bW5FdmVudHMgPSBldmVudHMuZmlsdGVyKGV2ZW50ID0+IGZpbHRlclRlbXBsYXRlLm1hdGNoZXMoZXZlbnQsIGNvbHVtbkVsKSk7XG4gICAgICAgICAgICAvLyBHZXQgb3IgY3JlYXRlIGV2ZW50cyBsYXllclxuICAgICAgICAgICAgbGV0IGV2ZW50c0xheWVyID0gY29sdW1uLnF1ZXJ5U2VsZWN0b3IoJ3N3cC1ldmVudHMtbGF5ZXInKTtcbiAgICAgICAgICAgIGlmICghZXZlbnRzTGF5ZXIpIHtcbiAgICAgICAgICAgICAgICBldmVudHNMYXllciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3N3cC1ldmVudHMtbGF5ZXInKTtcbiAgICAgICAgICAgICAgICBjb2x1bW4uYXBwZW5kQ2hpbGQoZXZlbnRzTGF5ZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQ2xlYXIgZXhpc3RpbmcgZXZlbnRzXG4gICAgICAgICAgICBldmVudHNMYXllci5pbm5lckhUTUwgPSAnJztcbiAgICAgICAgICAgIC8vIEZpbHRlciB0byB0aW1lZCBldmVudHMgb25seVxuICAgICAgICAgICAgY29uc3QgdGltZWRFdmVudHMgPSBjb2x1bW5FdmVudHMuZmlsdGVyKGV2ZW50ID0+ICFldmVudC5hbGxEYXkpO1xuICAgICAgICAgICAgLy8gQ2FsY3VsYXRlIGxheW91dCB3aXRoIHN0YWNraW5nL2dyb3VwaW5nXG4gICAgICAgICAgICBjb25zdCBsYXlvdXQgPSBjYWxjdWxhdGVDb2x1bW5MYXlvdXQodGltZWRFdmVudHMsIHRoaXMuZ3JpZENvbmZpZyk7XG4gICAgICAgICAgICAvLyBSZW5kZXIgR1JJRCBncm91cHMgKHNpbXVsdGFuZW91cyBldmVudHMgc2lkZS1ieS1zaWRlKVxuICAgICAgICAgICAgbGF5b3V0LmdyaWRzLmZvckVhY2goZ3JpZCA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZ3JvdXBFbCA9IHRoaXMucmVuZGVyR3JpZEdyb3VwKGdyaWQpO1xuICAgICAgICAgICAgICAgIGV2ZW50c0xheWVyLmFwcGVuZENoaWxkKGdyb3VwRWwpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAvLyBSZW5kZXIgU1RBQ0tFRCBldmVudHMgKG92ZXJsYXBwaW5nIHdpdGggbWFyZ2luIG9mZnNldClcbiAgICAgICAgICAgIGxheW91dC5zdGFja2VkLmZvckVhY2goaXRlbSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXZlbnRFbCA9IHRoaXMucmVuZGVyU3RhY2tlZEV2ZW50KGl0ZW0uZXZlbnQsIGl0ZW0uc3RhY2tMZXZlbCk7XG4gICAgICAgICAgICAgICAgZXZlbnRzTGF5ZXIuYXBwZW5kQ2hpbGQoZXZlbnRFbCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIHNpbmdsZSBldmVudCBlbGVtZW50XG4gICAgICpcbiAgICAgKiBDTEVBTiBhcHByb2FjaDpcbiAgICAgKiAtIE9ubHkgZGF0YS1pZCBmb3IgbG9va3VwXG4gICAgICogLSBWaXNpYmxlIGNvbnRlbnQgaW4gaW5uZXJIVE1MIG9ubHlcbiAgICAgKi9cbiAgICBjcmVhdGVFdmVudEVsZW1lbnQoZXZlbnQpIHtcbiAgICAgICAgY29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3N3cC1ldmVudCcpO1xuICAgICAgICAvLyBEYXRhIGF0dHJpYnV0ZXMgZm9yIFN3cEV2ZW50IGNvbXBhdGliaWxpdHlcbiAgICAgICAgZWxlbWVudC5kYXRhc2V0LmV2ZW50SWQgPSBldmVudC5pZDtcbiAgICAgICAgaWYgKGV2ZW50LnJlc291cmNlSWQpIHtcbiAgICAgICAgICAgIGVsZW1lbnQuZGF0YXNldC5yZXNvdXJjZUlkID0gZXZlbnQucmVzb3VyY2VJZDtcbiAgICAgICAgfVxuICAgICAgICAvLyBDYWxjdWxhdGUgcG9zaXRpb25cbiAgICAgICAgY29uc3QgcG9zaXRpb24gPSBjYWxjdWxhdGVFdmVudFBvc2l0aW9uKGV2ZW50LnN0YXJ0LCBldmVudC5lbmQsIHRoaXMuZ3JpZENvbmZpZyk7XG4gICAgICAgIGVsZW1lbnQuc3R5bGUudG9wID0gYCR7cG9zaXRpb24udG9wfXB4YDtcbiAgICAgICAgZWxlbWVudC5zdHlsZS5oZWlnaHQgPSBgJHtwb3NpdGlvbi5oZWlnaHR9cHhgO1xuICAgICAgICAvLyBDb2xvciBjbGFzcyBiYXNlZCBvbiBldmVudCB0eXBlXG4gICAgICAgIGNvbnN0IGNvbG9yQ2xhc3MgPSB0aGlzLmdldENvbG9yQ2xhc3MoZXZlbnQpO1xuICAgICAgICBpZiAoY29sb3JDbGFzcykge1xuICAgICAgICAgICAgZWxlbWVudC5jbGFzc0xpc3QuYWRkKGNvbG9yQ2xhc3MpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFZpc2libGUgY29udGVudCBvbmx5XG4gICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gYFxyXG4gICAgICA8c3dwLWV2ZW50LXRpbWU+JHt0aGlzLmRhdGVTZXJ2aWNlLmZvcm1hdFRpbWVSYW5nZShldmVudC5zdGFydCwgZXZlbnQuZW5kKX08L3N3cC1ldmVudC10aW1lPlxyXG4gICAgICA8c3dwLWV2ZW50LXRpdGxlPiR7dGhpcy5lc2NhcGVIdG1sKGV2ZW50LnRpdGxlKX08L3N3cC1ldmVudC10aXRsZT5cclxuICAgICAgJHtldmVudC5kZXNjcmlwdGlvbiA/IGA8c3dwLWV2ZW50LWRlc2NyaXB0aW9uPiR7dGhpcy5lc2NhcGVIdG1sKGV2ZW50LmRlc2NyaXB0aW9uKX08L3N3cC1ldmVudC1kZXNjcmlwdGlvbj5gIDogJyd9XHJcbiAgICBgO1xuICAgICAgICByZXR1cm4gZWxlbWVudDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGNvbG9yIGNsYXNzIGJhc2VkIG9uIG1ldGFkYXRhLmNvbG9yIG9yIGV2ZW50IHR5cGVcbiAgICAgKi9cbiAgICBnZXRDb2xvckNsYXNzKGV2ZW50KSB7XG4gICAgICAgIC8vIENoZWNrIG1ldGFkYXRhLmNvbG9yIGZpcnN0XG4gICAgICAgIGlmIChldmVudC5tZXRhZGF0YT8uY29sb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBgaXMtJHtldmVudC5tZXRhZGF0YS5jb2xvcn1gO1xuICAgICAgICB9XG4gICAgICAgIC8vIEZhbGxiYWNrIHRvIHR5cGUtYmFzZWQgY29sb3JcbiAgICAgICAgY29uc3QgdHlwZUNvbG9ycyA9IHtcbiAgICAgICAgICAgICdjdXN0b21lcic6ICdpcy1ibHVlJyxcbiAgICAgICAgICAgICd2YWNhdGlvbic6ICdpcy1ncmVlbicsXG4gICAgICAgICAgICAnYnJlYWsnOiAnaXMtYW1iZXInLFxuICAgICAgICAgICAgJ21lZXRpbmcnOiAnaXMtcHVycGxlJyxcbiAgICAgICAgICAgICdibG9ja2VkJzogJ2lzLXJlZCdcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHR5cGVDb2xvcnNbZXZlbnQudHlwZV0gfHwgJ2lzLWJsdWUnO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBFc2NhcGUgSFRNTCB0byBwcmV2ZW50IFhTU1xuICAgICAqL1xuICAgIGVzY2FwZUh0bWwodGV4dCkge1xuICAgICAgICBjb25zdCBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgZGl2LnRleHRDb250ZW50ID0gdGV4dDtcbiAgICAgICAgcmV0dXJuIGRpdi5pbm5lckhUTUw7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlbmRlciBhIEdSSUQgZ3JvdXAgd2l0aCBzaWRlLWJ5LXNpZGUgY29sdW1uc1xuICAgICAqIFVzZWQgd2hlbiBtdWx0aXBsZSBldmVudHMgc3RhcnQgYXQgdGhlIHNhbWUgdGltZVxuICAgICAqL1xuICAgIHJlbmRlckdyaWRHcm91cChsYXlvdXQpIHtcbiAgICAgICAgY29uc3QgZ3JvdXAgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzd3AtZXZlbnQtZ3JvdXAnKTtcbiAgICAgICAgZ3JvdXAuY2xhc3NMaXN0LmFkZChgY29scy0ke2xheW91dC5jb2x1bW5zLmxlbmd0aH1gKTtcbiAgICAgICAgZ3JvdXAuc3R5bGUudG9wID0gYCR7bGF5b3V0LnBvc2l0aW9uLnRvcH1weGA7XG4gICAgICAgIC8vIFN0YWNrIGxldmVsIHN0eWxpbmcgZm9yIGVudGlyZSBncm91cCAoaWYgbmVzdGVkIGluIGFub3RoZXIgZXZlbnQpXG4gICAgICAgIGlmIChsYXlvdXQuc3RhY2tMZXZlbCA+IDApIHtcbiAgICAgICAgICAgIGdyb3VwLnN0eWxlLm1hcmdpbkxlZnQgPSBgJHtsYXlvdXQuc3RhY2tMZXZlbCAqIDE1fXB4YDtcbiAgICAgICAgICAgIGdyb3VwLnN0eWxlLnpJbmRleCA9IGAkezEwMCArIGxheW91dC5zdGFja0xldmVsfWA7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBoZWlnaHQgbmVlZGVkIGZvciB0aGUgZ3JvdXAgKHRhbGxlc3QgZXZlbnQpXG4gICAgICAgIGxldCBtYXhCb3R0b20gPSAwO1xuICAgICAgICBmb3IgKGNvbnN0IGV2ZW50IG9mIGxheW91dC5ldmVudHMpIHtcbiAgICAgICAgICAgIGNvbnN0IHBvcyA9IGNhbGN1bGF0ZUV2ZW50UG9zaXRpb24oZXZlbnQuc3RhcnQsIGV2ZW50LmVuZCwgdGhpcy5ncmlkQ29uZmlnKTtcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50Qm90dG9tID0gcG9zLnRvcCArIHBvcy5oZWlnaHQ7XG4gICAgICAgICAgICBpZiAoZXZlbnRCb3R0b20gPiBtYXhCb3R0b20pXG4gICAgICAgICAgICAgICAgbWF4Qm90dG9tID0gZXZlbnRCb3R0b207XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZ3JvdXBIZWlnaHQgPSBtYXhCb3R0b20gLSBsYXlvdXQucG9zaXRpb24udG9wO1xuICAgICAgICBncm91cC5zdHlsZS5oZWlnaHQgPSBgJHtncm91cEhlaWdodH1weGA7XG4gICAgICAgIC8vIENyZWF0ZSB3cmFwcGVyIGRpdiBmb3IgZWFjaCBjb2x1bW5cbiAgICAgICAgbGF5b3V0LmNvbHVtbnMuZm9yRWFjaChjb2x1bW5FdmVudHMgPT4ge1xuICAgICAgICAgICAgY29uc3Qgd3JhcHBlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICAgICAgd3JhcHBlci5zdHlsZS5wb3NpdGlvbiA9ICdyZWxhdGl2ZSc7XG4gICAgICAgICAgICBjb2x1bW5FdmVudHMuZm9yRWFjaChldmVudCA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXZlbnRFbCA9IHRoaXMuY3JlYXRlRXZlbnRFbGVtZW50KGV2ZW50KTtcbiAgICAgICAgICAgICAgICAvLyBQb3NpdGlvbiByZWxhdGl2ZSB0byBncm91cCB0b3BcbiAgICAgICAgICAgICAgICBjb25zdCBwb3MgPSBjYWxjdWxhdGVFdmVudFBvc2l0aW9uKGV2ZW50LnN0YXJ0LCBldmVudC5lbmQsIHRoaXMuZ3JpZENvbmZpZyk7XG4gICAgICAgICAgICAgICAgZXZlbnRFbC5zdHlsZS50b3AgPSBgJHtwb3MudG9wIC0gbGF5b3V0LnBvc2l0aW9uLnRvcH1weGA7XG4gICAgICAgICAgICAgICAgZXZlbnRFbC5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgICAgICAgICAgICAgZXZlbnRFbC5zdHlsZS5sZWZ0ID0gJzAnO1xuICAgICAgICAgICAgICAgIGV2ZW50RWwuc3R5bGUucmlnaHQgPSAnMCc7XG4gICAgICAgICAgICAgICAgd3JhcHBlci5hcHBlbmRDaGlsZChldmVudEVsKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZ3JvdXAuYXBwZW5kQ2hpbGQod3JhcHBlcik7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gZ3JvdXA7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlbmRlciBhIFNUQUNLRUQgZXZlbnQgd2l0aCBtYXJnaW4tbGVmdCBvZmZzZXRcbiAgICAgKiBVc2VkIGZvciBvdmVybGFwcGluZyBldmVudHMgdGhhdCBkb24ndCBzdGFydCBhdCB0aGUgc2FtZSB0aW1lXG4gICAgICovXG4gICAgcmVuZGVyU3RhY2tlZEV2ZW50KGV2ZW50LCBzdGFja0xldmVsKSB7XG4gICAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLmNyZWF0ZUV2ZW50RWxlbWVudChldmVudCk7XG4gICAgICAgIC8vIEFkZCBzdGFjayBtZXRhZGF0YSBmb3IgZHJhZy1kcm9wIGFuZCBvdGhlciBmZWF0dXJlc1xuICAgICAgICBlbGVtZW50LmRhdGFzZXQuc3RhY2tMaW5rID0gSlNPTi5zdHJpbmdpZnkoeyBzdGFja0xldmVsIH0pO1xuICAgICAgICAvLyBWaXN1YWwgc3R5bGluZyBiYXNlZCBvbiBzdGFjayBsZXZlbFxuICAgICAgICBpZiAoc3RhY2tMZXZlbCA+IDApIHtcbiAgICAgICAgICAgIGVsZW1lbnQuc3R5bGUubWFyZ2luTGVmdCA9IGAke3N0YWNrTGV2ZWwgKiAxNX1weGA7XG4gICAgICAgICAgICBlbGVtZW50LnN0eWxlLnpJbmRleCA9IGAkezEwMCArIHN0YWNrTGV2ZWx9YDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZWxlbWVudDtcbiAgICB9XG59XG4iLCAiLyoqXG4gKiBTY2hlZHVsZVJlbmRlcmVyIC0gUmVuZGVycyB1bmF2YWlsYWJsZSB0aW1lIHpvbmVzIGluIGRheSBjb2x1bW5zXG4gKlxuICogQ3JlYXRlcyB2aXN1YWwgaW5kaWNhdG9ycyBmb3IgdGltZXMgb3V0c2lkZSB0aGUgcmVzb3VyY2UncyB3b3JraW5nIGhvdXJzOlxuICogLSBCZWZvcmUgd29yayBzdGFydCAoZS5nLiwgMDY6MDAgLSAwOTowMClcbiAqIC0gQWZ0ZXIgd29yayBlbmQgKGUuZy4sIDE3OjAwIC0gMTg6MDApXG4gKiAtIEZ1bGwgZGF5IGlmIHJlc291cmNlIGlzIG9mZiAoc2NoZWR1bGUgPSBudWxsKVxuICovXG5leHBvcnQgY2xhc3MgU2NoZWR1bGVSZW5kZXJlciB7XG4gICAgY29uc3RydWN0b3Ioc2NoZWR1bGVTZXJ2aWNlLCBkYXRlU2VydmljZSwgZ3JpZENvbmZpZykge1xuICAgICAgICB0aGlzLnNjaGVkdWxlU2VydmljZSA9IHNjaGVkdWxlU2VydmljZTtcbiAgICAgICAgdGhpcy5kYXRlU2VydmljZSA9IGRhdGVTZXJ2aWNlO1xuICAgICAgICB0aGlzLmdyaWRDb25maWcgPSBncmlkQ29uZmlnO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZW5kZXIgdW5hdmFpbGFibGUgem9uZXMgZm9yIHZpc2libGUgY29sdW1uc1xuICAgICAqIEBwYXJhbSBjb250YWluZXIgLSBDYWxlbmRhciBjb250YWluZXIgZWxlbWVudFxuICAgICAqIEBwYXJhbSBmaWx0ZXIgLSBGaWx0ZXIgd2l0aCAnZGF0ZScgYW5kICdyZXNvdXJjZScgYXJyYXlzXG4gICAgICovXG4gICAgYXN5bmMgcmVuZGVyKGNvbnRhaW5lciwgZmlsdGVyKSB7XG4gICAgICAgIGNvbnN0IGRhdGVzID0gZmlsdGVyWydkYXRlJ10gfHwgW107XG4gICAgICAgIGNvbnN0IHJlc291cmNlSWRzID0gZmlsdGVyWydyZXNvdXJjZSddIHx8IFtdO1xuICAgICAgICBpZiAoZGF0ZXMubGVuZ3RoID09PSAwKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAvLyBGaW5kIGRheSBjb2x1bW5zXG4gICAgICAgIGNvbnN0IGRheUNvbHVtbnMgPSBjb250YWluZXIucXVlcnlTZWxlY3Rvcignc3dwLWRheS1jb2x1bW5zJyk7XG4gICAgICAgIGlmICghZGF5Q29sdW1ucylcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY29uc3QgY29sdW1ucyA9IGRheUNvbHVtbnMucXVlcnlTZWxlY3RvckFsbCgnc3dwLWRheS1jb2x1bW4nKTtcbiAgICAgICAgZm9yIChjb25zdCBjb2x1bW4gb2YgY29sdW1ucykge1xuICAgICAgICAgICAgY29uc3QgZGF0ZSA9IGNvbHVtbi5kYXRhc2V0LmRhdGU7XG4gICAgICAgICAgICBjb25zdCByZXNvdXJjZUlkID0gY29sdW1uLmRhdGFzZXQucmVzb3VyY2VJZDtcbiAgICAgICAgICAgIGlmICghZGF0ZSB8fCAhcmVzb3VyY2VJZClcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIC8vIEdldCBvciBjcmVhdGUgdW5hdmFpbGFibGUgbGF5ZXJcbiAgICAgICAgICAgIGxldCB1bmF2YWlsYWJsZUxheWVyID0gY29sdW1uLnF1ZXJ5U2VsZWN0b3IoJ3N3cC11bmF2YWlsYWJsZS1sYXllcicpO1xuICAgICAgICAgICAgaWYgKCF1bmF2YWlsYWJsZUxheWVyKSB7XG4gICAgICAgICAgICAgICAgdW5hdmFpbGFibGVMYXllciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3N3cC11bmF2YWlsYWJsZS1sYXllcicpO1xuICAgICAgICAgICAgICAgIGNvbHVtbi5pbnNlcnRCZWZvcmUodW5hdmFpbGFibGVMYXllciwgY29sdW1uLmZpcnN0Q2hpbGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQ2xlYXIgZXhpc3RpbmdcbiAgICAgICAgICAgIHVuYXZhaWxhYmxlTGF5ZXIuaW5uZXJIVE1MID0gJyc7XG4gICAgICAgICAgICAvLyBHZXQgc2NoZWR1bGUgZm9yIHRoaXMgcmVzb3VyY2UvZGF0ZVxuICAgICAgICAgICAgY29uc3Qgc2NoZWR1bGUgPSBhd2FpdCB0aGlzLnNjaGVkdWxlU2VydmljZS5nZXRTY2hlZHVsZUZvckRhdGUocmVzb3VyY2VJZCwgZGF0ZSk7XG4gICAgICAgICAgICAvLyBSZW5kZXIgdW5hdmFpbGFibGUgem9uZXNcbiAgICAgICAgICAgIHRoaXMucmVuZGVyVW5hdmFpbGFibGVab25lcyh1bmF2YWlsYWJsZUxheWVyLCBzY2hlZHVsZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVuZGVyIHVuYXZhaWxhYmxlIHRpbWUgem9uZXMgYmFzZWQgb24gc2NoZWR1bGVcbiAgICAgKi9cbiAgICByZW5kZXJVbmF2YWlsYWJsZVpvbmVzKGxheWVyLCBzY2hlZHVsZSkge1xuICAgICAgICBjb25zdCBkYXlTdGFydE1pbnV0ZXMgPSB0aGlzLmdyaWRDb25maWcuZGF5U3RhcnRIb3VyICogNjA7XG4gICAgICAgIGNvbnN0IGRheUVuZE1pbnV0ZXMgPSB0aGlzLmdyaWRDb25maWcuZGF5RW5kSG91ciAqIDYwO1xuICAgICAgICBjb25zdCBtaW51dGVIZWlnaHQgPSB0aGlzLmdyaWRDb25maWcuaG91ckhlaWdodCAvIDYwO1xuICAgICAgICBpZiAoc2NoZWR1bGUgPT09IG51bGwpIHtcbiAgICAgICAgICAgIC8vIEZ1bGwgZGF5IHVuYXZhaWxhYmxlXG4gICAgICAgICAgICBjb25zdCB6b25lID0gdGhpcy5jcmVhdGVVbmF2YWlsYWJsZVpvbmUoMCwgKGRheUVuZE1pbnV0ZXMgLSBkYXlTdGFydE1pbnV0ZXMpICogbWludXRlSGVpZ2h0KTtcbiAgICAgICAgICAgIGxheWVyLmFwcGVuZENoaWxkKHpvbmUpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHdvcmtTdGFydE1pbnV0ZXMgPSB0aGlzLmRhdGVTZXJ2aWNlLnRpbWVUb01pbnV0ZXMoc2NoZWR1bGUuc3RhcnQpO1xuICAgICAgICBjb25zdCB3b3JrRW5kTWludXRlcyA9IHRoaXMuZGF0ZVNlcnZpY2UudGltZVRvTWludXRlcyhzY2hlZHVsZS5lbmQpO1xuICAgICAgICAvLyBCZWZvcmUgd29yayBzdGFydFxuICAgICAgICBpZiAod29ya1N0YXJ0TWludXRlcyA+IGRheVN0YXJ0TWludXRlcykge1xuICAgICAgICAgICAgY29uc3QgdG9wID0gMDtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9ICh3b3JrU3RhcnRNaW51dGVzIC0gZGF5U3RhcnRNaW51dGVzKSAqIG1pbnV0ZUhlaWdodDtcbiAgICAgICAgICAgIGNvbnN0IHpvbmUgPSB0aGlzLmNyZWF0ZVVuYXZhaWxhYmxlWm9uZSh0b3AsIGhlaWdodCk7XG4gICAgICAgICAgICBsYXllci5hcHBlbmRDaGlsZCh6b25lKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBBZnRlciB3b3JrIGVuZFxuICAgICAgICBpZiAod29ya0VuZE1pbnV0ZXMgPCBkYXlFbmRNaW51dGVzKSB7XG4gICAgICAgICAgICBjb25zdCB0b3AgPSAod29ya0VuZE1pbnV0ZXMgLSBkYXlTdGFydE1pbnV0ZXMpICogbWludXRlSGVpZ2h0O1xuICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gKGRheUVuZE1pbnV0ZXMgLSB3b3JrRW5kTWludXRlcykgKiBtaW51dGVIZWlnaHQ7XG4gICAgICAgICAgICBjb25zdCB6b25lID0gdGhpcy5jcmVhdGVVbmF2YWlsYWJsZVpvbmUodG9wLCBoZWlnaHQpO1xuICAgICAgICAgICAgbGF5ZXIuYXBwZW5kQ2hpbGQoem9uZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGFuIHVuYXZhaWxhYmxlIHpvbmUgZWxlbWVudFxuICAgICAqL1xuICAgIGNyZWF0ZVVuYXZhaWxhYmxlWm9uZSh0b3AsIGhlaWdodCkge1xuICAgICAgICBjb25zdCB6b25lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3dwLXVuYXZhaWxhYmxlLXpvbmUnKTtcbiAgICAgICAgem9uZS5zdHlsZS50b3AgPSBgJHt0b3B9cHhgO1xuICAgICAgICB6b25lLnN0eWxlLmhlaWdodCA9IGAke2hlaWdodH1weGA7XG4gICAgICAgIHJldHVybiB6b25lO1xuICAgIH1cbn1cbiIsICJpbXBvcnQgeyBDb3JlRXZlbnRzIH0gZnJvbSAnLi4vLi4vY29uc3RhbnRzL0NvcmVFdmVudHMnO1xuLyoqXG4gKiBIZWFkZXJEcmF3ZXJSZW5kZXJlciAtIEhhbmRsZXMgcmVuZGVyaW5nIG9mIGl0ZW1zIGluIHRoZSBoZWFkZXIgZHJhd2VyXG4gKlxuICogTGlzdGVucyB0byBkcmFnIGV2ZW50cyBmcm9tIERyYWdEcm9wTWFuYWdlciBhbmQgY3JlYXRlcy9tYW5hZ2VzXG4gKiBzd3AtaGVhZGVyLWl0ZW0gZWxlbWVudHMgaW4gdGhlIGhlYWRlciBkcmF3ZXIuXG4gKlxuICogVXNlcyBzdWJncmlkIGZvciBjb2x1bW4gYWxpZ25tZW50IHdpdGggcGFyZW50IHN3cC1jYWxlbmRhci1oZWFkZXIuXG4gKiBQb3NpdGlvbiBpdGVtcyB2aWEgZ3JpZEFyZWEgZm9yIGV4cGxpY2l0IHJvdy9jb2x1bW4gcGxhY2VtZW50LlxuICovXG5leHBvcnQgY2xhc3MgSGVhZGVyRHJhd2VyUmVuZGVyZXIge1xuICAgIGNvbnN0cnVjdG9yKGV2ZW50QnVzLCBncmlkQ29uZmlnLCBoZWFkZXJEcmF3ZXJNYW5hZ2VyLCBldmVudFNlcnZpY2UsIGRhdGVTZXJ2aWNlKSB7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMgPSBldmVudEJ1cztcbiAgICAgICAgdGhpcy5ncmlkQ29uZmlnID0gZ3JpZENvbmZpZztcbiAgICAgICAgdGhpcy5oZWFkZXJEcmF3ZXJNYW5hZ2VyID0gaGVhZGVyRHJhd2VyTWFuYWdlcjtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UgPSBldmVudFNlcnZpY2U7XG4gICAgICAgIHRoaXMuZGF0ZVNlcnZpY2UgPSBkYXRlU2VydmljZTtcbiAgICAgICAgdGhpcy5jdXJyZW50SXRlbSA9IG51bGw7XG4gICAgICAgIHRoaXMuY29udGFpbmVyID0gbnVsbDtcbiAgICAgICAgdGhpcy5zb3VyY2VFbGVtZW50ID0gbnVsbDtcbiAgICAgICAgdGhpcy53YXNFeHBhbmRlZEJlZm9yZURyYWcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5maWx0ZXJUZW1wbGF0ZSA9IG51bGw7XG4gICAgICAgIHRoaXMuc2V0dXBMaXN0ZW5lcnMoKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVuZGVyIGFsbERheSBldmVudHMgaW50byB0aGUgaGVhZGVyIGRyYXdlciB3aXRoIHJvdyBzdGFja2luZ1xuICAgICAqIEBwYXJhbSBmaWx0ZXJUZW1wbGF0ZSAtIFRlbXBsYXRlIGZvciBtYXRjaGluZyBldmVudHMgdG8gY29sdW1uc1xuICAgICAqL1xuICAgIGFzeW5jIHJlbmRlcihjb250YWluZXIsIGZpbHRlciwgZmlsdGVyVGVtcGxhdGUpIHtcbiAgICAgICAgLy8gU3RvcmUgZmlsdGVyVGVtcGxhdGUgZm9yIGJ1aWxkQ29sdW1uS2V5RnJvbUV2ZW50XG4gICAgICAgIHRoaXMuZmlsdGVyVGVtcGxhdGUgPSBmaWx0ZXJUZW1wbGF0ZTtcbiAgICAgICAgY29uc3QgZHJhd2VyID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJ3N3cC1oZWFkZXItZHJhd2VyJyk7XG4gICAgICAgIGlmICghZHJhd2VyKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBjb25zdCB2aXNpYmxlRGF0ZXMgPSBmaWx0ZXJbJ2RhdGUnXSB8fCBbXTtcbiAgICAgICAgaWYgKHZpc2libGVEYXRlcy5sZW5ndGggPT09IDApXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIC8vIEdldCBjb2x1bW4ga2V5cyBmcm9tIERPTSBmb3IgY29ycmVjdCBtdWx0aS1yZXNvdXJjZSBwb3NpdGlvbmluZ1xuICAgICAgICBjb25zdCB2aXNpYmxlQ29sdW1uS2V5cyA9IHRoaXMuZ2V0VmlzaWJsZUNvbHVtbktleXNGcm9tRE9NKCk7XG4gICAgICAgIGlmICh2aXNpYmxlQ29sdW1uS2V5cy5sZW5ndGggPT09IDApXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIC8vIEZldGNoIGV2ZW50cyBmb3IgZGF0ZSByYW5nZVxuICAgICAgICBjb25zdCBzdGFydERhdGUgPSBuZXcgRGF0ZSh2aXNpYmxlRGF0ZXNbMF0pO1xuICAgICAgICBjb25zdCBlbmREYXRlID0gbmV3IERhdGUodmlzaWJsZURhdGVzW3Zpc2libGVEYXRlcy5sZW5ndGggLSAxXSk7XG4gICAgICAgIGVuZERhdGUuc2V0SG91cnMoMjMsIDU5LCA1OSwgOTk5KTtcbiAgICAgICAgY29uc3QgZXZlbnRzID0gYXdhaXQgdGhpcy5ldmVudFNlcnZpY2UuZ2V0QnlEYXRlUmFuZ2Uoc3RhcnREYXRlLCBlbmREYXRlKTtcbiAgICAgICAgLy8gRmlsdGVyIHRvIGFsbERheSBldmVudHMgb25seSAoYWxsRGF5ICE9PSBmYWxzZSlcbiAgICAgICAgY29uc3QgYWxsRGF5RXZlbnRzID0gZXZlbnRzLmZpbHRlcihldmVudCA9PiBldmVudC5hbGxEYXkgIT09IGZhbHNlKTtcbiAgICAgICAgLy8gQ2xlYXIgZXhpc3RpbmcgaXRlbXNcbiAgICAgICAgZHJhd2VyLmlubmVySFRNTCA9ICcnO1xuICAgICAgICBpZiAoYWxsRGF5RXZlbnRzLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgLy8gQ2FsY3VsYXRlIGxheW91dCB3aXRoIHJvdyBzdGFja2luZyB1c2luZyBjb2x1bW5LZXlzXG4gICAgICAgIGNvbnN0IGxheW91dHMgPSB0aGlzLmNhbGN1bGF0ZUxheW91dChhbGxEYXlFdmVudHMsIHZpc2libGVDb2x1bW5LZXlzKTtcbiAgICAgICAgY29uc3Qgcm93Q291bnQgPSBNYXRoLm1heCgxLCAuLi5sYXlvdXRzLm1hcChsID0+IGwucm93KSk7XG4gICAgICAgIC8vIFJlbmRlciBlYWNoIGl0ZW0gd2l0aCBsYXlvdXRcbiAgICAgICAgbGF5b3V0cy5mb3JFYWNoKGxheW91dCA9PiB7XG4gICAgICAgICAgICBjb25zdCBpdGVtID0gdGhpcy5jcmVhdGVIZWFkZXJJdGVtKGxheW91dCk7XG4gICAgICAgICAgICBkcmF3ZXIuYXBwZW5kQ2hpbGQoaXRlbSk7XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBFeHBhbmQgZHJhd2VyIHRvIGZpdCBhbGwgcm93c1xuICAgICAgICB0aGlzLmhlYWRlckRyYXdlck1hbmFnZXIuZXhwYW5kVG9Sb3dzKHJvd0NvdW50KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGEgaGVhZGVyIGl0ZW0gZWxlbWVudCBmcm9tIGxheW91dFxuICAgICAqL1xuICAgIGNyZWF0ZUhlYWRlckl0ZW0obGF5b3V0KSB7XG4gICAgICAgIGNvbnN0IHsgZXZlbnQsIGNvbHVtbktleSwgcm93LCBjb2xTdGFydCwgY29sRW5kIH0gPSBsYXlvdXQ7XG4gICAgICAgIGNvbnN0IGl0ZW0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzd3AtaGVhZGVyLWl0ZW0nKTtcbiAgICAgICAgaXRlbS5kYXRhc2V0LmV2ZW50SWQgPSBldmVudC5pZDtcbiAgICAgICAgaXRlbS5kYXRhc2V0Lml0ZW1UeXBlID0gJ2V2ZW50JztcbiAgICAgICAgaXRlbS5kYXRhc2V0LnN0YXJ0ID0gZXZlbnQuc3RhcnQudG9JU09TdHJpbmcoKTtcbiAgICAgICAgaXRlbS5kYXRhc2V0LmVuZCA9IGV2ZW50LmVuZC50b0lTT1N0cmluZygpO1xuICAgICAgICBpdGVtLmRhdGFzZXQuY29sdW1uS2V5ID0gY29sdW1uS2V5O1xuICAgICAgICBpdGVtLnRleHRDb250ZW50ID0gZXZlbnQudGl0bGU7XG4gICAgICAgIC8vIENvbG9yIGNsYXNzXG4gICAgICAgIGNvbnN0IGNvbG9yQ2xhc3MgPSB0aGlzLmdldENvbG9yQ2xhc3MoZXZlbnQpO1xuICAgICAgICBpZiAoY29sb3JDbGFzcylcbiAgICAgICAgICAgIGl0ZW0uY2xhc3NMaXN0LmFkZChjb2xvckNsYXNzKTtcbiAgICAgICAgLy8gR3JpZCBwb3NpdGlvbiBmcm9tIGxheW91dFxuICAgICAgICBpdGVtLnN0eWxlLmdyaWRBcmVhID0gYCR7cm93fSAvICR7Y29sU3RhcnR9IC8gJHtyb3cgKyAxfSAvICR7Y29sRW5kfWA7XG4gICAgICAgIHJldHVybiBpdGVtO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDYWxjdWxhdGUgbGF5b3V0IGZvciBhbGwgZXZlbnRzIHdpdGggcm93IHN0YWNraW5nXG4gICAgICogVXNlcyB0cmFjay1iYXNlZCBhbGdvcml0aG0gdG8gZmluZCBhdmFpbGFibGUgcm93cyBmb3Igb3ZlcmxhcHBpbmcgZXZlbnRzXG4gICAgICovXG4gICAgY2FsY3VsYXRlTGF5b3V0KGV2ZW50cywgdmlzaWJsZUNvbHVtbktleXMpIHtcbiAgICAgICAgLy8gdHJhY2tzW3Jvd11bY29sXSA9IG9jY3VwaWVkXG4gICAgICAgIGNvbnN0IHRyYWNrcyA9IFtuZXcgQXJyYXkodmlzaWJsZUNvbHVtbktleXMubGVuZ3RoKS5maWxsKGZhbHNlKV07XG4gICAgICAgIGNvbnN0IGxheW91dHMgPSBbXTtcbiAgICAgICAgZm9yIChjb25zdCBldmVudCBvZiBldmVudHMpIHtcbiAgICAgICAgICAgIC8vIEJ1aWxkIGNvbHVtbktleSBmcm9tIGV2ZW50IGZpZWxkcyAob25seSBwbGFjZSB3ZSBuZWVkIHRvIGNvbnN0cnVjdCBpdClcbiAgICAgICAgICAgIGNvbnN0IGNvbHVtbktleSA9IHRoaXMuYnVpbGRDb2x1bW5LZXlGcm9tRXZlbnQoZXZlbnQpO1xuICAgICAgICAgICAgY29uc3Qgc3RhcnRDb2wgPSB2aXNpYmxlQ29sdW1uS2V5cy5pbmRleE9mKGNvbHVtbktleSk7XG4gICAgICAgICAgICBjb25zdCBlbmRDb2x1bW5LZXkgPSB0aGlzLmJ1aWxkQ29sdW1uS2V5RnJvbUV2ZW50KGV2ZW50LCBldmVudC5lbmQpO1xuICAgICAgICAgICAgY29uc3QgZW5kQ29sID0gdmlzaWJsZUNvbHVtbktleXMuaW5kZXhPZihlbmRDb2x1bW5LZXkpO1xuICAgICAgICAgICAgaWYgKHN0YXJ0Q29sID09PSAtMSAmJiBlbmRDb2wgPT09IC0xKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgLy8gQ2xhbXAgdGlsIHN5bmxpZ2Uga29sb25uZXJcbiAgICAgICAgICAgIGNvbnN0IGNvbFN0YXJ0ID0gTWF0aC5tYXgoMCwgc3RhcnRDb2wpO1xuICAgICAgICAgICAgY29uc3QgY29sRW5kID0gKGVuZENvbCAhPT0gLTEgPyBlbmRDb2wgOiB2aXNpYmxlQ29sdW1uS2V5cy5sZW5ndGggLSAxKSArIDE7XG4gICAgICAgICAgICAvLyBGaW5kIGxlZGlnIHJcdTAwRTZra2VcbiAgICAgICAgICAgIGNvbnN0IHJvdyA9IHRoaXMuZmluZEF2YWlsYWJsZVJvdyh0cmFja3MsIGNvbFN0YXJ0LCBjb2xFbmQpO1xuICAgICAgICAgICAgLy8gTWFya2VyIHNvbSBvcHRhZ2V0XG4gICAgICAgICAgICBmb3IgKGxldCBjID0gY29sU3RhcnQ7IGMgPCBjb2xFbmQ7IGMrKykge1xuICAgICAgICAgICAgICAgIHRyYWNrc1tyb3ddW2NdID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxheW91dHMucHVzaCh7IGV2ZW50LCBjb2x1bW5LZXksIHJvdzogcm93ICsgMSwgY29sU3RhcnQ6IGNvbFN0YXJ0ICsgMSwgY29sRW5kOiBjb2xFbmQgKyAxIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsYXlvdXRzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBCdWlsZCBjb2x1bW5LZXkgZnJvbSBldmVudCB1c2luZyBGaWx0ZXJUZW1wbGF0ZVxuICAgICAqIFVzZXMgdGhlIHNhbWUgdGVtcGxhdGUgdGhhdCBjb2x1bW5zIHVzZSBmb3IgbWF0Y2hpbmdcbiAgICAgKi9cbiAgICBidWlsZENvbHVtbktleUZyb21FdmVudChldmVudCwgZGF0ZSkge1xuICAgICAgICBpZiAoIXRoaXMuZmlsdGVyVGVtcGxhdGUpIHtcbiAgICAgICAgICAgIC8vIEZhbGxiYWNrIGlmIG5vIHRlbXBsYXRlIC0gc2hvdWxkbid0IGhhcHBlbiBpbiBub3JtYWwgZmxvd1xuICAgICAgICAgICAgY29uc3QgZGF0ZVN0ciA9IHRoaXMuZGF0ZVNlcnZpY2UuZ2V0RGF0ZUtleShkYXRlIHx8IGV2ZW50LnN0YXJ0KTtcbiAgICAgICAgICAgIHJldHVybiBkYXRlU3RyO1xuICAgICAgICB9XG4gICAgICAgIC8vIEZvciBtdWx0aS1kYXkgZXZlbnRzLCB3ZSBuZWVkIHRvIG92ZXJyaWRlIHRoZSBkYXRlIGluIHRoZSBldmVudFxuICAgICAgICBpZiAoZGF0ZSAmJiBkYXRlLmdldFRpbWUoKSAhPT0gZXZlbnQuc3RhcnQuZ2V0VGltZSgpKSB7XG4gICAgICAgICAgICAvLyBDcmVhdGUgdGVtcG9yYXJ5IGV2ZW50IHdpdGggb3ZlcnJpZGRlbiBzdGFydCBmb3Iga2V5IGdlbmVyYXRpb25cbiAgICAgICAgICAgIGNvbnN0IHRlbXBFdmVudCA9IHsgLi4uZXZlbnQsIHN0YXJ0OiBkYXRlIH07XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5maWx0ZXJUZW1wbGF0ZS5idWlsZEtleUZyb21FdmVudCh0ZW1wRXZlbnQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmZpbHRlclRlbXBsYXRlLmJ1aWxkS2V5RnJvbUV2ZW50KGV2ZW50KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRmluZCBhdmFpbGFibGUgcm93IGZvciBldmVudCBzcGFubmluZyBjb2x1bW5zIFtjb2xTdGFydCwgY29sRW5kKVxuICAgICAqL1xuICAgIGZpbmRBdmFpbGFibGVSb3codHJhY2tzLCBjb2xTdGFydCwgY29sRW5kKSB7XG4gICAgICAgIGZvciAobGV0IHJvdyA9IDA7IHJvdyA8IHRyYWNrcy5sZW5ndGg7IHJvdysrKSB7XG4gICAgICAgICAgICBsZXQgYXZhaWxhYmxlID0gdHJ1ZTtcbiAgICAgICAgICAgIGZvciAobGV0IGMgPSBjb2xTdGFydDsgYyA8IGNvbEVuZDsgYysrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRyYWNrc1tyb3ddW2NdKSB7XG4gICAgICAgICAgICAgICAgICAgIGF2YWlsYWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYXZhaWxhYmxlKVxuICAgICAgICAgICAgICAgIHJldHVybiByb3c7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTnkgclx1MDBFNmtrZVxuICAgICAgICB0cmFja3MucHVzaChuZXcgQXJyYXkodHJhY2tzWzBdLmxlbmd0aCkuZmlsbChmYWxzZSkpO1xuICAgICAgICByZXR1cm4gdHJhY2tzLmxlbmd0aCAtIDE7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBjb2xvciBjbGFzcyBiYXNlZCBvbiBldmVudCBtZXRhZGF0YSBvciB0eXBlXG4gICAgICovXG4gICAgZ2V0Q29sb3JDbGFzcyhldmVudCkge1xuICAgICAgICBpZiAoZXZlbnQubWV0YWRhdGE/LmNvbG9yKSB7XG4gICAgICAgICAgICByZXR1cm4gYGlzLSR7ZXZlbnQubWV0YWRhdGEuY29sb3J9YDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB0eXBlQ29sb3JzID0ge1xuICAgICAgICAgICAgJ2N1c3RvbWVyJzogJ2lzLWJsdWUnLFxuICAgICAgICAgICAgJ3ZhY2F0aW9uJzogJ2lzLWdyZWVuJyxcbiAgICAgICAgICAgICdicmVhayc6ICdpcy1hbWJlcicsXG4gICAgICAgICAgICAnbWVldGluZyc6ICdpcy1wdXJwbGUnLFxuICAgICAgICAgICAgJ2Jsb2NrZWQnOiAnaXMtcmVkJ1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gdHlwZUNvbG9yc1tldmVudC50eXBlXSB8fCAnaXMtYmx1ZSc7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNldHVwIGV2ZW50IGxpc3RlbmVycyBmb3IgZHJhZyBldmVudHNcbiAgICAgKi9cbiAgICBzZXR1cExpc3RlbmVycygpIHtcbiAgICAgICAgdGhpcy5ldmVudEJ1cy5vbihDb3JlRXZlbnRzLkVWRU5UX0RSQUdfRU5URVJfSEVBREVSLCAoZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IGUuZGV0YWlsO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVEcmFnRW50ZXIocGF5bG9hZCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENvcmVFdmVudHMuRVZFTlRfRFJBR19NT1ZFX0hFQURFUiwgKGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSBlLmRldGFpbDtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlRHJhZ01vdmUocGF5bG9hZCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENvcmVFdmVudHMuRVZFTlRfRFJBR19MRUFWRV9IRUFERVIsIChlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwYXlsb2FkID0gZS5kZXRhaWw7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZURyYWdMZWF2ZShwYXlsb2FkKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMub24oQ29yZUV2ZW50cy5FVkVOVF9EUkFHX0VORCwgKGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSBlLmRldGFpbDtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlRHJhZ0VuZChwYXlsb2FkKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMub24oQ29yZUV2ZW50cy5FVkVOVF9EUkFHX0NBTkNFTCwgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5jbGVhbnVwKCk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgZHJhZyBlbnRlcmluZyBoZWFkZXIgem9uZSAtIGNyZWF0ZSBwcmV2aWV3IGl0ZW1cbiAgICAgKi9cbiAgICBoYW5kbGVEcmFnRW50ZXIocGF5bG9hZCkge1xuICAgICAgICB0aGlzLmNvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ3N3cC1oZWFkZXItZHJhd2VyJyk7XG4gICAgICAgIGlmICghdGhpcy5jb250YWluZXIpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIC8vIFJlbWVtYmVyIGlmIGRyYXdlciB3YXMgYWxyZWFkeSBleHBhbmRlZFxuICAgICAgICB0aGlzLndhc0V4cGFuZGVkQmVmb3JlRHJhZyA9IHRoaXMuaGVhZGVyRHJhd2VyTWFuYWdlci5pc0V4cGFuZGVkKCk7XG4gICAgICAgIC8vIEV4cGFuZCB0byBhdCBsZWFzdCAxIHJvdyBpZiBjb2xsYXBzZWQsIG90aGVyd2lzZSBrZWVwIGN1cnJlbnQgaGVpZ2h0XG4gICAgICAgIGlmICghdGhpcy53YXNFeHBhbmRlZEJlZm9yZURyYWcpIHtcbiAgICAgICAgICAgIHRoaXMuaGVhZGVyRHJhd2VyTWFuYWdlci5leHBhbmRUb1Jvd3MoMSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gU3RvcmUgcmVmZXJlbmNlIHRvIHNvdXJjZSBlbGVtZW50XG4gICAgICAgIHRoaXMuc291cmNlRWxlbWVudCA9IHBheWxvYWQuZWxlbWVudDtcbiAgICAgICAgLy8gQ3JlYXRlIGhlYWRlciBpdGVtXG4gICAgICAgIGNvbnN0IGl0ZW0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzd3AtaGVhZGVyLWl0ZW0nKTtcbiAgICAgICAgaXRlbS5kYXRhc2V0LmV2ZW50SWQgPSBwYXlsb2FkLmV2ZW50SWQ7XG4gICAgICAgIGl0ZW0uZGF0YXNldC5pdGVtVHlwZSA9IHBheWxvYWQuaXRlbVR5cGU7XG4gICAgICAgIGl0ZW0uZGF0YXNldC5kdXJhdGlvbiA9IFN0cmluZyhwYXlsb2FkLmR1cmF0aW9uKTtcbiAgICAgICAgaXRlbS5kYXRhc2V0LmNvbHVtbktleSA9IHBheWxvYWQuc291cmNlQ29sdW1uS2V5O1xuICAgICAgICBpdGVtLnRleHRDb250ZW50ID0gcGF5bG9hZC50aXRsZTtcbiAgICAgICAgLy8gQXBwbHkgY29sb3IgY2xhc3MgaWYgcHJlc2VudFxuICAgICAgICBpZiAocGF5bG9hZC5jb2xvckNsYXNzKSB7XG4gICAgICAgICAgICBpdGVtLmNsYXNzTGlzdC5hZGQocGF5bG9hZC5jb2xvckNsYXNzKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBBZGQgZHJhZ2dpbmcgc3RhdGVcbiAgICAgICAgaXRlbS5jbGFzc0xpc3QuYWRkKCdkcmFnZ2luZycpO1xuICAgICAgICAvLyBJbml0aWFsIHBsYWNlbWVudCAoZHVyYXRpb24gZGV0ZXJtaW5lcyBjb2x1bW4gc3BhbilcbiAgICAgICAgLy8gZ3JpZEFyZWEgZm9ybWF0OiBcInJvdyAvIGNvbC1zdGFydCAvIHJvdysxIC8gY29sLWVuZFwiXG4gICAgICAgIGNvbnN0IGNvbCA9IHBheWxvYWQuc291cmNlQ29sdW1uSW5kZXggKyAxO1xuICAgICAgICBjb25zdCBlbmRDb2wgPSBjb2wgKyBwYXlsb2FkLmR1cmF0aW9uO1xuICAgICAgICBpdGVtLnN0eWxlLmdyaWRBcmVhID0gYDEgLyAke2NvbH0gLyAyIC8gJHtlbmRDb2x9YDtcbiAgICAgICAgdGhpcy5jb250YWluZXIuYXBwZW5kQ2hpbGQoaXRlbSk7XG4gICAgICAgIHRoaXMuY3VycmVudEl0ZW0gPSBpdGVtO1xuICAgICAgICAvLyBIaWRlIG9yaWdpbmFsIGVsZW1lbnQgd2hpbGUgaW4gaGVhZGVyXG4gICAgICAgIHBheWxvYWQuZWxlbWVudC5zdHlsZS52aXNpYmlsaXR5ID0gJ2hpZGRlbic7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEhhbmRsZSBkcmFnIG1vdmluZyB3aXRoaW4gaGVhZGVyIC0gdXBkYXRlIGNvbHVtbiBwb3NpdGlvblxuICAgICAqL1xuICAgIGhhbmRsZURyYWdNb3ZlKHBheWxvYWQpIHtcbiAgICAgICAgaWYgKCF0aGlzLmN1cnJlbnRJdGVtKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAvLyBVcGRhdGUgY29sdW1uIHBvc2l0aW9uXG4gICAgICAgIGNvbnN0IGNvbCA9IHBheWxvYWQuY29sdW1uSW5kZXggKyAxO1xuICAgICAgICBjb25zdCBkdXJhdGlvbiA9IHBhcnNlSW50KHRoaXMuY3VycmVudEl0ZW0uZGF0YXNldC5kdXJhdGlvbiB8fCAnMScsIDEwKTtcbiAgICAgICAgY29uc3QgZW5kQ29sID0gY29sICsgZHVyYXRpb247XG4gICAgICAgIHRoaXMuY3VycmVudEl0ZW0uc3R5bGUuZ3JpZEFyZWEgPSBgMSAvICR7Y29sfSAvIDIgLyAke2VuZENvbH1gO1xuICAgICAgICAvLyBVcGRhdGUgY29sdW1uS2V5IHRvIG5ldyBwb3NpdGlvblxuICAgICAgICB0aGlzLmN1cnJlbnRJdGVtLmRhdGFzZXQuY29sdW1uS2V5ID0gcGF5bG9hZC5jb2x1bW5LZXk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEhhbmRsZSBkcmFnIGxlYXZpbmcgaGVhZGVyIC0gY2xlYW51cCBmb3IgZ3JpZFx1MjE5MmhlYWRlciBkcmFnIG9ubHlcbiAgICAgKi9cbiAgICBoYW5kbGVEcmFnTGVhdmUocGF5bG9hZCkge1xuICAgICAgICAvLyBPbmx5IGNsZWFudXAgZm9yIGdyaWRcdTIxOTJoZWFkZXIgZHJhZyAod2hlbiBncmlkIGV2ZW50IGxlYXZlcyBoZWFkZXIgYmFjayB0byBncmlkKVxuICAgICAgICAvLyBGb3IgaGVhZGVyXHUyMTkyZ3JpZCBkcmFnLCB0aGUgaGVhZGVyIGl0ZW0gc3RheXMgYXMgZ2hvc3QgdW50aWwgZHJvcFxuICAgICAgICBpZiAocGF5bG9hZC5zb3VyY2UgPT09ICdncmlkJykge1xuICAgICAgICAgICAgdGhpcy5jbGVhbnVwKCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gRm9yIGhlYWRlciBzb3VyY2UsIGRvIG5vdGhpbmcgLSBnaG9zdCBzdGF5cyB1bnRpbCBFVkVOVF9EUkFHX0VORFxuICAgIH1cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgZHJhZyBlbmQgLSBmaW5hbGl6ZSBiYXNlZCBvbiBkcm9wIHRhcmdldFxuICAgICAqL1xuICAgIGhhbmRsZURyYWdFbmQocGF5bG9hZCkge1xuICAgICAgICBpZiAocGF5bG9hZC50YXJnZXQgPT09ICdoZWFkZXInKSB7XG4gICAgICAgICAgICAvLyBHcmlkXHUyMTkySGVhZGVyOiBGaW5hbGl6ZSB0aGUgaGVhZGVyIGl0ZW0gKGl0IHN0YXlzIGluIGhlYWRlcilcbiAgICAgICAgICAgIGlmICh0aGlzLmN1cnJlbnRJdGVtKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50SXRlbS5jbGFzc0xpc3QucmVtb3ZlKCdkcmFnZ2luZycpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVjYWxjdWxhdGVEcmF3ZXJMYXlvdXQoKTtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRJdGVtID0gbnVsbDtcbiAgICAgICAgICAgICAgICB0aGlzLnNvdXJjZUVsZW1lbnQgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gSGVhZGVyXHUyMTkyR3JpZDogUmVtb3ZlIGdob3N0IGhlYWRlciBpdGVtIGFuZCByZWNhbGN1bGF0ZVxuICAgICAgICAgICAgY29uc3QgZ2hvc3QgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGBzd3AtaGVhZGVyLWl0ZW0uZHJhZy1naG9zdFtkYXRhLWV2ZW50LWlkPVwiJHtwYXlsb2FkLnN3cEV2ZW50LmV2ZW50SWR9XCJdYCk7XG4gICAgICAgICAgICBnaG9zdD8ucmVtb3ZlKCk7XG4gICAgICAgICAgICB0aGlzLnJlY2FsY3VsYXRlRHJhd2VyTGF5b3V0KCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVjYWxjdWxhdGUgbGF5b3V0IGZvciBhbGwgaXRlbXMgY3VycmVudGx5IGluIHRoZSBkcmF3ZXJcbiAgICAgKiBDYWxsZWQgYWZ0ZXIgZHJvcCB0byByZXBvc2l0aW9uIGl0ZW1zIGFuZCBhZGp1c3QgaGVpZ2h0XG4gICAgICovXG4gICAgcmVjYWxjdWxhdGVEcmF3ZXJMYXlvdXQoKSB7XG4gICAgICAgIGNvbnN0IGRyYXdlciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ3N3cC1oZWFkZXItZHJhd2VyJyk7XG4gICAgICAgIGlmICghZHJhd2VyKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBjb25zdCBpdGVtcyA9IEFycmF5LmZyb20oZHJhd2VyLnF1ZXJ5U2VsZWN0b3JBbGwoJ3N3cC1oZWFkZXItaXRlbScpKTtcbiAgICAgICAgaWYgKGl0ZW1zLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgLy8gR2V0IHZpc2libGUgY29sdW1uIGtleXMgZm9yIGNvcnJlY3QgbXVsdGktcmVzb3VyY2UgcG9zaXRpb25pbmdcbiAgICAgICAgY29uc3QgdmlzaWJsZUNvbHVtbktleXMgPSB0aGlzLmdldFZpc2libGVDb2x1bW5LZXlzRnJvbURPTSgpO1xuICAgICAgICBpZiAodmlzaWJsZUNvbHVtbktleXMubGVuZ3RoID09PSAwKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAvLyBCdWlsZCBsYXlvdXQgZGF0YSBmcm9tIERPTSBpdGVtcyAtIHVzZSBjb2x1bW5LZXkgZGlyZWN0bHkgKG9wYXF1ZSBtYXRjaGluZylcbiAgICAgICAgY29uc3QgaXRlbURhdGEgPSBpdGVtcy5tYXAoaXRlbSA9PiAoe1xuICAgICAgICAgICAgZWxlbWVudDogaXRlbSxcbiAgICAgICAgICAgIGNvbHVtbktleTogaXRlbS5kYXRhc2V0LmNvbHVtbktleSB8fCAnJyxcbiAgICAgICAgICAgIGR1cmF0aW9uOiBwYXJzZUludChpdGVtLmRhdGFzZXQuZHVyYXRpb24gfHwgJzEnLCAxMClcbiAgICAgICAgfSkpO1xuICAgICAgICAvLyBDYWxjdWxhdGUgbmV3IGxheW91dCB1c2luZyB0cmFjayBhbGdvcml0aG1cbiAgICAgICAgY29uc3QgdHJhY2tzID0gW25ldyBBcnJheSh2aXNpYmxlQ29sdW1uS2V5cy5sZW5ndGgpLmZpbGwoZmFsc2UpXTtcbiAgICAgICAgZm9yIChjb25zdCBpdGVtIG9mIGl0ZW1EYXRhKSB7XG4gICAgICAgICAgICAvLyBEaXJlY3QgY29sdW1uS2V5IG1hdGNoaW5nIC0gbm8gcGFyc2luZyBvciBjb25zdHJ1Y3Rpb24gbmVlZGVkXG4gICAgICAgICAgICBjb25zdCBzdGFydENvbCA9IHZpc2libGVDb2x1bW5LZXlzLmluZGV4T2YoaXRlbS5jb2x1bW5LZXkpO1xuICAgICAgICAgICAgaWYgKHN0YXJ0Q29sID09PSAtMSlcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIGNvbnN0IGNvbFN0YXJ0ID0gc3RhcnRDb2w7XG4gICAgICAgICAgICBjb25zdCBjb2xFbmQgPSBNYXRoLm1pbihzdGFydENvbCArIGl0ZW0uZHVyYXRpb24sIHZpc2libGVDb2x1bW5LZXlzLmxlbmd0aCk7XG4gICAgICAgICAgICBjb25zdCByb3cgPSB0aGlzLmZpbmRBdmFpbGFibGVSb3codHJhY2tzLCBjb2xTdGFydCwgY29sRW5kKTtcbiAgICAgICAgICAgIGZvciAobGV0IGMgPSBjb2xTdGFydDsgYyA8IGNvbEVuZDsgYysrKSB7XG4gICAgICAgICAgICAgICAgdHJhY2tzW3Jvd11bY10gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gVXBkYXRlIGVsZW1lbnQgcG9zaXRpb25cbiAgICAgICAgICAgIGl0ZW0uZWxlbWVudC5zdHlsZS5ncmlkQXJlYSA9IGAke3JvdyArIDF9IC8gJHtjb2xTdGFydCArIDF9IC8gJHtyb3cgKyAyfSAvICR7Y29sRW5kICsgMX1gO1xuICAgICAgICB9XG4gICAgICAgIC8vIFVwZGF0ZSBkcmF3ZXIgaGVpZ2h0XG4gICAgICAgIGNvbnN0IHJvd0NvdW50ID0gdHJhY2tzLmxlbmd0aDtcbiAgICAgICAgdGhpcy5oZWFkZXJEcmF3ZXJNYW5hZ2VyLmV4cGFuZFRvUm93cyhyb3dDb3VudCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCB2aXNpYmxlIGNvbHVtbiBrZXlzIGZyb20gRE9NIChwcmVzZXJ2ZXMgb3JkZXIgZm9yIG11bHRpLXJlc291cmNlIHZpZXdzKVxuICAgICAqIFVzZXMgZmlsdGVyVGVtcGxhdGUuYnVpbGRLZXlGcm9tQ29sdW1uKCkgZm9yIGNvbnNpc3RlbnQga2V5IGZvcm1hdCB3aXRoIGV2ZW50c1xuICAgICAqL1xuICAgIGdldFZpc2libGVDb2x1bW5LZXlzRnJvbURPTSgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmZpbHRlclRlbXBsYXRlKVxuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICBjb25zdCBjb2x1bW5zID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnc3dwLWRheS1jb2x1bW4nKTtcbiAgICAgICAgY29uc3QgY29sdW1uS2V5cyA9IFtdO1xuICAgICAgICBjb2x1bW5zLmZvckVhY2goY29sID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbHVtbktleSA9IHRoaXMuZmlsdGVyVGVtcGxhdGUuYnVpbGRLZXlGcm9tQ29sdW1uKGNvbCk7XG4gICAgICAgICAgICBpZiAoY29sdW1uS2V5KVxuICAgICAgICAgICAgICAgIGNvbHVtbktleXMucHVzaChjb2x1bW5LZXkpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGNvbHVtbktleXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENsZWFudXAgcHJldmlldyBpdGVtIGFuZCByZXN0b3JlIHNvdXJjZSB2aXNpYmlsaXR5XG4gICAgICovXG4gICAgY2xlYW51cCgpIHtcbiAgICAgICAgLy8gUmVtb3ZlIHByZXZpZXcgaXRlbVxuICAgICAgICB0aGlzLmN1cnJlbnRJdGVtPy5yZW1vdmUoKTtcbiAgICAgICAgdGhpcy5jdXJyZW50SXRlbSA9IG51bGw7XG4gICAgICAgIC8vIFJlc3RvcmUgc291cmNlIGVsZW1lbnQgdmlzaWJpbGl0eVxuICAgICAgICBpZiAodGhpcy5zb3VyY2VFbGVtZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNvdXJjZUVsZW1lbnQuc3R5bGUudmlzaWJpbGl0eSA9ICcnO1xuICAgICAgICAgICAgdGhpcy5zb3VyY2VFbGVtZW50ID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICAvLyBDb2xsYXBzZSBkcmF3ZXIgaWYgaXQgd2Fzbid0IGV4cGFuZGVkIGJlZm9yZSBkcmFnXG4gICAgICAgIGlmICghdGhpcy53YXNFeHBhbmRlZEJlZm9yZURyYWcpIHtcbiAgICAgICAgICAgIHRoaXMuaGVhZGVyRHJhd2VyTWFuYWdlci5jb2xsYXBzZSgpO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwgIi8qKlxuICogU2NoZWR1bGVPdmVycmlkZVN0b3JlIC0gSW5kZXhlZERCIE9iamVjdFN0b3JlIGZvciBzY2hlZHVsZSBvdmVycmlkZXNcbiAqXG4gKiBTdG9yZXMgZGF0ZS1zcGVjaWZpYyBzY2hlZHVsZSBvdmVycmlkZXMgZm9yIHJlc291cmNlcy5cbiAqIEluZGV4ZXM6IHJlc291cmNlSWQsIGRhdGUsIGNvbXBvdW5kIChyZXNvdXJjZUlkICsgZGF0ZSlcbiAqL1xuZXhwb3J0IGNsYXNzIFNjaGVkdWxlT3ZlcnJpZGVTdG9yZSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuc3RvcmVOYW1lID0gU2NoZWR1bGVPdmVycmlkZVN0b3JlLlNUT1JFX05BTUU7XG4gICAgfVxuICAgIGNyZWF0ZShkYikge1xuICAgICAgICBjb25zdCBzdG9yZSA9IGRiLmNyZWF0ZU9iamVjdFN0b3JlKFNjaGVkdWxlT3ZlcnJpZGVTdG9yZS5TVE9SRV9OQU1FLCB7IGtleVBhdGg6ICdpZCcgfSk7XG4gICAgICAgIHN0b3JlLmNyZWF0ZUluZGV4KCdyZXNvdXJjZUlkJywgJ3Jlc291cmNlSWQnLCB7IHVuaXF1ZTogZmFsc2UgfSk7XG4gICAgICAgIHN0b3JlLmNyZWF0ZUluZGV4KCdkYXRlJywgJ2RhdGUnLCB7IHVuaXF1ZTogZmFsc2UgfSk7XG4gICAgICAgIHN0b3JlLmNyZWF0ZUluZGV4KCdyZXNvdXJjZUlkX2RhdGUnLCBbJ3Jlc291cmNlSWQnLCAnZGF0ZSddLCB7IHVuaXF1ZTogdHJ1ZSB9KTtcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ3N5bmNTdGF0dXMnLCAnc3luY1N0YXR1cycsIHsgdW5pcXVlOiBmYWxzZSB9KTtcbiAgICB9XG59XG5TY2hlZHVsZU92ZXJyaWRlU3RvcmUuU1RPUkVfTkFNRSA9ICdzY2hlZHVsZU92ZXJyaWRlcyc7XG4iLCAiaW1wb3J0IHsgU2NoZWR1bGVPdmVycmlkZVN0b3JlIH0gZnJvbSAnLi9TY2hlZHVsZU92ZXJyaWRlU3RvcmUnO1xuLyoqXG4gKiBTY2hlZHVsZU92ZXJyaWRlU2VydmljZSAtIENSVUQgZm9yIHNjaGVkdWxlIG92ZXJyaWRlc1xuICpcbiAqIFByb3ZpZGVzIGFjY2VzcyB0byBkYXRlLXNwZWNpZmljIHNjaGVkdWxlIG92ZXJyaWRlcyBmb3IgcmVzb3VyY2VzLlxuICovXG5leHBvcnQgY2xhc3MgU2NoZWR1bGVPdmVycmlkZVNlcnZpY2Uge1xuICAgIGNvbnN0cnVjdG9yKGNvbnRleHQpIHtcbiAgICAgICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgICB9XG4gICAgZ2V0IGRiKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb250ZXh0LmdldERhdGFiYXNlKCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBvdmVycmlkZSBmb3IgYSBzcGVjaWZpYyByZXNvdXJjZSBhbmQgZGF0ZVxuICAgICAqL1xuICAgIGFzeW5jIGdldE92ZXJyaWRlKHJlc291cmNlSWQsIGRhdGUpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gdGhpcy5kYi50cmFuc2FjdGlvbihbU2NoZWR1bGVPdmVycmlkZVN0b3JlLlNUT1JFX05BTUVdLCAncmVhZG9ubHknKTtcbiAgICAgICAgICAgIGNvbnN0IHN0b3JlID0gdHJhbnNhY3Rpb24ub2JqZWN0U3RvcmUoU2NoZWR1bGVPdmVycmlkZVN0b3JlLlNUT1JFX05BTUUpO1xuICAgICAgICAgICAgY29uc3QgaW5kZXggPSBzdG9yZS5pbmRleCgncmVzb3VyY2VJZF9kYXRlJyk7XG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gaW5kZXguZ2V0KFtyZXNvdXJjZUlkLCBkYXRlXSk7XG4gICAgICAgICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZXNvbHZlKHJlcXVlc3QucmVzdWx0IHx8IG51bGwpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gZ2V0IG92ZXJyaWRlIGZvciAke3Jlc291cmNlSWR9IG9uICR7ZGF0ZX06ICR7cmVxdWVzdC5lcnJvcn1gKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGFsbCBvdmVycmlkZXMgZm9yIGEgcmVzb3VyY2VcbiAgICAgKi9cbiAgICBhc3luYyBnZXRCeVJlc291cmNlKHJlc291cmNlSWQpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gdGhpcy5kYi50cmFuc2FjdGlvbihbU2NoZWR1bGVPdmVycmlkZVN0b3JlLlNUT1JFX05BTUVdLCAncmVhZG9ubHknKTtcbiAgICAgICAgICAgIGNvbnN0IHN0b3JlID0gdHJhbnNhY3Rpb24ub2JqZWN0U3RvcmUoU2NoZWR1bGVPdmVycmlkZVN0b3JlLlNUT1JFX05BTUUpO1xuICAgICAgICAgICAgY29uc3QgaW5kZXggPSBzdG9yZS5pbmRleCgncmVzb3VyY2VJZCcpO1xuICAgICAgICAgICAgY29uc3QgcmVxdWVzdCA9IGluZGV4LmdldEFsbChyZXNvdXJjZUlkKTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25zdWNjZXNzID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlc29sdmUocmVxdWVzdC5yZXN1bHQgfHwgW10pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gZ2V0IG92ZXJyaWRlcyBmb3IgJHtyZXNvdXJjZUlkfTogJHtyZXF1ZXN0LmVycm9yfWApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgb3ZlcnJpZGVzIGZvciBhIGRhdGUgcmFuZ2VcbiAgICAgKi9cbiAgICBhc3luYyBnZXRCeURhdGVSYW5nZShyZXNvdXJjZUlkLCBzdGFydERhdGUsIGVuZERhdGUpIHtcbiAgICAgICAgY29uc3QgYWxsID0gYXdhaXQgdGhpcy5nZXRCeVJlc291cmNlKHJlc291cmNlSWQpO1xuICAgICAgICByZXR1cm4gYWxsLmZpbHRlcihvID0+IG8uZGF0ZSA+PSBzdGFydERhdGUgJiYgby5kYXRlIDw9IGVuZERhdGUpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTYXZlIGFuIG92ZXJyaWRlXG4gICAgICovXG4gICAgYXN5bmMgc2F2ZShvdmVycmlkZSkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSB0aGlzLmRiLnRyYW5zYWN0aW9uKFtTY2hlZHVsZU92ZXJyaWRlU3RvcmUuU1RPUkVfTkFNRV0sICdyZWFkd3JpdGUnKTtcbiAgICAgICAgICAgIGNvbnN0IHN0b3JlID0gdHJhbnNhY3Rpb24ub2JqZWN0U3RvcmUoU2NoZWR1bGVPdmVycmlkZVN0b3JlLlNUT1JFX05BTUUpO1xuICAgICAgICAgICAgY29uc3QgcmVxdWVzdCA9IHN0b3JlLnB1dChvdmVycmlkZSk7XG4gICAgICAgICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHJlc29sdmUoKTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gc2F2ZSBvdmVycmlkZSAke292ZXJyaWRlLmlkfTogJHtyZXF1ZXN0LmVycm9yfWApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBEZWxldGUgYW4gb3ZlcnJpZGVcbiAgICAgKi9cbiAgICBhc3luYyBkZWxldGUoaWQpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gdGhpcy5kYi50cmFuc2FjdGlvbihbU2NoZWR1bGVPdmVycmlkZVN0b3JlLlNUT1JFX05BTUVdLCAncmVhZHdyaXRlJyk7XG4gICAgICAgICAgICBjb25zdCBzdG9yZSA9IHRyYW5zYWN0aW9uLm9iamVjdFN0b3JlKFNjaGVkdWxlT3ZlcnJpZGVTdG9yZS5TVE9SRV9OQU1FKTtcbiAgICAgICAgICAgIGNvbnN0IHJlcXVlc3QgPSBzdG9yZS5kZWxldGUoaWQpO1xuICAgICAgICAgICAgcmVxdWVzdC5vbnN1Y2Nlc3MgPSAoKSA9PiByZXNvbHZlKCk7XG4gICAgICAgICAgICByZXF1ZXN0Lm9uZXJyb3IgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgRmFpbGVkIHRvIGRlbGV0ZSBvdmVycmlkZSAke2lkfTogJHtyZXF1ZXN0LmVycm9yfWApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIFJlc291cmNlU2NoZWR1bGVTZXJ2aWNlIC0gR2V0IGVmZmVjdGl2ZSBzY2hlZHVsZSBmb3IgYSByZXNvdXJjZSBvbiBhIGRhdGVcbiAqXG4gKiBMb2dpYzpcbiAqIDEuIENoZWNrIGZvciBvdmVycmlkZSBvbiB0aGlzIGRhdGVcbiAqIDIuIEZhbGwgYmFjayB0byBkZWZhdWx0IHNjaGVkdWxlIGZvciB0aGUgd2Vla2RheVxuICovXG5leHBvcnQgY2xhc3MgUmVzb3VyY2VTY2hlZHVsZVNlcnZpY2Uge1xuICAgIGNvbnN0cnVjdG9yKHJlc291cmNlU2VydmljZSwgb3ZlcnJpZGVTZXJ2aWNlLCBkYXRlU2VydmljZSkge1xuICAgICAgICB0aGlzLnJlc291cmNlU2VydmljZSA9IHJlc291cmNlU2VydmljZTtcbiAgICAgICAgdGhpcy5vdmVycmlkZVNlcnZpY2UgPSBvdmVycmlkZVNlcnZpY2U7XG4gICAgICAgIHRoaXMuZGF0ZVNlcnZpY2UgPSBkYXRlU2VydmljZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGVmZmVjdGl2ZSBzY2hlZHVsZSBmb3IgYSByZXNvdXJjZSBvbiBhIHNwZWNpZmljIGRhdGVcbiAgICAgKlxuICAgICAqIEBwYXJhbSByZXNvdXJjZUlkIC0gUmVzb3VyY2UgSURcbiAgICAgKiBAcGFyYW0gZGF0ZSAtIERhdGUgc3RyaW5nIFwiWVlZWS1NTS1ERFwiXG4gICAgICogQHJldHVybnMgSVRpbWVTbG90IG9yIG51bGwgKGZyaS9jbG9zZWQpXG4gICAgICovXG4gICAgYXN5bmMgZ2V0U2NoZWR1bGVGb3JEYXRlKHJlc291cmNlSWQsIGRhdGUpIHtcbiAgICAgICAgLy8gMS4gQ2hlY2sgZm9yIG92ZXJyaWRlXG4gICAgICAgIGNvbnN0IG92ZXJyaWRlID0gYXdhaXQgdGhpcy5vdmVycmlkZVNlcnZpY2UuZ2V0T3ZlcnJpZGUocmVzb3VyY2VJZCwgZGF0ZSk7XG4gICAgICAgIGlmIChvdmVycmlkZSkge1xuICAgICAgICAgICAgcmV0dXJuIG92ZXJyaWRlLnNjaGVkdWxlO1xuICAgICAgICB9XG4gICAgICAgIC8vIDIuIFVzZSBkZWZhdWx0IHNjaGVkdWxlIGZvciB3ZWVrZGF5XG4gICAgICAgIGNvbnN0IHJlc291cmNlID0gYXdhaXQgdGhpcy5yZXNvdXJjZVNlcnZpY2UuZ2V0KHJlc291cmNlSWQpO1xuICAgICAgICBpZiAoIXJlc291cmNlIHx8ICFyZXNvdXJjZS5kZWZhdWx0U2NoZWR1bGUpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHdlZWtEYXkgPSB0aGlzLmRhdGVTZXJ2aWNlLmdldElTT1dlZWtEYXkoZGF0ZSk7XG4gICAgICAgIHJldHVybiByZXNvdXJjZS5kZWZhdWx0U2NoZWR1bGVbd2Vla0RheV0gfHwgbnVsbDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IHNjaGVkdWxlcyBmb3IgbXVsdGlwbGUgZGF0ZXNcbiAgICAgKlxuICAgICAqIEBwYXJhbSByZXNvdXJjZUlkIC0gUmVzb3VyY2UgSURcbiAgICAgKiBAcGFyYW0gZGF0ZXMgLSBBcnJheSBvZiBkYXRlIHN0cmluZ3MgXCJZWVlZLU1NLUREXCJcbiAgICAgKiBAcmV0dXJucyBNYXAgb2YgZGF0ZSAtPiBJVGltZVNsb3QgfCBudWxsXG4gICAgICovXG4gICAgYXN5bmMgZ2V0U2NoZWR1bGVzRm9yRGF0ZXMocmVzb3VyY2VJZCwgZGF0ZXMpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IE1hcCgpO1xuICAgICAgICAvLyBHZXQgcmVzb3VyY2Ugb25jZVxuICAgICAgICBjb25zdCByZXNvdXJjZSA9IGF3YWl0IHRoaXMucmVzb3VyY2VTZXJ2aWNlLmdldChyZXNvdXJjZUlkKTtcbiAgICAgICAgLy8gR2V0IGFsbCBvdmVycmlkZXMgaW4gZGF0ZSByYW5nZVxuICAgICAgICBjb25zdCBvdmVycmlkZXMgPSBkYXRlcy5sZW5ndGggPiAwXG4gICAgICAgICAgICA/IGF3YWl0IHRoaXMub3ZlcnJpZGVTZXJ2aWNlLmdldEJ5RGF0ZVJhbmdlKHJlc291cmNlSWQsIGRhdGVzWzBdLCBkYXRlc1tkYXRlcy5sZW5ndGggLSAxXSlcbiAgICAgICAgICAgIDogW107XG4gICAgICAgIC8vIEJ1aWxkIG92ZXJyaWRlIG1hcFxuICAgICAgICBjb25zdCBvdmVycmlkZU1hcCA9IG5ldyBNYXAob3ZlcnJpZGVzLm1hcChvID0+IFtvLmRhdGUsIG8uc2NoZWR1bGVdKSk7XG4gICAgICAgIC8vIFJlc29sdmUgZWFjaCBkYXRlXG4gICAgICAgIGZvciAoY29uc3QgZGF0ZSBvZiBkYXRlcykge1xuICAgICAgICAgICAgLy8gQ2hlY2sgb3ZlcnJpZGUgZmlyc3RcbiAgICAgICAgICAgIGlmIChvdmVycmlkZU1hcC5oYXMoZGF0ZSkpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQuc2V0KGRhdGUsIG92ZXJyaWRlTWFwLmdldChkYXRlKSk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBGYWxsIGJhY2sgdG8gZGVmYXVsdFxuICAgICAgICAgICAgaWYgKHJlc291cmNlPy5kZWZhdWx0U2NoZWR1bGUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB3ZWVrRGF5ID0gdGhpcy5kYXRlU2VydmljZS5nZXRJU09XZWVrRGF5KGRhdGUpO1xuICAgICAgICAgICAgICAgIHJlc3VsdC5zZXQoZGF0ZSwgcmVzb3VyY2UuZGVmYXVsdFNjaGVkdWxlW3dlZWtEYXldIHx8IG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnNldChkYXRlLCBudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbn1cbiIsICIvKipcbiAqIFN3cEV2ZW50IC0gV3JhcHBlciBjbGFzcyBmb3IgY2FsZW5kYXIgZXZlbnQgZWxlbWVudHNcbiAqXG4gKiBFbmNhcHN1bGF0ZXMgYW4gSFRNTEVsZW1lbnQgYW5kIHByb3ZpZGVzIGNvbXB1dGVkIHByb3BlcnRpZXNcbiAqIGZvciBzdGFydC9lbmQgdGltZXMgYmFzZWQgb24gZWxlbWVudCBwb3NpdGlvbiBhbmQgZ3JpZCBjb25maWcuXG4gKlxuICogVXNhZ2U6XG4gKiAtIGV2ZW50SWQgaXMgcmVhZCBmcm9tIGVsZW1lbnQuZGF0YXNldFxuICogLSBjb2x1bW5LZXkgaWRlbnRpZmllcyB0aGUgY29sdW1uIHVuaWZvcm1seVxuICogLSBQb3NpdGlvbiAodG9wLCBoZWlnaHQpIGlzIHJlYWQgZnJvbSBlbGVtZW50LnN0eWxlXG4gKiAtIEZhY3RvcnkgbWV0aG9kIGBmcm9tRWxlbWVudCgpYCBjYWxjdWxhdGVzIERhdGUgb2JqZWN0c1xuICovXG5leHBvcnQgY2xhc3MgU3dwRXZlbnQge1xuICAgIGNvbnN0cnVjdG9yKGVsZW1lbnQsIGNvbHVtbktleSwgc3RhcnQsIGVuZCkge1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgICB0aGlzLmNvbHVtbktleSA9IGNvbHVtbktleTtcbiAgICAgICAgdGhpcy5fc3RhcnQgPSBzdGFydDtcbiAgICAgICAgdGhpcy5fZW5kID0gZW5kO1xuICAgIH1cbiAgICAvKiogRXZlbnQgSUQgZnJvbSBlbGVtZW50LmRhdGFzZXQuZXZlbnRJZCAqL1xuICAgIGdldCBldmVudElkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbGVtZW50LmRhdGFzZXQuZXZlbnRJZCB8fCAnJztcbiAgICB9XG4gICAgZ2V0IHN0YXJ0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fc3RhcnQ7XG4gICAgfVxuICAgIGdldCBlbmQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbmQ7XG4gICAgfVxuICAgIC8qKiBEdXJhdGlvbiBpbiBtaW51dGVzICovXG4gICAgZ2V0IGR1cmF0aW9uTWludXRlcygpIHtcbiAgICAgICAgcmV0dXJuICh0aGlzLl9lbmQuZ2V0VGltZSgpIC0gdGhpcy5fc3RhcnQuZ2V0VGltZSgpKSAvICgxMDAwICogNjApO1xuICAgIH1cbiAgICAvKiogRHVyYXRpb24gaW4gbWlsbGlzZWNvbmRzICovXG4gICAgZ2V0IGR1cmF0aW9uTXMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbmQuZ2V0VGltZSgpIC0gdGhpcy5fc3RhcnQuZ2V0VGltZSgpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBGYWN0b3J5OiBDcmVhdGUgU3dwRXZlbnQgZnJvbSBlbGVtZW50ICsgY29sdW1uS2V5XG4gICAgICogUmVhZHMgdG9wL2hlaWdodCBmcm9tIGVsZW1lbnQuc3R5bGUgdG8gY2FsY3VsYXRlIHN0YXJ0L2VuZFxuICAgICAqIEBwYXJhbSBjb2x1bW5LZXkgLSBPcGFxdWUgY29sdW1uIGlkZW50aWZpZXIgKGRvIE5PVCBwYXJzZSAtIHVzZSBvbmx5IGZvciBtYXRjaGluZylcbiAgICAgKiBAcGFyYW0gZGF0ZSAtIERhdGUgc3RyaW5nIChZWVlZLU1NLUREKSBmb3IgdGltZSBjYWxjdWxhdGlvbnNcbiAgICAgKi9cbiAgICBzdGF0aWMgZnJvbUVsZW1lbnQoZWxlbWVudCwgY29sdW1uS2V5LCBkYXRlLCBncmlkQ29uZmlnKSB7XG4gICAgICAgIGNvbnN0IHRvcFBpeGVscyA9IHBhcnNlRmxvYXQoZWxlbWVudC5zdHlsZS50b3ApIHx8IDA7XG4gICAgICAgIGNvbnN0IGhlaWdodFBpeGVscyA9IHBhcnNlRmxvYXQoZWxlbWVudC5zdHlsZS5oZWlnaHQpIHx8IDA7XG4gICAgICAgIC8vIENhbGN1bGF0ZSBzdGFydCBmcm9tIHRvcCBwb3NpdGlvblxuICAgICAgICBjb25zdCBzdGFydE1pbnV0ZXNGcm9tR3JpZCA9ICh0b3BQaXhlbHMgLyBncmlkQ29uZmlnLmhvdXJIZWlnaHQpICogNjA7XG4gICAgICAgIGNvbnN0IHRvdGFsTWludXRlcyA9IChncmlkQ29uZmlnLmRheVN0YXJ0SG91ciAqIDYwKSArIHN0YXJ0TWludXRlc0Zyb21HcmlkO1xuICAgICAgICBjb25zdCBzdGFydCA9IG5ldyBEYXRlKGRhdGUpO1xuICAgICAgICBzdGFydC5zZXRIb3VycyhNYXRoLmZsb29yKHRvdGFsTWludXRlcyAvIDYwKSwgdG90YWxNaW51dGVzICUgNjAsIDAsIDApO1xuICAgICAgICAvLyBDYWxjdWxhdGUgZW5kIGZyb20gaGVpZ2h0XG4gICAgICAgIGNvbnN0IGR1cmF0aW9uTWludXRlcyA9IChoZWlnaHRQaXhlbHMgLyBncmlkQ29uZmlnLmhvdXJIZWlnaHQpICogNjA7XG4gICAgICAgIGNvbnN0IGVuZCA9IG5ldyBEYXRlKHN0YXJ0LmdldFRpbWUoKSArIGR1cmF0aW9uTWludXRlcyAqIDYwICogMTAwMCk7XG4gICAgICAgIHJldHVybiBuZXcgU3dwRXZlbnQoZWxlbWVudCwgY29sdW1uS2V5LCBzdGFydCwgZW5kKTtcbiAgICB9XG59XG4iLCAiaW1wb3J0IHsgQ29yZUV2ZW50cyB9IGZyb20gJy4uL2NvbnN0YW50cy9Db3JlRXZlbnRzJztcbmltcG9ydCB7IHNuYXBUb0dyaWQgfSBmcm9tICcuLi91dGlscy9Qb3NpdGlvblV0aWxzJztcbmltcG9ydCB7IFN3cEV2ZW50IH0gZnJvbSAnLi4vdHlwZXMvU3dwRXZlbnQnO1xuLyoqXG4gKiBEcmFnRHJvcE1hbmFnZXIgLSBIYW5kbGVzIGRyYWctZHJvcCBmb3IgY2FsZW5kYXIgZXZlbnRzXG4gKlxuICogU3RyYXRlZ3k6IERyYWcgb3JpZ2luYWwgZWxlbWVudCwgbGVhdmUgZ2hvc3QtY2xvbmUgaW4gcGxhY2VcbiAqIC0gbW91c2Vkb3duOiBTdG9yZSBpbml0aWFsIHN0YXRlLCB3YWl0IGZvciBtb3ZlbWVudFxuICogLSBtb3VzZW1vdmUgKD41cHgpOiBDcmVhdGUgZ2hvc3QsIHN0YXJ0IGRyYWdnaW5nIG9yaWdpbmFsXG4gKiAtIG1vdXNldXA6IFNuYXAgdG8gZ3JpZCwgcmVtb3ZlIGdob3N0LCBlbWl0IGRyYWc6ZW5kXG4gKiAtIGNhbmNlbDogQW5pbWF0ZSBiYWNrIHRvIHN0YXJ0WSwgcmVtb3ZlIGdob3N0XG4gKi9cbmV4cG9ydCBjbGFzcyBEcmFnRHJvcE1hbmFnZXIge1xuICAgIGNvbnN0cnVjdG9yKGV2ZW50QnVzLCBncmlkQ29uZmlnKSB7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMgPSBldmVudEJ1cztcbiAgICAgICAgdGhpcy5ncmlkQ29uZmlnID0gZ3JpZENvbmZpZztcbiAgICAgICAgdGhpcy5kcmFnU3RhdGUgPSBudWxsO1xuICAgICAgICB0aGlzLm1vdXNlRG93blBvc2l0aW9uID0gbnVsbDtcbiAgICAgICAgdGhpcy5wZW5kaW5nRWxlbWVudCA9IG51bGw7XG4gICAgICAgIHRoaXMucGVuZGluZ01vdXNlT2Zmc2V0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5jb250YWluZXIgPSBudWxsO1xuICAgICAgICB0aGlzLmluSGVhZGVyID0gZmFsc2U7XG4gICAgICAgIHRoaXMuRFJBR19USFJFU0hPTEQgPSA1O1xuICAgICAgICB0aGlzLklOVEVSUE9MQVRJT05fRkFDVE9SID0gMC4zO1xuICAgICAgICB0aGlzLmhhbmRsZVBvaW50ZXJEb3duID0gKGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldCA9IGUudGFyZ2V0O1xuICAgICAgICAgICAgLy8gSWdub3JlIGlmIGNsaWNraW5nIG9uIHJlc2l6ZSBoYW5kbGVcbiAgICAgICAgICAgIGlmICh0YXJnZXQuY2xvc2VzdCgnc3dwLXJlc2l6ZS1oYW5kbGUnKSlcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAvLyBNYXRjaCBib3RoIHN3cC1ldmVudCBhbmQgc3dwLWhlYWRlci1pdGVtXG4gICAgICAgICAgICBjb25zdCBldmVudEVsZW1lbnQgPSB0YXJnZXQuY2xvc2VzdCgnc3dwLWV2ZW50Jyk7XG4gICAgICAgICAgICBjb25zdCBoZWFkZXJJdGVtID0gdGFyZ2V0LmNsb3Nlc3QoJ3N3cC1oZWFkZXItaXRlbScpO1xuICAgICAgICAgICAgY29uc3QgZHJhZ2dhYmxlID0gZXZlbnRFbGVtZW50IHx8IGhlYWRlckl0ZW07XG4gICAgICAgICAgICBpZiAoIWRyYWdnYWJsZSlcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAvLyBTdG9yZSBmb3IgcG90ZW50aWFsIGRyYWdcbiAgICAgICAgICAgIHRoaXMubW91c2VEb3duUG9zaXRpb24gPSB7IHg6IGUuY2xpZW50WCwgeTogZS5jbGllbnRZIH07XG4gICAgICAgICAgICB0aGlzLnBlbmRpbmdFbGVtZW50ID0gZHJhZ2dhYmxlO1xuICAgICAgICAgICAgLy8gQ2FsY3VsYXRlIG1vdXNlIG9mZnNldCB3aXRoaW4gZWxlbWVudFxuICAgICAgICAgICAgY29uc3QgcmVjdCA9IGRyYWdnYWJsZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIHRoaXMucGVuZGluZ01vdXNlT2Zmc2V0ID0ge1xuICAgICAgICAgICAgICAgIHg6IGUuY2xpZW50WCAtIHJlY3QubGVmdCxcbiAgICAgICAgICAgICAgICB5OiBlLmNsaWVudFkgLSByZWN0LnRvcFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIC8vIENhcHR1cmUgcG9pbnRlciBmb3IgcmVsaWFibGUgdHJhY2tpbmdcbiAgICAgICAgICAgIGRyYWdnYWJsZS5zZXRQb2ludGVyQ2FwdHVyZShlLnBvaW50ZXJJZCk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlUG9pbnRlck1vdmUgPSAoZSkgPT4ge1xuICAgICAgICAgICAgLy8gTm90IGluIHBvdGVudGlhbCBkcmFnIHN0YXRlXG4gICAgICAgICAgICBpZiAoIXRoaXMubW91c2VEb3duUG9zaXRpb24gfHwgIXRoaXMucGVuZGluZ0VsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAvLyBBbHJlYWR5IGRyYWdnaW5nIC0gdXBkYXRlIHRhcmdldFxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmRyYWdTdGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZURyYWdUYXJnZXQoZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIENoZWNrIHRocmVzaG9sZFxuICAgICAgICAgICAgY29uc3QgZGVsdGFYID0gTWF0aC5hYnMoZS5jbGllbnRYIC0gdGhpcy5tb3VzZURvd25Qb3NpdGlvbi54KTtcbiAgICAgICAgICAgIGNvbnN0IGRlbHRhWSA9IE1hdGguYWJzKGUuY2xpZW50WSAtIHRoaXMubW91c2VEb3duUG9zaXRpb24ueSk7XG4gICAgICAgICAgICBjb25zdCBkaXN0YW5jZSA9IE1hdGguc3FydChkZWx0YVggKiBkZWx0YVggKyBkZWx0YVkgKiBkZWx0YVkpO1xuICAgICAgICAgICAgaWYgKGRpc3RhbmNlIDwgdGhpcy5EUkFHX1RIUkVTSE9MRClcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAvLyBTdGFydCBkcmFnXG4gICAgICAgICAgICB0aGlzLmluaXRpYWxpemVEcmFnKHRoaXMucGVuZGluZ0VsZW1lbnQsIHRoaXMucGVuZGluZ01vdXNlT2Zmc2V0LCBlKTtcbiAgICAgICAgICAgIHRoaXMubW91c2VEb3duUG9zaXRpb24gPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5wZW5kaW5nRWxlbWVudCA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnBlbmRpbmdNb3VzZU9mZnNldCA9IG51bGw7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaGFuZGxlUG9pbnRlclVwID0gKF9lKSA9PiB7XG4gICAgICAgICAgICAvLyBDbGVhciBwZW5kaW5nIHN0YXRlXG4gICAgICAgICAgICB0aGlzLm1vdXNlRG93blBvc2l0aW9uID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMucGVuZGluZ0VsZW1lbnQgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5wZW5kaW5nTW91c2VPZmZzZXQgPSBudWxsO1xuICAgICAgICAgICAgaWYgKCF0aGlzLmRyYWdTdGF0ZSlcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAvLyBTdG9wIGFuaW1hdGlvblxuICAgICAgICAgICAgY2FuY2VsQW5pbWF0aW9uRnJhbWUodGhpcy5kcmFnU3RhdGUuYW5pbWF0aW9uSWQpO1xuICAgICAgICAgICAgLy8gSGFuZGxlIGJhc2VkIG9uIGRyYWcgc291cmNlIGFuZCB0YXJnZXRcbiAgICAgICAgICAgIGlmICh0aGlzLmRyYWdTdGF0ZS5kcmFnU291cmNlID09PSAnaGVhZGVyJykge1xuICAgICAgICAgICAgICAgIC8vIEhlYWRlciBpdGVtIGRyYWcgZW5kXG4gICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVIZWFkZXJJdGVtRHJhZ0VuZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gR3JpZCBldmVudCBkcmFnIGVuZFxuICAgICAgICAgICAgICAgIHRoaXMuaGFuZGxlR3JpZEV2ZW50RHJhZ0VuZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQ2xlYW51cFxuICAgICAgICAgICAgdGhpcy5kcmFnU3RhdGUuZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCdkcmFnZ2luZycpO1xuICAgICAgICAgICAgdGhpcy5kcmFnU3RhdGUgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5pbkhlYWRlciA9IGZhbHNlO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmFuaW1hdGVEcmFnID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmRyYWdTdGF0ZSlcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICBjb25zdCBkaWZmID0gdGhpcy5kcmFnU3RhdGUudGFyZ2V0WSAtIHRoaXMuZHJhZ1N0YXRlLmN1cnJlbnRZO1xuICAgICAgICAgICAgLy8gU3RvcCBhbmltYXRpb24gd2hlbiBjbG9zZSBlbm91Z2ggdG8gdGFyZ2V0XG4gICAgICAgICAgICBpZiAoTWF0aC5hYnMoZGlmZikgPD0gMC41KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kcmFnU3RhdGUuYW5pbWF0aW9uSWQgPSAwO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEludGVycG9sYXRlIHRvd2FyZHMgdGFyZ2V0XG4gICAgICAgICAgICB0aGlzLmRyYWdTdGF0ZS5jdXJyZW50WSArPSBkaWZmICogdGhpcy5JTlRFUlBPTEFUSU9OX0ZBQ1RPUjtcbiAgICAgICAgICAgIC8vIFVwZGF0ZSBlbGVtZW50IHBvc2l0aW9uXG4gICAgICAgICAgICB0aGlzLmRyYWdTdGF0ZS5lbGVtZW50LnN0eWxlLnRvcCA9IGAke3RoaXMuZHJhZ1N0YXRlLmN1cnJlbnRZfXB4YDtcbiAgICAgICAgICAgIC8vIEVtaXQgZHJhZzptb3ZlIChvbmx5IGlmIHdlIGhhdmUgYSBjb2x1bW4pXG4gICAgICAgICAgICBpZiAodGhpcy5kcmFnU3RhdGUuY29sdW1uRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50SWQ6IHRoaXMuZHJhZ1N0YXRlLmV2ZW50SWQsXG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQ6IHRoaXMuZHJhZ1N0YXRlLmVsZW1lbnQsXG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRZOiB0aGlzLmRyYWdTdGF0ZS5jdXJyZW50WSxcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uRWxlbWVudDogdGhpcy5kcmFnU3RhdGUuY29sdW1uRWxlbWVudFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENvcmVFdmVudHMuRVZFTlRfRFJBR19NT1ZFLCBwYXlsb2FkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIENvbnRpbnVlIGFuaW1hdGlvblxuICAgICAgICAgICAgdGhpcy5kcmFnU3RhdGUuYW5pbWF0aW9uSWQgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy5hbmltYXRlRHJhZyk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc2V0dXBTY3JvbGxMaXN0ZW5lcigpO1xuICAgIH1cbiAgICBzZXR1cFNjcm9sbExpc3RlbmVyKCkge1xuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENvcmVFdmVudHMuRURHRV9TQ1JPTExfVElDSywgKGUpID0+IHtcbiAgICAgICAgICAgIGlmICghdGhpcy5kcmFnU3RhdGUpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgY29uc3QgeyBzY3JvbGxEZWx0YSB9ID0gZS5kZXRhaWw7XG4gICAgICAgICAgICAvLyBFbGVtZW50IHNrYWwgZmx5dHRlIG1lZCBzY3JvbGwgZm9yIGF0IGZvcmJsaXZlIHVuZGVyIG11c2VuXG4gICAgICAgICAgICAvLyAoZWxlbWVudGV0cyB0b3AgZXIgcmVsYXRpdiB0aWwga29sb25uZW4sIHNvbSBzY3JvbGxlciBtZWQgdmlld3BvcnQpXG4gICAgICAgICAgICB0aGlzLmRyYWdTdGF0ZS50YXJnZXRZICs9IHNjcm9sbERlbHRhO1xuICAgICAgICAgICAgdGhpcy5kcmFnU3RhdGUuY3VycmVudFkgKz0gc2Nyb2xsRGVsdGE7XG4gICAgICAgICAgICB0aGlzLmRyYWdTdGF0ZS5lbGVtZW50LnN0eWxlLnRvcCA9IGAke3RoaXMuZHJhZ1N0YXRlLmN1cnJlbnRZfXB4YDtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemUgZHJhZy1kcm9wIG9uIGEgY29udGFpbmVyIGVsZW1lbnRcbiAgICAgKi9cbiAgICBpbml0KGNvbnRhaW5lcikge1xuICAgICAgICB0aGlzLmNvbnRhaW5lciA9IGNvbnRhaW5lcjtcbiAgICAgICAgY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJkb3duJywgdGhpcy5oYW5kbGVQb2ludGVyRG93bik7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJtb3ZlJywgdGhpcy5oYW5kbGVQb2ludGVyTW92ZSk7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJ1cCcsIHRoaXMuaGFuZGxlUG9pbnRlclVwKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSGFuZGxlIGRyYWcgZW5kIGZvciBoZWFkZXIgaXRlbXNcbiAgICAgKi9cbiAgICBoYW5kbGVIZWFkZXJJdGVtRHJhZ0VuZCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmRyYWdTdGF0ZSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgLy8gSWYgZHJvcHBlZCBpbiBncmlkIChub3QgaW4gaGVhZGVyKSwgdGhlIHN3cC1ldmVudCB3YXMgYWxyZWFkeSBjcmVhdGVkXG4gICAgICAgIC8vIGJ5IEV2ZW50UmVuZGVyZXIgbGlzdGVuaW5nIHRvIEVWRU5UX0RSQUdfTEVBVkVfSEVBREVSXG4gICAgICAgIC8vIEp1c3QgZW1pdCBkcmFnOmVuZCBmb3IgcGVyc2lzdGVuY2VcbiAgICAgICAgaWYgKCF0aGlzLmluSGVhZGVyICYmIHRoaXMuZHJhZ1N0YXRlLmN1cnJlbnRDb2x1bW4pIHtcbiAgICAgICAgICAgIC8vIERyb3BwZWQgaW4gZ3JpZCAtIGVtaXQgZHJhZzplbmQgd2l0aCB0aGUgbmV3IHN3cC1ldmVudCBlbGVtZW50XG4gICAgICAgICAgICBjb25zdCBncmlkRXZlbnQgPSB0aGlzLmRyYWdTdGF0ZS5jdXJyZW50Q29sdW1uLnF1ZXJ5U2VsZWN0b3IoYHN3cC1ldmVudFtkYXRhLWV2ZW50LWlkPVwiJHt0aGlzLmRyYWdTdGF0ZS5ldmVudElkfVwiXWApO1xuICAgICAgICAgICAgaWYgKGdyaWRFdmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbHVtbktleSA9IHRoaXMuZHJhZ1N0YXRlLmN1cnJlbnRDb2x1bW4uZGF0YXNldC5jb2x1bW5LZXkgfHwgJyc7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0ZSA9IHRoaXMuZHJhZ1N0YXRlLmN1cnJlbnRDb2x1bW4uZGF0YXNldC5kYXRlIHx8ICcnO1xuICAgICAgICAgICAgICAgIGNvbnN0IHN3cEV2ZW50ID0gU3dwRXZlbnQuZnJvbUVsZW1lbnQoZ3JpZEV2ZW50LCBjb2x1bW5LZXksIGRhdGUsIHRoaXMuZ3JpZENvbmZpZyk7XG4gICAgICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgICAgICAgICAgICAgc3dwRXZlbnQsXG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZUNvbHVtbktleTogdGhpcy5kcmFnU3RhdGUuc291cmNlQ29sdW1uS2V5LFxuICAgICAgICAgICAgICAgICAgICB0YXJnZXQ6ICdncmlkJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENvcmVFdmVudHMuRVZFTlRfRFJBR19FTkQsIHBheWxvYWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIElmIHN0aWxsIGluIGhlYWRlciwgbm8gcGVyc2lzdGVuY2UgbmVlZGVkIChzdGF5ZWQgaW4gaGVhZGVyKVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgZHJhZyBlbmQgZm9yIGdyaWQgZXZlbnRzXG4gICAgICovXG4gICAgaGFuZGxlR3JpZEV2ZW50RHJhZ0VuZCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmRyYWdTdGF0ZSB8fCAhdGhpcy5kcmFnU3RhdGUuY29sdW1uRWxlbWVudClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgLy8gU25hcCB0byBncmlkXG4gICAgICAgIGNvbnN0IHNuYXBwZWRZID0gc25hcFRvR3JpZCh0aGlzLmRyYWdTdGF0ZS5jdXJyZW50WSwgdGhpcy5ncmlkQ29uZmlnKTtcbiAgICAgICAgdGhpcy5kcmFnU3RhdGUuZWxlbWVudC5zdHlsZS50b3AgPSBgJHtzbmFwcGVkWX1weGA7XG4gICAgICAgIC8vIFJlbW92ZSBnaG9zdFxuICAgICAgICB0aGlzLmRyYWdTdGF0ZS5naG9zdEVsZW1lbnQ/LnJlbW92ZSgpO1xuICAgICAgICAvLyBHZXQgY29sdW1uS2V5IGFuZCBkYXRlIGZyb20gdGFyZ2V0IGNvbHVtblxuICAgICAgICBjb25zdCBjb2x1bW5LZXkgPSB0aGlzLmRyYWdTdGF0ZS5jb2x1bW5FbGVtZW50LmRhdGFzZXQuY29sdW1uS2V5IHx8ICcnO1xuICAgICAgICBjb25zdCBkYXRlID0gdGhpcy5kcmFnU3RhdGUuY29sdW1uRWxlbWVudC5kYXRhc2V0LmRhdGUgfHwgJyc7XG4gICAgICAgIC8vIENyZWF0ZSBTd3BFdmVudCBmcm9tIGVsZW1lbnQgKHJlYWRzIHRvcC9oZWlnaHQvZXZlbnRJZCBmcm9tIGVsZW1lbnQpXG4gICAgICAgIGNvbnN0IHN3cEV2ZW50ID0gU3dwRXZlbnQuZnJvbUVsZW1lbnQodGhpcy5kcmFnU3RhdGUuZWxlbWVudCwgY29sdW1uS2V5LCBkYXRlLCB0aGlzLmdyaWRDb25maWcpO1xuICAgICAgICAvLyBFbWl0IGRyYWc6ZW5kXG4gICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgICAgICBzd3BFdmVudCxcbiAgICAgICAgICAgIHNvdXJjZUNvbHVtbktleTogdGhpcy5kcmFnU3RhdGUuc291cmNlQ29sdW1uS2V5LFxuICAgICAgICAgICAgdGFyZ2V0OiB0aGlzLmluSGVhZGVyID8gJ2hlYWRlcicgOiAnZ3JpZCdcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENvcmVFdmVudHMuRVZFTlRfRFJBR19FTkQsIHBheWxvYWQpO1xuICAgIH1cbiAgICBpbml0aWFsaXplRHJhZyhlbGVtZW50LCBtb3VzZU9mZnNldCwgZSkge1xuICAgICAgICBjb25zdCBldmVudElkID0gZWxlbWVudC5kYXRhc2V0LmV2ZW50SWQgfHwgJyc7XG4gICAgICAgIGNvbnN0IGlzSGVhZGVySXRlbSA9IGVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnc3dwLWhlYWRlci1pdGVtJztcbiAgICAgICAgY29uc3QgY29sdW1uRWxlbWVudCA9IGVsZW1lbnQuY2xvc2VzdCgnc3dwLWRheS1jb2x1bW4nKTtcbiAgICAgICAgLy8gRm9yIGdyaWQgZXZlbnRzLCB3ZSBuZWVkIGEgY29sdW1uXG4gICAgICAgIGlmICghaXNIZWFkZXJJdGVtICYmICFjb2x1bW5FbGVtZW50KVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBpZiAoaXNIZWFkZXJJdGVtKSB7XG4gICAgICAgICAgICAvLyBIZWFkZXIgaXRlbSBkcmFnIGluaXRpYWxpemF0aW9uXG4gICAgICAgICAgICB0aGlzLmluaXRpYWxpemVIZWFkZXJJdGVtRHJhZyhlbGVtZW50LCBtb3VzZU9mZnNldCwgZXZlbnRJZCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBHcmlkIGV2ZW50IGRyYWcgaW5pdGlhbGl6YXRpb25cbiAgICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZUdyaWRFdmVudERyYWcoZWxlbWVudCwgbW91c2VPZmZzZXQsIGUsIGNvbHVtbkVsZW1lbnQsIGV2ZW50SWQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemUgZHJhZyBmb3IgYSBoZWFkZXIgaXRlbSAoYWxsRGF5IGV2ZW50KVxuICAgICAqL1xuICAgIGluaXRpYWxpemVIZWFkZXJJdGVtRHJhZyhlbGVtZW50LCBtb3VzZU9mZnNldCwgZXZlbnRJZCkge1xuICAgICAgICAvLyBNYXJrIGFzIGRyYWdnaW5nXG4gICAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LmFkZCgnZHJhZ2dpbmcnKTtcbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBkcmFnIHN0YXRlIGZvciBoZWFkZXIgaXRlbVxuICAgICAgICB0aGlzLmRyYWdTdGF0ZSA9IHtcbiAgICAgICAgICAgIGV2ZW50SWQsXG4gICAgICAgICAgICBlbGVtZW50LFxuICAgICAgICAgICAgZ2hvc3RFbGVtZW50OiBudWxsLCAvLyBObyBnaG9zdCBmb3IgaGVhZGVyIGl0ZW1zXG4gICAgICAgICAgICBzdGFydFk6IDAsXG4gICAgICAgICAgICBtb3VzZU9mZnNldCxcbiAgICAgICAgICAgIGNvbHVtbkVsZW1lbnQ6IG51bGwsXG4gICAgICAgICAgICBjdXJyZW50Q29sdW1uOiBudWxsLFxuICAgICAgICAgICAgdGFyZ2V0WTogMCxcbiAgICAgICAgICAgIGN1cnJlbnRZOiAwLFxuICAgICAgICAgICAgYW5pbWF0aW9uSWQ6IDAsXG4gICAgICAgICAgICBzb3VyY2VDb2x1bW5LZXk6ICcnLCAvLyBXaWxsIGJlIHNldCBmcm9tIGhlYWRlciBpdGVtIGRhdGFcbiAgICAgICAgICAgIGRyYWdTb3VyY2U6ICdoZWFkZXInXG4gICAgICAgIH07XG4gICAgICAgIC8vIFN0YXJ0IGluIGhlYWRlciBtb2RlXG4gICAgICAgIHRoaXMuaW5IZWFkZXIgPSB0cnVlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplIGRyYWcgZm9yIGEgZ3JpZCBldmVudFxuICAgICAqL1xuICAgIGluaXRpYWxpemVHcmlkRXZlbnREcmFnKGVsZW1lbnQsIG1vdXNlT2Zmc2V0LCBlLCBjb2x1bW5FbGVtZW50LCBldmVudElkKSB7XG4gICAgICAgIC8vIENhbGN1bGF0ZSBhYnNvbHV0ZSBZIHBvc2l0aW9uIHVzaW5nIGdldEJvdW5kaW5nQ2xpZW50UmVjdFxuICAgICAgICBjb25zdCBlbGVtZW50UmVjdCA9IGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIGNvbnN0IGNvbHVtblJlY3QgPSBjb2x1bW5FbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICBjb25zdCBzdGFydFkgPSBlbGVtZW50UmVjdC50b3AgLSBjb2x1bW5SZWN0LnRvcDtcbiAgICAgICAgLy8gSWYgZXZlbnQgaXMgaW5zaWRlIGEgZ3JvdXAsIG1vdmUgaXQgdG8gZXZlbnRzLWxheWVyIGZvciBjb3JyZWN0IHBvc2l0aW9uaW5nIGR1cmluZyBkcmFnXG4gICAgICAgIGNvbnN0IGdyb3VwID0gZWxlbWVudC5jbG9zZXN0KCdzd3AtZXZlbnQtZ3JvdXAnKTtcbiAgICAgICAgaWYgKGdyb3VwKSB7XG4gICAgICAgICAgICBjb25zdCBldmVudHNMYXllciA9IGNvbHVtbkVsZW1lbnQucXVlcnlTZWxlY3Rvcignc3dwLWV2ZW50cy1sYXllcicpO1xuICAgICAgICAgICAgaWYgKGV2ZW50c0xheWVyKSB7XG4gICAgICAgICAgICAgICAgZXZlbnRzTGF5ZXIuYXBwZW5kQ2hpbGQoZWxlbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gU2V0IGNvbnNpc3RlbnQgcG9zaXRpb25pbmcgZm9yIGRyYWcgKHdvcmtzIGZvciBib3RoIGdyb3VwZWQgYW5kIHN0YWNrZWQgZXZlbnRzKVxuICAgICAgICBlbGVtZW50LnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICAgICAgZWxlbWVudC5zdHlsZS50b3AgPSBgJHtzdGFydFl9cHhgO1xuICAgICAgICBlbGVtZW50LnN0eWxlLmxlZnQgPSAnMnB4JztcbiAgICAgICAgZWxlbWVudC5zdHlsZS5yaWdodCA9ICcycHgnO1xuICAgICAgICBlbGVtZW50LnN0eWxlLm1hcmdpbkxlZnQgPSAnMCc7IC8vIFJlc2V0IHN0YWNraW5nIG1hcmdpblxuICAgICAgICAvLyBDcmVhdGUgZ2hvc3QgY2xvbmVcbiAgICAgICAgY29uc3QgZ2hvc3RFbGVtZW50ID0gZWxlbWVudC5jbG9uZU5vZGUodHJ1ZSk7XG4gICAgICAgIGdob3N0RWxlbWVudC5jbGFzc0xpc3QuYWRkKCdkcmFnLWdob3N0Jyk7XG4gICAgICAgIGdob3N0RWxlbWVudC5zdHlsZS5vcGFjaXR5ID0gJzAuMyc7XG4gICAgICAgIGdob3N0RWxlbWVudC5zdHlsZS5wb2ludGVyRXZlbnRzID0gJ25vbmUnO1xuICAgICAgICAvLyBJbnNlcnQgZ2hvc3QgYmVmb3JlIG9yaWdpbmFsXG4gICAgICAgIGVsZW1lbnQucGFyZW50Tm9kZT8uaW5zZXJ0QmVmb3JlKGdob3N0RWxlbWVudCwgZWxlbWVudCk7XG4gICAgICAgIC8vIFNldHVwIGVsZW1lbnQgZm9yIGRyYWdnaW5nXG4gICAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LmFkZCgnZHJhZ2dpbmcnKTtcbiAgICAgICAgLy8gQ2FsY3VsYXRlIGluaXRpYWwgdGFyZ2V0IGZyb20gbW91c2UgcG9zaXRpb25cbiAgICAgICAgY29uc3QgdGFyZ2V0WSA9IGUuY2xpZW50WSAtIGNvbHVtblJlY3QudG9wIC0gbW91c2VPZmZzZXQueTtcbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBkcmFnIHN0YXRlXG4gICAgICAgIHRoaXMuZHJhZ1N0YXRlID0ge1xuICAgICAgICAgICAgZXZlbnRJZCxcbiAgICAgICAgICAgIGVsZW1lbnQsXG4gICAgICAgICAgICBnaG9zdEVsZW1lbnQsXG4gICAgICAgICAgICBzdGFydFksXG4gICAgICAgICAgICBtb3VzZU9mZnNldCxcbiAgICAgICAgICAgIGNvbHVtbkVsZW1lbnQsXG4gICAgICAgICAgICBjdXJyZW50Q29sdW1uOiBjb2x1bW5FbGVtZW50LFxuICAgICAgICAgICAgdGFyZ2V0WTogTWF0aC5tYXgoMCwgdGFyZ2V0WSksXG4gICAgICAgICAgICBjdXJyZW50WTogc3RhcnRZLFxuICAgICAgICAgICAgYW5pbWF0aW9uSWQ6IDAsXG4gICAgICAgICAgICBzb3VyY2VDb2x1bW5LZXk6IGNvbHVtbkVsZW1lbnQuZGF0YXNldC5jb2x1bW5LZXkgfHwgJycsXG4gICAgICAgICAgICBkcmFnU291cmNlOiAnZ3JpZCdcbiAgICAgICAgfTtcbiAgICAgICAgLy8gRW1pdCBkcmFnOnN0YXJ0XG4gICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgICAgICBldmVudElkLFxuICAgICAgICAgICAgZWxlbWVudCxcbiAgICAgICAgICAgIGdob3N0RWxlbWVudCxcbiAgICAgICAgICAgIHN0YXJ0WSxcbiAgICAgICAgICAgIG1vdXNlT2Zmc2V0LFxuICAgICAgICAgICAgY29sdW1uRWxlbWVudFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ29yZUV2ZW50cy5FVkVOVF9EUkFHX1NUQVJULCBwYXlsb2FkKTtcbiAgICAgICAgLy8gU3RhcnQgYW5pbWF0aW9uIGxvb3BcbiAgICAgICAgdGhpcy5hbmltYXRlRHJhZygpO1xuICAgIH1cbiAgICB1cGRhdGVEcmFnVGFyZ2V0KGUpIHtcbiAgICAgICAgaWYgKCF0aGlzLmRyYWdTdGF0ZSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgLy8gQ2hlY2sgaGVhZGVyIHpvbmUgZmlyc3RcbiAgICAgICAgdGhpcy5jaGVja0hlYWRlclpvbmUoZSk7XG4gICAgICAgIC8vIFNraXAgbm9ybWFsIGdyaWQgaGFuZGxpbmcgaWYgaW4gaGVhZGVyXG4gICAgICAgIGlmICh0aGlzLmluSGVhZGVyKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAvLyBDaGVjayBmb3IgY29sdW1uIGNoYW5nZVxuICAgICAgICBjb25zdCBjb2x1bW5BdFBvaW50ID0gdGhpcy5nZXRDb2x1bW5BdFBvaW50KGUuY2xpZW50WCk7XG4gICAgICAgIC8vIEZvciBoZWFkZXIgaXRlbXMgZW50ZXJpbmcgZ3JpZCwgc2V0IGluaXRpYWwgY29sdW1uXG4gICAgICAgIGlmICh0aGlzLmRyYWdTdGF0ZS5kcmFnU291cmNlID09PSAnaGVhZGVyJyAmJiBjb2x1bW5BdFBvaW50ICYmICF0aGlzLmRyYWdTdGF0ZS5jdXJyZW50Q29sdW1uKSB7XG4gICAgICAgICAgICB0aGlzLmRyYWdTdGF0ZS5jdXJyZW50Q29sdW1uID0gY29sdW1uQXRQb2ludDtcbiAgICAgICAgICAgIHRoaXMuZHJhZ1N0YXRlLmNvbHVtbkVsZW1lbnQgPSBjb2x1bW5BdFBvaW50O1xuICAgICAgICB9XG4gICAgICAgIGlmIChjb2x1bW5BdFBvaW50ICYmIGNvbHVtbkF0UG9pbnQgIT09IHRoaXMuZHJhZ1N0YXRlLmN1cnJlbnRDb2x1bW4gJiYgdGhpcy5kcmFnU3RhdGUuY3VycmVudENvbHVtbikge1xuICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgICAgICAgICBldmVudElkOiB0aGlzLmRyYWdTdGF0ZS5ldmVudElkLFxuICAgICAgICAgICAgICAgIGVsZW1lbnQ6IHRoaXMuZHJhZ1N0YXRlLmVsZW1lbnQsXG4gICAgICAgICAgICAgICAgcHJldmlvdXNDb2x1bW46IHRoaXMuZHJhZ1N0YXRlLmN1cnJlbnRDb2x1bW4sXG4gICAgICAgICAgICAgICAgbmV3Q29sdW1uOiBjb2x1bW5BdFBvaW50LFxuICAgICAgICAgICAgICAgIGN1cnJlbnRZOiB0aGlzLmRyYWdTdGF0ZS5jdXJyZW50WVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMuZW1pdChDb3JlRXZlbnRzLkVWRU5UX0RSQUdfQ09MVU1OX0NIQU5HRSwgcGF5bG9hZCk7XG4gICAgICAgICAgICB0aGlzLmRyYWdTdGF0ZS5jdXJyZW50Q29sdW1uID0gY29sdW1uQXRQb2ludDtcbiAgICAgICAgICAgIHRoaXMuZHJhZ1N0YXRlLmNvbHVtbkVsZW1lbnQgPSBjb2x1bW5BdFBvaW50O1xuICAgICAgICB9XG4gICAgICAgIC8vIFNraXAgZ3JpZCBwb3NpdGlvbiB1cGRhdGVzIGlmIG5vIGNvbHVtbiB5ZXRcbiAgICAgICAgaWYgKCF0aGlzLmRyYWdTdGF0ZS5jb2x1bW5FbGVtZW50KVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBjb25zdCBjb2x1bW5SZWN0ID0gdGhpcy5kcmFnU3RhdGUuY29sdW1uRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgY29uc3QgdGFyZ2V0WSA9IGUuY2xpZW50WSAtIGNvbHVtblJlY3QudG9wIC0gdGhpcy5kcmFnU3RhdGUubW91c2VPZmZzZXQueTtcbiAgICAgICAgdGhpcy5kcmFnU3RhdGUudGFyZ2V0WSA9IE1hdGgubWF4KDAsIHRhcmdldFkpO1xuICAgICAgICAvLyBTdGFydCBhbmltYXRpb24gaWYgbm90IHJ1bm5pbmdcbiAgICAgICAgaWYgKCF0aGlzLmRyYWdTdGF0ZS5hbmltYXRpb25JZCkge1xuICAgICAgICAgICAgdGhpcy5hbmltYXRlRHJhZygpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIHBvaW50ZXIgaXMgaW4gaGVhZGVyIHpvbmUgYW5kIGVtaXQgYXBwcm9wcmlhdGUgZXZlbnRzXG4gICAgICovXG4gICAgY2hlY2tIZWFkZXJab25lKGUpIHtcbiAgICAgICAgaWYgKCF0aGlzLmRyYWdTdGF0ZSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY29uc3QgaGVhZGVyVmlld3BvcnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdzd3AtaGVhZGVyLXZpZXdwb3J0Jyk7XG4gICAgICAgIGlmICghaGVhZGVyVmlld3BvcnQpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNvbnN0IHJlY3QgPSBoZWFkZXJWaWV3cG9ydC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgY29uc3QgaXNJbkhlYWRlciA9IGUuY2xpZW50WSA8IHJlY3QuYm90dG9tO1xuICAgICAgICBpZiAoaXNJbkhlYWRlciAmJiAhdGhpcy5pbkhlYWRlcikge1xuICAgICAgICAgICAgLy8gRW50ZXJlZCBoZWFkZXIgKGZyb20gZ3JpZClcbiAgICAgICAgICAgIHRoaXMuaW5IZWFkZXIgPSB0cnVlO1xuICAgICAgICAgICAgaWYgKHRoaXMuZHJhZ1N0YXRlLmRyYWdTb3VyY2UgPT09ICdncmlkJyAmJiB0aGlzLmRyYWdTdGF0ZS5jb2x1bW5FbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRJZDogdGhpcy5kcmFnU3RhdGUuZXZlbnRJZCxcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogdGhpcy5kcmFnU3RhdGUuZWxlbWVudCxcbiAgICAgICAgICAgICAgICAgICAgc291cmNlQ29sdW1uSW5kZXg6IHRoaXMuZ2V0Q29sdW1uSW5kZXgodGhpcy5kcmFnU3RhdGUuY29sdW1uRWxlbWVudCksXG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZUNvbHVtbktleTogdGhpcy5kcmFnU3RhdGUuY29sdW1uRWxlbWVudC5kYXRhc2V0LmNvbHVtbktleSB8fCAnJyxcbiAgICAgICAgICAgICAgICAgICAgdGl0bGU6IHRoaXMuZHJhZ1N0YXRlLmVsZW1lbnQucXVlcnlTZWxlY3Rvcignc3dwLWV2ZW50LXRpdGxlJyk/LnRleHRDb250ZW50IHx8ICcnLFxuICAgICAgICAgICAgICAgICAgICBjb2xvckNsYXNzOiBbLi4udGhpcy5kcmFnU3RhdGUuZWxlbWVudC5jbGFzc0xpc3RdLmZpbmQoYyA9PiBjLnN0YXJ0c1dpdGgoJ2lzLScpKSxcbiAgICAgICAgICAgICAgICAgICAgaXRlbVR5cGU6ICdldmVudCcsXG4gICAgICAgICAgICAgICAgICAgIGR1cmF0aW9uOiAxXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ29yZUV2ZW50cy5FVkVOVF9EUkFHX0VOVEVSX0hFQURFUiwgcGF5bG9hZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBGb3IgaGVhZGVyIHNvdXJjZSByZS1lbnRlcmluZyBoZWFkZXIsIGp1c3QgdXBkYXRlIGluSGVhZGVyIGZsYWdcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghaXNJbkhlYWRlciAmJiB0aGlzLmluSGVhZGVyKSB7XG4gICAgICAgICAgICAvLyBMZWZ0IGhlYWRlciAoZW50ZXJpbmcgZ3JpZClcbiAgICAgICAgICAgIHRoaXMuaW5IZWFkZXIgPSBmYWxzZTtcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldENvbHVtbiA9IHRoaXMuZ2V0Q29sdW1uQXRQb2ludChlLmNsaWVudFgpO1xuICAgICAgICAgICAgaWYgKHRoaXMuZHJhZ1N0YXRlLmRyYWdTb3VyY2UgPT09ICdoZWFkZXInKSB7XG4gICAgICAgICAgICAgICAgLy8gSGVhZGVyIGl0ZW0gbGVhdmluZyBoZWFkZXIgXHUyMTkyIGNyZWF0ZSBzd3AtZXZlbnQgaW4gZ3JpZFxuICAgICAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50SWQ6IHRoaXMuZHJhZ1N0YXRlLmV2ZW50SWQsXG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZTogJ2hlYWRlcicsXG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQ6IHRoaXMuZHJhZ1N0YXRlLmVsZW1lbnQsXG4gICAgICAgICAgICAgICAgICAgIHRhcmdldENvbHVtbjogdGFyZ2V0Q29sdW1uIHx8IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IHRoaXMuZHJhZ1N0YXRlLmVsZW1lbnQuZGF0YXNldC5zdGFydCA/IG5ldyBEYXRlKHRoaXMuZHJhZ1N0YXRlLmVsZW1lbnQuZGF0YXNldC5zdGFydCkgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICAgIGVuZDogdGhpcy5kcmFnU3RhdGUuZWxlbWVudC5kYXRhc2V0LmVuZCA/IG5ldyBEYXRlKHRoaXMuZHJhZ1N0YXRlLmVsZW1lbnQuZGF0YXNldC5lbmQpIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgICAgICB0aXRsZTogdGhpcy5kcmFnU3RhdGUuZWxlbWVudC50ZXh0Q29udGVudCB8fCAnJyxcbiAgICAgICAgICAgICAgICAgICAgY29sb3JDbGFzczogWy4uLnRoaXMuZHJhZ1N0YXRlLmVsZW1lbnQuY2xhc3NMaXN0XS5maW5kKGMgPT4gYy5zdGFydHNXaXRoKCdpcy0nKSlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMuZW1pdChDb3JlRXZlbnRzLkVWRU5UX0RSQUdfTEVBVkVfSEVBREVSLCBwYXlsb2FkKTtcbiAgICAgICAgICAgICAgICAvLyBSZS1hdHRhY2ggdG8gdGhlIG5ldyBzd3AtZXZlbnQgY3JlYXRlZCBieSBFdmVudFJlbmRlcmVyXG4gICAgICAgICAgICAgICAgaWYgKHRhcmdldENvbHVtbikge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdFbGVtZW50ID0gdGFyZ2V0Q29sdW1uLnF1ZXJ5U2VsZWN0b3IoYHN3cC1ldmVudFtkYXRhLWV2ZW50LWlkPVwiJHt0aGlzLmRyYWdTdGF0ZS5ldmVudElkfVwiXWApO1xuICAgICAgICAgICAgICAgICAgICBpZiAobmV3RWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kcmFnU3RhdGUuZWxlbWVudCA9IG5ld0VsZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRyYWdTdGF0ZS5jb2x1bW5FbGVtZW50ID0gdGFyZ2V0Q29sdW1uO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kcmFnU3RhdGUuY3VycmVudENvbHVtbiA9IHRhcmdldENvbHVtbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN0YXJ0IGFuaW1hdGlvbiBmb3IgdGhlIG5ldyBlbGVtZW50XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFuaW1hdGVEcmFnKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBHcmlkIGV2ZW50IGxlYXZpbmcgaGVhZGVyIFx1MjE5MiByZXN0b3JlIHRvIGdyaWRcbiAgICAgICAgICAgICAgICBjb25zdCBwYXlsb2FkID0ge1xuICAgICAgICAgICAgICAgICAgICBldmVudElkOiB0aGlzLmRyYWdTdGF0ZS5ldmVudElkLFxuICAgICAgICAgICAgICAgICAgICBzb3VyY2U6ICdncmlkJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENvcmVFdmVudHMuRVZFTlRfRFJBR19MRUFWRV9IRUFERVIsIHBheWxvYWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGlzSW5IZWFkZXIpIHtcbiAgICAgICAgICAgIC8vIE1vdmluZyB3aXRoaW4gaGVhZGVyXG4gICAgICAgICAgICBjb25zdCBjb2x1bW4gPSB0aGlzLmdldENvbHVtbkF0WChlLmNsaWVudFgpO1xuICAgICAgICAgICAgaWYgKGNvbHVtbikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50SWQ6IHRoaXMuZHJhZ1N0YXRlLmV2ZW50SWQsXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkluZGV4OiB0aGlzLmdldENvbHVtbkluZGV4KGNvbHVtbiksXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbktleTogY29sdW1uLmRhdGFzZXQuY29sdW1uS2V5IHx8ICcnXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ29yZUV2ZW50cy5FVkVOVF9EUkFHX01PVkVfSEVBREVSLCBwYXlsb2FkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgY29sdW1uIGluZGV4ICgwLWJhc2VkKSBmb3IgYSBjb2x1bW4gZWxlbWVudFxuICAgICAqL1xuICAgIGdldENvbHVtbkluZGV4KGNvbHVtbikge1xuICAgICAgICBpZiAoIXRoaXMuY29udGFpbmVyIHx8ICFjb2x1bW4pXG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgY29uc3QgY29sdW1ucyA9IEFycmF5LmZyb20odGhpcy5jb250YWluZXIucXVlcnlTZWxlY3RvckFsbCgnc3dwLWRheS1jb2x1bW4nKSk7XG4gICAgICAgIHJldHVybiBjb2x1bW5zLmluZGV4T2YoY29sdW1uKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGNvbHVtbiBhdCBYIGNvb3JkaW5hdGUgKGFsaWFzIGZvciBnZXRDb2x1bW5BdFBvaW50KVxuICAgICAqL1xuICAgIGdldENvbHVtbkF0WChjbGllbnRYKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENvbHVtbkF0UG9pbnQoY2xpZW50WCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEZpbmQgY29sdW1uIGVsZW1lbnQgYXQgZ2l2ZW4gWCBjb29yZGluYXRlXG4gICAgICovXG4gICAgZ2V0Q29sdW1uQXRQb2ludChjbGllbnRYKSB7XG4gICAgICAgIGlmICghdGhpcy5jb250YWluZXIpXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgY29uc3QgY29sdW1ucyA9IHRoaXMuY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3JBbGwoJ3N3cC1kYXktY29sdW1uJyk7XG4gICAgICAgIGZvciAoY29uc3QgY29sIG9mIGNvbHVtbnMpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlY3QgPSBjb2wuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICBpZiAoY2xpZW50WCA+PSByZWN0LmxlZnQgJiYgY2xpZW50WCA8PSByZWN0LnJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ2FuY2VsIGRyYWcgYW5kIGFuaW1hdGUgYmFjayB0byBzdGFydCBwb3NpdGlvblxuICAgICAqL1xuICAgIGNhbmNlbERyYWcoKSB7XG4gICAgICAgIGlmICghdGhpcy5kcmFnU3RhdGUpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIC8vIFN0b3AgYW5pbWF0aW9uXG4gICAgICAgIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHRoaXMuZHJhZ1N0YXRlLmFuaW1hdGlvbklkKTtcbiAgICAgICAgY29uc3QgeyBlbGVtZW50LCBnaG9zdEVsZW1lbnQsIHN0YXJ0WSwgZXZlbnRJZCB9ID0gdGhpcy5kcmFnU3RhdGU7XG4gICAgICAgIC8vIEFuaW1hdGUgYmFjayB0byBzdGFydFxuICAgICAgICBlbGVtZW50LnN0eWxlLnRyYW5zaXRpb24gPSAndG9wIDIwMG1zIGVhc2Utb3V0JztcbiAgICAgICAgZWxlbWVudC5zdHlsZS50b3AgPSBgJHtzdGFydFl9cHhgO1xuICAgICAgICAvLyBSZW1vdmUgZ2hvc3QgYWZ0ZXIgYW5pbWF0aW9uIChpZiBleGlzdHMpXG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgZ2hvc3RFbGVtZW50Py5yZW1vdmUoKTtcbiAgICAgICAgICAgIGVsZW1lbnQuc3R5bGUudHJhbnNpdGlvbiA9ICcnO1xuICAgICAgICAgICAgZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCdkcmFnZ2luZycpO1xuICAgICAgICB9LCAyMDApO1xuICAgICAgICAvLyBFbWl0IGRyYWc6Y2FuY2VsXG4gICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgICAgICBldmVudElkLFxuICAgICAgICAgICAgZWxlbWVudCxcbiAgICAgICAgICAgIHN0YXJ0WVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ29yZUV2ZW50cy5FVkVOVF9EUkFHX0NBTkNFTCwgcGF5bG9hZCk7XG4gICAgICAgIHRoaXMuZHJhZ1N0YXRlID0gbnVsbDtcbiAgICAgICAgdGhpcy5pbkhlYWRlciA9IGZhbHNlO1xuICAgIH1cbn1cbiIsICJpbXBvcnQgeyBDb3JlRXZlbnRzIH0gZnJvbSAnLi4vY29uc3RhbnRzL0NvcmVFdmVudHMnO1xuZXhwb3J0IGNsYXNzIEVkZ2VTY3JvbGxNYW5hZ2VyIHtcbiAgICBjb25zdHJ1Y3RvcihldmVudEJ1cykge1xuICAgICAgICB0aGlzLmV2ZW50QnVzID0gZXZlbnRCdXM7XG4gICAgICAgIHRoaXMuc2Nyb2xsYWJsZUNvbnRlbnQgPSBudWxsO1xuICAgICAgICB0aGlzLnRpbWVHcmlkID0gbnVsbDtcbiAgICAgICAgdGhpcy5kcmFnZ2VkRWxlbWVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuc2Nyb2xsUkFGID0gbnVsbDtcbiAgICAgICAgdGhpcy5tb3VzZVkgPSAwO1xuICAgICAgICB0aGlzLmlzRHJhZ2dpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5pc1Njcm9sbGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmxhc3RUcyA9IDA7XG4gICAgICAgIHRoaXMucmVjdCA9IG51bGw7XG4gICAgICAgIHRoaXMuaW5pdGlhbFNjcm9sbFRvcCA9IDA7XG4gICAgICAgIHRoaXMuT1VURVJfWk9ORSA9IDEwMDtcbiAgICAgICAgdGhpcy5JTk5FUl9aT05FID0gNTA7XG4gICAgICAgIHRoaXMuU0xPV19TUEVFRCA9IDE0MDtcbiAgICAgICAgdGhpcy5GQVNUX1NQRUVEID0gNjQwO1xuICAgICAgICB0aGlzLnRyYWNrTW91c2UgPSAoZSkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNEcmFnZ2luZykge1xuICAgICAgICAgICAgICAgIHRoaXMubW91c2VZID0gZS5jbGllbnRZO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLnNjcm9sbFRpY2sgPSAodHMpID0+IHtcbiAgICAgICAgICAgIGlmICghdGhpcy5pc0RyYWdnaW5nIHx8ICF0aGlzLnNjcm9sbGFibGVDb250ZW50KVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIGNvbnN0IGR0ID0gdGhpcy5sYXN0VHMgPyAodHMgLSB0aGlzLmxhc3RUcykgLyAxMDAwIDogMDtcbiAgICAgICAgICAgIHRoaXMubGFzdFRzID0gdHM7XG4gICAgICAgICAgICB0aGlzLnJlY3QgPz8gKHRoaXMucmVjdCA9IHRoaXMuc2Nyb2xsYWJsZUNvbnRlbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkpO1xuICAgICAgICAgICAgY29uc3QgdmVsb2NpdHkgPSB0aGlzLmNhbGN1bGF0ZVZlbG9jaXR5KCk7XG4gICAgICAgICAgICBpZiAodmVsb2NpdHkgIT09IDAgJiYgIXRoaXMuaXNBdEJvdW5kYXJ5KHZlbG9jaXR5KSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHNjcm9sbERlbHRhID0gdmVsb2NpdHkgKiBkdDtcbiAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbGFibGVDb250ZW50LnNjcm9sbFRvcCArPSBzY3JvbGxEZWx0YTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlY3QgPSBudWxsO1xuICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMuZW1pdChDb3JlRXZlbnRzLkVER0VfU0NST0xMX1RJQ0ssIHsgc2Nyb2xsRGVsdGEgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTY3JvbGxpbmdTdGF0ZSh0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U2Nyb2xsaW5nU3RhdGUoZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zY3JvbGxSQUYgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy5zY3JvbGxUaWNrKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5zdWJzY3JpYmVUb0V2ZW50cygpO1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdwb2ludGVybW92ZScsIHRoaXMudHJhY2tNb3VzZSk7XG4gICAgfVxuICAgIGluaXQoc2Nyb2xsYWJsZUNvbnRlbnQpIHtcbiAgICAgICAgdGhpcy5zY3JvbGxhYmxlQ29udGVudCA9IHNjcm9sbGFibGVDb250ZW50O1xuICAgICAgICB0aGlzLnRpbWVHcmlkID0gc2Nyb2xsYWJsZUNvbnRlbnQucXVlcnlTZWxlY3Rvcignc3dwLXRpbWUtZ3JpZCcpO1xuICAgICAgICB0aGlzLnNjcm9sbGFibGVDb250ZW50LnN0eWxlLnNjcm9sbEJlaGF2aW9yID0gJ2F1dG8nO1xuICAgIH1cbiAgICBzdWJzY3JpYmVUb0V2ZW50cygpIHtcbiAgICAgICAgdGhpcy5ldmVudEJ1cy5vbihDb3JlRXZlbnRzLkVWRU5UX0RSQUdfU1RBUlQsIChldmVudCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IGV2ZW50LmRldGFpbDtcbiAgICAgICAgICAgIHRoaXMuZHJhZ2dlZEVsZW1lbnQgPSBwYXlsb2FkLmVsZW1lbnQ7XG4gICAgICAgICAgICB0aGlzLnN0YXJ0RHJhZygpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5ldmVudEJ1cy5vbihDb3JlRXZlbnRzLkVWRU5UX0RSQUdfRU5ELCAoKSA9PiB0aGlzLnN0b3BEcmFnKCkpO1xuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENvcmVFdmVudHMuRVZFTlRfRFJBR19DQU5DRUwsICgpID0+IHRoaXMuc3RvcERyYWcoKSk7XG4gICAgfVxuICAgIHN0YXJ0RHJhZygpIHtcbiAgICAgICAgdGhpcy5pc0RyYWdnaW5nID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5pc1Njcm9sbGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmxhc3RUcyA9IDA7XG4gICAgICAgIHRoaXMuaW5pdGlhbFNjcm9sbFRvcCA9IHRoaXMuc2Nyb2xsYWJsZUNvbnRlbnQ/LnNjcm9sbFRvcCA/PyAwO1xuICAgICAgICBpZiAodGhpcy5zY3JvbGxSQUYgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsUkFGID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHRoaXMuc2Nyb2xsVGljayk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgc3RvcERyYWcoKSB7XG4gICAgICAgIHRoaXMuaXNEcmFnZ2luZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLnNldFNjcm9sbGluZ1N0YXRlKGZhbHNlKTtcbiAgICAgICAgaWYgKHRoaXMuc2Nyb2xsUkFGICE9PSBudWxsKSB7XG4gICAgICAgICAgICBjYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLnNjcm9sbFJBRik7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbFJBRiA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZWN0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5sYXN0VHMgPSAwO1xuICAgICAgICB0aGlzLmluaXRpYWxTY3JvbGxUb3AgPSAwO1xuICAgIH1cbiAgICBjYWxjdWxhdGVWZWxvY2l0eSgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnJlY3QpXG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgY29uc3QgZGlzdFRvcCA9IHRoaXMubW91c2VZIC0gdGhpcy5yZWN0LnRvcDtcbiAgICAgICAgY29uc3QgZGlzdEJvdCA9IHRoaXMucmVjdC5ib3R0b20gLSB0aGlzLm1vdXNlWTtcbiAgICAgICAgaWYgKGRpc3RUb3AgPCB0aGlzLklOTkVSX1pPTkUpXG4gICAgICAgICAgICByZXR1cm4gLXRoaXMuRkFTVF9TUEVFRDtcbiAgICAgICAgaWYgKGRpc3RUb3AgPCB0aGlzLk9VVEVSX1pPTkUpXG4gICAgICAgICAgICByZXR1cm4gLXRoaXMuU0xPV19TUEVFRDtcbiAgICAgICAgaWYgKGRpc3RCb3QgPCB0aGlzLklOTkVSX1pPTkUpXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5GQVNUX1NQRUVEO1xuICAgICAgICBpZiAoZGlzdEJvdCA8IHRoaXMuT1VURVJfWk9ORSlcbiAgICAgICAgICAgIHJldHVybiB0aGlzLlNMT1dfU1BFRUQ7XG4gICAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgICBpc0F0Qm91bmRhcnkodmVsb2NpdHkpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNjcm9sbGFibGVDb250ZW50IHx8ICF0aGlzLnRpbWVHcmlkIHx8ICF0aGlzLmRyYWdnZWRFbGVtZW50KVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBjb25zdCBhdFRvcCA9IHRoaXMuc2Nyb2xsYWJsZUNvbnRlbnQuc2Nyb2xsVG9wIDw9IDAgJiYgdmVsb2NpdHkgPCAwO1xuICAgICAgICBjb25zdCBhdEJvdHRvbSA9IHZlbG9jaXR5ID4gMCAmJlxuICAgICAgICAgICAgdGhpcy5kcmFnZ2VkRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5ib3R0b20gPj1cbiAgICAgICAgICAgICAgICB0aGlzLnRpbWVHcmlkLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmJvdHRvbTtcbiAgICAgICAgcmV0dXJuIGF0VG9wIHx8IGF0Qm90dG9tO1xuICAgIH1cbiAgICBzZXRTY3JvbGxpbmdTdGF0ZShzY3JvbGxpbmcpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNTY3JvbGxpbmcgPT09IHNjcm9sbGluZylcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgdGhpcy5pc1Njcm9sbGluZyA9IHNjcm9sbGluZztcbiAgICAgICAgaWYgKHNjcm9sbGluZykge1xuICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENvcmVFdmVudHMuRURHRV9TQ1JPTExfU1RBUlRFRCwge30pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5pbml0aWFsU2Nyb2xsVG9wID0gdGhpcy5zY3JvbGxhYmxlQ29udGVudD8uc2Nyb2xsVG9wID8/IDA7XG4gICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ29yZUV2ZW50cy5FREdFX1NDUk9MTF9TVE9QUEVELCB7fSk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCAiaW1wb3J0IHsgcGl4ZWxzVG9NaW51dGVzLCBtaW51dGVzVG9QaXhlbHMsIHNuYXBUb0dyaWQgfSBmcm9tICcuLi91dGlscy9Qb3NpdGlvblV0aWxzJztcbmltcG9ydCB7IENvcmVFdmVudHMgfSBmcm9tICcuLi9jb25zdGFudHMvQ29yZUV2ZW50cyc7XG5pbXBvcnQgeyBTd3BFdmVudCB9IGZyb20gJy4uL3R5cGVzL1N3cEV2ZW50JztcbmV4cG9ydCBjbGFzcyBSZXNpemVNYW5hZ2VyIHtcbiAgICBjb25zdHJ1Y3RvcihldmVudEJ1cywgZ3JpZENvbmZpZywgZGF0ZVNlcnZpY2UpIHtcbiAgICAgICAgdGhpcy5ldmVudEJ1cyA9IGV2ZW50QnVzO1xuICAgICAgICB0aGlzLmdyaWRDb25maWcgPSBncmlkQ29uZmlnO1xuICAgICAgICB0aGlzLmRhdGVTZXJ2aWNlID0gZGF0ZVNlcnZpY2U7XG4gICAgICAgIHRoaXMuY29udGFpbmVyID0gbnVsbDtcbiAgICAgICAgdGhpcy5yZXNpemVTdGF0ZSA9IG51bGw7XG4gICAgICAgIHRoaXMuWl9JTkRFWF9SRVNJWklORyA9ICcxMDAwJztcbiAgICAgICAgdGhpcy5BTklNQVRJT05fU1BFRUQgPSAwLjM1O1xuICAgICAgICB0aGlzLk1JTl9IRUlHSFRfTUlOVVRFUyA9IDE1O1xuICAgICAgICAvKipcbiAgICAgICAgICogSGFuZGxlIG1vdXNlb3ZlciAtIGNyZWF0ZSByZXNpemUgaGFuZGxlIGlmIG5vdCBleGlzdHNcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuaGFuZGxlTW91c2VPdmVyID0gKGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldCA9IGUudGFyZ2V0O1xuICAgICAgICAgICAgY29uc3QgZXZlbnRFbGVtZW50ID0gdGFyZ2V0LmNsb3Nlc3QoJ3N3cC1ldmVudCcpO1xuICAgICAgICAgICAgaWYgKCFldmVudEVsZW1lbnQgfHwgdGhpcy5yZXNpemVTdGF0ZSlcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAvLyBDaGVjayBpZiBoYW5kbGUgYWxyZWFkeSBleGlzdHNcbiAgICAgICAgICAgIGlmICghZXZlbnRFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJzpzY29wZSA+IHN3cC1yZXNpemUtaGFuZGxlJykpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBoYW5kbGUgPSB0aGlzLmNyZWF0ZVJlc2l6ZUhhbmRsZSgpO1xuICAgICAgICAgICAgICAgIGV2ZW50RWxlbWVudC5hcHBlbmRDaGlsZChoYW5kbGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogSGFuZGxlIHBvaW50ZXJkb3duIC0gc3RhcnQgcmVzaXplIGlmIG9uIGhhbmRsZVxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5oYW5kbGVQb2ludGVyRG93biA9IChlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBoYW5kbGUgPSBlLnRhcmdldC5jbG9zZXN0KCdzd3AtcmVzaXplLWhhbmRsZScpO1xuICAgICAgICAgICAgaWYgKCFoYW5kbGUpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IGhhbmRsZS5wYXJlbnRFbGVtZW50O1xuICAgICAgICAgICAgaWYgKCFlbGVtZW50KVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50SWQgPSBlbGVtZW50LmRhdGFzZXQuZXZlbnRJZCB8fCAnJztcbiAgICAgICAgICAgIGNvbnN0IHN0YXJ0SGVpZ2h0ID0gZWxlbWVudC5vZmZzZXRIZWlnaHQ7XG4gICAgICAgICAgICBjb25zdCBzdGFydER1cmF0aW9uTWludXRlcyA9IHBpeGVsc1RvTWludXRlcyhzdGFydEhlaWdodCwgdGhpcy5ncmlkQ29uZmlnKTtcbiAgICAgICAgICAgIC8vIFN0b3JlIHByZXZpb3VzIHotaW5kZXhcbiAgICAgICAgICAgIGNvbnN0IGNvbnRhaW5lciA9IGVsZW1lbnQuY2xvc2VzdCgnc3dwLWV2ZW50LWdyb3VwJykgPz8gZWxlbWVudDtcbiAgICAgICAgICAgIGNvbnN0IHByZXZaSW5kZXggPSBjb250YWluZXIuc3R5bGUuekluZGV4O1xuICAgICAgICAgICAgLy8gU2V0IHJlc2l6ZSBzdGF0ZVxuICAgICAgICAgICAgdGhpcy5yZXNpemVTdGF0ZSA9IHtcbiAgICAgICAgICAgICAgICBldmVudElkLFxuICAgICAgICAgICAgICAgIGVsZW1lbnQsXG4gICAgICAgICAgICAgICAgaGFuZGxlRWxlbWVudDogaGFuZGxlLFxuICAgICAgICAgICAgICAgIHN0YXJ0WTogZS5jbGllbnRZLFxuICAgICAgICAgICAgICAgIHN0YXJ0SGVpZ2h0LFxuICAgICAgICAgICAgICAgIHN0YXJ0RHVyYXRpb25NaW51dGVzLFxuICAgICAgICAgICAgICAgIHBvaW50ZXJJZDogZS5wb2ludGVySWQsXG4gICAgICAgICAgICAgICAgcHJldlpJbmRleCxcbiAgICAgICAgICAgICAgICAvLyBBbmltYXRpb24gc3RhdGVcbiAgICAgICAgICAgICAgICBjdXJyZW50SGVpZ2h0OiBzdGFydEhlaWdodCxcbiAgICAgICAgICAgICAgICB0YXJnZXRIZWlnaHQ6IHN0YXJ0SGVpZ2h0LFxuICAgICAgICAgICAgICAgIGFuaW1hdGlvbklkOiBudWxsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgLy8gRWxldmF0ZSB6LWluZGV4XG4gICAgICAgICAgICBjb250YWluZXIuc3R5bGUuekluZGV4ID0gdGhpcy5aX0lOREVYX1JFU0laSU5HO1xuICAgICAgICAgICAgLy8gQ2FwdHVyZSBwb2ludGVyIGZvciBzbW9vdGggdHJhY2tpbmdcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaGFuZGxlLnNldFBvaW50ZXJDYXB0dXJlKGUucG9pbnRlcklkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1BvaW50ZXIgY2FwdHVyZSBmYWlsZWQ6JywgZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEFkZCBnbG9iYWwgcmVzaXppbmcgY2xhc3NcbiAgICAgICAgICAgIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGFzc0xpc3QuYWRkKCdzd3AtLXJlc2l6aW5nJyk7XG4gICAgICAgICAgICAvLyBFbWl0IHJlc2l6ZSBzdGFydCBldmVudFxuICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENvcmVFdmVudHMuRVZFTlRfUkVTSVpFX1NUQVJULCB7XG4gICAgICAgICAgICAgICAgZXZlbnRJZCxcbiAgICAgICAgICAgICAgICBlbGVtZW50LFxuICAgICAgICAgICAgICAgIHN0YXJ0SGVpZ2h0XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEhhbmRsZSBwb2ludGVybW92ZSAtIHVwZGF0ZSB0YXJnZXQgaGVpZ2h0IGR1cmluZyByZXNpemVcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuaGFuZGxlUG9pbnRlck1vdmUgPSAoZSkgPT4ge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnJlc2l6ZVN0YXRlKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIGNvbnN0IGRlbHRhWSA9IGUuY2xpZW50WSAtIHRoaXMucmVzaXplU3RhdGUuc3RhcnRZO1xuICAgICAgICAgICAgY29uc3QgbWluSGVpZ2h0ID0gKHRoaXMuTUlOX0hFSUdIVF9NSU5VVEVTIC8gNjApICogdGhpcy5ncmlkQ29uZmlnLmhvdXJIZWlnaHQ7XG4gICAgICAgICAgICBjb25zdCBuZXdIZWlnaHQgPSBNYXRoLm1heChtaW5IZWlnaHQsIHRoaXMucmVzaXplU3RhdGUuc3RhcnRIZWlnaHQgKyBkZWx0YVkpO1xuICAgICAgICAgICAgLy8gU2V0IHRhcmdldCBoZWlnaHQgZm9yIGFuaW1hdGlvblxuICAgICAgICAgICAgdGhpcy5yZXNpemVTdGF0ZS50YXJnZXRIZWlnaHQgPSBuZXdIZWlnaHQ7XG4gICAgICAgICAgICAvLyBTdGFydCBhbmltYXRpb24gaWYgbm90IHJ1bm5pbmdcbiAgICAgICAgICAgIGlmICh0aGlzLnJlc2l6ZVN0YXRlLmFuaW1hdGlvbklkID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hbmltYXRlSGVpZ2h0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSQUYgYW5pbWF0aW9uIGxvb3AgZm9yIHNtb290aCBoZWlnaHQgaW50ZXJwb2xhdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5hbmltYXRlSGVpZ2h0ID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnJlc2l6ZVN0YXRlKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIGNvbnN0IGRpZmYgPSB0aGlzLnJlc2l6ZVN0YXRlLnRhcmdldEhlaWdodCAtIHRoaXMucmVzaXplU3RhdGUuY3VycmVudEhlaWdodDtcbiAgICAgICAgICAgIC8vIFN0b3AgYW5pbWF0aW9uIHdoZW4gY2xvc2UgZW5vdWdoXG4gICAgICAgICAgICBpZiAoTWF0aC5hYnMoZGlmZikgPCAwLjUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2l6ZVN0YXRlLmFuaW1hdGlvbklkID0gbnVsbDtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBJbnRlcnBvbGF0ZSB0b3dhcmRzIHRhcmdldCAoMzUlIHBlciBmcmFtZSBsaWtlIFYxKVxuICAgICAgICAgICAgdGhpcy5yZXNpemVTdGF0ZS5jdXJyZW50SGVpZ2h0ICs9IGRpZmYgKiB0aGlzLkFOSU1BVElPTl9TUEVFRDtcbiAgICAgICAgICAgIHRoaXMucmVzaXplU3RhdGUuZWxlbWVudC5zdHlsZS5oZWlnaHQgPSBgJHt0aGlzLnJlc2l6ZVN0YXRlLmN1cnJlbnRIZWlnaHR9cHhgO1xuICAgICAgICAgICAgLy8gVXBkYXRlIHRpbWVzdGFtcCBkaXNwbGF5IChzbmFwcGVkKVxuICAgICAgICAgICAgdGhpcy51cGRhdGVUaW1lc3RhbXBEaXNwbGF5KCk7XG4gICAgICAgICAgICAvLyBDb250aW51ZSBhbmltYXRpb25cbiAgICAgICAgICAgIHRoaXMucmVzaXplU3RhdGUuYW5pbWF0aW9uSWQgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy5hbmltYXRlSGVpZ2h0KTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEhhbmRsZSBwb2ludGVydXAgLSBmaW5pc2ggcmVzaXplXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmhhbmRsZVBvaW50ZXJVcCA9IChlKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXRoaXMucmVzaXplU3RhdGUpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgLy8gQ2FuY2VsIGFueSBwZW5kaW5nIGFuaW1hdGlvblxuICAgICAgICAgICAgaWYgKHRoaXMucmVzaXplU3RhdGUuYW5pbWF0aW9uSWQgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBjYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLnJlc2l6ZVN0YXRlLmFuaW1hdGlvbklkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFJlbGVhc2UgcG9pbnRlciBjYXB0dXJlXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplU3RhdGUuaGFuZGxlRWxlbWVudC5yZWxlYXNlUG9pbnRlckNhcHR1cmUoZS5wb2ludGVySWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignUG9pbnRlciByZWxlYXNlIGZhaWxlZDonLCBlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gU25hcCBmaW5hbCBoZWlnaHQgdG8gZ3JpZFxuICAgICAgICAgICAgdGhpcy5zbmFwVG9HcmlkRmluYWwoKTtcbiAgICAgICAgICAgIC8vIFVwZGF0ZSB0aW1lc3RhbXAgb25lIGZpbmFsIHRpbWVcbiAgICAgICAgICAgIHRoaXMudXBkYXRlVGltZXN0YW1wRGlzcGxheSgpO1xuICAgICAgICAgICAgLy8gUmVzdG9yZSB6LWluZGV4XG4gICAgICAgICAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLnJlc2l6ZVN0YXRlLmVsZW1lbnQuY2xvc2VzdCgnc3dwLWV2ZW50LWdyb3VwJykgPz8gdGhpcy5yZXNpemVTdGF0ZS5lbGVtZW50O1xuICAgICAgICAgICAgY29udGFpbmVyLnN0eWxlLnpJbmRleCA9IHRoaXMucmVzaXplU3RhdGUucHJldlpJbmRleDtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBnbG9iYWwgcmVzaXppbmcgY2xhc3NcbiAgICAgICAgICAgIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCdzd3AtLXJlc2l6aW5nJyk7XG4gICAgICAgICAgICAvLyBHZXQgY29sdW1uS2V5IGFuZCBkYXRlIGZyb20gcGFyZW50IGNvbHVtblxuICAgICAgICAgICAgY29uc3QgY29sdW1uID0gdGhpcy5yZXNpemVTdGF0ZS5lbGVtZW50LmNsb3Nlc3QoJ3N3cC1kYXktY29sdW1uJyk7XG4gICAgICAgICAgICBjb25zdCBjb2x1bW5LZXkgPSBjb2x1bW4/LmRhdGFzZXQuY29sdW1uS2V5IHx8ICcnO1xuICAgICAgICAgICAgY29uc3QgZGF0ZSA9IGNvbHVtbj8uZGF0YXNldC5kYXRlIHx8ICcnO1xuICAgICAgICAgICAgLy8gQ3JlYXRlIFN3cEV2ZW50IGZyb20gZWxlbWVudCAocmVhZHMgdG9wL2hlaWdodC9ldmVudElkIGZyb20gZWxlbWVudClcbiAgICAgICAgICAgIGNvbnN0IHN3cEV2ZW50ID0gU3dwRXZlbnQuZnJvbUVsZW1lbnQodGhpcy5yZXNpemVTdGF0ZS5lbGVtZW50LCBjb2x1bW5LZXksIGRhdGUsIHRoaXMuZ3JpZENvbmZpZyk7XG4gICAgICAgICAgICAvLyBFbWl0IHJlc2l6ZSBlbmQgZXZlbnRcbiAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMuZW1pdChDb3JlRXZlbnRzLkVWRU5UX1JFU0laRV9FTkQsIHtcbiAgICAgICAgICAgICAgICBzd3BFdmVudFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAvLyBSZXNldCBzdGF0ZVxuICAgICAgICAgICAgdGhpcy5yZXNpemVTdGF0ZSA9IG51bGw7XG4gICAgICAgIH07XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemUgcmVzaXplIGZ1bmN0aW9uYWxpdHkgb24gY29udGFpbmVyXG4gICAgICovXG4gICAgaW5pdChjb250YWluZXIpIHtcbiAgICAgICAgdGhpcy5jb250YWluZXIgPSBjb250YWluZXI7XG4gICAgICAgIC8vIE1vdXNlb3ZlciBsaXN0ZW5lciBmb3IgaGFuZGxlIGNyZWF0aW9uIChjYXB0dXJlIHBoYXNlIGxpa2UgVjEpXG4gICAgICAgIGNvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW92ZXInLCB0aGlzLmhhbmRsZU1vdXNlT3ZlciwgdHJ1ZSk7XG4gICAgICAgIC8vIFBvaW50ZXIgbGlzdGVuZXJzIGZvciByZXNpemUgKGNhcHR1cmUgcGhhc2UgbGlrZSBWMSlcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncG9pbnRlcmRvd24nLCB0aGlzLmhhbmRsZVBvaW50ZXJEb3duLCB0cnVlKTtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncG9pbnRlcm1vdmUnLCB0aGlzLmhhbmRsZVBvaW50ZXJNb3ZlLCB0cnVlKTtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncG9pbnRlcnVwJywgdGhpcy5oYW5kbGVQb2ludGVyVXAsIHRydWUpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgcmVzaXplIGhhbmRsZSBlbGVtZW50XG4gICAgICovXG4gICAgY3JlYXRlUmVzaXplSGFuZGxlKCkge1xuICAgICAgICBjb25zdCBoYW5kbGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzd3AtcmVzaXplLWhhbmRsZScpO1xuICAgICAgICBoYW5kbGUuc2V0QXR0cmlidXRlKCdhcmlhLWxhYmVsJywgJ1Jlc2l6ZSBldmVudCcpO1xuICAgICAgICBoYW5kbGUuc2V0QXR0cmlidXRlKCdyb2xlJywgJ3NlcGFyYXRvcicpO1xuICAgICAgICByZXR1cm4gaGFuZGxlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGltZXN0YW1wIGRpc3BsYXkgd2l0aCBzbmFwcGVkIGVuZCB0aW1lXG4gICAgICovXG4gICAgdXBkYXRlVGltZXN0YW1wRGlzcGxheSgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnJlc2l6ZVN0YXRlKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBjb25zdCB0aW1lRWwgPSB0aGlzLnJlc2l6ZVN0YXRlLmVsZW1lbnQucXVlcnlTZWxlY3Rvcignc3dwLWV2ZW50LXRpbWUnKTtcbiAgICAgICAgaWYgKCF0aW1lRWwpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIC8vIEdldCBzdGFydCB0aW1lIGZyb20gZWxlbWVudCBwb3NpdGlvblxuICAgICAgICBjb25zdCB0b3AgPSBwYXJzZUZsb2F0KHRoaXMucmVzaXplU3RhdGUuZWxlbWVudC5zdHlsZS50b3ApIHx8IDA7XG4gICAgICAgIGNvbnN0IHN0YXJ0TWludXRlc0Zyb21HcmlkID0gcGl4ZWxzVG9NaW51dGVzKHRvcCwgdGhpcy5ncmlkQ29uZmlnKTtcbiAgICAgICAgY29uc3Qgc3RhcnRNaW51dGVzID0gKHRoaXMuZ3JpZENvbmZpZy5kYXlTdGFydEhvdXIgKiA2MCkgKyBzdGFydE1pbnV0ZXNGcm9tR3JpZDtcbiAgICAgICAgLy8gQ2FsY3VsYXRlIHNuYXBwZWQgZW5kIHRpbWUgZnJvbSBjdXJyZW50IGhlaWdodFxuICAgICAgICBjb25zdCBzbmFwcGVkSGVpZ2h0ID0gc25hcFRvR3JpZCh0aGlzLnJlc2l6ZVN0YXRlLmN1cnJlbnRIZWlnaHQsIHRoaXMuZ3JpZENvbmZpZyk7XG4gICAgICAgIGNvbnN0IGR1cmF0aW9uTWludXRlcyA9IHBpeGVsc1RvTWludXRlcyhzbmFwcGVkSGVpZ2h0LCB0aGlzLmdyaWRDb25maWcpO1xuICAgICAgICBjb25zdCBlbmRNaW51dGVzID0gc3RhcnRNaW51dGVzICsgZHVyYXRpb25NaW51dGVzO1xuICAgICAgICAvLyBGb3JtYXQgYW5kIHVwZGF0ZVxuICAgICAgICBjb25zdCBzdGFydCA9IHRoaXMubWludXRlc1RvRGF0ZShzdGFydE1pbnV0ZXMpO1xuICAgICAgICBjb25zdCBlbmQgPSB0aGlzLm1pbnV0ZXNUb0RhdGUoZW5kTWludXRlcyk7XG4gICAgICAgIHRpbWVFbC50ZXh0Q29udGVudCA9IHRoaXMuZGF0ZVNlcnZpY2UuZm9ybWF0VGltZVJhbmdlKHN0YXJ0LCBlbmQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0IG1pbnV0ZXMgc2luY2UgbWlkbmlnaHQgdG8gRGF0ZVxuICAgICAqL1xuICAgIG1pbnV0ZXNUb0RhdGUobWludXRlcykge1xuICAgICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoKTtcbiAgICAgICAgZGF0ZS5zZXRIb3VycyhNYXRoLmZsb29yKG1pbnV0ZXMgLyA2MCkgJSAyNCwgbWludXRlcyAlIDYwLCAwLCAwKTtcbiAgICAgICAgcmV0dXJuIGRhdGU7XG4gICAgfVxuICAgIDtcbiAgICAvKipcbiAgICAgKiBTbmFwIGZpbmFsIGhlaWdodCB0byBncmlkIGludGVydmFsXG4gICAgICovXG4gICAgc25hcFRvR3JpZEZpbmFsKCkge1xuICAgICAgICBpZiAoIXRoaXMucmVzaXplU3RhdGUpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNvbnN0IGN1cnJlbnRIZWlnaHQgPSB0aGlzLnJlc2l6ZVN0YXRlLmVsZW1lbnQub2Zmc2V0SGVpZ2h0O1xuICAgICAgICBjb25zdCBzbmFwcGVkSGVpZ2h0ID0gc25hcFRvR3JpZChjdXJyZW50SGVpZ2h0LCB0aGlzLmdyaWRDb25maWcpO1xuICAgICAgICBjb25zdCBtaW5IZWlnaHQgPSBtaW51dGVzVG9QaXhlbHModGhpcy5NSU5fSEVJR0hUX01JTlVURVMsIHRoaXMuZ3JpZENvbmZpZyk7XG4gICAgICAgIGNvbnN0IGZpbmFsSGVpZ2h0ID0gTWF0aC5tYXgobWluSGVpZ2h0LCBzbmFwcGVkSGVpZ2h0KTtcbiAgICAgICAgdGhpcy5yZXNpemVTdGF0ZS5lbGVtZW50LnN0eWxlLmhlaWdodCA9IGAke2ZpbmFsSGVpZ2h0fXB4YDtcbiAgICAgICAgdGhpcy5yZXNpemVTdGF0ZS5jdXJyZW50SGVpZ2h0ID0gZmluYWxIZWlnaHQ7XG4gICAgfVxufVxuIiwgImltcG9ydCB7IENvcmVFdmVudHMgfSBmcm9tICcuLi9jb25zdGFudHMvQ29yZUV2ZW50cyc7XG5leHBvcnQgY2xhc3MgRXZlbnRQZXJzaXN0ZW5jZU1hbmFnZXIge1xuICAgIGNvbnN0cnVjdG9yKGV2ZW50U2VydmljZSwgZXZlbnRCdXMsIGRhdGVTZXJ2aWNlKSB7XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlID0gZXZlbnRTZXJ2aWNlO1xuICAgICAgICB0aGlzLmV2ZW50QnVzID0gZXZlbnRCdXM7XG4gICAgICAgIHRoaXMuZGF0ZVNlcnZpY2UgPSBkYXRlU2VydmljZTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEhhbmRsZSBkcmFnIGVuZCAtIHVwZGF0ZSBldmVudCBwb3NpdGlvbiBpbiBJbmRleGVkREJcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuaGFuZGxlRHJhZ0VuZCA9IGFzeW5jIChlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwYXlsb2FkID0gZS5kZXRhaWw7XG4gICAgICAgICAgICBjb25zdCB7IHN3cEV2ZW50IH0gPSBwYXlsb2FkO1xuICAgICAgICAgICAgLy8gR2V0IGV4aXN0aW5nIGV2ZW50IHRvIG1lcmdlIHdpdGhcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50ID0gYXdhaXQgdGhpcy5ldmVudFNlcnZpY2UuZ2V0KHN3cEV2ZW50LmV2ZW50SWQpO1xuICAgICAgICAgICAgaWYgKCFldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgRXZlbnRQZXJzaXN0ZW5jZU1hbmFnZXI6IEV2ZW50ICR7c3dwRXZlbnQuZXZlbnRJZH0gbm90IGZvdW5kYCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gUGFyc2UgcmVzb3VyY2VJZCBmcm9tIGNvbHVtbktleSBpZiBwcmVzZW50XG4gICAgICAgICAgICBjb25zdCB7IHJlc291cmNlIH0gPSB0aGlzLmRhdGVTZXJ2aWNlLnBhcnNlQ29sdW1uS2V5KHN3cEV2ZW50LmNvbHVtbktleSk7XG4gICAgICAgICAgICAvLyBVcGRhdGUgYW5kIHNhdmUgLSBzdGFydC9lbmQgYWxyZWFkeSBjYWxjdWxhdGVkIGluIFN3cEV2ZW50XG4gICAgICAgICAgICAvLyBTZXQgYWxsRGF5IGJhc2VkIG9uIGRyb3AgdGFyZ2V0OlxuICAgICAgICAgICAgLy8gLSBoZWFkZXI6IGFsbERheSA9IHRydWVcbiAgICAgICAgICAgIC8vIC0gZ3JpZDogYWxsRGF5ID0gZmFsc2UgKGNvbnZlcnRzIGFsbERheSBldmVudCB0byB0aW1lZClcbiAgICAgICAgICAgIGNvbnN0IHVwZGF0ZWRFdmVudCA9IHtcbiAgICAgICAgICAgICAgICAuLi5ldmVudCxcbiAgICAgICAgICAgICAgICBzdGFydDogc3dwRXZlbnQuc3RhcnQsXG4gICAgICAgICAgICAgICAgZW5kOiBzd3BFdmVudC5lbmQsXG4gICAgICAgICAgICAgICAgcmVzb3VyY2VJZDogcmVzb3VyY2UgPz8gZXZlbnQucmVzb3VyY2VJZCxcbiAgICAgICAgICAgICAgICBhbGxEYXk6IHBheWxvYWQudGFyZ2V0ID09PSAnaGVhZGVyJyxcbiAgICAgICAgICAgICAgICBzeW5jU3RhdHVzOiAncGVuZGluZydcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmV2ZW50U2VydmljZS5zYXZlKHVwZGF0ZWRFdmVudCk7XG4gICAgICAgICAgICAvLyBFbWl0IEVWRU5UX1VQREFURUQgZm9yIEV2ZW50UmVuZGVyZXIgdG8gcmUtcmVuZGVyIGFmZmVjdGVkIGNvbHVtbnNcbiAgICAgICAgICAgIGNvbnN0IHVwZGF0ZVBheWxvYWQgPSB7XG4gICAgICAgICAgICAgICAgZXZlbnRJZDogdXBkYXRlZEV2ZW50LmlkLFxuICAgICAgICAgICAgICAgIHNvdXJjZUNvbHVtbktleTogcGF5bG9hZC5zb3VyY2VDb2x1bW5LZXksXG4gICAgICAgICAgICAgICAgdGFyZ2V0Q29sdW1uS2V5OiBzd3BFdmVudC5jb2x1bW5LZXlcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ29yZUV2ZW50cy5FVkVOVF9VUERBVEVELCB1cGRhdGVQYXlsb2FkKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEhhbmRsZSByZXNpemUgZW5kIC0gdXBkYXRlIGV2ZW50IGR1cmF0aW9uIGluIEluZGV4ZWREQlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5oYW5kbGVSZXNpemVFbmQgPSBhc3luYyAoZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IGUuZGV0YWlsO1xuICAgICAgICAgICAgY29uc3QgeyBzd3BFdmVudCB9ID0gcGF5bG9hZDtcbiAgICAgICAgICAgIC8vIEdldCBleGlzdGluZyBldmVudCB0byBtZXJnZSB3aXRoXG4gICAgICAgICAgICBjb25zdCBldmVudCA9IGF3YWl0IHRoaXMuZXZlbnRTZXJ2aWNlLmdldChzd3BFdmVudC5ldmVudElkKTtcbiAgICAgICAgICAgIGlmICghZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYEV2ZW50UGVyc2lzdGVuY2VNYW5hZ2VyOiBFdmVudCAke3N3cEV2ZW50LmV2ZW50SWR9IG5vdCBmb3VuZGApO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFVwZGF0ZSBhbmQgc2F2ZSAtIGVuZCBhbHJlYWR5IGNhbGN1bGF0ZWQgaW4gU3dwRXZlbnRcbiAgICAgICAgICAgIGNvbnN0IHVwZGF0ZWRFdmVudCA9IHtcbiAgICAgICAgICAgICAgICAuLi5ldmVudCxcbiAgICAgICAgICAgICAgICBlbmQ6IHN3cEV2ZW50LmVuZCxcbiAgICAgICAgICAgICAgICBzeW5jU3RhdHVzOiAncGVuZGluZydcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmV2ZW50U2VydmljZS5zYXZlKHVwZGF0ZWRFdmVudCk7XG4gICAgICAgICAgICAvLyBFbWl0IEVWRU5UX1VQREFURUQgZm9yIEV2ZW50UmVuZGVyZXIgdG8gcmUtcmVuZGVyIHRoZSBjb2x1bW5cbiAgICAgICAgICAgIC8vIFJlc2l6ZSBzdGF5cyBpbiBzYW1lIGNvbHVtbiwgc28gc291cmNlIGFuZCB0YXJnZXQgYXJlIHRoZSBzYW1lXG4gICAgICAgICAgICBjb25zdCB1cGRhdGVQYXlsb2FkID0ge1xuICAgICAgICAgICAgICAgIGV2ZW50SWQ6IHVwZGF0ZWRFdmVudC5pZCxcbiAgICAgICAgICAgICAgICBzb3VyY2VDb2x1bW5LZXk6IHN3cEV2ZW50LmNvbHVtbktleSxcbiAgICAgICAgICAgICAgICB0YXJnZXRDb2x1bW5LZXk6IHN3cEV2ZW50LmNvbHVtbktleVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMuZW1pdChDb3JlRXZlbnRzLkVWRU5UX1VQREFURUQsIHVwZGF0ZVBheWxvYWQpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLnNldHVwTGlzdGVuZXJzKCk7XG4gICAgfVxuICAgIHNldHVwTGlzdGVuZXJzKCkge1xuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENvcmVFdmVudHMuRVZFTlRfRFJBR19FTkQsIHRoaXMuaGFuZGxlRHJhZ0VuZCk7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMub24oQ29yZUV2ZW50cy5FVkVOVF9SRVNJWkVfRU5ELCB0aGlzLmhhbmRsZVJlc2l6ZUVuZCk7XG4gICAgfVxufVxuIiwgImltcG9ydCB7IENvbnRhaW5lciB9IGZyb20gJ0Bub3ZhZGkvY29yZSc7XG5pbXBvcnQgeyBEYXRlUmVuZGVyZXIgfSBmcm9tICcuL2ZlYXR1cmVzL2RhdGUvRGF0ZVJlbmRlcmVyJztcbmltcG9ydCB7IERhdGVTZXJ2aWNlIH0gZnJvbSAnLi9jb3JlL0RhdGVTZXJ2aWNlJztcbmltcG9ydCB7IFJlc291cmNlUmVuZGVyZXIgfSBmcm9tICcuL2ZlYXR1cmVzL3Jlc291cmNlL1Jlc291cmNlUmVuZGVyZXInO1xuaW1wb3J0IHsgVGVhbVJlbmRlcmVyIH0gZnJvbSAnLi9mZWF0dXJlcy90ZWFtL1RlYW1SZW5kZXJlcic7XG5pbXBvcnQgeyBEZXBhcnRtZW50UmVuZGVyZXIgfSBmcm9tICcuL2ZlYXR1cmVzL2RlcGFydG1lbnQvRGVwYXJ0bWVudFJlbmRlcmVyJztcbmltcG9ydCB7IENhbGVuZGFyT3JjaGVzdHJhdG9yIH0gZnJvbSAnLi9jb3JlL0NhbGVuZGFyT3JjaGVzdHJhdG9yJztcbmltcG9ydCB7IENhbGVuZGFyQXBwIH0gZnJvbSAnLi9jb3JlL0NhbGVuZGFyQXBwJztcbmltcG9ydCB7IFRpbWVBeGlzUmVuZGVyZXIgfSBmcm9tICcuL2ZlYXR1cmVzL3RpbWVheGlzL1RpbWVBeGlzUmVuZGVyZXInO1xuaW1wb3J0IHsgU2Nyb2xsTWFuYWdlciB9IGZyb20gJy4vY29yZS9TY3JvbGxNYW5hZ2VyJztcbmltcG9ydCB7IEhlYWRlckRyYXdlck1hbmFnZXIgfSBmcm9tICcuL2NvcmUvSGVhZGVyRHJhd2VyTWFuYWdlcic7XG5pbXBvcnQgeyBNb2NrVGVhbVN0b3JlLCBNb2NrUmVzb3VyY2VTdG9yZSB9IGZyb20gJy4vZGVtby9Nb2NrU3RvcmVzJztcbmltcG9ydCB7IERlbW9BcHAgfSBmcm9tICcuL2RlbW8vRGVtb0FwcCc7XG4vLyBFdmVudCBzeXN0ZW1cbmltcG9ydCB7IEV2ZW50QnVzIH0gZnJvbSAnLi9jb3JlL0V2ZW50QnVzJztcbi8vIFN0b3JhZ2VcbmltcG9ydCB7IEluZGV4ZWREQkNvbnRleHQgfSBmcm9tICcuL3N0b3JhZ2UvSW5kZXhlZERCQ29udGV4dCc7XG5pbXBvcnQgeyBFdmVudFN0b3JlIH0gZnJvbSAnLi9zdG9yYWdlL2V2ZW50cy9FdmVudFN0b3JlJztcbmltcG9ydCB7IEV2ZW50U2VydmljZSB9IGZyb20gJy4vc3RvcmFnZS9ldmVudHMvRXZlbnRTZXJ2aWNlJztcbmltcG9ydCB7IFJlc291cmNlU3RvcmUgfSBmcm9tICcuL3N0b3JhZ2UvcmVzb3VyY2VzL1Jlc291cmNlU3RvcmUnO1xuaW1wb3J0IHsgUmVzb3VyY2VTZXJ2aWNlIH0gZnJvbSAnLi9zdG9yYWdlL3Jlc291cmNlcy9SZXNvdXJjZVNlcnZpY2UnO1xuaW1wb3J0IHsgQm9va2luZ1N0b3JlIH0gZnJvbSAnLi9zdG9yYWdlL2Jvb2tpbmdzL0Jvb2tpbmdTdG9yZSc7XG5pbXBvcnQgeyBCb29raW5nU2VydmljZSB9IGZyb20gJy4vc3RvcmFnZS9ib29raW5ncy9Cb29raW5nU2VydmljZSc7XG5pbXBvcnQgeyBDdXN0b21lclN0b3JlIH0gZnJvbSAnLi9zdG9yYWdlL2N1c3RvbWVycy9DdXN0b21lclN0b3JlJztcbmltcG9ydCB7IEN1c3RvbWVyU2VydmljZSB9IGZyb20gJy4vc3RvcmFnZS9jdXN0b21lcnMvQ3VzdG9tZXJTZXJ2aWNlJztcbmltcG9ydCB7IFRlYW1TdG9yZSB9IGZyb20gJy4vc3RvcmFnZS90ZWFtcy9UZWFtU3RvcmUnO1xuaW1wb3J0IHsgVGVhbVNlcnZpY2UgfSBmcm9tICcuL3N0b3JhZ2UvdGVhbXMvVGVhbVNlcnZpY2UnO1xuaW1wb3J0IHsgRGVwYXJ0bWVudFN0b3JlIH0gZnJvbSAnLi9zdG9yYWdlL2RlcGFydG1lbnRzL0RlcGFydG1lbnRTdG9yZSc7XG5pbXBvcnQgeyBEZXBhcnRtZW50U2VydmljZSB9IGZyb20gJy4vc3RvcmFnZS9kZXBhcnRtZW50cy9EZXBhcnRtZW50U2VydmljZSc7XG5pbXBvcnQgeyBTZXR0aW5nc1N0b3JlIH0gZnJvbSAnLi9zdG9yYWdlL3NldHRpbmdzL1NldHRpbmdzU3RvcmUnO1xuaW1wb3J0IHsgU2V0dGluZ3NTZXJ2aWNlIH0gZnJvbSAnLi9zdG9yYWdlL3NldHRpbmdzL1NldHRpbmdzU2VydmljZSc7XG5pbXBvcnQgeyBWaWV3Q29uZmlnU3RvcmUgfSBmcm9tICcuL3N0b3JhZ2Uvdmlld2NvbmZpZ3MvVmlld0NvbmZpZ1N0b3JlJztcbmltcG9ydCB7IFZpZXdDb25maWdTZXJ2aWNlIH0gZnJvbSAnLi9zdG9yYWdlL3ZpZXdjb25maWdzL1ZpZXdDb25maWdTZXJ2aWNlJztcbi8vIEF1ZGl0XG5pbXBvcnQgeyBBdWRpdFN0b3JlIH0gZnJvbSAnLi9zdG9yYWdlL2F1ZGl0L0F1ZGl0U3RvcmUnO1xuaW1wb3J0IHsgQXVkaXRTZXJ2aWNlIH0gZnJvbSAnLi9zdG9yYWdlL2F1ZGl0L0F1ZGl0U2VydmljZSc7XG5pbXBvcnQgeyBNb2NrRXZlbnRSZXBvc2l0b3J5IH0gZnJvbSAnLi9yZXBvc2l0b3JpZXMvTW9ja0V2ZW50UmVwb3NpdG9yeSc7XG5pbXBvcnQgeyBNb2NrUmVzb3VyY2VSZXBvc2l0b3J5IH0gZnJvbSAnLi9yZXBvc2l0b3JpZXMvTW9ja1Jlc291cmNlUmVwb3NpdG9yeSc7XG5pbXBvcnQgeyBNb2NrQm9va2luZ1JlcG9zaXRvcnkgfSBmcm9tICcuL3JlcG9zaXRvcmllcy9Nb2NrQm9va2luZ1JlcG9zaXRvcnknO1xuaW1wb3J0IHsgTW9ja0N1c3RvbWVyUmVwb3NpdG9yeSB9IGZyb20gJy4vcmVwb3NpdG9yaWVzL01vY2tDdXN0b21lclJlcG9zaXRvcnknO1xuaW1wb3J0IHsgTW9ja0F1ZGl0UmVwb3NpdG9yeSB9IGZyb20gJy4vcmVwb3NpdG9yaWVzL01vY2tBdWRpdFJlcG9zaXRvcnknO1xuaW1wb3J0IHsgTW9ja1RlYW1SZXBvc2l0b3J5IH0gZnJvbSAnLi9yZXBvc2l0b3JpZXMvTW9ja1RlYW1SZXBvc2l0b3J5JztcbmltcG9ydCB7IE1vY2tEZXBhcnRtZW50UmVwb3NpdG9yeSB9IGZyb20gJy4vcmVwb3NpdG9yaWVzL01vY2tEZXBhcnRtZW50UmVwb3NpdG9yeSc7XG5pbXBvcnQgeyBNb2NrU2V0dGluZ3NSZXBvc2l0b3J5IH0gZnJvbSAnLi9yZXBvc2l0b3JpZXMvTW9ja1NldHRpbmdzUmVwb3NpdG9yeSc7XG5pbXBvcnQgeyBNb2NrVmlld0NvbmZpZ1JlcG9zaXRvcnkgfSBmcm9tICcuL3JlcG9zaXRvcmllcy9Nb2NrVmlld0NvbmZpZ1JlcG9zaXRvcnknO1xuLy8gV29ya2Vyc1xuaW1wb3J0IHsgRGF0YVNlZWRlciB9IGZyb20gJy4vd29ya2Vycy9EYXRhU2VlZGVyJztcbi8vIEZlYXR1cmVzXG5pbXBvcnQgeyBFdmVudFJlbmRlcmVyIH0gZnJvbSAnLi9mZWF0dXJlcy9ldmVudC9FdmVudFJlbmRlcmVyJztcbmltcG9ydCB7IFNjaGVkdWxlUmVuZGVyZXIgfSBmcm9tICcuL2ZlYXR1cmVzL3NjaGVkdWxlL1NjaGVkdWxlUmVuZGVyZXInO1xuaW1wb3J0IHsgSGVhZGVyRHJhd2VyUmVuZGVyZXIgfSBmcm9tICcuL2ZlYXR1cmVzL2hlYWRlcmRyYXdlci9IZWFkZXJEcmF3ZXJSZW5kZXJlcic7XG4vLyBTY2hlZHVsZVxuaW1wb3J0IHsgU2NoZWR1bGVPdmVycmlkZVN0b3JlIH0gZnJvbSAnLi9zdG9yYWdlL3NjaGVkdWxlcy9TY2hlZHVsZU92ZXJyaWRlU3RvcmUnO1xuaW1wb3J0IHsgU2NoZWR1bGVPdmVycmlkZVNlcnZpY2UgfSBmcm9tICcuL3N0b3JhZ2Uvc2NoZWR1bGVzL1NjaGVkdWxlT3ZlcnJpZGVTZXJ2aWNlJztcbmltcG9ydCB7IFJlc291cmNlU2NoZWR1bGVTZXJ2aWNlIH0gZnJvbSAnLi9zdG9yYWdlL3NjaGVkdWxlcy9SZXNvdXJjZVNjaGVkdWxlU2VydmljZSc7XG4vLyBNYW5hZ2Vyc1xuaW1wb3J0IHsgRHJhZ0Ryb3BNYW5hZ2VyIH0gZnJvbSAnLi9tYW5hZ2Vycy9EcmFnRHJvcE1hbmFnZXInO1xuaW1wb3J0IHsgRWRnZVNjcm9sbE1hbmFnZXIgfSBmcm9tICcuL21hbmFnZXJzL0VkZ2VTY3JvbGxNYW5hZ2VyJztcbmltcG9ydCB7IFJlc2l6ZU1hbmFnZXIgfSBmcm9tICcuL21hbmFnZXJzL1Jlc2l6ZU1hbmFnZXInO1xuaW1wb3J0IHsgRXZlbnRQZXJzaXN0ZW5jZU1hbmFnZXIgfSBmcm9tICcuL21hbmFnZXJzL0V2ZW50UGVyc2lzdGVuY2VNYW5hZ2VyJztcbmNvbnN0IGRlZmF1bHRUaW1lRm9ybWF0Q29uZmlnID0ge1xuICAgIHRpbWV6b25lOiBJbnRsLkRhdGVUaW1lRm9ybWF0KCkucmVzb2x2ZWRPcHRpb25zKCkudGltZVpvbmUsXG4gICAgdXNlMjRIb3VyRm9ybWF0OiB0cnVlLFxuICAgIGxvY2FsZTogJ2RhLURLJyxcbiAgICBkYXRlRm9ybWF0OiAnbG9jYWxlJyxcbiAgICBzaG93U2Vjb25kczogZmFsc2Vcbn07XG5jb25zdCBkZWZhdWx0R3JpZENvbmZpZyA9IHtcbiAgICBob3VySGVpZ2h0OiA2NCxcbiAgICBkYXlTdGFydEhvdXI6IDYsXG4gICAgZGF5RW5kSG91cjogMTgsXG4gICAgc25hcEludGVydmFsOiAxNSxcbiAgICBncmlkU3RhcnRUaHJlc2hvbGRNaW51dGVzOiAzMFxufTtcbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVWMkNvbnRhaW5lcigpIHtcbiAgICBjb25zdCBjb250YWluZXIgPSBuZXcgQ29udGFpbmVyKCk7XG4gICAgY29uc3QgYnVpbGRlciA9IGNvbnRhaW5lci5idWlsZGVyKCk7XG4gICAgLy8gQ29uZmlnXG4gICAgYnVpbGRlci5yZWdpc3Rlckluc3RhbmNlKGRlZmF1bHRUaW1lRm9ybWF0Q29uZmlnKS5hcyhcIklUaW1lRm9ybWF0Q29uZmlnXCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJJbnN0YW5jZShkZWZhdWx0R3JpZENvbmZpZykuYXMoXCJJR3JpZENvbmZpZ1wiKTtcbiAgICAvLyBDb3JlIC0gRXZlbnRCdXNcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShFdmVudEJ1cykuYXMoXCJFdmVudEJ1c1wiKTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShFdmVudEJ1cykuYXMoXCJJRXZlbnRCdXNcIik7XG4gICAgLy8gU2VydmljZXNcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShEYXRlU2VydmljZSkuYXMoXCJEYXRlU2VydmljZVwiKS5hdXRvV2lyZSh7XG4gICAgICAgIG1hcFJlc29sdmVyczogW1xuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSVRpbWVGb3JtYXRDb25maWdcIiksXG4gICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIC8vIFN0b3JhZ2UgaW5mcmFzdHJ1Y3R1cmVcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShJbmRleGVkREJDb250ZXh0KS5hcyhcIkluZGV4ZWREQkNvbnRleHRcIikuYXV0b1dpcmUoe1xuICAgICAgICBtYXBSZXNvbHZlcnM6IFtcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZUFsbChcIklTdG9yZVwiKVxuICAgICAgICBdXG4gICAgfSk7XG4gICAgLy8gU3RvcmVzIChmb3IgSW5kZXhlZERCIHNjaGVtYSBjcmVhdGlvbilcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShFdmVudFN0b3JlKS5hcyhcIklTdG9yZVwiKTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShSZXNvdXJjZVN0b3JlKS5hcyhcIklTdG9yZVwiKTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShCb29raW5nU3RvcmUpLmFzKFwiSVN0b3JlXCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKEN1c3RvbWVyU3RvcmUpLmFzKFwiSVN0b3JlXCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKFRlYW1TdG9yZSkuYXMoXCJJU3RvcmVcIik7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoRGVwYXJ0bWVudFN0b3JlKS5hcyhcIklTdG9yZVwiKTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShTY2hlZHVsZU92ZXJyaWRlU3RvcmUpLmFzKFwiSVN0b3JlXCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKEF1ZGl0U3RvcmUpLmFzKFwiSVN0b3JlXCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKFNldHRpbmdzU3RvcmUpLmFzKFwiSVN0b3JlXCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKFZpZXdDb25maWdTdG9yZSkuYXMoXCJJU3RvcmVcIik7XG4gICAgLy8gRW50aXR5IHNlcnZpY2VzIChmb3IgRGF0YVNlZWRlciBwb2x5bW9ycGhpYyBhcnJheSlcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShFdmVudFNlcnZpY2UpLmFzKFwiSUVudGl0eVNlcnZpY2VcIikuYXV0b1dpcmUoe1xuICAgICAgICBtYXBSZXNvbHZlcnM6IFtcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkluZGV4ZWREQkNvbnRleHRcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJRXZlbnRCdXNcIilcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKEV2ZW50U2VydmljZSkuYXMoXCJJRW50aXR5U2VydmljZVwiKS5hdXRvV2lyZSh7XG4gICAgICAgIG1hcFJlc29sdmVyczogW1xuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSW5kZXhlZERCQ29udGV4dFwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIklFdmVudEJ1c1wiKVxuICAgICAgICBdXG4gICAgfSk7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoRXZlbnRTZXJ2aWNlKS5hcyhcIkV2ZW50U2VydmljZVwiKS5hdXRvV2lyZSh7XG4gICAgICAgIG1hcFJlc29sdmVyczogW1xuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSW5kZXhlZERCQ29udGV4dFwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIklFdmVudEJ1c1wiKVxuICAgICAgICBdXG4gICAgfSk7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoUmVzb3VyY2VTZXJ2aWNlKS5hcyhcIklFbnRpdHlTZXJ2aWNlXCIpLmF1dG9XaXJlKHtcbiAgICAgICAgbWFwUmVzb2x2ZXJzOiBbXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJbmRleGVkREJDb250ZXh0XCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSUV2ZW50QnVzXCIpXG4gICAgICAgIF1cbiAgICB9KTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShSZXNvdXJjZVNlcnZpY2UpLmFzKFwiSUVudGl0eVNlcnZpY2VcIikuYXV0b1dpcmUoe1xuICAgICAgICBtYXBSZXNvbHZlcnM6IFtcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkluZGV4ZWREQkNvbnRleHRcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJRXZlbnRCdXNcIilcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKFJlc291cmNlU2VydmljZSkuYXMoXCJSZXNvdXJjZVNlcnZpY2VcIikuYXV0b1dpcmUoe1xuICAgICAgICBtYXBSZXNvbHZlcnM6IFtcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkluZGV4ZWREQkNvbnRleHRcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJRXZlbnRCdXNcIilcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKEJvb2tpbmdTZXJ2aWNlKS5hcyhcIklFbnRpdHlTZXJ2aWNlXCIpLmF1dG9XaXJlKHtcbiAgICAgICAgbWFwUmVzb2x2ZXJzOiBbXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJbmRleGVkREJDb250ZXh0XCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSUV2ZW50QnVzXCIpXG4gICAgICAgIF1cbiAgICB9KTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShCb29raW5nU2VydmljZSkuYXMoXCJJRW50aXR5U2VydmljZVwiKS5hdXRvV2lyZSh7XG4gICAgICAgIG1hcFJlc29sdmVyczogW1xuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSW5kZXhlZERCQ29udGV4dFwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIklFdmVudEJ1c1wiKVxuICAgICAgICBdXG4gICAgfSk7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoQm9va2luZ1NlcnZpY2UpLmFzKFwiQm9va2luZ1NlcnZpY2VcIikuYXV0b1dpcmUoe1xuICAgICAgICBtYXBSZXNvbHZlcnM6IFtcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkluZGV4ZWREQkNvbnRleHRcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJRXZlbnRCdXNcIilcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKEN1c3RvbWVyU2VydmljZSkuYXMoXCJJRW50aXR5U2VydmljZVwiKS5hdXRvV2lyZSh7XG4gICAgICAgIG1hcFJlc29sdmVyczogW1xuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSW5kZXhlZERCQ29udGV4dFwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIklFdmVudEJ1c1wiKVxuICAgICAgICBdXG4gICAgfSk7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoQ3VzdG9tZXJTZXJ2aWNlKS5hcyhcIklFbnRpdHlTZXJ2aWNlXCIpLmF1dG9XaXJlKHtcbiAgICAgICAgbWFwUmVzb2x2ZXJzOiBbXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJbmRleGVkREJDb250ZXh0XCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSUV2ZW50QnVzXCIpXG4gICAgICAgIF1cbiAgICB9KTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShDdXN0b21lclNlcnZpY2UpLmFzKFwiQ3VzdG9tZXJTZXJ2aWNlXCIpLmF1dG9XaXJlKHtcbiAgICAgICAgbWFwUmVzb2x2ZXJzOiBbXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJbmRleGVkREJDb250ZXh0XCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSUV2ZW50QnVzXCIpXG4gICAgICAgIF1cbiAgICB9KTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShUZWFtU2VydmljZSkuYXMoXCJJRW50aXR5U2VydmljZVwiKS5hdXRvV2lyZSh7XG4gICAgICAgIG1hcFJlc29sdmVyczogW1xuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSW5kZXhlZERCQ29udGV4dFwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIklFdmVudEJ1c1wiKVxuICAgICAgICBdXG4gICAgfSk7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoVGVhbVNlcnZpY2UpLmFzKFwiSUVudGl0eVNlcnZpY2VcIikuYXV0b1dpcmUoe1xuICAgICAgICBtYXBSZXNvbHZlcnM6IFtcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkluZGV4ZWREQkNvbnRleHRcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJRXZlbnRCdXNcIilcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKFRlYW1TZXJ2aWNlKS5hcyhcIlRlYW1TZXJ2aWNlXCIpLmF1dG9XaXJlKHtcbiAgICAgICAgbWFwUmVzb2x2ZXJzOiBbXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJbmRleGVkREJDb250ZXh0XCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSUV2ZW50QnVzXCIpXG4gICAgICAgIF1cbiAgICB9KTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShEZXBhcnRtZW50U2VydmljZSkuYXMoXCJJRW50aXR5U2VydmljZVwiKS5hdXRvV2lyZSh7XG4gICAgICAgIG1hcFJlc29sdmVyczogW1xuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSW5kZXhlZERCQ29udGV4dFwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIklFdmVudEJ1c1wiKVxuICAgICAgICBdXG4gICAgfSk7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoRGVwYXJ0bWVudFNlcnZpY2UpLmFzKFwiSUVudGl0eVNlcnZpY2VcIikuYXV0b1dpcmUoe1xuICAgICAgICBtYXBSZXNvbHZlcnM6IFtcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkluZGV4ZWREQkNvbnRleHRcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJRXZlbnRCdXNcIilcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKERlcGFydG1lbnRTZXJ2aWNlKS5hcyhcIkRlcGFydG1lbnRTZXJ2aWNlXCIpLmF1dG9XaXJlKHtcbiAgICAgICAgbWFwUmVzb2x2ZXJzOiBbXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJbmRleGVkREJDb250ZXh0XCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSUV2ZW50QnVzXCIpXG4gICAgICAgIF1cbiAgICB9KTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShTZXR0aW5nc1NlcnZpY2UpLmFzKFwiSUVudGl0eVNlcnZpY2VcIikuYXV0b1dpcmUoe1xuICAgICAgICBtYXBSZXNvbHZlcnM6IFtcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkluZGV4ZWREQkNvbnRleHRcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJRXZlbnRCdXNcIilcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKFNldHRpbmdzU2VydmljZSkuYXMoXCJJRW50aXR5U2VydmljZVwiKS5hdXRvV2lyZSh7XG4gICAgICAgIG1hcFJlc29sdmVyczogW1xuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSW5kZXhlZERCQ29udGV4dFwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIklFdmVudEJ1c1wiKVxuICAgICAgICBdXG4gICAgfSk7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoU2V0dGluZ3NTZXJ2aWNlKS5hcyhcIlNldHRpbmdzU2VydmljZVwiKS5hdXRvV2lyZSh7XG4gICAgICAgIG1hcFJlc29sdmVyczogW1xuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSW5kZXhlZERCQ29udGV4dFwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIklFdmVudEJ1c1wiKVxuICAgICAgICBdXG4gICAgfSk7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoVmlld0NvbmZpZ1NlcnZpY2UpLmFzKFwiSUVudGl0eVNlcnZpY2VcIikuYXV0b1dpcmUoe1xuICAgICAgICBtYXBSZXNvbHZlcnM6IFtcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkluZGV4ZWREQkNvbnRleHRcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJRXZlbnRCdXNcIilcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKFZpZXdDb25maWdTZXJ2aWNlKS5hcyhcIklFbnRpdHlTZXJ2aWNlXCIpLmF1dG9XaXJlKHtcbiAgICAgICAgbWFwUmVzb2x2ZXJzOiBbXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJbmRleGVkREJDb250ZXh0XCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSUV2ZW50QnVzXCIpXG4gICAgICAgIF1cbiAgICB9KTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShWaWV3Q29uZmlnU2VydmljZSkuYXMoXCJWaWV3Q29uZmlnU2VydmljZVwiKS5hdXRvV2lyZSh7XG4gICAgICAgIG1hcFJlc29sdmVyczogW1xuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSW5kZXhlZERCQ29udGV4dFwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIklFdmVudEJ1c1wiKVxuICAgICAgICBdXG4gICAgfSk7XG4gICAgLy8gUmVwb3NpdG9yaWVzIChmb3IgRGF0YVNlZWRlciBwb2x5bW9ycGhpYyBhcnJheSlcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShNb2NrRXZlbnRSZXBvc2l0b3J5KS5hcyhcIklBcGlSZXBvc2l0b3J5XCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKE1vY2tFdmVudFJlcG9zaXRvcnkpLmFzKFwiSUFwaVJlcG9zaXRvcnlcIik7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoTW9ja1Jlc291cmNlUmVwb3NpdG9yeSkuYXMoXCJJQXBpUmVwb3NpdG9yeVwiKTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShNb2NrUmVzb3VyY2VSZXBvc2l0b3J5KS5hcyhcIklBcGlSZXBvc2l0b3J5XCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKE1vY2tCb29raW5nUmVwb3NpdG9yeSkuYXMoXCJJQXBpUmVwb3NpdG9yeVwiKTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShNb2NrQm9va2luZ1JlcG9zaXRvcnkpLmFzKFwiSUFwaVJlcG9zaXRvcnlcIik7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoTW9ja0N1c3RvbWVyUmVwb3NpdG9yeSkuYXMoXCJJQXBpUmVwb3NpdG9yeVwiKTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShNb2NrQ3VzdG9tZXJSZXBvc2l0b3J5KS5hcyhcIklBcGlSZXBvc2l0b3J5XCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKE1vY2tBdWRpdFJlcG9zaXRvcnkpLmFzKFwiSUFwaVJlcG9zaXRvcnlcIik7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoTW9ja0F1ZGl0UmVwb3NpdG9yeSkuYXMoXCJJQXBpUmVwb3NpdG9yeVwiKTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShNb2NrVGVhbVJlcG9zaXRvcnkpLmFzKFwiSUFwaVJlcG9zaXRvcnlcIik7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoTW9ja1RlYW1SZXBvc2l0b3J5KS5hcyhcIklBcGlSZXBvc2l0b3J5XCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKE1vY2tEZXBhcnRtZW50UmVwb3NpdG9yeSkuYXMoXCJJQXBpUmVwb3NpdG9yeVwiKTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShNb2NrRGVwYXJ0bWVudFJlcG9zaXRvcnkpLmFzKFwiSUFwaVJlcG9zaXRvcnlcIik7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoTW9ja1NldHRpbmdzUmVwb3NpdG9yeSkuYXMoXCJJQXBpUmVwb3NpdG9yeVwiKTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShNb2NrU2V0dGluZ3NSZXBvc2l0b3J5KS5hcyhcIklBcGlSZXBvc2l0b3J5XCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKE1vY2tWaWV3Q29uZmlnUmVwb3NpdG9yeSkuYXMoXCJJQXBpUmVwb3NpdG9yeVwiKTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShNb2NrVmlld0NvbmZpZ1JlcG9zaXRvcnkpLmFzKFwiSUFwaVJlcG9zaXRvcnlcIik7XG4gICAgLy8gQXVkaXQgc2VydmljZSAobGlzdGVucyB0byBFTlRJVFlfU0FWRUQvREVMRVRFRCBldmVudHMgYXV0b21hdGljYWxseSlcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShBdWRpdFNlcnZpY2UpLmFzKFwiQXVkaXRTZXJ2aWNlXCIpLmF1dG9XaXJlKHtcbiAgICAgICAgbWFwUmVzb2x2ZXJzOiBbXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJbmRleGVkREJDb250ZXh0XCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSUV2ZW50QnVzXCIpXG4gICAgICAgIF1cbiAgICB9KTtcbiAgICAvLyBXb3JrZXJzXG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoRGF0YVNlZWRlcikuYXMoXCJEYXRhU2VlZGVyXCIpLmF1dG9XaXJlKHtcbiAgICAgICAgbWFwUmVzb2x2ZXJzOiBbXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGVBbGwoXCJJRW50aXR5U2VydmljZVwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZUFsbChcIklBcGlSZXBvc2l0b3J5XCIpXG4gICAgICAgIF1cbiAgICB9KTtcbiAgICAvLyBTY2hlZHVsZSBzZXJ2aWNlc1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKFNjaGVkdWxlT3ZlcnJpZGVTZXJ2aWNlKS5hcyhcIlNjaGVkdWxlT3ZlcnJpZGVTZXJ2aWNlXCIpLmF1dG9XaXJlKHtcbiAgICAgICAgbWFwUmVzb2x2ZXJzOiBbXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJbmRleGVkREJDb250ZXh0XCIpXG4gICAgICAgIF1cbiAgICB9KTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShSZXNvdXJjZVNjaGVkdWxlU2VydmljZSkuYXMoXCJSZXNvdXJjZVNjaGVkdWxlU2VydmljZVwiKS5hdXRvV2lyZSh7XG4gICAgICAgIG1hcFJlc29sdmVyczogW1xuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiUmVzb3VyY2VTZXJ2aWNlXCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiU2NoZWR1bGVPdmVycmlkZVNlcnZpY2VcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJEYXRlU2VydmljZVwiKVxuICAgICAgICBdXG4gICAgfSk7XG4gICAgLy8gRmVhdHVyZXNcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShFdmVudFJlbmRlcmVyKS5hcyhcIkV2ZW50UmVuZGVyZXJcIikuYXV0b1dpcmUoe1xuICAgICAgICBtYXBSZXNvbHZlcnM6IFtcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkV2ZW50U2VydmljZVwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkRhdGVTZXJ2aWNlXCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSUdyaWRDb25maWdcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJRXZlbnRCdXNcIilcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKFNjaGVkdWxlUmVuZGVyZXIpLmFzKFwiU2NoZWR1bGVSZW5kZXJlclwiKS5hdXRvV2lyZSh7XG4gICAgICAgIG1hcFJlc29sdmVyczogW1xuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiUmVzb3VyY2VTY2hlZHVsZVNlcnZpY2VcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJEYXRlU2VydmljZVwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIklHcmlkQ29uZmlnXCIpXG4gICAgICAgIF1cbiAgICB9KTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShIZWFkZXJEcmF3ZXJSZW5kZXJlcikuYXMoXCJIZWFkZXJEcmF3ZXJSZW5kZXJlclwiKS5hdXRvV2lyZSh7XG4gICAgICAgIG1hcFJlc29sdmVyczogW1xuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSUV2ZW50QnVzXCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSUdyaWRDb25maWdcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJIZWFkZXJEcmF3ZXJNYW5hZ2VyXCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiRXZlbnRTZXJ2aWNlXCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiRGF0ZVNlcnZpY2VcIilcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIC8vIFJlbmRlcmVycyAtIHJlZ2lzdHJlcmVzIHNvbSBSZW5kZXJlciAoYXJyYXkgaW5qZWN0aW9uIHRpbCBDYWxlbmRhck9yY2hlc3RyYXRvcilcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShEYXRlUmVuZGVyZXIpLmFzKFwiSVJlbmRlcmVyXCIpLmF1dG9XaXJlKHtcbiAgICAgICAgbWFwUmVzb2x2ZXJzOiBbXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJEYXRlU2VydmljZVwiKVxuICAgICAgICBdXG4gICAgfSk7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoUmVzb3VyY2VSZW5kZXJlcikuYXMoXCJJUmVuZGVyZXJcIikuYXV0b1dpcmUoe1xuICAgICAgICBtYXBSZXNvbHZlcnM6IFtcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIlJlc291cmNlU2VydmljZVwiKVxuICAgICAgICBdXG4gICAgfSk7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoVGVhbVJlbmRlcmVyKS5hcyhcIklSZW5kZXJlclwiKS5hdXRvV2lyZSh7XG4gICAgICAgIG1hcFJlc29sdmVyczogW1xuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiVGVhbVNlcnZpY2VcIilcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKERlcGFydG1lbnRSZW5kZXJlcikuYXMoXCJJUmVuZGVyZXJcIikuYXV0b1dpcmUoe1xuICAgICAgICBtYXBSZXNvbHZlcnM6IFtcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkRlcGFydG1lbnRTZXJ2aWNlXCIpXG4gICAgICAgIF1cbiAgICB9KTtcbiAgICAvLyBTdG9yZXMgLSByZWdpc3RyZXJlcyBzb20gSUdyb3VwaW5nU3RvcmVcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShNb2NrVGVhbVN0b3JlKS5hcyhcIklHcm91cGluZ1N0b3JlXCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKE1vY2tSZXNvdXJjZVN0b3JlKS5hcyhcIklHcm91cGluZ1N0b3JlXCIpO1xuICAgIC8vIENhbGVuZGFyT3JjaGVzdHJhdG9yIG1vZHRhZ2VyIElHcm91cGluZ1N0b3JlW10gYXV0b21hdGlzayAoYXJyYXkgaW5qZWN0aW9uKVxuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKENhbGVuZGFyT3JjaGVzdHJhdG9yKS5hcyhcIkNhbGVuZGFyT3JjaGVzdHJhdG9yXCIpLmF1dG9XaXJlKHtcbiAgICAgICAgbWFwUmVzb2x2ZXJzOiBbXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGVBbGwoXCJJUmVuZGVyZXJcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJFdmVudFJlbmRlcmVyXCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiU2NoZWR1bGVSZW5kZXJlclwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkhlYWRlckRyYXdlclJlbmRlcmVyXCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiRGF0ZVNlcnZpY2VcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGVBbGwoXCJJRW50aXR5U2VydmljZVwiKVxuICAgICAgICBdXG4gICAgfSk7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoVGltZUF4aXNSZW5kZXJlcikuYXMoXCJUaW1lQXhpc1JlbmRlcmVyXCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKFNjcm9sbE1hbmFnZXIpLmFzKFwiU2Nyb2xsTWFuYWdlclwiKTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShIZWFkZXJEcmF3ZXJNYW5hZ2VyKS5hcyhcIkhlYWRlckRyYXdlck1hbmFnZXJcIik7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoRHJhZ0Ryb3BNYW5hZ2VyKS5hcyhcIkRyYWdEcm9wTWFuYWdlclwiKS5hdXRvV2lyZSh7XG4gICAgICAgIG1hcFJlc29sdmVyczogW1xuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSUV2ZW50QnVzXCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSUdyaWRDb25maWdcIilcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKEVkZ2VTY3JvbGxNYW5hZ2VyKS5hcyhcIkVkZ2VTY3JvbGxNYW5hZ2VyXCIpLmF1dG9XaXJlKHtcbiAgICAgICAgbWFwUmVzb2x2ZXJzOiBbXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJRXZlbnRCdXNcIilcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKFJlc2l6ZU1hbmFnZXIpLmFzKFwiUmVzaXplTWFuYWdlclwiKS5hdXRvV2lyZSh7XG4gICAgICAgIG1hcFJlc29sdmVyczogW1xuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSUV2ZW50QnVzXCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSUdyaWRDb25maWdcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJEYXRlU2VydmljZVwiKVxuICAgICAgICBdXG4gICAgfSk7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoRXZlbnRQZXJzaXN0ZW5jZU1hbmFnZXIpLmFzKFwiRXZlbnRQZXJzaXN0ZW5jZU1hbmFnZXJcIikuYXV0b1dpcmUoe1xuICAgICAgICBtYXBSZXNvbHZlcnM6IFtcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkV2ZW50U2VydmljZVwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIklFdmVudEJ1c1wiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkRhdGVTZXJ2aWNlXCIpXG4gICAgICAgIF1cbiAgICB9KTtcbiAgICAvLyBDYWxlbmRhckFwcCAtIGdlbmJydWdlbGlnIGthbGVuZGVya29tcG9uZW50XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoQ2FsZW5kYXJBcHApLmFzKFwiQ2FsZW5kYXJBcHBcIikuYXV0b1dpcmUoe1xuICAgICAgICBtYXBSZXNvbHZlcnM6IFtcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkNhbGVuZGFyT3JjaGVzdHJhdG9yXCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiVGltZUF4aXNSZW5kZXJlclwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkRhdGVTZXJ2aWNlXCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiU2Nyb2xsTWFuYWdlclwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkhlYWRlckRyYXdlck1hbmFnZXJcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJEcmFnRHJvcE1hbmFnZXJcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJFZGdlU2Nyb2xsTWFuYWdlclwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIlJlc2l6ZU1hbmFnZXJcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJIZWFkZXJEcmF3ZXJSZW5kZXJlclwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkV2ZW50UGVyc2lzdGVuY2VNYW5hZ2VyXCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiU2V0dGluZ3NTZXJ2aWNlXCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiVmlld0NvbmZpZ1NlcnZpY2VcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJRXZlbnRCdXNcIilcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIC8vIERlbW8gYXBwXG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoRGVtb0FwcCkuYXMoXCJEZW1vQXBwXCIpLmF1dG9XaXJlKHtcbiAgICAgICAgbWFwUmVzb2x2ZXJzOiBbXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJbmRleGVkREJDb250ZXh0XCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiRGF0YVNlZWRlclwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkF1ZGl0U2VydmljZVwiKSxcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkNhbGVuZGFyQXBwXCIpLFxuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiRGF0ZVNlcnZpY2VcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJSZXNvdXJjZVNlcnZpY2VcIiksXG4gICAgICAgICAgICBjID0+IGMucmVzb2x2ZVR5cGUoXCJJRXZlbnRCdXNcIilcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIHJldHVybiBidWlsZGVyLmJ1aWxkKCk7XG59XG4iLCAiaW1wb3J0IHsgY3JlYXRlVjJDb250YWluZXIgfSBmcm9tICcuLi9WMkNvbXBvc2l0aW9uUm9vdCc7XG5jb25zdCBjb250YWluZXIgPSBjcmVhdGVWMkNvbnRhaW5lcigpO1xuY29udGFpbmVyLnJlc29sdmVUeXBlKFwiRGVtb0FwcFwiKS5pbml0KCkuY2F0Y2goY29uc29sZS5lcnJvcik7XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBLEtBQUMsU0FBUyxHQUFFLEdBQUU7QUFBQyxrQkFBVSxPQUFPLFdBQVMsZUFBYSxPQUFPLFNBQU8sT0FBTyxVQUFRLEVBQUUsSUFBRSxjQUFZLE9BQU8sVUFBUSxPQUFPLE1BQUksT0FBTyxDQUFDLEtBQUcsSUFBRSxlQUFhLE9BQU8sYUFBVyxhQUFXLEtBQUcsTUFBTSxRQUFNLEVBQUU7QUFBQSxJQUFDLEVBQUUsU0FBTSxXQUFVO0FBQUM7QUFBYSxVQUFJLElBQUUsS0FBSSxJQUFFLEtBQUksSUFB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V0FBVztBQUFBLElBQ2xDO0FBQUEsRUFDSixDQUFDO0FBRUQsVUFBUSxhQUFhLE9BQU8sRUFBRSxHQUFHLFNBQVMsRUFBRSxTQUFTO0FBQUEsSUFDakQsY0FBYztBQUFBLE1BQ1YsT0FBSyxFQUFFLFlBQVksa0JBQWtCO0FBQUEsTUFDckMsT0FBSyxFQUFFLFlBQVksWUFBWTtBQUFBLE1BQy9CLE9BQUssRUFBRSxZQUFZLGNBQWM7QUFBQSxNQUNqQyxPQUFLLEVBQUUsWUFBWSxhQUFhO0FBQUEsTUFDaEMsT0FBSyxFQUFFLFlBQVksYUFBYTtBQUFBLE1BQ2hDLE9BQUssRUFBRSxZQUFZLGlCQUFpQjtBQUFBLE1BQ3BDLE9BQUssRUFBRSxZQUFZLFdBQVc7QUFBQSxJQUNsQztBQUFBLEVBQ0osQ0FBQztBQUNELFNBQU8sUUFBUSxNQUFNO0FBQ3pCO0FBdlZnQjs7O0FDekVoQixJQUFNLFlBQVksa0JBQWtCO0FBQ3BDLFVBQVUsWUFBWSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sUUFBUSxLQUFLOyIsCiAgIm5hbWVzIjogWyJ0IiwgImUiLCAibiIsICJyIiwgImkiLCAicyIsICJ1IiwgImEiLCAiTSIsICJtIiwgImYiLCAibCIsICIkIiwgInkiLCAidiIsICJnIiwgIkQiLCAibyIsICJkIiwgImMiLCAiaCIsICJ0IiwgImkiLCAiZSIsICJzIiwgImYiLCAibiIsICJ1IiwgInIiLCAibyIsICJ0IiwgIm4iLCAiaSIsICJvIiwgInIiLCAiZSIsICJ1IiwgImYiLCAicyIsICJhIiwgInQiLCAiaSIsICJkIiwgIm4iLCAiZSIsICJzIiwgInRva2VuIiwgImNvbnRhaW5lciIsICJjb250YWluZXIiLCAidG9rZW4iLCAiY29udGFpbmVyIiwgImRheWpzIiwgInV0YyIsICJ0aW1lem9uZSIsICJpc29XZWVrIiwgImNvbnRhaW5lciIsICJjb250YWluZXIiLCAiY29udGFpbmVyIiwgImNvbnRhaW5lciIsICJjb250YWluZXIiLCAiY29udGFpbmVyIiwgImdldEtleSIsICJza2lwUGF0aCIsICJrZXkiLCAiY29udGFpbmVyIiwgImNvbnRhaW5lciIsICJjb250YWluZXIiLCAiZGlmZiIsICJjb250YWluZXIiLCAiY29udGFpbmVyIiwgImRpZmYiLCAiY29udGFpbmVyIl0KfQo=