#!/usr/bin/env node
/**
 * Stellwerk Installer v1.3.0
 *
 * Kopiert die zwoelf Skills nach ~/.claude/skills/ oder ./.claude/skills/,
 * schreibt .claude/workflow.config.json und .claude/kit/board.mjs.
 *
 * Aufruf:
 *   node install.mjs
 *   node install.mjs --version
 *   npx github:mannewolff/claude-workflow-kit  (nach Veroeffentlichung)
 *
 * Aenderung v1.3.0: Config-Schema nutzt codeHost + issueTracker statt provider.
 * Bestehende Configs mit provider werden beim Lesen still migriert (abwaertskompatibel).
 */

import { createInterface } from "node:readline";
import { existsSync, mkdirSync, cpSync, writeFileSync, readFileSync } from "node:fs";
import { resolve, join, dirname } from "node:path";
import { homedir } from "node:os";
import { fileURLToPath } from "node:url";

const __dirname = dirname(fileURLToPath(import.meta.url));

const VERSION = "1.11.0";

// --- CLAUDE-workflow.md (Base64-eingebettet fuer Single-File-Portabilitaet) ---
// SYNC: Nach jeder Aenderung an templates/CLAUDE-workflow.md neu generieren:
//   node tools/sync-blobs.mjs        (Pruefung: node tools/sync-blobs.mjs --check)
const CLAUDE_WORKFLOW_MD_B64 = "IyBDTEFVREUtd29ya2Zsb3cubWQg4oCUIFN0ZWxsd2Vyay1Qcm96ZXNzCgpWZXJiaW5kbGljaGVyIFByb3plc3MgZnVlciBLSS1nZXN0dWV0enRlIFNvZnR3YXJlZW50d2lja2x1bmcgaW4gZGllc2VtIFByb2pla3QuCkJhc2llcnQgYXVmIGRlbSA5LVNjaHJpdHQtUHJvemVzcyAoV2hpdGVwYXBlciAiRWluIFByb3plc3MgenVyIEtJLWdlc3R1ZXR6dGVuIFNvZnR3YXJlZW50d2lja2x1bmciLCBNYW5uZSBXb2xmZiwgMjAyNikuCgotLS0KCiMjIERpZSBuZXVuIFNjaHJpdHRlCgp8IFNjaHJpdHQgfCBBa3RvciB8IFdhcyBwYXNzaWVydCB8IFNraWxsIHwKfC0tLS0tLS0tLXwtLS0tLS0tfC0tLS0tLS0tLS0tLS18LS0tLS0tLXwKfCAxLiBBbmZvcmRlcnVuZyB8IE1lbnNjaCB8IEZvcm11bGllcnQgb2RlciBkaWt0aWVydCBkaWUgQW5mb3JkZXJ1bmcgfCDigJQgfAp8IDIuIFBsYW4gfCBLSSB8IEVyc3RlbGx0IFBsYW4sIHN0ZWxsdCB6dXIgRGlza3Vzc2lvbiwgaW1wbGVtZW50aWVydCBuaWNodHMgfCBgL3BsYW5gIHwKfCAzLiBQbGFuIHp1IElzc3VlcyB8IEtJIHwgVWViZXJ0cmFlZ3QgUGxhbiBpbiBHaXRIdWItSXNzdWVzIChWaWVyLUFic2Nobml0dC1Gb3JtYXQpIHwgYC9pc3N1ZXNgIHwKfCA0LiBHTyB8IE1lbnNjaCB8IFppZWh0IElzc3VlcyBuYWNoIFJlYWR5IOKAlCBkYXMgaXN0IGRhcyBHTyB8IOKAlCB8CnwgNS4gSW1wbGVtZW50aWVydW5nIHwgS0kgfCBBcmJlaXRldCBSZWFkeS1Jc3N1ZXMgc2VxdWVuemllbGwgYWIsIGNvbW1pdHRldCBsb2thbCB8IGAvaW1wbGVtZW50LXJlYWR5YCB8CnwgNi4gTG9rYWxlIFBydWVmdW5nIHwgS0kgKyBNZW5zY2ggfCBQZmxpY2h0LUNoZWNrcyArIG1hbnVlbGxlIFVJLVZlcmlmaWthdGlvbiB8IGAvbG9jYWwtY2hlY2tgIHwKfCA3LiBDb2RlLVJldmlldyB8IEtJIHwgU3RhcnRldCBPcHVzLVJldmlld2VyIGluIGZyaXNjaGVyIFNlc3Npb24gfCBgL3Jldmlld2AgfAp8IDcuNS4gUmV0cm8gfCBLSSB8IEtJLVJldHJvc3Bla3RpdmUsIE1lbW9yeSBrb25zb2xpZGllcmVuIHwgYC9yZXRyb2AgfAp8IDguIFB1c2ggfCBNZW5zY2ggfCBUaXBwdCBgcHVzaCBtYWluYCDigJQgQ2xhdWRlIHB1c2h0IGRlbiBCYXRjaCB8IGAvcHVzaC1tYWluYCB8CnwgOS4gTWVyZ2UgfCBNZW5zY2ggfCBUaXBwdCBgbWVyZ2UgcHJvZHVjdGlvbmAg4oCUIENsYXVkZSBlcnN0ZWxsdCBQUiB8IGAvbWVyZ2UtcHJvZHVjdGlvbmAgfAoKLS0tCgojIyBEaWUgZHJlaSBTdG9wLVB1bmt0ZSAobmllIGF1dG9tYXRpc2llcnQpCgoxLiAqKkdPIChTY2hyaXR0IDQpOioqIElzc3VlIG5hY2ggUmVhZHkgemllaGVuLiBDbGF1ZGUgd2FydGV0LgoyLiAqKlB1c2ggKFNjaHJpdHQgOCk6KiogVHJpZ2dlci1QaHJhc2UgYHB1c2ggbWFpbmAuIENsYXVkZSBwdXNodCBuaWNodCBhdXRvbm9tLgozLiAqKk1lcmdlIChTY2hyaXR0IDkpOioqIFRyaWdnZXItUGhyYXNlIGBtZXJnZSBwcm9kdWN0aW9uYC4gQ2xhdWRlIG1lcmdlZCBuaWNodC4KCkRpZXNlIGRyZWkgU2Nocml0dGUgc2luZCBkaWUgVmVyYW50d29ydHVuZ3NzY2h3ZWxsZW4uIFNpZSBibGVpYmVuIG1lbnNjaGxpY2ggdW5kIHRpcHBiYXIuCgotLS0KCiMjIFp3ZWkgQmFobmVuCgoqKkJhaG4gMSDigJQgS2xlaW5lIMOEbmRlcnVuZyoqIChkaXJla3Q7IGtlaW4gUGxhbi9Jc3N1ZS9HTyk6IGdlbmF1IGVpbmUgRGF0ZWkgLyBlaW4gQXNzZXQgLyBlaW5lIENvbmZpZzsga2VpbmUgRmx5d2F5LU1pZ3JhdGlvbjsga2VpbiBuZXVlci9nZcOkbmRlcnRlciBFbmRwb2ludDsga2VpbiBEYXRlbm1vZGVsbDsg4omkIDEgTW9kdWw7IGtlaW5lIHNpY2hlcmhlaXRzcmVsZXZhbnRlIExvZ2lrIOKGkiBkaXJla3QgdW1zZXR6ZW4sIGVpbiBDb21taXQsIGtlaW4gUHVzaCBvaG5lIFRyaWdnZXIuCgoqKkJhaG4gMiDigJQgRmVhdHVyZSoqICh2b2xsZXIgOS1TY2hyaXR0KTogYmVyw7xocnQgRGF0ZW5tb2RlbGwsIEFQSS9FbmRwb2ludCwgTWlncmF0aW9uLCBTaWNoZXJoZWl0IG9kZXIgPiAxIE1vZHVsOyBvZGVyIEF1ZndhbmQgPiB+MSBDb21taXQg4oaSIGAvcGxhbmAg4oaSIGAvaXNzdWVzYCDihpIgR08g4oaSIGAvaW1wbGVtZW50LXJlYWR5YC4KCioqTWV0YS1SZWdlbDoqKiBWb3IgQmVnaW5uIGplZGVyIG5ldWVuIEF1ZmdhYmUgZGllIEJhaG4gbGF1dCBiZW5lbm5lbiAoIkRhcyBpc3QgQmFobiAxLzIsIGljaCDigKYiKTsgaW0gWndlaWZlbCBCYWhuIDIuCgp8IEJlaXNwaWVsIHwgQmFobiB8CnwtLS0tLS0tLS0tfC0tLS0tLXwKfCBJY29uLS9GYXZpY29uLVRhdXNjaCB8IDEgfAp8IFRleHRrb3JyZWt0dXIgfCAxIHwKfCBDb25maWctRGVmYXVsdCB8IDEgfAp8IE5ldWUgVGFiZWxsZSB8IDIgfAp8IE5ldWVyIEVuZHBvaW50IHwgMiB8CnwgTmV1ZXMgVUktRmVhdHVyZSB8IDIgfAoKLS0tCgojIyBLYW5iYW4tQm9hcmQgKDUgU3BhbHRlbikKCnwgU3BhbHRlIHwgQmVkZXV0dW5nIHwgV2VyIGJld2VndCB8CnwtLS0tLS0tLXwtLS0tLS0tLS0tLXwtLS0tLS0tLS0tLXwKfCBCYWNrbG9nIHwgSWRlZSBvZGVyIElzc3VlIG1pdCBvZmZlbmVuIEZyYWdlbiB8IEJlaWRlIHwKfCBSZWFkeSB8IEZyZWlnZWdlYmVuLCBnaWx0IGFscyBHTyB8IE51ciBNZW5zY2ggfAp8IEluIHByb2dyZXNzIHwgQWt0dWVsbGUgQXJiZWl0LCBlaW4gSXNzdWUgenVyIFplaXQgfCBLSSBiZWltIFN0YXJ0IHwKfCBJbiByZXZpZXcgfCBMb2thbCBmZXJ0aWcsIG5pY2h0IGdlcHVzaHQgfCBLSSBiZWltIEFic2NobHVzcyB8CnwgRG9uZSB8IE1lbnNjaCBoYXQgZ2V0ZXN0ZXQsIFB1c2ggZXJmb2xndCB8IE51ciBNZW5zY2ggfAoKQ2xhdWRlIGdlaHQgbnVyIGJpcyAqKkluIHJldmlldyoqLiBEb25lIHNldHp0IGRlciBNZW5zY2ggbmFjaCBzZWluZW0gVGVzdC4KCi0tLQoKIyMgR2l0LVdvcmtmbG93IChzdHJpa3QgYmluZGVuZCkKCjEuIENsYXVkZSBjb21taXR0ZXQgbG9rYWwsIHB1c2h0IE5JQ0hUIGF1dG9tYXRpc2NoLgoyLiBNZW5zY2ggdGVzdGV0IGxva2FsIChEZXYtU2VydmVyIHN0YXJ0ZW4sIEdvbGRlbiBQYXRoIGR1cmNoa2xpY2tlbikuCjMuIE1lbnNjaCB0aXBwdCBgcHVzaCBtYWluYCDigJQgQ2xhdWRlIHB1c2h0IGF1ZiBgbWFpbkJyYW5jaGAuCjQuIE1lbnNjaCB0ZXN0ZXQgYXVmIFRlc3RzZXJ2ZXIuCjUuIE1lbnNjaCB0aXBwdCBgbWVyZ2UgcHJvZHVjdGlvbmAg4oCUIENsYXVkZSBlcnN0ZWxsdCBQUiBgbWFpbkJyYW5jaCAtPiBwcm9kdWN0aW9uQnJhbmNoYC4KNi4gTWVuc2NoIG1lcmdldCBkZW4gUFIuCgpBYnNvbHV0IGJpbmRlbmQ6Ci0gS2VpbiBGb3JjZS1QdXNoIGF1ZiBgbWFpbkJyYW5jaGAgb2RlciBgcHJvZHVjdGlvbkJyYW5jaGAgb2huZSBleHBsaXppdGUgRWluemVsYW53ZWlzdW5nLgotIEhvb2tzIChQcmUtQ29tbWl0IC8gUHJlLVB1c2gpIHdlcmRlbiBuaWNodCBtaXQgYC0tbm8tdmVyaWZ5YCB1bWdhbmdlbi4KLSBgcHJvZHVjdGlvbkJyYW5jaGAgd2lyZCBuaWUgZGlyZWt0IGdlcHVzaHQuCgotLS0KCiMjIENvbmZpZyAoLmNsYXVkZS93b3JrZmxvdy5jb25maWcuanNvbikKCmBgYGpzb24KewogICJjb2RlSG9zdCI6ICJnaXRodWIiLAogICJpc3N1ZVRyYWNrZXIiOiAiZ2l0aHViIiwKICAiYnVpbGRDaGVja3MiOiBbIjxidWlsZC1rb21tYW5kbz4iLCAiPHRlc3Qta29tbWFuZG8+Il0sCiAgIm11dGF0aW9uQ29tbWFuZCI6ICI8bXV0YXRpb25zLXRlc3Qta29tbWFuZG8gb2RlciBsZWVyPiIsCiAgIm1haW5CcmFuY2giOiAibWFpbiIsCiAgInByb2R1Y3Rpb25CcmFuY2giOiAicHJvZHVjdGlvbiIsCiAgInJldmlld1Njb3BlIjogImRpZmYiLAogICJyZXZpZXdNb2RlbCI6ICJjbGF1ZGUtb3B1cy00LTgiLAogICJ0cmlnZ2VycyI6IHsgImdvIjogIkdPIiwgInB1c2giOiAicHVzaCBtYWluIiwgIm1lcmdlIjogIm1lcmdlIHByb2R1Y3Rpb24iIH0sCiAgImxvY2FsIjogeyAiaXNzdWVzRGlyIjogImlzc3VlcyIgfQp9CmBgYAoKYGNvZGVIb3N0YCBzdGV1ZXJ0IGRlbiBDb2RlLUhvc3QgKGdpdGh1YiB8IGdpdGxhYiB8IGxvY2FsKS4KYGlzc3VlVHJhY2tlcmAgc3RldWVydCBJc3N1ZXMgdW5kIEJvYXJkIChnaXRodWIgfCBnaXRsYWIgfCBsb2NhbCkuCkJlaSBHaXRIdWIgdW5kIEdpdExhYiB6ZWlnZW4gYmVpZGUgYXVmIGRlbnNlbGJlbiBXZXJ0LgpCZXN0ZWhlbmRlIENvbmZpZ3MgbWl0IGBwcm92aWRlcmAgd2VyZGVuIGF1dG9tYXRpc2NoIG1pZ3JpZXJ0LgoKYGJ1aWxkQ2hlY2tzYCB1bmQgYG11dGF0aW9uQ29tbWFuZGAgYW5wYXNzZW4uIEFsbGUgYW5kZXJlbiBGZWxkZXIgaGFiZW4gc2lubnZvbGxlIERlZmF1bHRzLgoKQmVpc3BpZWxlIGZ1ZXIgdmVyc2NoaWVkZW5lIFN0YWNrczoKCnwgU3RhY2sgfCBidWlsZENoZWNrcyB8IG11dGF0aW9uQ29tbWFuZCB8CnwtLS0tLS0tfC0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLXwKfCBKYXZhL01hdmVuIHwgYFsibXZuIHZlcmlmeSJdYCB8IGAibXZuIG9yZy5waXRlc3Q6cGl0ZXN0LW1hdmVuOm11dGF0aW9uQ292ZXJhZ2UiYCB8CnwgTm9kZS9ucG0gfCBgWyJucG0gdGVzdCIsICJucG0gcnVuIGJ1aWxkIl1gIHwgYCIiYCB8CnwgUHl0aG9uIHwgYFsicHl0ZXN0IiwgInB5dGhvbiAtbSBidWlsZCJdYCB8IGAiImAgfAp8IEdvIHwgYFsiZ28gdGVzdCAuLy4uLiIsICJnbyBidWlsZCAuLy4uLiJdYCB8IGAiImAgfAoKLS0tCgojIyBQZmxpY2h0Y2hlY2tzIHZvciBQdXNoIChTY2hyaXR0IDYpCgpBbGxlIGBidWlsZENoZWNrc2AgYXVzIGRlciBDb25maWcgbGF1ZmVuIGdydWVuLiBSb3RlIENoZWNrcyBibG9ja2llcmVuIGRlbiBQdXNoIG1lY2hhbmlzY2guCkJlaSBVSS1BZW5kZXJ1bmdlbjogRGV2LVNlcnZlciBzdGFydGVuLCBHb2xkZW4gUGF0aCB1bmQgbWluZGVzdGVucyBlaW5lbiBFZGdlIENhc2UgbWFudWVsbCBwcnVlZmVuLgpXZW5uIGVpbiBDaGVjayBuaWNodCBsb2thbCBhdXNmdWVocmJhciBpc3Q6IGltIEFic2NobHVzc2JlcmljaHQgdmVybWVya2VuLCBuaWNodCB2ZXJzY2h3ZWlnZW4uCgotLS0KCiMjIElzc3VlLUZvcm1hdCAoVmllciBBYnNjaG5pdHRlKQoKYGBgbWFya2Rvd24KIyMgS29udGV4dApXYXJ1bSB3aXJkIGRpZXNlIEF1ZmdhYmUgZ2VtYWNodD8KCiMjIEF1ZmdhYmUKV2FzIGtvbmtyZXQgaXN0IHp1IHR1bj8KCiMjIEFremVwdGFuemtyaXRlcml1bQpXaWUgd2lyZCB2ZXJpZml6aWVydCwgZGFzcyBkaWUgQXVmZ2FiZSBlcmxlZGlndCBpc3Q/ClBvcnRhYmlsaXRhZXRzLUtvbnZlbnRpb246IFdlbm4gZWluZSBEYXRlaSBhbHMgZWlnZW5zdGFlbmRpZyBwb3J0YWJlbCBnZWRhY2h0IGlzdCAoSW5zdGFsbGVyLCBrb3BpZXJiYXJlcyBTY3JpcHQpLCBtdXNzIGhpZXIgc3RlaGVuOiAibGF1ZmZhZWhpZyBvaG5lIHdlaXRlcmVuIFJlcG8tS29udGV4dCIuCgojIyBBYmhhZW5naWdrZWl0ZW4KS2VpbmUuIChvZGVyOiBJc3N1ZSAjTiBtdXNzIHZvcmhlciBmZXJ0aWcgc2VpbikKYGBgCgotLS0KCiMjIEFic2NobHVzc2JlcmljaHQtRm9ybWF0CgpgYGAKIyMjIEFlbmRlcnVuZ2VuCi0gYERhdGVpYCDigJQga3VyemUgQmVzY2hyZWlidW5nIGRlciBXaXJrdW5nCgojIyMgVGVzdHMgdW5kIENoZWNrcwotIDxLb21tYW5kbz4gLT4gPEVyZ2VibmlzPgoKIyMjIEhpbndlaXNlCi0gPFJlc3RyaXNpa2VuLCBvZmZlbmUgUHVua3RlLCBtYW51ZWxsZSBGb2xnZXNjaHJpdHRlPgpgYGAKCi0tLQoKIyMgUHJpb3JpdGFldGVuIGJlaSBaaWVsa29uZmxpa3RlbgoKMS4gU2ljaGVyaGVpdAoyLiBLb3JyZWt0aGVpdAozLiBEYXRlbmludGVncml0YWV0CjQuIEFjY2Vzc2liaWxpdHkKNS4gV2FydGJhcmtlaXQKNi4gUGVyZm9ybWFuY2UKNy4gVmlzdWVsbGUgUHJhZWZlcmVuego4LiBCZXF1ZW1saWNoa2VpdCBkZXIgSW1wbGVtZW50aWVydW5nCgotLS0KCiMjIEtJLVJldHJvIChhbGxlIDEtMiBXb2NoZW4pCgpgL3JldHJvYCBzdGFydGV0IGRpZSBLSS1SZXRyb3NwZWt0aXZlLiBEcmVpIEZyYWdlbjoKLSBXbyBoYXQgZGllIE1lbnNjaC1LSS1adXNhbW1lbmFyYmVpdCBnZWhha3Q/Ci0gV2VsY2hlIE1lbW9yeS1FaW50cmFlZ2Ugc2luZCB2ZXJhbHRldD8KLSBXZWxjaGUgV29ya2Zsb3ctUmVnZWwgYnJhdWNodCBlaW5lIFNjaGFlcmZ1bmc/CgpPdXRwdXQ6IGtvbmtyZXRlIEFlbmRlcnVuZ2VuIGFuIE1lbW9yeS1EYXRlaWVuIHVuZCBDTEFVREUqLm1kLURhdGVpZW4uCg==";

