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} 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().autoWire() * * // Strategy 2: map (minify-safe, explicit) * builder.registerType(EventBus).as().autoWire({ * map: { * logger: (c) => c.resolveType() * } * }) * * // Strategy 3: class (requires build-time codegen) * builder.registerType(EventBus).as().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 = ` ${this.dateService.getDayName(date, "short")} ${date.getDate()} `; 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 = ""; 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 = ` ${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 = ` ${this.dateService.formatTimeRange(event.start, event.end)} ${this.escapeHtml(event.title)} ${event.description ? `${this.escapeHtml(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=