doxa-maps/vite.config.js.timestamp-1790698770542-9b99b49958ff6.mjs
Doxa Maps 769d863f99 Rebuild the twenty consumers the merged library changes reach
The branch merges thirteen shared library files, including two new modules, so
every bundle that imports them was carrying older bytes than its source.

Found by building each of the twenty-two bundles the freshness step names, one
at a time: all twenty-two build cleanly in 8-24 seconds, none fails and none
hangs -- and twenty of them produce different bytes. Big Picture alone moves
510 bytes.

That also corrects a check I trusted earlier in this branch. `bun run tree`
reported zero changed files and I read it as "the consumers are fresh". It is
not: tree stages assets and regenerates leaf pages, and does NOT rebuild the
bundles, so it can report a clean tree over twenty stale ones. Only a build
answers that question.

Hashes rebaked and check:sri passes across every leaf.
2026-09-29 16:26:23 +00:00

1982 lines
386 KiB
JavaScript

var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __esm = (fn, res) => function __init() {
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
// internal/i18n-areas.mjs
var i18n_areas_exports = {};
__export(i18n_areas_exports, {
allAreas: () => allAreas,
areasForBundle: () => areasForBundle,
bundleGraph: () => bundleGraph
});
import { readFileSync as readFileSync6, existsSync as existsSync5, readdirSync as readdirSync4, statSync as statSync3 } from "node:fs";
import { resolve as resolve7, dirname as dirname5, join as join3, relative } from "node:path";
function allAreas(root) {
return readdirSync4(join3(root, "library/i18n/locales/en")).filter((f) => f.endsWith(".json")).map((f) => f.replace(/\.json$/, "")).sort();
}
function resolveFile(p) {
for (const cand of [p, p + ".js", p + ".mjs", p + ".vue", p + ".json", join3(p, "index.js")]) {
try {
if (existsSync5(cand) && statSync3(cand).isFile()) return cand;
} catch {
}
}
return null;
}
function expandGlob(pattern, fromDir) {
const abs = resolve7(fromDir, pattern);
const parts = abs.split("/");
const out = [];
const walk = (i, dir) => {
if (i === parts.length) return;
const seg = parts[i];
if (i === 0) return walk(1, "/");
if (!seg.includes("*")) {
const next = join3(dir, seg);
if (i === parts.length - 1) {
if (existsSync5(next)) out.push(next);
} else walk(i + 1, next);
return;
}
const re = new RegExp("^" + seg.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*") + "$");
let entries = [];
try {
entries = readdirSync4(dir);
} catch {
return;
}
for (const e of entries) if (re.test(e)) {
if (i === parts.length - 1) out.push(join3(dir, e));
else walk(i + 1, join3(dir, e));
}
};
walk(0, "/");
return out;
}
function bundleGraph(root, bundle) {
const entry = join3(root, "plugin-designs", bundle, "index.js");
const seen = /* @__PURE__ */ new Set();
const queue = [entry];
const LOCALES = join3(root, "library/i18n/locales");
while (queue.length) {
const f = queue.pop();
if (!f || seen.has(f) || f.startsWith(LOCALES) || f.includes("/node_modules/")) continue;
seen.add(f);
let src2 = "";
try {
src2 = readFileSync6(f, "utf8");
} catch {
continue;
}
const dir = dirname5(f);
const add = (spec) => {
if (!spec) return;
let p = null;
if (spec.startsWith("@map/")) p = join3(root, "library", spec.slice(5));
else if (spec.startsWith(".") || spec.startsWith("/")) p = spec.startsWith("/") ? join3(root, spec) : resolve7(dir, spec);
else return;
p = p.replace(/\?.*$/, "");
const r = resolveFile(p);
if (r) queue.push(r);
};
for (const m of src2.matchAll(IMPORT_RE)) add(m[1] || m[2] || m[3]);
for (const m of src2.matchAll(GLOB_RE)) {
const pats = m[1].startsWith("[") ? [...m[1].matchAll(/['"]([^'"]+)['"]/g)].map((x) => x[1]) : [m[1].slice(1, -1)];
for (const pat of pats) {
if (pat.startsWith("!")) continue;
const base = pat.startsWith("@map/") ? join3(root, "library") : dir;
for (const hit of expandGlob(pat.replace(/^@map\//, ""), base)) queue.push(hit);
}
}
}
return [...seen];
}
function areasForBundle(root, bundle, { extra = [] } = {}) {
const areas = allAreas(root);
const files = bundleGraph(root, bundle);
const text = files.map((f) => {
try {
return readFileSync6(f, "utf8");
} catch {
return "";
}
}).join("\n");
const used = new Set(extra);
const assemblesUnknownKeys = /\b(?:t|te|tm|tStatic|T)\(\s*`\$\{/.test(text);
for (const a of areas) {
const esc = a.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
if (new RegExp(`['"\`]${esc}\\.`).test(text)) {
used.add(a);
continue;
}
if (new RegExp(`\\b(?:useOptionalT|useOptionalI18n|qualify|tm|t|te|tStatic|rt)\\(\\s*['"\`]${esc}['"\`]`).test(text)) {
used.add(a);
continue;
}
if (assemblesUnknownKeys && new RegExp(`['"\`]${esc}['"\`]`).test(text)) used.add(a);
}
return { areas: [...used].filter((a) => areas.includes(a)).sort(), files: files.map((f) => relative(root, f)) };
}
var IMPORT_RE, GLOB_RE;
var init_i18n_areas = __esm({
"internal/i18n-areas.mjs"() {
IMPORT_RE = /(?:import|export)\s[^'"`;]*?from\s*['"]([^'"]+)['"]|import\s*['"]([^'"]+)['"]|import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
GLOB_RE = /import\.meta\.glob\s*\(\s*(\[[^\]]*\]|['"][^'"]+['"])/g;
}
});
// vite.config.js
import { defineConfig, loadEnv } from "file:///home/lk10x/Workspace/eco-dx/root-doxa-maps/doxa-maps-plugin-studio/node_modules/vite/dist/node/index.js";
import vue from "file:///home/lk10x/Workspace/eco-dx/root-doxa-maps/doxa-maps-plugin-studio/node_modules/@vitejs/plugin-vue/dist/index.mjs";
import cssInjectedByJsPlugin from "file:///home/lk10x/Workspace/eco-dx/root-doxa-maps/doxa-maps-plugin-studio/node_modules/vite-plugin-css-injected-by-js/dist/esm/index.js";
// internal/plugin-gallery/dev-plugin.mjs
import { resolve as resolve4, extname } from "node:path";
import { spawnSync } from "node:child_process";
import { readdirSync as readdirSync3, statSync as statSync2, existsSync as existsSync3, readFileSync as readFileSync5 } from "node:fs";
// internal/plugin-gallery/discover.mjs
import { resolve, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { readdirSync, statSync, existsSync, readFileSync } from "node:fs";
var __vite_injected_original_import_meta_url = "file:///home/lk10x/Workspace/eco-dx/root-doxa-maps/wt-hf/internal/plugin-gallery/discover.mjs";
var REPO_ROOT = resolve(dirname(fileURLToPath(__vite_injected_original_import_meta_url)), "..", "..");
var PROFILE_TIER = {
"nested-mfe-spa": 0,
"nested-elements-mfe": 1,
"monolithic": 2,
"parameterized": 3,
"single": 4
};
var TYPE_DISPLAY = {
"single": "single-element",
"parameterized": "preset-element",
"monolithic": "multi-view-element",
"nested-elements-mfe": "composite-element",
"nested-mfe-spa": "app-shell"
};
var TYPE_ALIASES = Object.fromEntries(Object.entries(TYPE_DISPLAY).map(([k, v]) => [v, k]));
var normalizeType = (t) => t && PROFILE_TIER[t] != null ? t : TYPE_ALIASES[t] || null;
function readJsonSafe(p) {
try {
return JSON.parse(readFileSync(p, "utf8"));
} catch {
return null;
}
}
function detectProfileType(dir, profile, ownTag, allTags, hasInstances) {
const meta = readJsonSafe(resolve(dir, `${profile}.meta.json`));
const declared = meta && normalizeType(meta.type);
if (declared) return { type: declared, label: meta.label || profile };
const type = hasInstances ? "parameterized" : "single";
try {
const childVue = countChildVue(dir);
if (childVue >= 5) {
console.warn(
`[discover] ${profile}: type INFERRED as "${type}" but the bundle has ${childVue} child .vue components. Tier 3+ is never inferred \u2014 if this nests multiple views internally it is "monolithic"; if its children are independently embeddable it is "nested-elements-mfe". Declare it in ${profile}.meta.json {"type": ...} or this ships understated.`
);
}
} catch {
}
return { type, label: meta && meta.label || profile };
}
function countChildVue(dir) {
let n = 0;
const walk = (d, depth) => {
for (const e of readdirSync(d, { withFileTypes: true })) {
if (e.name.startsWith(".") || e.name === "node_modules") continue;
const p = resolve(d, e.name);
if (e.isDirectory()) walk(p, depth + 1);
else if (depth > 0 && e.name.endsWith(".vue")) n++;
}
};
walk(dir, 0);
return n;
}
function discoverSpaRegistry(root = REPO_ROOT) {
const APP_DIR = resolve(root, "plugin-designs");
const bundles = [];
if (!existsSync(APP_DIR)) return bundles;
const dirs = readdirSync(APP_DIR).sort().filter((n) => {
const d = resolve(APP_DIR, n);
return statSync(d).isDirectory() && n !== "template-bundle" && existsSync(resolve(d, "index.js"));
});
const tagOf = {};
for (const n of dirs) {
try {
const m = readFileSync(resolve(APP_DIR, n, "index.js"), "utf8").match(/customElements\.define\(\s*['"]([^'"]+)['"]/);
if (m) tagOf[n] = m[1];
} catch {
}
}
const allTags = Object.values(tagOf);
for (const n of dirs) {
const dir = resolve(APP_DIR, n), tag = tagOf[n];
if (!tag) continue;
const files = readdirSync(dir);
const instFile = files.find((f) => /\.instances\.json$/i.test(f));
const rawInst = instFile ? readJsonSafe(resolve(dir, instFile)) : null;
const instances = Array.isArray(rawInst) ? rawInst : rawInst && Array.isArray(rawInst.instances) ? rawInst.instances : null;
const hasInstances = !!(instances && instances.length);
const instApi = rawInst && !Array.isArray(rawInst) && typeof rawInst.apiBaseUrl === "string" ? rawInst.apiBaseUrl : "";
const items = [];
for (const profile of files.filter((f) => f.endsWith(".vue")).map((f) => f.replace(/\.vue$/, "")).sort()) {
const t = detectProfileType(dir, profile, tag, allTags, hasInstances);
if (t.type === "parameterized" && hasInstances) {
for (const inst of instances) {
items.push({ profile, id: inst.id || inst.title || profile, label: inst.title || inst.id || profile, type: "parameterized", props: inst.props || {}, apiBaseUrl: instApi });
}
} else {
items.push({ profile, id: profile, label: t.label, type: t.type, props: null });
}
}
if (!items.length) continue;
items.sort((a, b) => (PROFILE_TIER[a.type] ?? 9) - (PROFILE_TIER[b.type] ?? 9));
const bestTier = Math.min(...items.map((i) => PROFILE_TIER[i.type] ?? 9));
bundles.push({ bundle: n, tag, items, bestTier });
}
bundles.sort((a, b) => a.bestTier - b.bestTier || a.bundle.localeCompare(b.bundle));
return bundles;
}
// internal/generate-gallery.mjs
import { readFileSync as readFileSync3, writeFileSync, existsSync as existsSync2, readdirSync as readdirSync2, mkdirSync } from "node:fs";
import { join, resolve as resolve3, dirname as dirname3 } from "node:path";
import { fileURLToPath as fileURLToPath3, pathToFileURL } from "node:url";
// internal/_tree-name.mjs
import { readFileSync as readFileSync2 } from "node:fs";
import { resolve as resolve2, dirname as dirname2 } from "node:path";
import { fileURLToPath as fileURLToPath2 } from "node:url";
var __vite_injected_original_import_meta_url2 = "file:///home/lk10x/Workspace/eco-dx/root-doxa-maps/wt-hf/internal/_tree-name.mjs";
var ROOT = resolve2(dirname2(fileURLToPath2(__vite_injected_original_import_meta_url2)), "..");
var BUILD_CONFIG_FILE = resolve2(ROOT, "vite.doxa-maps-build-config.json");
var FALLBACK = "doxa-maps";
function read() {
let name = "";
try {
const cfg = JSON.parse(readFileSync2(BUILD_CONFIG_FILE, "utf8"));
if (cfg && typeof cfg.name === "string") name = cfg.name.trim();
} catch {
}
if (!name) return FALLBACK;
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(name) || name.includes("..")) {
throw new Error(`[_tree-name] build config "name" must be a single URL-safe path segment, got ${JSON.stringify(name)}`);
}
return name;
}
var TREE_NAME = read();
function readGated() {
try {
const cfg = JSON.parse(readFileSync2(BUILD_CONFIG_FILE, "utf8"));
return Array.isArray(cfg.gatedProfiles) ? cfg.gatedProfiles.filter((x) => typeof x === "string" && x.trim()).map((x) => x.trim()) : [];
} catch {
return [];
}
}
var GATED_PROFILES = readGated();
var TREE_NAME_RE = TREE_NAME.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
if (process.argv[1] && resolve2(process.argv[1]) === fileURLToPath2(__vite_injected_original_import_meta_url2)) process.stdout.write(TREE_NAME + "\n");
// internal/generate-gallery.mjs
var __vite_injected_original_import_meta_url3 = "file:///home/lk10x/Workspace/eco-dx/root-doxa-maps/wt-hf/internal/generate-gallery.mjs";
var ROOT2 = resolve3(dirname3(fileURLToPath3(__vite_injected_original_import_meta_url3)), "..");
function readSourceTiers(appDir = join(ROOT2, "plugin-designs")) {
const out = {};
if (!existsSync2(appDir)) return out;
let dirs = [];
try {
dirs = readdirSync2(appDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
} catch {
return out;
}
for (const bundle of dirs) {
const dir = join(appDir, bundle);
let files = [];
try {
files = readdirSync2(dir);
} catch {
continue;
}
const hasInstances = files.some((f) => /\.instances\.json$/i.test(f));
for (const f of files) {
if (!f.endsWith(".vue")) continue;
const profile = f.replace(/\.vue$/, "");
try {
const t = detectProfileType(dir, profile, "", [], hasInstances);
out[bundle + "/" + profile] = t.type;
} catch {
}
}
}
return out;
}
function readBuildConfig() {
let cfg = {};
try {
cfg = JSON.parse(readFileSync3(join(ROOT2, "vite.doxa-maps-build-config.json"), "utf8"));
} catch {
}
const str = (k) => typeof cfg[k] === "string" ? cfg[k].trim() : "";
let tokenUrl = str("tokenUrl");
if (!tokenUrl) {
try {
const src2 = JSON.parse(readFileSync3(join(ROOT2, "library/api/sources.json"), "utf8"));
const v = src2?._meta?.mapboxTokenUrl || src2?.mapboxTokenUrl;
if (typeof v === "string" && v.trim()) tokenUrl = v.trim();
} catch {
}
}
return {
name: str("name") || TREE_NAME,
title: str("displayTitle") || TREE_NAME,
tokenUrl: tokenUrl || "window.MAP_TOKEN_URL",
token: str("token"),
apiBaseUrl: str("apiBaseUrl").replace(/\/+$/, ""),
assetsBaseUrl: str("assetsBaseUrl").replace(/\/+$/, ""),
qaWidget: cfg.qaWidget !== false
};
}
function snip(b, p, x) {
var u = (x || p).u, tag = x && x.e || p.e || b.e[0] || b.b;
var r = { iframe: '<iframe src="' + u + '?utm_source=YOUR_SOURCE" width="100%" height="600" style="border:none;border-radius:12px;" allowfullscreen></iframe>' };
if (!x) r.script = '<script src="' + b.s + '"' + (b.i ? ' integrity="' + b.i + '" crossorigin="anonymous"' : "") + "></script>\n<" + tag + " profile-config='" + JSON.stringify({ profile: p.p, tk: "YOUR_MAPBOX_TOKEN", utmSource: "YOUR_SOURCE" }) + "'></" + tag + ">";
return r;
}
function compact(m, lean, tierMap) {
tierMap = tierMap || {};
var PT = { "nested-mfe-spa": 0, "nested-elements-mfe": 1, "monolithic": 2, "parameterized": 3, "single": 4 };
var capFor = function(t) {
return PT[t] != null ? 5 - PT[t] : 1;
};
return (m.bundles || []).map(function(src2) {
var b = { b: src2.bundle, s: src2.scriptUrl || "", i: src2.integrity || "", e: src2.elements || [], p: [] };
b.p = (src2.profiles || []).map(function(sp) {
var type = sp.type || tierMap[src2.bundle + "/" + sp.profile] || "single";
var c = capFor(type);
var p = { p: sp.profile, e: sp.element || "", u: sp.iframeUrl || "", d: sp.description || "", c };
var em = sp.embed || {}, d = snip(b, p, null);
if (!lean || em.iframe !== d.iframe || em.script !== d.script) p.em = em;
var ins = (sp.instances || []).map(function(sx) {
var x = { id: sx.id, t: sx.title || sx.id, a: sx.apiBaseUrl || "", pr: sx.props || {}, e: sx.element || "", u: sx.iframeUrl || "" };
var xe = sx.embed || {}, xd = snip(b, p, x);
if (!lean || xe.iframe !== xd.iframe) x.em = xe;
return x;
});
if (ins.length) p.in = ins;
return p;
});
return b;
});
}
var src = (fn) => fn.toString().replace(/<\/script/gi, "<\\/script");
var LADDER_CSS = String.raw`:root{--acc:#1a73e8}@media(prefers-color-scheme:dark){:root{--acc:#64b5f6}}
.ladder{position:relative;margin-left:auto;display:flex;align-items:center;gap:6px;white-space:nowrap}
.rung{display:inline-flex;align-items:center;gap:4px}.rname{font:500 12px/1 ui-monospace,Menlo,monospace}
.arrow{color:var(--mut);font-size:12px;padding:0 1px}
.q{width:18px;height:18px;padding:0;border-radius:50%;font:700 11px/1 system-ui,sans-serif;color:var(--mut);background:var(--bg);display:inline-grid;place-items:center}
.start{font:600 10.5px/1 system-ui,sans-serif;letter-spacing:.04em;text-transform:uppercase;color:var(--acc);background:var(--bg);border-radius:999px;padding:4px 9px;margin-right:4px}
.q:hover,.q[aria-expanded=true],.start:hover,.start[aria-expanded=true]{color:var(--acc);border-color:var(--acc);background:var(--bg)}
.explain{position:absolute;top:calc(100% + 8px);right:0;width:420px;max-width:calc(100vw - 32px);max-height:70vh;overflow:auto;z-index:40;background:var(--bg);border:1px solid var(--bd);border-radius:10px;box-shadow:0 4px 16px rgba(0,0,0,.14);padding:12px 14px;font-size:13px;line-height:1.45;text-align:left;white-space:normal}
.explain h3{margin:0 0 5px;font-size:14px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}.explain h4{margin:8px 0 3px;font-size:13px}
.explain .tier{font:700 10px/1 system-ui,sans-serif;letter-spacing:.6px;text-transform:uppercase;color:var(--mut)}
.explain p{margin:0 0 6px}.explain .aka{font-size:11.5px;color:var(--mut);margin:-2px 0 6px}
.explain .how{margin:0 0 6px;font-size:12.5px}.explain .how summary{cursor:pointer;color:var(--acc);font-weight:600;font-size:12px}.explain .how p{margin:6px 0 0;color:var(--mut)}
.explain .ex{color:var(--mut);font-size:12px}
@media(max-width:1280px){.ladder{display:none}}
`;
var LADDER_HTML = '<nav class="ladder" id="ladder" aria-label="Composability ladder" v-pre></nav>';
var LADDER_JS = String.raw`<script>
(function () {
var PRIMER = [
{ title: 'Element',
def: 'A custom HTML tag this repo invents, such as &lt;doxa-map&gt;: the browser learns it once, then you can paste it into any page as often as you like. Each pasted tag is one live copy, called an instance. (People also say &quot;web component&quot;.)',
how: 'The bundle index.js turns the shared ProfileLoader into an element class with defineCustomElement and registers the tag once with customElements.define.',
ex: '&lt;doxa-map profile-config=&#39;{&quot;profile&quot;:&quot;doxa-simple-map&quot;}&#39;&gt;&lt;/doxa-map&gt;' },
{ title: 'App profile (mounting file)',
def: 'One flat .vue file in plugin-designs/&lt;bundle&gt;/ that defines a whole map app — the main component of that map. The settings written on the tag (profile-config) name which app profile to load, and the shared ProfileLoader picks it. In class-and-object terms: the element class is the class, each tag on a page is an instance, and the app profile is the screen that instance loads.',
how: 'Most repos need one such main file per app. ${TREE_NAME} builds hundreds of maps from one shared library, so every map gets its own app profile — the folder plugin-designs/ is where they sit. The five kinds on this ladder are the five shapes those files come in.',
ex: 'plugin-designs/doxa-simple-map/doxa-simple-map.vue' }
];
var LADDER = [
{ label: 'single-element', tier: 4, title: 'Single element', aka: 'single',
def: 'One app profile, one map: paste its tag into any page, once or many times, and set it up right there in profile-config. The smallest kind and the default — no preset table, no tabs, no nested maps.',
how: 'A flat .vue with no &lt;profile&gt;.meta.json beside it and no *.instances.json in the bundle folder. Machine key: single.',
ex: 'cities-internet/connectivity-map.vue → &lt;cities-internet-map&gt; · gospel-resources/resources-map.vue' },
{ label: 'preset-element', tier: 3, title: 'Preset element', aka: 'parameterized · prop-many-elements',
def: 'One app profile plus a small table of named presets (&lt;name&gt;.instances.json). Each row is one ready-made map with its settings baked in and gets its own embed page and sidebar entry — same code, same tag.',
how: 'The bundle folder holds &lt;name&gt;.instances.json ({&quot;instances&quot;:[{id,title,props}]}); the build writes one embed page per row at &lt;bundle&gt;/&lt;profile&gt;/&lt;id&gt;/index.html. Machine key: parameterized. Not this if the versions need different code — make another app profile.',
ex: 'doxa-simple-map.vue + simple-map.instances.json → Prayer / Engagement / Adoption' },
{ label: 'multi-view-element', tier: 2, title: 'Multi-view element', aka: 'monolithic · monolithic-mfe',
def: 'One app profile that holds several screens you switch between — tabs or steps — all written in one .vue and shown as one element, one screen at a time. Keeping them in one file is on purpose.',
how: 'Declared, never guessed: &lt;profile&gt;.meta.json {&quot;type&quot;:&quot;monolithic&quot;} (or &quot;multi-view-element&quot;); the .vue owns its own switcher. Not this if the pieces are other app profiles (composite) or all panels show at once (single).',
ex: 'doxa-research-map/research-map.vue — six tabs in one &lt;doxa-research-map&gt;' },
{ label: 'composite-element', tier: 1, title: 'Composite element', aka: 'nested-elements-mfe',
def: 'An app profile whose template places the maps of other app profiles together — stacked or side by side, such as a map and a poster wall — and ships the result as one new element. One tag embeds the whole set.',
how: 'Declared: &lt;profile&gt;.meta.json {&quot;type&quot;:&quot;nested-elements-mfe&quot;,&quot;composes&quot;:[…]} (or &quot;composite-element&quot;); the .vue creates each child tag with its own profile-config on the pane layout (layouts/pane-wrapper). Not this if the screens are written inside one file (multi-view).',
ex: 'my-upg-100-list/upg-100-mfe.vue — Map pane + Prayer Lists pane, one Share button' },
{ label: 'app-shell', tier: 0, title: 'App shell', aka: 'nested-mfe-spa · container application · root config · host',
def: 'The outer frame of a whole app — sidebar, header, navigation — that loads any of the other four kinds inside it and switches between them without a page reload. The only rung that is a page, not an element: what a visitor actually opens.',
how: 'Today both shells are HTML pages, not .vue app profiles: layouts/app-wrapper-material/index.html and this plugin gallery (internal/generate-gallery.mjs, one generator for the dev root and public/index.html). Machine key nested-mfe-spa (or app-shell) is reserved for a future .vue shell.',
ex: 'this plugin gallery · the Doxa Maps SPA' }
];
var ladder = document.getElementById('ladder'), openQ = null;
var pop = document.createElement('div'); pop.className = 'explain'; pop.hidden = true; pop.setAttribute('role', 'dialog');
function closePop() { pop.hidden = true; if (openQ) { openQ.setAttribute('aria-expanded', 'false'); openQ = null } }
function showPop(btn, html) { if (openQ === btn) { closePop(); return } closePop(); openQ = btn; btn.setAttribute('aria-expanded', 'true'); pop.innerHTML = html; pop.hidden = false }
function howBlock(t) { return '<details class="how"><summary>For builders — how to recognise it</summary><p>' + t + '</p></details>' }
function kindHtml(r) { return '<h3>' + r.title + ' <span class="tier">tier ' + r.tier + ' · ' + r.label + '</span></h3><p>' + r.def + '</p><div class="aka">a.k.a. ' + r.aka + '</div>' + howBlock(r.how) + '<div class="ex">e.g. ' + r.ex + '</div>' }
function primerHtml() { return '<h3>Start here <span class="tier">the two words every rung uses</span></h3>' + PRIMER.map(function (p) { return '<h4>' + p.title + '</h4><p>' + p.def + '</p>' + howBlock(p.how) + '<div class="ex">e.g. ' + p.ex + '</div>' }).join('') }
var start = document.createElement('button'); start.className = 'start'; start.type = 'button'; start.textContent = 'Start here'; start.setAttribute('aria-expanded', 'false');
start.setAttribute('aria-label', 'What is an element? What is an app profile?'); start.onclick = function (e) { e.stopPropagation(); showPop(start, primerHtml()) }; ladder.appendChild(start);
LADDER.forEach(function (r, i) {
if (i) { var a = document.createElement('span'); a.className = 'arrow'; a.textContent = '→'; ladder.appendChild(a) }
var rung = document.createElement('span'); rung.className = 'rung';
var nm = document.createElement('span'); nm.className = 'rname'; nm.textContent = r.label;
var q = document.createElement('button'); q.className = 'q'; q.type = 'button'; q.textContent = '?'; q.setAttribute('aria-label', 'What is a ' + r.title.toLowerCase() + '?'); q.setAttribute('aria-expanded', 'false');
q.onclick = function (e) { e.stopPropagation(); showPop(q, kindHtml(r)) };
rung.appendChild(nm); rung.appendChild(q); ladder.appendChild(rung);
});
ladder.appendChild(pop);
document.addEventListener('click', function (e) { if (!ladder.contains(e.target)) closePop() });
document.addEventListener('keydown', function (e) { if (e.key === 'Escape') closePop() });
})();
</script>
`;
function renderGallery(model, opts = {}) {
const { mode = "build", title = TREE_NAME, tree = TREE_NAME, tokenUrl = "window.MAP_TOKEN_URL", token = "", apiBaseUrl = "", assetsBaseUrl = "", qaWidget = true, tierMap = {} } = opts;
const dev = mode === "dev";
const baked = compact(model, true, tierMap);
const json = (v) => JSON.stringify(v).replace(/</g, "\\u003c");
const esc = (s) => String(s).replace(/&/g, "&amp;").replace(/</g, "&lt;");
const loader = dev ? `function bundle(b) { return import(rel(b.s)) }` : `function bundle(b) { return once(rel(b.s), 'js', b.i ? { integrity: b.i, crossOrigin: 'anonymous' } : {}) }`;
return String.raw`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>${esc(title)}</title>
<link rel="icon" href="data:,">
<style>
:root{--bg:#fff;--bg2:#f6f7f9;--bg3:#eceef2;--bd:#e2e5ea;--fg:#15181d;--mut:#667085;--err:#d13c3c}
@media(prefers-color-scheme:dark){:root{--bg:#111318;--bg2:#181b21;--bg3:#232730;--bd:#2b3038;--fg:#eef0f3;--mut:#9aa3b2;--err:#ff7b7b}}
*{box-sizing:border-box}html,body{margin:0;height:100%}
body{background:var(--bg);color:var(--fg);font:14px/1.4 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;display:flex;flex-direction:column;height:100vh}
header{flex:0 0 auto;display:flex;align-items:center;gap:10px;padding:8px 14px;border-bottom:1px solid var(--bd)}
header b{font-size:15px}.n{color:var(--mut);font-size:12px}
#menu{display:none;margin-left:auto}
button,.btn{font:inherit;font-size:12px;padding:5px 10px;border:1px solid var(--bd);border-radius:8px;background:var(--bg2);color:var(--fg);cursor:pointer;text-decoration:none;white-space:nowrap}
button:hover,.btn:hover{background:var(--bg3)}
.body{flex:1 1 auto;display:flex;min-height:0}
nav{flex:0 0 270px;overflow:auto;border-right:1px solid var(--bd);padding:6px 0 20px}
.gh{padding:12px 14px 4px;font-weight:600;font-size:13px;display:flex;justify-content:space-between;gap:8px}.gh span{color:var(--mut);font-weight:400}
.row{display:block;width:100%;text-align:left;border:0;border-radius:0;background:none;padding:6px 14px;font-size:13px;line-height:1.3;white-space:normal}
.row.in{padding-left:28px}.row code{display:block;font-size:11px;color:var(--mut)}
.row:hover{background:var(--bg2)}.row[aria-current=true]{background:var(--bg3);font-weight:600}
main{flex:1 1 auto;display:flex;flex-direction:column;min-width:0;padding:10px 12px 12px;gap:8px}
.bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.bar .t{flex:1 1 auto;min-width:0}.bar b{font-size:15px}.s{display:block;font-size:12px;color:var(--mut)}
code{font-family:ui-monospace,Menlo,monospace}
#embed{display:flex;flex-direction:column;gap:6px;padding:8px;border:1px solid var(--bd);border-radius:8px;background:var(--bg2)}
#embed label{font-size:12px;color:var(--mut);display:flex;justify-content:space-between;align-items:center}
#embed textarea{width:100%;height:58px;font:11px/1.35 ui-monospace,Menlo,monospace;border:1px solid var(--bd);border-radius:6px;background:var(--bg);color:var(--fg);padding:6px;resize:vertical}
#slot{flex:1 1 auto;position:relative;min-height:240px;border:1px solid var(--bd);border-radius:10px;overflow:hidden;background:var(--bg2)}
#slot>*{position:absolute;inset:0;width:100%;height:100%;display:block;border:0}
.hint{display:grid;place-items:center;padding:20px;text-align:center;color:var(--mut);font-size:13px}
.hint.err{color:var(--err)}
.hint input{font:12px ui-monospace,Menlo,monospace;padding:6px 8px;border-radius:6px;border:1px solid var(--bd);background:var(--bg);color:var(--fg);width:min(320px,70vw)}
/* Capability tiers (5 → 1): the vertical-tab sections of the nested-mfe-spa sidebar. */
.tier{padding:12px 14px 2px;display:flex;align-items:baseline;gap:7px}
.tier .cap{font:700 10px/1 system-ui,sans-serif;letter-spacing:.5px;color:var(--bg);background:var(--mut);border-radius:999px;padding:3px 7px}
.tier .tl{font-weight:600;font-size:12px}.tier .td{color:var(--mut);font-size:11px;margin-left:auto}
#app{flex:1 1 auto;display:flex;flex-direction:column;min-height:0}
[hidden]{display:none!important}
@media(max-width:700px){.body{flex-direction:column}nav{flex:0 0 auto;max-height:45vh;border-right:0;border-bottom:1px solid var(--bd)}#menu{display:inline-block}}
${dev ? LADDER_CSS : ""}</style>
</head>
<body>
<!-- The ${TREE_NAME} nested-mfe-spa (capability 5, the reserved app-shell): a Vue single-page app
whose sidebar is the composability ladder rendered as vertical tabs (capability 5 → 1),
each row mounting that plugin's custom element in the one slot. This SAME page is the
served studio root (public/index.html) AND the Capacitor mobile-app entry (webDir: public).
Vue drives the shell; the map elements mount imperatively into #slot (they own their DOM). -->
<div id="app">
<header>
<b>${esc(title)}</b><span class="n">{{ countLabel }}</span>${dev ? LADDER_HTML : ""}
<button id="menu" type="button" aria-controls="nav" aria-expanded="true" @click="navOpen = !navOpen">Maps</button>
</header>
<div class="body">
<nav id="nav" aria-label="Maps · sorted by capability 5 → 1" v-show="navOpen">
<div class="grp" v-for="grp in groups" :key="grp.cap">
<div class="tier"><span class="cap">CAP {{ grp.cap }}</span><span class="tl">{{ grp.label }}</span><span class="td">{{ grp.rows.length }}</span></div>
<!-- data-k EXPOSES THE ROW IDENTITY TO THE DOM. A Vue :key is a RECONCILIATION HINT and is NOT
rendered as an attribute — a distinction that had smoke:gallery failing on a working page.
That gate reads row.dataset.k to confirm a deep link selected the row it asked for; with no
such attribute it read undefined and reported "deep link resolved to undefined".
MEASURED 2026-09-22: data-k appeared ZERO times in this generator and zero times in the
built page, while the gallery itself mounts its elements correctly — a false RED, which is
as corrosive as a false green because it gets the gate switched off.
Asserting on the rendered LABEL instead would be worse: it couples a machine check to
display text, so renaming a profile would break the gate. Identity belongs in the DOM.
NOTE: this markup lives inside a TEMPLATE LITERAL — no backticks anywhere in this comment,
or the literal ends here and the rest of the file is parsed as code. -->
<button v-for="r in grp.rows" :key="r.key" :data-k="r.key" type="button" class="row" :class="{ in: r.kind === 'instance' }"
:aria-current="String(activeKey === r.key)" @click="go(r.key)">
<span>{{ r.label }}</span><code>&lt;{{ r.tag }}&gt;</code>
</button>
</div>
</nav>
<main>
<div class="bar">
<div class="t"><b>{{ ttl }}</b><span class="s">{{ sub }}</span></div>
<a class="btn" :href="openHref" target="_blank" rel="noopener" v-show="openHref">Open page</a>
<button type="button" v-show="hasSel" :aria-expanded="String(embedOpen)" @click="embedOpen = !embedOpen">Copy embed</button>
</div>
<div id="embed" v-show="embedOpen && hasSel">
<label>iframe embed <button type="button" @click="copyText(embedIframe, $event.target)">Copy</button></label>
<textarea readonly :value="embedIframe"></textarea>
<div v-show="embedScript"><label>script embed <button type="button" @click="copyText(embedScript, $event.target)">Copy</button></label>
<textarea readonly :value="embedScript"></textarea></div>
</div>
<div id="slot" ref="slot"><div class="hint">Choose a map from the list.</div></div>
</main>
</div>
</div>
<script>
(function () {
var TREE = ${json(tree)}, TOKEN_SRC = ${json(tokenUrl)}, BAKED_TOKEN = ${json(token)}, API_BASE = ${json(apiBaseUrl)}, ASSETS_BASE = ${json(assetsBaseUrl)}, QA = ${json(qaWidget)};
var DEFAULT_TOKEN_URL = '/api/maps/token';
var BAKED = ${json(baked)};
var snip = ${src(snip)};
var compact = ${src(compact)};
// Peer engines, the same tags every leaf page carries; loaded once, before the bundle.
var PEERS = {
mapbox: { css: ['https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css', 'https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css'],
js: ['https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js', 'https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js'] },
maplibre: { css: ['https://cdn.jsdelivr.net/npm/maplibre-gl@5/dist/maplibre-gl.css'], js: ['https://cdn.jsdelivr.net/npm/maplibre-gl@5/dist/maplibre-gl.js'] }
};
var $ = function (id) { return document.getElementById(id) };
// The map custom elements mount imperatively into this slot (they own their own DOM and must
// not be re-rendered by Vue); the Vue app writes its ref here after mount. Falls back to the
// element id so the loader works even before the app boots.
var slotEl = function () { return (window.__spa && window.__spa.slot) || $('slot') };
var TIER_MAP = ${json(tierMap)}; // "<bundle>/<profile>" → composition tier, for live re-compact
// THIS PAGE'S OWN DIRECTORY. A host may serve the folder at /…/doxa-maps-build (no trailing
// slash); the browser would then resolve every relative ref against the PARENT directory and
// drop the folder name, so bundles 404. Derive the directory explicitly and build refs from it.
var BASE = (function () {
var p = location.pathname || '/';
return /\.[a-z0-9]+$/i.test(p) ? p.replace(/[^/]*$/, '') : p.replace(/\/*$/, '') + '/';
})();
// ★ THE TREE ROOT AS ONE ABSOLUTE URL — derive it ONCE, never re-join TREE by hand.
// TREE is PAGE-RELATIVE and its value differs per surface ('../doxa-maps' in the built tree,
// '__plugin-gallery' in dev), so a bare TREE + '/x' join is only accidentally right. It was right
// in the built tree (where the '../' climbs out of /__gallery/) and WRONG in dev, where it asked
// for /__gallery/__plugin-gallery/manifest.json. MEASURED 2026-09-22, both servers running:
// dev /__gallery/__plugin-gallery/manifest.json ... 404 (what the page asked for)
// dev /__plugin-gallery/manifest.json ............. 200 (what it meant)
// built /doxa-maps/manifest.json .................... 200
// rel() never had the bug because it always anchored to BASE. Resolving through the URL parser
// (rather than string-joining) also collapses the '../' properly for BOTH surfaces at once.
// Resolve TREE *against* the page's own directory — do NOT string-join it onto BASE. TREE may be
// ROOTED ('/__plugin-gallery' in dev), and 'BASE + TREE' would glue it on to yield
// /__gallery//__plugin-gallery, which 404s just as surely as the original bug. Passing BASE as
// the base URL lets the URL parser apply the right rule per shape: a rooted TREE replaces the
// path, a '../' TREE climbs out of /__gallery/, and a bare name resolves beside it.
var TREE_URL = new URL(TREE, new URL(BASE, location.href)).href.replace(/\/+$/, '');
// ASSETS live INSIDE the tree (public/<tree>/assets), which is what every leaf page points at:
// a leaf at /<tree>/<bundle>/<profile>/ bakes assetsBase "../../assets" -> /<tree>/assets. So
// anchor to TREE_URL, not to this PAGE's directory.
// This was BASE + 'assets' — correct only while the gallery WAS the root page, where the two
// coincide. Since the gallery moved to /__gallery it asked for /__gallery/assets/... MEASURED
// on the built tree with the page at /__gallery/:
// /__gallery/assets/vendor/vue/vue.global.prod.js ... 404 (what the page asked for)
// /doxa-maps/assets/vendor/vue/vue.global.prod.js ... 200 (where it lives)
// It degraded quietly rather than blanking — loadVue() falls back to the jsDelivr CDN — so the
// page still worked while silently losing the portable/offline/no-CDN property the vendored
// copy exists to provide. The dev server passes assetsBaseUrl explicitly, so this is the
// built-tree half of the same fix its comment already documents.
var ASSETS = ASSETS_BASE || TREE_URL + '/assets';
var REG = BAKED, active = null, seq = 0, loaded = {}, fetchedToken = '';
var narrow = function () { return window.matchMedia && window.matchMedia('(max-width:700px)').matches };
// Manifest refs are relative to the tree root; this page sits one level above it. Refs are
// anchored to BASE (above) so they resolve the same with or without a trailing slash.
function rel(u) { return /^([a-z]+:|\/)/i.test(u) ? u : BASE + TREE + '/' + u.replace(/^\.\//, '') }
function qp(name) { try { return new URLSearchParams(location.search).get(name) || '' } catch (e) { return '' } }
function hint(msg, err) { var slot = slotEl(); var d = document.createElement('div'); d.className = 'hint' + (err ? ' err' : ''); d.textContent = msg; slot.innerHTML = ''; slot.appendChild(d); return d }
function assign(t) { for (var i = 1; i < arguments.length; i++) { var s = arguments[i]; for (var k in s) if (Object.prototype.hasOwnProperty.call(s, k)) t[k] = s[k] } return t }
function once(url, kind, attrs) {
if (loaded[url]) return loaded[url];
loaded[url] = new Promise(function (ok, fail) {
var el = document.createElement(kind === 'css' ? 'link' : 'script');
if (kind === 'css') { el.rel = 'stylesheet'; el.href = url } else { el.src = url; assign(el, attrs || {}) }
el.onload = function () { ok() }; el.onerror = function () { delete loaded[url]; fail(new Error('failed to load ' + url)) };
document.head.appendChild(el);
});
return loaded[url];
}
function peer(provider) {
var p = PEERS[provider] || PEERS.mapbox, chain = Promise.resolve();
p.css.forEach(function (u) { once(u, 'css') });
p.js.forEach(function (u) { chain = chain.then(function () { return once(u, 'js') }) });
return chain;
}
${loader}
// Resolve a deep-link key ("<bundle>/<profile>[/<instance>]") against the live registry.
function find(parts) {
for (var i = 0; i < REG.length; i++) if (REG[i].b === parts[0]) {
var b = REG[i];
for (var j = 0; j < b.p.length; j++) if (b.p[j].p === parts[1]) {
var p = b.p[j];
if (parts.length < 3) return { b: b, p: p, x: null };
for (var k = 0; k < (p.in || []).length; k++) if (p.in[k].id === parts[2]) return { b: b, p: p, x: p.in[k] };
}
}
return null;
}
// Same profile-config the leaf page bakes (profile page: profile + dataSource + instanceId;
// instance page: its props), plus the host-supplied share URL of that leaf page.
function mount(b, p, x, tag) {
var cfg = x ? assign({ assetsBase: ASSETS }, x.pr) : { profile: p.p, dataSource: 'pray-tools', instanceId: b.b + '-' + p.p, assetsBase: ASSETS };
if (QA) cfg.qa = true;
cfg.shareUrl = new URL(rel((x || p).u), location.href).href;
// ★ HAND THE TREE ROOT DOWN — an element that fetches the manifest cannot guess it from here.
// A cap-5 shell derives its tree root from location.pathname when nothing is passed, which is
// right on its own <tree>/<bundle>/<profile>/ leaf page and WRONG in this gallery, where the
// path belongs to the PAGE, not the element. doxa-maps-spa's relative fallback is '../', so
// from /__gallery/ it asked for /manifest.json. MEASURED by the smoke:gallery gate:
// ✗ doxa-maps-spa/doxa-maps-spa data: 404 http://localhost:5173/manifest.json
// The SPA's OWN nested-mount path already sets both of these for exactly this reason; this
// gallery was the one mount path that never learned the lesson. Set both, because not every
// element reads profile-config (an element mounting its own SFC has no ProfileLoader above it
// and takes tree-base as a prop); an element that declares neither ignores both.
cfg.treeBase = TREE_URL;
window.MAP_APP_API_URL = (x && x.a) || API_BASE;
var provider = cfg.provider === 'maplibre' ? 'maplibre' : 'mapbox', my = ++seq;
hint(provider === 'maplibre' ? 'loading map…' : 'loading token…');
peer(provider).then(function () { return bundle(b) }).then(function () {
if (my !== seq) return;
resolveToken(cfg, provider === 'maplibre', function (token) {
if (my !== seq) return;
try {
var c = token ? assign({}, cfg, { tk: token }) : cfg;
var el = document.createElement(tag); el.setAttribute('profile-config', JSON.stringify(c));
el.setAttribute('tree-base', TREE_URL); // see cfg.treeBase above — both, for both kinds of element
var slot = slotEl(); slot.innerHTML = ''; slot.appendChild(el);
} catch (e) { hint(e && e.message ? e.message : String(e), true) }
});
}).catch(function (e) { if (my === seq) hint('Failed to load ' + b.b + ': ' + (e && e.message ? e.message : e), true) });
}
// Mapbox token resolution — the leaf pages' ladder, in precedence order:
// 1. prop (config.tk) 2. ?tk= on this page's URL (stored once for every page of the tree)
// 3. baked token — then, none found, a token ENDPOINT is fetched, first answer wins:
// 4. window.MAP_TOKEN_URL 5. configured TOKEN_SRC 6. same-origin /api/maps/token — else ask once.
function resolveToken(cfg, tokenFree, done) {
if (tokenFree) return done('');
var stored = ''; try { stored = localStorage.getItem('MAPS_STAGING_TK') || '' } catch (e) {}
var urlTk = qp('tk'); if (urlTk) { try { localStorage.setItem('MAPS_STAGING_TK', urlTk) } catch (e) {} }
var directToken = cfg.tk || urlTk || stored || BAKED_TOKEN || fetchedToken;
if (directToken) return done(directToken);
function askToken(prefix) {
var d = hint('', true);
d.innerHTML = (prefix ? '<div></div>' : '') + '<div>map needs a Mapbox token — <input id="tkIn" type="password" placeholder="paste pk.… (stays in this browser)"> <button id="tkGo" type="button">use it</button></div>';
if (prefix) d.firstChild.textContent = prefix;
$('tkGo').onclick = function () { var v = ($('tkIn').value || '').trim(); if (!v) return; try { localStorage.setItem('MAPS_STAGING_TK', v) } catch (e) {} done(v) };
}
var candidates = [];
function addCandidate(u) { if (u && candidates.indexOf(u) === -1) candidates.push(u) }
addCandidate(window.MAP_TOKEN_URL);
addCandidate(TOKEN_SRC && TOKEN_SRC !== 'window.MAP_TOKEN_URL' ? TOKEN_SRC : '');
addCandidate(DEFAULT_TOKEN_URL);
function extractToken(data) { if (typeof data === 'string') return data.trim(); if (data && typeof data === 'object') return data.token || data.tk || data.accessToken || ''; return '' }
function fetchToken(i, errors) {
if (i >= candidates.length) return askToken('Token fetch failed from ' + candidates.join(', ') + ' — set window.MAP_TOKEN_URL or pass ?tk=. (' + errors.join(' | ') + ')');
var url = candidates[i];
return fetch(url).then(function (r) {
if (!r.ok) throw new Error(url + ' → HTTP ' + r.status);
return (r.headers.get('content-type') || '').indexOf('json') !== -1 ? r.json() : r.text();
}).then(function (data) {
var tk = extractToken(data); if (!tk) throw new Error(url + ' → no token in response');
fetchedToken = tk; done(tk);
}).catch(function (e) { errors.push(e && e.message ? e.message : String(e)); return fetchToken(i + 1, errors) });
}
fetchToken(0, []);
}
function copyText(text, btn) {
var ok = function () { var t = btn.textContent; btn.textContent = 'Copied'; setTimeout(function () { btn.textContent = t }, 1200) };
if (navigator.clipboard && navigator.clipboard.writeText) navigator.clipboard.writeText(text).then(ok, function () {}); else {
try { var ta = document.createElement('textarea'); ta.value = text; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); document.body.removeChild(ta); ok() } catch (e) {}
}
}
// ── The capability ladder for the sidebar headings (5 → 1), reader-facing names ──
var CAP_LABEL = { 5: 'App shell · nested-mfe-spa', 4: 'Composite element', 3: 'Multi-view element', 2: 'Preset element', 1: 'Single element' };
// REG → tab groups keyed by capability, most-composed first (5 → 1). Each group lists every
// profile (and its preset instances) as one row; a bundle contributes rows to the tier of each
// profile it holds, so one bundle can appear under several capability headings.
function toGroups() {
var byCap = {};
REG.forEach(function (b) {
(b.p || []).forEach(function (p) {
var cap = p.c || 1, tag = p.e || b.e[0] || b.b;
(byCap[cap] = byCap[cap] || []).push({ key: b.b + '/' + p.p, kind: 'profile', label: p.p, tag: tag, bundle: b.b });
(p.in || []).forEach(function (x) {
byCap[cap].push({ key: b.b + '/' + p.p + '/' + x.id, kind: 'instance', label: x.t, tag: x.e || tag, bundle: b.b });
});
});
});
return [5, 4, 3, 2, 1].filter(function (c) { return byCap[c] && byCap[c].length }).map(function (c) {
return { cap: c, label: CAP_LABEL[c] || ('capability ' + c), rows: byCap[c] };
});
}
function bootVue(Vue) {
var app = Vue.createApp({
data: function () {
return {
groups: toGroups(), activeKey: '', navOpen: true, embedOpen: false,
ttl: 'Choose a map', sub: '', openHref: '', hasSel: false, embedIframe: '', embedScript: ''
};
},
computed: {
countLabel: function () {
var nb = REG.length, np = 0, ni = 0;
REG.forEach(function (b) { np += (b.p || []).length; (b.p || []).forEach(function (p) { ni += (p.in || []).length }) });
return nb + ' bundles · ' + np + ' profiles · ' + ni + ' instances';
}
},
methods: {
go: function (key) { location.hash = '#/' + key.split('/').map(encodeURIComponent).join('/') },
copyText: copyText,
rebuild: function (m) { if (m) { try { REG = compact(m, false, TIER_MAP) } catch (e) { REG = BAKED } } this.groups = toGroups(); this.route(); },
route: function () { var h = (location.hash || '').replace(/^#\/?/, ''); if (h) this.select(h); },
select: function (key) {
var parts = key.split('/').map(function (s) { try { return decodeURIComponent(s) } catch (e) { return s } });
var hit = find(parts); this.activeKey = parts.join('/');
if (!hit) { this.ttl = 'No such map'; this.sub = key; this.openHref = ''; this.hasSel = false; this.embedOpen = false; hint('No such map: ' + key, true); return; }
var b = hit.b, p = hit.p, x = hit.x, tag = (x && x.e) || p.e || b.e[0] || b.b;
this.ttl = x ? x.t : p.p; this.sub = b.b + ' · <' + tag + '>' + (p.d ? ' · ' + p.d : '');
this.openHref = rel((x || p).u); this.hasSel = true; this.embedOpen = false;
var em = x ? (x.em || snip(b, p, x)) : (p.em || snip(b, p, null));
this.embedIframe = em.iframe || ''; this.embedScript = em.script || '';
if (narrow()) this.navOpen = false;
mount(b, p, x, tag);
}
},
mounted: function () {
var self = this;
window.__spa = { slot: this.$refs.slot, app: this };
window.addEventListener('hashchange', function () { self.route() });
try { window.matchMedia('(max-width:700px)').addEventListener('change', function (e) { if (!e.matches) self.navOpen = true }) } catch (e) {}
// Live manifest first (the page stays right when bundles change); baked copy is the fallback.
if (typeof fetch === 'function' && location.protocol !== 'file:') {
fetch(TREE_URL + '/manifest.json', { cache: 'no-cache' }).then(function (r) { return r.ok ? r.json() : null })
.then(function (m) { self.rebuild(m) }, function () { self.route() });
} else { self.route(); }
}
});
app.config.compilerOptions.isCustomElement = function () { return true }; // map tags are custom elements
app.mount('#app');
}
// Vue drives the shell (the nested-mfe-spa). Self-hosted first (portable / offline / no-CDN),
// then a CDN fallback; if neither loads, degrade to a plain rendered list so the page never
// blanks. once() resolves the tree-relative ASSETS path the same way every leaf page does.
function loadVue() {
if (window.Vue) return Promise.resolve(window.Vue);
var local = ASSETS + '/vendor/vue/vue.global.prod.js';
var cdn = 'https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js';
return once(local, 'js').then(function () { return window.Vue }, function () {
return once(cdn, 'js').then(function () { return window.Vue });
});
}
loadVue().then(function (Vue) {
if (Vue) bootVue(Vue);
else fallbackRender();
}).catch(function () { fallbackRender(); });
// No-Vue degrade: render the same capability-sorted list with plain DOM so a map is still
// reachable (parse-safe, dependency-free). Rare — Vue is vendored in the tree.
function fallbackRender() {
var host = $('app'); if (!host) return;
function paint() {
var nav = host.querySelector('#nav'); if (!nav) return;
nav.innerHTML = '';
toGroups().forEach(function (g) {
var h = document.createElement('div'); h.className = 'tier'; h.textContent = 'CAP ' + g.cap + ' · ' + g.label; nav.appendChild(h);
g.rows.forEach(function (r) {
var btn = document.createElement('button'); btn.type = 'button'; btn.className = 'row' + (r.kind === 'instance' ? ' in' : '');
btn.textContent = r.label; btn.onclick = function () { location.hash = '#/' + r.key.split('/').map(encodeURIComponent).join('/') };
nav.appendChild(btn);
});
});
}
function route() {
var h = (location.hash || '').replace(/^#\/?/, ''); if (!h) return;
var parts = h.split('/').map(function (s) { try { return decodeURIComponent(s) } catch (e) { return s } });
var hit = find(parts); if (hit) mount(hit.b, hit.p, hit.x, (hit.x && hit.x.e) || hit.p.e || hit.b.e[0] || hit.b.b); else hint('No such map: ' + h, true);
}
window.__spa = { slot: $('slot') };
if (typeof fetch === 'function' && location.protocol !== 'file:') {
fetch(TREE_URL + '/manifest.json', { cache: 'no-cache' }).then(function (r) { return r.ok ? r.json() : null })
.then(function (m) { if (m) { try { REG = compact(m, false, TIER_MAP) } catch (e) { REG = BAKED } } paint(); route(); }, function () { paint(); route(); });
} else { paint(); route(); }
window.addEventListener('hashchange', route);
}
})();
</script>
${dev ? LADDER_JS : ""}</body>
</html>
`;
}
function main() {
const CFG = readBuildConfig();
const manifestPath = join(ROOT2, "public", CFG.name, "manifest.json");
if (!existsSync2(manifestPath)) {
console.error(`[generate-gallery] missing ${manifestPath} \u2014 run \`bun run tree\` first`);
process.exit(1);
}
const manifest = JSON.parse(readFileSync3(manifestPath, "utf8"));
const tierMap = readSourceTiers();
const html = renderGallery(manifest, { mode: "build", title: CFG.title, tree: "../" + CFG.name, tokenUrl: CFG.tokenUrl, token: CFG.token, apiBaseUrl: CFG.apiBaseUrl, assetsBaseUrl: CFG.assetsBaseUrl, qaWidget: CFG.qaWidget, tierMap });
const baked = compact(manifest, true, tierMap);
const nProfiles = baked.reduce((n, b) => n + b.p.length, 0);
const nInstances = baked.reduce((n, b) => n + b.p.reduce((k, p) => k + (p.in ? p.in.length : 0), 0), 0);
const nOverrides = baked.reduce((n, b) => n + b.p.reduce((k, p) => k + (p.em ? 1 : 0) + (p.in || []).filter((x) => x.em).length, 0), 0);
const oi = process.argv.indexOf("--out");
const outDir = oi >= 0 && process.argv[oi + 1] ? resolve3(process.argv[oi + 1]) : null;
if (!outDir) {
console.log("[generate-gallery] ARCHIVED \u2014 not written. The gallery is no longer part of the build or of public/;");
console.log(" the Plugin Studio (<tree>/index.html) is the front page. To render it anyway: bun run gallery -- --out <dir>");
return;
}
if (outDir === resolve3(ROOT2, "public") || outDir.startsWith(resolve3(ROOT2, "public") + "/")) {
console.error("[generate-gallery] refusing to write into public/ \u2014 it holds only the output folder.");
process.exit(1);
}
const dir = outDir;
mkdirSync(dir, { recursive: true });
writeFileSync(join(dir, "index.html"), html);
console.log(`[generate-gallery] ${dir}/index.html (ARCHIVED rendering) \u2014 ${(html.length / 1024).toFixed(1)} KB \xB7 ${baked.length} bundle(s) \xB7 ${nProfiles} profile(s) \xB7 ${nInstances} instance(s) \xB7 ${nOverrides} embed snippet(s) baked verbatim (the rest re-derive)`);
}
if (process.argv[1] && __vite_injected_original_import_meta_url3 === pathToFileURL(process.argv[1]).href) main();
// internal/profile-meta.mjs
import { readFileSync as readFileSync4 } from "node:fs";
import { join as join2 } from "node:path";
var CORNERS = ["bottom-right", "bottom-left", "top-right", "top-left"];
var VISIBILITY = ["team", "public"];
var MOBILE = ["desktop-only", "larger-screens"];
function readProfileMeta(dir, profileName) {
try {
const meta = JSON.parse(readFileSync4(join2(dir, `${profileName}.meta.json`), "utf8"));
const corner = meta?.widget?.corner;
const name = [meta?.label, meta?.title, meta?.displayName].find((v) => typeof v === "string" && v.trim());
return {
stage: meta?.stage === "production" ? "production" : "experimental",
heavy: meta?.heavy === true,
widget: CORNERS.includes(corner) ? { corner } : null,
label: name ? name.trim() : "",
// Where the plugin runs ("web", "desktop"…); absent = web. A desktop-only plugin is never a gallery tab.
targets: Array.isArray(meta?.targets) ? meta.targets.filter((t) => typeof t === "string") : null,
visibility: VISIBILITY.includes(meta?.visibility) ? meta.visibility : "team",
// The declared-but-unrecognised value, kept so the generator can name it in the failure.
// null when the key is absent (the supported way to say "team") or already valid.
visibilityInvalid: meta?.visibility === void 0 || VISIBILITY.includes(meta?.visibility) ? null : String(meta.visibility),
mobile: MOBILE.includes(meta?.mobile) ? meta.mobile : null
};
} catch {
return { stage: "experimental", heavy: false, widget: null, label: "", targets: null, visibility: "team", visibilityInvalid: null, mobile: null };
}
}
function profileMetaFields(dir, profileName) {
const m = readProfileMeta(dir, profileName);
return { stage: m.stage, ...m.visibility === "public" ? { visibility: "public" } : {}, ...m.label ? { label: m.label } : {}, ...m.targets ? { targets: m.targets } : {}, ...m.heavy ? { heavy: true } : {}, ...m.widget ? { widget: m.widget } : {}, ...m.mobile ? { mobile: m.mobile } : {} };
}
var bundleStage = (profiles) => profiles.some((p) => p.stage === "production") ? "production" : "experimental";
var bundleVisibility = (profiles) => profiles.some((p) => p.visibility === "public") ? "public" : "team";
// internal/plugin-gallery/dev-plugin.mjs
var DEV_ASSET_MIME = {
".json": "application/json; charset=utf-8",
".geojson": "application/geo+json; charset=utf-8",
".js": "text/javascript; charset=utf-8",
".css": "text/css; charset=utf-8",
".csv": "text/csv; charset=utf-8",
".txt": "text/plain; charset=utf-8",
".html": "text/html; charset=utf-8",
".svg": "image/svg+xml",
".png": "image/png",
".webp": "image/webp",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".gif": "image/gif",
".woff2": "font/woff2",
".woff": "font/woff",
".pdf": "application/pdf"
};
function resolveDevAsset(rel, root = REPO_ROOT) {
const isFile = (p) => existsSync3(p) && statSync2(p).isFile();
const source = resolve4(root, "data", rel);
if (isFile(source)) return source;
const shipped = resolve4(root, "public", TREE_NAME, "assets", rel);
if (isFile(shipped)) return shipped;
const profiles = resolve4(root, "plugin-designs");
for (const name of readdirSync3(profiles)) {
if (name.startsWith("_") || name.startsWith(".")) continue;
const cand = resolve4(profiles, name, "data", rel);
if (isFile(cand)) return cand;
}
return null;
}
function readComposes(bundle, profile) {
try {
const meta = JSON.parse(readFileSync5(resolve4(REPO_ROOT, "plugin-designs", bundle, `${profile}.meta.json`), "utf8"));
return Array.isArray(meta?.composes) ? meta.composes.map(String).filter(Boolean) : [];
} catch {
return [];
}
}
function galleryModel(reg) {
const iframe = (u) => `<iframe src="${u}?utm_source=YOUR_SOURCE" width="100%" height="600" style="border:none;border-radius:12px;" allowfullscreen></iframe>`;
const link = (...parts) => "/__leaf/" + parts.map(encodeURIComponent).join("/");
let gated = /* @__PURE__ */ new Set();
try {
const cfg = JSON.parse(readFileSync5(resolve4(REPO_ROOT, "vite.doxa-maps-build-config.json"), "utf8"));
if (Array.isArray(cfg.gatedProfiles)) gated = new Set(cfg.gatedProfiles.map(String));
} catch {
}
const bundles = [...reg].filter((b) => !gated.has(b.bundle)).sort((a, b) => a.bundle.localeCompare(b.bundle)).map((b) => {
const scriptUrl = `/plugin-designs/${b.bundle}/index.js`;
const presets = /* @__PURE__ */ new Map();
const typeOf = /* @__PURE__ */ new Map();
for (const it of b.items) {
if (!presets.has(it.profile)) presets.set(it.profile, []);
if (!typeOf.has(it.profile)) typeOf.set(it.profile, it.type);
if (it.type === "parameterized") presets.get(it.profile).push(it);
}
const profiles = [...presets.keys()].sort().map((profile) => {
const p = {
profile,
file: `${profile}.vue`,
description: "",
element: b.tag,
type: typeOf.get(profile) || "single",
...profileMetaFields(resolve4(REPO_ROOT, "plugin-designs", b.bundle), profile),
// same as the built manifest
iframeUrl: link(b.bundle, profile),
scriptUrl,
embed: {
iframe: iframe(`./${b.bundle}/${profile}/index.html`),
script: `<script src="./${b.bundle}/${b.bundle}.js"></script>
<${b.tag} profile-config='${JSON.stringify({ profile, tk: "YOUR_MAPBOX_TOKEN", utmSource: "YOUR_SOURCE" })}'></${b.tag}>`
}
};
const instances = presets.get(profile).map((it) => ({
id: it.id,
title: it.label,
apiBaseUrl: it.apiBaseUrl || "",
props: { profile, ...it.props || {} },
element: b.tag,
iframeUrl: link(b.bundle, profile, it.id),
embed: { iframe: iframe(`./${b.bundle}/${profile}/${it.id}/index.html`) }
}));
if (instances.length) p.instances = instances;
return p;
});
const composes = [...new Set([...presets.keys()].flatMap((profile) => readComposes(b.bundle, profile)))];
return { bundle: b.bundle, scriptUrl, integrity: "", elements: [b.tag], stage: bundleStage(profiles), ...bundleVisibility(profiles) === "public" ? { visibility: "public" } : {}, ...composes.length ? { composes } : {}, profiles };
});
return {
schema: "doxa-maps-manifest@1",
generatedFrom: "plugin-designs/*/*.vue (dev discovery)",
embedBase: ".",
bundleCount: bundles.length,
profileCount: bundles.reduce((n, b) => n + b.profiles.length, 0),
bundles
};
}
function leafRewrite(path, treeName = TREE_NAME) {
if (!path.endsWith("/index.html")) return "";
let segs = path.slice(0, -"/index.html".length).split("/").filter(Boolean);
if (segs[0] === treeName) segs = segs.slice(1);
if (segs.length < 2 || segs.length > 3) return "";
for (const s of segs) {
let d = s;
try {
d = decodeURIComponent(s);
} catch {
return "";
}
if (!d || d === "." || d === ".." || d.includes("/") || d.includes("\\")) return "";
}
return "/__leaf/" + segs.join("/");
}
function autoSpaDevPlugin(token = "") {
const page = () => {
const cfg = readBuildConfig();
return renderGallery(galleryModel(discoverSpaRegistry()), {
// ★ `/__plugin-gallery`, ABSOLUTE — the SAME move, and the same fix, as assetsBaseUrl below.
// `tree` is the folder the live manifest is fetched from and that relative refs resolve
// against. It was '__plugin-gallery' (relative), correct only while the gallery WAS the root
// page. The gallery now lives at /__gallery, so the relative form resolves one level deeper.
// MEASURED 2026-09-22 on the running dev server:
// /__plugin-gallery/manifest.json ............. 200
// /__gallery/__plugin-gallery/manifest.json ... 404
// Naming it absolutely makes the value independent of the page depth the gallery sits at —
// which is the whole reason assetsBaseUrl was made absolute in the same move. The built tree
// passes '../<name>' for the same reason; both now resolve to the real tree root.
mode: "dev",
title: cfg.title,
tree: "/__plugin-gallery",
tokenUrl: cfg.tokenUrl,
token: token || cfg.token,
// ★ ABSOLUTE, NOT RELATIVE — the gallery no longer lives at the root.
// This was '' (relative), which was correct while the gallery WAS the root page: a map asked
// for assets/tables/x.json and got /assets/tables/x.json. The gallery has since moved to
// /__gallery so the studio can own /, and the same relative path now resolves one level deeper
// to /__gallery/assets/... — which 404s. MEASURED 2026-09-22 on the running dev server:
// /assets/tables/internet-by-country.json ............. 200
// /__gallery/assets/tables/internet-by-country.json ... 404
// Nothing failed at move time; the breakage only appears when a map FETCHES, and it surfaces as
// "JSON.parse: unexpected end of data" rather than as a 404, because Vite answers an unknown
// path with HTML. The dev server serves the asset tree at /assets/ (see resolveDevAsset), so
// naming it absolutely makes the value independent of whatever page depth the gallery sits at.
apiBaseUrl: cfg.apiBaseUrl,
assetsBaseUrl: "/assets",
qaWidget: cfg.qaWidget
});
};
const json = (res, body, status = 200) => {
res.statusCode = status;
res.setHeader("Content-Type", "application/json; charset=utf-8");
res.setHeader("Cache-Control", "no-cache");
res.end(JSON.stringify(body));
};
return {
name: "doxa-auto-spa",
apply: "serve",
configureServer(server) {
server.middlewares.use((req, res, next) => {
const rawPath = (req.url || "").split("?")[0];
let _decoded = rawPath;
try {
_decoded = decodeURIComponent(rawPath);
} catch {
}
if (/(^|\/)\.(git|env)(\/|$)|(^|\/)\.(merge-queue|main-capture)(\/|$)/i.test(_decoded)) {
res.statusCode = 404;
return res.end();
}
let treeName = TREE_NAME;
try {
treeName = readBuildConfig()?.name || treeName;
} catch {
}
const rewritten = leafRewrite(rawPath, treeName);
const path = rewritten || rawPath;
if (rewritten) req.url = rewritten + (req.url || "").slice(rawPath.length);
const iife = /^\/(?:([^/]+)\/)?([a-z0-9][a-z0-9-]*)\/([a-z0-9][a-z0-9-]*)\.js$/.exec(rawPath);
if (iife && iife[2] === iife[3] && (!iife[1] || iife[1] === treeName)) {
const file = resolve4(REPO_ROOT, "public", treeName, iife[2], iife[2] + ".js");
if (existsSync3(file)) {
res.setHeader("Content-Type", "text/javascript; charset=utf-8");
res.setHeader("Cache-Control", "no-cache");
return res.end(readFileSync5(file));
}
if (existsSync3(resolve4(REPO_ROOT, "plugin-designs", iife[2]))) {
res.statusCode = 404;
res.setHeader("Content-Type", "text/plain; charset=utf-8");
return res.end(`${iife[2]}.js is only produced by a build: run \`bun run build\` (or BUNDLE=${iife[2]} bun x vite build), then reload.`);
}
}
const leafAsset = /^\/__leaf\/(?:[^/]+\/){0,3}assets\//.exec(path);
const assetPrefix = path.startsWith("/assets/") ? "/assets/" : path.startsWith("/__plugin-gallery/assets/") ? "/__plugin-gallery/assets/" : path.startsWith(`/${treeName}/assets/`) ? `/${treeName}/assets/` : leafAsset ? leafAsset[0] : "";
if (assetPrefix) {
let rel = "";
try {
rel = decodeURIComponent(path.slice(assetPrefix.length));
} catch {
rel = "";
}
if (!rel || rel.split("/").includes("..")) {
res.statusCode = 400;
return res.end("bad asset path");
}
const file = resolveDevAsset(rel);
if (!file) return json(res, { error: "asset not found", asset: rel, looked: [`public/${TREE_NAME}/assets/`, "data/", "plugin-designs/*/data/"] }, 404);
res.statusCode = 200;
res.setHeader("Content-Type", DEV_ASSET_MIME[extname(file).toLowerCase()] || "application/octet-stream");
res.setHeader("Cache-Control", "no-cache");
return res.end(readFileSync5(file));
}
if (path === "/__dev-sha") {
const git2 = (...a) => spawnSync("git", a, { cwd: REPO_ROOT, encoding: "utf8" }).stdout.trim();
const sha = git2("rev-parse", "HEAD");
const dirty = git2("status", "--porcelain", "--untracked-files=no", "--", "library", "plugin-designs", "internal", "vite.config.js", "package.json") ? "+dirty" : "";
res.statusCode = sha ? 200 : 500;
res.setHeader("Content-Type", "text/plain; charset=utf-8");
res.setHeader("Cache-Control", "no-store");
return res.end((sha || "unknown") + dirty + "\n");
}
if (path === "/__plugin-gallery/registry.json" || path === "/__plugin-gallery/manifest.json") {
let reg;
try {
reg = discoverSpaRegistry();
} catch (e) {
return json(res, { error: String(e) }, 500);
}
return json(res, path.endsWith("/manifest.json") ? galleryModel(reg) : reg);
}
if (path.startsWith("/__leaf/")) {
const parts = path.slice("/__leaf/".length).split("/").filter(Boolean).map((s) => {
try {
return decodeURIComponent(s);
} catch {
return "";
}
});
const [bundle, profile, instance] = parts;
if (!bundle || !profile || parts.some((s) => !s || s.includes("..") || s.includes("/"))) {
res.statusCode = 400;
return res.end("bad leaf path");
}
let reg;
try {
reg = discoverSpaRegistry();
} catch (e) {
return json(res, { error: String(e) }, 500);
}
const entry = reg.find((b) => b.bundle === bundle);
if (!entry) {
const named = reg.find((b) => b.bundle === profile);
const hint = named ? `this plugin's own page is /__leaf/${named.bundle}/${named.items?.[0]?.profile || named.bundle}` : "a plugin's own page is /__leaf/<plugin>/<profile>; every plugin is listed at /__plugin-gallery/manifest.json";
return json(res, { error: "unknown bundle", bundle, hint }, 404);
}
const tag = entry.tag;
let leafCfg = {};
try {
leafCfg = readBuildConfig() || {};
} catch {
leafCfg = {};
}
const leafTok = token || leafCfg.token || "";
const apiBase = leafCfg.apiBaseUrl || "";
const pc = JSON.stringify(instance ? { profile, instanceId: instance, assetsBase: "/assets" } : { profile, assetsBase: "/assets" });
const scrollPage = (entry.items || []).some(
(it) => it.profile === profile && it.type === "nested-elements-mfe"
);
res.statusCode = 200;
res.setHeader("Content-Type", "text/html; charset=utf-8");
res.setHeader("Cache-Control", "no-cache");
return res.end([
"<!DOCTYPE html>",
`<html lang="en"><head><meta charset="UTF-8" /><title>${bundle} \xB7 ${profile}</title>`,
'<meta name="viewport" content="width=device-width, initial-scale=1.0" />',
'<link rel="icon" href="data:,">',
leafTok ? `<script>window.MAP_TOKEN=${JSON.stringify(leafTok)};</script>` : "",
// ★ MAP_APP_API_URL IS NOT OPTIONAL — without it every dashboard renders EMPTY in dev.
// The BUILT leaves bake `window.MAP_APP_API_URL = "https://pray.doxa.life"`; these dev
// pages baked only the Mapbox token, so the dashboards fell back to a RELATIVE
// `/api/people-groups/list?...`. Vite answers an unknown path with SPA-fallback HTML at
// HTTP 200, so the fetch "succeeds", JSON.parse fails or yields nothing, and the facet
// rail renders ZERO rows with no console error and no error card. Measured 2026-09-22:
// 8 such 404/fallback requests during one studio sweep. That reads as a broken component
// and is really a missing global — the worst kind of dev-only divergence, and exactly the
// four-surface class (see REFERENCE-the-four-surface-contract.md).
apiBase ? `<script>window.MAP_APP_API_URL=${JSON.stringify(apiBase)};</script>` : "",
// ── FIXED-VIEWPORT LEAF vs SCROLL-PAGE LEAF ────────────────────────────────────────
// The BUILT tree makes exactly this distinction (internal/generate-tree.mjs, `scrollPage`)
// and this dev leaf did NOT — it served the fixed-viewport style to EVERY bundle. That is
// the whole of BUG-CANNOT-SCROLL-DOWN-TO-THE-GRID-UNDER-THE-DASHBOARD: the three-file fix
// for BUG-DASHBOARD-CANT-SCROLL-DOWN landed in the built tree only, so the dev URL that
// actually gets tested was never covered and still traps the composite.
//
// WHY `height:100%` ON BODY IS THE TRAP, and why scrollHeight LIES about it. A definite
// height + `overflow:visible` lets content SPILL (so scrollHeight inflates — measured 3531
// against a 900 viewport) WITHOUT creating a scrollport, so the viewport has nothing to
// scroll. The research-dashboard's own inner `overflow:auto` regions then swallow every
// wheel event. MEASURED 2026-09-22 on this leaf: 12 wheel events of 600px moved the page
// 0px while 2,631px of content sat below the fold. A geometry check calls that "scrollable";
// only a real wheel exposes it.
//
// A cap-4 composite (nested-elements-mfe) is a StackLayout scroll-stack, so the DOCUMENT
// must own the scroll: `min-height` (a floor, not a cage) + explicit `overflow-y:auto`,
// and the element takes its NATURAL height so the page grows and the grid below is
// reachable. Every other tier keeps the fixed-viewport leaf — a map IS the page.
scrollPage ? `<style>html{height:100%;}html,body{margin:0;padding:0;background:#f3f3f1;}body{min-height:100%;overflow-y:auto;}${tag}{display:block;width:100%;min-height:100dvh;}</style>` : `<style>html,body{margin:0;padding:0;height:100%;background:#f3f3f1;}${tag}{display:block;width:100%;height:100vh;}</style>`,
"</head><body>",
// tree-base ON THE LEAF TOO — cap-5 shells nested here fetch a manifest of their own.
// doxa-maps-spa (like plugin-studio) discovers its tabs from the tree's manifest.json and
// resolves it RELATIVE to its own page when no base is given. On a /__leaf/ URL that
// resolved to /__leaf/manifest.json and 400'd. Harmless (both shells carry a baked
// fallback list) but it silently degrades the tab list to the fallback instead of the
// live 19-bundle tree. Passing the base makes a nested shell see exactly what the top
// level sees. Elements that ignore tree-base simply drop an unknown attribute.
`<${tag} tree-base="/__plugin-gallery" profile-config='${pc}'></${tag}>`,
`<script type="module" src="/plugin-designs/${bundle}/index.js"></script>`,
"</body></html>"
].filter(Boolean).join("\n"));
}
if (path === "/" || path === "/index.html") {
let devCfg = {};
try {
devCfg = readBuildConfig() || {};
} catch {
devCfg = {};
}
const devTok = token || devCfg.token || "";
const devApiBase = devCfg.apiBaseUrl || "";
res.statusCode = 200;
res.setHeader("Content-Type", "text/html; charset=utf-8");
res.setHeader("Cache-Control", "no-cache");
return res.end([
"<!DOCTYPE html>",
'<html lang="en"><head><meta charset="UTF-8" />',
'<meta name="viewport" content="width=device-width, initial-scale=1.0" />',
`<title>${TREE_NAME} plugin studio</title>`,
'<link rel="icon" href="data:,">',
// The token ladder's baked rung, exactly as the built leaves receive it, so maps paint
// in dev without anyone appending ?tk=.
devTok ? `<script>window.MAP_TOKEN=${JSON.stringify(devTok)};</script>` : "",
// Same reason as the leaf route above: without MAP_APP_API_URL the dashboards nested in
// the studio fetch a relative /api/... that Vite answers with HTML at 200, so they mount
// and then show nothing. The value comes from the SAME build config the built leaves use,
// so dev and built agree by construction rather than by a second hard-coded copy.
devApiBase ? `<script>window.MAP_APP_API_URL=${JSON.stringify(devApiBase)};</script>` : "",
// No chrome, no prose: the element fills the viewport. "Without a lot of text garb
// that takes up so much space" is a layout requirement, so the host page contributes
// ZERO text — every pixel belongs to the studio element.
"<style>html,body{margin:0;padding:0;height:100%;background:#f3f3f1;}",
"plugin-studio{display:block;width:100%;height:100vh;}</style>",
"</head><body>",
// tree-base IS REQUIRED IN DEV — without it the studio mounts EMPTY.
// The studio builds its tab list at runtime by fetching `<base>manifest.json`, and with
// no base it falls back to '../manifest.json' RELATIVE TO ITS SCRIPT URL. In dev the
// script is /plugin-designs/plugin-studio/index.js, so that resolves to
// /plugin-designs/manifest.json — which does not exist. The shell then renders with zero
// rows: 31 shadow descendants, no nested plugin tags. (Measured exactly that before this
// line existed; the symptom reads as "no elements in the studio", not as a failed fetch.)
// The dev server's manifest lives on its own route instead, serving the SAME
// manifest-shaped model the built tree bakes (19 bundles / 30 profiles), so pointing the
// studio at it gives dev the same tab list production has.
'<plugin-studio tree-base="/__plugin-gallery"></plugin-studio>',
'<script type="module" src="/plugin-designs/plugin-studio/index.js"></script>',
"</body></html>"
].filter(Boolean).join("\n"));
}
if (path !== "/__gallery" && path !== "/__gallery/") return next();
let html;
try {
html = page();
} catch (e) {
console.error(`[plugin-gallery] ${e && e.stack ? e.stack : e}`);
return next();
}
res.statusCode = 200;
res.setHeader("Content-Type", "text/html; charset=utf-8");
res.end(html);
});
}
};
}
// internal/vite-plugin-strip-shadow-css-comments.mjs
import { resolve as resolve5, dirname as dirname4, sep } from "node:path";
import { fileURLToPath as fileURLToPath4 } from "node:url";
var __vite_injected_original_import_meta_url4 = "file:///home/lk10x/Workspace/eco-dx/root-doxa-maps/wt-hf/internal/vite-plugin-strip-shadow-css-comments.mjs";
var ROOT3 = resolve5(dirname4(fileURLToPath4(__vite_injected_original_import_meta_url4)), "..");
var SOURCE_ROOTS = ["library", "plugin-designs"].map((d) => resolve5(ROOT3, d) + sep);
var TAG = "[strip-shadow-css-comments]";
var CALL = /\buseShadowStyles\(\s*(?:[A-Za-z_$][\w$]*\s*\+\s*)*`|\b(?:export\s+)?const\s+[A-Z][A-Z0-9_]*(?:_CSS|_STYLES)\s*=\s*`/g;
function findTemplateEnd(code, from) {
for (let i = from; i < code.length; i++) {
const c = code[i];
if (c === "\\") {
i++;
continue;
}
if (c === "`") return { end: i };
if (c === "$" && code[i + 1] === "{") return { reason: "contains a ${\u2026} substitution", at: i };
}
return { reason: "template literal never closes", at: code.length };
}
function stripCssComments(css) {
const n = css.length;
let out = "";
let comments = 0;
let i = 0;
while (i < n) {
const c = css[i];
if (c === '"' || c === "'") {
let j = i + 1;
while (j < n && css[j] !== c && css[j] !== "\n") {
if (css[j] === "\\") j++;
j++;
}
if (j >= n) return { reason: "a CSS string never closes" };
if (css[j] === "\n") {
out += css.slice(i, j);
i = j;
continue;
}
out += css.slice(i, j + 1);
i = j + 1;
continue;
}
if (c === "/" && css[i + 1] === "*") {
const j = css.indexOf("*/", i + 2);
if (j < 0) return { reason: "a CSS comment never closes" };
comments++;
i = j + 2;
continue;
}
if ((c === "u" || c === "U") && /^url\(/i.test(css.slice(i, i + 4)) && (i === 0 || !/[\w-]/.test(css[i - 1]))) {
let j = i + 4;
while (j < n && (css[j] === " " || css[j] === " ")) j++;
if (css[j] === '"' || css[j] === "'") {
out += css.slice(i, j);
i = j;
continue;
}
const k = css.indexOf(")", j);
if (k < 0) return { reason: "an unquoted url() never closes" };
out += css.slice(i, k + 1);
i = k + 1;
continue;
}
out += c;
i++;
}
if (comments > 0) {
out = out.replace(/[ \t]+(?=\r?\n|$)/g, "");
out = out.replace(/\r?\n(?:[ \t]*\r?\n)+/g, "\n");
}
return { css: out, comments };
}
function stripShadowStyleComments(code) {
const result = { code, changed: false, literals: 0, comments: 0, bytes: 0, skipped: [] };
let out = "";
let last = 0;
CALL.lastIndex = 0;
let m;
while (m = CALL.exec(code)) {
const open = m.index + m[0].length;
const lit = findTemplateEnd(code, open);
if (lit.reason) {
result.skipped.push({ line: lineOf(code, m.index), reason: lit.reason });
CALL.lastIndex = lit.at;
continue;
}
result.literals++;
const original = code.slice(open, lit.end);
const stripped = stripCssComments(original);
if (stripped.reason) {
result.skipped.push({ line: lineOf(code, m.index), reason: stripped.reason });
} else if (stripped.css !== original) {
out += code.slice(last, open) + stripped.css;
last = lit.end;
result.comments += stripped.comments;
result.bytes += original.length - stripped.css.length;
result.changed = true;
}
CALL.lastIndex = lit.end + 1;
}
if (result.changed) result.code = out + code.slice(last);
return result;
}
function lineOf(code, index) {
let line = 1;
for (let i = 0; i < index; i++) if (code[i] === "\n") line++;
return line;
}
function isSourceModule(id) {
const q = id.indexOf("?");
if (q >= 0) return false;
if (!(id.endsWith(".vue") || id.endsWith(".js"))) return false;
return SOURCE_ROOTS.some((root) => id.startsWith(root));
}
function stripShadowCssCommentsPlugin() {
let logger = console;
const totals = { files: 0, literals: 0, comments: 0, bytes: 0, skipped: 0 };
return {
name: "doxa:strip-shadow-css-comments",
apply: "build",
enforce: "pre",
configResolved(config) {
logger = config.logger;
},
transform(code, id) {
if (!isSourceModule(id)) return null;
const r = stripShadowStyleComments(code);
for (const s of r.skipped) {
totals.skipped++;
logger.warn(`${TAG} left untouched ${id.slice(ROOT3.length + 1)}:${s.line} \u2014 ${s.reason}`);
}
if (!r.changed) return null;
totals.files++;
totals.literals += r.literals;
totals.comments += r.comments;
totals.bytes += r.bytes;
return { code: r.code, map: null };
},
buildEnd() {
logger.info(`${TAG} removed ${totals.comments} CSS comments (${totals.bytes} bytes) from ${totals.literals} shadow-style literals in ${totals.files} files` + (totals.skipped ? `; ${totals.skipped} literal(s) left untouched` : ""));
}
};
}
// internal/backend-dev-plugin.mjs
import { spawn } from "node:child_process";
import { existsSync as existsSync4, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, rmSync, chmodSync, renameSync, createWriteStream } from "node:fs";
import { createHash } from "node:crypto";
import { connect } from "node:net";
import { inflateRawSync } from "node:zlib";
import { resolve as resolve6 } from "node:path";
var PB_VERSION = "0.40.4";
var PB_SHA256 = {
linux_amd64: "9042ec818570e79c3628dadcd0a756c1496d9e1173918ec409d133c02f82e5fa",
linux_arm64: "86095bf8ed9345954f0d2bf0a5fb9b57584ae60b77ebf3b6cd23a8003a3fd418",
darwin_amd64: "052906521f09f6f23405cd804c930d2b7a1f8eee06d39b85723b5054b2acb4e4",
darwin_arm64: "eeb619ea4f8a06421daedb946d133bed269fea334a760941d147f76befc25ebc"
};
function devBackends(env = process.env) {
const pbPort = Number(env.DX_PB_PORT || 8090);
return [
{
name: "rudder-engine",
bin: "backend/bin/rudder-engine",
build: "cd backend/rudder-engine && go build -o ../bin/rudder-engine .",
// What a fresh clone is told at startup when this backend is not built: it is OPTIONAL (desktop voice).
optional: "optional: Rudder (desktop voice-to-text) is not built, which is fine for the maps. It needs Go 1.22+; see documentation/HOWTO-build-the-desktop-app.md.",
route: "/api/rudder",
port: Number(process.env.RUDDER_PORT || 5193),
env: { RUDDER_PORT: String(process.env.RUDDER_PORT || 5193), RUDDER_NEMO_PORT: String(process.env.RUDDER_NEMO_PORT || 5194) },
// This server is SUPPOSED to run the engine (a server deployment with the engine switched on): while it
// is down, the plugin says "not running yet" instead of "runs on your own computer".
expected: () => process.env.RUDDER_ENGINE === "1" || process.env.RUDDER_AUDIO === "browser",
// RUDDER_ENGINE=0 (a server where Rudder is laptop-only, 2026-09-27): never start it, even if a
// binary built by an earlier engine-on deploy is still there — it would offer to record a server's mic.
disabled: () => process.env.RUDDER_ENGINE === "0"
},
{
// Hooks off (a hooks dir that never exists): only the migrations in git shape the schema, as in the cloud.
// DX_PB_URL points this laptop at a shared PocketBase instead (e.g. the cloud pb-dev); none starts here.
name: "pocketbase",
bin: "backend/bin/pocketbase",
args: ["serve", "--http", `127.0.0.1:${pbPort}`, "--dir", ".pb/dev", "--migrationsDir", "backend/pocketbase/pb_migrations", "--hooksDir", ".pb/hooks-off"],
build: "it downloads on the next `bun run dev` (or set DX_PB_URL)",
fetch: fetchPocketBase,
portEnv: "DX_PB_PORT",
route: "/api/pb",
rewrite: (p) => p.replace(/^\/api\/pb/, "") || "/",
port: pbPort,
remote: env.DX_PB_URL || "",
offline: (res) => {
res.writeHead(503, { "Content-Type": "application/json" });
res.end(JSON.stringify({ status: 503, message: "PocketBase is not running on this computer (yet). See the dev server log." }));
}
}
];
}
async function fetchPocketBase(root, logger) {
const plat = { "linux-x64": "linux_amd64", "linux-arm64": "linux_arm64", "darwin-x64": "darwin_amd64", "darwin-arm64": "darwin_arm64" }[`${process.platform}-${process.arch}`];
if (!plat) {
logger.warn(`[pocketbase] no pinned build for ${process.platform}-${process.arch}: put PocketBase ${PB_VERSION} at backend/bin/pocketbase, or set DX_PB_URL`);
return false;
}
const name = `pocketbase_${PB_VERSION}_${plat}.zip`;
const dir = resolve6(root, "backend/bin");
const part = resolve6(dir, `.pocketbase.part`);
logger.info(`[pocketbase] downloading ${name} (first run only)`);
try {
mkdirSync2(dir, { recursive: true });
const r = await fetch(`https://github.com/pocketbase/pocketbase/releases/download/v${PB_VERSION}/${name}`);
if (!r.ok) throw new Error(`HTTP ${r.status}`);
const buf = Buffer.from(await r.arrayBuffer());
const sha = createHash("sha256").update(buf).digest("hex");
if (sha !== PB_SHA256[plat]) throw new Error(`checksum mismatch (${sha}): refusing to use it`);
writeFileSync2(part, unzipOne(buf, "pocketbase"));
chmodSync(part, 493);
renameSync(part, resolve6(dir, "pocketbase"));
return true;
} catch (e) {
logger.warn(`[pocketbase] download failed (${e.message}); /api/pb answers 503 until the next \`bun run dev\``);
return false;
} finally {
rmSync(part, { force: true });
}
}
function unzipOne(buf, want) {
const end = buf.lastIndexOf(Buffer.from([80, 75, 5, 6]));
if (end < 0) throw new Error("not a zip");
for (let i = 0, p = buf.readUInt32LE(end + 16); i < buf.readUInt16LE(end + 10); i++) {
const method = buf.readUInt16LE(p + 10), size = buf.readUInt32LE(p + 20);
const nameLen = buf.readUInt16LE(p + 28), local = buf.readUInt32LE(p + 42);
if (buf.toString("utf8", p + 46, p + 46 + nameLen) === want) {
const start2 = local + 30 + buf.readUInt16LE(local + 26) + buf.readUInt16LE(local + 28);
const data = buf.subarray(start2, start2 + size);
if (method === 8) return inflateRawSync(data);
if (method === 0) return data;
throw new Error(`unsupported zip method ${method}`);
}
p += 46 + nameLen + buf.readUInt16LE(p + 30) + buf.readUInt16LE(p + 32);
}
throw new Error(`${want} not in the zip`);
}
var portInUse = (port) => new Promise((ok) => {
const s = connect({ host: "127.0.0.1", port }, () => {
s.destroy();
ok(true);
});
s.on("error", () => ok(false));
});
function devBackendProxy(env = process.env) {
return Object.fromEntries(devBackends(env).map((b) => [b.route, {
target: b.remote || `http://127.0.0.1:${b.port}`,
changeOrigin: !!b.remote,
ws: true,
...b.rewrite ? { rewrite: b.rewrite } : {}
}]));
}
var REG = globalThis.__dxDevBackends ||= { procs: /* @__PURE__ */ new Map(), exitHooked: false, stopping: false };
var isAlive = (name) => {
const e = REG.procs.get(name);
return !!e && e.child.exitCode === null && e.child.signalCode === null;
};
function stopAll() {
REG.stopping = true;
for (const { child } of REG.procs.values()) {
try {
child.kill("SIGTERM");
} catch {
}
}
}
function start(root, b, logger, restarts = 0) {
const tag = `[${b.name}]`;
const child = spawn(resolve6(root, b.bin), b.args || [], { cwd: root, env: { ...process.env, ...b.env }, stdio: ["ignore", "pipe", "pipe"] });
const entry = { child, restarts, logger };
REG.procs.set(b.name, entry);
const logDir = resolve6(root, ".pb", "logs");
mkdirSync2(logDir, { recursive: true });
const sink = createWriteStream(resolve6(logDir, `${b.name}.log`), { flags: "a" });
const LOUD = /\b(error|fail(ed|ure)?|panic|fatal|warn(ing)?|refused|denied|in use|cannot|unable|superuser|pbinstall?)\b/i;
const out = (d) => {
sink.write(d);
String(d).trim().split("\n").forEach((l) => l && LOUD.test(l) && entry.logger.info(`${tag} ${l}`));
};
child.stdout.on("data", out);
child.stderr.on("data", out);
child.on("exit", () => sink.end());
child.on("exit", (code) => {
if (REG.procs.get(b.name) !== entry) return;
REG.procs.delete(b.name);
if (REG.stopping) return;
entry.logger.warn(`${tag} exited (${code})`);
if (entry.restarts < 5) {
setTimeout(() => {
if (REG.stopping || REG.procs.has(b.name)) return;
entry.logger.warn(`${tag} restarting (${entry.restarts + 1}/5)`);
start(root, b, entry.logger, entry.restarts + 1);
}, 2e3);
}
});
logger.info(`${tag} started \u2192 ${b.route} on 127.0.0.1:${b.port} (full log: .pb/logs/${b.name}.log)`);
}
function backendDevPlugin(root, env = process.env) {
const backends = devBackends(env);
return {
name: "dx-backend-dev",
apply: "serve",
configureServer(server) {
for (const b of backends) {
server.middlewares.use(b.route, (req, res, next) => {
if (b.remote || isAlive(b.name)) return next();
if (b.offline) return b.offline(res);
const status = { engine: "offline", expected: !!(b.expected && b.expected()), error: "The desktop engine is not running." };
if ((req.url || "").startsWith("/events")) {
res.writeHead(200, { "Content-Type": "text/event-stream", "Cache-Control": "no-cache", Connection: "keep-alive" });
res.write(`data: ${JSON.stringify({ type: "status", status })}
`);
return;
}
if ((req.url || "").startsWith("/status")) {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify(status));
return;
}
res.writeHead(200, { "Content-Type": "application/json" });
res.end("[]");
});
}
const logger = server.config.logger;
if (!REG.exitHooked) {
REG.exitHooked = true;
process.once("exit", stopAll);
process.once("SIGINT", () => {
stopAll();
process.exit(0);
});
process.once("SIGTERM", () => {
stopAll();
process.exit(0);
});
}
for (const b of backends) {
if (b.remote) {
logger.info(`[${b.name}] not started here: ${b.route} \u2192 ${b.remote}`);
continue;
}
if (isAlive(b.name)) {
REG.procs.get(b.name).logger = logger;
logger.info(`[${b.name}] still running \u2192 ${b.route} (kept across the dev-server restart)`);
continue;
}
if (b.disabled && b.disabled()) {
logger.info(`[backend] ${b.name} switched off here (${b.name === "rudder-engine" ? "RUDDER_ENGINE=0" : "disabled"})`);
continue;
}
const launch = async () => {
if (b.portEnv && await portInUse(b.port)) {
logger.warn(`[${b.name}] port ${b.port} is already in use (another \`bun run dev\`?): not started. Set ${b.portEnv} to use another port.`);
return;
}
if (!REG.stopping && !isAlive(b.name)) start(root, b, logger);
};
if (!existsSync4(resolve6(root, b.bin))) {
if (b.fetch) {
REG.fetching ||= /* @__PURE__ */ new Set();
if (REG.fetching.has(b.name)) continue;
REG.fetching.add(b.name);
b.fetch(root, logger).then((ok) => {
REG.fetching.delete(b.name);
if (ok) launch();
});
continue;
}
if (b.optional) logger.info(`[backend] ${b.optional}`);
else logger.warn(`[backend] ${b.name} not built \u2014 its plugin will show "engine offline". Build: ${b.build}`);
continue;
}
launch();
}
}
};
}
// internal/dev-sync-plugin.mjs
import { execFile } from "node:child_process";
var git = (root, args) => new Promise((ok) => execFile(
"git",
args,
{ cwd: root, timeout: 6e4, env: { ...process.env, GIT_TERMINAL_PROMPT: "0" } },
(e, out, err) => {
const all = String(err || e?.message || "").trim();
ok({ ok: !e, out: String(out || "").trim(), err: all.split("\n")[0], errAll: all });
}
));
var AUTH_RE = /unauthori[sz]ed|authentication failed|could not read (username|password)|terminal prompts disabled|permission denied \(publickey|\b40[13]\b/i;
var shown = (remote) => remote.replace(/\/\/[^/@]*@/, "//");
var label = (remote, branch) => remote.includes("/") ? `${branch} of ${shown(remote)}` : `${remote}/${branch}`;
var REG2 = globalThis.__dxDevSync ||= { timer: null, running: false, status: { enabled: false } };
async function syncOnce(root, remote, branch, log = { info() {
}, warn() {
} }) {
if (REG2.running) return REG2.status;
REG2.running = true;
try {
const src2 = label(remote, branch);
const s = { enabled: true, remote: shown(remote), branch, checkedAt: (/* @__PURE__ */ new Date()).toISOString() };
const f = await git(root, ["fetch", "-q", remote, branch]);
if (!f.ok) {
const auth = AUTH_RE.test(f.errAll);
const state = auth ? "needs-credentials" : "fetch-failed";
const message = auth ? `dev-sync needs git credentials for ${shown(remote)} (a credential helper, or an SSH remote your key can read); git said: ${shown(f.err)}` : `could not fetch ${src2}: ${shown(f.err)}`;
if (REG2.status.state !== state || REG2.status.message !== message) log.warn(`[dev-sync] ${message}`);
return REG2.status = { ...s, state, message };
}
const up = (await git(root, ["rev-parse", "FETCH_HEAD"])).out;
const head = (await git(root, ["rev-parse", "HEAD"])).out;
const cur = (await git(root, ["symbolic-ref", "-q", "--short", "HEAD"])).out;
const behind = Number((await git(root, ["rev-list", "--count", `HEAD..${up}`])).out || 0);
const ahead = Number((await git(root, ["rev-list", "--count", `${up}..HEAD`])).out || 0);
const dirty = (await git(root, ["status", "--porcelain", "--untracked-files=no"])).out !== "";
Object.assign(s, { upstream: up, behind, ahead, dirty, currentBranch: cur || "(detached)" });
if (behind === 0) return REG2.status = { ...s, state: "up-to-date", message: `up to date with ${src2}` };
const why = cur !== branch ? `this checkout is on ${cur || "a detached HEAD"}, not ${branch}` : dirty ? "you have local edits" : ahead ? `you have ${ahead} local commit(s) that are not on ${src2}` : "";
const m = why ? null : await git(root, ["merge", "--ff-only", "-q", up]);
if (why || !m.ok) {
const message = `${branch} is ${behind} commit(s) ahead; ${why || `fast-forward refused (${m.err})`}, so nothing was merged. Pull when ready.`;
if (REG2.status.upstream !== up || REG2.status.state !== "behind") log.warn(`[dev-sync] ${message}`);
return REG2.status = { ...s, state: "behind", message };
}
log.info(`[dev-sync] fast-forwarded ${head.slice(0, 8)} \u2192 ${up.slice(0, 8)} (${behind} commit(s) from ${src2})`);
return REG2.status = { ...s, behind: 0, state: "up-to-date", lastMerge: s.checkedAt, message: `fast-forwarded ${behind} commit(s) from ${src2}` };
} finally {
REG2.running = false;
}
}
function devSyncPlugin(root, env = process.env) {
const remote = env.DX_SYNC_REMOTE || "";
const branch = env.DX_SYNC_BRANCH || "development";
const every = Math.max(2, Number(env.DX_SYNC_INTERVAL) || 5);
return {
name: "dx-dev-sync",
apply: "serve",
configureServer(server) {
server.middlewares.use("/api/dev-sync", (req, res) => {
res.writeHead(200, { "Content-Type": "application/json", "Cache-Control": "no-store" });
res.end(JSON.stringify(REG2.status));
});
clearInterval(REG2.timer);
if (!remote) {
REG2.status = { enabled: false, message: "off: set DX_SYNC_REMOTE (a remote name like origin, or a repo URL) in .env.local to follow a shared branch" };
return;
}
const log = server.config.logger;
log.info(`[dev-sync] following ${label(remote, branch)} every ${every}s (fast-forward only, never over local edits)`);
const tick = () => syncOnce(root, remote, branch, log);
REG2.timer = setInterval(tick, every * 1e3);
REG2.timer.unref?.();
tick();
}
};
}
// vite.config.js
import { fileURLToPath as fileURLToPath5 } from "node:url";
import { resolve as resolve8, dirname as dirname6, join as join4 } from "node:path";
import { readdirSync as readdirSync5, statSync as statSync4, existsSync as existsSync6, readFileSync as readFileSync7 } from "node:fs";
import { createHash as createHash2 } from "node:crypto";
var __vite_injected_original_import_meta_url5 = "file:///home/lk10x/Workspace/eco-dx/root-doxa-maps/wt-hf/vite.config.js";
var __dirname = dirname6(fileURLToPath5(__vite_injected_original_import_meta_url5));
var SHIP_ONE_LOCALE = process.env.DX_SHIP_ONE_LOCALE === "1";
var profilesDir = resolve8(__dirname, "plugin-designs");
var MFE_NAME = TREE_NAME;
var OUT_ROOT = process.env.DOXA_OUT_ROOT ? resolve8(process.env.DOXA_OUT_ROOT) : GATED_PROFILES.includes(process.env.BUNDLE) ? resolve8(__dirname, ".gated", MFE_NAME) : resolve8(__dirname, "public", MFE_NAME);
function discoverBundles() {
if (!existsSync6(profilesDir)) return {};
const entries = {};
for (const name of readdirSync5(profilesDir)) {
if (name.startsWith("_") || name.startsWith(".")) continue;
const dir = resolve8(profilesDir, name);
if (!statSync4(dir).isDirectory()) continue;
const html = resolve8(dir, "index.html");
const js = resolve8(dir, "index.js");
if (!existsSync6(html) || !existsSync6(js)) continue;
entries[name] = { html, js };
}
return entries;
}
var localeDirs = () => readdirSync5(join4(__dirname, "library/i18n/locales"), { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
function localeTree(areas, lc) {
const root = join4(__dirname, "library/i18n/locales");
const tree = {};
for (const a of areas) {
const p = join4(root, lc, `${a}.json`);
if (!existsSync6(p)) continue;
try {
tree[a] = JSON.parse(readFileSync7(p, "utf8"));
} catch {
}
}
return Object.keys(tree).length ? JSON.stringify(tree) : null;
}
function i18nAreasPlugin(bundle) {
let areas = null;
return {
name: "doxa-i18n-areas",
enforce: "pre",
async buildStart() {
const { areasForBundle: areasForBundle2 } = await Promise.resolve().then(() => (init_i18n_areas(), i18n_areas_exports));
areas = areasForBundle2(__dirname, bundle).areas;
this.info?.(`i18n areas for ${bundle}: ${areas.join(", ") || "(none)"}`);
},
transform(code, id) {
if (!areas || !id.replace(/\\/g, "/").endsWith("/library/i18n/index.js")) return null;
const GLOB = "import.meta.glob('./locales/*/*.json'";
if (!code.includes(GLOB)) this.error("i18n catalogue glob not found in library/i18n/index.js; cannot narrow it");
const loc = SHIP_ONE_LOCALE ? "en" : "*";
const list = areas.length ? "[" + areas.map((a) => `'./locales/${loc}/${a}.json'`).join(", ") + "]" : "['./locales/*/__none__.json']";
let out = code.replace(GLOB, "import.meta.glob(" + list);
if (SHIP_ONE_LOCALE) {
const sri = {};
for (const lc of localeDirs()) {
if (lc === "en") continue;
const json = localeTree(areas, lc);
if (json) sri[lc] = "sha384-" + createHash2("sha384").update(json).digest("base64");
}
out = `const __DX_LOCALE_SRI__ = ${JSON.stringify(sri)};
` + out;
}
return { code: out, map: null };
},
// Emit <bundle>/locales/<lc>.json for every locale the IIFE no longer carries, holding exactly
// the areas this bundle uses — the same areasForBundle() answer the glob above was narrowed
// with, so the two dimensions cannot drift apart. Emitted from THIS plugin on purpose: the
// composite-freshness, landing-consumers, fix:sri and .gated/ steps already walk the build's
// own output, so assets that appear here are covered with no new pipeline step.
generateBundle() {
if (!SHIP_ONE_LOCALE || !areas?.length) return;
for (const lc of localeDirs()) {
if (lc === "en") continue;
const json = localeTree(areas, lc);
if (json) this.emitFile({ type: "asset", fileName: `locales/${lc}.json`, source: json });
}
}
};
}
var vite_config_default = defineConfig(({ command, mode }) => {
const env = loadEnv(mode, __dirname, "");
const all = discoverBundles();
const allNames = Object.keys(all);
const target = process.env.BUNDLE;
const isBuild = command === "build";
if (isBuild && !target) {
throw new Error(
`[${MFE_NAME}] Set BUNDLE=<name> for build, or use \`npm run build\` (loops all).
Available: ${allNames.join(", ") || "(none)"}`
);
}
if (isBuild && !all[target]) {
throw new Error(
`[${MFE_NAME}] Bundle "${target}" is not buildable: plugin-designs/${target}/ is missing index.html and/or index.js (the custom-element entry pair every bundle needs).
Buildable bundles: ${allNames.join(", ") || "(none)"}`
);
}
const buildEntries = isBuild ? { [target]: all[target].js } : Object.fromEntries(allNames.map((n) => [n, all[n].html]));
return {
// COMPILE-TIME QA GATE (release governance): the QA corner widget references
// the maintainer's internal platform and must NOT exist in public
// artifacts. Default FALSE strips it from every bundle (dead-branch +
// treeshake); an explicitly-flagged platform build sets DOXA_QA=1.
// The dev server listens on THIS MACHINE ONLY. A reachable one serves the source tree, node_modules
// and the token baked into /; a remote viewer reaches it through an ssh tunnel (ssh -L), never a public
// port. `--host` on the command line still overrides this for a deliberate LAN session.
// Local plugin backends (backend/, e.g. rudder-engine) are started by backendDevPlugin and reached
// through these same-origin routes, so a plugin calls /api/<name>/… in dev exactly as on desktop.
// NOT WATCHING public/ (the first laptop run with DX_SYNC_REMOTE, 2026-09-28): a landing rewrites
// dozens of built leaf index.html files there, and Vite answers each changed .html with a FULL page reload
// (measured: one edited leaf page -> one full-reload broadcast), so a pull fired a burst of reloads while
// git was still writing and the page went white. The dev server never serves public/ through its module
// graph (the script-embed route reads it on request), so nothing there needs watching.
server: { host: "127.0.0.1", proxy: devBackendProxy(env), watch: { ignored: ["**/public/**"] } },
define: {
// ★ NO 'unsafe-eval' (CRITIC-4, 2026-09-26). vue-i18n's default message compiler builds each message
// with `new Function`, so a partner with a strict Content-Security-Policy saw every translated string
// fail. The JIT compiler (vue-i18n >= 9.3) compiles messages to an AST and evaluates it without eval;
// defining the flag lets the bundler drop the eval path entirely (check:no-eval asserts it).
__INTLIFY_JIT_COMPILATION__: "true",
__INTLIFY_DROP_MESSAGE_COMPILER__: "false",
__DOXA_QA__: JSON.stringify(process.env.DOXA_QA === "1"),
// The output tree's name (vite.doxa-maps-build-config.json `name`, the same value OUT_ROOT uses),
// for the few runtime paths that must name the tree — so renaming the tree needs no source edit.
__DOXA_TREE_NAME__: JSON.stringify(MFE_NAME)
},
// Build only: shadow-DOM CSS is injected from useShadowStyles(`…`) literals that
// ship verbatim, so their block comments are stripped before the Vue compiler
// runs (enforce: 'pre'). Dev keeps the comments.
plugins: [
// ★ ONLY THE TRANSLATION AREAS THIS BUNDLE USES (CRITIC-10). library/i18n/index.js globs every
// locales/*/*.json; in a BUNDLE build the glob is narrowed to the areas internal/i18n-areas.mjs finds
// in this bundle's source graph. Dev (no BUNDLE) keeps every area. check:i18n-treeshake verifies it.
isBuild && target ? i18nAreasPlugin(target) : null,
stripShadowCssCommentsPlugin(),
// ─── STRUCTURAL shadow-DOM CSS fix (customElement mode) ──────────────────
// WHY: every bundle here is a `defineCustomElement(...)` that renders inside a
// SHADOW ROOT. In @vitejs/plugin-vue's DEFAULT mode, each SFC <style> compiles
// to a CSS *asset* that vite-plugin-css-injected-by-js dumps into document.head —
// which a shadow root CANNOT see, so Vue's _applyStyles gets an empty styles[]
// and the element renders unstyled (a list of naked buttons / a collapsed shell).
// Running the plugin in customElement mode makes it compile each SFC <style> as an
// INLINE string and attach it to the component's `styles: [...]` array (see
// genStyleCode in @vitejs/plugin-vue: `directQuery = &inline`, then
// attachedProps.push(['styles', ...])). Vue's defineCustomElement then injects that
// array into EVERY instance's shadow root automatically — correct-by-construction,
// so no element can forget it. This replaces the per-element useShadowStyles()
// discipline for each SFC's OWN <style>; the remaining useShadowStyles() calls stay
// (they inject a child's critical CSS and are idempotent-by-key, so a double inject
// is harmless). `true` = ALL .vue in this build are custom-element SFCs, which is
// exactly what this repo builds (one defineCustomElement per bundle).
vue({ customElement: true }),
cssInjectedByJsPlugin(),
autoSpaDevPlugin(env.VITE_MAPBOX_TOKEN || process.env.VITE_MAPBOX_TOKEN || ""),
backendDevPlugin(__dirname, env),
devSyncPlugin(__dirname, env)
],
resolve: {
alias: { "@map": resolve8(__dirname, "library") }
},
// COLD `bun run dev` (rega, all 40 dev pages): the first load of every page got "504 (Outdated Optimize
// Dep)" on vue.js / pinia.js, because Vite discovered them mid-request, re-optimised, and invalidated the
// page before it mounted. Naming the bare packages the leaves import makes Vite pre-bundle them at
// startup. These are EVERY bare runtime import in library/ and plugin-designs/ (vue, vue-i18n, pinia)
// plus jspdf, loaded lazily on poster export and so otherwise re-optimised on the first export. The map
// engines and d3 are pinned CDN scripts, not imports.
optimizeDeps: { include: ["vue", "vue-i18n", "pinia", "jspdf"] },
// NEVER copy public/ into a bundle's output. Vite's default publicDir is
// 'public', and the build runs vite ONCE PER PROFILE — so the default copied
// the entire 95MB shared asset tree into all nine bundle folders, taking the
// served tree to 717MB (assets/previews/west-africa.webp existed nine times)
// and making `cap sync` push 717MB into the APK, past Play's 150MB ceiling.
// public/ is the SHARED web-root: bundles reach it via the `assetsBase` that
// generate-tree stamps into each page, not via a private copy.
publicDir: false,
build: {
// Each bundle lands in its own folder: public/<name>/<bundle>/<bundle>.js.
// public/ IS the served web-root and is committed, so the build writes there
// DIRECTLY — no intermediate tree and no copy step migrating files in from
// elsewhere. generate-tree.mjs then fills in the index.html files + manifest.
outDir: isBuild ? resolve8(OUT_ROOT, target) : OUT_ROOT,
emptyOutDir: false,
cssCodeSplit: false,
assetsInlineLimit: Number.MAX_SAFE_INTEGER,
sourcemap: false,
assetsDir: "",
// emit assets next to the .js, no assets/ subfolder
chunkSizeWarningLimit: 2500,
// research-map is ~1.2 MB; tree-shaking already done
rollupOptions: {
input: buildEntries,
// Externalize jspdf — it is used ONLY by the lazy poster/packet export
// (`await import('jspdf')` in useMapPoster/useMapPacket). Because the IIFE
// build uses inlineDynamicImports, that "lazy" import was being INLINED,
// bloating every research/countries/upg bundle by ~0.6 MB (jspdf pulls in
// html2canvas + canvg). Marking it external + mapping it to a CDN ESM URL
// keeps it out of the bundle entirely; the browser fetches it at runtime
// ONLY when the user actually exports a poster/packet. (Build-only — dev
// still resolves jspdf from node_modules.)
external: isBuild ? ["jspdf"] : [],
output: isBuild ? {
format: "iife",
name: `MapForge_${(target || "").replace(/[^a-zA-Z0-9_]/g, "_")}`,
entryFileNames: "[name].js",
assetFileNames: () => `${target}.[ext]`,
inlineDynamicImports: true,
// Resolve the externalized `import('jspdf')` to a CDN ESM module at runtime.
paths: { jspdf: "https://esm.sh/jspdf@4.2.1" }
} : {
entryFileNames: "[name].js"
}
}
}
};
});
export {
vite_config_default as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiaW50ZXJuYWwvaTE4bi1hcmVhcy5tanMiLCAidml0ZS5jb25maWcuanMiLCAiaW50ZXJuYWwvcGx1Z2luLWdhbGxlcnkvZGV2LXBsdWdpbi5tanMiLCAiaW50ZXJuYWwvcGx1Z2luLWdhbGxlcnkvZGlzY292ZXIubWpzIiwgImludGVybmFsL2dlbmVyYXRlLWdhbGxlcnkubWpzIiwgImludGVybmFsL190cmVlLW5hbWUubWpzIiwgImludGVybmFsL3Byb2ZpbGUtbWV0YS5tanMiLCAiaW50ZXJuYWwvdml0ZS1wbHVnaW4tc3RyaXAtc2hhZG93LWNzcy1jb21tZW50cy5tanMiLCAiaW50ZXJuYWwvYmFja2VuZC1kZXYtcGx1Z2luLm1qcyIsICJpbnRlcm5hbC9kZXYtc3luYy1wbHVnaW4ubWpzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL2hvbWUvbGsxMHgvV29ya3NwYWNlL2Vjby1keC9yb290LWRveGEtbWFwcy93dC1oZi9pbnRlcm5hbFwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL2hvbWUvbGsxMHgvV29ya3NwYWNlL2Vjby1keC9yb290LWRveGEtbWFwcy93dC1oZi9pbnRlcm5hbC9pMThuLWFyZWFzLm1qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vaG9tZS9sazEweC9Xb3Jrc3BhY2UvZWNvLWR4L3Jvb3QtZG94YS1tYXBzL3d0LWhmL2ludGVybmFsL2kxOG4tYXJlYXMubWpzXCI7LyoqXG4gKiBpMThuLWFyZWFzLm1qcyBcdTIwMTQgd2hpY2ggdHJhbnNsYXRpb24gQVJFQVMgKGxpYnJhcnkvaTE4bi9sb2NhbGVzLzxsYz4vPGFyZWE+Lmpzb24pIGEgYnVuZGxlIGNhbiB1c2UuXG4gKlxuICogV0hZIChDUklUSUMtMTAsIDIwMjYtMDktMjYpOiBsaWJyYXJ5L2kxOG4vaW5kZXguanMgZ2xvYmJlZCBFVkVSWSBhcmVhIGludG8gZXZlcnkgYnVuZGxlLCBzbyBlYWNoIG9mIDE5XG4gKiBidW5kbGVzIGNhcnJpZWQgYWxsIDI1IGFyZWFzIHggMTEgbG9jYWxlcyAofjMyMCBLQiByYXcpIFx1MjAxNCBvdGhlciBwbHVnaW5zJyBzdHJpbmdzIGluY2x1ZGVkIFx1MjAxNCBhbmQgZWFjaCBuZXdcbiAqIGFyZWEgZ3JldyBldmVyeSBidW5kbGUuIFRoZSBidWlsZCBub3cgYnVuZGxlcyBvbmx5IHRoZSBhcmVhcyB0aGlzIGZ1bmN0aW9uIHJldHVybnMuXG4gKlxuICogSE9XLCBjb25zZXJ2YXRpdmVseTogd2FsayB0aGUgYnVuZGxlJ3MgU09VUkNFIGltcG9ydCBncmFwaCBmcm9tIHBsdWdpbi1kZXNpZ25zLzxidW5kbGU+L2luZGV4LmpzXG4gKiAocmVsYXRpdmUgYW5kIEBtYXAvIGltcG9ydHMsIGR5bmFtaWMgaW1wb3J0KCksIGV4cG9ydC1mcm9tLCBhbmQgaW1wb3J0Lm1ldGEuZ2xvYiBwYXR0ZXJucyksIHRoZW4ga2VlcCBhblxuICogYXJlYSBpZiBpdHMgbmFtZSBhcHBlYXJzIGluIGFueSByZWFjaGVkIGZpbGUgYXMgYSBrZXkgcHJlZml4ICgnYXJlYS4nIGluIGEgc3RyaW5nIG9yIHRlbXBsYXRlIGxpdGVyYWwpIG9yXG4gKiBhcyBhIGJhcmUgc3RyaW5nIGxpdGVyYWwgKCdhcmVhJywgd2hpY2ggY292ZXJzIGtleXMgYXNzZW1ibGVkIGF0IHJ1bnRpbWUgYXMgYCR7YXJlYX0uJHtrZXl9YCkuXG4gKiBSdW50aW1lLWZldGNoZWQgZGF0YSBjYXJyaWVzIG5vIGkxOG4ga2V5cyAobWVhc3VyZWQ6IG5vIGRhdGEvIEpTT04gaG9sZHMgYW4gXCJhcmVhLmtleVwiIHN0cmluZyksIHNvIHRoZVxuICogc291cmNlIGdyYXBoIGlzIHRoZSB3aG9sZSBzdG9yeS4gT3Zlci1pbmNsdXNpb24gY29zdHMgYnl0ZXM7IG9taXNzaW9uIHdvdWxkIGNvc3Qgc3RyaW5ncywgc28gZXZlcnkgcnVsZVxuICogZXJycyB0b3dhcmQgaW5jbHVkaW5nLiBjaGVjazppMThuLXRyZWVzaGFrZSB2ZXJpZmllcyB0aGUgcmVzdWx0IGFnYWluc3QgdGhlIEJVSUxUIGJ1bmRsZS5cbiAqL1xuaW1wb3J0IHsgcmVhZEZpbGVTeW5jLCBleGlzdHNTeW5jLCByZWFkZGlyU3luYywgc3RhdFN5bmMgfSBmcm9tICdub2RlOmZzJ1xuaW1wb3J0IHsgcmVzb2x2ZSwgZGlybmFtZSwgam9pbiwgcmVsYXRpdmUgfSBmcm9tICdub2RlOnBhdGgnXG5cbmV4cG9ydCBmdW5jdGlvbiBhbGxBcmVhcyhyb290KSB7XG4gIHJldHVybiByZWFkZGlyU3luYyhqb2luKHJvb3QsICdsaWJyYXJ5L2kxOG4vbG9jYWxlcy9lbicpKS5maWx0ZXIoKGYpID0+IGYuZW5kc1dpdGgoJy5qc29uJykpLm1hcCgoZikgPT4gZi5yZXBsYWNlKC9cXC5qc29uJC8sICcnKSkuc29ydCgpXG59XG5cbmNvbnN0IElNUE9SVF9SRSA9IC8oPzppbXBvcnR8ZXhwb3J0KVxcc1teJ1wiYDtdKj9mcm9tXFxzKlsnXCJdKFteJ1wiXSspWydcIl18aW1wb3J0XFxzKlsnXCJdKFteJ1wiXSspWydcIl18aW1wb3J0XFxzKlxcKFxccypbJ1wiXShbXidcIl0rKVsnXCJdXFxzKlxcKS9nXG5jb25zdCBHTE9CX1JFID0gL2ltcG9ydFxcLm1ldGFcXC5nbG9iXFxzKlxcKFxccyooXFxbW15cXF1dKlxcXXxbJ1wiXVteJ1wiXStbJ1wiXSkvZ1xuXG5mdW5jdGlvbiByZXNvbHZlRmlsZShwKSB7XG4gIGZvciAoY29uc3QgY2FuZCBvZiBbcCwgcCArICcuanMnLCBwICsgJy5tanMnLCBwICsgJy52dWUnLCBwICsgJy5qc29uJywgam9pbihwLCAnaW5kZXguanMnKV0pIHtcbiAgICB0cnkgeyBpZiAoZXhpc3RzU3luYyhjYW5kKSAmJiBzdGF0U3luYyhjYW5kKS5pc0ZpbGUoKSkgcmV0dXJuIGNhbmQgfSBjYXRjaCB7IC8qIG5leHQgKi8gfVxuICB9XG4gIHJldHVybiBudWxsXG59XG5cbmZ1bmN0aW9uIGV4cGFuZEdsb2IocGF0dGVybiwgZnJvbURpcikge1xuICAvLyBPbmx5IHRoZSBzaGFwZXMgdGhpcyByZXBvIHVzZXM6IGEgZGlyZWN0b3J5IHBhcnQgcGx1cyBhIGZpbGUgcGF0dGVybiB3aXRoICogKGFuZCBvcHRpb25hbGx5IGEgKiBkaXIpLlxuICBjb25zdCBhYnMgPSByZXNvbHZlKGZyb21EaXIsIHBhdHRlcm4pXG4gIGNvbnN0IHBhcnRzID0gYWJzLnNwbGl0KCcvJylcbiAgY29uc3Qgb3V0ID0gW11cbiAgY29uc3Qgd2FsayA9IChpLCBkaXIpID0+IHtcbiAgICBpZiAoaSA9PT0gcGFydHMubGVuZ3RoKSByZXR1cm5cbiAgICBjb25zdCBzZWcgPSBwYXJ0c1tpXVxuICAgIGlmIChpID09PSAwKSByZXR1cm4gd2FsaygxLCAnLycpXG4gICAgaWYgKCFzZWcuaW5jbHVkZXMoJyonKSkge1xuICAgICAgY29uc3QgbmV4dCA9IGpvaW4oZGlyLCBzZWcpXG4gICAgICBpZiAoaSA9PT0gcGFydHMubGVuZ3RoIC0gMSkgeyBpZiAoZXhpc3RzU3luYyhuZXh0KSkgb3V0LnB1c2gobmV4dCkgfSBlbHNlIHdhbGsoaSArIDEsIG5leHQpXG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgY29uc3QgcmUgPSBuZXcgUmVnRXhwKCdeJyArIHNlZy5yZXBsYWNlKC9bLiteJHt9KCl8W1xcXVxcXFxdL2csICdcXFxcJCYnKS5yZXBsYWNlKC9cXCpcXCovZywgJy4qJykucmVwbGFjZSgvXFwqL2csICdbXi9dKicpICsgJyQnKVxuICAgIGxldCBlbnRyaWVzID0gW11cbiAgICB0cnkgeyBlbnRyaWVzID0gcmVhZGRpclN5bmMoZGlyKSB9IGNhdGNoIHsgcmV0dXJuIH1cbiAgICBmb3IgKGNvbnN0IGUgb2YgZW50cmllcykgaWYgKHJlLnRlc3QoZSkpIHtcbiAgICAgIGlmIChpID09PSBwYXJ0cy5sZW5ndGggLSAxKSBvdXQucHVzaChqb2luKGRpciwgZSkpOyBlbHNlIHdhbGsoaSArIDEsIGpvaW4oZGlyLCBlKSlcbiAgICB9XG4gIH1cbiAgd2FsaygwLCAnLycpXG4gIHJldHVybiBvdXRcbn1cblxuLyoqIEV2ZXJ5IHNvdXJjZSBmaWxlIHJlYWNoYWJsZSBmcm9tIHRoZSBidW5kbGUncyBlbnRyeSAobGlicmFyeS9pMThuL2xvY2FsZXMgZXhjbHVkZWQpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1bmRsZUdyYXBoKHJvb3QsIGJ1bmRsZSkge1xuICBjb25zdCBlbnRyeSA9IGpvaW4ocm9vdCwgJ3BsdWdpbi1kZXNpZ25zJywgYnVuZGxlLCAnaW5kZXguanMnKVxuICBjb25zdCBzZWVuID0gbmV3IFNldCgpXG4gIGNvbnN0IHF1ZXVlID0gW2VudHJ5XVxuICBjb25zdCBMT0NBTEVTID0gam9pbihyb290LCAnbGlicmFyeS9pMThuL2xvY2FsZXMnKVxuICB3aGlsZSAocXVldWUubGVuZ3RoKSB7XG4gICAgY29uc3QgZiA9IHF1ZXVlLnBvcCgpXG4gICAgaWYgKCFmIHx8IHNlZW4uaGFzKGYpIHx8IGYuc3RhcnRzV2l0aChMT0NBTEVTKSB8fCBmLmluY2x1ZGVzKCcvbm9kZV9tb2R1bGVzLycpKSBjb250aW51ZVxuICAgIHNlZW4uYWRkKGYpXG4gICAgbGV0IHNyYyA9ICcnXG4gICAgdHJ5IHsgc3JjID0gcmVhZEZpbGVTeW5jKGYsICd1dGY4JykgfSBjYXRjaCB7IGNvbnRpbnVlIH1cbiAgICBjb25zdCBkaXIgPSBkaXJuYW1lKGYpXG4gICAgY29uc3QgYWRkID0gKHNwZWMpID0+IHtcbiAgICAgIGlmICghc3BlYykgcmV0dXJuXG4gICAgICBsZXQgcCA9IG51bGxcbiAgICAgIGlmIChzcGVjLnN0YXJ0c1dpdGgoJ0BtYXAvJykpIHAgPSBqb2luKHJvb3QsICdsaWJyYXJ5Jywgc3BlYy5zbGljZSg1KSlcbiAgICAgIGVsc2UgaWYgKHNwZWMuc3RhcnRzV2l0aCgnLicpIHx8IHNwZWMuc3RhcnRzV2l0aCgnLycpKSBwID0gc3BlYy5zdGFydHNXaXRoKCcvJykgPyBqb2luKHJvb3QsIHNwZWMpIDogcmVzb2x2ZShkaXIsIHNwZWMpXG4gICAgICBlbHNlIHJldHVybiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBwYWNrYWdlOiBjYXJyaWVzIG5vbmUgb2Ygb3VyIGtleXNcbiAgICAgIHAgPSBwLnJlcGxhY2UoL1xcPy4qJC8sICcnKVxuICAgICAgY29uc3QgciA9IHJlc29sdmVGaWxlKHApXG4gICAgICBpZiAocikgcXVldWUucHVzaChyKVxuICAgIH1cbiAgICBmb3IgKGNvbnN0IG0gb2Ygc3JjLm1hdGNoQWxsKElNUE9SVF9SRSkpIGFkZChtWzFdIHx8IG1bMl0gfHwgbVszXSlcbiAgICBmb3IgKGNvbnN0IG0gb2Ygc3JjLm1hdGNoQWxsKEdMT0JfUkUpKSB7XG4gICAgICBjb25zdCBwYXRzID0gbVsxXS5zdGFydHNXaXRoKCdbJykgPyBbLi4ubVsxXS5tYXRjaEFsbCgvWydcIl0oW14nXCJdKylbJ1wiXS9nKV0ubWFwKCh4KSA9PiB4WzFdKSA6IFttWzFdLnNsaWNlKDEsIC0xKV1cbiAgICAgIGZvciAoY29uc3QgcGF0IG9mIHBhdHMpIHtcbiAgICAgICAgaWYgKHBhdC5zdGFydHNXaXRoKCchJykpIGNvbnRpbnVlXG4gICAgICAgIGNvbnN0IGJhc2UgPSBwYXQuc3RhcnRzV2l0aCgnQG1hcC8nKSA/IGpvaW4ocm9vdCwgJ2xpYnJhcnknKSA6IGRpclxuICAgICAgICBmb3IgKGNvbnN0IGhpdCBvZiBleHBhbmRHbG9iKHBhdC5yZXBsYWNlKC9eQG1hcFxcLy8sICcnKSwgYmFzZSkpIHF1ZXVlLnB1c2goaGl0KVxuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gWy4uLnNlZW5dXG59XG5cbi8qKiBUaGUgYXJlYXMgYSBidW5kbGUgbmVlZHMsIHNvcnRlZC4gYGV4dHJhYCBpcyBhbHdheXMgaW5jbHVkZWQgKGFyZWFzIHRoZSBpMThuIGNvcmUgaXRzZWxmIHJlYWRzKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcmVhc0ZvckJ1bmRsZShyb290LCBidW5kbGUsIHsgZXh0cmEgPSBbXSB9ID0ge30pIHtcbiAgY29uc3QgYXJlYXMgPSBhbGxBcmVhcyhyb290KVxuICBjb25zdCBmaWxlcyA9IGJ1bmRsZUdyYXBoKHJvb3QsIGJ1bmRsZSlcbiAgY29uc3QgdGV4dCA9IGZpbGVzLm1hcCgoZikgPT4geyB0cnkgeyByZXR1cm4gcmVhZEZpbGVTeW5jKGYsICd1dGY4JykgfSBjYXRjaCB7IHJldHVybiAnJyB9IH0pLmpvaW4oJ1xcbicpXG4gIGNvbnN0IHVzZWQgPSBuZXcgU2V0KGV4dHJhKVxuICAvLyBcdTI2MDUgQSBCQVJFIE5BTUUgQ09VTlRTIE9OTFkgV0hFUkUgSVQgQlVJTERTIEEgS0VZLiBUaGUgZmlyc3QgdmVyc2lvbiBrZXB0IGFuIGFyZWEgd2hlcmV2ZXIgaXRzIG5hbWVcbiAgLy8gYXBwZWFyZWQgYXMgQU5ZIHN0cmluZyBsaXRlcmFsLCB0byBjb3ZlciBrZXlzIGFzc2VtYmxlZCBhdCBydW50aW1lLiBCdXQgc2V2ZXJhbCBhcmVhIG5hbWVzIGFyZSBhbHNvXG4gIC8vIG9yZGluYXJ5IGlkcyBcdTIwMTQgJ2dvc3BlbCcgaXMgYSBjb2xvdXIgc3RyYXRlZ3ksIGEgZGF0YSBzb3VyY2UgYW5kIGEgY2hhcnQgaWQ7ICdyZWxpZ2lvbicsICdyZWdpb25zJyxcbiAgLy8gJ2RldGFpbCcsICdwb3N0ZXInIGFyZSBmaWVsZHMgYW5kIG1vZGVzIFx1MjAxNCBzbyBldmVyeSBidW5kbGUgaW1wb3J0aW5nIHRob3NlIG1vZHVsZXMgY2FycmllZCBjYXRhbG9ndWVzXG4gIC8vIGl0IG5ldmVyIHNob3dzOiBtZWFzdXJlZCwgODAgYXJlYSBpbmNsdXNpb25zIGFjcm9zcyAyNiBidW5kbGVzLCBhbmQgZ29zcGVsJ3MgY2F0YWxvZ3VlIGFsb25lIHB1c2hlZFxuICAvLyBjb3VudHJ5LXBvc3RlcnMgOS41IEtCIG92ZXIgdGhlIDEuNSBNQiBjZWlsaW5nLiBUaGUgd2F5cyBhIGJhcmUgbmFtZSByZWFsbHkgZG9lcyBidWlsZCBhIGtleSBoZXJlIGFyZVxuICAvLyBmZXcgYW5kIG5hbWVkOiBhIG5hbWVzcGFjZSBoZWxwZXIgKHVzZU9wdGlvbmFsVCAvIHVzZU9wdGlvbmFsSTE4biAvIHF1YWxpZnkpIG9yIGEgdHJhbnNsYXRvciByZWFkaW5nIGFcbiAgLy8gd2hvbGUgYXJlYSAodG0gLyB0IC8gdGUgLyB0U3RhdGljIC8gcnQgd2l0aCB0aGUgbmFtZSBhbG9uZSkuIEEgYnVuZGxlIHdob3NlIGNvZGUgYXNzZW1ibGVzIGEga2V5IHdpdGggYVxuICAvLyBsZWFkaW5nIGAke1x1MjAyNn1gIGtlZXBzIHRoZSBvbGQsIGdlbmVyb3VzIHJ1bGUsIHNpbmNlIGl0cyBhcmVhIGNhbm5vdCBiZSByZWFkIGZyb20gdGhlIHNvdXJjZS5cbiAgY29uc3QgYXNzZW1ibGVzVW5rbm93bktleXMgPSAvXFxiKD86dHx0ZXx0bXx0U3RhdGljfFQpXFwoXFxzKmBcXCRcXHsvLnRlc3QodGV4dClcbiAgZm9yIChjb25zdCBhIG9mIGFyZWFzKSB7XG4gICAgY29uc3QgZXNjID0gYS5yZXBsYWNlKC9bLiorP14ke30oKXxbXFxdXFxcXF0vZywgJ1xcXFwkJicpXG4gICAgaWYgKG5ldyBSZWdFeHAoYFsnXCJcXGBdJHtlc2N9XFxcXC5gKS50ZXN0KHRleHQpKSB7IHVzZWQuYWRkKGEpOyBjb250aW51ZSB9ICAgICAgICAgICAgICAgICAgLy8gJ2FyZWEua2V5J1xuICAgIGlmIChuZXcgUmVnRXhwKGBcXFxcYig/OnVzZU9wdGlvbmFsVHx1c2VPcHRpb25hbEkxOG58cXVhbGlmeXx0bXx0fHRlfHRTdGF0aWN8cnQpXFxcXChcXFxccypbJ1wiXFxgXSR7ZXNjfVsnXCJcXGBdYCkudGVzdCh0ZXh0KSkgeyB1c2VkLmFkZChhKTsgY29udGludWUgfVxuICAgIGlmIChhc3NlbWJsZXNVbmtub3duS2V5cyAmJiBuZXcgUmVnRXhwKGBbJ1wiXFxgXSR7ZXNjfVsnXCJcXGBdYCkudGVzdCh0ZXh0KSkgdXNlZC5hZGQoYSlcbiAgfVxuICByZXR1cm4geyBhcmVhczogWy4uLnVzZWRdLmZpbHRlcigoYSkgPT4gYXJlYXMuaW5jbHVkZXMoYSkpLnNvcnQoKSwgZmlsZXM6IGZpbGVzLm1hcCgoZikgPT4gcmVsYXRpdmUocm9vdCwgZikpIH1cbn1cbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL2hvbWUvbGsxMHgvV29ya3NwYWNlL2Vjby1keC9yb290LWRveGEtbWFwcy93dC1oZlwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL2hvbWUvbGsxMHgvV29ya3NwYWNlL2Vjby1keC9yb290LWRveGEtbWFwcy93dC1oZi92aXRlLmNvbmZpZy5qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vaG9tZS9sazEweC9Xb3Jrc3BhY2UvZWNvLWR4L3Jvb3QtZG94YS1tYXBzL3d0LWhmL3ZpdGUuY29uZmlnLmpzXCI7LyoqXG4gKiBkb3hhLW1hcHMgVml0ZSBjb25maWcgXHUyMDE0IHBlci1idW5kbGUgSUlGRSBidWlsZC5cbiAqIFdIWT8gLT4gISEhIEVBQ0ggQlVORExFIE9OTFkgQlVORExFUyBXSEFUIElUIE5FRURTIEJBU0VEIE9OIElUUyBBUFAgUFJPRklMRSA6KVxuICogTGF5b3V0OlxuICogICBsaWJyYXJ5LyAgICAgICAgICAgICAgIFx1MjE5MCBzaGFyZWQgbGlicmFyeSAoY29tcG9uZW50cywgY29tcG9zYWJsZXMsIGNvbmZpZywgZXRjLjsgYWxpYXNlZCBhcyBAbWFwKVxuICogICBwbHVnaW4tZGVzaWducy88bmFtZT4vICAgXHUyMTkwIGJ1bmRsZSBzb3VyY2UgZm9sZGVyXG4gKiAgICAgXHUyNTFDXHUyNTAwXHUyNTAwIGluZGV4Lmh0bWwgICAgICAgXHUyMTkwIFZpdGUgaHRtbCBlbnRyeSAoc3RhZ2luZyBwYWdlOyBsb2FkcyBpbmRleC5qcyBhcyBhIG1vZHVsZSBpbiBkZXYpXG4gKiAgICAgXHUyNTFDXHUyNTAwXHUyNTAwIGluZGV4LmpzICAgICAgICAgXHUyMTkwIGJ1bmRsZSBlbnRyeSBcdTIwMTQgcmVnaXN0ZXJzIHRoZSBjdXN0b20gZWxlbWVudCAoZ2xvYnMgLi8qLnZ1ZSlcbiAqICAgICBcdTI1MTRcdTI1MDBcdTI1MDAgKi52dWUgICAgICAgICAgICBcdTIxOTAgcHJvZmlsZSBjb21wb25lbnRzIGF0IHRoZSBidW5kbGUgcm9vdCAoYXV0by1kaXNjb3ZlcmVkIHZpYSBpbXBvcnQubWV0YS5nbG9iKCcuLyoudnVlJykpXG4gKiAgIGFwcC9kb3hhLW1hcHMvICAgICAgICAgXHUyMTkwIGJ1aWxkIG91dHB1dCB0cmVlIChzZWUgYmVsb3cpXG4gKlxuICogQnVpbGQgbW9kZTogZWFjaCBpbnZvY2F0aW9uIGJ1aWxkcyBPTkUgYnVuZGxlIChzZWxlY3RlZCB2aWEgQlVORExFIGVudiB2YXIpIHNvIHdlIGNhblxuICogdXNlIElJRkUgZm9ybWF0IHdpdGggaW5saW5lRHluYW1pY0ltcG9ydHMuIFRoZSBucG0gYGJ1aWxkYCBzY3JpcHQgcnVucyB2aXRlIG9uY2UgcGVyXG4gKiBwbHVnaW4tZGVzaWducy88bmFtZT4vIGZvbGRlciwgZW1pdHRpbmcgYXBwL2RveGEtbWFwcy88YnVuZGxlPi88YnVuZGxlPi5qcy4gQWZ0ZXIgYWxsXG4gKiBidW5kbGVzIGFyZSBidWlsdCwgYGdlbmVyYXRlLXRyZWUubWpzYCB3cml0ZXMgdGhlIG1hbmlmZXN0ICsgc2VsZi1jb250YWluZWQgc3RhZ2luZ1xuICogSFRNTCBpbnRvIHRoZSB0cmVlIGFuZCBjb3BpZXMgdGhlIHdob2xlIGRveGEtbWFwcy8gZm9sZGVyIHRvIGV2ZXJ5IGRlc3RpbmF0aW9uXG4gKiAoZGVmYXVsdCAuL2FwcC8gKyBlYWNoIGxpbmUgaW4gdml0ZS5kZXN0aW5hdGlvbi5tZCkuXG4gKlxuICogRGV2IG1vZGUgKGBucG0gcnVuIGRldmApOiBubyBCVU5ETEUgc2VsZWN0aW9uIFx1MjAxNCBWaXRlIHNlcnZlcyBhbGwgYnVuZGxlcyBhdCB0aGVpciBodG1sXG4gKiBwYXRocyB1bmRlciB0aGUgZGV2IHNlcnZlci5cbiAqL1xuaW1wb3J0IHsgZGVmaW5lQ29uZmlnLCBsb2FkRW52IH0gZnJvbSAndml0ZSdcbmltcG9ydCB2dWUgZnJvbSAnQHZpdGVqcy9wbHVnaW4tdnVlJ1xuaW1wb3J0IGNzc0luamVjdGVkQnlKc1BsdWdpbiBmcm9tICd2aXRlLXBsdWdpbi1jc3MtaW5qZWN0ZWQtYnktanMnXG5pbXBvcnQgeyBhdXRvU3BhRGV2UGx1Z2luIH0gZnJvbSAnLi9pbnRlcm5hbC9wbHVnaW4tZ2FsbGVyeS9kZXYtcGx1Z2luLm1qcydcbmltcG9ydCB7IHN0cmlwU2hhZG93Q3NzQ29tbWVudHNQbHVnaW4gfSBmcm9tICcuL2ludGVybmFsL3ZpdGUtcGx1Z2luLXN0cmlwLXNoYWRvdy1jc3MtY29tbWVudHMubWpzJ1xuaW1wb3J0IHsgYmFja2VuZERldlBsdWdpbiwgZGV2QmFja2VuZFByb3h5IH0gZnJvbSAnLi9pbnRlcm5hbC9iYWNrZW5kLWRldi1wbHVnaW4ubWpzJ1xuaW1wb3J0IHsgZGV2U3luY1BsdWdpbiB9IGZyb20gJy4vaW50ZXJuYWwvZGV2LXN5bmMtcGx1Z2luLm1qcydcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tICdub2RlOnVybCdcbmltcG9ydCB7IHJlc29sdmUsIGRpcm5hbWUsIGpvaW4gfSBmcm9tICdub2RlOnBhdGgnXG5pbXBvcnQgeyByZWFkZGlyU3luYywgc3RhdFN5bmMsIGV4aXN0c1N5bmMsIHJlYWRGaWxlU3luYyB9IGZyb20gJ25vZGU6ZnMnXG5pbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSAnbm9kZTpjcnlwdG8nXG5pbXBvcnQgeyBUUkVFX05BTUUsIEdBVEVEX1BST0ZJTEVTIH0gZnJvbSAnLi9pbnRlcm5hbC9fdHJlZS1uYW1lLm1qcydcblxuY29uc3QgX19kaXJuYW1lID0gZGlybmFtZShmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnVybCkpXG4vLyBTaGlwIG9ubHkgdGhlIEFDVElWRSBsb2NhbGU6IGlubGluZSBgZW5gICh0aGUgZmFsbGJhY2tMb2NhbGUpIGFuZCBlbWl0IHRoZSBvdGhlciB0ZW4gYmVzaWRlIGVhY2hcbi8vIGJ1bmRsZSBmb3IgdGhlIHJ1bnRpbWUgdG8gZmV0Y2guIE9mZiBieSBkZWZhdWx0IFx1MjAxNCB0aGUgYnVpbGQgaXMgYnl0ZS1pZGVudGljYWwgdW50aWwgaXQgaXMgc2V0IFx1MjAxNFxuLy8gc28gdGhpcyBjYW4gbGFuZCwgYmUgbWVhc3VyZWQsIGFuZCBiZSB0dXJuZWQgb24gYXMgYSBzZXBhcmF0ZSBkZWNpc2lvbi5cbmNvbnN0IFNISVBfT05FX0xPQ0FMRSA9IHByb2Nlc3MuZW52LkRYX1NISVBfT05FX0xPQ0FMRSA9PT0gJzEnXG5jb25zdCBwcm9maWxlc0RpciA9IHJlc29sdmUoX19kaXJuYW1lLCAncGx1Z2luLWRlc2lnbnMnKVxuXG4vLyBUaGUgbXVsdGktTUZFIG91dHB1dCBmb2xkZXIgbmFtZSBpcyBjb25maWd1cmVkIGluIHZpdGUuZG94YS1tYXBzLWJ1aWxkLWNvbmZpZy5qc29uIChgbmFtZWApLFxuLy8gc28geW91IGNhbiBuYW1lIHRoZSBvdXRwdXQgdHJlZSBpbmRlcGVuZGVudGx5IG9mIHRoaXMgYnVuZGxlciBmb2xkZXIncyBvd24gbmFtZS4gSXQgaXMgcmVhZCBpblxuLy8gT05FIHBsYWNlLCBpbnRlcm5hbC9fdHJlZS1uYW1lLm1qcywgd2hpY2ggZXZlcnkgdG9vbCBzaGFyZXMgXHUyMDE0IHNvIHJlbmFtaW5nIHRoZSB0cmVlIGlzIGEgb25lLWxpbmVcbi8vIGNvbmZpZyBjaGFuZ2UgcmF0aGVyIHRoYW4gYSBodW50IHRocm91Z2ggdGhlIGdhdGVzLlxuY29uc3QgTUZFX05BTUUgPSBUUkVFX05BTUVcblxuLy8gRGVmYXVsdCBvdXRwdXQgdHJlZS4gZ2VuZXJhdGUtdHJlZS5tanMgcmVhZHMgdGhlIHNhbWUgbmFtZSArIGNvcGllcyBpdCBvbndhcmQuXG4vLyBET1hBX09VVF9ST09UIHJlZGlyZWN0cyBhIGJ1aWxkJ3Mgb3V0cHV0IFdJVEhPVVQgdG91Y2hpbmcgcHVibGljLzogY2hlY2s6Y29tcG9zaXRlIHJlYnVpbGRzIGVhY2hcbi8vIGNvbXBvc2l0ZSBpbnRvIGEgdGVtcCBkaXIgYW5kIGNvbXBhcmVzIGJ5dGVzIHdpdGggdGhlIGNvbW1pdHRlZCBidW5kbGUuIFVuc2V0ID0gdW5jaGFuZ2VkIGJlaGF2aW91ci5cbi8vIFx1MjYwNSBBIEdBVEVEIGJ1bmRsZSAoZ2F0ZWRQcm9maWxlcykgbmV2ZXIgYnVpbGRzIGludG8gcHVibGljLzogaXQgZ29lcyB0byAuZ2F0ZWQvPHRyZWU+Lywgd2hpY2ggZ2l0IGlnbm9yZXMuXG4vLyBMZWF2aW5nIGl0IG91dCBvZiB0aGUgbWFuaWZlc3Qgd2FzIG5vdCBlbm91Z2g6IGl0cyAuanMgc2F0IGluIHB1YmxpYy88dHJlZT4vPGJ1bmRsZT4vLCBzbyBhbnkgaG9zdCB0aGF0XG4vLyBzZXJ2ZXMgb3IgY29waWVzIHRoZSBmb2xkZXIgKHRoZSBkcm9wLWluIGNvcGllcyA8dHJlZT4vIHdob2xlKSBzaGlwcGVkIGl0IGFueXdheS5cbmNvbnN0IE9VVF9ST09UID0gcHJvY2Vzcy5lbnYuRE9YQV9PVVRfUk9PVCA/IHJlc29sdmUocHJvY2Vzcy5lbnYuRE9YQV9PVVRfUk9PVClcbiAgOiBHQVRFRF9QUk9GSUxFUy5pbmNsdWRlcyhwcm9jZXNzLmVudi5CVU5ETEUpID8gcmVzb2x2ZShfX2Rpcm5hbWUsICcuZ2F0ZWQnLCBNRkVfTkFNRSlcbiAgOiByZXNvbHZlKF9fZGlybmFtZSwgJ3B1YmxpYycsIE1GRV9OQU1FKVxuXG5mdW5jdGlvbiBkaXNjb3ZlckJ1bmRsZXMoKSB7XG4gIGlmICghZXhpc3RzU3luYyhwcm9maWxlc0RpcikpIHJldHVybiB7fVxuICBjb25zdCBlbnRyaWVzID0ge31cbiAgZm9yIChjb25zdCBuYW1lIG9mIHJlYWRkaXJTeW5jKHByb2ZpbGVzRGlyKSkge1xuICAgIGlmIChuYW1lLnN0YXJ0c1dpdGgoJ18nKSB8fCBuYW1lLnN0YXJ0c1dpdGgoJy4nKSkgY29udGludWVcbiAgICBjb25zdCBkaXIgPSByZXNvbHZlKHByb2ZpbGVzRGlyLCBuYW1lKVxuICAgIGlmICghc3RhdFN5bmMoZGlyKS5pc0RpcmVjdG9yeSgpKSBjb250aW51ZVxuICAgIGNvbnN0IGh0bWwgPSByZXNvbHZlKGRpciwgJ2luZGV4Lmh0bWwnKVxuICAgIGNvbnN0IGpzID0gcmVzb2x2ZShkaXIsICdpbmRleC5qcycpXG4gICAgaWYgKCFleGlzdHNTeW5jKGh0bWwpIHx8ICFleGlzdHNTeW5jKGpzKSkgY29udGludWVcbiAgICBlbnRyaWVzW25hbWVdID0geyBodG1sLCBqcyB9XG4gIH1cbiAgcmV0dXJuIGVudHJpZXNcbn1cblxuLy8gTmFycm93IGxpYnJhcnkvaTE4bi9pbmRleC5qcydzIGNhdGFsb2d1ZSBnbG9iIHRvIHRoZSBhcmVhcyBvbmUgYnVuZGxlIHVzZXMgKHNlZSBwbHVnaW5zIGJlbG93KS5cbi8qKiBMb2NhbGUgZm9sZGVycyBvbiBkaXNrIFx1MjAxNCBkaXJlY3RvcmllcyBvbmx5LCBzbyBhIFJFQURNRSBiZXNpZGUgdGhlbSBpcyBub3QgcmVhZCBhcyBhIGxvY2FsZS4gKi9cbmNvbnN0IGxvY2FsZURpcnMgPSAoKSA9PiByZWFkZGlyU3luYyhqb2luKF9fZGlybmFtZSwgJ2xpYnJhcnkvaTE4bi9sb2NhbGVzJyksIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSB9KVxuICAuZmlsdGVyKChlKSA9PiBlLmlzRGlyZWN0b3J5KCkpLm1hcCgoZSkgPT4gZS5uYW1lKS5zb3J0KClcblxuLyoqIFRoZSBleGFjdCBKU09OIHRoaXMgYnVpbGQgd2lsbCBlbWl0IGZvciBvbmUgbG9jYWxlLCBzbyBpdHMgaGFzaCBkZXNjcmliZXMgd2hhdCBhY3R1YWxseSBzaGlwcy4gKi9cbmZ1bmN0aW9uIGxvY2FsZVRyZWUoYXJlYXMsIGxjKSB7XG4gIGNvbnN0IHJvb3QgPSBqb2luKF9fZGlybmFtZSwgJ2xpYnJhcnkvaTE4bi9sb2NhbGVzJylcbiAgY29uc3QgdHJlZSA9IHt9XG4gIGZvciAoY29uc3QgYSBvZiBhcmVhcykge1xuICAgIGNvbnN0IHAgPSBqb2luKHJvb3QsIGxjLCBgJHthfS5qc29uYClcbiAgICBpZiAoIWV4aXN0c1N5bmMocCkpIGNvbnRpbnVlICAgICAgICAgICAgICAgLy8gbWlzc2luZyBhcmVhOiBmYWxscyBiYWNrIHRvIEVuZ2xpc2ggYnkgZGVzaWduXG4gICAgdHJ5IHsgdHJlZVthXSA9IEpTT04ucGFyc2UocmVhZEZpbGVTeW5jKHAsICd1dGY4JykpIH0gY2F0Y2ggeyAvKiBza2lwIGFuIHVucmVhZGFibGUgYXJlYSAqLyB9XG4gIH1cbiAgcmV0dXJuIE9iamVjdC5rZXlzKHRyZWUpLmxlbmd0aCA/IEpTT04uc3RyaW5naWZ5KHRyZWUpIDogbnVsbFxufVxuXG5mdW5jdGlvbiBpMThuQXJlYXNQbHVnaW4oYnVuZGxlKSB7XG4gIGxldCBhcmVhcyA9IG51bGxcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnZG94YS1pMThuLWFyZWFzJyxcbiAgICBlbmZvcmNlOiAncHJlJyxcbiAgICBhc3luYyBidWlsZFN0YXJ0KCkge1xuICAgICAgY29uc3QgeyBhcmVhc0ZvckJ1bmRsZSB9ID0gYXdhaXQgaW1wb3J0KCcuL2ludGVybmFsL2kxOG4tYXJlYXMubWpzJylcbiAgICAgIGFyZWFzID0gYXJlYXNGb3JCdW5kbGUoX19kaXJuYW1lLCBidW5kbGUpLmFyZWFzXG4gICAgICB0aGlzLmluZm8/LihgaTE4biBhcmVhcyBmb3IgJHtidW5kbGV9OiAke2FyZWFzLmpvaW4oJywgJykgfHwgJyhub25lKSd9YClcbiAgICB9LFxuICAgIHRyYW5zZm9ybShjb2RlLCBpZCkge1xuICAgICAgaWYgKCFhcmVhcyB8fCAhaWQucmVwbGFjZSgvXFxcXC9nLCAnLycpLmVuZHNXaXRoKCcvbGlicmFyeS9pMThuL2luZGV4LmpzJykpIHJldHVybiBudWxsXG4gICAgICBjb25zdCBHTE9CID0gXCJpbXBvcnQubWV0YS5nbG9iKCcuL2xvY2FsZXMvKi8qLmpzb24nXCJcbiAgICAgIGlmICghY29kZS5pbmNsdWRlcyhHTE9CKSkgdGhpcy5lcnJvcignaTE4biBjYXRhbG9ndWUgZ2xvYiBub3QgZm91bmQgaW4gbGlicmFyeS9pMThuL2luZGV4LmpzOyBjYW5ub3QgbmFycm93IGl0JylcbiAgICAgIC8vIFx1MjYwNSBUSEUgTE9DQUxFIFNUQVIgSVMgVEhFIFNFQ09ORCBESU1FTlNJT04uIFdpdGggRFhfU0hJUF9PTkVfTE9DQUxFIG9uLCBvbmx5IGBlbmAgaXMgaW5saW5lZFxuICAgICAgLy8gXHUyMDE0IGl0IGlzIHRoZSBmYWxsYmFja0xvY2FsZSwgc28gaXQgbXVzdCBiZSBcdTIwMTQgYW5kIHRoZSBvdGhlciB0ZW4gYXJlIGVtaXR0ZWQgYmVsb3cgYXMgYXNzZXRzXG4gICAgICAvLyB0aGlzIGJ1bmRsZSBmZXRjaGVzLiBNZWFzdXJlZCBvbiBkb3hhLXNpbXBsZS1tYXA6IHRoZSB0ZW4gdW51c2VkIGxvY2FsZXMgYXJlIDExMyBLQiBnemlwLFxuICAgICAgLy8gNDAlIG9mIHdoYXQgYSByZWFkZXIgZG93bmxvYWRzLiBXaXRob3V0IHRoZSBmbGFnIHRoZSBnbG9iIGtlZXBzIGV2ZXJ5IGxvY2FsZSwgc28gdGhpcyBpc1xuICAgICAgLy8gdGhlIHNhbWUgYnVpbGQgaXQgaGFzIGFsd2F5cyBiZWVuIHVudGlsIHNvbWVvbmUgdHVybnMgaXQgb24uXG4gICAgICBjb25zdCBsb2MgPSBTSElQX09ORV9MT0NBTEUgPyAnZW4nIDogJyonXG4gICAgICBjb25zdCBsaXN0ID0gYXJlYXMubGVuZ3RoID8gJ1snICsgYXJlYXMubWFwKChhKSA9PiBgJy4vbG9jYWxlcy8ke2xvY30vJHthfS5qc29uJ2ApLmpvaW4oJywgJykgKyAnXScgOiBcIlsnLi9sb2NhbGVzLyovX19ub25lX18uanNvbiddXCJcbiAgICAgIGxldCBvdXQgPSBjb2RlLnJlcGxhY2UoR0xPQiwgJ2ltcG9ydC5tZXRhLmdsb2IoJyArIGxpc3QpXG4gICAgICAvLyBcdTI2MDUgVEhFIFBJTiBUUkFWRUxTIFdJVEggVEhFIEJVTkRMRS4gRW1iZWRzIGFyZSBTUkktcGlubmVkIGFuZCBhIGZldGNoZWQgY2F0YWxvZ3VlIHdvdWxkIG5vdFxuICAgICAgLy8gYmUsIHNvIGVhY2ggZW1pdHRlZCBmaWxlJ3Mgc2hhMzg0IGlzIGJha2VkIGluIGhlcmUgYW5kIHBhc3NlZCB0byBmZXRjaCh7IGludGVncml0eSB9KS4gQVxuICAgICAgLy8gc3dhcHBlZCBjYXRhbG9ndWUgdGhlbiBmYWlscyBjbG9zZWQgdG8gRW5nbGlzaCBpbnN0ZWFkIG9mIGluamVjdGluZyB0ZXh0IGludG8gdGhlIHBhZ2UuXG4gICAgICAvLyBIYXNoZWQgZnJvbSBsb2NhbGVUcmVlKCkgXHUyMDE0IHRoZSBzYW1lIGJ5dGVzIGdlbmVyYXRlQnVuZGxlKCkgZW1pdHMsIHNvIHRoZSBwaW4gY2Fubm90IGRlc2NyaWJlXG4gICAgICAvLyBhIGZpbGUgdGhhdCB3YXMgbmV2ZXIgc2hpcHBlZC5cbiAgICAgIGlmIChTSElQX09ORV9MT0NBTEUpIHtcbiAgICAgICAgY29uc3Qgc3JpID0ge31cbiAgICAgICAgZm9yIChjb25zdCBsYyBvZiBsb2NhbGVEaXJzKCkpIHtcbiAgICAgICAgICBpZiAobGMgPT09ICdlbicpIGNvbnRpbnVlXG4gICAgICAgICAgY29uc3QganNvbiA9IGxvY2FsZVRyZWUoYXJlYXMsIGxjKVxuICAgICAgICAgIGlmIChqc29uKSBzcmlbbGNdID0gJ3NoYTM4NC0nICsgY3JlYXRlSGFzaCgnc2hhMzg0JykudXBkYXRlKGpzb24pLmRpZ2VzdCgnYmFzZTY0JylcbiAgICAgICAgfVxuICAgICAgICBvdXQgPSBgY29uc3QgX19EWF9MT0NBTEVfU1JJX18gPSAke0pTT04uc3RyaW5naWZ5KHNyaSl9O1xcbmAgKyBvdXRcbiAgICAgIH1cbiAgICAgIHJldHVybiB7IGNvZGU6IG91dCwgbWFwOiBudWxsIH1cbiAgICB9LFxuICAgIC8vIEVtaXQgPGJ1bmRsZT4vbG9jYWxlcy88bGM+Lmpzb24gZm9yIGV2ZXJ5IGxvY2FsZSB0aGUgSUlGRSBubyBsb25nZXIgY2FycmllcywgaG9sZGluZyBleGFjdGx5XG4gICAgLy8gdGhlIGFyZWFzIHRoaXMgYnVuZGxlIHVzZXMgXHUyMDE0IHRoZSBzYW1lIGFyZWFzRm9yQnVuZGxlKCkgYW5zd2VyIHRoZSBnbG9iIGFib3ZlIHdhcyBuYXJyb3dlZFxuICAgIC8vIHdpdGgsIHNvIHRoZSB0d28gZGltZW5zaW9ucyBjYW5ub3QgZHJpZnQgYXBhcnQuIEVtaXR0ZWQgZnJvbSBUSElTIHBsdWdpbiBvbiBwdXJwb3NlOiB0aGVcbiAgICAvLyBjb21wb3NpdGUtZnJlc2huZXNzLCBsYW5kaW5nLWNvbnN1bWVycywgZml4OnNyaSBhbmQgLmdhdGVkLyBzdGVwcyBhbHJlYWR5IHdhbGsgdGhlIGJ1aWxkJ3NcbiAgICAvLyBvd24gb3V0cHV0LCBzbyBhc3NldHMgdGhhdCBhcHBlYXIgaGVyZSBhcmUgY292ZXJlZCB3aXRoIG5vIG5ldyBwaXBlbGluZSBzdGVwLlxuICAgIGdlbmVyYXRlQnVuZGxlKCkge1xuICAgICAgaWYgKCFTSElQX09ORV9MT0NBTEUgfHwgIWFyZWFzPy5sZW5ndGgpIHJldHVyblxuICAgICAgZm9yIChjb25zdCBsYyBvZiBsb2NhbGVEaXJzKCkpIHtcbiAgICAgICAgaWYgKGxjID09PSAnZW4nKSBjb250aW51ZSAgICAgICAgICAgICAgICAgICAgICAvLyBpbmxpbmVkOiBuZXZlciBmZXRjaGVkXG4gICAgICAgIGNvbnN0IGpzb24gPSBsb2NhbGVUcmVlKGFyZWFzLCBsYylcbiAgICAgICAgLy8gZmlsZU5hbWUgaXMgYWxyZWFkeSByZWxhdGl2ZSB0byB0aGlzIGJ1bmRsZSdzIG91dHB1dCBkaXIgXHUyMDE0IHByZWZpeGluZyB0aGUgYnVuZGxlIG5hbWVcbiAgICAgICAgLy8gYWdhaW4gcHJvZHVjZWQgPGJ1bmRsZT4vPGJ1bmRsZT4vbG9jYWxlcy8sIHdoaWNoIHRoZSBydW50aW1lIHdvdWxkIG5ldmVyIGZpbmQuXG4gICAgICAgIGlmIChqc29uKSB0aGlzLmVtaXRGaWxlKHsgdHlwZTogJ2Fzc2V0JywgZmlsZU5hbWU6IGBsb2NhbGVzLyR7bGN9Lmpzb25gLCBzb3VyY2U6IGpzb24gfSlcbiAgICAgIH1cbiAgICB9LFxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IGRlZmluZUNvbmZpZygoeyBjb21tYW5kLCBtb2RlIH0pID0+IHtcbiAgLy8gLmVudiB2YWx1ZXMgKFZJVEVfTUFQQk9YX1RPS0VOKSBhcmUgTk9UIG9uIHByb2Nlc3MuZW52IGluc2lkZSB0aGlzIGNvbmZpZyBcdTIwMTRcbiAgLy8gbG9hZCB0aGVtIGV4cGxpY2l0bHkgc28gdGhlIGRldiBwbHVnaW4gZ2FsbGVyeSBjYW4gaGFuZCB0aGUgdG9rZW4gdG8gZWFjaCBtYXAuXG4gIGNvbnN0IGVudiA9IGxvYWRFbnYobW9kZSwgX19kaXJuYW1lLCAnJylcbiAgY29uc3QgYWxsID0gZGlzY292ZXJCdW5kbGVzKClcbiAgY29uc3QgYWxsTmFtZXMgPSBPYmplY3Qua2V5cyhhbGwpXG4gIGNvbnN0IHRhcmdldCA9IHByb2Nlc3MuZW52LkJVTkRMRVxuICBjb25zdCBpc0J1aWxkID0gY29tbWFuZCA9PT0gJ2J1aWxkJ1xuXG4gIGlmIChpc0J1aWxkICYmICF0YXJnZXQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgWyR7TUZFX05BTUV9XSBTZXQgQlVORExFPTxuYW1lPiBmb3IgYnVpbGQsIG9yIHVzZSBcXGBucG0gcnVuIGJ1aWxkXFxgIChsb29wcyBhbGwpLlxcbmAgK1xuICAgICAgYEF2YWlsYWJsZTogJHthbGxOYW1lcy5qb2luKCcsICcpIHx8ICcobm9uZSknfWBcbiAgICApXG4gIH1cblxuICBpZiAoaXNCdWlsZCAmJiAhYWxsW3RhcmdldF0pIHtcbiAgICAvLyBBIHBsdWdpbi1kZXNpZ25zLzxuYW1lPi8gZm9sZGVyIHdhcyBwYXNzZWQgYXMgQlVORExFIGJ1dCBoYXMgbm8gaW5kZXguaHRtbCtpbmRleC5qc1xuICAgIC8vIGVudHJ5IHBhaXIgKGUuZy4gYSBoYWxmLWF1dGhvcmVkIG1hcCwgb3IgYSBmb2xkZXIgc3RpbGwgYmVpbmcgc2NhZmZvbGRlZCkuIEZhaWwgd2l0aFxuICAgIC8vIGEgY2xlYXIsIGFjdGlvbmFibGUgbWVzc2FnZSBpbnN0ZWFkIG9mIGEgYENhbm5vdCByZWFkIHByb3BlcnRpZXMgb2YgdW5kZWZpbmVkYCBzdGFjay5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgWyR7TUZFX05BTUV9XSBCdW5kbGUgXCIke3RhcmdldH1cIiBpcyBub3QgYnVpbGRhYmxlOiBwbHVnaW4tZGVzaWducy8ke3RhcmdldH0vIGlzIG1pc3NpbmcgYCArXG4gICAgICBgaW5kZXguaHRtbCBhbmQvb3IgaW5kZXguanMgKHRoZSBjdXN0b20tZWxlbWVudCBlbnRyeSBwYWlyIGV2ZXJ5IGJ1bmRsZSBuZWVkcykuXFxuYCArXG4gICAgICBgQnVpbGRhYmxlIGJ1bmRsZXM6ICR7YWxsTmFtZXMuam9pbignLCAnKSB8fCAnKG5vbmUpJ31gXG4gICAgKVxuICB9XG5cbiAgY29uc3QgYnVpbGRFbnRyaWVzID0gaXNCdWlsZFxuICAgID8geyBbdGFyZ2V0XTogYWxsW3RhcmdldF0uanMgfVxuICAgIDogT2JqZWN0LmZyb21FbnRyaWVzKGFsbE5hbWVzLm1hcChuID0+IFtuLCBhbGxbbl0uaHRtbF0pKVxuXG4gIHJldHVybiB7XG4gICAgLy8gQ09NUElMRS1USU1FIFFBIEdBVEUgKHJlbGVhc2UgZ292ZXJuYW5jZSk6IHRoZSBRQSBjb3JuZXIgd2lkZ2V0IHJlZmVyZW5jZXNcbiAgICAvLyB0aGUgbWFpbnRhaW5lcidzIGludGVybmFsIHBsYXRmb3JtIGFuZCBtdXN0IE5PVCBleGlzdCBpbiBwdWJsaWNcbiAgICAvLyBhcnRpZmFjdHMuIERlZmF1bHQgRkFMU0Ugc3RyaXBzIGl0IGZyb20gZXZlcnkgYnVuZGxlIChkZWFkLWJyYW5jaCArXG4gICAgLy8gdHJlZXNoYWtlKTsgYW4gZXhwbGljaXRseS1mbGFnZ2VkIHBsYXRmb3JtIGJ1aWxkIHNldHMgRE9YQV9RQT0xLlxuICAgIC8vIFRoZSBkZXYgc2VydmVyIGxpc3RlbnMgb24gVEhJUyBNQUNISU5FIE9OTFkuIEEgcmVhY2hhYmxlIG9uZSBzZXJ2ZXMgdGhlIHNvdXJjZSB0cmVlLCBub2RlX21vZHVsZXNcbiAgICAvLyBhbmQgdGhlIHRva2VuIGJha2VkIGludG8gLzsgYSByZW1vdGUgdmlld2VyIHJlYWNoZXMgaXQgdGhyb3VnaCBhbiBzc2ggdHVubmVsIChzc2ggLUwpLCBuZXZlciBhIHB1YmxpY1xuICAgIC8vIHBvcnQuIGAtLWhvc3RgIG9uIHRoZSBjb21tYW5kIGxpbmUgc3RpbGwgb3ZlcnJpZGVzIHRoaXMgZm9yIGEgZGVsaWJlcmF0ZSBMQU4gc2Vzc2lvbi5cbiAgICAvLyBMb2NhbCBwbHVnaW4gYmFja2VuZHMgKGJhY2tlbmQvLCBlLmcuIHJ1ZGRlci1lbmdpbmUpIGFyZSBzdGFydGVkIGJ5IGJhY2tlbmREZXZQbHVnaW4gYW5kIHJlYWNoZWRcbiAgICAvLyB0aHJvdWdoIHRoZXNlIHNhbWUtb3JpZ2luIHJvdXRlcywgc28gYSBwbHVnaW4gY2FsbHMgL2FwaS88bmFtZT4vXHUyMDI2IGluIGRldiBleGFjdGx5IGFzIG9uIGRlc2t0b3AuXG4gICAgLy8gTk9UIFdBVENISU5HIHB1YmxpYy8gKHRoZSBmaXJzdCBsYXB0b3AgcnVuIHdpdGggRFhfU1lOQ19SRU1PVEUsIDIwMjYtMDktMjgpOiBhIGxhbmRpbmcgcmV3cml0ZXNcbiAgICAvLyBkb3plbnMgb2YgYnVpbHQgbGVhZiBpbmRleC5odG1sIGZpbGVzIHRoZXJlLCBhbmQgVml0ZSBhbnN3ZXJzIGVhY2ggY2hhbmdlZCAuaHRtbCB3aXRoIGEgRlVMTCBwYWdlIHJlbG9hZFxuICAgIC8vIChtZWFzdXJlZDogb25lIGVkaXRlZCBsZWFmIHBhZ2UgLT4gb25lIGZ1bGwtcmVsb2FkIGJyb2FkY2FzdCksIHNvIGEgcHVsbCBmaXJlZCBhIGJ1cnN0IG9mIHJlbG9hZHMgd2hpbGVcbiAgICAvLyBnaXQgd2FzIHN0aWxsIHdyaXRpbmcgYW5kIHRoZSBwYWdlIHdlbnQgd2hpdGUuIFRoZSBkZXYgc2VydmVyIG5ldmVyIHNlcnZlcyBwdWJsaWMvIHRocm91Z2ggaXRzIG1vZHVsZVxuICAgIC8vIGdyYXBoICh0aGUgc2NyaXB0LWVtYmVkIHJvdXRlIHJlYWRzIGl0IG9uIHJlcXVlc3QpLCBzbyBub3RoaW5nIHRoZXJlIG5lZWRzIHdhdGNoaW5nLlxuICAgIHNlcnZlcjogeyBob3N0OiAnMTI3LjAuMC4xJywgcHJveHk6IGRldkJhY2tlbmRQcm94eShlbnYpLCB3YXRjaDogeyBpZ25vcmVkOiBbJyoqL3B1YmxpYy8qKiddIH0gfSxcbiAgICBkZWZpbmU6IHtcbiAgICAgIC8vIFx1MjYwNSBOTyAndW5zYWZlLWV2YWwnIChDUklUSUMtNCwgMjAyNi0wOS0yNikuIHZ1ZS1pMThuJ3MgZGVmYXVsdCBtZXNzYWdlIGNvbXBpbGVyIGJ1aWxkcyBlYWNoIG1lc3NhZ2VcbiAgICAgIC8vIHdpdGggYG5ldyBGdW5jdGlvbmAsIHNvIGEgcGFydG5lciB3aXRoIGEgc3RyaWN0IENvbnRlbnQtU2VjdXJpdHktUG9saWN5IHNhdyBldmVyeSB0cmFuc2xhdGVkIHN0cmluZ1xuICAgICAgLy8gZmFpbC4gVGhlIEpJVCBjb21waWxlciAodnVlLWkxOG4gPj0gOS4zKSBjb21waWxlcyBtZXNzYWdlcyB0byBhbiBBU1QgYW5kIGV2YWx1YXRlcyBpdCB3aXRob3V0IGV2YWw7XG4gICAgICAvLyBkZWZpbmluZyB0aGUgZmxhZyBsZXRzIHRoZSBidW5kbGVyIGRyb3AgdGhlIGV2YWwgcGF0aCBlbnRpcmVseSAoY2hlY2s6bm8tZXZhbCBhc3NlcnRzIGl0KS5cbiAgICAgIF9fSU5UTElGWV9KSVRfQ09NUElMQVRJT05fXzogJ3RydWUnLFxuICAgICAgX19JTlRMSUZZX0RST1BfTUVTU0FHRV9DT01QSUxFUl9fOiAnZmFsc2UnLFxuICAgICAgX19ET1hBX1FBX186IEpTT04uc3RyaW5naWZ5KHByb2Nlc3MuZW52LkRPWEFfUUEgPT09ICcxJyksXG4gICAgICAvLyBUaGUgb3V0cHV0IHRyZWUncyBuYW1lICh2aXRlLmRveGEtbWFwcy1idWlsZC1jb25maWcuanNvbiBgbmFtZWAsIHRoZSBzYW1lIHZhbHVlIE9VVF9ST09UIHVzZXMpLFxuICAgICAgLy8gZm9yIHRoZSBmZXcgcnVudGltZSBwYXRocyB0aGF0IG11c3QgbmFtZSB0aGUgdHJlZSBcdTIwMTQgc28gcmVuYW1pbmcgdGhlIHRyZWUgbmVlZHMgbm8gc291cmNlIGVkaXQuXG4gICAgICBfX0RPWEFfVFJFRV9OQU1FX186IEpTT04uc3RyaW5naWZ5KE1GRV9OQU1FKSxcbiAgICB9LFxuICAgIC8vIEJ1aWxkIG9ubHk6IHNoYWRvdy1ET00gQ1NTIGlzIGluamVjdGVkIGZyb20gdXNlU2hhZG93U3R5bGVzKGBcdTIwMjZgKSBsaXRlcmFscyB0aGF0XG4gICAgLy8gc2hpcCB2ZXJiYXRpbSwgc28gdGhlaXIgYmxvY2sgY29tbWVudHMgYXJlIHN0cmlwcGVkIGJlZm9yZSB0aGUgVnVlIGNvbXBpbGVyXG4gICAgLy8gcnVucyAoZW5mb3JjZTogJ3ByZScpLiBEZXYga2VlcHMgdGhlIGNvbW1lbnRzLlxuICAgIHBsdWdpbnM6IFtcbiAgICAgIC8vIFx1MjYwNSBPTkxZIFRIRSBUUkFOU0xBVElPTiBBUkVBUyBUSElTIEJVTkRMRSBVU0VTIChDUklUSUMtMTApLiBsaWJyYXJ5L2kxOG4vaW5kZXguanMgZ2xvYnMgZXZlcnlcbiAgICAgIC8vIGxvY2FsZXMvKi8qLmpzb247IGluIGEgQlVORExFIGJ1aWxkIHRoZSBnbG9iIGlzIG5hcnJvd2VkIHRvIHRoZSBhcmVhcyBpbnRlcm5hbC9pMThuLWFyZWFzLm1qcyBmaW5kc1xuICAgICAgLy8gaW4gdGhpcyBidW5kbGUncyBzb3VyY2UgZ3JhcGguIERldiAobm8gQlVORExFKSBrZWVwcyBldmVyeSBhcmVhLiBjaGVjazppMThuLXRyZWVzaGFrZSB2ZXJpZmllcyBpdC5cbiAgICAgIGlzQnVpbGQgJiYgdGFyZ2V0ID8gaTE4bkFyZWFzUGx1Z2luKHRhcmdldCkgOiBudWxsLFxuICAgICAgc3RyaXBTaGFkb3dDc3NDb21tZW50c1BsdWdpbigpLFxuICAgICAgLy8gXHUyNTAwXHUyNTAwXHUyNTAwIFNUUlVDVFVSQUwgc2hhZG93LURPTSBDU1MgZml4IChjdXN0b21FbGVtZW50IG1vZGUpIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxuICAgICAgLy8gV0hZOiBldmVyeSBidW5kbGUgaGVyZSBpcyBhIGBkZWZpbmVDdXN0b21FbGVtZW50KC4uLilgIHRoYXQgcmVuZGVycyBpbnNpZGUgYVxuICAgICAgLy8gU0hBRE9XIFJPT1QuIEluIEB2aXRlanMvcGx1Z2luLXZ1ZSdzIERFRkFVTFQgbW9kZSwgZWFjaCBTRkMgPHN0eWxlPiBjb21waWxlc1xuICAgICAgLy8gdG8gYSBDU1MgKmFzc2V0KiB0aGF0IHZpdGUtcGx1Z2luLWNzcy1pbmplY3RlZC1ieS1qcyBkdW1wcyBpbnRvIGRvY3VtZW50LmhlYWQgXHUyMDE0XG4gICAgICAvLyB3aGljaCBhIHNoYWRvdyByb290IENBTk5PVCBzZWUsIHNvIFZ1ZSdzIF9hcHBseVN0eWxlcyBnZXRzIGFuIGVtcHR5IHN0eWxlc1tdXG4gICAgICAvLyBhbmQgdGhlIGVsZW1lbnQgcmVuZGVycyB1bnN0eWxlZCAoYSBsaXN0IG9mIG5ha2VkIGJ1dHRvbnMgLyBhIGNvbGxhcHNlZCBzaGVsbCkuXG4gICAgICAvLyBSdW5uaW5nIHRoZSBwbHVnaW4gaW4gY3VzdG9tRWxlbWVudCBtb2RlIG1ha2VzIGl0IGNvbXBpbGUgZWFjaCBTRkMgPHN0eWxlPiBhcyBhblxuICAgICAgLy8gSU5MSU5FIHN0cmluZyBhbmQgYXR0YWNoIGl0IHRvIHRoZSBjb21wb25lbnQncyBgc3R5bGVzOiBbLi4uXWAgYXJyYXkgKHNlZVxuICAgICAgLy8gZ2VuU3R5bGVDb2RlIGluIEB2aXRlanMvcGx1Z2luLXZ1ZTogYGRpcmVjdFF1ZXJ5ID0gJmlubGluZWAsIHRoZW5cbiAgICAgIC8vIGF0dGFjaGVkUHJvcHMucHVzaChbJ3N0eWxlcycsIC4uLl0pKS4gVnVlJ3MgZGVmaW5lQ3VzdG9tRWxlbWVudCB0aGVuIGluamVjdHMgdGhhdFxuICAgICAgLy8gYXJyYXkgaW50byBFVkVSWSBpbnN0YW5jZSdzIHNoYWRvdyByb290IGF1dG9tYXRpY2FsbHkgXHUyMDE0IGNvcnJlY3QtYnktY29uc3RydWN0aW9uLFxuICAgICAgLy8gc28gbm8gZWxlbWVudCBjYW4gZm9yZ2V0IGl0LiBUaGlzIHJlcGxhY2VzIHRoZSBwZXItZWxlbWVudCB1c2VTaGFkb3dTdHlsZXMoKVxuICAgICAgLy8gZGlzY2lwbGluZSBmb3IgZWFjaCBTRkMncyBPV04gPHN0eWxlPjsgdGhlIHJlbWFpbmluZyB1c2VTaGFkb3dTdHlsZXMoKSBjYWxscyBzdGF5XG4gICAgICAvLyAodGhleSBpbmplY3QgYSBjaGlsZCdzIGNyaXRpY2FsIENTUyBhbmQgYXJlIGlkZW1wb3RlbnQtYnkta2V5LCBzbyBhIGRvdWJsZSBpbmplY3RcbiAgICAgIC8vIGlzIGhhcm1sZXNzKS4gYHRydWVgID0gQUxMIC52dWUgaW4gdGhpcyBidWlsZCBhcmUgY3VzdG9tLWVsZW1lbnQgU0ZDcywgd2hpY2ggaXNcbiAgICAgIC8vIGV4YWN0bHkgd2hhdCB0aGlzIHJlcG8gYnVpbGRzIChvbmUgZGVmaW5lQ3VzdG9tRWxlbWVudCBwZXIgYnVuZGxlKS5cbiAgICAgIHZ1ZSh7IGN1c3RvbUVsZW1lbnQ6IHRydWUgfSksXG4gICAgICBjc3NJbmplY3RlZEJ5SnNQbHVnaW4oKSxcbiAgICAgIGF1dG9TcGFEZXZQbHVnaW4oZW52LlZJVEVfTUFQQk9YX1RPS0VOIHx8IHByb2Nlc3MuZW52LlZJVEVfTUFQQk9YX1RPS0VOIHx8ICcnKSxcbiAgICAgIGJhY2tlbmREZXZQbHVnaW4oX19kaXJuYW1lLCBlbnYpLFxuICAgICAgZGV2U3luY1BsdWdpbihfX2Rpcm5hbWUsIGVudiksXG4gICAgXSxcbiAgICByZXNvbHZlOiB7XG4gICAgICBhbGlhczogeyAnQG1hcCc6IHJlc29sdmUoX19kaXJuYW1lLCAnbGlicmFyeScpIH0sXG4gICAgfSxcbiAgICAvLyBDT0xEIGBidW4gcnVuIGRldmAgKHJlZ2EsIGFsbCA0MCBkZXYgcGFnZXMpOiB0aGUgZmlyc3QgbG9hZCBvZiBldmVyeSBwYWdlIGdvdCBcIjUwNCAoT3V0ZGF0ZWQgT3B0aW1pemVcbiAgICAvLyBEZXApXCIgb24gdnVlLmpzIC8gcGluaWEuanMsIGJlY2F1c2UgVml0ZSBkaXNjb3ZlcmVkIHRoZW0gbWlkLXJlcXVlc3QsIHJlLW9wdGltaXNlZCwgYW5kIGludmFsaWRhdGVkIHRoZVxuICAgIC8vIHBhZ2UgYmVmb3JlIGl0IG1vdW50ZWQuIE5hbWluZyB0aGUgYmFyZSBwYWNrYWdlcyB0aGUgbGVhdmVzIGltcG9ydCBtYWtlcyBWaXRlIHByZS1idW5kbGUgdGhlbSBhdFxuICAgIC8vIHN0YXJ0dXAuIFRoZXNlIGFyZSBFVkVSWSBiYXJlIHJ1bnRpbWUgaW1wb3J0IGluIGxpYnJhcnkvIGFuZCBwbHVnaW4tZGVzaWducy8gKHZ1ZSwgdnVlLWkxOG4sIHBpbmlhKVxuICAgIC8vIHBsdXMganNwZGYsIGxvYWRlZCBsYXppbHkgb24gcG9zdGVyIGV4cG9ydCBhbmQgc28gb3RoZXJ3aXNlIHJlLW9wdGltaXNlZCBvbiB0aGUgZmlyc3QgZXhwb3J0LiBUaGUgbWFwXG4gICAgLy8gZW5naW5lcyBhbmQgZDMgYXJlIHBpbm5lZCBDRE4gc2NyaXB0cywgbm90IGltcG9ydHMuXG4gICAgb3B0aW1pemVEZXBzOiB7IGluY2x1ZGU6IFsndnVlJywgJ3Z1ZS1pMThuJywgJ3BpbmlhJywgJ2pzcGRmJ10gfSxcbiAgICAvLyBORVZFUiBjb3B5IHB1YmxpYy8gaW50byBhIGJ1bmRsZSdzIG91dHB1dC4gVml0ZSdzIGRlZmF1bHQgcHVibGljRGlyIGlzXG4gICAgLy8gJ3B1YmxpYycsIGFuZCB0aGUgYnVpbGQgcnVucyB2aXRlIE9OQ0UgUEVSIFBST0ZJTEUgXHUyMDE0IHNvIHRoZSBkZWZhdWx0IGNvcGllZFxuICAgIC8vIHRoZSBlbnRpcmUgOTVNQiBzaGFyZWQgYXNzZXQgdHJlZSBpbnRvIGFsbCBuaW5lIGJ1bmRsZSBmb2xkZXJzLCB0YWtpbmcgdGhlXG4gICAgLy8gc2VydmVkIHRyZWUgdG8gNzE3TUIgKGFzc2V0cy9wcmV2aWV3cy93ZXN0LWFmcmljYS53ZWJwIGV4aXN0ZWQgbmluZSB0aW1lcylcbiAgICAvLyBhbmQgbWFraW5nIGBjYXAgc3luY2AgcHVzaCA3MTdNQiBpbnRvIHRoZSBBUEssIHBhc3QgUGxheSdzIDE1ME1CIGNlaWxpbmcuXG4gICAgLy8gcHVibGljLyBpcyB0aGUgU0hBUkVEIHdlYi1yb290OiBidW5kbGVzIHJlYWNoIGl0IHZpYSB0aGUgYGFzc2V0c0Jhc2VgIHRoYXRcbiAgICAvLyBnZW5lcmF0ZS10cmVlIHN0YW1wcyBpbnRvIGVhY2ggcGFnZSwgbm90IHZpYSBhIHByaXZhdGUgY29weS5cbiAgICBwdWJsaWNEaXI6IGZhbHNlLFxuICAgIGJ1aWxkOiB7XG4gICAgICAvLyBFYWNoIGJ1bmRsZSBsYW5kcyBpbiBpdHMgb3duIGZvbGRlcjogcHVibGljLzxuYW1lPi88YnVuZGxlPi88YnVuZGxlPi5qcy5cbiAgICAgIC8vIHB1YmxpYy8gSVMgdGhlIHNlcnZlZCB3ZWItcm9vdCBhbmQgaXMgY29tbWl0dGVkLCBzbyB0aGUgYnVpbGQgd3JpdGVzIHRoZXJlXG4gICAgICAvLyBESVJFQ1RMWSBcdTIwMTQgbm8gaW50ZXJtZWRpYXRlIHRyZWUgYW5kIG5vIGNvcHkgc3RlcCBtaWdyYXRpbmcgZmlsZXMgaW4gZnJvbVxuICAgICAgLy8gZWxzZXdoZXJlLiBnZW5lcmF0ZS10cmVlLm1qcyB0aGVuIGZpbGxzIGluIHRoZSBpbmRleC5odG1sIGZpbGVzICsgbWFuaWZlc3QuXG4gICAgICBvdXREaXI6IGlzQnVpbGQgPyByZXNvbHZlKE9VVF9ST09ULCB0YXJnZXQpIDogT1VUX1JPT1QsXG4gICAgICBlbXB0eU91dERpcjogZmFsc2UsXG4gICAgICBjc3NDb2RlU3BsaXQ6IGZhbHNlLFxuICAgICAgYXNzZXRzSW5saW5lTGltaXQ6IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSLFxuICAgICAgc291cmNlbWFwOiBmYWxzZSxcbiAgICAgIGFzc2V0c0RpcjogJycsICAgICAgICAgICAgICAgICAgLy8gZW1pdCBhc3NldHMgbmV4dCB0byB0aGUgLmpzLCBubyBhc3NldHMvIHN1YmZvbGRlclxuICAgICAgY2h1bmtTaXplV2FybmluZ0xpbWl0OiAyNTAwLCAgICAvLyByZXNlYXJjaC1tYXAgaXMgfjEuMiBNQjsgdHJlZS1zaGFraW5nIGFscmVhZHkgZG9uZVxuICAgICAgcm9sbHVwT3B0aW9uczoge1xuICAgICAgICBpbnB1dDogYnVpbGRFbnRyaWVzLFxuICAgICAgICAvLyBFeHRlcm5hbGl6ZSBqc3BkZiBcdTIwMTQgaXQgaXMgdXNlZCBPTkxZIGJ5IHRoZSBsYXp5IHBvc3Rlci9wYWNrZXQgZXhwb3J0XG4gICAgICAgIC8vIChgYXdhaXQgaW1wb3J0KCdqc3BkZicpYCBpbiB1c2VNYXBQb3N0ZXIvdXNlTWFwUGFja2V0KS4gQmVjYXVzZSB0aGUgSUlGRVxuICAgICAgICAvLyBidWlsZCB1c2VzIGlubGluZUR5bmFtaWNJbXBvcnRzLCB0aGF0IFwibGF6eVwiIGltcG9ydCB3YXMgYmVpbmcgSU5MSU5FRCxcbiAgICAgICAgLy8gYmxvYXRpbmcgZXZlcnkgcmVzZWFyY2gvY291bnRyaWVzL3VwZyBidW5kbGUgYnkgfjAuNiBNQiAoanNwZGYgcHVsbHMgaW5cbiAgICAgICAgLy8gaHRtbDJjYW52YXMgKyBjYW52ZykuIE1hcmtpbmcgaXQgZXh0ZXJuYWwgKyBtYXBwaW5nIGl0IHRvIGEgQ0ROIEVTTSBVUkxcbiAgICAgICAgLy8ga2VlcHMgaXQgb3V0IG9mIHRoZSBidW5kbGUgZW50aXJlbHk7IHRoZSBicm93c2VyIGZldGNoZXMgaXQgYXQgcnVudGltZVxuICAgICAgICAvLyBPTkxZIHdoZW4gdGhlIHVzZXIgYWN0dWFsbHkgZXhwb3J0cyBhIHBvc3Rlci9wYWNrZXQuIChCdWlsZC1vbmx5IFx1MjAxNCBkZXZcbiAgICAgICAgLy8gc3RpbGwgcmVzb2x2ZXMganNwZGYgZnJvbSBub2RlX21vZHVsZXMuKVxuICAgICAgICBleHRlcm5hbDogaXNCdWlsZCA/IFsnanNwZGYnXSA6IFtdLFxuICAgICAgICBvdXRwdXQ6IGlzQnVpbGQgPyB7XG4gICAgICAgICAgZm9ybWF0OiAnaWlmZScsXG4gICAgICAgICAgbmFtZTogYE1hcEZvcmdlXyR7KHRhcmdldCB8fCAnJykucmVwbGFjZSgvW15hLXpBLVowLTlfXS9nLCAnXycpfWAsXG4gICAgICAgICAgZW50cnlGaWxlTmFtZXM6ICdbbmFtZV0uanMnLFxuICAgICAgICAgIGFzc2V0RmlsZU5hbWVzOiAoKSA9PiBgJHt0YXJnZXR9LltleHRdYCxcbiAgICAgICAgICBpbmxpbmVEeW5hbWljSW1wb3J0czogdHJ1ZSxcbiAgICAgICAgICAvLyBSZXNvbHZlIHRoZSBleHRlcm5hbGl6ZWQgYGltcG9ydCgnanNwZGYnKWAgdG8gYSBDRE4gRVNNIG1vZHVsZSBhdCBydW50aW1lLlxuICAgICAgICAgIHBhdGhzOiB7IGpzcGRmOiAnaHR0cHM6Ly9lc20uc2gvanNwZGZANC4yLjEnIH0sXG4gICAgICAgIH0gOiB7XG4gICAgICAgICAgZW50cnlGaWxlTmFtZXM6ICdbbmFtZV0uanMnLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9XG59KVxuIiwgImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCIvaG9tZS9sazEweC9Xb3Jrc3BhY2UvZWNvLWR4L3Jvb3QtZG94YS1tYXBzL3d0LWhmL2ludGVybmFsL3BsdWdpbi1nYWxsZXJ5XCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCIvaG9tZS9sazEweC9Xb3Jrc3BhY2UvZWNvLWR4L3Jvb3QtZG94YS1tYXBzL3d0LWhmL2ludGVybmFsL3BsdWdpbi1nYWxsZXJ5L2Rldi1wbHVnaW4ubWpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9ob21lL2xrMTB4L1dvcmtzcGFjZS9lY28tZHgvcm9vdC1kb3hhLW1hcHMvd3QtaGYvaW50ZXJuYWwvcGx1Z2luLWdhbGxlcnkvZGV2LXBsdWdpbi5tanNcIjsvKipcbiAqIGRldi1wbHVnaW4ubWpzIFx1MjAxNCB0aGUgVml0ZSBkZXYtb25seSBwbHVnaW4gdGhhdCBzZXJ2ZXMgdGhlIHBsdWdpbiBnYWxsZXJ5LlxuICpcbiAqIFJvdXRlczogIEdFVCAvICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZSBwbHVnaW4gZ2FsbGVyeTogaW50ZXJuYWwvZ2VuZXJhdGUtZ2FsbGVyeS5tanNcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlckdhbGxlcnkobW9kZWwsIHsgbW9kZTogJ2RldicgfSkgb3ZlclxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2FsbGVyeU1vZGVsKGRpc2NvdmVyU3BhUmVnaXN0cnkoKSlcbiAqICAgICAgICAgIEdFVCAvX19wbHVnaW4tZ2FsbGVyeS9tYW5pZmVzdC5qc29uICAgIHRoYXQgbW9kZWwsIG1hbmlmZXN0LXNoYXBlZCAodGhlIHBhZ2UgZmV0Y2hlcyBpdCBsaXZlKVxuICogICAgICAgICAgR0VUIC9fX3BsdWdpbi1nYWxsZXJ5L3JlZ2lzdHJ5Lmpzb24gICAgdGhlIGRpc2NvdmVyeSByZWdpc3RyeSwgbWFjaGluZS1yZWFkYWJsZSAoc21va2UgdG9vbHMpXG4gKiAgICAgICAgICBHRVQgL2Fzc2V0cy88cmVsPiAgKGFuZCAvX19wbHVnaW4tZ2FsbGVyeS9hc3NldHMvPHJlbD4pICBzaGFyZWQgYXNzZXQgcm9vdCAoc2VlIHJlc29sdmVEZXZBc3NldClcbiAqIFdpcmUtdXA6IHBsdWdpbnM6IFt2dWUoKSwgY3NzSW5qZWN0ZWRCeUpzUGx1Z2luKCksIGF1dG9TcGFEZXZQbHVnaW4odG9rZW4pXSBpbiB2aXRlLmNvbmZpZy5qcy5cbiAqIFZlcmlmeTogIGJ1biBydW4gc21va2U6Z2FsbGVyeSAgKGludGVybmFsL3BsdWdpbi1nYWxsZXJ5LXNtb2tlLm1qcyBcdTIwMTQgZXZlcnkgZWxlbWVudCBtdXN0IGJvb3QpXG4gKi9cbmltcG9ydCB7IHJlc29sdmUsIGV4dG5hbWUgfSBmcm9tICdub2RlOnBhdGgnXG5pbXBvcnQgeyBzcGF3blN5bmMgfSBmcm9tICdub2RlOmNoaWxkX3Byb2Nlc3MnXG5pbXBvcnQgeyByZWFkZGlyU3luYywgc3RhdFN5bmMsIGV4aXN0c1N5bmMsIHJlYWRGaWxlU3luYyB9IGZyb20gJ25vZGU6ZnMnXG5pbXBvcnQgeyBSRVBPX1JPT1QsIGRpc2NvdmVyU3BhUmVnaXN0cnkgfSBmcm9tICcuL2Rpc2NvdmVyLm1qcydcbmltcG9ydCB7IHJlYWRCdWlsZENvbmZpZywgcmVuZGVyR2FsbGVyeSB9IGZyb20gJy4uL2dlbmVyYXRlLWdhbGxlcnkubWpzJ1xuaW1wb3J0IHsgVFJFRV9OQU1FIH0gZnJvbSAnLi4vX3RyZWUtbmFtZS5tanMnXG5pbXBvcnQgeyBwcm9maWxlTWV0YUZpZWxkcywgYnVuZGxlU3RhZ2UsIGJ1bmRsZVZpc2liaWxpdHkgfSBmcm9tICcuLi9wcm9maWxlLW1ldGEubWpzJ1xuXG4vLyBcdTI1MDBcdTI1MDBcdTI1MDAgREVWIHBsdWdpbiBnYWxsZXJ5IFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxuLy8gYGJ1biB4IHZpdGVgIChkZXYpIHNlcnZlcyB0aGUgcGx1Z2luIGdhbGxlcnkgYXQgYC9gIFx1MjAxNCB0aGUgc2FtZSBwYWdlIGBidW4gcnVuIGJ1aWxkYFxuLy8gd3JpdGVzIHRvIHB1YmxpYy9pbmRleC5odG1sIFx1MjAxNCBvdmVyIGV2ZXJ5IHByb2ZpbGUgRElTQ09WRVJFRCBhY3Jvc3MgcGx1Z2luLWRlc2lnbnMvKi8uXG4vLyBDaG9vc2luZyBhIG1hcCBsYXp5LWltcG9ydHMgdGhhdCBidW5kbGUncyBkZXYgZW50cnkgKHJlZ2lzdGVyaW5nIGl0cyBjdXN0b20gZWxlbWVudClcbi8vIGFuZCBtb3VudHMgaXQsIHdpdGggdGhlIGRldiBNYXBib3ggdG9rZW4gKFZJVEVfTUFQQk9YX1RPS0VOKSBhcyB0aGUgYmFrZWQgcnVuZyBvZlxuLy8gdGhlIHRva2VuIGxhZGRlciBzbyBtYXBzIGp1c3Qgd29yay4gRGV2LW9ubHkgKGFwcGx5OidzZXJ2ZScpOyB0aGUgYnVpbGQgaXMgdW50b3VjaGVkLlxuXG4vLyBTaGFyZWQgYXNzZXQgcm9vdCBmb3IgdGhlIGRldiBwbHVnaW4gZ2FsbGVyeS4gRGF0YS1kcml2ZW4gcHJvZmlsZXMgKGNvbm5lY3Rpdml0eS1tYXAsXG4vLyByZXNvdXJjZXMtbWFwLCBjaXRpZXMtbWFwLCBwb3N0ZXIgd2FsbHMsIHRhYmxlcykgZmV0Y2ggYGFzc2V0c0Jhc2UgKyAnL3RhYmxlcy8qLmpzb24nYFxuLy8gYW5kIGAnL2JvdW5kYXJpZXMvKi5nZW9qc29uJ2AuIHB1YmxpY0RpciBpcyBmYWxzZSBPTiBQVVJQT1NFIChhIGJ1bmRsZSBidWlsZCBtdXN0IG5ldmVyXG4vLyBpbmxpbmUgcHVibGljLyksIHNvIGRldiBoYXMgdG8gc2VydmUgdGhlIGFzc2V0IHRyZWUgZXhwbGljaXRseSwgdGhlIHdheSB0aGUgYnVpbHQgc2l0ZVxuLy8gZG9lczogcHVibGljL2Fzc2V0cyBmaXJzdCAoZXhhY3RseSB3aGF0IGdlbmVyYXRlLXRyZWUgc2hpcHMpLCBlbHNlIHRoZSB0cmFja2VkIGRhdGEvIHNvdXJjZSwgZWxzZSB0aGUgcGVyLWJ1bmRsZSBzb3VyY2Vcbi8vIG9mIHRydXRoIHBsdWdpbi1kZXNpZ25zLzxidW5kbGU+L2RhdGEvPHJlbD4gd2hlbiBwdWJsaWMvIGhhcyBiZWVuIGNsZWFuZWQuXG5jb25zdCBERVZfQVNTRVRfTUlNRSA9IHtcbiAgJy5qc29uJzogJ2FwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9dXRmLTgnLCAnLmdlb2pzb24nOiAnYXBwbGljYXRpb24vZ2VvK2pzb247IGNoYXJzZXQ9dXRmLTgnLFxuICAnLmpzJzogJ3RleHQvamF2YXNjcmlwdDsgY2hhcnNldD11dGYtOCcsICcuY3NzJzogJ3RleHQvY3NzOyBjaGFyc2V0PXV0Zi04JywgJy5jc3YnOiAndGV4dC9jc3Y7IGNoYXJzZXQ9dXRmLTgnLFxuICAnLnR4dCc6ICd0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04JywgJy5odG1sJzogJ3RleHQvaHRtbDsgY2hhcnNldD11dGYtOCcsICcuc3ZnJzogJ2ltYWdlL3N2Zyt4bWwnLFxuICAnLnBuZyc6ICdpbWFnZS9wbmcnLCAnLndlYnAnOiAnaW1hZ2Uvd2VicCcsICcuanBnJzogJ2ltYWdlL2pwZWcnLCAnLmpwZWcnOiAnaW1hZ2UvanBlZycsICcuZ2lmJzogJ2ltYWdlL2dpZicsXG4gICcud29mZjInOiAnZm9udC93b2ZmMicsICcud29mZic6ICdmb250L3dvZmYnLCAnLnBkZic6ICdhcHBsaWNhdGlvbi9wZGYnLFxufVxuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVEZXZBc3NldChyZWwsIHJvb3QgPSBSRVBPX1JPT1QpIHtcbiAgY29uc3QgaXNGaWxlID0gKHApID0+IGV4aXN0c1N5bmMocCkgJiYgc3RhdFN5bmMocCkuaXNGaWxlKClcbiAgLy8gVGhlIGJ1aWx0IGNvcHkgbGl2ZXMgSU5TSURFIHRoZSBvdXRwdXQgZm9sZGVyIChwdWJsaWMvPHRyZWU+L2Fzc2V0cykgXHUyMDE0IHB1YmxpYy8gaG9sZHMgbm90aGluZyBlbHNlXG4gIC8vIHNpbmNlIEJVSUxELU9VVFBVVC1JUy1PTkUtRk9MREVSLiBUaGUgZGF0YS8gZmFsbGJhY2sgYmVsb3cga2VlcHMgYSBmcmVzaCBjbG9uZSB3b3JraW5nIHVuYnVpbHQuXG4gIC8vIGRhdGEvPHJlbD4gRklSU1Q6IGl0IGlzIHRoZSB0cmFja2VkIHNvdXJjZSBvZiB0cnV0aCB0aGF0IHRoZSBidWlsdCBjb3B5IG1pcnJvcnMuIFNlcnZpbmcgdGhlIGJ1aWx0IGNvcHlcbiAgLy8gZmlyc3QgbWVhbnQgYSBkYXRhLyBlZGl0IHNob3dlZCBPTEQgZGF0YSB1bmRlciB0aGUgZGV2IHNlcnZlciB1bnRpbCBzb21lb25lIHJlYnVpbHQgKDczIGZpbGVzIGhhdmVcbiAgLy8gYm90aDsgZm91bmQgYnkgdGhlIG11bHRpcGxheWVyIGRldi1zZXJ2ZXIgc3Bpa2UsIDIwMjYtMDktMjYpLiBBIGRldiBzZXJ2ZXIgc2hvd3MgdGhlIHNvdXJjZS5cbiAgY29uc3Qgc291cmNlID0gcmVzb2x2ZShyb290LCAnZGF0YScsIHJlbClcbiAgaWYgKGlzRmlsZShzb3VyY2UpKSByZXR1cm4gc291cmNlXG4gIC8vIFRoZSBidWlsdCBjb3B5IChwdWJsaWMvPHRyZWU+L2Fzc2V0cykgc3RpbGwgYW5zd2VycyBmb3Igd2hhdCBleGlzdHMgb25seSB0aGVyZTogZmlsZXMgZ2VuZXJhdGUtdHJlZVxuICAvLyBkZXJpdmVzIHJhdGhlciB0aGFuIGNvcGllcy5cbiAgY29uc3Qgc2hpcHBlZCA9IHJlc29sdmUocm9vdCwgJ3B1YmxpYycsIFRSRUVfTkFNRSwgJ2Fzc2V0cycsIHJlbClcbiAgaWYgKGlzRmlsZShzaGlwcGVkKSkgcmV0dXJuIHNoaXBwZWRcbiAgY29uc3QgcHJvZmlsZXMgPSByZXNvbHZlKHJvb3QsICdwbHVnaW4tZGVzaWducycpXG4gIGZvciAoY29uc3QgbmFtZSBvZiByZWFkZGlyU3luYyhwcm9maWxlcykpIHtcbiAgICBpZiAobmFtZS5zdGFydHNXaXRoKCdfJykgfHwgbmFtZS5zdGFydHNXaXRoKCcuJykpIGNvbnRpbnVlXG4gICAgY29uc3QgY2FuZCA9IHJlc29sdmUocHJvZmlsZXMsIG5hbWUsICdkYXRhJywgcmVsKVxuICAgIGlmIChpc0ZpbGUoY2FuZCkpIHJldHVybiBjYW5kXG4gIH1cbiAgcmV0dXJuIG51bGxcbn1cblxuLy8gVGhlIG1hbmlmZXN0LXNoYXBlZCBtb2RlbCAoc2NoZW1hIGRveGEtbWFwcy1tYW5pZmVzdEAxOiBidW5kbGVzIFx1MjE5MiBwcm9maWxlcyBcdTIxOTIgaW5zdGFuY2VzKVxuLy8gdGhlIGdhbGxlcnkgcmVuZGVycywgZnJvbSB0aGUgZGlzY292ZXJ5IHJlZ2lzdHJ5LiBCdW5kbGVzIGFuZCBwcm9maWxlcyBhcmUgb3JkZXJlZFxuLy8gYWxwaGFiZXRpY2FsbHksIGFzIGdlbmVyYXRlLXRyZWUgb3JkZXJzIHRoZSBtYW5pZmVzdDsgYSBwcmVzZXQgcHJvZmlsZSBrZWVwcyBpdHMgb3duXG4vLyByb3cgYWJvdmUgaXRzIGluc3RhbmNlcywgZXhhY3RseSBhcyB0aGUgYnVpbHQgcGFnZSBsaXN0cyBpdC5cbi8vICAgc2NyaXB0VXJsICB0aGUgYnVuZGxlJ3MgZGV2IGVudHJ5IFx1MjAxNCB0aGUgcGFnZSBpbXBvcnRzIGl0IChubyBJSUZFIGV4aXN0cyB1bmRlciB0aGUgZGV2IHNlcnZlcilcbi8vICAgaWZyYW1lVXJsICB0aGlzIGdhbGxlcnkncyBvd24gZGVlcCBsaW5rIFx1MjAxNCB0aGUgb25seSBwYWdlIHVuZGVyIHRoZSBkZXYgc2VydmVyIHRoYXQgc2hvd3Ncbi8vICAgICAgICAgICAgICBleGFjdGx5IHRoaXMgbWFwICh0aGUgYnVpbHQgbGVhZiBwYWdlcyBkbyBub3QgZXhpc3QgaGVyZSk7IE9wZW4gcGFnZSBhbmQgdGhlXG4vLyAgICAgICAgICAgICAgbWFwcycgU2hhcmUgYnV0dG9uIHVzZSBpdCwgc28gYSBzaGFyZWQgbGluayByZW9wZW5zIHRoZSBzYW1lIG1hcFxuLy8gICBlbWJlZCAgICAgIHRoZSBzbmlwcGV0cyB0aGUgYnVpbGQgd2lsbCB3cml0ZSAoZ2VuZXJhdGUtdHJlZSdzIHRlbXBsYXRlLCB0cmVlLXJlbGF0aXZlO1xuLy8gICAgICAgICAgICAgIGludGVncml0eSBvbmx5IGV4aXN0cyBhZnRlciBhIGJ1aWxkKSwgc28gQ29weSBlbWJlZCBwcmV2aWV3cyB3aGF0IHNoaXBzXG5mdW5jdGlvbiByZWFkQ29tcG9zZXMoYnVuZGxlLCBwcm9maWxlKSB7XG4gIHRyeSB7XG4gICAgY29uc3QgbWV0YSA9IEpTT04ucGFyc2UocmVhZEZpbGVTeW5jKHJlc29sdmUoUkVQT19ST09ULCAncGx1Z2luLWRlc2lnbnMnLCBidW5kbGUsIGAke3Byb2ZpbGV9Lm1ldGEuanNvbmApLCAndXRmOCcpKVxuICAgIHJldHVybiBBcnJheS5pc0FycmF5KG1ldGE/LmNvbXBvc2VzKSA/IG1ldGEuY29tcG9zZXMubWFwKFN0cmluZykuZmlsdGVyKEJvb2xlYW4pIDogW11cbiAgfSBjYXRjaCB7IHJldHVybiBbXSB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnYWxsZXJ5TW9kZWwocmVnKSB7XG4gIGNvbnN0IGlmcmFtZSA9ICh1KSA9PiBgPGlmcmFtZSBzcmM9XCIke3V9P3V0bV9zb3VyY2U9WU9VUl9TT1VSQ0VcIiB3aWR0aD1cIjEwMCVcIiBoZWlnaHQ9XCI2MDBcIiBzdHlsZT1cImJvcmRlcjpub25lO2JvcmRlci1yYWRpdXM6MTJweDtcIiBhbGxvd2Z1bGxzY3JlZW4+PC9pZnJhbWU+YFxuICAvLyBBIFJFQUwgREVWIExFQUYsIG5vdCBhIGhhc2ggZGVlcC1saW5rIGludG8gdGhlIGdhbGxlcnkuXG4gIC8vXG4gIC8vIFRISVMgVVNFRCBUTyBCRSBgJy8jLycgKyBwYXJ0cy5qb2luKCcvJylgIFx1MjAxNCBhIGhhc2ggcm91dGUgaW50byB0aGUgZ2FsbGVyeSBQQUdFLiBUaGF0IHdhc1xuICAvLyBjb2hlcmVudCB3aGlsZSBgL2AgV0FTIHRoZSBnYWxsZXJ5LCBidXQgdGhlIHN0dWRpbyBuZXN0cyBtYXAgcHJvZmlsZXMgaW4gYSBsYXp5IGlmcmFtZSBwb2ludGVkXG4gIC8vIGF0IGV4YWN0bHkgdGhpcyBVUkwgKHBsdWdpbi1zdHVkaW8udnVlOjI1LCBtb2RlICdpZnJhbWUnKSwgc28gZXZlcnkgbWFwIHRhYiB3YXMgaWZyYW1pbmcgdGhlXG4gIC8vIGdhbGxlcnkuIFRoZSBzdGFnaW5nIGJsdXJiIFx1MjAxNCBcIk9uZSBzaGFyZWQgY29yZSwgb25lIGJ1aWxkLCBtYW55IHBhc3RlLWFueXdoZXJlIG1hcHMuLi5cIiBcdTIwMTRcbiAgLy8gcmVuZGVyZWQgSU5TSURFIGVhY2ggcGx1Z2luIHBhbmUsIGFuZCB0aGUgc3R1ZGlvIHdhcyByZXBvcnRlZCBhcyBzdGlsbCBsb2FkaW5nIGFuIEhUTUwgcGFnZVxuICAvLyB3aXRoIHRoYXQgdGV4dCBmb3IgZWFjaCBwbHVnaW4uIEl0IHdhczogdGhlIGdhbGxlcnksIHJlY3Vyc2l2ZWx5LCBvbmNlIHBlciBtYXAgdGFiLlxuICAvL1xuICAvLyBgL19fbGVhZi88YnVuZGxlPi88cHJvZmlsZT5bLzxpbnN0YW5jZT5dYCBpbnN0ZWFkIHNlcnZlcyBhIG1pbmltYWwgcGFnZSB0aGF0IG1vdW50cyBPTkUgZWxlbWVudFxuICAvLyBhbmQgbm90aGluZyBlbHNlIFx1MjAxNCB0aGUgZGV2IGVxdWl2YWxlbnQgb2YgdGhlIGJ1aWx0IHRyZWUncyA8YnVuZGxlPi88cHJvZmlsZT4vaW5kZXguaHRtbCwgd2hpY2hcbiAgLy8gaXMgd2hhdCB0aGlzIFVSTCBtZWFucyBpbiBwcm9kdWN0aW9uLiBTYW1lIGNvbnRyYWN0LCBzbyB0aGUgc3R1ZGlvIGJlaGF2ZXMgaWRlbnRpY2FsbHkgaW4gYm90aC5cbiAgY29uc3QgbGluayA9ICguLi5wYXJ0cykgPT4gJy9fX2xlYWYvJyArIHBhcnRzLm1hcChlbmNvZGVVUklDb21wb25lbnQpLmpvaW4oJy8nKVxuICAvLyBHQVRFRCBidW5kbGVzICh2aXRlLmRveGEtbWFwcy1idWlsZC1jb25maWcuanNvbiBgZ2F0ZWRQcm9maWxlc2AsIGUuZy4ga2V5LWNpdGllcykgYXJlIHdpdGhoZWxkXG4gIC8vIGZyb20gZXZlcnkgcHVibGljIHN1cmZhY2UgdGhlIEJVSUxEIGVtaXRzLiBUaGUgZGV2IG1vZGVsIGxpc3RlZCB0aGVtIGFueXdheSwgc28gdGhlIHN0dWRpbyBhbmQgdGhlXG4gIC8vIFJlc2VhcmNoIEdhbGxlcnkncyBFeHBlcmltZW50YWwgc2hlbGYgc2hvd2VkIHVuZGVyIHRoZSBkZXYgc2VydmVyIFx1MjAxNCB3aGljaCBpcyB3aGF0IERYIHJ1bnMgZmlyc3RcbiAgLy8gYWZ0ZXIgY2xvbmluZyBcdTIwMTQgYSBwbHVnaW4gdGhlIGJ1aWx0IHRyZWUgZGVsaWJlcmF0ZWx5IGhpZGVzLiBTYW1lIHJ1bGUgaGVyZSwgc28gZGV2ID09IGJ1aWx0LlxuICBsZXQgZ2F0ZWQgPSBuZXcgU2V0KClcbiAgLy8gUmVhZCBmcm9tIHRoZSBjb25maWcgZmlsZSBpdHNlbGYsIGFzIGdlbmVyYXRlLXRyZWUgZG9lczogcmVhZEJ1aWxkQ29uZmlnKCkgcmV0dXJucyBhIHByb2plY3Rpb25cbiAgLy8gdGhhdCBkb2VzIG5vdCBjYXJyeSBnYXRlZFByb2ZpbGVzLlxuICB0cnkge1xuICAgIGNvbnN0IGNmZyA9IEpTT04ucGFyc2UocmVhZEZpbGVTeW5jKHJlc29sdmUoUkVQT19ST09ULCAndml0ZS5kb3hhLW1hcHMtYnVpbGQtY29uZmlnLmpzb24nKSwgJ3V0ZjgnKSlcbiAgICBpZiAoQXJyYXkuaXNBcnJheShjZmcuZ2F0ZWRQcm9maWxlcykpIGdhdGVkID0gbmV3IFNldChjZmcuZ2F0ZWRQcm9maWxlcy5tYXAoU3RyaW5nKSlcbiAgfSBjYXRjaCB7IC8qIG5vIGNvbmZpZzogZ2F0ZSBub3RoaW5nICovIH1cbiAgY29uc3QgYnVuZGxlcyA9IFsuLi5yZWddLmZpbHRlcigoYikgPT4gIWdhdGVkLmhhcyhiLmJ1bmRsZSkpLnNvcnQoKGEsIGIpID0+IGEuYnVuZGxlLmxvY2FsZUNvbXBhcmUoYi5idW5kbGUpKS5tYXAoKGIpID0+IHtcbiAgICBjb25zdCBzY3JpcHRVcmwgPSBgL3BsdWdpbi1kZXNpZ25zLyR7Yi5idW5kbGV9L2luZGV4LmpzYFxuICAgIGNvbnN0IHByZXNldHMgPSBuZXcgTWFwKCkgICAvLyBwcm9maWxlIFx1MjE5MiBpdHMgcHJlc2V0IGluc3RhbmNlcyAoZW1wdHkgZm9yIGV2ZXJ5IG90aGVyIGtpbmQpXG4gICAgY29uc3QgdHlwZU9mID0gbmV3IE1hcCgpICAgIC8vIHByb2ZpbGUgXHUyMTkyIGNvbXBvc2l0aW9uIHRpZXIgbWFjaGluZSBrZXkgKHNpbmdsZSBcdTIwMjYgbmVzdGVkLW1mZS1zcGEpXG4gICAgZm9yIChjb25zdCBpdCBvZiBiLml0ZW1zKSB7XG4gICAgICBpZiAoIXByZXNldHMuaGFzKGl0LnByb2ZpbGUpKSBwcmVzZXRzLnNldChpdC5wcm9maWxlLCBbXSlcbiAgICAgIGlmICghdHlwZU9mLmhhcyhpdC5wcm9maWxlKSkgdHlwZU9mLnNldChpdC5wcm9maWxlLCBpdC50eXBlKVxuICAgICAgaWYgKGl0LnR5cGUgPT09ICdwYXJhbWV0ZXJpemVkJykgcHJlc2V0cy5nZXQoaXQucHJvZmlsZSkucHVzaChpdClcbiAgICB9XG4gICAgY29uc3QgcHJvZmlsZXMgPSBbLi4ucHJlc2V0cy5rZXlzKCldLnNvcnQoKS5tYXAoKHByb2ZpbGUpID0+IHtcbiAgICAgIGNvbnN0IHAgPSB7XG4gICAgICAgIHByb2ZpbGUsIGZpbGU6IGAke3Byb2ZpbGV9LnZ1ZWAsIGRlc2NyaXB0aW9uOiAnJywgZWxlbWVudDogYi50YWcsXG4gICAgICAgIHR5cGU6IHR5cGVPZi5nZXQocHJvZmlsZSkgfHwgJ3NpbmdsZScsXG4gICAgICAgIC4uLnByb2ZpbGVNZXRhRmllbGRzKHJlc29sdmUoUkVQT19ST09ULCAncGx1Z2luLWRlc2lnbnMnLCBiLmJ1bmRsZSksIHByb2ZpbGUpLCAgIC8vIHNhbWUgYXMgdGhlIGJ1aWx0IG1hbmlmZXN0XG4gICAgICAgIGlmcmFtZVVybDogbGluayhiLmJ1bmRsZSwgcHJvZmlsZSksIHNjcmlwdFVybCxcbiAgICAgICAgZW1iZWQ6IHtcbiAgICAgICAgICBpZnJhbWU6IGlmcmFtZShgLi8ke2IuYnVuZGxlfS8ke3Byb2ZpbGV9L2luZGV4Lmh0bWxgKSxcbiAgICAgICAgICBzY3JpcHQ6IGA8c2NyaXB0IHNyYz1cIi4vJHtiLmJ1bmRsZX0vJHtiLmJ1bmRsZX0uanNcIj48L3NjcmlwdD5cXG48JHtiLnRhZ30gcHJvZmlsZS1jb25maWc9JyR7SlNPTi5zdHJpbmdpZnkoeyBwcm9maWxlLCB0azogJ1lPVVJfTUFQQk9YX1RPS0VOJywgdXRtU291cmNlOiAnWU9VUl9TT1VSQ0UnIH0pfSc+PC8ke2IudGFnfT5gLFxuICAgICAgICB9LFxuICAgICAgfVxuICAgICAgY29uc3QgaW5zdGFuY2VzID0gcHJlc2V0cy5nZXQocHJvZmlsZSkubWFwKChpdCkgPT4gKHtcbiAgICAgICAgaWQ6IGl0LmlkLCB0aXRsZTogaXQubGFiZWwsIGFwaUJhc2VVcmw6IGl0LmFwaUJhc2VVcmwgfHwgJycsXG4gICAgICAgIHByb3BzOiB7IHByb2ZpbGUsIC4uLihpdC5wcm9wcyB8fCB7fSkgfSwgZWxlbWVudDogYi50YWcsXG4gICAgICAgIGlmcmFtZVVybDogbGluayhiLmJ1bmRsZSwgcHJvZmlsZSwgaXQuaWQpLFxuICAgICAgICBlbWJlZDogeyBpZnJhbWU6IGlmcmFtZShgLi8ke2IuYnVuZGxlfS8ke3Byb2ZpbGV9LyR7aXQuaWR9L2luZGV4Lmh0bWxgKSB9LFxuICAgICAgfSkpXG4gICAgICBpZiAoaW5zdGFuY2VzLmxlbmd0aCkgcC5pbnN0YW5jZXMgPSBpbnN0YW5jZXNcbiAgICAgIHJldHVybiBwXG4gICAgfSlcbiAgICAvLyBDT01QT1NJVElPTiBFREdFUywgdGhlIHNhbWUgc291cmNlIGFuZCBzaGFwZSBnZW5lcmF0ZS10cmVlIHB1Ymxpc2hlczogdGhlIHVuaW9uIG9mIGV2ZXJ5XG4gICAgLy8gcHJvZmlsZSdzIDxwcm9maWxlPi5tZXRhLmpzb24gYGNvbXBvc2VzYCwgYXQgYnVuZGxlIGxldmVsLCBvbWl0dGVkIHdoZW4gbm9uZS4gVGhpcyBtb2RlbCB1c2VkXG4gICAgLy8gdG8gZHJvcCB0aGVtLCBzbyB1bmRlciB0aGUgZGV2IHNlcnZlciBcdTIwMTQgd2hpY2ggaXMgd2hhdCBhIGxhcHRvcCBydW5zIFx1MjAxNCB0aGUgc3R1ZGlvJ3NcbiAgICAvLyBDb21wb3NlZC1vZiBwYW5lbCBhbmQgY29tcG9zaXRpb24gdHJlZXMgd2VyZSBzaWxlbnRseSBlbXB0eSBmb3IgZXZlcnkgY29tcG9zaXRlLlxuICAgIGNvbnN0IGNvbXBvc2VzID0gWy4uLm5ldyBTZXQoWy4uLnByZXNldHMua2V5cygpXS5mbGF0TWFwKChwcm9maWxlKSA9PiByZWFkQ29tcG9zZXMoYi5idW5kbGUsIHByb2ZpbGUpKSldXG4gICAgcmV0dXJuIHsgYnVuZGxlOiBiLmJ1bmRsZSwgc2NyaXB0VXJsLCBpbnRlZ3JpdHk6ICcnLCBlbGVtZW50czogW2IudGFnXSwgc3RhZ2U6IGJ1bmRsZVN0YWdlKHByb2ZpbGVzKSwgLi4uKGJ1bmRsZVZpc2liaWxpdHkocHJvZmlsZXMpID09PSAncHVibGljJyA/IHsgdmlzaWJpbGl0eTogJ3B1YmxpYycgfSA6IHt9KSwgLi4uKGNvbXBvc2VzLmxlbmd0aCA/IHsgY29tcG9zZXMgfSA6IHt9KSwgcHJvZmlsZXMgfVxuICB9KVxuICByZXR1cm4ge1xuICAgIHNjaGVtYTogJ2RveGEtbWFwcy1tYW5pZmVzdEAxJywgZ2VuZXJhdGVkRnJvbTogJ3BsdWdpbi1kZXNpZ25zLyovKi52dWUgKGRldiBkaXNjb3ZlcnkpJywgZW1iZWRCYXNlOiAnLicsXG4gICAgYnVuZGxlQ291bnQ6IGJ1bmRsZXMubGVuZ3RoLCBwcm9maWxlQ291bnQ6IGJ1bmRsZXMucmVkdWNlKChuLCBiKSA9PiBuICsgYi5wcm9maWxlcy5sZW5ndGgsIDApLCBidW5kbGVzLFxuICB9XG59XG5cbi8vIFx1MjUwMFx1MjUwMCBUSEUgUFJPRFVDVElPTiBFTUJFRCBVUkwsIEFOU1dFUkVEIEJZIFRIRSBERVYgU0VSVkVSIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxuLy8gVGhlIG1hbmlmZXN0IGFkdmVydGlzZXMsIGFuZCBhIHBlcnNvbiBjb3BpZXMsIHRyZWUtcmVsYXRpdmUgZW1iZWQgVVJMcyBvZiB0aGUgc2hhcGVcbi8vIGA8YnVuZGxlPi88cHJvZmlsZT4vaW5kZXguaHRtbGAgYW5kIGA8YnVuZGxlPi88cHJvZmlsZT4vPGluc3RhbmNlPi9pbmRleC5odG1sYCBcdTIwMTQgc2VydmVkIGluXG4vLyBwcm9kdWN0aW9uIG91dCBvZiBwdWJsaWMvPHRyZWVOYW1lPi8uIFRoZSBkZXYgc2VydmVyIGhhZCBOTyByb3V0ZSBmb3IgdGhhdCBzaGFwZTsgaXQgc2VydmVkIGl0c1xuLy8gbGVhZiBzdGFuZC1pbiBhdCBgL19fbGVhZi88YnVuZGxlPi88cHJvZmlsZT5bLzxpbnN0YW5jZT5dYCBvbmx5LlxuLy9cbi8vIFJFUE9SVEVEIDIwMjYtMDktMjM6IGFuIGVtYmVkIFVSTCwgY29waWVkIGFuZCBvcGVuZWQgYWdhaW5zdCBhIGRldiBzZXJ2ZXIgXHUyMDE0XG4vLyAgICAgaHR0cDovL2xvY2FsaG9zdDo1MTc0L2RveGEtc2ltcGxlLW1hcC9kb3hhLXNpbXBsZS1tYXAvcHJheWVyL2luZGV4Lmh0bWxcbi8vIFx1MjAxNCBkaWQgbm90IHdvcmsuIFRoZSBsZWFmIGlzIHJlYWwgKHRoYXQgZXhhY3QgcGF0aCBzZXJ2ZXMgMjAwIGZyb20gdGhlIGJ1aWx0IHRyZWUpIGFuZFxuLy8gdGhlIGVtYmVkIGlzIGhlYWx0aHkgKGl0IG1vdW50cyBhdCA3MDBweCBpbiBhIHJlYWwgaWZyYW1lKS4gVGhlIGRldiBzZXJ2ZXIgc2ltcGx5IGhhZCBubyByb3V0ZS5cbi8vXG4vLyBcdTI2MDUgQU5EIElUIEZBSUxFRCBTSUxFTlRMWSwgd2hpY2ggaXMgdGhlIHBhcnQgdGhhdCBjb3N0cyBob3Vycy4gV2l0aCBubyByb3V0ZSwgVml0ZSdzIFNQQSBmYWxsYmFja1xuLy8gYW5zd2VycyBhbiB1bmtub3duIHBhdGggd2l0aCB0aGUgU1RVRElPJ1MgSFRNTCBhdCBzdGF0dXMgMjAwLiBUaGUgcmVhZGVyIGFza3MgZm9yIG9uZSBtYXAgYW5kXG4vLyByZWNlaXZlcyBhIGRpZmZlcmVudCwgZW50aXJlbHkgd29ya2luZyBwYWdlLCB3aXRoIG5vIDQwNCBhbmQgbm90aGluZyBpbiB0aGUgY29uc29sZS4gVGhhdCBpcyB0aGVcbi8vIHNhbWUgZm91ci1zdXJmYWNlIGNsYXNzIGFzIHRoZSB0d28gb3RoZXIgYnVncyBmaXhlZCB0aGUgc2FtZSBkYXkgKGEgbWFuaWZlc3QgNDA0IHJldHVybmluZyBIVE1MO1xuLy8gYSAuLi8uLi8gY2hpbGQgcGF0aCB0aGF0IDQwNCdkIG9ubHkgZnJvbSBhIGRlZXBlciBsZWFmKSBcdTIwMTQgc2VlIHRoZSBhc3NldHNCYXNlVXJsIGFuZFxuLy8gTUFQX0FQUF9BUElfVVJMIG5vdGVzIGJlbG93LCBib3RoIG9mIHdoaWNoIGFyZSB0aGF0IHNoYXBlLlxuLy9cbi8vIFRoZSBmaXggUkVXUklURVMgb250byB0aGUgZXhpc3RpbmcgYC9fX2xlYWYvYCByZW5kZXJlciByYXRoZXIgdGhhbiBjb3B5aW5nIGl0LiBUd28gcmVuZGVyZXJzXG4vLyB3b3VsZCBkcmlmdCwgYW5kIHRoZSBlbnRpcmUgcG9pbnQgb2YgdGhlIHJvdXRlIGlzIHRoYXQgb25lIGVtYmVkIFVSTCByZW5kZXJzIHRoZSBTQU1FIHRoaW5nIGluXG4vLyBib3RoIGVudmlyb25tZW50cyBcdTIwMTQgYSBzZWNvbmQgY29weSB3b3VsZCBxdWlldGx5IG1ha2UgdGhhdCBmYWxzZS5cbi8vXG4vLyBCb3RoIHByZWZpeGVzIGFyZSBhY2NlcHRlZCBiZWNhdXNlIGJvdGggYXJlIHJlYWw6XG4vLyAgIC9kb3hhLXNpbXBsZS1tYXAvZG94YS1zaW1wbGUtbWFwL3ByYXllci9pbmRleC5odG1sICAgICAgICAgICAgICBiYXJlLCB0cmVlLXJlbGF0aXZlIFx1MjAxNCB3aGF0IHRoZVxuLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFuaWZlc3QncyBgLi88Yj4vPHA+L1x1MjAyNmAgc25pcHBldFxuLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVjb21lcyB3aGVuIHBhc3RlZCBhdCB0aGUgcm9vdFxuLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHRoaXMgaXMgdGhlIFVSTCB0aGF0IHdhcyB1c2VkKVxuLy8gICAvZG94YS1tYXBzL2RveGEtc2ltcGxlLW1hcC9kb3hhLXNpbXBsZS1tYXAvcHJheWVyL2luZGV4Lmh0bWwgICAgcHJlZml4ZWQgXHUyMDE0IHRoZSBidWlsdCB0cmVlJ3Mgb3duXG4vLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoIHVuZGVyIHB1YmxpYy88dHJlZU5hbWU+L1xuLy8gYHRyZWVOYW1lYCBjb21lcyBmcm9tIHRoZSBidWlsZCBjb25maWcgKGBuYW1lYCwgZGVmYXVsdCAnZG94YS1tYXBzJyksIG5ldmVyIGhhcmRjb2RlZCwgc28gcmVuYW1pbmdcbi8vIHRoZSBvdXRwdXQgZm9sZGVyIGNhbm5vdCBzaWxlbnRseSBzdHJhbmQgdGhpcyByb3V0ZS5cbi8vXG4vLyBSZXR1cm5zIHRoZSByZXdyaXR0ZW4gYC9fX2xlYWYvXHUyMDI2YCBwYXRoLCBvciAnJyB3aGVuIHRoZSBVUkwgaXMgbm90IGFuIGVtYmVkIGxlYWYgVVJMICh0aGUgY29tbW9uXG4vLyBjYXNlIFx1MjAxNCBldmVyeSBvdGhlciByZXF1ZXN0IG11c3QgZmFsbCB0aHJvdWdoIHVudG91Y2hlZCkuXG5leHBvcnQgZnVuY3Rpb24gbGVhZlJld3JpdGUocGF0aCwgdHJlZU5hbWUgPSBUUkVFX05BTUUpIHtcbiAgaWYgKCFwYXRoLmVuZHNXaXRoKCcvaW5kZXguaHRtbCcpKSByZXR1cm4gJydcbiAgbGV0IHNlZ3MgPSBwYXRoLnNsaWNlKDAsIC0nL2luZGV4Lmh0bWwnLmxlbmd0aCkuc3BsaXQoJy8nKS5maWx0ZXIoQm9vbGVhbilcbiAgaWYgKHNlZ3NbMF0gPT09IHRyZWVOYW1lKSBzZWdzID0gc2Vncy5zbGljZSgxKSAgICAgICAgICAvLyB0b2xlcmF0ZSB0aGUgdHJlZS1wcmVmaXhlZCBmb3JtXG4gIC8vIDxidW5kbGU+Lzxwcm9maWxlPiBvciA8YnVuZGxlPi88cHJvZmlsZT4vPGluc3RhbmNlPi4gQW55dGhpbmcgZWxzZSBpcyBub3QgYSBsZWFmIFVSTDsgbGV0IGl0XG4gIC8vIGZhbGwgdGhyb3VnaCB0byBWaXRlIHJhdGhlciB0aGFuIGd1ZXNzIChhIHdyb25nIGd1ZXNzIGhlcmUgd291bGQgc2hhZG93IGEgcmVhbCBwYWdlKS5cbiAgaWYgKHNlZ3MubGVuZ3RoIDwgMiB8fCBzZWdzLmxlbmd0aCA+IDMpIHJldHVybiAnJ1xuICAvLyBUcmF2ZXJzYWwgZ3VhcmQgQkVGT1JFIHRoZSBzZWdtZW50cyBhcmUgcmUtam9pbmVkIGludG8gYSBVUkwgdGhlIGxlYWYgcm91dGUgd2lsbCBwYXJzZS4gVGhlXG4gIC8vIGxlYWYgcm91dGUgZ3VhcmRzIGFnYWluIG9uIGl0cyBvd24gZGVjb2RlZCBzZWdtZW50czsgdGhpcyBvbmUgc3RvcHMgYW4gZW5jb2RlZCBgLi5gIGZyb20gZXZlclxuICAvLyBiZWluZyBmb3JtZWQgaW50byB0aGUgcmV3cml0dGVuIHBhdGguXG4gIGZvciAoY29uc3QgcyBvZiBzZWdzKSB7XG4gICAgbGV0IGQgPSBzXG4gICAgdHJ5IHsgZCA9IGRlY29kZVVSSUNvbXBvbmVudChzKSB9IGNhdGNoIHsgcmV0dXJuICcnIH1cbiAgICBpZiAoIWQgfHwgZCA9PT0gJy4nIHx8IGQgPT09ICcuLicgfHwgZC5pbmNsdWRlcygnLycpIHx8IGQuaW5jbHVkZXMoJ1xcXFwnKSkgcmV0dXJuICcnXG4gIH1cbiAgcmV0dXJuICcvX19sZWFmLycgKyBzZWdzLmpvaW4oJy8nKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gYXV0b1NwYURldlBsdWdpbih0b2tlbiA9ICcnKSB7XG4gIC8vIE9uZSBnZW5lcmF0b3IgZm9yIGJvdGggZ2FsbGVyaWVzIChpbnRlcm5hbC9nZW5lcmF0ZS1nYWxsZXJ5Lm1qcyksIGRyaXZlbiBieSB0aGUgc2FtZSBidWlsZFxuICAvLyBjb25maWcgdGhlIGJ1aWx0IHBhZ2UgYmFrZXMuIFdoYXQgZGV2IGNoYW5nZXM6IHRoZSBtb2RlbCBjb21lcyBmcm9tIGRpc2NvdmVyeSwgdGhlIGxpdmVcbiAgLy8gbW9kZWwgcm91dGUgc3RhbmRzIGluIGZvciA8dHJlZT4vbWFuaWZlc3QuanNvbiwgc2hhcmVkIGFzc2V0cyBjb21lIGZyb20gdGhpcyBzZXJ2ZXInc1xuICAvLyAvYXNzZXRzIHJvdXRlLCBhbmQgdGhlIC5lbnYgdG9rZW4gaXMgdGhlIGJha2VkIHJ1bmcgb2YgdGhlIHRva2VuIGxhZGRlci5cbiAgY29uc3QgcGFnZSA9ICgpID0+IHtcbiAgICBjb25zdCBjZmcgPSByZWFkQnVpbGRDb25maWcoKVxuICAgIHJldHVybiByZW5kZXJHYWxsZXJ5KGdhbGxlcnlNb2RlbChkaXNjb3ZlclNwYVJlZ2lzdHJ5KCkpLCB7XG4gICAgICAvLyBcdTI2MDUgYC9fX3BsdWdpbi1nYWxsZXJ5YCwgQUJTT0xVVEUgXHUyMDE0IHRoZSBTQU1FIG1vdmUsIGFuZCB0aGUgc2FtZSBmaXgsIGFzIGFzc2V0c0Jhc2VVcmwgYmVsb3cuXG4gICAgICAvLyBgdHJlZWAgaXMgdGhlIGZvbGRlciB0aGUgbGl2ZSBtYW5pZmVzdCBpcyBmZXRjaGVkIGZyb20gYW5kIHRoYXQgcmVsYXRpdmUgcmVmcyByZXNvbHZlXG4gICAgICAvLyBhZ2FpbnN0LiBJdCB3YXMgJ19fcGx1Z2luLWdhbGxlcnknIChyZWxhdGl2ZSksIGNvcnJlY3Qgb25seSB3aGlsZSB0aGUgZ2FsbGVyeSBXQVMgdGhlIHJvb3RcbiAgICAgIC8vIHBhZ2UuIFRoZSBnYWxsZXJ5IG5vdyBsaXZlcyBhdCAvX19nYWxsZXJ5LCBzbyB0aGUgcmVsYXRpdmUgZm9ybSByZXNvbHZlcyBvbmUgbGV2ZWwgZGVlcGVyLlxuICAgICAgLy8gTUVBU1VSRUQgMjAyNi0wOS0yMiBvbiB0aGUgcnVubmluZyBkZXYgc2VydmVyOlxuICAgICAgLy8gICAgIC9fX3BsdWdpbi1nYWxsZXJ5L21hbmlmZXN0Lmpzb24gLi4uLi4uLi4uLi4uLiAyMDBcbiAgICAgIC8vICAgICAvX19nYWxsZXJ5L19fcGx1Z2luLWdhbGxlcnkvbWFuaWZlc3QuanNvbiAuLi4gNDA0XG4gICAgICAvLyBOYW1pbmcgaXQgYWJzb2x1dGVseSBtYWtlcyB0aGUgdmFsdWUgaW5kZXBlbmRlbnQgb2YgdGhlIHBhZ2UgZGVwdGggdGhlIGdhbGxlcnkgc2l0cyBhdCBcdTIwMTRcbiAgICAgIC8vIHdoaWNoIGlzIHRoZSB3aG9sZSByZWFzb24gYXNzZXRzQmFzZVVybCB3YXMgbWFkZSBhYnNvbHV0ZSBpbiB0aGUgc2FtZSBtb3ZlLiBUaGUgYnVpbHQgdHJlZVxuICAgICAgLy8gcGFzc2VzICcuLi88bmFtZT4nIGZvciB0aGUgc2FtZSByZWFzb247IGJvdGggbm93IHJlc29sdmUgdG8gdGhlIHJlYWwgdHJlZSByb290LlxuICAgICAgbW9kZTogJ2RldicsIHRpdGxlOiBjZmcudGl0bGUsIHRyZWU6ICcvX19wbHVnaW4tZ2FsbGVyeScsIHRva2VuVXJsOiBjZmcudG9rZW5VcmwsIHRva2VuOiB0b2tlbiB8fCBjZmcudG9rZW4sXG4gICAgICAvLyBcdTI2MDUgQUJTT0xVVEUsIE5PVCBSRUxBVElWRSBcdTIwMTQgdGhlIGdhbGxlcnkgbm8gbG9uZ2VyIGxpdmVzIGF0IHRoZSByb290LlxuICAgICAgLy8gVGhpcyB3YXMgJycgKHJlbGF0aXZlKSwgd2hpY2ggd2FzIGNvcnJlY3Qgd2hpbGUgdGhlIGdhbGxlcnkgV0FTIHRoZSByb290IHBhZ2U6IGEgbWFwIGFza2VkXG4gICAgICAvLyBmb3IgYXNzZXRzL3RhYmxlcy94Lmpzb24gYW5kIGdvdCAvYXNzZXRzL3RhYmxlcy94Lmpzb24uIFRoZSBnYWxsZXJ5IGhhcyBzaW5jZSBtb3ZlZCB0b1xuICAgICAgLy8gL19fZ2FsbGVyeSBzbyB0aGUgc3R1ZGlvIGNhbiBvd24gLywgYW5kIHRoZSBzYW1lIHJlbGF0aXZlIHBhdGggbm93IHJlc29sdmVzIG9uZSBsZXZlbCBkZWVwZXJcbiAgICAgIC8vIHRvIC9fX2dhbGxlcnkvYXNzZXRzLy4uLiBcdTIwMTQgd2hpY2ggNDA0cy4gTUVBU1VSRUQgMjAyNi0wOS0yMiBvbiB0aGUgcnVubmluZyBkZXYgc2VydmVyOlxuICAgICAgLy8gICAgIC9hc3NldHMvdGFibGVzL2ludGVybmV0LWJ5LWNvdW50cnkuanNvbiAuLi4uLi4uLi4uLi4uIDIwMFxuICAgICAgLy8gICAgIC9fX2dhbGxlcnkvYXNzZXRzL3RhYmxlcy9pbnRlcm5ldC1ieS1jb3VudHJ5Lmpzb24gLi4uIDQwNFxuICAgICAgLy8gTm90aGluZyBmYWlsZWQgYXQgbW92ZSB0aW1lOyB0aGUgYnJlYWthZ2Ugb25seSBhcHBlYXJzIHdoZW4gYSBtYXAgRkVUQ0hFUywgYW5kIGl0IHN1cmZhY2VzIGFzXG4gICAgICAvLyBcIkpTT04ucGFyc2U6IHVuZXhwZWN0ZWQgZW5kIG9mIGRhdGFcIiByYXRoZXIgdGhhbiBhcyBhIDQwNCwgYmVjYXVzZSBWaXRlIGFuc3dlcnMgYW4gdW5rbm93blxuICAgICAgLy8gcGF0aCB3aXRoIEhUTUwuIFRoZSBkZXYgc2VydmVyIHNlcnZlcyB0aGUgYXNzZXQgdHJlZSBhdCAvYXNzZXRzLyAoc2VlIHJlc29sdmVEZXZBc3NldCksIHNvXG4gICAgICAvLyBuYW1pbmcgaXQgYWJzb2x1dGVseSBtYWtlcyB0aGUgdmFsdWUgaW5kZXBlbmRlbnQgb2Ygd2hhdGV2ZXIgcGFnZSBkZXB0aCB0aGUgZ2FsbGVyeSBzaXRzIGF0LlxuICAgICAgYXBpQmFzZVVybDogY2ZnLmFwaUJhc2VVcmwsIGFzc2V0c0Jhc2VVcmw6ICcvYXNzZXRzJywgcWFXaWRnZXQ6IGNmZy5xYVdpZGdldCxcbiAgICB9KVxuICB9XG4gIGNvbnN0IGpzb24gPSAocmVzLCBib2R5LCBzdGF0dXMgPSAyMDApID0+IHtcbiAgICByZXMuc3RhdHVzQ29kZSA9IHN0YXR1c1xuICAgIHJlcy5zZXRIZWFkZXIoJ0NvbnRlbnQtVHlwZScsICdhcHBsaWNhdGlvbi9qc29uOyBjaGFyc2V0PXV0Zi04JylcbiAgICByZXMuc2V0SGVhZGVyKCdDYWNoZS1Db250cm9sJywgJ25vLWNhY2hlJylcbiAgICByZXMuZW5kKEpTT04uc3RyaW5naWZ5KGJvZHkpKVxuICB9XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ2RveGEtYXV0by1zcGEnLFxuICAgIGFwcGx5OiAnc2VydmUnLFxuICAgIGNvbmZpZ3VyZVNlcnZlcihzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlci5taWRkbGV3YXJlcy51c2UoKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgICAgIGNvbnN0IHJhd1BhdGggPSAocmVxLnVybCB8fCAnJykuc3BsaXQoJz8nKVswXVxuICAgICAgICAvLyBORVZFUiBUSEUgUkVQT1NJVE9SWSBJVFNFTEYuIFZpdGUgc2VydmVzIHRoZSBwcm9qZWN0IHJvb3QsIHNvIGEgcmVhY2hhYmxlIGRldiBzZXJ2ZXIgYW5zd2VyZWRcbiAgICAgICAgLy8gLy5naXQvXHUyMDI2IHdpdGggMjAwIFx1MjAxNCB0aGUgd2hvbGUgaGlzdG9yeSwgYW5kIGFueSBjcmVkZW50aWFsIGluIHRoZSByZW1vdGUgVVJMIChtdWx0aXBsYXllciBzcGlrZSxcbiAgICAgICAgLy8gMjAyNi0wOS0yNikuIFRoZXNlIHJvdXRlcyBydW4gYmVmb3JlIFZpdGUncyBvd24gY2hlY2tzLCBzbyB0aGUgcmVmdXNhbCBpcyBoZXJlLlxuICAgICAgICBsZXQgX2RlY29kZWQgPSByYXdQYXRoXG4gICAgICAgIHRyeSB7IF9kZWNvZGVkID0gZGVjb2RlVVJJQ29tcG9uZW50KHJhd1BhdGgpIH0gY2F0Y2ggeyAvKiBrZWVwIHJhdyAqLyB9XG4gICAgICAgIGlmICgvKF58XFwvKVxcLihnaXR8ZW52KShcXC98JCl8KF58XFwvKVxcLihtZXJnZS1xdWV1ZXxtYWluLWNhcHR1cmUpKFxcL3wkKS9pLnRlc3QoX2RlY29kZWQpKSB7IHJlcy5zdGF0dXNDb2RlID0gNDA0OyByZXR1cm4gcmVzLmVuZCgpIH1cbiAgICAgICAgLy8gQSBwcm9kdWN0aW9uIGVtYmVkIFVSTCAoYDxidW5kbGU+Lzxwcm9maWxlPlsvPGluc3RhbmNlPl0vaW5kZXguaHRtbGApIGlzIHJld3JpdHRlbiBvbnRvXG4gICAgICAgIC8vIHRoZSBgL19fbGVhZi9gIHJvdXRlIEJFRk9SRSBhbnkgYnJhbmNoIHJ1bnMsIHNvIHRoZSBleGlzdGluZyBsZWFmIHJlbmRlcmVyIGFuc3dlcnMgaXRcbiAgICAgICAgLy8gdW5jaGFuZ2VkIFx1MjAxNCBzZWUgbGVhZlJld3JpdGUgYWJvdmUgZm9yIHdoeSB0aGUgZGV2IHNlcnZlciBtdXN0IGtub3cgdGhpcyBzaGFwZSBhdCBhbGwuXG4gICAgICAgIC8vIFRoZSByZXdyaXRlIGlzIGFwcGxpZWQgdG8gYHBhdGhgICh3aGljaCBldmVyeSBicmFuY2ggcmVhZHMpIGFuZCB0byBgcmVxLnVybGAgKHNvIGFueXRoaW5nXG4gICAgICAgIC8vIGRvd25zdHJlYW0gc2VlcyBhIGNvbnNpc3RlbnQgcmVxdWVzdCk7IG5ldmVyIHZpYSBzZXJ2ZXIubWlkZGxld2FyZXMuaGFuZGxlKCksIHdoaWNoXG4gICAgICAgIC8vIHJlcGxheXMgdGhpcyBzYW1lIG1pZGRsZXdhcmUgYW5kIHdvdWxkIGxvb3AuXG4gICAgICAgIGxldCB0cmVlTmFtZSA9IFRSRUVfTkFNRVxuICAgICAgICB0cnkgeyB0cmVlTmFtZSA9IHJlYWRCdWlsZENvbmZpZygpPy5uYW1lIHx8IHRyZWVOYW1lIH0gY2F0Y2ggeyAvKiBrZWVwIHRoZSBkZWZhdWx0ICovIH1cbiAgICAgICAgY29uc3QgcmV3cml0dGVuID0gbGVhZlJld3JpdGUocmF3UGF0aCwgdHJlZU5hbWUpXG4gICAgICAgIGNvbnN0IHBhdGggPSByZXdyaXR0ZW4gfHwgcmF3UGF0aFxuICAgICAgICBpZiAocmV3cml0dGVuKSByZXEudXJsID0gcmV3cml0dGVuICsgKHJlcS51cmwgfHwgJycpLnNsaWNlKHJhd1BhdGgubGVuZ3RoKVxuICAgICAgICAvLyBUSEUgU0NSSVBUIEVNQkVELCBUT08gKHJlcG8sIDIwMjYtMDktMjgpOiB0aGUgY29weWFibGUgc25pcHBldCBgLi88Yj4vPGI+LmpzYCA0MDQnZCBvbiB0aGUgZGV2XG4gICAgICAgIC8vIHNlcnZlciBmb3IgZXZlcnkgcHJvZHVjdGlvbiBtYXAgd2hpbGUgdGhlIGlmcmFtZSBzbmlwcGV0IHdvcmtlZCB0aHJvdWdoIGxlYWZSZXdyaXRlLiBUaGUgYnVuZGxlXG4gICAgICAgIC8vIElJRkUgb25seSBleGlzdHMgQlVJTFQsIHNvIGl0IGlzIHNlcnZlZCBmcm9tIHB1YmxpYy88dHJlZT4vIFx1MjAxNCBiYXJlIG9yIHRyZWUtcHJlZml4ZWQsIGxpa2UgdGhlXG4gICAgICAgIC8vIGxlYWYuIE5vdCBidWlsdCB5ZXQ6IGEgcGxhaW4gNDA0IHRoYXQgc2F5cyBzbywgbmV2ZXIgVml0ZSdzIEhUTUwgZmFsbGJhY2suXG4gICAgICAgIGNvbnN0IGlpZmUgPSAvXlxcLyg/OihbXi9dKylcXC8pPyhbYS16MC05XVthLXowLTktXSopXFwvKFthLXowLTldW2EtejAtOS1dKilcXC5qcyQvLmV4ZWMocmF3UGF0aClcbiAgICAgICAgaWYgKGlpZmUgJiYgaWlmZVsyXSA9PT0gaWlmZVszXSAmJiAoIWlpZmVbMV0gfHwgaWlmZVsxXSA9PT0gdHJlZU5hbWUpKSB7XG4gICAgICAgICAgY29uc3QgZmlsZSA9IHJlc29sdmUoUkVQT19ST09ULCAncHVibGljJywgdHJlZU5hbWUsIGlpZmVbMl0sIGlpZmVbMl0gKyAnLmpzJylcbiAgICAgICAgICBpZiAoZXhpc3RzU3luYyhmaWxlKSkge1xuICAgICAgICAgICAgcmVzLnNldEhlYWRlcignQ29udGVudC1UeXBlJywgJ3RleHQvamF2YXNjcmlwdDsgY2hhcnNldD11dGYtOCcpXG4gICAgICAgICAgICByZXMuc2V0SGVhZGVyKCdDYWNoZS1Db250cm9sJywgJ25vLWNhY2hlJylcbiAgICAgICAgICAgIHJldHVybiByZXMuZW5kKHJlYWRGaWxlU3luYyhmaWxlKSlcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGV4aXN0c1N5bmMocmVzb2x2ZShSRVBPX1JPT1QsICdwbHVnaW4tZGVzaWducycsIGlpZmVbMl0pKSkge1xuICAgICAgICAgICAgcmVzLnN0YXR1c0NvZGUgPSA0MDRcbiAgICAgICAgICAgIHJlcy5zZXRIZWFkZXIoJ0NvbnRlbnQtVHlwZScsICd0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04JylcbiAgICAgICAgICAgIHJldHVybiByZXMuZW5kKGAke2lpZmVbMl19LmpzIGlzIG9ubHkgcHJvZHVjZWQgYnkgYSBidWlsZDogcnVuIFxcYGJ1biBydW4gYnVpbGRcXGAgKG9yIEJVTkRMRT0ke2lpZmVbMl19IGJ1biB4IHZpdGUgYnVpbGQpLCB0aGVuIHJlbG9hZC5gKVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyAvYXNzZXRzLyogXHUyMDE0IHNlZSByZXNvbHZlRGV2QXNzZXQuIEEgbWlzcyBpcyBhIFJFQUwgNDA0LCBuZXZlciBWaXRlJ3MgSFRNTFxuICAgICAgICAvLyBmYWxsYmFjazogSFRNTC1mb3ItSlNPTiBtYWRlIHRocmVlIG1hcHMgZGllIHNpbGVudGx5IGF0IEpTT04ucGFyc2UgYmVmb3JlXG4gICAgICAgIC8vIHRoZXkgZXZlciBjcmVhdGVkIGEgbWFwLCB3aXRoIG5vIGNvbnNvbGUgZXJyb3IgYW5kIG5vIGVycm9yIGNhcmQuXG4gICAgICAgIC8vIDx0cmVlPi9hc3NldHMvKiB0b286IGEgcGx1Z2luIG5lc3RlZCBpbiBhIGNhcC01IHNoZWxsIHJlc29sdmVzIGl0cyBhc3NldHMgYWdhaW5zdCB0aGUgdHJlZSBiYXNlXG4gICAgICAgIC8vIHRoZSBzaGVsbCBoYW5kcyBpdCAocGx1Z2luLXN0dWRpbyBwYXNzZXMgL19fcGx1Z2luLWdhbGxlcnkvKSwgZXhhY3RseSBhcyBpdCB3b3VsZCBhZ2FpbnN0XG4gICAgICAgIC8vIDx0cmVlPi9hc3NldHMgaW4gdGhlIGJ1aWx0IHRyZWUuIE9ubHkgL2Fzc2V0cy8gd2FzIHNlcnZlZCwgc28gZXZlcnkgbmVzdGVkIGRhdGEgdGFibGUgNDA0J2QuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFx1MjYwNSBBTkQgQU5ZIC9fX2xlYWYvXHUyMDI2L2Fzc2V0cy8qICgyMDI2LTA5LTI1LCByZXBvcnRlZCBmcm9tIGEgbGFwdG9wIGRldiBzZXJ2ZXI6IG5vIGJvdW5kYXJ5IHBvbHlnb25zXG4gICAgICAgIC8vIG9uIEJpZyBQaWN0dXJlLCBSZWdpb25zLCBVUEctMTAwLCBDaXRpZXMsIEdvc3BlbCkuIEEgZGV2IGxlYWYgcGFnZSBpcyAvX19sZWFmLzxidW5kbGU+Lzxwcm9maWxlPixcbiAgICAgICAgLy8gYW5kIGEgcGx1Z2luIHRoYXQgZmFsbHMgYmFjayB0byB0aGUgUEFHRS1SRUxBVElWRSAnLi9hc3NldHMnIGFza3MgZm9yIC9fX2xlYWYvPGJ1bmRsZT4vYXNzZXRzL1x1MjAyNlxuICAgICAgICAvLyBcdTIwMTQgd2hpY2ggdGhlIGxlYWYgcm91dGUgYmVsb3cgYW5zd2VyZWQgd2l0aCBpdHMgb3duIEhUTUwgYXQgSFRUUCAyMDAuIEpTT04ucGFyc2UgdGhlbiBmYWlsZWQgYW5kXG4gICAgICAgIC8vIHRoZSBtYXAgZHJldyB3aXRoIG5vIHBvbHlnb25zLCBubyBwcmV2aWV3cywgbm8gdGFibGVzLiBUaGUgYnVpbHQgbGVhZiBuZXZlciBoaXRzIHRoaXM6IGl0cyBwYWdlXG4gICAgICAgIC8vIGhhbmRzIHRoZSBlbGVtZW50IGFzc2V0c0Jhc2UgXCIuLi8uLi9hc3NldHNcIi4gU2VydmluZyB0aGUgcG9vbCBhdCBldmVyeSBzdWNoIHByZWZpeCBtYWtlcyB0aGVcbiAgICAgICAgLy8gcGFnZS1yZWxhdGl2ZSBkZWZhdWx0IHJlc29sdmUgaW4gZGV2IGV4YWN0bHkgYXMgaXQgZG9lcyBpbiB0aGUgdHJlZSAoLzx0cmVlPi9hc3NldHMgaW5jbHVkZWQpLlxuICAgICAgICBjb25zdCBsZWFmQXNzZXQgPSAvXlxcL19fbGVhZlxcLyg/OlteL10rXFwvKXswLDN9YXNzZXRzXFwvLy5leGVjKHBhdGgpXG4gICAgICAgIGNvbnN0IGFzc2V0UHJlZml4ID0gcGF0aC5zdGFydHNXaXRoKCcvYXNzZXRzLycpID8gJy9hc3NldHMvJ1xuICAgICAgICAgIDogcGF0aC5zdGFydHNXaXRoKCcvX19wbHVnaW4tZ2FsbGVyeS9hc3NldHMvJykgPyAnL19fcGx1Z2luLWdhbGxlcnkvYXNzZXRzLydcbiAgICAgICAgICA6IHBhdGguc3RhcnRzV2l0aChgLyR7dHJlZU5hbWV9L2Fzc2V0cy9gKSA/IGAvJHt0cmVlTmFtZX0vYXNzZXRzL2BcbiAgICAgICAgICA6IGxlYWZBc3NldCA/IGxlYWZBc3NldFswXSA6ICcnXG4gICAgICAgIGlmIChhc3NldFByZWZpeCkge1xuICAgICAgICAgIGxldCByZWwgPSAnJ1xuICAgICAgICAgIHRyeSB7IHJlbCA9IGRlY29kZVVSSUNvbXBvbmVudChwYXRoLnNsaWNlKGFzc2V0UHJlZml4Lmxlbmd0aCkpIH0gY2F0Y2ggeyByZWwgPSAnJyB9XG4gICAgICAgICAgaWYgKCFyZWwgfHwgcmVsLnNwbGl0KCcvJykuaW5jbHVkZXMoJy4uJykpIHsgcmVzLnN0YXR1c0NvZGUgPSA0MDA7IHJldHVybiByZXMuZW5kKCdiYWQgYXNzZXQgcGF0aCcpIH1cbiAgICAgICAgICBjb25zdCBmaWxlID0gcmVzb2x2ZURldkFzc2V0KHJlbClcbiAgICAgICAgICBpZiAoIWZpbGUpIHJldHVybiBqc29uKHJlcywgeyBlcnJvcjogJ2Fzc2V0IG5vdCBmb3VuZCcsIGFzc2V0OiByZWwsIGxvb2tlZDogW2BwdWJsaWMvJHtUUkVFX05BTUV9L2Fzc2V0cy9gLCAnZGF0YS8nLCAncGx1Z2luLWRlc2lnbnMvKi9kYXRhLyddIH0sIDQwNClcbiAgICAgICAgICByZXMuc3RhdHVzQ29kZSA9IDIwMFxuICAgICAgICAgIHJlcy5zZXRIZWFkZXIoJ0NvbnRlbnQtVHlwZScsIERFVl9BU1NFVF9NSU1FW2V4dG5hbWUoZmlsZSkudG9Mb3dlckNhc2UoKV0gfHwgJ2FwcGxpY2F0aW9uL29jdGV0LXN0cmVhbScpXG4gICAgICAgICAgcmVzLnNldEhlYWRlcignQ2FjaGUtQ29udHJvbCcsICduby1jYWNoZScpXG4gICAgICAgICAgcmV0dXJuIHJlcy5lbmQocmVhZEZpbGVTeW5jKGZpbGUpKVxuICAgICAgICB9XG4gICAgICAgIC8vIE1hY2hpbmUtcmVhZGFibGUsIHRoZSBzYW1lIGRpc2NvdmVyeSB0aGUgcGFnZSByZW5kZXJzOiB0aGUgcmVnaXN0cnkgKGtpbmRzICsgaXRlbXMsXG4gICAgICAgIC8vIHJlYWQgYnkgdGhlIHNtb2tlIHRvb2xzKSBhbmQgdGhlIG1hbmlmZXN0LXNoYXBlZCBtb2RlbCAod2hhdCB0aGUgcGFnZSBmZXRjaGVzIGxpdmUpLlxuICAgICAgICAvLyAvX19kZXYtc2hhIFx1MjAxNCBXSElDSCBDT01NSVQgVEhJUyBERVYgU0VSVkVSIElTIFNFUlZJTkcsIHJlYWQgYXQgcmVxdWVzdCB0aW1lIChhIHNoYXJlZCBkZXYgc2VydmVyXG4gICAgICAgIC8vIGZvbGxvd3MgbWFpbiwgc28gaXRzIGFuc3dlciBjaGFuZ2VzIHVuZGVyIGl0KS4gXCI8c2hhPlwiIG9yIFwiPHNoYT4rZGlydHlcIiB3aGVuIHRoZSBjaGVja291dCBoYXNcbiAgICAgICAgLy8gbG9jYWwgZWRpdHMuIEV2ZXJ5IGNoZWNrIGFpbWVkIGF0IGEgZGV2IHNlcnZlciBwcmludHMgdGhpcyBmaXJzdCwgYXMgZ2F0ZXMgcHJpbnQgdHJlZSBpZGVudGl0eS5cbiAgICAgICAgaWYgKHBhdGggPT09ICcvX19kZXYtc2hhJykge1xuICAgICAgICAgIGNvbnN0IGdpdCA9ICguLi5hKSA9PiBzcGF3blN5bmMoJ2dpdCcsIGEsIHsgY3dkOiBSRVBPX1JPT1QsIGVuY29kaW5nOiAndXRmOCcgfSkuc3Rkb3V0LnRyaW0oKVxuICAgICAgICAgIGNvbnN0IHNoYSA9IGdpdCgncmV2LXBhcnNlJywgJ0hFQUQnKVxuICAgICAgICAgIGNvbnN0IGRpcnR5ID0gZ2l0KCdzdGF0dXMnLCAnLS1wb3JjZWxhaW4nLCAnLS11bnRyYWNrZWQtZmlsZXM9bm8nLCAnLS0nLCAnbGlicmFyeScsICdwbHVnaW4tZGVzaWducycsICdpbnRlcm5hbCcsICd2aXRlLmNvbmZpZy5qcycsICdwYWNrYWdlLmpzb24nKSA/ICcrZGlydHknIDogJydcbiAgICAgICAgICByZXMuc3RhdHVzQ29kZSA9IHNoYSA/IDIwMCA6IDUwMFxuICAgICAgICAgIHJlcy5zZXRIZWFkZXIoJ0NvbnRlbnQtVHlwZScsICd0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04JylcbiAgICAgICAgICByZXMuc2V0SGVhZGVyKCdDYWNoZS1Db250cm9sJywgJ25vLXN0b3JlJylcbiAgICAgICAgICByZXR1cm4gcmVzLmVuZCgoc2hhIHx8ICd1bmtub3duJykgKyBkaXJ0eSArICdcXG4nKVxuICAgICAgICB9XG4gICAgICAgIGlmIChwYXRoID09PSAnL19fcGx1Z2luLWdhbGxlcnkvcmVnaXN0cnkuanNvbicgfHwgcGF0aCA9PT0gJy9fX3BsdWdpbi1nYWxsZXJ5L21hbmlmZXN0Lmpzb24nKSB7XG4gICAgICAgICAgbGV0IHJlZ1xuICAgICAgICAgIHRyeSB7IHJlZyA9IGRpc2NvdmVyU3BhUmVnaXN0cnkoKSB9IGNhdGNoIChlKSB7IHJldHVybiBqc29uKHJlcywgeyBlcnJvcjogU3RyaW5nKGUpIH0sIDUwMCkgfVxuICAgICAgICAgIHJldHVybiBqc29uKHJlcywgcGF0aC5lbmRzV2l0aCgnL21hbmlmZXN0Lmpzb24nKSA/IGdhbGxlcnlNb2RlbChyZWcpIDogcmVnKVxuICAgICAgICB9XG4gICAgICAgIC8vIFx1MjUwMFx1MjUwMCBgL19fbGVhZi88YnVuZGxlPi88cHJvZmlsZT5bLzxpbnN0YW5jZT5dYCBcdTIwMTQgT05FIGVsZW1lbnQsIG5vdGhpbmcgZWxzZSBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcbiAgICAgICAgLy8gVGhlIGRldiBzdGFuZC1pbiBmb3IgdGhlIGJ1aWx0IHRyZWUncyA8YnVuZGxlPi88cHJvZmlsZT4vaW5kZXguaHRtbC4gVGhlIHN0dWRpbydzIGlmcmFtZVxuICAgICAgICAvLyBwYW5lcyBwb2ludCBoZXJlIChzZWUgdGhlIGxpbmsoKSBub3RlIGFib3ZlKTsgd2l0aG91dCBpdCB0aGV5IGZlbGwgdGhyb3VnaCB0byBWaXRlJ3MgU1BBXG4gICAgICAgIC8vIGZhbGxiYWNrIGFuZCByZW5kZXJlZCBgL2AgXHUyMDE0IGkuZS4gdGhlIHdob2xlIHN0dWRpby9nYWxsZXJ5IFx1MjAxNCBpbnNpZGUgZXZlcnkgbWFwIHRhYi5cbiAgICAgICAgLy8gRGVsaWJlcmF0ZWx5IG1pbmltYWw6IG5vIGNocm9tZSwgbm8gcHJvc2UsIG5vIGdhbGxlcnkuIEp1c3QgdGhlIHRhZywgaXRzIGJ1bmRsZSBlbnRyeSwgYW5kXG4gICAgICAgIC8vIHRoZSBiYWtlZCB0b2tlbiwgc28gd2hhdCBtb3VudHMgaGVyZSBpcyB0aGUgZWxlbWVudCBhbmQgb25seSB0aGUgZWxlbWVudC5cbiAgICAgICAgaWYgKHBhdGguc3RhcnRzV2l0aCgnL19fbGVhZi8nKSkge1xuICAgICAgICAgIGNvbnN0IHBhcnRzID0gcGF0aC5zbGljZSgnL19fbGVhZi8nLmxlbmd0aCkuc3BsaXQoJy8nKS5maWx0ZXIoQm9vbGVhbikubWFwKHMgPT4ge1xuICAgICAgICAgICAgdHJ5IHsgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChzKSB9IGNhdGNoIHsgcmV0dXJuICcnIH1cbiAgICAgICAgICB9KVxuICAgICAgICAgIGNvbnN0IFtidW5kbGUsIHByb2ZpbGUsIGluc3RhbmNlXSA9IHBhcnRzXG4gICAgICAgICAgLy8gUGF0aCB0cmF2ZXJzYWwgZ3VhcmQ6IHRoZXNlIGxhbmQgaW4gYSBmaWxlc3lzdGVtLWlzaCBVUkwgYmVsb3cuXG4gICAgICAgICAgaWYgKCFidW5kbGUgfHwgIXByb2ZpbGUgfHwgcGFydHMuc29tZShzID0+ICFzIHx8IHMuaW5jbHVkZXMoJy4uJykgfHwgcy5pbmNsdWRlcygnLycpKSkge1xuICAgICAgICAgICAgcmVzLnN0YXR1c0NvZGUgPSA0MDA7IHJldHVybiByZXMuZW5kKCdiYWQgbGVhZiBwYXRoJylcbiAgICAgICAgICB9XG4gICAgICAgICAgbGV0IHJlZ1xuICAgICAgICAgIHRyeSB7IHJlZyA9IGRpc2NvdmVyU3BhUmVnaXN0cnkoKSB9IGNhdGNoIChlKSB7IHJldHVybiBqc29uKHJlcywgeyBlcnJvcjogU3RyaW5nKGUpIH0sIDUwMCkgfVxuICAgICAgICAgIGNvbnN0IGVudHJ5ID0gcmVnLmZpbmQoYiA9PiBiLmJ1bmRsZSA9PT0gYnVuZGxlKVxuICAgICAgICAgIGlmICghZW50cnkpIHtcbiAgICAgICAgICAgIC8vIEEgcGx1Z2luIGZvbGRlcidzIG93biAvcGx1Z2luLWRlc2lnbnMvPHg+L2luZGV4Lmh0bWwgYXJyaXZlcyBoZXJlIGFzIGJ1bmRsZSAncGx1Z2luLWRlc2lnbnMnXG4gICAgICAgICAgICAvLyAobGVhZlJld3JpdGUgcmVhZHMgYW55IDxhPi88Yj4vaW5kZXguaHRtbCBhcyA8YnVuZGxlPi88cHJvZmlsZT4pLiBBIGZyZXNoIHJlYWRlciBmb2xsb3dlZCB0aGVcbiAgICAgICAgICAgIC8vIFJFQURNRSdzIFwiYW4gaW5kZXguaHRtbCBmb3IgcHJldmlld2luZyBpdFwiIHRvIGV4YWN0bHkgdGhhdCBVUkwsIHNvIG5hbWUgdGhlIHBhZ2UgdGhhdCBleGlzdHMuXG4gICAgICAgICAgICBjb25zdCBuYW1lZCA9IHJlZy5maW5kKGIgPT4gYi5idW5kbGUgPT09IHByb2ZpbGUpXG4gICAgICAgICAgICBjb25zdCBoaW50ID0gbmFtZWRcbiAgICAgICAgICAgICAgPyBgdGhpcyBwbHVnaW4ncyBvd24gcGFnZSBpcyAvX19sZWFmLyR7bmFtZWQuYnVuZGxlfS8ke25hbWVkLml0ZW1zPy5bMF0/LnByb2ZpbGUgfHwgbmFtZWQuYnVuZGxlfWBcbiAgICAgICAgICAgICAgOiBcImEgcGx1Z2luJ3Mgb3duIHBhZ2UgaXMgL19fbGVhZi88cGx1Z2luPi88cHJvZmlsZT47IGV2ZXJ5IHBsdWdpbiBpcyBsaXN0ZWQgYXQgL19fcGx1Z2luLWdhbGxlcnkvbWFuaWZlc3QuanNvblwiXG4gICAgICAgICAgICByZXR1cm4ganNvbihyZXMsIHsgZXJyb3I6ICd1bmtub3duIGJ1bmRsZScsIGJ1bmRsZSwgaGludCB9LCA0MDQpXG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IHRhZyA9IGVudHJ5LnRhZ1xuICAgICAgICAgIC8vIE9uZSBjb25maWcgcmVhZCBmb3IgQk9USCBnbG9iYWxzLCBzbyB0aGUgdG9rZW4gYW5kIHRoZSBBUEkgYmFzZSBjYW4gbmV2ZXIgZGlzYWdyZWUgYWJvdXRcbiAgICAgICAgICAvLyB3aGljaCBjb25maWcgdGhleSBjYW1lIGZyb20uXG4gICAgICAgICAgbGV0IGxlYWZDZmcgPSB7fVxuICAgICAgICAgIHRyeSB7IGxlYWZDZmcgPSByZWFkQnVpbGRDb25maWcoKSB8fCB7fSB9IGNhdGNoIHsgbGVhZkNmZyA9IHt9IH1cbiAgICAgICAgICBjb25zdCBsZWFmVG9rID0gdG9rZW4gfHwgbGVhZkNmZy50b2tlbiB8fCAnJ1xuICAgICAgICAgIGNvbnN0IGFwaUJhc2UgPSBsZWFmQ2ZnLmFwaUJhc2VVcmwgfHwgJydcbiAgICAgICAgICAvLyBwcm9maWxlLWNvbmZpZyBjYXJyaWVzIHRoZSBzYW1lIHNoYXBlIHRoZSBidWlsdCBsZWF2ZXMgcGFzcywgc28gYSBwcm9maWxlL2luc3RhbmNlXG4gICAgICAgICAgLy8gcmVuZGVycyB0aGUgU0FNRSB2aWV3IGhlcmUgYXMgaW4gcHJvZHVjdGlvbiByYXRoZXIgdGhhbiB0aGUgYnVuZGxlJ3MgZGVmYXVsdC5cbiAgICAgICAgICAvLyBhc3NldHNCYXNlIHRvbywgYXMgdGhlIGJ1aWx0IGxlYWYncyBCQVNFX0NPTkZJRyBjYXJyaWVzIGl0IChcIi4uLy4uL2Fzc2V0c1wiIHRoZXJlOyByb290LWFic29sdXRlXG4gICAgICAgICAgLy8gaGVyZSwgYmVjYXVzZSBhIC9fX2xlYWYvIFVSTCdzIGRlcHRoIGRpZmZlcnMgZnJvbSB0aGUgdHJlZSdzIGFuZCB0aGUgcG9vbCBpcyBzZXJ2ZWQgYXQgL2Fzc2V0cykuXG4gICAgICAgICAgY29uc3QgcGMgPSBKU09OLnN0cmluZ2lmeShpbnN0YW5jZSA/IHsgcHJvZmlsZSwgaW5zdGFuY2VJZDogaW5zdGFuY2UsIGFzc2V0c0Jhc2U6ICcvYXNzZXRzJyB9IDogeyBwcm9maWxlLCBhc3NldHNCYXNlOiAnL2Fzc2V0cycgfSlcbiAgICAgICAgICAvLyBUaGUgY29tcG9zaXRpb24gdGllciBvZiBUSElTIHByb2ZpbGUsIHJlYWQgZnJvbSB0aGUgc2FtZSBkaXNjb3ZlcnkgdGhlIGdhbGxlcnkgdXNlcy5cbiAgICAgICAgICAvLyBgbmVzdGVkLWVsZW1lbnRzLW1mZWAgKGNhcC00KSBpcyB0aGUgU3RhY2tMYXlvdXQgc2Nyb2xsLXN0YWNrIHRpZXIgXHUyMDE0IHNlZSB0aGUgc3R5bGUgbm90ZVxuICAgICAgICAgIC8vIGJlbG93LiBBbiB1bmtub3duIHByb2ZpbGUgZmFsbHMgdGhyb3VnaCB0byB0aGUgZml4ZWQtdmlld3BvcnQgbGVhZiwgdGhlIHNhZmUgZGVmYXVsdC5cbiAgICAgICAgICBjb25zdCBzY3JvbGxQYWdlID0gKGVudHJ5Lml0ZW1zIHx8IFtdKS5zb21lKFxuICAgICAgICAgICAgaXQgPT4gaXQucHJvZmlsZSA9PT0gcHJvZmlsZSAmJiBpdC50eXBlID09PSAnbmVzdGVkLWVsZW1lbnRzLW1mZScpXG4gICAgICAgICAgcmVzLnN0YXR1c0NvZGUgPSAyMDBcbiAgICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAndGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04JylcbiAgICAgICAgICByZXMuc2V0SGVhZGVyKCdDYWNoZS1Db250cm9sJywgJ25vLWNhY2hlJylcbiAgICAgICAgICByZXR1cm4gcmVzLmVuZChbXG4gICAgICAgICAgICAnPCFET0NUWVBFIGh0bWw+JyxcbiAgICAgICAgICAgIGA8aHRtbCBsYW5nPVwiZW5cIj48aGVhZD48bWV0YSBjaGFyc2V0PVwiVVRGLThcIiAvPjx0aXRsZT4ke2J1bmRsZX0gXHUwMEI3ICR7cHJvZmlsZX08L3RpdGxlPmAsXG4gICAgICAgICAgICAnPG1ldGEgbmFtZT1cInZpZXdwb3J0XCIgY29udGVudD1cIndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLjBcIiAvPicsXG4gICAgICAgICAgICAnPGxpbmsgcmVsPVwiaWNvblwiIGhyZWY9XCJkYXRhOixcIj4nLFxuICAgICAgICAgICAgbGVhZlRvayA/IGA8c2NyaXB0PndpbmRvdy5NQVBfVE9LRU49JHtKU09OLnN0cmluZ2lmeShsZWFmVG9rKX07PC9zY3JpcHQ+YCA6ICcnLFxuICAgICAgICAgICAgLy8gXHUyNjA1IE1BUF9BUFBfQVBJX1VSTCBJUyBOT1QgT1BUSU9OQUwgXHUyMDE0IHdpdGhvdXQgaXQgZXZlcnkgZGFzaGJvYXJkIHJlbmRlcnMgRU1QVFkgaW4gZGV2LlxuICAgICAgICAgICAgLy8gVGhlIEJVSUxUIGxlYXZlcyBiYWtlIGB3aW5kb3cuTUFQX0FQUF9BUElfVVJMID0gXCJodHRwczovL3ByYXkuZG94YS5saWZlXCJgOyB0aGVzZSBkZXZcbiAgICAgICAgICAgIC8vIHBhZ2VzIGJha2VkIG9ubHkgdGhlIE1hcGJveCB0b2tlbiwgc28gdGhlIGRhc2hib2FyZHMgZmVsbCBiYWNrIHRvIGEgUkVMQVRJVkVcbiAgICAgICAgICAgIC8vIGAvYXBpL3Blb3BsZS1ncm91cHMvbGlzdD8uLi5gLiBWaXRlIGFuc3dlcnMgYW4gdW5rbm93biBwYXRoIHdpdGggU1BBLWZhbGxiYWNrIEhUTUwgYXRcbiAgICAgICAgICAgIC8vIEhUVFAgMjAwLCBzbyB0aGUgZmV0Y2ggXCJzdWNjZWVkc1wiLCBKU09OLnBhcnNlIGZhaWxzIG9yIHlpZWxkcyBub3RoaW5nLCBhbmQgdGhlIGZhY2V0XG4gICAgICAgICAgICAvLyByYWlsIHJlbmRlcnMgWkVSTyByb3dzIHdpdGggbm8gY29uc29sZSBlcnJvciBhbmQgbm8gZXJyb3IgY2FyZC4gTWVhc3VyZWQgMjAyNi0wOS0yMjpcbiAgICAgICAgICAgIC8vIDggc3VjaCA0MDQvZmFsbGJhY2sgcmVxdWVzdHMgZHVyaW5nIG9uZSBzdHVkaW8gc3dlZXAuIFRoYXQgcmVhZHMgYXMgYSBicm9rZW4gY29tcG9uZW50XG4gICAgICAgICAgICAvLyBhbmQgaXMgcmVhbGx5IGEgbWlzc2luZyBnbG9iYWwgXHUyMDE0IHRoZSB3b3JzdCBraW5kIG9mIGRldi1vbmx5IGRpdmVyZ2VuY2UsIGFuZCBleGFjdGx5IHRoZVxuICAgICAgICAgICAgLy8gZm91ci1zdXJmYWNlIGNsYXNzIChzZWUgUkVGRVJFTkNFLXRoZS1mb3VyLXN1cmZhY2UtY29udHJhY3QubWQpLlxuICAgICAgICAgICAgYXBpQmFzZSA/IGA8c2NyaXB0PndpbmRvdy5NQVBfQVBQX0FQSV9VUkw9JHtKU09OLnN0cmluZ2lmeShhcGlCYXNlKX07PC9zY3JpcHQ+YCA6ICcnLFxuICAgICAgICAgICAgLy8gXHUyNTAwXHUyNTAwIEZJWEVELVZJRVdQT1JUIExFQUYgdnMgU0NST0xMLVBBR0UgTEVBRiBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcbiAgICAgICAgICAgIC8vIFRoZSBCVUlMVCB0cmVlIG1ha2VzIGV4YWN0bHkgdGhpcyBkaXN0aW5jdGlvbiAoaW50ZXJuYWwvZ2VuZXJhdGUtdHJlZS5tanMsIGBzY3JvbGxQYWdlYClcbiAgICAgICAgICAgIC8vIGFuZCB0aGlzIGRldiBsZWFmIGRpZCBOT1QgXHUyMDE0IGl0IHNlcnZlZCB0aGUgZml4ZWQtdmlld3BvcnQgc3R5bGUgdG8gRVZFUlkgYnVuZGxlLiBUaGF0IGlzXG4gICAgICAgICAgICAvLyB0aGUgd2hvbGUgb2YgQlVHLUNBTk5PVC1TQ1JPTEwtRE9XTi1UTy1USEUtR1JJRC1VTkRFUi1USEUtREFTSEJPQVJEOiB0aGUgdGhyZWUtZmlsZSBmaXhcbiAgICAgICAgICAgIC8vIGZvciBCVUctREFTSEJPQVJELUNBTlQtU0NST0xMLURPV04gbGFuZGVkIGluIHRoZSBidWlsdCB0cmVlIG9ubHksIHNvIHRoZSBkZXYgVVJMIHRoYXRcbiAgICAgICAgICAgIC8vIGFjdHVhbGx5IGdldHMgdGVzdGVkIHdhcyBuZXZlciBjb3ZlcmVkIGFuZCBzdGlsbCB0cmFwcyB0aGUgY29tcG9zaXRlLlxuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vIFdIWSBgaGVpZ2h0OjEwMCVgIE9OIEJPRFkgSVMgVEhFIFRSQVAsIGFuZCB3aHkgc2Nyb2xsSGVpZ2h0IExJRVMgYWJvdXQgaXQuIEEgZGVmaW5pdGVcbiAgICAgICAgICAgIC8vIGhlaWdodCArIGBvdmVyZmxvdzp2aXNpYmxlYCBsZXRzIGNvbnRlbnQgU1BJTEwgKHNvIHNjcm9sbEhlaWdodCBpbmZsYXRlcyBcdTIwMTQgbWVhc3VyZWQgMzUzMVxuICAgICAgICAgICAgLy8gYWdhaW5zdCBhIDkwMCB2aWV3cG9ydCkgV0lUSE9VVCBjcmVhdGluZyBhIHNjcm9sbHBvcnQsIHNvIHRoZSB2aWV3cG9ydCBoYXMgbm90aGluZyB0b1xuICAgICAgICAgICAgLy8gc2Nyb2xsLiBUaGUgcmVzZWFyY2gtZGFzaGJvYXJkJ3Mgb3duIGlubmVyIGBvdmVyZmxvdzphdXRvYCByZWdpb25zIHRoZW4gc3dhbGxvdyBldmVyeVxuICAgICAgICAgICAgLy8gd2hlZWwgZXZlbnQuIE1FQVNVUkVEIDIwMjYtMDktMjIgb24gdGhpcyBsZWFmOiAxMiB3aGVlbCBldmVudHMgb2YgNjAwcHggbW92ZWQgdGhlIHBhZ2VcbiAgICAgICAgICAgIC8vIDBweCB3aGlsZSAyLDYzMXB4IG9mIGNvbnRlbnQgc2F0IGJlbG93IHRoZSBmb2xkLiBBIGdlb21ldHJ5IGNoZWNrIGNhbGxzIHRoYXQgXCJzY3JvbGxhYmxlXCI7XG4gICAgICAgICAgICAvLyBvbmx5IGEgcmVhbCB3aGVlbCBleHBvc2VzIGl0LlxuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vIEEgY2FwLTQgY29tcG9zaXRlIChuZXN0ZWQtZWxlbWVudHMtbWZlKSBpcyBhIFN0YWNrTGF5b3V0IHNjcm9sbC1zdGFjaywgc28gdGhlIERPQ1VNRU5UXG4gICAgICAgICAgICAvLyBtdXN0IG93biB0aGUgc2Nyb2xsOiBgbWluLWhlaWdodGAgKGEgZmxvb3IsIG5vdCBhIGNhZ2UpICsgZXhwbGljaXQgYG92ZXJmbG93LXk6YXV0b2AsXG4gICAgICAgICAgICAvLyBhbmQgdGhlIGVsZW1lbnQgdGFrZXMgaXRzIE5BVFVSQUwgaGVpZ2h0IHNvIHRoZSBwYWdlIGdyb3dzIGFuZCB0aGUgZ3JpZCBiZWxvdyBpc1xuICAgICAgICAgICAgLy8gcmVhY2hhYmxlLiBFdmVyeSBvdGhlciB0aWVyIGtlZXBzIHRoZSBmaXhlZC12aWV3cG9ydCBsZWFmIFx1MjAxNCBhIG1hcCBJUyB0aGUgcGFnZS5cbiAgICAgICAgICAgIHNjcm9sbFBhZ2VcbiAgICAgICAgICAgICAgPyAnPHN0eWxlPmh0bWx7aGVpZ2h0OjEwMCU7fWh0bWwsYm9keXttYXJnaW46MDtwYWRkaW5nOjA7YmFja2dyb3VuZDojZjNmM2YxO30nICtcbiAgICAgICAgICAgICAgICAnYm9keXttaW4taGVpZ2h0OjEwMCU7b3ZlcmZsb3cteTphdXRvO30nICtcbiAgICAgICAgICAgICAgICAvLyBtaW4taGVpZ2h0IGluIFZJRVdQT1JUIHVuaXRzLCBuZXZlciBwZXJjZW50OiBhIHBlcmNlbnRhZ2UgcmVzb2x2ZXMgYWdhaW5zdCBib2R5J3NcbiAgICAgICAgICAgICAgICAvLyBhdXRvIGhlaWdodCBhbmQgY29sbGFwc2VzIHRvIDAgKEJVRy1VUEcxMDAtTkVTVEVELUVMRU1FTlRTLVpFUk8tSEVJR0hUKS4gMTAwZHZoXG4gICAgICAgICAgICAgICAgLy8gZGVwZW5kcyBvbiBubyBhbmNlc3RvciBhbmQgc3RheXMgYSBmbG9vciwgc28gdGhlIHBhZ2UgY2FuIHN0aWxsIGdyb3cgcGFzdCBpdC5cbiAgICAgICAgICAgICAgICBgJHt0YWd9e2Rpc3BsYXk6YmxvY2s7d2lkdGg6MTAwJTttaW4taGVpZ2h0OjEwMGR2aDt9PC9zdHlsZT5gXG4gICAgICAgICAgICAgIDogJzxzdHlsZT5odG1sLGJvZHl7bWFyZ2luOjA7cGFkZGluZzowO2hlaWdodDoxMDAlO2JhY2tncm91bmQ6I2YzZjNmMTt9JyArXG4gICAgICAgICAgICAgICAgYCR7dGFnfXtkaXNwbGF5OmJsb2NrO3dpZHRoOjEwMCU7aGVpZ2h0OjEwMHZoO308L3N0eWxlPmAsXG4gICAgICAgICAgICAnPC9oZWFkPjxib2R5PicsXG4gICAgICAgICAgICAvLyB0cmVlLWJhc2UgT04gVEhFIExFQUYgVE9PIFx1MjAxNCBjYXAtNSBzaGVsbHMgbmVzdGVkIGhlcmUgZmV0Y2ggYSBtYW5pZmVzdCBvZiB0aGVpciBvd24uXG4gICAgICAgICAgICAvLyBkb3hhLW1hcHMtc3BhIChsaWtlIHBsdWdpbi1zdHVkaW8pIGRpc2NvdmVycyBpdHMgdGFicyBmcm9tIHRoZSB0cmVlJ3MgbWFuaWZlc3QuanNvbiBhbmRcbiAgICAgICAgICAgIC8vIHJlc29sdmVzIGl0IFJFTEFUSVZFIHRvIGl0cyBvd24gcGFnZSB3aGVuIG5vIGJhc2UgaXMgZ2l2ZW4uIE9uIGEgL19fbGVhZi8gVVJMIHRoYXRcbiAgICAgICAgICAgIC8vIHJlc29sdmVkIHRvIC9fX2xlYWYvbWFuaWZlc3QuanNvbiBhbmQgNDAwJ2QuIEhhcm1sZXNzIChib3RoIHNoZWxscyBjYXJyeSBhIGJha2VkXG4gICAgICAgICAgICAvLyBmYWxsYmFjayBsaXN0KSBidXQgaXQgc2lsZW50bHkgZGVncmFkZXMgdGhlIHRhYiBsaXN0IHRvIHRoZSBmYWxsYmFjayBpbnN0ZWFkIG9mIHRoZVxuICAgICAgICAgICAgLy8gbGl2ZSAxOS1idW5kbGUgdHJlZS4gUGFzc2luZyB0aGUgYmFzZSBtYWtlcyBhIG5lc3RlZCBzaGVsbCBzZWUgZXhhY3RseSB3aGF0IHRoZSB0b3BcbiAgICAgICAgICAgIC8vIGxldmVsIHNlZXMuIEVsZW1lbnRzIHRoYXQgaWdub3JlIHRyZWUtYmFzZSBzaW1wbHkgZHJvcCBhbiB1bmtub3duIGF0dHJpYnV0ZS5cbiAgICAgICAgICAgIGA8JHt0YWd9IHRyZWUtYmFzZT1cIi9fX3BsdWdpbi1nYWxsZXJ5XCIgcHJvZmlsZS1jb25maWc9JyR7cGN9Jz48LyR7dGFnfT5gLFxuICAgICAgICAgICAgYDxzY3JpcHQgdHlwZT1cIm1vZHVsZVwiIHNyYz1cIi9wbHVnaW4tZGVzaWducy8ke2J1bmRsZX0vaW5kZXguanNcIj48L3NjcmlwdD5gLFxuICAgICAgICAgICAgJzwvYm9keT48L2h0bWw+JyxcbiAgICAgICAgICBdLmZpbHRlcihCb29sZWFuKS5qb2luKCdcXG4nKSlcbiAgICAgICAgfVxuICAgICAgICAvLyBcdTI1MDBcdTI1MDAgYC9gIE1PVU5UUyBUSEUgUExVR0lOIFNUVURJTywgTk9UIFRIRSBTVEFHSU5HIEdBTExFUlkgXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXG4gICAgICAgIC8vIFRIRSBESVJFQ1RJT04gKDIwMjYtMDktMjIpOiB0aGUgZGV2IHNlcnZlciBvcGVucyBhIFBsdWdpbiBTdHVkaW8gdGhhdCBnaXZlcyBhY2Nlc3MgdG8gYWxsXG4gICAgICAgIC8vIHRoZSBwbHVnaW5zIGluIG9uZSBwbGFjZSwgd2l0aG91dCB0ZXh0IHRoYXQgdGFrZXMgdXAgc3BhY2U7IGFuZCB0aGUgZ2VuZXJhdGVkIHN0YWdpbmdcbiAgICAgICAgLy8gcGFnZXMgYXJlIG5vIGxvbmdlciBuZWVkZWQsIGJlY2F1c2UgdGhlIFBsdWdpbiBTdHVkaW8gcmVwbGFjZXMgdGhvc2UgaW5kZXguaHRtbCBmaWxlcy5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gV0hZIFRISVMgUk9VVEUgSEFEIFRPIEVYSVNUIEFUIEFMTC4gVGhlIGRldiBzZXJ2ZXIgcHJldmlvdXNseSBzZXJ2ZWQgT05MWSB0aGUgZ2FsbGVyeSBhdFxuICAgICAgICAvLyBgL2AsIGFuZCBoYWQgbm8gcm91dGUgZm9yIGEgYnVuZGxlIGxlYWYgXHUyMDE0IHNvIGBidW4gcnVuIGRldmAgY291bGQgbm90IHNob3cgdGhlIGNhcC01IHN0dWRpb1xuICAgICAgICAvLyBieSBhbnkgVVJMLiBPcGVuaW5nIGAvYCBzaG93ZWQgcGx1Z2lucyB3cmFwcGVkIGluIHBlci1idW5kbGUgZnJhbWVzIGJlaGluZCBhIHdhbGwgb2ZcbiAgICAgICAgLy8gZXhwbGFuYXRvcnkgcHJvc2UsIHdoaWNoIHJlYXNvbmFibHkgcmVhZCBhcyBub25lIG9mIHRoZSBlbGVtZW50cyB3b3JraW5nLiBUaGV5XG4gICAgICAgIC8vIHdlcmUgd29ya2luZzsgdGhlIHBhZ2Ugd2FzIGEgQ0hPT1NFUiBwcmVzZW50aW5nIGl0c2VsZiBhcyB0aGUgcHJvZHVjdC5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gV0hZIE1PVU5UIFRIRSBUQUcgUkFUSEVSIFRIQU4gUkVESVJFQ1QgVE8gQSBMRUFGOiBwbHVnaW4tc3R1ZGlvIGlzIGEgcmVhbCBjYXAtNVxuICAgICAgICAvLyBkZWZpbmVDdXN0b21FbGVtZW50IGVsZW1lbnQsIHNvIHRoZSBob25lc3QgZGV2IHN1cmZhY2UgaXMgdGhlIGVsZW1lbnQgaXRzZWxmLCBsb2FkZWRcbiAgICAgICAgLy8gdGhyb3VnaCBpdHMgb3duIGluZGV4LmpzIFx1MjAxNCB0aGUgc2FtZSBwYXRoIHRoZSBidWlsdCBidW5kbGUgdGFrZXMuIFRoYXQga2VlcHMgSE1SIHdvcmtpbmdcbiAgICAgICAgLy8gKFZpdGUgdHJhbnNmb3JtcyB0aGUgLnZ1ZSBvbiBkZW1hbmQpIGFuZCBrZWVwcyByZWdpc3RlclN0cmF0ZWdpZXMvcHJvZmlsZU1vZHVsZXMvUGluaWFcbiAgICAgICAgLy8gaW50YWN0LCB3aGljaCBiYWtpbmcgb3IgaWZyYW1pbmcgd291bGQgYnlwYXNzLlxuICAgICAgICAvL1xuICAgICAgICAvLyBUaGUgZ2FsbGVyeSBpcyBOT1QgZGVsZXRlZCBcdTIwMTQgaXQgaXMgc3RpbGwgZ2VuZXJhdGVkIGZvciB0aGUgYnVpbHQgdHJlZSBhbmQgaXMgc3RpbGxcbiAgICAgICAgLy8gbG9hZC1iZWFyaW5nIGZvciB0aGUgbWFuaWZlc3QuIEl0IHNpbXBseSBzdG9wcyBiZWluZyB3aGF0IGEgZGV2ZWxvcGVyIGxhbmRzIG9uLiBJdCBzdGF5c1xuICAgICAgICAvLyByZWFjaGFibGUgYXQgYW4gZXhwbGljaXQgVVJMIGZvciBhbnlvbmUgd2hvIHdhbnRzIHRoZSBidW5kbGUgaW5kZXguXG4gICAgICAgIGlmIChwYXRoID09PSAnLycgfHwgcGF0aCA9PT0gJy9pbmRleC5odG1sJykge1xuICAgICAgICAgIC8vIFNhbWUgcmVzb2x1dGlvbiBvcmRlciB0aGUgZ2FsbGVyeSB1c2VzOiB0aGUgLmVudi9WSVRFX01BUEJPWF9UT0tFTiB2YWx1ZSBwYXNzZWQgaW50b1xuICAgICAgICAgIC8vIGF1dG9TcGFEZXZQbHVnaW4odG9rZW4pLCBlbHNlIHRoZSBidWlsZCBjb25maWcncyBiYWtlZCB0b2tlbi4gcmVhZEJ1aWxkQ29uZmlnKCkgaXNcbiAgICAgICAgICAvLyBjYWxsZWQgSEVSRSByYXRoZXIgdGhhbiByZXVzaW5nIHBhZ2UoKSdzIGBjZmdgIFx1MjAxNCB0aGF0IGNvbnN0IGxpdmVzIGluc2lkZSB0aGUgcGFnZSgpXG4gICAgICAgICAgLy8gYXJyb3cgZnVuY3Rpb24sIHNvIGl0IGlzIG5vdCBpbiBzY29wZSBpbiB0aGlzIG1pZGRsZXdhcmUgKGFuIGVhcmxpZXIgdmVyc2lvbiByZWZlcmVuY2VkXG4gICAgICAgICAgLy8gaXQgYW5kIHRoZSBkZXYgc2VydmVyIDUwMCdkIHdpdGggXCJjZmcgaXMgbm90IGRlZmluZWRcIikuXG4gICAgICAgICAgLy8gT25lIGNvbmZpZyByZWFkIGZvciBCT1RIIGdsb2JhbHMgKHNlZSB0aGUgbGVhZiByb3V0ZSBhYm92ZSBmb3Igd2h5IHRoZSBBUEkgYmFzZSBtYXR0ZXJzKS5cbiAgICAgICAgICBsZXQgZGV2Q2ZnID0ge31cbiAgICAgICAgICB0cnkgeyBkZXZDZmcgPSByZWFkQnVpbGRDb25maWcoKSB8fCB7fSB9IGNhdGNoIHsgZGV2Q2ZnID0ge30gfVxuICAgICAgICAgIGNvbnN0IGRldlRvayA9IHRva2VuIHx8IGRldkNmZy50b2tlbiB8fCAnJ1xuICAgICAgICAgIGNvbnN0IGRldkFwaUJhc2UgPSBkZXZDZmcuYXBpQmFzZVVybCB8fCAnJ1xuICAgICAgICAgIHJlcy5zdGF0dXNDb2RlID0gMjAwXG4gICAgICAgICAgcmVzLnNldEhlYWRlcignQ29udGVudC1UeXBlJywgJ3RleHQvaHRtbDsgY2hhcnNldD11dGYtOCcpXG4gICAgICAgICAgcmVzLnNldEhlYWRlcignQ2FjaGUtQ29udHJvbCcsICduby1jYWNoZScpXG4gICAgICAgICAgcmV0dXJuIHJlcy5lbmQoW1xuICAgICAgICAgICAgJzwhRE9DVFlQRSBodG1sPicsXG4gICAgICAgICAgICAnPGh0bWwgbGFuZz1cImVuXCI+PGhlYWQ+PG1ldGEgY2hhcnNldD1cIlVURi04XCIgLz4nLFxuICAgICAgICAgICAgJzxtZXRhIG5hbWU9XCJ2aWV3cG9ydFwiIGNvbnRlbnQ9XCJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MS4wXCIgLz4nLFxuICAgICAgICAgICAgYDx0aXRsZT4ke1RSRUVfTkFNRX0gcGx1Z2luIHN0dWRpbzwvdGl0bGU+YCxcbiAgICAgICAgICAgICc8bGluayByZWw9XCJpY29uXCIgaHJlZj1cImRhdGE6LFwiPicsXG4gICAgICAgICAgICAvLyBUaGUgdG9rZW4gbGFkZGVyJ3MgYmFrZWQgcnVuZywgZXhhY3RseSBhcyB0aGUgYnVpbHQgbGVhdmVzIHJlY2VpdmUgaXQsIHNvIG1hcHMgcGFpbnRcbiAgICAgICAgICAgIC8vIGluIGRldiB3aXRob3V0IGFueW9uZSBhcHBlbmRpbmcgP3RrPS5cbiAgICAgICAgICAgIGRldlRvayA/IGA8c2NyaXB0PndpbmRvdy5NQVBfVE9LRU49JHtKU09OLnN0cmluZ2lmeShkZXZUb2spfTs8L3NjcmlwdD5gIDogXCJcIixcbiAgICAgICAgICAgIC8vIFNhbWUgcmVhc29uIGFzIHRoZSBsZWFmIHJvdXRlIGFib3ZlOiB3aXRob3V0IE1BUF9BUFBfQVBJX1VSTCB0aGUgZGFzaGJvYXJkcyBuZXN0ZWQgaW5cbiAgICAgICAgICAgIC8vIHRoZSBzdHVkaW8gZmV0Y2ggYSByZWxhdGl2ZSAvYXBpLy4uLiB0aGF0IFZpdGUgYW5zd2VycyB3aXRoIEhUTUwgYXQgMjAwLCBzbyB0aGV5IG1vdW50XG4gICAgICAgICAgICAvLyBhbmQgdGhlbiBzaG93IG5vdGhpbmcuIFRoZSB2YWx1ZSBjb21lcyBmcm9tIHRoZSBTQU1FIGJ1aWxkIGNvbmZpZyB0aGUgYnVpbHQgbGVhdmVzIHVzZSxcbiAgICAgICAgICAgIC8vIHNvIGRldiBhbmQgYnVpbHQgYWdyZWUgYnkgY29uc3RydWN0aW9uIHJhdGhlciB0aGFuIGJ5IGEgc2Vjb25kIGhhcmQtY29kZWQgY29weS5cbiAgICAgICAgICAgIGRldkFwaUJhc2UgPyBgPHNjcmlwdD53aW5kb3cuTUFQX0FQUF9BUElfVVJMPSR7SlNPTi5zdHJpbmdpZnkoZGV2QXBpQmFzZSl9Ozwvc2NyaXB0PmAgOiBcIlwiLFxuICAgICAgICAgICAgLy8gTm8gY2hyb21lLCBubyBwcm9zZTogdGhlIGVsZW1lbnQgZmlsbHMgdGhlIHZpZXdwb3J0LiBcIldpdGhvdXQgYSBsb3Qgb2YgdGV4dCBnYXJiXG4gICAgICAgICAgICAvLyB0aGF0IHRha2VzIHVwIHNvIG11Y2ggc3BhY2VcIiBpcyBhIGxheW91dCByZXF1aXJlbWVudCwgc28gdGhlIGhvc3QgcGFnZSBjb250cmlidXRlc1xuICAgICAgICAgICAgLy8gWkVSTyB0ZXh0IFx1MjAxNCBldmVyeSBwaXhlbCBiZWxvbmdzIHRvIHRoZSBzdHVkaW8gZWxlbWVudC5cbiAgICAgICAgICAgICc8c3R5bGU+aHRtbCxib2R5e21hcmdpbjowO3BhZGRpbmc6MDtoZWlnaHQ6MTAwJTtiYWNrZ3JvdW5kOiNmM2YzZjE7fScsXG4gICAgICAgICAgICAncGx1Z2luLXN0dWRpb3tkaXNwbGF5OmJsb2NrO3dpZHRoOjEwMCU7aGVpZ2h0OjEwMHZoO308L3N0eWxlPicsXG4gICAgICAgICAgICAnPC9oZWFkPjxib2R5PicsXG4gICAgICAgICAgICAvLyB0cmVlLWJhc2UgSVMgUkVRVUlSRUQgSU4gREVWIFx1MjAxNCB3aXRob3V0IGl0IHRoZSBzdHVkaW8gbW91bnRzIEVNUFRZLlxuICAgICAgICAgICAgLy8gVGhlIHN0dWRpbyBidWlsZHMgaXRzIHRhYiBsaXN0IGF0IHJ1bnRpbWUgYnkgZmV0Y2hpbmcgYDxiYXNlPm1hbmlmZXN0Lmpzb25gLCBhbmQgd2l0aFxuICAgICAgICAgICAgLy8gbm8gYmFzZSBpdCBmYWxscyBiYWNrIHRvICcuLi9tYW5pZmVzdC5qc29uJyBSRUxBVElWRSBUTyBJVFMgU0NSSVBUIFVSTC4gSW4gZGV2IHRoZVxuICAgICAgICAgICAgLy8gc2NyaXB0IGlzIC9wbHVnaW4tZGVzaWducy9wbHVnaW4tc3R1ZGlvL2luZGV4LmpzLCBzbyB0aGF0IHJlc29sdmVzIHRvXG4gICAgICAgICAgICAvLyAvcGx1Z2luLWRlc2lnbnMvbWFuaWZlc3QuanNvbiBcdTIwMTQgd2hpY2ggZG9lcyBub3QgZXhpc3QuIFRoZSBzaGVsbCB0aGVuIHJlbmRlcnMgd2l0aCB6ZXJvXG4gICAgICAgICAgICAvLyByb3dzOiAzMSBzaGFkb3cgZGVzY2VuZGFudHMsIG5vIG5lc3RlZCBwbHVnaW4gdGFncy4gKE1lYXN1cmVkIGV4YWN0bHkgdGhhdCBiZWZvcmUgdGhpc1xuICAgICAgICAgICAgLy8gbGluZSBleGlzdGVkOyB0aGUgc3ltcHRvbSByZWFkcyBhcyBcIm5vIGVsZW1lbnRzIGluIHRoZSBzdHVkaW9cIiwgbm90IGFzIGEgZmFpbGVkIGZldGNoLilcbiAgICAgICAgICAgIC8vIFRoZSBkZXYgc2VydmVyJ3MgbWFuaWZlc3QgbGl2ZXMgb24gaXRzIG93biByb3V0ZSBpbnN0ZWFkLCBzZXJ2aW5nIHRoZSBTQU1FXG4gICAgICAgICAgICAvLyBtYW5pZmVzdC1zaGFwZWQgbW9kZWwgdGhlIGJ1aWx0IHRyZWUgYmFrZXMgKDE5IGJ1bmRsZXMgLyAzMCBwcm9maWxlcyksIHNvIHBvaW50aW5nIHRoZVxuICAgICAgICAgICAgLy8gc3R1ZGlvIGF0IGl0IGdpdmVzIGRldiB0aGUgc2FtZSB0YWIgbGlzdCBwcm9kdWN0aW9uIGhhcy5cbiAgICAgICAgICAgICc8cGx1Z2luLXN0dWRpbyB0cmVlLWJhc2U9XCIvX19wbHVnaW4tZ2FsbGVyeVwiPjwvcGx1Z2luLXN0dWRpbz4nLFxuICAgICAgICAgICAgJzxzY3JpcHQgdHlwZT1cIm1vZHVsZVwiIHNyYz1cIi9wbHVnaW4tZGVzaWducy9wbHVnaW4tc3R1ZGlvL2luZGV4LmpzXCI+PC9zY3JpcHQ+JyxcbiAgICAgICAgICAgICc8L2JvZHk+PC9odG1sPicsXG4gICAgICAgICAgXS5maWx0ZXIoQm9vbGVhbikuam9pbignXFxuJykpXG4gICAgICAgIH1cbiAgICAgICAgLy8gVGhlIHN0YWdpbmcgZ2FsbGVyeSwga2VwdCBidXQgREVNT1RFRCB0byBhbiBleHBsaWNpdCBvcHQtaW4gVVJMLlxuICAgICAgICBpZiAocGF0aCAhPT0gJy9fX2dhbGxlcnknICYmIHBhdGggIT09ICcvX19nYWxsZXJ5LycpIHJldHVybiBuZXh0KClcbiAgICAgICAgbGV0IGh0bWxcbiAgICAgICAgdHJ5IHsgaHRtbCA9IHBhZ2UoKSB9XG4gICAgICAgIGNhdGNoIChlKSB7IGNvbnNvbGUuZXJyb3IoYFtwbHVnaW4tZ2FsbGVyeV0gJHtlICYmIGUuc3RhY2sgPyBlLnN0YWNrIDogZX1gKTsgcmV0dXJuIG5leHQoKSB9XG4gICAgICAgIHJlcy5zdGF0dXNDb2RlID0gMjAwXG4gICAgICAgIHJlcy5zZXRIZWFkZXIoJ0NvbnRlbnQtVHlwZScsICd0ZXh0L2h0bWw7IGNoYXJzZXQ9dXRmLTgnKVxuICAgICAgICByZXMuZW5kKGh0bWwpXG4gICAgICB9KVxuICAgIH0sXG4gIH1cbn1cbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL2hvbWUvbGsxMHgvV29ya3NwYWNlL2Vjby1keC9yb290LWRveGEtbWFwcy93dC1oZi9pbnRlcm5hbC9wbHVnaW4tZ2FsbGVyeVwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL2hvbWUvbGsxMHgvV29ya3NwYWNlL2Vjby1keC9yb290LWRveGEtbWFwcy93dC1oZi9pbnRlcm5hbC9wbHVnaW4tZ2FsbGVyeS9kaXNjb3Zlci5tanNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL2hvbWUvbGsxMHgvV29ya3NwYWNlL2Vjby1keC9yb290LWRveGEtbWFwcy93dC1oZi9pbnRlcm5hbC9wbHVnaW4tZ2FsbGVyeS9kaXNjb3Zlci5tanNcIjsvKipcbiAqIGRpc2NvdmVyLm1qcyBcdTIwMTQgdGhlIGF1dG8tZ2VuZXJhdGVkIFNQQSdzIHJlZ2lzdHJ5OiBldmVyeSBidW5kbGUgdW5kZXIgcGx1Z2luLWRlc2lnbnMvLFxuICogZXZlcnkgcHJvZmlsZSBpbnNpZGUgaXQsIGNsYXNzaWZpZWQgaW50byBhIGNvbXBvc2l0aW9uIHRpZXIuXG4gKlxuICogICBzaW5nbGUgXHUyMTkyIHBhcmFtZXRlcml6ZWQgXHUyMTkyIG1vbm9saXRoaWMgXHUyMTkyIG5lc3RlZC1lbGVtZW50cy1tZmUgXHUyMTkyIG5lc3RlZC1tZmUtc3BhXG4gKlxuICogQ29udmVudGlvbnMgaXQgcmVhZHMgKGFsbCBvcHRpb25hbCwgYWxsIHBlciBidW5kbGUgZm9sZGVyKTpcbiAqICAgPHByb2ZpbGU+Lm1ldGEuanNvbiAgIHtcInR5cGVcIjogXCI8dGllcj5cIiwgXCJsYWJlbFwiOiBcIkh1bWFuIG5hbWVcIn0gXHUyMDE0IHRoZSBPTkxZIHdheSB0byBkZWNsYXJlIGFcbiAqICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvc2l0ZSB0aWVyIChtb25vbGl0aGljIC8gbmVzdGVkLWVsZW1lbnRzLW1mZSAvIG5lc3RlZC1tZmUtc3BhKS5cbiAqICAgPG5hbWU+Lmluc3RhbmNlcy5qc29uIFt7aWQsIHRpdGxlLCBwcm9wc31dIG9yIHtcImluc3RhbmNlc1wiOiBbLi4uXX0gXHUyMDE0IG1hcmtzIHRoZSBidW5kbGUnc1xuICogICAgICAgICAgICAgICAgICAgICAgICAgcHJvZmlsZXMgUEFSQU1FVEVSSVpFRCBhbmQgZXhwYW5kcyBvbmUgZWxlbWVudCBwZXIgaW5zdGFuY2UuXG4gKiBQdXJlICsgc2lkZS1lZmZlY3QgZnJlZTogdGhlIGRldiBwbHVnaW4gKGRldi1wbHVnaW4ubWpzKSB0dXJucyBpdHMgcmVzdWx0IGludG8gdGhlXG4gKiBtYW5pZmVzdC1zaGFwZWQgbW9kZWwgdGhlIHBsdWdpbiBnYWxsZXJ5IHJlbmRlcnM7IGFueSB0b29sIHRoYXQgbmVlZHMgdGhlIGNhdGFsb2cgY2FuIHVzZSBpdC5cbiAqL1xuaW1wb3J0IHsgcmVzb2x2ZSwgZGlybmFtZSB9IGZyb20gJ25vZGU6cGF0aCdcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tICdub2RlOnVybCdcbmltcG9ydCB7IHJlYWRkaXJTeW5jLCBzdGF0U3luYywgZXhpc3RzU3luYywgcmVhZEZpbGVTeW5jIH0gZnJvbSAnbm9kZTpmcydcblxuZXhwb3J0IGNvbnN0IFJFUE9fUk9PVCA9IHJlc29sdmUoZGlybmFtZShmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnVybCkpLCAnLi4nLCAnLi4nKVxuXG4vLyBDb21wb3NpdGlvbiB0aWVycywgbW9zdC1jb21wb3NlZCBcdTIxOTIgaW5kaXZpZHVhbC4gRHJpdmVzIG9yZGVyaW5nICsgbGFiZWxzLlxuZXhwb3J0IGNvbnN0IFBST0ZJTEVfVElFUiA9IHtcbiAgJ25lc3RlZC1tZmUtc3BhJzogMCxcbiAgJ25lc3RlZC1lbGVtZW50cy1tZmUnOiAxLFxuICAnbW9ub2xpdGhpYyc6IDIsXG4gICdwYXJhbWV0ZXJpemVkJzogMyxcbiAgJ3NpbmdsZSc6IDQsXG59XG4vLyBSZWFkZXItZmFjaW5nIG5hbWVzICh2YWxpZGF0ZWQgdm9jYWJ1bGFyeSwgc2VlIGRvY3VtZW50YXRpb24vcmVmZXJlbmNlLm1kIFwiUHJvZmlsZSB0eXBlc1wiKTogdGhlIG1hY2hpbmVcbi8vIGtleXMgYWJvdmUgc3RheSBjYW5vbmljYWw7IGEgPHByb2ZpbGU+Lm1ldGEuanNvbiBtYXkgdXNlIGVpdGhlciBzcGVsbGluZy4gUGF0dGVybjpcbi8vIFwiPGF0dGVzdGVkIGhlYWQgd29yZD4tPHdoYXQgdGhlIGZpbGUgeWllbGRzPlwiIFx1MjAxNCBzaW5nbGUtZWxlbWVudCBcdTIxOTIgcHJlc2V0LWVsZW1lbnQgXHUyMTkyXG4vLyBtdWx0aS12aWV3LWVsZW1lbnQgXHUyMTkyIGNvbXBvc2l0ZS1lbGVtZW50IFx1MjE5MiBhcHAtc2hlbGwuXG5leHBvcnQgY29uc3QgVFlQRV9ESVNQTEFZID0ge1xuICAnc2luZ2xlJzogJ3NpbmdsZS1lbGVtZW50JyxcbiAgJ3BhcmFtZXRlcml6ZWQnOiAncHJlc2V0LWVsZW1lbnQnLFxuICAnbW9ub2xpdGhpYyc6ICdtdWx0aS12aWV3LWVsZW1lbnQnLFxuICAnbmVzdGVkLWVsZW1lbnRzLW1mZSc6ICdjb21wb3NpdGUtZWxlbWVudCcsXG4gICduZXN0ZWQtbWZlLXNwYSc6ICdhcHAtc2hlbGwnLFxufVxuZXhwb3J0IGNvbnN0IFRZUEVfQUxJQVNFUyA9IE9iamVjdC5mcm9tRW50cmllcyhPYmplY3QuZW50cmllcyhUWVBFX0RJU1BMQVkpLm1hcCgoW2ssIHZdKSA9PiBbdiwga10pKVxuZXhwb3J0IGNvbnN0IG5vcm1hbGl6ZVR5cGUgPSAodCkgPT4gKHQgJiYgUFJPRklMRV9USUVSW3RdICE9IG51bGwpID8gdCA6IChUWVBFX0FMSUFTRVNbdF0gfHwgbnVsbClcbmZ1bmN0aW9uIHJlYWRKc29uU2FmZShwKSB7IHRyeSB7IHJldHVybiBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhwLCAndXRmOCcpKSB9IGNhdGNoIHsgcmV0dXJuIG51bGwgfSB9XG5cbi8vIENsYXNzaWZ5IG9uZSBwcm9maWxlIGludG8gYSB0eXBlLiBQcmVjZWRlbmNlOiBleHBsaWNpdCA8cHJvZmlsZT4ubWV0YS5qc29uIChtYWNoaW5lIGtleVxuLy8gb3IgZGlzcGxheSBhbGlhcykgXHUyMTkyIHBhcmFtZXRlcml6ZWQgKHRoZSBidW5kbGUgc2hpcHMgYW4gKi5pbnN0YW5jZXMuanNvbikgXHUyMTkyIHNpbmdsZSAodGhlXG4vLyBzaW1wbGVzdCwgZGVmYXVsdCkuIENvbXBvc2l0ZSBraW5kcyBhcmUgbmV2ZXIgaW5mZXJyZWQgZnJvbSBzb3VyY2UuXG5leHBvcnQgZnVuY3Rpb24gZGV0ZWN0UHJvZmlsZVR5cGUoZGlyLCBwcm9maWxlLCBvd25UYWcsIGFsbFRhZ3MsIGhhc0luc3RhbmNlcykge1xuICBjb25zdCBtZXRhID0gcmVhZEpzb25TYWZlKHJlc29sdmUoZGlyLCBgJHtwcm9maWxlfS5tZXRhLmpzb25gKSlcbiAgY29uc3QgZGVjbGFyZWQgPSBtZXRhICYmIG5vcm1hbGl6ZVR5cGUobWV0YS50eXBlKVxuICBpZiAoZGVjbGFyZWQpIHJldHVybiB7IHR5cGU6IGRlY2xhcmVkLCBsYWJlbDogbWV0YS5sYWJlbCB8fCBwcm9maWxlIH1cbiAgLy8gUmVsaWFibGUgYXV0by1zaWduYWxzIE9OTFkgKHNvdXJjZSB0YWctc2Nhbm5pbmcgY2F1c2VkIGZhbHNlIHBvc2l0aXZlcyk6XG4gIC8vICAgYSBidW5kbGUgd2l0aCBhbiAqLmluc3RhbmNlcy5qc29uIC0+IHBhcmFtZXRlcml6ZWQ7IG90aGVyd2lzZSB0aGUgc2ltcGxlc3QgdGllciwgc2luZ2xlLlxuICAvLyBDb21wb3NpdGUgdGllcnMgKG1vbm9saXRoaWMgLyBuZXN0ZWQtZWxlbWVudHMtbWZlIC8gbmVzdGVkLW1mZS1zcGEpIGFyZSBBVVRIT1JFRCB2aWEgYW5cbiAgLy8gZXhwbGljaXQgPHByb2ZpbGU+Lm1ldGEuanNvbiB7XCJ0eXBlXCI6IC4uLn0gXHUyMDE0IHRoZSBzaW5nbGUgc291cmNlIG9mIHRydXRoIChkb2N1bWVudGF0aW9uL3JlZmVyZW5jZS5tZCxcbiAgLy8gJ1Byb2ZpbGUgdHlwZXMgXHUyMDE0IHRoZSBjb21wb3NhYmlsaXR5IGxhZGRlcicpLiBTZWUgZWNvLWR4IChpbnRlcm5hbCk6IFBTMDAxLWNvbXBvc2l0aW9uLW1vZGVsLlxuICBjb25zdCB0eXBlID0gaGFzSW5zdGFuY2VzID8gJ3BhcmFtZXRlcml6ZWQnIDogJ3NpbmdsZSdcblxuICAvLyBcdTI2MDUgVElFUi12cy1DT01QTEVYSVRZIFdBUk5JTkcgXHUyMDE0IGFuIElORkVSRU5DRSBGQUxMQkFDSyBpcyBub3QgYSBERUNMQVJBVElPTi5cbiAgLy8gSGl0IGZvciByZWFsIDIwMjYtMDktMjA6IHJlc2VhcmNoLWRhc2hib2FyZCBoYWQgTk8gbWV0YS5qc29uLCBzbyBpdCBmZWxsIHRocm91Z2ggdG9cbiAgLy8gYHNpbmdsZWAgPSBDQVBBQklMSVRZIDEgXHUyMDE0IHdoaWxlIGFjdHVhbGx5IG5lc3RpbmcgVEVOIGludGVybmFsIHZpZXcgY29tcG9uZW50cyBiZWhpbmQgYVxuICAvLyByZXNwb25zaXZlIHNoZWxsIGFuZCByZW5kZXJpbmcgfjEsMTAwIGVsZW1lbnRzLiBJdCBpcyBtb25vbGl0aGljIChjYXAtMykuIE5vdGhpbmcgd2FybmVkO1xuICAvLyBhIG1pc3NpbmcgZmlsZSBpcyBpbmRpc3Rpbmd1aXNoYWJsZSBmcm9tIGEgZGVsaWJlcmF0ZSBjaG9pY2UsIGFuZCB0aGUgdW5kZXJzdGF0ZW1lbnQgcG9pbnRzXG4gIC8vIHRoZSBkaXJlY3Rpb24gbm9ib2R5IGF1ZGl0cyAodGhlIG1hbmlmZXN0LCB0aGUgZ2FsbGVyeSBhbmQgZXZlcnkgY2FwYWJpbGl0eSBjbGFpbSByZWFkIHRoaXMpLlxuICAvL1xuICAvLyBUSEUgU0lHTkFMIElTIE1FQVNVUkVELCBOT1QgR1VFU1NFRC4gQ291bnRpbmcgY2hpbGQgLnZ1ZSBmaWxlcyB1bmRlciB0aGUgYnVuZGxlIChleGNsdWRpbmdcbiAgLy8gaXRzIHJvb3QgcHJvZmlsZXMpIGFjcm9zcyBhbGwgMTggYnVuZGxlcyBnaXZlczogcmVzZWFyY2gtZGFzaGJvYXJkIDEwLCBiaWctcGljdHVyZSAxLCBhbmRcbiAgLy8gWkVSTyBmb3IgZXZlcnkgb3RoZXIgYnVuZGxlLiBUaGUgaW50ZW5kZWQgY2F0Y2ggc2l0cyBhbiBvcmRlciBvZiBtYWduaXR1ZGUgYWJvdmUgZXZlcnkgb3RoZXJcbiAgLy8gc2FtcGxlLCBzbyB0aGlzIGlzIGEgcmVhbCBnYXAgaW4gdGhlIGRhdGEgcmF0aGVyIHRoYW4gYSB0dW5lZCBjdXRvZmYuXG4gIC8vXG4gIC8vIE9OTFkgRklSRVMgT04gQU4gSU5GRVJSRUQgVFlQRSBcdTIwMTQgbmV2ZXIgc2Vjb25kLWd1ZXNzZXMgYW4gZXhwbGljaXQgbWV0YS5qc29uLiBkb3hhLXJlc2VhcmNoLW1hcFxuICAvLyBpcyBERUNMQVJFRCBtb25vbGl0aGljIHdpdGggMCBjaGlsZCAudnVlIGZpbGVzLCB3aGljaCBpcyBwZXJmZWN0bHkgbGVnaXRpbWF0ZTogY29tcGxleGl0eSBjYW5cbiAgLy8gbGl2ZSBpbiBvbmUgYmlnIGZpbGUuIEFic2VuY2Ugb2YgdGhlIHNpZ25hbCBwcm92ZXMgbm90aGluZzsgcHJlc2VuY2Ugb2YgaXQgcGx1cyBubyBkZWNsYXJhdGlvblxuICAvLyBpcyB3aGF0IGlzIHN1c3BpY2lvdXMuIFdBUk5TIHJhdGhlciB0aGFuIGZhaWxzOiB0aGlzIGlzIGEgaGV1cmlzdGljIGFib3V0IGF1dGhvcmluZyBpbnRlbnQsXG4gIC8vIGFuZCB0aGUgY29kZWJhc2UncyBzdGFuZGluZyBydWxlIGlzIHRoYXQgY29tcG9zaXRlIHRpZXJzIGFyZSBBVVRIT1JFRCwgbm90IGluZmVycmVkLlxuICB0cnkge1xuICAgIGNvbnN0IGNoaWxkVnVlID0gY291bnRDaGlsZFZ1ZShkaXIpXG4gICAgaWYgKGNoaWxkVnVlID49IDUpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYFtkaXNjb3Zlcl0gJHtwcm9maWxlfTogdHlwZSBJTkZFUlJFRCBhcyBcIiR7dHlwZX1cIiBidXQgdGhlIGJ1bmRsZSBoYXMgJHtjaGlsZFZ1ZX0gY2hpbGQgYCArXG4gICAgICAgICcudnVlIGNvbXBvbmVudHMuIFRpZXIgMysgaXMgbmV2ZXIgaW5mZXJyZWQgXHUyMDE0IGlmIHRoaXMgbmVzdHMgbXVsdGlwbGUgdmlld3MgaW50ZXJuYWxseSBpdCAnICtcbiAgICAgICAgYGlzIFwibW9ub2xpdGhpY1wiOyBpZiBpdHMgY2hpbGRyZW4gYXJlIGluZGVwZW5kZW50bHkgZW1iZWRkYWJsZSBpdCBpcyBcIm5lc3RlZC1lbGVtZW50cy1tZmVcIi4gYCArXG4gICAgICAgIGBEZWNsYXJlIGl0IGluICR7cHJvZmlsZX0ubWV0YS5qc29uIHtcInR5cGVcIjogLi4ufSBvciB0aGlzIHNoaXBzIHVuZGVyc3RhdGVkLmBcbiAgICAgIClcbiAgICB9XG4gIH0gY2F0Y2ggeyAvKiBhZHZpc29yeSBvbmx5IFx1MjAxNCBuZXZlciBsZXQgdGhlIHdhcm5pbmcgYnJlYWsgYSBidWlsZCAqLyB9XG5cbiAgcmV0dXJuIHsgdHlwZSwgbGFiZWw6IChtZXRhICYmIG1ldGEubGFiZWwpIHx8IHByb2ZpbGUgfVxufVxuXG4vKiogQ291bnQgLnZ1ZSBmaWxlcyBCRUxPVyBhIGJ1bmRsZSBkaXIgKGl0cyByb290IHByb2ZpbGVzIGRvIG5vdCBjb3VudCBhcyBuZXN0ZWQgdmlld3MpLiAqL1xuZnVuY3Rpb24gY291bnRDaGlsZFZ1ZShkaXIpIHtcbiAgbGV0IG4gPSAwXG4gIGNvbnN0IHdhbGsgPSAoZCwgZGVwdGgpID0+IHtcbiAgICBmb3IgKGNvbnN0IGUgb2YgcmVhZGRpclN5bmMoZCwgeyB3aXRoRmlsZVR5cGVzOiB0cnVlIH0pKSB7XG4gICAgICBpZiAoZS5uYW1lLnN0YXJ0c1dpdGgoJy4nKSB8fCBlLm5hbWUgPT09ICdub2RlX21vZHVsZXMnKSBjb250aW51ZVxuICAgICAgY29uc3QgcCA9IHJlc29sdmUoZCwgZS5uYW1lKVxuICAgICAgaWYgKGUuaXNEaXJlY3RvcnkoKSkgd2FsayhwLCBkZXB0aCArIDEpXG4gICAgICBlbHNlIGlmIChkZXB0aCA+IDAgJiYgZS5uYW1lLmVuZHNXaXRoKCcudnVlJykpIG4rK1xuICAgIH1cbiAgfVxuICB3YWxrKGRpciwgMClcbiAgcmV0dXJuIG5cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRpc2NvdmVyU3BhUmVnaXN0cnkocm9vdCA9IFJFUE9fUk9PVCkge1xuICBjb25zdCBBUFBfRElSID0gcmVzb2x2ZShyb290LCAncGx1Z2luLWRlc2lnbnMnKVxuICBjb25zdCBidW5kbGVzID0gW11cbiAgaWYgKCFleGlzdHNTeW5jKEFQUF9ESVIpKSByZXR1cm4gYnVuZGxlc1xuICBjb25zdCBkaXJzID0gcmVhZGRpclN5bmMoQVBQX0RJUikuc29ydCgpLmZpbHRlcihuID0+IHtcbiAgICBjb25zdCBkID0gcmVzb2x2ZShBUFBfRElSLCBuKVxuICAgIHJldHVybiBzdGF0U3luYyhkKS5pc0RpcmVjdG9yeSgpICYmIG4gIT09ICd0ZW1wbGF0ZS1idW5kbGUnICYmIGV4aXN0c1N5bmMocmVzb2x2ZShkLCAnaW5kZXguanMnKSlcbiAgfSlcbiAgLy8gRmlyc3QgcGFzczogZXZlcnkgYnVuZGxlJ3MgZWxlbWVudCB0YWcgKG5lZWRlZCBmb3IgY29tcG9zaXRlIGRldGVjdGlvbikuXG4gIGNvbnN0IHRhZ09mID0ge31cbiAgZm9yIChjb25zdCBuIG9mIGRpcnMpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgbSA9IHJlYWRGaWxlU3luYyhyZXNvbHZlKEFQUF9ESVIsIG4sICdpbmRleC5qcycpLCAndXRmOCcpLm1hdGNoKC9jdXN0b21FbGVtZW50c1xcLmRlZmluZVxcKFxccypbJ1wiXShbXidcIl0rKVsnXCJdLylcbiAgICAgIGlmIChtKSB0YWdPZltuXSA9IG1bMV1cbiAgICB9IGNhdGNoIHsgLyogaWdub3JlICovIH1cbiAgfVxuICBjb25zdCBhbGxUYWdzID0gT2JqZWN0LnZhbHVlcyh0YWdPZilcbiAgZm9yIChjb25zdCBuIG9mIGRpcnMpIHtcbiAgICBjb25zdCBkaXIgPSByZXNvbHZlKEFQUF9ESVIsIG4pLCB0YWcgPSB0YWdPZltuXVxuICAgIGlmICghdGFnKSBjb250aW51ZVxuICAgIGNvbnN0IGZpbGVzID0gcmVhZGRpclN5bmMoZGlyKVxuICAgIGNvbnN0IGluc3RGaWxlID0gZmlsZXMuZmluZChmID0+IC9cXC5pbnN0YW5jZXNcXC5qc29uJC9pLnRlc3QoZikpXG4gICAgY29uc3QgcmF3SW5zdCA9IGluc3RGaWxlID8gcmVhZEpzb25TYWZlKHJlc29sdmUoZGlyLCBpbnN0RmlsZSkpIDogbnVsbFxuICAgIGNvbnN0IGluc3RhbmNlcyA9IEFycmF5LmlzQXJyYXkocmF3SW5zdCkgPyByYXdJbnN0IDogKHJhd0luc3QgJiYgQXJyYXkuaXNBcnJheShyYXdJbnN0Lmluc3RhbmNlcykgPyByYXdJbnN0Lmluc3RhbmNlcyA6IG51bGwpXG4gICAgY29uc3QgaGFzSW5zdGFuY2VzID0gISEoaW5zdGFuY2VzICYmIGluc3RhbmNlcy5sZW5ndGgpXG4gICAgLy8gVGhlIHRhYmxlJ3MgZGF0YSBBUEkgKGl0cyB0b3AtbGV2ZWwgYXBpQmFzZVVybCksIGJha2VkIHBlciBpbnN0YW5jZSBhcyBnZW5lcmF0ZS10cmVlIGRvZXMuXG4gICAgY29uc3QgaW5zdEFwaSA9IHJhd0luc3QgJiYgIUFycmF5LmlzQXJyYXkocmF3SW5zdCkgJiYgdHlwZW9mIHJhd0luc3QuYXBpQmFzZVVybCA9PT0gJ3N0cmluZycgPyByYXdJbnN0LmFwaUJhc2VVcmwgOiAnJ1xuICAgIGNvbnN0IGl0ZW1zID0gW11cbiAgICBmb3IgKGNvbnN0IHByb2ZpbGUgb2YgZmlsZXMuZmlsdGVyKGYgPT4gZi5lbmRzV2l0aCgnLnZ1ZScpKS5tYXAoZiA9PiBmLnJlcGxhY2UoL1xcLnZ1ZSQvLCAnJykpLnNvcnQoKSkge1xuICAgICAgY29uc3QgdCA9IGRldGVjdFByb2ZpbGVUeXBlKGRpciwgcHJvZmlsZSwgdGFnLCBhbGxUYWdzLCBoYXNJbnN0YW5jZXMpXG4gICAgICBpZiAodC50eXBlID09PSAncGFyYW1ldGVyaXplZCcgJiYgaGFzSW5zdGFuY2VzKSB7XG4gICAgICAgIC8vIEV4cGFuZCB0aGUgcGFyYW1ldGVyaXplZCB0YWJsZSBpbnRvIG9uZSBlbGVtZW50IFBFUiBwcmVjb25maWd1cmVkIGluc3RhbmNlLlxuICAgICAgICBmb3IgKGNvbnN0IGluc3Qgb2YgaW5zdGFuY2VzKSB7XG4gICAgICAgICAgaXRlbXMucHVzaCh7IHByb2ZpbGUsIGlkOiBpbnN0LmlkIHx8IGluc3QudGl0bGUgfHwgcHJvZmlsZSwgbGFiZWw6IGluc3QudGl0bGUgfHwgaW5zdC5pZCB8fCBwcm9maWxlLCB0eXBlOiAncGFyYW1ldGVyaXplZCcsIHByb3BzOiBpbnN0LnByb3BzIHx8IHt9LCBhcGlCYXNlVXJsOiBpbnN0QXBpIH0pXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGl0ZW1zLnB1c2goeyBwcm9maWxlLCBpZDogcHJvZmlsZSwgbGFiZWw6IHQubGFiZWwsIHR5cGU6IHQudHlwZSwgcHJvcHM6IG51bGwgfSlcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFpdGVtcy5sZW5ndGgpIGNvbnRpbnVlXG4gICAgLy8gU29ydCBieSBjb21wb3NhYmlsaXR5IHRpZXIgT05MWSAoc3RhYmxlKSBzbyBwYXJhbWV0ZXJpemVkIGluc3RhbmNlcyBrZWVwIHRoZWlyXG4gICAgLy8gZGVjbGFyZWQgdGFibGUgb3JkZXIgXHUyMDE0IGUuZy4gUHJheWVyIE1hcCBzdGF5cyBmaXJzdCwgYXMgdGhlIGxhbmRpbmcgdmlldy5cbiAgICBpdGVtcy5zb3J0KChhLCBiKSA9PiAoUFJPRklMRV9USUVSW2EudHlwZV0gPz8gOSkgLSAoUFJPRklMRV9USUVSW2IudHlwZV0gPz8gOSkpXG4gICAgY29uc3QgYmVzdFRpZXIgPSBNYXRoLm1pbiguLi5pdGVtcy5tYXAoaSA9PiBQUk9GSUxFX1RJRVJbaS50eXBlXSA/PyA5KSlcbiAgICBidW5kbGVzLnB1c2goeyBidW5kbGU6IG4sIHRhZywgaXRlbXMsIGJlc3RUaWVyIH0pXG4gIH1cbiAgYnVuZGxlcy5zb3J0KChhLCBiKSA9PiBhLmJlc3RUaWVyIC0gYi5iZXN0VGllciB8fCBhLmJ1bmRsZS5sb2NhbGVDb21wYXJlKGIuYnVuZGxlKSlcbiAgcmV0dXJuIGJ1bmRsZXNcbn1cbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL2hvbWUvbGsxMHgvV29ya3NwYWNlL2Vjby1keC9yb290LWRveGEtbWFwcy93dC1oZi9pbnRlcm5hbFwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL2hvbWUvbGsxMHgvV29ya3NwYWNlL2Vjby1keC9yb290LWRveGEtbWFwcy93dC1oZi9pbnRlcm5hbC9nZW5lcmF0ZS1nYWxsZXJ5Lm1qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vaG9tZS9sazEweC9Xb3Jrc3BhY2UvZWNvLWR4L3Jvb3QtZG94YS1tYXBzL3d0LWhmL2ludGVybmFsL2dlbmVyYXRlLWdhbGxlcnkubWpzXCI7LyoqXG4gKiBnZW5lcmF0ZS1nYWxsZXJ5Lm1qcyBcdTIwMTQgVEhFIHBsdWdpbiBnYWxsZXJ5OiBvbmUgZ2VuZXJhdG9yLCB0d28gbW9kZXMuXG4gKiAoTm8gc2hlYmFuZyBvbiBwdXJwb3NlOiB2aXRlLmNvbmZpZy5qcyBpbXBvcnRzIHRoaXMgbW9kdWxlIHRocm91Z2ggVml0ZSdzIGNvbmZpZyBidW5kbGVyLFxuICogd2hpY2ggcHJlcGVuZHMgYSBzaGltIHRvIGV2ZXJ5IGJ1bmRsZWQgZmlsZSBcdTIwMTQgYSBzaGViYW5nIGJlbG93IGxpbmUgMSBpcyBhIHN5bnRheCBlcnJvciB0aGVyZS4pXG4gKlxuICogICByZW5kZXJHYWxsZXJ5KG1vZGVsLCB7IG1vZGU6ICdidWlsZCcgfSkgICBwdWJsaWMvX19nYWxsZXJ5L2luZGV4Lmh0bWwgXHUyMDE0IEFSQ0hJVkVEIGJlc2lkZSB0aGVcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdCwgd3JpdHRlbiBieSBgYnVuIHJ1biBnYWxsZXJ5YCAobGFzdCBzdGVwIG9mXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBidW4gcnVuIGJ1aWxkYCkgZnJvbSBwdWJsaWMvPHRyZWU+L21hbmlmZXN0Lmpzb24uXG4gKiAgIHJlbmRlckdhbGxlcnkobW9kZWwsIHsgbW9kZTogJ2RldicgfSkgICAgIHdoYXQgYGJ1biBydW4gZGV2YCBzZXJ2ZXMgYXQgL19fZ2FsbGVyeSBcdTIwMTQgdGhlIHNhbWVcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZSBvdmVyIGEgbWFuaWZlc3Qtc2hhcGVkIG1vZGVsIG9mIHBsdWdpbi1kZXNpZ25zL1xuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc2VlIGludGVybmFsL3BsdWdpbi1nYWxsZXJ5L2Rldi1wbHVnaW4ubWpzKS5cbiAqXG4gKiBcdTI2MDUgVEhJUyBJUyBOTyBMT05HRVIgVEhFIFJPT1QgUEFHRSAoMjAyNi0wOS0yMikuIEluIEJPVEggdHJlZXMgYC9gIG5vdyBtb3VudHMgPHBsdWdpbi1zdHVkaW8+LFxuICogdGhlIGNhcC01IGRldmVsb3BlciBzdHVkaW87IHRoaXMgZ2FsbGVyeSBpcyB0aGUgYXJjaGl2ZWQgYnVuZGxlIGluZGV4IGF0IC9fX2dhbGxlcnkuIFRoZSBtb2R1bGVcbiAqIHN0YXlzIGJlY2F1c2UgaXQgaXMgbG9hZC1iZWFyaW5nLCBub3QgZm9yIHRoZSBwYWdlIGFsb25lOiB0aGUgZGV2IHBsdWdpbiBpbXBvcnRzIHJlbmRlckdhbGxlcnkoKVxuICogYW5kIHJlYWRCdWlsZENvbmZpZygpLCBhbmQgaXQgY29tcHV0ZXMgdGhlIG1hbmlmZXN0LXNoYXBlZCBtb2RlbCBib3RoIHRyZWVzIHJlbmRlci5cbiAqXG4gKiBwdWJsaWMvIGhvbGRzIGFzc2V0cy8gKGRhdGEpLCA8dHJlZT4vICh0aGUgYnVuZGxlIGZvbGRlcnMgKyBtYW5pZmVzdC5qc29uKSwgdGhlIGdlbmVyYXRlZCByb290XG4gKiBwYWdlICh0aGUgc3R1ZGlvIGhvc3QsIHdyaXR0ZW4gYnkgaW50ZXJuYWwvZ2VuZXJhdGUtdHJlZS5tanMpIGFuZCBfX2dhbGxlcnkvIFx1MjAxNCB0aGlzIHBhZ2UsIHdoaWNoXG4gKiBsaXN0cyBldmVyeSBidW5kbGUgXHUyMTkyIHByb2ZpbGUgXHUyMTkyIGluc3RhbmNlIHRoZSBtYW5pZmVzdCBkZWNsYXJlcyBhbmRcbiAqIG1vdW50cyB0aGUgY2hvc2VuIG9uZS4gSXQgaXMgR0VORVJBVEVEIFx1MjAxNCBuZXZlciBoYW5kLWVkaXRlZCBcdTIwMTQgYXMgYSBzaW5nbGUgc3RhdGljIGZpbGU6IGlubGluZVxuICogQ1NTLCBpbmxpbmUgdmFuaWxsYSBKUywgZXZlcnkgcGF0aCByZWxhdGl2ZSwgc28gdGhlIHNhbWUgZmlsZSB3b3JrcyBmcm9tIGFueSBzdGF0aWMgaG9zdCxcbiAqIHVuZGVyIGEgc3VicGF0aCAodGhlIHdlYnNpdGUgc2VydmVzIGl0IGF0IC9lbWJlZC9kb3hhLW1hcHMtYnVpbGQvaW5kZXguaHRtbCkgYW5kIGZyb20gZmlsZTovLy5cbiAqXG4gKiBBdCBydW50aW1lIHRoZSBwYWdlIGZldGNoZXMgPHRyZWU+L21hbmlmZXN0Lmpzb24gc28gaXQgc3RheXMgY29ycmVjdCB3aGVuIGJ1bmRsZXMgY2hhbmdlOyBhXG4gKiBjb21wYWN0IGNvcHkgb2YgdGhlIG1hbmlmZXN0IGlzIGJha2VkIGluIGFzIHRoZSBmYWxsYmFjayAoZmlsZTovLywgb3IgdGhlIGZldGNoIGZhaWxzKS4gRW1iZWRcbiAqIHNuaXBwZXRzIGFyZSByZS1kZXJpdmVkIGZyb20gdGhlIG1hbmlmZXN0IGZpZWxkcyB3aXRoIHRoZSB0ZW1wbGF0ZSBnZW5lcmF0ZS10cmVlIHVzZXM7IHRoaXNcbiAqIHNjcmlwdCBjaGVja3MgdGhlIGRlcml2YXRpb24gYWdhaW5zdCBldmVyeSBtYW5pZmVzdCBzbmlwcGV0IGFuZCBiYWtlcyBhbnkgdGhhdCBkaWZmZXIsIHNvIHRoZVxuICogZmFsbGJhY2sgaXMgZXhhY3Qgd2l0aG91dCBjYXJyeWluZyB0aGUgc25pcHBldHMgdHdpY2UuXG4gKlxuICogVGhlIGNob3NlbiBtYXAgbW91bnRzIGV4YWN0bHkgbGlrZSBpdHMgbGVhZiBwYWdlOiBzYW1lIHBlZXIgZW5naW5lIChNYXBib3gsIG9yIE1hcExpYnJlIGZvciBhXG4gKiBwcm92aWRlcjonbWFwbGlicmUnIGluc3RhbmNlKSwgc2FtZSBwcm9maWxlLWNvbmZpZyAoYXNzZXRzQmFzZSwgZGF0YVNvdXJjZSwgaW5zdGFuY2VJZCBvciB0aGVcbiAqIGluc3RhbmNlIHByb3BzKSwgd2luZG93Lk1BUF9BUFBfQVBJX1VSTCwgYW5kIHRoZSBzYW1lIHRva2VuIGxhZGRlciBcdTIwMTQgcHJvZmlsZS1jb25maWcgdGsgXHUyMTkyXG4gKiA/dGs9IG9uIHRoaXMgcGFnZSdzIFVSTCBcdTIxOTIgdGhlIHBhc3RlLW9uY2UgbG9jYWxTdG9yYWdlIHRva2VuIFx1MjE5MiBiYWtlZCB0b2tlbiBcdTIxOTIgd2luZG93Lk1BUF9UT0tFTl9VUkxcbiAqIFx1MjE5MiB0aGUgY29uZmlndXJlZCB0b2tlblVybCBcdTIxOTIgc2FtZS1vcmlnaW4gL2FwaS9tYXBzL3Rva2VuIFx1MjE5MiBhc2sgb25jZS5cbiAqXG4gKiBEZWVwIGxpbms6ICMvPGJ1bmRsZT4vPHByb2ZpbGU+Wy88aW5zdGFuY2U+XS4gQWN0aW9uczogT3BlbiBwYWdlICh0aGUgbGVhZiBwYWdlKSwgQ29weSBlbWJlZFxuICogKHRoZSBtYW5pZmVzdCdzIGVtYmVkLmlmcmFtZSAvIGVtYmVkLnNjcmlwdCkuXG4gKlxuICogV2hhdCBtb2RlICdkZXYnIGNoYW5nZXMgXHUyMDE0IGFuZCBub3RoaW5nIGVsc2U6IHRoZSBsb2FkZXIgaW1wb3J0cyB0aGUgYnVuZGxlJ3MgZGV2IGVudHJ5XG4gKiAoc2NyaXB0VXJsID0gL3BsdWdpbi1kZXNpZ25zLzxidW5kbGU+L2luZGV4LmpzLCBhbiBFUyBtb2R1bGUgVml0ZSBzZXJ2ZXMpIGluc3RlYWQgb2YgYWRkaW5nIGFuXG4gKiBJSUZFIHNjcmlwdCB0YWc7IHRoZSBsaXZlIG1vZGVsIGlzIGZldGNoZWQgZnJvbSB0aGUgZGV2IHJvdXRlICg8dHJlZT4gPSBfX3BsdWdpbi1nYWxsZXJ5KTsgYW5kXG4gKiB0aGUgaGVhZGVyIGNhcnJpZXMgdGhlIGNvbXBvc2FiaWxpdHkgbGFkZGVyIHdpdGggaXRzIFwiP1wiIHBvcG92ZXJzIChraW5kIGV4cGxhbmF0aW9ucyArIHRoZVxuICogXCJTdGFydCBoZXJlXCIgcHJpbWVyKS4gVGhlIHBvcG92ZXJzIHN0YXkgb3V0IG9mIHRoZSBidWlsdCBwYWdlIG9uIHB1cnBvc2U6IHRoZXkgYWRkIH44IEtCIG9mXG4gKiB0ZXh0IHRvIGEgMjIgS0IgcGFnZSBhbmQgZXhwbGFpbiB0aGUgc291cmNlIHRyZWUsIHdoaWNoIGEgdmlzaXRvciBvZiB0aGUgc2VydmVkIHJvb3QgbmV2ZXIgc2Vlcy5cbiAqXG4gKiBVc2FnZTogIG5vZGUgaW50ZXJuYWwvZ2VuZXJhdGUtZ2FsbGVyeS5tanMgICAgICAoYGJ1biBydW4gZ2FsbGVyeWAgXHUyMDE0IGxhc3Qgc3RlcCBvZiBgYnVuIHJ1biBidWlsZGApXG4gKi9cbmltcG9ydCB7IHJlYWRGaWxlU3luYywgd3JpdGVGaWxlU3luYywgZXhpc3RzU3luYywgcmVhZGRpclN5bmMsIG1rZGlyU3luYyB9IGZyb20gJ25vZGU6ZnMnXG5pbXBvcnQgeyBqb2luLCByZXNvbHZlLCBkaXJuYW1lIH0gZnJvbSAnbm9kZTpwYXRoJ1xuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCwgcGF0aFRvRmlsZVVSTCB9IGZyb20gJ25vZGU6dXJsJ1xuaW1wb3J0IHsgUFJPRklMRV9USUVSLCBUWVBFX0RJU1BMQVksIGRldGVjdFByb2ZpbGVUeXBlIH0gZnJvbSAnLi9wbHVnaW4tZ2FsbGVyeS9kaXNjb3Zlci5tanMnXG5pbXBvcnQgeyBUUkVFX05BTUUgfSBmcm9tICcuL190cmVlLW5hbWUubWpzJ1xuXG5jb25zdCBST09UID0gcmVzb2x2ZShkaXJuYW1lKGZpbGVVUkxUb1BhdGgoaW1wb3J0Lm1ldGEudXJsKSksICcuLicpXG5cbi8vIENvbXBvc2l0aW9uIHRpZXIgXHUyMTkyIGNhcGFiaWxpdHkgbnVtYmVyICg1ID0gYXBwLXNoZWxsL25lc3RlZC1tZmUtc3BhIFx1MjAyNiAxID0gc2luZ2xlLWVsZW1lbnQpLlxuLy8gVGhlIHBsdWdpbiBzdHVkaW8gaXMgaXRzZWxmIHRoZSBuZXN0ZWQtbWZlLXNwYSAoY2FwYWJpbGl0eSA1KSBcdTIwMTQgdGhlIHJlc2VydmVkIGFwcC1zaGVsbCBrZXkuXG4vLyBjYXAgPSA1IC0gUFJPRklMRV9USUVSIChuZXN0ZWQtbWZlLXNwYTowXHUyMTkyNSBcdTAwQjcgbmVzdGVkLWVsZW1lbnRzLW1mZToxXHUyMTkyNCBcdTAwQjcgbW9ub2xpdGhpYzoyXHUyMTkyMyBcdTAwQjdcbi8vIHBhcmFtZXRlcml6ZWQ6M1x1MjE5MjIgXHUwMEI3IHNpbmdsZTo0XHUyMTkyMSkuIFVua25vd24gXHUyMTkyIDEgKHNpbmdsZSwgdGhlIHNhZmUgZmxvb3IpLlxuZXhwb3J0IGNvbnN0IENBUF9PRiA9ICh0eXBlKSA9PiAoUFJPRklMRV9USUVSW3R5cGVdICE9IG51bGwgPyA1IC0gUFJPRklMRV9USUVSW3R5cGVdIDogMSlcblxuLy8gQnVpbGQtbW9kZTogdGhlIG1hbmlmZXN0IGNhcnJpZXMgbm8gY29tcG9zaXRpb24gdGllciwgc28gcmVhZCBpdCBmcm9tIHNvdXJjZSB0aGUgd2F5IHRoZVxuLy8gZGV2IGRpc2NvdmVyeSBkb2VzIChleHBsaWNpdCA8cHJvZmlsZT4ubWV0YS5qc29uIFx1MjE5MiBhbiAqLmluc3RhbmNlcy5qc29uIG1lYW5zIHBhcmFtZXRlcml6ZWQgXHUyMTkyXG4vLyBzaW5nbGUpLiBSZXR1cm5zIHsgXCI8YnVuZGxlPi88cHJvZmlsZT5cIjogXCI8bWFjaGluZSBrZXk+XCIgfS4gUHVyZSBiZXN0LWVmZm9ydDogYSBtaXNzaW5nIHRyZWVcbi8vIG9yIHVucmVhZGFibGUgZm9sZGVyIGp1c3QgeWllbGRzIHt9IGFuZCBldmVyeSBwcm9maWxlIGZhbGxzIGJhY2sgdG8gY2FwYWJpbGl0eSAxLlxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRTb3VyY2VUaWVycyhhcHBEaXIgPSBqb2luKFJPT1QsICdwbHVnaW4tZGVzaWducycpKSB7XG4gIGNvbnN0IG91dCA9IHt9XG4gIGlmICghZXhpc3RzU3luYyhhcHBEaXIpKSByZXR1cm4gb3V0XG4gIGxldCBkaXJzID0gW11cbiAgdHJ5IHsgZGlycyA9IHJlYWRkaXJTeW5jKGFwcERpciwgeyB3aXRoRmlsZVR5cGVzOiB0cnVlIH0pLmZpbHRlcigoZCkgPT4gZC5pc0RpcmVjdG9yeSgpKS5tYXAoKGQpID0+IGQubmFtZSkgfSBjYXRjaCB7IHJldHVybiBvdXQgfVxuICBmb3IgKGNvbnN0IGJ1bmRsZSBvZiBkaXJzKSB7XG4gICAgY29uc3QgZGlyID0gam9pbihhcHBEaXIsIGJ1bmRsZSlcbiAgICBsZXQgZmlsZXMgPSBbXVxuICAgIHRyeSB7IGZpbGVzID0gcmVhZGRpclN5bmMoZGlyKSB9IGNhdGNoIHsgY29udGludWUgfVxuICAgIGNvbnN0IGhhc0luc3RhbmNlcyA9IGZpbGVzLnNvbWUoKGYpID0+IC9cXC5pbnN0YW5jZXNcXC5qc29uJC9pLnRlc3QoZikpXG4gICAgZm9yIChjb25zdCBmIG9mIGZpbGVzKSB7XG4gICAgICBpZiAoIWYuZW5kc1dpdGgoJy52dWUnKSkgY29udGludWVcbiAgICAgIGNvbnN0IHByb2ZpbGUgPSBmLnJlcGxhY2UoL1xcLnZ1ZSQvLCAnJylcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHQgPSBkZXRlY3RQcm9maWxlVHlwZShkaXIsIHByb2ZpbGUsICcnLCBbXSwgaGFzSW5zdGFuY2VzKVxuICAgICAgICBvdXRbYnVuZGxlICsgJy8nICsgcHJvZmlsZV0gPSB0LnR5cGVcbiAgICAgIH0gY2F0Y2ggeyAvKiBsZWF2ZSB1bmxpc3RlZCBcdTIxOTIgY2FwYWJpbGl0eSAxICovIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIG91dFxufVxuXG4vLyBTYW1lIGZpZWxkcyB0aGUgdHJlZSBnZW5lcmF0b3IgYmFrZXMgaW50byBldmVyeSBsZWFmIHBhZ2UgKHZpdGUuZG94YS1tYXBzLWJ1aWxkLWNvbmZpZy5qc29uKS5cbmV4cG9ydCBmdW5jdGlvbiByZWFkQnVpbGRDb25maWcoKSB7XG4gIGxldCBjZmcgPSB7fVxuICB0cnkgeyBjZmcgPSBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhqb2luKFJPT1QsICd2aXRlLmRveGEtbWFwcy1idWlsZC1jb25maWcuanNvbicpLCAndXRmOCcpKSB9IGNhdGNoIHsgLyogZGVmYXVsdHMgKi8gfVxuICBjb25zdCBzdHIgPSAoaykgPT4gKHR5cGVvZiBjZmdba10gPT09ICdzdHJpbmcnID8gY2ZnW2tdLnRyaW0oKSA6ICcnKVxuICBsZXQgdG9rZW5VcmwgPSBzdHIoJ3Rva2VuVXJsJylcbiAgaWYgKCF0b2tlblVybCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBzcmMgPSBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhqb2luKFJPT1QsICdsaWJyYXJ5L2FwaS9zb3VyY2VzLmpzb24nKSwgJ3V0ZjgnKSlcbiAgICAgIGNvbnN0IHYgPSBzcmM/Ll9tZXRhPy5tYXBib3hUb2tlblVybCB8fCBzcmM/Lm1hcGJveFRva2VuVXJsXG4gICAgICBpZiAodHlwZW9mIHYgPT09ICdzdHJpbmcnICYmIHYudHJpbSgpKSB0b2tlblVybCA9IHYudHJpbSgpXG4gICAgfSBjYXRjaCB7IC8qIGZhbGwgdGhyb3VnaCAqLyB9XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiBzdHIoJ25hbWUnKSB8fCBUUkVFX05BTUUsXG4gICAgdGl0bGU6IHN0cignZGlzcGxheVRpdGxlJykgfHwgVFJFRV9OQU1FLFxuICAgIHRva2VuVXJsOiB0b2tlblVybCB8fCAnd2luZG93Lk1BUF9UT0tFTl9VUkwnLFxuICAgIHRva2VuOiBzdHIoJ3Rva2VuJyksXG4gICAgYXBpQmFzZVVybDogc3RyKCdhcGlCYXNlVXJsJykucmVwbGFjZSgvXFwvKyQvLCAnJyksXG4gICAgYXNzZXRzQmFzZVVybDogc3RyKCdhc3NldHNCYXNlVXJsJykucmVwbGFjZSgvXFwvKyQvLCAnJyksXG4gICAgcWFXaWRnZXQ6IGNmZy5xYVdpZGdldCAhPT0gZmFsc2UsXG4gIH1cbn1cblxuLy8gXHUyNTAwXHUyNTAwIFNoYXJlZCB3aXRoIHRoZSBwYWdlIChpbmplY3RlZCBieSBzb3VyY2UsIHNvIE5vZGUgYW5kIHRoZSBicm93c2VyIHJ1biB0aGUgc2FtZSBjb2RlKSBcdTI1MDBcdTI1MDBcbi8vIFRoZSBlbWJlZCBzbmlwcGV0cyBleGFjdGx5IGFzIGdlbmVyYXRlLXRyZWUgd3JpdGVzIHRoZW0gaW50byB0aGUgbWFuaWZlc3Q6IHByb2ZpbGUgXHUyMTkyIGlmcmFtZSArXG4vLyBzY3JpcHQsIGluc3RhbmNlIFx1MjE5MiBpZnJhbWUgb25seS4gYi9wL3ggYXJlIHRoZSBjb21wYWN0IHJlY29yZHMgYmVsb3cuXG5mdW5jdGlvbiBzbmlwKGIsIHAsIHgpIHtcbiAgdmFyIHUgPSAoeCB8fCBwKS51LCB0YWcgPSAoeCAmJiB4LmUpIHx8IHAuZSB8fCBiLmVbMF0gfHwgYi5iXG4gIHZhciByID0geyBpZnJhbWU6ICc8aWZyYW1lIHNyYz1cIicgKyB1ICsgJz91dG1fc291cmNlPVlPVVJfU09VUkNFXCIgd2lkdGg9XCIxMDAlXCIgaGVpZ2h0PVwiNjAwXCIgc3R5bGU9XCJib3JkZXI6bm9uZTtib3JkZXItcmFkaXVzOjEycHg7XCIgYWxsb3dmdWxsc2NyZWVuPjwvaWZyYW1lPicgfVxuICBpZiAoIXgpIHIuc2NyaXB0ID0gJzxzY3JpcHQgc3JjPVwiJyArIGIucyArICdcIicgKyAoYi5pID8gJyBpbnRlZ3JpdHk9XCInICsgYi5pICsgJ1wiIGNyb3Nzb3JpZ2luPVwiYW5vbnltb3VzXCInIDogJycpICsgJz48XFwvc2NyaXB0PlxcbjwnICsgdGFnICsgXCIgcHJvZmlsZS1jb25maWc9J1wiICsgSlNPTi5zdHJpbmdpZnkoeyBwcm9maWxlOiBwLnAsIHRrOiAnWU9VUl9NQVBCT1hfVE9LRU4nLCB1dG1Tb3VyY2U6ICdZT1VSX1NPVVJDRScgfSkgKyBcIic+PC9cIiArIHRhZyArICc+J1xuICByZXR1cm4gclxufVxuLy8gTWFuaWZlc3QgXHUyMTkyIGNvbXBhY3QgcmVnaXN0cnk6IFt7YixzLGksZSxwOlt7cCxlLHUsZCxlbT8saW4/Olt7aWQsdCxhLHByLGUsdSxlbT99XX1dfV0uXG4vLyBsZWFuID0gZHJvcCBldmVyeSBlbWJlZCBzbmlwcGV0IHRoZSBwYWdlIGNhbiByZS1kZXJpdmUgd2l0aCBzbmlwKCkgKHRoZSBiYWtlZCBmYWxsYmFjayk7XG4vLyB0aGUgbGl2ZSBtYW5pZmVzdCBrZWVwcyBpdHMgc25pcHBldHMgdmVyYmF0aW0uXG4vLyB0aWVyTWFwIChidWlsZCBtb2RlKTogeyBcIjxidW5kbGU+Lzxwcm9maWxlPlwiOiBcIjxtYWNoaW5lIGtleT5cIiB9IGZyb20gcmVhZFNvdXJjZVRpZXJzLCB1c2VkXG4vLyB3aGVuIHRoZSBtYW5pZmVzdCBwcm9maWxlIGNhcnJpZXMgbm8gYHR5cGVgLiBjID0gY2FwYWJpbGl0eSBudW1iZXIgKDFcdTIwMTM1KTsgdGhlIFNQQSBncm91cHNcbi8vIGFuZCBzb3J0cyBieSBpdCAoNSBcdTIxOTIgMSkuIERldiBtb2RlIHBhc3NlcyBwcm9maWxlcyB0aGF0IGFscmVhZHkgY2FycnkgYHNwLnR5cGVgLlxuZXhwb3J0IGZ1bmN0aW9uIGNvbXBhY3QobSwgbGVhbiwgdGllck1hcCkge1xuICB0aWVyTWFwID0gdGllck1hcCB8fCB7fVxuICAvLyBDb21wb3NpdGlvbiB0aWVyIFx1MjE5MiBjYXBhYmlsaXR5IG51bWJlciwgc2VsZi1jb250YWluZWQgc28gdGhlIGJyb3dzZXIgY29weSBvZiB0aGlzIGZ1bmN0aW9uXG4gIC8vIChzaGlwcGVkIHZpYSBzcmMoY29tcGFjdCkgYW5kIHJlLXJ1biBvbiB0aGUgbGl2ZSBtYW5pZmVzdCkgbmVlZHMgbm8gaW1wb3J0LiA1ID0gYXBwLXNoZWxsXG4gIC8vIChuZXN0ZWQtbWZlLXNwYSkgXHUyMDI2IDEgPSBzaW5nbGUuIFRoZSBtb2RlbCBtYXkgYmFrZSBgc3AudHlwZWA7IGVsc2UgdGllck1hcCByZXNvbHZlcyBpdC5cbiAgdmFyIFBUID0geyAnbmVzdGVkLW1mZS1zcGEnOiAwLCAnbmVzdGVkLWVsZW1lbnRzLW1mZSc6IDEsICdtb25vbGl0aGljJzogMiwgJ3BhcmFtZXRlcml6ZWQnOiAzLCAnc2luZ2xlJzogNCB9XG4gIHZhciBjYXBGb3IgPSBmdW5jdGlvbiAodCkgeyByZXR1cm4gUFRbdF0gIT0gbnVsbCA/IDUgLSBQVFt0XSA6IDEgfVxuICByZXR1cm4gKG0uYnVuZGxlcyB8fCBbXSkubWFwKGZ1bmN0aW9uIChzcmMpIHtcbiAgICB2YXIgYiA9IHsgYjogc3JjLmJ1bmRsZSwgczogc3JjLnNjcmlwdFVybCB8fCAnJywgaTogc3JjLmludGVncml0eSB8fCAnJywgZTogc3JjLmVsZW1lbnRzIHx8IFtdLCBwOiBbXSB9XG4gICAgYi5wID0gKHNyYy5wcm9maWxlcyB8fCBbXSkubWFwKGZ1bmN0aW9uIChzcCkge1xuICAgICAgdmFyIHR5cGUgPSBzcC50eXBlIHx8IHRpZXJNYXBbc3JjLmJ1bmRsZSArICcvJyArIHNwLnByb2ZpbGVdIHx8ICdzaW5nbGUnXG4gICAgICB2YXIgYyA9IGNhcEZvcih0eXBlKVxuICAgICAgdmFyIHAgPSB7IHA6IHNwLnByb2ZpbGUsIGU6IHNwLmVsZW1lbnQgfHwgJycsIHU6IHNwLmlmcmFtZVVybCB8fCAnJywgZDogc3AuZGVzY3JpcHRpb24gfHwgJycsIGM6IGMgfVxuICAgICAgdmFyIGVtID0gc3AuZW1iZWQgfHwge30sIGQgPSBzbmlwKGIsIHAsIG51bGwpXG4gICAgICBpZiAoIWxlYW4gfHwgZW0uaWZyYW1lICE9PSBkLmlmcmFtZSB8fCBlbS5zY3JpcHQgIT09IGQuc2NyaXB0KSBwLmVtID0gZW1cbiAgICAgIHZhciBpbnMgPSAoc3AuaW5zdGFuY2VzIHx8IFtdKS5tYXAoZnVuY3Rpb24gKHN4KSB7XG4gICAgICAgIHZhciB4ID0geyBpZDogc3guaWQsIHQ6IHN4LnRpdGxlIHx8IHN4LmlkLCBhOiBzeC5hcGlCYXNlVXJsIHx8ICcnLCBwcjogc3gucHJvcHMgfHwge30sIGU6IHN4LmVsZW1lbnQgfHwgJycsIHU6IHN4LmlmcmFtZVVybCB8fCAnJyB9XG4gICAgICAgIHZhciB4ZSA9IHN4LmVtYmVkIHx8IHt9LCB4ZCA9IHNuaXAoYiwgcCwgeClcbiAgICAgICAgaWYgKCFsZWFuIHx8IHhlLmlmcmFtZSAhPT0geGQuaWZyYW1lKSB4LmVtID0geGVcbiAgICAgICAgcmV0dXJuIHhcbiAgICAgIH0pXG4gICAgICBpZiAoaW5zLmxlbmd0aCkgcC5pbiA9IGluc1xuICAgICAgcmV0dXJuIHBcbiAgICB9KVxuICAgIHJldHVybiBiXG4gIH0pXG59XG4vLyBGdW5jdGlvbiBzb3VyY2UgZm9yIHRoZSBwYWdlLiBUaGUgZGV2IHNlcnZlciBsb2FkcyB0aGlzIG1vZHVsZSB0aHJvdWdoIFZpdGUncyBjb25maWcgYnVuZGxlcixcbi8vIHdob3NlIHByaW50ZXIgbWF5IHR1cm4gdGhlICc8XFwvc2NyaXB0PicgbGl0ZXJhbCBhYm92ZSBiYWNrIGludG8gJzwvc2NyaXB0PicgXHUyMDE0IGluc2lkZSBhbiBpbmxpbmVcbi8vIHNjcmlwdCB0aGF0IHdvdWxkIGVuZCB0aGUgZWxlbWVudCBlYXJseSwgc28gdGhlIGVzY2FwZSBpcyByZXN0b3JlZCBoZXJlIChhIG5vLW9wIHVuZGVyIG5vZGUpLlxuY29uc3Qgc3JjID0gKGZuKSA9PiBmbi50b1N0cmluZygpLnJlcGxhY2UoLzxcXC9zY3JpcHQvZ2ksICc8XFxcXC9zY3JpcHQnKVxuXG4vLyBcdTI1MDBcdTI1MDAgbW9kZSAnZGV2JyBvbmx5OiB0aGUgY29tcG9zYWJpbGl0eSBsYWRkZXIgKyBpdHMgXCI/XCIgcG9wb3ZlcnMgXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXG4vLyBWb2NhYnVsYXJ5IGlzIHRoZSB2YWxpZGF0ZWQgc2V0IGZyb20gZG9jdW1lbnRhdGlvbi9yZWZlcmVuY2UubWQgXCJQcm9maWxlIHR5cGVzXCI6IGhlYWQgd29yZHMgYXJlXG4vLyBlc3RhYmxpc2hlZCB0ZXJtcyAoY3VzdG9tIGVsZW1lbnQsIHByZXNldCwgbXVsdGktdmlldywgY29tcG9zaXRlLCBhcHAgc2hlbGwpOyB0aGUgY29pbmVkIHdvcmRzXG4vLyBzdGF5IGFzIGEuay5hLiBQb3BvdmVyIHN0cmluZ3MgYXJlIEhUTUwgKGlubmVySFRNTCkgXHUyMDE0IHRhZ3MgYXJlIGVzY2FwZWQuXG5jb25zdCBMQURERVJfQ1NTID0gU3RyaW5nLnJhd2A6cm9vdHstLWFjYzojMWE3M2U4fUBtZWRpYShwcmVmZXJzLWNvbG9yLXNjaGVtZTpkYXJrKXs6cm9vdHstLWFjYzojNjRiNWY2fX1cbi5sYWRkZXJ7cG9zaXRpb246cmVsYXRpdmU7bWFyZ2luLWxlZnQ6YXV0bztkaXNwbGF5OmZsZXg7YWxpZ24taXRlbXM6Y2VudGVyO2dhcDo2cHg7d2hpdGUtc3BhY2U6bm93cmFwfVxuLnJ1bmd7ZGlzcGxheTppbmxpbmUtZmxleDthbGlnbi1pdGVtczpjZW50ZXI7Z2FwOjRweH0ucm5hbWV7Zm9udDo1MDAgMTJweC8xIHVpLW1vbm9zcGFjZSxNZW5sbyxtb25vc3BhY2V9XG4uYXJyb3d7Y29sb3I6dmFyKC0tbXV0KTtmb250LXNpemU6MTJweDtwYWRkaW5nOjAgMXB4fVxuLnF7d2lkdGg6MThweDtoZWlnaHQ6MThweDtwYWRkaW5nOjA7Ym9yZGVyLXJhZGl1czo1MCU7Zm9udDo3MDAgMTFweC8xIHN5c3RlbS11aSxzYW5zLXNlcmlmO2NvbG9yOnZhcigtLW11dCk7YmFja2dyb3VuZDp2YXIoLS1iZyk7ZGlzcGxheTppbmxpbmUtZ3JpZDtwbGFjZS1pdGVtczpjZW50ZXJ9XG4uc3RhcnR7Zm9udDo2MDAgMTAuNXB4LzEgc3lzdGVtLXVpLHNhbnMtc2VyaWY7bGV0dGVyLXNwYWNpbmc6LjA0ZW07dGV4dC10cmFuc2Zvcm06dXBwZXJjYXNlO2NvbG9yOnZhcigtLWFjYyk7YmFja2dyb3VuZDp2YXIoLS1iZyk7Ym9yZGVyLXJhZGl1czo5OTlweDtwYWRkaW5nOjRweCA5cHg7bWFyZ2luLXJpZ2h0OjRweH1cbi5xOmhvdmVyLC5xW2FyaWEtZXhwYW5kZWQ9dHJ1ZV0sLnN0YXJ0OmhvdmVyLC5zdGFydFthcmlhLWV4cGFuZGVkPXRydWVde2NvbG9yOnZhcigtLWFjYyk7Ym9yZGVyLWNvbG9yOnZhcigtLWFjYyk7YmFja2dyb3VuZDp2YXIoLS1iZyl9XG4uZXhwbGFpbntwb3NpdGlvbjphYnNvbHV0ZTt0b3A6Y2FsYygxMDAlICsgOHB4KTtyaWdodDowO3dpZHRoOjQyMHB4O21heC13aWR0aDpjYWxjKDEwMHZ3IC0gMzJweCk7bWF4LWhlaWdodDo3MHZoO292ZXJmbG93OmF1dG87ei1pbmRleDo0MDtiYWNrZ3JvdW5kOnZhcigtLWJnKTtib3JkZXI6MXB4IHNvbGlkIHZhcigtLWJkKTtib3JkZXItcmFkaXVzOjEwcHg7Ym94LXNoYWRvdzowIDRweCAxNnB4IHJnYmEoMCwwLDAsLjE0KTtwYWRkaW5nOjEycHggMTRweDtmb250LXNpemU6MTNweDtsaW5lLWhlaWdodDoxLjQ1O3RleHQtYWxpZ246bGVmdDt3aGl0ZS1zcGFjZTpub3JtYWx9XG4uZXhwbGFpbiBoM3ttYXJnaW46MCAwIDVweDtmb250LXNpemU6MTRweDtkaXNwbGF5OmZsZXg7YWxpZ24taXRlbXM6Y2VudGVyO2dhcDo4cHg7ZmxleC13cmFwOndyYXB9LmV4cGxhaW4gaDR7bWFyZ2luOjhweCAwIDNweDtmb250LXNpemU6MTNweH1cbi5leHBsYWluIC50aWVye2ZvbnQ6NzAwIDEwcHgvMSBzeXN0ZW0tdWksc2Fucy1zZXJpZjtsZXR0ZXItc3BhY2luZzouNnB4O3RleHQtdHJhbnNmb3JtOnVwcGVyY2FzZTtjb2xvcjp2YXIoLS1tdXQpfVxuLmV4cGxhaW4gcHttYXJnaW46MCAwIDZweH0uZXhwbGFpbiAuYWthe2ZvbnQtc2l6ZToxMS41cHg7Y29sb3I6dmFyKC0tbXV0KTttYXJnaW46LTJweCAwIDZweH1cbi5leHBsYWluIC5ob3d7bWFyZ2luOjAgMCA2cHg7Zm9udC1zaXplOjEyLjVweH0uZXhwbGFpbiAuaG93IHN1bW1hcnl7Y3Vyc29yOnBvaW50ZXI7Y29sb3I6dmFyKC0tYWNjKTtmb250LXdlaWdodDo2MDA7Zm9udC1zaXplOjEycHh9LmV4cGxhaW4gLmhvdyBwe21hcmdpbjo2cHggMCAwO2NvbG9yOnZhcigtLW11dCl9XG4uZXhwbGFpbiAuZXh7Y29sb3I6dmFyKC0tbXV0KTtmb250LXNpemU6MTJweH1cbkBtZWRpYShtYXgtd2lkdGg6MTI4MHB4KXsubGFkZGVye2Rpc3BsYXk6bm9uZX19XG5gXG5jb25zdCBMQURERVJfSFRNTCA9ICc8bmF2IGNsYXNzPVwibGFkZGVyXCIgaWQ9XCJsYWRkZXJcIiBhcmlhLWxhYmVsPVwiQ29tcG9zYWJpbGl0eSBsYWRkZXJcIiB2LXByZT48L25hdj4nXG5jb25zdCBMQURERVJfSlMgPSBTdHJpbmcucmF3YDxzY3JpcHQ+XG4oZnVuY3Rpb24gKCkge1xuICB2YXIgUFJJTUVSID0gW1xuICAgIHsgdGl0bGU6ICdFbGVtZW50JyxcbiAgICAgIGRlZjogJ0EgY3VzdG9tIEhUTUwgdGFnIHRoaXMgcmVwbyBpbnZlbnRzLCBzdWNoIGFzICZsdDtkb3hhLW1hcCZndDs6IHRoZSBicm93c2VyIGxlYXJucyBpdCBvbmNlLCB0aGVuIHlvdSBjYW4gcGFzdGUgaXQgaW50byBhbnkgcGFnZSBhcyBvZnRlbiBhcyB5b3UgbGlrZS4gRWFjaCBwYXN0ZWQgdGFnIGlzIG9uZSBsaXZlIGNvcHksIGNhbGxlZCBhbiBpbnN0YW5jZS4gKFBlb3BsZSBhbHNvIHNheSAmcXVvdDt3ZWIgY29tcG9uZW50JnF1b3Q7LiknLFxuICAgICAgaG93OiAnVGhlIGJ1bmRsZSBpbmRleC5qcyB0dXJucyB0aGUgc2hhcmVkIFByb2ZpbGVMb2FkZXIgaW50byBhbiBlbGVtZW50IGNsYXNzIHdpdGggZGVmaW5lQ3VzdG9tRWxlbWVudCBhbmQgcmVnaXN0ZXJzIHRoZSB0YWcgb25jZSB3aXRoIGN1c3RvbUVsZW1lbnRzLmRlZmluZS4nLFxuICAgICAgZXg6ICcmbHQ7ZG94YS1tYXAgcHJvZmlsZS1jb25maWc9JiMzOTt7JnF1b3Q7cHJvZmlsZSZxdW90OzomcXVvdDtkb3hhLXNpbXBsZS1tYXAmcXVvdDt9JiMzOTsmZ3Q7Jmx0Oy9kb3hhLW1hcCZndDsnIH0sXG4gICAgeyB0aXRsZTogJ0FwcCBwcm9maWxlIChtb3VudGluZyBmaWxlKScsXG4gICAgICBkZWY6ICdPbmUgZmxhdCAudnVlIGZpbGUgaW4gcGx1Z2luLWRlc2lnbnMvJmx0O2J1bmRsZSZndDsvIHRoYXQgZGVmaW5lcyBhIHdob2xlIG1hcCBhcHAgXHUyMDE0IHRoZSBtYWluIGNvbXBvbmVudCBvZiB0aGF0IG1hcC4gVGhlIHNldHRpbmdzIHdyaXR0ZW4gb24gdGhlIHRhZyAocHJvZmlsZS1jb25maWcpIG5hbWUgd2hpY2ggYXBwIHByb2ZpbGUgdG8gbG9hZCwgYW5kIHRoZSBzaGFyZWQgUHJvZmlsZUxvYWRlciBwaWNrcyBpdC4gSW4gY2xhc3MtYW5kLW9iamVjdCB0ZXJtczogdGhlIGVsZW1lbnQgY2xhc3MgaXMgdGhlIGNsYXNzLCBlYWNoIHRhZyBvbiBhIHBhZ2UgaXMgYW4gaW5zdGFuY2UsIGFuZCB0aGUgYXBwIHByb2ZpbGUgaXMgdGhlIHNjcmVlbiB0aGF0IGluc3RhbmNlIGxvYWRzLicsXG4gICAgICBob3c6ICdNb3N0IHJlcG9zIG5lZWQgb25lIHN1Y2ggbWFpbiBmaWxlIHBlciBhcHAuICR7VFJFRV9OQU1FfSBidWlsZHMgaHVuZHJlZHMgb2YgbWFwcyBmcm9tIG9uZSBzaGFyZWQgbGlicmFyeSwgc28gZXZlcnkgbWFwIGdldHMgaXRzIG93biBhcHAgcHJvZmlsZSBcdTIwMTQgdGhlIGZvbGRlciBwbHVnaW4tZGVzaWducy8gaXMgd2hlcmUgdGhleSBzaXQuIFRoZSBmaXZlIGtpbmRzIG9uIHRoaXMgbGFkZGVyIGFyZSB0aGUgZml2ZSBzaGFwZXMgdGhvc2UgZmlsZXMgY29tZSBpbi4nLFxuICAgICAgZXg6ICdwbHVnaW4tZGVzaWducy9kb3hhLXNpbXBsZS1tYXAvZG94YS1zaW1wbGUtbWFwLnZ1ZScgfVxuICBdO1xuICB2YXIgTEFEREVSID0gW1xuICAgIHsgbGFiZWw6ICdzaW5nbGUtZWxlbWVudCcsIHRpZXI6IDQsIHRpdGxlOiAnU2luZ2xlIGVsZW1lbnQnLCBha2E6ICdzaW5nbGUnLFxuICAgICAgZGVmOiAnT25lIGFwcCBwcm9maWxlLCBvbmUgbWFwOiBwYXN0ZSBpdHMgdGFnIGludG8gYW55IHBhZ2UsIG9uY2Ugb3IgbWFueSB0aW1lcywgYW5kIHNldCBpdCB1cCByaWdodCB0aGVyZSBpbiBwcm9maWxlLWNvbmZpZy4gVGhlIHNtYWxsZXN0IGtpbmQgYW5kIHRoZSBkZWZhdWx0IFx1MjAxNCBubyBwcmVzZXQgdGFibGUsIG5vIHRhYnMsIG5vIG5lc3RlZCBtYXBzLicsXG4gICAgICBob3c6ICdBIGZsYXQgLnZ1ZSB3aXRoIG5vICZsdDtwcm9maWxlJmd0Oy5tZXRhLmpzb24gYmVzaWRlIGl0IGFuZCBubyAqLmluc3RhbmNlcy5qc29uIGluIHRoZSBidW5kbGUgZm9sZGVyLiBNYWNoaW5lIGtleTogc2luZ2xlLicsXG4gICAgICBleDogJ2NpdGllcy1pbnRlcm5ldC9jb25uZWN0aXZpdHktbWFwLnZ1ZSBcdTIxOTIgJmx0O2NpdGllcy1pbnRlcm5ldC1tYXAmZ3Q7IFx1MDBCNyBnb3NwZWwtcmVzb3VyY2VzL3Jlc291cmNlcy1tYXAudnVlJyB9LFxuICAgIHsgbGFiZWw6ICdwcmVzZXQtZWxlbWVudCcsIHRpZXI6IDMsIHRpdGxlOiAnUHJlc2V0IGVsZW1lbnQnLCBha2E6ICdwYXJhbWV0ZXJpemVkIFx1MDBCNyBwcm9wLW1hbnktZWxlbWVudHMnLFxuICAgICAgZGVmOiAnT25lIGFwcCBwcm9maWxlIHBsdXMgYSBzbWFsbCB0YWJsZSBvZiBuYW1lZCBwcmVzZXRzICgmbHQ7bmFtZSZndDsuaW5zdGFuY2VzLmpzb24pLiBFYWNoIHJvdyBpcyBvbmUgcmVhZHktbWFkZSBtYXAgd2l0aCBpdHMgc2V0dGluZ3MgYmFrZWQgaW4gYW5kIGdldHMgaXRzIG93biBlbWJlZCBwYWdlIGFuZCBzaWRlYmFyIGVudHJ5IFx1MjAxNCBzYW1lIGNvZGUsIHNhbWUgdGFnLicsXG4gICAgICBob3c6ICdUaGUgYnVuZGxlIGZvbGRlciBob2xkcyAmbHQ7bmFtZSZndDsuaW5zdGFuY2VzLmpzb24gKHsmcXVvdDtpbnN0YW5jZXMmcXVvdDs6W3tpZCx0aXRsZSxwcm9wc31dfSk7IHRoZSBidWlsZCB3cml0ZXMgb25lIGVtYmVkIHBhZ2UgcGVyIHJvdyBhdCAmbHQ7YnVuZGxlJmd0Oy8mbHQ7cHJvZmlsZSZndDsvJmx0O2lkJmd0Oy9pbmRleC5odG1sLiBNYWNoaW5lIGtleTogcGFyYW1ldGVyaXplZC4gTm90IHRoaXMgaWYgdGhlIHZlcnNpb25zIG5lZWQgZGlmZmVyZW50IGNvZGUgXHUyMDE0IG1ha2UgYW5vdGhlciBhcHAgcHJvZmlsZS4nLFxuICAgICAgZXg6ICdkb3hhLXNpbXBsZS1tYXAudnVlICsgc2ltcGxlLW1hcC5pbnN0YW5jZXMuanNvbiBcdTIxOTIgUHJheWVyIC8gRW5nYWdlbWVudCAvIEFkb3B0aW9uJyB9LFxuICAgIHsgbGFiZWw6ICdtdWx0aS12aWV3LWVsZW1lbnQnLCB0aWVyOiAyLCB0aXRsZTogJ011bHRpLXZpZXcgZWxlbWVudCcsIGFrYTogJ21vbm9saXRoaWMgXHUwMEI3IG1vbm9saXRoaWMtbWZlJyxcbiAgICAgIGRlZjogJ09uZSBhcHAgcHJvZmlsZSB0aGF0IGhvbGRzIHNldmVyYWwgc2NyZWVucyB5b3Ugc3dpdGNoIGJldHdlZW4gXHUyMDE0IHRhYnMgb3Igc3RlcHMgXHUyMDE0IGFsbCB3cml0dGVuIGluIG9uZSAudnVlIGFuZCBzaG93biBhcyBvbmUgZWxlbWVudCwgb25lIHNjcmVlbiBhdCBhIHRpbWUuIEtlZXBpbmcgdGhlbSBpbiBvbmUgZmlsZSBpcyBvbiBwdXJwb3NlLicsXG4gICAgICBob3c6ICdEZWNsYXJlZCwgbmV2ZXIgZ3Vlc3NlZDogJmx0O3Byb2ZpbGUmZ3Q7Lm1ldGEuanNvbiB7JnF1b3Q7dHlwZSZxdW90OzomcXVvdDttb25vbGl0aGljJnF1b3Q7fSAob3IgJnF1b3Q7bXVsdGktdmlldy1lbGVtZW50JnF1b3Q7KTsgdGhlIC52dWUgb3ducyBpdHMgb3duIHN3aXRjaGVyLiBOb3QgdGhpcyBpZiB0aGUgcGllY2VzIGFyZSBvdGhlciBhcHAgcHJvZmlsZXMgKGNvbXBvc2l0ZSkgb3IgYWxsIHBhbmVscyBzaG93IGF0IG9uY2UgKHNpbmdsZSkuJyxcbiAgICAgIGV4OiAnZG94YS1yZXNlYXJjaC1tYXAvcmVzZWFyY2gtbWFwLnZ1ZSBcdTIwMTQgc2l4IHRhYnMgaW4gb25lICZsdDtkb3hhLXJlc2VhcmNoLW1hcCZndDsnIH0sXG4gICAgeyBsYWJlbDogJ2NvbXBvc2l0ZS1lbGVtZW50JywgdGllcjogMSwgdGl0bGU6ICdDb21wb3NpdGUgZWxlbWVudCcsIGFrYTogJ25lc3RlZC1lbGVtZW50cy1tZmUnLFxuICAgICAgZGVmOiAnQW4gYXBwIHByb2ZpbGUgd2hvc2UgdGVtcGxhdGUgcGxhY2VzIHRoZSBtYXBzIG9mIG90aGVyIGFwcCBwcm9maWxlcyB0b2dldGhlciBcdTIwMTQgc3RhY2tlZCBvciBzaWRlIGJ5IHNpZGUsIHN1Y2ggYXMgYSBtYXAgYW5kIGEgcG9zdGVyIHdhbGwgXHUyMDE0IGFuZCBzaGlwcyB0aGUgcmVzdWx0IGFzIG9uZSBuZXcgZWxlbWVudC4gT25lIHRhZyBlbWJlZHMgdGhlIHdob2xlIHNldC4nLFxuICAgICAgaG93OiAnRGVjbGFyZWQ6ICZsdDtwcm9maWxlJmd0Oy5tZXRhLmpzb24geyZxdW90O3R5cGUmcXVvdDs6JnF1b3Q7bmVzdGVkLWVsZW1lbnRzLW1mZSZxdW90OywmcXVvdDtjb21wb3NlcyZxdW90OzpbXHUyMDI2XX0gKG9yICZxdW90O2NvbXBvc2l0ZS1lbGVtZW50JnF1b3Q7KTsgdGhlIC52dWUgY3JlYXRlcyBlYWNoIGNoaWxkIHRhZyB3aXRoIGl0cyBvd24gcHJvZmlsZS1jb25maWcgb24gdGhlIHBhbmUgbGF5b3V0IChsYXlvdXRzL3BhbmUtd3JhcHBlcikuIE5vdCB0aGlzIGlmIHRoZSBzY3JlZW5zIGFyZSB3cml0dGVuIGluc2lkZSBvbmUgZmlsZSAobXVsdGktdmlldykuJyxcbiAgICAgIGV4OiAnbXktdXBnLTEwMC1saXN0L3VwZy0xMDAtbWZlLnZ1ZSBcdTIwMTQgTWFwIHBhbmUgKyBQcmF5ZXIgTGlzdHMgcGFuZSwgb25lIFNoYXJlIGJ1dHRvbicgfSxcbiAgICB7IGxhYmVsOiAnYXBwLXNoZWxsJywgdGllcjogMCwgdGl0bGU6ICdBcHAgc2hlbGwnLCBha2E6ICduZXN0ZWQtbWZlLXNwYSBcdTAwQjcgY29udGFpbmVyIGFwcGxpY2F0aW9uIFx1MDBCNyByb290IGNvbmZpZyBcdTAwQjcgaG9zdCcsXG4gICAgICBkZWY6ICdUaGUgb3V0ZXIgZnJhbWUgb2YgYSB3aG9sZSBhcHAgXHUyMDE0IHNpZGViYXIsIGhlYWRlciwgbmF2aWdhdGlvbiBcdTIwMTQgdGhhdCBsb2FkcyBhbnkgb2YgdGhlIG90aGVyIGZvdXIga2luZHMgaW5zaWRlIGl0IGFuZCBzd2l0Y2hlcyBiZXR3ZWVuIHRoZW0gd2l0aG91dCBhIHBhZ2UgcmVsb2FkLiBUaGUgb25seSBydW5nIHRoYXQgaXMgYSBwYWdlLCBub3QgYW4gZWxlbWVudDogd2hhdCBhIHZpc2l0b3IgYWN0dWFsbHkgb3BlbnMuJyxcbiAgICAgIGhvdzogJ1RvZGF5IGJvdGggc2hlbGxzIGFyZSBIVE1MIHBhZ2VzLCBub3QgLnZ1ZSBhcHAgcHJvZmlsZXM6IGxheW91dHMvYXBwLXdyYXBwZXItbWF0ZXJpYWwvaW5kZXguaHRtbCBhbmQgdGhpcyBwbHVnaW4gZ2FsbGVyeSAoaW50ZXJuYWwvZ2VuZXJhdGUtZ2FsbGVyeS5tanMsIG9uZSBnZW5lcmF0b3IgZm9yIHRoZSBkZXYgcm9vdCBhbmQgcHVibGljL2luZGV4Lmh0bWwpLiBNYWNoaW5lIGtleSBuZXN0ZWQtbWZlLXNwYSAob3IgYXBwLXNoZWxsKSBpcyByZXNlcnZlZCBmb3IgYSBmdXR1cmUgLnZ1ZSBzaGVsbC4nLFxuICAgICAgZXg6ICd0aGlzIHBsdWdpbiBnYWxsZXJ5IFx1MDBCNyB0aGUgRG94YSBNYXBzIFNQQScgfVxuICBdO1xuICB2YXIgbGFkZGVyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2xhZGRlcicpLCBvcGVuUSA9IG51bGw7XG4gIHZhciBwb3AgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsgcG9wLmNsYXNzTmFtZSA9ICdleHBsYWluJzsgcG9wLmhpZGRlbiA9IHRydWU7IHBvcC5zZXRBdHRyaWJ1dGUoJ3JvbGUnLCAnZGlhbG9nJyk7XG4gIGZ1bmN0aW9uIGNsb3NlUG9wKCkgeyBwb3AuaGlkZGVuID0gdHJ1ZTsgaWYgKG9wZW5RKSB7IG9wZW5RLnNldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcsICdmYWxzZScpOyBvcGVuUSA9IG51bGwgfSB9XG4gIGZ1bmN0aW9uIHNob3dQb3AoYnRuLCBodG1sKSB7IGlmIChvcGVuUSA9PT0gYnRuKSB7IGNsb3NlUG9wKCk7IHJldHVybiB9IGNsb3NlUG9wKCk7IG9wZW5RID0gYnRuOyBidG4uc2V0QXR0cmlidXRlKCdhcmlhLWV4cGFuZGVkJywgJ3RydWUnKTsgcG9wLmlubmVySFRNTCA9IGh0bWw7IHBvcC5oaWRkZW4gPSBmYWxzZSB9XG4gIGZ1bmN0aW9uIGhvd0Jsb2NrKHQpIHsgcmV0dXJuICc8ZGV0YWlscyBjbGFzcz1cImhvd1wiPjxzdW1tYXJ5PkZvciBidWlsZGVycyBcdTIwMTQgaG93IHRvIHJlY29nbmlzZSBpdDwvc3VtbWFyeT48cD4nICsgdCArICc8L3A+PC9kZXRhaWxzPicgfVxuICBmdW5jdGlvbiBraW5kSHRtbChyKSB7IHJldHVybiAnPGgzPicgKyByLnRpdGxlICsgJyA8c3BhbiBjbGFzcz1cInRpZXJcIj50aWVyICcgKyByLnRpZXIgKyAnIFx1MDBCNyAnICsgci5sYWJlbCArICc8L3NwYW4+PC9oMz48cD4nICsgci5kZWYgKyAnPC9wPjxkaXYgY2xhc3M9XCJha2FcIj5hLmsuYS4gJyArIHIuYWthICsgJzwvZGl2PicgKyBob3dCbG9jayhyLmhvdykgKyAnPGRpdiBjbGFzcz1cImV4XCI+ZS5nLiAnICsgci5leCArICc8L2Rpdj4nIH1cbiAgZnVuY3Rpb24gcHJpbWVySHRtbCgpIHsgcmV0dXJuICc8aDM+U3RhcnQgaGVyZSA8c3BhbiBjbGFzcz1cInRpZXJcIj50aGUgdHdvIHdvcmRzIGV2ZXJ5IHJ1bmcgdXNlczwvc3Bhbj48L2gzPicgKyBQUklNRVIubWFwKGZ1bmN0aW9uIChwKSB7IHJldHVybiAnPGg0PicgKyBwLnRpdGxlICsgJzwvaDQ+PHA+JyArIHAuZGVmICsgJzwvcD4nICsgaG93QmxvY2socC5ob3cpICsgJzxkaXYgY2xhc3M9XCJleFwiPmUuZy4gJyArIHAuZXggKyAnPC9kaXY+JyB9KS5qb2luKCcnKSB9XG4gIHZhciBzdGFydCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2J1dHRvbicpOyBzdGFydC5jbGFzc05hbWUgPSAnc3RhcnQnOyBzdGFydC50eXBlID0gJ2J1dHRvbic7IHN0YXJ0LnRleHRDb250ZW50ID0gJ1N0YXJ0IGhlcmUnOyBzdGFydC5zZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnLCAnZmFsc2UnKTtcbiAgc3RhcnQuc2V0QXR0cmlidXRlKCdhcmlhLWxhYmVsJywgJ1doYXQgaXMgYW4gZWxlbWVudD8gV2hhdCBpcyBhbiBhcHAgcHJvZmlsZT8nKTsgc3RhcnQub25jbGljayA9IGZ1bmN0aW9uIChlKSB7IGUuc3RvcFByb3BhZ2F0aW9uKCk7IHNob3dQb3Aoc3RhcnQsIHByaW1lckh0bWwoKSkgfTsgbGFkZGVyLmFwcGVuZENoaWxkKHN0YXJ0KTtcbiAgTEFEREVSLmZvckVhY2goZnVuY3Rpb24gKHIsIGkpIHtcbiAgICBpZiAoaSkgeyB2YXIgYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTsgYS5jbGFzc05hbWUgPSAnYXJyb3cnOyBhLnRleHRDb250ZW50ID0gJ1x1MjE5Mic7IGxhZGRlci5hcHBlbmRDaGlsZChhKSB9XG4gICAgdmFyIHJ1bmcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyk7IHJ1bmcuY2xhc3NOYW1lID0gJ3J1bmcnO1xuICAgIHZhciBubSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTsgbm0uY2xhc3NOYW1lID0gJ3JuYW1lJzsgbm0udGV4dENvbnRlbnQgPSByLmxhYmVsO1xuICAgIHZhciBxID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYnV0dG9uJyk7IHEuY2xhc3NOYW1lID0gJ3EnOyBxLnR5cGUgPSAnYnV0dG9uJzsgcS50ZXh0Q29udGVudCA9ICc/JzsgcS5zZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnLCAnV2hhdCBpcyBhICcgKyByLnRpdGxlLnRvTG93ZXJDYXNlKCkgKyAnPycpOyBxLnNldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcsICdmYWxzZScpO1xuICAgIHEub25jbGljayA9IGZ1bmN0aW9uIChlKSB7IGUuc3RvcFByb3BhZ2F0aW9uKCk7IHNob3dQb3AocSwga2luZEh0bWwocikpIH07XG4gICAgcnVuZy5hcHBlbmRDaGlsZChubSk7IHJ1bmcuYXBwZW5kQ2hpbGQocSk7IGxhZGRlci5hcHBlbmRDaGlsZChydW5nKTtcbiAgfSk7XG4gIGxhZGRlci5hcHBlbmRDaGlsZChwb3ApO1xuICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7IGlmICghbGFkZGVyLmNvbnRhaW5zKGUudGFyZ2V0KSkgY2xvc2VQb3AoKSB9KTtcbiAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIGZ1bmN0aW9uIChlKSB7IGlmIChlLmtleSA9PT0gJ0VzY2FwZScpIGNsb3NlUG9wKCkgfSk7XG59KSgpO1xuPC9zY3JpcHQ+XG5gXG5cbi8qKlxuICogVGhlIHdob2xlIHBhZ2UgZnJvbSBhIG1hbmlmZXN0LXNoYXBlZCBtb2RlbCAoc2NoZW1hIGRveGEtbWFwcy1tYW5pZmVzdEAxOiBidW5kbGVzIFx1MjE5MiBwcm9maWxlcyBcdTIxOTJcbiAqIGluc3RhbmNlcywgd2l0aCBzY3JpcHRVcmwgLyBpZnJhbWVVcmwgLyBlbWJlZCAvIGludGVncml0eSkuIFB1cmU6IG5vIEkvTywgbm8gZ2xvYmFscy5cbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gbW9kZWwgICB0aGUgbWFuaWZlc3QgKGJ1aWxkKSBvciB0aGUgZGV2IG1vZGVsIChkZXYtcGx1Z2luLm1qcyBnYWxsZXJ5TW9kZWwpXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0cyAgICBtb2RlICdidWlsZCcgfCAnZGV2JzsgdGl0bGU7IHRyZWUgXHUyMDE0IHRoZSBmb2xkZXIgdGhlIGxpdmUgbWFuaWZlc3QgaXNcbiAqICAgICAgICAgICAgICAgICAgICAgICAgIGZldGNoZWQgZnJvbSAoPHRyZWU+L21hbmlmZXN0Lmpzb24pIGFuZCB0aGF0IHJlbGF0aXZlIHJlZnMgcmVzb2x2ZVxuICogICAgICAgICAgICAgICAgICAgICAgICAgYWdhaW5zdCAoYnVpbGQ6IHRoZSB0cmVlIG5hbWU7IGRldjogdGhlIHJvdXRlIHByZWZpeCwgcmVmcyBhYnNvbHV0ZSk7XG4gKiAgICAgICAgICAgICAgICAgICAgICAgICB0b2tlblVybCAvIHRva2VuIC8gYXBpQmFzZVVybCAvIGFzc2V0c0Jhc2VVcmwgLyBxYVdpZGdldCBcdTIwMTQgdGhlIGJ1aWxkXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICBjb25maWcgZmllbGRzIGV2ZXJ5IGxlYWYgcGFnZSBiYWtlcyAocmVhZEJ1aWxkQ29uZmlnKVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyR2FsbGVyeShtb2RlbCwgb3B0cyA9IHt9KSB7XG4gIGNvbnN0IHsgbW9kZSA9ICdidWlsZCcsIHRpdGxlID0gVFJFRV9OQU1FLCB0cmVlID0gVFJFRV9OQU1FLCB0b2tlblVybCA9ICd3aW5kb3cuTUFQX1RPS0VOX1VSTCcsIHRva2VuID0gJycsIGFwaUJhc2VVcmwgPSAnJywgYXNzZXRzQmFzZVVybCA9ICcnLCBxYVdpZGdldCA9IHRydWUsIHRpZXJNYXAgPSB7fSB9ID0gb3B0c1xuICBjb25zdCBkZXYgPSBtb2RlID09PSAnZGV2J1xuICBjb25zdCBiYWtlZCA9IGNvbXBhY3QobW9kZWwsIHRydWUsIHRpZXJNYXApXG4gIGNvbnN0IGpzb24gPSAodikgPT4gSlNPTi5zdHJpbmdpZnkodikucmVwbGFjZSgvPC9nLCAnXFxcXHUwMDNjJylcbiAgY29uc3QgZXNjID0gKHMpID0+IFN0cmluZyhzKS5yZXBsYWNlKC8mL2csICcmYW1wOycpLnJlcGxhY2UoLzwvZywgJyZsdDsnKVxuICAvLyBUaGUgb25lIGxpbmUgdGhlIHR3byBtb2RlcyBsb2FkIGEgYnVuZGxlIHdpdGg6IHRoZSBidWlsdCBJSUZFIChTUkktY2hlY2tlZCkgdnMgdGhlIGRldiBlbnRyeS5cbiAgY29uc3QgbG9hZGVyID0gZGV2XG4gICAgPyBgZnVuY3Rpb24gYnVuZGxlKGIpIHsgcmV0dXJuIGltcG9ydChyZWwoYi5zKSkgfWBcbiAgICA6IGBmdW5jdGlvbiBidW5kbGUoYikgeyByZXR1cm4gb25jZShyZWwoYi5zKSwgJ2pzJywgYi5pID8geyBpbnRlZ3JpdHk6IGIuaSwgY3Jvc3NPcmlnaW46ICdhbm9ueW1vdXMnIH0gOiB7fSkgfWBcblxuICByZXR1cm4gU3RyaW5nLnJhd2A8IURPQ1RZUEUgaHRtbD5cbjxodG1sIGxhbmc9XCJlblwiPlxuPGhlYWQ+XG48bWV0YSBjaGFyc2V0PVwidXRmLThcIj5cbjxtZXRhIG5hbWU9XCJ2aWV3cG9ydFwiIGNvbnRlbnQ9XCJ3aWR0aD1kZXZpY2Utd2lkdGgsaW5pdGlhbC1zY2FsZT0xXCI+XG48dGl0bGU+JHtlc2ModGl0bGUpfTwvdGl0bGU+XG48bGluayByZWw9XCJpY29uXCIgaHJlZj1cImRhdGE6LFwiPlxuPHN0eWxlPlxuOnJvb3R7LS1iZzojZmZmOy0tYmcyOiNmNmY3Zjk7LS1iZzM6I2VjZWVmMjstLWJkOiNlMmU1ZWE7LS1mZzojMTUxODFkOy0tbXV0OiM2NjcwODU7LS1lcnI6I2QxM2MzY31cbkBtZWRpYShwcmVmZXJzLWNvbG9yLXNjaGVtZTpkYXJrKXs6cm9vdHstLWJnOiMxMTEzMTg7LS1iZzI6IzE4MWIyMTstLWJnMzojMjMyNzMwOy0tYmQ6IzJiMzAzODstLWZnOiNlZWYwZjM7LS1tdXQ6IzlhYTNiMjstLWVycjojZmY3YjdifX1cbip7Ym94LXNpemluZzpib3JkZXItYm94fWh0bWwsYm9keXttYXJnaW46MDtoZWlnaHQ6MTAwJX1cbmJvZHl7YmFja2dyb3VuZDp2YXIoLS1iZyk7Y29sb3I6dmFyKC0tZmcpO2ZvbnQ6MTRweC8xLjQgc3lzdGVtLXVpLC1hcHBsZS1zeXN0ZW0sXCJTZWdvZSBVSVwiLFJvYm90byxzYW5zLXNlcmlmO2Rpc3BsYXk6ZmxleDtmbGV4LWRpcmVjdGlvbjpjb2x1bW47aGVpZ2h0OjEwMHZofVxuaGVhZGVye2ZsZXg6MCAwIGF1dG87ZGlzcGxheTpmbGV4O2FsaWduLWl0ZW1zOmNlbnRlcjtnYXA6MTBweDtwYWRkaW5nOjhweCAxNHB4O2JvcmRlci1ib3R0b206MXB4IHNvbGlkIHZhcigtLWJkKX1cbmhlYWRlciBie2ZvbnQtc2l6ZToxNXB4fS5ue2NvbG9yOnZhcigtLW11dCk7Zm9udC1zaXplOjEycHh9XG4jbWVudXtkaXNwbGF5Om5vbmU7bWFyZ2luLWxlZnQ6YXV0b31cbmJ1dHRvbiwuYnRue2ZvbnQ6aW5oZXJpdDtmb250LXNpemU6MTJweDtwYWRkaW5nOjVweCAxMHB4O2JvcmRlcjoxcHggc29saWQgdmFyKC0tYmQpO2JvcmRlci1yYWRpdXM6OHB4O2JhY2tncm91bmQ6dmFyKC0tYmcyKTtjb2xvcjp2YXIoLS1mZyk7Y3Vyc29yOnBvaW50ZXI7dGV4dC1kZWNvcmF0aW9uOm5vbmU7d2hpdGUtc3BhY2U6bm93cmFwfVxuYnV0dG9uOmhvdmVyLC5idG46aG92ZXJ7YmFja2dyb3VuZDp2YXIoLS1iZzMpfVxuLmJvZHl7ZmxleDoxIDEgYXV0bztkaXNwbGF5OmZsZXg7bWluLWhlaWdodDowfVxubmF2e2ZsZXg6MCAwIDI3MHB4O292ZXJmbG93OmF1dG87Ym9yZGVyLXJpZ2h0OjFweCBzb2xpZCB2YXIoLS1iZCk7cGFkZGluZzo2cHggMCAyMHB4fVxuLmdoe3BhZGRpbmc6MTJweCAxNHB4IDRweDtmb250LXdlaWdodDo2MDA7Zm9udC1zaXplOjEzcHg7ZGlzcGxheTpmbGV4O2p1c3RpZnktY29udGVudDpzcGFjZS1iZXR3ZWVuO2dhcDo4cHh9LmdoIHNwYW57Y29sb3I6dmFyKC0tbXV0KTtmb250LXdlaWdodDo0MDB9XG4ucm93e2Rpc3BsYXk6YmxvY2s7d2lkdGg6MTAwJTt0ZXh0LWFsaWduOmxlZnQ7Ym9yZGVyOjA7Ym9yZGVyLXJhZGl1czowO2JhY2tncm91bmQ6bm9uZTtwYWRkaW5nOjZweCAxNHB4O2ZvbnQtc2l6ZToxM3B4O2xpbmUtaGVpZ2h0OjEuMzt3aGl0ZS1zcGFjZTpub3JtYWx9XG4ucm93Lmlue3BhZGRpbmctbGVmdDoyOHB4fS5yb3cgY29kZXtkaXNwbGF5OmJsb2NrO2ZvbnQtc2l6ZToxMXB4O2NvbG9yOnZhcigtLW11dCl9XG4ucm93OmhvdmVye2JhY2tncm91bmQ6dmFyKC0tYmcyKX0ucm93W2FyaWEtY3VycmVudD10cnVlXXtiYWNrZ3JvdW5kOnZhcigtLWJnMyk7Zm9udC13ZWlnaHQ6NjAwfVxubWFpbntmbGV4OjEgMSBhdXRvO2Rpc3BsYXk6ZmxleDtmbGV4LWRpcmVjdGlvbjpjb2x1bW47bWluLXdpZHRoOjA7cGFkZGluZzoxMHB4IDEycHggMTJweDtnYXA6OHB4fVxuLmJhcntkaXNwbGF5OmZsZXg7YWxpZ24taXRlbXM6Y2VudGVyO2dhcDo4cHg7ZmxleC13cmFwOndyYXB9XG4uYmFyIC50e2ZsZXg6MSAxIGF1dG87bWluLXdpZHRoOjB9LmJhciBie2ZvbnQtc2l6ZToxNXB4fS5ze2Rpc3BsYXk6YmxvY2s7Zm9udC1zaXplOjEycHg7Y29sb3I6dmFyKC0tbXV0KX1cbmNvZGV7Zm9udC1mYW1pbHk6dWktbW9ub3NwYWNlLE1lbmxvLG1vbm9zcGFjZX1cbiNlbWJlZHtkaXNwbGF5OmZsZXg7ZmxleC1kaXJlY3Rpb246Y29sdW1uO2dhcDo2cHg7cGFkZGluZzo4cHg7Ym9yZGVyOjFweCBzb2xpZCB2YXIoLS1iZCk7Ym9yZGVyLXJhZGl1czo4cHg7YmFja2dyb3VuZDp2YXIoLS1iZzIpfVxuI2VtYmVkIGxhYmVse2ZvbnQtc2l6ZToxMnB4O2NvbG9yOnZhcigtLW11dCk7ZGlzcGxheTpmbGV4O2p1c3RpZnktY29udGVudDpzcGFjZS1iZXR3ZWVuO2FsaWduLWl0ZW1zOmNlbnRlcn1cbiNlbWJlZCB0ZXh0YXJlYXt3aWR0aDoxMDAlO2hlaWdodDo1OHB4O2ZvbnQ6MTFweC8xLjM1IHVpLW1vbm9zcGFjZSxNZW5sbyxtb25vc3BhY2U7Ym9yZGVyOjFweCBzb2xpZCB2YXIoLS1iZCk7Ym9yZGVyLXJhZGl1czo2cHg7YmFja2dyb3VuZDp2YXIoLS1iZyk7Y29sb3I6dmFyKC0tZmcpO3BhZGRpbmc6NnB4O3Jlc2l6ZTp2ZXJ0aWNhbH1cbiNzbG90e2ZsZXg6MSAxIGF1dG87cG9zaXRpb246cmVsYXRpdmU7bWluLWhlaWdodDoyNDBweDtib3JkZXI6MXB4IHNvbGlkIHZhcigtLWJkKTtib3JkZXItcmFkaXVzOjEwcHg7b3ZlcmZsb3c6aGlkZGVuO2JhY2tncm91bmQ6dmFyKC0tYmcyKX1cbiNzbG90Pip7cG9zaXRpb246YWJzb2x1dGU7aW5zZXQ6MDt3aWR0aDoxMDAlO2hlaWdodDoxMDAlO2Rpc3BsYXk6YmxvY2s7Ym9yZGVyOjB9XG4uaGludHtkaXNwbGF5OmdyaWQ7cGxhY2UtaXRlbXM6Y2VudGVyO3BhZGRpbmc6MjBweDt0ZXh0LWFsaWduOmNlbnRlcjtjb2xvcjp2YXIoLS1tdXQpO2ZvbnQtc2l6ZToxM3B4fVxuLmhpbnQuZXJye2NvbG9yOnZhcigtLWVycil9XG4uaGludCBpbnB1dHtmb250OjEycHggdWktbW9ub3NwYWNlLE1lbmxvLG1vbm9zcGFjZTtwYWRkaW5nOjZweCA4cHg7Ym9yZGVyLXJhZGl1czo2cHg7Ym9yZGVyOjFweCBzb2xpZCB2YXIoLS1iZCk7YmFja2dyb3VuZDp2YXIoLS1iZyk7Y29sb3I6dmFyKC0tZmcpO3dpZHRoOm1pbigzMjBweCw3MHZ3KX1cbi8qIENhcGFiaWxpdHkgdGllcnMgKDUgXHUyMTkyIDEpOiB0aGUgdmVydGljYWwtdGFiIHNlY3Rpb25zIG9mIHRoZSBuZXN0ZWQtbWZlLXNwYSBzaWRlYmFyLiAqL1xuLnRpZXJ7cGFkZGluZzoxMnB4IDE0cHggMnB4O2Rpc3BsYXk6ZmxleDthbGlnbi1pdGVtczpiYXNlbGluZTtnYXA6N3B4fVxuLnRpZXIgLmNhcHtmb250OjcwMCAxMHB4LzEgc3lzdGVtLXVpLHNhbnMtc2VyaWY7bGV0dGVyLXNwYWNpbmc6LjVweDtjb2xvcjp2YXIoLS1iZyk7YmFja2dyb3VuZDp2YXIoLS1tdXQpO2JvcmRlci1yYWRpdXM6OTk5cHg7cGFkZGluZzozcHggN3B4fVxuLnRpZXIgLnRse2ZvbnQtd2VpZ2h0OjYwMDtmb250LXNpemU6MTJweH0udGllciAudGR7Y29sb3I6dmFyKC0tbXV0KTtmb250LXNpemU6MTFweDttYXJnaW4tbGVmdDphdXRvfVxuI2FwcHtmbGV4OjEgMSBhdXRvO2Rpc3BsYXk6ZmxleDtmbGV4LWRpcmVjdGlvbjpjb2x1bW47bWluLWhlaWdodDowfVxuW2hpZGRlbl17ZGlzcGxheTpub25lIWltcG9ydGFudH1cbkBtZWRpYShtYXgtd2lkdGg6NzAwcHgpey5ib2R5e2ZsZXgtZGlyZWN0aW9uOmNvbHVtbn1uYXZ7ZmxleDowIDAgYXV0bzttYXgtaGVpZ2h0OjQ1dmg7Ym9yZGVyLXJpZ2h0OjA7Ym9yZGVyLWJvdHRvbToxcHggc29saWQgdmFyKC0tYmQpfSNtZW51e2Rpc3BsYXk6aW5saW5lLWJsb2NrfX1cbiR7ZGV2ID8gTEFEREVSX0NTUyA6ICcnfTwvc3R5bGU+XG48L2hlYWQ+XG48Ym9keT5cbjwhLS0gVGhlICR7VFJFRV9OQU1FfSBuZXN0ZWQtbWZlLXNwYSAoY2FwYWJpbGl0eSA1LCB0aGUgcmVzZXJ2ZWQgYXBwLXNoZWxsKTogYSBWdWUgc2luZ2xlLXBhZ2UgYXBwXG4gICAgIHdob3NlIHNpZGViYXIgaXMgdGhlIGNvbXBvc2FiaWxpdHkgbGFkZGVyIHJlbmRlcmVkIGFzIHZlcnRpY2FsIHRhYnMgKGNhcGFiaWxpdHkgNSBcdTIxOTIgMSksXG4gICAgIGVhY2ggcm93IG1vdW50aW5nIHRoYXQgcGx1Z2luJ3MgY3VzdG9tIGVsZW1lbnQgaW4gdGhlIG9uZSBzbG90LiBUaGlzIFNBTUUgcGFnZSBpcyB0aGVcbiAgICAgc2VydmVkIHN0dWRpbyByb290IChwdWJsaWMvaW5kZXguaHRtbCkgQU5EIHRoZSBDYXBhY2l0b3IgbW9iaWxlLWFwcCBlbnRyeSAod2ViRGlyOiBwdWJsaWMpLlxuICAgICBWdWUgZHJpdmVzIHRoZSBzaGVsbDsgdGhlIG1hcCBlbGVtZW50cyBtb3VudCBpbXBlcmF0aXZlbHkgaW50byAjc2xvdCAodGhleSBvd24gdGhlaXIgRE9NKS4gLS0+XG48ZGl2IGlkPVwiYXBwXCI+XG48aGVhZGVyPlxuICA8Yj4ke2VzYyh0aXRsZSl9PC9iPjxzcGFuIGNsYXNzPVwiblwiPnt7IGNvdW50TGFiZWwgfX08L3NwYW4+JHtkZXYgPyBMQURERVJfSFRNTCA6ICcnfVxuICA8YnV0dG9uIGlkPVwibWVudVwiIHR5cGU9XCJidXR0b25cIiBhcmlhLWNvbnRyb2xzPVwibmF2XCIgYXJpYS1leHBhbmRlZD1cInRydWVcIiBAY2xpY2s9XCJuYXZPcGVuID0gIW5hdk9wZW5cIj5NYXBzPC9idXR0b24+XG48L2hlYWRlcj5cbjxkaXYgY2xhc3M9XCJib2R5XCI+XG4gIDxuYXYgaWQ9XCJuYXZcIiBhcmlhLWxhYmVsPVwiTWFwcyBcdTAwQjcgc29ydGVkIGJ5IGNhcGFiaWxpdHkgNSBcdTIxOTIgMVwiIHYtc2hvdz1cIm5hdk9wZW5cIj5cbiAgICA8ZGl2IGNsYXNzPVwiZ3JwXCIgdi1mb3I9XCJncnAgaW4gZ3JvdXBzXCIgOmtleT1cImdycC5jYXBcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJ0aWVyXCI+PHNwYW4gY2xhc3M9XCJjYXBcIj5DQVAge3sgZ3JwLmNhcCB9fTwvc3Bhbj48c3BhbiBjbGFzcz1cInRsXCI+e3sgZ3JwLmxhYmVsIH19PC9zcGFuPjxzcGFuIGNsYXNzPVwidGRcIj57eyBncnAucm93cy5sZW5ndGggfX08L3NwYW4+PC9kaXY+XG4gICAgICA8IS0tIGRhdGEtayBFWFBPU0VTIFRIRSBST1cgSURFTlRJVFkgVE8gVEhFIERPTS4gQSBWdWUgOmtleSBpcyBhIFJFQ09OQ0lMSUFUSU9OIEhJTlQgYW5kIGlzIE5PVFxuICAgICAgICAgICByZW5kZXJlZCBhcyBhbiBhdHRyaWJ1dGUgXHUyMDE0IGEgZGlzdGluY3Rpb24gdGhhdCBoYWQgc21va2U6Z2FsbGVyeSBmYWlsaW5nIG9uIGEgd29ya2luZyBwYWdlLlxuICAgICAgICAgICBUaGF0IGdhdGUgcmVhZHMgcm93LmRhdGFzZXQuayB0byBjb25maXJtIGEgZGVlcCBsaW5rIHNlbGVjdGVkIHRoZSByb3cgaXQgYXNrZWQgZm9yOyB3aXRoIG5vXG4gICAgICAgICAgIHN1Y2ggYXR0cmlidXRlIGl0IHJlYWQgdW5kZWZpbmVkIGFuZCByZXBvcnRlZCBcImRlZXAgbGluayByZXNvbHZlZCB0byB1bmRlZmluZWRcIi5cbiAgICAgICAgICAgTUVBU1VSRUQgMjAyNi0wOS0yMjogZGF0YS1rIGFwcGVhcmVkIFpFUk8gdGltZXMgaW4gdGhpcyBnZW5lcmF0b3IgYW5kIHplcm8gdGltZXMgaW4gdGhlXG4gICAgICAgICAgIGJ1aWx0IHBhZ2UsIHdoaWxlIHRoZSBnYWxsZXJ5IGl0c2VsZiBtb3VudHMgaXRzIGVsZW1lbnRzIGNvcnJlY3RseSBcdTIwMTQgYSBmYWxzZSBSRUQsIHdoaWNoIGlzXG4gICAgICAgICAgIGFzIGNvcnJvc2l2ZSBhcyBhIGZhbHNlIGdyZWVuIGJlY2F1c2UgaXQgZ2V0cyB0aGUgZ2F0ZSBzd2l0Y2hlZCBvZmYuXG4gICAgICAgICAgIEFzc2VydGluZyBvbiB0aGUgcmVuZGVyZWQgTEFCRUwgaW5zdGVhZCB3b3VsZCBiZSB3b3JzZTogaXQgY291cGxlcyBhIG1hY2hpbmUgY2hlY2sgdG9cbiAgICAgICAgICAgZGlzcGxheSB0ZXh0LCBzbyByZW5hbWluZyBhIHByb2ZpbGUgd291bGQgYnJlYWsgdGhlIGdhdGUuIElkZW50aXR5IGJlbG9uZ3MgaW4gdGhlIERPTS5cbiAgICAgICAgICAgTk9URTogdGhpcyBtYXJrdXAgbGl2ZXMgaW5zaWRlIGEgVEVNUExBVEUgTElURVJBTCBcdTIwMTQgbm8gYmFja3RpY2tzIGFueXdoZXJlIGluIHRoaXMgY29tbWVudCxcbiAgICAgICAgICAgb3IgdGhlIGxpdGVyYWwgZW5kcyBoZXJlIGFuZCB0aGUgcmVzdCBvZiB0aGUgZmlsZSBpcyBwYXJzZWQgYXMgY29kZS4gLS0+XG4gICAgICA8YnV0dG9uIHYtZm9yPVwiciBpbiBncnAucm93c1wiIDprZXk9XCJyLmtleVwiIDpkYXRhLWs9XCJyLmtleVwiIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cInJvd1wiIDpjbGFzcz1cInsgaW46IHIua2luZCA9PT0gJ2luc3RhbmNlJyB9XCJcbiAgICAgICAgICAgICAgOmFyaWEtY3VycmVudD1cIlN0cmluZyhhY3RpdmVLZXkgPT09IHIua2V5KVwiIEBjbGljaz1cImdvKHIua2V5KVwiPlxuICAgICAgICA8c3Bhbj57eyByLmxhYmVsIH19PC9zcGFuPjxjb2RlPiZsdDt7eyByLnRhZyB9fSZndDs8L2NvZGU+XG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgPC9uYXY+XG4gIDxtYWluPlxuICAgIDxkaXYgY2xhc3M9XCJiYXJcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJ0XCI+PGI+e3sgdHRsIH19PC9iPjxzcGFuIGNsYXNzPVwic1wiPnt7IHN1YiB9fTwvc3Bhbj48L2Rpdj5cbiAgICAgIDxhIGNsYXNzPVwiYnRuXCIgOmhyZWY9XCJvcGVuSHJlZlwiIHRhcmdldD1cIl9ibGFua1wiIHJlbD1cIm5vb3BlbmVyXCIgdi1zaG93PVwib3BlbkhyZWZcIj5PcGVuIHBhZ2U8L2E+XG4gICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiB2LXNob3c9XCJoYXNTZWxcIiA6YXJpYS1leHBhbmRlZD1cIlN0cmluZyhlbWJlZE9wZW4pXCIgQGNsaWNrPVwiZW1iZWRPcGVuID0gIWVtYmVkT3BlblwiPkNvcHkgZW1iZWQ8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGlkPVwiZW1iZWRcIiB2LXNob3c9XCJlbWJlZE9wZW4gJiYgaGFzU2VsXCI+XG4gICAgICA8bGFiZWw+aWZyYW1lIGVtYmVkIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIEBjbGljaz1cImNvcHlUZXh0KGVtYmVkSWZyYW1lLCAkZXZlbnQudGFyZ2V0KVwiPkNvcHk8L2J1dHRvbj48L2xhYmVsPlxuICAgICAgPHRleHRhcmVhIHJlYWRvbmx5IDp2YWx1ZT1cImVtYmVkSWZyYW1lXCI+PC90ZXh0YXJlYT5cbiAgICAgIDxkaXYgdi1zaG93PVwiZW1iZWRTY3JpcHRcIj48bGFiZWw+c2NyaXB0IGVtYmVkIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIEBjbGljaz1cImNvcHlUZXh0KGVtYmVkU2NyaXB0LCAkZXZlbnQudGFyZ2V0KVwiPkNvcHk8L2J1dHRvbj48L2xhYmVsPlxuICAgICAgPHRleHRhcmVhIHJlYWRvbmx5IDp2YWx1ZT1cImVtYmVkU2NyaXB0XCI+PC90ZXh0YXJlYT48L2Rpdj5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGlkPVwic2xvdFwiIHJlZj1cInNsb3RcIj48ZGl2IGNsYXNzPVwiaGludFwiPkNob29zZSBhIG1hcCBmcm9tIHRoZSBsaXN0LjwvZGl2PjwvZGl2PlxuICA8L21haW4+XG48L2Rpdj5cbjwvZGl2PlxuPHNjcmlwdD5cbihmdW5jdGlvbiAoKSB7XG4gIHZhciBUUkVFID0gJHtqc29uKHRyZWUpfSwgVE9LRU5fU1JDID0gJHtqc29uKHRva2VuVXJsKX0sIEJBS0VEX1RPS0VOID0gJHtqc29uKHRva2VuKX0sIEFQSV9CQVNFID0gJHtqc29uKGFwaUJhc2VVcmwpfSwgQVNTRVRTX0JBU0UgPSAke2pzb24oYXNzZXRzQmFzZVVybCl9LCBRQSA9ICR7anNvbihxYVdpZGdldCl9O1xuICB2YXIgREVGQVVMVF9UT0tFTl9VUkwgPSAnL2FwaS9tYXBzL3Rva2VuJztcbiAgdmFyIEJBS0VEID0gJHtqc29uKGJha2VkKX07XG4gIHZhciBzbmlwID0gJHtzcmMoc25pcCl9O1xuICB2YXIgY29tcGFjdCA9ICR7c3JjKGNvbXBhY3QpfTtcbiAgLy8gUGVlciBlbmdpbmVzLCB0aGUgc2FtZSB0YWdzIGV2ZXJ5IGxlYWYgcGFnZSBjYXJyaWVzOyBsb2FkZWQgb25jZSwgYmVmb3JlIHRoZSBidW5kbGUuXG4gIHZhciBQRUVSUyA9IHtcbiAgICBtYXBib3g6IHsgY3NzOiBbJ2h0dHBzOi8vYXBpLm1hcGJveC5jb20vbWFwYm94LWdsLWpzL3YzLjI0LjAvbWFwYm94LWdsLmNzcycsICdodHRwczovL2FwaS5tYXBib3guY29tL21hcGJveC1nbC1qcy9wbHVnaW5zL21hcGJveC1nbC1nZW9jb2Rlci92NS4wLjAvbWFwYm94LWdsLWdlb2NvZGVyLmNzcyddLFxuICAgICAgICAgICAgICBqczogWydodHRwczovL2FwaS5tYXBib3guY29tL21hcGJveC1nbC1qcy92My4yNC4wL21hcGJveC1nbC5qcycsICdodHRwczovL2FwaS5tYXBib3guY29tL21hcGJveC1nbC1qcy9wbHVnaW5zL21hcGJveC1nbC1nZW9jb2Rlci92NS4wLjAvbWFwYm94LWdsLWdlb2NvZGVyLm1pbi5qcyddIH0sXG4gICAgbWFwbGlicmU6IHsgY3NzOiBbJ2h0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbWFwbGlicmUtZ2xANS9kaXN0L21hcGxpYnJlLWdsLmNzcyddLCBqczogWydodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL21hcGxpYnJlLWdsQDUvZGlzdC9tYXBsaWJyZS1nbC5qcyddIH1cbiAgfTtcbiAgdmFyICQgPSBmdW5jdGlvbiAoaWQpIHsgcmV0dXJuIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKSB9O1xuICAvLyBUaGUgbWFwIGN1c3RvbSBlbGVtZW50cyBtb3VudCBpbXBlcmF0aXZlbHkgaW50byB0aGlzIHNsb3QgKHRoZXkgb3duIHRoZWlyIG93biBET00gYW5kIG11c3RcbiAgLy8gbm90IGJlIHJlLXJlbmRlcmVkIGJ5IFZ1ZSk7IHRoZSBWdWUgYXBwIHdyaXRlcyBpdHMgcmVmIGhlcmUgYWZ0ZXIgbW91bnQuIEZhbGxzIGJhY2sgdG8gdGhlXG4gIC8vIGVsZW1lbnQgaWQgc28gdGhlIGxvYWRlciB3b3JrcyBldmVuIGJlZm9yZSB0aGUgYXBwIGJvb3RzLlxuICB2YXIgc2xvdEVsID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gKHdpbmRvdy5fX3NwYSAmJiB3aW5kb3cuX19zcGEuc2xvdCkgfHwgJCgnc2xvdCcpIH07XG4gIHZhciBUSUVSX01BUCA9ICR7anNvbih0aWVyTWFwKX07ICAgLy8gXCI8YnVuZGxlPi88cHJvZmlsZT5cIiBcdTIxOTIgY29tcG9zaXRpb24gdGllciwgZm9yIGxpdmUgcmUtY29tcGFjdFxuICAvLyBUSElTIFBBR0UnUyBPV04gRElSRUNUT1JZLiBBIGhvc3QgbWF5IHNlcnZlIHRoZSBmb2xkZXIgYXQgL1x1MjAyNi9kb3hhLW1hcHMtYnVpbGQgKG5vIHRyYWlsaW5nXG4gIC8vIHNsYXNoKTsgdGhlIGJyb3dzZXIgd291bGQgdGhlbiByZXNvbHZlIGV2ZXJ5IHJlbGF0aXZlIHJlZiBhZ2FpbnN0IHRoZSBQQVJFTlQgZGlyZWN0b3J5IGFuZFxuICAvLyBkcm9wIHRoZSBmb2xkZXIgbmFtZSwgc28gYnVuZGxlcyA0MDQuIERlcml2ZSB0aGUgZGlyZWN0b3J5IGV4cGxpY2l0bHkgYW5kIGJ1aWxkIHJlZnMgZnJvbSBpdC5cbiAgdmFyIEJBU0UgPSAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBwID0gbG9jYXRpb24ucGF0aG5hbWUgfHwgJy8nO1xuICAgIHJldHVybiAvXFwuW2EtejAtOV0rJC9pLnRlc3QocCkgPyBwLnJlcGxhY2UoL1teL10qJC8sICcnKSA6IHAucmVwbGFjZSgvXFwvKiQvLCAnJykgKyAnLyc7XG4gIH0pKCk7XG4gIC8vIFx1MjYwNSBUSEUgVFJFRSBST09UIEFTIE9ORSBBQlNPTFVURSBVUkwgXHUyMDE0IGRlcml2ZSBpdCBPTkNFLCBuZXZlciByZS1qb2luIFRSRUUgYnkgaGFuZC5cbiAgLy8gVFJFRSBpcyBQQUdFLVJFTEFUSVZFIGFuZCBpdHMgdmFsdWUgZGlmZmVycyBwZXIgc3VyZmFjZSAoJy4uL2RveGEtbWFwcycgaW4gdGhlIGJ1aWx0IHRyZWUsXG4gIC8vICdfX3BsdWdpbi1nYWxsZXJ5JyBpbiBkZXYpLCBzbyBhIGJhcmUgVFJFRSArICcveCcgam9pbiBpcyBvbmx5IGFjY2lkZW50YWxseSByaWdodC4gSXQgd2FzIHJpZ2h0XG4gIC8vIGluIHRoZSBidWlsdCB0cmVlICh3aGVyZSB0aGUgJy4uLycgY2xpbWJzIG91dCBvZiAvX19nYWxsZXJ5LykgYW5kIFdST05HIGluIGRldiwgd2hlcmUgaXQgYXNrZWRcbiAgLy8gZm9yIC9fX2dhbGxlcnkvX19wbHVnaW4tZ2FsbGVyeS9tYW5pZmVzdC5qc29uLiBNRUFTVVJFRCAyMDI2LTA5LTIyLCBib3RoIHNlcnZlcnMgcnVubmluZzpcbiAgLy8gICAgIGRldiAgIC9fX2dhbGxlcnkvX19wbHVnaW4tZ2FsbGVyeS9tYW5pZmVzdC5qc29uIC4uLiA0MDQgICAod2hhdCB0aGUgcGFnZSBhc2tlZCBmb3IpXG4gIC8vICAgICBkZXYgICAvX19wbHVnaW4tZ2FsbGVyeS9tYW5pZmVzdC5qc29uIC4uLi4uLi4uLi4uLi4gMjAwICAgKHdoYXQgaXQgbWVhbnQpXG4gIC8vICAgICBidWlsdCAvZG94YS1tYXBzL21hbmlmZXN0Lmpzb24gLi4uLi4uLi4uLi4uLi4uLi4uLi4gMjAwXG4gIC8vIHJlbCgpIG5ldmVyIGhhZCB0aGUgYnVnIGJlY2F1c2UgaXQgYWx3YXlzIGFuY2hvcmVkIHRvIEJBU0UuIFJlc29sdmluZyB0aHJvdWdoIHRoZSBVUkwgcGFyc2VyXG4gIC8vIChyYXRoZXIgdGhhbiBzdHJpbmctam9pbmluZykgYWxzbyBjb2xsYXBzZXMgdGhlICcuLi8nIHByb3Blcmx5IGZvciBCT1RIIHN1cmZhY2VzIGF0IG9uY2UuXG4gIC8vIFJlc29sdmUgVFJFRSAqYWdhaW5zdCogdGhlIHBhZ2UncyBvd24gZGlyZWN0b3J5IFx1MjAxNCBkbyBOT1Qgc3RyaW5nLWpvaW4gaXQgb250byBCQVNFLiBUUkVFIG1heSBiZVxuICAvLyBST09URUQgKCcvX19wbHVnaW4tZ2FsbGVyeScgaW4gZGV2KSwgYW5kICdCQVNFICsgVFJFRScgd291bGQgZ2x1ZSBpdCBvbiB0byB5aWVsZFxuICAvLyAvX19nYWxsZXJ5Ly9fX3BsdWdpbi1nYWxsZXJ5LCB3aGljaCA0MDRzIGp1c3QgYXMgc3VyZWx5IGFzIHRoZSBvcmlnaW5hbCBidWcuIFBhc3NpbmcgQkFTRSBhc1xuICAvLyB0aGUgYmFzZSBVUkwgbGV0cyB0aGUgVVJMIHBhcnNlciBhcHBseSB0aGUgcmlnaHQgcnVsZSBwZXIgc2hhcGU6IGEgcm9vdGVkIFRSRUUgcmVwbGFjZXMgdGhlXG4gIC8vIHBhdGgsIGEgJy4uLycgVFJFRSBjbGltYnMgb3V0IG9mIC9fX2dhbGxlcnkvLCBhbmQgYSBiYXJlIG5hbWUgcmVzb2x2ZXMgYmVzaWRlIGl0LlxuICB2YXIgVFJFRV9VUkwgPSBuZXcgVVJMKFRSRUUsIG5ldyBVUkwoQkFTRSwgbG9jYXRpb24uaHJlZikpLmhyZWYucmVwbGFjZSgvXFwvKyQvLCAnJyk7XG4gIC8vIEFTU0VUUyBsaXZlIElOU0lERSB0aGUgdHJlZSAocHVibGljLzx0cmVlPi9hc3NldHMpLCB3aGljaCBpcyB3aGF0IGV2ZXJ5IGxlYWYgcGFnZSBwb2ludHMgYXQ6XG4gIC8vIGEgbGVhZiBhdCAvPHRyZWU+LzxidW5kbGU+Lzxwcm9maWxlPi8gYmFrZXMgYXNzZXRzQmFzZSBcIi4uLy4uL2Fzc2V0c1wiIC0+IC88dHJlZT4vYXNzZXRzLiBTb1xuICAvLyBhbmNob3IgdG8gVFJFRV9VUkwsIG5vdCB0byB0aGlzIFBBR0UncyBkaXJlY3RvcnkuXG4gIC8vIFRoaXMgd2FzIEJBU0UgKyAnYXNzZXRzJyBcdTIwMTQgY29ycmVjdCBvbmx5IHdoaWxlIHRoZSBnYWxsZXJ5IFdBUyB0aGUgcm9vdCBwYWdlLCB3aGVyZSB0aGUgdHdvXG4gIC8vIGNvaW5jaWRlLiBTaW5jZSB0aGUgZ2FsbGVyeSBtb3ZlZCB0byAvX19nYWxsZXJ5IGl0IGFza2VkIGZvciAvX19nYWxsZXJ5L2Fzc2V0cy8uLi4gTUVBU1VSRURcbiAgLy8gb24gdGhlIGJ1aWx0IHRyZWUgd2l0aCB0aGUgcGFnZSBhdCAvX19nYWxsZXJ5LzpcbiAgLy8gICAgIC9fX2dhbGxlcnkvYXNzZXRzL3ZlbmRvci92dWUvdnVlLmdsb2JhbC5wcm9kLmpzIC4uLiA0MDQgICAod2hhdCB0aGUgcGFnZSBhc2tlZCBmb3IpXG4gIC8vICAgICAvZG94YS1tYXBzL2Fzc2V0cy92ZW5kb3IvdnVlL3Z1ZS5nbG9iYWwucHJvZC5qcyAuLi4gMjAwICAgKHdoZXJlIGl0IGxpdmVzKVxuICAvLyBJdCBkZWdyYWRlZCBxdWlldGx5IHJhdGhlciB0aGFuIGJsYW5raW5nIFx1MjAxNCBsb2FkVnVlKCkgZmFsbHMgYmFjayB0byB0aGUganNEZWxpdnIgQ0ROIFx1MjAxNCBzbyB0aGVcbiAgLy8gcGFnZSBzdGlsbCB3b3JrZWQgd2hpbGUgc2lsZW50bHkgbG9zaW5nIHRoZSBwb3J0YWJsZS9vZmZsaW5lL25vLUNETiBwcm9wZXJ0eSB0aGUgdmVuZG9yZWRcbiAgLy8gY29weSBleGlzdHMgdG8gcHJvdmlkZS4gVGhlIGRldiBzZXJ2ZXIgcGFzc2VzIGFzc2V0c0Jhc2VVcmwgZXhwbGljaXRseSwgc28gdGhpcyBpcyB0aGVcbiAgLy8gYnVpbHQtdHJlZSBoYWxmIG9mIHRoZSBzYW1lIGZpeCBpdHMgY29tbWVudCBhbHJlYWR5IGRvY3VtZW50cy5cbiAgdmFyIEFTU0VUUyA9IEFTU0VUU19CQVNFIHx8IFRSRUVfVVJMICsgJy9hc3NldHMnO1xuICB2YXIgUkVHID0gQkFLRUQsIGFjdGl2ZSA9IG51bGwsIHNlcSA9IDAsIGxvYWRlZCA9IHt9LCBmZXRjaGVkVG9rZW4gPSAnJztcbiAgdmFyIG5hcnJvdyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5tYXRjaE1lZGlhICYmIHdpbmRvdy5tYXRjaE1lZGlhKCcobWF4LXdpZHRoOjcwMHB4KScpLm1hdGNoZXMgfTtcblxuICAvLyBNYW5pZmVzdCByZWZzIGFyZSByZWxhdGl2ZSB0byB0aGUgdHJlZSByb290OyB0aGlzIHBhZ2Ugc2l0cyBvbmUgbGV2ZWwgYWJvdmUgaXQuIFJlZnMgYXJlXG4gIC8vIGFuY2hvcmVkIHRvIEJBU0UgKGFib3ZlKSBzbyB0aGV5IHJlc29sdmUgdGhlIHNhbWUgd2l0aCBvciB3aXRob3V0IGEgdHJhaWxpbmcgc2xhc2guXG4gIGZ1bmN0aW9uIHJlbCh1KSB7IHJldHVybiAvXihbYS16XSs6fFxcLykvaS50ZXN0KHUpID8gdSA6IEJBU0UgKyBUUkVFICsgJy8nICsgdS5yZXBsYWNlKC9eXFwuXFwvLywgJycpIH1cbiAgZnVuY3Rpb24gcXAobmFtZSkgeyB0cnkgeyByZXR1cm4gbmV3IFVSTFNlYXJjaFBhcmFtcyhsb2NhdGlvbi5zZWFyY2gpLmdldChuYW1lKSB8fCAnJyB9IGNhdGNoIChlKSB7IHJldHVybiAnJyB9IH1cbiAgZnVuY3Rpb24gaGludChtc2csIGVycikgeyB2YXIgc2xvdCA9IHNsb3RFbCgpOyB2YXIgZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOyBkLmNsYXNzTmFtZSA9ICdoaW50JyArIChlcnIgPyAnIGVycicgOiAnJyk7IGQudGV4dENvbnRlbnQgPSBtc2c7IHNsb3QuaW5uZXJIVE1MID0gJyc7IHNsb3QuYXBwZW5kQ2hpbGQoZCk7IHJldHVybiBkIH1cbiAgZnVuY3Rpb24gYXNzaWduKHQpIHsgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsgdmFyIHMgPSBhcmd1bWVudHNbaV07IGZvciAodmFyIGsgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBrKSkgdFtrXSA9IHNba10gfSByZXR1cm4gdCB9XG5cbiAgZnVuY3Rpb24gb25jZSh1cmwsIGtpbmQsIGF0dHJzKSB7XG4gICAgaWYgKGxvYWRlZFt1cmxdKSByZXR1cm4gbG9hZGVkW3VybF07XG4gICAgbG9hZGVkW3VybF0gPSBuZXcgUHJvbWlzZShmdW5jdGlvbiAob2ssIGZhaWwpIHtcbiAgICAgIHZhciBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoa2luZCA9PT0gJ2NzcycgPyAnbGluaycgOiAnc2NyaXB0Jyk7XG4gICAgICBpZiAoa2luZCA9PT0gJ2NzcycpIHsgZWwucmVsID0gJ3N0eWxlc2hlZXQnOyBlbC5ocmVmID0gdXJsIH0gZWxzZSB7IGVsLnNyYyA9IHVybDsgYXNzaWduKGVsLCBhdHRycyB8fCB7fSkgfVxuICAgICAgZWwub25sb2FkID0gZnVuY3Rpb24gKCkgeyBvaygpIH07IGVsLm9uZXJyb3IgPSBmdW5jdGlvbiAoKSB7IGRlbGV0ZSBsb2FkZWRbdXJsXTsgZmFpbChuZXcgRXJyb3IoJ2ZhaWxlZCB0byBsb2FkICcgKyB1cmwpKSB9O1xuICAgICAgZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChlbCk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGxvYWRlZFt1cmxdO1xuICB9XG4gIGZ1bmN0aW9uIHBlZXIocHJvdmlkZXIpIHtcbiAgICB2YXIgcCA9IFBFRVJTW3Byb3ZpZGVyXSB8fCBQRUVSUy5tYXBib3gsIGNoYWluID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgcC5jc3MuZm9yRWFjaChmdW5jdGlvbiAodSkgeyBvbmNlKHUsICdjc3MnKSB9KTtcbiAgICBwLmpzLmZvckVhY2goZnVuY3Rpb24gKHUpIHsgY2hhaW4gPSBjaGFpbi50aGVuKGZ1bmN0aW9uICgpIHsgcmV0dXJuIG9uY2UodSwgJ2pzJykgfSkgfSk7XG4gICAgcmV0dXJuIGNoYWluO1xuICB9XG4gICR7bG9hZGVyfVxuXG4gIC8vIFJlc29sdmUgYSBkZWVwLWxpbmsga2V5IChcIjxidW5kbGU+Lzxwcm9maWxlPlsvPGluc3RhbmNlPl1cIikgYWdhaW5zdCB0aGUgbGl2ZSByZWdpc3RyeS5cbiAgZnVuY3Rpb24gZmluZChwYXJ0cykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgUkVHLmxlbmd0aDsgaSsrKSBpZiAoUkVHW2ldLmIgPT09IHBhcnRzWzBdKSB7XG4gICAgICB2YXIgYiA9IFJFR1tpXTtcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYi5wLmxlbmd0aDsgaisrKSBpZiAoYi5wW2pdLnAgPT09IHBhcnRzWzFdKSB7XG4gICAgICAgIHZhciBwID0gYi5wW2pdO1xuICAgICAgICBpZiAocGFydHMubGVuZ3RoIDwgMykgcmV0dXJuIHsgYjogYiwgcDogcCwgeDogbnVsbCB9O1xuICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IChwLmluIHx8IFtdKS5sZW5ndGg7IGsrKykgaWYgKHAuaW5ba10uaWQgPT09IHBhcnRzWzJdKSByZXR1cm4geyBiOiBiLCBwOiBwLCB4OiBwLmluW2tdIH07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLy8gU2FtZSBwcm9maWxlLWNvbmZpZyB0aGUgbGVhZiBwYWdlIGJha2VzIChwcm9maWxlIHBhZ2U6IHByb2ZpbGUgKyBkYXRhU291cmNlICsgaW5zdGFuY2VJZDtcbiAgLy8gaW5zdGFuY2UgcGFnZTogaXRzIHByb3BzKSwgcGx1cyB0aGUgaG9zdC1zdXBwbGllZCBzaGFyZSBVUkwgb2YgdGhhdCBsZWFmIHBhZ2UuXG4gIGZ1bmN0aW9uIG1vdW50KGIsIHAsIHgsIHRhZykge1xuICAgIHZhciBjZmcgPSB4ID8gYXNzaWduKHsgYXNzZXRzQmFzZTogQVNTRVRTIH0sIHgucHIpIDogeyBwcm9maWxlOiBwLnAsIGRhdGFTb3VyY2U6ICdwcmF5LXRvb2xzJywgaW5zdGFuY2VJZDogYi5iICsgJy0nICsgcC5wLCBhc3NldHNCYXNlOiBBU1NFVFMgfTtcbiAgICBpZiAoUUEpIGNmZy5xYSA9IHRydWU7XG4gICAgY2ZnLnNoYXJlVXJsID0gbmV3IFVSTChyZWwoKHggfHwgcCkudSksIGxvY2F0aW9uLmhyZWYpLmhyZWY7XG4gICAgLy8gXHUyNjA1IEhBTkQgVEhFIFRSRUUgUk9PVCBET1dOIFx1MjAxNCBhbiBlbGVtZW50IHRoYXQgZmV0Y2hlcyB0aGUgbWFuaWZlc3QgY2Fubm90IGd1ZXNzIGl0IGZyb20gaGVyZS5cbiAgICAvLyBBIGNhcC01IHNoZWxsIGRlcml2ZXMgaXRzIHRyZWUgcm9vdCBmcm9tIGxvY2F0aW9uLnBhdGhuYW1lIHdoZW4gbm90aGluZyBpcyBwYXNzZWQsIHdoaWNoIGlzXG4gICAgLy8gcmlnaHQgb24gaXRzIG93biA8dHJlZT4vPGJ1bmRsZT4vPHByb2ZpbGU+LyBsZWFmIHBhZ2UgYW5kIFdST05HIGluIHRoaXMgZ2FsbGVyeSwgd2hlcmUgdGhlXG4gICAgLy8gcGF0aCBiZWxvbmdzIHRvIHRoZSBQQUdFLCBub3QgdGhlIGVsZW1lbnQuIGRveGEtbWFwcy1zcGEncyByZWxhdGl2ZSBmYWxsYmFjayBpcyAnLi4vJywgc29cbiAgICAvLyBmcm9tIC9fX2dhbGxlcnkvIGl0IGFza2VkIGZvciAvbWFuaWZlc3QuanNvbi4gTUVBU1VSRUQgYnkgdGhlIHNtb2tlOmdhbGxlcnkgZ2F0ZTpcbiAgICAvLyAgICAgXHUyNzE3IGRveGEtbWFwcy1zcGEvZG94YS1tYXBzLXNwYSAgIGRhdGE6IDQwNCBodHRwOi8vbG9jYWxob3N0OjUxNzMvbWFuaWZlc3QuanNvblxuICAgIC8vIFRoZSBTUEEncyBPV04gbmVzdGVkLW1vdW50IHBhdGggYWxyZWFkeSBzZXRzIGJvdGggb2YgdGhlc2UgZm9yIGV4YWN0bHkgdGhpcyByZWFzb247IHRoaXNcbiAgICAvLyBnYWxsZXJ5IHdhcyB0aGUgb25lIG1vdW50IHBhdGggdGhhdCBuZXZlciBsZWFybmVkIHRoZSBsZXNzb24uIFNldCBib3RoLCBiZWNhdXNlIG5vdCBldmVyeVxuICAgIC8vIGVsZW1lbnQgcmVhZHMgcHJvZmlsZS1jb25maWcgKGFuIGVsZW1lbnQgbW91bnRpbmcgaXRzIG93biBTRkMgaGFzIG5vIFByb2ZpbGVMb2FkZXIgYWJvdmUgaXRcbiAgICAvLyBhbmQgdGFrZXMgdHJlZS1iYXNlIGFzIGEgcHJvcCk7IGFuIGVsZW1lbnQgdGhhdCBkZWNsYXJlcyBuZWl0aGVyIGlnbm9yZXMgYm90aC5cbiAgICBjZmcudHJlZUJhc2UgPSBUUkVFX1VSTDtcbiAgICB3aW5kb3cuTUFQX0FQUF9BUElfVVJMID0gKHggJiYgeC5hKSB8fCBBUElfQkFTRTtcbiAgICB2YXIgcHJvdmlkZXIgPSBjZmcucHJvdmlkZXIgPT09ICdtYXBsaWJyZScgPyAnbWFwbGlicmUnIDogJ21hcGJveCcsIG15ID0gKytzZXE7XG4gICAgaGludChwcm92aWRlciA9PT0gJ21hcGxpYnJlJyA/ICdsb2FkaW5nIG1hcFx1MjAyNicgOiAnbG9hZGluZyB0b2tlblx1MjAyNicpO1xuICAgIHBlZXIocHJvdmlkZXIpLnRoZW4oZnVuY3Rpb24gKCkgeyByZXR1cm4gYnVuZGxlKGIpIH0pLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKG15ICE9PSBzZXEpIHJldHVybjtcbiAgICAgIHJlc29sdmVUb2tlbihjZmcsIHByb3ZpZGVyID09PSAnbWFwbGlicmUnLCBmdW5jdGlvbiAodG9rZW4pIHtcbiAgICAgICAgaWYgKG15ICE9PSBzZXEpIHJldHVybjtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICB2YXIgYyA9IHRva2VuID8gYXNzaWduKHt9LCBjZmcsIHsgdGs6IHRva2VuIH0pIDogY2ZnO1xuICAgICAgICAgIHZhciBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnKTsgZWwuc2V0QXR0cmlidXRlKCdwcm9maWxlLWNvbmZpZycsIEpTT04uc3RyaW5naWZ5KGMpKTtcbiAgICAgICAgICBlbC5zZXRBdHRyaWJ1dGUoJ3RyZWUtYmFzZScsIFRSRUVfVVJMKTsgICAvLyBzZWUgY2ZnLnRyZWVCYXNlIGFib3ZlIFx1MjAxNCBib3RoLCBmb3IgYm90aCBraW5kcyBvZiBlbGVtZW50XG4gICAgICAgICAgdmFyIHNsb3QgPSBzbG90RWwoKTsgc2xvdC5pbm5lckhUTUwgPSAnJzsgc2xvdC5hcHBlbmRDaGlsZChlbCk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgaGludChlICYmIGUubWVzc2FnZSA/IGUubWVzc2FnZSA6IFN0cmluZyhlKSwgdHJ1ZSkgfVxuICAgICAgfSk7XG4gICAgfSkuY2F0Y2goZnVuY3Rpb24gKGUpIHsgaWYgKG15ID09PSBzZXEpIGhpbnQoJ0ZhaWxlZCB0byBsb2FkICcgKyBiLmIgKyAnOiAnICsgKGUgJiYgZS5tZXNzYWdlID8gZS5tZXNzYWdlIDogZSksIHRydWUpIH0pO1xuICB9XG5cbiAgLy8gTWFwYm94IHRva2VuIHJlc29sdXRpb24gXHUyMDE0IHRoZSBsZWFmIHBhZ2VzJyBsYWRkZXIsIGluIHByZWNlZGVuY2Ugb3JkZXI6XG4gIC8vICAgMS4gcHJvcCAoY29uZmlnLnRrKSAgMi4gP3RrPSBvbiB0aGlzIHBhZ2UncyBVUkwgKHN0b3JlZCBvbmNlIGZvciBldmVyeSBwYWdlIG9mIHRoZSB0cmVlKVxuICAvLyAgIDMuIGJha2VkIHRva2VuIFx1MjAxNCB0aGVuLCBub25lIGZvdW5kLCBhIHRva2VuIEVORFBPSU5UIGlzIGZldGNoZWQsIGZpcnN0IGFuc3dlciB3aW5zOlxuICAvLyAgIDQuIHdpbmRvdy5NQVBfVE9LRU5fVVJMICA1LiBjb25maWd1cmVkIFRPS0VOX1NSQyAgNi4gc2FtZS1vcmlnaW4gL2FwaS9tYXBzL3Rva2VuIFx1MjAxNCBlbHNlIGFzayBvbmNlLlxuICBmdW5jdGlvbiByZXNvbHZlVG9rZW4oY2ZnLCB0b2tlbkZyZWUsIGRvbmUpIHtcbiAgICBpZiAodG9rZW5GcmVlKSByZXR1cm4gZG9uZSgnJyk7XG4gICAgdmFyIHN0b3JlZCA9ICcnOyB0cnkgeyBzdG9yZWQgPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnTUFQU19TVEFHSU5HX1RLJykgfHwgJycgfSBjYXRjaCAoZSkge31cbiAgICB2YXIgdXJsVGsgPSBxcCgndGsnKTsgaWYgKHVybFRrKSB7IHRyeSB7IGxvY2FsU3RvcmFnZS5zZXRJdGVtKCdNQVBTX1NUQUdJTkdfVEsnLCB1cmxUaykgfSBjYXRjaCAoZSkge30gfVxuICAgIHZhciBkaXJlY3RUb2tlbiA9IGNmZy50ayB8fCB1cmxUayB8fCBzdG9yZWQgfHwgQkFLRURfVE9LRU4gfHwgZmV0Y2hlZFRva2VuO1xuICAgIGlmIChkaXJlY3RUb2tlbikgcmV0dXJuIGRvbmUoZGlyZWN0VG9rZW4pO1xuICAgIGZ1bmN0aW9uIGFza1Rva2VuKHByZWZpeCkge1xuICAgICAgdmFyIGQgPSBoaW50KCcnLCB0cnVlKTtcbiAgICAgIGQuaW5uZXJIVE1MID0gKHByZWZpeCA/ICc8ZGl2PjwvZGl2PicgOiAnJykgKyAnPGRpdj5tYXAgbmVlZHMgYSBNYXBib3ggdG9rZW4gXHUyMDE0IDxpbnB1dCBpZD1cInRrSW5cIiB0eXBlPVwicGFzc3dvcmRcIiBwbGFjZWhvbGRlcj1cInBhc3RlIHBrLlx1MjAyNiAoc3RheXMgaW4gdGhpcyBicm93c2VyKVwiPiA8YnV0dG9uIGlkPVwidGtHb1wiIHR5cGU9XCJidXR0b25cIj51c2UgaXQ8L2J1dHRvbj48L2Rpdj4nO1xuICAgICAgaWYgKHByZWZpeCkgZC5maXJzdENoaWxkLnRleHRDb250ZW50ID0gcHJlZml4O1xuICAgICAgJCgndGtHbycpLm9uY2xpY2sgPSBmdW5jdGlvbiAoKSB7IHZhciB2ID0gKCQoJ3RrSW4nKS52YWx1ZSB8fCAnJykudHJpbSgpOyBpZiAoIXYpIHJldHVybjsgdHJ5IHsgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ01BUFNfU1RBR0lOR19USycsIHYpIH0gY2F0Y2ggKGUpIHt9IGRvbmUodikgfTtcbiAgICB9XG4gICAgdmFyIGNhbmRpZGF0ZXMgPSBbXTtcbiAgICBmdW5jdGlvbiBhZGRDYW5kaWRhdGUodSkgeyBpZiAodSAmJiBjYW5kaWRhdGVzLmluZGV4T2YodSkgPT09IC0xKSBjYW5kaWRhdGVzLnB1c2godSkgfVxuICAgIGFkZENhbmRpZGF0ZSh3aW5kb3cuTUFQX1RPS0VOX1VSTCk7XG4gICAgYWRkQ2FuZGlkYXRlKFRPS0VOX1NSQyAmJiBUT0tFTl9TUkMgIT09ICd3aW5kb3cuTUFQX1RPS0VOX1VSTCcgPyBUT0tFTl9TUkMgOiAnJyk7XG4gICAgYWRkQ2FuZGlkYXRlKERFRkFVTFRfVE9LRU5fVVJMKTtcbiAgICBmdW5jdGlvbiBleHRyYWN0VG9rZW4oZGF0YSkgeyBpZiAodHlwZW9mIGRhdGEgPT09ICdzdHJpbmcnKSByZXR1cm4gZGF0YS50cmltKCk7IGlmIChkYXRhICYmIHR5cGVvZiBkYXRhID09PSAnb2JqZWN0JykgcmV0dXJuIGRhdGEudG9rZW4gfHwgZGF0YS50ayB8fCBkYXRhLmFjY2Vzc1Rva2VuIHx8ICcnOyByZXR1cm4gJycgfVxuICAgIGZ1bmN0aW9uIGZldGNoVG9rZW4oaSwgZXJyb3JzKSB7XG4gICAgICBpZiAoaSA+PSBjYW5kaWRhdGVzLmxlbmd0aCkgcmV0dXJuIGFza1Rva2VuKCdUb2tlbiBmZXRjaCBmYWlsZWQgZnJvbSAnICsgY2FuZGlkYXRlcy5qb2luKCcsICcpICsgJyBcdTIwMTQgc2V0IHdpbmRvdy5NQVBfVE9LRU5fVVJMIG9yIHBhc3MgP3RrPS4gKCcgKyBlcnJvcnMuam9pbignIHwgJykgKyAnKScpO1xuICAgICAgdmFyIHVybCA9IGNhbmRpZGF0ZXNbaV07XG4gICAgICByZXR1cm4gZmV0Y2godXJsKS50aGVuKGZ1bmN0aW9uIChyKSB7XG4gICAgICAgIGlmICghci5vaykgdGhyb3cgbmV3IEVycm9yKHVybCArICcgXHUyMTkyIEhUVFAgJyArIHIuc3RhdHVzKTtcbiAgICAgICAgcmV0dXJuIChyLmhlYWRlcnMuZ2V0KCdjb250ZW50LXR5cGUnKSB8fCAnJykuaW5kZXhPZignanNvbicpICE9PSAtMSA/IHIuanNvbigpIDogci50ZXh0KCk7XG4gICAgICB9KS50aGVuKGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgIHZhciB0ayA9IGV4dHJhY3RUb2tlbihkYXRhKTsgaWYgKCF0aykgdGhyb3cgbmV3IEVycm9yKHVybCArICcgXHUyMTkyIG5vIHRva2VuIGluIHJlc3BvbnNlJyk7XG4gICAgICAgIGZldGNoZWRUb2tlbiA9IHRrOyBkb25lKHRrKTtcbiAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlKSB7IGVycm9ycy5wdXNoKGUgJiYgZS5tZXNzYWdlID8gZS5tZXNzYWdlIDogU3RyaW5nKGUpKTsgcmV0dXJuIGZldGNoVG9rZW4oaSArIDEsIGVycm9ycykgfSk7XG4gICAgfVxuICAgIGZldGNoVG9rZW4oMCwgW10pO1xuICB9XG5cbiAgZnVuY3Rpb24gY29weVRleHQodGV4dCwgYnRuKSB7XG4gICAgdmFyIG9rID0gZnVuY3Rpb24gKCkgeyB2YXIgdCA9IGJ0bi50ZXh0Q29udGVudDsgYnRuLnRleHRDb250ZW50ID0gJ0NvcGllZCc7IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyBidG4udGV4dENvbnRlbnQgPSB0IH0sIDEyMDApIH07XG4gICAgaWYgKG5hdmlnYXRvci5jbGlwYm9hcmQgJiYgbmF2aWdhdG9yLmNsaXBib2FyZC53cml0ZVRleHQpIG5hdmlnYXRvci5jbGlwYm9hcmQud3JpdGVUZXh0KHRleHQpLnRoZW4ob2ssIGZ1bmN0aW9uICgpIHt9KTsgZWxzZSB7XG4gICAgICB0cnkgeyB2YXIgdGEgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0ZXh0YXJlYScpOyB0YS52YWx1ZSA9IHRleHQ7IGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQodGEpOyB0YS5zZWxlY3QoKTsgZG9jdW1lbnQuZXhlY0NvbW1hbmQoJ2NvcHknKTsgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZCh0YSk7IG9rKCkgfSBjYXRjaCAoZSkge31cbiAgICB9XG4gIH1cblxuICAvLyBcdTI1MDBcdTI1MDAgVGhlIGNhcGFiaWxpdHkgbGFkZGVyIGZvciB0aGUgc2lkZWJhciBoZWFkaW5ncyAoNSBcdTIxOTIgMSksIHJlYWRlci1mYWNpbmcgbmFtZXMgXHUyNTAwXHUyNTAwXG4gIHZhciBDQVBfTEFCRUwgPSB7IDU6ICdBcHAgc2hlbGwgXHUwMEI3IG5lc3RlZC1tZmUtc3BhJywgNDogJ0NvbXBvc2l0ZSBlbGVtZW50JywgMzogJ011bHRpLXZpZXcgZWxlbWVudCcsIDI6ICdQcmVzZXQgZWxlbWVudCcsIDE6ICdTaW5nbGUgZWxlbWVudCcgfTtcbiAgLy8gUkVHIFx1MjE5MiB0YWIgZ3JvdXBzIGtleWVkIGJ5IGNhcGFiaWxpdHksIG1vc3QtY29tcG9zZWQgZmlyc3QgKDUgXHUyMTkyIDEpLiBFYWNoIGdyb3VwIGxpc3RzIGV2ZXJ5XG4gIC8vIHByb2ZpbGUgKGFuZCBpdHMgcHJlc2V0IGluc3RhbmNlcykgYXMgb25lIHJvdzsgYSBidW5kbGUgY29udHJpYnV0ZXMgcm93cyB0byB0aGUgdGllciBvZiBlYWNoXG4gIC8vIHByb2ZpbGUgaXQgaG9sZHMsIHNvIG9uZSBidW5kbGUgY2FuIGFwcGVhciB1bmRlciBzZXZlcmFsIGNhcGFiaWxpdHkgaGVhZGluZ3MuXG4gIGZ1bmN0aW9uIHRvR3JvdXBzKCkge1xuICAgIHZhciBieUNhcCA9IHt9O1xuICAgIFJFRy5mb3JFYWNoKGZ1bmN0aW9uIChiKSB7XG4gICAgICAoYi5wIHx8IFtdKS5mb3JFYWNoKGZ1bmN0aW9uIChwKSB7XG4gICAgICAgIHZhciBjYXAgPSBwLmMgfHwgMSwgdGFnID0gcC5lIHx8IGIuZVswXSB8fCBiLmI7XG4gICAgICAgIChieUNhcFtjYXBdID0gYnlDYXBbY2FwXSB8fCBbXSkucHVzaCh7IGtleTogYi5iICsgJy8nICsgcC5wLCBraW5kOiAncHJvZmlsZScsIGxhYmVsOiBwLnAsIHRhZzogdGFnLCBidW5kbGU6IGIuYiB9KTtcbiAgICAgICAgKHAuaW4gfHwgW10pLmZvckVhY2goZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgICBieUNhcFtjYXBdLnB1c2goeyBrZXk6IGIuYiArICcvJyArIHAucCArICcvJyArIHguaWQsIGtpbmQ6ICdpbnN0YW5jZScsIGxhYmVsOiB4LnQsIHRhZzogeC5lIHx8IHRhZywgYnVuZGxlOiBiLmIgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIFs1LCA0LCAzLCAyLCAxXS5maWx0ZXIoZnVuY3Rpb24gKGMpIHsgcmV0dXJuIGJ5Q2FwW2NdICYmIGJ5Q2FwW2NdLmxlbmd0aCB9KS5tYXAoZnVuY3Rpb24gKGMpIHtcbiAgICAgIHJldHVybiB7IGNhcDogYywgbGFiZWw6IENBUF9MQUJFTFtjXSB8fCAoJ2NhcGFiaWxpdHkgJyArIGMpLCByb3dzOiBieUNhcFtjXSB9O1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gYm9vdFZ1ZShWdWUpIHtcbiAgICB2YXIgYXBwID0gVnVlLmNyZWF0ZUFwcCh7XG4gICAgICBkYXRhOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgZ3JvdXBzOiB0b0dyb3VwcygpLCBhY3RpdmVLZXk6ICcnLCBuYXZPcGVuOiB0cnVlLCBlbWJlZE9wZW46IGZhbHNlLFxuICAgICAgICAgIHR0bDogJ0Nob29zZSBhIG1hcCcsIHN1YjogJycsIG9wZW5IcmVmOiAnJywgaGFzU2VsOiBmYWxzZSwgZW1iZWRJZnJhbWU6ICcnLCBlbWJlZFNjcmlwdDogJydcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgICBjb21wdXRlZDoge1xuICAgICAgICBjb3VudExhYmVsOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdmFyIG5iID0gUkVHLmxlbmd0aCwgbnAgPSAwLCBuaSA9IDA7XG4gICAgICAgICAgUkVHLmZvckVhY2goZnVuY3Rpb24gKGIpIHsgbnAgKz0gKGIucCB8fCBbXSkubGVuZ3RoOyAoYi5wIHx8IFtdKS5mb3JFYWNoKGZ1bmN0aW9uIChwKSB7IG5pICs9IChwLmluIHx8IFtdKS5sZW5ndGggfSkgfSk7XG4gICAgICAgICAgcmV0dXJuIG5iICsgJyBidW5kbGVzIFx1MDBCNyAnICsgbnAgKyAnIHByb2ZpbGVzIFx1MDBCNyAnICsgbmkgKyAnIGluc3RhbmNlcyc7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBtZXRob2RzOiB7XG4gICAgICAgIGdvOiBmdW5jdGlvbiAoa2V5KSB7IGxvY2F0aW9uLmhhc2ggPSAnIy8nICsga2V5LnNwbGl0KCcvJykubWFwKGVuY29kZVVSSUNvbXBvbmVudCkuam9pbignLycpIH0sXG4gICAgICAgIGNvcHlUZXh0OiBjb3B5VGV4dCxcbiAgICAgICAgcmVidWlsZDogZnVuY3Rpb24gKG0pIHsgaWYgKG0pIHsgdHJ5IHsgUkVHID0gY29tcGFjdChtLCBmYWxzZSwgVElFUl9NQVApIH0gY2F0Y2ggKGUpIHsgUkVHID0gQkFLRUQgfSB9IHRoaXMuZ3JvdXBzID0gdG9Hcm91cHMoKTsgdGhpcy5yb3V0ZSgpOyB9LFxuICAgICAgICByb3V0ZTogZnVuY3Rpb24gKCkgeyB2YXIgaCA9IChsb2NhdGlvbi5oYXNoIHx8ICcnKS5yZXBsYWNlKC9eI1xcLz8vLCAnJyk7IGlmIChoKSB0aGlzLnNlbGVjdChoKTsgfSxcbiAgICAgICAgc2VsZWN0OiBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgdmFyIHBhcnRzID0ga2V5LnNwbGl0KCcvJykubWFwKGZ1bmN0aW9uIChzKSB7IHRyeSB7IHJldHVybiBkZWNvZGVVUklDb21wb25lbnQocykgfSBjYXRjaCAoZSkgeyByZXR1cm4gcyB9IH0pO1xuICAgICAgICAgIHZhciBoaXQgPSBmaW5kKHBhcnRzKTsgdGhpcy5hY3RpdmVLZXkgPSBwYXJ0cy5qb2luKCcvJyk7XG4gICAgICAgICAgaWYgKCFoaXQpIHsgdGhpcy50dGwgPSAnTm8gc3VjaCBtYXAnOyB0aGlzLnN1YiA9IGtleTsgdGhpcy5vcGVuSHJlZiA9ICcnOyB0aGlzLmhhc1NlbCA9IGZhbHNlOyB0aGlzLmVtYmVkT3BlbiA9IGZhbHNlOyBoaW50KCdObyBzdWNoIG1hcDogJyArIGtleSwgdHJ1ZSk7IHJldHVybjsgfVxuICAgICAgICAgIHZhciBiID0gaGl0LmIsIHAgPSBoaXQucCwgeCA9IGhpdC54LCB0YWcgPSAoeCAmJiB4LmUpIHx8IHAuZSB8fCBiLmVbMF0gfHwgYi5iO1xuICAgICAgICAgIHRoaXMudHRsID0geCA/IHgudCA6IHAucDsgdGhpcy5zdWIgPSBiLmIgKyAnIFx1MDBCNyA8JyArIHRhZyArICc+JyArIChwLmQgPyAnIFx1MDBCNyAnICsgcC5kIDogJycpO1xuICAgICAgICAgIHRoaXMub3BlbkhyZWYgPSByZWwoKHggfHwgcCkudSk7IHRoaXMuaGFzU2VsID0gdHJ1ZTsgdGhpcy5lbWJlZE9wZW4gPSBmYWxzZTtcbiAgICAgICAgICB2YXIgZW0gPSB4ID8gKHguZW0gfHwgc25pcChiLCBwLCB4KSkgOiAocC5lbSB8fCBzbmlwKGIsIHAsIG51bGwpKTtcbiAgICAgICAgICB0aGlzLmVtYmVkSWZyYW1lID0gZW0uaWZyYW1lIHx8ICcnOyB0aGlzLmVtYmVkU2NyaXB0ID0gZW0uc2NyaXB0IHx8ICcnO1xuICAgICAgICAgIGlmIChuYXJyb3coKSkgdGhpcy5uYXZPcGVuID0gZmFsc2U7XG4gICAgICAgICAgbW91bnQoYiwgcCwgeCwgdGFnKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIG1vdW50ZWQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICB3aW5kb3cuX19zcGEgPSB7IHNsb3Q6IHRoaXMuJHJlZnMuc2xvdCwgYXBwOiB0aGlzIH07XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdoYXNoY2hhbmdlJywgZnVuY3Rpb24gKCkgeyBzZWxmLnJvdXRlKCkgfSk7XG4gICAgICAgIHRyeSB7IHdpbmRvdy5tYXRjaE1lZGlhKCcobWF4LXdpZHRoOjcwMHB4KScpLmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIGZ1bmN0aW9uIChlKSB7IGlmICghZS5tYXRjaGVzKSBzZWxmLm5hdk9wZW4gPSB0cnVlIH0pIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgIC8vIExpdmUgbWFuaWZlc3QgZmlyc3QgKHRoZSBwYWdlIHN0YXlzIHJpZ2h0IHdoZW4gYnVuZGxlcyBjaGFuZ2UpOyBiYWtlZCBjb3B5IGlzIHRoZSBmYWxsYmFjay5cbiAgICAgICAgaWYgKHR5cGVvZiBmZXRjaCA9PT0gJ2Z1bmN0aW9uJyAmJiBsb2NhdGlvbi5wcm90b2NvbCAhPT0gJ2ZpbGU6Jykge1xuICAgICAgICAgIGZldGNoKFRSRUVfVVJMICsgJy9tYW5pZmVzdC5qc29uJywgeyBjYWNoZTogJ25vLWNhY2hlJyB9KS50aGVuKGZ1bmN0aW9uIChyKSB7IHJldHVybiByLm9rID8gci5qc29uKCkgOiBudWxsIH0pXG4gICAgICAgICAgICAudGhlbihmdW5jdGlvbiAobSkgeyBzZWxmLnJlYnVpbGQobSkgfSwgZnVuY3Rpb24gKCkgeyBzZWxmLnJvdXRlKCkgfSk7XG4gICAgICAgIH0gZWxzZSB7IHNlbGYucm91dGUoKTsgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIGFwcC5jb25maWcuY29tcGlsZXJPcHRpb25zLmlzQ3VzdG9tRWxlbWVudCA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRydWUgfTsgLy8gbWFwIHRhZ3MgYXJlIGN1c3RvbSBlbGVtZW50c1xuICAgIGFwcC5tb3VudCgnI2FwcCcpO1xuICB9XG5cbiAgLy8gVnVlIGRyaXZlcyB0aGUgc2hlbGwgKHRoZSBuZXN0ZWQtbWZlLXNwYSkuIFNlbGYtaG9zdGVkIGZpcnN0IChwb3J0YWJsZSAvIG9mZmxpbmUgLyBuby1DRE4pLFxuICAvLyB0aGVuIGEgQ0ROIGZhbGxiYWNrOyBpZiBuZWl0aGVyIGxvYWRzLCBkZWdyYWRlIHRvIGEgcGxhaW4gcmVuZGVyZWQgbGlzdCBzbyB0aGUgcGFnZSBuZXZlclxuICAvLyBibGFua3MuIG9uY2UoKSByZXNvbHZlcyB0aGUgdHJlZS1yZWxhdGl2ZSBBU1NFVFMgcGF0aCB0aGUgc2FtZSB3YXkgZXZlcnkgbGVhZiBwYWdlIGRvZXMuXG4gIGZ1bmN0aW9uIGxvYWRWdWUoKSB7XG4gICAgaWYgKHdpbmRvdy5WdWUpIHJldHVybiBQcm9taXNlLnJlc29sdmUod2luZG93LlZ1ZSk7XG4gICAgdmFyIGxvY2FsID0gQVNTRVRTICsgJy92ZW5kb3IvdnVlL3Z1ZS5nbG9iYWwucHJvZC5qcyc7XG4gICAgdmFyIGNkbiA9ICdodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL3Z1ZUAzL2Rpc3QvdnVlLmdsb2JhbC5wcm9kLmpzJztcbiAgICByZXR1cm4gb25jZShsb2NhbCwgJ2pzJykudGhlbihmdW5jdGlvbiAoKSB7IHJldHVybiB3aW5kb3cuVnVlIH0sIGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBvbmNlKGNkbiwgJ2pzJykudGhlbihmdW5jdGlvbiAoKSB7IHJldHVybiB3aW5kb3cuVnVlIH0pO1xuICAgIH0pO1xuICB9XG4gIGxvYWRWdWUoKS50aGVuKGZ1bmN0aW9uIChWdWUpIHtcbiAgICBpZiAoVnVlKSBib290VnVlKFZ1ZSk7XG4gICAgZWxzZSBmYWxsYmFja1JlbmRlcigpO1xuICB9KS5jYXRjaChmdW5jdGlvbiAoKSB7IGZhbGxiYWNrUmVuZGVyKCk7IH0pO1xuXG4gIC8vIE5vLVZ1ZSBkZWdyYWRlOiByZW5kZXIgdGhlIHNhbWUgY2FwYWJpbGl0eS1zb3J0ZWQgbGlzdCB3aXRoIHBsYWluIERPTSBzbyBhIG1hcCBpcyBzdGlsbFxuICAvLyByZWFjaGFibGUgKHBhcnNlLXNhZmUsIGRlcGVuZGVuY3ktZnJlZSkuIFJhcmUgXHUyMDE0IFZ1ZSBpcyB2ZW5kb3JlZCBpbiB0aGUgdHJlZS5cbiAgZnVuY3Rpb24gZmFsbGJhY2tSZW5kZXIoKSB7XG4gICAgdmFyIGhvc3QgPSAkKCdhcHAnKTsgaWYgKCFob3N0KSByZXR1cm47XG4gICAgZnVuY3Rpb24gcGFpbnQoKSB7XG4gICAgICB2YXIgbmF2ID0gaG9zdC5xdWVyeVNlbGVjdG9yKCcjbmF2Jyk7IGlmICghbmF2KSByZXR1cm47XG4gICAgICBuYXYuaW5uZXJIVE1MID0gJyc7XG4gICAgICB0b0dyb3VwcygpLmZvckVhY2goZnVuY3Rpb24gKGcpIHtcbiAgICAgICAgdmFyIGggPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsgaC5jbGFzc05hbWUgPSAndGllcic7IGgudGV4dENvbnRlbnQgPSAnQ0FQICcgKyBnLmNhcCArICcgXHUwMEI3ICcgKyBnLmxhYmVsOyBuYXYuYXBwZW5kQ2hpbGQoaCk7XG4gICAgICAgIGcucm93cy5mb3JFYWNoKGZ1bmN0aW9uIChyKSB7XG4gICAgICAgICAgdmFyIGJ0biA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2J1dHRvbicpOyBidG4udHlwZSA9ICdidXR0b24nOyBidG4uY2xhc3NOYW1lID0gJ3JvdycgKyAoci5raW5kID09PSAnaW5zdGFuY2UnID8gJyBpbicgOiAnJyk7XG4gICAgICAgICAgYnRuLnRleHRDb250ZW50ID0gci5sYWJlbDsgYnRuLm9uY2xpY2sgPSBmdW5jdGlvbiAoKSB7IGxvY2F0aW9uLmhhc2ggPSAnIy8nICsgci5rZXkuc3BsaXQoJy8nKS5tYXAoZW5jb2RlVVJJQ29tcG9uZW50KS5qb2luKCcvJykgfTtcbiAgICAgICAgICBuYXYuYXBwZW5kQ2hpbGQoYnRuKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcm91dGUoKSB7XG4gICAgICB2YXIgaCA9IChsb2NhdGlvbi5oYXNoIHx8ICcnKS5yZXBsYWNlKC9eI1xcLz8vLCAnJyk7IGlmICghaCkgcmV0dXJuO1xuICAgICAgdmFyIHBhcnRzID0gaC5zcGxpdCgnLycpLm1hcChmdW5jdGlvbiAocykgeyB0cnkgeyByZXR1cm4gZGVjb2RlVVJJQ29tcG9uZW50KHMpIH0gY2F0Y2ggKGUpIHsgcmV0dXJuIHMgfSB9KTtcbiAgICAgIHZhciBoaXQgPSBmaW5kKHBhcnRzKTsgaWYgKGhpdCkgbW91bnQoaGl0LmIsIGhpdC5wLCBoaXQueCwgKGhpdC54ICYmIGhpdC54LmUpIHx8IGhpdC5wLmUgfHwgaGl0LmIuZVswXSB8fCBoaXQuYi5iKTsgZWxzZSBoaW50KCdObyBzdWNoIG1hcDogJyArIGgsIHRydWUpO1xuICAgIH1cbiAgICB3aW5kb3cuX19zcGEgPSB7IHNsb3Q6ICQoJ3Nsb3QnKSB9O1xuICAgIGlmICh0eXBlb2YgZmV0Y2ggPT09ICdmdW5jdGlvbicgJiYgbG9jYXRpb24ucHJvdG9jb2wgIT09ICdmaWxlOicpIHtcbiAgICAgIGZldGNoKFRSRUVfVVJMICsgJy9tYW5pZmVzdC5qc29uJywgeyBjYWNoZTogJ25vLWNhY2hlJyB9KS50aGVuKGZ1bmN0aW9uIChyKSB7IHJldHVybiByLm9rID8gci5qc29uKCkgOiBudWxsIH0pXG4gICAgICAgIC50aGVuKGZ1bmN0aW9uIChtKSB7IGlmIChtKSB7IHRyeSB7IFJFRyA9IGNvbXBhY3QobSwgZmFsc2UsIFRJRVJfTUFQKSB9IGNhdGNoIChlKSB7IFJFRyA9IEJBS0VEIH0gfSBwYWludCgpOyByb3V0ZSgpOyB9LCBmdW5jdGlvbiAoKSB7IHBhaW50KCk7IHJvdXRlKCk7IH0pO1xuICAgIH0gZWxzZSB7IHBhaW50KCk7IHJvdXRlKCk7IH1cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignaGFzaGNoYW5nZScsIHJvdXRlKTtcbiAgfVxufSkoKTtcbjwvc2NyaXB0PlxuJHtkZXYgPyBMQURERVJfSlMgOiAnJ308L2JvZHk+XG48L2h0bWw+XG5gXG59XG5cbi8vIFx1MjUwMFx1MjUwMCBDTEk6IHRoZSBBUkNISVZFRCBnYWxsZXJ5LCBwdWJsaWMvX19nYWxsZXJ5L2luZGV4Lmh0bWwgXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXG4vL1xuLy8gXHUyNjA1IFRIRSBST09UIFBBR0UgSVMgVEhFIFNUVURJTyBOT1c7IFRIRSBHQUxMRVJZIElTIEFSQ0hJVkVEIEJFU0lERSBJVCAoMjAyNi0wOS0yMikuXG4vLyBUSEUgRElSRUNUSU9OOiBiYWNrIHVwIGFuZCBBUkNISVZFIHdoYXQgaXMgb2xkIGluc3RlYWQgb2YgZWRpdGluZyBpdC4gV2hhdCBpcyBuZWVkZWQgaXMgYVxuLy8gZnVuY3Rpb25hbCBQbHVnaW4gU3R1ZGlvIHdpdGggZXZlcnkgcGx1Z2luIHdvcmtpbmcsIG5vdCB0aGUgb2xkIHN0YWdpbmcgaW5kZXguaHRtbCBwYWdlcyB0aGF0XG4vLyBnZXQgaW4gdGhlIHdheS5cbi8vXG4vLyBUaGUgQlVJTFQgdHJlZSBub3cgYmVoYXZlcyBleGFjdGx5IGxpa2UgdGhlIERFViBzZXJ2ZXIgKGludGVybmFsL3BsdWdpbi1nYWxsZXJ5L2Rldi1wbHVnaW4ubWpzLFxuLy8gd2hpY2ggbWFkZSB0aGlzIG1vdmUgZmlyc3QpOiBgL2AgbW91bnRzIDxwbHVnaW4tc3R1ZGlvPiwgYW5kIHRoZSBnYWxsZXJ5IHN0YXlzIHJlYWNoYWJsZSBhdCB0aGVcbi8vIGV4cGxpY2l0IC9fX2dhbGxlcnkgZm9yIGFueW9uZSB3aG8gd2FudHMgYSBidW5kbGUgaW5kZXguIElkZW50aWNhbCByb3V0ZXMgaW4gYm90aCB0cmVlcyBpcyB0aGVcbi8vIHBvaW50IFx1MjAxNCBhIGRldmVsb3BlciB3aG8gbGVhcm5zIGAvYCBpbiBkZXYgbXVzdCBub3QgZmluZCBhIGRpZmZlcmVudCBwcm9kdWN0IGluIHRoZSBidWlsdCB0cmVlLlxuLy9cbi8vIEFSQ0hJVkVELCBOT1QgREVMRVRFRCBcdTIwMTQgZGVsaWJlcmF0ZWx5LiBUaGlzIG1vZHVsZSBpcyBOT1QgZGVhZCBjb2RlIGFuZCBtdXN0IG5vdCBiZSByZW1vdmVkOlxuLy8gaXQgYWxzbyBleHBvcnRzIHJlbmRlckdhbGxlcnkoKS9yZWFkQnVpbGRDb25maWcoKSwgd2hpY2ggdGhlIGRldiBwbHVnaW4gaW1wb3J0cywgYW5kIGl0IGNvbXB1dGVzXG4vLyB0aGUgbWFuaWZlc3Qtc2hhcGVkIG1vZGVsLiBEZWxldGluZyBpdCBicmVha3MgYGJ1biBydW4gZGV2YCBhbmQgYGJ1biBydW4gYnVpbGRgLiBTbyB0aGUgcGFnZSBpdFxuLy8gd3JpdGVzIHNpbXBseSBNT1ZFUyBvbmUgbGV2ZWwgZG93bjsgbm90aGluZyBhYm91dCBob3cgaXQgaXMgYnVpbHQgY2hhbmdlcy5cbi8vXG4vLyBXSFkgYHRyZWVgIEdBSU5TIEEgJy4uLyc6IHRoZSBnYWxsZXJ5J3MgcnVudGltZSByZWZzIChyZWwoKSBhbmQgdGhlIHR3byBtYW5pZmVzdCBmZXRjaGVzKSBhcmVcbi8vIFJFTEFUSVZFIHRvIHRoZSBwYWdlLiBNb3ZpbmcgdGhlIHBhZ2UgZnJvbSBwdWJsaWMvaW5kZXguaHRtbCBpbnRvIHB1YmxpYy9fX2dhbGxlcnkvaW5kZXguaHRtbFxuLy8gcHV0cyBpdCBvbmUgbGV2ZWwgZGVlcGVyLCBzbyB0aGUgc2FtZSBzdHJpbmcgbXVzdCBjbGltYiBiYWNrIG91dCB0byByZWFjaCBwdWJsaWMvPHRyZWU+Ly5cbi8vIFdpdGhvdXQgdGhpcyB0aGUgYXJjaGl2ZWQgcGFnZSBmZXRjaGVzIC9fX2dhbGxlcnkvZG94YS1tYXBzL21hbmlmZXN0Lmpzb24gYW5kIHJlbmRlcnMgRU1QVFkgXHUyMDE0XG4vLyB0aGUgaWRlbnRpY2FsIGZhaWx1cmUgbW9kZSB0aGUgc3R1ZGlvIGhpdCBpbiBkZXYgd2hlbiBpdHMgdHJlZS1iYXNlIHdhcyBtaXNzaW5nLlxuZnVuY3Rpb24gbWFpbigpIHtcbiAgY29uc3QgQ0ZHID0gcmVhZEJ1aWxkQ29uZmlnKClcbiAgY29uc3QgbWFuaWZlc3RQYXRoID0gam9pbihST09ULCAncHVibGljJywgQ0ZHLm5hbWUsICdtYW5pZmVzdC5qc29uJylcbiAgaWYgKCFleGlzdHNTeW5jKG1hbmlmZXN0UGF0aCkpIHsgY29uc29sZS5lcnJvcihgW2dlbmVyYXRlLWdhbGxlcnldIG1pc3NpbmcgJHttYW5pZmVzdFBhdGh9IFx1MjAxNCBydW4gXFxgYnVuIHJ1biB0cmVlXFxgIGZpcnN0YCk7IHByb2Nlc3MuZXhpdCgxKSB9XG4gIGNvbnN0IG1hbmlmZXN0ID0gSlNPTi5wYXJzZShyZWFkRmlsZVN5bmMobWFuaWZlc3RQYXRoLCAndXRmOCcpKVxuICBjb25zdCB0aWVyTWFwID0gcmVhZFNvdXJjZVRpZXJzKCkgICAvLyBcIjxidW5kbGU+Lzxwcm9maWxlPlwiIFx1MjE5MiBjb21wb3NpdGlvbiB0aWVyICh0aGUgbWFuaWZlc3QgY2FycmllcyBub25lKVxuICBjb25zdCBodG1sID0gcmVuZGVyR2FsbGVyeShtYW5pZmVzdCwgeyBtb2RlOiAnYnVpbGQnLCB0aXRsZTogQ0ZHLnRpdGxlLCB0cmVlOiAnLi4vJyArIENGRy5uYW1lLCB0b2tlblVybDogQ0ZHLnRva2VuVXJsLCB0b2tlbjogQ0ZHLnRva2VuLCBhcGlCYXNlVXJsOiBDRkcuYXBpQmFzZVVybCwgYXNzZXRzQmFzZVVybDogQ0ZHLmFzc2V0c0Jhc2VVcmwsIHFhV2lkZ2V0OiBDRkcucWFXaWRnZXQsIHRpZXJNYXAgfSlcbiAgY29uc3QgYmFrZWQgPSBjb21wYWN0KG1hbmlmZXN0LCB0cnVlLCB0aWVyTWFwKVxuICBjb25zdCBuUHJvZmlsZXMgPSBiYWtlZC5yZWR1Y2UoKG4sIGIpID0+IG4gKyBiLnAubGVuZ3RoLCAwKVxuICBjb25zdCBuSW5zdGFuY2VzID0gYmFrZWQucmVkdWNlKChuLCBiKSA9PiBuICsgYi5wLnJlZHVjZSgoaywgcCkgPT4gayArIChwLmluID8gcC5pbi5sZW5ndGggOiAwKSwgMCksIDApXG4gIGNvbnN0IG5PdmVycmlkZXMgPSBiYWtlZC5yZWR1Y2UoKG4sIGIpID0+IG4gKyBiLnAucmVkdWNlKChrLCBwKSA9PiBrICsgKHAuZW0gPyAxIDogMCkgKyAocC5pbiB8fCBbXSkuZmlsdGVyKHggPT4geC5lbSkubGVuZ3RoLCAwKSwgMClcbiAgLy8gQVJDSElWRUQgT1VUIE9GIHB1YmxpYy8gKGRlY2lzaW9uLCBjYXJkIEJVSUxELU9VVFBVVC1JUy1PTkUtRk9MREVSKTogcHVibGljLyBob2xkcyBvbmx5IHRoZVxuICAvLyBvdXRwdXQgZm9sZGVyICsgUkVBRE1FLm1kLCBhbmQgdGhlIHN0dWRpbyBhdCA8dHJlZT4vaW5kZXguaHRtbCBpcyB0aGUgZnJvbnQgcGFnZS4gVGhlIGxhc3RcbiAgLy8gZ2VuZXJhdGVkIGNvcHkgaXMga2VwdCBpbiB0aGUgdW1icmVsbGEncyBfcWEtY3ljbGUvYXJjaGl2ZS8uIFRoaXMgc3RpbGwgcmVuZGVycyBvbiByZXF1ZXN0LCBpbnRvIGFcbiAgLy8gZGlyZWN0b3J5IHlvdSBuYW1lIFx1MjAxNCBuZXZlciBpbnRvIHB1YmxpYy8uXG4gIGNvbnN0IG9pID0gcHJvY2Vzcy5hcmd2LmluZGV4T2YoJy0tb3V0JylcbiAgY29uc3Qgb3V0RGlyID0gb2kgPj0gMCAmJiBwcm9jZXNzLmFyZ3Zbb2kgKyAxXSA/IHJlc29sdmUocHJvY2Vzcy5hcmd2W29pICsgMV0pIDogbnVsbFxuICBpZiAoIW91dERpcikge1xuICAgIGNvbnNvbGUubG9nKCdbZ2VuZXJhdGUtZ2FsbGVyeV0gQVJDSElWRUQgXHUyMDE0IG5vdCB3cml0dGVuLiBUaGUgZ2FsbGVyeSBpcyBubyBsb25nZXIgcGFydCBvZiB0aGUgYnVpbGQgb3Igb2YgcHVibGljLzsnKVxuICAgIGNvbnNvbGUubG9nKCcgIHRoZSBQbHVnaW4gU3R1ZGlvICg8dHJlZT4vaW5kZXguaHRtbCkgaXMgdGhlIGZyb250IHBhZ2UuIFRvIHJlbmRlciBpdCBhbnl3YXk6IGJ1biBydW4gZ2FsbGVyeSAtLSAtLW91dCA8ZGlyPicpXG4gICAgcmV0dXJuXG4gIH1cbiAgaWYgKG91dERpciA9PT0gcmVzb2x2ZShST09ULCAncHVibGljJykgfHwgb3V0RGlyLnN0YXJ0c1dpdGgocmVzb2x2ZShST09ULCAncHVibGljJykgKyAnLycpKSB7XG4gICAgY29uc29sZS5lcnJvcignW2dlbmVyYXRlLWdhbGxlcnldIHJlZnVzaW5nIHRvIHdyaXRlIGludG8gcHVibGljLyBcdTIwMTQgaXQgaG9sZHMgb25seSB0aGUgb3V0cHV0IGZvbGRlci4nKTsgcHJvY2Vzcy5leGl0KDEpXG4gIH1cbiAgY29uc3QgZGlyID0gb3V0RGlyXG4gIG1rZGlyU3luYyhkaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pXG4gIHdyaXRlRmlsZVN5bmMoam9pbihkaXIsICdpbmRleC5odG1sJyksIGh0bWwpXG4gIGNvbnNvbGUubG9nKGBbZ2VuZXJhdGUtZ2FsbGVyeV0gJHtkaXJ9L2luZGV4Lmh0bWwgKEFSQ0hJVkVEIHJlbmRlcmluZykgXHUyMDE0ICR7KGh0bWwubGVuZ3RoIC8gMTAyNCkudG9GaXhlZCgxKX0gS0IgXHUwMEI3ICR7YmFrZWQubGVuZ3RofSBidW5kbGUocykgXHUwMEI3ICR7blByb2ZpbGVzfSBwcm9maWxlKHMpIFx1MDBCNyAke25JbnN0YW5jZXN9IGluc3RhbmNlKHMpIFx1MDBCNyAke25PdmVycmlkZXN9IGVtYmVkIHNuaXBwZXQocykgYmFrZWQgdmVyYmF0aW0gKHRoZSByZXN0IHJlLWRlcml2ZSlgKVxufVxuLy8gUnVucyBvbmx5IGFzIGEgc2NyaXB0OyBpbXBvcnRpbmcgaXQgKHRoZSBkZXYgcGx1Z2luIGRvZXMpIGhhcyBubyBzaWRlIGVmZmVjdHMuXG5pZiAocHJvY2Vzcy5hcmd2WzFdICYmIGltcG9ydC5tZXRhLnVybCA9PT0gcGF0aFRvRmlsZVVSTChwcm9jZXNzLmFyZ3ZbMV0pLmhyZWYpIG1haW4oKVxuIiwgImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCIvaG9tZS9sazEweC9Xb3Jrc3BhY2UvZWNvLWR4L3Jvb3QtZG94YS1tYXBzL3d0LWhmL2ludGVybmFsXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCIvaG9tZS9sazEweC9Xb3Jrc3BhY2UvZWNvLWR4L3Jvb3QtZG94YS1tYXBzL3d0LWhmL2ludGVybmFsL190cmVlLW5hbWUubWpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9ob21lL2xrMTB4L1dvcmtzcGFjZS9lY28tZHgvcm9vdC1kb3hhLW1hcHMvd3QtaGYvaW50ZXJuYWwvX3RyZWUtbmFtZS5tanNcIjsvKipcbiAqIF90cmVlLW5hbWUubWpzIFx1MjAxNCB0aGUgT05FIHBsYWNlIHRoZSBvdXRwdXQgdHJlZSdzIG5hbWUgaXMgcmVhZC5cbiAqXG4gKiBUaGUgYnVpbHQgdHJlZSBsaXZlcyBhdCBwdWJsaWMvPFRSRUVfTkFNRT4vIGFuZCBldmVyeSBlbWJlZGRhYmxlIFVSTCBjYXJyaWVzIGl0XG4gKiAoXHUyMDI2LzxUUkVFX05BTUU+LzxidW5kbGU+Lzxwcm9maWxlPi9pbmRleC5odG1sKS4gSXRzIG5hbWUgaGFzIGFsd2F5cyBiZWVuIGNvbmZpZ3VyYWJsZSBcdTIwMTRcbiAqIHZpdGUuZG94YS1tYXBzLWJ1aWxkLWNvbmZpZy5qc29uIGBuYW1lYCBcdTIwMTQgYnV0IGEgY2Vuc3VzIG9uIDIwMjYtMDktMjUgZm91bmQgNjEgdG9vbGluZyBmaWxlc1xuICogdGhhdCBpZ25vcmVkIHRoZSBrbm9iIGFuZCBoYXJkY29kZWQgJ2RveGEtbWFwcycgKDE4MSBsaXRlcmFscyksIHNvIGNoYW5naW5nIHRoZSBjb25maWcgcmVuYW1lZFxuICogdGhlIGJ1aWxkIHdoaWxlIHRob3NlIGdhdGVzIGtlcHQgcmVhZGluZyB0aGUgb2xkIGZvbGRlci4gRXZlcnkgdG9vbCBub3cgaW1wb3J0cyBUUkVFX05BTUUgZnJvbVxuICogaGVyZSwgd2hpY2ggbWFrZXMgcmVuYW1pbmcgdGhlIHRyZWUgYSBvbmUtbGluZSBjb25maWcgY2hhbmdlIChzZWVcbiAqIF9xYS1jeWNsZS8wMy1kZXBsb3ltZW50LWN5Y2xlL3FhLWxvb3BzL1JFTkFNRS1JTVBBQ1QtZHgubWQsIG1lY2hhbmlzbSBBKS5cbiAqXG4gKiAgIGltcG9ydCB7IFRSRUVfTkFNRSwgQlVJTERfQ09ORklHX0ZJTEUgfSBmcm9tICcuL190cmVlLW5hbWUubWpzJ1xuICogICBUUkVFPSQobm9kZSBpbnRlcm5hbC9fdHJlZS1uYW1lLm1qcykgICAgICAgICAgICAjIGZyb20gYSBzaGVsbCBzY3JpcHRcbiAqXG4gKiBUaGUgZmFsbGJhY2ssIHVzZWQgb25seSB3aGVuIHRoZSBjb25maWcgaXMgbWlzc2luZyBvciBoYXMgbm8gbmFtZSwgaXMgdGhlIGhpc3RvcmljYWwgbmFtZSxcbiAqIHNvIGEgY2hlY2tvdXQgd2l0aG91dCB0aGUgY29uZmlnIGJlaGF2ZXMgZXhhY3RseSBhcyBiZWZvcmUuXG4gKi9cbmltcG9ydCB7IHJlYWRGaWxlU3luYyB9IGZyb20gJ25vZGU6ZnMnXG5pbXBvcnQgeyByZXNvbHZlLCBkaXJuYW1lIH0gZnJvbSAnbm9kZTpwYXRoJ1xuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCB9IGZyb20gJ25vZGU6dXJsJ1xuXG5jb25zdCBST09UID0gcmVzb2x2ZShkaXJuYW1lKGZpbGVVUkxUb1BhdGgoaW1wb3J0Lm1ldGEudXJsKSksICcuLicpXG5leHBvcnQgY29uc3QgQlVJTERfQ09ORklHX0ZJTEUgPSByZXNvbHZlKFJPT1QsICd2aXRlLmRveGEtbWFwcy1idWlsZC1jb25maWcuanNvbicpXG5jb25zdCBGQUxMQkFDSyA9ICdkb3hhLW1hcHMnXG5cbmZ1bmN0aW9uIHJlYWQoKSB7XG4gIGxldCBuYW1lID0gJydcbiAgdHJ5IHtcbiAgICBjb25zdCBjZmcgPSBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhCVUlMRF9DT05GSUdfRklMRSwgJ3V0ZjgnKSlcbiAgICBpZiAoY2ZnICYmIHR5cGVvZiBjZmcubmFtZSA9PT0gJ3N0cmluZycpIG5hbWUgPSBjZmcubmFtZS50cmltKClcbiAgfSBjYXRjaCB7IC8qIG5vIGNvbmZpZzogdGhlIGZhbGxiYWNrICovIH1cbiAgaWYgKCFuYW1lKSByZXR1cm4gRkFMTEJBQ0tcbiAgLy8gQSB0cmVlIG5hbWUgaXMgT05FIHBhdGggc2VnbWVudCB0aGF0IGFsc28gYXBwZWFycyBpbiBwdWJsaWMgVVJMczogcmVmdXNlIGFueXRoaW5nIHRoYXQgY291bGRcbiAgLy8gZXNjYXBlIHB1YmxpYy8gb3IgbmVlZCBlc2NhcGluZyBpbiBhIFVSTCwgcmF0aGVyIHRoYW4gYnVpbGQgaW50byBhIHN1cnByaXNpbmcgcGxhY2UuXG4gIGlmICghL15bYS16MC05XVthLXowLTkuXy1dKiQvaS50ZXN0KG5hbWUpIHx8IG5hbWUuaW5jbHVkZXMoJy4uJykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFtfdHJlZS1uYW1lXSBidWlsZCBjb25maWcgXCJuYW1lXCIgbXVzdCBiZSBhIHNpbmdsZSBVUkwtc2FmZSBwYXRoIHNlZ21lbnQsIGdvdCAke0pTT04uc3RyaW5naWZ5KG5hbWUpfWApXG4gIH1cbiAgcmV0dXJuIG5hbWVcbn1cblxuZXhwb3J0IGNvbnN0IFRSRUVfTkFNRSA9IHJlYWQoKVxuLy8gR0FURUQgcHJvZmlsZXMgKHRoZSBjb25maWcncyBnYXRlZFByb2ZpbGVzKTogYnVuZGxlcyB0aGF0IGJ1aWxkIGJ1dCBtdXN0IG5ldmVyIHJlYWNoIGEgcHVibGljIHN1cmZhY2UuXG4vLyBnZW5lcmF0ZS10cmVlIGxlYXZlcyB0aGVtIG91dCBvZiB0aGUgbWFuaWZlc3QgYW5kIHBhZ2VzOyB2aXRlLmNvbmZpZy5qcyBidWlsZHMgdGhlbSBPVVRTSURFIHB1YmxpYy9cbi8vICguZ2F0ZWQvPHRyZWU+Lyk7IGNoZWNrOmdhdGVkLW5vdC1pbi10cmVlIGZhaWxzIGlmIG9uZSBhcHBlYXJzIGluIHRoZSB0cmVlIGFueXdheS5cbmZ1bmN0aW9uIHJlYWRHYXRlZCgpIHtcbiAgdHJ5IHtcbiAgICBjb25zdCBjZmcgPSBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhCVUlMRF9DT05GSUdfRklMRSwgJ3V0ZjgnKSlcbiAgICByZXR1cm4gQXJyYXkuaXNBcnJheShjZmcuZ2F0ZWRQcm9maWxlcykgPyBjZmcuZ2F0ZWRQcm9maWxlcy5maWx0ZXIoKHgpID0+IHR5cGVvZiB4ID09PSAnc3RyaW5nJyAmJiB4LnRyaW0oKSkubWFwKCh4KSA9PiB4LnRyaW0oKSkgOiBbXVxuICB9IGNhdGNoIHsgcmV0dXJuIFtdIH1cbn1cbmV4cG9ydCBjb25zdCBHQVRFRF9QUk9GSUxFUyA9IHJlYWRHYXRlZCgpXG5cbi8vIFRoZSBuYW1lIGVzY2FwZWQgZm9yIHVzZSBpbnNpZGUgYSBSZWdFeHAgc291cmNlIChhICcuJyBpbiBhIGZ1dHVyZSBuYW1lIG11c3Qgbm90IG1hdGNoIGFueSBjaGFyKS5cbmV4cG9ydCBjb25zdCBUUkVFX05BTUVfUkUgPSBUUkVFX05BTUUucmVwbGFjZSgvWy4qKz9eJHt9KCl8W1xcXVxcXFxdL2csICdcXFxcJCYnKVxuXG5pZiAocHJvY2Vzcy5hcmd2WzFdICYmIHJlc29sdmUocHJvY2Vzcy5hcmd2WzFdKSA9PT0gZmlsZVVSTFRvUGF0aChpbXBvcnQubWV0YS51cmwpKSBwcm9jZXNzLnN0ZG91dC53cml0ZShUUkVFX05BTUUgKyAnXFxuJylcbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL2hvbWUvbGsxMHgvV29ya3NwYWNlL2Vjby1keC9yb290LWRveGEtbWFwcy93dC1oZi9pbnRlcm5hbFwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL2hvbWUvbGsxMHgvV29ya3NwYWNlL2Vjby1keC9yb290LWRveGEtbWFwcy93dC1oZi9pbnRlcm5hbC9wcm9maWxlLW1ldGEubWpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9ob21lL2xrMTB4L1dvcmtzcGFjZS9lY28tZHgvcm9vdC1kb3hhLW1hcHMvd3QtaGYvaW50ZXJuYWwvcHJvZmlsZS1tZXRhLm1qc1wiOy8qKlxuICogcHJvZmlsZS1tZXRhLm1qcyBcdTIwMTQgdGhlIHBlci1wcm9maWxlIGZpZWxkcyBhIGhvc3QgcmVhZHMgZnJvbSA8cHJvZmlsZT4ubWV0YS5qc29uLCBpbiBPTkUgcGxhY2UuXG4gKlxuICogZ2VuZXJhdGUtdHJlZSAodGhlIGJ1aWx0IG1hbmlmZXN0Lmpzb24pIGFuZCB0aGUgZGV2IHNlcnZlcidzIC9fX3BsdWdpbi1nYWxsZXJ5L21hbmlmZXN0Lmpzb24gYm90aCBjYWxsXG4gKiB0aGlzLCBzbyB0aGUgZGV2IFN0dWRpbyBhbmQgdGhlIGJ1aWx0IFN0dWRpbyBjYW5ub3QgZGlzYWdyZWUgKHJlZ2E6IHRoZSBjb3JuZXIgd2lkZ2V0IG5ldmVyIG1vdW50ZWQgaW5cbiAqIGRldiBiZWNhdXNlIG9ubHkgdGhlIGJ1aWx0IG1hbmlmZXN0IGNhcnJpZWQgXCJ3aWRnZXRcIikuXG4gKiAgIHN0YWdlICAgXCJwcm9kdWN0aW9uXCIgfCBcImV4cGVyaW1lbnRhbFwiICAgZGVmYXVsdCBleHBlcmltZW50YWxcbiAqICAgaGVhdnkgICB0cnVlIHdoZW4gdGhlIGVsZW1lbnQgaG9sZHMgbGl2ZSBXZWJHTCBjb250ZXh0c1xuICogICB3aWRnZXQgIHsgY29ybmVyIH0gZm9yIGEgY29ybmVyIHdpZGdldCB0aGUgUGx1Z2luIFN0dWRpbyBtb3VudHMgb25jZSwgZml4ZWRcbiAqICAgdmlzaWJpbGl0eSAgXCJ0ZWFtXCIgfCBcInB1YmxpY1wiICAgZGVmYXVsdCB0ZWFtIFx1MjAxNCBzZWUgVklTSUJJTElUWSBiZWxvd1xuICogICBtb2JpbGUgIFwiZGVza3RvcC1vbmx5XCIgfCBcImxhcmdlci1zY3JlZW5zXCIgICBhYnNlbnQgPSBwaG9uZS1yZWFkeSBcdTIwMTQgc2VlIE1PQklMRSBiZWxvd1xuICovXG5pbXBvcnQgeyByZWFkRmlsZVN5bmMgfSBmcm9tICdub2RlOmZzJ1xuaW1wb3J0IHsgam9pbiB9IGZyb20gJ25vZGU6cGF0aCdcblxuY29uc3QgQ09STkVSUyA9IFsnYm90dG9tLXJpZ2h0JywgJ2JvdHRvbS1sZWZ0JywgJ3RvcC1yaWdodCcsICd0b3AtbGVmdCddXG5cbi8qKlxuICogXHUyNjA1IFdITyBFTFNFIE1BWSBMSVNUIFRISVMgUExVR0lOIChkeC1iYXNlLCAyMDI2LTA5LTI4KS4gVGhlIHBsYXRmb3JtIGRhc2hib2FyZCByZWFkcyBlYWNoIHRlYW0nc1xuICogb3duIC9jZG4vZHgtbWFwcy9tYW5pZmVzdC5qc29uIGluc3RlYWQgb2Ygb25lIHNoYXJlZCBpbmRleCwgc28gdGhpcyBmaWVsZCBpcyB3aGF0IGRlY2lkZXMgd2hldGhlclxuICogYSBwbHVnaW4gYXBwZWFycyBpbiBBTk9USEVSIHRlYW0ncyBsaWJyYXJ5IChsb2FkZWQgcmVhZC1vbmx5IGZyb20gdGhlIG93bmVyJ3MgQ0ROKS5cbiAqXG4gKiAgIFwidGVhbVwiICAgIGxpc3RlZCBvbmx5IGluIHRoZSBvd25pbmcgdGVhbSdzIGxpYnJhcnlcbiAqICAgXCJwdWJsaWNcIiAgYWxzbyBsaXN0ZWQgaW4gZXZlcnkgb3RoZXIgdGVhbSdzIGxpYnJhcnlcbiAqICAgQUJTRU5UICAgIHRlYW0gXHUyMDE0IGV2ZXJ5IG1hbmlmZXN0IHRoYXQgZXhpc3RzIHRvZGF5IGlzIHByaXZhdGUgdW50aWwgYSBwbHVnaW4gb3B0cyBpblxuICpcbiAqIFx1MjYwNSBETyBOT1QgUkVBQ0ggRk9SIGBzdGFnZWAgVE8gRVhQUkVTUyBUSElTLiBJdCBzaXRzIHJpZ2h0IG5leHQgdG8gaXQgaW4gdGhpcyBmaWxlIGFuZCByZWFkcyBsaWtlXG4gKiBhIGZpdDogaXQgaXMgbWF0dXJpdHksIG5vdCBhdWRpZW5jZS4gVXNpbmcgaXQgd291bGQgaGlkZSBldmVyeSBleHBlcmltZW50YWwgcGx1Z2luIGZyb20gaXRzIE9XTlxuICogdGVhbSBhbmQgcHVibGlzaCBldmVyeSBwcm9kdWN0aW9uIG9uZSB0byBldmVyeWJvZHkgXHUyMDE0IHdyb25nIGluIGJvdGggZGlyZWN0aW9ucyBhdCBvbmNlLlxuICpcbiAqIFx1MjYwNSBBTiBVTktOT1dOIFZBTFVFIElTIFJFRlVTRUQsIE5PVCBERUZBVUxURUQuIERlZmF1bHRpbmcgXCJQdWJsaWNcIiBvciBcInB1YmljXCIgdG8gdGVhbSBpcyB0aGUgc2FmZVxuICogZGlyZWN0aW9uIGFuZCB0aGF0IGlzIGV4YWN0bHkgd2hhdCBtYWtlcyBpdCBkYW5nZXJvdXM6IHRoZSBhdXRob3IgcmVhZHMgdGhlaXIgb3B0LWluIGFzIGRvbmUsIHRoZVxuICogZmllbGQgc2F5cyBwcml2YXRlLCBhbmQgbm9ib2R5IGZpbmRzIG91dCB1bnRpbCBzb21lb25lIGFza3Mgd2h5IHRoZSBwbHVnaW4gbmV2ZXIgYXBwZWFyZWQuIFRoZVxuICogZ2VuZXJhdG9yIGV4aXRzIG9uIGl0IChnZW5lcmF0ZS10cmVlLCBcInZpc2liaWxpdHlcIiBibG9jaykgc28gYSB0eXBvIGlzIGEgYnVpbGQgZmFpbHVyZSwgbG91ZCwgYXRcbiAqIHRoZSBtb21lbnQgaXQgaXMgaW50cm9kdWNlZC5cbiAqL1xuZXhwb3J0IGNvbnN0IFZJU0lCSUxJVFkgPSBbJ3RlYW0nLCAncHVibGljJ11cblxuLyoqXG4gKiBcdTI2MDUgSE9XIEEgTUFQIEJFSEFWRVMgT04gQSBQSE9ORSwgZGVjbGFyZWQgb25jZSBwZXIgcHJvZmlsZSAoU1BFQy1NT0JJTEUtRkxBRykuIFRoZSBSZXNlYXJjaCBHYWxsZXJ5XG4gKiBhbmQgdGhlIHN0YW5kYWxvbmUgbGVhZiBwYWdlIGJvdGggcmVhZCBpdCBmcm9tIGhlcmUsIHRocm91Z2ggdGhlIG1hbmlmZXN0IGFuZCB0aGUgbGVhZidzIGNvbmZpZzpcbiAqXG4gKiAgIFwiZGVza3RvcC1vbmx5XCIgICAgQkxPQ0tTIG9uIGEgbmFycm93IHNjcmVlbjogdGhlIG1hcCBpcyBub3QgbW91bnRlZCwgYSBtZXNzYWdlIHNheXMgd2h5XG4gKiAgIFwibGFyZ2VyLXNjcmVlbnNcIiAgQURWSVNFUzogdGhlIG1hcCBvcGVucywgd2l0aCBhIGRpc21pc3NpYmxlIG5vdGljZSBhdCBpdHMgdG9wXG4gKiAgIEFCU0VOVCAgICAgICAgICAgIHBob25lLXJlYWR5OiBub3RoaW5nIGlzIHNob3duXG4gKlxuICogQW55IG90aGVyIHZhbHVlIGlzIG5vdCBjb2VyY2VkOiBjaGVjazptb2JpbGUtZ2F0aW5nIGZhaWxzIG9uIGl0LCBieSBwcm9maWxlLCBzbyBhIHR5cG8gY2Fubm90XG4gKiBxdWlldGx5IHR1cm4gYSBkZXNrdG9wLW9ubHkgbWFwIGludG8gYSBwaG9uZS1yZWFkeSBvbmUuXG4gKi9cbmV4cG9ydCBjb25zdCBNT0JJTEUgPSBbJ2Rlc2t0b3Atb25seScsICdsYXJnZXItc2NyZWVucyddXG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkUHJvZmlsZU1ldGEoZGlyLCBwcm9maWxlTmFtZSkge1xuICB0cnkge1xuICAgIGNvbnN0IG1ldGEgPSBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhqb2luKGRpciwgYCR7cHJvZmlsZU5hbWV9Lm1ldGEuanNvbmApLCAndXRmOCcpKVxuICAgIGNvbnN0IGNvcm5lciA9IG1ldGE/LndpZGdldD8uY29ybmVyXG4gICAgLy8gVGhlIHBsdWdpbidzIG93biBkaXNwbGF5IG5hbWUgKGxhYmVsLCBvciB0aXRsZSAvIGRpc3BsYXlOYW1lKTogd2hhdCB0aGUgUGx1Z2luIFN0dWRpbyByYWlsIGNhbGxzIGl0LlxuICAgIGNvbnN0IG5hbWUgPSBbbWV0YT8ubGFiZWwsIG1ldGE/LnRpdGxlLCBtZXRhPy5kaXNwbGF5TmFtZV0uZmluZCgodikgPT4gdHlwZW9mIHYgPT09ICdzdHJpbmcnICYmIHYudHJpbSgpKVxuICAgIHJldHVybiB7XG4gICAgICBzdGFnZTogbWV0YT8uc3RhZ2UgPT09ICdwcm9kdWN0aW9uJyA/ICdwcm9kdWN0aW9uJyA6ICdleHBlcmltZW50YWwnLFxuICAgICAgaGVhdnk6IG1ldGE/LmhlYXZ5ID09PSB0cnVlLFxuICAgICAgd2lkZ2V0OiBDT1JORVJTLmluY2x1ZGVzKGNvcm5lcikgPyB7IGNvcm5lciB9IDogbnVsbCxcbiAgICAgIGxhYmVsOiBuYW1lID8gbmFtZS50cmltKCkgOiAnJyxcbiAgICAgIC8vIFdoZXJlIHRoZSBwbHVnaW4gcnVucyAoXCJ3ZWJcIiwgXCJkZXNrdG9wXCJcdTIwMjYpOyBhYnNlbnQgPSB3ZWIuIEEgZGVza3RvcC1vbmx5IHBsdWdpbiBpcyBuZXZlciBhIGdhbGxlcnkgdGFiLlxuICAgICAgdGFyZ2V0czogQXJyYXkuaXNBcnJheShtZXRhPy50YXJnZXRzKSA/IG1ldGEudGFyZ2V0cy5maWx0ZXIoKHQpID0+IHR5cGVvZiB0ID09PSAnc3RyaW5nJykgOiBudWxsLFxuICAgICAgdmlzaWJpbGl0eTogVklTSUJJTElUWS5pbmNsdWRlcyhtZXRhPy52aXNpYmlsaXR5KSA/IG1ldGEudmlzaWJpbGl0eSA6ICd0ZWFtJyxcbiAgICAgIC8vIFRoZSBkZWNsYXJlZC1idXQtdW5yZWNvZ25pc2VkIHZhbHVlLCBrZXB0IHNvIHRoZSBnZW5lcmF0b3IgY2FuIG5hbWUgaXQgaW4gdGhlIGZhaWx1cmUuXG4gICAgICAvLyBudWxsIHdoZW4gdGhlIGtleSBpcyBhYnNlbnQgKHRoZSBzdXBwb3J0ZWQgd2F5IHRvIHNheSBcInRlYW1cIikgb3IgYWxyZWFkeSB2YWxpZC5cbiAgICAgIHZpc2liaWxpdHlJbnZhbGlkOiBtZXRhPy52aXNpYmlsaXR5ID09PSB1bmRlZmluZWQgfHwgVklTSUJJTElUWS5pbmNsdWRlcyhtZXRhPy52aXNpYmlsaXR5KVxuICAgICAgICA/IG51bGxcbiAgICAgICAgOiBTdHJpbmcobWV0YS52aXNpYmlsaXR5KSxcbiAgICAgIG1vYmlsZTogTU9CSUxFLmluY2x1ZGVzKG1ldGE/Lm1vYmlsZSkgPyBtZXRhLm1vYmlsZSA6IG51bGwsXG4gICAgfVxuICB9IGNhdGNoIHsgcmV0dXJuIHsgc3RhZ2U6ICdleHBlcmltZW50YWwnLCBoZWF2eTogZmFsc2UsIHdpZGdldDogbnVsbCwgbGFiZWw6ICcnLCB0YXJnZXRzOiBudWxsLCB2aXNpYmlsaXR5OiAndGVhbScsIHZpc2liaWxpdHlJbnZhbGlkOiBudWxsLCBtb2JpbGU6IG51bGwgfSB9XG59XG5cbi8qKiBUaGUgb3B0aW9uYWwgbWFuaWZlc3Qga2V5cyBmb3Igb25lIHByb2ZpbGUgKHN0YWdlIGFsd2F5czsgaGVhdnkgLyB3aWRnZXQgb25seSB3aGVuIHNldCkuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvZmlsZU1ldGFGaWVsZHMoZGlyLCBwcm9maWxlTmFtZSkge1xuICBjb25zdCBtID0gcmVhZFByb2ZpbGVNZXRhKGRpciwgcHJvZmlsZU5hbWUpXG4gIC8vIHZpc2liaWxpdHkgaXMgZW1pdHRlZCBPTkxZIHdoZW4gaXQgaXMgXCJwdWJsaWNcIjogYWJzZW50IG1lYW5zIHRlYW0sIHNvIGV2ZXJ5IG1hbmlmZXN0IGluIHRoZVxuICAvLyB0cmVlIHRvZGF5IGtlZXBzIHRoZSBieXRlcyBpdCBoYXMgYW5kIG5vdGhpbmcgYmVjb21lcyB2aXNpYmxlIGJ5IHVwZ3JhZGluZyB0aGUgZ2VuZXJhdG9yLlxuICByZXR1cm4geyBzdGFnZTogbS5zdGFnZSwgLi4uKG0udmlzaWJpbGl0eSA9PT0gJ3B1YmxpYycgPyB7IHZpc2liaWxpdHk6ICdwdWJsaWMnIH0gOiB7fSksIC4uLihtLmxhYmVsID8geyBsYWJlbDogbS5sYWJlbCB9IDoge30pLCAuLi4obS50YXJnZXRzID8geyB0YXJnZXRzOiBtLnRhcmdldHMgfSA6IHt9KSwgLi4uKG0uaGVhdnkgPyB7IGhlYXZ5OiB0cnVlIH0gOiB7fSksIC4uLihtLndpZGdldCA/IHsgd2lkZ2V0OiBtLndpZGdldCB9IDoge30pLCAuLi4obS5tb2JpbGUgPyB7IG1vYmlsZTogbS5tb2JpbGUgfSA6IHt9KSB9XG59XG5cbi8qKiBBIGJ1bmRsZSBpcyBwcm9kdWN0aW9uIGlmIEFOWSBvZiBpdHMgcHJvZmlsZXMgc2F5cyBzby4gKi9cbmV4cG9ydCBjb25zdCBidW5kbGVTdGFnZSA9IChwcm9maWxlcykgPT4gKHByb2ZpbGVzLnNvbWUoKHApID0+IHAuc3RhZ2UgPT09ICdwcm9kdWN0aW9uJykgPyAncHJvZHVjdGlvbicgOiAnZXhwZXJpbWVudGFsJylcblxuLyoqXG4gKiBBIGJ1bmRsZSBpcyBwdWJsaWMgaWYgQU5ZIG9mIGl0cyBwcm9maWxlcyBpcyBcdTIwMTQgYmVjYXVzZSBhIGJ1bmRsZSBpcyBPTkUgSUlGRS4gVGhlIHByb2ZpbGVzIGluIGl0XG4gKiBzaGFyZSBhIHNpbmdsZSAuanMsIHNvIHB1Ymxpc2hpbmcgb25lIHByb2ZpbGUgcHVibGlzaGVzIHRoZSBmaWxlIHRoZSBvdGhlcnMgYXJlIGNvbXBpbGVkIGludG87XG4gKiB0aGVyZSBpcyBubyBzaGFwZSBvZiB0aGlzIGZpZWxkIHRoYXQgbWFrZXMgaGFsZiBhIHNjcmlwdCBmZXRjaGFibGUuIFRoZSBwZXItcHJvZmlsZSBrZXkgaXMgc3RpbGxcbiAqIGVtaXR0ZWQsIHNvIGEgcmVhZGVyIGNhbiBsaXN0IG9ubHkgdGhlIHByb2ZpbGVzIHRoYXQgb3B0ZWQgaW4gd2hpbGUgbG9hZGluZyB0aGUgb25lIGJ1bmRsZS5cbiAqL1xuZXhwb3J0IGNvbnN0IGJ1bmRsZVZpc2liaWxpdHkgPSAocHJvZmlsZXMpID0+IChwcm9maWxlcy5zb21lKChwKSA9PiBwLnZpc2liaWxpdHkgPT09ICdwdWJsaWMnKSA/ICdwdWJsaWMnIDogJ3RlYW0nKVxuIiwgImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCIvaG9tZS9sazEweC9Xb3Jrc3BhY2UvZWNvLWR4L3Jvb3QtZG94YS1tYXBzL3d0LWhmL2ludGVybmFsXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCIvaG9tZS9sazEweC9Xb3Jrc3BhY2UvZWNvLWR4L3Jvb3QtZG94YS1tYXBzL3d0LWhmL2ludGVybmFsL3ZpdGUtcGx1Z2luLXN0cmlwLXNoYWRvdy1jc3MtY29tbWVudHMubWpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9ob21lL2xrMTB4L1dvcmtzcGFjZS9lY28tZHgvcm9vdC1kb3hhLW1hcHMvd3QtaGYvaW50ZXJuYWwvdml0ZS1wbHVnaW4tc3RyaXAtc2hhZG93LWNzcy1jb21tZW50cy5tanNcIjsvLyB2aXRlLXBsdWdpbi1zdHJpcC1zaGFkb3ctY3NzLWNvbW1lbnRzIFx1MjAxNCBwcm9kdWN0aW9uIGJ1bmRsZXMgY2Fycnkgb25seSBDU1MgcnVsZXMuXG4vL1xuLy8gRXZlcnkgY29tcG9uZW50IGluamVjdHMgaXRzIHNoYWRvdy1ET00gc3R5bGVzIGZyb20gYSB0ZW1wbGF0ZSBsaXRlcmFsIHBhc3NlZCB0b1xuLy8gdXNlU2hhZG93U3R5bGVzKGBcdTIwMjZgKS4gVGhvc2UgbGl0ZXJhbHMgc2hpcCB2ZXJiYXRpbSBpbnNpZGUgdGhlIGJ1aWx0IElJRkUsIHNvIGFueVxuLy8gQ1NTIGJsb2NrIGNvbW1lbnQgd3JpdHRlbiBpbiB0aGVtIHdvdWxkIHJlYWNoIHRoZSBwdWJsaWMgZHJvcC1pbiBhcyBkZWFkIHdlaWdodC5cbi8vIFRoaXMgYnVpbGQtb25seSBwbHVnaW4gcmV3cml0ZXMgdGhlIHNvdXJjZSBvZiBldmVyeSAudnVlIGFuZCAuanMgZmlsZSB1bmRlclxuLy8gbGlicmFyeS8gYW5kIHBsdWdpbi1kZXNpZ25zLyBiZWZvcmUgdGhlIFZ1ZSBjb21waWxlciBzZWVzIGl0IChlbmZvcmNlOiAncHJlJyk6XG4vLyBpbnNpZGUgZWFjaCBzdWNoIGxpdGVyYWwgaXQgcmVtb3ZlcyB0aGUgYmxvY2sgY29tbWVudHMgYW5kIGNvbGxhcHNlcyB0aGUgYmxhbmtcbi8vIGxpbmVzIHRoZXkgbGVhdmUgYmVoaW5kLiBOb3RoaW5nIG91dHNpZGUgdGhlIGxpdGVyYWwgY2hhbmdlcywgYW5kIGRldiBtb2RlIGlzXG4vLyB1bnRvdWNoZWQgc28gdGhlIGNvbW1lbnRzIHN0YXkgcmVhZGFibGUgd2hpbGUgd29ya2luZy5cbi8vXG4vLyBBIGxpdGVyYWwgaXMgbGVmdCBleGFjdGx5IGFzIHdyaXR0ZW4gKHdpdGggYSBidWlsZCB3YXJuaW5nKSB3aGVuIGl0IGNhbm5vdCBiZVxuLy8gcmV3cml0dGVuIHNhZmVseTogaXQgY29udGFpbnMgYSBgJHtcdTIwMjZ9YCBzdWJzdGl0dXRpb24sIG9yIGEgY29tbWVudCwgc3RyaW5nIG9yXG4vLyB1cmwoKSBpbnNpZGUgaXQgbmV2ZXIgY2xvc2VzLiBDb21tZW50IG1hcmtlcnMgdGhhdCBzaXQgaW5zaWRlIGEgQ1NTIHN0cmluZ1xuLy8gKGBjb250ZW50OlwiKi9cImApIG9yIGFuIHVucXVvdGVkIHVybCgpIGFyZSBzdHJpbmcgY29udGVudCBhbmQgYXJlIHByZXNlcnZlZC5cbmltcG9ydCB7IHJlc29sdmUsIGRpcm5hbWUsIHNlcCB9IGZyb20gJ25vZGU6cGF0aCdcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tICdub2RlOnVybCdcblxuY29uc3QgUk9PVCA9IHJlc29sdmUoZGlybmFtZShmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnVybCkpLCAnLi4nKVxuY29uc3QgU09VUkNFX1JPT1RTID0gWydsaWJyYXJ5JywgJ3BsdWdpbi1kZXNpZ25zJ10ubWFwKGQgPT4gcmVzb2x2ZShST09ULCBkKSArIHNlcClcbmNvbnN0IFRBRyA9ICdbc3RyaXAtc2hhZG93LWNzcy1jb21tZW50c10nXG5cbi8vIFRoZSBsaXRlcmFscyB0aGF0IHNoaXAgYXMgQ1NTLCBpbiB0aGUgdGhyZWUgc2hhcGVzIHRoaXMgdHJlZSB3cml0ZXMgdGhlbTpcbi8vICAgdXNlU2hhZG93U3R5bGVzKGBcdTIwMjZgKSAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlIGxpdGVyYWwgcGFzc2VkIGRpcmVjdGx5O1xuLy8gICB1c2VTaGFkb3dTdHlsZXMoUEFORV9HUklEX1NUWUxFUyArIGBcdTIwMjZgKSAgICAgICBhIGxpdGVyYWwgYXBwZW5kZWQgdG8gc2hhcmVkIHN0eWxlcztcbi8vICAgY29uc3QgUFNfU0hBRE9XX0NTUyA9IGBcdTIwMjZgIC8gZXhwb3J0IGNvbnN0IFBBTkVfR1JJRF9TVFlMRVMgPSBgXHUyMDI2YCAgIGEgbmFtZWQgbGl0ZXJhbCBwYXNzZWQgbGF0ZXIuXG4vLyBPbmx5IHRoZSBmaXJzdCBzaGFwZSB3YXMgbWF0Y2hlZCB1bnRpbCAyMDI2LTA5LTI4LCBhbmQgcmVnaW9ucyBmb3VuZCB0aHJlZSBwbHVnaW5zJyBjb21tZW50cyBzaGlwcGluZ1xuLy8gZnJvbSB0aGUgb3RoZXIgdHdvIChjaGVjazpwdWJsaWMtaHlnaWVuZSkgXHUyMDE0IHRoZSBzYW1lIG1pc3Rha2Ugd3JpdHRlbiBpbmRlcGVuZGVudGx5LCBpLmUuIGEgdHJhcC5cbmNvbnN0IENBTEwgPSAvXFxidXNlU2hhZG93U3R5bGVzXFwoXFxzKig/OltBLVphLXpfJF1bXFx3JF0qXFxzKlxcK1xccyopKmB8XFxiKD86ZXhwb3J0XFxzKyk/Y29uc3RcXHMrW0EtWl1bQS1aMC05X10qKD86X0NTU3xfU1RZTEVTKVxccyo9XFxzKmAvZ1xuXG4vKipcbiAqIEZpbmQgdGhlIGVuZCBvZiBhIHRlbXBsYXRlIGxpdGVyYWwgd2hvc2Ugb3BlbmluZyBiYWNrdGljayBpcyBqdXN0IGJlZm9yZSBgZnJvbWAuXG4gKiBSZXR1cm5zIHsgZW5kIH0gPSBpbmRleCBvZiB0aGUgY2xvc2luZyBiYWNrdGljaywgb3IgeyByZWFzb24gfSB3aGVuIHRoZSBsaXRlcmFsXG4gKiBjb250YWlucyBhIHN1YnN0aXR1dGlvbiBvciBuZXZlciBjbG9zZXMuXG4gKi9cbmZ1bmN0aW9uIGZpbmRUZW1wbGF0ZUVuZChjb2RlLCBmcm9tKSB7XG4gIGZvciAobGV0IGkgPSBmcm9tOyBpIDwgY29kZS5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGMgPSBjb2RlW2ldXG4gICAgaWYgKGMgPT09ICdcXFxcJykgeyBpKys7IGNvbnRpbnVlIH1cbiAgICBpZiAoYyA9PT0gJ2AnKSByZXR1cm4geyBlbmQ6IGkgfVxuICAgIGlmIChjID09PSAnJCcgJiYgY29kZVtpICsgMV0gPT09ICd7JykgcmV0dXJuIHsgcmVhc29uOiAnY29udGFpbnMgYSAke1x1MjAyNn0gc3Vic3RpdHV0aW9uJywgYXQ6IGkgfVxuICB9XG4gIHJldHVybiB7IHJlYXNvbjogJ3RlbXBsYXRlIGxpdGVyYWwgbmV2ZXIgY2xvc2VzJywgYXQ6IGNvZGUubGVuZ3RoIH1cbn1cblxuLyoqXG4gKiBSZW1vdmUgQ1NTIGJsb2NrIGNvbW1lbnRzIGZyb20gb25lIGxpdGVyYWwncyB0ZXh0LiBTdHJpbmdzICgnXHUyMDI2JyAvIFwiXHUyMDI2XCIpIGFuZFxuICogdW5xdW90ZWQgdXJsKFx1MjAyNikgYXJlIGNvcGllZCB0aHJvdWdoIHVudG91Y2hlZCBzbyBhIGNvbW1lbnQgbWFya2VyIGluc2lkZSB0aGVtXG4gKiBpcyBuZXZlciBtaXN0YWtlbiBmb3IgYSBjb21tZW50LiBSZXR1cm5zIHsgY3NzLCBjb21tZW50cyB9IG9yIHsgcmVhc29uIH0uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdHJpcENzc0NvbW1lbnRzKGNzcykge1xuICBjb25zdCBuID0gY3NzLmxlbmd0aFxuICBsZXQgb3V0ID0gJydcbiAgbGV0IGNvbW1lbnRzID0gMFxuICBsZXQgaSA9IDBcbiAgd2hpbGUgKGkgPCBuKSB7XG4gICAgY29uc3QgYyA9IGNzc1tpXVxuICAgIGlmIChjID09PSAnXCInIHx8IGMgPT09IFwiJ1wiKSB7XG4gICAgICBsZXQgaiA9IGkgKyAxXG4gICAgICB3aGlsZSAoaiA8IG4gJiYgY3NzW2pdICE9PSBjICYmIGNzc1tqXSAhPT0gJ1xcbicpIHsgaWYgKGNzc1tqXSA9PT0gJ1xcXFwnKSBqKys7IGorKyB9XG4gICAgICBpZiAoaiA+PSBuKSByZXR1cm4geyByZWFzb246ICdhIENTUyBzdHJpbmcgbmV2ZXIgY2xvc2VzJyB9XG4gICAgICBpZiAoY3NzW2pdID09PSAnXFxuJykgeyBvdXQgKz0gY3NzLnNsaWNlKGksIGopOyBpID0gajsgY29udGludWUgfSAgIC8vIHN0cmF5IHF1b3RlOiBvbmx5IGl0cyBvd24gbGluZSBpcyB0cmVhdGVkIGFzIGEgc3RyaW5nXG4gICAgICBvdXQgKz0gY3NzLnNsaWNlKGksIGogKyAxKTsgaSA9IGogKyAxOyBjb250aW51ZVxuICAgIH1cbiAgICBpZiAoYyA9PT0gJy8nICYmIGNzc1tpICsgMV0gPT09ICcqJykge1xuICAgICAgY29uc3QgaiA9IGNzcy5pbmRleE9mKCcqLycsIGkgKyAyKVxuICAgICAgaWYgKGogPCAwKSByZXR1cm4geyByZWFzb246ICdhIENTUyBjb21tZW50IG5ldmVyIGNsb3NlcycgfVxuICAgICAgY29tbWVudHMrKzsgaSA9IGogKyAyOyBjb250aW51ZVxuICAgIH1cbiAgICBpZiAoKGMgPT09ICd1JyB8fCBjID09PSAnVScpICYmIC9edXJsXFwoL2kudGVzdChjc3Muc2xpY2UoaSwgaSArIDQpKSAmJiAoaSA9PT0gMCB8fCAhL1tcXHctXS8udGVzdChjc3NbaSAtIDFdKSkpIHtcbiAgICAgIGxldCBqID0gaSArIDRcbiAgICAgIHdoaWxlIChqIDwgbiAmJiAoY3NzW2pdID09PSAnICcgfHwgY3NzW2pdID09PSAnXFx0JykpIGorK1xuICAgICAgaWYgKGNzc1tqXSA9PT0gJ1wiJyB8fCBjc3Nbal0gPT09IFwiJ1wiKSB7IG91dCArPSBjc3Muc2xpY2UoaSwgaik7IGkgPSBqOyBjb250aW51ZSB9ICAgLy8gcXVvdGVkIHVybDogdGhlIHN0cmluZyBicmFuY2ggb3ducyBpdFxuICAgICAgY29uc3QgayA9IGNzcy5pbmRleE9mKCcpJywgailcbiAgICAgIGlmIChrIDwgMCkgcmV0dXJuIHsgcmVhc29uOiAnYW4gdW5xdW90ZWQgdXJsKCkgbmV2ZXIgY2xvc2VzJyB9XG4gICAgICBvdXQgKz0gY3NzLnNsaWNlKGksIGsgKyAxKTsgaSA9IGsgKyAxOyBjb250aW51ZVxuICAgIH1cbiAgICBvdXQgKz0gYzsgaSsrXG4gIH1cbiAgaWYgKGNvbW1lbnRzID4gMCkge1xuICAgIG91dCA9IG91dC5yZXBsYWNlKC9bIFxcdF0rKD89XFxyP1xcbnwkKS9nLCAnJykgICAgICAgLy8gd2hpdGVzcGFjZSBsZWZ0IGJlaGluZCBhdCB0aGUgZW5kIG9mIGEgbGluZVxuICAgIG91dCA9IG91dC5yZXBsYWNlKC9cXHI/XFxuKD86WyBcXHRdKlxccj9cXG4pKy9nLCAnXFxuJykgLy8gcnVucyBvZiBibGFuayBsaW5lc1xuICB9XG4gIHJldHVybiB7IGNzczogb3V0LCBjb21tZW50cyB9XG59XG5cbi8qKlxuICogUmV3cml0ZSBldmVyeSB1c2VTaGFkb3dTdHlsZXMoYFx1MjAyNmApIGxpdGVyYWwgaW4gYSBtb2R1bGUncyBzb3VyY2UuXG4gKiBSZXR1cm5zIHsgY29kZSwgY2hhbmdlZCwgbGl0ZXJhbHMsIGNvbW1lbnRzLCBieXRlcywgc2tpcHBlZDogW3sgbGluZSwgcmVhc29uIH1dIH0uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdHJpcFNoYWRvd1N0eWxlQ29tbWVudHMoY29kZSkge1xuICBjb25zdCByZXN1bHQgPSB7IGNvZGUsIGNoYW5nZWQ6IGZhbHNlLCBsaXRlcmFsczogMCwgY29tbWVudHM6IDAsIGJ5dGVzOiAwLCBza2lwcGVkOiBbXSB9XG4gIGxldCBvdXQgPSAnJ1xuICBsZXQgbGFzdCA9IDBcbiAgQ0FMTC5sYXN0SW5kZXggPSAwXG4gIGxldCBtXG4gIHdoaWxlICgobSA9IENBTEwuZXhlYyhjb2RlKSkpIHtcbiAgICBjb25zdCBvcGVuID0gbS5pbmRleCArIG1bMF0ubGVuZ3RoXG4gICAgY29uc3QgbGl0ID0gZmluZFRlbXBsYXRlRW5kKGNvZGUsIG9wZW4pXG4gICAgaWYgKGxpdC5yZWFzb24pIHtcbiAgICAgIHJlc3VsdC5za2lwcGVkLnB1c2goeyBsaW5lOiBsaW5lT2YoY29kZSwgbS5pbmRleCksIHJlYXNvbjogbGl0LnJlYXNvbiB9KVxuICAgICAgQ0FMTC5sYXN0SW5kZXggPSBsaXQuYXRcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIHJlc3VsdC5saXRlcmFscysrXG4gICAgY29uc3Qgb3JpZ2luYWwgPSBjb2RlLnNsaWNlKG9wZW4sIGxpdC5lbmQpXG4gICAgY29uc3Qgc3RyaXBwZWQgPSBzdHJpcENzc0NvbW1lbnRzKG9yaWdpbmFsKVxuICAgIGlmIChzdHJpcHBlZC5yZWFzb24pIHtcbiAgICAgIHJlc3VsdC5za2lwcGVkLnB1c2goeyBsaW5lOiBsaW5lT2YoY29kZSwgbS5pbmRleCksIHJlYXNvbjogc3RyaXBwZWQucmVhc29uIH0pXG4gICAgfSBlbHNlIGlmIChzdHJpcHBlZC5jc3MgIT09IG9yaWdpbmFsKSB7XG4gICAgICBvdXQgKz0gY29kZS5zbGljZShsYXN0LCBvcGVuKSArIHN0cmlwcGVkLmNzc1xuICAgICAgbGFzdCA9IGxpdC5lbmRcbiAgICAgIHJlc3VsdC5jb21tZW50cyArPSBzdHJpcHBlZC5jb21tZW50c1xuICAgICAgcmVzdWx0LmJ5dGVzICs9IG9yaWdpbmFsLmxlbmd0aCAtIHN0cmlwcGVkLmNzcy5sZW5ndGhcbiAgICAgIHJlc3VsdC5jaGFuZ2VkID0gdHJ1ZVxuICAgIH1cbiAgICBDQUxMLmxhc3RJbmRleCA9IGxpdC5lbmQgKyAxXG4gIH1cbiAgaWYgKHJlc3VsdC5jaGFuZ2VkKSByZXN1bHQuY29kZSA9IG91dCArIGNvZGUuc2xpY2UobGFzdClcbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5mdW5jdGlvbiBsaW5lT2YoY29kZSwgaW5kZXgpIHtcbiAgbGV0IGxpbmUgPSAxXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgaW5kZXg7IGkrKykgaWYgKGNvZGVbaV0gPT09ICdcXG4nKSBsaW5lKytcbiAgcmV0dXJuIGxpbmVcbn1cblxuZnVuY3Rpb24gaXNTb3VyY2VNb2R1bGUoaWQpIHtcbiAgY29uc3QgcSA9IGlkLmluZGV4T2YoJz8nKVxuICBpZiAocSA+PSAwKSByZXR1cm4gZmFsc2UgICAgICAgICAgICAgICAgICAgICAvLyBWdWUgc3ViLXJlcXVlc3RzICg/dnVlJnR5cGU9XHUyMDI2KSByZWFkIHRoZSBhbHJlYWR5LXJld3JpdHRlbiBkZXNjcmlwdG9yXG4gIGlmICghKGlkLmVuZHNXaXRoKCcudnVlJykgfHwgaWQuZW5kc1dpdGgoJy5qcycpKSkgcmV0dXJuIGZhbHNlXG4gIHJldHVybiBTT1VSQ0VfUk9PVFMuc29tZShyb290ID0+IGlkLnN0YXJ0c1dpdGgocm9vdCkpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdHJpcFNoYWRvd0Nzc0NvbW1lbnRzUGx1Z2luKCkge1xuICBsZXQgbG9nZ2VyID0gY29uc29sZVxuICBjb25zdCB0b3RhbHMgPSB7IGZpbGVzOiAwLCBsaXRlcmFsczogMCwgY29tbWVudHM6IDAsIGJ5dGVzOiAwLCBza2lwcGVkOiAwIH1cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnZG94YTpzdHJpcC1zaGFkb3ctY3NzLWNvbW1lbnRzJyxcbiAgICBhcHBseTogJ2J1aWxkJyxcbiAgICBlbmZvcmNlOiAncHJlJyxcbiAgICBjb25maWdSZXNvbHZlZChjb25maWcpIHsgbG9nZ2VyID0gY29uZmlnLmxvZ2dlciB9LFxuICAgIHRyYW5zZm9ybShjb2RlLCBpZCkge1xuICAgICAgaWYgKCFpc1NvdXJjZU1vZHVsZShpZCkpIHJldHVybiBudWxsXG4gICAgICBjb25zdCByID0gc3RyaXBTaGFkb3dTdHlsZUNvbW1lbnRzKGNvZGUpXG4gICAgICBmb3IgKGNvbnN0IHMgb2Ygci5za2lwcGVkKSB7XG4gICAgICAgIHRvdGFscy5za2lwcGVkKytcbiAgICAgICAgbG9nZ2VyLndhcm4oYCR7VEFHfSBsZWZ0IHVudG91Y2hlZCAke2lkLnNsaWNlKFJPT1QubGVuZ3RoICsgMSl9OiR7cy5saW5lfSBcdTIwMTQgJHtzLnJlYXNvbn1gKVxuICAgICAgfVxuICAgICAgaWYgKCFyLmNoYW5nZWQpIHJldHVybiBudWxsXG4gICAgICB0b3RhbHMuZmlsZXMrKzsgdG90YWxzLmxpdGVyYWxzICs9IHIubGl0ZXJhbHM7IHRvdGFscy5jb21tZW50cyArPSByLmNvbW1lbnRzOyB0b3RhbHMuYnl0ZXMgKz0gci5ieXRlc1xuICAgICAgcmV0dXJuIHsgY29kZTogci5jb2RlLCBtYXA6IG51bGwgfVxuICAgIH0sXG4gICAgYnVpbGRFbmQoKSB7XG4gICAgICBsb2dnZXIuaW5mbyhgJHtUQUd9IHJlbW92ZWQgJHt0b3RhbHMuY29tbWVudHN9IENTUyBjb21tZW50cyAoJHt0b3RhbHMuYnl0ZXN9IGJ5dGVzKSBmcm9tICR7dG90YWxzLmxpdGVyYWxzfSBzaGFkb3ctc3R5bGUgbGl0ZXJhbHMgaW4gJHt0b3RhbHMuZmlsZXN9IGZpbGVzYCArXG4gICAgICAgICh0b3RhbHMuc2tpcHBlZCA/IGA7ICR7dG90YWxzLnNraXBwZWR9IGxpdGVyYWwocykgbGVmdCB1bnRvdWNoZWRgIDogJycpKVxuICAgIH0sXG4gIH1cbn1cbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL2hvbWUvbGsxMHgvV29ya3NwYWNlL2Vjby1keC9yb290LWRveGEtbWFwcy93dC1oZi9pbnRlcm5hbFwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL2hvbWUvbGsxMHgvV29ya3NwYWNlL2Vjby1keC9yb290LWRveGEtbWFwcy93dC1oZi9pbnRlcm5hbC9iYWNrZW5kLWRldi1wbHVnaW4ubWpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9ob21lL2xrMTB4L1dvcmtzcGFjZS9lY28tZHgvcm9vdC1kb3hhLW1hcHMvd3QtaGYvaW50ZXJuYWwvYmFja2VuZC1kZXYtcGx1Z2luLm1qc1wiOy8qKlxuICogaW50ZXJuYWwvYmFja2VuZC1kZXYtcGx1Z2luLm1qcyBcdTIwMTQgYGJ1biBydW4gZGV2YCBzdGFydHMgdGhlIGxvY2FsIHBsdWdpbiBiYWNrZW5kcy5cbiAqXG4gKiBXSFk6IHNvbWUgcGx1Z2lucyBzaGlwIHRvIERFU0tUT1Agd2l0aCBhIGxvY2FsIGJhY2tlbmQgKHJ1ZGRlci12b2ljZSBcdTIxOTIgYmFja2VuZC9iaW4vcnVkZGVyLWVuZ2luZSxcbiAqIHJ1biBhcyBhIFRhdXJpIHNpZGVjYXIpLiBJbiB0aGUgUGx1Z2luIFN0dWRpbyB0aGUgc2FtZSBiYWNrZW5kIG11c3QgYmUgcnVubmluZywgb3IgdGhlIHBsdWdpbiBjYW4ndFxuICogYmUgdGVzdGVkIGluIHRoZSBicm93c2VyLiBUaGlzIHBsdWdpbiBzdGFydHMgZWFjaCBidWlsdCBiYWNrZW5kIHdpdGggdGhlIGRldiBzZXJ2ZXIsIGZvcndhcmRzIGl0c1xuICogL2FwaS88bmFtZT4vIHJvdXRlcywgYW5kIHN0b3BzIGl0IHdoZW4gdGhlIGRldiBzZXJ2ZXIgc3RvcHMuIEEgYmFja2VuZCB0aGF0IGlzbid0IGJ1aWx0IGlzIHNraXBwZWRcbiAqIHdpdGggYSBoaW50OiBwbHVnaW5zIHdpdGhvdXQgYSBiYWNrZW5kIG5ldmVyIG5vdGljZSB0aGlzIGZpbGUuXG4gKlxuICogXHUyNjA1IE9ORSBCQUNLRU5EIFBFUiBgYnVuIHJ1biBkZXZgLCBTVVJWSVZJTkcgVklURSBSRVNUQVJUUy4gVml0ZSByZXN0YXJ0cyBpdHNlbGYgd2hlbmV2ZXIgdml0ZS5jb25maWcuanNcbiAqIG9yIGFueXRoaW5nIGl0IGltcG9ydHMgY2hhbmdlcywgYW5kIHJlLXJ1bnMgY29uZmlndXJlU2VydmVyLiBTdG9wcGluZyB0aGUgYmFja2VuZCBvbiBldmVyeSByZXN0YXJ0IGFuZFxuICogc3RhcnRpbmcgYSBuZXcgb25lIGF0IG9uY2UgcmFjZWQgdGhlIG9sZCBwcm9jZXNzIGZvciBpdHMgcG9ydDogdGhlIG5ldyBvbmUgZGllZCB3aXRoIFwiYWRkcmVzcyBhbHJlYWR5XG4gKiBpbiB1c2VcIiBhbmQgUnVkZGVyIHNob3dlZCBcImVuZ2luZSBvZmZsaW5lXCIgdW50aWwgYGJ1biBydW4gZGV2YCB3YXMgcmVzdGFydGVkIGJ5IGhhbmQgKG1lYXN1cmVkXG4gKiAyMDI2LTA5LTI3LCB0d2ljZSBpbiBvbmUgc2Vzc2lvbikuIEVhY2ggYmFja2VuZCBub3cgbGl2ZXMgaW4gYSBwcm9jZXNzLXdpZGUgcmVnaXN0cnkgKGdsb2JhbFRoaXMgXHUyMDE0IHRoZVxuICogY29uZmlnIG1vZHVsZSBpdHNlbGYgaXMgcmUtaW1wb3J0ZWQgb24gYSByZXN0YXJ0KTogYSByZXN0YXJ0IFJFVVNFUyB0aGUgcnVubmluZyBiYWNrZW5kLCBpdCBpcyBzdG9wcGVkXG4gKiBvbmx5IHdoZW4gdGhlIGRldiBwcm9jZXNzIGV4aXRzLCBhbmQgaXQgaXMgcmVzdGFydGVkICh1cCB0byA1IHRpbWVzKSBpZiBpdCBjcmFzaGVzLlxuICpcbiAqIERFViBPTkxZIChgYXBwbHk6ICdzZXJ2ZSdgKS4gQSBwcm9kdWN0aW9uIGJ1aWxkIG5ldmVyIHN0YXJ0cyBvciBidW5kbGVzIGEgYmFja2VuZC5cbiAqL1xuaW1wb3J0IHsgc3Bhd24gfSBmcm9tICdub2RlOmNoaWxkX3Byb2Nlc3MnXG5pbXBvcnQgeyBleGlzdHNTeW5jLCBta2RpclN5bmMsIHdyaXRlRmlsZVN5bmMsIHJtU3luYywgY2htb2RTeW5jLCByZW5hbWVTeW5jLCBjcmVhdGVXcml0ZVN0cmVhbSB9IGZyb20gJ25vZGU6ZnMnXG5pbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSAnbm9kZTpjcnlwdG8nXG5pbXBvcnQgeyBjb25uZWN0IH0gZnJvbSAnbm9kZTpuZXQnXG5pbXBvcnQgeyBpbmZsYXRlUmF3U3luYyB9IGZyb20gJ25vZGU6emxpYidcbmltcG9ydCB7IHJlc29sdmUgfSBmcm9tICdub2RlOnBhdGgnXG5cbi8vIFBvY2tldEJhc2UsIHRoZSBiYWNrZW5kIGZvciBwbHVnaW5zIHRoYXQgbmVlZCBvbmU6IHRoZSBTQU1FIHBpbm5lZCB2ZXJzaW9uIGFzIHRoZSBjbG91ZCBjb250YWluZXJcbi8vICh0aGUgcmVwby1yb290IERvY2tlcmZpbGUpLCBTSEEtMjU2IGZyb20gdGhlIHJlbGVhc2UncyBjaGVja3N1bXMudHh0LiBEb3dubG9hZGVkIG9uIHRoZSBmaXJzdFxuLy8gYGJ1biBydW4gZGV2YCBpbnRvIGJhY2tlbmQvYmluIChnaXRpZ25vcmVkKTsgaXRzIGRhdGEgbGl2ZXMgaW4gLnBiL2RldiAoZ2l0aWdub3JlZCkuXG5jb25zdCBQQl9WRVJTSU9OID0gJzAuNDAuNCdcbmNvbnN0IFBCX1NIQTI1NiA9IHtcbiAgbGludXhfYW1kNjQ6ICc5MDQyZWM4MTg1NzBlNzljMzYyOGRhZGNkMGE3NTZjMTQ5NmQ5ZTExNzM5MThlYzQwOWQxMzNjMDJmODJlNWZhJyxcbiAgbGludXhfYXJtNjQ6ICc4NjA5NWJmOGVkOTM0NTk1NGYwZDJiZjBhNWZiOWI1NzU4NGFlNjBiNzdlYmYzYjZjZDIzYTgwMDNhM2ZkNDE4JyxcbiAgZGFyd2luX2FtZDY0OiAnMDUyOTA2NTIxZjA5ZjZmMjM0MDVjZDgwNGM5MzBkMmI3YTFmOGVlZTA2ZDM5Yjg1NzIzYjUwNTRiMmFjYjRlNCcsXG4gIGRhcndpbl9hcm02NDogJ2VlYjYxOWVhNGY4YTA2NDIxZGFlZGI5NDZkMTMzYmVkMjY5ZmVhMzM0YTc2MDk0MWQxNDdmNzZiZWZjMjVlYmMnLFxufVxuXG4vLyBuYW1lIFx1MjE5MiBob3cgdG8gcnVuIGl0LiBgcm91dGVgIGlzIHByb3hpZWQgdG8gYHBvcnRgIG9uIDEyNy4wLjAuMSwgb3IgdG8gYHJlbW90ZWAgd2hlbiB0aGF0IGlzIHNldC5cbi8vIGBlbnZgIGlzIHZpdGUncyBsb2FkRW52IChzbyAuZW52LmxvY2FsIGNvdW50cyksIGZhbGxpbmcgYmFjayB0byBwcm9jZXNzLmVudi5cbmV4cG9ydCBmdW5jdGlvbiBkZXZCYWNrZW5kcyhlbnYgPSBwcm9jZXNzLmVudikge1xuICBjb25zdCBwYlBvcnQgPSBOdW1iZXIoZW52LkRYX1BCX1BPUlQgfHwgODA5MClcbiAgcmV0dXJuIFtcbiAge1xuICAgIG5hbWU6ICdydWRkZXItZW5naW5lJyxcbiAgICBiaW46ICdiYWNrZW5kL2Jpbi9ydWRkZXItZW5naW5lJyxcbiAgICBidWlsZDogJ2NkIGJhY2tlbmQvcnVkZGVyLWVuZ2luZSAmJiBnbyBidWlsZCAtbyAuLi9iaW4vcnVkZGVyLWVuZ2luZSAuJyxcbiAgICAvLyBXaGF0IGEgZnJlc2ggY2xvbmUgaXMgdG9sZCBhdCBzdGFydHVwIHdoZW4gdGhpcyBiYWNrZW5kIGlzIG5vdCBidWlsdDogaXQgaXMgT1BUSU9OQUwgKGRlc2t0b3Agdm9pY2UpLlxuICAgIG9wdGlvbmFsOiAnb3B0aW9uYWw6IFJ1ZGRlciAoZGVza3RvcCB2b2ljZS10by10ZXh0KSBpcyBub3QgYnVpbHQsIHdoaWNoIGlzIGZpbmUgZm9yIHRoZSBtYXBzLiBJdCBuZWVkcyBHbyAxLjIyKzsgc2VlIGRvY3VtZW50YXRpb24vSE9XVE8tYnVpbGQtdGhlLWRlc2t0b3AtYXBwLm1kLicsXG4gICAgcm91dGU6ICcvYXBpL3J1ZGRlcicsXG4gICAgcG9ydDogTnVtYmVyKHByb2Nlc3MuZW52LlJVRERFUl9QT1JUIHx8IDUxOTMpLFxuICAgIGVudjogeyBSVURERVJfUE9SVDogU3RyaW5nKHByb2Nlc3MuZW52LlJVRERFUl9QT1JUIHx8IDUxOTMpLCBSVURERVJfTkVNT19QT1JUOiBTdHJpbmcocHJvY2Vzcy5lbnYuUlVEREVSX05FTU9fUE9SVCB8fCA1MTk0KSB9LFxuICAgIC8vIFRoaXMgc2VydmVyIGlzIFNVUFBPU0VEIHRvIHJ1biB0aGUgZW5naW5lIChhIHNlcnZlciBkZXBsb3ltZW50IHdpdGggdGhlIGVuZ2luZSBzd2l0Y2hlZCBvbik6IHdoaWxlIGl0XG4gICAgLy8gaXMgZG93biwgdGhlIHBsdWdpbiBzYXlzIFwibm90IHJ1bm5pbmcgeWV0XCIgaW5zdGVhZCBvZiBcInJ1bnMgb24geW91ciBvd24gY29tcHV0ZXJcIi5cbiAgICBleHBlY3RlZDogKCkgPT4gcHJvY2Vzcy5lbnYuUlVEREVSX0VOR0lORSA9PT0gJzEnIHx8IHByb2Nlc3MuZW52LlJVRERFUl9BVURJTyA9PT0gJ2Jyb3dzZXInLFxuICAgIC8vIFJVRERFUl9FTkdJTkU9MCAoYSBzZXJ2ZXIgd2hlcmUgUnVkZGVyIGlzIGxhcHRvcC1vbmx5LCAyMDI2LTA5LTI3KTogbmV2ZXIgc3RhcnQgaXQsIGV2ZW4gaWYgYVxuICAgIC8vIGJpbmFyeSBidWlsdCBieSBhbiBlYXJsaWVyIGVuZ2luZS1vbiBkZXBsb3kgaXMgc3RpbGwgdGhlcmUgXHUyMDE0IGl0IHdvdWxkIG9mZmVyIHRvIHJlY29yZCBhIHNlcnZlcidzIG1pYy5cbiAgICBkaXNhYmxlZDogKCkgPT4gcHJvY2Vzcy5lbnYuUlVEREVSX0VOR0lORSA9PT0gJzAnLFxuICB9LFxuICB7XG4gICAgLy8gSG9va3Mgb2ZmIChhIGhvb2tzIGRpciB0aGF0IG5ldmVyIGV4aXN0cyk6IG9ubHkgdGhlIG1pZ3JhdGlvbnMgaW4gZ2l0IHNoYXBlIHRoZSBzY2hlbWEsIGFzIGluIHRoZSBjbG91ZC5cbiAgICAvLyBEWF9QQl9VUkwgcG9pbnRzIHRoaXMgbGFwdG9wIGF0IGEgc2hhcmVkIFBvY2tldEJhc2UgaW5zdGVhZCAoZS5nLiB0aGUgY2xvdWQgcGItZGV2KTsgbm9uZSBzdGFydHMgaGVyZS5cbiAgICBuYW1lOiAncG9ja2V0YmFzZScsXG4gICAgYmluOiAnYmFja2VuZC9iaW4vcG9ja2V0YmFzZScsXG4gICAgYXJnczogWydzZXJ2ZScsICctLWh0dHAnLCBgMTI3LjAuMC4xOiR7cGJQb3J0fWAsICctLWRpcicsICcucGIvZGV2JywgJy0tbWlncmF0aW9uc0RpcicsICdiYWNrZW5kL3BvY2tldGJhc2UvcGJfbWlncmF0aW9ucycsICctLWhvb2tzRGlyJywgJy5wYi9ob29rcy1vZmYnXSxcbiAgICBidWlsZDogJ2l0IGRvd25sb2FkcyBvbiB0aGUgbmV4dCBgYnVuIHJ1biBkZXZgIChvciBzZXQgRFhfUEJfVVJMKScsXG4gICAgZmV0Y2g6IGZldGNoUG9ja2V0QmFzZSxcbiAgICBwb3J0RW52OiAnRFhfUEJfUE9SVCcsXG4gICAgcm91dGU6ICcvYXBpL3BiJyxcbiAgICByZXdyaXRlOiAocCkgPT4gcC5yZXBsYWNlKC9eXFwvYXBpXFwvcGIvLCAnJykgfHwgJy8nLFxuICAgIHBvcnQ6IHBiUG9ydCxcbiAgICByZW1vdGU6IGVudi5EWF9QQl9VUkwgfHwgJycsXG4gICAgb2ZmbGluZTogKHJlcykgPT4ge1xuICAgICAgcmVzLndyaXRlSGVhZCg1MDMsIHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9KVxuICAgICAgcmVzLmVuZChKU09OLnN0cmluZ2lmeSh7IHN0YXR1czogNTAzLCBtZXNzYWdlOiAnUG9ja2V0QmFzZSBpcyBub3QgcnVubmluZyBvbiB0aGlzIGNvbXB1dGVyICh5ZXQpLiBTZWUgdGhlIGRldiBzZXJ2ZXIgbG9nLicgfSkpXG4gICAgfSxcbiAgfSxcbiAgXVxufVxuXG5hc3luYyBmdW5jdGlvbiBmZXRjaFBvY2tldEJhc2Uocm9vdCwgbG9nZ2VyKSB7XG4gIGNvbnN0IHBsYXQgPSB7ICdsaW51eC14NjQnOiAnbGludXhfYW1kNjQnLCAnbGludXgtYXJtNjQnOiAnbGludXhfYXJtNjQnLCAnZGFyd2luLXg2NCc6ICdkYXJ3aW5fYW1kNjQnLCAnZGFyd2luLWFybTY0JzogJ2Rhcndpbl9hcm02NCcgfVtgJHtwcm9jZXNzLnBsYXRmb3JtfS0ke3Byb2Nlc3MuYXJjaH1gXVxuICBpZiAoIXBsYXQpIHtcbiAgICBsb2dnZXIud2FybihgW3BvY2tldGJhc2VdIG5vIHBpbm5lZCBidWlsZCBmb3IgJHtwcm9jZXNzLnBsYXRmb3JtfS0ke3Byb2Nlc3MuYXJjaH06IHB1dCBQb2NrZXRCYXNlICR7UEJfVkVSU0lPTn0gYXQgYmFja2VuZC9iaW4vcG9ja2V0YmFzZSwgb3Igc2V0IERYX1BCX1VSTGApXG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbiAgY29uc3QgbmFtZSA9IGBwb2NrZXRiYXNlXyR7UEJfVkVSU0lPTn1fJHtwbGF0fS56aXBgXG4gIGNvbnN0IGRpciA9IHJlc29sdmUocm9vdCwgJ2JhY2tlbmQvYmluJylcbiAgY29uc3QgcGFydCA9IHJlc29sdmUoZGlyLCBgLnBvY2tldGJhc2UucGFydGApXG4gIGxvZ2dlci5pbmZvKGBbcG9ja2V0YmFzZV0gZG93bmxvYWRpbmcgJHtuYW1lfSAoZmlyc3QgcnVuIG9ubHkpYClcbiAgdHJ5IHtcbiAgICBta2RpclN5bmMoZGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KVxuICAgIGNvbnN0IHIgPSBhd2FpdCBmZXRjaChgaHR0cHM6Ly9naXRodWIuY29tL3BvY2tldGJhc2UvcG9ja2V0YmFzZS9yZWxlYXNlcy9kb3dubG9hZC92JHtQQl9WRVJTSU9OfS8ke25hbWV9YClcbiAgICBpZiAoIXIub2spIHRocm93IG5ldyBFcnJvcihgSFRUUCAke3Iuc3RhdHVzfWApXG4gICAgY29uc3QgYnVmID0gQnVmZmVyLmZyb20oYXdhaXQgci5hcnJheUJ1ZmZlcigpKVxuICAgIGNvbnN0IHNoYSA9IGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShidWYpLmRpZ2VzdCgnaGV4JylcbiAgICBpZiAoc2hhICE9PSBQQl9TSEEyNTZbcGxhdF0pIHRocm93IG5ldyBFcnJvcihgY2hlY2tzdW0gbWlzbWF0Y2ggKCR7c2hhfSk6IHJlZnVzaW5nIHRvIHVzZSBpdGApXG4gICAgd3JpdGVGaWxlU3luYyhwYXJ0LCB1bnppcE9uZShidWYsICdwb2NrZXRiYXNlJykpICAgLy8gbm90IGV2ZXJ5IGxhcHRvcCBoYXMgYHVuemlwYFxuICAgIGNobW9kU3luYyhwYXJ0LCAwbzc1NSlcbiAgICByZW5hbWVTeW5jKHBhcnQsIHJlc29sdmUoZGlyLCAncG9ja2V0YmFzZScpKVxuICAgIHJldHVybiB0cnVlXG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBsb2dnZXIud2FybihgW3BvY2tldGJhc2VdIGRvd25sb2FkIGZhaWxlZCAoJHtlLm1lc3NhZ2V9KTsgL2FwaS9wYiBhbnN3ZXJzIDUwMyB1bnRpbCB0aGUgbmV4dCBcXGBidW4gcnVuIGRldlxcYGApXG4gICAgcmV0dXJuIGZhbHNlXG4gIH0gZmluYWxseSB7XG4gICAgcm1TeW5jKHBhcnQsIHsgZm9yY2U6IHRydWUgfSlcbiAgfVxufVxuXG4vLyBPbmUgZmlsZSBvdXQgb2YgYSAobm9uLXppcDY0KSB6aXAsIHZpYSBpdHMgY2VudHJhbCBkaXJlY3Rvcnk7IHRoZSB6aXAncyBTSEEtMjU2IHdhcyBjaGVja2VkIGJlZm9yZSB0aGlzLlxuZnVuY3Rpb24gdW56aXBPbmUoYnVmLCB3YW50KSB7XG4gIGNvbnN0IGVuZCA9IGJ1Zi5sYXN0SW5kZXhPZihCdWZmZXIuZnJvbShbMHg1MCwgMHg0YiwgMHgwNSwgMHgwNl0pKVxuICBpZiAoZW5kIDwgMCkgdGhyb3cgbmV3IEVycm9yKCdub3QgYSB6aXAnKVxuICBmb3IgKGxldCBpID0gMCwgcCA9IGJ1Zi5yZWFkVUludDMyTEUoZW5kICsgMTYpOyBpIDwgYnVmLnJlYWRVSW50MTZMRShlbmQgKyAxMCk7IGkrKykge1xuICAgIGNvbnN0IG1ldGhvZCA9IGJ1Zi5yZWFkVUludDE2TEUocCArIDEwKSwgc2l6ZSA9IGJ1Zi5yZWFkVUludDMyTEUocCArIDIwKVxuICAgIGNvbnN0IG5hbWVMZW4gPSBidWYucmVhZFVJbnQxNkxFKHAgKyAyOCksIGxvY2FsID0gYnVmLnJlYWRVSW50MzJMRShwICsgNDIpXG4gICAgaWYgKGJ1Zi50b1N0cmluZygndXRmOCcsIHAgKyA0NiwgcCArIDQ2ICsgbmFtZUxlbikgPT09IHdhbnQpIHtcbiAgICAgIGNvbnN0IHN0YXJ0ID0gbG9jYWwgKyAzMCArIGJ1Zi5yZWFkVUludDE2TEUobG9jYWwgKyAyNikgKyBidWYucmVhZFVJbnQxNkxFKGxvY2FsICsgMjgpXG4gICAgICBjb25zdCBkYXRhID0gYnVmLnN1YmFycmF5KHN0YXJ0LCBzdGFydCArIHNpemUpXG4gICAgICBpZiAobWV0aG9kID09PSA4KSByZXR1cm4gaW5mbGF0ZVJhd1N5bmMoZGF0YSlcbiAgICAgIGlmIChtZXRob2QgPT09IDApIHJldHVybiBkYXRhXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIHppcCBtZXRob2QgJHttZXRob2R9YClcbiAgICB9XG4gICAgcCArPSA0NiArIG5hbWVMZW4gKyBidWYucmVhZFVJbnQxNkxFKHAgKyAzMCkgKyBidWYucmVhZFVJbnQxNkxFKHAgKyAzMilcbiAgfVxuICB0aHJvdyBuZXcgRXJyb3IoYCR7d2FudH0gbm90IGluIHRoZSB6aXBgKVxufVxuXG4vLyBBbm90aGVyIGBidW4gcnVuIGRldmAgKGFub3RoZXIgd29ya3RyZWUpIG1heSBhbHJlYWR5IGhvbGQgdGhlIHBvcnQ6IHNheSBzbyBvbmNlIGluc3RlYWQgb2YgY3Jhc2gtbG9vcGluZy5cbmNvbnN0IHBvcnRJblVzZSA9IChwb3J0KSA9PiBuZXcgUHJvbWlzZSgob2spID0+IHtcbiAgY29uc3QgcyA9IGNvbm5lY3QoeyBob3N0OiAnMTI3LjAuMC4xJywgcG9ydCB9LCAoKSA9PiB7IHMuZGVzdHJveSgpOyBvayh0cnVlKSB9KVxuICBzLm9uKCdlcnJvcicsICgpID0+IG9rKGZhbHNlKSlcbn0pXG5cbi8vIFRoZSBwcm94eSB0YWJsZSBmb3Igdml0ZSdzIGBzZXJ2ZXIucHJveHlgLiBTU0UgKGAvZXZlbnRzYCkgc3RyZWFtcyB0aHJvdWdoIHVuYnVmZmVyZWQuXG5leHBvcnQgZnVuY3Rpb24gZGV2QmFja2VuZFByb3h5KGVudiA9IHByb2Nlc3MuZW52KSB7XG4gIC8vIHdzOiBhIGJhY2tlbmQgbWF5IHRha2UgYSBXZWJTb2NrZXQgKHJ1ZGRlcidzIC9zdHJlYW0gY2FycmllcyB0aGUgYnJvd3NlcidzIG1pY3JvcGhvbmUgb24gYSBzZXJ2ZXIgZGVwbG95bWVudCkuXG4gIHJldHVybiBPYmplY3QuZnJvbUVudHJpZXMoZGV2QmFja2VuZHMoZW52KS5tYXAoKGIpID0+IFtiLnJvdXRlLCB7XG4gICAgdGFyZ2V0OiBiLnJlbW90ZSB8fCBgaHR0cDovLzEyNy4wLjAuMToke2IucG9ydH1gLCBjaGFuZ2VPcmlnaW46ICEhYi5yZW1vdGUsIHdzOiB0cnVlLFxuICAgIC4uLihiLnJld3JpdGUgPyB7IHJld3JpdGU6IGIucmV3cml0ZSB9IDoge30pLFxuICB9XSkpXG59XG5cbmNvbnN0IFJFRyA9IChnbG9iYWxUaGlzLl9fZHhEZXZCYWNrZW5kcyB8fD0geyBwcm9jczogbmV3IE1hcCgpLCBleGl0SG9va2VkOiBmYWxzZSwgc3RvcHBpbmc6IGZhbHNlIH0pXG5jb25zdCBpc0FsaXZlID0gKG5hbWUpID0+IHsgY29uc3QgZSA9IFJFRy5wcm9jcy5nZXQobmFtZSk7IHJldHVybiAhIWUgJiYgZS5jaGlsZC5leGl0Q29kZSA9PT0gbnVsbCAmJiBlLmNoaWxkLnNpZ25hbENvZGUgPT09IG51bGwgfVxuXG5mdW5jdGlvbiBzdG9wQWxsKCkge1xuICBSRUcuc3RvcHBpbmcgPSB0cnVlXG4gIGZvciAoY29uc3QgeyBjaGlsZCB9IG9mIFJFRy5wcm9jcy52YWx1ZXMoKSkgeyB0cnkgeyBjaGlsZC5raWxsKCdTSUdURVJNJykgfSBjYXRjaCB7fSB9XG59XG5cbmZ1bmN0aW9uIHN0YXJ0KHJvb3QsIGIsIGxvZ2dlciwgcmVzdGFydHMgPSAwKSB7XG4gIGNvbnN0IHRhZyA9IGBbJHtiLm5hbWV9XWBcbiAgY29uc3QgY2hpbGQgPSBzcGF3bihyZXNvbHZlKHJvb3QsIGIuYmluKSwgYi5hcmdzIHx8IFtdLCB7IGN3ZDogcm9vdCwgZW52OiB7IC4uLnByb2Nlc3MuZW52LCAuLi5iLmVudiB9LCBzdGRpbzogWydpZ25vcmUnLCAncGlwZScsICdwaXBlJ10gfSlcbiAgY29uc3QgZW50cnkgPSB7IGNoaWxkLCByZXN0YXJ0cywgbG9nZ2VyIH1cbiAgUkVHLnByb2NzLnNldChiLm5hbWUsIGVudHJ5KVxuICAvLyBcdTI2MDUgVEhFIEZVTEwgTE9HIEdPRVMgVE8gQSBGSUxFOyBUSEUgVEVSTUlOQUwgR0VUUyBXSEFUIEEgUEVSU09OIE1VU1QgQUNUIE9OLiBQb2NrZXRCYXNlIHByaW50cyBhYm91dFxuICAvLyAyMzAgbGluZXMgb2Ygc3RhcnR1cCBTUUwsIHdoaWNoIHNjcm9sbGVkIFZpdGUncyBcIlx1Mjc5QyBMb2NhbDpcIiBhZGRyZXNzIG91dCBvZiB2aWV3IGZvciBhIGZyZXNoIHJlYWRlciBvZiB0aGVcbiAgLy8gUkVBRE1FLiBFdmVyeSBsaW5lIHN0aWxsIGxhbmRzIGluIC5wYi9sb2dzLzxuYW1lPi5sb2cgKGdpdGlnbm9yZWQpLiBFcnJvcnMsIHdhcm5pbmdzIGFuZCBcImFkZHJlc3MgYWxyZWFkeVxuICAvLyBpbiB1c2VcIiAodGhlIGxpbmUgdGhlIFJFQURNRSBhbmQgSE9XVE8gdGVsbCBhIHJlYWRlciB0byB3YXRjaCBmb3IgYmVmb3JlIHNldHRpbmcgRFhfUEJfUE9SVCkgYXJlXG4gIC8vIGZvcndhcmRlZCBleGFjdGx5IGFzIGJlZm9yZS5cbiAgY29uc3QgbG9nRGlyID0gcmVzb2x2ZShyb290LCAnLnBiJywgJ2xvZ3MnKVxuICBta2RpclN5bmMobG9nRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KVxuICBjb25zdCBzaW5rID0gY3JlYXRlV3JpdGVTdHJlYW0ocmVzb2x2ZShsb2dEaXIsIGAke2IubmFtZX0ubG9nYCksIHsgZmxhZ3M6ICdhJyB9KVxuICAvLyBUaGUgZmlyc3QtcnVuIFwiY3JlYXRlIHlvdXIgZmlyc3Qgc3VwZXJ1c2VyXCIgbGluayBpcyBmb3J3YXJkZWQgdG9vOiBpdCBpcyBhIHN0ZXAgYSBwZXJzb24gbXVzdCB0YWtlLFxuICAvLyBhbmQgdGhlIEhPV1RPJ3MgYWRtaW4gc2NyZWVuIGF0IC9hcGkvcGIvXy8gaXMgdW51c2FibGUgb24gYSBmcmVzaCAucGIgd2l0aG91dCBpdC5cbiAgY29uc3QgTE9VRCA9IC9cXGIoZXJyb3J8ZmFpbChlZHx1cmUpP3xwYW5pY3xmYXRhbHx3YXJuKGluZyk/fHJlZnVzZWR8ZGVuaWVkfGluIHVzZXxjYW5ub3R8dW5hYmxlfHN1cGVydXNlcnxwYmluc3RhbGw/KVxcYi9pXG4gIGNvbnN0IG91dCA9IChkKSA9PiB7XG4gICAgc2luay53cml0ZShkKVxuICAgIFN0cmluZyhkKS50cmltKCkuc3BsaXQoJ1xcbicpLmZvckVhY2goKGwpID0+IGwgJiYgTE9VRC50ZXN0KGwpICYmIGVudHJ5LmxvZ2dlci5pbmZvKGAke3RhZ30gJHtsfWApKVxuICB9XG4gIGNoaWxkLnN0ZG91dC5vbignZGF0YScsIG91dClcbiAgY2hpbGQuc3RkZXJyLm9uKCdkYXRhJywgb3V0KVxuICBjaGlsZC5vbignZXhpdCcsICgpID0+IHNpbmsuZW5kKCkpXG4gIGNoaWxkLm9uKCdleGl0JywgKGNvZGUpID0+IHtcbiAgICBpZiAoUkVHLnByb2NzLmdldChiLm5hbWUpICE9PSBlbnRyeSkgcmV0dXJuXG4gICAgUkVHLnByb2NzLmRlbGV0ZShiLm5hbWUpXG4gICAgaWYgKFJFRy5zdG9wcGluZykgcmV0dXJuXG4gICAgZW50cnkubG9nZ2VyLndhcm4oYCR7dGFnfSBleGl0ZWQgKCR7Y29kZX0pYClcbiAgICAvLyBDcmFzaGVkIG9uIGl0cyBvd246IHJlc3RhcnQgaXQsIGFmdGVyIGl0cyBwb3J0IGhhcyBoYWQgYSBtb21lbnQgdG8gZnJlZSB1cC5cbiAgICBpZiAoZW50cnkucmVzdGFydHMgPCA1KSB7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgaWYgKFJFRy5zdG9wcGluZyB8fCBSRUcucHJvY3MuaGFzKGIubmFtZSkpIHJldHVyblxuICAgICAgICBlbnRyeS5sb2dnZXIud2FybihgJHt0YWd9IHJlc3RhcnRpbmcgKCR7ZW50cnkucmVzdGFydHMgKyAxfS81KWApXG4gICAgICAgIHN0YXJ0KHJvb3QsIGIsIGVudHJ5LmxvZ2dlciwgZW50cnkucmVzdGFydHMgKyAxKVxuICAgICAgfSwgMjAwMClcbiAgICB9XG4gIH0pXG4gIGxvZ2dlci5pbmZvKGAke3RhZ30gc3RhcnRlZCBcdTIxOTIgJHtiLnJvdXRlfSBvbiAxMjcuMC4wLjE6JHtiLnBvcnR9IChmdWxsIGxvZzogLnBiL2xvZ3MvJHtiLm5hbWV9LmxvZylgKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gYmFja2VuZERldlBsdWdpbihyb290LCBlbnYgPSBwcm9jZXNzLmVudikge1xuICBjb25zdCBiYWNrZW5kcyA9IGRldkJhY2tlbmRzKGVudilcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnZHgtYmFja2VuZC1kZXYnLFxuICAgIGFwcGx5OiAnc2VydmUnLFxuICAgIGNvbmZpZ3VyZVNlcnZlcihzZXJ2ZXIpIHtcbiAgICAgIC8vIEVOR0lORSBOT1QgUlVOTklORywgUVVJRVRMWSAoZHgtc2hlcGhlcmQsIFI1MDApOiB3aXRoIG5vIGJhY2tlbmQgcHJvY2VzcyB0aGUgcHJveHkgYW5zd2VyZWRcbiAgICAgIC8vIDUwMCBFQ09OTlJFRlVTRUQsIHdoaWNoIGV2ZXJ5IHBhZ2Ugc2hvd2VkIGFzIGNvbnNvbGUgZXJyb3JzLiBXaGlsZSBhIGJhY2tlbmQgaXMgZG93biBpdHMgcm91dGVzIGdldFxuICAgICAgLy8gd2VsbC1mb3JtZWQgYW5zd2VycyBpbnN0ZWFkOiAvZXZlbnRzIHN0cmVhbXMgT05FIHN0YXR1cyBldmVudCBzYXlpbmcgdGhlIGVuZ2luZSBpcyBvZmZsaW5lICh0aGVcbiAgICAgIC8vIHBsdWdpbiByZW5kZXJzIGl0cyBvd24gXCJlbmdpbmUgbm90IHJ1bm5pbmdcIiBzdGF0ZSBmcm9tIGl0KSwgYW55dGhpbmcgZWxzZSByZXR1cm5zIGFuIGVtcHR5IEpTT05cbiAgICAgIC8vIGxpc3QuIFJlZ2lzdGVyZWQgaGVyZSwgc28gaXQgcnVucyBiZWZvcmUgdml0ZSdzIHByb3h5LlxuICAgICAgZm9yIChjb25zdCBiIG9mIGJhY2tlbmRzKSB7XG4gICAgICAgIHNlcnZlci5taWRkbGV3YXJlcy51c2UoYi5yb3V0ZSwgKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgICAgICAgaWYgKGIucmVtb3RlIHx8IGlzQWxpdmUoYi5uYW1lKSkgcmV0dXJuIG5leHQoKVxuICAgICAgICAgIGlmIChiLm9mZmxpbmUpIHJldHVybiBiLm9mZmxpbmUocmVzKVxuICAgICAgICAgIGNvbnN0IHN0YXR1cyA9IHsgZW5naW5lOiAnb2ZmbGluZScsIGV4cGVjdGVkOiAhIShiLmV4cGVjdGVkICYmIGIuZXhwZWN0ZWQoKSksIGVycm9yOiAnVGhlIGRlc2t0b3AgZW5naW5lIGlzIG5vdCBydW5uaW5nLicgfVxuICAgICAgICAgIGlmICgocmVxLnVybCB8fCAnJykuc3RhcnRzV2l0aCgnL2V2ZW50cycpKSB7XG4gICAgICAgICAgICByZXMud3JpdGVIZWFkKDIwMCwgeyAnQ29udGVudC1UeXBlJzogJ3RleHQvZXZlbnQtc3RyZWFtJywgJ0NhY2hlLUNvbnRyb2wnOiAnbm8tY2FjaGUnLCBDb25uZWN0aW9uOiAna2VlcC1hbGl2ZScgfSlcbiAgICAgICAgICAgIHJlcy53cml0ZShgZGF0YTogJHtKU09OLnN0cmluZ2lmeSh7IHR5cGU6ICdzdGF0dXMnLCBzdGF0dXMgfSl9XFxuXFxuYClcbiAgICAgICAgICAgIHJldHVybiAgIC8vIGhlbGQgb3Blbiwgc28gdGhlIEV2ZW50U291cmNlIGRvZXMgbm90IHJlY29ubmVjdCBpbiBhIGxvb3BcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gL3N0YXR1cyBhbnN3ZXJzIHRoZSBzYW1lLCBmb3IgYSBwYWdlIHdob3NlIGV2ZW50IHN0cmVhbSBjYW5ub3QgZ2V0IHRocm91Z2ggKGEgcHJveHkgdGhhdCBidWZmZXJzKS5cbiAgICAgICAgICBpZiAoKHJlcS51cmwgfHwgJycpLnN0YXJ0c1dpdGgoJy9zdGF0dXMnKSkge1xuICAgICAgICAgICAgcmVzLndyaXRlSGVhZCgyMDAsIHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9KVxuICAgICAgICAgICAgcmVzLmVuZChKU09OLnN0cmluZ2lmeShzdGF0dXMpKVxuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgfVxuICAgICAgICAgIHJlcy53cml0ZUhlYWQoMjAwLCB7ICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicgfSlcbiAgICAgICAgICByZXMuZW5kKCdbXScpXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgICBjb25zdCBsb2dnZXIgPSBzZXJ2ZXIuY29uZmlnLmxvZ2dlclxuICAgICAgaWYgKCFSRUcuZXhpdEhvb2tlZCkge1xuICAgICAgICBSRUcuZXhpdEhvb2tlZCA9IHRydWVcbiAgICAgICAgcHJvY2Vzcy5vbmNlKCdleGl0Jywgc3RvcEFsbClcbiAgICAgICAgcHJvY2Vzcy5vbmNlKCdTSUdJTlQnLCAoKSA9PiB7IHN0b3BBbGwoKTsgcHJvY2Vzcy5leGl0KDApIH0pXG4gICAgICAgIHByb2Nlc3Mub25jZSgnU0lHVEVSTScsICgpID0+IHsgc3RvcEFsbCgpOyBwcm9jZXNzLmV4aXQoMCkgfSlcbiAgICAgIH1cbiAgICAgIGZvciAoY29uc3QgYiBvZiBiYWNrZW5kcykge1xuICAgICAgICBpZiAoYi5yZW1vdGUpIHtcbiAgICAgICAgICBsb2dnZXIuaW5mbyhgWyR7Yi5uYW1lfV0gbm90IHN0YXJ0ZWQgaGVyZTogJHtiLnJvdXRlfSBcdTIxOTIgJHtiLnJlbW90ZX1gKVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzQWxpdmUoYi5uYW1lKSkge1xuICAgICAgICAgIFJFRy5wcm9jcy5nZXQoYi5uYW1lKS5sb2dnZXIgPSBsb2dnZXIgICAvLyBsb2cgdGhyb3VnaCB0aGUgcmVzdGFydGVkIHNlcnZlclxuICAgICAgICAgIGxvZ2dlci5pbmZvKGBbJHtiLm5hbWV9XSBzdGlsbCBydW5uaW5nIFx1MjE5MiAke2Iucm91dGV9IChrZXB0IGFjcm9zcyB0aGUgZGV2LXNlcnZlciByZXN0YXJ0KWApXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuICAgICAgICBpZiAoYi5kaXNhYmxlZCAmJiBiLmRpc2FibGVkKCkpIHtcbiAgICAgICAgICBsb2dnZXIuaW5mbyhgW2JhY2tlbmRdICR7Yi5uYW1lfSBzd2l0Y2hlZCBvZmYgaGVyZSAoJHtiLm5hbWUgPT09ICdydWRkZXItZW5naW5lJyA/ICdSVURERVJfRU5HSU5FPTAnIDogJ2Rpc2FibGVkJ30pYClcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGxhdW5jaCA9IGFzeW5jICgpID0+IHtcbiAgICAgICAgICBpZiAoYi5wb3J0RW52ICYmIGF3YWl0IHBvcnRJblVzZShiLnBvcnQpKSB7XG4gICAgICAgICAgICBsb2dnZXIud2FybihgWyR7Yi5uYW1lfV0gcG9ydCAke2IucG9ydH0gaXMgYWxyZWFkeSBpbiB1c2UgKGFub3RoZXIgXFxgYnVuIHJ1biBkZXZcXGA/KTogbm90IHN0YXJ0ZWQuIFNldCAke2IucG9ydEVudn0gdG8gdXNlIGFub3RoZXIgcG9ydC5gKVxuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghUkVHLnN0b3BwaW5nICYmICFpc0FsaXZlKGIubmFtZSkpIHN0YXJ0KHJvb3QsIGIsIGxvZ2dlcilcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWV4aXN0c1N5bmMocmVzb2x2ZShyb290LCBiLmJpbikpKSB7XG4gICAgICAgICAgaWYgKGIuZmV0Y2gpIHtcbiAgICAgICAgICAgIFJFRy5mZXRjaGluZyB8fD0gbmV3IFNldCgpXG4gICAgICAgICAgICBpZiAoUkVHLmZldGNoaW5nLmhhcyhiLm5hbWUpKSBjb250aW51ZSAgIC8vIGEgdml0ZSByZXN0YXJ0IG1pZC1kb3dubG9hZDogdGhlIGZpcnN0IG9uZSBmaW5pc2hlcyBpdFxuICAgICAgICAgICAgUkVHLmZldGNoaW5nLmFkZChiLm5hbWUpXG4gICAgICAgICAgICBiLmZldGNoKHJvb3QsIGxvZ2dlcikudGhlbigob2spID0+IHsgUkVHLmZldGNoaW5nLmRlbGV0ZShiLm5hbWUpOyBpZiAob2spIGxhdW5jaCgpIH0pXG4gICAgICAgICAgICBjb250aW51ZVxuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBBbiBPUFRJT05BTCBiYWNrZW5kIGlzIGEgbm90ZSwgbm90IGEgd2FybmluZzogYSBzdHJhbmdlcidzIGZpcnN0IGBidW4gcnVuIGRldmAgbGluZSBzYWlkXG4gICAgICAgICAgLy8gXCJydWRkZXItZW5naW5lIG5vdCBidWlsdCBcdTIwMjYgZ28gYnVpbGQgXHUyMDI2XCIgd2l0aCBubyB3b3JkIHRoYXQgaXQgaXMgb3B0aW9uYWwgb3IgbmVlZHMgR28gKHVwZzEwMCdzXG4gICAgICAgICAgLy8gZnJlc2gtY2xvbmUgcnVuKS4gQSBiYWNrZW5kIHdpdGhvdXQgdGhhdCBub3RlIGtlZXBzIHRoZSBidWlsZCBpbnN0cnVjdGlvbi5cbiAgICAgICAgICBpZiAoYi5vcHRpb25hbCkgbG9nZ2VyLmluZm8oYFtiYWNrZW5kXSAke2Iub3B0aW9uYWx9YClcbiAgICAgICAgICBlbHNlIGxvZ2dlci53YXJuKGBbYmFja2VuZF0gJHtiLm5hbWV9IG5vdCBidWlsdCBcdTIwMTQgaXRzIHBsdWdpbiB3aWxsIHNob3cgXCJlbmdpbmUgb2ZmbGluZVwiLiBCdWlsZDogJHtiLmJ1aWxkfWApXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuICAgICAgICBsYXVuY2goKVxuICAgICAgfVxuICAgIH0sXG4gIH1cbn1cbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL2hvbWUvbGsxMHgvV29ya3NwYWNlL2Vjby1keC9yb290LWRveGEtbWFwcy93dC1oZi9pbnRlcm5hbFwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL2hvbWUvbGsxMHgvV29ya3NwYWNlL2Vjby1keC9yb290LWRveGEtbWFwcy93dC1oZi9pbnRlcm5hbC9kZXYtc3luYy1wbHVnaW4ubWpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9ob21lL2xrMTB4L1dvcmtzcGFjZS9lY28tZHgvcm9vdC1kb3hhLW1hcHMvd3QtaGYvaW50ZXJuYWwvZGV2LXN5bmMtcGx1Z2luLm1qc1wiOy8qKlxuICogaW50ZXJuYWwvZGV2LXN5bmMtcGx1Z2luLm1qcyBcdTIwMTQgYGJ1biBydW4gZGV2YCBmb2xsb3dzIGEgc2hhcmVkIGJyYW5jaCwgc28gYSBsYXB0b3Agc2VlcyB0ZWFtbWF0ZXMnIGxhbmRpbmdzLlxuICpcbiAqIFdIWTogdGVuIHBlb3BsZSBlYWNoIHJ1bm5pbmcgYGJ1biBydW4gZGV2YCBzaG91bGQgc2VlIHdoYXQgdGhlIG90aGVycyBsYW5kZWQgb24gZGV2ZWxvcG1lbnQgd2l0aG91dCBhbnlvbmVcbiAqIHR5cGluZyBgZ2l0IHB1bGxgOiB0aGUgZGV2IHNlcnZlciBmYXN0LWZvcndhcmRzIGFuZCBWaXRlIGhvdC1yZWxvYWRzIHRoZSBjaGFuZ2VkIGZpbGVzLiBJdCBpcyB0aGUgbG9jYWxcbiAqIGZvcm0gb2YgdGhlIGNsb3VkIGNvbnRhaW5lcidzIHB1bGwgbG9vcCAoZGVwbG95bWVudC9jbG91ZC9lbnRyeS5zaCksIE1JTlVTIHRoZSBgcmVzZXQgLS1oYXJkYDogYSBsYXB0b3BcbiAqIGhvbGRzIHNvbWVvbmUncyB1bnNhdmVkIHdvcmssIHNvIHRoaXMgTkVWRVIgbWVyZ2VzIG92ZXIgbG9jYWwgZWRpdHMsIG5ldmVyIHN0YXNoZXMsIG5ldmVyIHJlc2V0cy5cbiAqXG4gKiBPUFQtSU4sIE9ORSBzd2l0Y2ggaW4gLmVudi5sb2NhbDogRFhfU1lOQ19SRU1PVEUgPSBhIHJlbW90ZSBuYW1lIChvcmlnaW4pIE9SIGEgcmVwbyBVUkwgKGh0dHBzOi8vXHUyMDI2L3guZ2l0KSxcbiAqIGUuZy4gdG8gd2F0Y2ggd2hhdCBjbG91ZCBhZ2VudHMgcHVzaC4gRFhfU1lOQ19CUkFOQ0ggZGVmYXVsdHMgdG8gZGV2ZWxvcG1lbnQgKHRoZSBzaGFyZWQgdGFibGU7IG1haW4gaXNcbiAqIHByb2R1Y3Rpb24gYW5kIG1vdmVzIG9ubHkgb24gYSBwdWJsaXNoKSwgRFhfU1lOQ19JTlRFUlZBTCB0byA1IHNlY29uZHMuXG4gKiBVbnNldCA9IG9mZjogcGxhaW4gaG90IHJlbG9hZCBvZiBsb2NhbCBlZGl0cywgYXMgYWx3YXlzLiBFdmVyeSBpbnRlcnZhbCBpdCBmZXRjaGVzIDxyZW1vdGU+IDxicmFuY2g+XG4gKiAoYSBVUkwgbmVlZHMgbm8gYGdpdCByZW1vdGUgYWRkYDsgcHJpdmF0ZSByZXBvcyB1c2UgeW91ciBub3JtYWwgZ2l0IGNyZWRlbnRpYWxzKSBhbmQgZmFzdC1mb3J3YXJkcyBPTkxZIHdoZW5cbiAqIHRoaXMgY2hlY2tvdXQgaXMgb24gdGhhdCBicmFuY2gsIG5vIHRyYWNrZWQgZmlsZSBpcyBtb2RpZmllZCwgYW5kIGBnaXQgbWVyZ2UgLS1mZi1vbmx5YCBhZ3JlZXMuXG4gKiBPdGhlcndpc2UgaXQgbG9ncyBvbmNlIHBlciBuZXcgdXBzdHJlYW0gY29tbWl0IChcImRldmVsb3BtZW50IGlzIE4gY29tbWl0cyBhaGVhZCwgcHVsbCB3aGVuIHJlYWR5XCIpIGFuZCByZXBvcnRzXG4gKiB0aGUgc3RhdGUgYXQgL2FwaS9kZXYtc3luYyBmb3IgYSBTdHVkaW8gYmFkZ2UuXG4gKlxuICogREVWIE9OTFkgKGBhcHBseTogJ3NlcnZlJ2ApLlxuICovXG5pbXBvcnQgeyBleGVjRmlsZSB9IGZyb20gJ25vZGU6Y2hpbGRfcHJvY2VzcydcblxuY29uc3QgZ2l0ID0gKHJvb3QsIGFyZ3MpID0+IG5ldyBQcm9taXNlKChvaykgPT4gZXhlY0ZpbGUoJ2dpdCcsIGFyZ3MsXG4gIHsgY3dkOiByb290LCB0aW1lb3V0OiA2MDAwMCwgZW52OiB7IC4uLnByb2Nlc3MuZW52LCBHSVRfVEVSTUlOQUxfUFJPTVBUOiAnMCcgfSB9LFxuICAoZSwgb3V0LCBlcnIpID0+IHtcbiAgICBjb25zdCBhbGwgPSBTdHJpbmcoZXJyIHx8IGU/Lm1lc3NhZ2UgfHwgJycpLnRyaW0oKVxuICAgIG9rKHsgb2s6ICFlLCBvdXQ6IFN0cmluZyhvdXQgfHwgJycpLnRyaW0oKSwgZXJyOiBhbGwuc3BsaXQoJ1xcbicpWzBdLCBlcnJBbGw6IGFsbCB9KVxuICB9KSlcblxuLy8gQSBmZXRjaCByZWZ1c2VkIGZvciB3YW50IG9mIENSRURFTlRJQUxTIGlzIG5vdCBhIG5ldHdvcmsgYmxpcDogaXQgZmFpbHMgaWRlbnRpY2FsbHkgZXZlcnkgaW50ZXJ2YWwgdW50aWxcbi8vIHRoaXMgbGFwdG9wIGNhbiByZWFkIHRoZSByZXBvLiBnaXQgcnVucyB3aXRoIEdJVF9URVJNSU5BTF9QUk9NUFQ9MCAoYSBwcm9tcHQgd291bGQgaGFuZyB0aGUgZGV2IHNlcnZlciksIHNvXG4vLyB3aXRoIG5vIGNyZWRlbnRpYWwgaGVscGVyIGl0IGNhbiBvbmx5IGZhaWwsIGFuZCBhIGJhcmUgXCJmZXRjaC1mYWlsZWQgLyByZW1vdGU6IFVuYXV0aG9yaXplZFwiIHJlYWQgYXMgYVxuLy8gYnJva2VuIHNlcnZlci4gTWVhc3VyZWQgb24gYSBmcmVzaCBjbG9uZTogdGhlIHNhbWUgZmV0Y2ggc3VjY2VlZGVkIG9uY2UgY3JlZGVudGlhbHMgd2VyZSBzdXBwbGllZC5cbmNvbnN0IEFVVEhfUkUgPSAvdW5hdXRob3JpW3N6XWVkfGF1dGhlbnRpY2F0aW9uIGZhaWxlZHxjb3VsZCBub3QgcmVhZCAodXNlcm5hbWV8cGFzc3dvcmQpfHRlcm1pbmFsIHByb21wdHMgZGlzYWJsZWR8cGVybWlzc2lvbiBkZW5pZWQgXFwocHVibGlja2V5fFxcYjQwWzEzXVxcYi9pXG5cbi8vIFdoYXQgdGhlIGxvZyBhbmQgL2FwaS9kZXYtc3luYyBzaG93OiBuZXZlciB0aGUgY3JlZGVudGlhbHMgb2YgYSBodHRwczovL3VzZXI6dG9rZW5AaG9zdC9cdTIwMjYgVVJMLlxuY29uc3Qgc2hvd24gPSAocmVtb3RlKSA9PiByZW1vdGUucmVwbGFjZSgvXFwvXFwvW14vQF0qQC8sICcvLycpXG5jb25zdCBsYWJlbCA9IChyZW1vdGUsIGJyYW5jaCkgPT4gKHJlbW90ZS5pbmNsdWRlcygnLycpID8gYCR7YnJhbmNofSBvZiAke3Nob3duKHJlbW90ZSl9YCA6IGAke3JlbW90ZX0vJHticmFuY2h9YClcblxuLy8gT25lIHRpbWVyIHBlciBgYnVuIHJ1biBkZXZgLCBrZXB0IGFjcm9zcyBWaXRlJ3Mgb3duIHJlc3RhcnRzICh0aGUgY29uZmlnIG1vZHVsZSBpcyByZS1pbXBvcnRlZCB0aGVuKS5cbmNvbnN0IFJFRyA9IChnbG9iYWxUaGlzLl9fZHhEZXZTeW5jIHx8PSB7IHRpbWVyOiBudWxsLCBydW5uaW5nOiBmYWxzZSwgc3RhdHVzOiB7IGVuYWJsZWQ6IGZhbHNlIH0gfSlcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN5bmNPbmNlKHJvb3QsIHJlbW90ZSwgYnJhbmNoLCBsb2cgPSB7IGluZm8oKSB7fSwgd2FybigpIHt9IH0pIHtcbiAgaWYgKFJFRy5ydW5uaW5nKSByZXR1cm4gUkVHLnN0YXR1c1xuICBSRUcucnVubmluZyA9IHRydWVcbiAgdHJ5IHtcbiAgICBjb25zdCBzcmMgPSBsYWJlbChyZW1vdGUsIGJyYW5jaClcbiAgICBjb25zdCBzID0geyBlbmFibGVkOiB0cnVlLCByZW1vdGU6IHNob3duKHJlbW90ZSksIGJyYW5jaCwgY2hlY2tlZEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCkgfVxuICAgIGNvbnN0IGYgPSBhd2FpdCBnaXQocm9vdCwgWydmZXRjaCcsICctcScsIHJlbW90ZSwgYnJhbmNoXSlcbiAgICBpZiAoIWYub2spIHtcbiAgICAgIGNvbnN0IGF1dGggPSBBVVRIX1JFLnRlc3QoZi5lcnJBbGwpXG4gICAgICBjb25zdCBzdGF0ZSA9IGF1dGggPyAnbmVlZHMtY3JlZGVudGlhbHMnIDogJ2ZldGNoLWZhaWxlZCdcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBhdXRoXG4gICAgICAgID8gYGRldi1zeW5jIG5lZWRzIGdpdCBjcmVkZW50aWFscyBmb3IgJHtzaG93bihyZW1vdGUpfSAoYSBjcmVkZW50aWFsIGhlbHBlciwgb3IgYW4gU1NIIHJlbW90ZSB5b3VyIGtleSBjYW4gcmVhZCk7IGdpdCBzYWlkOiAke3Nob3duKGYuZXJyKX1gXG4gICAgICAgIDogYGNvdWxkIG5vdCBmZXRjaCAke3NyY306ICR7c2hvd24oZi5lcnIpfWBcbiAgICAgIGlmIChSRUcuc3RhdHVzLnN0YXRlICE9PSBzdGF0ZSB8fCBSRUcuc3RhdHVzLm1lc3NhZ2UgIT09IG1lc3NhZ2UpIGxvZy53YXJuKGBbZGV2LXN5bmNdICR7bWVzc2FnZX1gKVxuICAgICAgcmV0dXJuIChSRUcuc3RhdHVzID0geyAuLi5zLCBzdGF0ZSwgbWVzc2FnZSB9KVxuICAgIH1cbiAgICBjb25zdCB1cCA9IChhd2FpdCBnaXQocm9vdCwgWydyZXYtcGFyc2UnLCAnRkVUQ0hfSEVBRCddKSkub3V0XG4gICAgY29uc3QgaGVhZCA9IChhd2FpdCBnaXQocm9vdCwgWydyZXYtcGFyc2UnLCAnSEVBRCddKSkub3V0XG4gICAgY29uc3QgY3VyID0gKGF3YWl0IGdpdChyb290LCBbJ3N5bWJvbGljLXJlZicsICctcScsICctLXNob3J0JywgJ0hFQUQnXSkpLm91dFxuICAgIGNvbnN0IGJlaGluZCA9IE51bWJlcigoYXdhaXQgZ2l0KHJvb3QsIFsncmV2LWxpc3QnLCAnLS1jb3VudCcsIGBIRUFELi4ke3VwfWBdKSkub3V0IHx8IDApXG4gICAgY29uc3QgYWhlYWQgPSBOdW1iZXIoKGF3YWl0IGdpdChyb290LCBbJ3Jldi1saXN0JywgJy0tY291bnQnLCBgJHt1cH0uLkhFQURgXSkpLm91dCB8fCAwKVxuICAgIGNvbnN0IGRpcnR5ID0gKGF3YWl0IGdpdChyb290LCBbJ3N0YXR1cycsICctLXBvcmNlbGFpbicsICctLXVudHJhY2tlZC1maWxlcz1ubyddKSkub3V0ICE9PSAnJ1xuICAgIE9iamVjdC5hc3NpZ24ocywgeyB1cHN0cmVhbTogdXAsIGJlaGluZCwgYWhlYWQsIGRpcnR5LCBjdXJyZW50QnJhbmNoOiBjdXIgfHwgJyhkZXRhY2hlZCknIH0pXG4gICAgaWYgKGJlaGluZCA9PT0gMCkgcmV0dXJuIChSRUcuc3RhdHVzID0geyAuLi5zLCBzdGF0ZTogJ3VwLXRvLWRhdGUnLCBtZXNzYWdlOiBgdXAgdG8gZGF0ZSB3aXRoICR7c3JjfWAgfSlcbiAgICBjb25zdCB3aHkgPSBjdXIgIT09IGJyYW5jaCA/IGB0aGlzIGNoZWNrb3V0IGlzIG9uICR7Y3VyIHx8ICdhIGRldGFjaGVkIEhFQUQnfSwgbm90ICR7YnJhbmNofWBcbiAgICAgIDogZGlydHkgPyAneW91IGhhdmUgbG9jYWwgZWRpdHMnXG4gICAgICA6IGFoZWFkID8gYHlvdSBoYXZlICR7YWhlYWR9IGxvY2FsIGNvbW1pdChzKSB0aGF0IGFyZSBub3Qgb24gJHtzcmN9YCA6ICcnXG4gICAgY29uc3QgbSA9IHdoeSA/IG51bGwgOiBhd2FpdCBnaXQocm9vdCwgWydtZXJnZScsICctLWZmLW9ubHknLCAnLXEnLCB1cF0pXG4gICAgaWYgKHdoeSB8fCAhbS5vaykge1xuICAgICAgY29uc3QgbWVzc2FnZSA9IGAke2JyYW5jaH0gaXMgJHtiZWhpbmR9IGNvbW1pdChzKSBhaGVhZDsgJHt3aHkgfHwgYGZhc3QtZm9yd2FyZCByZWZ1c2VkICgke20uZXJyfSlgfSwgc28gbm90aGluZyB3YXMgbWVyZ2VkLiBQdWxsIHdoZW4gcmVhZHkuYFxuICAgICAgaWYgKFJFRy5zdGF0dXMudXBzdHJlYW0gIT09IHVwIHx8IFJFRy5zdGF0dXMuc3RhdGUgIT09ICdiZWhpbmQnKSBsb2cud2FybihgW2Rldi1zeW5jXSAke21lc3NhZ2V9YClcbiAgICAgIHJldHVybiAoUkVHLnN0YXR1cyA9IHsgLi4ucywgc3RhdGU6ICdiZWhpbmQnLCBtZXNzYWdlIH0pXG4gICAgfVxuICAgIGxvZy5pbmZvKGBbZGV2LXN5bmNdIGZhc3QtZm9yd2FyZGVkICR7aGVhZC5zbGljZSgwLCA4KX0gXHUyMTkyICR7dXAuc2xpY2UoMCwgOCl9ICgke2JlaGluZH0gY29tbWl0KHMpIGZyb20gJHtzcmN9KWApXG4gICAgcmV0dXJuIChSRUcuc3RhdHVzID0geyAuLi5zLCBiZWhpbmQ6IDAsIHN0YXRlOiAndXAtdG8tZGF0ZScsIGxhc3RNZXJnZTogcy5jaGVja2VkQXQsIG1lc3NhZ2U6IGBmYXN0LWZvcndhcmRlZCAke2JlaGluZH0gY29tbWl0KHMpIGZyb20gJHtzcmN9YCB9KVxuICB9IGZpbmFsbHkge1xuICAgIFJFRy5ydW5uaW5nID0gZmFsc2VcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZGV2U3luY1BsdWdpbihyb290LCBlbnYgPSBwcm9jZXNzLmVudikge1xuICBjb25zdCByZW1vdGUgPSBlbnYuRFhfU1lOQ19SRU1PVEUgfHwgJydcbiAgY29uc3QgYnJhbmNoID0gZW52LkRYX1NZTkNfQlJBTkNIIHx8ICdkZXZlbG9wbWVudCdcbiAgY29uc3QgZXZlcnkgPSBNYXRoLm1heCgyLCBOdW1iZXIoZW52LkRYX1NZTkNfSU5URVJWQUwpIHx8IDUpXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ2R4LWRldi1zeW5jJyxcbiAgICBhcHBseTogJ3NlcnZlJyxcbiAgICBjb25maWd1cmVTZXJ2ZXIoc2VydmVyKSB7XG4gICAgICBzZXJ2ZXIubWlkZGxld2FyZXMudXNlKCcvYXBpL2Rldi1zeW5jJywgKHJlcSwgcmVzKSA9PiB7XG4gICAgICAgIHJlcy53cml0ZUhlYWQoMjAwLCB7ICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsICdDYWNoZS1Db250cm9sJzogJ25vLXN0b3JlJyB9KVxuICAgICAgICByZXMuZW5kKEpTT04uc3RyaW5naWZ5KFJFRy5zdGF0dXMpKVxuICAgICAgfSlcbiAgICAgIGNsZWFySW50ZXJ2YWwoUkVHLnRpbWVyKVxuICAgICAgaWYgKCFyZW1vdGUpIHtcbiAgICAgICAgUkVHLnN0YXR1cyA9IHsgZW5hYmxlZDogZmFsc2UsIG1lc3NhZ2U6ICdvZmY6IHNldCBEWF9TWU5DX1JFTU9URSAoYSByZW1vdGUgbmFtZSBsaWtlIG9yaWdpbiwgb3IgYSByZXBvIFVSTCkgaW4gLmVudi5sb2NhbCB0byBmb2xsb3cgYSBzaGFyZWQgYnJhbmNoJyB9XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuICAgICAgY29uc3QgbG9nID0gc2VydmVyLmNvbmZpZy5sb2dnZXJcbiAgICAgIGxvZy5pbmZvKGBbZGV2LXN5bmNdIGZvbGxvd2luZyAke2xhYmVsKHJlbW90ZSwgYnJhbmNoKX0gZXZlcnkgJHtldmVyeX1zIChmYXN0LWZvcndhcmQgb25seSwgbmV2ZXIgb3ZlciBsb2NhbCBlZGl0cylgKVxuICAgICAgY29uc3QgdGljayA9ICgpID0+IHN5bmNPbmNlKHJvb3QsIHJlbW90ZSwgYnJhbmNoLCBsb2cpXG4gICAgICBSRUcudGltZXIgPSBzZXRJbnRlcnZhbCh0aWNrLCBldmVyeSAqIDEwMDApXG4gICAgICBSRUcudGltZXIudW5yZWY/LigpXG4gICAgICB0aWNrKClcbiAgICB9LFxuICB9XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQWVBLFNBQVMsZ0JBQUFBLGVBQWMsY0FBQUMsYUFBWSxlQUFBQyxjQUFhLFlBQUFDLGlCQUFnQjtBQUNoRSxTQUFTLFdBQUFDLFVBQVMsV0FBQUMsVUFBUyxRQUFBQyxPQUFNLGdCQUFnQjtBQUUxQyxTQUFTLFNBQVMsTUFBTTtBQUM3QixTQUFPSixhQUFZSSxNQUFLLE1BQU0seUJBQXlCLENBQUMsRUFBRSxPQUFPLENBQUMsTUFBTSxFQUFFLFNBQVMsT0FBTyxDQUFDLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxRQUFRLFdBQVcsRUFBRSxDQUFDLEVBQUUsS0FBSztBQUN6STtBQUtBLFNBQVMsWUFBWSxHQUFHO0FBQ3RCLGFBQVcsUUFBUSxDQUFDLEdBQUcsSUFBSSxPQUFPLElBQUksUUFBUSxJQUFJLFFBQVEsSUFBSSxTQUFTQSxNQUFLLEdB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O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQStENUIsTUFBTTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBZ05SLE1BQU0sWUFBWSxFQUFFO0FBQUE7QUFBQTtBQUd0QjtBQXdCQSxTQUFTLE9BQU87QUFDZCxRQUFNLE1BQU0sZ0JBQWdCO0FBQzVCLFFBQU0sZUFBZSxLQUFLSixPQUFNLFVBQVUsSUFBSSxNQUFNLGVBQWU7QUFDbkUsTUFBSSxDQUFDQyxZQUFXLFlBQVksR0FBRztBQUFFLFlBQVEsTUFBTSw4QkFBOEIsWUFBWSxvQ0FBK0I7QUFBRyxZQUFRLEtBQUssQ0FBQztBQUFBLEVBQUU7QUFDM0ksUUFBTSxXQUFXLEtBQUssTUFBTUUsY0FBYSxjQUFjLE1BQU0sQ0FBQztBQUM5RCxRQUFNLFVBQVUsZ0JBQWdCO0FBQ2hDLFFBQU0sT0FBTyxjQUFjLFVBQVUsRUFBRSxNQUFNLFNBQVMsT0FBTyxJQUFJLE9BQU8sTUFBTSxRQUFRLElBQUksTUFBTSxVQUFVLElBQUksVUFBVSxPQUFPLElBQUksT0FBTyxZQUFZLElBQUksWUFBWSxlQUFlLElBQUksZUFBZSxVQUFVLElBQUksVUFBVSxRQUFRLENBQUM7QUFDek8sUUFBTSxRQUFRLFFBQVEsVUFBVSxNQUFNLE9BQU87QUFDN0MsUUFBTSxZQUFZLE1BQU0sT0FBTyxDQUFDLEdBQUcsTUFBTSxJQUFJLEVBQUUsRUFBRSxRQUFRLENBQUM7QUFDMUQsUUFBTSxhQUFhLE1BQU0sT0FBTyxDQUFDLEdBQUcsTUFBTSxJQUFJLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxNQUFNLEtBQUssRUFBRSxLQUFLLEVBQUUsR0FBRyxTQUFTLElBQUksQ0FBQyxHQUFHLENBQUM7QUFDdEcsUUFBTSxhQUFhLE1BQU0sT0FBTyxDQUFDLEdBQUcsTUFBTSxJQUFJLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxNQUFNLEtBQUssRUFBRSxLQUFLLElBQUksTUFBTSxFQUFFLE1BQU0sQ0FBQyxHQUFHLE9BQU8sT0FBSyxFQUFFLEVBQUUsRUFBRSxRQUFRLENBQUMsR0FBRyxDQUFDO0FBS3BJLFFBQU0sS0FBSyxRQUFRLEtBQUssUUFBUSxPQUFPO0FBQ3ZDLFFBQU0sU0FBUyxNQUFNLEtBQUssUUFBUSxLQUFLLEtBQUssQ0FBQyxJQUFJRSxTQUFRLFFBQVEsS0FBSyxLQUFLLENBQUMsQ0FBQyxJQUFJO0FBQ2pGLE1BQUksQ0FBQyxRQUFRO0FBQ1gsWUFBUSxJQUFJLDJHQUFzRztBQUNsSCxZQUFRLElBQUksZ0hBQWdIO0FBQzVIO0FBQUEsRUFDRjtBQUNBLE1BQUksV0FBV0EsU0FBUUwsT0FBTSxRQUFRLEtBQUssT0FBTyxXQUFXSyxTQUFRTCxPQUFNLFFBQVEsSUFBSSxHQUFHLEdBQUc7QUFDMUYsWUFBUSxNQUFNLDJGQUFzRjtBQUFHLFlBQVEsS0FBSyxDQUFDO0FBQUEsRUFDdkg7QUFDQSxRQUFNLE1BQU07QUFDWixZQUFVLEtBQUssRUFBRSxXQUFXLEtBQUssQ0FBQztBQUNsQyxnQkFBYyxLQUFLLEtBQUssWUFBWSxHQUFHLElBQUk7QUFDM0MsVUFBUSxJQUFJLHNCQUFzQixHQUFHLDRDQUF1QyxLQUFLLFNBQVMsTUFBTSxRQUFRLENBQUMsQ0FBQyxZQUFTLE1BQU0sTUFBTSxtQkFBZ0IsU0FBUyxvQkFBaUIsVUFBVSxxQkFBa0IsVUFBVSx1REFBdUQ7QUFDeFE7QUFFQSxJQUFJLFFBQVEsS0FBSyxDQUFDLEtBQUtNLDhDQUFvQixjQUFjLFFBQVEsS0FBSyxDQUFDLENBQUMsRUFBRSxLQUFNLE1BQUs7OztBRTlxQnJGLFNBQVMsZ0JBQUFDLHFCQUFvQjtBQUM3QixTQUFTLFFBQUFDLGFBQVk7QUFFckIsSUFBTSxVQUFVLENBQUMsZ0JBQWdCLGVBQWUsYUFBYSxVQUFVO0FBcUJoRSxJQUFNLGFBQWEsQ0FBQyxRQUFRLFFBQVE7QUFhcEMsSUFBTSxTQUFTLENBQUMsZ0JBQWdCLGdCQUFnQjtBQUVoRCxTQUFTLGdCQUFnQixLQUFLLGFBQWE7QUFDaEQsTUFBSTtBQUNGLFVBQU0sT0FBTyxLQUFLLE1BQU1DLGNBQWFDLE1BQUssS0FBSyxHQUFHLFdBQVcsWUFBWSxHQUFHLE1BQU0sQ0FBQztBQUNuRixVQUFNLFNBQVMsTUFBTSxRQUFRO0FBRTdCLFVBQU0sT0FBTyxDQUFDLE1BQU0sT0FBTyxNQUFNLE9BQU8sTUFBTSxXQUFXLEVBQUUsS0FBSyxDQUFDLE1BQU0sT0FBTyxNQUFNLFlBQVksRUFBRSxLQUFLLENBQUM7QUFDeEcsV0FBTztBQUFBLE1BQ0wsT0FBTyxNQUFNLFVBQVUsZUFBZSxlQUFlO0FBQUEsTUFDckQsT0FBTyxNQUFNLFVBQVU7QUFBQSxNQUN2QixRQUFRLFFBQVEsU0FBUyxNQUFNLElBQUksRUFBRSxPQUFPLElBQUk7QUFBQSxNQUNoRCxPQUFPLE9BQU8sS0FBSyxLQUFLLElBQUk7QUFBQTtBQUFBLE1BRTVCLFNBQVMsTUFBTSxRQUFRLE1BQU0sT0FBTyxJQUFJLEtBQUssUUFBUSxPQUFPLENBQUMsTUFBTSxPQUFPLE1BQU0sUUFBUSxJQUFJO0FBQUEsTUFDNUYsWUFBWSxXQUFXLFNBQVMsTUFBTSxVQUFVLElBQUksS0FBSyxhQUFhO0FBQUE7QUFBQTtBQUFBLE1BR3RFLG1CQUFtQixNQUFNLGVBQWUsVUFBYSxXQUFXLFNBQVMsTUFBTSxVQUFVLElBQ3JGLE9BQ0EsT0FBTyxLQUFLLFVBQVU7QUFBQSxNQUMxQixRQUFRLE9BQU8sU0FBUyxNQUFNLE1BQU0sSUFBSSxLQUFLLFNBQVM7QUFBQSxJQUN4RDtBQUFBLEVBQ0YsUUFBUTtBQUFFLFdBQU8sRUFBRSxPQUFPLGdCQUFnQixPQUFPLE9BQU8sUUFBUSxNQUFNLE9BQU8sSUFBSSxTQUFTLE1BQU0sWUFBWSxRQUFRLG1CQUFtQixNQUFNLFFBQVEsS0FBSztBQUFBLEVBQUU7QUFDOUo7QUFHTyxTQUFTLGtCQUFrQixLQUFLLGFBQWE7QUFDbEQsUUFBTSxJQUFJLGdCQUFnQixLQUFLLFdBQVc7QUFHMUMsU0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLEdBQUksRUFBRSxlQUFlLFdBQVcsRUFBRSxZQUFZLFNBQVMsSUFBSSxDQUFDLEdBQUksR0FBSSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsTUFBTSxJQUFJLENBQUMsR0FBSSxHQUFJLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxRQUFRLElBQUksQ0FBQyxHQUFJLEdBQUksRUFBRSxRQUFRLEVBQUUsT0FBTyxLQUFLLElBQUksQ0FBQyxHQUFJLEdBQUksRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLE9BQU8sSUFBSSxDQUFDLEdBQUksR0FBSSxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsT0FBTyxJQUFJLENBQUMsRUFBRztBQUMzUztBQUdPLElBQU0sY0FBYyxDQUFDLGFBQWMsU0FBUyxLQUFLLENBQUMsTUFBTSxFQUFFLFVBQVUsWUFBWSxJQUFJLGVBQWU7QUFRbkcsSUFBTSxtQkFBbUIsQ0FBQyxhQUFjLFNBQVMsS0FBSyxDQUFDLE1BQU0sRUFBRSxlQUFlLFFBQVEsSUFBSSxXQUFXOzs7QUozRDVHLElBQU0saUJBQWlCO0FBQUEsRUFDckIsU0FBUztBQUFBLEVBQW1DLFlBQVk7QUFBQSxFQUN4RCxPQUFPO0FBQUEsRUFBa0MsUUFBUTtBQUFBLEVBQTJCLFFBQVE7QUFBQSxFQUNwRixRQUFRO0FBQUEsRUFBNkIsU0FBUztBQUFBLEVBQTRCLFFBQVE7QUFBQSxFQUNsRixRQUFRO0FBQUEsRUFBYSxTQUFTO0FBQUEsRUFBYyxRQUFRO0FBQUEsRUFBYyxTQUFTO0FBQUEsRUFBYyxRQUFRO0FBQUEsRUFDakcsVUFBVTtBQUFBLEVBQWMsU0FBUztBQUFBLEVBQWEsUUFBUTtBQUN4RDtBQUNPLFNBQVMsZ0JBQWdCLEtBQUssT0FBTyxXQUFXO0FBQ3JELFFBQU0sU0FBUyxDQUFDLE1BQU1DLFlBQVcsQ0FBQyxLQUFLQyxVQUFTLENBQUMsRUFBRSxPQUFPO0FBTTFELFFBQU0sU0FBU0MsU0FBUSxNQUFNLFFBQVEsR0FBRztBQUN4QyxNQUFJLE9BQU8sTUFBTSxFQUFHLFFBQU87QUFHM0IsUUFBTSxVQUFVQSxTQUFRLE1BQU0sVUFBVSxXQUFXLFVBQVUsR0FBRztBQUNoRSxNQUFJLE9BQU8sT0FBTyxFQUFHLFFBQU87QUFDNUIsUUFBTSxXQUFXQSxTQUFRLE1BQU0sZ0JBQWdCO0FBQy9DLGFBQVcsUUFBUUMsYUFBWSxRQUFRLEdBQUc7QUFDeEMsUUFBSSxLQUFLLFdBQVcsR0FBRyxLQUFLLEtBQUssV0FBVyxHQUFHLEVBQUc7QUFDbEQsVUFBTSxPQUFPRCxTQUFRLFVBQVUsTUFBTSxRQUFRLEdBQUc7QUFDaEQsUUFBSSxPQUFPLElBQUksRUFBRyxRQUFPO0FBQUEsRUFDM0I7QUFDQSxTQUFPO0FBQ1Q7QUFZQSxTQUFTLGFBQWEsUUFBUSxTQUFTO0FBQ3JDLE1BQUk7QUFDRixVQUFNLE9BQU8sS0FBSyxNQUFNRSxjQUFhRixTQUFRLFdBQVcsa0JBQWtCLFFBQVEsR0FBRyxPQUFPLFlBQVksR0FBRyxNQUFNLENBQUM7QUFDbEgsV0FBTyxNQUFNLFFBQVEsTUFBTSxRQUFRLElBQUksS0FBSyxTQUFTLElBQUksTUFBTSxFQUFFLE9BQU8sT0FBTyxJQUFJLENBQUM7QUFBQSxFQUN0RixRQUFRO0FBQUUsV0FBTyxDQUFDO0FBQUEsRUFBRTtBQUN0QjtBQUVPLFNBQVMsYUFBYSxLQUFLO0FBQ2hDLFFBQU0sU0FBUyxDQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFhdkMsUUFBTSxPQUFPLElBQUksVUFBVSxhQUFhLE1BQU0sSUFBSSxrQkFBa0IsRUFBRSxLQUFLLEdBQUc7QUFLOUUsTUFBSSxRQUFRLG9CQUFJLElBQUk7QUFHcEIsTUFBSTtBQUNGLFVBQU0sTUFBTSxLQUFLLE1BQU1FLGNBQWFGLFNBQVEsV0FBVyxrQ0FBa0MsR0FBRyxNQUFNLENBQUM7QUFDbkcsUUFBSSxNQUFNLFFBQVEsSUFBSSxhQUFhLEVBQUcsU0FBUSxJQUFJLElBQUksSUFBSSxjQUFjLElBQUksTUFBTSxDQUFDO0FBQUEsRUFDckYsUUFBUTtBQUFBLEVBQWdDO0FBQ3hDLFFBQU0sVUFBVSxDQUFDLEdBQUcsR0FBRyxFQUFFLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxJQUFJLEVBQUUsTUFBTSxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsTUFBTSxFQUFFLE9BQU8sY0FBYyxFQUFFLE1BQU0sQ0FBQyxFQUFFLElBQUksQ0FBQyxNQUFNO0FBQ3ZILFVBQU0sWUFBWSxtQkFBbUIsRUFBRSxNQUFNO0FBQzdDLFVBQU0sVUFBVSxvQkFBSSxJQUFJO0FBQ3hCLFVBQU0sU0FBUyxvQkFBSSxJQUFJO0FBQ3ZCLGVBQVcsTUFBTSxFQUFFLE9BQU87QUFDeEIsVUFBSSxDQUFDLFFBQVEsSUFBSSxHQUFHLE9BQU8sRUFBRyxTQUFRLElBQUksR0FBRyxTQUFTLENBQUMsQ0FBQztBQUN4RCxVQUFJLENBQUMsT0FBTyxJQUFJLEdBQUcsT0FBTyxFQUFHLFFBQU8sSUFBSSxHQUFHLFNBQVMsR0FBRyxJQUFJO0FBQzNELFVBQUksR0FBRyxTQUFTLGdCQUFpQixTQUFRLElBQUksR0FBRyxPQUFPLEVBQUUsS0FBSyxFQUFFO0FBQUEsSUFDbEU7QUFDQSxVQUFNLFdBQVcsQ0FBQyxHQUFHLFFBQVEsS0FBSyxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxZQUFZO0FBQzNELFlBQU0sSUFBSTtBQUFBLFFBQ1I7QUFBQSxRQUFTLE1BQU0sR0FBRyxPQUFPO0FBQUEsUUFBUSxhQUFhO0FBQUEsUUFBSSxTQUFTLEVBQUU7QUFBQSxRQUM3RCxNQUFNLE9BQU8sSUFBSSxPQUFPLEtBQUs7QUFBQSxRQUM3QixHQUFHLGtCQUFrQkEsU0FBUSxXQUFXLGtCQUFrQixFQUFFLE1BQU0sR0FBRyxPQUFPO0FBQUE7QUFBQSxRQUM1RSxXQUFXLEtBQUssRUFBRSxRQUFRLE9BQU87QUFBQSxRQUFHO0FBQUEsUUFDcEMsT0FBTztBQUFBLFVBQ0wsUUFBUSxPQUFPLEtBQUssRUFBRSxNQUFNLElBQUksT0FBTyxhQUFhO0FBQUEsVUFDcEQsUUFBUSxrQkFBa0IsRUFBRSxNQUFNLElBQUksRUFBRSxNQUFNO0FBQUEsR0FBb0IsRUFBRSxHQUFHLG9CQUFvQixLQUFLLFVBQVUsRUFBRSxTQUFTLElBQUkscUJBQXFCLFdBQVcsY0FBYyxDQUFDLENBQUMsT0FBTyxFQUFFLEdBQUc7QUFBQSxRQUN2TDtBQUFBLE1BQ0Y7QUFDQSxZQUFNLFlBQVksUUFBUSxJQUFJLE9BQU8sRUFBRSxJQUFJLENBQUMsUUFBUTtBQUFBLFFBQ2xELElBQUksR0FBRztBQUFBLFFBQUksT0FBTyxHQUFHO0FBQUEsUUFBTyxZQUFZLEdBQUcsY0FBYztBQUFBLFFBQ3pELE9BQU8sRUFBRSxTQUFTLEdBQUksR0FBRyxTQUFTLENBQUMsRUFBRztBQUFBLFFBQUcsU0FBUyxFQUFFO0FBQUEsUUFDcEQsV0FBVyxLQUFLLEVBQUUsUUFBUSxTQUFTLEdBQUcsRUFBRTtBQUFBLFFBQ3hDLE9BQU8sRUFBRSxRQUFRLE9BQU8sS0FBSyxFQUFFLE1BQU0sSUFBSSxPQUFPLElBQUksR0FBRyxFQUFFLGFBQWEsRUFBRTtBQUFBLE1BQzFFLEVBQUU7QUFDRixVQUFJLFVBQVUsT0FBUSxHQUFFLFlBQVk7QUFDcEMsYUFBTztBQUFBLElBQ1QsQ0FBQztBQUtELFVBQU0sV0FBVyxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsR0FBRyxRQUFRLEtBQUssQ0FBQyxFQUFFLFFBQVEsQ0FBQyxZQUFZLGFBQWEsRUFBRSxRQUFRLE9BQU8sQ0FBQyxDQUFDLENBQUM7QUFDdkcsV0FBTyxFQUFFLFFBQVEsRUFBRSxRQUFRLFdBQVcsV0FBVyxJQUFJLFVBQVUsQ0FBQyxFQUFFLEdBQUcsR0FBRyxPQUFPLFlBQVksUUFBUSxHQUFHLEdBQUksaUJBQWlCLFFBQVEsTUFBTSxXQUFXLEVBQUUsWUFBWSxTQUFTLElBQUksQ0FBQyxHQUFJLEdBQUksU0FBUyxTQUFTLEVBQUUsU0FBUyxJQUFJLENBQUMsR0FBSSxTQUFTO0FBQUEsRUFDek8sQ0FBQztBQUNELFNBQU87QUFBQSxJQUNMLFFBQVE7QUFBQSxJQUF3QixlQUFlO0FBQUEsSUFBMEMsV0FBVztBQUFBLElBQ3BHLGFBQWEsUUFBUTtBQUFBLElBQVEsY0FBYyxRQUFRLE9BQU8sQ0FBQyxHQUFHLE1BQU0sSUFBSSxFQUFFLFNBQVMsUUFBUSxDQUFDO0FBQUEsSUFBRztBQUFBLEVBQ2pHO0FBQ0Y7QUFvQ08sU0FBUyxZQUFZLE1BQU0sV0FBVyxXQUFXO0FBQ3RELE1BQUksQ0FBQyxLQUFLLFNBQVMsYUFBYSxFQUFHLFFBQU87QUFDMUMsTUFBSSxPQUFPLEtBQUssTUFBTSxHQUFHLENBQUMsY0FBYyxNQUFNLEVBQUUsTUFBTSxHQUFHLEVBQUUsT0FBTyxPQUFPO0FBQ3pFLE1BQUksS0FBSyxDQUFDLE1BQU0sU0FBVSxRQUFPLEtBQUssTUFBTSxDQUFDO0FBRzdDLE1BQUksS0FBSyxTQUFTLEtBQUssS0FBSyxTQUFTLEVBQUcsUUFBTztBQUkvQyxhQUFXLEtBQUssTUFBTTtBQUNwQixRQUFJLElBQUk7QUFDUixRQUFJO0FBQUUsVUFBSSxtQkFBbUIsQ0FBQztBQUFBLElBQUUsUUFBUTtBQUFFLGFBQU87QUFBQSxJQUFHO0FBQ3BELFFBQUksQ0FBQyxLQUFLLE1BQU0sT0FBTyxNQUFNLFFBQVEsRUFBRSxTQUFTLEdBQUcsS0FBSyxFQUFFLFNBQVMsSUFBSSxFQUFHLFFBQU87QUFBQSxFQUNuRjtBQUNBLFNBQU8sYUFBYSxLQUFLLEtBQUssR0FBRztBQUNuQztBQUVPLFNBQVMsaUJBQWlCLFFBQVEsSUFBSTtBQUszQyxRQUFNLE9BQU8sTUFBTTtBQUNqQixVQUFNLE1BQU0sZ0JBQWdCO0FBQzVCLFdBQU8sY0FBYyxhQUFhLG9CQUFvQixDQUFDLEdBQUc7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLE1BV3hELE1BQU07QUFBQSxNQUFPLE9BQU8sSUFBSTtBQUFBLE1BQU8sTUFBTTtBQUFBLE1BQXFCLFVBQVUsSUFBSTtBQUFBLE1BQVUsT0FBTyxTQUFTLElBQUk7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsTUFZdEcsWUFBWSxJQUFJO0FBQUEsTUFBWSxlQUFlO0FBQUEsTUFBVyxVQUFVLElBQUk7QUFBQSxJQUN0RSxDQUFDO0FBQUEsRUFDSDtBQUNBLFFBQU0sT0FBTyxDQUFDLEtBQUssTUFBTSxTQUFTLFFBQVE7QUFDeEMsUUFBSSxhQUFhO0FBQ2pCLFFBQUksVUFBVSxnQkFBZ0IsaUNBQWlDO0FBQy9ELFFBQUksVUFBVSxpQkFBaUIsVUFBVTtBQUN6QyxRQUFJLElBQUksS0FBSyxVQUFVLElBQUksQ0FBQztBQUFBLEVBQzlCO0FBQ0EsU0FBTztBQUFBLElBQ0wsTUFBTTtBQUFBLElBQ04sT0FBTztBQUFBLElBQ1AsZ0JBQWdCLFFBQVE7QUFDdEIsYUFBTyxZQUFZLElBQUksQ0FBQyxLQUFLLEtBQUssU0FBUztBQUN6QyxjQUFNLFdBQVcsSUFBSSxPQUFPLElBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQztBQUk1QyxZQUFJLFdBQVc7QUFDZixZQUFJO0FBQUUscUJBQVcsbUJBQW1CLE9BQU87QUFBQSxRQUFFLFFBQVE7QUFBQSxRQUFpQjtBQUN0RSxZQUFJLG9FQUFvRSxLQUFLLFFBQVEsR0FBRztBQUFFLGNBQUksYUFBYTtBQUFLLGlCQUFPLElBQUksSUFBSTtBQUFBLFFBQUU7QUFPakksWUFBSSxXQUFXO0FBQ2YsWUFBSTtBQUFFLHFCQUFXLGdCQUFnQixHQUFHLFFBQVE7QUFBQSxRQUFTLFFBQVE7QUFBQSxRQUF5QjtBQUN0RixjQUFNLFlBQVksWUFBWSxTQUFTLFFBQVE7QUFDL0MsY0FBTSxPQUFPLGFBQWE7QUFDMUIsWUFBSSxVQUFXLEtBQUksTUFBTSxhQUFhLElBQUksT0FBTyxJQUFJLE1BQU0sUUFBUSxNQUFNO0FBS3pFLGNBQU0sT0FBTyxtRUFBbUUsS0FBSyxPQUFPO0FBQzVGLFlBQUksUUFBUSxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLEtBQUssQ0FBQyxNQUFNLFdBQVc7QUFDckUsZ0JBQU0sT0FBT0EsU0FBUSxXQUFXLFVBQVUsVUFBVSxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUMsSUFBSSxLQUFLO0FBQzVFLGNBQUlGLFlBQVcsSUFBSSxHQUFHO0FBQ3BCLGdCQUFJLFVBQVUsZ0JBQWdCLGdDQUFnQztBQUM5RCxnQkFBSSxVQUFVLGlCQUFpQixVQUFVO0FBQ3pDLG1CQUFPLElBQUksSUFBSUksY0FBYSxJQUFJLENBQUM7QUFBQSxVQUNuQztBQUNBLGNBQUlKLFlBQVdFLFNBQVEsV0FBVyxrQkFBa0IsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHO0FBQzdELGdCQUFJLGFBQWE7QUFDakIsZ0JBQUksVUFBVSxnQkFBZ0IsMkJBQTJCO0FBQ3pELG1CQUFPLElBQUksSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLHFFQUFxRSxLQUFLLENBQUMsQ0FBQyxrQ0FBa0M7QUFBQSxVQUN6STtBQUFBLFFBQ0Y7QUFlQSxjQUFNLFlBQVksc0NBQXNDLEtBQUssSUFBSTtBQUNqRSxjQUFNLGNBQWMsS0FBSyxXQUFXLFVBQVUsSUFBSSxhQUM5QyxLQUFLLFdBQVcsMkJBQTJCLElBQUksOEJBQy9DLEtBQUssV0FBVyxJQUFJLFFBQVEsVUFBVSxJQUFJLElBQUksUUFBUSxhQUN0RCxZQUFZLFVBQVUsQ0FBQyxJQUFJO0FBQy9CLFlBQUksYUFBYTtBQUNmLGNBQUksTUFBTTtBQUNWLGNBQUk7QUFBRSxrQkFBTSxtQkFBbUIsS0FBSyxNQUFNLFlBQVksTUFBTSxDQUFDO0FBQUEsVUFBRSxRQUFRO0FBQUUsa0JBQU07QUFBQSxVQUFHO0FBQ2xGLGNBQUksQ0FBQyxPQUFPLElBQUksTUFBTSxHQUFHLEVBQUUsU0FBUyxJQUFJLEdBQUc7QUFBRSxnQkFBSSxhQUFhO0FBQUssbUJBQU8sSUFBSSxJQUFJLGdCQUFnQjtBQUFBLFVBQUU7QUFDcEcsZ0JBQU0sT0FBTyxnQkFBZ0IsR0FBRztBQUNoQyxjQUFJLENBQUMsS0FBTSxRQUFPLEtBQUssS0FBSyxFQUFFLE9BQU8sbUJBQW1CLE9BQU8sS0FBSyxRQUFRLENBQUMsVUFBVSxTQUFTLFlBQVksU0FBUyx3QkFBd0IsRUFBRSxHQUFHLEdBQUc7QUFDckosY0FBSSxhQUFhO0FBQ2pCLGNBQUksVUFBVSxnQkFBZ0IsZUFBZSxRQUFRLElBQUksRUFBRSxZQUFZLENBQUMsS0FBSywwQkFBMEI7QUFDdkcsY0FBSSxVQUFVLGlCQUFpQixVQUFVO0FBQ3pDLGlCQUFPLElBQUksSUFBSUUsY0FBYSxJQUFJLENBQUM7QUFBQSxRQUNuQztBQU1BLFlBQUksU0FBUyxjQUFjO0FBQ3pCLGdCQUFNQyxPQUFNLElBQUksTUFBTSxVQUFVLE9BQU8sR0FBRyxFQUFFLEtBQUssV0FBVyxVQUFVLE9BQU8sQ0FBQyxFQUFFLE9BQU8sS0FBSztBQUM1RixnQkFBTSxNQUFNQSxLQUFJLGFBQWEsTUFBTTtBQUNuQyxnQkFBTSxRQUFRQSxLQUFJLFVBQVUsZUFBZSx3QkFBd0IsTUFBTSxXQUFXLGtCQUFrQixZQUFZLGtCQUFrQixjQUFjLElBQUksV0FBVztBQUNqSyxjQUFJLGFBQWEsTUFBTSxNQUFNO0FBQzdCLGNBQUksVUFBVSxnQkFBZ0IsMkJBQTJCO0FBQ3pELGNBQUksVUFBVSxpQkFBaUIsVUFBVTtBQUN6QyxpQkFBTyxJQUFJLEtBQUssT0FBTyxhQUFhLFFBQVEsSUFBSTtBQUFBLFFBQ2xEO0FBQ0EsWUFBSSxTQUFTLHFDQUFxQyxTQUFTLG1DQUFtQztBQUM1RixjQUFJO0FBQ0osY0FBSTtBQUFFLGtCQUFNLG9CQUFvQjtBQUFBLFVBQUUsU0FBUyxHQUFHO0FBQUUsbUJBQU8sS0FBSyxLQUFLLEVBQUUsT0FBTyxPQUFPLENBQUMsRUFBRSxHQUFHLEdBQUc7QUFBQSxVQUFFO0FBQzVGLGlCQUFPLEtBQUssS0FBSyxLQUFLLFNBQVMsZ0JBQWdCLElBQUksYUFBYSxHQUFHLElBQUksR0FBRztBQUFBLFFBQzVFO0FBT0EsWUFBSSxLQUFLLFdBQVcsVUFBVSxHQUFHO0FBQy9CLGdCQUFNLFFBQVEsS0FBSyxNQUFNLFdBQVcsTUFBTSxFQUFFLE1BQU0sR0FBRyxFQUFFLE9BQU8sT0FBTyxFQUFFLElBQUksT0FBSztBQUM5RSxnQkFBSTtBQUFFLHFCQUFPLG1CQUFtQixDQUFDO0FBQUEsWUFBRSxRQUFRO0FBQUUscUJBQU87QUFBQSxZQUFHO0FBQUEsVUFDekQsQ0FBQztBQUNELGdCQUFNLENBQUMsUUFBUSxTQUFTLFFBQVEsSUFBSTtBQUVwQyxjQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsTUFBTSxLQUFLLE9BQUssQ0FBQyxLQUFLLEVBQUUsU0FBUyxJQUFJLEtBQUssRUFBRSxTQUFTLEdBQUcsQ0FBQyxHQUFHO0FBQ3JGLGdCQUFJLGFBQWE7QUFBSyxtQkFBTyxJQUFJLElBQUksZUFBZTtBQUFBLFVBQ3REO0FBQ0EsY0FBSTtBQUNKLGNBQUk7QUFBRSxrQkFBTSxvQkFBb0I7QUFBQSxVQUFFLFNBQVMsR0FBRztBQUFFLG1CQUFPLEtBQUssS0FBSyxFQUFFLE9BQU8sT0FBTyxDQUFDLEVBQUUsR0FBRyxHQUFHO0FBQUEsVUFBRTtBQUM1RixnQkFBTSxRQUFRLElBQUksS0FBSyxPQUFLLEVBQUUsV0FBVyxNQUFNO0FBQy9DLGNBQUksQ0FBQyxPQUFPO0FBSVYsa0JBQU0sUUFBUSxJQUFJLEtBQUssT0FBSyxFQUFFLFdBQVcsT0FBTztBQUNoRCxrQkFBTSxPQUFPLFFBQ1QscUNBQXFDLE1BQU0sTUFBTSxJQUFJLE1BQU0sUUFBUSxDQUFDLEdBQUcsV0FBVyxNQUFNLE1BQU0sS0FDOUY7QUFDSixtQkFBTyxLQUFLLEtBQUssRUFBRSxPQUFPLGtCQUFrQixRQUFRLEtBQUssR0FBRyxHQUFHO0FBQUEsVUFDakU7QUFDQSxnQkFBTSxNQUFNLE1BQU07QUFHbEIsY0FBSSxVQUFVLENBQUM7QUFDZixjQUFJO0FBQUUsc0JBQVUsZ0JBQWdCLEtBQUssQ0FBQztBQUFBLFVBQUUsUUFBUTtBQUFFLHNCQUFVLENBQUM7QUFBQSxVQUFFO0FBQy9ELGdCQUFNLFVBQVUsU0FBUyxRQUFRLFNBQVM7QUFDMUMsZ0JBQU0sVUFBVSxRQUFRLGNBQWM7QUFLdEMsZ0JBQU0sS0FBSyxLQUFLLFVBQVUsV0FBVyxFQUFFLFNBQVMsWUFBWSxVQUFVLFlBQVksVUFBVSxJQUFJLEVBQUUsU0FBUyxZQUFZLFVBQVUsQ0FBQztBQUlsSSxnQkFBTSxjQUFjLE1BQU0sU0FBUyxDQUFDLEdBQUc7QUFBQSxZQUNyQyxRQUFNLEdBQUcsWUFBWSxXQUFXLEdBQUcsU0FBUztBQUFBLFVBQXFCO0FBQ25FLGNBQUksYUFBYTtBQUNqQixjQUFJLFVBQVUsZ0JBQWdCLDBCQUEwQjtBQUN4RCxjQUFJLFVBQVUsaUJBQWlCLFVBQVU7QUFDekMsaUJBQU8sSUFBSSxJQUFJO0FBQUEsWUFDYjtBQUFBLFlBQ0Esd0RBQXdELE1BQU0sU0FBTSxPQUFPO0FBQUEsWUFDM0U7QUFBQSxZQUNBO0FBQUEsWUFDQSxVQUFVLDRCQUE0QixLQUFLLFVBQVUsT0FBTyxDQUFDLGVBQWU7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxZQVU1RSxVQUFVLGtDQUFrQyxLQUFLLFVBQVUsT0FBTyxDQUFDLGVBQWU7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFlBb0JsRixhQUNJLG1IQUtHLEdBQUcsMERBQ04sdUVBQ0csR0FBRztBQUFBLFlBQ1Y7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLFlBUUEsSUFBSSxHQUFHLGtEQUFrRCxFQUFFLE9BQU8sR0FBRztBQUFBLFlBQ3JFLDhDQUE4QyxNQUFNO0FBQUEsWUFDcEQ7QUFBQSxVQUNGLEVBQUUsT0FBTyxPQUFPLEVBQUUsS0FBSyxJQUFJLENBQUM7QUFBQSxRQUM5QjtBQXFCQSxZQUFJLFNBQVMsT0FBTyxTQUFTLGVBQWU7QUFPMUMsY0FBSSxTQUFTLENBQUM7QUFDZCxjQUFJO0FBQUUscUJBQVMsZ0JBQWdCLEtBQUssQ0FBQztBQUFBLFVBQUUsUUFBUTtBQUFFLHFCQUFTLENBQUM7QUFBQSxVQUFFO0FBQzdELGdCQUFNLFNBQVMsU0FBUyxPQUFPLFNBQVM7QUFDeEMsZ0JBQU0sYUFBYSxPQUFPLGNBQWM7QUFDeEMsY0FBSSxhQUFhO0FBQ2pCLGNBQUksVUFBVSxnQkFBZ0IsMEJBQTBCO0FBQ3hELGNBQUksVUFBVSxpQkFBaUIsVUFBVTtBQUN6QyxpQkFBTyxJQUFJLElBQUk7QUFBQSxZQUNiO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxZQUNBLFVBQVUsU0FBUztBQUFBLFlBQ25CO0FBQUE7QUFBQTtBQUFBLFlBR0EsU0FBUyw0QkFBNEIsS0FBSyxVQUFVLE1BQU0sQ0FBQyxlQUFlO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxZQUsxRSxhQUFhLGtDQUFrQyxLQUFLLFVBQVUsVUFBVSxDQUFDLGVBQWU7QUFBQTtBQUFBO0FBQUE7QUFBQSxZQUl4RjtBQUFBLFlBQ0E7QUFBQSxZQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxZQVdBO0FBQUEsWUFDQTtBQUFBLFlBQ0E7QUFBQSxVQUNGLEVBQUUsT0FBTyxPQUFPLEVBQUUsS0FBSyxJQUFJLENBQUM7QUFBQSxRQUM5QjtBQUVBLFlBQUksU0FBUyxnQkFBZ0IsU0FBUyxjQUFlLFFBQU8sS0FBSztBQUNqRSxZQUFJO0FBQ0osWUFBSTtBQUFFLGlCQUFPLEtBQUs7QUFBQSxRQUFFLFNBQ2IsR0FBRztBQUFFLGtCQUFRLE1BQU0sb0JBQW9CLEtBQUssRUFBRSxRQUFRLEVBQUUsUUFBUSxDQUFDLEVBQUU7QUFBRyxpQkFBTyxLQUFLO0FBQUEsUUFBRTtBQUMzRixZQUFJLGFBQWE7QUFDakIsWUFBSSxVQUFVLGdCQUFnQiwwQkFBMEI7QUFDeEQsWUFBSSxJQUFJLElBQUk7QUFBQSxNQUNkLENBQUM7QUFBQSxJQUNIO0FBQUEsRUFDRjtBQUNGOzs7QUtsZkEsU0FBUyxXQUFBQyxVQUFTLFdBQUFDLFVBQVMsV0FBVztBQUN0QyxTQUFTLGlCQUFBQyxzQkFBcUI7QUFoQnlOLElBQU1DLDRDQUEyQztBQWtCeFMsSUFBTUMsUUFBT0MsU0FBUUMsU0FBUUMsZUFBY0oseUNBQWUsQ0FBQyxHQUFHLElBQUk7QUFDbEUsSUFBTSxlQUFlLENBQUMsV0FBVyxnQkFBZ0IsRUFBRSxJQUFJLE9BQUtFLFNBQVFELE9BQU0sQ0FBQyxJQUFJLEdBQUc7QUFDbEYsSUFBTSxNQUFNO0FBUVosSUFBTSxPQUFPO0FBT2IsU0FBUyxnQkFBZ0IsTUFBTSxNQUFNO0FBQ25DLFdBQVMsSUFBSSxNQUFNLElBQUksS0FBSyxRQUFRLEtBQUs7QUFDdkMsVUFBTSxJQUFJLEtBQUssQ0FBQztBQUNoQixRQUFJLE1BQU0sTUFBTTtBQUFFO0FBQUs7QUFBQSxJQUFTO0FBQ2hDLFFBQUksTUFBTSxJQUFLLFFBQU8sRUFBRSxLQUFLLEVBQUU7QUFDL0IsUUFBSSxNQUFNLE9BQU8sS0FBSyxJQUFJLENBQUMsTUFBTSxJQUFLLFFBQU8sRUFBRSxRQUFRLHFDQUFnQyxJQUFJLEVBQUU7QUFBQSxFQUMvRjtBQUNBLFNBQU8sRUFBRSxRQUFRLGlDQUFpQyxJQUFJLEtBQUssT0FBTztBQUNwRTtBQU9PLFNBQVMsaUJBQWlCLEtBQUs7QUFDcEMsUUFBTSxJQUFJLElBQUk7QUFDZCxNQUFJLE1BQU07QUFDVixNQUFJLFdBQVc7QUFDZixNQUFJLElBQUk7QUFDUixTQUFPLElBQUksR0FBRztBQUNaLFVBQU0sSUFBSSxJQUFJLENBQUM7QUFDZixRQUFJLE1BQU0sT0FBTyxNQUFNLEtBQUs7QUFDMUIsVUFBSSxJQUFJLElBQUk7QUFDWixhQUFPLElBQUksS0FBSyxJQUFJLENBQUMsTUFBTSxLQUFLLElBQUksQ0FBQyxNQUFNLE1BQU07QUFBRSxZQUFJLElBQUksQ0FBQyxNQUFNLEtBQU07QUFBSztBQUFBLE1BQUk7QUFDakYsVUFBSSxLQUFLLEVBQUcsUUFBTyxFQUFFLFFBQVEsNEJBQTRCO0FBQ3pELFVBQUksSUFBSSxDQUFDLE1BQU0sTUFBTTtBQUFFLGVBQU8sSUFBSSxNQUFNLEdBQUcsQ0FBQztBQUFHLFlBQUk7QUFBRztBQUFBLE1BQVM7QUFDL0QsYUFBTyxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUM7QUFBRyxVQUFJLElBQUk7QUFBRztBQUFBLElBQ3pDO0FBQ0EsUUFBSSxNQUFNLE9BQU8sSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLO0FBQ25DLFlBQU0sSUFBSSxJQUFJLFFBQVEsTUFBTSxJQUFJLENBQUM7QUFDakMsVUFBSSxJQUFJLEVBQUcsUUFBTyxFQUFFLFFBQVEsNkJBQTZCO0FBQ3pEO0FBQVksVUFBSSxJQUFJO0FBQUc7QUFBQSxJQUN6QjtBQUNBLFNBQUssTUFBTSxPQUFPLE1BQU0sUUFBUSxVQUFVLEtBQUssSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLENBQUMsTUFBTSxNQUFNLEtBQUssQ0FBQyxRQUFRLEtBQUssSUFBSSxJQUFJLENBQUMsQ0FBQyxJQUFJO0FBQzdHLFVBQUksSUFBSSxJQUFJO0FBQ1osYUFBTyxJQUFJLE1BQU0sSUFBSSxDQUFDLE1BQU0sT0FBTyxJQUFJLENBQUMsTUFBTSxLQUFPO0FBQ3JELFVBQUksSUFBSSxDQUFDLE1BQU0sT0FBTyxJQUFJLENBQUMsTUFBTSxLQUFLO0FBQUUsZUFBTyxJQUFJLE1BQU0sR0FBRyxDQUFDO0FBQUcsWUFBSTtBQUFHO0FBQUEsTUFBUztBQUNoRixZQUFNLElBQUksSUFBSSxRQUFRLEtBQUssQ0FBQztBQUM1QixVQUFJLElBQUksRUFBRyxRQUFPLEVBQUUsUUFBUSxpQ0FBaUM7QUFDN0QsYUFBTyxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUM7QUFBRyxVQUFJLElBQUk7QUFBRztBQUFBLElBQ3pDO0FBQ0EsV0FBTztBQUFHO0FBQUEsRUFDWjtBQUNBLE1BQUksV0FBVyxHQUFHO0FBQ2hCLFVBQU0sSUFBSSxRQUFRLHNCQUFzQixFQUFFO0FBQzFDLFVBQU0sSUFBSSxRQUFRLDBCQUEwQixJQUFJO0FBQUEsRUFDbEQ7QUFDQSxTQUFPLEVBQUUsS0FBSyxLQUFLLFNBQVM7QUFDOUI7QUFNTyxTQUFTLHlCQUF5QixNQUFNO0FBQzdDLFFBQU0sU0FBUyxFQUFFLE1BQU0sU0FBUyxPQUFPLFVBQVUsR0FBRyxVQUFVLEdBQUcsT0FBTyxHQUFHLFNBQVMsQ0FBQyxFQUFFO0FBQ3ZGLE1BQUksTUFBTTtBQUNWLE1BQUksT0FBTztBQUNYLE9BQUssWUFBWTtBQUNqQixNQUFJO0FBQ0osU0FBUSxJQUFJLEtBQUssS0FBSyxJQUFJLEdBQUk7QUFDNUIsVUFBTSxPQUFPLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRTtBQUM1QixVQUFNLE1BQU0sZ0JBQWdCLE1BQU0sSUFBSTtBQUN0QyxRQUFJLElBQUksUUFBUTtBQUNkLGFBQU8sUUFBUSxLQUFLLEVBQUUsTUFBTSxPQUFPLE1BQU0sRUFBRSxLQUFLLEdBQUcsUUFBUSxJQUFJLE9BQU8sQ0FBQztBQUN2RSxXQUFLLFlBQVksSUFBSTtBQUNyQjtBQUFBLElBQ0Y7QUFDQSxXQUFPO0FBQ1AsVUFBTSxXQUFXLEtBQUssTUFBTSxNQUFNLElBQUksR0FBRztBQUN6QyxVQUFNLFdBQVcsaUJBQWlCLFFBQVE7QUFDMUMsUUFBSSxTQUFTLFFBQVE7QUFDbkIsYUFBTyxRQUFRLEtBQUssRUFBRSxNQUFNLE9BQU8sTUFBTSxFQUFFLEtBQUssR0FBRyxRQUFRLFNBQVMsT0FBTyxDQUFDO0FBQUEsSUFDOUUsV0FBVyxTQUFTLFFBQVEsVUFBVTtBQUNwQyxhQUFPLEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxTQUFTO0FBQ3pDLGFBQU8sSUFBSTtBQUNYLGFBQU8sWUFBWSxTQUFTO0FBQzVCLGFBQU8sU0FBUyxTQUFTLFNBQVMsU0FBUyxJQUFJO0FBQy9DLGFBQU8sVUFBVTtBQUFBLElBQ25CO0FBQ0EsU0FBSyxZQUFZLElBQUksTUFBTTtBQUFBLEVBQzdCO0FBQ0EsTUFBSSxPQUFPLFFBQVMsUUFBTyxPQUFPLE1BQU0sS0FBSyxNQUFNLElBQUk7QUFDdkQsU0FBTztBQUNUO0FBRUEsU0FBUyxPQUFPLE1BQU0sT0FBTztBQUMzQixNQUFJLE9BQU87QUFDWCxXQUFTLElBQUksR0FBRyxJQUFJLE9BQU8sSUFBSyxLQUFJLEtBQUssQ0FBQyxNQUFNLEtBQU07QUFDdEQsU0FBTztBQUNUO0FBRUEsU0FBUyxlQUFlLElBQUk7QUFDMUIsUUFBTSxJQUFJLEdBQUcsUUFBUSxHQUFHO0FBQ3hCLE1BQUksS0FBSyxFQUFHLFFBQU87QUFDbkIsTUFBSSxFQUFFLEdBQUcsU0FBUyxNQUFNLEtBQUssR0FBRyxTQUFTLEtBQUssR0FBSSxRQUFPO0FBQ3pELFNBQU8sYUFBYSxLQUFLLFVBQVEsR0FBRyxXQUFXLElBQUksQ0FBQztBQUN0RDtBQUVPLFNBQVMsK0JBQStCO0FBQzdDLE1BQUksU0FBUztBQUNiLFFBQU0sU0FBUyxFQUFFLE9BQU8sR0FBRyxVQUFVLEdBQUcsVUFBVSxHQUFHLE9BQU8sR0FBRyxTQUFTLEVBQUU7QUFDMUUsU0FBTztBQUFBLElBQ0wsTUFBTTtBQUFBLElBQ04sT0FBTztBQUFBLElBQ1AsU0FBUztBQUFBLElBQ1QsZUFBZSxRQUFRO0FBQUUsZUFBUyxPQUFPO0FBQUEsSUFBTztBQUFBLElBQ2hELFVBQVUsTUFBTSxJQUFJO0FBQ2xCLFVBQUksQ0FBQyxlQUFlLEVBQUUsRUFBRyxRQUFPO0FBQ2hDLFlBQU0sSUFBSSx5QkFBeUIsSUFBSTtBQUN2QyxpQkFBVyxLQUFLLEVBQUUsU0FBUztBQUN6QixlQUFPO0FBQ1AsZUFBTyxLQUFLLEdBQUcsR0FBRyxtQkFBbUIsR0FBRyxNQUFNQSxNQUFLLFNBQVMsQ0FBQyxDQUFDLElBQUksRUFBRSxJQUFJLFdBQU0sRUFBRSxNQUFNLEVBQUU7QUFBQSxNQUMxRjtBQUNBLFVBQUksQ0FBQyxFQUFFLFFBQVMsUUFBTztBQUN2QixhQUFPO0FBQVMsYUFBTyxZQUFZLEVBQUU7QUFBVSxhQUFPLFlBQVksRUFBRTtBQUFVLGFBQU8sU0FBUyxFQUFFO0FBQ2hHLGFBQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxLQUFLLEtBQUs7QUFBQSxJQUNuQztBQUFBLElBQ0EsV0FBVztBQUNULGFBQU8sS0FBSyxHQUFHLEdBQUcsWUFBWSxPQUFPLFFBQVEsa0JBQWtCLE9BQU8sS0FBSyxnQkFBZ0IsT0FBTyxRQUFRLDZCQUE2QixPQUFPLEtBQUssWUFDaEosT0FBTyxVQUFVLEtBQUssT0FBTyxPQUFPLCtCQUErQixHQUFHO0FBQUEsSUFDM0U7QUFBQSxFQUNGO0FBQ0Y7OztBQzVJQSxTQUFTLGFBQWE7QUFDdEIsU0FBUyxjQUFBSSxhQUFZLGFBQUFDLFlBQVcsaUJBQUFDLGdCQUFlLFFBQVEsV0FBVyxZQUFZLHlCQUF5QjtBQUN2RyxTQUFTLGtCQUFrQjtBQUMzQixTQUFTLGVBQWU7QUFDeEIsU0FBUyxzQkFBc0I7QUFDL0IsU0FBUyxXQUFBQyxnQkFBZTtBQUt4QixJQUFNLGFBQWE7QUFDbkIsSUFBTSxZQUFZO0FBQUEsRUFDaEIsYUFBYTtBQUFBLEVBQ2IsYUFBYTtBQUFBLEVBQ2IsY0FBYztBQUFBLEVBQ2QsY0FBYztBQUNoQjtBQUlPLFNBQVMsWUFBWSxNQUFNLFFBQVEsS0FBSztBQUM3QyxRQUFNLFNBQVMsT0FBTyxJQUFJLGNBQWMsSUFBSTtBQUM1QyxTQUFPO0FBQUEsSUFDUDtBQUFBLE1BQ0UsTUFBTTtBQUFBLE1BQ04sS0FBSztBQUFBLE1BQ0wsT0FBTztBQUFBO0FBQUEsTUFFUCxVQUFVO0FBQUEsTUFDVixPQUFPO0FBQUEsTUFDUCxNQUFNLE9BQU8sUUFBUSxJQUFJLGVBQWUsSUFBSTtBQUFBLE1BQzVDLEtBQUssRUFBRSxhQUFhLE9BQU8sUUFBUSxJQUFJLGVBQWUsSUFBSSxHQUFHLGtCQUFrQixPQUFPLFFBQVEsSUFBSSxvQkFBb0IsSUFBSSxFQUFFO0FBQUE7QUFBQTtBQUFBLE1BRzVILFVBQVUsTUFBTSxRQUFRLElBQUksa0JBQWtCLE9BQU8sUUFBUSxJQUFJLGlCQUFpQjtBQUFBO0FBQUE7QUFBQSxNQUdsRixVQUFVLE1BQU0sUUFBUSxJQUFJLGtCQUFrQjtBQUFBLElBQ2hEO0FBQUEsSUFDQTtBQUFBO0FBQUE7QUFBQSxNQUdFLE1BQU07QUFBQSxNQUNOLEtBQUs7QUFBQSxNQUNMLE1BQU0sQ0FBQyxTQUFTLFVBQVUsYUFBYSxNQUFNLElBQUksU0FBUyxXQUFXLG1CQUFtQixvQ0FBb0MsY0FBYyxlQUFlO0FBQUEsTUFDekosT0FBTztBQUFBLE1BQ1AsT0FBTztBQUFBLE1BQ1AsU0FBUztBQUFBLE1BQ1QsT0FBTztBQUFBLE1BQ1AsU0FBUyxDQUFDLE1BQU0sRUFBRSxRQUFRLGNBQWMsRUFBRSxLQUFLO0FBQUEsTUFDL0MsTUFBTTtBQUFBLE1BQ04sUUFBUSxJQUFJLGFBQWE7QUFBQSxNQUN6QixTQUFTLENBQUMsUUFBUTtBQUNoQixZQUFJLFVBQVUsS0FBSyxFQUFFLGdCQUFnQixtQkFBbUIsQ0FBQztBQUN6RCxZQUFJLElBQUksS0FBSyxVQUFVLEVBQUUsUUFBUSxLQUFLLFNBQVMsNEVBQTRFLENBQUMsQ0FBQztBQUFBLE1BQy9IO0FBQUEsSUFDRjtBQUFBLEVBQ0E7QUFDRjtBQUVBLGVBQWUsZ0JBQWdCLE1BQU0sUUFBUTtBQUMzQyxRQUFNLE9BQU8sRUFBRSxhQUFhLGVBQWUsZUFBZSxlQUFlLGNBQWMsZ0JBQWdCLGdCQUFnQixlQUFlLEVBQUUsR0FBRyxRQUFRLFFBQVEsSUFBSSxRQUFRLElBQUksRUFBRTtBQUM3SyxNQUFJLENBQUMsTUFBTTtBQUNULFdBQU8sS0FBSyxvQ0FBb0MsUUFBUSxRQUFRLElBQUksUUFBUSxJQUFJLG9CQUFvQixVQUFVLDhDQUE4QztBQUM1SixXQUFPO0FBQUEsRUFDVDtBQUNBLFFBQU0sT0FBTyxjQUFjLFVBQVUsSUFBSSxJQUFJO0FBQzdDLFFBQU0sTUFBTUMsU0FBUSxNQUFNLGFBQWE7QUFDdkMsUUFBTSxPQUFPQSxTQUFRLEtBQUssa0JBQWtCO0FBQzVDLFNBQU8sS0FBSyw0QkFBNEIsSUFBSSxtQkFBbUI7QUFDL0QsTUFBSTtBQUNGLElBQUFDLFdBQVUsS0FBSyxFQUFFLFdBQVcsS0FBSyxDQUFDO0FBQ2xDLFVBQU0sSUFBSSxNQUFNLE1BQU0sK0RBQStELFVBQVUsSUFBSSxJQUFJLEVBQUU7QUFDekcsUUFBSSxDQUFDLEVBQUUsR0FBSSxPQUFNLElBQUksTUFBTSxRQUFRLEVBQUUsTUFBTSxFQUFFO0FBQzdDLFVBQU0sTUFBTSxPQUFPLEtBQUssTUFBTSxFQUFFLFlBQVksQ0FBQztBQUM3QyxVQUFNLE1BQU0sV0FBVyxRQUFRLEVBQUUsT0FBTyxHQUFHLEVBQUUsT0FBTyxLQUFLO0FBQ3pELFFBQUksUUFBUSxVQUFVLElBQUksRUFBRyxPQUFNLElBQUksTUFBTSxzQkFBc0IsR0FBRyx1QkFBdUI7QUFDN0YsSUFBQUMsZUFBYyxNQUFNLFNBQVMsS0FBSyxZQUFZLENBQUM7QUFDL0MsY0FBVSxNQUFNLEdBQUs7QUFDckIsZUFBVyxNQUFNRixTQUFRLEtBQUssWUFBWSxDQUFDO0FBQzNDLFdBQU87QUFBQSxFQUNULFNBQVMsR0FBRztBQUNWLFdBQU8sS0FBSyxpQ0FBaUMsRUFBRSxPQUFPLHVEQUF1RDtBQUM3RyxXQUFPO0FBQUEsRUFDVCxVQUFFO0FBQ0EsV0FBTyxNQUFNLEVBQUUsT0FBTyxLQUFLLENBQUM7QUFBQSxFQUM5QjtBQUNGO0FBR0EsU0FBUyxTQUFTLEtBQUssTUFBTTtBQUMzQixRQUFNLE1BQU0sSUFBSSxZQUFZLE9BQU8sS0FBSyxDQUFDLElBQU0sSUFBTSxHQUFNLENBQUksQ0FBQyxDQUFDO0FBQ2pFLE1BQUksTUFBTSxFQUFHLE9BQU0sSUFBSSxNQUFNLFdBQVc7QUFDeEMsV0FBUyxJQUFJLEdBQUcsSUFBSSxJQUFJLGFBQWEsTUFBTSxFQUFFLEdBQUcsSUFBSSxJQUFJLGFBQWEsTUFBTSxFQUFFLEdBQUcsS0FBSztBQUNuRixVQUFNLFNBQVMsSUFBSSxhQUFhLElBQUksRUFBRSxHQUFHLE9BQU8sSUFBSSxhQUFhLElBQUksRUFBRTtBQUN2RSxVQUFNLFVBQVUsSUFBSSxhQUFhLElBQUksRUFBRSxHQUFHLFFBQVEsSUFBSSxhQUFhLElBQUksRUFBRTtBQUN6RSxRQUFJLElBQUksU0FBUyxRQUFRLElBQUksSUFBSSxJQUFJLEtBQUssT0FBTyxNQUFNLE1BQU07QUFDM0QsWUFBTUcsU0FBUSxRQUFRLEtBQUssSUFBSSxhQUFhLFFBQVEsRUFBRSxJQUFJLElBQUksYUFBYSxRQUFRLEVBQUU7QUFDckYsWUFBTSxPQUFPLElBQUksU0FBU0EsUUFBT0EsU0FBUSxJQUFJO0FBQzdDLFVBQUksV0FBVyxFQUFHLFFBQU8sZUFBZSxJQUFJO0FBQzVDLFVBQUksV0FBVyxFQUFHLFFBQU87QUFDekIsWUFBTSxJQUFJLE1BQU0sMEJBQTBCLE1BQU0sRUFBRTtBQUFBLElBQ3BEO0FBQ0EsU0FBSyxLQUFLLFVBQVUsSUFBSSxhQUFhLElBQUksRUFBRSxJQUFJLElBQUksYUFBYSxJQUFJLEVBQUU7QUFBQSxFQUN4RTtBQUNBLFFBQU0sSUFBSSxNQUFNLEdBQUcsSUFBSSxpQkFBaUI7QUFDMUM7QUFHQSxJQUFNLFlBQVksQ0FBQyxTQUFTLElBQUksUUFBUSxDQUFDLE9BQU87QUFDOUMsUUFBTSxJQUFJLFFBQVEsRUFBRSxNQUFNLGFBQWEsS0FBSyxHQUFHLE1BQU07QUFBRSxNQUFFLFFBQVE7QUFBRyxPQUFHLElBQUk7QUFBQSxFQUFFLENBQUM7QUFDOUUsSUFBRSxHQUFHLFNBQVMsTUFBTSxHQUFHLEtBQUssQ0FBQztBQUMvQixDQUFDO0FBR00sU0FBUyxnQkFBZ0IsTUFBTSxRQUFRLEtBQUs7QUFFakQsU0FBTyxPQUFPLFlBQVksWUFBWSxHQUFHLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLE9BQU87QUFBQSxJQUM5RCxRQUFRLEVBQUUsVUFBVSxvQkFBb0IsRUFBRSxJQUFJO0FBQUEsSUFBSSxjQUFjLENBQUMsQ0FBQyxFQUFFO0FBQUEsSUFBUSxJQUFJO0FBQUEsSUFDaEYsR0FBSSxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsUUFBUSxJQUFJLENBQUM7QUFBQSxFQUM1QyxDQUFDLENBQUMsQ0FBQztBQUNMO0FBRUEsSUFBTSxNQUFPLFdBQVcsb0JBQW9CLEVBQUUsT0FBTyxvQkFBSSxJQUFJLEdBQUcsWUFBWSxPQUFPLFVBQVUsTUFBTTtBQUNuRyxJQUFNLFVBQVUsQ0FBQyxTQUFTO0FBQUUsUUFBTSxJQUFJLElBQUksTUFBTSxJQUFJLElBQUk7QUFBRyxTQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxhQUFhLFFBQVEsRUFBRSxNQUFNLGVBQWU7QUFBSztBQUVsSSxTQUFTLFVBQVU7QUFDakIsTUFBSSxXQUFXO0FBQ2YsYUFBVyxFQUFFLE1BQU0sS0FBSyxJQUFJLE1BQU0sT0FBTyxHQUFHO0FBQUUsUUFBSTtBQUFFLFlBQU0sS0FBSyxTQUFTO0FBQUEsSUFBRSxRQUFRO0FBQUEsSUFBQztBQUFBLEVBQUU7QUFDdkY7QUFFQSxTQUFTLE1BQU0sTUFBTSxHQUFHLFFBQVEsV0FBVyxHQUFHO0FBQzVDLFFBQU0sTUFBTSxJQUFJLEVBQUUsSUFBSTtBQUN0QixRQUFNLFFBQVEsTUFBTUgsU0FBUSxNQUFNLEVBQUUsR0FBRyxHQUFHLEVBQUUsUUFBUSxDQUFDLEdBQUcsRUFBRSxLQUFLLE1BQU0sS0FBSyxFQUFFLEdBQUcsUUFBUSxLQUFLLEdBQUcsRUFBRSxJQUFJLEdBQUcsT0FBTyxDQUFDLFVBQVUsUUFBUSxNQUFNLEVBQUUsQ0FBQztBQUMzSSxRQUFNLFFBQVEsRUFBRSxPQUFPLFVBQVUsT0FBTztBQUN4QyxNQUFJLE1BQU0sSUFBSSxFQUFFLE1BQU0sS0FBSztBQU0zQixRQUFNLFNBQVNBLFNBQVEsTUFBTSxPQUFPLE1BQU07QUFDMUMsRUFBQUMsV0FBVSxRQUFRLEVBQUUsV0FBVyxLQUFLLENBQUM7QUFDckMsUUFBTSxPQUFPLGtCQUFrQkQsU0FBUSxRQUFRLEdBQUcsRUFBRSxJQUFJLE1BQU0sR0FBRyxFQUFFLE9BQU8sSUFBSSxDQUFDO0FBRy9FLFFBQU0sT0FBTztBQUNiLFFBQU0sTUFBTSxDQUFDLE1BQU07QUFDakIsU0FBSyxNQUFNLENBQUM7QUFDWixXQUFPLENBQUMsRUFBRSxLQUFLLEVBQUUsTUFBTSxJQUFJLEVBQUUsUUFBUSxDQUFDLE1BQU0sS0FBSyxLQUFLLEtBQUssQ0FBQyxLQUFLLE1BQU0sT0FBTyxLQUFLLEdBQUcsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDO0FBQUEsRUFDbkc7QUFDQSxRQUFNLE9BQU8sR0FBRyxRQUFRLEdBQUc7QUFDM0IsUUFBTSxPQUFPLEdBQUcsUUFBUSxHQUFHO0FBQzNCLFFBQU0sR0FBRyxRQUFRLE1BQU0sS0FBSyxJQUFJLENBQUM7QUFDakMsUUFBTSxHQUFHLFFBQVEsQ0FBQyxTQUFTO0FBQ3pCLFFBQUksSUFBSSxNQUFNLElBQUksRUFBRSxJQUFJLE1BQU0sTUFBTztBQUNyQyxRQUFJLE1BQU0sT0FBTyxFQUFFLElBQUk7QUFDdkIsUUFBSSxJQUFJLFNBQVU7QUFDbEIsVUFBTSxPQUFPLEtBQUssR0FBRyxHQUFHLFlBQVksSUFBSSxHQUFHO0FBRTNDLFFBQUksTUFBTSxXQUFXLEdBQUc7QUFDdEIsaUJBQVcsTUFBTTtBQUNmLFlBQUksSUFBSSxZQUFZLElBQUksTUFBTSxJQUFJLEVBQUUsSUFBSSxFQUFHO0FBQzNDLGNBQU0sT0FBTyxLQUFLLEdBQUcsR0FBRyxnQkFBZ0IsTUFBTSxXQUFXLENBQUMsS0FBSztBQUMvRCxjQUFNLE1BQU0sR0FBRyxNQUFNLFFBQVEsTUFBTSxXQUFXLENBQUM7QUFBQSxNQUNqRCxHQUFHLEdBQUk7QUFBQSxJQUNUO0FBQUEsRUFDRixDQUFDO0FBQ0QsU0FBTyxLQUFLLEdBQUcsR0FBRyxtQkFBYyxFQUFFLEtBQUssaUJBQWlCLEVBQUUsSUFBSSx3QkFBd0IsRUFBRSxJQUFJLE9BQU87QUFDckc7QUFFTyxTQUFTLGlCQUFpQixNQUFNLE1BQU0sUUFBUSxLQUFLO0FBQ3hELFFBQU0sV0FBVyxZQUFZLEdBQUc7QUFDaEMsU0FBTztBQUFBLElBQ0wsTUFBTTtBQUFBLElBQ04sT0FBTztBQUFBLElBQ1AsZ0JBQWdCLFFBQVE7QUFNdEIsaUJBQVcsS0FBSyxVQUFVO0FBQ3hCLGVBQU8sWUFBWSxJQUFJLEVBQUUsT0FBTyxDQUFDLEtBQUssS0FBSyxTQUFTO0FBQ2xELGNBQUksRUFBRSxVQUFVLFFBQVEsRUFBRSxJQUFJLEVBQUcsUUFBTyxLQUFLO0FBQzdDLGNBQUksRUFBRSxRQUFTLFFBQU8sRUFBRSxRQUFRLEdBQUc7QUFDbkMsZ0JBQU0sU0FBUyxFQUFFLFFBQVEsV0FBVyxVQUFVLENBQUMsRUFBRSxFQUFFLFlBQVksRUFBRSxTQUFTLElBQUksT0FBTyxxQ0FBcUM7QUFDMUgsZUFBSyxJQUFJLE9BQU8sSUFBSSxXQUFXLFNBQVMsR0FBRztBQUN6QyxnQkFBSSxVQUFVLEtBQUssRUFBRSxnQkFBZ0IscUJBQXFCLGlCQUFpQixZQUFZLFlBQVksYUFBYSxDQUFDO0FBQ2pILGdCQUFJLE1BQU0sU0FBUyxLQUFLLFVBQVUsRUFBRSxNQUFNLFVBQVUsT0FBTyxDQUFDLENBQUM7QUFBQTtBQUFBLENBQU07QUFDbkU7QUFBQSxVQUNGO0FBRUEsZUFBSyxJQUFJLE9BQU8sSUFBSSxXQUFXLFNBQVMsR0FBRztBQUN6QyxnQkFBSSxVQUFVLEtBQUssRUFBRSxnQkFBZ0IsbUJBQW1CLENBQUM7QUFDekQsZ0JBQUksSUFBSSxLQUFLLFVBQVUsTUFBTSxDQUFDO0FBQzlCO0FBQUEsVUFDRjtBQUNBLGNBQUksVUFBVSxLQUFLLEVBQUUsZ0JBQWdCLG1CQUFtQixDQUFDO0FBQ3pELGNBQUksSUFBSSxJQUFJO0FBQUEsUUFDZCxDQUFDO0FBQUEsTUFDSDtBQUNBLFlBQU0sU0FBUyxPQUFPLE9BQU87QUFDN0IsVUFBSSxDQUFDLElBQUksWUFBWTtBQUNuQixZQUFJLGFBQWE7QUFDakIsZ0JBQVEsS0FBSyxRQUFRLE9BQU87QUFDNUIsZ0JBQVEsS0FBSyxVQUFVLE1BQU07QUFBRSxrQkFBUTtBQUFHLGtCQUFRLEtBQUssQ0FBQztBQUFBLFFBQUUsQ0FBQztBQUMzRCxnQkFBUSxLQUFLLFdBQVcsTUFBTTtBQUFFLGtCQUFRO0FBQUcsa0JBQVEsS0FBSyxDQUFDO0FBQUEsUUFBRSxDQUFDO0FBQUEsTUFDOUQ7QUFDQSxpQkFBVyxLQUFLLFVBQVU7QUFDeEIsWUFBSSxFQUFFLFFBQVE7QUFDWixpQkFBTyxLQUFLLElBQUksRUFBRSxJQUFJLHVCQUF1QixFQUFFLEtBQUssV0FBTSxFQUFFLE1BQU0sRUFBRTtBQUNwRTtBQUFBLFFBQ0Y7QUFDQSxZQUFJLFFBQVEsRUFBRSxJQUFJLEdBQUc7QUFDbkIsY0FBSSxNQUFNLElBQUksRUFBRSxJQUFJLEVBQUUsU0FBUztBQUMvQixpQkFBTyxLQUFLLElBQUksRUFBRSxJQUFJLDBCQUFxQixFQUFFLEtBQUssdUNBQXVDO0FBQ3pGO0FBQUEsUUFDRjtBQUNBLFlBQUksRUFBRSxZQUFZLEVBQUUsU0FBUyxHQUFHO0FBQzlCLGlCQUFPLEtBQUssYUFBYSxFQUFFLElBQUksdUJBQXVCLEVBQUUsU0FBUyxrQkFBa0Isb0JBQW9CLFVBQVUsR0FBRztBQUNwSDtBQUFBLFFBQ0Y7QUFDQSxjQUFNLFNBQVMsWUFBWTtBQUN6QixjQUFJLEVBQUUsV0FBVyxNQUFNLFVBQVUsRUFBRSxJQUFJLEdBQUc7QUFDeEMsbUJBQU8sS0FBSyxJQUFJLEVBQUUsSUFBSSxVQUFVLEVBQUUsSUFBSSxtRUFBbUUsRUFBRSxPQUFPLHVCQUF1QjtBQUN6STtBQUFBLFVBQ0Y7QUFDQSxjQUFJLENBQUMsSUFBSSxZQUFZLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRyxPQUFNLE1BQU0sR0FBRyxNQUFNO0FBQUEsUUFDOUQ7QUFDQSxZQUFJLENBQUNJLFlBQVdKLFNBQVEsTUFBTSxFQUFFLEdBQUcsQ0FBQyxHQUFHO0FBQ3JDLGNBQUksRUFBRSxPQUFPO0FBQ1gsZ0JBQUksYUFBYSxvQkFBSSxJQUFJO0FBQ3pCLGdCQUFJLElBQUksU0FBUyxJQUFJLEVBQUUsSUFBSSxFQUFHO0FBQzlCLGdCQUFJLFNBQVMsSUFBSSxFQUFFLElBQUk7QUFDdkIsY0FBRSxNQUFNLE1BQU0sTUFBTSxFQUFFLEtBQUssQ0FBQyxPQUFPO0FBQUUsa0JBQUksU0FBUyxPQUFPLEVBQUUsSUFBSTtBQUFHLGtCQUFJLEdBQUksUUFBTztBQUFBLFlBQUUsQ0FBQztBQUNwRjtBQUFBLFVBQ0Y7QUFJQSxjQUFJLEVBQUUsU0FBVSxRQUFPLEtBQUssYUFBYSxFQUFFLFFBQVEsRUFBRTtBQUFBLGNBQ2hELFFBQU8sS0FBSyxhQUFhLEVBQUUsSUFBSSxtRUFBOEQsRUFBRSxLQUFLLEVBQUU7QUFDM0c7QUFBQSxRQUNGO0FBQ0EsZUFBTztBQUFBLE1BQ1Q7QUFBQSxJQUNGO0FBQUEsRUFDRjtBQUNGOzs7QUN6UEEsU0FBUyxnQkFBZ0I7QUFFekIsSUFBTSxNQUFNLENBQUMsTUFBTSxTQUFTLElBQUksUUFBUSxDQUFDLE9BQU87QUFBQSxFQUFTO0FBQUEsRUFBTztBQUFBLEVBQzlELEVBQUUsS0FBSyxNQUFNLFNBQVMsS0FBTyxLQUFLLEVBQUUsR0FBRyxRQUFRLEtBQUsscUJBQXFCLElBQUksRUFBRTtBQUFBLEVBQy9FLENBQUMsR0FBRyxLQUFLLFFBQVE7QUFDZixVQUFNLE1BQU0sT0FBTyxPQUFPLEdBQUcsV0FBVyxFQUFFLEVBQUUsS0FBSztBQUNqRCxPQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUcsS0FBSyxPQUFPLE9BQU8sRUFBRSxFQUFFLEtBQUssR0FBRyxLQUFLLElBQUksTUFBTSxJQUFJLEVBQUUsQ0FBQyxHQUFHLFFBQVEsSUFBSSxDQUFDO0FBQUEsRUFDcEY7QUFBQyxDQUFDO0FBTUosSUFBTSxVQUFVO0FBR2hCLElBQU0sUUFBUSxDQUFDLFdBQVcsT0FBTyxRQUFRLGVBQWUsSUFBSTtBQUM1RCxJQUFNLFFBQVEsQ0FBQyxRQUFRLFdBQVksT0FBTyxTQUFTLEdBQUcsSUFBSSxHQUFHLE1BQU0sT0FBTyxNQUFNLE1BQU0sQ0FBQyxLQUFLLEdBQUcsTUFBTSxJQUFJLE1BQU07QUFHL0csSUFBTUssT0FBTyxXQUFXLGdCQUFnQixFQUFFLE9BQU8sTUFBTSxTQUFTLE9BQU8sUUFBUSxFQUFFLFNBQVMsTUFBTSxFQUFFO0FBRWxHLGVBQXNCLFNBQVMsTUFBTSxRQUFRLFFBQVEsTUFBTSxFQUFFLE9BQU87QUFBQyxHQUFHLE9BQU87QUFBQyxFQUFFLEdBQUc7QUFDbkYsTUFBSUEsS0FBSSxRQUFTLFFBQU9BLEtBQUk7QUFDNUIsRUFBQUEsS0FBSSxVQUFVO0FBQ2QsTUFBSTtBQUNGLFVBQU1DLE9BQU0sTUFBTSxRQUFRLE1BQU07QUFDaEMsVUFBTSxJQUFJLEVBQUUsU0FBUyxNQUFNLFFBQVEsTUFBTSxNQUFNLEdBQUcsUUFBUSxZQUFXLG9CQUFJLEtBQUssR0FBRSxZQUFZLEVBQUU7QUFDOUYsVUFBTSxJQUFJLE1BQU0sSUFBSSxNQUFNLENBQUMsU0FBUyxNQUFNLFFBQVEsTUFBTSxDQUFDO0FBQ3pELFFBQUksQ0FBQyxFQUFFLElBQUk7QUFDVCxZQUFNLE9BQU8sUUFBUSxLQUFLLEVBQUUsTUFBTTtBQUNsQyxZQUFNLFFBQVEsT0FBTyxzQkFBc0I7QUFDM0MsWUFBTSxVQUFVLE9BQ1osc0NBQXNDLE1BQU0sTUFBTSxDQUFDLHlFQUF5RSxNQUFNLEVBQUUsR0FBRyxDQUFDLEtBQ3hJLG1CQUFtQkEsSUFBRyxLQUFLLE1BQU0sRUFBRSxHQUFHLENBQUM7QUFDM0MsVUFBSUQsS0FBSSxPQUFPLFVBQVUsU0FBU0EsS0FBSSxPQUFPLFlBQVksUUFBUyxLQUFJLEtBQUssY0FBYyxPQUFPLEVBQUU7QUFDbEcsYUFBUUEsS0FBSSxTQUFTLEVBQUUsR0FBRyxHQUFHLE9BQU8sUUFBUTtBQUFBLElBQzlDO0FBQ0EsVUFBTSxNQUFNLE1BQU0sSUFBSSxNQUFNLENBQUMsYUFBYSxZQUFZLENBQUMsR0FBRztBQUMxRCxVQUFNLFFBQVEsTUFBTSxJQUFJLE1BQU0sQ0FBQyxhQUFhLE1BQU0sQ0FBQyxHQUFHO0FBQ3RELFVBQU0sT0FBTyxNQUFNLElBQUksTUFBTSxDQUFDLGdCQUFnQixNQUFNLFdBQVcsTUFBTSxDQUFDLEdBQUc7QUFDekUsVUFBTSxTQUFTLFFBQVEsTUFBTSxJQUFJLE1BQU0sQ0FBQyxZQUFZLFdBQVcsU0FBUyxFQUFFLEVBQUUsQ0FBQyxHQUFHLE9BQU8sQ0FBQztBQUN4RixVQUFNLFFBQVEsUUFBUSxNQUFNLElBQUksTUFBTSxDQUFDLFlBQVksV0FBVyxHQUFHLEVBQUUsUUFBUSxDQUFDLEdBQUcsT0FBTyxDQUFDO0FBQ3ZGLFVBQU0sU0FBUyxNQUFNLElBQUksTUFBTSxDQUFDLFVBQVUsZUFBZSxzQkFBc0IsQ0FBQyxHQUFHLFFBQVE7QUFDM0YsV0FBTyxPQUFPLEdBQUcsRUFBRSxVQUFVLElBQUksUUFBUSxPQUFPLE9BQU8sZUFBZSxPQUFPLGFBQWEsQ0FBQztBQUMzRixRQUFJLFdBQVcsRUFBRyxRQUFRQSxLQUFJLFNBQVMsRUFBRSxHQUFHLEdBQUcsT0FBTyxjQUFjLFNBQVMsbUJBQW1CQyxJQUFHLEdBQUc7QUFDdEcsVUFBTSxNQUFNLFFBQVEsU0FBUyx1QkFBdUIsT0FBTyxpQkFBaUIsU0FBUyxNQUFNLEtBQ3ZGLFFBQVEseUJBQ1IsUUFBUSxZQUFZLEtBQUssb0NBQW9DQSxJQUFHLEtBQUs7QUFDekUsVUFBTSxJQUFJLE1BQU0sT0FBTyxNQUFNLElBQUksTUFBTSxDQUFDLFNBQVMsYUFBYSxNQUFNLEVBQUUsQ0FBQztBQUN2RSxRQUFJLE9BQU8sQ0FBQyxFQUFFLElBQUk7QUFDaEIsWUFBTSxVQUFVLEdBQUcsTUFBTSxPQUFPLE1BQU0scUJBQXFCLE9BQU8seUJBQXlCLEVBQUUsR0FBRyxHQUFHO0FBQ25HLFVBQUlELEtBQUksT0FBTyxhQUFhLE1BQU1BLEtBQUksT0FBTyxVQUFVLFNBQVUsS0FBSSxLQUFLLGNBQWMsT0FBTyxFQUFFO0FBQ2pHLGFBQVFBLEtBQUksU0FBUyxFQUFFLEdBQUcsR0FBRyxPQUFPLFVBQVUsUUFBUTtBQUFBLElBQ3hEO0FBQ0EsUUFBSSxLQUFLLDZCQUE2QixLQUFLLE1BQU0sR0FBRyxDQUFDLENBQUMsV0FBTSxHQUFHLE1BQU0sR0FBRyxDQUFDLENBQUMsS0FBSyxNQUFNLG1CQUFtQkMsSUFBRyxHQUFHO0FBQzlHLFdBQVFELEtBQUksU0FBUyxFQUFFLEdBQUcsR0FBRyxRQUFRLEdBQUcsT0FBTyxjQUFjLFdBQVcsRUFBRSxXQUFXLFNBQVMsa0JBQWtCLE1BQU0sbUJBQW1CQyxJQUFHLEdBQUc7QUFBQSxFQUNqSixVQUFFO0FBQ0EsSUFBQUQsS0FBSSxVQUFVO0FBQUEsRUFDaEI7QUFDRjtBQUVPLFNBQVMsY0FBYyxNQUFNLE1BQU0sUUFBUSxLQUFLO0FBQ3JELFFBQU0sU0FBUyxJQUFJLGtCQUFrQjtBQUNyQyxRQUFNLFNBQVMsSUFBSSxrQkFBa0I7QUFDckMsUUFBTSxRQUFRLEtBQUssSUFBSSxHQUFHLE9BQU8sSUFBSSxnQkFBZ0IsS0FBSyxDQUFDO0FBQzNELFNBQU87QUFBQSxJQUNMLE1BQU07QUFBQSxJQUNOLE9BQU87QUFBQSxJQUNQLGdCQUFnQixRQUFRO0FBQ3RCLGFBQU8sWUFBWSxJQUFJLGlCQUFpQixDQUFDLEtBQUssUUFBUTtBQUNwRCxZQUFJLFVBQVUsS0FBSyxFQUFFLGdCQUFnQixvQkFBb0IsaUJBQWlCLFdBQVcsQ0FBQztBQUN0RixZQUFJLElBQUksS0FBSyxVQUFVQSxLQUFJLE1BQU0sQ0FBQztBQUFBLE1BQ3BDLENBQUM7QUFDRCxvQkFBY0EsS0FBSSxLQUFLO0FBQ3ZCLFVBQUksQ0FBQyxRQUFRO0FBQ1gsUUFBQUEsS0FBSSxTQUFTLEVBQUUsU0FBUyxPQUFPLFNBQVMsNkdBQTZHO0FBQ3JKO0FBQUEsTUFDRjtBQUNBLFlBQU0sTUFBTSxPQUFPLE9BQU87QUFDMUIsVUFBSSxLQUFLLHdCQUF3QixNQUFNLFFBQVEsTUFBTSxDQUFDLFVBQVUsS0FBSywrQ0FBK0M7QUFDcEgsWUFBTSxPQUFPLE1BQU0sU0FBUyxNQUFNLFFBQVEsUUFBUSxHQUFHO0FBQ3JELE1BQUFBLEtBQUksUUFBUSxZQUFZLE1BQU0sUUFBUSxHQUFJO0FBQzFDLE1BQUFBLEtBQUksTUFBTSxRQUFRO0FBQ2xCLFdBQUs7QUFBQSxJQUNQO0FBQUEsRUFDRjtBQUNGOzs7QVI5RUEsU0FBUyxpQkFBQUUsc0JBQXFCO0FBQzlCLFNBQVMsV0FBQUMsVUFBUyxXQUFBQyxVQUFTLFFBQUFDLGFBQVk7QUFDdkMsU0FBUyxlQUFBQyxjQUFhLFlBQUFDLFdBQVUsY0FBQUMsYUFBWSxnQkFBQUMscUJBQW9CO0FBQ2hFLFNBQVMsY0FBQUMsbUJBQWtCO0FBL0IrSyxJQUFNQyw0Q0FBMkM7QUFrQzNQLElBQU0sWUFBWUMsU0FBUUMsZUFBY0YseUNBQWUsQ0FBQztBQUl4RCxJQUFNLGtCQUFrQixRQUFRLElBQUksdUJBQXVCO0FBQzNELElBQU0sY0FBY0csU0FBUSxXQUFXLGdCQUFnQjtBQU12RCxJQUFNLFdBQVc7QUFRakIsSUFBTSxXQUFXLFFBQVEsSUFBSSxnQkFBZ0JBLFNBQVEsUUFBUSxJQUFJLGFBQWEsSUFDMUUsZUFBZSxTQUFTLFFBQVEsSUFBSSxNQUFNLElBQUlBLFNBQVEsV0FBVyxVQUFVLFFBQVEsSUFDbkZBLFNBQVEsV0FBVyxVQUFVLFFBQVE7QUFFekMsU0FBUyxrQkFBa0I7QUFDekIsTUFBSSxDQUFDQyxZQUFXLFdBQVcsRUFBRyxRQUFPLENBQUM7QUFDdEMsUUFBTSxVQUFVLENBQUM7QUFDakIsYUFBVyxRQUFRQyxhQUFZLFdBQVcsR0FBRztBQUMzQyxRQUFJLEtBQUssV0FBVyxHQUFHLEtBQUssS0FBSyxXQUFXLEdBQUcsRUFBRztBQUNsRCxVQUFNLE1BQU1GLFNBQVEsYUFBYSxJQUFJO0FBQ3JDLFFBQUksQ0FBQ0csVUFBUyxHQUFHLEVBQUUsWUFBWSxFQUFHO0FBQ2xDLFVBQU0sT0FBT0gsU0FBUSxLQUFLLFlBQVk7QUFDdEMsVUFBTSxLQUFLQSxTQUFRLEtBQUssVUFBVTtBQUNsQyxRQUFJLENBQUNDLFlBQVcsSUFBSSxLQUFLLENBQUNBLFlBQVcsRUFBRSxFQUFHO0FBQzFDLFlBQVEsSUFBSSxJQUFJLEVBQUUsTUFBTSxHQUFHO0FBQUEsRUFDN0I7QUFDQSxTQUFPO0FBQ1Q7QUFJQSxJQUFNLGFBQWEsTUFBTUMsYUFBWUUsTUFBSyxXQUFXLHNCQUFzQixHQUFHLEVBQUUsZUFBZSxLQUFLLENBQUMsRUFDbEcsT0FBTyxDQUFDLE1BQU0sRUFBRSxZQUFZLENBQUMsRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLO0FBRzFELFNBQVMsV0FBVyxPQUFPLElBQUk7QUFDN0IsUUFBTSxPQUFPQSxNQUFLLFdBQVcsc0JBQXNCO0FBQ25ELFFBQU0sT0FBTyxDQUFDO0FBQ2QsYUFBVyxLQUFLLE9BQU87QUFDckIsVUFBTSxJQUFJQSxNQUFLLE1BQU0sSUFBSSxHQUFHLENBQUMsT0FBTztBQUNwQyxRQUFJLENBQUNILFlBQVcsQ0FBQyxFQUFHO0FBQ3BCLFFBQUk7QUFBRSxXQUFLLENBQUMsSUFBSSxLQUFLLE1BQU1JLGNBQWEsR0FBRyxNQUFNLENBQUM7QUFBQSxJQUFFLFFBQVE7QUFBQSxJQUFnQztBQUFBLEVBQzlGO0FBQ0EsU0FBTyxPQUFPLEtBQUssSUFBSSxFQUFFLFNBQVMsS0FBSyxVQUFVLElBQUksSUFBSTtBQUMzRDtBQUVBLFNBQVMsZ0JBQWdCLFFBQVE7QUFDL0IsTUFBSSxRQUFRO0FBQ1osU0FBTztBQUFBLElBQ0wsTUFBTTtBQUFBLElBQ04sU0FBUztBQUFBLElBQ1QsTUFBTSxhQUFhO0FBQ2pCLFlBQU0sRUFBRSxnQkFBQUMsZ0JBQWUsSUFBSSxNQUFNO0FBQ2pDLGNBQVFBLGdCQUFlLFdBQVcsTUFBTSxFQUFFO0FBQzFDLFdBQUssT0FBTyxrQkFBa0IsTUFBTSxLQUFLLE1BQU0sS0FBSyxJQUFJLEtBQUssUUFBUSxFQUFFO0FBQUEsSUFDekU7QUFBQSxJQUNBLFVBQVUsTUFBTSxJQUFJO0FBQ2xCLFVBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxRQUFRLE9BQU8sR0FBRyxFQUFFLFNBQVMsd0JBQXdCLEVBQUcsUUFBTztBQUNqRixZQUFNLE9BQU87QUFDYixVQUFJLENBQUMsS0FBSyxTQUFTLElBQUksRUFBRyxNQUFLLE1BQU0sMEVBQTBFO0FBTS9HLFlBQU0sTUFBTSxrQkFBa0IsT0FBTztBQUNyQyxZQUFNLE9BQU8sTUFBTSxTQUFTLE1BQU0sTUFBTSxJQUFJLENBQUMsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxLQUFLLElBQUksSUFBSSxNQUFNO0FBQ3RHLFVBQUksTUFBTSxLQUFLLFFBQVEsTUFBTSxzQkFBc0IsSUFBSTtBQU12RCxVQUFJLGlCQUFpQjtBQUNuQixjQUFNLE1BQU0sQ0FBQztBQUNiLG1CQUFXLE1BQU0sV0FBVyxHQUFHO0FBQzdCLGNBQUksT0FBTyxLQUFNO0FBQ2pCLGdCQUFNLE9BQU8sV0FBVyxPQUFPLEVBQUU7QUFDakMsY0FBSSxLQUFNLEtBQUksRUFBRSxJQUFJLFlBQVlDLFlBQVcsUUFBUSxFQUFFLE9BQU8sSUFBSSxFQUFFLE9BQU8sUUFBUTtBQUFBLFFBQ25GO0FBQ0EsY0FBTSw2QkFBNkIsS0FBSyxVQUFVLEdBQUcsQ0FBQztBQUFBLElBQVE7QUFBQSxNQUNoRTtBQUNBLGFBQU8sRUFBRSxNQUFNLEtBQUssS0FBSyxLQUFLO0FBQUEsSUFDaEM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsSUFNQSxpQkFBaUI7QUFDZixVQUFJLENBQUMsbUJBQW1CLENBQUMsT0FBTyxPQUFRO0FBQ3hDLGlCQUFXLE1BQU0sV0FBVyxHQUFHO0FBQzdCLFlBQUksT0FBTyxLQUFNO0FBQ2pCLGNBQU0sT0FBTyxXQUFXLE9BQU8sRUFBRTtBQUdqQyxZQUFJLEtBQU0sTUFBSyxTQUFTLEVBQUUsTUFBTSxTQUFTLFVBQVUsV0FBVyxFQUFFLFNBQVMsUUFBUSxLQUFLLENBQUM7QUFBQSxNQUN6RjtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQ0Y7QUFFQSxJQUFPLHNCQUFRLGFBQWEsQ0FBQyxFQUFFLFNBQVMsS0FBSyxNQUFNO0FBR2pELFFBQU0sTUFBTSxRQUFRLE1BQU0sV0FBVyxFQUFFO0FBQ3ZDLFFBQU0sTUFBTSxnQkFBZ0I7QUFDNUIsUUFBTSxXQUFXLE9BQU8sS0FBSyxHQUFHO0FBQ2hDLFFBQU0sU0FBUyxRQUFRLElBQUk7QUFDM0IsUUFBTSxVQUFVLFlBQVk7QUFFNUIsTUFBSSxXQUFXLENBQUMsUUFBUTtBQUN0QixVQUFNLElBQUk7QUFBQSxNQUNSLElBQUksUUFBUTtBQUFBLGFBQ0UsU0FBUyxLQUFLLElBQUksS0FBSyxRQUFRO0FBQUEsSUFDL0M7QUFBQSxFQUNGO0FBRUEsTUFBSSxXQUFXLENBQUMsSUFBSSxNQUFNLEdBQUc7QUFJM0IsVUFBTSxJQUFJO0FBQUEsTUFDUixJQUFJLFFBQVEsYUFBYSxNQUFNLHNDQUFzQyxNQUFNO0FBQUEscUJBRXJELFNBQVMsS0FBSyxJQUFJLEtBQUssUUFBUTtBQUFBLElBQ3ZEO0FBQUEsRUFDRjtBQUVBLFFBQU0sZUFBZSxVQUNqQixFQUFFLENBQUMsTUFBTSxHQUFHLElBQUksTUFBTSxFQUFFLEdBQUcsSUFDM0IsT0FBTyxZQUFZLFNBQVMsSUFBSSxPQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUUxRCxTQUFPO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLElBZUwsUUFBUSxFQUFFLE1BQU0sYUFBYSxPQUFPLGdCQUFnQixHQUFHLEdBQUcsT0FBTyxFQUFFLFNBQVMsQ0FBQyxjQUFjLEVBQUUsRUFBRTtBQUFBLElBQy9GLFFBQVE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLE1BS04sNkJBQTZCO0FBQUEsTUFDN0IsbUNBQW1DO0FBQUEsTUFDbkMsYUFBYSxLQUFLLFVBQVUsUUFBUSxJQUFJLFlBQVksR0FBRztBQUFBO0FBQUE7QUFBQSxNQUd2RCxvQkFBb0IsS0FBSyxVQUFVLFFBQVE7QUFBQSxJQUM3QztBQUFBO0FBQUE7QUFBQTtBQUFBLElBSUEsU0FBUztBQUFBO0FBQUE7QUFBQTtBQUFBLE1BSVAsV0FBVyxTQUFTLGdCQUFnQixNQUFNLElBQUk7QUFBQSxNQUM5Qyw2QkFBNkI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLE1BaUI3QixJQUFJLEVBQUUsZUFBZSxLQUFLLENBQUM7QUFBQSxNQUMzQixzQkFBc0I7QUFBQSxNQUN0QixpQkFBaUIsSUFBSSxxQkFBcUIsUUFBUSxJQUFJLHFCQUFxQixFQUFFO0FBQUEsTUFDN0UsaUJBQWlCLFdBQVcsR0FBRztBQUFBLE1BQy9CLGNBQWMsV0FBVyxHQUFHO0FBQUEsSUFDOUI7QUFBQSxJQUNBLFNBQVM7QUFBQSxNQUNQLE9BQU8sRUFBRSxRQUFRUCxTQUFRLFdBQVcsU0FBUyxFQUFFO0FBQUEsSUFDakQ7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQU9BLGNBQWMsRUFBRSxTQUFTLENBQUMsT0FBTyxZQUFZLFNBQVMsT0FBTyxFQUFFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQVEvRCxXQUFXO0FBQUEsSUFDWCxPQUFPO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxNQUtMLFFBQVEsVUFBVUEsU0FBUSxVQUFVLE1BQU0sSUFBSTtBQUFBLE1BQzlDLGFBQWE7QUFBQSxNQUNiLGNBQWM7QUFBQSxNQUNkLG1CQUFtQixPQUFPO0FBQUEsTUFDMUIsV0FBVztBQUFBLE1BQ1gsV0FBVztBQUFBO0FBQUEsTUFDWCx1QkFBdUI7QUFBQTtBQUFBLE1BQ3ZCLGVBQWU7QUFBQSxRQUNiLE9BQU87QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsUUFTUCxVQUFVLFVBQVUsQ0FBQyxPQUFPLElBQUksQ0FBQztBQUFBLFFBQ2pDLFFBQVEsVUFBVTtBQUFBLFVBQ2hCLFFBQVE7QUFBQSxVQUNSLE1BQU0sYUFBYSxVQUFVLElBQUksUUFBUSxrQkFBa0IsR0FBRyxDQUFDO0FBQUEsVUFDL0QsZ0JBQWdCO0FBQUEsVUFDaEIsZ0JBQWdCLE1BQU0sR0FBRyxNQUFNO0FBQUEsVUFDL0Isc0JBQXNCO0FBQUE7QUFBQSxVQUV0QixPQUFPLEVBQUUsT0FBTyw2QkFBNkI7QUFBQSxRQUMvQyxJQUFJO0FBQUEsVUFDRixnQkFBZ0I7QUFBQSxRQUNsQjtBQUFBLE1BQ0Y7QUFBQSxJQUNGO0FBQUEsRUFDRjtBQUNGLENBQUM7IiwKICAibmFtZXMiOiBbInJlYWRGaWxlU3luYyIsICJleGlzdHNTeW5jIiwgInJlYWRkaXJTeW5jIiwgInN0YXRTeW5jIiwgInJlc29sdmUiLCAiZGlybmFtZSIsICJqb2luIiwgInNyYyIsICJyZXNvbHZlIiwgInJlYWRkaXJTeW5jIiwgInN0YXRTeW5jIiwgImV4aXN0c1N5bmMiLCAicmVhZEZpbGVTeW5jIiwgInJlYWRGaWxlU3luYyIsICJleGlzdHNTeW5jIiwgInJlYWRkaXJTeW5jIiwgInJlc29sdmUiLCAiZGlybmFtZSIsICJmaWxlVVJMVG9QYXRoIiwgInJlYWRGaWxlU3luYyIsICJyZXNvbHZlIiwgImRpcm5hbWUiLCAiZmlsZVVSTFRvUGF0aCIsICJfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsIiwgInJlc29sdmUiLCAiZGlybmFtZSIsICJmaWxlVVJMVG9QYXRoIiwgInJlYWRGaWxlU3luYyIsICJfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsIiwgIlJPT1QiLCAicmVzb2x2ZSIsICJkaXJuYW1lIiwgImZpbGVVUkxUb1BhdGgiLCAiUk9PVCIsICJleGlzdHNTeW5jIiwgInJlYWRkaXJTeW5jIiwgInJlYWRGaWxlU3luYyIsICJzcmMiLCAicmVzb2x2ZSIsICJfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsIiwgInJlYWRGaWxlU3luYyIsICJqb2luIiwgInJlYWRGaWxlU3luYyIsICJqb2luIiwgImV4aXN0c1N5bmMiLCAic3RhdFN5bmMiLCAicmVzb2x2ZSIsICJyZWFkZGlyU3luYyIsICJyZWFkRmlsZVN5bmMiLCAiZ2l0IiwgInJlc29sdmUiLCAiZGlybmFtZSIsICJmaWxlVVJMVG9QYXRoIiwgIl9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwiLCAiUk9PVCIsICJyZXNvbHZlIiwgImRpcm5hbWUiLCAiZmlsZVVSTFRvUGF0aCIsICJleGlzdHNTeW5jIiwgIm1rZGlyU3luYyIsICJ3cml0ZUZpbGVTeW5jIiwgInJlc29sdmUiLCAicmVzb2x2ZSIsICJta2RpclN5bmMiLCAid3JpdGVGaWxlU3luYyIsICJzdGFydCIsICJleGlzdHNTeW5jIiwgIlJFRyIsICJzcmMiLCAiZmlsZVVSTFRvUGF0aCIsICJyZXNvbHZlIiwgImRpcm5hbWUiLCAiam9pbiIsICJyZWFkZGlyU3luYyIsICJzdGF0U3luYyIsICJleGlzdHNTeW5jIiwgInJlYWRGaWxlU3luYyIsICJjcmVhdGVIYXNoIiwgIl9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwiLCAiZGlybmFtZSIsICJmaWxlVVJMVG9QYXRoIiwgInJlc29sdmUiLCAiZXhpc3RzU3luYyIsICJyZWFkZGlyU3luYyIsICJzdGF0U3luYyIsICJqb2luIiwgInJlYWRGaWxlU3luYyIsICJhcmVhc0ZvckJ1bmRsZSIsICJjcmVhdGVIYXNoIl0KfQo=