// --- board.mjs (Base64-eingebettet fuer Single-File-Portabilitaet) ---
// SYNC: Nach jeder Aenderung an kit/board.mjs neu generieren:
//   node tools/sync-blobs.mjs        (Pruefung: node tools/sync-blobs.mjs --check)
const BOARD_MJS_B64 = "IyEvdXNyL2Jpbi9lbnYgbm9kZQovKioKICogYm9hcmQubWpzIOKAlCBQcm92aWRlci1hZ25vc3Rpc2NoZXIgRWluc3RpZWdzcHVua3QgZnVlciBhbGxlIEJvYXJkLU9wZXJhdGlvbmVuLgogKiBMaWVzdCAuY2xhdWRlL3dvcmtmbG93LmNvbmZpZy5qc29uLCB3YWVobHQgYW5oYW5kIGlzc3VlVHJhY2tlci9jb2RlSG9zdCBkZW4gQWRhcHRlcgogKiB1bmQgZnVlaHJ0IGRpZSBhbmdlZm9yZGVydGUgT3BlcmF0aW9uIGF1cy4KICoKICogUVVFTExFIERFUiBXQUhSSEVJVDogRGllc2UgRGF0ZWkgd2lyZCBpbSBLaXQtUmVwbyAoY2xhdWRlLXdvcmtmbG93LWtpdCkgZ2VwZmxlZ3QuCiAqIEFlbmRlcnVuZ2VuIGF1c3NjaGxpZXNzbGljaCBoaWVyIHZvcm5laG1lbiwgZGFuYWNoIGBub2RlIHRvb2xzL3N5bmMtYmxvYnMubWpzYAogKiAoYWt0dWFsaXNpZXJ0IGRlbiBlaW5nZWJldHRldGVuIEJsb2IgaW4gaW5zdGFsbC5tanMpLgogKgogKiBBdXNnYWJlOiBKU09OIGF1ZiBzdGRvdXQuIEZlaGxlcjogTWVsZHVuZyBhdWYgc3RkZXJyLCBFeGl0LUNvZGUgMS4KICoKICogTnV0enVuZzoKICogICBub2RlIGJvYXJkLm1qcyBpc3N1ZSBjcmVhdGUgLS10aXRsZSAiLi4uIiAtLWJvZHkgIi4uLiIKICogICBub2RlIGJvYXJkLm1qcyBpc3N1ZSBnZXQgPGlkPgogKiAgIG5vZGUgYm9hcmQubWpzIGlzc3VlIGxpc3QgWy0tc3RhdHVzIDxzdGF0dXM+XQogKiAgIG5vZGUgYm9hcmQubWpzIGlzc3VlIG1vdmUgPGlkPiA8c3RhdHVzPgogKiAgIG5vZGUgYm9hcmQubWpzIGlzc3VlIGNvbW1lbnQgPGlkPiAtLXRleHQgIi4uLiIKICogICBub2RlIGJvYXJkLm1qcyBjb2RlIHJlcG8tbmFtZQogKiAgIG5vZGUgYm9hcmQubWpzIGNvZGUgcHIgLS1mcm9tIDxicmFuY2g+IC0tdG8gPGJyYW5jaD4KICovCgppbXBvcnQgeyByZWFkRmlsZVN5bmMsIHdyaXRlRmlsZVN5bmMsIGV4aXN0c1N5bmMsIHJlYWRkaXJTeW5jLCBta2RpclN5bmMgfSBmcm9tICJub2RlOmZzIjsKaW1wb3J0IHsgcmVzb2x2ZSwgam9pbiwgZGlybmFtZSwgYmFzZW5hbWUgfSBmcm9tICJub2RlOnBhdGgiOwppbXBvcnQgeyBmaWxlVVJMVG9QYXRoIH0gZnJvbSAibm9kZTp1cmwiOwppbXBvcnQgeyBleGVjU3luYyB9IGZyb20gIm5vZGU6Y2hpbGRfcHJvY2VzcyI7CmltcG9ydCB7IGhvbWVkaXIgfSBmcm9tICJub2RlOm9zIjsKCmNvbnN0IF9fZGlybmFtZSA9IGRpcm5hbWUoZmlsZVVSTFRvUGF0aChpbXBvcnQubWV0YS51cmwpKTsKCmNvbnN0IFZBTElEX1NUQVRVU0VTID0gWyJiYWNrbG9nIiwgInJlYWR5IiwgImluX3Byb2dyZXNzIiwgImluX3JldmlldyIsICJkb25lIl07Cgpjb25zdCBDT0xVTU5fREVGQVVMVFMgPSB7CiAgYmFja2xvZzogICAgICJCYWNrbG9nIiwKICByZWFkeTogICAgICAgIlJlYWR5IiwKICBpbl9wcm9ncmVzczogIkluIHByb2dyZXNzIiwKICBpbl9yZXZpZXc6ICAgIkluIHJldmlldyIsCiAgZG9uZTogICAgICAgICJEb25lIiwKfTsKCmZ1bmN0aW9uIGNvbHVtbkxhYmVscyhjb25maWcpIHsKICByZXR1cm4gY29uZmlnLmNvbHVtbnMgfHwgQ09MVU1OX0RFRkFVTFRTOwp9CgovLyBFbnRzY2hlaWR1bmdza3JpdGVyaXVtIGZ1ZXIgZGVuIEdpdExhYi1BZGFwdGVyOiAnZG9uZScgaXN0IGltbWVyIGRlciBHaXRMYWItWnVzdGFuZAovLyBDbG9zZWQuICdiYWNrbG9nJyBpc3QgZGVyIEdpdExhYi1adXN0YW5kIE9wZW4gbnVyLCB3ZW5uIHNvIGtvbmZpZ3VyaWVydAovLyAoY29sdW1ucy5iYWNrbG9nID09PSAiT3BlbiIpOyBzb25zdCBlaW4gbm9ybWFsZXMgTGFiZWwuIEFsbGUgYW5kZXJlbiBTcGFsdGVuIHNpbmQKLy8gaW1tZXIgTGFiZWxzLiBFaW56aWdlIFF1ZWxsZSBkZXIgV2FocmhlaXQgZnVlciBjcmVhdGVJc3N1ZS9tb3ZlSXNzdWUvbGlzdElzc3Vlcy9sYWJlbFRvU3RhdHVzLgpmdW5jdGlvbiBpc1N0YXRlQ29sdW1uKHN0YXR1cywgY29uZmlnKSB7CiAgaWYgKHN0YXR1cyA9PT0gImRvbmUiKSByZXR1cm4gdHJ1ZTsKICBpZiAoc3RhdHVzID09PSAiYmFja2xvZyIpIHJldHVybiBjb2x1bW5MYWJlbHMoY29uZmlnKS5iYWNrbG9nID09PSAiT3BlbiI7CiAgcmV0dXJuIGZhbHNlOwp9Cgpjb25zdCBIRUxQID0gYGJvYXJkLm1qcyDigJQgQm9hcmQtQWRhcHRlciBmdWVyIGRhcyBjbGF1ZGUtd29ya2Zsb3cta2l0CgpOdXR6dW5nOgogIG5vZGUgYm9hcmQubWpzIGlzc3VlIGNyZWF0ZSAtLXRpdGxlICIuLi4iIC0tYm9keSAiLi4uIgogIG5vZGUgYm9hcmQubWpzIGlzc3VlIGdldCA8aWQ+CiAgbm9kZSBib2FyZC5tanMgaXNzdWUgbGlzdCBbLS1zdGF0dXMgPHN0YXR1cz5dCiAgbm9kZSBib2FyZC5tanMgaXNzdWUgbW92ZSA8aWQ+IDxzdGF0dXM+CiAgbm9kZSBib2FyZC5tanMgaXNzdWUgY29tbWVudCA8aWQ+IC0tdGV4dCAiLi4uIgogIG5vZGUgYm9hcmQubWpzIGNvZGUgcmVwby1uYW1lCiAgbm9kZSBib2FyZC5tanMgY29kZSBwciAtLWZyb20gPGJyYW5jaD4gLS10byA8YnJhbmNoPgoKR3VlbHRpZ2UgU3RhdHVzLVdlcnRlOiAke1ZBTElEX1NUQVRVU0VTLmpvaW4oIiB8ICIpfQoKS29uZmlndXJhdGlvbjogLmNsYXVkZS93b3JrZmxvdy5jb25maWcuanNvbiAoaXNzdWVUcmFja2VyLCBjb2RlSG9zdCkKRnVlciBHaXRIdWItQm9hcmQtSW50ZWdyYXRpb246IGdpdGh1Yi5wcm9qZWN0TnVtYmVyIGluIGRlciBDb25maWcgc2V0emVuLiBGZWhsdCBzaWUsCndpcmQgYmVpIGdlbmF1IGVpbmVtIEdpdEh1YiBQcm9qZWN0IGZ1ZXIgZGVuIE93bmVyIGF1dG9tYXRpc2NoIGRlc3NlbiBOdW1tZXIgdmVyd2VuZGV0LgpgOwoKLy8gLS0tIFNoZWxsLUhpbGZzZnVua3Rpb25lbiAtLS0KCmZ1bmN0aW9uIGV4ZWMoY21kKSB7CiAgdHJ5IHsKICAgIHJldHVybiBleGVjU3luYyhjbWQsIHsgZW5jb2Rpbmc6ICJ1dGYtOCIsIHN0ZGlvOiBbInBpcGUiLCAicGlwZSIsICJwaXBlIl0gfSkudHJpbSgpOwogIH0gY2F0Y2ggKGUpIHsKICAgIHRocm93IG5ldyBFcnJvcihlLnN0ZGVycj8udG9TdHJpbmcoKS50cmltKCkgfHwgZS5tZXNzYWdlKTsKICB9Cn0KCmZ1bmN0aW9uIGV4ZWNKU09OKGNtZCkgewogIHJldHVybiBKU09OLnBhcnNlKGV4ZWMoY21kKSk7Cn0KCi8vIC0tLSBGZWhsZXJiZWhhbmRsdW5nIC0tLQoKLy8gRXJ3YXJ0ZXRlIEZlaGxlciBhdXMgZGVuIEFkYXB0ZXJuOiBhYmZhbmdiYXIsIGltIENMSS1MYXllciBhbHMgIkZlaGxlcjogLi4uIiBhdXNnZWdlYmVuCmNsYXNzIEJvYXJkRXJyb3IgZXh0ZW5kcyBFcnJvciB7fQoKZnVuY3Rpb24gZmFpbChtc2cpIHsKICBwcm9jZXNzLnN0ZGVyci53cml0ZShgRmVobGVyOiAke21zZ31cbmApOwogIHByb2Nlc3MuZXhpdCgxKTsKfQoKZnVuY3Rpb24gb3V0KGRhdGEpIHsKICBwcm9jZXNzLnN0ZG91dC53cml0ZShKU09OLnN0cmluZ2lmeShkYXRhLCBudWxsLCAyKSArICJcbiIpOwp9CgpmdW5jdGlvbiBzbGVlcChtcykgewogIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCBtcykpOwp9CgovLyAtLS0gQ29uZmlnIGxhZGVuIC0tLQoKZnVuY3Rpb24gbG9hZENvbmZpZygpIHsKICBjb25zdCBjYW5kaWRhdGVzID0gWwogICAgcmVzb2x2ZSgiLmNsYXVkZSIsICJ3b3JrZmxvdy5jb25maWcuanNvbiIpLAogICAgam9pbihfX2Rpcm5hbWUsICIuLiIsICIuY2xhdWRlIiwgIndvcmtmbG93LmNvbmZpZy5qc29uIiksCiAgXTsKICBmb3IgKGNvbnN0IHAgb2YgY2FuZGlkYXRlcykgewogICAgaWYgKGV4aXN0c1N5bmMocCkpIHsKICAgICAgdHJ5IHsKICAgICAgICBjb25zdCByYXcgPSBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhwLCAidXRmLTgiKSk7CiAgICAgICAgLy8gUnVlY2t3YWVydHNrb21wYXRpYmlsaXRhZXQ6IHByb3ZpZGVyIC0+IGNvZGVIb3N0L2lzc3VlVHJhY2tlcgogICAgICAgIGlmIChyYXcucHJvdmlkZXIgJiYgIXJhdy5jb2RlSG9zdCkgcmF3LmNvZGVIb3N0ID0gcmF3LnByb3ZpZGVyOwogICAgICAgIGlmIChyYXcucHJvdmlkZXIgJiYgIXJhdy5pc3N1ZVRyYWNrZXIpIHJhdy5pc3N1ZVRyYWNrZXIgPSByYXcucHJvdmlkZXI7CiAgICAgICAgcmV0dXJuIHJhdzsKICAgICAgfSBjYXRjaCB7CiAgICAgICAgZmFpbChgd29ya2Zsb3cuY29uZmlnLmpzb24ga29ubnRlIG5pY2h0IGdlbGVzZW4gd2VyZGVuOiAke3B9YCk7CiAgICAgIH0KICAgIH0KICB9CiAgZmFpbCgKICAgICJLZWluZSAuY2xhdWRlL3dvcmtmbG93LmNvbmZpZy5qc29uIGdlZnVuZGVuLiBCaXR0ZSB6dWVyc3QgZGVuIEluc3RhbGxlciBhdXNmdWVocmVuLiIKICApOwp9CgovLyAtLS0gQXJndW1lbnQtUGFyc2VyIC0tLQoKZnVuY3Rpb24gcGFyc2VBcmdzKGFyZ3YpIHsKICBjb25zdCByZXN1bHQgPSB7IF86IFtdIH07CiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcmd2Lmxlbmd0aDsgaSsrKSB7CiAgICBjb25zdCBhID0gYXJndltpXTsKICAgIGlmIChhLnN0YXJ0c1dpdGgoIi0tIikpIHsKICAgICAgY29uc3Qga2V5ID0gYS5zbGljZSgyKTsKICAgICAgY29uc3QgbmV4dCA9IGFyZ3ZbaSArIDFdOwogICAgICBpZiAobmV4dCAhPT0gdW5kZWZpbmVkICYmICFuZXh0LnN0YXJ0c1dpdGgoIi0tIikpIHsKICAgICAgICByZXN1bHRba2V5XSA9IG5leHQ7CiAgICAgICAgaSsrOwogICAgICB9IGVsc2UgewogICAgICAgIHJlc3VsdFtrZXldID0gdHJ1ZTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgcmVzdWx0Ll8ucHVzaChhKTsKICAgIH0KICB9CiAgcmV0dXJuIHJlc3VsdDsKfQoKLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ci8vIEdpdEh1Yi1BZGFwdGVyCi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKY2xhc3MgR2l0SHViSXNzdWVUcmFja2VyIHsKICBjb25zdHJ1Y3Rvcihjb25maWcpIHsKICAgIHRoaXMuX2NmZyA9IGNvbmZpZzsKICAgIHRoaXMuX3JlcG9OYW1lID0gbnVsbDsKICAgIHRoaXMuX3Byb2plY3RJZCA9IG51bGw7CiAgICB0aGlzLl9zdGF0dXNGaWVsZCA9IG51bGw7IC8vIHsgaWQsIG9wdGlvbnM6IHsgW3N0YXR1c106IG9wdGlvbklkIH0gfQogICAgdGhpcy5fcHJvamVjdE51bWJlckNhY2hlID0gbnVsbDsKICB9CgogIF9yZXBvKCkgewogICAgaWYgKCF0aGlzLl9yZXBvTmFtZSkgewogICAgICB0aGlzLl9yZXBvTmFtZSA9IGV4ZWMoImdoIHJlcG8gdmlldyAtLWpzb24gbmFtZVdpdGhPd25lciAtcSAubmFtZVdpdGhPd25lciIpOwogICAgfQogICAgcmV0dXJuIHRoaXMuX3JlcG9OYW1lOwogIH0KCiAgX293bmVyKCkgewogICAgcmV0dXJuIHRoaXMuX3JlcG8oKS5zcGxpdCgiLyIpWzBdOwogIH0KCiAgLy8gT2huZSBrb25maWd1cmllcnRlIGdpdGh1Yi5wcm9qZWN0TnVtYmVyIHdpcmQgdmVyc3VjaHQsIGRpZSBOdW1tZXIgYXV0b21hdGlzY2ggenUKICAvLyBlcmtlbm5lbjogZ2lidCBlcyBmdWVyIGRlbiBPd25lciBnZW5hdSBlaW4gR2l0SHViIFByb2plY3QsIHdpcmQgZGllc2VzIHZlcndlbmRldAogIC8vIChtaXQgSGlud2Vpcywga2VpbiBzdGlsbGVyIFNjaHJlaWJ6dWdyaWZmIGF1ZiB3b3JrZmxvdy5jb25maWcuanNvbikuIEJlaSBrZWluZW0KICAvLyBvZGVyIG1laHJlcmVuIFByb2plY3RzIGJsZWlidCBlcyBiZWltIGhhcnRlbiBGZWhsZXIgbWl0IFByb2pla3QtTGlzdGUuIEVyZ2VibmlzCiAgLy8gd2lyZCBwcm8gUHJvemVzcyBtZW1vaXNpZXJ0IHVuZCBkaWUgQXV0by1Fcmtlbm51bmcgenVzYWV0emxpY2ggcHJvemVzc3VlYmVyZ3JlaWZlbmQKICAvLyBnZWNhY2h0IChzaWVoZSBfcmVhZEF1dG9Qcm9qZWN0TnVtYmVyQ2FjaGUpLCBkYW1pdCBuaWNodCBqZWRlciBBdWZydWYgb2huZQogIC8vIGtvbmZpZ3VyaWVydGUgTnVtbWVyIGVybmV1dCBnaCBwcm9qZWN0IGxpc3Qga29zdGV0LgogIF9wcm9qZWN0TnVtYmVyKCkgewogICAgaWYgKHRoaXMuX3Byb2plY3ROdW1iZXJDYWNoZSkgcmV0dXJuIHRoaXMuX3Byb2plY3ROdW1iZXJDYWNoZTsKCiAgICBjb25zdCBjb25maWd1cmVkID0gdGhpcy5fY2ZnLmdpdGh1Yj8ucHJvamVjdE51bWJlcjsKICAgIGlmIChjb25maWd1cmVkKSB7CiAgICAgIHRoaXMuX3Byb2plY3ROdW1iZXJDYWNoZSA9IGNvbmZpZ3VyZWQ7CiAgICAgIHJldHVybiBjb25maWd1cmVkOwogICAgfQoKICAgIGNvbnN0IG93bmVyID0gdGhpcy5fb3duZXIoKTsKICAgIGNvbnN0IGNhY2hlZEF1dG8gPSB0aGlzLl9yZWFkQXV0b1Byb2plY3ROdW1iZXJDYWNoZShvd25lcik7CiAgICBpZiAoY2FjaGVkQXV0bykgewogICAgICB0aGlzLl9wcm9qZWN0TnVtYmVyQ2FjaGUgPSBjYWNoZWRBdXRvOwogICAgICByZXR1cm4gY2FjaGVkQXV0bzsKICAgIH0KCiAgICBjb25zdCBwcm9qZWN0cyA9IGV4ZWNKU09OKGBnaCBwcm9qZWN0IGxpc3QgLS1vd25lciAke293bmVyfSAtLWZvcm1hdCBqc29uYCkucHJvamVjdHMgfHwgW107CiAgICBpZiAocHJvamVjdHMubGVuZ3RoID09PSAxKSB7CiAgICAgIGNvbnN0IG51bSA9IHByb2plY3RzWzBdLm51bWJlcjsKICAgICAgcHJvY2Vzcy5zdGRlcnIud3JpdGUoCiAgICAgICAgYEhpbndlaXM6IGdpdGh1Yi5wcm9qZWN0TnVtYmVyIGZlaGx0IGluIHdvcmtmbG93LmNvbmZpZy5qc29uLCB2ZXJ3ZW5kZSBhdXRvbWF0aXNjaCBgICsKICAgICAgICBgZXJrYW5udGVzIGVpbnppZ2VzIEdpdEh1YiBQcm9qZWN0ICMke251bX0gKCcke3Byb2plY3RzWzBdLnRpdGxlfScpIGZ1ZXIgT3duZXIgJyR7b3duZXJ9Jy4gYCArCiAgICAgICAgYFp1ciBkYXVlcmhhZnRlbiBGaXhpZXJ1bmcgZXJnYWVuemVuOiAnImdpdGh1YiI6IHsgInByb2plY3ROdW1iZXIiOiAke251bX0gfSdcbmAKICAgICAgKTsKICAgICAgdGhpcy5fd3JpdGVBdXRvUHJvamVjdE51bWJlckNhY2hlKG93bmVyLCBudW0pOwogICAgICB0aGlzLl9wcm9qZWN0TnVtYmVyQ2FjaGUgPSBudW07CiAgICAgIHJldHVybiBudW07CiAgICB9CiAgICBpZiAocHJvamVjdHMubGVuZ3RoID09PSAwKSB7CiAgICAgIHRocm93IG5ldyBCb2FyZEVycm9yKAogICAgICAgIGBnaXRodWIucHJvamVjdE51bWJlciBmZWhsdCBpbiB3b3JrZmxvdy5jb25maWcuanNvbiwgdW5kIE93bmVyICcke293bmVyfScgaGF0IGtlaW4gR2l0SHViIFByb2plY3QuIGAgKwogICAgICAgIGBCaXR0ZSBlcmdhbnplbjogJyJnaXRodWIiOiB7ICJwcm9qZWN0TnVtYmVyIjogPE4+IH0nYAogICAgICApOwogICAgfQogICAgY29uc3QgbGlzdCA9IHByb2plY3RzLm1hcCgocCkgPT4gYCMke3AubnVtYmVyfSAoJHtwLnRpdGxlfSlgKS5qb2luKCIsICIpOwogICAgdGhyb3cgbmV3IEJvYXJkRXJyb3IoCiAgICAgIGBnaXRodWIucHJvamVjdE51bWJlciBmZWhsdCBpbiB3b3JrZmxvdy5jb25maWcuanNvbiwgT3duZXIgJyR7b3duZXJ9JyBoYXQgbWVocmVyZSBQcm9qZWN0czogJHtsaXN0fS4gYCArCiAgICAgIGBCaXR0ZSBlcmdhbnplbjogJyJnaXRodWIiOiB7ICJwcm9qZWN0TnVtYmVyIjogPE4+IH0nYAogICAgKTsKICB9CgogIF9hdXRvQ2FjaGVLZXkob3duZXIpIHsKICAgIHJldHVybiBgJHtvd25lcn0jYXV0b2A7CiAgfQoKICBfcmVhZEF1dG9Qcm9qZWN0TnVtYmVyQ2FjaGUob3duZXIpIHsKICAgIGNvbnN0IHAgPSB0aGlzLl9tZXRhQ2FjaGVQYXRoKCk7CiAgICBpZiAoIWV4aXN0c1N5bmMocCkpIHJldHVybiBudWxsOwogICAgdHJ5IHsKICAgICAgY29uc3QgYWxsID0gSlNPTi5wYXJzZShyZWFkRmlsZVN5bmMocCwgInV0Zi04IikpOwogICAgICByZXR1cm4gYWxsW3RoaXMuX2F1dG9DYWNoZUtleShvd25lcildPy5wcm9qZWN0TnVtYmVyIHx8IG51bGw7CiAgICB9IGNhdGNoIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgfQoKICBfd3JpdGVBdXRvUHJvamVjdE51bWJlckNhY2hlKG93bmVyLCBudW0pIHsKICAgIGNvbnN0IHAgPSB0aGlzLl9tZXRhQ2FjaGVQYXRoKCk7CiAgICBsZXQgYWxsID0ge307CiAgICBpZiAoZXhpc3RzU3luYyhwKSkgewogICAgICB0cnkgeyBhbGwgPSBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhwLCAidXRmLTgiKSk7IH0gY2F0Y2ggeyBhbGwgPSB7fTsgfQogICAgfQogICAgYWxsW3RoaXMuX2F1dG9DYWNoZUtleShvd25lcildID0geyBwcm9qZWN0TnVtYmVyOiBudW0gfTsKICAgIG1rZGlyU3luYyhkaXJuYW1lKHApLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTsKICAgIHdyaXRlRmlsZVN5bmMocCwgSlNPTi5zdHJpbmdpZnkoYWxsLCBudWxsLCAyKSArICJcbiIpOwogIH0KCiAgLy8gUHJvamVjdC1JRCwgU3RhdHVzLUZpZWxkLUlEIHVuZCBPcHRpb24tSURzIGFlbmRlcm4gc2ljaCBwcmFrdGlzY2ggbmllLiBTaWUgd2VyZGVuCiAgLy8gZGVzaGFsYiBwZXJzaXN0ZW50IGdlY2FjaHQgKC5jbGF1ZGUvYm9hcmQtbWV0YS1jYWNoZS5qc29uKSwgZGFtaXQgbmljaHQgamVkZXIKICAvLyBib2FyZC5tanMtQXVmcnVmIHp3ZWkgR3JhcGhRTC1BYmZyYWdlbiAoZ2ggcHJvamVjdCBsaXN0IC8gZmllbGQtbGlzdCkga29zdGV0IOKAlCBkZXIKICAvLyBJbi1NZW1vcnktQ2FjaGUgaGFlbHQgbnVyIGlubmVyaGFsYiBlaW5lcyBQcm96ZXNzZXMsIGplZGVyIENMSS1BdWZydWYgaXN0IGFiZXIgbmV1LgogIF9tZXRhQ2FjaGVQYXRoKCkgewogICAgcmV0dXJuIHJlc29sdmUoIi5jbGF1ZGUiLCAiYm9hcmQtbWV0YS1jYWNoZS5qc29uIik7CiAgfQoKICBfbWV0YUNhY2hlS2V5KCkgewogICAgcmV0dXJuIGAke3RoaXMuX293bmVyKCl9IyR7dGhpcy5fcHJvamVjdE51bWJlcigpfWA7CiAgfQoKICBfcmVhZE1ldGFDYWNoZSgpIHsKICAgIGNvbnN0IHAgPSB0aGlzLl9tZXRhQ2FjaGVQYXRoKCk7CiAgICBpZiAoIWV4aXN0c1N5bmMocCkpIHJldHVybiBudWxsOwogICAgbGV0IGFsbDsKICAgIHRyeSB7CiAgICAgIGFsbCA9IEpTT04ucGFyc2UocmVhZEZpbGVTeW5jKHAsICJ1dGYtOCIpKTsKICAgIH0gY2F0Y2ggewogICAgICByZXR1cm4gbnVsbDsgLy8ga29ycnVwdGUgQ2FjaGUtRGF0ZWkgd2llIENhY2hlLU1pc3MgYmVoYW5kZWxuCiAgICB9CiAgICBjb25zdCBlbnRyeSA9IGFsbFt0aGlzLl9tZXRhQ2FjaGVLZXkoKV07CiAgICBpZiAoIWVudHJ5Py5wcm9qZWN0SWQgfHwgIWVudHJ5Py5zdGF0dXNGaWVsZCkgcmV0dXJuIG51bGw7CiAgICAvLyBCZWkgZ2VhZW5kZXJ0ZW4gU3BhbHRlbi1MYWJlbHMgaXN0IGRpZSBPcHRpb24tWnVvcmRudW5nIHZlcmFsdGV0IOKAlCBuZXUgYXVmYmF1ZW4uCiAgICBpZiAoSlNPTi5zdHJpbmdpZnkoZW50cnkuY29sdW1uTGFiZWxzKSAhPT0gSlNPTi5zdHJpbmdpZnkoY29sdW1uTGFiZWxzKHRoaXMuX2NmZykpKSByZXR1cm4gbnVsbDsKICAgIHJldHVybiBlbnRyeTsKICB9CgogIF93cml0ZU1ldGFDYWNoZSgpIHsKICAgIGNvbnN0IHAgPSB0aGlzLl9tZXRhQ2FjaGVQYXRoKCk7CiAgICBsZXQgYWxsID0ge307CiAgICBpZiAoZXhpc3RzU3luYyhwKSkgewogICAgICB0cnkgeyBhbGwgPSBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhwLCAidXRmLTgiKSk7IH0gY2F0Y2ggeyBhbGwgPSB7fTsgfQogICAgfQogICAgYWxsW3RoaXMuX21ldGFDYWNoZUtleSgpXSA9IHsKICAgICAgcHJvamVjdElkOiB0aGlzLl9wcm9qZWN0SWQsCiAgICAgIHN0YXR1c0ZpZWxkOiB0aGlzLl9zdGF0dXNGaWVsZCwKICAgICAgY29sdW1uTGFiZWxzOiBjb2x1bW5MYWJlbHModGhpcy5fY2ZnKSwKICAgIH07CiAgICBta2RpclN5bmMoZGlybmFtZShwKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7CiAgICB3cml0ZUZpbGVTeW5jKHAsIEpTT04uc3RyaW5naWZ5KGFsbCwgbnVsbCwgMikgKyAiXG4iKTsKICB9CgogIF9pbnZhbGlkYXRlTWV0YUNhY2hlKCkgewogICAgdGhpcy5fcHJvamVjdElkID0gbnVsbDsKICAgIHRoaXMuX3N0YXR1c0ZpZWxkID0gbnVsbDsKICAgIGNvbnN0IHAgPSB0aGlzLl9tZXRhQ2FjaGVQYXRoKCk7CiAgICBpZiAoIWV4aXN0c1N5bmMocCkpIHJldHVybjsKICAgIHRyeSB7CiAgICAgIGNvbnN0IGFsbCA9IEpTT04ucGFyc2UocmVhZEZpbGVTeW5jKHAsICJ1dGYtOCIpKTsKICAgICAgZGVsZXRlIGFsbFt0aGlzLl9tZXRhQ2FjaGVLZXkoKV07CiAgICAgIHdyaXRlRmlsZVN5bmMocCwgSlNPTi5zdHJpbmdpZnkoYWxsLCBudWxsLCAyKSArICJcbiIpOwogICAgfSBjYXRjaCB7CiAgICAgIC8vIGtvcnJ1cHRlIERhdGVpOiBkZXIgbmFlY2hzdGUgX3dyaXRlTWV0YUNhY2hlIHVlYmVyc2NocmVpYnQgc2llIG9obmVoaW4KICAgIH0KICB9CgogIF9lbnN1cmVQcm9qZWN0TWV0YSgpIHsKICAgIGlmICh0aGlzLl9wcm9qZWN0SWQgJiYgdGhpcy5fc3RhdHVzRmllbGQpIHJldHVybjsKCiAgICBjb25zdCBjYWNoZWQgPSB0aGlzLl9yZWFkTWV0YUNhY2hlKCk7CiAgICBpZiAoY2FjaGVkKSB7CiAgICAgIHRoaXMuX3Byb2plY3RJZCA9IGNhY2hlZC5wcm9qZWN0SWQ7CiAgICAgIHRoaXMuX3N0YXR1c0ZpZWxkID0gY2FjaGVkLnN0YXR1c0ZpZWxkOwogICAgICByZXR1cm47CiAgICB9CgogICAgdGhpcy5fbG9hZFByb2plY3RNZXRhRnJvbUFwaSgpOwogICAgdGhpcy5fd3JpdGVNZXRhQ2FjaGUoKTsKICB9CgogIF9sb2FkUHJvamVjdE1ldGFGcm9tQXBpKCkgewogICAgY29uc3Qgb3duZXIgPSB0aGlzLl9vd25lcigpOwogICAgY29uc3QgbnVtID0gdGhpcy5fcHJvamVjdE51bWJlcigpOwoKICAgIC8vIFByb2plY3QtSUQKICAgIGNvbnN0IHByb2plY3RMaXN0ID0gZXhlY0pTT04oYGdoIHByb2plY3QgbGlzdCAtLW93bmVyICR7b3duZXJ9IC0tZm9ybWF0IGpzb25gKTsKICAgIGNvbnN0IHByb2plY3QgPSAocHJvamVjdExpc3QucHJvamVjdHMgfHwgW10pLmZpbmQoKHApID0+IHAubnVtYmVyID09PSBudW0pOwogICAgaWYgKCFwcm9qZWN0KSB0aHJvdyBuZXcgQm9hcmRFcnJvcihgR2l0SHViIFByb2plY3QgIyR7bnVtfSBuaWNodCBnZWZ1bmRlbiBmdWVyIE93bmVyICcke293bmVyfSdgKTsKICAgIHRoaXMuX3Byb2plY3RJZCA9IHByb2plY3QuaWQ7CgogICAgLy8gU3RhdHVzLUZpZWxkIHVuZCBPcHRpb25lbgogICAgY29uc3QgZmllbGRzID0gZXhlY0pTT04oYGdoIHByb2plY3QgZmllbGQtbGlzdCAke251bX0gLS1vd25lciAke293bmVyfSAtLWZvcm1hdCBqc29uYCk7CiAgICBjb25zdCBzdGF0dXNGaWVsZCA9IChmaWVsZHMuZmllbGRzIHx8IFtdKS5maW5kKChmKSA9PiBmLm5hbWUgPT09ICJTdGF0dXMiKTsKICAgIGlmICghc3RhdHVzRmllbGQpIHRocm93IG5ldyBCb2FyZEVycm9yKGBLZWluICdTdGF0dXMnLUZlbGQgaW4gR2l0SHViIFByb2plY3QgIyR7bnVtfSBnZWZ1bmRlbmApOwoKICAgIGNvbnN0IG9wdGlvbk1hcCA9IHt9OwogICAgZm9yIChjb25zdCBvcHQgb2Ygc3RhdHVzRmllbGQub3B0aW9ucyB8fCBbXSkgewogICAgICAvLyBOb3JtYWxpc2llcmUgZGVuIE9wdGlvbi1OYW1lbiBhdWYgZGVuIFN0YXR1cy1FbnVtCiAgICAgIGNvbnN0IGxhYmVscyA9IGNvbHVtbkxhYmVscyh0aGlzLl9jZmcpOwogICAgICBjb25zdCBrZXkgPSBPYmplY3Qua2V5cyhsYWJlbHMpLmZpbmQoCiAgICAgICAgKGspID0+IGxhYmVsc1trXS50b0xvd2VyQ2FzZSgpID09PSBvcHQubmFtZS50b0xvd2VyQ2FzZSgpCiAgICAgICk7CiAgICAgIGlmIChrZXkpIHsKICAgICAgICBpZiAobGFiZWxzW2tleV0gIT09IG9wdC5uYW1lKSB7CiAgICAgICAgICBwcm9jZXNzLnN0ZGVyci53cml0ZSgKICAgICAgICAgICAgYEhpbndlaXM6IHdvcmtmbG93LmNvbmZpZy5qc29uIGtvbmZpZ3VyaWVydCBmdWVyIFN0YXR1cyAnJHtrZXl9JyBkYXMgTGFiZWwgJyR7bGFiZWxzW2tleV19JywgYCArCiAgICAgICAgICAgIGBkYXMgR2l0SHViIFByb2plY3QgdmVyd2VuZGV0IHRhdHNhZWNobGljaCAnJHtvcHQubmFtZX0nIChHcm9zcy0vS2xlaW5zY2hyZWlidW5nIHdlaWNodCBhYikuIGAgKwogICAgICAgICAgICBgQWt0dWVsbCBub2NoIHBlciBGYWxsYmFjayBlcmthbm50IOKAlCB6dXIgVmVybWVpZHVuZyBzdGlsbGVyIEZvbGdlZmVobGVyIGJpdHRlIGluIGAgKwogICAgICAgICAgICBgd29ya2Zsb3cuY29uZmlnLmpzb24gYW5wYXNzZW46ICciY29sdW1ucyI6IHsgIiR7a2V5fSI6ICIke29wdC5uYW1lfSIgfSdcbmAKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIG9wdGlvbk1hcFtrZXldID0gb3B0LmlkOwogICAgICB9CiAgICB9CiAgICB0aGlzLl9zdGF0dXNGaWVsZCA9IHsgaWQ6IHN0YXR1c0ZpZWxkLmlkLCBvcHRpb25zOiBvcHRpb25NYXAgfTsKICB9CgogIC8vIEdlemllbHRlciBMb29rdXAgZGVyIFByb2plY3QtSXRlbS1JRCBmdWVyIGdlbmF1IGRpZXNlcyBlaW5lIElzc3VlIHZpYSBHcmFwaFFMLQogIC8vIEVpbnplbGFiZnJhZ2UgKHJlcG9zaXRvcnkgLT4gaXNzdWUgLT4gcHJvamVjdEl0ZW1zKS4gS29zdGV0IH4xIEtvbnRpbmdlbnRwdW5rdAogIC8vIHVuYWJoYWVuZ2lnIHZvbiBkZXIgQm9hcmRncm9lc3NlIOKAlCBzdGF0dCBlaW5lcyBwYWdpbmllcnRlbiBgZ2ggcHJvamVjdCBpdGVtLWxpc3RgCiAgLy8gdWViZXIgYWxsZSBiaXMgenUgMTAwMCBJdGVtcywgZGFzIGplIG5hY2ggQm9hcmQgendlaXN0ZWxsaWdlIFB1bmt0emFobGVuIHZlcmJyYXVjaHQuCiAgX2dldFByb2plY3RJdGVtSWQoaXNzdWVOdW1iZXIpIHsKICAgIGNvbnN0IG93bmVyID0gdGhpcy5fb3duZXIoKTsKICAgIGNvbnN0IHJlcG9OYW1lID0gdGhpcy5fcmVwbygpLnNwbGl0KCIvIilbMV07CiAgICBjb25zdCBudW0gPSB0aGlzLl9wcm9qZWN0TnVtYmVyKCk7CiAgICBjb25zdCBudW1iZXIgPSBOdW1iZXIoaXNzdWVOdW1iZXIpOwoKICAgIGNvbnN0IHF1ZXJ5ID0gWwogICAgICAicXVlcnkoJG93bmVyOlN0cmluZyEsJHJlcG86U3RyaW5nISwkbnVtYmVyOkludCEpeyIsCiAgICAgICIgIHJlcG9zaXRvcnkob3duZXI6JG93bmVyLG5hbWU6JHJlcG8peyIsCiAgICAgICIgICAgaXNzdWUobnVtYmVyOiRudW1iZXIpeyIsCiAgICAgICIgICAgICBwcm9qZWN0SXRlbXMoZmlyc3Q6MjApeyIsCiAgICAgICIgICAgICAgIG5vZGVzeyIsCiAgICAgICIgICAgICAgICAgaWQiLAogICAgICAiICAgICAgICAgIHByb2plY3R7IG51bWJlciBvd25lcnsgLi4uIG9uIFVzZXJ7IGxvZ2luIH0gLi4uIG9uIE9yZ2FuaXphdGlvbnsgbG9naW4gfSB9IH0iLAogICAgICAiICAgICAgICB9IiwKICAgICAgIiAgICAgIH0iLAogICAgICAiICAgIH0iLAogICAgICAiICB9IiwKICAgICAgIn0iLAogICAgXS5qb2luKCJcbiIpOwoKICAgIGNvbnN0IGRhdGEgPSBleGVjSlNPTigKICAgICAgYGdoIGFwaSBncmFwaHFsIC1mIHF1ZXJ5PSR7c2hlbGxRdW90ZShxdWVyeSl9IGAgKwogICAgICBgLWYgb3duZXI9JHtzaGVsbFF1b3RlKG93bmVyKX0gLWYgcmVwbz0ke3NoZWxsUXVvdGUocmVwb05hbWUpfSAtRiBudW1iZXI9JHtudW1iZXJ9YAogICAgKTsKCiAgICBjb25zdCBpc3N1ZSA9IGRhdGE/LmRhdGE/LnJlcG9zaXRvcnk/Lmlzc3VlOwogICAgaWYgKCFpc3N1ZSkgdGhyb3cgbmV3IEJvYXJkRXJyb3IoYElzc3VlICMke2lzc3VlTnVtYmVyfSBuaWNodCBpbiBSZXBvICcke3RoaXMuX3JlcG8oKX0nIGdlZnVuZGVuYCk7CgogICAgY29uc3Qgbm9kZXMgPSBpc3N1ZS5wcm9qZWN0SXRlbXM/Lm5vZGVzIHx8IFtdOwogICAgY29uc3QgaXRlbSA9IG5vZGVzLmZpbmQoCiAgICAgIChuKSA9PiBuLnByb2plY3Q/Lm51bWJlciA9PT0gbnVtICYmIG4ucHJvamVjdD8ub3duZXI/LmxvZ2luID09PSBvd25lcgogICAgKTsKICAgIGlmICghaXRlbSkgdGhyb3cgbmV3IEJvYXJkRXJyb3IoYElzc3VlICMke2lzc3VlTnVtYmVyfSBuaWNodCBpbSBQcm9qZWN0IEJvYXJkICMke251bX0gZ2VmdW5kZW5gKTsKICAgIHJldHVybiBpdGVtLmlkOwogIH0KCiAgYXN5bmMgY3JlYXRlSXNzdWUoeyB0aXRsZSwgYm9keSB9KSB7CiAgICBjb25zdCByZXBvID0gdGhpcy5fcmVwbygpOwogICAgY29uc3Qgb3V0cHV0ID0gZXhlYygKICAgICAgYGdoIGlzc3VlIGNyZWF0ZSAtLXJlcG8gJHtyZXBvfSAtLXRpdGxlICR7c2hlbGxRdW90ZSh0aXRsZSl9IC0tYm9keSAke3NoZWxsUXVvdGUoYm9keSB8fCAiIil9YAogICAgKTsKICAgIC8vIGdoIGdpYnQgZ2dmLiBIaW53ZWlzemVpbGVuIHZvciBkZXIgVVJMIGF1cyDigJQgVVJMIHVuZCBJRCBwZXIgUmVnZXggZXh0cmFoaWVyZW4KICAgIGNvbnN0IG1hdGNoID0gb3V0cHV0Lm1hdGNoKC8oaHR0cHM/OlwvXC9cUytcL2lzc3Vlc1wvKFxkKykpLyk7CiAgICBpZiAoIW1hdGNoKSB0aHJvdyBuZXcgQm9hcmRFcnJvcihgS29ubnRlIElzc3VlLVVSTCBhdXMgZ2gtQXVzZ2FiZSBuaWNodCBsZXNlbjogJHtvdXRwdXR9YCk7CiAgICBjb25zdCB1cmwgPSBtYXRjaFsxXTsKICAgIGNvbnN0IGlkID0gbWF0Y2hbMl07CgogICAgLy8gQW5zIFByb2plY3QgQm9hcmQgaGFlbmdlbi4gX3Byb2plY3ROdW1iZXIoKSB3aXJmdCwgd2VubiB3ZWRlciBrb25maWd1cmllcnQKICAgIC8vIG5vY2ggZWluZGV1dGlnIGF1dG9tYXRpc2NoIGVya2VubmJhciDigJQgZGFubiBibGVpYnQgZGllIFp1b3JkbnVuZyBhdXMgKEhpbndlaXMpLgogICAgdHJ5IHsKICAgICAgY29uc3Qgb3duZXIgPSB0aGlzLl9vd25lcigpOwogICAgICBjb25zdCBudW0gPSB0aGlzLl9wcm9qZWN0TnVtYmVyKCk7CiAgICAgIGV4ZWMoYGdoIHByb2plY3QgaXRlbS1hZGQgJHtudW19IC0tb3duZXIgJHtvd25lcn0gLS11cmwgJHt1cmx9YCk7CiAgICAgIC8vIFN0YXR1cyBhdWYgYmFja2xvZyBzZXR6ZW4uIGl0ZW0tbGlzdCB6ZWlndCBmcmlzY2ggaGluenVnZWZ1ZWd0ZSBJdGVtcwogICAgICAvLyB0ZWlscyB2ZXJ6b2VnZXJ0IChFdmVudHVhbCBDb25zaXN0ZW5jeSkg4oCUIGRhaGVyIGt1cnplciBSZXRyeS4KICAgICAgbGV0IGxhc3RFcnIgPSBudWxsOwogICAgICBmb3IgKGxldCBhdHRlbXB0ID0gMTsgYXR0ZW1wdCA8PSAzOyBhdHRlbXB0KyspIHsKICAgICAgICBpZiAoYXR0ZW1wdCA+IDEpIGF3YWl0IHNsZWVwKDI1MDApOwogICAgICAgIHRyeSB7CiAgICAgICAgICBhd2FpdCB0aGlzLm1vdmVJc3N1ZShpZCwgImJhY2tsb2ciKTsKICAgICAgICAgIGxhc3RFcnIgPSBudWxsOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgbGFzdEVyciA9IGU7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChsYXN0RXJyKSB0aHJvdyBsYXN0RXJyOwogICAgfSBjYXRjaCAoZSkgewogICAgICBwcm9jZXNzLnN0ZGVyci53cml0ZShgSGlud2VpczogQm9hcmQtWnVvcmRudW5nIGZlaGxnZXNjaGxhZ2VuOiAke2UubWVzc2FnZX1cbmApOwogICAgfQogICAgcmV0dXJuIHsgaWQsIHVybCB9OwogIH0KCiAgYXN5bmMgZ2V0SXNzdWUoaWQpIHsKICAgIGNvbnN0IHJlcG8gPSB0aGlzLl9yZXBvKCk7CiAgICBjb25zdCBkYXRhID0gZXhlY0pTT04oCiAgICAgIGBnaCBpc3N1ZSB2aWV3ICR7aWR9IC0tcmVwbyAke3JlcG99IC0tanNvbiBudW1iZXIsdGl0bGUsYm9keSxzdGF0ZWAKICAgICk7CiAgICByZXR1cm4gewogICAgICBpZDogU3RyaW5nKGRhdGEubnVtYmVyKSwKICAgICAgdGl0bGU6IGRhdGEudGl0bGUsCiAgICAgIGJvZHk6IGRhdGEuYm9keSwKICAgICAgc3RhdHVzOiBudWxsLCAvLyBCb2FyZC1TdGF0dXMgbmljaHQgaW0gSXNzdWUtT2JqZWt0LCBlcmZvcmRlcnQgUHJvamVjdC1BYmZyYWdlCiAgICB9OwogIH0KCiAgYXN5bmMgbGlzdElzc3VlcyhzdGF0dXMpIHsKICAgIGNvbnN0IHJlcG8gPSB0aGlzLl9yZXBvKCk7CgogICAgaWYgKCFzdGF0dXMpIHsKICAgICAgY29uc3QgaXRlbXMgPSBleGVjSlNPTigKICAgICAgICBgZ2ggaXNzdWUgbGlzdCAtLXJlcG8gJHtyZXBvfSAtLXN0YXRlIG9wZW4gLS1qc29uIG51bWJlcix0aXRsZSxib2R5YAogICAgICApOwogICAgICByZXR1cm4gaXRlbXMubWFwKChpKSA9PiAoeyBpZDogU3RyaW5nKGkubnVtYmVyKSwgdGl0bGU6IGkudGl0bGUsIGJvZHk6IGkuYm9keSwgc3RhdHVzOiBudWxsIH0pKTsKICAgIH0KCiAgICAvLyBGaWx0ZXJ1bmcgbmFjaCBCb2FyZC1TdGF0dXMgdmlhIFByb2plY3QKICAgIGxldCBudW07CiAgICB0cnkgewogICAgICBudW0gPSB0aGlzLl9wcm9qZWN0TnVtYmVyKCk7CiAgICB9IGNhdGNoIHsKICAgICAgcHJvY2Vzcy5zdGRlcnIud3JpdGUoCiAgICAgICAgIkhpbndlaXM6IEtlaW4gZWluZGV1dGlnZXMgR2l0SHViIFByb2plY3QgYmVzdGltbWJhciwga2VpbiBCb2FyZC1TdGF0dXMtRmlsdGVyIG1vZWdsaWNoLiBMaXN0ZSBhbGxlIG9mZmVuZW4gSXNzdWVzLlxuIgogICAgICApOwogICAgICByZXR1cm4gdGhpcy5saXN0SXNzdWVzKHVuZGVmaW5lZCk7CiAgICB9CgogICAgdGhpcy5fZW5zdXJlUHJvamVjdE1ldGEoKTsKICAgIGNvbnN0IG93bmVyID0gdGhpcy5fb3duZXIoKTsKICAgIGNvbnN0IGl0ZW1zID0gZXhlY0pTT04oYGdoIHByb2plY3QgaXRlbS1saXN0ICR7bnVtfSAtLW93bmVyICR7b3duZXJ9IC0tZm9ybWF0IGpzb24gLS1saW1pdCAxMDAwYCk7CgogICAgY29uc3Qgb3B0aW9uSWQgPSB0aGlzLl9zdGF0dXNGaWVsZC5vcHRpb25zW3N0YXR1c107CiAgICBpZiAoIW9wdGlvbklkKSB0aHJvdyBuZXcgQm9hcmRFcnJvcihgU3RhdHVzICcke3N0YXR1c30nIGhhdCBrZWluZSBFbnRzcHJlY2h1bmcgaW0gR2l0SHViIFByb2plY3RgKTsKCiAgICBjb25zdCB3YW50ZWRTdGF0dXMgPSBnaXRodWJTdGF0dXNOYW1lKHN0YXR1cywgdGhpcy5fY2ZnKS50b0xvd2VyQ2FzZSgpOwogICAgcmV0dXJuIChpdGVtcy5pdGVtcyB8fCBbXSkKICAgICAgLmZpbHRlcigoaSkgPT4gKGkuc3RhdHVzIHx8ICIiKS50b0xvd2VyQ2FzZSgpID09PSB3YW50ZWRTdGF0dXMpCiAgICAgIC5tYXAoKGkpID0+ICh7CiAgICAgICAgaWQ6IFN0cmluZyhpLmNvbnRlbnQ/Lm51bWJlciksCiAgICAgICAgdGl0bGU6IGkuY29udGVudD8udGl0bGUsCiAgICAgICAgYm9keTogbnVsbCwKICAgICAgICBzdGF0dXMsCiAgICAgIH0pKQogICAgICAuc29ydCgoYSwgYikgPT4gTnVtYmVyKGEuaWQpIC0gTnVtYmVyKGIuaWQpKTsKICB9CgogIGFzeW5jIG1vdmVJc3N1ZShpZCwgdG8pIHsKICAgIHRoaXMuX2Vuc3VyZVByb2plY3RNZXRhKCk7CiAgICBjb25zdCBpdGVtSWQgPSB0aGlzLl9nZXRQcm9qZWN0SXRlbUlkKGlkKTsKICAgIHRoaXMuX29wdGlvbklkRm9yKHRvKTsgLy8gd2lyZnQgZnJ1ZWgsIGZhbGxzIFN0YXR1cyB1bmJla2FubnQKCiAgICB0cnkgewogICAgICB0aGlzLl9lZGl0SXRlbVN0YXR1cyhpdGVtSWQsIHRvKTsKICAgIH0gY2F0Y2ggKGZpcnN0RXJyKSB7CiAgICAgIC8vIEdlY2FjaHRlIElEcyBrb2VubnRlbiB2ZXJhbHRldCBzZWluICh6LkIuIE9wdGlvbi1JRCBpbSBQcm9qZWN0IGVudGZlcm50KSDigJQKICAgICAgLy8gQ2FjaGUgdmVyd2VyZmVuLCBNZXRhIGZyaXNjaCBhdXMgZGVyIEFQSSBsYWRlbiB1bmQgZWlubWFsIHdpZWRlcmhvbGVuLgogICAgICB0aGlzLl9pbnZhbGlkYXRlTWV0YUNhY2hlKCk7CiAgICAgIHRoaXMuX2Vuc3VyZVByb2plY3RNZXRhKCk7CiAgICAgIHRyeSB7CiAgICAgICAgdGhpcy5fZWRpdEl0ZW1TdGF0dXMoaXRlbUlkLCB0byk7CiAgICAgIH0gY2F0Y2ggKHJldHJ5RXJyKSB7CiAgICAgICAgdGhyb3cgbmV3IEJvYXJkRXJyb3IoCiAgICAgICAgICBgU3RhdHVzLVVwZGF0ZSBmZWhsZ2VzY2hsYWdlbiAoYXVjaCBuYWNoIENhY2hlLVJlZnJlc2gpOiAke3JldHJ5RXJyLm1lc3NhZ2V9IGAgKwogICAgICAgICAgYCh1cnNwcnVlbmdsaWNoZXIgRmVobGVyOiAke2ZpcnN0RXJyLm1lc3NhZ2V9KWAKICAgICAgICApOwogICAgICB9CiAgICB9CiAgfQoKICBfb3B0aW9uSWRGb3Ioc3RhdHVzKSB7CiAgICBjb25zdCBvcHRpb25JZCA9IHRoaXMuX3N0YXR1c0ZpZWxkLm9wdGlvbnNbc3RhdHVzXTsKICAgIGlmICghb3B0aW9uSWQpIHRocm93IG5ldyBCb2FyZEVycm9yKGBTdGF0dXMgJyR7c3RhdHVzfScgaGF0IGtlaW5lIEVudHNwcmVjaHVuZyBpbSBHaXRIdWIgUHJvamVjdGApOwogICAgcmV0dXJuIG9wdGlvbklkOwogIH0KCiAgX2VkaXRJdGVtU3RhdHVzKGl0ZW1JZCwgc3RhdHVzKSB7CiAgICBleGVjKAogICAgICBgZ2ggcHJvamVjdCBpdGVtLWVkaXQgLS1pZCAke2l0ZW1JZH0gLS1wcm9qZWN0LWlkICR7dGhpcy5fcHJvamVjdElkfSBgICsKICAgICAgYC0tZmllbGQtaWQgJHt0aGlzLl9zdGF0dXNGaWVsZC5pZH0gLS1zaW5nbGUtc2VsZWN0LW9wdGlvbi1pZCAke3RoaXMuX29wdGlvbklkRm9yKHN0YXR1cyl9YAogICAgKTsKICB9CgogIGFzeW5jIGNvbW1lbnRJc3N1ZShpZCwgdGV4dCkgewogICAgY29uc3QgcmVwbyA9IHRoaXMuX3JlcG8oKTsKICAgIGV4ZWMoYGdoIGlzc3VlIGNvbW1lbnQgJHtpZH0gLS1yZXBvICR7cmVwb30gLS1ib2R5ICR7c2hlbGxRdW90ZSh0ZXh0KX1gKTsKICB9Cn0KCmZ1bmN0aW9uIGdpdGh1YlN0YXR1c05hbWUoc3RhdHVzLCBjb25maWcpIHsKICByZXR1cm4gY29sdW1uTGFiZWxzKGNvbmZpZylbc3RhdHVzXSB8fCBzdGF0dXM7Cn0KCmNsYXNzIEdpdEh1YkNvZGVIb3N0IHsKICBjb25zdHJ1Y3Rvcihjb25maWcpIHsgdGhpcy5fY2ZnID0gY29uZmlnOyB9CgogIGFzeW5jIGdldFJlcG9OYW1lKCkgewogICAgdHJ5IHsKICAgICAgcmV0dXJuIGV4ZWMoImdoIHJlcG8gdmlldyAtLWpzb24gbmFtZVdpdGhPd25lciAtcSAubmFtZVdpdGhPd25lciIpOwogICAgfSBjYXRjaCB7CiAgICAgIHJldHVybiBleGVjKCJnaXQgcmVtb3RlIGdldC11cmwgb3JpZ2luIDI+L2Rldi9udWxsIHx8IGJhc2VuYW1lICQocHdkKSIpOwogICAgfQogIH0KCiAgc3VwcG9ydHNQdWxsUmVxdWVzdHMoKSB7IHJldHVybiB0cnVlOyB9CgogIGFzeW5jIGNyZWF0ZVB1bGxSZXF1ZXN0KHsgZnJvbSwgdG8sIHRpdGxlIH0pIHsKICAgIGNvbnN0IHQgPSB0aXRsZSB8fCBgJHtmcm9tfSDihpIgJHt0b31gOwogICAgY29uc3QgdXJsID0gZXhlYygKICAgICAgYGdoIHByIGNyZWF0ZSAtLWJhc2UgJHt0b30gLS1oZWFkICR7ZnJvbX0gLS10aXRsZSAke3NoZWxsUXVvdGUodCl9IC0tYm9keSAiImAKICAgICk7CiAgICByZXR1cm4geyB1cmwgfTsKICB9Cn0KCi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQovLyBHaXRMYWItQWRhcHRlcgovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCmNsYXNzIEdpdExhYklzc3VlVHJhY2tlciB7CiAgY29uc3RydWN0b3IoY29uZmlnKSB7IHRoaXMuX2NmZyA9IGNvbmZpZzsgfQoKICBhc3luYyBjcmVhdGVJc3N1ZSh7IHRpdGxlLCBib2R5IH0pIHsKICAgIGNvbnN0IG91dHB1dCA9IGV4ZWMoCiAgICAgIGBnbGFiIGlzc3VlIGNyZWF0ZSAtLXRpdGxlICR7c2hlbGxRdW90ZSh0aXRsZSl9IC0tZGVzY3JpcHRpb24gJHtzaGVsbFF1b3RlKGJvZHkgfHwgIiIpfWAKICAgICk7CiAgICAvLyBnbGFiIGdpYnQgZGllIElzc3VlLVVSTCBhdXMsIHouQi4gaHR0cHM6Ly9naXRsYWIuY29tL293bmVyL3JlcG8vLS9pc3N1ZXMvNDIKICAgIGNvbnN0IG1hdGNoID0gb3V0cHV0Lm1hdGNoKC9cL2lzc3Vlc1wvKFxkKykvKTsKICAgIGlmICghbWF0Y2gpIHRocm93IG5ldyBCb2FyZEVycm9yKGBLb25udGUgSXNzdWUtSUQgYXVzIGdsYWItQXVzZ2FiZSBuaWNodCBsZXNlbjogJHtvdXRwdXR9YCk7CiAgICBjb25zdCBpZCA9IG1hdGNoWzFdOwogICAgLy8gQmFja2xvZy1MYWJlbCBudXIgc2V0emVuLCB3ZW5uIGJhY2tsb2cgcGVyIENvbmZpZyB1ZWJlcmhhdXB0IGVpbiBMYWJlbCBpc3QKICAgIC8vIChuaWNodCBkZXIgbmF0aXZlIE9wZW4tWnVzdGFuZCkg4oCUIHNvbnN0IGJsZWlidCBkYXMgbmV1ZSBJc3N1ZSBlaW5mYWNoIG9mZmVuLgogICAgaWYgKCFpc1N0YXRlQ29sdW1uKCJiYWNrbG9nIiwgdGhpcy5fY2ZnKSkgewogICAgICBjb25zdCBsYWJlbCA9IGNvbHVtbkxhYmVscyh0aGlzLl9jZmcpLmJhY2tsb2c7CiAgICAgIHRyeSB7CiAgICAgICAgZXhlYyhgZ2xhYiBpc3N1ZSB1cGRhdGUgJHtpZH0gLS1sYWJlbCAke3NoZWxsUXVvdGUobGFiZWwpfWApOwogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgcHJvY2Vzcy5zdGRlcnIud3JpdGUoYEhpbndlaXM6IEJhY2tsb2ctTGFiZWwga29ubnRlIG5pY2h0IGdlc2V0enQgd2VyZGVuOiAke2UubWVzc2FnZX1cbmApOwogICAgICB9CiAgICB9CiAgICByZXR1cm4geyBpZCwgdXJsOiBvdXRwdXQudHJpbSgpIH07CiAgfQoKICBhc3luYyBnZXRJc3N1ZShpZCkgewogICAgY29uc3QgZGF0YSA9IGV4ZWNKU09OKGBnbGFiIGlzc3VlIHZpZXcgJHtpZH0gLS1vdXRwdXQganNvbmApOwogICAgY29uc3QgbGFiZWxOYW1lcyA9IChkYXRhLmxhYmVscyB8fCBbXSkubWFwKChsKSA9PiBsLm5hbWUgfHwgbCk7CiAgICBjb25zdCBzdGF0dXMgPSBsYWJlbFRvU3RhdHVzKGxhYmVsTmFtZXMsIHRoaXMuX2NmZywgZGF0YS5zdGF0ZSkgfHwgbnVsbDsKICAgIHJldHVybiB7CiAgICAgIGlkOiBTdHJpbmcoZGF0YS5paWQgfHwgZGF0YS5pZCksCiAgICAgIHRpdGxlOiBkYXRhLnRpdGxlLAogICAgICBib2R5OiBkYXRhLmRlc2NyaXB0aW9uLAogICAgICBzdGF0dXMsCiAgICB9OwogIH0KCiAgYXN5bmMgbGlzdElzc3VlcyhzdGF0dXMpIHsKICAgIGxldCBjbWQgPSAiZ2xhYiBpc3N1ZSBsaXN0IC0tb3V0cHV0IGpzb24iOwogICAgaWYgKHN0YXR1cykgewogICAgICBpZiAoaXNTdGF0ZUNvbHVtbihzdGF0dXMsIHRoaXMuX2NmZykpIHsKICAgICAgICBpZiAoc3RhdHVzID09PSAiZG9uZSIpIHsKICAgICAgICAgIGNtZCArPSAiIC0tY2xvc2VkIjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgLy8gYmFja2xvZyBhbHMgT3Blbi1adXN0YW5kOiBvZmZlbmUgSXNzdWVzIG9obmUgZGllIGFuZGVyZW4gU3RhdHVzLUxhYmVscy4KICAgICAgICAgIGNvbnN0IG90aGVyTGFiZWxzID0gT2JqZWN0LmVudHJpZXMoY29sdW1uTGFiZWxzKHRoaXMuX2NmZykpCiAgICAgICAgICAgIC5maWx0ZXIoKFtzXSkgPT4gcyAhPT0gImJhY2tsb2ciICYmICFpc1N0YXRlQ29sdW1uKHMsIHRoaXMuX2NmZykpCiAgICAgICAgICAgIC5tYXAoKFssIGxdKSA9PiBsKTsKICAgICAgICAgIGNtZCArPSBvdGhlckxhYmVscy5tYXAoKGwpID0+IGAgLS1ub3QtbGFiZWwgJHtzaGVsbFF1b3RlKGwpfWApLmpvaW4oIiIpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBsYWJlbCA9IGNvbHVtbkxhYmVscyh0aGlzLl9jZmcpW3N0YXR1c107CiAgICAgICAgaWYgKCFsYWJlbCkgdGhyb3cgbmV3IEJvYXJkRXJyb3IoYFN0YXR1cyAnJHtzdGF0dXN9JyBoYXQga2VpbiBHaXRMYWItTGFiZWwtTWFwcGluZ2ApOwogICAgICAgIGNtZCArPSBgIC0tbGFiZWwgJHtzaGVsbFF1b3RlKGxhYmVsKX1gOwogICAgICB9CiAgICB9CiAgICBjb25zdCBpdGVtcyA9IGV4ZWNKU09OKGNtZCk7CiAgICByZXR1cm4gKEFycmF5LmlzQXJyYXkoaXRlbXMpID8gaXRlbXMgOiBbXSkKICAgICAgLm1hcCgoaSkgPT4gewogICAgICAgIGNvbnN0IGxhYmVsTmFtZXMgPSAoaS5sYWJlbHMgfHwgW10pLm1hcCgobCkgPT4gbC5uYW1lIHx8IGwpOwogICAgICAgIHJldHVybiB7CiAgICAgICAgICBpZDogU3RyaW5nKGkuaWlkKSwKICAgICAgICAgIHRpdGxlOiBpLnRpdGxlLAogICAgICAgICAgYm9keTogaS5kZXNjcmlwdGlvbiwKICAgICAgICAgIHN0YXR1czogbGFiZWxUb1N0YXR1cyhsYWJlbE5hbWVzLCB0aGlzLl9jZmcsIGkuc3RhdGUpIHx8IG51bGwsCiAgICAgICAgfTsKICAgICAgfSkKICAgICAgLnNvcnQoKGEsIGIpID0+IE51bWJlcihhLmlkKSAtIE51bWJlcihiLmlkKSk7CiAgfQoKICBhc3luYyBtb3ZlSXNzdWUoaWQsIHRvKSB7CiAgICBjb25zdCBsYWJlbHMgPSBjb2x1bW5MYWJlbHModGhpcy5fY2ZnKTsKICAgIGNvbnN0IHN0YXR1c0xhYmVscyA9IE9iamVjdC52YWx1ZXMobGFiZWxzKTsKCiAgICAvLyBiYWNrbG9nIChmYWxscyBhbHMgT3Blbi1adXN0YW5kIGtvbmZpZ3VyaWVydCkgdW5kIGRvbmUgc2luZCBHaXRMYWItWnVzdGFlbmRlLAogICAgLy8ga2VpbmUgTGFiZWxzOiBudXIgU3RhdHVzLUxhYmVscyBlbnRmZXJuZW4sIElzc3VlIG9lZmZuZW4gYnp3LiBzY2hsaWVzc2VuLCBrZWluCiAgICAvLyBQaGFudG9tLUxhYmVsIHNldHplbi4KICAgIGlmIChpc1N0YXRlQ29sdW1uKHRvLCB0aGlzLl9jZmcpKSB7CiAgICAgIGNvbnN0IHVubGFiZWxBcmdzID0gc3RhdHVzTGFiZWxzLm1hcCgobCkgPT4gYC0tdW5sYWJlbCAke3NoZWxsUXVvdGUobCl9YCkuam9pbigiICIpOwogICAgICBleGVjKGBnbGFiIGlzc3VlIHVwZGF0ZSAke2lkfSAke3VubGFiZWxBcmdzfWApOwogICAgICBleGVjKHRvID09PSAiZG9uZSIgPyBgZ2xhYiBpc3N1ZSBjbG9zZSAke2lkfWAgOiBgZ2xhYiBpc3N1ZSByZW9wZW4gJHtpZH1gKTsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIGNvbnN0IGxhYmVsID0gbGFiZWxzW3RvXTsKICAgIGlmICghbGFiZWwpIHRocm93IG5ldyBCb2FyZEVycm9yKGBTdGF0dXMgJyR7dG99JyBoYXQga2VpbiBHaXRMYWItTGFiZWwtTWFwcGluZ2ApOwogICAgLy8gQWxsZSBhbmRlcmVuIFN0YXR1cy1MYWJlbHMgZW50ZmVybmVuLCBaaWVsLUxhYmVsIHNldHplbiAoWmllbC1MYWJlbAogICAgLy8gTklDSFQgaW0gc2VsYmVuIEF1ZnJ1ZiB1bmxhYmVsbiwgc29uc3QgdmVycmVjaG5ldCBnbGFiIGJlaWRlcyBnZWdlbmVpbmFuZGVyKS4KICAgIGNvbnN0IHVubGFiZWxBcmdzID0gc3RhdHVzTGFiZWxzCiAgICAgIC5maWx0ZXIoKGwpID0+IGwgIT09IGxhYmVsKQogICAgICAubWFwKChsKSA9PiBgLS11bmxhYmVsICR7c2hlbGxRdW90ZShsKX1gKQogICAgICAuam9pbigiICIpOwogICAgZXhlYyhgZ2xhYiBpc3N1ZSB1cGRhdGUgJHtpZH0gJHt1bmxhYmVsQXJnc30gLS1sYWJlbCAke3NoZWxsUXVvdGUobGFiZWwpfWApOwogIH0KCiAgYXN5bmMgY29tbWVudElzc3VlKGlkLCB0ZXh0KSB7CiAgICBleGVjKGBnbGFiIGlzc3VlIG5vdGUgY3JlYXRlICR7aWR9IC0tbWVzc2FnZSAke3NoZWxsUXVvdGUodGV4dCl9YCk7CiAgfQp9CgpjbGFzcyBHaXRMYWJDb2RlSG9zdCB7CiAgYXN5bmMgZ2V0UmVwb05hbWUoKSB7CiAgICB0cnkgewogICAgICBjb25zdCB1cmwgPSBleGVjKCJnaXQgcmVtb3RlIGdldC11cmwgb3JpZ2luIik7CiAgICAgIHJldHVybiB1cmwucmVwbGFjZSgvXC5naXQkLywgIiIpLnNwbGl0KCIvIikuc2xpY2UoLTIpLmpvaW4oIi8iKTsKICAgIH0gY2F0Y2ggewogICAgICByZXR1cm4gZXhlYygiYmFzZW5hbWUgJChwd2QpIik7CiAgICB9CiAgfQoKICBzdXBwb3J0c1B1bGxSZXF1ZXN0cygpIHsgcmV0dXJuIHRydWU7IH0KCiAgYXN5bmMgY3JlYXRlUHVsbFJlcXVlc3QoeyBmcm9tLCB0bywgdGl0bGUgfSkgewogICAgY29uc3QgdCA9IHRpdGxlIHx8IGAke2Zyb219IC0+ICR7dG99YDsKICAgIGNvbnN0IHVybCA9IGV4ZWMoCiAgICAgIGBnbGFiIG1yIGNyZWF0ZSAtLXNvdXJjZS1icmFuY2ggJHtmcm9tfSAtLXRhcmdldC1icmFuY2ggJHt0b30gLS10aXRsZSAke3NoZWxsUXVvdGUodCl9IC0tZGVzY3JpcHRpb24gIiIgLS15ZXNgCiAgICApOwogICAgLy8gZ2xhYiBnaWJ0IGRpZSBNUi1VUkwgYXVzCiAgICBjb25zdCBtYXRjaCA9IHVybC5tYXRjaCgvaHR0cHM/OlwvXC9cUysvKTsKICAgIHJldHVybiB7IHVybDogbWF0Y2ggPyBtYXRjaFswXSA6IHVybC50cmltKCkgfTsKICB9Cn0KCi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQovLyBMb2NhbC1BZGFwdGVyCi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKLy8gTWluaW1hbGVyIFlBTUwtRnJvbnRtYXR0ZXItUGFyc2VyIGZ1ZXIgZGllIElzc3VlLURhdGVpZW4gKGtlaW4gZXh0ZXJuZXMgTW9kdWwpLgovLyBCZXd1c3N0IG1pbmltYWw6IG51ciBmbGFjaGVzLCBlaW56ZWlsaWdlcyBZQU1MIChyZWljaHQgZnVlciBkYXMgSXNzdWUtRm9ybWF0KS4KZnVuY3Rpb24gcGFyc2VGcm9udG1hdHRlcihjb250ZW50KSB7CiAgY29uc3QgbWF0Y2ggPSBjb250ZW50Lm1hdGNoKC9eLS0tXG4oW1xzXFNdKj8pXG4tLS1cbj8oW1xzXFNdKikkLyk7CiAgaWYgKCFtYXRjaCkgcmV0dXJuIHsgbWV0YToge30sIGJvZHk6IGNvbnRlbnQgfTsKICBjb25zdCBtZXRhID0ge307CiAgZm9yIChjb25zdCBsaW5lIG9mIG1hdGNoWzFdLnNwbGl0KCJcbiIpKSB7CiAgICAvLyBGdWVocmVuZGUgTGVlcnplaWNoZW4gbmFjaCBkZW0gRG9wcGVscHVua3QgdWViZXJuaW1tdCBkYXMgbmFjaGdlbGFnZXJ0ZSAudHJpbSgpOwogICAgLy8gZGVzaGFsYiBoaWVyIGJld3Vzc3Qga2VpbiBccyogKHZlcm1laWRldCB1ZWJlcmxhcHBlbmRlIFplaWNoZW5rbGFzc2VuL0JhY2t0cmFja2luZykuCiAgICBjb25zdCBtID0gbGluZS5tYXRjaCgvXihcdyspOiguKikkLyk7CiAgICBpZiAobSkgbWV0YVttWzFdXSA9IG1bMl0udHJpbSgpLnJlcGxhY2UoL15bIiddfFsiJ10kL2csICIiKTsKICB9CiAgcmV0dXJuIHsgbWV0YSwgYm9keTogbWF0Y2hbMl0gfTsKfQoKZnVuY3Rpb24gc2VyaWFsaXplRnJvbnRtYXR0ZXIobWV0YSwgYm9keSkgewogIGNvbnN0IGxpbmVzID0gT2JqZWN0LmVudHJpZXMobWV0YSkubWFwKChbaywgdl0pID0+IGAke2t9OiAke3Z9YCk7CiAgcmV0dXJuIGAtLS1cbiR7bGluZXMuam9pbigiXG4iKX1cbi0tLVxuJHtib2R5fWA7Cn0KCmZ1bmN0aW9uIGlzc3Vlc0Rpcihjb25maWcpIHsKICByZXR1cm4gcmVzb2x2ZShjb25maWcubG9jYWw/Lmlzc3Vlc0RpciB8fCAiaXNzdWVzIik7Cn0KCmZ1bmN0aW9uIHBhZElkKG4pIHsKICByZXR1cm4gU3RyaW5nKG4pLnBhZFN0YXJ0KDQsICIwIik7Cn0KCi8vIEVwaWMtRm9ydHNjaHJpdHQgYXVzIGRlbiBLaW5kZXJuIChwYXJlbnQtWmVpZ2VyKS4KLy8gS2luZGVyID0gbmljaHQtRXBpYy1Jc3N1ZXMgbWl0IHBhcmVudCA9PSBlcGljSWQ7IGRvbmUgPSBLaW5kZXIgaW0gU3RhdHVzICJkb25lIi4KZnVuY3Rpb24gZXBpY1Byb2dyZXNzKGlzc3VlcywgZXBpY0lkKSB7CiAgY29uc3QgY2hpbGRyZW4gPSBpc3N1ZXMuZmlsdGVyKChpKSA9PiBpLnR5cGUgIT09ICJlcGljIiAmJiBpLnBhcmVudCA9PT0gZXBpY0lkKTsKICBjb25zdCBkb25lID0gY2hpbGRyZW4uZmlsdGVyKChpKSA9PiBpLnN0YXR1cyA9PT0gImRvbmUiKS5sZW5ndGg7CiAgcmV0dXJuIHsgdG90YWw6IGNoaWxkcmVuLmxlbmd0aCwgZG9uZSB9Owp9CgpjbGFzcyBMb2NhbElzc3VlVHJhY2tlciB7CiAgY29uc3RydWN0b3IoY29uZmlnKSB7IHRoaXMuX2NmZyA9IGNvbmZpZzsgfQoKICBfZGlyKCkgewogICAgcmV0dXJuIGlzc3Vlc0Rpcih0aGlzLl9jZmcpOwogIH0KCiAgX2FsbEZpbGVzKCkgewogICAgY29uc3QgZGlyID0gdGhpcy5fZGlyKCk7CiAgICBpZiAoIWV4aXN0c1N5bmMoZGlyKSkgcmV0dXJuIFtdOwogICAgcmV0dXJuIHJlYWRkaXJTeW5jKGRpcikKICAgICAgLmZpbHRlcigoZikgPT4gZi5lbmRzV2l0aCgiLm1kIikpCiAgICAgIC5zb3J0KCk7IC8vIGF1ZnN0ZWlnZW5kIG5hY2ggRGF0ZWluYW1lID0gYXVmc3RlaWdlbmQgbmFjaCBpZAogIH0KCiAgX2ZpbGVQYXRoKGlkKSB7CiAgICByZXR1cm4gam9pbih0aGlzLl9kaXIoKSwgYCR7cGFkSWQoaWQpfS5tZGApOwogIH0KCiAgX3JlYWQoaWQpIHsKICAgIGNvbnN0IHAgPSB0aGlzLl9maWxlUGF0aChpZCk7CiAgICBpZiAoIWV4aXN0c1N5bmMocCkpIHRocm93IG5ldyBCb2FyZEVycm9yKGBJc3N1ZSAke2lkfSBuaWNodCBnZWZ1bmRlbjogJHtwfWApOwogICAgY29uc3QgcmF3ID0gcmVhZEZpbGVTeW5jKHAsICJ1dGYtOCIpOwogICAgY29uc3QgeyBtZXRhLCBib2R5IH0gPSBwYXJzZUZyb250bWF0dGVyKHJhdyk7CiAgICByZXR1cm4geyBpZDogbWV0YS5pZCB8fCBwYWRJZChpZCksIHR5cGU6IG1ldGEudHlwZSB8fCAidGFzayIsIHBhcmVudDogbWV0YS5wYXJlbnQgfHwgIiIsIHRpdGxlOiBtZXRhLnRpdGxlIHx8ICIiLCBzdGF0dXM6IG1ldGEuc3RhdHVzIHx8ICJiYWNrbG9nIiwgY3JlYXRlZDogbWV0YS5jcmVhdGVkIHx8ICIiLCBib2R5IH07CiAgfQoKICBfbmV4dElkKCkgewogICAgY29uc3QgZmlsZXMgPSB0aGlzLl9hbGxGaWxlcygpOwogICAgaWYgKGZpbGVzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIDE7CiAgICBjb25zdCBudW1zID0gZmlsZXMubWFwKChmKSA9PiBOdW1iZXIucGFyc2VJbnQoZiwgMTApKS5maWx0ZXIoKG4pID0+ICFOdW1iZXIuaXNOYU4obikpOwogICAgcmV0dXJuIG51bXMubGVuZ3RoID4gMCA/IE1hdGgubWF4KC4uLm51bXMpICsgMSA6IDE7CiAgfQoKICBhc3luYyBjcmVhdGVJc3N1ZSh7IHRpdGxlLCBib2R5LCB0eXBlLCBwYXJlbnQsIGNvbG9yLCBzaG9ydGNvZGUgfSkgewogICAgY29uc3QgZGlyID0gdGhpcy5fZGlyKCk7CiAgICBta2RpclN5bmMoZGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTsKICAgIGNvbnN0IG4gPSB0aGlzLl9uZXh0SWQoKTsKICAgIGNvbnN0IGlkID0gcGFkSWQobik7CiAgICBjb25zdCB0b2RheSA9IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKS5zbGljZSgwLCAxMCk7CiAgICBjb25zdCB0ID0gdHlwZSB8fCAidGFzayI7CiAgICBjb25zdCBtZXRhID0geyBpZDogYCIke2lkfSJgLCB0eXBlOiB0IH07CiAgICBpZiAocGFyZW50KSBtZXRhLnBhcmVudCA9IGAiJHtwYXJlbnR9ImA7CiAgICBpZiAoY29sb3IpIG1ldGEuY29sb3IgPSBjb2xvcjsKICAgIGlmIChzaG9ydGNvZGUpIG1ldGEuc2hvcnRjb2RlID0gc2hvcnRjb2RlOwogICAgLy8gRXBpY3MgbmVobWVuIG5pY2h0IGFtIFNwYWx0ZW4tV29ya2Zsb3cgdGVpbCAoRTUpOiBrZWluIHN0YXR1cy1GZWxkLgogICAgaWYgKHQgIT09ICJlcGljIikgbWV0YS5zdGF0dXMgPSAiYmFja2xvZyI7CiAgICBtZXRhLnRpdGxlID0gdGl0bGU7CiAgICBtZXRhLmNyZWF0ZWQgPSB0b2RheTsKICAgIGNvbnN0IGNvbnRlbnQgPSBzZXJpYWxpemVGcm9udG1hdHRlcigKICAgICAgbWV0YSwKICAgICAgYm9keSB8fCAiXG4jIyBLb250ZXh0XG5cbiMjIEF1ZmdhYmVcblxuIyMgQWt6ZXB0YW56a3JpdGVyaXVtXG5cbiMjIEFiaGFlbmdpZ2tlaXRlblxuIgogICAgKTsKICAgIHdyaXRlRmlsZVN5bmModGhpcy5fZmlsZVBhdGgobiksIGNvbnRlbnQsICJ1dGYtOCIpOwogICAgcmV0dXJuIHsgaWQsIHBhdGg6IHRoaXMuX2ZpbGVQYXRoKG4pIH07CiAgfQoKICBhc3luYyBnZXRJc3N1ZShpZCkgewogICAgcmV0dXJuIHRoaXMuX3JlYWQoaWQpOwogIH0KCiAgYXN5bmMgbGlzdElzc3VlcyhzdGF0dXMpIHsKICAgIHJldHVybiB0aGlzLl9hbGxGaWxlcygpCiAgICAgIC5tYXAoKGYpID0+IHsKICAgICAgICBjb25zdCByYXcgPSByZWFkRmlsZVN5bmMoam9pbih0aGlzLl9kaXIoKSwgZiksICJ1dGYtOCIpOwogICAgICAgIGNvbnN0IHsgbWV0YSwgYm9keSB9ID0gcGFyc2VGcm9udG1hdHRlcihyYXcpOwogICAgICAgIHJldHVybiB7IGlkOiBtZXRhLmlkIHx8IGJhc2VuYW1lKGYsICIubWQiKSwgdHlwZTogbWV0YS50eXBlIHx8ICJ0YXNrIiwgcGFyZW50OiBtZXRhLnBhcmVudCB8fCAiIiwgY29sb3I6IG1ldGEuY29sb3IgfHwgIiIsIHNob3J0Y29kZTogbWV0YS5zaG9ydGNvZGUgfHwgIiIsIHRpdGxlOiBtZXRhLnRpdGxlIHx8ICIiLCBzdGF0dXM6IG1ldGEuc3RhdHVzIHx8ICJiYWNrbG9nIiwgYm9keSB9OwogICAgICB9KQogICAgICAvLyBFcGljcyBuZWhtZW4gbmljaHQgYW0gU3BhbHRlbi1Xb3JrZmxvdyB0ZWlsIChFNSk6IGJlaSBTdGF0dXMtRmlsdGVydW5nCiAgICAgIC8vICh6LkIuIC0tc3RhdHVzIHJlYWR5IGbDvHIgaW1wbGVtZW50LXJlYWR5KSB0YXVjaGVuIHNpZSBuaWUgYXVmLgogICAgICAuZmlsdGVyKChpKSA9PiAhc3RhdHVzIHx8IChpLnR5cGUgIT09ICJlcGljIiAmJiBpLnN0YXR1cyA9PT0gc3RhdHVzKSk7CiAgfQoKICBhc3luYyBsaXN0RXBpY3MoKSB7CiAgICBjb25zdCBhbGwgPSBhd2FpdCB0aGlzLmxpc3RJc3N1ZXMoKTsKICAgIHJldHVybiBhbGwKICAgICAgLmZpbHRlcigoaSkgPT4gaS50eXBlID09PSAiZXBpYyIpCiAgICAgIC5tYXAoKGUpID0+ICh7IC4uLmUsIHByb2dyZXNzOiBlcGljUHJvZ3Jlc3MoYWxsLCBlLmlkKSB9KSk7CiAgfQoKICBhc3luYyBtb3ZlSXNzdWUoaWQsIHRvKSB7CiAgICBjb25zdCBwID0gdGhpcy5fZmlsZVBhdGgoaWQpOwogICAgaWYgKCFleGlzdHNTeW5jKHApKSB0aHJvdyBuZXcgQm9hcmRFcnJvcihgSXNzdWUgJHtpZH0gbmljaHQgZ2VmdW5kZW46ICR7cH1gKTsKICAgIGNvbnN0IHJhdyA9IHJlYWRGaWxlU3luYyhwLCAidXRmLTgiKTsKICAgIGNvbnN0IHsgbWV0YSwgYm9keSB9ID0gcGFyc2VGcm9udG1hdHRlcihyYXcpOwogICAgbWV0YS5zdGF0dXMgPSB0bzsKICAgIHdyaXRlRmlsZVN5bmMocCwgc2VyaWFsaXplRnJvbnRtYXR0ZXIobWV0YSwgYm9keSksICJ1dGYtOCIpOwogIH0KCiAgYXN5bmMgY29tbWVudElzc3VlKGlkLCB0ZXh0KSB7CiAgICBjb25zdCBwID0gdGhpcy5fZmlsZVBhdGgoaWQpOwogICAgaWYgKCFleGlzdHNTeW5jKHApKSB0aHJvdyBuZXcgQm9hcmRFcnJvcihgSXNzdWUgJHtpZH0gbmljaHQgZ2VmdW5kZW46ICR7cH1gKTsKICAgIGNvbnN0IHJhdyA9IHJlYWRGaWxlU3luYyhwLCAidXRmLTgiKTsKICAgIGNvbnN0IHRpbWVzdGFtcCA9IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKS5yZXBsYWNlKCJUIiwgIiAiKS5zbGljZSgwLCAxNik7CiAgICBjb25zdCBjb21tZW50ID0gYFxuXG4tLS1cbioqS29tbWVudGFyKiogKCR7dGltZXN0YW1wfSlcblxuJHt0ZXh0fWA7CiAgICB3cml0ZUZpbGVTeW5jKHAsIHJhdyArIGNvbW1lbnQsICJ1dGYtOCIpOwogIH0KfQoKY2xhc3MgTG9jYWxDb2RlSG9zdCB7CiAgYXN5bmMgZ2V0UmVwb05hbWUoKSB7CiAgICB0cnkgewogICAgICBjb25zdCB1cmwgPSBleGVjKCJnaXQgcmVtb3RlIGdldC11cmwgb3JpZ2luIDI+L2Rldi9udWxsIik7CiAgICAgIHJldHVybiB1cmwucmVwbGFjZSgvXC5naXQkLywgIiIpLnNwbGl0KCIvIikucG9wKCk7CiAgICB9IGNhdGNoIHsKICAgICAgcmV0dXJuIGJhc2VuYW1lKHJlc29sdmUoIi4iKSk7CiAgICB9CiAgfQoKICBzdXBwb3J0c1B1bGxSZXF1ZXN0cygpIHsgcmV0dXJuIGZhbHNlOyB9CgogIGFzeW5jIGNyZWF0ZVB1bGxSZXF1ZXN0KHsgZnJvbSwgdG8gfSkgewogICAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoCiAgICAgIEpTT04uc3RyaW5naWZ5KHsKICAgICAgICBvazogZmFsc2UsCiAgICAgICAgbWVzc2FnZTogYExva2FsZXIgTW9kdXM6IGtlaW4gUHVsbCBSZXF1ZXN0LiBGdWVocmUgZWluZW4gbG9rYWxlbiBNZXJnZSBkdXJjaDpcbiAgZ2l0IGNoZWNrb3V0ICR7dG99XG4gIGdpdCBtZXJnZSAke2Zyb219XG4gIGdpdCBwdXNoYAogICAgICB9LCBudWxsLCAyKSArICJcbiIKICAgICk7CiAgICBwcm9jZXNzLmV4aXQoMCk7CiAgfQp9CgovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8gVG9vbGJveC1BZGFwdGVyIChlaWdlbmVzIEthbmJhbi1Cb2FyZCBhbHMgSXNzdWUtVHJhY2tlciwgIzM2OCkKLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgovLyBLaXQtU3RhdHVzIDwtPiBLYW5iYW5Db2x1bW4gKEJhY2tlbmQpLiBTaW1wbGUgVXBwZXJjYXNlLUFiYmlsZHVuZy4KY29uc3QgVE9PTEJPWF9TVEFUVVNfVE9fQ09MVU1OID0gewogIGJhY2tsb2c6ICAgICAiQkFDS0xPRyIsCiAgcmVhZHk6ICAgICAgICJSRUFEWSIsCiAgaW5fcHJvZ3Jlc3M6ICJJTl9QUk9HUkVTUyIsCiAgaW5fcmV2aWV3OiAgICJJTl9SRVZJRVciLAogIGRvbmU6ICAgICAgICAiRE9ORSIsCn07CmNvbnN0IFRPT0xCT1hfQ09MVU1OX1RPX1NUQVRVUyA9IE9iamVjdC5mcm9tRW50cmllcygKICBPYmplY3QuZW50cmllcyhUT09MQk9YX1NUQVRVU19UT19DT0xVTU4pLm1hcCgoW3MsIGNdKSA9PiBbYywgc10pCik7CgovKioKICogSXNzdWUtVHJhY2tlciBnZWdlbiBkYXMgZWlnZW5lIFRvb2xib3gtS2FuYmFuLUJvYXJkLiBad2VpLUFjaHNlbi1Nb2RlbGwgKCMzNjgpOiBkZXIgQ29kZSBsaWVndAogKiB3ZWl0ZXIgYXVmIEdpdEh1YiAoY29kZUhvc3QgYmxlaWJ0IGdpdGh1YiksIG51ciBkZXIgSXNzdWUtVHJhY2tlciBpc3QgZGFzIEJvYXJkLgogKgogKiBBdXRoOiBsaWVzdCBIb3N0ICsgVG9rZW4gYXVzIH4vLmNvbmZpZy90b29sYm94LWNsaS97Y29uZmlnLHRva2Vuc30uanNvbiAoZGllc2VsYmUgUXVlbGxlIHdpZSBkYXMKICogdGJ4LUNMSSwgIzM2Nyk7IEhvc3QgcGVyIGNvbmZpZy50b29sYm94Lmhvc3QgdWViZXJzY2hyZWliYmFyLiBBbGxlIEF1ZnJ1ZmUgdHJhZ2VuIGRlbiBIZWFkZXIKICogWC1LYW5iYW4tVG9rZW4uCiAqCiAqIG51bWJlciB2cy4gREItaWQ6IERlciBXb3JrZmxvdyBhZHJlc3NpZXJ0IElzc3VlcyB1ZWJlciBkaWUgQm9hcmQtQW56ZWlnZW51bW1lciAoI04pLiBNb3ZlL0NvbW1lbnQKICogYnJhdWNoZW4gZGllIERCLWlkIGF1cyBkZXIgSXRlbS1SZXNwb25zZTsgc2llIHdpcmQgaW50ZXJuIHBlciBCb2FyZC1GZXRjaCBhdWZnZWxvZXN0LgogKi8KY2xhc3MgVG9vbGJveElzc3VlVHJhY2tlciB7CiAgY29uc3RydWN0b3IoY29uZmlnKSB7IHRoaXMuX2NmZyA9IGNvbmZpZzsgfQoKICBfYXV0aCgpIHsKICAgIGNvbnN0IGRpciA9IHByb2Nlc3MuZW52LlRCWF9DT05GSUdfRElSIHx8IGpvaW4oaG9tZWRpcigpLCAiLmNvbmZpZyIsICJ0b29sYm94LWNsaSIpOwogICAgY29uc3Qgc3RvcmVkID0gdGhpcy5fcmVhZEpzb24oam9pbihkaXIsICJjb25maWcuanNvbiIpKTsKICAgIGNvbnN0IHRva2VucyA9IHRoaXMuX3JlYWRKc29uKGpvaW4oZGlyLCAidG9rZW5zLmpzb24iKSk7CiAgICBjb25zdCBob3N0ID0gdGhpcy5fY2ZnLnRvb2xib3g/Lmhvc3QgfHwgc3RvcmVkPy5ob3N0OwogICAgY29uc3QgdG9rZW4gPSB0b2tlbnM/LnRva2VuOwogICAgaWYgKCFob3N0IHx8ICF0b2tlbikgewogICAgICB0aHJvdyBuZXcgQm9hcmRFcnJvcigKICAgICAgICAiS2VpbiBUb29sYm94LUxvZ2luIGdlZnVuZGVuLiBUb2tlbiBpbiBkZXIgV2ViLVVJIGVyemV1Z2VuIHVuZCAndGJ4IGF1dGggbG9naW4nIGF1c2Z1ZWhyZW4uIgogICAgICApOwogICAgfQogICAgcmV0dXJuIHsgaG9zdCwgdG9rZW4gfTsKICB9CgogIF9yZWFkSnNvbihwYXRoKSB7CiAgICBpZiAoIWV4aXN0c1N5bmMocGF0aCkpIHJldHVybiBudWxsOwogICAgdHJ5IHsgcmV0dXJuIEpTT04ucGFyc2UocmVhZEZpbGVTeW5jKHBhdGgsICJ1dGYtOCIpKTsgfSBjYXRjaCB7IHJldHVybiBudWxsOyB9CiAgfQoKICBhc3luYyBfZmV0Y2gocGF0aCwgb3B0aW9ucyA9IHt9KSB7CiAgICBjb25zdCB7IGhvc3QsIHRva2VuIH0gPSB0aGlzLl9hdXRoKCk7CiAgICBsZXQgcmVzOwogICAgdHJ5IHsKICAgICAgcmVzID0gYXdhaXQgZmV0Y2goYCR7aG9zdH0ke3BhdGh9YCwgewogICAgICAgIC4uLm9wdGlvbnMsCiAgICAgICAgaGVhZGVyczogeyAuLi5vcHRpb25zLmhlYWRlcnMsICJYLUthbmJhbi1Ub2tlbiI6IHRva2VuIH0sCiAgICAgIH0pOwogICAgfSBjYXRjaCAoZSkgewogICAgICB0aHJvdyBuZXcgQm9hcmRFcnJvcihgVG9vbGJveC1BUEkgbmljaHQgZXJyZWljaGJhciAoJHtob3N0fSk6ICR7ZS5tZXNzYWdlfWApOwogICAgfQogICAgaWYgKHJlcy5zdGF0dXMgPT09IDQwMSkgewogICAgICB0aHJvdyBuZXcgQm9hcmRFcnJvcigiVG9rZW4gdW5ndWVsdGlnIG9kZXIgd2lkZXJydWZlbi4gQml0dGUgJ3RieCBhdXRoIGxvZ2luJyBlcm5ldXQgYXVzZnVlaHJlbi4iKTsKICAgIH0KICAgIGlmICghcmVzLm9rKSB7CiAgICAgIGxldCBtc2cgPSBgSFRUUCAke3Jlcy5zdGF0dXN9YDsKICAgICAgdHJ5IHsKICAgICAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVzLmpzb24oKTsKICAgICAgICBpZiAoYm9keT8ubWVzc2FnZSkgbXNnID0gYm9keS5tZXNzYWdlOwogICAgICB9IGNhdGNoIHsgLyoga2VpbiBKU09OLUJvZHkgKi8gfQogICAgICB0aHJvdyBuZXcgQm9hcmRFcnJvcihgVG9vbGJveC1BUEktRmVobGVyOiAke21zZ31gKTsKICAgIH0KICAgIHJldHVybiByZXM7CiAgfQoKICBfdG9Db2x1bW4oc3RhdHVzKSB7CiAgICBjb25zdCBjb2x1bW4gPSBUT09MQk9YX1NUQVRVU19UT19DT0xVTU5bc3RhdHVzXTsKICAgIGlmICghY29sdW1uKSB0aHJvdyBuZXcgQm9hcmRFcnJvcihgVW5ndWVsdGlnZXIgU3RhdHVzICcke3N0YXR1c30nLiBHdWVsdGlnOiAke1ZBTElEX1NUQVRVU0VTLmpvaW4oIiwgIil9YCk7CiAgICByZXR1cm4gY29sdW1uOwogIH0KCiAgX3RvU3RhdHVzKGNvbHVtbikgewogICAgcmV0dXJuIFRPT0xCT1hfQ09MVU1OX1RPX1NUQVRVU1tjb2x1bW5dIHx8IG51bGw7CiAgfQoKICAvKiogTGllc3QgZGFzIGdydXBwaWVydGUgQm9hcmQgdW5kIGxpZWZlcnQgZWluZSBmbGFjaGUgTGlzdGUgaW5rbC4gYWJnZWxlaXRldGVtIFN0YXR1cy4gKi8KICBhc3luYyBfYm9hcmRJdGVtcygpIHsKICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMuX2ZldGNoKCIvYXBpL2thbmJhbi9pdGVtcyIpOwogICAgY29uc3QgZ3JvdXBlZCA9IGF3YWl0IHJlcy5qc29uKCk7CiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyhncm91cGVkKQogICAgICAuZmxhdCgpCiAgICAgIC5tYXAoKGl0ZW0pID0+ICh7IC4uLml0ZW0sIHN0YXR1czogdGhpcy5fdG9TdGF0dXMoaXRlbS5jb2x1bW4pIH0pKTsKICB9CgogIF9maW5kQnlOdW1iZXIoaXRlbXMsIG51bWJlcikgewogICAgcmV0dXJuIGl0ZW1zLmZpbmQoKGkpID0+IGkubnVtYmVyID09PSBudW1iZXIpIHx8IG51bGw7CiAgfQoKICBfcmVzb2x2ZUJ5TnVtYmVyKGl0ZW1zLCBudW1iZXIpIHsKICAgIGNvbnN0IGl0ZW0gPSB0aGlzLl9maW5kQnlOdW1iZXIoaXRlbXMsIG51bWJlcik7CiAgICBpZiAoIWl0ZW0pIHRocm93IG5ldyBCb2FyZEVycm9yKGBJc3N1ZSAke251bWJlcn0gbmljaHQgZ2VmdW5kZW5gKTsKICAgIHJldHVybiBpdGVtOwogIH0KCiAgYXN5bmMgY3JlYXRlSXNzdWUoeyB0aXRsZSwgYm9keSB9KSB7CiAgICBjb25zdCB7IGhvc3QgfSA9IHRoaXMuX2F1dGgoKTsKICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMuX2ZldGNoKCIvYXBpL2thbmJhbi9pdGVtcyIsIHsKICAgICAgbWV0aG9kOiAiUE9TVCIsCiAgICAgIGhlYWRlcnM6IHsgIkNvbnRlbnQtVHlwZSI6ICJhcHBsaWNhdGlvbi9qc29uIiB9LAogICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7IHRpdGxlLCBib2R5OiBib2R5IHx8ICIiLCBjb2x1bW46ICJCQUNLTE9HIiB9KSwKICAgIH0pOwogICAgY29uc3QgY3JlYXRlZCA9IGF3YWl0IHJlcy5qc29uKCk7CiAgICByZXR1cm4geyBpZDogU3RyaW5nKGNyZWF0ZWQubnVtYmVyKSwgdXJsOiBgJHtob3N0fS9rYW5iYW5gIH07CiAgfQoKICBhc3luYyBnZXRJc3N1ZShudW1iZXIpIHsKICAgIGNvbnN0IG51bSA9IE51bWJlcihudW1iZXIpOwogICAgY29uc3QgaXRlbSA9IHRoaXMuX3Jlc29sdmVCeU51bWJlcihhd2FpdCB0aGlzLl9ib2FyZEl0ZW1zKCksIG51bSk7CiAgICByZXR1cm4geyBpZDogU3RyaW5nKGl0ZW0ubnVtYmVyKSwgdGl0bGU6IGl0ZW0udGl0bGUsIGJvZHk6IGl0ZW0uYm9keSwgc3RhdHVzOiBpdGVtLnN0YXR1cyB9OwogIH0KCiAgYXN5bmMgbGlzdElzc3VlcyhzdGF0dXMpIHsKICAgIGlmIChzdGF0dXMgJiYgIVZBTElEX1NUQVRVU0VTLmluY2x1ZGVzKHN0YXR1cykpIHsKICAgICAgdGhyb3cgbmV3IEJvYXJkRXJyb3IoYFVuZ3VlbHRpZ2VyIFN0YXR1cyAnJHtzdGF0dXN9Jy4gR3VlbHRpZzogJHtWQUxJRF9TVEFUVVNFUy5qb2luKCIsICIpfWApOwogICAgfQogICAgY29uc3QgaXRlbXMgPSBhd2FpdCB0aGlzLl9ib2FyZEl0ZW1zKCk7CiAgICByZXR1cm4gaXRlbXMKICAgICAgLy8gRXBpY3MgbmVobWVuIG5pY2h0IGFtIFNwYWx0ZW4tV29ya2Zsb3cgdGVpbDogYmVpIFN0YXR1cy1GaWx0ZXIgYXVzc2NobGllc3Nlbi4KICAgICAgLmZpbHRlcigoaSkgPT4gIXN0YXR1cyB8fCAoaS50eXBlICE9PSAiZXBpYyIgJiYgaS5zdGF0dXMgPT09IHN0YXR1cykpCiAgICAgIC5zb3J0KChhLCBiKSA9PiBhLm51bWJlciAtIGIubnVtYmVyKQogICAgICAubWFwKChpKSA9PiAoeyBpZDogU3RyaW5nKGkubnVtYmVyKSwgdGl0bGU6IGkudGl0bGUsIGJvZHk6IGkuYm9keSwgc3RhdHVzOiBpLnN0YXR1cyB9KSk7CiAgfQoKICBhc3luYyBsaXN0RXBpY3MoKSB7CiAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLl9mZXRjaCgiL2FwaS9rYW5iYW4vZXBpY3MiKTsKICAgIGNvbnN0IGVwaWNzID0gYXdhaXQgcmVzLmpzb24oKTsKICAgIHJldHVybiAoQXJyYXkuaXNBcnJheShlcGljcykgPyBlcGljcyA6IFtdKS5tYXAoKGUpID0+ICh7CiAgICAgIGlkOiBTdHJpbmcoZS5udW1iZXIgPz8gZS5pZCksCiAgICAgIHRpdGxlOiBlLnRpdGxlLAogICAgICBzaG9ydGNvZGU6IGUuc2hvcnRjb2RlIHx8ICIiLAogICAgICBwcm9ncmVzczogZS5wcm9ncmVzcyB8fCB7IHRvdGFsOiAwLCBkb25lOiAwIH0sCiAgICB9KSk7CiAgfQoKICBhc3luYyBtb3ZlSXNzdWUobnVtYmVyLCB0bykgewogICAgY29uc3QgbnVtID0gTnVtYmVyKG51bWJlcik7CiAgICBjb25zdCBjb2x1bW4gPSB0aGlzLl90b0NvbHVtbih0byk7CiAgICBjb25zdCBpdGVtcyA9IGF3YWl0IHRoaXMuX2JvYXJkSXRlbXMoKTsKICAgIGNvbnN0IGl0ZW0gPSB0aGlzLl9yZXNvbHZlQnlOdW1iZXIoaXRlbXMsIG51bSk7CiAgICAvLyBaaWVscG9zaXRpb24gPSBFbmRlIGRlciBaaWVsc3BhbHRlIChiZWkgZ2xlaWNoYmxlaWJlbmRlciBTcGFsdGU6IGFrdHVlbGxlIFBvc2l0aW9uIGhhbHRlbikuCiAgICBjb25zdCB0YXJnZXRQb3NpdGlvbiA9CiAgICAgIGl0ZW0uY29sdW1uID09PSBjb2x1bW4gPyBpdGVtLnBvc2l0aW9uIDogaXRlbXMuZmlsdGVyKChpKSA9PiBpLmNvbHVtbiA9PT0gY29sdW1uKS5sZW5ndGg7CiAgICBhd2FpdCB0aGlzLl9mZXRjaChgL2FwaS9rYW5iYW4vaXRlbXMvJHtpdGVtLmlkfS9tb3ZlYCwgewogICAgICBtZXRob2Q6ICJQVVQiLAogICAgICBoZWFkZXJzOiB7ICJDb250ZW50LVR5cGUiOiAiYXBwbGljYXRpb24vanNvbiIgfSwKICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoeyBjb2x1bW4sIHBvc2l0aW9uOiB0YXJnZXRQb3NpdGlvbiB9KSwKICAgIH0pOwogIH0KCiAgYXN5bmMgY29tbWVudElzc3VlKG51bWJlciwgdGV4dCkgewogICAgY29uc3QgbnVtID0gTnVtYmVyKG51bWJlcik7CiAgICBjb25zdCBpdGVtID0gdGhpcy5fcmVzb2x2ZUJ5TnVtYmVyKGF3YWl0IHRoaXMuX2JvYXJkSXRlbXMoKSwgbnVtKTsKICAgIGF3YWl0IHRoaXMuX2ZldGNoKGAvYXBpL2thbmJhbi9pdGVtcy8ke2l0ZW0uaWR9L2NvbW1lbnRzYCwgewogICAgICBtZXRob2Q6ICJQT1NUIiwKICAgICAgaGVhZGVyczogeyAiQ29udGVudC1UeXBlIjogImFwcGxpY2F0aW9uL2pzb24iIH0sCiAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHsgYm9keTogdGV4dCB9KSwKICAgIH0pOwogIH0KfQoKLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ci8vIEhpbGZzZnVua3Rpb25lbgovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCmZ1bmN0aW9uIHNoZWxsUXVvdGUoc3RyKSB7CiAgLy8gS2xhc3Npc2NoZXMgUE9TSVgtU2luZ2xlLVF1b3RlLUVzY2FwaW5nOiBqZWRlcyAnIHdpcmQgenUgJ1wnJyAoc2NobGllc3NlbiwgZXNjYXB0ZXMKICAvLyBRdW90ZSwgd2llZGVyIG9lZmZuZW4pLiBTdHJpbmcucmF3IGhhZWx0IGRpZSBFcnNldHp1bmcgZnJlaSB2b24gQmFja3NsYXNoLUVzY2FwZXMuCiAgY29uc3QgZXNjYXBlZCA9IFN0cmluZyhzdHIpLnJlcGxhY2VBbGwoIiciLCBTdHJpbmcucmF3YCdcJydgKTsKICByZXR1cm4gYCcke2VzY2FwZWR9J2A7Cn0KCmZ1bmN0aW9uIGxhYmVsVG9TdGF0dXMobGFiZWxOYW1lcywgY29uZmlnLCBzdGF0ZSkgewogIGZvciAoY29uc3QgW3N0YXR1cywgbGFiZWxdIG9mIE9iamVjdC5lbnRyaWVzKGNvbHVtbkxhYmVscyhjb25maWcpKSkgewogICAgaWYgKGlzU3RhdGVDb2x1bW4oc3RhdHVzLCBjb25maWcpKSBjb250aW51ZTsKICAgIGlmIChsYWJlbE5hbWVzLmluY2x1ZGVzKGxhYmVsKSkgcmV0dXJuIHN0YXR1czsKICB9CiAgaWYgKHN0YXRlID09PSAiY2xvc2VkIikgcmV0dXJuICJkb25lIjsKICBpZiAoc3RhdGUgPT09ICJvcGVuZWQiICYmIGlzU3RhdGVDb2x1bW4oImJhY2tsb2ciLCBjb25maWcpKSByZXR1cm4gImJhY2tsb2ciOwogIHJldHVybiBudWxsOwp9CgovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8gQWRhcHRlci1BdXN3YWhsCi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKZnVuY3Rpb24gcmVzb2x2ZVRyYWNrZXIoY29uZmlnKSB7CiAgc3dpdGNoIChjb25maWcuaXNzdWVUcmFja2VyKSB7CiAgICBjYXNlICJnaXRodWIiOiByZXR1cm4gbmV3IEdpdEh1Yklzc3VlVHJhY2tlcihjb25maWcpOwogICAgY2FzZSAiZ2l0bGFiIjogcmV0dXJuIG5ldyBHaXRMYWJJc3N1ZVRyYWNrZXIoY29uZmlnKTsKICAgIGNhc2UgImxvY2FsIjogIHJldHVybiBuZXcgTG9jYWxJc3N1ZVRyYWNrZXIoY29uZmlnKTsKICAgIGNhc2UgInRvb2xib3giOiByZXR1cm4gbmV3IFRvb2xib3hJc3N1ZVRyYWNrZXIoY29uZmlnKTsKICAgIGRlZmF1bHQ6IGZhaWwoYFVuYmVrYW5udGVyIGlzc3VlVHJhY2tlcjogJyR7Y29uZmlnLmlzc3VlVHJhY2tlcn0nLiBFcndhcnRldDogZ2l0aHViIHwgZ2l0bGFiIHwgbG9jYWwgfCB0b29sYm94YCk7CiAgfQp9CgpmdW5jdGlvbiByZXNvbHZlQ29kZUhvc3QoY29uZmlnKSB7CiAgc3dpdGNoIChjb25maWcuY29kZUhvc3QpIHsKICAgIGNhc2UgImdpdGh1YiI6IHJldHVybiBuZXcgR2l0SHViQ29kZUhvc3QoY29uZmlnKTsKICAgIGNhc2UgImdpdGxhYiI6IHJldHVybiBuZXcgR2l0TGFiQ29kZUhvc3QoKTsKICAgIGNhc2UgImxvY2FsIjogIHJldHVybiBuZXcgTG9jYWxDb2RlSG9zdCgpOwogICAgZGVmYXVsdDogZmFpbChgVW5iZWthbm50ZXIgY29kZUhvc3Q6ICcke2NvbmZpZy5jb2RlSG9zdH0nLiBFcndhcnRldDogZ2l0aHViIHwgZ2l0bGFiIHwgbG9jYWxgKTsKICB9Cn0KCi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQovLyBEaXNwYXRjaAovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCi8vIEVpbiBIYW5kbGVyIGplIGlzc3VlLVN1YmJlZmVobDogaGFlbHQgZGllIEFyZ3VtZW50LVZhbGlkaWVydW5nIGZsYWNoIChhdWYgRnVua3Rpb25zZWJlbmUKLy8gc3RhdHQgdGllZiBpbiB2ZXJzY2hhY2h0ZWx0ZW4gc3dpdGNoLWNhc2VzKSB1bmQgZGFtaXQgZGllIGtvZ25pdGl2ZSBLb21wbGV4aXRhZXQgbmllZHJpZy4KYXN5bmMgZnVuY3Rpb24gaXNzdWVDcmVhdGUodHJhY2tlciwgYXJncykgewogIGlmICghYXJncy50aXRsZSkgZmFpbCgiLS10aXRsZSBpc3QgZXJmb3JkZXJsaWNoIik7CiAgb3V0KGF3YWl0IHRyYWNrZXIuY3JlYXRlSXNzdWUoewogICAgdGl0bGU6IGFyZ3MudGl0bGUsCiAgICBib2R5OiBhcmdzLmJvZHkgfHwgIiIsCiAgICB0eXBlOiBhcmdzLnR5cGUsCiAgICBwYXJlbnQ6IGFyZ3MucGFyZW50LAogICAgY29sb3I6IGFyZ3MuY29sb3IsCiAgICBzaG9ydGNvZGU6IGFyZ3Muc2hvcnRjb2RlLAogIH0pKTsKfQoKYXN5bmMgZnVuY3Rpb24gaXNzdWVHZXQodHJhY2tlciwgYXJncykgewogIGNvbnN0IGlkID0gYXJncy5fWzBdOwogIGlmICghaWQpIGZhaWwoImlkIGlzdCBlcmZvcmRlcmxpY2g6IGJvYXJkLm1qcyBpc3N1ZSBnZXQgPGlkPiIpOwogIG91dChhd2FpdCB0cmFja2VyLmdldElzc3VlKGlkKSk7Cn0KCmFzeW5jIGZ1bmN0aW9uIGlzc3VlTGlzdCh0cmFja2VyLCBhcmdzKSB7CiAgaWYgKGFyZ3Muc3RhdHVzICYmICFWQUxJRF9TVEFUVVNFUy5pbmNsdWRlcyhhcmdzLnN0YXR1cykpIHsKICAgIGZhaWwoYFVuZ3VlbHRpZ2VyIFN0YXR1cyAnJHthcmdzLnN0YXR1c30nLiBHdWVsdGlnOiAke1ZBTElEX1NUQVRVU0VTLmpvaW4oIiwgIil9YCk7CiAgfQogIG91dChhd2FpdCB0cmFja2VyLmxpc3RJc3N1ZXMoYXJncy5zdGF0dXMpKTsKfQoKYXN5bmMgZnVuY3Rpb24gaXNzdWVFcGljcyh0cmFja2VyKSB7CiAgaWYgKHR5cGVvZiB0cmFja2VyLmxpc3RFcGljcyAhPT0gImZ1bmN0aW9uIikgewogICAgZmFpbCgiZXBpY3Mgd2lyZCBudXIgaW0gbG9rYWxlbiBNb2R1cyB1bnRlcnN0dWV0enQgKGlzc3VlVHJhY2tlcjogbG9jYWwpIik7CiAgfQogIG91dChhd2FpdCB0cmFja2VyLmxpc3RFcGljcygpKTsKfQoKYXN5bmMgZnVuY3Rpb24gaXNzdWVNb3ZlKHRyYWNrZXIsIGFyZ3MpIHsKICBjb25zdCBbaWQsIHRvU3RhdHVzXSA9IGFyZ3MuXzsKICBpZiAoIWlkKSBmYWlsKCJpZCBpc3QgZXJmb3JkZXJsaWNoOiBib2FyZC5tanMgaXNzdWUgbW92ZSA8aWQ+IDxzdGF0dXM+Iik7CiAgaWYgKCF0b1N0YXR1cykgZmFpbCgic3RhdHVzIGlzdCBlcmZvcmRlcmxpY2g6IGJvYXJkLm1qcyBpc3N1ZSBtb3ZlIDxpZD4gPHN0YXR1cz4iKTsKICBpZiAoIVZBTElEX1NUQVRVU0VTLmluY2x1ZGVzKHRvU3RhdHVzKSkgewogICAgZmFpbChgVW5ndWVsdGlnZXIgU3RhdHVzICcke3RvU3RhdHVzfScuIEd1ZWx0aWc6ICR7VkFMSURfU1RBVFVTRVMuam9pbigiLCAiKX1gKTsKICB9CiAgYXdhaXQgdHJhY2tlci5tb3ZlSXNzdWUoaWQsIHRvU3RhdHVzKTsKICBvdXQoeyBvazogdHJ1ZSwgaWQsIHN0YXR1czogdG9TdGF0dXMgfSk7Cn0KCmFzeW5jIGZ1bmN0aW9uIGlzc3VlQ29tbWVudCh0cmFja2VyLCBhcmdzKSB7CiAgY29uc3QgaWQgPSBhcmdzLl9bMF07CiAgaWYgKCFpZCkgZmFpbCgiaWQgaXN0IGVyZm9yZGVybGljaDogYm9hcmQubWpzIGlzc3VlIGNvbW1lbnQgPGlkPiAtLXRleHQgXCIuLi5cIiIpOwogIGlmICghYXJncy50ZXh0KSBmYWlsKCItLXRleHQgaXN0IGVyZm9yZGVybGljaCIpOwogIGF3YWl0IHRyYWNrZXIuY29tbWVudElzc3VlKGlkLCBhcmdzLnRleHQpOwogIG91dCh7IG9rOiB0cnVlLCBpZCB9KTsKfQoKYXN5bmMgZnVuY3Rpb24gZGlzcGF0Y2hJc3N1ZShjb21tYW5kLCBhcmdzKSB7CiAgY29uc3QgdHJhY2tlciA9IHJlc29sdmVUcmFja2VyKGxvYWRDb25maWcoKSk7CiAgc3dpdGNoIChjb21tYW5kKSB7CiAgICBjYXNlICJjcmVhdGUiOiAgcmV0dXJuIGlzc3VlQ3JlYXRlKHRyYWNrZXIsIGFyZ3MpOwogICAgY2FzZSAiZ2V0IjogICAgIHJldHVybiBpc3N1ZUdldCh0cmFja2VyLCBhcmdzKTsKICAgIGNhc2UgImxpc3QiOiAgICByZXR1cm4gaXNzdWVMaXN0KHRyYWNrZXIsIGFyZ3MpOwogICAgY2FzZSAiZXBpY3MiOiAgIHJldHVybiBpc3N1ZUVwaWNzKHRyYWNrZXIpOwogICAgY2FzZSAibW92ZSI6ICAgIHJldHVybiBpc3N1ZU1vdmUodHJhY2tlciwgYXJncyk7CiAgICBjYXNlICJjb21tZW50IjogcmV0dXJuIGlzc3VlQ29tbWVudCh0cmFja2VyLCBhcmdzKTsKICAgIGRlZmF1bHQ6CiAgICAgIHByb2Nlc3Muc3Rkb3V0LndyaXRlKEhFTFApOwogICAgICBmYWlsKGBVbmJla2FubnRlciBpc3N1ZS1CZWZlaGw6ICcke2NvbW1hbmR9J2ApOwogIH0KfQoKYXN5bmMgZnVuY3Rpb24gY29kZVJlcG9OYW1lKGhvc3QpIHsKICBvdXQoeyByZXBvTmFtZTogYXdhaXQgaG9zdC5nZXRSZXBvTmFtZSgpIH0pOwp9Cgphc3luYyBmdW5jdGlvbiBjb2RlUHIoaG9zdCwgYXJncykgewogIGlmICghYXJncy5mcm9tKSBmYWlsKCItLWZyb20gaXN0IGVyZm9yZGVybGljaCIpOwogIGlmICghYXJncy50bykgZmFpbCgiLS10byBpc3QgZXJmb3JkZXJsaWNoIik7CiAgaWYgKCFob3N0LnN1cHBvcnRzUHVsbFJlcXVlc3RzKCkpIHsKICAgIGZhaWwoIkRpZXNlciBjb2RlSG9zdCB1bnRlcnN0dWV0enQga2VpbmUgUHVsbCBSZXF1ZXN0cy4gTnV0emUgZWluZW4gbG9rYWxlbiBnaXQtTWVyZ2UuIik7CiAgfQogIG91dChhd2FpdCBob3N0LmNyZWF0ZVB1bGxSZXF1ZXN0KHsgZnJvbTogYXJncy5mcm9tLCB0bzogYXJncy50bywgdGl0bGU6IGFyZ3MudGl0bGUgfSkpOwp9Cgphc3luYyBmdW5jdGlvbiBkaXNwYXRjaENvZGUoY29tbWFuZCwgYXJncykgewogIGNvbnN0IGhvc3QgPSByZXNvbHZlQ29kZUhvc3QobG9hZENvbmZpZygpKTsKICBzd2l0Y2ggKGNvbW1hbmQpIHsKICAgIGNhc2UgInJlcG8tbmFtZSI6IHJldHVybiBjb2RlUmVwb05hbWUoaG9zdCk7CiAgICBjYXNlICJwciI6ICAgICAgICByZXR1cm4gY29kZVByKGhvc3QsIGFyZ3MpOwogICAgZGVmYXVsdDoKICAgICAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoSEVMUCk7CiAgICAgIGZhaWwoYFVuYmVrYW5udGVyIGNvZGUtQmVmZWhsOiAnJHtjb21tYW5kfSdgKTsKICB9Cn0KCmFzeW5jIGZ1bmN0aW9uIG1haW4oKSB7CiAgY29uc3QgYXJndiA9IHByb2Nlc3MuYXJndi5zbGljZSgyKTsKCiAgaWYgKGFyZ3YubGVuZ3RoID09PSAwIHx8IGFyZ3ZbMF0gPT09ICItLWhlbHAiIHx8IGFyZ3ZbMF0gPT09ICItaCIpIHsKICAgIHByb2Nlc3Muc3Rkb3V0LndyaXRlKEhFTFApOwogICAgcHJvY2Vzcy5leGl0KDApOwogIH0KCiAgY29uc3QgW2F4aXMsIGNvbW1hbmQsIC4uLnJlc3RdID0gYXJndjsKICBjb25zdCBhcmdzID0gcGFyc2VBcmdzKHJlc3QpOwoKICBpZiAoYXhpcyA9PT0gImlzc3VlIikgewogICAgYXdhaXQgZGlzcGF0Y2hJc3N1ZShjb21tYW5kLCBhcmdzKTsKICB9IGVsc2UgaWYgKGF4aXMgPT09ICJjb2RlIikgewogICAgYXdhaXQgZGlzcGF0Y2hDb2RlKGNvbW1hbmQsIGFyZ3MpOwogIH0gZWxzZSB7CiAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShIRUxQKTsKICAgIGZhaWwoYFVuYmVrYW5udGUgQWNoc2U6ICcke2F4aXN9Jy4gRXJ3YXJ0ZXQ6IGlzc3VlIHwgY29kZWApOwogIH0KfQoKdHJ5IHsKICBhd2FpdCBtYWluKCk7Cn0gY2F0Y2ggKGVycikgewogIGNvbnN0IHByZWZpeCA9IGVyciBpbnN0YW5jZW9mIEJvYXJkRXJyb3IgPyAiRmVobGVyIiA6ICJVbmVyd2FydGV0ZXIgRmVobGVyIjsKICBwcm9jZXNzLnN0ZGVyci53cml0ZShgJHtwcmVmaXh9OiAke2Vyci5tZXNzYWdlfVxuYCk7CiAgcHJvY2Vzcy5leGl0KDEpOwp9Cg==";

