ObsidianSimpleTimeTracker/test-vault/.obsidian/plugins/obsidian-simple-time-tracker/main.js
2022-09-28 14:11:49 +02:00

276 lines
34 KiB
JavaScript

/*
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();
let content = yield app.vault.cachedRead(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).setButtonText(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" }));
for (let entry of tracker.entries) {
let row = table.createEl("tr");
row.createEl("td", { text: entry.name });
row.createEl("td", { text: formatTimestamp(entry.startTime, settings) });
if (entry.endTime) {
row.createEl("td", { text: formatTimestamp(entry.endTime, settings) });
row.createEl("td", { text: formatDurationBetween(entry.startTime, entry.endTime) });
}
}
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-simple-time-tracker`,
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+IGkuZ2V0U2VjdGlvbkluZm8oZSksIHRoaXMuc2V0dGluZ3MpO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0dGhpcy5hZGRDb21tYW5kKHtcclxuXHRcdFx0aWQ6IGBpbnNlcnQtc2ltcGxlLXRpbWUtdHJhY2tlcmAsXHJcblx0XHRcdG5hbWU6IGBJbnNlcnQgVGltZSBUcmFja2VyYCxcclxuXHRcdFx0ZWRpdG9yQ2FsbGJhY2s6IChlLCBfKSA9PiB7XHJcblx0XHRcdFx0ZS5yZXBsYWNlU2VsZWN0aW9uKFwiYGBgc2ltcGxlLXRpbWUtdHJhY2tlclxcbmBgYFxcblwiKTtcclxuXHRcdFx0fVxyXG5cdFx0fSk7XHJcblx0fVxyXG5cclxuXHRhc3luYyBsb2FkU2V0dGluZ3MoKSB7XHJcblx0XHR0aGlzLnNldHRpbmdzID0gT2JqZWN0LmFzc2lnbih7fSwgZGVmYXVsdFNldHRpbmdzLCBhd2FpdCB0aGlzLmxvYWREYXRhKCkpO1xyXG5cdH1cclxuXHJcblx0YXN5bmMgc2F2ZVNldHRpbmdzKCkge1xyXG5cdFx0YXdhaXQgdGhpcy5zYXZlRGF0YSh0aGlzLnNldHRpbmdzKTtcclxuXHR9XHJcbn1cclxuIiwgImV4cG9ydCBjb25zdCBkZWZhdWx0U2V0dGluZ3M6IFNpbXBsZVRpbWVUcmFja2VyU2V0dGluZ3MgPSB7XHJcbiAgICB0aW1lc3RhbXBGb3JtYXQ6IFwiWVktTU0tREQgaGg6bW06c3NcIixcclxuICAgIGNzdkRlbGltaXRlcjogXCIsXCJcclxufTtcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgU2ltcGxlVGltZVRyYWNrZXJTZXR0aW5ncyB7XHJcblxyXG4gICAgdGltZXN0YW1wRm9ybWF0OiBzdHJpbmc7XHJcbiAgICBjc3ZEZWxpbWl0ZXI6IHN0cmluZztcclxuXHJcbn1cclxuIiwgImltcG9ydCB7IEFwcCwgUGx1Z2luU2V0dGluZ1RhYiwgU2V0dGluZyB9IGZyb20gXCJvYnNpZGlhblwiO1xyXG5pbXBvcnQgU2ltcGxlVGltZVRyYWNrZXJQbHVnaW4gZnJvbSBcIi4vbWFpblwiO1xyXG5pbXBvcnQgeyBkZWZhdWx0U2V0dGluZ3MgfSBmcm9tIFwiLi9zZXR0aW5nc1wiO1xyXG5cclxuZXhwb3J0IGNsYXNzIFNpbXBsZVRpbWVUcmFja2VyU2V0dGluZ3NUYWIgZXh0ZW5kcyBQbHVnaW5TZXR0aW5nVGFiIHtcclxuXHJcbiAgICBwbHVnaW46IFNpbXBsZVRpbWVUcmFja2VyUGx1Z2luO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKGFwcDogQXBwLCBwbHVnaW46IFNpbXBsZVRpbWVUcmFja2VyUGx1Z2luKSB7XHJcbiAgICAgICAgc3VwZXIoYXBwLCBwbHVnaW4pO1xyXG4gICAgICAgIHRoaXMucGx1Z2luID0gcGx1Z2luO1xyXG4gICAgfVxyXG5cclxuICAgIGRpc3BsYXkoKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5jb250YWluZXJFbC5lbXB0eSgpO1xyXG4gICAgICAgIHRoaXMuY29udGFpbmVyRWwuY3JlYXRlRWwoXCJoMlwiLCB7IHRleHQ6IFwiU3VwZXIgU2ltcGxlIFRpbWUgVHJhY2tlciBTZXR0aW5nc1wiIH0pO1xyXG5cclxuICAgICAgICBuZXcgU2V0dGluZyh0aGlzLmNvbnRhaW5lckVsKVxyXG4gICAgICAgICAgICAuc2V0TmFtZShcIlRpbWVzdGFtcCBEaXNwbGF5IEZvcm1hdFwiKVxyXG4gICAgICAgICAgICAuc2V0RGVzYyhjcmVhdGVGcmFnbWVudChmID0+IHtcclxuICAgICAgICAgICAgICAgIGYuY3JlYXRlU3Bhbih7IHRleHQ6IFwiVGhlIHdheSB0aGF0IHRpbWVzdGFtcHMgaW4gdGltZSB0cmFja2VyIHRhYmxlcyBzaG91bGQgYmUgZGlzcGxheWVkLiBVc2VzIFwiIH0pO1xyXG4gICAgICAgICAgICAgICAgZi5jcmVhdGVFbChcImFcIiwgeyB0ZXh0OiBcIm1vbWVudC5qc1wiLCBocmVmOiBcImh0dHBzOi8vbW9tZW50anMuY29tL2RvY3MvIy9wYXJzaW5nL3N0cmluZy1mb3JtYXQvXCIgfSk7XHJcbiAgICAgICAgICAgICAgICBmLmNyZWF0ZVNwYW4oeyB0ZXh0OiBcIiBzeW50YXguXCIgfSk7XHJcbiAgICAgICAgICAgIH0pKVxyXG4gICAgICAgICAgICAuYWRkVGV4dCh0ID0+IHtcclxuICAgICAgICAgICAgICAgIHQuc2V0VmFsdWUoU3RyaW5nKHRoaXMucGx1Z2luLnNldHRpbmdzLnRpbWVzdGFtcEZvcm1hdCkpO1xyXG4gICAgICAgICAgICAgICAgdC5vbkNoYW5nZShhc3luYyB2ID0+IHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy50aW1lc3RhbXBGb3JtYXQgPSB2Lmxlbmd0aCA/IHYgOiBkZWZhdWx0U2V0dGluZ3MudGltZXN0YW1wRm9ybWF0O1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICBuZXcgU2V0dGluZyh0aGlzLmNvbnRhaW5lckVsKVxyXG4gICAgICAgICAgICAuc2V0TmFtZShcIkNTViBEZWxpbWl0ZXJcIilcclxuICAgICAgICAgICAgLnNldERlc2MoXCJUaGUgZGVsaW1pdGVyIGNoYXJhY3RlciB0aGF0IHNob3VsZCBiZSB1c2VkIHdoZW4gY29weWluZyBhIHRyYWNrZXIgdGFibGUgYXMgQ1NWLiBGb3IgZXhhbXBsZSwgc29tZSBsYW5ndWFnZXMgdXNlIGEgc2VtaWNvbG9uIGluc3RlYWQgb2YgYSBjb21tYS5cIilcclxuICAgICAgICAgICAgLmFkZFRleHQodCA9PiB7XHJcbiAgICAgICAgICAgICAgICB0LnNldFZhbHVlKFN0cmluZyh0aGlzLnBsdWdpbi5zZXR0aW5ncy5jc3ZEZWxpbWl0ZXIpKTtcclxuICAgICAgICAgICAgICAgIHQub25DaGFuZ2UoYXN5bmMgdiA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MuY3N2RGVsaW1pdGVyID0gdi5sZW5ndGggPyB2IDogZGVmYXVsdFNldHRpbmdzLmNzdkRlbGltaXRlcjtcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdGhpcy5jb250YWluZXJFbC5jcmVhdGVFbChcImhyXCIpO1xyXG4gICAgICAgIHRoaXMuY29udGFpbmVyRWwuY3JlYXRlRWwoXCJwXCIsIHsgdGV4dDogXCJJZiB5b3UgbGlrZSB0aGlzIHBsdWdpbiBhbmQgd2FudCB0byBzdXBwb3J0IGl0cyBkZXZlbG9wbWVudCwgeW91IGNhbiBkbyBzbyB0aHJvdWdoIG15IHdlYnNpdGUgYnkgY2xpY2tpbmcgdGhpcyBmYW5jeSBpbWFnZSFcIiB9KTtcclxuICAgICAgICB0aGlzLmNvbnRhaW5lckVsLmNyZWF0ZUVsKFwiYVwiLCB7IGhyZWY6IFwiaHR0cHM6Ly9lbGxwZWNrLmRlL3N1cHBvcnRcIiB9KVxyXG4gICAgICAgICAgICAuY3JlYXRlRWwoXCJpbWdcIiwgeyBhdHRyOiB7IHNyYzogXCJodHRwczovL2VsbHBlY2suZGUvcmVzL2dlbmVyYWxzdXBwb3J0LnBuZ1wiIH0sIGNsczogXCJzaW1wbGUtdGltZS10cmFja2VyLXN1cHBvcnRcIiB9KTtcclxuICAgIH1cclxufVxyXG4iLCAiaW1wb3J0IHsgbW9tZW50LCBBcHAsIE1hcmtkb3duU2VjdGlvbkluZm9ybWF0aW9uLCBCdXR0b25Db21wb25lbnQsIFRleHRDb21wb25lbnQgfSBmcm9tIFwib2JzaWRpYW5cIjtcclxuaW1wb3J0IHsgU2ltcGxlVGltZVRyYWNrZXJTZXR0aW5ncyB9IGZyb20gXCIuL3NldHRpbmdzXCI7XHJcblxyXG5leHBvcnQgY2xhc3MgVHJhY2tlciB7XHJcbiAgICBlbnRyaWVzOiBFbnRyeVtdO1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIEVudHJ5IHtcclxuICAgIG5hbWU6IHN0cmluZztcclxuICAgIHN0YXJ0VGltZTogbnVtYmVyO1xyXG4gICAgZW5kVGltZTogbnVtYmVyO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gc3RhcnRFbnRyeSh0cmFja2VyOiBUcmFja2VyLCBuYW1lOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGlmICghbmFtZSlcclxuICAgICAgICBuYW1lID0gYFNlZ21lbnQgJHt0cmFja2VyLmVudHJpZXMubGVuZ3RoICsgMX1gO1xyXG4gICAgbGV0IGVudHJ5OiBFbnRyeSA9IHsgbmFtZTogbmFtZSwgc3RhcnRUaW1lOiBtb21lbnQoKS51bml4KCksIGVuZFRpbWU6IG51bGwgfTtcclxuICAgIHRyYWNrZXIuZW50cmllcy5wdXNoKGVudHJ5KTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBlbmRFbnRyeSh0cmFja2VyOiBUcmFja2VyKTogdm9pZCB7XHJcbiAgICBsZXQgbGFzdCA9IHRyYWNrZXIuZW50cmllcy5sYXN0KCk7XHJcbiAgICBsYXN0LmVuZFRpbWUgPSBtb21lbnQoKS51bml4KCk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBpc1J1bm5pbmcodHJhY2tlcjogVHJhY2tlcik6IGJvb2xlYW4ge1xyXG4gICAgbGV0IGxhc3QgPSB0cmFja2VyLmVudHJpZXMubGFzdCgpO1xyXG4gICAgcmV0dXJuIGxhc3QgIT0gbnVsbCAmJiAhbGFzdC5lbmRUaW1lO1xyXG59XHJcblxyXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2F2ZVRyYWNrZXIodHJhY2tlcjogVHJhY2tlciwgYXBwOiBBcHAsIHNlY3Rpb246IE1hcmtkb3duU2VjdGlvbkluZm9ybWF0aW9uKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICBsZXQgZmlsZSA9IGFwcC53b3Jrc3BhY2UuZ2V0QWN0aXZlRmlsZSgpO1xyXG4gICAgbGV0IGNvbnRlbnQgPSBhd2FpdCBhcHAudmF1bHQuY2FjaGVkUmVhZChmaWxlKTtcclxuXHJcbiAgICAvLyBmaWd1cmUgb3V0IHdoYXQgcGFydCBvZiB0aGUgY29udGVudCB3ZSBoYXZlIHRvIGVkaXRcclxuICAgIGxldCBsaW5lcyA9IGNvbnRlbnQuc3BsaXQoXCJcXG5cIik7XHJcbiAgICBsZXQgcHJldiA9IGxpbmVzLmZpbHRlcigoXywgaSkgPT4gaSA8PSBzZWN0aW9uLmxpbmVTdGFydCkuam9pbihcIlxcblwiKTtcclxuICAgIGxldCBuZXh0ID0gbGluZXMuZmlsdGVyKChfLCBpKSA9PiBpID49IHNlY3Rpb24ubGluZUVuZCkuam9pbihcIlxcblwiKTtcclxuICAgIC8vIGVkaXQgb25seSB0aGUgY29kZSBibG9jayBjb250ZW50LCBsZWF2ZSB0aGUgcmVzdCB1bnRvdWNoZWRcclxuICAgIGNvbnRlbnQgPSBgJHtwcmV2fVxcbiR7SlNPTi5zdHJpbmdpZnkodHJhY2tlcil9XFxuJHtuZXh0fWA7XHJcblxyXG4gICAgYXdhaXQgYXBwLnZhdWx0Lm1vZGlmeShmaWxlLCBjb250ZW50KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGxvYWRUcmFja2VyKGpzb246IHN0cmluZyk6IFRyYWNrZXIge1xyXG4gICAgaWYgKGpzb24pIHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShqc29uKTtcclxuICAgICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBGYWlsZWQgdG8gcGFyc2UgVHJhY2tlciBmcm9tICR7anNvbn1gKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4geyBlbnRyaWVzOiBbXSB9O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gZGlzcGxheVRyYWNrZXIodHJhY2tlcjogVHJhY2tlciwgZWxlbWVudDogSFRNTEVsZW1lbnQsIGdldFNlY3Rpb25JbmZvOiAoKSA9PiBNYXJrZG93blNlY3Rpb25JbmZvcm1hdGlvbiwgc2V0dGluZ3M6IFNpbXBsZVRpbWVUcmFja2VyU2V0dGluZ3MpOiB2b2lkIHtcclxuICAgIC8vIGFkZCBzdGFydC9zdG9wIGNvbnRyb2xzXHJcbiAgICBsZXQgcnVubmluZyA9IGlzUnVubmluZyh0cmFja2VyKTtcclxuICAgIGxldCBidG4gPSBuZXcgQnV0dG9uQ29tcG9uZW50KGVsZW1lbnQpXHJcbiAgICAgICAgLnNldEJ1dHRvblRleHQocnVubmluZyA/IFwiRW5kXCIgOiBcIlN0YXJ0XCIpXHJcbiAgICAgICAgLm9uQ2xpY2soYXN5bmMgKCkgPT4ge1xyXG4gICAgICAgICAgICBpZiAocnVubmluZykge1xyXG4gICAgICAgICAgICAgICAgZW5kRW50cnkodHJhY2tlcik7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBzdGFydEVudHJ5KHRyYWNrZXIsIG5hbWUuZ2V0VmFsdWUoKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgYXdhaXQgc2F2ZVRyYWNrZXIodHJhY2tlciwgdGhpcy5hcHAsIGdldFNlY3Rpb25JbmZvKCkpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgYnRuLmJ1dHRvbkVsLmFkZENsYXNzKFwic2ltcGxlLXRpbWUtdHJhY2tlci1idG5cIik7XHJcbiAgICBsZXQgbmFtZSA9IG5ldyBUZXh0Q29tcG9uZW50KGVsZW1lbnQpXHJcbiAgICAgICAgLnNldFBsYWNlaG9sZGVyKFwiU2VnbWVudCBuYW1lXCIpXHJcbiAgICAgICAgLnNldERpc2FibGVkKHJ1bm5pbmcpO1xyXG4gICAgbmFtZS5pbnB1dEVsLmFkZENsYXNzKFwic2ltcGxlLXRpbWUtdHJhY2tlci10eHRcIik7XHJcblxyXG4gICAgLy8gYWRkIHRpbWVyc1xyXG4gICAgbGV0IHRpbWVyID0gZWxlbWVudC5jcmVhdGVEaXYoeyBjbHM6IFwic2ltcGxlLXRpbWUtdHJhY2tlci10aW1lcnNcIiB9KTtcclxuICAgIGxldCBjdXJyZW50RGl2ID0gdGltZXIuY3JlYXRlRWwoXCJkaXZcIiwgeyBjbHM6IFwic2ltcGxlLXRpbWUtdHJhY2tlci10aW1lclwiIH0pO1xyXG4gICAgbGV0IGN1cnJlbnQgPSBjdXJyZW50RGl2LmNyZWF0ZUVsKFwic3BhblwiLCB7IGNsczogXCJzaW1wbGUtdGltZS10cmFja2VyLXRpbWVyLXRpbWVcIiB9KTtcclxuICAgIGN1cnJlbnREaXYuY3JlYXRlRWwoXCJzcGFuXCIsIHsgdGV4dDogXCJDdXJyZW50XCIgfSk7XHJcbiAgICBsZXQgdG90YWxEaXYgPSB0aW1lci5jcmVhdGVFbChcImRpdlwiLCB7IGNsczogXCJzaW1wbGUtdGltZS10cmFja2VyLXRpbWVyXCIgfSk7XHJcbiAgICBsZXQgdG90YWwgPSB0b3RhbERpdi5jcmVhdGVFbChcInNwYW5cIiwgeyBjbHM6IFwic2ltcGxlLXRpbWUtdHJhY2tlci10aW1lci10aW1lXCIsIHRleHQ6IFwiMHNcIiB9KTtcclxuICAgIHRvdGFsRGl2LmNyZWF0ZUVsKFwic3BhblwiLCB7IHRleHQ6IFwiVG90YWxcIiB9KTtcclxuXHJcbiAgICBpZiAodHJhY2tlci5lbnRyaWVzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAvLyBhZGQgdGFibGVcclxuICAgICAgICBsZXQgdGFibGUgPSBlbGVtZW50LmNyZWF0ZUVsKFwidGFibGVcIiwgeyBjbHM6IFwic2ltcGxlLXRpbWUtdHJhY2tlci10YWJsZVwiIH0pO1xyXG4gICAgICAgIHRhYmxlLmNyZWF0ZUVsKFwidHJcIikuYXBwZW5kKFxyXG4gICAgICAgICAgICBjcmVhdGVFbChcInRoXCIsIHsgdGV4dDogXCJTZWdtZW50XCIgfSksXHJcbiAgICAgICAgICAgIGNyZWF0ZUVsKFwidGhcIiwgeyB0ZXh0OiBcIlN0YXJ0IHRpbWVcIiB9KSxcclxuICAgICAgICAgICAgY3JlYXRlRWwoXCJ0aFwiLCB7IHRleHQ6IFwiRW5kIHRpbWVcIiB9KSxcclxuICAgICAgICAgICAgY3JlYXRlRWwoXCJ0aFwiLCB7IHRleHQ6IFwiRHVyYXRpb25cIiB9KSk7XHJcblxyXG4gICAgICAgIGZvciAobGV0IGVudHJ5IG9mIHRyYWNrZXIuZW50cmllcykge1xyXG4gICAgICAgICAgICBsZXQgcm93ID0gdGFibGUuY3JlYXRlRWwoXCJ0clwiKTtcclxuICAgICAgICAgICAgcm93LmNyZWF0ZUVsKFwidGRcIiwgeyB0ZXh0OiBlbnRyeS5uYW1lIH0pO1xyXG4gICAgICAgICAgICByb3cuY3JlYXRlRWwoXCJ0ZFwiLCB7IHRleHQ6IGZvcm1hdFRpbWVzdGFtcChlbnRyeS5zdGFydFRpbWUsIHNldHRpbmdzKSB9KTtcclxuICAgICAgICAgICAgaWYgKGVudHJ5LmVuZFRpbWUpIHtcclxuICAgICAgICAgICAgICAgIHJvdy5jcmVhdGVFbChcInRkXCIsIHsgdGV4dDogZm9ybWF0VGltZXN0YW1wKGVudHJ5LmVuZFRpbWUsIHNldHRpbmdzKSB9KTtcclxuICAgICAgICAgICAgICAgIHJvdy5jcmVhdGVFbChcInRkXCIsIHsgdGV4dDogZm9ybWF0RHVyYXRpb25CZXR3ZWVuKGVudHJ5LnN0YXJ0VGltZSwgZW50cnkuZW5kVGltZSkgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIGFkZCBjb3B5IGJ1dHRvbnNcclxuICAgICAgICBsZXQgYnV0dG9ucyA9IGVsZW1lbnQuY3JlYXRlRWwoXCJkaXZcIiwgeyBjbHM6IFwic2ltcGxlLXRpbWUtdHJhY2tlci1ib3R0b21cIiB9KTtcclxuICAgICAgICBuZXcgQnV0dG9uQ29tcG9uZW50KGJ1dHRvbnMpXHJcbiAgICAgICAgICAgIC5zZXRCdXR0b25UZXh0KFwiQ29weSBhcyB0YWJsZVwiKVxyXG4gICAgICAgICAgICAub25DbGljaygoKSA9PiBuYXZpZ2F0b3IuY2xpcGJvYXJkLndyaXRlVGV4dChjcmVhdGVNYXJrZG93blRhYmxlKHRyYWNrZXIsIHNldHRpbmdzKSkpO1xyXG4gICAgICAgIG5ldyBCdXR0b25Db21wb25lbnQoYnV0dG9ucylcclxuICAgICAgICAgICAgLnNldEJ1dHRvblRleHQoXCJDb3B5IGFzIENTVlwiKVxyXG4gICAgICAgICAgICAub25DbGljaygoKSA9PiBuYXZpZ2F0b3IuY2xpcGJvYXJkLndyaXRlVGV4dChjcmVhdGVDc3YodHJhY2tlciwgc2V0dGluZ3MpKSk7XHJcbiAgICB9XHJcblxyXG5cclxuICAgIHNldENvdW50ZG93blZhbHVlcyh0cmFja2VyLCBjdXJyZW50LCB0b3RhbCwgY3VycmVudERpdik7XHJcbiAgICBsZXQgaW50ZXJ2YWxJZCA9IHdpbmRvdy5zZXRJbnRlcnZhbCgoKSA9PiB7XHJcbiAgICAgICAgLy8gd2UgZGVsZXRlIHRoZSBpbnRlcnZhbCB0aW1lciB3aGVuIHRoZSBlbGVtZW50IGlzIHJlbW92ZWRcclxuICAgICAgICBpZiAoIWVsZW1lbnQuaXNDb25uZWN0ZWQpIHtcclxuICAgICAgICAgICAgd2luZG93LmNsZWFySW50ZXJ2YWwoaW50ZXJ2YWxJZCk7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgc2V0Q291bnRkb3duVmFsdWVzKHRyYWNrZXIsIGN1cnJlbnQsIHRvdGFsLCBjdXJyZW50RGl2KTtcclxuICAgIH0sIDEwMDApO1xyXG59XHJcblxyXG5mdW5jdGlvbiBzZXRDb3VudGRvd25WYWx1ZXModHJhY2tlcjogVHJhY2tlciwgY3VycmVudDogSFRNTEVsZW1lbnQsIHRvdGFsOiBIVE1MRWxlbWVudCwgY3VycmVudERpdjogSFRNTERpdkVsZW1lbnQpIHtcclxuICAgIGxldCBjdXJyRW50cnkgPSB0cmFja2VyLmVudHJpZXMubGFzdCgpO1xyXG4gICAgaWYgKGN1cnJFbnRyeSkge1xyXG4gICAgICAgIGlmICghY3VyckVudHJ5LmVuZFRpbWUpXHJcbiAgICAgICAgICAgIGN1cnJlbnQuc2V0VGV4dChmb3JtYXREdXJhdGlvbkJldHdlZW4oY3VyckVudHJ5LnN0YXJ0VGltZSwgbW9tZW50KCkudW5peCgpKSk7XHJcbiAgICAgICAgdG90YWwuc2V0VGV4dChmb3JtYXREdXJhdGlvbihnZXRUb3RhbER1cmF0aW9uKHRyYWNrZXIpKSk7XHJcbiAgICB9XHJcbiAgICBjdXJyZW50RGl2LmhpZGRlbiA9ICFjdXJyRW50cnkgfHwgISFjdXJyRW50cnkuZW5kVGltZTtcclxufVxyXG5cclxuZnVuY3Rpb24gZ2V0VG90YWxEdXJhdGlvbih0cmFja2VyOiBUcmFja2VyKTogbnVtYmVyIHtcclxuICAgIGxldCB0b3RhbER1cmF0aW9uID0gMDtcclxuICAgIGZvciAobGV0IGVudHJ5IG9mIHRyYWNrZXIuZW50cmllcykge1xyXG4gICAgICAgIGxldCBlbmRUaW1lID0gZW50cnkuZW5kVGltZSA/IG1vbWVudC51bml4KGVudHJ5LmVuZFRpbWUpIDogbW9tZW50KCk7XHJcbiAgICAgICAgdG90YWxEdXJhdGlvbiArPSBlbmRUaW1lLmRpZmYobW9tZW50LnVuaXgoZW50cnkuc3RhcnRUaW1lKSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdG90YWxEdXJhdGlvbjtcclxufVxyXG5cclxuZnVuY3Rpb24gZm9ybWF0VGltZXN0YW1wKHRpbWVzdGFtcDogbnVtYmVyLCBzZXR0aW5nczogU2ltcGxlVGltZVRyYWNrZXJTZXR0aW5ncyk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gbW9tZW50LnVuaXgodGltZXN0YW1wKS5mb3JtYXQoc2V0dGluZ3MudGltZXN0YW1wRm9ybWF0KTtcclxufVxyXG5cclxuZnVuY3Rpb24gZm9ybWF0RHVyYXRpb25CZXR3ZWVuKHN0YXJ0VGltZTogbnVtYmVyLCBlbmRUaW1lOiBudW1iZXIpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIGZvcm1hdER1cmF0aW9uKG1vbWVudC51bml4KGVuZFRpbWUpLmRpZmYobW9tZW50LnVuaXgoc3RhcnRUaW1lKSkpO1xyXG59XHJcblxyXG5mdW5jdGlvbiBmb3JtYXREdXJhdGlvbih0b3RhbFRpbWU6IG51bWJlcik6IHN0cmluZyB7XHJcbiAgICBsZXQgZHVyYXRpb24gPSBtb21lbnQuZHVyYXRpb24odG90YWxUaW1lKTtcclxuICAgIGxldCByZXQgPSBcIlwiO1xyXG4gICAgaWYgKGR1cmF0aW9uLmhvdXJzKCkgPiAwKVxyXG4gICAgICAgIHJldCArPSBkdXJhdGlvbi5ob3VycygpICsgXCJoIFwiO1xyXG4gICAgaWYgKGR1cmF0aW9uLm1pbnV0ZXMoKSA+IDApXHJcbiAgICAgICAgcmV0ICs9IGR1cmF0aW9uLm1pbnV0ZXMoKSArIFwibSBcIjtcclxuICAgIHJldCArPSBkdXJhdGlvbi5zZWNvbmRzKCkgKyBcInNcIjtcclxuICAgIHJldHVybiByZXQ7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZU1hcmtkb3duVGFibGUodHJhY2tlcjogVHJhY2tlciwgc2V0dGluZ3M6IFNpbXBsZVRpbWVUcmFja2VyU2V0dGluZ3MpOiBzdHJpbmcge1xyXG4gICAgbGV0IHRhYmxlID0gW1tcIlNlZ21lbnRcIiwgXCJTdGFydCB0aW1lXCIsIFwiRW5kIHRpbWVcIiwgXCJEdXJhdGlvblwiXV07XHJcbiAgICBmb3IgKGxldCBlbnRyeSBvZiB0cmFja2VyLmVudHJpZXMpXHJcbiAgICAgICAgdGFibGUucHVzaChjcmVhdGVUYWJsZVJvdyhlbnRyeSwgc2V0dGluZ3MpKTtcclxuICAgIHRhYmxlLnB1c2goW1wiKipUb3RhbCoqXCIsIFwiXCIsIFwiXCIsIGAqKiR7Zm9ybWF0RHVyYXRpb24oZ2V0VG90YWxEdXJhdGlvbih0cmFja2VyKSl9KipgXSk7XHJcblxyXG4gICAgbGV0IHJldCA9IFwiXCI7XHJcbiAgICAvLyBjYWxjdWxhdGUgdGhlIHdpZHRoIGV2ZXJ5IGNvbHVtbiBuZWVkcyB0byBsb29rIG5lYXQgd2hlbiBtb25vc3BhY2VkXHJcbiAgICBsZXQgd2lkdGhzID0gQXJyYXkuZnJvbShBcnJheSg0KS5rZXlzKCkpLm1hcChpID0+IE1hdGgubWF4KC4uLnRhYmxlLm1hcChhID0+IGFbaV0ubGVuZ3RoKSkpO1xyXG4gICAgZm9yIChsZXQgciA9IDA7IHIgPCB0YWJsZS5sZW5ndGg7IHIrKykge1xyXG4gICAgICAgIC8vIGFkZCBzZXBhcmF0b3JzIGFmdGVyIGZpcnN0IHJvd1xyXG4gICAgICAgIGlmIChyID09IDEpXHJcbiAgICAgICAgICAgIHJldCArPSBBcnJheS5mcm9tKEFycmF5KDQpLmtleXMoKSkubWFwKGkgPT4gXCItXCIucmVwZWF0KHdpZHRoc1tpXSkpLmpvaW4oXCIgfCBcIikgKyBcIlxcblwiO1xyXG5cclxuICAgICAgICBsZXQgcm93OiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNDsgaSsrKVxyXG4gICAgICAgICAgICByb3cucHVzaCh0YWJsZVtyXVtpXS5wYWRFbmQod2lkdGhzW2ldLCBcIiBcIikpO1xyXG4gICAgICAgIHJldCArPSByb3cuam9pbihcIiB8IFwiKSArIFwiXFxuXCI7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcmV0O1xyXG59XHJcblxyXG5mdW5jdGlvbiBjcmVhdGVDc3YodHJhY2tlcjogVHJhY2tlciwgc2V0dGluZ3M6IFNpbXBsZVRpbWVUcmFja2VyU2V0dGluZ3MpOiBzdHJpbmcge1xyXG4gICAgbGV0IHJldCA9IFwiXCI7XHJcbiAgICBmb3IgKGxldCBlbnRyeSBvZiB0cmFja2VyLmVudHJpZXMpXHJcbiAgICAgICAgcmV0ICs9IGNyZWF0ZVRhYmxlUm93KGVudHJ5LCBzZXR0aW5ncykuam9pbihzZXR0aW5ncy5jc3ZEZWxpbWl0ZXIpICsgXCJcXG5cIjtcclxuICAgIHJldHVybiByZXQ7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZVRhYmxlUm93KGVudHJ5OiBFbnRyeSwgc2V0dGluZ3M6IFNpbXBsZVRpbWVUcmFja2VyU2V0dGluZ3MpOiBzdHJpbmdbXSB7XHJcbiAgICByZXR1cm4gW1xyXG4gICAgICAgIGVudHJ5Lm5hbWUsXHJcbiAgICAgICAgZm9ybWF0VGltZXN0YW1wKGVudHJ5LnN0YXJ0VGltZSwgc2V0dGluZ3MpLFxyXG4gICAgICAgIGVudHJ5LmVuZFRpbWUgPyBmb3JtYXRUaW1lc3RhbXAoZW50cnkuZW5kVGltZSwgc2V0dGluZ3MpIDogXCJcIixcclxuICAgICAgICBlbnRyeS5lbmRUaW1lID8gZm9ybWF0RHVyYXRpb25CZXR3ZWVuKGVudHJ5LnN0YXJ0VGltZSwgZW50cnkuZW5kVGltZSkgOiBcIlwiXTtcclxufVxyXG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUEsdUJBQXVCOzs7QUNBaEIsSUFBTSxrQkFBNkM7QUFBQSxFQUN0RCxpQkFBaUI7QUFBQSxFQUNqQixjQUFjO0FBQUE7OztBQ0ZsQixzQkFBK0M7QUFJeEMsaURBQTJDLGlDQUFpQjtBQUFBLEVBSS9ELFlBQVksS0FBVSxRQUFpQztBQUNuRCxVQUFNLEtBQUs7QUFDWCxTQUFLLFNBQVM7QUFBQTtBQUFBLEVBR2xCLFVBQWdCO0FBQ1osU0FBSyxZQUFZO0FBQ2pCLFNBQUssWUFBWSxTQUFTLE1BQU0sRUFBRSxNQUFNO0FBRXhDLFFBQUksd0JBQVEsS0FBSyxhQUNaLFFBQVEsNEJBQ1IsUUFBUSxlQUFlLE9BQUs7QUFDekIsUUFBRSxXQUFXLEVBQUUsTUFBTTtBQUNyQixRQUFFLFNBQVMsS0FBSyxFQUFFLE1BQU0sYUFBYSxNQUFNO0FBQzNDLFFBQUUsV0FBVyxFQUFFLE1BQU07QUFBQSxRQUV4QixRQUFRLE9BQUs7QUFDVixRQUFFLFNBQVMsT0FBTyxLQUFLLE9BQU8sU0FBUztBQUN2QyxRQUFFLFNBQVMsQ0FBTSxNQUFLO0FBQ2xCLGFBQUssT0FBTyxTQUFTLGtCQUFrQixFQUFFLFNBQVMsSUFBSSxnQkFBZ0I7QUFDdEUsY0FBTSxLQUFLLE9BQU87QUFBQTtBQUFBO0FBSTlCLFFBQUksd0JBQVEsS0FBSyxhQUNaLFFBQVEsaUJBQ1IsUUFBUSxvSkFDUixRQUFRLE9BQUs7QUFDVixRQUFFLFNBQVMsT0FBTyxLQUFLLE9BQU8sU0FBUztBQUN2QyxRQUFFLFNBQVMsQ0FBTSxNQUFLO0FBQ2xCLGFBQUssT0FBTyxTQUFTLGVBQWUsRUFBRSxTQUFTLElBQUksZ0JBQWdCO0FBQ25FLGNBQU0sS0FBSyxPQUFPO0FBQUE7QUFBQTtBQUk5QixTQUFLLFlBQVksU0FBUztBQUMxQixTQUFLLFlBQVksU0FBUyxLQUFLLEVBQUUsTUFBTTtBQUN2QyxTQUFLLFlBQVksU0FBUyxLQUFLLEVBQUUsTUFBTSxnQ0FDbEMsU0FBUyxPQUFPLEVBQUUsTUFBTSxFQUFFLEtBQUssK0NBQStDLEtBQUs7QUFBQTtBQUFBOzs7QUM5Q2hHLHVCQUF3RjtBQWFqRixvQkFBb0IsU0FBa0IsTUFBb0I7QUFDN0QsTUFBSSxDQUFDO0FBQ0QsV0FBTyxXQUFXLFFBQVEsUUFBUSxTQUFTO0FBQy9DLE1BQUksUUFBZSxFQUFFLE1BQVksV0FBVywrQkFBUyxRQUFRLFNBQVM7QUFDdEUsVUFBUSxRQUFRLEtBQUs7QUFBQTtBQUdsQixrQkFBa0IsU0FBd0I7QUFDN0MsTUFBSSxPQUFPLFFBQVEsUUFBUTtBQUMzQixPQUFLLFVBQVUsK0JBQVM7QUFBQTtBQUdyQixtQkFBbUIsU0FBMkI7QUFDakQsTUFBSSxPQUFPLFFBQVEsUUFBUTtBQUMzQixTQUFPLFFBQVEsUUFBUSxDQUFDLEtBQUs7QUFBQTtBQUdqQyxxQkFBa0MsU0FBa0IsS0FBVSxTQUFvRDtBQUFBO0FBQzlHLFFBQUksT0FBTyxJQUFJLFVBQVU7QUFDekIsUUFBSSxVQUFVLE1BQU0sSUFBSSxNQUFNLFdBQVc7QUFHekMsUUFBSSxRQUFRLFFBQVEsTUFBTTtBQUMxQixRQUFJLE9BQU8sTUFBTSxPQUFPLENBQUMsR0FBRyxNQUFNLEtBQUssUUFBUSxXQUFXLEtBQUs7QUFDL0QsUUFBSSxPQUFPLE1BQU0sT0FBTyxDQUFDLEdBQUcsTUFBTSxLQUFLLFFBQVEsU0FBUyxLQUFLO0FBRTdELGNBQVUsR0FBRztBQUFBLEVBQVMsS0FBSyxVQUFVO0FBQUEsRUFBYTtBQUVsRCxVQUFNLElBQUksTUFBTSxPQUFPLE1BQU07QUFBQTtBQUFBO0FBRzFCLHFCQUFxQixNQUF1QjtBQUMvQyxNQUFJLE1BQU07QUFDTixRQUFJO0FBQ0EsYUFBTyxLQUFLLE1BQU07QUFBQSxhQUNiLEdBQVA7QUFDRSxjQUFRLElBQUksZ0NBQWdDO0FBQUE7QUFBQTtBQUdwRCxTQUFPLEVBQUUsU0FBUztBQUFBO0FBR2Ysd0JBQXdCLFNBQWtCLFNBQXNCLGdCQUFrRCxVQUEyQztBQUVoSyxNQUFJLFVBQVUsVUFBVTtBQUN4QixNQUFJLE1BQU0sSUFBSSxpQ0FBZ0IsU0FDekIsY0FBYyxVQUFVLFFBQVEsU0FDaEMsUUFBUSxNQUFZO0FBQ2pCLFFBQUksU0FBUztBQUNULGVBQVM7QUFBQSxXQUNOO0FBQ0gsaUJBQVcsU0FBUyxLQUFLO0FBQUE7QUFFN0IsVUFBTSxZQUFZLFNBQVMsS0FBSyxLQUFLO0FBQUE7QUFFN0MsTUFBSSxTQUFTLFNBQVM7QUFDdEIsTUFBSSxPQUFPLElBQUksK0JBQWMsU0FDeEIsZUFBZSxnQkFDZixZQUFZO0FBQ2pCLE9BQUssUUFBUSxTQUFTO0FBR3RCLE1BQUksUUFBUSxRQUFRLFVBQVUsRUFBRSxLQUFLO0FBQ3JDLE1BQUksYUFBYSxNQUFNLFNBQVMsT0FBTyxFQUFFLEtBQUs7QUFDOUMsTUFBSSxVQUFVLFdBQVcsU0FBUyxRQUFRLEVBQUUsS0FBSztBQUNqRCxhQUFXLFNBQVMsUUFBUSxFQUFFLE1BQU07QUFDcEMsTUFBSSxXQUFXLE1BQU0sU0FBUyxPQUFPLEVBQUUsS0FBSztBQUM1QyxNQUFJLFFBQVEsU0FBUyxTQUFTLFFBQVEsRUFBRSxLQUFLLGtDQUFrQyxNQUFNO0FBQ3JGLFdBQVMsU0FBUyxRQUFRLEVBQUUsTUFBTTtBQUVsQyxNQUFJLFFBQVEsUUFBUSxTQUFTLEdBQUc7QUFFNUIsUUFBSSxRQUFRLFFBQVEsU0FBUyxTQUFTLEVBQUUsS0FBSztBQUM3QyxVQUFNLFNBQVMsTUFBTSxPQUNqQixTQUFTLE1BQU0sRUFBRSxNQUFNLGNBQ3ZCLFNBQVMsTUFBTSxFQUFFLE1BQU0saUJBQ3ZCLFNBQVMsTUFBTSxFQUFFLE1BQU0sZUFDdkIsU0FBUyxNQUFNLEVBQUUsTUFBTTtBQUUzQixhQUFTLFNBQVMsUUFBUSxTQUFTO0FBQy9CLFVBQUksTUFBTSxNQUFNLFNBQVM7QUFDekIsVUFBSSxTQUFTLE1BQU0sRUFBRSxNQUFNLE1BQU07QUFDakMsVUFBSSxTQUFTLE1BQU0sRUFBRSxNQUFNLGdCQUFnQixNQUFNLFdBQVc7QUFDNUQsVUFBSSxNQUFNLFNBQVM7QUFDZixZQUFJLFNBQVMsTUFBTSxFQUFFLE1BQU0sZ0JBQWdCLE1BQU0sU0FBUztBQUMxRCxZQUFJLFNBQVMsTUFBTSxFQUFFLE1BQU0sc0JBQXNCLE1BQU0sV0FBVyxNQUFNO0FBQUE7QUFBQTtBQUtoRixRQUFJLFVBQVUsUUFBUSxTQUFTLE9BQU8sRUFBRSxLQUFLO0FBQzdDLFFBQUksaUNBQWdCLFNBQ2YsY0FBYyxpQkFDZCxRQUFRLE1BQU0sVUFBVSxVQUFVLFVBQVUsb0JBQW9CLFNBQVM7QUFDOUUsUUFBSSxpQ0FBZ0IsU0FDZixjQUFjLGVBQ2QsUUFBUSxNQUFNLFVBQVUsVUFBVSxVQUFVLFVBQVUsU0FBUztBQUFBO0FBSXhFLHFCQUFtQixTQUFTLFNBQVMsT0FBTztBQUM1QyxNQUFJLGFBQWEsT0FBTyxZQUFZLE1BQU07QUFFdEMsUUFBSSxDQUFDLFFBQVEsYUFBYTtBQUN0QixhQUFPLGNBQWM7QUFDckI7QUFBQTtBQUVKLHVCQUFtQixTQUFTLFNBQVMsT0FBTztBQUFBLEtBQzdDO0FBQUE7QUFHUCw0QkFBNEIsU0FBa0IsU0FBc0IsT0FBb0IsWUFBNEI7QUFDaEgsTUFBSSxZQUFZLFFBQVEsUUFBUTtBQUNoQyxNQUFJLFdBQVc7QUFDWCxRQUFJLENBQUMsVUFBVTtBQUNYLGNBQVEsUUFBUSxzQkFBc0IsVUFBVSxXQUFXLCtCQUFTO0FBQ3hFLFVBQU0sUUFBUSxlQUFlLGlCQUFpQjtBQUFBO0FBRWxELGFBQVcsU0FBUyxDQUFDLGFBQWEsQ0FBQyxDQUFDLFVBQVU7QUFBQTtBQUdsRCwwQkFBMEIsU0FBMEI7QUFDaEQsTUFBSSxnQkFBZ0I7QUFDcEIsV0FBUyxTQUFTLFFBQVEsU0FBUztBQUMvQixRQUFJLFVBQVUsTUFBTSxVQUFVLHdCQUFPLEtBQUssTUFBTSxXQUFXO0FBQzNELHFCQUFpQixRQUFRLEtBQUssd0JBQU8sS0FBSyxNQUFNO0FBQUE7QUFFcEQsU0FBTztBQUFBO0FBR1gseUJBQXlCLFdBQW1CLFVBQTZDO0FBQ3JGLFNBQU8sd0JBQU8sS0FBSyxXQUFXLE9BQU8sU0FBUztBQUFBO0FBR2xELCtCQUErQixXQUFtQixTQUF5QjtBQUN2RSxTQUFPLGVBQWUsd0JBQU8sS0FBSyxTQUFTLEtBQUssd0JBQU8sS0FBSztBQUFBO0FBR2hFLHdCQUF3QixXQUEyQjtBQUMvQyxNQUFJLFdBQVcsd0JBQU8sU0FBUztBQUMvQixNQUFJLE1BQU07QUFDVixNQUFJLFNBQVMsVUFBVTtBQUNuQixXQUFPLFNBQVMsVUFBVTtBQUM5QixNQUFJLFNBQVMsWUFBWTtBQUNyQixXQUFPLFNBQVMsWUFBWTtBQUNoQyxTQUFPLFNBQVMsWUFBWTtBQUM1QixTQUFPO0FBQUE7QUFHWCw2QkFBNkIsU0FBa0IsVUFBNkM7QUFDeEYsTUFBSSxRQUFRLENBQUMsQ0FBQyxXQUFXLGNBQWMsWUFBWTtBQUNuRCxXQUFTLFNBQVMsUUFBUTtBQUN0QixVQUFNLEtBQUssZUFBZSxPQUFPO0FBQ3JDLFFBQU0sS0FBSyxDQUFDLGFBQWEsSUFBSSxJQUFJLEtBQUssZUFBZSxpQkFBaUI7QUFFdEUsTUFBSSxNQUFNO0FBRVYsTUFBSSxTQUFTLE1BQU0sS0FBSyxNQUFNLEdBQUcsUUFBUSxJQUFJLE9BQUssS0FBSyxJQUFJLEdBQUcsTUFBTSxJQUFJLE9BQUssRUFBRSxHQUFHO0FBQ2xGLFdBQVMsSUFBSSxHQUFHLElBQUksTUFBTSxRQUFRLEtBQUs7QUFFbkMsUUFBSSxLQUFLO0FBQ0wsYUFBTyxNQUFNLEtBQUssTUFBTSxHQUFHLFFBQVEsSUFBSSxPQUFLLElBQUksT0FBTyxPQUFPLEtBQUssS0FBSyxTQUFTO0FBRXJGLFFBQUksTUFBZ0I7QUFDcEIsYUFBUyxJQUFJLEdBQUcsSUFBSSxHQUFHO0FBQ25CLFVBQUksS0FBSyxNQUFNLEdBQUcsR0FBRyxPQUFPLE9BQU8sSUFBSTtBQUMzQyxXQUFPLElBQUksS0FBSyxTQUFTO0FBQUE7QUFFN0IsU0FBTztBQUFBO0FBR1gsbUJBQW1CLFNBQWtCLFVBQTZDO0FBQzlFLE1BQUksTUFBTTtBQUNWLFdBQVMsU0FBUyxRQUFRO0FBQ3RCLFdBQU8sZUFBZSxPQUFPLFVBQVUsS0FBSyxTQUFTLGdCQUFnQjtBQUN6RSxTQUFPO0FBQUE7QUFHWCx3QkFBd0IsT0FBYyxVQUErQztBQUNqRixTQUFPO0FBQUEsSUFDSCxNQUFNO0FBQUEsSUFDTixnQkFBZ0IsTUFBTSxXQUFXO0FBQUEsSUFDakMsTUFBTSxVQUFVLGdCQUFnQixNQUFNLFNBQVMsWUFBWTtBQUFBLElBQzNELE1BQU0sVUFBVSxzQkFBc0IsTUFBTSxXQUFXLE1BQU0sV0FBVztBQUFBO0FBQUE7OztBSC9MaEYsNENBQXFELHdCQUFPO0FBQUEsRUFJckQsU0FBd0I7QUFBQTtBQUM3QixZQUFNLEtBQUs7QUFFWCxXQUFLLGNBQWMsSUFBSSw2QkFBNkIsS0FBSyxLQUFLO0FBRTlELFdBQUssbUNBQW1DLHVCQUF1QixDQUFDLEdBQUcsR0FBRyxNQUFNO0FBQzNFLFlBQUksVUFBVSxZQUFZO0FBQzFCLFVBQUU7QUFDRix1QkFBZSxTQUFTLEdBQUcsTUFBTSxFQUFFLGVBQWUsSUFBSSxLQUFLO0FBQUE7QUFHNUQsV0FBSyxXQUFXO0FBQUEsUUFDZixJQUFJO0FBQUEsUUFDSixNQUFNO0FBQUEsUUFDTixnQkFBZ0IsQ0FBQyxHQUFHLE1BQU07QUFDekIsWUFBRSxpQkFBaUI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS2hCLGVBQWU7QUFBQTtBQUNwQixXQUFLLFdBQVcsT0FBTyxPQUFPLElBQUksaUJBQWlCLE1BQU0sS0FBSztBQUFBO0FBQUE7QUFBQSxFQUd6RCxlQUFlO0FBQUE7QUFDcEIsWUFBTSxLQUFLLFNBQVMsS0FBSztBQUFBO0FBQUE7QUFBQTsiLAogICJuYW1lcyI6IFtdCn0K