diff --git a/.obsidian/community-plugins.json b/.obsidian/community-plugins.json
index 076b7d2..9aada7c 100644
--- a/.obsidian/community-plugins.json
+++ b/.obsidian/community-plugins.json
@@ -1,4 +1,5 @@
[
"obsidian-dirtreeist",
- "obsidian-git"
+ "obsidian-git",
+ "number-headings-obsidian"
]
\ No newline at end of file
diff --git a/.obsidian/plugins/number-headings-obsidian/data.json b/.obsidian/plugins/number-headings-obsidian/data.json
new file mode 100644
index 0000000..071c717
--- /dev/null
+++ b/.obsidian/plugins/number-headings-obsidian/data.json
@@ -0,0 +1,13 @@
+{
+ "skipTopLevel": false,
+ "firstLevel": 1,
+ "maxLevel": 6,
+ "styleLevel1": "1",
+ "styleLevelOther": "1",
+ "auto": true,
+ "separator": ".",
+ "contents": "",
+ "skipHeadings": "",
+ "startAt": "",
+ "off": false
+}
\ No newline at end of file
diff --git a/.obsidian/plugins/number-headings-obsidian/main.js b/.obsidian/plugins/number-headings-obsidian/main.js
new file mode 100644
index 0000000..e49aad8
--- /dev/null
+++ b/.obsidian/plugins/number-headings-obsidian/main.js
@@ -0,0 +1,1136 @@
+/*
+THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
+if you want to view the source visit the plugins github repository
+*/
+
+'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;
+};
+
+function getActiveView(app) {
+ const activeView = app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ return activeView !== null && activeView !== void 0 ? activeView : undefined;
+}
+function isViewActive(app) {
+ const activeView = getActiveView(app);
+ if (activeView && activeView.file)
+ return true;
+ return false;
+}
+function getViewMetadata(app) {
+ const activeView = getActiveView(app);
+ if (activeView && activeView.file) {
+ const data = app.metadataCache.getFileCache(activeView.file) || {};
+ return data;
+ }
+ return undefined;
+}
+function getViewInfo(app) {
+ const activeView = getActiveView(app);
+ const data = getViewMetadata(app);
+ const editor = activeView ? activeView.editor : undefined;
+ if (activeView && data && editor) {
+ return {
+ activeView, data, editor
+ };
+ }
+ return undefined;
+}
+
+const roman_map = {
+ M: 1000,
+ CM: 900,
+ D: 500,
+ CD: 400,
+ C: 100,
+ XC: 90,
+ L: 50,
+ XL: 40,
+ X: 10,
+ IX: 9,
+ V: 5,
+ IV: 4,
+ I: 1
+};
+
+const allChars = Object.keys(roman_map);
+const allNumerals = Object.values(roman_map);
+const romanPattern =
+ /^(M{1,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})|M{0,4}(CM|C?D|D?C{1,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})|M{0,4}(CM|CD|D?C{0,3})(XC|X?L|L?X{1,3})(IX|IV|V?I{0,3})|M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|I?V|V?I{1,3}))$/;
+
+const romanize = (decimal) => {
+ if (
+ decimal <= 0 ||
+ typeof decimal !== 'number' ||
+ Math.floor(decimal) !== decimal
+ ) {
+ throw new Error('requires an unsigned integer')
+ }
+ if (decimal >= 4000) {
+ throw new Error('requires max value of less than 3999 or less')
+ }
+ let roman = '';
+ for (let i = 0; i < allChars.length; i++) {
+ while (decimal >= allNumerals[i]) {
+ decimal -= allNumerals[i];
+ roman += allChars[i];
+ }
+ }
+ return roman
+};
+
+const deromanize = (romanStr) => {
+ if (typeof romanStr !== 'string') {
+ throw new Error('requires a string')
+ }
+ if (!romanPattern.test(romanStr)) {
+ throw new Error('requires valid roman numeral string')
+ }
+ let romanString = romanStr.toUpperCase();
+ let arabic = 0;
+ let iteration = romanString.length;
+ while (iteration--) {
+ let cumulative = roman_map[romanString[iteration]];
+ if (cumulative < roman_map[romanString[iteration + 1]]) {
+ arabic -= cumulative;
+ } else {
+ arabic += cumulative;
+ }
+ }
+ return arabic
+};
+
+var romans = {
+ deromanize,
+ romanize,
+ allChars,
+ allNumerals
+};
+
+// Validates the string using a regex to ensure is is a valid arabic numbering value
+function isValidArabicNumberingValueString(s) {
+ const regex = /^[0-9]+$/;
+ return regex.test(s);
+}
+// Validates the string using a regex to ensure is is a valid alphabet numbering value
+function isValidAlphabetNumberingValueString(s) {
+ const regex = /^[A-Z]$/;
+ return regex.test(s);
+}
+// Validates the string using a regex to ensure is is a valid roman numbering value
+function isValidRomanNumberingValueString(s) {
+ const regex = /^[0IVXLCDM]+$/; // This includes zero for zeroth testing
+ return regex.test(s);
+}
+function printableNumberingToken(t) {
+ switch (t.style) {
+ case '1':
+ return t.value.toString();
+ case 'A':
+ return t.value;
+ case 'I':
+ return t.value;
+ }
+}
+function zerothNumberingTokenInStyle(style) {
+ switch (style) {
+ case '1':
+ return { style: '1', value: 0 };
+ case 'A':
+ return { style: 'A', value: 'Z' };
+ case 'I':
+ return { style: 'I', value: '0' };
+ }
+}
+function firstNumberingTokenInStyle(style) {
+ switch (style) {
+ case '1':
+ return { style: '1', value: 1 };
+ case 'A':
+ return { style: 'A', value: 'A' };
+ case 'I':
+ return { style: 'I', value: 'I' };
+ }
+}
+function nextNumberingToken(t) {
+ switch (t.style) {
+ case '1':
+ return { style: '1', value: t.value + 1 };
+ case 'A':
+ if (t.value === 'Z')
+ return { style: 'A', value: 'A' };
+ else
+ return { style: 'A', value: String.fromCharCode(t.value.charCodeAt(0) + 1) };
+ case 'I':
+ if (t.value === '0')
+ return { style: 'I', value: 'I' };
+ else
+ return { style: 'I', value: romans.romanize(romans.deromanize(t.value) + 1) };
+ }
+}
+function previousNumberingToken(t) {
+ switch (t.style) {
+ case '1':
+ return { style: '1', value: t.value - 1 };
+ case 'A':
+ if (t.value === 'A')
+ return { style: 'A', value: 'Z' };
+ else
+ return { style: 'A', value: String.fromCharCode(t.value.charCodeAt(0) - 1) };
+ case 'I':
+ if (t.value === 'I')
+ return { style: 'I', value: '0' };
+ else
+ return { style: 'I', value: romans.romanize(romans.deromanize(t.value) - 1) };
+ }
+}
+function makeNumberingString(numberingStack) {
+ let numberingString = '';
+ for (let i = 0; i < numberingStack.length; i++) {
+ if (i === 0) {
+ numberingString += ' ';
+ }
+ else {
+ numberingString += '.';
+ }
+ numberingString += printableNumberingToken(numberingStack[i]);
+ }
+ return numberingString;
+}
+function startAtOrZerothInStyle(startAtSettingString, style) {
+ if (startAtSettingString === '')
+ return zerothNumberingTokenInStyle(style);
+ let firstNumberingTokenFromSetting;
+ switch (style) {
+ case '1':
+ if (!isValidArabicNumberingValueString(startAtSettingString))
+ return zerothNumberingTokenInStyle(style);
+ firstNumberingTokenFromSetting = { style: '1', value: parseInt(startAtSettingString) };
+ break;
+ case 'A':
+ if (!isValidAlphabetNumberingValueString(startAtSettingString))
+ return zerothNumberingTokenInStyle(style);
+ firstNumberingTokenFromSetting = { style: 'A', value: startAtSettingString };
+ break;
+ case 'I':
+ if (!isValidRomanNumberingValueString(startAtSettingString))
+ return zerothNumberingTokenInStyle(style);
+ firstNumberingTokenFromSetting = { style: 'I', value: startAtSettingString };
+ break;
+ }
+ // Convert the first numbering token to a zeroth numbering token
+ return previousNumberingToken(firstNumberingTokenFromSetting);
+}
+
+const DEFAULT_SETTINGS = {
+ skipTopLevel: false,
+ firstLevel: 1,
+ maxLevel: 6,
+ styleLevel1: '1',
+ styleLevelOther: '1',
+ auto: false,
+ separator: '',
+ contents: '',
+ skipHeadings: '',
+ startAt: '',
+ off: false
+};
+function isValidNumberingStyleString(s) {
+ if (s === 'A' || s === '1' || s === 'I')
+ return true;
+ return false;
+}
+function isValidNumberingValueString(s) {
+ if (s === '' || isValidArabicNumberingValueString(s) || isValidAlphabetNumberingValueString(s) || isValidRomanNumberingValueString(s))
+ return true;
+ return false;
+}
+function isValidFlag(f) {
+ if (f === true || f === false)
+ return true;
+ return false;
+}
+function isValidFirstOrMaxLevel(x) {
+ if (typeof x === 'number' && x >= 1 && x <= 6)
+ return true;
+ return false;
+}
+function isValidSeparator(x) {
+ return typeof x === 'string' &&
+ (x === '' ||
+ x === ':' || x === ' :' ||
+ x === '.' || x === ' .' ||
+ x === '-' || x === ' -' ||
+ x === '—' || x === ' —' || /* em-dash */
+ x === ')' || x === ' )');
+}
+function isValidBlockIdSetting(x) {
+ if (typeof x === 'string' && (x === '' || x.startsWith('^')))
+ return true;
+ return false;
+}
+function isNonEmptyBlockId(x) {
+ if (x.length > 2 && x.startsWith('^'))
+ return true;
+ return false;
+}
+
+function createSupportFlagsFromSettings(styleLevel1, styleLevelOther) {
+ return {
+ alphabet: styleLevel1 === 'A' || styleLevelOther === 'A',
+ roman: styleLevel1 === 'I' || styleLevelOther === 'I'
+ };
+}
+// Get the regex for the header string, based on the support flags. The generated regex is used to find the range of the header prefix.
+// The regex is generated dynamically, because the regex is different depending on the support flags.
+function getRegexForHeaderString(flags) {
+ if (flags.alphabet && flags.roman) {
+ // Regex to match the heading prefix, including the space after the hash(es), but not the heading text
+ return /^\s{0,4}#+( )?([0-9]+\.|[A-Z]\.|[IVXLCDM]+\.)*([0-9]+|[A-Z]|[IVXLCDM]+)?( )?[)—:.-]?( )+/g;
+ }
+ else if (!flags.alphabet && flags.roman) {
+ // Regex to match the heading prefix, including the space after the hash(es), but not the heading text
+ return /^\s{0,4}#+( )?([0-9]+\.|[IVXLCDM]+\.)*([0-9]+|[IVXLCDM]+)?( )?[)—:.-]?( )+/g;
+ }
+ else if (flags.alphabet && !flags.roman) {
+ // Regex to match the heading prefix, including the space after the hash(es), but not the heading text
+ return /^\s{0,4}#+( )?([0-9]+\.|[A-Z]\.)*([0-9]+|[A-Z])?( )?[)—:.-]?( )+/g;
+ }
+ else if (!flags.alphabet && !flags.roman) {
+ // Regex to match the heading prefix, including the space after the hash(es), but not the heading text
+ return /^\s{0,4}#+( )?([0-9]+\.)*([0-9]+)?( )?[)—:.-]?( )+/g;
+ }
+ throw new Error('Unexpected combination of support flags');
+}
+// Find the range of the heading prefix, including the space after any numbering, but not the heading text
+function findRangeInHeaderString(lineText, lineNumber, flags) {
+ const regex = getRegexForHeaderString(flags);
+ if (!lineText)
+ return undefined;
+ const matches = lineText.match(regex);
+ if (matches && matches.length !== 1) {
+ // eslint-disable-next-line no-console
+ console.log("Unexpected heading format: '" + lineText + "'");
+ return undefined;
+ }
+ const match = matches ? matches[0] : '';
+ const from = {
+ line: lineNumber,
+ ch: 0
+ };
+ const to = {
+ line: lineNumber,
+ ch: match.length
+ };
+ return { from, to };
+}
+function updateSettingsFromFrontMatterFormatPart(part, settings) {
+ // Parse the separator
+ let partWithoutSeparator = part;
+ const potentialTwoCharSeparator = part.slice(-2);
+ if (isValidSeparator(potentialTwoCharSeparator)) {
+ settings.separator = potentialTwoCharSeparator;
+ partWithoutSeparator = part.slice(0, -2);
+ }
+ else {
+ const potentialOneCharSeparator = part.slice(-1);
+ if (isValidSeparator(potentialOneCharSeparator)) {
+ settings.separator = potentialOneCharSeparator;
+ partWithoutSeparator = part.slice(0, -1);
+ }
+ else {
+ settings.separator = '';
+ }
+ }
+ // Parse the numbering style
+ const descriptors = partWithoutSeparator.split('.');
+ let firstNumberedDescriptor = 0;
+ // Handle the case where the first descriptor is an underscore
+ if (descriptors.length > 1 && descriptors[0] === '_') {
+ // The first descriptor is an instruction to skip top levels, so skip them
+ settings.skipTopLevel = true;
+ firstNumberedDescriptor = 1;
+ }
+ else {
+ settings.skipTopLevel = false;
+ }
+ if (descriptors.length - firstNumberedDescriptor >= 2) {
+ const styleLevel1 = descriptors[firstNumberedDescriptor];
+ if (isValidNumberingStyleString(styleLevel1)) {
+ settings.styleLevel1 = styleLevel1;
+ }
+ const styleLevelOther = descriptors[firstNumberedDescriptor + 1];
+ if (isValidNumberingStyleString(styleLevelOther)) {
+ settings.styleLevelOther = styleLevelOther;
+ }
+ }
+ return settings;
+}
+
+const AUTO_PART_KEY = 'auto';
+const FIRST_LEVEL_PART_KEY = 'first-level';
+const MAX_LEVEL_PART_KEY = 'max';
+const CONTENTS_PART_KEY = 'contents';
+const SKIP_PART_KEY = 'skip';
+const START_AT_PART_KEY = 'start-at';
+const OFF_PART_KEY = 'off';
+function parseCompactFrontMatterSettings(fm) {
+ const entry = obsidian.parseFrontMatterEntry(fm, 'number headings');
+ if (entry) {
+ const entryString = String(entry);
+ const parts = entryString.split(',');
+ let settings = Object.assign({}, DEFAULT_SETTINGS);
+ for (const part of parts) {
+ const trimmedPart = part.trim();
+ if (trimmedPart.length === 0)
+ continue;
+ if (trimmedPart === OFF_PART_KEY) {
+ // Parse off part
+ settings.off = true;
+ }
+ else if (trimmedPart === AUTO_PART_KEY) {
+ // Parse auto numbering part
+ settings.auto = true;
+ }
+ else if (trimmedPart.startsWith(FIRST_LEVEL_PART_KEY)) {
+ // Parse first level part
+ const nstring = trimmedPart.substring(FIRST_LEVEL_PART_KEY.length + 1);
+ const n = parseInt(nstring);
+ if (isValidFirstOrMaxLevel(n)) {
+ settings.firstLevel = n;
+ }
+ }
+ else if (trimmedPart.startsWith(MAX_LEVEL_PART_KEY)) {
+ // Parse max level part
+ const nstring = trimmedPart.substring(MAX_LEVEL_PART_KEY.length + 1);
+ const n = parseInt(nstring);
+ if (isValidFirstOrMaxLevel(n)) {
+ settings.maxLevel = n;
+ }
+ }
+ else if (trimmedPart.startsWith(START_AT_PART_KEY)) {
+ // Parse "start at" part
+ const value = trimmedPart.substring(START_AT_PART_KEY.length + 1);
+ if (isValidNumberingValueString(value)) {
+ settings.startAt = value;
+ }
+ }
+ else if (trimmedPart.startsWith(CONTENTS_PART_KEY)) {
+ if (trimmedPart.length <= CONTENTS_PART_KEY.length + 1)
+ continue;
+ // Parse contents heading part
+ const tocHeadingBlockIdName = trimmedPart.substring(CONTENTS_PART_KEY.length + 1);
+ if (isValidBlockIdSetting(tocHeadingBlockIdName)) {
+ settings.contents = tocHeadingBlockIdName;
+ }
+ }
+ else if (trimmedPart.startsWith(SKIP_PART_KEY)) {
+ if (trimmedPart.length <= SKIP_PART_KEY.length + 1)
+ continue;
+ // Parse skip heading part
+ const skipHeadingBlockIdName = trimmedPart.substring(SKIP_PART_KEY.length + 1);
+ if (isValidBlockIdSetting(skipHeadingBlockIdName)) {
+ settings.skipHeadings = skipHeadingBlockIdName;
+ }
+ }
+ else {
+ // Parse formatting part
+ settings = updateSettingsFromFrontMatterFormatPart(trimmedPart, settings);
+ }
+ }
+ return settings;
+ }
+ return undefined;
+}
+const getFrontMatterSettingsOrAlternative = ({ frontmatter }, alternativeSettings) => {
+ var _a, _b, _c, _d, _e;
+ if (frontmatter !== undefined) {
+ const decompactedSettings = parseCompactFrontMatterSettings(frontmatter);
+ if (decompactedSettings !== undefined)
+ return decompactedSettings;
+ // NOTE: Everything below is for backwards compatibility only
+ const skipTopLevelEntry = (_a = obsidian.parseFrontMatterEntry(frontmatter, 'number-headings-skip-top-level')) !== null && _a !== void 0 ? _a : obsidian.parseFrontMatterEntry(frontmatter, 'header-numbering-skip-top-level');
+ const skipTopLevel = isValidFlag(skipTopLevelEntry) ? skipTopLevelEntry : alternativeSettings.skipTopLevel;
+ const maxLevelEntry = (_b = obsidian.parseFrontMatterEntry(frontmatter, 'number-headings-max-level')) !== null && _b !== void 0 ? _b : obsidian.parseFrontMatterEntry(frontmatter, 'header-numbering-max-level');
+ const maxLevel = isValidFirstOrMaxLevel(maxLevelEntry) ? maxLevelEntry : alternativeSettings.maxLevel;
+ const styleLevel1Entry = String((_c = obsidian.parseFrontMatterEntry(frontmatter, 'number-headings-style-level-1')) !== null && _c !== void 0 ? _c : obsidian.parseFrontMatterEntry(frontmatter, 'header-numbering-style-level-1'));
+ const styleLevel1 = isValidNumberingStyleString(styleLevel1Entry) ? styleLevel1Entry : alternativeSettings.styleLevel1;
+ const styleLevelOtherEntry = String((_d = obsidian.parseFrontMatterEntry(frontmatter, 'number-headings-style-level-other')) !== null && _d !== void 0 ? _d : obsidian.parseFrontMatterEntry(frontmatter, 'header-numbering-style-level-other'));
+ const styleLevelOther = isValidNumberingStyleString(styleLevelOtherEntry) ? styleLevelOtherEntry : alternativeSettings.styleLevelOther;
+ const autoEntry = (_e = obsidian.parseFrontMatterEntry(frontmatter, 'number-headings-auto')) !== null && _e !== void 0 ? _e : obsidian.parseFrontMatterEntry(frontmatter, 'header-numbering-auto');
+ const auto = isValidFlag(autoEntry) ? autoEntry : alternativeSettings.auto;
+ return Object.assign(Object.assign({}, alternativeSettings), { skipTopLevel, maxLevel, styleLevel1, styleLevelOther, auto });
+ }
+ else {
+ return alternativeSettings;
+ }
+};
+function settingsToCompactFrontMatterValue(settings) {
+ if (settings.off)
+ return OFF_PART_KEY;
+ const autoPart = settings.auto ? 'auto, ' : '';
+ const firstLevelPart = `first-level ${settings.firstLevel}, `;
+ const maxPart = `max ${settings.maxLevel}, `;
+ const contentsPart = settings.contents && settings.contents.length > 0 ? `contents ${settings.contents}, ` : '';
+ const skipHeadingsPart = settings.skipHeadings && settings.skipHeadings.length > 0 ? `skip ${settings.skipHeadings}, ` : '';
+ const skipTopLevelString = settings.skipTopLevel ? '_.' : '';
+ const stylePart = `${skipTopLevelString}${settings.styleLevel1}.${settings.styleLevelOther}${settings.separator}`;
+ const startAtPart = settings.startAt !== '' ? `start-at ${settings.startAt}, ` : '';
+ return autoPart + firstLevelPart + maxPart + contentsPart + skipHeadingsPart + startAtPart + stylePart;
+}
+const saveSettingsToFrontMatter = (fileManager, file, settings) => {
+ fileManager.processFrontMatter(file, frontmatter => {
+ const v = settingsToCompactFrontMatterValue(settings);
+ frontmatter['number headings'] = v;
+ });
+};
+
+class NumberingDoneModal extends obsidian.Modal {
+ constructor(app, config) {
+ super(app);
+ this.config = config;
+ }
+ onOpen() {
+ const { contentEl, titleEl } = this;
+ titleEl.setText('Number Headings - Successfully Completed');
+ contentEl.createEl('div', { text: this.config.message });
+ contentEl.createEl('pre', { text: this.config.preformattedMessage });
+ contentEl.createEl('div', { text: "Do you want to save these settings in the document's front matter?", cls: 'number-headings-question' });
+ const containerForButtons = contentEl.createEl('div', { cls: 'number-headings-button-container' });
+ const noButton = containerForButtons.createEl('button', {});
+ noButton.setText('No');
+ noButton.onClickEvent((ev) => {
+ this.close();
+ return ev;
+ });
+ const yesButton = containerForButtons.createEl('button', {});
+ yesButton.setText('Yes, save settings in document');
+ yesButton.onClickEvent((ev) => {
+ this.config.saveSettingsCallback(false);
+ this.close();
+ return ev;
+ });
+ const yesAndAutoButton = containerForButtons.createEl('button', {});
+ yesAndAutoButton.setText('Yes, save settings in document, and automatically number');
+ yesAndAutoButton.onClickEvent((ev) => {
+ this.config.saveSettingsCallback(true);
+ this.close();
+ return ev;
+ });
+ }
+ onClose() {
+ const { contentEl, titleEl } = this;
+ contentEl.empty();
+ titleEl.empty();
+ }
+}
+function showNumberingDoneMessage(app, settings) {
+ const saveSettingsCallback = (shouldAddAutoFlag) => {
+ const tweakedSettings = Object.assign({}, settings);
+ if (shouldAddAutoFlag)
+ tweakedSettings.auto = true;
+ const file = app.workspace.getActiveFile();
+ if (file) {
+ saveSettingsToFrontMatter(app.fileManager, file, tweakedSettings);
+ }
+ };
+ const config = {
+ message: `Successfully updated all heading numbers in the document, using the settings below.
+ See settings panel to change how headings are numbered, or use front matter
+ (see settings panel).`,
+ preformattedMessage: `Skip top heading level: ${settings.skipTopLevel}
+First heading level: ${settings.firstLevel}
+Start numbering first heading at: ${settings.startAt}
+Maximum heading level: ${settings.maxLevel}
+Style for level 1 headings: ${settings.styleLevel1}
+Style for lower level headings (below level 1): ${settings.styleLevelOther}
+Separator: ${settings.separator}
+Table of Contents Anchor: ${settings.contents}
+Skip Headings Anchor: ${settings.skipHeadings}`,
+ saveSettingsCallback
+ };
+ const leaf = app.workspace.activeLeaf;
+ if (leaf) {
+ new NumberingDoneModal(app, config).open();
+ }
+}
+
+const TOC_LIST_ITEM_BULLET = '-';
+function makeHeadingHashString(editor, heading) {
+ const regex = /^\s{0,4}#+/g;
+ const headingLineString = editor.getLine(heading.position.start.line);
+ if (!headingLineString)
+ return undefined;
+ const matches = headingLineString.match(regex);
+ if (!matches)
+ return undefined;
+ if (matches.length !== 1) {
+ // eslint-disable-next-line no-console
+ console.log("Unexpected heading format: '" + headingLineString + "'");
+ return undefined;
+ }
+ const match = matches[0];
+ return match.trimLeft();
+}
+function findHeadingPrefixRange(editor, heading, flags) {
+ const lineNumber = heading.position.start.line;
+ const lineText = editor.getLine(lineNumber);
+ return findRangeInHeaderString(lineText, lineNumber, flags);
+}
+function cleanHeadingTextForToc(htext) {
+ if (htext.contains('^')) {
+ const x = htext.split('^');
+ if (x.length > 1) {
+ return x[0].trim();
+ }
+ }
+ return htext.trim();
+}
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+function createTocEntry(h, settings, initialHeadingLevel) {
+ const text = h.heading;
+ const cleanText = cleanHeadingTextForToc(text);
+ let bulletIndent = '';
+ const startLevel = initialHeadingLevel;
+ for (let i = startLevel; i < h.level; i++) {
+ bulletIndent += '\t';
+ }
+ const entryLink = `[[#${text}|${cleanText}]]`;
+ return bulletIndent + TOC_LIST_ITEM_BULLET + ' ' + entryLink;
+}
+// Replace a range, but only if there is a change in text, to prevent poluting the undo stack
+function replaceRangeEconomically(editor, changes, range, text) {
+ const previousText = editor.getRange(range.from, range.to);
+ if (previousText !== text) {
+ changes.push({
+ text: text,
+ from: range.from,
+ to: range.to
+ });
+ }
+}
+const updateHeadingNumbering = (viewInfo, settings) => {
+ var _a;
+ if (!viewInfo)
+ return;
+ const headings = (_a = viewInfo.data.headings) !== null && _a !== void 0 ? _a : [];
+ const editor = viewInfo.editor;
+ const supportFlags = createSupportFlagsFromSettings(settings.styleLevel1, settings.styleLevelOther);
+ let previousLevel = 1;
+ let numberingStack = [startAtOrZerothInStyle(settings.startAt, settings.styleLevel1)];
+ if (settings.firstLevel > 1) {
+ previousLevel = settings.firstLevel;
+ }
+ else if (settings.skipTopLevel) {
+ previousLevel = 2;
+ }
+ const changes = [];
+ for (const heading of headings) {
+ // Update the numbering stack based on the level and previous level
+ const level = heading.level;
+ // Handle skipped & ignored levels.
+ if ((settings.firstLevel > level) || (settings.skipTopLevel && level === 1)) {
+ // Resets the numbering when a level is skipped.
+ // Note: This leaves headings as they are, allowing people to have numbers at the start of
+ // ignored headings.
+ numberingStack = [startAtOrZerothInStyle(settings.startAt, settings.styleLevel1)];
+ if (settings.firstLevel > 1) {
+ previousLevel = settings.firstLevel;
+ }
+ else if (settings.skipTopLevel) {
+ previousLevel = 2;
+ }
+ continue;
+ }
+ // Handle skipped headings
+ if (settings.skipHeadings.length > 0) {
+ if (heading.heading.endsWith(settings.skipHeadings)) {
+ continue;
+ }
+ }
+ // Adjust numbering stack
+ if (level === previousLevel) {
+ const x = numberingStack.pop();
+ if (x !== undefined) {
+ numberingStack.push(nextNumberingToken(x));
+ }
+ }
+ else if (level < previousLevel) {
+ for (let i = previousLevel; i > level; i--) {
+ numberingStack.pop();
+ }
+ const x = numberingStack.pop();
+ if (x !== undefined) {
+ numberingStack.push(nextNumberingToken(x));
+ }
+ }
+ else if (level > previousLevel) {
+ for (let i = previousLevel; i < level; i++) {
+ numberingStack.push(firstNumberingTokenInStyle(settings.styleLevelOther));
+ }
+ }
+ // Set the previous level to this level for the next iteration
+ previousLevel = level;
+ if (level > settings.maxLevel) {
+ // If we are above the max level, just don't number it
+ continue;
+ }
+ // Find the range to replace, and then do it
+ const prefixRange = findHeadingPrefixRange(editor, heading, supportFlags);
+ if (prefixRange === undefined)
+ return;
+ const headingHashString = makeHeadingHashString(editor, heading);
+ if (headingHashString === undefined)
+ return;
+ const prefixString = makeNumberingString(numberingStack);
+ replaceRangeEconomically(editor, changes, prefixRange, headingHashString + prefixString + settings.separator + ' ');
+ }
+ // Execute the transaction to make all the changes at once
+ if (changes.length > 0) {
+ // eslint-disable-next-line no-console
+ console.log('Number Headings Plugin: Applying headings numbering changes:', changes.length);
+ editor.transaction({
+ changes: changes
+ });
+ }
+};
+const updateTableOfContents = (viewInfo, settings) => {
+ var _a;
+ if (!viewInfo)
+ return;
+ const headings = (_a = viewInfo.data.headings) !== null && _a !== void 0 ? _a : [];
+ const editor = viewInfo.editor;
+ if (!isNonEmptyBlockId(settings.contents))
+ return;
+ let tocHeading;
+ let tocBuilder = '\n';
+ const changes = [];
+ // In case headings start above level 1, we don't want to indent the bullets too much
+ let initialHeadingLevel = 1;
+ if (headings.length > 0) {
+ initialHeadingLevel = headings[0].level;
+ }
+ for (const heading of headings) {
+ // ORDERING: Important to find the TOC heading before skipping skipped headings, since that is for numbering
+ // Find the TOC heading
+ if (heading.heading.endsWith(settings.contents)) {
+ tocHeading = heading;
+ }
+ /* This code lets us skip TOC lines for skipped headings, but doesn't work well with first-level setting
+ if ((settings.skipTopLevel && heading.level === 1) || (heading.level > settings.maxLevel)) {
+ continue
+ }
+ */
+ const tocEntry = createTocEntry(heading, settings, initialHeadingLevel);
+ tocBuilder += tocEntry + '\n';
+ }
+ // Insert the generated table of contents
+ if (tocHeading) {
+ const from = {
+ line: tocHeading.position.start.line + 1,
+ ch: 0
+ };
+ // Find the end of the TOC section
+ const startingLine = tocHeading.position.start.line + 1;
+ let endingLine = startingLine;
+ let foundList = false;
+ const lastLineInEditor = editor.lastLine();
+ for (;; endingLine++) {
+ const line = editor.getLine(endingLine);
+ if (line === undefined || endingLine > lastLineInEditor) {
+ // Reached end of file, insert at the start of the TOC section
+ endingLine = startingLine;
+ break;
+ }
+ const trimmedLineText = line.trimStart();
+ if (foundList) {
+ if (!trimmedLineText.startsWith(TOC_LIST_ITEM_BULLET))
+ break;
+ if (trimmedLineText.startsWith('#'))
+ break;
+ }
+ else {
+ if (trimmedLineText.startsWith(TOC_LIST_ITEM_BULLET)) {
+ foundList = true;
+ }
+ else if (trimmedLineText.startsWith('#')) {
+ // Reached the next heading without finding existing TOC list, insert at the start of the TOC section
+ endingLine = startingLine;
+ break;
+ }
+ else {
+ continue;
+ }
+ }
+ }
+ if (tocBuilder === '\n') {
+ tocBuilder = '';
+ }
+ const to = {
+ line: endingLine,
+ ch: 0
+ };
+ const range = { from, to };
+ replaceRangeEconomically(editor, changes, range, tocBuilder);
+ }
+ // Execute the transaction to make all the changes at once
+ if (changes.length > 0) {
+ // eslint-disable-next-line no-console
+ console.log('Number Headings Plugin: Applying table of contents changes:', changes.length);
+ editor.transaction({
+ changes: changes
+ });
+ }
+};
+const removeHeadingNumbering = (viewInfo) => {
+ var _a;
+ if (!viewInfo)
+ return;
+ const headings = (_a = viewInfo.data.headings) !== null && _a !== void 0 ? _a : [];
+ const editor = viewInfo.editor;
+ const changes = [];
+ for (const heading of headings) {
+ const prefixRange = findHeadingPrefixRange(editor, heading, { alphabet: true, roman: true });
+ if (prefixRange === undefined)
+ return;
+ const headingHashString = makeHeadingHashString(editor, heading);
+ if (headingHashString === undefined)
+ return;
+ replaceRangeEconomically(editor, changes, prefixRange, headingHashString + ' ');
+ }
+ if (changes.length > 0) {
+ editor.transaction({
+ changes: changes
+ });
+ }
+};
+
+class NumberHeadingsPluginSettingTab extends obsidian.PluginSettingTab {
+ constructor(app, plugin) {
+ super(app, plugin);
+ this.plugin = plugin;
+ }
+ display() {
+ const { containerEl } = this;
+ containerEl.empty();
+ containerEl.createEl('h2', { text: 'Number Headings - Settings' });
+ containerEl.createEl('div', { text: 'To add numbering to your document, bring up the command window (on Mac, type CMD+P), and then type "Number Headings" to see a list of available commands.' });
+ containerEl.createEl('br', {});
+ containerEl.createEl('div', { text: 'If the document has front matter defined with the below settings, the project-wide settings defined on this screen will be ignored. You can define front matter like this:' });
+ containerEl.createEl('pre', {
+ text: ` ---
+ alias:
+ - Example Alias
+ tags:
+ - example-tag
+ number headings: first-level 1, start-at 2, max 6, 1.1, auto, contents ^toc
+ ---`
+ });
+ containerEl.createEl('div', {
+ text: `
+ The 'number headings' front matter key is used to store numbering settings specific to the file. There are four possible options
+ in the value to the right of the colon, separated by commas.
+ `
+ });
+ const ul = containerEl.createEl('ul', {});
+ const li0 = ul.createEl('li', {});
+ li0.createEl('b', { text: 'Automatic numbering' });
+ li0.createEl('span', { text: ': If \'auto\' appears, the document will be automatically numbered.' });
+ const li1 = ul.createEl('li', {});
+ li1.createEl('b', { text: 'First level to number' });
+ li1.createEl('span', { text: ': If \'first-level 2\' appears, the numbering will start at the second level' });
+ const li2 = ul.createEl('li', {});
+ li2.createEl('b', { text: 'Start numbering first heading at' });
+ li2.createEl('span', { text: ': If \'start-at C\' appears, the numbering of the first level will start at C, instead of A' });
+ const li3 = ul.createEl('li', {});
+ li3.createEl('b', { text: 'Maximum level to number' });
+ li3.createEl('span', { text: ': If \'max 6\' appears, the headings above level 6 will be skipped.' });
+ const li4 = ul.createEl('li', {});
+ li4.createEl('b', { text: 'Table of contents anchor' });
+ li4.createEl('span', { text: ': If \'contents ^toc\' appears, the heading that ends with the anchor ^toc will have a table of contents inserted beneath it.' });
+ const li41 = ul.createEl('li', {});
+ li41.createEl('b', { text: 'Skip headings anchor' });
+ li41.createEl('span', { text: ': If \'skip ^skipped\' appears, the heading that ends with the anchor ^skipped will not be numbered.' });
+ const li5 = ul.createEl('li', {});
+ li5.createEl('b', { text: 'Numbering style' });
+ li5.createEl('span', {
+ text: `:
+ A style text like '1.1', 'A.1', or '_.1.1' tells the plugin how to format the headings.
+ If a style string ends with '.' (a dot), ':' (a colon), '-' (a dash), '—' (an emdash), or ')' (a right parenthesis), the heading numbers will be separated from the heading title
+ with that symbol.`
+ });
+ const ul3 = li5.createEl('ul', {});
+ ul3.createEl('li', {
+ text: `
+ For example, '1.1' means both top level and other headings will be numbered starting from '1'.
+ `
+ });
+ ul3.createEl('li', {
+ text: `
+ For example, 'A.1' means top level headings will be numbered starting from 'A'.
+ `
+ });
+ ul3.createEl('li', {
+ text: `
+ For example, '_.A.1' means top level headings will NOT be numbered, but the next levels will be numbered with letters and numbers.
+ `
+ });
+ ul3.createEl('li', {
+ text: `
+ For example, '1.1:' means headings will look like '## 2.4: Example Heading'
+ `
+ });
+ ul3.createEl('li', {
+ text: `
+ For example, 'A.1-' means headings will look like '## B.5- Example Heading'
+ `
+ });
+ ul3.createEl('li', {
+ text: `
+ For example, 'I.A —' means headings will look like '## IV.A — Example Heading' (with Roman numerals)
+ `
+ });
+ const li100 = ul.createEl('li', {});
+ li100.createEl('b', { text: 'Numbering off' });
+ li100.createEl('span', { text: ': If \'off\' appears, the document will not be numbered.' });
+ new obsidian.Setting(containerEl)
+ .setName('Skip top heading level')
+ .setDesc('If selected, numbering will not be applied to the top heading level.')
+ .addToggle(toggle => toggle
+ .setValue(this.plugin.settings.skipTopLevel)
+ .setTooltip('Skip top heading level')
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.skipTopLevel = value;
+ yield this.plugin.saveSettings();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('First heading level')
+ .setDesc('First heading level to number.')
+ .addSlider(slider => slider
+ .setLimits(1, 6, 1)
+ .setValue(this.plugin.settings.firstLevel)
+ .setDynamicTooltip()
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.firstLevel = value;
+ yield this.plugin.saveSettings();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Start numbering at')
+ .setDesc('Start numbering the first heading level from this value.')
+ .addText(text => text
+ .setValue(this.plugin.settings.startAt)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.startAt = value;
+ yield this.plugin.saveSettings();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Maximum heading level')
+ .setDesc('Maximum heading level to number.')
+ .addSlider(slider => slider
+ .setLimits(1, 6, 1)
+ .setValue(this.plugin.settings.maxLevel)
+ .setDynamicTooltip()
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.maxLevel = value;
+ yield this.plugin.saveSettings();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Style for level 1 headings')
+ .setDesc('Defines the numbering style for level one headings. Valid values are 1 (for numbers) or A (for capital letters) or I (for Roman numerals).')
+ .addText(text => text
+ .setValue(this.plugin.settings.styleLevel1)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.styleLevel1 = value;
+ yield this.plugin.saveSettings();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Style for lower level headings (below level 1)')
+ .setDesc('Defines the numbering style for headings below level one. Valid values are 1 (for numbers) or A (for capital letters) or I (for Roman numerals).')
+ .addText(text => text
+ .setValue(this.plugin.settings.styleLevelOther)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.styleLevelOther = value;
+ yield this.plugin.saveSettings();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Automatic numbering')
+ .setDesc('Turns on automatic numbering of documents.')
+ .addToggle(toggle => toggle
+ .setValue(this.plugin.settings.auto)
+ .setTooltip('Turn on automatic numbering')
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.auto = value;
+ yield this.plugin.saveSettings();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Separator style')
+ .setDesc('Defines the separator style between the heading number and the heading text. Valid values are : (colon) or . (dot) or - (dash) or — (emdash) or ) (a right parenthesis). You can also leave it blank for no separator, or have a space before the separator.')
+ .addText(text => text
+ .setValue(this.plugin.settings.separator)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.separator = value;
+ yield this.plugin.saveSettings();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Table of Contents Anchor')
+ .setDesc('Anchor which labels the header where a table of contents should be inserted. The anchor should be added at the end of a header. For example, ^toc.')
+ .addText(text => text
+ .setValue(this.plugin.settings.contents)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.contents = value;
+ yield this.plugin.saveSettings();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Skip Headings Anchor')
+ .setDesc('Anchor which labels the headers that should not be numbered. The anchor should be added at the end of a header. For example, ^skipped.')
+ .addText(text => text
+ .setValue(this.plugin.settings.skipHeadings)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.skipHeadings = value;
+ yield this.plugin.saveSettings();
+ })));
+ }
+}
+class NumberHeadingsPlugin extends obsidian.Plugin {
+ onload() {
+ return __awaiter(this, void 0, void 0, function* () {
+ // eslint-disable-next-line no-console
+ console.info('Loading Number Headings Plugin, version ' + this.manifest.version);
+ yield this.loadSettings();
+ this.addCommand({
+ id: 'number-headings-with-options',
+ name: 'Number all headings in document (and show options)',
+ checkCallback: (checking) => {
+ if (checking)
+ return isViewActive(this.app);
+ const viewInfo = getViewInfo(this.app);
+ if (viewInfo) {
+ const settings = getFrontMatterSettingsOrAlternative(viewInfo.data, this.settings);
+ if (settings.off)
+ return false;
+ updateHeadingNumbering(viewInfo, settings);
+ setTimeout(() => {
+ // HACK: This must happen after a timeout so that there is time for the editor transaction to complete
+ const postNumberingViewInfo = getViewInfo(this.app);
+ updateTableOfContents(postNumberingViewInfo, settings);
+ }, 3000);
+ showNumberingDoneMessage(this.app, settings);
+ }
+ return false;
+ }
+ });
+ this.addCommand({
+ id: 'number-headings',
+ name: 'Number all headings in document',
+ checkCallback: (checking) => {
+ if (checking)
+ return isViewActive(this.app);
+ const viewInfo = getViewInfo(this.app);
+ if (viewInfo) {
+ const settings = getFrontMatterSettingsOrAlternative(viewInfo.data, this.settings);
+ if (settings.off)
+ return false;
+ updateHeadingNumbering(viewInfo, settings);
+ setTimeout(() => {
+ // HACK: This must happen after a timeout so that there is time for the editor transaction to complete
+ const postNumberingViewInfo = getViewInfo(this.app);
+ updateTableOfContents(postNumberingViewInfo, settings);
+ }, 3000);
+ // NOTE: The line below is intentionally commented out, since this command is the same as
+ // the above command, except for this line
+ // showNumberingDoneMessage(this.app, settings, viewInfo)
+ }
+ return false;
+ }
+ });
+ this.addCommand({
+ id: 'remove-number-headings',
+ name: 'Remove numbering from all headings in document',
+ checkCallback: (checking) => {
+ if (checking)
+ return isViewActive(this.app);
+ const viewInfo = getViewInfo(this.app);
+ removeHeadingNumbering(viewInfo);
+ return true;
+ }
+ });
+ this.addCommand({
+ id: 'save-settings-to-front-matter',
+ name: 'Save settings to front matter',
+ checkCallback: (checking) => {
+ if (checking)
+ return isViewActive(this.app);
+ const viewInfo = getViewInfo(this.app);
+ const file = this.app.workspace.getActiveFile();
+ if (viewInfo && file) {
+ const settings = getFrontMatterSettingsOrAlternative(viewInfo.data, this.settings);
+ saveSettingsToFrontMatter(this.app.fileManager, file, settings);
+ }
+ return false;
+ }
+ });
+ this.addSettingTab(new NumberHeadingsPluginSettingTab(this.app, this));
+ this.registerInterval(window.setInterval(() => {
+ const viewInfo = getViewInfo(this.app);
+ if (viewInfo) {
+ const settings = getFrontMatterSettingsOrAlternative(viewInfo.data, this.settings);
+ if (settings.off)
+ return;
+ if (settings.auto) {
+ updateHeadingNumbering(viewInfo, settings);
+ setTimeout(() => {
+ // HACK: This must happen after a timeout so that there is time for the editor transaction to complete
+ const postNumberingViewInfo = getViewInfo(this.app);
+ updateTableOfContents(postNumberingViewInfo, settings);
+ }, 3000);
+ // eslint-disable-next-line no-console
+ console.log('Number Headings Plugin: Automatically numbered document');
+ }
+ }
+ }, 10 * 1000));
+ });
+ }
+ 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);
+ });
+ }
+}
+
+module.exports = NumberHeadingsPlugin;
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsInNyYy9hY3RpdmVWaWV3SGVscGVycy50cyIsIm5vZGVfbW9kdWxlcy9yb21hbnMvcm9tYW5zLmpzIiwic3JjL251bWJlcmluZ1Rva2Vucy50cyIsInNyYy9zZXR0aW5nc1R5cGVzLnRzIiwic3JjL3RleHRQcm9jZXNzaW5nLnRzIiwic3JjL2Zyb250TWF0dGVyLnRzIiwic3JjL21lc3NhZ2VzLnRzIiwic3JjL251bWJlcmluZy50cyIsInNyYy9tYWluLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uXHJcblxyXG5QZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBhbmQvb3IgZGlzdHJpYnV0ZSB0aGlzIHNvZnR3YXJlIGZvciBhbnlcclxucHVycG9zZSB3aXRoIG9yIHdpdGhvdXQgZmVlIGlzIGhlcmVieSBncmFudGVkLlxyXG5cclxuVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiBBTkQgVEhFIEFVVEhPUiBESVNDTEFJTVMgQUxMIFdBUlJBTlRJRVMgV0lUSFxyXG5SRUdBUkQgVE8gVEhJUyBTT0ZUV0FSRSBJTkNMVURJTkcgQUxMIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFlcclxuQU5EIEZJVE5FU1MuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1IgQkUgTElBQkxFIEZPUiBBTlkgU1BFQ0lBTCwgRElSRUNULFxyXG5JTkRJUkVDVCwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIE9SIEFOWSBEQU1BR0VTIFdIQVRTT0VWRVIgUkVTVUxUSU5HIEZST01cclxuTE9TUyBPRiBVU0UsIERBVEEgT1IgUFJPRklUUywgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIE5FR0xJR0VOQ0UgT1JcclxuT1RIRVIgVE9SVElPVVMgQUNUSU9OLCBBUklTSU5HIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFVTRSBPUlxyXG5QRVJGT1JNQU5DRSBPRiBUSElTIFNPRlRXQVJFLlxyXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqL1xyXG4vKiBnbG9iYWwgUmVmbGVjdCwgUHJvbWlzZSwgU3VwcHJlc3NlZEVycm9yLCBTeW1ib2wgKi9cclxuXHJcbnZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24oZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcclxuICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXHJcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xyXG4gICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxuICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxyXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fYXNzaWduID0gZnVuY3Rpb24oKSB7XHJcbiAgICBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gX19hc3NpZ24odCkge1xyXG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xyXG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xyXG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpIHRbcF0gPSBzW3BdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdDtcclxuICAgIH1cclxuICAgIHJldHVybiBfX2Fzc2lnbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZXN0KHMsIGUpIHtcclxuICAgIHZhciB0ID0ge307XHJcbiAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkgJiYgZS5pbmRleE9mKHApIDwgMClcclxuICAgICAgICB0W3BdID0gc1twXTtcclxuICAgIGlmIChzICE9IG51bGwgJiYgdHlwZW9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPT09IFwiZnVuY3Rpb25cIilcclxuICAgICAgICBmb3IgKHZhciBpID0gMCwgcCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocyk7IGkgPCBwLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmIChlLmluZGV4T2YocFtpXSkgPCAwICYmIE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChzLCBwW2ldKSlcclxuICAgICAgICAgICAgICAgIHRbcFtpXV0gPSBzW3BbaV1dO1xyXG4gICAgICAgIH1cclxuICAgIHJldHVybiB0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xyXG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XHJcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xyXG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcGFyYW0ocGFyYW1JbmRleCwgZGVjb3JhdG9yKSB7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXNEZWNvcmF0ZShjdG9yLCBkZXNjcmlwdG9ySW4sIGRlY29yYXRvcnMsIGNvbnRleHRJbiwgaW5pdGlhbGl6ZXJzLCBleHRyYUluaXRpYWxpemVycykge1xyXG4gICAgZnVuY3Rpb24gYWNjZXB0KGYpIHsgaWYgKGYgIT09IHZvaWQgMCAmJiB0eXBlb2YgZiAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiRnVuY3Rpb24gZXhwZWN0ZWRcIik7IHJldHVybiBmOyB9XHJcbiAgICB2YXIga2luZCA9IGNvbnRleHRJbi5raW5kLCBrZXkgPSBraW5kID09PSBcImdldHRlclwiID8gXCJnZXRcIiA6IGtpbmQgPT09IFwic2V0dGVyXCIgPyBcInNldFwiIDogXCJ2YWx1ZVwiO1xyXG4gICAgdmFyIHRhcmdldCA9ICFkZXNjcmlwdG9ySW4gJiYgY3RvciA/IGNvbnRleHRJbltcInN0YXRpY1wiXSA/IGN0b3IgOiBjdG9yLnByb3RvdHlwZSA6IG51bGw7XHJcbiAgICB2YXIgZGVzY3JpcHRvciA9IGRlc2NyaXB0b3JJbiB8fCAodGFyZ2V0ID8gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGNvbnRleHRJbi5uYW1lKSA6IHt9KTtcclxuICAgIHZhciBfLCBkb25lID0gZmFsc2U7XHJcbiAgICBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xyXG4gICAgICAgIHZhciBjb250ZXh0ID0ge307XHJcbiAgICAgICAgZm9yICh2YXIgcCBpbiBjb250ZXh0SW4pIGNvbnRleHRbcF0gPSBwID09PSBcImFjY2Vzc1wiID8ge30gOiBjb250ZXh0SW5bcF07XHJcbiAgICAgICAgZm9yICh2YXIgcCBpbiBjb250ZXh0SW4uYWNjZXNzKSBjb250ZXh0LmFjY2Vzc1twXSA9IGNvbnRleHRJbi5hY2Nlc3NbcF07XHJcbiAgICAgICAgY29udGV4dC5hZGRJbml0aWFsaXplciA9IGZ1bmN0aW9uIChmKSB7IGlmIChkb25lKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGFkZCBpbml0aWFsaXplcnMgYWZ0ZXIgZGVjb3JhdGlvbiBoYXMgY29tcGxldGVkXCIpOyBleHRyYUluaXRpYWxpemVycy5wdXNoKGFjY2VwdChmIHx8IG51bGwpKTsgfTtcclxuICAgICAgICB2YXIgcmVzdWx0ID0gKDAsIGRlY29yYXRvcnNbaV0pKGtpbmQgPT09IFwiYWNjZXNzb3JcIiA/IHsgZ2V0OiBkZXNjcmlwdG9yLmdldCwgc2V0OiBkZXNjcmlwdG9yLnNldCB9IDogZGVzY3JpcHRvcltrZXldLCBjb250ZXh0KTtcclxuICAgICAgICBpZiAoa2luZCA9PT0gXCJhY2Nlc3NvclwiKSB7XHJcbiAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IHZvaWQgMCkgY29udGludWU7XHJcbiAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IG51bGwgfHwgdHlwZW9mIHJlc3VsdCAhPT0gXCJvYmplY3RcIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk9iamVjdCBleHBlY3RlZFwiKTtcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LmdldCkpIGRlc2NyaXB0b3IuZ2V0ID0gXztcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LnNldCkpIGRlc2NyaXB0b3Iuc2V0ID0gXztcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LmluaXQpKSBpbml0aWFsaXplcnMudW5zaGlmdChfKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAoXyA9IGFjY2VwdChyZXN1bHQpKSB7XHJcbiAgICAgICAgICAgIGlmIChraW5kID09PSBcImZpZWxkXCIpIGluaXRpYWxpemVycy51bnNoaWZ0KF8pO1xyXG4gICAgICAgICAgICBlbHNlIGRlc2NyaXB0b3Jba2V5XSA9IF87XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKHRhcmdldCkgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgY29udGV4dEluLm5hbWUsIGRlc2NyaXB0b3IpO1xyXG4gICAgZG9uZSA9IHRydWU7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19ydW5Jbml0aWFsaXplcnModGhpc0FyZywgaW5pdGlhbGl6ZXJzLCB2YWx1ZSkge1xyXG4gICAgdmFyIHVzZVZhbHVlID0gYXJndW1lbnRzLmxlbmd0aCA+IDI7XHJcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluaXRpYWxpemVycy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIHZhbHVlID0gdXNlVmFsdWUgPyBpbml0aWFsaXplcnNbaV0uY2FsbCh0aGlzQXJnLCB2YWx1ZSkgOiBpbml0aWFsaXplcnNbaV0uY2FsbCh0aGlzQXJnKTtcclxuICAgIH1cclxuICAgIHJldHVybiB1c2VWYWx1ZSA/IHZhbHVlIDogdm9pZCAwO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcHJvcEtleSh4KSB7XHJcbiAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3ltYm9sXCIgPyB4IDogXCJcIi5jb25jYXQoeCk7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19zZXRGdW5jdGlvbk5hbWUoZiwgbmFtZSwgcHJlZml4KSB7XHJcbiAgICBpZiAodHlwZW9mIG5hbWUgPT09IFwic3ltYm9sXCIpIG5hbWUgPSBuYW1lLmRlc2NyaXB0aW9uID8gXCJbXCIuY29uY2F0KG5hbWUuZGVzY3JpcHRpb24sIFwiXVwiKSA6IFwiXCI7XHJcbiAgICByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KGYsIFwibmFtZVwiLCB7IGNvbmZpZ3VyYWJsZTogdHJ1ZSwgdmFsdWU6IHByZWZpeCA/IFwiXCIuY29uY2F0KHByZWZpeCwgXCIgXCIsIG5hbWUpIDogbmFtZSB9KTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKSB7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QubWV0YWRhdGEgPT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIFJlZmxlY3QubWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdGVyKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xyXG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XHJcbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cclxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZ2VuZXJhdG9yKHRoaXNBcmcsIGJvZHkpIHtcclxuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XHJcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xyXG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcclxuICAgICAgICB3aGlsZSAoZyAmJiAoZyA9IDAsIG9wWzBdICYmIChfID0gMCkpLCBfKSB0cnkge1xyXG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XHJcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXTtcclxuICAgICAgICAgICAgc3dpdGNoIChvcFswXSkge1xyXG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IF8ubGFiZWwrKzsgcmV0dXJuIHsgdmFsdWU6IG9wWzFdLCBkb25lOiBmYWxzZSB9O1xyXG4gICAgICAgICAgICAgICAgY2FzZSA1OiBfLmxhYmVsKys7IHkgPSBvcFsxXTsgb3AgPSBbMF07IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAgICAgICBpZiAoISh0ID0gXy50cnlzLCB0ID0gdC5sZW5ndGggPiAwICYmIHRbdC5sZW5ndGggLSAxXSkgJiYgKG9wWzBdID09PSA2IHx8IG9wWzBdID09PSAyKSkgeyBfID0gMDsgY29udGludWU7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gNiAmJiBfLmxhYmVsIDwgdFsxXSkgeyBfLmxhYmVsID0gdFsxXTsgdCA9IG9wOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7IF8ubGFiZWwgPSB0WzJdOyBfLm9wcy5wdXNoKG9wKTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcclxuICAgICAgICB9IGNhdGNoIChlKSB7IG9wID0gWzYsIGVdOyB5ID0gMDsgfSBmaW5hbGx5IHsgZiA9IHQgPSAwOyB9XHJcbiAgICAgICAgaWYgKG9wWzBdICYgNSkgdGhyb3cgb3BbMV07IHJldHVybiB7IHZhbHVlOiBvcFswXSA/IG9wWzFdIDogdm9pZCAwLCBkb25lOiB0cnVlIH07XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCB2YXIgX19jcmVhdGVCaW5kaW5nID0gT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xyXG4gICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcclxuICAgIHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihtLCBrKTtcclxuICAgIGlmICghZGVzYyB8fCAoXCJnZXRcIiBpbiBkZXNjID8gIW0uX19lc01vZHVsZSA6IGRlc2Mud3JpdGFibGUgfHwgZGVzYy5jb25maWd1cmFibGUpKSB7XHJcbiAgICAgICAgZGVzYyA9IHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfTtcclxuICAgIH1cclxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgZGVzYyk7XHJcbn0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XHJcbiAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xyXG4gICAgb1trMl0gPSBtW2tdO1xyXG59KTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2V4cG9ydFN0YXIobSwgbykge1xyXG4gICAgZm9yICh2YXIgcCBpbiBtKSBpZiAocCAhPT0gXCJkZWZhdWx0XCIgJiYgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvLCBwKSkgX19jcmVhdGVCaW5kaW5nKG8sIG0sIHApO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX192YWx1ZXMobykge1xyXG4gICAgdmFyIHMgPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgU3ltYm9sLml0ZXJhdG9yLCBtID0gcyAmJiBvW3NdLCBpID0gMDtcclxuICAgIGlmIChtKSByZXR1cm4gbS5jYWxsKG8pO1xyXG4gICAgaWYgKG8gJiYgdHlwZW9mIG8ubGVuZ3RoID09PSBcIm51bWJlclwiKSByZXR1cm4ge1xyXG4gICAgICAgIG5leHQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKG8gJiYgaSA+PSBvLmxlbmd0aCkgbyA9IHZvaWQgMDtcclxuICAgICAgICAgICAgcmV0dXJuIHsgdmFsdWU6IG8gJiYgb1tpKytdLCBkb25lOiAhbyB9O1xyXG4gICAgICAgIH1cclxuICAgIH07XHJcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKHMgPyBcIk9iamVjdCBpcyBub3QgaXRlcmFibGUuXCIgOiBcIlN5bWJvbC5pdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3JlYWQobywgbikge1xyXG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdO1xyXG4gICAgaWYgKCFtKSByZXR1cm4gbztcclxuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xyXG4gICAgdHJ5IHtcclxuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcclxuICAgIH1cclxuICAgIGNhdGNoIChlcnJvcikgeyBlID0geyBlcnJvcjogZXJyb3IgfTsgfVxyXG4gICAgZmluYWxseSB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKHIgJiYgIXIuZG9uZSAmJiAobSA9IGlbXCJyZXR1cm5cIl0pKSBtLmNhbGwoaSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG4vKiogQGRlcHJlY2F0ZWQgKi9cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkKCkge1xyXG4gICAgZm9yICh2YXIgYXIgPSBbXSwgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspXHJcbiAgICAgICAgYXIgPSBhci5jb25jYXQoX19yZWFkKGFyZ3VtZW50c1tpXSkpO1xyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG4vKiogQGRlcHJlY2F0ZWQgKi9cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkQXJyYXlzKCkge1xyXG4gICAgZm9yICh2YXIgcyA9IDAsIGkgPSAwLCBpbCA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBpbDsgaSsrKSBzICs9IGFyZ3VtZW50c1tpXS5sZW5ndGg7XHJcbiAgICBmb3IgKHZhciByID0gQXJyYXkocyksIGsgPSAwLCBpID0gMDsgaSA8IGlsOyBpKyspXHJcbiAgICAgICAgZm9yICh2YXIgYSA9IGFyZ3VtZW50c1tpXSwgaiA9IDAsIGpsID0gYS5sZW5ndGg7IGogPCBqbDsgaisrLCBrKyspXHJcbiAgICAgICAgICAgIHJba10gPSBhW2pdO1xyXG4gICAgcmV0dXJuIHI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZEFycmF5KHRvLCBmcm9tLCBwYWNrKSB7XHJcbiAgICBpZiAocGFjayB8fCBhcmd1bWVudHMubGVuZ3RoID09PSAyKSBmb3IgKHZhciBpID0gMCwgbCA9IGZyb20ubGVuZ3RoLCBhcjsgaSA8IGw7IGkrKykge1xyXG4gICAgICAgIGlmIChhciB8fCAhKGkgaW4gZnJvbSkpIHtcclxuICAgICAgICAgICAgaWYgKCFhcikgYXIgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChmcm9tLCAwLCBpKTtcclxuICAgICAgICAgICAgYXJbaV0gPSBmcm9tW2ldO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiB0by5jb25jYXQoYXIgfHwgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZnJvbSkpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdCh2KSB7XHJcbiAgICByZXR1cm4gdGhpcyBpbnN0YW5jZW9mIF9fYXdhaXQgPyAodGhpcy52ID0gdiwgdGhpcykgOiBuZXcgX19hd2FpdCh2KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNHZW5lcmF0b3IodGhpc0FyZywgX2FyZ3VtZW50cywgZ2VuZXJhdG9yKSB7XHJcbiAgICBpZiAoIVN5bWJvbC5hc3luY0l0ZXJhdG9yKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3ltYm9sLmFzeW5jSXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgdmFyIGcgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSksIGksIHEgPSBbXTtcclxuICAgIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyBpZiAoZ1tuXSkgaVtuXSA9IGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAoYSwgYikgeyBxLnB1c2goW24sIHYsIGEsIGJdKSA+IDEgfHwgcmVzdW1lKG4sIHYpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gcmVzdW1lKG4sIHYpIHsgdHJ5IHsgc3RlcChnW25dKHYpKTsgfSBjYXRjaCAoZSkgeyBzZXR0bGUocVswXVszXSwgZSk7IH0gfVxyXG4gICAgZnVuY3Rpb24gc3RlcChyKSB7IHIudmFsdWUgaW5zdGFuY2VvZiBfX2F3YWl0ID8gUHJvbWlzZS5yZXNvbHZlKHIudmFsdWUudikudGhlbihmdWxmaWxsLCByZWplY3QpIDogc2V0dGxlKHFbMF1bMl0sIHIpOyB9XHJcbiAgICBmdW5jdGlvbiBmdWxmaWxsKHZhbHVlKSB7IHJlc3VtZShcIm5leHRcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiByZWplY3QodmFsdWUpIHsgcmVzdW1lKFwidGhyb3dcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUoZiwgdikgeyBpZiAoZih2KSwgcS5zaGlmdCgpLCBxLmxlbmd0aCkgcmVzdW1lKHFbMF1bMF0sIHFbMF1bMV0pOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jRGVsZWdhdG9yKG8pIHtcclxuICAgIHZhciBpLCBwO1xyXG4gICAgcmV0dXJuIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiLCBmdW5jdGlvbiAoZSkgeyB0aHJvdyBlOyB9KSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobiwgZikgeyBpW25dID0gb1tuXSA/IGZ1bmN0aW9uICh2KSB7IHJldHVybiAocCA9ICFwKSA/IHsgdmFsdWU6IF9fYXdhaXQob1tuXSh2KSksIGRvbmU6IGZhbHNlIH0gOiBmID8gZih2KSA6IHY7IH0gOiBmOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jVmFsdWVzKG8pIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICB2YXIgbSA9IG9bU3ltYm9sLmFzeW5jSXRlcmF0b3JdLCBpO1xyXG4gICAgcmV0dXJuIG0gPyBtLmNhbGwobykgOiAobyA9IHR5cGVvZiBfX3ZhbHVlcyA9PT0gXCJmdW5jdGlvblwiID8gX192YWx1ZXMobykgOiBvW1N5bWJvbC5pdGVyYXRvcl0oKSwgaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGkpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IGlbbl0gPSBvW25dICYmIGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7IHYgPSBvW25dKHYpLCBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCB2LmRvbmUsIHYudmFsdWUpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgZCwgdikgeyBQcm9taXNlLnJlc29sdmUodikudGhlbihmdW5jdGlvbih2KSB7IHJlc29sdmUoeyB2YWx1ZTogdiwgZG9uZTogZCB9KTsgfSwgcmVqZWN0KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tYWtlVGVtcGxhdGVPYmplY3QoY29va2VkLCByYXcpIHtcclxuICAgIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIHsgT2JqZWN0LmRlZmluZVByb3BlcnR5KGNvb2tlZCwgXCJyYXdcIiwgeyB2YWx1ZTogcmF3IH0pOyB9IGVsc2UgeyBjb29rZWQucmF3ID0gcmF3OyB9XHJcbiAgICByZXR1cm4gY29va2VkO1xyXG59O1xyXG5cclxudmFyIF9fc2V0TW9kdWxlRGVmYXVsdCA9IE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgdikge1xyXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIFwiZGVmYXVsdFwiLCB7IGVudW1lcmFibGU6IHRydWUsIHZhbHVlOiB2IH0pO1xyXG59KSA6IGZ1bmN0aW9uKG8sIHYpIHtcclxuICAgIG9bXCJkZWZhdWx0XCJdID0gdjtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2ltcG9ydFN0YXIobW9kKSB7XHJcbiAgICBpZiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSByZXR1cm4gbW9kO1xyXG4gICAgdmFyIHJlc3VsdCA9IHt9O1xyXG4gICAgaWYgKG1vZCAhPSBudWxsKSBmb3IgKHZhciBrIGluIG1vZCkgaWYgKGsgIT09IFwiZGVmYXVsdFwiICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtb2QsIGspKSBfX2NyZWF0ZUJpbmRpbmcocmVzdWx0LCBtb2QsIGspO1xyXG4gICAgX19zZXRNb2R1bGVEZWZhdWx0KHJlc3VsdCwgbW9kKTtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2ltcG9ydERlZmF1bHQobW9kKSB7XHJcbiAgICByZXR1cm4gKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgPyBtb2QgOiB7IGRlZmF1bHQ6IG1vZCB9O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19jbGFzc1ByaXZhdGVGaWVsZEdldChyZWNlaXZlciwgc3RhdGUsIGtpbmQsIGYpIHtcclxuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcclxuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xyXG4gICAgcmV0dXJuIGtpbmQgPT09IFwibVwiID8gZiA6IGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyKSA6IGYgPyBmLnZhbHVlIDogc3RhdGUuZ2V0KHJlY2VpdmVyKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRTZXQocmVjZWl2ZXIsIHN0YXRlLCB2YWx1ZSwga2luZCwgZikge1xyXG4gICAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xyXG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgc2V0dGVyXCIpO1xyXG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3Qgd3JpdGUgcHJpdmF0ZSBtZW1iZXIgdG8gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcclxuICAgIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19jbGFzc1ByaXZhdGVGaWVsZEluKHN0YXRlLCByZWNlaXZlcikge1xyXG4gICAgaWYgKHJlY2VpdmVyID09PSBudWxsIHx8ICh0eXBlb2YgcmVjZWl2ZXIgIT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIHJlY2VpdmVyICE9PSBcImZ1bmN0aW9uXCIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHVzZSAnaW4nIG9wZXJhdG9yIG9uIG5vbi1vYmplY3RcIik7XHJcbiAgICByZXR1cm4gdHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciA9PT0gc3RhdGUgOiBzdGF0ZS5oYXMocmVjZWl2ZXIpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hZGREaXNwb3NhYmxlUmVzb3VyY2UoZW52LCB2YWx1ZSwgYXN5bmMpIHtcclxuICAgIGlmICh2YWx1ZSAhPT0gbnVsbCAmJiB2YWx1ZSAhPT0gdm9pZCAwKSB7XHJcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgdmFsdWUgIT09IFwiZnVuY3Rpb25cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk9iamVjdCBleHBlY3RlZC5cIik7XHJcbiAgICAgICAgdmFyIGRpc3Bvc2U7XHJcbiAgICAgICAgaWYgKGFzeW5jKSB7XHJcbiAgICAgICAgICAgIGlmICghU3ltYm9sLmFzeW5jRGlzcG9zZSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0Rpc3Bvc2UgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgICAgICAgICBkaXNwb3NlID0gdmFsdWVbU3ltYm9sLmFzeW5jRGlzcG9zZV07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChkaXNwb3NlID09PSB2b2lkIDApIHtcclxuICAgICAgICAgICAgaWYgKCFTeW1ib2wuZGlzcG9zZSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5kaXNwb3NlIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgICAgICAgICAgZGlzcG9zZSA9IHZhbHVlW1N5bWJvbC5kaXNwb3NlXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHR5cGVvZiBkaXNwb3NlICE9PSBcImZ1bmN0aW9uXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJPYmplY3Qgbm90IGRpc3Bvc2FibGUuXCIpO1xyXG4gICAgICAgIGVudi5zdGFjay5wdXNoKHsgdmFsdWU6IHZhbHVlLCBkaXNwb3NlOiBkaXNwb3NlLCBhc3luYzogYXN5bmMgfSk7XHJcbiAgICB9XHJcbiAgICBlbHNlIGlmIChhc3luYykge1xyXG4gICAgICAgIGVudi5zdGFjay5wdXNoKHsgYXN5bmM6IHRydWUgfSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdmFsdWU7XHJcbn1cclxuXHJcbnZhciBfU3VwcHJlc3NlZEVycm9yID0gdHlwZW9mIFN1cHByZXNzZWRFcnJvciA9PT0gXCJmdW5jdGlvblwiID8gU3VwcHJlc3NlZEVycm9yIDogZnVuY3Rpb24gKGVycm9yLCBzdXBwcmVzc2VkLCBtZXNzYWdlKSB7XHJcbiAgICB2YXIgZSA9IG5ldyBFcnJvcihtZXNzYWdlKTtcclxuICAgIHJldHVybiBlLm5hbWUgPSBcIlN1cHByZXNzZWRFcnJvclwiLCBlLmVycm9yID0gZXJyb3IsIGUuc3VwcHJlc3NlZCA9IHN1cHByZXNzZWQsIGU7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19kaXNwb3NlUmVzb3VyY2VzKGVudikge1xyXG4gICAgZnVuY3Rpb24gZmFpbChlKSB7XHJcbiAgICAgICAgZW52LmVycm9yID0gZW52Lmhhc0Vycm9yID8gbmV3IF9TdXBwcmVzc2VkRXJyb3IoZSwgZW52LmVycm9yLCBcIkFuIGVycm9yIHdhcyBzdXBwcmVzc2VkIGR1cmluZyBkaXNwb3NhbC5cIikgOiBlO1xyXG4gICAgICAgIGVudi5oYXNFcnJvciA9IHRydWU7XHJcbiAgICB9XHJcbiAgICBmdW5jdGlvbiBuZXh0KCkge1xyXG4gICAgICAgIHdoaWxlIChlbnYuc3RhY2subGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIHZhciByZWMgPSBlbnYuc3RhY2sucG9wKCk7XHJcbiAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gcmVjLmRpc3Bvc2UgJiYgcmVjLmRpc3Bvc2UuY2FsbChyZWMudmFsdWUpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHJlYy5hc3luYykgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXN1bHQpLnRoZW4obmV4dCwgZnVuY3Rpb24oZSkgeyBmYWlsKGUpOyByZXR1cm4gbmV4dCgpOyB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgZmFpbChlKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoZW52Lmhhc0Vycm9yKSB0aHJvdyBlbnYuZXJyb3I7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbmV4dCgpO1xyXG59XHJcblxyXG5leHBvcnQgZGVmYXVsdCB7XHJcbiAgICBfX2V4dGVuZHM6IF9fZXh0ZW5kcyxcclxuICAgIF9fYXNzaWduOiBfX2Fzc2lnbixcclxuICAgIF9fcmVzdDogX19yZXN0LFxyXG4gICAgX19kZWNvcmF0ZTogX19kZWNvcmF0ZSxcclxuICAgIF9fcGFyYW06IF9fcGFyYW0sXHJcbiAgICBfX21ldGFkYXRhOiBfX21ldGFkYXRhLFxyXG4gICAgX19hd2FpdGVyOiBfX2F3YWl0ZXIsXHJcbiAgICBfX2dlbmVyYXRvcjogX19nZW5lcmF0b3IsXHJcbiAgICBfX2NyZWF0ZUJpbmRpbmc6IF9fY3JlYXRlQmluZGluZyxcclxuICAgIF9fZXhwb3J0U3RhcjogX19leHBvcnRTdGFyLFxyXG4gICAgX192YWx1ZXM6IF9fdmFsdWVzLFxyXG4gICAgX19yZWFkOiBfX3JlYWQsXHJcbiAgICBfX3NwcmVhZDogX19zcHJlYWQsXHJcbiAgICBfX3NwcmVhZEFycmF5czogX19zcHJlYWRBcnJheXMsXHJcbiAgICBfX3NwcmVhZEFycmF5OiBfX3NwcmVhZEFycmF5LFxyXG4gICAgX19hd2FpdDogX19hd2FpdCxcclxuICAgIF9fYXN5bmNHZW5lcmF0b3I6IF9fYXN5bmNHZW5lcmF0b3IsXHJcbiAgICBfX2FzeW5jRGVsZWdhdG9yOiBfX2FzeW5jRGVsZWdhdG9yLFxyXG4gICAgX19hc3luY1ZhbHVlczogX19hc3luY1ZhbHVlcyxcclxuICAgIF9fbWFrZVRlbXBsYXRlT2JqZWN0OiBfX21ha2VUZW1wbGF0ZU9iamVjdCxcclxuICAgIF9faW1wb3J0U3RhcjogX19pbXBvcnRTdGFyLFxyXG4gICAgX19pbXBvcnREZWZhdWx0OiBfX2ltcG9ydERlZmF1bHQsXHJcbiAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0OiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0LFxyXG4gICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldDogX19jbGFzc1ByaXZhdGVGaWVsZFNldCxcclxuICAgIF9fY2xhc3NQcml2YXRlRmllbGRJbjogX19jbGFzc1ByaXZhdGVGaWVsZEluLFxyXG4gICAgX19hZGREaXNwb3NhYmxlUmVzb3VyY2U6IF9fYWRkRGlzcG9zYWJsZVJlc291cmNlLFxyXG4gICAgX19kaXNwb3NlUmVzb3VyY2VzOiBfX2Rpc3Bvc2VSZXNvdXJjZXMsXHJcbn07XHJcbiIsImltcG9ydCB7IEFwcCwgQ2FjaGVkTWV0YWRhdGEsIEVkaXRvciwgTWFya2Rvd25WaWV3IH0gZnJvbSAnb2JzaWRpYW4nXG5cbmZ1bmN0aW9uIGdldEFjdGl2ZVZpZXcoYXBwOiBBcHApOiBNYXJrZG93blZpZXcgfCB1bmRlZmluZWQge1xuICBjb25zdCBhY3RpdmVWaWV3ID0gYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVWaWV3T2ZUeXBlKE1hcmtkb3duVmlldylcbiAgcmV0dXJuIGFjdGl2ZVZpZXcgPz8gdW5kZWZpbmVkXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1ZpZXdBY3RpdmUoYXBwOiBBcHApOiBib29sZWFuIHtcbiAgY29uc3QgYWN0aXZlVmlldyA9IGdldEFjdGl2ZVZpZXcoYXBwKVxuICBpZiAoYWN0aXZlVmlldyAmJiBhY3RpdmVWaWV3LmZpbGUpIHJldHVybiB0cnVlXG4gIHJldHVybiBmYWxzZVxufVxuXG5mdW5jdGlvbiBnZXRWaWV3TWV0YWRhdGEoYXBwOiBBcHApOiBDYWNoZWRNZXRhZGF0YSB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGFjdGl2ZVZpZXcgPSBnZXRBY3RpdmVWaWV3KGFwcClcbiAgaWYgKGFjdGl2ZVZpZXcgJiYgYWN0aXZlVmlldy5maWxlKSB7XG4gICAgY29uc3QgZGF0YSA9IGFwcC5tZXRhZGF0YUNhY2hlLmdldEZpbGVDYWNoZShhY3RpdmVWaWV3LmZpbGUpIHx8IHt9XG4gICAgcmV0dXJuIGRhdGFcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVmlld0luZm8ge1xuICBhY3RpdmVWaWV3OiBNYXJrZG93blZpZXdcbiAgZGF0YTogQ2FjaGVkTWV0YWRhdGFcbiAgZWRpdG9yOiBFZGl0b3Jcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFZpZXdJbmZvKGFwcDogQXBwKTogVmlld0luZm8gfCB1bmRlZmluZWQge1xuICBjb25zdCBhY3RpdmVWaWV3ID0gZ2V0QWN0aXZlVmlldyhhcHApXG4gIGNvbnN0IGRhdGEgPSBnZXRWaWV3TWV0YWRhdGEoYXBwKVxuICBjb25zdCBlZGl0b3IgPSBhY3RpdmVWaWV3ID8gYWN0aXZlVmlldy5lZGl0b3IgOiB1bmRlZmluZWRcblxuICBpZiAoYWN0aXZlVmlldyAmJiBkYXRhICYmIGVkaXRvcikge1xuICAgIHJldHVybiB7XG4gICAgICBhY3RpdmVWaWV3LCBkYXRhLCBlZGl0b3JcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdW5kZWZpbmVkXG59XG4iLCJjb25zdCByb21hbl9tYXAgPSB7XG4gIE06IDEwMDAsXG4gIENNOiA5MDAsXG4gIEQ6IDUwMCxcbiAgQ0Q6IDQwMCxcbiAgQzogMTAwLFxuICBYQzogOTAsXG4gIEw6IDUwLFxuICBYTDogNDAsXG4gIFg6IDEwLFxuICBJWDogOSxcbiAgVjogNSxcbiAgSVY6IDQsXG4gIEk6IDFcbn1cblxuY29uc3QgYWxsQ2hhcnMgPSBPYmplY3Qua2V5cyhyb21hbl9tYXApXG5jb25zdCBhbGxOdW1lcmFscyA9IE9iamVjdC52YWx1ZXMocm9tYW5fbWFwKVxuY29uc3Qgcm9tYW5QYXR0ZXJuID1cbiAgL14oTXsxLDR9KENNfENEfEQ/Q3swLDN9KShYQ3xYTHxMP1h7MCwzfSkoSVh8SVZ8Vj9JezAsM30pfE17MCw0fShDTXxDP0R8RD9DezEsM30pKFhDfFhMfEw/WHswLDN9KShJWHxJVnxWP0l7MCwzfSl8TXswLDR9KENNfENEfEQ/Q3swLDN9KShYQ3xYP0x8TD9YezEsM30pKElYfElWfFY/SXswLDN9KXxNezAsNH0oQ018Q0R8RD9DezAsM30pKFhDfFhMfEw/WHswLDN9KShJWHxJP1Z8Vj9JezEsM30pKSQvXG5cbmNvbnN0IHJvbWFuaXplID0gKGRlY2ltYWwpID0+IHtcbiAgaWYgKFxuICAgIGRlY2ltYWwgPD0gMCB8fFxuICAgIHR5cGVvZiBkZWNpbWFsICE9PSAnbnVtYmVyJyB8fFxuICAgIE1hdGguZmxvb3IoZGVjaW1hbCkgIT09IGRlY2ltYWxcbiAgKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdyZXF1aXJlcyBhbiB1bnNpZ25lZCBpbnRlZ2VyJylcbiAgfVxuICBpZiAoZGVjaW1hbCA+PSA0MDAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdyZXF1aXJlcyBtYXggdmFsdWUgb2YgbGVzcyB0aGFuIDM5OTkgb3IgbGVzcycpXG4gIH1cbiAgbGV0IHJvbWFuID0gJydcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhbGxDaGFycy5sZW5ndGg7IGkrKykge1xuICAgIHdoaWxlIChkZWNpbWFsID49IGFsbE51bWVyYWxzW2ldKSB7XG4gICAgICBkZWNpbWFsIC09IGFsbE51bWVyYWxzW2ldXG4gICAgICByb21hbiArPSBhbGxDaGFyc1tpXVxuICAgIH1cbiAgfVxuICByZXR1cm4gcm9tYW5cbn1cblxuY29uc3QgZGVyb21hbml6ZSA9IChyb21hblN0cikgPT4ge1xuICBpZiAodHlwZW9mIHJvbWFuU3RyICE9PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBFcnJvcigncmVxdWlyZXMgYSBzdHJpbmcnKVxuICB9XG4gIGlmICghcm9tYW5QYXR0ZXJuLnRlc3Qocm9tYW5TdHIpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdyZXF1aXJlcyB2YWxpZCByb21hbiBudW1lcmFsIHN0cmluZycpXG4gIH1cbiAgbGV0IHJvbWFuU3RyaW5nID0gcm9tYW5TdHIudG9VcHBlckNhc2UoKVxuICBsZXQgYXJhYmljID0gMFxuICBsZXQgaXRlcmF0aW9uID0gcm9tYW5TdHJpbmcubGVuZ3RoXG4gIHdoaWxlIChpdGVyYXRpb24tLSkge1xuICAgIGxldCBjdW11bGF0aXZlID0gcm9tYW5fbWFwW3JvbWFuU3RyaW5nW2l0ZXJhdGlvbl1dXG4gICAgaWYgKGN1bXVsYXRpdmUgPCByb21hbl9tYXBbcm9tYW5TdHJpbmdbaXRlcmF0aW9uICsgMV1dKSB7XG4gICAgICBhcmFiaWMgLT0gY3VtdWxhdGl2ZVxuICAgIH0gZWxzZSB7XG4gICAgICBhcmFiaWMgKz0gY3VtdWxhdGl2ZVxuICAgIH1cbiAgfVxuICByZXR1cm4gYXJhYmljXG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBkZXJvbWFuaXplLFxuICByb21hbml6ZSxcbiAgYWxsQ2hhcnMsXG4gIGFsbE51bWVyYWxzXG59XG4iLCJpbXBvcnQgeyBkZXJvbWFuaXplLCByb21hbml6ZSB9IGZyb20gJ3JvbWFucydcblxuZXhwb3J0IHR5cGUgTnVtYmVyaW5nVG9rZW4gPSBOdW1iZXJpbmdUb2tlbkFyYWJpYyB8IE51bWJlcmluZ1Rva2VuQWxwaGFiZXQgfCBOdW1iZXJpbmdUb2tlblJvbWFuXG5leHBvcnQgdHlwZSBOdW1iZXJpbmdUb2tlbkFyYWJpYyA9IHtcbiAgc3R5bGU6ICcxJ1xuICB2YWx1ZTogbnVtYmVyXG59XG5leHBvcnQgdHlwZSBOdW1iZXJpbmdUb2tlbkFscGhhYmV0ID0ge1xuICBzdHlsZTogJ0EnXG4gIHZhbHVlOiBzdHJpbmdcbn1cbmV4cG9ydCB0eXBlIE51bWJlcmluZ1Rva2VuUm9tYW4gPSB7XG4gIHN0eWxlOiAnSSdcbiAgdmFsdWU6IHN0cmluZ1xufVxuZXhwb3J0IHR5cGUgTnVtYmVyaW5nU3R5bGUgPSAnMScgfCAnQScgfCAnSSdcbmV4cG9ydCB0eXBlIE51bWJlcmluZ1ZhbHVlID0gbnVtYmVyIHwgc3RyaW5nXG5cbi8vIFZhbGlkYXRlcyB0aGUgc3RyaW5nIHVzaW5nIGEgcmVnZXggdG8gZW5zdXJlIGlzIGlzIGEgdmFsaWQgYXJhYmljIG51bWJlcmluZyB2YWx1ZVxuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWRBcmFiaWNOdW1iZXJpbmdWYWx1ZVN0cmluZyhzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgY29uc3QgcmVnZXggPSAvXlswLTldKyQvXG4gIHJldHVybiByZWdleC50ZXN0KHMpXG59XG5cbi8vIFZhbGlkYXRlcyB0aGUgc3RyaW5nIHVzaW5nIGEgcmVnZXggdG8gZW5zdXJlIGlzIGlzIGEgdmFsaWQgYWxwaGFiZXQgbnVtYmVyaW5nIHZhbHVlXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZEFscGhhYmV0TnVtYmVyaW5nVmFsdWVTdHJpbmcoczogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IHJlZ2V4ID0gL15bQS1aXSQvXG4gIHJldHVybiByZWdleC50ZXN0KHMpXG59XG5cbi8vIFZhbGlkYXRlcyB0aGUgc3RyaW5nIHVzaW5nIGEgcmVnZXggdG8gZW5zdXJlIGlzIGlzIGEgdmFsaWQgcm9tYW4gbnVtYmVyaW5nIHZhbHVlXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZFJvbWFuTnVtYmVyaW5nVmFsdWVTdHJpbmcoczogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IHJlZ2V4ID0gL15bMElWWExDRE1dKyQvIC8vIFRoaXMgaW5jbHVkZXMgemVybyBmb3IgemVyb3RoIHRlc3RpbmdcbiAgcmV0dXJuIHJlZ2V4LnRlc3Qocylcbn1cblxuZnVuY3Rpb24gcHJpbnRhYmxlTnVtYmVyaW5nVG9rZW4odDogTnVtYmVyaW5nVG9rZW4pOiBzdHJpbmcge1xuICBzd2l0Y2ggKHQuc3R5bGUpIHtcbiAgICBjYXNlICcxJzpcbiAgICAgIHJldHVybiB0LnZhbHVlLnRvU3RyaW5nKClcbiAgICBjYXNlICdBJzpcbiAgICAgIHJldHVybiB0LnZhbHVlXG4gICAgY2FzZSAnSSc6XG4gICAgICByZXR1cm4gdC52YWx1ZVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB6ZXJvdGhOdW1iZXJpbmdUb2tlbkluU3R5bGUoc3R5bGU6IE51bWJlcmluZ1N0eWxlKTogTnVtYmVyaW5nVG9rZW4ge1xuICBzd2l0Y2ggKHN0eWxlKSB7XG4gICAgY2FzZSAnMSc6XG4gICAgICByZXR1cm4geyBzdHlsZTogJzEnLCB2YWx1ZTogMCB9XG4gICAgY2FzZSAnQSc6XG4gICAgICByZXR1cm4geyBzdHlsZTogJ0EnLCB2YWx1ZTogJ1onIH1cbiAgICBjYXNlICdJJzpcbiAgICAgIHJldHVybiB7IHN0eWxlOiAnSScsIHZhbHVlOiAnMCcgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmaXJzdE51bWJlcmluZ1Rva2VuSW5TdHlsZShzdHlsZTogTnVtYmVyaW5nU3R5bGUpOiBOdW1iZXJpbmdUb2tlbiB7XG4gIHN3aXRjaCAoc3R5bGUpIHtcbiAgICBjYXNlICcxJzpcbiAgICAgIHJldHVybiB7IHN0eWxlOiAnMScsIHZhbHVlOiAxIH1cbiAgICBjYXNlICdBJzpcbiAgICAgIHJldHVybiB7IHN0eWxlOiAnQScsIHZhbHVlOiAnQScgfVxuICAgIGNhc2UgJ0knOlxuICAgICAgcmV0dXJuIHsgc3R5bGU6ICdJJywgdmFsdWU6ICdJJyB9XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG5leHROdW1iZXJpbmdUb2tlbih0OiBOdW1iZXJpbmdUb2tlbik6IE51bWJlcmluZ1Rva2VuIHtcbiAgc3dpdGNoICh0LnN0eWxlKSB7XG4gICAgY2FzZSAnMSc6XG4gICAgICByZXR1cm4geyBzdHlsZTogJzEnLCB2YWx1ZTogdC52YWx1ZSArIDEgfVxuICAgIGNhc2UgJ0EnOlxuICAgICAgaWYgKHQudmFsdWUgPT09ICdaJykgcmV0dXJuIHsgc3R5bGU6ICdBJywgdmFsdWU6ICdBJyB9XG4gICAgICBlbHNlIHJldHVybiB7IHN0eWxlOiAnQScsIHZhbHVlOiBTdHJpbmcuZnJvbUNoYXJDb2RlKHQudmFsdWUuY2hhckNvZGVBdCgwKSArIDEpIH1cbiAgICBjYXNlICdJJzpcbiAgICAgIGlmICh0LnZhbHVlID09PSAnMCcpIHJldHVybiB7IHN0eWxlOiAnSScsIHZhbHVlOiAnSScgfVxuICAgICAgZWxzZSByZXR1cm4geyBzdHlsZTogJ0knLCB2YWx1ZTogcm9tYW5pemUoZGVyb21hbml6ZSh0LnZhbHVlKSArIDEpIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gcHJldmlvdXNOdW1iZXJpbmdUb2tlbih0OiBOdW1iZXJpbmdUb2tlbik6IE51bWJlcmluZ1Rva2VuIHtcbiAgc3dpdGNoICh0LnN0eWxlKSB7XG4gICAgY2FzZSAnMSc6XG4gICAgICByZXR1cm4geyBzdHlsZTogJzEnLCB2YWx1ZTogdC52YWx1ZSAtIDEgfVxuICAgIGNhc2UgJ0EnOlxuICAgICAgaWYgKHQudmFsdWUgPT09ICdBJykgcmV0dXJuIHsgc3R5bGU6ICdBJywgdmFsdWU6ICdaJyB9XG4gICAgICBlbHNlIHJldHVybiB7IHN0eWxlOiAnQScsIHZhbHVlOiBTdHJpbmcuZnJvbUNoYXJDb2RlKHQudmFsdWUuY2hhckNvZGVBdCgwKSAtIDEpIH1cbiAgICBjYXNlICdJJzpcbiAgICAgIGlmICh0LnZhbHVlID09PSAnSScpIHJldHVybiB7IHN0eWxlOiAnSScsIHZhbHVlOiAnMCcgfVxuICAgICAgZWxzZSByZXR1cm4geyBzdHlsZTogJ0knLCB2YWx1ZTogcm9tYW5pemUoZGVyb21hbml6ZSh0LnZhbHVlKSAtIDEpIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbWFrZU51bWJlcmluZ1N0cmluZyhudW1iZXJpbmdTdGFjazogTnVtYmVyaW5nVG9rZW5bXSk6IHN0cmluZyB7XG4gIGxldCBudW1iZXJpbmdTdHJpbmcgPSAnJ1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyaW5nU3RhY2subGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgbnVtYmVyaW5nU3RyaW5nICs9ICcgJ1xuICAgIH0gZWxzZSB7XG4gICAgICBudW1iZXJpbmdTdHJpbmcgKz0gJy4nXG4gICAgfVxuICAgIG51bWJlcmluZ1N0cmluZyArPSBwcmludGFibGVOdW1iZXJpbmdUb2tlbihudW1iZXJpbmdTdGFja1tpXSlcbiAgfVxuXG4gIHJldHVybiBudW1iZXJpbmdTdHJpbmdcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0YXJ0QXRPclplcm90aEluU3R5bGUoc3RhcnRBdFNldHRpbmdTdHJpbmc6IHN0cmluZywgc3R5bGU6IE51bWJlcmluZ1N0eWxlKTogTnVtYmVyaW5nVG9rZW4ge1xuICBpZiAoc3RhcnRBdFNldHRpbmdTdHJpbmcgPT09ICcnKSByZXR1cm4gemVyb3RoTnVtYmVyaW5nVG9rZW5JblN0eWxlKHN0eWxlKVxuXG4gIGxldCBmaXJzdE51bWJlcmluZ1Rva2VuRnJvbVNldHRpbmc6IE51bWJlcmluZ1Rva2VuXG5cbiAgc3dpdGNoIChzdHlsZSkge1xuICAgIGNhc2UgJzEnOlxuICAgICAgaWYgKCFpc1ZhbGlkQXJhYmljTnVtYmVyaW5nVmFsdWVTdHJpbmcoc3RhcnRBdFNldHRpbmdTdHJpbmcpKSByZXR1cm4gemVyb3RoTnVtYmVyaW5nVG9rZW5JblN0eWxlKHN0eWxlKVxuXG4gICAgICBmaXJzdE51bWJlcmluZ1Rva2VuRnJvbVNldHRpbmcgPSB7IHN0eWxlOiAnMScsIHZhbHVlOiBwYXJzZUludChzdGFydEF0U2V0dGluZ1N0cmluZykgfVxuICAgICAgYnJlYWtcbiAgICBjYXNlICdBJzpcbiAgICAgIGlmICghaXNWYWxpZEFscGhhYmV0TnVtYmVyaW5nVmFsdWVTdHJpbmcoc3RhcnRBdFNldHRpbmdTdHJpbmcpKSByZXR1cm4gemVyb3RoTnVtYmVyaW5nVG9rZW5JblN0eWxlKHN0eWxlKVxuXG4gICAgICBmaXJzdE51bWJlcmluZ1Rva2VuRnJvbVNldHRpbmcgPSB7IHN0eWxlOiAnQScsIHZhbHVlOiBzdGFydEF0U2V0dGluZ1N0cmluZyB9XG4gICAgICBicmVha1xuICAgIGNhc2UgJ0knOlxuICAgICAgaWYgKCFpc1ZhbGlkUm9tYW5OdW1iZXJpbmdWYWx1ZVN0cmluZyhzdGFydEF0U2V0dGluZ1N0cmluZykpIHJldHVybiB6ZXJvdGhOdW1iZXJpbmdUb2tlbkluU3R5bGUoc3R5bGUpXG4gICAgICBmaXJzdE51bWJlcmluZ1Rva2VuRnJvbVNldHRpbmcgPSB7IHN0eWxlOiAnSScsIHZhbHVlOiBzdGFydEF0U2V0dGluZ1N0cmluZyB9XG4gICAgICBicmVha1xuICB9XG5cbiAgLy8gQ29udmVydCB0aGUgZmlyc3QgbnVtYmVyaW5nIHRva2VuIHRvIGEgemVyb3RoIG51bWJlcmluZyB0b2tlblxuICByZXR1cm4gcHJldmlvdXNOdW1iZXJpbmdUb2tlbihmaXJzdE51bWJlcmluZ1Rva2VuRnJvbVNldHRpbmcpXG59XG4iLCJpbXBvcnQgeyBpc1ZhbGlkQWxwaGFiZXROdW1iZXJpbmdWYWx1ZVN0cmluZywgaXNWYWxpZEFyYWJpY051bWJlcmluZ1ZhbHVlU3RyaW5nLCBpc1ZhbGlkUm9tYW5OdW1iZXJpbmdWYWx1ZVN0cmluZywgTnVtYmVyaW5nU3R5bGUgfSBmcm9tICcuL251bWJlcmluZ1Rva2VucydcblxuZXhwb3J0IGludGVyZmFjZSBOdW1iZXJIZWFkaW5nc1BsdWdpblNldHRpbmdzIHtcbiAgc2tpcFRvcExldmVsOiBib29sZWFuLFxuICBmaXJzdExldmVsOiBudW1iZXIsXG4gIG1heExldmVsOiBudW1iZXIsXG4gIHN0eWxlTGV2ZWwxOiBOdW1iZXJpbmdTdHlsZSxcbiAgc3R5bGVMZXZlbE90aGVyOiBOdW1iZXJpbmdTdHlsZSxcbiAgYXV0bzogYm9vbGVhbixcbiAgc2VwYXJhdG9yOiBzdHJpbmcsXG4gIGNvbnRlbnRzOiBzdHJpbmcsXG4gIHNraXBIZWFkaW5nczogc3RyaW5nLFxuICBzdGFydEF0OiBzdHJpbmcsXG4gIG9mZjogYm9vbGVhblxufVxuXG5leHBvcnQgY29uc3QgREVGQVVMVF9TRVRUSU5HUzogUmVhZG9ubHk8TnVtYmVySGVhZGluZ3NQbHVnaW5TZXR0aW5ncz4gPSB7XG4gIHNraXBUb3BMZXZlbDogZmFsc2UsXG4gIGZpcnN0TGV2ZWw6IDEsXG4gIG1heExldmVsOiA2LFxuICBzdHlsZUxldmVsMTogJzEnLFxuICBzdHlsZUxldmVsT3RoZXI6ICcxJyxcbiAgYXV0bzogZmFsc2UsXG4gIHNlcGFyYXRvcjogJycsXG4gIGNvbnRlbnRzOiAnJyxcbiAgc2tpcEhlYWRpbmdzOiAnJyxcbiAgc3RhcnRBdDogJycsXG4gIG9mZjogZmFsc2Vcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWROdW1iZXJpbmdTdHlsZVN0cmluZyhzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgaWYgKHMgPT09ICdBJyB8fCBzID09PSAnMScgfHwgcyA9PT0gJ0knKSByZXR1cm4gdHJ1ZVxuICByZXR1cm4gZmFsc2Vcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWROdW1iZXJpbmdWYWx1ZVN0cmluZyhzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgaWYgKHMgPT09ICcnIHx8IGlzVmFsaWRBcmFiaWNOdW1iZXJpbmdWYWx1ZVN0cmluZyhzKSB8fCBpc1ZhbGlkQWxwaGFiZXROdW1iZXJpbmdWYWx1ZVN0cmluZyhzKSB8fCBpc1ZhbGlkUm9tYW5OdW1iZXJpbmdWYWx1ZVN0cmluZyhzKSkgcmV0dXJuIHRydWVcbiAgcmV0dXJuIGZhbHNlXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1ZhbGlkRmxhZyhmOiB1bmtub3duKTogYm9vbGVhbiB7XG4gIGlmIChmID09PSB0cnVlIHx8IGYgPT09IGZhbHNlKSByZXR1cm4gdHJ1ZVxuICByZXR1cm4gZmFsc2Vcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWRGaXJzdE9yTWF4TGV2ZWwoeDogdW5rbm93bik6IGJvb2xlYW4ge1xuICBpZiAodHlwZW9mIHggPT09ICdudW1iZXInICYmIHggPj0gMSAmJiB4IDw9IDYpIHJldHVybiB0cnVlXG4gIHJldHVybiBmYWxzZVxufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZFNlcGFyYXRvcih4OiB1bmtub3duKTogYm9vbGVhbiB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgJiZcbiAgICAoXG4gICAgICB4ID09PSAnJyB8fFxuICAgICAgeCA9PT0gJzonIHx8IHggPT09ICcgOicgfHxcbiAgICAgIHggPT09ICcuJyB8fCB4ID09PSAnIC4nIHx8XG4gICAgICB4ID09PSAnLScgfHwgeCA9PT0gJyAtJyB8fFxuICAgICAgeCA9PT0gJ+KAlCcgfHwgeCA9PT0gJyDigJQnIHx8IC8qIGVtLWRhc2ggKi9cbiAgICAgIHggPT09ICcpJyB8fCB4ID09PSAnICknXG4gICAgKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZEJsb2NrSWRTZXR0aW5nKHg6IHVua25vd24pOiBib29sZWFuIHtcbiAgaWYgKHR5cGVvZiB4ID09PSAnc3RyaW5nJyAmJiAoeCA9PT0gJycgfHwgeC5zdGFydHNXaXRoKCdeJykpKSByZXR1cm4gdHJ1ZVxuICByZXR1cm4gZmFsc2Vcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzTm9uRW1wdHlCbG9ja0lkKHg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBpZiAoeC5sZW5ndGggPiAyICYmIHguc3RhcnRzV2l0aCgnXicpKSByZXR1cm4gdHJ1ZVxuICByZXR1cm4gZmFsc2Vcbn1cbiIsImltcG9ydCB7IEVkaXRvclJhbmdlIH0gZnJvbSAnb2JzaWRpYW4nXG5pbXBvcnQgeyBOdW1iZXJpbmdTdHlsZSB9IGZyb20gJy4vbnVtYmVyaW5nVG9rZW5zJ1xuaW1wb3J0IHsgaXNWYWxpZE51bWJlcmluZ1N0eWxlU3RyaW5nLCBpc1ZhbGlkU2VwYXJhdG9yLCBOdW1iZXJIZWFkaW5nc1BsdWdpblNldHRpbmdzIH0gZnJvbSAnLi9zZXR0aW5nc1R5cGVzJ1xuXG5leHBvcnQgdHlwZSBTdXBwb3J0RmxhZ3MgPSB7XG4gIGFscGhhYmV0OiBib29sZWFuLFxuICByb21hbjogYm9vbGVhbixcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVN1cHBvcnRGbGFnc0Zyb21TZXR0aW5ncyhzdHlsZUxldmVsMTogc3RyaW5nLCBzdHlsZUxldmVsT3RoZXI6IHN0cmluZyk6IFN1cHBvcnRGbGFncyB7XG4gIHJldHVybiB7XG4gICAgYWxwaGFiZXQ6IHN0eWxlTGV2ZWwxID09PSAnQScgfHwgc3R5bGVMZXZlbE90aGVyID09PSAnQScsXG4gICAgcm9tYW46IHN0eWxlTGV2ZWwxID09PSAnSScgfHwgc3R5bGVMZXZlbE90aGVyID09PSAnSSdcbiAgfVxufVxuXG4vLyBHZXQgdGhlIHJlZ2V4IGZvciB0aGUgaGVhZGVyIHN0cmluZywgYmFzZWQgb24gdGhlIHN1cHBvcnQgZmxhZ3MuIFRoZSBnZW5lcmF0ZWQgcmVnZXggaXMgdXNlZCB0byBmaW5kIHRoZSByYW5nZSBvZiB0aGUgaGVhZGVyIHByZWZpeC5cbi8vIFRoZSByZWdleCBpcyBnZW5lcmF0ZWQgZHluYW1pY2FsbHksIGJlY2F1c2UgdGhlIHJlZ2V4IGlzIGRpZmZlcmVudCBkZXBlbmRpbmcgb24gdGhlIHN1cHBvcnQgZmxhZ3MuXG5mdW5jdGlvbiBnZXRSZWdleEZvckhlYWRlclN0cmluZyhmbGFnczogU3VwcG9ydEZsYWdzKTogUmVnRXhwIHtcbiAgaWYgKGZsYWdzLmFscGhhYmV0ICYmIGZsYWdzLnJvbWFuKSB7XG4gICAgLy8gUmVnZXggdG8gbWF0Y2ggdGhlIGhlYWRpbmcgcHJlZml4LCBpbmNsdWRpbmcgdGhlIHNwYWNlIGFmdGVyIHRoZSBoYXNoKGVzKSwgYnV0IG5vdCB0aGUgaGVhZGluZyB0ZXh0XG4gICAgcmV0dXJuIC9eXFxzezAsNH0jKyggKT8oWzAtOV0rXFwufFtBLVpdXFwufFtJVlhMQ0RNXStcXC4pKihbMC05XSt8W0EtWl18W0lWWExDRE1dKyk/KCApP1sp4oCUOi4tXT8oICkrL2dcbiAgfSBlbHNlIGlmICghZmxhZ3MuYWxwaGFiZXQgJiYgZmxhZ3Mucm9tYW4pIHtcbiAgICAvLyBSZWdleCB0byBtYXRjaCB0aGUgaGVhZGluZyBwcmVmaXgsIGluY2x1ZGluZyB0aGUgc3BhY2UgYWZ0ZXIgdGhlIGhhc2goZXMpLCBidXQgbm90IHRoZSBoZWFkaW5nIHRleHRcbiAgICByZXR1cm4gL15cXHN7MCw0fSMrKCApPyhbMC05XStcXC58W0lWWExDRE1dK1xcLikqKFswLTldK3xbSVZYTENETV0rKT8oICk/WynigJQ6Li1dPyggKSsvZ1xuICB9IGVsc2UgaWYgKGZsYWdzLmFscGhhYmV0ICYmICFmbGFncy5yb21hbikge1xuICAgIC8vIFJlZ2V4IHRvIG1hdGNoIHRoZSBoZWFkaW5nIHByZWZpeCwgaW5jbHVkaW5nIHRoZSBzcGFjZSBhZnRlciB0aGUgaGFzaChlcyksIGJ1dCBub3QgdGhlIGhlYWRpbmcgdGV4dFxuICAgIHJldHVybiAvXlxcc3swLDR9IysoICk/KFswLTldK1xcLnxbQS1aXVxcLikqKFswLTldK3xbQS1aXSk/KCApP1sp4oCUOi4tXT8oICkrL2dcbiAgfSBlbHNlIGlmICghZmxhZ3MuYWxwaGFiZXQgJiYgIWZsYWdzLnJvbWFuKSB7XG4gICAgLy8gUmVnZXggdG8gbWF0Y2ggdGhlIGhlYWRpbmcgcHJlZml4LCBpbmNsdWRpbmcgdGhlIHNwYWNlIGFmdGVyIHRoZSBoYXNoKGVzKSwgYnV0IG5vdCB0aGUgaGVhZGluZyB0ZXh0XG4gICAgcmV0dXJuIC9eXFxzezAsNH0jKyggKT8oWzAtOV0rXFwuKSooWzAtOV0rKT8oICk/WynigJQ6Li1dPyggKSsvZ1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCdVbmV4cGVjdGVkIGNvbWJpbmF0aW9uIG9mIHN1cHBvcnQgZmxhZ3MnKVxufVxuXG4vLyBGaW5kIHRoZSByYW5nZSBvZiB0aGUgaGVhZGluZyBwcmVmaXgsIGluY2x1ZGluZyB0aGUgc3BhY2UgYWZ0ZXIgYW55IG51bWJlcmluZywgYnV0IG5vdCB0aGUgaGVhZGluZyB0ZXh0XG5leHBvcnQgZnVuY3Rpb24gZmluZFJhbmdlSW5IZWFkZXJTdHJpbmcobGluZVRleHQ6IHN0cmluZywgbGluZU51bWJlcjogbnVtYmVyLCBmbGFnczogU3VwcG9ydEZsYWdzKTogRWRpdG9yUmFuZ2UgfCB1bmRlZmluZWQge1xuICBjb25zdCByZWdleCA9IGdldFJlZ2V4Rm9ySGVhZGVyU3RyaW5nKGZsYWdzKVxuXG4gIGlmICghbGluZVRleHQpIHJldHVybiB1bmRlZmluZWRcblxuICBjb25zdCBtYXRjaGVzID0gbGluZVRleHQubWF0Y2gocmVnZXgpXG5cbiAgaWYgKG1hdGNoZXMgJiYgbWF0Y2hlcy5sZW5ndGggIT09IDEpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgIGNvbnNvbGUubG9nKFwiVW5leHBlY3RlZCBoZWFkaW5nIGZvcm1hdDogJ1wiICsgbGluZVRleHQgKyBcIidcIilcbiAgICByZXR1cm4gdW5kZWZpbmVkXG4gIH1cblxuICBjb25zdCBtYXRjaCA9IG1hdGNoZXMgPyBtYXRjaGVzWzBdIDogJydcblxuICBjb25zdCBmcm9tID0ge1xuICAgIGxpbmU6IGxpbmVOdW1iZXIsXG4gICAgY2g6IDBcbiAgfVxuICBjb25zdCB0byA9IHtcbiAgICBsaW5lOiBsaW5lTnVtYmVyLFxuICAgIGNoOiBtYXRjaC5sZW5ndGhcbiAgfVxuXG4gIHJldHVybiB7IGZyb20sIHRvIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZVNldHRpbmdzRnJvbUZyb250TWF0dGVyRm9ybWF0UGFydChwYXJ0OiBzdHJpbmcsIHNldHRpbmdzOiBOdW1iZXJIZWFkaW5nc1BsdWdpblNldHRpbmdzKTogTnVtYmVySGVhZGluZ3NQbHVnaW5TZXR0aW5ncyB7XG4gIC8vIFBhcnNlIHRoZSBzZXBhcmF0b3JcbiAgbGV0IHBhcnRXaXRob3V0U2VwYXJhdG9yID0gcGFydFxuICBjb25zdCBwb3RlbnRpYWxUd29DaGFyU2VwYXJhdG9yID0gcGFydC5zbGljZSgtMilcbiAgaWYgKGlzVmFsaWRTZXBhcmF0b3IocG90ZW50aWFsVHdvQ2hhclNlcGFyYXRvcikpIHtcbiAgICBzZXR0aW5ncy5zZXBhcmF0b3IgPSBwb3RlbnRpYWxUd29DaGFyU2VwYXJhdG9yXG4gICAgcGFydFdpdGhvdXRTZXBhcmF0b3IgPSBwYXJ0LnNsaWNlKDAsIC0yKVxuICB9IGVsc2Uge1xuICAgIGNvbnN0IHBvdGVudGlhbE9uZUNoYXJTZXBhcmF0b3IgPSBwYXJ0LnNsaWNlKC0xKVxuICAgIGlmIChpc1ZhbGlkU2VwYXJhdG9yKHBvdGVudGlhbE9uZUNoYXJTZXBhcmF0b3IpKSB7XG4gICAgICBzZXR0aW5ncy5zZXBhcmF0b3IgPSBwb3RlbnRpYWxPbmVDaGFyU2VwYXJhdG9yXG4gICAgICBwYXJ0V2l0aG91dFNlcGFyYXRvciA9IHBhcnQuc2xpY2UoMCwgLTEpXG4gICAgfSBlbHNlIHtcbiAgICAgIHNldHRpbmdzLnNlcGFyYXRvciA9ICcnXG4gICAgfVxuICB9XG5cbiAgLy8gUGFyc2UgdGhlIG51bWJlcmluZyBzdHlsZVxuICBjb25zdCBkZXNjcmlwdG9ycyA9IHBhcnRXaXRob3V0U2VwYXJhdG9yLnNwbGl0KCcuJylcbiAgbGV0IGZpcnN0TnVtYmVyZWREZXNjcmlwdG9yID0gMFxuXG4gIC8vIEhhbmRsZSB0aGUgY2FzZSB3aGVyZSB0aGUgZmlyc3QgZGVzY3JpcHRvciBpcyBhbiB1bmRlcnNjb3JlXG4gIGlmIChkZXNjcmlwdG9ycy5sZW5ndGggPiAxICYmIGRlc2NyaXB0b3JzWzBdID09PSAnXycpIHtcbiAgICAvLyBUaGUgZmlyc3QgZGVzY3JpcHRvciBpcyBhbiBpbnN0cnVjdGlvbiB0byBza2lwIHRvcCBsZXZlbHMsIHNvIHNraXAgdGhlbVxuICAgIHNldHRpbmdzLnNraXBUb3BMZXZlbCA9IHRydWVcbiAgICBmaXJzdE51bWJlcmVkRGVzY3JpcHRvciA9IDFcbiAgfSBlbHNlIHtcbiAgICBzZXR0aW5ncy5za2lwVG9wTGV2ZWwgPSBmYWxzZVxuICB9XG5cbiAgaWYgKGRlc2NyaXB0b3JzLmxlbmd0aCAtIGZpcnN0TnVtYmVyZWREZXNjcmlwdG9yID49IDIpIHtcbiAgICBjb25zdCBzdHlsZUxldmVsMSA9IGRlc2NyaXB0b3JzW2ZpcnN0TnVtYmVyZWREZXNjcmlwdG9yXVxuICAgIGlmIChpc1ZhbGlkTnVtYmVyaW5nU3R5bGVTdHJpbmcoc3R5bGVMZXZlbDEpKSB7XG4gICAgICBzZXR0aW5ncy5zdHlsZUxldmVsMSA9IHN0eWxlTGV2ZWwxIGFzIE51bWJlcmluZ1N0eWxlXG4gICAgfVxuICAgIGNvbnN0IHN0eWxlTGV2ZWxPdGhlciA9IGRlc2NyaXB0b3JzW2ZpcnN0TnVtYmVyZWREZXNjcmlwdG9yICsgMV1cbiAgICBpZiAoaXNWYWxpZE51bWJlcmluZ1N0eWxlU3RyaW5nKHN0eWxlTGV2ZWxPdGhlcikpIHtcbiAgICAgIHNldHRpbmdzLnN0eWxlTGV2ZWxPdGhlciA9IHN0eWxlTGV2ZWxPdGhlciBhcyBOdW1iZXJpbmdTdHlsZVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBzZXR0aW5nc1xufVxuIiwiaW1wb3J0IHsgQ2FjaGVkTWV0YWRhdGEsIEZpbGVNYW5hZ2VyLCBGcm9udE1hdHRlckNhY2hlLCBURmlsZSwgcGFyc2VGcm9udE1hdHRlckVudHJ5IH0gZnJvbSAnb2JzaWRpYW4nXG5pbXBvcnQgeyBOdW1iZXJpbmdTdHlsZSB9IGZyb20gJy4vbnVtYmVyaW5nVG9rZW5zJ1xuaW1wb3J0IHsgREVGQVVMVF9TRVRUSU5HUywgTnVtYmVySGVhZGluZ3NQbHVnaW5TZXR0aW5ncywgaXNWYWxpZEJsb2NrSWRTZXR0aW5nLCBpc1ZhbGlkRmlyc3RPck1heExldmVsLCBpc1ZhbGlkRmxhZywgaXNWYWxpZE51bWJlcmluZ1N0eWxlU3RyaW5nLCBpc1ZhbGlkTnVtYmVyaW5nVmFsdWVTdHJpbmcgfSBmcm9tICcuL3NldHRpbmdzVHlwZXMnXG5pbXBvcnQgeyB1cGRhdGVTZXR0aW5nc0Zyb21Gcm9udE1hdHRlckZvcm1hdFBhcnQgfSBmcm9tICcuL3RleHRQcm9jZXNzaW5nJ1xuXG5jb25zdCBBVVRPX1BBUlRfS0VZID0gJ2F1dG8nXG5jb25zdCBGSVJTVF9MRVZFTF9QQVJUX0tFWSA9ICdmaXJzdC1sZXZlbCdcbmNvbnN0IE1BWF9MRVZFTF9QQVJUX0tFWSA9ICdtYXgnXG5jb25zdCBDT05URU5UU19QQVJUX0tFWSA9ICdjb250ZW50cydcbmNvbnN0IFNLSVBfUEFSVF9LRVkgPSAnc2tpcCdcbmNvbnN0IFNUQVJUX0FUX1BBUlRfS0VZID0gJ3N0YXJ0LWF0J1xuY29uc3QgT0ZGX1BBUlRfS0VZID0gJ29mZidcblxuZnVuY3Rpb24gcGFyc2VDb21wYWN0RnJvbnRNYXR0ZXJTZXR0aW5ncyhmbTogRnJvbnRNYXR0ZXJDYWNoZSk6IE51bWJlckhlYWRpbmdzUGx1Z2luU2V0dGluZ3MgfCB1bmRlZmluZWQge1xuICBjb25zdCBlbnRyeSA9IHBhcnNlRnJvbnRNYXR0ZXJFbnRyeShmbSwgJ251bWJlciBoZWFkaW5ncycpXG4gIGlmIChlbnRyeSkge1xuICAgIGNvbnN0IGVudHJ5U3RyaW5nID0gU3RyaW5nKGVudHJ5KVxuICAgIGNvbnN0IHBhcnRzID0gZW50cnlTdHJpbmcuc3BsaXQoJywnKVxuICAgIGxldCBzZXR0aW5nczogTnVtYmVySGVhZGluZ3NQbHVnaW5TZXR0aW5ncyA9IHsgLi4uREVGQVVMVF9TRVRUSU5HUyB9XG5cbiAgICBmb3IgKGNvbnN0IHBhcnQgb2YgcGFydHMpIHtcbiAgICAgIGNvbnN0IHRyaW1tZWRQYXJ0ID0gcGFydC50cmltKClcbiAgICAgIGlmICh0cmltbWVkUGFydC5sZW5ndGggPT09IDApIGNvbnRpbnVlXG5cbiAgICAgIGlmICh0cmltbWVkUGFydCA9PT0gT0ZGX1BBUlRfS0VZKSB7XG4gICAgICAgIC8vIFBhcnNlIG9mZiBwYXJ0XG4gICAgICAgIHNldHRpbmdzLm9mZiA9IHRydWVcbiAgICAgIH0gZWxzZSBpZiAodHJpbW1lZFBhcnQgPT09IEFVVE9fUEFSVF9LRVkpIHtcbiAgICAgICAgLy8gUGFyc2UgYXV0byBudW1iZXJpbmcgcGFydFxuICAgICAgICBzZXR0aW5ncy5hdXRvID0gdHJ1ZVxuICAgICAgfSBlbHNlIGlmICh0cmltbWVkUGFydC5zdGFydHNXaXRoKEZJUlNUX0xFVkVMX1BBUlRfS0VZKSkge1xuICAgICAgICAvLyBQYXJzZSBmaXJzdCBsZXZlbCBwYXJ0XG4gICAgICAgIGNvbnN0IG5zdHJpbmcgPSB0cmltbWVkUGFydC5zdWJzdHJpbmcoRklSU1RfTEVWRUxfUEFSVF9LRVkubGVuZ3RoICsgMSlcbiAgICAgICAgY29uc3QgbiA9IHBhcnNlSW50KG5zdHJpbmcpXG4gICAgICAgIGlmIChpc1ZhbGlkRmlyc3RPck1heExldmVsKG4pKSB7XG4gICAgICAgICAgc2V0dGluZ3MuZmlyc3RMZXZlbCA9IG5cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0cmltbWVkUGFydC5zdGFydHNXaXRoKE1BWF9MRVZFTF9QQVJUX0tFWSkpIHtcbiAgICAgICAgLy8gUGFyc2UgbWF4IGxldmVsIHBhcnRcbiAgICAgICAgY29uc3QgbnN0cmluZyA9IHRyaW1tZWRQYXJ0LnN1YnN0cmluZyhNQVhfTEVWRUxfUEFSVF9LRVkubGVuZ3RoICsgMSlcbiAgICAgICAgY29uc3QgbiA9IHBhcnNlSW50KG5zdHJpbmcpXG4gICAgICAgIGlmIChpc1ZhbGlkRmlyc3RPck1heExldmVsKG4pKSB7XG4gICAgICAgICAgc2V0dGluZ3MubWF4TGV2ZWwgPSBuXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAodHJpbW1lZFBhcnQuc3RhcnRzV2l0aChTVEFSVF9BVF9QQVJUX0tFWSkpIHtcbiAgICAgICAgLy8gUGFyc2UgXCJzdGFydCBhdFwiIHBhcnRcbiAgICAgICAgY29uc3QgdmFsdWUgPSB0cmltbWVkUGFydC5zdWJzdHJpbmcoU1RBUlRfQVRfUEFSVF9LRVkubGVuZ3RoICsgMSlcbiAgICAgICAgaWYgKGlzVmFsaWROdW1iZXJpbmdWYWx1ZVN0cmluZyh2YWx1ZSkpIHtcbiAgICAgICAgICBzZXR0aW5ncy5zdGFydEF0ID0gdmFsdWVcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0cmltbWVkUGFydC5zdGFydHNXaXRoKENPTlRFTlRTX1BBUlRfS0VZKSkge1xuICAgICAgICBpZiAodHJpbW1lZFBhcnQubGVuZ3RoIDw9IENPTlRFTlRTX1BBUlRfS0VZLmxlbmd0aCArIDEpIGNvbnRpbnVlXG4gICAgICAgIC8vIFBhcnNlIGNvbnRlbnRzIGhlYWRpbmcgcGFydFxuICAgICAgICBjb25zdCB0b2NIZWFkaW5nQmxvY2tJZE5hbWUgPSB0cmltbWVkUGFydC5zdWJzdHJpbmcoQ09OVEVOVFNfUEFSVF9LRVkubGVuZ3RoICsgMSlcbiAgICAgICAgaWYgKGlzVmFsaWRCbG9ja0lkU2V0dGluZyh0b2NIZWFkaW5nQmxvY2tJZE5hbWUpKSB7XG4gICAgICAgICAgc2V0dGluZ3MuY29udGVudHMgPSB0b2NIZWFkaW5nQmxvY2tJZE5hbWVcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0cmltbWVkUGFydC5zdGFydHNXaXRoKFNLSVBfUEFSVF9LRVkpKSB7XG4gICAgICAgIGlmICh0cmltbWVkUGFydC5sZW5ndGggPD0gU0tJUF9QQVJUX0tFWS5sZW5ndGggKyAxKSBjb250aW51ZVxuICAgICAgICAvLyBQYXJzZSBza2lwIGhlYWRpbmcgcGFydFxuICAgICAgICBjb25zdCBza2lwSGVhZGluZ0Jsb2NrSWROYW1lID0gdHJpbW1lZFBhcnQuc3Vic3RyaW5nKFNLSVBfUEFSVF9LRVkubGVuZ3RoICsgMSlcbiAgICAgICAgaWYgKGlzVmFsaWRCbG9ja0lkU2V0dGluZyhza2lwSGVhZGluZ0Jsb2NrSWROYW1lKSkge1xuICAgICAgICAgIHNldHRpbmdzLnNraXBIZWFkaW5ncyA9IHNraXBIZWFkaW5nQmxvY2tJZE5hbWVcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gUGFyc2UgZm9ybWF0dGluZyBwYXJ0XG4gICAgICAgIHNldHRpbmdzID0gdXBkYXRlU2V0dGluZ3NGcm9tRnJvbnRNYXR0ZXJGb3JtYXRQYXJ0KHRyaW1tZWRQYXJ0LCBzZXR0aW5ncylcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2V0dGluZ3NcbiAgfVxuXG4gIHJldHVybiB1bmRlZmluZWRcbn1cblxuZXhwb3J0IGNvbnN0IGdldEZyb250TWF0dGVyU2V0dGluZ3NPckFsdGVybmF0aXZlID0gKFxuICB7IGZyb250bWF0dGVyIH06IENhY2hlZE1ldGFkYXRhLFxuICBhbHRlcm5hdGl2ZVNldHRpbmdzOiBOdW1iZXJIZWFkaW5nc1BsdWdpblNldHRpbmdzXG4pOiBOdW1iZXJIZWFkaW5nc1BsdWdpblNldHRpbmdzID0+IHtcbiAgaWYgKGZyb250bWF0dGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25zdCBkZWNvbXBhY3RlZFNldHRpbmdzID0gcGFyc2VDb21wYWN0RnJvbnRNYXR0ZXJTZXR0aW5ncyhmcm9udG1hdHRlcilcbiAgICBpZiAoZGVjb21wYWN0ZWRTZXR0aW5ncyAhPT0gdW5kZWZpbmVkKSByZXR1cm4gZGVjb21wYWN0ZWRTZXR0aW5nc1xuXG4gICAgLy8gTk9URTogRXZlcnl0aGluZyBiZWxvdyBpcyBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgb25seVxuXG4gICAgY29uc3Qgc2tpcFRvcExldmVsRW50cnkgPSBwYXJzZUZyb250TWF0dGVyRW50cnkoZnJvbnRtYXR0ZXIsICdudW1iZXItaGVhZGluZ3Mtc2tpcC10b3AtbGV2ZWwnKSA/PyBwYXJzZUZyb250TWF0dGVyRW50cnkoZnJvbnRtYXR0ZXIsICdoZWFkZXItbnVtYmVyaW5nLXNraXAtdG9wLWxldmVsJylcbiAgICBjb25zdCBza2lwVG9wTGV2ZWwgPSBpc1ZhbGlkRmxhZyhza2lwVG9wTGV2ZWxFbnRyeSkgPyBza2lwVG9wTGV2ZWxFbnRyeSA6IGFsdGVybmF0aXZlU2V0dGluZ3Muc2tpcFRvcExldmVsXG5cbiAgICBjb25zdCBtYXhMZXZlbEVudHJ5ID0gcGFyc2VGcm9udE1hdHRlckVudHJ5KGZyb250bWF0dGVyLCAnbnVtYmVyLWhlYWRpbmdzLW1heC1sZXZlbCcpID8/IHBhcnNlRnJvbnRNYXR0ZXJFbnRyeShmcm9udG1hdHRlciwgJ2hlYWRlci1udW1iZXJpbmctbWF4LWxldmVsJylcbiAgICBjb25zdCBtYXhMZXZlbCA9IGlzVmFsaWRGaXJzdE9yTWF4TGV2ZWwobWF4TGV2ZWxFbnRyeSkgPyBtYXhMZXZlbEVudHJ5IDogYWx0ZXJuYXRpdmVTZXR0aW5ncy5tYXhMZXZlbFxuXG4gICAgY29uc3Qgc3R5bGVMZXZlbDFFbnRyeSA9IFN0cmluZyhcbiAgICAgIHBhcnNlRnJvbnRNYXR0ZXJFbnRyeShmcm9udG1hdHRlciwgJ251bWJlci1oZWFkaW5ncy1zdHlsZS1sZXZlbC0xJykgPz9cbiAgICAgIHBhcnNlRnJvbnRNYXR0ZXJFbnRyeShmcm9udG1hdHRlciwgJ2hlYWRlci1udW1iZXJpbmctc3R5bGUtbGV2ZWwtMScpXG4gICAgKVxuICAgIGNvbnN0IHN0eWxlTGV2ZWwxOiBOdW1iZXJpbmdTdHlsZSA9IGlzVmFsaWROdW1iZXJpbmdTdHlsZVN0cmluZyhzdHlsZUxldmVsMUVudHJ5KSA/IHN0eWxlTGV2ZWwxRW50cnkgYXMgTnVtYmVyaW5nU3R5bGUgOiBhbHRlcm5hdGl2ZVNldHRpbmdzLnN0eWxlTGV2ZWwxXG5cbiAgICBjb25zdCBzdHlsZUxldmVsT3RoZXJFbnRyeSA9IFN0cmluZyhcbiAgICAgIHBhcnNlRnJvbnRNYXR0ZXJFbnRyeShmcm9udG1hdHRlciwgJ251bWJlci1oZWFkaW5ncy1zdHlsZS1sZXZlbC1vdGhlcicpID8/XG4gICAgICBwYXJzZUZyb250TWF0dGVyRW50cnkoZnJvbnRtYXR0ZXIsICdoZWFkZXItbnVtYmVyaW5nLXN0eWxlLWxldmVsLW90aGVyJylcbiAgICApXG4gICAgY29uc3Qgc3R5bGVMZXZlbE90aGVyOiBOdW1iZXJpbmdTdHlsZSA9IGlzVmFsaWROdW1iZXJpbmdTdHlsZVN0cmluZyhzdHlsZUxldmVsT3RoZXJFbnRyeSkgPyBzdHlsZUxldmVsT3RoZXJFbnRyeSBhcyBOdW1iZXJpbmdTdHlsZSA6IGFsdGVybmF0aXZlU2V0dGluZ3Muc3R5bGVMZXZlbE90aGVyXG5cbiAgICBjb25zdCBhdXRvRW50cnkgPSBwYXJzZUZyb250TWF0dGVyRW50cnkoZnJvbnRtYXR0ZXIsICdudW1iZXItaGVhZGluZ3MtYXV0bycpID8/IHBhcnNlRnJvbnRNYXR0ZXJFbnRyeShmcm9udG1hdHRlciwgJ2hlYWRlci1udW1iZXJpbmctYXV0bycpXG4gICAgY29uc3QgYXV0byA9IGlzVmFsaWRGbGFnKGF1dG9FbnRyeSkgPyBhdXRvRW50cnkgOiBhbHRlcm5hdGl2ZVNldHRpbmdzLmF1dG9cblxuICAgIHJldHVybiB7IC4uLmFsdGVybmF0aXZlU2V0dGluZ3MsIHNraXBUb3BMZXZlbCwgbWF4TGV2ZWwsIHN0eWxlTGV2ZWwxLCBzdHlsZUxldmVsT3RoZXIsIGF1dG8gfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBhbHRlcm5hdGl2ZVNldHRpbmdzXG4gIH1cbn1cblxuZnVuY3Rpb24gc2V0dGluZ3NUb0NvbXBhY3RGcm9udE1hdHRlclZhbHVlKHNldHRpbmdzOiBOdW1iZXJIZWFkaW5nc1BsdWdpblNldHRpbmdzKTogc3RyaW5nIHtcbiAgaWYgKHNldHRpbmdzLm9mZikgcmV0dXJuIE9GRl9QQVJUX0tFWVxuXG4gIGNvbnN0IGF1dG9QYXJ0ID0gc2V0dGluZ3MuYXV0byA/ICdhdXRvLCAnIDogJydcbiAgY29uc3QgZmlyc3RMZXZlbFBhcnQgPSBgZmlyc3QtbGV2ZWwgJHtzZXR0aW5ncy5maXJzdExldmVsfSwgYFxuICBjb25zdCBtYXhQYXJ0ID0gYG1heCAke3NldHRpbmdzLm1heExldmVsfSwgYFxuICBjb25zdCBjb250ZW50c1BhcnQgPSBzZXR0aW5ncy5jb250ZW50cyAmJiBzZXR0aW5ncy5jb250ZW50cy5sZW5ndGggPiAwID8gYGNvbnRlbnRzICR7c2V0dGluZ3MuY29udGVudHN9LCBgIDogJydcbiAgY29uc3Qgc2tpcEhlYWRpbmdzUGFydCA9IHNldHRpbmdzLnNraXBIZWFkaW5ncyAmJiBzZXR0aW5ncy5za2lwSGVhZGluZ3MubGVuZ3RoID4gMCA/IGBza2lwICR7c2V0dGluZ3Muc2tpcEhlYWRpbmdzfSwgYCA6ICcnXG4gIGNvbnN0IHNraXBUb3BMZXZlbFN0cmluZyA9IHNldHRpbmdzLnNraXBUb3BMZXZlbCA/ICdfLicgOiAnJ1xuICBjb25zdCBzdHlsZVBhcnQgPSBgJHtza2lwVG9wTGV2ZWxTdHJpbmd9JHtzZXR0aW5ncy5zdHlsZUxldmVsMX0uJHtzZXR0aW5ncy5zdHlsZUxldmVsT3RoZXJ9JHtzZXR0aW5ncy5zZXBhcmF0b3J9YFxuICBjb25zdCBzdGFydEF0UGFydCA9IHNldHRpbmdzLnN0YXJ0QXQgIT09ICcnID8gYHN0YXJ0LWF0ICR7c2V0dGluZ3Muc3RhcnRBdH0sIGAgOiAnJ1xuICByZXR1cm4gYXV0b1BhcnQgKyBmaXJzdExldmVsUGFydCArIG1heFBhcnQgKyBjb250ZW50c1BhcnQgKyBza2lwSGVhZGluZ3NQYXJ0ICsgc3RhcnRBdFBhcnQgKyBzdHlsZVBhcnRcbn1cblxuZXhwb3J0IGNvbnN0IHNhdmVTZXR0aW5nc1RvRnJvbnRNYXR0ZXIgPSAoXG4gIGZpbGVNYW5hZ2VyOiBGaWxlTWFuYWdlcixcbiAgZmlsZTogVEZpbGUsXG4gIHNldHRpbmdzOiBOdW1iZXJIZWFkaW5nc1BsdWdpblNldHRpbmdzXG4pOiB2b2lkID0+IHtcbiAgZmlsZU1hbmFnZXIucHJvY2Vzc0Zyb250TWF0dGVyKGZpbGUsIGZyb250bWF0dGVyID0+IHtcbiAgICBjb25zdCB2OiBzdHJpbmcgPSBzZXR0aW5nc1RvQ29tcGFjdEZyb250TWF0dGVyVmFsdWUoc2V0dGluZ3MpXG4gICAgZnJvbnRtYXR0ZXJbJ251bWJlciBoZWFkaW5ncyddID0gdlxuICB9KVxufVxuIiwiaW1wb3J0IHsgQXBwLCBNb2RhbCB9IGZyb20gJ29ic2lkaWFuJ1xuaW1wb3J0IHsgc2F2ZVNldHRpbmdzVG9Gcm9udE1hdHRlciB9IGZyb20gJy4vZnJvbnRNYXR0ZXInXG5pbXBvcnQgeyBOdW1iZXJIZWFkaW5nc1BsdWdpblNldHRpbmdzIH0gZnJvbSAnLi9zZXR0aW5nc1R5cGVzJ1xuXG5leHBvcnQgaW50ZXJmYWNlIE51bWJlcmluZ0RvbmVDb25maWcge1xuICBtZXNzYWdlOiBzdHJpbmdcbiAgcHJlZm9ybWF0dGVkTWVzc2FnZTogc3RyaW5nXG4gIHNhdmVTZXR0aW5nc0NhbGxiYWNrOiAoc2hvdWxkQWRkQXV0b0ZsYWc6IGJvb2xlYW4pID0+IHZvaWRcbn1cblxuY2xhc3MgTnVtYmVyaW5nRG9uZU1vZGFsIGV4dGVuZHMgTW9kYWwge1xuICBjb25maWc6IE51bWJlcmluZ0RvbmVDb25maWdcblxuICBjb25zdHJ1Y3RvcihhcHA6IEFwcCwgY29uZmlnOiBOdW1iZXJpbmdEb25lQ29uZmlnKSB7XG4gICAgc3VwZXIoYXBwKVxuICAgIHRoaXMuY29uZmlnID0gY29uZmlnXG4gIH1cblxuICBvbk9wZW4oKTogdm9pZCB7XG4gICAgY29uc3QgeyBjb250ZW50RWwsIHRpdGxlRWwgfSA9IHRoaXNcbiAgICB0aXRsZUVsLnNldFRleHQoJ051bWJlciBIZWFkaW5ncyAtIFN1Y2Nlc3NmdWxseSBDb21wbGV0ZWQnKVxuXG4gICAgY29udGVudEVsLmNyZWF0ZUVsKCdkaXYnLCB7IHRleHQ6IHRoaXMuY29uZmlnLm1lc3NhZ2UgfSlcbiAgICBjb250ZW50RWwuY3JlYXRlRWwoJ3ByZScsIHsgdGV4dDogdGhpcy5jb25maWcucHJlZm9ybWF0dGVkTWVzc2FnZSB9KVxuXG4gICAgY29udGVudEVsLmNyZWF0ZUVsKCdkaXYnLCB7IHRleHQ6IFwiRG8geW91IHdhbnQgdG8gc2F2ZSB0aGVzZSBzZXR0aW5ncyBpbiB0aGUgZG9jdW1lbnQncyBmcm9udCBtYXR0ZXI/XCIsIGNsczogJ251bWJlci1oZWFkaW5ncy1xdWVzdGlvbicgfSlcblxuICAgIGNvbnN0IGNvbnRhaW5lckZvckJ1dHRvbnMgPSBjb250ZW50RWwuY3JlYXRlRWwoJ2RpdicsIHsgY2xzOiAnbnVtYmVyLWhlYWRpbmdzLWJ1dHRvbi1jb250YWluZXInIH0pXG5cbiAgICBjb25zdCBub0J1dHRvbiA9IGNvbnRhaW5lckZvckJ1dHRvbnMuY3JlYXRlRWwoJ2J1dHRvbicsIHt9KVxuICAgIG5vQnV0dG9uLnNldFRleHQoJ05vJylcbiAgICBub0J1dHRvbi5vbkNsaWNrRXZlbnQoKGV2OiBNb3VzZUV2ZW50KSA9PiB7XG4gICAgICB0aGlzLmNsb3NlKClcbiAgICAgIHJldHVybiBldlxuICAgIH0pXG5cbiAgICBjb25zdCB5ZXNCdXR0b24gPSBjb250YWluZXJGb3JCdXR0b25zLmNyZWF0ZUVsKCdidXR0b24nLCB7fSlcbiAgICB5ZXNCdXR0b24uc2V0VGV4dCgnWWVzLCBzYXZlIHNldHRpbmdzIGluIGRvY3VtZW50JylcbiAgICB5ZXNCdXR0b24ub25DbGlja0V2ZW50KChldjogTW91c2VFdmVudCkgPT4ge1xuICAgICAgdGhpcy5jb25maWcuc2F2ZVNldHRpbmdzQ2FsbGJhY2soZmFsc2UpXG4gICAgICB0aGlzLmNsb3NlKClcbiAgICAgIHJldHVybiBldlxuICAgIH0pXG5cbiAgICBjb25zdCB5ZXNBbmRBdXRvQnV0dG9uID0gY29udGFpbmVyRm9yQnV0dG9ucy5jcmVhdGVFbCgnYnV0dG9uJywge30pXG4gICAgeWVzQW5kQXV0b0J1dHRvbi5zZXRUZXh0KCdZZXMsIHNhdmUgc2V0dGluZ3MgaW4gZG9jdW1lbnQsIGFuZCBhdXRvbWF0aWNhbGx5IG51bWJlcicpXG4gICAgeWVzQW5kQXV0b0J1dHRvbi5vbkNsaWNrRXZlbnQoKGV2OiBNb3VzZUV2ZW50KSA9PiB7XG4gICAgICB0aGlzLmNvbmZpZy5zYXZlU2V0dGluZ3NDYWxsYmFjayh0cnVlKVxuICAgICAgdGhpcy5jbG9zZSgpXG4gICAgICByZXR1cm4gZXZcbiAgICB9KVxuICB9XG5cbiAgb25DbG9zZSgpOiB2b2lkIHtcbiAgICBjb25zdCB7IGNvbnRlbnRFbCwgdGl0bGVFbCB9ID0gdGhpc1xuICAgIGNvbnRlbnRFbC5lbXB0eSgpXG4gICAgdGl0bGVFbC5lbXB0eSgpXG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNob3dOdW1iZXJpbmdEb25lTWVzc2FnZShhcHA6IEFwcCwgc2V0dGluZ3M6IE51bWJlckhlYWRpbmdzUGx1Z2luU2V0dGluZ3MpOiB2b2lkIHtcbiAgY29uc3Qgc2F2ZVNldHRpbmdzQ2FsbGJhY2sgPSAoc2hvdWxkQWRkQXV0b0ZsYWc6IGJvb2xlYW4pOiB2b2lkID0+IHtcbiAgICBjb25zdCB0d2Vha2VkU2V0dGluZ3MgPSB7IC4uLnNldHRpbmdzIH1cbiAgICBpZiAoc2hvdWxkQWRkQXV0b0ZsYWcpIHR3ZWFrZWRTZXR0aW5ncy5hdXRvID0gdHJ1ZVxuICAgIGNvbnN0IGZpbGUgPSBhcHAud29ya3NwYWNlLmdldEFjdGl2ZUZpbGUoKVxuICAgIGlmIChmaWxlKSB7XG4gICAgICBzYXZlU2V0dGluZ3NUb0Zyb250TWF0dGVyKGFwcC5maWxlTWFuYWdlciwgZmlsZSwgdHdlYWtlZFNldHRpbmdzKVxuICAgIH1cbiAgfVxuICBjb25zdCBjb25maWc6IE51bWJlcmluZ0RvbmVDb25maWcgPSB7XG4gICAgbWVzc2FnZTogYFN1Y2Nlc3NmdWxseSB1cGRhdGVkIGFsbCBoZWFkaW5nIG51bWJlcnMgaW4gdGhlIGRvY3VtZW50LCB1c2luZyB0aGUgc2V0dGluZ3MgYmVsb3cuIFxuICAgICAgU2VlIHNldHRpbmdzIHBhbmVsIHRvIGNoYW5nZSBob3cgaGVhZGluZ3MgYXJlIG51bWJlcmVkLCBvciB1c2UgZnJvbnQgbWF0dGVyXG4gICAgICAoc2VlIHNldHRpbmdzIHBhbmVsKS5gLFxuICAgIHByZWZvcm1hdHRlZE1lc3NhZ2U6IGBTa2lwIHRvcCBoZWFkaW5nIGxldmVsOiAke3NldHRpbmdzLnNraXBUb3BMZXZlbH1cbkZpcnN0IGhlYWRpbmcgbGV2ZWw6ICR7c2V0dGluZ3MuZmlyc3RMZXZlbH1cblN0YXJ0IG51bWJlcmluZyBmaXJzdCBoZWFkaW5nIGF0OiAke3NldHRpbmdzLnN0YXJ0QXR9XG5NYXhpbXVtIGhlYWRpbmcgbGV2ZWw6ICR7c2V0dGluZ3MubWF4TGV2ZWx9XG5TdHlsZSBmb3IgbGV2ZWwgMSBoZWFkaW5nczogJHtzZXR0aW5ncy5zdHlsZUxldmVsMX1cblN0eWxlIGZvciBsb3dlciBsZXZlbCBoZWFkaW5ncyAoYmVsb3cgbGV2ZWwgMSk6ICR7c2V0dGluZ3Muc3R5bGVMZXZlbE90aGVyfVxuU2VwYXJhdG9yOiAke3NldHRpbmdzLnNlcGFyYXRvcn1cblRhYmxlIG9mIENvbnRlbnRzIEFuY2hvcjogJHtzZXR0aW5ncy5jb250ZW50c31cblNraXAgSGVhZGluZ3MgQW5jaG9yOiAke3NldHRpbmdzLnNraXBIZWFkaW5nc31gLFxuICAgIHNhdmVTZXR0aW5nc0NhbGxiYWNrXG4gIH1cblxuICBjb25zdCBsZWFmID0gYXBwLndvcmtzcGFjZS5hY3RpdmVMZWFmXG4gIGlmIChsZWFmKSB7XG4gICAgbmV3IE51bWJlcmluZ0RvbmVNb2RhbChhcHAsIGNvbmZpZykub3BlbigpXG4gIH1cbn1cbiIsImltcG9ydCB7IEVkaXRvciwgRWRpdG9yQ2hhbmdlLCBFZGl0b3JSYW5nZSwgSGVhZGluZ0NhY2hlIH0gZnJvbSAnb2JzaWRpYW4nXG5pbXBvcnQgeyBWaWV3SW5mbyB9IGZyb20gJy4vYWN0aXZlVmlld0hlbHBlcnMnXG5pbXBvcnQgeyBOdW1iZXJpbmdUb2tlbiwgZmlyc3ROdW1iZXJpbmdUb2tlbkluU3R5bGUsIG1ha2VOdW1iZXJpbmdTdHJpbmcsIG5leHROdW1iZXJpbmdUb2tlbiwgc3RhcnRBdE9yWmVyb3RoSW5TdHlsZSB9IGZyb20gJy4vbnVtYmVyaW5nVG9rZW5zJ1xuaW1wb3J0IHsgTnVtYmVySGVhZGluZ3NQbHVnaW5TZXR0aW5ncywgaXNOb25FbXB0eUJsb2NrSWQgfSBmcm9tICcuL3NldHRpbmdzVHlwZXMnXG5pbXBvcnQgeyBTdXBwb3J0RmxhZ3MsIGNyZWF0ZVN1cHBvcnRGbGFnc0Zyb21TZXR0aW5ncywgZmluZFJhbmdlSW5IZWFkZXJTdHJpbmcgfSBmcm9tICcuL3RleHRQcm9jZXNzaW5nJ1xuXG5jb25zdCBUT0NfTElTVF9JVEVNX0JVTExFVCA9ICctJ1xuXG5mdW5jdGlvbiBtYWtlSGVhZGluZ0hhc2hTdHJpbmcoZWRpdG9yOiBFZGl0b3IsIGhlYWRpbmc6IEhlYWRpbmdDYWNoZSk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHJlZ2V4ID0gL15cXHN7MCw0fSMrL2dcbiAgY29uc3QgaGVhZGluZ0xpbmVTdHJpbmcgPSBlZGl0b3IuZ2V0TGluZShoZWFkaW5nLnBvc2l0aW9uLnN0YXJ0LmxpbmUpXG4gIGlmICghaGVhZGluZ0xpbmVTdHJpbmcpIHJldHVybiB1bmRlZmluZWRcblxuICBjb25zdCBtYXRjaGVzID0gaGVhZGluZ0xpbmVTdHJpbmcubWF0Y2gocmVnZXgpXG4gIGlmICghbWF0Y2hlcykgcmV0dXJuIHVuZGVmaW5lZFxuXG4gIGlmIChtYXRjaGVzLmxlbmd0aCAhPT0gMSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgY29uc29sZS5sb2coXCJVbmV4cGVjdGVkIGhlYWRpbmcgZm9ybWF0OiAnXCIgKyBoZWFkaW5nTGluZVN0cmluZyArIFwiJ1wiKVxuICAgIHJldHVybiB1bmRlZmluZWRcbiAgfVxuXG4gIGNvbnN0IG1hdGNoID0gbWF0Y2hlc1swXVxuICByZXR1cm4gbWF0Y2gudHJpbUxlZnQoKVxufVxuXG5mdW5jdGlvbiBmaW5kSGVhZGluZ1ByZWZpeFJhbmdlKGVkaXRvcjogRWRpdG9yLCBoZWFkaW5nOiBIZWFkaW5nQ2FjaGUsIGZsYWdzOiBTdXBwb3J0RmxhZ3MpOiBFZGl0b3JSYW5nZSB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGxpbmVOdW1iZXIgPSBoZWFkaW5nLnBvc2l0aW9uLnN0YXJ0LmxpbmVcbiAgY29uc3QgbGluZVRleHQgPSBlZGl0b3IuZ2V0TGluZShsaW5lTnVtYmVyKVxuICByZXR1cm4gZmluZFJhbmdlSW5IZWFkZXJTdHJpbmcobGluZVRleHQsIGxpbmVOdW1iZXIsIGZsYWdzKVxufVxuXG5mdW5jdGlvbiBjbGVhbkhlYWRpbmdUZXh0Rm9yVG9jKGh0ZXh0OiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAoaHRleHQuY29udGFpbnMoJ14nKSkge1xuICAgIGNvbnN0IHggPSBodGV4dC5zcGxpdCgnXicpXG4gICAgaWYgKHgubGVuZ3RoID4gMSkge1xuICAgICAgcmV0dXJuIHhbMF0udHJpbSgpXG4gICAgfVxuICB9XG4gIHJldHVybiBodGV4dC50cmltKClcbn1cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuZnVuY3Rpb24gY3JlYXRlVG9jRW50cnkoaDogSGVhZGluZ0NhY2hlLCBzZXR0aW5nczogTnVtYmVySGVhZGluZ3NQbHVnaW5TZXR0aW5ncywgaW5pdGlhbEhlYWRpbmdMZXZlbDogbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgdGV4dCA9IGguaGVhZGluZ1xuICBjb25zdCBjbGVhblRleHQgPSBjbGVhbkhlYWRpbmdUZXh0Rm9yVG9jKHRleHQpXG5cbiAgbGV0IGJ1bGxldEluZGVudCA9ICcnXG4gIGNvbnN0IHN0YXJ0TGV2ZWwgPSBpbml0aWFsSGVhZGluZ0xldmVsXG4gIGZvciAobGV0IGkgPSBzdGFydExldmVsOyBpIDwgaC5sZXZlbDsgaSsrKSB7XG4gICAgYnVsbGV0SW5kZW50ICs9ICdcXHQnXG4gIH1cblxuICBjb25zdCBlbnRyeUxpbmsgPSBgW1sjJHt0ZXh0fXwke2NsZWFuVGV4dH1dXWBcblxuICByZXR1cm4gYnVsbGV0SW5kZW50ICsgVE9DX0xJU1RfSVRFTV9CVUxMRVQgKyAnICcgKyBlbnRyeUxpbmtcbn1cblxuLy8gUmVwbGFjZSBhIHJhbmdlLCBidXQgb25seSBpZiB0aGVyZSBpcyBhIGNoYW5nZSBpbiB0ZXh0LCB0byBwcmV2ZW50IHBvbHV0aW5nIHRoZSB1bmRvIHN0YWNrXG5mdW5jdGlvbiByZXBsYWNlUmFuZ2VFY29ub21pY2FsbHkoZWRpdG9yOiBFZGl0b3IsIGNoYW5nZXM6IEVkaXRvckNoYW5nZVtdLCByYW5nZTogRWRpdG9yUmFuZ2UsIHRleHQ6IHN0cmluZyk6IHZvaWQge1xuICBjb25zdCBwcmV2aW91c1RleHQgPSBlZGl0b3IuZ2V0UmFuZ2UocmFuZ2UuZnJvbSwgcmFuZ2UudG8pXG5cbiAgaWYgKHByZXZpb3VzVGV4dCAhPT0gdGV4dCkge1xuICAgIGNoYW5nZXMucHVzaCh7XG4gICAgICB0ZXh0OiB0ZXh0LFxuICAgICAgZnJvbTogcmFuZ2UuZnJvbSxcbiAgICAgIHRvOiByYW5nZS50b1xuICAgIH0pXG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IHVwZGF0ZUhlYWRpbmdOdW1iZXJpbmcgPSAoXG4gIHZpZXdJbmZvOiBWaWV3SW5mbyB8IHVuZGVmaW5lZCxcbiAgc2V0dGluZ3M6IE51bWJlckhlYWRpbmdzUGx1Z2luU2V0dGluZ3Ncbik6IHZvaWQgPT4ge1xuICBpZiAoIXZpZXdJbmZvKSByZXR1cm5cbiAgY29uc3QgaGVhZGluZ3MgPSB2aWV3SW5mby5kYXRhLmhlYWRpbmdzID8/IFtdXG4gIGNvbnN0IGVkaXRvciA9IHZpZXdJbmZvLmVkaXRvclxuICBjb25zdCBzdXBwb3J0RmxhZ3MgPSBjcmVhdGVTdXBwb3J0RmxhZ3NGcm9tU2V0dGluZ3Moc2V0dGluZ3Muc3R5bGVMZXZlbDEsIHNldHRpbmdzLnN0eWxlTGV2ZWxPdGhlcilcblxuICBsZXQgcHJldmlvdXNMZXZlbCA9IDFcblxuICBsZXQgbnVtYmVyaW5nU3RhY2s6IE51bWJlcmluZ1Rva2VuW10gPSBbc3RhcnRBdE9yWmVyb3RoSW5TdHlsZShzZXR0aW5ncy5zdGFydEF0LCBzZXR0aW5ncy5zdHlsZUxldmVsMSldXG5cbiAgaWYgKHNldHRpbmdzLmZpcnN0TGV2ZWwgPiAxKSB7XG4gICAgcHJldmlvdXNMZXZlbCA9IHNldHRpbmdzLmZpcnN0TGV2ZWxcbiAgfSBlbHNlIGlmIChzZXR0aW5ncy5za2lwVG9wTGV2ZWwpIHtcbiAgICBwcmV2aW91c0xldmVsID0gMlxuICB9XG5cbiAgY29uc3QgY2hhbmdlczogRWRpdG9yQ2hhbmdlW10gPSBbXVxuXG4gIGZvciAoY29uc3QgaGVhZGluZyBvZiBoZWFkaW5ncykge1xuICAgIC8vIFVwZGF0ZSB0aGUgbnVtYmVyaW5nIHN0YWNrIGJhc2VkIG9uIHRoZSBsZXZlbCBhbmQgcHJldmlvdXMgbGV2ZWxcblxuICAgIGNvbnN0IGxldmVsID0gaGVhZGluZy5sZXZlbFxuXG4gICAgLy8gSGFuZGxlIHNraXBwZWQgJiBpZ25vcmVkIGxldmVscy5cbiAgICBpZiAoKHNldHRpbmdzLmZpcnN0TGV2ZWwgPiBsZXZlbCkgfHwgKHNldHRpbmdzLnNraXBUb3BMZXZlbCAmJiBsZXZlbCA9PT0gMSkpIHtcbiAgICAgIC8vIFJlc2V0cyB0aGUgbnVtYmVyaW5nIHdoZW4gYSBsZXZlbCBpcyBza2lwcGVkLlxuICAgICAgLy8gTm90ZTogVGhpcyBsZWF2ZXMgaGVhZGluZ3MgYXMgdGhleSBhcmUsIGFsbG93aW5nIHBlb3BsZSB0byBoYXZlIG51bWJlcnMgYXQgdGhlIHN0YXJ0IG9mXG4gICAgICAvLyBpZ25vcmVkIGhlYWRpbmdzLlxuXG4gICAgICBudW1iZXJpbmdTdGFjayA9IFtzdGFydEF0T3JaZXJvdGhJblN0eWxlKHNldHRpbmdzLnN0YXJ0QXQsIHNldHRpbmdzLnN0eWxlTGV2ZWwxKV1cblxuICAgICAgaWYgKHNldHRpbmdzLmZpcnN0TGV2ZWwgPiAxKSB7XG4gICAgICAgIHByZXZpb3VzTGV2ZWwgPSBzZXR0aW5ncy5maXJzdExldmVsXG4gICAgICB9IGVsc2UgaWYgKHNldHRpbmdzLnNraXBUb3BMZXZlbCkge1xuICAgICAgICBwcmV2aW91c0xldmVsID0gMlxuICAgICAgfVxuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICAvLyBIYW5kbGUgc2tpcHBlZCBoZWFkaW5nc1xuICAgIGlmIChzZXR0aW5ncy5za2lwSGVhZGluZ3MubGVuZ3RoID4gMCkge1xuICAgICAgaWYgKGhlYWRpbmcuaGVhZGluZy5lbmRzV2l0aChzZXR0aW5ncy5za2lwSGVhZGluZ3MpKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQWRqdXN0IG51bWJlcmluZyBzdGFja1xuICAgIGlmIChsZXZlbCA9PT0gcHJldmlvdXNMZXZlbCkge1xuICAgICAgY29uc3QgeCA9IG51bWJlcmluZ1N0YWNrLnBvcCgpXG4gICAgICBpZiAoeCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIG51bWJlcmluZ1N0YWNrLnB1c2gobmV4dE51bWJlcmluZ1Rva2VuKHgpKVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAobGV2ZWwgPCBwcmV2aW91c0xldmVsKSB7XG4gICAgICBmb3IgKGxldCBpID0gcHJldmlvdXNMZXZlbDsgaSA+IGxldmVsOyBpLS0pIHtcbiAgICAgICAgbnVtYmVyaW5nU3RhY2sucG9wKClcbiAgICAgIH1cbiAgICAgIGNvbnN0IHggPSBudW1iZXJpbmdTdGFjay5wb3AoKVxuICAgICAgaWYgKHggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBudW1iZXJpbmdTdGFjay5wdXNoKG5leHROdW1iZXJpbmdUb2tlbih4KSlcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGxldmVsID4gcHJldmlvdXNMZXZlbCkge1xuICAgICAgZm9yIChsZXQgaSA9IHByZXZpb3VzTGV2ZWw7IGkgPCBsZXZlbDsgaSsrKSB7XG4gICAgICAgIG51bWJlcmluZ1N0YWNrLnB1c2goZmlyc3ROdW1iZXJpbmdUb2tlbkluU3R5bGUoc2V0dGluZ3Muc3R5bGVMZXZlbE90aGVyKSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTZXQgdGhlIHByZXZpb3VzIGxldmVsIHRvIHRoaXMgbGV2ZWwgZm9yIHRoZSBuZXh0IGl0ZXJhdGlvblxuICAgIHByZXZpb3VzTGV2ZWwgPSBsZXZlbFxuXG4gICAgaWYgKGxldmVsID4gc2V0dGluZ3MubWF4TGV2ZWwpIHtcbiAgICAgIC8vIElmIHdlIGFyZSBhYm92ZSB0aGUgbWF4IGxldmVsLCBqdXN0IGRvbid0IG51bWJlciBpdFxuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICAvLyBGaW5kIHRoZSByYW5nZSB0byByZXBsYWNlLCBhbmQgdGhlbiBkbyBpdFxuICAgIGNvbnN0IHByZWZpeFJhbmdlID0gZmluZEhlYWRpbmdQcmVmaXhSYW5nZShlZGl0b3IsIGhlYWRpbmcsIHN1cHBvcnRGbGFncylcbiAgICBpZiAocHJlZml4UmFuZ2UgPT09IHVuZGVmaW5lZCkgcmV0dXJuXG4gICAgY29uc3QgaGVhZGluZ0hhc2hTdHJpbmcgPSBtYWtlSGVhZGluZ0hhc2hTdHJpbmcoZWRpdG9yLCBoZWFkaW5nKVxuICAgIGlmIChoZWFkaW5nSGFzaFN0cmluZyA9PT0gdW5kZWZpbmVkKSByZXR1cm5cbiAgICBjb25zdCBwcmVmaXhTdHJpbmcgPSBtYWtlTnVtYmVyaW5nU3RyaW5nKG51bWJlcmluZ1N0YWNrKVxuICAgIHJlcGxhY2VSYW5nZUVjb25vbWljYWxseShlZGl0b3IsIGNoYW5nZXMsIHByZWZpeFJhbmdlLCBoZWFkaW5nSGFzaFN0cmluZyArIHByZWZpeFN0cmluZyArIHNldHRpbmdzLnNlcGFyYXRvciArICcgJylcbiAgfVxuXG4gIC8vIEV4ZWN1dGUgdGhlIHRyYW5zYWN0aW9uIHRvIG1ha2UgYWxsIHRoZSBjaGFuZ2VzIGF0IG9uY2VcbiAgaWYgKGNoYW5nZXMubGVuZ3RoID4gMCkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgY29uc29sZS5sb2coJ051bWJlciBIZWFkaW5ncyBQbHVnaW46IEFwcGx5aW5nIGhlYWRpbmdzIG51bWJlcmluZyBjaGFuZ2VzOicsIGNoYW5nZXMubGVuZ3RoKVxuICAgIGVkaXRvci50cmFuc2FjdGlvbih7XG4gICAgICBjaGFuZ2VzOiBjaGFuZ2VzXG4gICAgfSlcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgdXBkYXRlVGFibGVPZkNvbnRlbnRzID0gKFxuICB2aWV3SW5mbzogVmlld0luZm8gfCB1bmRlZmluZWQsXG4gIHNldHRpbmdzOiBOdW1iZXJIZWFkaW5nc1BsdWdpblNldHRpbmdzXG4pOiB2b2lkID0+IHtcbiAgaWYgKCF2aWV3SW5mbykgcmV0dXJuXG4gIGNvbnN0IGhlYWRpbmdzID0gdmlld0luZm8uZGF0YS5oZWFkaW5ncyA/PyBbXVxuICBjb25zdCBlZGl0b3IgPSB2aWV3SW5mby5lZGl0b3JcblxuICBpZiAoIWlzTm9uRW1wdHlCbG9ja0lkKHNldHRpbmdzLmNvbnRlbnRzKSkgcmV0dXJuXG5cbiAgbGV0IHRvY0hlYWRpbmc6IEhlYWRpbmdDYWNoZSB8IHVuZGVmaW5lZFxuICBsZXQgdG9jQnVpbGRlciA9ICdcXG4nXG4gIGNvbnN0IGNoYW5nZXM6IEVkaXRvckNoYW5nZVtdID0gW11cblxuICAvLyBJbiBjYXNlIGhlYWRpbmdzIHN0YXJ0IGFib3ZlIGxldmVsIDEsIHdlIGRvbid0IHdhbnQgdG8gaW5kZW50IHRoZSBidWxsZXRzIHRvbyBtdWNoXG4gIGxldCBpbml0aWFsSGVhZGluZ0xldmVsID0gMVxuICBpZiAoaGVhZGluZ3MubGVuZ3RoID4gMCkge1xuICAgIGluaXRpYWxIZWFkaW5nTGV2ZWwgPSBoZWFkaW5nc1swXS5sZXZlbFxuICB9XG5cbiAgZm9yIChjb25zdCBoZWFkaW5nIG9mIGhlYWRpbmdzKSB7XG4gICAgLy8gT1JERVJJTkc6IEltcG9ydGFudCB0byBmaW5kIHRoZSBUT0MgaGVhZGluZyBiZWZvcmUgc2tpcHBpbmcgc2tpcHBlZCBoZWFkaW5ncywgc2luY2UgdGhhdCBpcyBmb3IgbnVtYmVyaW5nXG5cbiAgICAvLyBGaW5kIHRoZSBUT0MgaGVhZGluZ1xuICAgIGlmIChoZWFkaW5nLmhlYWRpbmcuZW5kc1dpdGgoc2V0dGluZ3MuY29udGVudHMpKSB7XG4gICAgICB0b2NIZWFkaW5nID0gaGVhZGluZ1xuICAgIH1cblxuICAgIC8qIFRoaXMgY29kZSBsZXRzIHVzIHNraXAgVE9DIGxpbmVzIGZvciBza2lwcGVkIGhlYWRpbmdzLCBidXQgZG9lc24ndCB3b3JrIHdlbGwgd2l0aCBmaXJzdC1sZXZlbCBzZXR0aW5nXG4gICAgaWYgKChzZXR0aW5ncy5za2lwVG9wTGV2ZWwgJiYgaGVhZGluZy5sZXZlbCA9PT0gMSkgfHwgKGhlYWRpbmcubGV2ZWwgPiBzZXR0aW5ncy5tYXhMZXZlbCkpIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgICovXG5cbiAgICBjb25zdCB0b2NFbnRyeSA9IGNyZWF0ZVRvY0VudHJ5KGhlYWRpbmcsIHNldHRpbmdzLCBpbml0aWFsSGVhZGluZ0xldmVsKVxuICAgIHRvY0J1aWxkZXIgKz0gdG9jRW50cnkgKyAnXFxuJ1xuICB9XG5cbiAgLy8gSW5zZXJ0IHRoZSBnZW5lcmF0ZWQgdGFibGUgb2YgY29udGVudHNcbiAgaWYgKHRvY0hlYWRpbmcpIHtcbiAgICBjb25zdCBmcm9tID0ge1xuICAgICAgbGluZTogdG9jSGVhZGluZy5wb3NpdGlvbi5zdGFydC5saW5lICsgMSxcbiAgICAgIGNoOiAwXG4gICAgfVxuXG4gICAgLy8gRmluZCB0aGUgZW5kIG9mIHRoZSBUT0Mgc2VjdGlvblxuICAgIGNvbnN0IHN0YXJ0aW5nTGluZSA9IHRvY0hlYWRpbmcucG9zaXRpb24uc3RhcnQubGluZSArIDFcbiAgICBsZXQgZW5kaW5nTGluZSA9IHN0YXJ0aW5nTGluZVxuICAgIGxldCBmb3VuZExpc3QgPSBmYWxzZVxuICAgIGNvbnN0IGxhc3RMaW5lSW5FZGl0b3IgPSBlZGl0b3IubGFzdExpbmUoKVxuICAgIGZvciAoOyA7IGVuZGluZ0xpbmUrKykge1xuICAgICAgY29uc3QgbGluZSA9IGVkaXRvci5nZXRMaW5lKGVuZGluZ0xpbmUpXG4gICAgICBpZiAobGluZSA9PT0gdW5kZWZpbmVkIHx8IGVuZGluZ0xpbmUgPiBsYXN0TGluZUluRWRpdG9yKSB7XG4gICAgICAgIC8vIFJlYWNoZWQgZW5kIG9mIGZpbGUsIGluc2VydCBhdCB0aGUgc3RhcnQgb2YgdGhlIFRPQyBzZWN0aW9uXG4gICAgICAgIGVuZGluZ0xpbmUgPSBzdGFydGluZ0xpbmVcbiAgICAgICAgYnJlYWtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHRyaW1tZWRMaW5lVGV4dCA9IGxpbmUudHJpbVN0YXJ0KClcbiAgICAgIGlmIChmb3VuZExpc3QpIHtcbiAgICAgICAgaWYgKCF0cmltbWVkTGluZVRleHQuc3RhcnRzV2l0aChUT0NfTElTVF9JVEVNX0JVTExFVCkpIGJyZWFrXG4gICAgICAgIGlmICh0cmltbWVkTGluZVRleHQuc3RhcnRzV2l0aCgnIycpKSBicmVha1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHRyaW1tZWRMaW5lVGV4dC5zdGFydHNXaXRoKFRPQ19MSVNUX0lURU1fQlVMTEVUKSkge1xuICAgICAgICAgIGZvdW5kTGlzdCA9IHRydWVcbiAgICAgICAgfSBlbHNlIGlmICh0cmltbWVkTGluZVRleHQuc3RhcnRzV2l0aCgnIycpKSB7XG4gICAgICAgICAgLy8gUmVhY2hlZCB0aGUgbmV4dCBoZWFkaW5nIHdpdGhvdXQgZmluZGluZyBleGlzdGluZyBUT0MgbGlzdCwgaW5zZXJ0IGF0IHRoZSBzdGFydCBvZiB0aGUgVE9DIHNlY3Rpb25cbiAgICAgICAgICBlbmRpbmdMaW5lID0gc3RhcnRpbmdMaW5lXG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRvY0J1aWxkZXIgPT09ICdcXG4nKSB7XG4gICAgICB0b2NCdWlsZGVyID0gJydcbiAgICB9XG5cbiAgICBjb25zdCB0byA9IHtcbiAgICAgIGxpbmU6IGVuZGluZ0xpbmUsXG4gICAgICBjaDogMFxuICAgIH1cbiAgICBjb25zdCByYW5nZSA9IHsgZnJvbSwgdG8gfVxuICAgIHJlcGxhY2VSYW5nZUVjb25vbWljYWxseShlZGl0b3IsIGNoYW5nZXMsIHJhbmdlLCB0b2NCdWlsZGVyKVxuICB9XG5cbiAgLy8gRXhlY3V0ZSB0aGUgdHJhbnNhY3Rpb24gdG8gbWFrZSBhbGwgdGhlIGNoYW5nZXMgYXQgb25jZVxuICBpZiAoY2hhbmdlcy5sZW5ndGggPiAwKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICBjb25zb2xlLmxvZygnTnVtYmVyIEhlYWRpbmdzIFBsdWdpbjogQXBwbHlpbmcgdGFibGUgb2YgY29udGVudHMgY2hhbmdlczonLCBjaGFuZ2VzLmxlbmd0aClcbiAgICBlZGl0b3IudHJhbnNhY3Rpb24oe1xuICAgICAgY2hhbmdlczogY2hhbmdlc1xuICAgIH0pXG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IHJlbW92ZUhlYWRpbmdOdW1iZXJpbmcgPSAoXG4gIHZpZXdJbmZvOiBWaWV3SW5mbyB8IHVuZGVmaW5lZFxuKTogdm9pZCA9PiB7XG4gIGlmICghdmlld0luZm8pIHJldHVyblxuICBjb25zdCBoZWFkaW5ncyA9IHZpZXdJbmZvLmRhdGEuaGVhZGluZ3MgPz8gW11cbiAgY29uc3QgZWRpdG9yID0gdmlld0luZm8uZWRpdG9yXG5cbiAgY29uc3QgY2hhbmdlczogRWRpdG9yQ2hhbmdlW10gPSBbXVxuXG4gIGZvciAoY29uc3QgaGVhZGluZyBvZiBoZWFkaW5ncykge1xuICAgIGNvbnN0IHByZWZpeFJhbmdlID0gZmluZEhlYWRpbmdQcmVmaXhSYW5nZShlZGl0b3IsIGhlYWRpbmcsIHsgYWxwaGFiZXQ6IHRydWUsIHJvbWFuOiB0cnVlIH0pXG4gICAgaWYgKHByZWZpeFJhbmdlID09PSB1bmRlZmluZWQpIHJldHVyblxuICAgIGNvbnN0IGhlYWRpbmdIYXNoU3RyaW5nID0gbWFrZUhlYWRpbmdIYXNoU3RyaW5nKGVkaXRvciwgaGVhZGluZylcbiAgICBpZiAoaGVhZGluZ0hhc2hTdHJpbmcgPT09IHVuZGVmaW5lZCkgcmV0dXJuXG4gICAgcmVwbGFjZVJhbmdlRWNvbm9taWNhbGx5KGVkaXRvciwgY2hhbmdlcywgcHJlZml4UmFuZ2UsIGhlYWRpbmdIYXNoU3RyaW5nICsgJyAnKVxuICB9XG5cbiAgaWYgKGNoYW5nZXMubGVuZ3RoID4gMCkge1xuICAgIGVkaXRvci50cmFuc2FjdGlvbih7XG4gICAgICBjaGFuZ2VzOiBjaGFuZ2VzXG4gICAgfSlcbiAgfVxufVxuIiwiaW1wb3J0IHsgQXBwLCBQbHVnaW4sIFBsdWdpblNldHRpbmdUYWIsIFNldHRpbmcgfSBmcm9tICdvYnNpZGlhbidcclxuaW1wb3J0IHsgZ2V0Vmlld0luZm8sIGlzVmlld0FjdGl2ZSB9IGZyb20gJy4vYWN0aXZlVmlld0hlbHBlcnMnXHJcbmltcG9ydCB7IGdldEZyb250TWF0dGVyU2V0dGluZ3NPckFsdGVybmF0aXZlLCBzYXZlU2V0dGluZ3NUb0Zyb250TWF0dGVyIH0gZnJvbSAnLi9mcm9udE1hdHRlcidcclxuaW1wb3J0IHsgc2hvd051bWJlcmluZ0RvbmVNZXNzYWdlIH0gZnJvbSAnLi9tZXNzYWdlcydcclxuaW1wb3J0IHsgcmVtb3ZlSGVhZGluZ051bWJlcmluZywgdXBkYXRlSGVhZGluZ051bWJlcmluZywgdXBkYXRlVGFibGVPZkNvbnRlbnRzIH0gZnJvbSAnLi9udW1iZXJpbmcnXHJcbmltcG9ydCB7IE51bWJlcmluZ1N0eWxlIH0gZnJvbSAnLi9udW1iZXJpbmdUb2tlbnMnXHJcbmltcG9ydCB7IERFRkFVTFRfU0VUVElOR1MsIE51bWJlckhlYWRpbmdzUGx1Z2luU2V0dGluZ3MgfSBmcm9tICcuL3NldHRpbmdzVHlwZXMnXHJcblxyXG5jbGFzcyBOdW1iZXJIZWFkaW5nc1BsdWdpblNldHRpbmdUYWIgZXh0ZW5kcyBQbHVnaW5TZXR0aW5nVGFiIHtcclxuICBwbHVnaW46IE51bWJlckhlYWRpbmdzUGx1Z2luXHJcblxyXG4gIGNvbnN0cnVjdG9yKGFwcDogQXBwLCBwbHVnaW46IE51bWJlckhlYWRpbmdzUGx1Z2luKSB7XHJcbiAgICBzdXBlcihhcHAsIHBsdWdpbilcclxuICAgIHRoaXMucGx1Z2luID0gcGx1Z2luXHJcbiAgfVxyXG5cclxuICBkaXNwbGF5KCk6IHZvaWQge1xyXG4gICAgY29uc3QgeyBjb250YWluZXJFbCB9ID0gdGhpc1xyXG5cclxuICAgIGNvbnRhaW5lckVsLmVtcHR5KClcclxuXHJcbiAgICBjb250YWluZXJFbC5jcmVhdGVFbCgnaDInLCB7IHRleHQ6ICdOdW1iZXIgSGVhZGluZ3MgLSBTZXR0aW5ncycgfSlcclxuXHJcbiAgICBjb250YWluZXJFbC5jcmVhdGVFbCgnZGl2JywgeyB0ZXh0OiAnVG8gYWRkIG51bWJlcmluZyB0byB5b3VyIGRvY3VtZW50LCBicmluZyB1cCB0aGUgY29tbWFuZCB3aW5kb3cgKG9uIE1hYywgdHlwZSBDTUQrUCksIGFuZCB0aGVuIHR5cGUgXCJOdW1iZXIgSGVhZGluZ3NcIiB0byBzZWUgYSBsaXN0IG9mIGF2YWlsYWJsZSBjb21tYW5kcy4nIH0pXHJcblxyXG4gICAgY29udGFpbmVyRWwuY3JlYXRlRWwoJ2JyJywge30pXHJcblxyXG4gICAgY29udGFpbmVyRWwuY3JlYXRlRWwoJ2RpdicsIHsgdGV4dDogJ0lmIHRoZSBkb2N1bWVudCBoYXMgZnJvbnQgbWF0dGVyIGRlZmluZWQgd2l0aCB0aGUgYmVsb3cgc2V0dGluZ3MsIHRoZSBwcm9qZWN0LXdpZGUgc2V0dGluZ3MgZGVmaW5lZCBvbiB0aGlzIHNjcmVlbiB3aWxsIGJlIGlnbm9yZWQuIFlvdSBjYW4gZGVmaW5lIGZyb250IG1hdHRlciBsaWtlIHRoaXM6JyB9KVxyXG5cclxuICAgIGNvbnRhaW5lckVsLmNyZWF0ZUVsKCdwcmUnLCB7XHJcbiAgICAgIHRleHQ6IGAgICAgLS0tXHJcbiAgICBhbGlhczpcclxuICAgIC0gRXhhbXBsZSBBbGlhc1xyXG4gICAgdGFnczpcclxuICAgIC0gZXhhbXBsZS10YWdcclxuICAgIG51bWJlciBoZWFkaW5nczogZmlyc3QtbGV2ZWwgMSwgc3RhcnQtYXQgMiwgbWF4IDYsIDEuMSwgYXV0bywgY29udGVudHMgXnRvY1xyXG4gICAgLS0tYFxyXG4gICAgfSlcclxuXHJcbiAgICBjb250YWluZXJFbC5jcmVhdGVFbCgnZGl2Jywge1xyXG4gICAgICB0ZXh0OiBgXHJcbiAgICAgIFRoZSAnbnVtYmVyIGhlYWRpbmdzJyBmcm9udCBtYXR0ZXIga2V5IGlzIHVzZWQgdG8gc3RvcmUgbnVtYmVyaW5nIHNldHRpbmdzIHNwZWNpZmljIHRvIHRoZSBmaWxlLiBUaGVyZSBhcmUgZm91ciBwb3NzaWJsZSBvcHRpb25zXHJcbiAgICAgIGluIHRoZSB2YWx1ZSB0byB0aGUgcmlnaHQgb2YgdGhlIGNvbG9uLCBzZXBhcmF0ZWQgYnkgY29tbWFzLlxyXG4gICAgYFxyXG4gICAgfSlcclxuXHJcbiAgICBjb25zdCB1bCA9IGNvbnRhaW5lckVsLmNyZWF0ZUVsKCd1bCcsIHt9KVxyXG5cclxuICAgIGNvbnN0IGxpMCA9IHVsLmNyZWF0ZUVsKCdsaScsIHt9KVxyXG4gICAgbGkwLmNyZWF0ZUVsKCdiJywgeyB0ZXh0OiAnQXV0b21hdGljIG51bWJlcmluZycgfSlcclxuICAgIGxpMC5jcmVhdGVFbCgnc3BhbicsIHsgdGV4dDogJzogSWYgXFwnYXV0b1xcJyBhcHBlYXJzLCB0aGUgZG9jdW1lbnQgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IG51bWJlcmVkLicgfSlcclxuXHJcbiAgICBjb25zdCBsaTEgPSB1bC5jcmVhdGVFbCgnbGknLCB7fSlcclxuICAgIGxpMS5jcmVhdGVFbCgnYicsIHsgdGV4dDogJ0ZpcnN0IGxldmVsIHRvIG51bWJlcicgfSlcclxuICAgIGxpMS5jcmVhdGVFbCgnc3BhbicsIHsgdGV4dDogJzogSWYgXFwnZmlyc3QtbGV2ZWwgMlxcJyBhcHBlYXJzLCB0aGUgbnVtYmVyaW5nIHdpbGwgc3RhcnQgYXQgdGhlIHNlY29uZCBsZXZlbCcgfSlcclxuXHJcbiAgICBjb25zdCBsaTIgPSB1bC5jcmVhdGVFbCgnbGknLCB7fSlcclxuICAgIGxpMi5jcmVhdGVFbCgnYicsIHsgdGV4dDogJ1N0YXJ0IG51bWJlcmluZyBmaXJzdCBoZWFkaW5nIGF0JyB9KVxyXG4gICAgbGkyLmNyZWF0ZUVsKCdzcGFuJywgeyB0ZXh0OiAnOiBJZiBcXCdzdGFydC1hdCBDXFwnIGFwcGVhcnMsIHRoZSBudW1iZXJpbmcgb2YgdGhlIGZpcnN0IGxldmVsIHdpbGwgc3RhcnQgYXQgQywgaW5zdGVhZCBvZiBBJyB9KVxyXG5cclxuICAgIGNvbnN0IGxpMyA9IHVsLmNyZWF0ZUVsKCdsaScsIHt9KVxyXG4gICAgbGkzLmNyZWF0ZUVsKCdiJywgeyB0ZXh0OiAnTWF4aW11bSBsZXZlbCB0byBudW1iZXInIH0pXHJcbiAgICBsaTMuY3JlYXRlRWwoJ3NwYW4nLCB7IHRleHQ6ICc6IElmIFxcJ21heCA2XFwnIGFwcGVhcnMsIHRoZSBoZWFkaW5ncyBhYm92ZSBsZXZlbCA2IHdpbGwgYmUgc2tpcHBlZC4nIH0pXHJcblxyXG4gICAgY29uc3QgbGk0ID0gdWwuY3JlYXRlRWwoJ2xpJywge30pXHJcbiAgICBsaTQuY3JlYXRlRWwoJ2InLCB7IHRleHQ6ICdUYWJsZSBvZiBjb250ZW50cyBhbmNob3InIH0pXHJcbiAgICBsaTQuY3JlYXRlRWwoJ3NwYW4nLCB7IHRleHQ6ICc6IElmIFxcJ2NvbnRlbnRzIF50b2NcXCcgYXBwZWFycywgdGhlIGhlYWRpbmcgdGhhdCBlbmRzIHdpdGggdGhlIGFuY2hvciBedG9jIHdpbGwgaGF2ZSBhIHRhYmxlIG9mIGNvbnRlbnRzIGluc2VydGVkIGJlbmVhdGggaXQuJyB9KVxyXG5cclxuICAgIGNvbnN0IGxpNDEgPSB1bC5jcmVhdGVFbCgnbGknLCB7fSlcclxuICAgIGxpNDEuY3JlYXRlRWwoJ2InLCB7IHRleHQ6ICdTa2lwIGhlYWRpbmdzIGFuY2hvcicgfSlcclxuICAgIGxpNDEuY3JlYXRlRWwoJ3NwYW4nLCB7IHRleHQ6ICc6IElmIFxcJ3NraXAgXnNraXBwZWRcXCcgYXBwZWFycywgdGhlIGhlYWRpbmcgdGhhdCBlbmRzIHdpdGggdGhlIGFuY2hvciBec2tpcHBlZCB3aWxsIG5vdCBiZSBudW1iZXJlZC4nIH0pXHJcblxyXG4gICAgY29uc3QgbGk1ID0gdWwuY3JlYXRlRWwoJ2xpJywge30pXHJcbiAgICBsaTUuY3JlYXRlRWwoJ2InLCB7IHRleHQ6ICdOdW1iZXJpbmcgc3R5bGUnIH0pXHJcbiAgICBsaTUuY3JlYXRlRWwoJ3NwYW4nLCB7XHJcbiAgICAgIHRleHQ6IGA6XHJcbiAgICAgIEEgc3R5bGUgdGV4dCBsaWtlICcxLjEnLCAnQS4xJywgb3IgJ18uMS4xJyB0ZWxscyB0aGUgcGx1Z2luIGhvdyB0byBmb3JtYXQgdGhlIGhlYWRpbmdzLlxyXG4gICAgICBJZiBhIHN0eWxlIHN0cmluZyBlbmRzIHdpdGggJy4nIChhIGRvdCksICc6JyAoYSBjb2xvbiksICctJyAoYSBkYXNoKSwgJ+KAlCcgKGFuIGVtZGFzaCksIG9yICcpJyAoYSByaWdodCBwYXJlbnRoZXNpcyksIHRoZSBoZWFkaW5nIG51bWJlcnMgd2lsbCBiZSBzZXBhcmF0ZWQgZnJvbSB0aGUgaGVhZGluZyB0aXRsZVxyXG4gICAgICB3aXRoIHRoYXQgc3ltYm9sLmBcclxuICAgIH0pXHJcblxyXG4gICAgY29uc3QgdWwzID0gbGk1LmNyZWF0ZUVsKCd1bCcsIHt9KVxyXG4gICAgdWwzLmNyZWF0ZUVsKCdsaScsIHtcclxuICAgICAgdGV4dDogYCAgICAgIFxyXG4gICAgICBGb3IgZXhhbXBsZSwgJzEuMScgbWVhbnMgYm90aCB0b3AgbGV2ZWwgYW5kIG90aGVyIGhlYWRpbmdzIHdpbGwgYmUgbnVtYmVyZWQgc3RhcnRpbmcgZnJvbSAnMScuXHJcbiAgICBgXHJcbiAgICB9KVxyXG4gICAgdWwzLmNyZWF0ZUVsKCdsaScsIHtcclxuICAgICAgdGV4dDogYCAgICAgIFxyXG4gICAgICBGb3IgZXhhbXBsZSwgJ0EuMScgbWVhbnMgdG9wIGxldmVsIGhlYWRpbmdzIHdpbGwgYmUgbnVtYmVyZWQgc3RhcnRpbmcgZnJvbSAnQScuXHJcbiAgICBgXHJcbiAgICB9KVxyXG4gICAgdWwzLmNyZWF0ZUVsKCdsaScsIHtcclxuICAgICAgdGV4dDogYCAgICAgIFxyXG4gICAgICBGb3IgZXhhbXBsZSwgJ18uQS4xJyBtZWFucyB0b3AgbGV2ZWwgaGVhZGluZ3Mgd2lsbCBOT1QgYmUgbnVtYmVyZWQsIGJ1dCB0aGUgbmV4dCBsZXZlbHMgd2lsbCBiZSBudW1iZXJlZCB3aXRoIGxldHRlcnMgYW5kIG51bWJlcnMuXHJcbiAgICBgXHJcbiAgICB9KVxyXG4gICAgdWwzLmNyZWF0ZUVsKCdsaScsIHtcclxuICAgICAgdGV4dDogYCAgICAgIFxyXG4gICAgICBGb3IgZXhhbXBsZSwgJzEuMTonIG1lYW5zIGhlYWRpbmdzIHdpbGwgbG9vayBsaWtlICcjIyAyLjQ6IEV4YW1wbGUgSGVhZGluZydcclxuICAgIGBcclxuICAgIH0pXHJcbiAgICB1bDMuY3JlYXRlRWwoJ2xpJywge1xyXG4gICAgICB0ZXh0OiBgICAgICAgXHJcbiAgICAgIEZvciBleGFtcGxlLCAnQS4xLScgbWVhbnMgaGVhZGluZ3Mgd2lsbCBsb29rIGxpa2UgJyMjIEIuNS0gRXhhbXBsZSBIZWFkaW5nJ1xyXG4gICAgYFxyXG4gICAgfSlcclxuICAgIHVsMy5jcmVhdGVFbCgnbGknLCB7XHJcbiAgICAgIHRleHQ6IGAgICAgICBcclxuICAgICAgRm9yIGV4YW1wbGUsICdJLkEg4oCUJyBtZWFucyBoZWFkaW5ncyB3aWxsIGxvb2sgbGlrZSAnIyMgSVYuQSDigJQgRXhhbXBsZSBIZWFkaW5nJyAod2l0aCBSb21hbiBudW1lcmFscylcclxuICAgIGBcclxuICAgIH0pXHJcblxyXG4gICAgY29uc3QgbGkxMDAgPSB1bC5jcmVhdGVFbCgnbGknLCB7fSlcclxuICAgIGxpMTAwLmNyZWF0ZUVsKCdiJywgeyB0ZXh0OiAnTnVtYmVyaW5nIG9mZicgfSlcclxuICAgIGxpMTAwLmNyZWF0ZUVsKCdzcGFuJywgeyB0ZXh0OiAnOiBJZiBcXCdvZmZcXCcgYXBwZWFycywgdGhlIGRvY3VtZW50IHdpbGwgbm90IGJlIG51bWJlcmVkLicgfSlcclxuXHJcbiAgICBuZXcgU2V0dGluZyhjb250YWluZXJFbClcclxuICAgICAgLnNldE5hbWUoJ1NraXAgdG9wIGhlYWRpbmcgbGV2ZWwnKVxyXG4gICAgICAuc2V0RGVzYygnSWYgc2VsZWN0ZWQsIG51bWJlcmluZyB3aWxsIG5vdCBiZSBhcHBsaWVkIHRvIHRoZSB0b3AgaGVhZGluZyBsZXZlbC4nKVxyXG4gICAgICAuYWRkVG9nZ2xlKHRvZ2dsZSA9PiB0b2dnbGVcclxuICAgICAgICAuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3Muc2tpcFRvcExldmVsKVxyXG4gICAgICAgIC5zZXRUb29sdGlwKCdTa2lwIHRvcCBoZWFkaW5nIGxldmVsJylcclxuICAgICAgICAub25DaGFuZ2UoYXN5bmMgKHZhbHVlKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5za2lwVG9wTGV2ZWwgPSB2YWx1ZVxyXG4gICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKClcclxuICAgICAgICB9KSlcclxuXHJcbiAgICBuZXcgU2V0dGluZyhjb250YWluZXJFbClcclxuICAgICAgLnNldE5hbWUoJ0ZpcnN0IGhlYWRpbmcgbGV2ZWwnKVxyXG4gICAgICAuc2V0RGVzYygnRmlyc3QgaGVhZGluZyBsZXZlbCB0byBudW1iZXIuJylcclxuICAgICAgLmFkZFNsaWRlcihzbGlkZXIgPT4gc2xpZGVyXHJcbiAgICAgICAgLnNldExpbWl0cygxLCA2LCAxKVxyXG4gICAgICAgIC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5maXJzdExldmVsKVxyXG4gICAgICAgIC5zZXREeW5hbWljVG9vbHRpcCgpXHJcbiAgICAgICAgLm9uQ2hhbmdlKGFzeW5jICh2YWx1ZSkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MuZmlyc3RMZXZlbCA9IHZhbHVlXHJcbiAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKVxyXG4gICAgICAgIH0pKVxyXG5cclxuICAgIG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxyXG4gICAgICAuc2V0TmFtZSgnU3RhcnQgbnVtYmVyaW5nIGF0JylcclxuICAgICAgLnNldERlc2MoJ1N0YXJ0IG51bWJlcmluZyB0aGUgZmlyc3QgaGVhZGluZyBsZXZlbCBmcm9tIHRoaXMgdmFsdWUuJylcclxuICAgICAgLmFkZFRleHQodGV4dCA9PiB0ZXh0XHJcbiAgICAgICAgLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLnN0YXJ0QXQpXHJcbiAgICAgICAgLm9uQ2hhbmdlKGFzeW5jICh2YWx1ZSkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3Muc3RhcnRBdCA9IHZhbHVlXHJcbiAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKVxyXG4gICAgICAgIH0pKVxyXG5cclxuICAgIG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxyXG4gICAgICAuc2V0TmFtZSgnTWF4aW11bSBoZWFkaW5nIGxldmVsJylcclxuICAgICAgLnNldERlc2MoJ01heGltdW0gaGVhZGluZyBsZXZlbCB0byBudW1iZXIuJylcclxuICAgICAgLmFkZFNsaWRlcihzbGlkZXIgPT4gc2xpZGVyXHJcbiAgICAgICAgLnNldExpbWl0cygxLCA2LCAxKVxyXG4gICAgICAgIC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5tYXhMZXZlbClcclxuICAgICAgICAuc2V0RHluYW1pY1Rvb2x0aXAoKVxyXG4gICAgICAgIC5vbkNoYW5nZShhc3luYyAodmFsdWUpID0+IHtcclxuICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLm1heExldmVsID0gdmFsdWVcclxuICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpXHJcbiAgICAgICAgfSkpXHJcblxyXG4gICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXHJcbiAgICAgIC5zZXROYW1lKCdTdHlsZSBmb3IgbGV2ZWwgMSBoZWFkaW5ncycpXHJcbiAgICAgIC5zZXREZXNjKCdEZWZpbmVzIHRoZSBudW1iZXJpbmcgc3R5bGUgZm9yIGxldmVsIG9uZSBoZWFkaW5ncy4gVmFsaWQgdmFsdWVzIGFyZSAxIChmb3IgbnVtYmVycykgb3IgQSAoZm9yIGNhcGl0YWwgbGV0dGVycykgb3IgSSAoZm9yIFJvbWFuIG51bWVyYWxzKS4nKVxyXG4gICAgICAuYWRkVGV4dCh0ZXh0ID0+IHRleHRcclxuICAgICAgICAuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3Muc3R5bGVMZXZlbDEpXHJcbiAgICAgICAgLm9uQ2hhbmdlKGFzeW5jICh2YWx1ZSkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3Muc3R5bGVMZXZlbDEgPSB2YWx1ZSBhcyBOdW1iZXJpbmdTdHlsZVxyXG4gICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKClcclxuICAgICAgICB9KSlcclxuXHJcbiAgICBuZXcgU2V0dGluZyhjb250YWluZXJFbClcclxuICAgICAgLnNldE5hbWUoJ1N0eWxlIGZvciBsb3dlciBsZXZlbCBoZWFkaW5ncyAoYmVsb3cgbGV2ZWwgMSknKVxyXG4gICAgICAuc2V0RGVzYygnRGVmaW5lcyB0aGUgbnVtYmVyaW5nIHN0eWxlIGZvciBoZWFkaW5ncyBiZWxvdyBsZXZlbCBvbmUuIFZhbGlkIHZhbHVlcyBhcmUgMSAoZm9yIG51bWJlcnMpIG9yIEEgKGZvciBjYXBpdGFsIGxldHRlcnMpIG9yIEkgKGZvciBSb21hbiBudW1lcmFscykuJylcclxuICAgICAgLmFkZFRleHQodGV4dCA9PiB0ZXh0XHJcbiAgICAgICAgLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLnN0eWxlTGV2ZWxPdGhlcilcclxuICAgICAgICAub25DaGFuZ2UoYXN5bmMgKHZhbHVlKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5zdHlsZUxldmVsT3RoZXIgPSB2YWx1ZSBhcyBOdW1iZXJpbmdTdHlsZVxyXG4gICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKClcclxuICAgICAgICB9KSlcclxuXHJcbiAgICBuZXcgU2V0dGluZyhjb250YWluZXJFbClcclxuICAgICAgLnNldE5hbWUoJ0F1dG9tYXRpYyBudW1iZXJpbmcnKVxyXG4gICAgICAuc2V0RGVzYygnVHVybnMgb24gYXV0b21hdGljIG51bWJlcmluZyBvZiBkb2N1bWVudHMuJylcclxuICAgICAgLmFkZFRvZ2dsZSh0b2dnbGUgPT4gdG9nZ2xlXHJcbiAgICAgICAgLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmF1dG8pXHJcbiAgICAgICAgLnNldFRvb2x0aXAoJ1R1cm4gb24gYXV0b21hdGljIG51bWJlcmluZycpXHJcbiAgICAgICAgLm9uQ2hhbmdlKGFzeW5jICh2YWx1ZSkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MuYXV0byA9IHZhbHVlXHJcbiAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKVxyXG4gICAgICAgIH0pKVxyXG5cclxuICAgIG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxyXG4gICAgICAuc2V0TmFtZSgnU2VwYXJhdG9yIHN0eWxlJylcclxuICAgICAgLnNldERlc2MoJ0RlZmluZXMgdGhlIHNlcGFyYXRvciBzdHlsZSBiZXR3ZWVuIHRoZSBoZWFkaW5nIG51bWJlciBhbmQgdGhlIGhlYWRpbmcgdGV4dC4gVmFsaWQgdmFsdWVzIGFyZSA6IChjb2xvbikgb3IgLiAoZG90KSBvciAtIChkYXNoKSBvciDigJQgKGVtZGFzaCkgb3IgKSAoYSByaWdodCBwYXJlbnRoZXNpcykuIFlvdSBjYW4gYWxzbyBsZWF2ZSBpdCBibGFuayBmb3Igbm8gc2VwYXJhdG9yLCBvciBoYXZlIGEgc3BhY2UgYmVmb3JlIHRoZSBzZXBhcmF0b3IuJylcclxuICAgICAgLmFkZFRleHQodGV4dCA9PiB0ZXh0XHJcbiAgICAgICAgLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLnNlcGFyYXRvcilcclxuICAgICAgICAub25DaGFuZ2UoYXN5bmMgKHZhbHVlKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5zZXBhcmF0b3IgPSB2YWx1ZVxyXG4gICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKClcclxuICAgICAgICB9KSlcclxuXHJcbiAgICBuZXcgU2V0dGluZyhjb250YWluZXJFbClcclxuICAgICAgLnNldE5hbWUoJ1RhYmxlIG9mIENvbnRlbnRzIEFuY2hvcicpXHJcbiAgICAgIC5zZXREZXNjKCdBbmNob3Igd2hpY2ggbGFiZWxzIHRoZSBoZWFkZXIgd2hlcmUgYSB0YWJsZSBvZiBjb250ZW50cyBzaG91bGQgYmUgaW5zZXJ0ZWQuIFRoZSBhbmNob3Igc2hvdWxkIGJlIGFkZGVkIGF0IHRoZSBlbmQgb2YgYSBoZWFkZXIuIEZvciBleGFtcGxlLCBedG9jLicpXHJcbiAgICAgIC5hZGRUZXh0KHRleHQgPT4gdGV4dFxyXG4gICAgICAgIC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5jb250ZW50cylcclxuICAgICAgICAub25DaGFuZ2UoYXN5bmMgKHZhbHVlKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5jb250ZW50cyA9IHZhbHVlXHJcbiAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKVxyXG4gICAgICAgIH0pKVxyXG5cclxuICAgIG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxyXG4gICAgICAuc2V0TmFtZSgnU2tpcCBIZWFkaW5ncyBBbmNob3InKVxyXG4gICAgICAuc2V0RGVzYygnQW5jaG9yIHdoaWNoIGxhYmVscyB0aGUgaGVhZGVycyB0aGF0IHNob3VsZCBub3QgYmUgbnVtYmVyZWQuIFRoZSBhbmNob3Igc2hvdWxkIGJlIGFkZGVkIGF0IHRoZSBlbmQgb2YgYSBoZWFkZXIuIEZvciBleGFtcGxlLCBec2tpcHBlZC4nKVxyXG4gICAgICAuYWRkVGV4dCh0ZXh0ID0+IHRleHRcclxuICAgICAgICAuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3Muc2tpcEhlYWRpbmdzKVxyXG4gICAgICAgIC5vbkNoYW5nZShhc3luYyAodmFsdWUpID0+IHtcclxuICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLnNraXBIZWFkaW5ncyA9IHZhbHVlXHJcbiAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKVxyXG4gICAgICAgIH0pKVxyXG4gIH1cclxufVxyXG5cclxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTnVtYmVySGVhZGluZ3NQbHVnaW4gZXh0ZW5kcyBQbHVnaW4ge1xyXG4gIHNldHRpbmdzITogTnVtYmVySGVhZGluZ3NQbHVnaW5TZXR0aW5nc1xyXG5cclxuICBhc3luYyBvbmxvYWQoKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxyXG4gICAgY29uc29sZS5pbmZvKCdMb2FkaW5nIE51bWJlciBIZWFkaW5ncyBQbHVnaW4sIHZlcnNpb24gJyArIHRoaXMubWFuaWZlc3QudmVyc2lvbilcclxuXHJcbiAgICBhd2FpdCB0aGlzLmxvYWRTZXR0aW5ncygpXHJcblxyXG4gICAgdGhpcy5hZGRDb21tYW5kKHtcclxuICAgICAgaWQ6ICdudW1iZXItaGVhZGluZ3Mtd2l0aC1vcHRpb25zJyxcclxuICAgICAgbmFtZTogJ051bWJlciBhbGwgaGVhZGluZ3MgaW4gZG9jdW1lbnQgKGFuZCBzaG93IG9wdGlvbnMpJyxcclxuICAgICAgY2hlY2tDYWxsYmFjazogKGNoZWNraW5nOiBib29sZWFuKSA9PiB7XHJcbiAgICAgICAgaWYgKGNoZWNraW5nKSByZXR1cm4gaXNWaWV3QWN0aXZlKHRoaXMuYXBwKVxyXG5cclxuICAgICAgICBjb25zdCB2aWV3SW5mbyA9IGdldFZpZXdJbmZvKHRoaXMuYXBwKVxyXG4gICAgICAgIGlmICh2aWV3SW5mbykge1xyXG4gICAgICAgICAgY29uc3Qgc2V0dGluZ3MgPSBnZXRGcm9udE1hdHRlclNldHRpbmdzT3JBbHRlcm5hdGl2ZSh2aWV3SW5mby5kYXRhLCB0aGlzLnNldHRpbmdzKVxyXG4gICAgICAgICAgaWYgKHNldHRpbmdzLm9mZikgcmV0dXJuIGZhbHNlXHJcblxyXG4gICAgICAgICAgdXBkYXRlSGVhZGluZ051bWJlcmluZyh2aWV3SW5mbywgc2V0dGluZ3MpXHJcbiAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgLy8gSEFDSzogVGhpcyBtdXN0IGhhcHBlbiBhZnRlciBhIHRpbWVvdXQgc28gdGhhdCB0aGVyZSBpcyB0aW1lIGZvciB0aGUgZWRpdG9yIHRyYW5zYWN0aW9uIHRvIGNvbXBsZXRlXHJcbiAgICAgICAgICAgIGNvbnN0IHBvc3ROdW1iZXJpbmdWaWV3SW5mbyA9IGdldFZpZXdJbmZvKHRoaXMuYXBwKVxyXG4gICAgICAgICAgICB1cGRhdGVUYWJsZU9mQ29udGVudHMocG9zdE51bWJlcmluZ1ZpZXdJbmZvLCBzZXR0aW5ncylcclxuICAgICAgICAgIH0sIDMwMDApXHJcblxyXG4gICAgICAgICAgc2hvd051bWJlcmluZ0RvbmVNZXNzYWdlKHRoaXMuYXBwLCBzZXR0aW5ncylcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBmYWxzZVxyXG4gICAgICB9XHJcbiAgICB9KVxyXG5cclxuICAgIHRoaXMuYWRkQ29tbWFuZCh7XHJcbiAgICAgIGlkOiAnbnVtYmVyLWhlYWRpbmdzJyxcclxuICAgICAgbmFtZTogJ051bWJlciBhbGwgaGVhZGluZ3MgaW4gZG9jdW1lbnQnLFxyXG4gICAgICBjaGVja0NhbGxiYWNrOiAoY2hlY2tpbmc6IGJvb2xlYW4pID0+IHtcclxuICAgICAgICBpZiAoY2hlY2tpbmcpIHJldHVybiBpc1ZpZXdBY3RpdmUodGhpcy5hcHApXHJcblxyXG4gICAgICAgIGNvbnN0IHZpZXdJbmZvID0gZ2V0Vmlld0luZm8odGhpcy5hcHApXHJcbiAgICAgICAgaWYgKHZpZXdJbmZvKSB7XHJcbiAgICAgICAgICBjb25zdCBzZXR0aW5ncyA9IGdldEZyb250TWF0dGVyU2V0dGluZ3NPckFsdGVybmF0aXZlKHZpZXdJbmZvLmRhdGEsIHRoaXMuc2V0dGluZ3MpXHJcbiAgICAgICAgICBpZiAoc2V0dGluZ3Mub2ZmKSByZXR1cm4gZmFsc2VcclxuXHJcbiAgICAgICAgICB1cGRhdGVIZWFkaW5nTnVtYmVyaW5nKHZpZXdJbmZvLCBzZXR0aW5ncylcclxuICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICAvLyBIQUNLOiBUaGlzIG11c3QgaGFwcGVuIGFmdGVyIGEgdGltZW91dCBzbyB0aGF0IHRoZXJlIGlzIHRpbWUgZm9yIHRoZSBlZGl0b3IgdHJhbnNhY3Rpb24gdG8gY29tcGxldGVcclxuICAgICAgICAgICAgY29uc3QgcG9zdE51bWJlcmluZ1ZpZXdJbmZvID0gZ2V0Vmlld0luZm8odGhpcy5hcHApXHJcbiAgICAgICAgICAgIHVwZGF0ZVRhYmxlT2ZDb250ZW50cyhwb3N0TnVtYmVyaW5nVmlld0luZm8sIHNldHRpbmdzKVxyXG4gICAgICAgICAgfSwgMzAwMClcclxuXHJcbiAgICAgICAgICAvLyBOT1RFOiBUaGUgbGluZSBiZWxvdyBpcyBpbnRlbnRpb25hbGx5IGNvbW1lbnRlZCBvdXQsIHNpbmNlIHRoaXMgY29tbWFuZCBpcyB0aGUgc2FtZSBhc1xyXG4gICAgICAgICAgLy8gICAgICAgdGhlIGFib3ZlIGNvbW1hbmQsIGV4Y2VwdCBmb3IgdGhpcyBsaW5lXHJcbiAgICAgICAgICAvLyBzaG93TnVtYmVyaW5nRG9uZU1lc3NhZ2UodGhpcy5hcHAsIHNldHRpbmdzLCB2aWV3SW5mbylcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBmYWxzZVxyXG4gICAgICB9XHJcbiAgICB9KVxyXG5cclxuICAgIHRoaXMuYWRkQ29tbWFuZCh7XHJcbiAgICAgIGlkOiAncmVtb3ZlLW51bWJlci1oZWFkaW5ncycsXHJcbiAgICAgIG5hbWU6ICdSZW1vdmUgbnVtYmVyaW5nIGZyb20gYWxsIGhlYWRpbmdzIGluIGRvY3VtZW50JyxcclxuICAgICAgY2hlY2tDYWxsYmFjazogKGNoZWNraW5nOiBib29sZWFuKSA9PiB7XHJcbiAgICAgICAgaWYgKGNoZWNraW5nKSByZXR1cm4gaXNWaWV3QWN0aXZlKHRoaXMuYXBwKVxyXG5cclxuICAgICAgICBjb25zdCB2aWV3SW5mbyA9IGdldFZpZXdJbmZvKHRoaXMuYXBwKVxyXG4gICAgICAgIHJlbW92ZUhlYWRpbmdOdW1iZXJpbmcodmlld0luZm8pXHJcblxyXG4gICAgICAgIHJldHVybiB0cnVlXHJcbiAgICAgIH1cclxuICAgIH0pXHJcblxyXG4gICAgdGhpcy5hZGRDb21tYW5kKHtcclxuICAgICAgaWQ6ICdzYXZlLXNldHRpbmdzLXRvLWZyb250LW1hdHRlcicsXHJcbiAgICAgIG5hbWU6ICdTYXZlIHNldHRpbmdzIHRvIGZyb250IG1hdHRlcicsXHJcbiAgICAgIGNoZWNrQ2FsbGJhY2s6IChjaGVja2luZzogYm9vbGVhbikgPT4ge1xyXG4gICAgICAgIGlmIChjaGVja2luZykgcmV0dXJuIGlzVmlld0FjdGl2ZSh0aGlzLmFwcClcclxuXHJcbiAgICAgICAgY29uc3Qgdmlld0luZm8gPSBnZXRWaWV3SW5mbyh0aGlzLmFwcClcclxuICAgICAgICBjb25zdCBmaWxlID0gdGhpcy5hcHAud29ya3NwYWNlLmdldEFjdGl2ZUZpbGUoKVxyXG4gICAgICAgIGlmICh2aWV3SW5mbyAmJiBmaWxlKSB7XHJcbiAgICAgICAgICBjb25zdCBzZXR0aW5ncyA9IGdldEZyb250TWF0dGVyU2V0dGluZ3NPckFsdGVybmF0aXZlKHZpZXdJbmZvLmRhdGEsIHRoaXMuc2V0dGluZ3MpXHJcbiAgICAgICAgICBzYXZlU2V0dGluZ3NUb0Zyb250TWF0dGVyKHRoaXMuYXBwLmZpbGVNYW5hZ2VyLCBmaWxlLCBzZXR0aW5ncylcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBmYWxzZVxyXG4gICAgICB9XHJcbiAgICB9KVxyXG5cclxuICAgIHRoaXMuYWRkU2V0dGluZ1RhYihuZXcgTnVtYmVySGVhZGluZ3NQbHVnaW5TZXR0aW5nVGFiKHRoaXMuYXBwLCB0aGlzKSlcclxuXHJcbiAgICB0aGlzLnJlZ2lzdGVySW50ZXJ2YWwod2luZG93LnNldEludGVydmFsKCgpID0+IHtcclxuICAgICAgY29uc3Qgdmlld0luZm8gPSBnZXRWaWV3SW5mbyh0aGlzLmFwcClcclxuICAgICAgaWYgKHZpZXdJbmZvKSB7XHJcbiAgICAgICAgY29uc3Qgc2V0dGluZ3MgPSBnZXRGcm9udE1hdHRlclNldHRpbmdzT3JBbHRlcm5hdGl2ZSh2aWV3SW5mby5kYXRhLCB0aGlzLnNldHRpbmdzKVxyXG5cclxuICAgICAgICBpZiAoc2V0dGluZ3Mub2ZmKSByZXR1cm5cclxuXHJcbiAgICAgICAgaWYgKHNldHRpbmdzLmF1dG8pIHtcclxuICAgICAgICAgIHVwZGF0ZUhlYWRpbmdOdW1iZXJpbmcodmlld0luZm8sIHNldHRpbmdzKVxyXG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgIC8vIEhBQ0s6IFRoaXMgbXVzdCBoYXBwZW4gYWZ0ZXIgYSB0aW1lb3V0IHNvIHRoYXQgdGhlcmUgaXMgdGltZSBmb3IgdGhlIGVkaXRvciB0cmFuc2FjdGlvbiB0byBjb21wbGV0ZVxyXG4gICAgICAgICAgICBjb25zdCBwb3N0TnVtYmVyaW5nVmlld0luZm8gPSBnZXRWaWV3SW5mbyh0aGlzLmFwcClcclxuICAgICAgICAgICAgdXBkYXRlVGFibGVPZkNvbnRlbnRzKHBvc3ROdW1iZXJpbmdWaWV3SW5mbywgc2V0dGluZ3MpXHJcbiAgICAgICAgICB9LCAzMDAwKVxyXG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcclxuICAgICAgICAgIGNvbnNvbGUubG9nKCdOdW1iZXIgSGVhZGluZ3MgUGx1Z2luOiBBdXRvbWF0aWNhbGx5IG51bWJlcmVkIGRvY3VtZW50JylcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0sIDEwICogMTAwMCkpXHJcbiAgfVxyXG5cclxuICBhc3luYyBsb2FkU2V0dGluZ3MoKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICB0aGlzLnNldHRpbmdzID0gT2JqZWN0LmFzc2lnbih7fSwgREVGQVVMVF9TRVRUSU5HUywgYXdhaXQgdGhpcy5sb2FkRGF0YSgpKVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgc2F2ZVNldHRpbmdzKCk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgYXdhaXQgdGhpcy5zYXZlRGF0YSh0aGlzLnNldHRpbmdzKVxyXG4gIH1cclxufVxyXG4iXSwibmFtZXMiOlsiTWFya2Rvd25WaWV3Iiwicm9tYW5pemUiLCJkZXJvbWFuaXplIiwicGFyc2VGcm9udE1hdHRlckVudHJ5IiwiTW9kYWwiLCJQbHVnaW5TZXR0aW5nVGFiIiwiU2V0dGluZyIsIlBsdWdpbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQW9HQTtBQUNPLFNBQVMsU0FBUyxDQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRTtBQUM3RCxJQUFJLFNBQVMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLE9BQU8sS0FBSyxZQUFZLENBQUMsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsVUFBVSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRTtBQUNoSCxJQUFJLE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRTtBQUMvRCxRQUFRLFNBQVMsU0FBUyxDQUFDLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFL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
diff --git a/.obsidian/plugins/number-headings-obsidian/manifest.json b/.obsidian/plugins/number-headings-obsidian/manifest.json
new file mode 100644
index 0000000..c7cd633
--- /dev/null
+++ b/.obsidian/plugins/number-headings-obsidian/manifest.json
@@ -0,0 +1,10 @@
+{
+ "id": "number-headings-obsidian",
+ "name": "Number Headings",
+ "version": "1.16.0",
+ "minAppVersion": "1.4.0",
+ "description": "Automatically number or re-number headings in an Obsidian document",
+ "author": "Kevin Albrecht (onlyafly@gmail.com)",
+ "authorUrl": "https://www.kevinalbrecht.com",
+ "isDesktopOnly": false
+}
\ No newline at end of file
diff --git a/.obsidian/plugins/number-headings-obsidian/styles.css b/.obsidian/plugins/number-headings-obsidian/styles.css
new file mode 100644
index 0000000..12a666b
--- /dev/null
+++ b/.obsidian/plugins/number-headings-obsidian/styles.css
@@ -0,0 +1,8 @@
+div.number-headings-button-container > button {
+ font-weight: normal;
+}
+
+div.number-headings-question {
+ font-weight: bold;
+ margin-bottom: 10px;
+}
\ No newline at end of file
diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json
index 1dbe4de..eb4f38f 100644
--- a/.obsidian/workspace.json
+++ b/.obsidian/workspace.json
@@ -4,39 +4,20 @@
"type": "split",
"children": [
{
- "id": "8d88ecb58e1896b9",
+ "id": "97efbe1d11fc4123",
"type": "tabs",
"children": [
{
- "id": "b441e35062a39cb4",
- "type": "leaf",
- "state": {
- "type": "diff-view",
- "state": {
- "file": "Home Server/Network/nginx for reverse proxy.md",
- "staged": false
- }
- },
- "group": "d1fb0956c6dbe2c1"
- }
- ]
- },
- {
- "id": "ca6bd2afed1473ff",
- "type": "tabs",
- "children": [
- {
- "id": "91fb38d5658db1d5",
+ "id": "b3362951cffea02c",
"type": "leaf",
"state": {
"type": "markdown",
"state": {
- "file": "Home Server/Gitea.md",
- "mode": "preview",
+ "file": "Home Server/Network/DNS/DNS.md",
+ "mode": "source",
"source": true
}
- },
- "group": "d1fb0956c6dbe2c1"
+ }
}
]
}
@@ -114,7 +95,9 @@
"type": "leaf",
"state": {
"type": "outline",
- "state": {}
+ "state": {
+ "file": "Home Server/Network/DNS/DNS.md"
+ }
}
},
{
@@ -123,6 +106,7 @@
"state": {
"type": "backlink",
"state": {
+ "file": "Home Server/Network/DNS/DNS.md",
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical",
@@ -139,6 +123,7 @@
"state": {
"type": "outgoing-link",
"state": {
+ "file": "Home Server/Network/DNS/DNS.md",
"linksCollapsed": false,
"unlinkedCollapsed": true
}
@@ -169,21 +154,36 @@
"command-palette:명령어 팔레트 열기": false
}
},
- "active": "b441e35062a39cb4",
+ "active": "6444ef15fb3eff8f",
"lastOpenFiles": [
- "Home Server/Gitea.md",
"Home Server/Network/nginx for reverse proxy.md",
+ "Home Server/Gitea.md",
+ "windows/SSH 접속 설정.md",
+ "Obsidian Flavored Markdown.md",
+ "template/howto.md",
+ "template/base_template.md",
+ "SBC(Single-Board Computer)/SBC.md",
+ "SBC(Single-Board Computer)/Raspberry Pi.md",
+ "SBC(Single-Board Computer)/ODROID H4+.md",
+ "SBC(Single-Board Computer)/ODROID.md",
+ "linux/User.md",
+ "linux/RAID.md",
+ "linux/Network stat.md",
+ "linux/Network interfaces.md",
+ "linux/Group.md",
+ "linux/dig.md",
+ "linux/설치 후 첫 root 로그인.md",
+ "Home Server/Samba.md",
"Home Server/docker compose - temp.md",
"Home Server/Network/DNS/Domain.md",
- "linux/Network Interfaces.md",
- "linux/network stat.md",
"Home Server/Network/DNS/DNS.md",
"Home Server/Network/DNS/CoreDNS.md",
- "linux/dig.md",
+ "_흥미로운 것/fail2ban.md",
+ "_흥미로운 것/메일 서버.md",
+ "_흥미로운 것/개인 도메인.md",
+ "daily/2024-07-27.md",
"Home Server/Network/DNS",
"Home Server/Network",
- "linux/RAID.md",
- "POE/3.25/재조합기 번역.md",
"POE/3.25/resources/07.접두접미완성1-1.png",
"POE/3.25/resources/08.접두접미완성1-2.png",
"POE/3.25/resources/08.접두접미완성1-2.png.crdownload",
@@ -197,25 +197,10 @@
"POE/3.25/resources/04.옵션옮기기2-2.png.crdownload",
"POE/3.25/resources/03.옵션옮기기2-1.png",
"POE/3.25/resources/03.옵션옮기기2-1.png.crdownload",
- "Obsidian Flavored Markdown.md",
"POE/3.25/resources/02.옵션옮기기1-2.png",
"POE/3.25/resources/02.옵션옮기기1-2.png.crdownload",
"POE/3.25/resources/01.옵션옮기기1-1.png",
"POE/3.25/resources/1.옵션옮기기1.png",
- "POE/3.25/resources/1.옵션옮기기1.png.crdownload",
- "POE/3.25/1. 스타터 냉기 방혈 지뢰 트릭스터/일지.md",
- "Home Server/Samba.md",
- "POE/3.25/파밍.md",
- "linux/Group.md",
- "linux/User.md",
- "linux/설치 후 첫 root 로그인.md",
- "_흥미로운 것/개인 도메인.md",
- "_흥미로운 것/메일 서버.md",
- "_흥미로운 것/fail2ban.md",
- "windows/SSH 접속 설정.md",
- "template/howto.md",
- "template/base_template.md",
- "SBC(Single-Board Computer)/ODROID H4+.md",
- "SBC(Single-Board Computer)/Raspberry Pi.md"
+ "POE/3.25/resources/1.옵션옮기기1.png.crdownload"
]
}
\ No newline at end of file
diff --git a/Home Server/Gitea.md b/Home Server/Gitea.md
index 521e1cf..4e2d1ea 100644
--- a/Home Server/Gitea.md
+++ b/Home Server/Gitea.md
@@ -1,8 +1,8 @@
-# 전제조건
+# 1. 전제조건
[[Network/nginx for reverse proxy|리버스 프록시]]가 필요함
-# Install using docker
-## Directory structure
+# 2. Install using docker
+## 2.1. Directory structure
```dirtree
- /mnt/md0/infra
- .env
@@ -19,7 +19,7 @@
/gitea 폴더 새로 생성
/nginx/conf.d/locations/gitea.conf 파일 새로 생성
-## Docker compose
+## 2.2. Docker compose
/compose.yml 수정
```yml
name: infrastructure
@@ -52,9 +52,9 @@ service:
driver: bridge
```
-## Reverse Proxy
+## 2.3. Reverse Proxy
-### /nginx/nginx.conf
+### 2.3.1. /nginx/nginx.conf
size 제한으로 인해 push에 실패할 수 있는 현상을 수정하기 위해 제한을 없앰
```nginx
@@ -67,7 +67,7 @@ http {
}
```
-### /nginx/conf.d/gitea.conf
+### 2.3.2. /nginx/conf.d/gitea.conf
```nginx
location /git {
@@ -81,7 +81,7 @@ location /git {
}
```
-# Init
+# 3. Init
수정할 설정 목록
- 데이터베이스 유형 : SQLite3
- 사이트 제목 : Home Gitea
diff --git a/Home Server/Network/DNS/CoreDNS.md b/Home Server/Network/DNS/CoreDNS.md
index 91cac14..15f74a3 100644
--- a/Home Server/Network/DNS/CoreDNS.md
+++ b/Home Server/Network/DNS/CoreDNS.md
@@ -2,8 +2,8 @@ Go로 작성된 오픈소스 [[DNS]] Server
경량, 유연성, 단순함이 특징
k8s의 기본 DNS로 사용됨
-# Install using docker
-## Directory structure
+# 1. Install using docker
+## 1.1. Directory structure
```dirtree
- /mnt/md0/infra
@@ -16,14 +16,14 @@ k8s의 기본 DNS로 사용됨
- /data
```
-## dotenv file
+## 1.2. dotenv file
/.env
```
BASE_PATH=/mnt/md0/infra
```
-## Docker compose
+## 1.3. Docker compose
/compose.yml
```yml
@@ -50,11 +50,11 @@ networks:
driver: bridge
```
-## 추가로 필요한 사항 - 리눅스
+## 1.4. 추가로 필요한 사항 - 리눅스
리눅스의 경우 53번 포트가 systemd-resolve 프로세스에 미리 점유되어 있다.
따라서 해당 프로세스가 53번 포트를 점유하지 않도록 바꿔주어야 DNS Server를 실행할 수 있다.
-### 프로세스 확인
+### 1.4.1. 프로세스 확인
```shell
sudo lsof -i :53
@@ -68,7 +68,7 @@ systemd-r 671 systemd-resolve 16u IPv4 8661 0t0 UDP _localdnsproxy:do
systemd-r 671 systemd-resolve 17u IPv4 8662 0t0 TCP _localdnsproxy:domain (LISTEN)
```
-### Edit systemd-resolved config
+### 1.4.2. Edit systemd-resolved config
```shell
sudo vim /etc/systemd/resolved.conf
@@ -112,19 +112,19 @@ DNSStubListener=no
#StaleRetentionSec=0
```
-### Create symlink
+### 1.4.3. Create symlink
```shell
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
```
-### Reboot
+### 1.4.4. Reboot
```shell
sudo reboot
```
-# Corefile
+# 2. Corefile
CoreDNS 의 설정 파일
```
@@ -143,7 +143,7 @@ home.server {
}
```
-# Zone file
+# 3. Zone file
[[DNS#DNS Zone file]]
```
diff --git a/Home Server/Network/DNS/DNS.md b/Home Server/Network/DNS/DNS.md
index c89519a..a31af80 100644
--- a/Home Server/Network/DNS/DNS.md
+++ b/Home Server/Network/DNS/DNS.md
@@ -1,13 +1,13 @@
Domain Name System, 도메인 이름 시스템
[[Domain|도메인]]을 IP로 변환하는 시스템
-# Public DNS server list
+# 1. Public DNS server list
- 1.1.1.1 1.0.0.1 : Cloudflare DNS
- 8.8.8.8 8.8.4.4 : Google DNS
- 208.67.222.222 208.67.220.220 : Cisco OpenDNS
- 168.126.63.1 168.126.63.2 : KT DNS
-# Self-hosted DNS server list
+# 2. Self-hosted DNS server list
- BIND
- CoreDNS
- dnsmasq
@@ -15,7 +15,7 @@ Domain Name System, 도메인 이름 시스템
- Pi-hole
- ...
-# 변환 과정
+# 3. 변환 과정
1. 클라이언트가 Recursive DNS resolver에게 쿼리를 보냄
2. Recursive DNS resolver의 캐시에 답변이 남아있으면 해당 답변을 답변함
3. Recursive DNS resolver의 캐시에 답변이 없으면 클라이언트 요청에 해당하는 TLD name server 정보를 Root name server에 쿼리함
@@ -26,11 +26,11 @@ Domain Name System, 도메인 이름 시스템
8. Authoritative name server는 요청받은 도메인에 대해 DNS Zone 파일을 답변함
9. Recursive DNS resolver는 답변받은 도메인 정보를 클라이언트에 답변함
-# DNS Zone file
+# 4. DNS Zone file
도메인에 대한 정보를 기술해놓은 파일
파일의 각 줄(레코드)에는 여러 가지 정보를 기술할 수 있음
-## Zone file 형식
+## 4.1. Zone file 형식
```
$ORIGIN (zone name)
@@ -57,19 +57,19 @@ www 3600 IN CNAME home.server.
>[!note]
>Zone file에서 `@` 기호는 `$ORIGIN` 값과 동일한 의미이다.
-## Record
+## 4.2. Record
- SOA : Start of Authority
- 이름, 관리자 이메일 주소, 캐시 새로 고침 정보 등을 기술
- 모든 DNS Zone file은 SOA 레코드를 가지고 있어야 함
- TTL : Time to Live, 캐시 유효 기간
- A, AAAA : IP 주소, A는 IPv4, AAAA는 IPv6에 해당
- MX : 도메인 SMTP 이메일 서버
-- CNAME : Canonical name, CNAME에 기록된 도메인은 해당 Zone file에 기술된 도메인과 같은 IP를 참조하도록 함.
+- CNAME : Canonical name, CNAME에 기록된 도메인은 해당 Zone file에 기술된 도메인과 같은 IP를 참조하도록 함
- NS : Name server, Authoritative name server 정보
- PTR : 역방향 DNS에 사용, IP 주소를 도메인에 매핑
-- TXT : 이메일 인증을 위한 발신자 정책 프레임워크 레코드
+- TXT : 아무 텍스트나 입력 가능
-### SOA Record
+### 4.2.1. SOA Record
```
NAME [TTL] IN SOA DNS-address admin-email-address (
@@ -93,7 +93,7 @@ NAME [TTL] IN SOA DNS-address admin-email-address (
- expire : 마스터가 응답하지 않는 경우 2차 DNS가 이 영역에 대한 요청 응답을 중지해야 하는 시간(초)
- minimum : Negative TTL 값, 존재하지 않는 도메인에 대해 호스트가 존재하지 않는다는 답변을 캐싱하는 최소 시간
-## Wildcard
+## 4.3. Wildcard
DNS Zone의 모든 subdomain을 가리키려면 DNS record에 wildcard를 추가하면 된다.
diff --git a/Home Server/Network/DNS/Domain.md b/Home Server/Network/DNS/Domain.md
index 5a20e5c..c746be4 100644
--- a/Home Server/Network/DNS/Domain.md
+++ b/Home Server/Network/DNS/Domain.md
@@ -1,44 +1,44 @@
-# 도메인 (도메인 네임)
+# 1. 도메인 (도메인 네임)
숫자로 이루어진 IP 주소를 문자로 이루어진 것으로 바꿔 기억하기 쉽게 만들어주는 인터넷 호스트 네임
좁은 의미로는 도메인 레지스트리에 등록된 이름을 말한다.
계층 구조에 따라서 도메인 네임이 결정된다.
도메인은 개인의 자산으로 간주된다.
-# 호스트 네임 (호스트명)
+# 2. 호스트 네임 (호스트명)
네트워크에 연결된 장치에 부여되는 고유한 이름
---
-# 도메인 관리 체계
+# 3. 도메인 관리 체계
-## ICANN
+## 3.1. ICANN
root DNS 관리, 신규 TLD 할당, IP 주소 관리, 레지스트리 및 레지스트라 인가, 도메인에 적용되는 공통 정책 제정 등의 일을 하는 미국 비영리기구.
두 글자로 이루어진 국가 코드 TLD(ccTLD) 관리 및 정책 제정은 각 국가에 위임한다.
세 글자 이상으로 이루어진 TLD는 gTLD(generic TLD)라고 칭하며 ICANN에서 정한 정책을 준수해야 한다.
단 `.gov`, `.mil`, `.edu`는 미국 정부에서 관리하며 미국에서만 사용할 수 있다.
-## 레지스트리 (Registry)
+## 3.2. 레지스트리 (Registry)
각 TLD와 해당 TLD에 속한 DNS 레코드를 관리하는 기관
-## 레지스트라 (Registrar)
+## 3.3. 레지스트라 (Registrar)
도메인 등록대행업체
도메인 레지스트리의 위임을 받아 도메인 레지스트런트에게서 일정한 비용을 받고 도메인 등록을 대행해준다.
-## 레지스트런트 (Registrant)
+## 3.4. 레지스트런트 (Registrant)
도메인 소유자, 도메인 사용자
---
-# 계층 구조
+# 4. 계층 구조
도메인은 계층 구조로 이루어져 있으며 보통 3단계로 구분한다.
-## TLD
+## 4.1. TLD
Top-Level Domain, 최상위 도메인
도메인의 제일 마지막 점 뒤에 붙은 문자열을 가리킨다.
`foo.com` 이라는 도메인이 있다면 `.com`이 TLD
레지스트리에서 관리
-## 2단계 도메인
+## 4.2. 2단계 도메인
SLD, Second-Level Domain
TLD 앞에 붙는 도메인
@@ -46,14 +46,14 @@ TLD 앞에 붙는 도메인
- 2단계 도메인을 레지스트런트가 사용하는 경우 (`foo.com`)
- 2단계 도메인까지 레지스트리가 관리하는 경우 (`foo.co.kr`), 이 경우도 TLD로 부르기도 함
-## 3단계 도메인
+## 4.3. 3단계 도메인
2단계 도메인 앞에 붙는 도메인
-# 도메인 구성
-## root 도메인
+# 5. 도메인 구성
+## 5.1. root 도메인
1. TLD + 레지스트런트가 사용하는 도메인 (`naver.com`)
2. DNS에서 TLD에 관한 정보를 제공하는 DNS
-## sub 도메인
+## 5.2. sub 도메인
root 도메인이 필요에 따라 하위에 생성하는 도메인 (`blog.naver.com`, `news.naver.com`)
www 역시 여기에 포함되며, 도메인을 웹에서 주로 사용하게 됨에 따라 www를 생략하는 경우가 많아졌음
\ No newline at end of file
diff --git a/Home Server/Network/nginx for reverse proxy.md b/Home Server/Network/nginx for reverse proxy.md
index 261ca33..220c6cf 100644
--- a/Home Server/Network/nginx for reverse proxy.md
+++ b/Home Server/Network/nginx for reverse proxy.md
@@ -1,7 +1,7 @@
[[DNS/CoreDNS|CoreDNS]]를 설정한 뒤 진행했음
-# Install using docker
-## Directory structure
+# 1. Install using docker
+## 1.1. Directory structure
```dirtree
- /mnt/md0/infra
- /coredns
@@ -16,13 +16,13 @@
- compose.yml
```
-## dotenv file
+## 1.2. dotenv file
/.env
```
BASE_PATH=/mnt/md0/infra
```
-## Docker compose
+## 1.3. Docker compose
/compose.yml
```yml
name: infrastructure
@@ -46,11 +46,11 @@ networks:
driver: bridge
```
-# nginx configuration
-## /nginx/nginx.conf
+# 2. nginx configuration
+## 2.1. /nginx/nginx.conf
기본 설정 파일을 그대로 사용함
-## /nginx/conf.d/default.conf
+## 2.2. /nginx/conf.d/default.conf
```nginx
server {
@@ -66,7 +66,7 @@ server {
}
```
-## subdomain
+## 2.3. subdomain
```nginx
server {
@@ -85,7 +85,7 @@ server {
}
```
-## reload
+## 2.4. reload
```shell
docker exec -it nginx-reverse-proxy nginx -s reload
diff --git a/Home Server/Samba.md b/Home Server/Samba.md
index db007ec..0a8d6a7 100644
--- a/Home Server/Samba.md
+++ b/Home Server/Samba.md
@@ -1,16 +1,16 @@
-# Samba 설치
+# 1. Samba 설치
```shell
sudo apt -y install samba
```
-# Samba user group 추가
+# 2. Samba user group 추가
[[../linux/Group#groupadd|Linux group add]]를 사용해 리눅스 유저 그룹을 추가한다.
-# User 추가
-## Linux user 추가
+# 3. User 추가
+## 3.1. Linux user 추가
[[../linux/User#useradd|Linux user add]]를 사용해 리눅스 유저를 먼저 추가해야 한다. 이 때 유저 그룹은 samba를 지정한다.
-## smbpasswd
+## 3.2. smbpasswd
```shell
sudo smbpasswd -a [username]
```
@@ -21,14 +21,14 @@ Retype new SMB password:
Added user tuska.
```
-# Samba 폴더 생성
+# 4. Samba 폴더 생성
```shell
sudo mkdir -p /mnt/md0/share/guest
sudo chown tuska:samba /mnt/md0/share
sudo chmod 775 /mnt/md0/share
```
-# Samba 설정
+# 5. Samba 설정
```shell
sudo vim /etc/samba/smb.conf
```
@@ -45,10 +45,10 @@ sudo vim /etc/samba/smb.conf
force group = samba
```
-# Samba service 재시작
+# 6. Samba service 재시작
```shell
sudo service smbd restart
```
-# 공유 폴더 접속
+# 7. 공유 폴더 접속
`\\[server-ip]\[section 이름]`
\ No newline at end of file
diff --git a/SBC(Single-Board Computer)/ODROID H4+.md b/SBC(Single-Board Computer)/ODROID H4+.md
index 5af80cb..b8b27b8 100644
--- a/SBC(Single-Board Computer)/ODROID H4+.md
+++ b/SBC(Single-Board Computer)/ODROID H4+.md
@@ -4,10 +4,10 @@ tags:
- sbc
- odroid
---
-# 개요
+# 1. 개요
한국의 하드커널에서 제작 및 판매하는 인텔 x86 기반 [[ODROID]] SBC 제품
-# Spec
+# 2. Spec
- Intel 12세대 프로세서 N97 사용 (하스웰 노트북용 i7, 데스크탑용 i5급, 4C4T, TDP 12W)
- DDR5-4800, MAX 48GB, Single Channel
- HDMI 1port, DP 2Port
@@ -17,7 +17,7 @@ tags:
- SATA III 4 port
- 19만원
-# 구매 목록
+# 3. 구매 목록
| 품목 | 가격 |
| ------------------------------- | ------- |
| ODROID-H4+ | 187,700 |
@@ -28,7 +28,7 @@ tags:
| 92x92x25mm DC Cooling Fan | 6,800 |
| TOTAL | 304,800 |
-# 추가 부품
+# 4. 추가 부품
| 품목 | 가격 |
| -------------------------------------------------- | ------- |
| 삼성 DDR5-4800 16GB | 64,590 |
@@ -36,7 +36,7 @@ tags:
| WD Ultrastar HC310 4TB
7200RPM 256MB package x 2ea | 378,000 |
| TOTAL | 513,590 |
-# 언박싱
+# 5. 언박싱
![[SBC(Single-Board Computer)/resources/ODROID H4+/01-구성품/01-택배.jpg]]
![[SBC(Single-Board Computer)/resources/ODROID H4+/01-구성품/02-언박싱.jpg]]
![[SBC(Single-Board Computer)/resources/ODROID H4+/01-구성품/03-구성품.jpg]]
@@ -44,12 +44,12 @@ tags:
![[SBC(Single-Board Computer)/resources/ODROID H4+/01-구성품/05-본체실물.jpg]]
![[SBC(Single-Board Computer)/resources/ODROID H4+/01-구성품/06-케이스.jpg]]
-# 구매 시 유의사항
+# 6. 구매 시 유의사항
1. 케이스에 쿨러가 동봉되어 있으므로 추가 쿨러 구매는 하지 않아도 됨
2. 하드디스크 사용을 위해 19V/7A 파워를 산다면 전기 공급을 위한 플러그는 별도로 구매해야 한다.
3. 하드디스크 연결용 SATA 케이블은 같이 구매하면 편하다. 남는 것이 있다면 구매하지 않아도 된다.
-# 조립
+# 7. 조립
![](https://www.youtube.com/watch?v=kxi5lZ67P8Y)
1. 쿨링 팬을 케이스에 부착. 이 때 나사는 3개만 사용 (좌하, 우상하).
![[SBC(Single-Board Computer)/resources/ODROID H4+/02-조립/01-쿨러.jpg]]
@@ -70,10 +70,10 @@ tags:
![[SBC(Single-Board Computer)/resources/ODROID H4+/02-조립/07-조립전면부.jpg]]
![[SBC(Single-Board Computer)/resources/ODROID H4+/02-조립/08-조립후면부.jpg]]
-# OS
+# 8. OS
하드커널에서는 별도의 OS 설치 미디어를 제공하지 않음
권장하는 OS는 우분투이며 x86 CPU 특성상 Windows를 포함한 다른 OS를 설치하더라도 큰 문제가 없을 것
-# 참조 링크
+# 9. 참조 링크
- https://www.hardkernel.com/shop/odroid-h4-plus/
- https://wiki.odroid.com/odroid-h4/start
\ No newline at end of file
diff --git a/SBC(Single-Board Computer)/ODROID.md b/SBC(Single-Board Computer)/ODROID.md
index d120e22..8671230 100644
--- a/SBC(Single-Board Computer)/ODROID.md
+++ b/SBC(Single-Board Computer)/ODROID.md
@@ -4,13 +4,13 @@ tags:
- sbc
- odroid
---
-# 개요
+# 1. 개요
한국의 하드커널에서 제작 및 판매하는 [[SBC]] 제품(군)
삼성 SoC를 이용한 안드로이드 개발 보드 제조가 그 시작이다.
현재는 삼성의 SoC가 단종되어 Amlogic, Rockchip 등의 Arm 기반 SoC와 인텔 x86 기반 프로세서를 사용한 SBC를 제작하고 있다.
배송은 우체국을 이용한다.
-# 제품(군)
+# 2. 제품(군)
- H Serise (x86)
- H4, H4+, H4 Ultra
- H3, H3+
diff --git a/SBC(Single-Board Computer)/Raspberry Pi.md b/SBC(Single-Board Computer)/Raspberry Pi.md
index 0de4f8d..eee5aa4 100644
--- a/SBC(Single-Board Computer)/Raspberry Pi.md
+++ b/SBC(Single-Board Computer)/Raspberry Pi.md
@@ -4,11 +4,11 @@ tags:
- sbc
- raspberry_pi
---
-# 개요
+# 1. 개요
영국의 Raspberry Pi Foundation이 개발하는 [[SBC]] 제품(군)
저렴한 가격을 무기로 시장에서 제일 대중화된 SBC이다.
-# 특징
+# 2. 특징
- SBC의 특징 (소형, 저전력)
- Arm기반 브로드컴 SoC를 사용
- 전용 OS인 Raspberry Pi OS 존재 (Debian 기반 Linux 배포판)
@@ -16,7 +16,7 @@ tags:
- 단 주변 기기 가격까지 더하다 보면 가성비가 나빠질 수 있음
- 수많은 사용자가 전 세계에 폭넓게 퍼져있음
- 이로 인해 다양한 사용방법을 손쉽게 검색할 수 있음
-# 제품(군)
+# 3. 제품(군)
- Raspberry Pi 5
- Raspberry Pi 4
- Raspberry Pi 3
diff --git a/SBC(Single-Board Computer)/SBC.md b/SBC(Single-Board Computer)/SBC.md
index 2377849..768cbbf 100644
--- a/SBC(Single-Board Computer)/SBC.md
+++ b/SBC(Single-Board Computer)/SBC.md
@@ -3,16 +3,16 @@ tags:
- hardware
- sbc
---
-# 정의
+# 1. 정의
Single-Board Computer 의 약자로 번역하면 단일 기판(보드) 컴퓨터다.
하나의 기판 안에 프로세서, 메모리, 입출력 인터페이스 등이 모두 들어있는 컴퓨터다.
-# 특징
+# 2. 특징
- 하나의 기판에 컴퓨터가 동작하기 위한 모든 요소가 들어있다.
- 크기가 작다.
- 전력을 적게 소모한다.
- 확장성이 낮다.
-# 종류
+# 3. 종류
- [[Raspberry Pi]]
- ODroid
\ No newline at end of file
diff --git a/linux/Group.md b/linux/Group.md
index 00ebb0f..d66b275 100644
--- a/linux/Group.md
+++ b/linux/Group.md
@@ -1,10 +1,10 @@
-# create
-## groupadd
+# 1. create
+## 1.1. groupadd
```shell
sudo groupadd [groupname]
```
-# read
+# 2. read
`/etc/group` 파일 확인
```shell
cat /etc/group
diff --git a/linux/Network Interfaces.md b/linux/Network Interfaces.md
index 868fec5..67a9738 100644
--- a/linux/Network Interfaces.md
+++ b/linux/Network Interfaces.md
@@ -1,4 +1,7 @@
-# Get network interface information
+# 1. ifconfig
+deprecated
+
+# 2. ip
```shell
ip a
@@ -37,9 +40,9 @@ ip a
valid_lft forever preferred_lft forever
```
-# Change IP settings
-## netplan
-### 파일 확인
+# 3. Change IP settings
+## 3.1. netplan
+### 3.1.1. 파일 확인
```shell
ls /etc/netplan
@@ -49,7 +52,7 @@ ls /etc/netplan
50-cloud-init.yaml
```
-### 내용 수정
+### 3.1.2. 내용 수정
```shell
sudo vim /etc/netplan/50-cloud-init.yaml
@@ -83,7 +86,7 @@ network:
version: 2
```
-## /etc/systemd/resolved.conf
+## 3.2. /etc/systemd/resolved.conf
DNS의 경우 /etc/systemd/resolved.conf 파일 수정이 필요할 수 있음
```
diff --git a/linux/RAID.md b/linux/RAID.md
index f434542..a6eb3d4 100644
--- a/linux/RAID.md
+++ b/linux/RAID.md
@@ -5,9 +5,9 @@ tags:
- hardware
- linux
---
-# 디스크 구성 확인
-## 마운트 리스트 및 용량 확인
-### df
+# 1. 디스크 구성 확인
+## 1.1. 마운트 리스트 및 용량 확인
+### 1.1.1. df
```shell
df -h
```
@@ -25,7 +25,7 @@ tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 1.6G 12K 1.6G 1% /run/user/1000
```
-### lsblk
+### 1.1.2. lsblk
```shell
sudo lsblk
```
@@ -42,7 +42,7 @@ nvme0n1 259:0 0 465.8G 0 disk
└─ubuntu--vg-ubuntu--lv 252:0 0 100G 0 lvm /
```
-## system file 확인
+## 1.2. system file 확인
```shell
cat /proc/partitions
```
@@ -60,7 +60,7 @@ major minor #blocks name
252 0 104857600 dm-0
```
-## fdisk
+## 1.3. fdisk
```shell
sudo fdisk -l
@@ -101,7 +101,7 @@ Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 16384 bytes / 131072 bytes
```
-# RAID용 Hard Disk partition 생성
+# 2. RAID용 Hard Disk partition 생성
```shell
sudo fdisk /dev/sda
```
@@ -159,13 +159,13 @@ Calling ioctl() to re-read partition table.
Syncing disks.
```
-# RAID 설정
-## mdadm 설치
+# 3. RAID 설정
+## 3.1. mdadm 설치
```shell
sudo apt install mdadm
```
-## RAID 생성
+## 3.2. RAID 생성
```shell
sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sda1 /dev/sdb1
# mdadm --create [raid경로/raid명칭] --level=[레이드 구분] --raid-devices=[레이드 구성할 하드 개수] [하드 1] [하드 2] ... [하드 n]
@@ -183,7 +183,7 @@ mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.
```
-## format
+## 3.3. format
```shell
sudo mkfs.ext4 /dev/md0
```
@@ -203,11 +203,11 @@ Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done
```
-# RAID 구성 확인
+# 4. RAID 구성 확인
[[#마운트 리스트 및 용량 확인]]
[[#system file 확인]]
-## RAID 세부 정보 확인하기
+## 4.1. RAID 세부 정보 확인하기
```shell
more /proc/mdstat
```
@@ -222,7 +222,7 @@ md0 : active raid1 sdb[1] sda[0]
unused devices:
```
-## mdadm
+## 4.2. mdadm
```shell
sudo mdadm --detail /dev/md0
```
@@ -260,8 +260,8 @@ Consistency Policy : bitmap
1 8 17 1 active sync /dev/sdb1
```
-# 재부팅 시 자동 마운트
-## /etc/fstab
+# 5. 재부팅 시 자동 마운트
+## 5.1. /etc/fstab
/dev/md0 와 같이 device 파일 이름을 fstab 파일에 추가하라는 글을 쉽게 검색할 수 있다.
하지만 재부팅 시 리눅스에서 RAID 이름을 md127과 같이 바꿔버려 부팅 과정에서 오류가 발생하므로 UUID를 추가해 오류를 방지해야 한다.
@@ -285,7 +285,7 @@ sudo vim /etc/fstab
UUID=c207facc-b75b-4041-9971-bb272b26b689 /mnt/md0 ext4 defaults 0 0
```
-## mdadm conf
+## 5.2. mdadm conf
```shell
sudo mdadm --detail --scan
```
@@ -305,18 +305,18 @@ MAILADDR root
ARRAY /dev/md0 metadata=1.2 UUID=4c154399:14eb5dc6:7d9a9795:32654856
```
-### 한 번에 실행
+### 5.2.1. 한 번에 실행
```shell
sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
```
-## RAID 마운트
+## 5.3. RAID 마운트
```shell
sudo mkdir /mnt/md0
sudo mount /dev/md0 /mnt/md0
```
-## 마운트 확인
+## 5.4. 마운트 확인
```shell
cd /mnt
ls -al
diff --git a/linux/User.md b/linux/User.md
index 56e7f72..cf799d6 100644
--- a/linux/User.md
+++ b/linux/User.md
@@ -1,5 +1,5 @@
-# create
-## useradd
+# 1. create
+## 1.1. useradd
계정을 생성하고 기본 쉘인 sh를 연결해준다.
옵션으로 그룹, 패스워드 등을 지정할 수 있다.
옵션을 지정하지 않을 경우 그룹, 패스워드 등을 설정하지 않는다.
@@ -18,7 +18,7 @@ sudo useradd [options] [username]
| -U | --user-group | 유저 아이디와 같은 그룹 생성 |
| -h | --help | 도움말 표시 |
-## adduser
+## 1.2. adduser
콘솔에서 대화식 입출력으로 계정을 생성한다.
```shell
sudo adduser [username]
@@ -46,8 +46,8 @@ info: Adding new user `kolpi13' to supplemental / extra groups `users' ...
info: Adding user `kolpi13' to group `users' ...
```
-# read
-## id
+# 2. read
+## 2.1. id
유저 아이디를 생략할 경우 현재 콘솔에서 로그인한 계정의 계정 정보를 확인한다.
유저 아이디를 입력할 경우 입력한 유저의 계정 정보를 출력한다.
```shell
@@ -65,7 +65,7 @@ uid=1000(tuska) gid=1000(tuska) groups=1000(tuska),4(adm),24(cdrom),27(sudo),30(
| -u | --user | uid 출력 |
| -n | --name | 숫자로 된 id 대신 이름 출력 (u\|g\|G 옵션과 같이 사용) |
-## whoami
+## 2.2. whoami
현재 콘솔에서 로그인한 계정명을 확인한다.
```shell
whoami
@@ -75,7 +75,7 @@ whoami
tuska
```
-## users
+## 2.3. users
현재 로그인 중인 계정 목록을 확인한다.
```shell
users
@@ -85,7 +85,7 @@ users
tuska
```
-## who
+## 2.4. who
현재 로그인 중인 계정 목록을 자세히 확인한다.
```shell
who
@@ -95,7 +95,7 @@ who
tuska pts/0 2024-08-16 14:21 (192.168.200.100)
```
-## 환경 설정 파일
+## 2.5. 환경 설정 파일
환경 설정 파일은 모두 `/etc`에 위치한다.
| 파일 | 설명 |
@@ -108,13 +108,13 @@ tuska pts/0 2024-08-16 14:21 (192.168.200.100)
| `/etc/login.defs` | 로그인 수행 시 기본설정 |
| `/etc/skel` | 홈 디렉터리 생성 시 기본 제공 파일 |
-# update
-## passwd
+# 3. update
+## 3.1. passwd
비밀번호 설정
```shell
sudo passwd [username]
```
-# delete
+# 4. delete
```shell
sudo userdel [options] [username]
```
diff --git a/linux/dig.md b/linux/dig.md
index bcc9b80..76f7a42 100644
--- a/linux/dig.md
+++ b/linux/dig.md
@@ -6,7 +6,7 @@ dig [@global-server] [domain] [q-type] [q-class] {q-opt}
[ host [@local-server] {local-d-opt} [...]]
```
-# basic
+# 1. basic
```shell
dig host
@@ -40,7 +40,7 @@ naver.com. 25 IN A 223.130.200.219
;; MSG SIZE rcvd: 102
```
-# +short
+# 2. +short
답변을 간단하게 볼 때 사용
```shell
@@ -58,7 +58,7 @@ dig naver.com +short
223.130.192.248
```
-# record 지정
+# 3. record 지정
```shell
dig host record
@@ -68,7 +68,7 @@ dig host record
dig naver.com a
```
-# dns 지정
+# 4. dns 지정
```shell
dig @dns-address host
@@ -78,7 +78,7 @@ dig @dns-address host
dig @8.8.8.8 google.com
```
-# Using DoH (DNS over Https)
+# 5. Using DoH (DNS over Https)
```shell
dig +https @dns-address host
diff --git a/linux/network stat.md b/linux/network stat.md
index 7036b1c..a9c7cb6 100644
--- a/linux/network stat.md
+++ b/linux/network stat.md
@@ -1,14 +1,14 @@
-# netstat
+# 1. netstat
deprecated
-# ss
+# 2. ss
socket statistics
```shell
ss [options] [filter]
```
-## basic
+## 2.1. basic
listening 소켓을 제외하고 연결중인 모든 소켓 표시
```shell
ss
@@ -24,14 +24,14 @@ tcp ESTAB 0 0
tcp ESTAB 0 52 [::ffff:192.168.200.10]:ssh [::ffff:192.168.200.100]:49173
```
-## all
+## 2.2. all
모든 소켓 표시
```shell
ss -a
```
-## numeric
+## 2.3. numeric
서비스 이름 대신 숫자로 표기
```shell
@@ -48,7 +48,7 @@ ss -n
[::ffff:192.168.200.10]:22
```
-## process
+## 2.4. process
관리자 권한 필요
```shell
diff --git a/linux/설치 후 첫 root 로그인.md b/linux/설치 후 첫 root 로그인.md
index 60fce31..673e616 100644
--- a/linux/설치 후 첫 root 로그인.md
+++ b/linux/설치 후 첫 root 로그인.md
@@ -5,6 +5,7 @@ tags:
---
# 1. root 유저 패스워드 설정
+
```shell
sudo passwd root
```
@@ -15,6 +16,7 @@ Retype new password: [type root user password before you type]
passwd: password updated successfully
```
# 2. root 로그인
+
```
$ su -
Password: [type root user password]
diff --git a/windows/SSH 접속 설정.md b/windows/SSH 접속 설정.md
index 2ea8d97..e3967df 100644
--- a/windows/SSH 접속 설정.md
+++ b/windows/SSH 접속 설정.md
@@ -6,7 +6,7 @@ tags:
- network
- ssh
---
-0. 기존에 만든 키가 있는지 확인
+# 1. 기존에 만든 키가 있는지 확인
```powershell
# 키 저장 위치로 이동
cd ~/.ssh
@@ -22,7 +22,7 @@ dir
# 키가 없다면 다음 1번부터 진행
```
-1. 공개키-개인키 생성
+# 2. 공개키-개인키 생성
- 커맨드라인
```powershell
ssh-keygen
@@ -53,12 +53,12 @@ dir
+----[SHA256]-----+
```
-2. 생성한 공개키 Server로 전송하기
+# 3. 생성한 공개키 Server로 전송하기
```powershell
type $env:[public key path] | ssh [username]@[remote-host] "cat >> .ssh/authorized_keys"
```
-3. ssh 접속
+# 4. ssh 접속
```shell
ssh [username]@[remote-host]
```