// --- Skills (Base64-eingebettet fuer Single-File-Portabilitaet) ---
// JSON { skillName: { dateiname: inhalt } } fuer alle Skill-Ordner unter skills/.
// SYNC: Nach jeder Aenderung an skills/<name>/ neu generieren:
//   node tools/sync-blobs.mjs        (Pruefung: node tools/sync-blobs.mjs --check)
const SKILLS_B64 = "eyJkb2N1bWVudCI6eyJTS0lMTC5tZCI6Ii0tLVxubmFtZTogZG9jdW1lbnRcbmRlc2NyaXB0aW9uOiBTY2hyaXR0IDkuNSBkZXMgOS1TY2hyaXR0LVByb3plc3NlcyDigJQgc2NocmVpYnQgbmFjaCBkZXIgU2Vzc2lvbiBlaW5lbiBUYWdlc2xvZy1FaW50cmFnIGluIGRlbiBWYXVsdCB1bmQgYWt0dWFsaXNpZXJ0IGRpZSBQcm9qZWt0bm90aXouIE51dHplIGRpZXNlbiBTa2lsbCB3ZW5uIGRlciBOdXR6ZXIgL2RvY3VtZW50IGF1ZnJ1ZnQgb2RlciBkaWUgU2Vzc2lvbiBkb2t1bWVudGllcmVuIHdpbGwuXG51c2VyLWludm9jYWJsZTogdHJ1ZVxuLS0tXG5cbiMgRG9jdW1lbnRcblxuU2Nocml0dCA5LjU6IFNlc3Npb24tRW5kZS4gV2FzIGluIGRpZXNlciBTZXNzaW9uIGdlYmF1dCwgZW50c2NoaWVkZW4gdW5kIGdlbGVybnQgd3VyZGUsIGluIGRlbiBNZW1vcnktVmF1bHQgc2NocmVpYmVuLlxuXG4jIyBWb3JiZWRpbmd1bmc6IE1vZHVzIGJlc3RpbW1lblxuXG5TdWNoZSBkaWUgQ29uZmlnIGluIGRpZXNlciBSZWloZW5mb2xnZSAoZXJzdGVzIGdlZnVuZGVuZXMgZ2V3aW5udCk6XG4xLiBgLmNsYXVkZS9rb250ZXh0LmNvbmZpZy5qc29uYCBpbSBha3R1ZWxsZW4gUHJvamVrdHZlcnplaWNobmlzXG4yLiBgfi8uY2xhdWRlL2tvbnRleHQuY29uZmlnLmpzb25gIChnbG9iYWwpXG5cbkRhcmF1cyBlcmdpYnQgc2ljaCBlaW5lciB2b24gendlaSBNb2RpOlxuXG4qKk1vZHVzIEEgKFZvbGxtb2R1cyk6KiogQ29uZmlnIGdlZnVuZGVuIHVuZCBgdmF1bHRgLUZlbGQgZ2VzZXR6dC4gVGFnZXNsb2cgaW4gZGVuIFZhdWx0IHNjaHJlaWJlbiwgUHJvamVrdG5vdGl6IGFrdHVhbGlzaWVyZW4uXG5cbioqTW9kdXMgQiAoRGVncmFkZWQgTW9kZSk6KiogQ29uZmlnIGZlaGx0IG9kZXIga2VpbiBgdmF1bHRgLUZlbGQuIExvZyBpbiBgZG9jcy9zZXNzaW9uLWxvZy9KSkpKLU1NLVRULm1kYCBpbSBQcm9qZWt0dmVyemVpY2huaXMgc2NocmVpYmVuLiBLZWluIEFiYnJ1Y2guXG5cbiMjIEFibGF1ZlxuXG4jIyMgMS4gQ29uZmlnIHVuZCBQcm9qZWt0bmFtZSBsZXNlblxuXG5MaWVzIGBrb250ZXh0LmNvbmZpZy5qc29uYCAobG9rYWxlIFZlcnNpb24gaGF0IFZvcnJhbmcpLiBFeHRyYWhpZXJlIGB2YXVsdGAgd2VubiB2b3JoYW5kZW4uXG5cblByb2pla3RuYW1lOlxuYGBgYmFzaFxubm9kZSAuY2xhdWRlL2tpdC9ib2FyZC5tanMgY29kZSByZXBvLW5hbWVcbmBgYFxuR2lidCBgeyBcInJlcG9OYW1lXCI6IFwib3duZXIvcmVwb1wiIH1gIHp1cnVlY2suIExldHp0ZXMgU2VnbWVudCBvaG5lIFBmYWQgdmVyd2VuZGVuLlxuXG5GYWxsYmFjayBpbSBsb2thbGVuIE1vZHVzIChgY29kZUhvc3Q6IGxvY2FsYCkgb2RlciBvaG5lIGdpdC1SZW1vdGU6IERlciBBZGFwdGVyIGxpZWZlcnQgZGVuICoqVmVyemVpY2huaXNuYW1lbioqIGRlcyBQcm9qZWt0cyAoYGJhc2VuYW1lYCBkZXMgQXJiZWl0c3ZlcnplaWNobmlzc2VzKSBzdGF0dCBgb3duZXIvcmVwb2AuIERhcyBpc3QgZXJ3YXJ0ZXRlcyBWZXJoYWx0ZW4sIGtlaW4gRmVobGVyIOKAlCBkZXIgVGFnZXNsb2ctRWludHJhZyB1bmQgZGllIFByb2pla3Rub3RpeiB2ZXJ3ZW5kZW4gZGFubiBkaWVzZW4gVmVyemVpY2huaXNuYW1lbiBhbHMgUHJvamVrdG5hbWVuLiBXZXIgZWluZW4gYW5kZXJlbiBOYW1lbiBpbSBMb2cgd2lsbCwgYmVuZW5udCBkYXMgUHJvamVrdHZlcnplaWNobmlzIGVudHNwcmVjaGVuZCBvZGVyIHNldHp0IGVpbiBnaXQtUmVtb3RlLlxuXG4jIyMgMi4gVGFnZXNsb2cgc2NocmVpYmVuXG5cbioqTW9kdXMgQToqKiBaaWVsLURhdGVpIGB7dmF1bHR9L0xvZy9KSkpKLU1NLVRULm1kYFxuXG4qKk1vZHVzIEI6KiogWmllbC1EYXRlaSBgZG9jcy9zZXNzaW9uLWxvZy9KSkpKLU1NLVRULm1kYCBpbSBQcm9qZWt0dmVyemVpY2huaXMuIFZlcnplaWNobmlzIGFubGVnZW4gd2VubiBuaWNodCB2b3JoYW5kZW4uXG5cbkluIGJlaWRlbiBNb2RpOlxuLSBXZW5uIGRpZSBEYXRlaSBub2NoIG5pY2h0IGV4aXN0aWVydDogbmV1IGFubGVnZW4uXG4tIFdlbm4gc2llIHNjaG9uIGV4aXN0aWVydCAoendlaXRlIFNlc3Npb24gYW0gc2VsYmVuIFRhZyk6IG5ldWVuIEFic2Nobml0dCBhbmhhZW5nZW4sIG5pY2h0IHVlYmVyc2NocmVpYmVuLlxuXG4qKkZvcm1hdDoqKlxuXG5gYGBtYXJrZG93blxuIyBKSkpKLU1NLVRUIOKAlCB7UHJvamVrdG5hbWV9IFNlc3Npb25cblxue0t1cnplciBFaW5zdGllZ3NzYXR6OiB3YXMgd2FyIGRlciBTY2h3ZXJwdW5rdCBkaWVzZXIgU2Vzc2lvbj99XG5cbiMjIEVpbnN0aWVnXG5cbi0ge1dlbGNoZSBEYXRlaWVuL1Jlc3NvdXJjZW4gd3VyZGVuIHp1IEJlZ2lubiBnZWxhZGVuP31cblxuIyMge0Fic2Nobml0dCBwcm8gdW1nZXNldHp0ZW0gSXNzdWUgb2RlciBUaGVtYX1cblxue0ZyZWllciBUZXh0OiB3YXMgd3VyZGUgZ2ViYXV0LCB3YXJ1bSBzbywgd2ljaHRpZ2UgRW50c2NoZWlkdW5nZW59XG5cbkNvbW1pdHRldCB7SEFTSH0gLyBDb21taXRzOiB7TGlzdGV9XG5cbiMjIE9mZmVuZSBQdW5rdGVcblxuLSB7V2FzIGJsZWlidCBvZmZlbiwgd2VsY2hlIG1hbnVlbGxlbiBTY2hyaXR0ZSBzdGVoZW4gYW4/fVxuYGBgXG5cblN5bnRoZXRpc2llcmUgZGVuIEluaGFsdCBhdXMgZGVtIFNlc3Npb24tS29udGV4dDogSXNzdWVzLCBDb21taXRzLCBFbnRzY2hlaWR1bmdlbiwgd2FzIGFscyBuYWVjaHN0ZXMga29tbXQuIEtlaW4gVGVtcGxhdGUtRmlsbC1Jbiwgc29uZGVybiBsZXNiYXJlIFp1c2FtbWVuZmFzc3VuZy5cblxuIyMjIDMuIFByb2pla3Rub3RpeiBha3R1YWxpc2llcmVuIChudXIgTW9kdXMgQSlcblxuUHJvamVrdG5vdGl6OiBge3ZhdWx0fS9Qcm9qZWt0ZS97bmFtZX0ve25hbWV9Lm1kYFxuXG5Ba3R1YWxpc2llcmUgZGVuIEFic2Nobml0dCBgIyMgWnVsZXR6dCBha3R1YWxpc2llcnRgIG1pdCBlaW5lbSBuZXVlbiBFaW50cmFnIG9iZW4gKG5ldWVzdGUgRWludHJhZWdlIHp1ZXJzdCk6XG5cbmBgYFxuLSBKSkpKLU1NLVRUOiB7S3VyemUgWnVzYW1tZW5mYXNzdW5nOiB3YXMgd3VyZGUgdW1nZXNldHp0LCB3YXMgc3RlaHQgbm9jaCBhdXN9XG5gYGBcblxuQmVzdGVoZW5kZSBFaW50cmFlZ2UgYmxlaWJlbiBlcmhhbHRlbi5cblxuIyMjIDQuIEJlc3RhZXRpZ3VuZ1xuXG5NZWxkZSB3YXMgZ2VzY2hyaWViZW4gd3VyZGU6XG5cbioqTW9kdXMgQToqKlxuYGBgXG5Eb2t1bWVudGllcnQ6XG4tIExvZy9KSkpKLU1NLVRULm1kIChuZXUgLyBlcmdhZW56dClcbi0gUHJvamVrdGUve25hbWV9L3tuYW1lfS5tZCAoWnVsZXR6dCBha3R1YWxpc2llcnQpXG5gYGBcblxuKipNb2R1cyBCOioqXG5gYGBcbkRva3VtZW50aWVydDpcbi0gZG9jcy9zZXNzaW9uLWxvZy9KSkpKLU1NLVRULm1kIChuZXUgLyBlcmdhZW56dClcblxuS2VpbiBWYXVsdCBrb25maWd1cmllcnQuIExvZyBpbnMgUHJvamVrdHZlcnplaWNobmlzIGdlc2NocmllYmVuLlxuRnVlciBWb2xsbW9kdXM6IH4vLmNsYXVkZS9rb250ZXh0LmNvbmZpZy5qc29uIGFubGVnZW4gbWl0IHZhdWx0LVBmYWQuXG5gYGBcblxuIyMgV2FzIGRpZXNlciBTa2lsbCBuaWNodCB0dXRcblxuLSBLZWluIExlc2VuIHZvbiBWYXVsdC1EYXRlaWVuIGluIGRlbiBLb250ZXh0IChkYXMgaXN0IC9rb250ZXh0KVxuLSBLZWluZSBDb2RlLcOEbmRlcnVuZ2VuXG4tIEtlaW4gQ29tbWl0LCBrZWluIFB1c2hcbi0gS2VpbiDDnGJlcnNjaHJlaWJlbiBiZXN0ZWhlbmRlciBMb2ctQWJzY2huaXR0ZSDigJQgbnVyIGFuaMOkbmdlblxuIn0sImltcGxlbWVudC1kb25lIjp7IlNLSUxMLm1kIjoiLS0tXG5uYW1lOiBpbXBsZW1lbnQtZG9uZVxuZGVzY3JpcHRpb246IEdyYW51bGFyZSBFaW5zdGVpZ2VyLVZhcmlhbnRlIHZvbiBTY2hyaXR0IDUgKFRlaWwgMikg4oCUIGltcGxlbWVudGllcnQgZ2VnZW4gZGllIHZvbiAvaW1wbGVtZW50LXRlc3Qgdm9yYmVyZWl0ZXRlbiByb3RlbiBUZXN0cywgYmlzIHNpZSBncnVlbiBzaW5kLCBjb21taXR0ZXQgdW5kIHZlcnNjaGllYnQgbmFjaCBJbiByZXZpZXcuIE51dHplIGRpZXNlbiBTa2lsbCB3ZW5uIGRlciBOdXR6ZXIgL2ltcGxlbWVudC1kb25lIGF1ZnJ1ZnQgb2RlciBuYWNoIC9pbXBsZW1lbnQtdGVzdCBkaWUgSW1wbGVtZW50aWVydW5nIGdlZ2VuIGRpZSByb3RlbiBUZXN0cyBmb3J0c2V0emVuIHdpbGwuXG51c2VyLWludm9jYWJsZTogdHJ1ZVxuLS0tXG5cbiMgSW1wbGVtZW50IERvbmVcblxuR3JhbnVsYXJlIFZhcmlhbnRlIHZvbiBTY2hyaXR0IDUgKFRlaWwgMiB2b24gMik6IGdlZ2VuIGRpZSB2b24gYC9pbXBsZW1lbnQtdGVzdGAgZ2VzY2hyaWViZW5lbiwgcm90ZW4gVGVzdHMgaW1wbGVtZW50aWVyZW4sIGJpcyBzaWUgZ3LDvG4gc2luZCwgY29tbWl0dGVuLCBuYWNoIEluIHJldmlldyB2ZXJzY2hpZWJlbi5cblxuIyMgVm9yYmVkaW5ndW5nXG5cbiMjIyAwLiBJc3N1ZSBpbiBJbiBwcm9ncmVzcyBmaW5kZW5cblxuYGBgYmFzaFxubm9kZSAuY2xhdWRlL2tpdC9ib2FyZC5tanMgaXNzdWUgbGlzdCAtLXN0YXR1cyBpbl9wcm9ncmVzc1xuYGBgXG5cbi0gS2VpbiBJc3N1ZSBkb3J0OiBzdG9wcGVuLlxuICA+IFwiS2VpbiBJc3N1ZSBpbiBJbiBwcm9ncmVzcy4gRXJzdCBgL2ltcGxlbWVudC10ZXN0YCBzdGFydGVuLCB1bSBUZXN0cyBmw7xyIGVpbiBJc3N1ZSB6dSBzY2hyZWliZW4uXCJcbi0gTWVociBhbHMgZWluIElzc3VlIGRvcnQ6IHN0b3BwZW4sIGF1Zmxpc3RlbiwgTnV0emVyIHVtIEF1c3dhaGwgYml0dGVuLiBOaWNodCByYXRlbiwgd2VsY2hlcyBnZW1laW50IGlzdC5cbi0gR2VuYXUgZWluIElzc3VlIGRvcnQ6IGRhcyBpc3QgZGFzIGFrdHVlbGxlIElzc3VlLlxuXG4jIyBBYmxhdWZcblxuIyMjIDEuIElzc3VlIHZvbGxzdMOkbmRpZyBsZXNlblxuXG5MaWVzIGFsbGUgdmllciBBYnNjaG5pdHRlIGVybmV1dC4gRGFzIEFremVwdGFuemtyaXRlcml1bSBpc3QgZGVyIE1hw59zdGFiIGbDvHIgZGllIEltcGxlbWVudGllcnVuZywgbmljaHQgZGllIGJlcmVpdHMgdm9yaGFuZGVuZW4gVGVzdHMgYWxsZWluLlxuXG4jIyMgMi4gR2VnZW4gZGllIFRlc3RzIGltcGxlbWVudGllcmVuXG5cbi0gSW1wbGVtZW50aWVyZW4sIGJpcyBkaWUgdm9uIGAvaW1wbGVtZW50LXRlc3RgIGdlc2NocmllYmVuZW4gVGVzdHMgZ3LDvG4gc2luZC5cbi0gVGVzdGNvZGUgbmljaHQgYW5mYXNzZW4g4oCUIGF1w59lciBlciBpc3QgbmFjaHdlaXNsaWNoIGZhbHNjaCBmb3JtdWxpZXJ0ICh3aWRlcnNwcmljaHQgZGVtIEFremVwdGFuemtyaXRlcml1bSwgdGVzdGV0IGRhcyBGYWxzY2hlKS4gRGFubiBSw7xja3NwcmFjaGUgbWl0IGRlbSBNZW5zY2hlbiBzdGF0dCBzdGlsbHNjaHdlaWdlbmRlciDDhG5kZXJ1bmcuXG4tIEJlc3RlaGVuZGUgTXVzdGVyIHVuZCBGdW5rdGlvbmVuIHdpZWRlcnZlcndlbmRlbi4gS2VpbiBGZWF0dXJlLCBrZWluZSBSZWZhY3RvcmluZywga2VpbmUgQWJzdHJha3Rpb24sIGRpZSBkYXMgSXNzdWUgbmljaHQgdmVybGFuZ3QuXG5cbiMjIyAzLiBMb2thbCBjb21taXR0ZW4gKG5pY2h0IHB1c2hlbilcblxuR2xlaWNoZXMgRm9ybWF0IHdpZSBgaW1wbGVtZW50LXJlYWR5YCBTY2hyaXR0IDQg4oCUIFRlc3RzIHVuZCBJbXBsZW1lbnRpZXJ1bmcgenVzYW1tZW4gaW4gZWluZW0gQ29tbWl0OlxuXG5gYGBiYXNoXG5naXQgYWRkIDxnZcOkbmRlcnRlIERhdGVpZW4+XG5naXQgY29tbWl0IC1tIFwiS3VyenRpdGVsIChJc3N1ZSAjTilcblxuQmVzY2hyZWlidW5nIGRlciDDhG5kZXJ1bmdlbiB1bmQgQmVncsO8bmR1bmcuXG5cblJlZnMgI05cblxuQ28tQXV0aG9yZWQtQnk6IENsYXVkZSBTb25uZXQgNC42IDxub3JlcGx5QGFudGhyb3BpYy5jb20+XCJcbmBgYFxuXG5OdXIgZXhwbGl6aXQgdmVyw6RuZGVydGUgRGF0ZWllbiBzdGFnZW4g4oCUIGtlaW4gYGdpdCBhZGQgLUFgIG9kZXIgYGdpdCBhZGQgLmAuXG5cbioqS2VpbiBgQ2xvc2VzYC9gRml4ZXNgL2BSZXNvbHZlcyAjTmAgaW0gQ29tbWl0LioqIERpZXNlIEtleXdvcmRzIHNjaGxpZcOfZW4gZGFzIElzc3VlIGF1dG9tYXRpc2NoIGJlaW0gUHVzaC9NZXJnZSwgdW5kIGRpZSBCb2FyZC1BdXRvbWF0aW9uIHppZWh0IGVzIGRhbm4gc29mb3J0IG5hY2ggRG9uZSDigJQgbm9jaCBiZXZvciBkZXIgTWVuc2NoIGdldGVzdGV0IGhhdC4gYFJlZnMgI05gIHZlcmxpbmt0LCBvaG5lIHp1IHNjaGxpZcOfZW4uIERhcyBTY2hsaWXDn2VuIG1hY2h0IGF1c3NjaGxpZcOfbGljaCBkZXIgTWVuc2NoLlxuXG4jIyMgNC4gSXNzdWUgbmFjaCBJbiByZXZpZXcgdmVyc2NoaWViZW4gKyBBYnNjaGx1c3NiZXJpY2h0XG5cbmBgYGJhc2hcbm5vZGUgLmNsYXVkZS9raXQvYm9hcmQubWpzIGlzc3VlIG1vdmUgPGlkPiBpbl9yZXZpZXdcbmBgYFxuXG5BYnNjaGx1c3NiZXJpY2h0IGFscyBJc3N1ZS1Lb21tZW50YXIsIGdsZWljaGVzIEZvcm1hdCB3aWUgYGltcGxlbWVudC1yZWFkeWAgU2Nocml0dCA1OlxuXG5gYGBiYXNoXG5ub2RlIC5jbGF1ZGUva2l0L2JvYXJkLm1qcyBpc3N1ZSBjb21tZW50IDxpZD4gLS10ZXh0IFwiIyMgQWJzY2hsdXNzYmVyaWNodCBJc3N1ZSAjTlxuLi4uXCJcbmBgYFxuXG5gYGBcbiMjIEFic2NobHVzc2JlcmljaHQgSXNzdWUgI05cblxuIyMjIMOEbmRlcnVuZ2VuXG4tIGBEYXRlaS5qYXZhYCDigJQga3VyemUgQmVzY2hyZWlidW5nIGRlciBXaXJrdW5nXG4tIGBEYXRlaVRlc3QuamF2YWAg4oCUIHdhcyBnZXRlc3RldCB3aXJkICh2b24gL2ltcGxlbWVudC10ZXN0IHZvcmJlcmVpdGV0KVxuXG4jIyMgVGVzdHMgdW5kIENoZWNrc1xuLSA8YXVzZ2Vmw7xocnRlcyBLb21tYW5kbz4g4oaSIDxFcmdlYm5pcz5cblxuIyMjIEhpbndlaXNlXG4tIDx2ZXJibGVpYmVuZGUgUmlzaWtlbiwgb2ZmZW5lIFB1bmt0ZSwgbWFudWVsbGUgRm9sZ2VzY2hyaXR0ZT5cbmBgYFxuXG4jIyBTdG9wLVB1bmt0ZVxuXG4tIFB1c2hlbjogbmllIG9obmUgZXhwbGl6aXRlIFRyaWdnZXItUGhyYXNlIGBwdXNoIG1haW5gXG4tIEJhY2tsb2cgbmFjaCBSZWFkeSB6aWVoZW46IG5pZSDigJQgZGFzIGlzdCBNYW5uZXMgR09cbi0gSXNzdWVzIGF1ZiBEb25lIHNldHplbjogbmllIOKAlCBkYXMgbWFjaHQgZGVyIE1lbnNjaCBuYWNoIHNlaW5lbSBUZXN0XG4tIElzc3VlLXNjaGxpZcOfZW5kZSBDb21taXQtS2V5d29yZHMgKGBDbG9zZXNgL2BGaXhlc2AvYFJlc29sdmVzICNOYCk6IG5pZSDigJQgbnVyIGBSZWZzICNOYFxuLSBUZXN0Y29kZSBzdGlsbHNjaHdlaWdlbmQgw6RuZGVybjogbmllIOKAlCBiZWkgWndlaWZlbCBSw7xja3NwcmFjaGUgc3RhdHQgZWlnZW5tw6RjaHRpZ2VyIEtvcnJla3R1clxuIn0sImltcGxlbWVudC1yZWFkeSI6eyJTS0lMTC5tZCI6Ii0tLVxubmFtZTogaW1wbGVtZW50LXJlYWR5XG5kZXNjcmlwdGlvbjogU2Nocml0dCA1IGRlcyA5LVNjaHJpdHQtUHJvemVzc2VzIOKAlCBhcmJlaXRldCBhbGxlIElzc3VlcyBpbiBkZXIgUmVhZHktU3BhbHRlIHNlcXVlbnppZWxsIG5hY2ggSXNzdWUtTnVtbWVyIGFiLCBjb21taXR0ZXQgbG9rYWwsIHB1c2h0IG5pY2h0LiBOdXR6ZSBkaWVzZW4gU2tpbGwgd2VubiBkZXIgTnV0emVyIC9pbXBsZW1lbnQtcmVhZHkgYXVmcnVmdCwgUmVhZHktSXNzdWVzIHVtc2V0emVuIHdpbGwgb2RlciBkYXMgR08genVyIEltcGxlbWVudGllcnVuZyBnaWJ0LlxudXNlci1pbnZvY2FibGU6IHRydWVcbi0tLVxuXG4jIEltcGxlbWVudCBSZWFkeVxuXG5TY2hyaXR0IDUgZGVzIDktU2Nocml0dC1Qcm96ZXNzZXM6IERpZSBLSSBhcmJlaXRldCBkaWUgUmVhZHktSXNzdWVzIHNlcXVlbnppZWxsIGFiLiBKZWRlcyBJc3N1ZSB3aXJkIHZvbGxzdMOkbmRpZyB1bWdlc2V0enQsIGxva2FsIGNvbW1pdHRldCB1bmQgbmFjaCBJbiByZXZpZXcgdmVyc2Nob2JlbiwgYmV2b3IgZGFzIG7DpGNoc3RlIGJlZ2lubnQuXG5cbiMjIFZvcmJlZGluZ3VuZ1xuXG5MaWVzIGAuY2xhdWRlL3dvcmtmbG93LmNvbmZpZy5qc29uYC4gUmVsZXZhbnRlcyBGZWxkOlxuLSBgbWFpbkJyYW5jaGA6IEJyYW5jaCBmw7xyIGxva2FsZSBDb21taXRzIChEZWZhdWx0OiBgbWFpbmApXG5cbiMjIEFibGF1ZiBwcm8gSXNzdWUgKFJlaWhlbmZvbGdlOiBhdWZzdGVpZ2VuZCBuYWNoIElzc3VlLUlELCB3aWUgdm9tIEFkYXB0ZXIgZ2VsaWVmZXJ0KVxuXG4jIyMgMC4gUmVhZHktSXNzdWVzIGxhZGVuXG5cbmBgYGJhc2hcbm5vZGUgLmNsYXVkZS9raXQvYm9hcmQubWpzIGlzc3VlIGxpc3QgLS1zdGF0dXMgcmVhZHlcbmBgYFxuXG5HaWJ0IGRpZSBJc3N1ZXMgYWxzIEpTT04tQXJyYXksIGF1ZnN0ZWlnZW5kIG5hY2ggSUQgc29ydGllcnQuIERpZXNlIFJlaWhlbmZvbGdlIGlzdCB2ZXJiaW5kbGljaC5cblxuIyMjIDEuIElzc3VlIG5hY2ggSW4gcHJvZ3Jlc3MgdmVyc2NoaWViZW5cblxuYGBgYmFzaFxubm9kZSAuY2xhdWRlL2tpdC9ib2FyZC5tanMgaXNzdWUgbW92ZSA8aWQ+IGluX3Byb2dyZXNzXG5gYGBcblxuIyMjIDIuIElzc3VlIHZvbGxzdMOkbmRpZyBsZXNlblxuXG5MaWVzIGFsbGUgdmllciBBYnNjaG5pdHRlIGRlcyBJc3N1ZXMuIEltcGxlbWVudGllcmUgKipnZWdlbiBkYXMgSXNzdWUqKiwgbmljaHQgZ2VnZW4gZGVuIENoYXQuIFdhcyBpbSBJc3N1ZSBzdGVodCwgd2lyZCBnZWJhdXQuIFdhcyBuaWNodCBkcmluc3RlaHQsIGJsZWlidCBkcmF1w59lbi5cblxuIyMjIDMuIEltcGxlbWVudGllcmVuXG5cbi0gVEREOiBUZXN0cyB6dWVyc3Qgc2NocmVpYmVuIHVuZCByb3QgbGF1ZmVuIGxhc3NlbiwgZGFubiBnZWdlbiBkaWUgVGVzdHMgaW1wbGVtZW50aWVyZW4sIGJpcyBncsO8blxuLSBCZXN0ZWhlbmRlIE11c3RlciB1bmQgRnVua3Rpb25lbiB3aWVkZXJ2ZXJ3ZW5kZW5cbi0gS2VpbiBGZWF0dXJlLCBrZWluZSBSZWZhY3RvcmluZywga2VpbmUgQWJzdHJha3Rpb24gZGllIGRhcyBJc3N1ZSBuaWNodCB2ZXJsYW5ndFxuLSBCZWkgVUktw4RuZGVydW5nZW46IERldi1TZXJ2ZXIgc3RhcnRlbiwgR29sZGVuIFBhdGggdW5kIEVkZ2UgQ2FzZXMgZHVyY2hrbGlja2VuXG4tIEJlaSBuZXVlciBvZGVyIGdlw6RuZGVydGVyIExvZ2lrOiBhYmdlZGVja3Qgb2RlciBiZWdyw7xuZGV0IGF1c2dlc2NobG9zc2VuIGdlbcOkw58gZGVyIENvdmVyYWdlLS9RdWFsaXTDpHRzLVBvbGljeSBkZXMgUHJvamVrdHMgKHNpZWhlIFByb2pla3QtR3VpZGUgYnp3LiBgd29ya2Zsb3cuY29uZmlnLmpzb25gKS4gVW50ZXN0ZXRlIExvZ2lrIG5pZSBzdGlsbHNjaHdlaWdlbmQgYXVzc2NobGllw59lbiwgU2Nod2VsbGVuIG5pZSBzZW5rZW4sIG51ciBkYW1pdCBlaW4gR2F0ZSBncsO8biB3aXJkLlxuXG5Gw7xyIGVpbmUgZ3JhbnVsYXJlcmUgVmFyaWFudGUgbWl0IGV4cGxpeml0ZW0gU3RvcHAgendpc2NoZW4gcm90IHVuZCBncsO8bjogYC9pbXBsZW1lbnQtdGVzdGAgZ2Vmb2xndCB2b24gYC9pbXBsZW1lbnQtZG9uZWAuXG5cbiMjIyA0LiBMb2thbCBjb21taXR0ZW4gKG5pY2h0IHB1c2hlbilcblxuYGBgYmFzaFxuZ2l0IGFkZCA8Z2XDpG5kZXJ0ZSBEYXRlaWVuPlxuZ2l0IGNvbW1pdCAtbSBcIkt1cnp0aXRlbCAoSXNzdWUgI04pXG5cbkJlc2NocmVpYnVuZyBkZXIgw4RuZGVydW5nZW4gdW5kIEJlZ3LDvG5kdW5nLlxuXG5SZWZzICNOXG5cbkNvLUF1dGhvcmVkLUJ5OiBDbGF1ZGUgU29ubmV0IDQuNiA8bm9yZXBseUBhbnRocm9waWMuY29tPlwiXG5gYGBcblxuTnVyIGV4cGxpeml0IHZlcsOkbmRlcnRlIERhdGVpZW4gc3RhZ2VuIOKAlCBrZWluIGBnaXQgYWRkIC1BYCBvZGVyIGBnaXQgYWRkIC5gLlxuXG4qKktlaW4gYENsb3Nlc2AvYEZpeGVzYC9gUmVzb2x2ZXMgI05gIGltIENvbW1pdC4qKiBEaWVzZSBLZXl3b3JkcyBzY2hsaWXDn2VuIGRhcyBJc3N1ZSBhdXRvbWF0aXNjaCwgc29iYWxkIGRlciBDb21taXQgYXVmIGRlbiBEZWZhdWx0LUJyYW5jaCBnZWxhbmd0IChgcHVzaGAvTWVyZ2UpLCB1bmQgZGllIEJvYXJkLUF1dG9tYXRpb24gemllaHQgZ2VzY2hsb3NzZW5lIElzc3VlcyBzb2ZvcnQgbmFjaCAqRG9uZSog4oCUIG5vY2ggYmV2b3IgZGVyIE1lbnNjaCB0ZXN0ZW4ga29ubnRlLiBgUmVmcyAjTmAgdmVybGlua3QgZGFzIElzc3VlLCBvaG5lIGVzIHp1IHNjaGxpZcOfZW4uIERhcyBTY2hsaWXDn2VuICjihpIgRG9uZSkgbWFjaHQgYXVzc2NobGllw59saWNoIGRlciBNZW5zY2ggbmFjaCBzZWluZW0gVGVzdC5cblxuIyMjIDUuIElzc3VlIG5hY2ggSW4gcmV2aWV3IHZlcnNjaGllYmVuICsgQWJzY2hsdXNzYmVyaWNodFxuXG5gYGBiYXNoXG5ub2RlIC5jbGF1ZGUva2l0L2JvYXJkLm1qcyBpc3N1ZSBtb3ZlIDxpZD4gaW5fcmV2aWV3XG5gYGBcblxuQWJzY2hsdXNzYmVyaWNodCBhbHMgSXNzdWUtS29tbWVudGFyOlxuXG5gYGBiYXNoXG5ub2RlIC5jbGF1ZGUva2l0L2JvYXJkLm1qcyBpc3N1ZSBjb21tZW50IDxpZD4gLS10ZXh0IFwiIyMgQWJzY2hsdXNzYmVyaWNodCBJc3N1ZSAjTlxuLi4uXCJcbmBgYFxuXG5Gb3JtYXQgZGVzIEFic2NobHVzc2JlcmljaHRzOlxuXG5gYGBcbiMjIEFic2NobHVzc2JlcmljaHQgSXNzdWUgI05cblxuIyMjIMOEbmRlcnVuZ2VuXG4tIGBEYXRlaS5qYXZhYCDigJQga3VyemUgQmVzY2hyZWlidW5nIGRlciBXaXJrdW5nXG4tIGBEYXRlaVRlc3QuamF2YWAg4oCUIHdhcyBnZXRlc3RldCB3aXJkXG5cbiMjIyBUZXN0cyB1bmQgQ2hlY2tzXG4tIDxhdXNnZWbDvGhydGVzIEtvbW1hbmRvPiDihpIgPEVyZ2VibmlzPlxuXG4jIyMgSGlud2Vpc2Vcbi0gPHZlcmJsZWliZW5kZSBSaXNpa2VuLCBvZmZlbmUgUHVua3RlLCBtYW51ZWxsZSBGb2xnZXNjaHJpdHRlPlxuYGBgXG5cbiMjIyA2LiBOw6RjaHN0ZXMgSXNzdWVcblxuU29iYWxkIGRhcyBJc3N1ZSBpbiBJbiByZXZpZXcgbGllZ3Q6IG5hZWNoc3RlIElzc3VlLUlEIGF1cyBkZW0genV2b3IgZ2VsYWRlbmVuIFJlYWR5LUFycmF5IGFiYXJiZWl0ZW4uIFdlbm4gUmVhZHkgbGVlciBpc3Q6IFZvbGx6dWcgbWVsZGVuLlxuXG4jIyBWZXJoYWx0ZW4gYmVpIGxlZXJlbSBSZWFkeVxuXG4+IFwiUmVhZHkgaXN0IGxlZXIuIEFsbGUgSXNzdWVzIGluIEluIHJldmlldy4gSWNoIHdhcnRlIGF1ZiBkZWluIEdPIGbDvHIgZGVuIG7DpGNoc3RlbiBCYXRjaC5cIlxuXG5LZWluIGVpZ2VubcOkY2h0aWdlcyBaaWVoZW4gYXVzIEJhY2tsb2cuIEtlaW4gUmF0ZW4sIHdlbGNoZXMgSXNzdWUgc2lubnZvbGwgd8OkcmUuXG5cbiMjIFN0b3AtUHVua3RlXG5cbi0gUHVzaGVuOiBuaWUgb2huZSBleHBsaXppdGUgVHJpZ2dlci1QaHJhc2UgYHB1c2ggbWFpbmBcbi0gQmFja2xvZyBuYWNoIFJlYWR5IHppZWhlbjogbmllIOKAlCBkYXMgaXN0IE1hbm5lcyBHT1xuLSBJc3N1ZXMgYXVmIERvbmUgc2V0emVuOiBuaWUg4oCUIGRhcyBtYWNodCBkZXIgTWVuc2NoIG5hY2ggc2VpbmVtIFRlc3Rcbi0gSXNzdWUtc2NobGllw59lbmRlIENvbW1pdC1LZXl3b3JkcyAoYENsb3Nlc2AvYEZpeGVzYC9gUmVzb2x2ZXMgI05gKTogbmllIOKAlCBzaWUgc2NobGllw59lbiBkYXMgSXNzdWUgYmVpbSBQdXNoL01lcmdlIHVuZCBkaWUgQm9hcmQtQXV0b21hdGlvbiB6aWVodCBlcyBuYWNoIERvbmUsIGJldm9yIGdldGVzdGV0IHd1cmRlLiBOdXIgYFJlZnMgI05gIHZlcndlbmRlbi5cbiJ9LCJpbXBsZW1lbnQtdGVzdCI6eyJTS0lMTC5tZCI6Ii0tLVxubmFtZTogaW1wbGVtZW50LXRlc3RcbmRlc2NyaXB0aW9uOiBHcmFudWxhcmUgRWluc3RlaWdlci1WYXJpYW50ZSB2b24gU2Nocml0dCA1IChUZWlsIDEpIOKAlCBzY2hyZWlidCBnZWdlbiBkYXMgbmFlY2hzdGUgUmVhZHktSXNzdWUgbnVyIGRpZSBUZXN0cyAocm90KSB1bmQgc3RvcHB0IHZvciBkZXIgSW1wbGVtZW50aWVydW5nLiBOdXR6ZSBkaWVzZW4gU2tpbGwgd2VubiBkZXIgTnV0emVyIC9pbXBsZW1lbnQtdGVzdCBhdWZydWZ0IG9kZXIgdGVzdGdldHJpZWJlbiB6dWVyc3QgbnVyIGRpZSByb3RlbiBUZXN0cyBzZWhlbiB3aWxsLCBiZXZvciBpbXBsZW1lbnRpZXJ0IHdpcmQuXG51c2VyLWludm9jYWJsZTogdHJ1ZVxuLS0tXG5cbiMgSW1wbGVtZW50IFRlc3RcblxuR3JhbnVsYXJlIFZhcmlhbnRlIHZvbiBTY2hyaXR0IDUgKFRlaWwgMSB2b24gMik6IFRlc3RzIGdlZ2VuIGVpbiBSZWFkeS1Jc3N1ZSBzY2hyZWliZW4sIHJvdCBsYXVmZW4gbGFzc2VuLCBzdG9wcGVuLiBGw7xyIE5ldWxpbmdlLCBkaWUgZGVuIFJvdOKGkkdyw7xuLcOcYmVyZ2FuZyBiZXd1c3N0IHNlaGVuIHdvbGxlbiwgc3RhdHQgVGVzdCB1bmQgSW1wbGVtZW50aWVydW5nIGluIGVpbmVtIFJ1dHNjaCB3aWUgYmVpIGAvaW1wbGVtZW50LXJlYWR5YC5cblxuIyMgVm9yYmVkaW5ndW5nXG5cbiMjIyAwLiBMw6R1ZnQgYmVyZWl0cyBlaW4gSXNzdWU/XG5cbmBgYGJhc2hcbm5vZGUgLmNsYXVkZS9raXQvYm9hcmQubWpzIGlzc3VlIGxpc3QgLS1zdGF0dXMgaW5fcHJvZ3Jlc3NcbmBgYFxuXG5TdGVodCBkb3J0IGJlcmVpdHMgZWluIElzc3VlOiBzdG9wcGVuLlxuXG4+IFwiSXNzdWUgI04gbGllZ3QgYmVyZWl0cyBpbiBJbiBwcm9ncmVzcyAoVGVzdHMgdmVybXV0bGljaCBzY2hvbiBnZXNjaHJpZWJlbikuIEVyc3QgYC9pbXBsZW1lbnQtZG9uZWAgZGFmw7xyIGxhdWZlbiBsYXNzZW4sIGJldm9yIGVpbiBuZXVlcyBJc3N1ZSBzdGFydGV0LlwiXG5cbktlaW4gendlaXRlcyBJc3N1ZSBwYXJhbGxlbCBhbmZhc3NlbiDigJQgZWluIElzc3VlIGluIEFyYmVpdCB6dXIgWmVpdC5cblxuIyMgQWJsYXVmXG5cbiMjIyAxLiBSZWFkeS1Jc3N1ZXMgbGFkZW5cblxuYGBgYmFzaFxubm9kZSAuY2xhdWRlL2tpdC9ib2FyZC5tanMgaXNzdWUgbGlzdCAtLXN0YXR1cyByZWFkeVxuYGBgXG5cbklzc3VlIG1pdCBkZXIgbmllZHJpZ3N0ZW4gSUQgbmVobWVuLiBEaWVzZSBBdXN3YWhsIGlzdCB2ZXJiaW5kbGljaCwga2VpbiBSYXRlbiwgd2VsY2hlcyBJc3N1ZSBzaW5udm9sbGVyIHfDpHJlLlxuXG4jIyMgMi4gSXNzdWUgbmFjaCBJbiBwcm9ncmVzcyB2ZXJzY2hpZWJlblxuXG5gYGBiYXNoXG5ub2RlIC5jbGF1ZGUva2l0L2JvYXJkLm1qcyBpc3N1ZSBtb3ZlIDxpZD4gaW5fcHJvZ3Jlc3NcbmBgYFxuXG4jIyMgMy4gSXNzdWUgdm9sbHN0w6RuZGlnIGxlc2VuXG5cbkxpZXMgYWxsZSB2aWVyIEFic2Nobml0dGUuIERpZSBUZXN0cyBlbnRzdGVoZW4gZ2VnZW4gZGFzIElzc3VlLCBuaWNodCBnZWdlbiBkZW4gQ2hhdC5cblxuIyMjIDQuIE51ciBkaWUgVGVzdHMgc2NocmVpYmVuXG5cbi0gVGVzdGRhdGVpKGVuKSBnZWdlbiBkYXMgQWt6ZXB0YW56a3JpdGVyaXVtIHNjaHJlaWJlbiDigJQgc28sIGRhc3Mgc2llIGJlaW0gamV0emlnZW4gU3RhbmQgZGVzIENvZGVzIGZlaGxzY2hsYWdlbiAocm90KS5cbi0gS2VpbmUgUHJvZHVrdGlvbnNsb2dpay4gS2VpbiBTdHViLCBrZWluZSBNb2NrLUltcGxlbWVudGllcnVuZywgZGllIGRlbiBUZXN0IHNjaG9uIGdyw7xuIG1hY2h0LlxuLSBCZXN0ZWhlbmRlIFRlc3QtTXVzdGVyIHVuZCAtSGVsZmVyIGRlcyBQcm9qZWt0cyB3aWVkZXJ2ZXJ3ZW5kZW4uXG5cbiMjIyA1LiBLZWluIENvbW1pdFxuXG5EaWUgcm90ZW4gVGVzdHMgYmxlaWJlbiB1bnN0YWdlZCBpbSBXb3JraW5nIFRyZWUuIERhcyBpc3QgZGVyIFN0b3BwLVB1bmt0IOKAlCBkZXIgbsOkY2hzdGUgU2Nocml0dCAoYC9pbXBsZW1lbnQtZG9uZWApIGNvbW1pdHRldCBUZXN0cyB1bmQgSW1wbGVtZW50aWVydW5nIGdlbWVpbnNhbS5cblxuIyMjIDYuIEFic2NobHVzcy1BdXNnYWJlXG5cbkxpc3RlIGRpZSBnZXNjaHJpZWJlbmVuIFRlc3RkYXRlaWVuIGFscyBhbmtsaWNrYmFyZSBNYXJrZG93bi1MaW5rcywgZGFtaXQgc2llIHNpY2ggZGlyZWt0IGluIGRlciBJREUgw7ZmZm5lbiBsYXNzZW46XG5cbmBgYFxuIyMjIFRlc3RzIGdlc2NocmllYmVuIChyb3QpIOKAlCBJc3N1ZSAjTlxuXG4tIFtEYXRlaVRlc3QuamF2YV0ocGZhZC96dXIvRGF0ZWlUZXN0LmphdmE6MSlcbi0gW0Fub3RoZXJUZXN0LmphdmFdKHBmYWQvenVyL0Fub3RoZXJUZXN0LmphdmE6MSlcblxuVGVzdHMgc3RlaGVuIHJvdC4gV2VpdGVyIG1pdCAvaW1wbGVtZW50LWRvbmUuXG5gYGBcblxuIyMgU3RvcC1QdW5rdGVcblxuLSBLZWluIFByb2R1a3Rpb25zY29kZTogZGllc2VyIFNraWxsIHNjaHJlaWJ0IGF1c3NjaGxpZcOfbGljaCBUZXN0cy5cbi0gS2VpbiBDb21taXQ6IGRlciBlbnRzdGVodCBlcnN0IGluIGAvaW1wbGVtZW50LWRvbmVgLlxuLSBLZWluIHp3ZWl0ZXMgSXNzdWUgcGFyYWxsZWwgc3RhcnRlbiwgc29sYW5nZSBlaW5zIGluIEluIHByb2dyZXNzIGxpZWd0LlxuLSBQdXNoZW4sIEJhY2tsb2cgbmFjaCBSZWFkeSB6aWVoZW4sIElzc3VlcyBhdWYgRG9uZSBzZXR6ZW46IHdpZSBiZWkgYC9pbXBsZW1lbnQtcmVhZHlgIG5pZSBlaWdlbm3DpGNodGlnLlxuIn0sImlzc3VlcyI6eyJTS0lMTC5tZCI6Ii0tLVxubmFtZTogaXNzdWVzXG5kZXNjcmlwdGlvbjogU2Nocml0dCAzIGRlcyA5LVNjaHJpdHQtUHJvemVzc2VzIOKAlCDDvGJlcmbDvGhydCBlaW5lbiBmcmVpZ2VnZWJlbmVuIFBsYW4gaW4ga2xlaW50ZWlsaWdlIEdpdEh1Yi1Jc3N1ZXMgaW0gVmllci1BYnNjaG5pdHQtRm9ybWF0LiBOdXR6ZSBkaWVzZW4gU2tpbGwgd2VubiBkZXIgTnV0emVyIC9pc3N1ZXMgYXVmcnVmdCwgSXNzdWVzIGF1cyBlaW5lbSBQbGFuIGVyc3RlbGxlbiB3aWxsIG9kZXIgU2Nocml0dCAzIGRlcyBQcm96ZXNzZXMgc3RhcnRldC5cbnVzZXItaW52b2NhYmxlOiB0cnVlXG4tLS1cblxuIyBJc3N1ZXNcblxuU2Nocml0dCAzIGRlcyA5LVNjaHJpdHQtUHJvemVzc2VzOiBEZXIgZnJlaWdlZ2ViZW5lIFBsYW4gd2lyZCBpbiBlaW4gb2RlciBtZWhyZXJlIElzc3VlcyDDvGJlcmbDvGhydC4gRGFzIElzc3VlIGlzdCBhYiBqZXR6dCBkaWUgUXVlbGxlIGRlciBXYWhyaGVpdCwgbmljaHQgZGVyIENoYXQuXG5cbiMjIEFibGF1ZlxuXG4jIyMgMS4gUGxhbiBwcsO8ZmVuXG5cblByw7xmZSwgb2IgZWluIGluICoqZGllc2VyIFNlc3Npb24qKiBmcmVpZ2VnZWJlbmVyIFBsYW4gZXhpc3RpZXJ0LiBXZW5uIG5laW46ICoqU1RPUFAg4oCUIGtlaW5lIElzc3VlcyBhbmxlZ2VuLioqIFZlcndlaXNlIGRhcmF1ZiwgZGFzcyBlcnN0IGAvcGxhbmAgbGF1ZmVuIHVuZCBmcmVpZ2VnZWJlbiB3ZXJkZW4gbXVzcy4gRWluZSBJZGVlbi0vVXNlLUNhc2UtTGlzdGUgaW0gQ2hhdCBpc3QgKiprZWluKiogZnJlaWdlZ2ViZW5lciBQbGFuLlxuXG4jIyMgMi4gSXNzdWVzIHNjaG5laWRlblxuXG5FaW4gSXNzdWUgPSBlaW4gbG9naXNjaGVyIFNjaHJpdHQsIGRlciBlaWdlbnN0w6RuZGlnIGdldGVzdGV0IHdlcmRlbiBrYW5uLiBLcml0ZXJpZW46XG4tIEVpbiBJc3N1ZSBsw7ZzdCBnZW5hdSBlaW5lIFNhY2hlXG4tIEVzIGthbm4gaXNvbGllcnQgY29tbWl0dGVkIHVuZCByZXZpZXdlZCB3ZXJkZW5cbi0gRXMgaGF0IG1lc3NiYXJlIEFremVwdGFuemtyaXRlcmllblxuLSBBYmjDpG5naWdrZWl0ZW4genUgYW5kZXJlbiBJc3N1ZXMgc2luZCBleHBsaXppdFxuXG5XZW5uIGVpbiBTY2hyaXR0IHNpY2ggbmljaHQgaW4gZWluZW0gw7xiZXJzY2hhdWJhcmVuIEF1ZndhbmQgZXJsZWRpZ2VuIGzDpHNzdCwgaW4gU3ViLUlzc3VlcyBzY2huZWlkZW4uXG5cblBvcnRhYmlsaXRhZXRzLUtvbnZlbnRpb246IFdlbm4gZWluZSBEYXRlaSBvZGVyIGVpbiBBcnRlZmFrdCBhbHMgZWlnZW5zdGFlbmRpZyBwb3J0YWJlbCBnZWRhY2h0IGlzdCAoSW5zdGFsbGVyLCBTaW5nbGUtRmlsZS1Ub29sLCBrb3BpZXJiYXJlcyBTY3JpcHQpLCBtdXNzIGRhcyBBa3plcHRhbnprcml0ZXJpdW0gZXhwbGl6aXQgZW50aGFsdGVuOiBcImxhdWZmYWVoaWcgb2huZSB3ZWl0ZXJlbiBSZXBvLUtvbnRleHRcIi4gT2huZSBkaWVzZW4gUHJ1ZWZmYWxsIGJsZWlidCBkaWUgUG9ydGFiaWxpdGFldCB1bmdldGVzdGV0LlxuXG4jIyMgMy4gSXNzdWVzIGltIFZpZXItQWJzY2huaXR0LUZvcm1hdCBhbmxlZ2VuXG5cbkplZGVzIElzc3VlIGJla29tbXQgdmllciBBYnNjaG5pdHRlOlxuXG5gYGBcbiMjIEtvbnRleHRcbldhcnVtIHdpcmQgZGllc2UgQXVmZ2FiZSBnZW1hY2h0PyBXYXMgZmVobHQgdm9yaGVyLCB3ZWxjaGUgVm9yZ2VzY2hpY2h0ZSBnZWjDtnJ0IGRhenU/XG5cbiMjIEF1ZmdhYmVcbldhcyBrb25rcmV0IGlzdCB6dSB0dW4/IEJldHJvZmZlbmUgRGF0ZWllbiwgenUgc2NocmVpYmVuZGUgVGVzdHMgKGJlaSBUREQgenVlcnN0KSwga29ua3JldGUgw4RuZGVydW5nZW4uXG5cbiMjIEFremVwdGFuemtyaXRlcml1bVxuV2llIHdpcmQgdmVyaWZpemllcnQsIGRhc3MgZGllIEF1ZmdhYmUgZXJsZWRpZ3QgaXN0PyBLb25rcmV0LCBtZXNzYmFyIG9kZXIgYXVzZsO8aHJiYXIuXG5cbiMjIEFiaMOkbmdpZ2tlaXRlblxuV2VsY2hlIGFuZGVyZW4gSXNzdWVzIG3DvHNzZW4genVlcnN0IGZlcnRpZyBzZWluPyBPZGVyOiBcIktlaW5lLlwiXG5gYGBcblxuSXNzdWUgYW5sZWdlbiB1ZWJlciBkZW4gQm9hcmQtQWRhcHRlcjpcblxuYGBgYmFzaFxubm9kZSAuY2xhdWRlL2tpdC9ib2FyZC5tanMgaXNzdWUgY3JlYXRlIC0tdGl0bGUgXCJUaXRlbFwiIC0tYm9keSBcIi4uLlwiXG5gYGBcblxuRGVyIEFkYXB0ZXIgbGVndCBkYXMgSXNzdWUgYW4sIGhhZW5ndCBlcyBhbnMgQm9hcmQgdW5kIHNldHp0IGRlbiBTdGF0dXMgYXVmIEJhY2tsb2cg4oCUIHByb3ZpZGVyLXVuYWJoYWVuZ2lnLlxuXG5TdGF0dXMgYmxlaWJ0ICoqQmFja2xvZyoqLiBEaWUgQmV3ZWd1bmcgbmFjaCBSZWFkeSBpc3QgZGFzIG1lbnNjaGxpY2hlIEdPIChTY2hyaXR0IDQpIOKAlCBDbGF1ZGUgemllaHQgSXNzdWVzIG5pZSBlaWdlbm1hZWNodGlnIG5hY2ggUmVhZHkuXG5cbiMjIyA0LiBBYnNjaGx1c3NcblxuTGlzdGUgYWxsZSBhbmdlbGVndGVuIElzc3VlcyBtaXQgTnVtbWVybiB1bmQgVGl0ZWxuLlxuXG5FcmfDpG56ZSBlaW5lIFRhYmVsbGUgbWl0IGVpbmVyIE1vZGVsbC1FbXBmZWhsdW5nIHBybyBJc3N1ZS4gU2llIGhpbGZ0IGRlbSBNZW5zY2hlbiwgdm9yIGRlbSBHTyB6dSBlbnRzY2hlaWRlbiwgbWl0IHdlbGNoZW0gTW9kZWxsIGplZGVzIElzc3VlIHVtZ2VzZXR6dCB3aXJkIOKAlCBvaG5lIGRlbiBQbGFuLUtvbnRleHQgbm9jaCBlaW5tYWwgenUgbGVzZW4uXG5cbnwgSXNzdWUgfCBFbXBmZWhsdW5nIHwgQmVncsO8bmR1bmcgfFxufC0tLS0tLS18LS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLXxcbnwgI04gfCA8TW9kZWxsPiB8IDxlaW4gU2F0ej4gfFxuXG5IZXVyaXN0aWsgZsO8ciBkaWUgRW1wZmVobHVuZzpcbi0gKipTY2huZWxsZXJlcyBTdGFuZGFyZC1Nb2RlbGwqKiBmw7xyIG1lY2hhbmlzY2hlLCBrbGFyIHNwZXppZml6aWVydGUgQXVmZ2FiZW46IGVpbiBFbnVtIGVyd2VpdGVybiwgVHlwZW4gbmFjaHppZWhlbiwgUmVzdHlsaW5nIG5hY2ggVm9ybGFnZSwgZWluZSDDhG5kZXJ1bmcgbmFjaCBiZXN0ZWhlbmRlbSBNdXN0ZXIuXG4tICoqU3TDpHJrc3RlcyB2ZXJmw7xnYmFyZXMgTW9kZWxsKiogZsO8ciBBdWZnYWJlbiBtaXQgQXJjaGl0ZWt0dXItLCBTaWNoZXJoZWl0cy0gb2RlciBrb21wbGV4ZXIgSW50ZXJha3Rpb25zbG9naWs6IE9BdXRoLUZsb3dzLCBuZXVlIEtvbXBvbmVudGVuIG1pdCB2aWVsIFp1c3RhbmQsIE5lYmVubMOkdWZpZ2tlaXQsIERhdGVubWlncmF0aW9uZW4uXG5cbkhhbHRlIGRpZSBNb2RlbGxuYW1lbiBnZW5lcmlzY2ggKFwiU3RhbmRhcmQtTW9kZWxsXCIgLyBcInN0w6Rya3N0ZXMgdmVyZsO8Z2JhcmVzIE1vZGVsbFwiKSB1bmQgbmVubmUgZGFzIGFrdHVlbGwgcGFzc2VuZGUgTW9kZWxsIG51ciBhbHMgQmVpc3BpZWwsIGRhbWl0IGRlciBTa2lsbCBiZWkgamVkZW0gTW9kZWxsLVJlbGVhc2UgYWt0dWVsbCBibGVpYnQuIERpZSBCZWdyw7xuZHVuZyBibGVpYnQgYmVpIGVpbmVtIFNhdHogcHJvIElzc3VlLlxuXG5TY2hyZWliZSBkYXJ1bnRlcjpcbj4gXCJBbGxlIElzc3VlcyBsaWVnZW4gaW4gQmFja2xvZy4gWmllaCBkaWUgSXNzdWVzIGRpZSBkdSB1bXNldHplbiB3aWxsc3QgbmFjaCBSZWFkeSDigJQgZGFzIGlzdCBkZWluIEdPLlwiXG5cbiMjIFN0b3AtUHVua3RcblxuRGllc2VyIFNraWxsIGVuZGV0IG5hY2ggZGVtIEFubGVnZW4gZGVyIElzc3Vlcy4gS2VpbiBDb2RlLCBrZWluIENvbW1pdC4gRGFzIEdPIChSZWFkeS1CZXdlZ3VuZykgbWFjaHQgZGVyIE1lbnNjaC5cbiJ9LCJrb250ZXh0Ijp7IlNLSUxMLm1kIjoiLS0tXG5uYW1lOiBrb250ZXh0XG5kZXNjcmlwdGlvbjogU2Nocml0dCAwIGRlcyA5LVNjaHJpdHQtUHJvemVzc2VzIOKAlCBsw6RkdCBkZW4gTWVtb3J5LVZhdWx0IHVuZCBnaWJ0IGVpbmVuIGt1cnplbiBTZXNzaW9uLVN0YXJ0LVN0YW5kLiBOdXR6ZSBkaWVzZW4gU2tpbGwgd2VubiBkZXIgTnV0emVyIC9rb250ZXh0IGF1ZnJ1ZnQgb2RlciBkaWUgU2Vzc2lvbiBtaXQgZGVtIFByb2pla3RzdGFuZCBzdGFydGVuIHdpbGwuXG51c2VyLWludm9jYWJsZTogdHJ1ZVxuLS0tXG5cbiMgS29udGV4dFxuXG5TY2hyaXR0IDA6IFNlc3Npb24tU3RhcnQuIFZhdWx0IGxhZGVuLCBQcm9qZWt0c3RhbmQgaG9sZW4sIGt1cnplbiDDnGJlcmJsaWNrIGdlYmVuLlxuXG4jIyBWb3JiZWRpbmd1bmc6IENvbmZpZy1Nb2R1cyBiZXN0aW1tZW5cblxuU3VjaGUgZGllIENvbmZpZyBpbiBkaWVzZXIgUmVpaGVuZm9sZ2UgKGVyc3RlcyBnZWZ1bmRlbmVzIGdld2lubnQpOlxuMS4gYC5jbGF1ZGUva29udGV4dC5jb25maWcuanNvbmAgaW0gYWt0dWVsbGVuIFByb2pla3R2ZXJ6ZWljaG5pc1xuMi4gYH4vLmNsYXVkZS9rb250ZXh0LmNvbmZpZy5qc29uYCAoZ2xvYmFsKVxuXG5EYXJhdXMgZXJnaWJ0IHNpY2ggZWluZXIgdm9uIGRyZWkgTW9kaTpcblxuKipNb2R1cyBBIChWb2xsbW9kdXMpOioqIENvbmZpZyBnZWZ1bmRlbiB1bmQgYHZhdWx0YC1GZWxkIGdlc2V0enQuIE5vcm1hbGVyIEFibGF1ZiBtaXQgVmF1bHQsIFByb2pla3Rub3RpeiwgYWx3YXlzLURhdGVpZW4uXG5cbioqTW9kdXMgQiAoRGVncmFkZWQgTW9kZSk6KiogQ29uZmlnIGdlZnVuZGVuIGFiZXIga2VpbiBgdmF1bHRgLUZlbGQsIG9kZXIga2VpbmUgQ29uZmlnIGdlZnVuZGVuLiBWYXVsdC1TY2hyaXR0ZSDDvGJlcnNwcmluZ2VuLiBOdXIgb2ZmZW5lIElzc3VlcyB1bmQgcHJvamVjdERvY3MgbGFkZW4uIEFtIEVuZGUgSGlud2VpcyBhdXNnZWJlbjogXCJLZWluIFZhdWx0IGtvbmZpZ3VyaWVydCwgYXJiZWl0ZSBvaG5lIHBlcnNpc3RlbnRlcyBNZW1vcnkuXCJcblxuS2VpbiBoYXJ0ZXIgQWJicnVjaC4gQmVpZGUgTW9kaSBsaWVmZXJuIHNpbm52b2xsZW4gT3V0cHV0LlxuXG4jIyBBYmxhdWZcblxuIyMjIDEuIENvbmZpZyBsZXNlblxuXG5GZWxkZXIgYXVzIGBrb250ZXh0LmNvbmZpZy5qc29uYCAoYWxsZSBvcHRpb25hbCk6XG4tIGB2YXVsdGA6IGFic29sdXRlciBQZmFkIHp1bSBNZW1vcnktVmF1bHRcbi0gYGFsd2F5c2A6IEFycmF5IHZvbiBEYXRlaXBmYWRlbiByZWxhdGl2IHp1bSBgdmF1bHRgLVJvb3QgKGltbWVyIGxlc2VuKVxuLSBgcHJvamVjdERvY3NgOiBBcnJheSB2b24gUGZhZGVuIG9kZXIgR2xvYi1NdXN0ZXJuIHJlbGF0aXYgenVtIFByb2pla3R2ZXJ6ZWljaG5pcy4gRmFsbGJhY2sgd2VubiBuaWNodCBnZXNldHp0OiBgW1wiQ0xBVURFLSpcIiwgXCIuY2xhdWRlL0NMQVVERS0qXCJdYFxuXG4jIyMgMi4gVmF1bHQtRGF0ZWllbiBsZXNlbiAobnVyIE1vZHVzIEEpXG5cbkxpZXMgYWxsZSBEYXRlaWVuIGF1cyBgYWx3YXlzYCByZWxhdGl2IHp1bSBgdmF1bHRgLVBmYWQuIFR5cGlzY2g6IGBJbmRleC5tZGAgKFN0cnVrdHVyICsgYWt0aXZlIFByb2pla3RlKSB1bmQgYFByb2ZpbC5tZGAgKE51dHplcnByb2ZpbCkuXG5cbiMjIyAzLiBQcm9qZWt0bm90aXogYXV0by1kZXRla3RpZXJlbiAobnVyIE1vZHVzIEEpXG5cbmBgYGJhc2hcbmdpdCByZW1vdGUgZ2V0LXVybCBvcmlnaW5cbmBgYFxuXG5FeHRyYWhpZXJlIGRlbiBSZXBvLU5hbWVuIChsZXR6dGVzIFNlZ21lbnQgb2huZSBgLmdpdGApIOKGkiBge25hbWV9YC4gU3VjaGUgYHt2YXVsdH0vUHJvamVrdGUve25hbWV9L3tuYW1lfS5tZGAuIFdlbm4gZ2VmdW5kZW46IGxlc2VuLlxuXG5XZW5uIGtlaW4gUmVwbyBvZGVyIGtlaW4gTWF0Y2g6IG51ciBkaWUgYGFsd2F5c2AtRGF0ZWllbiB6ZWlnZW4sIGtlaW5lbiBGZWhsZXIgd2VyZmVuLlxuXG4jIyMgNC4gUHJvamVrdC1zcGV6aWZpc2NoZSBEb2NzIGxlc2VuIChiZWlkZSBNb2RpKVxuXG5MaWVzIGFsbGUgRGF0ZWllbiBhdXMgYHByb2plY3REb2NzYCByZWxhdGl2IHp1bSBQcm9qZWt0dmVyemVpY2huaXMuIEVpbnRyw6RnZSBrw7ZubmVuIGtvbmtyZXRlIERhdGVpbmFtZW4gb2RlciBHbG9iLU11c3RlciBzZWluOlxuXG5gYGBiYXNoXG5maW5kIC4gLW1heGRlcHRoIDEgLW5hbWUgXCJDTEFVREUtKlwiIC10eXBlIGZcbmBgYFxuXG5GZWhsZW5kZSBEYXRlaWVuIHVuZCBNdXN0ZXIgb2huZSBUcmVmZmVyIGxlaXNlIMO8YmVyc3ByaW5nZW4gKGtlaW4gRmVobGVyKS5cblxuIyMjIDUuIE9mZmVuZSBJc3N1ZXMgaG9sZW4gKGJlaWRlIE1vZGkpXG5cbk9mZmVuZSBJc3N1ZXMgdW5kIFJlcG8tTmFtZSB1ZWJlciBkZW4gQm9hcmQtQWRhcHRlcjpcblxuYGBgYmFzaFxubm9kZSAuY2xhdWRlL2tpdC9ib2FyZC5tanMgaXNzdWUgbGlzdFxubm9kZSAuY2xhdWRlL2tpdC9ib2FyZC5tanMgY29kZSByZXBvLW5hbWVcbmBgYFxuXG5XZW5uIGRlciBBZGFwdGVyIGVpbmVuIEZlaGxlciB6dXJ1ZWNrZ2lidDogU2Nocml0dCB1ZWJlcnNwcmluZ2VuLCBrZWluIGhhcnRlciBBYmJydWNoLlxuXG4jIyMgNi4gWnVzYW1tZW5mYXNzdW5nIGF1c2dlYmVuXG5cbktvbXBha3RlciBTZXNzaW9uLVN0YXJ0LVN0YW5kOlxuXG5gYGBcbiMjIFNlc3Npb24tU3RhcnQg4oCUIHtQcm9qZWt0bmFtZX1cblxuIyMjIEFrdGl2ZSBJc3N1ZXNcbi0gI04gVGl0ZWwgW1N0YXR1c11cbi0gLi4uXG5cbiMjIyBMZXR6dGUgRW50c2NoZWlkdW5nZW4gLyBadWxldHp0IGFrdHVhbGlzaWVydFxuKGF1cyBkZXIgUHJvamVrdG5vdGl6IOKAlCBudXIgTW9kdXMgQSlcblxuIyMjIFdhcyBhbHMgbsOkY2hzdGVzIGtvbW10XG4oYXVzIGRlciBQcm9qZWt0bm90aXogb2RlciBCb2FyZC1SZWFkeS1TcGFsdGUpXG5gYGBcblxuSW0gRGVncmFkZWQgTW9kZSBhbSBFbmRlIGFuZnVlZ2VuOlxuPiBcIktlaW4gVmF1bHQga29uZmlndXJpZXJ0LCBhcmJlaXRlIG9obmUgcGVyc2lzdGVudGVzIE1lbW9yeS4gRnVlciBWb2xsbW9kdXM6IGB+Ly5jbGF1ZGUva29udGV4dC5jb25maWcuanNvbmAgYW5sZWdlbiBtaXQgdmF1bHQtUGZhZC5cIlxuXG5LZWluZSB2b2xsc3RhZW5kaWdlIFdpZWRlcmdhYmUgZGVyIFZhdWx0LUluaGFsdGUg4oCUIG51ciB3YXMgZnVlciBkZW4gc29mb3J0aWdlbiBFaW5zdGllZyByZWxldmFudCBpc3QuXG5cbiMjIFdhcyBkaWVzZXIgU2tpbGwgbmljaHQgdHV0XG5cbi0gS2VpbiBTY2hyZWliZW4gaW4gZGVuIFZhdWx0IChkYXMgaXN0IC9kb2N1bWVudClcbi0gS2VpbmUgQ29kZS3DhG5kZXJ1bmdlblxuLSBLZWluIGVpZ2VubcOkY2h0aWdlcyBTdGFydGVuIGFuZGVyZXIgU2tpbGxzXG4ifSwibG9jYWwtY2hlY2siOnsiU0tJTEwubWQiOiItLS1cbm5hbWU6IGxvY2FsLWNoZWNrXG5kZXNjcmlwdGlvbjogU2Nocml0dCA2IGRlcyA5LVNjaHJpdHQtUHJvemVzc2VzIOKAlCBmw7xocnQgZGllIFBmbGljaHQtQ2hlY2tzIGF1cyBkZXIgQ29uZmlnIGF1cyB1bmQgZ2lidCBlaW5lIGdyw7xuZSBDaGVja2xpc3QgenVyw7xjay4gTnV0emUgZGllc2VuIFNraWxsIHdlbm4gZGVyIE51dHplciAvbG9jYWwtY2hlY2sgYXVmcnVmdCBvZGVyIFNjaHJpdHQgNiAobG9rYWxlIFByw7xmdW5nKSBzdGFydGV0LlxudXNlci1pbnZvY2FibGU6IHRydWVcbi0tLVxuXG4jIExvY2FsIENoZWNrXG5cblNjaHJpdHQgNiBkZXMgOS1TY2hyaXR0LVByb3plc3NlczogQWxsZSBQZmxpY2h0LUNoZWNrcyBsYXVmZW4gbG9rYWwgZHVyY2guIE91dHB1dCBpc3QgZWluZSBncsO8bmUgKG9kZXIgZXhwbGl6aXQgcm90ZSkgQ2hlY2tsaXN0LlxuXG4jIyBWb3JiZWRpbmd1bmdcblxuTGllcyBgLmNsYXVkZS93b3JrZmxvdy5jb25maWcuanNvbmAuIFJlbGV2YW50ZSBGZWxkZXI6XG4tIGBidWlsZENoZWNrc2A6IExpc3RlIGRlciBhdXN6dWbDvGhyZW5kZW4gQnVpbGQtL1Rlc3QtS29tbWFuZG9zICh6LkIuIGBbXCJtdm4gdmVyaWZ5XCIsIFwibnBtIHJ1biBidWlsZFwiXWApXG4tIGBtdXRhdGlvbkNvbW1hbmRgOiBNdXRhdGlvbnMtVGVzdC1Lb21tYW5kbyAob3B0aW9uYWwsIHouQi4gYFwibXZuIG9yZy5waXRlc3Q6cGl0ZXN0LW1hdmVuOm11dGF0aW9uQ292ZXJhZ2VcImApXG5cbkZlaGx0IGRpZSBDb25maWc6IEbDvGhyZSBgYnVpbGRDaGVja3M6IFtdYCBhdXMgdW5kIHdlaXNlIGRhcmF1ZiBoaW4sIGRhc3Mga2VpbmUgQ2hlY2tzIGtvbmZpZ3VyaWVydCBzaW5kLlxuXG4jIyBQZmxpY2h0LUNoZWNrc1xuXG4qKkxlaXRwbGFua2U6IEVpbiBDb3ZlcmFnZS0vUXVhbGl0w6R0cy1HYXRlIGlzdCBlaW4gRmxvb3IsIGtlaW4gQmV3ZWlzIHZvbGxlciBBYmRlY2t1bmcuKiogR3LDvG4gaGVpw590IOKAnsO8YmVyIGRlciB2ZXJlaW5iYXJ0ZW4gU2Nod2VsbGVcIiwgbmljaHQg4oCedm9sbHN0w6RuZGlnIGdldGVzdGV0XCIuIEFscyBWZXJ0cmF1ZW5zc2lnbmFsIHRyw6RndCBlaW5lIE1ldHJpayBudXIsIHdlbm4gc2llIGVocmxpY2ggYmxlaWJ0OiBFaW5lIEzDvGNrZSBtdXNzIGVjaHQgdW5nZXRlc3RldGUgTG9naWsgYmVkZXV0ZW4sIG5pZSBzdGlsbHNjaHdlaWdlbmQgYXVzZ2VzY2hsb3NzZW5lcyBSYXVzY2hlbi4gTGllZ3QgZGVyIENvdmVyYWdlLVJlcG9ydCB1bnRlciBkZW0gaW0gUHJvamVrdCB2ZXJlaW5iYXJ0ZW4gWmllbCAoc2llaGUgUHJvamVrdC1HdWlkZSBiencuIGB3b3JrZmxvdy5jb25maWcuanNvbmApLCBkYXMgZXhwbGl6aXQgYWxzIFNpZ25hbCBhdXN3ZWlzZW4gc3RhdHQgZXMgc3RpbGwgZHVyY2h6dXdpbmtlbiDigJQgZGVyIE1lbnNjaCBlbnRzY2hlaWRldCwgb2IgcmVpbmdlc2NoYXV0IG9kZXIgVGVzdHMgbmFjaGdlem9nZW4gd2VyZGVuLlxuXG4jIyMgMS4gQnVpbGQtQ2hlY2tzIGF1cyBkZXIgQ29uZmlnXG5cbkbDvGhyZSBhbGxlIEtvbW1hbmRvcyBpbiBgYnVpbGRDaGVja3NgIHNlcXVlbnppZWxsIGF1czpcblxuYGBgYmFzaFxuPGtvbW1hbmRvIGF1cyBidWlsZENoZWNrc1swXT5cbjxrb21tYW5kbyBhdXMgYnVpbGRDaGVja3NbMV0+XG4uLi5cbmBgYFxuXG5CZWkgRmVobGVyOiBBdXNnYWJlIHplaWdlbiwgVXJzYWNoZSBhbmFseXNpZXJlbiwgRml4IHZvcnNjaGxhZ2VuLiBOaWNodCBzdGlsbHNjaHdlaWdlbmQgd2VpdGVybWFjaGVuLlxuXG4qKkJldm9yenVndCBpbSBWb3JkZXJncnVuZCBhdXNmw7xocmVuKiog4oCUIGRlciBFeGl0LUNvZGUgaXN0IGRhbm4gZGlyZWt0IHNpY2h0YmFyIHVuZCBlaW5kZXV0aWcgZGVtIENoZWNrIHp1enVvcmRuZW4uXG5cbldpcmQgZWluIGxhbmdlciBDaGVjayBkZW5ub2NoIGluIGRlbiBIaW50ZXJncnVuZCB2ZXJzY2hvYmVuOiBkZW4gKiplY2h0ZW4qKiBFeGl0LUNvZGUgaW4gZWluZSBEYXRlaSBzY2hyZWliZW4gdW5kIHZvbiBkb3J0IGF1c3dlcnRlbiwgc3RhdHQgZGVtIGF1dG9tYXRpc2NoIGdlbWVsZGV0ZW4gQWJzY2hsdXNzLVN0YXR1cyBkZXIgS29tbWFuZG9rZXR0ZSB6dSB2ZXJ0cmF1ZW46XG5cbmBgYGJhc2hcbjxrb21tYW5kbz4gPiBsb2cudHh0IDI+JjEgOyBlY2hvIFwiRVhJVD0kP1wiID4+IGxvZy50eHRcbmBgYFxuXG5FaW4gbmFjaGdlc3RlbGx0ZXMgYGVjaG9gIG1hc2tpZXJ0IGRlbiBFeGl0LUNvZGUsIHdlbm4gZGllIEF1c3dlcnR1bmcgbnVyIGF1ZiBkZW4gZ2VtZWxkZXRlbiBBYnNjaGx1c3MtU3RhdHVzIGRlciBnZXNhbXRlbiBLb21tYW5kb2tldHRlIHNjaGF1dCDigJQgZGVyIGlzdCBkYW5uIGltbWVyIGRlciB2b24gYGVjaG9gICgwKSwgbmljaHQgZGVyIGRlcyBlaWdlbnRsaWNoZW4gQ2hlY2tzLiBEaWUgQXVzd2VydHVuZyBtdXNzIGRlbiBpbiBkZXIgRGF0ZWkgZ2VzY2hyaWViZW5lbiBXZXJ0IGxlc2VuIChgZ3JlcCBcIl5FWElUPVwiYCksIG5pY2h0IGRlbiBTdGF0dXMgZGVyIEtvbW1hbmRva2V0dGUgc2VsYnN0LlxuXG5adXPDpHR6bGljaCB6dSB0b29sLXNwZXppZmlzY2hlbiBFcmZvbGdzbWVsZHVuZ2VuIGdlbmVyaXNjaCBhdWYgYFtFUlJPUl1gIGJ6dy4gYEJVSUxEIEZBSUxVUkVgIGltIExvZyBwcsO8ZmVuLCBuaWNodCBudXIgYXVmIGVuZ2UgU3RpY2h3b3J0ZSAoei4gQi4gbnVyIFBJVC1TdXJ2aXZvcnMgb2RlciBudXIgZGFzIFdvcnQg4oCeRkFJTFVSRVwiKSDigJQgc29uc3QgcnV0c2NoZW4gYW5kZXJlIEZlaGxlcmFydGVuICh6LiBCLiBGb3JtYXRpZXJ1bmdzLSBvZGVyIExpbnQtVmlvbGF0aW9ucykgdW5iZW1lcmt0IGR1cmNoLlxuXG4jIyMgMi4gTXV0YXRpb25zLVRlc3QgKHdlbm4ga29uZmlndXJpZXJ0KVxuXG5gYGBiYXNoXG48bXV0YXRpb25Db21tYW5kPlxuYGBgXG5cbk51ciB3ZW5uIGBtdXRhdGlvbkNvbW1hbmRgIGluIGRlciBDb25maWcgZ2VzZXR6dCBpc3QuIFdlbm4gZGVyIFRlc3QgbmljaHQgbG9rYWwgYXVzZsO8aHJiYXIgaXN0IChrZWluIEJ1aWxkLVRvb2wsIGtlaW4gRGFlbW9uKSwgZGFzIGV4cGxpeml0IHZlcm1lcmtlbi5cblxuIyMjIDMuIE1hbnVlbGxlIFVJLVZlcmlmaWthdGlvbiAoYmVpIEZyb250ZW5kLcOEbmRlcnVuZ2VuKVxuXG5XZW5uIGRpZSBsZXR6dGVuIENvbW1pdHMgRnJvbnRlbmQtRGF0ZWllbiBiZXRyZWZmZW46XG5cbj4gKipNYW51ZWxsZSBQcsO8ZnVuZyBlcmZvcmRlcmxpY2g6KiogU3RhcnRlIGRlbiBEZXYtU2VydmVyIChgPHN0YXJ0a29tbWFuZG8+YCkgdW5kIGtsaWNrZSBkdXJjaDpcbj4gLSBHb2xkZW4gUGF0aDogPEJlc2NocmVpYnVuZyBkZXMgSGF1cHRmYWxscz5cbj4gLSBFZGdlIENhc2VzOiA8QmVzY2hyZWlidW5nIGRlciBHcmVuembDpGxsZT5cbj5cbj4gTWVsZGUgZGFzIEVyZ2VibmlzLCBiZXZvciBlcyB3ZWl0ZXJnZWh0LlxuXG5EaWUgS0kga2FubiBrZWluZW4gQnJvd3NlciBiZWRpZW5lbi4gRGllc2VyIFNjaHJpdHQgYmxlaWJ0IGJlaW0gTWVuc2NoZW4uXG5cbiMjIEVyZ2VibmlzXG5cbkNoZWNrbGlzdCBpbSBGb3JtYXQ6XG5cbmBgYFxuIyMjIExva2FsZSBQcsO8ZnVuZ1xuXG4tIOKchSA8YnVpbGRDaGVja3NbMF0+IOKGkiA8RXJnZWJuaXM+XG4tIOKchSA8YnVpbGRDaGVja3NbMV0+IOKGkiA8RXJnZWJuaXM+XG4tIOKchSBNdXRhdGlvbnMtVGVzdCDihpIgPEVyZ2VibmlzPlxuLSDij7MgVUktVmVyaWZpa2F0aW9uIOKGkiBtYW51ZWxsZSBQcsO8ZnVuZyBhdXNzdGVoZW5kXG5cbkFsbGUgYXV0b21hdGlzaWVydGVuIENoZWNrcyBncsO8bi4gVUktQ2hlY2sgc3RlaHQgYXVzLlxuYGBgXG5cbldlbm4gYGJ1aWxkQ2hlY2tzYCBsZWVyIGlzdDogSGlud2VpcyBhdXNnZWJlbiBcIktlaW5lIGJ1aWxkQ2hlY2tzIGtvbmZpZ3VyaWVydC4gUGFzc2UgYC5jbGF1ZGUvd29ya2Zsb3cuY29uZmlnLmpzb25gIGFuLlwiIEtlaW4gRmVobGVyLCBrZWluIEFiYnJ1Y2guXG5cblJvdGVyIENoZWNrIChg4p2MYCkgc3RvcHB0IGRlbiBQcm96ZXNzLiBOaWNodCB3ZWl0ZXJnZWhlbiwgYmV2b3IgZGVyIEZlaGxlciBnZWtsw6RydCBpc3QuXG5cbiMjIFN0b3AtUHVua3RcblxuTmFjaCBncsO8bmVyIENoZWNrbGlzdCB3YXJ0ZXQgZGVyIFByb3plc3MgYXVmIGRlbiBTdGFydCB2b24gYC9yZXZpZXdgIChTY2hyaXR0IDcpLiBQdXNoIGVyZm9sZ3QgZXJzdCBuYWNoIGV4cGxpeml0ZXIgVHJpZ2dlci1QaHJhc2UgYHB1c2ggbWFpbmAuXG4ifSwibWVyZ2UtcHJvZHVjdGlvbiI6eyJTS0lMTC5tZCI6Ii0tLVxubmFtZTogbWVyZ2UtcHJvZHVjdGlvblxuZGVzY3JpcHRpb246IFNjaHJpdHQgOSBkZXMgOS1TY2hyaXR0LVByb3plc3NlcyDigJQgZXJzdGVsbHQgZWluZW4gUFIgdm9uIG1haW4gbmFjaCBwcm9kdWN0aW9uLiBOdXIgYXVmIGV4cGxpeml0ZSBUcmlnZ2VyLVBocmFzZSBkZXMgTWVuc2NoZW4uIE51dHplIGRpZXNlbiBTa2lsbCBOVVIgd2VubiBkZXIgTnV0emVyIGV4cGxpeml0IFwibWVyZ2UgcHJvZHVjdGlvblwiIHRpcHB0LlxudXNlci1pbnZvY2FibGU6IHRydWVcbmRpc2FibGUtbW9kZWwtaW52b2NhdGlvbjogdHJ1ZVxuLS0tXG5cbiMgTWVyZ2UgUHJvZHVjdGlvblxuXG5TY2hyaXR0IDkgZGVzIDktU2Nocml0dC1Qcm96ZXNzZXM6IEVpbmVuIFB1bGwgUmVxdWVzdCB2b24gYG1haW5CcmFuY2hgIG5hY2ggYHByb2R1Y3Rpb25CcmFuY2hgIGVyc3RlbGxlbi4gRGVyIE1lcmdlIHNlbGJzdCBpc3QgTWFubmVzIEF1ZmdhYmUuXG5cbioqRGllc2VyIFNraWxsIGRhcmYgdm9uIENsYXVkZSBuaWNodCBhdXRvbm9tIGdlem9nZW4gd2VyZGVuLioqIEVyIGzDpHVmdCBudXIgYXVmIGRpZSBleHBsaXppdGUgVHJpZ2dlci1QaHJhc2UgZGVzIE1lbnNjaGVuLlxuXG4jIyBUcmlnZ2VyLVBocmFzZVxuXG5EZXIgTWVuc2NoIHRpcHB0OiBgbWVyZ2UgcHJvZHVjdGlvbmAgKG9kZXIgZGllIGluIGAuY2xhdWRlL3dvcmtmbG93LmNvbmZpZy5qc29uYCB1bnRlciBgdHJpZ2dlcnMubWVyZ2VgIGtvbmZpZ3VyaWVydGUgUGhyYXNlKS5cblxuIyMgQWJsYXVmXG5cbiMjIyAxLiBDb25maWcgbGVzZW5cblxuTGllcyBgLmNsYXVkZS93b3JrZmxvdy5jb25maWcuanNvbmA6XG4tIGBtYWluQnJhbmNoYDogUXVlbGwtQnJhbmNoIChEZWZhdWx0OiBgbWFpbmApXG4tIGBwcm9kdWN0aW9uQnJhbmNoYDogWmllbC1CcmFuY2ggKERlZmF1bHQ6IGBwcm9kdWN0aW9uYClcblxuIyMjIDIuIENvbW1pdHMgenVzYW1tZW5mYXNzZW5cblxuYGBgYmFzaFxuZ2l0IGxvZyBvcmlnaW4vPHByb2R1Y3Rpb25CcmFuY2g+Li5vcmlnaW4vPG1haW5CcmFuY2g+IC0tb25lbGluZVxuYGBgXG5cbkRpZXNlIENvbW1pdHMga29tbWVuIGluIGRlbiBQUi1Cb2R5IGFscyDDhG5kZXJ1bmdzw7xiZXJzaWNodC5cblxuIyMjIDMuIFJlbGVhc2UtU2Nocml0dGUgKGZhbGxzIGBSRUxFQVNJTkcubWRgIGV4aXN0aWVydClcblxuUHLDvGZlLCBvYiBpbSBSZXBvLVJvb3QgZWluZSBgUkVMRUFTSU5HLm1kYCBsaWVndC5cbi0gKipKYToqKiBGw7xocmUgZGllIGRvcnQgdW50ZXIgZGVtIE1lcmdlLVRyaWdnZXIgKGBtZXJnZSBwcm9kdWN0aW9uYCkgYmVzY2hyaWViZW5lblxuICBSZWxlYXNlLVNjaHJpdHRlIGF1cyDigJQgdHlwaXNjaGVyd2Vpc2UgZWluIFZlcnNpb24tQnVtcCwgb3B0aW9uYWwgZXJnw6RuenQgdW0gZWluZVxuICBDaGFuZ2Vsb2ctR2VuZXJpZXJ1bmcgdW5kIGVpbmVuIGxva2FsZW4gR2l0LVRhZy4gQ29tbWl0dGUgZGllIGdlw6RuZGVydGVuIERhdGVpZW5cbiAgYXVmIGBtYWluQnJhbmNoYCwgZGFtaXQgc2llIGltIFBSIG5hY2ggYHByb2R1Y3Rpb25gIGVudGhhbHRlbiBzaW5kLlxuLSAqKk5laW46KiogTmljaHRzIHdlaXRlciB0dW4uXG5cbkRlciBTa2lsbCBzZWxic3Qga2VubnQga2VpbmUgcHJvamVrdHNwZXppZmlzY2hlIFZlcnNpb25zLSwgQ2hhbmdlbG9nLSBvZGVyXG5UYWctTG9naWs7IGRpZXNlIGxlYnQgYXVzc2NobGllw59saWNoIGluIGRlciBgUkVMRUFTSU5HLm1kYCBkZXMgamV3ZWlsaWdlbiBSZXBvcy5cblxuIyMjIDQuIFRhZyhzKSBtaXRwdXNoZW4gKGZhbGxzIGR1cmNoIFNjaHJpdHQgMyBlaW4gVGFnIGVudHN0YW5kZW4gaXN0KVxuXG5gYGBiYXNoXG5naXQgcHVzaCBvcmlnaW4gPHRhZz5cbmBgYFxuXG5CZWkgbWVocmVyZW4gbmV1ZW4gVGFnczogYGdpdCBwdXNoIG9yaWdpbiAtLXRhZ3NgLiBIYXQgYFJFTEVBU0lORy5tZGAga2VpbmVuIFRhZ1xuZXJ6ZXVndCAob2RlciBleGlzdGllcnQga2VpbmUgYFJFTEVBU0lORy5tZGApOiBTY2hyaXR0IMO8YmVyc3ByaW5nZW4uXG5cbkRlciBUYWcgemVpZ3QgYXVmIGRlbiBSZWxlYXNlLUNvbW1pdCBhdXMgU2Nocml0dCAzIGF1ZiBgbWFpbkJyYW5jaGAg4oCUIG5pY2h0IGF1ZlxuYHByb2R1Y3Rpb25gLiBLZWluIEZvcmNlLVB1c2gsIGtlaW4gw5xiZXJzY2hyZWliZW4gYmVzdGVoZW5kZXIgVGFncy5cblxuIyMjIDUuIFBSIGJ6dy4gTVIgZXJzdGVsbGVuXG5cbmBgYGJhc2hcbm5vZGUgLmNsYXVkZS9raXQvYm9hcmQubWpzIGNvZGUgcHIgXFxcbiAgLS1mcm9tIDxtYWluQnJhbmNoPiBcXFxuICAtLXRvIDxwcm9kdWN0aW9uQnJhbmNoPiBcXFxuICAtLXRpdGxlIFwiUmVsZWFzZTogPG1haW5CcmFuY2g+IC0+IDxwcm9kdWN0aW9uQnJhbmNoPiAoPERBVFVNPilcIlxuYGBgXG5cbkRlciBBZGFwdGVyIGVyc3RlbGx0IGRlbiBQUi9NUiBwcm92aWRlci11bmFiaGFlbmdpZy4gQmVpIGBjb2RlSG9zdDogbG9jYWxgIGdpYnQgZXIgZWluZW4gZ2VmdWVocnRlbiBNZXJnZS1EaWFsb2cgYXVzLlxuXG4jIyMgNi4gR2l0SHViIFJlbGVhc2UgZXJzdGVsbGVuIChudXIgd2VubiBgY29kZUhvc3Q6IGdpdGh1YmAgdW5kIFNjaHJpdHQgNCBlaW5lbiBUYWcgZ2VwdXNodCBoYXQpXG5cbmBgYGJhc2hcbmdoIHJlbGVhc2UgY3JlYXRlIDx0YWc+IC0tdGl0bGUgPHRhZz4gLS1ub3Rlcy1maWxlIDxwZmFkLXp1bS1jaGFuZ2Vsb2ctYWJzY2huaXR0PlxuYGBgXG5cbkRlciBOb3Rlcy1Cb2R5IGlzdCBkZXIgbmV1ZSBBYnNjaG5pdHQgYXVzIGBDSEFOR0VMT0cubWRgIChmYWxscyBkaWVcbmBSRUxFQVNJTkcubWRgLVNjaHJpdHRlIGVpbmVuIGVyemV1Z3QgaGFiZW4pOyBvaG5lIENoYW5nZWxvZy1EYXRlaSBkaWVcbkNvbW1pdC1MaXN0ZSBhdXMgU2Nocml0dCAyIGFscyBOb3RlcyB2ZXJ3ZW5kZW4uXG5cbkJlaSBgY29kZUhvc3RgIHVuZ2xlaWNoIGBnaXRodWJgICh6LiBCLiBgZ2l0bGFiYCwgYGxvY2FsYCkgb2RlciB3ZW5uIGtlaW4gVGFnXG5leGlzdGllcnQ6IFNjaHJpdHQgw7xiZXJzcHJpbmdlbiB1bmQgaW0gQWJzY2hsdXNzYmVyaWNodCB2ZXJtZXJrZW4sIG5pY2h0XG5zdGlsbHNjaHdlaWdlbmQgYXVzbGFzc2VuLlxuXG4jIyMgNy4gUFIvTVItVVJMIHp1csO8Y2tnZWJlblxuXG5HaWIgZGllIFVSTCBhdXMgZGVtIEFkYXB0ZXItT3V0cHV0IGF1cy4gRGVyIE1lcmdlIGlzdCBNYW5uZXMgQXVmZ2FiZSDigJQgQ2xhdWRlIG1lcmdlZCBuaWNodC5cblxuPiBcIlBSL01SIGVyc3RlbGx0OiA8VVJMPi4gRGVyIE1lcmdlIG5hY2ggcHJvZHVjdGlvbiBsaWVndCBiZWkgZGlyLlwiXG5cbiMjIFdhcyBkaWVzZXIgU2tpbGwgbmljaHQgdHV0XG5cbi0gS2VpbiBkaXJla3RlciBQdXNoIGF1ZiBgcHJvZHVjdGlvbmBcbi0gS2VpbiBNZXJnZSBkZXMgUFIg4oCUIGRhcyBtYWNodCBkZXIgTWVuc2NoXG4tIEtlaW4gYXV0b21hdGlzY2hlciBQUiBuYWNoIFB1c2ggb2RlciBuYWNoIGdyw7xuZW0gUmV2aWV3XG4tIEtlaW4gRm9yY2UtTWVyZ2Ugb2RlciBCeXBhc3Mgdm9uIEJyYW5jaC1Qcm90ZWN0aW9uLVJlZ2VsblxuLSBLZWluIEZvcmNlLVB1c2ggdm9uIFRhZ3MsIGtlaW4gw5xiZXJzY2hyZWliZW4gYmVzdGVoZW5kZXIgVGFnc1xuIn0sInBsYW4iOnsiU0tJTEwubWQiOiItLS1cbm5hbWU6IHBsYW5cbmRlc2NyaXB0aW9uOiBTY2hyaXR0IDIgZGVzIDktU2Nocml0dC1Qcm96ZXNzZXMg4oCUIGVyc3RlbGx0IGVpbmVuIEltcGxlbWVudGllcnVuZ3NwbGFuLCBzdGVsbHQgaWhuIHp1ciBEaXNrdXNzaW9uIHVuZCBpbXBsZW1lbnRpZXJ0IG5pY2h0cy4gTnV0emUgZGllc2VuIFNraWxsIHdlbm4gZGVyIE51dHplciAvcGxhbiBhdWZydWZ0LCBlaW5lbiBQbGFuIGVyc3RlbGxlbiB3aWxsIG9kZXIgU2Nocml0dCAyIGRlcyBQcm96ZXNzZXMgc3RhcnRldC5cbnVzZXItaW52b2NhYmxlOiB0cnVlXG4tLS1cblxuIyBQbGFuXG5cblNjaHJpdHQgMiBkZXMgOS1TY2hyaXR0LVByb3plc3NlczogRGllIEtJIGVyc3RlbGx0IGVpbmVuIFBsYW4uIERlciBQbGFuIHdpcmQgenVyIERpc2t1c3Npb24gZ2VzdGVsbHQsIG5pY2h0IHp1ciBJbXBsZW1lbnRpZXJ1bmcuXG5cbiMjIEFibGF1ZlxuXG4jIyMgMC4gQmFobiBiZXN0aW1tZW5cblxuSXN0IGRpZSBBbmZvcmRlcnVuZyBCYWhuIDEgKGtsZWluZSDDhG5kZXJ1bmcgbmFjaCBkZXIgRGVmaW5pdGlvbiBpbiBDTEFVREUtd29ya2Zsb3cubWQpLCBzYWcgZGFzIHVuZCBiaWV0ZSBhbiwgc2llICoqZGlyZWt0KiogdW16dXNldHplbiBzdGF0dCB6dSBwbGFuZW4g4oCUIGtlaW4gUGxhbi1PdmVyaGVhZC4gTnVyIGJlaSBCYWhuIDIgZGVuIHZvbGxlbiBQbGFuIGVyc3RlbGxlbi5cblxuIyMjIDEuIEFuZm9yZGVydW5nIHZlcnN0ZWhlblxuXG5LbMOkcmUgenVlcnN0OlxuLSBXYXMgc29sbCBnZWJhdXQgd2VyZGVuPyAoV2FzIGZlaGx0IGRpciBub2NoLCB1bSBkYXMgc2ljaGVyIHp1IHNhZ2VuPylcbi0gV2VsY2hlIEJlcmVpY2hlIGRlcyBDb2RlcyBzaW5kIGJldHJvZmZlbj9cbi0gR2lidCBlcyBBYmjDpG5naWdrZWl0ZW4genUgYW5kZXJlbiBJc3N1ZXMgb2RlciBsYXVmZW5kZW4gQXJiZWl0ZW4/XG5cbkZyYWdlIG5hY2gsIHdlbm4gZXR3YXMgdW5rbGFyIGlzdC4gUmF0ZW4gaXN0IGtlaW4gRXJzYXR6IGbDvHIgZWluZSBrdXJ6ZSBSw7xja2ZyYWdlLlxuXG4jIyMgMi4gUmVsZXZhbnRlIERhdGVpZW4gbGVzZW5cblxuTGllcyBkaWUgYmV0cm9mZmVuZW4gRGF0ZWllbiB1bmQgdm9yaGFuZGVuZSBNdXN0ZXIuIE51dHplIGVpbmVuIEV4cGxvcmUtQWdlbnRlbiwgd2VubiBkZXIgU2NvcGUgdW5rbGFyIGlzdC4gU3VjaGUgYWt0aXYgbmFjaCB3aWVkZXJ2ZXJ3ZW5kYmFyZW4gRnVua3Rpb25lbiB1bmQgTXVzdGVybiDigJQgdmVybWVpZGUgbmV1ZW4gQ29kZSwgd2VubiBlaW5lIHBhc3NlbmRlIEltcGxlbWVudGllcnVuZyBiZXJlaXRzIGV4aXN0aWVydC5cblxuIyMjIDMuIFBsYW4gZXJzdGVsbGVuXG5cbkRlciBQbGFuIGJlbmVubnQ6XG4tICoqWmllbCoqIHVuZCBOdXR6ZXJ3aXJrdW5nXG4tICoqQmV0cm9mZmVuZSBCZXJlaWNoZSoqIChEYXRlaWVuLCBNb2R1bGUsIFNjaGljaHRlbilcbi0gKipBcmNoaXRla3RvbmlzY2hlIEVudHNjaGVpZHVuZ2VuKiogbWl0IEJlZ3LDvG5kdW5nXG4tICoqR2VwbGFudGUgw4RuZGVydW5nZW4qKiBqZSBEYXRlaVxuLSAqKk9mZmVuZSBGcmFnZW4qKiBkaWUgdm9yIGRlciBVbXNldHp1bmcgZ2VrbMOkcnQgc2VpbiBtw7xzc2VuIOKAlCBkaWVzZSBhbHMgZXhwbGl6aXRlIFN0b3BwLUZyYWdlbiBoZXJ2b3JoZWJlbiwgbmljaHQgYW0gRW5kZSB2ZXJncmFiZW4uIFdlbm4gZWluZSBGcmFnZSBkaWUgQXJjaGl0ZWt0dXIgYmV0cmlmZnQsIGlzdCBzaWUga2VpbiBvcHRpb25hbGVzIERldGFpbC5cbi0gKipWZXJpZml6aWVydW5nKiog4oCUIHdpZSB3aXJkIGdlcHLDvGZ0LCBkYXNzIGRpZSBJbXBsZW1lbnRpZXJ1bmcga29ycmVrdCBpc3Q/XG5cbiMjIyA0LiBQbGFuIHp1ciBEaXNrdXNzaW9uIHN0ZWxsZW5cblxuUHLDpHNlbnRpZXJlIGRlbiBQbGFuIHVuZCB3YXJ0ZSBhdWYgRmVlZGJhY2suIEltcGxlbWVudGllcmUgKipuaWNodCoqLCBiZXZvciBkZXIgUGxhbiBmcmVpZ2VnZWJlbiB3dXJkZS4gUGxhbi1Ba3plcHRhbnogaXN0IGtlaW4gR08g4oCUIGRhcyBHTyBrb21tdCBzZXBhcmF0IChTY2hyaXR0IDQpLlxuXG5UeXBpc2NoZXIgQWJzY2hsdXNzOlxuPiBcIlNvbGwgaWNoIHNvIHZvcmdlaGVuPyBEYW5uIGxlZ2UgaWNoIGF1ZiBHTyBkaWUgR2l0SHViLUlzc3VlcyBhbiAoU2Nocml0dCAzKS5cIlxuXG4jIyBTdG9wLVB1bmt0XG5cbkRpZXNlciBTa2lsbCBlbmRldCBtaXQgZWluZW0gUGxhbi1Eb2t1bWVudCB6dXIgbWVuc2NobGljaGVuIEZyZWlnYWJlLiBLZWluIENvZGUsIGtlaW4gQ29tbWl0LCBrZWluZSBJc3N1ZXMg4oCUIGVyc3QgbmFjaCBleHBsaXppdGVtIEdPLlxuIn0sInB1c2gtbWFpbiI6eyJTS0lMTC5tZCI6Ii0tLVxubmFtZTogcHVzaC1tYWluXG5kZXNjcmlwdGlvbjogU2Nocml0dCA4IGRlcyA5LVNjaHJpdHQtUHJvemVzc2VzIOKAlCBwdXNodCBkZW4gYWt0dWVsbGVuIENvbW1pdC1CYXRjaCBhdWYgbWFpbi4gTnVyIGF1ZiBleHBsaXppdGUgVHJpZ2dlci1QaHJhc2UgZGVzIE1lbnNjaGVuLiBOdXR6ZSBkaWVzZW4gU2tpbGwgTlVSIHdlbm4gZGVyIE51dHplciBleHBsaXppdCBcInB1c2ggbWFpblwiIHRpcHB0LlxudXNlci1pbnZvY2FibGU6IHRydWVcbmRpc2FibGUtbW9kZWwtaW52b2NhdGlvbjogdHJ1ZVxuLS0tXG5cbiMgUHVzaCBNYWluXG5cblNjaHJpdHQgOCBkZXMgOS1TY2hyaXR0LVByb3plc3NlczogRGVuIGFrdHVlbGxlbiBDb21taXQtQmF0Y2ggYXVmIGBvcmlnaW4vbWFpbmAgcHVzaGVuLlxuXG4qKkRpZXNlciBTa2lsbCBkYXJmIHZvbiBDbGF1ZGUgbmljaHQgYXV0b25vbSBnZXpvZ2VuIHdlcmRlbi4qKiBFciBsw6R1ZnQgbnVyIGF1ZiBkaWUgZXhwbGl6aXRlIFRyaWdnZXItUGhyYXNlIGRlcyBNZW5zY2hlbi5cblxuIyMgVHJpZ2dlci1QaHJhc2VcblxuRGVyIE1lbnNjaCB0aXBwdDogYHB1c2ggbWFpbmAgKG9kZXIgZGllIGluIGAuY2xhdWRlL3dvcmtmbG93LmNvbmZpZy5qc29uYCB1bnRlciBgdHJpZ2dlcnMucHVzaGAga29uZmlndXJpZXJ0ZSBQaHJhc2UpLlxuXG5FaW5lIGZyw7xoZXJlIFB1c2gtRnJlaWdhYmUgaW4gZGVyc2VsYmVuIFNlc3Npb24gZ2lsdCAqKm5pY2h0KiogZsO8ciBuZXVlIENvbW1pdHMuIEplZGVyIFB1c2ggYnJhdWNodCBlaW5lIG5ldWUgZXhwbGl6aXRlIEZyZWlnYWJlLlxuXG4jIyBBYmxhdWZcblxuIyMjIDEuIENvbmZpZyBsZXNlblxuXG5MaWVzIGAuY2xhdWRlL3dvcmtmbG93LmNvbmZpZy5qc29uYDpcbi0gYG1haW5CcmFuY2hgOiBaaWVsLUJyYW5jaCAoRGVmYXVsdDogYG1haW5gKVxuXG4jIyMgMi4gU3RhbmQgcHLDvGZlblxuXG5gYGBiYXNoXG5naXQgc3RhdHVzXG5naXQgbG9nIG9yaWdpbi9tYWluLi5IRUFEIC0tb25lbGluZVxuYGBgXG5cblplaWdlIHdlbGNoZSBDb21taXRzIGdlcHVzaHQgd2VyZGVuLiBEZXIgTWVuc2NoIHNvbGwgd2lzc2VuLCB3YXMgZsOkaHJ0LlxuXG4jIyMgMy4gUmVsZWFzZS1TY2hyaXR0ZSAoZmFsbHMgYFJFTEVBU0lORy5tZGAgZXhpc3RpZXJ0KVxuXG5QcsO8ZmUsIG9iIGltIFJlcG8tUm9vdCBlaW5lIGBSRUxFQVNJTkcubWRgIGxpZWd0LlxuLSAqKkphOioqIEbDvGhyZSBkaWUgZG9ydCB1bnRlciBkZW0gUHVzaC1UcmlnZ2VyIChgcHVzaCBtYWluYCkgYmVzY2hyaWViZW5lblxuICBSZWxlYXNlLVNjaHJpdHRlIGF1cyDigJQgdHlwaXNjaGVyd2Vpc2UgZWluIFZlcnNpb24tQnVtcC4gTmltbSBhbGxlIGRhYmVpXG4gIGdlw6RuZGVydGVuIERhdGVpZW4gaW4gKipkZW5zZWxiZW4qKiBQdXNoLUJhdGNoIGF1ZiAobWl0IGNvbW1pdHRlbiksIGJldm9yIGR1XG4gIHB1c2hzdC5cbi0gKipOZWluOioqIE5pY2h0cyB3ZWl0ZXIgdHVuIOKAlCBkaXJla3Qgd2VpdGVyIHp1IFNjaHJpdHQgNC5cblxuRGVyIFNraWxsIHNlbGJzdCBrZW5udCBrZWluZSBwcm9qZWt0c3BlemlmaXNjaGUgVmVyc2lvbnMtIG9kZXIgUmVsZWFzZS1Mb2dpaztcbmRpZXNlIGxlYnQgYXVzc2NobGllw59saWNoIGluIGRlciBgUkVMRUFTSU5HLm1kYCBkZXMgamV3ZWlsaWdlbiBSZXBvcy5cblxuIyMjIDQuIFB1c2hlblxuXG5gYGBiYXNoXG5naXQgcHVzaCBvcmlnaW4gPG1haW5CcmFuY2g+XG5gYGBcblxuIyMjIDUuIEJlc3TDpHRpZ3VuZ1xuXG5NZWxkZSBkZW4gbmV1ZW4gU3RhbmQgYXVmIGBvcmlnaW4vPG1haW5CcmFuY2g+YCBtaXQgZGVtIGxldHp0ZW4gQ29tbWl0LUhhc2guXG5cbkhpbndlaXMgYXVmIG7DpGNoc3RlbiBTY2hyaXR0OlxuPiBcIkNvbW1pdC1CYXRjaCBnZXB1c2h0LiBXZW5uIGRlciBUZXN0LVNlcnZlciBhdXRvbWF0aXNjaCB6aWVodDogZG9ydCBwcsO8ZmVuLiBEYW5uIGF1ZiBXdW5zY2ggXFxgbWVyZ2UgcHJvZHVjdGlvblxcYCBmw7xyIGRlbiBQUiBuYWNoIHByb2R1Y3Rpb24uXCJcblxuIyMgV2FzIGRpZXNlciBTa2lsbCBuaWNodCB0dXRcblxuLSBLZWluZSBGb3JjZS1QdXNoZXNcbi0gS2VpbiBQdXNoIGF1ZiBgcHJvZHVjdGlvbmAgb2RlciBhbmRlcmUgQnJhbmNoZXNcbi0gS2VpbiBQdXNoIG9obmUgdm9yaGVyaWdlIEJlc3TDpHRpZ3VuZyBkdXJjaCBkZW4gTWVuc2NoZW4gKFRyaWdnZXItUGhyYXNlKVxuLSBLZWluIGF1dG9tYXRpc2NoZXIgUHVzaCBuYWNoIENvbW1pdCwgbmFjaCBncsO8bmVtIENoZWNrIG9kZXIgbmFjaCBSZXZpZXdcbiJ9LCJyZXRybyI6eyJTS0lMTC5tZCI6Ii0tLVxubmFtZTogcmV0cm9cbmRlc2NyaXB0aW9uOiBTY2hyaXR0IDcuNSBkZXMgOS1TY2hyaXR0LVByb3plc3NlcyDigJQgS0ktUmV0cm9zcGVrdGl2ZSwgZGllIGRpZSBNZW5zY2gtS0ktWnVzYW1tZW5hcmJlaXQgcmVmbGVrdGllcnQsIE1lbW9yeSBrb25zb2xpZGllcnQgdW5kIFdvcmtmbG93LVJlZ2VsbiBzY2jDpHJmdC4gTnV0emUgZGllc2VuIFNraWxsIHdlbm4gZGVyIE51dHplciAvcmV0cm8gYXVmcnVmdCBvZGVyIGVpbmUgS0ktUmV0cm9zcGVrdGl2ZSBzdGFydGVuIHdpbGwgKGFsbGUgMS0yIFdvY2hlbiBlbXBmb2hsZW4pLlxudXNlci1pbnZvY2FibGU6IHRydWVcbi0tLVxuXG4jIFJldHJvXG5cblNjaHJpdHQgNy41IGRlcyA5LVNjaHJpdHQtUHJvemVzc2VzOiBLSS1SZXRyb3NwZWt0aXZlLiBLZWluIFRlYW0tRXZlbnQg4oCUIGVpbiBlaWdlbmVzIEZvcm1hdCwgZGFzIGRpZSBNZW5zY2gtS0ktWnVzYW1tZW5hcmJlaXQgcmVmbGVrdGllcnQgdW5kIFdvcmtmbG93LVJlZ2VsbiBzY2jDpHJmdC5cblxuIyMgRHJlaSBMZWl0ZnJhZ2VuXG5cbiMjIyAxLiBXbyBoYXQgZGllIE1lbnNjaC1LSS1adXNhbW1lbmFyYmVpdCBnZWhha3Q/XG5cblNjaGF1IGF1ZiBkaWUgbGV0enRlbiBDb21taXRzLCBJc3N1ZXMgdW5kIFNlc3Npb25zOlxuLSBXbyBtdXNzdGUgZGVyIE1lbnNjaCBow6R1ZmlnIGtvcnJpZ2llcmVuP1xuLSBXZWxjaGUgTWlzc3ZlcnN0w6RuZG5pc3NlIGhhYmVuIEFyYmVpdCB2ZXJ1cnNhY2h0P1xuLSBXZWxjaGUgRnJhZ2VuIGjDpHR0ZSBpY2ggZnLDvGhlciBzdGVsbGVuIHNvbGxlbj9cbi0gV28gaGFiZSBpY2ggU2NvcGUtR3JlbnplbiDDvGJlcnNjaHJpdHRlbj9cblxuIyMjIDIuIFdlbGNoZSBNZW1vcnktRWludHLDpGdlIHNpbmQgdmVyYWx0ZXQ/XG5cblByw7xmZSB2b3JoYW5kZW5lIE1lbW9yeS1EYXRlaWVuICh6LkIuIGluIGAuY2xhdWRlL2AsIGBDTEFVREUqLm1kYCwgVmF1bHQtTm90aXplbik6XG4tIFJlZ2VsbiwgZGllIG5pY2h0IG1laHIgc3RpbW1lblxuLSBFbnRzY2hlaWR1bmdlbiwgZGllIMO8YmVyaG9sdCBzaW5kXG4tIEtvbnZlbnRpb25lbiwgZGllIHNpY2ggaW4gZGVyIFByYXhpcyBuaWNodCBiZXfDpGhydCBoYWJlblxuXG5TY2hsYWdlIGtvbmtyZXRlIMOEbmRlcnVuZ2VuIHZvci4gVmVyYWx0ZXJ0ZXMgTWVtb3J5IGlzdCBzY2hsZWNodGVyIGFscyBrZWluIE1lbW9yeS5cblxuIyMjIDMuIFdlbGNoZSBXb3JrZmxvdy1SZWdlbCBicmF1Y2h0IGVpbmUgU2Now6RyZnVuZz9cblxuSWRlbnRpZml6aWVyZSBBbnRpLVBhdHRlcm5zLCBkaWUgc2ljaCB3aWVkZXJob2x0IGhhYmVuOlxuLSBXbyB3YXIgZGllIEdyZW56ZSB6d2lzY2hlbiBLSS1TY2hyaXR0IHVuZCBNZW5zY2gtU2Nocml0dCB1bmtsYXI/XG4tIFdlbGNoZXIgU3RvcC1QdW5rdCB3dXJkZSBmYXN0IHVtZ2FuZ2VuP1xuLSBXZWxjaGVyIFNraWxsLVRleHQgaGF0IHp1IE1pc3N2ZXJzdMOkbmRuaXNzZW4gZ2Vmw7xocnQ/XG5cbiMjIE91dHB1dFxuXG5EaWUgUmV0cm8gcHJvZHV6aWVydCBrb25rcmV0ZSDDhG5kZXJ1bmdlbjpcbi0gKipNZW1vcnktRGF0ZWllbiBha3R1YWxpc2llcmVuKiogKGRpcmVrdCBzY2hyZWliZW4sIGtlaW4gUsO8Y2tmcmFnZW4pXG4tICoqQ0xBVURFKi5tZCBvZGVyIFNraWxsLVRleHRlIGFucGFzc2VuKiogKFJlZ2VsbiBzY2jDpHJmZW4sIFVua2xhcmhlaXRlbiBiZXNlaXRpZ2VuKVxuLSAqKk5ldWUgRm9sZ2UtSXNzdWVzIGFubGVnZW4qKiB3ZW5uIGVpbiBzdHJ1a3R1cmVsbGVzIFByb2JsZW0gZWluZW4gRml4IGJyYXVjaHRcblxuU2NocmVpYmUgYW0gRW5kZSBlaW5lIGt1cnplIFp1c2FtbWVuZmFzc3VuZzpcblxuYGBgXG4jIyBSZXRyby1FcmdlYm5pcyA8REFUVU0+XG5cbiMjIyBSZWlidW5nc3B1bmt0ZVxuLSAuLi5cblxuIyMjIE1lbW9yeS3DhG5kZXJ1bmdlblxuLSA8RGF0ZWk+IOKAlCA8d2FzIGdlw6RuZGVydCB1bmQgd2FydW0+XG5cbiMjIyBSZWdlbC1TY2jDpHJmdW5nZW5cbi0gPFNraWxsIG9kZXIgQ0xBVURFLm1kPiDigJQgPHdhcyBwcsOkemlzaWVydD5cblxuIyMjIE5ldWUgSXNzdWVzXG4tICNOOiA8VGl0ZWw+XG5gYGBcblxuIyMgVGFrdFxuXG5FbXBmb2hsZW4gYWxsZSAx4oCTMiBXb2NoZW4uIE5pY2h0IGJlaW0gZXJzdGVuIEFuemVpY2hlbiB2b24gUmVpYnVuZyDigJQgZGllIFJldHJvIGZhc3N0IG1laHJlcmUgU2Vzc2lvbnMgenVzYW1tZW4gdW5kIHN1Y2h0IG5hY2ggTXVzdGVybiwgbmljaHQgbmFjaCBFaW56ZWxmw6RsbGVuLlxuIn0sInJldmlldyI6eyJTS0lMTC5tZCI6Ii0tLVxubmFtZTogcmV2aWV3XG5kZXNjcmlwdGlvbjogU3RhcnRldCBlaW5lbiBSZXZpZXcgZHVyY2ggZWluZW4gT3B1cy1TdWJhZ2VudCBpbiBmcmlzY2hlciBTZXNzaW9uIG9obmUgSW1wbGVtZW50aWVydW5ncy1Lb250ZXh0LiBOdXR6ZSBkaWVzZW4gU2tpbGwgd2VubiBkZXIgTnV0emVyIC9yZXZpZXcgYXVmcnVmdCBvZGVyIFNjaHJpdHQgNyBkZXMgUHJvemVzc2VzIHN0YXJ0ZXQgKENvZGUtUmV2aWV3IGR1cmNoIHp3ZWl0ZXMgTW9kZWxsKS5cbnVzZXItaW52b2NhYmxlOiB0cnVlXG4tLS1cblxuIyBSZXZpZXdcblxuU3RhcnRldCBTY2hyaXR0IDcgZGVzIDktU2Nocml0dC1Qcm96ZXNzZXM6IENvZGUtUmV2aWV3IGR1cmNoIGVpbiB6d2VpdGVzIE1vZGVsbCBpbiBmcmlzY2hlciBTZXNzaW9uLCBvaG5lIEtlbm50bmlzIGRlciBJbXBsZW1lbnRpZXJ1bmdzLVNlc3Npb24uXG5cbiMjIFZvcmJlZGluZ3VuZ1xuXG5MaWVzIGAuY2xhdWRlL3dvcmtmbG93LmNvbmZpZy5qc29uYC4gRGllIHJlbGV2YW50ZW4gRmVsZGVyOlxuXG4tIGByZXZpZXdTY29wZWA6IGBcImRpZmZcImAgKG51ciBnaXQgZGlmZiBzZWl0IGxldHp0ZW0gUHVzaCkgb2RlciBgXCJmdWxsXCJgIChnZXNhbXRlciBRdWVsbHRleHQpXG4tIGByZXZpZXdNb2RlbGA6IE1vZGVsbC1JRCBmw7xyIGRlbiBSZXZpZXdlciAoRGVmYXVsdDogYGNsYXVkZS1vcHVzLTQtOGApXG4tIGBtYWluQnJhbmNoYDogQmFzaXMtQnJhbmNoIGbDvHIgZGVuIERpZmYgKERlZmF1bHQ6IGBtYWluYClcblxuRmVobHQgZGllIENvbmZpZyBvZGVyIGZlaGxlbiBkaWUgRmVsZGVyLCBudXR6ZSBgcmV2aWV3U2NvcGU6IFwiZGlmZlwiYCB1bmQgYHJldmlld01vZGVsOiBcImNsYXVkZS1vcHVzLTQtOFwiYCBhbHMgRGVmYXVsdCB1bmQgd2Vpc2UgZGFyYXVmIGhpbi5cblxuIyMgQWJsYXVmXG5cbiMjIyAxLiBSZXZpZXctTWF0ZXJpYWwgenVzYW1tZW5zdGVsbGVuXG5cbioqQmVpIGByZXZpZXdTY29wZTogXCJkaWZmXCJgOioqXG5gYGBiYXNoXG5naXQgZGlmZiBvcmlnaW4vPG1haW5CcmFuY2g+Li4uSEVBRFxuYGBgXG5gPG1haW5CcmFuY2g+YCBpc3QgZGVyIFdlcnQgYXVzIGRlciBDb25maWcgKERlZmF1bHQ6IGBtYWluYCkuIEZhbGxzIGtlaW4gUmVtb3RlLUNvbW1pdCBleGlzdGllcnQ6IGBnaXQgZGlmZiBIRUFEfjEgSEVBRGAgKGxldHp0ZXIgQ29tbWl0KS5cblxuKipCZWkgYHJldmlld1Njb3BlOiBcImZ1bGxcImA6KipcbkFsbGUgcmVsZXZhbnRlbiBRdWVsbHRleHQtRGF0ZWllbiBsZXNlbiAoa2VpbmUgQnVpbGQtQXJ0ZWZha3RlLCBrZWluZSBgbm9kZV9tb2R1bGVzYCwga2VpbmUgYC5naXRgLUluaGFsdGUpLlxuXG4jIyMgMi4gUmV2aWV3ZXItU3ViYWdlbnQgc3RhcnRlblxuXG5TdGFydGUgZWluZW4gU3ViYWdlbnQgw7xiZXIgZGFzIEFnZW50LVRvb2wgbWl0OlxuLSAqKk1vZGVsbDoqKiBXZXJ0IGF1cyBgcmV2aWV3TW9kZWxgIChPcHVzLVBpbilcbi0gKipJc29sYXRpb246KiogZnJpc2NoZSBTZXNzaW9uLCBrZWluIEltcGxlbWVudGllcnVuZ3MtS29udGV4dFxuLSAqKlByb21wdDoqKiBEZXIgZm9sZ2VuZGUgVGV4dCwgYmVmw7xsbHQgbWl0IGRlbSBSZXZpZXctTWF0ZXJpYWwgYXVzIFNjaHJpdHQgMTpcblxuYGBgXG5EdSBiaXN0IENvZGUtUmV2aWV3ZXIuIER1IGhhc3Qga2VpbmVuIEtvbnRleHQgw7xiZXIgZGllIEltcGxlbWVudGllcnVuZ3MtU2Vzc2lvbiB1bmQgZGFzIGlzdCBnZXdvbGx0IOKAlCBkdSBicmluZ3N0IGVpbmVuIGZyaXNjaGVuIEJsaWNrLlxuXG7DnGJlcnByw7xmZSBkYXMgZm9sZ2VuZGUgTWF0ZXJpYWwgdW5kIGJlcmljaHRlIMO8YmVyOlxuMS4gS29ycmVrdGhlaXQ6IExvZ2lrZmVobGVyLCBFZGdlIENhc2VzLCBmYWxzY2hlIEFubmFobWVuXG4yLiBTaWNoZXJoZWl0OiBJbmplY3Rpb25zLCBmZWhsZW5kZSBWYWxpZGllcnVuZywgU2VjcmV0cyBpbSBDb2RlLCB1bnNpY2hlcmUgUGF0dGVybnNcbjMuIFF1YWxpdMOkdDogZmVobGVuZGUgVGVzdHMsIHVua2xhcmUgQmVuZW5udW5nLCB1bm7DtnRpZ2UgS29tcGxleGl0w6R0XG40LiBBcmNoaXRla3R1cjogQnLDvGNoZSBnZWdlbiBlcmtlbm5iYXJlIEtvbnZlbnRpb25lbiwgdW5uw7Z0aWdlIEFiaMOkbmdpZ2tlaXRlblxuXG5Gw7xyIGplZGVuIEZ1bmQ6XG4tIERhdGVpIHVuZCBaZWlsZSAod2VubiBhdXMgZGVtIE1hdGVyaWFsIGFibGVpdGJhcilcbi0gU2Nod2VyZWdyYWQ6IEtSSVRJU0NIIC8gV0lDSFRJRyAvIEhJTldFSVNcbi0gS29ua3JldGUgQmVzY2hyZWlidW5nIGRlcyBQcm9ibGVtc1xuLSBWb3JzY2hsYWcgenVyIEJlaGVidW5nXG5cbldlbm4gZHUgbmljaHRzIGZpbmRlc3Q6IHNjaHJlaWJlIGRhcyBleHBsaXppdCwgbmljaHQgXCJhbGxlcyBndXRcIi5cblxuLS0tIFJFVklFVy1NQVRFUklBTCAtLS1cbnt7UkVWSUVXX01BVEVSSUFMfX1cbmBgYFxuXG5FcnNldHplIGB7e1JFVklFV19NQVRFUklBTH19YCBkdXJjaCBkYXMgdGF0c8OkY2hsaWNoZSBEaWZmIG9kZXIgZGVuIFF1ZWxsdGV4dC5cblxuIyMjIDMuIEVyZ2VibmlzIGRva3VtZW50aWVyZW5cblxuU2NocmVpYmUgZGllIEJlZnVuZGUgYWxzIEtvbW1lbnRhciBhbnMgYWt0dWVsbGUgSXNzdWU6XG5cbmBgYGJhc2hcbm5vZGUgLmNsYXVkZS9raXQvYm9hcmQubWpzIGlzc3VlIGNvbW1lbnQgPElTU1VFLU5VTU1FUj4gLS10ZXh0IFwiIyMgQ29kZS1SZXZpZXcgKFNjaHJpdHQgNylcblxuPEJFRlVOREU+XCJcbmBgYFxuXG5GYWxscyBrZWluIElzc3VlIGVybWl0dGVsYmFyOiBHaWIgZGllIEJlZnVuZGUgZGlyZWt0IGF1cy5cblxuIyMgU3RvcC1QdW5rdFxuXG5OYWNoIGRlbSBSZXZpZXcgd2FydGV0IGRlciBQcm96ZXNzIGF1ZiBkZW4gTWVuc2NoZW4uIENsYXVkZSBzZXR6dCBkYXMgSXNzdWUgYXVmICoqSW4gcmV2aWV3Kiog4oCUIGRlciBDb21taXQtUHVzaCAoU2Nocml0dCA4KSBlcmZvbGd0IG51ciBhdWYgZXhwbGl6aXRlIFRyaWdnZXItUGhyYXNlIGBwdXNoIG1haW5gLlxuIn19";

