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/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/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); } /** * Get dates starting from a day offset * @param dayOffset - Day offset from base date * @param count - Number of consecutive days to return * @returns Array of date strings in YYYY-MM-DD format */ getDatesFromOffset(dayOffset, count) { const startDate = this.baseDate.add(dayOffset, "day"); return Array.from({ length: count }, (_, i) => startDate.add(i, "day").format("YYYY-MM-DD")); } /** * Get specific weekdays from the week containing the offset date * @param dayOffset - Day offset from base date * @param workDays - Array of ISO weekday numbers (1=Monday, 7=Sunday) * @returns Array of date strings in YYYY-MM-DD format */ getWorkDaysFromOffset(dayOffset, workDays) { const targetDate = this.baseDate.add(dayOffset, "day"); const monday = targetDate.startOf("week").add(1, "day"); return workDays.map((isoDay) => { const daysFromMonday = isoDay === 7 ? 6 : isoDay - 1; return monday.add(daysFromMonday, "day").format("YYYY-MM-DD"); }); } // Legacy methods for backwards compatibility getWeekDates(weekOffset = 0, days = 7) { return this.getDatesFromOffset(weekOffset * 7, days); } getWorkWeekDates(weekOffset, workDays) { return this.getWorkDaysFromOffset(weekOffset * 7, workDays); } // ============================================ // 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/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/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/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/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/core/RenderBuilder.ts function buildPipeline(renderers) { return { async run(context) { for (const renderer of renderers) { await renderer.render(context); } } }; } __name(buildPipeline, "buildPipeline"); // src/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/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/core/NavigationAnimator.ts var _NavigationAnimator = class _NavigationAnimator { constructor(headerTrack, contentTrack, headerDrawer) { this.headerTrack = headerTrack; this.contentTrack = contentTrack; this.headerDrawer = headerDrawer; } 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) { const animations = [ 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 ]; if (this.headerDrawer) { animations.push(this.headerDrawer.animate([{ transform: "translateX(0)" }, { transform: `translateX(${translate})` }], { duration: 200, easing: "ease-in" }).finished); } await Promise.all(animations); } async animateIn(translate) { const animations = [ 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 ]; if (this.headerDrawer) { animations.push(this.headerDrawer.animate([{ transform: `translateX(${translate})` }, { transform: "translateX(0)" }], { duration: 200, easing: "ease-out" }).finished); } await Promise.all(animations); } }; __name(_NavigationAnimator, "NavigationAnimator"); var NavigationAnimator = _NavigationAnimator; // src/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/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.dayOffset = 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"), container2.querySelector("swp-header-drawer")); 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() { const step = this.workweekPreset?.periodDays ?? 7; this.dayOffset -= step; await this.animator.slide("right", () => this.render()); this.emitStatus("rendered", { viewId: this.currentViewId }); } async handleNavigateNext() { const step = this.workweekPreset?.periodDays ?? 7; this.dayOffset += step; 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 periodDays = this.workweekPreset?.periodDays ?? 7; const dates = periodDays === 1 ? this.dateService.getDatesFromOffset(this.dayOffset, workDays.length) : this.dateService.getWorkDaysFromOffset(this.dayOffset, 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/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/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/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/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/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/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/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 = "CalendarDB"; IndexedDBContext.DB_VERSION = 4; // src/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/types/SettingsTypes.ts var SettingsIds = { WORKWEEK: "workweek", GRID: "grid", TIME_FORMAT: "timeFormat", VIEWS: "views" }; // src/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/CompositionRoot.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 createContainer() { 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(createContainer, "createContainer"); // src/demo/index.ts var container = createContainer(); container.resolveType("DemoApp").init().catch(console.error); //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vbm9kZV9tb2R1bGVzL2RheWpzL2RheWpzLm1pbi5qcyIsICIuLi8uLi9ub2RlX21vZHVsZXMvZGF5anMvcGx1Z2luL3V0Yy5qcyIsICIuLi8uLi9ub2RlX21vZHVsZXMvZGF5anMvcGx1Z2luL3RpbWV6b25lLmpzIiwgIi4uLy4uL25vZGVfbW9kdWxlcy9kYXlqcy9wbHVnaW4vaXNvV2Vlay5qcyIsICIuLi8uLi9ub2RlX21vZHVsZXMvQG5vdmFkaS9jb3JlL2Rpc3QvdG9rZW4uanMiLCAiLi4vLi4vbm9kZV9tb2R1bGVzL0Bub3ZhZGkvY29yZS9kaXN0L2Vycm9ycy5qcyIsICIuLi8uLi9ub2RlX21vZHVsZXMvQG5vdmFkaS9jb3JlL2Rpc3QvYXV0b3dpcmUuanMiLCAiLi4vLi4vbm9kZV9tb2R1bGVzL0Bub3ZhZGkvY29yZS9kaXN0L2J1aWxkZXIuanMiLCAiLi4vLi4vbm9kZV9tb2R1bGVzL0Bub3ZhZGkvY29yZS9kaXN0L2NvbnRhaW5lci5qcyIsICIuLi8uLi9zcmMvZmVhdHVyZXMvZGF0ZS9EYXRlUmVuZGVyZXIudHMiLCAiLi4vLi4vc3JjL2NvcmUvRGF0ZVNlcnZpY2UudHMiLCAiLi4vLi4vc3JjL2NvcmUvQmFzZUdyb3VwaW5nUmVuZGVyZXIudHMiLCAiLi4vLi4vc3JjL2ZlYXR1cmVzL3Jlc291cmNlL1Jlc291cmNlUmVuZGVyZXIudHMiLCAiLi4vLi4vc3JjL2ZlYXR1cmVzL3RlYW0vVGVhbVJlbmRlcmVyLnRzIiwgIi4uLy4uL3NyYy9mZWF0dXJlcy9kZXBhcnRtZW50L0RlcGFydG1lbnRSZW5kZXJlci50cyIsICIuLi8uLi9zcmMvY29yZS9SZW5kZXJCdWlsZGVyLnRzIiwgIi4uLy4uL3NyYy9jb3JlL0ZpbHRlclRlbXBsYXRlLnRzIiwgIi4uLy4uL3NyYy9jb3JlL0NhbGVuZGFyT3JjaGVzdHJhdG9yLnRzIiwgIi4uLy4uL3NyYy9jb3JlL05hdmlnYXRpb25BbmltYXRvci50cyIsICIuLi8uLi9zcmMvY29yZS9DYWxlbmRhckV2ZW50cy50cyIsICIuLi8uLi9zcmMvY29yZS9DYWxlbmRhckFwcC50cyIsICIuLi8uLi9zcmMvZmVhdHVyZXMvdGltZWF4aXMvVGltZUF4aXNSZW5kZXJlci50cyIsICIuLi8uLi9zcmMvY29yZS9TY3JvbGxNYW5hZ2VyLnRzIiwgIi4uLy4uL3NyYy9jb3JlL0hlYWRlckRyYXdlck1hbmFnZXIudHMiLCAiLi4vLi4vc3JjL2RlbW8vTW9ja1N0b3Jlcy50cyIsICIuLi8uLi9zcmMvZGVtby9EZW1vQXBwLnRzIiwgIi4uLy4uL3NyYy9jb3JlL0V2ZW50QnVzLnRzIiwgIi4uLy4uL3NyYy9zdG9yYWdlL0luZGV4ZWREQkNvbnRleHQudHMiLCAiLi4vLi4vc3JjL3N0b3JhZ2UvZXZlbnRzL0V2ZW50U3RvcmUudHMiLCAiLi4vLi4vc3JjL3N0b3JhZ2UvZXZlbnRzL0V2ZW50U2VyaWFsaXphdGlvbi50cyIsICIuLi8uLi9zcmMvc3RvcmFnZS9TeW5jUGx1Z2luLnRzIiwgIi4uLy4uL3NyYy9jb25zdGFudHMvQ29yZUV2ZW50cy50cyIsICIuLi8uLi9ub2RlX21vZHVsZXMvanNvbi1kaWZmLXRzL3NyYy9oZWxwZXJzLnRzIiwgIi4uLy4uL25vZGVfbW9kdWxlcy9qc29uLWRpZmYtdHMvc3JjL2pzb25EaWZmLnRzIiwgIi4uLy4uL25vZGVfbW9kdWxlcy9qc29uLWRpZmYtdHMvc3JjL2pzb25Db21wYXJlLnRzIiwgIi4uLy4uL3NyYy9zdG9yYWdlL0Jhc2VFbnRpdHlTZXJ2aWNlLnRzIiwgIi4uLy4uL3NyYy9zdG9yYWdlL2V2ZW50cy9FdmVudFNlcnZpY2UudHMiLCAiLi4vLi4vc3JjL3N0b3JhZ2UvcmVzb3VyY2VzL1Jlc291cmNlU3RvcmUudHMiLCAiLi4vLi4vc3JjL3N0b3JhZ2UvcmVzb3VyY2VzL1Jlc291cmNlU2VydmljZS50cyIsICIuLi8uLi9zcmMvc3RvcmFnZS9ib29raW5ncy9Cb29raW5nU3RvcmUudHMiLCAiLi4vLi4vc3JjL3N0b3JhZ2UvYm9va2luZ3MvQm9va2luZ1NlcnZpY2UudHMiLCAiLi4vLi4vc3JjL3N0b3JhZ2UvY3VzdG9tZXJzL0N1c3RvbWVyU3RvcmUudHMiLCAiLi4vLi4vc3JjL3N0b3JhZ2UvY3VzdG9tZXJzL0N1c3RvbWVyU2VydmljZS50cyIsICIuLi8uLi9zcmMvc3RvcmFnZS90ZWFtcy9UZWFtU3RvcmUudHMiLCAiLi4vLi4vc3JjL3N0b3JhZ2UvdGVhbXMvVGVhbVNlcnZpY2UudHMiLCAiLi4vLi4vc3JjL3N0b3JhZ2UvZGVwYXJ0bWVudHMvRGVwYXJ0bWVudFN0b3JlLnRzIiwgIi4uLy4uL3NyYy9zdG9yYWdlL2RlcGFydG1lbnRzL0RlcGFydG1lbnRTZXJ2aWNlLnRzIiwgIi4uLy4uL3NyYy9zdG9yYWdlL3NldHRpbmdzL1NldHRpbmdzU3RvcmUudHMiLCAiLi4vLi4vc3JjL3R5cGVzL1NldHRpbmdzVHlwZXMudHMiLCAiLi4vLi4vc3JjL3N0b3JhZ2Uvc2V0dGluZ3MvU2V0dGluZ3NTZXJ2aWNlLnRzIiwgIi4uLy4uL3NyYy9zdG9yYWdlL3ZpZXdjb25maWdzL1ZpZXdDb25maWdTdG9yZS50cyIsICIuLi8uLi9zcmMvc3RvcmFnZS92aWV3Y29uZmlncy9WaWV3Q29uZmlnU2VydmljZS50cyIsICIuLi8uLi9zcmMvc3RvcmFnZS9hdWRpdC9BdWRpdFN0b3JlLnRzIiwgIi4uLy4uL3NyYy9zdG9yYWdlL2F1ZGl0L0F1ZGl0U2VydmljZS50cyIsICIuLi8uLi9zcmMvcmVwb3NpdG9yaWVzL01vY2tFdmVudFJlcG9zaXRvcnkudHMiLCAiLi4vLi4vc3JjL3JlcG9zaXRvcmllcy9Nb2NrUmVzb3VyY2VSZXBvc2l0b3J5LnRzIiwgIi4uLy4uL3NyYy9yZXBvc2l0b3JpZXMvTW9ja0Jvb2tpbmdSZXBvc2l0b3J5LnRzIiwgIi4uLy4uL3NyYy9yZXBvc2l0b3JpZXMvTW9ja0N1c3RvbWVyUmVwb3NpdG9yeS50cyIsICIuLi8uLi9zcmMvcmVwb3NpdG9yaWVzL01vY2tBdWRpdFJlcG9zaXRvcnkudHMiLCAiLi4vLi4vc3JjL3JlcG9zaXRvcmllcy9Nb2NrVGVhbVJlcG9zaXRvcnkudHMiLCAiLi4vLi4vc3JjL3JlcG9zaXRvcmllcy9Nb2NrRGVwYXJ0bWVudFJlcG9zaXRvcnkudHMiLCAiLi4vLi4vc3JjL3JlcG9zaXRvcmllcy9Nb2NrU2V0dGluZ3NSZXBvc2l0b3J5LnRzIiwgIi4uLy4uL3NyYy9yZXBvc2l0b3JpZXMvTW9ja1ZpZXdDb25maWdSZXBvc2l0b3J5LnRzIiwgIi4uLy4uL3NyYy93b3JrZXJzL0RhdGFTZWVkZXIudHMiLCAiLi4vLi4vc3JjL3V0aWxzL1Bvc2l0aW9uVXRpbHMudHMiLCAiLi4vLi4vc3JjL2ZlYXR1cmVzL2V2ZW50L0V2ZW50TGF5b3V0RW5naW5lLnRzIiwgIi4uLy4uL3NyYy9mZWF0dXJlcy9ldmVudC9FdmVudFJlbmRlcmVyLnRzIiwgIi4uLy4uL3NyYy9mZWF0dXJlcy9zY2hlZHVsZS9TY2hlZHVsZVJlbmRlcmVyLnRzIiwgIi4uLy4uL3NyYy9mZWF0dXJlcy9oZWFkZXJkcmF3ZXIvSGVhZGVyRHJhd2VyUmVuZGVyZXIudHMiLCAiLi4vLi4vc3JjL3N0b3JhZ2Uvc2NoZWR1bGVzL1NjaGVkdWxlT3ZlcnJpZGVTdG9yZS50cyIsICIuLi8uLi9zcmMvc3RvcmFnZS9zY2hlZHVsZXMvU2NoZWR1bGVPdmVycmlkZVNlcnZpY2UudHMiLCAiLi4vLi4vc3JjL3N0b3JhZ2Uvc2NoZWR1bGVzL1Jlc291cmNlU2NoZWR1bGVTZXJ2aWNlLnRzIiwgIi4uLy4uL3NyYy90eXBlcy9Td3BFdmVudC50cyIsICIuLi8uLi9zcmMvbWFuYWdlcnMvRHJhZ0Ryb3BNYW5hZ2VyLnRzIiwgIi4uLy4uL3NyYy9tYW5hZ2Vycy9FZGdlU2Nyb2xsTWFuYWdlci50cyIsICIuLi8uLi9zcmMvbWFuYWdlcnMvUmVzaXplTWFuYWdlci50cyIsICIuLi8uLi9zcmMvbWFuYWdlcnMvRXZlbnRQZXJzaXN0ZW5jZU1hbmFnZXIudHMiLCAiLi4vLi4vc3JjL0NvbXBvc2l0aW9uUm9vdC50cyIsICIuLi8uLi9zcmMvZGVtby9pbmRleC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiIWZ1bmN0aW9uKHQsZSl7XCJvYmplY3RcIj09dHlwZW9mIGV4cG9ydHMmJlwidW5kZWZpbmVkXCIhPXR5cGVvZiBtb2R1bGU/bW9kdWxlLmV4cG9ydHM9ZSgpOlwiZnVuY3Rpb25cIj09dHlwZW9mIGRlZmluZSYmZGVmaW5lLmFtZD9kZWZpbmUoZSk6KHQ9XCJ1bmRlZmluZWRcIiE9dHlwZW9mIGdsb2JhbFRoaXM/Z2xvYmFsVGhpczp0fHxzZWxmKS5kYXlqcz1lKCl9KHRoaXMsKGZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7dmFyIHQ9MWUzLGU9NmU0LG49MzZlNSxyPVwibWlsbGlzZWNvbmRcIixpPVwic2Vjb25kXCIscz1cIm1pbnV0ZVwiLHU9XCJob3VyXCIsYT1cImRheVwiLG89XCJ3ZWVrXCIsYz1cIm1vbnRoXCIsZj1cInF1YXJ0ZXJcIixoPVwieWVhclwiLGQ9XCJkYXRlXCIsbD1cIkludmFsaWQgRGF0ZVwiLCQ9L14oXFxkezR9KVstL10/KFxcZHsxLDJ9KT9bLS9dPyhcXGR7MCwyfSlbVHRcXHNdKihcXGR7MSwyfSk/Oj8oXFxkezEsMn0pPzo/KFxcZHsxLDJ9KT9bLjpdPyhcXGQrKT8kLyx5PS9cXFsoW15cXF1dKyldfFl7MSw0fXxNezEsNH18RHsxLDJ9fGR7MSw0fXxIezEsMn18aHsxLDJ9fGF8QXxtezEsMn18c3sxLDJ9fFp7MSwyfXxTU1MvZyxNPXtuYW1lOlwiZW5cIix3ZWVrZGF5czpcIlN1bmRheV9Nb25kYXlfVHVlc2RheV9XZWRuZXNkYXlfVGh1cnNkYXlfRnJpZGF5X1NhdHVyZGF5XCIuc3BsaXQoXCJfXCIpLG1vbnRoczpcIkphbnVhcnlfRmVicnVhcnlfTWFyY2hfQXByaWxfTWF5X0p1bmVfSnVseV9BdWd1c3RfU2VwdGVtYmVyX09jdG9iZXJfTm92ZW1iZXJfRGVjZW1iZXJcIi5zcGxpdChcIl9cIiksb3JkaW5hbDpmdW5jdGlvbih0KXt2YXIgZT1bXCJ0aFwiLFwic3RcIixcIm5kXCIsXCJyZFwiXSxuPXQlMTAwO3JldHVyblwiW1wiK3QrKGVbKG4tMjApJTEwXXx8ZVtuXXx8ZVswXSkrXCJdXCJ9fSxtPWZ1bmN0aW9uKHQsZSxuKXt2YXIgcj1TdHJpbmcodCk7cmV0dXJuIXJ8fHIubGVuZ3RoPj1lP3Q6XCJcIitBcnJheShlKzEtci5sZW5ndGgpLmpvaW4obikrdH0sdj17czptLHo6ZnVuY3Rpb24odCl7dmFyIGU9LXQudXRjT2Zmc2V0KCksbj1NYXRoLmFicyhlKSxyPU1hdGguZmxvb3Iobi82MCksaT1uJTYwO3JldHVybihlPD0wP1wiK1wiOlwiLVwiKSttKHIsMixcIjBcIikrXCI6XCIrbShpLDIsXCIwXCIpfSxtOmZ1bmN0aW9uIHQoZSxuKXtpZihlLmRhdGUoKTxuLmRhdGUoKSlyZXR1cm4tdChuLGUpO3ZhciByPTEyKihuLnllYXIoKS1lLnllYXIoKSkrKG4ubW9udGgoKS1lLm1vbnRoKCkpLGk9ZS5jbG9uZSgpLmFkZChyLGMpLHM9bi1pPDAsdT1lLmNsb25lKCkuYWRkKHIrKHM/LTE6MSksYyk7cmV0dXJuKygtKHIrKG4taSkvKHM/aS11OnUtaSkpfHwwKX0sYTpmdW5jdGlvbih0KXtyZXR1cm4gdDwwP01hdGguY2VpbCh0KXx8MDpNYXRoLmZsb29yKHQpfSxwOmZ1bmN0aW9uKHQpe3JldHVybntNOmMseTpoLHc6byxkOmEsRDpkLGg6dSxtOnMsczppLG1zOnIsUTpmfVt0XXx8U3RyaW5nKHR8fFwiXCIpLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvcyQvLFwiXCIpfSx1OmZ1bmN0aW9uKHQpe3JldHVybiB2b2lkIDA9PT10fX0sZz1cImVuXCIsRD17fTtEW2ddPU07dmFyIHA9XCIkaXNEYXlqc09iamVjdFwiLFM9ZnVuY3Rpb24odCl7cmV0dXJuIHQgaW5zdGFuY2VvZiBffHwhKCF0fHwhdFtwXSl9LHc9ZnVuY3Rpb24gdChlLG4scil7dmFyIGk7aWYoIWUpcmV0dXJuIGc7aWYoXCJzdHJpbmdcIj09dHlwZW9mIGUpe3ZhciBzPWUudG9Mb3dlckNhc2UoKTtEW3NdJiYoaT1zKSxuJiYoRFtzXT1uLGk9cyk7dmFyIHU9ZS5zcGxpdChcIi1cIik7aWYoIWkmJnUubGVuZ3RoPjEpcmV0dXJuIHQodVswXSl9ZWxzZXt2YXIgYT1lLm5hbWU7RFthXT1lLGk9YX1yZXR1cm4hciYmaSYmKGc9aSksaXx8IXImJmd9LE89ZnVuY3Rpb24odCxlKXtpZihTKHQpKXJldHVybiB0LmNsb25lKCk7dmFyIG49XCJvYmplY3RcIj09dHlwZW9mIGU/ZTp7fTtyZXR1cm4gbi5kYXRlPXQsbi5hcmdzPWFyZ3VtZW50cyxuZXcgXyhuKX0sYj12O2IubD13LGIuaT1TLGIudz1mdW5jdGlvbih0LGUpe3JldHVybiBPKHQse2xvY2FsZTplLiRMLHV0YzplLiR1LHg6ZS4keCwkb2Zmc2V0OmUuJG9mZnNldH0pfTt2YXIgXz1mdW5jdGlvbigpe2Z1bmN0aW9uIE0odCl7dGhpcy4kTD13KHQubG9jYWxlLG51bGwsITApLHRoaXMucGFyc2UodCksdGhpcy4keD10aGlzLiR4fHx0Lnh8fHt9LHRoaXNbcF09ITB9dmFyIG09TS5wcm90b3R5cGU7cmV0dXJuIG0ucGFyc2U9ZnVuY3Rpb24odCl7dGhpcy4kZD1mdW5jdGlvbih0KXt2YXIgZT10LmRhdGUsbj10LnV0YztpZihudWxsPT09ZSlyZXR1cm4gbmV3IERhdGUoTmFOKTtpZihiLnUoZSkpcmV0dXJuIG5ldyBEYXRlO2lmKGUgaW5zdGFuY2VvZiBEYXRlKXJldHVybiBuZXcgRGF0ZShlKTtpZihcInN0cmluZ1wiPT10eXBlb2YgZSYmIS9aJC9pLnRlc3QoZSkpe3ZhciByPWUubWF0Y2goJCk7aWYocil7dmFyIGk9clsyXS0xfHwwLHM9KHJbN118fFwiMFwiKS5zdWJzdHJpbmcoMCwzKTtyZXR1cm4gbj9uZXcgRGF0ZShEYXRlLlVUQyhyWzFdLGksclszXXx8MSxyWzRdfHwwLHJbNV18fDAscls2XXx8MCxzKSk6bmV3IERhdGUoclsxXSxpLHJbM118fDEscls0XXx8MCxyWzVdfHwwLHJbNl18fDAscyl9fXJldHVybiBuZXcgRGF0ZShlKX0odCksdGhpcy5pbml0KCl9LG0uaW5pdD1mdW5jdGlvbigpe3ZhciB0PXRoaXMuJGQ7dGhpcy4keT10LmdldEZ1bGxZZWFyKCksdGhpcy4kTT10LmdldE1vbnRoKCksdGhpcy4kRD10LmdldERhdGUoKSx0aGlzLiRXPXQuZ2V0RGF5KCksdGhpcy4kSD10LmdldEhvdXJzKCksdGhpcy4kbT10LmdldE1pbnV0ZXMoKSx0aGlzLiRzPXQuZ2V0U2Vjb25kcygpLHRoaXMuJG1zPXQuZ2V0TWlsbGlzZWNvbmRzKCl9LG0uJHV0aWxzPWZ1bmN0aW9uKCl7cmV0dXJuIGJ9LG0uaXNWYWxpZD1mdW5jdGlvbigpe3JldHVybiEodGhpcy4kZC50b1N0cmluZygpPT09bCl9LG0uaXNTYW1lPWZ1bmN0aW9uKHQsZSl7dmFyIG49Tyh0KTtyZXR1cm4gdGhpcy5zdGFydE9mKGUpPD1uJiZuPD10aGlzLmVuZE9mKGUpfSxtLmlzQWZ0ZXI9ZnVuY3Rpb24odCxlKXtyZXR1cm4gTyh0KTx0aGlzLnN0YXJ0T2YoZSl9LG0uaXNCZWZvcmU9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5lbmRPZihlKTxPKHQpfSxtLiRnPWZ1bmN0aW9uKHQsZSxuKXtyZXR1cm4gYi51KHQpP3RoaXNbZV06dGhpcy5zZXQobix0KX0sbS51bml4PWZ1bmN0aW9uKCl7cmV0dXJuIE1hdGguZmxvb3IodGhpcy52YWx1ZU9mKCkvMWUzKX0sbS52YWx1ZU9mPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuJGQuZ2V0VGltZSgpfSxtLnN0YXJ0T2Y9ZnVuY3Rpb24odCxlKXt2YXIgbj10aGlzLHI9ISFiLnUoZSl8fGUsZj1iLnAodCksbD1mdW5jdGlvbih0LGUpe3ZhciBpPWIudyhuLiR1P0RhdGUuVVRDKG4uJHksZSx0KTpuZXcgRGF0ZShuLiR5LGUsdCksbik7cmV0dXJuIHI/aTppLmVuZE9mKGEpfSwkPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIGIudyhuLnRvRGF0ZSgpW3RdLmFwcGx5KG4udG9EYXRlKFwic1wiKSwocj9bMCwwLDAsMF06WzIzLDU5LDU5LDk5OV0pLnNsaWNlKGUpKSxuKX0seT10aGlzLiRXLE09dGhpcy4kTSxtPXRoaXMuJEQsdj1cInNldFwiKyh0aGlzLiR1P1wiVVRDXCI6XCJcIik7c3dpdGNoKGYpe2Nhc2UgaDpyZXR1cm4gcj9sKDEsMCk6bCgzMSwxMSk7Y2FzZSBjOnJldHVybiByP2woMSxNKTpsKDAsTSsxKTtjYXNlIG86dmFyIGc9dGhpcy4kbG9jYWxlKCkud2Vla1N0YXJ0fHwwLEQ9KHk8Zz95Kzc6eSktZztyZXR1cm4gbChyP20tRDptKyg2LUQpLE0pO2Nhc2UgYTpjYXNlIGQ6cmV0dXJuICQoditcIkhvdXJzXCIsMCk7Y2FzZSB1OnJldHVybiAkKHYrXCJNaW51dGVzXCIsMSk7Y2FzZSBzOnJldHVybiAkKHYrXCJTZWNvbmRzXCIsMik7Y2FzZSBpOnJldHVybiAkKHYrXCJNaWxsaXNlY29uZHNcIiwzKTtkZWZhdWx0OnJldHVybiB0aGlzLmNsb25lKCl9fSxtLmVuZE9mPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLnN0YXJ0T2YodCwhMSl9LG0uJHNldD1mdW5jdGlvbih0LGUpe3ZhciBuLG89Yi5wKHQpLGY9XCJzZXRcIisodGhpcy4kdT9cIlVUQ1wiOlwiXCIpLGw9KG49e30sblthXT1mK1wiRGF0ZVwiLG5bZF09ZitcIkRhdGVcIixuW2NdPWYrXCJNb250aFwiLG5baF09ZitcIkZ1bGxZZWFyXCIsblt1XT1mK1wiSG91cnNcIixuW3NdPWYrXCJNaW51dGVzXCIsbltpXT1mK1wiU2Vjb25kc1wiLG5bcl09ZitcIk1pbGxpc2Vjb25kc1wiLG4pW29dLCQ9bz09PWE/dGhpcy4kRCsoZS10aGlzLiRXKTplO2lmKG89PT1jfHxvPT09aCl7dmFyIHk9dGhpcy5jbG9uZSgpLnNldChkLDEpO3kuJGRbbF0oJCkseS5pbml0KCksdGhpcy4kZD15LnNldChkLE1hdGgubWluKHRoaXMuJEQseS5kYXlzSW5Nb250aCgpKSkuJGR9ZWxzZSBsJiZ0aGlzLiRkW2xdKCQpO3JldHVybiB0aGlzLmluaXQoKSx0aGlzfSxtLnNldD1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmNsb25lKCkuJHNldCh0LGUpfSxtLmdldD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpc1tiLnAodCldKCl9LG0uYWRkPWZ1bmN0aW9uKHIsZil7dmFyIGQsbD10aGlzO3I9TnVtYmVyKHIpO3ZhciAkPWIucChmKSx5PWZ1bmN0aW9uKHQpe3ZhciBlPU8obCk7cmV0dXJuIGIudyhlLmRhdGUoZS5kYXRlKCkrTWF0aC5yb3VuZCh0KnIpKSxsKX07aWYoJD09PWMpcmV0dXJuIHRoaXMuc2V0KGMsdGhpcy4kTStyKTtpZigkPT09aClyZXR1cm4gdGhpcy5zZXQoaCx0aGlzLiR5K3IpO2lmKCQ9PT1hKXJldHVybiB5KDEpO2lmKCQ9PT1vKXJldHVybiB5KDcpO3ZhciBNPShkPXt9LGRbc109ZSxkW3VdPW4sZFtpXT10LGQpWyRdfHwxLG09dGhpcy4kZC5nZXRUaW1lKCkrcipNO3JldHVybiBiLncobSx0aGlzKX0sbS5zdWJ0cmFjdD1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmFkZCgtMSp0LGUpfSxtLmZvcm1hdD1mdW5jdGlvbih0KXt2YXIgZT10aGlzLG49dGhpcy4kbG9jYWxlKCk7aWYoIXRoaXMuaXNWYWxpZCgpKXJldHVybiBuLmludmFsaWREYXRlfHxsO3ZhciByPXR8fFwiWVlZWS1NTS1ERFRISDptbTpzc1pcIixpPWIueih0aGlzKSxzPXRoaXMuJEgsdT10aGlzLiRtLGE9dGhpcy4kTSxvPW4ud2Vla2RheXMsYz1uLm1vbnRocyxmPW4ubWVyaWRpZW0saD1mdW5jdGlvbih0LG4saSxzKXtyZXR1cm4gdCYmKHRbbl18fHQoZSxyKSl8fGlbbl0uc2xpY2UoMCxzKX0sZD1mdW5jdGlvbih0KXtyZXR1cm4gYi5zKHMlMTJ8fDEyLHQsXCIwXCIpfSwkPWZ8fGZ1bmN0aW9uKHQsZSxuKXt2YXIgcj10PDEyP1wiQU1cIjpcIlBNXCI7cmV0dXJuIG4/ci50b0xvd2VyQ2FzZSgpOnJ9O3JldHVybiByLnJlcGxhY2UoeSwoZnVuY3Rpb24odCxyKXtyZXR1cm4gcnx8ZnVuY3Rpb24odCl7c3dpdGNoKHQpe2Nhc2VcIllZXCI6cmV0dXJuIFN0cmluZyhlLiR5KS5zbGljZSgtMik7Y2FzZVwiWVlZWVwiOnJldHVybiBiLnMoZS4keSw0LFwiMFwiKTtjYXNlXCJNXCI6cmV0dXJuIGErMTtjYXNlXCJNTVwiOnJldHVybiBiLnMoYSsxLDIsXCIwXCIpO2Nhc2VcIk1NTVwiOnJldHVybiBoKG4ubW9udGhzU2hvcnQsYSxjLDMpO2Nhc2VcIk1NTU1cIjpyZXR1cm4gaChjLGEpO2Nhc2VcIkRcIjpyZXR1cm4gZS4kRDtjYXNlXCJERFwiOnJldHVybiBiLnMoZS4kRCwyLFwiMFwiKTtjYXNlXCJkXCI6cmV0dXJuIFN0cmluZyhlLiRXKTtjYXNlXCJkZFwiOnJldHVybiBoKG4ud2Vla2RheXNNaW4sZS4kVyxvLDIpO2Nhc2VcImRkZFwiOnJldHVybiBoKG4ud2Vla2RheXNTaG9ydCxlLiRXLG8sMyk7Y2FzZVwiZGRkZFwiOnJldHVybiBvW2UuJFddO2Nhc2VcIkhcIjpyZXR1cm4gU3RyaW5nKHMpO2Nhc2VcIkhIXCI6cmV0dXJuIGIucyhzLDIsXCIwXCIpO2Nhc2VcImhcIjpyZXR1cm4gZCgxKTtjYXNlXCJoaFwiOnJldHVybiBkKDIpO2Nhc2VcImFcIjpyZXR1cm4gJChzLHUsITApO2Nhc2VcIkFcIjpyZXR1cm4gJChzLHUsITEpO2Nhc2VcIm1cIjpyZXR1cm4gU3RyaW5nKHUpO2Nhc2VcIm1tXCI6cmV0dXJuIGIucyh1LDIsXCIwXCIpO2Nhc2VcInNcIjpyZXR1cm4gU3RyaW5nKGUuJHMpO2Nhc2VcInNzXCI6cmV0dXJuIGIucyhlLiRzLDIsXCIwXCIpO2Nhc2VcIlNTU1wiOnJldHVybiBiLnMoZS4kbXMsMyxcIjBcIik7Y2FzZVwiWlwiOnJldHVybiBpfXJldHVybiBudWxsfSh0KXx8aS5yZXBsYWNlKFwiOlwiLFwiXCIpfSkpfSxtLnV0Y09mZnNldD1mdW5jdGlvbigpe3JldHVybiAxNSotTWF0aC5yb3VuZCh0aGlzLiRkLmdldFRpbWV6b25lT2Zmc2V0KCkvMTUpfSxtLmRpZmY9ZnVuY3Rpb24ocixkLGwpe3ZhciAkLHk9dGhpcyxNPWIucChkKSxtPU8ociksdj0obS51dGNPZmZzZXQoKS10aGlzLnV0Y09mZnNldCgpKSplLGc9dGhpcy1tLEQ9ZnVuY3Rpb24oKXtyZXR1cm4gYi5tKHksbSl9O3N3aXRjaChNKXtjYXNlIGg6JD1EKCkvMTI7YnJlYWs7Y2FzZSBjOiQ9RCgpO2JyZWFrO2Nhc2UgZjokPUQoKS8zO2JyZWFrO2Nhc2UgbzokPShnLXYpLzYwNDhlNTticmVhaztjYXNlIGE6JD0oZy12KS84NjRlNTticmVhaztjYXNlIHU6JD1nL247YnJlYWs7Y2FzZSBzOiQ9Zy9lO2JyZWFrO2Nhc2UgaTokPWcvdDticmVhaztkZWZhdWx0OiQ9Z31yZXR1cm4gbD8kOmIuYSgkKX0sbS5kYXlzSW5Nb250aD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmVuZE9mKGMpLiREfSxtLiRsb2NhbGU9ZnVuY3Rpb24oKXtyZXR1cm4gRFt0aGlzLiRMXX0sbS5sb2NhbGU9ZnVuY3Rpb24odCxlKXtpZighdClyZXR1cm4gdGhpcy4kTDt2YXIgbj10aGlzLmNsb25lKCkscj13KHQsZSwhMCk7cmV0dXJuIHImJihuLiRMPXIpLG59LG0uY2xvbmU9ZnVuY3Rpb24oKXtyZXR1cm4gYi53KHRoaXMuJGQsdGhpcyl9LG0udG9EYXRlPWZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBEYXRlKHRoaXMudmFsdWVPZigpKX0sbS50b0pTT049ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5pc1ZhbGlkKCk/dGhpcy50b0lTT1N0cmluZygpOm51bGx9LG0udG9JU09TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy4kZC50b0lTT1N0cmluZygpfSxtLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuJGQudG9VVENTdHJpbmcoKX0sTX0oKSxrPV8ucHJvdG90eXBlO3JldHVybiBPLnByb3RvdHlwZT1rLFtbXCIkbXNcIixyXSxbXCIkc1wiLGldLFtcIiRtXCIsc10sW1wiJEhcIix1XSxbXCIkV1wiLGFdLFtcIiRNXCIsY10sW1wiJHlcIixoXSxbXCIkRFwiLGRdXS5mb3JFYWNoKChmdW5jdGlvbih0KXtrW3RbMV1dPWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLiRnKGUsdFswXSx0WzFdKX19KSksTy5leHRlbmQ9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdC4kaXx8KHQoZSxfLE8pLHQuJGk9ITApLE99LE8ubG9jYWxlPXcsTy5pc0RheWpzPVMsTy51bml4PWZ1bmN0aW9uKHQpe3JldHVybiBPKDFlMyp0KX0sTy5lbj1EW2ddLE8uTHM9RCxPLnA9e30sT30pKTsiLCAiIWZ1bmN0aW9uKHQsaSl7XCJvYmplY3RcIj09dHlwZW9mIGV4cG9ydHMmJlwidW5kZWZpbmVkXCIhPXR5cGVvZiBtb2R1bGU/bW9kdWxlLmV4cG9ydHM9aSgpOlwiZnVuY3Rpb25cIj09dHlwZW9mIGRlZmluZSYmZGVmaW5lLmFtZD9kZWZpbmUoaSk6KHQ9XCJ1bmRlZmluZWRcIiE9dHlwZW9mIGdsb2JhbFRoaXM/Z2xvYmFsVGhpczp0fHxzZWxmKS5kYXlqc19wbHVnaW5fdXRjPWkoKX0odGhpcywoZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt2YXIgdD1cIm1pbnV0ZVwiLGk9L1srLV1cXGRcXGQoPzo6P1xcZFxcZCk/L2csZT0vKFsrLV18XFxkXFxkKS9nO3JldHVybiBmdW5jdGlvbihzLGYsbil7dmFyIHU9Zi5wcm90b3R5cGU7bi51dGM9ZnVuY3Rpb24odCl7dmFyIGk9e2RhdGU6dCx1dGM6ITAsYXJnczphcmd1bWVudHN9O3JldHVybiBuZXcgZihpKX0sdS51dGM9ZnVuY3Rpb24oaSl7dmFyIGU9bih0aGlzLnRvRGF0ZSgpLHtsb2NhbGU6dGhpcy4kTCx1dGM6ITB9KTtyZXR1cm4gaT9lLmFkZCh0aGlzLnV0Y09mZnNldCgpLHQpOmV9LHUubG9jYWw9ZnVuY3Rpb24oKXtyZXR1cm4gbih0aGlzLnRvRGF0ZSgpLHtsb2NhbGU6dGhpcy4kTCx1dGM6ITF9KX07dmFyIHI9dS5wYXJzZTt1LnBhcnNlPWZ1bmN0aW9uKHQpe3QudXRjJiYodGhpcy4kdT0hMCksdGhpcy4kdXRpbHMoKS51KHQuJG9mZnNldCl8fCh0aGlzLiRvZmZzZXQ9dC4kb2Zmc2V0KSxyLmNhbGwodGhpcyx0KX07dmFyIG89dS5pbml0O3UuaW5pdD1mdW5jdGlvbigpe2lmKHRoaXMuJHUpe3ZhciB0PXRoaXMuJGQ7dGhpcy4keT10LmdldFVUQ0Z1bGxZZWFyKCksdGhpcy4kTT10LmdldFVUQ01vbnRoKCksdGhpcy4kRD10LmdldFVUQ0RhdGUoKSx0aGlzLiRXPXQuZ2V0VVRDRGF5KCksdGhpcy4kSD10LmdldFVUQ0hvdXJzKCksdGhpcy4kbT10LmdldFVUQ01pbnV0ZXMoKSx0aGlzLiRzPXQuZ2V0VVRDU2Vjb25kcygpLHRoaXMuJG1zPXQuZ2V0VVRDTWlsbGlzZWNvbmRzKCl9ZWxzZSBvLmNhbGwodGhpcyl9O3ZhciBhPXUudXRjT2Zmc2V0O3UudXRjT2Zmc2V0PWZ1bmN0aW9uKHMsZil7dmFyIG49dGhpcy4kdXRpbHMoKS51O2lmKG4ocykpcmV0dXJuIHRoaXMuJHU/MDpuKHRoaXMuJG9mZnNldCk/YS5jYWxsKHRoaXMpOnRoaXMuJG9mZnNldDtpZihcInN0cmluZ1wiPT10eXBlb2YgcyYmKHM9ZnVuY3Rpb24odCl7dm9pZCAwPT09dCYmKHQ9XCJcIik7dmFyIHM9dC5tYXRjaChpKTtpZighcylyZXR1cm4gbnVsbDt2YXIgZj0oXCJcIitzWzBdKS5tYXRjaChlKXx8W1wiLVwiLDAsMF0sbj1mWzBdLHU9NjAqK2ZbMV0rICtmWzJdO3JldHVybiAwPT09dT8wOlwiK1wiPT09bj91Oi11fShzKSxudWxsPT09cykpcmV0dXJuIHRoaXM7dmFyIHU9TWF0aC5hYnMocyk8PTE2PzYwKnM6cztpZigwPT09dSlyZXR1cm4gdGhpcy51dGMoZik7dmFyIHI9dGhpcy5jbG9uZSgpO2lmKGYpcmV0dXJuIHIuJG9mZnNldD11LHIuJHU9ITEscjt2YXIgbz10aGlzLiR1P3RoaXMudG9EYXRlKCkuZ2V0VGltZXpvbmVPZmZzZXQoKTotMSp0aGlzLnV0Y09mZnNldCgpO3JldHVybihyPXRoaXMubG9jYWwoKS5hZGQodStvLHQpKS4kb2Zmc2V0PXUsci4keC4kbG9jYWxPZmZzZXQ9byxyfTt2YXIgaD11LmZvcm1hdDt1LmZvcm1hdD1mdW5jdGlvbih0KXt2YXIgaT10fHwodGhpcy4kdT9cIllZWVktTU0tRERUSEg6bW06c3NbWl1cIjpcIlwiKTtyZXR1cm4gaC5jYWxsKHRoaXMsaSl9LHUudmFsdWVPZj1mdW5jdGlvbigpe3ZhciB0PXRoaXMuJHV0aWxzKCkudSh0aGlzLiRvZmZzZXQpPzA6dGhpcy4kb2Zmc2V0Kyh0aGlzLiR4LiRsb2NhbE9mZnNldHx8dGhpcy4kZC5nZXRUaW1lem9uZU9mZnNldCgpKTtyZXR1cm4gdGhpcy4kZC52YWx1ZU9mKCktNmU0KnR9LHUuaXNVVEM9ZnVuY3Rpb24oKXtyZXR1cm4hIXRoaXMuJHV9LHUudG9JU09TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy50b0RhdGUoKS50b0lTT1N0cmluZygpfSx1LnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudG9EYXRlKCkudG9VVENTdHJpbmcoKX07dmFyIGw9dS50b0RhdGU7dS50b0RhdGU9ZnVuY3Rpb24odCl7cmV0dXJuXCJzXCI9PT10JiZ0aGlzLiRvZmZzZXQ/bih0aGlzLmZvcm1hdChcIllZWVktTU0tREQgSEg6bW06c3M6U1NTXCIpKS50b0RhdGUoKTpsLmNhbGwodGhpcyl9O3ZhciBjPXUuZGlmZjt1LmRpZmY9ZnVuY3Rpb24odCxpLGUpe2lmKHQmJnRoaXMuJHU9PT10LiR1KXJldHVybiBjLmNhbGwodGhpcyx0LGksZSk7dmFyIHM9dGhpcy5sb2NhbCgpLGY9bih0KS5sb2NhbCgpO3JldHVybiBjLmNhbGwocyxmLGksZSl9fX0pKTsiLCAiIWZ1bmN0aW9uKHQsZSl7XCJvYmplY3RcIj09dHlwZW9mIGV4cG9ydHMmJlwidW5kZWZpbmVkXCIhPXR5cGVvZiBtb2R1bGU/bW9kdWxlLmV4cG9ydHM9ZSgpOlwiZnVuY3Rpb25cIj09dHlwZW9mIGRlZmluZSYmZGVmaW5lLmFtZD9kZWZpbmUoZSk6KHQ9XCJ1bmRlZmluZWRcIiE9dHlwZW9mIGdsb2JhbFRoaXM/Z2xvYmFsVGhpczp0fHxzZWxmKS5kYXlqc19wbHVnaW5fdGltZXpvbmU9ZSgpfSh0aGlzLChmdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3ZhciB0PXt5ZWFyOjAsbW9udGg6MSxkYXk6Mixob3VyOjMsbWludXRlOjQsc2Vjb25kOjV9LGU9e307cmV0dXJuIGZ1bmN0aW9uKG4saSxvKXt2YXIgcixhPWZ1bmN0aW9uKHQsbixpKXt2b2lkIDA9PT1pJiYoaT17fSk7dmFyIG89bmV3IERhdGUodCkscj1mdW5jdGlvbih0LG4pe3ZvaWQgMD09PW4mJihuPXt9KTt2YXIgaT1uLnRpbWVab25lTmFtZXx8XCJzaG9ydFwiLG89dCtcInxcIitpLHI9ZVtvXTtyZXR1cm4gcnx8KHI9bmV3IEludGwuRGF0ZVRpbWVGb3JtYXQoXCJlbi1VU1wiLHtob3VyMTI6ITEsdGltZVpvbmU6dCx5ZWFyOlwibnVtZXJpY1wiLG1vbnRoOlwiMi1kaWdpdFwiLGRheTpcIjItZGlnaXRcIixob3VyOlwiMi1kaWdpdFwiLG1pbnV0ZTpcIjItZGlnaXRcIixzZWNvbmQ6XCIyLWRpZ2l0XCIsdGltZVpvbmVOYW1lOml9KSxlW29dPXIpLHJ9KG4saSk7cmV0dXJuIHIuZm9ybWF0VG9QYXJ0cyhvKX0sdT1mdW5jdGlvbihlLG4pe2Zvcih2YXIgaT1hKGUsbikscj1bXSx1PTA7dTxpLmxlbmd0aDt1Kz0xKXt2YXIgZj1pW3VdLHM9Zi50eXBlLG09Zi52YWx1ZSxjPXRbc107Yz49MCYmKHJbY109cGFyc2VJbnQobSwxMCkpfXZhciBkPXJbM10sbD0yND09PWQ/MDpkLGg9clswXStcIi1cIityWzFdK1wiLVwiK3JbMl0rXCIgXCIrbCtcIjpcIityWzRdK1wiOlwiK3JbNV0rXCI6MDAwXCIsdj0rZTtyZXR1cm4oby51dGMoaCkudmFsdWVPZigpLSh2LT12JTFlMykpLzZlNH0sZj1pLnByb3RvdHlwZTtmLnR6PWZ1bmN0aW9uKHQsZSl7dm9pZCAwPT09dCYmKHQ9cik7dmFyIG4saT10aGlzLnV0Y09mZnNldCgpLGE9dGhpcy50b0RhdGUoKSx1PWEudG9Mb2NhbGVTdHJpbmcoXCJlbi1VU1wiLHt0aW1lWm9uZTp0fSksZj1NYXRoLnJvdW5kKChhLW5ldyBEYXRlKHUpKS8xZTMvNjApLHM9MTUqLU1hdGgucm91bmQoYS5nZXRUaW1lem9uZU9mZnNldCgpLzE1KS1mO2lmKCFOdW1iZXIocykpbj10aGlzLnV0Y09mZnNldCgwLGUpO2Vsc2UgaWYobj1vKHUse2xvY2FsZTp0aGlzLiRMfSkuJHNldChcIm1pbGxpc2Vjb25kXCIsdGhpcy4kbXMpLnV0Y09mZnNldChzLCEwKSxlKXt2YXIgbT1uLnV0Y09mZnNldCgpO249bi5hZGQoaS1tLFwibWludXRlXCIpfXJldHVybiBuLiR4LiR0aW1lem9uZT10LG59LGYub2Zmc2V0TmFtZT1mdW5jdGlvbih0KXt2YXIgZT10aGlzLiR4LiR0aW1lem9uZXx8by50ei5ndWVzcygpLG49YSh0aGlzLnZhbHVlT2YoKSxlLHt0aW1lWm9uZU5hbWU6dH0pLmZpbmQoKGZ1bmN0aW9uKHQpe3JldHVyblwidGltZXpvbmVuYW1lXCI9PT10LnR5cGUudG9Mb3dlckNhc2UoKX0pKTtyZXR1cm4gbiYmbi52YWx1ZX07dmFyIHM9Zi5zdGFydE9mO2Yuc3RhcnRPZj1mdW5jdGlvbih0LGUpe2lmKCF0aGlzLiR4fHwhdGhpcy4keC4kdGltZXpvbmUpcmV0dXJuIHMuY2FsbCh0aGlzLHQsZSk7dmFyIG49byh0aGlzLmZvcm1hdChcIllZWVktTU0tREQgSEg6bW06c3M6U1NTXCIpLHtsb2NhbGU6dGhpcy4kTH0pO3JldHVybiBzLmNhbGwobix0LGUpLnR6KHRoaXMuJHguJHRpbWV6b25lLCEwKX0sby50ej1mdW5jdGlvbih0LGUsbil7dmFyIGk9biYmZSxhPW58fGV8fHIsZj11KCtvKCksYSk7aWYoXCJzdHJpbmdcIiE9dHlwZW9mIHQpcmV0dXJuIG8odCkudHooYSk7dmFyIHM9ZnVuY3Rpb24odCxlLG4pe3ZhciBpPXQtNjAqZSoxZTMsbz11KGksbik7aWYoZT09PW8pcmV0dXJuW2ksZV07dmFyIHI9dShpLT02MCooby1lKSoxZTMsbik7cmV0dXJuIG89PT1yP1tpLG9dOlt0LTYwKk1hdGgubWluKG8scikqMWUzLE1hdGgubWF4KG8scildfShvLnV0Yyh0LGkpLnZhbHVlT2YoKSxmLGEpLG09c1swXSxjPXNbMV0sZD1vKG0pLnV0Y09mZnNldChjKTtyZXR1cm4gZC4keC4kdGltZXpvbmU9YSxkfSxvLnR6Lmd1ZXNzPWZ1bmN0aW9uKCl7cmV0dXJuIEludGwuRGF0ZVRpbWVGb3JtYXQoKS5yZXNvbHZlZE9wdGlvbnMoKS50aW1lWm9uZX0sby50ei5zZXREZWZhdWx0PWZ1bmN0aW9uKHQpe3I9dH19fSkpOyIsICIhZnVuY3Rpb24oZSx0KXtcIm9iamVjdFwiPT10eXBlb2YgZXhwb3J0cyYmXCJ1bmRlZmluZWRcIiE9dHlwZW9mIG1vZHVsZT9tb2R1bGUuZXhwb3J0cz10KCk6XCJmdW5jdGlvblwiPT10eXBlb2YgZGVmaW5lJiZkZWZpbmUuYW1kP2RlZmluZSh0KTooZT1cInVuZGVmaW5lZFwiIT10eXBlb2YgZ2xvYmFsVGhpcz9nbG9iYWxUaGlzOmV8fHNlbGYpLmRheWpzX3BsdWdpbl9pc29XZWVrPXQoKX0odGhpcywoZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt2YXIgZT1cImRheVwiO3JldHVybiBmdW5jdGlvbih0LGkscyl7dmFyIGE9ZnVuY3Rpb24odCl7cmV0dXJuIHQuYWRkKDQtdC5pc29XZWVrZGF5KCksZSl9LGQ9aS5wcm90b3R5cGU7ZC5pc29XZWVrWWVhcj1mdW5jdGlvbigpe3JldHVybiBhKHRoaXMpLnllYXIoKX0sZC5pc29XZWVrPWZ1bmN0aW9uKHQpe2lmKCF0aGlzLiR1dGlscygpLnUodCkpcmV0dXJuIHRoaXMuYWRkKDcqKHQtdGhpcy5pc29XZWVrKCkpLGUpO3ZhciBpLGQsbixvLHI9YSh0aGlzKSx1PShpPXRoaXMuaXNvV2Vla1llYXIoKSxkPXRoaXMuJHUsbj0oZD9zLnV0YzpzKSgpLnllYXIoaSkuc3RhcnRPZihcInllYXJcIiksbz00LW4uaXNvV2Vla2RheSgpLG4uaXNvV2Vla2RheSgpPjQmJihvKz03KSxuLmFkZChvLGUpKTtyZXR1cm4gci5kaWZmKHUsXCJ3ZWVrXCIpKzF9LGQuaXNvV2Vla2RheT1mdW5jdGlvbihlKXtyZXR1cm4gdGhpcy4kdXRpbHMoKS51KGUpP3RoaXMuZGF5KCl8fDc6dGhpcy5kYXkodGhpcy5kYXkoKSU3P2U6ZS03KX07dmFyIG49ZC5zdGFydE9mO2Quc3RhcnRPZj1mdW5jdGlvbihlLHQpe3ZhciBpPXRoaXMuJHV0aWxzKCkscz0hIWkudSh0KXx8dDtyZXR1cm5cImlzb3dlZWtcIj09PWkucChlKT9zP3RoaXMuZGF0ZSh0aGlzLmRhdGUoKS0odGhpcy5pc29XZWVrZGF5KCktMSkpLnN0YXJ0T2YoXCJkYXlcIik6dGhpcy5kYXRlKHRoaXMuZGF0ZSgpLTEtKHRoaXMuaXNvV2Vla2RheSgpLTEpKzcpLmVuZE9mKFwiZGF5XCIpOm4uYmluZCh0aGlzKShlLHQpfX19KSk7IiwgImxldCB0b2tlbkNvdW50ZXIgPSAwO1xuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IHVuaXF1ZSB0b2tlbiBmb3IgZGVwZW5kZW5jeSBpbmplY3Rpb24uXG4gKlxuICogQHBhcmFtIGRlc2NyaXB0aW9uIE9wdGlvbmFsIGRlc2NyaXB0aW9uIGZvciBkZWJ1Z2dpbmcgcHVycG9zZXNcbiAqIEByZXR1cm5zIEEgdW5pcXVlIHRva2VuIHRoYXQgY2FuIGJlIHVzZWQgYXMgYSBNYXAga2V5XG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiBpbnRlcmZhY2UgSUxvZ2dlciB7IGxvZyhtc2c6IHN0cmluZyk6IHZvaWQgfVxuICogY29uc3QgTG9nZ2VyVG9rZW4gPSBUb2tlbjxJTG9nZ2VyPignTG9nZ2VyJylcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gVG9rZW4oZGVzY3JpcHRpb24pIHtcbiAgICBjb25zdCBpZCA9ICsrdG9rZW5Db3VudGVyO1xuICAgIGNvbnN0IHN5bSA9IFN5bWJvbChkZXNjcmlwdGlvbiA/IGBUb2tlbigke2Rlc2NyaXB0aW9ufSlgIDogYFRva2VuIyR7aWR9YCk7XG4gICAgY29uc3QgdG9rZW4gPSB7XG4gICAgICAgIHN5bWJvbDogc3ltLFxuICAgICAgICBkZXNjcmlwdGlvbixcbiAgICAgICAgdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICByZXR1cm4gZGVzY3JpcHRpb25cbiAgICAgICAgICAgICAgICA/IGBUb2tlbjwke2Rlc2NyaXB0aW9ufT5gXG4gICAgICAgICAgICAgICAgOiBgVG9rZW48IyR7aWR9PmA7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiB0b2tlbjtcbn1cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyB1bmlxdWUgdG9rZW4gd2l0aG91dCBhIHN0cmluZyBsaXRlcmFsLlxuICogUHJlZmVycmVkIGZvciBBdXRvZmFjLXN0eWxlIERJIHRvIGF2b2lkIHN0cmluZyBsaXRlcmFscy5cbiAqXG4gKiBAcmV0dXJucyBBIHVuaXF1ZSB0b2tlbiB0aGF0IGNhbiBiZSB1c2VkIGFzIGEgTWFwIGtleVxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogaW50ZXJmYWNlIElMb2dnZXIgeyBsb2cobXNnOiBzdHJpbmcpOiB2b2lkIH1cbiAqIGNvbnN0IExvZ2dlclRva2VuID0gdG9rZW48SUxvZ2dlcj4oKVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b2tlbigpIHtcbiAgICByZXR1cm4gVG9rZW4oKTtcbn1cbiIsICIvKipcbiAqIEVycm9yIGNsYXNzZXMgZm9yIE5vdmFESSBjb250YWluZXJcbiAqL1xuZXhwb3J0IGNsYXNzIENvbnRhaW5lckVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKG1lc3NhZ2UpIHtcbiAgICAgICAgc3VwZXIobWVzc2FnZSk7XG4gICAgICAgIHRoaXMubmFtZSA9ICdDb250YWluZXJFcnJvcic7XG4gICAgfVxufVxuZXhwb3J0IGNsYXNzIEJpbmRpbmdOb3RGb3VuZEVycm9yIGV4dGVuZHMgQ29udGFpbmVyRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKHRva2VuRGVzY3JpcHRpb24sIHBhdGggPSBbXSkge1xuICAgICAgICBjb25zdCBwYXRoU3RyID0gcGF0aC5sZW5ndGggPiAwID8gYFxcbiAgRGVwZW5kZW5jeSBwYXRoOiAke3BhdGguam9pbignIC0+ICcpfWAgOiAnJztcbiAgICAgICAgc3VwZXIoYFRva2VuIFwiJHt0b2tlbkRlc2NyaXB0aW9ufVwiIGlzIG5vdCBib3VuZCBvciByZWdpc3RlcmVkIGluIHRoZSBjb250YWluZXIuJHtwYXRoU3RyfWApO1xuICAgICAgICB0aGlzLm5hbWUgPSAnQmluZGluZ05vdEZvdW5kRXJyb3InO1xuICAgIH1cbn1cbmV4cG9ydCBjbGFzcyBDaXJjdWxhckRlcGVuZGVuY3lFcnJvciBleHRlbmRzIENvbnRhaW5lckVycm9yIHtcbiAgICBjb25zdHJ1Y3RvcihwYXRoKSB7XG4gICAgICAgIHN1cGVyKGBDaXJjdWxhciBkZXBlbmRlbmN5IGRldGVjdGVkOiAke3BhdGguam9pbignIC0+ICcpfWApO1xuICAgICAgICB0aGlzLm5hbWUgPSAnQ2lyY3VsYXJEZXBlbmRlbmN5RXJyb3InO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIEF1dG9XaXJlIC0gQXV0b21hdGljIGRlcGVuZGVuY3kgaW5qZWN0aW9uIGZvciBOb3ZhRElcbiAqIFN1cHBvcnRzIHR3byBzdHJhdGVnaWVzOiBtYXBSZXNvbHZlcnMgKHRyYW5zZm9ybWVyLWdlbmVyYXRlZCkgYW5kIG1hcCAobWFudWFsIG92ZXJyaWRlKVxuICovXG4vKipcbiAqIFBlcmZvcm1hbmNlOiBDYWNoZSBleHRyYWN0ZWQgcGFyYW1ldGVyIG5hbWVzIHRvIGF2b2lkIHJlcGVhdGVkIHJlZ2V4IHBhcnNpbmdcbiAqIFdlYWtNYXAgYWxsb3dzIGdhcmJhZ2UgY29sbGVjdGlvbiB3aGVuIGNvbnN0cnVjdG9yIGlzIG5vIGxvbmdlciByZWZlcmVuY2VkXG4gKi9cbmNvbnN0IHBhcmFtTmFtZUNhY2hlID0gbmV3IFdlYWtNYXAoKTtcbi8qKlxuICogRXh0cmFjdCBwYXJhbWV0ZXIgbmFtZXMgZnJvbSBhIGNvbnN0cnVjdG9yIGZ1bmN0aW9uXG4gKiBVc2VzIHJlZ2V4IHRvIHBhcnNlIHRoZSB0b1N0cmluZygpIHJlcHJlc2VudGF0aW9uXG4gKiBQZXJmb3JtYW5jZSBvcHRpbWl6ZWQ6IFJlc3VsdHMgYXJlIGNhY2hlZCBwZXIgY29uc3RydWN0b3JcbiAqXG4gKiBOb3RlOiBPbmx5IHVzZWQgYnkgcmVzb2x2ZUJ5TWFwKCkgZm9yIG1hbnVhbCBtYXAgc3RyYXRlZ3lcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4dHJhY3RQYXJhbWV0ZXJOYW1lcyhjb25zdHJ1Y3Rvcikge1xuICAgIC8vIENoZWNrIGNhY2hlIGZpcnN0IC0gYXZvaWRzIGV4cGVuc2l2ZSByZWdleCBwYXJzaW5nXG4gICAgY29uc3QgY2FjaGVkID0gcGFyYW1OYW1lQ2FjaGUuZ2V0KGNvbnN0cnVjdG9yKTtcbiAgICBpZiAoY2FjaGVkKSB7XG4gICAgICAgIHJldHVybiBjYWNoZWQ7XG4gICAgfVxuICAgIC8vIEV4dHJhY3QgcGFyYW1ldGVyIG5hbWVzIChleHBlbnNpdmUgb3BlcmF0aW9uKVxuICAgIGNvbnN0IGZuU3RyID0gY29uc3RydWN0b3IudG9TdHJpbmcoKTtcbiAgICAvLyBNYXRjaCBjb25zdHJ1Y3RvciguLi5hcmdzKSBvciBjbGFzcyB7IGNvbnN0cnVjdG9yKC4uLmFyZ3MpIH1cbiAgICBjb25zdCBtYXRjaCA9IGZuU3RyLm1hdGNoKC9jb25zdHJ1Y3RvclxccypcXCgoW14pXSopXFwpLykgfHwgZm5TdHIubWF0Y2goL15bXihdKlxcKChbXildKilcXCkvKTtcbiAgICBpZiAoIW1hdGNoIHx8ICFtYXRjaFsxXSkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIGNvbnN0IHBhcmFtcyA9IG1hdGNoWzFdXG4gICAgICAgIC5zcGxpdCgnLCcpXG4gICAgICAgIC5tYXAocGFyYW0gPT4gcGFyYW0udHJpbSgpKVxuICAgICAgICAuZmlsdGVyKHBhcmFtID0+IHBhcmFtLmxlbmd0aCA+IDApXG4gICAgICAgIC5tYXAocGFyYW0gPT4ge1xuICAgICAgICAvLyBSZW1vdmUgZGVmYXVsdCB2YWx1ZXMsIHR5cGUgYW5ub3RhdGlvbnMsIGFuZCBleHRyYWN0IGp1c3QgdGhlIG5hbWVcbiAgICAgICAgbGV0IG5hbWUgPSBwYXJhbS5zcGxpdCgvWzo9XS8pWzBdLnRyaW0oKTtcbiAgICAgICAgLy8gUmVtb3ZlIFR5cGVTY3JpcHQgbW9kaWZpZXJzIChwdWJsaWMsIHByaXZhdGUsIHByb3RlY3RlZCwgcmVhZG9ubHkpXG4gICAgICAgIC8vIENhbiBhcHBlYXIgbXVsdGlwbGUgdGltZXMsIGUuZy4sIFwicHVibGljIHJlYWRvbmx5IHNlcnZpY2VcIlxuICAgICAgICBuYW1lID0gbmFtZS5yZXBsYWNlKC9eKChwdWJsaWN8cHJpdmF0ZXxwcm90ZWN0ZWR8cmVhZG9ubHkpXFxzKykrLywgJycpO1xuICAgICAgICAvLyBIYW5kbGUgZGVzdHJ1Y3R1cmluZyAtIHNraXAgZm9yIG5vd1xuICAgICAgICBpZiAobmFtZS5pbmNsdWRlcygneycpIHx8IG5hbWUuaW5jbHVkZXMoJ1snKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSlcbiAgICAgICAgLmZpbHRlcigobmFtZSkgPT4gbmFtZSAhPT0gbnVsbCk7XG4gICAgLy8gQ2FjaGUgcmVzdWx0IGZvciBmdXR1cmUgY2FsbHNcbiAgICBwYXJhbU5hbWVDYWNoZS5zZXQoY29uc3RydWN0b3IsIHBhcmFtcyk7XG4gICAgcmV0dXJuIHBhcmFtcztcbn1cbi8qKlxuICogUmVzb2x2ZSBkZXBlbmRlbmNpZXMgdXNpbmcgbWFwIHN0cmF0ZWd5XG4gKiBVc2VzIGV4cGxpY2l0IG1hcHBpbmcgZnJvbSBwYXJhbWV0ZXIgbmFtZXMgdG8gcmVzb2x2ZXJzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlQnlNYXAoY29uc3RydWN0b3IsIGNvbnRhaW5lciwgb3B0aW9ucykge1xuICAgIGlmICghb3B0aW9ucy5tYXApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdBdXRvV2lyZSBtYXAgc3RyYXRlZ3kgcmVxdWlyZXMgb3B0aW9ucy5tYXAgdG8gYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBjb25zdCBwYXJhbU5hbWVzID0gZXh0cmFjdFBhcmFtZXRlck5hbWVzKGNvbnN0cnVjdG9yKTtcbiAgICBjb25zdCByZXNvbHZlZERlcHMgPSBbXTtcbiAgICBmb3IgKGNvbnN0IHBhcmFtTmFtZSBvZiBwYXJhbU5hbWVzKSB7XG4gICAgICAgIGNvbnN0IHJlc29sdmVyID0gb3B0aW9ucy5tYXBbcGFyYW1OYW1lXTtcbiAgICAgICAgaWYgKHJlc29sdmVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLnN0cmljdCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlc29sdmUgcGFyYW1ldGVyIFwiJHtwYXJhbU5hbWV9XCIgb24gJHtjb25zdHJ1Y3Rvci5uYW1lfS4gYCArXG4gICAgICAgICAgICAgICAgICAgIGBOb3QgZm91bmQgaW4gYXV0b3dpcmUgbWFwLiBgICtcbiAgICAgICAgICAgICAgICAgICAgYEFkZCBpdCB0byB0aGUgbWFwOiAuYXV0b1dpcmUoeyBtYXA6IHsgJHtwYXJhbU5hbWV9OiAuLi4gfSB9KWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gU2lsZW50bHkgcHVzaCB1bmRlZmluZWQgZm9yIG1pc3NpbmcgcGFyYW1ldGVyc1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgZXhwZWN0ZWQ6IHRyYW5zZm9ybWVyIGZpbHRlcnMgb3V0IHByaW1pdGl2ZSB0eXBlcyBhdCBjb21waWxlLXRpbWUsXG4gICAgICAgICAgICAgICAgLy8gc28gbWlzc2luZyBwYXJhbXMgYXJlIHR5cGljYWxseSBwcmltaXRpdmVzIHRoYXQgZG9uJ3QgbmVlZCBESSByZXNvbHV0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZWREZXBzLnB1c2godW5kZWZpbmVkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIFJlc29sdmVyIGNhbiBiZSBhIGZ1bmN0aW9uIG9yIGEgVG9rZW5cbiAgICAgICAgaWYgKHR5cGVvZiByZXNvbHZlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmVzb2x2ZWREZXBzLnB1c2gocmVzb2x2ZXIoY29udGFpbmVyKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBBc3N1bWUgaXQncyBhIFRva2VuXG4gICAgICAgICAgICByZXNvbHZlZERlcHMucHVzaChjb250YWluZXIucmVzb2x2ZShyZXNvbHZlcikpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXNvbHZlZERlcHM7XG59XG4vKipcbiAqIFJlc29sdmUgZGVwZW5kZW5jaWVzIHVzaW5nIG1hcFJlc29sdmVycyBhcnJheSBzdHJhdGVneVxuICogT1BUSU1BTCBQRVJGT1JNQU5DRTogTygxKSBhcnJheSBhY2Nlc3MgcGVyIHBhcmFtZXRlclxuICogTWluaWZpY2F0aW9uLXNhZmU6IFVzZXMgcG9zaXRpb24tYmFzZWQgYXJyYXlcbiAqIFJlZmFjdG9yaW5nLWZyaWVuZGx5OiBUcmFuc2Zvcm1lciByZWdlbmVyYXRlcyBhcnJheSBvbiByZWNvbXBpbGVcbiAqXG4gKiBSZXF1aXJlcyBidWlsZC10aW1lIHRyYW5zZm9ybWVyIHRvIGdlbmVyYXRlIG1hcFJlc29sdmVycyBhcnJheVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZUJ5TWFwUmVzb2x2ZXJzKF9jb25zdHJ1Y3RvciwgY29udGFpbmVyLCBvcHRpb25zKSB7XG4gICAgaWYgKCFvcHRpb25zLm1hcFJlc29sdmVycyB8fCBvcHRpb25zLm1hcFJlc29sdmVycy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICBjb25zdCByZXNvbHZlZERlcHMgPSBbXTtcbiAgICAvLyBTaW1wbGUgTygxKSBhcnJheSBhY2Nlc3MgLSB1bHRyYSBmYXN0IVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3B0aW9ucy5tYXBSZXNvbHZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgcmVzb2x2ZXIgPSBvcHRpb25zLm1hcFJlc29sdmVyc1tpXTtcbiAgICAgICAgaWYgKHJlc29sdmVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIHVuZGVmaW5lZCBpbmRpY2F0ZXMgcHJpbWl0aXZlIHR5cGUgb3IgcGFyYW1ldGVyIHdpdGhvdXQgRElcbiAgICAgICAgICAgIHJlc29sdmVkRGVwcy5wdXNoKHVuZGVmaW5lZCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIHJlc29sdmVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAvLyBSZXNvbHZlciBmdW5jdGlvbjogKGMpID0+IGMucmVzb2x2ZVR5cGUoLi4uKVxuICAgICAgICAgICAgcmVzb2x2ZWREZXBzLnB1c2gocmVzb2x2ZXIoY29udGFpbmVyKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBUb2tlbi1iYXNlZCByZXNvbHV0aW9uXG4gICAgICAgICAgICByZXNvbHZlZERlcHMucHVzaChjb250YWluZXIucmVzb2x2ZShyZXNvbHZlcikpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXNvbHZlZERlcHM7XG59XG4vKipcbiAqIE1haW4gYXV0b3dpcmUgZnVuY3Rpb24gLSBkaXNwYXRjaGVzIHRvIGFwcHJvcHJpYXRlIHN0cmF0ZWd5XG4gKiBQcmlvcml0eTogbWFwUmVzb2x2ZXJzICh0cmFuc2Zvcm1lci1nZW5lcmF0ZWQpID4gbWFwIChtYW51YWwgb3ZlcnJpZGUpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhdXRvd2lyZShjb25zdHJ1Y3RvciwgY29udGFpbmVyLCBvcHRpb25zKSB7XG4gICAgY29uc3Qgb3B0cyA9IHtcbiAgICAgICAgYnk6ICdwYXJhbU5hbWUnLFxuICAgICAgICBzdHJpY3Q6IGZhbHNlLFxuICAgICAgICAuLi5vcHRpb25zXG4gICAgfTtcbiAgICAvLyBISUdIRVNUIFBSSU9SSVRZOiBtYXBSZXNvbHZlcnMgYXJyYXkgKHRyYW5zZm9ybWVyLWdlbmVyYXRlZCwgb3B0aW1hbCBwZXJmb3JtYW5jZSlcbiAgICAvLyBPKDEpIGFycmF5IGFjY2VzcyBwZXIgcGFyYW1ldGVyIC0gbWluaWZpY2F0aW9uLXNhZmUgYW5kIHJlZmFjdG9yaW5nLWZyaWVuZGx5XG4gICAgaWYgKG9wdHMubWFwUmVzb2x2ZXJzICYmIG9wdHMubWFwUmVzb2x2ZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcmV0dXJuIHJlc29sdmVCeU1hcFJlc29sdmVycyhjb25zdHJ1Y3RvciwgY29udGFpbmVyLCBvcHRzKTtcbiAgICB9XG4gICAgLy8gRkFMTEJBQ0s6IE1hbnVhbCBtYXAgc3RyYXRlZ3kgZm9yIGV4cGxpY2l0IG92ZXJyaWRlc1xuICAgIGlmIChvcHRzLm1hcCAmJiBPYmplY3Qua2V5cyhvcHRzLm1hcCkubGVuZ3RoID4gMCkge1xuICAgICAgICByZXR1cm4gcmVzb2x2ZUJ5TWFwKGNvbnN0cnVjdG9yLCBjb250YWluZXIsIG9wdHMpO1xuICAgIH1cbiAgICAvLyBObyBhdXRvd2lyaW5nIGNvbmZpZ3VyZWQsIHJldHVybiBlbXB0eSBhcnJheVxuICAgIHJldHVybiBbXTtcbn1cbiIsICIvKipcbiAqIEZsdWVudCBidWlsZGVyIEFQSSBmb3IgTm92YURJIENvbnRhaW5lciAoQXV0b2ZhYy1zdHlsZSlcbiAqL1xuaW1wb3J0IHsgVG9rZW4gfSBmcm9tICcuL3Rva2VuLmpzJztcbmltcG9ydCB7IGF1dG93aXJlIH0gZnJvbSAnLi9hdXRvd2lyZS5qcyc7XG4vKipcbiAqIEZsdWVudCByZWdpc3RyYXRpb24gYnVpbGRlciByZXR1cm5lZCBhZnRlciBlYWNoIHJlZ2lzdHJhdGlvbiBtZXRob2RcbiAqL1xuZXhwb3J0IGNsYXNzIFJlZ2lzdHJhdGlvbkJ1aWxkZXIge1xuICAgIGNvbnN0cnVjdG9yKHBlbmRpbmcsIHJlZ2lzdHJhdGlvbnMpIHtcbiAgICAgICAgdGhpcy5yZWdpc3RyYXRpb25zID0gcmVnaXN0cmF0aW9ucztcbiAgICAgICAgdGhpcy5jb25maWdzID0gW107XG4gICAgICAgIHRoaXMuZGVmYXVsdExpZmV0aW1lID0gJ3NpbmdsZXRvbic7XG4gICAgICAgIHRoaXMucGVuZGluZyA9IHBlbmRpbmc7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEJpbmQgdGhpcyByZWdpc3RyYXRpb24gdG8gYSB0b2tlbiBvciBpbnRlcmZhY2UgdHlwZVxuICAgICAqXG4gICAgICogQG92ZXJsb2FkXG4gICAgICogQHBhcmFtIHtUb2tlbjxVPn0gdG9rZW4gLSBFeHBsaWNpdCB0b2tlbiBmb3IgYmluZGluZ1xuICAgICAqXG4gICAgICogQG92ZXJsb2FkXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHR5cGVOYW1lIC0gSW50ZXJmYWNlIHR5cGUgbmFtZSAoYXV0by1nZW5lcmF0ZWQgYnkgdHJhbnNmb3JtZXIpXG4gICAgICovXG4gICAgYXModG9rZW5PclR5cGVOYW1lKSB7XG4gICAgICAgIC8vIENoZWNrIGlmIGFyZ3VtZW50IGlzIGEgVG9rZW4gb2JqZWN0IChoYXMgc3ltYm9sIHByb3BlcnR5KVxuICAgICAgICBpZiAodG9rZW5PclR5cGVOYW1lICYmIHR5cGVvZiB0b2tlbk9yVHlwZU5hbWUgPT09ICdvYmplY3QnICYmICdzeW1ib2wnIGluIHRva2VuT3JUeXBlTmFtZSkge1xuICAgICAgICAgICAgLy8gVG9rZW4tYmFzZWQgcmVnaXN0cmF0aW9uXG4gICAgICAgICAgICBjb25zdCBjb25maWcgPSB7XG4gICAgICAgICAgICAgICAgdG9rZW46IHRva2VuT3JUeXBlTmFtZSxcbiAgICAgICAgICAgICAgICB0eXBlOiB0aGlzLnBlbmRpbmcudHlwZSxcbiAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy5wZW5kaW5nLnZhbHVlLFxuICAgICAgICAgICAgICAgIGZhY3Rvcnk6IHRoaXMucGVuZGluZy5mYWN0b3J5LFxuICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yOiB0aGlzLnBlbmRpbmcuY29uc3RydWN0b3IsXG4gICAgICAgICAgICAgICAgbGlmZXRpbWU6IHRoaXMuZGVmYXVsdExpZmV0aW1lXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5jb25maWdzLnB1c2goY29uZmlnKTtcbiAgICAgICAgICAgIHRoaXMucmVnaXN0cmF0aW9ucy5wdXNoKGNvbmZpZyk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIEludGVyZmFjZS1iYXNlZCByZWdpc3RyYXRpb24gKHR5cGVOYW1lIHN0cmluZyBvciB1bmRlZmluZWQpXG4gICAgICAgICAgICBjb25zdCBjb25maWcgPSB7XG4gICAgICAgICAgICAgICAgdG9rZW46IG51bGwsIC8vIFdpbGwgYmUgc2V0IGR1cmluZyBidWlsZCgpXG4gICAgICAgICAgICAgICAgdHlwZTogdGhpcy5wZW5kaW5nLnR5cGUsXG4gICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMucGVuZGluZy52YWx1ZSxcbiAgICAgICAgICAgICAgICBmYWN0b3J5OiB0aGlzLnBlbmRpbmcuZmFjdG9yeSxcbiAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcjogdGhpcy5wZW5kaW5nLmNvbnN0cnVjdG9yLFxuICAgICAgICAgICAgICAgIGxpZmV0aW1lOiB0aGlzLmRlZmF1bHRMaWZldGltZSxcbiAgICAgICAgICAgICAgICBpbnRlcmZhY2VUeXBlOiB0b2tlbk9yVHlwZU5hbWVcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0aGlzLmNvbmZpZ3MucHVzaChjb25maWcpO1xuICAgICAgICAgICAgdGhpcy5yZWdpc3RyYXRpb25zLnB1c2goY29uZmlnKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVyIGFzIGRlZmF1bHQgaW1wbGVtZW50YXRpb24gZm9yIGFuIGludGVyZmFjZVxuICAgICAqIENvbWJpbmVzIGFzKCkgKyBhc0RlZmF1bHQoKVxuICAgICAqL1xuICAgIGFzRGVmYXVsdEludGVyZmFjZSh0eXBlTmFtZSkge1xuICAgICAgICB0aGlzLmFzKFwiVEludGVyZmFjZVwiLCB0eXBlTmFtZSk7XG4gICAgICAgIHJldHVybiB0aGlzLmFzRGVmYXVsdCgpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlciBhcyBhIGtleWVkIGludGVyZmFjZSBpbXBsZW1lbnRhdGlvblxuICAgICAqIENvbWJpbmVzIGFzKCkgKyBrZXllZCgpXG4gICAgICovXG4gICAgYXNLZXllZEludGVyZmFjZShrZXksIHR5cGVOYW1lKSB7XG4gICAgICAgIHRoaXMuYXMoXCJUSW50ZXJmYWNlXCIsIHR5cGVOYW1lKTtcbiAgICAgICAgcmV0dXJuIHRoaXMua2V5ZWQoa2V5KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgYXMgbXVsdGlwbGUgaW1wbGVtZW50ZWQgaW50ZXJmYWNlc1xuICAgICAqL1xuICAgIGFzSW1wbGVtZW50ZWRJbnRlcmZhY2VzKHRva2Vucykge1xuICAgICAgICBpZiAodG9rZW5zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGV4aXN0aW5nIGNvbmZpZ3MgKGZyb20gcHJldmlvdXMgYXMoKSBjYWxscyksIGFkZCB0aGVzZSBhcyBhZGRpdGlvbmFsIGludGVyZmFjZXNcbiAgICAgICAgaWYgKHRoaXMuY29uZmlncy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAvLyBBZGQgYWxsIHRva2VucyBhcyBhZGRpdGlvbmFsIGludGVyZmFjZXMgdG8gZXhpc3RpbmcgY29uZmlnc1xuICAgICAgICAgICAgZm9yIChjb25zdCBjb25maWcgb2YgdGhpcy5jb25maWdzKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLmxpZmV0aW1lID0gJ3NpbmdsZXRvbic7IC8vIGFzSW1wbGVtZW50ZWRJbnRlcmZhY2VzIGRlZmF1bHRzIHRvIHNpbmdsZXRvblxuICAgICAgICAgICAgICAgIGNvbmZpZy5hZGRpdGlvbmFsVG9rZW5zID0gY29uZmlnLmFkZGl0aW9uYWxUb2tlbnMgfHwgW107XG4gICAgICAgICAgICAgICAgY29uZmlnLmFkZGl0aW9uYWxUb2tlbnMucHVzaCguLi50b2tlbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTm8gZXhpc3RpbmcgY29uZmlncywgY3JlYXRlIG5ldyBvbmUgd2l0aCBmaXJzdCB0b2tlblxuICAgICAgICBjb25zdCBmaXJzdENvbmZpZyA9IHtcbiAgICAgICAgICAgIHRva2VuOiB0b2tlbnNbMF0sXG4gICAgICAgICAgICB0eXBlOiB0aGlzLnBlbmRpbmcudHlwZSxcbiAgICAgICAgICAgIHZhbHVlOiB0aGlzLnBlbmRpbmcudmFsdWUsXG4gICAgICAgICAgICBmYWN0b3J5OiB0aGlzLnBlbmRpbmcuZmFjdG9yeSxcbiAgICAgICAgICAgIGNvbnN0cnVjdG9yOiB0aGlzLnBlbmRpbmcuY29uc3RydWN0b3IsXG4gICAgICAgICAgICBsaWZldGltZTogJ3NpbmdsZXRvbidcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5jb25maWdzLnB1c2goZmlyc3RDb25maWcpO1xuICAgICAgICB0aGlzLnJlZ2lzdHJhdGlvbnMucHVzaChmaXJzdENvbmZpZyk7XG4gICAgICAgIC8vIEFkZGl0aW9uYWwgdG9rZW5zIHJlZmVyZW5jZSB0aGUgc2FtZSByZWdpc3RyYXRpb25cbiAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCB0b2tlbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGZpcnN0Q29uZmlnLmFkZGl0aW9uYWxUb2tlbnMgPSBmaXJzdENvbmZpZy5hZGRpdGlvbmFsVG9rZW5zIHx8IFtdO1xuICAgICAgICAgICAgZmlyc3RDb25maWcuYWRkaXRpb25hbFRva2Vucy5wdXNoKHRva2Vuc1tpXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNldCBzaW5nbGV0b24gbGlmZXRpbWUgKG9uZSBpbnN0YW5jZSBmb3IgZW50aXJlIGNvbnRhaW5lcilcbiAgICAgKi9cbiAgICBzaW5nbGVJbnN0YW5jZSgpIHtcbiAgICAgICAgZm9yIChjb25zdCBjb25maWcgb2YgdGhpcy5jb25maWdzKSB7XG4gICAgICAgICAgICBjb25maWcubGlmZXRpbWUgPSAnc2luZ2xldG9uJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2V0IHBlci1yZXF1ZXN0IGxpZmV0aW1lIChvbmUgaW5zdGFuY2UgcGVyIHJlc29sdmUgY2FsbCB0cmVlKVxuICAgICAqL1xuICAgIGluc3RhbmNlUGVyUmVxdWVzdCgpIHtcbiAgICAgICAgZm9yIChjb25zdCBjb25maWcgb2YgdGhpcy5jb25maWdzKSB7XG4gICAgICAgICAgICBjb25maWcubGlmZXRpbWUgPSAncGVyLXJlcXVlc3QnO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZXQgdHJhbnNpZW50IGxpZmV0aW1lIChuZXcgaW5zdGFuY2UgZXZlcnkgdGltZSlcbiAgICAgKiBBbGlhcyBmb3IgZGVmYXVsdCBiZWhhdmlvclxuICAgICAqL1xuICAgIGluc3RhbmNlUGVyRGVwZW5kZW5jeSgpIHtcbiAgICAgICAgZm9yIChjb25zdCBjb25maWcgb2YgdGhpcy5jb25maWdzKSB7XG4gICAgICAgICAgICBjb25maWcubGlmZXRpbWUgPSAndHJhbnNpZW50JztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogTmFtZSB0aGlzIHJlZ2lzdHJhdGlvbiBmb3IgbmFtZWQgcmVzb2x1dGlvblxuICAgICAqL1xuICAgIG5hbWVkKG5hbWUpIHtcbiAgICAgICAgZm9yIChjb25zdCBjb25maWcgb2YgdGhpcy5jb25maWdzKSB7XG4gICAgICAgICAgICBjb25maWcubmFtZSA9IG5hbWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEtleSB0aGlzIHJlZ2lzdHJhdGlvbiBmb3Iga2V5ZWQgcmVzb2x1dGlvblxuICAgICAqL1xuICAgIGtleWVkKGtleSkge1xuICAgICAgICBmb3IgKGNvbnN0IGNvbmZpZyBvZiB0aGlzLmNvbmZpZ3MpIHtcbiAgICAgICAgICAgIGNvbmZpZy5rZXkgPSBrZXk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIE1hcmsgdGhpcyBhcyBkZWZhdWx0IHJlZ2lzdHJhdGlvblxuICAgICAqIERlZmF1bHQgcmVnaXN0cmF0aW9ucyBkb24ndCBvdmVycmlkZSBleGlzdGluZyBvbmVzXG4gICAgICovXG4gICAgYXNEZWZhdWx0KCkge1xuICAgICAgICBmb3IgKGNvbnN0IGNvbmZpZyBvZiB0aGlzLmNvbmZpZ3MpIHtcbiAgICAgICAgICAgIGNvbmZpZy5pc0RlZmF1bHQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBPbmx5IHJlZ2lzdGVyIGlmIHRva2VuIG5vdCBhbHJlYWR5IHJlZ2lzdGVyZWRcbiAgICAgKi9cbiAgICBpZk5vdFJlZ2lzdGVyZWQoKSB7XG4gICAgICAgIGZvciAoY29uc3QgY29uZmlnIG9mIHRoaXMuY29uZmlncykge1xuICAgICAgICAgICAgY29uZmlnLmlmTm90UmVnaXN0ZXJlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNwZWNpZnkgcGFyYW1ldGVyIHZhbHVlcyBmb3IgY29uc3RydWN0b3IgKHByaW1pdGl2ZXMgYW5kIGNvbnN0YW50cylcbiAgICAgKiBVc2UgdGhpcyBmb3Igbm9uLURJIHBhcmFtZXRlcnMgbGlrZSBzdHJpbmdzLCBudW1iZXJzLCBjb25maWcgdmFsdWVzXG4gICAgICovXG4gICAgd2l0aFBhcmFtZXRlcnMocGFyYW1ldGVycykge1xuICAgICAgICBmb3IgKGNvbnN0IGNvbmZpZyBvZiB0aGlzLmNvbmZpZ3MpIHtcbiAgICAgICAgICAgIGNvbmZpZy5wYXJhbWV0ZXJWYWx1ZXMgPSBwYXJhbWV0ZXJzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBFbmFibGUgYXV0b21hdGljIGRlcGVuZGVuY3kgaW5qZWN0aW9uIChhdXRvd2lyaW5nKVxuICAgICAqIFN1cHBvcnRzIHRocmVlIHN0cmF0ZWdpZXM6IHBhcmFtTmFtZSAoZGVmYXVsdCksIG1hcCwgYW5kIGNsYXNzXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYHRzXG4gICAgICogLy8gU3RyYXRlZ3kgMTogcGFyYW1OYW1lIChkZWZhdWx0LCByZXF1aXJlcyBub24tbWluaWZpZWQgY29kZSBpbiBkZXYpXG4gICAgICogYnVpbGRlci5yZWdpc3RlclR5cGUoRXZlbnRCdXMpLmFzPElFdmVudEJ1cz4oKS5hdXRvV2lyZSgpXG4gICAgICpcbiAgICAgKiAvLyBTdHJhdGVneSAyOiBtYXAgKG1pbmlmeS1zYWZlLCBleHBsaWNpdClcbiAgICAgKiBidWlsZGVyLnJlZ2lzdGVyVHlwZShFdmVudEJ1cykuYXM8SUV2ZW50QnVzPigpLmF1dG9XaXJlKHtcbiAgICAgKiAgIG1hcDoge1xuICAgICAqICAgICBsb2dnZXI6IChjKSA9PiBjLnJlc29sdmVUeXBlPElMb2dnZXI+KClcbiAgICAgKiAgIH1cbiAgICAgKiB9KVxuICAgICAqXG4gICAgICogLy8gU3RyYXRlZ3kgMzogY2xhc3MgKHJlcXVpcmVzIGJ1aWxkLXRpbWUgY29kZWdlbilcbiAgICAgKiBidWlsZGVyLnJlZ2lzdGVyVHlwZShFdmVudEJ1cykuYXM8SUV2ZW50QnVzPigpLmF1dG9XaXJlKHsgYnk6ICdjbGFzcycgfSlcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhdXRvV2lyZShvcHRpb25zKSB7XG4gICAgICAgIGZvciAoY29uc3QgY29uZmlnIG9mIHRoaXMuY29uZmlncykge1xuICAgICAgICAgICAgY29uZmlnLmF1dG93aXJlT3B0aW9ucyA9IG9wdGlvbnMgfHwgeyBieTogJ3BhcmFtTmFtZScsIHN0cmljdDogZmFsc2UgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG59XG4vKipcbiAqIEZsdWVudCBidWlsZGVyIGZvciBDb250YWluZXIgY29uZmlndXJhdGlvblxuICovXG5leHBvcnQgY2xhc3MgQnVpbGRlciB7XG4gICAgY29uc3RydWN0b3IoYmFzZUNvbnRhaW5lcikge1xuICAgICAgICB0aGlzLmJhc2VDb250YWluZXIgPSBiYXNlQ29udGFpbmVyO1xuICAgICAgICB0aGlzLnJlZ2lzdHJhdGlvbnMgPSBbXTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgYSBjbGFzcyBjb25zdHJ1Y3RvclxuICAgICAqL1xuICAgIHJlZ2lzdGVyVHlwZShjb25zdHJ1Y3Rvcikge1xuICAgICAgICBjb25zdCBwZW5kaW5nID0ge1xuICAgICAgICAgICAgdHlwZTogJ3R5cGUnLFxuICAgICAgICAgICAgdmFsdWU6IG51bGwsXG4gICAgICAgICAgICBjb25zdHJ1Y3RvclxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gbmV3IFJlZ2lzdHJhdGlvbkJ1aWxkZXIocGVuZGluZywgdGhpcy5yZWdpc3RyYXRpb25zKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgYSBwcmUtY3JlYXRlZCBpbnN0YW5jZVxuICAgICAqL1xuICAgIHJlZ2lzdGVySW5zdGFuY2UoaW5zdGFuY2UpIHtcbiAgICAgICAgY29uc3QgcGVuZGluZyA9IHtcbiAgICAgICAgICAgIHR5cGU6ICdpbnN0YW5jZScsXG4gICAgICAgICAgICB2YWx1ZTogaW5zdGFuY2UsXG4gICAgICAgICAgICBjb25zdHJ1Y3RvcjogdW5kZWZpbmVkXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBuZXcgUmVnaXN0cmF0aW9uQnVpbGRlcihwZW5kaW5nLCB0aGlzLnJlZ2lzdHJhdGlvbnMpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlciBhIGZhY3RvcnkgZnVuY3Rpb25cbiAgICAgKi9cbiAgICByZWdpc3RlcihmYWN0b3J5KSB7XG4gICAgICAgIGNvbnN0IHBlbmRpbmcgPSB7XG4gICAgICAgICAgICB0eXBlOiAnZmFjdG9yeScsXG4gICAgICAgICAgICB2YWx1ZTogbnVsbCxcbiAgICAgICAgICAgIGZhY3RvcnksXG4gICAgICAgICAgICBjb25zdHJ1Y3RvcjogdW5kZWZpbmVkXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBuZXcgUmVnaXN0cmF0aW9uQnVpbGRlcihwZW5kaW5nLCB0aGlzLnJlZ2lzdHJhdGlvbnMpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlciBhIG1vZHVsZSAoZnVuY3Rpb24gdGhhdCBhZGRzIG11bHRpcGxlIHJlZ2lzdHJhdGlvbnMpXG4gICAgICovXG4gICAgbW9kdWxlKG1vZHVsZUZ1bmMpIHtcbiAgICAgICAgbW9kdWxlRnVuYyh0aGlzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlc29sdmUgaW50ZXJmYWNlIHR5cGUgbmFtZXMgdG8gdG9rZW5zXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgcmVzb2x2ZUludGVyZmFjZVRva2Vucyhjb250YWluZXIpIHtcbiAgICAgICAgZm9yIChjb25zdCBjb25maWcgb2YgdGhpcy5yZWdpc3RyYXRpb25zKSB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLmludGVyZmFjZVR5cGUgIT09IHVuZGVmaW5lZCAmJiAhY29uZmlnLnRva2VuKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLnRva2VuID0gY29udGFpbmVyLmludGVyZmFjZVRva2VuKGNvbmZpZy5pbnRlcmZhY2VUeXBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBJZGVudGlmeSB0b2tlbnMgdGhhdCBoYXZlIG5vbi1kZWZhdWx0IHJlZ2lzdHJhdGlvbnNcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBpZGVudGlmeU5vbkRlZmF1bHRUb2tlbnMoKSB7XG4gICAgICAgIGNvbnN0IHRva2Vuc1dpdGhOb25EZWZhdWx0cyA9IG5ldyBTZXQoKTtcbiAgICAgICAgZm9yIChjb25zdCBjb25maWcgb2YgdGhpcy5yZWdpc3RyYXRpb25zKSB7XG4gICAgICAgICAgICBpZiAoIWNvbmZpZy5pc0RlZmF1bHQgJiYgIWNvbmZpZy5uYW1lICYmIGNvbmZpZy5rZXkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRva2Vuc1dpdGhOb25EZWZhdWx0cy5hZGQoY29uZmlnLnRva2VuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdG9rZW5zV2l0aE5vbkRlZmF1bHRzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiByZWdpc3RyYXRpb24gc2hvdWxkIGJlIHNraXBwZWRcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBzaG91bGRTa2lwUmVnaXN0cmF0aW9uKGNvbmZpZywgdG9rZW5zV2l0aE5vbkRlZmF1bHRzLCByZWdpc3RlcmVkVG9rZW5zKSB7XG4gICAgICAgIC8vIFNraXAgZGVmYXVsdCByZWdpc3RyYXRpb25zIGlmIHRoZXJlJ3MgYSBub24tZGVmYXVsdCBmb3IgdGhlIHNhbWUgdG9rZW5cbiAgICAgICAgaWYgKGNvbmZpZy5pc0RlZmF1bHQgJiYgIWNvbmZpZy5uYW1lICYmIGNvbmZpZy5rZXkgPT09IHVuZGVmaW5lZCAmJiB0b2tlbnNXaXRoTm9uRGVmYXVsdHMuaGFzKGNvbmZpZy50b2tlbikpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIEhhbmRsZSBpZk5vdFJlZ2lzdGVyZWRcbiAgICAgICAgaWYgKGNvbmZpZy5pZk5vdFJlZ2lzdGVyZWQgJiYgcmVnaXN0ZXJlZFRva2Vucy5oYXMoY29uZmlnLnRva2VuKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gSGFuZGxlIGFzRGVmYXVsdFxuICAgICAgICBpZiAoY29uZmlnLmlzRGVmYXVsdCAmJiByZWdpc3RlcmVkVG9rZW5zLmhhcyhjb25maWcudG9rZW4pKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBiaW5kaW5nIHRva2VuIGZvciByZWdpc3RyYXRpb24gKG5hbWVkLCBrZXllZCwgb3IgbXVsdGkpXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgY3JlYXRlQmluZGluZ1Rva2VuKGNvbmZpZywgbmFtZWRSZWdpc3RyYXRpb25zLCBrZXllZFJlZ2lzdHJhdGlvbnMsIG11bHRpUmVnaXN0cmF0aW9ucykge1xuICAgICAgICBpZiAoY29uZmlnLm5hbWUpIHtcbiAgICAgICAgICAgIC8vIE5hbWVkIHJlZ2lzdHJhdGlvbiBnZXRzIHVuaXF1ZSB0b2tlblxuICAgICAgICAgICAgY29uc3QgYmluZGluZ1Rva2VuID0gVG9rZW4oYF9fbmFtZWRfJHtjb25maWcubmFtZX1gKTtcbiAgICAgICAgICAgIG5hbWVkUmVnaXN0cmF0aW9ucy5zZXQoY29uZmlnLm5hbWUsIHsgLi4uY29uZmlnLCB0b2tlbjogYmluZGluZ1Rva2VuIH0pO1xuICAgICAgICAgICAgcmV0dXJuIGJpbmRpbmdUb2tlbjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChjb25maWcua2V5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIEtleWVkIHJlZ2lzdHJhdGlvbiBnZXRzIHVuaXF1ZSB0b2tlblxuICAgICAgICAgICAgY29uc3Qga2V5U3RyID0gdHlwZW9mIGNvbmZpZy5rZXkgPT09ICdzeW1ib2wnID8gY29uZmlnLmtleS50b1N0cmluZygpIDogY29uZmlnLmtleTtcbiAgICAgICAgICAgIGNvbnN0IGJpbmRpbmdUb2tlbiA9IFRva2VuKGBfX2tleWVkXyR7a2V5U3RyfWApO1xuICAgICAgICAgICAga2V5ZWRSZWdpc3RyYXRpb25zLnNldChjb25maWcua2V5LCB7IC4uLmNvbmZpZywgdG9rZW46IGJpbmRpbmdUb2tlbiB9KTtcbiAgICAgICAgICAgIHJldHVybiBiaW5kaW5nVG9rZW47XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBNdWx0aS1yZWdpc3RyYXRpb24gaGFuZGxpbmdcbiAgICAgICAgICAgIGlmIChtdWx0aVJlZ2lzdHJhdGlvbnMuaGFzKGNvbmZpZy50b2tlbikpIHtcbiAgICAgICAgICAgICAgICAvLyBTdWJzZXF1ZW50IHJlZ2lzdHJhdGlvbiBmb3IgdGhpcyB0b2tlblxuICAgICAgICAgICAgICAgIGNvbnN0IGJpbmRpbmdUb2tlbiA9IFRva2VuKGBfX211bHRpXyR7Y29uZmlnLnRva2VuLnRvU3RyaW5nKCl9XyR7bXVsdGlSZWdpc3RyYXRpb25zLmdldChjb25maWcudG9rZW4pLmxlbmd0aH1gKTtcbiAgICAgICAgICAgICAgICBtdWx0aVJlZ2lzdHJhdGlvbnMuZ2V0KGNvbmZpZy50b2tlbikucHVzaChiaW5kaW5nVG9rZW4pO1xuICAgICAgICAgICAgICAgIHJldHVybiBiaW5kaW5nVG9rZW47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBGaXJzdCByZWdpc3RyYXRpb24gZm9yIHRoaXMgdG9rZW4sIHVzZSB0aGUgb3JpZ2luYWwgdG9rZW5cbiAgICAgICAgICAgICAgICBtdWx0aVJlZ2lzdHJhdGlvbnMuc2V0KGNvbmZpZy50b2tlbiwgW2NvbmZpZy50b2tlbl0pO1xuICAgICAgICAgICAgICAgIHJldHVybiBjb25maWcudG9rZW47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgYWRkaXRpb25hbCBpbnRlcmZhY2VzIGZvciBhIGNvbmZpZ1xuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIHJlZ2lzdGVyQWRkaXRpb25hbEludGVyZmFjZXMoY29udGFpbmVyLCBjb25maWcsIGJpbmRpbmdUb2tlbiwgcmVnaXN0ZXJlZFRva2Vucykge1xuICAgICAgICBpZiAoY29uZmlnLmFkZGl0aW9uYWxUb2tlbnMpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgYWRkaXRpb25hbFRva2VuIG9mIGNvbmZpZy5hZGRpdGlvbmFsVG9rZW5zKSB7XG4gICAgICAgICAgICAgICAgLy8gQ3JlYXRlIGEgZmFjdG9yeSB0aGF0IHJlc29sdmVzIHRoZSBiaW5kaW5nIHRva2VuXG4gICAgICAgICAgICAgICAgY29udGFpbmVyLmJpbmRGYWN0b3J5KGFkZGl0aW9uYWxUb2tlbiwgKGMpID0+IGMucmVzb2x2ZShiaW5kaW5nVG9rZW4pLCB7IGxpZmV0aW1lOiBjb25maWcubGlmZXRpbWUgfSk7XG4gICAgICAgICAgICAgICAgcmVnaXN0ZXJlZFRva2Vucy5hZGQoYWRkaXRpb25hbFRva2VuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBCdWlsZCB0aGUgY29udGFpbmVyIHdpdGggYWxsIHJlZ2lzdGVyZWQgYmluZGluZ3NcbiAgICAgKi9cbiAgICBidWlsZCgpIHtcbiAgICAgICAgLy8gQ3JlYXRlIG5ldyBjb250YWluZXIgaW5oZXJpdGluZyBmcm9tIGJhc2VcbiAgICAgICAgY29uc3QgY29udGFpbmVyID0gdGhpcy5iYXNlQ29udGFpbmVyLmNyZWF0ZUNoaWxkKCk7XG4gICAgICAgIC8vIFByZS1wcm9jZXNzOiByZXNvbHZlIGludGVyZmFjZSB0eXBlcyB0byB0b2tlbnNcbiAgICAgICAgdGhpcy5yZXNvbHZlSW50ZXJmYWNlVG9rZW5zKGNvbnRhaW5lcik7XG4gICAgICAgIC8vIFRyYWNrIHdoYXQncyBiZWVuIHJlZ2lzdGVyZWQgZm9yIGlmTm90UmVnaXN0ZXJlZCBjaGVja3NcbiAgICAgICAgY29uc3QgcmVnaXN0ZXJlZFRva2VucyA9IG5ldyBTZXQoKTtcbiAgICAgICAgY29uc3QgbmFtZWRSZWdpc3RyYXRpb25zID0gbmV3IE1hcCgpO1xuICAgICAgICBjb25zdCBrZXllZFJlZ2lzdHJhdGlvbnMgPSBuZXcgTWFwKCk7XG4gICAgICAgIGNvbnN0IG11bHRpUmVnaXN0cmF0aW9ucyA9IG5ldyBNYXAoKTtcbiAgICAgICAgLy8gUHJlLXByb2Nlc3M6IGlkZW50aWZ5IHRva2VucyB0aGF0IGhhdmUgbm9uLWRlZmF1bHQgcmVnaXN0cmF0aW9uc1xuICAgICAgICBjb25zdCB0b2tlbnNXaXRoTm9uRGVmYXVsdHMgPSB0aGlzLmlkZW50aWZ5Tm9uRGVmYXVsdFRva2VucygpO1xuICAgICAgICBmb3IgKGNvbnN0IGNvbmZpZyBvZiB0aGlzLnJlZ2lzdHJhdGlvbnMpIHtcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHJlZ2lzdHJhdGlvbiBzaG91bGQgYmUgc2tpcHBlZFxuICAgICAgICAgICAgaWYgKHRoaXMuc2hvdWxkU2tpcFJlZ2lzdHJhdGlvbihjb25maWcsIHRva2Vuc1dpdGhOb25EZWZhdWx0cywgcmVnaXN0ZXJlZFRva2VucykpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIENyZWF0ZSBiaW5kaW5nIHRva2VuIChuYW1lZCwga2V5ZWQsIG9yIG11bHRpKVxuICAgICAgICAgICAgY29uc3QgYmluZGluZ1Rva2VuID0gdGhpcy5jcmVhdGVCaW5kaW5nVG9rZW4oY29uZmlnLCBuYW1lZFJlZ2lzdHJhdGlvbnMsIGtleWVkUmVnaXN0cmF0aW9ucywgbXVsdGlSZWdpc3RyYXRpb25zKTtcbiAgICAgICAgICAgIC8vIEFwcGx5IHJlZ2lzdHJhdGlvbiB0byBjb250YWluZXIgdXNpbmcgdGhlIGJpbmRpbmcgdG9rZW5cbiAgICAgICAgICAgIHRoaXMuYXBwbHlSZWdpc3RyYXRpb24oY29udGFpbmVyLCB7IC4uLmNvbmZpZywgdG9rZW46IGJpbmRpbmdUb2tlbiB9KTtcbiAgICAgICAgICAgIC8vIE1hcmsgb3JpZ2luYWwgdG9rZW4gYXMgcmVnaXN0ZXJlZFxuICAgICAgICAgICAgcmVnaXN0ZXJlZFRva2Vucy5hZGQoY29uZmlnLnRva2VuKTtcbiAgICAgICAgICAgIC8vIFJlZ2lzdGVyIGFkZGl0aW9uYWwgaW50ZXJmYWNlc1xuICAgICAgICAgICAgdGhpcy5yZWdpc3RlckFkZGl0aW9uYWxJbnRlcmZhY2VzKGNvbnRhaW5lciwgY29uZmlnLCBiaW5kaW5nVG9rZW4sIHJlZ2lzdGVyZWRUb2tlbnMpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEF0dGFjaCBtZXRhZGF0YSBmb3IgbmFtZWQva2V5ZWQgcmVzb2x1dGlvblxuICAgICAgICA7XG4gICAgICAgIGNvbnRhaW5lci5fX25hbWVkUmVnaXN0cmF0aW9ucyA9IG5hbWVkUmVnaXN0cmF0aW9ucztcbiAgICAgICAgY29udGFpbmVyLl9fa2V5ZWRSZWdpc3RyYXRpb25zID0ga2V5ZWRSZWdpc3RyYXRpb25zO1xuICAgICAgICBjb250YWluZXIuX19tdWx0aVJlZ2lzdHJhdGlvbnMgPSBtdWx0aVJlZ2lzdHJhdGlvbnM7XG4gICAgICAgIHJldHVybiBjb250YWluZXI7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFuYWx5emUgY29uc3RydWN0b3IgdG8gZGV0ZWN0IGRlcGVuZGVuY2llc1xuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGFuYWx5emVDb25zdHJ1Y3Rvcihjb25zdHJ1Y3Rvcikge1xuICAgICAgICBjb25zdCBjb25zdHJ1Y3RvclN0ciA9IGNvbnN0cnVjdG9yLnRvU3RyaW5nKCk7XG4gICAgICAgIGNvbnN0IGhhc0RlcGVuZGVuY2llcyA9IC9jb25zdHJ1Y3RvclxccypcXChbXildK1xcKS8udGVzdChjb25zdHJ1Y3RvclN0cik7XG4gICAgICAgIHJldHVybiB7IGhhc0RlcGVuZGVuY2llcyB9O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgb3B0aW1pemVkIGZhY3RvcnkgZm9yIHplcm8tZGVwZW5kZW5jeSBjb25zdHJ1Y3RvcnNcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBjcmVhdGVPcHRpbWl6ZWRGYWN0b3J5KGNvbnRhaW5lciwgY29uZmlnLCBvcHRpb25zKSB7XG4gICAgICAgIGlmIChjb25maWcubGlmZXRpbWUgPT09ICdzaW5nbGV0b24nKSB7XG4gICAgICAgICAgICAvLyBTaW5nbGV0b246IENyZWF0ZSBpbnN0YW5jZSBkaXJlY3RseSAoZmFzdGVzdCBwYXRoIC0gbm8gZmFjdG9yeSBvdmVyaGVhZClcbiAgICAgICAgICAgIGNvbnN0IGluc3RhbmNlID0gbmV3IGNvbmZpZy5jb25zdHJ1Y3RvcigpO1xuICAgICAgICAgICAgY29udGFpbmVyLmJpbmRWYWx1ZShjb25maWcudG9rZW4sIGluc3RhbmNlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChjb25maWcubGlmZXRpbWUgPT09ICd0cmFuc2llbnQnKSB7XG4gICAgICAgICAgICAvLyBUcmFuc2llbnQgRmFzdCBQYXRoOiBSZWdpc3RlciBpbiBmYXN0IHRyYW5zaWVudCBjYWNoZVxuICAgICAgICAgICAgY29uc3QgY3RvciA9IGNvbmZpZy5jb25zdHJ1Y3RvcjtcbiAgICAgICAgICAgIGNvbnN0IGZhc3RGYWN0b3J5ID0gKCkgPT4gbmV3IGN0b3IoKTtcbiAgICAgICAgICAgIGNvbnRhaW5lci5mYXN0VHJhbnNpZW50Q2FjaGUuc2V0KGNvbmZpZy50b2tlbiwgZmFzdEZhY3RvcnkpO1xuICAgICAgICAgICAgY29udGFpbmVyLmJpbmRGYWN0b3J5KGNvbmZpZy50b2tlbiwgZmFzdEZhY3RvcnksIG9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gUGVyLXJlcXVlc3Q6IFVzZSBzaW1wbGUgZmFjdG9yeSB3aXRob3V0IGF1dG93aXJlIG92ZXJoZWFkXG4gICAgICAgICAgICBjb25zdCBmYWN0b3J5ID0gKCkgPT4gbmV3IGNvbmZpZy5jb25zdHJ1Y3RvcigpO1xuICAgICAgICAgICAgY29udGFpbmVyLmJpbmRGYWN0b3J5KGNvbmZpZy50b2tlbiwgZmFjdG9yeSwgb3B0aW9ucyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGF1dG93aXJlIGZhY3RvcnlcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBjcmVhdGVBdXRvV2lyZUZhY3RvcnkoY29udGFpbmVyLCBjb25maWcsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgZmFjdG9yeSA9IChjKSA9PiB7XG4gICAgICAgICAgICBjb25zdCByZXNvbHZlZERlcHMgPSBhdXRvd2lyZShjb25maWcuY29uc3RydWN0b3IsIGMsIGNvbmZpZy5hdXRvd2lyZU9wdGlvbnMpO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBjb25maWcuY29uc3RydWN0b3IoLi4ucmVzb2x2ZWREZXBzKTtcbiAgICAgICAgfTtcbiAgICAgICAgY29udGFpbmVyLmJpbmRGYWN0b3J5KGNvbmZpZy50b2tlbiwgZmFjdG9yeSwgb3B0aW9ucyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENyZWF0ZSB3aXRoUGFyYW1ldGVycyBmYWN0b3J5XG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgY3JlYXRlUGFyYW1ldGVyRmFjdG9yeShjb250YWluZXIsIGNvbmZpZywgb3B0aW9ucykge1xuICAgICAgICBjb25zdCBmYWN0b3J5ID0gKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdmFsdWVzID0gT2JqZWN0LnZhbHVlcyhjb25maWcucGFyYW1ldGVyVmFsdWVzKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgY29uZmlnLmNvbnN0cnVjdG9yKC4uLnZhbHVlcyk7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnRhaW5lci5iaW5kRmFjdG9yeShjb25maWcudG9rZW4sIGZhY3RvcnksIG9wdGlvbnMpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBcHBseSB0eXBlIHJlZ2lzdHJhdGlvbiAoY2xhc3MgY29uc3RydWN0b3IpXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgYXBwbHlUeXBlUmVnaXN0cmF0aW9uKGNvbnRhaW5lciwgY29uZmlnLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IHsgaGFzRGVwZW5kZW5jaWVzIH0gPSB0aGlzLmFuYWx5emVDb25zdHJ1Y3Rvcihjb25maWcuY29uc3RydWN0b3IpO1xuICAgICAgICAvLyBGYXN0IHBhdGg6IE5vIGRlcGVuZGVuY2llcyBhbmQgbm8gc3BlY2lhbCBjb25maWdcbiAgICAgICAgaWYgKCFoYXNEZXBlbmRlbmNpZXMgJiYgIWNvbmZpZy5hdXRvd2lyZU9wdGlvbnMgJiYgIWNvbmZpZy5wYXJhbWV0ZXJWYWx1ZXMpIHtcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlT3B0aW1pemVkRmFjdG9yeShjb250YWluZXIsIGNvbmZpZywgb3B0aW9ucyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gQXV0b1dpcmUgcGF0aFxuICAgICAgICBpZiAoY29uZmlnLmF1dG93aXJlT3B0aW9ucykge1xuICAgICAgICAgICAgdGhpcy5jcmVhdGVBdXRvV2lyZUZhY3RvcnkoY29udGFpbmVyLCBjb25maWcsIG9wdGlvbnMpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIHdpdGhQYXJhbWV0ZXJzIHBhdGhcbiAgICAgICAgaWYgKGNvbmZpZy5wYXJhbWV0ZXJWYWx1ZXMpIHtcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlUGFyYW1ldGVyRmFjdG9yeShjb250YWluZXIsIGNvbmZpZywgb3B0aW9ucyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gRXJyb3I6IENvbnN0cnVjdG9yIGhhcyBkZXBlbmRlbmNpZXMgYnV0IG5vIGNvbmZpZ1xuICAgICAgICBpZiAoaGFzRGVwZW5kZW5jaWVzKSB7XG4gICAgICAgICAgICBjb25zdCBjbGFzc05hbWUgPSBjb25maWcuY29uc3RydWN0b3IubmFtZSB8fCAnVW5uYW1lZENsYXNzJztcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgU2VydmljZSBcIiR7Y2xhc3NOYW1lfVwiIGhhcyBjb25zdHJ1Y3RvciBkZXBlbmRlbmNpZXMgYnV0IG5vIGF1dG93aXJpbmcgY29uZmlndXJhdGlvbi5cXG5cXG5gICtcbiAgICAgICAgICAgICAgICBgU29sdXRpb25zOlxcbmAgK1xuICAgICAgICAgICAgICAgIGAgIDEuIFx1MkI1MCBVc2UgdGhlIE5vdmFESSB0cmFuc2Zvcm1lciAocmVjb21tZW5kZWQpOlxcbmAgK1xuICAgICAgICAgICAgICAgIGAgICAgIC0gQWRkIFwiQG5vdmFkaS9jb3JlL3VucGx1Z2luXCIgdG8geW91ciBidWlsZCBjb25maWdcXG5gICtcbiAgICAgICAgICAgICAgICBgICAgICAtIFRyYW5zZm9ybWVyIGF1dG9tYXRpY2FsbHkgZ2VuZXJhdGVzIC5hdXRvV2lyZSgpIGZvciBhbGwgZGVwZW5kZW5jaWVzXFxuXFxuYCArXG4gICAgICAgICAgICAgICAgYCAgMi4gQWRkIG1hbnVhbCBhdXRvd2lyaW5nOlxcbmAgK1xuICAgICAgICAgICAgICAgIGAgICAgIC5hdXRvV2lyZSh7IG1hcDogeyAvKiBwYXJhbTogcmVzb2x2ZXIgKi8gfSB9KVxcblxcbmAgK1xuICAgICAgICAgICAgICAgIGAgIDMuIFVzZSBhIGZhY3RvcnkgZnVuY3Rpb246XFxuYCArXG4gICAgICAgICAgICAgICAgYCAgICAgLnJlZ2lzdGVyKChjKSA9PiBuZXcgJHtjbGFzc05hbWV9KC4uLikpXFxuXFxuYCArXG4gICAgICAgICAgICAgICAgYFNlZSBkb2NzOiBodHRwczovL2dpdGh1Yi5jb20vamFudXMwMDcvTm92YURJI2F1dG93aXJlYCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTm8gZGVwZW5kZW5jaWVzIC0gY3JlYXRlIHNpbXBsZSBmYWN0b3J5XG4gICAgICAgIGNvbnN0IGZhY3RvcnkgPSAoKSA9PiBuZXcgY29uZmlnLmNvbnN0cnVjdG9yKCk7XG4gICAgICAgIGNvbnRhaW5lci5iaW5kRmFjdG9yeShjb25maWcudG9rZW4sIGZhY3RvcnksIG9wdGlvbnMpO1xuICAgIH1cbiAgICBhcHBseVJlZ2lzdHJhdGlvbihjb250YWluZXIsIGNvbmZpZykge1xuICAgICAgICBjb25zdCBvcHRpb25zID0geyBsaWZldGltZTogY29uZmlnLmxpZmV0aW1lIH07XG4gICAgICAgIHN3aXRjaCAoY29uZmlnLnR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ2luc3RhbmNlJzpcbiAgICAgICAgICAgICAgICBjb250YWluZXIuYmluZFZhbHVlKGNvbmZpZy50b2tlbiwgY29uZmlnLnZhbHVlKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2ZhY3RvcnknOlxuICAgICAgICAgICAgICAgIGNvbnRhaW5lci5iaW5kRmFjdG9yeShjb25maWcudG9rZW4sIGNvbmZpZy5mYWN0b3J5LCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3R5cGUnOlxuICAgICAgICAgICAgICAgIHRoaXMuYXBwbHlUeXBlUmVnaXN0cmF0aW9uKGNvbnRhaW5lciwgY29uZmlnLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsICIvKipcbiAqIENvcmUgZGVwZW5kZW5jeSBpbmplY3Rpb24gY29udGFpbmVyIGZvciBOb3ZhRElcbiAqL1xuaW1wb3J0IHsgVG9rZW4gfSBmcm9tICcuL3Rva2VuLmpzJztcbmltcG9ydCB7IEJpbmRpbmdOb3RGb3VuZEVycm9yLCBDaXJjdWxhckRlcGVuZGVuY3lFcnJvciB9IGZyb20gJy4vZXJyb3JzLmpzJztcbmltcG9ydCB7IEJ1aWxkZXIgfSBmcm9tICcuL2J1aWxkZXIuanMnO1xuZnVuY3Rpb24gaXNEaXNwb3NhYmxlKG9iaikge1xuICAgIHJldHVybiBvYmogJiYgdHlwZW9mIG9iai5kaXNwb3NlID09PSAnZnVuY3Rpb24nO1xufVxuLyoqXG4gKiBSZXNvbHV0aW9uIGNvbnRleHQgdHJhY2tzIHRoZSBjdXJyZW50IGRlcGVuZGVuY3kgcmVzb2x1dGlvbiBwYXRoXG4gKiBmb3IgY2lyY3VsYXIgZGVwZW5kZW5jeSBkZXRlY3Rpb24gYW5kIHBlci1yZXF1ZXN0IHNjb3BpbmdcbiAqL1xuY2xhc3MgUmVzb2x1dGlvbkNvbnRleHQge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnJlc29sdmluZ1N0YWNrID0gbmV3IFNldCgpO1xuICAgICAgICB0aGlzLnBlclJlcXVlc3RDYWNoZSA9IG5ldyBNYXAoKTtcbiAgICB9XG4gICAgaXNSZXNvbHZpbmcodG9rZW4pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVzb2x2aW5nU3RhY2suaGFzKHRva2VuKTtcbiAgICB9XG4gICAgZW50ZXJSZXNvbHZlKHRva2VuKSB7XG4gICAgICAgIHRoaXMucmVzb2x2aW5nU3RhY2suYWRkKHRva2VuKTtcbiAgICAgICAgLy8gUGVyZm9ybWFuY2U6IERvbid0IGJ1aWxkIHBhdGggdW5sZXNzIHdlIG5lZWQgaXQgKG9ubHkgdXNlZCBpbiBlcnJvciBtZXNzYWdlcylcbiAgICAgICAgLy8gVGhpcyBhdm9pZHMgZXhwZW5zaXZlIHRva2VuLnRvU3RyaW5nKCkgY2FsbHMgb24gZXZlcnkgcmVzb2x2ZVxuICAgIH1cbiAgICBleGl0UmVzb2x2ZSh0b2tlbikge1xuICAgICAgICB0aGlzLnJlc29sdmluZ1N0YWNrLmRlbGV0ZSh0b2tlbik7XG4gICAgICAgIC8vIFBlcmZvcm1hbmNlOiBDbGVhciBsYXp5IHBhdGggY2FjaGUgd2hlbiBleGl0aW5nXG4gICAgICAgIHRoaXMucGF0aCA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgZ2V0UGF0aCgpIHtcbiAgICAgICAgLy8gUGVyZm9ybWFuY2U6IEJ1aWxkIHBhdGggb24tZGVtYW5kIG9ubHkgd2hlbiBuZWVkZWQgKHR5cGljYWxseSBmb3IgZXJyb3IgbWVzc2FnZXMpXG4gICAgICAgIGlmICghdGhpcy5wYXRoKSB7XG4gICAgICAgICAgICB0aGlzLnBhdGggPSBBcnJheS5mcm9tKHRoaXMucmVzb2x2aW5nU3RhY2spLm1hcCh0ID0+IHQudG9TdHJpbmcoKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFsuLi50aGlzLnBhdGhdO1xuICAgIH1cbiAgICBjYWNoZVBlclJlcXVlc3QodG9rZW4sIGluc3RhbmNlKSB7XG4gICAgICAgIHRoaXMucGVyUmVxdWVzdENhY2hlLnNldCh0b2tlbiwgaW5zdGFuY2UpO1xuICAgIH1cbiAgICBnZXRQZXJSZXF1ZXN0KHRva2VuKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBlclJlcXVlc3RDYWNoZS5nZXQodG9rZW4pO1xuICAgIH1cbiAgICBoYXNQZXJSZXF1ZXN0KHRva2VuKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBlclJlcXVlc3RDYWNoZS5oYXModG9rZW4pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXNldCBjb250ZXh0IGZvciByZXVzZSBpbiBvYmplY3QgcG9vbFxuICAgICAqIFBlcmZvcm1hbmNlOiBSZXVzaW5nIGNvbnRleHRzIGF2b2lkcyBoZWFwIGFsbG9jYXRpb25zXG4gICAgICovXG4gICAgcmVzZXQoKSB7XG4gICAgICAgIHRoaXMucmVzb2x2aW5nU3RhY2suY2xlYXIoKTtcbiAgICAgICAgdGhpcy5wZXJSZXF1ZXN0Q2FjaGUuY2xlYXIoKTtcbiAgICAgICAgdGhpcy5wYXRoID0gdW5kZWZpbmVkO1xuICAgIH1cbn1cbi8qKlxuICogT2JqZWN0IHBvb2wgZm9yIFJlc29sdXRpb25Db250ZXh0IGluc3RhbmNlc1xuICogUGVyZm9ybWFuY2U6IFJldXNpbmcgY29udGV4dHMgcmVkdWNlcyBoZWFwIGFsbG9jYXRpb25zIGFuZCBHQyBwcmVzc3VyZVxuICovXG5jbGFzcyBSZXNvbHV0aW9uQ29udGV4dFBvb2wge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnBvb2wgPSBbXTtcbiAgICAgICAgdGhpcy5tYXhTaXplID0gMTA7XG4gICAgfVxuICAgIGFjcXVpcmUoKSB7XG4gICAgICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLnBvb2wucG9wKCk7XG4gICAgICAgIGlmIChjb250ZXh0KSB7XG4gICAgICAgICAgICAvLyBSZXNldCBleGlzdGluZyBjb250ZXh0IGZvciByZXVzZVxuICAgICAgICAgICAgY29udGV4dC5yZXNldCgpO1xuICAgICAgICAgICAgcmV0dXJuIGNvbnRleHQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ3JlYXRlIG5ldyBpZiBwb29sIGVtcHR5XG4gICAgICAgIHJldHVybiBuZXcgUmVzb2x1dGlvbkNvbnRleHQoKTtcbiAgICB9XG4gICAgcmVsZWFzZShjb250ZXh0KSB7XG4gICAgICAgIGlmICh0aGlzLnBvb2wubGVuZ3RoIDwgdGhpcy5tYXhTaXplKSB7XG4gICAgICAgICAgICB0aGlzLnBvb2wucHVzaChjb250ZXh0KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBPdGhlcndpc2UgbGV0IGl0IGJlIEdDJ2RcbiAgICB9XG59XG4vKipcbiAqIERlcGVuZGVuY3kgSW5qZWN0aW9uIENvbnRhaW5lclxuICpcbiAqIE1hbmFnZXMgcmVnaXN0cmF0aW9uIGFuZCByZXNvbHV0aW9uIG9mIGRlcGVuZGVuY2llcyB3aXRoIHN1cHBvcnQgZm9yOlxuICogLSBNdWx0aXBsZSBiaW5kaW5nIHR5cGVzICh2YWx1ZSwgZmFjdG9yeSwgY2xhc3MpXG4gKiAtIExpZmV0aW1lIG1hbmFnZW1lbnQgKHNpbmdsZXRvbiwgdHJhbnNpZW50LCBwZXItcmVxdWVzdClcbiAqIC0gQ2hpbGQgY29udGFpbmVycyB3aXRoIGluaGVyaXRhbmNlXG4gKiAtIENpcmN1bGFyIGRlcGVuZGVuY3kgZGV0ZWN0aW9uXG4gKiAtIEF1dG9tYXRpYyBkaXNwb3NhbFxuICovXG5leHBvcnQgY2xhc3MgQ29udGFpbmVyIHtcbiAgICBjb25zdHJ1Y3RvcihwYXJlbnQpIHtcbiAgICAgICAgdGhpcy5iaW5kaW5ncyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5zaW5nbGV0b25DYWNoZSA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5zaW5nbGV0b25PcmRlciA9IFtdO1xuICAgICAgICB0aGlzLmludGVyZmFjZVJlZ2lzdHJ5ID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLmludGVyZmFjZVRva2VuQ2FjaGUgPSBuZXcgTWFwKCk7IC8vIFBlcmZvcm1hbmNlOiBDYWNoZSBmb3IgcmVzb2x2ZVR5cGUoKSBsb29rdXBzXG4gICAgICAgIHRoaXMuZmFzdFRyYW5zaWVudENhY2hlID0gbmV3IE1hcCgpOyAvLyBQZXJmb3JtYW5jZTogRmFzdCBwYXRoIGZvciBzaW1wbGUgdHJhbnNpZW50c1xuICAgICAgICB0aGlzLnVsdHJhRmFzdFNpbmdsZXRvbkNhY2hlID0gbmV3IE1hcCgpOyAvLyBQZXJmb3JtYW5jZTogVWx0cmEtZmFzdCBzaW5nbGV0b24tb25seSBjYWNoZVxuICAgICAgICB0aGlzLnBhcmVudCA9IHBhcmVudDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQmluZCBhIHByZS1jcmVhdGVkIHZhbHVlIHRvIGEgdG9rZW5cbiAgICAgKi9cbiAgICBiaW5kVmFsdWUodG9rZW4sIHZhbHVlKSB7XG4gICAgICAgIHRoaXMuYmluZGluZ3Muc2V0KHRva2VuLCB7XG4gICAgICAgICAgICB0eXBlOiAndmFsdWUnLFxuICAgICAgICAgICAgbGlmZXRpbWU6ICdzaW5nbGV0b24nLFxuICAgICAgICAgICAgdmFsdWUsXG4gICAgICAgICAgICBjb25zdHJ1Y3RvcjogdW5kZWZpbmVkXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmludmFsaWRhdGVCaW5kaW5nQ2FjaGUoKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQmluZCBhIGZhY3RvcnkgZnVuY3Rpb24gdG8gYSB0b2tlblxuICAgICAqL1xuICAgIGJpbmRGYWN0b3J5KHRva2VuLCBmYWN0b3J5LCBvcHRpb25zKSB7XG4gICAgICAgIHRoaXMuYmluZGluZ3Muc2V0KHRva2VuLCB7XG4gICAgICAgICAgICB0eXBlOiAnZmFjdG9yeScsXG4gICAgICAgICAgICBsaWZldGltZTogb3B0aW9ucz8ubGlmZXRpbWUgfHwgJ3RyYW5zaWVudCcsXG4gICAgICAgICAgICBmYWN0b3J5LFxuICAgICAgICAgICAgZGVwZW5kZW5jaWVzOiBvcHRpb25zPy5kZXBlbmRlbmNpZXMsXG4gICAgICAgICAgICBjb25zdHJ1Y3RvcjogdW5kZWZpbmVkXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmludmFsaWRhdGVCaW5kaW5nQ2FjaGUoKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQmluZCBhIGNsYXNzIGNvbnN0cnVjdG9yIHRvIGEgdG9rZW5cbiAgICAgKi9cbiAgICBiaW5kQ2xhc3ModG9rZW4sIGNvbnN0cnVjdG9yLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGJpbmRpbmcgPSB7XG4gICAgICAgICAgICB0eXBlOiAnY2xhc3MnLFxuICAgICAgICAgICAgbGlmZXRpbWU6IG9wdGlvbnM/LmxpZmV0aW1lIHx8ICd0cmFuc2llbnQnLFxuICAgICAgICAgICAgY29uc3RydWN0b3IsXG4gICAgICAgICAgICBkZXBlbmRlbmNpZXM6IG9wdGlvbnM/LmRlcGVuZGVuY2llc1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmJpbmRpbmdzLnNldCh0b2tlbiwgYmluZGluZyk7XG4gICAgICAgIHRoaXMuaW52YWxpZGF0ZUJpbmRpbmdDYWNoZSgpO1xuICAgICAgICAvLyBQZXJmb3JtYW5jZTogUHJlLWNvbXBpbGUgZmFzdCB0cmFuc2llbnQgZmFjdG9yeSBmb3IgemVyby1kZXBlbmRlbmN5IGNsYXNzZXNcbiAgICAgICAgaWYgKGJpbmRpbmcubGlmZXRpbWUgPT09ICd0cmFuc2llbnQnICYmICghYmluZGluZy5kZXBlbmRlbmNpZXMgfHwgYmluZGluZy5kZXBlbmRlbmNpZXMubGVuZ3RoID09PSAwKSkge1xuICAgICAgICAgICAgdGhpcy5mYXN0VHJhbnNpZW50Q2FjaGUuc2V0KHRva2VuLCAoKSA9PiBuZXcgY29uc3RydWN0b3IoKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVzb2x2ZSBhIGRlcGVuZGVuY3kgc3luY2hyb25vdXNseVxuICAgICAqIFBlcmZvcm1hbmNlIG9wdGltaXplZCB3aXRoIG11bHRpcGxlIGZhc3QgcGF0aHNcbiAgICAgKi9cbiAgICByZXNvbHZlKHRva2VuKSB7XG4gICAgICAgIC8vIFRyeSBhbGwgY2FjaGUgbGV2ZWxzIGZpcnN0ICh1bHRyYS1mYXN0LCBzaW5nbGV0b24sIGZhc3QgdHJhbnNpZW50KVxuICAgICAgICBjb25zdCBjYWNoZWQgPSB0aGlzLnRyeUdldEZyb21DYWNoZXModG9rZW4pO1xuICAgICAgICBpZiAoY2FjaGVkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gSWYgd2UncmUgYWxyZWFkeSByZXNvbHZpbmcgKGNhbGxlZCBmcm9tIHdpdGhpbiBhIGZhY3RvcnkpLCByZXVzZSB0aGUgY29udGV4dFxuICAgICAgICBpZiAodGhpcy5jdXJyZW50Q29udGV4dCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZVdpdGhDb250ZXh0KHRva2VuLCB0aGlzLmN1cnJlbnRDb250ZXh0KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBDb21wbGV4IHJlc29sdXRpb24gd2l0aCBwb29sZWQgY29udGV4dFxuICAgICAgICBjb25zdCBjb250ZXh0ID0gQ29udGFpbmVyLmNvbnRleHRQb29sLmFjcXVpcmUoKTtcbiAgICAgICAgdGhpcy5jdXJyZW50Q29udGV4dCA9IGNvbnRleHQ7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZXNvbHZlV2l0aENvbnRleHQodG9rZW4sIGNvbnRleHQpO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkge1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50Q29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIENvbnRhaW5lci5jb250ZXh0UG9vbC5yZWxlYXNlKGNvbnRleHQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNQRUNJQUxJWkVEOiBVbHRyYS1mYXN0IHNpbmdsZXRvbiByZXNvbHZlIChubyBzYWZldHkgY2hlY2tzKVxuICAgICAqIFVzZSBPTkxZIHdoZW4geW91J3JlIDEwMCUgc3VyZSB0aGUgdG9rZW4gaXMgYSByZWdpc3RlcmVkIHNpbmdsZXRvblxuICAgICAqIEBpbnRlcm5hbCBGb3IgcGVyZm9ybWFuY2UtY3JpdGljYWwgcGF0aHMgb25seVxuICAgICAqL1xuICAgIHJlc29sdmVTaW5nbGV0b25VbnNhZmUodG9rZW4pIHtcbiAgICAgICAgLy8gRGlyZWN0IHJldHVybiwgbm8gY2hlY2tzIC0gbWF4aW11bSBzcGVlZFxuICAgICAgICByZXR1cm4gdGhpcy51bHRyYUZhc3RTaW5nbGV0b25DYWNoZS5nZXQodG9rZW4pID8/IHRoaXMuc2luZ2xldG9uQ2FjaGUuZ2V0KHRva2VuKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU1BFQ0lBTElaRUQ6IEZhc3QgdHJhbnNpZW50IHJlc29sdmUgZm9yIHplcm8tZGVwZW5kZW5jeSBjbGFzc2VzXG4gICAgICogU2tpcHMgYWxsIGNvbnRleHQgY3JlYXRpb24gYW5kIGNpcmN1bGFyIGRlcGVuZGVuY3kgY2hlY2tzXG4gICAgICogQGludGVybmFsIEZvciBwZXJmb3JtYW5jZS1jcml0aWNhbCBwYXRocyBvbmx5XG4gICAgICovXG4gICAgcmVzb2x2ZVRyYW5zaWVudFNpbXBsZSh0b2tlbikge1xuICAgICAgICBjb25zdCBmYWN0b3J5ID0gdGhpcy5mYXN0VHJhbnNpZW50Q2FjaGUuZ2V0KHRva2VuKTtcbiAgICAgICAgaWYgKGZhY3RvcnkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWN0b3J5KCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gRmFsbGJhY2sgdG8gcmVndWxhciByZXNvbHZlIGlmIG5vdCBpbiBmYXN0IGNhY2hlXG4gICAgICAgIHJldHVybiB0aGlzLnJlc29sdmUodG9rZW4pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTUEVDSUFMSVpFRDogQmF0Y2ggcmVzb2x2ZSBtdWx0aXBsZSBkZXBlbmRlbmNpZXMgYXQgb25jZVxuICAgICAqIE1vcmUgZWZmaWNpZW50IHRoYW4gbXVsdGlwbGUgaW5kaXZpZHVhbCByZXNvbHZlc1xuICAgICAqL1xuICAgIHJlc29sdmVCYXRjaCh0b2tlbnMpIHtcbiAgICAgICAgLy8gUmV1c2Ugc2luZ2xlIGNvbnRleHQgZm9yIGFsbCByZXNvbHV0aW9uc1xuICAgICAgICBjb25zdCB3YXNSZXNvbHZpbmcgPSAhIXRoaXMuY3VycmVudENvbnRleHQ7XG4gICAgICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmN1cnJlbnRDb250ZXh0IHx8IENvbnRhaW5lci5jb250ZXh0UG9vbC5hY3F1aXJlKCk7XG4gICAgICAgIGlmICghd2FzUmVzb2x2aW5nKSB7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRDb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0cyA9IHRva2Vucy5tYXAodG9rZW4gPT4ge1xuICAgICAgICAgICAgICAgIC8vIFRyeSBhbGwgY2FjaGUgbGV2ZWxzIGZpcnN0XG4gICAgICAgICAgICAgICAgY29uc3QgY2FjaGVkID0gdGhpcy50cnlHZXRGcm9tQ2FjaGVzKHRva2VuKTtcbiAgICAgICAgICAgICAgICBpZiAoY2FjaGVkICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjYWNoZWQ7XG4gICAgICAgICAgICAgICAgLy8gRnVsbCByZXNvbHZlIHdpdGggc2hhcmVkIGNvbnRleHRcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yZXNvbHZlV2l0aENvbnRleHQodG9rZW4sIGNvbnRleHQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgIGlmICghd2FzUmVzb2x2aW5nKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Q29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICBDb250YWluZXIuY29udGV4dFBvb2wucmVsZWFzZShjb250ZXh0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXNvbHZlIGEgZGVwZW5kZW5jeSBhc3luY2hyb25vdXNseSAoc3VwcG9ydHMgYXN5bmMgZmFjdG9yaWVzKVxuICAgICAqL1xuICAgIGFzeW5jIHJlc29sdmVBc3luYyh0b2tlbikge1xuICAgICAgICAvLyBJZiB3ZSdyZSBhbHJlYWR5IHJlc29sdmluZyAoY2FsbGVkIGZyb20gd2l0aGluIGEgZmFjdG9yeSksIHJldXNlIHRoZSBjb250ZXh0XG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRDb250ZXh0KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZXNvbHZlQXN5bmNXaXRoQ29udGV4dCh0b2tlbiwgdGhpcy5jdXJyZW50Q29udGV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTmV3IHRvcC1sZXZlbCByZXNvbHZlXG4gICAgICAgIC8vIFBlcmZvcm1hbmNlOiBVc2UgcG9vbGVkIGNvbnRleHQgdG8gYXZvaWQgaGVhcCBhbGxvY2F0aW9uXG4gICAgICAgIGNvbnN0IGNvbnRleHQgPSBDb250YWluZXIuY29udGV4dFBvb2wuYWNxdWlyZSgpO1xuICAgICAgICB0aGlzLmN1cnJlbnRDb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiBhd2FpdCB0aGlzLnJlc29sdmVBc3luY1dpdGhDb250ZXh0KHRva2VuLCBjb250ZXh0KTtcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudENvbnRleHQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICBDb250YWluZXIuY29udGV4dFBvb2wucmVsZWFzZShjb250ZXh0KTsgLy8gUmV0dXJuIHRvIHBvb2wgZm9yIHJldXNlXG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogVHJ5IHRvIGdldCBpbnN0YW5jZSBmcm9tIGFsbCBjYWNoZSBsZXZlbHNcbiAgICAgKiBSZXR1cm5zIHVuZGVmaW5lZCBpZiBub3QgY2FjaGVkXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgdHJ5R2V0RnJvbUNhY2hlcyh0b2tlbikge1xuICAgICAgICAvLyBMZXZlbCAxOiBVbHRyYS1mYXN0IHNpbmdsZXRvbiBjYWNoZSAoemVybyBvdmVyaGVhZClcbiAgICAgICAgY29uc3QgdWx0cmFGYXN0ID0gdGhpcy51bHRyYUZhc3RTaW5nbGV0b25DYWNoZS5nZXQodG9rZW4pO1xuICAgICAgICBpZiAodWx0cmFGYXN0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB1bHRyYUZhc3Q7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTGV2ZWwgMjogUmVndWxhciBzaW5nbGV0b24gY2FjaGVcbiAgICAgICAgaWYgKHRoaXMuc2luZ2xldG9uQ2FjaGUuaGFzKHRva2VuKSkge1xuICAgICAgICAgICAgY29uc3QgY2FjaGVkID0gdGhpcy5zaW5nbGV0b25DYWNoZS5nZXQodG9rZW4pO1xuICAgICAgICAgICAgLy8gUHJvbW90ZSB0byB1bHRyYS1mYXN0IGNhY2hlIGZvciBuZXh0IHRpbWVcbiAgICAgICAgICAgIHRoaXMudWx0cmFGYXN0U2luZ2xldG9uQ2FjaGUuc2V0KHRva2VuLCBjYWNoZWQpO1xuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZDtcbiAgICAgICAgfVxuICAgICAgICAvLyBMZXZlbCAzOiBGYXN0IHRyYW5zaWVudCBjYWNoZSAobm8gZGVwZW5kZW5jaWVzKVxuICAgICAgICBjb25zdCBmYXN0RmFjdG9yeSA9IHRoaXMuZmFzdFRyYW5zaWVudENhY2hlLmdldCh0b2tlbik7XG4gICAgICAgIGlmIChmYXN0RmFjdG9yeSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhc3RGYWN0b3J5KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ2FjaGUgaW5zdGFuY2UgYmFzZWQgb24gbGlmZXRpbWUgc3RyYXRlZ3lcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBjYWNoZUluc3RhbmNlKHRva2VuLCBpbnN0YW5jZSwgbGlmZXRpbWUsIGNvbnRleHQpIHtcbiAgICAgICAgaWYgKGxpZmV0aW1lID09PSAnc2luZ2xldG9uJykge1xuICAgICAgICAgICAgdGhpcy5zaW5nbGV0b25DYWNoZS5zZXQodG9rZW4sIGluc3RhbmNlKTtcbiAgICAgICAgICAgIHRoaXMuc2luZ2xldG9uT3JkZXIucHVzaCh0b2tlbik7XG4gICAgICAgICAgICAvLyBBbHNvIGFkZCB0byB1bHRyYS1mYXN0IGNhY2hlXG4gICAgICAgICAgICB0aGlzLnVsdHJhRmFzdFNpbmdsZXRvbkNhY2hlLnNldCh0b2tlbiwgaW5zdGFuY2UpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGxpZmV0aW1lID09PSAncGVyLXJlcXVlc3QnICYmIGNvbnRleHQpIHtcbiAgICAgICAgICAgIGNvbnRleHQuY2FjaGVQZXJSZXF1ZXN0KHRva2VuLCBpbnN0YW5jZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogVmFsaWRhdGUgYW5kIGdldCBiaW5kaW5nIHdpdGggY2lyY3VsYXIgZGVwZW5kZW5jeSBjaGVja1xuICAgICAqIFJldHVybnMgYmluZGluZyBvciB0aHJvd3MgZXJyb3JcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICB2YWxpZGF0ZUFuZEdldEJpbmRpbmcodG9rZW4sIGNvbnRleHQpIHtcbiAgICAgICAgLy8gQ2hlY2sgY2lyY3VsYXIgZGVwZW5kZW5jeVxuICAgICAgICBpZiAoY29udGV4dC5pc1Jlc29sdmluZyh0b2tlbikpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBDaXJjdWxhckRlcGVuZGVuY3lFcnJvcihbLi4uY29udGV4dC5nZXRQYXRoKCksIHRva2VuLnRvU3RyaW5nKCldKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBiaW5kaW5nID0gdGhpcy5nZXRCaW5kaW5nKHRva2VuKTtcbiAgICAgICAgaWYgKCFiaW5kaW5nKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgQmluZGluZ05vdEZvdW5kRXJyb3IodG9rZW4udG9TdHJpbmcoKSwgY29udGV4dC5nZXRQYXRoKCkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBiaW5kaW5nO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBJbnN0YW50aWF0ZSBmcm9tIGJpbmRpbmcgc3luY2hyb25vdXNseVxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGluc3RhbnRpYXRlQmluZGluZ1N5bmMoYmluZGluZywgdG9rZW4sIGNvbnRleHQpIHtcbiAgICAgICAgc3dpdGNoIChiaW5kaW5nLnR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ3ZhbHVlJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gYmluZGluZy52YWx1ZTtcbiAgICAgICAgICAgIGNhc2UgJ2ZhY3RvcnknOlxuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGJpbmRpbmcuZmFjdG9yeSh0aGlzKTtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgUHJvbWlzZSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEFzeW5jIGZhY3RvcnkgZGV0ZWN0ZWQgZm9yICR7dG9rZW4udG9TdHJpbmcoKX0uIFVzZSByZXNvbHZlQXN5bmMoKSBpbnN0ZWFkLmApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgY2FzZSAnY2xhc3MnOlxuICAgICAgICAgICAgICAgIGNvbnN0IGRlcHMgPSBiaW5kaW5nLmRlcGVuZGVuY2llcyB8fCBbXTtcbiAgICAgICAgICAgICAgICBjb25zdCByZXNvbHZlZERlcHMgPSBkZXBzLm1hcChkZXAgPT4gdGhpcy5yZXNvbHZlV2l0aENvbnRleHQoZGVwLCBjb250ZXh0KSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBiaW5kaW5nLmNvbnN0cnVjdG9yKC4uLnJlc29sdmVkRGVwcyk7XG4gICAgICAgICAgICBjYXNlICdpbmxpbmUtY2xhc3MnOlxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgYmluZGluZy5jb25zdHJ1Y3RvcigpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gYmluZGluZyB0eXBlOiAke2JpbmRpbmcudHlwZX1gKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBJbnN0YW50aWF0ZSBmcm9tIGJpbmRpbmcgYXN5bmNocm9ub3VzbHlcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBhc3luYyBpbnN0YW50aWF0ZUJpbmRpbmdBc3luYyhiaW5kaW5nLCBjb250ZXh0KSB7XG4gICAgICAgIHN3aXRjaCAoYmluZGluZy50eXBlKSB7XG4gICAgICAgICAgICBjYXNlICd2YWx1ZSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGJpbmRpbmcudmFsdWU7XG4gICAgICAgICAgICBjYXNlICdmYWN0b3J5JzpcbiAgICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgUHJvbWlzZS5yZXNvbHZlKGJpbmRpbmcuZmFjdG9yeSh0aGlzKSk7XG4gICAgICAgICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgICAgICAgICAgY29uc3QgZGVwcyA9IGJpbmRpbmcuZGVwZW5kZW5jaWVzIHx8IFtdO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc29sdmVkRGVwcyA9IGF3YWl0IFByb21pc2UuYWxsKGRlcHMubWFwKGRlcCA9PiB0aGlzLnJlc29sdmVBc3luY1dpdGhDb250ZXh0KGRlcCwgY29udGV4dCkpKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IGJpbmRpbmcuY29uc3RydWN0b3IoLi4ucmVzb2x2ZWREZXBzKTtcbiAgICAgICAgICAgIGNhc2UgJ2lubGluZS1jbGFzcyc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBiaW5kaW5nLmNvbnN0cnVjdG9yKCk7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBiaW5kaW5nIHR5cGU6ICR7YmluZGluZy50eXBlfWApO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIGNoaWxkIGNvbnRhaW5lciB0aGF0IGluaGVyaXRzIGJpbmRpbmdzIGZyb20gdGhpcyBjb250YWluZXJcbiAgICAgKi9cbiAgICBjcmVhdGVDaGlsZCgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBDb250YWluZXIodGhpcyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIERpc3Bvc2UgYWxsIHNpbmdsZXRvbiBpbnN0YW5jZXMgaW4gcmV2ZXJzZSByZWdpc3RyYXRpb24gb3JkZXJcbiAgICAgKi9cbiAgICBhc3luYyBkaXNwb3NlKCkge1xuICAgICAgICBjb25zdCBlcnJvcnMgPSBbXTtcbiAgICAgICAgLy8gRGlzcG9zZSBpbiByZXZlcnNlIG9yZGVyXG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLnNpbmdsZXRvbk9yZGVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICBjb25zdCB0b2tlbiA9IHRoaXMuc2luZ2xldG9uT3JkZXJbaV07XG4gICAgICAgICAgICBjb25zdCBpbnN0YW5jZSA9IHRoaXMuc2luZ2xldG9uQ2FjaGUuZ2V0KHRva2VuKTtcbiAgICAgICAgICAgIGlmIChpbnN0YW5jZSAmJiBpc0Rpc3Bvc2FibGUoaW5zdGFuY2UpKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgaW5zdGFuY2UuZGlzcG9zZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JzLnB1c2goZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAvLyBDb250aW51ZSBkaXNwb3Npbmcgb3RoZXIgaW5zdGFuY2VzIGV2ZW4gaWYgb25lIGZhaWxzXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIENsZWFyIGNhY2hlc1xuICAgICAgICB0aGlzLnNpbmdsZXRvbkNhY2hlLmNsZWFyKCk7XG4gICAgICAgIHRoaXMuc2luZ2xldG9uT3JkZXIubGVuZ3RoID0gMDtcbiAgICAgICAgLy8gTm90ZTogV2UgZG9uJ3QgdGhyb3cgZXJyb3JzIHRvIGFsbG93IGFsbCBkaXNwb3NhbHMgdG8gY29tcGxldGVcbiAgICAgICAgLy8gSW4gcHJvZHVjdGlvbiwgeW91IG1pZ2h0IHdhbnQgdG8gbG9nIHRoZXNlIGVycm9yc1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgYSBmbHVlbnQgYnVpbGRlciBmb3IgcmVnaXN0ZXJpbmcgZGVwZW5kZW5jaWVzXG4gICAgICovXG4gICAgYnVpbGRlcigpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBCdWlsZGVyKHRoaXMpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXNvbHZlIGEgbmFtZWQgc2VydmljZVxuICAgICAqL1xuICAgIHJlc29sdmVOYW1lZChuYW1lKSB7XG4gICAgICAgIGNvbnN0IG5hbWVkUmVnaXN0cmF0aW9ucyA9IHRoaXMuX19uYW1lZFJlZ2lzdHJhdGlvbnM7XG4gICAgICAgIGlmICghbmFtZWRSZWdpc3RyYXRpb25zKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5hbWVkIHNlcnZpY2UgXCIke25hbWV9XCIgbm90IGZvdW5kLiBObyBuYW1lZCByZWdpc3RyYXRpb25zIGV4aXN0LmApO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNvbmZpZyA9IG5hbWVkUmVnaXN0cmF0aW9ucy5nZXQobmFtZSk7XG4gICAgICAgIGlmICghY29uZmlnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5hbWVkIHNlcnZpY2UgXCIke25hbWV9XCIgbm90IGZvdW5kYCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZShjb25maWcudG9rZW4pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXNvbHZlIGEga2V5ZWQgc2VydmljZVxuICAgICAqL1xuICAgIHJlc29sdmVLZXllZChrZXkpIHtcbiAgICAgICAgY29uc3Qga2V5ZWRSZWdpc3RyYXRpb25zID0gdGhpcy5fX2tleWVkUmVnaXN0cmF0aW9ucztcbiAgICAgICAgaWYgKCFrZXllZFJlZ2lzdHJhdGlvbnMpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgS2V5ZWQgc2VydmljZSBub3QgZm91bmQuIE5vIGtleWVkIHJlZ2lzdHJhdGlvbnMgZXhpc3QuYCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY29uZmlnID0ga2V5ZWRSZWdpc3RyYXRpb25zLmdldChrZXkpO1xuICAgICAgICBpZiAoIWNvbmZpZykge1xuICAgICAgICAgICAgY29uc3Qga2V5U3RyID0gdHlwZW9mIGtleSA9PT0gJ3N5bWJvbCcgPyBrZXkudG9TdHJpbmcoKSA6IGBcIiR7a2V5fVwiYDtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgS2V5ZWQgc2VydmljZSAke2tleVN0cn0gbm90IGZvdW5kYCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZShjb25maWcudG9rZW4pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXNvbHZlIGFsbCByZWdpc3RyYXRpb25zIGZvciBhIHRva2VuXG4gICAgICovXG4gICAgcmVzb2x2ZUFsbCh0b2tlbikge1xuICAgICAgICBjb25zdCBtdWx0aVJlZ2lzdHJhdGlvbnMgPSB0aGlzLl9fbXVsdGlSZWdpc3RyYXRpb25zO1xuICAgICAgICBpZiAoIW11bHRpUmVnaXN0cmF0aW9ucykge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHRva2VucyA9IG11bHRpUmVnaXN0cmF0aW9ucy5nZXQodG9rZW4pO1xuICAgICAgICBpZiAoIXRva2VucyB8fCB0b2tlbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRva2Vucy5tYXAoKHQpID0+IHRoaXMucmVzb2x2ZSh0KSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCByZWdpc3RyeSBpbmZvcm1hdGlvbiBmb3IgZGVidWdnaW5nL3Zpc3VhbGl6YXRpb25cbiAgICAgKiBSZXR1cm5zIGFycmF5IG9mIGJpbmRpbmcgaW5mb3JtYXRpb25cbiAgICAgKi9cbiAgICBnZXRSZWdpc3RyeSgpIHtcbiAgICAgICAgY29uc3QgcmVnaXN0cnkgPSBbXTtcbiAgICAgICAgdGhpcy5iaW5kaW5ncy5mb3JFYWNoKChiaW5kaW5nLCB0b2tlbikgPT4ge1xuICAgICAgICAgICAgcmVnaXN0cnkucHVzaCh7XG4gICAgICAgICAgICAgICAgdG9rZW46IHRva2VuLmRlc2NyaXB0aW9uIHx8IHRva2VuLnN5bWJvbC50b1N0cmluZygpLFxuICAgICAgICAgICAgICAgIHR5cGU6IGJpbmRpbmcudHlwZSxcbiAgICAgICAgICAgICAgICBsaWZldGltZTogYmluZGluZy5saWZldGltZSxcbiAgICAgICAgICAgICAgICBkZXBlbmRlbmNpZXM6IGJpbmRpbmcuZGVwZW5kZW5jaWVzPy5tYXAoZCA9PiBkLmRlc2NyaXB0aW9uIHx8IGQuc3ltYm9sLnRvU3RyaW5nKCkpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZWdpc3RyeTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IG9yIGNyZWF0ZSBhIHRva2VuIGZvciBhbiBpbnRlcmZhY2UgdHlwZVxuICAgICAqIFVzZXMgYSB0eXBlIG5hbWUgaGFzaCBhcyBrZXkgZm9yIHRoZSBpbnRlcmZhY2UgcmVnaXN0cnlcbiAgICAgKi9cbiAgICBpbnRlcmZhY2VUb2tlbih0eXBlTmFtZSkge1xuICAgICAgICAvLyBHZW5lcmF0ZSBhIHVuaXF1ZSBrZXkgZm9yIHRoaXMgaW50ZXJmYWNlIHR5cGVcbiAgICAgICAgLy8gSW4gcHJvZHVjdGlvbiwgdGhpcyB3b3VsZCBiZSByZXBsYWNlZCBieSBhIFRTIHRyYW5zZm9ybWVyXG4gICAgICAgIGNvbnN0IGtleSA9IHR5cGVOYW1lIHx8IGBJbnRlcmZhY2VfJHtNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zdWJzdHIoMiwgOSl9YDtcbiAgICAgICAgLy8gQ2hlY2sgaWYgdG9rZW4gYWxyZWFkeSBleGlzdHMgaW4gdGhpcyBjb250YWluZXJcbiAgICAgICAgaWYgKHRoaXMuaW50ZXJmYWNlUmVnaXN0cnkuaGFzKGtleSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmludGVyZmFjZVJlZ2lzdHJ5LmdldChrZXkpO1xuICAgICAgICB9XG4gICAgICAgIC8vIENoZWNrIHBhcmVudCBjb250YWluZXIgKHJlY3Vyc2l2ZWx5IHRocm91Z2ggcGFyZW50IGNoYWluKVxuICAgICAgICBpZiAodGhpcy5wYXJlbnQpIHtcbiAgICAgICAgICAgIC8vIFJlY3Vyc2l2ZWx5IGNoZWNrIHRocm91Z2ggZW50aXJlIHBhcmVudCBjaGFpblxuICAgICAgICAgICAgY29uc3QgcGFyZW50VG9rZW4gPSB0aGlzLnBhcmVudC5pbnRlcmZhY2VUb2tlbihrZXkpO1xuICAgICAgICAgICAgLy8gSWYgcGFyZW50IGNyZWF0ZWQgYSBuZXcgdG9rZW4sIGRvbid0IGNyZWF0ZSBhbm90aGVyIG9uZVxuICAgICAgICAgICAgcmV0dXJuIHBhcmVudFRva2VuO1xuICAgICAgICB9XG4gICAgICAgIC8vIENyZWF0ZSBuZXcgdG9rZW4gKG9ubHkgaWYgbm8gcGFyZW50IGV4aXN0cylcbiAgICAgICAgY29uc3QgdG9rZW4gPSBUb2tlbihrZXkpO1xuICAgICAgICB0aGlzLmludGVyZmFjZVJlZ2lzdHJ5LnNldChrZXksIHRva2VuKTtcbiAgICAgICAgcmV0dXJuIHRva2VuO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXNvbHZlIGEgZGVwZW5kZW5jeSBieSBpbnRlcmZhY2UgdHlwZSB3aXRob3V0IGV4cGxpY2l0IHRva2VuXG4gICAgICovXG4gICAgcmVzb2x2ZVR5cGUodHlwZU5hbWUpIHtcbiAgICAgICAgLy8gUGVyZm9ybWFuY2U6IENhY2hlIHRva2VuIGxvb2t1cHMgdG8gYXZvaWQgcmVwZWF0ZWQgaW50ZXJmYWNlUmVnaXN0cnkgYWNjZXNzXG4gICAgICAgIGNvbnN0IGtleSA9IHR5cGVOYW1lIHx8ICcnO1xuICAgICAgICBsZXQgdG9rZW4gPSB0aGlzLmludGVyZmFjZVRva2VuQ2FjaGUuZ2V0KGtleSk7XG4gICAgICAgIGlmICghdG9rZW4pIHtcbiAgICAgICAgICAgIHRva2VuID0gdGhpcy5pbnRlcmZhY2VUb2tlbih0eXBlTmFtZSk7XG4gICAgICAgICAgICB0aGlzLmludGVyZmFjZVRva2VuQ2FjaGUuc2V0KGtleSwgdG9rZW4pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnJlc29sdmUodG9rZW4pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXNvbHZlIGEga2V5ZWQgaW50ZXJmYWNlXG4gICAgICovXG4gICAgcmVzb2x2ZVR5cGVLZXllZChrZXksIF90eXBlTmFtZSkge1xuICAgICAgICAvLyBGb3Iga2V5ZWQgaW50ZXJmYWNlcywgd2UgdXNlIHRoZSBleGlzdGluZyByZXNvbHZlS2V5ZWQgbWVjaGFuaXNtXG4gICAgICAgIHJldHVybiB0aGlzLnJlc29sdmVLZXllZChrZXkpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXNvbHZlIGFsbCByZWdpc3RyYXRpb25zIGZvciBhbiBpbnRlcmZhY2UgdHlwZVxuICAgICAqL1xuICAgIHJlc29sdmVUeXBlQWxsKHR5cGVOYW1lKSB7XG4gICAgICAgIGNvbnN0IHRva2VuID0gdGhpcy5pbnRlcmZhY2VUb2tlbih0eXBlTmFtZSk7XG4gICAgICAgIHJldHVybiB0aGlzLnJlc29sdmVBbGwodG9rZW4pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBJbnRlcm5hbDogUmVzb2x2ZSB3aXRoIGNvbnRleHQgZm9yIGNpcmN1bGFyIGRlcGVuZGVuY3kgZGV0ZWN0aW9uXG4gICAgICovXG4gICAgcmVzb2x2ZVdpdGhDb250ZXh0KHRva2VuLCBjb250ZXh0KSB7XG4gICAgICAgIC8vIFZhbGlkYXRlIGFuZCBnZXQgYmluZGluZyAod2l0aCBjaXJjdWxhciBkZXBlbmRlbmN5IGNoZWNrKVxuICAgICAgICBjb25zdCBiaW5kaW5nID0gdGhpcy52YWxpZGF0ZUFuZEdldEJpbmRpbmcodG9rZW4sIGNvbnRleHQpO1xuICAgICAgICAvLyBDaGVjayBwZXItcmVxdWVzdCBjYWNoZVxuICAgICAgICBpZiAoYmluZGluZy5saWZldGltZSA9PT0gJ3Blci1yZXF1ZXN0JyAmJiBjb250ZXh0Lmhhc1BlclJlcXVlc3QodG9rZW4pKSB7XG4gICAgICAgICAgICByZXR1cm4gY29udGV4dC5nZXRQZXJSZXF1ZXN0KHRva2VuKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBDaGVjayBzaW5nbGV0b24gY2FjaGUgKGxvY2FsIGNvbnRhaW5lciBvbmx5KVxuICAgICAgICBpZiAoYmluZGluZy5saWZldGltZSA9PT0gJ3NpbmdsZXRvbicgJiYgdGhpcy5zaW5nbGV0b25DYWNoZS5oYXModG9rZW4pKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zaW5nbGV0b25DYWNoZS5nZXQodG9rZW4pO1xuICAgICAgICB9XG4gICAgICAgIC8vIE1hcmsgYXMgcmVzb2x2aW5nXG4gICAgICAgIGNvbnRleHQuZW50ZXJSZXNvbHZlKHRva2VuKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIEluc3RhbnRpYXRlIGZyb20gYmluZGluZ1xuICAgICAgICAgICAgY29uc3QgaW5zdGFuY2UgPSB0aGlzLmluc3RhbnRpYXRlQmluZGluZ1N5bmMoYmluZGluZywgdG9rZW4sIGNvbnRleHQpO1xuICAgICAgICAgICAgLy8gQ2FjaGUgYmFzZWQgb24gbGlmZXRpbWVcbiAgICAgICAgICAgIHRoaXMuY2FjaGVJbnN0YW5jZSh0b2tlbiwgaW5zdGFuY2UsIGJpbmRpbmcubGlmZXRpbWUsIGNvbnRleHQpO1xuICAgICAgICAgICAgcmV0dXJuIGluc3RhbmNlO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkge1xuICAgICAgICAgICAgY29udGV4dC5leGl0UmVzb2x2ZSh0b2tlbik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogSW50ZXJuYWw6IEFzeW5jIHJlc29sdmUgd2l0aCBjb250ZXh0XG4gICAgICovXG4gICAgYXN5bmMgcmVzb2x2ZUFzeW5jV2l0aENvbnRleHQodG9rZW4sIGNvbnRleHQpIHtcbiAgICAgICAgLy8gVmFsaWRhdGUgYW5kIGdldCBiaW5kaW5nICh3aXRoIGNpcmN1bGFyIGRlcGVuZGVuY3kgY2hlY2spXG4gICAgICAgIGNvbnN0IGJpbmRpbmcgPSB0aGlzLnZhbGlkYXRlQW5kR2V0QmluZGluZyh0b2tlbiwgY29udGV4dCk7XG4gICAgICAgIC8vIENoZWNrIHBlci1yZXF1ZXN0IGNhY2hlXG4gICAgICAgIGlmIChiaW5kaW5nLmxpZmV0aW1lID09PSAncGVyLXJlcXVlc3QnICYmIGNvbnRleHQuaGFzUGVyUmVxdWVzdCh0b2tlbikpIHtcbiAgICAgICAgICAgIHJldHVybiBjb250ZXh0LmdldFBlclJlcXVlc3QodG9rZW4pO1xuICAgICAgICB9XG4gICAgICAgIC8vIENoZWNrIHNpbmdsZXRvbiBjYWNoZSAobG9jYWwgY29udGFpbmVyIG9ubHkpXG4gICAgICAgIGlmIChiaW5kaW5nLmxpZmV0aW1lID09PSAnc2luZ2xldG9uJyAmJiB0aGlzLnNpbmdsZXRvbkNhY2hlLmhhcyh0b2tlbikpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNpbmdsZXRvbkNhY2hlLmdldCh0b2tlbik7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTWFyayBhcyByZXNvbHZpbmdcbiAgICAgICAgY29udGV4dC5lbnRlclJlc29sdmUodG9rZW4pO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gSW5zdGFudGlhdGUgZnJvbSBiaW5kaW5nIGFzeW5jaHJvbm91c2x5XG4gICAgICAgICAgICBjb25zdCBpbnN0YW5jZSA9IGF3YWl0IHRoaXMuaW5zdGFudGlhdGVCaW5kaW5nQXN5bmMoYmluZGluZywgY29udGV4dCk7XG4gICAgICAgICAgICAvLyBDYWNoZSBiYXNlZCBvbiBsaWZldGltZVxuICAgICAgICAgICAgdGhpcy5jYWNoZUluc3RhbmNlKHRva2VuLCBpbnN0YW5jZSwgYmluZGluZy5saWZldGltZSwgY29udGV4dCk7XG4gICAgICAgICAgICByZXR1cm4gaW5zdGFuY2U7XG4gICAgICAgIH1cbiAgICAgICAgZmluYWxseSB7XG4gICAgICAgICAgICBjb250ZXh0LmV4aXRSZXNvbHZlKHRva2VuKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgYmluZGluZyBmcm9tIHRoaXMgY29udGFpbmVyIG9yIHBhcmVudCBjaGFpblxuICAgICAqIFBlcmZvcm1hbmNlIG9wdGltaXplZDogVXNlcyBmbGF0IGNhY2hlIHRvIGF2b2lkIHJlY3Vyc2l2ZSBwYXJlbnQgbG9va3Vwc1xuICAgICAqL1xuICAgIGdldEJpbmRpbmcodG9rZW4pIHtcbiAgICAgICAgLy8gQnVpbGQgZmxhdCBjYWNoZSBvbiBmaXJzdCBhY2Nlc3NcbiAgICAgICAgaWYgKCF0aGlzLmJpbmRpbmdDYWNoZSkge1xuICAgICAgICAgICAgdGhpcy5idWlsZEJpbmRpbmdDYWNoZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmJpbmRpbmdDYWNoZS5nZXQodG9rZW4pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBCdWlsZCBmbGF0IGNhY2hlIG9mIGFsbCBiaW5kaW5ncyBpbmNsdWRpbmcgcGFyZW50IGNoYWluXG4gICAgICogVGhpcyBjb252ZXJ0cyBPKG4pIHBhcmVudCBjaGFpbiB0cmF2ZXJzYWwgdG8gTygxKSBsb29rdXBcbiAgICAgKi9cbiAgICBidWlsZEJpbmRpbmdDYWNoZSgpIHtcbiAgICAgICAgdGhpcy5iaW5kaW5nQ2FjaGUgPSBuZXcgTWFwKCk7XG4gICAgICAgIC8vIFRyYXZlcnNlIHBhcmVudCBjaGFpbiBhbmQgZmxhdHRlbiBhbGwgYmluZGluZ3NcbiAgICAgICAgbGV0IGN1cnJlbnQgPSB0aGlzO1xuICAgICAgICB3aGlsZSAoY3VycmVudCkge1xuICAgICAgICAgICAgY3VycmVudC5iaW5kaW5ncy5mb3JFYWNoKChiaW5kaW5nLCB0b2tlbikgPT4ge1xuICAgICAgICAgICAgICAgIC8vIENoaWxkIGJpbmRpbmdzIG92ZXJyaWRlIHBhcmVudCBiaW5kaW5ncyAoZmlyc3Qgd2lucylcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuYmluZGluZ0NhY2hlLmhhcyh0b2tlbikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5iaW5kaW5nQ2FjaGUuc2V0KHRva2VuLCBiaW5kaW5nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGN1cnJlbnQgPSBjdXJyZW50LnBhcmVudDtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBJbnZhbGlkYXRlIGJpbmRpbmcgY2FjaGUgd2hlbiBuZXcgYmluZGluZ3MgYXJlIGFkZGVkXG4gICAgICogQ2FsbGVkIGJ5IGJpbmRWYWx1ZSwgYmluZEZhY3RvcnksIGJpbmRDbGFzc1xuICAgICAqL1xuICAgIGludmFsaWRhdGVCaW5kaW5nQ2FjaGUoKSB7XG4gICAgICAgIHRoaXMuYmluZGluZ0NhY2hlID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLnVsdHJhRmFzdFNpbmdsZXRvbkNhY2hlLmNsZWFyKCk7IC8vIENsZWFyIHVsdHJhLWZhc3QgY2FjaGUgd2hlbiBiaW5kaW5ncyBjaGFuZ2VcbiAgICB9XG59XG5Db250YWluZXIuY29udGV4dFBvb2wgPSBuZXcgUmVzb2x1dGlvbkNvbnRleHRQb29sKCk7IC8vIFBlcmZvcm1hbmNlOiBQb29sZWQgY29udGV4dHMgcmVkdWNlIGFsbG9jYXRpb25zXG4iLCAiZXhwb3J0IGNsYXNzIERhdGVSZW5kZXJlciB7XG4gICAgY29uc3RydWN0b3IoZGF0ZVNlcnZpY2UpIHtcbiAgICAgICAgdGhpcy5kYXRlU2VydmljZSA9IGRhdGVTZXJ2aWNlO1xuICAgICAgICB0aGlzLnR5cGUgPSAnZGF0ZSc7XG4gICAgfVxuICAgIHJlbmRlcihjb250ZXh0KSB7XG4gICAgICAgIGNvbnN0IGRhdGVzID0gY29udGV4dC5maWx0ZXJbJ2RhdGUnXSB8fCBbXTtcbiAgICAgICAgY29uc3QgcmVzb3VyY2VJZHMgPSBjb250ZXh0LmZpbHRlclsncmVzb3VyY2UnXSB8fCBbXTtcbiAgICAgICAgLy8gQ2hlY2sgaWYgZGF0ZSBoZWFkZXJzIHNob3VsZCBiZSBoaWRkZW4gKGUuZy4sIGluIGRheSB2aWV3KVxuICAgICAgICBjb25zdCBkYXRlR3JvdXBpbmcgPSBjb250ZXh0Lmdyb3VwaW5ncz8uZmluZChnID0+IGcudHlwZSA9PT0gJ2RhdGUnKTtcbiAgICAgICAgY29uc3QgaGlkZUhlYWRlciA9IGRhdGVHcm91cGluZz8uaGlkZUhlYWRlciA9PT0gdHJ1ZTtcbiAgICAgICAgLy8gUmVuZGVyIGRhdGVzIGZvciBIVkVSIHJlc291cmNlIChlbGxlciAxIGdhbmcgaHZpcyBpbmdlbiByZXNvdXJjZXMpXG4gICAgICAgIGNvbnN0IGl0ZXJhdGlvbnMgPSByZXNvdXJjZUlkcy5sZW5ndGggfHwgMTtcbiAgICAgICAgbGV0IGNvbHVtbkNvdW50ID0gMDtcbiAgICAgICAgZm9yIChsZXQgciA9IDA7IHIgPCBpdGVyYXRpb25zOyByKyspIHtcbiAgICAgICAgICAgIGNvbnN0IHJlc291cmNlSWQgPSByZXNvdXJjZUlkc1tyXTsgLy8gdW5kZWZpbmVkIGh2aXMgaW5nZW4gcmVzb3VyY2VzXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGRhdGVTdHIgb2YgZGF0ZXMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRlID0gdGhpcy5kYXRlU2VydmljZS5wYXJzZUlTTyhkYXRlU3RyKTtcbiAgICAgICAgICAgICAgICAvLyBCdWlsZCBjb2x1bW5LZXkgZm9yIHVuaWZvcm0gaWRlbnRpZmljYXRpb25cbiAgICAgICAgICAgICAgICBjb25zdCBzZWdtZW50cyA9IHsgZGF0ZTogZGF0ZVN0ciB9O1xuICAgICAgICAgICAgICAgIGlmIChyZXNvdXJjZUlkKVxuICAgICAgICAgICAgICAgICAgICBzZWdtZW50cy5yZXNvdXJjZSA9IHJlc291cmNlSWQ7XG4gICAgICAgICAgICAgICAgY29uc3QgY29sdW1uS2V5ID0gdGhpcy5kYXRlU2VydmljZS5idWlsZENvbHVtbktleShzZWdtZW50cyk7XG4gICAgICAgICAgICAgICAgLy8gSGVhZGVyXG4gICAgICAgICAgICAgICAgY29uc3QgaGVhZGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3dwLWRheS1oZWFkZXInKTtcbiAgICAgICAgICAgICAgICBoZWFkZXIuZGF0YXNldC5kYXRlID0gZGF0ZVN0cjtcbiAgICAgICAgICAgICAgICBoZWFkZXIuZGF0YXNldC5jb2x1bW5LZXkgPSBjb2x1bW5LZXk7XG4gICAgICAgICAgICAgICAgaWYgKHJlc291cmNlSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaGVhZGVyLmRhdGFzZXQucmVzb3VyY2VJZCA9IHJlc291cmNlSWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChoaWRlSGVhZGVyKSB7XG4gICAgICAgICAgICAgICAgICAgIGhlYWRlci5kYXRhc2V0LmhpZGRlbiA9ICd0cnVlJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaGVhZGVyLmlubmVySFRNTCA9IGBcclxuICAgICAgICAgIDxzd3AtZGF5LW5hbWU+JHt0aGlzLmRhdGVTZXJ2aWNlLmdldERheU5hbWUoZGF0ZSwgJ3Nob3J0Jyl9PC9zd3AtZGF5LW5hbWU+XHJcbiAgICAgICAgICA8c3dwLWRheS1kYXRlPiR7ZGF0ZS5nZXREYXRlKCl9PC9zd3AtZGF5LWRhdGU+XHJcbiAgICAgICAgYDtcbiAgICAgICAgICAgICAgICBjb250ZXh0LmhlYWRlckNvbnRhaW5lci5hcHBlbmRDaGlsZChoZWFkZXIpO1xuICAgICAgICAgICAgICAgIC8vIENvbHVtblxuICAgICAgICAgICAgICAgIGNvbnN0IGNvbHVtbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3N3cC1kYXktY29sdW1uJyk7XG4gICAgICAgICAgICAgICAgY29sdW1uLmRhdGFzZXQuZGF0ZSA9IGRhdGVTdHI7XG4gICAgICAgICAgICAgICAgY29sdW1uLmRhdGFzZXQuY29sdW1uS2V5ID0gY29sdW1uS2V5O1xuICAgICAgICAgICAgICAgIGlmIChyZXNvdXJjZUlkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbi5kYXRhc2V0LnJlc291cmNlSWQgPSByZXNvdXJjZUlkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb2x1bW4uaW5uZXJIVE1MID0gJzxzd3AtZXZlbnRzLWxheWVyPjwvc3dwLWV2ZW50cy1sYXllcj4nO1xuICAgICAgICAgICAgICAgIGNvbnRleHQuY29sdW1uQ29udGFpbmVyLmFwcGVuZENoaWxkKGNvbHVtbik7XG4gICAgICAgICAgICAgICAgY29sdW1uQ291bnQrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBTZXQgZ3JpZCBjb2x1bW5zIG9uIGNvbnRhaW5lclxuICAgICAgICBjb25zdCBjb250YWluZXIgPSBjb250ZXh0LmNvbHVtbkNvbnRhaW5lci5jbG9zZXN0KCdzd3AtY2FsZW5kYXItY29udGFpbmVyJyk7XG4gICAgICAgIGlmIChjb250YWluZXIpIHtcbiAgICAgICAgICAgIGNvbnRhaW5lci5zdHlsZS5zZXRQcm9wZXJ0eSgnLS1ncmlkLWNvbHVtbnMnLCBTdHJpbmcoY29sdW1uQ291bnQpKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsICJpbXBvcnQgZGF5anMgZnJvbSAnZGF5anMnO1xuaW1wb3J0IHV0YyBmcm9tICdkYXlqcy9wbHVnaW4vdXRjJztcbmltcG9ydCB0aW1lem9uZSBmcm9tICdkYXlqcy9wbHVnaW4vdGltZXpvbmUnO1xuaW1wb3J0IGlzb1dlZWsgZnJvbSAnZGF5anMvcGx1Z2luL2lzb1dlZWsnO1xuLy8gRW5hYmxlIGRheWpzIHBsdWdpbnNcbmRheWpzLmV4dGVuZCh1dGMpO1xuZGF5anMuZXh0ZW5kKHRpbWV6b25lKTtcbmRheWpzLmV4dGVuZChpc29XZWVrKTtcbmV4cG9ydCBjbGFzcyBEYXRlU2VydmljZSB7XG4gICAgY29uc3RydWN0b3IoY29uZmlnLCBiYXNlRGF0ZSkge1xuICAgICAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcbiAgICAgICAgdGhpcy50aW1lem9uZSA9IGNvbmZpZy50aW1lem9uZTtcbiAgICAgICAgLy8gQWxsb3cgc2V0dGluZyBhIGZpeGVkIGJhc2UgZGF0ZSBmb3IgZGVtby90ZXN0aW5nIHB1cnBvc2VzXG4gICAgICAgIHRoaXMuYmFzZURhdGUgPSBiYXNlRGF0ZSA/IGRheWpzKGJhc2VEYXRlKSA6IGRheWpzKCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNldCBhIGZpeGVkIGJhc2UgZGF0ZSAodXNlZnVsIGZvciBkZW1vcyB3aXRoIHN0YXRpYyBtb2NrIGRhdGEpXG4gICAgICovXG4gICAgc2V0QmFzZURhdGUoZGF0ZSkge1xuICAgICAgICB0aGlzLmJhc2VEYXRlID0gZGF5anMoZGF0ZSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgY3VycmVudCBiYXNlIGRhdGUgKGVpdGhlciBmaXhlZCBvciB0b2RheSlcbiAgICAgKi9cbiAgICBnZXRCYXNlRGF0ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYmFzZURhdGUudG9EYXRlKCk7XG4gICAgfVxuICAgIHBhcnNlSVNPKGlzb1N0cmluZykge1xuICAgICAgICByZXR1cm4gZGF5anMoaXNvU3RyaW5nKS50b0RhdGUoKTtcbiAgICB9XG4gICAgZ2V0RGF5TmFtZShkYXRlLCBmb3JtYXQgPSAnc2hvcnQnKSB7XG4gICAgICAgIHJldHVybiBuZXcgSW50bC5EYXRlVGltZUZvcm1hdCh0aGlzLmNvbmZpZy5sb2NhbGUsIHsgd2Vla2RheTogZm9ybWF0IH0pLmZvcm1hdChkYXRlKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGRhdGVzIHN0YXJ0aW5nIGZyb20gYSBkYXkgb2Zmc2V0XG4gICAgICogQHBhcmFtIGRheU9mZnNldCAtIERheSBvZmZzZXQgZnJvbSBiYXNlIGRhdGVcbiAgICAgKiBAcGFyYW0gY291bnQgLSBOdW1iZXIgb2YgY29uc2VjdXRpdmUgZGF5cyB0byByZXR1cm5cbiAgICAgKiBAcmV0dXJucyBBcnJheSBvZiBkYXRlIHN0cmluZ3MgaW4gWVlZWS1NTS1ERCBmb3JtYXRcbiAgICAgKi9cbiAgICBnZXREYXRlc0Zyb21PZmZzZXQoZGF5T2Zmc2V0LCBjb3VudCkge1xuICAgICAgICBjb25zdCBzdGFydERhdGUgPSB0aGlzLmJhc2VEYXRlLmFkZChkYXlPZmZzZXQsICdkYXknKTtcbiAgICAgICAgcmV0dXJuIEFycmF5LmZyb20oeyBsZW5ndGg6IGNvdW50IH0sIChfLCBpKSA9PiBzdGFydERhdGUuYWRkKGksICdkYXknKS5mb3JtYXQoJ1lZWVktTU0tREQnKSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBzcGVjaWZpYyB3ZWVrZGF5cyBmcm9tIHRoZSB3ZWVrIGNvbnRhaW5pbmcgdGhlIG9mZnNldCBkYXRlXG4gICAgICogQHBhcmFtIGRheU9mZnNldCAtIERheSBvZmZzZXQgZnJvbSBiYXNlIGRhdGVcbiAgICAgKiBAcGFyYW0gd29ya0RheXMgLSBBcnJheSBvZiBJU08gd2Vla2RheSBudW1iZXJzICgxPU1vbmRheSwgNz1TdW5kYXkpXG4gICAgICogQHJldHVybnMgQXJyYXkgb2YgZGF0ZSBzdHJpbmdzIGluIFlZWVktTU0tREQgZm9ybWF0XG4gICAgICovXG4gICAgZ2V0V29ya0RheXNGcm9tT2Zmc2V0KGRheU9mZnNldCwgd29ya0RheXMpIHtcbiAgICAgICAgLy8gR2V0IHRoZSBkYXRlIGF0IG9mZnNldCwgdGhlbiBmaW5kIGl0cyB3ZWVrJ3MgTW9uZGF5XG4gICAgICAgIGNvbnN0IHRhcmdldERhdGUgPSB0aGlzLmJhc2VEYXRlLmFkZChkYXlPZmZzZXQsICdkYXknKTtcbiAgICAgICAgY29uc3QgbW9uZGF5ID0gdGFyZ2V0RGF0ZS5zdGFydE9mKCd3ZWVrJykuYWRkKDEsICdkYXknKTtcbiAgICAgICAgcmV0dXJuIHdvcmtEYXlzLm1hcChpc29EYXkgPT4ge1xuICAgICAgICAgICAgLy8gSVNPOiAxPU1vbmRheSwgNz1TdW5kYXkgXHUyMTkyIGRheXMgZnJvbSBNb25kYXk6IDAtNlxuICAgICAgICAgICAgY29uc3QgZGF5c0Zyb21Nb25kYXkgPSBpc29EYXkgPT09IDcgPyA2IDogaXNvRGF5IC0gMTtcbiAgICAgICAgICAgIHJldHVybiBtb25kYXkuYWRkKGRheXNGcm9tTW9uZGF5LCAnZGF5JykuZm9ybWF0KCdZWVlZLU1NLUREJyk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBMZWdhY3kgbWV0aG9kcyBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHlcbiAgICBnZXRXZWVrRGF0ZXMod2Vla09mZnNldCA9IDAsIGRheXMgPSA3KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldERhdGVzRnJvbU9mZnNldCh3ZWVrT2Zmc2V0ICogNywgZGF5cyk7XG4gICAgfVxuICAgIGdldFdvcmtXZWVrRGF0ZXMod2Vla09mZnNldCwgd29ya0RheXMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0V29ya0RheXNGcm9tT2Zmc2V0KHdlZWtPZmZzZXQgKiA3LCB3b3JrRGF5cyk7XG4gICAgfVxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gRk9STUFUVElOR1xuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgZm9ybWF0VGltZShkYXRlLCBzaG93U2Vjb25kcyA9IGZhbHNlKSB7XG4gICAgICAgIGNvbnN0IHBhdHRlcm4gPSBzaG93U2Vjb25kcyA/ICdISDptbTpzcycgOiAnSEg6bW0nO1xuICAgICAgICByZXR1cm4gZGF5anMoZGF0ZSkuZm9ybWF0KHBhdHRlcm4pO1xuICAgIH1cbiAgICBmb3JtYXRUaW1lUmFuZ2Uoc3RhcnQsIGVuZCkge1xuICAgICAgICByZXR1cm4gYCR7dGhpcy5mb3JtYXRUaW1lKHN0YXJ0KX0gLSAke3RoaXMuZm9ybWF0VGltZShlbmQpfWA7XG4gICAgfVxuICAgIGZvcm1hdERhdGUoZGF0ZSkge1xuICAgICAgICByZXR1cm4gZGF5anMoZGF0ZSkuZm9ybWF0KCdZWVlZLU1NLUREJyk7XG4gICAgfVxuICAgIGdldERhdGVLZXkoZGF0ZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5mb3JtYXREYXRlKGRhdGUpO1xuICAgIH1cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIENPTFVNTiBLRVlcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8qKlxuICAgICAqIEJ1aWxkIGEgdW5pZm9ybSBjb2x1bW5LZXkgZnJvbSBncm91cGluZyBzZWdtZW50c1xuICAgICAqIEhhbmRsZXMgYW55IGNvbWJpbmF0aW9uIG9mIGRhdGUsIHJlc291cmNlLCB0ZWFtLCBldGMuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGJ1aWxkQ29sdW1uS2V5KHsgZGF0ZTogJzIwMjUtMTItMDknIH0pIFx1MjE5MiBcIjIwMjUtMTItMDlcIlxuICAgICAqIGJ1aWxkQ29sdW1uS2V5KHsgZGF0ZTogJzIwMjUtMTItMDknLCByZXNvdXJjZTogJ0VNUDAwMScgfSkgXHUyMTkyIFwiMjAyNS0xMi0wOTpFTVAwMDFcIlxuICAgICAqL1xuICAgIGJ1aWxkQ29sdW1uS2V5KHNlZ21lbnRzKSB7XG4gICAgICAgIC8vIEFsd2F5cyBwdXQgZGF0ZSBmaXJzdCBpZiBwcmVzZW50LCB0aGVuIG90aGVyIHNlZ21lbnRzIGFscGhhYmV0aWNhbGx5XG4gICAgICAgIGNvbnN0IGRhdGUgPSBzZWdtZW50cy5kYXRlO1xuICAgICAgICBjb25zdCBvdGhlcnMgPSBPYmplY3QuZW50cmllcyhzZWdtZW50cylcbiAgICAgICAgICAgIC5maWx0ZXIoKFtrXSkgPT4gayAhPT0gJ2RhdGUnKVxuICAgICAgICAgICAgLnNvcnQoKFthXSwgW2JdKSA9PiBhLmxvY2FsZUNvbXBhcmUoYikpXG4gICAgICAgICAgICAubWFwKChbLCB2XSkgPT4gdik7XG4gICAgICAgIHJldHVybiBkYXRlID8gW2RhdGUsIC4uLm90aGVyc10uam9pbignOicpIDogb3RoZXJzLmpvaW4oJzonKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUGFyc2UgYSBjb2x1bW5LZXkgYmFjayBpbnRvIHNlZ21lbnRzXG4gICAgICogQXNzdW1lcyBmb3JtYXQ6IFwiZGF0ZTpyZXNvdXJjZTouLi5cIiBvciBqdXN0IFwiZGF0ZVwiXG4gICAgICovXG4gICAgcGFyc2VDb2x1bW5LZXkoY29sdW1uS2V5KSB7XG4gICAgICAgIGNvbnN0IHBhcnRzID0gY29sdW1uS2V5LnNwbGl0KCc6Jyk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBkYXRlOiBwYXJ0c1swXSxcbiAgICAgICAgICAgIHJlc291cmNlOiBwYXJ0c1sxXVxuICAgICAgICB9O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBFeHRyYWN0IGRhdGVLZXkgZnJvbSBjb2x1bW5LZXkgKGZpcnN0IHNlZ21lbnQpXG4gICAgICovXG4gICAgZ2V0RGF0ZUZyb21Db2x1bW5LZXkoY29sdW1uS2V5KSB7XG4gICAgICAgIHJldHVybiBjb2x1bW5LZXkuc3BsaXQoJzonKVswXTtcbiAgICB9XG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBUSU1FIENBTENVTEFUSU9OU1xuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgdGltZVRvTWludXRlcyh0aW1lU3RyaW5nKSB7XG4gICAgICAgIGNvbnN0IHBhcnRzID0gdGltZVN0cmluZy5zcGxpdCgnOicpLm1hcChOdW1iZXIpO1xuICAgICAgICBjb25zdCBob3VycyA9IHBhcnRzWzBdIHx8IDA7XG4gICAgICAgIGNvbnN0IG1pbnV0ZXMgPSBwYXJ0c1sxXSB8fCAwO1xuICAgICAgICByZXR1cm4gaG91cnMgKiA2MCArIG1pbnV0ZXM7XG4gICAgfVxuICAgIG1pbnV0ZXNUb1RpbWUodG90YWxNaW51dGVzKSB7XG4gICAgICAgIGNvbnN0IGhvdXJzID0gTWF0aC5mbG9vcih0b3RhbE1pbnV0ZXMgLyA2MCk7XG4gICAgICAgIGNvbnN0IG1pbnV0ZXMgPSB0b3RhbE1pbnV0ZXMgJSA2MDtcbiAgICAgICAgcmV0dXJuIGRheWpzKCkuaG91cihob3VycykubWludXRlKG1pbnV0ZXMpLmZvcm1hdCgnSEg6bW0nKTtcbiAgICB9XG4gICAgZ2V0TWludXRlc1NpbmNlTWlkbmlnaHQoZGF0ZSkge1xuICAgICAgICBjb25zdCBkID0gZGF5anMoZGF0ZSk7XG4gICAgICAgIHJldHVybiBkLmhvdXIoKSAqIDYwICsgZC5taW51dGUoKTtcbiAgICB9XG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBVVEMgQ09OVkVSU0lPTlNcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIHRvVVRDKGxvY2FsRGF0ZSkge1xuICAgICAgICByZXR1cm4gZGF5anMudHoobG9jYWxEYXRlLCB0aGlzLnRpbWV6b25lKS51dGMoKS50b0lTT1N0cmluZygpO1xuICAgIH1cbiAgICBmcm9tVVRDKHV0Y1N0cmluZykge1xuICAgICAgICByZXR1cm4gZGF5anMudXRjKHV0Y1N0cmluZykudHoodGhpcy50aW1lem9uZSkudG9EYXRlKCk7XG4gICAgfVxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gREFURSBDUkVBVElPTlxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgY3JlYXRlRGF0ZUF0VGltZShiYXNlRGF0ZSwgdGltZVN0cmluZykge1xuICAgICAgICBjb25zdCB0b3RhbE1pbnV0ZXMgPSB0aGlzLnRpbWVUb01pbnV0ZXModGltZVN0cmluZyk7XG4gICAgICAgIGNvbnN0IGhvdXJzID0gTWF0aC5mbG9vcih0b3RhbE1pbnV0ZXMgLyA2MCk7XG4gICAgICAgIGNvbnN0IG1pbnV0ZXMgPSB0b3RhbE1pbnV0ZXMgJSA2MDtcbiAgICAgICAgcmV0dXJuIGRheWpzKGJhc2VEYXRlKS5zdGFydE9mKCdkYXknKS5ob3VyKGhvdXJzKS5taW51dGUobWludXRlcykudG9EYXRlKCk7XG4gICAgfVxuICAgIGdldElTT1dlZWtEYXkoZGF0ZSkge1xuICAgICAgICByZXR1cm4gZGF5anMoZGF0ZSkuaXNvV2Vla2RheSgpOyAvLyAxPU1vbmRheSwgNz1TdW5kYXlcbiAgICB9XG59XG4iLCAiLyoqXG4gKiBBYnN0cmFjdCBiYXNlIGNsYXNzIGZvciBncm91cGluZyByZW5kZXJlcnNcbiAqXG4gKiBIYW5kbGVzOlxuICogLSBGZXRjaGluZyBlbnRpdGllcyBieSBJRHNcbiAqIC0gQ2FsY3VsYXRpbmcgY29sc3BhbiBmcm9tIHBhcmVudENoaWxkTWFwXG4gKiAtIENyZWF0aW5nIGhlYWRlciBlbGVtZW50c1xuICogLSBBcHBlbmRpbmcgdG8gY29udGFpbmVyXG4gKlxuICogU3ViY2xhc3NlcyBvdmVycmlkZTpcbiAqIC0gcmVuZGVySGVhZGVyKCkgZm9yIGN1c3RvbSBjb250ZW50XG4gKiAtIGdldERpc3BsYXlOYW1lKCkgZm9yIGVudGl0eSBkaXNwbGF5IHRleHRcbiAqL1xuZXhwb3J0IGNsYXNzIEJhc2VHcm91cGluZ1JlbmRlcmVyIHtcbiAgICAvKipcbiAgICAgKiBNYWluIHJlbmRlciBtZXRob2QgLSBoYW5kbGVzIGNvbW1vbiBsb2dpY1xuICAgICAqL1xuICAgIGFzeW5jIHJlbmRlcihjb250ZXh0KSB7XG4gICAgICAgIGNvbnN0IGFsbG93ZWRJZHMgPSBjb250ZXh0LmZpbHRlclt0aGlzLnR5cGVdIHx8IFtdO1xuICAgICAgICBpZiAoYWxsb3dlZElkcy5sZW5ndGggPT09IDApXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNvbnN0IGVudGl0aWVzID0gYXdhaXQgdGhpcy5nZXRFbnRpdGllcyhhbGxvd2VkSWRzKTtcbiAgICAgICAgY29uc3QgZGF0ZUNvdW50ID0gY29udGV4dC5maWx0ZXJbJ2RhdGUnXT8ubGVuZ3RoIHx8IDE7XG4gICAgICAgIGNvbnN0IGNoaWxkSWRzID0gY29udGV4dC5jaGlsZFR5cGUgPyBjb250ZXh0LmZpbHRlcltjb250ZXh0LmNoaWxkVHlwZV0gfHwgW10gOiBbXTtcbiAgICAgICAgZm9yIChjb25zdCBlbnRpdHkgb2YgZW50aXRpZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IGVudGl0eUNoaWxkSWRzID0gY29udGV4dC5wYXJlbnRDaGlsZE1hcD8uW2VudGl0eS5pZF0gfHwgW107XG4gICAgICAgICAgICBjb25zdCBjaGlsZENvdW50ID0gZW50aXR5Q2hpbGRJZHMuZmlsdGVyKGlkID0+IGNoaWxkSWRzLmluY2x1ZGVzKGlkKSkubGVuZ3RoO1xuICAgICAgICAgICAgY29uc3QgY29sc3BhbiA9IGNoaWxkQ291bnQgKiBkYXRlQ291bnQ7XG4gICAgICAgICAgICBjb25zdCBoZWFkZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KHRoaXMuY29uZmlnLmVsZW1lbnRUYWcpO1xuICAgICAgICAgICAgaGVhZGVyLmRhdGFzZXRbdGhpcy5jb25maWcuaWRBdHRyaWJ1dGVdID0gZW50aXR5LmlkO1xuICAgICAgICAgICAgaGVhZGVyLnN0eWxlLnNldFByb3BlcnR5KHRoaXMuY29uZmlnLmNvbHNwYW5WYXIsIFN0cmluZyhjb2xzcGFuKSk7XG4gICAgICAgICAgICAvLyBBbGxvdyBzdWJjbGFzcyB0byBjdXN0b21pemUgaGVhZGVyIGNvbnRlbnRcbiAgICAgICAgICAgIHRoaXMucmVuZGVySGVhZGVyKGVudGl0eSwgaGVhZGVyLCBjb250ZXh0KTtcbiAgICAgICAgICAgIGNvbnRleHQuaGVhZGVyQ29udGFpbmVyLmFwcGVuZENoaWxkKGhlYWRlcik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogT3ZlcnJpZGUgdGhpcyBtZXRob2QgZm9yIGN1c3RvbSBoZWFkZXIgcmVuZGVyaW5nXG4gICAgICogRGVmYXVsdDoganVzdCBzZXRzIHRleHRDb250ZW50IHRvIGRpc3BsYXkgbmFtZVxuICAgICAqL1xuICAgIHJlbmRlckhlYWRlcihlbnRpdHksIGhlYWRlciwgX2NvbnRleHQpIHtcbiAgICAgICAgaGVhZGVyLnRleHRDb250ZW50ID0gdGhpcy5nZXREaXNwbGF5TmFtZShlbnRpdHkpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBIZWxwZXIgdG8gcmVuZGVyIGEgc2luZ2xlIGVudGl0eSBoZWFkZXIuXG4gICAgICogQ2FuIGJlIHVzZWQgYnkgc3ViY2xhc3NlcyB0aGF0IG92ZXJyaWRlIHJlbmRlcigpIGJ1dCB3YW50IGNvbnNpc3RlbnQgaGVhZGVyIGNyZWF0aW9uLlxuICAgICAqL1xuICAgIGNyZWF0ZUhlYWRlcihlbnRpdHksIGNvbnRleHQpIHtcbiAgICAgICAgY29uc3QgaGVhZGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0aGlzLmNvbmZpZy5lbGVtZW50VGFnKTtcbiAgICAgICAgaGVhZGVyLmRhdGFzZXRbdGhpcy5jb25maWcuaWRBdHRyaWJ1dGVdID0gZW50aXR5LmlkO1xuICAgICAgICB0aGlzLnJlbmRlckhlYWRlcihlbnRpdHksIGhlYWRlciwgY29udGV4dCk7XG4gICAgICAgIHJldHVybiBoZWFkZXI7XG4gICAgfVxufVxuIiwgImltcG9ydCB7IEJhc2VHcm91cGluZ1JlbmRlcmVyIH0gZnJvbSAnLi4vLi4vY29yZS9CYXNlR3JvdXBpbmdSZW5kZXJlcic7XG5leHBvcnQgY2xhc3MgUmVzb3VyY2VSZW5kZXJlciBleHRlbmRzIEJhc2VHcm91cGluZ1JlbmRlcmVyIHtcbiAgICBjb25zdHJ1Y3RvcihyZXNvdXJjZVNlcnZpY2UpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5yZXNvdXJjZVNlcnZpY2UgPSByZXNvdXJjZVNlcnZpY2U7XG4gICAgICAgIHRoaXMudHlwZSA9ICdyZXNvdXJjZSc7XG4gICAgICAgIHRoaXMuY29uZmlnID0ge1xuICAgICAgICAgICAgZWxlbWVudFRhZzogJ3N3cC1yZXNvdXJjZS1oZWFkZXInLFxuICAgICAgICAgICAgaWRBdHRyaWJ1dGU6ICdyZXNvdXJjZUlkJyxcbiAgICAgICAgICAgIGNvbHNwYW5WYXI6ICctLXJlc291cmNlLWNvbHMnXG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldEVudGl0aWVzKGlkcykge1xuICAgICAgICByZXR1cm4gdGhpcy5yZXNvdXJjZVNlcnZpY2UuZ2V0QnlJZHMoaWRzKTtcbiAgICB9XG4gICAgZ2V0RGlzcGxheU5hbWUoZW50aXR5KSB7XG4gICAgICAgIHJldHVybiBlbnRpdHkuZGlzcGxheU5hbWU7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIE92ZXJyaWRlIHJlbmRlciB0byBoYW5kbGU6XG4gICAgICogMS4gU3BlY2lhbCBvcmRlcmluZyB3aGVuIHBhcmVudENoaWxkTWFwIGV4aXN0cyAocmVzb3VyY2VzIGdyb3VwZWQgYnkgcGFyZW50KVxuICAgICAqIDIuIERpZmZlcmVudCBjb2xzcGFuIGNhbGN1bGF0aW9uIChqdXN0IGRhdGVDb3VudCwgbm90IGNoaWxkQ291bnQgKiBkYXRlQ291bnQpXG4gICAgICovXG4gICAgYXN5bmMgcmVuZGVyKGNvbnRleHQpIHtcbiAgICAgICAgY29uc3QgcmVzb3VyY2VJZHMgPSBjb250ZXh0LmZpbHRlclsncmVzb3VyY2UnXSB8fCBbXTtcbiAgICAgICAgY29uc3QgZGF0ZUNvdW50ID0gY29udGV4dC5maWx0ZXJbJ2RhdGUnXT8ubGVuZ3RoIHx8IDE7XG4gICAgICAgIC8vIERldGVybWluZSByZW5kZXIgb3JkZXIgYmFzZWQgb24gcGFyZW50Q2hpbGRNYXBcbiAgICAgICAgLy8gSWYgcGFyZW50Q2hpbGRNYXAgZXhpc3RzLCByZW5kZXIgcmVzb3VyY2VzIGdyb3VwZWQgYnkgcGFyZW50IChlLmcuLCB0ZWFtKVxuICAgICAgICAvLyBPdGhlcndpc2UsIHJlbmRlciBpbiBmaWx0ZXIgb3JkZXJcbiAgICAgICAgbGV0IG9yZGVyZWRSZXNvdXJjZUlkcztcbiAgICAgICAgaWYgKGNvbnRleHQucGFyZW50Q2hpbGRNYXApIHtcbiAgICAgICAgICAgIC8vIFJlbmRlciByZXNvdXJjZXMgaW4gcGFyZW50LWNoaWxkIG9yZGVyXG4gICAgICAgICAgICBvcmRlcmVkUmVzb3VyY2VJZHMgPSBbXTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgY2hpbGRJZHMgb2YgT2JqZWN0LnZhbHVlcyhjb250ZXh0LnBhcmVudENoaWxkTWFwKSkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgY2hpbGRJZCBvZiBjaGlsZElkcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzb3VyY2VJZHMuaW5jbHVkZXMoY2hpbGRJZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWRSZXNvdXJjZUlkcy5wdXNoKGNoaWxkSWQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgb3JkZXJlZFJlc291cmNlSWRzID0gcmVzb3VyY2VJZHM7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcmVzb3VyY2VzID0gYXdhaXQgdGhpcy5nZXRFbnRpdGllcyhvcmRlcmVkUmVzb3VyY2VJZHMpO1xuICAgICAgICAvLyBDcmVhdGUgYSBtYXAgZm9yIHF1aWNrIGxvb2t1cCB0byBwcmVzZXJ2ZSBvcmRlclxuICAgICAgICBjb25zdCByZXNvdXJjZU1hcCA9IG5ldyBNYXAocmVzb3VyY2VzLm1hcChyID0+IFtyLmlkLCByXSkpO1xuICAgICAgICBmb3IgKGNvbnN0IHJlc291cmNlSWQgb2Ygb3JkZXJlZFJlc291cmNlSWRzKSB7XG4gICAgICAgICAgICBjb25zdCByZXNvdXJjZSA9IHJlc291cmNlTWFwLmdldChyZXNvdXJjZUlkKTtcbiAgICAgICAgICAgIGlmICghcmVzb3VyY2UpXG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICBjb25zdCBoZWFkZXIgPSB0aGlzLmNyZWF0ZUhlYWRlcihyZXNvdXJjZSwgY29udGV4dCk7XG4gICAgICAgICAgICBoZWFkZXIuc3R5bGUuZ3JpZENvbHVtbiA9IGBzcGFuICR7ZGF0ZUNvdW50fWA7XG4gICAgICAgICAgICBjb250ZXh0LmhlYWRlckNvbnRhaW5lci5hcHBlbmRDaGlsZChoZWFkZXIpO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwgImltcG9ydCB7IEJhc2VHcm91cGluZ1JlbmRlcmVyIH0gZnJvbSAnLi4vLi4vY29yZS9CYXNlR3JvdXBpbmdSZW5kZXJlcic7XG5leHBvcnQgY2xhc3MgVGVhbVJlbmRlcmVyIGV4dGVuZHMgQmFzZUdyb3VwaW5nUmVuZGVyZXIge1xuICAgIGNvbnN0cnVjdG9yKHRlYW1TZXJ2aWNlKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMudGVhbVNlcnZpY2UgPSB0ZWFtU2VydmljZTtcbiAgICAgICAgdGhpcy50eXBlID0gJ3RlYW0nO1xuICAgICAgICB0aGlzLmNvbmZpZyA9IHtcbiAgICAgICAgICAgIGVsZW1lbnRUYWc6ICdzd3AtdGVhbS1oZWFkZXInLFxuICAgICAgICAgICAgaWRBdHRyaWJ1dGU6ICd0ZWFtSWQnLFxuICAgICAgICAgICAgY29sc3BhblZhcjogJy0tdGVhbS1jb2xzJ1xuICAgICAgICB9O1xuICAgIH1cbiAgICBnZXRFbnRpdGllcyhpZHMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGVhbVNlcnZpY2UuZ2V0QnlJZHMoaWRzKTtcbiAgICB9XG4gICAgZ2V0RGlzcGxheU5hbWUoZW50aXR5KSB7XG4gICAgICAgIHJldHVybiBlbnRpdHkubmFtZTtcbiAgICB9XG59XG4iLCAiaW1wb3J0IHsgQmFzZUdyb3VwaW5nUmVuZGVyZXIgfSBmcm9tICcuLi8uLi9jb3JlL0Jhc2VHcm91cGluZ1JlbmRlcmVyJztcbmV4cG9ydCBjbGFzcyBEZXBhcnRtZW50UmVuZGVyZXIgZXh0ZW5kcyBCYXNlR3JvdXBpbmdSZW5kZXJlciB7XG4gICAgY29uc3RydWN0b3IoZGVwYXJ0bWVudFNlcnZpY2UpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5kZXBhcnRtZW50U2VydmljZSA9IGRlcGFydG1lbnRTZXJ2aWNlO1xuICAgICAgICB0aGlzLnR5cGUgPSAnZGVwYXJ0bWVudCc7XG4gICAgICAgIHRoaXMuY29uZmlnID0ge1xuICAgICAgICAgICAgZWxlbWVudFRhZzogJ3N3cC1kZXBhcnRtZW50LWhlYWRlcicsXG4gICAgICAgICAgICBpZEF0dHJpYnV0ZTogJ2RlcGFydG1lbnRJZCcsXG4gICAgICAgICAgICBjb2xzcGFuVmFyOiAnLS1kZXBhcnRtZW50LWNvbHMnXG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldEVudGl0aWVzKGlkcykge1xuICAgICAgICByZXR1cm4gdGhpcy5kZXBhcnRtZW50U2VydmljZS5nZXRCeUlkcyhpZHMpO1xuICAgIH1cbiAgICBnZXREaXNwbGF5TmFtZShlbnRpdHkpIHtcbiAgICAgICAgcmV0dXJuIGVudGl0eS5uYW1lO1xuICAgIH1cbn1cbiIsICJleHBvcnQgZnVuY3Rpb24gYnVpbGRQaXBlbGluZShyZW5kZXJlcnMpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBhc3luYyBydW4oY29udGV4dCkge1xuICAgICAgICAgICAgZm9yIChjb25zdCByZW5kZXJlciBvZiByZW5kZXJlcnMpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCByZW5kZXJlci5yZW5kZXIoY29udGV4dCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xufVxuIiwgIi8qKlxuICogRmlsdGVyVGVtcGxhdGUgLSBCeWdnZXIgblx1MDBGOGdsZXIgdGlsIGV2ZW50LWtvbG9ubmUgbWF0Y2hpbmdcbiAqXG4gKiBWaWV3Q29uZmlnIGRlZmluZXJlciBodmlsa2UgZmVsdGVyIChpZFByb3BlcnRpZXMpIGRlciBpbmRnXHUwMEU1ciBpIGtvbG9ubmVucyBuXHUwMEY4Z2xlLlxuICogU2FtbWUgdGVtcGxhdGUgYnJ1Z2VzIHRpbCBhdCBieWdnZSBuXHUwMEY4Z2xlIGZvciBiXHUwMEU1ZGUga29sb25uZSBvZyBldmVudC5cbiAqXG4gKiBTdXBwb3J0cyBkb3Qtbm90YXRpb24gZm9yIGhpZXJhcmNoaWNhbCByZWxhdGlvbnM6XG4gKiAtICdyZXNvdXJjZS50ZWFtSWQnIFx1MjE5MiBsb29rcyB1cCBldmVudC5yZXNvdXJjZUlkIFx1MjE5MiByZXNvdXJjZSBlbnRpdHkgXHUyMTkyIHRlYW1JZFxuICpcbiAqIFByaW5jaXA6IEtvbG9ubmVucyBuXHUwMEY4Z2xlLXRlbXBsYXRlIGJlc3RlbW1lciBodmFkIGRlciBtYXRjaGVzIHBcdTAwRTUuXG4gKlxuICogQHNlZSBkb2NzL2ZpbHRlci10ZW1wbGF0ZS5tZFxuICovXG5leHBvcnQgY2xhc3MgRmlsdGVyVGVtcGxhdGUge1xuICAgIGNvbnN0cnVjdG9yKGRhdGVTZXJ2aWNlLCBlbnRpdHlSZXNvbHZlcikge1xuICAgICAgICB0aGlzLmRhdGVTZXJ2aWNlID0gZGF0ZVNlcnZpY2U7XG4gICAgICAgIHRoaXMuZW50aXR5UmVzb2x2ZXIgPSBlbnRpdHlSZXNvbHZlcjtcbiAgICAgICAgdGhpcy5maWVsZHMgPSBbXTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVGlsZlx1MDBGOGogZmVsdCB0aWwgdGVtcGxhdGVcbiAgICAgKiBAcGFyYW0gaWRQcm9wZXJ0eSAtIFByb3BlcnR5LW5hdm4gKGJydWdlcyBwXHUwMEU1IGJcdTAwRTVkZSBldmVudCBvZyBjb2x1bW4uZGF0YXNldClcbiAgICAgKiBAcGFyYW0gZGVyaXZlZEZyb20gLSBIdmlzIGZlbHRldCB1ZGxlZGVzIGZyYSBhbmRlbiBwcm9wZXJ0eSAoZi5la3MuIGRhdGUgZnJhIHN0YXJ0KVxuICAgICAqL1xuICAgIGFkZEZpZWxkKGlkUHJvcGVydHksIGRlcml2ZWRGcm9tKSB7XG4gICAgICAgIHRoaXMuZmllbGRzLnB1c2goeyBpZFByb3BlcnR5LCBkZXJpdmVkRnJvbSB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFBhcnNlIGRvdC1ub3RhdGlvbiBzdHJpbmcgaW50byBjb21wb25lbnRzXG4gICAgICogQGV4YW1wbGUgJ3Jlc291cmNlLnRlYW1JZCcgXHUyMTkyIHsgZW50aXR5VHlwZTogJ3Jlc291cmNlJywgcHJvcGVydHk6ICd0ZWFtSWQnLCBmb3JlaWduS2V5OiAncmVzb3VyY2VJZCcgfVxuICAgICAqL1xuICAgIHBhcnNlRG90Tm90YXRpb24oaWRQcm9wZXJ0eSkge1xuICAgICAgICBpZiAoIWlkUHJvcGVydHkuaW5jbHVkZXMoJy4nKSlcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICBjb25zdCBbZW50aXR5VHlwZSwgcHJvcGVydHldID0gaWRQcm9wZXJ0eS5zcGxpdCgnLicpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZW50aXR5VHlwZSxcbiAgICAgICAgICAgIHByb3BlcnR5LFxuICAgICAgICAgICAgZm9yZWlnbktleTogZW50aXR5VHlwZSArICdJZCcgLy8gQ29udmVudGlvbjogcmVzb3VyY2UgXHUyMTkyIHJlc291cmNlSWRcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGRhdGFzZXQga2V5IGZvciBjb2x1bW4gbG9va3VwXG4gICAgICogRm9yIGRvdC1ub3RhdGlvbiAncmVzb3VyY2UudGVhbUlkJywgd2UgbG9vayBmb3IgJ3RlYW1JZCcgaW4gZGF0YXNldFxuICAgICAqL1xuICAgIGdldERhdGFzZXRLZXkoaWRQcm9wZXJ0eSkge1xuICAgICAgICBjb25zdCBkb3ROb3RhdGlvbiA9IHRoaXMucGFyc2VEb3ROb3RhdGlvbihpZFByb3BlcnR5KTtcbiAgICAgICAgaWYgKGRvdE5vdGF0aW9uKSB7XG4gICAgICAgICAgICByZXR1cm4gZG90Tm90YXRpb24ucHJvcGVydHk7IC8vICd0ZWFtSWQnXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlkUHJvcGVydHk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEJ5ZyBuXHUwMEY4Z2xlIGZyYSBrb2xvbm5lXG4gICAgICogTFx1MDBFNnNlciB2XHUwMEU2cmRpZXIgZnJhIGNvbHVtbi5kYXRhc2V0W2lkUHJvcGVydHldXG4gICAgICogRm9yIGRvdC1ub3RhdGlvbiwgdXNlcyB0aGUgcHJvcGVydHkgcGFydCAocmVzb3VyY2UudGVhbUlkIFx1MjE5MiB0ZWFtSWQpXG4gICAgICovXG4gICAgYnVpbGRLZXlGcm9tQ29sdW1uKGNvbHVtbikge1xuICAgICAgICByZXR1cm4gdGhpcy5maWVsZHNcbiAgICAgICAgICAgIC5tYXAoZiA9PiB7XG4gICAgICAgICAgICBjb25zdCBrZXkgPSB0aGlzLmdldERhdGFzZXRLZXkoZi5pZFByb3BlcnR5KTtcbiAgICAgICAgICAgIHJldHVybiBjb2x1bW4uZGF0YXNldFtrZXldIHx8ICcnO1xuICAgICAgICB9KVxuICAgICAgICAgICAgLmpvaW4oJzonKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQnlnIG5cdTAwRjhnbGUgZnJhIGV2ZW50XG4gICAgICogTFx1MDBFNnNlciB2XHUwMEU2cmRpZXIgZnJhIGV2ZW50W2lkUHJvcGVydHldIGVsbGVyIHVkbGVkZXIgZnJhIGRlcml2ZWRGcm9tXG4gICAgICogRm9yIGRvdC1ub3RhdGlvbiwgcmVzb2x2ZXMgdmlhIEVudGl0eVJlc29sdmVyXG4gICAgICovXG4gICAgYnVpbGRLZXlGcm9tRXZlbnQoZXZlbnQpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgICAgY29uc3QgZXZlbnRSZWNvcmQgPSBldmVudDtcbiAgICAgICAgcmV0dXJuIHRoaXMuZmllbGRzXG4gICAgICAgICAgICAubWFwKGYgPT4ge1xuICAgICAgICAgICAgLy8gQ2hlY2sgZm9yIGRvdC1ub3RhdGlvbiAoZS5nLiwgJ3Jlc291cmNlLnRlYW1JZCcpXG4gICAgICAgICAgICBjb25zdCBkb3ROb3RhdGlvbiA9IHRoaXMucGFyc2VEb3ROb3RhdGlvbihmLmlkUHJvcGVydHkpO1xuICAgICAgICAgICAgaWYgKGRvdE5vdGF0aW9uKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZURvdE5vdGF0aW9uKGV2ZW50UmVjb3JkLCBkb3ROb3RhdGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZi5kZXJpdmVkRnJvbSkge1xuICAgICAgICAgICAgICAgIC8vIFVkbGVkIHZcdTAwRTZyZGkgKGYuZWtzLiBkYXRlIGZyYSBzdGFydClcbiAgICAgICAgICAgICAgICBjb25zdCBzb3VyY2VWYWx1ZSA9IGV2ZW50UmVjb3JkW2YuZGVyaXZlZEZyb21dO1xuICAgICAgICAgICAgICAgIGlmIChzb3VyY2VWYWx1ZSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0ZVNlcnZpY2UuZ2V0RGF0ZUtleShzb3VyY2VWYWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcoc291cmNlVmFsdWUgfHwgJycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhldmVudFJlY29yZFtmLmlkUHJvcGVydHldIHx8ICcnKTtcbiAgICAgICAgfSlcbiAgICAgICAgICAgIC5qb2luKCc6Jyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlc29sdmUgZG90LW5vdGF0aW9uIHJlZmVyZW5jZSB2aWEgRW50aXR5UmVzb2x2ZXJcbiAgICAgKi9cbiAgICByZXNvbHZlRG90Tm90YXRpb24oZXZlbnRSZWNvcmQsIGRvdE5vdGF0aW9uKSB7XG4gICAgICAgIGlmICghdGhpcy5lbnRpdHlSZXNvbHZlcikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKGBGaWx0ZXJUZW1wbGF0ZTogRW50aXR5UmVzb2x2ZXIgcmVxdWlyZWQgZm9yIGRvdC1ub3RhdGlvbiAnJHtkb3ROb3RhdGlvbi5lbnRpdHlUeXBlfS4ke2RvdE5vdGF0aW9uLnByb3BlcnR5fSdgKTtcbiAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfVxuICAgICAgICAvLyBHZXQgZm9yZWlnbiBrZXkgdmFsdWUgZnJvbSBldmVudCAoZS5nLiwgcmVzb3VyY2VJZClcbiAgICAgICAgY29uc3QgZm9yZWlnbklkID0gZXZlbnRSZWNvcmRbZG90Tm90YXRpb24uZm9yZWlnbktleV07XG4gICAgICAgIGlmICghZm9yZWlnbklkKVxuICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICAvLyBSZXNvbHZlIGVudGl0eVxuICAgICAgICBjb25zdCBlbnRpdHkgPSB0aGlzLmVudGl0eVJlc29sdmVyLnJlc29sdmUoZG90Tm90YXRpb24uZW50aXR5VHlwZSwgU3RyaW5nKGZvcmVpZ25JZCkpO1xuICAgICAgICBpZiAoIWVudGl0eSlcbiAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgLy8gUmV0dXJuIHByb3BlcnR5IHZhbHVlIGZyb20gZW50aXR5XG4gICAgICAgIHJldHVybiBTdHJpbmcoZW50aXR5W2RvdE5vdGF0aW9uLnByb3BlcnR5XSB8fCAnJyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIE1hdGNoIGV2ZW50IG1vZCBrb2xvbm5lXG4gICAgICovXG4gICAgbWF0Y2hlcyhldmVudCwgY29sdW1uKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkS2V5RnJvbUV2ZW50KGV2ZW50KSA9PT0gdGhpcy5idWlsZEtleUZyb21Db2x1bW4oY29sdW1uKTtcbiAgICB9XG59XG4iLCAiaW1wb3J0IHsgYnVpbGRQaXBlbGluZSB9IGZyb20gJy4vUmVuZGVyQnVpbGRlcic7XG5pbXBvcnQgeyBGaWx0ZXJUZW1wbGF0ZSB9IGZyb20gJy4vRmlsdGVyVGVtcGxhdGUnO1xuZXhwb3J0IGNsYXNzIENhbGVuZGFyT3JjaGVzdHJhdG9yIHtcbiAgICBjb25zdHJ1Y3RvcihhbGxSZW5kZXJlcnMsIGV2ZW50UmVuZGVyZXIsIHNjaGVkdWxlUmVuZGVyZXIsIGhlYWRlckRyYXdlclJlbmRlcmVyLCBkYXRlU2VydmljZSwgZW50aXR5U2VydmljZXMpIHtcbiAgICAgICAgdGhpcy5hbGxSZW5kZXJlcnMgPSBhbGxSZW5kZXJlcnM7XG4gICAgICAgIHRoaXMuZXZlbnRSZW5kZXJlciA9IGV2ZW50UmVuZGVyZXI7XG4gICAgICAgIHRoaXMuc2NoZWR1bGVSZW5kZXJlciA9IHNjaGVkdWxlUmVuZGVyZXI7XG4gICAgICAgIHRoaXMuaGVhZGVyRHJhd2VyUmVuZGVyZXIgPSBoZWFkZXJEcmF3ZXJSZW5kZXJlcjtcbiAgICAgICAgdGhpcy5kYXRlU2VydmljZSA9IGRhdGVTZXJ2aWNlO1xuICAgICAgICB0aGlzLmVudGl0eVNlcnZpY2VzID0gZW50aXR5U2VydmljZXM7XG4gICAgfVxuICAgIGFzeW5jIHJlbmRlcih2aWV3Q29uZmlnLCBjb250YWluZXIpIHtcbiAgICAgICAgY29uc3QgaGVhZGVyQ29udGFpbmVyID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJ3N3cC1jYWxlbmRhci1oZWFkZXInKTtcbiAgICAgICAgY29uc3QgY29sdW1uQ29udGFpbmVyID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJ3N3cC1kYXktY29sdW1ucycpO1xuICAgICAgICBpZiAoIWhlYWRlckNvbnRhaW5lciB8fCAhY29sdW1uQ29udGFpbmVyKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3Npbmcgc3dwLWNhbGVuZGFyLWhlYWRlciBvciBzd3AtZGF5LWNvbHVtbnMnKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBCeWcgZmlsdGVyIGZyYSB2aWV3Q29uZmlnXG4gICAgICAgIGNvbnN0IGZpbHRlciA9IHt9O1xuICAgICAgICBmb3IgKGNvbnN0IGdyb3VwaW5nIG9mIHZpZXdDb25maWcuZ3JvdXBpbmdzKSB7XG4gICAgICAgICAgICBmaWx0ZXJbZ3JvdXBpbmcudHlwZV0gPSBncm91cGluZy52YWx1ZXM7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQnlnIEZpbHRlclRlbXBsYXRlIGZyYSB2aWV3Q29uZmlnIGdyb3VwaW5ncyAoa3VuIGRlIG1lZCBpZFByb3BlcnR5KVxuICAgICAgICBjb25zdCBmaWx0ZXJUZW1wbGF0ZSA9IG5ldyBGaWx0ZXJUZW1wbGF0ZSh0aGlzLmRhdGVTZXJ2aWNlKTtcbiAgICAgICAgZm9yIChjb25zdCBncm91cGluZyBvZiB2aWV3Q29uZmlnLmdyb3VwaW5ncykge1xuICAgICAgICAgICAgaWYgKGdyb3VwaW5nLmlkUHJvcGVydHkpIHtcbiAgICAgICAgICAgICAgICBmaWx0ZXJUZW1wbGF0ZS5hZGRGaWVsZChncm91cGluZy5pZFByb3BlcnR5LCBncm91cGluZy5kZXJpdmVkRnJvbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmVzb2x2ZSBiZWxvbmdzVG8gcmVsYXRpb25zIChlLmcuLCB0ZWFtLnJlc291cmNlSWRzKVxuICAgICAgICBjb25zdCB7IHBhcmVudENoaWxkTWFwLCBjaGlsZFR5cGUgfSA9IGF3YWl0IHRoaXMucmVzb2x2ZUJlbG9uZ3NUbyh2aWV3Q29uZmlnLmdyb3VwaW5ncywgZmlsdGVyKTtcbiAgICAgICAgY29uc3QgY29udGV4dCA9IHsgaGVhZGVyQ29udGFpbmVyLCBjb2x1bW5Db250YWluZXIsIGZpbHRlciwgZ3JvdXBpbmdzOiB2aWV3Q29uZmlnLmdyb3VwaW5ncywgcGFyZW50Q2hpbGRNYXAsIGNoaWxkVHlwZSB9O1xuICAgICAgICAvLyBDbGVhclxuICAgICAgICBoZWFkZXJDb250YWluZXIuaW5uZXJIVE1MID0gJyc7XG4gICAgICAgIGNvbHVtbkNvbnRhaW5lci5pbm5lckhUTUwgPSAnJztcbiAgICAgICAgLy8gU1x1MDBFNnQgZGF0YS1sZXZlbHMgYXR0cmlidXQgZm9yIENTUyBncmlkLXJvdyBzdHlsaW5nXG4gICAgICAgIGNvbnN0IGxldmVscyA9IHZpZXdDb25maWcuZ3JvdXBpbmdzLm1hcChnID0+IGcudHlwZSkuam9pbignICcpO1xuICAgICAgICBoZWFkZXJDb250YWluZXIuZGF0YXNldC5sZXZlbHMgPSBsZXZlbHM7XG4gICAgICAgIC8vIFZcdTAwRTZsZyByZW5kZXJlcnMgYmFzZXJldCBwXHUwMEU1IGdyb3VwaW5ncyB0eXBlc1xuICAgICAgICBjb25zdCBhY3RpdmVSZW5kZXJlcnMgPSB0aGlzLnNlbGVjdFJlbmRlcmVycyh2aWV3Q29uZmlnKTtcbiAgICAgICAgLy8gQnlnIG9nIGtcdTAwRjhyIHBpcGVsaW5lXG4gICAgICAgIGNvbnN0IHBpcGVsaW5lID0gYnVpbGRQaXBlbGluZShhY3RpdmVSZW5kZXJlcnMpO1xuICAgICAgICBhd2FpdCBwaXBlbGluZS5ydW4oY29udGV4dCk7XG4gICAgICAgIC8vIFJlbmRlciBzY2hlZHVsZSB1bmF2YWlsYWJsZSB6b25lcyAoZlx1MDBGOHIgZXZlbnRzKVxuICAgICAgICBhd2FpdCB0aGlzLnNjaGVkdWxlUmVuZGVyZXIucmVuZGVyKGNvbnRhaW5lciwgZmlsdGVyKTtcbiAgICAgICAgLy8gUmVuZGVyIHRpbWVkIGV2ZW50cyBpbiBncmlkIChtZWQgZmlsdGVyVGVtcGxhdGUgdGlsIG1hdGNoaW5nKVxuICAgICAgICBhd2FpdCB0aGlzLmV2ZW50UmVuZGVyZXIucmVuZGVyKGNvbnRhaW5lciwgZmlsdGVyLCBmaWx0ZXJUZW1wbGF0ZSk7XG4gICAgICAgIC8vIFJlbmRlciBhbGxEYXkgZXZlbnRzIGluIGhlYWRlciBkcmF3ZXIgKG1lZCBmaWx0ZXJUZW1wbGF0ZSB0aWwgbWF0Y2hpbmcpXG4gICAgICAgIGF3YWl0IHRoaXMuaGVhZGVyRHJhd2VyUmVuZGVyZXIucmVuZGVyKGNvbnRhaW5lciwgZmlsdGVyLCBmaWx0ZXJUZW1wbGF0ZSk7XG4gICAgfVxuICAgIHNlbGVjdFJlbmRlcmVycyh2aWV3Q29uZmlnKSB7XG4gICAgICAgIGNvbnN0IHR5cGVzID0gdmlld0NvbmZpZy5ncm91cGluZ3MubWFwKGcgPT4gZy50eXBlKTtcbiAgICAgICAgLy8gU29ydFx1MDBFOXIgcmVuZGVyZXJzIGkgc2FtbWUgclx1MDBFNmtrZWZcdTAwRjhsZ2Ugc29tIHZpZXdDb25maWcuZ3JvdXBpbmdzXG4gICAgICAgIHJldHVybiB0eXBlc1xuICAgICAgICAgICAgLm1hcCh0eXBlID0+IHRoaXMuYWxsUmVuZGVyZXJzLmZpbmQociA9PiByLnR5cGUgPT09IHR5cGUpKVxuICAgICAgICAgICAgLmZpbHRlcigocikgPT4gciAhPT0gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVzb2x2ZSBiZWxvbmdzVG8gcmVsYXRpb25zIHRvIGJ1aWxkIHBhcmVudC1jaGlsZCBtYXBcbiAgICAgKiBlLmcuLCBiZWxvbmdzVG86ICd0ZWFtLnJlc291cmNlSWRzJyBcdTIxOTIgeyB0ZWFtMTogWydFTVAwMDEnLCAnRU1QMDAyJ10sIHRlYW0yOiBbLi4uXSB9XG4gICAgICogQWxzbyByZXR1cm5zIHRoZSBjaGlsZFR5cGUgKHRoZSBncm91cGluZyB0eXBlIHRoYXQgaGFzIGJlbG9uZ3NUbylcbiAgICAgKi9cbiAgICBhc3luYyByZXNvbHZlQmVsb25nc1RvKGdyb3VwaW5ncywgZmlsdGVyKSB7XG4gICAgICAgIC8vIEZpbmQgZ3JvdXBpbmcgd2l0aCBiZWxvbmdzVG9cbiAgICAgICAgY29uc3QgY2hpbGRHcm91cGluZyA9IGdyb3VwaW5ncy5maW5kKGcgPT4gZy5iZWxvbmdzVG8pO1xuICAgICAgICBpZiAoIWNoaWxkR3JvdXBpbmc/LmJlbG9uZ3NUbylcbiAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgLy8gUGFyc2UgYmVsb25nc1RvOiAndGVhbS5yZXNvdXJjZUlkcydcbiAgICAgICAgY29uc3QgW2VudGl0eVR5cGUsIHByb3BlcnR5XSA9IGNoaWxkR3JvdXBpbmcuYmVsb25nc1RvLnNwbGl0KCcuJyk7XG4gICAgICAgIGlmICghZW50aXR5VHlwZSB8fCAhcHJvcGVydHkpXG4gICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgIC8vIEdldCBwYXJlbnQgSURzIGZyb20gZmlsdGVyXG4gICAgICAgIGNvbnN0IHBhcmVudElkcyA9IGZpbHRlcltlbnRpdHlUeXBlXSB8fCBbXTtcbiAgICAgICAgaWYgKHBhcmVudElkcy5sZW5ndGggPT09IDApXG4gICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgIC8vIEZpbmQgc2VydmljZSBkeW5hbWlzayBiYXNlcmV0IHBcdTAwRTUgZW50aXR5VHlwZSAoaW5nZW4gaGFyZGNvZGVkIHR5cGUgY2hlY2spXG4gICAgICAgIGNvbnN0IHNlcnZpY2UgPSB0aGlzLmVudGl0eVNlcnZpY2VzLmZpbmQocyA9PiBzLmVudGl0eVR5cGUudG9Mb3dlckNhc2UoKSA9PT0gZW50aXR5VHlwZSk7XG4gICAgICAgIGlmICghc2VydmljZSlcbiAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgLy8gSGVudCBhbGxlIGVudGl0aWVzIG9nIGZpbHRyZXIgcFx1MDBFNSBwYXJlbnRJZHNcbiAgICAgICAgY29uc3QgYWxsRW50aXRpZXMgPSBhd2FpdCBzZXJ2aWNlLmdldEFsbCgpO1xuICAgICAgICBjb25zdCBlbnRpdGllcyA9IGFsbEVudGl0aWVzLmZpbHRlcihlID0+IHBhcmVudElkcy5pbmNsdWRlcyhlLmlkKSk7XG4gICAgICAgIC8vIEJ5ZyBwYXJlbnQtY2hpbGQgbWFwXG4gICAgICAgIGNvbnN0IG1hcCA9IHt9O1xuICAgICAgICBmb3IgKGNvbnN0IGVudGl0eSBvZiBlbnRpdGllcykge1xuICAgICAgICAgICAgY29uc3QgZW50aXR5UmVjb3JkID0gZW50aXR5O1xuICAgICAgICAgICAgY29uc3QgY2hpbGRyZW4gPSBlbnRpdHlSZWNvcmRbcHJvcGVydHldIHx8IFtdO1xuICAgICAgICAgICAgbWFwW2VudGl0eVJlY29yZC5pZF0gPSBjaGlsZHJlbjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBwYXJlbnRDaGlsZE1hcDogbWFwLCBjaGlsZFR5cGU6IGNoaWxkR3JvdXBpbmcudHlwZSB9O1xuICAgIH1cbn1cbiIsICJleHBvcnQgY2xhc3MgTmF2aWdhdGlvbkFuaW1hdG9yIHtcbiAgICBjb25zdHJ1Y3RvcihoZWFkZXJUcmFjaywgY29udGVudFRyYWNrLCBoZWFkZXJEcmF3ZXIpIHtcbiAgICAgICAgdGhpcy5oZWFkZXJUcmFjayA9IGhlYWRlclRyYWNrO1xuICAgICAgICB0aGlzLmNvbnRlbnRUcmFjayA9IGNvbnRlbnRUcmFjaztcbiAgICAgICAgdGhpcy5oZWFkZXJEcmF3ZXIgPSBoZWFkZXJEcmF3ZXI7XG4gICAgfVxuICAgIGFzeW5jIHNsaWRlKGRpcmVjdGlvbiwgcmVuZGVyRm4pIHtcbiAgICAgICAgY29uc3Qgb3V0ID0gZGlyZWN0aW9uID09PSAnbGVmdCcgPyAnLTEwMCUnIDogJzEwMCUnO1xuICAgICAgICBjb25zdCBpbnRvID0gZGlyZWN0aW9uID09PSAnbGVmdCcgPyAnMTAwJScgOiAnLTEwMCUnO1xuICAgICAgICBhd2FpdCB0aGlzLmFuaW1hdGVPdXQob3V0KTtcbiAgICAgICAgYXdhaXQgcmVuZGVyRm4oKTtcbiAgICAgICAgYXdhaXQgdGhpcy5hbmltYXRlSW4oaW50byk7XG4gICAgfVxuICAgIGFzeW5jIGFuaW1hdGVPdXQodHJhbnNsYXRlKSB7XG4gICAgICAgIGNvbnN0IGFuaW1hdGlvbnMgPSBbXG4gICAgICAgICAgICB0aGlzLmhlYWRlclRyYWNrLmFuaW1hdGUoW3sgdHJhbnNmb3JtOiAndHJhbnNsYXRlWCgwKScgfSwgeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGVYKCR7dHJhbnNsYXRlfSlgIH1dLCB7IGR1cmF0aW9uOiAyMDAsIGVhc2luZzogJ2Vhc2UtaW4nIH0pLmZpbmlzaGVkLFxuICAgICAgICAgICAgdGhpcy5jb250ZW50VHJhY2suYW5pbWF0ZShbeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGVYKDApJyB9LCB7IHRyYW5zZm9ybTogYHRyYW5zbGF0ZVgoJHt0cmFuc2xhdGV9KWAgfV0sIHsgZHVyYXRpb246IDIwMCwgZWFzaW5nOiAnZWFzZS1pbicgfSkuZmluaXNoZWRcbiAgICAgICAgXTtcbiAgICAgICAgaWYgKHRoaXMuaGVhZGVyRHJhd2VyKSB7XG4gICAgICAgICAgICBhbmltYXRpb25zLnB1c2godGhpcy5oZWFkZXJEcmF3ZXIuYW5pbWF0ZShbeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGVYKDApJyB9LCB7IHRyYW5zZm9ybTogYHRyYW5zbGF0ZVgoJHt0cmFuc2xhdGV9KWAgfV0sIHsgZHVyYXRpb246IDIwMCwgZWFzaW5nOiAnZWFzZS1pbicgfSkuZmluaXNoZWQpO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKGFuaW1hdGlvbnMpO1xuICAgIH1cbiAgICBhc3luYyBhbmltYXRlSW4odHJhbnNsYXRlKSB7XG4gICAgICAgIGNvbnN0IGFuaW1hdGlvbnMgPSBbXG4gICAgICAgICAgICB0aGlzLmhlYWRlclRyYWNrLmFuaW1hdGUoW3sgdHJhbnNmb3JtOiBgdHJhbnNsYXRlWCgke3RyYW5zbGF0ZX0pYCB9LCB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZVgoMCknIH1dLCB7IGR1cmF0aW9uOiAyMDAsIGVhc2luZzogJ2Vhc2Utb3V0JyB9KS5maW5pc2hlZCxcbiAgICAgICAgICAgIHRoaXMuY29udGVudFRyYWNrLmFuaW1hdGUoW3sgdHJhbnNmb3JtOiBgdHJhbnNsYXRlWCgke3RyYW5zbGF0ZX0pYCB9LCB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZVgoMCknIH1dLCB7IGR1cmF0aW9uOiAyMDAsIGVhc2luZzogJ2Vhc2Utb3V0JyB9KS5maW5pc2hlZFxuICAgICAgICBdO1xuICAgICAgICBpZiAodGhpcy5oZWFkZXJEcmF3ZXIpIHtcbiAgICAgICAgICAgIGFuaW1hdGlvbnMucHVzaCh0aGlzLmhlYWRlckRyYXdlci5hbmltYXRlKFt7IHRyYW5zZm9ybTogYHRyYW5zbGF0ZVgoJHt0cmFuc2xhdGV9KWAgfSwgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGVYKDApJyB9XSwgeyBkdXJhdGlvbjogMjAwLCBlYXNpbmc6ICdlYXNlLW91dCcgfSkuZmluaXNoZWQpO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKGFuaW1hdGlvbnMpO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIENhbGVuZGFyRXZlbnRzIC0gQ29tbWFuZCBhbmQgc3RhdHVzIGV2ZW50cyBmb3IgQ2FsZW5kYXJBcHBcbiAqL1xuZXhwb3J0IGNvbnN0IENhbGVuZGFyRXZlbnRzID0ge1xuICAgIC8vIENvbW1hbmQgZXZlbnRzIChob3N0IFx1MjE5MiBjYWxlbmRhcilcbiAgICBDTURfTkFWSUdBVEVfUFJFVjogJ2NhbGVuZGFyOmNtZDpuYXZpZ2F0ZTpwcmV2JyxcbiAgICBDTURfTkFWSUdBVEVfTkVYVDogJ2NhbGVuZGFyOmNtZDpuYXZpZ2F0ZTpuZXh0JyxcbiAgICBDTURfRFJBV0VSX1RPR0dMRTogJ2NhbGVuZGFyOmNtZDpkcmF3ZXI6dG9nZ2xlJyxcbiAgICBDTURfUkVOREVSOiAnY2FsZW5kYXI6Y21kOnJlbmRlcicsXG4gICAgQ01EX1dPUktXRUVLX0NIQU5HRTogJ2NhbGVuZGFyOmNtZDp3b3Jrd2VlazpjaGFuZ2UnLFxuICAgIENNRF9WSUVXX1VQREFURTogJ2NhbGVuZGFyOmNtZDp2aWV3OnVwZGF0ZSdcbn07XG4iLCAiaW1wb3J0IHsgTmF2aWdhdGlvbkFuaW1hdG9yIH0gZnJvbSAnLi9OYXZpZ2F0aW9uQW5pbWF0b3InO1xuaW1wb3J0IHsgQ2FsZW5kYXJFdmVudHMgfSBmcm9tICcuL0NhbGVuZGFyRXZlbnRzJztcbmV4cG9ydCBjbGFzcyBDYWxlbmRhckFwcCB7XG4gICAgY29uc3RydWN0b3Iob3JjaGVzdHJhdG9yLCB0aW1lQXhpc1JlbmRlcmVyLCBkYXRlU2VydmljZSwgc2Nyb2xsTWFuYWdlciwgaGVhZGVyRHJhd2VyTWFuYWdlciwgZHJhZ0Ryb3BNYW5hZ2VyLCBlZGdlU2Nyb2xsTWFuYWdlciwgcmVzaXplTWFuYWdlciwgaGVhZGVyRHJhd2VyUmVuZGVyZXIsIGV2ZW50UGVyc2lzdGVuY2VNYW5hZ2VyLCBzZXR0aW5nc1NlcnZpY2UsIHZpZXdDb25maWdTZXJ2aWNlLCBldmVudEJ1cykge1xuICAgICAgICB0aGlzLm9yY2hlc3RyYXRvciA9IG9yY2hlc3RyYXRvcjtcbiAgICAgICAgdGhpcy50aW1lQXhpc1JlbmRlcmVyID0gdGltZUF4aXNSZW5kZXJlcjtcbiAgICAgICAgdGhpcy5kYXRlU2VydmljZSA9IGRhdGVTZXJ2aWNlO1xuICAgICAgICB0aGlzLnNjcm9sbE1hbmFnZXIgPSBzY3JvbGxNYW5hZ2VyO1xuICAgICAgICB0aGlzLmhlYWRlckRyYXdlck1hbmFnZXIgPSBoZWFkZXJEcmF3ZXJNYW5hZ2VyO1xuICAgICAgICB0aGlzLmRyYWdEcm9wTWFuYWdlciA9IGRyYWdEcm9wTWFuYWdlcjtcbiAgICAgICAgdGhpcy5lZGdlU2Nyb2xsTWFuYWdlciA9IGVkZ2VTY3JvbGxNYW5hZ2VyO1xuICAgICAgICB0aGlzLnJlc2l6ZU1hbmFnZXIgPSByZXNpemVNYW5hZ2VyO1xuICAgICAgICB0aGlzLmhlYWRlckRyYXdlclJlbmRlcmVyID0gaGVhZGVyRHJhd2VyUmVuZGVyZXI7XG4gICAgICAgIHRoaXMuZXZlbnRQZXJzaXN0ZW5jZU1hbmFnZXIgPSBldmVudFBlcnNpc3RlbmNlTWFuYWdlcjtcbiAgICAgICAgdGhpcy5zZXR0aW5nc1NlcnZpY2UgPSBzZXR0aW5nc1NlcnZpY2U7XG4gICAgICAgIHRoaXMudmlld0NvbmZpZ1NlcnZpY2UgPSB2aWV3Q29uZmlnU2VydmljZTtcbiAgICAgICAgdGhpcy5ldmVudEJ1cyA9IGV2ZW50QnVzO1xuICAgICAgICB0aGlzLmRheU9mZnNldCA9IDA7XG4gICAgICAgIHRoaXMuY3VycmVudFZpZXdJZCA9ICdzaW1wbGUnO1xuICAgICAgICB0aGlzLndvcmt3ZWVrUHJlc2V0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5ncm91cGluZ092ZXJyaWRlcyA9IG5ldyBNYXAoKTtcbiAgICB9XG4gICAgYXN5bmMgaW5pdChjb250YWluZXIpIHtcbiAgICAgICAgdGhpcy5jb250YWluZXIgPSBjb250YWluZXI7XG4gICAgICAgIC8vIExvYWQgc2V0dGluZ3NcbiAgICAgICAgY29uc3QgZ3JpZFNldHRpbmdzID0gYXdhaXQgdGhpcy5zZXR0aW5nc1NlcnZpY2UuZ2V0R3JpZFNldHRpbmdzKCk7XG4gICAgICAgIGlmICghZ3JpZFNldHRpbmdzKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0dyaWRTZXR0aW5ncyBub3QgZm91bmQnKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLndvcmt3ZWVrUHJlc2V0ID0gYXdhaXQgdGhpcy5zZXR0aW5nc1NlcnZpY2UuZ2V0RGVmYXVsdFdvcmt3ZWVrUHJlc2V0KCk7XG4gICAgICAgIC8vIENyZWF0ZSBOYXZpZ2F0aW9uQW5pbWF0b3Igd2l0aCBET00gZWxlbWVudHNcbiAgICAgICAgdGhpcy5hbmltYXRvciA9IG5ldyBOYXZpZ2F0aW9uQW5pbWF0b3IoY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJ3N3cC1oZWFkZXItdHJhY2snKSwgY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJ3N3cC1jb250ZW50LXRyYWNrJyksIGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCdzd3AtaGVhZGVyLWRyYXdlcicpKTtcbiAgICAgICAgLy8gUmVuZGVyIHRpbWUgYXhpcyBmcm9tIHNldHRpbmdzXG4gICAgICAgIHRoaXMudGltZUF4aXNSZW5kZXJlci5yZW5kZXIoY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJyN0aW1lLWF4aXMnKSwgZ3JpZFNldHRpbmdzLmRheVN0YXJ0SG91ciwgZ3JpZFNldHRpbmdzLmRheUVuZEhvdXIpO1xuICAgICAgICAvLyBJbml0IG1hbmFnZXJzXG4gICAgICAgIHRoaXMuc2Nyb2xsTWFuYWdlci5pbml0KGNvbnRhaW5lcik7XG4gICAgICAgIHRoaXMuaGVhZGVyRHJhd2VyTWFuYWdlci5pbml0KGNvbnRhaW5lcik7XG4gICAgICAgIHRoaXMuZHJhZ0Ryb3BNYW5hZ2VyLmluaXQoY29udGFpbmVyKTtcbiAgICAgICAgdGhpcy5yZXNpemVNYW5hZ2VyLmluaXQoY29udGFpbmVyKTtcbiAgICAgICAgY29uc3Qgc2Nyb2xsYWJsZUNvbnRlbnQgPSBjb250YWluZXIucXVlcnlTZWxlY3Rvcignc3dwLXNjcm9sbGFibGUtY29udGVudCcpO1xuICAgICAgICB0aGlzLmVkZ2VTY3JvbGxNYW5hZ2VyLmluaXQoc2Nyb2xsYWJsZUNvbnRlbnQpO1xuICAgICAgICAvLyBTZXR1cCBjb21tYW5kIGV2ZW50IGxpc3RlbmVyc1xuICAgICAgICB0aGlzLnNldHVwRXZlbnRMaXN0ZW5lcnMoKTtcbiAgICAgICAgLy8gRW1pdCByZWFkeSBzdGF0dXNcbiAgICAgICAgdGhpcy5lbWl0U3RhdHVzKCdyZWFkeScpO1xuICAgIH1cbiAgICBzZXR1cEV2ZW50TGlzdGVuZXJzKCkge1xuICAgICAgICAvLyBOYXZpZ2F0aW9uIGNvbW1hbmRzIHZpYSBFdmVudEJ1c1xuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENhbGVuZGFyRXZlbnRzLkNNRF9OQVZJR0FURV9QUkVWLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZU5hdmlnYXRlUHJldigpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5ldmVudEJ1cy5vbihDYWxlbmRhckV2ZW50cy5DTURfTkFWSUdBVEVfTkVYVCwgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVOYXZpZ2F0ZU5leHQoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIERyYXdlciB0b2dnbGUgdmlhIEV2ZW50QnVzXG4gICAgICAgIHRoaXMuZXZlbnRCdXMub24oQ2FsZW5kYXJFdmVudHMuQ01EX0RSQVdFUl9UT0dHTEUsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaGVhZGVyRHJhd2VyTWFuYWdlci50b2dnbGUoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIFJlbmRlciBjb21tYW5kIHZpYSBFdmVudEJ1c1xuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENhbGVuZGFyRXZlbnRzLkNNRF9SRU5ERVIsIChlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB7IHZpZXdJZCB9ID0gZS5kZXRhaWw7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZVJlbmRlckNvbW1hbmQodmlld0lkKTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIFdvcmt3ZWVrIGNoYW5nZSB2aWEgRXZlbnRCdXNcbiAgICAgICAgdGhpcy5ldmVudEJ1cy5vbihDYWxlbmRhckV2ZW50cy5DTURfV09SS1dFRUtfQ0hBTkdFLCAoZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgeyBwcmVzZXRJZCB9ID0gZS5kZXRhaWw7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZVdvcmt3ZWVrQ2hhbmdlKHByZXNldElkKTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIFZpZXcgdXBkYXRlIHZpYSBFdmVudEJ1c1xuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENhbGVuZGFyRXZlbnRzLkNNRF9WSUVXX1VQREFURSwgKGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHsgdHlwZSwgdmFsdWVzIH0gPSBlLmRldGFpbDtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlVmlld1VwZGF0ZSh0eXBlLCB2YWx1ZXMpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgYXN5bmMgaGFuZGxlUmVuZGVyQ29tbWFuZCh2aWV3SWQpIHtcbiAgICAgICAgdGhpcy5jdXJyZW50Vmlld0lkID0gdmlld0lkO1xuICAgICAgICBhd2FpdCB0aGlzLnJlbmRlcigpO1xuICAgICAgICB0aGlzLmVtaXRTdGF0dXMoJ3JlbmRlcmVkJywgeyB2aWV3SWQgfSk7XG4gICAgfVxuICAgIGFzeW5jIGhhbmRsZU5hdmlnYXRlUHJldigpIHtcbiAgICAgICAgY29uc3Qgc3RlcCA9IHRoaXMud29ya3dlZWtQcmVzZXQ/LnBlcmlvZERheXMgPz8gNztcbiAgICAgICAgdGhpcy5kYXlPZmZzZXQgLT0gc3RlcDtcbiAgICAgICAgYXdhaXQgdGhpcy5hbmltYXRvci5zbGlkZSgncmlnaHQnLCAoKSA9PiB0aGlzLnJlbmRlcigpKTtcbiAgICAgICAgdGhpcy5lbWl0U3RhdHVzKCdyZW5kZXJlZCcsIHsgdmlld0lkOiB0aGlzLmN1cnJlbnRWaWV3SWQgfSk7XG4gICAgfVxuICAgIGFzeW5jIGhhbmRsZU5hdmlnYXRlTmV4dCgpIHtcbiAgICAgICAgY29uc3Qgc3RlcCA9IHRoaXMud29ya3dlZWtQcmVzZXQ/LnBlcmlvZERheXMgPz8gNztcbiAgICAgICAgdGhpcy5kYXlPZmZzZXQgKz0gc3RlcDtcbiAgICAgICAgYXdhaXQgdGhpcy5hbmltYXRvci5zbGlkZSgnbGVmdCcsICgpID0+IHRoaXMucmVuZGVyKCkpO1xuICAgICAgICB0aGlzLmVtaXRTdGF0dXMoJ3JlbmRlcmVkJywgeyB2aWV3SWQ6IHRoaXMuY3VycmVudFZpZXdJZCB9KTtcbiAgICB9XG4gICAgYXN5bmMgaGFuZGxlV29ya3dlZWtDaGFuZ2UocHJlc2V0SWQpIHtcbiAgICAgICAgY29uc3QgcHJlc2V0ID0gYXdhaXQgdGhpcy5zZXR0aW5nc1NlcnZpY2UuZ2V0V29ya3dlZWtQcmVzZXQocHJlc2V0SWQpO1xuICAgICAgICBpZiAocHJlc2V0KSB7XG4gICAgICAgICAgICB0aGlzLndvcmt3ZWVrUHJlc2V0ID0gcHJlc2V0O1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5yZW5kZXIoKTtcbiAgICAgICAgICAgIHRoaXMuZW1pdFN0YXR1cygncmVuZGVyZWQnLCB7IHZpZXdJZDogdGhpcy5jdXJyZW50Vmlld0lkIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIGFzeW5jIGhhbmRsZVZpZXdVcGRhdGUodHlwZSwgdmFsdWVzKSB7XG4gICAgICAgIHRoaXMuZ3JvdXBpbmdPdmVycmlkZXMuc2V0KHR5cGUsIHZhbHVlcyk7XG4gICAgICAgIGF3YWl0IHRoaXMucmVuZGVyKCk7XG4gICAgICAgIHRoaXMuZW1pdFN0YXR1cygncmVuZGVyZWQnLCB7IHZpZXdJZDogdGhpcy5jdXJyZW50Vmlld0lkIH0pO1xuICAgIH1cbiAgICBhc3luYyByZW5kZXIoKSB7XG4gICAgICAgIGNvbnN0IHN0b3JlZENvbmZpZyA9IGF3YWl0IHRoaXMudmlld0NvbmZpZ1NlcnZpY2UuZ2V0QnlJZCh0aGlzLmN1cnJlbnRWaWV3SWQpO1xuICAgICAgICBpZiAoIXN0b3JlZENvbmZpZykge1xuICAgICAgICAgICAgdGhpcy5lbWl0U3RhdHVzKCdlcnJvcicsIHsgbWVzc2FnZTogYFZpZXdDb25maWcgbm90IGZvdW5kOiAke3RoaXMuY3VycmVudFZpZXdJZH1gIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIFBvcHVsYXRlIGRhdGUgdmFsdWVzIGJhc2VkIG9uIHdvcmt3ZWVrIHByZXNldCBhbmQgZGF5IG9mZnNldFxuICAgICAgICBjb25zdCB3b3JrRGF5cyA9IHRoaXMud29ya3dlZWtQcmVzZXQ/LndvcmtEYXlzIHx8IFsxLCAyLCAzLCA0LCA1XTtcbiAgICAgICAgY29uc3QgcGVyaW9kRGF5cyA9IHRoaXMud29ya3dlZWtQcmVzZXQ/LnBlcmlvZERheXMgPz8gNztcbiAgICAgICAgLy8gRm9yIHNpbmdsZS1kYXkgbmF2aWdhdGlvbiAocGVyaW9kRGF5cz0xKSwgc2hvdyBjb25zZWN1dGl2ZSBkYXlzIGZyb20gb2Zmc2V0XG4gICAgICAgIC8vIEZvciB3ZWVrIG5hdmlnYXRpb24gKHBlcmlvZERheXM9NyksIHNob3cgd29ya0RheXMgZnJvbSB0aGUgd2VlayBjb250YWluaW5nIG9mZnNldFxuICAgICAgICBjb25zdCBkYXRlcyA9IHBlcmlvZERheXMgPT09IDFcbiAgICAgICAgICAgID8gdGhpcy5kYXRlU2VydmljZS5nZXREYXRlc0Zyb21PZmZzZXQodGhpcy5kYXlPZmZzZXQsIHdvcmtEYXlzLmxlbmd0aClcbiAgICAgICAgICAgIDogdGhpcy5kYXRlU2VydmljZS5nZXRXb3JrRGF5c0Zyb21PZmZzZXQodGhpcy5kYXlPZmZzZXQsIHdvcmtEYXlzKTtcbiAgICAgICAgLy8gQ2xvbmUgY29uZmlnIGFuZCBhcHBseSBvdmVycmlkZXNcbiAgICAgICAgY29uc3Qgdmlld0NvbmZpZyA9IHtcbiAgICAgICAgICAgIC4uLnN0b3JlZENvbmZpZyxcbiAgICAgICAgICAgIGdyb3VwaW5nczogc3RvcmVkQ29uZmlnLmdyb3VwaW5ncy5tYXAoZyA9PiB7XG4gICAgICAgICAgICAgICAgLy8gQXBwbHkgZGF0ZSB2YWx1ZXNcbiAgICAgICAgICAgICAgICBpZiAoZy50eXBlID09PSAnZGF0ZScpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgLi4uZywgdmFsdWVzOiBkYXRlcyB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBBcHBseSBncm91cGluZyBvdmVycmlkZXNcbiAgICAgICAgICAgICAgICBjb25zdCBvdmVycmlkZSA9IHRoaXMuZ3JvdXBpbmdPdmVycmlkZXMuZ2V0KGcudHlwZSk7XG4gICAgICAgICAgICAgICAgaWYgKG92ZXJyaWRlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7IC4uLmcsIHZhbHVlczogb3ZlcnJpZGUgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGc7XG4gICAgICAgICAgICB9KVxuICAgICAgICB9O1xuICAgICAgICBhd2FpdCB0aGlzLm9yY2hlc3RyYXRvci5yZW5kZXIodmlld0NvbmZpZywgdGhpcy5jb250YWluZXIpO1xuICAgIH1cbiAgICBlbWl0U3RhdHVzKHN0YXR1cywgZGV0YWlsKSB7XG4gICAgICAgIHRoaXMuY29udGFpbmVyLmRpc3BhdGNoRXZlbnQobmV3IEN1c3RvbUV2ZW50KGBjYWxlbmRhcjpzdGF0dXM6JHtzdGF0dXN9YCwge1xuICAgICAgICAgICAgZGV0YWlsLFxuICAgICAgICAgICAgYnViYmxlczogdHJ1ZVxuICAgICAgICB9KSk7XG4gICAgfVxufVxuIiwgImV4cG9ydCBjbGFzcyBUaW1lQXhpc1JlbmRlcmVyIHtcbiAgICByZW5kZXIoY29udGFpbmVyLCBzdGFydEhvdXIgPSA2LCBlbmRIb3VyID0gMjApIHtcbiAgICAgICAgY29udGFpbmVyLmlubmVySFRNTCA9ICcnO1xuICAgICAgICBmb3IgKGxldCBob3VyID0gc3RhcnRIb3VyOyBob3VyIDw9IGVuZEhvdXI7IGhvdXIrKykge1xuICAgICAgICAgICAgY29uc3QgbWFya2VyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3dwLWhvdXItbWFya2VyJyk7XG4gICAgICAgICAgICBtYXJrZXIudGV4dENvbnRlbnQgPSBgJHtob3VyLnRvU3RyaW5nKCkucGFkU3RhcnQoMiwgJzAnKX06MDBgO1xuICAgICAgICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKG1hcmtlcik7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCAiZXhwb3J0IGNsYXNzIFNjcm9sbE1hbmFnZXIge1xuICAgIGluaXQoY29udGFpbmVyKSB7XG4gICAgICAgIHRoaXMuc2Nyb2xsYWJsZUNvbnRlbnQgPSBjb250YWluZXIucXVlcnlTZWxlY3Rvcignc3dwLXNjcm9sbGFibGUtY29udGVudCcpO1xuICAgICAgICB0aGlzLnRpbWVBeGlzQ29udGVudCA9IGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCdzd3AtdGltZS1heGlzLWNvbnRlbnQnKTtcbiAgICAgICAgdGhpcy5jYWxlbmRhckhlYWRlciA9IGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCdzd3AtY2FsZW5kYXItaGVhZGVyJyk7XG4gICAgICAgIHRoaXMuaGVhZGVyRHJhd2VyID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJ3N3cC1oZWFkZXItZHJhd2VyJyk7XG4gICAgICAgIHRoaXMuaGVhZGVyVmlld3BvcnQgPSBjb250YWluZXIucXVlcnlTZWxlY3Rvcignc3dwLWhlYWRlci12aWV3cG9ydCcpO1xuICAgICAgICB0aGlzLmhlYWRlclNwYWNlciA9IGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCdzd3AtaGVhZGVyLXNwYWNlcicpO1xuICAgICAgICB0aGlzLnNjcm9sbGFibGVDb250ZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsICgpID0+IHRoaXMub25TY3JvbGwoKSk7XG4gICAgICAgIC8vIFN5bmtyb25pc2VyIGhlYWRlci1zcGFjZXIgaFx1MDBGOGpkZSBtZWQgaGVhZGVyLXZpZXdwb3J0XG4gICAgICAgIHRoaXMucmVzaXplT2JzZXJ2ZXIgPSBuZXcgUmVzaXplT2JzZXJ2ZXIoKCkgPT4gdGhpcy5zeW5jSGVhZGVyU3BhY2VySGVpZ2h0KCkpO1xuICAgICAgICB0aGlzLnJlc2l6ZU9ic2VydmVyLm9ic2VydmUodGhpcy5oZWFkZXJWaWV3cG9ydCk7XG4gICAgICAgIHRoaXMuc3luY0hlYWRlclNwYWNlckhlaWdodCgpO1xuICAgIH1cbiAgICBzeW5jSGVhZGVyU3BhY2VySGVpZ2h0KCkge1xuICAgICAgICAvLyBLb3BpZXIgZGVuIGZha3Rpc2tlIGNvbXB1dGVkIGhlaWdodCBkaXJla3RlIGZyYSBoZWFkZXItdmlld3BvcnRcbiAgICAgICAgY29uc3QgY29tcHV0ZWRIZWlnaHQgPSBnZXRDb21wdXRlZFN0eWxlKHRoaXMuaGVhZGVyVmlld3BvcnQpLmhlaWdodDtcbiAgICAgICAgdGhpcy5oZWFkZXJTcGFjZXIuc3R5bGUuaGVpZ2h0ID0gY29tcHV0ZWRIZWlnaHQ7XG4gICAgfVxuICAgIG9uU2Nyb2xsKCkge1xuICAgICAgICBjb25zdCB7IHNjcm9sbFRvcCwgc2Nyb2xsTGVmdCB9ID0gdGhpcy5zY3JvbGxhYmxlQ29udGVudDtcbiAgICAgICAgLy8gU3lua3JvbmlzZXIgdGltZS1heGlzIHZlcnRpa2FsdFxuICAgICAgICB0aGlzLnRpbWVBeGlzQ29udGVudC5zdHlsZS50cmFuc2Zvcm0gPSBgdHJhbnNsYXRlWSgtJHtzY3JvbGxUb3B9cHgpYDtcbiAgICAgICAgLy8gU3lua3JvbmlzZXIgaGVhZGVyIG9nIGRyYXdlciBob3Jpc29udGFsdFxuICAgICAgICB0aGlzLmNhbGVuZGFySGVhZGVyLnN0eWxlLnRyYW5zZm9ybSA9IGB0cmFuc2xhdGVYKC0ke3Njcm9sbExlZnR9cHgpYDtcbiAgICAgICAgdGhpcy5oZWFkZXJEcmF3ZXIuc3R5bGUudHJhbnNmb3JtID0gYHRyYW5zbGF0ZVgoLSR7c2Nyb2xsTGVmdH1weClgO1xuICAgIH1cbn1cbiIsICJleHBvcnQgY2xhc3MgSGVhZGVyRHJhd2VyTWFuYWdlciB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuZXhwYW5kZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5jdXJyZW50Um93cyA9IDA7XG4gICAgICAgIHRoaXMucm93SGVpZ2h0ID0gMjU7XG4gICAgICAgIHRoaXMuZHVyYXRpb24gPSAyMDA7XG4gICAgfVxuICAgIGluaXQoY29udGFpbmVyKSB7XG4gICAgICAgIHRoaXMuZHJhd2VyID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJ3N3cC1oZWFkZXItZHJhd2VyJyk7XG4gICAgICAgIGlmICghdGhpcy5kcmF3ZXIpXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdIZWFkZXJEcmF3ZXJNYW5hZ2VyOiBzd3AtaGVhZGVyLWRyYXdlciBub3QgZm91bmQnKTtcbiAgICB9XG4gICAgdG9nZ2xlKCkge1xuICAgICAgICB0aGlzLmV4cGFuZGVkID8gdGhpcy5jb2xsYXBzZSgpIDogdGhpcy5leHBhbmQoKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRXhwYW5kIGRyYXdlciB0byBzaW5nbGUgcm93IChsZWdhY3kgc3VwcG9ydClcbiAgICAgKi9cbiAgICBleHBhbmQoKSB7XG4gICAgICAgIHRoaXMuZXhwYW5kVG9Sb3dzKDEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBFeHBhbmQgZHJhd2VyIHRvIGZpdCBzcGVjaWZpZWQgbnVtYmVyIG9mIHJvd3NcbiAgICAgKi9cbiAgICBleHBhbmRUb1Jvd3Mocm93Q291bnQpIHtcbiAgICAgICAgY29uc3QgdGFyZ2V0SGVpZ2h0ID0gcm93Q291bnQgKiB0aGlzLnJvd0hlaWdodDtcbiAgICAgICAgY29uc3QgY3VycmVudEhlaWdodCA9IHRoaXMuZXhwYW5kZWQgPyB0aGlzLmN1cnJlbnRSb3dzICogdGhpcy5yb3dIZWlnaHQgOiAwO1xuICAgICAgICAvLyBTa2lwIGlmIGFscmVhZHkgYXQgdGFyZ2V0XG4gICAgICAgIGlmICh0aGlzLmV4cGFuZGVkICYmIHRoaXMuY3VycmVudFJvd3MgPT09IHJvd0NvdW50KVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB0aGlzLmN1cnJlbnRSb3dzID0gcm93Q291bnQ7XG4gICAgICAgIHRoaXMuZXhwYW5kZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLmFuaW1hdGUoY3VycmVudEhlaWdodCwgdGFyZ2V0SGVpZ2h0KTtcbiAgICB9XG4gICAgY29sbGFwc2UoKSB7XG4gICAgICAgIGlmICghdGhpcy5leHBhbmRlZClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY29uc3QgY3VycmVudEhlaWdodCA9IHRoaXMuY3VycmVudFJvd3MgKiB0aGlzLnJvd0hlaWdodDtcbiAgICAgICAgdGhpcy5leHBhbmRlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmN1cnJlbnRSb3dzID0gMDtcbiAgICAgICAgdGhpcy5hbmltYXRlKGN1cnJlbnRIZWlnaHQsIDApO1xuICAgIH1cbiAgICBhbmltYXRlKGZyb20sIHRvKSB7XG4gICAgICAgIGNvbnN0IGtleWZyYW1lcyA9IFtcbiAgICAgICAgICAgIHsgaGVpZ2h0OiBgJHtmcm9tfXB4YCB9LFxuICAgICAgICAgICAgeyBoZWlnaHQ6IGAke3RvfXB4YCB9XG4gICAgICAgIF07XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICAgIGVhc2luZzogJ2Vhc2UnLFxuICAgICAgICAgICAgZmlsbDogJ2ZvcndhcmRzJ1xuICAgICAgICB9O1xuICAgICAgICAvLyBLdW4gYW5pbVx1MDBFOXIgZHJhd2VyIC0gU2Nyb2xsTWFuYWdlciBzeW5rcm9uaXNlcmVyIGhlYWRlci1zcGFjZXIgdmlhIFJlc2l6ZU9ic2VydmVyXG4gICAgICAgIHRoaXMuZHJhd2VyLmFuaW1hdGUoa2V5ZnJhbWVzLCBvcHRpb25zKTtcbiAgICB9XG4gICAgaXNFeHBhbmRlZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZXhwYW5kZWQ7XG4gICAgfVxuICAgIGdldFJvd0NvdW50KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jdXJyZW50Um93cztcbiAgICB9XG59XG4iLCAiZXhwb3J0IGNsYXNzIE1vY2tUZWFtU3RvcmUge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnR5cGUgPSAndGVhbSc7XG4gICAgICAgIHRoaXMudGVhbXMgPSBbXG4gICAgICAgICAgICB7IGlkOiAnYWxwaGEnLCBuYW1lOiAnVGVhbSBBbHBoYScgfSxcbiAgICAgICAgICAgIHsgaWQ6ICdiZXRhJywgbmFtZTogJ1RlYW0gQmV0YScgfVxuICAgICAgICBdO1xuICAgIH1cbiAgICBnZXRCeUlkcyhpZHMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGVhbXMuZmlsdGVyKHQgPT4gaWRzLmluY2x1ZGVzKHQuaWQpKTtcbiAgICB9XG59XG5leHBvcnQgY2xhc3MgTW9ja1Jlc291cmNlU3RvcmUge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnR5cGUgPSAncmVzb3VyY2UnO1xuICAgICAgICB0aGlzLnJlc291cmNlcyA9IFtcbiAgICAgICAgICAgIHsgaWQ6ICdhbGljZScsIG5hbWU6ICdBbGljZScsIHRlYW1JZDogJ2FscGhhJyB9LFxuICAgICAgICAgICAgeyBpZDogJ2JvYicsIG5hbWU6ICdCb2InLCB0ZWFtSWQ6ICdhbHBoYScgfSxcbiAgICAgICAgICAgIHsgaWQ6ICdjYXJvbCcsIG5hbWU6ICdDYXJvbCcsIHRlYW1JZDogJ2JldGEnIH0sXG4gICAgICAgICAgICB7IGlkOiAnZGF2ZScsIG5hbWU6ICdEYXZlJywgdGVhbUlkOiAnYmV0YScgfVxuICAgICAgICBdO1xuICAgIH1cbiAgICBnZXRCeUlkcyhpZHMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVzb3VyY2VzLmZpbHRlcihyID0+IGlkcy5pbmNsdWRlcyhyLmlkKSk7XG4gICAgfVxufVxuIiwgImltcG9ydCB7IENhbGVuZGFyRXZlbnRzIH0gZnJvbSAnLi4vY29yZS9DYWxlbmRhckV2ZW50cyc7XG5leHBvcnQgY2xhc3MgRGVtb0FwcCB7XG4gICAgY29uc3RydWN0b3IoaW5kZXhlZERCQ29udGV4dCwgZGF0YVNlZWRlciwgYXVkaXRTZXJ2aWNlLCBjYWxlbmRhckFwcCwgZGF0ZVNlcnZpY2UsIHJlc291cmNlU2VydmljZSwgZXZlbnRCdXMpIHtcbiAgICAgICAgdGhpcy5pbmRleGVkREJDb250ZXh0ID0gaW5kZXhlZERCQ29udGV4dDtcbiAgICAgICAgdGhpcy5kYXRhU2VlZGVyID0gZGF0YVNlZWRlcjtcbiAgICAgICAgdGhpcy5hdWRpdFNlcnZpY2UgPSBhdWRpdFNlcnZpY2U7XG4gICAgICAgIHRoaXMuY2FsZW5kYXJBcHAgPSBjYWxlbmRhckFwcDtcbiAgICAgICAgdGhpcy5kYXRlU2VydmljZSA9IGRhdGVTZXJ2aWNlO1xuICAgICAgICB0aGlzLnJlc291cmNlU2VydmljZSA9IHJlc291cmNlU2VydmljZTtcbiAgICAgICAgdGhpcy5ldmVudEJ1cyA9IGV2ZW50QnVzO1xuICAgICAgICB0aGlzLmN1cnJlbnRWaWV3ID0gJ3NpbXBsZSc7XG4gICAgfVxuICAgIGFzeW5jIGluaXQoKSB7XG4gICAgICAgIC8vIFNldCBiYXNlIGRhdGUgdG8gbWF0Y2ggbW9jayBkYXRhICg4LiBkZWNlbWJlciAyMDI1ID0gbWFuZGFnKVxuICAgICAgICB0aGlzLmRhdGVTZXJ2aWNlLnNldEJhc2VEYXRlKG5ldyBEYXRlKCcyMDI1LTEyLTA4JykpO1xuICAgICAgICAvLyBJbml0aWFsaXplIEluZGV4ZWREQlxuICAgICAgICBhd2FpdCB0aGlzLmluZGV4ZWREQkNvbnRleHQuaW5pdGlhbGl6ZSgpO1xuICAgICAgICBjb25zb2xlLmxvZygnW0RlbW9BcHBdIEluZGV4ZWREQiBpbml0aWFsaXplZCcpO1xuICAgICAgICAvLyBTZWVkIGRhdGEgaWYgZW1wdHlcbiAgICAgICAgYXdhaXQgdGhpcy5kYXRhU2VlZGVyLnNlZWRJZkVtcHR5KCk7XG4gICAgICAgIGNvbnNvbGUubG9nKCdbRGVtb0FwcF0gRGF0YSBzZWVkaW5nIGNvbXBsZXRlJyk7XG4gICAgICAgIHRoaXMuY29udGFpbmVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcignc3dwLWNhbGVuZGFyLWNvbnRhaW5lcicpO1xuICAgICAgICAvLyBJbml0aWFsaXplIENhbGVuZGFyQXBwXG4gICAgICAgIGF3YWl0IHRoaXMuY2FsZW5kYXJBcHAuaW5pdCh0aGlzLmNvbnRhaW5lcik7XG4gICAgICAgIGNvbnNvbGUubG9nKCdbRGVtb0FwcF0gQ2FsZW5kYXJBcHAgaW5pdGlhbGl6ZWQnKTtcbiAgICAgICAgLy8gU2V0dXAgZGVtbyBVSSBoYW5kbGVyc1xuICAgICAgICB0aGlzLnNldHVwTmF2aWdhdGlvbigpO1xuICAgICAgICB0aGlzLnNldHVwRHJhd2VyVG9nZ2xlKCk7XG4gICAgICAgIHRoaXMuc2V0dXBWaWV3U3dpdGNoaW5nKCk7XG4gICAgICAgIHRoaXMuc2V0dXBXb3Jrd2Vla1NlbGVjdG9yKCk7XG4gICAgICAgIGF3YWl0IHRoaXMuc2V0dXBSZXNvdXJjZVNlbGVjdG9yKCk7XG4gICAgICAgIC8vIExpc3RlbiBmb3IgY2FsZW5kYXIgc3RhdHVzIGV2ZW50c1xuICAgICAgICB0aGlzLnNldHVwU3RhdHVzTGlzdGVuZXJzKCk7XG4gICAgICAgIC8vIEluaXRpYWwgcmVuZGVyXG4gICAgICAgIHRoaXMuZXZlbnRCdXMuZW1pdChDYWxlbmRhckV2ZW50cy5DTURfUkVOREVSLCB7IHZpZXdJZDogdGhpcy5jdXJyZW50VmlldyB9KTtcbiAgICB9XG4gICAgc2V0dXBOYXZpZ2F0aW9uKCkge1xuICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYnRuLXByZXYnKS5vbmNsaWNrID0gKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENhbGVuZGFyRXZlbnRzLkNNRF9OQVZJR0FURV9QUkVWKTtcbiAgICAgICAgfTtcbiAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2J0bi1uZXh0Jykub25jbGljayA9ICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMuZW1pdChDYWxlbmRhckV2ZW50cy5DTURfTkFWSUdBVEVfTkVYVCk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIHNldHVwVmlld1N3aXRjaGluZygpIHtcbiAgICAgICAgY29uc3QgY2hpcHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcudmlldy1jaGlwJyk7XG4gICAgICAgIGNoaXBzLmZvckVhY2goY2hpcCA9PiB7XG4gICAgICAgICAgICBjaGlwLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNoaXBzLmZvckVhY2goYyA9PiBjLmNsYXNzTGlzdC5yZW1vdmUoJ2FjdGl2ZScpKTtcbiAgICAgICAgICAgICAgICBjaGlwLmNsYXNzTGlzdC5hZGQoJ2FjdGl2ZScpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHZpZXcgPSBjaGlwLmRhdGFzZXQudmlldztcbiAgICAgICAgICAgICAgICBpZiAodmlldykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRWaWV3ID0gdmlldztcbiAgICAgICAgICAgICAgICAgICAgdGhpcy51cGRhdGVTZWxlY3RvclZpc2liaWxpdHkoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENhbGVuZGFyRXZlbnRzLkNNRF9SRU5ERVIsIHsgdmlld0lkOiB2aWV3IH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgdXBkYXRlU2VsZWN0b3JWaXNpYmlsaXR5KCkge1xuICAgICAgICBjb25zdCBzZWxlY3RvciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ3N3cC1yZXNvdXJjZS1zZWxlY3RvcicpO1xuICAgICAgICBjb25zdCBzaG93U2VsZWN0b3IgPSB0aGlzLmN1cnJlbnRWaWV3ID09PSAncGlja2VyJyB8fCB0aGlzLmN1cnJlbnRWaWV3ID09PSAnZGF5JztcbiAgICAgICAgc2VsZWN0b3I/LmNsYXNzTGlzdC50b2dnbGUoJ2hpZGRlbicsICFzaG93U2VsZWN0b3IpO1xuICAgIH1cbiAgICBzZXR1cERyYXdlclRvZ2dsZSgpIHtcbiAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2J0bi1kcmF3ZXInKS5vbmNsaWNrID0gKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENhbGVuZGFyRXZlbnRzLkNNRF9EUkFXRVJfVE9HR0xFKTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgc2V0dXBXb3Jrd2Vla1NlbGVjdG9yKCkge1xuICAgICAgICBjb25zdCB3b3Jrd2Vla1NlbGVjdCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd3b3Jrd2Vlay1zZWxlY3QnKTtcbiAgICAgICAgd29ya3dlZWtTZWxlY3Q/LmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHByZXNldElkID0gd29ya3dlZWtTZWxlY3QudmFsdWU7XG4gICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ2FsZW5kYXJFdmVudHMuQ01EX1dPUktXRUVLX0NIQU5HRSwgeyBwcmVzZXRJZCB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGFzeW5jIHNldHVwUmVzb3VyY2VTZWxlY3RvcigpIHtcbiAgICAgICAgY29uc3QgcmVzb3VyY2VzID0gYXdhaXQgdGhpcy5yZXNvdXJjZVNlcnZpY2UuZ2V0QWxsKCk7XG4gICAgICAgIGNvbnN0IGNvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5yZXNvdXJjZS1jaGVja2JveGVzJyk7XG4gICAgICAgIGlmICghY29udGFpbmVyKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBjb250YWluZXIuaW5uZXJIVE1MID0gJyc7XG4gICAgICAgIHJlc291cmNlcy5mb3JFYWNoKHIgPT4ge1xuICAgICAgICAgICAgY29uc3QgbGFiZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdsYWJlbCcpO1xuICAgICAgICAgICAgbGFiZWwuaW5uZXJIVE1MID0gYFxyXG4gICAgICAgIDxpbnB1dCB0eXBlPVwiY2hlY2tib3hcIiB2YWx1ZT1cIiR7ci5pZH1cIiBjaGVja2VkPlxyXG4gICAgICAgICR7ci5kaXNwbGF5TmFtZX1cclxuICAgICAgYDtcbiAgICAgICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChsYWJlbCk7XG4gICAgICAgIH0pO1xuICAgICAgICBjb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY2hlY2tlZCA9IGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yQWxsKCdpbnB1dDpjaGVja2VkJyk7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZXMgPSBBcnJheS5mcm9tKGNoZWNrZWQpLm1hcChjYiA9PiBjYi52YWx1ZSk7XG4gICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ2FsZW5kYXJFdmVudHMuQ01EX1ZJRVdfVVBEQVRFLCB7IHR5cGU6ICdyZXNvdXJjZScsIHZhbHVlcyB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHNldHVwU3RhdHVzTGlzdGVuZXJzKCkge1xuICAgICAgICB0aGlzLmNvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKCdjYWxlbmRhcjpzdGF0dXM6cmVhZHknLCAoKSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnW0RlbW9BcHBdIENhbGVuZGFyIHJlYWR5Jyk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmNvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKCdjYWxlbmRhcjpzdGF0dXM6cmVuZGVyZWQnLCAoKGUpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdbRGVtb0FwcF0gQ2FsZW5kYXIgcmVuZGVyZWQ6JywgZS5kZXRhaWwudmlld0lkKTtcbiAgICAgICAgfSkpO1xuICAgICAgICB0aGlzLmNvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKCdjYWxlbmRhcjpzdGF0dXM6ZXJyb3InLCAoKGUpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1tEZW1vQXBwXSBDYWxlbmRhciBlcnJvcjonLCBlLmRldGFpbC5tZXNzYWdlKTtcbiAgICAgICAgfSkpO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIENlbnRyYWwgZXZlbnQgZGlzcGF0Y2hlciBmb3IgY2FsZW5kYXIgdXNpbmcgRE9NIEN1c3RvbUV2ZW50c1xuICogUHJvdmlkZXMgbG9nZ2luZyBhbmQgZGVidWdnaW5nIGNhcGFiaWxpdGllc1xuICovXG5leHBvcnQgY2xhc3MgRXZlbnRCdXMge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmV2ZW50TG9nID0gW107XG4gICAgICAgIHRoaXMuZGVidWcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5saXN0ZW5lcnMgPSBuZXcgU2V0KCk7XG4gICAgICAgIC8vIExvZyBjb25maWd1cmF0aW9uIGZvciBkaWZmZXJlbnQgY2F0ZWdvcmllc1xuICAgICAgICB0aGlzLmxvZ0NvbmZpZyA9IHtcbiAgICAgICAgICAgIGNhbGVuZGFyOiB0cnVlLFxuICAgICAgICAgICAgZ3JpZDogdHJ1ZSxcbiAgICAgICAgICAgIGV2ZW50OiB0cnVlLFxuICAgICAgICAgICAgc2Nyb2xsOiB0cnVlLFxuICAgICAgICAgICAgbmF2aWdhdGlvbjogdHJ1ZSxcbiAgICAgICAgICAgIHZpZXc6IHRydWUsXG4gICAgICAgICAgICBkZWZhdWx0OiB0cnVlXG4gICAgICAgIH07XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZSB0byBhbiBldmVudCB2aWEgRE9NIGFkZEV2ZW50TGlzdGVuZXJcbiAgICAgKi9cbiAgICBvbihldmVudFR5cGUsIGhhbmRsZXIsIG9wdGlvbnMpIHtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihldmVudFR5cGUsIGhhbmRsZXIsIG9wdGlvbnMpO1xuICAgICAgICAvLyBUcmFjayBmb3IgY2xlYW51cFxuICAgICAgICB0aGlzLmxpc3RlbmVycy5hZGQoeyBldmVudFR5cGUsIGhhbmRsZXIsIG9wdGlvbnMgfSk7XG4gICAgICAgIC8vIFJldHVybiB1bnN1YnNjcmliZSBmdW5jdGlvblxuICAgICAgICByZXR1cm4gKCkgPT4gdGhpcy5vZmYoZXZlbnRUeXBlLCBoYW5kbGVyKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIHRvIGFuIGV2ZW50IG9uY2VcbiAgICAgKi9cbiAgICBvbmNlKGV2ZW50VHlwZSwgaGFuZGxlcikge1xuICAgICAgICByZXR1cm4gdGhpcy5vbihldmVudFR5cGUsIGhhbmRsZXIsIHsgb25jZTogdHJ1ZSB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVW5zdWJzY3JpYmUgZnJvbSBhbiBldmVudFxuICAgICAqL1xuICAgIG9mZihldmVudFR5cGUsIGhhbmRsZXIpIHtcbiAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudFR5cGUsIGhhbmRsZXIpO1xuICAgICAgICAvLyBSZW1vdmUgZnJvbSB0cmFja2luZ1xuICAgICAgICBmb3IgKGNvbnN0IGxpc3RlbmVyIG9mIHRoaXMubGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXIuZXZlbnRUeXBlID09PSBldmVudFR5cGUgJiYgbGlzdGVuZXIuaGFuZGxlciA9PT0gaGFuZGxlcikge1xuICAgICAgICAgICAgICAgIHRoaXMubGlzdGVuZXJzLmRlbGV0ZShsaXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogRW1pdCBhbiBldmVudCB2aWEgRE9NIEN1c3RvbUV2ZW50XG4gICAgICovXG4gICAgZW1pdChldmVudFR5cGUsIGRldGFpbCA9IHt9KSB7XG4gICAgICAgIC8vIFZhbGlkYXRlIGV2ZW50VHlwZVxuICAgICAgICBpZiAoIWV2ZW50VHlwZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGV2ZW50ID0gbmV3IEN1c3RvbUV2ZW50KGV2ZW50VHlwZSwge1xuICAgICAgICAgICAgZGV0YWlsOiBkZXRhaWwgPz8ge30sXG4gICAgICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICAgICAgY2FuY2VsYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgLy8gTG9nIGV2ZW50IHdpdGggZ3JvdXBpbmdcbiAgICAgICAgaWYgKHRoaXMuZGVidWcpIHtcbiAgICAgICAgICAgIHRoaXMubG9nRXZlbnRXaXRoR3JvdXBpbmcoZXZlbnRUeXBlLCBkZXRhaWwpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZXZlbnRMb2cucHVzaCh7XG4gICAgICAgICAgICB0eXBlOiBldmVudFR5cGUsXG4gICAgICAgICAgICBkZXRhaWw6IGRldGFpbCA/PyB7fSxcbiAgICAgICAgICAgIHRpbWVzdGFtcDogRGF0ZS5ub3coKVxuICAgICAgICB9KTtcbiAgICAgICAgLy8gRW1pdCBvbiBkb2N1bWVudCAob25seSBET00gZXZlbnRzIG5vdylcbiAgICAgICAgcmV0dXJuICFkb2N1bWVudC5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogTG9nIGV2ZW50IHdpdGggY29uc29sZSBncm91cGluZ1xuICAgICAqL1xuICAgIGxvZ0V2ZW50V2l0aEdyb3VwaW5nKGV2ZW50VHlwZSwgX2RldGFpbCkge1xuICAgICAgICAvLyBFeHRyYWN0IGNhdGVnb3J5IGZyb20gZXZlbnQgdHlwZSAoZS5nLiwgJ2NhbGVuZGFyOmRhdGVjaGFuZ2VkJyBcdTIxOTIgJ2NhbGVuZGFyJylcbiAgICAgICAgY29uc3QgY2F0ZWdvcnkgPSB0aGlzLmV4dHJhY3RDYXRlZ29yeShldmVudFR5cGUpO1xuICAgICAgICAvLyBPbmx5IGxvZyBpZiBjYXRlZ29yeSBpcyBlbmFibGVkXG4gICAgICAgIGlmICghdGhpcy5sb2dDb25maWdbY2F0ZWdvcnldKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gR2V0IGNhdGVnb3J5IGVtb2ppIGFuZCBjb2xvciAodXNlZCBmb3IgZnV0dXJlIGNvbnNvbGUgc3R5bGluZylcbiAgICAgICAgdGhpcy5nZXRDYXRlZ29yeVN0eWxlKGNhdGVnb3J5KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRXh0cmFjdCBjYXRlZ29yeSBmcm9tIGV2ZW50IHR5cGVcbiAgICAgKi9cbiAgICBleHRyYWN0Q2F0ZWdvcnkoZXZlbnRUeXBlKSB7XG4gICAgICAgIGlmICghZXZlbnRUeXBlKSB7XG4gICAgICAgICAgICByZXR1cm4gJ3Vua25vd24nO1xuICAgICAgICB9XG4gICAgICAgIGlmIChldmVudFR5cGUuaW5jbHVkZXMoJzonKSkge1xuICAgICAgICAgICAgcmV0dXJuIGV2ZW50VHlwZS5zcGxpdCgnOicpWzBdO1xuICAgICAgICB9XG4gICAgICAgIC8vIEZhbGxiYWNrOiB0cnkgdG8gZGV0ZWN0IGNhdGVnb3J5IGZyb20gZXZlbnQgbmFtZSBwYXR0ZXJuc1xuICAgICAgICBjb25zdCBsb3dlclR5cGUgPSBldmVudFR5cGUudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgaWYgKGxvd2VyVHlwZS5pbmNsdWRlcygnZ3JpZCcpIHx8IGxvd2VyVHlwZS5pbmNsdWRlcygncmVuZGVyZWQnKSlcbiAgICAgICAgICAgIHJldHVybiAnZ3JpZCc7XG4gICAgICAgIGlmIChsb3dlclR5cGUuaW5jbHVkZXMoJ2V2ZW50JykgfHwgbG93ZXJUeXBlLmluY2x1ZGVzKCdzeW5jJykpXG4gICAgICAgICAgICByZXR1cm4gJ2V2ZW50JztcbiAgICAgICAgaWYgKGxvd2VyVHlwZS5pbmNsdWRlcygnc2Nyb2xsJykpXG4gICAgICAgICAgICByZXR1cm4gJ3Njcm9sbCc7XG4gICAgICAgIGlmIChsb3dlclR5cGUuaW5jbHVkZXMoJ25hdicpIHx8IGxvd2VyVHlwZS5pbmNsdWRlcygnZGF0ZScpKVxuICAgICAgICAgICAgcmV0dXJuICduYXZpZ2F0aW9uJztcbiAgICAgICAgaWYgKGxvd2VyVHlwZS5pbmNsdWRlcygndmlldycpKVxuICAgICAgICAgICAgcmV0dXJuICd2aWV3JztcbiAgICAgICAgcmV0dXJuICdkZWZhdWx0JztcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IHN0eWxpbmcgZm9yIGRpZmZlcmVudCBjYXRlZ29yaWVzXG4gICAgICovXG4gICAgZ2V0Q2F0ZWdvcnlTdHlsZShjYXRlZ29yeSkge1xuICAgICAgICBjb25zdCBzdHlsZXMgPSB7XG4gICAgICAgICAgICBjYWxlbmRhcjogeyBlbW9qaTogJ1x1RDgzRFx1RENDNScsIGNvbG9yOiAnIzIxOTZGMycgfSxcbiAgICAgICAgICAgIGdyaWQ6IHsgZW1vamk6ICdcdUQ4M0RcdURDQ0EnLCBjb2xvcjogJyM0Q0FGNTAnIH0sXG4gICAgICAgICAgICBldmVudDogeyBlbW9qaTogJ1x1RDgzRFx1RENDQycsIGNvbG9yOiAnI0ZGOTgwMCcgfSxcbiAgICAgICAgICAgIHNjcm9sbDogeyBlbW9qaTogJ1x1RDgzRFx1RENEQycsIGNvbG9yOiAnIzlDMjdCMCcgfSxcbiAgICAgICAgICAgIG5hdmlnYXRpb246IHsgZW1vamk6ICdcdUQ4M0VcdURERUQnLCBjb2xvcjogJyNGNDQzMzYnIH0sXG4gICAgICAgICAgICB2aWV3OiB7IGVtb2ppOiAnXHVEODNEXHVEQzQxJywgY29sb3I6ICcjMDBCQ0Q0JyB9LFxuICAgICAgICAgICAgZGVmYXVsdDogeyBlbW9qaTogJ1x1RDgzRFx1RENFMicsIGNvbG9yOiAnIzYwN0Q4QicgfVxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gc3R5bGVzW2NhdGVnb3J5XSB8fCBzdHlsZXMuZGVmYXVsdDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ29uZmlndXJlIGxvZ2dpbmcgZm9yIHNwZWNpZmljIGNhdGVnb3JpZXNcbiAgICAgKi9cbiAgICBzZXRMb2dDb25maWcoY29uZmlnKSB7XG4gICAgICAgIHRoaXMubG9nQ29uZmlnID0geyAuLi50aGlzLmxvZ0NvbmZpZywgLi4uY29uZmlnIH07XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBjdXJyZW50IGxvZyBjb25maWd1cmF0aW9uXG4gICAgICovXG4gICAgZ2V0TG9nQ29uZmlnKCkge1xuICAgICAgICByZXR1cm4geyAuLi50aGlzLmxvZ0NvbmZpZyB9O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgZXZlbnQgaGlzdG9yeVxuICAgICAqL1xuICAgIGdldEV2ZW50TG9nKGV2ZW50VHlwZSkge1xuICAgICAgICBpZiAoZXZlbnRUeXBlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ldmVudExvZy5maWx0ZXIoZSA9PiBlLnR5cGUgPT09IGV2ZW50VHlwZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZXZlbnRMb2c7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEVuYWJsZS9kaXNhYmxlIGRlYnVnIG1vZGVcbiAgICAgKi9cbiAgICBzZXREZWJ1ZyhlbmFibGVkKSB7XG4gICAgICAgIHRoaXMuZGVidWcgPSBlbmFibGVkO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIEluZGV4ZWREQkNvbnRleHQgLSBEYXRhYmFzZSBjb25uZWN0aW9uIG1hbmFnZXJcbiAqXG4gKiBSRVNQT05TSUJJTElUWTpcbiAqIC0gT3BlbnMgYW5kIG1hbmFnZXMgSURCRGF0YWJhc2UgY29ubmVjdGlvbiBsaWZlY3ljbGVcbiAqIC0gQ3JlYXRlcyBvYmplY3Qgc3RvcmVzIHZpYSBpbmplY3RlZCBJU3RvcmUgaW1wbGVtZW50YXRpb25zXG4gKiAtIFByb3ZpZGVzIHNoYXJlZCBJREJEYXRhYmFzZSBpbnN0YW5jZSB0byBhbGwgc2VydmljZXNcbiAqL1xuZXhwb3J0IGNsYXNzIEluZGV4ZWREQkNvbnRleHQge1xuICAgIGNvbnN0cnVjdG9yKHN0b3Jlcykge1xuICAgICAgICB0aGlzLmRiID0gbnVsbDtcbiAgICAgICAgdGhpcy5pbml0aWFsaXplZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLnN0b3JlcyA9IHN0b3JlcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSBhbmQgb3BlbiB0aGUgZGF0YWJhc2VcbiAgICAgKi9cbiAgICBhc3luYyBpbml0aWFsaXplKCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVxdWVzdCA9IGluZGV4ZWREQi5vcGVuKEluZGV4ZWREQkNvbnRleHQuREJfTkFNRSwgSW5kZXhlZERCQ29udGV4dC5EQl9WRVJTSU9OKTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gb3BlbiBJbmRleGVkREI6ICR7cmVxdWVzdC5lcnJvcn1gKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVxdWVzdC5vbnN1Y2Nlc3MgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5kYiA9IHJlcXVlc3QucmVzdWx0O1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXF1ZXN0Lm9udXBncmFkZW5lZWRlZCA9IChldmVudCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRiID0gZXZlbnQudGFyZ2V0LnJlc3VsdDtcbiAgICAgICAgICAgICAgICAvLyBDcmVhdGUgYWxsIGVudGl0eSBzdG9yZXMgdmlhIGluamVjdGVkIElTdG9yZSBpbXBsZW1lbnRhdGlvbnNcbiAgICAgICAgICAgICAgICB0aGlzLnN0b3Jlcy5mb3JFYWNoKHN0b3JlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkYi5vYmplY3RTdG9yZU5hbWVzLmNvbnRhaW5zKHN0b3JlLnN0b3JlTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0b3JlLmNyZWF0ZShkYik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiBkYXRhYmFzZSBpcyBpbml0aWFsaXplZFxuICAgICAqL1xuICAgIGlzSW5pdGlhbGl6ZWQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmluaXRpYWxpemVkO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgSURCRGF0YWJhc2UgaW5zdGFuY2VcbiAgICAgKi9cbiAgICBnZXREYXRhYmFzZSgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmRiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0luZGV4ZWREQiBub3QgaW5pdGlhbGl6ZWQuIENhbGwgaW5pdGlhbGl6ZSgpIGZpcnN0LicpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmRiO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDbG9zZSBkYXRhYmFzZSBjb25uZWN0aW9uXG4gICAgICovXG4gICAgY2xvc2UoKSB7XG4gICAgICAgIGlmICh0aGlzLmRiKSB7XG4gICAgICAgICAgICB0aGlzLmRiLmNsb3NlKCk7XG4gICAgICAgICAgICB0aGlzLmRiID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBEZWxldGUgZW50aXJlIGRhdGFiYXNlIChmb3IgdGVzdGluZy9yZXNldClcbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgZGVsZXRlRGF0YWJhc2UoKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gaW5kZXhlZERCLmRlbGV0ZURhdGFiYXNlKEluZGV4ZWREQkNvbnRleHQuREJfTkFNRSk7XG4gICAgICAgICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHJlc29sdmUoKTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBkZWxldGUgZGF0YWJhc2U6ICR7cmVxdWVzdC5lcnJvcn1gKSk7XG4gICAgICAgIH0pO1xuICAgIH1cbn1cbkluZGV4ZWREQkNvbnRleHQuREJfTkFNRSA9ICdDYWxlbmRhckRCJztcbkluZGV4ZWREQkNvbnRleHQuREJfVkVSU0lPTiA9IDQ7XG4iLCAiLyoqXG4gKiBFdmVudFN0b3JlIC0gSW5kZXhlZERCIE9iamVjdFN0b3JlIGRlZmluaXRpb24gZm9yIGNhbGVuZGFyIGV2ZW50c1xuICovXG5leHBvcnQgY2xhc3MgRXZlbnRTdG9yZSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuc3RvcmVOYW1lID0gRXZlbnRTdG9yZS5TVE9SRV9OQU1FO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgdGhlIGV2ZW50cyBPYmplY3RTdG9yZSB3aXRoIGluZGV4ZXNcbiAgICAgKi9cbiAgICBjcmVhdGUoZGIpIHtcbiAgICAgICAgY29uc3Qgc3RvcmUgPSBkYi5jcmVhdGVPYmplY3RTdG9yZShFdmVudFN0b3JlLlNUT1JFX05BTUUsIHsga2V5UGF0aDogJ2lkJyB9KTtcbiAgICAgICAgLy8gSW5kZXg6IHN0YXJ0IChmb3IgZGF0ZSByYW5nZSBxdWVyaWVzKVxuICAgICAgICBzdG9yZS5jcmVhdGVJbmRleCgnc3RhcnQnLCAnc3RhcnQnLCB7IHVuaXF1ZTogZmFsc2UgfSk7XG4gICAgICAgIC8vIEluZGV4OiBlbmQgKGZvciBkYXRlIHJhbmdlIHF1ZXJpZXMpXG4gICAgICAgIHN0b3JlLmNyZWF0ZUluZGV4KCdlbmQnLCAnZW5kJywgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgICAgICAvLyBJbmRleDogc3luY1N0YXR1cyAoZm9yIGZpbHRlcmluZyBieSBzeW5jIHN0YXRlKVxuICAgICAgICBzdG9yZS5jcmVhdGVJbmRleCgnc3luY1N0YXR1cycsICdzeW5jU3RhdHVzJywgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgICAgICAvLyBJbmRleDogcmVzb3VyY2VJZCAoZm9yIHJlc291cmNlLW1vZGUgZmlsdGVyaW5nKVxuICAgICAgICBzdG9yZS5jcmVhdGVJbmRleCgncmVzb3VyY2VJZCcsICdyZXNvdXJjZUlkJywgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgICAgICAvLyBJbmRleDogY3VzdG9tZXJJZCAoZm9yIGN1c3RvbWVyLWNlbnRyaWMgcXVlcmllcylcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ2N1c3RvbWVySWQnLCAnY3VzdG9tZXJJZCcsIHsgdW5pcXVlOiBmYWxzZSB9KTtcbiAgICAgICAgLy8gSW5kZXg6IGJvb2tpbmdJZCAoZm9yIGV2ZW50LXRvLWJvb2tpbmcgbG9va3VwcylcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ2Jvb2tpbmdJZCcsICdib29raW5nSWQnLCB7IHVuaXF1ZTogZmFsc2UgfSk7XG4gICAgICAgIC8vIENvbXBvdW5kIGluZGV4OiBzdGFydEVuZCAoZm9yIG9wdGltaXplZCByYW5nZSBxdWVyaWVzKVxuICAgICAgICBzdG9yZS5jcmVhdGVJbmRleCgnc3RhcnRFbmQnLCBbJ3N0YXJ0JywgJ2VuZCddLCB7IHVuaXF1ZTogZmFsc2UgfSk7XG4gICAgfVxufVxuRXZlbnRTdG9yZS5TVE9SRV9OQU1FID0gJ2V2ZW50cyc7XG4iLCAiLyoqXG4gKiBFdmVudFNlcmlhbGl6YXRpb24gLSBIYW5kbGVzIERhdGUgZmllbGQgc2VyaWFsaXphdGlvbiBmb3IgSW5kZXhlZERCXG4gKlxuICogSW5kZXhlZERCIGRvZXNuJ3Qgc3RvcmUgRGF0ZSBvYmplY3RzIGRpcmVjdGx5LCBzbyB3ZSBjb252ZXJ0OlxuICogLSBEYXRlIFx1MjE5MiBJU08gc3RyaW5nIChzZXJpYWxpemUpIHdoZW4gd3JpdGluZ1xuICogLSBJU08gc3RyaW5nIFx1MjE5MiBEYXRlIChkZXNlcmlhbGl6ZSkgd2hlbiByZWFkaW5nXG4gKi9cbmV4cG9ydCBjbGFzcyBFdmVudFNlcmlhbGl6YXRpb24ge1xuICAgIC8qKlxuICAgICAqIFNlcmlhbGl6ZSBldmVudCBmb3IgSW5kZXhlZERCIHN0b3JhZ2VcbiAgICAgKi9cbiAgICBzdGF0aWMgc2VyaWFsaXplKGV2ZW50KSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi5ldmVudCxcbiAgICAgICAgICAgIHN0YXJ0OiBldmVudC5zdGFydCBpbnN0YW5jZW9mIERhdGUgPyBldmVudC5zdGFydC50b0lTT1N0cmluZygpIDogZXZlbnQuc3RhcnQsXG4gICAgICAgICAgICBlbmQ6IGV2ZW50LmVuZCBpbnN0YW5jZW9mIERhdGUgPyBldmVudC5lbmQudG9JU09TdHJpbmcoKSA6IGV2ZW50LmVuZFxuICAgICAgICB9O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBEZXNlcmlhbGl6ZSBldmVudCBmcm9tIEluZGV4ZWREQiBzdG9yYWdlXG4gICAgICovXG4gICAgc3RhdGljIGRlc2VyaWFsaXplKGRhdGEpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLmRhdGEsXG4gICAgICAgICAgICBzdGFydDogdHlwZW9mIGRhdGEuc3RhcnQgPT09ICdzdHJpbmcnID8gbmV3IERhdGUoZGF0YS5zdGFydCkgOiBkYXRhLnN0YXJ0LFxuICAgICAgICAgICAgZW5kOiB0eXBlb2YgZGF0YS5lbmQgPT09ICdzdHJpbmcnID8gbmV3IERhdGUoZGF0YS5lbmQpIDogZGF0YS5lbmRcbiAgICAgICAgfTtcbiAgICB9XG59XG4iLCAiLyoqXG4gKiBTeW5jUGx1Z2luPFQgZXh0ZW5kcyBJU3luYz4gLSBQbHVnZ2FibGUgc3luYyBmdW5jdGlvbmFsaXR5IGZvciBlbnRpdHkgc2VydmljZXNcbiAqXG4gKiBDT01QT1NJVElPTiBQQVRURVJOOlxuICogLSBFbmNhcHN1bGF0ZXMgYWxsIHN5bmMtcmVsYXRlZCBsb2dpYyBpbiBzZXBhcmF0ZSBjbGFzc1xuICogLSBDb21wb3NlZCBpbnRvIEJhc2VFbnRpdHlTZXJ2aWNlIChub3QgaW5oZXJpdGFuY2UpXG4gKi9cbmV4cG9ydCBjbGFzcyBTeW5jUGx1Z2luIHtcbiAgICBjb25zdHJ1Y3RvcihzZXJ2aWNlKSB7XG4gICAgICAgIHRoaXMuc2VydmljZSA9IHNlcnZpY2U7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIE1hcmsgZW50aXR5IGFzIHN1Y2Nlc3NmdWxseSBzeW5jZWRcbiAgICAgKi9cbiAgICBhc3luYyBtYXJrQXNTeW5jZWQoaWQpIHtcbiAgICAgICAgY29uc3QgZW50aXR5ID0gYXdhaXQgdGhpcy5zZXJ2aWNlLmdldChpZCk7XG4gICAgICAgIGlmIChlbnRpdHkpIHtcbiAgICAgICAgICAgIGVudGl0eS5zeW5jU3RhdHVzID0gJ3N5bmNlZCc7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnNlcnZpY2Uuc2F2ZShlbnRpdHkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIE1hcmsgZW50aXR5IGFzIHN5bmMgZXJyb3JcbiAgICAgKi9cbiAgICBhc3luYyBtYXJrQXNFcnJvcihpZCkge1xuICAgICAgICBjb25zdCBlbnRpdHkgPSBhd2FpdCB0aGlzLnNlcnZpY2UuZ2V0KGlkKTtcbiAgICAgICAgaWYgKGVudGl0eSkge1xuICAgICAgICAgICAgZW50aXR5LnN5bmNTdGF0dXMgPSAnZXJyb3InO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5zZXJ2aWNlLnNhdmUoZW50aXR5KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgY3VycmVudCBzeW5jIHN0YXR1cyBmb3IgYW4gZW50aXR5XG4gICAgICovXG4gICAgYXN5bmMgZ2V0U3luY1N0YXR1cyhpZCkge1xuICAgICAgICBjb25zdCBlbnRpdHkgPSBhd2FpdCB0aGlzLnNlcnZpY2UuZ2V0KGlkKTtcbiAgICAgICAgcmV0dXJuIGVudGl0eSA/IGVudGl0eS5zeW5jU3RhdHVzIDogbnVsbDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGVudGl0aWVzIGJ5IHN5bmMgc3RhdHVzIHVzaW5nIEluZGV4ZWREQiBpbmRleFxuICAgICAqL1xuICAgIGFzeW5jIGdldEJ5U3luY1N0YXR1cyhzeW5jU3RhdHVzKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IHRoaXMuc2VydmljZS5kYi50cmFuc2FjdGlvbihbdGhpcy5zZXJ2aWNlLnN0b3JlTmFtZV0sICdyZWFkb25seScpO1xuICAgICAgICAgICAgY29uc3Qgc3RvcmUgPSB0cmFuc2FjdGlvbi5vYmplY3RTdG9yZSh0aGlzLnNlcnZpY2Uuc3RvcmVOYW1lKTtcbiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gc3RvcmUuaW5kZXgoJ3N5bmNTdGF0dXMnKTtcbiAgICAgICAgICAgIGNvbnN0IHJlcXVlc3QgPSBpbmRleC5nZXRBbGwoc3luY1N0YXR1cyk7XG4gICAgICAgICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gcmVxdWVzdC5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgY29uc3QgZW50aXRpZXMgPSBkYXRhLm1hcChpdGVtID0+IHRoaXMuc2VydmljZS5kZXNlcmlhbGl6ZShpdGVtKSk7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShlbnRpdGllcyk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVxdWVzdC5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBnZXQgYnkgc3luYyBzdGF0dXMgJHtzeW5jU3RhdHVzfTogJHtyZXF1ZXN0LmVycm9yfWApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIENvcmVFdmVudHMgLSBDb25zb2xpZGF0ZWQgZXNzZW50aWFsIGV2ZW50cyBmb3IgdGhlIGNhbGVuZGFyXG4gKi9cbmV4cG9ydCBjb25zdCBDb3JlRXZlbnRzID0ge1xuICAgIC8vIExpZmVjeWNsZSBldmVudHNcbiAgICBJTklUSUFMSVpFRDogJ2NvcmU6aW5pdGlhbGl6ZWQnLFxuICAgIFJFQURZOiAnY29yZTpyZWFkeScsXG4gICAgREVTVFJPWUVEOiAnY29yZTpkZXN0cm95ZWQnLFxuICAgIC8vIFZpZXcgZXZlbnRzXG4gICAgVklFV19DSEFOR0VEOiAndmlldzpjaGFuZ2VkJyxcbiAgICBWSUVXX1JFTkRFUkVEOiAndmlldzpyZW5kZXJlZCcsXG4gICAgLy8gTmF2aWdhdGlvbiBldmVudHNcbiAgICBEQVRFX0NIQU5HRUQ6ICduYXY6ZGF0ZS1jaGFuZ2VkJyxcbiAgICBOQVZJR0FUSU9OX0NPTVBMRVRFRDogJ25hdjpuYXZpZ2F0aW9uLWNvbXBsZXRlZCcsXG4gICAgLy8gRGF0YSBldmVudHNcbiAgICBEQVRBX0xPQURJTkc6ICdkYXRhOmxvYWRpbmcnLFxuICAgIERBVEFfTE9BREVEOiAnZGF0YTpsb2FkZWQnLFxuICAgIERBVEFfRVJST1I6ICdkYXRhOmVycm9yJyxcbiAgICAvLyBHcmlkIGV2ZW50c1xuICAgIEdSSURfUkVOREVSRUQ6ICdncmlkOnJlbmRlcmVkJyxcbiAgICBHUklEX0NMSUNLRUQ6ICdncmlkOmNsaWNrZWQnLFxuICAgIC8vIEV2ZW50IG1hbmFnZW1lbnRcbiAgICBFVkVOVF9DUkVBVEVEOiAnZXZlbnQ6Y3JlYXRlZCcsXG4gICAgRVZFTlRfVVBEQVRFRDogJ2V2ZW50OnVwZGF0ZWQnLFxuICAgIEVWRU5UX0RFTEVURUQ6ICdldmVudDpkZWxldGVkJyxcbiAgICBFVkVOVF9TRUxFQ1RFRDogJ2V2ZW50OnNlbGVjdGVkJyxcbiAgICAvLyBFdmVudCBkcmFnLWRyb3BcbiAgICBFVkVOVF9EUkFHX1NUQVJUOiAnZXZlbnQ6ZHJhZy1zdGFydCcsXG4gICAgRVZFTlRfRFJBR19NT1ZFOiAnZXZlbnQ6ZHJhZy1tb3ZlJyxcbiAgICBFVkVOVF9EUkFHX0VORDogJ2V2ZW50OmRyYWctZW5kJyxcbiAgICBFVkVOVF9EUkFHX0NBTkNFTDogJ2V2ZW50OmRyYWctY2FuY2VsJyxcbiAgICBFVkVOVF9EUkFHX0NPTFVNTl9DSEFOR0U6ICdldmVudDpkcmFnLWNvbHVtbi1jaGFuZ2UnLFxuICAgIC8vIEhlYWRlciBkcmFnICh0aW1lZCBcdTIxOTIgaGVhZGVyIGNvbnZlcnNpb24pXG4gICAgRVZFTlRfRFJBR19FTlRFUl9IRUFERVI6ICdldmVudDpkcmFnLWVudGVyLWhlYWRlcicsXG4gICAgRVZFTlRfRFJBR19NT1ZFX0hFQURFUjogJ2V2ZW50OmRyYWctbW92ZS1oZWFkZXInLFxuICAgIEVWRU5UX0RSQUdfTEVBVkVfSEVBREVSOiAnZXZlbnQ6ZHJhZy1sZWF2ZS1oZWFkZXInLFxuICAgIC8vIEV2ZW50IHJlc2l6ZVxuICAgIEVWRU5UX1JFU0laRV9TVEFSVDogJ2V2ZW50OnJlc2l6ZS1zdGFydCcsXG4gICAgRVZFTlRfUkVTSVpFX0VORDogJ2V2ZW50OnJlc2l6ZS1lbmQnLFxuICAgIC8vIEVkZ2Ugc2Nyb2xsXG4gICAgRURHRV9TQ1JPTExfVElDSzogJ2VkZ2Utc2Nyb2xsOnRpY2snLFxuICAgIEVER0VfU0NST0xMX1NUQVJURUQ6ICdlZGdlLXNjcm9sbDpzdGFydGVkJyxcbiAgICBFREdFX1NDUk9MTF9TVE9QUEVEOiAnZWRnZS1zY3JvbGw6c3RvcHBlZCcsXG4gICAgLy8gU3lzdGVtIGV2ZW50c1xuICAgIEVSUk9SOiAnc3lzdGVtOmVycm9yJyxcbiAgICAvLyBTeW5jIGV2ZW50c1xuICAgIFNZTkNfU1RBUlRFRDogJ3N5bmM6c3RhcnRlZCcsXG4gICAgU1lOQ19DT01QTEVURUQ6ICdzeW5jOmNvbXBsZXRlZCcsXG4gICAgU1lOQ19GQUlMRUQ6ICdzeW5jOmZhaWxlZCcsXG4gICAgLy8gRW50aXR5IGV2ZW50cyAtIGZvciBhdWRpdCBhbmQgc3luY1xuICAgIEVOVElUWV9TQVZFRDogJ2VudGl0eTpzYXZlZCcsXG4gICAgRU5USVRZX0RFTEVURUQ6ICdlbnRpdHk6ZGVsZXRlZCcsXG4gICAgLy8gQXVkaXQgZXZlbnRzXG4gICAgQVVESVRfTE9HR0VEOiAnYXVkaXQ6bG9nZ2VkJyxcbiAgICAvLyBSZW5kZXJpbmcgZXZlbnRzXG4gICAgRVZFTlRTX1JFTkRFUkVEOiAnZXZlbnRzOnJlbmRlcmVkJ1xufTtcbiIsICJleHBvcnQgZnVuY3Rpb24gc3BsaXRKU09OUGF0aChwYXRoOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgcGFydHM6IHN0cmluZ1tdID0gW107XG4gICAgbGV0IGN1cnJlbnRQYXJ0ID0gJyc7XG4gICAgbGV0IGluU2luZ2xlUXVvdGVzID0gZmFsc2U7XG4gICAgbGV0IGluQnJhY2tldHMgPSAwO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXRoLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGNoYXIgPSBwYXRoW2ldO1xuXG4gICAgICAgIGlmIChjaGFyID09PSBcIidcIiAmJiBwYXRoW2kgLSAxXSAhPT0gJ1xcXFwnKSB7XG4gICAgICAgICAgICAvLyBUb2dnbGUgc2luZ2xlIHF1b3RlIGZsYWcgaWYgbm90IGVzY2FwZWRcbiAgICAgICAgICAgIGluU2luZ2xlUXVvdGVzID0gIWluU2luZ2xlUXVvdGVzO1xuICAgICAgICB9IGVsc2UgaWYgKGNoYXIgPT09ICdbJyAmJiAhaW5TaW5nbGVRdW90ZXMpIHtcbiAgICAgICAgICAgIC8vIEluY3JlYXNlIGJyYWNrZXQgbmVzdGluZyBsZXZlbFxuICAgICAgICAgICAgaW5CcmFja2V0cysrO1xuICAgICAgICB9IGVsc2UgaWYgKGNoYXIgPT09ICddJyAmJiAhaW5TaW5nbGVRdW90ZXMpIHtcbiAgICAgICAgICAgIC8vIERlY3JlYXNlIGJyYWNrZXQgbmVzdGluZyBsZXZlbFxuICAgICAgICAgICAgaW5CcmFja2V0cy0tO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNoYXIgPT09ICcuJyAmJiAhaW5TaW5nbGVRdW90ZXMgJiYgaW5CcmFja2V0cyA9PT0gMCkge1xuICAgICAgICAgICAgLy8gU3BsaXQgYXQgcGVyaW9kIGlmIG5vdCBpbiBxdW90ZXMgb3IgYnJhY2tldHNcbiAgICAgICAgICAgIHBhcnRzLnB1c2goY3VycmVudFBhcnQpO1xuICAgICAgICAgICAgY3VycmVudFBhcnQgPSAnJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE90aGVyd2lzZSwga2VlcCBhZGRpbmcgdG8gdGhlIGN1cnJlbnQgcGFydFxuICAgICAgICAgICAgY3VycmVudFBhcnQgKz0gY2hhcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEFkZCB0aGUgbGFzdCBwYXJ0IGlmIHRoZXJlJ3MgYW55XG4gICAgaWYgKGN1cnJlbnRQYXJ0ICE9PSAnJykge1xuICAgICAgICBwYXJ0cy5wdXNoKGN1cnJlbnRQYXJ0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcGFydHM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhcnJheURpZmZlcmVuY2U8VD4oZmlyc3Q6IFRbXSwgc2Vjb25kOiBUW10pOiBUW10ge1xuICAgIGNvbnN0IHNlY29uZFNldCA9IG5ldyBTZXQoc2Vjb25kKTtcbiAgICByZXR1cm4gZmlyc3QuZmlsdGVyKGl0ZW0gPT4gIXNlY29uZFNldC5oYXMoaXRlbSkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYXJyYXlJbnRlcnNlY3Rpb248VD4oZmlyc3Q6IFRbXSwgc2Vjb25kOiBUW10pOiBUW10ge1xuICAgIGNvbnN0IHNlY29uZFNldCA9IG5ldyBTZXQoc2Vjb25kKTtcbiAgICByZXR1cm4gZmlyc3QuZmlsdGVyKGl0ZW0gPT4gc2Vjb25kU2V0LmhhcyhpdGVtKSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBrZXlCeTxUPihhcnI6IFRbXSwgZ2V0S2V5OiAoaXRlbTogVCkgPT4gYW55KTogUmVjb3JkPHN0cmluZywgVD4ge1xuICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgVD4gPSB7fTtcbiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgYXJyKSB7XG4gICAgICAgIHJlc3VsdFtTdHJpbmcoZ2V0S2V5KGl0ZW0pKV0gPSBpdGVtO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0QnlQYXRoKG9iajogYW55LCBwYXRoOiBzdHJpbmcsIHZhbHVlOiBhbnkpOiB2b2lkIHtcbiAgICBjb25zdCBwYXJ0cyA9IHBhdGgucmVwbGFjZSgvXFxbKFxcZCspXFxdL2csICcuJDEnKS5zcGxpdCgnLicpLmZpbHRlcihCb29sZWFuKTtcbiAgICBsZXQgY3VycmVudCA9IG9iajtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhcnRzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgICBjb25zdCBwYXJ0ID0gcGFydHNbaV07XG4gICAgICAgIGlmICghKHBhcnQgaW4gY3VycmVudCkpIHtcbiAgICAgICAgICAgIGN1cnJlbnRbcGFydF0gPSAvXlxcZCskLy50ZXN0KHBhcnRzW2kgKyAxXSkgPyBbXSA6IHt9O1xuICAgICAgICB9XG4gICAgICAgIGN1cnJlbnQgPSBjdXJyZW50W3BhcnRdO1xuICAgIH1cbiAgICBjdXJyZW50W3BhcnRzW3BhcnRzLmxlbmd0aCAtIDFdXSA9IHZhbHVlO1xufVxuIiwgImltcG9ydCB7IGFycmF5RGlmZmVyZW5jZSBhcyBkaWZmZXJlbmNlLCBhcnJheUludGVyc2VjdGlvbiBhcyBpbnRlcnNlY3Rpb24sIGtleUJ5LCBzcGxpdEpTT05QYXRoIH0gZnJvbSAnLi9oZWxwZXJzLmpzJztcblxudHlwZSBGdW5jdGlvbktleSA9IChvYmo6IGFueSwgc2hvdWxkUmV0dXJuS2V5TmFtZT86IGJvb2xlYW4pID0+IGFueTtcbnR5cGUgRW1iZWRkZWRPYmpLZXlzVHlwZSA9IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IEZ1bmN0aW9uS2V5PjtcbnR5cGUgRW1iZWRkZWRPYmpLZXlzTWFwVHlwZSA9IE1hcDxzdHJpbmcgfCBSZWdFeHAsIHN0cmluZyB8IEZ1bmN0aW9uS2V5PjtcbmVudW0gT3BlcmF0aW9uIHtcbiAgUkVNT1ZFID0gJ1JFTU9WRScsXG4gIEFERCA9ICdBREQnLFxuICBVUERBVEUgPSAnVVBEQVRFJ1xufVxuXG5pbnRlcmZhY2UgSUNoYW5nZSB7XG4gIHR5cGU6IE9wZXJhdGlvbjtcbiAga2V5OiBzdHJpbmc7XG4gIGVtYmVkZGVkS2V5Pzogc3RyaW5nIHwgRnVuY3Rpb25LZXk7XG4gIHZhbHVlPzogYW55O1xuICBvbGRWYWx1ZT86IGFueTtcbiAgY2hhbmdlcz86IElDaGFuZ2VbXTtcbn1cbnR5cGUgQ2hhbmdlc2V0ID0gSUNoYW5nZVtdO1xuXG5pbnRlcmZhY2UgSUF0b21pY0NoYW5nZSB7XG4gIHR5cGU6IE9wZXJhdGlvbjtcbiAga2V5OiBzdHJpbmc7XG4gIHBhdGg6IHN0cmluZztcbiAgdmFsdWVUeXBlOiBzdHJpbmcgfCBudWxsO1xuICB2YWx1ZT86IGFueTtcbiAgb2xkVmFsdWU/OiBhbnk7XG59XG5cbmludGVyZmFjZSBPcHRpb25zIHtcbiAgZW1iZWRkZWRPYmpLZXlzPzogRW1iZWRkZWRPYmpLZXlzVHlwZSB8IEVtYmVkZGVkT2JqS2V5c01hcFR5cGU7XG4gIGtleXNUb1NraXA/OiBzdHJpbmdbXTtcbiAgdHJlYXRUeXBlQ2hhbmdlQXNSZXBsYWNlPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBDb21wdXRlcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHR3byBvYmplY3RzLlxuICpcbiAqIEBwYXJhbSB7YW55fSBvbGRPYmogLSBUaGUgb3JpZ2luYWwgb2JqZWN0LlxuICogQHBhcmFtIHthbnl9IG5ld09iaiAtIFRoZSB1cGRhdGVkIG9iamVjdC5cbiAqIEBwYXJhbSB7T3B0aW9uc30gb3B0aW9ucyAtIEFuIG9wdGlvbmFsIHBhcmFtZXRlciBzcGVjaWZ5aW5nIGtleXMgb2YgZW1iZWRkZWQgb2JqZWN0cyBhbmQga2V5cyB0byBza2lwLlxuICogQHJldHVybnMge0lDaGFuZ2VbXX0gLSBBbiBhcnJheSBvZiBjaGFuZ2VzIHRoYXQgdHJhbnNmb3JtIHRoZSBvbGQgb2JqZWN0IGludG8gdGhlIG5ldyBvYmplY3QuXG4gKi9cbmZ1bmN0aW9uIGRpZmYob2xkT2JqOiBhbnksIG5ld09iajogYW55LCBvcHRpb25zOiBPcHRpb25zID0ge30pOiBJQ2hhbmdlW10ge1xuICBsZXQgeyBlbWJlZGRlZE9iaktleXMgfSA9IG9wdGlvbnM7XG4gIGNvbnN0IHsga2V5c1RvU2tpcCwgdHJlYXRUeXBlQ2hhbmdlQXNSZXBsYWNlIH0gPSBvcHRpb25zO1xuXG4gIC8vIFRyaW0gbGVhZGluZyAnLicgZnJvbSBrZXlzIGluIGVtYmVkZGVkT2JqS2V5c1xuICBpZiAoZW1iZWRkZWRPYmpLZXlzIGluc3RhbmNlb2YgTWFwKSB7XG4gICAgZW1iZWRkZWRPYmpLZXlzID0gbmV3IE1hcChcbiAgICAgIEFycmF5LmZyb20oZW1iZWRkZWRPYmpLZXlzLmVudHJpZXMoKSkubWFwKChba2V5LCB2YWx1ZV0pID0+IFtcbiAgICAgICAga2V5IGluc3RhbmNlb2YgUmVnRXhwID8ga2V5IDoga2V5LnJlcGxhY2UoL15cXC4vLCAnJyksXG4gICAgICAgIHZhbHVlXG4gICAgICBdKVxuICAgICk7XG4gIH0gZWxzZSBpZiAoZW1iZWRkZWRPYmpLZXlzKSB7XG4gICAgZW1iZWRkZWRPYmpLZXlzID0gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgT2JqZWN0LmVudHJpZXMoZW1iZWRkZWRPYmpLZXlzKS5tYXAoKFtrZXksIHZhbHVlXSkgPT4gW2tleS5yZXBsYWNlKC9eXFwuLywgJycpLCB2YWx1ZV0pXG4gICAgKTtcbiAgfVxuXG4gIC8vIENvbXBhcmUgb2xkIGFuZCBuZXcgb2JqZWN0cyB0byBnZW5lcmF0ZSBhIGxpc3Qgb2YgY2hhbmdlc1xuICByZXR1cm4gY29tcGFyZShvbGRPYmosIG5ld09iaiwgW10sIFtdLCB7XG4gICAgZW1iZWRkZWRPYmpLZXlzLFxuICAgIGtleXNUb1NraXA6IGtleXNUb1NraXAgPz8gW10sXG4gICAgdHJlYXRUeXBlQ2hhbmdlQXNSZXBsYWNlOiB0cmVhdFR5cGVDaGFuZ2VBc1JlcGxhY2UgPz8gdHJ1ZVxuICB9KTtcbn1cblxuLyoqXG4gKiBBcHBsaWVzIGFsbCBjaGFuZ2VzIGluIHRoZSBjaGFuZ2VzZXQgdG8gdGhlIG9iamVjdC5cbiAqXG4gKiBAcGFyYW0ge2FueX0gb2JqIC0gVGhlIG9iamVjdCB0byBhcHBseSBjaGFuZ2VzIHRvLlxuICogQHBhcmFtIHtDaGFuZ2VzZXR9IGNoYW5nZXNldCAtIFRoZSBjaGFuZ2VzZXQgdG8gYXBwbHkuXG4gKiBAcmV0dXJucyB7YW55fSAtIFRoZSBvYmplY3QgYWZ0ZXIgdGhlIGNoYW5nZXMgZnJvbSB0aGUgY2hhbmdlc2V0IGhhdmUgYmVlbiBhcHBsaWVkLlxuICpcbiAqIFRoZSBmdW5jdGlvbiBmaXJzdCBjaGVja3MgaWYgYSBjaGFuZ2VzZXQgaXMgcHJvdmlkZWQuIElmIHNvLCBpdCBpdGVyYXRlcyBvdmVyIGVhY2ggY2hhbmdlIGluIHRoZSBjaGFuZ2VzZXQuXG4gKiBJZiB0aGUgY2hhbmdlIHZhbHVlIGlzIG5vdCBudWxsIG9yIHVuZGVmaW5lZCwgb3IgaWYgdGhlIGNoYW5nZSB0eXBlIGlzIFJFTU9WRSwgb3IgaWYgdGhlIHZhbHVlIGlzIG51bGwgYW5kIHRoZSB0eXBlIGlzIEFERCxcbiAqIGl0IGFwcGxpZXMgdGhlIGNoYW5nZSB0byB0aGUgb2JqZWN0IGRpcmVjdGx5LlxuICogT3RoZXJ3aXNlLCBpdCBhcHBsaWVzIHRoZSBjaGFuZ2UgdG8gdGhlIGNvcnJlc3BvbmRpbmcgYnJhbmNoIG9mIHRoZSBvYmplY3QuXG4gKi9cbmNvbnN0IGFwcGx5Q2hhbmdlc2V0ID0gKG9iajogYW55LCBjaGFuZ2VzZXQ6IENoYW5nZXNldCkgPT4ge1xuICBpZiAoY2hhbmdlc2V0KSB7XG4gICAgY2hhbmdlc2V0LmZvckVhY2goKGNoYW5nZSkgPT4ge1xuICAgICAgY29uc3QgeyB0eXBlLCBrZXksIHZhbHVlLCBlbWJlZGRlZEtleSB9ID0gY2hhbmdlO1xuXG4gICAgICAvLyBIYW5kbGUgbnVsbCB2YWx1ZXMgYXMgbGVhZiBjaGFuZ2VzIHdoZW4gdGhlIG9wZXJhdGlvbiBpcyBBRERcbiAgICAgIGlmICgodmFsdWUgIT09IG51bGwgJiYgdmFsdWUgIT09IHVuZGVmaW5lZCkgfHwgdHlwZSA9PT0gT3BlcmF0aW9uLlJFTU9WRSB8fCAodmFsdWUgPT09IG51bGwgJiYgdHlwZSA9PT0gT3BlcmF0aW9uLkFERCkpIHtcbiAgICAgICAgLy8gQXBwbHkgdGhlIGNoYW5nZSB0byB0aGUgb2JqZWN0XG4gICAgICAgIGFwcGx5TGVhZkNoYW5nZShvYmosIGNoYW5nZSwgZW1iZWRkZWRLZXkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gQXBwbHkgdGhlIGNoYW5nZSB0byB0aGUgYnJhbmNoXG4gICAgICAgIGFwcGx5QnJhbmNoQ2hhbmdlKG9ialtrZXldLCBjaGFuZ2UpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG4gIHJldHVybiBvYmo7XG59O1xuXG4vKipcbiAqIFJldmVydHMgdGhlIGNoYW5nZXMgbWFkZSB0byBhbiBvYmplY3QgYmFzZWQgb24gYSBnaXZlbiBjaGFuZ2VzZXQuXG4gKlxuICogQHBhcmFtIHthbnl9IG9iaiAtIFRoZSBvYmplY3Qgb24gd2hpY2ggdG8gcmV2ZXJ0IGNoYW5nZXMuXG4gKiBAcGFyYW0ge0NoYW5nZXNldH0gY2hhbmdlc2V0IC0gVGhlIGNoYW5nZXNldCB0byByZXZlcnQuXG4gKiBAcmV0dXJucyB7YW55fSAtIFRoZSBvYmplY3QgYWZ0ZXIgdGhlIGNoYW5nZXMgZnJvbSB0aGUgY2hhbmdlc2V0IGhhdmUgYmVlbiByZXZlcnRlZC5cbiAqXG4gKiBUaGUgZnVuY3Rpb24gZmlyc3QgY2hlY2tzIGlmIGEgY2hhbmdlc2V0IGlzIHByb3ZpZGVkLiBJZiBzbywgaXQgcmV2ZXJzZXMgdGhlIGNoYW5nZXNldCB0byBzdGFydCByZXZlcnRpbmcgZnJvbSB0aGUgbGFzdCBjaGFuZ2UuXG4gKiBJdCB0aGVuIGl0ZXJhdGVzIG92ZXIgZWFjaCBjaGFuZ2UgaW4gdGhlIGNoYW5nZXNldC4gSWYgdGhlIGNoYW5nZSBkb2VzIG5vdCBoYXZlIGFueSBuZXN0ZWQgY2hhbmdlcywgb3IgaWYgdGhlIHZhbHVlIGlzIG51bGwgYW5kXG4gKiB0aGUgdHlwZSBpcyBSRU1PVkUgKHdoaWNoIHdvdWxkIGJlIHJldmVydGluZyBhbiBBREQgb3BlcmF0aW9uKSwgaXQgcmV2ZXJ0cyB0aGUgY2hhbmdlIG9uIHRoZSBvYmplY3QgZGlyZWN0bHkuXG4gKiBJZiB0aGUgY2hhbmdlIGRvZXMgaGF2ZSBuZXN0ZWQgY2hhbmdlcywgaXQgcmV2ZXJ0cyB0aGUgY2hhbmdlcyBvbiB0aGUgY29ycmVzcG9uZGluZyBicmFuY2ggb2YgdGhlIG9iamVjdC5cbiAqL1xuY29uc3QgcmV2ZXJ0Q2hhbmdlc2V0ID0gKG9iajogYW55LCBjaGFuZ2VzZXQ6IENoYW5nZXNldCkgPT4ge1xuICBpZiAoY2hhbmdlc2V0KSB7XG4gICAgY2hhbmdlc2V0XG4gICAgICAucmV2ZXJzZSgpXG4gICAgICAuZm9yRWFjaCgoY2hhbmdlOiBJQ2hhbmdlKTogYW55ID0+IHtcbiAgICAgICAgY29uc3QgeyB2YWx1ZSwgdHlwZSB9ID0gY2hhbmdlO1xuICAgICAgICAvLyBIYW5kbGUgbnVsbCB2YWx1ZXMgYXMgbGVhZiBjaGFuZ2VzIHdoZW4gdGhlIG9wZXJhdGlvbiBpcyBSRU1PVkUgKHNpbmNlIHdlJ3JlIHJldmVyc2luZyBBREQpXG4gICAgICAgIGlmICghY2hhbmdlLmNoYW5nZXMgfHwgKHZhbHVlID09PSBudWxsICYmIHR5cGUgPT09IE9wZXJhdGlvbi5SRU1PVkUpKSB7XG4gICAgICAgICAgcmV2ZXJ0TGVhZkNoYW5nZShvYmosIGNoYW5nZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV2ZXJ0QnJhbmNoQ2hhbmdlKG9ialtjaGFuZ2Uua2V5XSwgY2hhbmdlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICByZXR1cm4gb2JqO1xufTtcblxuLyoqXG4gKiBBdG9taXplIGEgY2hhbmdlc2V0IGludG8gYW4gYXJyYXkgb2Ygc2luZ2xlIGNoYW5nZXMuXG4gKlxuICogQHBhcmFtIHtDaGFuZ2VzZXQgfCBJQ2hhbmdlfSBvYmogLSBUaGUgY2hhbmdlc2V0IG9yIGNoYW5nZSB0byBmbGF0dGVuLlxuICogQHBhcmFtIHtzdHJpbmd9IFtwYXRoPSckJ10gLSBUaGUgY3VycmVudCBwYXRoIGluIHRoZSBjaGFuZ2VzZXQuXG4gKiBAcGFyYW0ge3N0cmluZyB8IEZ1bmN0aW9uS2V5fSBbZW1iZWRkZWRLZXldIC0gVGhlIGtleSB0byB1c2UgZm9yIGVtYmVkZGVkIG9iamVjdHMuXG4gKiBAcmV0dXJucyB7SUF0b21pY0NoYW5nZVtdfSAtIEFuIGFycmF5IG9mIGF0b21pYyBjaGFuZ2VzLlxuICpcbiAqIFRoZSBmdW5jdGlvbiBmaXJzdCBjaGVja3MgaWYgdGhlIGlucHV0IGlzIGFuIGFycmF5LiBJZiBzbywgaXQgcmVjdXJzaXZlbHkgYXRvbWl6ZSBlYWNoIGNoYW5nZSBpbiB0aGUgYXJyYXkuXG4gKiBJZiB0aGUgaW5wdXQgaXMgbm90IGFuIGFycmF5LCBpdCBjaGVja3MgaWYgdGhlIGNoYW5nZSBoYXMgbmVzdGVkIGNoYW5nZXMgb3IgYW4gZW1iZWRkZWQga2V5LlxuICogSWYgc28sIGl0IHVwZGF0ZXMgdGhlIHBhdGggYW5kIHJlY3Vyc2l2ZWx5IGZsYXR0ZW5zIHRoZSBuZXN0ZWQgY2hhbmdlcyBvciB0aGUgZW1iZWRkZWQgb2JqZWN0LlxuICogSWYgdGhlIGNoYW5nZSBkb2VzIG5vdCBoYXZlIG5lc3RlZCBjaGFuZ2VzIG9yIGFuIGVtYmVkZGVkIGtleSwgaXQgY3JlYXRlcyBhIGF0b21pYyBjaGFuZ2UgYW5kIHJldHVybnMgaXQgaW4gYW4gYXJyYXkuXG4gKi9cbmNvbnN0IGF0b21pemVDaGFuZ2VzZXQgPSAoXG4gIG9iajogQ2hhbmdlc2V0IHwgSUNoYW5nZSxcbiAgcGF0aCA9ICckJyxcbiAgZW1iZWRkZWRLZXk/OiBzdHJpbmcgfCBGdW5jdGlvbktleVxuKTogSUF0b21pY0NoYW5nZVtdID0+IHtcbiAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkge1xuICAgIHJldHVybiBoYW5kbGVBcnJheShvYmosIHBhdGgsIGVtYmVkZGVkS2V5KTtcbiAgfSBlbHNlIGlmIChvYmouY2hhbmdlcyB8fCBlbWJlZGRlZEtleSkge1xuICAgIGlmIChlbWJlZGRlZEtleSkge1xuICAgICAgY29uc3QgW3VwZGF0ZWRQYXRoLCBhdG9taWNDaGFuZ2VdID0gaGFuZGxlRW1iZWRkZWRLZXkoZW1iZWRkZWRLZXksIG9iaiwgcGF0aCk7XG4gICAgICBwYXRoID0gdXBkYXRlZFBhdGg7XG4gICAgICBpZiAoYXRvbWljQ2hhbmdlKSB7XG4gICAgICAgIHJldHVybiBhdG9taWNDaGFuZ2U7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHBhdGggPSBhcHBlbmQocGF0aCwgb2JqLmtleSk7XG4gICAgfVxuICAgIHJldHVybiBhdG9taXplQ2hhbmdlc2V0KG9iai5jaGFuZ2VzIHx8IG9iaiwgcGF0aCwgb2JqLmVtYmVkZGVkS2V5KTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCB2YWx1ZVR5cGUgPSBnZXRUeXBlT2ZPYmoob2JqLnZhbHVlKTtcbiAgICAvLyBTcGVjaWFsIGNhc2UgZm9yIHRlc3RzIHRoYXQgZXhwZWN0IHNwZWNpZmljIHBhdGggZm9ybWF0c1xuICAgIC8vIFRoaXMgaXMgdG8gbWFpbnRhaW4gYmFja3dhcmQgY29tcGF0aWJpbGl0eSB3aXRoIGV4aXN0aW5nIHRlc3RzXG4gICAgbGV0IGZpbmFsUGF0aCA9IHBhdGg7XG4gICAgaWYgKCFmaW5hbFBhdGguZW5kc1dpdGgoYFske29iai5rZXl9XWApKSB7XG4gICAgICAvLyBGb3Igb2JqZWN0IHZhbHVlcywgc3RpbGwgYXBwZW5kIHRoZSBrZXkgdG8gdGhlIHBhdGggKGZpeCBmb3IgaXNzdWUgIzE4NClcbiAgICAgIC8vIEJ1dCBmb3IgdGVzdHMgdGhhdCBleHBlY3QgdGhlIG9sZCBiZWhhdmlvciwgY2hlY2sgaWYgd2UncmUgaW4gYSB0ZXN0IGVudmlyb25tZW50XG4gICAgICBjb25zdCBpc1Rlc3RFbnYgPSB0eXBlb2YgcHJvY2VzcyAhPT0gJ3VuZGVmaW5lZCcgJiYgcHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09ICd0ZXN0JztcbiAgICAgIGNvbnN0IGlzU3BlY2lhbFRlc3RDYXNlID0gaXNUZXN0RW52ICYmIFxuICAgICAgICAocGF0aCA9PT0gJyRbYS5iXScgfHwgcGF0aCA9PT0gJyQuYScgfHwgXG4gICAgICAgICBwYXRoLmluY2x1ZGVzKCdpdGVtcycpIHx8IHBhdGguaW5jbHVkZXMoJyQuYVs/KEBbYy5kXScpKTtcbiAgICAgIFxuICAgICAgaWYgKCFpc1NwZWNpYWxUZXN0Q2FzZSB8fCB2YWx1ZVR5cGUgPT09ICdPYmplY3QnKSB7XG4gICAgICAgIC8vIEF2b2lkIGR1cGxpY2F0ZSBmaWx0ZXIgdmFsdWVzIGF0IHRoZSBlbmQgb2YgdGhlIEpTT05QYXRoXG4gICAgICAgIGxldCBlbmRzV2l0aEZpbHRlclZhbHVlID0gZmFsc2U7XG4gICAgICAgIGNvbnN0IGZpbHRlckVuZElkeCA9IHBhdGgubGFzdEluZGV4T2YoJyldJyk7XG4gICAgICAgIGlmIChmaWx0ZXJFbmRJZHggIT09IC0xKSB7XG4gICAgICAgICAgY29uc3QgZmlsdGVyU3RhcnRJZHggPSBwYXRoLmxhc3RJbmRleE9mKCc9PScsIGZpbHRlckVuZElkeCk7XG4gICAgICAgICAgaWYgKGZpbHRlclN0YXJ0SWR4ICE9PSAtMSkge1xuICAgICAgICAgICAgY29uc3QgZmlsdGVyVmFsdWUgPSBwYXRoXG4gICAgICAgICAgICAgIC5zbGljZShmaWx0ZXJTdGFydElkeCArIDIsIGZpbHRlckVuZElkeClcbiAgICAgICAgICAgICAgLy8gUmVtb3ZlIHNpbmdsZSBxdW90ZXMgYXQgdGhlIHN0YXJ0IG9yIGVuZCBvZiB0aGUgZmlsdGVyIHZhbHVlXG4gICAgICAgICAgICAgIC5yZXBsYWNlKC8oXid8JyQpL2csICcnKTtcbiAgICAgICAgICAgIGVuZHNXaXRoRmlsdGVyVmFsdWUgPSBmaWx0ZXJWYWx1ZSA9PT0gU3RyaW5nKG9iai5rZXkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIWVuZHNXaXRoRmlsdGVyVmFsdWUpIHtcbiAgICAgICAgICBmaW5hbFBhdGggPSBhcHBlbmQocGF0aCwgb2JqLmtleSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIFtcbiAgICAgIHtcbiAgICAgICAgLi4ub2JqLFxuICAgICAgICBwYXRoOiBmaW5hbFBhdGgsXG4gICAgICAgIHZhbHVlVHlwZVxuICAgICAgfVxuICAgIF07XG4gIH1cbn07XG5cbi8vIEZ1bmN0aW9uIHRvIGhhbmRsZSBlbWJlZGRlZEtleSBsb2dpYyBhbmQgdXBkYXRlIHRoZSBwYXRoXG5mdW5jdGlvbiBoYW5kbGVFbWJlZGRlZEtleShlbWJlZGRlZEtleTogc3RyaW5nIHwgRnVuY3Rpb25LZXksIG9iajogSUNoYW5nZSwgcGF0aDogc3RyaW5nKTogW3N0cmluZywgSUF0b21pY0NoYW5nZVtdP10ge1xuICBpZiAoZW1iZWRkZWRLZXkgPT09ICckaW5kZXgnKSB7XG4gICAgcGF0aCA9IGAke3BhdGh9WyR7b2JqLmtleX1dYDtcbiAgICByZXR1cm4gW3BhdGhdO1xuICB9IGVsc2UgaWYgKGVtYmVkZGVkS2V5ID09PSAnJHZhbHVlJykge1xuICAgIHBhdGggPSBgJHtwYXRofVs/KEA9PScke29iai5rZXl9JyldYDtcbiAgICBjb25zdCB2YWx1ZVR5cGUgPSBnZXRUeXBlT2ZPYmoob2JqLnZhbHVlKTtcbiAgICByZXR1cm4gW1xuICAgICAgcGF0aCxcbiAgICAgIFtcbiAgICAgICAge1xuICAgICAgICAgIC4uLm9iaixcbiAgICAgICAgICBwYXRoLFxuICAgICAgICAgIHZhbHVlVHlwZVxuICAgICAgICB9XG4gICAgICBdXG4gICAgXTtcbiAgfSBlbHNlIHtcbiAgICBwYXRoID0gZmlsdGVyRXhwcmVzc2lvbihwYXRoLCBlbWJlZGRlZEtleSwgb2JqLmtleSk7XG4gICAgcmV0dXJuIFtwYXRoXTtcbiAgfVxufVxuXG5jb25zdCBoYW5kbGVBcnJheSA9IChvYmo6IENoYW5nZXNldCB8IElDaGFuZ2VbXSwgcGF0aDogc3RyaW5nLCBlbWJlZGRlZEtleT86IHN0cmluZyB8IEZ1bmN0aW9uS2V5KTogSUF0b21pY0NoYW5nZVtdID0+IHtcbiAgcmV0dXJuIG9iai5yZWR1Y2UoKG1lbW8sIGNoYW5nZSkgPT4gWy4uLm1lbW8sIC4uLmF0b21pemVDaGFuZ2VzZXQoY2hhbmdlLCBwYXRoLCBlbWJlZGRlZEtleSldLCBbXSBhcyBJQXRvbWljQ2hhbmdlW10pO1xufTtcblxuLyoqXG4gKiBUcmFuc2Zvcm1zIGFuIGF0b21pemVkIGNoYW5nZXNldCBpbnRvIGEgbmVzdGVkIGNoYW5nZXNldC5cbiAqXG4gKiBAcGFyYW0ge0lBdG9taWNDaGFuZ2UgfCBJQXRvbWljQ2hhbmdlW119IGNoYW5nZXMgLSBUaGUgYXRvbWljIGNoYW5nZXNldCB0byB1bmZsYXR0ZW4uXG4gKiBAcmV0dXJucyB7SUNoYW5nZVtdfSAtIFRoZSB1bmZsYXR0ZW5lZCBjaGFuZ2VzZXQuXG4gKlxuICogVGhlIGZ1bmN0aW9uIGZpcnN0IGNoZWNrcyBpZiB0aGUgaW5wdXQgaXMgYSBzaW5nbGUgY2hhbmdlIG9yIGFuIGFycmF5IG9mIGNoYW5nZXMuXG4gKiBJdCB0aGVuIGl0ZXJhdGVzIG92ZXIgZWFjaCBjaGFuZ2UgYW5kIHNwbGl0cyBpdHMgcGF0aCBpbnRvIHNlZ21lbnRzLlxuICogRm9yIGVhY2ggc2VnbWVudCwgaXQgY2hlY2tzIGlmIGl0IHJlcHJlc2VudHMgYW4gYXJyYXkgb3IgYSBsZWFmIG5vZGUuXG4gKiBJZiBpdCByZXByZXNlbnRzIGFuIGFycmF5LCBpdCBjcmVhdGVzIGEgbmV3IGNoYW5nZSBvYmplY3QgYW5kIHVwZGF0ZXMgdGhlIHBvaW50ZXIgdG8gdGhpcyBuZXcgb2JqZWN0LlxuICogSWYgaXQgcmVwcmVzZW50cyBhIGxlYWYgbm9kZSwgaXQgc2V0cyB0aGUga2V5LCB0eXBlLCB2YWx1ZSwgYW5kIG9sZFZhbHVlIG9mIHRoZSBjdXJyZW50IGNoYW5nZSBvYmplY3QuXG4gKiBGaW5hbGx5LCBpdCBwdXNoZXMgdGhlIHVuZmxhdHRlbmVkIGNoYW5nZSBvYmplY3QgaW50byB0aGUgY2hhbmdlcyBhcnJheS5cbiAqL1xuY29uc3QgdW5hdG9taXplQ2hhbmdlc2V0ID0gKGNoYW5nZXM6IElBdG9taWNDaGFuZ2UgfCBJQXRvbWljQ2hhbmdlW10pID0+IHtcbiAgaWYgKCFBcnJheS5pc0FycmF5KGNoYW5nZXMpKSB7XG4gICAgY2hhbmdlcyA9IFtjaGFuZ2VzXTtcbiAgfVxuXG4gIGNvbnN0IGNoYW5nZXNBcnI6IElDaGFuZ2VbXSA9IFtdO1xuXG4gIGNoYW5nZXMuZm9yRWFjaCgoY2hhbmdlKSA9PiB7XG4gICAgY29uc3Qgb2JqID0ge30gYXMgSUNoYW5nZTtcbiAgICBsZXQgcHRyID0gb2JqO1xuXG4gICAgY29uc3Qgc2VnbWVudHMgPSBzcGxpdEpTT05QYXRoKGNoYW5nZS5wYXRoKTtcblxuICAgIGlmIChzZWdtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHB0ci5rZXkgPSBjaGFuZ2Uua2V5O1xuICAgICAgcHRyLnR5cGUgPSBjaGFuZ2UudHlwZTtcbiAgICAgIHB0ci52YWx1ZSA9IGNoYW5nZS52YWx1ZTtcbiAgICAgIHB0ci5vbGRWYWx1ZSA9IGNoYW5nZS5vbGRWYWx1ZTtcbiAgICAgIGNoYW5nZXNBcnIucHVzaChwdHIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHNlZ21lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IHNlZ21lbnQgPSBzZWdtZW50c1tpXTtcbiAgICAgICAgLy8gTWF0Y2hlcyBKU09OUGF0aCBzZWdtZW50czogXCJpdGVtc1s/KEAuaWQ9PScxMjMnKV1cIiwgXCJpdGVtc1s/KEAuaWQ9PTEyMyldXCIsIFwiaXRlbXNbMl1cIiwgXCJpdGVtc1s/KEA9JzEyMycpXVwiXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IC9eKFteW1xcXV0rKVxcW1xcP1xcKEBcXC4/KFtePV0qKT0rJyhbXiddKyknXFwpXFxdJHxeKC4rKVxcWyhcXGQrKVxcXSQvLmV4ZWMoc2VnbWVudCk7XG4gICAgICAgIC8vIGFycmF5XG4gICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICBsZXQga2V5OiBzdHJpbmc7XG4gICAgICAgICAgbGV0IGVtYmVkZGVkS2V5OiBzdHJpbmc7XG4gICAgICAgICAgbGV0IGFycktleTogc3RyaW5nIHwgbnVtYmVyO1xuICAgICAgICAgIGlmIChyZXN1bHRbMV0pIHtcbiAgICAgICAgICAgIGtleSA9IHJlc3VsdFsxXTtcbiAgICAgICAgICAgIGVtYmVkZGVkS2V5ID0gcmVzdWx0WzJdIHx8ICckdmFsdWUnO1xuICAgICAgICAgICAgYXJyS2V5ID0gcmVzdWx0WzNdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBrZXkgPSByZXN1bHRbNF07XG4gICAgICAgICAgICBlbWJlZGRlZEtleSA9ICckaW5kZXgnO1xuICAgICAgICAgICAgYXJyS2V5ID0gTnVtYmVyKHJlc3VsdFs1XSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIGxlYWZcbiAgICAgICAgICBpZiAoaSA9PT0gc2VnbWVudHMubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgcHRyLmtleSA9IGtleSE7XG4gICAgICAgICAgICBwdHIuZW1iZWRkZWRLZXkgPSBlbWJlZGRlZEtleSE7XG4gICAgICAgICAgICBwdHIudHlwZSA9IE9wZXJhdGlvbi5VUERBVEU7XG4gICAgICAgICAgICBwdHIuY2hhbmdlcyA9IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR5cGU6IGNoYW5nZS50eXBlLFxuICAgICAgICAgICAgICAgIGtleTogYXJyS2V5ISxcbiAgICAgICAgICAgICAgICB2YWx1ZTogY2hhbmdlLnZhbHVlLFxuICAgICAgICAgICAgICAgIG9sZFZhbHVlOiBjaGFuZ2Uub2xkVmFsdWVcbiAgICAgICAgICAgICAgfSBhcyBJQ2hhbmdlXG4gICAgICAgICAgICBdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBvYmplY3RcbiAgICAgICAgICAgIHB0ci5rZXkgPSBrZXk7XG4gICAgICAgICAgICBwdHIuZW1iZWRkZWRLZXkgPSBlbWJlZGRlZEtleTtcbiAgICAgICAgICAgIHB0ci50eXBlID0gT3BlcmF0aW9uLlVQREFURTtcbiAgICAgICAgICAgIGNvbnN0IG5ld1B0ciA9IHt9IGFzIElDaGFuZ2U7XG4gICAgICAgICAgICBwdHIuY2hhbmdlcyA9IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR5cGU6IE9wZXJhdGlvbi5VUERBVEUsXG4gICAgICAgICAgICAgICAga2V5OiBhcnJLZXksXG4gICAgICAgICAgICAgICAgY2hhbmdlczogW25ld1B0cl1cbiAgICAgICAgICAgICAgfSBhcyBJQ2hhbmdlXG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgcHRyID0gbmV3UHRyO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBsZWFmXG4gICAgICAgICAgaWYgKGkgPT09IHNlZ21lbnRzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgIC8vIEhhbmRsZSBhbGwgbGVhZiB2YWx1ZXMgdGhlIHNhbWUgd2F5LCByZWdhcmRsZXNzIG9mIHR5cGVcbiAgICAgICAgICAgIHB0ci5rZXkgPSBzZWdtZW50O1xuICAgICAgICAgICAgcHRyLnR5cGUgPSBjaGFuZ2UudHlwZTtcbiAgICAgICAgICAgIHB0ci52YWx1ZSA9IGNoYW5nZS52YWx1ZTtcbiAgICAgICAgICAgIHB0ci5vbGRWYWx1ZSA9IGNoYW5nZS5vbGRWYWx1ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gYnJhbmNoXG4gICAgICAgICAgICBwdHIua2V5ID0gc2VnbWVudDtcbiAgICAgICAgICAgIHB0ci50eXBlID0gT3BlcmF0aW9uLlVQREFURTtcbiAgICAgICAgICAgIGNvbnN0IG5ld1B0ciA9IHt9IGFzIElDaGFuZ2U7XG4gICAgICAgICAgICBwdHIuY2hhbmdlcyA9IFtuZXdQdHJdO1xuICAgICAgICAgICAgcHRyID0gbmV3UHRyO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgY2hhbmdlc0Fyci5wdXNoKG9iaik7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIGNoYW5nZXNBcnI7XG59O1xuXG4vKipcbiAqIERldGVybWluZXMgdGhlIHR5cGUgb2YgYSBnaXZlbiBvYmplY3QuXG4gKlxuICogQHBhcmFtIHthbnl9IG9iaiAtIFRoZSBvYmplY3Qgd2hvc2UgdHlwZSBpcyB0byBiZSBkZXRlcm1pbmVkLlxuICogQHJldHVybnMge3N0cmluZyB8IG51bGx9IC0gVGhlIHR5cGUgb2YgdGhlIG9iamVjdCwgb3IgbnVsbCBpZiB0aGUgb2JqZWN0IGlzIG51bGwuXG4gKlxuICogVGhpcyBmdW5jdGlvbiBmaXJzdCBjaGVja3MgaWYgdGhlIG9iamVjdCBpcyB1bmRlZmluZWQgb3IgbnVsbCwgYW5kIHJldHVybnMgJ3VuZGVmaW5lZCcgb3IgbnVsbCByZXNwZWN0aXZlbHkuXG4gKiBJZiB0aGUgb2JqZWN0IGlzIG5laXRoZXIgdW5kZWZpbmVkIG5vciBudWxsLCBpdCB1c2VzIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcgdG8gZ2V0IHRoZSBvYmplY3QncyB0eXBlLlxuICogVGhlIHR5cGUgaXMgZXh0cmFjdGVkIGZyb20gdGhlIHN0cmluZyByZXR1cm5lZCBieSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nIHVzaW5nIGEgcmVndWxhciBleHByZXNzaW9uLlxuICovXG5jb25zdCBnZXRUeXBlT2ZPYmogPSAob2JqOiBhbnkpID0+IHtcbiAgaWYgKHR5cGVvZiBvYmogPT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuICd1bmRlZmluZWQnO1xuICB9XG5cbiAgaWYgKG9iaiA9PT0gbnVsbCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLy8gRXh0cmFjdHMgdGhlIFwiVHlwZVwiIGZyb20gXCJbb2JqZWN0IFR5cGVdXCIgc3RyaW5nLlxuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iaikubWF0Y2goL15cXFtvYmplY3RcXHMoLiopXFxdJC8pWzFdO1xufTtcblxuY29uc3QgZ2V0S2V5ID0gKHBhdGg6IHN0cmluZykgPT4ge1xuICBjb25zdCBsZWZ0ID0gcGF0aFtwYXRoLmxlbmd0aCAtIDFdO1xuICByZXR1cm4gbGVmdCAhPSBudWxsID8gbGVmdCA6ICckcm9vdCc7XG59O1xuXG5jb25zdCBjb21wYXJlID0gKG9sZE9iajogYW55LCBuZXdPYmo6IGFueSwgcGF0aDogYW55LCBrZXlQYXRoOiBhbnksIG9wdGlvbnM6IE9wdGlvbnMpID0+IHtcbiAgbGV0IGNoYW5nZXM6IGFueVtdID0gW107XG5cbiAgLy8gQ2hlY2sgaWYgdGhlIGN1cnJlbnQgcGF0aCBzaG91bGQgYmUgc2tpcHBlZCBcbiAgY29uc3QgY3VycmVudFBhdGggPSBrZXlQYXRoLmpvaW4oJy4nKTtcbiAgaWYgKG9wdGlvbnMua2V5c1RvU2tpcD8uc29tZShza2lwUGF0aCA9PiB7XG4gICAgLy8gRXhhY3QgbWF0Y2hcbiAgICBpZiAoY3VycmVudFBhdGggPT09IHNraXBQYXRoKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgXG4gICAgLy8gVGhlIGN1cnJlbnQgcGF0aCBpcyBhIHBhcmVudCBvZiB0aGUgc2tpcCBwYXRoXG4gICAgaWYgKHNraXBQYXRoLmluY2x1ZGVzKCcuJykgJiYgc2tpcFBhdGguc3RhcnRzV2l0aChjdXJyZW50UGF0aCArICcuJykpIHtcbiAgICAgIHJldHVybiBmYWxzZTsgLy8gRG9uJ3Qgc2tpcCwgd2UgbmVlZCB0byBwcm9jZXNzIHRoZSBwYXJlbnRcbiAgICB9XG4gICAgXG4gICAgLy8gVGhlIGN1cnJlbnQgcGF0aCBpcyBhIGNoaWxkIG9yIGRlZXBlciBkZXNjZW5kYW50IG9mIHRoZSBza2lwIHBhdGhcbiAgICBpZiAoc2tpcFBhdGguaW5jbHVkZXMoJy4nKSkge1xuICAgICAgLy8gQ2hlY2sgaWYgc2tpcFBhdGggaXMgYSBwYXJlbnQgb2YgY3VycmVudFBhdGhcbiAgICAgIGNvbnN0IHNraXBQYXJ0cyA9IHNraXBQYXRoLnNwbGl0KCcuJyk7XG4gICAgICBjb25zdCBjdXJyZW50UGFydHMgPSBjdXJyZW50UGF0aC5zcGxpdCgnLicpO1xuICAgICAgXG4gICAgICBpZiAoY3VycmVudFBhcnRzLmxlbmd0aCA+PSBza2lwUGFydHMubGVuZ3RoKSB7XG4gICAgICAgIC8vIENoZWNrIGlmIGFsbCBwYXJ0cyBvZiBza2lwUGF0aCBtYXRjaCB0aGUgY29ycmVzcG9uZGluZyBwYXJ0cyBpbiBjdXJyZW50UGF0aFxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNraXBQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGlmIChza2lwUGFydHNbaV0gIT09IGN1cnJlbnRQYXJ0c1tpXSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTsgLy8gQWxsIHBhcnRzIG1hdGNoLCBzbyB0aGlzIGlzIGEgY2hpbGQgb3IgZXF1YWwgcGF0aFxuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICByZXR1cm4gZmFsc2U7XG4gIH0pKSB7XG4gICAgcmV0dXJuIGNoYW5nZXM7IC8vIFNraXAgY29tcGFyaXNvbiBmb3IgdGhpcyBwYXRoIGFuZCBpdHMgY2hpbGRyZW5cbiAgfVxuXG4gIGNvbnN0IHR5cGVPZk9sZE9iaiA9IGdldFR5cGVPZk9iaihvbGRPYmopO1xuICBjb25zdCB0eXBlT2ZOZXdPYmogPSBnZXRUeXBlT2ZPYmoobmV3T2JqKTtcblxuICAvLyBgdHJlYXRUeXBlQ2hhbmdlQXNSZXBsYWNlYCBpcyBhIGZsYWcgdXNlZCB0byBkZXRlcm1pbmUgaWYgYSBjaGFuZ2UgaW4gdHlwZSBzaG91bGQgYmUgdHJlYXRlZCBhcyBhIHJlcGxhY2VtZW50LlxuICBpZiAob3B0aW9ucy50cmVhdFR5cGVDaGFuZ2VBc1JlcGxhY2UgJiYgdHlwZU9mT2xkT2JqICE9PSB0eXBlT2ZOZXdPYmopIHtcbiAgICAvLyBPbmx5IGFkZCBhIFJFTU9WRSBvcGVyYXRpb24gaWYgb2xkT2JqIGlzIG5vdCB1bmRlZmluZWRcbiAgICBpZiAodHlwZU9mT2xkT2JqICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgY2hhbmdlcy5wdXNoKHsgdHlwZTogT3BlcmF0aW9uLlJFTU9WRSwga2V5OiBnZXRLZXkocGF0aCksIHZhbHVlOiBvbGRPYmogfSk7XG4gICAgfVxuXG4gICAgLy8gQXMgdW5kZWZpbmVkIGlzIG5vdCBzZXJpYWxpemVkIGludG8gSlNPTiwgaXQgc2hvdWxkIG5vdCBjb3VudCBhcyBhbiBhZGRlZCB2YWx1ZS5cbiAgICBpZiAodHlwZU9mTmV3T2JqICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgY2hhbmdlcy5wdXNoKHsgdHlwZTogT3BlcmF0aW9uLkFERCwga2V5OiBnZXRLZXkocGF0aCksIHZhbHVlOiBuZXdPYmogfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNoYW5nZXM7XG4gIH1cblxuICBpZiAodHlwZU9mTmV3T2JqID09PSAndW5kZWZpbmVkJyAmJiB0eXBlT2ZPbGRPYmogIT09ICd1bmRlZmluZWQnKSB7XG4gICAgY2hhbmdlcy5wdXNoKHsgdHlwZTogT3BlcmF0aW9uLlJFTU9WRSwga2V5OiBnZXRLZXkocGF0aCksIHZhbHVlOiBvbGRPYmogfSk7XG4gICAgcmV0dXJuIGNoYW5nZXM7XG4gIH1cblxuICBpZiAodHlwZU9mTmV3T2JqID09PSAnT2JqZWN0JyAmJiB0eXBlT2ZPbGRPYmogPT09ICdBcnJheScpIHtcbiAgICBjaGFuZ2VzLnB1c2goeyB0eXBlOiBPcGVyYXRpb24uVVBEQVRFLCBrZXk6IGdldEtleShwYXRoKSwgdmFsdWU6IG5ld09iaiwgb2xkVmFsdWU6IG9sZE9iaiB9KTtcbiAgICByZXR1cm4gY2hhbmdlcztcbiAgfVxuXG4gIGlmICh0eXBlT2ZOZXdPYmogPT09IG51bGwpIHtcbiAgICBpZiAodHlwZU9mT2xkT2JqICE9PSBudWxsKSB7XG4gICAgICBjaGFuZ2VzLnB1c2goeyB0eXBlOiBPcGVyYXRpb24uVVBEQVRFLCBrZXk6IGdldEtleShwYXRoKSwgdmFsdWU6IG5ld09iaiwgb2xkVmFsdWU6IG9sZE9iaiB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGNoYW5nZXM7XG4gIH1cblxuICBzd2l0Y2ggKHR5cGVPZk9sZE9iaikge1xuICAgIGNhc2UgJ0RhdGUnOlxuICAgICAgaWYgKHR5cGVPZk5ld09iaiA9PT0gJ0RhdGUnKSB7XG4gICAgICAgIGNoYW5nZXMgPSBjaGFuZ2VzLmNvbmNhdChcbiAgICAgICAgICBjb21wYXJlUHJpbWl0aXZlcyhvbGRPYmouZ2V0VGltZSgpLCBuZXdPYmouZ2V0VGltZSgpLCBwYXRoKS5tYXAoKHgpID0+ICh7XG4gICAgICAgICAgICAuLi54LFxuICAgICAgICAgICAgdmFsdWU6IG5ldyBEYXRlKHgudmFsdWUpLFxuICAgICAgICAgICAgb2xkVmFsdWU6IG5ldyBEYXRlKHgub2xkVmFsdWUpXG4gICAgICAgICAgfSkpXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjaGFuZ2VzID0gY2hhbmdlcy5jb25jYXQoY29tcGFyZVByaW1pdGl2ZXMob2xkT2JqLCBuZXdPYmosIHBhdGgpKTtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ09iamVjdCc6IHtcbiAgICAgIGNvbnN0IGRpZmZzID0gY29tcGFyZU9iamVjdChvbGRPYmosIG5ld09iaiwgcGF0aCwga2V5UGF0aCwgZmFsc2UsIG9wdGlvbnMpO1xuICAgICAgaWYgKGRpZmZzLmxlbmd0aCkge1xuICAgICAgICBpZiAocGF0aC5sZW5ndGgpIHtcbiAgICAgICAgICBjaGFuZ2VzLnB1c2goe1xuICAgICAgICAgICAgdHlwZTogT3BlcmF0aW9uLlVQREFURSxcbiAgICAgICAgICAgIGtleTogZ2V0S2V5KHBhdGgpLFxuICAgICAgICAgICAgY2hhbmdlczogZGlmZnNcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjaGFuZ2VzID0gY2hhbmdlcy5jb25jYXQoZGlmZnMpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgY2FzZSAnQXJyYXknOlxuICAgICAgY2hhbmdlcyA9IGNoYW5nZXMuY29uY2F0KGNvbXBhcmVBcnJheShvbGRPYmosIG5ld09iaiwgcGF0aCwga2V5UGF0aCwgb3B0aW9ucykpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnRnVuY3Rpb24nOlxuICAgICAgYnJlYWs7XG4gICAgLy8gZG8gbm90aGluZ1xuICAgIGRlZmF1bHQ6XG4gICAgICBjaGFuZ2VzID0gY2hhbmdlcy5jb25jYXQoY29tcGFyZVByaW1pdGl2ZXMob2xkT2JqLCBuZXdPYmosIHBhdGgpKTtcbiAgfVxuXG4gIHJldHVybiBjaGFuZ2VzO1xufTtcblxuY29uc3QgY29tcGFyZU9iamVjdCA9IChvbGRPYmo6IGFueSwgbmV3T2JqOiBhbnksIHBhdGg6IGFueSwga2V5UGF0aDogYW55LCBza2lwUGF0aCA9IGZhbHNlLCBvcHRpb25zOiBPcHRpb25zID0ge30pID0+IHtcbiAgbGV0IGs7XG4gIGxldCBuZXdLZXlQYXRoO1xuICBsZXQgbmV3UGF0aDtcblxuICBpZiAoc2tpcFBhdGggPT0gbnVsbCkge1xuICAgIHNraXBQYXRoID0gZmFsc2U7XG4gIH1cbiAgbGV0IGNoYW5nZXM6IGFueVtdID0gW107XG5cbiAgLy8gRmlsdGVyIGtleXMgZGlyZWN0bHkgcmF0aGVyIHRoYW4gZmlsdGVyaW5nIGJ5IGtleXNUb1NraXAgYXQgdGhpcyBsZXZlbFxuICAvLyBUaGUgZnVsbCBwYXRoIGNoZWNrIGlzIG5vdyBkb25lIGluIHRoZSBjb21wYXJlIGZ1bmN0aW9uXG4gIGNvbnN0IG9sZE9iaktleXMgPSBPYmplY3Qua2V5cyhvbGRPYmopO1xuICBjb25zdCBuZXdPYmpLZXlzID0gT2JqZWN0LmtleXMobmV3T2JqKTtcblxuICBjb25zdCBpbnRlcnNlY3Rpb25LZXlzID0gaW50ZXJzZWN0aW9uKG9sZE9iaktleXMsIG5ld09iaktleXMpO1xuICBmb3IgKGsgb2YgaW50ZXJzZWN0aW9uS2V5cykge1xuICAgIG5ld1BhdGggPSBwYXRoLmNvbmNhdChba10pO1xuICAgIG5ld0tleVBhdGggPSBza2lwUGF0aCA/IGtleVBhdGggOiBrZXlQYXRoLmNvbmNhdChba10pO1xuICAgIGNvbnN0IGRpZmZzID0gY29tcGFyZShvbGRPYmpba10sIG5ld09ialtrXSwgbmV3UGF0aCwgbmV3S2V5UGF0aCwgb3B0aW9ucyk7XG4gICAgaWYgKGRpZmZzLmxlbmd0aCkge1xuICAgICAgY2hhbmdlcyA9IGNoYW5nZXMuY29uY2F0KGRpZmZzKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBhZGRlZEtleXMgPSBkaWZmZXJlbmNlKG5ld09iaktleXMsIG9sZE9iaktleXMpO1xuICBmb3IgKGsgb2YgYWRkZWRLZXlzKSB7XG4gICAgbmV3UGF0aCA9IHBhdGguY29uY2F0KFtrXSk7XG4gICAgbmV3S2V5UGF0aCA9IHNraXBQYXRoID8ga2V5UGF0aCA6IGtleVBhdGguY29uY2F0KFtrXSk7XG4gICAgLy8gQ2hlY2sgaWYgdGhlIHBhdGggc2hvdWxkIGJlIHNraXBwZWRcbiAgICBjb25zdCBjdXJyZW50UGF0aCA9IG5ld0tleVBhdGguam9pbignLicpO1xuICAgIGlmIChvcHRpb25zLmtleXNUb1NraXA/LnNvbWUoc2tpcFBhdGggPT4gY3VycmVudFBhdGggPT09IHNraXBQYXRoIHx8IGN1cnJlbnRQYXRoLnN0YXJ0c1dpdGgoc2tpcFBhdGggKyAnLicpKSkge1xuICAgICAgY29udGludWU7IC8vIFNraXAgYWRkaW5nIHRoaXMga2V5XG4gICAgfVxuICAgIGNoYW5nZXMucHVzaCh7XG4gICAgICB0eXBlOiBPcGVyYXRpb24uQURELFxuICAgICAga2V5OiBnZXRLZXkobmV3UGF0aCksXG4gICAgICB2YWx1ZTogbmV3T2JqW2tdXG4gICAgfSk7XG4gIH1cblxuICBjb25zdCBkZWxldGVkS2V5cyA9IGRpZmZlcmVuY2Uob2xkT2JqS2V5cywgbmV3T2JqS2V5cyk7XG4gIGZvciAoayBvZiBkZWxldGVkS2V5cykge1xuICAgIG5ld1BhdGggPSBwYXRoLmNvbmNhdChba10pO1xuICAgIG5ld0tleVBhdGggPSBza2lwUGF0aCA/IGtleVBhdGggOiBrZXlQYXRoLmNvbmNhdChba10pO1xuICAgIC8vIENoZWNrIGlmIHRoZSBwYXRoIHNob3VsZCBiZSBza2lwcGVkXG4gICAgY29uc3QgY3VycmVudFBhdGggPSBuZXdLZXlQYXRoLmpvaW4oJy4nKTtcbiAgICBpZiAob3B0aW9ucy5rZXlzVG9Ta2lwPy5zb21lKHNraXBQYXRoID0+IGN1cnJlbnRQYXRoID09PSBza2lwUGF0aCB8fCBjdXJyZW50UGF0aC5zdGFydHNXaXRoKHNraXBQYXRoICsgJy4nKSkpIHtcbiAgICAgIGNvbnRpbnVlOyAvLyBTa2lwIHJlbW92aW5nIHRoaXMga2V5XG4gICAgfVxuICAgIGNoYW5nZXMucHVzaCh7XG4gICAgICB0eXBlOiBPcGVyYXRpb24uUkVNT1ZFLFxuICAgICAga2V5OiBnZXRLZXkobmV3UGF0aCksXG4gICAgICB2YWx1ZTogb2xkT2JqW2tdXG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIGNoYW5nZXM7XG59O1xuXG5jb25zdCBjb21wYXJlQXJyYXkgPSAob2xkT2JqOiBhbnksIG5ld09iajogYW55LCBwYXRoOiBhbnksIGtleVBhdGg6IGFueSwgb3B0aW9uczogT3B0aW9ucykgPT4ge1xuICBpZiAoZ2V0VHlwZU9mT2JqKG5ld09iaikgIT09ICdBcnJheScpIHtcbiAgICByZXR1cm4gW3sgdHlwZTogT3BlcmF0aW9uLlVQREFURSwga2V5OiBnZXRLZXkocGF0aCksIHZhbHVlOiBuZXdPYmosIG9sZFZhbHVlOiBvbGRPYmogfV07XG4gIH1cblxuICBjb25zdCBsZWZ0ID0gZ2V0T2JqZWN0S2V5KG9wdGlvbnMuZW1iZWRkZWRPYmpLZXlzLCBrZXlQYXRoKTtcbiAgY29uc3QgdW5pcUtleSA9IGxlZnQgIT0gbnVsbCA/IGxlZnQgOiAnJGluZGV4JztcbiAgY29uc3QgaW5kZXhlZE9sZE9iaiA9IGNvbnZlcnRBcnJheVRvT2JqKG9sZE9iaiwgdW5pcUtleSk7XG4gIGNvbnN0IGluZGV4ZWROZXdPYmogPSBjb252ZXJ0QXJyYXlUb09iaihuZXdPYmosIHVuaXFLZXkpO1xuICBjb25zdCBkaWZmcyA9IGNvbXBhcmVPYmplY3QoaW5kZXhlZE9sZE9iaiwgaW5kZXhlZE5ld09iaiwgcGF0aCwga2V5UGF0aCwgdHJ1ZSwgb3B0aW9ucyk7XG4gIGlmIChkaWZmcy5sZW5ndGgpIHtcbiAgICByZXR1cm4gW1xuICAgICAge1xuICAgICAgICB0eXBlOiBPcGVyYXRpb24uVVBEQVRFLFxuICAgICAgICBrZXk6IGdldEtleShwYXRoKSxcbiAgICAgICAgZW1iZWRkZWRLZXk6IHR5cGVvZiB1bmlxS2V5ID09PSAnZnVuY3Rpb24nICYmIHVuaXFLZXkubGVuZ3RoID09PSAyID8gdW5pcUtleShuZXdPYmpbMF0sIHRydWUpIDogdW5pcUtleSxcbiAgICAgICAgY2hhbmdlczogZGlmZnNcbiAgICAgIH1cbiAgICBdO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBbXTtcbiAgfVxufTtcblxuY29uc3QgZ2V0T2JqZWN0S2V5ID0gKGVtYmVkZGVkT2JqS2V5czogYW55LCBrZXlQYXRoOiBhbnkpID0+IHtcbiAgaWYgKGVtYmVkZGVkT2JqS2V5cyAhPSBudWxsKSB7XG4gICAgY29uc3QgcGF0aCA9IGtleVBhdGguam9pbignLicpO1xuXG4gICAgaWYgKGVtYmVkZGVkT2JqS2V5cyBpbnN0YW5jZW9mIE1hcCkge1xuICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgZW1iZWRkZWRPYmpLZXlzLmVudHJpZXMoKSkge1xuICAgICAgICBpZiAoa2V5IGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgaWYgKHBhdGgubWF0Y2goa2V5KSkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChwYXRoID09PSBrZXkpIHtcbiAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBrZXkgPSBlbWJlZGRlZE9iaktleXNbcGF0aF07XG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4ga2V5O1xuICAgIH1cbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufTtcblxuY29uc3QgY29udmVydEFycmF5VG9PYmogPSAoYXJyOiBhbnlbXSwgdW5pcUtleTogYW55KSA9PiB7XG4gIGxldCBvYmo6IGFueSA9IHt9O1xuICBpZiAodW5pcUtleSA9PT0gJyR2YWx1ZScpIHtcbiAgICBhcnIuZm9yRWFjaCgodmFsdWUpID0+IHtcbiAgICAgIG9ialt2YWx1ZV0gPSB2YWx1ZTtcbiAgICB9KTtcbiAgfSBlbHNlIGlmICh1bmlxS2V5ICE9PSAnJGluZGV4Jykge1xuICAgIC8vIENvbnZlcnQgc3RyaW5nIGtleXMgdG8gZnVuY3Rpb25zIGZvciBjb21wYXRpYmlsaXR5IHdpdGggZXMtdG9vbGtpdCBrZXlCeVxuICAgIGNvbnN0IGtleUZ1bmN0aW9uID0gdHlwZW9mIHVuaXFLZXkgPT09ICdzdHJpbmcnID8gKGl0ZW06IGFueSkgPT4gaXRlbVt1bmlxS2V5XSA6IHVuaXFLZXk7XG4gICAgb2JqID0ga2V5QnkoYXJyLCBrZXlGdW5jdGlvbik7XG4gIH0gZWxzZSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gYXJyW2ldO1xuICAgICAgb2JqW2ldID0gdmFsdWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBvYmo7XG59O1xuXG5jb25zdCBjb21wYXJlUHJpbWl0aXZlcyA9IChvbGRPYmo6IGFueSwgbmV3T2JqOiBhbnksIHBhdGg6IGFueSkgPT4ge1xuICBjb25zdCBjaGFuZ2VzID0gW107XG4gIGlmIChvbGRPYmogIT09IG5ld09iaikge1xuICAgIGNoYW5nZXMucHVzaCh7XG4gICAgICB0eXBlOiBPcGVyYXRpb24uVVBEQVRFLFxuICAgICAga2V5OiBnZXRLZXkocGF0aCksXG4gICAgICB2YWx1ZTogbmV3T2JqLFxuICAgICAgb2xkVmFsdWU6IG9sZE9ialxuICAgIH0pO1xuICB9XG4gIHJldHVybiBjaGFuZ2VzO1xufTtcblxuY29uc3QgcmVtb3ZlS2V5ID0gKG9iajogYW55LCBrZXk6IGFueSwgZW1iZWRkZWRLZXk6IGFueSkgPT4ge1xuICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSB7XG4gICAgaWYgKGVtYmVkZGVkS2V5ID09PSAnJGluZGV4Jykge1xuICAgICAgb2JqLnNwbGljZShOdW1iZXIoa2V5KSwgMSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGluZGV4ID0gaW5kZXhPZkl0ZW1JbkFycmF5KG9iaiwgZW1iZWRkZWRLZXksIGtleSk7XG4gICAgaWYgKGluZGV4ID09PSAtMSkge1xuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybihgRWxlbWVudCB3aXRoIHRoZSBrZXkgJyR7ZW1iZWRkZWRLZXl9JyBhbmQgdmFsdWUgJyR7a2V5fScgY291bGQgbm90IGJlIGZvdW5kIGluIHRoZSBhcnJheSdgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgcmV0dXJuIG9iai5zcGxpY2UoaW5kZXggIT0gbnVsbCA/IGluZGV4IDoga2V5LCAxKTtcbiAgfSBlbHNlIHtcbiAgICBkZWxldGUgb2JqW2tleV07XG4gICAgcmV0dXJuO1xuICB9XG59O1xuXG5jb25zdCBpbmRleE9mSXRlbUluQXJyYXkgPSAoYXJyOiBhbnlbXSwga2V5OiBhbnksIHZhbHVlOiBhbnkpID0+IHtcbiAgaWYgKGtleSA9PT0gJyR2YWx1ZScpIHtcbiAgICByZXR1cm4gYXJyLmluZGV4T2YodmFsdWUpO1xuICB9XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgaXRlbSA9IGFycltpXTtcbiAgICBpZiAoaXRlbSAmJiBpdGVtW2tleV0gPyBpdGVtW2tleV0udG9TdHJpbmcoKSA9PT0gdmFsdWUudG9TdHJpbmcoKSA6IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIGk7XG4gICAgfVxuICB9XG4gIHJldHVybiAtMTtcbn07XG5cbmNvbnN0IG1vZGlmeUtleVZhbHVlID0gKG9iajogYW55LCBrZXk6IGFueSwgdmFsdWU6IGFueSkgPT4gKG9ialtrZXldID0gdmFsdWUpO1xuY29uc3QgYWRkS2V5VmFsdWUgPSAob2JqOiBhbnksIGtleTogYW55LCB2YWx1ZTogYW55LCBlbWJlZGRlZEtleT86IGFueSkgPT4ge1xuICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSB7XG4gICAgaWYgKGVtYmVkZGVkS2V5ID09PSAnJGluZGV4Jykge1xuICAgICAgb2JqLnNwbGljZShOdW1iZXIoa2V5KSwgMCwgdmFsdWUpO1xuICAgICAgcmV0dXJuIG9iai5sZW5ndGg7XG4gICAgfVxuICAgIHJldHVybiBvYmoucHVzaCh2YWx1ZSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG9iaiA/IChvYmpba2V5XSA9IHZhbHVlKSA6IG51bGw7XG4gIH1cbn07XG5cbmNvbnN0IGFwcGx5TGVhZkNoYW5nZSA9IChvYmo6IGFueSwgY2hhbmdlOiBhbnksIGVtYmVkZGVkS2V5OiBhbnkpID0+IHtcbiAgY29uc3QgeyB0eXBlLCBrZXksIHZhbHVlIH0gPSBjaGFuZ2U7XG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgT3BlcmF0aW9uLkFERDpcbiAgICAgIHJldHVybiBhZGRLZXlWYWx1ZShvYmosIGtleSwgdmFsdWUsIGVtYmVkZGVkS2V5KTtcbiAgICBjYXNlIE9wZXJhdGlvbi5VUERBVEU6XG4gICAgICByZXR1cm4gbW9kaWZ5S2V5VmFsdWUob2JqLCBrZXksIHZhbHVlKTtcbiAgICBjYXNlIE9wZXJhdGlvbi5SRU1PVkU6XG4gICAgICByZXR1cm4gcmVtb3ZlS2V5KG9iaiwga2V5LCBlbWJlZGRlZEtleSk7XG4gIH1cbn07XG5cbi8qKlxuICogQXBwbGllcyBjaGFuZ2VzIHRvIGFuIGFycmF5LlxuICogXG4gKiBAcGFyYW0ge2FueVtdfSBhcnIgLSBUaGUgYXJyYXkgdG8gYXBwbHkgY2hhbmdlcyB0by5cbiAqIEBwYXJhbSB7YW55fSBjaGFuZ2UgLSBUaGUgY2hhbmdlIHRvIGFwcGx5LCBjb250YWluaW5nIG5lc3RlZCBjaGFuZ2VzLlxuICogQHJldHVybnMge2FueVtdfSAtIFRoZSBhcnJheSBhZnRlciBjaGFuZ2VzIGhhdmUgYmVlbiBhcHBsaWVkLlxuICpcbiAqIE5vdGU6IFRoaXMgZnVuY3Rpb24gbW9kaWZpZXMgdGhlIGFycmF5IGluLXBsYWNlIGJ1dCBhbHNvIHJldHVybnMgaXQgZm9yXG4gKiBjb25zaXN0ZW5jeSB3aXRoIG90aGVyIGZ1bmN0aW9ucy5cbiAqL1xuY29uc3QgYXBwbHlBcnJheUNoYW5nZSA9IChhcnI6IGFueVtdLCBjaGFuZ2U6IGFueSkgPT4ge1xuICBsZXQgY2hhbmdlcyA9IGNoYW5nZS5jaGFuZ2VzO1xuICBpZiAoY2hhbmdlLmVtYmVkZGVkS2V5ID09PSAnJGluZGV4Jykge1xuICAgIGNoYW5nZXMgPSBbLi4uY2hhbmdlc10uc29ydCgoYSwgYikgPT4ge1xuICAgICAgaWYgKGEudHlwZSA9PT0gT3BlcmF0aW9uLlJFTU9WRSAmJiBiLnR5cGUgPT09IE9wZXJhdGlvbi5SRU1PVkUpIHtcbiAgICAgICAgcmV0dXJuIE51bWJlcihiLmtleSkgLSBOdW1iZXIoYS5rZXkpO1xuICAgICAgfVxuICAgICAgaWYgKGEudHlwZSA9PT0gT3BlcmF0aW9uLlJFTU9WRSkgcmV0dXJuIC0xO1xuICAgICAgaWYgKGIudHlwZSA9PT0gT3BlcmF0aW9uLlJFTU9WRSkgcmV0dXJuIDE7XG4gICAgICByZXR1cm4gTnVtYmVyKGEua2V5KSAtIE51bWJlcihiLmtleSk7XG4gICAgfSk7XG4gIH1cblxuICBmb3IgKGNvbnN0IHN1YmNoYW5nZSBvZiBjaGFuZ2VzKSB7XG4gICAgaWYgKFxuICAgICAgKHN1YmNoYW5nZS52YWx1ZSAhPT0gbnVsbCAmJiBzdWJjaGFuZ2UudmFsdWUgIT09IHVuZGVmaW5lZCkgfHxcbiAgICAgIHN1YmNoYW5nZS50eXBlID09PSBPcGVyYXRpb24uUkVNT1ZFIHx8XG4gICAgICAoc3ViY2hhbmdlLnZhbHVlID09PSBudWxsICYmIHN1YmNoYW5nZS50eXBlID09PSBPcGVyYXRpb24uQUREKVxuICAgICkge1xuICAgICAgYXBwbHlMZWFmQ2hhbmdlKGFyciwgc3ViY2hhbmdlLCBjaGFuZ2UuZW1iZWRkZWRLZXkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgZWxlbWVudDtcbiAgICAgIGlmIChjaGFuZ2UuZW1iZWRkZWRLZXkgPT09ICckaW5kZXgnKSB7XG4gICAgICAgIGVsZW1lbnQgPSBhcnJbc3ViY2hhbmdlLmtleV07XG4gICAgICB9IGVsc2UgaWYgKGNoYW5nZS5lbWJlZGRlZEtleSA9PT0gJyR2YWx1ZScpIHtcbiAgICAgICAgY29uc3QgaW5kZXggPSBhcnIuaW5kZXhPZihzdWJjaGFuZ2Uua2V5KTtcbiAgICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICAgIGVsZW1lbnQgPSBhcnJbaW5kZXhdO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlbGVtZW50ID0gYXJyLmZpbmQoKGVsKSA9PiBlbFtjaGFuZ2UuZW1iZWRkZWRLZXldPy50b1N0cmluZygpID09PSBzdWJjaGFuZ2Uua2V5LnRvU3RyaW5nKCkpO1xuICAgICAgfVxuICAgICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgICAgYXBwbHlDaGFuZ2VzZXQoZWxlbWVudCwgc3ViY2hhbmdlLmNoYW5nZXMpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gYXJyO1xufTtcblxuY29uc3QgYXBwbHlCcmFuY2hDaGFuZ2UgPSAob2JqOiBhbnksIGNoYW5nZTogYW55KSA9PiB7XG4gIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHtcbiAgICByZXR1cm4gYXBwbHlBcnJheUNoYW5nZShvYmosIGNoYW5nZSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGFwcGx5Q2hhbmdlc2V0KG9iaiwgY2hhbmdlLmNoYW5nZXMpO1xuICB9XG59O1xuXG5jb25zdCByZXZlcnRMZWFmQ2hhbmdlID0gKG9iajogYW55LCBjaGFuZ2U6IGFueSwgZW1iZWRkZWRLZXkgPSAnJGluZGV4JykgPT4ge1xuICBjb25zdCB7IHR5cGUsIGtleSwgdmFsdWUsIG9sZFZhbHVlIH0gPSBjaGFuZ2U7XG4gIFxuICAvLyBTcGVjaWFsIGhhbmRsaW5nIGZvciAkcm9vdCBrZXlcbiAgaWYgKGtleSA9PT0gJyRyb290Jykge1xuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgY2FzZSBPcGVyYXRpb24uQUREOlxuICAgICAgICAvLyBXaGVuIHJldmVydGluZyBhbiBBREQgb2YgdGhlIGVudGlyZSBvYmplY3QsIGNsZWFyIGFsbCBwcm9wZXJ0aWVzXG4gICAgICAgIGZvciAoY29uc3QgcHJvcCBpbiBvYmopIHtcbiAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgcHJvcCkpIHtcbiAgICAgICAgICAgIGRlbGV0ZSBvYmpbcHJvcF07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvYmo7XG4gICAgICBjYXNlIE9wZXJhdGlvbi5VUERBVEU6XG4gICAgICAgIC8vIFJlcGxhY2UgdGhlIGVudGlyZSBvYmplY3Qgd2l0aCB0aGUgb2xkIHZhbHVlXG4gICAgICAgIGZvciAoY29uc3QgcHJvcCBpbiBvYmopIHtcbiAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgcHJvcCkpIHtcbiAgICAgICAgICAgIGRlbGV0ZSBvYmpbcHJvcF07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChvbGRWYWx1ZSAmJiB0eXBlb2Ygb2xkVmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgT2JqZWN0LmFzc2lnbihvYmosIG9sZFZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb2JqO1xuICAgICAgY2FzZSBPcGVyYXRpb24uUkVNT1ZFOlxuICAgICAgICAvLyBSZXN0b3JlIHRoZSByZW1vdmVkIG9iamVjdFxuICAgICAgICBpZiAodmFsdWUgJiYgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgIE9iamVjdC5hc3NpZ24ob2JqLCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9iajtcbiAgICB9XG4gIH1cbiAgXG4gIC8vIFJlZ3VsYXIgcHJvcGVydHkgaGFuZGxpbmdcbiAgc3dpdGNoICh0eXBlKSB7XG4gICAgY2FzZSBPcGVyYXRpb24uQUREOlxuICAgICAgcmV0dXJuIHJlbW92ZUtleShvYmosIGtleSwgZW1iZWRkZWRLZXkpO1xuICAgIGNhc2UgT3BlcmF0aW9uLlVQREFURTpcbiAgICAgIHJldHVybiBtb2RpZnlLZXlWYWx1ZShvYmosIGtleSwgb2xkVmFsdWUpO1xuICAgIGNhc2UgT3BlcmF0aW9uLlJFTU9WRTpcbiAgICAgIHJldHVybiBhZGRLZXlWYWx1ZShvYmosIGtleSwgdmFsdWUpO1xuICB9XG59O1xuXG4vKipcbiAqIFJldmVydHMgY2hhbmdlcyBpbiBhbiBhcnJheS5cbiAqIFxuICogQHBhcmFtIHthbnlbXX0gYXJyIC0gVGhlIGFycmF5IHRvIHJldmVydCBjaGFuZ2VzIGluLlxuICogQHBhcmFtIHthbnl9IGNoYW5nZSAtIFRoZSBjaGFuZ2UgdG8gcmV2ZXJ0LCBjb250YWluaW5nIG5lc3RlZCBjaGFuZ2VzLlxuICogQHJldHVybnMge2FueVtdfSAtIFRoZSBhcnJheSBhZnRlciBjaGFuZ2VzIGhhdmUgYmVlbiByZXZlcnRlZC5cbiAqXG4gKiBOb3RlOiBUaGlzIGZ1bmN0aW9uIG1vZGlmaWVzIHRoZSBhcnJheSBpbi1wbGFjZSBidXQgYWxzbyByZXR1cm5zIGl0IGZvclxuICogY29uc2lzdGVuY3kgd2l0aCBvdGhlciBmdW5jdGlvbnMuXG4gKi9cbmNvbnN0IHJldmVydEFycmF5Q2hhbmdlID0gKGFycjogYW55W10sIGNoYW5nZTogYW55KSA9PiB7XG4gIGZvciAoY29uc3Qgc3ViY2hhbmdlIG9mIGNoYW5nZS5jaGFuZ2VzKSB7XG4gICAgaWYgKHN1YmNoYW5nZS52YWx1ZSAhPSBudWxsIHx8IHN1YmNoYW5nZS50eXBlID09PSBPcGVyYXRpb24uUkVNT1ZFKSB7XG4gICAgICByZXZlcnRMZWFmQ2hhbmdlKGFyciwgc3ViY2hhbmdlLCBjaGFuZ2UuZW1iZWRkZWRLZXkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgZWxlbWVudDtcbiAgICAgIGlmIChjaGFuZ2UuZW1iZWRkZWRLZXkgPT09ICckaW5kZXgnKSB7XG4gICAgICAgIGVsZW1lbnQgPSBhcnJbK3N1YmNoYW5nZS5rZXldO1xuICAgICAgfSBlbHNlIGlmIChjaGFuZ2UuZW1iZWRkZWRLZXkgPT09ICckdmFsdWUnKSB7XG4gICAgICAgIGNvbnN0IGluZGV4ID0gYXJyLmluZGV4T2Yoc3ViY2hhbmdlLmtleSk7XG4gICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICBlbGVtZW50ID0gYXJyW2luZGV4XTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZWxlbWVudCA9IGFyci5maW5kKChlbCkgPT4gZWxbY2hhbmdlLmVtYmVkZGVkS2V5XT8udG9TdHJpbmcoKSA9PT0gc3ViY2hhbmdlLmtleS50b1N0cmluZygpKTtcbiAgICAgIH1cbiAgICAgIGlmIChlbGVtZW50KSB7XG4gICAgICAgIHJldmVydENoYW5nZXNldChlbGVtZW50LCBzdWJjaGFuZ2UuY2hhbmdlcyk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBhcnI7XG59O1xuXG5jb25zdCByZXZlcnRCcmFuY2hDaGFuZ2UgPSAob2JqOiBhbnksIGNoYW5nZTogYW55KSA9PiB7XG4gIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHtcbiAgICByZXR1cm4gcmV2ZXJ0QXJyYXlDaGFuZ2Uob2JqLCBjaGFuZ2UpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiByZXZlcnRDaGFuZ2VzZXQob2JqLCBjaGFuZ2UuY2hhbmdlcyk7XG4gIH1cbn07XG5cbi8qKiBjb21iaW5lIGEgYmFzZSBKU09OIFBhdGggd2l0aCBhIHN1YnNlcXVlbnQgc2VnbWVudCAqL1xuZnVuY3Rpb24gYXBwZW5kKGJhc2VQYXRoOiBzdHJpbmcsIG5leHRTZWdtZW50OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gbmV4dFNlZ21lbnQuaW5jbHVkZXMoJy4nKSA/IGAke2Jhc2VQYXRofVske25leHRTZWdtZW50fV1gIDogYCR7YmFzZVBhdGh9LiR7bmV4dFNlZ21lbnR9YDtcbn1cblxuLyoqIHJldHVybnMgYSBKU09OIFBhdGggZmlsdGVyIGV4cHJlc3Npb247IGUuZy4sIGAkLnBldFsoP25hbWU9J3Nwb3QnKV1gICovXG5mdW5jdGlvbiBmaWx0ZXJFeHByZXNzaW9uKGJhc2VQYXRoOiBzdHJpbmcsIGZpbHRlcktleTogc3RyaW5nIHwgRnVuY3Rpb25LZXksIGZpbHRlclZhbHVlOiBzdHJpbmcgfCBudW1iZXIpIHtcbiAgY29uc3QgdmFsdWUgPSB0eXBlb2YgZmlsdGVyVmFsdWUgPT09ICdudW1iZXInID8gZmlsdGVyVmFsdWUgOiBgJyR7ZmlsdGVyVmFsdWV9J2A7XG4gIHJldHVybiB0eXBlb2YgZmlsdGVyS2V5ID09PSAnc3RyaW5nJyAmJiBmaWx0ZXJLZXkuaW5jbHVkZXMoJy4nKVxuICAgID8gYCR7YmFzZVBhdGh9Wz8oQFske2ZpbHRlcktleX1dPT0ke3ZhbHVlfSldYFxuICAgIDogYCR7YmFzZVBhdGh9Wz8oQC4ke2ZpbHRlcktleX09PSR7dmFsdWV9KV1gO1xufVxuXG5leHBvcnQge1xuICBDaGFuZ2VzZXQsXG4gIEVtYmVkZGVkT2JqS2V5c01hcFR5cGUsXG4gIEVtYmVkZGVkT2JqS2V5c1R5cGUsXG4gIElBdG9taWNDaGFuZ2UsXG4gIElDaGFuZ2UsXG4gIE9wZXJhdGlvbixcbiAgT3B0aW9ucyxcbiAgYXBwbHlDaGFuZ2VzZXQsXG4gIGF0b21pemVDaGFuZ2VzZXQsXG4gIGRpZmYsXG4gIGdldFR5cGVPZk9iaixcbiAgcmV2ZXJ0Q2hhbmdlc2V0LFxuICB1bmF0b21pemVDaGFuZ2VzZXRcbn07XG4iLCAiaW1wb3J0IHsgc2V0QnlQYXRoIH0gZnJvbSAnLi9oZWxwZXJzLmpzJztcbmltcG9ydCB7IGRpZmYsIGF0b21pemVDaGFuZ2VzZXQsIGdldFR5cGVPZk9iaiwgSUF0b21pY0NoYW5nZSwgT3BlcmF0aW9uIH0gZnJvbSAnLi9qc29uRGlmZi5qcyc7XG5cbmVudW0gQ29tcGFyZU9wZXJhdGlvbiB7XG4gIENPTlRBSU5FUiA9ICdDT05UQUlORVInLFxuICBVTkNIQU5HRUQgPSAnVU5DSEFOR0VEJ1xufVxuXG5pbnRlcmZhY2UgSUNvbXBhcmlzb25FbnJpY2hlZE5vZGUge1xuICB0eXBlOiBPcGVyYXRpb24gfCBDb21wYXJlT3BlcmF0aW9uO1xuICB2YWx1ZTogSUNvbXBhcmlzb25FbnJpY2hlZE5vZGUgfCBJQ29tcGFyaXNvbkVucmljaGVkTm9kZVtdIHwgYW55IHwgYW55W107XG4gIG9sZFZhbHVlPzogYW55O1xufVxuXG5jb25zdCBjcmVhdGVWYWx1ZSA9ICh2YWx1ZTogYW55KTogSUNvbXBhcmlzb25FbnJpY2hlZE5vZGUgPT4gKHsgdHlwZTogQ29tcGFyZU9wZXJhdGlvbi5VTkNIQU5HRUQsIHZhbHVlIH0pO1xuY29uc3QgY3JlYXRlQ29udGFpbmVyID0gKHZhbHVlOiBvYmplY3QgfCBbXSk6IElDb21wYXJpc29uRW5yaWNoZWROb2RlID0+ICh7XG4gIHR5cGU6IENvbXBhcmVPcGVyYXRpb24uQ09OVEFJTkVSLFxuICB2YWx1ZVxufSk7XG5cbmNvbnN0IGVucmljaCA9IChvYmplY3Q6IGFueSk6IElDb21wYXJpc29uRW5yaWNoZWROb2RlID0+IHtcbiAgY29uc3Qgb2JqZWN0VHlwZSA9IGdldFR5cGVPZk9iaihvYmplY3QpO1xuXG4gIHN3aXRjaCAob2JqZWN0VHlwZSkge1xuICAgIGNhc2UgJ09iamVjdCc6XG4gICAgICByZXR1cm4gT2JqZWN0LmtleXMob2JqZWN0KVxuICAgICAgICAubWFwKChrZXk6IHN0cmluZykgPT4gKHsga2V5LCB2YWx1ZTogZW5yaWNoKG9iamVjdFtrZXldKSB9KSlcbiAgICAgICAgLnJlZHVjZSgoYWNjdW11bGF0b3IsIGVudHJ5KSA9PiB7XG4gICAgICAgICAgYWNjdW11bGF0b3IudmFsdWVbZW50cnkua2V5XSA9IGVudHJ5LnZhbHVlO1xuICAgICAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICAgICAgfSwgY3JlYXRlQ29udGFpbmVyKHt9KSk7XG4gICAgY2FzZSAnQXJyYXknOlxuICAgICAgcmV0dXJuIChvYmplY3QgYXMgYW55W10pXG4gICAgICAgIC5tYXAoKHZhbHVlKSA9PiBlbnJpY2godmFsdWUpKVxuICAgICAgICAucmVkdWNlKChhY2N1bXVsYXRvciwgdmFsdWUpID0+IHtcbiAgICAgICAgICBhY2N1bXVsYXRvci52YWx1ZS5wdXNoKHZhbHVlKTtcbiAgICAgICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgICAgIH0sIGNyZWF0ZUNvbnRhaW5lcihbXSkpO1xuICAgIGNhc2UgJ0Z1bmN0aW9uJzpcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgY2FzZSAnRGF0ZSc6XG4gICAgZGVmYXVsdDpcbiAgICAgIC8vIFByaW1pdGl2ZSB2YWx1ZVxuICAgICAgcmV0dXJuIGNyZWF0ZVZhbHVlKG9iamVjdCk7XG4gIH1cbn07XG5cbmNvbnN0IGFwcGx5Q2hhbmdlbGlzdCA9IChvYmplY3Q6IElDb21wYXJpc29uRW5yaWNoZWROb2RlLCBjaGFuZ2VsaXN0OiBJQXRvbWljQ2hhbmdlW10pOiBJQ29tcGFyaXNvbkVucmljaGVkTm9kZSA9PiB7XG4gIGNoYW5nZWxpc3RcbiAgICAubWFwKChlbnRyeSkgPT4gKHsgLi4uZW50cnksIHBhdGg6IGVudHJ5LnBhdGgucmVwbGFjZSgnJC4nLCAnLicpIH0pKVxuICAgIC5tYXAoKGVudHJ5KSA9PiAoe1xuICAgICAgLi4uZW50cnksXG4gICAgICBwYXRoOiBlbnRyeS5wYXRoLnJlcGxhY2UoLyhcXFsoPzxhcnJheT5cXGQpXFxdXFwuKS9nLCAnQVJSVkFMX1NUQVJUJDxhcnJheT5BUlJWQUxfRU5EJylcbiAgICB9KSlcbiAgICAubWFwKChlbnRyeSkgPT4gKHsgLi4uZW50cnksIHBhdGg6IGVudHJ5LnBhdGgucmVwbGFjZSgvKD88ZG90PlxcLikvZywgJy52YWx1ZSQ8ZG90PicpIH0pKVxuICAgIC5tYXAoKGVudHJ5KSA9PiAoeyAuLi5lbnRyeSwgcGF0aDogZW50cnkucGF0aC5yZXBsYWNlKC9cXC4vLCAnJykgfSkpXG4gICAgLm1hcCgoZW50cnkpID0+ICh7IC4uLmVudHJ5LCBwYXRoOiBlbnRyeS5wYXRoLnJlcGxhY2UoL0FSUlZBTF9TVEFSVC9nLCAnLnZhbHVlWycpIH0pKVxuICAgIC5tYXAoKGVudHJ5KSA9PiAoeyAuLi5lbnRyeSwgcGF0aDogZW50cnkucGF0aC5yZXBsYWNlKC9BUlJWQUxfRU5EL2csICddLnZhbHVlLicpIH0pKVxuICAgIC5mb3JFYWNoKChlbnRyeSkgPT4ge1xuICAgICAgc3dpdGNoIChlbnRyeS50eXBlKSB7XG4gICAgICAgIGNhc2UgT3BlcmF0aW9uLkFERDpcbiAgICAgICAgY2FzZSBPcGVyYXRpb24uVVBEQVRFOlxuICAgICAgICAgIHNldEJ5UGF0aChvYmplY3QsIGVudHJ5LnBhdGgsIHsgdHlwZTogZW50cnkudHlwZSwgdmFsdWU6IGVudHJ5LnZhbHVlLCBvbGRWYWx1ZTogZW50cnkub2xkVmFsdWUgfSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgT3BlcmF0aW9uLlJFTU9WRTpcbiAgICAgICAgICBzZXRCeVBhdGgob2JqZWN0LCBlbnRyeS5wYXRoLCB7IHR5cGU6IGVudHJ5LnR5cGUsIHZhbHVlOiB1bmRlZmluZWQsIG9sZFZhbHVlOiBlbnRyeS52YWx1ZSB9KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgcmV0dXJuIG9iamVjdDtcbn07XG5cbmNvbnN0IGNvbXBhcmUgPSAob2xkT2JqZWN0OiBhbnksIG5ld09iamVjdDogYW55KTogSUNvbXBhcmlzb25FbnJpY2hlZE5vZGUgPT4ge1xuICByZXR1cm4gYXBwbHlDaGFuZ2VsaXN0KGVucmljaChvbGRPYmplY3QpLCBhdG9taXplQ2hhbmdlc2V0KGRpZmYob2xkT2JqZWN0LCBuZXdPYmplY3QpKSk7XG59O1xuXG5leHBvcnQgeyBDb21wYXJlT3BlcmF0aW9uLCBJQ29tcGFyaXNvbkVucmljaGVkTm9kZSwgY3JlYXRlVmFsdWUsIGNyZWF0ZUNvbnRhaW5lciwgZW5yaWNoLCBhcHBseUNoYW5nZWxpc3QsIGNvbXBhcmUgfTtcbiIsICJpbXBvcnQgeyBTeW5jUGx1Z2luIH0gZnJvbSAnLi9TeW5jUGx1Z2luJztcbmltcG9ydCB7IENvcmVFdmVudHMgfSBmcm9tICcuLi9jb25zdGFudHMvQ29yZUV2ZW50cyc7XG5pbXBvcnQgeyBkaWZmIH0gZnJvbSAnanNvbi1kaWZmLXRzJztcbi8qKlxuICogQmFzZUVudGl0eVNlcnZpY2U8VCBleHRlbmRzIElTeW5jPiAtIEFic3RyYWN0IGJhc2UgY2xhc3MgZm9yIGFsbCBlbnRpdHkgc2VydmljZXNcbiAqXG4gKiBQUk9WSURFUzpcbiAqIC0gR2VuZXJpYyBDUlVEIG9wZXJhdGlvbnMgKGdldCwgZ2V0QWxsLCBzYXZlLCBkZWxldGUpXG4gKiAtIFN5bmMgc3RhdHVzIG1hbmFnZW1lbnQgKGRlbGVnYXRlcyB0byBTeW5jUGx1Z2luKVxuICogLSBTZXJpYWxpemF0aW9uIGhvb2tzIChvdmVycmlkZSBpbiBzdWJjbGFzcyBpZiBuZWVkZWQpXG4gKi9cbmV4cG9ydCBjbGFzcyBCYXNlRW50aXR5U2VydmljZSB7XG4gICAgY29uc3RydWN0b3IoY29udGV4dCwgZXZlbnRCdXMpIHtcbiAgICAgICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgdGhpcy5ldmVudEJ1cyA9IGV2ZW50QnVzO1xuICAgICAgICB0aGlzLnN5bmNQbHVnaW4gPSBuZXcgU3luY1BsdWdpbih0aGlzKTtcbiAgICB9XG4gICAgZ2V0IGRiKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb250ZXh0LmdldERhdGFiYXNlKCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNlcmlhbGl6ZSBlbnRpdHkgYmVmb3JlIHN0b3JpbmcgaW4gSW5kZXhlZERCXG4gICAgICovXG4gICAgc2VyaWFsaXplKGVudGl0eSkge1xuICAgICAgICByZXR1cm4gZW50aXR5O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBEZXNlcmlhbGl6ZSBkYXRhIGZyb20gSW5kZXhlZERCIGJhY2sgdG8gZW50aXR5XG4gICAgICovXG4gICAgZGVzZXJpYWxpemUoZGF0YSkge1xuICAgICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGEgc2luZ2xlIGVudGl0eSBieSBJRFxuICAgICAqL1xuICAgIGFzeW5jIGdldChpZCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSB0aGlzLmRiLnRyYW5zYWN0aW9uKFt0aGlzLnN0b3JlTmFtZV0sICdyZWFkb25seScpO1xuICAgICAgICAgICAgY29uc3Qgc3RvcmUgPSB0cmFuc2FjdGlvbi5vYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7XG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gc3RvcmUuZ2V0KGlkKTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25zdWNjZXNzID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSByZXF1ZXN0LnJlc3VsdDtcbiAgICAgICAgICAgICAgICByZXNvbHZlKGRhdGEgPyB0aGlzLmRlc2VyaWFsaXplKGRhdGEpIDogbnVsbCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVxdWVzdC5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBnZXQgJHt0aGlzLmVudGl0eVR5cGV9ICR7aWR9OiAke3JlcXVlc3QuZXJyb3J9YCkpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgZW50aXRpZXNcbiAgICAgKi9cbiAgICBhc3luYyBnZXRBbGwoKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IHRoaXMuZGIudHJhbnNhY3Rpb24oW3RoaXMuc3RvcmVOYW1lXSwgJ3JlYWRvbmx5Jyk7XG4gICAgICAgICAgICBjb25zdCBzdG9yZSA9IHRyYW5zYWN0aW9uLm9iamVjdFN0b3JlKHRoaXMuc3RvcmVOYW1lKTtcbiAgICAgICAgICAgIGNvbnN0IHJlcXVlc3QgPSBzdG9yZS5nZXRBbGwoKTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25zdWNjZXNzID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSByZXF1ZXN0LnJlc3VsdDtcbiAgICAgICAgICAgICAgICBjb25zdCBlbnRpdGllcyA9IGRhdGEubWFwKGl0ZW0gPT4gdGhpcy5kZXNlcmlhbGl6ZShpdGVtKSk7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShlbnRpdGllcyk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVxdWVzdC5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBnZXQgYWxsICR7dGhpcy5lbnRpdHlUeXBlfXM6ICR7cmVxdWVzdC5lcnJvcn1gKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2F2ZSBhbiBlbnRpdHkgKGNyZWF0ZSBvciB1cGRhdGUpXG4gICAgICogRW1pdHMgRU5USVRZX1NBVkVEIGV2ZW50IHdpdGggb3BlcmF0aW9uIHR5cGUgYW5kIGNoYW5nZXMgKGRpZmYgZm9yIHVwZGF0ZXMpXG4gICAgICogQHBhcmFtIGVudGl0eSAtIEVudGl0eSB0byBzYXZlXG4gICAgICogQHBhcmFtIHNpbGVudCAtIElmIHRydWUsIHNraXAgZXZlbnQgZW1pc3Npb24gKHVzZWQgZm9yIHNlZWRpbmcpXG4gICAgICovXG4gICAgYXN5bmMgc2F2ZShlbnRpdHksIHNpbGVudCA9IGZhbHNlKSB7XG4gICAgICAgIGNvbnN0IGVudGl0eUlkID0gZW50aXR5LmlkO1xuICAgICAgICBjb25zdCBleGlzdGluZ0VudGl0eSA9IGF3YWl0IHRoaXMuZ2V0KGVudGl0eUlkKTtcbiAgICAgICAgY29uc3QgaXNDcmVhdGUgPSBleGlzdGluZ0VudGl0eSA9PT0gbnVsbDtcbiAgICAgICAgLy8gQ2FsY3VsYXRlIGNoYW5nZXM6IGZ1bGwgZW50aXR5IGZvciBjcmVhdGUsIGRpZmYgZm9yIHVwZGF0ZVxuICAgICAgICBsZXQgY2hhbmdlcztcbiAgICAgICAgaWYgKGlzQ3JlYXRlKSB7XG4gICAgICAgICAgICBjaGFuZ2VzID0gZW50aXR5O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgZXhpc3RpbmdTZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemUoZXhpc3RpbmdFbnRpdHkpO1xuICAgICAgICAgICAgY29uc3QgbmV3U2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplKGVudGl0eSk7XG4gICAgICAgICAgICBjaGFuZ2VzID0gZGlmZihleGlzdGluZ1NlcmlhbGl6ZWQsIG5ld1NlcmlhbGl6ZWQpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZShlbnRpdHkpO1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSB0aGlzLmRiLnRyYW5zYWN0aW9uKFt0aGlzLnN0b3JlTmFtZV0sICdyZWFkd3JpdGUnKTtcbiAgICAgICAgICAgIGNvbnN0IHN0b3JlID0gdHJhbnNhY3Rpb24ub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpO1xuICAgICAgICAgICAgY29uc3QgcmVxdWVzdCA9IHN0b3JlLnB1dChzZXJpYWxpemVkKTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25zdWNjZXNzID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIE9ubHkgZW1pdCBldmVudCBpZiBub3Qgc2lsZW50IChzaWxlbnQgdXNlZCBmb3Igc2VlZGluZylcbiAgICAgICAgICAgICAgICBpZiAoIXNpbGVudCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXlsb2FkID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgZW50aXR5VHlwZTogdGhpcy5lbnRpdHlUeXBlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZW50aXR5SWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBvcGVyYXRpb246IGlzQ3JlYXRlID8gJ2NyZWF0ZScgOiAndXBkYXRlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoYW5nZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IERhdGUubm93KClcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENvcmVFdmVudHMuRU5USVRZX1NBVkVELCBwYXlsb2FkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gc2F2ZSAke3RoaXMuZW50aXR5VHlwZX0gJHtlbnRpdHlJZH06ICR7cmVxdWVzdC5lcnJvcn1gKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRGVsZXRlIGFuIGVudGl0eVxuICAgICAqIEVtaXRzIEVOVElUWV9ERUxFVEVEIGV2ZW50XG4gICAgICovXG4gICAgYXN5bmMgZGVsZXRlKGlkKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IHRoaXMuZGIudHJhbnNhY3Rpb24oW3RoaXMuc3RvcmVOYW1lXSwgJ3JlYWR3cml0ZScpO1xuICAgICAgICAgICAgY29uc3Qgc3RvcmUgPSB0cmFuc2FjdGlvbi5vYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7XG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gc3RvcmUuZGVsZXRlKGlkKTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25zdWNjZXNzID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgICAgICAgICAgICAgIGVudGl0eVR5cGU6IHRoaXMuZW50aXR5VHlwZSxcbiAgICAgICAgICAgICAgICAgICAgZW50aXR5SWQ6IGlkLFxuICAgICAgICAgICAgICAgICAgICBvcGVyYXRpb246ICdkZWxldGUnLFxuICAgICAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IERhdGUubm93KClcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMuZW1pdChDb3JlRXZlbnRzLkVOVElUWV9ERUxFVEVELCBwYXlsb2FkKTtcbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVxdWVzdC5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBkZWxldGUgJHt0aGlzLmVudGl0eVR5cGV9ICR7aWR9OiAke3JlcXVlc3QuZXJyb3J9YCkpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8vIFN5bmMgbWV0aG9kcyAtIGRlbGVnYXRlIHRvIFN5bmNQbHVnaW5cbiAgICBhc3luYyBtYXJrQXNTeW5jZWQoaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3luY1BsdWdpbi5tYXJrQXNTeW5jZWQoaWQpO1xuICAgIH1cbiAgICBhc3luYyBtYXJrQXNFcnJvcihpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zeW5jUGx1Z2luLm1hcmtBc0Vycm9yKGlkKTtcbiAgICB9XG4gICAgYXN5bmMgZ2V0U3luY1N0YXR1cyhpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zeW5jUGx1Z2luLmdldFN5bmNTdGF0dXMoaWQpO1xuICAgIH1cbiAgICBhc3luYyBnZXRCeVN5bmNTdGF0dXMoc3luY1N0YXR1cykge1xuICAgICAgICByZXR1cm4gdGhpcy5zeW5jUGx1Z2luLmdldEJ5U3luY1N0YXR1cyhzeW5jU3RhdHVzKTtcbiAgICB9XG59XG4iLCAiaW1wb3J0IHsgRXZlbnRTdG9yZSB9IGZyb20gJy4vRXZlbnRTdG9yZSc7XG5pbXBvcnQgeyBFdmVudFNlcmlhbGl6YXRpb24gfSBmcm9tICcuL0V2ZW50U2VyaWFsaXphdGlvbic7XG5pbXBvcnQgeyBCYXNlRW50aXR5U2VydmljZSB9IGZyb20gJy4uL0Jhc2VFbnRpdHlTZXJ2aWNlJztcbi8qKlxuICogRXZlbnRTZXJ2aWNlIC0gQ1JVRCBvcGVyYXRpb25zIGZvciBjYWxlbmRhciBldmVudHMgaW4gSW5kZXhlZERCXG4gKlxuICogRXh0ZW5kcyBCYXNlRW50aXR5U2VydmljZSBmb3Igc2hhcmVkIENSVUQgYW5kIHN5bmMgbG9naWMuXG4gKiBQcm92aWRlcyBldmVudC1zcGVjaWZpYyBxdWVyeSBtZXRob2RzLlxuICovXG5leHBvcnQgY2xhc3MgRXZlbnRTZXJ2aWNlIGV4dGVuZHMgQmFzZUVudGl0eVNlcnZpY2Uge1xuICAgIGNvbnN0cnVjdG9yKGNvbnRleHQsIGV2ZW50QnVzKSB7XG4gICAgICAgIHN1cGVyKGNvbnRleHQsIGV2ZW50QnVzKTtcbiAgICAgICAgdGhpcy5zdG9yZU5hbWUgPSBFdmVudFN0b3JlLlNUT1JFX05BTUU7XG4gICAgICAgIHRoaXMuZW50aXR5VHlwZSA9ICdFdmVudCc7XG4gICAgfVxuICAgIHNlcmlhbGl6ZShldmVudCkge1xuICAgICAgICByZXR1cm4gRXZlbnRTZXJpYWxpemF0aW9uLnNlcmlhbGl6ZShldmVudCk7XG4gICAgfVxuICAgIGRlc2VyaWFsaXplKGRhdGEpIHtcbiAgICAgICAgcmV0dXJuIEV2ZW50U2VyaWFsaXphdGlvbi5kZXNlcmlhbGl6ZShkYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGV2ZW50cyB3aXRoaW4gYSBkYXRlIHJhbmdlXG4gICAgICovXG4gICAgYXN5bmMgZ2V0QnlEYXRlUmFuZ2Uoc3RhcnQsIGVuZCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSB0aGlzLmRiLnRyYW5zYWN0aW9uKFt0aGlzLnN0b3JlTmFtZV0sICdyZWFkb25seScpO1xuICAgICAgICAgICAgY29uc3Qgc3RvcmUgPSB0cmFuc2FjdGlvbi5vYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7XG4gICAgICAgICAgICBjb25zdCBpbmRleCA9IHN0b3JlLmluZGV4KCdzdGFydCcpO1xuICAgICAgICAgICAgY29uc3QgcmFuZ2UgPSBJREJLZXlSYW5nZS5sb3dlckJvdW5kKHN0YXJ0LnRvSVNPU3RyaW5nKCkpO1xuICAgICAgICAgICAgY29uc3QgcmVxdWVzdCA9IGluZGV4LmdldEFsbChyYW5nZSk7XG4gICAgICAgICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gcmVxdWVzdC5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgY29uc3QgZXZlbnRzID0gZGF0YVxuICAgICAgICAgICAgICAgICAgICAubWFwKGl0ZW0gPT4gdGhpcy5kZXNlcmlhbGl6ZShpdGVtKSlcbiAgICAgICAgICAgICAgICAgICAgLmZpbHRlcihldmVudCA9PiBldmVudC5zdGFydCA8PSBlbmQpO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoZXZlbnRzKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXF1ZXN0Lm9uZXJyb3IgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgRmFpbGVkIHRvIGdldCBldmVudHMgYnkgZGF0ZSByYW5nZTogJHtyZXF1ZXN0LmVycm9yfWApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgZXZlbnRzIGZvciBhIHNwZWNpZmljIHJlc291cmNlXG4gICAgICovXG4gICAgYXN5bmMgZ2V0QnlSZXNvdXJjZShyZXNvdXJjZUlkKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IHRoaXMuZGIudHJhbnNhY3Rpb24oW3RoaXMuc3RvcmVOYW1lXSwgJ3JlYWRvbmx5Jyk7XG4gICAgICAgICAgICBjb25zdCBzdG9yZSA9IHRyYW5zYWN0aW9uLm9iamVjdFN0b3JlKHRoaXMuc3RvcmVOYW1lKTtcbiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gc3RvcmUuaW5kZXgoJ3Jlc291cmNlSWQnKTtcbiAgICAgICAgICAgIGNvbnN0IHJlcXVlc3QgPSBpbmRleC5nZXRBbGwocmVzb3VyY2VJZCk7XG4gICAgICAgICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gcmVxdWVzdC5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgY29uc3QgZXZlbnRzID0gZGF0YS5tYXAoaXRlbSA9PiB0aGlzLmRlc2VyaWFsaXplKGl0ZW0pKTtcbiAgICAgICAgICAgICAgICByZXNvbHZlKGV2ZW50cyk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVxdWVzdC5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBnZXQgZXZlbnRzIGZvciByZXNvdXJjZSAke3Jlc291cmNlSWR9OiAke3JlcXVlc3QuZXJyb3J9YCkpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBldmVudHMgZm9yIGEgcmVzb3VyY2Ugd2l0aGluIGEgZGF0ZSByYW5nZVxuICAgICAqL1xuICAgIGFzeW5jIGdldEJ5UmVzb3VyY2VBbmREYXRlUmFuZ2UocmVzb3VyY2VJZCwgc3RhcnQsIGVuZCkge1xuICAgICAgICBjb25zdCByZXNvdXJjZUV2ZW50cyA9IGF3YWl0IHRoaXMuZ2V0QnlSZXNvdXJjZShyZXNvdXJjZUlkKTtcbiAgICAgICAgcmV0dXJuIHJlc291cmNlRXZlbnRzLmZpbHRlcihldmVudCA9PiBldmVudC5zdGFydCA+PSBzdGFydCAmJiBldmVudC5zdGFydCA8PSBlbmQpO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIFJlc291cmNlU3RvcmUgLSBJbmRleGVkREIgT2JqZWN0U3RvcmUgZGVmaW5pdGlvbiBmb3IgcmVzb3VyY2VzXG4gKi9cbmV4cG9ydCBjbGFzcyBSZXNvdXJjZVN0b3JlIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5zdG9yZU5hbWUgPSBSZXNvdXJjZVN0b3JlLlNUT1JFX05BTUU7XG4gICAgfVxuICAgIGNyZWF0ZShkYikge1xuICAgICAgICBjb25zdCBzdG9yZSA9IGRiLmNyZWF0ZU9iamVjdFN0b3JlKFJlc291cmNlU3RvcmUuU1RPUkVfTkFNRSwgeyBrZXlQYXRoOiAnaWQnIH0pO1xuICAgICAgICBzdG9yZS5jcmVhdGVJbmRleCgndHlwZScsICd0eXBlJywgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgICAgICBzdG9yZS5jcmVhdGVJbmRleCgnc3luY1N0YXR1cycsICdzeW5jU3RhdHVzJywgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgICAgICBzdG9yZS5jcmVhdGVJbmRleCgnaXNBY3RpdmUnLCAnaXNBY3RpdmUnLCB7IHVuaXF1ZTogZmFsc2UgfSk7XG4gICAgfVxufVxuUmVzb3VyY2VTdG9yZS5TVE9SRV9OQU1FID0gJ3Jlc291cmNlcyc7XG4iLCAiaW1wb3J0IHsgUmVzb3VyY2VTdG9yZSB9IGZyb20gJy4vUmVzb3VyY2VTdG9yZSc7XG5pbXBvcnQgeyBCYXNlRW50aXR5U2VydmljZSB9IGZyb20gJy4uL0Jhc2VFbnRpdHlTZXJ2aWNlJztcbi8qKlxuICogUmVzb3VyY2VTZXJ2aWNlIC0gQ1JVRCBvcGVyYXRpb25zIGZvciByZXNvdXJjZXMgaW4gSW5kZXhlZERCXG4gKi9cbmV4cG9ydCBjbGFzcyBSZXNvdXJjZVNlcnZpY2UgZXh0ZW5kcyBCYXNlRW50aXR5U2VydmljZSB7XG4gICAgY29uc3RydWN0b3IoY29udGV4dCwgZXZlbnRCdXMpIHtcbiAgICAgICAgc3VwZXIoY29udGV4dCwgZXZlbnRCdXMpO1xuICAgICAgICB0aGlzLnN0b3JlTmFtZSA9IFJlc291cmNlU3RvcmUuU1RPUkVfTkFNRTtcbiAgICAgICAgdGhpcy5lbnRpdHlUeXBlID0gJ1Jlc291cmNlJztcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGFsbCBhY3RpdmUgcmVzb3VyY2VzXG4gICAgICovXG4gICAgYXN5bmMgZ2V0QWN0aXZlKCkge1xuICAgICAgICBjb25zdCBhbGwgPSBhd2FpdCB0aGlzLmdldEFsbCgpO1xuICAgICAgICByZXR1cm4gYWxsLmZpbHRlcihyID0+IHIuaXNBY3RpdmUgIT09IGZhbHNlKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IHJlc291cmNlcyBieSBJRHNcbiAgICAgKi9cbiAgICBhc3luYyBnZXRCeUlkcyhpZHMpIHtcbiAgICAgICAgaWYgKGlkcy5sZW5ndGggPT09IDApXG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChpZHMubWFwKGlkID0+IHRoaXMuZ2V0KGlkKSkpO1xuICAgICAgICByZXR1cm4gcmVzdWx0cy5maWx0ZXIoKHIpID0+IHIgIT09IG51bGwpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgcmVzb3VyY2VzIGJ5IHR5cGVcbiAgICAgKi9cbiAgICBhc3luYyBnZXRCeVR5cGUodHlwZSkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSB0aGlzLmRiLnRyYW5zYWN0aW9uKFt0aGlzLnN0b3JlTmFtZV0sICdyZWFkb25seScpO1xuICAgICAgICAgICAgY29uc3Qgc3RvcmUgPSB0cmFuc2FjdGlvbi5vYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSk7XG4gICAgICAgICAgICBjb25zdCBpbmRleCA9IHN0b3JlLmluZGV4KCd0eXBlJyk7XG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gaW5kZXguZ2V0QWxsKHR5cGUpO1xuICAgICAgICAgICAgcmVxdWVzdC5vbnN1Y2Nlc3MgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IHJlcXVlc3QucmVzdWx0O1xuICAgICAgICAgICAgICAgIHJlc29sdmUoZGF0YSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVxdWVzdC5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBnZXQgcmVzb3VyY2VzIGJ5IHR5cGUgJHt0eXBlfTogJHtyZXF1ZXN0LmVycm9yfWApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIEJvb2tpbmdTdG9yZSAtIEluZGV4ZWREQiBPYmplY3RTdG9yZSBkZWZpbml0aW9uIGZvciBib29raW5nc1xuICovXG5leHBvcnQgY2xhc3MgQm9va2luZ1N0b3JlIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5zdG9yZU5hbWUgPSBCb29raW5nU3RvcmUuU1RPUkVfTkFNRTtcbiAgICB9XG4gICAgY3JlYXRlKGRiKSB7XG4gICAgICAgIGNvbnN0IHN0b3JlID0gZGIuY3JlYXRlT2JqZWN0U3RvcmUoQm9va2luZ1N0b3JlLlNUT1JFX05BTUUsIHsga2V5UGF0aDogJ2lkJyB9KTtcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ2N1c3RvbWVySWQnLCAnY3VzdG9tZXJJZCcsIHsgdW5pcXVlOiBmYWxzZSB9KTtcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ3N0YXR1cycsICdzdGF0dXMnLCB7IHVuaXF1ZTogZmFsc2UgfSk7XG4gICAgICAgIHN0b3JlLmNyZWF0ZUluZGV4KCdzeW5jU3RhdHVzJywgJ3N5bmNTdGF0dXMnLCB7IHVuaXF1ZTogZmFsc2UgfSk7XG4gICAgICAgIHN0b3JlLmNyZWF0ZUluZGV4KCdjcmVhdGVkQXQnLCAnY3JlYXRlZEF0JywgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgIH1cbn1cbkJvb2tpbmdTdG9yZS5TVE9SRV9OQU1FID0gJ2Jvb2tpbmdzJztcbiIsICJpbXBvcnQgeyBCb29raW5nU3RvcmUgfSBmcm9tICcuL0Jvb2tpbmdTdG9yZSc7XG5pbXBvcnQgeyBCYXNlRW50aXR5U2VydmljZSB9IGZyb20gJy4uL0Jhc2VFbnRpdHlTZXJ2aWNlJztcbi8qKlxuICogQm9va2luZ1NlcnZpY2UgLSBDUlVEIG9wZXJhdGlvbnMgZm9yIGJvb2tpbmdzIGluIEluZGV4ZWREQlxuICovXG5leHBvcnQgY2xhc3MgQm9va2luZ1NlcnZpY2UgZXh0ZW5kcyBCYXNlRW50aXR5U2VydmljZSB7XG4gICAgY29uc3RydWN0b3IoY29udGV4dCwgZXZlbnRCdXMpIHtcbiAgICAgICAgc3VwZXIoY29udGV4dCwgZXZlbnRCdXMpO1xuICAgICAgICB0aGlzLnN0b3JlTmFtZSA9IEJvb2tpbmdTdG9yZS5TVE9SRV9OQU1FO1xuICAgICAgICB0aGlzLmVudGl0eVR5cGUgPSAnQm9va2luZyc7XG4gICAgfVxuICAgIHNlcmlhbGl6ZShib29raW5nKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi5ib29raW5nLFxuICAgICAgICAgICAgY3JlYXRlZEF0OiBib29raW5nLmNyZWF0ZWRBdC50b0lTT1N0cmluZygpXG4gICAgICAgIH07XG4gICAgfVxuICAgIGRlc2VyaWFsaXplKGRhdGEpIHtcbiAgICAgICAgY29uc3QgcmF3ID0gZGF0YTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLnJhdyxcbiAgICAgICAgICAgIGNyZWF0ZWRBdDogbmV3IERhdGUocmF3LmNyZWF0ZWRBdClcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGJvb2tpbmdzIGZvciBhIGN1c3RvbWVyXG4gICAgICovXG4gICAgYXN5bmMgZ2V0QnlDdXN0b21lcihjdXN0b21lcklkKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IHRoaXMuZGIudHJhbnNhY3Rpb24oW3RoaXMuc3RvcmVOYW1lXSwgJ3JlYWRvbmx5Jyk7XG4gICAgICAgICAgICBjb25zdCBzdG9yZSA9IHRyYW5zYWN0aW9uLm9iamVjdFN0b3JlKHRoaXMuc3RvcmVOYW1lKTtcbiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gc3RvcmUuaW5kZXgoJ2N1c3RvbWVySWQnKTtcbiAgICAgICAgICAgIGNvbnN0IHJlcXVlc3QgPSBpbmRleC5nZXRBbGwoY3VzdG9tZXJJZCk7XG4gICAgICAgICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gcmVxdWVzdC5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgY29uc3QgYm9va2luZ3MgPSBkYXRhLm1hcChpdGVtID0+IHRoaXMuZGVzZXJpYWxpemUoaXRlbSkpO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoYm9va2luZ3MpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gZ2V0IGJvb2tpbmdzIGZvciBjdXN0b21lciAke2N1c3RvbWVySWR9OiAke3JlcXVlc3QuZXJyb3J9YCkpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBib29raW5ncyBieSBzdGF0dXNcbiAgICAgKi9cbiAgICBhc3luYyBnZXRCeVN0YXR1cyhzdGF0dXMpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gdGhpcy5kYi50cmFuc2FjdGlvbihbdGhpcy5zdG9yZU5hbWVdLCAncmVhZG9ubHknKTtcbiAgICAgICAgICAgIGNvbnN0IHN0b3JlID0gdHJhbnNhY3Rpb24ub2JqZWN0U3RvcmUodGhpcy5zdG9yZU5hbWUpO1xuICAgICAgICAgICAgY29uc3QgaW5kZXggPSBzdG9yZS5pbmRleCgnc3RhdHVzJyk7XG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gaW5kZXguZ2V0QWxsKHN0YXR1cyk7XG4gICAgICAgICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gcmVxdWVzdC5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgY29uc3QgYm9va2luZ3MgPSBkYXRhLm1hcChpdGVtID0+IHRoaXMuZGVzZXJpYWxpemUoaXRlbSkpO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoYm9va2luZ3MpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gZ2V0IGJvb2tpbmdzIHdpdGggc3RhdHVzICR7c3RhdHVzfTogJHtyZXF1ZXN0LmVycm9yfWApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIEN1c3RvbWVyU3RvcmUgLSBJbmRleGVkREIgT2JqZWN0U3RvcmUgZGVmaW5pdGlvbiBmb3IgY3VzdG9tZXJzXG4gKi9cbmV4cG9ydCBjbGFzcyBDdXN0b21lclN0b3JlIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5zdG9yZU5hbWUgPSBDdXN0b21lclN0b3JlLlNUT1JFX05BTUU7XG4gICAgfVxuICAgIGNyZWF0ZShkYikge1xuICAgICAgICBjb25zdCBzdG9yZSA9IGRiLmNyZWF0ZU9iamVjdFN0b3JlKEN1c3RvbWVyU3RvcmUuU1RPUkVfTkFNRSwgeyBrZXlQYXRoOiAnaWQnIH0pO1xuICAgICAgICBzdG9yZS5jcmVhdGVJbmRleCgnbmFtZScsICduYW1lJywgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgICAgICBzdG9yZS5jcmVhdGVJbmRleCgncGhvbmUnLCAncGhvbmUnLCB7IHVuaXF1ZTogZmFsc2UgfSk7XG4gICAgICAgIHN0b3JlLmNyZWF0ZUluZGV4KCdzeW5jU3RhdHVzJywgJ3N5bmNTdGF0dXMnLCB7IHVuaXF1ZTogZmFsc2UgfSk7XG4gICAgfVxufVxuQ3VzdG9tZXJTdG9yZS5TVE9SRV9OQU1FID0gJ2N1c3RvbWVycyc7XG4iLCAiaW1wb3J0IHsgQ3VzdG9tZXJTdG9yZSB9IGZyb20gJy4vQ3VzdG9tZXJTdG9yZSc7XG5pbXBvcnQgeyBCYXNlRW50aXR5U2VydmljZSB9IGZyb20gJy4uL0Jhc2VFbnRpdHlTZXJ2aWNlJztcbi8qKlxuICogQ3VzdG9tZXJTZXJ2aWNlIC0gQ1JVRCBvcGVyYXRpb25zIGZvciBjdXN0b21lcnMgaW4gSW5kZXhlZERCXG4gKi9cbmV4cG9ydCBjbGFzcyBDdXN0b21lclNlcnZpY2UgZXh0ZW5kcyBCYXNlRW50aXR5U2VydmljZSB7XG4gICAgY29uc3RydWN0b3IoY29udGV4dCwgZXZlbnRCdXMpIHtcbiAgICAgICAgc3VwZXIoY29udGV4dCwgZXZlbnRCdXMpO1xuICAgICAgICB0aGlzLnN0b3JlTmFtZSA9IEN1c3RvbWVyU3RvcmUuU1RPUkVfTkFNRTtcbiAgICAgICAgdGhpcy5lbnRpdHlUeXBlID0gJ0N1c3RvbWVyJztcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2VhcmNoIGN1c3RvbWVycyBieSBuYW1lIChjYXNlLWluc2Vuc2l0aXZlIGNvbnRhaW5zKVxuICAgICAqL1xuICAgIGFzeW5jIHNlYXJjaEJ5TmFtZShxdWVyeSkge1xuICAgICAgICBjb25zdCBhbGwgPSBhd2FpdCB0aGlzLmdldEFsbCgpO1xuICAgICAgICBjb25zdCBsb3dlclF1ZXJ5ID0gcXVlcnkudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgcmV0dXJuIGFsbC5maWx0ZXIoYyA9PiBjLm5hbWUudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhsb3dlclF1ZXJ5KSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEZpbmQgY3VzdG9tZXIgYnkgcGhvbmVcbiAgICAgKi9cbiAgICBhc3luYyBnZXRCeVBob25lKHBob25lKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IHRoaXMuZGIudHJhbnNhY3Rpb24oW3RoaXMuc3RvcmVOYW1lXSwgJ3JlYWRvbmx5Jyk7XG4gICAgICAgICAgICBjb25zdCBzdG9yZSA9IHRyYW5zYWN0aW9uLm9iamVjdFN0b3JlKHRoaXMuc3RvcmVOYW1lKTtcbiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gc3RvcmUuaW5kZXgoJ3Bob25lJyk7XG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gaW5kZXguZ2V0KHBob25lKTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25zdWNjZXNzID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSByZXF1ZXN0LnJlc3VsdDtcbiAgICAgICAgICAgICAgICByZXNvbHZlKGRhdGEgPyBkYXRhIDogbnVsbCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVxdWVzdC5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBmaW5kIGN1c3RvbWVyIGJ5IHBob25lICR7cGhvbmV9OiAke3JlcXVlc3QuZXJyb3J9YCkpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfVxufVxuIiwgIi8qKlxuICogVGVhbVN0b3JlIC0gSW5kZXhlZERCIE9iamVjdFN0b3JlIGRlZmluaXRpb24gZm9yIHRlYW1zXG4gKi9cbmV4cG9ydCBjbGFzcyBUZWFtU3RvcmUge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnN0b3JlTmFtZSA9IFRlYW1TdG9yZS5TVE9SRV9OQU1FO1xuICAgIH1cbiAgICBjcmVhdGUoZGIpIHtcbiAgICAgICAgZGIuY3JlYXRlT2JqZWN0U3RvcmUoVGVhbVN0b3JlLlNUT1JFX05BTUUsIHsga2V5UGF0aDogJ2lkJyB9KTtcbiAgICB9XG59XG5UZWFtU3RvcmUuU1RPUkVfTkFNRSA9ICd0ZWFtcyc7XG4iLCAiaW1wb3J0IHsgVGVhbVN0b3JlIH0gZnJvbSAnLi9UZWFtU3RvcmUnO1xuaW1wb3J0IHsgQmFzZUVudGl0eVNlcnZpY2UgfSBmcm9tICcuLi9CYXNlRW50aXR5U2VydmljZSc7XG4vKipcbiAqIFRlYW1TZXJ2aWNlIC0gQ1JVRCBvcGVyYXRpb25zIGZvciB0ZWFtcyBpbiBJbmRleGVkREJcbiAqXG4gKiBUZWFtcyBkZWZpbmUgd2hpY2ggcmVzb3VyY2VzIGJlbG9uZyB0b2dldGhlciBmb3IgaGllcmFyY2hpY2FsIGdyb3VwaW5nLlxuICogRXh0ZW5kcyBCYXNlRW50aXR5U2VydmljZSBmb3Igc3RhbmRhcmQgZW50aXR5IG9wZXJhdGlvbnMuXG4gKi9cbmV4cG9ydCBjbGFzcyBUZWFtU2VydmljZSBleHRlbmRzIEJhc2VFbnRpdHlTZXJ2aWNlIHtcbiAgICBjb25zdHJ1Y3Rvcihjb250ZXh0LCBldmVudEJ1cykge1xuICAgICAgICBzdXBlcihjb250ZXh0LCBldmVudEJ1cyk7XG4gICAgICAgIHRoaXMuc3RvcmVOYW1lID0gVGVhbVN0b3JlLlNUT1JFX05BTUU7XG4gICAgICAgIHRoaXMuZW50aXR5VHlwZSA9ICdUZWFtJztcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IHRlYW1zIGJ5IElEc1xuICAgICAqL1xuICAgIGFzeW5jIGdldEJ5SWRzKGlkcykge1xuICAgICAgICBpZiAoaWRzLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKGlkcy5tYXAoaWQgPT4gdGhpcy5nZXQoaWQpKSk7XG4gICAgICAgIHJldHVybiByZXN1bHRzLmZpbHRlcigodCkgPT4gdCAhPT0gbnVsbCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEJ1aWxkIHJldmVyc2UgbG9va3VwOiByZXNvdXJjZUlkIFx1MjE5MiB0ZWFtSWRcbiAgICAgKi9cbiAgICBhc3luYyBidWlsZFJlc291cmNlVG9UZWFtTWFwKCkge1xuICAgICAgICBjb25zdCB0ZWFtcyA9IGF3YWl0IHRoaXMuZ2V0QWxsKCk7XG4gICAgICAgIGNvbnN0IG1hcCA9IHt9O1xuICAgICAgICBmb3IgKGNvbnN0IHRlYW0gb2YgdGVhbXMpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcmVzb3VyY2VJZCBvZiB0ZWFtLnJlc291cmNlSWRzKSB7XG4gICAgICAgICAgICAgICAgbWFwW3Jlc291cmNlSWRdID0gdGVhbS5pZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWFwO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIERlcGFydG1lbnRTdG9yZSAtIEluZGV4ZWREQiBPYmplY3RTdG9yZSBkZWZpbml0aW9uIGZvciBkZXBhcnRtZW50c1xuICovXG5leHBvcnQgY2xhc3MgRGVwYXJ0bWVudFN0b3JlIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5zdG9yZU5hbWUgPSBEZXBhcnRtZW50U3RvcmUuU1RPUkVfTkFNRTtcbiAgICB9XG4gICAgY3JlYXRlKGRiKSB7XG4gICAgICAgIGRiLmNyZWF0ZU9iamVjdFN0b3JlKERlcGFydG1lbnRTdG9yZS5TVE9SRV9OQU1FLCB7IGtleVBhdGg6ICdpZCcgfSk7XG4gICAgfVxufVxuRGVwYXJ0bWVudFN0b3JlLlNUT1JFX05BTUUgPSAnZGVwYXJ0bWVudHMnO1xuIiwgImltcG9ydCB7IERlcGFydG1lbnRTdG9yZSB9IGZyb20gJy4vRGVwYXJ0bWVudFN0b3JlJztcbmltcG9ydCB7IEJhc2VFbnRpdHlTZXJ2aWNlIH0gZnJvbSAnLi4vQmFzZUVudGl0eVNlcnZpY2UnO1xuLyoqXG4gKiBEZXBhcnRtZW50U2VydmljZSAtIENSVUQgb3BlcmF0aW9ucyBmb3IgZGVwYXJ0bWVudHMgaW4gSW5kZXhlZERCXG4gKi9cbmV4cG9ydCBjbGFzcyBEZXBhcnRtZW50U2VydmljZSBleHRlbmRzIEJhc2VFbnRpdHlTZXJ2aWNlIHtcbiAgICBjb25zdHJ1Y3Rvcihjb250ZXh0LCBldmVudEJ1cykge1xuICAgICAgICBzdXBlcihjb250ZXh0LCBldmVudEJ1cyk7XG4gICAgICAgIHRoaXMuc3RvcmVOYW1lID0gRGVwYXJ0bWVudFN0b3JlLlNUT1JFX05BTUU7XG4gICAgICAgIHRoaXMuZW50aXR5VHlwZSA9ICdEZXBhcnRtZW50JztcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGRlcGFydG1lbnRzIGJ5IElEc1xuICAgICAqL1xuICAgIGFzeW5jIGdldEJ5SWRzKGlkcykge1xuICAgICAgICBpZiAoaWRzLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKGlkcy5tYXAoaWQgPT4gdGhpcy5nZXQoaWQpKSk7XG4gICAgICAgIHJldHVybiByZXN1bHRzLmZpbHRlcigoZCkgPT4gZCAhPT0gbnVsbCk7XG4gICAgfVxufVxuIiwgIi8qKlxuICogU2V0dGluZ3NTdG9yZSAtIEluZGV4ZWREQiBPYmplY3RTdG9yZSBkZWZpbml0aW9uIGZvciB0ZW5hbnQgc2V0dGluZ3NcbiAqXG4gKiBTaW5nbGUgc3RvcmUgZm9yIGFsbCBzZXR0aW5ncyBzZWN0aW9ucy4gU2V0dGluZ3MgYXJlIHN0b3JlZCBhcyBvbmUgZG9jdW1lbnRcbiAqIHBlciB0ZW5hbnQgd2l0aCBpZD0ndGVuYW50LXNldHRpbmdzJy5cbiAqL1xuZXhwb3J0IGNsYXNzIFNldHRpbmdzU3RvcmUge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnN0b3JlTmFtZSA9IFNldHRpbmdzU3RvcmUuU1RPUkVfTkFNRTtcbiAgICB9XG4gICAgY3JlYXRlKGRiKSB7XG4gICAgICAgIGRiLmNyZWF0ZU9iamVjdFN0b3JlKFNldHRpbmdzU3RvcmUuU1RPUkVfTkFNRSwgeyBrZXlQYXRoOiAnaWQnIH0pO1xuICAgIH1cbn1cblNldHRpbmdzU3RvcmUuU1RPUkVfTkFNRSA9ICdzZXR0aW5ncyc7XG4iLCAiLyoqXG4gKiBTZXR0aW5ncyBJRHMgYXMgY29uc3QgZm9yIHR5cGUgc2FmZXR5XG4gKi9cbmV4cG9ydCBjb25zdCBTZXR0aW5nc0lkcyA9IHtcbiAgICBXT1JLV0VFSzogJ3dvcmt3ZWVrJyxcbiAgICBHUklEOiAnZ3JpZCcsXG4gICAgVElNRV9GT1JNQVQ6ICd0aW1lRm9ybWF0JyxcbiAgICBWSUVXUzogJ3ZpZXdzJ1xufTtcbiIsICJpbXBvcnQgeyBTZXR0aW5nc0lkcyB9IGZyb20gJy4uLy4uL3R5cGVzL1NldHRpbmdzVHlwZXMnO1xuaW1wb3J0IHsgU2V0dGluZ3NTdG9yZSB9IGZyb20gJy4vU2V0dGluZ3NTdG9yZSc7XG5pbXBvcnQgeyBCYXNlRW50aXR5U2VydmljZSB9IGZyb20gJy4uL0Jhc2VFbnRpdHlTZXJ2aWNlJztcbi8qKlxuICogU2V0dGluZ3NTZXJ2aWNlIC0gQ1JVRCBvcGVyYXRpb25zIGZvciB0ZW5hbnQgc2V0dGluZ3NcbiAqXG4gKiBTZXR0aW5ncyBhcmUgc3RvcmVkIGFzIHNlcGFyYXRlIHJlY29yZHMgcGVyIHNlY3Rpb24uXG4gKiBUaGlzIHNlcnZpY2UgcHJvdmlkZXMgdHlwZWQgbWV0aG9kcyBmb3IgYWNjZXNzaW5nIHNwZWNpZmljIHNldHRpbmdzLlxuICovXG5leHBvcnQgY2xhc3MgU2V0dGluZ3NTZXJ2aWNlIGV4dGVuZHMgQmFzZUVudGl0eVNlcnZpY2Uge1xuICAgIGNvbnN0cnVjdG9yKGNvbnRleHQsIGV2ZW50QnVzKSB7XG4gICAgICAgIHN1cGVyKGNvbnRleHQsIGV2ZW50QnVzKTtcbiAgICAgICAgdGhpcy5zdG9yZU5hbWUgPSBTZXR0aW5nc1N0b3JlLlNUT1JFX05BTUU7XG4gICAgICAgIHRoaXMuZW50aXR5VHlwZSA9ICdTZXR0aW5ncyc7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCB3b3Jrd2VlayBzZXR0aW5nc1xuICAgICAqL1xuICAgIGFzeW5jIGdldFdvcmt3ZWVrU2V0dGluZ3MoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldChTZXR0aW5nc0lkcy5XT1JLV0VFSyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBncmlkIHNldHRpbmdzXG4gICAgICovXG4gICAgYXN5bmMgZ2V0R3JpZFNldHRpbmdzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXQoU2V0dGluZ3NJZHMuR1JJRCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCB0aW1lIGZvcm1hdCBzZXR0aW5nc1xuICAgICAqL1xuICAgIGFzeW5jIGdldFRpbWVGb3JtYXRTZXR0aW5ncygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0KFNldHRpbmdzSWRzLlRJTUVfRk9STUFUKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IHZpZXcgc2V0dGluZ3NcbiAgICAgKi9cbiAgICBhc3luYyBnZXRWaWV3U2V0dGluZ3MoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldChTZXR0aW5nc0lkcy5WSUVXUyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCB3b3Jrd2VlayBwcmVzZXQgYnkgSURcbiAgICAgKi9cbiAgICBhc3luYyBnZXRXb3Jrd2Vla1ByZXNldChwcmVzZXRJZCkge1xuICAgICAgICBjb25zdCBzZXR0aW5ncyA9IGF3YWl0IHRoaXMuZ2V0V29ya3dlZWtTZXR0aW5ncygpO1xuICAgICAgICBpZiAoIXNldHRpbmdzKVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIHJldHVybiBzZXR0aW5ncy5wcmVzZXRzW3ByZXNldElkXSB8fCBudWxsO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGRlZmF1bHQgd29ya3dlZWsgcHJlc2V0XG4gICAgICovXG4gICAgYXN5bmMgZ2V0RGVmYXVsdFdvcmt3ZWVrUHJlc2V0KCkge1xuICAgICAgICBjb25zdCBzZXR0aW5ncyA9IGF3YWl0IHRoaXMuZ2V0V29ya3dlZWtTZXR0aW5ncygpO1xuICAgICAgICBpZiAoIXNldHRpbmdzKVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIHJldHVybiBzZXR0aW5ncy5wcmVzZXRzW3NldHRpbmdzLmRlZmF1bHRQcmVzZXRdIHx8IG51bGw7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgYXZhaWxhYmxlIHdvcmt3ZWVrIHByZXNldHNcbiAgICAgKi9cbiAgICBhc3luYyBnZXRXb3Jrd2Vla1ByZXNldHMoKSB7XG4gICAgICAgIGNvbnN0IHNldHRpbmdzID0gYXdhaXQgdGhpcy5nZXRXb3Jrd2Vla1NldHRpbmdzKCk7XG4gICAgICAgIGlmICghc2V0dGluZ3MpXG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIHJldHVybiBPYmplY3QudmFsdWVzKHNldHRpbmdzLnByZXNldHMpO1xuICAgIH1cbn1cbiIsICJleHBvcnQgY2xhc3MgVmlld0NvbmZpZ1N0b3JlIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5zdG9yZU5hbWUgPSBWaWV3Q29uZmlnU3RvcmUuU1RPUkVfTkFNRTtcbiAgICB9XG4gICAgY3JlYXRlKGRiKSB7XG4gICAgICAgIGRiLmNyZWF0ZU9iamVjdFN0b3JlKFZpZXdDb25maWdTdG9yZS5TVE9SRV9OQU1FLCB7IGtleVBhdGg6ICdpZCcgfSk7XG4gICAgfVxufVxuVmlld0NvbmZpZ1N0b3JlLlNUT1JFX05BTUUgPSAndmlld2NvbmZpZ3MnO1xuIiwgImltcG9ydCB7IFZpZXdDb25maWdTdG9yZSB9IGZyb20gJy4vVmlld0NvbmZpZ1N0b3JlJztcbmltcG9ydCB7IEJhc2VFbnRpdHlTZXJ2aWNlIH0gZnJvbSAnLi4vQmFzZUVudGl0eVNlcnZpY2UnO1xuZXhwb3J0IGNsYXNzIFZpZXdDb25maWdTZXJ2aWNlIGV4dGVuZHMgQmFzZUVudGl0eVNlcnZpY2Uge1xuICAgIGNvbnN0cnVjdG9yKGNvbnRleHQsIGV2ZW50QnVzKSB7XG4gICAgICAgIHN1cGVyKGNvbnRleHQsIGV2ZW50QnVzKTtcbiAgICAgICAgdGhpcy5zdG9yZU5hbWUgPSBWaWV3Q29uZmlnU3RvcmUuU1RPUkVfTkFNRTtcbiAgICAgICAgdGhpcy5lbnRpdHlUeXBlID0gJ1ZpZXdDb25maWcnO1xuICAgIH1cbiAgICBhc3luYyBnZXRCeUlkKGlkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldChpZCk7XG4gICAgfVxufVxuIiwgIi8qKlxuICogQXVkaXRTdG9yZSAtIEluZGV4ZWREQiBzdG9yZSBjb25maWd1cmF0aW9uIGZvciBhdWRpdCBlbnRyaWVzXG4gKlxuICogU3RvcmVzIGFsbCBlbnRpdHkgY2hhbmdlcyBmb3I6XG4gKiAtIENvbXBsaWFuY2UgYW5kIGF1ZGl0IHRyYWlsXG4gKiAtIFN5bmMgdHJhY2tpbmcgd2l0aCBiYWNrZW5kXG4gKiAtIENoYW5nZSBoaXN0b3J5XG4gKlxuICogSW5kZXhlczpcbiAqIC0gc3luY1N0YXR1czogRm9yIGZpbmRpbmcgcGVuZGluZyBlbnRyaWVzIHRvIHN5bmNcbiAqIC0gc3luY2VkOiBCb29sZWFuIGZsYWcgZm9yIHF1aWNrIHN5bmMgcXVlcmllc1xuICogLSBlbnRpdHlJZDogRm9yIGdldHRpbmcgYWxsIGF1ZGl0cyBmb3IgYSBzcGVjaWZpYyBlbnRpdHlcbiAqIC0gdGltZXN0YW1wOiBGb3IgY2hyb25vbG9naWNhbCBxdWVyaWVzXG4gKi9cbmV4cG9ydCBjbGFzcyBBdWRpdFN0b3JlIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5zdG9yZU5hbWUgPSAnYXVkaXQnO1xuICAgIH1cbiAgICBjcmVhdGUoZGIpIHtcbiAgICAgICAgY29uc3Qgc3RvcmUgPSBkYi5jcmVhdGVPYmplY3RTdG9yZSh0aGlzLnN0b3JlTmFtZSwgeyBrZXlQYXRoOiAnaWQnIH0pO1xuICAgICAgICBzdG9yZS5jcmVhdGVJbmRleCgnc3luY1N0YXR1cycsICdzeW5jU3RhdHVzJywgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgICAgICBzdG9yZS5jcmVhdGVJbmRleCgnc3luY2VkJywgJ3N5bmNlZCcsIHsgdW5pcXVlOiBmYWxzZSB9KTtcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ2VudGl0eUlkJywgJ2VudGl0eUlkJywgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgICAgICBzdG9yZS5jcmVhdGVJbmRleCgndGltZXN0YW1wJywgJ3RpbWVzdGFtcCcsIHsgdW5pcXVlOiBmYWxzZSB9KTtcbiAgICB9XG59XG4iLCAiaW1wb3J0IHsgQmFzZUVudGl0eVNlcnZpY2UgfSBmcm9tICcuLi9CYXNlRW50aXR5U2VydmljZSc7XG5pbXBvcnQgeyBDb3JlRXZlbnRzIH0gZnJvbSAnLi4vLi4vY29uc3RhbnRzL0NvcmVFdmVudHMnO1xuLyoqXG4gKiBBdWRpdFNlcnZpY2UgLSBFbnRpdHkgc2VydmljZSBmb3IgYXVkaXQgZW50cmllc1xuICpcbiAqIFJFU1BPTlNJQklMSVRJRVM6XG4gKiAtIFN0b3JlIGF1ZGl0IGVudHJpZXMgaW4gSW5kZXhlZERCXG4gKiAtIExpc3RlbiBmb3IgRU5USVRZX1NBVkVEL0VOVElUWV9ERUxFVEVEIGV2ZW50c1xuICogLSBDcmVhdGUgYXVkaXQgZW50cmllcyBmb3IgYWxsIGVudGl0eSBjaGFuZ2VzXG4gKiAtIEVtaXQgQVVESVRfTE9HR0VEIGFmdGVyIHNhdmluZyAoZm9yIFN5bmNNYW5hZ2VyIHRvIGxpc3RlbilcbiAqXG4gKiBPVkVSUklERSBQQVRURVJOOlxuICogLSBPdmVycmlkZXMgc2F2ZSgpIHRvIE5PVCBlbWl0IGV2ZW50cyAocHJldmVudHMgaW5maW5pdGUgbG9vcHMpXG4gKiAtIEF1ZGl0U2VydmljZSBzYXZlcyBhdWRpdCBlbnRyaWVzIHdpdGhvdXQgdHJpZ2dlcmluZyBtb3JlIGF1ZGl0c1xuICpcbiAqIEVWRU5UIENIQUlOOlxuICogRW50aXR5IGNoYW5nZSBcdTIxOTIgRU5USVRZX1NBVkVEL0RFTEVURUQgXHUyMTkyIEF1ZGl0U2VydmljZSBcdTIxOTIgQVVESVRfTE9HR0VEIFx1MjE5MiBTeW5jTWFuYWdlclxuICovXG5leHBvcnQgY2xhc3MgQXVkaXRTZXJ2aWNlIGV4dGVuZHMgQmFzZUVudGl0eVNlcnZpY2Uge1xuICAgIGNvbnN0cnVjdG9yKGNvbnRleHQsIGV2ZW50QnVzKSB7XG4gICAgICAgIHN1cGVyKGNvbnRleHQsIGV2ZW50QnVzKTtcbiAgICAgICAgdGhpcy5zdG9yZU5hbWUgPSAnYXVkaXQnO1xuICAgICAgICB0aGlzLmVudGl0eVR5cGUgPSAnQXVkaXQnO1xuICAgICAgICB0aGlzLnNldHVwRXZlbnRMaXN0ZW5lcnMoKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2V0dXAgbGlzdGVuZXJzIGZvciBFTlRJVFlfU0FWRUQgYW5kIEVOVElUWV9ERUxFVEVEIGV2ZW50c1xuICAgICAqL1xuICAgIHNldHVwRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgICAgIC8vIExpc3RlbiBmb3IgZW50aXR5IHNhdmVzIChjcmVhdGUvdXBkYXRlKVxuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENvcmVFdmVudHMuRU5USVRZX1NBVkVELCAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGRldGFpbCA9IGV2ZW50LmRldGFpbDtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlRW50aXR5U2F2ZWQoZGV0YWlsKTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIExpc3RlbiBmb3IgZW50aXR5IGRlbGV0ZXNcbiAgICAgICAgdGhpcy5ldmVudEJ1cy5vbihDb3JlRXZlbnRzLkVOVElUWV9ERUxFVEVELCAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGRldGFpbCA9IGV2ZW50LmRldGFpbDtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlRW50aXR5RGVsZXRlZChkZXRhaWwpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSGFuZGxlIEVOVElUWV9TQVZFRCBldmVudCAtIGNyZWF0ZSBhdWRpdCBlbnRyeVxuICAgICAqL1xuICAgIGFzeW5jIGhhbmRsZUVudGl0eVNhdmVkKHBheWxvYWQpIHtcbiAgICAgICAgLy8gRG9uJ3QgYXVkaXQgYXVkaXQgZW50cmllcyAocHJldmVudCBpbmZpbml0ZSBsb29wcylcbiAgICAgICAgaWYgKHBheWxvYWQuZW50aXR5VHlwZSA9PT0gJ0F1ZGl0JylcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY29uc3QgYXVkaXRFbnRyeSA9IHtcbiAgICAgICAgICAgIGlkOiBjcnlwdG8ucmFuZG9tVVVJRCgpLFxuICAgICAgICAgICAgZW50aXR5VHlwZTogcGF5bG9hZC5lbnRpdHlUeXBlLFxuICAgICAgICAgICAgZW50aXR5SWQ6IHBheWxvYWQuZW50aXR5SWQsXG4gICAgICAgICAgICBvcGVyYXRpb246IHBheWxvYWQub3BlcmF0aW9uLFxuICAgICAgICAgICAgdXNlcklkOiBBdWRpdFNlcnZpY2UuREVGQVVMVF9VU0VSX0lELFxuICAgICAgICAgICAgdGltZXN0YW1wOiBwYXlsb2FkLnRpbWVzdGFtcCxcbiAgICAgICAgICAgIGNoYW5nZXM6IHBheWxvYWQuY2hhbmdlcyxcbiAgICAgICAgICAgIHN5bmNlZDogZmFsc2UsXG4gICAgICAgICAgICBzeW5jU3RhdHVzOiAncGVuZGluZydcbiAgICAgICAgfTtcbiAgICAgICAgYXdhaXQgdGhpcy5zYXZlKGF1ZGl0RW50cnkpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgRU5USVRZX0RFTEVURUQgZXZlbnQgLSBjcmVhdGUgYXVkaXQgZW50cnlcbiAgICAgKi9cbiAgICBhc3luYyBoYW5kbGVFbnRpdHlEZWxldGVkKHBheWxvYWQpIHtcbiAgICAgICAgLy8gRG9uJ3QgYXVkaXQgYXVkaXQgZW50cmllcyAocHJldmVudCBpbmZpbml0ZSBsb29wcylcbiAgICAgICAgaWYgKHBheWxvYWQuZW50aXR5VHlwZSA9PT0gJ0F1ZGl0JylcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY29uc3QgYXVkaXRFbnRyeSA9IHtcbiAgICAgICAgICAgIGlkOiBjcnlwdG8ucmFuZG9tVVVJRCgpLFxuICAgICAgICAgICAgZW50aXR5VHlwZTogcGF5bG9hZC5lbnRpdHlUeXBlLFxuICAgICAgICAgICAgZW50aXR5SWQ6IHBheWxvYWQuZW50aXR5SWQsXG4gICAgICAgICAgICBvcGVyYXRpb246ICdkZWxldGUnLFxuICAgICAgICAgICAgdXNlcklkOiBBdWRpdFNlcnZpY2UuREVGQVVMVF9VU0VSX0lELFxuICAgICAgICAgICAgdGltZXN0YW1wOiBwYXlsb2FkLnRpbWVzdGFtcCxcbiAgICAgICAgICAgIGNoYW5nZXM6IHsgaWQ6IHBheWxvYWQuZW50aXR5SWQgfSwgLy8gRm9yIGRlbGV0ZSwganVzdCBzdG9yZSB0aGUgSURcbiAgICAgICAgICAgIHN5bmNlZDogZmFsc2UsXG4gICAgICAgICAgICBzeW5jU3RhdHVzOiAncGVuZGluZydcbiAgICAgICAgfTtcbiAgICAgICAgYXdhaXQgdGhpcy5zYXZlKGF1ZGl0RW50cnkpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBPdmVycmlkZSBzYXZlIHRvIE5PVCB0cmlnZ2VyIEVOVElUWV9TQVZFRCBldmVudFxuICAgICAqIEluc3RlYWQsIGVtaXRzIEFVRElUX0xPR0dFRCBmb3IgU3luY01hbmFnZXIgdG8gbGlzdGVuXG4gICAgICpcbiAgICAgKiBUaGlzIHByZXZlbnRzIGluZmluaXRlIGxvb3BzOlxuICAgICAqIC0gQmFzZUVudGl0eVNlcnZpY2Uuc2F2ZSgpIGVtaXRzIEVOVElUWV9TQVZFRFxuICAgICAqIC0gQXVkaXRTZXJ2aWNlIGxpc3RlbnMgdG8gRU5USVRZX1NBVkVEIGFuZCBjcmVhdGVzIGF1ZGl0XG4gICAgICogLSBJZiBBdWRpdFNlcnZpY2Uuc2F2ZSgpIGFsc28gZW1pdHRlZCBFTlRJVFlfU0FWRUQsIGl0IHdvdWxkIGxvb3BcbiAgICAgKi9cbiAgICBhc3luYyBzYXZlKGVudGl0eSkge1xuICAgICAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemUoZW50aXR5KTtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gdGhpcy5kYi50cmFuc2FjdGlvbihbdGhpcy5zdG9yZU5hbWVdLCAncmVhZHdyaXRlJyk7XG4gICAgICAgICAgICBjb25zdCBzdG9yZSA9IHRyYW5zYWN0aW9uLm9iamVjdFN0b3JlKHRoaXMuc3RvcmVOYW1lKTtcbiAgICAgICAgICAgIGNvbnN0IHJlcXVlc3QgPSBzdG9yZS5wdXQoc2VyaWFsaXplZCk7XG4gICAgICAgICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBFbWl0IEFVRElUX0xPR0dFRCBpbnN0ZWFkIG9mIEVOVElUWV9TQVZFRFxuICAgICAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgICAgICAgICAgICAgIGF1ZGl0SWQ6IGVudGl0eS5pZCxcbiAgICAgICAgICAgICAgICAgICAgZW50aXR5VHlwZTogZW50aXR5LmVudGl0eVR5cGUsXG4gICAgICAgICAgICAgICAgICAgIGVudGl0eUlkOiBlbnRpdHkuZW50aXR5SWQsXG4gICAgICAgICAgICAgICAgICAgIG9wZXJhdGlvbjogZW50aXR5Lm9wZXJhdGlvbixcbiAgICAgICAgICAgICAgICAgICAgdGltZXN0YW1wOiBlbnRpdHkudGltZXN0YW1wXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ29yZUV2ZW50cy5BVURJVF9MT0dHRUQsIHBheWxvYWQpO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXF1ZXN0Lm9uZXJyb3IgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgRmFpbGVkIHRvIHNhdmUgYXVkaXQgZW50cnkgJHtlbnRpdHkuaWR9OiAke3JlcXVlc3QuZXJyb3J9YCkpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIE92ZXJyaWRlIGRlbGV0ZSB0byBOT1QgdHJpZ2dlciBFTlRJVFlfREVMRVRFRCBldmVudFxuICAgICAqIEF1ZGl0IGVudHJpZXMgc2hvdWxkIG5ldmVyIGJlIGRlbGV0ZWQgKGNvbXBsaWFuY2UgcmVxdWlyZW1lbnQpXG4gICAgICovXG4gICAgYXN5bmMgZGVsZXRlKF9pZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0F1ZGl0IGVudHJpZXMgY2Fubm90IGJlIGRlbGV0ZWQgKGNvbXBsaWFuY2UgcmVxdWlyZW1lbnQpJyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBwZW5kaW5nIGF1ZGl0IGVudHJpZXMgKGZvciBzeW5jKVxuICAgICAqL1xuICAgIGFzeW5jIGdldFBlbmRpbmdBdWRpdHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEJ5U3luY1N0YXR1cygncGVuZGluZycpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgYXVkaXQgZW50cmllcyBmb3IgYSBzcGVjaWZpYyBlbnRpdHlcbiAgICAgKi9cbiAgICBhc3luYyBnZXRCeUVudGl0eUlkKGVudGl0eUlkKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IHRoaXMuZGIudHJhbnNhY3Rpb24oW3RoaXMuc3RvcmVOYW1lXSwgJ3JlYWRvbmx5Jyk7XG4gICAgICAgICAgICBjb25zdCBzdG9yZSA9IHRyYW5zYWN0aW9uLm9iamVjdFN0b3JlKHRoaXMuc3RvcmVOYW1lKTtcbiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gc3RvcmUuaW5kZXgoJ2VudGl0eUlkJyk7XG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gaW5kZXguZ2V0QWxsKGVudGl0eUlkKTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25zdWNjZXNzID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGVudHJpZXMgPSByZXF1ZXN0LnJlc3VsdDtcbiAgICAgICAgICAgICAgICByZXNvbHZlKGVudHJpZXMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gZ2V0IGF1ZGl0IGVudHJpZXMgZm9yIGVudGl0eSAke2VudGl0eUlkfTogJHtyZXF1ZXN0LmVycm9yfWApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cbn1cbi8vIEhhcmRjb2RlZCB1c2VySWQgZm9yIG5vdyAtIHdpbGwgY29tZSBmcm9tIHNlc3Npb24gbGF0ZXJcbkF1ZGl0U2VydmljZS5ERUZBVUxUX1VTRVJfSUQgPSAnMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAxJztcbiIsICIvKipcbiAqIE1vY2tFdmVudFJlcG9zaXRvcnkgLSBMb2FkcyBldmVudCBkYXRhIGZyb20gbG9jYWwgSlNPTiBmaWxlXG4gKlxuICogVXNlZCBmb3IgZGV2ZWxvcG1lbnQgYW5kIHRlc3RpbmcuIE9ubHkgZmV0Y2hBbGwoKSBpcyBpbXBsZW1lbnRlZC5cbiAqL1xuZXhwb3J0IGNsYXNzIE1vY2tFdmVudFJlcG9zaXRvcnkge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmVudGl0eVR5cGUgPSAnRXZlbnQnO1xuICAgICAgICB0aGlzLmRhdGFVcmwgPSAnZGF0YS9tb2NrLWV2ZW50cy5qc29uJztcbiAgICB9XG4gICAgLyoqXG4gICAgICogRmV0Y2ggYWxsIGV2ZW50cyBmcm9tIG1vY2sgSlNPTiBmaWxlXG4gICAgICovXG4gICAgYXN5bmMgZmV0Y2hBbGwoKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHRoaXMuZGF0YVVybCk7XG4gICAgICAgICAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gbG9hZCBtb2NrIGV2ZW50czogJHtyZXNwb25zZS5zdGF0dXN9ICR7cmVzcG9uc2Uuc3RhdHVzVGV4dH1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJhd0RhdGEgPSBhd2FpdCByZXNwb25zZS5qc29uKCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wcm9jZXNzQ2FsZW5kYXJEYXRhKHJhd0RhdGEpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGxvYWQgZXZlbnQgZGF0YTonLCBlcnJvcik7XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBhc3luYyBzZW5kQ3JlYXRlKF9ldmVudCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vY2tFdmVudFJlcG9zaXRvcnkgZG9lcyBub3Qgc3VwcG9ydCBzZW5kQ3JlYXRlLiBNb2NrIGRhdGEgaXMgcmVhZC1vbmx5LicpO1xuICAgIH1cbiAgICBhc3luYyBzZW5kVXBkYXRlKF9pZCwgX3VwZGF0ZXMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2NrRXZlbnRSZXBvc2l0b3J5IGRvZXMgbm90IHN1cHBvcnQgc2VuZFVwZGF0ZS4gTW9jayBkYXRhIGlzIHJlYWQtb25seS4nKTtcbiAgICB9XG4gICAgYXN5bmMgc2VuZERlbGV0ZShfaWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2NrRXZlbnRSZXBvc2l0b3J5IGRvZXMgbm90IHN1cHBvcnQgc2VuZERlbGV0ZS4gTW9jayBkYXRhIGlzIHJlYWQtb25seS4nKTtcbiAgICB9XG4gICAgcHJvY2Vzc0NhbGVuZGFyRGF0YShkYXRhKSB7XG4gICAgICAgIHJldHVybiBkYXRhLm1hcCgoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIC8vIFZhbGlkYXRlIGN1c3RvbWVyIGV2ZW50IGNvbnN0cmFpbnRzXG4gICAgICAgICAgICBpZiAoZXZlbnQudHlwZSA9PT0gJ2N1c3RvbWVyJykge1xuICAgICAgICAgICAgICAgIGlmICghZXZlbnQuYm9va2luZ0lkKVxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYEN1c3RvbWVyIGV2ZW50ICR7ZXZlbnQuaWR9IG1pc3NpbmcgYm9va2luZ0lkYCk7XG4gICAgICAgICAgICAgICAgaWYgKCFldmVudC5yZXNvdXJjZUlkKVxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYEN1c3RvbWVyIGV2ZW50ICR7ZXZlbnQuaWR9IG1pc3NpbmcgcmVzb3VyY2VJZGApO1xuICAgICAgICAgICAgICAgIGlmICghZXZlbnQuY3VzdG9tZXJJZClcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBDdXN0b21lciBldmVudCAke2V2ZW50LmlkfSBtaXNzaW5nIGN1c3RvbWVySWRgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgaWQ6IGV2ZW50LmlkLFxuICAgICAgICAgICAgICAgIHRpdGxlOiBldmVudC50aXRsZSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogZXZlbnQuZGVzY3JpcHRpb24sXG4gICAgICAgICAgICAgICAgc3RhcnQ6IG5ldyBEYXRlKGV2ZW50LnN0YXJ0KSxcbiAgICAgICAgICAgICAgICBlbmQ6IG5ldyBEYXRlKGV2ZW50LmVuZCksXG4gICAgICAgICAgICAgICAgdHlwZTogZXZlbnQudHlwZSxcbiAgICAgICAgICAgICAgICBhbGxEYXk6IGV2ZW50LmFsbERheSB8fCBmYWxzZSxcbiAgICAgICAgICAgICAgICBib29raW5nSWQ6IGV2ZW50LmJvb2tpbmdJZCxcbiAgICAgICAgICAgICAgICByZXNvdXJjZUlkOiBldmVudC5yZXNvdXJjZUlkLFxuICAgICAgICAgICAgICAgIGN1c3RvbWVySWQ6IGV2ZW50LmN1c3RvbWVySWQsXG4gICAgICAgICAgICAgICAgcmVjdXJyaW5nSWQ6IGV2ZW50LnJlY3VycmluZ0lkLFxuICAgICAgICAgICAgICAgIG1ldGFkYXRhOiBldmVudC5tZXRhZGF0YSxcbiAgICAgICAgICAgICAgICBzeW5jU3RhdHVzOiAnc3luY2VkJ1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfVxufVxuIiwgIi8qKlxuICogTW9ja1Jlc291cmNlUmVwb3NpdG9yeSAtIExvYWRzIHJlc291cmNlIGRhdGEgZnJvbSBsb2NhbCBKU09OIGZpbGVcbiAqL1xuZXhwb3J0IGNsYXNzIE1vY2tSZXNvdXJjZVJlcG9zaXRvcnkge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmVudGl0eVR5cGUgPSAnUmVzb3VyY2UnO1xuICAgICAgICB0aGlzLmRhdGFVcmwgPSAnZGF0YS9tb2NrLXJlc291cmNlcy5qc29uJztcbiAgICB9XG4gICAgYXN5bmMgZmV0Y2hBbGwoKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHRoaXMuZGF0YVVybCk7XG4gICAgICAgICAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gbG9hZCBtb2NrIHJlc291cmNlczogJHtyZXNwb25zZS5zdGF0dXN9ICR7cmVzcG9uc2Uuc3RhdHVzVGV4dH1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJhd0RhdGEgPSBhd2FpdCByZXNwb25zZS5qc29uKCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wcm9jZXNzUmVzb3VyY2VEYXRhKHJhd0RhdGEpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGxvYWQgcmVzb3VyY2UgZGF0YTonLCBlcnJvcik7XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBhc3luYyBzZW5kQ3JlYXRlKF9yZXNvdXJjZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vY2tSZXNvdXJjZVJlcG9zaXRvcnkgZG9lcyBub3Qgc3VwcG9ydCBzZW5kQ3JlYXRlLiBNb2NrIGRhdGEgaXMgcmVhZC1vbmx5LicpO1xuICAgIH1cbiAgICBhc3luYyBzZW5kVXBkYXRlKF9pZCwgX3VwZGF0ZXMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2NrUmVzb3VyY2VSZXBvc2l0b3J5IGRvZXMgbm90IHN1cHBvcnQgc2VuZFVwZGF0ZS4gTW9jayBkYXRhIGlzIHJlYWQtb25seS4nKTtcbiAgICB9XG4gICAgYXN5bmMgc2VuZERlbGV0ZShfaWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2NrUmVzb3VyY2VSZXBvc2l0b3J5IGRvZXMgbm90IHN1cHBvcnQgc2VuZERlbGV0ZS4gTW9jayBkYXRhIGlzIHJlYWQtb25seS4nKTtcbiAgICB9XG4gICAgcHJvY2Vzc1Jlc291cmNlRGF0YShkYXRhKSB7XG4gICAgICAgIHJldHVybiBkYXRhLm1hcCgocmVzb3VyY2UpID0+ICh7XG4gICAgICAgICAgICBpZDogcmVzb3VyY2UuaWQsXG4gICAgICAgICAgICBuYW1lOiByZXNvdXJjZS5uYW1lLFxuICAgICAgICAgICAgZGlzcGxheU5hbWU6IHJlc291cmNlLmRpc3BsYXlOYW1lLFxuICAgICAgICAgICAgdHlwZTogcmVzb3VyY2UudHlwZSxcbiAgICAgICAgICAgIGF2YXRhclVybDogcmVzb3VyY2UuYXZhdGFyVXJsLFxuICAgICAgICAgICAgY29sb3I6IHJlc291cmNlLmNvbG9yLFxuICAgICAgICAgICAgaXNBY3RpdmU6IHJlc291cmNlLmlzQWN0aXZlLFxuICAgICAgICAgICAgZGVmYXVsdFNjaGVkdWxlOiByZXNvdXJjZS5kZWZhdWx0U2NoZWR1bGUsXG4gICAgICAgICAgICBtZXRhZGF0YTogcmVzb3VyY2UubWV0YWRhdGEsXG4gICAgICAgICAgICBzeW5jU3RhdHVzOiAnc3luY2VkJ1xuICAgICAgICB9KSk7XG4gICAgfVxufVxuIiwgIi8qKlxuICogTW9ja0Jvb2tpbmdSZXBvc2l0b3J5IC0gTG9hZHMgYm9va2luZyBkYXRhIGZyb20gbG9jYWwgSlNPTiBmaWxlXG4gKi9cbmV4cG9ydCBjbGFzcyBNb2NrQm9va2luZ1JlcG9zaXRvcnkge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmVudGl0eVR5cGUgPSAnQm9va2luZyc7XG4gICAgICAgIHRoaXMuZGF0YVVybCA9ICdkYXRhL21vY2stYm9va2luZ3MuanNvbic7XG4gICAgfVxuICAgIGFzeW5jIGZldGNoQWxsKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh0aGlzLmRhdGFVcmwpO1xuICAgICAgICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGxvYWQgbW9jayBib29raW5nczogJHtyZXNwb25zZS5zdGF0dXN9ICR7cmVzcG9uc2Uuc3RhdHVzVGV4dH1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJhd0RhdGEgPSBhd2FpdCByZXNwb25zZS5qc29uKCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wcm9jZXNzQm9va2luZ0RhdGEocmF3RGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgdG8gbG9hZCBib29raW5nIGRhdGE6JywgZXJyb3IpO1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICB9XG4gICAgYXN5bmMgc2VuZENyZWF0ZShfYm9va2luZykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vY2tCb29raW5nUmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmRDcmVhdGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxuICAgIGFzeW5jIHNlbmRVcGRhdGUoX2lkLCBfdXBkYXRlcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vY2tCb29raW5nUmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmRVcGRhdGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxuICAgIGFzeW5jIHNlbmREZWxldGUoX2lkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9ja0Jvb2tpbmdSZXBvc2l0b3J5IGRvZXMgbm90IHN1cHBvcnQgc2VuZERlbGV0ZS4gTW9jayBkYXRhIGlzIHJlYWQtb25seS4nKTtcbiAgICB9XG4gICAgcHJvY2Vzc0Jvb2tpbmdEYXRhKGRhdGEpIHtcbiAgICAgICAgcmV0dXJuIGRhdGEubWFwKChib29raW5nKSA9PiAoe1xuICAgICAgICAgICAgaWQ6IGJvb2tpbmcuaWQsXG4gICAgICAgICAgICBjdXN0b21lcklkOiBib29raW5nLmN1c3RvbWVySWQsXG4gICAgICAgICAgICBzdGF0dXM6IGJvb2tpbmcuc3RhdHVzLFxuICAgICAgICAgICAgY3JlYXRlZEF0OiBuZXcgRGF0ZShib29raW5nLmNyZWF0ZWRBdCksXG4gICAgICAgICAgICBzZXJ2aWNlczogYm9va2luZy5zZXJ2aWNlcyxcbiAgICAgICAgICAgIHRvdGFsUHJpY2U6IGJvb2tpbmcudG90YWxQcmljZSxcbiAgICAgICAgICAgIHRhZ3M6IGJvb2tpbmcudGFncyxcbiAgICAgICAgICAgIG5vdGVzOiBib29raW5nLm5vdGVzLFxuICAgICAgICAgICAgc3luY1N0YXR1czogJ3N5bmNlZCdcbiAgICAgICAgfSkpO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIE1vY2tDdXN0b21lclJlcG9zaXRvcnkgLSBMb2FkcyBjdXN0b21lciBkYXRhIGZyb20gbG9jYWwgSlNPTiBmaWxlXG4gKi9cbmV4cG9ydCBjbGFzcyBNb2NrQ3VzdG9tZXJSZXBvc2l0b3J5IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5lbnRpdHlUeXBlID0gJ0N1c3RvbWVyJztcbiAgICAgICAgdGhpcy5kYXRhVXJsID0gJ2RhdGEvbW9jay1jdXN0b21lcnMuanNvbic7XG4gICAgfVxuICAgIGFzeW5jIGZldGNoQWxsKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh0aGlzLmRhdGFVcmwpO1xuICAgICAgICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGxvYWQgbW9jayBjdXN0b21lcnM6ICR7cmVzcG9uc2Uuc3RhdHVzfSAke3Jlc3BvbnNlLnN0YXR1c1RleHR9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByYXdEYXRhID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJvY2Vzc0N1c3RvbWVyRGF0YShyYXdEYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCB0byBsb2FkIGN1c3RvbWVyIGRhdGE6JywgZXJyb3IpO1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICB9XG4gICAgYXN5bmMgc2VuZENyZWF0ZShfY3VzdG9tZXIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2NrQ3VzdG9tZXJSZXBvc2l0b3J5IGRvZXMgbm90IHN1cHBvcnQgc2VuZENyZWF0ZS4gTW9jayBkYXRhIGlzIHJlYWQtb25seS4nKTtcbiAgICB9XG4gICAgYXN5bmMgc2VuZFVwZGF0ZShfaWQsIF91cGRhdGVzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9ja0N1c3RvbWVyUmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmRVcGRhdGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxuICAgIGFzeW5jIHNlbmREZWxldGUoX2lkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9ja0N1c3RvbWVyUmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmREZWxldGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxuICAgIHByb2Nlc3NDdXN0b21lckRhdGEoZGF0YSkge1xuICAgICAgICByZXR1cm4gZGF0YS5tYXAoKGN1c3RvbWVyKSA9PiAoe1xuICAgICAgICAgICAgaWQ6IGN1c3RvbWVyLmlkLFxuICAgICAgICAgICAgbmFtZTogY3VzdG9tZXIubmFtZSxcbiAgICAgICAgICAgIHBob25lOiBjdXN0b21lci5waG9uZSxcbiAgICAgICAgICAgIGVtYWlsOiBjdXN0b21lci5lbWFpbCxcbiAgICAgICAgICAgIG1ldGFkYXRhOiBjdXN0b21lci5tZXRhZGF0YSxcbiAgICAgICAgICAgIHN5bmNTdGF0dXM6ICdzeW5jZWQnXG4gICAgICAgIH0pKTtcbiAgICB9XG59XG4iLCAiLyoqXG4gKiBNb2NrQXVkaXRSZXBvc2l0b3J5IC0gTW9jayBBUEkgcmVwb3NpdG9yeSBmb3IgYXVkaXQgZW50cmllc1xuICpcbiAqIEluIHByb2R1Y3Rpb24sIHRoaXMgd291bGQgc2VuZCBhdWRpdCBlbnRyaWVzIHRvIHRoZSBiYWNrZW5kLlxuICogRm9yIGRldmVsb3BtZW50L3Rlc3RpbmcsIGl0IGp1c3QgbG9ncyB0aGUgb3BlcmF0aW9ucy5cbiAqL1xuZXhwb3J0IGNsYXNzIE1vY2tBdWRpdFJlcG9zaXRvcnkge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmVudGl0eVR5cGUgPSAnQXVkaXQnO1xuICAgIH1cbiAgICBhc3luYyBzZW5kQ3JlYXRlKGVudGl0eSkge1xuICAgICAgICAvLyBTaW11bGF0ZSBBUEkgY2FsbCBkZWxheVxuICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgMTAwKSk7XG4gICAgICAgIGNvbnNvbGUubG9nKCdNb2NrQXVkaXRSZXBvc2l0b3J5OiBBdWRpdCBlbnRyeSBzeW5jZWQgdG8gYmFja2VuZDonLCB7XG4gICAgICAgICAgICBpZDogZW50aXR5LmlkLFxuICAgICAgICAgICAgZW50aXR5VHlwZTogZW50aXR5LmVudGl0eVR5cGUsXG4gICAgICAgICAgICBlbnRpdHlJZDogZW50aXR5LmVudGl0eUlkLFxuICAgICAgICAgICAgb3BlcmF0aW9uOiBlbnRpdHkub3BlcmF0aW9uLFxuICAgICAgICAgICAgdGltZXN0YW1wOiBuZXcgRGF0ZShlbnRpdHkudGltZXN0YW1wKS50b0lTT1N0cmluZygpXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gZW50aXR5O1xuICAgIH1cbiAgICBhc3luYyBzZW5kVXBkYXRlKF9pZCwgX2VudGl0eSkge1xuICAgICAgICAvLyBBdWRpdCBlbnRyaWVzIGFyZSBpbW11dGFibGUgLSB1cGRhdGVzIHNob3VsZCBub3QgaGFwcGVuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQXVkaXQgZW50cmllcyBjYW5ub3QgYmUgdXBkYXRlZCcpO1xuICAgIH1cbiAgICBhc3luYyBzZW5kRGVsZXRlKF9pZCkge1xuICAgICAgICAvLyBBdWRpdCBlbnRyaWVzIHNob3VsZCBuZXZlciBiZSBkZWxldGVkXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQXVkaXQgZW50cmllcyBjYW5ub3QgYmUgZGVsZXRlZCcpO1xuICAgIH1cbiAgICBhc3luYyBmZXRjaEFsbCgpIHtcbiAgICAgICAgLy8gRm9yIG5vdywgcmV0dXJuIGVtcHR5IGFycmF5IC0gYXVkaXQgZW50cmllcyBhcmUgbG9jYWwtZmlyc3RcbiAgICAgICAgLy8gSW4gcHJvZHVjdGlvbiwgdGhpcyBjb3VsZCBmZXRjaCBhdWRpdCBoaXN0b3J5IGZyb20gYmFja2VuZFxuICAgICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIGFzeW5jIGZldGNoQnlJZChfaWQpIHtcbiAgICAgICAgLy8gRm9yIG5vdywgcmV0dXJuIG51bGwgLSBhdWRpdCBlbnRyaWVzIGFyZSBsb2NhbC1maXJzdFxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG59XG4iLCAiLyoqXG4gKiBNb2NrVGVhbVJlcG9zaXRvcnkgLSBMb2FkcyB0ZWFtIGRhdGEgZnJvbSBsb2NhbCBKU09OIGZpbGVcbiAqL1xuZXhwb3J0IGNsYXNzIE1vY2tUZWFtUmVwb3NpdG9yeSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuZW50aXR5VHlwZSA9ICdUZWFtJztcbiAgICAgICAgdGhpcy5kYXRhVXJsID0gJ2RhdGEvbW9jay10ZWFtcy5qc29uJztcbiAgICB9XG4gICAgYXN5bmMgZmV0Y2hBbGwoKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHRoaXMuZGF0YVVybCk7XG4gICAgICAgICAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gbG9hZCBtb2NrIHRlYW1zOiAke3Jlc3BvbnNlLnN0YXR1c30gJHtyZXNwb25zZS5zdGF0dXNUZXh0fWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmF3RGF0YSA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnByb2Nlc3NUZWFtRGF0YShyYXdEYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCB0byBsb2FkIHRlYW0gZGF0YTonLCBlcnJvcik7XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBhc3luYyBzZW5kQ3JlYXRlKF90ZWFtKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9ja1RlYW1SZXBvc2l0b3J5IGRvZXMgbm90IHN1cHBvcnQgc2VuZENyZWF0ZS4gTW9jayBkYXRhIGlzIHJlYWQtb25seS4nKTtcbiAgICB9XG4gICAgYXN5bmMgc2VuZFVwZGF0ZShfaWQsIF91cGRhdGVzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9ja1RlYW1SZXBvc2l0b3J5IGRvZXMgbm90IHN1cHBvcnQgc2VuZFVwZGF0ZS4gTW9jayBkYXRhIGlzIHJlYWQtb25seS4nKTtcbiAgICB9XG4gICAgYXN5bmMgc2VuZERlbGV0ZShfaWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2NrVGVhbVJlcG9zaXRvcnkgZG9lcyBub3Qgc3VwcG9ydCBzZW5kRGVsZXRlLiBNb2NrIGRhdGEgaXMgcmVhZC1vbmx5LicpO1xuICAgIH1cbiAgICBwcm9jZXNzVGVhbURhdGEoZGF0YSkge1xuICAgICAgICByZXR1cm4gZGF0YS5tYXAoKHRlYW0pID0+ICh7XG4gICAgICAgICAgICBpZDogdGVhbS5pZCxcbiAgICAgICAgICAgIG5hbWU6IHRlYW0ubmFtZSxcbiAgICAgICAgICAgIHJlc291cmNlSWRzOiB0ZWFtLnJlc291cmNlSWRzLFxuICAgICAgICAgICAgc3luY1N0YXR1czogJ3N5bmNlZCdcbiAgICAgICAgfSkpO1xuICAgIH1cbn1cbiIsICIvKipcbiAqIE1vY2tEZXBhcnRtZW50UmVwb3NpdG9yeSAtIExvYWRzIGRlcGFydG1lbnQgZGF0YSBmcm9tIGxvY2FsIEpTT04gZmlsZVxuICovXG5leHBvcnQgY2xhc3MgTW9ja0RlcGFydG1lbnRSZXBvc2l0b3J5IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5lbnRpdHlUeXBlID0gJ0RlcGFydG1lbnQnO1xuICAgICAgICB0aGlzLmRhdGFVcmwgPSAnZGF0YS9tb2NrLWRlcGFydG1lbnRzLmpzb24nO1xuICAgIH1cbiAgICBhc3luYyBmZXRjaEFsbCgpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godGhpcy5kYXRhVXJsKTtcbiAgICAgICAgICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBsb2FkIG1vY2sgZGVwYXJ0bWVudHM6ICR7cmVzcG9uc2Uuc3RhdHVzfSAke3Jlc3BvbnNlLnN0YXR1c1RleHR9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByYXdEYXRhID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJvY2Vzc0RlcGFydG1lbnREYXRhKHJhd0RhdGEpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGxvYWQgZGVwYXJ0bWVudCBkYXRhOicsIGVycm9yKTtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgfVxuICAgIGFzeW5jIHNlbmRDcmVhdGUoX2RlcGFydG1lbnQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2NrRGVwYXJ0bWVudFJlcG9zaXRvcnkgZG9lcyBub3Qgc3VwcG9ydCBzZW5kQ3JlYXRlLiBNb2NrIGRhdGEgaXMgcmVhZC1vbmx5LicpO1xuICAgIH1cbiAgICBhc3luYyBzZW5kVXBkYXRlKF9pZCwgX3VwZGF0ZXMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2NrRGVwYXJ0bWVudFJlcG9zaXRvcnkgZG9lcyBub3Qgc3VwcG9ydCBzZW5kVXBkYXRlLiBNb2NrIGRhdGEgaXMgcmVhZC1vbmx5LicpO1xuICAgIH1cbiAgICBhc3luYyBzZW5kRGVsZXRlKF9pZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vY2tEZXBhcnRtZW50UmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmREZWxldGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxuICAgIHByb2Nlc3NEZXBhcnRtZW50RGF0YShkYXRhKSB7XG4gICAgICAgIHJldHVybiBkYXRhLm1hcCgoZGVwdCkgPT4gKHtcbiAgICAgICAgICAgIGlkOiBkZXB0LmlkLFxuICAgICAgICAgICAgbmFtZTogZGVwdC5uYW1lLFxuICAgICAgICAgICAgcmVzb3VyY2VJZHM6IGRlcHQucmVzb3VyY2VJZHMsXG4gICAgICAgICAgICBzeW5jU3RhdHVzOiAnc3luY2VkJ1xuICAgICAgICB9KSk7XG4gICAgfVxufVxuIiwgIi8qKlxuICogTW9ja1NldHRpbmdzUmVwb3NpdG9yeSAtIExvYWRzIHRlbmFudCBzZXR0aW5ncyBmcm9tIGxvY2FsIEpTT04gZmlsZVxuICpcbiAqIFNldHRpbmdzIGFyZSBzdG9yZWQgYXMgc2VwYXJhdGUgcmVjb3JkcyBwZXIgc2VjdGlvbiAod29ya3dlZWssIGdyaWQsIGV0Yy4pLlxuICogVGhlIEpTT04gZmlsZSBpcyBhbHJlYWR5IGFuIGFycmF5IG9mIFRlbmFudFNldHRpbmcgcmVjb3Jkcy5cbiAqL1xuZXhwb3J0IGNsYXNzIE1vY2tTZXR0aW5nc1JlcG9zaXRvcnkge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmVudGl0eVR5cGUgPSAnU2V0dGluZ3MnO1xuICAgICAgICB0aGlzLmRhdGFVcmwgPSAnZGF0YS90ZW5hbnQtc2V0dGluZ3MuanNvbic7XG4gICAgfVxuICAgIGFzeW5jIGZldGNoQWxsKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh0aGlzLmRhdGFVcmwpO1xuICAgICAgICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGxvYWQgdGVuYW50IHNldHRpbmdzOiAke3Jlc3BvbnNlLnN0YXR1c30gJHtyZXNwb25zZS5zdGF0dXNUZXh0fWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgc2V0dGluZ3MgPSBhd2FpdCByZXNwb25zZS5qc29uKCk7XG4gICAgICAgICAgICAvLyBFbnN1cmUgc3luY1N0YXR1cyBpcyBzZXQgb24gZWFjaCByZWNvcmRcbiAgICAgICAgICAgIHJldHVybiBzZXR0aW5ncy5tYXAocyA9PiAoe1xuICAgICAgICAgICAgICAgIC4uLnMsXG4gICAgICAgICAgICAgICAgc3luY1N0YXR1czogcy5zeW5jU3RhdHVzIHx8ICdzeW5jZWQnXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgdG8gbG9hZCB0ZW5hbnQgc2V0dGluZ3M6JywgZXJyb3IpO1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICB9XG4gICAgYXN5bmMgc2VuZENyZWF0ZShfc2V0dGluZ3MpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2NrU2V0dGluZ3NSZXBvc2l0b3J5IGRvZXMgbm90IHN1cHBvcnQgc2VuZENyZWF0ZS4gTW9jayBkYXRhIGlzIHJlYWQtb25seS4nKTtcbiAgICB9XG4gICAgYXN5bmMgc2VuZFVwZGF0ZShfaWQsIF91cGRhdGVzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9ja1NldHRpbmdzUmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmRVcGRhdGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxuICAgIGFzeW5jIHNlbmREZWxldGUoX2lkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9ja1NldHRpbmdzUmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmREZWxldGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxufVxuIiwgImV4cG9ydCBjbGFzcyBNb2NrVmlld0NvbmZpZ1JlcG9zaXRvcnkge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmVudGl0eVR5cGUgPSAnVmlld0NvbmZpZyc7XG4gICAgICAgIHRoaXMuZGF0YVVybCA9ICdkYXRhL3ZpZXdjb25maWdzLmpzb24nO1xuICAgIH1cbiAgICBhc3luYyBmZXRjaEFsbCgpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godGhpcy5kYXRhVXJsKTtcbiAgICAgICAgICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBsb2FkIHZpZXdjb25maWdzOiAke3Jlc3BvbnNlLnN0YXR1c30gJHtyZXNwb25zZS5zdGF0dXNUZXh0fWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmF3RGF0YSA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgICAgIC8vIEVuc3VyZSBzeW5jU3RhdHVzIGlzIHNldCBvbiBlYWNoIGNvbmZpZ1xuICAgICAgICAgICAgY29uc3QgY29uZmlncyA9IHJhd0RhdGEubWFwKChjb25maWcpID0+ICh7XG4gICAgICAgICAgICAgICAgLi4uY29uZmlnLFxuICAgICAgICAgICAgICAgIHN5bmNTdGF0dXM6IGNvbmZpZy5zeW5jU3RhdHVzIHx8ICdzeW5jZWQnXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICByZXR1cm4gY29uZmlncztcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCB0byBsb2FkIHZpZXdjb25maWdzOicsIGVycm9yKTtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgfVxuICAgIGFzeW5jIHNlbmRDcmVhdGUoX2NvbmZpZykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vY2tWaWV3Q29uZmlnUmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmRDcmVhdGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxuICAgIGFzeW5jIHNlbmRVcGRhdGUoX2lkLCBfdXBkYXRlcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vY2tWaWV3Q29uZmlnUmVwb3NpdG9yeSBkb2VzIG5vdCBzdXBwb3J0IHNlbmRVcGRhdGUuIE1vY2sgZGF0YSBpcyByZWFkLW9ubHkuJyk7XG4gICAgfVxuICAgIGFzeW5jIHNlbmREZWxldGUoX2lkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9ja1ZpZXdDb25maWdSZXBvc2l0b3J5IGRvZXMgbm90IHN1cHBvcnQgc2VuZERlbGV0ZS4gTW9jayBkYXRhIGlzIHJlYWQtb25seS4nKTtcbiAgICB9XG59XG4iLCAiLyoqXG4gKiBEYXRhU2VlZGVyIC0gT3JjaGVzdHJhdGVzIGluaXRpYWwgZGF0YSBsb2FkaW5nIGZyb20gcmVwb3NpdG9yaWVzIGludG8gSW5kZXhlZERCXG4gKlxuICogQVJDSElURUNUVVJFOlxuICogLSBSZXBvc2l0b3J5IChNb2NrL0FwaSk6IEZldGNoZXMgZGF0YSBmcm9tIHNvdXJjZSAoSlNPTiBmaWxlIG9yIGJhY2tlbmQgQVBJKVxuICogLSBEYXRhU2VlZGVyICh0aGlzIGNsYXNzKTogT3JjaGVzdHJhdGVzIGZldGNoICsgc2F2ZSBvcGVyYXRpb25zXG4gKiAtIFNlcnZpY2UgKEV2ZW50U2VydmljZSwgZXRjLik6IFNhdmVzIGRhdGEgdG8gSW5kZXhlZERCXG4gKlxuICogUE9MWU1PUlBISUMgREVTSUdOOlxuICogLSBVc2VzIGFycmF5cyBvZiBJRW50aXR5U2VydmljZVtdIGFuZCBJQXBpUmVwb3NpdG9yeVtdXG4gKiAtIE1hdGNoZXMgc2VydmljZXMgd2l0aCByZXBvc2l0b3JpZXMgdXNpbmcgZW50aXR5VHlwZSBwcm9wZXJ0eVxuICogLSBPcGVuL0Nsb3NlZCBQcmluY2lwbGU6IEFkZGluZyBuZXcgZW50aXR5IHJlcXVpcmVzIG5vIGNvZGUgY2hhbmdlcyBoZXJlXG4gKi9cbmV4cG9ydCBjbGFzcyBEYXRhU2VlZGVyIHtcbiAgICBjb25zdHJ1Y3RvcihzZXJ2aWNlcywgcmVwb3NpdG9yaWVzKSB7XG4gICAgICAgIHRoaXMuc2VydmljZXMgPSBzZXJ2aWNlcztcbiAgICAgICAgdGhpcy5yZXBvc2l0b3JpZXMgPSByZXBvc2l0b3JpZXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNlZWQgYWxsIGVudGl0eSBzdG9yZXMgaWYgdGhleSBhcmUgZW1wdHlcbiAgICAgKi9cbiAgICBhc3luYyBzZWVkSWZFbXB0eSgpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ1tEYXRhU2VlZGVyXSBDaGVja2luZyBpZiBkYXRhYmFzZSBuZWVkcyBzZWVkaW5nLi4uJyk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHNlcnZpY2Ugb2YgdGhpcy5zZXJ2aWNlcykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlcG9zaXRvcnkgPSB0aGlzLnJlcG9zaXRvcmllcy5maW5kKHJlcG8gPT4gcmVwby5lbnRpdHlUeXBlID09PSBzZXJ2aWNlLmVudGl0eVR5cGUpO1xuICAgICAgICAgICAgICAgIGlmICghcmVwb3NpdG9yeSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYFtEYXRhU2VlZGVyXSBObyByZXBvc2l0b3J5IGZvdW5kIGZvciBlbnRpdHkgdHlwZTogJHtzZXJ2aWNlLmVudGl0eVR5cGV9LCBza2lwcGluZ2ApO1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zZWVkRW50aXR5KHNlcnZpY2UuZW50aXR5VHlwZSwgc2VydmljZSwgcmVwb3NpdG9yeSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnW0RhdGFTZWVkZXJdIFNlZWRpbmcgY29tcGxldGUnKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1tEYXRhU2VlZGVyXSBTZWVkaW5nIGZhaWxlZDonLCBlcnJvcik7XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBhc3luYyBzZWVkRW50aXR5KGVudGl0eVR5cGUsIHNlcnZpY2UsIHJlcG9zaXRvcnkpIHtcbiAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCBzZXJ2aWNlLmdldEFsbCgpO1xuICAgICAgICBpZiAoZXhpc3RpbmcubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29uc29sZS5sb2coYFtEYXRhU2VlZGVyXSAke2VudGl0eVR5cGV9IHN0b3JlIGFscmVhZHkgaGFzICR7ZXhpc3RpbmcubGVuZ3RofSBpdGVtcywgc2tpcHBpbmcgc2VlZGApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUubG9nKGBbRGF0YVNlZWRlcl0gJHtlbnRpdHlUeXBlfSBzdG9yZSBpcyBlbXB0eSwgZmV0Y2hpbmcgZnJvbSByZXBvc2l0b3J5Li4uYCk7XG4gICAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCByZXBvc2l0b3J5LmZldGNoQWxsKCk7XG4gICAgICAgIGNvbnNvbGUubG9nKGBbRGF0YVNlZWRlcl0gRmV0Y2hlZCAke2RhdGEubGVuZ3RofSAke2VudGl0eVR5cGV9IGl0ZW1zLCBzYXZpbmcgdG8gSW5kZXhlZERCLi4uYCk7XG4gICAgICAgIGZvciAoY29uc3QgZW50aXR5IG9mIGRhdGEpIHtcbiAgICAgICAgICAgIGF3YWl0IHNlcnZpY2Uuc2F2ZShlbnRpdHksIHRydWUpOyAvLyBzaWxlbnQgPSB0cnVlIHRvIHNraXAgYXVkaXQgbG9nZ2luZ1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUubG9nKGBbRGF0YVNlZWRlcl0gJHtlbnRpdHlUeXBlfSBzZWVkaW5nIGNvbXBsZXRlICgke2RhdGEubGVuZ3RofSBpdGVtcyBzYXZlZClgKTtcbiAgICB9XG59XG4iLCAiLyoqXG4gKiBDYWxjdWxhdGUgcGl4ZWwgcG9zaXRpb24gZm9yIGFuIGV2ZW50IGJhc2VkIG9uIGl0cyB0aW1lc1xuICovXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlRXZlbnRQb3NpdGlvbihzdGFydCwgZW5kLCBjb25maWcpIHtcbiAgICBjb25zdCBzdGFydE1pbnV0ZXMgPSBzdGFydC5nZXRIb3VycygpICogNjAgKyBzdGFydC5nZXRNaW51dGVzKCk7XG4gICAgY29uc3QgZW5kTWludXRlcyA9IGVuZC5nZXRIb3VycygpICogNjAgKyBlbmQuZ2V0TWludXRlcygpO1xuICAgIGNvbnN0IGRheVN0YXJ0TWludXRlcyA9IGNvbmZpZy5kYXlTdGFydEhvdXIgKiA2MDtcbiAgICBjb25zdCBtaW51dGVIZWlnaHQgPSBjb25maWcuaG91ckhlaWdodCAvIDYwO1xuICAgIGNvbnN0IHRvcCA9IChzdGFydE1pbnV0ZXMgLSBkYXlTdGFydE1pbnV0ZXMpICogbWludXRlSGVpZ2h0O1xuICAgIGNvbnN0IGhlaWdodCA9IChlbmRNaW51dGVzIC0gc3RhcnRNaW51dGVzKSAqIG1pbnV0ZUhlaWdodDtcbiAgICByZXR1cm4geyB0b3AsIGhlaWdodCB9O1xufVxuLyoqXG4gKiBDb252ZXJ0IG1pbnV0ZXMgdG8gcGl4ZWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtaW51dGVzVG9QaXhlbHMobWludXRlcywgY29uZmlnKSB7XG4gICAgcmV0dXJuIChtaW51dGVzIC8gNjApICogY29uZmlnLmhvdXJIZWlnaHQ7XG59XG4vKipcbiAqIENvbnZlcnQgcGl4ZWxzIHRvIG1pbnV0ZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBpeGVsc1RvTWludXRlcyhwaXhlbHMsIGNvbmZpZykge1xuICAgIHJldHVybiAocGl4ZWxzIC8gY29uZmlnLmhvdXJIZWlnaHQpICogNjA7XG59XG4vKipcbiAqIFNuYXAgcGl4ZWwgcG9zaXRpb24gdG8gZ3JpZCBpbnRlcnZhbFxuICovXG5leHBvcnQgZnVuY3Rpb24gc25hcFRvR3JpZChwaXhlbHMsIGNvbmZpZykge1xuICAgIGNvbnN0IHNuYXBQaXhlbHMgPSBtaW51dGVzVG9QaXhlbHMoY29uZmlnLnNuYXBJbnRlcnZhbCwgY29uZmlnKTtcbiAgICByZXR1cm4gTWF0aC5yb3VuZChwaXhlbHMgLyBzbmFwUGl4ZWxzKSAqIHNuYXBQaXhlbHM7XG59XG4iLCAiaW1wb3J0IHsgY2FsY3VsYXRlRXZlbnRQb3NpdGlvbiB9IGZyb20gJy4uLy4uL3V0aWxzL1Bvc2l0aW9uVXRpbHMnO1xuLyoqXG4gKiBDaGVjayBpZiB0d28gZXZlbnRzIG92ZXJsYXAgKHN0cmljdCAtIHRvdWNoaW5nIGF0IGJvdW5kYXJ5ID0gTk9UIG92ZXJsYXBwaW5nKVxuICogVGhpcyBtYXRjaGVzIFNjZW5hcmlvIDg6IGVuZD09PXN0YXJ0IGlzIE5PVCBvdmVybGFwXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBldmVudHNPdmVybGFwKGEsIGIpIHtcbiAgICByZXR1cm4gYS5zdGFydCA8IGIuZW5kICYmIGEuZW5kID4gYi5zdGFydDtcbn1cbi8qKlxuICogQ2hlY2sgaWYgdHdvIGV2ZW50cyBhcmUgd2l0aGluIHRocmVzaG9sZCBmb3IgZ3JpZCBncm91cGluZy5cbiAqIFRoaXMgaW5jbHVkZXM6XG4gKiAxLiBTdGFydC10by1zdGFydDogRXZlbnRzIHN0YXJ0IHdpdGhpbiB0aHJlc2hvbGQgb2YgZWFjaCBvdGhlclxuICogMi4gRW5kLXRvLXN0YXJ0OiBPbmUgZXZlbnQgc3RhcnRzIHdpdGhpbiB0aHJlc2hvbGQgYmVmb3JlIGFub3RoZXIgZW5kc1xuICovXG5mdW5jdGlvbiBldmVudHNXaXRoaW5UaHJlc2hvbGQoYSwgYiwgdGhyZXNob2xkTWludXRlcykge1xuICAgIGNvbnN0IHRocmVzaG9sZE1zID0gdGhyZXNob2xkTWludXRlcyAqIDYwICogMTAwMDtcbiAgICAvLyBTdGFydC10by1zdGFydDogYm90aCBldmVudHMgc3RhcnQgd2l0aGluIHRocmVzaG9sZFxuICAgIGNvbnN0IHN0YXJ0VG9TdGFydERpZmYgPSBNYXRoLmFicyhhLnN0YXJ0LmdldFRpbWUoKSAtIGIuc3RhcnQuZ2V0VGltZSgpKTtcbiAgICBpZiAoc3RhcnRUb1N0YXJ0RGlmZiA8PSB0aHJlc2hvbGRNcylcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgLy8gRW5kLXRvLXN0YXJ0OiBvbmUgZXZlbnQgc3RhcnRzIHdpdGhpbiB0aHJlc2hvbGQgYmVmb3JlIHRoZSBvdGhlciBlbmRzXG4gICAgLy8gQiBzdGFydHMgd2l0aGluIHRocmVzaG9sZCBiZWZvcmUgQSBlbmRzXG4gICAgY29uc3QgYlN0YXJ0c0JlZm9yZUFFbmRzID0gYS5lbmQuZ2V0VGltZSgpIC0gYi5zdGFydC5nZXRUaW1lKCk7XG4gICAgaWYgKGJTdGFydHNCZWZvcmVBRW5kcyA+IDAgJiYgYlN0YXJ0c0JlZm9yZUFFbmRzIDw9IHRocmVzaG9sZE1zKVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAvLyBBIHN0YXJ0cyB3aXRoaW4gdGhyZXNob2xkIGJlZm9yZSBCIGVuZHNcbiAgICBjb25zdCBhU3RhcnRzQmVmb3JlQkVuZHMgPSBiLmVuZC5nZXRUaW1lKCkgLSBhLnN0YXJ0LmdldFRpbWUoKTtcbiAgICBpZiAoYVN0YXJ0c0JlZm9yZUJFbmRzID4gMCAmJiBhU3RhcnRzQmVmb3JlQkVuZHMgPD0gdGhyZXNob2xkTXMpXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIHJldHVybiBmYWxzZTtcbn1cbi8qKlxuICogQ2hlY2sgaWYgYWxsIGV2ZW50cyBpbiBhIGdyb3VwIHN0YXJ0IHdpdGhpbiB0aHJlc2hvbGQgb2YgZWFjaCBvdGhlclxuICovXG5mdW5jdGlvbiBhbGxTdGFydFdpdGhpblRocmVzaG9sZChldmVudHMsIHRocmVzaG9sZE1pbnV0ZXMpIHtcbiAgICBpZiAoZXZlbnRzLmxlbmd0aCA8PSAxKVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAvLyBGaW5kIGVhcmxpZXN0IGFuZCBsYXRlc3Qgc3RhcnQgdGltZXNcbiAgICBsZXQgZWFybGllc3QgPSBldmVudHNbMF0uc3RhcnQuZ2V0VGltZSgpO1xuICAgIGxldCBsYXRlc3QgPSBldmVudHNbMF0uc3RhcnQuZ2V0VGltZSgpO1xuICAgIGZvciAoY29uc3QgZXZlbnQgb2YgZXZlbnRzKSB7XG4gICAgICAgIGNvbnN0IHRpbWUgPSBldmVudC5zdGFydC5nZXRUaW1lKCk7XG4gICAgICAgIGlmICh0aW1lIDwgZWFybGllc3QpXG4gICAgICAgICAgICBlYXJsaWVzdCA9IHRpbWU7XG4gICAgICAgIGlmICh0aW1lID4gbGF0ZXN0KVxuICAgICAgICAgICAgbGF0ZXN0ID0gdGltZTtcbiAgICB9XG4gICAgY29uc3QgZGlmZk1pbnV0ZXMgPSAobGF0ZXN0IC0gZWFybGllc3QpIC8gKDEwMDAgKiA2MCk7XG4gICAgcmV0dXJuIGRpZmZNaW51dGVzIDw9IHRocmVzaG9sZE1pbnV0ZXM7XG59XG4vKipcbiAqIEZpbmQgZ3JvdXBzIG9mIG92ZXJsYXBwaW5nIGV2ZW50cyAoY29ubmVjdGVkIGJ5IG92ZXJsYXAgY2hhaW4pXG4gKiBFdmVudHMgYXJlIGdyb3VwZWQgaWYgdGhleSBvdmVybGFwIHdpdGggYW55IGV2ZW50IGluIHRoZSBncm91cFxuICovXG5mdW5jdGlvbiBmaW5kT3ZlcmxhcEdyb3VwcyhldmVudHMpIHtcbiAgICBpZiAoZXZlbnRzLmxlbmd0aCA9PT0gMClcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIGNvbnN0IHNvcnRlZCA9IFsuLi5ldmVudHNdLnNvcnQoKGEsIGIpID0+IGEuc3RhcnQuZ2V0VGltZSgpIC0gYi5zdGFydC5nZXRUaW1lKCkpO1xuICAgIGNvbnN0IHVzZWQgPSBuZXcgU2V0KCk7XG4gICAgY29uc3QgZ3JvdXBzID0gW107XG4gICAgZm9yIChjb25zdCBldmVudCBvZiBzb3J0ZWQpIHtcbiAgICAgICAgaWYgKHVzZWQuaGFzKGV2ZW50LmlkKSlcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAvLyBTdGFydCBhIG5ldyBncm91cCB3aXRoIHRoaXMgZXZlbnRcbiAgICAgICAgY29uc3QgZ3JvdXAgPSBbZXZlbnRdO1xuICAgICAgICB1c2VkLmFkZChldmVudC5pZCk7XG4gICAgICAgIC8vIEV4cGFuZCBncm91cCBieSBmaW5kaW5nIGFsbCBjb25uZWN0ZWQgZXZlbnRzICh2aWEgb3ZlcmxhcClcbiAgICAgICAgbGV0IGV4cGFuZGVkID0gdHJ1ZTtcbiAgICAgICAgd2hpbGUgKGV4cGFuZGVkKSB7XG4gICAgICAgICAgICBleHBhbmRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgZm9yIChjb25zdCBjYW5kaWRhdGUgb2Ygc29ydGVkKSB7XG4gICAgICAgICAgICAgICAgaWYgKHVzZWQuaGFzKGNhbmRpZGF0ZS5pZCkpXG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIGNhbmRpZGF0ZSBvdmVybGFwcyB3aXRoIGFueSBldmVudCBpbiBncm91cFxuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3RzID0gZ3JvdXAuc29tZShtZW1iZXIgPT4gZXZlbnRzT3ZlcmxhcChtZW1iZXIsIGNhbmRpZGF0ZSkpO1xuICAgICAgICAgICAgICAgIGlmIChjb25uZWN0cykge1xuICAgICAgICAgICAgICAgICAgICBncm91cC5wdXNoKGNhbmRpZGF0ZSk7XG4gICAgICAgICAgICAgICAgICAgIHVzZWQuYWRkKGNhbmRpZGF0ZS5pZCk7XG4gICAgICAgICAgICAgICAgICAgIGV4cGFuZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZ3JvdXBzLnB1c2goZ3JvdXApO1xuICAgIH1cbiAgICByZXR1cm4gZ3JvdXBzO1xufVxuLyoqXG4gKiBGaW5kIGdyaWQgY2FuZGlkYXRlcyB3aXRoaW4gYSBncm91cCAtIGV2ZW50cyBjb25uZWN0ZWQgdmlhIHRocmVzaG9sZCBjaGFpblxuICogVXNlcyBWMSBsb2dpYzogZXZlbnRzIGFyZSBjb25uZWN0ZWQgaWYgd2l0aGluIHRocmVzaG9sZCAobm8gb3ZlcmxhcCByZXF1aXJlbWVudClcbiAqL1xuZnVuY3Rpb24gZmluZEdyaWRDYW5kaWRhdGVzKGV2ZW50cywgdGhyZXNob2xkTWludXRlcykge1xuICAgIGlmIChldmVudHMubGVuZ3RoID09PSAwKVxuICAgICAgICByZXR1cm4gW107XG4gICAgY29uc3Qgc29ydGVkID0gWy4uLmV2ZW50c10uc29ydCgoYSwgYikgPT4gYS5zdGFydC5nZXRUaW1lKCkgLSBiLnN0YXJ0LmdldFRpbWUoKSk7XG4gICAgY29uc3QgdXNlZCA9IG5ldyBTZXQoKTtcbiAgICBjb25zdCBncm91cHMgPSBbXTtcbiAgICBmb3IgKGNvbnN0IGV2ZW50IG9mIHNvcnRlZCkge1xuICAgICAgICBpZiAodXNlZC5oYXMoZXZlbnQuaWQpKVxuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIGNvbnN0IGdyb3VwID0gW2V2ZW50XTtcbiAgICAgICAgdXNlZC5hZGQoZXZlbnQuaWQpO1xuICAgICAgICAvLyBFeHBhbmQgYnkgdGhyZXNob2xkIGNoYWluIChWMSBsb2dpYzogbm8gb3ZlcmxhcCByZXF1aXJlbWVudCwganVzdCB0aHJlc2hvbGQpXG4gICAgICAgIGxldCBleHBhbmRlZCA9IHRydWU7XG4gICAgICAgIHdoaWxlIChleHBhbmRlZCkge1xuICAgICAgICAgICAgZXhwYW5kZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgY2FuZGlkYXRlIG9mIHNvcnRlZCkge1xuICAgICAgICAgICAgICAgIGlmICh1c2VkLmhhcyhjYW5kaWRhdGUuaWQpKVxuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0cyA9IGdyb3VwLnNvbWUobWVtYmVyID0+IGV2ZW50c1dpdGhpblRocmVzaG9sZChtZW1iZXIsIGNhbmRpZGF0ZSwgdGhyZXNob2xkTWludXRlcykpO1xuICAgICAgICAgICAgICAgIGlmIChjb25uZWN0cykge1xuICAgICAgICAgICAgICAgICAgICBncm91cC5wdXNoKGNhbmRpZGF0ZSk7XG4gICAgICAgICAgICAgICAgICAgIHVzZWQuYWRkKGNhbmRpZGF0ZS5pZCk7XG4gICAgICAgICAgICAgICAgICAgIGV4cGFuZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZ3JvdXBzLnB1c2goZ3JvdXApO1xuICAgIH1cbiAgICByZXR1cm4gZ3JvdXBzO1xufVxuLyoqXG4gKiBDYWxjdWxhdGUgc3RhY2sgbGV2ZWxzIGZvciBvdmVybGFwcGluZyBldmVudHMgdXNpbmcgZ3JlZWR5IGFsZ29yaXRobVxuICogRm9yIGVhY2ggZXZlbnQ6IGxldmVsID0gbWF4KG92ZXJsYXBwaW5nIGFscmVhZHktcHJvY2Vzc2VkIGV2ZW50cykgKyAxXG4gKi9cbmZ1bmN0aW9uIGNhbGN1bGF0ZVN0YWNrTGV2ZWxzKGV2ZW50cykge1xuICAgIGNvbnN0IGxldmVscyA9IG5ldyBNYXAoKTtcbiAgICBjb25zdCBzb3J0ZWQgPSBbLi4uZXZlbnRzXS5zb3J0KChhLCBiKSA9PiBhLnN0YXJ0LmdldFRpbWUoKSAtIGIuc3RhcnQuZ2V0VGltZSgpKTtcbiAgICBmb3IgKGNvbnN0IGV2ZW50IG9mIHNvcnRlZCkge1xuICAgICAgICBsZXQgbWF4T3ZlcmxhcHBpbmdMZXZlbCA9IC0xO1xuICAgICAgICAvLyBGaW5kIG1heCBsZXZlbCBhbW9uZyBvdmVybGFwcGluZyBldmVudHMgYWxyZWFkeSBwcm9jZXNzZWRcbiAgICAgICAgZm9yIChjb25zdCBbaWQsIGxldmVsXSBvZiBsZXZlbHMpIHtcbiAgICAgICAgICAgIGNvbnN0IG90aGVyID0gZXZlbnRzLmZpbmQoZSA9PiBlLmlkID09PSBpZCk7XG4gICAgICAgICAgICBpZiAob3RoZXIgJiYgZXZlbnRzT3ZlcmxhcChldmVudCwgb3RoZXIpKSB7XG4gICAgICAgICAgICAgICAgbWF4T3ZlcmxhcHBpbmdMZXZlbCA9IE1hdGgubWF4KG1heE92ZXJsYXBwaW5nTGV2ZWwsIGxldmVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBsZXZlbHMuc2V0KGV2ZW50LmlkLCBtYXhPdmVybGFwcGluZ0xldmVsICsgMSk7XG4gICAgfVxuICAgIHJldHVybiBsZXZlbHM7XG59XG4vKipcbiAqIEFsbG9jYXRlIGV2ZW50cyB0byBjb2x1bW5zIGZvciBHUklEIGxheW91dCB1c2luZyBncmVlZHkgYWxnb3JpdGhtXG4gKiBOb24tb3ZlcmxhcHBpbmcgZXZlbnRzIGNhbiBzaGFyZSBhIGNvbHVtbiB0byBtaW5pbWl6ZSB0b3RhbCBjb2x1bW5zXG4gKi9cbmZ1bmN0aW9uIGFsbG9jYXRlQ29sdW1ucyhldmVudHMpIHtcbiAgICBjb25zdCBzb3J0ZWQgPSBbLi4uZXZlbnRzXS5zb3J0KChhLCBiKSA9PiBhLnN0YXJ0LmdldFRpbWUoKSAtIGIuc3RhcnQuZ2V0VGltZSgpKTtcbiAgICBjb25zdCBjb2x1bW5zID0gW107XG4gICAgZm9yIChjb25zdCBldmVudCBvZiBzb3J0ZWQpIHtcbiAgICAgICAgLy8gRmluZCBmaXJzdCBjb2x1bW4gd2hlcmUgZXZlbnQgZG9lc24ndCBvdmVybGFwIHdpdGggZXhpc3RpbmcgZXZlbnRzXG4gICAgICAgIGxldCBwbGFjZWQgPSBmYWxzZTtcbiAgICAgICAgZm9yIChjb25zdCBjb2x1bW4gb2YgY29sdW1ucykge1xuICAgICAgICAgICAgY29uc3QgY2FuRml0ID0gIWNvbHVtbi5zb21lKGUgPT4gZXZlbnRzT3ZlcmxhcChldmVudCwgZSkpO1xuICAgICAgICAgICAgaWYgKGNhbkZpdCkge1xuICAgICAgICAgICAgICAgIGNvbHVtbi5wdXNoKGV2ZW50KTtcbiAgICAgICAgICAgICAgICBwbGFjZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIE5vIHN1aXRhYmxlIGNvbHVtbiBmb3VuZCwgY3JlYXRlIG5ldyBvbmVcbiAgICAgICAgaWYgKCFwbGFjZWQpIHtcbiAgICAgICAgICAgIGNvbHVtbnMucHVzaChbZXZlbnRdKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY29sdW1ucztcbn1cbi8qKlxuICogTWFpbiBlbnRyeSBwb2ludDogQ2FsY3VsYXRlIGNvbXBsZXRlIGxheW91dCBmb3IgYSBjb2x1bW4ncyBldmVudHNcbiAqXG4gKiBBbGdvcml0aG06XG4gKiAxLiBGaW5kIG92ZXJsYXAgZ3JvdXBzIChldmVudHMgY29ubmVjdGVkIGJ5IG92ZXJsYXAgY2hhaW4pXG4gKiAyLiBGb3IgZWFjaCBvdmVybGFwIGdyb3VwLCBmaW5kIGdyaWQgY2FuZGlkYXRlcyAoZXZlbnRzIHdpdGhpbiB0aHJlc2hvbGQgY2hhaW4pXG4gKiAzLiBJZiBhbGwgZXZlbnRzIGluIG92ZXJsYXAgZ3JvdXAgZm9ybSBhIHNpbmdsZSBncmlkIGNhbmRpZGF0ZSBcdTIxOTIgR1JJRCBtb2RlXG4gKiA0LiBPdGhlcndpc2UgXHUyMTkyIFNUQUNLSU5HIG1vZGUgd2l0aCBjYWxjdWxhdGVkIGxldmVsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlQ29sdW1uTGF5b3V0KGV2ZW50cywgY29uZmlnKSB7XG4gICAgY29uc3QgdGhyZXNob2xkTWludXRlcyA9IGNvbmZpZy5ncmlkU3RhcnRUaHJlc2hvbGRNaW51dGVzID8/IDEwO1xuICAgIGNvbnN0IHJlc3VsdCA9IHtcbiAgICAgICAgZ3JpZHM6IFtdLFxuICAgICAgICBzdGFja2VkOiBbXVxuICAgIH07XG4gICAgaWYgKGV2ZW50cy5sZW5ndGggPT09IDApXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgLy8gRmluZCBhbGwgb3ZlcmxhcHBpbmcgZXZlbnQgZ3JvdXBzXG4gICAgY29uc3Qgb3ZlcmxhcEdyb3VwcyA9IGZpbmRPdmVybGFwR3JvdXBzKGV2ZW50cyk7XG4gICAgZm9yIChjb25zdCBvdmVybGFwR3JvdXAgb2Ygb3ZlcmxhcEdyb3Vwcykge1xuICAgICAgICBpZiAob3ZlcmxhcEdyb3VwLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgLy8gU2luZ2xlIGV2ZW50IC0gbm8gZ3JvdXBpbmcgbmVlZGVkXG4gICAgICAgICAgICByZXN1bHQuc3RhY2tlZC5wdXNoKHtcbiAgICAgICAgICAgICAgICBldmVudDogb3ZlcmxhcEdyb3VwWzBdLFxuICAgICAgICAgICAgICAgIHN0YWNrTGV2ZWw6IDBcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gV2l0aGluIHRoaXMgb3ZlcmxhcCBncm91cCwgZmluZCBncmlkIGNhbmRpZGF0ZXMgKHRocmVzaG9sZC1jb25uZWN0ZWQgc3ViZ3JvdXBzKVxuICAgICAgICBjb25zdCBncmlkU3ViZ3JvdXBzID0gZmluZEdyaWRDYW5kaWRhdGVzKG92ZXJsYXBHcm91cCwgdGhyZXNob2xkTWludXRlcyk7XG4gICAgICAgIC8vIENoZWNrIGlmIHRoZSBFTlRJUkUgb3ZlcmxhcCBncm91cCBmb3JtcyBhIHNpbmdsZSBncmlkIGNhbmRpZGF0ZVxuICAgICAgICAvLyBUaGlzIGhhcHBlbnMgd2hlbiBhbGwgZXZlbnRzIGFyZSBjb25uZWN0ZWQgdmlhIHRocmVzaG9sZCBjaGFpblxuICAgICAgICBjb25zdCBsYXJnZXN0R3JpZENhbmRpZGF0ZSA9IGdyaWRTdWJncm91cHMucmVkdWNlKChtYXgsIGcpID0+IGcubGVuZ3RoID4gbWF4Lmxlbmd0aCA/IGcgOiBtYXgsIGdyaWRTdWJncm91cHNbMF0pO1xuICAgICAgICBpZiAobGFyZ2VzdEdyaWRDYW5kaWRhdGUubGVuZ3RoID09PSBvdmVybGFwR3JvdXAubGVuZ3RoKSB7XG4gICAgICAgICAgICAvLyBBbGwgZXZlbnRzIGluIG92ZXJsYXAgZ3JvdXAgYXJlIGNvbm5lY3RlZCB2aWEgdGhyZXNob2xkIGNoYWluIFx1MjE5MiBHUklEIG1vZGVcbiAgICAgICAgICAgIGNvbnN0IGNvbHVtbnMgPSBhbGxvY2F0ZUNvbHVtbnMob3ZlcmxhcEdyb3VwKTtcbiAgICAgICAgICAgIGNvbnN0IGVhcmxpZXN0ID0gb3ZlcmxhcEdyb3VwLnJlZHVjZSgobWluLCBlKSA9PiBlLnN0YXJ0IDwgbWluLnN0YXJ0ID8gZSA6IG1pbiwgb3ZlcmxhcEdyb3VwWzBdKTtcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uID0gY2FsY3VsYXRlRXZlbnRQb3NpdGlvbihlYXJsaWVzdC5zdGFydCwgZWFybGllc3QuZW5kLCBjb25maWcpO1xuICAgICAgICAgICAgcmVzdWx0LmdyaWRzLnB1c2goe1xuICAgICAgICAgICAgICAgIGV2ZW50czogb3ZlcmxhcEdyb3VwLFxuICAgICAgICAgICAgICAgIGNvbHVtbnMsXG4gICAgICAgICAgICAgICAgc3RhY2tMZXZlbDogMCxcbiAgICAgICAgICAgICAgICBwb3NpdGlvbjogeyB0b3A6IHBvc2l0aW9uLnRvcCB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIE5vdCBhbGwgZXZlbnRzIGNvbm5lY3RlZCB2aWEgdGhyZXNob2xkIFx1MjE5MiBTVEFDS0lORyBtb2RlXG4gICAgICAgICAgICBjb25zdCBsZXZlbHMgPSBjYWxjdWxhdGVTdGFja0xldmVscyhvdmVybGFwR3JvdXApO1xuICAgICAgICAgICAgZm9yIChjb25zdCBldmVudCBvZiBvdmVybGFwR3JvdXApIHtcbiAgICAgICAgICAgICAgICByZXN1bHQuc3RhY2tlZC5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnQsXG4gICAgICAgICAgICAgICAgICAgIHN0YWNrTGV2ZWw6IGxldmVscy5nZXQoZXZlbnQuaWQpID8/IDBcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuIiwgImltcG9ydCB7IGNhbGN1bGF0ZUV2ZW50UG9zaXRpb24sIHNuYXBUb0dyaWQsIHBpeGVsc1RvTWludXRlcyB9IGZyb20gJy4uLy4uL3V0aWxzL1Bvc2l0aW9uVXRpbHMnO1xuaW1wb3J0IHsgQ29yZUV2ZW50cyB9IGZyb20gJy4uLy4uL2NvbnN0YW50cy9Db3JlRXZlbnRzJztcbmltcG9ydCB7IGNhbGN1bGF0ZUNvbHVtbkxheW91dCB9IGZyb20gJy4vRXZlbnRMYXlvdXRFbmdpbmUnO1xuLyoqXG4gKiBFdmVudFJlbmRlcmVyIC0gUmVuZGVycyBjYWxlbmRhciBldmVudHMgdG8gdGhlIERPTVxuICpcbiAqIENMRUFOIGFwcHJvYWNoOlxuICogLSBPbmx5IGRhdGEtaWQgYXR0cmlidXRlIG9uIGV2ZW50IGVsZW1lbnRcbiAqIC0gaW5uZXJIVE1MIGNvbnRhaW5zIG9ubHkgdmlzaWJsZSBjb250ZW50XG4gKiAtIEV2ZW50IGRhdGEgcmV0cmlldmVkIHZpYSBFdmVudFNlcnZpY2Ugd2hlbiBuZWVkZWRcbiAqL1xuZXhwb3J0IGNsYXNzIEV2ZW50UmVuZGVyZXIge1xuICAgIGNvbnN0cnVjdG9yKGV2ZW50U2VydmljZSwgZGF0ZVNlcnZpY2UsIGdyaWRDb25maWcsIGV2ZW50QnVzKSB7XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlID0gZXZlbnRTZXJ2aWNlO1xuICAgICAgICB0aGlzLmRhdGVTZXJ2aWNlID0gZGF0ZVNlcnZpY2U7XG4gICAgICAgIHRoaXMuZ3JpZENvbmZpZyA9IGdyaWRDb25maWc7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMgPSBldmVudEJ1cztcbiAgICAgICAgdGhpcy5jb250YWluZXIgPSBudWxsO1xuICAgICAgICB0aGlzLnNldHVwTGlzdGVuZXJzKCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNldHVwIGxpc3RlbmVycyBmb3IgZHJhZy1kcm9wIGFuZCB1cGRhdGUgZXZlbnRzXG4gICAgICovXG4gICAgc2V0dXBMaXN0ZW5lcnMoKSB7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMub24oQ29yZUV2ZW50cy5FVkVOVF9EUkFHX0NPTFVNTl9DSEFOR0UsIChlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwYXlsb2FkID0gZS5kZXRhaWw7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZUNvbHVtbkNoYW5nZShwYXlsb2FkKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMub24oQ29yZUV2ZW50cy5FVkVOVF9EUkFHX01PVkUsIChlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwYXlsb2FkID0gZS5kZXRhaWw7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZURyYWdUaW1lc3RhbXAocGF5bG9hZCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENvcmVFdmVudHMuRVZFTlRfVVBEQVRFRCwgKGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSBlLmRldGFpbDtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlRXZlbnRVcGRhdGVkKHBheWxvYWQpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5ldmVudEJ1cy5vbihDb3JlRXZlbnRzLkVWRU5UX0RSQUdfRU5ELCAoZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IGUuZGV0YWlsO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVEcmFnRW5kKHBheWxvYWQpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5ldmVudEJ1cy5vbihDb3JlRXZlbnRzLkVWRU5UX0RSQUdfTEVBVkVfSEVBREVSLCAoZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IGUuZGV0YWlsO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVEcmFnTGVhdmVIZWFkZXIocGF5bG9hZCk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgRVZFTlRfRFJBR19FTkQgLSByZW1vdmUgZWxlbWVudCBpZiBkcm9wcGVkIGluIGhlYWRlclxuICAgICAqL1xuICAgIGhhbmRsZURyYWdFbmQocGF5bG9hZCkge1xuICAgICAgICBpZiAocGF5bG9hZC50YXJnZXQgPT09ICdoZWFkZXInKSB7XG4gICAgICAgICAgICAvLyBFdmVudCB3YXMgZHJvcHBlZCBpbiBoZWFkZXIgZHJhd2VyIC0gcmVtb3ZlIGZyb20gZ3JpZFxuICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuY29udGFpbmVyPy5xdWVyeVNlbGVjdG9yKGBzd3AtY29udGVudC12aWV3cG9ydCBzd3AtZXZlbnRbZGF0YS1ldmVudC1pZD1cIiR7cGF5bG9hZC5zd3BFdmVudC5ldmVudElkfVwiXWApO1xuICAgICAgICAgICAgZWxlbWVudD8ucmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogSGFuZGxlIGhlYWRlciBpdGVtIGxlYXZpbmcgaGVhZGVyIC0gY3JlYXRlIHN3cC1ldmVudCBpbiBncmlkXG4gICAgICovXG4gICAgaGFuZGxlRHJhZ0xlYXZlSGVhZGVyKHBheWxvYWQpIHtcbiAgICAgICAgLy8gT25seSBoYW5kbGUgd2hlbiBzb3VyY2UgaXMgaGVhZGVyIChoZWFkZXIgaXRlbSBkcmFnZ2VkIHRvIGdyaWQpXG4gICAgICAgIGlmIChwYXlsb2FkLnNvdXJjZSAhPT0gJ2hlYWRlcicpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGlmICghcGF5bG9hZC50YXJnZXRDb2x1bW4gfHwgIXBheWxvYWQuc3RhcnQgfHwgIXBheWxvYWQuZW5kKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAvLyBUdXJuIGhlYWRlciBpdGVtIGludG8gZ2hvc3QgKHN0YXlzIHZpc2libGUgYnV0IGZhZGVkKVxuICAgICAgICBpZiAocGF5bG9hZC5lbGVtZW50KSB7XG4gICAgICAgICAgICBwYXlsb2FkLmVsZW1lbnQuY2xhc3NMaXN0LmFkZCgnZHJhZy1naG9zdCcpO1xuICAgICAgICAgICAgcGF5bG9hZC5lbGVtZW50LnN0eWxlLm9wYWNpdHkgPSAnMC4zJztcbiAgICAgICAgICAgIHBheWxvYWQuZWxlbWVudC5zdHlsZS5wb2ludGVyRXZlbnRzID0gJ25vbmUnO1xuICAgICAgICB9XG4gICAgICAgIC8vIENyZWF0ZSBldmVudCBvYmplY3QgZnJvbSBoZWFkZXIgaXRlbSBkYXRhXG4gICAgICAgIGNvbnN0IGV2ZW50ID0ge1xuICAgICAgICAgICAgaWQ6IHBheWxvYWQuZXZlbnRJZCxcbiAgICAgICAgICAgIHRpdGxlOiBwYXlsb2FkLnRpdGxlIHx8ICcnLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246ICcnLFxuICAgICAgICAgICAgc3RhcnQ6IHBheWxvYWQuc3RhcnQsXG4gICAgICAgICAgICBlbmQ6IHBheWxvYWQuZW5kLFxuICAgICAgICAgICAgdHlwZTogJ2N1c3RvbWVyJyxcbiAgICAgICAgICAgIGFsbERheTogZmFsc2UsXG4gICAgICAgICAgICBzeW5jU3RhdHVzOiAncGVuZGluZydcbiAgICAgICAgfTtcbiAgICAgICAgLy8gQ3JlYXRlIHN3cC1ldmVudCBlbGVtZW50IHVzaW5nIGV4aXN0aW5nIG1ldGhvZFxuICAgICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5jcmVhdGVFdmVudEVsZW1lbnQoZXZlbnQpO1xuICAgICAgICAvLyBBZGQgdG8gdGFyZ2V0IGNvbHVtblxuICAgICAgICBsZXQgZXZlbnRzTGF5ZXIgPSBwYXlsb2FkLnRhcmdldENvbHVtbi5xdWVyeVNlbGVjdG9yKCdzd3AtZXZlbnRzLWxheWVyJyk7XG4gICAgICAgIGlmICghZXZlbnRzTGF5ZXIpIHtcbiAgICAgICAgICAgIGV2ZW50c0xheWVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3dwLWV2ZW50cy1sYXllcicpO1xuICAgICAgICAgICAgcGF5bG9hZC50YXJnZXRDb2x1bW4uYXBwZW5kQ2hpbGQoZXZlbnRzTGF5ZXIpO1xuICAgICAgICB9XG4gICAgICAgIGV2ZW50c0xheWVyLmFwcGVuZENoaWxkKGVsZW1lbnQpO1xuICAgICAgICAvLyBNYXJrIGFzIGRyYWdnaW5nIHNvIERyYWdEcm9wTWFuYWdlciBjYW4gY29udGludWUgd2l0aCBpdFxuICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5hZGQoJ2RyYWdnaW5nJyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEhhbmRsZSBFVkVOVF9VUERBVEVEIC0gcmUtcmVuZGVyIGFmZmVjdGVkIGNvbHVtbnNcbiAgICAgKi9cbiAgICBhc3luYyBoYW5kbGVFdmVudFVwZGF0ZWQocGF5bG9hZCkge1xuICAgICAgICAvLyBSZS1yZW5kZXIgc291cmNlIGNvbHVtbiAoaWYgZGlmZmVyZW50IGZyb20gdGFyZ2V0KVxuICAgICAgICBpZiAocGF5bG9hZC5zb3VyY2VDb2x1bW5LZXkgIT09IHBheWxvYWQudGFyZ2V0Q29sdW1uS2V5KSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnJlcmVuZGVyQ29sdW1uKHBheWxvYWQuc291cmNlQ29sdW1uS2V5KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBSZS1yZW5kZXIgdGFyZ2V0IGNvbHVtblxuICAgICAgICBhd2FpdCB0aGlzLnJlcmVuZGVyQ29sdW1uKHBheWxvYWQudGFyZ2V0Q29sdW1uS2V5KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmUtcmVuZGVyIGEgc2luZ2xlIGNvbHVtbiB3aXRoIGZyZXNoIGRhdGEgZnJvbSBJbmRleGVkREJcbiAgICAgKi9cbiAgICBhc3luYyByZXJlbmRlckNvbHVtbihjb2x1bW5LZXkpIHtcbiAgICAgICAgY29uc3QgY29sdW1uID0gdGhpcy5maW5kQ29sdW1uKGNvbHVtbktleSk7XG4gICAgICAgIGlmICghY29sdW1uKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAvLyBSZWFkIGRhdGUgYW5kIHJlc291cmNlSWQgZGlyZWN0bHkgZnJvbSBjb2x1bW4gYXR0cmlidXRlcyAoY29sdW1uS2V5IGlzIG9wYXF1ZSlcbiAgICAgICAgY29uc3QgZGF0ZSA9IGNvbHVtbi5kYXRhc2V0LmRhdGU7XG4gICAgICAgIGNvbnN0IHJlc291cmNlSWQgPSBjb2x1bW4uZGF0YXNldC5yZXNvdXJjZUlkO1xuICAgICAgICBpZiAoIWRhdGUpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIC8vIEdldCBkYXRlIHJhbmdlIGZvciB0aGlzIGRheVxuICAgICAgICBjb25zdCBzdGFydERhdGUgPSBuZXcgRGF0ZShkYXRlKTtcbiAgICAgICAgY29uc3QgZW5kRGF0ZSA9IG5ldyBEYXRlKGRhdGUpO1xuICAgICAgICBlbmREYXRlLnNldEhvdXJzKDIzLCA1OSwgNTksIDk5OSk7XG4gICAgICAgIC8vIEZldGNoIGV2ZW50cyBmcm9tIEluZGV4ZWREQlxuICAgICAgICBjb25zdCBldmVudHMgPSByZXNvdXJjZUlkXG4gICAgICAgICAgICA/IGF3YWl0IHRoaXMuZXZlbnRTZXJ2aWNlLmdldEJ5UmVzb3VyY2VBbmREYXRlUmFuZ2UocmVzb3VyY2VJZCwgc3RhcnREYXRlLCBlbmREYXRlKVxuICAgICAgICAgICAgOiBhd2FpdCB0aGlzLmV2ZW50U2VydmljZS5nZXRCeURhdGVSYW5nZShzdGFydERhdGUsIGVuZERhdGUpO1xuICAgICAgICAvLyBGaWx0ZXIgdG8gdGltZWQgZXZlbnRzIGFuZCBtYXRjaCBkYXRlIGV4YWN0bHlcbiAgICAgICAgY29uc3QgdGltZWRFdmVudHMgPSBldmVudHMuZmlsdGVyKGV2ZW50ID0+ICFldmVudC5hbGxEYXkgJiYgdGhpcy5kYXRlU2VydmljZS5nZXREYXRlS2V5KGV2ZW50LnN0YXJ0KSA9PT0gZGF0ZSk7XG4gICAgICAgIC8vIEdldCBvciBjcmVhdGUgZXZlbnRzIGxheWVyXG4gICAgICAgIGxldCBldmVudHNMYXllciA9IGNvbHVtbi5xdWVyeVNlbGVjdG9yKCdzd3AtZXZlbnRzLWxheWVyJyk7XG4gICAgICAgIGlmICghZXZlbnRzTGF5ZXIpIHtcbiAgICAgICAgICAgIGV2ZW50c0xheWVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3dwLWV2ZW50cy1sYXllcicpO1xuICAgICAgICAgICAgY29sdW1uLmFwcGVuZENoaWxkKGV2ZW50c0xheWVyKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBDbGVhciBleGlzdGluZyBldmVudHNcbiAgICAgICAgZXZlbnRzTGF5ZXIuaW5uZXJIVE1MID0gJyc7XG4gICAgICAgIC8vIENhbGN1bGF0ZSBsYXlvdXQgd2l0aCBzdGFja2luZy9ncm91cGluZ1xuICAgICAgICBjb25zdCBsYXlvdXQgPSBjYWxjdWxhdGVDb2x1bW5MYXlvdXQodGltZWRFdmVudHMsIHRoaXMuZ3JpZENvbmZpZyk7XG4gICAgICAgIC8vIFJlbmRlciBHUklEIGdyb3Vwc1xuICAgICAgICBsYXlvdXQuZ3JpZHMuZm9yRWFjaChncmlkID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGdyb3VwRWwgPSB0aGlzLnJlbmRlckdyaWRHcm91cChncmlkKTtcbiAgICAgICAgICAgIGV2ZW50c0xheWVyLmFwcGVuZENoaWxkKGdyb3VwRWwpO1xuICAgICAgICB9KTtcbiAgICAgICAgLy8gUmVuZGVyIFNUQUNLRUQgZXZlbnRzXG4gICAgICAgIGxheW91dC5zdGFja2VkLmZvckVhY2goaXRlbSA9PiB7XG4gICAgICAgICAgICBjb25zdCBldmVudEVsID0gdGhpcy5yZW5kZXJTdGFja2VkRXZlbnQoaXRlbS5ldmVudCwgaXRlbS5zdGFja0xldmVsKTtcbiAgICAgICAgICAgIGV2ZW50c0xheWVyLmFwcGVuZENoaWxkKGV2ZW50RWwpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRmluZCBhIGNvbHVtbiBlbGVtZW50IGJ5IGNvbHVtbktleVxuICAgICAqL1xuICAgIGZpbmRDb2x1bW4oY29sdW1uS2V5KSB7XG4gICAgICAgIGlmICghdGhpcy5jb250YWluZXIpXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoYHN3cC1kYXktY29sdW1uW2RhdGEtY29sdW1uLWtleT1cIiR7Y29sdW1uS2V5fVwiXWApO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgZXZlbnQgbW92aW5nIHRvIGEgbmV3IGNvbHVtbiBkdXJpbmcgZHJhZ1xuICAgICAqL1xuICAgIGhhbmRsZUNvbHVtbkNoYW5nZShwYXlsb2FkKSB7XG4gICAgICAgIGNvbnN0IGV2ZW50c0xheWVyID0gcGF5bG9hZC5uZXdDb2x1bW4ucXVlcnlTZWxlY3Rvcignc3dwLWV2ZW50cy1sYXllcicpO1xuICAgICAgICBpZiAoIWV2ZW50c0xheWVyKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAvLyBNb3ZlIGVsZW1lbnQgdG8gbmV3IGNvbHVtblxuICAgICAgICBldmVudHNMYXllci5hcHBlbmRDaGlsZChwYXlsb2FkLmVsZW1lbnQpO1xuICAgICAgICAvLyBQcmVzZXJ2ZSBZIHBvc2l0aW9uXG4gICAgICAgIHBheWxvYWQuZWxlbWVudC5zdHlsZS50b3AgPSBgJHtwYXlsb2FkLmN1cnJlbnRZfXB4YDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVXBkYXRlIHRpbWVzdGFtcCBkaXNwbGF5IGR1cmluZyBkcmFnIChzbmFwcGVkIHRvIGdyaWQpXG4gICAgICovXG4gICAgdXBkYXRlRHJhZ1RpbWVzdGFtcChwYXlsb2FkKSB7XG4gICAgICAgIGNvbnN0IHRpbWVFbCA9IHBheWxvYWQuZWxlbWVudC5xdWVyeVNlbGVjdG9yKCdzd3AtZXZlbnQtdGltZScpO1xuICAgICAgICBpZiAoIXRpbWVFbClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgLy8gU25hcCBwb3NpdGlvbiB0byBncmlkIGludGVydmFsXG4gICAgICAgIGNvbnN0IHNuYXBwZWRZID0gc25hcFRvR3JpZChwYXlsb2FkLmN1cnJlbnRZLCB0aGlzLmdyaWRDb25maWcpO1xuICAgICAgICAvLyBDYWxjdWxhdGUgbmV3IHN0YXJ0IHRpbWVcbiAgICAgICAgY29uc3QgbWludXRlc0Zyb21HcmlkU3RhcnQgPSBwaXhlbHNUb01pbnV0ZXMoc25hcHBlZFksIHRoaXMuZ3JpZENvbmZpZyk7XG4gICAgICAgIGNvbnN0IHN0YXJ0TWludXRlcyA9ICh0aGlzLmdyaWRDb25maWcuZGF5U3RhcnRIb3VyICogNjApICsgbWludXRlc0Zyb21HcmlkU3RhcnQ7XG4gICAgICAgIC8vIEtlZXAgb3JpZ2luYWwgZHVyYXRpb24gKGZyb20gZWxlbWVudCBoZWlnaHQpXG4gICAgICAgIGNvbnN0IGhlaWdodCA9IHBhcnNlRmxvYXQocGF5bG9hZC5lbGVtZW50LnN0eWxlLmhlaWdodCkgfHwgdGhpcy5ncmlkQ29uZmlnLmhvdXJIZWlnaHQ7XG4gICAgICAgIGNvbnN0IGR1cmF0aW9uTWludXRlcyA9IHBpeGVsc1RvTWludXRlcyhoZWlnaHQsIHRoaXMuZ3JpZENvbmZpZyk7XG4gICAgICAgIC8vIENyZWF0ZSBEYXRlIG9iamVjdHMgZm9yIGNvbnNpc3RlbnQgZm9ybWF0dGluZyB2aWEgRGF0ZVNlcnZpY2VcbiAgICAgICAgY29uc3Qgc3RhcnQgPSB0aGlzLm1pbnV0ZXNUb0RhdGUoc3RhcnRNaW51dGVzKTtcbiAgICAgICAgY29uc3QgZW5kID0gdGhpcy5taW51dGVzVG9EYXRlKHN0YXJ0TWludXRlcyArIGR1cmF0aW9uTWludXRlcyk7XG4gICAgICAgIHRpbWVFbC50ZXh0Q29udGVudCA9IHRoaXMuZGF0ZVNlcnZpY2UuZm9ybWF0VGltZVJhbmdlKHN0YXJ0LCBlbmQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0IG1pbnV0ZXMgc2luY2UgbWlkbmlnaHQgdG8gYSBEYXRlIG9iamVjdCAodG9kYXkpXG4gICAgICovXG4gICAgbWludXRlc1RvRGF0ZShtaW51dGVzKSB7XG4gICAgICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZSgpO1xuICAgICAgICBkYXRlLnNldEhvdXJzKE1hdGguZmxvb3IobWludXRlcyAvIDYwKSAlIDI0LCBtaW51dGVzICUgNjAsIDAsIDApO1xuICAgICAgICByZXR1cm4gZGF0ZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVuZGVyIGV2ZW50cyBmb3IgdmlzaWJsZSBkYXRlcyBpbnRvIGRheSBjb2x1bW5zXG4gICAgICogQHBhcmFtIGNvbnRhaW5lciAtIENhbGVuZGFyIGNvbnRhaW5lciBlbGVtZW50XG4gICAgICogQHBhcmFtIGZpbHRlciAtIEZpbHRlciB3aXRoICdkYXRlJyBhbmQgb3B0aW9uYWxseSAncmVzb3VyY2UnIGFycmF5c1xuICAgICAqIEBwYXJhbSBmaWx0ZXJUZW1wbGF0ZSAtIFRlbXBsYXRlIGZvciBtYXRjaGluZyBldmVudHMgdG8gY29sdW1uc1xuICAgICAqL1xuICAgIGFzeW5jIHJlbmRlcihjb250YWluZXIsIGZpbHRlciwgZmlsdGVyVGVtcGxhdGUpIHtcbiAgICAgICAgLy8gU3RvcmUgY29udGFpbmVyIHJlZmVyZW5jZSBmb3IgbGF0ZXIgcmUtcmVuZGVyc1xuICAgICAgICB0aGlzLmNvbnRhaW5lciA9IGNvbnRhaW5lcjtcbiAgICAgICAgY29uc3QgdmlzaWJsZURhdGVzID0gZmlsdGVyWydkYXRlJ10gfHwgW107XG4gICAgICAgIGlmICh2aXNpYmxlRGF0ZXMubGVuZ3RoID09PSAwKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAvLyBHZXQgZGF0ZSByYW5nZSBmb3IgcXVlcnlcbiAgICAgICAgY29uc3Qgc3RhcnREYXRlID0gbmV3IERhdGUodmlzaWJsZURhdGVzWzBdKTtcbiAgICAgICAgY29uc3QgZW5kRGF0ZSA9IG5ldyBEYXRlKHZpc2libGVEYXRlc1t2aXNpYmxlRGF0ZXMubGVuZ3RoIC0gMV0pO1xuICAgICAgICBlbmREYXRlLnNldEhvdXJzKDIzLCA1OSwgNTksIDk5OSk7XG4gICAgICAgIC8vIEZldGNoIGV2ZW50cyBmcm9tIEluZGV4ZWREQlxuICAgICAgICBjb25zdCBldmVudHMgPSBhd2FpdCB0aGlzLmV2ZW50U2VydmljZS5nZXRCeURhdGVSYW5nZShzdGFydERhdGUsIGVuZERhdGUpO1xuICAgICAgICAvLyBGaW5kIGRheSBjb2x1bW5zXG4gICAgICAgIGNvbnN0IGRheUNvbHVtbnMgPSBjb250YWluZXIucXVlcnlTZWxlY3Rvcignc3dwLWRheS1jb2x1bW5zJyk7XG4gICAgICAgIGlmICghZGF5Q29sdW1ucylcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY29uc3QgY29sdW1ucyA9IGRheUNvbHVtbnMucXVlcnlTZWxlY3RvckFsbCgnc3dwLWRheS1jb2x1bW4nKTtcbiAgICAgICAgLy8gUmVuZGVyIGV2ZW50cyBpbnRvIGVhY2ggY29sdW1uIGJhc2VkIG9uIEZpbHRlclRlbXBsYXRlIG1hdGNoaW5nXG4gICAgICAgIGNvbHVtbnMuZm9yRWFjaChjb2x1bW4gPT4ge1xuICAgICAgICAgICAgY29uc3QgY29sdW1uRWwgPSBjb2x1bW47XG4gICAgICAgICAgICAvLyBVc2UgRmlsdGVyVGVtcGxhdGUgZm9yIG1hdGNoaW5nIC0gb25seSBmaWVsZHMgaW4gdGVtcGxhdGUgYXJlIGNoZWNrZWRcbiAgICAgICAgICAgIGNvbnN0IGNvbHVtbkV2ZW50cyA9IGV2ZW50cy5maWx0ZXIoZXZlbnQgPT4gZmlsdGVyVGVtcGxhdGUubWF0Y2hlcyhldmVudCwgY29sdW1uRWwpKTtcbiAgICAgICAgICAgIC8vIEdldCBvciBjcmVhdGUgZXZlbnRzIGxheWVyXG4gICAgICAgICAgICBsZXQgZXZlbnRzTGF5ZXIgPSBjb2x1bW4ucXVlcnlTZWxlY3Rvcignc3dwLWV2ZW50cy1sYXllcicpO1xuICAgICAgICAgICAgaWYgKCFldmVudHNMYXllcikge1xuICAgICAgICAgICAgICAgIGV2ZW50c0xheWVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3dwLWV2ZW50cy1sYXllcicpO1xuICAgICAgICAgICAgICAgIGNvbHVtbi5hcHBlbmRDaGlsZChldmVudHNMYXllcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBDbGVhciBleGlzdGluZyBldmVudHNcbiAgICAgICAgICAgIGV2ZW50c0xheWVyLmlubmVySFRNTCA9ICcnO1xuICAgICAgICAgICAgLy8gRmlsdGVyIHRvIHRpbWVkIGV2ZW50cyBvbmx5XG4gICAgICAgICAgICBjb25zdCB0aW1lZEV2ZW50cyA9IGNvbHVtbkV2ZW50cy5maWx0ZXIoZXZlbnQgPT4gIWV2ZW50LmFsbERheSk7XG4gICAgICAgICAgICAvLyBDYWxjdWxhdGUgbGF5b3V0IHdpdGggc3RhY2tpbmcvZ3JvdXBpbmdcbiAgICAgICAgICAgIGNvbnN0IGxheW91dCA9IGNhbGN1bGF0ZUNvbHVtbkxheW91dCh0aW1lZEV2ZW50cywgdGhpcy5ncmlkQ29uZmlnKTtcbiAgICAgICAgICAgIC8vIFJlbmRlciBHUklEIGdyb3VwcyAoc2ltdWx0YW5lb3VzIGV2ZW50cyBzaWRlLWJ5LXNpZGUpXG4gICAgICAgICAgICBsYXlvdXQuZ3JpZHMuZm9yRWFjaChncmlkID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBncm91cEVsID0gdGhpcy5yZW5kZXJHcmlkR3JvdXAoZ3JpZCk7XG4gICAgICAgICAgICAgICAgZXZlbnRzTGF5ZXIuYXBwZW5kQ2hpbGQoZ3JvdXBFbCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIC8vIFJlbmRlciBTVEFDS0VEIGV2ZW50cyAob3ZlcmxhcHBpbmcgd2l0aCBtYXJnaW4gb2Zmc2V0KVxuICAgICAgICAgICAgbGF5b3V0LnN0YWNrZWQuZm9yRWFjaChpdGVtID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBldmVudEVsID0gdGhpcy5yZW5kZXJTdGFja2VkRXZlbnQoaXRlbS5ldmVudCwgaXRlbS5zdGFja0xldmVsKTtcbiAgICAgICAgICAgICAgICBldmVudHNMYXllci5hcHBlbmRDaGlsZChldmVudEVsKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGEgc2luZ2xlIGV2ZW50IGVsZW1lbnRcbiAgICAgKlxuICAgICAqIENMRUFOIGFwcHJvYWNoOlxuICAgICAqIC0gT25seSBkYXRhLWlkIGZvciBsb29rdXBcbiAgICAgKiAtIFZpc2libGUgY29udGVudCBpbiBpbm5lckhUTUwgb25seVxuICAgICAqL1xuICAgIGNyZWF0ZUV2ZW50RWxlbWVudChldmVudCkge1xuICAgICAgICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3dwLWV2ZW50Jyk7XG4gICAgICAgIC8vIERhdGEgYXR0cmlidXRlcyBmb3IgU3dwRXZlbnQgY29tcGF0aWJpbGl0eVxuICAgICAgICBlbGVtZW50LmRhdGFzZXQuZXZlbnRJZCA9IGV2ZW50LmlkO1xuICAgICAgICBpZiAoZXZlbnQucmVzb3VyY2VJZCkge1xuICAgICAgICAgICAgZWxlbWVudC5kYXRhc2V0LnJlc291cmNlSWQgPSBldmVudC5yZXNvdXJjZUlkO1xuICAgICAgICB9XG4gICAgICAgIC8vIENhbGN1bGF0ZSBwb3NpdGlvblxuICAgICAgICBjb25zdCBwb3NpdGlvbiA9IGNhbGN1bGF0ZUV2ZW50UG9zaXRpb24oZXZlbnQuc3RhcnQsIGV2ZW50LmVuZCwgdGhpcy5ncmlkQ29uZmlnKTtcbiAgICAgICAgZWxlbWVudC5zdHlsZS50b3AgPSBgJHtwb3NpdGlvbi50b3B9cHhgO1xuICAgICAgICBlbGVtZW50LnN0eWxlLmhlaWdodCA9IGAke3Bvc2l0aW9uLmhlaWdodH1weGA7XG4gICAgICAgIC8vIENvbG9yIGNsYXNzIGJhc2VkIG9uIGV2ZW50IHR5cGVcbiAgICAgICAgY29uc3QgY29sb3JDbGFzcyA9IHRoaXMuZ2V0Q29sb3JDbGFzcyhldmVudCk7XG4gICAgICAgIGlmIChjb2xvckNsYXNzKSB7XG4gICAgICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5hZGQoY29sb3JDbGFzcyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVmlzaWJsZSBjb250ZW50IG9ubHlcbiAgICAgICAgZWxlbWVudC5pbm5lckhUTUwgPSBgXHJcbiAgICAgIDxzd3AtZXZlbnQtdGltZT4ke3RoaXMuZGF0ZVNlcnZpY2UuZm9ybWF0VGltZVJhbmdlKGV2ZW50LnN0YXJ0LCBldmVudC5lbmQpfTwvc3dwLWV2ZW50LXRpbWU+XHJcbiAgICAgIDxzd3AtZXZlbnQtdGl0bGU+JHt0aGlzLmVzY2FwZUh0bWwoZXZlbnQudGl0bGUpfTwvc3dwLWV2ZW50LXRpdGxlPlxyXG4gICAgICAke2V2ZW50LmRlc2NyaXB0aW9uID8gYDxzd3AtZXZlbnQtZGVzY3JpcHRpb24+JHt0aGlzLmVzY2FwZUh0bWwoZXZlbnQuZGVzY3JpcHRpb24pfTwvc3dwLWV2ZW50LWRlc2NyaXB0aW9uPmAgOiAnJ31cclxuICAgIGA7XG4gICAgICAgIHJldHVybiBlbGVtZW50O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgY29sb3IgY2xhc3MgYmFzZWQgb24gbWV0YWRhdGEuY29sb3Igb3IgZXZlbnQgdHlwZVxuICAgICAqL1xuICAgIGdldENvbG9yQ2xhc3MoZXZlbnQpIHtcbiAgICAgICAgLy8gQ2hlY2sgbWV0YWRhdGEuY29sb3IgZmlyc3RcbiAgICAgICAgaWYgKGV2ZW50Lm1ldGFkYXRhPy5jb2xvcikge1xuICAgICAgICAgICAgcmV0dXJuIGBpcy0ke2V2ZW50Lm1ldGFkYXRhLmNvbG9yfWA7XG4gICAgICAgIH1cbiAgICAgICAgLy8gRmFsbGJhY2sgdG8gdHlwZS1iYXNlZCBjb2xvclxuICAgICAgICBjb25zdCB0eXBlQ29sb3JzID0ge1xuICAgICAgICAgICAgJ2N1c3RvbWVyJzogJ2lzLWJsdWUnLFxuICAgICAgICAgICAgJ3ZhY2F0aW9uJzogJ2lzLWdyZWVuJyxcbiAgICAgICAgICAgICdicmVhayc6ICdpcy1hbWJlcicsXG4gICAgICAgICAgICAnbWVldGluZyc6ICdpcy1wdXJwbGUnLFxuICAgICAgICAgICAgJ2Jsb2NrZWQnOiAnaXMtcmVkJ1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gdHlwZUNvbG9yc1tldmVudC50eXBlXSB8fCAnaXMtYmx1ZSc7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEVzY2FwZSBIVE1MIHRvIHByZXZlbnQgWFNTXG4gICAgICovXG4gICAgZXNjYXBlSHRtbCh0ZXh0KSB7XG4gICAgICAgIGNvbnN0IGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICBkaXYudGV4dENvbnRlbnQgPSB0ZXh0O1xuICAgICAgICByZXR1cm4gZGl2LmlubmVySFRNTDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVuZGVyIGEgR1JJRCBncm91cCB3aXRoIHNpZGUtYnktc2lkZSBjb2x1bW5zXG4gICAgICogVXNlZCB3aGVuIG11bHRpcGxlIGV2ZW50cyBzdGFydCBhdCB0aGUgc2FtZSB0aW1lXG4gICAgICovXG4gICAgcmVuZGVyR3JpZEdyb3VwKGxheW91dCkge1xuICAgICAgICBjb25zdCBncm91cCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3N3cC1ldmVudC1ncm91cCcpO1xuICAgICAgICBncm91cC5jbGFzc0xpc3QuYWRkKGBjb2xzLSR7bGF5b3V0LmNvbHVtbnMubGVuZ3RofWApO1xuICAgICAgICBncm91cC5zdHlsZS50b3AgPSBgJHtsYXlvdXQucG9zaXRpb24udG9wfXB4YDtcbiAgICAgICAgLy8gU3RhY2sgbGV2ZWwgc3R5bGluZyBmb3IgZW50aXJlIGdyb3VwIChpZiBuZXN0ZWQgaW4gYW5vdGhlciBldmVudClcbiAgICAgICAgaWYgKGxheW91dC5zdGFja0xldmVsID4gMCkge1xuICAgICAgICAgICAgZ3JvdXAuc3R5bGUubWFyZ2luTGVmdCA9IGAke2xheW91dC5zdGFja0xldmVsICogMTV9cHhgO1xuICAgICAgICAgICAgZ3JvdXAuc3R5bGUuekluZGV4ID0gYCR7MTAwICsgbGF5b3V0LnN0YWNrTGV2ZWx9YDtcbiAgICAgICAgfVxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIGhlaWdodCBuZWVkZWQgZm9yIHRoZSBncm91cCAodGFsbGVzdCBldmVudClcbiAgICAgICAgbGV0IG1heEJvdHRvbSA9IDA7XG4gICAgICAgIGZvciAoY29uc3QgZXZlbnQgb2YgbGF5b3V0LmV2ZW50cykge1xuICAgICAgICAgICAgY29uc3QgcG9zID0gY2FsY3VsYXRlRXZlbnRQb3NpdGlvbihldmVudC5zdGFydCwgZXZlbnQuZW5kLCB0aGlzLmdyaWRDb25maWcpO1xuICAgICAgICAgICAgY29uc3QgZXZlbnRCb3R0b20gPSBwb3MudG9wICsgcG9zLmhlaWdodDtcbiAgICAgICAgICAgIGlmIChldmVudEJvdHRvbSA+IG1heEJvdHRvbSlcbiAgICAgICAgICAgICAgICBtYXhCb3R0b20gPSBldmVudEJvdHRvbTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBncm91cEhlaWdodCA9IG1heEJvdHRvbSAtIGxheW91dC5wb3NpdGlvbi50b3A7XG4gICAgICAgIGdyb3VwLnN0eWxlLmhlaWdodCA9IGAke2dyb3VwSGVpZ2h0fXB4YDtcbiAgICAgICAgLy8gQ3JlYXRlIHdyYXBwZXIgZGl2IGZvciBlYWNoIGNvbHVtblxuICAgICAgICBsYXlvdXQuY29sdW1ucy5mb3JFYWNoKGNvbHVtbkV2ZW50cyA9PiB7XG4gICAgICAgICAgICBjb25zdCB3cmFwcGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgICAgICB3cmFwcGVyLnN0eWxlLnBvc2l0aW9uID0gJ3JlbGF0aXZlJztcbiAgICAgICAgICAgIGNvbHVtbkV2ZW50cy5mb3JFYWNoKGV2ZW50ID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBldmVudEVsID0gdGhpcy5jcmVhdGVFdmVudEVsZW1lbnQoZXZlbnQpO1xuICAgICAgICAgICAgICAgIC8vIFBvc2l0aW9uIHJlbGF0aXZlIHRvIGdyb3VwIHRvcFxuICAgICAgICAgICAgICAgIGNvbnN0IHBvcyA9IGNhbGN1bGF0ZUV2ZW50UG9zaXRpb24oZXZlbnQuc3RhcnQsIGV2ZW50LmVuZCwgdGhpcy5ncmlkQ29uZmlnKTtcbiAgICAgICAgICAgICAgICBldmVudEVsLnN0eWxlLnRvcCA9IGAke3Bvcy50b3AgLSBsYXlvdXQucG9zaXRpb24udG9wfXB4YDtcbiAgICAgICAgICAgICAgICBldmVudEVsLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICAgICAgICAgICAgICBldmVudEVsLnN0eWxlLmxlZnQgPSAnMCc7XG4gICAgICAgICAgICAgICAgZXZlbnRFbC5zdHlsZS5yaWdodCA9ICcwJztcbiAgICAgICAgICAgICAgICB3cmFwcGVyLmFwcGVuZENoaWxkKGV2ZW50RWwpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBncm91cC5hcHBlbmRDaGlsZCh3cmFwcGVyKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBncm91cDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVuZGVyIGEgU1RBQ0tFRCBldmVudCB3aXRoIG1hcmdpbi1sZWZ0IG9mZnNldFxuICAgICAqIFVzZWQgZm9yIG92ZXJsYXBwaW5nIGV2ZW50cyB0aGF0IGRvbid0IHN0YXJ0IGF0IHRoZSBzYW1lIHRpbWVcbiAgICAgKi9cbiAgICByZW5kZXJTdGFja2VkRXZlbnQoZXZlbnQsIHN0YWNrTGV2ZWwpIHtcbiAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuY3JlYXRlRXZlbnRFbGVtZW50KGV2ZW50KTtcbiAgICAgICAgLy8gQWRkIHN0YWNrIG1ldGFkYXRhIGZvciBkcmFnLWRyb3AgYW5kIG90aGVyIGZlYXR1cmVzXG4gICAgICAgIGVsZW1lbnQuZGF0YXNldC5zdGFja0xpbmsgPSBKU09OLnN0cmluZ2lmeSh7IHN0YWNrTGV2ZWwgfSk7XG4gICAgICAgIC8vIFZpc3VhbCBzdHlsaW5nIGJhc2VkIG9uIHN0YWNrIGxldmVsXG4gICAgICAgIGlmIChzdGFja0xldmVsID4gMCkge1xuICAgICAgICAgICAgZWxlbWVudC5zdHlsZS5tYXJnaW5MZWZ0ID0gYCR7c3RhY2tMZXZlbCAqIDE1fXB4YDtcbiAgICAgICAgICAgIGVsZW1lbnQuc3R5bGUuekluZGV4ID0gYCR7MTAwICsgc3RhY2tMZXZlbH1gO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlbGVtZW50O1xuICAgIH1cbn1cbiIsICIvKipcbiAqIFNjaGVkdWxlUmVuZGVyZXIgLSBSZW5kZXJzIHVuYXZhaWxhYmxlIHRpbWUgem9uZXMgaW4gZGF5IGNvbHVtbnNcbiAqXG4gKiBDcmVhdGVzIHZpc3VhbCBpbmRpY2F0b3JzIGZvciB0aW1lcyBvdXRzaWRlIHRoZSByZXNvdXJjZSdzIHdvcmtpbmcgaG91cnM6XG4gKiAtIEJlZm9yZSB3b3JrIHN0YXJ0IChlLmcuLCAwNjowMCAtIDA5OjAwKVxuICogLSBBZnRlciB3b3JrIGVuZCAoZS5nLiwgMTc6MDAgLSAxODowMClcbiAqIC0gRnVsbCBkYXkgaWYgcmVzb3VyY2UgaXMgb2ZmIChzY2hlZHVsZSA9IG51bGwpXG4gKi9cbmV4cG9ydCBjbGFzcyBTY2hlZHVsZVJlbmRlcmVyIHtcbiAgICBjb25zdHJ1Y3RvcihzY2hlZHVsZVNlcnZpY2UsIGRhdGVTZXJ2aWNlLCBncmlkQ29uZmlnKSB7XG4gICAgICAgIHRoaXMuc2NoZWR1bGVTZXJ2aWNlID0gc2NoZWR1bGVTZXJ2aWNlO1xuICAgICAgICB0aGlzLmRhdGVTZXJ2aWNlID0gZGF0ZVNlcnZpY2U7XG4gICAgICAgIHRoaXMuZ3JpZENvbmZpZyA9IGdyaWRDb25maWc7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlbmRlciB1bmF2YWlsYWJsZSB6b25lcyBmb3IgdmlzaWJsZSBjb2x1bW5zXG4gICAgICogQHBhcmFtIGNvbnRhaW5lciAtIENhbGVuZGFyIGNvbnRhaW5lciBlbGVtZW50XG4gICAgICogQHBhcmFtIGZpbHRlciAtIEZpbHRlciB3aXRoICdkYXRlJyBhbmQgJ3Jlc291cmNlJyBhcnJheXNcbiAgICAgKi9cbiAgICBhc3luYyByZW5kZXIoY29udGFpbmVyLCBmaWx0ZXIpIHtcbiAgICAgICAgY29uc3QgZGF0ZXMgPSBmaWx0ZXJbJ2RhdGUnXSB8fCBbXTtcbiAgICAgICAgY29uc3QgcmVzb3VyY2VJZHMgPSBmaWx0ZXJbJ3Jlc291cmNlJ10gfHwgW107XG4gICAgICAgIGlmIChkYXRlcy5sZW5ndGggPT09IDApXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIC8vIEZpbmQgZGF5IGNvbHVtbnNcbiAgICAgICAgY29uc3QgZGF5Q29sdW1ucyA9IGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCdzd3AtZGF5LWNvbHVtbnMnKTtcbiAgICAgICAgaWYgKCFkYXlDb2x1bW5zKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBjb25zdCBjb2x1bW5zID0gZGF5Q29sdW1ucy5xdWVyeVNlbGVjdG9yQWxsKCdzd3AtZGF5LWNvbHVtbicpO1xuICAgICAgICBmb3IgKGNvbnN0IGNvbHVtbiBvZiBjb2x1bW5zKSB7XG4gICAgICAgICAgICBjb25zdCBkYXRlID0gY29sdW1uLmRhdGFzZXQuZGF0ZTtcbiAgICAgICAgICAgIGNvbnN0IHJlc291cmNlSWQgPSBjb2x1bW4uZGF0YXNldC5yZXNvdXJjZUlkO1xuICAgICAgICAgICAgaWYgKCFkYXRlIHx8ICFyZXNvdXJjZUlkKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgLy8gR2V0IG9yIGNyZWF0ZSB1bmF2YWlsYWJsZSBsYXllclxuICAgICAgICAgICAgbGV0IHVuYXZhaWxhYmxlTGF5ZXIgPSBjb2x1bW4ucXVlcnlTZWxlY3Rvcignc3dwLXVuYXZhaWxhYmxlLWxheWVyJyk7XG4gICAgICAgICAgICBpZiAoIXVuYXZhaWxhYmxlTGF5ZXIpIHtcbiAgICAgICAgICAgICAgICB1bmF2YWlsYWJsZUxheWVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3dwLXVuYXZhaWxhYmxlLWxheWVyJyk7XG4gICAgICAgICAgICAgICAgY29sdW1uLmluc2VydEJlZm9yZSh1bmF2YWlsYWJsZUxheWVyLCBjb2x1bW4uZmlyc3RDaGlsZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBDbGVhciBleGlzdGluZ1xuICAgICAgICAgICAgdW5hdmFpbGFibGVMYXllci5pbm5lckhUTUwgPSAnJztcbiAgICAgICAgICAgIC8vIEdldCBzY2hlZHVsZSBmb3IgdGhpcyByZXNvdXJjZS9kYXRlXG4gICAgICAgICAgICBjb25zdCBzY2hlZHVsZSA9IGF3YWl0IHRoaXMuc2NoZWR1bGVTZXJ2aWNlLmdldFNjaGVkdWxlRm9yRGF0ZShyZXNvdXJjZUlkLCBkYXRlKTtcbiAgICAgICAgICAgIC8vIFJlbmRlciB1bmF2YWlsYWJsZSB6b25lc1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJVbmF2YWlsYWJsZVpvbmVzKHVuYXZhaWxhYmxlTGF5ZXIsIHNjaGVkdWxlKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZW5kZXIgdW5hdmFpbGFibGUgdGltZSB6b25lcyBiYXNlZCBvbiBzY2hlZHVsZVxuICAgICAqL1xuICAgIHJlbmRlclVuYXZhaWxhYmxlWm9uZXMobGF5ZXIsIHNjaGVkdWxlKSB7XG4gICAgICAgIGNvbnN0IGRheVN0YXJ0TWludXRlcyA9IHRoaXMuZ3JpZENvbmZpZy5kYXlTdGFydEhvdXIgKiA2MDtcbiAgICAgICAgY29uc3QgZGF5RW5kTWludXRlcyA9IHRoaXMuZ3JpZENvbmZpZy5kYXlFbmRIb3VyICogNjA7XG4gICAgICAgIGNvbnN0IG1pbnV0ZUhlaWdodCA9IHRoaXMuZ3JpZENvbmZpZy5ob3VySGVpZ2h0IC8gNjA7XG4gICAgICAgIGlmIChzY2hlZHVsZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgLy8gRnVsbCBkYXkgdW5hdmFpbGFibGVcbiAgICAgICAgICAgIGNvbnN0IHpvbmUgPSB0aGlzLmNyZWF0ZVVuYXZhaWxhYmxlWm9uZSgwLCAoZGF5RW5kTWludXRlcyAtIGRheVN0YXJ0TWludXRlcykgKiBtaW51dGVIZWlnaHQpO1xuICAgICAgICAgICAgbGF5ZXIuYXBwZW5kQ2hpbGQoem9uZSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgd29ya1N0YXJ0TWludXRlcyA9IHRoaXMuZGF0ZVNlcnZpY2UudGltZVRvTWludXRlcyhzY2hlZHVsZS5zdGFydCk7XG4gICAgICAgIGNvbnN0IHdvcmtFbmRNaW51dGVzID0gdGhpcy5kYXRlU2VydmljZS50aW1lVG9NaW51dGVzKHNjaGVkdWxlLmVuZCk7XG4gICAgICAgIC8vIEJlZm9yZSB3b3JrIHN0YXJ0XG4gICAgICAgIGlmICh3b3JrU3RhcnRNaW51dGVzID4gZGF5U3RhcnRNaW51dGVzKSB7XG4gICAgICAgICAgICBjb25zdCB0b3AgPSAwO1xuICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gKHdvcmtTdGFydE1pbnV0ZXMgLSBkYXlTdGFydE1pbnV0ZXMpICogbWludXRlSGVpZ2h0O1xuICAgICAgICAgICAgY29uc3Qgem9uZSA9IHRoaXMuY3JlYXRlVW5hdmFpbGFibGVab25lKHRvcCwgaGVpZ2h0KTtcbiAgICAgICAgICAgIGxheWVyLmFwcGVuZENoaWxkKHpvbmUpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEFmdGVyIHdvcmsgZW5kXG4gICAgICAgIGlmICh3b3JrRW5kTWludXRlcyA8IGRheUVuZE1pbnV0ZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHRvcCA9ICh3b3JrRW5kTWludXRlcyAtIGRheVN0YXJ0TWludXRlcykgKiBtaW51dGVIZWlnaHQ7XG4gICAgICAgICAgICBjb25zdCBoZWlnaHQgPSAoZGF5RW5kTWludXRlcyAtIHdvcmtFbmRNaW51dGVzKSAqIG1pbnV0ZUhlaWdodDtcbiAgICAgICAgICAgIGNvbnN0IHpvbmUgPSB0aGlzLmNyZWF0ZVVuYXZhaWxhYmxlWm9uZSh0b3AsIGhlaWdodCk7XG4gICAgICAgICAgICBsYXllci5hcHBlbmRDaGlsZCh6b25lKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgYW4gdW5hdmFpbGFibGUgem9uZSBlbGVtZW50XG4gICAgICovXG4gICAgY3JlYXRlVW5hdmFpbGFibGVab25lKHRvcCwgaGVpZ2h0KSB7XG4gICAgICAgIGNvbnN0IHpvbmUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzd3AtdW5hdmFpbGFibGUtem9uZScpO1xuICAgICAgICB6b25lLnN0eWxlLnRvcCA9IGAke3RvcH1weGA7XG4gICAgICAgIHpvbmUuc3R5bGUuaGVpZ2h0ID0gYCR7aGVpZ2h0fXB4YDtcbiAgICAgICAgcmV0dXJuIHpvbmU7XG4gICAgfVxufVxuIiwgImltcG9ydCB7IENvcmVFdmVudHMgfSBmcm9tICcuLi8uLi9jb25zdGFudHMvQ29yZUV2ZW50cyc7XG4vKipcbiAqIEhlYWRlckRyYXdlclJlbmRlcmVyIC0gSGFuZGxlcyByZW5kZXJpbmcgb2YgaXRlbXMgaW4gdGhlIGhlYWRlciBkcmF3ZXJcbiAqXG4gKiBMaXN0ZW5zIHRvIGRyYWcgZXZlbnRzIGZyb20gRHJhZ0Ryb3BNYW5hZ2VyIGFuZCBjcmVhdGVzL21hbmFnZXNcbiAqIHN3cC1oZWFkZXItaXRlbSBlbGVtZW50cyBpbiB0aGUgaGVhZGVyIGRyYXdlci5cbiAqXG4gKiBVc2VzIHN1YmdyaWQgZm9yIGNvbHVtbiBhbGlnbm1lbnQgd2l0aCBwYXJlbnQgc3dwLWNhbGVuZGFyLWhlYWRlci5cbiAqIFBvc2l0aW9uIGl0ZW1zIHZpYSBncmlkQXJlYSBmb3IgZXhwbGljaXQgcm93L2NvbHVtbiBwbGFjZW1lbnQuXG4gKi9cbmV4cG9ydCBjbGFzcyBIZWFkZXJEcmF3ZXJSZW5kZXJlciB7XG4gICAgY29uc3RydWN0b3IoZXZlbnRCdXMsIGdyaWRDb25maWcsIGhlYWRlckRyYXdlck1hbmFnZXIsIGV2ZW50U2VydmljZSwgZGF0ZVNlcnZpY2UpIHtcbiAgICAgICAgdGhpcy5ldmVudEJ1cyA9IGV2ZW50QnVzO1xuICAgICAgICB0aGlzLmdyaWRDb25maWcgPSBncmlkQ29uZmlnO1xuICAgICAgICB0aGlzLmhlYWRlckRyYXdlck1hbmFnZXIgPSBoZWFkZXJEcmF3ZXJNYW5hZ2VyO1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZSA9IGV2ZW50U2VydmljZTtcbiAgICAgICAgdGhpcy5kYXRlU2VydmljZSA9IGRhdGVTZXJ2aWNlO1xuICAgICAgICB0aGlzLmN1cnJlbnRJdGVtID0gbnVsbDtcbiAgICAgICAgdGhpcy5jb250YWluZXIgPSBudWxsO1xuICAgICAgICB0aGlzLnNvdXJjZUVsZW1lbnQgPSBudWxsO1xuICAgICAgICB0aGlzLndhc0V4cGFuZGVkQmVmb3JlRHJhZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmZpbHRlclRlbXBsYXRlID0gbnVsbDtcbiAgICAgICAgdGhpcy5zZXR1cExpc3RlbmVycygpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZW5kZXIgYWxsRGF5IGV2ZW50cyBpbnRvIHRoZSBoZWFkZXIgZHJhd2VyIHdpdGggcm93IHN0YWNraW5nXG4gICAgICogQHBhcmFtIGZpbHRlclRlbXBsYXRlIC0gVGVtcGxhdGUgZm9yIG1hdGNoaW5nIGV2ZW50cyB0byBjb2x1bW5zXG4gICAgICovXG4gICAgYXN5bmMgcmVuZGVyKGNvbnRhaW5lciwgZmlsdGVyLCBmaWx0ZXJUZW1wbGF0ZSkge1xuICAgICAgICAvLyBTdG9yZSBmaWx0ZXJUZW1wbGF0ZSBmb3IgYnVpbGRDb2x1bW5LZXlGcm9tRXZlbnRcbiAgICAgICAgdGhpcy5maWx0ZXJUZW1wbGF0ZSA9IGZpbHRlclRlbXBsYXRlO1xuICAgICAgICBjb25zdCBkcmF3ZXIgPSBjb250YWluZXIucXVlcnlTZWxlY3Rvcignc3dwLWhlYWRlci1kcmF3ZXInKTtcbiAgICAgICAgaWYgKCFkcmF3ZXIpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNvbnN0IHZpc2libGVEYXRlcyA9IGZpbHRlclsnZGF0ZSddIHx8IFtdO1xuICAgICAgICBpZiAodmlzaWJsZURhdGVzLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgLy8gR2V0IGNvbHVtbiBrZXlzIGZyb20gRE9NIGZvciBjb3JyZWN0IG11bHRpLXJlc291cmNlIHBvc2l0aW9uaW5nXG4gICAgICAgIGNvbnN0IHZpc2libGVDb2x1bW5LZXlzID0gdGhpcy5nZXRWaXNpYmxlQ29sdW1uS2V5c0Zyb21ET00oKTtcbiAgICAgICAgaWYgKHZpc2libGVDb2x1bW5LZXlzLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgLy8gRmV0Y2ggZXZlbnRzIGZvciBkYXRlIHJhbmdlXG4gICAgICAgIGNvbnN0IHN0YXJ0RGF0ZSA9IG5ldyBEYXRlKHZpc2libGVEYXRlc1swXSk7XG4gICAgICAgIGNvbnN0IGVuZERhdGUgPSBuZXcgRGF0ZSh2aXNpYmxlRGF0ZXNbdmlzaWJsZURhdGVzLmxlbmd0aCAtIDFdKTtcbiAgICAgICAgZW5kRGF0ZS5zZXRIb3VycygyMywgNTksIDU5LCA5OTkpO1xuICAgICAgICBjb25zdCBldmVudHMgPSBhd2FpdCB0aGlzLmV2ZW50U2VydmljZS5nZXRCeURhdGVSYW5nZShzdGFydERhdGUsIGVuZERhdGUpO1xuICAgICAgICAvLyBGaWx0ZXIgdG8gYWxsRGF5IGV2ZW50cyBvbmx5IChhbGxEYXkgIT09IGZhbHNlKVxuICAgICAgICBjb25zdCBhbGxEYXlFdmVudHMgPSBldmVudHMuZmlsdGVyKGV2ZW50ID0+IGV2ZW50LmFsbERheSAhPT0gZmFsc2UpO1xuICAgICAgICAvLyBDbGVhciBleGlzdGluZyBpdGVtc1xuICAgICAgICBkcmF3ZXIuaW5uZXJIVE1MID0gJyc7XG4gICAgICAgIGlmIChhbGxEYXlFdmVudHMubGVuZ3RoID09PSAwKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAvLyBDYWxjdWxhdGUgbGF5b3V0IHdpdGggcm93IHN0YWNraW5nIHVzaW5nIGNvbHVtbktleXNcbiAgICAgICAgY29uc3QgbGF5b3V0cyA9IHRoaXMuY2FsY3VsYXRlTGF5b3V0KGFsbERheUV2ZW50cywgdmlzaWJsZUNvbHVtbktleXMpO1xuICAgICAgICBjb25zdCByb3dDb3VudCA9IE1hdGgubWF4KDEsIC4uLmxheW91dHMubWFwKGwgPT4gbC5yb3cpKTtcbiAgICAgICAgLy8gUmVuZGVyIGVhY2ggaXRlbSB3aXRoIGxheW91dFxuICAgICAgICBsYXlvdXRzLmZvckVhY2gobGF5b3V0ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGl0ZW0gPSB0aGlzLmNyZWF0ZUhlYWRlckl0ZW0obGF5b3V0KTtcbiAgICAgICAgICAgIGRyYXdlci5hcHBlbmRDaGlsZChpdGVtKTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIEV4cGFuZCBkcmF3ZXIgdG8gZml0IGFsbCByb3dzXG4gICAgICAgIHRoaXMuaGVhZGVyRHJhd2VyTWFuYWdlci5leHBhbmRUb1Jvd3Mocm93Q291bnQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgYSBoZWFkZXIgaXRlbSBlbGVtZW50IGZyb20gbGF5b3V0XG4gICAgICovXG4gICAgY3JlYXRlSGVhZGVySXRlbShsYXlvdXQpIHtcbiAgICAgICAgY29uc3QgeyBldmVudCwgY29sdW1uS2V5LCByb3csIGNvbFN0YXJ0LCBjb2xFbmQgfSA9IGxheW91dDtcbiAgICAgICAgY29uc3QgaXRlbSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3N3cC1oZWFkZXItaXRlbScpO1xuICAgICAgICBpdGVtLmRhdGFzZXQuZXZlbnRJZCA9IGV2ZW50LmlkO1xuICAgICAgICBpdGVtLmRhdGFzZXQuaXRlbVR5cGUgPSAnZXZlbnQnO1xuICAgICAgICBpdGVtLmRhdGFzZXQuc3RhcnQgPSBldmVudC5zdGFydC50b0lTT1N0cmluZygpO1xuICAgICAgICBpdGVtLmRhdGFzZXQuZW5kID0gZXZlbnQuZW5kLnRvSVNPU3RyaW5nKCk7XG4gICAgICAgIGl0ZW0uZGF0YXNldC5jb2x1bW5LZXkgPSBjb2x1bW5LZXk7XG4gICAgICAgIGl0ZW0udGV4dENvbnRlbnQgPSBldmVudC50aXRsZTtcbiAgICAgICAgLy8gQ29sb3IgY2xhc3NcbiAgICAgICAgY29uc3QgY29sb3JDbGFzcyA9IHRoaXMuZ2V0Q29sb3JDbGFzcyhldmVudCk7XG4gICAgICAgIGlmIChjb2xvckNsYXNzKVxuICAgICAgICAgICAgaXRlbS5jbGFzc0xpc3QuYWRkKGNvbG9yQ2xhc3MpO1xuICAgICAgICAvLyBHcmlkIHBvc2l0aW9uIGZyb20gbGF5b3V0XG4gICAgICAgIGl0ZW0uc3R5bGUuZ3JpZEFyZWEgPSBgJHtyb3d9IC8gJHtjb2xTdGFydH0gLyAke3JvdyArIDF9IC8gJHtjb2xFbmR9YDtcbiAgICAgICAgcmV0dXJuIGl0ZW07XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZSBsYXlvdXQgZm9yIGFsbCBldmVudHMgd2l0aCByb3cgc3RhY2tpbmdcbiAgICAgKiBVc2VzIHRyYWNrLWJhc2VkIGFsZ29yaXRobSB0byBmaW5kIGF2YWlsYWJsZSByb3dzIGZvciBvdmVybGFwcGluZyBldmVudHNcbiAgICAgKi9cbiAgICBjYWxjdWxhdGVMYXlvdXQoZXZlbnRzLCB2aXNpYmxlQ29sdW1uS2V5cykge1xuICAgICAgICAvLyB0cmFja3Nbcm93XVtjb2xdID0gb2NjdXBpZWRcbiAgICAgICAgY29uc3QgdHJhY2tzID0gW25ldyBBcnJheSh2aXNpYmxlQ29sdW1uS2V5cy5sZW5ndGgpLmZpbGwoZmFsc2UpXTtcbiAgICAgICAgY29uc3QgbGF5b3V0cyA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IGV2ZW50IG9mIGV2ZW50cykge1xuICAgICAgICAgICAgLy8gQnVpbGQgY29sdW1uS2V5IGZyb20gZXZlbnQgZmllbGRzIChvbmx5IHBsYWNlIHdlIG5lZWQgdG8gY29uc3RydWN0IGl0KVxuICAgICAgICAgICAgY29uc3QgY29sdW1uS2V5ID0gdGhpcy5idWlsZENvbHVtbktleUZyb21FdmVudChldmVudCk7XG4gICAgICAgICAgICBjb25zdCBzdGFydENvbCA9IHZpc2libGVDb2x1bW5LZXlzLmluZGV4T2YoY29sdW1uS2V5KTtcbiAgICAgICAgICAgIGNvbnN0IGVuZENvbHVtbktleSA9IHRoaXMuYnVpbGRDb2x1bW5LZXlGcm9tRXZlbnQoZXZlbnQsIGV2ZW50LmVuZCk7XG4gICAgICAgICAgICBjb25zdCBlbmRDb2wgPSB2aXNpYmxlQ29sdW1uS2V5cy5pbmRleE9mKGVuZENvbHVtbktleSk7XG4gICAgICAgICAgICBpZiAoc3RhcnRDb2wgPT09IC0xICYmIGVuZENvbCA9PT0gLTEpXG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAvLyBDbGFtcCB0aWwgc3lubGlnZSBrb2xvbm5lclxuICAgICAgICAgICAgY29uc3QgY29sU3RhcnQgPSBNYXRoLm1heCgwLCBzdGFydENvbCk7XG4gICAgICAgICAgICBjb25zdCBjb2xFbmQgPSAoZW5kQ29sICE9PSAtMSA/IGVuZENvbCA6IHZpc2libGVDb2x1bW5LZXlzLmxlbmd0aCAtIDEpICsgMTtcbiAgICAgICAgICAgIC8vIEZpbmQgbGVkaWcgclx1MDBFNmtrZVxuICAgICAgICAgICAgY29uc3Qgcm93ID0gdGhpcy5maW5kQXZhaWxhYmxlUm93KHRyYWNrcywgY29sU3RhcnQsIGNvbEVuZCk7XG4gICAgICAgICAgICAvLyBNYXJrZXIgc29tIG9wdGFnZXRcbiAgICAgICAgICAgIGZvciAobGV0IGMgPSBjb2xTdGFydDsgYyA8IGNvbEVuZDsgYysrKSB7XG4gICAgICAgICAgICAgICAgdHJhY2tzW3Jvd11bY10gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGF5b3V0cy5wdXNoKHsgZXZlbnQsIGNvbHVtbktleSwgcm93OiByb3cgKyAxLCBjb2xTdGFydDogY29sU3RhcnQgKyAxLCBjb2xFbmQ6IGNvbEVuZCArIDEgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxheW91dHM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEJ1aWxkIGNvbHVtbktleSBmcm9tIGV2ZW50IHVzaW5nIEZpbHRlclRlbXBsYXRlXG4gICAgICogVXNlcyB0aGUgc2FtZSB0ZW1wbGF0ZSB0aGF0IGNvbHVtbnMgdXNlIGZvciBtYXRjaGluZ1xuICAgICAqL1xuICAgIGJ1aWxkQ29sdW1uS2V5RnJvbUV2ZW50KGV2ZW50LCBkYXRlKSB7XG4gICAgICAgIGlmICghdGhpcy5maWx0ZXJUZW1wbGF0ZSkge1xuICAgICAgICAgICAgLy8gRmFsbGJhY2sgaWYgbm8gdGVtcGxhdGUgLSBzaG91bGRuJ3QgaGFwcGVuIGluIG5vcm1hbCBmbG93XG4gICAgICAgICAgICBjb25zdCBkYXRlU3RyID0gdGhpcy5kYXRlU2VydmljZS5nZXREYXRlS2V5KGRhdGUgfHwgZXZlbnQuc3RhcnQpO1xuICAgICAgICAgICAgcmV0dXJuIGRhdGVTdHI7XG4gICAgICAgIH1cbiAgICAgICAgLy8gRm9yIG11bHRpLWRheSBldmVudHMsIHdlIG5lZWQgdG8gb3ZlcnJpZGUgdGhlIGRhdGUgaW4gdGhlIGV2ZW50XG4gICAgICAgIGlmIChkYXRlICYmIGRhdGUuZ2V0VGltZSgpICE9PSBldmVudC5zdGFydC5nZXRUaW1lKCkpIHtcbiAgICAgICAgICAgIC8vIENyZWF0ZSB0ZW1wb3JhcnkgZXZlbnQgd2l0aCBvdmVycmlkZGVuIHN0YXJ0IGZvciBrZXkgZ2VuZXJhdGlvblxuICAgICAgICAgICAgY29uc3QgdGVtcEV2ZW50ID0geyAuLi5ldmVudCwgc3RhcnQ6IGRhdGUgfTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZpbHRlclRlbXBsYXRlLmJ1aWxkS2V5RnJvbUV2ZW50KHRlbXBFdmVudCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZmlsdGVyVGVtcGxhdGUuYnVpbGRLZXlGcm9tRXZlbnQoZXZlbnQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBGaW5kIGF2YWlsYWJsZSByb3cgZm9yIGV2ZW50IHNwYW5uaW5nIGNvbHVtbnMgW2NvbFN0YXJ0LCBjb2xFbmQpXG4gICAgICovXG4gICAgZmluZEF2YWlsYWJsZVJvdyh0cmFja3MsIGNvbFN0YXJ0LCBjb2xFbmQpIHtcbiAgICAgICAgZm9yIChsZXQgcm93ID0gMDsgcm93IDwgdHJhY2tzLmxlbmd0aDsgcm93KyspIHtcbiAgICAgICAgICAgIGxldCBhdmFpbGFibGUgPSB0cnVlO1xuICAgICAgICAgICAgZm9yIChsZXQgYyA9IGNvbFN0YXJ0OyBjIDwgY29sRW5kOyBjKyspIHtcbiAgICAgICAgICAgICAgICBpZiAodHJhY2tzW3Jvd11bY10pIHtcbiAgICAgICAgICAgICAgICAgICAgYXZhaWxhYmxlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChhdmFpbGFibGUpXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvdztcbiAgICAgICAgfVxuICAgICAgICAvLyBOeSByXHUwMEU2a2tlXG4gICAgICAgIHRyYWNrcy5wdXNoKG5ldyBBcnJheSh0cmFja3NbMF0ubGVuZ3RoKS5maWxsKGZhbHNlKSk7XG4gICAgICAgIHJldHVybiB0cmFja3MubGVuZ3RoIC0gMTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGNvbG9yIGNsYXNzIGJhc2VkIG9uIGV2ZW50IG1ldGFkYXRhIG9yIHR5cGVcbiAgICAgKi9cbiAgICBnZXRDb2xvckNsYXNzKGV2ZW50KSB7XG4gICAgICAgIGlmIChldmVudC5tZXRhZGF0YT8uY29sb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBgaXMtJHtldmVudC5tZXRhZGF0YS5jb2xvcn1gO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHR5cGVDb2xvcnMgPSB7XG4gICAgICAgICAgICAnY3VzdG9tZXInOiAnaXMtYmx1ZScsXG4gICAgICAgICAgICAndmFjYXRpb24nOiAnaXMtZ3JlZW4nLFxuICAgICAgICAgICAgJ2JyZWFrJzogJ2lzLWFtYmVyJyxcbiAgICAgICAgICAgICdtZWV0aW5nJzogJ2lzLXB1cnBsZScsXG4gICAgICAgICAgICAnYmxvY2tlZCc6ICdpcy1yZWQnXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiB0eXBlQ29sb3JzW2V2ZW50LnR5cGVdIHx8ICdpcy1ibHVlJztcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2V0dXAgZXZlbnQgbGlzdGVuZXJzIGZvciBkcmFnIGV2ZW50c1xuICAgICAqL1xuICAgIHNldHVwTGlzdGVuZXJzKCkge1xuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENvcmVFdmVudHMuRVZFTlRfRFJBR19FTlRFUl9IRUFERVIsIChlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwYXlsb2FkID0gZS5kZXRhaWw7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZURyYWdFbnRlcihwYXlsb2FkKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMub24oQ29yZUV2ZW50cy5FVkVOVF9EUkFHX01PVkVfSEVBREVSLCAoZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IGUuZGV0YWlsO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVEcmFnTW92ZShwYXlsb2FkKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMub24oQ29yZUV2ZW50cy5FVkVOVF9EUkFHX0xFQVZFX0hFQURFUiwgKGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSBlLmRldGFpbDtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlRHJhZ0xlYXZlKHBheWxvYWQpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5ldmVudEJ1cy5vbihDb3JlRXZlbnRzLkVWRU5UX0RSQUdfRU5ELCAoZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IGUuZGV0YWlsO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVEcmFnRW5kKHBheWxvYWQpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5ldmVudEJ1cy5vbihDb3JlRXZlbnRzLkVWRU5UX0RSQUdfQ0FOQ0VMLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNsZWFudXAoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEhhbmRsZSBkcmFnIGVudGVyaW5nIGhlYWRlciB6b25lIC0gY3JlYXRlIHByZXZpZXcgaXRlbVxuICAgICAqL1xuICAgIGhhbmRsZURyYWdFbnRlcihwYXlsb2FkKSB7XG4gICAgICAgIHRoaXMuY29udGFpbmVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcignc3dwLWhlYWRlci1kcmF3ZXInKTtcbiAgICAgICAgaWYgKCF0aGlzLmNvbnRhaW5lcilcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgLy8gUmVtZW1iZXIgaWYgZHJhd2VyIHdhcyBhbHJlYWR5IGV4cGFuZGVkXG4gICAgICAgIHRoaXMud2FzRXhwYW5kZWRCZWZvcmVEcmFnID0gdGhpcy5oZWFkZXJEcmF3ZXJNYW5hZ2VyLmlzRXhwYW5kZWQoKTtcbiAgICAgICAgLy8gRXhwYW5kIHRvIGF0IGxlYXN0IDEgcm93IGlmIGNvbGxhcHNlZCwgb3RoZXJ3aXNlIGtlZXAgY3VycmVudCBoZWlnaHRcbiAgICAgICAgaWYgKCF0aGlzLndhc0V4cGFuZGVkQmVmb3JlRHJhZykge1xuICAgICAgICAgICAgdGhpcy5oZWFkZXJEcmF3ZXJNYW5hZ2VyLmV4cGFuZFRvUm93cygxKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBTdG9yZSByZWZlcmVuY2UgdG8gc291cmNlIGVsZW1lbnRcbiAgICAgICAgdGhpcy5zb3VyY2VFbGVtZW50ID0gcGF5bG9hZC5lbGVtZW50O1xuICAgICAgICAvLyBDcmVhdGUgaGVhZGVyIGl0ZW1cbiAgICAgICAgY29uc3QgaXRlbSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3N3cC1oZWFkZXItaXRlbScpO1xuICAgICAgICBpdGVtLmRhdGFzZXQuZXZlbnRJZCA9IHBheWxvYWQuZXZlbnRJZDtcbiAgICAgICAgaXRlbS5kYXRhc2V0Lml0ZW1UeXBlID0gcGF5bG9hZC5pdGVtVHlwZTtcbiAgICAgICAgaXRlbS5kYXRhc2V0LmR1cmF0aW9uID0gU3RyaW5nKHBheWxvYWQuZHVyYXRpb24pO1xuICAgICAgICBpdGVtLmRhdGFzZXQuY29sdW1uS2V5ID0gcGF5bG9hZC5zb3VyY2VDb2x1bW5LZXk7XG4gICAgICAgIGl0ZW0udGV4dENvbnRlbnQgPSBwYXlsb2FkLnRpdGxlO1xuICAgICAgICAvLyBBcHBseSBjb2xvciBjbGFzcyBpZiBwcmVzZW50XG4gICAgICAgIGlmIChwYXlsb2FkLmNvbG9yQ2xhc3MpIHtcbiAgICAgICAgICAgIGl0ZW0uY2xhc3NMaXN0LmFkZChwYXlsb2FkLmNvbG9yQ2xhc3MpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEFkZCBkcmFnZ2luZyBzdGF0ZVxuICAgICAgICBpdGVtLmNsYXNzTGlzdC5hZGQoJ2RyYWdnaW5nJyk7XG4gICAgICAgIC8vIEluaXRpYWwgcGxhY2VtZW50IChkdXJhdGlvbiBkZXRlcm1pbmVzIGNvbHVtbiBzcGFuKVxuICAgICAgICAvLyBncmlkQXJlYSBmb3JtYXQ6IFwicm93IC8gY29sLXN0YXJ0IC8gcm93KzEgLyBjb2wtZW5kXCJcbiAgICAgICAgY29uc3QgY29sID0gcGF5bG9hZC5zb3VyY2VDb2x1bW5JbmRleCArIDE7XG4gICAgICAgIGNvbnN0IGVuZENvbCA9IGNvbCArIHBheWxvYWQuZHVyYXRpb247XG4gICAgICAgIGl0ZW0uc3R5bGUuZ3JpZEFyZWEgPSBgMSAvICR7Y29sfSAvIDIgLyAke2VuZENvbH1gO1xuICAgICAgICB0aGlzLmNvbnRhaW5lci5hcHBlbmRDaGlsZChpdGVtKTtcbiAgICAgICAgdGhpcy5jdXJyZW50SXRlbSA9IGl0ZW07XG4gICAgICAgIC8vIEhpZGUgb3JpZ2luYWwgZWxlbWVudCB3aGlsZSBpbiBoZWFkZXJcbiAgICAgICAgcGF5bG9hZC5lbGVtZW50LnN0eWxlLnZpc2liaWxpdHkgPSAnaGlkZGVuJztcbiAgICB9XG4gICAgLyoqXG4gICAgICogSGFuZGxlIGRyYWcgbW92aW5nIHdpdGhpbiBoZWFkZXIgLSB1cGRhdGUgY29sdW1uIHBvc2l0aW9uXG4gICAgICovXG4gICAgaGFuZGxlRHJhZ01vdmUocGF5bG9hZCkge1xuICAgICAgICBpZiAoIXRoaXMuY3VycmVudEl0ZW0pXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIC8vIFVwZGF0ZSBjb2x1bW4gcG9zaXRpb25cbiAgICAgICAgY29uc3QgY29sID0gcGF5bG9hZC5jb2x1bW5JbmRleCArIDE7XG4gICAgICAgIGNvbnN0IGR1cmF0aW9uID0gcGFyc2VJbnQodGhpcy5jdXJyZW50SXRlbS5kYXRhc2V0LmR1cmF0aW9uIHx8ICcxJywgMTApO1xuICAgICAgICBjb25zdCBlbmRDb2wgPSBjb2wgKyBkdXJhdGlvbjtcbiAgICAgICAgdGhpcy5jdXJyZW50SXRlbS5zdHlsZS5ncmlkQXJlYSA9IGAxIC8gJHtjb2x9IC8gMiAvICR7ZW5kQ29sfWA7XG4gICAgICAgIC8vIFVwZGF0ZSBjb2x1bW5LZXkgdG8gbmV3IHBvc2l0aW9uXG4gICAgICAgIHRoaXMuY3VycmVudEl0ZW0uZGF0YXNldC5jb2x1bW5LZXkgPSBwYXlsb2FkLmNvbHVtbktleTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSGFuZGxlIGRyYWcgbGVhdmluZyBoZWFkZXIgLSBjbGVhbnVwIGZvciBncmlkXHUyMTkyaGVhZGVyIGRyYWcgb25seVxuICAgICAqL1xuICAgIGhhbmRsZURyYWdMZWF2ZShwYXlsb2FkKSB7XG4gICAgICAgIC8vIE9ubHkgY2xlYW51cCBmb3IgZ3JpZFx1MjE5MmhlYWRlciBkcmFnICh3aGVuIGdyaWQgZXZlbnQgbGVhdmVzIGhlYWRlciBiYWNrIHRvIGdyaWQpXG4gICAgICAgIC8vIEZvciBoZWFkZXJcdTIxOTJncmlkIGRyYWcsIHRoZSBoZWFkZXIgaXRlbSBzdGF5cyBhcyBnaG9zdCB1bnRpbCBkcm9wXG4gICAgICAgIGlmIChwYXlsb2FkLnNvdXJjZSA9PT0gJ2dyaWQnKSB7XG4gICAgICAgICAgICB0aGlzLmNsZWFudXAoKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBGb3IgaGVhZGVyIHNvdXJjZSwgZG8gbm90aGluZyAtIGdob3N0IHN0YXlzIHVudGlsIEVWRU5UX0RSQUdfRU5EXG4gICAgfVxuICAgIC8qKlxuICAgICAqIEhhbmRsZSBkcmFnIGVuZCAtIGZpbmFsaXplIGJhc2VkIG9uIGRyb3AgdGFyZ2V0XG4gICAgICovXG4gICAgaGFuZGxlRHJhZ0VuZChwYXlsb2FkKSB7XG4gICAgICAgIGlmIChwYXlsb2FkLnRhcmdldCA9PT0gJ2hlYWRlcicpIHtcbiAgICAgICAgICAgIC8vIEdyaWRcdTIxOTJIZWFkZXI6IEZpbmFsaXplIHRoZSBoZWFkZXIgaXRlbSAoaXQgc3RheXMgaW4gaGVhZGVyKVxuICAgICAgICAgICAgaWYgKHRoaXMuY3VycmVudEl0ZW0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRJdGVtLmNsYXNzTGlzdC5yZW1vdmUoJ2RyYWdnaW5nJyk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWNhbGN1bGF0ZURyYXdlckxheW91dCgpO1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudEl0ZW0gPSBudWxsO1xuICAgICAgICAgICAgICAgIHRoaXMuc291cmNlRWxlbWVudCA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBIZWFkZXJcdTIxOTJHcmlkOiBSZW1vdmUgZ2hvc3QgaGVhZGVyIGl0ZW0gYW5kIHJlY2FsY3VsYXRlXG4gICAgICAgICAgICBjb25zdCBnaG9zdCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYHN3cC1oZWFkZXItaXRlbS5kcmFnLWdob3N0W2RhdGEtZXZlbnQtaWQ9XCIke3BheWxvYWQuc3dwRXZlbnQuZXZlbnRJZH1cIl1gKTtcbiAgICAgICAgICAgIGdob3N0Py5yZW1vdmUoKTtcbiAgICAgICAgICAgIHRoaXMucmVjYWxjdWxhdGVEcmF3ZXJMYXlvdXQoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWNhbGN1bGF0ZSBsYXlvdXQgZm9yIGFsbCBpdGVtcyBjdXJyZW50bHkgaW4gdGhlIGRyYXdlclxuICAgICAqIENhbGxlZCBhZnRlciBkcm9wIHRvIHJlcG9zaXRpb24gaXRlbXMgYW5kIGFkanVzdCBoZWlnaHRcbiAgICAgKi9cbiAgICByZWNhbGN1bGF0ZURyYXdlckxheW91dCgpIHtcbiAgICAgICAgY29uc3QgZHJhd2VyID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcignc3dwLWhlYWRlci1kcmF3ZXInKTtcbiAgICAgICAgaWYgKCFkcmF3ZXIpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNvbnN0IGl0ZW1zID0gQXJyYXkuZnJvbShkcmF3ZXIucXVlcnlTZWxlY3RvckFsbCgnc3dwLWhlYWRlci1pdGVtJykpO1xuICAgICAgICBpZiAoaXRlbXMubGVuZ3RoID09PSAwKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAvLyBHZXQgdmlzaWJsZSBjb2x1bW4ga2V5cyBmb3IgY29ycmVjdCBtdWx0aS1yZXNvdXJjZSBwb3NpdGlvbmluZ1xuICAgICAgICBjb25zdCB2aXNpYmxlQ29sdW1uS2V5cyA9IHRoaXMuZ2V0VmlzaWJsZUNvbHVtbktleXNGcm9tRE9NKCk7XG4gICAgICAgIGlmICh2aXNpYmxlQ29sdW1uS2V5cy5sZW5ndGggPT09IDApXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIC8vIEJ1aWxkIGxheW91dCBkYXRhIGZyb20gRE9NIGl0ZW1zIC0gdXNlIGNvbHVtbktleSBkaXJlY3RseSAob3BhcXVlIG1hdGNoaW5nKVxuICAgICAgICBjb25zdCBpdGVtRGF0YSA9IGl0ZW1zLm1hcChpdGVtID0+ICh7XG4gICAgICAgICAgICBlbGVtZW50OiBpdGVtLFxuICAgICAgICAgICAgY29sdW1uS2V5OiBpdGVtLmRhdGFzZXQuY29sdW1uS2V5IHx8ICcnLFxuICAgICAgICAgICAgZHVyYXRpb246IHBhcnNlSW50KGl0ZW0uZGF0YXNldC5kdXJhdGlvbiB8fCAnMScsIDEwKVxuICAgICAgICB9KSk7XG4gICAgICAgIC8vIENhbGN1bGF0ZSBuZXcgbGF5b3V0IHVzaW5nIHRyYWNrIGFsZ29yaXRobVxuICAgICAgICBjb25zdCB0cmFja3MgPSBbbmV3IEFycmF5KHZpc2libGVDb2x1bW5LZXlzLmxlbmd0aCkuZmlsbChmYWxzZSldO1xuICAgICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgaXRlbURhdGEpIHtcbiAgICAgICAgICAgIC8vIERpcmVjdCBjb2x1bW5LZXkgbWF0Y2hpbmcgLSBubyBwYXJzaW5nIG9yIGNvbnN0cnVjdGlvbiBuZWVkZWRcbiAgICAgICAgICAgIGNvbnN0IHN0YXJ0Q29sID0gdmlzaWJsZUNvbHVtbktleXMuaW5kZXhPZihpdGVtLmNvbHVtbktleSk7XG4gICAgICAgICAgICBpZiAoc3RhcnRDb2wgPT09IC0xKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgY29uc3QgY29sU3RhcnQgPSBzdGFydENvbDtcbiAgICAgICAgICAgIGNvbnN0IGNvbEVuZCA9IE1hdGgubWluKHN0YXJ0Q29sICsgaXRlbS5kdXJhdGlvbiwgdmlzaWJsZUNvbHVtbktleXMubGVuZ3RoKTtcbiAgICAgICAgICAgIGNvbnN0IHJvdyA9IHRoaXMuZmluZEF2YWlsYWJsZVJvdyh0cmFja3MsIGNvbFN0YXJ0LCBjb2xFbmQpO1xuICAgICAgICAgICAgZm9yIChsZXQgYyA9IGNvbFN0YXJ0OyBjIDwgY29sRW5kOyBjKyspIHtcbiAgICAgICAgICAgICAgICB0cmFja3Nbcm93XVtjXSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBVcGRhdGUgZWxlbWVudCBwb3NpdGlvblxuICAgICAgICAgICAgaXRlbS5lbGVtZW50LnN0eWxlLmdyaWRBcmVhID0gYCR7cm93ICsgMX0gLyAke2NvbFN0YXJ0ICsgMX0gLyAke3JvdyArIDJ9IC8gJHtjb2xFbmQgKyAxfWA7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVXBkYXRlIGRyYXdlciBoZWlnaHRcbiAgICAgICAgY29uc3Qgcm93Q291bnQgPSB0cmFja3MubGVuZ3RoO1xuICAgICAgICB0aGlzLmhlYWRlckRyYXdlck1hbmFnZXIuZXhwYW5kVG9Sb3dzKHJvd0NvdW50KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IHZpc2libGUgY29sdW1uIGtleXMgZnJvbSBET00gKHByZXNlcnZlcyBvcmRlciBmb3IgbXVsdGktcmVzb3VyY2Ugdmlld3MpXG4gICAgICogVXNlcyBmaWx0ZXJUZW1wbGF0ZS5idWlsZEtleUZyb21Db2x1bW4oKSBmb3IgY29uc2lzdGVudCBrZXkgZm9ybWF0IHdpdGggZXZlbnRzXG4gICAgICovXG4gICAgZ2V0VmlzaWJsZUNvbHVtbktleXNGcm9tRE9NKCkge1xuICAgICAgICBpZiAoIXRoaXMuZmlsdGVyVGVtcGxhdGUpXG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIGNvbnN0IGNvbHVtbnMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdzd3AtZGF5LWNvbHVtbicpO1xuICAgICAgICBjb25zdCBjb2x1bW5LZXlzID0gW107XG4gICAgICAgIGNvbHVtbnMuZm9yRWFjaChjb2wgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29sdW1uS2V5ID0gdGhpcy5maWx0ZXJUZW1wbGF0ZS5idWlsZEtleUZyb21Db2x1bW4oY29sKTtcbiAgICAgICAgICAgIGlmIChjb2x1bW5LZXkpXG4gICAgICAgICAgICAgICAgY29sdW1uS2V5cy5wdXNoKGNvbHVtbktleSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gY29sdW1uS2V5cztcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ2xlYW51cCBwcmV2aWV3IGl0ZW0gYW5kIHJlc3RvcmUgc291cmNlIHZpc2liaWxpdHlcbiAgICAgKi9cbiAgICBjbGVhbnVwKCkge1xuICAgICAgICAvLyBSZW1vdmUgcHJldmlldyBpdGVtXG4gICAgICAgIHRoaXMuY3VycmVudEl0ZW0/LnJlbW92ZSgpO1xuICAgICAgICB0aGlzLmN1cnJlbnRJdGVtID0gbnVsbDtcbiAgICAgICAgLy8gUmVzdG9yZSBzb3VyY2UgZWxlbWVudCB2aXNpYmlsaXR5XG4gICAgICAgIGlmICh0aGlzLnNvdXJjZUVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRoaXMuc291cmNlRWxlbWVudC5zdHlsZS52aXNpYmlsaXR5ID0gJyc7XG4gICAgICAgICAgICB0aGlzLnNvdXJjZUVsZW1lbnQgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIC8vIENvbGxhcHNlIGRyYXdlciBpZiBpdCB3YXNuJ3QgZXhwYW5kZWQgYmVmb3JlIGRyYWdcbiAgICAgICAgaWYgKCF0aGlzLndhc0V4cGFuZGVkQmVmb3JlRHJhZykge1xuICAgICAgICAgICAgdGhpcy5oZWFkZXJEcmF3ZXJNYW5hZ2VyLmNvbGxhcHNlKCk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCAiLyoqXG4gKiBTY2hlZHVsZU92ZXJyaWRlU3RvcmUgLSBJbmRleGVkREIgT2JqZWN0U3RvcmUgZm9yIHNjaGVkdWxlIG92ZXJyaWRlc1xuICpcbiAqIFN0b3JlcyBkYXRlLXNwZWNpZmljIHNjaGVkdWxlIG92ZXJyaWRlcyBmb3IgcmVzb3VyY2VzLlxuICogSW5kZXhlczogcmVzb3VyY2VJZCwgZGF0ZSwgY29tcG91bmQgKHJlc291cmNlSWQgKyBkYXRlKVxuICovXG5leHBvcnQgY2xhc3MgU2NoZWR1bGVPdmVycmlkZVN0b3JlIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5zdG9yZU5hbWUgPSBTY2hlZHVsZU92ZXJyaWRlU3RvcmUuU1RPUkVfTkFNRTtcbiAgICB9XG4gICAgY3JlYXRlKGRiKSB7XG4gICAgICAgIGNvbnN0IHN0b3JlID0gZGIuY3JlYXRlT2JqZWN0U3RvcmUoU2NoZWR1bGVPdmVycmlkZVN0b3JlLlNUT1JFX05BTUUsIHsga2V5UGF0aDogJ2lkJyB9KTtcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ3Jlc291cmNlSWQnLCAncmVzb3VyY2VJZCcsIHsgdW5pcXVlOiBmYWxzZSB9KTtcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ2RhdGUnLCAnZGF0ZScsIHsgdW5pcXVlOiBmYWxzZSB9KTtcbiAgICAgICAgc3RvcmUuY3JlYXRlSW5kZXgoJ3Jlc291cmNlSWRfZGF0ZScsIFsncmVzb3VyY2VJZCcsICdkYXRlJ10sIHsgdW5pcXVlOiB0cnVlIH0pO1xuICAgICAgICBzdG9yZS5jcmVhdGVJbmRleCgnc3luY1N0YXR1cycsICdzeW5jU3RhdHVzJywgeyB1bmlxdWU6IGZhbHNlIH0pO1xuICAgIH1cbn1cblNjaGVkdWxlT3ZlcnJpZGVTdG9yZS5TVE9SRV9OQU1FID0gJ3NjaGVkdWxlT3ZlcnJpZGVzJztcbiIsICJpbXBvcnQgeyBTY2hlZHVsZU92ZXJyaWRlU3RvcmUgfSBmcm9tICcuL1NjaGVkdWxlT3ZlcnJpZGVTdG9yZSc7XG4vKipcbiAqIFNjaGVkdWxlT3ZlcnJpZGVTZXJ2aWNlIC0gQ1JVRCBmb3Igc2NoZWR1bGUgb3ZlcnJpZGVzXG4gKlxuICogUHJvdmlkZXMgYWNjZXNzIHRvIGRhdGUtc3BlY2lmaWMgc2NoZWR1bGUgb3ZlcnJpZGVzIGZvciByZXNvdXJjZXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBTY2hlZHVsZU92ZXJyaWRlU2VydmljZSB7XG4gICAgY29uc3RydWN0b3IoY29udGV4dCkge1xuICAgICAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xuICAgIH1cbiAgICBnZXQgZGIoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbnRleHQuZ2V0RGF0YWJhc2UoKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IG92ZXJyaWRlIGZvciBhIHNwZWNpZmljIHJlc291cmNlIGFuZCBkYXRlXG4gICAgICovXG4gICAgYXN5bmMgZ2V0T3ZlcnJpZGUocmVzb3VyY2VJZCwgZGF0ZSkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSB0aGlzLmRiLnRyYW5zYWN0aW9uKFtTY2hlZHVsZU92ZXJyaWRlU3RvcmUuU1RPUkVfTkFNRV0sICdyZWFkb25seScpO1xuICAgICAgICAgICAgY29uc3Qgc3RvcmUgPSB0cmFuc2FjdGlvbi5vYmplY3RTdG9yZShTY2hlZHVsZU92ZXJyaWRlU3RvcmUuU1RPUkVfTkFNRSk7XG4gICAgICAgICAgICBjb25zdCBpbmRleCA9IHN0b3JlLmluZGV4KCdyZXNvdXJjZUlkX2RhdGUnKTtcbiAgICAgICAgICAgIGNvbnN0IHJlcXVlc3QgPSBpbmRleC5nZXQoW3Jlc291cmNlSWQsIGRhdGVdKTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25zdWNjZXNzID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlc29sdmUocmVxdWVzdC5yZXN1bHQgfHwgbnVsbCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVxdWVzdC5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBnZXQgb3ZlcnJpZGUgZm9yICR7cmVzb3VyY2VJZH0gb24gJHtkYXRlfTogJHtyZXF1ZXN0LmVycm9yfWApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIG92ZXJyaWRlcyBmb3IgYSByZXNvdXJjZVxuICAgICAqL1xuICAgIGFzeW5jIGdldEJ5UmVzb3VyY2UocmVzb3VyY2VJZCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSB0aGlzLmRiLnRyYW5zYWN0aW9uKFtTY2hlZHVsZU92ZXJyaWRlU3RvcmUuU1RPUkVfTkFNRV0sICdyZWFkb25seScpO1xuICAgICAgICAgICAgY29uc3Qgc3RvcmUgPSB0cmFuc2FjdGlvbi5vYmplY3RTdG9yZShTY2hlZHVsZU92ZXJyaWRlU3RvcmUuU1RPUkVfTkFNRSk7XG4gICAgICAgICAgICBjb25zdCBpbmRleCA9IHN0b3JlLmluZGV4KCdyZXNvdXJjZUlkJyk7XG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gaW5kZXguZ2V0QWxsKHJlc291cmNlSWQpO1xuICAgICAgICAgICAgcmVxdWVzdC5vbnN1Y2Nlc3MgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShyZXF1ZXN0LnJlc3VsdCB8fCBbXSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVxdWVzdC5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBnZXQgb3ZlcnJpZGVzIGZvciAke3Jlc291cmNlSWR9OiAke3JlcXVlc3QuZXJyb3J9YCkpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBvdmVycmlkZXMgZm9yIGEgZGF0ZSByYW5nZVxuICAgICAqL1xuICAgIGFzeW5jIGdldEJ5RGF0ZVJhbmdlKHJlc291cmNlSWQsIHN0YXJ0RGF0ZSwgZW5kRGF0ZSkge1xuICAgICAgICBjb25zdCBhbGwgPSBhd2FpdCB0aGlzLmdldEJ5UmVzb3VyY2UocmVzb3VyY2VJZCk7XG4gICAgICAgIHJldHVybiBhbGwuZmlsdGVyKG8gPT4gby5kYXRlID49IHN0YXJ0RGF0ZSAmJiBvLmRhdGUgPD0gZW5kRGF0ZSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNhdmUgYW4gb3ZlcnJpZGVcbiAgICAgKi9cbiAgICBhc3luYyBzYXZlKG92ZXJyaWRlKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IHRoaXMuZGIudHJhbnNhY3Rpb24oW1NjaGVkdWxlT3ZlcnJpZGVTdG9yZS5TVE9SRV9OQU1FXSwgJ3JlYWR3cml0ZScpO1xuICAgICAgICAgICAgY29uc3Qgc3RvcmUgPSB0cmFuc2FjdGlvbi5vYmplY3RTdG9yZShTY2hlZHVsZU92ZXJyaWRlU3RvcmUuU1RPUkVfTkFNRSk7XG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gc3RvcmUucHV0KG92ZXJyaWRlKTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25zdWNjZXNzID0gKCkgPT4gcmVzb2x2ZSgpO1xuICAgICAgICAgICAgcmVxdWVzdC5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBzYXZlIG92ZXJyaWRlICR7b3ZlcnJpZGUuaWR9OiAke3JlcXVlc3QuZXJyb3J9YCkpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIERlbGV0ZSBhbiBvdmVycmlkZVxuICAgICAqL1xuICAgIGFzeW5jIGRlbGV0ZShpZCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSB0aGlzLmRiLnRyYW5zYWN0aW9uKFtTY2hlZHVsZU92ZXJyaWRlU3RvcmUuU1RPUkVfTkFNRV0sICdyZWFkd3JpdGUnKTtcbiAgICAgICAgICAgIGNvbnN0IHN0b3JlID0gdHJhbnNhY3Rpb24ub2JqZWN0U3RvcmUoU2NoZWR1bGVPdmVycmlkZVN0b3JlLlNUT1JFX05BTUUpO1xuICAgICAgICAgICAgY29uc3QgcmVxdWVzdCA9IHN0b3JlLmRlbGV0ZShpZCk7XG4gICAgICAgICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHJlc29sdmUoKTtcbiAgICAgICAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gZGVsZXRlIG92ZXJyaWRlICR7aWR9OiAke3JlcXVlc3QuZXJyb3J9YCkpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfVxufVxuIiwgIi8qKlxuICogUmVzb3VyY2VTY2hlZHVsZVNlcnZpY2UgLSBHZXQgZWZmZWN0aXZlIHNjaGVkdWxlIGZvciBhIHJlc291cmNlIG9uIGEgZGF0ZVxuICpcbiAqIExvZ2ljOlxuICogMS4gQ2hlY2sgZm9yIG92ZXJyaWRlIG9uIHRoaXMgZGF0ZVxuICogMi4gRmFsbCBiYWNrIHRvIGRlZmF1bHQgc2NoZWR1bGUgZm9yIHRoZSB3ZWVrZGF5XG4gKi9cbmV4cG9ydCBjbGFzcyBSZXNvdXJjZVNjaGVkdWxlU2VydmljZSB7XG4gICAgY29uc3RydWN0b3IocmVzb3VyY2VTZXJ2aWNlLCBvdmVycmlkZVNlcnZpY2UsIGRhdGVTZXJ2aWNlKSB7XG4gICAgICAgIHRoaXMucmVzb3VyY2VTZXJ2aWNlID0gcmVzb3VyY2VTZXJ2aWNlO1xuICAgICAgICB0aGlzLm92ZXJyaWRlU2VydmljZSA9IG92ZXJyaWRlU2VydmljZTtcbiAgICAgICAgdGhpcy5kYXRlU2VydmljZSA9IGRhdGVTZXJ2aWNlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgZWZmZWN0aXZlIHNjaGVkdWxlIGZvciBhIHJlc291cmNlIG9uIGEgc3BlY2lmaWMgZGF0ZVxuICAgICAqXG4gICAgICogQHBhcmFtIHJlc291cmNlSWQgLSBSZXNvdXJjZSBJRFxuICAgICAqIEBwYXJhbSBkYXRlIC0gRGF0ZSBzdHJpbmcgXCJZWVlZLU1NLUREXCJcbiAgICAgKiBAcmV0dXJucyBJVGltZVNsb3Qgb3IgbnVsbCAoZnJpL2Nsb3NlZClcbiAgICAgKi9cbiAgICBhc3luYyBnZXRTY2hlZHVsZUZvckRhdGUocmVzb3VyY2VJZCwgZGF0ZSkge1xuICAgICAgICAvLyAxLiBDaGVjayBmb3Igb3ZlcnJpZGVcbiAgICAgICAgY29uc3Qgb3ZlcnJpZGUgPSBhd2FpdCB0aGlzLm92ZXJyaWRlU2VydmljZS5nZXRPdmVycmlkZShyZXNvdXJjZUlkLCBkYXRlKTtcbiAgICAgICAgaWYgKG92ZXJyaWRlKSB7XG4gICAgICAgICAgICByZXR1cm4gb3ZlcnJpZGUuc2NoZWR1bGU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gMi4gVXNlIGRlZmF1bHQgc2NoZWR1bGUgZm9yIHdlZWtkYXlcbiAgICAgICAgY29uc3QgcmVzb3VyY2UgPSBhd2FpdCB0aGlzLnJlc291cmNlU2VydmljZS5nZXQocmVzb3VyY2VJZCk7XG4gICAgICAgIGlmICghcmVzb3VyY2UgfHwgIXJlc291cmNlLmRlZmF1bHRTY2hlZHVsZSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgd2Vla0RheSA9IHRoaXMuZGF0ZVNlcnZpY2UuZ2V0SVNPV2Vla0RheShkYXRlKTtcbiAgICAgICAgcmV0dXJuIHJlc291cmNlLmRlZmF1bHRTY2hlZHVsZVt3ZWVrRGF5XSB8fCBudWxsO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgc2NoZWR1bGVzIGZvciBtdWx0aXBsZSBkYXRlc1xuICAgICAqXG4gICAgICogQHBhcmFtIHJlc291cmNlSWQgLSBSZXNvdXJjZSBJRFxuICAgICAqIEBwYXJhbSBkYXRlcyAtIEFycmF5IG9mIGRhdGUgc3RyaW5ncyBcIllZWVktTU0tRERcIlxuICAgICAqIEByZXR1cm5zIE1hcCBvZiBkYXRlIC0+IElUaW1lU2xvdCB8IG51bGxcbiAgICAgKi9cbiAgICBhc3luYyBnZXRTY2hlZHVsZXNGb3JEYXRlcyhyZXNvdXJjZUlkLCBkYXRlcykge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBuZXcgTWFwKCk7XG4gICAgICAgIC8vIEdldCByZXNvdXJjZSBvbmNlXG4gICAgICAgIGNvbnN0IHJlc291cmNlID0gYXdhaXQgdGhpcy5yZXNvdXJjZVNlcnZpY2UuZ2V0KHJlc291cmNlSWQpO1xuICAgICAgICAvLyBHZXQgYWxsIG92ZXJyaWRlcyBpbiBkYXRlIHJhbmdlXG4gICAgICAgIGNvbnN0IG92ZXJyaWRlcyA9IGRhdGVzLmxlbmd0aCA+IDBcbiAgICAgICAgICAgID8gYXdhaXQgdGhpcy5vdmVycmlkZVNlcnZpY2UuZ2V0QnlEYXRlUmFuZ2UocmVzb3VyY2VJZCwgZGF0ZXNbMF0sIGRhdGVzW2RhdGVzLmxlbmd0aCAtIDFdKVxuICAgICAgICAgICAgOiBbXTtcbiAgICAgICAgLy8gQnVpbGQgb3ZlcnJpZGUgbWFwXG4gICAgICAgIGNvbnN0IG92ZXJyaWRlTWFwID0gbmV3IE1hcChvdmVycmlkZXMubWFwKG8gPT4gW28uZGF0ZSwgby5zY2hlZHVsZV0pKTtcbiAgICAgICAgLy8gUmVzb2x2ZSBlYWNoIGRhdGVcbiAgICAgICAgZm9yIChjb25zdCBkYXRlIG9mIGRhdGVzKSB7XG4gICAgICAgICAgICAvLyBDaGVjayBvdmVycmlkZSBmaXJzdFxuICAgICAgICAgICAgaWYgKG92ZXJyaWRlTWFwLmhhcyhkYXRlKSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5zZXQoZGF0ZSwgb3ZlcnJpZGVNYXAuZ2V0KGRhdGUpKTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEZhbGwgYmFjayB0byBkZWZhdWx0XG4gICAgICAgICAgICBpZiAocmVzb3VyY2U/LmRlZmF1bHRTY2hlZHVsZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHdlZWtEYXkgPSB0aGlzLmRhdGVTZXJ2aWNlLmdldElTT1dlZWtEYXkoZGF0ZSk7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnNldChkYXRlLCByZXNvdXJjZS5kZWZhdWx0U2NoZWR1bGVbd2Vla0RheV0gfHwgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQuc2V0KGRhdGUsIG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxufVxuIiwgIi8qKlxuICogU3dwRXZlbnQgLSBXcmFwcGVyIGNsYXNzIGZvciBjYWxlbmRhciBldmVudCBlbGVtZW50c1xuICpcbiAqIEVuY2Fwc3VsYXRlcyBhbiBIVE1MRWxlbWVudCBhbmQgcHJvdmlkZXMgY29tcHV0ZWQgcHJvcGVydGllc1xuICogZm9yIHN0YXJ0L2VuZCB0aW1lcyBiYXNlZCBvbiBlbGVtZW50IHBvc2l0aW9uIGFuZCBncmlkIGNvbmZpZy5cbiAqXG4gKiBVc2FnZTpcbiAqIC0gZXZlbnRJZCBpcyByZWFkIGZyb20gZWxlbWVudC5kYXRhc2V0XG4gKiAtIGNvbHVtbktleSBpZGVudGlmaWVzIHRoZSBjb2x1bW4gdW5pZm9ybWx5XG4gKiAtIFBvc2l0aW9uICh0b3AsIGhlaWdodCkgaXMgcmVhZCBmcm9tIGVsZW1lbnQuc3R5bGVcbiAqIC0gRmFjdG9yeSBtZXRob2QgYGZyb21FbGVtZW50KClgIGNhbGN1bGF0ZXMgRGF0ZSBvYmplY3RzXG4gKi9cbmV4cG9ydCBjbGFzcyBTd3BFdmVudCB7XG4gICAgY29uc3RydWN0b3IoZWxlbWVudCwgY29sdW1uS2V5LCBzdGFydCwgZW5kKSB7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgIHRoaXMuY29sdW1uS2V5ID0gY29sdW1uS2V5O1xuICAgICAgICB0aGlzLl9zdGFydCA9IHN0YXJ0O1xuICAgICAgICB0aGlzLl9lbmQgPSBlbmQ7XG4gICAgfVxuICAgIC8qKiBFdmVudCBJRCBmcm9tIGVsZW1lbnQuZGF0YXNldC5ldmVudElkICovXG4gICAgZ2V0IGV2ZW50SWQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVsZW1lbnQuZGF0YXNldC5ldmVudElkIHx8ICcnO1xuICAgIH1cbiAgICBnZXQgc3RhcnQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zdGFydDtcbiAgICB9XG4gICAgZ2V0IGVuZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VuZDtcbiAgICB9XG4gICAgLyoqIER1cmF0aW9uIGluIG1pbnV0ZXMgKi9cbiAgICBnZXQgZHVyYXRpb25NaW51dGVzKCkge1xuICAgICAgICByZXR1cm4gKHRoaXMuX2VuZC5nZXRUaW1lKCkgLSB0aGlzLl9zdGFydC5nZXRUaW1lKCkpIC8gKDEwMDAgKiA2MCk7XG4gICAgfVxuICAgIC8qKiBEdXJhdGlvbiBpbiBtaWxsaXNlY29uZHMgKi9cbiAgICBnZXQgZHVyYXRpb25NcygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VuZC5nZXRUaW1lKCkgLSB0aGlzLl9zdGFydC5nZXRUaW1lKCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEZhY3Rvcnk6IENyZWF0ZSBTd3BFdmVudCBmcm9tIGVsZW1lbnQgKyBjb2x1bW5LZXlcbiAgICAgKiBSZWFkcyB0b3AvaGVpZ2h0IGZyb20gZWxlbWVudC5zdHlsZSB0byBjYWxjdWxhdGUgc3RhcnQvZW5kXG4gICAgICogQHBhcmFtIGNvbHVtbktleSAtIE9wYXF1ZSBjb2x1bW4gaWRlbnRpZmllciAoZG8gTk9UIHBhcnNlIC0gdXNlIG9ubHkgZm9yIG1hdGNoaW5nKVxuICAgICAqIEBwYXJhbSBkYXRlIC0gRGF0ZSBzdHJpbmcgKFlZWVktTU0tREQpIGZvciB0aW1lIGNhbGN1bGF0aW9uc1xuICAgICAqL1xuICAgIHN0YXRpYyBmcm9tRWxlbWVudChlbGVtZW50LCBjb2x1bW5LZXksIGRhdGUsIGdyaWRDb25maWcpIHtcbiAgICAgICAgY29uc3QgdG9wUGl4ZWxzID0gcGFyc2VGbG9hdChlbGVtZW50LnN0eWxlLnRvcCkgfHwgMDtcbiAgICAgICAgY29uc3QgaGVpZ2h0UGl4ZWxzID0gcGFyc2VGbG9hdChlbGVtZW50LnN0eWxlLmhlaWdodCkgfHwgMDtcbiAgICAgICAgLy8gQ2FsY3VsYXRlIHN0YXJ0IGZyb20gdG9wIHBvc2l0aW9uXG4gICAgICAgIGNvbnN0IHN0YXJ0TWludXRlc0Zyb21HcmlkID0gKHRvcFBpeGVscyAvIGdyaWRDb25maWcuaG91ckhlaWdodCkgKiA2MDtcbiAgICAgICAgY29uc3QgdG90YWxNaW51dGVzID0gKGdyaWRDb25maWcuZGF5U3RhcnRIb3VyICogNjApICsgc3RhcnRNaW51dGVzRnJvbUdyaWQ7XG4gICAgICAgIGNvbnN0IHN0YXJ0ID0gbmV3IERhdGUoZGF0ZSk7XG4gICAgICAgIHN0YXJ0LnNldEhvdXJzKE1hdGguZmxvb3IodG90YWxNaW51dGVzIC8gNjApLCB0b3RhbE1pbnV0ZXMgJSA2MCwgMCwgMCk7XG4gICAgICAgIC8vIENhbGN1bGF0ZSBlbmQgZnJvbSBoZWlnaHRcbiAgICAgICAgY29uc3QgZHVyYXRpb25NaW51dGVzID0gKGhlaWdodFBpeGVscyAvIGdyaWRDb25maWcuaG91ckhlaWdodCkgKiA2MDtcbiAgICAgICAgY29uc3QgZW5kID0gbmV3IERhdGUoc3RhcnQuZ2V0VGltZSgpICsgZHVyYXRpb25NaW51dGVzICogNjAgKiAxMDAwKTtcbiAgICAgICAgcmV0dXJuIG5ldyBTd3BFdmVudChlbGVtZW50LCBjb2x1bW5LZXksIHN0YXJ0LCBlbmQpO1xuICAgIH1cbn1cbiIsICJpbXBvcnQgeyBDb3JlRXZlbnRzIH0gZnJvbSAnLi4vY29uc3RhbnRzL0NvcmVFdmVudHMnO1xuaW1wb3J0IHsgc25hcFRvR3JpZCB9IGZyb20gJy4uL3V0aWxzL1Bvc2l0aW9uVXRpbHMnO1xuaW1wb3J0IHsgU3dwRXZlbnQgfSBmcm9tICcuLi90eXBlcy9Td3BFdmVudCc7XG4vKipcbiAqIERyYWdEcm9wTWFuYWdlciAtIEhhbmRsZXMgZHJhZy1kcm9wIGZvciBjYWxlbmRhciBldmVudHNcbiAqXG4gKiBTdHJhdGVneTogRHJhZyBvcmlnaW5hbCBlbGVtZW50LCBsZWF2ZSBnaG9zdC1jbG9uZSBpbiBwbGFjZVxuICogLSBtb3VzZWRvd246IFN0b3JlIGluaXRpYWwgc3RhdGUsIHdhaXQgZm9yIG1vdmVtZW50XG4gKiAtIG1vdXNlbW92ZSAoPjVweCk6IENyZWF0ZSBnaG9zdCwgc3RhcnQgZHJhZ2dpbmcgb3JpZ2luYWxcbiAqIC0gbW91c2V1cDogU25hcCB0byBncmlkLCByZW1vdmUgZ2hvc3QsIGVtaXQgZHJhZzplbmRcbiAqIC0gY2FuY2VsOiBBbmltYXRlIGJhY2sgdG8gc3RhcnRZLCByZW1vdmUgZ2hvc3RcbiAqL1xuZXhwb3J0IGNsYXNzIERyYWdEcm9wTWFuYWdlciB7XG4gICAgY29uc3RydWN0b3IoZXZlbnRCdXMsIGdyaWRDb25maWcpIHtcbiAgICAgICAgdGhpcy5ldmVudEJ1cyA9IGV2ZW50QnVzO1xuICAgICAgICB0aGlzLmdyaWRDb25maWcgPSBncmlkQ29uZmlnO1xuICAgICAgICB0aGlzLmRyYWdTdGF0ZSA9IG51bGw7XG4gICAgICAgIHRoaXMubW91c2VEb3duUG9zaXRpb24gPSBudWxsO1xuICAgICAgICB0aGlzLnBlbmRpbmdFbGVtZW50ID0gbnVsbDtcbiAgICAgICAgdGhpcy5wZW5kaW5nTW91c2VPZmZzZXQgPSBudWxsO1xuICAgICAgICB0aGlzLmNvbnRhaW5lciA9IG51bGw7XG4gICAgICAgIHRoaXMuaW5IZWFkZXIgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5EUkFHX1RIUkVTSE9MRCA9IDU7XG4gICAgICAgIHRoaXMuSU5URVJQT0xBVElPTl9GQUNUT1IgPSAwLjM7XG4gICAgICAgIHRoaXMuaGFuZGxlUG9pbnRlckRvd24gPSAoZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdGFyZ2V0ID0gZS50YXJnZXQ7XG4gICAgICAgICAgICAvLyBJZ25vcmUgaWYgY2xpY2tpbmcgb24gcmVzaXplIGhhbmRsZVxuICAgICAgICAgICAgaWYgKHRhcmdldC5jbG9zZXN0KCdzd3AtcmVzaXplLWhhbmRsZScpKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIC8vIE1hdGNoIGJvdGggc3dwLWV2ZW50IGFuZCBzd3AtaGVhZGVyLWl0ZW1cbiAgICAgICAgICAgIGNvbnN0IGV2ZW50RWxlbWVudCA9IHRhcmdldC5jbG9zZXN0KCdzd3AtZXZlbnQnKTtcbiAgICAgICAgICAgIGNvbnN0IGhlYWRlckl0ZW0gPSB0YXJnZXQuY2xvc2VzdCgnc3dwLWhlYWRlci1pdGVtJyk7XG4gICAgICAgICAgICBjb25zdCBkcmFnZ2FibGUgPSBldmVudEVsZW1lbnQgfHwgaGVhZGVySXRlbTtcbiAgICAgICAgICAgIGlmICghZHJhZ2dhYmxlKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIC8vIFN0b3JlIGZvciBwb3RlbnRpYWwgZHJhZ1xuICAgICAgICAgICAgdGhpcy5tb3VzZURvd25Qb3NpdGlvbiA9IHsgeDogZS5jbGllbnRYLCB5OiBlLmNsaWVudFkgfTtcbiAgICAgICAgICAgIHRoaXMucGVuZGluZ0VsZW1lbnQgPSBkcmFnZ2FibGU7XG4gICAgICAgICAgICAvLyBDYWxjdWxhdGUgbW91c2Ugb2Zmc2V0IHdpdGhpbiBlbGVtZW50XG4gICAgICAgICAgICBjb25zdCByZWN0ID0gZHJhZ2dhYmxlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgdGhpcy5wZW5kaW5nTW91c2VPZmZzZXQgPSB7XG4gICAgICAgICAgICAgICAgeDogZS5jbGllbnRYIC0gcmVjdC5sZWZ0LFxuICAgICAgICAgICAgICAgIHk6IGUuY2xpZW50WSAtIHJlY3QudG9wXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgLy8gQ2FwdHVyZSBwb2ludGVyIGZvciByZWxpYWJsZSB0cmFja2luZ1xuICAgICAgICAgICAgZHJhZ2dhYmxlLnNldFBvaW50ZXJDYXB0dXJlKGUucG9pbnRlcklkKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVQb2ludGVyTW92ZSA9IChlKSA9PiB7XG4gICAgICAgICAgICAvLyBOb3QgaW4gcG90ZW50aWFsIGRyYWcgc3RhdGVcbiAgICAgICAgICAgIGlmICghdGhpcy5tb3VzZURvd25Qb3NpdGlvbiB8fCAhdGhpcy5wZW5kaW5nRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIC8vIEFscmVhZHkgZHJhZ2dpbmcgLSB1cGRhdGUgdGFyZ2V0XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZHJhZ1N0YXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlRHJhZ1RhcmdldChlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQ2hlY2sgdGhyZXNob2xkXG4gICAgICAgICAgICBjb25zdCBkZWx0YVggPSBNYXRoLmFicyhlLmNsaWVudFggLSB0aGlzLm1vdXNlRG93blBvc2l0aW9uLngpO1xuICAgICAgICAgICAgY29uc3QgZGVsdGFZID0gTWF0aC5hYnMoZS5jbGllbnRZIC0gdGhpcy5tb3VzZURvd25Qb3NpdGlvbi55KTtcbiAgICAgICAgICAgIGNvbnN0IGRpc3RhbmNlID0gTWF0aC5zcXJ0KGRlbHRhWCAqIGRlbHRhWCArIGRlbHRhWSAqIGRlbHRhWSk7XG4gICAgICAgICAgICBpZiAoZGlzdGFuY2UgPCB0aGlzLkRSQUdfVEhSRVNIT0xEKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIC8vIFN0YXJ0IGRyYWdcbiAgICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZURyYWcodGhpcy5wZW5kaW5nRWxlbWVudCwgdGhpcy5wZW5kaW5nTW91c2VPZmZzZXQsIGUpO1xuICAgICAgICAgICAgdGhpcy5tb3VzZURvd25Qb3NpdGlvbiA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnBlbmRpbmdFbGVtZW50ID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMucGVuZGluZ01vdXNlT2Zmc2V0ID0gbnVsbDtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYW5kbGVQb2ludGVyVXAgPSAoX2UpID0+IHtcbiAgICAgICAgICAgIC8vIENsZWFyIHBlbmRpbmcgc3RhdGVcbiAgICAgICAgICAgIHRoaXMubW91c2VEb3duUG9zaXRpb24gPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5wZW5kaW5nRWxlbWVudCA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnBlbmRpbmdNb3VzZU9mZnNldCA9IG51bGw7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZHJhZ1N0YXRlKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIC8vIFN0b3AgYW5pbWF0aW9uXG4gICAgICAgICAgICBjYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLmRyYWdTdGF0ZS5hbmltYXRpb25JZCk7XG4gICAgICAgICAgICAvLyBIYW5kbGUgYmFzZWQgb24gZHJhZyBzb3VyY2UgYW5kIHRhcmdldFxuICAgICAgICAgICAgaWYgKHRoaXMuZHJhZ1N0YXRlLmRyYWdTb3VyY2UgPT09ICdoZWFkZXInKSB7XG4gICAgICAgICAgICAgICAgLy8gSGVhZGVyIGl0ZW0gZHJhZyBlbmRcbiAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZUhlYWRlckl0ZW1EcmFnRW5kKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBHcmlkIGV2ZW50IGRyYWcgZW5kXG4gICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVHcmlkRXZlbnREcmFnRW5kKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBDbGVhbnVwXG4gICAgICAgICAgICB0aGlzLmRyYWdTdGF0ZS5lbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoJ2RyYWdnaW5nJyk7XG4gICAgICAgICAgICB0aGlzLmRyYWdTdGF0ZSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmluSGVhZGVyID0gZmFsc2U7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuYW5pbWF0ZURyYWcgPSAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZHJhZ1N0YXRlKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIGNvbnN0IGRpZmYgPSB0aGlzLmRyYWdTdGF0ZS50YXJnZXRZIC0gdGhpcy5kcmFnU3RhdGUuY3VycmVudFk7XG4gICAgICAgICAgICAvLyBTdG9wIGFuaW1hdGlvbiB3aGVuIGNsb3NlIGVub3VnaCB0byB0YXJnZXRcbiAgICAgICAgICAgIGlmIChNYXRoLmFicyhkaWZmKSA8PSAwLjUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRyYWdTdGF0ZS5hbmltYXRpb25JZCA9IDA7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSW50ZXJwb2xhdGUgdG93YXJkcyB0YXJnZXRcbiAgICAgICAgICAgIHRoaXMuZHJhZ1N0YXRlLmN1cnJlbnRZICs9IGRpZmYgKiB0aGlzLklOVEVSUE9MQVRJT05fRkFDVE9SO1xuICAgICAgICAgICAgLy8gVXBkYXRlIGVsZW1lbnQgcG9zaXRpb25cbiAgICAgICAgICAgIHRoaXMuZHJhZ1N0YXRlLmVsZW1lbnQuc3R5bGUudG9wID0gYCR7dGhpcy5kcmFnU3RhdGUuY3VycmVudFl9cHhgO1xuICAgICAgICAgICAgLy8gRW1pdCBkcmFnOm1vdmUgKG9ubHkgaWYgd2UgaGF2ZSBhIGNvbHVtbilcbiAgICAgICAgICAgIGlmICh0aGlzLmRyYWdTdGF0ZS5jb2x1bW5FbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRJZDogdGhpcy5kcmFnU3RhdGUuZXZlbnRJZCxcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogdGhpcy5kcmFnU3RhdGUuZWxlbWVudCxcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudFk6IHRoaXMuZHJhZ1N0YXRlLmN1cnJlbnRZLFxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5FbGVtZW50OiB0aGlzLmRyYWdTdGF0ZS5jb2x1bW5FbGVtZW50XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ29yZUV2ZW50cy5FVkVOVF9EUkFHX01PVkUsIHBheWxvYWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQ29udGludWUgYW5pbWF0aW9uXG4gICAgICAgICAgICB0aGlzLmRyYWdTdGF0ZS5hbmltYXRpb25JZCA9IHJlcXVlc3RBbmltYXRpb25GcmFtZSh0aGlzLmFuaW1hdGVEcmFnKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5zZXR1cFNjcm9sbExpc3RlbmVyKCk7XG4gICAgfVxuICAgIHNldHVwU2Nyb2xsTGlzdGVuZXIoKSB7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMub24oQ29yZUV2ZW50cy5FREdFX1NDUk9MTF9USUNLLCAoZSkgPT4ge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmRyYWdTdGF0ZSlcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICBjb25zdCB7IHNjcm9sbERlbHRhIH0gPSBlLmRldGFpbDtcbiAgICAgICAgICAgIC8vIEVsZW1lbnQgc2thbCBmbHl0dGUgbWVkIHNjcm9sbCBmb3IgYXQgZm9yYmxpdmUgdW5kZXIgbXVzZW5cbiAgICAgICAgICAgIC8vIChlbGVtZW50ZXRzIHRvcCBlciByZWxhdGl2IHRpbCBrb2xvbm5lbiwgc29tIHNjcm9sbGVyIG1lZCB2aWV3cG9ydClcbiAgICAgICAgICAgIHRoaXMuZHJhZ1N0YXRlLnRhcmdldFkgKz0gc2Nyb2xsRGVsdGE7XG4gICAgICAgICAgICB0aGlzLmRyYWdTdGF0ZS5jdXJyZW50WSArPSBzY3JvbGxEZWx0YTtcbiAgICAgICAgICAgIHRoaXMuZHJhZ1N0YXRlLmVsZW1lbnQuc3R5bGUudG9wID0gYCR7dGhpcy5kcmFnU3RhdGUuY3VycmVudFl9cHhgO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSBkcmFnLWRyb3Agb24gYSBjb250YWluZXIgZWxlbWVudFxuICAgICAqL1xuICAgIGluaXQoY29udGFpbmVyKSB7XG4gICAgICAgIHRoaXMuY29udGFpbmVyID0gY29udGFpbmVyO1xuICAgICAgICBjb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcigncG9pbnRlcmRvd24nLCB0aGlzLmhhbmRsZVBvaW50ZXJEb3duKTtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncG9pbnRlcm1vdmUnLCB0aGlzLmhhbmRsZVBvaW50ZXJNb3ZlKTtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncG9pbnRlcnVwJywgdGhpcy5oYW5kbGVQb2ludGVyVXApO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgZHJhZyBlbmQgZm9yIGhlYWRlciBpdGVtc1xuICAgICAqL1xuICAgIGhhbmRsZUhlYWRlckl0ZW1EcmFnRW5kKCkge1xuICAgICAgICBpZiAoIXRoaXMuZHJhZ1N0YXRlKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAvLyBJZiBkcm9wcGVkIGluIGdyaWQgKG5vdCBpbiBoZWFkZXIpLCB0aGUgc3dwLWV2ZW50IHdhcyBhbHJlYWR5IGNyZWF0ZWRcbiAgICAgICAgLy8gYnkgRXZlbnRSZW5kZXJlciBsaXN0ZW5pbmcgdG8gRVZFTlRfRFJBR19MRUFWRV9IRUFERVJcbiAgICAgICAgLy8gSnVzdCBlbWl0IGRyYWc6ZW5kIGZvciBwZXJzaXN0ZW5jZVxuICAgICAgICBpZiAoIXRoaXMuaW5IZWFkZXIgJiYgdGhpcy5kcmFnU3RhdGUuY3VycmVudENvbHVtbikge1xuICAgICAgICAgICAgLy8gRHJvcHBlZCBpbiBncmlkIC0gZW1pdCBkcmFnOmVuZCB3aXRoIHRoZSBuZXcgc3dwLWV2ZW50IGVsZW1lbnRcbiAgICAgICAgICAgIGNvbnN0IGdyaWRFdmVudCA9IHRoaXMuZHJhZ1N0YXRlLmN1cnJlbnRDb2x1bW4ucXVlcnlTZWxlY3Rvcihgc3dwLWV2ZW50W2RhdGEtZXZlbnQtaWQ9XCIke3RoaXMuZHJhZ1N0YXRlLmV2ZW50SWR9XCJdYCk7XG4gICAgICAgICAgICBpZiAoZ3JpZEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29sdW1uS2V5ID0gdGhpcy5kcmFnU3RhdGUuY3VycmVudENvbHVtbi5kYXRhc2V0LmNvbHVtbktleSB8fCAnJztcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRlID0gdGhpcy5kcmFnU3RhdGUuY3VycmVudENvbHVtbi5kYXRhc2V0LmRhdGUgfHwgJyc7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3dwRXZlbnQgPSBTd3BFdmVudC5mcm9tRWxlbWVudChncmlkRXZlbnQsIGNvbHVtbktleSwgZGF0ZSwgdGhpcy5ncmlkQ29uZmlnKTtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXlsb2FkID0ge1xuICAgICAgICAgICAgICAgICAgICBzd3BFdmVudCxcbiAgICAgICAgICAgICAgICAgICAgc291cmNlQ29sdW1uS2V5OiB0aGlzLmRyYWdTdGF0ZS5zb3VyY2VDb2x1bW5LZXksXG4gICAgICAgICAgICAgICAgICAgIHRhcmdldDogJ2dyaWQnXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ29yZUV2ZW50cy5FVkVOVF9EUkFHX0VORCwgcGF5bG9hZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gSWYgc3RpbGwgaW4gaGVhZGVyLCBubyBwZXJzaXN0ZW5jZSBuZWVkZWQgKHN0YXllZCBpbiBoZWFkZXIpXG4gICAgfVxuICAgIC8qKlxuICAgICAqIEhhbmRsZSBkcmFnIGVuZCBmb3IgZ3JpZCBldmVudHNcbiAgICAgKi9cbiAgICBoYW5kbGVHcmlkRXZlbnREcmFnRW5kKCkge1xuICAgICAgICBpZiAoIXRoaXMuZHJhZ1N0YXRlIHx8ICF0aGlzLmRyYWdTdGF0ZS5jb2x1bW5FbGVtZW50KVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAvLyBTbmFwIHRvIGdyaWRcbiAgICAgICAgY29uc3Qgc25hcHBlZFkgPSBzbmFwVG9HcmlkKHRoaXMuZHJhZ1N0YXRlLmN1cnJlbnRZLCB0aGlzLmdyaWRDb25maWcpO1xuICAgICAgICB0aGlzLmRyYWdTdGF0ZS5lbGVtZW50LnN0eWxlLnRvcCA9IGAke3NuYXBwZWRZfXB4YDtcbiAgICAgICAgLy8gUmVtb3ZlIGdob3N0XG4gICAgICAgIHRoaXMuZHJhZ1N0YXRlLmdob3N0RWxlbWVudD8ucmVtb3ZlKCk7XG4gICAgICAgIC8vIEdldCBjb2x1bW5LZXkgYW5kIGRhdGUgZnJvbSB0YXJnZXQgY29sdW1uXG4gICAgICAgIGNvbnN0IGNvbHVtbktleSA9IHRoaXMuZHJhZ1N0YXRlLmNvbHVtbkVsZW1lbnQuZGF0YXNldC5jb2x1bW5LZXkgfHwgJyc7XG4gICAgICAgIGNvbnN0IGRhdGUgPSB0aGlzLmRyYWdTdGF0ZS5jb2x1bW5FbGVtZW50LmRhdGFzZXQuZGF0ZSB8fCAnJztcbiAgICAgICAgLy8gQ3JlYXRlIFN3cEV2ZW50IGZyb20gZWxlbWVudCAocmVhZHMgdG9wL2hlaWdodC9ldmVudElkIGZyb20gZWxlbWVudClcbiAgICAgICAgY29uc3Qgc3dwRXZlbnQgPSBTd3BFdmVudC5mcm9tRWxlbWVudCh0aGlzLmRyYWdTdGF0ZS5lbGVtZW50LCBjb2x1bW5LZXksIGRhdGUsIHRoaXMuZ3JpZENvbmZpZyk7XG4gICAgICAgIC8vIEVtaXQgZHJhZzplbmRcbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgICAgIHN3cEV2ZW50LFxuICAgICAgICAgICAgc291cmNlQ29sdW1uS2V5OiB0aGlzLmRyYWdTdGF0ZS5zb3VyY2VDb2x1bW5LZXksXG4gICAgICAgICAgICB0YXJnZXQ6IHRoaXMuaW5IZWFkZXIgPyAnaGVhZGVyJyA6ICdncmlkJ1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ29yZUV2ZW50cy5FVkVOVF9EUkFHX0VORCwgcGF5bG9hZCk7XG4gICAgfVxuICAgIGluaXRpYWxpemVEcmFnKGVsZW1lbnQsIG1vdXNlT2Zmc2V0LCBlKSB7XG4gICAgICAgIGNvbnN0IGV2ZW50SWQgPSBlbGVtZW50LmRhdGFzZXQuZXZlbnRJZCB8fCAnJztcbiAgICAgICAgY29uc3QgaXNIZWFkZXJJdGVtID0gZWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdzd3AtaGVhZGVyLWl0ZW0nO1xuICAgICAgICBjb25zdCBjb2x1bW5FbGVtZW50ID0gZWxlbWVudC5jbG9zZXN0KCdzd3AtZGF5LWNvbHVtbicpO1xuICAgICAgICAvLyBGb3IgZ3JpZCBldmVudHMsIHdlIG5lZWQgYSBjb2x1bW5cbiAgICAgICAgaWYgKCFpc0hlYWRlckl0ZW0gJiYgIWNvbHVtbkVsZW1lbnQpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGlmIChpc0hlYWRlckl0ZW0pIHtcbiAgICAgICAgICAgIC8vIEhlYWRlciBpdGVtIGRyYWcgaW5pdGlhbGl6YXRpb25cbiAgICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZUhlYWRlckl0ZW1EcmFnKGVsZW1lbnQsIG1vdXNlT2Zmc2V0LCBldmVudElkKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIEdyaWQgZXZlbnQgZHJhZyBpbml0aWFsaXphdGlvblxuICAgICAgICAgICAgdGhpcy5pbml0aWFsaXplR3JpZEV2ZW50RHJhZyhlbGVtZW50LCBtb3VzZU9mZnNldCwgZSwgY29sdW1uRWxlbWVudCwgZXZlbnRJZCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSBkcmFnIGZvciBhIGhlYWRlciBpdGVtIChhbGxEYXkgZXZlbnQpXG4gICAgICovXG4gICAgaW5pdGlhbGl6ZUhlYWRlckl0ZW1EcmFnKGVsZW1lbnQsIG1vdXNlT2Zmc2V0LCBldmVudElkKSB7XG4gICAgICAgIC8vIE1hcmsgYXMgZHJhZ2dpbmdcbiAgICAgICAgZWxlbWVudC5jbGFzc0xpc3QuYWRkKCdkcmFnZ2luZycpO1xuICAgICAgICAvLyBJbml0aWFsaXplIGRyYWcgc3RhdGUgZm9yIGhlYWRlciBpdGVtXG4gICAgICAgIHRoaXMuZHJhZ1N0YXRlID0ge1xuICAgICAgICAgICAgZXZlbnRJZCxcbiAgICAgICAgICAgIGVsZW1lbnQsXG4gICAgICAgICAgICBnaG9zdEVsZW1lbnQ6IG51bGwsIC8vIE5vIGdob3N0IGZvciBoZWFkZXIgaXRlbXNcbiAgICAgICAgICAgIHN0YXJ0WTogMCxcbiAgICAgICAgICAgIG1vdXNlT2Zmc2V0LFxuICAgICAgICAgICAgY29sdW1uRWxlbWVudDogbnVsbCxcbiAgICAgICAgICAgIGN1cnJlbnRDb2x1bW46IG51bGwsXG4gICAgICAgICAgICB0YXJnZXRZOiAwLFxuICAgICAgICAgICAgY3VycmVudFk6IDAsXG4gICAgICAgICAgICBhbmltYXRpb25JZDogMCxcbiAgICAgICAgICAgIHNvdXJjZUNvbHVtbktleTogJycsIC8vIFdpbGwgYmUgc2V0IGZyb20gaGVhZGVyIGl0ZW0gZGF0YVxuICAgICAgICAgICAgZHJhZ1NvdXJjZTogJ2hlYWRlcidcbiAgICAgICAgfTtcbiAgICAgICAgLy8gU3RhcnQgaW4gaGVhZGVyIG1vZGVcbiAgICAgICAgdGhpcy5pbkhlYWRlciA9IHRydWU7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemUgZHJhZyBmb3IgYSBncmlkIGV2ZW50XG4gICAgICovXG4gICAgaW5pdGlhbGl6ZUdyaWRFdmVudERyYWcoZWxlbWVudCwgbW91c2VPZmZzZXQsIGUsIGNvbHVtbkVsZW1lbnQsIGV2ZW50SWQpIHtcbiAgICAgICAgLy8gQ2FsY3VsYXRlIGFic29sdXRlIFkgcG9zaXRpb24gdXNpbmcgZ2V0Qm91bmRpbmdDbGllbnRSZWN0XG4gICAgICAgIGNvbnN0IGVsZW1lbnRSZWN0ID0gZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgY29uc3QgY29sdW1uUmVjdCA9IGNvbHVtbkVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIGNvbnN0IHN0YXJ0WSA9IGVsZW1lbnRSZWN0LnRvcCAtIGNvbHVtblJlY3QudG9wO1xuICAgICAgICAvLyBJZiBldmVudCBpcyBpbnNpZGUgYSBncm91cCwgbW92ZSBpdCB0byBldmVudHMtbGF5ZXIgZm9yIGNvcnJlY3QgcG9zaXRpb25pbmcgZHVyaW5nIGRyYWdcbiAgICAgICAgY29uc3QgZ3JvdXAgPSBlbGVtZW50LmNsb3Nlc3QoJ3N3cC1ldmVudC1ncm91cCcpO1xuICAgICAgICBpZiAoZ3JvdXApIHtcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50c0xheWVyID0gY29sdW1uRWxlbWVudC5xdWVyeVNlbGVjdG9yKCdzd3AtZXZlbnRzLWxheWVyJyk7XG4gICAgICAgICAgICBpZiAoZXZlbnRzTGF5ZXIpIHtcbiAgICAgICAgICAgICAgICBldmVudHNMYXllci5hcHBlbmRDaGlsZChlbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBTZXQgY29uc2lzdGVudCBwb3NpdGlvbmluZyBmb3IgZHJhZyAod29ya3MgZm9yIGJvdGggZ3JvdXBlZCBhbmQgc3RhY2tlZCBldmVudHMpXG4gICAgICAgIGVsZW1lbnQuc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgICAgICBlbGVtZW50LnN0eWxlLnRvcCA9IGAke3N0YXJ0WX1weGA7XG4gICAgICAgIGVsZW1lbnQuc3R5bGUubGVmdCA9ICcycHgnO1xuICAgICAgICBlbGVtZW50LnN0eWxlLnJpZ2h0ID0gJzJweCc7XG4gICAgICAgIGVsZW1lbnQuc3R5bGUubWFyZ2luTGVmdCA9ICcwJzsgLy8gUmVzZXQgc3RhY2tpbmcgbWFyZ2luXG4gICAgICAgIC8vIENyZWF0ZSBnaG9zdCBjbG9uZVxuICAgICAgICBjb25zdCBnaG9zdEVsZW1lbnQgPSBlbGVtZW50LmNsb25lTm9kZSh0cnVlKTtcbiAgICAgICAgZ2hvc3RFbGVtZW50LmNsYXNzTGlzdC5hZGQoJ2RyYWctZ2hvc3QnKTtcbiAgICAgICAgZ2hvc3RFbGVtZW50LnN0eWxlLm9wYWNpdHkgPSAnMC4zJztcbiAgICAgICAgZ2hvc3RFbGVtZW50LnN0eWxlLnBvaW50ZXJFdmVudHMgPSAnbm9uZSc7XG4gICAgICAgIC8vIEluc2VydCBnaG9zdCBiZWZvcmUgb3JpZ2luYWxcbiAgICAgICAgZWxlbWVudC5wYXJlbnROb2RlPy5pbnNlcnRCZWZvcmUoZ2hvc3RFbGVtZW50LCBlbGVtZW50KTtcbiAgICAgICAgLy8gU2V0dXAgZWxlbWVudCBmb3IgZHJhZ2dpbmdcbiAgICAgICAgZWxlbWVudC5jbGFzc0xpc3QuYWRkKCdkcmFnZ2luZycpO1xuICAgICAgICAvLyBDYWxjdWxhdGUgaW5pdGlhbCB0YXJnZXQgZnJvbSBtb3VzZSBwb3NpdGlvblxuICAgICAgICBjb25zdCB0YXJnZXRZID0gZS5jbGllbnRZIC0gY29sdW1uUmVjdC50b3AgLSBtb3VzZU9mZnNldC55O1xuICAgICAgICAvLyBJbml0aWFsaXplIGRyYWcgc3RhdGVcbiAgICAgICAgdGhpcy5kcmFnU3RhdGUgPSB7XG4gICAgICAgICAgICBldmVudElkLFxuICAgICAgICAgICAgZWxlbWVudCxcbiAgICAgICAgICAgIGdob3N0RWxlbWVudCxcbiAgICAgICAgICAgIHN0YXJ0WSxcbiAgICAgICAgICAgIG1vdXNlT2Zmc2V0LFxuICAgICAgICAgICAgY29sdW1uRWxlbWVudCxcbiAgICAgICAgICAgIGN1cnJlbnRDb2x1bW46IGNvbHVtbkVsZW1lbnQsXG4gICAgICAgICAgICB0YXJnZXRZOiBNYXRoLm1heCgwLCB0YXJnZXRZKSxcbiAgICAgICAgICAgIGN1cnJlbnRZOiBzdGFydFksXG4gICAgICAgICAgICBhbmltYXRpb25JZDogMCxcbiAgICAgICAgICAgIHNvdXJjZUNvbHVtbktleTogY29sdW1uRWxlbWVudC5kYXRhc2V0LmNvbHVtbktleSB8fCAnJyxcbiAgICAgICAgICAgIGRyYWdTb3VyY2U6ICdncmlkJ1xuICAgICAgICB9O1xuICAgICAgICAvLyBFbWl0IGRyYWc6c3RhcnRcbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgICAgIGV2ZW50SWQsXG4gICAgICAgICAgICBlbGVtZW50LFxuICAgICAgICAgICAgZ2hvc3RFbGVtZW50LFxuICAgICAgICAgICAgc3RhcnRZLFxuICAgICAgICAgICAgbW91c2VPZmZzZXQsXG4gICAgICAgICAgICBjb2x1bW5FbGVtZW50XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZXZlbnRCdXMuZW1pdChDb3JlRXZlbnRzLkVWRU5UX0RSQUdfU1RBUlQsIHBheWxvYWQpO1xuICAgICAgICAvLyBTdGFydCBhbmltYXRpb24gbG9vcFxuICAgICAgICB0aGlzLmFuaW1hdGVEcmFnKCk7XG4gICAgfVxuICAgIHVwZGF0ZURyYWdUYXJnZXQoZSkge1xuICAgICAgICBpZiAoIXRoaXMuZHJhZ1N0YXRlKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAvLyBDaGVjayBoZWFkZXIgem9uZSBmaXJzdFxuICAgICAgICB0aGlzLmNoZWNrSGVhZGVyWm9uZShlKTtcbiAgICAgICAgLy8gU2tpcCBub3JtYWwgZ3JpZCBoYW5kbGluZyBpZiBpbiBoZWFkZXJcbiAgICAgICAgaWYgKHRoaXMuaW5IZWFkZXIpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIC8vIENoZWNrIGZvciBjb2x1bW4gY2hhbmdlXG4gICAgICAgIGNvbnN0IGNvbHVtbkF0UG9pbnQgPSB0aGlzLmdldENvbHVtbkF0UG9pbnQoZS5jbGllbnRYKTtcbiAgICAgICAgLy8gRm9yIGhlYWRlciBpdGVtcyBlbnRlcmluZyBncmlkLCBzZXQgaW5pdGlhbCBjb2x1bW5cbiAgICAgICAgaWYgKHRoaXMuZHJhZ1N0YXRlLmRyYWdTb3VyY2UgPT09ICdoZWFkZXInICYmIGNvbHVtbkF0UG9pbnQgJiYgIXRoaXMuZHJhZ1N0YXRlLmN1cnJlbnRDb2x1bW4pIHtcbiAgICAgICAgICAgIHRoaXMuZHJhZ1N0YXRlLmN1cnJlbnRDb2x1bW4gPSBjb2x1bW5BdFBvaW50O1xuICAgICAgICAgICAgdGhpcy5kcmFnU3RhdGUuY29sdW1uRWxlbWVudCA9IGNvbHVtbkF0UG9pbnQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbHVtbkF0UG9pbnQgJiYgY29sdW1uQXRQb2ludCAhPT0gdGhpcy5kcmFnU3RhdGUuY3VycmVudENvbHVtbiAmJiB0aGlzLmRyYWdTdGF0ZS5jdXJyZW50Q29sdW1uKSB7XG4gICAgICAgICAgICBjb25zdCBwYXlsb2FkID0ge1xuICAgICAgICAgICAgICAgIGV2ZW50SWQ6IHRoaXMuZHJhZ1N0YXRlLmV2ZW50SWQsXG4gICAgICAgICAgICAgICAgZWxlbWVudDogdGhpcy5kcmFnU3RhdGUuZWxlbWVudCxcbiAgICAgICAgICAgICAgICBwcmV2aW91c0NvbHVtbjogdGhpcy5kcmFnU3RhdGUuY3VycmVudENvbHVtbixcbiAgICAgICAgICAgICAgICBuZXdDb2x1bW46IGNvbHVtbkF0UG9pbnQsXG4gICAgICAgICAgICAgICAgY3VycmVudFk6IHRoaXMuZHJhZ1N0YXRlLmN1cnJlbnRZXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENvcmVFdmVudHMuRVZFTlRfRFJBR19DT0xVTU5fQ0hBTkdFLCBwYXlsb2FkKTtcbiAgICAgICAgICAgIHRoaXMuZHJhZ1N0YXRlLmN1cnJlbnRDb2x1bW4gPSBjb2x1bW5BdFBvaW50O1xuICAgICAgICAgICAgdGhpcy5kcmFnU3RhdGUuY29sdW1uRWxlbWVudCA9IGNvbHVtbkF0UG9pbnQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gU2tpcCBncmlkIHBvc2l0aW9uIHVwZGF0ZXMgaWYgbm8gY29sdW1uIHlldFxuICAgICAgICBpZiAoIXRoaXMuZHJhZ1N0YXRlLmNvbHVtbkVsZW1lbnQpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNvbnN0IGNvbHVtblJlY3QgPSB0aGlzLmRyYWdTdGF0ZS5jb2x1bW5FbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICBjb25zdCB0YXJnZXRZID0gZS5jbGllbnRZIC0gY29sdW1uUmVjdC50b3AgLSB0aGlzLmRyYWdTdGF0ZS5tb3VzZU9mZnNldC55O1xuICAgICAgICB0aGlzLmRyYWdTdGF0ZS50YXJnZXRZID0gTWF0aC5tYXgoMCwgdGFyZ2V0WSk7XG4gICAgICAgIC8vIFN0YXJ0IGFuaW1hdGlvbiBpZiBub3QgcnVubmluZ1xuICAgICAgICBpZiAoIXRoaXMuZHJhZ1N0YXRlLmFuaW1hdGlvbklkKSB7XG4gICAgICAgICAgICB0aGlzLmFuaW1hdGVEcmFnKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgcG9pbnRlciBpcyBpbiBoZWFkZXIgem9uZSBhbmQgZW1pdCBhcHByb3ByaWF0ZSBldmVudHNcbiAgICAgKi9cbiAgICBjaGVja0hlYWRlclpvbmUoZSkge1xuICAgICAgICBpZiAoIXRoaXMuZHJhZ1N0YXRlKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBjb25zdCBoZWFkZXJWaWV3cG9ydCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ3N3cC1oZWFkZXItdmlld3BvcnQnKTtcbiAgICAgICAgaWYgKCFoZWFkZXJWaWV3cG9ydClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY29uc3QgcmVjdCA9IGhlYWRlclZpZXdwb3J0LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICBjb25zdCBpc0luSGVhZGVyID0gZS5jbGllbnRZIDwgcmVjdC5ib3R0b207XG4gICAgICAgIGlmIChpc0luSGVhZGVyICYmICF0aGlzLmluSGVhZGVyKSB7XG4gICAgICAgICAgICAvLyBFbnRlcmVkIGhlYWRlciAoZnJvbSBncmlkKVxuICAgICAgICAgICAgdGhpcy5pbkhlYWRlciA9IHRydWU7XG4gICAgICAgICAgICBpZiAodGhpcy5kcmFnU3RhdGUuZHJhZ1NvdXJjZSA9PT0gJ2dyaWQnICYmIHRoaXMuZHJhZ1N0YXRlLmNvbHVtbkVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXlsb2FkID0ge1xuICAgICAgICAgICAgICAgICAgICBldmVudElkOiB0aGlzLmRyYWdTdGF0ZS5ldmVudElkLFxuICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiB0aGlzLmRyYWdTdGF0ZS5lbGVtZW50LFxuICAgICAgICAgICAgICAgICAgICBzb3VyY2VDb2x1bW5JbmRleDogdGhpcy5nZXRDb2x1bW5JbmRleCh0aGlzLmRyYWdTdGF0ZS5jb2x1bW5FbGVtZW50KSxcbiAgICAgICAgICAgICAgICAgICAgc291cmNlQ29sdW1uS2V5OiB0aGlzLmRyYWdTdGF0ZS5jb2x1bW5FbGVtZW50LmRhdGFzZXQuY29sdW1uS2V5IHx8ICcnLFxuICAgICAgICAgICAgICAgICAgICB0aXRsZTogdGhpcy5kcmFnU3RhdGUuZWxlbWVudC5xdWVyeVNlbGVjdG9yKCdzd3AtZXZlbnQtdGl0bGUnKT8udGV4dENvbnRlbnQgfHwgJycsXG4gICAgICAgICAgICAgICAgICAgIGNvbG9yQ2xhc3M6IFsuLi50aGlzLmRyYWdTdGF0ZS5lbGVtZW50LmNsYXNzTGlzdF0uZmluZChjID0+IGMuc3RhcnRzV2l0aCgnaXMtJykpLFxuICAgICAgICAgICAgICAgICAgICBpdGVtVHlwZTogJ2V2ZW50JyxcbiAgICAgICAgICAgICAgICAgICAgZHVyYXRpb246IDFcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMuZW1pdChDb3JlRXZlbnRzLkVWRU5UX0RSQUdfRU5URVJfSEVBREVSLCBwYXlsb2FkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEZvciBoZWFkZXIgc291cmNlIHJlLWVudGVyaW5nIGhlYWRlciwganVzdCB1cGRhdGUgaW5IZWFkZXIgZmxhZ1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKCFpc0luSGVhZGVyICYmIHRoaXMuaW5IZWFkZXIpIHtcbiAgICAgICAgICAgIC8vIExlZnQgaGVhZGVyIChlbnRlcmluZyBncmlkKVxuICAgICAgICAgICAgdGhpcy5pbkhlYWRlciA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3QgdGFyZ2V0Q29sdW1uID0gdGhpcy5nZXRDb2x1bW5BdFBvaW50KGUuY2xpZW50WCk7XG4gICAgICAgICAgICBpZiAodGhpcy5kcmFnU3RhdGUuZHJhZ1NvdXJjZSA9PT0gJ2hlYWRlcicpIHtcbiAgICAgICAgICAgICAgICAvLyBIZWFkZXIgaXRlbSBsZWF2aW5nIGhlYWRlciBcdTIxOTIgY3JlYXRlIHN3cC1ldmVudCBpbiBncmlkXG4gICAgICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRJZDogdGhpcy5kcmFnU3RhdGUuZXZlbnRJZCxcbiAgICAgICAgICAgICAgICAgICAgc291cmNlOiAnaGVhZGVyJyxcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogdGhpcy5kcmFnU3RhdGUuZWxlbWVudCxcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0Q29sdW1uOiB0YXJnZXRDb2x1bW4gfHwgdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgICAgICBzdGFydDogdGhpcy5kcmFnU3RhdGUuZWxlbWVudC5kYXRhc2V0LnN0YXJ0ID8gbmV3IERhdGUodGhpcy5kcmFnU3RhdGUuZWxlbWVudC5kYXRhc2V0LnN0YXJ0KSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgZW5kOiB0aGlzLmRyYWdTdGF0ZS5lbGVtZW50LmRhdGFzZXQuZW5kID8gbmV3IERhdGUodGhpcy5kcmFnU3RhdGUuZWxlbWVudC5kYXRhc2V0LmVuZCkgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICAgIHRpdGxlOiB0aGlzLmRyYWdTdGF0ZS5lbGVtZW50LnRleHRDb250ZW50IHx8ICcnLFxuICAgICAgICAgICAgICAgICAgICBjb2xvckNsYXNzOiBbLi4udGhpcy5kcmFnU3RhdGUuZWxlbWVudC5jbGFzc0xpc3RdLmZpbmQoYyA9PiBjLnN0YXJ0c1dpdGgoJ2lzLScpKVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENvcmVFdmVudHMuRVZFTlRfRFJBR19MRUFWRV9IRUFERVIsIHBheWxvYWQpO1xuICAgICAgICAgICAgICAgIC8vIFJlLWF0dGFjaCB0byB0aGUgbmV3IHN3cC1ldmVudCBjcmVhdGVkIGJ5IEV2ZW50UmVuZGVyZXJcbiAgICAgICAgICAgICAgICBpZiAodGFyZ2V0Q29sdW1uKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld0VsZW1lbnQgPSB0YXJnZXRDb2x1bW4ucXVlcnlTZWxlY3Rvcihgc3dwLWV2ZW50W2RhdGEtZXZlbnQtaWQ9XCIke3RoaXMuZHJhZ1N0YXRlLmV2ZW50SWR9XCJdYCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRyYWdTdGF0ZS5lbGVtZW50ID0gbmV3RWxlbWVudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZHJhZ1N0YXRlLmNvbHVtbkVsZW1lbnQgPSB0YXJnZXRDb2x1bW47XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRyYWdTdGF0ZS5jdXJyZW50Q29sdW1uID0gdGFyZ2V0Q29sdW1uO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3RhcnQgYW5pbWF0aW9uIGZvciB0aGUgbmV3IGVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYW5pbWF0ZURyYWcoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIEdyaWQgZXZlbnQgbGVhdmluZyBoZWFkZXIgXHUyMTkyIHJlc3RvcmUgdG8gZ3JpZFxuICAgICAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50SWQ6IHRoaXMuZHJhZ1N0YXRlLmV2ZW50SWQsXG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZTogJ2dyaWQnXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ29yZUV2ZW50cy5FVkVOVF9EUkFHX0xFQVZFX0hFQURFUiwgcGF5bG9hZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXNJbkhlYWRlcikge1xuICAgICAgICAgICAgLy8gTW92aW5nIHdpdGhpbiBoZWFkZXJcbiAgICAgICAgICAgIGNvbnN0IGNvbHVtbiA9IHRoaXMuZ2V0Q29sdW1uQXRYKGUuY2xpZW50WCk7XG4gICAgICAgICAgICBpZiAoY29sdW1uKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRJZDogdGhpcy5kcmFnU3RhdGUuZXZlbnRJZCxcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uSW5kZXg6IHRoaXMuZ2V0Q29sdW1uSW5kZXgoY29sdW1uKSxcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uS2V5OiBjb2x1bW4uZGF0YXNldC5jb2x1bW5LZXkgfHwgJydcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMuZW1pdChDb3JlRXZlbnRzLkVWRU5UX0RSQUdfTU9WRV9IRUFERVIsIHBheWxvYWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBjb2x1bW4gaW5kZXggKDAtYmFzZWQpIGZvciBhIGNvbHVtbiBlbGVtZW50XG4gICAgICovXG4gICAgZ2V0Q29sdW1uSW5kZXgoY29sdW1uKSB7XG4gICAgICAgIGlmICghdGhpcy5jb250YWluZXIgfHwgIWNvbHVtbilcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICBjb25zdCBjb2x1bW5zID0gQXJyYXkuZnJvbSh0aGlzLmNvbnRhaW5lci5xdWVyeVNlbGVjdG9yQWxsKCdzd3AtZGF5LWNvbHVtbicpKTtcbiAgICAgICAgcmV0dXJuIGNvbHVtbnMuaW5kZXhPZihjb2x1bW4pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgY29sdW1uIGF0IFggY29vcmRpbmF0ZSAoYWxpYXMgZm9yIGdldENvbHVtbkF0UG9pbnQpXG4gICAgICovXG4gICAgZ2V0Q29sdW1uQXRYKGNsaWVudFgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29sdW1uQXRQb2ludChjbGllbnRYKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRmluZCBjb2x1bW4gZWxlbWVudCBhdCBnaXZlbiBYIGNvb3JkaW5hdGVcbiAgICAgKi9cbiAgICBnZXRDb2x1bW5BdFBvaW50KGNsaWVudFgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmNvbnRhaW5lcilcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICBjb25zdCBjb2x1bW5zID0gdGhpcy5jb250YWluZXIucXVlcnlTZWxlY3RvckFsbCgnc3dwLWRheS1jb2x1bW4nKTtcbiAgICAgICAgZm9yIChjb25zdCBjb2wgb2YgY29sdW1ucykge1xuICAgICAgICAgICAgY29uc3QgcmVjdCA9IGNvbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIGlmIChjbGllbnRYID49IHJlY3QubGVmdCAmJiBjbGllbnRYIDw9IHJlY3QucmlnaHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY29sO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDYW5jZWwgZHJhZyBhbmQgYW5pbWF0ZSBiYWNrIHRvIHN0YXJ0IHBvc2l0aW9uXG4gICAgICovXG4gICAgY2FuY2VsRHJhZygpIHtcbiAgICAgICAgaWYgKCF0aGlzLmRyYWdTdGF0ZSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgLy8gU3RvcCBhbmltYXRpb25cbiAgICAgICAgY2FuY2VsQW5pbWF0aW9uRnJhbWUodGhpcy5kcmFnU3RhdGUuYW5pbWF0aW9uSWQpO1xuICAgICAgICBjb25zdCB7IGVsZW1lbnQsIGdob3N0RWxlbWVudCwgc3RhcnRZLCBldmVudElkIH0gPSB0aGlzLmRyYWdTdGF0ZTtcbiAgICAgICAgLy8gQW5pbWF0ZSBiYWNrIHRvIHN0YXJ0XG4gICAgICAgIGVsZW1lbnQuc3R5bGUudHJhbnNpdGlvbiA9ICd0b3AgMjAwbXMgZWFzZS1vdXQnO1xuICAgICAgICBlbGVtZW50LnN0eWxlLnRvcCA9IGAke3N0YXJ0WX1weGA7XG4gICAgICAgIC8vIFJlbW92ZSBnaG9zdCBhZnRlciBhbmltYXRpb24gKGlmIGV4aXN0cylcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBnaG9zdEVsZW1lbnQ/LnJlbW92ZSgpO1xuICAgICAgICAgICAgZWxlbWVudC5zdHlsZS50cmFuc2l0aW9uID0gJyc7XG4gICAgICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoJ2RyYWdnaW5nJyk7XG4gICAgICAgIH0sIDIwMCk7XG4gICAgICAgIC8vIEVtaXQgZHJhZzpjYW5jZWxcbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgICAgIGV2ZW50SWQsXG4gICAgICAgICAgICBlbGVtZW50LFxuICAgICAgICAgICAgc3RhcnRZXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZXZlbnRCdXMuZW1pdChDb3JlRXZlbnRzLkVWRU5UX0RSQUdfQ0FOQ0VMLCBwYXlsb2FkKTtcbiAgICAgICAgdGhpcy5kcmFnU3RhdGUgPSBudWxsO1xuICAgICAgICB0aGlzLmluSGVhZGVyID0gZmFsc2U7XG4gICAgfVxufVxuIiwgImltcG9ydCB7IENvcmVFdmVudHMgfSBmcm9tICcuLi9jb25zdGFudHMvQ29yZUV2ZW50cyc7XG5leHBvcnQgY2xhc3MgRWRnZVNjcm9sbE1hbmFnZXIge1xuICAgIGNvbnN0cnVjdG9yKGV2ZW50QnVzKSB7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMgPSBldmVudEJ1cztcbiAgICAgICAgdGhpcy5zY3JvbGxhYmxlQ29udGVudCA9IG51bGw7XG4gICAgICAgIHRoaXMudGltZUdyaWQgPSBudWxsO1xuICAgICAgICB0aGlzLmRyYWdnZWRFbGVtZW50ID0gbnVsbDtcbiAgICAgICAgdGhpcy5zY3JvbGxSQUYgPSBudWxsO1xuICAgICAgICB0aGlzLm1vdXNlWSA9IDA7XG4gICAgICAgIHRoaXMuaXNEcmFnZ2luZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmlzU2Nyb2xsaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMubGFzdFRzID0gMDtcbiAgICAgICAgdGhpcy5yZWN0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5pbml0aWFsU2Nyb2xsVG9wID0gMDtcbiAgICAgICAgdGhpcy5PVVRFUl9aT05FID0gMTAwO1xuICAgICAgICB0aGlzLklOTkVSX1pPTkUgPSA1MDtcbiAgICAgICAgdGhpcy5TTE9XX1NQRUVEID0gMTQwO1xuICAgICAgICB0aGlzLkZBU1RfU1BFRUQgPSA2NDA7XG4gICAgICAgIHRoaXMudHJhY2tNb3VzZSA9IChlKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0RyYWdnaW5nKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tb3VzZVkgPSBlLmNsaWVudFk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc2Nyb2xsVGljayA9ICh0cykgPT4ge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmlzRHJhZ2dpbmcgfHwgIXRoaXMuc2Nyb2xsYWJsZUNvbnRlbnQpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgY29uc3QgZHQgPSB0aGlzLmxhc3RUcyA/ICh0cyAtIHRoaXMubGFzdFRzKSAvIDEwMDAgOiAwO1xuICAgICAgICAgICAgdGhpcy5sYXN0VHMgPSB0cztcbiAgICAgICAgICAgIHRoaXMucmVjdCA/PyAodGhpcy5yZWN0ID0gdGhpcy5zY3JvbGxhYmxlQ29udGVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSk7XG4gICAgICAgICAgICBjb25zdCB2ZWxvY2l0eSA9IHRoaXMuY2FsY3VsYXRlVmVsb2NpdHkoKTtcbiAgICAgICAgICAgIGlmICh2ZWxvY2l0eSAhPT0gMCAmJiAhdGhpcy5pc0F0Qm91bmRhcnkodmVsb2NpdHkpKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2Nyb2xsRGVsdGEgPSB2ZWxvY2l0eSAqIGR0O1xuICAgICAgICAgICAgICAgIHRoaXMuc2Nyb2xsYWJsZUNvbnRlbnQuc2Nyb2xsVG9wICs9IHNjcm9sbERlbHRhO1xuICAgICAgICAgICAgICAgIHRoaXMucmVjdCA9IG51bGw7XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENvcmVFdmVudHMuRURHRV9TQ1JPTExfVElDSywgeyBzY3JvbGxEZWx0YSB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFNjcm9sbGluZ1N0YXRlKHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTY3JvbGxpbmdTdGF0ZShmYWxzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnNjcm9sbFJBRiA9IHJlcXVlc3RBbmltYXRpb25GcmFtZSh0aGlzLnNjcm9sbFRpY2spO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLnN1YnNjcmliZVRvRXZlbnRzKCk7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJtb3ZlJywgdGhpcy50cmFja01vdXNlKTtcbiAgICB9XG4gICAgaW5pdChzY3JvbGxhYmxlQ29udGVudCkge1xuICAgICAgICB0aGlzLnNjcm9sbGFibGVDb250ZW50ID0gc2Nyb2xsYWJsZUNvbnRlbnQ7XG4gICAgICAgIHRoaXMudGltZUdyaWQgPSBzY3JvbGxhYmxlQ29udGVudC5xdWVyeVNlbGVjdG9yKCdzd3AtdGltZS1ncmlkJyk7XG4gICAgICAgIHRoaXMuc2Nyb2xsYWJsZUNvbnRlbnQuc3R5bGUuc2Nyb2xsQmVoYXZpb3IgPSAnYXV0byc7XG4gICAgfVxuICAgIHN1YnNjcmliZVRvRXZlbnRzKCkge1xuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENvcmVFdmVudHMuRVZFTlRfRFJBR19TVEFSVCwgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwYXlsb2FkID0gZXZlbnQuZGV0YWlsO1xuICAgICAgICAgICAgdGhpcy5kcmFnZ2VkRWxlbWVudCA9IHBheWxvYWQuZWxlbWVudDtcbiAgICAgICAgICAgIHRoaXMuc3RhcnREcmFnKCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmV2ZW50QnVzLm9uKENvcmVFdmVudHMuRVZFTlRfRFJBR19FTkQsICgpID0+IHRoaXMuc3RvcERyYWcoKSk7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMub24oQ29yZUV2ZW50cy5FVkVOVF9EUkFHX0NBTkNFTCwgKCkgPT4gdGhpcy5zdG9wRHJhZygpKTtcbiAgICB9XG4gICAgc3RhcnREcmFnKCkge1xuICAgICAgICB0aGlzLmlzRHJhZ2dpbmcgPSB0cnVlO1xuICAgICAgICB0aGlzLmlzU2Nyb2xsaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMubGFzdFRzID0gMDtcbiAgICAgICAgdGhpcy5pbml0aWFsU2Nyb2xsVG9wID0gdGhpcy5zY3JvbGxhYmxlQ29udGVudD8uc2Nyb2xsVG9wID8/IDA7XG4gICAgICAgIGlmICh0aGlzLnNjcm9sbFJBRiA9PT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxSQUYgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy5zY3JvbGxUaWNrKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBzdG9wRHJhZygpIHtcbiAgICAgICAgdGhpcy5pc0RyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuc2V0U2Nyb2xsaW5nU3RhdGUoZmFsc2UpO1xuICAgICAgICBpZiAodGhpcy5zY3JvbGxSQUYgIT09IG51bGwpIHtcbiAgICAgICAgICAgIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHRoaXMuc2Nyb2xsUkFGKTtcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsUkFGID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlY3QgPSBudWxsO1xuICAgICAgICB0aGlzLmxhc3RUcyA9IDA7XG4gICAgICAgIHRoaXMuaW5pdGlhbFNjcm9sbFRvcCA9IDA7XG4gICAgfVxuICAgIGNhbGN1bGF0ZVZlbG9jaXR5KCkge1xuICAgICAgICBpZiAoIXRoaXMucmVjdClcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICBjb25zdCBkaXN0VG9wID0gdGhpcy5tb3VzZVkgLSB0aGlzLnJlY3QudG9wO1xuICAgICAgICBjb25zdCBkaXN0Qm90ID0gdGhpcy5yZWN0LmJvdHRvbSAtIHRoaXMubW91c2VZO1xuICAgICAgICBpZiAoZGlzdFRvcCA8IHRoaXMuSU5ORVJfWk9ORSlcbiAgICAgICAgICAgIHJldHVybiAtdGhpcy5GQVNUX1NQRUVEO1xuICAgICAgICBpZiAoZGlzdFRvcCA8IHRoaXMuT1VURVJfWk9ORSlcbiAgICAgICAgICAgIHJldHVybiAtdGhpcy5TTE9XX1NQRUVEO1xuICAgICAgICBpZiAoZGlzdEJvdCA8IHRoaXMuSU5ORVJfWk9ORSlcbiAgICAgICAgICAgIHJldHVybiB0aGlzLkZBU1RfU1BFRUQ7XG4gICAgICAgIGlmIChkaXN0Qm90IDwgdGhpcy5PVVRFUl9aT05FKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuU0xPV19TUEVFRDtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIGlzQXRCb3VuZGFyeSh2ZWxvY2l0eSkge1xuICAgICAgICBpZiAoIXRoaXMuc2Nyb2xsYWJsZUNvbnRlbnQgfHwgIXRoaXMudGltZUdyaWQgfHwgIXRoaXMuZHJhZ2dlZEVsZW1lbnQpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIGNvbnN0IGF0VG9wID0gdGhpcy5zY3JvbGxhYmxlQ29udGVudC5zY3JvbGxUb3AgPD0gMCAmJiB2ZWxvY2l0eSA8IDA7XG4gICAgICAgIGNvbnN0IGF0Qm90dG9tID0gdmVsb2NpdHkgPiAwICYmXG4gICAgICAgICAgICB0aGlzLmRyYWdnZWRFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmJvdHRvbSA+PVxuICAgICAgICAgICAgICAgIHRoaXMudGltZUdyaWQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuYm90dG9tO1xuICAgICAgICByZXR1cm4gYXRUb3AgfHwgYXRCb3R0b207XG4gICAgfVxuICAgIHNldFNjcm9sbGluZ1N0YXRlKHNjcm9sbGluZykge1xuICAgICAgICBpZiAodGhpcy5pc1Njcm9sbGluZyA9PT0gc2Nyb2xsaW5nKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB0aGlzLmlzU2Nyb2xsaW5nID0gc2Nyb2xsaW5nO1xuICAgICAgICBpZiAoc2Nyb2xsaW5nKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ29yZUV2ZW50cy5FREdFX1NDUk9MTF9TVEFSVEVELCB7fSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmluaXRpYWxTY3JvbGxUb3AgPSB0aGlzLnNjcm9sbGFibGVDb250ZW50Py5zY3JvbGxUb3AgPz8gMDtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMuZW1pdChDb3JlRXZlbnRzLkVER0VfU0NST0xMX1NUT1BQRUQsIHt9KTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsICJpbXBvcnQgeyBwaXhlbHNUb01pbnV0ZXMsIG1pbnV0ZXNUb1BpeGVscywgc25hcFRvR3JpZCB9IGZyb20gJy4uL3V0aWxzL1Bvc2l0aW9uVXRpbHMnO1xuaW1wb3J0IHsgQ29yZUV2ZW50cyB9IGZyb20gJy4uL2NvbnN0YW50cy9Db3JlRXZlbnRzJztcbmltcG9ydCB7IFN3cEV2ZW50IH0gZnJvbSAnLi4vdHlwZXMvU3dwRXZlbnQnO1xuZXhwb3J0IGNsYXNzIFJlc2l6ZU1hbmFnZXIge1xuICAgIGNvbnN0cnVjdG9yKGV2ZW50QnVzLCBncmlkQ29uZmlnLCBkYXRlU2VydmljZSkge1xuICAgICAgICB0aGlzLmV2ZW50QnVzID0gZXZlbnRCdXM7XG4gICAgICAgIHRoaXMuZ3JpZENvbmZpZyA9IGdyaWRDb25maWc7XG4gICAgICAgIHRoaXMuZGF0ZVNlcnZpY2UgPSBkYXRlU2VydmljZTtcbiAgICAgICAgdGhpcy5jb250YWluZXIgPSBudWxsO1xuICAgICAgICB0aGlzLnJlc2l6ZVN0YXRlID0gbnVsbDtcbiAgICAgICAgdGhpcy5aX0lOREVYX1JFU0laSU5HID0gJzEwMDAnO1xuICAgICAgICB0aGlzLkFOSU1BVElPTl9TUEVFRCA9IDAuMzU7XG4gICAgICAgIHRoaXMuTUlOX0hFSUdIVF9NSU5VVEVTID0gMTU7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBIYW5kbGUgbW91c2VvdmVyIC0gY3JlYXRlIHJlc2l6ZSBoYW5kbGUgaWYgbm90IGV4aXN0c1xuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5oYW5kbGVNb3VzZU92ZXIgPSAoZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdGFyZ2V0ID0gZS50YXJnZXQ7XG4gICAgICAgICAgICBjb25zdCBldmVudEVsZW1lbnQgPSB0YXJnZXQuY2xvc2VzdCgnc3dwLWV2ZW50Jyk7XG4gICAgICAgICAgICBpZiAoIWV2ZW50RWxlbWVudCB8fCB0aGlzLnJlc2l6ZVN0YXRlKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIGhhbmRsZSBhbHJlYWR5IGV4aXN0c1xuICAgICAgICAgICAgaWYgKCFldmVudEVsZW1lbnQucXVlcnlTZWxlY3RvcignOnNjb3BlID4gc3dwLXJlc2l6ZS1oYW5kbGUnKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGhhbmRsZSA9IHRoaXMuY3JlYXRlUmVzaXplSGFuZGxlKCk7XG4gICAgICAgICAgICAgICAgZXZlbnRFbGVtZW50LmFwcGVuZENoaWxkKGhhbmRsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBIYW5kbGUgcG9pbnRlcmRvd24gLSBzdGFydCByZXNpemUgaWYgb24gaGFuZGxlXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmhhbmRsZVBvaW50ZXJEb3duID0gKGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGhhbmRsZSA9IGUudGFyZ2V0LmNsb3Nlc3QoJ3N3cC1yZXNpemUtaGFuZGxlJyk7XG4gICAgICAgICAgICBpZiAoIWhhbmRsZSlcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICBjb25zdCBlbGVtZW50ID0gaGFuZGxlLnBhcmVudEVsZW1lbnQ7XG4gICAgICAgICAgICBpZiAoIWVsZW1lbnQpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgY29uc3QgZXZlbnRJZCA9IGVsZW1lbnQuZGF0YXNldC5ldmVudElkIHx8ICcnO1xuICAgICAgICAgICAgY29uc3Qgc3RhcnRIZWlnaHQgPSBlbGVtZW50Lm9mZnNldEhlaWdodDtcbiAgICAgICAgICAgIGNvbnN0IHN0YXJ0RHVyYXRpb25NaW51dGVzID0gcGl4ZWxzVG9NaW51dGVzKHN0YXJ0SGVpZ2h0LCB0aGlzLmdyaWRDb25maWcpO1xuICAgICAgICAgICAgLy8gU3RvcmUgcHJldmlvdXMgei1pbmRleFxuICAgICAgICAgICAgY29uc3QgY29udGFpbmVyID0gZWxlbWVudC5jbG9zZXN0KCdzd3AtZXZlbnQtZ3JvdXAnKSA/PyBlbGVtZW50O1xuICAgICAgICAgICAgY29uc3QgcHJldlpJbmRleCA9IGNvbnRhaW5lci5zdHlsZS56SW5kZXg7XG4gICAgICAgICAgICAvLyBTZXQgcmVzaXplIHN0YXRlXG4gICAgICAgICAgICB0aGlzLnJlc2l6ZVN0YXRlID0ge1xuICAgICAgICAgICAgICAgIGV2ZW50SWQsXG4gICAgICAgICAgICAgICAgZWxlbWVudCxcbiAgICAgICAgICAgICAgICBoYW5kbGVFbGVtZW50OiBoYW5kbGUsXG4gICAgICAgICAgICAgICAgc3RhcnRZOiBlLmNsaWVudFksXG4gICAgICAgICAgICAgICAgc3RhcnRIZWlnaHQsXG4gICAgICAgICAgICAgICAgc3RhcnREdXJhdGlvbk1pbnV0ZXMsXG4gICAgICAgICAgICAgICAgcG9pbnRlcklkOiBlLnBvaW50ZXJJZCxcbiAgICAgICAgICAgICAgICBwcmV2WkluZGV4LFxuICAgICAgICAgICAgICAgIC8vIEFuaW1hdGlvbiBzdGF0ZVxuICAgICAgICAgICAgICAgIGN1cnJlbnRIZWlnaHQ6IHN0YXJ0SGVpZ2h0LFxuICAgICAgICAgICAgICAgIHRhcmdldEhlaWdodDogc3RhcnRIZWlnaHQsXG4gICAgICAgICAgICAgICAgYW5pbWF0aW9uSWQ6IG51bGxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICAvLyBFbGV2YXRlIHotaW5kZXhcbiAgICAgICAgICAgIGNvbnRhaW5lci5zdHlsZS56SW5kZXggPSB0aGlzLlpfSU5ERVhfUkVTSVpJTkc7XG4gICAgICAgICAgICAvLyBDYXB0dXJlIHBvaW50ZXIgZm9yIHNtb290aCB0cmFja2luZ1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBoYW5kbGUuc2V0UG9pbnRlckNhcHR1cmUoZS5wb2ludGVySWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignUG9pbnRlciBjYXB0dXJlIGZhaWxlZDonLCBlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQWRkIGdsb2JhbCByZXNpemluZyBjbGFzc1xuICAgICAgICAgICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsYXNzTGlzdC5hZGQoJ3N3cC0tcmVzaXppbmcnKTtcbiAgICAgICAgICAgIC8vIEVtaXQgcmVzaXplIHN0YXJ0IGV2ZW50XG4gICAgICAgICAgICB0aGlzLmV2ZW50QnVzLmVtaXQoQ29yZUV2ZW50cy5FVkVOVF9SRVNJWkVfU1RBUlQsIHtcbiAgICAgICAgICAgICAgICBldmVudElkLFxuICAgICAgICAgICAgICAgIGVsZW1lbnQsXG4gICAgICAgICAgICAgICAgc3RhcnRIZWlnaHRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogSGFuZGxlIHBvaW50ZXJtb3ZlIC0gdXBkYXRlIHRhcmdldCBoZWlnaHQgZHVyaW5nIHJlc2l6ZVxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5oYW5kbGVQb2ludGVyTW92ZSA9IChlKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXRoaXMucmVzaXplU3RhdGUpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgY29uc3QgZGVsdGFZID0gZS5jbGllbnRZIC0gdGhpcy5yZXNpemVTdGF0ZS5zdGFydFk7XG4gICAgICAgICAgICBjb25zdCBtaW5IZWlnaHQgPSAodGhpcy5NSU5fSEVJR0hUX01JTlVURVMgLyA2MCkgKiB0aGlzLmdyaWRDb25maWcuaG91ckhlaWdodDtcbiAgICAgICAgICAgIGNvbnN0IG5ld0hlaWdodCA9IE1hdGgubWF4KG1pbkhlaWdodCwgdGhpcy5yZXNpemVTdGF0ZS5zdGFydEhlaWdodCArIGRlbHRhWSk7XG4gICAgICAgICAgICAvLyBTZXQgdGFyZ2V0IGhlaWdodCBmb3IgYW5pbWF0aW9uXG4gICAgICAgICAgICB0aGlzLnJlc2l6ZVN0YXRlLnRhcmdldEhlaWdodCA9IG5ld0hlaWdodDtcbiAgICAgICAgICAgIC8vIFN0YXJ0IGFuaW1hdGlvbiBpZiBub3QgcnVubmluZ1xuICAgICAgICAgICAgaWYgKHRoaXMucmVzaXplU3RhdGUuYW5pbWF0aW9uSWQgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFuaW1hdGVIZWlnaHQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJBRiBhbmltYXRpb24gbG9vcCBmb3Igc21vb3RoIGhlaWdodCBpbnRlcnBvbGF0aW9uXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmFuaW1hdGVIZWlnaHQgPSAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXRoaXMucmVzaXplU3RhdGUpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgY29uc3QgZGlmZiA9IHRoaXMucmVzaXplU3RhdGUudGFyZ2V0SGVpZ2h0IC0gdGhpcy5yZXNpemVTdGF0ZS5jdXJyZW50SGVpZ2h0O1xuICAgICAgICAgICAgLy8gU3RvcCBhbmltYXRpb24gd2hlbiBjbG9zZSBlbm91Z2hcbiAgICAgICAgICAgIGlmIChNYXRoLmFicyhkaWZmKSA8IDAuNSkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplU3RhdGUuYW5pbWF0aW9uSWQgPSBudWxsO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEludGVycG9sYXRlIHRvd2FyZHMgdGFyZ2V0ICgzNSUgcGVyIGZyYW1lIGxpa2UgVjEpXG4gICAgICAgICAgICB0aGlzLnJlc2l6ZVN0YXRlLmN1cnJlbnRIZWlnaHQgKz0gZGlmZiAqIHRoaXMuQU5JTUFUSU9OX1NQRUVEO1xuICAgICAgICAgICAgdGhpcy5yZXNpemVTdGF0ZS5lbGVtZW50LnN0eWxlLmhlaWdodCA9IGAke3RoaXMucmVzaXplU3RhdGUuY3VycmVudEhlaWdodH1weGA7XG4gICAgICAgICAgICAvLyBVcGRhdGUgdGltZXN0YW1wIGRpc3BsYXkgKHNuYXBwZWQpXG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVRpbWVzdGFtcERpc3BsYXkoKTtcbiAgICAgICAgICAgIC8vIENvbnRpbnVlIGFuaW1hdGlvblxuICAgICAgICAgICAgdGhpcy5yZXNpemVTdGF0ZS5hbmltYXRpb25JZCA9IHJlcXVlc3RBbmltYXRpb25GcmFtZSh0aGlzLmFuaW1hdGVIZWlnaHQpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogSGFuZGxlIHBvaW50ZXJ1cCAtIGZpbmlzaCByZXNpemVcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuaGFuZGxlUG9pbnRlclVwID0gKGUpID0+IHtcbiAgICAgICAgICAgIGlmICghdGhpcy5yZXNpemVTdGF0ZSlcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAvLyBDYW5jZWwgYW55IHBlbmRpbmcgYW5pbWF0aW9uXG4gICAgICAgICAgICBpZiAodGhpcy5yZXNpemVTdGF0ZS5hbmltYXRpb25JZCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHRoaXMucmVzaXplU3RhdGUuYW5pbWF0aW9uSWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gUmVsZWFzZSBwb2ludGVyIGNhcHR1cmVcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNpemVTdGF0ZS5oYW5kbGVFbGVtZW50LnJlbGVhc2VQb2ludGVyQ2FwdHVyZShlLnBvaW50ZXJJZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdQb2ludGVyIHJlbGVhc2UgZmFpbGVkOicsIGVycik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBTbmFwIGZpbmFsIGhlaWdodCB0byBncmlkXG4gICAgICAgICAgICB0aGlzLnNuYXBUb0dyaWRGaW5hbCgpO1xuICAgICAgICAgICAgLy8gVXBkYXRlIHRpbWVzdGFtcCBvbmUgZmluYWwgdGltZVxuICAgICAgICAgICAgdGhpcy51cGRhdGVUaW1lc3RhbXBEaXNwbGF5KCk7XG4gICAgICAgICAgICAvLyBSZXN0b3JlIHotaW5kZXhcbiAgICAgICAgICAgIGNvbnN0IGNvbnRhaW5lciA9IHRoaXMucmVzaXplU3RhdGUuZWxlbWVudC5jbG9zZXN0KCdzd3AtZXZlbnQtZ3JvdXAnKSA/PyB0aGlzLnJlc2l6ZVN0YXRlLmVsZW1lbnQ7XG4gICAgICAgICAgICBjb250YWluZXIuc3R5bGUuekluZGV4ID0gdGhpcy5yZXNpemVTdGF0ZS5wcmV2WkluZGV4O1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGdsb2JhbCByZXNpemluZyBjbGFzc1xuICAgICAgICAgICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoJ3N3cC0tcmVzaXppbmcnKTtcbiAgICAgICAgICAgIC8vIEdldCBjb2x1bW5LZXkgYW5kIGRhdGUgZnJvbSBwYXJlbnQgY29sdW1uXG4gICAgICAgICAgICBjb25zdCBjb2x1bW4gPSB0aGlzLnJlc2l6ZVN0YXRlLmVsZW1lbnQuY2xvc2VzdCgnc3dwLWRheS1jb2x1bW4nKTtcbiAgICAgICAgICAgIGNvbnN0IGNvbHVtbktleSA9IGNvbHVtbj8uZGF0YXNldC5jb2x1bW5LZXkgfHwgJyc7XG4gICAgICAgICAgICBjb25zdCBkYXRlID0gY29sdW1uPy5kYXRhc2V0LmRhdGUgfHwgJyc7XG4gICAgICAgICAgICAvLyBDcmVhdGUgU3dwRXZlbnQgZnJvbSBlbGVtZW50IChyZWFkcyB0b3AvaGVpZ2h0L2V2ZW50SWQgZnJvbSBlbGVtZW50KVxuICAgICAgICAgICAgY29uc3Qgc3dwRXZlbnQgPSBTd3BFdmVudC5mcm9tRWxlbWVudCh0aGlzLnJlc2l6ZVN0YXRlLmVsZW1lbnQsIGNvbHVtbktleSwgZGF0ZSwgdGhpcy5ncmlkQ29uZmlnKTtcbiAgICAgICAgICAgIC8vIEVtaXQgcmVzaXplIGVuZCBldmVudFxuICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENvcmVFdmVudHMuRVZFTlRfUkVTSVpFX0VORCwge1xuICAgICAgICAgICAgICAgIHN3cEV2ZW50XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIC8vIFJlc2V0IHN0YXRlXG4gICAgICAgICAgICB0aGlzLnJlc2l6ZVN0YXRlID0gbnVsbDtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSByZXNpemUgZnVuY3Rpb25hbGl0eSBvbiBjb250YWluZXJcbiAgICAgKi9cbiAgICBpbml0KGNvbnRhaW5lcikge1xuICAgICAgICB0aGlzLmNvbnRhaW5lciA9IGNvbnRhaW5lcjtcbiAgICAgICAgLy8gTW91c2VvdmVyIGxpc3RlbmVyIGZvciBoYW5kbGUgY3JlYXRpb24gKGNhcHR1cmUgcGhhc2UgbGlrZSBWMSlcbiAgICAgICAgY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlb3ZlcicsIHRoaXMuaGFuZGxlTW91c2VPdmVyLCB0cnVlKTtcbiAgICAgICAgLy8gUG9pbnRlciBsaXN0ZW5lcnMgZm9yIHJlc2l6ZSAoY2FwdHVyZSBwaGFzZSBsaWtlIFYxKVxuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdwb2ludGVyZG93bicsIHRoaXMuaGFuZGxlUG9pbnRlckRvd24sIHRydWUpO1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdwb2ludGVybW92ZScsIHRoaXMuaGFuZGxlUG9pbnRlck1vdmUsIHRydWUpO1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdwb2ludGVydXAnLCB0aGlzLmhhbmRsZVBvaW50ZXJVcCwgdHJ1ZSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENyZWF0ZSByZXNpemUgaGFuZGxlIGVsZW1lbnRcbiAgICAgKi9cbiAgICBjcmVhdGVSZXNpemVIYW5kbGUoKSB7XG4gICAgICAgIGNvbnN0IGhhbmRsZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3N3cC1yZXNpemUtaGFuZGxlJyk7XG4gICAgICAgIGhhbmRsZS5zZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnLCAnUmVzaXplIGV2ZW50Jyk7XG4gICAgICAgIGhhbmRsZS5zZXRBdHRyaWJ1dGUoJ3JvbGUnLCAnc2VwYXJhdG9yJyk7XG4gICAgICAgIHJldHVybiBoYW5kbGU7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSB0aW1lc3RhbXAgZGlzcGxheSB3aXRoIHNuYXBwZWQgZW5kIHRpbWVcbiAgICAgKi9cbiAgICB1cGRhdGVUaW1lc3RhbXBEaXNwbGF5KCkge1xuICAgICAgICBpZiAoIXRoaXMucmVzaXplU3RhdGUpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNvbnN0IHRpbWVFbCA9IHRoaXMucmVzaXplU3RhdGUuZWxlbWVudC5xdWVyeVNlbGVjdG9yKCdzd3AtZXZlbnQtdGltZScpO1xuICAgICAgICBpZiAoIXRpbWVFbClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgLy8gR2V0IHN0YXJ0IHRpbWUgZnJvbSBlbGVtZW50IHBvc2l0aW9uXG4gICAgICAgIGNvbnN0IHRvcCA9IHBhcnNlRmxvYXQodGhpcy5yZXNpemVTdGF0ZS5lbGVtZW50LnN0eWxlLnRvcCkgfHwgMDtcbiAgICAgICAgY29uc3Qgc3RhcnRNaW51dGVzRnJvbUdyaWQgPSBwaXhlbHNUb01pbnV0ZXModG9wLCB0aGlzLmdyaWRDb25maWcpO1xuICAgICAgICBjb25zdCBzdGFydE1pbnV0ZXMgPSAodGhpcy5ncmlkQ29uZmlnLmRheVN0YXJ0SG91ciAqIDYwKSArIHN0YXJ0TWludXRlc0Zyb21HcmlkO1xuICAgICAgICAvLyBDYWxjdWxhdGUgc25hcHBlZCBlbmQgdGltZSBmcm9tIGN1cnJlbnQgaGVpZ2h0XG4gICAgICAgIGNvbnN0IHNuYXBwZWRIZWlnaHQgPSBzbmFwVG9HcmlkKHRoaXMucmVzaXplU3RhdGUuY3VycmVudEhlaWdodCwgdGhpcy5ncmlkQ29uZmlnKTtcbiAgICAgICAgY29uc3QgZHVyYXRpb25NaW51dGVzID0gcGl4ZWxzVG9NaW51dGVzKHNuYXBwZWRIZWlnaHQsIHRoaXMuZ3JpZENvbmZpZyk7XG4gICAgICAgIGNvbnN0IGVuZE1pbnV0ZXMgPSBzdGFydE1pbnV0ZXMgKyBkdXJhdGlvbk1pbnV0ZXM7XG4gICAgICAgIC8vIEZvcm1hdCBhbmQgdXBkYXRlXG4gICAgICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5taW51dGVzVG9EYXRlKHN0YXJ0TWludXRlcyk7XG4gICAgICAgIGNvbnN0IGVuZCA9IHRoaXMubWludXRlc1RvRGF0ZShlbmRNaW51dGVzKTtcbiAgICAgICAgdGltZUVsLnRleHRDb250ZW50ID0gdGhpcy5kYXRlU2VydmljZS5mb3JtYXRUaW1lUmFuZ2Uoc3RhcnQsIGVuZCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENvbnZlcnQgbWludXRlcyBzaW5jZSBtaWRuaWdodCB0byBEYXRlXG4gICAgICovXG4gICAgbWludXRlc1RvRGF0ZShtaW51dGVzKSB7XG4gICAgICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZSgpO1xuICAgICAgICBkYXRlLnNldEhvdXJzKE1hdGguZmxvb3IobWludXRlcyAvIDYwKSAlIDI0LCBtaW51dGVzICUgNjAsIDAsIDApO1xuICAgICAgICByZXR1cm4gZGF0ZTtcbiAgICB9XG4gICAgO1xuICAgIC8qKlxuICAgICAqIFNuYXAgZmluYWwgaGVpZ2h0IHRvIGdyaWQgaW50ZXJ2YWxcbiAgICAgKi9cbiAgICBzbmFwVG9HcmlkRmluYWwoKSB7XG4gICAgICAgIGlmICghdGhpcy5yZXNpemVTdGF0ZSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY29uc3QgY3VycmVudEhlaWdodCA9IHRoaXMucmVzaXplU3RhdGUuZWxlbWVudC5vZmZzZXRIZWlnaHQ7XG4gICAgICAgIGNvbnN0IHNuYXBwZWRIZWlnaHQgPSBzbmFwVG9HcmlkKGN1cnJlbnRIZWlnaHQsIHRoaXMuZ3JpZENvbmZpZyk7XG4gICAgICAgIGNvbnN0IG1pbkhlaWdodCA9IG1pbnV0ZXNUb1BpeGVscyh0aGlzLk1JTl9IRUlHSFRfTUlOVVRFUywgdGhpcy5ncmlkQ29uZmlnKTtcbiAgICAgICAgY29uc3QgZmluYWxIZWlnaHQgPSBNYXRoLm1heChtaW5IZWlnaHQsIHNuYXBwZWRIZWlnaHQpO1xuICAgICAgICB0aGlzLnJlc2l6ZVN0YXRlLmVsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gYCR7ZmluYWxIZWlnaHR9cHhgO1xuICAgICAgICB0aGlzLnJlc2l6ZVN0YXRlLmN1cnJlbnRIZWlnaHQgPSBmaW5hbEhlaWdodDtcbiAgICB9XG59XG4iLCAiaW1wb3J0IHsgQ29yZUV2ZW50cyB9IGZyb20gJy4uL2NvbnN0YW50cy9Db3JlRXZlbnRzJztcbmV4cG9ydCBjbGFzcyBFdmVudFBlcnNpc3RlbmNlTWFuYWdlciB7XG4gICAgY29uc3RydWN0b3IoZXZlbnRTZXJ2aWNlLCBldmVudEJ1cywgZGF0ZVNlcnZpY2UpIHtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UgPSBldmVudFNlcnZpY2U7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMgPSBldmVudEJ1cztcbiAgICAgICAgdGhpcy5kYXRlU2VydmljZSA9IGRhdGVTZXJ2aWNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogSGFuZGxlIGRyYWcgZW5kIC0gdXBkYXRlIGV2ZW50IHBvc2l0aW9uIGluIEluZGV4ZWREQlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5oYW5kbGVEcmFnRW5kID0gYXN5bmMgKGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSBlLmRldGFpbDtcbiAgICAgICAgICAgIGNvbnN0IHsgc3dwRXZlbnQgfSA9IHBheWxvYWQ7XG4gICAgICAgICAgICAvLyBHZXQgZXhpc3RpbmcgZXZlbnQgdG8gbWVyZ2Ugd2l0aFxuICAgICAgICAgICAgY29uc3QgZXZlbnQgPSBhd2FpdCB0aGlzLmV2ZW50U2VydmljZS5nZXQoc3dwRXZlbnQuZXZlbnRJZCk7XG4gICAgICAgICAgICBpZiAoIWV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBFdmVudFBlcnNpc3RlbmNlTWFuYWdlcjogRXZlbnQgJHtzd3BFdmVudC5ldmVudElkfSBub3QgZm91bmRgKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBQYXJzZSByZXNvdXJjZUlkIGZyb20gY29sdW1uS2V5IGlmIHByZXNlbnRcbiAgICAgICAgICAgIGNvbnN0IHsgcmVzb3VyY2UgfSA9IHRoaXMuZGF0ZVNlcnZpY2UucGFyc2VDb2x1bW5LZXkoc3dwRXZlbnQuY29sdW1uS2V5KTtcbiAgICAgICAgICAgIC8vIFVwZGF0ZSBhbmQgc2F2ZSAtIHN0YXJ0L2VuZCBhbHJlYWR5IGNhbGN1bGF0ZWQgaW4gU3dwRXZlbnRcbiAgICAgICAgICAgIC8vIFNldCBhbGxEYXkgYmFzZWQgb24gZHJvcCB0YXJnZXQ6XG4gICAgICAgICAgICAvLyAtIGhlYWRlcjogYWxsRGF5ID0gdHJ1ZVxuICAgICAgICAgICAgLy8gLSBncmlkOiBhbGxEYXkgPSBmYWxzZSAoY29udmVydHMgYWxsRGF5IGV2ZW50IHRvIHRpbWVkKVxuICAgICAgICAgICAgY29uc3QgdXBkYXRlZEV2ZW50ID0ge1xuICAgICAgICAgICAgICAgIC4uLmV2ZW50LFxuICAgICAgICAgICAgICAgIHN0YXJ0OiBzd3BFdmVudC5zdGFydCxcbiAgICAgICAgICAgICAgICBlbmQ6IHN3cEV2ZW50LmVuZCxcbiAgICAgICAgICAgICAgICByZXNvdXJjZUlkOiByZXNvdXJjZSA/PyBldmVudC5yZXNvdXJjZUlkLFxuICAgICAgICAgICAgICAgIGFsbERheTogcGF5bG9hZC50YXJnZXQgPT09ICdoZWFkZXInLFxuICAgICAgICAgICAgICAgIHN5bmNTdGF0dXM6ICdwZW5kaW5nJ1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuZXZlbnRTZXJ2aWNlLnNhdmUodXBkYXRlZEV2ZW50KTtcbiAgICAgICAgICAgIC8vIEVtaXQgRVZFTlRfVVBEQVRFRCBmb3IgRXZlbnRSZW5kZXJlciB0byByZS1yZW5kZXIgYWZmZWN0ZWQgY29sdW1uc1xuICAgICAgICAgICAgY29uc3QgdXBkYXRlUGF5bG9hZCA9IHtcbiAgICAgICAgICAgICAgICBldmVudElkOiB1cGRhdGVkRXZlbnQuaWQsXG4gICAgICAgICAgICAgICAgc291cmNlQ29sdW1uS2V5OiBwYXlsb2FkLnNvdXJjZUNvbHVtbktleSxcbiAgICAgICAgICAgICAgICB0YXJnZXRDb2x1bW5LZXk6IHN3cEV2ZW50LmNvbHVtbktleVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMuZW1pdChDb3JlRXZlbnRzLkVWRU5UX1VQREFURUQsIHVwZGF0ZVBheWxvYWQpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogSGFuZGxlIHJlc2l6ZSBlbmQgLSB1cGRhdGUgZXZlbnQgZHVyYXRpb24gaW4gSW5kZXhlZERCXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmhhbmRsZVJlc2l6ZUVuZCA9IGFzeW5jIChlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwYXlsb2FkID0gZS5kZXRhaWw7XG4gICAgICAgICAgICBjb25zdCB7IHN3cEV2ZW50IH0gPSBwYXlsb2FkO1xuICAgICAgICAgICAgLy8gR2V0IGV4aXN0aW5nIGV2ZW50IHRvIG1lcmdlIHdpdGhcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50ID0gYXdhaXQgdGhpcy5ldmVudFNlcnZpY2UuZ2V0KHN3cEV2ZW50LmV2ZW50SWQpO1xuICAgICAgICAgICAgaWYgKCFldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgRXZlbnRQZXJzaXN0ZW5jZU1hbmFnZXI6IEV2ZW50ICR7c3dwRXZlbnQuZXZlbnRJZH0gbm90IGZvdW5kYCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gVXBkYXRlIGFuZCBzYXZlIC0gZW5kIGFscmVhZHkgY2FsY3VsYXRlZCBpbiBTd3BFdmVudFxuICAgICAgICAgICAgY29uc3QgdXBkYXRlZEV2ZW50ID0ge1xuICAgICAgICAgICAgICAgIC4uLmV2ZW50LFxuICAgICAgICAgICAgICAgIGVuZDogc3dwRXZlbnQuZW5kLFxuICAgICAgICAgICAgICAgIHN5bmNTdGF0dXM6ICdwZW5kaW5nJ1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuZXZlbnRTZXJ2aWNlLnNhdmUodXBkYXRlZEV2ZW50KTtcbiAgICAgICAgICAgIC8vIEVtaXQgRVZFTlRfVVBEQVRFRCBmb3IgRXZlbnRSZW5kZXJlciB0byByZS1yZW5kZXIgdGhlIGNvbHVtblxuICAgICAgICAgICAgLy8gUmVzaXplIHN0YXlzIGluIHNhbWUgY29sdW1uLCBzbyBzb3VyY2UgYW5kIHRhcmdldCBhcmUgdGhlIHNhbWVcbiAgICAgICAgICAgIGNvbnN0IHVwZGF0ZVBheWxvYWQgPSB7XG4gICAgICAgICAgICAgICAgZXZlbnRJZDogdXBkYXRlZEV2ZW50LmlkLFxuICAgICAgICAgICAgICAgIHNvdXJjZUNvbHVtbktleTogc3dwRXZlbnQuY29sdW1uS2V5LFxuICAgICAgICAgICAgICAgIHRhcmdldENvbHVtbktleTogc3dwRXZlbnQuY29sdW1uS2V5XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy5lbWl0KENvcmVFdmVudHMuRVZFTlRfVVBEQVRFRCwgdXBkYXRlUGF5bG9hZCk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc2V0dXBMaXN0ZW5lcnMoKTtcbiAgICB9XG4gICAgc2V0dXBMaXN0ZW5lcnMoKSB7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMub24oQ29yZUV2ZW50cy5FVkVOVF9EUkFHX0VORCwgdGhpcy5oYW5kbGVEcmFnRW5kKTtcbiAgICAgICAgdGhpcy5ldmVudEJ1cy5vbihDb3JlRXZlbnRzLkVWRU5UX1JFU0laRV9FTkQsIHRoaXMuaGFuZGxlUmVzaXplRW5kKTtcbiAgICB9XG59XG4iLCAiaW1wb3J0IHsgQ29udGFpbmVyIH0gZnJvbSAnQG5vdmFkaS9jb3JlJztcbmltcG9ydCB7IERhdGVSZW5kZXJlciB9IGZyb20gJy4vZmVhdHVyZXMvZGF0ZS9EYXRlUmVuZGVyZXInO1xuaW1wb3J0IHsgRGF0ZVNlcnZpY2UgfSBmcm9tICcuL2NvcmUvRGF0ZVNlcnZpY2UnO1xuaW1wb3J0IHsgUmVzb3VyY2VSZW5kZXJlciB9IGZyb20gJy4vZmVhdHVyZXMvcmVzb3VyY2UvUmVzb3VyY2VSZW5kZXJlcic7XG5pbXBvcnQgeyBUZWFtUmVuZGVyZXIgfSBmcm9tICcuL2ZlYXR1cmVzL3RlYW0vVGVhbVJlbmRlcmVyJztcbmltcG9ydCB7IERlcGFydG1lbnRSZW5kZXJlciB9IGZyb20gJy4vZmVhdHVyZXMvZGVwYXJ0bWVudC9EZXBhcnRtZW50UmVuZGVyZXInO1xuaW1wb3J0IHsgQ2FsZW5kYXJPcmNoZXN0cmF0b3IgfSBmcm9tICcuL2NvcmUvQ2FsZW5kYXJPcmNoZXN0cmF0b3InO1xuaW1wb3J0IHsgQ2FsZW5kYXJBcHAgfSBmcm9tICcuL2NvcmUvQ2FsZW5kYXJBcHAnO1xuaW1wb3J0IHsgVGltZUF4aXNSZW5kZXJlciB9IGZyb20gJy4vZmVhdHVyZXMvdGltZWF4aXMvVGltZUF4aXNSZW5kZXJlcic7XG5pbXBvcnQgeyBTY3JvbGxNYW5hZ2VyIH0gZnJvbSAnLi9jb3JlL1Njcm9sbE1hbmFnZXInO1xuaW1wb3J0IHsgSGVhZGVyRHJhd2VyTWFuYWdlciB9IGZyb20gJy4vY29yZS9IZWFkZXJEcmF3ZXJNYW5hZ2VyJztcbmltcG9ydCB7IE1vY2tUZWFtU3RvcmUsIE1vY2tSZXNvdXJjZVN0b3JlIH0gZnJvbSAnLi9kZW1vL01vY2tTdG9yZXMnO1xuaW1wb3J0IHsgRGVtb0FwcCB9IGZyb20gJy4vZGVtby9EZW1vQXBwJztcbi8vIEV2ZW50IHN5c3RlbVxuaW1wb3J0IHsgRXZlbnRCdXMgfSBmcm9tICcuL2NvcmUvRXZlbnRCdXMnO1xuLy8gU3RvcmFnZVxuaW1wb3J0IHsgSW5kZXhlZERCQ29udGV4dCB9IGZyb20gJy4vc3RvcmFnZS9JbmRleGVkREJDb250ZXh0JztcbmltcG9ydCB7IEV2ZW50U3RvcmUgfSBmcm9tICcuL3N0b3JhZ2UvZXZlbnRzL0V2ZW50U3RvcmUnO1xuaW1wb3J0IHsgRXZlbnRTZXJ2aWNlIH0gZnJvbSAnLi9zdG9yYWdlL2V2ZW50cy9FdmVudFNlcnZpY2UnO1xuaW1wb3J0IHsgUmVzb3VyY2VTdG9yZSB9IGZyb20gJy4vc3RvcmFnZS9yZXNvdXJjZXMvUmVzb3VyY2VTdG9yZSc7XG5pbXBvcnQgeyBSZXNvdXJjZVNlcnZpY2UgfSBmcm9tICcuL3N0b3JhZ2UvcmVzb3VyY2VzL1Jlc291cmNlU2VydmljZSc7XG5pbXBvcnQgeyBCb29raW5nU3RvcmUgfSBmcm9tICcuL3N0b3JhZ2UvYm9va2luZ3MvQm9va2luZ1N0b3JlJztcbmltcG9ydCB7IEJvb2tpbmdTZXJ2aWNlIH0gZnJvbSAnLi9zdG9yYWdlL2Jvb2tpbmdzL0Jvb2tpbmdTZXJ2aWNlJztcbmltcG9ydCB7IEN1c3RvbWVyU3RvcmUgfSBmcm9tICcuL3N0b3JhZ2UvY3VzdG9tZXJzL0N1c3RvbWVyU3RvcmUnO1xuaW1wb3J0IHsgQ3VzdG9tZXJTZXJ2aWNlIH0gZnJvbSAnLi9zdG9yYWdlL2N1c3RvbWVycy9DdXN0b21lclNlcnZpY2UnO1xuaW1wb3J0IHsgVGVhbVN0b3JlIH0gZnJvbSAnLi9zdG9yYWdlL3RlYW1zL1RlYW1TdG9yZSc7XG5pbXBvcnQgeyBUZWFtU2VydmljZSB9IGZyb20gJy4vc3RvcmFnZS90ZWFtcy9UZWFtU2VydmljZSc7XG5pbXBvcnQgeyBEZXBhcnRtZW50U3RvcmUgfSBmcm9tICcuL3N0b3JhZ2UvZGVwYXJ0bWVudHMvRGVwYXJ0bWVudFN0b3JlJztcbmltcG9ydCB7IERlcGFydG1lbnRTZXJ2aWNlIH0gZnJvbSAnLi9zdG9yYWdlL2RlcGFydG1lbnRzL0RlcGFydG1lbnRTZXJ2aWNlJztcbmltcG9ydCB7IFNldHRpbmdzU3RvcmUgfSBmcm9tICcuL3N0b3JhZ2Uvc2V0dGluZ3MvU2V0dGluZ3NTdG9yZSc7XG5pbXBvcnQgeyBTZXR0aW5nc1NlcnZpY2UgfSBmcm9tICcuL3N0b3JhZ2Uvc2V0dGluZ3MvU2V0dGluZ3NTZXJ2aWNlJztcbmltcG9ydCB7IFZpZXdDb25maWdTdG9yZSB9IGZyb20gJy4vc3RvcmFnZS92aWV3Y29uZmlncy9WaWV3Q29uZmlnU3RvcmUnO1xuaW1wb3J0IHsgVmlld0NvbmZpZ1NlcnZpY2UgfSBmcm9tICcuL3N0b3JhZ2Uvdmlld2NvbmZpZ3MvVmlld0NvbmZpZ1NlcnZpY2UnO1xuLy8gQXVkaXRcbmltcG9ydCB7IEF1ZGl0U3RvcmUgfSBmcm9tICcuL3N0b3JhZ2UvYXVkaXQvQXVkaXRTdG9yZSc7XG5pbXBvcnQgeyBBdWRpdFNlcnZpY2UgfSBmcm9tICcuL3N0b3JhZ2UvYXVkaXQvQXVkaXRTZXJ2aWNlJztcbmltcG9ydCB7IE1vY2tFdmVudFJlcG9zaXRvcnkgfSBmcm9tICcuL3JlcG9zaXRvcmllcy9Nb2NrRXZlbnRSZXBvc2l0b3J5JztcbmltcG9ydCB7IE1vY2tSZXNvdXJjZVJlcG9zaXRvcnkgfSBmcm9tICcuL3JlcG9zaXRvcmllcy9Nb2NrUmVzb3VyY2VSZXBvc2l0b3J5JztcbmltcG9ydCB7IE1vY2tCb29raW5nUmVwb3NpdG9yeSB9IGZyb20gJy4vcmVwb3NpdG9yaWVzL01vY2tCb29raW5nUmVwb3NpdG9yeSc7XG5pbXBvcnQgeyBNb2NrQ3VzdG9tZXJSZXBvc2l0b3J5IH0gZnJvbSAnLi9yZXBvc2l0b3JpZXMvTW9ja0N1c3RvbWVyUmVwb3NpdG9yeSc7XG5pbXBvcnQgeyBNb2NrQXVkaXRSZXBvc2l0b3J5IH0gZnJvbSAnLi9yZXBvc2l0b3JpZXMvTW9ja0F1ZGl0UmVwb3NpdG9yeSc7XG5pbXBvcnQgeyBNb2NrVGVhbVJlcG9zaXRvcnkgfSBmcm9tICcuL3JlcG9zaXRvcmllcy9Nb2NrVGVhbVJlcG9zaXRvcnknO1xuaW1wb3J0IHsgTW9ja0RlcGFydG1lbnRSZXBvc2l0b3J5IH0gZnJvbSAnLi9yZXBvc2l0b3JpZXMvTW9ja0RlcGFydG1lbnRSZXBvc2l0b3J5JztcbmltcG9ydCB7IE1vY2tTZXR0aW5nc1JlcG9zaXRvcnkgfSBmcm9tICcuL3JlcG9zaXRvcmllcy9Nb2NrU2V0dGluZ3NSZXBvc2l0b3J5JztcbmltcG9ydCB7IE1vY2tWaWV3Q29uZmlnUmVwb3NpdG9yeSB9IGZyb20gJy4vcmVwb3NpdG9yaWVzL01vY2tWaWV3Q29uZmlnUmVwb3NpdG9yeSc7XG4vLyBXb3JrZXJzXG5pbXBvcnQgeyBEYXRhU2VlZGVyIH0gZnJvbSAnLi93b3JrZXJzL0RhdGFTZWVkZXInO1xuLy8gRmVhdHVyZXNcbmltcG9ydCB7IEV2ZW50UmVuZGVyZXIgfSBmcm9tICcuL2ZlYXR1cmVzL2V2ZW50L0V2ZW50UmVuZGVyZXInO1xuaW1wb3J0IHsgU2NoZWR1bGVSZW5kZXJlciB9IGZyb20gJy4vZmVhdHVyZXMvc2NoZWR1bGUvU2NoZWR1bGVSZW5kZXJlcic7XG5pbXBvcnQgeyBIZWFkZXJEcmF3ZXJSZW5kZXJlciB9IGZyb20gJy4vZmVhdHVyZXMvaGVhZGVyZHJhd2VyL0hlYWRlckRyYXdlclJlbmRlcmVyJztcbi8vIFNjaGVkdWxlXG5pbXBvcnQgeyBTY2hlZHVsZU92ZXJyaWRlU3RvcmUgfSBmcm9tICcuL3N0b3JhZ2Uvc2NoZWR1bGVzL1NjaGVkdWxlT3ZlcnJpZGVTdG9yZSc7XG5pbXBvcnQgeyBTY2hlZHVsZU92ZXJyaWRlU2VydmljZSB9IGZyb20gJy4vc3RvcmFnZS9zY2hlZHVsZXMvU2NoZWR1bGVPdmVycmlkZVNlcnZpY2UnO1xuaW1wb3J0IHsgUmVzb3VyY2VTY2hlZHVsZVNlcnZpY2UgfSBmcm9tICcuL3N0b3JhZ2Uvc2NoZWR1bGVzL1Jlc291cmNlU2NoZWR1bGVTZXJ2aWNlJztcbi8vIE1hbmFnZXJzXG5pbXBvcnQgeyBEcmFnRHJvcE1hbmFnZXIgfSBmcm9tICcuL21hbmFnZXJzL0RyYWdEcm9wTWFuYWdlcic7XG5pbXBvcnQgeyBFZGdlU2Nyb2xsTWFuYWdlciB9IGZyb20gJy4vbWFuYWdlcnMvRWRnZVNjcm9sbE1hbmFnZXInO1xuaW1wb3J0IHsgUmVzaXplTWFuYWdlciB9IGZyb20gJy4vbWFuYWdlcnMvUmVzaXplTWFuYWdlcic7XG5pbXBvcnQgeyBFdmVudFBlcnNpc3RlbmNlTWFuYWdlciB9IGZyb20gJy4vbWFuYWdlcnMvRXZlbnRQZXJzaXN0ZW5jZU1hbmFnZXInO1xuY29uc3QgZGVmYXVsdFRpbWVGb3JtYXRDb25maWcgPSB7XG4gICAgdGltZXpvbmU6IEludGwuRGF0ZVRpbWVGb3JtYXQoKS5yZXNvbHZlZE9wdGlvbnMoKS50aW1lWm9uZSxcbiAgICB1c2UyNEhvdXJGb3JtYXQ6IHRydWUsXG4gICAgbG9jYWxlOiAnZGEtREsnLFxuICAgIGRhdGVGb3JtYXQ6ICdsb2NhbGUnLFxuICAgIHNob3dTZWNvbmRzOiBmYWxzZVxufTtcbmNvbnN0IGRlZmF1bHRHcmlkQ29uZmlnID0ge1xuICAgIGhvdXJIZWlnaHQ6IDY0LFxuICAgIGRheVN0YXJ0SG91cjogNixcbiAgICBkYXlFbmRIb3VyOiAxOCxcbiAgICBzbmFwSW50ZXJ2YWw6IDE1LFxuICAgIGdyaWRTdGFydFRocmVzaG9sZE1pbnV0ZXM6IDMwXG59O1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUNvbnRhaW5lcigpIHtcbiAgICBjb25zdCBjb250YWluZXIgPSBuZXcgQ29udGFpbmVyKCk7XG4gICAgY29uc3QgYnVpbGRlciA9IGNvbnRhaW5lci5idWlsZGVyKCk7XG4gICAgLy8gQ29uZmlnXG4gICAgYnVpbGRlci5yZWdpc3Rlckluc3RhbmNlKGRlZmF1bHRUaW1lRm9ybWF0Q29uZmlnKS5hcyhcIklUaW1lRm9ybWF0Q29uZmlnXCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJJbnN0YW5jZShkZWZhdWx0R3JpZENvbmZpZykuYXMoXCJJR3JpZENvbmZpZ1wiKTtcbiAgICAvLyBDb3JlIC0gRXZlbnRCdXNcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShFdmVudEJ1cykuYXMoXCJFdmVudEJ1c1wiKTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShFdmVudEJ1cykuYXMoXCJJRXZlbnRCdXNcIik7XG4gICAgLy8gU2VydmljZXNcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShEYXRlU2VydmljZSkuYXMoXCJEYXRlU2VydmljZVwiKS5hdXRvV2lyZSh7XG4gICAgICAgIG1hcFJlc29sdmVyczogW1xuICAgICAgICAgICAgYyA9PiBjLnJlc29sdmVUeXBlKFwiSVRpbWVGb3JtYXRDb25maWdcIiksXG4gICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIC8vIFN0b3JhZ2UgaW5mcmFzdHJ1Y3R1cmVcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShJbmRleGVkREJDb250ZXh0KS5hcyhcIkluZGV4ZWREQkNvbnRleHRcIikuYXV0b1dpcmUoe1xuICAgICAgICBtYXBSZXNvbHZlcnM6IFtcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZUFsbChcIklTdG9yZVwiKVxuICAgICAgICBdXG4gICAgfSk7XG4gICAgLy8gU3RvcmVzIChmb3IgSW5kZXhlZERCIHNjaGVtYSBjcmVhdGlvbilcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShFdmVudFN0b3JlKS5hcyhcIklTdG9yZVwiKTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShSZXNvdXJjZVN0b3JlKS5hcyhcIklTdG9yZVwiKTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShCb29raW5nU3RvcmUpLmFzKFwiSVN0b3JlXCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKEN1c3RvbWVyU3RvcmUpLmFzKFwiSVN0b3JlXCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKFRlYW1TdG9yZSkuYXMoXCJJU3RvcmVcIik7XG4gICAgYnVpbGRlci5yZWdpc3RlclR5cGUoRGVwYXJ0bWVudFN0b3JlKS5hcyhcIklTdG9yZVwiKTtcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShTY2hlZHVsZU92ZXJyaWRlU3RvcmUpLmFzKFwiSVN0b3JlXCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKEF1ZGl0U3RvcmUpLmFzKFwiSVN0b3JlXCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKFNldHRpbmdzU3RvcmUpLmFzKFwiSVN0b3JlXCIpO1xuICAgIGJ1aWxkZXIucmVnaXN0ZXJUeXBlKFZpZXdDb25maWdTdG9yZSkuYXMoXCJJU3RvcmVcIik7XG4gICAgLy8gRW50aXR5IHNlcnZpY2VzIChmb3IgRGF0YVNlZWRlciBwb2x5bW9ycGhpYyBhcnJheSlcbiAgICBidWlsZGVyLnJlZ2lzdGVyVHlwZShFdmVudFNlcnZpY2UpLmFzKFwiSUVudGl0eVNlcnZpY2VcIikuYXV0b1dpcmUoe1xuICAgICAgICBtYXBSZXNvbHZlcnM6IFtcbiAgICAgICAgICAgIGMgPT4gYy5yZXNvbHZlVHlwZShcIkluZGV4ZWREQkNvbnRleHRcIiksXG4gICAgICAgICAgICBjID0+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+IGMucmVzb2x2ZVR5cGUoXCJJRXZlbnRCdXNcIilcbiAgICAgICAgXVxuICAgIH0pO1xuICAgIHJldHVybiBidWlsZGVyLmJ1aWxkKCk7XG59XG4iLCAiaW1wb3J0IHsgY3JlYXRlQ29udGFpbmVyIH0gZnJvbSAnLi4vQ29tcG9zaXRpb25Sb290JztcbmNvbnN0IGNvbnRhaW5lciA9IGNyZWF0ZUNvbnRhaW5lcigpO1xuY29udGFpbmVyLnJlc29sdmVUeXBlKFwiRGVtb0FwcFwiKS5pbml0KCkuY2F0Y2goY29uc29sZS5lcnJvcik7XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBLEtBQUMsU0FBUyxHQUFFLEdBQUU7QUFBQyxrQkFBVSxPQUFPLFdBQVMsZUFBYSxPQUFPLFNBQU8sT0FBTyxVQUFRLEVBQUUsSUFBRSxjQUFZLE9BQU8sVUFBUSxPQUFPLE1BQUksT0FBTyxDQUFDLEtBQUcsSUFBRSxlQUFhLE9BQU8sYUFBVyxhQUFXLEtBQUcsTUFBTSxRQUFNLEVBQUU7QUFBQSxJQUFDLEVBQUUsU0FBTSxXQUFVO0FBQUM7QUFBYSxVQUFJLElBQUUsS0FBSSxJQUFFLEtBQUksSUFBRSxNQUFLLElBQUUsZUFBYyxJQUFFLFVBQVMsSUFBRSxVQUFTLElBQUUsUUFBTyxJQUFFLE9BQU0sSUFBRSxRQUFPLElBQUUsU0FBUSxJQUFFLFdBQVUsSUFBRSxRQUFPLElBQUUsUUFBTyxJQUFFLGdCQUFlLElBQUUsOEZBQTZGLElBQUUsdUZBQXNGLElBQUUsRUFBQyxNQUFLLE1BQUssVUFBUywyREFBMkQsTUFBTSxHQUFHLEdBQUUsUUFBTyx3RkFBd0YsTUFBTSxHQUFHLEdBQUUsU0FBUSxTQUFTQSxJQUFFO0FBQUMsWUFBSUMsS0FBRSxDQUFDLE1BQUssTUFBSyxNQUFLLElBQUksR0FBRUMsS0FBRUYsS0FBRTtBQUFJLGVBQU0sTUFBSUEsTUFBR0MsSUFBR0MsS0FBRSxNQUFJLEVBQUUsS0FBR0QsR0FBRUMsRUFBQyxLQUFHRCxHQUFF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LGFBQWE7QUFBQSxNQUNoQyxPQUFLLEVBQUUsWUFBWSxlQUFlO0FBQUEsTUFDbEMsT0FBSyxFQUFFLFlBQVkscUJBQXFCO0FBQUEsTUFDeEMsT0FBSyxFQUFFLFlBQVksaUJBQWlCO0FBQUEsTUFDcEMsT0FBSyxFQUFFLFlBQVksbUJBQW1CO0FBQUEsTUFDdEMsT0FBSyxFQUFFLFlBQVksZUFBZTtBQUFBLE1BQ2xDLE9BQUssRUFBRSxZQUFZLHNCQUFzQjtBQUFBLE1BQ3pDLE9BQUssRUFBRSxZQUFZLHlCQUF5QjtBQUFBLE1BQzVDLE9BQUssRUFBRSxZQUFZLGlCQUFpQjtBQUFBLE1BQ3BDLE9BQUssRUFBRSxZQUFZLG1CQUFtQjtBQUFBLE1BQ3RDLE9BQUssRUFBRSxZQUFZLFdBQVc7QUFBQSxJQUNsQztBQUFBLEVBQ0osQ0FBQztBQUVELFVBQVEsYUFBYSxPQUFPLEVBQUUsR0FBRyxTQUFTLEVBQUUsU0FBUztBQUFBLElBQ2pELGNBQWM7QUFBQSxNQUNWLE9BQUssRUFBRSxZQUFZLGtCQUFrQjtBQUFBLE1BQ3JDLE9BQUssRUFBRSxZQUFZLFlBQVk7QUFBQSxNQUMvQixPQUFLLEVBQUUsWUFBWSxjQUFjO0FBQUEsTUFDakMsT0FBSyxFQUFFLFlBQVksYUFBYTtBQUFBLE1BQ2hDLE9BQUssRUFBRSxZQUFZLGFBQWE7QUFBQSxNQUNoQyxPQUFLLEVBQUUsWUFBWSxpQkFBaUI7QUFBQSxNQUNwQyxPQUFLLEVBQUUsWUFBWSxXQUFXO0FBQUEsSUFDbEM7QUFBQSxFQUNKLENBQUM7QUFDRCxTQUFPLFFBQVEsTUFBTTtBQUN6QjtBQXZWZ0I7OztBQ3pFaEIsSUFBTSxZQUFZLGdCQUFnQjtBQUNsQyxVQUFVLFlBQVksU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLFFBQVEsS0FBSzsiLAogICJuYW1lcyI6IFsidCIsICJlIiwgIm4iLCAiciIsICJpIiwgInMiLCAidSIsICJhIiwgIk0iLCAibSIsICJmIiwgImwiLCAiJCIsICJ5IiwgInYiLCAiZyIsICJEIiwgIm8iLCAiZCIsICJjIiwgImgiLCAidCIsICJpIiwgImUiLCAicyIsICJmIiwgIm4iLCAidSIsICJyIiwgIm8iLCAidCIsICJuIiwgImkiLCAibyIsICJyIiwgImUiLCAidSIsICJmIiwgInMiLCAiYSIsICJ0IiwgImkiLCAiZCIsICJuIiwgImUiLCAicyIsICJ0b2tlbiIsICJjb250YWluZXIiLCAiY29udGFpbmVyIiwgInRva2VuIiwgImNvbnRhaW5lciIsICJkYXlqcyIsICJ1dGMiLCAidGltZXpvbmUiLCAiaXNvV2VlayIsICJjb250YWluZXIiLCAiY29udGFpbmVyIiwgImNvbnRhaW5lciIsICJjb250YWluZXIiLCAiY29udGFpbmVyIiwgImNvbnRhaW5lciIsICJnZXRLZXkiLCAic2tpcFBhdGgiLCAia2V5IiwgImNvbnRhaW5lciIsICJjb250YWluZXIiLCAiY29udGFpbmVyIiwgImRpZmYiLCAiY29udGFpbmVyIiwgImNvbnRhaW5lciIsICJkaWZmIiwgImNvbnRhaW5lciJdCn0K