/* THIS IS A GENERATED/BUNDLED FILE BY ESBUILD if you want to view the source, please visit the github repository of this plugin */ 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 __markAsModule = (target) => __defProp(target, "__esModule", { value: true }); var __export = (target, all) => { __markAsModule(target); for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __reExport = (target, module2, desc) => { if (module2 && typeof module2 === "object" || typeof module2 === "function") { for (let key of __getOwnPropNames(module2)) if (!__hasOwnProp.call(target, key) && key !== "default") __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable }); } return target; }; var __toModule = (module2) => { return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2); }; var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; // src/main.ts __export(exports, { default: () => SimpleTimeTrackerPlugin }); var import_obsidian3 = __toModule(require("obsidian")); // src/settings.ts var defaultSettings = { timestampFormat: "YY-MM-DD hh:mm:ss", csvDelimiter: "," }; // src/settings-tab.ts var import_obsidian = __toModule(require("obsidian")); var SimpleTimeTrackerSettingsTab = class extends import_obsidian.PluginSettingTab { constructor(app, plugin) { super(app, plugin); this.plugin = plugin; } display() { this.containerEl.empty(); this.containerEl.createEl("h2", { text: "Super Simple Time Tracker Settings" }); new import_obsidian.Setting(this.containerEl).setName("Timestamp Display Format").setDesc(createFragment((f) => { f.createSpan({ text: "The way that timestamps in time tracker tables should be displayed. Uses " }); f.createEl("a", { text: "moment.js", href: "https://momentjs.com/docs/#/parsing/string-format/" }); f.createSpan({ text: " syntax." }); })).addText((t) => { t.setValue(String(this.plugin.settings.timestampFormat)); t.onChange((v) => __async(this, null, function* () { this.plugin.settings.timestampFormat = v.length ? v : defaultSettings.timestampFormat; yield this.plugin.saveSettings(); })); }); new import_obsidian.Setting(this.containerEl).setName("CSV Delimiter").setDesc("The delimiter character that should be used when copying a tracker table as CSV. For example, some languages use a semicolon instead of a comma.").addText((t) => { t.setValue(String(this.plugin.settings.csvDelimiter)); t.onChange((v) => __async(this, null, function* () { this.plugin.settings.csvDelimiter = v.length ? v : defaultSettings.csvDelimiter; yield this.plugin.saveSettings(); })); }); this.containerEl.createEl("hr"); this.containerEl.createEl("p", { text: "If you like this plugin and want to support its development, you can do so through my website by clicking this fancy image!" }); this.containerEl.createEl("a", { href: "https://ellpeck.de/support" }).createEl("img", { attr: { src: "https://ellpeck.de/res/generalsupport.png" }, cls: "simple-time-tracker-support" }); } }; // src/tracker.ts var import_obsidian2 = __toModule(require("obsidian")); function startEntry(tracker, name) { if (!name) name = `Segment ${tracker.entries.length + 1}`; let entry = { name, startTime: (0, import_obsidian2.moment)().unix(), endTime: null }; tracker.entries.push(entry); } function endEntry(tracker) { let last = tracker.entries.last(); last.endTime = (0, import_obsidian2.moment)().unix(); } function isRunning(tracker) { let last = tracker.entries.last(); return last != null && !last.endTime; } function saveTracker(tracker, app, section) { return __async(this, null, function* () { let file = app.workspace.getActiveFile(); if (!file) return; let content = yield app.vault.read(file); let lines = content.split("\n"); let prev = lines.filter((_, i) => i <= section.lineStart).join("\n"); let next = lines.filter((_, i) => i >= section.lineEnd).join("\n"); content = `${prev} ${JSON.stringify(tracker)} ${next}`; yield app.vault.modify(file, content); }); } function loadTracker(json) { if (json) { try { return JSON.parse(json); } catch (e) { console.log(`Failed to parse Tracker from ${json}`); } } return { entries: [] }; } function displayTracker(tracker, element, getSectionInfo, settings) { let running = isRunning(tracker); let btn = new import_obsidian2.ButtonComponent(element).setClass("clickable-icon").setIcon(`lucide-${running ? "stop" : "play"}-circle`).setTooltip(running ? "End" : "Start").onClick(() => __async(this, null, function* () { if (running) { endEntry(tracker); } else { startEntry(tracker, name.getValue()); } yield saveTracker(tracker, this.app, getSectionInfo()); })); btn.buttonEl.addClass("simple-time-tracker-btn"); let name = new import_obsidian2.TextComponent(element).setPlaceholder("Segment name").setDisabled(running); name.inputEl.addClass("simple-time-tracker-txt"); let timer = element.createDiv({ cls: "simple-time-tracker-timers" }); let currentDiv = timer.createEl("div", { cls: "simple-time-tracker-timer" }); let current = currentDiv.createEl("span", { cls: "simple-time-tracker-timer-time" }); currentDiv.createEl("span", { text: "Current" }); let totalDiv = timer.createEl("div", { cls: "simple-time-tracker-timer" }); let total = totalDiv.createEl("span", { cls: "simple-time-tracker-timer-time", text: "0s" }); totalDiv.createEl("span", { text: "Total" }); if (tracker.entries.length > 0) { let table = element.createEl("table", { cls: "simple-time-tracker-table" }); table.createEl("tr").append(createEl("th", { text: "Segment" }), createEl("th", { text: "Start time" }), createEl("th", { text: "End time" }), createEl("th", { text: "Duration" }), createEl("th")); for (let entry of tracker.entries) { let row = table.createEl("tr"); let name2 = row.createEl("td"); let namePar = name2.createEl("span", { text: entry.name }); let nameBox = new import_obsidian2.TextComponent(name2).setValue(entry.name); nameBox.inputEl.hidden = true; row.createEl("td", { text: formatTimestamp(entry.startTime, settings) }); row.createEl("td", { text: entry.endTime ? formatTimestamp(entry.endTime, settings) : "" }); row.createEl("td", { text: entry.endTime ? formatDurationBetween(entry.startTime, entry.endTime) : "" }); let entryButtons = row.createEl("td"); let editButton = new import_obsidian2.ButtonComponent(entryButtons).setClass("clickable-icon").setTooltip("Edit").setIcon("lucide-pencil").onClick(() => { if (namePar.hidden) { namePar.hidden = false; nameBox.inputEl.hidden = true; if (nameBox.getValue()) namePar.setText(nameBox.getValue()); editButton.setIcon("lucide-pencil"); } else { namePar.hidden = true; nameBox.inputEl.hidden = false; nameBox.setValue(namePar.getText()); editButton.setIcon("lucide-check"); } }); new import_obsidian2.ButtonComponent(entryButtons).setClass("clickable-icon").setTooltip("Remove").setIcon("lucide-trash").onClick(() => __async(this, null, function* () { tracker.entries.remove(entry); yield saveTracker(tracker, this.app, getSectionInfo()); })); } let buttons = element.createEl("div", { cls: "simple-time-tracker-bottom" }); new import_obsidian2.ButtonComponent(buttons).setButtonText("Copy as table").onClick(() => navigator.clipboard.writeText(createMarkdownTable(tracker, settings))); new import_obsidian2.ButtonComponent(buttons).setButtonText("Copy as CSV").onClick(() => navigator.clipboard.writeText(createCsv(tracker, settings))); } setCountdownValues(tracker, current, total, currentDiv); let intervalId = window.setInterval(() => { if (!element.isConnected) { window.clearInterval(intervalId); return; } setCountdownValues(tracker, current, total, currentDiv); }, 1e3); } function setCountdownValues(tracker, current, total, currentDiv) { let currEntry = tracker.entries.last(); if (currEntry) { if (!currEntry.endTime) current.setText(formatDurationBetween(currEntry.startTime, (0, import_obsidian2.moment)().unix())); total.setText(formatDuration(getTotalDuration(tracker))); } currentDiv.hidden = !currEntry || !!currEntry.endTime; } function getTotalDuration(tracker) { let totalDuration = 0; for (let entry of tracker.entries) { let endTime = entry.endTime ? import_obsidian2.moment.unix(entry.endTime) : (0, import_obsidian2.moment)(); totalDuration += endTime.diff(import_obsidian2.moment.unix(entry.startTime)); } return totalDuration; } function formatTimestamp(timestamp, settings) { return import_obsidian2.moment.unix(timestamp).format(settings.timestampFormat); } function formatDurationBetween(startTime, endTime) { return formatDuration(import_obsidian2.moment.unix(endTime).diff(import_obsidian2.moment.unix(startTime))); } function formatDuration(totalTime) { let duration = import_obsidian2.moment.duration(totalTime); let ret = ""; if (duration.hours() > 0) ret += duration.hours() + "h "; if (duration.minutes() > 0) ret += duration.minutes() + "m "; ret += duration.seconds() + "s"; return ret; } function createMarkdownTable(tracker, settings) { let table = [["Segment", "Start time", "End time", "Duration"]]; for (let entry of tracker.entries) table.push(createTableRow(entry, settings)); table.push(["**Total**", "", "", `**${formatDuration(getTotalDuration(tracker))}**`]); let ret = ""; let widths = Array.from(Array(4).keys()).map((i) => Math.max(...table.map((a) => a[i].length))); for (let r = 0; r < table.length; r++) { if (r == 1) ret += Array.from(Array(4).keys()).map((i) => "-".repeat(widths[i])).join(" | ") + "\n"; let row = []; for (let i = 0; i < 4; i++) row.push(table[r][i].padEnd(widths[i], " ")); ret += row.join(" | ") + "\n"; } return ret; } function createCsv(tracker, settings) { let ret = ""; for (let entry of tracker.entries) ret += createTableRow(entry, settings).join(settings.csvDelimiter) + "\n"; return ret; } function createTableRow(entry, settings) { return [ entry.name, formatTimestamp(entry.startTime, settings), entry.endTime ? formatTimestamp(entry.endTime, settings) : "", entry.endTime ? formatDurationBetween(entry.startTime, entry.endTime) : "" ]; } // src/main.ts var SimpleTimeTrackerPlugin = class extends import_obsidian3.Plugin { onload() { return __async(this, null, function* () { yield this.loadSettings(); this.addSettingTab(new SimpleTimeTrackerSettingsTab(this.app, this)); this.registerMarkdownCodeBlockProcessor("simple-time-tracker", (s, e, i) => { let tracker = loadTracker(s); e.empty(); displayTracker(tracker, e, () => i.getSectionInfo(e), this.settings); }); this.addCommand({ id: `insert`, name: `Insert Time Tracker`, editorCallback: (e, _) => { e.replaceSelection("```simple-time-tracker\n```\n"); } }); }); } loadSettings() { return __async(this, null, function* () { this.settings = Object.assign({}, defaultSettings, yield this.loadData()); }); } saveSettings() { return __async(this, null, function* () { yield this.saveData(this.settings); }); } }; //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL21haW4udHMiLCAic3JjL3NldHRpbmdzLnRzIiwgInNyYy9zZXR0aW5ncy10YWIudHMiLCAic3JjL3RyYWNrZXIudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IFBsdWdpbiB9IGZyb20gXCJvYnNpZGlhblwiO1xyXG5pbXBvcnQgeyBkZWZhdWx0U2V0dGluZ3MsIFNpbXBsZVRpbWVUcmFja2VyU2V0dGluZ3MgfSBmcm9tIFwiLi9zZXR0aW5nc1wiO1xyXG5pbXBvcnQgeyBTaW1wbGVUaW1lVHJhY2tlclNldHRpbmdzVGFiIH0gZnJvbSBcIi4vc2V0dGluZ3MtdGFiXCI7XHJcbmltcG9ydCB7IGRpc3BsYXlUcmFja2VyLCBsb2FkVHJhY2tlciB9IGZyb20gXCIuL3RyYWNrZXJcIjtcclxuXHJcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNpbXBsZVRpbWVUcmFja2VyUGx1Z2luIGV4dGVuZHMgUGx1Z2luIHtcclxuXHJcblx0c2V0dGluZ3M6IFNpbXBsZVRpbWVUcmFja2VyU2V0dGluZ3M7XHJcblxyXG5cdGFzeW5jIG9ubG9hZCgpOiBQcm9taXNlPHZvaWQ+IHtcclxuXHRcdGF3YWl0IHRoaXMubG9hZFNldHRpbmdzKCk7XHJcblxyXG5cdFx0dGhpcy5hZGRTZXR0aW5nVGFiKG5ldyBTaW1wbGVUaW1lVHJhY2tlclNldHRpbmdzVGFiKHRoaXMuYXBwLCB0aGlzKSk7XHJcblxyXG5cdFx0dGhpcy5yZWdpc3Rlck1hcmtkb3duQ29kZUJsb2NrUHJvY2Vzc29yKFwic2ltcGxlLXRpbWUtdHJhY2tlclwiLCAocywgZSwgaSkgPT4ge1xyXG5cdFx0XHRsZXQgdHJhY2tlciA9IGxvYWRUcmFja2VyKHMpO1xyXG5cdFx0XHRlLmVtcHR5KCk7XHJcblx0XHRcdGRpc3BsYXlUcmFja2VyKHRyYWNrZXIsIGUsICgpID0+IGkuZ2V0U2VjdGlvbkluZm8oZSksIHRoaXMuc2V0dGluZ3MpO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0dGhpcy5hZGRDb21tYW5kKHtcclxuXHRcdFx0aWQ6IGBpbnNlcnRgLFxyXG5cdFx0XHRuYW1lOiBgSW5zZXJ0IFRpbWUgVHJhY2tlcmAsXHJcblx0XHRcdGVkaXRvckNhbGxiYWNrOiAoZSwgXykgPT4ge1xyXG5cdFx0XHRcdGUucmVwbGFjZVNlbGVjdGlvbihcImBgYHNpbXBsZS10aW1lLXRyYWNrZXJcXG5gYGBcXG5cIik7XHJcblx0XHRcdH1cclxuXHRcdH0pO1xyXG5cdH1cclxuXHJcblx0YXN5bmMgbG9hZFNldHRpbmdzKCkge1xyXG5cdFx0dGhpcy5zZXR0aW5ncyA9IE9iamVjdC5hc3NpZ24oe30sIGRlZmF1bHRTZXR0aW5ncywgYXdhaXQgdGhpcy5sb2FkRGF0YSgpKTtcclxuXHR9XHJcblxyXG5cdGFzeW5jIHNhdmVTZXR0aW5ncygpIHtcclxuXHRcdGF3YWl0IHRoaXMuc2F2ZURhdGEodGhpcy5zZXR0aW5ncyk7XHJcblx0fVxyXG59XHJcbiIsICJleHBvcnQgY29uc3QgZGVmYXVsdFNldHRpbmdzOiBTaW1wbGVUaW1lVHJhY2tlclNldHRpbmdzID0ge1xyXG4gICAgdGltZXN0YW1wRm9ybWF0OiBcIllZLU1NLUREIGhoOm1tOnNzXCIsXHJcbiAgICBjc3ZEZWxpbWl0ZXI6IFwiLFwiXHJcbn07XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFNpbXBsZVRpbWVUcmFja2VyU2V0dGluZ3Mge1xyXG5cclxuICAgIHRpbWVzdGFtcEZvcm1hdDogc3RyaW5nO1xyXG4gICAgY3N2RGVsaW1pdGVyOiBzdHJpbmc7XHJcblxyXG59XHJcbiIsICJpbXBvcnQgeyBBcHAsIFBsdWdpblNldHRpbmdUYWIsIFNldHRpbmcgfSBmcm9tIFwib2JzaWRpYW5cIjtcclxuaW1wb3J0IFNpbXBsZVRpbWVUcmFja2VyUGx1Z2luIGZyb20gXCIuL21haW5cIjtcclxuaW1wb3J0IHsgZGVmYXVsdFNldHRpbmdzIH0gZnJvbSBcIi4vc2V0dGluZ3NcIjtcclxuXHJcbmV4cG9ydCBjbGFzcyBTaW1wbGVUaW1lVHJhY2tlclNldHRpbmdzVGFiIGV4dGVuZHMgUGx1Z2luU2V0dGluZ1RhYiB7XHJcblxyXG4gICAgcGx1Z2luOiBTaW1wbGVUaW1lVHJhY2tlclBsdWdpbjtcclxuXHJcbiAgICBjb25zdHJ1Y3RvcihhcHA6IEFwcCwgcGx1Z2luOiBTaW1wbGVUaW1lVHJhY2tlclBsdWdpbikge1xyXG4gICAgICAgIHN1cGVyKGFwcCwgcGx1Z2luKTtcclxuICAgICAgICB0aGlzLnBsdWdpbiA9IHBsdWdpbjtcclxuICAgIH1cclxuXHJcbiAgICBkaXNwbGF5KCk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuY29udGFpbmVyRWwuZW1wdHkoKTtcclxuICAgICAgICB0aGlzLmNvbnRhaW5lckVsLmNyZWF0ZUVsKFwiaDJcIiwgeyB0ZXh0OiBcIlN1cGVyIFNpbXBsZSBUaW1lIFRyYWNrZXIgU2V0dGluZ3NcIiB9KTtcclxuXHJcbiAgICAgICAgbmV3IFNldHRpbmcodGhpcy5jb250YWluZXJFbClcclxuICAgICAgICAgICAgLnNldE5hbWUoXCJUaW1lc3RhbXAgRGlzcGxheSBGb3JtYXRcIilcclxuICAgICAgICAgICAgLnNldERlc2MoY3JlYXRlRnJhZ21lbnQoZiA9PiB7XHJcbiAgICAgICAgICAgICAgICBmLmNyZWF0ZVNwYW4oeyB0ZXh0OiBcIlRoZSB3YXkgdGhhdCB0aW1lc3RhbXBzIGluIHRpbWUgdHJhY2tlciB0YWJsZXMgc2hvdWxkIGJlIGRpc3BsYXllZC4gVXNlcyBcIiB9KTtcclxuICAgICAgICAgICAgICAgIGYuY3JlYXRlRWwoXCJhXCIsIHsgdGV4dDogXCJtb21lbnQuanNcIiwgaHJlZjogXCJodHRwczovL21vbWVudGpzLmNvbS9kb2NzLyMvcGFyc2luZy9zdHJpbmctZm9ybWF0L1wiIH0pO1xyXG4gICAgICAgICAgICAgICAgZi5jcmVhdGVTcGFuKHsgdGV4dDogXCIgc3ludGF4LlwiIH0pO1xyXG4gICAgICAgICAgICB9KSlcclxuICAgICAgICAgICAgLmFkZFRleHQodCA9PiB7XHJcbiAgICAgICAgICAgICAgICB0LnNldFZhbHVlKFN0cmluZyh0aGlzLnBsdWdpbi5zZXR0aW5ncy50aW1lc3RhbXBGb3JtYXQpKTtcclxuICAgICAgICAgICAgICAgIHQub25DaGFuZ2UoYXN5bmMgdiA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MudGltZXN0YW1wRm9ybWF0ID0gdi5sZW5ndGggPyB2IDogZGVmYXVsdFNldHRpbmdzLnRpbWVzdGFtcEZvcm1hdDtcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgbmV3IFNldHRpbmcodGhpcy5jb250YWluZXJFbClcclxuICAgICAgICAgICAgLnNldE5hbWUoXCJDU1YgRGVsaW1pdGVyXCIpXHJcbiAgICAgICAgICAgIC5zZXREZXNjKFwiVGhlIGRlbGltaXRlciBjaGFyYWN0ZXIgdGhhdCBzaG91bGQgYmUgdXNlZCB3aGVuIGNvcHlpbmcgYSB0cmFja2VyIHRhYmxlIGFzIENTVi4gRm9yIGV4YW1wbGUsIHNvbWUgbGFuZ3VhZ2VzIHVzZSBhIHNlbWljb2xvbiBpbnN0ZWFkIG9mIGEgY29tbWEuXCIpXHJcbiAgICAgICAgICAgIC5hZGRUZXh0KHQgPT4ge1xyXG4gICAgICAgICAgICAgICAgdC5zZXRWYWx1ZShTdHJpbmcodGhpcy5wbHVnaW4uc2V0dGluZ3MuY3N2RGVsaW1pdGVyKSk7XHJcbiAgICAgICAgICAgICAgICB0Lm9uQ2hhbmdlKGFzeW5jIHYgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmNzdkRlbGltaXRlciA9IHYubGVuZ3RoID8gdiA6IGRlZmF1bHRTZXR0aW5ncy5jc3ZEZWxpbWl0ZXI7XHJcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHRoaXMuY29udGFpbmVyRWwuY3JlYXRlRWwoXCJoclwiKTtcclxuICAgICAgICB0aGlzLmNvbnRhaW5lckVsLmNyZWF0ZUVsKFwicFwiLCB7IHRleHQ6IFwiSWYgeW91IGxpa2UgdGhpcyBwbHVnaW4gYW5kIHdhbnQgdG8gc3VwcG9ydCBpdHMgZGV2ZWxvcG1lbnQsIHlvdSBjYW4gZG8gc28gdGhyb3VnaCBteSB3ZWJzaXRlIGJ5IGNsaWNraW5nIHRoaXMgZmFuY3kgaW1hZ2UhXCIgfSk7XHJcbiAgICAgICAgdGhpcy5jb250YWluZXJFbC5jcmVhdGVFbChcImFcIiwgeyBocmVmOiBcImh0dHBzOi8vZWxscGVjay5kZS9zdXBwb3J0XCIgfSlcclxuICAgICAgICAgICAgLmNyZWF0ZUVsKFwiaW1nXCIsIHsgYXR0cjogeyBzcmM6IFwiaHR0cHM6Ly9lbGxwZWNrLmRlL3Jlcy9nZW5lcmFsc3VwcG9ydC5wbmdcIiB9LCBjbHM6IFwic2ltcGxlLXRpbWUtdHJhY2tlci1zdXBwb3J0XCIgfSk7XHJcbiAgICB9XHJcbn1cclxuIiwgImltcG9ydCB7IG1vbWVudCwgQXBwLCBNYXJrZG93blNlY3Rpb25JbmZvcm1hdGlvbiwgQnV0dG9uQ29tcG9uZW50LCBUZXh0Q29tcG9uZW50IH0gZnJvbSBcIm9ic2lkaWFuXCI7XHJcbmltcG9ydCB7IFNpbXBsZVRpbWVUcmFja2VyU2V0dGluZ3MgfSBmcm9tIFwiLi9zZXR0aW5nc1wiO1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBUcmFja2VyIHtcclxuICAgIGVudHJpZXM6IEVudHJ5W107XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgRW50cnkge1xyXG4gICAgbmFtZTogc3RyaW5nO1xyXG4gICAgc3RhcnRUaW1lOiBudW1iZXI7XHJcbiAgICBlbmRUaW1lOiBudW1iZXI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBzdGFydEVudHJ5KHRyYWNrZXI6IFRyYWNrZXIsIG5hbWU6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgaWYgKCFuYW1lKVxyXG4gICAgICAgIG5hbWUgPSBgU2VnbWVudCAke3RyYWNrZXIuZW50cmllcy5sZW5ndGggKyAxfWA7XHJcbiAgICBsZXQgZW50cnk6IEVudHJ5ID0geyBuYW1lOiBuYW1lLCBzdGFydFRpbWU6IG1vbWVudCgpLnVuaXgoKSwgZW5kVGltZTogbnVsbCB9O1xyXG4gICAgdHJhY2tlci5lbnRyaWVzLnB1c2goZW50cnkpO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGVuZEVudHJ5KHRyYWNrZXI6IFRyYWNrZXIpOiB2b2lkIHtcclxuICAgIGxldCBsYXN0ID0gdHJhY2tlci5lbnRyaWVzLmxhc3QoKTtcclxuICAgIGxhc3QuZW5kVGltZSA9IG1vbWVudCgpLnVuaXgoKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGlzUnVubmluZyh0cmFja2VyOiBUcmFja2VyKTogYm9vbGVhbiB7XHJcbiAgICBsZXQgbGFzdCA9IHRyYWNrZXIuZW50cmllcy5sYXN0KCk7XHJcbiAgICByZXR1cm4gbGFzdCAhPSBudWxsICYmICFsYXN0LmVuZFRpbWU7XHJcbn1cclxuXHJcbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzYXZlVHJhY2tlcih0cmFja2VyOiBUcmFja2VyLCBhcHA6IEFwcCwgc2VjdGlvbjogTWFya2Rvd25TZWN0aW9uSW5mb3JtYXRpb24pOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIGxldCBmaWxlID0gYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVGaWxlKCk7XHJcbiAgICBpZiAoIWZpbGUpXHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgbGV0IGNvbnRlbnQgPSBhd2FpdCBhcHAudmF1bHQucmVhZChmaWxlKTtcclxuXHJcbiAgICAvLyBmaWd1cmUgb3V0IHdoYXQgcGFydCBvZiB0aGUgY29udGVudCB3ZSBoYXZlIHRvIGVkaXRcclxuICAgIGxldCBsaW5lcyA9IGNvbnRlbnQuc3BsaXQoXCJcXG5cIik7XHJcbiAgICBsZXQgcHJldiA9IGxpbmVzLmZpbHRlcigoXywgaSkgPT4gaSA8PSBzZWN0aW9uLmxpbmVTdGFydCkuam9pbihcIlxcblwiKTtcclxuICAgIGxldCBuZXh0ID0gbGluZXMuZmlsdGVyKChfLCBpKSA9PiBpID49IHNlY3Rpb24ubGluZUVuZCkuam9pbihcIlxcblwiKTtcclxuICAgIC8vIGVkaXQgb25seSB0aGUgY29kZSBibG9jayBjb250ZW50LCBsZWF2ZSB0aGUgcmVzdCB1bnRvdWNoZWRcclxuICAgIGNvbnRlbnQgPSBgJHtwcmV2fVxcbiR7SlNPTi5zdHJpbmdpZnkodHJhY2tlcil9XFxuJHtuZXh0fWA7XHJcblxyXG4gICAgYXdhaXQgYXBwLnZhdWx0Lm1vZGlmeShmaWxlLCBjb250ZW50KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGxvYWRUcmFja2VyKGpzb246IHN0cmluZyk6IFRyYWNrZXIge1xyXG4gICAgaWYgKGpzb24pIHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShqc29uKTtcclxuICAgICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBGYWlsZWQgdG8gcGFyc2UgVHJhY2tlciBmcm9tICR7anNvbn1gKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4geyBlbnRyaWVzOiBbXSB9O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gZGlzcGxheVRyYWNrZXIodHJhY2tlcjogVHJhY2tlciwgZWxlbWVudDogSFRNTEVsZW1lbnQsIGdldFNlY3Rpb25JbmZvOiAoKSA9PiBNYXJrZG93blNlY3Rpb25JbmZvcm1hdGlvbiwgc2V0dGluZ3M6IFNpbXBsZVRpbWVUcmFja2VyU2V0dGluZ3MpOiB2b2lkIHtcclxuICAgIC8vIGFkZCBzdGFydC9zdG9wIGNvbnRyb2xzXHJcbiAgICBsZXQgcnVubmluZyA9IGlzUnVubmluZyh0cmFja2VyKTtcclxuICAgIGxldCBidG4gPSBuZXcgQnV0dG9uQ29tcG9uZW50KGVsZW1lbnQpXHJcbiAgICAgICAgLnNldENsYXNzKFwiY2xpY2thYmxlLWljb25cIilcclxuICAgICAgICAuc2V0SWNvbihgbHVjaWRlLSR7cnVubmluZyA/IFwic3RvcFwiIDogXCJwbGF5XCJ9LWNpcmNsZWApXHJcbiAgICAgICAgLnNldFRvb2x0aXAocnVubmluZyA/IFwiRW5kXCIgOiBcIlN0YXJ0XCIpXHJcbiAgICAgICAgLm9uQ2xpY2soYXN5bmMgKCkgPT4ge1xyXG4gICAgICAgICAgICBpZiAocnVubmluZykge1xyXG4gICAgICAgICAgICAgICAgZW5kRW50cnkodHJhY2tlcik7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBzdGFydEVudHJ5KHRyYWNrZXIsIG5hbWUuZ2V0VmFsdWUoKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgYXdhaXQgc2F2ZVRyYWNrZXIodHJhY2tlciwgdGhpcy5hcHAsIGdldFNlY3Rpb25JbmZvKCkpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgYnRuLmJ1dHRvbkVsLmFkZENsYXNzKFwic2ltcGxlLXRpbWUtdHJhY2tlci1idG5cIik7XHJcbiAgICBsZXQgbmFtZSA9IG5ldyBUZXh0Q29tcG9uZW50KGVsZW1lbnQpXHJcbiAgICAgICAgLnNldFBsYWNlaG9sZGVyKFwiU2VnbWVudCBuYW1lXCIpXHJcbiAgICAgICAgLnNldERpc2FibGVkKHJ1bm5pbmcpO1xyXG4gICAgbmFtZS5pbnB1dEVsLmFkZENsYXNzKFwic2ltcGxlLXRpbWUtdHJhY2tlci10eHRcIik7XHJcblxyXG4gICAgLy8gYWRkIHRpbWVyc1xyXG4gICAgbGV0IHRpbWVyID0gZWxlbWVudC5jcmVhdGVEaXYoeyBjbHM6IFwic2ltcGxlLXRpbWUtdHJhY2tlci10aW1lcnNcIiB9KTtcclxuICAgIGxldCBjdXJyZW50RGl2ID0gdGltZXIuY3JlYXRlRWwoXCJkaXZcIiwgeyBjbHM6IFwic2ltcGxlLXRpbWUtdHJhY2tlci10aW1lclwiIH0pO1xyXG4gICAgbGV0IGN1cnJlbnQgPSBjdXJyZW50RGl2LmNyZWF0ZUVsKFwic3BhblwiLCB7IGNsczogXCJzaW1wbGUtdGltZS10cmFja2VyLXRpbWVyLXRpbWVcIiB9KTtcclxuICAgIGN1cnJlbnREaXYuY3JlYXRlRWwoXCJzcGFuXCIsIHsgdGV4dDogXCJDdXJyZW50XCIgfSk7XHJcbiAgICBsZXQgdG90YWxEaXYgPSB0aW1lci5jcmVhdGVFbChcImRpdlwiLCB7IGNsczogXCJzaW1wbGUtdGltZS10cmFja2VyLXRpbWVyXCIgfSk7XHJcbiAgICBsZXQgdG90YWwgPSB0b3RhbERpdi5jcmVhdGVFbChcInNwYW5cIiwgeyBjbHM6IFwic2ltcGxlLXRpbWUtdHJhY2tlci10aW1lci10aW1lXCIsIHRleHQ6IFwiMHNcIiB9KTtcclxuICAgIHRvdGFsRGl2LmNyZWF0ZUVsKFwic3BhblwiLCB7IHRleHQ6IFwiVG90YWxcIiB9KTtcclxuXHJcbiAgICBpZiAodHJhY2tlci5lbnRyaWVzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAvLyBhZGQgdGFibGVcclxuICAgICAgICBsZXQgdGFibGUgPSBlbGVtZW50LmNyZWF0ZUVsKFwidGFibGVcIiwgeyBjbHM6IFwic2ltcGxlLXRpbWUtdHJhY2tlci10YWJsZVwiIH0pO1xyXG4gICAgICAgIHRhYmxlLmNyZWF0ZUVsKFwidHJcIikuYXBwZW5kKFxyXG4gICAgICAgICAgICBjcmVhdGVFbChcInRoXCIsIHsgdGV4dDogXCJTZWdtZW50XCIgfSksXHJcbiAgICAgICAgICAgIGNyZWF0ZUVsKFwidGhcIiwgeyB0ZXh0OiBcIlN0YXJ0IHRpbWVcIiB9KSxcclxuICAgICAgICAgICAgY3JlYXRlRWwoXCJ0aFwiLCB7IHRleHQ6IFwiRW5kIHRpbWVcIiB9KSxcclxuICAgICAgICAgICAgY3JlYXRlRWwoXCJ0aFwiLCB7IHRleHQ6IFwiRHVyYXRpb25cIiB9KSxcclxuICAgICAgICAgICAgY3JlYXRlRWwoXCJ0aFwiKSk7XHJcblxyXG4gICAgICAgIGZvciAobGV0IGVudHJ5IG9mIHRyYWNrZXIuZW50cmllcykge1xyXG4gICAgICAgICAgICBsZXQgcm93ID0gdGFibGUuY3JlYXRlRWwoXCJ0clwiKTtcclxuXHJcbiAgICAgICAgICAgIGxldCBuYW1lID0gcm93LmNyZWF0ZUVsKFwidGRcIik7XHJcbiAgICAgICAgICAgIGxldCBuYW1lUGFyID0gbmFtZS5jcmVhdGVFbChcInNwYW5cIiwgeyB0ZXh0OiBlbnRyeS5uYW1lIH0pO1xyXG4gICAgICAgICAgICBsZXQgbmFtZUJveCA9IG5ldyBUZXh0Q29tcG9uZW50KG5hbWUpLnNldFZhbHVlKGVudHJ5Lm5hbWUpO1xyXG4gICAgICAgICAgICBuYW1lQm94LmlucHV0RWwuaGlkZGVuID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgIHJvdy5jcmVhdGVFbChcInRkXCIsIHsgdGV4dDogZm9ybWF0VGltZXN0YW1wKGVudHJ5LnN0YXJ0VGltZSwgc2V0dGluZ3MpIH0pO1xyXG4gICAgICAgICAgICByb3cuY3JlYXRlRWwoXCJ0ZFwiLCB7IHRleHQ6IGVudHJ5LmVuZFRpbWUgPyBmb3JtYXRUaW1lc3RhbXAoZW50cnkuZW5kVGltZSwgc2V0dGluZ3MpIDogXCJcIiB9KTtcclxuICAgICAgICAgICAgcm93LmNyZWF0ZUVsKFwidGRcIiwgeyB0ZXh0OiBlbnRyeS5lbmRUaW1lID8gZm9ybWF0RHVyYXRpb25CZXR3ZWVuKGVudHJ5LnN0YXJ0VGltZSwgZW50cnkuZW5kVGltZSkgOiBcIlwiIH0pO1xyXG5cclxuICAgICAgICAgICAgbGV0IGVudHJ5QnV0dG9ucyA9IHJvdy5jcmVhdGVFbChcInRkXCIpO1xyXG4gICAgICAgICAgICBsZXQgZWRpdEJ1dHRvbiA9IG5ldyBCdXR0b25Db21wb25lbnQoZW50cnlCdXR0b25zKVxyXG4gICAgICAgICAgICAgICAgLnNldENsYXNzKFwiY2xpY2thYmxlLWljb25cIilcclxuICAgICAgICAgICAgICAgIC5zZXRUb29sdGlwKFwiRWRpdFwiKVxyXG4gICAgICAgICAgICAgICAgLnNldEljb24oXCJsdWNpZGUtcGVuY2lsXCIpXHJcbiAgICAgICAgICAgICAgICAub25DbGljaygoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5hbWVQYXIuaGlkZGVuKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVQYXIuaGlkZGVuID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVCb3guaW5wdXRFbC5oaWRkZW4gPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobmFtZUJveC5nZXRWYWx1ZSgpKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZVBhci5zZXRUZXh0KG5hbWVCb3guZ2V0VmFsdWUoKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRCdXR0b24uc2V0SWNvbihcImx1Y2lkZS1wZW5jaWxcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbmFtZVBhci5oaWRkZW4gPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBuYW1lQm94LmlucHV0RWwuaGlkZGVuID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVCb3guc2V0VmFsdWUobmFtZVBhci5nZXRUZXh0KCkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBlZGl0QnV0dG9uLnNldEljb24oXCJsdWNpZGUtY2hlY2tcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIG5ldyBCdXR0b25Db21wb25lbnQoZW50cnlCdXR0b25zKVxyXG4gICAgICAgICAgICAgICAgLnNldENsYXNzKFwiY2xpY2thYmxlLWljb25cIilcclxuICAgICAgICAgICAgICAgIC5zZXRUb29sdGlwKFwiUmVtb3ZlXCIpXHJcbiAgICAgICAgICAgICAgICAuc2V0SWNvbihcImx1Y2lkZS10cmFzaFwiKVxyXG4gICAgICAgICAgICAgICAgLm9uQ2xpY2soYXN5bmMgKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRyYWNrZXIuZW50cmllcy5yZW1vdmUoZW50cnkpO1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHNhdmVUcmFja2VyKHRyYWNrZXIsIHRoaXMuYXBwLCBnZXRTZWN0aW9uSW5mbygpKTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gYWRkIGNvcHkgYnV0dG9uc1xyXG4gICAgICAgIGxldCBidXR0b25zID0gZWxlbWVudC5jcmVhdGVFbChcImRpdlwiLCB7IGNsczogXCJzaW1wbGUtdGltZS10cmFja2VyLWJvdHRvbVwiIH0pO1xyXG4gICAgICAgIG5ldyBCdXR0b25Db21wb25lbnQoYnV0dG9ucylcclxuICAgICAgICAgICAgLnNldEJ1dHRvblRleHQoXCJDb3B5IGFzIHRhYmxlXCIpXHJcbiAgICAgICAgICAgIC5vbkNsaWNrKCgpID0+IG5hdmlnYXRvci5jbGlwYm9hcmQud3JpdGVUZXh0KGNyZWF0ZU1hcmtkb3duVGFibGUodHJhY2tlciwgc2V0dGluZ3MpKSk7XHJcbiAgICAgICAgbmV3IEJ1dHRvbkNvbXBvbmVudChidXR0b25zKVxyXG4gICAgICAgICAgICAuc2V0QnV0dG9uVGV4dChcIkNvcHkgYXMgQ1NWXCIpXHJcbiAgICAgICAgICAgIC5vbkNsaWNrKCgpID0+IG5hdmlnYXRvci5jbGlwYm9hcmQud3JpdGVUZXh0KGNyZWF0ZUNzdih0cmFja2VyLCBzZXR0aW5ncykpKTtcclxuICAgIH1cclxuXHJcblxyXG4gICAgc2V0Q291bnRkb3duVmFsdWVzKHRyYWNrZXIsIGN1cnJlbnQsIHRvdGFsLCBjdXJyZW50RGl2KTtcclxuICAgIGxldCBpbnRlcnZhbElkID0gd2luZG93LnNldEludGVydmFsKCgpID0+IHtcclxuICAgICAgICAvLyB3ZSBkZWxldGUgdGhlIGludGVydmFsIHRpbWVyIHdoZW4gdGhlIGVsZW1lbnQgaXMgcmVtb3ZlZFxyXG4gICAgICAgIGlmICghZWxlbWVudC5pc0Nvbm5lY3RlZCkge1xyXG4gICAgICAgICAgICB3aW5kb3cuY2xlYXJJbnRlcnZhbChpbnRlcnZhbElkKTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICBzZXRDb3VudGRvd25WYWx1ZXModHJhY2tlciwgY3VycmVudCwgdG90YWwsIGN1cnJlbnREaXYpO1xyXG4gICAgfSwgMTAwMCk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHNldENvdW50ZG93blZhbHVlcyh0cmFja2VyOiBUcmFja2VyLCBjdXJyZW50OiBIVE1MRWxlbWVudCwgdG90YWw6IEhUTUxFbGVtZW50LCBjdXJyZW50RGl2OiBIVE1MRGl2RWxlbWVudCkge1xyXG4gICAgbGV0IGN1cnJFbnRyeSA9IHRyYWNrZXIuZW50cmllcy5sYXN0KCk7XHJcbiAgICBpZiAoY3VyckVudHJ5KSB7XHJcbiAgICAgICAgaWYgKCFjdXJyRW50cnkuZW5kVGltZSlcclxuICAgICAgICAgICAgY3VycmVudC5zZXRUZXh0KGZvcm1hdER1cmF0aW9uQmV0d2VlbihjdXJyRW50cnkuc3RhcnRUaW1lLCBtb21lbnQoKS51bml4KCkpKTtcclxuICAgICAgICB0b3RhbC5zZXRUZXh0KGZvcm1hdER1cmF0aW9uKGdldFRvdGFsRHVyYXRpb24odHJhY2tlcikpKTtcclxuICAgIH1cclxuICAgIGN1cnJlbnREaXYuaGlkZGVuID0gIWN1cnJFbnRyeSB8fCAhIWN1cnJFbnRyeS5lbmRUaW1lO1xyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRUb3RhbER1cmF0aW9uKHRyYWNrZXI6IFRyYWNrZXIpOiBudW1iZXIge1xyXG4gICAgbGV0IHRvdGFsRHVyYXRpb24gPSAwO1xyXG4gICAgZm9yIChsZXQgZW50cnkgb2YgdHJhY2tlci5lbnRyaWVzKSB7XHJcbiAgICAgICAgbGV0IGVuZFRpbWUgPSBlbnRyeS5lbmRUaW1lID8gbW9tZW50LnVuaXgoZW50cnkuZW5kVGltZSkgOiBtb21lbnQoKTtcclxuICAgICAgICB0b3RhbER1cmF0aW9uICs9IGVuZFRpbWUuZGlmZihtb21lbnQudW5peChlbnRyeS5zdGFydFRpbWUpKTtcclxuICAgIH1cclxuICAgIHJldHVybiB0b3RhbER1cmF0aW9uO1xyXG59XHJcblxyXG5mdW5jdGlvbiBmb3JtYXRUaW1lc3RhbXAodGltZXN0YW1wOiBudW1iZXIsIHNldHRpbmdzOiBTaW1wbGVUaW1lVHJhY2tlclNldHRpbmdzKTogc3RyaW5nIHtcclxuICAgIHJldHVybiBtb21lbnQudW5peCh0aW1lc3RhbXApLmZvcm1hdChzZXR0aW5ncy50aW1lc3RhbXBGb3JtYXQpO1xyXG59XHJcblxyXG5mdW5jdGlvbiBmb3JtYXREdXJhdGlvbkJldHdlZW4oc3RhcnRUaW1lOiBudW1iZXIsIGVuZFRpbWU6IG51bWJlcik6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gZm9ybWF0RHVyYXRpb24obW9tZW50LnVuaXgoZW5kVGltZSkuZGlmZihtb21lbnQudW5peChzdGFydFRpbWUpKSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGZvcm1hdER1cmF0aW9uKHRvdGFsVGltZTogbnVtYmVyKTogc3RyaW5nIHtcclxuICAgIGxldCBkdXJhdGlvbiA9IG1vbWVudC5kdXJhdGlvbih0b3RhbFRpbWUpO1xyXG4gICAgbGV0IHJldCA9IFwiXCI7XHJcbiAgICBpZiAoZHVyYXRpb24uaG91cnMoKSA+IDApXHJcbiAgICAgICAgcmV0ICs9IGR1cmF0aW9uLmhvdXJzKCkgKyBcImggXCI7XHJcbiAgICBpZiAoZHVyYXRpb24ubWludXRlcygpID4gMClcclxuICAgICAgICByZXQgKz0gZHVyYXRpb24ubWludXRlcygpICsgXCJtIFwiO1xyXG4gICAgcmV0ICs9IGR1cmF0aW9uLnNlY29uZHMoKSArIFwic1wiO1xyXG4gICAgcmV0dXJuIHJldDtcclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlTWFya2Rvd25UYWJsZSh0cmFja2VyOiBUcmFja2VyLCBzZXR0aW5nczogU2ltcGxlVGltZVRyYWNrZXJTZXR0aW5ncyk6IHN0cmluZyB7XHJcbiAgICBsZXQgdGFibGUgPSBbW1wiU2VnbWVudFwiLCBcIlN0YXJ0IHRpbWVcIiwgXCJFbmQgdGltZVwiLCBcIkR1cmF0aW9uXCJdXTtcclxuICAgIGZvciAobGV0IGVudHJ5IG9mIHRyYWNrZXIuZW50cmllcylcclxuICAgICAgICB0YWJsZS5wdXNoKGNyZWF0ZVRhYmxlUm93KGVudHJ5LCBzZXR0aW5ncykpO1xyXG4gICAgdGFibGUucHVzaChbXCIqKlRvdGFsKipcIiwgXCJcIiwgXCJcIiwgYCoqJHtmb3JtYXREdXJhdGlvbihnZXRUb3RhbER1cmF0aW9uKHRyYWNrZXIpKX0qKmBdKTtcclxuXHJcbiAgICBsZXQgcmV0ID0gXCJcIjtcclxuICAgIC8vIGNhbGN1bGF0ZSB0aGUgd2lkdGggZXZlcnkgY29sdW1uIG5lZWRzIHRvIGxvb2sgbmVhdCB3aGVuIG1vbm9zcGFjZWRcclxuICAgIGxldCB3aWR0aHMgPSBBcnJheS5mcm9tKEFycmF5KDQpLmtleXMoKSkubWFwKGkgPT4gTWF0aC5tYXgoLi4udGFibGUubWFwKGEgPT4gYVtpXS5sZW5ndGgpKSk7XHJcbiAgICBmb3IgKGxldCByID0gMDsgciA8IHRhYmxlLmxlbmd0aDsgcisrKSB7XHJcbiAgICAgICAgLy8gYWRkIHNlcGFyYXRvcnMgYWZ0ZXIgZmlyc3Qgcm93XHJcbiAgICAgICAgaWYgKHIgPT0gMSlcclxuICAgICAgICAgICAgcmV0ICs9IEFycmF5LmZyb20oQXJyYXkoNCkua2V5cygpKS5tYXAoaSA9PiBcIi1cIi5yZXBlYXQod2lkdGhzW2ldKSkuam9pbihcIiB8IFwiKSArIFwiXFxuXCI7XHJcblxyXG4gICAgICAgIGxldCByb3c6IHN0cmluZ1tdID0gW107XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCA0OyBpKyspXHJcbiAgICAgICAgICAgIHJvdy5wdXNoKHRhYmxlW3JdW2ldLnBhZEVuZCh3aWR0aHNbaV0sIFwiIFwiKSk7XHJcbiAgICAgICAgcmV0ICs9IHJvdy5qb2luKFwiIHwgXCIpICsgXCJcXG5cIjtcclxuICAgIH1cclxuICAgIHJldHVybiByZXQ7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZUNzdih0cmFja2VyOiBUcmFja2VyLCBzZXR0aW5nczogU2ltcGxlVGltZVRyYWNrZXJTZXR0aW5ncyk6IHN0cmluZyB7XHJcbiAgICBsZXQgcmV0ID0gXCJcIjtcclxuICAgIGZvciAobGV0IGVudHJ5IG9mIHRyYWNrZXIuZW50cmllcylcclxuICAgICAgICByZXQgKz0gY3JlYXRlVGFibGVSb3coZW50cnksIHNldHRpbmdzKS5qb2luKHNldHRpbmdzLmNzdkRlbGltaXRlcikgKyBcIlxcblwiO1xyXG4gICAgcmV0dXJuIHJldDtcclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlVGFibGVSb3coZW50cnk6IEVudHJ5LCBzZXR0aW5nczogU2ltcGxlVGltZVRyYWNrZXJTZXR0aW5ncyk6IHN0cmluZ1tdIHtcclxuICAgIHJldHVybiBbXHJcbiAgICAgICAgZW50cnkubmFtZSxcclxuICAgICAgICBmb3JtYXRUaW1lc3RhbXAoZW50cnkuc3RhcnRUaW1lLCBzZXR0aW5ncyksXHJcbiAgICAgICAgZW50cnkuZW5kVGltZSA/IGZvcm1hdFRpbWVzdGFtcChlbnRyeS5lbmRUaW1lLCBzZXR0aW5ncykgOiBcIlwiLFxyXG4gICAgICAgIGVudHJ5LmVuZFRpbWUgPyBmb3JtYXREdXJhdGlvbkJldHdlZW4oZW50cnkuc3RhcnRUaW1lLCBlbnRyeS5lbmRUaW1lKSA6IFwiXCJdO1xyXG59XHJcbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQSx1QkFBdUI7OztBQ0FoQixJQUFNLGtCQUE2QztBQUFBLEVBQ3RELGlCQUFpQjtBQUFBLEVBQ2pCLGNBQWM7QUFBQTs7O0FDRmxCLHNCQUErQztBQUl4QyxpREFBMkMsaUNBQWlCO0FBQUEsRUFJL0QsWUFBWSxLQUFVLFFBQWlDO0FBQ25ELFVBQU0sS0FBSztBQUNYLFNBQUssU0FBUztBQUFBO0FBQUEsRUFHbEIsVUFBZ0I7QUFDWixTQUFLLFlBQVk7QUFDakIsU0FBSyxZQUFZLFNBQVMsTUFBTSxFQUFFLE1BQU07QUFFeEMsUUFBSSx3QkFBUSxLQUFLLGFBQ1osUUFBUSw0QkFDUixRQUFRLGVBQWUsT0FBSztBQUN6QixRQUFFLFdBQVcsRUFBRSxNQUFNO0FBQ3JCLFFBQUUsU0FBUyxLQUFLLEVBQUUsTUFBTSxhQUFhLE1BQU07QUFDM0MsUUFBRSxXQUFXLEVBQUUsTUFBTTtBQUFBLFFBRXhCLFFBQVEsT0FBSztBQUNWLFFBQUUsU0FBUyxPQUFPLEtBQUssT0FBTyxTQUFTO0FBQ3ZDLFFBQUUsU0FBUyxDQUFNLE1BQUs7QUFDbEIsYUFBSyxPQUFPLFNBQVMsa0JBQWtCLEVBQUUsU0FBUyxJQUFJLGdCQUFnQjtBQUN0RSxjQUFNLEtBQUssT0FBTztBQUFBO0FBQUE7QUFJOUIsUUFBSSx3QkFBUSxLQUFLLGFBQ1osUUFBUSxpQkFDUixRQUFRLG9KQUNSLFFBQVEsT0FBSztBQUNWLFFBQUUsU0FBUyxPQUFPLEtBQUssT0FBTyxTQUFTO0FBQ3ZDLFFBQUUsU0FBUyxDQUFNLE1BQUs7QUFDbEIsYUFBSyxPQUFPLFNBQVMsZUFBZSxFQUFFLFNBQVMsSUFBSSxnQkFBZ0I7QUFDbkUsY0FBTSxLQUFLLE9BQU87QUFBQTtBQUFBO0FBSTlCLFNBQUssWUFBWSxTQUFTO0FBQzFCLFNBQUssWUFBWSxTQUFTLEtBQUssRUFBRSxNQUFNO0FBQ3ZDLFNBQUssWUFBWSxTQUFTLEtBQUssRUFBRSxNQUFNLGdDQUNsQyxTQUFTLE9BQU8sRUFBRSxNQUFNLEVBQUUsS0FBSywrQ0FBK0MsS0FBSztBQUFBO0FBQUE7OztBQzlDaEcsdUJBQXdGO0FBYWpGLG9CQUFvQixTQUFrQixNQUFvQjtBQUM3RCxNQUFJLENBQUM7QUFDRCxXQUFPLFdBQVcsUUFBUSxRQUFRLFNBQVM7QUFDL0MsTUFBSSxRQUFlLEVBQUUsTUFBWSxXQUFXLCtCQUFTLFFBQVEsU0FBUztBQUN0RSxVQUFRLFFBQVEsS0FBSztBQUFBO0FBR2xCLGtCQUFrQixTQUF3QjtBQUM3QyxNQUFJLE9BQU8sUUFBUSxRQUFRO0FBQzNCLE9BQUssVUFBVSwrQkFBUztBQUFBO0FBR3JCLG1CQUFtQixTQUEyQjtBQUNqRCxNQUFJLE9BQU8sUUFBUSxRQUFRO0FBQzNCLFNBQU8sUUFBUSxRQUFRLENBQUMsS0FBSztBQUFBO0FBR2pDLHFCQUFrQyxTQUFrQixLQUFVLFNBQW9EO0FBQUE7QUFDOUcsUUFBSSxPQUFPLElBQUksVUFBVTtBQUN6QixRQUFJLENBQUM7QUFDRDtBQUNKLFFBQUksVUFBVSxNQUFNLElBQUksTUFBTSxLQUFLO0FBR25DLFFBQUksUUFBUSxRQUFRLE1BQU07QUFDMUIsUUFBSSxPQUFPLE1BQU0sT0FBTyxDQUFDLEdBQUcsTUFBTSxLQUFLLFFBQVEsV0FBVyxLQUFLO0FBQy9ELFFBQUksT0FBTyxNQUFNLE9BQU8sQ0FBQyxHQUFHLE1BQU0sS0FBSyxRQUFRLFNBQVMsS0FBSztBQUU3RCxjQUFVLEdBQUc7QUFBQSxFQUFTLEtBQUssVUFBVTtBQUFBLEVBQWE7QUFFbEQsVUFBTSxJQUFJLE1BQU0sT0FBTyxNQUFNO0FBQUE7QUFBQTtBQUcxQixxQkFBcUIsTUFBdUI7QUFDL0MsTUFBSSxNQUFNO0FBQ04sUUFBSTtBQUNBLGFBQU8sS0FBSyxNQUFNO0FBQUEsYUFDYixHQUFQO0FBQ0UsY0FBUSxJQUFJLGdDQUFnQztBQUFBO0FBQUE7QUFHcEQsU0FBTyxFQUFFLFNBQVM7QUFBQTtBQUdmLHdCQUF3QixTQUFrQixTQUFzQixnQkFBa0QsVUFBMkM7QUFFaEssTUFBSSxVQUFVLFVBQVU7QUFDeEIsTUFBSSxNQUFNLElBQUksaUNBQWdCLFNBQ3pCLFNBQVMsa0JBQ1QsUUFBUSxVQUFVLFVBQVUsU0FBUyxpQkFDckMsV0FBVyxVQUFVLFFBQVEsU0FDN0IsUUFBUSxNQUFZO0FBQ2pCLFFBQUksU0FBUztBQUNULGVBQVM7QUFBQSxXQUNOO0FBQ0gsaUJBQVcsU0FBUyxLQUFLO0FBQUE7QUFFN0IsVUFBTSxZQUFZLFNBQVMsS0FBSyxLQUFLO0FBQUE7QUFFN0MsTUFBSSxTQUFTLFNBQVM7QUFDdEIsTUFBSSxPQUFPLElBQUksK0JBQWMsU0FDeEIsZUFBZSxnQkFDZixZQUFZO0FBQ2pCLE9BQUssUUFBUSxTQUFTO0FBR3RCLE1BQUksUUFBUSxRQUFRLFVBQVUsRUFBRSxLQUFLO0FBQ3JDLE1BQUksYUFBYSxNQUFNLFNBQVMsT0FBTyxFQUFFLEtBQUs7QUFDOUMsTUFBSSxVQUFVLFdBQVcsU0FBUyxRQUFRLEVBQUUsS0FBSztBQUNqRCxhQUFXLFNBQVMsUUFBUSxFQUFFLE1BQU07QUFDcEMsTUFBSSxXQUFXLE1BQU0sU0FBUyxPQUFPLEVBQUUsS0FBSztBQUM1QyxNQUFJLFFBQVEsU0FBUyxTQUFTLFFBQVEsRUFBRSxLQUFLLGtDQUFrQyxNQUFNO0FBQ3JGLFdBQVMsU0FBUyxRQUFRLEVBQUUsTUFBTTtBQUVsQyxNQUFJLFFBQVEsUUFBUSxTQUFTLEdBQUc7QUFFNUIsUUFBSSxRQUFRLFFBQVEsU0FBUyxTQUFTLEVBQUUsS0FBSztBQUM3QyxVQUFNLFNBQVMsTUFBTSxPQUNqQixTQUFTLE1BQU0sRUFBRSxNQUFNLGNBQ3ZCLFNBQVMsTUFBTSxFQUFFLE1BQU0saUJBQ3ZCLFNBQVMsTUFBTSxFQUFFLE1BQU0sZUFDdkIsU0FBUyxNQUFNLEVBQUUsTUFBTSxlQUN2QixTQUFTO0FBRWIsYUFBUyxTQUFTLFFBQVEsU0FBUztBQUMvQixVQUFJLE1BQU0sTUFBTSxTQUFTO0FBRXpCLFVBQUksUUFBTyxJQUFJLFNBQVM7QUFDeEIsVUFBSSxVQUFVLE1BQUssU0FBUyxRQUFRLEVBQUUsTUFBTSxNQUFNO0FBQ2xELFVBQUksVUFBVSxJQUFJLCtCQUFjLE9BQU0sU0FBUyxNQUFNO0FBQ3JELGNBQVEsUUFBUSxTQUFTO0FBRXpCLFVBQUksU0FBUyxNQUFNLEVBQUUsTUFBTSxnQkFBZ0IsTUFBTSxXQUFXO0FBQzVELFVBQUksU0FBUyxNQUFNLEVBQUUsTUFBTSxNQUFNLFVBQVUsZ0JBQWdCLE1BQU0sU0FBUyxZQUFZO0FBQ3RGLFVBQUksU0FBUyxNQUFNLEVBQUUsTUFBTSxNQUFNLFVBQVUsc0JBQXNCLE1BQU0sV0FBVyxNQUFNLFdBQVc7QUFFbkcsVUFBSSxlQUFlLElBQUksU0FBUztBQUNoQyxVQUFJLGFBQWEsSUFBSSxpQ0FBZ0IsY0FDaEMsU0FBUyxrQkFDVCxXQUFXLFFBQ1gsUUFBUSxpQkFDUixRQUFRLE1BQU07QUFDWCxZQUFJLFFBQVEsUUFBUTtBQUNoQixrQkFBUSxTQUFTO0FBQ2pCLGtCQUFRLFFBQVEsU0FBUztBQUN6QixjQUFJLFFBQVE7QUFDUixvQkFBUSxRQUFRLFFBQVE7QUFDNUIscUJBQVcsUUFBUTtBQUFBLGVBQ2hCO0FBQ0gsa0JBQVEsU0FBUztBQUNqQixrQkFBUSxRQUFRLFNBQVM7QUFDekIsa0JBQVEsU0FBUyxRQUFRO0FBQ3pCLHFCQUFXLFFBQVE7QUFBQTtBQUFBO0FBRy9CLFVBQUksaUNBQWdCLGNBQ2YsU0FBUyxrQkFDVCxXQUFXLFVBQ1gsUUFBUSxnQkFDUixRQUFRLE1BQVk7QUFDakIsZ0JBQVEsUUFBUSxPQUFPO0FBQ3ZCLGNBQU0sWUFBWSxTQUFTLEtBQUssS0FBSztBQUFBO0FBQUE7QUFLakQsUUFBSSxVQUFVLFFBQVEsU0FBUyxPQUFPLEVBQUUsS0FBSztBQUM3QyxRQUFJLGlDQUFnQixTQUNmLGNBQWMsaUJBQ2QsUUFBUSxNQUFNLFVBQVUsVUFBVSxVQUFVLG9CQUFvQixTQUFTO0FBQzlFLFFBQUksaUNBQWdCLFNBQ2YsY0FBYyxlQUNkLFFBQVEsTUFBTSxVQUFVLFVBQVUsVUFBVSxVQUFVLFNBQVM7QUFBQTtBQUl4RSxxQkFBbUIsU0FBUyxTQUFTLE9BQU87QUFDNUMsTUFBSSxhQUFhLE9BQU8sWUFBWSxNQUFNO0FBRXRDLFFBQUksQ0FBQyxRQUFRLGFBQWE7QUFDdEIsYUFBTyxjQUFjO0FBQ3JCO0FBQUE7QUFFSix1QkFBbUIsU0FBUyxTQUFTLE9BQU87QUFBQSxLQUM3QztBQUFBO0FBR1AsNEJBQTRCLFNBQWtCLFNBQXNCLE9BQW9CLFlBQTRCO0FBQ2hILE1BQUksWUFBWSxRQUFRLFFBQVE7QUFDaEMsTUFBSSxXQUFXO0FBQ1gsUUFBSSxDQUFDLFVBQVU7QUFDWCxjQUFRLFFBQVEsc0JBQXNCLFVBQVUsV0FBVywrQkFBUztBQUN4RSxVQUFNLFFBQVEsZUFBZSxpQkFBaUI7QUFBQTtBQUVsRCxhQUFXLFNBQVMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxVQUFVO0FBQUE7QUFHbEQsMEJBQTBCLFNBQTBCO0FBQ2hELE1BQUksZ0JBQWdCO0FBQ3BCLFdBQVMsU0FBUyxRQUFRLFNBQVM7QUFDL0IsUUFBSSxVQUFVLE1BQU0sVUFBVSx3QkFBTyxLQUFLLE1BQU0sV0FBVztBQUMzRCxxQkFBaUIsUUFBUSxLQUFLLHdCQUFPLEtBQUssTUFBTTtBQUFBO0FBRXBELFNBQU87QUFBQTtBQUdYLHlCQUF5QixXQUFtQixVQUE2QztBQUNyRixTQUFPLHdCQUFPLEtBQUssV0FBVyxPQUFPLFNBQVM7QUFBQTtBQUdsRCwrQkFBK0IsV0FBbUIsU0FBeUI7QUFDdkUsU0FBTyxlQUFlLHdCQUFPLEtBQUssU0FBUyxLQUFLLHdCQUFPLEtBQUs7QUFBQTtBQUdoRSx3QkFBd0IsV0FBMkI7QUFDL0MsTUFBSSxXQUFXLHdCQUFPLFNBQVM7QUFDL0IsTUFBSSxNQUFNO0FBQ1YsTUFBSSxTQUFTLFVBQVU7QUFDbkIsV0FBTyxTQUFTLFVBQVU7QUFDOUIsTUFBSSxTQUFTLFlBQVk7QUFDckIsV0FBTyxTQUFTLFlBQVk7QUFDaEMsU0FBTyxTQUFTLFlBQVk7QUFDNUIsU0FBTztBQUFBO0FBR1gsNkJBQTZCLFNBQWtCLFVBQTZDO0FBQ3hGLE1BQUksUUFBUSxDQUFDLENBQUMsV0FBVyxjQUFjLFlBQVk7QUFDbkQsV0FBUyxTQUFTLFFBQVE7QUFDdEIsVUFBTSxLQUFLLGVBQWUsT0FBTztBQUNyQyxRQUFNLEtBQUssQ0FBQyxhQUFhLElBQUksSUFBSSxLQUFLLGVBQWUsaUJBQWlCO0FBRXRFLE1BQUksTUFBTTtBQUVWLE1BQUksU0FBUyxNQUFNLEtBQUssTUFBTSxHQUFHLFFBQVEsSUFBSSxPQUFLLEtBQUssSUFBSSxHQUFHLE1BQU0sSUFBSSxPQUFLLEVBQUUsR0FBRztBQUNsRixXQUFTLElBQUksR0FBRyxJQUFJLE1BQU0sUUFBUSxLQUFLO0FBRW5DLFFBQUksS0FBSztBQUNMLGFBQU8sTUFBTSxLQUFLLE1BQU0sR0FBRyxRQUFRLElBQUksT0FBSyxJQUFJLE9BQU8sT0FBTyxLQUFLLEtBQUssU0FBUztBQUVyRixRQUFJLE1BQWdCO0FBQ3BCLGFBQVMsSUFBSSxHQUFHLElBQUksR0FBRztBQUNuQixVQUFJLEtBQUssTUFBTSxHQUFHLEdBQUcsT0FBTyxPQUFPLElBQUk7QUFDM0MsV0FBTyxJQUFJLEtBQUssU0FBUztBQUFBO0FBRTdCLFNBQU87QUFBQTtBQUdYLG1CQUFtQixTQUFrQixVQUE2QztBQUM5RSxNQUFJLE1BQU07QUFDVixXQUFTLFNBQVMsUUFBUTtBQUN0QixXQUFPLGVBQWUsT0FBTyxVQUFVLEtBQUssU0FBUyxnQkFBZ0I7QUFDekUsU0FBTztBQUFBO0FBR1gsd0JBQXdCLE9BQWMsVUFBK0M7QUFDakYsU0FBTztBQUFBLElBQ0gsTUFBTTtBQUFBLElBQ04sZ0JBQWdCLE1BQU0sV0FBVztBQUFBLElBQ2pDLE1BQU0sVUFBVSxnQkFBZ0IsTUFBTSxTQUFTLFlBQVk7QUFBQSxJQUMzRCxNQUFNLFVBQVUsc0JBQXNCLE1BQU0sV0FBVyxNQUFNLFdBQVc7QUFBQTtBQUFBOzs7QUhuT2hGLDRDQUFxRCx3QkFBTztBQUFBLEVBSXJELFNBQXdCO0FBQUE7QUFDN0IsWUFBTSxLQUFLO0FBRVgsV0FBSyxjQUFjLElBQUksNkJBQTZCLEtBQUssS0FBSztBQUU5RCxXQUFLLG1DQUFtQyx1QkFBdUIsQ0FBQyxHQUFHLEdBQUcsTUFBTTtBQUMzRSxZQUFJLFVBQVUsWUFBWTtBQUMxQixVQUFFO0FBQ0YsdUJBQWUsU0FBUyxHQUFHLE1BQU0sRUFBRSxlQUFlLElBQUksS0FBSztBQUFBO0FBRzVELFdBQUssV0FBVztBQUFBLFFBQ2YsSUFBSTtBQUFBLFFBQ0osTUFBTTtBQUFBLFFBQ04sZ0JBQWdCLENBQUMsR0FBRyxNQUFNO0FBQ3pCLFlBQUUsaUJBQWlCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQUtoQixlQUFlO0FBQUE7QUFDcEIsV0FBSyxXQUFXLE9BQU8sT0FBTyxJQUFJLGlCQUFpQixNQUFNLEtBQUs7QUFBQTtBQUFBO0FBQUEsRUFHekQsZUFBZTtBQUFBO0FBQ3BCLFlBQU0sS0FBSyxTQUFTLEtBQUs7QUFBQTtBQUFBO0FBQUE7IiwKICAibmFtZXMiOiBbXQp9Cg==