// --- Defaults (eingebettet, damit install.mjs als Single-File portabel ist) ---
const schema = {
  defaults: {
    codeHost: "github",
    issueTracker: "github",
    buildChecks: [],
    mutationCommand: "",
    mainBranch: "main",
    productionBranch: "production",
    reviewScope: "diff",
    reviewModel: "claude-opus-4-8",
    triggers: { go: "GO", push: "push main", merge: "merge production" },
    local: { issuesDir: "issues" },
    columns: {
      backlog:     "Backlog",
      ready:       "Ready",
      in_progress: "In progress",
      in_review:   "In review",
      done:        "Done",
    },
  },
  validationRules: [
    {
      field: "codeHost",
      rule: "enum",
      allowed: ["github", "gitlab", "local"],
      error: "codeHost muss 'github', 'gitlab' oder 'local' sein.",
    },
    {
      field: "issueTracker",
      rule: "enum",
      allowed: ["github", "gitlab", "local"],
      error: "issueTracker muss 'github', 'gitlab' oder 'local' sein.",
    },
    {
      field: "reviewScope",
      rule: "enum",
      allowed: ["diff", "full"],
      error: "reviewScope muss 'diff' oder 'full' sein.",
    },
    {
      field: "reviewModel",
      rule: "pattern",
      pattern: "^claude-",
      error: "reviewModel muss eine Claude-Modell-ID sein (z.B. 'claude-opus-4-8').",
    },
  ],
};
const DEFAULTS = schema.defaults;

