ankit-kapur_obsidian-kanban.../main.js
2025-03-12 17:21:45 -07:00

544 lines
112 KiB
JavaScript

'use strict';
var obsidian = require('obsidian');
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
const DEFAULT_SETTINGS = {
statusPropertyName: 'status',
showNotifications: true,
debugMode: true
};
class KanbanStatusUpdaterPlugin extends obsidian.Plugin {
constructor() {
super(...arguments);
// Process flags to avoid infinite loops
this.processingMutation = false;
this.pendingCardUpdates = new Map();
this.mutationDebounceTimeout = null;
}
onload() {
return __awaiter(this, void 0, void 0, function* () {
yield this.loadSettings();
// Set up debug logging with rate limiting
let lastLogTime = Date.now();
let logCount = 0;
this.debugLog = (message) => {
if (this.settings.debugMode) {
// Rate limit logs to prevent console flooding
const now = Date.now();
if (now - lastLogTime > 5000) {
// Reset counter after 5 seconds
logCount = 0;
lastLogTime = now;
}
if (logCount < 50) { // Limit to 50 logs per 5 seconds
console.log(`[Kanban Status Updater] ${message}`);
logCount++;
if (this.statusBarItem) {
this.statusBarItem.setText(`[KSU] ${message.substring(0, 40)}${message.length > 40 ? '...' : ''}`);
// Reset after 5 seconds
setTimeout(() => {
if (this.statusBarItem) {
this.statusBarItem.setText('Kanban Status Updater Active');
}
}, 5000);
}
}
else if (logCount === 50) {
console.log(`[Kanban Status Updater] Too many logs, throttling until ${new Date(lastLogTime + 5000).toLocaleTimeString()}`);
logCount++;
}
}
};
// Display startup notification
new obsidian.Notice('Kanban Status Updater plugin activated');
this.debugLog('Plugin loaded and activated');
// Hook into DOM events to detect Kanban card movements
this.registerDomEvent(document, 'dragend', this.handleDragEnd.bind(this));
this.debugLog('Registered drag event listener');
// Register for mutation events to catch non-drag updates - with optimizations
const observer = new MutationObserver((mutations) => {
// Skip processing if we're already handling a mutation
if (this.processingMutation)
return;
// Debounce mutation processing to avoid too many updates
if (this.mutationDebounceTimeout) {
clearTimeout(this.mutationDebounceTimeout);
}
this.mutationDebounceTimeout = setTimeout(() => {
this.handleDOMMutations(mutations);
this.mutationDebounceTimeout = null;
}, 500); // Wait 500ms before processing
});
this.app.workspace.onLayoutReady(() => {
// Find Kanban board containers to observe more specifically
const kanbanBoards = document.querySelectorAll('.kanban-plugin__board');
if (kanbanBoards && kanbanBoards.length > 0) {
// Observe each Kanban board specifically rather than the entire document
kanbanBoards.forEach(board => {
observer.observe(board, {
childList: true,
subtree: true,
attributes: false // Don't need attribute changes, just structure
});
});
this.debugLog(`MutationObserver attached to ${kanbanBoards.length} Kanban boards`);
}
else {
// Fallback to a more targeted observation if no boards found
const workspace = document.querySelector('.workspace');
if (workspace) {
observer.observe(workspace, {
childList: true,
subtree: true,
attributes: false
});
this.debugLog('MutationObserver attached to workspace (no Kanban boards found yet)');
}
else {
// Last resort - observe body with more restrictions
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: false
});
this.debugLog('MutationObserver attached to document body (fallback mode)');
}
}
// Set up a periodic check for new Kanban boards (in case they're added later)
setInterval(() => {
const currentBoards = document.querySelectorAll('.kanban-plugin__board');
if (currentBoards && currentBoards.length > 0) {
currentBoards.forEach(board => {
if (!board.hasAttribute('data-ksu-observed')) {
observer.observe(board, {
childList: true,
subtree: true,
attributes: false
});
board.setAttribute('data-ksu-observed', 'true');
this.debugLog('Added observer to new Kanban board');
}
});
}
}, 10000); // Check every 10 seconds
});
// Add settings tab
this.addSettingTab(new KanbanStatusUpdaterSettingTab(this.app, this));
// Add a status bar item to show the plugin is active
this.statusBarItem = this.addStatusBarItem();
this.statusBarItem.setText('Kanban Status Updater Active');
this.statusBarItem.addClass('plugin-kanban-status-updater');
// Check if Kanban plugin is loaded - using safer approach
try {
// @ts-ignore - Check if kanban plugin exists using app.plugins (may not be in type definitions)
const kanbanLoaded = this.app.plugins &&
// @ts-ignore
((this.app.plugins.plugins && this.app.plugins.plugins['obsidian-kanban']) ||
// @ts-ignore
(this.app.plugins.enabledPlugins && this.app.plugins.enabledPlugins.has('obsidian-kanban')));
if (!kanbanLoaded) {
new obsidian.Notice('⚠️ Warning: Kanban plugin might not be enabled. Kanban Status Updater requires it.', 10000);
this.debugLog('WARNING: Kanban plugin not detected!');
}
else {
this.debugLog('Kanban plugin detected');
}
}
catch (e) {
// If we can't detect it, just log and continue
this.debugLog(`Couldn't verify Kanban plugin: ${e.message}`);
}
});
}
onunload() {
this.debugLog('Plugin unloaded');
new obsidian.Notice('Kanban Status Updater plugin deactivated');
}
loadSettings() {
return __awaiter(this, void 0, void 0, function* () {
this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
});
}
saveSettings() {
return __awaiter(this, void 0, void 0, function* () {
yield this.saveData(this.settings);
});
}
handleDragEnd(evt) {
// Check if this was a Kanban card being dragged
const target = evt.target;
if (!target) {
this.debugLog('Drag event had no target');
return;
}
this.debugLog(`Drag event detected on element: ${target.tagName}${target.className ? ' with class ' + target.className : ''}`);
const kanbanCard = target.closest('.kanban-card');
if (!kanbanCard) {
this.debugLog('Element is not or does not contain a Kanban card');
return;
}
this.debugLog('Kanban card found in drag event');
// Get the column the card was dropped in
const column = kanbanCard.closest('.kanban-column');
if (!column) {
this.debugLog('Could not find parent Kanban column');
return;
}
this.debugLog('Card was moved to a column, processing movement');
// Process the card movement
this.processCardMovement(kanbanCard, column);
}
handleDOMMutations(mutations) {
var _a;
if (this.processingMutation) {
this.debugLog('Already processing mutations, skipping');
return;
}
// Process only a sample of mutations if there are too many
const mutationsToProcess = mutations.length > 10 ?
mutations.slice(0, 10) : mutations;
this.debugLog(`Processing ${mutationsToProcess.length} mutations (of ${mutations.length} total)`);
// Set flag to prevent recursive processing
this.processingMutation = true;
this.debugLog(`HELLO`);
try {
// Clear the pending updates map
this.pendingCardUpdates.clear();
// Check for relevant mutations (card being added to a column)
for (const mutation of mutationsToProcess) {
if (mutation.type === 'childList') {
// Only log if there are actually Kanban-related nodes
let foundKanbanElements = false;
this.debugLog(`mutation.type === 'childList'`);
for (const node of Array.from(mutation.addedNodes)) {
if (node instanceof HTMLElement) {
// Check if this is or contains Kanban card elements
const isKanbanElement = node.classList.contains('kanban-card') ||
node.classList.contains('kanban-column') ||
node.querySelector('.kanban-card') !== null;
this.debugLog(`isKanbanElement: ${isKanbanElement}`);
this.debugLog(`node.classList: ${node.classList}`);
this.debugLog(`node.tagName: ${node.tagName}`);
this.debugLog(`node.className: ${node.className}`);
if (isKanbanElement) {
foundKanbanElements = true;
// Only now log details
this.debugLog(`Relevant mutation: ${node.tagName}${node.className ? ' with class ' + node.className : ''}`);
// Look for Kanban cards
const kanbanCards = node.classList.contains('kanban-card')
? [node]
: Array.from(node.querySelectorAll('.kanban-card'));
for (const card of kanbanCards) {
const column = card.closest('.kanban-column');
if (column) {
// Create a unique ID for this card to avoid duplicates
const cardText = (_a = card.textContent) === null || _a === void 0 ? void 0 : _a.trim();
const cardId = (cardText === null || cardText === void 0 ? void 0 : cardText.substring(0, 50)) || card.id || 'unknown';
this.debugLog(`Added card to pendingCardUpdates: ${cardText}`);
this.debugLog(`Column: ${column.textContent}`);
// Add to pending updates map, this way if same card appears in multiple
// mutations, we only process the last one
this.pendingCardUpdates.set(cardId, {
card: card,
column: column
});
this.debugLog(`Queued card update: ${cardId.substring(0, 20)}...`);
}
}
}
}
}
// Only log for mutations with Kanban elements
if (foundKanbanElements) {
this.debugLog(`Processed mutation with ${mutation.addedNodes.length} nodes`);
}
}
}
// Process all pending updates
if (this.pendingCardUpdates.size > 0) {
this.debugLog(`Processing ${this.pendingCardUpdates.size} card updates`);
// Process each card update (with a slight delay between them to avoid overloading)
let index = 0;
for (const [cardId, { card, column }] of this.pendingCardUpdates.entries()) {
// Stagger processing to avoid too much at once
setTimeout(() => {
this.processCardMovement(card, column);
}, index * 100); // 100ms between each card
index++;
}
}
}
catch (e) {
this.debugLog(`Error processing mutations: ${e.message}`);
}
finally {
// Clear the flag when done
setTimeout(() => {
this.processingMutation = false;
this.debugLog('Mutation processing complete');
}, 1000); // Ensure a minimum cool-down period between mutation processing
}
}
processCardMovement(card, column) {
// Get the column name (new status)
const headerElement = column.querySelector('.kanban-column-header');
if (!headerElement) {
this.debugLog('Could not find column header element');
return;
}
const newStatus = headerElement.textContent.trim();
this.debugLog(`Column name (new status): "${newStatus}"`);
// Get the card content and look for the first link
const cardContentElement = card.querySelector('.kanban-card-text, .kanban-card-content');
if (!cardContentElement) {
this.debugLog('Could not find card content element');
return;
}
const cardContent = cardContentElement.textContent;
this.debugLog(`Card content: "${cardContent.substring(0, 50)}${cardContent.length > 50 ? '...' : ''}"`);
// Look for wiki-links [[Link]] or [[Link|Display Text]]
const linkMatch = cardContent.match(/\[\[(.*?)(?:\|.*?)?\]\]/);
if (!linkMatch || !linkMatch[1]) {
this.debugLog(`No link found in card: ${cardContent}`);
new obsidian.Notice('⚠️ No link found in Kanban card', 3000);
return;
}
const linkPath = linkMatch[1].trim();
this.debugLog(`Found link to: "${linkPath}"`);
// Show visual confirmation that we're updating
new obsidian.Notice(`Updating ${this.settings.statusPropertyName} to "${newStatus}" for "${linkPath}"...`, 2000);
this.updateLinkedNoteStatus(linkPath, newStatus);
}
updateLinkedNoteStatus(linkPath, newStatus) {
return __awaiter(this, void 0, void 0, function* () {
// Find the linked file
const file = this.app.metadataCache.getFirstLinkpathDest(linkPath, '');
if (!file) {
this.debugLog(`Linked file not found: ${linkPath}`);
new obsidian.Notice(`⚠️ Error: File "${linkPath}" not found`, 5000);
return;
}
this.debugLog(`Found linked file: ${file.path}`);
try {
// Read the file content
const content = yield this.app.vault.read(file);
this.debugLog(`File content loaded (${content.length} chars)`);
// Check if the file has frontmatter
const frontmatterRegex = /^---\n([\s\S]*?)\n---/;
const frontmatterMatch = content.match(frontmatterRegex);
let newContent;
let oldStatus = 'none';
let action = 'created';
if (frontmatterMatch) {
this.debugLog('File has frontmatter');
// File has frontmatter
const frontmatterText = frontmatterMatch[1];
let frontmatterObj;
try {
// Try to parse the frontmatter
frontmatterObj = obsidian.parseYaml(frontmatterText);
this.debugLog('Frontmatter parsed successfully');
// Check if status property already exists
if (frontmatterObj[this.settings.statusPropertyName]) {
oldStatus = frontmatterObj[this.settings.statusPropertyName];
action = 'updated';
}
}
catch (e) {
this.debugLog(`Error parsing frontmatter: ${e.message}`);
new obsidian.Notice(`⚠️ Warning: Invalid frontmatter in ${file.basename}, creating new frontmatter`, 5000);
frontmatterObj = {};
}
// Update the status property
frontmatterObj[this.settings.statusPropertyName] = newStatus;
// Generate the new frontmatter text
const newFrontmatterText = obsidian.stringifyYaml(frontmatterObj);
this.debugLog('New frontmatter generated');
// Replace the frontmatter in the content
newContent = content.replace(frontmatterRegex, `---\n${newFrontmatterText}---`);
}
else {
this.debugLog('File has no frontmatter, creating new frontmatter');
// File has no frontmatter, create it
const frontmatterObj = {
[this.settings.statusPropertyName]: newStatus
};
const frontmatterText = obsidian.stringifyYaml(frontmatterObj);
newContent = `---\n${frontmatterText}---\n\n${content}`;
}
// Save the modified content
yield this.app.vault.modify(file, newContent);
this.debugLog('File modified successfully');
// Show notification with more details
const banner = createFragment(el => {
el.createDiv({
text: `${this.settings.statusPropertyName} ${action}:`,
cls: 'status-updated-banner-title'
});
el.createDiv({
cls: 'status-updated-banner-details'
}, div => {
div.createSpan({ text: 'File: ' });
div.createSpan({
text: file.basename,
cls: 'status-updated-filename'
});
div.createEl('br');
if (action === 'updated') {
div.createSpan({ text: 'Changed from: ' });
div.createSpan({
text: `"${oldStatus}"`,
cls: 'status-updated-old-value'
});
div.createEl('br');
}
div.createSpan({ text: 'New value: ' });
div.createSpan({
text: `"${newStatus}"`,
cls: 'status-updated-new-value'
});
});
});
// Always show the detailed banner
new obsidian.Notice(banner, 5000);
// Update status bar
this.statusBarItem.setText(`Updated: ${file.basename}${newStatus}`);
setTimeout(() => {
this.statusBarItem.setText('Kanban Status Updater Active');
}, 5000);
this.debugLog(`Success: ${this.settings.statusPropertyName} for ${file.basename} ${action} from "${oldStatus}" to "${newStatus}"`);
}
catch (error) {
this.debugLog(`Error updating note status: ${error.message}`);
new obsidian.Notice(`⚠️ Error updating ${this.settings.statusPropertyName} for ${file.basename}: ${error.message}`, 10000);
}
});
}
}
// Settings Tab
class KanbanStatusUpdaterSettingTab extends obsidian.PluginSettingTab {
constructor(app, plugin) {
super(app, plugin);
this.plugin = plugin;
}
display() {
const { containerEl } = this;
containerEl.empty();
containerEl.createEl('h2', { text: 'Kanban Status Updater Settings' });
new obsidian.Setting(containerEl)
.setName('Status Property Name')
.setDesc('The name of the property to update when a card is moved')
.addText(text => text
.setPlaceholder('status')
.setValue(this.plugin.settings.statusPropertyName)
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.statusPropertyName = value;
yield this.plugin.saveSettings();
})));
new obsidian.Setting(containerEl)
.setName('Show Notifications')
.setDesc('Show a notification when a status is updated')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.showNotifications)
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.showNotifications = value;
yield this.plugin.saveSettings();
})));
new obsidian.Setting(containerEl)
.setName('Debug Mode')
.setDesc('Enable detailed logging to console and status bar updates')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.debugMode)
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.debugMode = value;
yield this.plugin.saveSettings();
new obsidian.Notice(`Debug mode ${value ? 'enabled' : 'disabled'}`);
})));
// Add a button to trigger a test update
new obsidian.Setting(containerEl)
.setName('Test Plugin')
.setDesc('Run a test to verify plugin functionality')
.addButton(button => button
.setButtonText('Run Test')
.onClick(() => {
new obsidian.Notice('Test function running - check console for logs');
this.plugin.debugLog('Test function triggered from settings');
// Show an example of what a successful update would look like
const banner = createFragment(el => {
el.createDiv({
text: `${this.plugin.settings.statusPropertyName} updated:`,
cls: 'status-updated-banner-title'
});
el.createDiv({
cls: 'status-updated-banner-details'
}, div => {
div.createSpan({ text: 'File: ' });
div.createSpan({
text: 'Example Note',
cls: 'status-updated-filename'
});
div.createEl('br');
div.createSpan({ text: 'Changed from: ' });
div.createSpan({
text: '"In Progress"',
cls: 'status-updated-old-value'
});
div.createEl('br');
div.createSpan({ text: 'New value: ' });
div.createSpan({
text: '"Completed"',
cls: 'status-updated-new-value'
});
});
});
new obsidian.Notice(banner, 5000);
}));
containerEl.createEl('h3', { text: 'Troubleshooting' });
containerEl.createEl('p', {
text: 'If the plugin is not working, check the following:'
});
const troubleshootingList = containerEl.createEl('ul');
troubleshootingList.createEl('li', {
text: 'Ensure the Kanban plugin is installed and enabled'
});
troubleshootingList.createEl('li', {
text: 'Verify your Kanban cards contain wiki-links (e.g., [[Note Title]])'
});
troubleshootingList.createEl('li', {
text: 'Try enabling Debug Mode to see detailed logs in the developer console (Ctrl+Shift+I)'
});
}
}
module.exports = KanbanStatusUpdaterPlugin;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsIm1haW4udHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlLCBTdXBwcmVzc2VkRXJyb3IsIFN5bWJvbCwgSXRlcmF0b3IgKi9cclxuXHJcbnZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24oZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcclxuICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXHJcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xyXG4gICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxuICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxyXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fYXNzaWduID0gZnVuY3Rpb24oKSB7XHJcbiAgICBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gX19hc3NpZ24odCkge1xyXG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xyXG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xyXG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpIHRbcF0gPSBzW3BdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdDtcclxuICAgIH1cclxuICAgIHJldHVybiBfX2Fzc2lnbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZXN0KHMsIGUpIHtcclxuICAgIHZhciB0ID0ge307XHJcbiAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkgJiYgZS5pbmRleE9mKHApIDwgMClcclxuICAgICAgICB0W3BdID0gc1twXTtcclxuICAgIGlmIChzICE9IG51bGwgJiYgdHlwZW9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPT09IFwiZnVuY3Rpb25cIilcclxuICAgICAgICBmb3IgKHZhciBpID0gMCwgcCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocyk7IGkgPCBwLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmIChlLmluZGV4T2YocFtpXSkgPCAwICYmIE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChzLCBwW2ldKSlcclxuICAgICAgICAgICAgICAgIHRbcFtpXV0gPSBzW3BbaV1dO1xyXG4gICAgICAgIH1cclxuICAgIHJldHVybiB0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xyXG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XHJcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xyXG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcGFyYW0ocGFyYW1JbmRleCwgZGVjb3JhdG9yKSB7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXNEZWNvcmF0ZShjdG9yLCBkZXNjcmlwdG9ySW4sIGRlY29yYXRvcnMsIGNvbnRleHRJbiwgaW5pdGlhbGl6ZXJzLCBleHRyYUluaXRpYWxpemVycykge1xyXG4gICAgZnVuY3Rpb24gYWNjZXB0KGYpIHsgaWYgKGYgIT09IHZvaWQgMCAmJiB0eXBlb2YgZiAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiRnVuY3Rpb24gZXhwZWN0ZWRcIik7IHJldHVybiBmOyB9XHJcbiAgICB2YXIga2luZCA9IGNvbnRleHRJbi5raW5kLCBrZXkgPSBraW5kID09PSBcImdldHRlclwiID8gXCJnZXRcIiA6IGtpbmQgPT09IFwic2V0dGVyXCIgPyBcInNldFwiIDogXCJ2YWx1ZVwiO1xyXG4gICAgdmFyIHRhcmdldCA9ICFkZXNjcmlwdG9ySW4gJiYgY3RvciA/IGNvbnRleHRJbltcInN0YXRpY1wiXSA/IGN0b3IgOiBjdG9yLnByb3RvdHlwZSA6IG51bGw7XHJcbiAgICB2YXIgZGVzY3JpcHRvciA9IGRlc2NyaXB0b3JJbiB8fCAodGFyZ2V0ID8gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGNvbnRleHRJbi5uYW1lKSA6IHt9KTtcclxuICAgIHZhciBfLCBkb25lID0gZmFsc2U7XHJcbiAgICBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xyXG4gICAgICAgIHZhciBjb250ZXh0ID0ge307XHJcbiAgICAgICAgZm9yICh2YXIgcCBpbiBjb250ZXh0SW4pIGNvbnRleHRbcF0gPSBwID09PSBcImFjY2Vzc1wiID8ge30gOiBjb250ZXh0SW5bcF07XHJcbiAgICAgICAgZm9yICh2YXIgcCBpbiBjb250ZXh0SW4uYWNjZXNzKSBjb250ZXh0LmFjY2Vzc1twXSA9IGNvbnRleHRJbi5hY2Nlc3NbcF07XHJcbiAgICAgICAgY29udGV4dC5hZGRJbml0aWFsaXplciA9IGZ1bmN0aW9uIChmKSB7IGlmIChkb25lKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGFkZCBpbml0aWFsaXplcnMgYWZ0ZXIgZGVjb3JhdGlvbiBoYXMgY29tcGxldGVkXCIpOyBleHRyYUluaXRpYWxpemVycy5wdXNoKGFjY2VwdChmIHx8IG51bGwpKTsgfTtcclxuICAgICAgICB2YXIgcmVzdWx0ID0gKDAsIGRlY29yYXRvcnNbaV0pKGtpbmQgPT09IFwiYWNjZXNzb3JcIiA/IHsgZ2V0OiBkZXNjcmlwdG9yLmdldCwgc2V0OiBkZXNjcmlwdG9yLnNldCB9IDogZGVzY3JpcHRvcltrZXldLCBjb250ZXh0KTtcclxuICAgICAgICBpZiAoa2luZCA9PT0gXCJhY2Nlc3NvclwiKSB7XHJcbiAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IHZvaWQgMCkgY29udGludWU7XHJcbiAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IG51bGwgfHwgdHlwZW9mIHJlc3VsdCAhPT0gXCJvYmplY3RcIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk9iamVjdCBleHBlY3RlZFwiKTtcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LmdldCkpIGRlc2NyaXB0b3IuZ2V0ID0gXztcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LnNldCkpIGRlc2NyaXB0b3Iuc2V0ID0gXztcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LmluaXQpKSBpbml0aWFsaXplcnMudW5zaGlmdChfKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAoXyA9IGFjY2VwdChyZXN1bHQpKSB7XHJcbiAgICAgICAgICAgIGlmIChraW5kID09PSBcImZpZWxkXCIpIGluaXRpYWxpemVycy51bnNoaWZ0KF8pO1xyXG4gICAgICAgICAgICBlbHNlIGRlc2NyaXB0b3Jba2V5XSA9IF87XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKHRhcmdldCkgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgY29udGV4dEluLm5hbWUsIGRlc2NyaXB0b3IpO1xyXG4gICAgZG9uZSA9IHRydWU7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19ydW5Jbml0aWFsaXplcnModGhpc0FyZywgaW5pdGlhbGl6ZXJzLCB2YWx1ZSkge1xyXG4gICAgdmFyIHVzZVZhbHVlID0gYXJndW1lbnRzLmxlbmd0aCA+IDI7XHJcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluaXRpYWxpemVycy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIHZhbHVlID0gdXNlVmFsdWUgPyBpbml0aWFsaXplcnNbaV0uY2FsbCh0aGlzQXJnLCB2YWx1ZSkgOiBpbml0aWFsaXplcnNbaV0uY2FsbCh0aGlzQXJnKTtcclxuICAgIH1cclxuICAgIHJldHVybiB1c2VWYWx1ZSA/IHZhbHVlIDogdm9pZCAwO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcHJvcEtleSh4KSB7XHJcbiAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3ltYm9sXCIgPyB4IDogXCJcIi5jb25jYXQoeCk7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19zZXRGdW5jdGlvbk5hbWUoZiwgbmFtZSwgcHJlZml4KSB7XHJcbiAgICBpZiAodHlwZW9mIG5hbWUgPT09IFwic3ltYm9sXCIpIG5hbWUgPSBuYW1lLmRlc2NyaXB0aW9uID8gXCJbXCIuY29uY2F0KG5hbWUuZGVzY3JpcHRpb24sIFwiXVwiKSA6IFwiXCI7XHJcbiAgICByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KGYsIFwibmFtZVwiLCB7IGNvbmZpZ3VyYWJsZTogdHJ1ZSwgdmFsdWU6IHByZWZpeCA/IFwiXCIuY29uY2F0KHByZWZpeCwgXCIgXCIsIG5hbWUpIDogbmFtZSB9KTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKSB7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QubWV0YWRhdGEgPT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIFJlZmxlY3QubWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdGVyKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xyXG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XHJcbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cclxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZ2VuZXJhdG9yKHRoaXNBcmcsIGJvZHkpIHtcclxuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGcgPSBPYmplY3QuY3JlYXRlKCh0eXBlb2YgSXRlcmF0b3IgPT09IFwiZnVuY3Rpb25cIiA/IEl0ZXJhdG9yIDogT2JqZWN0KS5wcm90b3R5cGUpO1xyXG4gICAgcmV0dXJuIGcubmV4dCA9IHZlcmIoMCksIGdbXCJ0aHJvd1wiXSA9IHZlcmIoMSksIGdbXCJyZXR1cm5cIl0gPSB2ZXJiKDIpLCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcclxuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XHJcbiAgICAgICAgd2hpbGUgKGcgJiYgKGcgPSAwLCBvcFswXSAmJiAoXyA9IDApKSwgXykgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xyXG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XHJcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxyXG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fY3JlYXRlQmluZGluZyA9IE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcclxuICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XHJcbiAgICB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobSwgayk7XHJcbiAgICBpZiAoIWRlc2MgfHwgKFwiZ2V0XCIgaW4gZGVzYyA/ICFtLl9fZXNNb2R1bGUgOiBkZXNjLndyaXRhYmxlIHx8IGRlc2MuY29uZmlndXJhYmxlKSkge1xyXG4gICAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XHJcbiAgICB9XHJcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgazIsIGRlc2MpO1xyXG59KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xyXG4gICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcclxuICAgIG9bazJdID0gbVtrXTtcclxufSk7XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHBvcnRTdGFyKG0sIG8pIHtcclxuICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKHAgIT09IFwiZGVmYXVsdFwiICYmICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobywgcCkpIF9fY3JlYXRlQmluZGluZyhvLCBtLCBwKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fdmFsdWVzKG8pIHtcclxuICAgIHZhciBzID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIFN5bWJvbC5pdGVyYXRvciwgbSA9IHMgJiYgb1tzXSwgaSA9IDA7XHJcbiAgICBpZiAobSkgcmV0dXJuIG0uY2FsbChvKTtcclxuICAgIGlmIChvICYmIHR5cGVvZiBvLmxlbmd0aCA9PT0gXCJudW1iZXJcIikgcmV0dXJuIHtcclxuICAgICAgICBuZXh0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmIChvICYmIGkgPj0gby5sZW5ndGgpIG8gPSB2b2lkIDA7XHJcbiAgICAgICAgICAgIHJldHVybiB7IHZhbHVlOiBvICYmIG9baSsrXSwgZG9uZTogIW8gfTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihzID8gXCJPYmplY3QgaXMgbm90IGl0ZXJhYmxlLlwiIDogXCJTeW1ib2wuaXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZWFkKG8sIG4pIHtcclxuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcclxuICAgIGlmICghbSkgcmV0dXJuIG87XHJcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcclxuICAgIHRyeSB7XHJcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XHJcbiAgICB9XHJcbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cclxuICAgIGZpbmFsbHkge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cclxuICAgIH1cclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuLyoqIEBkZXByZWNhdGVkICovXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZCgpIHtcclxuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKVxyXG4gICAgICAgIGFyID0gYXIuY29uY2F0KF9fcmVhZChhcmd1bWVudHNbaV0pKTtcclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuLyoqIEBkZXByZWNhdGVkICovXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZEFycmF5cygpIHtcclxuICAgIGZvciAodmFyIHMgPSAwLCBpID0gMCwgaWwgPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgaWw7IGkrKykgcyArPSBhcmd1bWVudHNbaV0ubGVuZ3RoO1xyXG4gICAgZm9yICh2YXIgciA9IEFycmF5KHMpLCBrID0gMCwgaSA9IDA7IGkgPCBpbDsgaSsrKVxyXG4gICAgICAgIGZvciAodmFyIGEgPSBhcmd1bWVudHNbaV0sIGogPSAwLCBqbCA9IGEubGVuZ3RoOyBqIDwgamw7IGorKywgaysrKVxyXG4gICAgICAgICAgICByW2tdID0gYVtqXTtcclxuICAgIHJldHVybiByO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19zcHJlYWRBcnJheSh0bywgZnJvbSwgcGFjaykge1xyXG4gICAgaWYgKHBhY2sgfHwgYXJndW1lbnRzLmxlbmd0aCA9PT0gMikgZm9yICh2YXIgaSA9IDAsIGwgPSBmcm9tLmxlbmd0aCwgYXI7IGkgPCBsOyBpKyspIHtcclxuICAgICAgICBpZiAoYXIgfHwgIShpIGluIGZyb20pKSB7XHJcbiAgICAgICAgICAgIGlmICghYXIpIGFyID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZnJvbSwgMCwgaSk7XHJcbiAgICAgICAgICAgIGFyW2ldID0gZnJvbVtpXTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdG8uY29uY2F0KGFyIHx8IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGZyb20pKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXQodikge1xyXG4gICAgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBfX2F3YWl0ID8gKHRoaXMudiA9IHYsIHRoaXMpIDogbmV3IF9fYXdhaXQodik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jR2VuZXJhdG9yKHRoaXNBcmcsIF9hcmd1bWVudHMsIGdlbmVyYXRvcikge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBnID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pLCBpLCBxID0gW107XHJcbiAgICByZXR1cm4gaSA9IE9iamVjdC5jcmVhdGUoKHR5cGVvZiBBc3luY0l0ZXJhdG9yID09PSBcImZ1bmN0aW9uXCIgPyBBc3luY0l0ZXJhdG9yIDogT2JqZWN0KS5wcm90b3R5cGUpLCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIsIGF3YWl0UmV0dXJuKSwgaVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpO1xyXG4gICAgZnVuY3Rpb24gYXdhaXRSZXR1cm4oZikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh2KS50aGVuKGYsIHJlamVjdCk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHZlcmIobiwgZikgeyBpZiAoZ1tuXSkgeyBpW25dID0gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChhLCBiKSB7IHEucHVzaChbbiwgdiwgYSwgYl0pID4gMSB8fCByZXN1bWUobiwgdik7IH0pOyB9OyBpZiAoZikgaVtuXSA9IGYoaVtuXSk7IH0gfVxyXG4gICAgZnVuY3Rpb24gcmVzdW1lKG4sIHYpIHsgdHJ5IHsgc3RlcChnW25dKHYpKTsgfSBjYXRjaCAoZSkgeyBzZXR0bGUocVswXVszXSwgZSk7IH0gfVxyXG4gICAgZnVuY3Rpb24gc3RlcChyKSB7IHIudmFsdWUgaW5zdGFuY2VvZiBfX2F3YWl0ID8gUHJvbWlzZS5yZXNvbHZlKHIudmFsdWUudikudGhlbihmdWxmaWxsLCByZWplY3QpIDogc2V0dGxlKHFbMF1bMl0sIHIpOyB9XHJcbiAgICBmdW5jdGlvbiBmdWxmaWxsKHZhbHVlKSB7IHJlc3VtZShcIm5leHRcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiByZWplY3QodmFsdWUpIHsgcmVzdW1lKFwidGhyb3dcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUoZiwgdikgeyBpZiAoZih2KSwgcS5zaGlmdCgpLCBxLmxlbmd0aCkgcmVzdW1lKHFbMF1bMF0sIHFbMF1bMV0pOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jRGVsZWdhdG9yKG8pIHtcclxuICAgIHZhciBpLCBwO1xyXG4gICAgcmV0dXJuIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiLCBmdW5jdGlvbiAoZSkgeyB0aHJvdyBlOyB9KSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobiwgZikgeyBpW25dID0gb1tuXSA/IGZ1bmN0aW9uICh2KSB7IHJldHVybiAocCA9ICFwKSA/IHsgdmFsdWU6IF9fYXdhaXQob1tuXSh2KSksIGRvbmU6IGZhbHNlIH0gOiBmID8gZih2KSA6IHY7IH0gOiBmOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jVmFsdWVzKG8pIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICB2YXIgbSA9IG9bU3ltYm9sLmFzeW5jSXRlcmF0b3JdLCBpO1xyXG4gICAgcmV0dXJuIG0gPyBtLmNhbGwobykgOiAobyA9IHR5cGVvZiBfX3ZhbHVlcyA9PT0gXCJmdW5jdGlvblwiID8gX192YWx1ZXMobykgOiBvW1N5bWJvbC5pdGVyYXRvcl0oKSwgaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGkpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IGlbbl0gPSBvW25dICYmIGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7IHYgPSBvW25dKHYpLCBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCB2LmRvbmUsIHYudmFsdWUpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgZCwgdikgeyBQcm9taXNlLnJlc29sdmUodikudGhlbihmdW5jdGlvbih2KSB7IHJlc29sdmUoeyB2YWx1ZTogdiwgZG9uZTogZCB9KTsgfSwgcmVqZWN0KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tYWtlVGVtcGxhdGVPYmplY3QoY29va2VkLCByYXcpIHtcclxuICAgIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIHsgT2JqZWN0LmRlZmluZVByb3BlcnR5KGNvb2tlZCwgXCJyYXdcIiwgeyB2YWx1ZTogcmF3IH0pOyB9IGVsc2UgeyBjb29rZWQucmF3ID0gcmF3OyB9XHJcbiAgICByZXR1cm4gY29va2VkO1xyXG59O1xyXG5cclxudmFyIF9fc2V0TW9kdWxlRGVmYXVsdCA9IE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgdikge1xyXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIFwiZGVmYXVsdFwiLCB7IGVudW1lcmFibGU6IHRydWUsIHZhbHVlOiB2IH0pO1xyXG59KSA6IGZ1bmN0aW9uKG8sIHYpIHtcclxuICAgIG9bXCJkZWZhdWx0XCJdID0gdjtcclxufTtcclxuXHJcbnZhciBvd25LZXlzID0gZnVuY3Rpb24obykge1xyXG4gICAgb3duS2V5cyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzIHx8IGZ1bmN0aW9uIChvKSB7XHJcbiAgICAgICAgdmFyIGFyID0gW107XHJcbiAgICAgICAgZm9yICh2YXIgayBpbiBvKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG8sIGspKSBhclthci5sZW5ndGhdID0gaztcclxuICAgICAgICByZXR1cm4gYXI7XHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIG93bktleXMobyk7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnRTdGFyKG1vZCkge1xyXG4gICAgaWYgKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgcmV0dXJuIG1vZDtcclxuICAgIHZhciByZXN1bHQgPSB7fTtcclxuICAgIGlmIChtb2QgIT0gbnVsbCkgZm9yICh2YXIgayA9IG93bktleXMobW9kKSwgaSA9IDA7IGkgPCBrLmxlbmd0aDsgaSsrKSBpZiAoa1tpXSAhPT0gXCJkZWZhdWx0XCIpIF9fY3JlYXRlQmluZGluZyhyZXN1bHQsIG1vZCwga1tpXSk7XHJcbiAgICBfX3NldE1vZHVsZURlZmF1bHQocmVzdWx0LCBtb2QpO1xyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9faW1wb3J0RGVmYXVsdChtb2QpIHtcclxuICAgIHJldHVybiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSA/IG1vZCA6IHsgZGVmYXVsdDogbW9kIH07XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xyXG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xyXG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XHJcbiAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19jbGFzc1ByaXZhdGVGaWVsZFNldChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmKSB7XHJcbiAgICBpZiAoa2luZCA9PT0gXCJtXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIG1ldGhvZCBpcyBub3Qgd3JpdGFibGVcIik7XHJcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBzZXR0ZXJcIik7XHJcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xyXG4gICAgcmV0dXJuIChraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlciwgdmFsdWUpIDogZiA/IGYudmFsdWUgPSB2YWx1ZSA6IHN0YXRlLnNldChyZWNlaXZlciwgdmFsdWUpKSwgdmFsdWU7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2NsYXNzUHJpdmF0ZUZpZWxkSW4oc3RhdGUsIHJlY2VpdmVyKSB7XHJcbiAgICBpZiAocmVjZWl2ZXIgPT09IG51bGwgfHwgKHR5cGVvZiByZWNlaXZlciAhPT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgcmVjZWl2ZXIgIT09IFwiZnVuY3Rpb25cIikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgdXNlICdpbicgb3BlcmF0b3Igb24gbm9uLW9iamVjdFwiKTtcclxuICAgIHJldHVybiB0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyID09PSBzdGF0ZSA6IHN0YXRlLmhhcyhyZWNlaXZlcik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FkZERpc3Bvc2FibGVSZXNvdXJjZShlbnYsIHZhbHVlLCBhc3luYykge1xyXG4gICAgaWYgKHZhbHVlICE9PSBudWxsICYmIHZhbHVlICE9PSB2b2lkIDApIHtcclxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSBcIm9iamVjdFwiICYmIHR5cGVvZiB2YWx1ZSAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiT2JqZWN0IGV4cGVjdGVkLlwiKTtcclxuICAgICAgICB2YXIgZGlzcG9zZSwgaW5uZXI7XHJcbiAgICAgICAgaWYgKGFzeW5jKSB7XHJcbiAgICAgICAgICAgIGlmICghU3ltYm9sLmFzeW5jRGlzcG9zZSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0Rpc3Bvc2UgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgICAgICAgICBkaXNwb3NlID0gdmFsdWVbU3ltYm9sLmFzeW5jRGlzcG9zZV07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChkaXNwb3NlID09PSB2b2lkIDApIHtcclxuICAgICAgICAgICAgaWYgKCFTeW1ib2wuZGlzcG9zZSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5kaXNwb3NlIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgICAgICAgICAgZGlzcG9zZSA9IHZhbHVlW1N5bWJvbC5kaXNwb3NlXTtcclxuICAgICAgICAgICAgaWYgKGFzeW5jKSBpbm5lciA9IGRpc3Bvc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICh0eXBlb2YgZGlzcG9zZSAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiT2JqZWN0IG5vdCBkaXNwb3NhYmxlLlwiKTtcclxuICAgICAgICBpZiAoaW5uZXIpIGRpc3Bvc2UgPSBmdW5jdGlvbigpIHsgdHJ5IHsgaW5uZXIuY2FsbCh0aGlzKTsgfSBjYXRjaCAoZSkgeyByZXR1cm4gUHJvbWlzZS5yZWplY3QoZSk7IH0gfTtcclxuICAgICAgICBlbnYuc3RhY2sucHVzaCh7IHZhbHVlOiB2YWx1ZSwgZGlzcG9zZTogZGlzcG9zZSwgYXN5bmM6IGFzeW5jIH0pO1xyXG4gICAgfVxyXG4gICAgZWxzZSBpZiAoYXN5bmMpIHtcclxuICAgICAgICBlbnYuc3RhY2sucHVzaCh7IGFzeW5jOiB0cnVlIH0pO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHZhbHVlO1xyXG5cclxufVxyXG5cclxudmFyIF9TdXBwcmVzc2VkRXJyb3IgPSB0eXBlb2YgU3VwcHJlc3NlZEVycm9yID09PSBcImZ1bmN0aW9uXCIgPyBTdXBwcmVzc2VkRXJyb3IgOiBmdW5jdGlvbiAoZXJyb3IsIHN1cHByZXNzZWQsIG1lc3NhZ2UpIHtcclxuICAgIHZhciBlID0gbmV3IEVycm9yKG1lc3NhZ2UpO1xyXG4gICAgcmV0dXJuIGUubmFtZSA9IFwiU3VwcHJlc3NlZEVycm9yXCIsIGUuZXJyb3IgPSBlcnJvciwgZS5zdXBwcmVzc2VkID0gc3VwcHJlc3NlZCwgZTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2Rpc3Bvc2VSZXNvdXJjZXMoZW52KSB7XHJcbiAgICBmdW5jdGlvbiBmYWlsKGUpIHtcclxuICAgICAgICBlbnYuZXJyb3IgPSBlbnYuaGFzRXJyb3IgPyBuZXcgX1N1cHByZXNzZWRFcnJvcihlLCBlbnYuZXJyb3IsIFwiQW4gZXJyb3Igd2FzIHN1cHByZXNzZWQgZHVyaW5nIGRpc3Bvc2FsLlwiKSA6IGU7XHJcbiAgICAgICAgZW52Lmhhc0Vycm9yID0gdHJ1ZTtcclxuICAgIH1cclxuICAgIHZhciByLCBzID0gMDtcclxuICAgIGZ1bmN0aW9uIG5leHQoKSB7XHJcbiAgICAgICAgd2hpbGUgKHIgPSBlbnYuc3RhY2sucG9wKCkpIHtcclxuICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgIGlmICghci5hc3luYyAmJiBzID09PSAxKSByZXR1cm4gcyA9IDAsIGVudi5zdGFjay5wdXNoKHIpLCBQcm9taXNlLnJlc29sdmUoKS50aGVuKG5leHQpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHIuZGlzcG9zZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSByLmRpc3Bvc2UuY2FsbChyLnZhbHVlKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoci5hc3luYykgcmV0dXJuIHMgfD0gMiwgUHJvbWlzZS5yZXNvbHZlKHJlc3VsdCkudGhlbihuZXh0LCBmdW5jdGlvbihlKSB7IGZhaWwoZSk7IHJldHVybiBuZXh0KCk7IH0pO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZWxzZSBzIHw9IDE7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgIGZhaWwoZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHMgPT09IDEpIHJldHVybiBlbnYuaGFzRXJyb3IgPyBQcm9taXNlLnJlamVjdChlbnYuZXJyb3IpIDogUHJvbWlzZS5yZXNvbHZlKCk7XHJcbiAgICAgICAgaWYgKGVudi5oYXNFcnJvcikgdGhyb3cgZW52LmVycm9yO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG5leHQoKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmV3cml0ZVJlbGF0aXZlSW1wb3J0RXh0ZW5zaW9uKHBhdGgsIHByZXNlcnZlSnN4KSB7XHJcbiAgICBpZiAodHlwZW9mIHBhdGggPT09IFwic3RyaW5nXCIgJiYgL15cXC5cXC4/XFwvLy50ZXN0KHBhdGgpKSB7XHJcbiAgICAgICAgcmV0dXJuIHBhdGgucmVwbGFjZSgvXFwuKHRzeCkkfCgoPzpcXC5kKT8pKCg/OlxcLlteLi9dKz8pPylcXC4oW2NtXT8pdHMkL2ksIGZ1bmN0aW9uIChtLCB0c3gsIGQsIGV4dCwgY20pIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRzeCA/IHByZXNlcnZlSnN4ID8gXCIuanN4XCIgOiBcIi5qc1wiIDogZCAmJiAoIWV4dCB8fCAhY20pID8gbSA6IChkICsgZXh0ICsgXCIuXCIgKyBjbS50b0xvd2VyQ2FzZSgpICsgXCJqc1wiKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuICAgIHJldHVybiBwYXRoO1xyXG59XHJcblxyXG5leHBvcnQgZGVmYXVsdCB7XHJcbiAgICBfX2V4dGVuZHM6IF9fZXh0ZW5kcyxcclxuICAgIF9fYXNzaWduOiBfX2Fzc2lnbixcclxuICAgIF9fcmVzdDogX19yZXN0LFxyXG4gICAgX19kZWNvcmF0ZTogX19kZWNvcmF0ZSxcclxuICAgIF9fcGFyYW06IF9fcGFyYW0sXHJcbiAgICBfX2VzRGVjb3JhdGU6IF9fZXNEZWNvcmF0ZSxcclxuICAgIF9fcnVuSW5pdGlhbGl6ZXJzOiBfX3J1bkluaXRpYWxpemVycyxcclxuICAgIF9fcHJvcEtleTogX19wcm9wS2V5LFxyXG4gICAgX19zZXRGdW5jdGlvbk5hbWU6IF9fc2V0RnVuY3Rpb25OYW1lLFxyXG4gICAgX19tZXRhZGF0YTogX19tZXRhZGF0YSxcclxuICAgIF9fYXdhaXRlcjogX19hd2FpdGVyLFxyXG4gICAgX19nZW5lcmF0b3I6IF9fZ2VuZXJhdG9yLFxyXG4gICAgX19jcmVhdGVCaW5kaW5nOiBfX2NyZWF0ZUJpbmRpbmcsXHJcbiAgICBfX2V4cG9ydFN0YXI6IF9fZXhwb3J0U3RhcixcclxuICAgIF9fdmFsdWVzOiBfX3ZhbHVlcyxcclxuICAgIF9fcmVhZDogX19yZWFkLFxyXG4gICAgX19zcHJlYWQ6IF9fc3ByZWFkLFxyXG4gICAgX19zcHJlYWRBcnJheXM6IF9fc3ByZWFkQXJyYXlzLFxyXG4gICAgX19zcHJlYWRBcnJheTogX19zcHJlYWRBcnJheSxcclxuICAgIF9fYXdhaXQ6IF9fYXdhaXQsXHJcbiAgICBfX2FzeW5jR2VuZXJhdG9yOiBfX2FzeW5jR2VuZXJhdG9yLFxyXG4gICAgX19hc3luY0RlbGVnYXRvcjogX19hc3luY0RlbGVnYXRvcixcclxuICAgIF9fYXN5bmNWYWx1ZXM6IF9fYXN5bmNWYWx1ZXMsXHJcbiAgICBfX21ha2VUZW1wbGF0ZU9iamVjdDogX19tYWtlVGVtcGxhdGVPYmplY3QsXHJcbiAgICBfX2ltcG9ydFN0YXI6IF9faW1wb3J0U3RhcixcclxuICAgIF9faW1wb3J0RGVmYXVsdDogX19pbXBvcnREZWZhdWx0LFxyXG4gICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldDogX19jbGFzc1ByaXZhdGVGaWVsZEdldCxcclxuICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQ6IF9fY2xhc3NQcml2YXRlRmllbGRTZXQsXHJcbiAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkSW46IF9fY2xhc3NQcml2YXRlRmllbGRJbixcclxuICAgIF9fYWRkRGlzcG9zYWJsZVJlc291cmNlOiBfX2FkZERpc3Bvc2FibGVSZXNvdXJjZSxcclxuICAgIF9fZGlzcG9zZVJlc291cmNlczogX19kaXNwb3NlUmVzb3VyY2VzLFxyXG4gICAgX19yZXdyaXRlUmVsYXRpdmVJbXBvcnRFeHRlbnNpb246IF9fcmV3cml0ZVJlbGF0aXZlSW1wb3J0RXh0ZW5zaW9uLFxyXG59O1xyXG4iLCJpbXBvcnQgeyBcbiAgQXBwLCBcbiAgRWRpdG9yLCBcbiAgTWFya2Rvd25WaWV3LCBcbiAgTW9kYWwsIFxuICBOb3RpY2UsIFxuICBQbHVnaW4sIFxuICBQbHVnaW5TZXR0aW5nVGFiLFxuICBTZXR0aW5nLFxuICBURmlsZSwgXG4gIEZyb250TWF0dGVyQ2FjaGUsIFxuICBwYXJzZVlhbWwsXG4gIHN0cmluZ2lmeVlhbWwsXG4gIFdvcmtzcGFjZUxlYWZcbn0gZnJvbSAnb2JzaWRpYW4nO1xuXG5pbnRlcmZhY2UgS2FuYmFuU3RhdHVzVXBkYXRlclNldHRpbmdzIHtcbiAgc3RhdHVzUHJvcGVydHlOYW1lOiBzdHJpbmc7XG4gIHNob3dOb3RpZmljYXRpb25zOiBib29sZWFuO1xuICBkZWJ1Z01vZGU6IGJvb2xlYW47XG59XG5cbmNvbnN0IERFRkFVTFRfU0VUVElOR1M6IEthbmJhblN0YXR1c1VwZGF0ZXJTZXR0aW5ncyA9IHtcbiAgc3RhdHVzUHJvcGVydHlOYW1lOiAnc3RhdHVzJyxcbiAgc2hvd05vdGlmaWNhdGlvbnM6IHRydWUsXG4gIGRlYnVnTW9kZTogdHJ1ZVxufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBLYW5iYW5TdGF0dXNVcGRhdGVyUGx1Z2luIGV4dGVuZHMgUGx1Z2luIHtcbiAgc2V0dGluZ3M6IEthbmJhblN0YXR1c1VwZGF0ZXJTZXR0aW5ncztcblxuICAvLyBQcm9jZXNzIGZsYWdzIHRvIGF2b2lkIGluZmluaXRlIGxvb3BzXG4gIHByaXZhdGUgcHJvY2Vzc2luZ011dGF0aW9uOiBib29sZWFuID0gZmFsc2U7XG4gIHByaXZhdGUgcGVuZGluZ0NhcmRVcGRhdGVzOiBNYXA8c3RyaW5nLCB7Y2FyZDogSFRNTEVsZW1lbnQsIGNvbHVtbjogSFRNTEVsZW1lbnR9PiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSBtdXRhdGlvbkRlYm91bmNlVGltZW91dDogTm9kZUpTLlRpbWVvdXQgPSBudWxsO1xuICBkZWJ1Z0xvZzogKG1lc3NhZ2U6IHN0cmluZykgPT4gdm9pZDtcbiAgc3RhdHVzQmFySXRlbTogYW55O1xuXG4gIGFzeW5jIG9ubG9hZCgpIHtcbiAgICAgIGF3YWl0IHRoaXMubG9hZFNldHRpbmdzKCk7XG5cbiAgICAgIC8vIFNldCB1cCBkZWJ1ZyBsb2dnaW5nIHdpdGggcmF0ZSBsaW1pdGluZ1xuICAgICAgbGV0IGxhc3RMb2dUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgIGxldCBsb2dDb3VudCA9IDA7XG4gICAgICB0aGlzLmRlYnVnTG9nID0gKG1lc3NhZ2U6IHN0cmluZykgPT4ge1xuICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmRlYnVnTW9kZSkge1xuICAgICAgICAgICAgICAvLyBSYXRlIGxpbWl0IGxvZ3MgdG8gcHJldmVudCBjb25zb2xlIGZsb29kaW5nXG4gICAgICAgICAgICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgIGlmIChub3cgLSBsYXN0TG9nVGltZSA+IDUwMDApIHtcbiAgICAgICAgICAgICAgICAgIC8vIFJlc2V0IGNvdW50ZXIgYWZ0ZXIgNSBzZWNvbmRzXG4gICAgICAgICAgICAgICAgICBsb2dDb3VudCA9IDA7XG4gICAgICAgICAgICAgICAgICBsYXN0TG9nVGltZSA9IG5vdztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgaWYgKGxvZ0NvdW50IDwgNTApIHsgLy8gTGltaXQgdG8gNTAgbG9ncyBwZXIgNSBzZWNvbmRzXG4gICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhgW0thbmJhbiBTdGF0dXMgVXBkYXRlcl0gJHttZXNzYWdlfWApO1xuICAgICAgICAgICAgICAgICAgbG9nQ291bnQrKztcbiAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdHVzQmFySXRlbSkge1xuICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHVzQmFySXRlbS5zZXRUZXh0KGBbS1NVXSAke21lc3NhZ2Uuc3Vic3RyaW5nKDAsIDQwKX0ke21lc3NhZ2UubGVuZ3RoID4gNDAgPyAnLi4uJyA6ICcnfWApO1xuICAgICAgICAgICAgICAgICAgICAgIC8vIFJlc2V0IGFmdGVyIDUgc2Vjb25kc1xuICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0dXNCYXJJdGVtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXR1c0Jhckl0ZW0uc2V0VGV4dCgnS2FuYmFuIFN0YXR1cyBVcGRhdGVyIEFjdGl2ZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgfSwgNTAwMCk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAobG9nQ291bnQgPT09IDUwKSB7XG4gICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhgW0thbmJhbiBTdGF0dXMgVXBkYXRlcl0gVG9vIG1hbnkgbG9ncywgdGhyb3R0bGluZyB1bnRpbCAke25ldyBEYXRlKGxhc3RMb2dUaW1lICsgNTAwMCkudG9Mb2NhbGVUaW1lU3RyaW5nKCl9YCk7XG4gICAgICAgICAgICAgICAgICBsb2dDb3VudCsrO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIFxuICAgICAgLy8gRGlzcGxheSBzdGFydHVwIG5vdGlmaWNhdGlvblxuICAgICAgbmV3IE5vdGljZSgnS2FuYmFuIFN0YXR1cyBVcGRhdGVyIHBsdWdpbiBhY3RpdmF0ZWQnKTtcbiAgICAgIHRoaXMuZGVidWdMb2coJ1BsdWdpbiBsb2FkZWQgYW5kIGFjdGl2YXRlZCcpO1xuXG4gICAgICAvLyBIb29rIGludG8gRE9NIGV2ZW50cyB0byBkZXRlY3QgS2FuYmFuIGNhcmQgbW92ZW1lbnRzXG4gICAgICB0aGlzLnJlZ2lzdGVyRG9tRXZlbnQoZG9jdW1lbnQsICdkcmFnZW5kJywgdGhpcy5oYW5kbGVEcmFnRW5kLmJpbmQodGhpcykpO1xuICAgICAgdGhpcy5kZWJ1Z0xvZygnUmVnaXN0ZXJlZCBkcmFnIGV2ZW50IGxpc3RlbmVyJyk7XG4gICAgICBcbiAgICAgIC8vIFJlZ2lzdGVyIGZvciBtdXRhdGlvbiBldmVudHMgdG8gY2F0Y2ggbm9uLWRyYWcgdXBkYXRlcyAtIHdpdGggb3B0aW1pemF0aW9uc1xuICAgICAgY29uc3Qgb2JzZXJ2ZXIgPSBuZXcgTXV0YXRpb25PYnNlcnZlcigobXV0YXRpb25zKSA9PiB7XG4gICAgICAgICAgLy8gU2tpcCBwcm9jZXNzaW5nIGlmIHdlJ3JlIGFscmVhZHkgaGFuZGxpbmcgYSBtdXRhdGlvblxuICAgICAgICAgIGlmICh0aGlzLnByb2Nlc3NpbmdNdXRhdGlvbikgcmV0dXJuO1xuICAgICAgICAgIFxuICAgICAgICAgIC8vIERlYm91bmNlIG11dGF0aW9uIHByb2Nlc3NpbmcgdG8gYXZvaWQgdG9vIG1hbnkgdXBkYXRlc1xuICAgICAgICAgIGlmICh0aGlzLm11dGF0aW9uRGVib3VuY2VUaW1lb3V0KSB7XG4gICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLm11dGF0aW9uRGVib3VuY2VUaW1lb3V0KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgXG4gICAgICAgICAgdGhpcy5tdXRhdGlvbkRlYm91bmNlVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICB0aGlzLmhhbmRsZURPTU11dGF0aW9ucyhtdXRhdGlvbnMpO1xuICAgICAgICAgICAgICB0aGlzLm11dGF0aW9uRGVib3VuY2VUaW1lb3V0ID0gbnVsbDtcbiAgICAgICAgICB9LCA1MDApOyAvLyBXYWl0IDUwMG1zIGJlZm9yZSBwcm9jZXNzaW5nXG4gICAgICB9KTtcbiAgICAgIFxuICAgICAgdGhpcy5hcHAud29ya3NwYWNlLm9uTGF5b3V0UmVhZHkoKCkgPT4ge1xuICAgICAgICAgIC8vIEZpbmQgS2FuYmFuIGJvYXJkIGNvbnRhaW5lcnMgdG8gb2JzZXJ2ZSBtb3JlIHNwZWNpZmljYWxseVxuICAgICAgICAgIGNvbnN0IGthbmJhbkJvYXJkcyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5rYW5iYW4tcGx1Z2luX19ib2FyZCcpO1xuICAgICAgICAgIFxuICAgICAgICAgIGlmIChrYW5iYW5Cb2FyZHMgJiYga2FuYmFuQm9hcmRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgLy8gT2JzZXJ2ZSBlYWNoIEthbmJhbiBib2FyZCBzcGVjaWZpY2FsbHkgcmF0aGVyIHRoYW4gdGhlIGVudGlyZSBkb2N1bWVudFxuICAgICAgICAgICAgICBrYW5iYW5Cb2FyZHMuZm9yRWFjaChib2FyZCA9PiB7XG4gICAgICAgICAgICAgICAgICBvYnNlcnZlci5vYnNlcnZlKGJvYXJkLCB7IFxuICAgICAgICAgICAgICAgICAgICAgIGNoaWxkTGlzdDogdHJ1ZSwgXG4gICAgICAgICAgICAgICAgICAgICAgc3VidHJlZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzOiBmYWxzZSAgLy8gRG9uJ3QgbmVlZCBhdHRyaWJ1dGUgY2hhbmdlcywganVzdCBzdHJ1Y3R1cmVcbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgdGhpcy5kZWJ1Z0xvZyhgTXV0YXRpb25PYnNlcnZlciBhdHRhY2hlZCB0byAke2thbmJhbkJvYXJkcy5sZW5ndGh9IEthbmJhbiBib2FyZHNgKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAvLyBGYWxsYmFjayB0byBhIG1vcmUgdGFyZ2V0ZWQgb2JzZXJ2YXRpb24gaWYgbm8gYm9hcmRzIGZvdW5kXG4gICAgICAgICAgICAgIGNvbnN0IHdvcmtzcGFjZSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy53b3Jrc3BhY2UnKTtcbiAgICAgICAgICAgICAgaWYgKHdvcmtzcGFjZSkge1xuICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIub2JzZXJ2ZSh3b3Jrc3BhY2UsIHtcbiAgICAgICAgICAgICAgICAgICAgICBjaGlsZExpc3Q6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgc3VidHJlZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzOiBmYWxzZVxuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICB0aGlzLmRlYnVnTG9nKCdNdXRhdGlvbk9ic2VydmVyIGF0dGFjaGVkIHRvIHdvcmtzcGFjZSAobm8gS2FuYmFuIGJvYXJkcyBmb3VuZCB5ZXQpJyk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAvLyBMYXN0IHJlc29ydCAtIG9ic2VydmUgYm9keSB3aXRoIG1vcmUgcmVzdHJpY3Rpb25zXG4gICAgICAgICAgICAgICAgICBvYnNlcnZlci5vYnNlcnZlKGRvY3VtZW50LmJvZHksIHsgXG4gICAgICAgICAgICAgICAgICAgICAgY2hpbGRMaXN0OiB0cnVlLCBcbiAgICAgICAgICAgICAgICAgICAgICBzdWJ0cmVlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXM6IGZhbHNlXG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgIHRoaXMuZGVidWdMb2coJ011dGF0aW9uT2JzZXJ2ZXIgYXR0YWNoZWQgdG8gZG9jdW1lbnQgYm9keSAoZmFsbGJhY2sgbW9kZSknKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBcbiAgICAgICAgICAvLyBTZXQgdXAgYSBwZXJpb2RpYyBjaGVjayBmb3IgbmV3IEthbmJhbiBib2FyZHMgKGluIGNhc2UgdGhleSdyZSBhZGRlZCBsYXRlcilcbiAgICAgICAgICBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRCb2FyZHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcua2FuYmFuLXBsdWdpbl9fYm9hcmQnKTtcbiAgICAgICAgICAgICAgaWYgKGN1cnJlbnRCb2FyZHMgJiYgY3VycmVudEJvYXJkcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICBjdXJyZW50Qm9hcmRzLmZvckVhY2goYm9hcmQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgIGlmICghYm9hcmQuaGFzQXR0cmlidXRlKCdkYXRhLWtzdS1vYnNlcnZlZCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm9ic2VydmUoYm9hcmQsIHsgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGlsZExpc3Q6IHRydWUsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VidHJlZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXM6IGZhbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBib2FyZC5zZXRBdHRyaWJ1dGUoJ2RhdGEta3N1LW9ic2VydmVkJywgJ3RydWUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWJ1Z0xvZygnQWRkZWQgb2JzZXJ2ZXIgdG8gbmV3IEthbmJhbiBib2FyZCcpO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgfSwgMTAwMDApOyAvLyBDaGVjayBldmVyeSAxMCBzZWNvbmRzXG4gICAgICB9KTtcblxuICAgICAgLy8gQWRkIHNldHRpbmdzIHRhYlxuICAgICAgdGhpcy5hZGRTZXR0aW5nVGFiKG5ldyBLYW5iYW5TdGF0dXNVcGRhdGVyU2V0dGluZ1RhYih0aGlzLmFwcCwgdGhpcykpO1xuXG4gICAgICAvLyBBZGQgYSBzdGF0dXMgYmFyIGl0ZW0gdG8gc2hvdyB0aGUgcGx1Z2luIGlzIGFjdGl2ZVxuICAgICAgdGhpcy5zdGF0dXNCYXJJdGVtID0gdGhpcy5hZGRTdGF0dXNCYXJJdGVtKCk7XG4gICAgICB0aGlzLnN0YXR1c0Jhckl0ZW0uc2V0VGV4dCgnS2FuYmFuIFN0YXR1cyBVcGRhdGVyIEFjdGl2ZScpO1xuICAgICAgdGhpcy5zdGF0dXNCYXJJdGVtLmFkZENsYXNzKCdwbHVnaW4ta2FuYmFuLXN0YXR1cy11cGRhdGVyJyk7XG4gICAgICBcbiAgICAgIC8vIENoZWNrIGlmIEthbmJhbiBwbHVnaW4gaXMgbG9hZGVkIC0gdXNpbmcgc2FmZXIgYXBwcm9hY2hcbiAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gQHRzLWlnbm9yZSAtIENoZWNrIGlmIGthbmJhbiBwbHVnaW4gZXhpc3RzIHVzaW5nIGFwcC5wbHVnaW5zIChtYXkgbm90IGJlIGluIHR5cGUgZGVmaW5pdGlvbnMpXG4gICAgICAgICAgY29uc3Qga2FuYmFuTG9hZGVkID0gdGhpcy5hcHAucGx1Z2lucyAmJiBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKCh0aGlzLmFwcC5wbHVnaW5zLnBsdWdpbnMgJiYgdGhpcy5hcHAucGx1Z2lucy5wbHVnaW5zWydvYnNpZGlhbi1rYW5iYW4nXSkgfHwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHRoaXMuYXBwLnBsdWdpbnMuZW5hYmxlZFBsdWdpbnMgJiYgdGhpcy5hcHAucGx1Z2lucy5lbmFibGVkUGx1Z2lucy5oYXMoJ29ic2lkaWFuLWthbmJhbicpKSk7XG4gICAgICAgICAgXG4gICAgICAgICAgaWYgKCFrYW5iYW5Mb2FkZWQpIHtcbiAgICAgICAgICAgICAgbmV3IE5vdGljZSgn4pqg77iPIFdhcm5pbmc6IEthbmJhbiBwbHVnaW4gbWlnaHQgbm90IGJlIGVuYWJsZWQuIEthbmJhbiBTdGF0dXMgVXBkYXRlciByZXF1aXJlcyBpdC4nLCAxMDAwMCk7XG4gICAgICAgICAgICAgIHRoaXMuZGVidWdMb2coJ1dBUk5JTkc6IEthbmJhbiBwbHVnaW4gbm90IGRldGVjdGVkIScpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRoaXMuZGVidWdMb2coJ0thbmJhbiBwbHVnaW4gZGV0ZWN0ZWQnKTtcbiAgICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgLy8gSWYgd2UgY2FuJ3QgZGV0ZWN0IGl0LCBqdXN0IGxvZyBhbmQgY29udGludWVcbiAgICAgICAgICB0aGlzLmRlYnVnTG9nKGBDb3VsZG4ndCB2ZXJpZnkgS2FuYmFuIHBsdWdpbjogJHtlLm1lc3NhZ2V9YCk7XG4gICAgICB9XG4gIH1cblxuICBvbnVubG9hZCgpIHtcbiAgICAgIHRoaXMuZGVidWdMb2coJ1BsdWdpbiB1bmxvYWRlZCcpO1xuICAgICAgbmV3IE5vdGljZSgnS2FuYmFuIFN0YXR1cyBVcGRhdGVyIHBsdWdpbiBkZWFjdGl2YXRlZCcpO1xuICB9XG5cbiAgYXN5bmMgbG9hZFNldHRpbmdzKCkge1xuICAgICAgdGhpcy5zZXR0aW5ncyA9IE9iamVjdC5hc3NpZ24oe30sIERFRkFVTFRfU0VUVElOR1MsIGF3YWl0IHRoaXMubG9hZERhdGEoKSk7XG4gIH1cblxuICBhc3luYyBzYXZlU2V0dGluZ3MoKSB7XG4gICAgICBhd2FpdCB0aGlzLnNhdmVEYXRhKHRoaXMuc2V0dGluZ3MpO1xuICB9XG5cbiAgaGFuZGxlRHJhZ0VuZChldnQ6IERyYWdFdmVudCkge1xuICAgICAgLy8gQ2hlY2sgaWYgdGhpcyB3YXMgYSBLYW5iYW4gY2FyZCBiZWluZyBkcmFnZ2VkXG4gICAgICBjb25zdCB0YXJnZXQgPSBldnQudGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuICAgICAgaWYgKCF0YXJnZXQpIHtcbiAgICAgICAgICB0aGlzLmRlYnVnTG9nKCdEcmFnIGV2ZW50IGhhZCBubyB0YXJnZXQnKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBcbiAgICAgIHRoaXMuZGVidWdMb2coYERyYWcgZXZlbnQgZGV0ZWN0ZWQgb24gZWxlbWVudDogJHt0YXJnZXQudGFnTmFtZX0ke3RhcmdldC5jbGFzc05hbWUgPyAnIHdpdGggY2xhc3MgJyArIHRhcmdldC5jbGFzc05hbWUgOiAnJ31gKTtcbiAgICAgIFxuICAgICAgY29uc3Qga2FuYmFuQ2FyZCA9IHRhcmdldC5jbG9zZXN0KCcua2FuYmFuLWNhcmQnKTtcbiAgICAgIGlmICgha2FuYmFuQ2FyZCkge1xuICAgICAgICAgIHRoaXMuZGVidWdMb2coJ0VsZW1lbnQgaXMgbm90IG9yIGRvZXMgbm90IGNvbnRhaW4gYSBLYW5iYW4gY2FyZCcpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgdGhpcy5kZWJ1Z0xvZygnS2FuYmFuIGNhcmQgZm91bmQgaW4gZHJhZyBldmVudCcpO1xuICAgICAgXG4gICAgICAvLyBHZXQgdGhlIGNvbHVtbiB0aGUgY2FyZCB3YXMgZHJvcHBlZCBpblxuICAgICAgY29uc3QgY29sdW1uID0ga2FuYmFuQ2FyZC5jbG9zZXN0KCcua2FuYmFuLWNvbHVtbicpO1xuICAgICAgaWYgKCFjb2x1bW4pIHtcbiAgICAgICAgICB0aGlzLmRlYnVnTG9nKCdDb3VsZCBub3QgZmluZCBwYXJlbnQgS2FuYmFuIGNvbHVtbicpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgdGhpcy5kZWJ1Z0xvZygnQ2FyZCB3YXMgbW92ZWQgdG8gYSBjb2x1bW4sIHByb2Nlc3NpbmcgbW92ZW1lbnQnKTtcbiAgICAgIFxuICAgICAgLy8gUHJvY2VzcyB0aGUgY2FyZCBtb3ZlbWVudFxuICAgICAgdGhpcy5wcm9jZXNzQ2FyZE1vdmVtZW50KGthbmJhbkNhcmQgYXMgSFRNTEVsZW1lbnQsIGNvbHVtbiBhcyBIVE1MRWxlbWVudCk7XG4gIH1cblxuICBoYW5kbGVET01NdXRhdGlvbnMobXV0YXRpb25zOiBNdXRhdGlvblJlY29yZFtdKSB7XG4gICAgICBpZiAodGhpcy5wcm9jZXNzaW5nTXV0YXRpb24pIHtcbiAgICAgICAgICB0aGlzLmRlYnVnTG9nKCdBbHJlYWR5IHByb2Nlc3NpbmcgbXV0YXRpb25zLCBza2lwcGluZycpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gUHJvY2VzcyBvbmx5IGEgc2FtcGxlIG9mIG11dGF0aW9ucyBpZiB0aGVyZSBhcmUgdG9vIG1hbnlcbiAgICAgIGNvbnN0IG11dGF0aW9uc1RvUHJvY2VzcyA9IG11dGF0aW9ucy5sZW5ndGggPiAxMCA/IFxuICAgICAgICAgIG11dGF0aW9ucy5zbGljZSgwLCAxMCkgOiBtdXRhdGlvbnM7XG4gICAgICAgICAgXG4gICAgICB0aGlzLmRlYnVnTG9nKGBQcm9jZXNzaW5nICR7bXV0YXRpb25zVG9Qcm9jZXNzLmxlbmd0aH0gbXV0YXRpb25zIChvZiAke211dGF0aW9ucy5sZW5ndGh9IHRvdGFsKWApO1xuICAgICAgXG4gICAgICAvLyBTZXQgZmxhZyB0byBwcmV2ZW50IHJlY3Vyc2l2ZSBwcm9jZXNzaW5nXG4gICAgICB0aGlzLnByb2Nlc3NpbmdNdXRhdGlvbiA9IHRydWU7XG5cbiAgICAgIHRoaXMuZGVidWdMb2coYEhFTExPYCk7XG4gICAgICBcbiAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gQ2xlYXIgdGhlIHBlbmRpbmcgdXBkYXRlcyBtYXBcbiAgICAgICAgICB0aGlzLnBlbmRpbmdDYXJkVXBkYXRlcy5jbGVhcigpO1xuICAgICAgICAgIFxuICAgICAgICAgIC8vIENoZWNrIGZvciByZWxldmFudCBtdXRhdGlvbnMgKGNhcmQgYmVpbmcgYWRkZWQgdG8gYSBjb2x1bW4pXG4gICAgICAgICAgZm9yIChjb25zdCBtdXRhdGlvbiBvZiBtdXRhdGlvbnNUb1Byb2Nlc3MpIHtcbiAgICAgICAgICAgICAgaWYgKG11dGF0aW9uLnR5cGUgPT09ICdjaGlsZExpc3QnKSB7XG4gICAgICAgICAgICAgICAgICAvLyBPbmx5IGxvZyBpZiB0aGVyZSBhcmUgYWN0dWFsbHkgS2FuYmFuLXJlbGF0ZWQgbm9kZXNcbiAgICAgICAgICAgICAgICAgIGxldCBmb3VuZEthbmJhbkVsZW1lbnRzID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICAgIHRoaXMuZGVidWdMb2coYG11dGF0aW9uLnR5cGUgPT09ICdjaGlsZExpc3QnYCk7XG4gICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiBBcnJheS5mcm9tKG11dGF0aW9uLmFkZGVkTm9kZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiB0aGlzIGlzIG9yIGNvbnRhaW5zIEthbmJhbiBjYXJkIGVsZW1lbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGlzS2FuYmFuRWxlbWVudCA9IFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5jbGFzc0xpc3QuY29udGFpbnMoJ2thbmJhbi1jYXJkJykgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuY2xhc3NMaXN0LmNvbnRhaW5zKCdrYW5iYW4tY29sdW1uJykgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucXVlcnlTZWxlY3RvcignLmthbmJhbi1jYXJkJykgIT09IG51bGw7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWJ1Z0xvZyhgaXNLYW5iYW5FbGVtZW50OiAke2lzS2FuYmFuRWxlbWVudH1gKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlYnVnTG9nKGBub2RlLmNsYXNzTGlzdDogJHtub2RlLmNsYXNzTGlzdH1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWJ1Z0xvZyhgbm9kZS50YWdOYW1lOiAke25vZGUudGFnTmFtZX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWJ1Z0xvZyhgbm9kZS5jbGFzc05hbWU6ICR7bm9kZS5jbGFzc05hbWV9YCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzS2FuYmFuRWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm91bmRLYW5iYW5FbGVtZW50cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9ubHkgbm93IGxvZyBkZXRhaWxzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlYnVnTG9nKGBSZWxldmFudCBtdXRhdGlvbjogJHtub2RlLnRhZ05hbWV9JHtub2RlLmNsYXNzTmFtZSA/ICcgd2l0aCBjbGFzcyAnICsgbm9kZS5jbGFzc05hbWUgOiAnJ31gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTG9vayBmb3IgS2FuYmFuIGNhcmRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBrYW5iYW5DYXJkcyA9IG5vZGUuY2xhc3NMaXN0LmNvbnRhaW5zKCdrYW5iYW4tY2FyZCcpIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gW25vZGVdIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogQXJyYXkuZnJvbShub2RlLnF1ZXJ5U2VsZWN0b3JBbGwoJy5rYW5iYW4tY2FyZCcpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBjYXJkIG9mIGthbmJhbkNhcmRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29sdW1uID0gY2FyZC5jbG9zZXN0KCcua2FuYmFuLWNvbHVtbicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb2x1bW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ3JlYXRlIGEgdW5pcXVlIElEIGZvciB0aGlzIGNhcmQgdG8gYXZvaWQgZHVwbGljYXRlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYXJkVGV4dCA9IGNhcmQudGV4dENvbnRlbnQ/LnRyaW0oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FyZElkID0gY2FyZFRleHQ/LnN1YnN0cmluZygwLCA1MCkgfHwgY2FyZC5pZCB8fCAndW5rbm93bic7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlYnVnTG9nKGBBZGRlZCBjYXJkIHRvIHBlbmRpbmdDYXJkVXBkYXRlczogJHtjYXJkVGV4dH1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWJ1Z0xvZyhgQ29sdW1uOiAke2NvbHVtbi50ZXh0Q29udGVudH1gKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgdG8gcGVuZGluZyB1cGRhdGVzIG1hcCwgdGhpcyB3YXkgaWYgc2FtZSBjYXJkIGFwcGVhcnMgaW4gbXVsdGlwbGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbXV0YXRpb25zLCB3ZSBvbmx5IHByb2Nlc3MgdGhlIGxhc3Qgb25lXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGVuZGluZ0NhcmRVcGRhdGVzLnNldChjYXJkSWQsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmQ6IGNhcmQgYXMgSFRNTEVsZW1lbnQsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uOiBjb2x1bW4gYXMgSFRNTEVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlYnVnTG9nKGBRdWV1ZWQgY2FyZCB1cGRhdGU6ICR7Y2FyZElkLnN1YnN0cmluZygwLCAyMCl9Li4uYCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAvLyBPbmx5IGxvZyBmb3IgbXV0YXRpb25zIHdpdGggS2FuYmFuIGVsZW1lbnRzXG4gICAgICAgICAgICAgICAgICBpZiAoZm91bmRLYW5iYW5FbGVtZW50cykge1xuICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVidWdMb2coYFByb2Nlc3NlZCBtdXRhdGlvbiB3aXRoICR7bXV0YXRpb24uYWRkZWROb2Rlcy5sZW5ndGh9IG5vZGVzYCk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgXG4gICAgICAgICAgLy8gUHJvY2VzcyBhbGwgcGVuZGluZyB1cGRhdGVzXG4gICAgICAgICAgaWYgKHRoaXMucGVuZGluZ0NhcmRVcGRhdGVzLnNpemUgPiAwKSB7XG4gICAgICAgICAgICAgIHRoaXMuZGVidWdMb2coYFByb2Nlc3NpbmcgJHt0aGlzLnBlbmRpbmdDYXJkVXBkYXRlcy5zaXplfSBjYXJkIHVwZGF0ZXNgKTtcbiAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgIC8vIFByb2Nlc3MgZWFjaCBjYXJkIHVwZGF0ZSAod2l0aCBhIHNsaWdodCBkZWxheSBiZXR3ZWVuIHRoZW0gdG8gYXZvaWQgb3ZlcmxvYWRpbmcpXG4gICAgICAgICAgICAgIGxldCBpbmRleCA9IDA7XG4gICAgICAgICAgICAgIGZvciAoY29uc3QgW2NhcmRJZCwge2NhcmQsIGNvbHVtbn1dIG9mIHRoaXMucGVuZGluZ0NhcmRVcGRhdGVzLmVudHJpZXMoKSkge1xuICAgICAgICAgICAgICAgICAgLy8gU3RhZ2dlciBwcm9jZXNzaW5nIHRvIGF2b2lkIHRvbyBtdWNoIGF0IG9uY2VcbiAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgIHRoaXMucHJvY2Vzc0NhcmRNb3ZlbWVudChjYXJkLCBjb2x1bW4pO1xuICAgICAgICAgICAgICAgICAgfSwgaW5kZXggKiAxMDApOyAvLyAxMDBtcyBiZXR3ZWVuIGVhY2ggY2FyZFxuICAgICAgICAgICAgICAgICAgaW5kZXgrKztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICB0aGlzLmRlYnVnTG9nKGBFcnJvciBwcm9jZXNzaW5nIG11dGF0aW9uczogJHtlLm1lc3NhZ2V9YCk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIC8vIENsZWFyIHRoZSBmbGFnIHdoZW4gZG9uZVxuICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICB0aGlzLnByb2Nlc3NpbmdNdXRhdGlvbiA9IGZhbHNlO1xuICAgICAgICAgICAgICB0aGlzLmRlYnVnTG9nKCdNdXRhdGlvbiBwcm9jZXNzaW5nIGNvbXBsZXRlJyk7XG4gICAgICAgICAgfSwgMTAwMCk7IC8vIEVuc3VyZSBhIG1pbmltdW0gY29vbC1kb3duIHBlcmlvZCBiZXR3ZWVuIG11dGF0aW9uIHByb2Nlc3NpbmdcbiAgICAgIH1cbiAgfVxuXG4gIHByb2Nlc3NDYXJkTW92ZW1lbnQoY2FyZDogSFRNTEVsZW1lbnQsIGNvbHVtbjogSFRNTEVsZW1lbnQpIHtcbiAgICAgIC8vIEdldCB0aGUgY29sdW1uIG5hbWUgKG5ldyBzdGF0dXMpXG4gICAgICBjb25zdCBoZWFkZXJFbGVtZW50ID0gY29sdW1uLnF1ZXJ5U2VsZWN0b3IoJy5rYW5iYW4tY29sdW1uLWhlYWRlcicpO1xuICAgICAgaWYgKCFoZWFkZXJFbGVtZW50KSB7XG4gICAgICAgICAgdGhpcy5kZWJ1Z0xvZygnQ291bGQgbm90IGZpbmQgY29sdW1uIGhlYWRlciBlbGVtZW50Jyk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgXG4gICAgICBjb25zdCBuZXdTdGF0dXMgPSBoZWFkZXJFbGVtZW50LnRleHRDb250ZW50LnRyaW0oKTtcbiAgICAgIHRoaXMuZGVidWdMb2coYENvbHVtbiBuYW1lIChuZXcgc3RhdHVzKTogXCIke25ld1N0YXR1c31cImApO1xuICAgICAgXG4gICAgICAvLyBHZXQgdGhlIGNhcmQgY29udGVudCBhbmQgbG9vayBmb3IgdGhlIGZpcnN0IGxpbmtcbiAgICAgIGNvbnN0IGNhcmRDb250ZW50RWxlbWVudCA9IGNhcmQucXVlcnlTZWxlY3RvcignLmthbmJhbi1jYXJkLXRleHQsIC5rYW5iYW4tY2FyZC1jb250ZW50Jyk7XG4gICAgICBpZiAoIWNhcmRDb250ZW50RWxlbWVudCkge1xuICAgICAgICAgIHRoaXMuZGVidWdMb2coJ0NvdWxkIG5vdCBmaW5kIGNhcmQgY29udGVudCBlbGVtZW50Jyk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgXG4gICAgICBjb25zdCBjYXJkQ29udGVudCA9IGNhcmRDb250ZW50RWxlbWVudC50ZXh0Q29udGVudDtcbiAgICAgIHRoaXMuZGVidWdMb2coYENhcmQgY29udGVudDogXCIke2NhcmRDb250ZW50LnN1YnN0cmluZygwLCA1MCl9JHtjYXJkQ29udGVudC5sZW5ndGggPiA1MCA/ICcuLi4nIDogJyd9XCJgKTtcbiAgICAgIFxuICAgICAgLy8gTG9vayBmb3Igd2lraS1saW5rcyBbW0xpbmtdXSBvciBbW0xpbmt8RGlzcGxheSBUZXh0XV1cbiAgICAgIGNvbnN0IGxpbmtNYXRjaCA9IGNhcmRDb250ZW50Lm1hdGNoKC9cXFtcXFsoLio/KSg/OlxcfC4qPyk/XFxdXFxdLyk7XG4gICAgICBcbiAgICAgIGlmICghbGlua01hdGNoIHx8ICFsaW5rTWF0Y2hbMV0pIHtcbiAgICAgICAgICB0aGlzLmRlYnVnTG9nKGBObyBsaW5rIGZvdW5kIGluIGNhcmQ6ICR7Y2FyZENvbnRlbnR9YCk7XG4gICAgICAgICAgbmV3IE5vdGljZSgn4pqg77iPIE5vIGxpbmsgZm91bmQgaW4gS2FuYmFuIGNhcmQnLCAzMDAwKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBcbiAgICAgIGNvbnN0IGxpbmtQYXRoID0gbGlua01hdGNoWzFdLnRyaW0oKTtcbiAgICAgIHRoaXMuZGVidWdMb2coYEZvdW5kIGxpbmsgdG86IFwiJHtsaW5rUGF0aH1cImApO1xuICAgICAgXG4gICAgICAvLyBTaG93IHZpc3VhbCBjb25maXJtYXRpb24gdGhhdCB3ZSdyZSB1cGRhdGluZ1xuICAgICAgbmV3IE5vdGljZShgVXBkYXRpbmcgJHt0aGlzLnNldHRpbmdzLnN0YXR1c1Byb3BlcnR5TmFtZX0gdG8gXCIke25ld1N0YXR1c31cIiBmb3IgXCIke2xpbmtQYXRofVwiLi4uYCwgMjAwMCk7XG4gICAgICBcbiAgICAgIHRoaXMudXBkYXRlTGlua2VkTm90ZVN0YXR1cyhsaW5rUGF0aCwgbmV3U3RhdHVzKTtcbiAgfVxuXG4gIGFzeW5jIHVwZGF0ZUxpbmtlZE5vdGVTdGF0dXMobGlua1BhdGg6IHN0cmluZywgbmV3U3RhdHVzOiBzdHJpbmcpIHtcbiAgICAgIC8vIEZpbmQgdGhlIGxpbmtlZCBmaWxlXG4gICAgICBjb25zdCBmaWxlID0gdGhpcy5hcHAubWV0YWRhdGFDYWNoZS5nZXRGaXJzdExpbmtwYXRoRGVzdChsaW5rUGF0aCwgJycpO1xuICAgICAgXG4gICAgICBpZiAoIWZpbGUpIHtcbiAgICAgICAgICB0aGlzLmRlYnVnTG9nKGBMaW5rZWQgZmlsZSBub3QgZm91bmQ6ICR7bGlua1BhdGh9YCk7XG4gICAgICAgICAgbmV3IE5vdGljZShg4pqg77iPIEVycm9yOiBGaWxlIFwiJHtsaW5rUGF0aH1cIiBub3QgZm91bmRgLCA1MDAwKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBcbiAgICAgIHRoaXMuZGVidWdMb2coYEZvdW5kIGxpbmtlZCBmaWxlOiAke2ZpbGUucGF0aH1gKTtcbiAgICAgIFxuICAgICAgdHJ5IHtcbiAgICAgICAgICAvLyBSZWFkIHRoZSBmaWxlIGNvbnRlbnRcbiAgICAgICAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgdGhpcy5hcHAudmF1bHQucmVhZChmaWxlKTtcbiAgICAgICAgICB0aGlzLmRlYnVnTG9nKGBGaWxlIGNvbnRlbnQgbG9hZGVkICgke2NvbnRlbnQubGVuZ3RofSBjaGFycylgKTtcbiAgICAgICAgICBcbiAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgZmlsZSBoYXMgZnJvbnRtYXR0ZXJcbiAgICAgICAgICBjb25zdCBmcm9udG1hdHRlclJlZ2V4ID0gL14tLS1cXG4oW1xcc1xcU10qPylcXG4tLS0vO1xuICAgICAgICAgIGNvbnN0IGZyb250bWF0dGVyTWF0Y2ggPSBjb250ZW50Lm1hdGNoKGZyb250bWF0dGVyUmVnZXgpO1xuICAgICAgICAgIFxuICAgICAgICAgIGxldCBuZXdDb250ZW50O1xuICAgICAgICAgIGxldCBvbGRTdGF0dXMgPSAnbm9uZSc7XG4gICAgICAgICAgbGV0IGFjdGlvbiA9ICdjcmVhdGVkJztcbiAgICAgICAgICBcbiAgICAgICAgICBpZiAoZnJvbnRtYXR0ZXJNYXRjaCkge1xuICAgICAgICAgICAgICB0aGlzLmRlYnVnTG9nKCdGaWxlIGhhcyBmcm9udG1hdHRlcicpO1xuICAgICAgICAgICAgICAvLyBGaWxlIGhhcyBmcm9udG1hdHRlclxuICAgICAgICAgICAgICBjb25zdCBmcm9udG1hdHRlclRleHQgPSBmcm9udG1hdHRlck1hdGNoWzFdO1xuICAgICAgICAgICAgICBsZXQgZnJvbnRtYXR0ZXJPYmo7XG4gICAgICAgICAgICAgIFxuICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgLy8gVHJ5IHRvIHBhcnNlIHRoZSBmcm9udG1hdHRlclxuICAgICAgICAgICAgICAgICAgZnJvbnRtYXR0ZXJPYmogPSBwYXJzZVlhbWwoZnJvbnRtYXR0ZXJUZXh0KTtcbiAgICAgICAgICAgICAgICAgIHRoaXMuZGVidWdMb2coJ0Zyb250bWF0dGVyIHBhcnNlZCBzdWNjZXNzZnVsbHknKTtcbiAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgc3RhdHVzIHByb3BlcnR5IGFscmVhZHkgZXhpc3RzXG4gICAgICAgICAgICAgICAgICBpZiAoZnJvbnRtYXR0ZXJPYmpbdGhpcy5zZXR0aW5ncy5zdGF0dXNQcm9wZXJ0eU5hbWVdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgb2xkU3RhdHVzID0gZnJvbnRtYXR0ZXJPYmpbdGhpcy5zZXR0aW5ncy5zdGF0dXNQcm9wZXJ0eU5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbiA9ICd1cGRhdGVkJztcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICB0aGlzLmRlYnVnTG9nKGBFcnJvciBwYXJzaW5nIGZyb250bWF0dGVyOiAke2UubWVzc2FnZX1gKTtcbiAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UoYOKaoO+4jyBXYXJuaW5nOiBJbnZhbGlkIGZyb250bWF0dGVyIGluICR7ZmlsZS5iYXNlbmFtZX0sIGNyZWF0aW5nIG5ldyBmcm9udG1hdHRlcmAsIDUwMDApO1xuICAgICAgICAgICAgICAgICAgZnJvbnRtYXR0ZXJPYmogPSB7fTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBzdGF0dXMgcHJvcGVydHlcbiAgICAgICAgICAgICAgZnJvbnRtYXR0ZXJPYmpbdGhpcy5zZXR0aW5ncy5zdGF0dXNQcm9wZXJ0eU5hbWVdID0gbmV3U3RhdHVzO1xuICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgLy8gR2VuZXJhdGUgdGhlIG5ldyBmcm9udG1hdHRlciB0ZXh0XG4gICAgICAgICAgICAgIGNvbnN0IG5ld0Zyb250bWF0dGVyVGV4dCA9IHN0cmluZ2lmeVlhbWwoZnJvbnRtYXR0ZXJPYmopO1xuICAgICAgICAgICAgICB0aGlzLmRlYnVnTG9nKCdOZXcgZnJvbnRtYXR0ZXIgZ2VuZXJhdGVkJyk7XG4gICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAvLyBSZXBsYWNlIHRoZSBmcm9udG1hdHRlciBpbiB0aGUgY29udGVudFxuICAgICAgICAgICAgICBuZXdDb250ZW50ID0gY29udGVudC5yZXBsYWNlKGZyb250bWF0dGVyUmVnZXgsIGAtLS1cXG4ke25ld0Zyb250bWF0dGVyVGV4dH0tLS1gKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aGlzLmRlYnVnTG9nKCdGaWxlIGhhcyBubyBmcm9udG1hdHRlciwgY3JlYXRpbmcgbmV3IGZyb250bWF0dGVyJyk7XG4gICAgICAgICAgICAgIC8vIEZpbGUgaGFzIG5vIGZyb250bWF0dGVyLCBjcmVhdGUgaXRcbiAgICAgICAgICAgICAgY29uc3QgZnJvbnRtYXR0ZXJPYmogPSB7XG4gICAgICAgICAgICAgICAgICBbdGhpcy5zZXR0aW5ncy5zdGF0dXNQcm9wZXJ0eU5hbWVdOiBuZXdTdGF0dXNcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgY29uc3QgZnJvbnRtYXR0ZXJUZXh0ID0gc3RyaW5naWZ5WWFtbChmcm9udG1hdHRlck9iaik7XG4gICAgICAgICAgICAgIG5ld0NvbnRlbnQgPSBgLS0tXFxuJHtmcm9udG1hdHRlclRleHR9LS0tXFxuXFxuJHtjb250ZW50fWA7XG4gICAgICAgICAgfVxuICAgICAgICAgIFxuICAgICAgICAgIC8vIFNhdmUgdGhlIG1vZGlmaWVkIGNvbnRlbnRcbiAgICAgICAgICBhd2FpdCB0aGlzLmFwcC52YXVsdC5tb2RpZnkoZmlsZSwgbmV3Q29udGVudCk7XG4gICAgICAgICAgdGhpcy5kZWJ1Z0xvZygnRmlsZSBtb2RpZmllZCBzdWNjZXNzZnVsbHknKTtcbiAgICAgICAgICBcbiAgICAgICAgICAvLyBTaG93IG5vdGlmaWNhdGlvbiB3aXRoIG1vcmUgZGV0YWlsc1xuICAgICAgICAgIGNvbnN0IGJhbm5lciA9IGNyZWF0ZUZyYWdtZW50KGVsID0+IHtcbiAgICAgICAgICAgICAgZWwuY3JlYXRlRGl2KHsgXG4gICAgICAgICAgICAgICAgICB0ZXh0OiBg4pyFICR7dGhpcy5zZXR0aW5ncy5zdGF0dXNQcm9wZXJ0eU5hbWV9ICR7YWN0aW9ufTpgLFxuICAgICAgICAgICAgICAgICAgY2xzOiAnc3RhdHVzLXVwZGF0ZWQtYmFubmVyLXRpdGxlJ1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgZWwuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgIGNsczogJ3N0YXR1cy11cGRhdGVkLWJhbm5lci1kZXRhaWxzJ1xuICAgICAgICAgICAgICB9LCBkaXYgPT4ge1xuICAgICAgICAgICAgICAgICAgZGl2LmNyZWF0ZVNwYW4oeyB0ZXh0OiAnRmlsZTogJyB9KTtcbiAgICAgICAgICAgICAgICAgIGRpdi5jcmVhdGVTcGFuKHsgXG4gICAgICAgICAgICAgICAgICAgICAgdGV4dDogZmlsZS5iYXNlbmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBjbHM6ICdzdGF0dXMtdXBkYXRlZC1maWxlbmFtZSdcbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgZGl2LmNyZWF0ZUVsKCdicicpO1xuICAgICAgICAgICAgICAgICAgaWYgKGFjdGlvbiA9PT0gJ3VwZGF0ZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgZGl2LmNyZWF0ZVNwYW4oeyB0ZXh0OiAnQ2hhbmdlZCBmcm9tOiAnIH0pO1xuICAgICAgICAgICAgICAgICAgICAgIGRpdi5jcmVhdGVTcGFuKHsgXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ6IGBcIiR7b2xkU3RhdHVzfVwiYCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiAnc3RhdHVzLXVwZGF0ZWQtb2xkLXZhbHVlJ1xuICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgIGRpdi5jcmVhdGVFbCgnYnInKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIGRpdi5jcmVhdGVTcGFuKHsgdGV4dDogJ05ldyB2YWx1ZTogJyB9KTtcbiAgICAgICAgICAgICAgICAgIGRpdi5jcmVhdGVTcGFuKHsgXG4gICAgICAgICAgICAgICAgICAgICAgdGV4dDogYFwiJHtuZXdTdGF0dXN9XCJgLFxuICAgICAgICAgICAgICAgICAgICAgIGNsczogJ3N0YXR1cy11cGRhdGVkLW5ldy12YWx1ZSdcbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBcbiAgICAgICAgICAvLyBBbHdheXMgc2hvdyB0aGUgZGV0YWlsZWQgYmFubmVyXG4gICAgICAgICAgbmV3IE5vdGljZShiYW5uZXIsIDUwMDApO1xuICAgICAgICAgIFxuICAgICAgICAgIC8vIFVwZGF0ZSBzdGF0dXMgYmFyXG4gICAgICAgICAgdGhpcy5zdGF0dXNCYXJJdGVtLnNldFRleHQoYFVwZGF0ZWQ6ICR7ZmlsZS5iYXNlbmFtZX0g4oaSICR7bmV3U3RhdHVzfWApO1xuICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICB0aGlzLnN0YXR1c0Jhckl0ZW0uc2V0VGV4dCgnS2FuYmFuIFN0YXR1cyBVcGRhdGVyIEFjdGl2ZScpO1xuICAgICAgICAgIH0sIDUwMDApO1xuICAgICAgICAgIFxuICAgICAgICAgIHRoaXMuZGVidWdMb2coYFN1Y2Nlc3M6ICR7dGhpcy5zZXR0aW5ncy5zdGF0dXNQcm9wZXJ0eU5hbWV9IGZvciAke2ZpbGUuYmFzZW5hbWV9ICR7YWN0aW9ufSBmcm9tIFwiJHtvbGRTdGF0dXN9XCIgdG8gXCIke25ld1N0YXR1c31cImApO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICB0aGlzLmRlYnVnTG9nKGBFcnJvciB1cGRhdGluZyBub3RlIHN0YXR1czogJHtlcnJvci5tZXNzYWdlfWApO1xuICAgICAgICAgIG5ldyBOb3RpY2UoYOKaoO+4jyBFcnJvciB1cGRhdGluZyAke3RoaXMuc2V0dGluZ3Muc3RhdHVzUHJvcGVydHlOYW1lfSBmb3IgJHtmaWxlLmJhc2VuYW1lfTogJHtlcnJvci5tZXNzYWdlfWAsIDEwMDAwKTtcbiAgICAgIH1cbiAgfVxufVxuXG4vLyBTZXR0aW5ncyBUYWJcbmNsYXNzIEthbmJhblN0YXR1c1VwZGF0ZXJTZXR0aW5nVGFiIGV4dGVuZHMgUGx1Z2luU2V0dGluZ1RhYiB7XG4gIHBsdWdpbjogS2FuYmFuU3RhdHVzVXBkYXRlclBsdWdpbjtcblxuICBjb25zdHJ1Y3RvcihhcHA6IEFwcCwgcGx1Z2luOiBLYW5iYW5TdGF0dXNVcGRhdGVyUGx1Z2luKSB7XG4gICAgICBzdXBlcihhcHAsIHBsdWdpbik7XG4gICAgICB0aGlzLnBsdWdpbiA9IHBsdWdpbjtcbiAgfVxuXG4gIGRpc3BsYXkoKTogdm9pZCB7XG4gICAgICBjb25zdCB7Y29udGFpbmVyRWx9ID0gdGhpcztcblxuICAgICAgY29udGFpbmVyRWwuZW1wdHkoKTtcbiAgICAgIGNvbnRhaW5lckVsLmNyZWF0ZUVsKCdoMicsIHt0ZXh0OiAnS2FuYmFuIFN0YXR1cyBVcGRhdGVyIFNldHRpbmdzJ30pO1xuXG4gICAgICBuZXcgU2V0dGluZyhjb250YWluZXJFbClcbiAgICAgICAgICAuc2V0TmFtZSgnU3RhdHVzIFByb3BlcnR5IE5hbWUnKVxuICAgICAgICAgIC5zZXREZXNjKCdUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkgdG8gdXBkYXRlIHdoZW4gYSBjYXJkIGlzIG1vdmVkJylcbiAgICAgICAgICAuYWRkVGV4dCh0ZXh0ID0+IHRleHRcbiAgICAgICAgICAgICAgLnNldFBsYWNlaG9sZGVyKCdzdGF0dXMnKVxuICAgICAgICAgICAgICAuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3Muc3RhdHVzUHJvcGVydHlOYW1lKVxuICAgICAgICAgICAgICAub25DaGFuZ2UoYXN5bmMgKHZhbHVlKSA9PiB7XG4gICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5zdGF0dXNQcm9wZXJ0eU5hbWUgPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuICAgICAgICAgICAgICB9KSk7XG5cbiAgICAgIG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuICAgICAgICAgIC5zZXROYW1lKCdTaG93IE5vdGlmaWNhdGlvbnMnKVxuICAgICAgICAgIC5zZXREZXNjKCdTaG93IGEgbm90aWZpY2F0aW9uIHdoZW4gYSBzdGF0dXMgaXMgdXBkYXRlZCcpXG4gICAgICAgICAgLmFkZFRvZ2dsZSh0b2dnbGUgPT4gdG9nZ2xlXG4gICAgICAgICAgICAgIC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5zaG93Tm90aWZpY2F0aW9ucylcbiAgICAgICAgICAgICAgLm9uQ2hhbmdlKGFzeW5jICh2YWx1ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3Muc2hvd05vdGlmaWNhdGlvbnMgPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgIFxuICAgICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG4gICAgICAgICAgLnNldE5hbWUoJ0RlYnVnIE1vZGUnKVxuICAgICAgICAgIC5zZXREZXNjKCdFbmFibGUgZGV0YWlsZWQgbG9nZ2luZyB0byBjb25zb2xlIGFuZCBzdGF0dXMgYmFyIHVwZGF0ZXMnKVxuICAgICAgICAgIC5hZGRUb2dnbGUodG9nZ2xlID0+IHRvZ2dsZVxuICAgICAgICAgICAgICAuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuZGVidWdNb2RlKVxuICAgICAgICAgICAgICAub25DaGFuZ2UoYXN5bmMgKHZhbHVlKSA9PiB7XG4gICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5kZWJ1Z01vZGUgPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgICAgbmV3IE5vdGljZShgRGVidWcgbW9kZSAke3ZhbHVlID8gJ2VuYWJsZWQnIDogJ2Rpc2FibGVkJ31gKTtcbiAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICBcbiAgICAgIC8vIEFkZCBhIGJ1dHRvbiB0byB0cmlnZ2VyIGEgdGVzdCB1cGRhdGVcbiAgICAgIG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuICAgICAgICAgIC5zZXROYW1lKCdUZXN0IFBsdWdpbicpXG4gICAgICAgICAgLnNldERlc2MoJ1J1biBhIHRlc3QgdG8gdmVyaWZ5IHBsdWdpbiBmdW5jdGlvbmFsaXR5JylcbiAgICAgICAgICAuYWRkQnV0dG9uKGJ1dHRvbiA9PiBidXR0b25cbiAgICAgICAgICAgICAgLnNldEJ1dHRvblRleHQoJ1J1biBUZXN0JylcbiAgICAgICAgICAgICAgLm9uQ2xpY2soKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgbmV3IE5vdGljZSgnVGVzdCBmdW5jdGlvbiBydW5uaW5nIC0gY2hlY2sgY29uc29sZSBmb3IgbG9ncycpO1xuICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uZGVidWdMb2coJ1Rlc3QgZnVuY3Rpb24gdHJpZ2dlcmVkIGZyb20gc2V0dGluZ3MnKTtcbiAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgLy8gU2hvdyBhbiBleGFtcGxlIG9mIHdoYXQgYSBzdWNjZXNzZnVsIHVwZGF0ZSB3b3VsZCBsb29rIGxpa2VcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGJhbm5lciA9IGNyZWF0ZUZyYWdtZW50KGVsID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICBlbC5jcmVhdGVEaXYoeyBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dDogYOKchSAke3RoaXMucGx1Z2luLnNldHRpbmdzLnN0YXR1c1Byb3BlcnR5TmFtZX0gdXBkYXRlZDpgLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBjbHM6ICdzdGF0dXMtdXBkYXRlZC1iYW5uZXItdGl0bGUnXG4gICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgZWwuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiAnc3RhdHVzLXVwZGF0ZWQtYmFubmVyLWRldGFpbHMnXG4gICAgICAgICAgICAgICAgICAgICAgfSwgZGl2ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZGl2LmNyZWF0ZVNwYW4oeyB0ZXh0OiAnRmlsZTogJyB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZGl2LmNyZWF0ZVNwYW4oeyBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ6ICdFeGFtcGxlIE5vdGUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiAnc3RhdHVzLXVwZGF0ZWQtZmlsZW5hbWUnXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBkaXYuY3JlYXRlRWwoJ2JyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGRpdi5jcmVhdGVTcGFuKHsgdGV4dDogJ0NoYW5nZWQgZnJvbTogJyB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZGl2LmNyZWF0ZVNwYW4oeyBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ6ICdcIkluIFByb2dyZXNzXCInLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiAnc3RhdHVzLXVwZGF0ZWQtb2xkLXZhbHVlJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZGl2LmNyZWF0ZUVsKCdicicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBkaXYuY3JlYXRlU3Bhbih7IHRleHQ6ICdOZXcgdmFsdWU6ICcgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGRpdi5jcmVhdGVTcGFuKHsgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0OiAnXCJDb21wbGV0ZWRcIicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHM6ICdzdGF0dXMtdXBkYXRlZC1uZXctdmFsdWUnXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UoYmFubmVyLCA1MDAwKTtcbiAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICBcbiAgICAgIGNvbnRhaW5lckVsLmNyZWF0ZUVsKCdoMycsIHt0ZXh0OiAnVHJvdWJsZXNob290aW5nJ30pO1xuICAgICAgXG4gICAgICBjb250YWluZXJFbC5jcmVhdGVFbCgncCcsIHtcbiAgICAgICAgICB0ZXh0OiAnSWYgdGhlIHBsdWdpbiBpcyBub3Qgd29ya2luZywgY2hlY2sgdGhlIGZvbGxvd2luZzonXG4gICAgICB9KTtcbiAgICAgIFxuICAgICAgY29uc3QgdHJvdWJsZXNob290aW5nTGlzdCA9IGNvbnRhaW5lckVsLmNyZWF0ZUVsKCd1bCcpO1xuICAgICAgXG4gICAgICB0cm91Ymxlc2hvb3RpbmdMaXN0LmNyZWF0ZUVsKCdsaScsIHtcbiAgICAgICAgICB0ZXh0OiAnRW5zdXJlIHRoZSBLYW5iYW4gcGx1Z2luIGlzIGluc3RhbGxlZCBhbmQgZW5hYmxlZCdcbiAgICAgIH0pO1xuICAgICAgXG4gICAgICB0cm91Ymxlc2hvb3RpbmdMaXN0LmNyZWF0ZUVsKCdsaScsIHtcbiAgICAgICAgICB0ZXh0OiAnVmVyaWZ5IHlvdXIgS2FuYmFuIGNhcmRzIGNvbnRhaW4gd2lraS1saW5rcyAoZS5nLiwgW1tOb3RlIFRpdGxlXV0pJ1xuICAgICAgfSk7XG4gICAgICBcbiAgICAgIHRyb3VibGVzaG9vdGluZ0xpc3QuY3JlYXRlRWwoJ2xpJywge1xuICAgICAgICAgIHRleHQ6ICdUcnkgZW5hYmxpbmcgRGVidWcgTW9kZSB0byBzZWUgZGV0YWlsZWQgbG9ncyBpbiB0aGUgZGV2ZWxvcGVyIGNvbnNvbGUgKEN0cmwrU2hpZnQrSSknXG4gICAgICB9KTtcbiAgfVxufVxuIl0sIm5hbWVzIjpbIlBsdWdpbiIsIk5vdGljZSIsInBhcnNlWWFtbCIsInN0cmluZ2lmeVlhbWwiLCJQbHVnaW5TZXR0aW5nVGFiIiwiU2V0dGluZyJdLCJtYXBwaW5ncyI6Ijs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFvR0E7QUFDTyxTQUFTLFNBQVMsQ0FBQyxPQUFPLEVBQUUsVUFBVSxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUU7QUFDN0QsSUFBSSxTQUFTLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxPQUFPLEtBQUssWUFBWSxDQUFDLEdBQUcsS0FBSyxHQUFHLElBQUksQ0FBQyxDQUFDLFVBQVUsT0FBTyxFQUFFLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUU7QUFDaEgsSUFBSSxPQUFPLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxPQUFPLENBQUMsRUFBRSxVQUFVLE9BQU8sRUFBRSxNQUFNLEVBQUU7QUFDL0QsUUFBUSxTQUFTLFNBQVMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO0FBQ25HLFFBQVEsU0FBUyxRQUFRLENB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