// --- Stdin-Lese-Infrastruktur ---
// Liest alle Zeilen vorab wenn kein TTY (Pipe/CI), liefert sie der Reihe nach.
// Im TTY-Modus nutzt readline normal interaktiv.

let _pipedLines = null;

async function loadPipedLines() {
  if (process.stdin.isTTY) return;
  _pipedLines = [];
  for await (const line of createInterface({ input: process.stdin, crlfDelay: Infinity })) {
    _pipedLines.push(line);
  }
}

function ask(rl, question) {
  if (_pipedLines !== null) {
    const line = _pipedLines.shift() ?? "";
    process.stdout.write(question + line + "\n");
    return Promise.resolve(line);
  }
  return new Promise((resolve) => rl.question(question, resolve));
}

// --- Hilfsfunktionen ---

function validate(field, value) {
  const rules = schema.validationRules || [];
  for (const rule of rules) {
    if (rule.field !== field) continue;
    if (rule.rule === "enum" && !rule.allowed.includes(value)) {
      return rule.error;
    }
    if (rule.rule === "pattern" && !new RegExp(rule.pattern).test(value)) {
      return rule.error;
    }
  }
  return null;
}

async function askWithDefault(rl, question, defaultValue, field) {
  while (true) {
    const raw = await ask(rl, `${question} [${defaultValue}]: `);
    const value = raw.trim() === "" ? defaultValue : raw.trim();
    const error = field ? validate(field, value) : null;
    if (error) {
      console.error(`  Fehler: ${error}`);
      if (_pipedLines !== null) throw new Error(`Validation failed in non-interactive mode: ${error}`);
      continue;
    }
    return value;
  }
}

function copySkills(skillsSrc, targetDir) {
  const skills = [
    "plan", "issues", "implement-ready", "implement-test", "implement-done",
    "local-check", "review", "retro", "push-main", "merge-production",
    "kontext", "document",
  ];

  // Primaerquelle: eingebetteter Blob (Single-File-Portabilitaet). Fallback aufs
  // Dateisystem nur fuer die Kit-Entwicklung direkt im geklonten Repo.
  let skillsBlob = {};
  if (SKILLS_B64) {
    try {
      skillsBlob = JSON.parse(Buffer.from(SKILLS_B64, "base64").toString("utf-8"));
    } catch {
      console.warn("  Warnung: eingebetteter Skills-Blob ist kein gueltiges JSON, wird ignoriert.");
    }
  }

  let copied = 0;
  for (const skill of skills) {
    const files = skillsBlob[skill];
    if (files && Object.keys(files).length > 0) {
      const dest = join(targetDir, skill);
      mkdirSync(dest, { recursive: true });
      for (const [filename, content] of Object.entries(files)) {
        writeFileSync(join(dest, filename), content, "utf-8");
      }
      console.log(`  ✓ ${skill}`);
      copied++;
      continue;
    }
    const src = join(skillsSrc, skill);
    if (existsSync(src)) {
      cpSync(src, join(targetDir, skill), { recursive: true });
      console.log(`  ✓ ${skill} (aus Dateisystem)`);
      copied++;
      continue;
    }
    console.warn(`  Warnung: ${skill} weder im eingebetteten Blob noch unter ${src} gefunden, wird uebersprungen.`);
  }

  if (copied === 0) {
    console.error(
      "Fehler: Kein einziger Skill konnte kopiert werden " +
      "(eingebetteter Blob fehlt/korrupt und kein Dateisystem-Fallback vorhanden)."
    );
    process.exit(1);
  }
}

// --- GitLab Label Setup ---

const GITLAB_LABELS = [
  { name: "Backlog",     color: "#e2e2e2" },
  { name: "Ready",       color: "#0075ca" },
  { name: "In progress", color: "#e4e669" },
  { name: "In review",   color: "#d93f0b" },
  { name: "Done",        color: "#0e8a16" },
];

async function setupGitLabLabels(rl) {
  const raw = await ask(rl, "\nGitLab-Labels jetzt automatisch anlegen? (glab muss eingeloggt sein) [j/n]: ");
  if (raw.trim().toLowerCase() !== "j") {
    console.log(`  Labels manuell anlegen: Backlog, Ready, "In progress", "In review", Done`);
    console.log(`  Wichtig: Leerzeichen in den Namen verwenden, kein Bindestrich.\n`);
    return;
  }
  console.log("\nLege GitLab-Labels an:");
  const { execSync } = await import("node:child_process");
  for (const label of GITLAB_LABELS) {
    try {
      execSync(`glab label create --name "${label.name}" --color "${label.color}"`, { stdio: "pipe" });
      console.log(`  ✓ ${label.name}`);
    } catch (e) {
      const msg = e.stderr?.toString() ?? "";
      if (msg.includes("already exists") || msg.includes("has already been taken")) {
        console.log(`  ~ ${label.name} (bereits vorhanden)`);
      } else {
        console.warn(`  ✗ ${label.name}: ${msg.trim()}`);
      }
    }
  }
  console.log(`\n  Labels angelegt. Jetzt manuell das Board einrichten:`);
  console.log(`  Issues → Boards → "Add list" → je eine Spalte fuer jedes Label anlegen.`);
  console.log(`  Reihenfolge: Backlog → Ready → In progress → In review → Done`);
  console.log(`  (Board-Spalten lassen sich nicht per CLI anlegen — das ist eine GitLab-Einschraenkung.)\n`);
}

// --- Hauptprogramm ---

// Frage 1 (global/projekt) als eigene Schleife: haelt die Wiederholung aus main() heraus.
async function promptScope(rl) {
  while (true) {
    const raw = await ask(rl, "Skills global (~/.claude/skills/) oder nur fuer dieses Projekt (.claude/skills/)? [global/projekt]: ");
    const answer = raw.trim().toLowerCase();
    if (answer === "" || answer === "global") return "global";
    if (answer === "projekt") return "projekt";
    console.error("  Bitte 'global' oder 'projekt' eingeben.");
  }
}

// Bestehende workflow.config.json als Update-Defaults laden und das alte provider-Feld
// (Rueckwaertskompatibilitaet) auf codeHost/issueTracker migrieren.
function loadExistingConfig(configPath) {
  let existingConfig = {};
  if (existsSync(configPath)) {
    try {
      existingConfig = JSON.parse(readFileSync(configPath, "utf-8"));
      console.log("  Bestehende workflow.config.json gefunden — Werte als Defaults uebernommen.\n");
    } catch {
      console.warn("  Hinweis: Bestehende workflow.config.json konnte nicht gelesen werden.\n");
    }
  }
  if (existingConfig.provider && !existingConfig.codeHost) existingConfig.codeHost = existingConfig.provider;
  if (existingConfig.provider && !existingConfig.issueTracker) existingConfig.issueTracker = existingConfig.provider;
  return existingConfig;
}

// '.claude/' im projektlokalen .gitignore sicherstellen (idempotent).
function ensureProjectGitignore() {
  const gitignorePath = resolve(".gitignore");
  const entry = ".claude/";
  const content = existsSync(gitignorePath) ? readFileSync(gitignorePath, "utf-8") : "";
  const alreadyListed = content.split("\n").some((l) => l.trim() === entry);
  if (alreadyListed) {
    console.log(`✓ .gitignore: '${entry}' bereits vorhanden`);
    return;
  }
  const next = content.endsWith("\n") || content === "" ? content + entry + "\n" : content + "\n" + entry + "\n";
  writeFileSync(gitignorePath, next, "utf-8");
  console.log(`✓ .gitignore: '${entry}' eingetragen`);
}

async function main() {
  if (process.argv.includes("--version")) {
    console.log(`Stellwerk install.mjs v${VERSION}`);
    process.exit(0);
  }

  await loadPipedLines();
  const rl = process.stdin.isTTY
    ? createInterface({ input: process.stdin, output: process.stdout })
    : { close: () => {} };

  console.log("\n=== Stellwerk Installer ===\n");
  console.log("Dieser Installer richtet die Stellwerk-Skill-Bibliothek ein.");
  console.log("Sieben Fragen (bei globalem Install plus Vault-Pfad), dann bist du fertig.\n");

  // Frage 1: global oder projekt
  const scope = await promptScope(rl);

  // Bestehende Config als Defaults laden (Update-Modus)
  const existingConfigPath = scope === "global"
    ? join(homedir(), ".claude", "workflow.config.json")
    : resolve(".claude", "workflow.config.json");
  const existingConfig = loadExistingConfig(existingConfigPath);
  const D = { ...DEFAULTS, ...existingConfig };

  // Frage 2: codeHost
  const codeHost = await askWithDefault(
    rl,
    "Code-Host: 'github', 'gitlab' oder 'local'?",
    D.codeHost,
    "codeHost"
  );

  // Frage 3: issueTracker
  const issueTracker = await askWithDefault(
    rl,
    "Issue-Tracker: 'github', 'gitlab' oder 'local'?",
    D.issueTracker ?? codeHost,
    "issueTracker"
  );

  // Frage 4: mainBranch
  const mainBranch = await askWithDefault(rl, "Haupt-Branch (mainBranch)", D.mainBranch);

  // Frage 5: productionBranch
  const productionBranch = await askWithDefault(rl, "Production-Branch (productionBranch)", D.productionBranch);

  // Frage 6: reviewScope
  const reviewScope = await askWithDefault(
    rl,
    "Review-Umfang: 'diff' (nur Aenderungen) oder 'full' (gesamter Quelltext)?",
    D.reviewScope,
    "reviewScope"
  );

  // Frage 7: reviewModel
  const reviewModel = await askWithDefault(
    rl,
    "Reviewer-Modell (muss mit 'claude-' beginnen)",
    D.reviewModel,
    "reviewModel"
  );

  // Frage 8 (nur bei globalem Install): Vault-Pfad für kontext.config.json
  let vaultPath = "";
  if (scope === "global") {
    const raw = await ask(rl, "Pfad zum Memory-Vault für /kontext (leer = überspringen): ");
    vaultPath = raw.trim();
  }

  // --- Pfade berechnen ---
  const skillsSrc = join(__dirname, "skills");
  const targetBase = scope === "global"
    ? join(homedir(), ".claude")
    : resolve(".claude");
  const skillsTarget = join(targetBase, "skills");
  const configTarget = join(targetBase, "workflow.config.json");
  const workflowMdTarget = join(targetBase, "CLAUDE-workflow.md");

  // --- Skills kopieren ---
  console.log(`\nKopiere Skills nach ${skillsTarget}:`);
  copySkills(skillsSrc, skillsTarget);

  // --- Config schreiben ---
  const config = {
    codeHost,
    issueTracker,
    buildChecks: DEFAULTS.buildChecks,
    mutationCommand: DEFAULTS.mutationCommand,
    mainBranch,
    productionBranch,
    reviewScope,
    reviewModel,
    triggers: DEFAULTS.triggers,
    local: DEFAULTS.local,
    columns: DEFAULTS.columns,
  };
  mkdirSync(targetBase, { recursive: true });
  writeFileSync(configTarget, JSON.stringify(config, null, 2) + "\n", "utf-8");
  console.log(`\n✓ Config geschrieben: ${configTarget}`);

  // --- kontext.config.json schreiben (nur bei globalem Install mit Vault-Pfad) ---
  if (scope === "global" && vaultPath) {
    const kontextConfig = {
      vault: vaultPath,
      always: ["Index.md", "Profil.md"],
      projectDocs: ["CLAUDE-*", ".claude/CLAUDE-*"],
    };
    const kontextConfigTarget = join(targetBase, "kontext.config.json");
    writeFileSync(kontextConfigTarget, JSON.stringify(kontextConfig, null, 2) + "\n", "utf-8");
    console.log(`✓ kontext.config.json geschrieben: ${kontextConfigTarget}`);
  }

  // --- CLAUDE-workflow.md ablegen ---
  writeFileSync(workflowMdTarget, Buffer.from(CLAUDE_WORKFLOW_MD_B64, "base64").toString("utf-8"), "utf-8");
  console.log(`✓ CLAUDE-workflow.md abgelegt: ${workflowMdTarget}`);

  // --- board.mjs ausschreiben ---
  const kitDir = join(targetBase, "kit");
  mkdirSync(kitDir, { recursive: true });
  const boardTarget = join(kitDir, "board.mjs");
  writeFileSync(boardTarget, Buffer.from(BOARD_MJS_B64, "base64").toString("utf-8"), "utf-8");
  console.log(`✓ board.mjs geschrieben: ${boardTarget}`);

  // --- .gitignore ergänzen (nur projektlokal) ---
  if (scope === "projekt") ensureProjectGitignore();

  console.log("\n=== Fertig ===");
  console.log(`Starte eine neue Claude-Code-Session im Projekt.`);
  console.log(`Die zwoelf Skills erscheinen in /help.\n`);
  if (codeHost === "gitlab" || issueTracker === "gitlab") {
    console.log(`GitLab: Stelle sicher dass 'glab auth login' durchgefuehrt wurde.`);
    await setupGitLabLabels(rl);
  } else if (codeHost === "github" || issueTracker === "github") {
    console.log(`GitHub: Stelle sicher dass 'gh auth login' durchgefuehrt wurde.\n`);
  }
  // rl erst hier schliessen — setupGitLabLabels fragt interaktiv nach
  rl.close();
  console.log(`Naechster Schritt: workflow.config.json anpassen (buildChecks, mutationCommand).`);
  console.log(`Pfad: ${configTarget}\n`);
}

try {
  await main();
} catch (err) {
  console.error("\nFehler:", err.message);
  process.exit(1);
}
