@query-farm/vgi 0.31.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/catalog/item-encoding.d.ts +17 -0
- package/dist/catalog/read-only.d.ts +16 -0
- package/dist/filter-pushdown/evaluate.d.ts +9 -0
- package/dist/filter-pushdown/history.d.ts +66 -0
- package/dist/filter-pushdown/index.d.ts +1 -0
- package/dist/functions/storage-cf-do.d.ts +2 -2
- package/dist/functions/storage.d.ts +39 -3
- package/dist/functions/table-in-out.d.ts +13 -8
- package/dist/functions/types.d.ts +14 -1
- package/dist/http/fetch.d.ts +1 -1
- package/dist/index.core.d.ts +1 -1
- package/dist/index.js +1325 -988
- package/dist/index.js.map +20 -16
- package/dist/protocol/carried-init-request.d.ts +28 -0
- package/dist/protocol/dispatch.d.ts +0 -7
- package/dist/protocol/handlers/function.d.ts +0 -1
- package/dist/protocol/handlers/shared.d.ts +0 -7
- package/dist/protocol/state-serializer.d.ts +29 -2
- package/dist/serve-entry.js +393 -190
- package/dist/serve-entry.js.map +16 -12
- package/dist/util/zstd-sync.d.ts +7 -0
- package/dist/worker-cf-entry.js +5045 -4712
- package/dist/worker-cf-entry.js.map +25 -21
- package/package.json +1 -1
- package/src/catalog/item-encoding.ts +59 -0
- package/src/catalog/read-only.ts +87 -19
- package/src/filter-pushdown/evaluate.ts +55 -8
- package/src/filter-pushdown/history.ts +239 -0
- package/src/filter-pushdown/index.ts +8 -0
- package/src/functions/storage-cf-do.ts +7 -12
- package/src/functions/storage.ts +54 -11
- package/src/functions/table-buffering.ts +0 -1
- package/src/functions/table-in-out.ts +99 -60
- package/src/functions/table.ts +41 -38
- package/src/functions/types.ts +14 -1
- package/src/http/fetch.ts +2 -17
- package/src/index.core.ts +1 -0
- package/src/protocol/carried-init-request.ts +139 -0
- package/src/protocol/dispatch.ts +0 -8
- package/src/protocol/handlers/catalog/admin.ts +5 -2
- package/src/protocol/handlers/function.ts +18 -15
- package/src/protocol/handlers/shared.ts +0 -22
- package/src/protocol/state-serializer.ts +109 -37
- package/src/util/zstd-sync.ts +50 -0
package/dist/serve-entry.js.map
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/functions/storage-cf-do.ts", "../src/functions/storage.ts", "../src/serve-entry.ts", "../src/http/fetch.ts", "../src/arrow/predicates.ts", "../src/arrow/impl-arrowjs/schema.ts", "../src/arrow/impl-arrowjs/empty.ts", "../src/arrow/impl-arrowjs/build.ts", "../src/arrow/codec/registry.ts", "../src/arrow/impl-arrowjs/canonical.ts", "../src/arrow/impl-arrowjs/iterate.ts", "../src/arrow/impl-arrowjs/filter.ts", "../src/arrow/impl-arrowjs/project.ts", "../src/arrow/impl-arrowjs/metadata.ts", "../src/arrow/impl-arrowjs/ipc.ts", "../src/arrow/impl-arrowjs/statistics.ts", "../src/arrow/impl-arrowjs/index.ts", "../src/arrow/schema-types.ts", "../src/util/bytes.ts", "../src/
|
|
3
|
+
"sources": ["../src/functions/storage-cf-do.ts", "../src/functions/storage.ts", "../src/serve-entry.ts", "../src/http/fetch.ts", "../src/arrow/predicates.ts", "../src/arrow/impl-arrowjs/schema.ts", "../src/arrow/impl-arrowjs/empty.ts", "../src/arrow/impl-arrowjs/build.ts", "../src/arrow/codec/registry.ts", "../src/arrow/impl-arrowjs/canonical.ts", "../src/arrow/impl-arrowjs/iterate.ts", "../src/arrow/impl-arrowjs/filter.ts", "../src/arrow/impl-arrowjs/project.ts", "../src/arrow/impl-arrowjs/metadata.ts", "../src/arrow/impl-arrowjs/ipc.ts", "../src/arrow/impl-arrowjs/statistics.ts", "../src/arrow/impl-arrowjs/index.ts", "../src/arrow/schema-types.ts", "../src/util/bytes.ts", "../src/filter-pushdown/history.ts", "../src/util/zstd-sync.ts", "../src/arguments/arguments.ts", "../src/protocol/serializers/arguments.ts", "../src/protocol/serializers/shared.ts", "../src/protocol/serializers/bind.ts", "../src/protocol/serializers/init.ts", "../src/protocol/serializers/cardinality.ts", "../src/protocol/carried-init-request.ts", "../src/protocol/state-serializer.ts", "../src/protocol/dispatch.ts", "../src/util/statistics.ts", "../src/generated/vgi-protocol-schemas.ts", "../src/schema-path.ts", "../src/protocol/handlers/shared.ts", "../src/errors.ts", "../node_modules/@noble/ciphers/utils.js", "../node_modules/@noble/ciphers/_arx.js", "../node_modules/@noble/ciphers/_poly1305.js", "../node_modules/@noble/ciphers/chacha.js", "../src/crypto.ts", "../src/protocol/handlers/catalog/shared.ts", "../src/request-auth.ts", "../src/protocol/serializers/splits.ts", "../src/split-token.ts", "../src/protocol/handlers/function.ts", "../src/arguments/argument-spec.ts", "../src/functions/aggregate.ts", "../src/protocol/handlers/aggregate.ts", "../src/protocol/handlers/table-buffering.ts", "../src/functions/table-buffering.ts", "../src/codec/asd.ts", "../src/generated/vgi-client.ts", "../src/catalog/item-encoding.ts", "../src/catalog/interface.ts", "../src/protocol/handlers/catalog/admin.ts", "../src/protocol/handlers/catalog/table.ts", "../src/protocol/handlers/catalog/view.ts", "../src/protocol/handlers/catalog/macro.ts", "../src/protocol/handlers/catalog/index_methods.ts", "../src/protocol/handlers/catalog/index.ts", "../src/http/landing-html.ts", "../src/http/client-bundle.ts", "../src/http/landing.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Cloudflare Durable Object storage for VGI function state.\n//\n// Port of vgi-python's vgi/function_storage_cf_do.py. Talks the Cloudflare\n// Worker + Durable Object's unified state_* / queue_* protocol\n// (vgi-cloudflare-durable-object-storage/src/index.ts). Every request carries\n// the per-attach `shard_key` (set via forShard); destructive ops carry a fresh\n// 32-hex `attempt_id`. The DO is single-threaded SQLite, so ops are atomic.\n//\n// Usage:\n// Set `VGI_WORKER_SHARED_STORAGE=cloudflare-do` plus `VGI_CF_DO_URL`.\n// Optionally set `VGI_CF_DO_TOKEN` for bearer auth.\n\nimport type { FunctionStorage } from \"./storage.js\";\nimport { UnknownInvocationError } from \"./storage.js\";\n\n/** Minimal fetch signature satisfied by both the global `fetch` and a\n * Cloudflare service-binding Fetcher (`env.<BINDING>`). */\nexport type FetchLike = (\n input: string,\n init?: { method?: string; headers?: Record<string, string>; body?: string },\n) => Promise<Response>;\n\n// Namespaces under the unified state_* table for the legacy worker/queue\n// families the DO no longer has dedicated endpoints for.\nconst NS_WORKER = new TextEncoder().encode(\"worker\");\n\nexport class FunctionStorageCfDo implements FunctionStorage {\n private readonly _baseUrl: string;\n private readonly _token: string | null;\n /** Per-attach routing key (att-<hex uuid>); \"\" until pinned via forShard. */\n private readonly _shardKey: string;\n /** Fetch implementation. Defaults to the global `fetch`; pass a Cloudflare\n * service-binding Fetcher (env.<BINDING>) when the storage worker lives on\n * the same account/zone — a same-zone public-URL fetch is rejected (CF\n * error 1042), but a service binding routes worker-to-worker directly. */\n private readonly _fetch: FetchLike;\n\n constructor(opts: {\n url: string;\n token?: string | null;\n shardKey?: string;\n fetch?: FetchLike;\n }) {\n // Strip trailing slash so endpoint paths can be appended unconditionally.\n this._baseUrl = opts.url.replace(/\\/+$/, \"\");\n this._token = opts.token ?? null;\n this._shardKey = opts.shardKey ?? \"\";\n this._fetch = opts.fetch ?? ((input, init) => fetch(input as any, init));\n }\n\n /** Build an instance from environment variables. */\n static fromEnv(): FunctionStorageCfDo {\n const url = process.env.VGI_CF_DO_URL;\n if (!url) {\n throw new Error(\n \"VGI_CF_DO_URL environment variable is required when \" +\n \"VGI_WORKER_SHARED_STORAGE=cloudflare-do\",\n );\n }\n return new FunctionStorageCfDo({\n url,\n token: process.env.VGI_CF_DO_TOKEN || null,\n });\n }\n\n /**\n * Return a view of this backend pinned to one shard key, so callers can route\n * per logical ATTACH. Shares the URL/token; only the shard key differs.\n */\n forShard(shardKey: string): FunctionStorageCfDo {\n return new FunctionStorageCfDo({\n url: this._baseUrl,\n token: this._token,\n shardKey,\n fetch: this._fetch,\n });\n }\n\n // --- Worker state → ns=worker, key = int64(worker_id) ---\n\n async workerPut(executionId: Uint8Array, workerId: number, state: Uint8Array): Promise<void> {\n await this._statePutMany(executionId, NS_WORKER, [[int64Key(workerId), state]]);\n }\n\n async workerCollect(executionId: Uint8Array): Promise<Uint8Array[]> {\n const rows = await this._statePaged(\"state_drain\", executionId, NS_WORKER, newAttemptId());\n return rows.map(([, v]) => v);\n }\n\n async workerScan(executionId: Uint8Array): Promise<Array<[number, Uint8Array]>> {\n const rows = await this._statePaged(\"state_scan\", executionId, NS_WORKER, null);\n return rows.map(([k, v]) => [int64FromKey(k), v]);\n }\n\n // --- Work queue ---\n\n async queuePush(executionId: Uint8Array, items: Uint8Array[]): Promise<number> {\n const data = await this._post<{ count: number }>(\"queue_push\", {\n execution_id: bytesToB64(executionId),\n items: items.map(bytesToB64),\n attempt_id: newAttemptId(),\n });\n return Number(data.count);\n }\n\n async queuePop(executionId: Uint8Array): Promise<Uint8Array | null> {\n const data = await this._post<{ item: string | null }>(\"queue_pop\", {\n execution_id: bytesToB64(executionId),\n attempt_id: newAttemptId(),\n });\n return data.item ? b64ToBytes(data.item) : null;\n }\n\n async queueClear(executionId: Uint8Array): Promise<number> {\n const data = await this._post<{ cleared: number }>(\"queue_clear\", {\n execution_id: bytesToB64(executionId),\n attempt_id: newAttemptId(),\n });\n return Number(data.cleared);\n }\n\n // --- Namespaced key/value state ---\n\n async stateGet(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array): Promise<Uint8Array | null> {\n const data = await this._post<{ rows: Array<{ value: string } | null> }>(\"state_get_many\", {\n scope_id: bytesToB64(scopeId),\n ns: bytesToB64(ns),\n keys: [bytesToB64(key)],\n });\n const row = (data.rows ?? [])[0];\n return row ? b64ToBytes(row.value) : null;\n }\n\n async statePut(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, value: Uint8Array): Promise<void> {\n await this._statePutMany(scopeId, ns, [[key, value]]);\n }\n\n // --- Append-only log ---\n\n async stateAppend(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, item: Uint8Array): Promise<number> {\n const data = await this._post<{ ordinal: number }>(\"state_append\", {\n scope_id: bytesToB64(scopeId),\n ns: bytesToB64(ns),\n key: bytesToB64(key),\n item: bytesToB64(item),\n attempt_id: newAttemptId(),\n });\n return Number(data.ordinal);\n }\n\n async stateLogScan(\n scopeId: Uint8Array,\n ns: Uint8Array,\n key: Uint8Array,\n afterId: number = -1,\n limit: number | null = null,\n ): Promise<Array<[number, Uint8Array]>> {\n const body: Record<string, unknown> = {\n scope_id: bytesToB64(scopeId),\n ns: bytesToB64(ns),\n key: bytesToB64(key),\n after_id: afterId,\n };\n if (limit != null && limit > 0) body.limit = limit;\n const data = await this._post<{ rows: Array<{ id: number; value: string }> }>(\"state_log_scan\", body);\n return (data.rows ?? []).map((r) => [Number(r.id), b64ToBytes(r.value)]);\n }\n\n async executionClear(scopeId: Uint8Array): Promise<number> {\n const data = await this._post<{ deleted: number }>(\"execution_clear\", {\n scope_id: bytesToB64(scopeId),\n attempt_id: newAttemptId(),\n });\n return Number(data.deleted);\n }\n\n // --- unified state_* helpers ---\n\n private async _statePutMany(\n scopeId: Uint8Array,\n ns: Uint8Array,\n items: Array<[Uint8Array, Uint8Array]>,\n ): Promise<void> {\n await this._post(\"state_put_many\", {\n scope_id: bytesToB64(scopeId),\n ns: bytesToB64(ns),\n items: items.map(([k, v]) => ({ key: bytesToB64(k), value: bytesToB64(v) })),\n attempt_id: newAttemptId(),\n });\n }\n\n /** Drive state_scan / state_drain across pages. attemptId is null for scan. */\n private async _statePaged(\n endpoint: string,\n scopeId: Uint8Array,\n ns: Uint8Array,\n attemptId: string | null,\n ): Promise<Array<[Uint8Array, Uint8Array]>> {\n const out: Array<[Uint8Array, Uint8Array]> = [];\n let afterKey: string | undefined;\n for (;;) {\n const body: Record<string, unknown> = { scope_id: bytesToB64(scopeId), ns: bytesToB64(ns) };\n if (afterKey != null) body.after_key = afterKey;\n if (attemptId != null) body.attempt_id = attemptId;\n const data = await this._post<{ rows: Array<{ key: string; value: string }>; next_after?: string }>(\n endpoint,\n body,\n );\n for (const r of data.rows ?? []) out.push([b64ToBytes(r.key), b64ToBytes(r.value)]);\n if (!data.next_after) break;\n afterKey = data.next_after;\n }\n return out;\n }\n\n // --- HTTP plumbing ---\n\n private async _post<T = Record<string, unknown>>(\n endpoint: string,\n body: Record<string, unknown>,\n ): Promise<T> {\n const url = `${this._baseUrl}/${endpoint}`;\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (this._token) headers[\"Authorization\"] = `Bearer ${this._token}`;\n // The Worker routes on shard_key (idFromName) and rejects requests without\n // one — always splice it in.\n const payload = JSON.stringify({ ...body, shard_key: this._shardKey });\n\n let lastErr: unknown;\n // One retry on transport-level failures, matching the python client.\n for (let attempt = 0; attempt < 2; attempt++) {\n let resp: Response;\n try {\n resp = await this._fetch(url, { method: \"POST\", headers, body: payload });\n } catch (err) {\n lastErr = err;\n continue;\n }\n\n let data: any;\n try {\n data = await resp.json();\n } catch {\n if (!resp.ok) {\n throw new Error(`CF DO storage error ${resp.status} on ${endpoint}: <non-json body>`);\n }\n return {} as T;\n }\n\n if (resp.status === 404 && data?.error === \"unknown_invocation\") {\n throw new UnknownInvocationError(\n data.message ??\n \"Invocation is not registered. Call queuePush first to register the invocation.\",\n );\n }\n if (resp.status === 401) {\n throw new Error(`Authentication failed: ${data?.error ?? \"unauthorized\"}`);\n }\n if (!resp.ok) {\n throw new Error(`CF DO storage error ${resp.status} on ${endpoint}: ${JSON.stringify(data)}`);\n }\n return data as T;\n }\n throw lastErr instanceof Error\n ? lastErr\n : new Error(`CF DO storage transport error on ${endpoint}: ${String(lastErr)}`);\n }\n}\n\n/** Fresh 32-char lowercase-hex idempotency token (the DO's attempt_id shape). */\nfunction newAttemptId(): string {\n const b = new Uint8Array(16);\n crypto.getRandomValues(b);\n let s = \"\";\n for (let i = 0; i < 16; i++) s += b[i].toString(16).padStart(2, \"0\");\n return s;\n}\n\n/** Encode an int64 worker/group id as an 8-byte big-endian state key. */\nfunction int64Key(v: number): Uint8Array {\n const b = new Uint8Array(8);\n new DataView(b.buffer).setBigInt64(0, BigInt(v), false);\n return b;\n}\n\nfunction int64FromKey(b: Uint8Array): number {\n if (b.length !== 8) return 0;\n return Number(new DataView(b.buffer, b.byteOffset, 8).getBigInt64(0, false));\n}\n\nfunction bytesToB64(buf: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < buf.length; i++) binary += String.fromCharCode(buf[i]);\n return btoa(binary);\n}\n\nfunction b64ToBytes(b64: string): Uint8Array {\n const binary = atob(b64);\n const out = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i);\n return out;\n}\n",
|
|
6
|
-
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Storage for VGI function state.\n// Provides shared state across worker processes for distributed execution.\n// Port of vgi-python's vgi/function_storage.py.\n//\n// The interface is async so HTTP-backed implementations (Cloudflare DO,\n// Azure SQL, etc.) can use fetch/network drivers without sync hacks.\n// FunctionStorageSqlite wraps bun:sqlite's sync calls in resolved promises.\n\n// FunctionStorageSqlite is the only thing in this module that needs Bun + node:*\n// modules. Workers (Cloudflare workerd / browsers) should use\n// FunctionStorageCfDo (HTTP-backed) instead — they never reach this class.\n// We resolve all node:* and bun:* dependencies through indirect string\n// variables that esbuild can't trace statically, so workerd bundles cleanly\n// without nodejs_compat polyfills for paths we never run.\ntype Database = any;\nconst _BUN_SQLITE_MOD = \"bun:sqlite\";\nconst _NODE_OS_MOD = \"node:os\";\nconst _NODE_PATH_MOD = \"node:path\";\nconst _NODE_FS_MOD = \"node:fs\";\nlet _Database: any = null;\nfunction _req(): any {\n const req: any = (import.meta as any).require ?? (globalThis as any).require ?? null;\n if (!req) {\n throw new Error(\n \"FunctionStorageSqlite requires Node.js or Bun (bun:sqlite + node:os/path/fs). \" +\n \"Use FunctionStorageCfDo on non-Bun runtimes.\",\n );\n }\n return req;\n}\nfunction _loadDatabase(): any {\n if (_Database) return _Database;\n try {\n _Database = _req()(_BUN_SQLITE_MOD).Database;\n return _Database;\n } catch (e: any) {\n throw new Error(\n `FunctionStorageSqlite: failed to load bun:sqlite — ${e?.message ?? e}`,\n );\n }\n}\nfunction _loadNodeIo(): {\n homedir: () => string;\n platform: () => string;\n join: (...parts: string[]) => string;\n mkdirSync: (path: string, opts?: any) => void;\n} {\n const r = _req();\n return {\n homedir: r(_NODE_OS_MOD).homedir,\n platform: r(_NODE_OS_MOD).platform,\n join: r(_NODE_PATH_MOD).join,\n mkdirSync: r(_NODE_FS_MOD).mkdirSync,\n };\n}\n\n// ============================================================================\n// Errors\n// ============================================================================\n\nexport class UnknownInvocationError extends Error {\n constructor(message?: string | Uint8Array) {\n let text: string;\n if (message instanceof Uint8Array) {\n text =\n `Invocation ${hexEncode(message)} is not registered. ` +\n \"Call queuePush first to register the invocation.\";\n } else {\n text =\n message ??\n \"Invocation is not registered. Call queuePush first to register the invocation.\";\n }\n super(text);\n this.name = \"UnknownInvocationError\";\n }\n}\n\nfunction hexEncode(buf: Uint8Array): string {\n return Array.from(buf, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\n// ============================================================================\n// FunctionStorage interface\n// ============================================================================\n\nexport interface FunctionStorage {\n workerPut(executionId: Uint8Array, workerId: number, state: Uint8Array): Promise<void>;\n workerCollect(executionId: Uint8Array): Promise<Uint8Array[]>;\n workerScan(executionId: Uint8Array): Promise<Array<[number, Uint8Array]>>;\n queuePush(executionId: Uint8Array, items: Uint8Array[]): Promise<number>;\n queuePop(executionId: Uint8Array): Promise<Uint8Array | null>;\n queueClear(executionId: Uint8Array): Promise<number>;\n // --- Namespaced key/value state (scoped by execution_id) ---\n stateGet(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array): Promise<Uint8Array | null>;\n statePut(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, value: Uint8Array): Promise<void>;\n // --- Append-only log (scoped by execution_id) ---\n stateAppend(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, item: Uint8Array): Promise<number>;\n stateLogScan(\n scopeId: Uint8Array,\n ns: Uint8Array,\n key: Uint8Array,\n afterId?: number,\n limit?: number | null,\n ): Promise<Array<[number, Uint8Array]>>;\n /** Wipe all state + log rows for a scope across every namespace. */\n executionClear(scopeId: Uint8Array): Promise<number>;\n /** Optional cleanup hook. Implementations holding a connection should release it here. */\n close?(): Promise<void> | void;\n}\n\n// FrameworkNS — namespaces the framework itself uses (mirrors Python's\n// FrameworkNS enum). User code picks its own arbitrary namespace bytes.\nexport const FrameworkNS = {\n BUFFERING_INIT: textBytes(\"_vgi/buffering_init\"),\n STREAMING_FINALIZE: textBytes(\"_vgi/streaming_finalize\"),\n} as const;\n\nfunction textBytes(s: string): Uint8Array {\n return new TextEncoder().encode(s);\n}\n\n/** Encode an int as 8-byte little-endian, matching Python's pack_int_key. */\nexport function packIntKey(i: number | bigint): Uint8Array {\n const buf = new ArrayBuffer(8);\n new DataView(buf).setBigInt64(0, BigInt(i), true);\n return new Uint8Array(buf);\n}\n\n// ============================================================================\n// FunctionStorageSqlite\n// ============================================================================\n\nfunction getDefaultDbPath(): string {\n // VGI_WORKER_SQLITE_PATH=\":memory:\" picks an in-process backend used by\n // single-process test fixtures (notably the HTTP server fixture) to avoid\n // per-op WAL fsync cost. Mirrors vgi-python's same env var.\n const override = process.env.VGI_WORKER_SQLITE_PATH;\n if (override) return override;\n const { homedir, platform, join, mkdirSync } = _loadNodeIo();\n const home = homedir();\n const stateDir =\n platform() === \"darwin\"\n ? join(home, \"Library\", \"Application Support\", \"vgi\")\n : join(home, \".local\", \"state\", \"vgi\");\n mkdirSync(stateDir, { recursive: true });\n return join(stateDir, \"vgi_storage.db\");\n}\n\n// Worker state rides the unified function_state table under a reserved\n// namespace, keyed by the worker/process id (8-byte big-endian) — exactly the\n// mapping the Cloudflare DO client uses, so both backends share one schema.\nconst NS_WORKER = new TextEncoder().encode(\"worker\");\n\n/** Encode an int64 worker id as an 8-byte big-endian state key. */\nfunction int64Key(v: number): Uint8Array {\n const b = new Uint8Array(8);\n new DataView(b.buffer).setBigInt64(0, BigInt(v), false);\n return b;\n}\n\nfunction int64FromKey(b: Uint8Array): number {\n if (b.length !== 8) return 0;\n return Number(new DataView(b.buffer, b.byteOffset, 8).getBigInt64(0, false));\n}\n\nexport class FunctionStorageSqlite implements FunctionStorage {\n readonly dbPath: string;\n private _db: Database;\n\n constructor(dbPath?: string) {\n this.dbPath = dbPath ?? getDefaultDbPath();\n // Persistent connection for the lifetime of this storage instance.\n // Bun is single-threaded, so one connection is the analogue of\n // Python's per-thread persistent connection. WAL still coordinates\n // writes across processes via file locking.\n const Db = _loadDatabase();\n this._db = new Db(this.dbPath);\n this._db.exec(\"PRAGMA journal_mode=WAL\");\n this._db.exec(\"PRAGMA synchronous=NORMAL\");\n this._db.exec(\"PRAGMA busy_timeout=30000\");\n this._db.exec(\"PRAGMA temp_store=MEMORY\");\n this._db.exec(\"PRAGMA cache_size=-65536\");\n this._ensureTables();\n }\n\n close(): void {\n this._db.close();\n }\n\n private _ensureTables(): void {\n const db = this._db;\n // Self-heal an older on-disk DB to the unified minimal schema. The local\n // SQLite tier carries none of the DO's HTTP idempotency machinery and no\n // created_at, so drop any table left over with those columns; all of this\n // is ephemeral in-progress state, so dropping + recreating is safe.\n for (const [table, staleCol] of [\n [\"function_state\", \"created_at\"],\n [\"function_state_log\", \"created_at\"],\n [\"work_queue\", \"created_at\"],\n ] as const) {\n const info = db.prepare(`PRAGMA table_info(${table})`).all() as Array<{ name: string }>;\n if (info.some((row) => row.name === staleCol)) {\n db.exec(`DROP TABLE IF EXISTS ${table}`);\n }\n }\n // Tables eliminated by the unified schema: worker collect now rides\n // function_state (ns=worker), and the queue carries no registration.\n for (const dead of [\"global_state_storage\", \"worker_state\", \"invocation_registry\", \"init_storage\"]) {\n db.exec(`DROP TABLE IF EXISTS ${dead}`);\n }\n\n // Unified schema — the same three tables every backend uses (the Durable\n // Object adds an HTTP-idempotency column layer on top).\n db.exec(`\n CREATE TABLE IF NOT EXISTS work_queue (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n execution_id BLOB NOT NULL,\n work_item BLOB NOT NULL\n )\n `);\n db.exec(`\n CREATE INDEX IF NOT EXISTS idx_work_queue_execution\n ON work_queue(execution_id, id)\n `);\n // Composite-key K/V over (scope_id, ns, key): the single home for\n // per-execution / per-transaction / per-group / per-worker state.\n db.exec(`\n CREATE TABLE IF NOT EXISTS function_state (\n scope_id BLOB NOT NULL,\n ns BLOB NOT NULL,\n key BLOB NOT NULL,\n value BLOB NOT NULL,\n PRIMARY KEY (scope_id, ns, key)\n )\n `);\n // Append-only log keyed by (scope, ns, key); the AUTOINCREMENT id is the\n // globally-monotonic scan cursor.\n db.exec(`\n CREATE TABLE IF NOT EXISTS function_state_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n scope_id BLOB NOT NULL,\n ns BLOB NOT NULL,\n key BLOB NOT NULL,\n value BLOB NOT NULL\n )\n `);\n db.exec(`\n CREATE INDEX IF NOT EXISTS idx_function_state_log_lookup\n ON function_state_log(scope_id, ns, key, id)\n `);\n }\n\n async stateGet(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array): Promise<Uint8Array | null> {\n const row = this._db\n .prepare(\"SELECT value FROM function_state WHERE scope_id = ? AND ns = ? AND key = ?\")\n .get(bufferArg(scopeId), bufferArg(ns), bufferArg(key)) as { value: Uint8Array } | null;\n return row ? new Uint8Array(row.value) : null;\n }\n\n async statePut(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, value: Uint8Array): Promise<void> {\n this._db\n .prepare(\n \"INSERT OR REPLACE INTO function_state (scope_id, ns, key, value) VALUES (?, ?, ?, ?)\",\n )\n .run(bufferArg(scopeId), bufferArg(ns), bufferArg(key), bufferArg(value));\n }\n\n async stateAppend(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, item: Uint8Array): Promise<number> {\n const res = this._db\n .prepare(\"INSERT INTO function_state_log (scope_id, ns, key, value) VALUES (?, ?, ?, ?)\")\n .run(bufferArg(scopeId), bufferArg(ns), bufferArg(key), bufferArg(item));\n return Number(res.lastInsertRowid);\n }\n\n async stateLogScan(\n scopeId: Uint8Array,\n ns: Uint8Array,\n key: Uint8Array,\n afterId: number = -1,\n limit: number | null = null,\n ): Promise<Array<[number, Uint8Array]>> {\n let sql =\n \"SELECT id, value FROM function_state_log \" +\n \"WHERE scope_id = ? AND ns = ? AND key = ? AND id > ? ORDER BY id ASC\";\n const args: any[] = [bufferArg(scopeId), bufferArg(ns), bufferArg(key), afterId];\n if (limit != null) {\n sql += \" LIMIT ?\";\n args.push(limit);\n }\n const rows = this._db.prepare(sql).all(...args) as Array<{ id: number; value: Uint8Array }>;\n return rows.map((r) => [Number(r.id), new Uint8Array(r.value)]);\n }\n\n async executionClear(scopeId: Uint8Array): Promise<number> {\n const eid = bufferArg(scopeId);\n let total = 0;\n total += (this._db.prepare(\"DELETE FROM function_state WHERE scope_id = ?\").run(eid).changes as number);\n total += (this._db.prepare(\"DELETE FROM function_state_log WHERE scope_id = ?\").run(eid).changes as number);\n return total;\n }\n\n // Worker state rides function_state under ns=worker, keyed by worker id.\n\n async workerPut(\n executionId: Uint8Array,\n workerId: number,\n state: Uint8Array\n ): Promise<void> {\n this._db\n .prepare(\n \"INSERT OR REPLACE INTO function_state (scope_id, ns, key, value) VALUES (?, ?, ?, ?)\"\n )\n .run(bufferArg(executionId), bufferArg(NS_WORKER), bufferArg(int64Key(workerId)), bufferArg(state));\n }\n\n async workerCollect(executionId: Uint8Array): Promise<Uint8Array[]> {\n const rows = this._db\n .prepare(\n \"DELETE FROM function_state WHERE scope_id = ? AND ns = ? RETURNING value\"\n )\n .all(bufferArg(executionId), bufferArg(NS_WORKER)) as Array<{ value: Uint8Array }>;\n return rows.map((row) => new Uint8Array(row.value));\n }\n\n async workerScan(executionId: Uint8Array): Promise<Array<[number, Uint8Array]>> {\n const rows = this._db\n .prepare(\n \"SELECT key, value FROM function_state WHERE scope_id = ? AND ns = ?\"\n )\n .all(bufferArg(executionId), bufferArg(NS_WORKER)) as Array<{\n key: Uint8Array;\n value: Uint8Array;\n }>;\n return rows.map((row) => [int64FromKey(new Uint8Array(row.key)), new Uint8Array(row.value)]);\n }\n\n async queuePush(executionId: Uint8Array, items: Uint8Array[]): Promise<number> {\n const eidBuf = bufferArg(executionId);\n this._db.exec(\"BEGIN\");\n try {\n const insert = this._db.prepare(\n \"INSERT INTO work_queue (execution_id, work_item) VALUES (?, ?)\"\n );\n for (const item of items) {\n insert.run(eidBuf, bufferArg(item));\n }\n this._db.exec(\"COMMIT\");\n } catch (e) {\n this._db.exec(\"ROLLBACK\");\n throw e;\n }\n return items.length;\n }\n\n async queuePop(executionId: Uint8Array): Promise<Uint8Array | null> {\n // No registration: an empty or never-pushed queue both return null,\n // matching the Durable Object.\n const row = this._db\n .prepare(\n \"DELETE FROM work_queue WHERE id = (\" +\n \" SELECT id FROM work_queue WHERE execution_id = ? ORDER BY id ASC LIMIT 1\" +\n \") RETURNING work_item\"\n )\n .get(bufferArg(executionId)) as { work_item: Uint8Array } | null;\n\n return row ? new Uint8Array(row.work_item) : null;\n }\n\n async queueClear(executionId: Uint8Array): Promise<number> {\n return this._db\n .prepare(\"DELETE FROM work_queue WHERE execution_id = ?\")\n .run(bufferArg(executionId)).changes;\n }\n}\n\n// ============================================================================\n// BoundStorage\n// ============================================================================\n\nexport class BoundStorage {\n private _base: FunctionStorage;\n private _executionId: Uint8Array;\n\n constructor(storage: FunctionStorage, executionId: Uint8Array) {\n this._base = storage;\n this._executionId = executionId;\n }\n\n put(state: Uint8Array): Promise<void> {\n return this._base.workerPut(this._executionId, process.pid, state);\n }\n\n collect(): Promise<Uint8Array[]> {\n return this._base.workerCollect(this._executionId);\n }\n\n workerScan(): Promise<Array<[number, Uint8Array]>> {\n return this._base.workerScan(this._executionId);\n }\n\n queuePush(items: Uint8Array[]): Promise<number> {\n return this._base.queuePush(this._executionId, items);\n }\n\n queuePop(): Promise<Uint8Array | null> {\n return this._base.queuePop(this._executionId);\n }\n\n queueClear(): Promise<number> {\n return this._base.queueClear(this._executionId);\n }\n\n stateGet(ns: Uint8Array, key: Uint8Array): Promise<Uint8Array | null> {\n return this._base.stateGet(this._executionId, ns, key);\n }\n\n statePut(ns: Uint8Array, key: Uint8Array, value: Uint8Array): Promise<void> {\n return this._base.statePut(this._executionId, ns, key, value);\n }\n\n stateAppend(ns: Uint8Array, key: Uint8Array, item: Uint8Array): Promise<number> {\n return this._base.stateAppend(this._executionId, ns, key, item);\n }\n\n stateLogScan(\n ns: Uint8Array,\n key: Uint8Array,\n afterId: number = -1,\n limit: number | null = null,\n ): Promise<Array<[number, Uint8Array]>> {\n return this._base.stateLogScan(this._executionId, ns, key, afterId, limit);\n }\n\n executionClear(): Promise<number> {\n return this._base.executionClear(this._executionId);\n }\n\n static packIntKey(i: number | bigint): Uint8Array {\n return packIntKey(i);\n }\n}\n\n// ============================================================================\n// Backend factory + lazy default storage\n// ============================================================================\n\n/**\n * Resolve the FunctionStorage backend from environment variables.\n *\n * Mirrors vgi-python's `_resolve_storage` in `vgi/function.py`.\n *\n * `VGI_WORKER_SHARED_STORAGE` selects the backend (default: `sqlite`):\n * - `memory` — `FunctionStorageSqlite` at `:memory:`. Process-local\n * with no cross-process coordination — single-process\n * deployments only. Ignores `VGI_WORKER_SQLITE_PATH`.\n * - `sqlite` — `FunctionStorageSqlite`. Honors `VGI_WORKER_SQLITE_PATH`\n * (including `:memory:`).\n * - `cloudflare-do` — `FunctionStorageCfDo`. Requires `VGI_CF_DO_URL`;\n * optional `VGI_CF_DO_TOKEN` for bearer auth.\n */\nexport function resolveStorageFromEnv(): FunctionStorage {\n const backend = (process.env.VGI_WORKER_SHARED_STORAGE ?? \"sqlite\").toLowerCase();\n if (backend === \"memory\") {\n return new FunctionStorageSqlite(\":memory:\");\n }\n if (backend === \"sqlite\") {\n return new FunctionStorageSqlite();\n }\n if (backend === \"cloudflare-do\") {\n // Lazy require to avoid loading the CF client when sqlite is in use.\n const { FunctionStorageCfDo } = require(\"./storage-cf-do.js\") as typeof import(\"./storage-cf-do.js\");\n return FunctionStorageCfDo.fromEnv();\n }\n throw new Error(\n `Unknown VGI_WORKER_SHARED_STORAGE backend: '${backend}'. Supported: 'memory', 'sqlite', 'cloudflare-do'.`,\n );\n}\n\n// Module-level proxy that lazy-resolves the configured backend on first use.\n// Importing this module no longer opens a SQLite connection — that happens\n// the first time anyone touches a storage method. Matches Python's\n// _DefaultStorageDescriptor lazy attribute pattern.\nlet _resolved: FunctionStorage | null = null;\nfunction getDefaultStorage(): FunctionStorage {\n if (_resolved == null) _resolved = resolveStorageFromEnv();\n return _resolved;\n}\n\n/**\n * Override the default backend used by the `storage` singleton. Call once at\n * worker startup to inject a pre-built backend that env-driven selection can't\n * construct — notably a `FunctionStorageCfDo` wired to a Cloudflare\n * service-binding Fetcher (the binding lives on `env`, not `process.env`, and a\n * same-zone public-URL fetch is rejected with CF error 1042). Takes precedence\n * over `VGI_WORKER_SHARED_STORAGE`.\n */\nexport function setStorage(impl: FunctionStorage): void {\n _resolved = impl;\n}\n\n/** Default FunctionStorage instance. Backend is selected via env on first access. */\nexport const storage: FunctionStorage = new Proxy(\n {} as FunctionStorage,\n {\n get(_t, prop, _r) {\n const inst = getDefaultStorage() as any;\n const v = inst[prop];\n return typeof v === \"function\" ? v.bind(inst) : v;\n },\n },\n);\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/** bun:sqlite needs Buffer for blob params */\nfunction bufferArg(data: Uint8Array): Buffer {\n return Buffer.from(data.buffer, data.byteOffset, data.byteLength);\n}\n",
|
|
5
|
+
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Cloudflare Durable Object storage for VGI function state.\n//\n// Port of vgi-python's vgi/function_storage_cf_do.py. Talks the Cloudflare\n// Worker + Durable Object's unified state_* / queue_* protocol\n// (vgi-cloudflare-durable-object-storage/src/index.ts). Every request carries\n// the per-attach `shard_key` (set via forShard); destructive ops carry a fresh\n// 32-hex `attempt_id`. The DO is single-threaded SQLite, so ops are atomic.\n//\n// Usage:\n// Set `VGI_WORKER_SHARED_STORAGE=cloudflare-do` plus `VGI_CF_DO_URL`.\n// Optionally set `VGI_CF_DO_TOKEN` for bearer auth.\n\nimport type { FunctionStorage, WorkerStateKey } from \"./storage.js\";\nimport { UnknownInvocationError, workerStateKey } from \"./storage.js\";\n\n/** Minimal fetch signature satisfied by both the global `fetch` and a\n * Cloudflare service-binding Fetcher (`env.<BINDING>`). */\nexport type FetchLike = (\n input: string,\n init?: { method?: string; headers?: Record<string, string>; body?: string },\n) => Promise<Response>;\n\n// Namespaces under the unified state_* table for the legacy worker/queue\n// families the DO no longer has dedicated endpoints for.\nconst NS_WORKER = new TextEncoder().encode(\"worker\");\n\nexport class FunctionStorageCfDo implements FunctionStorage {\n private readonly _baseUrl: string;\n private readonly _token: string | null;\n /** Per-attach routing key (att-<hex uuid>); \"\" until pinned via forShard. */\n private readonly _shardKey: string;\n /** Fetch implementation. Defaults to the global `fetch`; pass a Cloudflare\n * service-binding Fetcher (env.<BINDING>) when the storage worker lives on\n * the same account/zone — a same-zone public-URL fetch is rejected (CF\n * error 1042), but a service binding routes worker-to-worker directly. */\n private readonly _fetch: FetchLike;\n\n constructor(opts: {\n url: string;\n token?: string | null;\n shardKey?: string;\n fetch?: FetchLike;\n }) {\n // Strip trailing slash so endpoint paths can be appended unconditionally.\n this._baseUrl = opts.url.replace(/\\/+$/, \"\");\n this._token = opts.token ?? null;\n this._shardKey = opts.shardKey ?? \"\";\n this._fetch = opts.fetch ?? ((input, init) => fetch(input as any, init));\n }\n\n /** Build an instance from environment variables. */\n static fromEnv(): FunctionStorageCfDo {\n const url = process.env.VGI_CF_DO_URL;\n if (!url) {\n throw new Error(\n \"VGI_CF_DO_URL environment variable is required when \" +\n \"VGI_WORKER_SHARED_STORAGE=cloudflare-do\",\n );\n }\n return new FunctionStorageCfDo({\n url,\n token: process.env.VGI_CF_DO_TOKEN || null,\n });\n }\n\n /**\n * Return a view of this backend pinned to one shard key, so callers can route\n * per logical ATTACH. Shares the URL/token; only the shard key differs.\n */\n forShard(shardKey: string): FunctionStorageCfDo {\n return new FunctionStorageCfDo({\n url: this._baseUrl,\n token: this._token,\n shardKey,\n fetch: this._fetch,\n });\n }\n\n // --- Worker state → ns=worker, key = substream_id bytes, or int64(worker_id) ---\n\n async workerPut(executionId: Uint8Array, worker: WorkerStateKey, state: Uint8Array): Promise<void> {\n await this._statePutMany(executionId, NS_WORKER, [[workerStateKey(worker), state]]);\n }\n\n async workerCollect(executionId: Uint8Array): Promise<Uint8Array[]> {\n const rows = await this._statePaged(\"state_drain\", executionId, NS_WORKER, newAttemptId());\n return rows.map(([, v]) => v);\n }\n\n async workerScan(executionId: Uint8Array): Promise<Array<[number, Uint8Array]>> {\n const rows = await this._statePaged(\"state_scan\", executionId, NS_WORKER, null);\n return rows.map(([k, v]) => [int64FromKey(k), v]);\n }\n\n // --- Work queue ---\n\n async queuePush(executionId: Uint8Array, items: Uint8Array[]): Promise<number> {\n const data = await this._post<{ count: number }>(\"queue_push\", {\n execution_id: bytesToB64(executionId),\n items: items.map(bytesToB64),\n attempt_id: newAttemptId(),\n });\n return Number(data.count);\n }\n\n async queuePop(executionId: Uint8Array): Promise<Uint8Array | null> {\n const data = await this._post<{ item: string | null }>(\"queue_pop\", {\n execution_id: bytesToB64(executionId),\n attempt_id: newAttemptId(),\n });\n return data.item ? b64ToBytes(data.item) : null;\n }\n\n async queueClear(executionId: Uint8Array): Promise<number> {\n const data = await this._post<{ cleared: number }>(\"queue_clear\", {\n execution_id: bytesToB64(executionId),\n attempt_id: newAttemptId(),\n });\n return Number(data.cleared);\n }\n\n // --- Namespaced key/value state ---\n\n async stateGet(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array): Promise<Uint8Array | null> {\n const data = await this._post<{ rows: Array<{ value: string } | null> }>(\"state_get_many\", {\n scope_id: bytesToB64(scopeId),\n ns: bytesToB64(ns),\n keys: [bytesToB64(key)],\n });\n const row = (data.rows ?? [])[0];\n return row ? b64ToBytes(row.value) : null;\n }\n\n async statePut(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, value: Uint8Array): Promise<void> {\n await this._statePutMany(scopeId, ns, [[key, value]]);\n }\n\n // --- Append-only log ---\n\n async stateAppend(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, item: Uint8Array): Promise<number> {\n const data = await this._post<{ ordinal: number }>(\"state_append\", {\n scope_id: bytesToB64(scopeId),\n ns: bytesToB64(ns),\n key: bytesToB64(key),\n item: bytesToB64(item),\n attempt_id: newAttemptId(),\n });\n return Number(data.ordinal);\n }\n\n async stateLogScan(\n scopeId: Uint8Array,\n ns: Uint8Array,\n key: Uint8Array,\n afterId: number = -1,\n limit: number | null = null,\n ): Promise<Array<[number, Uint8Array]>> {\n const body: Record<string, unknown> = {\n scope_id: bytesToB64(scopeId),\n ns: bytesToB64(ns),\n key: bytesToB64(key),\n after_id: afterId,\n };\n if (limit != null && limit > 0) body.limit = limit;\n const data = await this._post<{ rows: Array<{ id: number; value: string }> }>(\"state_log_scan\", body);\n return (data.rows ?? []).map((r) => [Number(r.id), b64ToBytes(r.value)]);\n }\n\n async executionClear(scopeId: Uint8Array): Promise<number> {\n const data = await this._post<{ deleted: number }>(\"execution_clear\", {\n scope_id: bytesToB64(scopeId),\n attempt_id: newAttemptId(),\n });\n return Number(data.deleted);\n }\n\n // --- unified state_* helpers ---\n\n private async _statePutMany(\n scopeId: Uint8Array,\n ns: Uint8Array,\n items: Array<[Uint8Array, Uint8Array]>,\n ): Promise<void> {\n await this._post(\"state_put_many\", {\n scope_id: bytesToB64(scopeId),\n ns: bytesToB64(ns),\n items: items.map(([k, v]) => ({ key: bytesToB64(k), value: bytesToB64(v) })),\n attempt_id: newAttemptId(),\n });\n }\n\n /** Drive state_scan / state_drain across pages. attemptId is null for scan. */\n private async _statePaged(\n endpoint: string,\n scopeId: Uint8Array,\n ns: Uint8Array,\n attemptId: string | null,\n ): Promise<Array<[Uint8Array, Uint8Array]>> {\n const out: Array<[Uint8Array, Uint8Array]> = [];\n let afterKey: string | undefined;\n for (;;) {\n const body: Record<string, unknown> = { scope_id: bytesToB64(scopeId), ns: bytesToB64(ns) };\n if (afterKey != null) body.after_key = afterKey;\n if (attemptId != null) body.attempt_id = attemptId;\n const data = await this._post<{ rows: Array<{ key: string; value: string }>; next_after?: string }>(\n endpoint,\n body,\n );\n for (const r of data.rows ?? []) out.push([b64ToBytes(r.key), b64ToBytes(r.value)]);\n if (!data.next_after) break;\n afterKey = data.next_after;\n }\n return out;\n }\n\n // --- HTTP plumbing ---\n\n private async _post<T = Record<string, unknown>>(\n endpoint: string,\n body: Record<string, unknown>,\n ): Promise<T> {\n const url = `${this._baseUrl}/${endpoint}`;\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (this._token) headers[\"Authorization\"] = `Bearer ${this._token}`;\n // The Worker routes on shard_key (idFromName) and rejects requests without\n // one — always splice it in.\n const payload = JSON.stringify({ ...body, shard_key: this._shardKey });\n\n let lastErr: unknown;\n // One retry on transport-level failures, matching the python client.\n for (let attempt = 0; attempt < 2; attempt++) {\n let resp: Response;\n try {\n resp = await this._fetch(url, { method: \"POST\", headers, body: payload });\n } catch (err) {\n lastErr = err;\n continue;\n }\n\n let data: any;\n try {\n data = await resp.json();\n } catch {\n if (!resp.ok) {\n throw new Error(`CF DO storage error ${resp.status} on ${endpoint}: <non-json body>`);\n }\n return {} as T;\n }\n\n if (resp.status === 404 && data?.error === \"unknown_invocation\") {\n throw new UnknownInvocationError(\n data.message ??\n \"Invocation is not registered. Call queuePush first to register the invocation.\",\n );\n }\n if (resp.status === 401) {\n throw new Error(`Authentication failed: ${data?.error ?? \"unauthorized\"}`);\n }\n if (!resp.ok) {\n throw new Error(`CF DO storage error ${resp.status} on ${endpoint}: ${JSON.stringify(data)}`);\n }\n return data as T;\n }\n throw lastErr instanceof Error\n ? lastErr\n : new Error(`CF DO storage transport error on ${endpoint}: ${String(lastErr)}`);\n }\n}\n\n/** Fresh 32-char lowercase-hex idempotency token (the DO's attempt_id shape). */\nfunction newAttemptId(): string {\n const b = new Uint8Array(16);\n crypto.getRandomValues(b);\n let s = \"\";\n for (let i = 0; i < 16; i++) s += b[i].toString(16).padStart(2, \"0\");\n return s;\n}\n\n/** Decode an 8-byte big-endian state key to its int64 worker id; any other\n * key (a substream id) has none, and decodes to 0. */\nfunction int64FromKey(b: Uint8Array): number {\n if (b.length !== 8) return 0;\n return Number(new DataView(b.buffer, b.byteOffset, 8).getBigInt64(0, false));\n}\n\nfunction bytesToB64(buf: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < buf.length; i++) binary += String.fromCharCode(buf[i]);\n return btoa(binary);\n}\n\nfunction b64ToBytes(b64: string): Uint8Array {\n const binary = atob(b64);\n const out = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i);\n return out;\n}\n",
|
|
6
|
+
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Storage for VGI function state.\n// Provides shared state across worker processes for distributed execution.\n// Port of vgi-python's vgi/function_storage.py.\n//\n// The interface is async so HTTP-backed implementations (Cloudflare DO,\n// Azure SQL, etc.) can use fetch/network drivers without sync hacks.\n// FunctionStorageSqlite wraps bun:sqlite's sync calls in resolved promises.\n\n// FunctionStorageSqlite is the only thing in this module that needs Bun + node:*\n// modules. Workers (Cloudflare workerd / browsers) should use\n// FunctionStorageCfDo (HTTP-backed) instead — they never reach this class.\n// We resolve all node:* and bun:* dependencies through indirect string\n// variables that esbuild can't trace statically, so workerd bundles cleanly\n// without nodejs_compat polyfills for paths we never run.\ntype Database = any;\nconst _BUN_SQLITE_MOD = \"bun:sqlite\";\nconst _NODE_OS_MOD = \"node:os\";\nconst _NODE_PATH_MOD = \"node:path\";\nconst _NODE_FS_MOD = \"node:fs\";\nlet _Database: any = null;\nfunction _req(): any {\n const req: any = (import.meta as any).require ?? (globalThis as any).require ?? null;\n if (!req) {\n throw new Error(\n \"FunctionStorageSqlite requires Node.js or Bun (bun:sqlite + node:os/path/fs). \" +\n \"Use FunctionStorageCfDo on non-Bun runtimes.\",\n );\n }\n return req;\n}\nfunction _loadDatabase(): any {\n if (_Database) return _Database;\n try {\n _Database = _req()(_BUN_SQLITE_MOD).Database;\n return _Database;\n } catch (e: any) {\n throw new Error(\n `FunctionStorageSqlite: failed to load bun:sqlite — ${e?.message ?? e}`,\n );\n }\n}\nfunction _loadNodeIo(): {\n homedir: () => string;\n platform: () => string;\n join: (...parts: string[]) => string;\n mkdirSync: (path: string, opts?: any) => void;\n} {\n const r = _req();\n return {\n homedir: r(_NODE_OS_MOD).homedir,\n platform: r(_NODE_OS_MOD).platform,\n join: r(_NODE_PATH_MOD).join,\n mkdirSync: r(_NODE_FS_MOD).mkdirSync,\n };\n}\n\n// ============================================================================\n// Errors\n// ============================================================================\n\nexport class UnknownInvocationError extends Error {\n constructor(message?: string | Uint8Array) {\n let text: string;\n if (message instanceof Uint8Array) {\n text =\n `Invocation ${hexEncode(message)} is not registered. ` +\n \"Call queuePush first to register the invocation.\";\n } else {\n text =\n message ??\n \"Invocation is not registered. Call queuePush first to register the invocation.\";\n }\n super(text);\n this.name = \"UnknownInvocationError\";\n }\n}\n\nfunction hexEncode(buf: Uint8Array): string {\n return Array.from(buf, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\n// ============================================================================\n// FunctionStorage interface\n// ============================================================================\n\n/**\n * Which slot of an execution's worker state a row occupies: a table-in-out\n * substream's client-minted `substream_id` (raw bytes), or -- only for a client\n * that sent none -- a numeric worker id, the process id (an int64 key). See\n * {@link BoundStorage.put}.\n */\nexport type WorkerStateKey = number | Uint8Array;\n\nexport interface FunctionStorage {\n /** Upsert `state` into the execution's worker-state slot `worker`. */\n workerPut(executionId: Uint8Array, worker: WorkerStateKey, state: Uint8Array): Promise<void>;\n /** Drain every worker-state slot of the execution, whatever its key. */\n workerCollect(executionId: Uint8Array): Promise<Uint8Array[]>;\n /** Read every worker-state slot without draining. A slot keyed by a\n * numeric worker id reports that id; one keyed by bytes (a substream id)\n * has none and reports 0. */\n workerScan(executionId: Uint8Array): Promise<Array<[number, Uint8Array]>>;\n queuePush(executionId: Uint8Array, items: Uint8Array[]): Promise<number>;\n queuePop(executionId: Uint8Array): Promise<Uint8Array | null>;\n queueClear(executionId: Uint8Array): Promise<number>;\n // --- Namespaced key/value state (scoped by execution_id) ---\n stateGet(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array): Promise<Uint8Array | null>;\n statePut(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, value: Uint8Array): Promise<void>;\n // --- Append-only log (scoped by execution_id) ---\n stateAppend(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, item: Uint8Array): Promise<number>;\n stateLogScan(\n scopeId: Uint8Array,\n ns: Uint8Array,\n key: Uint8Array,\n afterId?: number,\n limit?: number | null,\n ): Promise<Array<[number, Uint8Array]>>;\n /** Wipe all state + log rows for a scope across every namespace. */\n executionClear(scopeId: Uint8Array): Promise<number>;\n /** Optional cleanup hook. Implementations holding a connection should release it here. */\n close?(): Promise<void> | void;\n}\n\n// FrameworkNS — namespaces the framework itself uses (mirrors Python's\n// FrameworkNS enum). User code picks its own arbitrary namespace bytes.\nexport const FrameworkNS = {\n BUFFERING_INIT: textBytes(\"_vgi/buffering_init\"),\n STREAMING_FINALIZE: textBytes(\"_vgi/streaming_finalize\"),\n} as const;\n\nfunction textBytes(s: string): Uint8Array {\n return new TextEncoder().encode(s);\n}\n\n/** Encode an int as 8-byte little-endian, matching Python's pack_int_key. */\nexport function packIntKey(i: number | bigint): Uint8Array {\n const buf = new ArrayBuffer(8);\n new DataView(buf).setBigInt64(0, BigInt(i), true);\n return new Uint8Array(buf);\n}\n\n// ============================================================================\n// FunctionStorageSqlite\n// ============================================================================\n\nfunction getDefaultDbPath(): string {\n // VGI_WORKER_SQLITE_PATH=\":memory:\" picks an in-process backend used by\n // single-process test fixtures (notably the HTTP server fixture) to avoid\n // per-op WAL fsync cost. Mirrors vgi-python's same env var.\n const override = process.env.VGI_WORKER_SQLITE_PATH;\n if (override) return override;\n const { homedir, platform, join, mkdirSync } = _loadNodeIo();\n const home = homedir();\n const stateDir =\n platform() === \"darwin\"\n ? join(home, \"Library\", \"Application Support\", \"vgi\")\n : join(home, \".local\", \"state\", \"vgi\");\n mkdirSync(stateDir, { recursive: true });\n return join(stateDir, \"vgi_storage.db\");\n}\n\n// Worker state rides the unified function_state table under a reserved\n// namespace, keyed by the substream id (its raw bytes) or, for a client that\n// sent none, the worker/process id (8-byte big-endian) — exactly the mapping\n// the Cloudflare DO client uses, so both backends share one schema.\nconst NS_WORKER = new TextEncoder().encode(\"worker\");\n\n/** Encode an int64 worker id as an 8-byte big-endian state key. */\nfunction int64Key(v: number): Uint8Array {\n const b = new Uint8Array(8);\n new DataView(b.buffer).setBigInt64(0, BigInt(v), false);\n return b;\n}\n\n/** The state key for a worker-state slot: a substream id as-is, a numeric\n * worker id as an int64. */\nexport function workerStateKey(worker: WorkerStateKey): Uint8Array {\n return typeof worker === \"number\" ? int64Key(worker) : worker;\n}\n\nfunction int64FromKey(b: Uint8Array): number {\n if (b.length !== 8) return 0;\n return Number(new DataView(b.buffer, b.byteOffset, 8).getBigInt64(0, false));\n}\n\nexport class FunctionStorageSqlite implements FunctionStorage {\n readonly dbPath: string;\n private _db: Database;\n\n constructor(dbPath?: string) {\n this.dbPath = dbPath ?? getDefaultDbPath();\n // Persistent connection for the lifetime of this storage instance.\n // Bun is single-threaded, so one connection is the analogue of\n // Python's per-thread persistent connection. WAL still coordinates\n // writes across processes via file locking.\n const Db = _loadDatabase();\n this._db = new Db(this.dbPath);\n this._db.exec(\"PRAGMA journal_mode=WAL\");\n this._db.exec(\"PRAGMA synchronous=NORMAL\");\n this._db.exec(\"PRAGMA busy_timeout=30000\");\n this._db.exec(\"PRAGMA temp_store=MEMORY\");\n this._db.exec(\"PRAGMA cache_size=-65536\");\n this._ensureTables();\n }\n\n close(): void {\n this._db.close();\n }\n\n private _ensureTables(): void {\n const db = this._db;\n // Self-heal an older on-disk DB to the unified minimal schema. The local\n // SQLite tier carries none of the DO's HTTP idempotency machinery and no\n // created_at, so drop any table left over with those columns; all of this\n // is ephemeral in-progress state, so dropping + recreating is safe.\n for (const [table, staleCol] of [\n [\"function_state\", \"created_at\"],\n [\"function_state_log\", \"created_at\"],\n [\"work_queue\", \"created_at\"],\n ] as const) {\n const info = db.prepare(`PRAGMA table_info(${table})`).all() as Array<{ name: string }>;\n if (info.some((row) => row.name === staleCol)) {\n db.exec(`DROP TABLE IF EXISTS ${table}`);\n }\n }\n // Tables eliminated by the unified schema: worker collect now rides\n // function_state (ns=worker), and the queue carries no registration.\n for (const dead of [\"global_state_storage\", \"worker_state\", \"invocation_registry\", \"init_storage\"]) {\n db.exec(`DROP TABLE IF EXISTS ${dead}`);\n }\n\n // Unified schema — the same three tables every backend uses (the Durable\n // Object adds an HTTP-idempotency column layer on top).\n db.exec(`\n CREATE TABLE IF NOT EXISTS work_queue (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n execution_id BLOB NOT NULL,\n work_item BLOB NOT NULL\n )\n `);\n db.exec(`\n CREATE INDEX IF NOT EXISTS idx_work_queue_execution\n ON work_queue(execution_id, id)\n `);\n // Composite-key K/V over (scope_id, ns, key): the single home for\n // per-execution / per-transaction / per-group / per-worker state.\n db.exec(`\n CREATE TABLE IF NOT EXISTS function_state (\n scope_id BLOB NOT NULL,\n ns BLOB NOT NULL,\n key BLOB NOT NULL,\n value BLOB NOT NULL,\n PRIMARY KEY (scope_id, ns, key)\n )\n `);\n // Append-only log keyed by (scope, ns, key); the AUTOINCREMENT id is the\n // globally-monotonic scan cursor.\n db.exec(`\n CREATE TABLE IF NOT EXISTS function_state_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n scope_id BLOB NOT NULL,\n ns BLOB NOT NULL,\n key BLOB NOT NULL,\n value BLOB NOT NULL\n )\n `);\n db.exec(`\n CREATE INDEX IF NOT EXISTS idx_function_state_log_lookup\n ON function_state_log(scope_id, ns, key, id)\n `);\n }\n\n async stateGet(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array): Promise<Uint8Array | null> {\n const row = this._db\n .prepare(\"SELECT value FROM function_state WHERE scope_id = ? AND ns = ? AND key = ?\")\n .get(bufferArg(scopeId), bufferArg(ns), bufferArg(key)) as { value: Uint8Array } | null;\n return row ? new Uint8Array(row.value) : null;\n }\n\n async statePut(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, value: Uint8Array): Promise<void> {\n this._db\n .prepare(\n \"INSERT OR REPLACE INTO function_state (scope_id, ns, key, value) VALUES (?, ?, ?, ?)\",\n )\n .run(bufferArg(scopeId), bufferArg(ns), bufferArg(key), bufferArg(value));\n }\n\n async stateAppend(scopeId: Uint8Array, ns: Uint8Array, key: Uint8Array, item: Uint8Array): Promise<number> {\n const res = this._db\n .prepare(\"INSERT INTO function_state_log (scope_id, ns, key, value) VALUES (?, ?, ?, ?)\")\n .run(bufferArg(scopeId), bufferArg(ns), bufferArg(key), bufferArg(item));\n return Number(res.lastInsertRowid);\n }\n\n async stateLogScan(\n scopeId: Uint8Array,\n ns: Uint8Array,\n key: Uint8Array,\n afterId: number = -1,\n limit: number | null = null,\n ): Promise<Array<[number, Uint8Array]>> {\n let sql =\n \"SELECT id, value FROM function_state_log \" +\n \"WHERE scope_id = ? AND ns = ? AND key = ? AND id > ? ORDER BY id ASC\";\n const args: any[] = [bufferArg(scopeId), bufferArg(ns), bufferArg(key), afterId];\n if (limit != null) {\n sql += \" LIMIT ?\";\n args.push(limit);\n }\n const rows = this._db.prepare(sql).all(...args) as Array<{ id: number; value: Uint8Array }>;\n return rows.map((r) => [Number(r.id), new Uint8Array(r.value)]);\n }\n\n async executionClear(scopeId: Uint8Array): Promise<number> {\n const eid = bufferArg(scopeId);\n let total = 0;\n total += (this._db.prepare(\"DELETE FROM function_state WHERE scope_id = ?\").run(eid).changes as number);\n total += (this._db.prepare(\"DELETE FROM function_state_log WHERE scope_id = ?\").run(eid).changes as number);\n return total;\n }\n\n // Worker state rides function_state under ns=worker, keyed by substream id\n // or worker id.\n\n async workerPut(\n executionId: Uint8Array,\n worker: WorkerStateKey,\n state: Uint8Array\n ): Promise<void> {\n this._db\n .prepare(\n \"INSERT OR REPLACE INTO function_state (scope_id, ns, key, value) VALUES (?, ?, ?, ?)\"\n )\n .run(bufferArg(executionId), bufferArg(NS_WORKER), bufferArg(workerStateKey(worker)), bufferArg(state));\n }\n\n async workerCollect(executionId: Uint8Array): Promise<Uint8Array[]> {\n const rows = this._db\n .prepare(\n \"DELETE FROM function_state WHERE scope_id = ? AND ns = ? RETURNING value\"\n )\n .all(bufferArg(executionId), bufferArg(NS_WORKER)) as Array<{ value: Uint8Array }>;\n return rows.map((row) => new Uint8Array(row.value));\n }\n\n async workerScan(executionId: Uint8Array): Promise<Array<[number, Uint8Array]>> {\n const rows = this._db\n .prepare(\n \"SELECT key, value FROM function_state WHERE scope_id = ? AND ns = ?\"\n )\n .all(bufferArg(executionId), bufferArg(NS_WORKER)) as Array<{\n key: Uint8Array;\n value: Uint8Array;\n }>;\n return rows.map((row) => [int64FromKey(new Uint8Array(row.key)), new Uint8Array(row.value)]);\n }\n\n async queuePush(executionId: Uint8Array, items: Uint8Array[]): Promise<number> {\n const eidBuf = bufferArg(executionId);\n this._db.exec(\"BEGIN\");\n try {\n const insert = this._db.prepare(\n \"INSERT INTO work_queue (execution_id, work_item) VALUES (?, ?)\"\n );\n for (const item of items) {\n insert.run(eidBuf, bufferArg(item));\n }\n this._db.exec(\"COMMIT\");\n } catch (e) {\n this._db.exec(\"ROLLBACK\");\n throw e;\n }\n return items.length;\n }\n\n async queuePop(executionId: Uint8Array): Promise<Uint8Array | null> {\n // No registration: an empty or never-pushed queue both return null,\n // matching the Durable Object.\n const row = this._db\n .prepare(\n \"DELETE FROM work_queue WHERE id = (\" +\n \" SELECT id FROM work_queue WHERE execution_id = ? ORDER BY id ASC LIMIT 1\" +\n \") RETURNING work_item\"\n )\n .get(bufferArg(executionId)) as { work_item: Uint8Array } | null;\n\n return row ? new Uint8Array(row.work_item) : null;\n }\n\n async queueClear(executionId: Uint8Array): Promise<number> {\n return this._db\n .prepare(\"DELETE FROM work_queue WHERE execution_id = ?\")\n .run(bufferArg(executionId)).changes;\n }\n}\n\n// ============================================================================\n// BoundStorage\n// ============================================================================\n\nexport class BoundStorage {\n private _base: FunctionStorage;\n private _executionId: Uint8Array;\n private _substreamId: Uint8Array | null;\n\n /**\n * @param substreamId The table-in-out substream this storage serves -- the\n * client-minted `InitRequest.substream_id`, identical across the\n * substream's init, every tick and its finalize -- or `null` when the\n * client sent none. Keys {@link put}.\n */\n constructor(storage: FunctionStorage, executionId: Uint8Array, substreamId: Uint8Array | null = null) {\n this._base = storage;\n this._executionId = executionId;\n this._substreamId = substreamId;\n }\n\n /**\n * Upsert this substream's state into the execution's worker state, which\n * {@link collect} drains at finalize.\n *\n * One row per **substream**, keyed by its `substream_id`. Storage is\n * already scoped to the execution, and every connection of a fanned-out\n * scan shares that execution -- so the key has to tell those connections\n * apart. The process id only does when each connection is its own process;\n * under the launcher, TCP or HTTP one process serves many of them, and a\n * per-process key let them overwrite each other's state so finish()\n * undercounted. The pid remains only for a client that sends no\n * `substream_id`, which it keys as before. Mirrors vgi-python's\n * `TableInOutFunction.process` (072e543).\n */\n put(state: Uint8Array): Promise<void> {\n return this._base.workerPut(this._executionId, this._substreamId ?? process.pid, state);\n }\n\n collect(): Promise<Uint8Array[]> {\n return this._base.workerCollect(this._executionId);\n }\n\n workerScan(): Promise<Array<[number, Uint8Array]>> {\n return this._base.workerScan(this._executionId);\n }\n\n queuePush(items: Uint8Array[]): Promise<number> {\n return this._base.queuePush(this._executionId, items);\n }\n\n queuePop(): Promise<Uint8Array | null> {\n return this._base.queuePop(this._executionId);\n }\n\n queueClear(): Promise<number> {\n return this._base.queueClear(this._executionId);\n }\n\n stateGet(ns: Uint8Array, key: Uint8Array): Promise<Uint8Array | null> {\n return this._base.stateGet(this._executionId, ns, key);\n }\n\n statePut(ns: Uint8Array, key: Uint8Array, value: Uint8Array): Promise<void> {\n return this._base.statePut(this._executionId, ns, key, value);\n }\n\n stateAppend(ns: Uint8Array, key: Uint8Array, item: Uint8Array): Promise<number> {\n return this._base.stateAppend(this._executionId, ns, key, item);\n }\n\n stateLogScan(\n ns: Uint8Array,\n key: Uint8Array,\n afterId: number = -1,\n limit: number | null = null,\n ): Promise<Array<[number, Uint8Array]>> {\n return this._base.stateLogScan(this._executionId, ns, key, afterId, limit);\n }\n\n executionClear(): Promise<number> {\n return this._base.executionClear(this._executionId);\n }\n\n static packIntKey(i: number | bigint): Uint8Array {\n return packIntKey(i);\n }\n}\n\n// ============================================================================\n// Backend factory + lazy default storage\n// ============================================================================\n\n/**\n * Resolve the FunctionStorage backend from environment variables.\n *\n * Mirrors vgi-python's `_resolve_storage` in `vgi/function.py`.\n *\n * `VGI_WORKER_SHARED_STORAGE` selects the backend (default: `sqlite`):\n * - `memory` — `FunctionStorageSqlite` at `:memory:`. Process-local\n * with no cross-process coordination — single-process\n * deployments only. Ignores `VGI_WORKER_SQLITE_PATH`.\n * - `sqlite` — `FunctionStorageSqlite`. Honors `VGI_WORKER_SQLITE_PATH`\n * (including `:memory:`).\n * - `cloudflare-do` — `FunctionStorageCfDo`. Requires `VGI_CF_DO_URL`;\n * optional `VGI_CF_DO_TOKEN` for bearer auth.\n */\nexport function resolveStorageFromEnv(): FunctionStorage {\n const backend = (process.env.VGI_WORKER_SHARED_STORAGE ?? \"sqlite\").toLowerCase();\n if (backend === \"memory\") {\n return new FunctionStorageSqlite(\":memory:\");\n }\n if (backend === \"sqlite\") {\n return new FunctionStorageSqlite();\n }\n if (backend === \"cloudflare-do\") {\n // Lazy require to avoid loading the CF client when sqlite is in use.\n const { FunctionStorageCfDo } = require(\"./storage-cf-do.js\") as typeof import(\"./storage-cf-do.js\");\n return FunctionStorageCfDo.fromEnv();\n }\n throw new Error(\n `Unknown VGI_WORKER_SHARED_STORAGE backend: '${backend}'. Supported: 'memory', 'sqlite', 'cloudflare-do'.`,\n );\n}\n\n// Module-level proxy that lazy-resolves the configured backend on first use.\n// Importing this module no longer opens a SQLite connection — that happens\n// the first time anyone touches a storage method. Matches Python's\n// _DefaultStorageDescriptor lazy attribute pattern.\nlet _resolved: FunctionStorage | null = null;\nfunction getDefaultStorage(): FunctionStorage {\n if (_resolved == null) _resolved = resolveStorageFromEnv();\n return _resolved;\n}\n\n/**\n * Override the default backend used by the `storage` singleton. Call once at\n * worker startup to inject a pre-built backend that env-driven selection can't\n * construct — notably a `FunctionStorageCfDo` wired to a Cloudflare\n * service-binding Fetcher (the binding lives on `env`, not `process.env`, and a\n * same-zone public-URL fetch is rejected with CF error 1042). Takes precedence\n * over `VGI_WORKER_SHARED_STORAGE`.\n */\nexport function setStorage(impl: FunctionStorage): void {\n _resolved = impl;\n}\n\n/** Default FunctionStorage instance. Backend is selected via env on first access. */\nexport const storage: FunctionStorage = new Proxy(\n {} as FunctionStorage,\n {\n get(_t, prop, _r) {\n const inst = getDefaultStorage() as any;\n const v = inst[prop];\n return typeof v === \"function\" ? v.bind(inst) : v;\n },\n },\n);\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/** bun:sqlite needs Buffer for blob params */\nfunction bufferArg(data: Uint8Array): Buffer {\n return Buffer.from(data.buffer, data.byteOffset, data.byteLength);\n}\n",
|
|
7
7
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Bun HTTP entrypoint for a VGI worker: `import { serveVgiWorker } from \"@query-farm/vgi/serve\"`.\n//\n// A worker's HTTP server is the same nine moving parts every time (protocol,\n// state-token key, TTL, CORS, landing surface, port, Bun.serve, startup log).\n// This collapses them to one call so a worker repo's serve script is its\n// registry + catalog and nothing else:\n//\n// serveVgiWorker({\n// name: \"ishares\",\n// doc: \"iShares (BlackRock) US fund data.\",\n// version: \"0.1.0\",\n// repositoryUrl: \"https://github.com/Query-farm/vgi-etf-ishares\",\n// registry,\n// catalogInterface,\n// });\n//\n// Mounted at the ROOT prefix, so DuckDB attaches the bare origin:\n// ATTACH 'ishares' AS ishares (TYPE vgi, LOCATION 'http://localhost:8787');\n//\n// Bun-only — it calls Bun.serve. Cloudflare Workers use `vgi/worker-cf`'s\n// createVgiFetch instead; both share the handler factory in http/fetch.ts.\n\nimport type { CatalogInterface } from \"./catalog/interface.js\";\nimport type { FunctionRegistry } from \"./functions/registry.js\";\nimport {\n irohForwardedHeaderIdentityProvider,\n IROH_FORWARDED_ENDPOINT_HEADER,\n observePeerIdentity,\n peerIdentityPrimary,\n type AuthenticateFn,\n type PeerResolutionOptions,\n} from \"@query-farm/vgi-rpc\";\nimport { createVgiFetch } from \"./http/fetch.js\";\n\n/** Environment variables `serveVgiWorker` reads. Injectable for testing. */\nexport interface ServeEnv {\n PORT?: string;\n VGI_SIGNING_KEY?: string;\n VGI_TOKEN_TTL?: string;\n CORS_ORIGINS?: string;\n}\n\nexport const DEFAULT_PORT = 8787;\nexport const DEFAULT_TOKEN_TTL = 3600;\n/** Bytes of HMAC key `createHttpHandler` expects; 64 hex characters. */\nexport const SIGNING_KEY_BYTES = 32;\n\n/** HTTP trust boundary for a colocated `vgi-iroh-bridge`. */\nexport interface IrohHttpBridgeOptions {\n /** Worker-local namespace for EndpointId principals. */\n issuer: string;\n /** Exact bridge IP addresses. No CIDRs or hostnames. */\n trustedProxyAddresses?: readonly string[];\n /** Authenticate the EndpointId (default) or expose evidence only. */\n authenticate?: boolean;\n /**\n * Host-specific physical peer and raw-header adapter. Required because a\n * Fetch Request alone does not preserve duplicate header fields.\n */\n peerResolutionContext?: (request: Request) => PeerResolutionOptions | Promise<PeerResolutionOptions>;\n}\n\nexport interface ServeVgiWorkerOptions {\n /** Short worker name shown on the landing page, e.g. \"ishares\". */\n name: string;\n /** One-line description of what the worker serves. */\n doc: string;\n /** Worker version string shown on the landing page. */\n version: string;\n /** Functions the worker serves, already registered. */\n registry: FunctionRegistry;\n /** Catalog DuckDB attaches to. */\n catalogInterface: CatalogInterface;\n\n /** Public source-repository URL, linked from the landing page. */\n repositoryUrl?: string;\n /** Overrides `$PORT` (default 8787). Pass 0 to bind an ephemeral port. */\n port?: number;\n /** Bind address. Iroh bridge mode defaults to loopback; otherwise Bun's default. */\n hostname?: string;\n /** Overrides `$VGI_SIGNING_KEY`. 32 bytes. */\n signingKey?: Uint8Array;\n /** Overrides `$VGI_TOKEN_TTL` (default 3600 seconds). */\n tokenTtl?: number;\n /** Overrides `$CORS_ORIGINS` (default \"*\"). Pass `null` to disable CORS. */\n corsOrigins?: string | null;\n /** Server ID for state-token attribution (default: `name`). */\n serverId?: string;\n /** Mount point for the VGI endpoints (default \"\", the origin root). */\n prefix?: string;\n /** Suppress the startup banner on stdout. */\n quiet?: boolean;\n /** Environment source (default `process.env`). */\n env?: ServeEnv;\n /** Authenticates each request, returning the caller's `AuthContext`.\n * Omit for an anonymous worker (the default). */\n authenticate?: AuthenticateFn;\n /** Preserve authenticated Iroh identity forwarded by an adjacent HTTP bridge. */\n irohBridge?: IrohHttpBridgeOptions;\n}\n\n/** The slice of `Bun.serve`'s return value this module uses. */\nexport interface VgiHttpServer {\n readonly port: number;\n readonly url: URL;\n stop(closeActiveConnections?: boolean): void;\n requestIP?(request: Request): { address: string } | null;\n}\n\ninterface BunLike {\n serve(options: {\n port: number;\n hostname?: string;\n fetch: (req: Request) => Promise<Response>;\n }): VgiHttpServer;\n}\n\n/**\n * Decode a 32-byte signing key from its hex representation.\n *\n * Throws on anything that is not exactly 64 hex characters. A silent truncate\n * or zero-pad here would produce a worker that starts happily with a key far\n * weaker than the operator believed they supplied.\n */\nexport function parseSigningKeyHex(hex: string): Uint8Array {\n const cleaned = hex.trim();\n const expected = SIGNING_KEY_BYTES * 2;\n if (cleaned.length !== expected || !/^[0-9a-fA-F]+$/.test(cleaned)) {\n throw new Error(\n `VGI_SIGNING_KEY must be exactly ${expected} hex characters ` +\n `(${SIGNING_KEY_BYTES} bytes); got ${cleaned.length}. ` +\n `Generate one with: openssl rand -hex ${SIGNING_KEY_BYTES}`,\n );\n }\n const key = new Uint8Array(SIGNING_KEY_BYTES);\n for (let i = 0; i < SIGNING_KEY_BYTES; i++) {\n key[i] = Number.parseInt(cleaned.slice(i * 2, i * 2 + 2), 16);\n }\n return key;\n}\n\n/**\n * Resolve the state-token signing key: explicit option, then `$VGI_SIGNING_KEY`,\n * then a fresh random key.\n *\n * The random fallback is safe but ephemeral, and that tradeoff is why it warns:\n * state tokens minted under it stop validating after a restart, and never\n * validate across a second instance behind a load balancer. It exists so\n * `bun run scripts/serve.ts` works with no setup, not so deployments can skip\n * the key.\n */\nexport function resolveSigningKey(\n explicit: Uint8Array | undefined,\n env: ServeEnv,\n warn: (msg: string) => void = console.error,\n): Uint8Array {\n if (explicit) {\n if (explicit.length !== SIGNING_KEY_BYTES) {\n throw new Error(\n `signingKey must be ${SIGNING_KEY_BYTES} bytes; got ${explicit.length}.`,\n );\n }\n return explicit;\n }\n const fromEnv = env.VGI_SIGNING_KEY?.trim();\n if (fromEnv) return parseSigningKeyHex(fromEnv);\n\n warn(\n \"WARNING: VGI_SIGNING_KEY is not set; generated a random state-token key.\\n\" +\n \" State tokens will not survive a restart, and will not validate\\n\" +\n \" across multiple instances behind a load balancer.\\n\" +\n ` Set it for any real deployment: openssl rand -hex ${SIGNING_KEY_BYTES}`,\n );\n return crypto.getRandomValues(new Uint8Array(SIGNING_KEY_BYTES));\n}\n\nfunction resolvePort(explicit: number | undefined, env: ServeEnv): number {\n if (explicit !== undefined) return explicit;\n const raw = env.PORT?.trim();\n if (!raw) return DEFAULT_PORT;\n const port = Number(raw);\n if (!Number.isInteger(port) || port < 0 || port > 65535) {\n throw new Error(`PORT must be an integer between 0 and 65535; got ${JSON.stringify(raw)}.`);\n }\n return port;\n}\n\nfunction resolveTokenTtl(explicit: number | undefined, env: ServeEnv): number {\n if (explicit !== undefined) return explicit;\n const raw = env.VGI_TOKEN_TTL?.trim();\n if (!raw) return DEFAULT_TOKEN_TTL;\n const ttl = Number(raw);\n if (!Number.isInteger(ttl) || ttl < 0) {\n throw new Error(`VGI_TOKEN_TTL must be a non-negative integer; got ${JSON.stringify(raw)}.`);\n }\n return ttl;\n}\n\n/**\n * Build the fetch handler a VGI worker serves over HTTP, with the standardized\n * landing surface mounted at `prefix`.\n *\n * Exposed separately from {@link serveVgiWorker} so a worker can put the VGI\n * routes inside its own Bun/Hono/Elysia server, or drive them from a test\n * without binding a port.\n */\nexport function createVgiWorkerFetch(\n opts: ServeVgiWorkerOptions,\n): (req: Request) => Promise<Response> {\n const env = opts.env ?? (process.env as ServeEnv);\n const signingKey = resolveSigningKey(opts.signingKey, env);\n const tokenTtl = resolveTokenTtl(opts.tokenTtl, env);\n // `null` disables CORS and must stay `null` through to createVgiFetch, which\n // now reads a bare `undefined` as \"default to *\" — passing `undefined` here to\n // mean \"off\" would silently re-enable it. `undefined` falls through to the env\n // var and then to that same default.\n const corsOrigins = opts.corsOrigins === null ? null : (opts.corsOrigins ?? env.CORS_ORIGINS);\n const bridge = opts.irohBridge;\n if (bridge && !bridge.peerResolutionContext) {\n throw new Error(\n \"irohBridge requires a peerResolutionContext when createVgiWorkerFetch is used without serveVgiWorker\",\n );\n }\n const trustedProxyAddresses = bridge?.trustedProxyAddresses ?? [\"127.0.0.1\"];\n\n return createVgiFetch({\n protocol: { registry: opts.registry, catalogInterface: opts.catalogInterface },\n signingKey,\n tokenTtl,\n prefix: opts.prefix ?? \"\",\n serverId: opts.serverId ?? opts.name,\n corsOrigins,\n repositoryUrl: opts.repositoryUrl,\n landingInfo: { name: opts.name, doc: opts.doc, version: opts.version },\n authenticate: opts.authenticate,\n peerIdentityProviders: bridge\n ? [irohForwardedHeaderIdentityProvider({ issuer: bridge.issuer, trustedProxyAddresses })]\n : undefined,\n peerAuthenticationPolicy: bridge\n ? (bridge.authenticate === false ? observePeerIdentity : peerIdentityPrimary(\"iroh\"))\n : undefined,\n peerResolutionContext: bridge?.peerResolutionContext,\n });\n}\n\n/**\n * Serve a VGI worker over HTTP on Bun and return the running server.\n *\n * Reads `PORT`, `VGI_SIGNING_KEY`, `VGI_TOKEN_TTL`, and `CORS_ORIGINS` from the\n * environment; every one has an explicit option that takes precedence.\n */\nexport function serveVgiWorker(opts: ServeVgiWorkerOptions): VgiHttpServer {\n const runtime = (globalThis as { Bun?: BunLike }).Bun;\n if (!runtime) {\n throw new Error(\n '\"@query-farm/vgi/serve\" requires the Bun runtime (it calls Bun.serve). ' +\n 'On Cloudflare Workers use createVgiFetch from \"@query-farm/vgi/worker-cf\"; ' +\n \"on other runtimes use createVgiWorkerFetch and bind the port yourself.\",\n );\n }\n\n const env = opts.env ?? (process.env as ServeEnv);\n const port = resolvePort(opts.port, env);\n const hostname = opts.hostname ?? (opts.irohBridge ? \"127.0.0.1\" : undefined);\n if (opts.irohBridge && ![\"127.0.0.1\", \"::1\", \"localhost\"].includes(hostname ?? \"\")) {\n throw new Error(\"an Iroh HTTP bridge upstream must bind loopback\");\n }\n let server: VgiHttpServer;\n const bridge = opts.irohBridge && !opts.irohBridge.peerResolutionContext\n ? {\n ...opts.irohBridge,\n peerResolutionContext(request: Request): PeerResolutionOptions {\n const immediatePeer = server.requestIP?.(request)?.address;\n const forwarded = request.headers.get(IROH_FORWARDED_ENDPOINT_HEADER);\n return {\n immediatePeer,\n headers: forwarded === null\n ? {}\n : { [IROH_FORWARDED_ENDPOINT_HEADER]: [forwarded] },\n };\n },\n }\n : opts.irohBridge;\n const fetch = createVgiWorkerFetch({ ...opts, irohBridge: bridge });\n server = runtime.serve({ port, hostname, fetch });\n\n if (!opts.quiet) {\n const base = `http://localhost:${server.port}`;\n console.log(`${opts.name} VGI HTTP worker listening on ${base}`);\n console.log(` landing page ${base}/`);\n console.log(` client bundle ${base}/vgi-client.js`);\n console.log(` health ${base}/health`);\n console.log(` attach ATTACH '${opts.name}' AS ${opts.name} (TYPE vgi, LOCATION '${base}');`);\n }\n return server;\n}\n",
|
|
8
|
-
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Shared HTTP fetch-handler factory for VGI workers.\n//\n// Both HTTP entrypoints funnel through here:\n// - `vgi/worker-cf` -> createVgiFetch, exported as `default.fetch` for workerd\n// - `vgi/serve` -> serveVgiWorker, which hands the handler to Bun.serve\n//\n// Centralising the wiring means the state-token key reaches `createHttpHandler`\n// as `tokenKey` (the option the handler actually reads) and reaches\n// `buildVgiProtocol` as `signingKey`, from one source. Passing different keys to\n// those two seams produces a worker that mints tokens it cannot recover.\n\nimport {\n AuthContext,\n createHttpHandler,\n unpackStateToken,\n type AuthenticateFn,\n type DispatchHook,\n type DispatchInfo,\n type HookToken,\n type PeerAuthenticationPolicy,\n type PeerIdentityProvider,\n type PeerResolutionOptions,\n type Protocol,\n} from \"@query-farm/vgi-rpc\";\nimport { arrowStateSerializer } from \"../protocol/state-serializer.js\";\nimport { buildVgiProtocol, VGI_PROTOCOL_NAME, type ProtocolConfig } from \"../protocol/dispatch.js\";\nimport { createLandingRoutes, type LandingInfo } from \"./landing.js\";\nimport { setRequestAuthScope, type RequestAuthHolder } from \"../request-auth.js\";\n\nexport interface VgiFetchOptions {\n /** Wire-protocol config (registry + catalogInterface). */\n protocol: Omit<ProtocolConfig, \"recoverExchangeState\">;\n /** HMAC key for state-token signing. Pass a stable, secret 32-byte key\n * (e.g. derived from a Wrangler secret). Required because Workers don't\n * preserve in-memory state across requests/instances. */\n signingKey: Uint8Array;\n /** State-token TTL in seconds (default 3600). */\n tokenTtl?: number;\n /** URL path prefix for VGI requests (default \"/vgi\"). Pass \"\" to mount at\n * the root, which is what a dedicated single-worker HTTP server wants. */\n prefix?: string;\n /** Server ID for state-token attribution (default \"vgi-cf\"). */\n serverId?: string;\n /** CORS allowed origins, added to all responses so the preflight `OPTIONS`\n * that browser clients send before `__describe__` succeeds.\n *\n * **Defaults to `\"*\"`.** A VGI worker exists to be attached and explored, and\n * the hosted Cupola UI reaches it from another origin, so cross-origin is the\n * normal case rather than the exception — and a worker that omits this gets\n * no CORS headers at all, which fails only in a browser and only for someone\n * else's page, i.e. nowhere its author is looking. `serveVgiWorker` has\n * always defaulted this way; this matches it so both entries agree.\n *\n * Pass `null` to disable CORS. */\n corsOrigins?: string | null;\n /** Public source-repository URL, surfaced on the landing page. */\n repositoryUrl?: string;\n /** Worker identity for the standardized VGI landing surface: `GET /` serves\n * the shared landing.html plus a JSON status document carrying this\n * identity, and `GET /vgi-client.js` serves the browser client build the\n * page reads the catalog with.\n *\n * Required, and deliberately so. It used to be optional, and omitting it\n * silently downgraded `GET /` to vgi-rpc's generic \"this is an RPC\n * endpoint\" placeholder while `GET /vgi-client.js` 404'd — a worker that\n * looked deployed but had no catalog tree, no Cupola link, and no ATTACH\n * snippet. Nothing failed loudly, so the only way to notice was to open the\n * page. `serveVgiWorker` never had the problem because it builds this from\n * its required name/doc/version; the CF entry had to remember, and\n * vgi-open-meteo shipped for weeks without it. */\n landingInfo: LandingInfo;\n /** Authenticates each incoming request, returning the caller's\n * {@link AuthContext}. Forwarded verbatim to `createHttpHandler`; omit it\n * and every caller is anonymous, which is what this package did before the\n * option existed.\n *\n * Supplying it is what makes a worker able to serve more than one principal,\n * and the identity it returns is the one the worker seals `attach_opaque_data`\n * and split tokens under. */\n authenticate?: AuthenticateFn;\n /** Off-wire transport identities, including a trusted Iroh HTTP bridge. */\n peerIdentityProviders?: readonly PeerIdentityProvider[];\n /** Policy composing peer evidence with application authentication. */\n peerAuthenticationPolicy?: PeerAuthenticationPolicy;\n /** Host adapter supplying the physical peer and multiplicity-preserving headers. */\n peerResolutionContext?: (request: Request) => PeerResolutionOptions | Promise<PeerResolutionOptions>;\n}\n\n// ---------------------------------------------------------------------------\n// Request-scoped caller identity\n//\n// `@query-farm/vgi-rpc` types stream initialization as `(params) => state` —\n// no CallContext — on both dispatchers, so the `init` handler cannot be handed\n// the principal as an argument the way every unary handler is. But `init` is\n// exactly where the identity-bound envelopes minted by `catalog_attach` and\n// `table_function_plan` (both unary, both sealed under the REAL caller) are\n// opened. Opening them under the anonymous identity works for anonymous\n// callers and fails for everyone else.\n//\n// So the identity travels the way vgi-python's `current_auth()` ContextVar\n// does: an ambient per-request scope. `AsyncLocalStorage.run` wraps the whole\n// handler call, and a dispatch hook fills the holder in with whatever identity\n// the framework actually dispatched under — the hook is read AFTER\n// authentication, the PKCE cookie chain and bearer introspection have all had\n// their say, so it reports the final principal rather than re-deriving one.\n//\n// A mutable holder rather than `enterWith`: `run` is the only form Cloudflare\n// Workers supports, and the identity is not known until authentication has run\n// inside the handler.\n// ---------------------------------------------------------------------------\n\n/** The `AsyncLocalStorage` surface used here, structurally typed so this file\n * compiles where `node:async_hooks` has no types. */\ninterface AsyncLocalStorageLike<T> {\n run<R>(store: T, fn: () => R): R;\n getStore(): T | undefined;\n}\n\nlet requestAuthStorage: AsyncLocalStorageLike<RequestAuthHolder> | null | undefined;\nlet requestAuthStoragePending: Promise<AsyncLocalStorageLike<RequestAuthHolder> | null> | undefined;\n\n/**\n * Resolve (once) the AsyncLocalStorage this process scopes requests with.\n *\n * `node:async_hooks` is loaded dynamically and defensively: it exists on Node\n * and Bun, and on Cloudflare Workers only with the `nodejs_compat` /\n * `nodejs_als` compatibility flag. Where it is missing this resolves to `null`\n * and the worker keeps serving exactly as it did before — anonymous callers\n * unaffected, authenticated ones still unable to open their sealed attach.\n * Degrading is the right failure here: refusing to start would break every\n * anonymous deployment to fix a case it does not have.\n */\nfunction ensureRequestAuthStorage(): Promise<AsyncLocalStorageLike<RequestAuthHolder> | null> {\n if (requestAuthStorage !== undefined) return Promise.resolve(requestAuthStorage);\n requestAuthStoragePending ??= import(\"node:async_hooks\")\n .then((mod) => {\n const storage = new mod.AsyncLocalStorage<RequestAuthHolder>() as AsyncLocalStorageLike<RequestAuthHolder>;\n requestAuthStorage = storage;\n setRequestAuthScope(storage);\n return storage;\n })\n .catch(() => {\n requestAuthStorage = null;\n return null;\n });\n return requestAuthStoragePending;\n}\n\n/**\n * Dispatch hook that records the dispatching principal on the open scope.\n *\n * Reads the identity off `DispatchInfo`, which the framework populates from the\n * resolved auth context for every method — so this sees the same principal the\n * access log and the unary handlers see, without this package having to know\n * how authentication was configured.\n */\nconst REQUEST_AUTH_DISPATCH_HOOK: DispatchHook = {\n onDispatchStart(info: DispatchInfo): HookToken {\n const holder = requestAuthStorage?.getStore();\n if (holder) {\n holder.auth = info.authenticated\n ? new AuthContext(info.authDomain ?? \"\", true, info.principal ?? \"\", info.claims ?? {})\n : AuthContext.anonymous();\n }\n return undefined;\n },\n onDispatchEnd() {\n // Nothing to record; the scope ends when the request does.\n },\n};\n\n/**\n * Build a fetch handler suitable for `export default { fetch }` in a CF\n * Worker module, or for `Bun.serve({ fetch })`. The returned handler is\n * async-safe across Workers' isolate-per-request execution model — all state\n * round-trips through the signed state token created here.\n */\nexport function createVgiFetch(opts: VgiFetchOptions): (req: Request) => Promise<Response> {\n // The type makes this required, but a plain-JS caller (or one that predates\n // the change) reaches here with it undefined, and the failure mode this\n // guards is silent: a worker that serves a placeholder page forever. Fail\n // at construction, where the stack points at the caller.\n if (!opts.landingInfo) {\n throw new Error(\n \"createVgiFetch requires `landingInfo` ({ name, doc, version }). Without it \" +\n \"GET / serves vgi-rpc's generic placeholder instead of the VGI landing page \" +\n \"and GET /vgi-client.js 404s.\",\n );\n }\n const tokenTtl = opts.tokenTtl ?? 3600;\n // `?? \"/vgi\"` and not `|| \"/vgi\"`: an explicit \"\" means \"mount at root\".\n const prefix = opts.prefix ?? \"/vgi\";\n const serverId = opts.serverId ?? \"vgi-cf\";\n\n const protocol: Protocol = buildVgiProtocol({\n signingKey: opts.signingKey,\n ...opts.protocol,\n recoverExchangeState: async (opaqueData: Uint8Array) => {\n const tokenString = new TextDecoder().decode(opaqueData);\n // principal binding is enforced by the HTTP handler on the request that\n // carried this token; the recovery path itself is not principal-scoped,\n // so the scope names the protocol and leaves the identity anonymous.\n // `protocol` is required since vgi-rpc 0.24.0: it is bound into the\n // token's AEAD associated data, so a cursor minted under one hosted\n // protocol cannot be opened under another.\n const unpacked = await unpackStateToken(tokenString, opts.signingKey, tokenTtl, {\n protocol: VGI_PROTOCOL_NAME,\n principal: undefined,\n });\n return arrowStateSerializer.deserialize(unpacked.stateBytes);\n },\n });\n\n const handler = createHttpHandler(protocol, {\n prefix,\n serverId,\n tokenKey: opts.signingKey,\n tokenTtl,\n stateSerializer: arrowStateSerializer,\n // Records the dispatching principal on the request scope opened below, so\n // stream `init` — the one handler the framework passes no CallContext to —\n // can still open the identity-bound attach and split envelopes.\n dispatchHook: REQUEST_AUTH_DISPATCH_HOOK,\n authenticate: opts.authenticate,\n peerIdentityProviders: opts.peerIdentityProviders,\n peerAuthenticationPolicy: opts.peerAuthenticationPolicy,\n peerResolutionContext: opts.peerResolutionContext,\n // `null` is the explicit opt-out; `undefined` (omitted) means \"*\".\n corsOrigins: opts.corsOrigins === null ? undefined : (opts.corsOrigins ?? \"*\"),\n repositoryUrl: opts.repositoryUrl,\n // The landing surface is ours, contributed into vgi-rpc's routing rather\n // than built there. `enableLandingPage: false` drops vgi-rpc's generic\n // \"this is an RPC endpoint\" page, which would otherwise sit behind ours for\n // no reason — a VGI worker always has the real thing.\n extraRoutes: createLandingRoutes(opts.landingInfo),\n enableLandingPage: false,\n });\n return async (req: Request) => {\n const storage = await ensureRequestAuthStorage();\n // No AsyncLocalStorage on this host: serve exactly as before.\n if (!storage) return handler(req);\n // One holder per request. The dispatch hook fills it in once the framework\n // has resolved the principal; `init` reads it back through\n // `currentRequestAuth()`.\n return storage.run({}, () => handler(req));\n };\n}\n",
|
|
8
|
+
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Shared HTTP fetch-handler factory for VGI workers.\n//\n// Both HTTP entrypoints funnel through here:\n// - `vgi/worker-cf` -> createVgiFetch, exported as `default.fetch` for workerd\n// - `vgi/serve` -> serveVgiWorker, which hands the handler to Bun.serve\n//\n// Centralising the wiring means the state-token key reaches `createHttpHandler`\n// as `tokenKey` (the option the handler actually reads) and reaches\n// `buildVgiProtocol` as `signingKey`, from one source. Passing different keys to\n// those two seams produces a worker that mints tokens it cannot recover.\n\nimport {\n AuthContext,\n createHttpHandler,\n type AuthenticateFn,\n type DispatchHook,\n type DispatchInfo,\n type HookToken,\n type PeerAuthenticationPolicy,\n type PeerIdentityProvider,\n type PeerResolutionOptions,\n type Protocol,\n} from \"@query-farm/vgi-rpc\";\nimport { arrowStateSerializer } from \"../protocol/state-serializer.js\";\nimport { buildVgiProtocol, type ProtocolConfig } from \"../protocol/dispatch.js\";\nimport { createLandingRoutes, type LandingInfo } from \"./landing.js\";\nimport { setRequestAuthScope, type RequestAuthHolder } from \"../request-auth.js\";\n\nexport interface VgiFetchOptions {\n /** Wire-protocol config (registry + catalogInterface). */\n protocol: ProtocolConfig;\n /** HMAC key for state-token signing. Pass a stable, secret 32-byte key\n * (e.g. derived from a Wrangler secret). Required because Workers don't\n * preserve in-memory state across requests/instances. */\n signingKey: Uint8Array;\n /** State-token TTL in seconds (default 3600). */\n tokenTtl?: number;\n /** URL path prefix for VGI requests (default \"/vgi\"). Pass \"\" to mount at\n * the root, which is what a dedicated single-worker HTTP server wants. */\n prefix?: string;\n /** Server ID for state-token attribution (default \"vgi-cf\"). */\n serverId?: string;\n /** CORS allowed origins, added to all responses so the preflight `OPTIONS`\n * that browser clients send before `__describe__` succeeds.\n *\n * **Defaults to `\"*\"`.** A VGI worker exists to be attached and explored, and\n * the hosted Cupola UI reaches it from another origin, so cross-origin is the\n * normal case rather than the exception — and a worker that omits this gets\n * no CORS headers at all, which fails only in a browser and only for someone\n * else's page, i.e. nowhere its author is looking. `serveVgiWorker` has\n * always defaulted this way; this matches it so both entries agree.\n *\n * Pass `null` to disable CORS. */\n corsOrigins?: string | null;\n /** Public source-repository URL, surfaced on the landing page. */\n repositoryUrl?: string;\n /** Worker identity for the standardized VGI landing surface: `GET /` serves\n * the shared landing.html plus a JSON status document carrying this\n * identity, and `GET /vgi-client.js` serves the browser client build the\n * page reads the catalog with.\n *\n * Required, and deliberately so. It used to be optional, and omitting it\n * silently downgraded `GET /` to vgi-rpc's generic \"this is an RPC\n * endpoint\" placeholder while `GET /vgi-client.js` 404'd — a worker that\n * looked deployed but had no catalog tree, no Cupola link, and no ATTACH\n * snippet. Nothing failed loudly, so the only way to notice was to open the\n * page. `serveVgiWorker` never had the problem because it builds this from\n * its required name/doc/version; the CF entry had to remember, and\n * vgi-open-meteo shipped for weeks without it. */\n landingInfo: LandingInfo;\n /** Authenticates each incoming request, returning the caller's\n * {@link AuthContext}. Forwarded verbatim to `createHttpHandler`; omit it\n * and every caller is anonymous, which is what this package did before the\n * option existed.\n *\n * Supplying it is what makes a worker able to serve more than one principal,\n * and the identity it returns is the one the worker seals `attach_opaque_data`\n * and split tokens under. */\n authenticate?: AuthenticateFn;\n /** Off-wire transport identities, including a trusted Iroh HTTP bridge. */\n peerIdentityProviders?: readonly PeerIdentityProvider[];\n /** Policy composing peer evidence with application authentication. */\n peerAuthenticationPolicy?: PeerAuthenticationPolicy;\n /** Host adapter supplying the physical peer and multiplicity-preserving headers. */\n peerResolutionContext?: (request: Request) => PeerResolutionOptions | Promise<PeerResolutionOptions>;\n}\n\n// ---------------------------------------------------------------------------\n// Request-scoped caller identity\n//\n// `@query-farm/vgi-rpc` types stream initialization as `(params) => state` —\n// no CallContext — on both dispatchers, so the `init` handler cannot be handed\n// the principal as an argument the way every unary handler is. But `init` is\n// exactly where the identity-bound envelopes minted by `catalog_attach` and\n// `table_function_plan` (both unary, both sealed under the REAL caller) are\n// opened. Opening them under the anonymous identity works for anonymous\n// callers and fails for everyone else.\n//\n// So the identity travels the way vgi-python's `current_auth()` ContextVar\n// does: an ambient per-request scope. `AsyncLocalStorage.run` wraps the whole\n// handler call, and a dispatch hook fills the holder in with whatever identity\n// the framework actually dispatched under — the hook is read AFTER\n// authentication, the PKCE cookie chain and bearer introspection have all had\n// their say, so it reports the final principal rather than re-deriving one.\n//\n// A mutable holder rather than `enterWith`: `run` is the only form Cloudflare\n// Workers supports, and the identity is not known until authentication has run\n// inside the handler.\n// ---------------------------------------------------------------------------\n\n/** The `AsyncLocalStorage` surface used here, structurally typed so this file\n * compiles where `node:async_hooks` has no types. */\ninterface AsyncLocalStorageLike<T> {\n run<R>(store: T, fn: () => R): R;\n getStore(): T | undefined;\n}\n\nlet requestAuthStorage: AsyncLocalStorageLike<RequestAuthHolder> | null | undefined;\nlet requestAuthStoragePending: Promise<AsyncLocalStorageLike<RequestAuthHolder> | null> | undefined;\n\n/**\n * Resolve (once) the AsyncLocalStorage this process scopes requests with.\n *\n * `node:async_hooks` is loaded dynamically and defensively: it exists on Node\n * and Bun, and on Cloudflare Workers only with the `nodejs_compat` /\n * `nodejs_als` compatibility flag. Where it is missing this resolves to `null`\n * and the worker keeps serving exactly as it did before — anonymous callers\n * unaffected, authenticated ones still unable to open their sealed attach.\n * Degrading is the right failure here: refusing to start would break every\n * anonymous deployment to fix a case it does not have.\n */\nfunction ensureRequestAuthStorage(): Promise<AsyncLocalStorageLike<RequestAuthHolder> | null> {\n if (requestAuthStorage !== undefined) return Promise.resolve(requestAuthStorage);\n requestAuthStoragePending ??= import(\"node:async_hooks\")\n .then((mod) => {\n const storage = new mod.AsyncLocalStorage<RequestAuthHolder>() as AsyncLocalStorageLike<RequestAuthHolder>;\n requestAuthStorage = storage;\n setRequestAuthScope(storage);\n return storage;\n })\n .catch(() => {\n requestAuthStorage = null;\n return null;\n });\n return requestAuthStoragePending;\n}\n\n/**\n * Dispatch hook that records the dispatching principal on the open scope.\n *\n * Reads the identity off `DispatchInfo`, which the framework populates from the\n * resolved auth context for every method — so this sees the same principal the\n * access log and the unary handlers see, without this package having to know\n * how authentication was configured.\n */\nconst REQUEST_AUTH_DISPATCH_HOOK: DispatchHook = {\n onDispatchStart(info: DispatchInfo): HookToken {\n const holder = requestAuthStorage?.getStore();\n if (holder) {\n holder.auth = info.authenticated\n ? new AuthContext(info.authDomain ?? \"\", true, info.principal ?? \"\", info.claims ?? {})\n : AuthContext.anonymous();\n }\n return undefined;\n },\n onDispatchEnd() {\n // Nothing to record; the scope ends when the request does.\n },\n};\n\n/**\n * Build a fetch handler suitable for `export default { fetch }` in a CF\n * Worker module, or for `Bun.serve({ fetch })`. The returned handler is\n * async-safe across Workers' isolate-per-request execution model — all state\n * round-trips through the signed state token created here.\n */\nexport function createVgiFetch(opts: VgiFetchOptions): (req: Request) => Promise<Response> {\n // The type makes this required, but a plain-JS caller (or one that predates\n // the change) reaches here with it undefined, and the failure mode this\n // guards is silent: a worker that serves a placeholder page forever. Fail\n // at construction, where the stack points at the caller.\n if (!opts.landingInfo) {\n throw new Error(\n \"createVgiFetch requires `landingInfo` ({ name, doc, version }). Without it \" +\n \"GET / serves vgi-rpc's generic placeholder instead of the VGI landing page \" +\n \"and GET /vgi-client.js 404s.\",\n );\n }\n const tokenTtl = opts.tokenTtl ?? 3600;\n // `?? \"/vgi\"` and not `|| \"/vgi\"`: an explicit \"\" means \"mount at root\".\n const prefix = opts.prefix ?? \"/vgi\";\n const serverId = opts.serverId ?? \"vgi-cf\";\n\n const protocol: Protocol = buildVgiProtocol({\n signingKey: opts.signingKey,\n ...opts.protocol,\n });\n\n const handler = createHttpHandler(protocol, {\n prefix,\n serverId,\n tokenKey: opts.signingKey,\n tokenTtl,\n stateSerializer: arrowStateSerializer,\n // Records the dispatching principal on the request scope opened below, so\n // stream `init` — the one handler the framework passes no CallContext to —\n // can still open the identity-bound attach and split envelopes.\n dispatchHook: REQUEST_AUTH_DISPATCH_HOOK,\n authenticate: opts.authenticate,\n peerIdentityProviders: opts.peerIdentityProviders,\n peerAuthenticationPolicy: opts.peerAuthenticationPolicy,\n peerResolutionContext: opts.peerResolutionContext,\n // `null` is the explicit opt-out; `undefined` (omitted) means \"*\".\n corsOrigins: opts.corsOrigins === null ? undefined : (opts.corsOrigins ?? \"*\"),\n repositoryUrl: opts.repositoryUrl,\n // The landing surface is ours, contributed into vgi-rpc's routing rather\n // than built there. `enableLandingPage: false` drops vgi-rpc's generic\n // \"this is an RPC endpoint\" page, which would otherwise sit behind ours for\n // no reason — a VGI worker always has the real thing.\n extraRoutes: createLandingRoutes(opts.landingInfo),\n enableLandingPage: false,\n });\n return async (req: Request) => {\n const storage = await ensureRequestAuthStorage();\n // No AsyncLocalStorage on this host: serve exactly as before.\n if (!storage) return handler(req);\n // One holder per request. The dispatch hook fills it in once the framework\n // has resolved the principal; `init` reads it back through\n // `currentRequestAuth()`.\n return storage.run({}, () => handler(req));\n };\n}\n",
|
|
9
9
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Backend-agnostic Arrow type predicates. Both arrow-js and flechette\n// expose `typeId` on every DataType with identical numeric values, so a\n// single `t.typeId === N` check works regardless of the active backend.\n\nimport type { VgiDataType } from \"./types.js\";\n\nexport const TypeId = {\n Null: 1,\n Int: 2,\n Float: 3,\n Binary: 4,\n Utf8: 5,\n Bool: 6,\n Decimal: 7,\n Date: 8,\n Time: 9,\n Timestamp: 10,\n Interval: 11,\n List: 12,\n Struct: 13,\n Union: 14,\n FixedSizeBinary: 15,\n FixedSizeList: 16,\n Map: 17,\n Duration: 18,\n LargeBinary: 19,\n LargeUtf8: 20,\n Dictionary: -1,\n} as const;\n\nexport function isNull(t: VgiDataType): boolean { return t.typeId === TypeId.Null; }\nexport function isInt(t: VgiDataType): boolean { return t.typeId === TypeId.Int; }\nexport function isFloat(t: VgiDataType): boolean { return t.typeId === TypeId.Float; }\nexport function isBinary(t: VgiDataType): boolean {\n return t.typeId === TypeId.Binary || t.typeId === TypeId.LargeBinary;\n}\nexport function isUtf8(t: VgiDataType): boolean {\n return t.typeId === TypeId.Utf8 || t.typeId === TypeId.LargeUtf8;\n}\nexport function isBool(t: VgiDataType): boolean { return t.typeId === TypeId.Bool; }\nexport function isDecimal(t: VgiDataType): boolean { return t.typeId === TypeId.Decimal; }\nexport function isDate(t: VgiDataType): boolean { return t.typeId === TypeId.Date; }\nexport function isTime(t: VgiDataType): boolean { return t.typeId === TypeId.Time; }\nexport function isTimestamp(t: VgiDataType): boolean { return t.typeId === TypeId.Timestamp; }\nexport function isInterval(t: VgiDataType): boolean { return t.typeId === TypeId.Interval; }\nexport function isList(t: VgiDataType): boolean { return t.typeId === TypeId.List; }\nexport function isStruct(t: VgiDataType): boolean { return t.typeId === TypeId.Struct; }\nexport function isUnion(t: VgiDataType): boolean { return t.typeId === TypeId.Union; }\nexport function isFixedSizeBinary(t: VgiDataType): boolean { return t.typeId === TypeId.FixedSizeBinary; }\nexport function isFixedSizeList(t: VgiDataType): boolean { return t.typeId === TypeId.FixedSizeList; }\nexport function isMap(t: VgiDataType): boolean { return t.typeId === TypeId.Map; }\nexport function isDuration(t: VgiDataType): boolean { return t.typeId === TypeId.Duration; }\nexport function isDictionary(t: VgiDataType): boolean { return t.typeId === TypeId.Dictionary; }\n\n/**\n * Stable structural identity for an Arrow type, usable for equality.\n *\n * `String(type)` is NOT usable for this: arrow-js DataTypes are class\n * instances with a meaningful `toString()` (\"Int64\", \"Utf8\", …), while\n * flechette types are plain object literals that stringify to\n * \"[object Object]\". Comparing with `toString()` therefore reports *every*\n * flechette type as equal to every other, and never equal to a declared\n * arrow-js type — which collapsed overload resolution to a first-match tie\n * (`type_info(42::BIGINT)` picked the INTEGER overload).\n *\n * Both libraries agree on `typeId` and on the parameter *values*; they differ\n * only on a few property names, so those are read under both spellings. The\n * output is an opaque key — compare it, don't display it.\n */\nexport function typeSignature(t: VgiDataType | null | undefined): string {\n if (t == null) return \"null\";\n const a = t as any;\n const kids = (): string =>\n Array.isArray(a.children)\n ? a.children.map((c: any) => `${c?.name ?? \"\"}:${typeSignature(c?.type ?? c)}`).join(\",\")\n : \"\";\n switch (t.typeId) {\n case TypeId.Int:\n return `int${a.bitWidth}${(a.isSigned ?? a.signed ?? true) ? \"\" : \"u\"}`;\n case TypeId.Float:\n return `float${a.precision}`;\n case TypeId.Decimal:\n return `decimal${a.bitWidth ?? 128}(${a.precision},${a.scale})`;\n case TypeId.Date:\n case TypeId.Time:\n case TypeId.Duration:\n return `${t.typeId}[${a.unit}]`;\n case TypeId.Timestamp:\n return `ts[${a.unit},${a.timezone ?? \"\"}]`;\n case TypeId.Interval:\n return `iv[${a.unit}]`;\n case TypeId.FixedSizeBinary:\n return `fsb(${a.byteWidth ?? a.stride})`;\n case TypeId.FixedSizeList:\n return `fsl(${a.listSize ?? a.stride},${kids()})`;\n case TypeId.List:\n case TypeId.Struct:\n case TypeId.Map:\n return `${t.typeId}<${kids()}>`;\n case TypeId.Union:\n return `union(${a.mode},${kids()})`;\n case TypeId.Dictionary:\n return `dict(${typeSignature(a.dictionary)},${typeSignature(a.indices)},${\n a.ordered ?? a.isOrdered ?? false\n })`;\n default:\n // Covers the parameterless types (Null, Bool, Utf8, Binary and their\n // Large variants) plus anything not enumerated above; children are\n // folded in when present so a nested type still differentiates.\n return Array.isArray(a.children) ? `${t.typeId}<${kids()}>` : String(t.typeId);\n }\n}\n\n/** Runtime check: does `x` quack like a VgiBatch? Used at API boundaries\n * where callers may pass either a batch or a plain column dict. Duck-typed\n * because arrow-js and flechette use unrelated classes. */\nexport function isBatch(x: unknown): x is import(\"./types.js\").VgiBatch {\n return (\n x != null &&\n typeof (x as any).numRows === \"number\" &&\n (x as any).schema != null &&\n Array.isArray((x as any).schema.fields)\n );\n}\n",
|
|
10
10
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Factory-style constructors for arrow-js Schema/Field/DataType values.\n// Mirrors flechette's API so internal code can call the same factory\n// regardless of the active backend.\n\nimport {\n Schema as A_Schema,\n Field as A_Field,\n Null as A_Null,\n Bool as A_Bool,\n Int8 as A_Int8,\n Int16 as A_Int16,\n Int32 as A_Int32,\n Int64 as A_Int64,\n Uint8 as A_Uint8,\n Uint16 as A_Uint16,\n Uint32 as A_Uint32,\n Uint64 as A_Uint64,\n Float16 as A_Float16,\n Float32 as A_Float32,\n Float64 as A_Float64,\n Utf8 as A_Utf8,\n LargeUtf8 as A_LargeUtf8,\n Binary as A_Binary,\n LargeBinary as A_LargeBinary,\n Decimal as A_Decimal,\n Date_ as A_Date,\n Time as A_Time,\n Timestamp as A_Timestamp,\n Duration as A_Duration,\n Interval as A_Interval,\n List as A_List,\n Struct as A_Struct,\n Map_ as A_Map,\n Dictionary as A_Dictionary,\n SparseUnion as A_SparseUnion,\n DenseUnion as A_DenseUnion,\n FixedSizeBinary as A_FixedSizeBinary,\n FixedSizeList as A_FixedSizeList,\n DateUnit as A_DateUnit,\n TimeUnit as A_TimeUnit,\n IntervalUnit as A_IntervalUnit,\n UnionMode as A_UnionMode,\n type DataType,\n} from \"@query-farm/apache-arrow\";\n\nimport type { VgiField, VgiSchema, VgiDataType } from \"../types.js\";\n\n// ----- TimeUnit / DateUnit / UnionMode constants ---------------------------\n// Numeric values match the Arrow IPC spec; both arrow-js and flechette\n// use the same integers, so internal code can freely cross backends.\n\nexport const TimeUnit = {\n SECOND: A_TimeUnit.SECOND,\n MILLISECOND: A_TimeUnit.MILLISECOND,\n MICROSECOND: A_TimeUnit.MICROSECOND,\n NANOSECOND: A_TimeUnit.NANOSECOND,\n} as const;\n\nexport const DateUnit = {\n DAY: A_DateUnit.DAY,\n MILLISECOND: A_DateUnit.MILLISECOND,\n} as const;\n\nexport const IntervalUnit = {\n YEAR_MONTH: A_IntervalUnit.YEAR_MONTH,\n DAY_TIME: A_IntervalUnit.DAY_TIME,\n MONTH_DAY_NANO: A_IntervalUnit.MONTH_DAY_NANO,\n} as const;\n\nexport const UnionMode = {\n Sparse: A_UnionMode.Sparse,\n Dense: A_UnionMode.Dense,\n} as const;\n\n// ----- Schema / Field ------------------------------------------------------\n\nexport function schema(\n fields: readonly VgiField[],\n metadata?: Map<string, string>,\n): VgiSchema {\n return new A_Schema(\n fields as A_Field[],\n metadata ?? new Map(),\n ) as unknown as VgiSchema;\n}\n\nexport function field(\n name: string,\n type: VgiDataType,\n nullable = true,\n metadata?: Map<string, string>,\n): VgiField {\n return new A_Field(\n name,\n type as DataType,\n nullable,\n metadata ?? new Map(),\n ) as unknown as VgiField;\n}\n\n// ----- Primitive types -----------------------------------------------------\n\nexport const nullType = (): VgiDataType => new A_Null() as unknown as VgiDataType;\nexport const bool = (): VgiDataType => new A_Bool() as unknown as VgiDataType;\n\nexport const int8 = (): VgiDataType => new A_Int8() as unknown as VgiDataType;\nexport const int16 = (): VgiDataType => new A_Int16() as unknown as VgiDataType;\nexport const int32 = (): VgiDataType => new A_Int32() as unknown as VgiDataType;\nexport const int64 = (): VgiDataType => new A_Int64() as unknown as VgiDataType;\nexport const uint8 = (): VgiDataType => new A_Uint8() as unknown as VgiDataType;\nexport const uint16 = (): VgiDataType => new A_Uint16() as unknown as VgiDataType;\nexport const uint32 = (): VgiDataType => new A_Uint32() as unknown as VgiDataType;\nexport const uint64 = (): VgiDataType => new A_Uint64() as unknown as VgiDataType;\nexport function int(bitWidth: 8 | 16 | 32 | 64 = 32, signed = true): VgiDataType {\n if (signed) {\n switch (bitWidth) {\n case 8: return int8();\n case 16: return int16();\n case 32: return int32();\n case 64: return int64();\n }\n } else {\n switch (bitWidth) {\n case 8: return uint8();\n case 16: return uint16();\n case 32: return uint32();\n case 64: return uint64();\n }\n }\n throw new Error(`int: unsupported bitWidth ${bitWidth}`);\n}\n\nexport const float16 = (): VgiDataType => new A_Float16() as unknown as VgiDataType;\nexport const float32 = (): VgiDataType => new A_Float32() as unknown as VgiDataType;\nexport const float64 = (): VgiDataType => new A_Float64() as unknown as VgiDataType;\n\nexport const utf8 = (): VgiDataType => new A_Utf8() as unknown as VgiDataType;\nexport const largeUtf8 = (): VgiDataType => new A_LargeUtf8() as unknown as VgiDataType;\nexport const binary = (): VgiDataType => new A_Binary() as unknown as VgiDataType;\nexport const largeBinary = (): VgiDataType => new A_LargeBinary() as unknown as VgiDataType;\nexport const fixedSizeBinary = (byteWidth: number): VgiDataType =>\n new A_FixedSizeBinary(byteWidth) as unknown as VgiDataType;\n\n// ----- Decimal -------------------------------------------------------------\n\nexport function decimal(\n precision: number,\n scale: number,\n bitWidth: 32 | 64 | 128 | 256 = 128,\n): VgiDataType {\n // arrow-js's Decimal constructor signature is (scale, precision, bitWidth) —\n // the OPPOSITE order of our facade (precision, scale). Passing them in facade\n // order made arrow-js report `.precision`/`.scale` swapped versus flechette.\n // Swap here so a facade-built decimal reports identical precision/scale on\n // both backends.\n return new A_Decimal(scale, precision, bitWidth) as unknown as VgiDataType;\n}\nexport const decimal128 = (precision: number, scale: number): VgiDataType =>\n decimal(precision, scale, 128);\nexport const decimal256 = (precision: number, scale: number): VgiDataType =>\n decimal(precision, scale, 256);\n\n// ----- Date / Time / Timestamp / Duration / Interval -----------------------\n\nexport const date = (unit: number = A_DateUnit.MILLISECOND): VgiDataType =>\n new A_Date(unit) as unknown as VgiDataType;\nexport const dateDay = (): VgiDataType => date(A_DateUnit.DAY);\nexport const dateMillisecond = (): VgiDataType => date(A_DateUnit.MILLISECOND);\n\nexport function time(unit: number = A_TimeUnit.MILLISECOND, bitWidth?: 32 | 64): VgiDataType {\n const bw = bitWidth ?? (unit <= A_TimeUnit.MILLISECOND ? 32 : 64);\n return new A_Time(unit, bw) as unknown as VgiDataType;\n}\nexport const timeSecond = (): VgiDataType => time(A_TimeUnit.SECOND, 32);\nexport const timeMillisecond = (): VgiDataType => time(A_TimeUnit.MILLISECOND, 32);\nexport const timeMicrosecond = (): VgiDataType => time(A_TimeUnit.MICROSECOND, 64);\nexport const timeNanosecond = (): VgiDataType => time(A_TimeUnit.NANOSECOND, 64);\n\nexport const timestamp = (\n unit: number = A_TimeUnit.MILLISECOND,\n timezone: string | null = null,\n): VgiDataType => new A_Timestamp(unit, timezone) as unknown as VgiDataType;\n\nexport const duration = (unit: number = A_TimeUnit.MILLISECOND): VgiDataType =>\n new A_Duration(unit) as unknown as VgiDataType;\n\nexport const interval = (unit: number = A_IntervalUnit.MONTH_DAY_NANO): VgiDataType =>\n new A_Interval(unit) as unknown as VgiDataType;\n\n// ----- Nested types --------------------------------------------------------\n\nexport function list(child: VgiField | VgiDataType): VgiDataType {\n const childField = isField(child) ? child : field(\"item\", child as VgiDataType, true);\n return new A_List(childField as A_Field) as unknown as VgiDataType;\n}\n\nexport function fixedSizeList(child: VgiField | VgiDataType, listSize: number): VgiDataType {\n const childField = isField(child) ? child : field(\"item\", child as VgiDataType, true);\n return new A_FixedSizeList(listSize, childField as A_Field) as unknown as VgiDataType;\n}\n\nexport function struct(children: readonly VgiField[]): VgiDataType {\n return new A_Struct(children as A_Field[]) as unknown as VgiDataType;\n}\n\nexport function map(\n keyField: VgiField | VgiDataType,\n valueField: VgiField | VgiDataType,\n keysSorted = false,\n): VgiDataType {\n const k = isField(keyField) ? keyField : field(\"key\", keyField as VgiDataType, false);\n const v = isField(valueField) ? valueField : field(\"value\", valueField as VgiDataType, true);\n // arrow-js Map_ takes a Field whose type is Struct{key,value}\n const entries = field(\"entries\", struct([k, v]), false);\n return new A_Map(entries as A_Field, keysSorted) as unknown as VgiDataType;\n}\n\nexport function dictionary(\n valueType: VgiDataType,\n indexType: VgiDataType = int16(),\n ordered = false,\n id?: number,\n): VgiDataType {\n return new A_Dictionary(\n valueType as DataType,\n indexType as any,\n id,\n ordered,\n ) as unknown as VgiDataType;\n}\n\nexport function union(\n mode: number,\n children: readonly (VgiField | VgiDataType)[],\n typeIds?: number[],\n): VgiDataType {\n const childFields = children.map((c, i) =>\n isField(c) ? c : field(String(i), c as VgiDataType, true),\n );\n const ids = typeIds ?? childFields.map((_, i) => i);\n const Ctor = mode === A_UnionMode.Dense ? A_DenseUnion : A_SparseUnion;\n return new Ctor(ids, childFields as A_Field[]) as unknown as VgiDataType;\n}\n\nexport const sparseUnion = (\n children: readonly (VgiField | VgiDataType)[],\n typeIds?: number[],\n): VgiDataType => union(A_UnionMode.Sparse, children, typeIds);\n\nexport const denseUnion = (\n children: readonly (VgiField | VgiDataType)[],\n typeIds?: number[],\n): VgiDataType => union(A_UnionMode.Dense, children, typeIds);\n\n// Utility: distinguish Field from DataType. arrow-js Fields have `name` and\n// `type`; bare DataTypes only have `typeId` (and class-specific props).\nfunction isField(x: VgiField | VgiDataType): x is VgiField {\n return typeof (x as VgiField).name === \"string\" && (x as VgiField).type != null;\n}\n",
|
|
11
11
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Empty (0-row) Arrow batch construction. Handles complex types (List, Map,\n// Struct) that need child data to round-trip through Arrow IPC serialization.\n\nimport {\n RecordBatch,\n Schema,\n Field,\n Struct,\n List,\n DataType,\n makeData,\n Map_,\n} from \"@query-farm/apache-arrow\";\n\n/**\n * Create empty (0-length) data for any Arrow type, handling complex types\n * that need child data (List, Map, Struct) to be serializable.\n */\nfunction emptyData(field: Field): any {\n const type = field.type;\n\n if (DataType.isList(type)) {\n const childField = (type as List).children[0];\n return makeData({\n type,\n length: 0,\n nullCount: 0,\n child: emptyData(childField),\n valueOffsets: new Int32Array([0]),\n });\n }\n\n if (DataType.isMap(type)) {\n const entriesField = (type as Map_).children[0];\n return makeData({\n type,\n length: 0,\n nullCount: 0,\n child: emptyData(entriesField),\n valueOffsets: new Int32Array([0]),\n });\n }\n\n if (DataType.isStruct(type)) {\n const children = type.children.map((child: Field) => emptyData(child));\n return makeData({ type, length: 0, nullCount: 0, children });\n }\n\n return makeData({ type, length: 0, nullCount: 0 });\n}\n\nimport type { VgiSchema } from \"../types.js\";\n\n/**\n * Create an empty (0-row) batch with the given schema. Accepts arrow-js\n * `Schema` or facade `VgiSchema` (cast at the boundary).\n */\nexport function emptyBatch(schema: Schema | VgiSchema): RecordBatch {\n const a = schema as Schema;\n const children = a.fields.map((f: Field) => emptyData(f));\n\n const structType = new Struct(a.fields);\n const data = makeData({\n type: structType,\n length: 0,\n children,\n nullCount: 0,\n });\n\n return new RecordBatch(a, data);\n}\n",
|
|
@@ -21,18 +21,21 @@
|
|
|
21
21
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// arrow-js backend for the vgi-typescript Arrow facade.\n// Default backend (Bun worker, Node) — selected via `#arrow-impl` resolution\n// when no `worker`/`workerd`/`browser` condition is active.\n\nimport type { VgiBackendInfo } from \"../types.js\";\n\nexport const backend: VgiBackendInfo = { name: \"arrow-js\" };\n\n// Schema / Field / DataType factories\nexport {\n schema,\n field,\n nullType,\n bool,\n int,\n int8, int16, int32, int64,\n uint8, uint16, uint32, uint64,\n float16, float32, float64,\n utf8, largeUtf8, binary, largeBinary, fixedSizeBinary,\n decimal, decimal128, decimal256,\n date, dateDay, dateMillisecond,\n time, timeSecond, timeMillisecond, timeMicrosecond, timeNanosecond,\n timestamp, duration, interval,\n list, fixedSizeList, struct, map,\n dictionary,\n union, sparseUnion, denseUnion,\n TimeUnit, DateUnit, IntervalUnit, UnionMode,\n} from \"./schema.js\";\n\n// Batch construction / iteration / utilities\nexport { emptyBatch } from \"./empty.js\";\nexport { batchFromRows, batchFromColumns, columnFromArray } from \"./build.js\";\nexport {\n iterRows,\n batchToScalarDict,\n batchToSecretDict,\n safeNumber,\n decodeDictValue,\n} from \"./iterate.js\";\nexport { filterBatch } from \"./filter.js\";\nexport { projectSchema, projectBatch } from \"./project.js\";\nexport { readCanonicalValue } from \"./canonical.js\";\nexport { withBatchMetadata } from \"./metadata.js\";\n\n// IPC\nexport {\n serializeSchema,\n deserializeSchema,\n serializeBatch,\n deserializeBatch,\n} from \"./ipc.js\";\n\n// Column statistics (sparse-union heavy — backend-specific).\nexport { buildStatisticsBatch, type ColumnStatistics } from \"./statistics.js\";\n\n/**\n * No-op on this backend: arrow-js `RecordBatch`/`Vector` already expose the\n * full API worker code uses, and arrow-js is a peer dependency, so there is\n * only ever one copy. Present so both backends satisfy one facade interface —\n * see impl-flechette/compat.ts for what this does there.\n */\nexport function adoptArrowJsShape<T>(batch: T): T {\n return batch;\n}\n",
|
|
22
22
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n//\n// Typed facade type-factories — phase 3 (the KEY ENABLER for static typing).\n//\n// The per-backend `schema.ts` factories build a runtime `VgiDataType` but only\n// declare their return as `VgiDataType` (`{ readonly typeId }`), which is too\n// coarse for the type-level value mapping in ./codec/repr.ts. This module wraps\n// each factory and casts the (unchanged) runtime value to the PRECISE nominal\n// descriptor from ./codec/type-descriptors.ts — e.g. `dateDay(): Date32Type`,\n// `timestamp(u): TimestampType<...>`, `struct(children)` preserving its field\n// tuple. Both backends route through the same `#arrow-impl` runtime, so they\n// report IDENTICAL static types from the facade.\n//\n// Runtime behavior is identical to the backend factories (these are pure casts\n// plus, for the unit-overloaded factories, a literal-unit overload set that\n// maps the integer TimeUnit to the descriptor's string-literal unit).\n\nimport * as impl from \"#arrow-impl\";\nimport type { VgiField, VgiDataType } from \"./types.js\";\nimport type {\n NullDescriptor,\n BoolType,\n Int8Type, Int16Type, Int32Type, Int64Type,\n Uint8Type, Uint16Type, Uint32Type, Uint64Type,\n IntType,\n FloatType,\n Utf8Type,\n LargeUtf8Type,\n BinaryType,\n LargeBinaryType,\n FixedSizeBinaryType,\n DecimalType,\n Date32Type, Date64Type,\n Time32Type, Time64Type,\n TimestampType,\n DurationType,\n IntervalType,\n ListType, FixedSizeListType,\n StructType,\n MapType,\n DictionaryType,\n UnionType,\n TypedField,\n TUnit,\n} from \"./codec/type-descriptors.js\";\n\n// Re-export the runtime unit/mode enums and schema/field helpers untouched.\nexport const { TimeUnit, DateUnit, IntervalUnit, UnionMode, schema } = impl;\n\n/** field(): preserve the precise name + type so struct() can carry a typed\n * child tuple. Runtime is the backend `field`. */\nexport function field<Name extends string, T extends VgiDataType>(\n name: Name,\n type: T,\n nullable?: boolean,\n metadata?: Map<string, string>,\n): TypedField<Name, T> {\n return impl.field(name, type as any, nullable, metadata) as unknown as TypedField<Name, T>;\n}\n\n// ----- Primitives ----------------------------------------------------------\n\nexport const nullType = (): NullDescriptor => impl.nullType() as unknown as NullDescriptor;\nexport const bool = (): BoolType => impl.bool() as unknown as BoolType;\n\nexport const int8 = (): Int8Type => impl.int8() as unknown as Int8Type;\nexport const int16 = (): Int16Type => impl.int16() as unknown as Int16Type;\nexport const int32 = (): Int32Type => impl.int32() as unknown as Int32Type;\nexport const int64 = (): Int64Type => impl.int64() as unknown as Int64Type;\nexport const uint8 = (): Uint8Type => impl.uint8() as unknown as Uint8Type;\nexport const uint16 = (): Uint16Type => impl.uint16() as unknown as Uint16Type;\nexport const uint32 = (): Uint32Type => impl.uint32() as unknown as Uint32Type;\nexport const uint64 = (): Uint64Type => impl.uint64() as unknown as Uint64Type;\n\n// int(bitWidth, signed): bitWidth/signedness aren't statically known from a\n// runtime `number`, so this degrades to the generic IntType (rich/raw fall back\n// to number/bigint per the width literal when callers pass a literal). Prefer\n// the named factories (int32(), int64(), …) for precise typing.\nexport function int(bitWidth?: 8 | 16 | 32 | 64, signed?: boolean): IntType<8 | 16 | 32 | 64, boolean> {\n return impl.int(bitWidth, signed) as unknown as IntType<8 | 16 | 32 | 64, boolean>;\n}\n\nexport const float16 = (): FloatType => impl.float16() as unknown as FloatType;\nexport const float32 = (): FloatType => impl.float32() as unknown as FloatType;\nexport const float64 = (): FloatType => impl.float64() as unknown as FloatType;\n\nexport const utf8 = (): Utf8Type => impl.utf8() as unknown as Utf8Type;\nexport const largeUtf8 = (): LargeUtf8Type => impl.largeUtf8() as unknown as LargeUtf8Type;\nexport const binary = (): BinaryType => impl.binary() as unknown as BinaryType;\nexport const largeBinary = (): LargeBinaryType => impl.largeBinary() as unknown as LargeBinaryType;\nexport const fixedSizeBinary = (byteWidth: number): FixedSizeBinaryType =>\n impl.fixedSizeBinary(byteWidth) as unknown as FixedSizeBinaryType;\n\n// ----- Decimal -------------------------------------------------------------\n\nexport const decimal = (precision: number, scale: number, bitWidth?: 32 | 64 | 128 | 256): DecimalType =>\n impl.decimal(precision, scale, bitWidth) as unknown as DecimalType;\nexport const decimal128 = (precision: number, scale: number): DecimalType =>\n impl.decimal128(precision, scale) as unknown as DecimalType;\nexport const decimal256 = (precision: number, scale: number): DecimalType =>\n impl.decimal256(precision, scale) as unknown as DecimalType;\n\n// ----- Date / Time / Timestamp / Duration / Interval -----------------------\n\n// `date(unit)` with a runtime unit isn't statically resolvable; it widens to\n// Date64Type (ms) — the default. Use dateDay()/dateMillisecond() for precision.\nexport const date = (unit?: number): Date64Type => impl.date(unit) as unknown as Date64Type;\nexport const dateDay = (): Date32Type => impl.dateDay() as unknown as Date32Type;\nexport const dateMillisecond = (): Date64Type => impl.dateMillisecond() as unknown as Date64Type;\n\nexport const timeSecond = (): Time32Type<\"s\"> => impl.timeSecond() as unknown as Time32Type<\"s\">;\nexport const timeMillisecond = (): Time32Type<\"ms\"> => impl.timeMillisecond() as unknown as Time32Type<\"ms\">;\nexport const timeMicrosecond = (): Time64Type<\"us\"> => impl.timeMicrosecond() as unknown as Time64Type<\"us\">;\nexport const timeNanosecond = (): Time64Type<\"ns\"> => impl.timeNanosecond() as unknown as Time64Type<\"ns\">;\n\n// Generic time(unit, bitWidth): degrades to a union of the precise time types.\nexport function time(unit?: number, bitWidth?: 32 | 64): Time32Type<\"s\" | \"ms\"> | Time64Type<\"us\" | \"ns\"> {\n return impl.time(unit, bitWidth) as unknown as Time32Type<\"s\" | \"ms\"> | Time64Type<\"us\" | \"ns\">;\n}\n\nconst UNIT_TO_TAG: Record<number, TUnit> = {\n [impl.TimeUnit.SECOND]: \"s\",\n [impl.TimeUnit.MILLISECOND]: \"ms\",\n [impl.TimeUnit.MICROSECOND]: \"us\",\n [impl.TimeUnit.NANOSECOND]: \"ns\",\n};\n\n/** timestamp(unit): when called with a literal unit constant the result type\n * carries that unit; with a runtime number it widens to TimestampType<TUnit>. */\nexport function timestamp<U extends TUnit = TUnit>(\n unit?: number,\n timezone?: string | null,\n): TimestampType<U> {\n return impl.timestamp(unit, timezone ?? null) as unknown as TimestampType<U>;\n}\n\nexport function duration<U extends TUnit = TUnit>(unit?: number): DurationType<U> {\n return impl.duration(unit) as unknown as DurationType<U>;\n}\n\n// Unit-precise convenience factories — these carry the wire unit in the static\n// type without the caller needing an explicit type argument, so raw-mode\n// branded typing is automatic. (The generic timestamp()/duration() above\n// can't infer the unit from a runtime `number`, so prefer these.)\nexport const timestampSeconds = (timezone?: string | null): TimestampType<\"s\"> =>\n impl.timestamp(impl.TimeUnit.SECOND, timezone ?? null) as unknown as TimestampType<\"s\">;\nexport const timestampMillis = (timezone?: string | null): TimestampType<\"ms\"> =>\n impl.timestamp(impl.TimeUnit.MILLISECOND, timezone ?? null) as unknown as TimestampType<\"ms\">;\nexport const timestampMicros = (timezone?: string | null): TimestampType<\"us\"> =>\n impl.timestamp(impl.TimeUnit.MICROSECOND, timezone ?? null) as unknown as TimestampType<\"us\">;\nexport const timestampNanos = (timezone?: string | null): TimestampType<\"ns\"> =>\n impl.timestamp(impl.TimeUnit.NANOSECOND, timezone ?? null) as unknown as TimestampType<\"ns\">;\n\nexport const durationSeconds = (): DurationType<\"s\"> =>\n impl.duration(impl.TimeUnit.SECOND) as unknown as DurationType<\"s\">;\nexport const durationMillis = (): DurationType<\"ms\"> =>\n impl.duration(impl.TimeUnit.MILLISECOND) as unknown as DurationType<\"ms\">;\nexport const durationMicros = (): DurationType<\"us\"> =>\n impl.duration(impl.TimeUnit.MICROSECOND) as unknown as DurationType<\"us\">;\nexport const durationNanos = (): DurationType<\"ns\"> =>\n impl.duration(impl.TimeUnit.NANOSECOND) as unknown as DurationType<\"ns\">;\n\nexport const interval = (unit?: number): IntervalType => impl.interval(unit) as unknown as IntervalType;\n\n// ----- Nested --------------------------------------------------------------\n\nexport function list<T extends VgiDataType>(child: TypedField<string, T> | T): ListType<T> {\n return impl.list(child as any) as unknown as ListType<T>;\n}\n\nexport function fixedSizeList<T extends VgiDataType>(\n child: TypedField<string, T> | T,\n listSize: number,\n): FixedSizeListType<T> {\n return impl.fixedSizeList(child as any, listSize) as unknown as FixedSizeListType<T>;\n}\n\nexport function struct<const C extends readonly TypedField<string, VgiDataType>[]>(\n children: C,\n): StructType<C> {\n return impl.struct(children as unknown as readonly VgiField[]) as unknown as StructType<C>;\n}\n\nexport function map<K extends VgiDataType, V extends VgiDataType>(\n keyField: TypedField<string, K> | K,\n valueField: TypedField<string, V> | V,\n keysSorted?: boolean,\n): MapType<K, V> {\n return impl.map(keyField as any, valueField as any, keysSorted) as unknown as MapType<K, V>;\n}\n\nexport function dictionary<V extends VgiDataType>(\n valueType: V,\n indexType?: VgiDataType,\n ordered?: boolean,\n id?: number,\n): DictionaryType<V> {\n return impl.dictionary(valueType as any, indexType as any, ordered, id) as unknown as DictionaryType<V>;\n}\n\nexport function union(\n mode: number,\n children: readonly (VgiField | VgiDataType)[],\n typeIds?: number[],\n): UnionType {\n return impl.union(mode, children as any, typeIds) as unknown as UnionType;\n}\n\nexport const sparseUnion = (\n children: readonly (VgiField | VgiDataType)[],\n typeIds?: number[],\n): UnionType => impl.sparseUnion(children as any, typeIds) as unknown as UnionType;\n\nexport const denseUnion = (\n children: readonly (VgiField | VgiDataType)[],\n typeIds?: number[],\n): UnionType => impl.denseUnion(children as any, typeIds) as unknown as UnionType;\n",
|
|
23
23
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Shared byte-conversion utility. Browser-safe (no bare Buffer.isBuffer).\n\n/** Convert any binary-ish value to a Uint8Array. Returns empty array for null/undefined. */\nexport function toUint8Array(val: any): Uint8Array {\n if (val instanceof Uint8Array) return val;\n if (val instanceof ArrayBuffer) return new Uint8Array(val);\n if (typeof Buffer !== \"undefined\" && Buffer.isBuffer(val))\n return new Uint8Array(val);\n if (val && val.buffer instanceof ArrayBuffer) {\n return new Uint8Array(val.buffer, val.byteOffset, val.byteLength);\n }\n return new Uint8Array(0);\n}\n",
|
|
24
|
-
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Arrow IPC state serializer for HTTP transport.\n// Replaces JSON serialization with Arrow IPC for the exchange state token,\n// avoiding base64/hex overhead and staying consistent with the rest of the protocol.\n\nimport {\n type VgiDataType,\n type VgiField,\n schema as makeSchema,\n field,\n struct as makeStruct,\n binary,\n int64,\n bool,\n float64,\n utf8,\n list as makeList,\n nullType,\n typeSignature,\n isStruct,\n isBinary,\n serializeBatch,\n deserializeBatch,\n batchFromColumns,\n readCanonicalValue,\n} from \"../arrow/index.js\";\nimport { codecFor } from \"../arrow/codec/registry.js\";\nimport type { StateSerializer } from \"@query-farm/vgi-rpc\";\nimport { toUint8Array } from \"../util/bytes.js\";\n\n/** Schema for the exchange state carried in HTTP state tokens. */\nexport const EXCHANGE_STATE_SCHEMA = makeSchema([\n field(\"function_name\", binary(), false),\n field(\"init_request\", binary(), false),\n field(\"execution_id\", binary(), false),\n field(\"max_workers\", int64(), false),\n field(\"opaque_data\", binary(), true),\n field(\"is_producer\", bool(), false),\n field(\"user_state\", binary(), true),\n]);\n\nconst TEXT_ENCODER = new TextEncoder();\nconst TEXT_DECODER = new TextDecoder();\n\n/**\n * Child field name for an inferred list. Arrow matches list children by\n * position, not name, so this is cosmetic — but keeping it at Arrow's\n * conventional `item` makes a dumped schema read the way people expect.\n */\nconst LIST_CHILD_NAME = \"item\";\n\n/**\n * Element type for an array with nothing to infer from — `[]`, or an array\n * whose every element is null.\n *\n * Deliberately NOT `nullType()`, which is the semantically honest choice:\n * flechette's column builder rejects a Null-typed list child (\"Unsupported\n * data type: Null\"), so a `[]` in userState would round-trip on arrow-js and\n * throw on flechette. Utf8 builds on both backends and, with no non-null\n * element to carry, is indistinguishable on the way back out: `[]` returns\n * `[]` and `[null, null]` returns `[null, null]`.\n */\nconst emptyListElementType = (): VgiDataType => utf8();\n\n/**\n * Infer the single Arrow element type an array's contents share.\n *\n * Arrow lists are homogeneous, so a genuinely mixed array (`[1, \"a\"]`,\n * or structs with differing field sets) has no faithful representation and is\n * rejected rather than silently coerced. Nulls are skipped — they are\n * representable at any element type — and an array with no non-null element\n * falls back to {@link emptyListElementType}.\n */\nfunction inferElementType(values: any[]): VgiDataType {\n let elementType: VgiDataType | null = null;\n let elementSig = \"\";\n for (const v of values) {\n if (v === null || v === undefined) continue;\n const t = inferFieldType(v);\n const sig = typeSignature(t);\n if (elementType === null) {\n elementType = t;\n elementSig = sig;\n continue;\n }\n if (sig !== elementSig) {\n throw new Error(\n `inferFieldType: arrays in userState must be homogeneous; ` +\n `found both '${elementSig}' and '${sig}' in the same array ` +\n `(split the values into separate fields, or normalize them to one type)`,\n );\n }\n }\n return elementType ?? emptyListElementType();\n}\n\n/** Infer an Arrow DataType from a JS value for user state serialization. */\nexport function inferFieldType(value: any): VgiDataType {\n if (value === null || value === undefined) return nullType();\n switch (typeof value) {\n case \"number\": return float64();\n case \"bigint\": return int64();\n case \"string\": return utf8();\n case \"boolean\": return bool();\n case \"object\":\n if (value instanceof Uint8Array || value instanceof ArrayBuffer) return binary();\n if (ArrayBuffer.isView(value)) return binary();\n if (Array.isArray(value)) {\n return makeList(field(LIST_CHILD_NAME, inferElementType(value), true));\n }\n if (value instanceof Map) {\n throw new Error(`inferFieldType: Map is not supported in userState (use a plain object instead)`);\n }\n if (value instanceof Set) {\n throw new Error(`inferFieldType: Set is not supported in userState (use an array or plain object instead)`);\n }\n if (value instanceof Date) {\n throw new Error(`inferFieldType: Date is not supported in userState (use a number (epoch ms) or ISO string instead)`);\n }\n if (value instanceof RegExp) {\n throw new Error(`inferFieldType: RegExp is not supported in userState (use a string pattern instead)`);\n }\n // Plain object → Struct\n const fields = Object.entries(value).map(\n ([k, v]) => field(k, inferFieldType(v), true),\n );\n return makeStruct(fields);\n default:\n throw new Error(`inferFieldType: unsupported type '${typeof value}'`);\n }\n}\n\n/**\n * Serialize userState to Arrow IPC bytes.\n * Infers schema from the JS object at runtime. Arrow IPC is self-describing,\n * so deserialization doesn't need the schema ahead of time.\n *\n * For an empty object `{}`, we emit a 0-row batch with empty schema —\n * `deserializeUserState` recognizes that shape and returns `{}` rather than\n * `null`. (`null` is reserved for \"no userState declared at all\".)\n */\nexport function serializeUserState(userState: any): Uint8Array | null {\n if (userState == null) return null;\n const entries = Object.entries(userState);\n if (entries.length === 0) {\n // 0-row, 0-field batch — round-trips back to {} via deserializeUserState.\n return serializeBatch(batchFromColumns({}, makeSchema([])));\n }\n const fields = entries.map(\n ([k, v]) => field(k, inferFieldType(v), true),\n );\n const sch = makeSchema(fields);\n const columns: Record<string, any[]> = {};\n for (const [key, val] of entries) {\n columns[key] = [val];\n }\n return serializeBatch(batchFromColumns(columns, sch));\n}\n\n/**\n * Extract a typed value from an Arrow column in RICH form via the codec /\n * canonical path. Backend-agnostic and lossless (BigInt for Int64, Uint8Array\n * for Binary, plain objects for Struct). userState forbids Date/temporal types\n * (see {@link inferFieldType}), so rich == canonical for everything stored here.\n */\nfunction extractTypedValue(col: any, index: number, type: VgiDataType): any {\n return codecFor(type).canonicalToRich(readCanonicalValue(type, col, index));\n}\n\n/**\n * Deserialize userState from Arrow IPC bytes.\n * Reconstructs a plain JS object, preserving BigInt for Int64 columns.\n */\nexport function deserializeUserState(bytes: Uint8Array | null): any {\n if (bytes == null) return null;\n const batch = deserializeBatch(bytes);\n if (batch.numRows === 0 && batch.schema.fields.length === 0) {\n return {};\n }\n if (batch.numRows === 0) return null;\n const result: Record<string, any> = {};\n for (const f of batch.schema.fields) {\n const col = batch.getChild(f.name);\n if (!col) { result[f.name] = null; continue; }\n result[f.name] = extractTypedValue(col, 0, f.type);\n }\n return result;\n}\n\n/** Arrow IPC state serializer — stores all data as native binary columns. */\nexport const arrowStateSerializer: StateSerializer = {\n serialize(state: any): Uint8Array {\n const columns: Record<string, any[]> = {\n function_name: [TEXT_ENCODER.encode(state.functionName)],\n init_request: [state.initRequestIpc],\n execution_id: [state.executionId],\n max_workers: [state.maxWorkers],\n opaque_data: [state.opaqueData ?? null],\n is_producer: [state.isProducer],\n user_state: [serializeUserState(state.userState)],\n };\n const batch = batchFromColumns(columns, EXCHANGE_STATE_SCHEMA);\n return serializeBatch(batch);\n },\n\n deserialize(bytes: Uint8Array): any {\n const batch = deserializeBatch(bytes);\n const fieldByName = new Map(batch.schema.fields.map((f) => [f.name, f]));\n const get = (name: string) => {\n const col = batch.getChild(name);\n const f = fieldByName.get(name);\n if (!col || !f) return null;\n const type = f.type as unknown as VgiDataType;\n return codecFor(type).canonicalToRich(readCanonicalValue(type, col, 0));\n };\n\n const isProducer = get(\"is_producer\");\n const opaqueDataRaw = get(\"opaque_data\");\n const fnNameRaw = get(\"function_name\");\n\n return {\n functionName: fnNameRaw != null ? TEXT_DECODER.decode(toUint8Array(fnNameRaw)) : \"\",\n initRequestIpc: toUint8Array(get(\"init_request\")),\n executionId: toUint8Array(get(\"execution_id\")),\n maxWorkers: Number(get(\"max_workers\")),\n opaqueData: opaqueDataRaw != null ? toUint8Array(opaqueDataRaw) : null,\n isProducer,\n // vgi-rpc dispatch reads __isProducer to choose producer vs exchange mode\n __isProducer: isProducer,\n userState: deserializeUserState(\n get(\"user_state\") != null ? toUint8Array(get(\"user_state\")) : null,\n ),\n };\n },\n};\n",
|
|
25
|
-
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n//
|
|
24
|
+
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Dynamic-filter state across HTTP turns: a compacted delta history.\n//\n// A table stream's filters can change mid-scan. DuckDB's Top-N operator (and\n// friends) tightens a bound as rows arrive and ships the change as a v2 *delta*\n// on the next tick's `vgi_pushdown_filters` metadata -- and only then: the\n// extension sends each delta ONCE per stream, when a filter's value changes, not\n// on every tick. A byte-stream transport keeps the parsed filters in memory\n// between ticks. An HTTP stream cannot: every turn rebuilds its handlers from the\n// state token, so whatever a delta changed has to ride that token or it is lost\n// on the next turn, and the worker quietly falls back to the init snapshot.\n//\n// Carrying every delta ever received would be the opposite bug: the token grows\n// by a delta per tick and each turn replays all of them, quadratic in the tick\n// count (vgi-python 0283898). So the token carries a COMPACTED history -- for\n// each (id, revision) of the live state, tombstones included, the first delta\n// that carried it. Replaying just those reproduces the same predicates, values\n// and revisions: an earlier update to an id is overwritten by its current\n// revision, and a later one was stale when it arrived and is stale again on\n// replay. The history is therefore bounded by the number of predicate ids, not\n// the number of ticks. Replay cannot always reproduce predicate ORDER (an id\n// removed and later re-added moves to the end), so the live order is recorded\n// alongside and restored after replay.\n\nimport { type VgiBatch, deserializeBatch, readCanonicalValue } from \"../arrow/index.js\";\nimport { FilterV2Error } from \"./deserialize.js\";\nimport type { PushdownFilters } from \"./evaluate.js\";\n\n/** Encoded-size limit on the base64 `vgi_pushdown_filters` value. */\nconst MAX_ENCODED_DELTA_BYTES = 24 << 20;\n/** Decoded-size limit on one delta's Arrow IPC payload. */\nconst MAX_DELTA_IPC_BYTES = 17 << 20;\nconst BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;\n\n/**\n * What an HTTP stream carries between turns to rebuild its dynamic filters.\n *\n * Both halves are plain data so the state serializer can put them in the\n * cursor, and both are bounded by the number of predicate ids the scan has\n * seen (see {@link recordFilterDelta}).\n */\nexport interface FilterDeltaHistory {\n /** Arrow IPC bytes of each delta still needed, in arrival order. */\n readonly deltas: readonly Uint8Array[];\n /** The live predicate ids, in the order the stream had them. */\n readonly order: readonly string[];\n}\n\n/** A stream that has applied no delta. */\nexport const EMPTY_FILTER_HISTORY: FilterDeltaHistory = Object.freeze({\n deltas: Object.freeze([]) as readonly Uint8Array[],\n order: Object.freeze([]) as readonly string[],\n});\n\n/**\n * Decode the base64 `vgi_pushdown_filters` metadata value into delta IPC bytes.\n *\n * Validates the encoding strictly and enforces the encoded and decoded size\n * limits before anything is parsed.\n */\nexport function decodeDynamicFilterMetadata(encoded: string): Uint8Array {\n if (new TextEncoder().encode(encoded).byteLength > MAX_ENCODED_DELTA_BYTES) {\n throw new Error(\"base64 dynamic filter metadata exceeds the encoded-size limit\");\n }\n if (encoded.length % 4 !== 0 || !BASE64.test(encoded)) {\n throw new Error(\"dynamic filter metadata is not valid base64\");\n }\n const binary = (globalThis as any).atob\n ? (globalThis as any).atob(encoded)\n : Buffer.from(encoded, \"base64\").toString(\"binary\");\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n if (bytes.byteLength > MAX_DELTA_IPC_BYTES) {\n throw new Error(\"dynamic filter IPC payload exceeds the encoded-size limit\");\n }\n return bytes;\n}\n\n/** Read one delta's IPC bytes into its single document batch. */\nexport function decodeFilterDelta(bytes: Uint8Array): VgiBatch {\n if (bytes.byteLength > MAX_DELTA_IPC_BYTES) {\n throw new Error(\"dynamic filter IPC payload exceeds the encoded-size limit\");\n }\n const batch = bytes.byteLength > 0 ? deserializeBatch(bytes) : null;\n if (!batch || (batch.numRows === 0 && batch.schema.fields.length === 0)) {\n throw new Error(\"dynamic filter metadata must contain one RecordBatch\");\n }\n return batch as VgiBatch;\n}\n\n/**\n * The `(id, revision)` of every update a delta document carries, as\n * `id\\0revision` keys.\n *\n * A structural read only, for bookkeeping over deltas that have already been\n * applied -- and therefore validated -- by {@link PushdownFilters.applyDelta}.\n * It neither applies nor validates anything.\n */\nfunction deltaRevisionKeys(batch: VgiBatch): string[] {\n const column = batch.getChildAt(0);\n if (!column) throw new FilterV2Error(\"delta document has no filter_spec column\");\n const raw = readCanonicalValue(batch.schema.fields[0].type, column, 0);\n const document = JSON.parse(String(raw)) as { updates?: Array<{ id: string; revision: number }> };\n return (document.updates ?? []).map((update) => revisionKey(update.id, update.revision));\n}\n\nfunction revisionKey(id: string, revision: number): string {\n return `${id}\\u0000${revision}`;\n}\n\n/**\n * Apply one tick's delta and return the new filters plus the history a cursor\n * must carry to rebuild them.\n *\n * The history is compacted to the deltas that installed some predicate's\n * CURRENT revision, tombstones included: for each `(id, revision)` of the live\n * state, the first delta (in arrival order) carrying it. That delta is the one\n * that was applied -- any later delta carrying the same revision was stale on\n * arrival -- and a delta none of whose updates is current can never matter\n * again, because revisions only move forward.\n *\n * @param current - The stream's filters before this delta.\n * @param history - The compacted history those filters were rebuilt from.\n * @param deltaBytes - The IPC bytes of the delta this tick carried.\n */\nexport function recordFilterDelta(\n current: PushdownFilters,\n history: FilterDeltaHistory,\n deltaBytes: Uint8Array,\n): { filters: PushdownFilters; history: FilterDeltaHistory } {\n const incoming = decodeFilterDelta(deltaBytes);\n // Assignment happens only after complete validation, so a rejected delta\n // leaves the caller's prior state (and history) intact.\n const filters = current.applyDelta(incoming);\n const wanted = new Set<string>();\n for (const [id, revision] of filters.revisions) wanted.add(revisionKey(id, revision));\n const deltas: Uint8Array[] = [];\n const consider = (bytes: Uint8Array, batch: VgiBatch): void => {\n let carries = false;\n for (const key of deltaRevisionKeys(batch)) {\n if (wanted.delete(key)) carries = true;\n }\n if (carries) deltas.push(bytes);\n };\n for (const bytes of history.deltas) consider(bytes, decodeFilterDelta(bytes));\n consider(deltaBytes, incoming);\n return { filters, history: { deltas, order: filters.predicates.map((predicate) => predicate.id) } };\n}\n\nconst HISTORY_FORMAT_VERSION = 1;\nconst UTF8_ENCODER = new TextEncoder();\nconst UTF8_DECODER = new TextDecoder(\"utf-8\", { fatal: true });\n\n/**\n * Encode a history for the state token, or `null` when there is nothing to\n * carry (no delta applied, which is every stream without dynamic filters).\n *\n * Layout (little-endian): `u8 version | u32 n | n x (u32 len, delta IPC) |\n * u32 m | m x (u32 len, utf8 id)`.\n */\nexport function encodeFilterHistory(history: FilterDeltaHistory | null | undefined): Uint8Array | null {\n if (!history || history.deltas.length === 0) return null;\n const ids = history.order.map((id) => UTF8_ENCODER.encode(id));\n let size = 1 + 4 + 4;\n for (const delta of history.deltas) size += 4 + delta.byteLength;\n for (const id of ids) size += 4 + id.byteLength;\n const out = new Uint8Array(size);\n const view = new DataView(out.buffer);\n let offset = 0;\n out[offset++] = HISTORY_FORMAT_VERSION;\n const put = (chunks: readonly Uint8Array[]): void => {\n view.setUint32(offset, chunks.length, true);\n offset += 4;\n for (const chunk of chunks) {\n view.setUint32(offset, chunk.byteLength, true);\n offset += 4;\n out.set(chunk, offset);\n offset += chunk.byteLength;\n }\n };\n put(history.deltas);\n put(ids);\n return out;\n}\n\n/** Decode {@link encodeFilterHistory}'s bytes; `null`/empty is the empty history. */\nexport function decodeFilterHistory(bytes: Uint8Array | null | undefined): FilterDeltaHistory {\n if (!bytes || bytes.byteLength === 0) return EMPTY_FILTER_HISTORY;\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n let offset = 0;\n const need = (n: number): void => {\n if (offset + n > bytes.byteLength) throw new Error(\"dynamic filter history in the state token is truncated\");\n };\n need(1);\n if (bytes[offset++] !== HISTORY_FORMAT_VERSION) {\n throw new Error(\"dynamic filter history in the state token has an unknown format\");\n }\n const take = (): Uint8Array[] => {\n need(4);\n const count = view.getUint32(offset, true);\n offset += 4;\n const chunks: Uint8Array[] = [];\n for (let i = 0; i < count; i++) {\n need(4);\n const length = view.getUint32(offset, true);\n offset += 4;\n need(length);\n // A copy, not a view: Arrow readers want their own aligned buffer.\n chunks.push(bytes.slice(offset, offset + length));\n offset += length;\n }\n return chunks;\n };\n const deltas = take();\n const order = take().map((id) => UTF8_DECODER.decode(id));\n if (offset !== bytes.byteLength) throw new Error(\"dynamic filter history in the state token has trailing bytes\");\n return { deltas, order };\n}\n\n/**\n * Rebuild a turn's filters from the init snapshot plus a carried history.\n *\n * Every delta here was validated when it first arrived and has ridden a\n * worker-sealed token since, but it is re-applied through the same strict\n * parser -- a TS delta parse is structural, with no bind to skip.\n *\n * @param filters - The filters parsed from the init request's snapshot.\n * @param history - The history {@link recordFilterDelta} produced.\n */\nexport function replayFilterHistory(\n filters: PushdownFilters | undefined,\n history: FilterDeltaHistory | null | undefined,\n): PushdownFilters | undefined {\n if (!history || history.deltas.length === 0) return filters;\n if (!filters) throw new Error(\"dynamic filter history carried without an initial snapshot\");\n let replayed = filters;\n for (const bytes of history.deltas) replayed = replayed.applyDelta(decodeFilterDelta(bytes));\n return replayed.withPredicateOrder(history.order);\n}\n",
|
|
25
|
+
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Synchronous zstd, where the runtime has it.\n//\n// The state serializer is synchronous (vgi-rpc's StateSerializer contract), so\n// it cannot use the async helpers vgi-rpc exposes. Bun has\n// `Bun.zstdCompressSync`; Node >= 22.15 has `zlib.zstdCompressSync`, reached\n// from ESM through `process.getBuiltinModule`. Anything else (workerd, a\n// browser) gets `null` and callers fall back to storing bytes uncompressed.\n\n/** A synchronous zstd codec. */\nexport interface ZstdSync {\n compress(data: Uint8Array): Uint8Array;\n decompress(data: Uint8Array): Uint8Array;\n}\n\n/** Level 3 is zstd's default: ~3.4x on an init request, ~50 us for 9 KB. */\nconst LEVEL = 3;\n\nfunction resolveZstdSync(): ZstdSync | null {\n const bun = (globalThis as any).Bun;\n if (typeof bun?.zstdCompressSync === \"function\" && typeof bun?.zstdDecompressSync === \"function\") {\n return {\n compress: (data) => new Uint8Array(bun.zstdCompressSync(data, { level: LEVEL })),\n // Copied into a fresh buffer: Arrow readers want byteOffset 0.\n decompress: (data) => new Uint8Array(bun.zstdDecompressSync(data)),\n };\n }\n let zlib: any = null;\n try {\n zlib = (globalThis as any).process?.getBuiltinModule?.(\"node:zlib\") ?? null;\n } catch {\n zlib = null;\n }\n if (typeof zlib?.zstdCompressSync === \"function\" && typeof zlib?.zstdDecompressSync === \"function\") {\n const params = { [zlib.constants.ZSTD_c_compressionLevel]: LEVEL };\n return {\n compress: (data) => new Uint8Array(zlib.zstdCompressSync(data, { params })),\n decompress: (data) => new Uint8Array(zlib.zstdDecompressSync(data)),\n };\n }\n return null;\n}\n\nlet resolved: ZstdSync | null | undefined;\n\n/** This runtime's synchronous zstd codec, or `null` when it has none. */\nexport function zstdSync(): ZstdSync | null {\n if (resolved === undefined) resolved = resolveZstdSync();\n return resolved;\n}\n",
|
|
26
26
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Arguments container for VGI function invocations.\n// Holds positional and named scalar values from DuckDB.\n\nimport type { VgiSchema } from \"../arrow/index.js\";\n\nexport class Arguments {\n readonly positional: (any | null)[];\n readonly named: Map<string, any | null>;\n /** Schema of the arguments batch (preserves original Arrow types). */\n readonly argumentsSchema: VgiSchema | null;\n\n constructor(\n positional: (any | null)[] = [],\n named: Map<string, any | null> = new Map(),\n argumentsSchema: VgiSchema | null = null,\n ) {\n this.positional = positional;\n this.named = named;\n this.argumentsSchema = argumentsSchema;\n }\n\n /**\n * Get an argument by position (number) or name (string).\n */\n get(position: number | string, defaultValue?: any): any {\n if (typeof position === \"number\") {\n if (position < this.positional.length) {\n const val = this.positional[position];\n if (val === null || val === undefined) {\n return defaultValue !== undefined ? defaultValue : null;\n }\n return unwrapScalar(val);\n }\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Positional argument ${position} not found`);\n }\n if (this.named.has(position)) {\n const val = this.named.get(position);\n if (val === null || val === undefined) {\n return defaultValue !== undefined ? defaultValue : null;\n }\n return unwrapScalar(val);\n }\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Named argument '${position}' not found`);\n }\n\n get length(): number {\n return this.positional.length;\n }\n}\n\n/**\n * Unwrap an Arrow Scalar to a plain JS value.\n */\nfunction unwrapScalar(val: any): any {\n if (val === null || val === undefined) return null;\n // If it's already a primitive, return it\n if (typeof val !== \"object\") return val;\n // Arrow Scalar objects have a valueOf() method\n if (typeof val.valueOf === \"function\") {\n let v: any;\n try {\n v = val.valueOf();\n } catch {\n // valueOf() may throw for large Decimal values (e.g. HUGEINT)\n return val;\n }\n // BigInt -> Number for safe integers\n if (typeof v === \"bigint\") {\n if (v >= Number.MIN_SAFE_INTEGER && v <= Number.MAX_SAFE_INTEGER) {\n return Number(v);\n }\n return v;\n }\n return v;\n }\n return val;\n}\n",
|
|
27
27
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Arguments wire format — single-row Arrow batch with one \"args\" Struct\n// column whose children are named `positional_<i>` / `named_<name>`.\n// Matches Python's Arguments.serialize_to_bytes().\n\nimport {\n type VgiDataType,\n type VgiField,\n schema as makeSchema,\n field,\n struct as makeStruct,\n utf8,\n binary,\n int64,\n bool,\n nullType,\n isInt,\n batchFromColumns,\n serializeBatch,\n deserializeBatch,\n readCanonicalValue,\n} from \"../../arrow/index.js\";\nimport { codecFor } from \"../../arrow/codec/registry.js\";\nimport { Arguments } from \"../../arguments/arguments.js\";\n\nexport function serializeArguments(args: Arguments): Uint8Array {\n // Arguments are serialized as a single-row batch with one \"args\" Struct column.\n // The struct has fields: \"positional_0\", \"positional_1\", ... and \"named_<name>\".\n\n const structFields: VgiField[] = [];\n const structValues: Record<string, any> = {};\n\n for (let i = 0; i < args.positional.length; i++) {\n const val = args.positional[i];\n const fieldName = `positional_${i}`;\n structFields.push(field(fieldName, inferScalarType(val), true));\n structValues[fieldName] = val;\n }\n\n for (const [name, val] of args.named) {\n const fieldName = `named_${name}`;\n structFields.push(field(fieldName, inferScalarType(val), true));\n structValues[fieldName] = val;\n }\n\n const structType = makeStruct(structFields);\n const sch = makeSchema([field(\"args\", structType, true)]);\n\n // Coerce JS numbers to BigInt for Int64 children — both backends require\n // BigInt at 64-bit width.\n const structRow: Record<string, any> = {};\n for (const f of structFields) {\n let val = structValues[f.name];\n if (isInt(f.type) && (f.type as any).bitWidth === 64 && typeof val === \"number\") {\n val = BigInt(val);\n }\n structRow[f.name] = val;\n }\n\n const batch = batchFromColumns({ args: [structRow] }, sch);\n return serializeBatch(batch);\n}\n\nfunction inferScalarType(val: any): VgiDataType {\n if (val === null || val === undefined) return nullType();\n if (typeof val === \"string\") return utf8();\n if (typeof val === \"boolean\") return bool();\n if (typeof val === \"number\") return int64();\n if (typeof val === \"bigint\") return int64();\n if (val instanceof Uint8Array || val instanceof ArrayBuffer) return binary();\n return utf8(); // fallback (e.g. an Int32Array INTERVAL quad -> stringified)\n}\n\nexport function deserializeArguments(bytes: Uint8Array): Arguments {\n if (!bytes || bytes.length === 0) return new Arguments();\n\n // Ensure we have a clean copy (not a view into a larger buffer)\n const cleanBytes = bytes.byteOffset !== 0 || bytes.byteLength !== bytes.buffer.byteLength\n ? new Uint8Array(bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength))\n : bytes;\n\n const batch = deserializeBatch(cleanBytes);\n const positional: any[] = [];\n const named = new Map<string, any>();\n\n if (batch.numRows === 0) {\n return new Arguments(positional, named);\n }\n\n // Arguments are serialized as a single \"args\" Struct column.\n // The struct has fields named \"positional_0\", \"positional_1\", etc.\n // for positional args, and \"named_<name>\" for named args.\n const argsCol = batch.getChild(\"args\");\n if (argsCol) {\n // Extract per-positional types from the struct's children\n const argsStructType = argsCol.type as any;\n const structSchema = argsStructType.children\n ? makeSchema(argsStructType.children)\n : batch.schema;\n\n // Read the args struct via the codec/canonical path (backend-agnostic,\n // lossless, RICH) — surfaces as a plain { field: value } object.\n const structType = argsCol.type as unknown as VgiDataType;\n const structVal = codecFor(structType).canonicalToRich(\n readCanonicalValue(structType, argsCol, 0),\n ) as any;\n if (structVal && typeof structVal === \"object\") {\n const dict: Record<string, any> = structVal;\n for (const [key, value] of Object.entries(dict)) {\n if (key.startsWith(\"positional_\")) {\n const idx = parseInt(key.slice(\"positional_\".length), 10);\n while (positional.length <= idx) positional.push(null);\n positional[idx] = value;\n } else if (key.startsWith(\"named_\")) {\n const name = key.slice(\"named_\".length);\n named.set(name, value);\n }\n }\n }\n return new Arguments(positional, named, structSchema);\n }\n\n // Fallback: flat columns (legacy format - each field is a column)\n const sch = batch.schema;\n if (!sch || sch.fields.length === 0) {\n return new Arguments(positional, named);\n }\n\n for (const f of sch.fields) {\n const col = batch.getChild(f.name);\n const ftype = f.type as unknown as VgiDataType;\n const val = col\n ? codecFor(ftype).canonicalToRich(readCanonicalValue(ftype, col, 0))\n : null;\n\n if (f.name.startsWith(\"positional_\")) {\n const idx = parseInt(f.name.slice(\"positional_\".length), 10);\n while (positional.length <= idx) positional.push(null);\n positional[idx] = val;\n } else if (f.name.startsWith(\"named_\")) {\n const name = f.name.slice(\"named_\".length);\n named.set(name, val);\n } else {\n // Try numeric field name (old format)\n const metadata = f.metadata;\n const isNamed = metadata?.get?.(\"vgi_arg\") === \"named\";\n if (isNamed) {\n named.set(f.name, val);\n } else {\n const idx = parseInt(f.name, 10);\n if (!isNaN(idx)) {\n while (positional.length <= idx) positional.push(null);\n positional[idx] = val;\n }\n }\n }\n }\n\n return new Arguments(positional, named, sch);\n}\n",
|
|
28
28
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Shared helpers for protocol wire serialization.\n\nimport {\n type VgiSchema,\n type VgiBatch,\n isInt,\n batchFromColumns,\n} from \"../../arrow/index.js\";\nimport { toUint8Array as toUint8ArrayBase } from \"../../util/bytes.js\";\n\n/**\n * Coerce a wire value (string / Uint8Array / Buffer / etc.) to a Uint8Array.\n * Throws when the input is non-null but produces zero bytes — that signals a\n * truly unsupported shape, distinct from a legitimate empty Uint8Array.\n */\nexport function toUint8Array(val: any): Uint8Array {\n if (typeof val === \"string\") return new TextEncoder().encode(val);\n const result = toUint8ArrayBase(val);\n if (result.length === 0 && val != null) {\n throw new Error(`Cannot convert ${typeof val} to Uint8Array`);\n }\n return result;\n}\n\n/**\n * Build a single-row RecordBatch from a {fieldName: value} dict matching the\n * given schema. Auto-coerces JS numbers to BigInt for Int64 fields.\n */\nexport function buildSingleRowBatch(\n schema: VgiSchema,\n values: Record<string, any>,\n): VgiBatch {\n // Build column dict, coercing Int64 numbers to BigInt where the schema\n // declares one — vectorFromArray/columnFromArray rejects plain Number for\n // 64-bit ints under both backends.\n const cols: Record<string, any[]> = {};\n for (const f of schema.fields) {\n let val = values[f.name];\n if (isInt(f.type) && (f.type as any).bitWidth === 64 && typeof val === \"number\") {\n val = BigInt(val);\n }\n cols[f.name] = [val];\n }\n return batchFromColumns(cols, schema);\n}\n",
|
|
29
29
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// BindRequest / BindResponse wire serialization. Schemas mirror Python's\n// ArrowSerializableDataclass field declaration order so the format is\n// positional-compatible with the Python reader.\n\nimport { type VgiSchema, schema, field, type VgiBatch, type VgiDataType, utf8, binary, bool, struct, dictionary, int16, list } from \"../../arrow/index.js\";\nimport { Arguments } from \"../../arguments/arguments.js\";\nimport { FunctionType } from \"../../types.js\";\nimport type { BindRequest, BindResponse, CopyFromContext, CopyToContext } from \"../types.js\";\nimport {\n serializeSchema,\n deserializeSchema,\n serializeBatch,\n deserializeBatch,\n} from \"../../util/arrow/index.js\";\nimport { toUint8Array, buildSingleRowBatch } from \"./shared.js\";\nimport { serializeArguments, deserializeArguments } from \"./arguments.js\";\n\n// The BindRequest wire record. This must equal `BindRequestSchema` in\n// src/generated/vgi-protocol-schemas.ts EXACTLY — same columns, same order,\n// same types, same nullability — and src/__tests__/wire-schema-completeness.ts\n// asserts that it does.\n//\n// Exactly, not approximately. It is tempting to reason that every peer reads\n// these columns by name, so a nullable column with nothing to say can be left\n// out and a bind that opens no COPY scan can keep a shorter \"legacy\" shape.\n// That is what this file used to do, and it is wrong: vgi-rpc-go validates a\n// request against its declared parameter contract with `arrow.Schema.Equal`,\n// which is order-, name-, type- AND nullability-sensitive. A record short one\n// nullable column fails EVERY call of that shape, with a message that prints\n// two schemas in full and leaves the reader to diff them by eye.\n//\n// So `copy_from` and `copy_to` are always present and null on a non-COPY bind,\n// `schema_path` and `argument_names` are last, and `function_type` is a dictionary\n// rather than plain utf8.\nconst COPY_FROM_STRUCT_TYPE = struct([\n field(\"format\", utf8(), false),\n field(\"file_path\", utf8(), false),\n field(\"expected_schema\", binary(), false),\n]);\n\nconst COPY_TO_STRUCT_TYPE = struct([\n field(\"format\", utf8(), false),\n field(\"file_path\", utf8(), false),\n]);\n\nconst BIND_REQUEST_SCHEMA = schema([\n field(\"function_name\", utf8(), false),\n field(\"arguments\", binary(), false),\n field(\"function_type\", dictionary(utf8(), int16()), false),\n field(\"input_schema\", binary(), true),\n field(\"settings\", binary(), true),\n field(\"secrets\", binary(), true),\n field(\"attach_opaque_data\", binary(), true),\n field(\"transaction_opaque_data\", binary(), true),\n field(\"resolved_secrets_provided\", bool(), false),\n // Time travel AT clause. Both null when the scan has no AT clause.\n field(\"at_unit\", utf8(), true),\n field(\"at_value\", utf8(), true),\n // Null unless this bind opens a COPY scan / sink.\n field(\"copy_from\", COPY_FROM_STRUCT_TYPE, true),\n field(\"copy_to\", COPY_TO_STRUCT_TYPE, true),\n // Catalog schema owning the function. A worker may register one name in\n // several schemas, so the bare name is not a unique key — resolution is by\n // (schema_path, function_name). Null for callers with no catalog context.\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n // Complete resolved logical signature, including const args and varargs.\n field(\"argument_names\", list(field(\"item\", utf8(), true)), true),\n]);\n\nexport function serializeBindRequest(req: BindRequest): VgiBatch {\n return buildSingleRowBatch(BIND_REQUEST_SCHEMA, {\n function_name: req.function_name,\n arguments: serializeArguments(req.arguments),\n function_type: req.function_type,\n input_schema: req.input_schema ? serializeSchema(req.input_schema) : null,\n settings: req.settings ? serializeBatch(req.settings) : null,\n secrets: req.secrets ? serializeBatch(req.secrets) : null,\n attach_opaque_data: req.attach_opaque_data ?? null,\n transaction_opaque_data: req.transaction_opaque_data ?? null,\n resolved_secrets_provided: req.resolved_secrets_provided ?? false,\n at_unit: req.at_unit ?? null,\n at_value: req.at_value ?? null,\n copy_from: req.copy_from\n ? {\n format: req.copy_from.format,\n file_path: req.copy_from.file_path,\n expected_schema: serializeSchema(req.copy_from.expected_schema),\n }\n : null,\n copy_to: req.copy_to\n ? { format: req.copy_to.format, file_path: req.copy_to.file_path }\n : null,\n schema_path: req.schema_path ?? null,\n argument_names: req.argument_names ?? null,\n });\n}\n\nfunction parseCopyFromContext(raw: any): CopyFromContext | null {\n // The struct column decodes to a plain { format, file_path, expected_schema }\n // object via the codec/canonical path (expected_schema is binary -> Uint8Array).\n if (raw == null) return null;\n const format = raw.format;\n const filePath = raw.file_path;\n const schemaBytes = raw.expected_schema;\n if (format == null || filePath == null || schemaBytes == null) return null;\n return {\n format: String(format),\n file_path: String(filePath),\n expected_schema: deserializeSchema(toUint8Array(schemaBytes)),\n };\n}\n\nfunction parseCopyToContext(raw: any): CopyToContext | null {\n // The struct column decodes to a plain { format, file_path } object via the\n // codec/canonical path.\n if (raw == null) return null;\n const format = raw.format;\n const filePath = raw.file_path;\n if (format == null || filePath == null) return null;\n return { format: String(format), file_path: String(filePath) };\n}\n\nexport function deserializeBindRequest(\n params: Record<string, any>\n): BindRequest {\n // params come from the RPC layer - already extracted from a single-row batch\n // arguments may be null/undefined when DuckDB sends empty args\n const args = params.arguments\n ? deserializeArguments(toUint8Array(params.arguments))\n : new Arguments();\n\n // function_type might be a string directly or enum name\n let functionType: FunctionType;\n const ftStr = String(params.function_type);\n if (ftStr === \"scalar\" || ftStr === \"SCALAR\") {\n functionType = FunctionType.SCALAR;\n } else if (ftStr === \"table\" || ftStr === \"TABLE\") {\n functionType = FunctionType.TABLE;\n } else if (ftStr === \"table_buffering\" || ftStr === \"TABLE_BUFFERING\") {\n functionType = FunctionType.TABLE_BUFFERING;\n } else if (ftStr === \"aggregate\" || ftStr === \"AGGREGATE\") {\n functionType = FunctionType.AGGREGATE;\n } else {\n functionType = ftStr as FunctionType;\n }\n\n return {\n function_name: params.function_name,\n arguments: args,\n function_type: functionType,\n input_schema: params.input_schema\n ? deserializeSchema(toUint8Array(params.input_schema))\n : null,\n settings: params.settings\n ? deserializeBatch(toUint8Array(params.settings))\n : null,\n secrets: params.secrets\n ? deserializeBatch(toUint8Array(params.secrets))\n : null,\n attach_opaque_data: params.attach_opaque_data ? toUint8Array(params.attach_opaque_data) : null,\n transaction_opaque_data: params.transaction_opaque_data\n ? toUint8Array(params.transaction_opaque_data)\n : null,\n resolved_secrets_provided: params.resolved_secrets_provided ?? false,\n // Empty string -> null (matches the C++ BuildBindRequest convention).\n at_unit: params.at_unit ? String(params.at_unit) : null,\n at_value: params.at_value ? String(params.at_value) : null,\n // Empty string -> null, same convention as at_unit/at_value.\n schema_path: params.schema_path\n ? (Array.isArray(params.schema_path) ? params.schema_path : [...params.schema_path]).map(String)\n : null,\n argument_names: params.argument_names\n ? (Array.isArray(params.argument_names) ? params.argument_names : [...params.argument_names])\n .map((value: unknown) => value == null ? null : String(value))\n : null,\n // COPY ... FROM context — absent for ordinary scans (params.copy_from\n // undefined -> null). The struct column decodes to a plain object.\n copy_from: parseCopyFromContext(params.copy_from),\n // COPY ... TO context — absent for ordinary scans / COPY FROM.\n copy_to: parseCopyToContext(params.copy_to),\n };\n}\n\nexport function serializeBindResponse(\n resp: BindResponse\n): Record<string, any> {\n return {\n output_schema: serializeSchema(resp.output_schema),\n opaque_data: resp.opaque_data ?? null,\n lookup_secret_types: resp.lookup_secret_types ?? [],\n lookup_scopes: resp.lookup_scopes ?? [],\n lookup_names: resp.lookup_names ?? [],\n };\n}\n\nexport function deserializeBindResponse(\n params: Record<string, any>\n): BindResponse {\n const toStrArray = (val: any): string[] => {\n if (!val) return [];\n const arr = Array.isArray(val) ? val : [...val];\n return arr.filter((v: any) => v != null).map(String);\n };\n return {\n output_schema: deserializeSchema(toUint8Array(params.output_schema)),\n opaque_data: params.opaque_data ? toUint8Array(params.opaque_data) : null,\n lookup_secret_types: toStrArray(params.lookup_secret_types),\n lookup_scopes: toStrArray(params.lookup_scopes),\n lookup_names: toStrArray(params.lookup_names),\n };\n}\n\n// BIND_REQUEST_SCHEMA has no codegen counterpart — the generated\n// BindParamsSchema is only the `{request: binary}` envelope, so the inner\n// record is spelled out above. The BindResponse copy that used to sit beside\n// it did have one, and the two had already drifted: this file called\n// `opaque_data` nullable where the generated BindResultSchema calls it\n// non-null. Nobody read the copy (handlers/function.ts wraps with the\n// generated schema), which is exactly how a duplicate goes stale unnoticed —\n// and a stale copy is how a *correct* client ends up rejected at its first\n// call. Use BindResultSchema from src/generated/vgi-protocol-schemas.ts.\nexport { BIND_REQUEST_SCHEMA };\n",
|
|
30
30
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// InitRequest / GlobalInitResponse wire serialization. Schema mirrors\n// vgi-python's InitRequest dataclass — outer wire shape:\n// bind_call: binary (nested IPC of BindRequest)\n// output_schema: binary (nullable serialized Schema)\n// bind_opaque_data: binary (nullable)\n// projection_ids: list<int64> (nullable)\n// pushdown_filters: large_binary (nullable) — nested IPC of filter batch\n// join_keys: list<large_binary> (nullable list of IPC-serialized batches)\n// phase: utf8 (nullable) — dictionary(int16,string) in Python\n// execution_id: binary (nullable)\n// init_opaque_data: binary (nullable)\n// Order pushdown hints + TABLESAMPLE pushdown hints follow.\n\nimport {\n type VgiBatch,\n schema as makeSchema,\n field,\n utf8,\n binary,\n int64,\n float64,\n list,\n largeBinary,\n dictionary,\n int16,\n} from \"../../arrow/index.js\";\n// RecordBatch type alias kept for the joinKeys closure below — it's a runtime\n// value that lands in BindRequest, not a wire shape.\ntype RecordBatch = VgiBatch;\nimport { TableInOutPhase } from \"../../types.js\";\nimport {\n OrderByDirection,\n OrderByNullOrder,\n type InitRequest,\n type GlobalInitResponse,\n} from \"../types.js\";\nimport {\n serializeSchema,\n deserializeSchema,\n serializeBatch,\n deserializeBatch,\n batchToScalarDict,\n} from \"../../util/arrow/index.js\";\nimport { toUint8Array, buildSingleRowBatch } from \"./shared.js\";\nimport { serializeBindRequest, deserializeBindRequest } from \"./bind.js\";\nimport { decodeDictValue } from \"../../util/arrow/index.js\";\n\n// The InitRequest wire record. This must equal `InitRequestSchema` in\n// src/generated/vgi-protocol-schemas.ts EXACTLY — see the note on\n// BIND_REQUEST_SCHEMA in bind.ts for why \"reads by name, so close enough\" is\n// not good enough (vgi-rpc-go compares with `arrow.Schema.Equal`).\n//\n// This declaration had drifted in six ways at once, none of which any test\n// could see: it was missing `split_tokens` and `row_limit` entirely, typed\n// `pushdown_filters` and the `join_keys` items as 32-bit binary where the\n// protocol says large, typed `phase` and the two order-by enums as plain utf8\n// where the protocol says dictionary, and put `finalize_state_id` last instead\n// of ninth.\nconst INIT_REQUEST_SCHEMA = makeSchema([\n field(\"bind_call\", binary(), false),\n field(\"output_schema\", binary(), false),\n field(\"bind_opaque_data\", binary(), true),\n field(\"projection_ids\", list(field(\"item\", int64(), true)), true),\n // Large: a serialized filter tree, a set of join keys, or a batch of split\n // tokens can exceed the 2 GiB that 32-bit offsets address.\n field(\"pushdown_filters\", largeBinary(), true),\n field(\"join_keys\", list(field(\"item\", largeBinary(), true)), true),\n field(\"split_tokens\", list(field(\"item\", largeBinary(), true)), true),\n field(\"row_limit\", int64(), true),\n field(\"phase\", dictionary(utf8(), int16()), true),\n // Buffered-table finalize stream identifier.\n field(\"finalize_state_id\", binary(), true),\n field(\"execution_id\", binary(), true),\n field(\"init_opaque_data\", binary(), true),\n // Per-substream identity for parallel streaming table-in-out (client-minted,\n // stable across this substream's init/process/finalize; null when absent).\n field(\"substream_id\", binary(), true),\n // Order pushdown hints from DuckDB's RowGroupPruner (all null when no hint).\n field(\"order_by_column_name\", utf8(), true),\n field(\"order_by_direction\", dictionary(utf8(), int16()), true),\n field(\"order_by_null_order\", dictionary(utf8(), int16()), true),\n field(\"order_by_limit\", int64(), true),\n // TABLESAMPLE pushdown hints from DuckDB's SamplingPushdown optimizer.\n field(\"tablesample_percentage\", float64(), true),\n field(\"tablesample_seed\", int64(), true),\n]);\n\n// The init stream's header. Codegen emits nothing for it (the generated\n// InitParamsSchema covers only the request envelope), so it is hand-written —\n// which is exactly why it must be hand-written ONCE. It used to be restated at\n// the `protocol.exchange(\"init\", ...)` registration in handlers/function.ts,\n// and two copies of a wire schema is how a *correct* client ends up rejected:\n// the copies disagree on some field's nullability and neither is wrong on its\n// own terms.\nconst GLOBAL_INIT_RESPONSE_SCHEMA = makeSchema([\n field(\"execution_id\", binary(), false),\n field(\"opaque_data\", binary(), true),\n field(\"max_workers\", int64(), false),\n]);\n\nexport function serializeInitRequest(req: InitRequest): VgiBatch {\n const bindCallBatch = serializeBindRequest(req.bind_call);\n const bindCallBytes = serializeBatch(bindCallBatch);\n\n const row: Record<string, any> = {\n bind_call: bindCallBytes,\n output_schema: serializeSchema(req.output_schema),\n bind_opaque_data: req.bind_opaque_data ?? null,\n projection_ids: req.projection_ids?.map((n) => BigInt(n)) ?? null,\n pushdown_filters: req.pushdown_filters\n ? serializeBatch(req.pushdown_filters)\n : null,\n join_keys: (req.join_keys ?? []).map((b) => serializeBatch(b)),\n split_tokens: req.split_tokens ?? null,\n row_limit: req.row_limit ?? null,\n phase: req.phase ?? null,\n finalize_state_id: req.finalize_state_id ?? null,\n execution_id: req.execution_id ?? null,\n init_opaque_data: req.init_opaque_data ?? null,\n substream_id: req.substream_id ?? null,\n order_by_column_name: req.order_by_column_name ?? null,\n order_by_direction: req.order_by_direction ?? null,\n order_by_null_order: req.order_by_null_order ?? null,\n order_by_limit: req.order_by_limit ?? null,\n tablesample_percentage: req.tablesample_percentage ?? null,\n tablesample_seed: req.tablesample_seed ?? null,\n };\n return buildSingleRowBatch(INIT_REQUEST_SCHEMA, row);\n}\n\nexport function deserializeInitRequest(\n params: Record<string, any>\n): InitRequest {\n const bindCallBytes = toUint8Array(params.bind_call);\n const bindCallBatch = deserializeBatch(bindCallBytes);\n // Extract the single row as params via the codec/canonical path.\n const bindParams = batchToScalarDict(bindCallBatch);\n\n const bindCall = deserializeBindRequest(bindParams);\n\n // Parse projection_ids - may be a list/array of Int32\n let projectionIds: number[] | null = null;\n if (params.projection_ids != null) {\n const raw = params.projection_ids;\n if (Array.isArray(raw)) {\n projectionIds = raw.map(Number);\n } else if (raw && typeof raw[Symbol.iterator] === \"function\") {\n projectionIds = [...raw].map(Number);\n }\n }\n\n // Parse phase. DuckDB sends this as a Dictionary on the wire; vgi-rpc's\n // row extractor doesn't auto-decode dictionaries, so values come in as raw\n // Arrow Data objects. decodeDictValue resolves them to the underlying string.\n let phase: TableInOutPhase | null = null;\n const phaseRaw = decodeDictValue(params.phase);\n if (phaseRaw != null) {\n const phaseStr = String(phaseRaw);\n if (phaseStr === \"INPUT\") {\n phase = TableInOutPhase.INPUT;\n } else if (phaseStr === \"FINALIZE\") {\n phase = TableInOutPhase.FINALIZE;\n } else if (phaseStr === \"TABLE_BUFFERING\") {\n phase = TableInOutPhase.TABLE_BUFFERING;\n } else if (phaseStr === \"TABLE_BUFFERING_FINALIZE\") {\n phase = TableInOutPhase.TABLE_BUFFERING_FINALIZE;\n }\n }\n\n // Parse join_keys - list of IPC-serialized RecordBatches\n const joinKeys: RecordBatch[] = [];\n if (params.join_keys != null) {\n const raw = params.join_keys;\n const iter: Iterable<any> = Array.isArray(raw)\n ? raw\n : typeof raw[Symbol.iterator] === \"function\"\n ? raw\n : [];\n for (const entry of iter) {\n if (entry == null) continue;\n try {\n joinKeys.push(deserializeBatch(toUint8Array(entry)));\n } catch {\n // Skip malformed batches rather than failing init.\n }\n }\n }\n\n return {\n bind_call: bindCall,\n output_schema: deserializeSchema(toUint8Array(params.output_schema)),\n bind_opaque_data: params.bind_opaque_data\n ? toUint8Array(params.bind_opaque_data)\n : null,\n projection_ids: projectionIds,\n row_limit: params.row_limit == null ? null : Number(params.row_limit),\n pushdown_filters: params.pushdown_filters\n ? deserializeBatch(toUint8Array(params.pushdown_filters))\n : null,\n join_keys: joinKeys,\n phase,\n finalize_state_id: params.finalize_state_id\n ? toUint8Array(params.finalize_state_id)\n : null,\n // The envelopes this init redeems. Read defensively: the column is absent\n // on a pre-1.4.0 client and null on every non-split scan, and neither is an\n // error — only a present, non-empty list means \"this is a split init\".\n split_tokens: (() => {\n const raw = params.split_tokens;\n if (raw == null) return null;\n const iter: Iterable<unknown> = Array.isArray(raw)\n ? raw\n : typeof (raw as { [Symbol.iterator]?: unknown })[Symbol.iterator] === \"function\"\n ? (raw as Iterable<unknown>)\n : [];\n const tokens = [...iter].filter((e) => e != null).map((e) => toUint8Array(e));\n return tokens.length > 0 ? tokens : null;\n })(),\n execution_id: params.execution_id\n ? toUint8Array(params.execution_id)\n : null,\n init_opaque_data: params.init_opaque_data\n ? toUint8Array(params.init_opaque_data)\n : null,\n substream_id: params.substream_id\n ? toUint8Array(params.substream_id)\n : null,\n order_by_column_name: parseEnum(decodeDictValue(params.order_by_column_name)) ?? null,\n order_by_direction: parseDirection(decodeDictValue(params.order_by_direction)),\n order_by_null_order: parseNullOrder(decodeDictValue(params.order_by_null_order)),\n order_by_limit: parseBigInt(params.order_by_limit),\n tablesample_percentage: parseNumber(params.tablesample_percentage),\n tablesample_seed: parseBigInt(params.tablesample_seed),\n };\n}\n\nfunction parseEnum(v: any): string | null {\n if (v === null || v === undefined) return null;\n return String(v);\n}\nfunction parseDirection(v: any): OrderByDirection | null {\n if (v === null || v === undefined) return null;\n const s = String(v);\n if (s === \"ASC\") return OrderByDirection.ASC;\n if (s === \"DESC\") return OrderByDirection.DESC;\n return null;\n}\nfunction parseNullOrder(v: any): OrderByNullOrder | null {\n if (v === null || v === undefined) return null;\n const s = String(v);\n if (s === \"NULLS_FIRST\") return OrderByNullOrder.NULLS_FIRST;\n if (s === \"NULLS_LAST\") return OrderByNullOrder.NULLS_LAST;\n return null;\n}\nfunction parseBigInt(v: any): bigint | null {\n if (v === null || v === undefined) return null;\n if (typeof v === \"bigint\") return v;\n if (typeof v === \"number\") return BigInt(v);\n try {\n return BigInt(String(v));\n } catch {\n return null;\n }\n}\nfunction parseNumber(v: any): number | null {\n if (v === null || v === undefined) return null;\n if (typeof v === \"number\") return v;\n if (typeof v === \"bigint\") return Number(v);\n const n = Number(v);\n return Number.isNaN(n) ? null : n;\n}\n\nexport function serializeGlobalInitResponse(\n resp: GlobalInitResponse\n): Record<string, any> {\n return {\n execution_id: resp.execution_id,\n opaque_data: resp.opaque_data ?? null,\n max_workers: resp.max_workers,\n };\n}\n\nexport function deserializeGlobalInitResponse(\n params: Record<string, any>\n): GlobalInitResponse {\n return {\n execution_id: toUint8Array(params.execution_id),\n opaque_data: params.opaque_data\n ? toUint8Array(params.opaque_data)\n : null,\n max_workers: Number(params.max_workers),\n };\n}\n\nexport { INIT_REQUEST_SCHEMA, GLOBAL_INIT_RESPONSE_SCHEMA };\n",
|
|
31
31
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// TableFunctionCardinalityRequest / TableCardinality wire serialization.\n\nimport { type VgiSchema, schema, type VgiField, field, type VgiDataType, binary } from \"../../arrow/index.js\";\nimport type { TableFunctionCardinalityRequest, TableCardinality } from \"../types.js\";\nimport { deserializeBatch, batchToScalarDict } from \"../../util/arrow/index.js\";\nimport { toUint8Array } from \"./shared.js\";\nimport { deserializeBindRequest } from \"./bind.js\";\n\nconst TABLE_FUNCTION_CARDINALITY_REQUEST_SCHEMA = schema([\n field(\"bind_call\", binary(), false),\n field(\"bind_opaque_data\", binary(), true),\n]);\n\nexport function deserializeCardinalityRequest(\n params: Record<string, any>\n): TableFunctionCardinalityRequest {\n const bindCallBytes = toUint8Array(params.bind_call);\n const bindCallBatch = deserializeBatch(bindCallBytes);\n const bindParams = batchToScalarDict(bindCallBatch);\n const bindCall = deserializeBindRequest(bindParams);\n\n return {\n bind_call: bindCall,\n bind_opaque_data: params.bind_opaque_data\n ? toUint8Array(params.bind_opaque_data)\n : null,\n };\n}\n\nexport function serializeTableCardinality(\n card: TableCardinality\n): Record<string, any> {\n return {\n estimate: card.estimate,\n max: card.max,\n };\n}\n\n// The TableCardinality result shape used to be restated here as well; it is\n// generated as TableFunctionCardinalityResultSchema, which is what\n// handlers/function.ts already wraps with. Only the request shape stays hand-\n// written, because codegen emits no schema for the inner request record (the\n// generated Params schema is just the `{request: binary}` envelope).\nexport { TABLE_FUNCTION_CARDINALITY_REQUEST_SCHEMA };\n",
|
|
32
|
+
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// The init request an HTTP stream carries in its cursor: packed once, parsed\n// once per process.\n//\n// An HTTP stream has no memory between turns, so its cursor carries the whole\n// init request (~9 KB of Arrow IPC for a DuckDB scan: the bind call with its\n// arguments, settings and sealed attach, the output schema, the filter\n// snapshot) and every turn used to re-parse it: the IPC read, the scalar-dict\n// walk and the nested bind-call / schema / filter reads cost ~0.9 ms, the\n// largest VGI-side share of the ~4 ms a 1000-row turn took. The cursor is also\n// re-sealed and base64-encoded on every turn, so its size is paid twice per\n// turn in AEAD and base64 work, and twice again on the wire.\n//\n// - `packInitRequest` zstd-compresses the request once, at /init (~9 KB ->\n// ~2.6 KB), behind a one-byte codec tag. A runtime without synchronous zstd\n// stores it raw.\n// - `parseCarriedInitRequest` keeps a small per-process LRU from the packed\n// bytes to their parse. It is a pure memo of a pure function: the key is the\n// exact bytes (hash, then a full comparison), so a hit returns precisely\n// what parsing those bytes would -- and those bytes came out of a cursor the\n// worker sealed. Nothing principal-dependent is cached: the split tokens and\n// the sealed attach are still opened, under the caller, on every turn. A\n// miss (cold process, eviction, another replica's stream) parses as before,\n// so correctness never depends on a hit.\n\nimport { deserializeBatch } from \"../arrow/index.js\";\nimport { batchToScalarDict } from \"../util/arrow/index.js\";\nimport { zstdSync } from \"../util/zstd-sync.js\";\nimport { deserializeInitRequest } from \"./serialize.js\";\nimport type { InitRequest } from \"./types.js\";\n\nconst RAW = 0;\nconst ZSTD = 1;\n\n/** Pack an init request's IPC bytes for the cursor: `u8 codec | payload`. */\nexport function packInitRequest(ipc: Uint8Array): Uint8Array {\n const codec = zstdSync();\n const compressed = codec ? codec.compress(ipc) : null;\n const useZstd = compressed !== null && compressed.byteLength < ipc.byteLength;\n const payload = useZstd ? compressed! : ipc;\n const packed = new Uint8Array(payload.byteLength + 1);\n packed[0] = useZstd ? ZSTD : RAW;\n packed.set(payload, 1);\n return packed;\n}\n\nfunction unpackInitRequest(packed: Uint8Array): Uint8Array {\n if (packed.byteLength === 0) throw new Error(\"state token carries no init request\");\n switch (packed[0]) {\n case RAW:\n return packed.slice(1);\n case ZSTD: {\n const codec = zstdSync();\n if (!codec) {\n throw new Error(\n \"state token carries a zstd-compressed init request, and this runtime has no synchronous zstd \" +\n \"(it was minted by a worker running under Bun or Node >= 22.15 with the same signing key)\",\n );\n }\n return codec.decompress(packed.subarray(1));\n }\n default:\n throw new Error(`state token carries an init request with unknown codec ${packed[0]}`);\n }\n}\n\n/** What a continuation needs from the carried init request. */\nexport interface CarriedInitRequest {\n /**\n * The parsed request -- a fresh top-level object with a fresh `bind_call`\n * each call, so the per-turn assignments the dispatcher makes (split\n * payloads) never reach the shared parse. The nested values (Arrow\n * schemas and batches, arguments) are shared and must be treated as\n * read-only, as they always were.\n */\n request: InitRequest;\n /** The raw bind-call IPC bytes, which the split-token fingerprint hashes. */\n bindCallIpc: Uint8Array;\n}\n\ninterface Parsed {\n packed: Uint8Array;\n request: InitRequest;\n bindCallIpc: Uint8Array;\n}\n\n/** Streams whose parse a process keeps. Past this, the least recently used is dropped. */\nconst MAX_ENTRIES = 128;\nconst parsed = new Map<number, Parsed>();\nconst stats = { parses: 0, hits: 0 };\n\n/** FNV-1a over the bytes, folded with the length. */\nfunction hashBytes(bytes: Uint8Array): number {\n let h = 0x811c9dc5 ^ bytes.byteLength;\n for (let i = 0; i < bytes.byteLength; i++) {\n h ^= bytes[i];\n h = Math.imul(h, 0x01000193);\n }\n return h >>> 0;\n}\n\nfunction sameBytes(a: Uint8Array, b: Uint8Array): boolean {\n if (a.byteLength !== b.byteLength) return false;\n for (let i = 0; i < a.byteLength; i++) if (a[i] !== b[i]) return false;\n return true;\n}\n\n/**\n * Parse the init request a cursor carries (as packed by\n * {@link packInitRequest}), from the process memo when this stream's turns have\n * been here before.\n */\nexport function parseCarriedInitRequest(packed: Uint8Array): CarriedInitRequest {\n const key = hashBytes(packed);\n let entry = parsed.get(key);\n if (entry && sameBytes(entry.packed, packed)) {\n // Refresh its recency.\n parsed.delete(key);\n parsed.set(key, entry);\n stats.hits++;\n } else {\n const dict = batchToScalarDict(deserializeBatch(unpackInitRequest(packed)));\n stats.parses++;\n entry = { packed: packed.slice(), request: deserializeInitRequest(dict), bindCallIpc: dict.bind_call };\n // A hash collision simply replaces the other stream's entry.\n parsed.delete(key);\n if (parsed.size >= MAX_ENTRIES) parsed.delete(parsed.keys().next().value!);\n parsed.set(key, entry);\n }\n return {\n request: { ...entry.request, bind_call: { ...entry.request.bind_call } },\n bindCallIpc: entry.bindCallIpc,\n };\n}\n\n/** Cumulative parse / memo-hit counts for this process (observability and tests). */\nexport function carriedInitRequestStats(): { parses: number; hits: number; entries: number } {\n return { ...stats, entries: parsed.size };\n}\n",
|
|
33
|
+
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// State serializer for the HTTP transport: the exchange state an HTTP cursor\n// carries between turns, and the Arrow IPC encoding of user state inside it.\n\nimport {\n type VgiDataType,\n type VgiField,\n schema as makeSchema,\n field,\n struct as makeStruct,\n binary,\n int64,\n bool,\n float64,\n utf8,\n list as makeList,\n nullType,\n typeSignature,\n isStruct,\n isBinary,\n serializeBatch,\n deserializeBatch,\n batchFromColumns,\n readCanonicalValue,\n} from \"../arrow/index.js\";\nimport { codecFor } from \"../arrow/codec/registry.js\";\nimport type { StateSerializer } from \"@query-farm/vgi-rpc\";\nimport { toUint8Array } from \"../util/bytes.js\";\nimport { decodeFilterHistory, encodeFilterHistory } from \"../filter-pushdown/history.js\";\nimport { packInitRequest } from \"./carried-init-request.js\";\n\n/**\n * The fields of the exchange state an HTTP cursor carries, by name and type.\n *\n * Descriptive: {@link arrowStateSerializer} writes them as a flat binary frame\n * (see there), not as an Arrow batch of this schema. Kept exported for API\n * stability.\n */\nexport const EXCHANGE_STATE_SCHEMA = makeSchema([\n field(\"function_name\", binary(), false),\n // The init request, packed by carried-init-request.ts (a codec byte, then\n // the IPC bytes, zstd-compressed where the runtime can).\n field(\"init_request\", binary(), false),\n field(\"execution_id\", binary(), false),\n field(\"max_workers\", int64(), false),\n field(\"opaque_data\", binary(), true),\n field(\"is_producer\", bool(), false),\n field(\"user_state\", binary(), true),\n // The stream's compacted dynamic-filter history (filter-pushdown/history.ts),\n // null when no delta has been applied. Bounded by the number of predicate\n // ids, so the token stays flat-sized however many turns the scan takes.\n field(\"filter_history\", binary(), true),\n]);\n\nconst TEXT_ENCODER = new TextEncoder();\nconst TEXT_DECODER = new TextDecoder();\n\n/** Version byte of the exchange state frame (never 0xFF, the first byte of an Arrow IPC stream). */\nconst STATE_FORMAT_VERSION = 1;\nconst FLAG_PRODUCER = 1;\nconst FLAG_OPAQUE_DATA = 2;\nconst FLAG_USER_STATE = 4;\nconst FLAG_FILTER_HISTORY = 8;\n\n/**\n * Child field name for an inferred list. Arrow matches list children by\n * position, not name, so this is cosmetic — but keeping it at Arrow's\n * conventional `item` makes a dumped schema read the way people expect.\n */\nconst LIST_CHILD_NAME = \"item\";\n\n/**\n * Element type for an array with nothing to infer from — `[]`, or an array\n * whose every element is null.\n *\n * Deliberately NOT `nullType()`, which is the semantically honest choice:\n * flechette's column builder rejects a Null-typed list child (\"Unsupported\n * data type: Null\"), so a `[]` in userState would round-trip on arrow-js and\n * throw on flechette. Utf8 builds on both backends and, with no non-null\n * element to carry, is indistinguishable on the way back out: `[]` returns\n * `[]` and `[null, null]` returns `[null, null]`.\n */\nconst emptyListElementType = (): VgiDataType => utf8();\n\n/**\n * Infer the single Arrow element type an array's contents share.\n *\n * Arrow lists are homogeneous, so a genuinely mixed array (`[1, \"a\"]`,\n * or structs with differing field sets) has no faithful representation and is\n * rejected rather than silently coerced. Nulls are skipped — they are\n * representable at any element type — and an array with no non-null element\n * falls back to {@link emptyListElementType}.\n */\nfunction inferElementType(values: any[]): VgiDataType {\n let elementType: VgiDataType | null = null;\n let elementSig = \"\";\n for (const v of values) {\n if (v === null || v === undefined) continue;\n const t = inferFieldType(v);\n const sig = typeSignature(t);\n if (elementType === null) {\n elementType = t;\n elementSig = sig;\n continue;\n }\n if (sig !== elementSig) {\n throw new Error(\n `inferFieldType: arrays in userState must be homogeneous; ` +\n `found both '${elementSig}' and '${sig}' in the same array ` +\n `(split the values into separate fields, or normalize them to one type)`,\n );\n }\n }\n return elementType ?? emptyListElementType();\n}\n\n/** Infer an Arrow DataType from a JS value for user state serialization. */\nexport function inferFieldType(value: any): VgiDataType {\n if (value === null || value === undefined) return nullType();\n switch (typeof value) {\n case \"number\": return float64();\n case \"bigint\": return int64();\n case \"string\": return utf8();\n case \"boolean\": return bool();\n case \"object\":\n if (value instanceof Uint8Array || value instanceof ArrayBuffer) return binary();\n if (ArrayBuffer.isView(value)) return binary();\n if (Array.isArray(value)) {\n return makeList(field(LIST_CHILD_NAME, inferElementType(value), true));\n }\n if (value instanceof Map) {\n throw new Error(`inferFieldType: Map is not supported in userState (use a plain object instead)`);\n }\n if (value instanceof Set) {\n throw new Error(`inferFieldType: Set is not supported in userState (use an array or plain object instead)`);\n }\n if (value instanceof Date) {\n throw new Error(`inferFieldType: Date is not supported in userState (use a number (epoch ms) or ISO string instead)`);\n }\n if (value instanceof RegExp) {\n throw new Error(`inferFieldType: RegExp is not supported in userState (use a string pattern instead)`);\n }\n // Plain object → Struct\n const fields = Object.entries(value).map(\n ([k, v]) => field(k, inferFieldType(v), true),\n );\n return makeStruct(fields);\n default:\n throw new Error(`inferFieldType: unsupported type '${typeof value}'`);\n }\n}\n\n/**\n * Serialize userState to Arrow IPC bytes.\n * Infers schema from the JS object at runtime. Arrow IPC is self-describing,\n * so deserialization doesn't need the schema ahead of time.\n *\n * For an empty object `{}`, we emit a 0-row batch with empty schema —\n * `deserializeUserState` recognizes that shape and returns `{}` rather than\n * `null`. (`null` is reserved for \"no userState declared at all\".)\n */\nexport function serializeUserState(userState: any): Uint8Array | null {\n if (userState == null) return null;\n const entries = Object.entries(userState);\n if (entries.length === 0) {\n // 0-row, 0-field batch — round-trips back to {} via deserializeUserState.\n return serializeBatch(batchFromColumns({}, makeSchema([])));\n }\n const fields = entries.map(\n ([k, v]) => field(k, inferFieldType(v), true),\n );\n const sch = makeSchema(fields);\n const columns: Record<string, any[]> = {};\n for (const [key, val] of entries) {\n columns[key] = [val];\n }\n return serializeBatch(batchFromColumns(columns, sch));\n}\n\n/**\n * Extract a typed value from an Arrow column in RICH form via the codec /\n * canonical path. Backend-agnostic and lossless (BigInt for Int64, Uint8Array\n * for Binary, plain objects for Struct). userState forbids Date/temporal types\n * (see {@link inferFieldType}), so rich == canonical for everything stored here.\n */\nfunction extractTypedValue(col: any, index: number, type: VgiDataType): any {\n return codecFor(type).canonicalToRich(readCanonicalValue(type, col, index));\n}\n\n/**\n * Deserialize userState from Arrow IPC bytes.\n * Reconstructs a plain JS object, preserving BigInt for Int64 columns.\n */\nexport function deserializeUserState(bytes: Uint8Array | null): any {\n if (bytes == null) return null;\n const batch = deserializeBatch(bytes);\n if (batch.numRows === 0 && batch.schema.fields.length === 0) {\n return {};\n }\n if (batch.numRows === 0) return null;\n const result: Record<string, any> = {};\n for (const f of batch.schema.fields) {\n const col = batch.getChild(f.name);\n if (!col) { result[f.name] = null; continue; }\n result[f.name] = extractTypedValue(col, 0, f.type);\n }\n return result;\n}\n\n/**\n * The HTTP exchange state serializer: what a stream's cursor carries between\n * turns.\n *\n * A flat, versioned binary frame, not an Arrow batch. The cursor is built and\n * parsed on every turn of every HTTP stream, and wrapping eight scalars in a\n * one-row Arrow batch cost ~0.4 ms a turn (a generic column builder per field,\n * an IPC schema message each way) plus ~1 KB of framing that was then sealed\n * and base64-encoded twice per turn. The fields are the ones\n * {@link EXCHANGE_STATE_SCHEMA} names; `user_state` stays Arrow IPC inside the\n * frame, because it carries typed user values.\n *\n * Layout (little-endian): `u8 version | u8 flags | f64 max_workers |\n * bytes function_name | bytes init_request | bytes execution_id |\n * [bytes opaque_data] [bytes user_state] [bytes filter_history]`, where\n * `bytes` is `u32 length, payload` and a bracketed field is present only when\n * its flag bit is set. The frame never leaves this worker unsealed, so the\n * version byte exists to turn a token minted by another build into a clean\n * refusal rather than a misread.\n *\n * The name is kept for API stability; the Arrow in it is the user state.\n */\nexport const arrowStateSerializer: StateSerializer = {\n serialize(state: any): Uint8Array {\n const functionName = TEXT_ENCODER.encode(state.functionName ?? \"\");\n // Packed on the init turn (the only one holding the raw bytes); every\n // continuation carries the packed bytes through unchanged.\n const initRequest: Uint8Array = state.initRequestPacked ?? packInitRequest(state.initRequestIpc);\n const executionId = toUint8Array(state.executionId);\n const opaqueData = state.opaqueData != null ? toUint8Array(state.opaqueData) : null;\n const userState = serializeUserState(state.userState);\n const filterHistory = encodeFilterHistory(state.filterHistory);\n const flags =\n (state.isProducer ? FLAG_PRODUCER : 0) |\n (opaqueData ? FLAG_OPAQUE_DATA : 0) |\n (userState ? FLAG_USER_STATE : 0) |\n (filterHistory ? FLAG_FILTER_HISTORY : 0);\n const chunks = [functionName, initRequest, executionId];\n if (opaqueData) chunks.push(opaqueData);\n if (userState) chunks.push(userState);\n if (filterHistory) chunks.push(filterHistory);\n let size = 2 + 8;\n for (const chunk of chunks) size += 4 + chunk.byteLength;\n const out = new Uint8Array(size);\n const view = new DataView(out.buffer);\n out[0] = STATE_FORMAT_VERSION;\n out[1] = flags;\n view.setFloat64(2, Number(state.maxWorkers ?? 1), true);\n let offset = 10;\n for (const chunk of chunks) {\n view.setUint32(offset, chunk.byteLength, true);\n out.set(chunk, offset + 4);\n offset += 4 + chunk.byteLength;\n }\n return out;\n },\n\n deserialize(bytes: Uint8Array): any {\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n if (bytes.byteLength < 10 || bytes[0] !== STATE_FORMAT_VERSION) {\n throw new Error(\"exchange state has an unknown format (minted by another build of this worker?)\");\n }\n const flags = bytes[1];\n const maxWorkers = view.getFloat64(2, true);\n let offset = 10;\n // Each field is copied out, not viewed: Arrow readers want a buffer of\n // their own (byteOffset 0), and nothing should pin the whole frame.\n const take = (): Uint8Array => {\n if (offset + 4 > bytes.byteLength) throw new Error(\"exchange state is truncated\");\n const length = view.getUint32(offset, true);\n offset += 4;\n if (offset + length > bytes.byteLength) throw new Error(\"exchange state is truncated\");\n const chunk = bytes.slice(offset, offset + length);\n offset += length;\n return chunk;\n };\n const functionName = TEXT_DECODER.decode(take());\n const initRequestPacked = take();\n const executionId = take();\n const opaqueData = flags & FLAG_OPAQUE_DATA ? take() : null;\n const userStateBytes = flags & FLAG_USER_STATE ? take() : null;\n const filterHistoryBytes = flags & FLAG_FILTER_HISTORY ? take() : null;\n if (offset !== bytes.byteLength) throw new Error(\"exchange state has trailing bytes\");\n const isProducer = (flags & FLAG_PRODUCER) !== 0;\n return {\n functionName,\n initRequestPacked,\n executionId,\n maxWorkers,\n opaqueData,\n isProducer,\n // vgi-rpc dispatch reads __isProducer to choose producer vs exchange mode\n __isProducer: isProducer,\n userState: deserializeUserState(userStateBytes),\n filterHistory: decodeFilterHistory(filterHistoryBytes),\n };\n },\n};\n",
|
|
34
|
+
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Build VGI protocol from worker implementation.\n// Orchestrator that registers function, aggregate, and catalog handlers\n// against vgi-rpc Protocol. The handler implementations live in handlers/.\n\nimport { Protocol } from \"@query-farm/vgi-rpc\";\n\n// NOTE: We must NOT use vgi-rpc's str/bytes/int/etc. singletons in Schema objects\n// because Bun loads apache-arrow as separate module instances for our code vs vgi-rpc's\n// compiled dist. Instead, we pre-build Schema objects and pass them directly to Protocol\n// methods (toSchema() passes Schema instances through without instanceof checks).\nimport type { FunctionRegistry } from \"../functions/registry.js\";\nimport type { CatalogInterface } from \"../catalog/interface.js\";\nimport { registerFunctionMethods } from \"./handlers/function.js\";\nimport { registerAggregateMethods } from \"./handlers/aggregate.js\";\nimport { registerTableBufferingMethods } from \"./handlers/table-buffering.js\";\nimport { registerCatalogMethods } from \"./handlers/catalog/index.js\";\n\nexport interface ProtocolConfig {\n registry: FunctionRegistry;\n catalogInterface?: CatalogInterface;\n catalogName?: string;\n /**\n * AEAD signing key for sealing catalog opaque-data envelopes. Pass the same\n * 32-byte key used for HTTP state tokens. When omitted (subprocess / unix\n * transports) attach_opaque_data / transaction_opaque_data pass through\n * unsealed — OS process ownership already enforces identity there.\n */\n signingKey?: Uint8Array;\n}\n\n/**\n * Wire name of the VGI protocol: the `vgi_rpc.protocol` routing key and the\n * `{protocol}` HTTP path segment.\n *\n * The name carries the major version, so an incompatible major is a\n * *different* protocol and therefore a 404 — an answer every proxy, WAF and\n * load balancer understands without an Arrow parser, and one that lets\n * `vgi.v2` and a future `vgi.v3` be served side by side while clients migrate.\n * That matters for this consumer specifically: the DuckDB extension ships to\n * users and cannot be flag-dayed.\n *\n * Declared rather than derived. Until the transports made the routing key\n * required, each implementation's wire name defaulted to whatever its local\n * type was called, which left the six ports disagreeing four ways — Python\n * `VgiProtocol`, Java and C# `VgiService`, Go the framework default `Service`,\n * this port `vgi` — so no client could address them all. The canonical name is\n * decided in vgi-python and emitted by the DuckDB extension; this is that same\n * string, not an independent choice.\n *\n * Since `@query-farm/vgi-rpc` 0.24.0 the name is also bound into the AEAD\n * associated data of every state and call token (`TokenScope.protocol`), so a\n * caller that opens a token minted by this protocol has to name it. Exported\n * so the HTTP entry points build that scope from the same constant the\n * protocol is registered under rather than a second copy of the literal.\n */\nexport const VGI_PROTOCOL_NAME = \"vgi.v2\";\n\nexport function buildVgiProtocol(config: ProtocolConfig): Protocol {\n const protocol = new Protocol(VGI_PROTOCOL_NAME, { protocolVersion: \"2.0.0\" });\n\n registerFunctionMethods(protocol, {\n registry: config.registry,\n signingKey: config.signingKey,\n catalogInterface: config.catalogInterface,\n });\n registerAggregateMethods(protocol, config.registry);\n registerTableBufferingMethods(protocol, config.registry, config.signingKey);\n registerCatalogMethods(protocol, config.catalogInterface, config.catalogName, config.signingKey);\n\n return protocol;\n}\n",
|
|
32
35
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Column statistics: types and sparse-union wire serialization.\n// Mirrors vgi-python's serialize_column_statistics in catalog_interface.py.\n//\n// The wire format is a single RecordBatch with schema\n// column_name: utf8\n// min: sparse_union<T0, T1, ...>\n// max: sparse_union<T0, T1, ...>\n// has_null: bool\n// has_not_null: bool\n// distinct_count: int64\n// contains_unicode: bool\n// max_string_length: uint64\n// where Ti are the distinct Arrow types present among the stats' min/max values.\n// A row's type_id picks which union child holds its real min/max; the other\n// children carry null at that slot (sparse-union invariant).\n//\n// SparseUnion data construction differs significantly between arrow-js\n// (typeIds buffer + per-type children built via makeData) and flechette\n// (typeIdForValue closure on columnFromArray), so the actual batch\n// assembly is delegated to the active backend via the facade.\n\nimport {\n type ColumnStatistics,\n buildStatisticsBatch,\n serializeBatch,\n} from \"../arrow/index.js\";\n\nexport type { ColumnStatistics };\n\n/**\n * Serialize column statistics to IPC bytes per vgi-python's wire format.\n * Returns an empty-stats batch when `stats` is empty (matching Python).\n */\nexport function serializeColumnStatistics(\n stats: ColumnStatistics[],\n _cacheMaxAgeSeconds?: number | null,\n): Uint8Array {\n return serializeBatch(buildStatisticsBatch(stats));\n}\n",
|
|
33
36
|
"// ============================================================================\n// GENERATED by vgi.codegen.ts_schemas. DO NOT EDIT BY HAND.\n//\n// Generator: vgi-gen-ts-schemas v2\n// Content hash: 668f198950df\n//\n// To regenerate:\n// uv run --project ~/Development/vgi-python vgi-gen-ts-schemas \\\n// > ~/Development/vgi-typescript/src/generated/vgi-protocol-schemas.ts\n// ============================================================================\n\nimport {\n TimeUnit,\n binary,\n bool,\n dictionary,\n field,\n float64,\n int16,\n int32,\n int64,\n largeBinary,\n list,\n map,\n schema,\n struct,\n timestamp,\n uint64,\n utf8,\n} from \"../arrow/index.js\";\n\n// Origin: CatalogInfo\nexport const CatalogInfoSchema = schema([\n field(\"name\", utf8(), false),\n field(\"implementation_version\", utf8(), true),\n field(\"data_version_spec\", utf8(), true),\n field(\"attach_option_specs\", list(field(\"item\", binary(), true)), false),\n field(\"releases\", list(field(\"item\", struct([field(\"version\", utf8(), false), field(\"released_at\", timestamp(TimeUnit.MICROSECOND, \"UTC\"), true), field(\"summary\", utf8(), false), field(\"notes_url\", utf8(), true)]), true)), false),\n field(\"source_url\", utf8(), true),\n]);\n\n// Origin: SchemaInfo\nexport const SchemaInfoSchema = schema([\n field(\"comment\", utf8(), true),\n field(\"tags\", map(field(\"key\", utf8(), false), field(\"value\", utf8(), true), false), false),\n field(\"attach_opaque_data\", binary(), false),\n field(\"path\", list(field(\"item\", utf8(), true)), false),\n field(\"estimated_object_count\", map(field(\"key\", utf8(), false), field(\"value\", int64(), true), false), true),\n]);\n\n// Origin: TableInfo\nexport const TableInfoSchema = schema([\n field(\"comment\", utf8(), true),\n field(\"tags\", map(field(\"key\", utf8(), false), field(\"value\", utf8(), true), false), false),\n field(\"name\", utf8(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"columns\", binary(), false),\n field(\"not_null_constraints\", list(field(\"item\", int32(), true)), false),\n field(\"unique_constraints\", list(field(\"item\", list(field(\"item\", int32(), true)), true)), false),\n field(\"check_constraints\", list(field(\"item\", utf8(), true)), false),\n field(\"primary_key_constraints\", list(field(\"item\", list(field(\"item\", int32(), true)), true)), false),\n field(\"foreign_key_constraints\", list(field(\"item\", binary(), true)), false),\n field(\"write_result_modes\", map(field(\"key\", utf8(), false), field(\"value\", utf8(), true), false), false),\n field(\"supports_column_statistics\", bool(), false),\n field(\"scan_function\", binary(), true),\n field(\"insert_function\", binary(), true),\n field(\"update_function\", binary(), true),\n field(\"delete_function\", binary(), true),\n field(\"cardinality_estimate\", int64(), true),\n field(\"cardinality_max\", int64(), true),\n field(\"column_statistics\", binary(), true),\n field(\"bind_result\", binary(), true),\n field(\"required_filters\", list(field(\"item\", list(field(\"item\", utf8(), true)), true)), false),\n]);\n\n// Origin: ViewInfo\nexport const ViewInfoSchema = schema([\n field(\"comment\", utf8(), true),\n field(\"tags\", map(field(\"key\", utf8(), false), field(\"value\", utf8(), true), false), false),\n field(\"name\", utf8(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"definition\", utf8(), false),\n field(\"column_comments\", map(field(\"key\", utf8(), false), field(\"value\", utf8(), true), false), false),\n]);\n\n// Origin: FunctionInfo\nexport const FunctionInfoSchema = schema([\n field(\"comment\", utf8(), true),\n field(\"tags\", map(field(\"key\", utf8(), false), field(\"value\", utf8(), true), false), false),\n field(\"name\", utf8(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"function_type\", dictionary(utf8(), int16()), false),\n field(\"arguments\", binary(), false),\n field(\"output_schema\", binary(), false),\n field(\"parameter_default_values\", binary(), true),\n field(\"stability\", dictionary(utf8(), int16()), true),\n field(\"null_handling\", dictionary(utf8(), int16()), true),\n field(\"argument_monotonicity\", list(field(\"item\", utf8(), true)), true),\n field(\"description\", utf8(), false),\n field(\"examples\", list(field(\"item\", struct([field(\"sql\", utf8(), false), field(\"description\", utf8(), false), field(\"expected_output\", utf8(), true)]), true)), false),\n field(\"categories\", list(field(\"item\", utf8(), true)), false),\n field(\"projection_pushdown\", bool(), true),\n field(\"filter_pushdown\", bool(), true),\n field(\"sampling_pushdown\", bool(), true),\n field(\"late_materialization\", bool(), true),\n field(\"filter_semantic_profiles\", list(field(\"item\", utf8(), true)), false),\n field(\"additional_filter_functions\", list(field(\"item\", struct([field(\"namespace\", utf8(), false), field(\"name\", utf8(), false), field(\"version\", uint64(), false)]), true)), false),\n field(\"runtime_filter_algorithms\", list(field(\"item\", struct([field(\"namespace\", utf8(), false), field(\"name\", utf8(), false), field(\"version\", uint64(), false)]), true)), false),\n field(\"filter_evaluation_contexts\", list(field(\"item\", struct([field(\"profile\", utf8(), false), field(\"provider_fingerprint\", utf8(), true)]), true)), false),\n field(\"order_preservation\", dictionary(utf8(), int16()), true),\n field(\"max_workers\", int32(), true),\n field(\"supports_batch_index\", bool(), false),\n field(\"supports_splits\", bool(), false),\n field(\"filters_exactly_applied\", bool(), false),\n field(\"supports_positions\", bool(), false),\n field(\"split_token_ttl_seconds\", int64(), true),\n field(\"partition_kind\", dictionary(utf8(), int16()), false),\n field(\"order_dependent\", dictionary(utf8(), int16()), false),\n field(\"distinct_dependent\", dictionary(utf8(), int16()), false),\n field(\"supports_window\", bool(), false),\n field(\"streaming_partitioned\", bool(), false),\n field(\"has_finalize\", bool(), false),\n field(\"source_order_dependent\", bool(), false),\n field(\"sink_order_dependent\", bool(), false),\n field(\"requires_input_batch_index\", bool(), false),\n field(\"input_from_args\", bool(), false),\n field(\"required_settings\", list(field(\"item\", utf8(), true)), false),\n field(\"required_secrets\", list(field(\"item\", struct([field(\"secret_type\", utf8(), false), field(\"scope\", utf8(), true), field(\"secret_name\", utf8(), true)]), true)), false),\n]);\n\n// Origin: MacroInfo\nexport const MacroInfoSchema = schema([\n field(\"comment\", utf8(), true),\n field(\"tags\", map(field(\"key\", utf8(), false), field(\"value\", utf8(), true), false), false),\n field(\"name\", utf8(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"macro_type\", dictionary(utf8(), int16()), false),\n field(\"parameters\", list(field(\"item\", utf8(), true)), false),\n field(\"parameter_default_values\", binary(), true),\n field(\"definition\", utf8(), false),\n field(\"arguments_schema\", binary(), true),\n]);\n\n// Origin: IndexInfo\nexport const IndexInfoSchema = schema([\n field(\"comment\", utf8(), true),\n field(\"tags\", map(field(\"key\", utf8(), false), field(\"value\", utf8(), true), false), false),\n field(\"name\", utf8(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"table_name\", utf8(), false),\n field(\"index_type\", utf8(), false),\n field(\"constraint_type\", dictionary(utf8(), int16()), false),\n field(\"expressions\", list(field(\"item\", utf8(), true)), false),\n field(\"options\", map(field(\"key\", utf8(), false), field(\"value\", utf8(), true), false), false),\n]);\n\n// Origin: CopyFromFormatInfo\nexport const CopyFromFormatInfoSchema = schema([\n field(\"comment\", utf8(), true),\n field(\"tags\", map(field(\"key\", utf8(), false), field(\"value\", utf8(), true), false), false),\n field(\"format_name\", utf8(), false),\n field(\"handler\", utf8(), false),\n field(\"options\", binary(), false),\n field(\"direction\", utf8(), false),\n field(\"description\", utf8(), false),\n field(\"ordered\", bool(), false),\n]);\n\n// Origin: ScanFunctionResult\nexport const ScanFunctionResultSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"arguments\", binary(), false),\n field(\"required_extensions\", list(field(\"item\", utf8(), true)), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: ScanBranchesResult\nexport const ScanBranchesResultSchema = schema([\n field(\"branches\", list(field(\"item\", binary(), true)), false),\n field(\"required_extensions\", list(field(\"item\", utf8(), true)), false),\n]);\n\n// Origin: ScanBranch\nexport const ScanBranchSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"arguments\", binary(), false),\n field(\"branch_filter\", utf8(), true),\n field(\"writable\", bool(), false),\n field(\"source_catalog\", utf8(), true),\n field(\"source_schema_path\", list(field(\"item\", utf8(), true)), true),\n field(\"source_table\", utf8(), true),\n field(\"format_name\", utf8(), true),\n field(\"format_locations\", list(field(\"item\", utf8(), true)), true),\n field(\"format_options\", binary(), true),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: ScanSplit\nexport const ScanSplitSchema = schema([\n field(\"payload\", binary(), false),\n field(\"token\", binary(), false),\n field(\"estimated_rows\", int64(), true),\n field(\"rows_exact\", bool(), false),\n field(\"estimated_bytes\", int64(), true),\n field(\"partition_bounds\", binary(), true),\n field(\"column_statistics\", binary(), true),\n field(\"location_ids\", list(field(\"item\", int64(), true)), true),\n field(\"start_position\", binary(), true),\n field(\"end_position\", binary(), true),\n]);\n\n// Origin: AttachCatalogInfo\nexport const AttachCatalogInfoSchema = schema([\n field(\"alias\", utf8(), false),\n field(\"target\", utf8(), false),\n field(\"db_type\", utf8(), false),\n field(\"options\", map(field(\"key\", utf8(), false), field(\"value\", utf8(), true), false), false),\n field(\"hidden\", bool(), false),\n field(\"required\", bool(), false),\n field(\"secret_ref\", utf8(), false),\n]);\n\n// Origin: ForeignKeyInfo\nexport const ForeignKeyInfoSchema = schema([\n field(\"fk_columns\", list(field(\"item\", utf8(), true)), false),\n field(\"pk_columns\", list(field(\"item\", utf8(), true)), false),\n field(\"referenced_table\", utf8(), false),\n field(\"referenced_schema_path\", list(field(\"item\", utf8(), true)), false),\n]);\n\n// Origin: AggregateBindRequest\nexport const AggregateBindRequestSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"arguments\", binary(), false),\n field(\"input_schema\", binary(), true),\n field(\"settings\", binary(), true),\n field(\"secrets\", binary(), true),\n field(\"attach_opaque_data\", binary(), true),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n field(\"argument_names\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: AggregateCombineRequest\nexport const AggregateCombineRequestSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"execution_id\", binary(), false),\n field(\"merge_batch\", binary(), false),\n field(\"attach_opaque_data\", binary(), true),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: AggregateDestructorRequest\nexport const AggregateDestructorRequestSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"execution_id\", binary(), false),\n field(\"group_ids_batch\", binary(), false),\n field(\"attach_opaque_data\", binary(), true),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: AggregateFinalizeRequest\nexport const AggregateFinalizeRequestSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"execution_id\", binary(), false),\n field(\"group_ids_batch\", binary(), false),\n field(\"output_schema\", binary(), false),\n field(\"attach_opaque_data\", binary(), true),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: AggregateStreamingChunkRequest\nexport const AggregateStreamingChunkRequestSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"execution_id\", binary(), false),\n field(\"input_batch\", binary(), false),\n field(\"attach_opaque_data\", binary(), true),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: AggregateStreamingCloseRequest\nexport const AggregateStreamingCloseRequestSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"execution_id\", binary(), false),\n field(\"attach_opaque_data\", binary(), true),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: AggregateStreamingOpenRequest\nexport const AggregateStreamingOpenRequestSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"arguments\", binary(), false),\n field(\"input_schema\", binary(), false),\n field(\"partition_key_count\", int64(), false),\n field(\"order_key_count\", int64(), false),\n field(\"output_schema\", binary(), false),\n field(\"settings\", binary(), true),\n field(\"secrets\", binary(), true),\n field(\"attach_opaque_data\", binary(), true),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: AggregateUpdateRequest\nexport const AggregateUpdateRequestSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"execution_id\", binary(), false),\n field(\"input_batch\", binary(), false),\n field(\"attach_opaque_data\", binary(), true),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: AggregateWindowBatchRequest\nexport const AggregateWindowBatchRequestSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"execution_id\", binary(), false),\n field(\"partition_id\", int64(), false),\n field(\"row_idx\", int64(), false),\n field(\"count\", int64(), false),\n field(\"frames_per_row\", list(field(\"item\", int64(), true)), false),\n field(\"frame_starts\", list(field(\"item\", int64(), true)), false),\n field(\"frame_ends\", list(field(\"item\", int64(), true)), false),\n field(\"attach_opaque_data\", binary(), true),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: AggregateWindowDestructorRequest\nexport const AggregateWindowDestructorRequestSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"execution_id\", binary(), false),\n field(\"partition_id\", int64(), false),\n field(\"attach_opaque_data\", binary(), true),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: AggregateWindowInitRequest\nexport const AggregateWindowInitRequestSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"execution_id\", binary(), false),\n field(\"partition_id\", int64(), false),\n field(\"row_count\", int64(), false),\n field(\"partition_batch\", binary(), false),\n field(\"output_schema\", binary(), false),\n field(\"filter_mask\", binary(), false),\n field(\"frame_stats\", binary(), false),\n field(\"all_valid\", binary(), false),\n field(\"attach_opaque_data\", binary(), true),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: AggregateWindowRequest\nexport const AggregateWindowRequestSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"execution_id\", binary(), false),\n field(\"partition_id\", int64(), false),\n field(\"rid\", int64(), false),\n field(\"frame_starts\", list(field(\"item\", int64(), true)), false),\n field(\"frame_ends\", list(field(\"item\", int64(), true)), false),\n field(\"attach_opaque_data\", binary(), true),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: BindRequest\nexport const BindRequestSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"arguments\", binary(), false),\n field(\"function_type\", dictionary(utf8(), int16()), false),\n field(\"input_schema\", binary(), true),\n field(\"settings\", binary(), true),\n field(\"secrets\", binary(), true),\n field(\"attach_opaque_data\", binary(), true),\n field(\"transaction_opaque_data\", binary(), true),\n field(\"resolved_secrets_provided\", bool(), false),\n field(\"at_unit\", utf8(), true),\n field(\"at_value\", utf8(), true),\n field(\"copy_from\", struct([field(\"format\", utf8(), false), field(\"file_path\", utf8(), false), field(\"expected_schema\", binary(), false)]), true),\n field(\"copy_to\", struct([field(\"format\", utf8(), false), field(\"file_path\", utf8(), false)]), true),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n field(\"argument_names\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: CatalogAttachRequest\nexport const CatalogAttachRequestSchema = schema([\n field(\"name\", utf8(), false),\n field(\"options\", binary(), true),\n field(\"data_version_spec\", utf8(), true),\n field(\"implementation_version\", utf8(), true),\n field(\"client_capabilities\", binary(), true),\n]);\n\n// Origin: CatalogCreateRequest\nexport const CatalogCreateRequestSchema = schema([\n field(\"name\", utf8(), false),\n field(\"on_conflict\", dictionary(utf8(), int16()), false),\n field(\"options\", binary(), true),\n]);\n\n// Origin: ClientCapabilities\nexport const ClientCapabilitiesSchema = schema([\n field(\"engine\", utf8(), false),\n field(\"native_formats\", list(field(\"item\", utf8(), true)), false),\n field(\"catalogs\", list(field(\"item\", utf8(), true)), false),\n field(\"can_stream\", bool(), false),\n field(\"filter_encodings\", list(field(\"item\", utf8(), true)), false),\n]);\n\n// Origin: CopyFromContext\nexport const CopyFromContextSchema = schema([\n field(\"format\", utf8(), false),\n field(\"file_path\", utf8(), false),\n field(\"expected_schema\", binary(), false),\n]);\n\n// Origin: CopyToContext\nexport const CopyToContextSchema = schema([\n field(\"format\", utf8(), false),\n field(\"file_path\", utf8(), false),\n]);\n\n// Origin: GlobalInitResponse\nexport const GlobalInitResponseSchema = schema([\n field(\"execution_id\", binary(), false),\n field(\"opaque_data\", binary(), true),\n field(\"max_workers\", int64(), false),\n]);\n\n// Origin: IndexCreateRequest\nexport const IndexCreateRequestSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"table_name\", utf8(), false),\n field(\"index_type\", utf8(), false),\n field(\"constraint_type\", dictionary(utf8(), int16()), false),\n field(\"expressions\", list(field(\"item\", utf8(), true)), false),\n field(\"on_conflict\", dictionary(utf8(), int16()), false),\n field(\"options\", map(field(\"key\", utf8(), false), field(\"value\", utf8(), true), false), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: InitRequest\nexport const InitRequestSchema = schema([\n field(\"bind_call\", binary(), false),\n field(\"output_schema\", binary(), false),\n field(\"bind_opaque_data\", binary(), true),\n field(\"projection_ids\", list(field(\"item\", int64(), true)), true),\n field(\"pushdown_filters\", largeBinary(), true),\n field(\"join_keys\", list(field(\"item\", largeBinary(), true)), true),\n field(\"split_tokens\", list(field(\"item\", largeBinary(), true)), true),\n field(\"row_limit\", int64(), true),\n field(\"phase\", dictionary(utf8(), int16()), true),\n field(\"finalize_state_id\", binary(), true),\n field(\"execution_id\", binary(), true),\n field(\"init_opaque_data\", binary(), true),\n field(\"substream_id\", binary(), true),\n field(\"order_by_column_name\", utf8(), true),\n field(\"order_by_direction\", dictionary(utf8(), int16()), true),\n field(\"order_by_null_order\", dictionary(utf8(), int16()), true),\n field(\"order_by_limit\", int64(), true),\n field(\"tablesample_percentage\", float64(), true),\n field(\"tablesample_seed\", int64(), true),\n]);\n\n// Origin: MacroCreateRequest\nexport const MacroCreateRequestSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"macro_type\", dictionary(utf8(), int16()), false),\n field(\"parameters\", list(field(\"item\", utf8(), true)), false),\n field(\"definition\", utf8(), false),\n field(\"on_conflict\", dictionary(utf8(), int16()), false),\n field(\"parameter_default_values\", binary(), true),\n field(\"arguments_schema\", binary(), true),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: TableCreateRequest\nexport const TableCreateRequestSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"columns\", binary(), false),\n field(\"on_conflict\", dictionary(utf8(), int16()), false),\n field(\"not_null_constraints\", list(field(\"item\", int32(), true)), false),\n field(\"unique_constraints\", list(field(\"item\", list(field(\"item\", int32(), true)), true)), false),\n field(\"check_constraints\", list(field(\"item\", utf8(), true)), false),\n field(\"primary_key_constraints\", list(field(\"item\", list(field(\"item\", int32(), true)), true)), false),\n field(\"foreign_key_constraints\", list(field(\"item\", binary(), true)), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: TableBufferingCombineRequest\nexport const TableBufferingCombineRequestSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"execution_id\", binary(), false),\n field(\"state_ids\", list(field(\"item\", binary(), true)), false),\n field(\"attach_opaque_data\", binary(), true),\n field(\"transaction_id\", binary(), true),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: TableBufferingDestructorRequest\nexport const TableBufferingDestructorRequestSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"execution_id\", binary(), false),\n field(\"attach_opaque_data\", binary(), true),\n field(\"transaction_id\", binary(), true),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: TableBufferingProcessRequest\nexport const TableBufferingProcessRequestSchema = schema([\n field(\"function_name\", utf8(), false),\n field(\"execution_id\", binary(), false),\n field(\"input_batch\", binary(), false),\n field(\"attach_opaque_data\", binary(), true),\n field(\"transaction_id\", binary(), true),\n field(\"batch_index\", int64(), true),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), true),\n]);\n\n// Origin: TableFunctionCardinalityRequest\nexport const TableFunctionCardinalityRequestSchema = schema([\n field(\"bind_call\", binary(), false),\n field(\"bind_opaque_data\", binary(), true),\n]);\n\n// Origin: TableFunctionDynamicToStringRequest\nexport const TableFunctionDynamicToStringRequestSchema = schema([\n field(\"bind_call\", binary(), false),\n field(\"bind_opaque_data\", binary(), true),\n field(\"global_execution_id\", binary(), false),\n]);\n\n// Origin: TableFunctionPlanRequest\nexport const TableFunctionPlanRequestSchema = schema([\n field(\"bind_call\", binary(), false),\n field(\"bind_opaque_data\", binary(), true),\n field(\"projection_ids\", list(field(\"item\", int64(), true)), true),\n field(\"pushdown_filters\", largeBinary(), true),\n field(\"join_keys\", list(field(\"item\", largeBinary(), true)), true),\n field(\"row_limit\", int64(), true),\n field(\"target_split_bytes\", int64(), true),\n field(\"min_splits\", int64(), true),\n field(\"max_splits_per_response\", int64(), true),\n field(\"cursor\", binary(), true),\n field(\"refined_filters\", largeBinary(), true),\n field(\"filters_complete\", bool(), false),\n field(\"start_position\", binary(), true),\n field(\"end_position\", binary(), true),\n field(\"order_by_column_name\", utf8(), true),\n field(\"order_by_direction\", dictionary(utf8(), int16()), true),\n field(\"order_by_null_order\", dictionary(utf8(), int16()), true),\n field(\"order_by_limit\", int64(), true),\n field(\"tablesample_percentage\", float64(), true),\n field(\"tablesample_seed\", int64(), true),\n]);\n\n// Origin: TableFunctionStatisticsRequest\nexport const TableFunctionStatisticsRequestSchema = schema([\n field(\"bind_call\", binary(), false),\n field(\"bind_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'aggregate_bind' result\nexport const AggregateBindResultSchema = schema([\n field(\"output_schema\", binary(), false),\n field(\"execution_id\", binary(), false),\n]);\n\n// Origin: method 'aggregate_combine' result\nexport const AggregateCombineResultSchema = schema([]);\n\n// Origin: method 'aggregate_destructor' result\nexport const AggregateDestructorResultSchema = schema([]);\n\n// Origin: method 'aggregate_finalize' result\nexport const AggregateFinalizeResultSchema = schema([\n field(\"result_batch\", binary(), false),\n]);\n\n// Origin: method 'aggregate_streaming_chunk' result\nexport const AggregateStreamingChunkResultSchema = schema([\n field(\"result_batch\", binary(), false),\n]);\n\n// Origin: method 'aggregate_streaming_close' result\nexport const AggregateStreamingCloseResultSchema = schema([]);\n\n// Origin: method 'aggregate_streaming_open' result\nexport const AggregateStreamingOpenResultSchema = schema([\n field(\"execution_id\", binary(), false),\n]);\n\n// Origin: method 'aggregate_update' result\nexport const AggregateUpdateResultSchema = schema([]);\n\n// Origin: method 'aggregate_window' result\nexport const AggregateWindowResultSchema = schema([\n field(\"result_batch\", binary(), false),\n]);\n\n// Origin: method 'aggregate_window_batch' result\nexport const AggregateWindowBatchResultSchema = schema([\n field(\"result_batch\", binary(), false),\n]);\n\n// Origin: method 'aggregate_window_destructor' result\nexport const AggregateWindowDestructorResultSchema = schema([]);\n\n// Origin: method 'aggregate_window_init' result\nexport const AggregateWindowInitResultSchema = schema([]);\n\n// Origin: method 'bind' result\nexport const BindResultSchema = schema([\n field(\"output_schema\", binary(), false),\n field(\"opaque_data\", binary(), true),\n field(\"lookup_secret_types\", list(field(\"item\", utf8(), true)), false),\n field(\"lookup_scopes\", list(field(\"item\", utf8(), true)), false),\n field(\"lookup_names\", list(field(\"item\", utf8(), true)), false),\n]);\n\n// Origin: method 'catalog_attach' result\nexport const CatalogAttachResultSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"supports_transactions\", bool(), false),\n field(\"supports_time_travel\", bool(), false),\n field(\"catalog_version_frozen\", bool(), false),\n field(\"catalog_version\", int64(), false),\n field(\"attach_opaque_data_required\", bool(), false),\n field(\"default_schema\", utf8(), false),\n field(\"settings\", list(field(\"item\", binary(), true)), false),\n field(\"secret_types\", list(field(\"item\", binary(), true)), false),\n field(\"attach_catalogs\", list(field(\"item\", binary(), true)), false),\n field(\"comment\", utf8(), true),\n field(\"tags\", map(field(\"key\", utf8(), false), field(\"value\", utf8(), true), false), false),\n field(\"supports_column_statistics\", bool(), false),\n field(\"global_functions\", list(field(\"item\", binary(), true)), false),\n field(\"global_function_prefix\", utf8(), false),\n field(\"resolved_data_version\", utf8(), true),\n field(\"resolved_implementation_version\", utf8(), true),\n]);\n\n// Origin: method 'catalog_catalogs' result\nexport const CatalogCatalogsResultSchema = schema([\n field(\"items\", list(field(\"item\", binary(), true)), false),\n]);\n\n// Origin: method 'catalog_copy_from_formats' result\nexport const CatalogCopyFromFormatsResultSchema = schema([\n field(\"items\", list(field(\"item\", binary(), true)), false),\n]);\n\n// Origin: method 'catalog_index_get' result\nexport const CatalogIndexGetResultSchema = schema([\n field(\"items\", list(field(\"item\", binary(), true)), false),\n]);\n\n// Origin: method 'catalog_macro_get' result\nexport const CatalogMacroGetResultSchema = schema([\n field(\"items\", list(field(\"item\", binary(), true)), false),\n]);\n\n// Origin: method 'catalog_schema_contents_functions' result\nexport const CatalogSchemaContentsFunctionsResultSchema = schema([\n field(\"items\", list(field(\"item\", binary(), true)), false),\n]);\n\n// Origin: method 'catalog_schema_contents_indexes' result\nexport const CatalogSchemaContentsIndexesResultSchema = schema([\n field(\"items\", list(field(\"item\", binary(), true)), false),\n]);\n\n// Origin: method 'catalog_schema_contents_macros' result\nexport const CatalogSchemaContentsMacrosResultSchema = schema([\n field(\"items\", list(field(\"item\", binary(), true)), false),\n]);\n\n// Origin: method 'catalog_schema_contents_tables' result\nexport const CatalogSchemaContentsTablesResultSchema = schema([\n field(\"items\", list(field(\"item\", binary(), true)), false),\n]);\n\n// Origin: method 'catalog_schema_contents_views' result\nexport const CatalogSchemaContentsViewsResultSchema = schema([\n field(\"items\", list(field(\"item\", binary(), true)), false),\n]);\n\n// Origin: method 'catalog_schema_get' result\nexport const CatalogSchemaGetResultSchema = schema([\n field(\"items\", list(field(\"item\", binary(), true)), false),\n]);\n\n// Origin: method 'catalog_schemas' result\nexport const CatalogSchemasResultSchema = schema([\n field(\"items\", list(field(\"item\", binary(), true)), false),\n]);\n\n// Origin: method 'catalog_table_get' result\nexport const CatalogTableGetResultSchema = schema([\n field(\"items\", list(field(\"item\", binary(), true)), false),\n]);\n\n// Origin: method 'catalog_transaction_begin' result\nexport const CatalogTransactionBeginResultSchema = schema([\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_version' result\nexport const CatalogVersionResultSchema = schema([\n field(\"version\", int64(), false),\n]);\n\n// Origin: method 'catalog_view_get' result\nexport const CatalogViewGetResultSchema = schema([\n field(\"items\", list(field(\"item\", binary(), true)), false),\n]);\n\n// Origin: method 'table_buffering_combine' result\nexport const TableBufferingCombineResultSchema = schema([\n field(\"finalize_state_ids\", list(field(\"item\", binary(), true)), false),\n]);\n\n// Origin: method 'table_buffering_destructor' result\nexport const TableBufferingDestructorResultSchema = schema([]);\n\n// Origin: method 'table_buffering_process' result\nexport const TableBufferingProcessResultSchema = schema([\n field(\"state_id\", binary(), false),\n]);\n\n// Origin: method 'table_function_cardinality' result\nexport const TableFunctionCardinalityResultSchema = schema([\n field(\"estimate\", int64(), true),\n field(\"max\", int64(), true),\n]);\n\n// Origin: method 'table_function_dynamic_to_string' result\nexport const TableFunctionDynamicToStringResultSchema = schema([\n field(\"keys\", list(field(\"item\", utf8(), true)), false),\n field(\"values\", list(field(\"item\", utf8(), true)), false),\n]);\n\n// Origin: method 'table_function_plan' result\nexport const TableFunctionPlanResultSchema = schema([\n field(\"splits\", list(field(\"item\", binary(), true)), false),\n field(\"next_cursors\", list(field(\"item\", binary(), true)), true),\n field(\"execution_id\", binary(), true),\n field(\"init_opaque_data\", binary(), true),\n field(\"max_workers\", int64(), true),\n field(\"estimated_total_splits\", int64(), true),\n field(\"estimated_total_rows\", int64(), true),\n field(\"estimated_total_bytes\", int64(), true),\n field(\"catalog_version\", int64(), true),\n field(\"scope\", utf8(), false),\n field(\"locations\", list(field(\"item\", utf8(), true)), true),\n field(\"partitioning\", list(field(\"item\", binary(), true)), true),\n field(\"sort_order\", list(field(\"item\", binary(), true)), true),\n field(\"cache_max_age_seconds\", int64(), true),\n field(\"start_position\", binary(), true),\n field(\"end_position\", binary(), true),\n]);\n\n// Origin: method 'aggregate_bind' params\nexport const AggregateBindParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'aggregate_combine' params\nexport const AggregateCombineParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'aggregate_destructor' params\nexport const AggregateDestructorParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'aggregate_finalize' params\nexport const AggregateFinalizeParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'aggregate_streaming_chunk' params\nexport const AggregateStreamingChunkParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'aggregate_streaming_close' params\nexport const AggregateStreamingCloseParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'aggregate_streaming_open' params\nexport const AggregateStreamingOpenParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'aggregate_update' params\nexport const AggregateUpdateParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'aggregate_window' params\nexport const AggregateWindowParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'aggregate_window_batch' params\nexport const AggregateWindowBatchParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'aggregate_window_destructor' params\nexport const AggregateWindowDestructorParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'aggregate_window_init' params\nexport const AggregateWindowInitParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'bind' params\nexport const BindParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'catalog_attach' params\nexport const CatalogAttachParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'catalog_catalogs' params\nexport const CatalogCatalogsParamsSchema = schema([]);\n\n// Origin: method 'catalog_copy_from_formats' params\nexport const CatalogCopyFromFormatsParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_create' params\nexport const CatalogCreateParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'catalog_detach' params\nexport const CatalogDetachParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n]);\n\n// Origin: method 'catalog_drop' params\nexport const CatalogDropParamsSchema = schema([\n field(\"name\", utf8(), false),\n]);\n\n// Origin: method 'catalog_index_create' params\nexport const CatalogIndexCreateParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'catalog_index_drop' params\nexport const CatalogIndexDropParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"ignore_not_found\", bool(), false),\n field(\"cascade\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_index_get' params\nexport const CatalogIndexGetParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_macro_create' params\nexport const CatalogMacroCreateParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'catalog_macro_drop' params\nexport const CatalogMacroDropParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"ignore_not_found\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_macro_get' params\nexport const CatalogMacroGetParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_schema_contents_functions' params\nexport const CatalogSchemaContentsFunctionsParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"path\", list(field(\"item\", utf8(), true)), false),\n field(\"type\", dictionary(utf8(), int16()), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_schema_contents_indexes' params\nexport const CatalogSchemaContentsIndexesParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"path\", list(field(\"item\", utf8(), true)), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_schema_contents_macros' params\nexport const CatalogSchemaContentsMacrosParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"path\", list(field(\"item\", utf8(), true)), false),\n field(\"type\", dictionary(utf8(), int16()), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_schema_contents_tables' params\nexport const CatalogSchemaContentsTablesParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"path\", list(field(\"item\", utf8(), true)), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_schema_contents_views' params\nexport const CatalogSchemaContentsViewsParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"path\", list(field(\"item\", utf8(), true)), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_schema_create' params\nexport const CatalogSchemaCreateParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"path\", list(field(\"item\", utf8(), true)), false),\n field(\"on_conflict\", dictionary(utf8(), int16()), false),\n field(\"comment\", utf8(), true),\n field(\"tags\", map(field(\"key\", utf8(), false), field(\"value\", utf8(), true), false), true),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_schema_drop' params\nexport const CatalogSchemaDropParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"path\", list(field(\"item\", utf8(), true)), false),\n field(\"ignore_not_found\", bool(), false),\n field(\"cascade\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_schema_get' params\nexport const CatalogSchemaGetParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"path\", list(field(\"item\", utf8(), true)), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_schemas' params\nexport const CatalogSchemasParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_column_add' params\nexport const CatalogTableColumnAddParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"column_definition\", binary(), false),\n field(\"ignore_not_found\", bool(), false),\n field(\"if_column_not_exists\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_column_comment_set' params\nexport const CatalogTableColumnCommentSetParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"column_name\", utf8(), false),\n field(\"comment\", utf8(), true),\n field(\"ignore_not_found\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_column_default_drop' params\nexport const CatalogTableColumnDefaultDropParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"column_name\", utf8(), false),\n field(\"ignore_not_found\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_column_default_set' params\nexport const CatalogTableColumnDefaultSetParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"column_name\", utf8(), false),\n field(\"expression\", utf8(), false),\n field(\"ignore_not_found\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_column_drop' params\nexport const CatalogTableColumnDropParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"column_name\", utf8(), false),\n field(\"ignore_not_found\", bool(), false),\n field(\"if_column_exists\", bool(), false),\n field(\"cascade\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_column_rename' params\nexport const CatalogTableColumnRenameParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"column_name\", utf8(), false),\n field(\"new_column_name\", utf8(), false),\n field(\"ignore_not_found\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_column_statistics_get' params\nexport const CatalogTableColumnStatisticsGetParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_column_type_change' params\nexport const CatalogTableColumnTypeChangeParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"column_definition\", binary(), false),\n field(\"expression\", utf8(), true),\n field(\"ignore_not_found\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_comment_set' params\nexport const CatalogTableCommentSetParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"comment\", utf8(), true),\n field(\"ignore_not_found\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_create' params\nexport const CatalogTableCreateParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'catalog_table_delete_function_get' params\nexport const CatalogTableDeleteFunctionGetParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_drop' params\nexport const CatalogTableDropParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"ignore_not_found\", bool(), false),\n field(\"cascade\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_get' params\nexport const CatalogTableGetParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"at_unit\", utf8(), true),\n field(\"at_value\", utf8(), true),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_insert_function_get' params\nexport const CatalogTableInsertFunctionGetParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"transaction_opaque_data\", binary(), true),\n field(\"writable_branch_function_name\", utf8(), true),\n]);\n\n// Origin: method 'catalog_table_not_null_drop' params\nexport const CatalogTableNotNullDropParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"column_name\", utf8(), false),\n field(\"ignore_not_found\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_not_null_set' params\nexport const CatalogTableNotNullSetParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"column_name\", utf8(), false),\n field(\"ignore_not_found\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_rename' params\nexport const CatalogTableRenameParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"new_name\", utf8(), false),\n field(\"ignore_not_found\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_scan_branches_get' params\nexport const CatalogTableScanBranchesGetParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"at_unit\", utf8(), true),\n field(\"at_value\", utf8(), true),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_scan_function_get' params\nexport const CatalogTableScanFunctionGetParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"at_unit\", utf8(), true),\n field(\"at_value\", utf8(), true),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_table_update_function_get' params\nexport const CatalogTableUpdateFunctionGetParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_transaction_begin' params\nexport const CatalogTransactionBeginParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n]);\n\n// Origin: method 'catalog_transaction_commit' params\nexport const CatalogTransactionCommitParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"transaction_opaque_data\", binary(), false),\n]);\n\n// Origin: method 'catalog_transaction_rollback' params\nexport const CatalogTransactionRollbackParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"transaction_opaque_data\", binary(), false),\n]);\n\n// Origin: method 'catalog_version' params\nexport const CatalogVersionParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_view_comment_set' params\nexport const CatalogViewCommentSetParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"comment\", utf8(), true),\n field(\"ignore_not_found\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_view_create' params\nexport const CatalogViewCreateParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"definition\", utf8(), false),\n field(\"on_conflict\", dictionary(utf8(), int16()), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_view_drop' params\nexport const CatalogViewDropParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"ignore_not_found\", bool(), false),\n field(\"cascade\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_view_get' params\nexport const CatalogViewGetParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'catalog_view_rename' params\nexport const CatalogViewRenameParamsSchema = schema([\n field(\"attach_opaque_data\", binary(), false),\n field(\"schema_path\", list(field(\"item\", utf8(), true)), false),\n field(\"name\", utf8(), false),\n field(\"new_name\", utf8(), false),\n field(\"ignore_not_found\", bool(), false),\n field(\"transaction_opaque_data\", binary(), true),\n]);\n\n// Origin: method 'init' params\nexport const InitParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'table_buffering_combine' params\nexport const TableBufferingCombineParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'table_buffering_destructor' params\nexport const TableBufferingDestructorParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'table_buffering_process' params\nexport const TableBufferingProcessParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'table_function_cardinality' params\nexport const TableFunctionCardinalityParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'table_function_dynamic_to_string' params\nexport const TableFunctionDynamicToStringParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'table_function_plan' params\nexport const TableFunctionPlanParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n// Origin: method 'table_function_statistics' params\nexport const TableFunctionStatisticsParamsSchema = schema([\n field(\"request\", binary(), false),\n]);\n\n",
|
|
34
37
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n\n/** Raw identifier components of a catalog schema, from root to leaf. */\nexport type SchemaPath = string[];\n\n/** Case-insensitive key used for catalog lookup and function dispatch. */\nexport function normalizeSchemaPath(path: Iterable<unknown> | string): string[] {\n return typeof path === \"string\" ? [path] : Array.from(path, String);\n}\n\nexport function schemaPathKey(path: Iterable<unknown> | string): string {\n const normalized = normalizeSchemaPath(path);\n if (normalized.length === 0 || normalized.some((part) => part.length === 0)) {\n throw new Error(\"schema paths must contain at least one non-empty component\");\n }\n return normalized.map((part) => part.toLowerCase()).join(\"\\u0000\");\n}\n\nexport function schemaPathsEqual(left: Iterable<unknown> | string, right: Iterable<unknown> | string): boolean {\n return schemaPathKey(left) === schemaPathKey(right);\n}\n\nexport function schemaPathDisplay(path: Iterable<unknown> | string): string {\n return normalizeSchemaPath(path).map((part) => JSON.stringify(part)).join(\".\");\n}\n",
|
|
35
|
-
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Shared schemas and helpers used by every protocol handler.\n\nimport { type VgiSchema, schema, type VgiField, field, type VgiDataType, binary } from \"../../arrow/index.js\";\nimport type { OverloadContext } from \"../../functions/registry.js\";\nimport { batchToScalarDict, deserializeBatch, serializeBatch, batchFromColumns } from \"../../util/arrow/index.js\";\nimport { toUint8Array } from \"../../util/bytes.js\";\nimport {
|
|
38
|
+
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Shared schemas and helpers used by every protocol handler.\n\nimport { type VgiSchema, schema, type VgiField, field, type VgiDataType, binary } from \"../../arrow/index.js\";\nimport type { OverloadContext } from \"../../functions/registry.js\";\nimport { batchToScalarDict, deserializeBatch, serializeBatch, batchFromColumns } from \"../../util/arrow/index.js\";\nimport { toUint8Array } from \"../../util/bytes.js\";\nimport { normalizeSchemaPath } from \"../../schema-path.js\";\n\n// The Python vgi-rpc framework wraps ALL non-void unary results in a single\n// \"result\" column. For ArrowSerializableDataclass types, the result is serialized\n// as Arrow IPC bytes in a Binary column. DuckDB's VGI extension expects this format.\nexport const RESULT_BINARY_SCHEMA = schema([\n field(\"result\", binary(), false),\n]);\n\n// DuckDB wraps ArrowSerializableDataclass parameters in a single \"request\" Binary column.\nexport const REQUEST_PARAMS_SCHEMA = schema([\n field(\"request\", binary(), false),\n]);\n\nexport const RESULT_BINARY_NULLABLE_SCHEMA = schema([\n field(\"result\", binary(), true),\n]);\n\n/**\n * Unwrap a \"request\" Binary column: deserialize the inner Arrow IPC batch\n * and return flat columns as a dict (row 0).\n */\nexport function unwrapRequest(requestBytes: any): Record<string, any> {\n const bytes = toUint8Array(requestBytes);\n const innerBatch = deserializeBatch(bytes);\n const params = batchToScalarDict(innerBatch);\n normalizeRequestSchemaPaths(params);\n return params;\n}\n\n/** Convert Arrow list scalars at RPC boundaries into ordinary string arrays. */\nexport function normalizeRequestSchemaPaths(params: Record<string, any>): void {\n if (params.path != null) params.path = normalizeSchemaPath(params.path);\n if (params.schema_path != null) params.schema_path = normalizeSchemaPath(params.schema_path);\n}\n\n/**\n * Wrap a dict of values into a single \"result\" Binary column.\n * Builds a 1-row batch from the values using the given schema,\n * serializes it to IPC bytes, and returns { result: bytes }.\n */\nexport function wrapResult(\n values: Record<string, any>,\n innerSchema: VgiSchema | import(\"../../arrow/index.js\").VgiSchema,\n): { result: Uint8Array } {\n const a = innerSchema as VgiSchema;\n const batch = batchFromColumns(\n Object.fromEntries(a.fields.map(f => [f.name, [values[f.name] ?? null]])),\n a,\n );\n return { result: serializeBatch(batch) };\n}\n\nexport function overloadContext(\n req: {\n function_name: string;\n arguments: any;\n input_schema: any;\n function_type: any;\n schema_path?: string[] | null;\n attach_opaque_data?: Uint8Array | null;\n },\n catalogInterface?: { catalogNameForAttach(a: Uint8Array): string | null },\n): OverloadContext {\n // The attachment identifies the catalog, which is the only key separating two\n // catalogs that declare the same schema AND function name.\n let catalogName: string | null = null;\n if (catalogInterface && req.attach_opaque_data) {\n try {\n catalogName = catalogInterface.catalogNameForAttach(req.attach_opaque_data);\n } catch {\n catalogName = null;\n }\n }\n return {\n arguments: req.arguments,\n inputSchema: req.input_schema,\n isScalar: String(req.function_type).toLowerCase() === \"scalar\",\n // Scopes resolution when the caller named a schema; a name registered in\n // several schemas is otherwise ambiguous.\n schemaPath: req.schema_path ?? null,\n catalogName,\n };\n}\n",
|
|
36
39
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// VGI-specific error classes.\n\nexport class VgiError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"VgiError\";\n }\n}\n\nexport class RowCountMismatchError extends VgiError {\n constructor(expected: number, actual: number) {\n super(\n `Scalar function output row count (${actual}) does not match ` +\n `input row count (${expected})`\n );\n this.name = \"RowCountMismatchError\";\n }\n}\n\nexport class FunctionNotFoundError extends VgiError {\n constructor(name: string, available?: string[]) {\n super(`Unknown function '${name}'`);\n this.name = \"FunctionNotFoundError\";\n }\n}\n\nexport class CatalogReadOnlyError extends VgiError {\n constructor(operation: string) {\n super(`catalog is read-only: ${operation} is not supported`);\n this.name = \"CatalogReadOnlyError\";\n }\n}\n\nexport class CatalogNotFoundError extends VgiError {\n constructor(entity: string, name: string) {\n super(`${entity} '${name}' not found`);\n this.name = \"CatalogNotFoundError\";\n }\n}\n\nexport class CatalogAlreadyExistsError extends VgiError {\n constructor(entity: string, name: string) {\n super(`${entity} '${name}' already exists`);\n this.name = \"CatalogAlreadyExistsError\";\n }\n}\n\nexport class ArgumentValidationError extends VgiError {\n constructor(message: string) {\n super(message);\n this.name = \"ArgumentValidationError\";\n }\n}\n\nexport class NoCatalogError extends VgiError {\n constructor() {\n super(\"No catalog is configured for this worker\");\n this.name = \"NoCatalogError\";\n }\n}\n",
|
|
37
40
|
"/**\n * Utilities for hex, bytes, CSPRNG.\n * @module\n */\n/*! noble-ciphers - MIT License (c) 2023 Paul Miller (paulmillr.com) */\nexport function aarray(item, title, inner = () => { }) {\n if (!Array.isArray(item))\n throw new TypeError(`\"${title}\" expected array, got type=${typeof item}`);\n for (let i = 0; i < item.length; i++)\n inner(item[i], `${title}[${i}]`);\n return item;\n}\n/**\n * Checks if something is Uint8Array. Be careful: nodejs Buffer will return true.\n * @param a - Value to inspect.\n * @returns `true` when the value is a Uint8Array view, including Node's `Buffer`.\n * @example\n * Guards a value before treating it as raw key material.\n *\n * ```ts\n * isBytes(new Uint8Array());\n * ```\n */\nexport function isBytes(a) {\n // Plain `instanceof Uint8Array` is too strict for some Buffer / proxy /\n // cross-realm cases. The fallback still requires a real ArrayBuffer view\n // so plain JSON-deserialized `{ constructor: ... }`\n // spoofing is rejected, and `BYTES_PER_ELEMENT === 1` keeps the fallback on byte-oriented views.\n return (a instanceof Uint8Array ||\n (ArrayBuffer.isView(a) &&\n a.constructor.name === 'Uint8Array' &&\n 'BYTES_PER_ELEMENT' in a &&\n a.BYTES_PER_ELEMENT === 1));\n}\n// Shared error-message prefix builder. Only called on throw paths, so assert\n// success paths never pay for the string concatenation.\nconst atitle = (title) => (title ? `\"${title}\" ` : '');\n/**\n * Asserts something is boolean.\n * @param value - Value to validate.\n * @returns The validated boolean.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Validates a boolean option before branching on it.\n *\n * ```ts\n * abool(true);\n * ```\n */\nexport function abool(value, title = '') {\n if (typeof value !== 'boolean')\n throw new TypeError(atitle(title) + 'expected boolean, got type=' + typeof value);\n return value;\n}\n/**\n * Asserts something is a non-negative safe integer.\n * @param n - Value to validate.\n * @returns The validated number.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Validates a non-negative length or counter.\n *\n * ```ts\n * anumber(1);\n * ```\n */\nexport function anumber(n, title = '') {\n if (typeof n !== 'number')\n throw new TypeError(atitle(title) + 'expected number, got ' + typeof n);\n if (!Number.isSafeInteger(n) || n < 0)\n throw new RangeError(atitle(title) + 'expected integer >= 0, got ' + n);\n return n;\n}\n/**\n * Asserts something is Uint8Array.\n * @param value - Value to validate.\n * @param length - Expected byte length.\n * @param title - Optional label used in error messages.\n * @returns The validated byte array.\n * On Node, `Buffer` is accepted too because it is a Uint8Array view.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument lengths. {@link RangeError}\n * @example\n * Validates a fixed-length nonce or key buffer.\n *\n * ```ts\n * abytes(new Uint8Array([1, 2]), 2);\n * ```\n */\nexport function abytes(value, length, title = '') {\n // Success path first: this runs at the start of every update() / digestInto(), and the\n // common `abytes(data)` form must not pay for length handling it does not use.\n if (isBytes(value) && (length === undefined || value.length === length))\n return value;\n // Error path: recompute freely to build the exact message.\n if (length !== undefined)\n anumber(length, 'length');\n const bytes = isBytes(value);\n const ofLen = length !== undefined ? ` of length ${length}` : '';\n const got = bytes ? `length=${value.length}` : `type=${typeof value}`;\n const message = atitle(title) + 'expected Uint8Array' + ofLen + ', got ' + got;\n if (!bytes)\n throw new TypeError(message);\n throw new RangeError(message);\n}\nconst aobject = (value, label) => {\n if (value === null || typeof value !== 'object' || Array.isArray(value))\n throw new TypeError(label === 'object'\n ? 'expected valid options object'\n : `\"${label}\" expected object, got type=${typeof value}`);\n};\n/**\n * Asserts a hash- or MAC-like instance has not been destroyed or finished.\n * @param instance - Stateful instance to validate.\n * @param checkFinished - Whether to reject finished instances.\n * When `false`, only `destroyed` is checked.\n * @throws If the hash instance has already been destroyed or finalized. {@link Error}\n * @example\n * Guards against calling `update()` or `digest()` on a finished hash.\n *\n * ```ts\n * aexists({ destroyed: false, finished: false });\n * ```\n */\nexport function aexists(instance, checkFinished = true) {\n // Runs on every update()/digestInto(); the flags are library-owned booleans, so only their\n // truthiness is checked - re-validating their type per call was pure hot-path overhead.\n if (instance.destroyed)\n throw new Error('hash was destroyed');\n if (checkFinished && instance.finished)\n throw new Error('digest() was already called');\n}\n/**\n * Asserts output is a sufficiently-sized byte array.\n * @param out - Output buffer to validate.\n * @param instance - Hash-like instance providing `outputLen`.\n * This is the relaxed `digestInto()`-style contract: output must be at least `outputLen`,\n * unlike one-shot cipher helpers elsewhere in the repo that often require exact lengths.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong output buffer lengths. {@link RangeError}\n * @example\n * Verifies that a caller-provided output buffer is large enough.\n *\n * ```ts\n * aoutput(new Uint8Array(16), { outputLen: 16 });\n * ```\n */\nexport function aoutput(out, instance) {\n abytes(out, undefined, 'output');\n // `outputLen` is a library-owned readonly number; the negated comparison keeps failing fast\n // when it is missing/NaN (comparisons with undefined/NaN are false) without an anumber() call.\n const min = instance.outputLen;\n if (!(out.length >= min)) {\n throw new RangeError('\"output\" expected length >= ' + min);\n }\n}\n/**\n * Asserts output is a sufficiently-sized, 4-byte-aligned byte array.\n * {@link aoutput} plus an {@link isAligned32} check, for `digestInto()` paths\n * that write through zero-allocation `u32` word views.\n * @param out - Output buffer to validate.\n * @param instance - Hash-like instance providing `outputLen`.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong output buffer lengths. {@link RangeError}\n * @throws On wrong output buffer alignment. {@link Error}\n * @example\n * Verifies that a caller-provided output buffer is large enough and aligned.\n *\n * ```ts\n * aoutput32(new Uint8Array(16), { outputLen: 16 });\n * ```\n */\nexport function aoutput32(out, instance) {\n aoutput(out, instance);\n if (!isAligned32(out))\n throw new Error('invalid output, must be aligned');\n}\n/**\n * Casts a typed-array view to Uint8Array.\n * @param arr - Typed-array view to reinterpret.\n * @returns Uint8Array view over the same bytes.\n * @example\n * Views 32-bit words as raw bytes without copying.\n *\n * ```ts\n * u8(new Uint32Array([1]));\n * ```\n */\nexport function u8(arr) {\n return new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n/**\n * Casts a typed-array view to Uint32Array.\n * @param arr - Typed-array view to reinterpret.\n * @returns Uint32Array view over the same bytes. Callers are expected to provide a\n * 4-byte-aligned offset; trailing `1..3` bytes are silently dropped.\n * @example\n * Views a byte buffer as 32-bit words for block processing.\n *\n * ```ts\n * u32(new Uint8Array(4));\n * ```\n */\nexport function u32(arr) {\n return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));\n}\n/**\n * Zeroizes typed arrays in place.\n * Warning: JS provides no guarantees.\n * @param arrays - Arrays to wipe.\n * @example\n * Wipes a temporary key buffer after use.\n *\n * ```ts\n * const bytes = new Uint8Array([1]);\n * clean(bytes);\n * ```\n */\nexport function clean(...arrays) {\n for (let i = 0; i < arrays.length; i++) {\n arrays[i].fill(0);\n }\n}\n/**\n * Creates a DataView for byte-level manipulation.\n * @param arr - Typed-array view to wrap.\n * @returns DataView over the same bytes.\n * @example\n * Creates an endian-aware view for length encoding.\n *\n * ```ts\n * createView(new Uint8Array(4));\n * ```\n */\nexport function createView(arr) {\n return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n/**\n * Whether the current platform is little-endian.\n * Most are; some IBM systems are not.\n */\nexport const isLE = /* @__PURE__ */ (() => new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44)();\n/**\n * Reverses byte order of one 32-bit word.\n * @param word - Unsigned 32-bit word to swap.\n * @returns The same word with bytes reversed.\n * @example\n * Swaps a big-endian word into little-endian byte order.\n *\n * ```ts\n * byteSwap(0x11223344);\n * ```\n */\nexport function byteSwap(word) {\n return (((word << 24) & 0xff000000) |\n ((word << 8) & 0xff0000) |\n ((word >>> 8) & 0xff00) |\n ((word >>> 24) & 0xff));\n}\n/**\n * Normalizes one 32-bit word to the little-endian representation expected by cipher cores.\n * @param n - Unsigned 32-bit word to normalize.\n * @returns Little-endian normalized word on big-endian hosts, else the input word unchanged.\n * @example\n * Normalizes a host-endian word before passing it into an ARX/AES core.\n *\n * ```ts\n * swap8IfBE(0x11223344);\n * ```\n */\nexport const swap8IfBE = isLE\n ? (n) => n\n : (n) => byteSwap(n) >>> 0;\n/**\n * Byte-swaps every word of a Uint32Array in place.\n * @param arr - Uint32Array whose words should be swapped.\n * @returns The same array after in-place byte swapping.\n * @example\n * Swaps every 32-bit word in a word-view buffer.\n *\n * ```ts\n * byteSwap32(new Uint32Array([0x11223344]));\n * ```\n */\nexport function byteSwap32(arr) {\n for (let i = 0; i < arr.length; i++) {\n arr[i] = byteSwap(arr[i]);\n }\n return arr;\n}\n/**\n * Normalizes a Uint32Array view to the little-endian representation expected by cipher cores.\n * @param u - Word view to normalize in place.\n * @returns Little-endian normalized word view.\n * @example\n * Normalizes a word-view buffer before block processing.\n *\n * ```ts\n * swap32IfBE(new Uint32Array([0x11223344]));\n * ```\n */\nexport const swap32IfBE = isLE\n ? (u) => u\n : byteSwap32;\n// Built-in hex conversion:\n// {@link https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex | caniuse entry}\nconst hasHexBuiltin = /* @__PURE__ */ (() => \n// @ts-ignore\ntypeof Uint8Array.from([]).toHex === 'function' && typeof Uint8Array.fromHex === 'function')();\n// Array where index 0xf0 (240) is mapped to string 'f0'\nconst hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));\n/**\n * Convert byte array to hex string. Uses built-in function, when available.\n * @param bytes - Bytes to encode.\n * @returns Lowercase hexadecimal string.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Formats ciphertext bytes for logs or test vectors.\n *\n * ```ts\n * bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])); // 'cafe0123'\n * ```\n */\nexport function bytesToHex(bytes) {\n abytes(bytes);\n // @ts-ignore\n if (hasHexBuiltin)\n return bytes.toHex();\n // pre-caching improves the speed 6x\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += hexes[bytes[i]];\n }\n return hex;\n}\n// Strict ASCII nibble parser: non-ASCII hex lookalikes are rejected as undefined.\n// ASCII codes: '0'..'9' = 48..57, 'A'..'F' = 65..70, 'a'..'f' = 97..102.\n// prettier-ignore\nfunction asciiToBase16(ch) {\n return ch >= 48 && ch <= 57 ? ch - 48 // '2' => 50-48\n : ch >= 65 && ch <= 70 ? ch - (65 - 10) // 'B' => 66-(65-10)\n : ch >= 97 && ch <= 102 ? ch - (97 - 10) // 'b' => 98-(97-10)\n : undefined;\n}\n/**\n * Convert hex string to byte array. Uses built-in function, when available.\n * @param hex - hexadecimal string to decode\n * @returns Decoded bytes.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Decode lowercase hexadecimal into bytes.\n * ```ts\n * hexToBytes('cafe0123'); // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n * ```\n */\nexport function hexToBytes(hex) {\n if (typeof hex !== 'string')\n throw new TypeError('hex string expected, got ' + typeof hex);\n if (hasHexBuiltin) {\n try {\n return Uint8Array.fromHex(hex);\n }\n catch (error) {\n if (error instanceof SyntaxError)\n throw new RangeError(error.message);\n throw error;\n }\n }\n const hl = hex.length;\n const al = hl / 2;\n if (hl % 2)\n throw new RangeError('hex string expected, got unpadded hex of length ' + hl);\n const array = new Uint8Array(al);\n for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {\n const n1 = asciiToBase16(hex.charCodeAt(hi)); // parse first char, multiply it by 16\n const n2 = asciiToBase16(hex.charCodeAt(hi + 1)); // parse second char\n if (n1 === undefined || n2 === undefined) {\n const char = hex[hi] + hex[hi + 1];\n throw new RangeError('hex string expected, got non-hex character \"' + char + '\" at index ' + hi);\n }\n array[ai] = n1 * 16 + n2; // example: 'A9' => 10*16 + 9\n }\n return array;\n}\nconst _0n = /* @__PURE__ */ BigInt(0);\n// Used in ff1, via bytesToNumberBE\n/**\n * Converts a big-endian hex string into bigint.\n * @param hex - Hexadecimal string without `0x`.\n * @returns Parsed bigint value. The empty string is treated as `0n`.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Parses a big-endian field element or counter from hex.\n *\n * ```ts\n * hexToNumber('ff');\n * ```\n */\nexport function hexToNumber(hex) {\n if (typeof hex !== 'string')\n throw new TypeError('hex string expected, got ' + typeof hex);\n // Numeric parser, not byte-hex decoder: odd-length forms like 'f' are valid,\n // and malformed syntax follows BigInt's native error behavior.\n return hex === '' ? _0n : BigInt('0x' + hex); // Big Endian\n}\n// Used in ff1\n// BE: Big Endian, LE: Little Endian\n/**\n * Converts big-endian bytes into bigint.\n * @param bytes - Big-endian bytes.\n * @returns Parsed bigint value. Empty input is treated as `0n`.\n * @throws On invalid byte input passed to the internal hex conversion. {@link TypeError}\n * @example\n * Reads a big-endian integer from serialized bytes.\n *\n * ```ts\n * bytesToNumberBE(new Uint8Array([1, 0]));\n * ```\n */\nexport function bytesToNumberBE(bytes) {\n return hexToNumber(bytesToHex(bytes));\n}\n/**\n * Validates that a value is a non-negative bigint or safe integer.\n * @param n - Value to validate.\n * @returns The same validated value.\n * @throws On wrong argument ranges or values. {@link RangeError}\n */\nfunction abignumber(n) {\n if (typeof n === 'bigint') {\n if (!(_0n <= n))\n throw new RangeError('positive bigint expected, got ' + n);\n }\n else\n anumber(n);\n return n;\n}\n// Used in ff1\n/**\n * Converts a number into big-endian bytes of fixed length.\n * @param n - Number to encode.\n * @param len - Output length in bytes. Must be greater than zero.\n * @returns Big-endian bytes padded to `len`.\n * Negative values, `len = 0`, and values that do not fit are rejected before\n * downstream hex parsing.\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @throws If a documented runtime validation or state check fails. {@link Error}\n * @example\n * Encodes a counter as fixed-width big-endian bytes.\n *\n * ```ts\n * numberToBytesBE(1, 2);\n * ```\n */\nexport function numberToBytesBE(n, len) {\n anumber(len);\n if (len === 0)\n throw new Error('zero output length is invalid');\n n = abignumber(n);\n const expectedLen = len * 2;\n const hex = n.toString(16);\n // Detect overflow before hex parsing so oversized values don't leak the shared odd-hex error.\n if (hex.length > expectedLen)\n throw new RangeError('number is too large');\n return hexToBytes(hex.padStart(expectedLen, '0'));\n}\n/**\n * Converts string to bytes using UTF8 encoding.\n * @param str - String to encode.\n * @returns UTF-8 bytes in a detached fresh Uint8Array copy.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Encodes application text before encryption or MACing.\n *\n * ```ts\n * utf8ToBytes('abc'); // new Uint8Array([97, 98, 99])\n * ```\n */\nexport function utf8ToBytes(str) {\n if (typeof str !== 'string')\n throw new TypeError('string expected');\n return new Uint8Array(new TextEncoder().encode(str)); // {@link https://bugzil.la/1681809 | Firefox bug 1681809}\n}\n/**\n * Converts bytes to string using UTF8 encoding.\n * @param bytes - UTF-8 bytes.\n * @returns Decoded string. Input validation is delegated to `TextDecoder`, and malformed\n * UTF-8 is replacement-decoded instead of rejected.\n * @example\n * Decodes UTF-8 plaintext back into a string.\n *\n * ```ts\n * bytesToUtf8(new Uint8Array([97, 98, 99])); // 'abc'\n * ```\n */\nexport function bytesToUtf8(bytes) {\n return new TextDecoder().decode(bytes);\n}\n/**\n * Checks if two U8A use same underlying buffer and overlaps.\n * This is invalid and can corrupt data.\n * @param a - First byte view.\n * @param b - Second byte view.\n * @returns `true` when the views overlap in memory.\n * @example\n * Detects whether two slices alias the same backing buffer.\n *\n * ```ts\n * overlapBytes(new Uint8Array(4), new Uint8Array(4));\n * ```\n */\nexport function overlapBytes(a, b) {\n // Zero-length views cannot overwrite anything, even if their offset sits inside another range.\n if (!a.byteLength || !b.byteLength)\n return false;\n return (a.buffer === b.buffer && // best we can do, may fail with an obscure Proxy\n a.byteOffset < b.byteOffset + b.byteLength && // a starts before b end\n b.byteOffset < a.byteOffset + a.byteLength // b starts before a end\n );\n}\n/**\n * If input and output overlap and input starts before output, we will overwrite end of input before\n * we start processing it, so this is not supported for most ciphers\n * (except chacha/salsa, which were designed for this)\n * @param input - Input bytes.\n * @param output - Output bytes.\n * @throws If the output view would overwrite unread input bytes. {@link Error}\n * @example\n * Rejects an in-place layout that would overwrite unread input bytes.\n *\n * ```ts\n * complexOverlapBytes(new Uint8Array(4), new Uint8Array(4));\n * ```\n */\nexport function complexOverlapBytes(input, output) {\n // This is very cursed. It works somehow, but I'm completely unsure,\n // reasoning about overlapping aligned windows is very hard.\n if (overlapBytes(input, output) && input.byteOffset < output.byteOffset)\n throw new Error('complex overlap of input and output is not supported');\n}\n/**\n * Copies several Uint8Arrays into one.\n * @param arrays - Byte arrays to concatenate.\n * @returns Combined byte array.\n * @throws On wrong argument types inside the byte-array list. {@link TypeError}\n * @example\n * Builds a `nonce || ciphertext` style buffer.\n *\n * ```ts\n * concatBytes(new Uint8Array([1]), new Uint8Array([2]));\n * ```\n */\nexport function concatBytes(...arrays) {\n let sum = 0;\n for (let i = 0; i < arrays.length; i++) {\n const a = arrays[i];\n abytes(a);\n sum += a.length;\n }\n const res = new Uint8Array(sum);\n for (let i = 0, pad = 0; i < arrays.length; i++) {\n const a = arrays[i];\n res.set(a, pad);\n pad += a.length;\n }\n return res;\n}\n/**\n * Merges user options into defaults.\n * @param defaults - Default option values.\n * @param opts - User-provided overrides.\n * @returns Combined options object.\n * `defaults` is a library-owned mutable object; user-provided `opts` only need to be\n * object-shaped, since \"plain object\" checks reject valid proxy/cross-realm containers.\n * The merge mutates `defaults` in place and returns the same object, so direct callers\n * should pass a fresh defaults object unless they intentionally want shared state updated.\n * @throws If options are missing or not an object. {@link Error}\n * @example\n * Applies user overrides to the default cipher options.\n *\n * ```ts\n * checkOpts({ rounds: 20 }, { rounds: 8 });\n * ```\n */\nexport function checkOpts(defaults, opts) {\n aobject(defaults, 'defaults');\n aobject(opts, 'opts');\n // Mutates defaults by design. __proto__ follows Object.assign semantics here and can only\n // affect this local option object; callers already control this low-level options surface.\n const merged = Object.assign(defaults, opts);\n return merged;\n}\n/**\n * Compares two byte arrays in kinda constant time once lengths already match.\n * @param a - First byte array.\n * @param b - Second byte array.\n * @returns `true` when the arrays contain the same bytes. Different lengths still return early.\n * @example\n * Compares an expected authentication tag with the received one.\n *\n * ```ts\n * equalBytes(new Uint8Array([1]), new Uint8Array([1]));\n * ```\n */\nexport function equalBytes(a, b) {\n a = abytes(a);\n b = abytes(b);\n if (a.length !== b.length)\n return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++)\n diff |= a[i] ^ b[i];\n return diff === 0;\n}\n/**\n * Wraps a keyed MAC constructor into a one-shot helper with `.create()`.\n * @param keyLen - Valid probe-key length used to read static metadata once.\n * The probe key is only used for `outputLen` / `blockLen`, so callers with several valid key sizes\n * can pass any representative size as long as those values stay fixed.\n * @param macCons - Keyed MAC constructor or factory.\n * @param fromMsg - Optional adapter that derives extra constructor args from the one-shot message.\n * @returns Callable MAC helper with `.create()`.\n */\nexport function wrapMacConstructor(keyLen, macCons, fromMsg) {\n const mac = macCons;\n const getArgs = (fromMsg || (() => []));\n const macC = (msg, key) => mac(key, ...getArgs(msg))\n .update(msg)\n .digest();\n const tmp = mac(new Uint8Array(keyLen), ...getArgs(new Uint8Array(0)));\n macC.outputLen = tmp.outputLen;\n macC.blockLen = tmp.blockLen;\n macC.create = (key, ...args) => mac(key, ...args);\n return macC;\n}\n/**\n * Wraps a cipher: validates args, ensures encrypt() can only be called once.\n * Used internally by the exported cipher constructors.\n * Output-buffer support is inferred from the wrapped `encrypt` / `decrypt`\n * arity (`fn.length === 2`), so wrapped output-capable methods must use a normal\n * second parameter, not a default/rest parameter. AAD support is explicit in\n * `params.withAAD`; optional AAD starts after the nonce slot when one is present.\n * @__NO_SIDE_EFFECTS__\n * @param params - Static cipher metadata. See {@link CipherParams}.\n * @param constructor - Cipher constructor.\n * @returns Wrapped constructor with validation.\n */\nexport const wrapCipher = (params, constructor) => {\n function wrappedCipher(key, ...args) {\n // Validate key\n abytes(key, undefined, 'key');\n // Validate nonce if nonceLength is present\n if (params.nonceLength !== undefined) {\n const nonce = args[0];\n abytes(nonce, params.varSizeNonce ? undefined : params.nonceLength, 'nonce');\n }\n // Keep tag length available for decrypt-size checks after constructor validation.\n const tagl = params.tagLength;\n const aadStart = params.nonceLength !== undefined ? 1 : 0;\n // No-AAD constructors otherwise silently ignore byte args meant as AAD.\n if (!params.withAAD) {\n for (let i = aadStart; i < args.length; i++)\n if (isBytes(args[i]))\n throw new Error('AAD not supported');\n }\n // Validate the first AAD slot early; rest-arg AAD constructors validate the tail themselves.\n if (params.withAAD && args[aadStart] !== undefined)\n abytes(args[aadStart], undefined, 'AAD');\n const cipher = constructor(key, ...args);\n const checkOutput = (fnLength, output) => {\n if (output !== undefined) {\n if (fnLength !== 2)\n throw new Error('cipher output not supported');\n abytes(output, undefined, 'output');\n }\n };\n // Create wrapped cipher with validation and single-use encryption\n let called = false;\n const wrCipher = {\n encrypt(data, output) {\n if (called)\n throw new Error('cannot encrypt() twice with same key + nonce');\n // Any encrypt attempt consumes the instance, even if validation rejects below.\n called = true;\n abytes(data, undefined, 'data');\n checkOutput(cipher.encrypt.length, output);\n return cipher.encrypt(data, output);\n },\n decrypt(data, output) {\n abytes(data, undefined, 'data');\n if (tagl && data.length < tagl)\n throw new Error('\"ciphertext\" expected length >= tagLength=' + tagl);\n checkOutput(cipher.decrypt.length, output);\n return cipher.decrypt(data, output);\n },\n };\n return wrCipher;\n }\n Object.assign(wrappedCipher, params);\n return wrappedCipher;\n};\n/**\n * By default, returns u8a of length.\n * When out is available, it checks it for validity and uses it.\n * @param expectedLength - Required output length.\n * @param out - Optional destination buffer.\n * @param onlyAligned - Whether `out` must be 4-byte aligned.\n * @returns Output buffer ready for writing.\n * @throws On wrong argument types. {@link TypeError}\n * @throws If the provided output buffer has the wrong size. {@link RangeError}\n * @throws If the provided output buffer has the wrong alignment. {@link Error}\n * @example\n * Reuses a caller-provided output buffer when lengths match.\n *\n * ```ts\n * getOutput(16, new Uint8Array(16));\n * ```\n */\nexport function getOutput(expectedLength, out, onlyAligned = true) {\n if (out === undefined)\n return new Uint8Array(expectedLength);\n // Keep Buffer/cross-realm Uint8Array support here instead of trusting a shape-compatible object.\n abytes(out, expectedLength, 'output');\n if (onlyAligned && !isAligned32(out))\n throw new Error('invalid output, must be aligned');\n return out;\n}\n/**\n * Encodes data and AAD lengths into a 16-byte buffer.\n * @param dataLength - Data length. Units are caller-defined: GCM passes bit\n * lengths, ChaCha20-Poly1305 passes byte lengths — the helper writes the raw values.\n * @param aadLength - AAD length, same unit convention as `dataLength`.\n * The serialized block is still `aadLength || dataLength`, matching GCM/Poly1305\n * conventions even though the helper parameter order is `(dataLength, aadLength)`.\n * @param isLE - Whether to encode lengths as little-endian.\n * @returns 16-byte length block.\n * @throws On wrong argument types passed to the endian validator. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Builds the length block appended by GCM and Poly1305.\n *\n * ```ts\n * u64Lengths(16, 8, true);\n * ```\n */\nexport function u64Lengths(dataLength, aadLength, isLE) {\n // Reject coercible non-number lengths like '10' and true before BigInt(...) accepts them.\n anumber(dataLength);\n anumber(aadLength);\n abool(isLE);\n const num = new Uint8Array(16);\n const view = createView(num);\n view.setBigUint64(0, BigInt(aadLength), isLE);\n view.setBigUint64(8, BigInt(dataLength), isLE);\n return num;\n}\n/**\n * Checks whether a byte array is aligned to a 4-byte offset.\n * @param bytes - Byte array to inspect.\n * @returns `true` when the view is 4-byte aligned.\n * @example\n * Checks whether a buffer can be safely viewed as Uint32Array.\n *\n * ```ts\n * isAligned32(new Uint8Array(4));\n * ```\n */\nexport function isAligned32(bytes) {\n return bytes.byteOffset % 4 === 0;\n}\n/**\n * Copies bytes into a new Uint8Array.\n * @param bytes - Bytes to copy.\n * @returns Copied byte array.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Copies input into an aligned Uint8Array before block processing.\n *\n * ```ts\n * copyBytes(new Uint8Array([1, 2]));\n * ```\n */\nexport function copyBytes(bytes) {\n // `Uint8Array.from(...)` would also accept arrays / other typed arrays. Keep this helper strict\n // because callers use it at byte-validation boundaries before mutating the detached copy.\n return Uint8Array.from(abytes(bytes));\n}\n/**\n * Cryptographically secure PRNG backed by `crypto.getRandomValues`.\n * @param bytesLength - number of random bytes to generate\n * @returns Random bytes.\n * The platform `getRandomValues()` implementation still defines any\n * single-call length cap, and this helper rejects oversize requests\n * with a stable library `RangeError` instead of host-specific errors.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @throws If the current runtime does not provide `crypto.getRandomValues`. {@link Error}\n * @example\n * Generate a fresh random key or nonce.\n * ```ts\n * const key = randomBytes(16);\n * ```\n */\nexport function randomBytes(bytesLength = 32) {\n // Match the repo's other length-taking helpers instead of relying on Uint8Array coercion.\n anumber(bytesLength, 'bytesLength');\n const cr = typeof globalThis === 'object' ? globalThis.crypto : null;\n if (typeof cr?.getRandomValues !== 'function')\n throw new Error('crypto.getRandomValues must be defined');\n // Web Cryptography API Level 2 §10.1.1:\n // if `byteLength > 65536`, throw `QuotaExceededError`.\n // Keep the guard explicit so callers can see the quota in code\n // instead of discovering it by reading the spec or host errors.\n // This wrapper surfaces the same quota as a stable library RangeError.\n if (bytesLength > 65536)\n throw new RangeError(`\"bytesLength\" expected <= 65536, got ${bytesLength}`);\n return cr.getRandomValues(new Uint8Array(bytesLength));\n}\n/**\n * Uses CSPRNG for nonce, nonce injected in ciphertext.\n * For `encrypt`, a `nonceBytes`-length buffer is fetched from CSPRNG and\n * prepended to encrypted ciphertext. For `decrypt`, first `nonceBytes` of ciphertext\n * are treated as nonce. The wrapper always allocates a fresh `nonce || ciphertext`\n * buffer on encrypt and intentionally does not support caller-provided destination buffers.\n * Too-short decrypt inputs are split into short/empty nonce views and then delegated\n * to the wrapped cipher instead of being rejected here first.\n *\n * NOTE: Under the same key, using random nonces (e.g. `managedNonce`) with AES-GCM and ChaCha\n * should be limited to `2**23` (8M) messages to get a collision chance of\n * `2**-50`. Stretching to `2**32` (4B) messages would raise that chance to\n * `2**-33`, still negligible but creeping up.\n * @param fn - Cipher constructor that expects a nonce.\n * @param randomBytes_ - Random-byte source used for nonce generation.\n * @returns Cipher constructor that prepends the nonce to ciphertext.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On invalid nonce lengths observed at wrapper construction or use. {@link RangeError}\n * @example\n * Prepends a fresh random nonce to every ciphertext.\n *\n * ```ts\n * import { gcm } from '@noble/ciphers/aes.js';\n * import { managedNonce, randomBytes } from '@noble/ciphers/utils.js';\n * const wrapped = managedNonce(gcm);\n * const key = randomBytes(16);\n * const ciphertext = wrapped(key).encrypt(new Uint8Array([1, 2, 3]));\n * wrapped(key).decrypt(ciphertext);\n * ```\n */\nexport function managedNonce(fn, randomBytes_ = randomBytes) {\n if (typeof fn !== 'function')\n throw new TypeError('\"fn\" expected cipher constructor, got type=' + typeof fn);\n if (typeof randomBytes_ !== 'function')\n throw new TypeError('\"randomBytes_\" expected function, got type=' + typeof randomBytes_);\n const { nonceLength } = fn;\n anumber(nonceLength, 'fn.nonceLength');\n const addNonce = (nonce, ciphertext, plaintext) => {\n const out = concatBytes(nonce, ciphertext);\n // Wrapped ciphers may alias caller plaintext on encrypt(); never zero\n // caller-owned buffers here.\n if (!overlapBytes(plaintext, ciphertext))\n ciphertext.fill(0);\n return out;\n };\n // NOTE: we cannot support DST here, it would be mistake:\n // - we don't know how much dst length cipher requires\n // - nonce may unalign dst and break everything\n // - we create new u8a anyway (concatBytes)\n // - previously we passed all args to cipher, but that was mistake!\n const res = ((key, ...args) => ({\n encrypt(plaintext) {\n abytes(plaintext, undefined, 'data');\n const nonce = randomBytes_(nonceLength);\n const encrypted = fn(key, nonce, ...args).encrypt(plaintext);\n // @ts-ignore\n if (encrypted instanceof Promise)\n return encrypted.then((ct) => addNonce(nonce, ct, plaintext));\n return addNonce(nonce, encrypted, plaintext);\n },\n decrypt(ciphertext) {\n abytes(ciphertext, undefined, 'data');\n const nonce = ciphertext.subarray(0, nonceLength);\n const decrypted = ciphertext.subarray(nonceLength);\n return fn(key, nonce, ...args).decrypt(decrypted);\n },\n }));\n // Auto-nonce wrappers still preserve the wrapped payload geometry.\n if ('blockSize' in fn)\n res.blockSize = fn.blockSize;\n if ('tagLength' in fn)\n res.tagLength = fn.tagLength;\n if ('withAAD' in fn)\n res.withAAD = fn.withAAD;\n return res;\n}\n",
|
|
38
41
|
"/**\n * Basic utils for ARX (add-rotate-xor) salsa and chacha ciphers.\n\nRFC8439 requires multi-step cipher stream, where\nauthKey starts with counter: 0, actual msg with counter: 1.\n\nFor this, we need a way to re-use nonce / counter:\n\n const counter = new Uint8Array(4);\n chacha(..., counter, ...); // counter is now 1\n chacha(..., counter, ...); // counter is now 2\n\nThis is complicated:\n\n- 32-bit counters are enough, no need for 64-bit: max ArrayBuffer size in JS is 4GB\n- Original papers don't allow mutating counters\n- Counter overflow is undefined [^1]\n- Idea A: allow providing (nonce | counter) instead of just nonce, re-use it\n- Caveat: Cannot be re-used through all cases:\n- * chacha has (counter | nonce)\n- * xchacha has (nonce16 | counter | nonce16)\n- Idea B: separate nonce / counter and provide separate API for counter re-use\n- Caveat: there are different counter sizes depending on an algorithm.\n- salsa & chacha also differ in structures of key & sigma:\n salsa20: s[0] | k(4) | s[1] | nonce(2) | cnt(2) | s[2] | k(4) | s[3]\n chacha: s(4) | k(8) | cnt(1) | nonce(3)\n chacha20orig: s(4) | k(8) | cnt(2) | nonce(2)\n- Idea C: helper method such as `setSalsaState(key, nonce, sigma, data)`\n- Caveat: we can't re-use counter array\n\nxchacha uses the subkey and remaining 8 byte nonce with ChaCha20 as normal\n(prefixed by 4 NUL bytes, since RFC8439 specifies a 12-byte nonce).\nCounter overflow is undefined; see {@link https://mailarchive.ietf.org/arch/msg/cfrg/gsOnTJzcbgG6OqD8Sc0GO5aR_tU/ | the CFRG thread}.\nCurrent noble policy is strict non-wrap for the shared 32-bit counter path:\nexported ARX ciphers reject initial `0xffffffff` and stop before any implicit\nwrap back to zero.\nSee {@link https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha#appendix-A.2 | the XChaCha appendix} for the extended-nonce construction.\n\n * @module\n */\nimport { abool, abytes, anumber, checkOpts, clean, copyBytes, getOutput, isAligned32, isLE, randomBytes, swap32IfBE, u32, } from \"./utils.js\";\n// Replaces `TextEncoder` for ASCII literals, which is enough for sigma constants.\n// Non-ASCII input would not match UTF-8 `TextEncoder` output.\nconst encodeStr = (str) => Uint8Array.from(str.split(''), (c) => c.charCodeAt(0));\n// Raw `createCipher(...)` exports consume these native-endian `u32(...)` views directly.\n// Public `wrapCipher(...)` APIs reject non-little-endian platforms before reaching this path.\n// RFC 8439 §2.3 / RFC 7539 §2.3 only define the 256-bit-key constants; this 16-byte sigma is\n// kept for legacy allowShortKeys Salsa/ChaCha variants.\nconst sigma16_32 = /* @__PURE__ */ (() => swap32IfBE(u32(encodeStr('expand 16-byte k'))))();\n// RFC 8439 §2.3 / RFC 7539 §2.3 define words 0-3 as\n// `0x61707865 0x3320646e 0x79622d32 0x6b206574`, i.e. `expand 32-byte k`.\nconst sigma32_32 = /* @__PURE__ */ (() => swap32IfBE(u32(encodeStr('expand 32-byte k'))))();\n/**\n * Rotates a 32-bit word left.\n * @param a - Input word.\n * @param b - Rotation count in bits.\n * @returns Rotated 32-bit word.\n * @example\n * Moves the top byte of `0x12345678` into the low byte position.\n * ```ts\n * rotl(0x12345678, 8);\n * ```\n */\nexport function rotl(a, b) {\n return (a << b) | (a >>> (32 - b));\n}\n// Salsa and Chacha block length is always 512-bit\nconst BLOCK_LEN = 64;\n// RFC 8439 §2.2 / RFC 7539 §2.2: the ChaCha state has 16 32-bit words.\nconst BLOCK_LEN32 = 16;\n// Counter policy for the shared public `counter` argument:\n// - RFC/IETF ChaCha20 uses a 32-bit counter.\n// - OpenSSL/Node `chacha20` instead treat the full 16-byte IV as a 128-bit\n// counter state and carry into the next word.\n// - Raw `chacha20orig`, `salsa20`, `xsalsa20`, and `xchacha20` use 64-bit counters in libsodium\n// and libtomcrypt, while some libs (for example libtomcrypt's RFC/IETF path) reject the max\n// boundary instead of carrying.\n// - AEAD wrappers diverge too: libsodium `xchacha20poly1305` uses the IETF payload counter from\n// block 1, while `secretstream_xchacha20poly1305` is a different protocol with rekey/reset.\n// Noble intentionally throws instead of silently picking one wrap model for users. In the default\n// path, even a 32-bit boundary would take 2^32 blocks * 64 bytes = 256 GiB, which is practically\n// unreachable for normal JS callers; advanced users who pass `counter` explicitly can implement\n// whatever wider carry / wrap policy they need on top.\nconst MAX_COUNTER = /* @__PURE__ */ (() => 2 ** 32 - 1)();\nconst U32_EMPTY = /* @__PURE__ */ Uint32Array.of();\nfunction runCipher(core, sigma, key, nonce, data, output, counter, rounds) {\n const len = data.length;\n const block = new Uint8Array(BLOCK_LEN);\n const b32 = u32(block);\n // Make sure that buffers aligned to 4 bytes\n const isAligned = isLE && isAligned32(data) && isAligned32(output);\n const d32 = isAligned ? u32(data) : U32_EMPTY;\n const o32 = isAligned ? u32(output) : U32_EMPTY;\n // RFC 8439 §2.4.1 / RFC 7539 §2.4.1 allow XORing one keystream block at a time and\n // truncating the final partial block instead of materializing the whole keystream.\n if (!isLE) {\n for (let pos = 0; pos < len; counter++) {\n core(sigma, key, nonce, b32, counter, rounds);\n // RFC 8439 §2.4 / RFC 7539 §2.4 serialize keystream words in little-endian order.\n swap32IfBE(b32);\n if (counter >= MAX_COUNTER)\n throw new Error('arx: counter overflow');\n const take = Math.min(BLOCK_LEN, len - pos);\n for (let j = 0, posj; j < take; j++) {\n posj = pos + j;\n output[posj] = data[posj] ^ block[j];\n }\n pos += take;\n }\n return;\n }\n for (let pos = 0; pos < len; counter++) {\n core(sigma, key, nonce, b32, counter, rounds);\n // See MAX_COUNTER policy note above: never silently wrap the shared public counter.\n if (counter >= MAX_COUNTER)\n throw new Error('arx: counter overflow');\n const take = Math.min(BLOCK_LEN, len - pos);\n // aligned to 4 bytes\n if (isAligned && take === BLOCK_LEN) {\n const pos32 = pos / 4;\n if (pos % 4 !== 0)\n throw new Error('arx: invalid block position');\n for (let j = 0, posj; j < BLOCK_LEN32; j++) {\n posj = pos32 + j;\n o32[posj] = d32[posj] ^ b32[j];\n }\n pos += BLOCK_LEN;\n continue;\n }\n for (let j = 0, posj; j < take; j++) {\n posj = pos + j;\n output[posj] = data[posj] ^ block[j];\n }\n pos += take;\n }\n}\n/**\n * Creates an ARX stream cipher from a 32-bit core permutation.\n * Used internally to build the exported Salsa and ChaCha stream ciphers.\n * @param core - Core function that fills one keystream block.\n * @param opts - Cipher layout and nonce-extension options. See {@link CipherOpts}.\n * @returns Stream cipher function over byte arrays.\n * @throws If the core callback, key size, counter, or output sizing is invalid. {@link Error}\n */\nexport function createCipher(core, opts) {\n const { allowShortKeys, extendNonceFn, counterLength, counterRight, rounds } = checkOpts({ allowShortKeys: false, counterLength: 8, counterRight: false, rounds: 20 }, opts);\n if (typeof core !== 'function')\n throw new Error('core must be a function');\n anumber(counterLength);\n anumber(rounds);\n abool(counterRight);\n abool(allowShortKeys);\n return (key, nonce, data, output, counter = 0) => {\n abytes(key, undefined, 'key');\n abytes(nonce, undefined, 'nonce');\n abytes(data, undefined, 'data');\n const len = data.length;\n // Raw XorStream APIs return ciphertext/plaintext bytes directly, so caller-provided outputs\n // must match the logical result length exactly instead of returning an oversized workspace.\n output = getOutput(len, output, false);\n anumber(counter);\n // See MAX_COUNTER policy note above: reject advanced explicit-counter requests before any wrap.\n if (counter < 0 || counter >= MAX_COUNTER)\n throw new Error('arx: counter overflow');\n const toClean = [];\n // Key & sigma\n // key=16 -> sigma16, k=key|key\n // key=32 -> sigma32, k=key\n let l = key.length;\n let k;\n let sigma;\n if (l === 32) {\n // Copy caller keys too: big-endian normalization, extended-nonce subkey derivation, and\n // final clean(...) all mutate or wipe the temporary buffer in place.\n toClean.push((k = copyBytes(key)));\n sigma = sigma32_32;\n }\n else if (l === 16 && allowShortKeys) {\n k = new Uint8Array(32);\n k.set(key);\n k.set(key, 16);\n sigma = sigma16_32;\n toClean.push(k);\n }\n else {\n abytes(key, 32, 'arx key');\n throw new Error('invalid key size');\n // throw new Error(`\"arx key\" expected Uint8Array of length 32, got length=${l}`);\n }\n // Nonce\n // salsa20: 8 (8-byte counter)\n // chacha20orig: 8 (8-byte counter)\n // chacha20: 12 (4-byte counter)\n // xsalsa20: 24 (16 -> hsalsa, 8 -> old nonce)\n // xchacha20: 24 (16 -> hchacha, 8 -> old nonce)\n // Copy before taking u32(...) views on misaligned inputs, and on big-endian so later\n // swap32IfBE(...) never mutates caller nonce bytes in place.\n if (!isLE || !isAligned32(nonce))\n toClean.push((nonce = copyBytes(nonce)));\n let k32 = u32(k);\n // hsalsa & hchacha: handle extended nonce\n if (extendNonceFn) {\n if (nonce.length !== 24)\n throw new Error('arx: extended nonce must be 24 bytes');\n const n16 = nonce.subarray(0, 16);\n if (isLE)\n extendNonceFn(sigma, k32, u32(n16), k32);\n else {\n const sigmaRaw = swap32IfBE(Uint32Array.from(sigma));\n extendNonceFn(sigmaRaw, k32, u32(n16), k32);\n clean(sigmaRaw);\n swap32IfBE(k32);\n }\n nonce = nonce.subarray(16);\n }\n else if (!isLE)\n swap32IfBE(k32);\n // Handle nonce counter\n const nonceNcLen = 16 - counterLength;\n if (nonceNcLen !== nonce.length)\n throw new Error(`arx: nonce must be ${nonceNcLen} or 16 bytes`);\n // Normalize 64-bit-nonce layouts to the 12-byte core input: ChaCha/XChaCha prefix 4 zero\n // counter bytes, while Salsa/XSalsa append them after the nonce words.\n if (nonceNcLen !== 12) {\n const nc = new Uint8Array(12);\n nc.set(nonce, counterRight ? 0 : 12 - nonce.length);\n nonce = nc;\n toClean.push(nonce);\n }\n const n32 = swap32IfBE(u32(nonce));\n // Ensure temporary key/nonce copies are wiped even if the remaining\n // runtime guard in runCipher(...) throws on counter overflow.\n try {\n runCipher(core, sigma, k32, n32, data, output, counter, rounds);\n return output;\n }\n finally {\n clean(...toClean);\n }\n };\n}\n/** Internal class which wraps chacha20 or chacha8 to create CSPRNG. */\nexport class _XorStreamPRG {\n blockLen;\n keyLen;\n nonceLen;\n state;\n buf;\n key;\n nonce;\n pos;\n ctr;\n cipher;\n constructor(cipher, blockLen, keyLen, nonceLen, seed) {\n this.cipher = cipher;\n this.blockLen = blockLen;\n this.keyLen = keyLen;\n this.nonceLen = nonceLen;\n this.state = new Uint8Array(this.keyLen + this.nonceLen);\n this.reseed(seed);\n this.ctr = 0;\n this.pos = this.blockLen;\n this.buf = new Uint8Array(this.blockLen);\n // Keep a single key||nonce backing buffer so reseed/addEntropy/clean update the live cipher\n // inputs in place through these subarray views.\n this.key = this.state.subarray(0, this.keyLen);\n this.nonce = this.state.subarray(this.keyLen);\n }\n reseed(seed) {\n abytes(seed, undefined, 'seed');\n if (!seed || seed.length === 0)\n throw new Error('entropy required');\n // Mix variable-length entropy cyclically across the whole key||nonce state, then restart the\n // keystream so buffered leftovers from the previous state are never reused.\n for (let i = 0; i < seed.length; i++)\n this.state[i % this.state.length] ^= seed[i];\n this.ctr = 0;\n this.pos = this.blockLen;\n }\n addEntropy(seed) {\n // Reject empty entropy before re-keying, otherwise a throwing call would still advance state.\n abytes(seed, undefined, 'seed');\n if (seed.length === 0)\n throw new Error('entropy required');\n // Re-key from the current stream first, then mix external entropy into the fresh key||nonce\n // state through reseed() so stale buffered bytes are discarded.\n this.state.set(this.randomBytes(this.state.length));\n this.reseed(seed);\n }\n randomBytes(len) {\n anumber(len);\n if (len === 0)\n return new Uint8Array(0);\n const avail = this.pos < this.blockLen ? this.blockLen - this.pos : 0;\n const blocks = Math.ceil(Math.max(0, len - avail) / this.blockLen);\n // Preflight overflow so failed reads don't partially consume keystream\n // and leave the PRG repeating blocks.\n if (blocks > 0 && this.ctr > MAX_COUNTER - blocks)\n throw new Error('arx: counter overflow');\n const out = new Uint8Array(len);\n let outPos = 0;\n // `out` starts zero-filled, and `buf.fill(0)` below does the same for leftovers: XOR-stream\n // ciphers then emit raw keystream bytes directly into those buffers.\n // Serve buffered leftovers first so split reads stay identical to one larger read.\n if (this.pos < this.blockLen) {\n const take = Math.min(len, this.blockLen - this.pos);\n out.set(this.buf.subarray(this.pos, this.pos + take), 0);\n this.pos += take;\n outPos += take;\n if (outPos === len)\n return out; // fast path\n }\n // Full blocks directly to out\n const full = Math.floor((len - outPos) / this.blockLen);\n if (full > 0) {\n const blockBytes = full * this.blockLen;\n const b = out.subarray(outPos, outPos + blockBytes);\n this.cipher(this.key, this.nonce, b, b, this.ctr);\n this.ctr += full;\n outPos += blockBytes;\n }\n // Save leftovers\n const left = len - outPos;\n if (left > 0) {\n this.buf.fill(0);\n // NOTE: cipher will handle overflow\n this.cipher(this.key, this.nonce, this.buf, this.buf, this.ctr++);\n out.set(this.buf.subarray(0, left), outPos);\n this.pos = left;\n }\n return out;\n }\n // Clone seeds the new instance from this stream, so the source PRG advances too.\n clone() {\n return new _XorStreamPRG(this.cipher, this.blockLen, this.keyLen, this.nonceLen, this.randomBytes(this.state.length));\n }\n // Zeroes the current state and leftover buffer, but does not make the instance unusable:\n // Later reads first drain zeros from the cleared buffer and then continue\n // from zero key||nonce state.\n clean() {\n this.pos = 0;\n this.ctr = 0;\n this.buf.fill(0);\n this.state.fill(0);\n }\n}\n/**\n * Creates a PRG constructor from a stream cipher.\n * @param cipher - Stream cipher used to fill output blocks.\n * @param blockLen - Keystream block length in bytes.\n * @param keyLen - Internal key length in bytes.\n * @param nonceLen - Internal nonce length in bytes.\n * @returns PRG factory for seeded concrete `_XorStreamPRG` instances.\n * @example\n * Builds a PRG from XChaCha20 and reads bytes from a randomly seeded instance.\n * ```ts\n * import { xchacha20 } from '@noble/ciphers/chacha.js';\n * import { createPRG } from '@noble/ciphers/_arx.js';\n * import { randomBytes } from '@noble/ciphers/utils.js';\n * const seed = randomBytes(32);\n * const init = createPRG(xchacha20, 64, 32, 24);\n * const prg = init(seed);\n * prg.randomBytes(8);\n * ```\n */\nexport const createPRG = (cipher, blockLen, keyLen, nonceLen) => {\n return ((seed = randomBytes(32)) => new _XorStreamPRG(cipher, blockLen, keyLen, nonceLen, seed));\n};\n",
|
|
@@ -43,16 +46,17 @@
|
|
|
43
46
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Request-scoped caller identity, for the code paths the RPC framework cannot\n// hand a CallContext to.\n//\n// Every unary VGI method receives the caller's `AuthContext` directly — the\n// dispatcher passes the OutputCollector, which *is* a CallContext. The stream\n// `init` method does not: `@query-farm/vgi-rpc` types stream initialization as\n// `(params) => state`, with no context parameter, on both the pipe and HTTP\n// dispatchers. That is a framework signature this package cannot change.\n//\n// It matters because `init` opens two identity-bound AEAD envelopes:\n// `attach_opaque_data` (sealed under `attachAad(auth)` by `catalog_attach`) and\n// every split token (sealed under `splitTokenAad(body, auth)` by\n// `table_function_plan`). Both of those minting sites ARE unary and therefore\n// seal under the REAL principal. Opening them under a hard-coded `undefined`\n// yields the anonymous identity tail, so the AAD only ever matches for an\n// anonymous caller: an authenticated one gets `OpaqueDataRejectedError:\n// attach_opaque_data not recognized` on the first scan. Anonymous workers never\n// saw it, which is why it survived — the example HTTP workers authenticate\n// nobody.\n//\n// The reference implementations solve this with an ambient, request-scoped\n// identity rather than a parameter: vgi-python reads a `ContextVar` via\n// `current_auth()`; vgi-go's RPC framework threads a `*CallContext` into\n// `handleInit`. This is the TypeScript equivalent — an `AsyncLocalStorage`\n// scope opened per HTTP request by `createVgiFetch` (see `http/fetch.ts`),\n// read here.\n//\n// Deliberately a registry rather than a direct `node:async_hooks` import: this\n// module is reachable from the protocol handlers, which also run under stdio,\n// AF_UNIX and browser builds. Only the HTTP entry points install a scope, and\n// they load `node:async_hooks` defensively. With no scope installed\n// `currentRequestAuth()` returns `undefined`, which is exactly the previous\n// behaviour — and correct, because a worker with no signing key seals nothing.\n\nimport type { AuthContext } from \"@query-farm/vgi-rpc\";\n\n/** Mutable per-request cell. The scope is opened before the identity is known\n * (authentication happens inside the handler), so the holder is published\n * first and filled in when the framework reports the principal. */\nexport interface RequestAuthHolder {\n auth?: AuthContext;\n}\n\n/** The slice of `AsyncLocalStorage` this module needs. Structural on purpose:\n * it keeps `node:async_hooks` out of every non-HTTP build, and lets a test\n * install a trivial stub. */\nexport interface RequestAuthScope {\n getStore(): RequestAuthHolder | undefined;\n}\n\nlet scope: RequestAuthScope | undefined;\n\n/**\n * Publish the scope `currentRequestAuth()` reads. Called once per process by\n * the HTTP entry point; idempotent for the same scope.\n */\nexport function setRequestAuthScope(next: RequestAuthScope | undefined): void {\n scope = next;\n}\n\n/**\n * The authenticated principal of the request being served on this async\n * context, or `undefined` when there is none — no scope installed (stdio /\n * AF_UNIX / a host that has no `AsyncLocalStorage`), or an unauthenticated\n * request.\n *\n * `undefined` and an anonymous `AuthContext` produce the same identity tail, so\n * the two cases need not be distinguished by callers.\n */\nexport function currentRequestAuth(): AuthContext | undefined {\n return scope?.getStore()?.auth;\n}\n",
|
|
44
47
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// TableFunctionPlanRequest / PlanResponse / ScanSplit wire serialization.\n//\n// Field ORDER and nullability are wire-significant: they mirror vgi/protocol.py\n// exactly, and the extension rejects a response whose schema disagrees.\n\nimport { type VgiSchema, schema, field, binary, bool, int64, list } from \"../../arrow/index.js\";\nimport {\n ScanSplitSchema,\n TableFunctionPlanResultSchema,\n} from \"../../generated/vgi-protocol-schemas.js\";\nimport type { BindRequest } from \"../types.js\";\nimport { deserializeBatch, batchToScalarDict } from \"../../util/arrow/index.js\";\nimport { toUint8Array } from \"./shared.js\";\nimport { deserializeBindRequest } from \"./bind.js\";\n\n/**\n * One named, independently redeemable unit of scan work.\n *\n * A worker sets `payload` and nothing else; the framework stamps `token` from\n * it, so an author cannot forget the consistency anchor or mis-bind the\n * fingerprint. The client sends the TOKEN back, never the raw payload.\n */\nexport interface ScanSplit {\n /** The worker's own bytes NAMING this unit of work. */\n payload: Uint8Array;\n /** Framework-stamped envelope. Set by the framework, never by a worker. */\n token?: Uint8Array;\n estimatedRows?: number | bigint | null;\n /** True if `estimatedRows` is exact — unlocks COUNT(*) from statistics. */\n rowsExact?: boolean;\n /**\n * Load-bearing for engines that bin-pack (DataFusion weight, Trino\n * SplitWeight). Omitting it degrades them to round-robin by count; a greedily\n * claiming client needs no cost model at all.\n */\n estimatedBytes?: number | bigint | null;\n /** 2-row (min, max) batch in the existing `vgi_partition_values` encoding. */\n partitionBounds?: Uint8Array | null;\n columnStatistics?: Uint8Array | null;\n locationIds?: number[] | null;\n startPosition?: Uint8Array | null;\n /** Absent means UNBOUNDED — a shard read forever. */\n endPosition?: Uint8Array | null;\n}\n\n/** What a table function's `plan` hook returns. */\nexport interface PlanResult {\n /**\n * One entry per unit of work. EMPTY is legal and means \"no work\": a\n * fully-pruned scan reaches it, and the client must produce an empty result\n * rather than an error.\n */\n splits: ScanSplit[];\n /**\n * Continued enumeration. More than one MUST partition the remaining\n * enumeration disjointly and exhaustively. No client checks this: a dedup was\n * tried and removed (it needed a set holding a copy of every token, it compared\n * token bytes so it could never work on a keyed worker where each mint uses a\n * fresh nonce, and the most a client can do with a duplicate is refuse anyway).\n * Violating it returns DUPLICATE ROWS, silently.\n */\n nextCursors?: Uint8Array[];\n /** NORMATIVE cap on redemption concurrency, not advisory. */\n maxWorkers?: number | null;\n estimatedTotalSplits?: number | bigint | null;\n estimatedTotalRows?: number | bigint | null;\n estimatedTotalBytes?: number | bigint | null;\n /**\n * The counter a stale token is detected against, and the anchor the framework\n * stamps into every token in this plan.\n */\n catalogVersion?: number | bigint | null;\n /**\n * `catalog` (the default) or `transaction`. A transaction-scoped plan is not\n * cacheable and is not redeemable after commit or rollback.\n */\n scope?: \"catalog\" | \"transaction\";\n cacheMaxAgeSeconds?: number | null;\n}\n\n/** The request a client sends to divide a scan. */\nexport interface TableFunctionPlanRequest {\n bind_call: BindRequest;\n bind_opaque_data: Uint8Array | null;\n projection_ids: number[] | null;\n pushdown_filters: Uint8Array | null;\n /** The primary sizing lever: every engine is byte-driven. */\n target_split_bytes: bigint | null;\n /**\n * The parallelism FLOOR — a small but expensive table still needs one reader\n * per thread, which a byte target alone would not give it.\n */\n min_splits: bigint | null;\n /**\n * A place in the ENUMERATION of splits — NOT a place in the data. A cursor\n * lives for one plan call; a position is checkpointed and must survive\n * restarts, upgrades and key rotation.\n */\n cursor: Uint8Array | null;\n}\n\n/**\n * The ScanSplit shape, from codegen rather than hand-written.\n *\n * It used to be spelled out here, and hand-written is how four SDKs ended up\n * disagreeing about which of these columns were binary and which were\n * large_binary — a disagreement the client surfaced as \"the worker bypassed the\n * framework\", on every scan.\n */\nexport const SCAN_SPLIT_SCHEMA: VgiSchema = ScanSplitSchema as VgiSchema;\n\n/**\n * The PlanResponse shape, taken from codegen rather than hand-written: it is\n * regenerated from the canonical protocol, so it cannot drift.\n */\nexport const PLAN_RESPONSE_SCHEMA: VgiSchema = TableFunctionPlanResultSchema as VgiSchema;\n\n/**\n * Decode a plan request.\n *\n * A client sends only the sizing inputs it actually has — the DuckDB extension\n * sends seven columns, because it has no basis to invent a byte target it did\n * not set — so every field but `bind_call` is read defensively.\n */\nexport function deserializePlanRequest(params: Record<string, any>): TableFunctionPlanRequest {\n const bindCallBytes = toUint8Array(params.bind_call);\n const bindCall = deserializeBindRequest(batchToScalarDict(deserializeBatch(bindCallBytes)));\n\n let projectionIds: number[] | null = null;\n if (params.projection_ids != null) {\n const raw = params.projection_ids;\n if (Array.isArray(raw)) projectionIds = raw.map(Number);\n else if (raw && typeof raw[Symbol.iterator] === \"function\") projectionIds = [...raw].map(Number);\n }\n\n const asBigInt = (v: unknown): bigint | null =>\n v == null ? null : typeof v === \"bigint\" ? v : BigInt(Number(v));\n\n return {\n bind_call: bindCall,\n bind_opaque_data: params.bind_opaque_data ? toUint8Array(params.bind_opaque_data) : null,\n projection_ids: projectionIds,\n pushdown_filters: params.pushdown_filters ? toUint8Array(params.pushdown_filters) : null,\n target_split_bytes: asBigInt(params.target_split_bytes),\n min_splits: asBigInt(params.min_splits),\n cursor: params.cursor ? toUint8Array(params.cursor) : null,\n };\n}\n\n/**\n * The raw bind fields the split-token fingerprint is derived from.\n *\n * Read from the UNDECODED bind_call dict rather than the parsed BindRequest,\n * because the fingerprint must be reproducible byte-for-byte between the plan\n * that minted a token and the init that redeems it. A decoded-then-re-encoded\n * argument list is not guaranteed to round-trip to identical bytes; the wire\n * bytes are.\n */\nexport function fingerprintInputs(bindCallBytes: Uint8Array): {\n schemaPath: string[];\n functionName: string;\n args: Uint8Array;\n settings: Uint8Array;\n} {\n const dict = batchToScalarDict(deserializeBatch(bindCallBytes));\n return {\n schemaPath: dict.schema_path == null\n ? []\n : (Array.isArray(dict.schema_path) ? dict.schema_path : [...dict.schema_path]).map(String),\n functionName: String(dict.function_name ?? \"\"),\n args: dict.arguments ? toUint8Array(dict.arguments) : new Uint8Array(0),\n settings: dict.settings ? toUint8Array(dict.settings) : new Uint8Array(0),\n };\n}\n\n/** Build the row dict for one `ScanSplit`. */\nexport function scanSplitRow(split: ScanSplit, token: Uint8Array): Record<string, any> {\n const asBigInt = (v: number | bigint | null | undefined): bigint | null =>\n v == null ? null : typeof v === \"bigint\" ? v : BigInt(v);\n return {\n // Cleared, not forwarded. The payload is sealed INTO the token, and shipping\n // the plaintext in the field beside the ciphertext made the seal decorative.\n // No client reads it — the C++ side pulls `token` alone — and redemption\n // recovers the payload from inside the envelope.\n payload: new Uint8Array(0),\n token,\n estimated_rows: asBigInt(split.estimatedRows),\n rows_exact: split.rowsExact === true,\n estimated_bytes: asBigInt(split.estimatedBytes),\n partition_bounds: split.partitionBounds ?? null,\n column_statistics: split.columnStatistics ?? null,\n location_ids: split.locationIds ?? null,\n start_position: split.startPosition ?? null,\n end_position: split.endPosition ?? null,\n };\n}\n\n/** Build the row dict for a `PlanResponse`, given already-serialized splits. */\nexport function planResponseRow(result: PlanResult, splitBlobs: Uint8Array[]): Record<string, any> {\n const asBigInt = (v: number | bigint | null | undefined): bigint | null =>\n v == null ? null : typeof v === \"bigint\" ? v : BigInt(v);\n return {\n splits: splitBlobs,\n next_cursors: result.nextCursors ?? [],\n execution_id: null,\n init_opaque_data: new Uint8Array(0),\n max_workers: asBigInt(result.maxWorkers),\n estimated_total_splits: asBigInt(result.estimatedTotalSplits),\n estimated_total_rows: asBigInt(result.estimatedTotalRows),\n estimated_total_bytes: asBigInt(result.estimatedTotalBytes),\n catalog_version: asBigInt(result.catalogVersion),\n scope: result.scope ?? \"catalog\",\n locations: null,\n partitioning: [],\n sort_order: [],\n cache_max_age_seconds: asBigInt(result.cacheMaxAgeSeconds),\n start_position: new Uint8Array(0),\n end_position: new Uint8Array(0),\n };\n}\n",
|
|
45
48
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n\n/**\n * Split-token envelope: the framework's wrapper around a worker's split payload.\n *\n * A split token *names* a unit of scan work so a distributed engine can\n * re-request exactly the work it was handed. The worker supplies only the\n * payload; everything around it is stamped here, so an author cannot forget the\n * consistency anchor or mis-bind the fingerprint, and never writes crypto.\n *\n * Layout (little-endian, fixed prefix) — byte-identical across every SDK:\n *\n * ```\n * offset size field\n * 0 1 format_version currently 1\n * 1 1 flags bit0 = payload_sealed; bits 1-7 reserved, MUST be 0\n * 2 2 anchor_len u16 LE\n * 4 16 bind_fingerprint truncated SHA-256 of the bind identity\n * 20 var consistency_anchor anchor_len bytes\n * 20+n var payload the worker's own bytes\n * ```\n *\n * **The header is plaintext on every transport; only the payload is sealed.**\n * That is not a preference: a worker has no signing key on subprocess and unix,\n * which is DuckDB's primary path, so a header readable only through AEAD would be\n * unreadable exactly where DuckDB runs. It also matters for streaming — a\n * checkpointed position must survive key rotation.\n *\n * @module\n */\n\nimport type { AuthContext } from \"@query-farm/vgi-rpc\";\n\nimport { identityTail, openBytes, sealBytes } from \"./crypto.js\";\n\n/** Envelope format version. Checked unconditionally, before anything else. */\nexport const SPLIT_TOKEN_FORMAT_VERSION = 1;\n\n/** bit0 of `flags`: the payload is AEAD-sealed rather than plaintext. */\nconst FLAG_PAYLOAD_SEALED = 0x01;\n\n/** bits 1-7 are reserved and MUST be zero; a set bit is a forward-compat violation. */\nconst RESERVED_FLAGS_MASK = 0xfe;\n\nconst FINGERPRINT_LEN = 16;\nconst HEADER_LEN = 4 + FINGERPRINT_LEN;\n\n/**\n * Matches the reference default (`crypto.seal_bytes` version=1), so a token\n * sealed by one SDK opens in another.\n */\nconst SEAL_VERSION = 1;\n\nconst AAD_PREFIX = new TextEncoder().encode(\"vgi.split_token.v1\\u0000\");\n\n/** Stable error-kind strings, identical across SDKs. */\nexport const SPLIT_TOKEN_INVALID = \"SPLIT_TOKEN_INVALID\";\nexport const SPLIT_SNAPSHOT_EXPIRED = \"SPLIT_SNAPSHOT_EXPIRED\";\nexport const SPLIT_TRANSACTION_ENDED = \"SPLIT_TRANSACTION_ENDED\";\n\n/**\n * Why a split token was refused.\n *\n * The kind matters to a connector: only `SPLIT_SNAPSHOT_EXPIRED` means \"re-run\n * the query\", and neither kind is retriable in place. Keeping the anchor in the\n * PLAINTEXT header rather than in the AAD is what makes that distinction\n * expressible — inside the AAD both collapse into one tag-check failure.\n */\nexport class SplitTokenError extends Error {\n readonly kind: string;\n\n constructor(kind: string, message: string) {\n // The message carries the stable KIND, because the kind is the part a caller\n // acts on: only SPLIT_SNAPSHOT_EXPIRED means \"re-run the query\", and a\n // connector several layers up sees the message string rather than this\n // class. Without it the three failures are indistinguishable to everyone\n // downstream.\n super(`[${kind}] ${message}`);\n this.name = \"SplitTokenError\";\n this.kind = kind;\n }\n}\n\nfunction concat(...parts: Uint8Array[]): Uint8Array {\n const total = parts.reduce((n, p) => n + p.length, 0);\n const out = new Uint8Array(total);\n let at = 0;\n for (const p of parts) {\n out.set(p, at);\n at += p.length;\n }\n return out;\n}\n\nfunction equalBytes(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];\n return diff === 0;\n}\n\n/**\n * Derive the 16-byte binding check for a bind call.\n *\n * Minted **and** verified by the same worker, so it needs self-consistency only\n * — it does not have to agree with any client, which is why the cross-SDK byte\n * fixtures do not cover it. 16 bytes is a binding check, not a MAC: forgery\n * resistance comes from the seal where a key exists, and from the uid trust\n * boundary where one does not.\n *\n * Uses Web Crypto rather than a hash dependency so this works unchanged in the\n * browser and Cloudflare Workers builds.\n */\nexport async function bindFingerprint(\n schemaPath: string[],\n functionName: string,\n args: Uint8Array,\n settings: Uint8Array,\n projection: Uint8Array,\n): Promise<Uint8Array> {\n const enc = new TextEncoder();\n const zero = Uint8Array.of(0);\n const field = (label: string, value: Uint8Array) => concat(enc.encode(label), zero, value, zero);\n const message = concat(\n AAD_PREFIX,\n field(\"schema_path\", enc.encode(JSON.stringify(schemaPath))),\n field(\"function_name\", enc.encode(functionName)),\n field(\"arguments\", args),\n field(\"settings\", settings),\n field(\"projection_ids\", projection),\n );\n const digest = await crypto.subtle.digest(\"SHA-256\", message as BufferSource);\n return new Uint8Array(digest).slice(0, FINGERPRINT_LEN);\n}\n\n/**\n * AAD for a sealed split payload: the plaintext header plus the caller identity.\n *\n * The identity half is load-bearing, not incidental — it stops a token minted for\n * one principal being replayed by another, exactly as the attach envelope does. A\n * split token names data (files, offsets, tenant partitions), so dropping it here\n * while keeping it on attach would be a regression.\n */\nfunction splitTokenAad(header: Uint8Array, auth: AuthContext | undefined): Uint8Array {\n return concat(header, identityTail(auth));\n}\n\n/**\n * Encode the consistency anchor.\n *\n * `catalog_version` is the counter that MOVES within an attach, so it is what a\n * plan is pinned to; `resolved_data_version` is fixed at attach and would say\n * nothing about staleness.\n */\nexport function splitAnchor(catalogVersion: bigint | number): Uint8Array {\n const out = new Uint8Array(8);\n new DataView(out.buffer).setBigInt64(0, BigInt(catalogVersion), true);\n return out;\n}\n\n/** Stamp (and, when a key exists, seal) a worker payload into a split token. */\nexport async function buildSplitToken(opts: {\n payload: Uint8Array;\n fingerprint: Uint8Array;\n anchor: Uint8Array;\n signingKey?: Uint8Array;\n auth?: AuthContext;\n}): Promise<Uint8Array> {\n const { payload, fingerprint, anchor, signingKey, auth } = opts;\n if (fingerprint.length !== FINGERPRINT_LEN) {\n throw new SplitTokenError(\n SPLIT_TOKEN_INVALID,\n `bind_fingerprint must be ${FINGERPRINT_LEN} bytes, got ${fingerprint.length}`,\n );\n }\n if (anchor.length > 0xffff) {\n throw new SplitTokenError(\n SPLIT_TOKEN_INVALID,\n `consistency_anchor too long: ${anchor.length} bytes exceeds u16`,\n );\n }\n\n const head = new Uint8Array(4);\n head[0] = SPLIT_TOKEN_FORMAT_VERSION;\n head[1] = signingKey ? FLAG_PAYLOAD_SEALED : 0;\n new DataView(head.buffer).setUint16(2, anchor.length, true);\n const body = concat(head, fingerprint, anchor);\n\n if (!signingKey) return concat(body, payload);\n const sealed = await sealBytes(payload, signingKey, splitTokenAad(body, auth), SEAL_VERSION);\n return concat(body, sealed);\n}\n\n/**\n * Verify a split token and return the worker's payload.\n *\n * `expectedFingerprint` and `currentAnchor` are optional; omitting one skips that\n * check.\n */\nexport async function openSplitToken(\n token: Uint8Array,\n opts: {\n signingKey?: Uint8Array;\n auth?: AuthContext;\n expectedFingerprint?: Uint8Array;\n currentAnchor?: Uint8Array;\n } = {},\n): Promise<Uint8Array> {\n const { signingKey, auth, expectedFingerprint, currentAnchor } = opts;\n\n if (token.length < HEADER_LEN) {\n throw new SplitTokenError(\n SPLIT_TOKEN_INVALID,\n `split token too short: ${token.length} bytes, need at least ${HEADER_LEN}`,\n );\n }\n const version = token[0];\n const flags = token[1];\n const view = new DataView(token.buffer, token.byteOffset, token.byteLength);\n const anchorLen = view.getUint16(2, true);\n\n if (version !== SPLIT_TOKEN_FORMAT_VERSION) {\n throw new SplitTokenError(\n SPLIT_TOKEN_INVALID,\n `unsupported split-token format_version ${version}; this worker speaks ` +\n `${SPLIT_TOKEN_FORMAT_VERSION}`,\n );\n }\n if (flags & RESERVED_FLAGS_MASK) {\n throw new SplitTokenError(\n SPLIT_TOKEN_INVALID,\n `split token sets reserved flag bits (flags=0x${flags.toString(16).padStart(2, \"0\")})`,\n );\n }\n const sealed = (flags & FLAG_PAYLOAD_SEALED) !== 0;\n\n // ---- The alg:none refusal. Load-bearing; do not relax. ----\n // `flags` is attacker-controlled plaintext, so it may say \"not sealed\" on a\n // token an attacker wrote by hand. A keyed worker that honoured that would\n // redeem forged work without ever opening an envelope. The WORKER'S OWN KEY\n // STATE decides, never the token.\n if (signingKey && !sealed) {\n throw new SplitTokenError(\n SPLIT_TOKEN_INVALID,\n \"split token is unsealed but this worker holds a signing key; refusing. An unsealed \" +\n \"token cannot be authenticated, so accepting one here would let any caller forge a \" +\n \"split (alg:none).\",\n );\n }\n if (!signingKey && sealed) {\n throw new SplitTokenError(\n SPLIT_TOKEN_INVALID,\n \"split token is sealed but this worker holds no signing key; cannot open it\",\n );\n }\n\n const endOfAnchor = HEADER_LEN + anchorLen;\n if (token.length < endOfAnchor) {\n throw new SplitTokenError(\n SPLIT_TOKEN_INVALID,\n `split token truncated: anchor_len=${anchorLen} exceeds token length ${token.length}`,\n );\n }\n\n const fingerprint = token.subarray(4, HEADER_LEN);\n const anchor = token.subarray(HEADER_LEN, endOfAnchor);\n const body = token.subarray(0, endOfAnchor);\n const rest = token.subarray(endOfAnchor);\n\n if (expectedFingerprint && !equalBytes(fingerprint, expectedFingerprint)) {\n throw new SplitTokenError(\n SPLIT_TOKEN_INVALID,\n \"split token was minted for a different bind (fingerprint mismatch)\",\n );\n }\n // Anchor check AFTER the bind check, and as its own kind: \"read version N\" is\n // a different situation from \"this token is not yours\".\n if (currentAnchor && !equalBytes(anchor, currentAnchor)) {\n throw new SplitTokenError(SPLIT_SNAPSHOT_EXPIRED, \"split snapshot expired; re-run the query\");\n }\n\n if (!sealed) return new Uint8Array(rest);\n try {\n return await openBytes(\n rest,\n signingKey as Uint8Array,\n splitTokenAad(body, auth),\n SEAL_VERSION,\n \"split token\",\n );\n } catch (err) {\n throw new SplitTokenError(\n SPLIT_TOKEN_INVALID,\n `split token failed authentication: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n",
|
|
46
|
-
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Handlers for the per-function lifecycle: bind, init (exchange), cardinality,\n// statistics. Generic over scalar/table/table-in-out — each function kind\n// implements VgiFunction.bind/globalInit/createStreamHandlers.\n\nimport { type VgiSchema, schema, type VgiField, field, type VgiDataType, binary, int64 } from \"../../arrow/index.js\";\nimport { Protocol, type AuthContext } from \"@query-farm/vgi-rpc\";\nimport type { FunctionRegistry } from \"../../functions/registry.js\";\nimport type { StreamHandlers, HandlerState } from \"../../functions/types.js\";\nimport {\n deserializeBindRequest,\n serializeBindResponse,\n deserializeInitRequest,\n serializeGlobalInitResponse,\n deserializeCardinalityRequest,\n serializeTableCardinality,\n} from \"../serialize.js\";\nimport type { GlobalInitResponse } from \"../types.js\";\nimport { batchToScalarDict, deserializeBatch, adoptArrowJsShape } from \"../../util/arrow/index.js\";\nimport { toUint8Array } from \"../../util/bytes.js\";\nimport { serializeColumnStatistics } from \"../../util/statistics.js\";\nimport {\n BindParamsSchema,\n BindResultSchema,\n InitParamsSchema,\n TableFunctionCardinalityParamsSchema,\n TableFunctionCardinalityResultSchema,\n TableFunctionDynamicToStringParamsSchema,\n TableFunctionDynamicToStringResultSchema,\n TableFunctionPlanParamsSchema,\n TableFunctionStatisticsParamsSchema,\n} from \"../../generated/vgi-protocol-schemas.js\";\nimport {\n REQUEST_PARAMS_SCHEMA,\n RESULT_BINARY_SCHEMA,\n RESULT_BINARY_NULLABLE_SCHEMA,\n unwrapRequest,\n wrapResult,\n overloadContext,\n recoverFinalizeState,\n} from \"./shared.js\";\nimport { GLOBAL_INIT_RESPONSE_SCHEMA } from \"../serializers/init.js\";\nimport { openAttach } from \"./catalog/shared.js\";\nimport { currentRequestAuth } from \"../../request-auth.js\";\nimport { batchFromColumns, serializeBatch } from \"../../util/arrow/index.js\";\nimport {\n deserializePlanRequest,\n fingerprintInputs,\n planResponseRow,\n scanSplitRow,\n PLAN_RESPONSE_SCHEMA,\n SCAN_SPLIT_SCHEMA,\n type PlanResult,\n} from \"../serializers/splits.js\";\nimport {\n bindFingerprint,\n buildSplitToken,\n openSplitToken,\n splitAnchor,\n} from \"../../split-token.js\";\n\nexport interface FunctionHandlerConfig {\n registry: FunctionRegistry;\n recoverExchangeState?: (opaqueData: Uint8Array) => any;\n signingKey?: Uint8Array;\n /**\n * Used to map a bind's `attach_opaque_data` to its catalog, so resolution can\n * be scoped when two catalogs declare the same schema and function name.\n * Optional — without it, resolution falls back to (schema, name).\n */\n catalogInterface?: {\n catalogNameForAttach(a: Uint8Array): string | null;\n /**\n * The catalog's current version, which is the consistency anchor every split\n * token is stamped with AND checked against.\n *\n * Both sides read it from here on purpose. Minting from a different value\n * than redemption compares against is not a subtle bug: it refuses every\n * token, and the documented response to SPLIT_SNAPSHOT_EXPIRED is \"re-run\n * the query\", which re-plans, mints the same mismatch and fails again — a\n * livelock returning no rows, blaming the data for moving when it has not.\n */\n version?(attach: Uint8Array, txn?: Uint8Array): number | Promise<number>;\n };\n}\n\n/**\n * The live anchor a split token must still name, or undefined when this worker's\n * catalog reports no version.\n *\n * Undefined means \"skip the staleness check\" rather than \"fail\" — a check that\n * cannot be made must not become a check that always fails, which would refuse\n * every split token on every unversioned catalog.\n */\nasync function liveSplitAnchor(\n catalogInterface: FunctionHandlerConfig[\"catalogInterface\"],\n bindCall: { attach_opaque_data?: Uint8Array | null; transaction_opaque_data?: Uint8Array | null },\n auth: AuthContext | undefined,\n signingKey: Uint8Array | undefined,\n): Promise<Uint8Array | undefined> {\n if (!catalogInterface?.version || bindCall.attach_opaque_data == null) return undefined;\n const raw = toUint8Array(bindCall.attach_opaque_data);\n const txn = bindCall.transaction_opaque_data\n ? toUint8Array(bindCall.transaction_opaque_data)\n : undefined;\n\n // The two call sites see the attach envelope at DIFFERENT processing stages —\n // `plan` receives it with the framework's 16-byte UUID prefix still attached,\n // `init` receives it already stripped — so neither form alone works for both.\n // Try each. Getting this wrong is not a degraded check but a total one: if\n // mint resolves a version and redemption does not (or vice versa) then every\n // token fails SPLIT_SNAPSHOT_EXPIRED, and the documented response to that is\n // \"re-run the query\", which re-plans and reproduces the same mismatch.\n // Each form is produced LAZILY, inside the try. Built as an array literal —\n // `[raw, await openAttach(...)]` — the unseal is evaluated before the loop\n // begins, so it throws from OUTSIDE the try and escapes the function instead\n // of falling through to the next candidate. `init` hands this function\n // already-stripped plaintext, which openAttach rejects, so the first form\n // never got a turn: every split scan died with OpaqueDataRejectedError, on\n // HTTP only (sealing is a pass-through when there is no signing key, which is\n // every non-HTTP transport).\n const forms: Array<() => Promise<Uint8Array>> = [\n async () => raw,\n async () => openAttach(raw, auth, signingKey),\n ];\n for (const form of forms) {\n try {\n return splitAnchor(await catalogInterface.version(await form(), txn));\n } catch {\n // try the next form\n }\n }\n // A catalog that cannot report a version means \"skip the staleness check\",\n // never \"fail it\" — a check that cannot be made must not become a check that\n // always fails, which would refuse every split token on every unversioned\n // catalog.\n return undefined;\n}\n\n/**\n * Open this request's split envelopes into `request.split_payloads`.\n *\n * `split_payloads` is DERIVED, not wire state: the tokens ride the request, the\n * payloads are what falls out of opening them. Only this layer holds the\n * signing key — a function does not — so redemption happens here and only the\n * payloads are handed down.\n *\n * It must run on continuation turns too. The HTTP exchange path rebuilds the\n * *wire* request from the cursor, which carries `split_tokens` but of course no\n * derived field, so a split-capable function used to see `splitPayloads:\n * undefined` on every turn after the first and could not tell that from \"the\n * planner gave me no splits\". Over HTTP that made every split scan fail on its\n * second turn; subprocess never noticed because it holds the handlers in memory\n * and never rebuilds anything.\n *\n * `checkAnchor` is false on a continuation, deliberately. The consistency\n * anchor answers \"is this plan still redeemable\", which is a question about\n * REDEMPTION — asked once, when the split is admitted. Re-asking it mid-stream\n * would let a catalog version bump kill an in-flight scan that had already been\n * accepted, turning a successful query into SPLIT_SNAPSHOT_EXPIRED halfway\n * through its rows.\n */\nasync function resolveSplitPayloads(\n request: any,\n innerParams: any,\n opts: {\n auth: any;\n signingKey: Uint8Array | undefined;\n catalogInterface: any;\n checkAnchor: boolean;\n },\n): Promise<void> {\n if (!request.split_tokens) return;\n const fp = fingerprintInputs(toUint8Array(innerParams.bind_call));\n const expected = await bindFingerprint(\n fp.schemaPath,\n fp.functionName,\n fp.args,\n fp.settings,\n new Uint8Array(0),\n );\n const currentAnchor = opts.checkAnchor\n ? await liveSplitAnchor(opts.catalogInterface, request.bind_call as any, opts.auth, opts.signingKey)\n : undefined;\n request.split_payloads = [];\n for (const token of request.split_tokens) {\n request.split_payloads.push(\n await openSplitToken(token, {\n signingKey: opts.signingKey,\n // Same principal `table_function_plan` sealed under. Omitting it opens\n // under the anonymous tail, so an authenticated caller's own tokens\n // fail authentication.\n auth: opts.auth,\n expectedFingerprint: expected,\n currentAnchor,\n }),\n );\n }\n}\n\nexport function registerFunctionMethods(protocol: Protocol, config: FunctionHandlerConfig): void {\n const { registry, signingKey, catalogInterface } = config;\n\n // The framework mints every attach as uuid(16) || catalog_bytes (sealed on\n // HTTP, plaintext on subprocess). Function bodies — like catalog bodies —\n // must see the catalog's own bytes, so unseal (when keyed) and strip the\n // framework UUID prefix before the user function reads attach_opaque_data.\n // `ctx` is the CallContext when the dispatcher supplies one (every unary\n // method) and absent otherwise (stream init); `currentRequestAuth()` is the\n // ambient per-request fallback the HTTP entry point publishes, so both reach\n // the same principal. Getting an authenticated caller's identity wrong here\n // is not a degraded lookup but a hard `OpaqueDataRejectedError`: the envelope\n // is sealed under `attachAad(auth)`.\n async function stripAttach(attach: any, ctx: any): Promise<Uint8Array | null> {\n if (attach == null) return null;\n const env = toUint8Array(attach);\n if (env.length === 0) return env;\n return openAttach(env, ctx?.auth ?? currentRequestAuth(), signingKey);\n }\n\n // Build an overload context whose attach has been unsealed, so catalog\n // resolution sees the real route byte. The bind/init handlers strip their\n // request in place and can call overloadContext directly; every other site\n // still holds the sealed envelope (73 bytes on HTTP vs 16 plaintext), whose\n // leading byte would otherwise route to an arbitrary catalog.\n async function strippedContext(bindCall: any, ctx?: any) {\n let attach: Uint8Array | null = null;\n try {\n attach = await stripAttach(bindCall.attach_opaque_data, ctx);\n } catch {\n attach = null; // Unopenable (wrong key / not sealed) — resolve unscoped.\n }\n return overloadContext({ ...bindCall, attach_opaque_data: attach }, catalogInterface);\n }\n\n // Shared with the serializer that actually emits the header, so the\n // advertised shape and the emitted shape cannot drift apart.\n const initHeaderSchema = GLOBAL_INIT_RESPONSE_SCHEMA;\n\n const emptySchema = schema([]);\n\n // Dummy non-empty schema for the init exchange registration.\n // The dispatch determines producer vs exchange based on inputSchema emptiness.\n // We need exchange mode so that input batches are passed to our callback.\n // The actual input schema comes from the IPC stream, not this registration.\n const dummyInputSchema = schema([\n field(\"_tick\", binary(), true),\n ]);\n\n // --------------------------------------------------------------------------\n // bind (unary)\n // --------------------------------------------------------------------------\n protocol.unary(\"bind\", {\n params: BindParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params, ctx) => {\n const innerParams = unwrapRequest(params.request);\n const request = deserializeBindRequest(innerParams);\n request.attach_opaque_data = await stripAttach(request.attach_opaque_data, ctx);\n const func = registry.get(request.function_name, overloadContext(request, catalogInterface));\n const response = await func.bind(request);\n const serialized = serializeBindResponse(response);\n return wrapResult(serialized, BindResultSchema);\n },\n });\n\n // --------------------------------------------------------------------------\n // init (streaming) - dynamically produces either producer or exchange streams\n // --------------------------------------------------------------------------\n protocol.exchange(\"init\", {\n params: InitParamsSchema,\n inputSchema: dummyInputSchema,\n outputSchema: emptySchema,\n init: async (params, ctx?: any) => {\n // Preserve raw request IPC bytes for exchange reconstruction\n const requestIpcBytes = toUint8Array(params.request);\n const innerParams = unwrapRequest(params.request);\n const request = deserializeInitRequest(innerParams);\n // The caller's identity, and the load-bearing line of this handler.\n //\n // vgi-rpc types stream init as `(params) => state`, so unlike every unary\n // method there is no CallContext to read `auth` off — `ctx` is only ever\n // populated by a caller that has one (the in-process client). The HTTP\n // entry point therefore publishes the dispatching principal on an ambient\n // per-request scope, the same shape vgi-python's `current_auth()`\n // ContextVar and vgi-go's `handleInit(callCtx)` give those ports.\n //\n // It has to be the REAL principal, not `undefined`: `attach_opaque_data`\n // is sealed by `catalog_attach` under `attachAad(auth)` and every split\n // token by `table_function_plan` under `splitTokenAad(body, auth)`, both\n // of which are unary and so seal under the authenticated caller. Opening\n // them here under the anonymous tail matches only for an anonymous\n // caller; an authenticated one got `OpaqueDataRejectedError:\n // attach_opaque_data not recognized` on its first scan, i.e. this worker\n // could not serve authenticated traffic at all.\n const auth = ctx?.auth ?? currentRequestAuth();\n request.bind_call.attach_opaque_data = await stripAttach(\n request.bind_call.attach_opaque_data,\n ctx,\n );\n\n // Verify and strip the split envelopes BEFORE any user code runs, so an\n // unverified token can never be acted on.\n await resolveSplitPayloads(request, innerParams, {\n auth,\n signingKey,\n catalogInterface,\n checkAnchor: true,\n });\n\n const func = registry.get(request.bind_call.function_name, overloadContext(request.bind_call, catalogInterface));\n\n // globalInit is async — table function onInit may touch HTTP-backed\n // FunctionStorage (e.g. Cloudflare DO).\n const initResponse = await func.globalInit(request);\n\n // For FINALIZE over HTTP, recover accumulated INPUT state from init_opaque_data.\n // The C++ extension passes the last exchange state token as init_opaque_data.\n const accumulatedState = recoverFinalizeState(request, config.recoverExchangeState);\n\n const handlers = func.createStreamHandlers(request, initResponse, accumulatedState);\n\n // Initialize the appropriate handler\n let handlerState: HandlerState | undefined;\n if (handlers.producerInit) {\n handlerState = handlers.producerInit();\n } else if (handlers.exchangeInit) {\n handlerState = handlers.exchangeInit();\n }\n\n const isProducer = !!handlers.producerFn;\n\n // Extract mutable user state from handler (e.g. { remaining, currentIndex })\n // for serialization across HTTP exchanges. The processParams/infrastructure\n // is reconstructed fresh; only user state needs to persist.\n const userState = handlerState?.state ?? null;\n\n // Build state object with raw binary data (no base64/hex encoding).\n // The Arrow state serializer picks fields by name; live objects\n // (_handlers, _handlerState, _initResponse, __outputSchema) are ignored.\n const state: any = {\n functionName: request.bind_call.function_name,\n initRequestIpc: requestIpcBytes,\n executionId: initResponse.execution_id,\n maxWorkers: Number(initResponse.max_workers),\n opaqueData: initResponse.opaque_data ?? null,\n isProducer,\n userState,\n __isProducer: isProducer,\n // Live Schemas for vgi-rpc to read during init (not serializable).\n // __inputSchema overrides dispatchStream's method.inputSchema per call\n // — the TS worker registers `init` as exchange with the permissive\n // `dummyInputSchema` sentinel; the real per-function input shape comes\n // from the bound handlers here.\n __outputSchema: handlers.outputSchema ?? emptySchema,\n __inputSchema: handlers.inputSchema ?? emptySchema,\n // Live objects for immediate use during init (producer mode).\n _handlers: handlers,\n _handlerState: handlerState,\n _initResponse: initResponse,\n };\n return state;\n },\n exchange: async (state, input, out) => {\n // `input` is the one batch worker code sees that this package did not\n // decode — vgi-rpc read it off the wire with its own Arrow backend. If\n // that resolved to a second copy of @query-farm/flechette (nested under\n // vgi-rpc whenever the version ranges disagree, even transiently), the\n // facade's prototype patches never touched its classes and user code\n // gets `col.isValid is not a function` on the first exchange round.\n // Adopting here is a WeakSet probe per call and a no-op on arrow-js.\n input = adoptArrowJsShape(input);\n // Reconstruct live objects from serializable state.\n // This handles both immediate use (producer during init, where _handlers\n // is still present) and deserialized exchange (where we reconstruct).\n let handlers: StreamHandlers;\n let handlerState: HandlerState | undefined;\n\n if (state._handlers) {\n // Immediate use (same request, state still in memory)\n handlers = state._handlers;\n handlerState = state._handlerState;\n } else {\n // Deserialized from token — reconstruct from serializable refs.\n // Infrastructure (processParams, BoundStorage) is recreated fresh.\n // Mutable user state is merged from state.userState.\n const initRequestBatch = deserializeBatch(state.initRequestIpc);\n const initRequestDict = batchToScalarDict(initRequestBatch);\n const request = deserializeInitRequest(initRequestDict);\n // Re-derive the split payloads. The cursor carries the wire request,\n // which has `split_tokens` but not the opened `split_payloads` — that\n // field only ever existed in memory on the init turn. Without this a\n // split-capable function sees `splitPayloads: undefined` from the\n // second turn onward, indistinguishable from \"the planner gave me no\n // splits at all\". checkAnchor is false: redemption was already decided\n // on the init turn, and re-checking here would let a mid-scan catalog\n // bump fail a query that had already been admitted.\n // fingerprintInputs hashes the RAW bind_call bytes, so pass the\n // pre-deserialization blob from the cursor — handing it the decoded\n // object hashes a different shape and every token fails as\n // SPLIT_TOKEN_INVALID \"minted for a different bind\".\n await resolveSplitPayloads(request, { bind_call: initRequestDict.bind_call }, {\n // Same principal the tokens were sealed under. The exchange dispatch\n // gets no ctx (see stripAttach above), so the request-scoped identity\n // is the only source — opening under the anonymous tail would fail\n // authentication for every authenticated caller's own tokens.\n auth: currentRequestAuth(),\n signingKey,\n catalogInterface,\n checkAnchor: false,\n });\n const func = registry.get(state.functionName, await strippedContext(request.bind_call));\n const executionId = state.executionId;\n const opaqueData = state.opaqueData ?? null;\n const initResponse: GlobalInitResponse = {\n execution_id: executionId,\n max_workers: Number(state.maxWorkers ?? 1),\n opaque_data: opaqueData,\n };\n\n // Recover accumulated state for FINALIZE phase from initOpaqueData\n const recoveredState = recoverFinalizeState(request, config.recoverExchangeState);\n\n handlers = func.createStreamHandlers(request, initResponse, recoveredState);\n if (handlers.producerInit) {\n handlerState = handlers.producerInit();\n } else if (handlers.exchangeInit) {\n handlerState = handlers.exchangeInit();\n }\n // Merge preserved user state (e.g. { remaining, currentIndex })\n if (state.userState != null && handlerState?.state !== undefined) {\n handlerState!.state = state.userState;\n }\n }\n\n if (state.isProducer && handlers.producerFn) {\n // Producer mode inside an exchange dispatch: patch finish() to bypass\n // OutputCollector's producerMode check (since dispatch created it\n // in exchange mode but we're actually producing).\n out.finish = () => { (out as any)._finished = true; };\n // Let the handler observe tick-batch metadata before producing. Used\n // by table functions to apply dynamic-filter updates DuckDB attaches\n // as `vgi_pushdown_filters` on each tick (Top-N heap tightening).\n if (handlers.onTick) {\n await handlers.onTick(handlerState, (input as any)?.metadata);\n }\n await handlers.producerFn(handlerState, out);\n } else if (handlers.exchangeFn) {\n await handlers.exchangeFn(handlerState, input, out);\n }\n\n // Save mutated user state for the next exchange round\n if (handlerState?.state !== undefined) {\n state.userState = handlerState!.state;\n }\n },\n headerSchema: initHeaderSchema,\n headerInit: (params: any, state: any, ctx: any) => {\n // During init, _initResponse is still in memory.\n // For exchange, this is never called (headers are only in init response).\n if (!state._initResponse) {\n throw new Error(\"headerInit called on deserialized state: _initResponse not available\");\n }\n return serializeGlobalInitResponse(state._initResponse);\n },\n });\n\n // --------------------------------------------------------------------------\n // table_function_cardinality (unary)\n // --------------------------------------------------------------------------\n protocol.unary(\"table_function_cardinality\", {\n params: TableFunctionCardinalityParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const innerParams = unwrapRequest(params.request);\n const request = deserializeCardinalityRequest(innerParams);\n const func = registry.get(request.bind_call.function_name, await strippedContext(request.bind_call));\n let cardResult: Record<string, any>;\n if (func.cardinality) {\n cardResult = serializeTableCardinality(await func.cardinality(request));\n } else {\n cardResult = { estimate: null, max: null };\n }\n return wrapResult(cardResult, TableFunctionCardinalityResultSchema);\n },\n });\n\n // --------------------------------------------------------------------------\n // table_function_plan (unary)\n // --------------------------------------------------------------------------\n // Divide a scan into named, independently redeemable splits, so a distributed\n // engine can retry a task without re-reading or skipping rows.\n //\n // A function that declares no `plan` hook gets the framework default: a SINGLE\n // empty-payload split, which is what \"not split-capable\" means — the whole scan\n // is one unit of work. That keeps every existing worker serving unchanged under\n // protocol 1.4.0, so splits stay opt-in rather than something every worker must\n // now implement.\n protocol.unary(\"table_function_plan\", {\n params: TableFunctionPlanParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params, ctx?: any) => {\n const innerParams = unwrapRequest(params.request);\n const request = deserializePlanRequest(innerParams);\n const func = registry.get(\n request.bind_call.function_name,\n await strippedContext(request.bind_call),\n );\n\n const plan: PlanResult = func.plan\n ? await func.plan(request)\n : { splits: [{ payload: new Uint8Array(0) }] };\n\n // The framework stamps every token: an author cannot forget the\n // consistency anchor, cannot mis-bind the fingerprint, and never writes\n // crypto — and the envelope stays a private implementation detail whose\n // layout can change without touching worker code in five languages.\n const fp = fingerprintInputs(toUint8Array(innerParams.bind_call));\n const fingerprint = await bindFingerprint(\n fp.schemaPath,\n fp.functionName,\n fp.args,\n fp.settings,\n // projection_ids is not a bind-call field (it rides the init request),\n // so it feeds in empty — matching the reference implementation, which\n // reads it off the bind call and likewise finds nothing.\n new Uint8Array(0),\n );\n // A worker that names its version is taken at its word — it knows which\n // snapshot it planned against. One that leaves it unset gets the LIVE\n // version, never 0: minting 0 while redemption compares against the live\n // counter refuses every token, and is invisible on a catalog whose version\n // happens to be 0, which is most fixtures.\n const anchor =\n plan.catalogVersion != null\n ? splitAnchor(plan.catalogVersion)\n : ((await liveSplitAnchor(catalogInterface, request.bind_call as any, ctx?.auth, signingKey)) ??\n splitAnchor(0));\n\n const blobs: Uint8Array[] = [];\n for (const split of plan.splits) {\n const token = await buildSplitToken({\n payload: split.payload,\n fingerprint,\n anchor,\n signingKey,\n // Bind the caller. Without it every token seals under the anonymous\n // identity, so one tenant's splits are replayable by another — the\n // exact replay the AAD exists to stop.\n auth: ctx?.auth,\n });\n blobs.push(\n serializeBatch(\n batchFromColumns(\n Object.fromEntries(\n SCAN_SPLIT_SCHEMA.fields.map((f) => [\n f.name,\n [scanSplitRow(split, token)[f.name] ?? null],\n ]),\n ),\n SCAN_SPLIT_SCHEMA,\n ),\n ),\n );\n }\n\n return wrapResult(planResponseRow(plan, blobs), PLAN_RESPONSE_SCHEMA);\n },\n });\n\n // --------------------------------------------------------------------------\n // table_function_statistics (unary)\n // --------------------------------------------------------------------------\n // Returns bytes-or-null result: serialized ColumnStatistics RecordBatch when\n // the function declared a statistics() hook and it produced a non-empty\n // list, else null. DuckDB uses the bounds for plan-time filter elimination\n // (folds impossible filters to EMPTY_RESULT).\n protocol.unary(\"table_function_statistics\", {\n params: TableFunctionStatisticsParamsSchema,\n result: RESULT_BINARY_NULLABLE_SCHEMA,\n handler: async (params) => {\n const innerParams = unwrapRequest(params.request);\n const request = deserializeCardinalityRequest(innerParams);\n const func = registry.get(request.bind_call.function_name, await strippedContext(request.bind_call));\n if (!func.statistics) return { result: null };\n const stats = func.statistics(request);\n if (!stats || stats.length === 0) return { result: null };\n return { result: serializeColumnStatistics(stats) };\n },\n });\n\n // --------------------------------------------------------------------------\n // table_function_dynamic_to_string (unary)\n // --------------------------------------------------------------------------\n // DuckDB calls this once per parallel scan thread at FinishSource. The\n // result is a List<Utf8>/List<Utf8> pair carrying ordered key→value\n // diagnostics that surface under EXPLAIN ANALYZE alongside the\n // intrinsics (Function, Rows Read, Threads). When the function doesn't\n // declare dynamicToString, return empty maps so the C++ side falls back\n // to intrinsics only.\n protocol.unary(\"table_function_dynamic_to_string\", {\n params: TableFunctionDynamicToStringParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const innerParams = unwrapRequest(params.request);\n const bindCallBytes = toUint8Array(innerParams.bind_call);\n const bindCallBatch = deserializeBatch(bindCallBytes);\n // Single-row bind_call batch -> dict via the codec/canonical path.\n const bindParams = batchToScalarDict(bindCallBatch);\n const bindCall = deserializeBindRequest(bindParams);\n const globalExecutionId = toUint8Array(innerParams.global_execution_id);\n const bindOpaqueData = innerParams.bind_opaque_data\n ? toUint8Array(innerParams.bind_opaque_data)\n : null;\n const func = registry.get(bindCall.function_name, await strippedContext(bindCall));\n const map = func.dynamicToString\n ? await func.dynamicToString({ bindCall, bindOpaqueData, globalExecutionId })\n : {};\n const keys = Object.keys(map);\n const values = keys.map((k) => map[k] ?? \"\");\n return wrapResult({ keys, values }, TableFunctionDynamicToStringResultSchema);\n },\n });\n}\n",
|
|
49
|
+
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Handlers for the per-function lifecycle: bind, init (exchange), cardinality,\n// statistics. Generic over scalar/table/table-in-out — each function kind\n// implements VgiFunction.bind/globalInit/createStreamHandlers.\n\nimport { type VgiSchema, schema, type VgiField, field, type VgiDataType, binary, int64 } from \"../../arrow/index.js\";\nimport { Protocol, type AuthContext } from \"@query-farm/vgi-rpc\";\nimport type { FunctionRegistry } from \"../../functions/registry.js\";\nimport type { StreamHandlers, HandlerState } from \"../../functions/types.js\";\nimport {\n deserializeBindRequest,\n serializeBindResponse,\n deserializeInitRequest,\n serializeGlobalInitResponse,\n deserializeCardinalityRequest,\n serializeTableCardinality,\n} from \"../serialize.js\";\nimport type { GlobalInitResponse } from \"../types.js\";\nimport { batchToScalarDict, deserializeBatch, adoptArrowJsShape } from \"../../util/arrow/index.js\";\nimport { toUint8Array } from \"../../util/bytes.js\";\nimport { serializeColumnStatistics } from \"../../util/statistics.js\";\nimport {\n BindParamsSchema,\n BindResultSchema,\n InitParamsSchema,\n TableFunctionCardinalityParamsSchema,\n TableFunctionCardinalityResultSchema,\n TableFunctionDynamicToStringParamsSchema,\n TableFunctionDynamicToStringResultSchema,\n TableFunctionPlanParamsSchema,\n TableFunctionStatisticsParamsSchema,\n} from \"../../generated/vgi-protocol-schemas.js\";\nimport {\n REQUEST_PARAMS_SCHEMA,\n RESULT_BINARY_SCHEMA,\n RESULT_BINARY_NULLABLE_SCHEMA,\n unwrapRequest,\n wrapResult,\n overloadContext,\n} from \"./shared.js\";\nimport { GLOBAL_INIT_RESPONSE_SCHEMA } from \"../serializers/init.js\";\nimport { parseCarriedInitRequest } from \"../carried-init-request.js\";\nimport { openAttach } from \"./catalog/shared.js\";\nimport { currentRequestAuth } from \"../../request-auth.js\";\nimport { batchFromColumns, serializeBatch } from \"../../util/arrow/index.js\";\nimport {\n deserializePlanRequest,\n fingerprintInputs,\n planResponseRow,\n scanSplitRow,\n PLAN_RESPONSE_SCHEMA,\n SCAN_SPLIT_SCHEMA,\n type PlanResult,\n} from \"../serializers/splits.js\";\nimport {\n bindFingerprint,\n buildSplitToken,\n openSplitToken,\n splitAnchor,\n} from \"../../split-token.js\";\n\nexport interface FunctionHandlerConfig {\n registry: FunctionRegistry;\n signingKey?: Uint8Array;\n /**\n * Used to map a bind's `attach_opaque_data` to its catalog, so resolution can\n * be scoped when two catalogs declare the same schema and function name.\n * Optional — without it, resolution falls back to (schema, name).\n */\n catalogInterface?: {\n catalogNameForAttach(a: Uint8Array): string | null;\n /**\n * The catalog's current version, which is the consistency anchor every split\n * token is stamped with AND checked against.\n *\n * Both sides read it from here on purpose. Minting from a different value\n * than redemption compares against is not a subtle bug: it refuses every\n * token, and the documented response to SPLIT_SNAPSHOT_EXPIRED is \"re-run\n * the query\", which re-plans, mints the same mismatch and fails again — a\n * livelock returning no rows, blaming the data for moving when it has not.\n */\n version?(attach: Uint8Array, txn?: Uint8Array): number | Promise<number>;\n };\n}\n\n/**\n * The live anchor a split token must still name, or undefined when this worker's\n * catalog reports no version.\n *\n * Undefined means \"skip the staleness check\" rather than \"fail\" — a check that\n * cannot be made must not become a check that always fails, which would refuse\n * every split token on every unversioned catalog.\n */\nasync function liveSplitAnchor(\n catalogInterface: FunctionHandlerConfig[\"catalogInterface\"],\n bindCall: { attach_opaque_data?: Uint8Array | null; transaction_opaque_data?: Uint8Array | null },\n auth: AuthContext | undefined,\n signingKey: Uint8Array | undefined,\n): Promise<Uint8Array | undefined> {\n if (!catalogInterface?.version || bindCall.attach_opaque_data == null) return undefined;\n const raw = toUint8Array(bindCall.attach_opaque_data);\n const txn = bindCall.transaction_opaque_data\n ? toUint8Array(bindCall.transaction_opaque_data)\n : undefined;\n\n // The two call sites see the attach envelope at DIFFERENT processing stages —\n // `plan` receives it with the framework's 16-byte UUID prefix still attached,\n // `init` receives it already stripped — so neither form alone works for both.\n // Try each. Getting this wrong is not a degraded check but a total one: if\n // mint resolves a version and redemption does not (or vice versa) then every\n // token fails SPLIT_SNAPSHOT_EXPIRED, and the documented response to that is\n // \"re-run the query\", which re-plans and reproduces the same mismatch.\n // Each form is produced LAZILY, inside the try. Built as an array literal —\n // `[raw, await openAttach(...)]` — the unseal is evaluated before the loop\n // begins, so it throws from OUTSIDE the try and escapes the function instead\n // of falling through to the next candidate. `init` hands this function\n // already-stripped plaintext, which openAttach rejects, so the first form\n // never got a turn: every split scan died with OpaqueDataRejectedError, on\n // HTTP only (sealing is a pass-through when there is no signing key, which is\n // every non-HTTP transport).\n const forms: Array<() => Promise<Uint8Array>> = [\n async () => raw,\n async () => openAttach(raw, auth, signingKey),\n ];\n for (const form of forms) {\n try {\n return splitAnchor(await catalogInterface.version(await form(), txn));\n } catch {\n // try the next form\n }\n }\n // A catalog that cannot report a version means \"skip the staleness check\",\n // never \"fail it\" — a check that cannot be made must not become a check that\n // always fails, which would refuse every split token on every unversioned\n // catalog.\n return undefined;\n}\n\n/**\n * Open this request's split envelopes into `request.split_payloads`.\n *\n * `split_payloads` is DERIVED, not wire state: the tokens ride the request, the\n * payloads are what falls out of opening them. Only this layer holds the\n * signing key — a function does not — so redemption happens here and only the\n * payloads are handed down.\n *\n * It must run on continuation turns too. The HTTP exchange path rebuilds the\n * *wire* request from the cursor, which carries `split_tokens` but of course no\n * derived field, so a split-capable function used to see `splitPayloads:\n * undefined` on every turn after the first and could not tell that from \"the\n * planner gave me no splits\". Over HTTP that made every split scan fail on its\n * second turn; subprocess never noticed because it holds the handlers in memory\n * and never rebuilds anything.\n *\n * `checkAnchor` is false on a continuation, deliberately. The consistency\n * anchor answers \"is this plan still redeemable\", which is a question about\n * REDEMPTION — asked once, when the split is admitted. Re-asking it mid-stream\n * would let a catalog version bump kill an in-flight scan that had already been\n * accepted, turning a successful query into SPLIT_SNAPSHOT_EXPIRED halfway\n * through its rows.\n */\nasync function resolveSplitPayloads(\n request: any,\n innerParams: any,\n opts: {\n auth: any;\n signingKey: Uint8Array | undefined;\n catalogInterface: any;\n checkAnchor: boolean;\n },\n): Promise<void> {\n if (!request.split_tokens) return;\n const fp = fingerprintInputs(toUint8Array(innerParams.bind_call));\n const expected = await bindFingerprint(\n fp.schemaPath,\n fp.functionName,\n fp.args,\n fp.settings,\n new Uint8Array(0),\n );\n const currentAnchor = opts.checkAnchor\n ? await liveSplitAnchor(opts.catalogInterface, request.bind_call as any, opts.auth, opts.signingKey)\n : undefined;\n request.split_payloads = [];\n for (const token of request.split_tokens) {\n request.split_payloads.push(\n await openSplitToken(token, {\n signingKey: opts.signingKey,\n // Same principal `table_function_plan` sealed under. Omitting it opens\n // under the anonymous tail, so an authenticated caller's own tokens\n // fail authentication.\n auth: opts.auth,\n expectedFingerprint: expected,\n currentAnchor,\n }),\n );\n }\n}\n\nexport function registerFunctionMethods(protocol: Protocol, config: FunctionHandlerConfig): void {\n const { registry, signingKey, catalogInterface } = config;\n\n // The framework mints every attach as uuid(16) || catalog_bytes (sealed on\n // HTTP, plaintext on subprocess). Function bodies — like catalog bodies —\n // must see the catalog's own bytes, so unseal (when keyed) and strip the\n // framework UUID prefix before the user function reads attach_opaque_data.\n // `ctx` is the CallContext when the dispatcher supplies one (every unary\n // method) and absent otherwise (stream init); `currentRequestAuth()` is the\n // ambient per-request fallback the HTTP entry point publishes, so both reach\n // the same principal. Getting an authenticated caller's identity wrong here\n // is not a degraded lookup but a hard `OpaqueDataRejectedError`: the envelope\n // is sealed under `attachAad(auth)`.\n async function stripAttach(attach: any, ctx: any): Promise<Uint8Array | null> {\n if (attach == null) return null;\n const env = toUint8Array(attach);\n if (env.length === 0) return env;\n return openAttach(env, ctx?.auth ?? currentRequestAuth(), signingKey);\n }\n\n // Build an overload context whose attach has been unsealed, so catalog\n // resolution sees the real route byte. The bind/init handlers strip their\n // request in place and can call overloadContext directly; every other site\n // still holds the sealed envelope (73 bytes on HTTP vs 16 plaintext), whose\n // leading byte would otherwise route to an arbitrary catalog.\n async function strippedContext(bindCall: any, ctx?: any) {\n let attach: Uint8Array | null = null;\n try {\n attach = await stripAttach(bindCall.attach_opaque_data, ctx);\n } catch {\n attach = null; // Unopenable (wrong key / not sealed) — resolve unscoped.\n }\n return overloadContext({ ...bindCall, attach_opaque_data: attach }, catalogInterface);\n }\n\n // Shared with the serializer that actually emits the header, so the\n // advertised shape and the emitted shape cannot drift apart.\n const initHeaderSchema = GLOBAL_INIT_RESPONSE_SCHEMA;\n\n const emptySchema = schema([]);\n\n // Dummy non-empty schema for the init exchange registration.\n // The dispatch determines producer vs exchange based on inputSchema emptiness.\n // We need exchange mode so that input batches are passed to our callback.\n // The actual input schema comes from the IPC stream, not this registration.\n const dummyInputSchema = schema([\n field(\"_tick\", binary(), true),\n ]);\n\n // --------------------------------------------------------------------------\n // bind (unary)\n // --------------------------------------------------------------------------\n protocol.unary(\"bind\", {\n params: BindParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params, ctx) => {\n const innerParams = unwrapRequest(params.request);\n const request = deserializeBindRequest(innerParams);\n request.attach_opaque_data = await stripAttach(request.attach_opaque_data, ctx);\n const func = registry.get(request.function_name, overloadContext(request, catalogInterface));\n const response = await func.bind(request);\n const serialized = serializeBindResponse(response);\n return wrapResult(serialized, BindResultSchema);\n },\n });\n\n // --------------------------------------------------------------------------\n // init (streaming) - dynamically produces either producer or exchange streams\n // --------------------------------------------------------------------------\n protocol.exchange(\"init\", {\n params: InitParamsSchema,\n inputSchema: dummyInputSchema,\n outputSchema: emptySchema,\n init: async (params, ctx?: any) => {\n // Preserve raw request IPC bytes for exchange reconstruction\n const requestIpcBytes = toUint8Array(params.request);\n const innerParams = unwrapRequest(params.request);\n const request = deserializeInitRequest(innerParams);\n // The caller's identity, and the load-bearing line of this handler.\n //\n // vgi-rpc types stream init as `(params) => state`, so unlike every unary\n // method there is no CallContext to read `auth` off — `ctx` is only ever\n // populated by a caller that has one (the in-process client). The HTTP\n // entry point therefore publishes the dispatching principal on an ambient\n // per-request scope, the same shape vgi-python's `current_auth()`\n // ContextVar and vgi-go's `handleInit(callCtx)` give those ports.\n //\n // It has to be the REAL principal, not `undefined`: `attach_opaque_data`\n // is sealed by `catalog_attach` under `attachAad(auth)` and every split\n // token by `table_function_plan` under `splitTokenAad(body, auth)`, both\n // of which are unary and so seal under the authenticated caller. Opening\n // them here under the anonymous tail matches only for an anonymous\n // caller; an authenticated one got `OpaqueDataRejectedError:\n // attach_opaque_data not recognized` on its first scan, i.e. this worker\n // could not serve authenticated traffic at all.\n const auth = ctx?.auth ?? currentRequestAuth();\n request.bind_call.attach_opaque_data = await stripAttach(\n request.bind_call.attach_opaque_data,\n ctx,\n );\n\n // Verify and strip the split envelopes BEFORE any user code runs, so an\n // unverified token can never be acted on.\n await resolveSplitPayloads(request, innerParams, {\n auth,\n signingKey,\n catalogInterface,\n checkAnchor: true,\n });\n\n const func = registry.get(request.bind_call.function_name, overloadContext(request.bind_call, catalogInterface));\n\n // globalInit is async — table function onInit may touch HTTP-backed\n // FunctionStorage (e.g. Cloudflare DO).\n const initResponse = await func.globalInit(request);\n\n // A FINALIZE stream reads its accumulated states from storage, where\n // every INPUT turn persisted them. Its `init_opaque_data` is the primary\n // init's opaque data echoed back (vgi-python's InitRequest), never a\n // cursor, so nothing here opens it.\n const handlers = func.createStreamHandlers(request, initResponse);\n\n // Initialize the appropriate handler\n let handlerState: HandlerState | undefined;\n if (handlers.producerInit) {\n handlerState = handlers.producerInit();\n } else if (handlers.exchangeInit) {\n handlerState = handlers.exchangeInit();\n }\n\n const isProducer = !!handlers.producerFn;\n\n // Extract mutable user state from handler (e.g. { remaining, currentIndex })\n // for serialization across HTTP exchanges. The processParams/infrastructure\n // is reconstructed fresh; only user state needs to persist.\n const userState = handlerState?.state ?? null;\n\n // Build state object with raw binary data (no base64/hex encoding).\n // The Arrow state serializer picks fields by name; live objects\n // (_handlers, _handlerState, _initResponse, __outputSchema) are ignored.\n const state: any = {\n functionName: request.bind_call.function_name,\n initRequestIpc: requestIpcBytes,\n executionId: initResponse.execution_id,\n maxWorkers: Number(initResponse.max_workers),\n opaqueData: initResponse.opaque_data ?? null,\n isProducer,\n userState,\n __isProducer: isProducer,\n // Live Schemas for vgi-rpc to read during init (not serializable).\n // __inputSchema overrides dispatchStream's method.inputSchema per call\n // — the TS worker registers `init` as exchange with the permissive\n // `dummyInputSchema` sentinel; the real per-function input shape comes\n // from the bound handlers here.\n __outputSchema: handlers.outputSchema ?? emptySchema,\n __inputSchema: handlers.inputSchema ?? emptySchema,\n // Live objects for immediate use during init (producer mode).\n _handlers: handlers,\n _handlerState: handlerState,\n _initResponse: initResponse,\n };\n return state;\n },\n exchange: async (state, input, out) => {\n // `input` is the one batch worker code sees that this package did not\n // decode — vgi-rpc read it off the wire with its own Arrow backend. If\n // that resolved to a second copy of @query-farm/flechette (nested under\n // vgi-rpc whenever the version ranges disagree, even transiently), the\n // facade's prototype patches never touched its classes and user code\n // gets `col.isValid is not a function` on the first exchange round.\n // Adopting here is a WeakSet probe per call and a no-op on arrow-js.\n input = adoptArrowJsShape(input);\n // Reconstruct live objects from serializable state.\n // This handles both immediate use (producer during init, where _handlers\n // is still present) and deserialized exchange (where we reconstruct).\n let handlers: StreamHandlers;\n let handlerState: HandlerState | undefined;\n\n if (state._handlers) {\n // Immediate use (same request, state still in memory)\n handlers = state._handlers;\n handlerState = state._handlerState;\n } else {\n // Deserialized from token — reconstruct from serializable refs.\n // Infrastructure (processParams, BoundStorage) is recreated fresh.\n // Mutable user state is merged from state.userState.\n // Parsed once per process per stream (carried-init-request.ts): the\n // cursor carries the packed request unchanged on every turn.\n const carried = parseCarriedInitRequest(state.initRequestPacked);\n const request = carried.request;\n // Re-derive the split payloads. The cursor carries the wire request,\n // which has `split_tokens` but not the opened `split_payloads` — that\n // field only ever existed in memory on the init turn. Without this a\n // split-capable function sees `splitPayloads: undefined` from the\n // second turn onward, indistinguishable from \"the planner gave me no\n // splits at all\". checkAnchor is false: redemption was already decided\n // on the init turn, and re-checking here would let a mid-scan catalog\n // bump fail a query that had already been admitted.\n // fingerprintInputs hashes the RAW bind_call bytes, so pass the\n // pre-deserialization blob from the cursor — handing it the decoded\n // object hashes a different shape and every token fails as\n // SPLIT_TOKEN_INVALID \"minted for a different bind\".\n await resolveSplitPayloads(request, { bind_call: carried.bindCallIpc }, {\n // Same principal the tokens were sealed under. The exchange dispatch\n // gets no ctx (see stripAttach above), so the request-scoped identity\n // is the only source — opening under the anonymous tail would fail\n // authentication for every authenticated caller's own tokens.\n auth: currentRequestAuth(),\n signingKey,\n catalogInterface,\n checkAnchor: false,\n });\n const func = registry.get(state.functionName, await strippedContext(request.bind_call));\n const executionId = state.executionId;\n const opaqueData = state.opaqueData ?? null;\n const initResponse: GlobalInitResponse = {\n execution_id: executionId,\n max_workers: Number(state.maxWorkers ?? 1),\n opaque_data: opaqueData,\n };\n\n // The cursor's compacted dynamic-filter history: without it every turn\n // after the one that received a delta would scan under the init\n // snapshot again, because the extension sends each delta only once.\n handlers = func.createStreamHandlers(request, initResponse, state.filterHistory ?? null);\n if (handlers.producerInit) {\n handlerState = handlers.producerInit();\n } else if (handlers.exchangeInit) {\n handlerState = handlers.exchangeInit();\n }\n // Merge preserved user state (e.g. { remaining, currentIndex })\n if (state.userState != null && handlerState?.state !== undefined) {\n handlerState!.state = state.userState;\n }\n }\n\n if (state.isProducer && handlers.producerFn) {\n // Producer mode inside an exchange dispatch: patch finish() to bypass\n // OutputCollector's producerMode check (since dispatch created it\n // in exchange mode but we're actually producing).\n out.finish = () => { (out as any)._finished = true; };\n // Let the handler observe tick-batch metadata before producing. Used\n // by table functions to apply dynamic-filter updates DuckDB attaches\n // as `vgi_pushdown_filters` on each tick (Top-N heap tightening).\n if (handlers.onTick) {\n await handlers.onTick(handlerState, (input as any)?.metadata);\n }\n await handlers.producerFn(handlerState, out);\n } else if (handlers.exchangeFn) {\n await handlers.exchangeFn(handlerState, input, out);\n }\n\n // Save mutated user state for the next exchange round\n if (handlerState?.state !== undefined) {\n state.userState = handlerState!.state;\n }\n // And the dynamic-filter history this turn left (compacted: bounded by\n // the number of predicate ids, not the number of turns).\n state.filterHistory = handlerState?.filterHistory ?? null;\n },\n headerSchema: initHeaderSchema,\n headerInit: (params: any, state: any, ctx: any) => {\n // During init, _initResponse is still in memory.\n // For exchange, this is never called (headers are only in init response).\n if (!state._initResponse) {\n throw new Error(\"headerInit called on deserialized state: _initResponse not available\");\n }\n return serializeGlobalInitResponse(state._initResponse);\n },\n });\n\n // --------------------------------------------------------------------------\n // table_function_cardinality (unary)\n // --------------------------------------------------------------------------\n protocol.unary(\"table_function_cardinality\", {\n params: TableFunctionCardinalityParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const innerParams = unwrapRequest(params.request);\n const request = deserializeCardinalityRequest(innerParams);\n const func = registry.get(request.bind_call.function_name, await strippedContext(request.bind_call));\n let cardResult: Record<string, any>;\n if (func.cardinality) {\n cardResult = serializeTableCardinality(await func.cardinality(request));\n } else {\n cardResult = { estimate: null, max: null };\n }\n return wrapResult(cardResult, TableFunctionCardinalityResultSchema);\n },\n });\n\n // --------------------------------------------------------------------------\n // table_function_plan (unary)\n // --------------------------------------------------------------------------\n // Divide a scan into named, independently redeemable splits, so a distributed\n // engine can retry a task without re-reading or skipping rows.\n //\n // A function that declares no `plan` hook gets the framework default: a SINGLE\n // empty-payload split, which is what \"not split-capable\" means — the whole scan\n // is one unit of work. That keeps every existing worker serving unchanged under\n // protocol 1.4.0, so splits stay opt-in rather than something every worker must\n // now implement.\n protocol.unary(\"table_function_plan\", {\n params: TableFunctionPlanParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params, ctx?: any) => {\n const innerParams = unwrapRequest(params.request);\n const request = deserializePlanRequest(innerParams);\n const func = registry.get(\n request.bind_call.function_name,\n await strippedContext(request.bind_call),\n );\n\n const plan: PlanResult = func.plan\n ? await func.plan(request)\n : { splits: [{ payload: new Uint8Array(0) }] };\n\n // The framework stamps every token: an author cannot forget the\n // consistency anchor, cannot mis-bind the fingerprint, and never writes\n // crypto — and the envelope stays a private implementation detail whose\n // layout can change without touching worker code in five languages.\n const fp = fingerprintInputs(toUint8Array(innerParams.bind_call));\n const fingerprint = await bindFingerprint(\n fp.schemaPath,\n fp.functionName,\n fp.args,\n fp.settings,\n // projection_ids is not a bind-call field (it rides the init request),\n // so it feeds in empty — matching the reference implementation, which\n // reads it off the bind call and likewise finds nothing.\n new Uint8Array(0),\n );\n // A worker that names its version is taken at its word — it knows which\n // snapshot it planned against. One that leaves it unset gets the LIVE\n // version, never 0: minting 0 while redemption compares against the live\n // counter refuses every token, and is invisible on a catalog whose version\n // happens to be 0, which is most fixtures.\n const anchor =\n plan.catalogVersion != null\n ? splitAnchor(plan.catalogVersion)\n : ((await liveSplitAnchor(catalogInterface, request.bind_call as any, ctx?.auth, signingKey)) ??\n splitAnchor(0));\n\n const blobs: Uint8Array[] = [];\n for (const split of plan.splits) {\n const token = await buildSplitToken({\n payload: split.payload,\n fingerprint,\n anchor,\n signingKey,\n // Bind the caller. Without it every token seals under the anonymous\n // identity, so one tenant's splits are replayable by another — the\n // exact replay the AAD exists to stop.\n auth: ctx?.auth,\n });\n blobs.push(\n serializeBatch(\n batchFromColumns(\n Object.fromEntries(\n SCAN_SPLIT_SCHEMA.fields.map((f) => [\n f.name,\n [scanSplitRow(split, token)[f.name] ?? null],\n ]),\n ),\n SCAN_SPLIT_SCHEMA,\n ),\n ),\n );\n }\n\n return wrapResult(planResponseRow(plan, blobs), PLAN_RESPONSE_SCHEMA);\n },\n });\n\n // --------------------------------------------------------------------------\n // table_function_statistics (unary)\n // --------------------------------------------------------------------------\n // Returns bytes-or-null result: serialized ColumnStatistics RecordBatch when\n // the function declared a statistics() hook and it produced a non-empty\n // list, else null. DuckDB uses the bounds for plan-time filter elimination\n // (folds impossible filters to EMPTY_RESULT).\n protocol.unary(\"table_function_statistics\", {\n params: TableFunctionStatisticsParamsSchema,\n result: RESULT_BINARY_NULLABLE_SCHEMA,\n handler: async (params) => {\n const innerParams = unwrapRequest(params.request);\n const request = deserializeCardinalityRequest(innerParams);\n const func = registry.get(request.bind_call.function_name, await strippedContext(request.bind_call));\n if (!func.statistics) return { result: null };\n const stats = func.statistics(request);\n if (!stats || stats.length === 0) return { result: null };\n return { result: serializeColumnStatistics(stats) };\n },\n });\n\n // --------------------------------------------------------------------------\n // table_function_dynamic_to_string (unary)\n // --------------------------------------------------------------------------\n // DuckDB calls this once per parallel scan thread at FinishSource. The\n // result is a List<Utf8>/List<Utf8> pair carrying ordered key→value\n // diagnostics that surface under EXPLAIN ANALYZE alongside the\n // intrinsics (Function, Rows Read, Threads). When the function doesn't\n // declare dynamicToString, return empty maps so the C++ side falls back\n // to intrinsics only.\n protocol.unary(\"table_function_dynamic_to_string\", {\n params: TableFunctionDynamicToStringParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const innerParams = unwrapRequest(params.request);\n const bindCallBytes = toUint8Array(innerParams.bind_call);\n const bindCallBatch = deserializeBatch(bindCallBytes);\n // Single-row bind_call batch -> dict via the codec/canonical path.\n const bindParams = batchToScalarDict(bindCallBatch);\n const bindCall = deserializeBindRequest(bindParams);\n const globalExecutionId = toUint8Array(innerParams.global_execution_id);\n const bindOpaqueData = innerParams.bind_opaque_data\n ? toUint8Array(innerParams.bind_opaque_data)\n : null;\n const func = registry.get(bindCall.function_name, await strippedContext(bindCall));\n const map = func.dynamicToString\n ? await func.dynamicToString({ bindCall, bindOpaqueData, globalExecutionId })\n : {};\n const keys = Object.keys(map);\n const values = keys.map((k) => map[k] ?? \"\");\n return wrapResult({ keys, values }, TableFunctionDynamicToStringResultSchema);\n },\n });\n}\n",
|
|
47
50
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// ArgumentSpec: converts function argument definitions to Arrow schema with VGI metadata keys.\n// Must produce byte-identical schemas to Python's argument_specs_to_schema().\n\nimport { type VgiSchema, schema as schema_, type VgiField, field as field_, type VgiDataType, nullType, deserializeBatch } from \"../arrow/index.js\";\nimport {\n VGI_ARG_KEY,\n VGI_ARG_NAMED,\n VGI_TYPE_KEY,\n VGI_TYPE_TABLE,\n VGI_TYPE_ANY,\n VGI_VARARGS_KEY,\n VGI_VARARGS_TRUE,\n VGI_CONST_KEY,\n VGI_CONST_TRUE,\n VGI_DOC_KEY,\n VGI_DEFAULT_KEY,\n VGI_CHOICES_KEY,\n VGI_RANGE_KEY,\n VGI_PATTERN_KEY,\n} from \"../types.js\";\nimport { ArgumentValidationError } from \"../errors.js\";\n\nexport interface ArgumentSpec {\n name: string;\n position: number | string;\n arrowType: VgiDataType;\n isTableInput?: boolean;\n isAnyType?: boolean;\n isVarargs?: boolean;\n isConst?: boolean;\n doc?: string;\n /**\n * Discovery-facing constraint metadata, pre-encoded to their surfaced UTF-8\n * forms (presence-only — `undefined` means the constraint is absent and the\n * corresponding field-metadata key is omitted entirely). Mirrors Python's\n * `ArgumentSpec.default_json` / `choices_json` / `range_notation` / `pattern`\n * so `argumentSpecsToSchema`/`schemaToArgumentSpecs` round-trip symmetrically.\n */\n defaultJson?: string;\n choicesJson?: string;\n rangeNotation?: string;\n pattern?: string;\n}\n\n/**\n * Raw per-argument constraint declarations, as authored on a function's\n * argument descriptor. Encoded into the pre-computed {@link ArgumentSpec}\n * constraint fields via {@link constraintSpecFields}.\n */\nexport interface ArgumentConstraints {\n /** Closed set of allowed values (JSON-encoded into `vgi_choices`). */\n choices?: readonly unknown[];\n /** Inclusive lower bound (`>=`). */\n ge?: number;\n /** Inclusive upper bound (`<=`). */\n le?: number;\n /** Exclusive lower bound (`>`). */\n gt?: number;\n /** Exclusive upper bound (`<`). */\n lt?: number;\n /** Regex the value must match (surfaced as `vgi_pattern`, as-is). */\n pattern?: string;\n /** Default value (JSON-encoded into `vgi_default`); optional args only. */\n default?: unknown;\n}\n\n/** `JSON.stringify`, falling back to the value's string form when unserializable. */\nfunction safeJson(value: unknown): string {\n try {\n const encoded = JSON.stringify(value);\n // JSON.stringify returns undefined for functions/symbols/undefined.\n if (encoded === undefined) {\n return JSON.stringify(String(value));\n }\n return encoded;\n } catch {\n return JSON.stringify(String(value));\n }\n}\n\n/**\n * Build interval notation from an argument's numeric bounds.\n *\n * Inclusive bounds (`ge`/`le`) render as square brackets, exclusive bounds\n * (`gt`/`lt`) as parentheses, and an open side as `-inf`/`+inf`. Returns\n * `undefined` when the argument has no numeric bound at all.\n *\n * Examples: `ge=0,le=10` -> `\"[0, 10]\"`; `gt=0` -> `\"(0, +inf)\"`;\n * `ge=1,lt=10` -> `\"[1, 10)\"`.\n */\nexport function formatRange(\n ge?: number,\n le?: number,\n gt?: number,\n lt?: number,\n): string | undefined {\n if (ge === undefined && le === undefined && gt === undefined && lt === undefined) {\n return undefined;\n }\n let low: string;\n if (gt !== undefined) {\n low = `(${gt}`;\n } else if (ge !== undefined) {\n low = `[${ge}`;\n } else {\n low = \"(-inf\";\n }\n let high: string;\n if (lt !== undefined) {\n high = `${lt})`;\n } else if (le !== undefined) {\n high = `${le}]`;\n } else {\n high = \"+inf)\";\n }\n return `${low}, ${high}`;\n}\n\n/**\n * Encode raw {@link ArgumentConstraints} into the pre-computed constraint\n * fields of an {@link ArgumentSpec} (presence-only — absent constraints yield\n * no field). `runtimeDefault`, when present, is authoritative for\n * `defaultJson`, keeping runtime binding and discovery metadata in sync.\n * Mirrors Python's `_constraint_kwargs`.\n */\nexport function constraintSpecFields(\n constraints: ArgumentConstraints | undefined,\n runtimeDefault?: unknown,\n): Pick<ArgumentSpec, \"defaultJson\" | \"choicesJson\" | \"rangeNotation\" | \"pattern\"> {\n const fields: Pick<\n ArgumentSpec,\n \"defaultJson\" | \"choicesJson\" | \"rangeNotation\" | \"pattern\"\n > = {};\n // argDefaults is the runtime source of truth. Surface that same value to\n // discovery so callers do not have to duplicate it as\n // argConstraints[name].default. Keep the latter as a backwards-compatible\n // discovery-only fallback for APIs that do not have a runtime default.\n if (runtimeDefault !== undefined) {\n fields.defaultJson = safeJson(runtimeDefault);\n } else if (constraints !== undefined && \"default\" in constraints && constraints.default !== undefined) {\n fields.defaultJson = safeJson(constraints.default);\n }\n if (constraints === undefined) return fields;\n if (constraints.choices !== undefined) {\n fields.choicesJson = safeJson([...constraints.choices]);\n }\n const range = formatRange(\n constraints.ge,\n constraints.le,\n constraints.gt,\n constraints.lt,\n );\n if (range !== undefined) {\n fields.rangeNotation = range;\n }\n if (constraints.pattern !== undefined) {\n fields.pattern = constraints.pattern;\n }\n return fields;\n}\n\n/** Coerce a numeric const value (number or int64 `bigint`) to `number`. */\nfunction toNumber(value: unknown): number | undefined {\n if (typeof value === \"number\") return value;\n if (typeof value === \"bigint\") return Number(value);\n return undefined;\n}\n\n/** Equality for a choice comparison, coercing numeric/bigint operands. */\nfunction choiceEquals(choice: unknown, value: unknown): boolean {\n const cn = toNumber(choice);\n const vn = toNumber(value);\n if (cn !== undefined && vn !== undefined) return cn === vn;\n return choice === value;\n}\n\n/**\n * Narrow a bind-time argument value from Arrow's bigint to a plain number.\n *\n * DuckDB types an integer literal as BIGINT, so `series(3)` arrives as `3n`\n * whether or not anyone wanted 64 bits. Nobody writes `BigInt(1000)` for a page\n * size, so the arg paths narrow — and they now all narrow the same way, which\n * they did not before (two sites used safeNumber, two a bare Number).\n *\n * This is lossy above 2^53, and that is a deliberate call rather than an\n * oversight. Every int64 *argument* across the fixtures and every shipped\n * worker is a small control value — count, page_size, batch_size, increment,\n * lag_minutes, restatement_lookback_days. The large int64s in the test suite\n * are all somewhere else entirely:\n *\n * - column data (copy_to/types.test, copy_to/parallel.test) — never touches\n * this path;\n * - filter-pushdown constants (filter_pushdown/integers.test pins 2^53+1 on\n * purpose) — deserialize.ts keeps those bigint, with its own regression\n * test;\n * - varargs values (constant_columns) — read raw off bindCall.arguments,\n * because extractArgs' copy of them is not what the function reads;\n * - time-travel versions — carried as strings (`at_value`).\n *\n * Preserving the bigint on overflow was tried and reverted: it buys nothing for\n * any argument that exists, and costs a JS type that depends on magnitude, so a\n * worker doing `args.n + 1` would work in every test and fail on one caller's\n * input. If an argument ever genuinely needs the full range — a snowflake id, a\n * nanosecond epoch — the fix is to make int64 arguments bigint by declared\n * type, not by magnitude.\n */\nexport function narrowArgValue(value: unknown): unknown {\n return typeof value === \"bigint\" ? Number(value) : value;\n}\n\n/**\n * Reject a type *factory* where an Arrow *type* was expected.\n *\n * `params: { n: int64 }` (no parentheses) is accepted by the type system —\n * `VgiDataType` is loose enough — and then silently produces an ArgumentSpec\n * whose `arrowType` is a Function. Nothing complains until the schema is\n * serialized or the bind arrives, and the error at that point names neither the\n * argument nor the cause.\n *\n * The mistake is easy to make on purpose, too: the same identifier is a\n * ready-made type on one entry point and a factory on another.\n *\n * @query-farm/vgi int, int32, float32, bool → type instances\n * @query-farm/vgi/worker-cf int, int32, float32, bool → factories\n *\n * So moving a worker to Cloudflare can turn a correct declaration into a\n * silently wrong one with no other edit. Failing here, at definition time,\n * makes that a startup error naming the field.\n */\nexport function assertArrowType(value: unknown, where: string): void {\n if (typeof value === \"function\") {\n const name = (value as { name?: string }).name;\n const call = name ? `${name}()` : \"the factory\";\n throw new ArgumentValidationError(\n `${where} is a type factory, not an Arrow type — call it: ${call}. ` +\n `(Note that int, int32, float32 and bool are ready-made types on ` +\n `@query-farm/vgi but factories on @query-farm/vgi/worker-cf, so the ` +\n `same name may need parentheses on one entry point and not the other. ` +\n `int64(), float64(), utf8() and the rest are factories everywhere.)`,\n );\n }\n if (value === null || value === undefined) {\n throw new ArgumentValidationError(`${where} is ${String(value)}, not an Arrow type.`);\n }\n}\n\n/** {@link assertArrowType} over a record of declared types, e.g. `params`. */\nexport function assertArrowTypes(\n types: Record<string, unknown> | undefined,\n where: string,\n): void {\n if (!types) return;\n for (const [name, type] of Object.entries(types)) {\n assertArrowType(type, `${where}.${name}`);\n }\n}\n\n/**\n * Enforce a bind-time const value against its declared {@link ArgumentConstraints},\n * throwing {@link ArgumentValidationError} on violation. Mirrors the Python SDK's\n * `Arg._validate`: numeric range (`ge`/`le`/`gt`/`lt`), closed choice set, and\n * regex `pattern`. A `null`/`undefined` value skips its value constraints.\n */\nexport function validateConstConstraints(\n name: string,\n constraints: ArgumentConstraints,\n value: unknown,\n): void {\n if (value === null || value === undefined) return;\n\n const num = toNumber(value);\n if (num !== undefined) {\n if (constraints.ge !== undefined && num < constraints.ge) {\n throw new ArgumentValidationError(`argument '${name}' must be >= ${constraints.ge}`);\n }\n if (constraints.le !== undefined && num > constraints.le) {\n throw new ArgumentValidationError(`argument '${name}' must be <= ${constraints.le}`);\n }\n if (constraints.gt !== undefined && num <= constraints.gt) {\n throw new ArgumentValidationError(`argument '${name}' must be > ${constraints.gt}`);\n }\n if (constraints.lt !== undefined && num >= constraints.lt) {\n throw new ArgumentValidationError(`argument '${name}' must be < ${constraints.lt}`);\n }\n }\n\n if (constraints.choices !== undefined && constraints.choices.length > 0) {\n if (!constraints.choices.some((c) => choiceEquals(c, value))) {\n throw new ArgumentValidationError(\n `argument '${name}' must be one of ${JSON.stringify([...constraints.choices])}`,\n );\n }\n }\n\n if (constraints.pattern !== undefined && typeof value === \"string\") {\n let re: RegExp | undefined;\n try {\n re = new RegExp(constraints.pattern);\n } catch {\n re = undefined; // an invalid declared regex must not reject the caller\n }\n if (re !== undefined && !re.test(value)) {\n throw new ArgumentValidationError(\n `argument '${name}' must match pattern ${JSON.stringify(constraints.pattern)}`,\n );\n }\n }\n}\n\nfunction argumentSpecSortKey(spec: ArgumentSpec): [number, number | string] {\n if (typeof spec.position === \"number\") {\n return [0, spec.position];\n }\n return [1, spec.position];\n}\n\n/**\n * Convert ArgumentSpecs to an Arrow Schema with VGI metadata keys.\n * Positional arguments come first (in order), named arguments follow.\n */\nexport function argumentSpecsToSchema(specs: ArgumentSpec[]): VgiSchema {\n const sorted = [...specs].sort((a, b) => {\n const ka = argumentSpecSortKey(a);\n const kb = argumentSpecSortKey(b);\n if (ka[0] !== kb[0]) return ka[0] - kb[0];\n if (typeof ka[1] === \"number\" && typeof kb[1] === \"number\") {\n return ka[1] - kb[1];\n }\n return String(ka[1]).localeCompare(String(kb[1]));\n });\n\n const fields: VgiField[] = [];\n for (const spec of sorted) {\n const metadata: Map<string, string> = new Map();\n\n if (typeof spec.position === \"string\") {\n metadata.set(VGI_ARG_KEY, VGI_ARG_NAMED);\n }\n\n if (spec.isTableInput) {\n metadata.set(VGI_TYPE_KEY, VGI_TYPE_TABLE);\n } else if (spec.isAnyType) {\n metadata.set(VGI_TYPE_KEY, VGI_TYPE_ANY);\n }\n\n if (spec.isVarargs) {\n metadata.set(VGI_VARARGS_KEY, VGI_VARARGS_TRUE);\n }\n\n if (spec.isConst) {\n metadata.set(VGI_CONST_KEY, VGI_CONST_TRUE);\n }\n\n // Per-argument description (UTF-8; presence-only — omit when empty).\n if (spec.doc) {\n metadata.set(VGI_DOC_KEY, spec.doc);\n }\n\n // Per-argument constraint metadata (presence-only; already value-encoded).\n if (spec.defaultJson !== undefined) {\n metadata.set(VGI_DEFAULT_KEY, spec.defaultJson);\n }\n if (spec.choicesJson !== undefined) {\n metadata.set(VGI_CHOICES_KEY, spec.choicesJson);\n }\n if (spec.rangeNotation !== undefined) {\n metadata.set(VGI_RANGE_KEY, spec.rangeNotation);\n }\n if (spec.pattern !== undefined) {\n metadata.set(VGI_PATTERN_KEY, spec.pattern);\n }\n\n const field = field_(\n spec.name,\n spec.arrowType,\n true,\n metadata.size > 0 ? metadata : undefined\n );\n fields.push(field);\n }\n\n return schema_(fields);\n}\n\n// =============================================================================\n// Macro Argument Schemas\n// =============================================================================\n\n/**\n * Build a macro `arguments_schema` describing macro parameters.\n *\n * Mirrors the function `arguments_schema` mechanism: one Arrow field per macro\n * parameter, in `parameters` order, each nullable. The per-parameter\n * description is carried via the same `vgi_doc` field-metadata key functions use\n * (UTF-8, presence-only — the key is omitted entirely when there is no doc). A\n * parameter's field type is the type of its default value when one is known\n * (decoded from `parameterDefaultValues`, a one-row RecordBatch serialized as\n * IPC bytes), else `nullType()`.\n *\n * @param parameters Ordered list of macro parameter names.\n * @param parameterDefaultValues Optional one-row RecordBatch (IPC bytes) whose\n * columns are parameter names with typed default values; used to infer each\n * parameter's field type.\n * @param parameterDocs Optional mapping of parameter name to description. Empty\n * or missing descriptions yield no `vgi_doc` metadata on the field.\n * @returns Arrow schema with one nullable field per parameter, in order.\n */\nexport function macroArgumentsSchema(\n parameters: string[],\n parameterDefaultValues?: Uint8Array | null,\n parameterDocs?: Record<string, string>,\n): VgiSchema {\n const docs = parameterDocs ?? {};\n\n // Map parameter name -> Arrow type from the typed default values, if any.\n const defaultTypes: Map<string, VgiDataType> = new Map();\n if (parameterDefaultValues && parameterDefaultValues.length > 0) {\n const batch = deserializeBatch(parameterDefaultValues);\n for (const f of batch.schema.fields) {\n defaultTypes.set(f.name, f.type);\n }\n }\n\n const fields: VgiField[] = [];\n for (const name of parameters) {\n const metadata: Map<string, string> = new Map();\n const doc = docs[name];\n if (doc) {\n metadata.set(VGI_DOC_KEY, doc);\n }\n const fieldType = defaultTypes.get(name) ?? nullType();\n fields.push(field_(name, fieldType, true, metadata.size > 0 ? metadata : undefined));\n }\n\n return schema_(fields);\n}\n\n/**\n * Extract per-parameter descriptions from a macro `arguments_schema`.\n *\n * Inverse of {@link macroArgumentsSchema}'s `vgi_doc` handling: reads the\n * `vgi_doc` field metadata (UTF-8) for each field. Fields without the key\n * (undocumented) are omitted from the result.\n *\n * @param schema A macro `arguments_schema` (one field per parameter).\n * @returns Mapping of parameter name to description, for documented parameters only.\n */\nexport function macroParameterDocsFromSchema(schema: VgiSchema): Record<string, string> {\n const docs: Record<string, string> = {};\n for (const field of schema.fields) {\n const doc = field.metadata.get(VGI_DOC_KEY);\n if (doc) {\n docs[field.name] = doc;\n }\n }\n return docs;\n}\n\n/**\n * Convert an Arrow Schema back to ArgumentSpecs.\n */\nexport function schemaToArgumentSpecs(schema: VgiSchema): ArgumentSpec[] {\n const specs: ArgumentSpec[] = [];\n let positionIndex = 0;\n\n for (const field of schema.fields) {\n const metadata = field.metadata;\n\n const isNamed = metadata.get(VGI_ARG_KEY) === VGI_ARG_NAMED;\n const position: number | string = isNamed\n ? field.name\n : positionIndex++;\n\n const vgiType = metadata.get(VGI_TYPE_KEY);\n const isTableInput = vgiType === VGI_TYPE_TABLE;\n const isAnyType = vgiType === VGI_TYPE_ANY;\n const isVarargs = metadata.get(VGI_VARARGS_KEY) === VGI_VARARGS_TRUE;\n const isConst = metadata.get(VGI_CONST_KEY) === VGI_CONST_TRUE;\n const doc = metadata.get(VGI_DOC_KEY) ?? \"\";\n\n // Per-argument constraint metadata (absent key -> undefined).\n const defaultJson = metadata.get(VGI_DEFAULT_KEY);\n const choicesJson = metadata.get(VGI_CHOICES_KEY);\n const rangeNotation = metadata.get(VGI_RANGE_KEY);\n const pattern = metadata.get(VGI_PATTERN_KEY);\n\n specs.push({\n name: field.name,\n position,\n arrowType: field.type,\n isTableInput,\n isAnyType,\n isVarargs,\n isConst,\n doc,\n defaultJson,\n choicesJson,\n rangeNotation,\n pattern,\n });\n }\n\n return specs;\n}\n",
|
|
48
51
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Aggregate function framework — mirrors vgi-python's vgi/aggregate_function.py\n// protocol at the wire level. Per-execution state lives in an in-memory store\n// keyed by (execution_id, group_id); fine for subprocess workers and for\n// single-instance HTTP. Multi-host HTTP deployments would need a pluggable\n// state backend (same tradeoff Python's FunctionStorage wraps).\n//\n// DuckDB drives the lifecycle via five unary RPCs:\n//\n// aggregate_bind → resolve output schema + allocate execution_id\n// aggregate_update → fold rows into per-group state\n// aggregate_combine → merge parallel-build states\n// aggregate_finalize → emit one result row per group_id\n// aggregate_destructor → free states (best-effort; see Python worker.py)\n\nimport { type VgiSchema, schema, type VgiField, field, type VgiBatch, type VgiDataType, nullType, isNull } from \"../arrow/index.js\";\nimport type { Arguments } from \"../arguments/arguments.js\";\nimport {\n constraintSpecFields,\n type ArgumentSpec,\n type ArgumentConstraints,\n} from \"../arguments/argument-spec.js\";\nimport { assertArrowType, assertArrowTypes } from \"../arguments/argument-spec.js\";\nimport type {\n FunctionMeta,\n VgiFunction,\n} from \"./types.js\";\nimport { DEFAULT_MAX_WORKERS } from \"../types.js\";\nimport type { FunctionExample } from \"./types.js\";\n// Aggregate state persistence uses node:fs/path/os to spill per-group state to\n// disk under VGI_AGG_STATE_DIR. Workers (Cloudflare workerd / browsers)\n// don't define aggregate functions in the first place, so we resolve the\n// node:* modules through indirect string variables that esbuild can't trace.\n// The bundle stays clean even without nodejs_compat polyfills.\nconst _NODE_FS_MOD = \"node:fs\";\nconst _NODE_PATH_MOD = \"node:path\";\nconst _NODE_OS_MOD = \"node:os\";\nfunction _aggReq(): any {\n const req: any = (import.meta as any).require ?? (globalThis as any).require ?? null;\n if (!req) {\n throw new Error(\n \"Aggregate state persistence requires Node.js or Bun (node:fs/path/os).\",\n );\n }\n return req;\n}\nconst fs: any = new Proxy({} as any, {\n get: (_t, prop) => (_aggReq()(_NODE_FS_MOD) as any)[prop],\n});\nconst path: any = new Proxy({} as any, {\n get: (_t, prop) => (_aggReq()(_NODE_PATH_MOD) as any)[prop],\n});\nconst os: any = new Proxy({} as any, {\n get: (_t, prop) => (_aggReq()(_NODE_OS_MOD) as any)[prop],\n});\n\n// Column name DuckDB prepends to every aggregate_update batch. One entry per\n// input row; the value identifies which group the row belongs to.\nexport const GROUP_COLUMN_NAME = \"__vgi_group_id\";\n\nexport interface AggregateBindParams<TArgs = Record<string, any>> {\n args: TArgs;\n arguments: Arguments;\n inputSchema: VgiSchema | null;\n settings: Record<string, any>;\n secrets: Record<string, Record<string, any>>;\n /** Resolved names aligned with the complete logical argument order. */\n argumentNames: (string | null)[] | null;\n}\n\nexport interface AggregateUpdateParams<TArgs = Record<string, any>, TState = any> {\n states: Map<bigint, TState>;\n groupIds: bigint[];\n columns: any[]; // arrow Vectors per declared param\n args: TArgs;\n /**\n * Get-or-initialize accessor for per-group state. Call this inside the loop\n * only when the row actually contributes to the aggregate — skipping it\n * (e.g. on NULL input under NullHandling.DEFAULT) leaves `states` without\n * an entry for the group, so finalize() can return SQL NULL for that\n * group (matches vgi-python's \"state absent = NULL\" semantics for\n * SUM/AVG/MIN/MAX over zero non-null rows).\n */\n ensureState: (gid: bigint) => TState;\n}\n\nexport interface AggregateFinalizeParams<TArgs = Record<string, any>, TState = any> {\n groupIds: bigint[];\n states: Map<bigint, TState | null>;\n outputSchema: VgiSchema;\n args: TArgs;\n}\n\nexport interface AggregateFunctionConfig<TArgs = Record<string, any>, TState = any> {\n name: string;\n description?: string;\n /**\n * Map of positional argument name → Arrow type. Passed through to DuckDB\n * function registration. Use `null` (untyped) for varargs placeholders.\n */\n args?: Record<string, VgiDataType>;\n /**\n * Names of args that accept a variable number of column arguments. DuckDB\n * treats these as varargs of the declared Arrow type; at call time the\n * function may receive 1..N columns of that type. update() sees all of\n * them as consecutive entries in `columns`.\n */\n varargs?: string[];\n /**\n * Names of args whose value is constant (known at bind time) and must be\n * folded away by DuckDB before reaching update(). The value arrives in\n * `bindParams.args[name]`; it is NOT passed as an input column in the\n * update batch. Use for aggregates parameterized by a literal (e.g.\n * percentile=0.5 in vgi_percentile).\n */\n constParams?: string[];\n /**\n * Arrow type of the aggregate's output (one value per group). DuckDB uses\n * this to build the result column type at bind time. May be overridden\n * at bind time by `onBind` (returning a different Arrow type) for\n * aggregates whose return type depends on the input column type\n * (e.g. vgi_generic_sum: BIGINT input → BIGINT output, DOUBLE → DOUBLE).\n */\n outputType: VgiDataType;\n /**\n * Optional bind-time hook for dynamic output types. Receives the bind\n * parameters (including input_schema) and returns the Arrow type to\n * advertise for this invocation. Defaults to returning `config.outputType`.\n */\n onBind?: (params: AggregateBindParams<TArgs>) => VgiDataType | Promise<VgiDataType>;\n /** Optional per-arg default values (positional only here). */\n argDefaults?: Record<string, any>;\n /** Authoritative typed defaults: one row, defaulted parameters only. */\n parameterDefaultValues?: VgiBatch | null;\n /**\n * Per-argument discovery constraints (choices / ge / le / gt / lt / pattern),\n * keyed by argument name. Surfaced via `vgi_function_arguments()` and enforced\n * at aggregate_bind for const params: a value violating a declared constraint\n * fails the bind with an ArgumentValidationError.\n */\n argConstraints?: Record<string, ArgumentConstraints>;\n\n initialState: (params: AggregateBindParams<TArgs>) => TState;\n /**\n * Fold a batch of input rows into the provided per-group state map.\n * Implementations mutate `states` in place. `groupIds[i]` identifies which\n * group row i belongs to; `columns[k][i]` is the value for the kth declared\n * column argument at row i.\n */\n update: (params: AggregateUpdateParams<TArgs, TState>) => void;\n combine: (source: TState, target: TState, params: AggregateBindParams<TArgs>) => TState;\n /** Must return a single-column RecordBatch with `groupIds.length` rows. */\n finalize: (params: AggregateFinalizeParams<TArgs, TState>) => VgiBatch;\n\n examples?: FunctionExample[];\n categories?: string[];\n /** Arbitrary function-level tags surfaced into duckdb_functions().tags. */\n tags?: Record<string, string>;\n nullHandling?: \"DEFAULT\" | \"SPECIAL\";\n /**\n * DuckDB secret types this aggregate needs. Advertised on the catalog's\n * `required_secrets` so the C++ extension pre-resolves matching secrets and\n * delivers their VALUES on the aggregate_bind request (keyed by secret name).\n * The secret is read at bind time only — update/combine/finalize receive an\n * empty ResolvedSecrets. Mirrors vgi-python's `Secret()` annotation on an\n * aggregate `on_bind`.\n */\n requiredSecrets?: string[];\n}\n\n// Per-execution state registry. Value = (gid → state) + bind context.\n//\n// Under DuckDB's parallel aggregate with worker pooling, aggregate_* RPCs for\n// the same execution_id can land on different worker processes — so state\n// needs to live in a place all workers can reach. We use a filesystem-backed\n// store (one directory per execution_id, one JSON file per group_id) with\n// atomic rename-on-write. Fine for subprocess transport and for\n// single-instance HTTP; multi-host HTTP would need a shared path or a\n// swap-in network backend. Override with VGI_AGG_STATE_DIR.\n//\n// In-memory cache sits in front of the filesystem to keep single-process\n// workloads fast — writes go to disk, reads prefer cache, and getExecutionState\n// lazily reconstructs from disk when a different worker's exec is requested.\n\ntype StateMap = Map<bigint, any>;\n\ninterface ExecEntry {\n states: StateMap;\n bindArgs: Arguments;\n bindParams: AggregateBindParams<any>;\n loaded: Set<bigint>; // gids fetched from disk (so we don't refetch in same call)\n}\n\nconst stateStore = new Map<string, ExecEntry>();\n\n// Custom JSON codec: BigInt ↔ {\"__bigint__\":\"…\"}. Keep the encoder/decoder\n// centralized so aggregate state classes with int64 fields (CountState,\n// SumState, etc.) round-trip without extra wiring.\nfunction jsonReplacer(_: string, v: any): any {\n if (typeof v === \"bigint\") return { __bigint__: v.toString() };\n return v;\n}\nfunction jsonReviver(_: string, v: any): any {\n if (v && typeof v === \"object\" && typeof (v as any).__bigint__ === \"string\") {\n return BigInt((v as any).__bigint__);\n }\n return v;\n}\n\nfunction stateDirRoot(): string {\n return process.env.VGI_AGG_STATE_DIR ?? path.join(os.tmpdir(), \"vgi-agg\");\n}\n\nfunction execDir(execHex: string): string {\n return path.join(stateDirRoot(), execHex);\n}\n\nfunction execKey(executionId: Uint8Array): string {\n let s = \"\";\n for (const b of executionId) s += b.toString(16).padStart(2, \"0\");\n return s;\n}\n\n// Atomic write: write to tmp then rename. Avoids partial reads from another\n// worker mid-update. Node's fs.renameSync is atomic on POSIX for same FS.\nfunction atomicWriteJson(filePath: string, value: any): void {\n const tmp = filePath + \".tmp.\" + process.pid + \".\" + Math.random().toString(36).slice(2);\n const parent = path.dirname(filePath);\n fs.mkdirSync(parent, { recursive: true });\n fs.writeFileSync(tmp, JSON.stringify(value, jsonReplacer));\n fs.renameSync(tmp, filePath);\n}\n\nfunction tryReadJson(filePath: string): any | undefined {\n try {\n const text = fs.readFileSync(filePath, \"utf8\");\n return JSON.parse(text, jsonReviver);\n } catch (e: any) {\n if (e?.code === \"ENOENT\") return undefined;\n throw e;\n }\n}\n\n/**\n * Fetch the execution context — bind args/params + states for requested gids.\n * On cache miss, tries to reconstruct from on-disk files written by a\n * sibling worker. Returns undefined if the exec never existed anywhere.\n * `requestedGids` (optional) tells us which group states to pre-load.\n */\nexport function getExecutionState(\n executionId: Uint8Array,\n requestedGids?: Iterable<bigint>,\n): ExecEntry | undefined {\n const key = execKey(executionId);\n let entry = stateStore.get(key);\n if (!entry) {\n // Try to reconstruct bind context from disk.\n const ctx = tryReadJson(path.join(execDir(key), \"context.json\"));\n if (!ctx) return undefined;\n // Restore bindParams + args from the serialized context. args is kept\n // only as a plain dict; the Arguments instance isn't needed after bind.\n entry = {\n states: new Map(),\n bindArgs: ctx.bindArgs, // placeholder — Arguments instance is only needed during bind\n bindParams: ctx.bindParams,\n loaded: new Set(),\n };\n stateStore.set(key, entry);\n }\n if (requestedGids) {\n // Always re-read from disk each RPC. A sibling worker may have just\n // written a newer value for this gid; relying on our in-memory cache\n // would overwrite their update on our next persist (read-modify-write\n // race). File I/O per-RPC is cheap compared to the RPC overhead.\n for (const gid of requestedGids) {\n const stateFile = path.join(execDir(key), gid.toString() + \".json\");\n const s = tryReadJson(stateFile);\n if (s !== undefined) {\n entry.states.set(gid, s);\n } else {\n entry.states.delete(gid);\n }\n entry.loaded.add(gid);\n }\n }\n return entry;\n}\n\nexport function setExecutionState(\n executionId: Uint8Array,\n entry: Omit<ExecEntry, \"loaded\">,\n): void {\n const key = execKey(executionId);\n stateStore.set(key, { ...entry, loaded: new Set() });\n // Persist bind context so sibling workers can reconstruct it on demand.\n atomicWriteJson(path.join(execDir(key), \"context.json\"), {\n bindParams: entry.bindParams,\n // bindArgs is a live Arguments instance; stash its args map separately\n // if needed for future state-dependent behavior. Workers reading the\n // context receive `bindParams.args` which is what update/finalize use.\n });\n}\n\n/**\n * Persist the given group states to disk so sibling workers can pick them up.\n * Deletes the on-disk entry when the in-memory state was removed (gid no\n * longer present in states map).\n */\nexport function persistGroupStates(\n executionId: Uint8Array,\n gids: Iterable<bigint>,\n): void {\n const key = execKey(executionId);\n const entry = stateStore.get(key);\n if (!entry) return;\n for (const gid of gids) {\n const stateFile = path.join(execDir(key), gid.toString() + \".json\");\n if (entry.states.has(gid)) {\n atomicWriteJson(stateFile, entry.states.get(gid));\n } else {\n try { fs.unlinkSync(stateFile); } catch { /* already gone */ }\n }\n entry.loaded.add(gid);\n }\n}\n\nexport function deleteExecutionState(executionId: Uint8Array): void {\n const key = execKey(executionId);\n stateStore.delete(key);\n try { fs.rmSync(execDir(key), { recursive: true, force: true }); } catch { /* best-effort */ }\n}\n\n/**\n * Declare an aggregate function. The returned VgiFunction has `kind:\n * \"aggregate\"` plus a `config` handle the dispatch layer uses to drive the\n * aggregate_* RPCs; the scalar/table-function code paths ignore it.\n */\nexport function defineAggregate<TArgs = Record<string, any>, TState = any>(\n config: AggregateFunctionConfig<TArgs, TState>,\n): VgiFunction & { aggregateConfig: AggregateFunctionConfig<TArgs, TState> } {\n assertArrowTypes((config as any).args, `defineAggregate(\"${config.name}\"): args`);\n\n const specs: ArgumentSpec[] = [];\n let posIdx = 0;\n const varargsSet = new Set(config.varargs ?? []);\n const constSet = new Set(config.constParams ?? []);\n if (config.args) {\n for (const [name, type] of Object.entries(config.args)) {\n const hasDefault = config.argDefaults?.[name] !== undefined;\n const isConst = constSet.has(name);\n const isAnyType = isNull(type);\n // Const params are always positional at the SQL call-site — a default\n // value just means \"the user may omit it and we'll use the default\",\n // not \"rename to a named kwarg\". Non-const args with defaults become\n // named (matches table-function behavior).\n specs.push({\n name,\n position: isConst || !hasDefault ? posIdx++ : name,\n arrowType: isAnyType ? nullType() : type,\n isAnyType,\n isVarargs: varargsSet.has(name),\n isConst,\n ...constraintSpecFields(\n config.argConstraints?.[name],\n config.argDefaults?.[name],\n ),\n });\n }\n }\n\n const meta: FunctionMeta = {\n name: config.name,\n description: config.description,\n examples: config.examples,\n categories: config.categories,\n tags: config.tags,\n parameterDefaultValues: config.parameterDefaultValues,\n nullHandling: config.nullHandling as any,\n requiredSecrets: config.requiredSecrets,\n };\n\n // The normal VgiFunction methods (bind/globalInit/createStreamHandlers) are\n // never invoked for aggregates — the dispatch layer routes aggregate_* RPCs\n // through the separate aggregate_* handler. Provide stubs that throw so\n // misrouted calls surface loudly rather than silently hanging.\n // Catalog output schema: single \"result\" column. Advertise config.outputType\n // when it's a real type (anything other than Null) — onBind may still override\n // at bind time, but for the catalog listing we prefer the static declaration\n // so duckdb_functions() shows a meaningful return type. Aggregates whose\n // return type genuinely depends on input set outputType: nullType() to\n // advertise ANY explicitly.\n const isAnyType = isNull(config.outputType);\n const defaultOutputSchema = isAnyType\n ? schema([field(\"result\", nullType(), true, new Map([[\"vgi:any\", \"true\"]]))])\n : schema([field(\"result\", config.outputType, true)]);\n\n return {\n kind: \"aggregate\" as any,\n meta,\n argumentSpecs: specs,\n defaultOutputSchema,\n bind: () => { throw new Error(`aggregate '${config.name}' received bind() — should be routed through aggregate_bind`); },\n globalInit: () => { throw new Error(`aggregate '${config.name}' received globalInit() — should be routed through aggregate_bind`); },\n createStreamHandlers: () => { throw new Error(`aggregate '${config.name}' is unary — no stream handlers`); },\n aggregateConfig: config,\n } as VgiFunction & { aggregateConfig: AggregateFunctionConfig<TArgs, TState> };\n}\n",
|
|
49
52
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Handlers for the aggregate function lifecycle: bind allocates execution_id\n// and output schema, update folds rows into per-group state, combine merges\n// states across workers, finalize emits one result row per group, destructor\n// drops finished group state.\n\nimport {\n type VgiSchema,\n type VgiBatch,\n type VgiDataType,\n schema as makeSchema,\n field,\n isDecimal,\n serializeBatch,\n deserializeBatch,\n} from \"../../arrow/index.js\";\nimport { Protocol } from \"@query-farm/vgi-rpc\";\nimport type { FunctionRegistry } from \"../../functions/registry.js\";\nimport { deserializeArguments } from \"../serialize.js\";\nimport { deserializeSchema, serializeSchema, batchToSecretDict } from \"../../util/arrow/index.js\";\nimport { toUint8Array } from \"../../util/bytes.js\";\nimport {\n AggregateBindParamsSchema,\n AggregateBindResultSchema,\n AggregateCombineParamsSchema,\n AggregateDestructorParamsSchema,\n AggregateFinalizeParamsSchema,\n AggregateFinalizeResultSchema,\n AggregateUpdateParamsSchema,\n} from \"../../generated/vgi-protocol-schemas.js\";\nimport {\n getExecutionState,\n setExecutionState,\n persistGroupStates,\n GROUP_COLUMN_NAME,\n type AggregateFunctionConfig,\n type AggregateBindParams,\n} from \"../../functions/aggregate.js\";\nimport { Arguments } from \"../../arguments/arguments.js\";\nimport { validateConstConstraints } from \"../../arguments/argument-spec.js\";\nimport {\n REQUEST_PARAMS_SCHEMA,\n RESULT_BINARY_SCHEMA,\n unwrapRequest,\n wrapResult,\n} from \"./shared.js\";\n\nexport function registerAggregateMethods(protocol: Protocol, registry: FunctionRegistry): void {\n // `schemaPath` scopes resolution to the schema the caller named. Every\n // aggregate RPC carries it (protocol 1.2.0), so an aggregate name declared in\n // two schemas dispatches to the one the request names rather than colliding\n // on the flat by-name index. `null` (no schema) keeps the cross-schema lookup.\n function resolveAggregate(\n name: string,\n schemaPath?: string[] | null,\n ): AggregateFunctionConfig<any, any> {\n const func = registry.get(name, {\n arguments: new Arguments(),\n inputSchema: null,\n isScalar: false,\n schemaPath: schemaPath ?? null,\n }) as any;\n if (!func || func.kind !== \"aggregate\") {\n throw new Error(`Function '${name}' is not an aggregate function`);\n }\n return func.aggregateConfig as AggregateFunctionConfig<any, any>;\n }\n\n // ------------------------------------------------------------------------\n // aggregate_bind — allocate execution_id, return output schema\n // ------------------------------------------------------------------------\n protocol.unary(\"aggregate_bind\", {\n params: AggregateBindParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const innerParams = unwrapRequest(params.request);\n const functionName: string = innerParams.function_name;\n const cfg = resolveAggregate(functionName, innerParams.schema_path ?? null);\n const argBytes = toUint8Array(innerParams.arguments);\n const args = deserializeArguments(argBytes);\n const inputSchema = innerParams.input_schema\n ? deserializeSchema(toUint8Array(innerParams.input_schema))\n : null;\n // Decode the resolved-secrets batch the extension pre-resolves for\n // aggregates that declared `requiredSecrets`. Mirrors the table-buffering\n // handler (batchToSecretDict). The secret VALUES are delivered only here,\n // at bind time — update/combine/finalize see no secrets by design.\n const secretsBytes = innerParams.secrets ? toUint8Array(innerParams.secrets) : null;\n const secretsBatch =\n secretsBytes && secretsBytes.length > 0 ? deserializeBatch(secretsBytes) : null;\n const secrets = secretsBatch ? batchToSecretDict(secretsBatch) : {};\n const bindParams: AggregateBindParams<any> = {\n args: extractArgMap(cfg, args),\n arguments: args,\n inputSchema,\n settings: {},\n secrets,\n argumentNames: innerParams.argument_names\n ? (Array.isArray(innerParams.argument_names)\n ? innerParams.argument_names\n : [...innerParams.argument_names])\n .map((value: unknown) => value == null ? null : String(value))\n : null,\n };\n const executionId = new Uint8Array(16);\n crypto.getRandomValues(executionId);\n setExecutionState(executionId, {\n states: new Map(),\n bindArgs: args,\n bindParams,\n });\n // Output schema is a single \"result\" column. Type comes from the\n // optional onBind hook (for aggregates whose return type depends on\n // input — e.g. vgi_generic_sum takes ANY and returns the same type);\n // otherwise the declared cfg.outputType.\n const outType = cfg.onBind ? await cfg.onBind(bindParams) : cfg.outputType;\n const outSchema = makeSchema([field(\"result\", outType, true)]);\n return wrapResult(\n { output_schema: serializeSchema(outSchema), execution_id: executionId },\n AggregateBindResultSchema,\n );\n },\n });\n\n // ------------------------------------------------------------------------\n // aggregate_update — fold the incoming batch into per-group state\n // ------------------------------------------------------------------------\n protocol.unary(\"aggregate_update\", {\n params: AggregateUpdateParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: (params) => {\n const innerParams = unwrapRequest(params.request);\n const functionName: string = innerParams.function_name;\n const executionId = toUint8Array(innerParams.execution_id);\n const cfg = resolveAggregate(functionName, innerParams.schema_path ?? null);\n const batch = readSingleBatch(toUint8Array(innerParams.input_batch));\n if (!batch || batch.numRows === 0) return wrapResult({}, makeSchema([]));\n\n const gidIdx = batch.schema.fields.findIndex((f) => f.name === GROUP_COLUMN_NAME);\n if (gidIdx < 0) {\n throw new Error(`aggregate_update: input batch missing ${GROUP_COLUMN_NAME} column`);\n }\n const gidCol = batch.getChildAt(gidIdx)!;\n const groupIds: bigint[] = [];\n const uniqueGids = new Set<bigint>();\n for (let i = 0; i < batch.numRows; i++) {\n const v = gidCol.get(i);\n const g = typeof v === \"bigint\" ? v : BigInt(v as any);\n groupIds.push(g);\n uniqueGids.add(g);\n }\n const exec = getExecutionState(executionId, uniqueGids);\n if (!exec) {\n throw new Error(`aggregate_update: unknown execution_id for '${functionName}' (bind missing or state dropped)`);\n }\n\n // Build column-arg arrays — every non-__vgi_group_id column, in\n // schema order — and pass to user's update(). We deliberately do NOT\n // pre-allocate state for every group_id seen — the user decides when\n // to call ensureState() so that groups with only-NULL input (skipped\n // rows) never get an entry, which lets finalize() return SQL NULL.\n const columns: any[] = [];\n for (let i = 0; i < batch.schema.fields.length; i++) {\n if (i === gidIdx) continue;\n columns.push(batch.getChildAt(i));\n }\n const ensureState = (gid: bigint) => {\n let s = exec.states.get(gid);\n if (s === undefined) {\n s = cfg.initialState(exec.bindParams);\n exec.states.set(gid, s);\n }\n return s;\n };\n cfg.update({\n states: exec.states,\n groupIds,\n columns,\n args: exec.bindParams.args,\n ensureState,\n });\n // Flush mutated states to disk so sibling workers see them. We persist\n // every group that was referenced this call — some may be unchanged\n // (skipped by NULL handling), in which case the file simply reflects\n // the pre-existing initial state; the idempotent rewrite is cheap\n // relative to the RPC overhead.\n persistGroupStates(executionId, uniqueGids);\n return wrapResult({}, makeSchema([]));\n },\n });\n\n // ------------------------------------------------------------------------\n // aggregate_combine — merge (source_group_id, target_group_id) pairs\n // ------------------------------------------------------------------------\n protocol.unary(\"aggregate_combine\", {\n params: AggregateCombineParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: (params) => {\n const innerParams = unwrapRequest(params.request);\n const functionName: string = innerParams.function_name;\n const executionId = toUint8Array(innerParams.execution_id);\n const cfg = resolveAggregate(functionName, innerParams.schema_path ?? null);\n const batch = readSingleBatch(toUint8Array(innerParams.merge_batch));\n if (!batch || batch.numRows === 0) return wrapResult({}, makeSchema([]));\n\n const srcCol = batch.getChild(\"source_group_id\")!;\n const tgtCol = batch.getChild(\"target_group_id\")!;\n const referencedGids = new Set<bigint>();\n const srcIds: bigint[] = [];\n const tgtIds: bigint[] = [];\n for (let i = 0; i < batch.numRows; i++) {\n const src = BigInt(srcCol.get(i) as any);\n const tgt = BigInt(tgtCol.get(i) as any);\n srcIds.push(src); tgtIds.push(tgt);\n referencedGids.add(src); referencedGids.add(tgt);\n }\n const exec = getExecutionState(executionId, referencedGids);\n if (!exec) {\n throw new Error(\n `aggregate_combine: unknown execution_id for '${functionName}' ` +\n `(context missing on disk — bind may have failed or been cleaned up)`,\n );\n }\n const touchedTargets = new Set<bigint>();\n for (let i = 0; i < batch.numRows; i++) {\n const src = srcIds[i];\n const tgt = tgtIds[i];\n const srcHas = exec.states.has(src);\n const tgtHas = exec.states.has(tgt);\n if (!srcHas && !tgtHas) continue;\n const srcState = srcHas ? exec.states.get(src)! : cfg.initialState(exec.bindParams);\n const tgtState = tgtHas ? exec.states.get(tgt)! : cfg.initialState(exec.bindParams);\n exec.states.set(tgt, cfg.combine(srcState, tgtState, exec.bindParams));\n touchedTargets.add(tgt);\n }\n persistGroupStates(executionId, touchedTargets);\n return wrapResult({}, makeSchema([]));\n },\n });\n\n // ------------------------------------------------------------------------\n // aggregate_finalize — emit one result row per requested group_id\n // ------------------------------------------------------------------------\n protocol.unary(\"aggregate_finalize\", {\n params: AggregateFinalizeParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: (params) => {\n const innerParams = unwrapRequest(params.request);\n const functionName: string = innerParams.function_name;\n const executionId = toUint8Array(innerParams.execution_id);\n const cfg = resolveAggregate(functionName, innerParams.schema_path ?? null);\n const outputSchema = deserializeSchema(toUint8Array(innerParams.output_schema));\n const gidBatch = readSingleBatch(toUint8Array(innerParams.group_ids_batch));\n const groupIds: bigint[] = [];\n const uniqueGids = new Set<bigint>();\n if (gidBatch) {\n const col = gidBatch.getChild(\"group_id\")!;\n for (let i = 0; i < gidBatch.numRows; i++) {\n const v = col.get(i);\n const g = typeof v === \"bigint\" ? v : BigInt(v as any);\n groupIds.push(g);\n uniqueGids.add(g);\n }\n }\n const exec = getExecutionState(executionId, uniqueGids);\n if (!exec) {\n throw new Error(`aggregate_finalize: unknown execution_id for '${functionName}'`);\n }\n // Groups never updated pass state = null so finalize() can emit SQL NULL\n // (matches Python semantics for SUM/AVG/MIN/MAX over zero rows).\n const states = new Map<bigint, any | null>();\n for (const gid of groupIds) {\n states.set(gid, exec.states.has(gid) ? exec.states.get(gid) : null);\n }\n const resultBatch = cfg.finalize({\n groupIds, states, outputSchema, args: exec.bindParams.args,\n });\n return wrapResult(\n { result_batch: serializeBatchWithSchema(resultBatch) },\n AggregateFinalizeResultSchema,\n );\n },\n });\n\n // ------------------------------------------------------------------------\n // aggregate_destructor — drop state for finished groups (best-effort)\n //\n // DuckDB sends a batch of group_ids to discard; we remove each from the\n // in-memory state map. We DO NOT tear down the entire execution on an\n // empty batch — DuckDB may still call finalize afterwards in some plans\n // (matches Python's conservative behavior; the execution entry is cleaned\n // up when the worker process exits).\n // ------------------------------------------------------------------------\n protocol.unary(\"aggregate_destructor\", {\n params: AggregateDestructorParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: (params) => {\n const innerParams = unwrapRequest(params.request);\n const executionId = toUint8Array(innerParams.execution_id);\n const exec = getExecutionState(executionId);\n if (!exec) return wrapResult({}, makeSchema([]));\n const gidBatch = readSingleBatch(toUint8Array(innerParams.group_ids_batch));\n if (!gidBatch || gidBatch.numRows === 0) return wrapResult({}, makeSchema([]));\n const col = gidBatch.getChild(\"group_id\")!;\n const toDrop = new Set<bigint>();\n for (let i = 0; i < gidBatch.numRows; i++) {\n const v = col.get(i);\n const g = typeof v === \"bigint\" ? v : BigInt(v as any);\n exec.states.delete(g);\n toDrop.add(g);\n }\n // Persist deletions (unlinks the per-group file so sibling workers\n // don't revive the state via getExecutionState's lazy disk load).\n persistGroupStates(executionId, toDrop);\n return wrapResult({}, makeSchema([]));\n },\n });\n}\n\nfunction extractArgMap(\n cfg: AggregateFunctionConfig<any, any>,\n args: Arguments,\n): Record<string, any> {\n const out: Record<string, any> = {};\n // The wire-side Arguments contains only const params — DuckDB erases const\n // args from the expression tree at bind time and serializes their values\n // into the aggregate_bind request's `arguments` field. So we index the\n // Arguments by the declaration order of const params only.\n const constSet = new Set(cfg.constParams ?? []);\n const constNames: string[] = [];\n if (cfg.args) {\n for (const name of Object.keys(cfg.args)) {\n if (constSet.has(name)) constNames.push(name);\n }\n }\n for (let i = 0; i < constNames.length; i++) {\n let v: any;\n try {\n v = args.get(i);\n // Decode DECIMAL scalars (DuckDB serializes 0.5-style literals as\n // DECIMAL(2,1), which Arrow stores as the unscaled integer — a raw\n // BigInt here). Scale back to float using the declared scale.\n const field = args.argumentsSchema?.fields.find(f => f.name === `positional_${i}`);\n if (field && isDecimal(field.type)) {\n const scale = (field.type as any).scale;\n if (typeof v === \"bigint\") v = Number(v) / Math.pow(10, scale);\n else if (typeof v === \"number\") v = v / Math.pow(10, scale);\n } else if (typeof v === \"bigint\") {\n v = Number(v);\n }\n } catch {\n // args.get throws when the arg isn't set — fall back to the declared\n // default so aggregates called without an explicit const value still\n // see it in update/finalize.\n const def = cfg.argDefaults?.[constNames[i]];\n if (def !== undefined) out[constNames[i]] = def;\n continue;\n }\n // Enforce declared constraints on the supplied value. This sits OUTSIDE the\n // try above so a constraint violation propagates as a bind error rather than\n // being swallowed and silently replaced by the default.\n const constraints = cfg.argConstraints?.[constNames[i]];\n if (constraints !== undefined) {\n validateConstConstraints(constNames[i], constraints, v);\n }\n out[constNames[i]] = v;\n }\n // Non-const args aren't in the wire Arguments, but users may still want\n // defaults surfaced for `params.args` — apply them here.\n if (cfg.argDefaults) {\n for (const [name, def] of Object.entries(cfg.argDefaults)) {\n if (!(name in out) && !constSet.has(name)) out[name] = def;\n }\n }\n return out;\n}\n\nfunction readSingleBatch(bytes: Uint8Array): VgiBatch | null {\n if (!bytes || bytes.length === 0) return null;\n const batch = deserializeBatch(bytes);\n return batch.numRows === 0 && batch.schema.fields.length === 0 ? null : batch;\n}\n\nfunction serializeBatchWithSchema(batch: VgiBatch): Uint8Array {\n // serializeBatch emits a full IPC stream (schema + batch + EOS) — the C++\n // aggregate_finalize reader expects exactly that.\n return serializeBatch(batch);\n}\n",
|
|
50
53
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Unary handlers for the table_buffering (Sink+Source) lifecycle:\n// table_buffering_process — sink one input batch, return state_id\n// table_buffering_combine — group/merge state_ids -> finalize_state_ids\n// table_buffering_destructor — best-effort end-of-query storage cleanup\n//\n// These RPCs carry no init context, so each cold-loads the init metadata that\n// the TABLE_BUFFERING init phase persisted to FunctionStorage (keyed by\n// execution_id), then rebuilds the user-facing TableBufferingParams. Mirrors\n// vgi-python's worker._load_table_buffering_params.\n\nimport { deserializeBatch } from \"../../arrow/index.js\";\nimport { Protocol } from \"@query-farm/vgi-rpc\";\nimport type { FunctionRegistry } from \"../../functions/registry.js\";\nimport { toUint8Array } from \"../../util/bytes.js\";\nimport { batchToScalarDict, batchToSecretDict } from \"../../util/arrow/index.js\";\nimport {\n TableBufferingCombineParamsSchema,\n TableBufferingCombineResultSchema,\n TableBufferingDestructorParamsSchema,\n TableBufferingDestructorResultSchema,\n TableBufferingProcessParamsSchema,\n TableBufferingProcessResultSchema,\n} from \"../../generated/vgi-protocol-schemas.js\";\nimport {\n REQUEST_PARAMS_SCHEMA,\n RESULT_BINARY_SCHEMA,\n unwrapRequest,\n wrapResult,\n} from \"./shared.js\";\nimport { openAttach } from \"./catalog/shared.js\";\nimport {\n BoundStorage,\n storage as defaultStorage,\n FrameworkNS,\n} from \"../../functions/storage.js\";\nimport {\n decodeBufferingInit,\n type TableBufferingVgiFunction,\n type TableBufferingParams,\n} from \"../../functions/table-buffering.js\";\nimport { Arguments } from \"../../arguments/arguments.js\";\n\nexport function registerTableBufferingMethods(\n protocol: Protocol,\n registry: FunctionRegistry,\n signingKey?: Uint8Array,\n): void {\n // `schemaPath` scopes resolution to the schema the caller named. The\n // buffering process/combine RPCs carry it (protocol 1.2.0), so a name\n // declared in two schemas resolves to the one the request names rather than\n // colliding on the flat by-name index. `null` keeps the cross-schema lookup.\n function resolveBuffering(\n name: string,\n schemaPath?: string[] | null,\n ): TableBufferingVgiFunction {\n const func = registry.get(name, {\n arguments: new Arguments(),\n inputSchema: null,\n isScalar: false,\n schemaPath: schemaPath ?? null,\n }) as any;\n if (!func || func.kind !== \"table_buffering\") {\n throw new Error(`Function '${name}' is not a table_buffering function`);\n }\n return func as TableBufferingVgiFunction;\n }\n\n // Cold-load init metadata + build TableBufferingParams from a unary request.\n async function loadParams(\n inner: Record<string, any>,\n clientLog: (level: string, message: string) => void,\n ctx: any,\n ): Promise<{ func: TableBufferingVgiFunction; params: TableBufferingParams<any> }> {\n const functionName: string = inner.function_name;\n const executionId = toUint8Array(inner.execution_id);\n // Unseal attach_opaque_data so combine()/process() see the SAME plaintext,\n // attach-scoped bytes that bind()/init() and plain table functions see.\n // Without this, on HTTP transport the buffering RPCs would scope persistent\n // BoundStorage by the *sealed* envelope while reads scope by the plaintext,\n // so attach-scoped state written in combine() is invisible to later reads.\n const rawAttach = inner.attach_opaque_data ? toUint8Array(inner.attach_opaque_data) : null;\n const attach =\n rawAttach && rawAttach.length > 0\n ? await openAttach(rawAttach, ctx?.auth, signingKey)\n : rawAttach;\n const transactionId = inner.transaction_id ? toUint8Array(inner.transaction_id) : null;\n\n const func = resolveBuffering(functionName, inner.schema_path ?? null);\n const bound = new BoundStorage(defaultStorage, executionId);\n const payload = await bound.stateGet(\n FrameworkNS.BUFFERING_INIT,\n BoundStorage.packIntKey(-1),\n );\n if (payload == null) {\n throw new Error(\n `table_buffering: unknown execution_id ${hex(executionId)} ` +\n `(init never ran or destructor already fired)`,\n );\n }\n const { request } = decodeBufferingInit(payload);\n const args = func.bufferingExtractArgs(request.bind_call);\n const settings = batchToScalarDict(request.bind_call.settings);\n const secrets = batchToSecretDict(request.bind_call.secrets);\n\n const params: TableBufferingParams<any> = {\n args,\n initCall: request,\n outputSchema: request.output_schema,\n settings,\n secrets,\n storage: bound,\n executionId,\n attachId: attach ?? new Uint8Array(0),\n transactionId,\n function_name: functionName,\n batchIndex: null,\n clientLog,\n };\n return { func, params };\n }\n\n // ------------------------------------------------------------------------\n // table_buffering_process — sink one batch, return state_id (unary)\n // ------------------------------------------------------------------------\n protocol.unary(\"table_buffering_process\", {\n params: TableBufferingProcessParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (rpcParams, ctx?: any) => {\n const inner = unwrapRequest(rpcParams.request);\n const clientLog = makeClientLog(ctx);\n const { func, params } = await loadParams(inner, clientLog, ctx);\n if (inner.batch_index != null) {\n params.batchIndex = Number(inner.batch_index);\n }\n const batch = deserializeBatch(toUint8Array(inner.input_batch));\n const stateId = await func.bufferingConfig.process(batch, params);\n if (!(stateId instanceof Uint8Array)) {\n throw new Error(\n `${func.meta.name}.process() must return Uint8Array (the opaque state_id)`,\n );\n }\n return wrapResult({ state_id: stateId }, TableBufferingProcessResultSchema);\n },\n });\n\n // ------------------------------------------------------------------------\n // table_buffering_combine — group/merge state_ids (unary)\n // ------------------------------------------------------------------------\n protocol.unary(\"table_buffering_combine\", {\n params: TableBufferingCombineParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (rpcParams, ctx?: any) => {\n const inner = unwrapRequest(rpcParams.request);\n const clientLog = makeClientLog(ctx);\n const { func, params } = await loadParams(inner, clientLog, ctx);\n const stateIds = decodeBytesList(inner.state_ids);\n const finalizeStateIds = await func.bufferingConfig.combine(stateIds, params);\n const out = finalizeStateIds.map((fid, i) => {\n if (!(fid instanceof Uint8Array)) {\n throw new Error(\n `${func.meta.name}.combine() returned non-Uint8Array finalize_state_id at index ${i}`,\n );\n }\n return fid;\n });\n return wrapResult(\n { finalize_state_ids: out },\n TableBufferingCombineResultSchema,\n );\n },\n });\n\n // ------------------------------------------------------------------------\n // table_buffering_destructor — best-effort end-of-query cleanup (unary)\n // ------------------------------------------------------------------------\n protocol.unary(\"table_buffering_destructor\", {\n params: TableBufferingDestructorParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (rpcParams) => {\n try {\n const inner = unwrapRequest(rpcParams.request);\n const executionId = toUint8Array(inner.execution_id);\n const bound = new BoundStorage(defaultStorage, executionId);\n await bound.executionClear();\n } catch {\n // Teardown path — swallow; the entry is wiped when the worker exits.\n }\n return wrapResult({}, TableBufferingDestructorResultSchema);\n },\n });\n}\n\nfunction makeClientLog(ctx: any): (level: string, message: string) => void {\n if (ctx && typeof ctx.clientLog === \"function\") {\n return (level: string, message: string) => ctx.clientLog(level, message);\n }\n return () => {};\n}\n\nfunction decodeBytesList(raw: any): Uint8Array[] {\n if (raw == null) return [];\n const out: Uint8Array[] = [];\n const iter: Iterable<any> = Array.isArray(raw)\n ? raw\n : typeof raw[Symbol.iterator] === \"function\"\n ? raw\n : [];\n for (const entry of iter) {\n if (entry == null) continue;\n out.push(toUint8Array(entry));\n }\n return out;\n}\n\nfunction hex(buf: Uint8Array): string {\n return Array.from(buf, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n",
|
|
51
|
-
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Table sink+source (\"table_buffering\") function implementation.\n//\n// Three phases, mirroring the C++ PhysicalVgiTableBuffering Sink+Source\n// operator:\n// 1. Sink — process(batch, params) -> state_id (bytes), one per input\n// batch. Driven by the unary `table_buffering_process` RPC.\n// 2. Combine — combine(state_ids, params) -> finalize_state_ids (bytes[]),\n// once on the coordinator. Driven by `table_buffering_combine`.\n// 3. Source — finalize(params, fid, state, out) producer-mode streaming,\n// one batch per tick. Driven by an init() stream with\n// phase=TABLE_BUFFERING_FINALIZE.\n//\n// CROSS-PROCESS INVARIANT: state written in process() that finalize() reads\n// MUST live in cross-process storage scoped by execution_id (BoundStorage).\n// The Source phase may route a finalize_state_id to a worker process that\n// did NOT run the corresponding process() calls.\n\nimport {\n type VgiSchema,\n schema,\n type VgiDataType,\n type VgiBatch,\n nullType,\n} from \"../arrow/index.js\";\nimport type { OutputCollector } from \"@query-farm/vgi-rpc\";\nimport { DEFAULT_MAX_WORKERS, TableInOutPhase } from \"../types.js\";\nimport type {\n BindRequest,\n BindResponse,\n InitRequest,\n GlobalInitResponse,\n TableFunctionCardinalityRequest,\n} from \"../protocol/types.js\";\nimport type { TableCardinality } from \"../types.js\";\nimport type {\n VgiFunction,\n FunctionMeta,\n StreamHandlers,\n FunctionExample,\n} from \"./types.js\";\nimport type { ArgumentConstraints, ArgumentSpec } from \"../arguments/argument-spec.js\";\nimport {\n assertArrowType,\n assertArrowTypes,\n constraintSpecFields,\n validateConstConstraints,\n} from \"../arguments/argument-spec.js\";\nimport { batchToScalarDict, batchToSecretDict, projectSchema } from \"../util/arrow/index.js\";\nimport { batchFromColumns, readCanonicalValue } from \"../arrow/index.js\";\nimport { codecFor } from \"../arrow/codec/registry.js\";\nimport {\n deserializeFilters,\n FilteringOutputCollector,\n type PushdownFilters,\n} from \"../filter-pushdown/index.js\";\nimport { FunctionStability } from \"../types.js\";\nimport { BoundStorage, storage as defaultStorage, FrameworkNS } from \"./storage.js\";\nimport {\n serializeInitRequest,\n deserializeInitRequest,\n serializeGlobalInitResponse,\n} from \"../protocol/serialize.js\";\nimport { serializeBatch, deserializeBatch } from \"../util/arrow/index.js\";\n\n// ============================================================================\n// Parameter bundles\n// ============================================================================\n\nexport interface TableBufferingBindParams<TArgs = Record<string, any>> {\n args: TArgs;\n bindCall: BindRequest;\n settings: Record<string, any>;\n secrets: Record<string, Record<string, any>>;\n /** True on the second bind pass, after the connector resolved the secrets\n * requested via the onBind `lookupSecret*` return fields on the first pass. */\n resolvedSecretsProvided: boolean;\n /** Resolved names aligned with the complete logical argument order. */\n argumentNames?: (string | null)[] | null;\n}\n\nexport interface TableBufferingParams<TArgs = Record<string, any>> {\n args: TArgs;\n initCall: InitRequest;\n outputSchema: VgiSchema;\n settings: Record<string, any>;\n secrets: Record<string, Record<string, any>>;\n /** Shared cross-process storage scoped by execution_id. */\n storage: BoundStorage;\n /** Stable across coordinator + secondary workers for one DuckDB execution. */\n executionId: Uint8Array;\n /** Catalog attach identity (plaintext bytes). */\n attachId: Uint8Array;\n /** Hex/raw VGI transaction id, or null. */\n transactionId: Uint8Array | null;\n function_name: string;\n /** Per-chunk batch_index when requiresInputBatchIndex=true; else null. */\n batchIndex: number | null;\n /** In-band log sink for the unary process()/combine() RPCs. */\n clientLog: (level: string, message: string) => void;\n}\n\n// ============================================================================\n// Functional API config\n// ============================================================================\n\nexport interface TableBufferingConfig<\n TArgs = Record<string, any>,\n TState = any,\n> {\n name: string;\n description?: string;\n args?: Record<string, VgiDataType>;\n namedArgs?: Record<string, VgiDataType>;\n argDefaults?: Record<string, any>;\n /** Authoritative typed defaults: one row, defaulted parameters only. */\n parameterDefaultValues?: VgiBatch | null;\n /** Argument descriptions keyed by argument name. */\n argDocs?: Record<string, string>;\n /** Discovery constraints, also enforced for scalar arguments at bind. */\n argConstraints?: Record<string, ArgumentConstraints>;\n /** Bind: default passes through input schema. May be async. Return non-empty\n * `lookupSecret*` lists on the first pass to request DuckDB secrets; the\n * connector then re-binds with `resolvedSecretsProvided` and the resolved\n * values are available in the process/finalize params' `secrets`. */\n onBind?: (params: TableBufferingBindParams<TArgs>) =>\n | {\n outputSchema: VgiSchema;\n opaqueData?: Uint8Array;\n lookupSecretTypes?: string[];\n lookupScopes?: string[];\n lookupNames?: string[];\n }\n | Promise<{\n outputSchema: VgiSchema;\n opaqueData?: Uint8Array;\n lookupSecretTypes?: string[];\n lookupScopes?: string[];\n lookupNames?: string[];\n }>;\n /** Sink: ingest one batch, return an opaque state_id. */\n process: (\n batch: VgiBatch,\n params: TableBufferingParams<TArgs>,\n ) => Uint8Array | Promise<Uint8Array>;\n /** Combine: group/merge state_ids, return finalize_state_ids. */\n combine: (\n stateIds: Uint8Array[],\n params: TableBufferingParams<TArgs>,\n ) => Uint8Array[] | Promise<Uint8Array[]>;\n /** Build the initial per-tick finalize state for a finalize_state_id. */\n initialFinalizeState?: (\n finalizeStateId: Uint8Array,\n params: TableBufferingParams<TArgs>,\n ) => TState | Promise<TState>;\n /** Source tick: emit one batch via out.emit / signal EOS via out.finish. */\n finalize: (\n params: TableBufferingParams<TArgs>,\n finalizeStateId: Uint8Array,\n state: TState,\n out: OutputCollector,\n ) => void | Promise<void>;\n cardinality?: (\n params: TableBufferingBindParams<TArgs>,\n ) => TableCardinality | Promise<TableCardinality>;\n // Metadata\n projectionPushdown?: boolean;\n filterPushdown?: boolean;\n autoApplyFilters?: boolean;\n /** Force ParallelSink=false in the C++ operator (single-thread ingest). */\n sinkOrderDependent?: boolean;\n /** Force serial Source drain in finalize_queue order. */\n sourceOrderDependent?: boolean;\n /** Thread DuckDB's per-chunk batch_index into every process() call. */\n requiresInputBatchIndex?: boolean;\n stability?: FunctionStability;\n examples?: FunctionExample[];\n categories?: string[];\n tags?: Record<string, string>;\n maxWorkers?: number;\n requiredSettings?: string[];\n requiredSecrets?: string[];\n}\n\n/**\n * A table_buffering VgiFunction also carries its callback config so the\n * protocol's unary handlers (process/combine/destructor) can reach it.\n */\nexport interface TableBufferingVgiFunction extends VgiFunction {\n bufferingConfig: TableBufferingConfig<any, any>;\n bufferingExtractArgs: (request: BindRequest) => any;\n}\n\nexport function defineTableBufferingFunction<\n TArgs = Record<string, any>,\n TState = any,\n>(config: TableBufferingConfig<TArgs, TState>): TableBufferingVgiFunction {\n assertArrowTypes((config as any).args, `defineTableBufferingFunction(\"${config.name}\"): args`);\n\n if (config.sinkOrderDependent && config.requiresInputBatchIndex) {\n throw new Error(\n `${config.name}: sinkOrderDependent and requiresInputBatchIndex are ` +\n `mutually exclusive — single-thread sink already orders input.`,\n );\n }\n\n const specs: ArgumentSpec[] = [];\n let posIdx = 0;\n if (config.args) {\n for (const [name, type] of Object.entries(config.args)) {\n specs.push({\n name,\n position: posIdx++,\n arrowType: type,\n doc: config.argDocs?.[name],\n ...constraintSpecFields(\n config.argConstraints?.[name],\n config.argDefaults?.[name],\n ),\n });\n }\n }\n specs.push({\n name: \"data\",\n position: posIdx++,\n arrowType: nullType(),\n isTableInput: true,\n });\n if (config.namedArgs) {\n for (const [name, type] of Object.entries(config.namedArgs)) {\n specs.push({\n name,\n position: name,\n arrowType: type,\n doc: config.argDocs?.[name],\n ...constraintSpecFields(\n config.argConstraints?.[name],\n config.argDefaults?.[name],\n ),\n });\n }\n }\n\n const meta: FunctionMeta = {\n name: config.name,\n description: config.description,\n stability: config.stability,\n projectionPushdown: config.projectionPushdown,\n filterPushdown: config.filterPushdown,\n autoApplyFilters: config.autoApplyFilters,\n examples: config.examples,\n categories: config.categories,\n tags: config.tags,\n parameterDefaultValues: config.parameterDefaultValues,\n maxWorkers: config.maxWorkers,\n requiredSettings: config.requiredSettings,\n requiredSecrets: config.requiredSecrets,\n // The Source phase always runs (it's how output is produced), so a\n // table_buffering function always advertises has_finalize.\n hasFinalize: true,\n sinkOrderDependent: config.sinkOrderDependent,\n sourceOrderDependent: config.sourceOrderDependent,\n requiresInputBatchIndex: config.requiresInputBatchIndex,\n };\n\n function extractArgs(request: BindRequest): TArgs {\n const args: Record<string, any> = {};\n for (const spec of specs) {\n if (spec.isTableInput) continue;\n const defaultVal =\n config.argDefaults?.[spec.name] !== undefined\n ? config.argDefaults[spec.name]\n : undefined;\n let val = request.arguments.get(spec.position, defaultVal);\n if (typeof val === \"bigint\") val = Number(val);\n const constraints = config.argConstraints?.[spec.name];\n if (constraints) validateConstConstraints(spec.name, constraints, val);\n args[spec.name] = val;\n }\n return args as TArgs;\n }\n\n const func: TableBufferingVgiFunction = {\n kind: \"table_buffering\" as any,\n meta,\n argumentSpecs: specs,\n bufferingConfig: config as TableBufferingConfig<any, any>,\n bufferingExtractArgs: extractArgs as any,\n\n async bind(request: BindRequest): Promise<BindResponse> {\n if (config.onBind) {\n const args = extractArgs(request);\n const settings = batchToScalarDict(request.settings);\n const secrets = batchToSecretDict(request.secrets);\n const result = await config.onBind({\n args,\n bindCall: request,\n settings,\n secrets,\n resolvedSecretsProvided: request.resolved_secrets_provided ?? false,\n argumentNames: request.argument_names ?? null,\n });\n return {\n output_schema: result.outputSchema,\n opaque_data: result.opaqueData ?? null,\n lookup_secret_types: result.lookupSecretTypes,\n lookup_scopes: result.lookupScopes,\n lookup_names: result.lookupNames,\n };\n }\n return {\n output_schema: request.input_schema ?? schema([]),\n opaque_data: null,\n };\n },\n\n async globalInit(request: InitRequest): Promise<GlobalInitResponse> {\n // Mint a stable execution_id for the primary; secondary inits reuse it.\n let executionId: Uint8Array;\n if (request.execution_id) {\n executionId = request.execution_id;\n } else {\n executionId = new Uint8Array(16);\n crypto.getRandomValues(executionId);\n }\n const response: GlobalInitResponse = {\n max_workers: config.maxWorkers ?? DEFAULT_MAX_WORKERS,\n execution_id: executionId,\n opaque_data: null,\n };\n\n // On the sink-side init, persist init metadata so any pool worker can\n // cold-load it when serving subsequent process()/combine() unary RPCs\n // (which carry no init context themselves). Mirrors Python's\n // FrameworkNS.BUFFERING_INIT state_put.\n if (request.phase === TableInOutPhase.TABLE_BUFFERING) {\n const bound = new BoundStorage(defaultStorage, executionId);\n await bound.statePut(\n FrameworkNS.BUFFERING_INIT,\n BoundStorage.packIntKey(-1),\n encodeBufferingInit(request, response),\n );\n }\n return response;\n },\n\n createStreamHandlers(\n request: InitRequest,\n response: GlobalInitResponse,\n _accumulatedState?: any,\n ): StreamHandlers {\n const args = extractArgs(request.bind_call);\n const settings = batchToScalarDict(request.bind_call.settings);\n const secrets = batchToSecretDict(request.bind_call.secrets);\n\n const projIds = request.projection_ids && meta.projectionPushdown\n ? request.projection_ids\n : null;\n const outputSchema = projIds\n ? projectSchema(projIds, request.output_schema)\n : request.output_schema;\n\n const pushdownFilters = request.pushdown_filters\n ? deserializeFilters(request.pushdown_filters, {\n outputSchema: request.output_schema,\n joinKeyBatches: request.join_keys,\n extensionFunctions: meta.additionalFilterFunctions,\n runtimeAlgorithms: meta.runtimeFilterAlgorithms,\n evaluationContexts: meta.filterEvaluationContexts,\n })\n : undefined;\n\n const bound = new BoundStorage(\n defaultStorage,\n response.execution_id ?? new Uint8Array(16),\n );\n\n const params: TableBufferingParams<TArgs> = {\n args,\n initCall: request,\n outputSchema,\n settings,\n secrets,\n storage: bound,\n executionId: response.execution_id,\n attachId: request.bind_call.attach_opaque_data ?? new Uint8Array(0),\n transactionId: request.bind_call.transaction_opaque_data ?? null,\n function_name: request.bind_call.function_name,\n batchIndex: null,\n clientLog: () => {},\n };\n\n if (request.phase === TableInOutPhase.TABLE_BUFFERING_FINALIZE) {\n // SOURCE phase: producer-mode streaming, one batch per tick.\n const finalizeStateId = request.finalize_state_id ?? new Uint8Array(0);\n return {\n outputSchema,\n producerInit: () => ({ state: { __tbf_uninit: true } as any }),\n producerFn: async (\n pState: { state: any },\n out: OutputCollector,\n ) => {\n // Lazily build the user's per-tick state on the first tick.\n // pState.state round-trips through the HTTP exchange-state token\n // between ticks; `__tbf_uninit` marks \"not yet initialized\".\n let userState: any = pState.state;\n if (userState && userState.__tbf_uninit) {\n userState = config.initialFinalizeState\n ? await config.initialFinalizeState(finalizeStateId, params)\n : null;\n pState.state = userState ?? null;\n } else {\n userState = pState.state;\n }\n\n // Narrow each emitted (full-width) buffered batch to the projected\n // output schema, then auto-apply pushdown filters. Mirrors the\n // streaming TableFunctionGenerator path: project first, filter\n // second.\n let wrappedOut: OutputCollector = projIds\n ? makeProjectingCollector(out, outputSchema)\n : out;\n if (config.autoApplyFilters && pushdownFilters) {\n wrappedOut = new FilteringOutputCollector(wrappedOut, pushdownFilters) as unknown as OutputCollector;\n }\n\n await config.finalize(params, finalizeStateId, userState, wrappedOut);\n\n // Persist the (possibly mutated) user state for the next tick.\n pState.state = userState ?? null;\n },\n };\n }\n\n // SINK-init phase (TABLE_BUFFERING): the C++ side opens the init stream\n // in exchange mode, immediately sends EOS, and drains output to EOS.\n // We produce nothing — the real sink traffic is the separate unary\n // table_buffering_process / _combine RPCs.\n return {\n outputSchema,\n inputSchema: request.bind_call.input_schema ?? undefined,\n exchangeInit: () => ({ state: null }),\n exchangeFn: async (\n _state: any,\n _input: VgiBatch,\n _out: OutputCollector,\n ) => {\n // No-op: no per-batch output on the sink-init stream.\n },\n };\n },\n };\n\n if (config.cardinality) {\n func.cardinality = async (request: TableFunctionCardinalityRequest) => {\n const args = extractArgs(request.bind_call);\n const settings = batchToScalarDict(request.bind_call.settings);\n const secrets = batchToSecretDict(request.bind_call.secrets);\n return config.cardinality!({\n args,\n bindCall: request.bind_call,\n settings,\n secrets,\n resolvedSecretsProvided: request.bind_call.resolved_secrets_provided ?? false,\n });\n };\n }\n\n return func;\n}\n\n// Wrap an OutputCollector so each emitted batch is projected-by-name to the\n// target (narrowed) output schema before forwarding. Mirrors table.ts's\n// makeProjectingCollector — buffered batches are stored full-width, so the\n// Source phase narrows them per-tick to the projected columns.\nfunction makeProjectingCollector(\n inner: OutputCollector,\n targetSchema: VgiSchema,\n): OutputCollector {\n function alreadyMatches(batch: VgiBatch): boolean {\n if (batch.schema.fields.length !== targetSchema.fields.length) return false;\n for (let i = 0; i < targetSchema.fields.length; i++) {\n if (batch.schema.fields[i].name !== targetSchema.fields[i].name) return false;\n }\n return true;\n }\n function project(batch: VgiBatch): VgiBatch {\n if (alreadyMatches(batch)) return batch;\n const cols: Record<string, any[]> = {};\n for (const f of targetSchema.fields) {\n const src = batch.getChild(f.name);\n if (src) {\n // Canonical read -> rich so the rebuild goes through the codec path\n // (backend-agnostic, lossless) rather than the raw `.get(i)`.\n const type = f.type as VgiDataType;\n const codec = codecFor(type);\n const arr: any[] = [];\n for (let i = 0; i < batch.numRows; i++) {\n arr.push(codec.canonicalToRich(readCanonicalValue(type, src, i)));\n }\n cols[f.name] = arr;\n } else {\n cols[f.name] = new Array(batch.numRows).fill(null);\n }\n }\n return batchFromColumns(cols, targetSchema);\n }\n return new Proxy(inner, {\n get(target, prop, receiver) {\n if (prop === \"emit\") {\n return function (\n this: OutputCollector,\n batchOrColumns: VgiBatch | Record<string, any[]>,\n metadata?: Map<string, string>,\n ) {\n if (batchOrColumns && typeof (batchOrColumns as any).getChild === \"function\") {\n return (target as any).emit(project(batchOrColumns as VgiBatch), metadata);\n }\n return (target as any).emit(batchOrColumns, metadata);\n };\n }\n const v = Reflect.get(target, prop, receiver);\n return typeof v === \"function\" ? v.bind(target) : v;\n },\n });\n}\n\n// ============================================================================\n// Init-metadata persistence (mirrors Python _encode/_decode_table_buffering_init)\n// ============================================================================\n\nexport function encodeBufferingInit(\n request: InitRequest,\n response: GlobalInitResponse,\n): Uint8Array {\n // Serialize the InitRequest batch and the GlobalInitResponse so any pool\n // worker can cold-rebuild params when serving a process()/combine() RPC.\n const initBatch = serializeInitRequest(request);\n const initBytes = serializeBatch(initBatch);\n const respBatch = serializeGlobalInitResponse(response);\n // GlobalInitResponse serializer returns a plain dict; rebuild a 1-row batch.\n // Simpler: re-serialize as a length-prefixed pair of byte blobs.\n const respBytes = encodeGlobalInitResponse(respBatch);\n return concatLenPrefixed([initBytes, respBytes]);\n}\n\nexport function decodeBufferingInit(\n payload: Uint8Array,\n): { request: InitRequest; response: GlobalInitResponse } {\n const [initBytes, respBytes] = splitLenPrefixed(payload, 2);\n const initBatch = deserializeBatch(initBytes);\n const initDict = batchToScalarDict(initBatch);\n const request = deserializeInitRequest(initDict);\n const response = decodeGlobalInitResponse(respBytes);\n return { request, response };\n}\n\nfunction encodeGlobalInitResponse(dict: Record<string, any>): Uint8Array {\n // Encode { execution_id, opaque_data, max_workers } as length-prefixed blobs.\n const eid: Uint8Array = dict.execution_id ?? new Uint8Array(0);\n const opaque: Uint8Array | null = dict.opaque_data ?? null;\n const maxWorkers = Number(dict.max_workers ?? 1);\n const mwBuf = new Uint8Array(8);\n new DataView(mwBuf.buffer).setBigInt64(0, BigInt(maxWorkers), true);\n return concatLenPrefixed([eid, opaque ?? new Uint8Array(0), mwBuf]);\n}\n\nfunction decodeGlobalInitResponse(bytes: Uint8Array): GlobalInitResponse {\n const [eid, opaque, mwBuf] = splitLenPrefixed(bytes, 3);\n const maxWorkers = Number(new DataView(mwBuf.buffer, mwBuf.byteOffset, 8).getBigInt64(0, true));\n return {\n execution_id: eid,\n opaque_data: opaque.length > 0 ? opaque : null,\n max_workers: maxWorkers,\n };\n}\n\nfunction concatLenPrefixed(parts: Uint8Array[]): Uint8Array {\n let total = 0;\n for (const p of parts) total += 4 + p.length;\n const out = new Uint8Array(total);\n const dv = new DataView(out.buffer);\n let off = 0;\n for (const p of parts) {\n dv.setUint32(off, p.length, true);\n off += 4;\n out.set(p, off);\n off += p.length;\n }\n return out;\n}\n\nfunction splitLenPrefixed(buf: Uint8Array, count: number): Uint8Array[] {\n const dv = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);\n const parts: Uint8Array[] = [];\n let off = 0;\n for (let i = 0; i < count; i++) {\n const len = dv.getUint32(off, true);\n off += 4;\n parts.push(buf.subarray(off, off + len));\n off += len;\n }\n return parts;\n}\n",
|
|
54
|
+
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Table sink+source (\"table_buffering\") function implementation.\n//\n// Three phases, mirroring the C++ PhysicalVgiTableBuffering Sink+Source\n// operator:\n// 1. Sink — process(batch, params) -> state_id (bytes), one per input\n// batch. Driven by the unary `table_buffering_process` RPC.\n// 2. Combine — combine(state_ids, params) -> finalize_state_ids (bytes[]),\n// once on the coordinator. Driven by `table_buffering_combine`.\n// 3. Source — finalize(params, fid, state, out) producer-mode streaming,\n// one batch per tick. Driven by an init() stream with\n// phase=TABLE_BUFFERING_FINALIZE.\n//\n// CROSS-PROCESS INVARIANT: state written in process() that finalize() reads\n// MUST live in cross-process storage scoped by execution_id (BoundStorage).\n// The Source phase may route a finalize_state_id to a worker process that\n// did NOT run the corresponding process() calls.\n\nimport {\n type VgiSchema,\n schema,\n type VgiDataType,\n type VgiBatch,\n nullType,\n} from \"../arrow/index.js\";\nimport type { OutputCollector } from \"@query-farm/vgi-rpc\";\nimport { DEFAULT_MAX_WORKERS, TableInOutPhase } from \"../types.js\";\nimport type {\n BindRequest,\n BindResponse,\n InitRequest,\n GlobalInitResponse,\n TableFunctionCardinalityRequest,\n} from \"../protocol/types.js\";\nimport type { TableCardinality } from \"../types.js\";\nimport type {\n VgiFunction,\n FunctionMeta,\n StreamHandlers,\n FunctionExample,\n} from \"./types.js\";\nimport type { ArgumentConstraints, ArgumentSpec } from \"../arguments/argument-spec.js\";\nimport {\n assertArrowType,\n assertArrowTypes,\n constraintSpecFields,\n validateConstConstraints,\n} from \"../arguments/argument-spec.js\";\nimport { batchToScalarDict, batchToSecretDict, projectSchema } from \"../util/arrow/index.js\";\nimport { batchFromColumns, readCanonicalValue } from \"../arrow/index.js\";\nimport { codecFor } from \"../arrow/codec/registry.js\";\nimport {\n deserializeFilters,\n FilteringOutputCollector,\n type PushdownFilters,\n} from \"../filter-pushdown/index.js\";\nimport { FunctionStability } from \"../types.js\";\nimport { BoundStorage, storage as defaultStorage, FrameworkNS } from \"./storage.js\";\nimport {\n serializeInitRequest,\n deserializeInitRequest,\n serializeGlobalInitResponse,\n} from \"../protocol/serialize.js\";\nimport { serializeBatch, deserializeBatch } from \"../util/arrow/index.js\";\n\n// ============================================================================\n// Parameter bundles\n// ============================================================================\n\nexport interface TableBufferingBindParams<TArgs = Record<string, any>> {\n args: TArgs;\n bindCall: BindRequest;\n settings: Record<string, any>;\n secrets: Record<string, Record<string, any>>;\n /** True on the second bind pass, after the connector resolved the secrets\n * requested via the onBind `lookupSecret*` return fields on the first pass. */\n resolvedSecretsProvided: boolean;\n /** Resolved names aligned with the complete logical argument order. */\n argumentNames?: (string | null)[] | null;\n}\n\nexport interface TableBufferingParams<TArgs = Record<string, any>> {\n args: TArgs;\n initCall: InitRequest;\n outputSchema: VgiSchema;\n settings: Record<string, any>;\n secrets: Record<string, Record<string, any>>;\n /** Shared cross-process storage scoped by execution_id. */\n storage: BoundStorage;\n /** Stable across coordinator + secondary workers for one DuckDB execution. */\n executionId: Uint8Array;\n /** Catalog attach identity (plaintext bytes). */\n attachId: Uint8Array;\n /** Hex/raw VGI transaction id, or null. */\n transactionId: Uint8Array | null;\n function_name: string;\n /** Per-chunk batch_index when requiresInputBatchIndex=true; else null. */\n batchIndex: number | null;\n /** In-band log sink for the unary process()/combine() RPCs. */\n clientLog: (level: string, message: string) => void;\n}\n\n// ============================================================================\n// Functional API config\n// ============================================================================\n\nexport interface TableBufferingConfig<\n TArgs = Record<string, any>,\n TState = any,\n> {\n name: string;\n description?: string;\n args?: Record<string, VgiDataType>;\n namedArgs?: Record<string, VgiDataType>;\n argDefaults?: Record<string, any>;\n /** Authoritative typed defaults: one row, defaulted parameters only. */\n parameterDefaultValues?: VgiBatch | null;\n /** Argument descriptions keyed by argument name. */\n argDocs?: Record<string, string>;\n /** Discovery constraints, also enforced for scalar arguments at bind. */\n argConstraints?: Record<string, ArgumentConstraints>;\n /** Bind: default passes through input schema. May be async. Return non-empty\n * `lookupSecret*` lists on the first pass to request DuckDB secrets; the\n * connector then re-binds with `resolvedSecretsProvided` and the resolved\n * values are available in the process/finalize params' `secrets`. */\n onBind?: (params: TableBufferingBindParams<TArgs>) =>\n | {\n outputSchema: VgiSchema;\n opaqueData?: Uint8Array;\n lookupSecretTypes?: string[];\n lookupScopes?: string[];\n lookupNames?: string[];\n }\n | Promise<{\n outputSchema: VgiSchema;\n opaqueData?: Uint8Array;\n lookupSecretTypes?: string[];\n lookupScopes?: string[];\n lookupNames?: string[];\n }>;\n /** Sink: ingest one batch, return an opaque state_id. */\n process: (\n batch: VgiBatch,\n params: TableBufferingParams<TArgs>,\n ) => Uint8Array | Promise<Uint8Array>;\n /** Combine: group/merge state_ids, return finalize_state_ids. */\n combine: (\n stateIds: Uint8Array[],\n params: TableBufferingParams<TArgs>,\n ) => Uint8Array[] | Promise<Uint8Array[]>;\n /** Build the initial per-tick finalize state for a finalize_state_id. */\n initialFinalizeState?: (\n finalizeStateId: Uint8Array,\n params: TableBufferingParams<TArgs>,\n ) => TState | Promise<TState>;\n /** Source tick: emit one batch via out.emit / signal EOS via out.finish. */\n finalize: (\n params: TableBufferingParams<TArgs>,\n finalizeStateId: Uint8Array,\n state: TState,\n out: OutputCollector,\n ) => void | Promise<void>;\n cardinality?: (\n params: TableBufferingBindParams<TArgs>,\n ) => TableCardinality | Promise<TableCardinality>;\n // Metadata\n projectionPushdown?: boolean;\n filterPushdown?: boolean;\n autoApplyFilters?: boolean;\n /** Force ParallelSink=false in the C++ operator (single-thread ingest). */\n sinkOrderDependent?: boolean;\n /** Force serial Source drain in finalize_queue order. */\n sourceOrderDependent?: boolean;\n /** Thread DuckDB's per-chunk batch_index into every process() call. */\n requiresInputBatchIndex?: boolean;\n stability?: FunctionStability;\n examples?: FunctionExample[];\n categories?: string[];\n tags?: Record<string, string>;\n maxWorkers?: number;\n requiredSettings?: string[];\n requiredSecrets?: string[];\n}\n\n/**\n * A table_buffering VgiFunction also carries its callback config so the\n * protocol's unary handlers (process/combine/destructor) can reach it.\n */\nexport interface TableBufferingVgiFunction extends VgiFunction {\n bufferingConfig: TableBufferingConfig<any, any>;\n bufferingExtractArgs: (request: BindRequest) => any;\n}\n\nexport function defineTableBufferingFunction<\n TArgs = Record<string, any>,\n TState = any,\n>(config: TableBufferingConfig<TArgs, TState>): TableBufferingVgiFunction {\n assertArrowTypes((config as any).args, `defineTableBufferingFunction(\"${config.name}\"): args`);\n\n if (config.sinkOrderDependent && config.requiresInputBatchIndex) {\n throw new Error(\n `${config.name}: sinkOrderDependent and requiresInputBatchIndex are ` +\n `mutually exclusive — single-thread sink already orders input.`,\n );\n }\n\n const specs: ArgumentSpec[] = [];\n let posIdx = 0;\n if (config.args) {\n for (const [name, type] of Object.entries(config.args)) {\n specs.push({\n name,\n position: posIdx++,\n arrowType: type,\n doc: config.argDocs?.[name],\n ...constraintSpecFields(\n config.argConstraints?.[name],\n config.argDefaults?.[name],\n ),\n });\n }\n }\n specs.push({\n name: \"data\",\n position: posIdx++,\n arrowType: nullType(),\n isTableInput: true,\n });\n if (config.namedArgs) {\n for (const [name, type] of Object.entries(config.namedArgs)) {\n specs.push({\n name,\n position: name,\n arrowType: type,\n doc: config.argDocs?.[name],\n ...constraintSpecFields(\n config.argConstraints?.[name],\n config.argDefaults?.[name],\n ),\n });\n }\n }\n\n const meta: FunctionMeta = {\n name: config.name,\n description: config.description,\n stability: config.stability,\n projectionPushdown: config.projectionPushdown,\n filterPushdown: config.filterPushdown,\n autoApplyFilters: config.autoApplyFilters,\n examples: config.examples,\n categories: config.categories,\n tags: config.tags,\n parameterDefaultValues: config.parameterDefaultValues,\n maxWorkers: config.maxWorkers,\n requiredSettings: config.requiredSettings,\n requiredSecrets: config.requiredSecrets,\n // The Source phase always runs (it's how output is produced), so a\n // table_buffering function always advertises has_finalize.\n hasFinalize: true,\n sinkOrderDependent: config.sinkOrderDependent,\n sourceOrderDependent: config.sourceOrderDependent,\n requiresInputBatchIndex: config.requiresInputBatchIndex,\n };\n\n function extractArgs(request: BindRequest): TArgs {\n const args: Record<string, any> = {};\n for (const spec of specs) {\n if (spec.isTableInput) continue;\n const defaultVal =\n config.argDefaults?.[spec.name] !== undefined\n ? config.argDefaults[spec.name]\n : undefined;\n let val = request.arguments.get(spec.position, defaultVal);\n if (typeof val === \"bigint\") val = Number(val);\n const constraints = config.argConstraints?.[spec.name];\n if (constraints) validateConstConstraints(spec.name, constraints, val);\n args[spec.name] = val;\n }\n return args as TArgs;\n }\n\n const func: TableBufferingVgiFunction = {\n kind: \"table_buffering\" as any,\n meta,\n argumentSpecs: specs,\n bufferingConfig: config as TableBufferingConfig<any, any>,\n bufferingExtractArgs: extractArgs as any,\n\n async bind(request: BindRequest): Promise<BindResponse> {\n if (config.onBind) {\n const args = extractArgs(request);\n const settings = batchToScalarDict(request.settings);\n const secrets = batchToSecretDict(request.secrets);\n const result = await config.onBind({\n args,\n bindCall: request,\n settings,\n secrets,\n resolvedSecretsProvided: request.resolved_secrets_provided ?? false,\n argumentNames: request.argument_names ?? null,\n });\n return {\n output_schema: result.outputSchema,\n opaque_data: result.opaqueData ?? null,\n lookup_secret_types: result.lookupSecretTypes,\n lookup_scopes: result.lookupScopes,\n lookup_names: result.lookupNames,\n };\n }\n return {\n output_schema: request.input_schema ?? schema([]),\n opaque_data: null,\n };\n },\n\n async globalInit(request: InitRequest): Promise<GlobalInitResponse> {\n // Mint a stable execution_id for the primary; secondary inits reuse it.\n let executionId: Uint8Array;\n if (request.execution_id) {\n executionId = request.execution_id;\n } else {\n executionId = new Uint8Array(16);\n crypto.getRandomValues(executionId);\n }\n const response: GlobalInitResponse = {\n max_workers: config.maxWorkers ?? DEFAULT_MAX_WORKERS,\n execution_id: executionId,\n opaque_data: null,\n };\n\n // On the sink-side init, persist init metadata so any pool worker can\n // cold-load it when serving subsequent process()/combine() unary RPCs\n // (which carry no init context themselves). Mirrors Python's\n // FrameworkNS.BUFFERING_INIT state_put.\n if (request.phase === TableInOutPhase.TABLE_BUFFERING) {\n const bound = new BoundStorage(defaultStorage, executionId);\n await bound.statePut(\n FrameworkNS.BUFFERING_INIT,\n BoundStorage.packIntKey(-1),\n encodeBufferingInit(request, response),\n );\n }\n return response;\n },\n\n createStreamHandlers(\n request: InitRequest,\n response: GlobalInitResponse,\n ): StreamHandlers {\n const args = extractArgs(request.bind_call);\n const settings = batchToScalarDict(request.bind_call.settings);\n const secrets = batchToSecretDict(request.bind_call.secrets);\n\n const projIds = request.projection_ids && meta.projectionPushdown\n ? request.projection_ids\n : null;\n const outputSchema = projIds\n ? projectSchema(projIds, request.output_schema)\n : request.output_schema;\n\n const pushdownFilters = request.pushdown_filters\n ? deserializeFilters(request.pushdown_filters, {\n outputSchema: request.output_schema,\n joinKeyBatches: request.join_keys,\n extensionFunctions: meta.additionalFilterFunctions,\n runtimeAlgorithms: meta.runtimeFilterAlgorithms,\n evaluationContexts: meta.filterEvaluationContexts,\n })\n : undefined;\n\n const bound = new BoundStorage(\n defaultStorage,\n response.execution_id ?? new Uint8Array(16),\n );\n\n const params: TableBufferingParams<TArgs> = {\n args,\n initCall: request,\n outputSchema,\n settings,\n secrets,\n storage: bound,\n executionId: response.execution_id,\n attachId: request.bind_call.attach_opaque_data ?? new Uint8Array(0),\n transactionId: request.bind_call.transaction_opaque_data ?? null,\n function_name: request.bind_call.function_name,\n batchIndex: null,\n clientLog: () => {},\n };\n\n if (request.phase === TableInOutPhase.TABLE_BUFFERING_FINALIZE) {\n // SOURCE phase: producer-mode streaming, one batch per tick.\n const finalizeStateId = request.finalize_state_id ?? new Uint8Array(0);\n return {\n outputSchema,\n producerInit: () => ({ state: { __tbf_uninit: true } as any }),\n producerFn: async (\n pState: { state: any },\n out: OutputCollector,\n ) => {\n // Lazily build the user's per-tick state on the first tick.\n // pState.state round-trips through the HTTP exchange-state token\n // between ticks; `__tbf_uninit` marks \"not yet initialized\".\n let userState: any = pState.state;\n if (userState && userState.__tbf_uninit) {\n userState = config.initialFinalizeState\n ? await config.initialFinalizeState(finalizeStateId, params)\n : null;\n pState.state = userState ?? null;\n } else {\n userState = pState.state;\n }\n\n // Narrow each emitted (full-width) buffered batch to the projected\n // output schema, then auto-apply pushdown filters. Mirrors the\n // streaming TableFunctionGenerator path: project first, filter\n // second.\n let wrappedOut: OutputCollector = projIds\n ? makeProjectingCollector(out, outputSchema)\n : out;\n if (config.autoApplyFilters && pushdownFilters) {\n wrappedOut = new FilteringOutputCollector(wrappedOut, pushdownFilters) as unknown as OutputCollector;\n }\n\n await config.finalize(params, finalizeStateId, userState, wrappedOut);\n\n // Persist the (possibly mutated) user state for the next tick.\n pState.state = userState ?? null;\n },\n };\n }\n\n // SINK-init phase (TABLE_BUFFERING): the C++ side opens the init stream\n // in exchange mode, immediately sends EOS, and drains output to EOS.\n // We produce nothing — the real sink traffic is the separate unary\n // table_buffering_process / _combine RPCs.\n return {\n outputSchema,\n inputSchema: request.bind_call.input_schema ?? undefined,\n exchangeInit: () => ({ state: null }),\n exchangeFn: async (\n _state: any,\n _input: VgiBatch,\n _out: OutputCollector,\n ) => {\n // No-op: no per-batch output on the sink-init stream.\n },\n };\n },\n };\n\n if (config.cardinality) {\n func.cardinality = async (request: TableFunctionCardinalityRequest) => {\n const args = extractArgs(request.bind_call);\n const settings = batchToScalarDict(request.bind_call.settings);\n const secrets = batchToSecretDict(request.bind_call.secrets);\n return config.cardinality!({\n args,\n bindCall: request.bind_call,\n settings,\n secrets,\n resolvedSecretsProvided: request.bind_call.resolved_secrets_provided ?? false,\n });\n };\n }\n\n return func;\n}\n\n// Wrap an OutputCollector so each emitted batch is projected-by-name to the\n// target (narrowed) output schema before forwarding. Mirrors table.ts's\n// makeProjectingCollector — buffered batches are stored full-width, so the\n// Source phase narrows them per-tick to the projected columns.\nfunction makeProjectingCollector(\n inner: OutputCollector,\n targetSchema: VgiSchema,\n): OutputCollector {\n function alreadyMatches(batch: VgiBatch): boolean {\n if (batch.schema.fields.length !== targetSchema.fields.length) return false;\n for (let i = 0; i < targetSchema.fields.length; i++) {\n if (batch.schema.fields[i].name !== targetSchema.fields[i].name) return false;\n }\n return true;\n }\n function project(batch: VgiBatch): VgiBatch {\n if (alreadyMatches(batch)) return batch;\n const cols: Record<string, any[]> = {};\n for (const f of targetSchema.fields) {\n const src = batch.getChild(f.name);\n if (src) {\n // Canonical read -> rich so the rebuild goes through the codec path\n // (backend-agnostic, lossless) rather than the raw `.get(i)`.\n const type = f.type as VgiDataType;\n const codec = codecFor(type);\n const arr: any[] = [];\n for (let i = 0; i < batch.numRows; i++) {\n arr.push(codec.canonicalToRich(readCanonicalValue(type, src, i)));\n }\n cols[f.name] = arr;\n } else {\n cols[f.name] = new Array(batch.numRows).fill(null);\n }\n }\n return batchFromColumns(cols, targetSchema);\n }\n return new Proxy(inner, {\n get(target, prop, receiver) {\n if (prop === \"emit\") {\n return function (\n this: OutputCollector,\n batchOrColumns: VgiBatch | Record<string, any[]>,\n metadata?: Map<string, string>,\n ) {\n if (batchOrColumns && typeof (batchOrColumns as any).getChild === \"function\") {\n return (target as any).emit(project(batchOrColumns as VgiBatch), metadata);\n }\n return (target as any).emit(batchOrColumns, metadata);\n };\n }\n const v = Reflect.get(target, prop, receiver);\n return typeof v === \"function\" ? v.bind(target) : v;\n },\n });\n}\n\n// ============================================================================\n// Init-metadata persistence (mirrors Python _encode/_decode_table_buffering_init)\n// ============================================================================\n\nexport function encodeBufferingInit(\n request: InitRequest,\n response: GlobalInitResponse,\n): Uint8Array {\n // Serialize the InitRequest batch and the GlobalInitResponse so any pool\n // worker can cold-rebuild params when serving a process()/combine() RPC.\n const initBatch = serializeInitRequest(request);\n const initBytes = serializeBatch(initBatch);\n const respBatch = serializeGlobalInitResponse(response);\n // GlobalInitResponse serializer returns a plain dict; rebuild a 1-row batch.\n // Simpler: re-serialize as a length-prefixed pair of byte blobs.\n const respBytes = encodeGlobalInitResponse(respBatch);\n return concatLenPrefixed([initBytes, respBytes]);\n}\n\nexport function decodeBufferingInit(\n payload: Uint8Array,\n): { request: InitRequest; response: GlobalInitResponse } {\n const [initBytes, respBytes] = splitLenPrefixed(payload, 2);\n const initBatch = deserializeBatch(initBytes);\n const initDict = batchToScalarDict(initBatch);\n const request = deserializeInitRequest(initDict);\n const response = decodeGlobalInitResponse(respBytes);\n return { request, response };\n}\n\nfunction encodeGlobalInitResponse(dict: Record<string, any>): Uint8Array {\n // Encode { execution_id, opaque_data, max_workers } as length-prefixed blobs.\n const eid: Uint8Array = dict.execution_id ?? new Uint8Array(0);\n const opaque: Uint8Array | null = dict.opaque_data ?? null;\n const maxWorkers = Number(dict.max_workers ?? 1);\n const mwBuf = new Uint8Array(8);\n new DataView(mwBuf.buffer).setBigInt64(0, BigInt(maxWorkers), true);\n return concatLenPrefixed([eid, opaque ?? new Uint8Array(0), mwBuf]);\n}\n\nfunction decodeGlobalInitResponse(bytes: Uint8Array): GlobalInitResponse {\n const [eid, opaque, mwBuf] = splitLenPrefixed(bytes, 3);\n const maxWorkers = Number(new DataView(mwBuf.buffer, mwBuf.byteOffset, 8).getBigInt64(0, true));\n return {\n execution_id: eid,\n opaque_data: opaque.length > 0 ? opaque : null,\n max_workers: maxWorkers,\n };\n}\n\nfunction concatLenPrefixed(parts: Uint8Array[]): Uint8Array {\n let total = 0;\n for (const p of parts) total += 4 + p.length;\n const out = new Uint8Array(total);\n const dv = new DataView(out.buffer);\n let off = 0;\n for (const p of parts) {\n dv.setUint32(off, p.length, true);\n off += 4;\n out.set(p, off);\n off += p.length;\n }\n return out;\n}\n\nfunction splitLenPrefixed(buf: Uint8Array, count: number): Uint8Array[] {\n const dv = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);\n const parts: Uint8Array[] = [];\n let off = 0;\n for (let i = 0; i < count; i++) {\n const len = dv.getUint32(off, true);\n off += 4;\n parts.push(buf.subarray(off, off + len));\n off += len;\n }\n return parts;\n}\n",
|
|
52
55
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// SPDX-License-Identifier: LicenseRef-QueryFarm-Source-Available-1.0\n\n/**\n * Generic ArrowSerializableDataclass (ASD) codec.\n *\n * Bridges between typed TS objects (snake_case, matching vgi-python dataclass\n * field names) and Arrow IPC bytes (single-row batch with the dataclass'\n * ARROW_SCHEMA). Used by the generated vgi-client.ts encode<X>/decode<X>\n * wrappers to make the typed client interfaces honest at the wire boundary.\n *\n * Encoding delegates to the facade's `batchFromRows` (which handles the\n * complex types — Decimal/BigInt/List/Map/Struct/Dictionary — uniformly\n * across both arrow-js and flechette backends). Decoding pulls each field's\n * value with `batchToScalarDict`, then runs `normalizeValue` to convert\n * Arrow representations (MapRow, BigInt, etc.) back into plain JS shapes.\n */\n\nimport {\n type VgiSchema,\n type VgiField,\n type VgiDataType,\n isBinary,\n isBool,\n isDictionary,\n isInt,\n isList,\n isMap,\n isStruct,\n batchFromRows,\n serializeBatch,\n deserializeBatch,\n} from \"../arrow/index.js\";\n\n/**\n * Encode a typed object as a single-row Arrow IPC stream using `schema`.\n * Matches Python's `ArrowSerializableDataclass.serialize_to_bytes()`.\n */\nexport function encodeASD(\n schema: VgiSchema,\n obj: Record<string, any>,\n): Uint8Array {\n return serializeBatch(batchFromRows([obj], schema));\n}\n\n/**\n * Decode a single-row Arrow IPC stream into a typed object using `schema`.\n * Matches Python's `ArrowSerializableDataclass.deserialize_from_bytes()`.\n */\nexport function decodeASD<T>(\n schema: VgiSchema,\n bytes: Uint8Array,\n): T {\n const batch = deserializeBatch(bytes);\n if (batch.numRows === 0) {\n const names = schema.fields.map((f) => f.name).join(\",\");\n throw new Error(`decodeASD: empty batch (expected 1 row for ${names})`);\n }\n const out: Record<string, any> = {};\n for (const field of schema.fields) {\n const col = batch.getChild(field.name);\n const raw = col ? col.get(0) : null;\n out[field.name] = normalizeValue(raw, field.type);\n }\n return out as T;\n}\n\n// --------------------------------------------------------------------------- //\n// Decode side: Arrow value -> normalized JS value\n// --------------------------------------------------------------------------- //\n\nfunction normalizeValue(raw: any, type: VgiDataType): any {\n if (raw == null) return null;\n\n if (isList(type)) {\n const childType = (type as any).children[0].type as VgiDataType;\n const out: any[] = [];\n for (const item of raw) out.push(normalizeValue(item, childType));\n return out;\n }\n\n if (isMap(type)) {\n const out: Record<string, string> = {};\n // arrow-js MapRow is iterable of [k,v]; flechette returns [[k,v],...] arrays.\n if (raw[Symbol.iterator]) {\n for (const entry of raw) {\n if (Array.isArray(entry)) {\n out[String(entry[0])] = String(entry[1] ?? \"\");\n } else if (entry && typeof entry === \"object\") {\n const k = entry.key ?? entry[0];\n const v = entry.value ?? entry[1];\n out[String(k)] = v == null ? \"\" : String(v);\n }\n }\n } else if (typeof raw === \"object\") {\n // Plain-object map (flechette without useMap): Object.entries fallback\n for (const [k, v] of Object.entries(raw)) {\n out[String(k)] = v == null ? \"\" : String(v);\n }\n }\n return out;\n }\n\n if (isStruct(type)) {\n const childFields = (type as any).children as VgiField[];\n const out: Record<string, any> = {};\n for (const cf of childFields) {\n out[cf.name] = normalizeValue(raw[cf.name], cf.type);\n }\n return out;\n }\n\n if (isDictionary(type)) {\n return raw == null ? null : String(raw);\n }\n\n if (isBinary(type)) {\n return toUint8Array(raw);\n }\n\n if (isInt(type) && (type as any).bitWidth === 64) {\n // Prefer number when representable; callers that need BigInt can convert.\n if (typeof raw === \"bigint\") {\n if (raw >= BigInt(Number.MIN_SAFE_INTEGER) && raw <= BigInt(Number.MAX_SAFE_INTEGER)) {\n return Number(raw);\n }\n return raw;\n }\n return raw;\n }\n\n if (isBool(type)) {\n return Boolean(raw);\n }\n\n // Utf8, Int8/16/32, Float32/64 — pass through as-is.\n return raw;\n}\n\nfunction toUint8Array(val: any): Uint8Array {\n if (val instanceof Uint8Array) return val;\n if (val instanceof ArrayBuffer) return new Uint8Array(val);\n if (val && val.buffer instanceof ArrayBuffer) {\n return new Uint8Array(val.buffer, val.byteOffset, val.byteLength);\n }\n return new Uint8Array(0);\n}\n",
|
|
53
56
|
"// ============================================================================\n// GENERATED by vgi.codegen.ts_client. DO NOT EDIT BY HAND.\n//\n// Generator: vgi-gen-ts-client v1\n// Content hash: 69731fc31f09\n//\n// To regenerate:\n// uv run --project ~/Development/vgi-python vgi-gen-ts-client \\\n// > ~/Development/vgi-typescript/src/generated/vgi-client.ts\n// ============================================================================\n\nimport { encodeASD, decodeASD } from \"../codec/asd.js\";\nimport {\n CatalogInfoSchema,\n FunctionInfoSchema,\n IndexInfoSchema,\n MacroInfoSchema,\n SchemaInfoSchema,\n TableInfoSchema,\n ViewInfoSchema,\n} from \"./vgi-protocol-schemas.js\";\n\nexport type ArgumentMonotonicity = \"UNKNOWN\" | \"CONSTANT\" | \"NON_DECREASING\" | \"STRICTLY_INCREASING\" | \"NON_INCREASING\" | \"STRICTLY_DECREASING\";\nexport type DistinctDependence = \"DISTINCT_DEPENDENT\" | \"NOT_DISTINCT_DEPENDENT\";\nexport type FunctionStability = \"CONSISTENT\" | \"VOLATILE\" | \"CONSISTENT_WITHIN_QUERY\";\nexport type FunctionType = \"SCALAR\" | \"TABLE\" | \"TABLE_BUFFERING\" | \"AGGREGATE\";\nexport type IndexConstraintType = \"NONE\" | \"UNIQUE\" | \"PRIMARY\";\nexport type InvocationFunctionType = \"AGGREGATE\" | \"SCALAR\" | \"TABLE\" | \"TABLE_BUFFERING\";\nexport type MacroType = \"SCALAR\" | \"TABLE\";\nexport type NullHandling = \"DEFAULT\" | \"SPECIAL\";\nexport type OnConflict = \"ERROR\" | \"IGNORE\" | \"REPLACE\";\nexport type OrderByDirection = \"ASC\" | \"DESC\";\nexport type OrderByNullOrder = \"NULLS_FIRST\" | \"NULLS_LAST\";\nexport type OrderDependence = \"ORDER_DEPENDENT\" | \"NOT_ORDER_DEPENDENT\";\nexport type OrderPreservation = \"PRESERVES_ORDER\" | \"NO_ORDER_GUARANTEE\" | \"FIXED_ORDER\";\nexport type PartitionKind = \"NOT_PARTITIONED\" | \"SINGLE_VALUE_PARTITIONS\" | \"OVERLAPPING_PARTITIONS\" | \"DISJOINT_PARTITIONS\";\nexport type SchemaObjectType = \"TABLE\" | \"VIEW\" | \"SCALAR_FUNCTION\" | \"TABLE_FUNCTION\" | \"AGGREGATE_FUNCTION\" | \"SCALAR_MACRO\" | \"TABLE_MACRO\" | \"INDEX\";\nexport type TableInOutFunctionInitPhase = \"INPUT\" | \"FINALIZE\" | \"TABLE_BUFFERING\" | \"TABLE_BUFFERING_FINALIZE\";\n\nexport interface CatalogDataVersionRelease {\n version: string;\n released_at?: bigint | null;\n summary: string;\n notes_url?: string | null;\n}\n\nexport interface CatalogInfo {\n name: string;\n implementation_version?: string | null;\n data_version_spec?: string | null;\n attach_option_specs: Uint8Array[];\n releases: CatalogDataVersionRelease[];\n source_url?: string | null;\n}\n\nexport interface SchemaInfo {\n comment?: string | null;\n tags: Record<string, string>;\n attach_opaque_data: Uint8Array;\n path: string[];\n estimated_object_count?: Record<string, number> | null;\n}\n\nexport interface TableInfo {\n comment?: string | null;\n tags: Record<string, string>;\n name: string;\n schema_path: string[];\n columns: Uint8Array;\n not_null_constraints: number[];\n unique_constraints: number[][];\n check_constraints: string[];\n primary_key_constraints: number[][];\n foreign_key_constraints: Uint8Array[];\n write_result_modes: Record<string, string>;\n supports_column_statistics: boolean;\n scan_function?: Uint8Array | null;\n insert_function?: Uint8Array | null;\n update_function?: Uint8Array | null;\n delete_function?: Uint8Array | null;\n cardinality_estimate?: number | null;\n cardinality_max?: number | null;\n column_statistics?: Uint8Array | null;\n bind_result?: Uint8Array | null;\n required_filters: string[][];\n}\n\nexport interface ViewInfo {\n comment?: string | null;\n tags: Record<string, string>;\n name: string;\n schema_path: string[];\n definition: string;\n column_comments: Record<string, string>;\n}\n\nexport interface CatalogExample {\n sql: string;\n description: string;\n expected_output?: string | null;\n}\n\nexport interface FilterFunctionCapability {\n namespace: string;\n name: string;\n version: number;\n}\n\nexport interface RuntimeFilterAlgorithmCapability {\n namespace: string;\n name: string;\n version: number;\n}\n\nexport interface EvaluationContextCapability {\n profile: string;\n provider_fingerprint?: string | null;\n}\n\nexport interface SecretLookupEntry {\n secret_type: string;\n scope?: string | null;\n secret_name?: string | null;\n}\n\nexport interface FunctionInfo {\n comment?: string | null;\n tags: Record<string, string>;\n name: string;\n schema_path: string[];\n function_type: FunctionType;\n arguments: Uint8Array;\n output_schema: Uint8Array;\n parameter_default_values?: /** @record-batch */ Uint8Array | null;\n stability?: FunctionStability | null;\n null_handling?: NullHandling | null;\n argument_monotonicity?: ArgumentMonotonicity[] | null;\n description: string;\n examples: CatalogExample[];\n categories: string[];\n projection_pushdown?: boolean | null;\n filter_pushdown?: boolean | null;\n sampling_pushdown?: boolean | null;\n late_materialization?: boolean | null;\n filter_semantic_profiles: string[];\n additional_filter_functions: FilterFunctionCapability[];\n runtime_filter_algorithms: RuntimeFilterAlgorithmCapability[];\n filter_evaluation_contexts: EvaluationContextCapability[];\n order_preservation?: OrderPreservation | null;\n max_workers?: number | null;\n supports_batch_index: boolean;\n supports_splits: boolean;\n filters_exactly_applied: boolean;\n supports_positions: boolean;\n split_token_ttl_seconds?: number | null;\n partition_kind: PartitionKind;\n order_dependent: OrderDependence;\n distinct_dependent: DistinctDependence;\n supports_window: boolean;\n streaming_partitioned: boolean;\n has_finalize: boolean;\n source_order_dependent: boolean;\n sink_order_dependent: boolean;\n requires_input_batch_index: boolean;\n input_from_args: boolean;\n required_settings: string[];\n required_secrets: SecretLookupEntry[];\n}\n\nexport interface MacroInfo {\n comment?: string | null;\n tags: Record<string, string>;\n name: string;\n schema_path: string[];\n macro_type: MacroType;\n parameters: string[];\n parameter_default_values?: /** @record-batch */ Uint8Array | null;\n definition: string;\n arguments_schema?: /** @arrow-schema */ Uint8Array | null;\n}\n\nexport interface IndexInfo {\n comment?: string | null;\n tags: Record<string, string>;\n name: string;\n schema_path: string[];\n table_name: string;\n index_type: string;\n constraint_type: IndexConstraintType;\n expressions: string[];\n options: Record<string, string>;\n}\n\nexport interface AggregateBindRequest {\n function_name: string;\n arguments: /** @vgi-arguments */ Uint8Array;\n input_schema?: /** @arrow-schema */ Uint8Array | null;\n settings?: /** @record-batch */ Uint8Array | null;\n secrets?: /** @record-batch */ Uint8Array | null;\n attach_opaque_data?: Uint8Array | null;\n schema_path?: string[] | null;\n argument_names?: (string | null)[] | null;\n}\n\nexport interface AggregateBindResponse {\n output_schema: /** @arrow-schema */ Uint8Array;\n execution_id: Uint8Array;\n}\n\nexport interface AggregateCombineRequest {\n function_name: string;\n execution_id: Uint8Array;\n merge_batch: Uint8Array;\n attach_opaque_data?: Uint8Array | null;\n schema_path?: string[] | null;\n}\n\nexport interface AggregateCombineResponse {\n}\n\nexport interface AggregateDestructorRequest {\n function_name: string;\n execution_id: Uint8Array;\n group_ids_batch: Uint8Array;\n attach_opaque_data?: Uint8Array | null;\n schema_path?: string[] | null;\n}\n\nexport interface AggregateDestructorResponse {\n}\n\nexport interface AggregateFinalizeRequest {\n function_name: string;\n execution_id: Uint8Array;\n group_ids_batch: Uint8Array;\n output_schema: /** @arrow-schema */ Uint8Array;\n attach_opaque_data?: Uint8Array | null;\n schema_path?: string[] | null;\n}\n\nexport interface AggregateFinalizeResponse {\n result_batch: Uint8Array;\n}\n\nexport interface AggregateStreamingChunkRequest {\n function_name: string;\n execution_id: Uint8Array;\n input_batch: Uint8Array;\n attach_opaque_data?: Uint8Array | null;\n schema_path?: string[] | null;\n}\n\nexport interface AggregateStreamingChunkResponse {\n result_batch: Uint8Array;\n}\n\nexport interface AggregateStreamingCloseRequest {\n function_name: string;\n execution_id: Uint8Array;\n attach_opaque_data?: Uint8Array | null;\n schema_path?: string[] | null;\n}\n\nexport interface AggregateStreamingCloseResponse {\n}\n\nexport interface AggregateStreamingOpenRequest {\n function_name: string;\n arguments: /** @vgi-arguments */ Uint8Array;\n input_schema: /** @arrow-schema */ Uint8Array;\n partition_key_count: number;\n order_key_count: number;\n output_schema: /** @arrow-schema */ Uint8Array;\n settings?: /** @record-batch */ Uint8Array | null;\n secrets?: /** @record-batch */ Uint8Array | null;\n attach_opaque_data?: Uint8Array | null;\n schema_path?: string[] | null;\n}\n\nexport interface AggregateStreamingOpenResponse {\n execution_id: Uint8Array;\n}\n\nexport interface AggregateUpdateRequest {\n function_name: string;\n execution_id: Uint8Array;\n input_batch: Uint8Array;\n attach_opaque_data?: Uint8Array | null;\n schema_path?: string[] | null;\n}\n\nexport interface AggregateUpdateResponse {\n}\n\nexport interface AggregateWindowRequest {\n function_name: string;\n execution_id: Uint8Array;\n partition_id: number;\n rid: number;\n frame_starts: number[];\n frame_ends: number[];\n attach_opaque_data?: Uint8Array | null;\n schema_path?: string[] | null;\n}\n\nexport interface AggregateWindowResponse {\n result_batch: Uint8Array;\n}\n\nexport interface AggregateWindowBatchRequest {\n function_name: string;\n execution_id: Uint8Array;\n partition_id: number;\n row_idx: number;\n count: number;\n frames_per_row: number[];\n frame_starts: number[];\n frame_ends: number[];\n attach_opaque_data?: Uint8Array | null;\n schema_path?: string[] | null;\n}\n\nexport interface AggregateWindowBatchResponse {\n result_batch: Uint8Array;\n}\n\nexport interface AggregateWindowDestructorRequest {\n function_name: string;\n execution_id: Uint8Array;\n partition_id: number;\n attach_opaque_data?: Uint8Array | null;\n schema_path?: string[] | null;\n}\n\nexport interface AggregateWindowDestructorResponse {\n}\n\nexport interface AggregateWindowInitRequest {\n function_name: string;\n execution_id: Uint8Array;\n partition_id: number;\n row_count: number;\n partition_batch: Uint8Array;\n output_schema: /** @arrow-schema */ Uint8Array;\n filter_mask: Uint8Array;\n frame_stats: Uint8Array;\n all_valid: Uint8Array;\n attach_opaque_data?: Uint8Array | null;\n schema_path?: string[] | null;\n}\n\nexport interface AggregateWindowInitResponse {\n}\n\nexport interface CopyFromContext {\n format: string;\n file_path: string;\n expected_schema: /** @arrow-schema */ Uint8Array;\n}\n\nexport interface CopyToContext {\n format: string;\n file_path: string;\n}\n\nexport interface BindRequest {\n function_name: string;\n arguments: /** @vgi-arguments */ Uint8Array;\n function_type: InvocationFunctionType;\n input_schema?: /** @arrow-schema */ Uint8Array | null;\n settings?: /** @record-batch */ Uint8Array | null;\n secrets?: /** @record-batch */ Uint8Array | null;\n attach_opaque_data?: Uint8Array | null;\n transaction_opaque_data?: Uint8Array | null;\n resolved_secrets_provided: boolean;\n at_unit?: string | null;\n at_value?: string | null;\n copy_from?: CopyFromContext | null;\n copy_to?: CopyToContext | null;\n schema_path?: string[] | null;\n argument_names?: (string | null)[] | null;\n}\n\nexport interface BindResponse {\n output_schema: /** @arrow-schema */ Uint8Array;\n opaque_data?: Uint8Array | null;\n lookup_secret_types: string[];\n lookup_scopes: string[];\n lookup_names: string[];\n}\n\nexport interface ClientCapabilities {\n engine: string;\n native_formats: string[];\n catalogs: string[];\n can_stream: boolean;\n filter_encodings: string[];\n}\n\nexport interface CatalogAttachRequest {\n name: string;\n options?: /** @record-batch */ Uint8Array | null;\n data_version_spec?: string | null;\n implementation_version?: string | null;\n client_capabilities?: ClientCapabilities | null;\n}\n\nexport interface CatalogAttachResult {\n attach_opaque_data: Uint8Array;\n supports_transactions: boolean;\n supports_time_travel: boolean;\n catalog_version_frozen: boolean;\n catalog_version: number;\n attach_opaque_data_required: boolean;\n default_schema: string;\n settings: Uint8Array[];\n secret_types: Uint8Array[];\n attach_catalogs: Uint8Array[];\n comment?: string | null;\n tags: Record<string, string>;\n supports_column_statistics: boolean;\n global_functions: Uint8Array[];\n global_function_prefix: string;\n resolved_data_version?: string | null;\n resolved_implementation_version?: string | null;\n}\n\nexport interface CatalogsResponse {\n items: CatalogInfo[];\n}\n\nexport interface CopyFromFormatsResponse {\n items: Uint8Array[];\n}\n\nexport interface CatalogCreateRequest {\n name: string;\n on_conflict: OnConflict;\n options?: /** @record-batch */ Uint8Array | null;\n}\n\nexport interface IndexCreateRequest {\n attach_opaque_data: Uint8Array;\n schema_path: string[];\n name: string;\n table_name: string;\n index_type: string;\n constraint_type: IndexConstraintType;\n expressions: string[];\n on_conflict: OnConflict;\n options: Record<string, string>;\n transaction_opaque_data?: Uint8Array | null;\n}\n\nexport interface IndexesResponse {\n items: IndexInfo[];\n}\n\nexport interface MacroCreateRequest {\n attach_opaque_data: Uint8Array;\n schema_path: string[];\n name: string;\n macro_type: MacroType;\n parameters: string[];\n definition: string;\n on_conflict: OnConflict;\n parameter_default_values?: /** @record-batch */ Uint8Array | null;\n arguments_schema?: /** @arrow-schema */ Uint8Array | null;\n transaction_opaque_data?: Uint8Array | null;\n}\n\nexport interface MacrosResponse {\n items: MacroInfo[];\n}\n\nexport interface FunctionsResponse {\n items: FunctionInfo[];\n}\n\nexport interface TablesResponse {\n items: TableInfo[];\n}\n\nexport interface ViewsResponse {\n items: ViewInfo[];\n}\n\nexport interface SchemasResponse {\n items: SchemaInfo[];\n}\n\nexport interface TableCreateRequest {\n attach_opaque_data: Uint8Array;\n schema_path: string[];\n name: string;\n columns: Uint8Array;\n on_conflict: OnConflict;\n not_null_constraints: number[];\n unique_constraints: number[][];\n check_constraints: string[];\n primary_key_constraints: number[][];\n foreign_key_constraints: Uint8Array[];\n transaction_opaque_data?: Uint8Array | null;\n}\n\nexport interface TransactionBeginResponse {\n transaction_opaque_data?: Uint8Array | null;\n}\n\nexport interface CatalogVersionResponse {\n version: number;\n}\n\nexport interface InitRequest {\n bind_call: BindRequest;\n output_schema: /** @arrow-schema */ Uint8Array;\n bind_opaque_data?: Uint8Array | null;\n projection_ids?: number[] | null;\n pushdown_filters?: /** @record-batch */ Uint8Array | null;\n join_keys?: /** @record-batch */ Uint8Array[] | null;\n split_tokens?: Uint8Array[] | null;\n row_limit?: number | null;\n phase?: TableInOutFunctionInitPhase | null;\n finalize_state_id?: Uint8Array | null;\n execution_id?: Uint8Array | null;\n init_opaque_data?: Uint8Array | null;\n substream_id?: Uint8Array | null;\n order_by_column_name?: string | null;\n order_by_direction?: OrderByDirection | null;\n order_by_null_order?: OrderByNullOrder | null;\n order_by_limit?: number | null;\n tablesample_percentage?: number | null;\n tablesample_seed?: number | null;\n}\n\nexport interface TableBufferingCombineRequest {\n function_name: string;\n execution_id: Uint8Array;\n state_ids: Uint8Array[];\n attach_opaque_data?: Uint8Array | null;\n transaction_id?: Uint8Array | null;\n schema_path?: string[] | null;\n}\n\nexport interface TableBufferingCombineResponse {\n finalize_state_ids: Uint8Array[];\n}\n\nexport interface TableBufferingDestructorRequest {\n function_name: string;\n execution_id: Uint8Array;\n attach_opaque_data?: Uint8Array | null;\n transaction_id?: Uint8Array | null;\n schema_path?: string[] | null;\n}\n\nexport interface TableBufferingDestructorResponse {\n}\n\nexport interface TableBufferingProcessRequest {\n function_name: string;\n execution_id: Uint8Array;\n input_batch: Uint8Array;\n attach_opaque_data?: Uint8Array | null;\n transaction_id?: Uint8Array | null;\n batch_index?: number | null;\n schema_path?: string[] | null;\n}\n\nexport interface TableBufferingProcessResponse {\n state_id: Uint8Array;\n}\n\nexport interface TableFunctionCardinalityRequest {\n bind_call: BindRequest;\n bind_opaque_data?: Uint8Array | null;\n}\n\nexport interface TableCardinality {\n estimate?: number | null;\n max?: number | null;\n}\n\nexport interface TableFunctionDynamicToStringRequest {\n bind_call: BindRequest;\n bind_opaque_data?: Uint8Array | null;\n global_execution_id: Uint8Array;\n}\n\nexport interface TableFunctionDynamicToStringResponse {\n keys: string[];\n values: string[];\n}\n\nexport interface TableFunctionPlanRequest {\n bind_call: BindRequest;\n bind_opaque_data?: Uint8Array | null;\n projection_ids?: number[] | null;\n pushdown_filters?: /** @record-batch */ Uint8Array | null;\n join_keys?: /** @record-batch */ Uint8Array[] | null;\n row_limit?: number | null;\n target_split_bytes?: number | null;\n min_splits?: number | null;\n max_splits_per_response?: number | null;\n cursor?: Uint8Array | null;\n refined_filters?: /** @record-batch */ Uint8Array | null;\n filters_complete: boolean;\n start_position?: Uint8Array | null;\n end_position?: Uint8Array | null;\n order_by_column_name?: string | null;\n order_by_direction?: OrderByDirection | null;\n order_by_null_order?: OrderByNullOrder | null;\n order_by_limit?: number | null;\n tablesample_percentage?: number | null;\n tablesample_seed?: number | null;\n}\n\nexport interface ScanSplit {\n payload: Uint8Array;\n token: Uint8Array;\n estimated_rows?: number | null;\n rows_exact: boolean;\n estimated_bytes?: number | null;\n partition_bounds?: /** @record-batch */ Uint8Array | null;\n column_statistics?: Uint8Array | null;\n location_ids?: number[] | null;\n start_position?: Uint8Array | null;\n end_position?: Uint8Array | null;\n}\n\nexport interface PlanResponse {\n splits: ScanSplit[] | Uint8Array[];\n next_cursors?: Uint8Array[] | null;\n execution_id?: Uint8Array | null;\n init_opaque_data?: Uint8Array | null;\n max_workers?: number | null;\n estimated_total_splits?: number | null;\n estimated_total_rows?: number | null;\n estimated_total_bytes?: number | null;\n catalog_version?: number | null;\n scope: string;\n locations?: string[] | null;\n partitioning?: Uint8Array[] | null;\n sort_order?: Uint8Array[] | null;\n cache_max_age_seconds?: number | null;\n start_position?: Uint8Array | null;\n end_position?: Uint8Array | null;\n}\n\nexport interface TableFunctionStatisticsRequest {\n bind_call: BindRequest;\n bind_opaque_data?: Uint8Array | null;\n}\n\n// ----------------------------------------------------------------------------\n// Codec wrappers: turn the typed interfaces above into actual wire bytes.\n// ----------------------------------------------------------------------------\n\nexport const encodeCatalogInfo = (v: CatalogInfo): Uint8Array => encodeASD(CatalogInfoSchema, v);\nexport const decodeCatalogInfo = (b: Uint8Array): CatalogInfo => decodeASD<CatalogInfo>(CatalogInfoSchema, b);\nexport const encodeFunctionInfo = (v: FunctionInfo): Uint8Array => encodeASD(FunctionInfoSchema, v);\nexport const decodeFunctionInfo = (b: Uint8Array): FunctionInfo => decodeASD<FunctionInfo>(FunctionInfoSchema, b);\nexport const encodeIndexInfo = (v: IndexInfo): Uint8Array => encodeASD(IndexInfoSchema, v);\nexport const decodeIndexInfo = (b: Uint8Array): IndexInfo => decodeASD<IndexInfo>(IndexInfoSchema, b);\nexport const encodeMacroInfo = (v: MacroInfo): Uint8Array => encodeASD(MacroInfoSchema, v);\nexport const decodeMacroInfo = (b: Uint8Array): MacroInfo => decodeASD<MacroInfo>(MacroInfoSchema, b);\nexport const encodeSchemaInfo = (v: SchemaInfo): Uint8Array => encodeASD(SchemaInfoSchema, v);\nexport const decodeSchemaInfo = (b: Uint8Array): SchemaInfo => decodeASD<SchemaInfo>(SchemaInfoSchema, b);\nexport const encodeTableInfo = (v: TableInfo): Uint8Array => encodeASD(TableInfoSchema, v);\nexport const decodeTableInfo = (b: Uint8Array): TableInfo => decodeASD<TableInfo>(TableInfoSchema, b);\nexport const encodeViewInfo = (v: ViewInfo): Uint8Array => encodeASD(ViewInfoSchema, v);\nexport const decodeViewInfo = (b: Uint8Array): ViewInfo => decodeASD<ViewInfo>(ViewInfoSchema, b);\n",
|
|
57
|
+
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Catalog items that are built once and encoded once.\n//\n// A function listing from a descriptor-driven catalog depends only on static\n// metadata, yet every catalog_schema_contents_functions request used to rebuild\n// each FunctionInfo (argument and output schemas serialized to IPC, metadata\n// resolved) and then Arrow-encode it again: ~1.5 ms per function, ~236 ms for\n// the example worker's main schema, paid on every function-set load DuckDB\n// makes. vgi-python fixed the same cost by caching the listing and storing each\n// item's encoding on its (frozen dataclass) instance (6cc522a).\n//\n// JS objects are not frozen by default, and an encoding memo keyed by object\n// identity is only sound for an object that cannot change after it was\n// encoded. So the memo applies to FROZEN items only: a catalog opts in by\n// returning items it froze with `freezeCatalogItem` (ReadOnlyCatalogInterface\n// does), and every other item -- a catalog that builds fresh objects per call,\n// or keeps and mutates its own -- is encoded on every call exactly as before.\n\nimport { encodeFunctionInfo, type FunctionInfo } from \"../generated/vgi-client.js\";\n\n/** Encoded bytes per frozen item instance. Weak, so it never pins an item. */\nconst ENCODED = new WeakMap<object, Uint8Array>();\n\n/**\n * Deep-freeze a catalog item (plain objects and arrays, recursively) so it can\n * be shared between requests and its encoding memoized.\n *\n * Binary fields (`Uint8Array` and other ArrayBuffer views) are left as they are\n * -- a typed array with elements cannot be frozen -- and must be treated as\n * read-only by convention, like the rest of a shared item.\n */\nexport function freezeCatalogItem<T extends object>(item: T): Readonly<T> {\n deepFreeze(item);\n return item;\n}\n\nfunction deepFreeze(value: unknown): void {\n if (value === null || typeof value !== \"object\" || Object.isFrozen(value) || ArrayBuffer.isView(value)) return;\n const proto = Object.getPrototypeOf(value);\n if (proto !== Object.prototype && proto !== Array.prototype && proto !== null) return;\n for (const child of Object.values(value)) deepFreeze(child);\n Object.freeze(value);\n}\n\n/**\n * Arrow-encode a FunctionInfo, once per frozen instance.\n *\n * The bytes returned for a frozen item are shared between calls; callers copy\n * them into a response and never write to them.\n */\nexport function encodeFunctionInfoOnce(info: FunctionInfo): Uint8Array {\n if (!Object.isFrozen(info)) return encodeFunctionInfo(info);\n let encoded = ENCODED.get(info);\n if (encoded === undefined) {\n encoded = encodeFunctionInfo(info);\n ENCODED.set(info, encoded);\n }\n return encoded;\n}\n",
|
|
54
58
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// CatalogInterface abstract class with ~35 methods.\n// Matching Python's vgi/catalog/catalog_interface.py\n\nimport { CatalogReadOnlyError } from \"../errors.js\";\nimport { schemaPathsEqual } from \"../schema-path.js\";\n\nexport type AttachOpaqueData = Uint8Array;\nexport type TransactionOpaqueData = Uint8Array;\n\n// Wire-encoded string union (matches Python's CatalogMacroType enum names).\nimport type { MacroType } from \"../generated/vgi-client.js\";\nexport type { MacroType };\n\n// CatalogAttachResult is the generated snake_case wire shape.\n// The `supports_column_statistics` field is a catalog-level opt-in for the\n// catalog_table_column_statistics_get RPC — defaults to true when unspecified;\n// individual tables still need to set TableInfo.supports_column_statistics\n// before DuckDB will actually call it.\nimport type { CatalogAttachResult } from \"../generated/vgi-client.js\";\nexport type { CatalogAttachResult };\n\n// ============================================================================\n// Serializable info types\n// ============================================================================\n\n// These serialize themselves to Arrow IPC bytes for catalog responses\n\n// SchemaInfo is the generated interface (snake_case wire shape).\n// Codecs live in ../generated/vgi-client.ts — no class needed.\nimport type { SchemaInfo } from \"../generated/vgi-client.js\";\nexport type { SchemaInfo };\nexport { encodeSchemaInfo, decodeSchemaInfo } from \"../generated/vgi-client.js\";\n\n// CatalogInfo — advertised by workers per catalog (name + versions).\nimport type { CatalogInfo } from \"../generated/vgi-client.js\";\nexport type { CatalogInfo };\nexport { encodeCatalogInfo, decodeCatalogInfo } from \"../generated/vgi-client.js\";\n\n// TableInfo is the generated interface (snake_case wire shape).\nimport type { TableInfo } from \"../generated/vgi-client.js\";\nexport type { TableInfo };\nexport { encodeTableInfo, decodeTableInfo } from \"../generated/vgi-client.js\";\n\n// ViewInfo is the generated interface (snake_case wire shape).\nimport type { ViewInfo } from \"../generated/vgi-client.js\";\nexport type { ViewInfo };\nexport { encodeViewInfo, decodeViewInfo } from \"../generated/vgi-client.js\";\n\n// FunctionInfo is the generated interface (snake_case wire shape).\n// FunctionInfoOptions was the camelCase constructor bag for the old class —\n// callers now use object literals matching the wire shape directly.\nimport type { FunctionInfo } from \"../generated/vgi-client.js\";\nexport type { FunctionInfo };\n/** @deprecated Use the FunctionInfo interface (snake_case) directly. */\nexport type FunctionInfoOptions = FunctionInfo;\nexport { encodeFunctionInfo, decodeFunctionInfo } from \"../generated/vgi-client.js\";\n\n// MacroInfo is the generated interface (snake_case wire shape).\nimport type { MacroInfo } from \"../generated/vgi-client.js\";\nexport type { MacroInfo };\nexport { encodeMacroInfo, decodeMacroInfo } from \"../generated/vgi-client.js\";\n\n// IndexInfo wire shape — declarative indexes a worker advertises and DuckDB\n// surfaces under duckdb_indexes(). Constraint type maps to is_unique /\n// is_primary on the DuckDB side.\nimport type { IndexInfo, IndexConstraintType } from \"../generated/vgi-client.js\";\nexport type { IndexInfo, IndexConstraintType };\nexport { encodeIndexInfo, decodeIndexInfo } from \"../generated/vgi-client.js\";\n\n// CopyFromFormatInfo — a custom `COPY ... FROM` format a VGI catalog advertises.\n// The wire shape matches the generated CopyFromFormatInfoSchema; the codegen\n// does not emit a dedicated interface/encoder for it (it's an items-list type\n// carried as binary), so we declare the snake_case interface here and reuse the\n// generic ASD codec with the generated schema. Mirrors vgi-python's\n// catalog_interface.CopyFromFormatInfo.\nimport { encodeASD } from \"../codec/asd.js\";\nimport {\n AttachCatalogInfoSchema,\n CopyFromFormatInfoSchema,\n} from \"../generated/vgi-protocol-schemas.js\";\n\nexport interface CopyFromFormatInfo {\n /** Free-text comment (CopyFromFunction's `copyFromComment`). */\n comment?: string | null;\n /** Function/format tags. */\n tags: Record<string, string>;\n /** The `FORMAT` identifier users type (single global namespace). */\n format_name: string;\n /** Registered name of the worker function that performs the read. */\n handler: string;\n /**\n * Serialized Arrow schema of the format's options (same encoding as\n * `FunctionInfo.arguments`), each field carrying type / `vgi_doc` description.\n */\n options: Uint8Array;\n /** `\"from\"` / `\"to\"` / `\"both\"` — the COPY direction this format serves. */\n direction: string;\n /** Intrinsic documentation from the handler's description. */\n description: string;\n /**\n * COPY ... TO only — when true the writer requires rows in source order, so\n * the extension uses a single-threaded sink (`REGULAR_COPY_TO_FILE`) instead\n * of the default parallel sharded write. Set via `Meta.sinkOrderDependent`\n * on a CopyToFunction; always false for readers. Mirrors vgi-python's\n * `CopyFromFormatInfo.ordered`.\n */\n ordered: boolean;\n}\n\n/** Encode a CopyFromFormatInfo to Arrow IPC bytes (single-row batch). */\nexport const encodeCopyFromFormatInfo = (v: CopyFromFormatInfo): Uint8Array =>\n encodeASD(CopyFromFormatInfoSchema, {\n comment: v.comment ?? null,\n tags: v.tags ?? {},\n format_name: v.format_name,\n handler: v.handler,\n options: v.options,\n direction: v.direction ?? \"from\",\n description: v.description ?? \"\",\n ordered: v.ordered ?? false,\n });\n\n/**\n * A companion catalog the client should ATTACH when this VGI catalog attaches\n * (lakehouse federation). Serialized into `CatalogAttachResult.attach_catalogs`;\n * the C++ VGI extension attaches each at VGI-attach time so multi-branch\n * catalog-table branches can resolve tables in a companion DuckLake / Iceberg /\n * Postgres / DuckDB.\n */\nexport interface AttachCatalogInfo {\n /** ATTACH alias; also a catalog-table ScanBranch's `sourceCatalog`. */\n alias: string;\n /** ATTACH target — a path or DSN (e.g. `ducklake:sqlite:/data/meta.sqlite`). */\n target: string;\n /** DuckDB db type; empty => inferred from the target scheme prefix. */\n db_type?: string;\n /** Extra ATTACH options forwarded verbatim (e.g. DuckLake DATA_PATH). */\n options?: Record<string, string>;\n /** Attach hidden (excluded from duckdb_databases()); still resolvable. */\n hidden?: boolean;\n /** When true, attach failure fails the whole VGI ATTACH. */\n required?: boolean;\n /** Optional named secret to inject into the companion's ATTACH options. */\n secret_ref?: string;\n}\n\n/** Encode an AttachCatalogInfo to Arrow IPC bytes (single-row batch). */\nexport const encodeAttachCatalogInfo = (v: AttachCatalogInfo): Uint8Array =>\n encodeASD(AttachCatalogInfoSchema, {\n alias: v.alias,\n target: v.target,\n db_type: v.db_type ?? \"\",\n options: v.options ?? {},\n hidden: v.hidden ?? false,\n required: v.required ?? false,\n secret_ref: v.secret_ref ?? \"\",\n });\n\n// ============================================================================\n// ScanFunctionResult — typed result for catalog_table_scan_function_get.\n// Mirrors vgi-python's ScanFunctionResult (catalog_interface.py:380).\n// ============================================================================\n\nimport { deserializeBatch, serializeBatch, batchFromColumns } from \"../util/arrow/index.js\";\nimport { schema as schema_, field as field_, type VgiDataType, type VgiField } from \"../arrow/index.js\";\nimport { toUint8Array } from \"../util/bytes.js\";\nimport { ScanBranchSchema, ScanFunctionResultSchema } from \"../generated/vgi-protocol-schemas.js\";\n\n/**\n * Result from `tableScanFunctionGet` — tells the VGI DuckDB extension which\n * DuckDB function to call to obtain the data for a table.\n */\nexport interface ScanFunctionResult {\n /** The DuckDB function to call (e.g. \"read_parquet\"). */\n functionName: string;\n /** Positional arguments, decoded from the inner Arrow batch. */\n positionalArguments: unknown[];\n /** Named arguments, decoded from the inner Arrow batch. */\n namedArguments: Record<string, unknown>;\n /** DuckDB extensions to load before calling the function. */\n requiredExtensions: string[];\n /**\n * Catalog schema path `functionName` is registered in (protocol 2.0.0). A function\n * name is unique only within a schema, so a client that doesn't know this\n * cannot tell which implementation a colliding name refers to — set it\n * whenever the resolving code already knows the schema. `null` for a\n * pre-1.5.0 peer, or when the resolved function is a native DuckDB function\n * with no VGI-side schema of its own (e.g. `read_parquet`).\n */\n schemaPath: string[] | null;\n}\n\n/**\n * Encode a ScanFunctionResult wire record — the single-row batch shape\n * `{ function_name, arguments, required_extensions, schema_path }` that\n * `catalog_table_scan_function_get` returns and that a function-backed table\n * inlines into `TableInfo.scan_function`.\n *\n * It exists so there is exactly one place that names those columns. The\n * inline-scan path used to restate the schema locally even though codegen\n * emits it; a hand-written wire schema is how four SDKs ended up disagreeing\n * about which columns were binary and which were large_binary.\n *\n * `argumentsBytes` is the already-serialized inner arguments batch (one column\n * per argument: `arg_<index>` positional, bare name for named).\n *\n * `schemaPath` (protocol 2.0.0) identifies the schema that registers `functionName`;\n * leave it null when the caller has no VGI-side schema to report.\n */\nexport function encodeScanFunctionResult(\n functionName: string,\n argumentsBytes: Uint8Array,\n requiredExtensions: string[] = [],\n schemaPath: string[] | null = null,\n): Uint8Array {\n return serializeBatch(\n batchFromColumns(\n {\n function_name: [functionName],\n arguments: [argumentsBytes],\n required_extensions: [requiredExtensions],\n schema_path: [schemaPath],\n },\n ScanFunctionResultSchema as any,\n ),\n );\n}\n\n/**\n * Decode a ScanFunctionResult from a wire-shape inner result dict.\n *\n * The wire shape (per ScanFunctionResultSchema) is\n * `{ function_name: utf8, arguments: binary, required_extensions: list<utf8>,\n * schema_path: list<utf8>? }`, where `arguments` is a serialized single-row batch\n * with one column per argument: `arg_<index>` for positional args, the bare\n * name for named args.\n */\nexport function decodeScanFunctionResult(inner: Record<string, unknown>): ScanFunctionResult {\n const argsBytes = inner.arguments;\n const positionalArguments: unknown[] = [];\n const namedArguments: Record<string, unknown> = {};\n\n if (argsBytes != null) {\n const batch = deserializeBatch(toUint8Array(argsBytes));\n for (const field of batch.schema.fields) {\n const col = batch.getChild(field.name);\n const value = col ? col.get(0) : null;\n if (field.name.startsWith(\"arg_\")) {\n const idx = parseInt(field.name.slice(4), 10);\n while (positionalArguments.length <= idx) positionalArguments.push(null);\n positionalArguments[idx] = value;\n } else {\n namedArguments[field.name] = value;\n }\n }\n }\n\n const exts = inner.required_extensions;\n const requiredExtensions: string[] = exts == null\n ? []\n : (Array.isArray(exts) ? exts : [...(exts as Iterable<unknown>)])\n .filter((v) => v != null)\n .map(String);\n\n return {\n functionName: String(inner.function_name ?? \"\"),\n positionalArguments,\n namedArguments,\n requiredExtensions,\n // Absent for a pre-1.5.0 peer — the column itself won't be on the wire in\n // that case, which reads the same as \"present but null\".\n schemaPath: inner.schema_path == null\n ? null\n : (Array.isArray(inner.schema_path) ? inner.schema_path : [...(inner.schema_path as Iterable<unknown>)])\n .filter((value) => value != null)\n .map(String),\n };\n}\n\n/**\n * Synthesise a one-branch `ScanBranchesResult` wire dict from a legacy\n * `tableScanFunctionGet` wire result. Mirrors vgi-python's default\n * `table_scan_branches_get` (catalog_interface.py): a single-source worker is\n * automatically compatible with the branches-aware C++ side.\n *\n * Each branch is its own IPC stream carried in a `list<binary>` column. The\n * legacy result's `arguments` field is already the nested-IPC form\n * `ScanBranch` expects, so it passes through untouched.\n */\nexport function singleBranchResult(\n legacy: {\n function_name: string;\n arguments: unknown;\n required_extensions?: string[];\n schema_path?: string[] | null;\n },\n): { branches: Uint8Array[]; required_extensions: string[] } {\n return {\n branches: [\n encodeScanBranch({\n function_name: legacy.function_name,\n arguments: toUint8Array(legacy.arguments),\n // This shim has no independent way to know the function's own schema;\n // propagate whatever `tableScanFunctionGet` already resolved rather\n // than dropping a value the legacy response carries.\n schema_path: legacy.schema_path ?? null,\n }),\n ],\n required_extensions: legacy.required_extensions ?? [],\n };\n}\n\n/**\n * The ONE place `ScanBranch`'s columns are named.\n *\n * Both branch builders used to carry their own copy of this key list, and both\n * copies were missing `format_name` / `format_locations` after those fields\n * were added to the schema. `format_locations` is a LIST, and Arrow's assembler\n * dereferences a list's `children[0]` while writing, so the omission did not\n * degrade anything — it killed every scan through those builders with\n * \"Cannot read properties of undefined (reading 'slice')\", including tables\n * that predated format branches entirely. One key list is the fix; the\n * completeness test in src/__tests__ pins it against ScanBranchSchema.\n *\n * Every column the schema declares must appear here, null included.\n */\nfunction encodeScanBranch(cols: {\n function_name: string;\n arguments: Uint8Array;\n branch_filter?: string | null;\n writable?: boolean;\n source_catalog?: string | null;\n source_schema_path?: string[] | null;\n source_table?: string | null;\n format_name?: string | null;\n format_locations?: string[] | null;\n format_options?: Uint8Array | null;\n schema_path?: string[] | null;\n}): Uint8Array {\n return serializeBatch(\n batchFromColumns(\n {\n function_name: [cols.function_name],\n arguments: [cols.arguments],\n branch_filter: [cols.branch_filter ?? null],\n writable: [cols.writable ?? false],\n source_catalog: [cols.source_catalog ?? null],\n source_schema_path: [cols.source_schema_path ?? null],\n source_table: [cols.source_table ?? null],\n format_name: [cols.format_name ?? null],\n format_locations: [cols.format_locations ?? null],\n format_options: [cols.format_options ?? null],\n schema_path: [cols.schema_path ?? null],\n },\n ScanBranchSchema as any,\n ),\n );\n}\n\n/**\n * One physical source backing a multi-branch scan, in the shape the\n * `buildScanBranchesResult` helper consumes. Mirrors vgi-python's\n * `ScanBranch` (catalog_interface.py).\n *\n * Each scalar argument carries an explicit Arrow `type` so the nested\n * arguments batch is built with the wire type the C++ binder expects\n * (e.g. utf8 for file paths, int64 for counts).\n */\nexport interface ScanBranchInput {\n /** DuckDB function to call for this branch (e.g. \"sequence\", \"read_parquet\"). */\n functionName: string;\n /** Positional scalar arguments, each with its Arrow type. */\n positionalArguments?: { value: unknown; type: VgiDataType }[];\n /** Named scalar arguments, each with its Arrow type. */\n namedArguments?: Record<string, { value: unknown; type: VgiDataType }>;\n /** Optional SQL filter text AND'd into every scan of this branch. */\n branchFilter?: string | null;\n /** Declares this branch as the INSERT target (at most one per table). */\n writable?: boolean;\n /** Custom file FORMAT this branch reads, for a format-backed branch. */\n formatName?: string | null;\n /** Locations the format branch reads. */\n formatLocations?: string[] | null;\n /** Reader options for a format branch, as a 1-row IPC batch whose COLUMN\n * NAMES are the option names — the same shape `arguments` uses, because an\n * option value may be any Arrow type. These BECOME the reader's named\n * arguments, so without them a format branch cannot pass its reader a\n * delimiter, a header flag, or anything else. */\n formatOptions?: Uint8Array | null;\n /**\n * Catalog-table branch (lakehouse federation): leave `functionName` empty and\n * set these to scan the base table\n * `sourceCatalog.sourceSchemaPath.sourceTable` in a companion catalog instead of\n * calling a table function.\n */\n sourceCatalog?: string | null;\n sourceSchemaPath?: string[] | null;\n sourceTable?: string | null;\n /**\n * Function branch only — the catalog schema that registers `functionName`\n * (protocol 2.0.0). Without it a client has to guess (the table's own\n * schema, then the catalog's default schema) which implementation\n * `functionName` refers to when the same name is registered in more than\n * one schema. Leave unset for a catalog-table or FORMAT branch, and for a\n * branch that delegates straight to a native DuckDB function\n * (`read_parquet`, `read_csv_auto`, `iceberg_scan`, …) — neither has a\n * VGI-side schema of its own to report, which is why the field is optional\n * rather than required. Not to be confused with `sourceSchemaPath` above, which\n * names a catalog-table branch's *source table's* schema.\n */\n schemaPath?: string[] | null;\n}\n\n/**\n * Serialize a single branch's arguments to the nested-IPC form `ScanBranch`\n * expects: a 1-row batch with one column per argument — `arg_<index>` for\n * positional args, the bare name for named args. Mirrors Python's\n * `ScanBranch.to_row_dict` argument handling.\n */\n/**\n * Encode a format branch's reader options.\n *\n * Same shape as a branch's `arguments` blob — a 1-row batch whose COLUMN NAMES\n * are the option names — because an option value may be any Arrow type, so no\n * static schema could describe the map. Exported because a worker building a\n * format branch needs it and has no other way to produce those bytes.\n */\nexport function encodeFormatOptions(\n options: Record<string, { value: unknown; type: VgiDataType }>,\n): Uint8Array {\n const fields: VgiField[] = [];\n const values: Record<string, unknown[]> = {};\n for (const [name, arg] of Object.entries(options)) {\n fields.push(field_(name, arg.type, true));\n values[name] = [arg.value];\n }\n return serializeBatch(batchFromColumns(values, schema_(fields)));\n}\n\nfunction serializeBranchArguments(branch: ScanBranchInput): Uint8Array {\n const fields: VgiField[] = [];\n const values: Record<string, unknown[]> = {};\n\n const positional = branch.positionalArguments ?? [];\n positional.forEach((arg, index) => {\n const name = `arg_${index}`;\n fields.push(field_(name, arg.type, true));\n values[name] = [arg.value];\n });\n\n for (const [name, arg] of Object.entries(branch.namedArguments ?? {})) {\n fields.push(field_(name, arg.type, true));\n values[name] = [arg.value];\n }\n\n const batchSchema = schema_(fields);\n // batchFromColumns handles the zero-column case by producing a 1-row\n // empty batch — same as Python's RecordBatch.from_pylist([{}]).\n return serializeBatch(batchFromColumns(values, batchSchema));\n}\n\n/**\n * Build a multi-branch `ScanBranchesResult` wire dict from explicit branch\n * definitions. Each branch becomes its own 1-row `ScanBranchSchema` IPC\n * stream carried in the `branches` list<binary> column. Mirrors vgi-python's\n * `ScanBranchesResult` construction in the test fixture's\n * `table_scan_branches_get`.\n *\n * An empty `branches` list is serialized verbatim — the C++ side loud-fails\n * on it (that asymmetry is exercised by multi_branch_empty_branches.test).\n */\nexport function buildScanBranchesResult(\n branches: ScanBranchInput[],\n requiredExtensions: string[] = [],\n): { branches: Uint8Array[]; required_extensions: string[] } {\n const serializedBranches = branches.map((branch) =>\n encodeScanBranch({\n function_name: branch.functionName,\n arguments: serializeBranchArguments(branch),\n branch_filter: branch.branchFilter,\n writable: branch.writable,\n source_catalog: branch.sourceCatalog,\n source_schema_path: branch.sourceSchemaPath,\n source_table: branch.sourceTable,\n format_name: branch.formatName,\n format_locations: branch.formatLocations,\n format_options: branch.formatOptions,\n schema_path: branch.schemaPath,\n }),\n );\n return {\n branches: serializedBranches,\n required_extensions: requiredExtensions,\n };\n}\n\n// ============================================================================\n// CatalogInterface abstract class\n// ============================================================================\n\n/**\n * Catalog method return type — sync `T` or `Promise<T>`. The framework's\n * dispatch handlers `await` every catalog call, so async overrides work\n * out of the box. Default impls return sync values.\n */\ntype Awaitable<T> = T | Promise<T>;\n\nfunction isPromise<T>(v: Awaitable<T>): v is Promise<T> {\n return v != null && typeof (v as any).then === \"function\";\n}\n\nexport abstract class CatalogInterface {\n /**\n * Which catalog an `attach_opaque_data` belongs to, or null if unknown.\n *\n * Two catalogs served by one worker may declare the same schema *and*\n * function name, in which case the attachment is the only thing that tells\n * them apart — the bind path uses this to scope function resolution. The\n * default answers from `catalogs()` when this interface owns exactly one,\n * which is right for every single-catalog implementation; the composite\n * overrides it to route by its backend index byte.\n */\n catalogNameForAttach(_attachOpaqueData: Uint8Array): string | null {\n const names = this.catalogs();\n return names.length === 1 ? names[0] : null;\n }\n\n // Required overrides\n abstract catalogs(): string[];\n /**\n * Attach this catalog. The framework already validates ATTACH options\n * (name + type) against the specs the worker advertises in\n * `catalogsInfo().attach_option_specs`, so `options` arrives as a\n * validated, decoded `{name: value}` dict with typed column values.\n * Use `{}` if no options were supplied.\n */\n abstract attach(\n name: string,\n options?: Record<string, unknown>,\n dataVersionSpec?: string | null,\n implementationVersion?: string | null,\n ): Awaitable<CatalogAttachResult>;\n /**\n * List the catalogs this worker exposes with their version metadata. The\n * `implementation_version` / `data_version_spec` come from the CatalogInfo\n * returned by the read-only catalogs() signature below — a versioned worker\n * overrides `catalogs()` / `catalogsInfo()` to advertise real values; the\n * default derives them from the registered descriptor(s).\n */\n catalogsInfo?(): Awaitable<import(\"../generated/vgi-client.js\").CatalogInfo[]>;\n abstract detach(attachOpaqueData: AttachOpaqueData): Awaitable<void>;\n abstract version(\n attachOpaqueData: AttachOpaqueData,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<number>;\n abstract schemas(\n attachOpaqueData: AttachOpaqueData,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<SchemaInfo[]>;\n\n // Default implementations (throw CatalogReadOnlyError)\n create(name: string, onConflict: string, options?: any): Awaitable<void> {\n throw new CatalogReadOnlyError(\"create\");\n }\n drop(name: string): Awaitable<void> {\n throw new CatalogReadOnlyError(\"drop\");\n }\n schemaGet(\n attachOpaqueData: AttachOpaqueData,\n path: string[],\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<SchemaInfo | null> {\n const all = this.schemas(attachOpaqueData, transactionOpaqueData);\n if (isPromise(all)) {\n return all.then((arr) => arr.find((s) => schemaPathsEqual(s.path, path)) ?? null);\n }\n return all.find((s) => schemaPathsEqual(s.path, path)) ?? null;\n }\n schemaCreate(\n attachOpaqueData: AttachOpaqueData,\n path: string[],\n comment?: string | null,\n tags?: any,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"schema_create\");\n }\n schemaDrop(\n attachOpaqueData: AttachOpaqueData,\n path: string[],\n ignoreNotFound?: boolean,\n cascade?: boolean,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"schema_drop\");\n }\n schemaContentsTables(\n attachOpaqueData: AttachOpaqueData,\n path: string[],\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<TableInfo[]> {\n return [];\n }\n schemaContentsViews(\n attachOpaqueData: AttachOpaqueData,\n path: string[],\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<ViewInfo[]> {\n return [];\n }\n schemaContentsFunctions(\n attachOpaqueData: AttachOpaqueData,\n path: string[],\n type: string,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<FunctionInfo[]> {\n return [];\n }\n tableGet(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n atUnit?: string,\n atValue?: string,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<TableInfo | null> {\n return null;\n }\n tableCreate(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n columns: Uint8Array,\n onConflict: string,\n notNullConstraints?: number[],\n uniqueConstraints?: number[][],\n checkConstraints?: string[],\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"table_create\");\n }\n tableDrop(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n ignoreNotFound?: boolean,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"table_drop\");\n }\n tableScanFunctionGet(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n atUnit?: string,\n atValue?: string,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<any> {\n throw new CatalogReadOnlyError(\"table_scan_function_get\");\n }\n /**\n * Return the scan branches for a (possibly multi-source) table. Default\n * delegates to `tableScanFunctionGet` and wraps the single result as a\n * one-branch list, so every single-source catalog is compatible with the\n * branches-aware C++ extension. Override for genuine multi-source tables.\n */\n tableScanBranchesGet(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n atUnit?: string,\n atValue?: string,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<any> {\n const legacy = this.tableScanFunctionGet(\n attachOpaqueData, schemaPath, name, atUnit, atValue, transactionOpaqueData,\n );\n return isPromise(legacy)\n ? legacy.then((r) => singleBranchResult(r))\n : singleBranchResult(legacy);\n }\n /**\n * Return serialized column statistics for a table, or null if none are\n * available. The result is the IPC bytes of a ColumnStatistics RecordBatch\n * (see src/util/statistics.ts for the schema) wrapped with an optional\n * cache TTL. Callers typically override this to pull stats from a\n * descriptor. Returning null signals \"no stats\" so DuckDB falls back to\n * the function-level `table_function_statistics` path.\n */\n tableColumnStatisticsGet(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n transactionOpaqueData?: TransactionOpaqueData,\n ): Awaitable<{ bytes: Uint8Array; cacheMaxAgeSeconds: number | null } | null> {\n return null;\n }\n tableCommentSet(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n comment?: string | null,\n ignoreNotFound?: boolean,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"table_comment_set\");\n }\n tableRename(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n newName: string,\n ignoreNotFound?: boolean,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"table_rename\");\n }\n tableColumnAdd(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n columnName: string,\n columnType: string,\n defaultValue?: string,\n ignoreNotFound?: boolean,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"table_column_add\");\n }\n tableColumnDrop(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n columnName: string,\n ignoreNotFound?: boolean,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"table_column_drop\");\n }\n tableColumnRename(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n columnName: string,\n newName: string,\n ignoreNotFound?: boolean,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"table_column_rename\");\n }\n tableColumnDefaultSet(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n columnName: string,\n defaultValue: string,\n ignoreNotFound?: boolean,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"table_column_default_set\");\n }\n tableColumnDefaultDrop(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n columnName: string,\n ignoreNotFound?: boolean,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"table_column_default_drop\");\n }\n tableColumnTypeChange(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n columnName: string,\n newType: string,\n ignoreNotFound?: boolean,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"table_column_type_change\");\n }\n tableNotNullSet(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n columnName: string,\n ignoreNotFound?: boolean,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"table_not_null_set\");\n }\n tableNotNullDrop(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n columnName: string,\n ignoreNotFound?: boolean,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"table_not_null_drop\");\n }\n viewGet(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<ViewInfo | null> {\n return null;\n }\n viewCreate(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n definition: string,\n onConflict: string,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"view_create\");\n }\n viewDrop(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n ignoreNotFound?: boolean,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"view_drop\");\n }\n viewRename(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n newName: string,\n ignoreNotFound?: boolean,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"view_rename\");\n }\n viewCommentSet(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n comment?: string | null,\n ignoreNotFound?: boolean,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"view_comment_set\");\n }\n macroGet(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<MacroInfo | null> {\n return null;\n }\n macroCreate(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n macroType: MacroType,\n parameters: string[],\n definition: string,\n onConflict: string,\n parameterDefaultValues?: Uint8Array | null,\n /**\n * Optional Arrow schema (one nullable field per parameter, in `parameters`\n * order) serialized as IPC bytes, carrying per-parameter descriptions via the\n * `vgi_doc` field metadata key. `null`/omitted when no per-parameter docs are\n * supplied. Build with `macroArgumentsSchema` + `serializeSchema`.\n */\n argumentsSchema?: Uint8Array | null,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"macro_create\");\n }\n macroDrop(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n ignoreNotFound?: boolean,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<void> {\n throw new CatalogReadOnlyError(\"macro_drop\");\n }\n schemaContentsMacros(\n attachOpaqueData: AttachOpaqueData,\n path: string[],\n type: string,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<MacroInfo[]> {\n return [];\n }\n schemaContentsIndexes(\n attachOpaqueData: AttachOpaqueData,\n path: string[],\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<IndexInfo[]> {\n return [];\n }\n indexGet(\n attachOpaqueData: AttachOpaqueData,\n schemaPath: string[],\n name: string,\n transactionOpaqueData?: TransactionOpaqueData\n ): Awaitable<IndexInfo | null> {\n return null;\n }\n /**\n * List custom `COPY ... FROM` formats advertised by this catalog. Catalog-level\n * (not schema-scoped). The default returns an empty list, so catalogs that\n * don't define COPY formats are unaffected. The VGI extension treats an empty\n * list (or a not-implemented method) as \"no custom formats\". Mirrors\n * vgi-python's `CatalogInterface.copy_from_formats`.\n */\n copyFromFormats(\n attachOpaqueData: AttachOpaqueData,\n transactionOpaqueData?: TransactionOpaqueData,\n ): Awaitable<CopyFromFormatInfo[]> {\n return [];\n }\n transactionBegin(attachOpaqueData: AttachOpaqueData): Awaitable<Uint8Array | null> {\n return null;\n }\n transactionCommit(\n attachOpaqueData: AttachOpaqueData,\n transactionOpaqueData: TransactionOpaqueData\n ): Awaitable<void> {}\n transactionRollback(\n attachOpaqueData: AttachOpaqueData,\n transactionOpaqueData: TransactionOpaqueData\n ): Awaitable<void> {}\n}\n",
|
|
55
|
-
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Catalog admin handlers: attach/detach/create/drop, version, transactions,\n// schemas (list, get, create, drop), schema contents listings.\n\nimport { type VgiSchema, schema, type VgiField, field, type VgiDataType, binary, utf8, bool } from \"../../../arrow/index.js\";\nimport { Protocol, type CallContext } from \"@query-farm/vgi-rpc\";\nimport { encodeSchemaInfo, encodeTableInfo, encodeViewInfo, encodeFunctionInfo, encodeCatalogInfo } from \"../../../generated/vgi-client.js\";\nimport { encodeCopyFromFormatInfo } from \"../../../catalog/interface.js\";\nimport {\n CatalogAttachParamsSchema,\n CatalogAttachResultSchema,\n CatalogCatalogsParamsSchema,\n CatalogCatalogsResultSchema,\n CatalogCopyFromFormatsParamsSchema,\n CatalogCopyFromFormatsResultSchema,\n CatalogCreateParamsSchema,\n CatalogDetachParamsSchema,\n CatalogDropParamsSchema,\n CatalogSchemaContentsFunctionsParamsSchema,\n CatalogSchemaContentsFunctionsResultSchema,\n CatalogSchemaContentsTablesParamsSchema,\n CatalogSchemaContentsTablesResultSchema,\n CatalogSchemaContentsViewsParamsSchema,\n CatalogSchemaContentsViewsResultSchema,\n CatalogSchemaCreateParamsSchema,\n CatalogSchemaDropParamsSchema,\n CatalogSchemaGetParamsSchema,\n CatalogSchemaGetResultSchema,\n CatalogSchemasParamsSchema,\n CatalogSchemasResultSchema,\n CatalogTransactionBeginParamsSchema,\n CatalogTransactionBeginResultSchema,\n CatalogTransactionCommitParamsSchema,\n CatalogTransactionRollbackParamsSchema,\n CatalogVersionParamsSchema,\n CatalogVersionResultSchema,\n} from \"../../../generated/vgi-protocol-schemas.js\";\nimport { toUint8Array } from \"../../../util/bytes.js\";\nimport { decodeDictValue } from \"../../../util/arrow/index.js\";\nimport {\n REQUEST_PARAMS_SCHEMA,\n RESULT_BINARY_SCHEMA,\n unwrapRequest,\n wrapResult,\n} from \"../shared.js\";\nimport {\n type GetCatalog,\n decodeOptionsBatch,\n emptyResultSchema,\n catalogUnary,\n sealAttach,\n openAttach,\n sealTransaction,\n} from \"./shared.js\";\n\nexport function registerCatalogAdminMethods(protocol: Protocol, getCatalog: GetCatalog, signingKey?: Uint8Array): void {\n // catalog_catalogs\n catalogUnary(protocol, signingKey, \"catalog_catalogs\", {\n params: CatalogCatalogsParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async () => {\n const cat = getCatalog();\n // Each catalog advertised as an IPC-serialized CatalogInfo\n // {name, implementation_version?, data_version_spec?}. Versioned workers\n // override catalogsInfo() to supply real values; otherwise both version\n // fields default to null.\n const infos = cat.catalogsInfo\n ? await cat.catalogsInfo()\n : cat.catalogs().map((name) => ({\n name,\n implementation_version: null,\n data_version_spec: null,\n attach_option_specs: [],\n releases: [],\n }));\n const items = infos.map((info) => encodeCatalogInfo(info));\n return wrapResult({ items }, CatalogCatalogsResultSchema);\n },\n });\n\n // catalog_attach (params wrapped in request: Binary like bind/init)\n protocol.unary(\"catalog_attach\", {\n params: CatalogAttachParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params, ctx) => {\n const innerParams = unwrapRequest(params.request);\n const cat = getCatalog();\n // The extension sends user-supplied ATTACH options as an IPC-serialized\n // RecordBatch of typed columns — one column per option. Deserialize\n // once here so workers see an ergonomic {name: value} dict instead of\n // raw bytes. Nullable / absent → {}.\n const optionsDict = decodeOptionsBatch(innerParams.options);\n const result = await cat.attach(\n innerParams.name,\n optionsDict,\n innerParams.data_version_spec ?? null,\n innerParams.implementation_version ?? null,\n );\n // Seal the attach value into an AEAD envelope bound to the caller's\n // identity before it leaves the worker (HTTP transport; pass-through\n // when there is no signing key).\n const sealedAttach = await sealAttach(\n toUint8Array(result.attach_opaque_data),\n (ctx as CallContext | undefined)?.auth,\n signingKey,\n );\n return wrapResult({\n attach_opaque_data: sealedAttach,\n supports_transactions: result.supports_transactions,\n supports_time_travel: result.supports_time_travel,\n catalog_version_frozen: result.catalog_version_frozen,\n catalog_version: result.catalog_version,\n attach_opaque_data_required: result.attach_opaque_data_required ?? true,\n default_schema: result.default_schema ?? \"main\",\n settings: result.settings ?? [],\n secret_types: result.secret_types ?? [],\n attach_catalogs: result.attach_catalogs ?? [],\n comment: result.comment ?? null,\n tags: result.tags ?? {},\n // True so DuckDB will route catalog_table_column_statistics_get RPCs\n // to our handler for tables whose TableInfo.supports_column_statistics\n // is also true. Catalogs that never serve column stats can override\n // this in attach() via CatalogAttachResult.supports_column_statistics.\n supports_column_statistics: result.supports_column_statistics ?? true,\n // Protocol 1.3.0: functions the worker asks the client to publish into\n // its global namespace. Empty unless the catalog advertises them —\n // but the columns must still be present, since the extension pins the\n // full CatalogAttachResult field list on the response schema.\n global_functions: result.global_functions ?? [],\n global_function_prefix: result.global_function_prefix ?? \"\",\n resolved_data_version: result.resolved_data_version ?? null,\n resolved_implementation_version: result.resolved_implementation_version ?? null,\n }, CatalogAttachResultSchema);\n },\n });\n\n // catalog_detach\n catalogUnary(protocol, signingKey, \"catalog_detach\", {\n params: CatalogDetachParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.detach(toUint8Array(params.attach_opaque_data));\n return {};\n },\n });\n\n // catalog_create\n catalogUnary(protocol, signingKey, \"catalog_create\", {\n params: CatalogCreateParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.create(params.name, params.on_conflict, params.options);\n return {};\n },\n });\n\n // catalog_drop\n catalogUnary(protocol, signingKey, \"catalog_drop\", {\n params: CatalogDropParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.drop(params.name);\n return {};\n },\n });\n\n // catalog_version\n catalogUnary(protocol, signingKey, \"catalog_version\", {\n params: CatalogVersionParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const version = await cat.version(\n toUint8Array(params.attach_opaque_data),\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return wrapResult({ version }, CatalogVersionResultSchema);\n },\n });\n\n // catalog_transaction_begin — bespoke: it must keep the *sealed* attach\n // envelope to bind the transaction envelope's AAD, so it cannot route\n // through catalogUnary (which would replace it with plaintext).\n protocol.unary(\"catalog_transaction_begin\", {\n params: CatalogTransactionBeginParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params, ctx) => {\n const auth = (ctx as CallContext | undefined)?.auth;\n const sealedAttach =\n params.attach_opaque_data != null ? toUint8Array(params.attach_opaque_data) : new Uint8Array(0);\n const attachPlain = await openAttach(sealedAttach, auth, signingKey);\n const cat = getCatalog();\n const txPlain = await cat.transactionBegin(attachPlain);\n // Seal the transaction value, binding it to the caller's identity and\n // the parent attach envelope it was minted under. null → null.\n const transaction_opaque_data =\n txPlain != null ? await sealTransaction(toUint8Array(txPlain), sealedAttach, auth, signingKey) : null;\n return wrapResult({ transaction_opaque_data }, CatalogTransactionBeginResultSchema);\n },\n });\n\n // catalog_transaction_commit\n catalogUnary(protocol, signingKey, \"catalog_transaction_commit\", {\n params: CatalogTransactionCommitParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.transactionCommit(\n toUint8Array(params.attach_opaque_data),\n toUint8Array(params.transaction_opaque_data)\n );\n return {};\n },\n });\n\n // catalog_transaction_rollback\n catalogUnary(protocol, signingKey, \"catalog_transaction_rollback\", {\n params: CatalogTransactionRollbackParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.transactionRollback(\n toUint8Array(params.attach_opaque_data),\n toUint8Array(params.transaction_opaque_data)\n );\n return {};\n },\n });\n\n // catalog_schemas\n catalogUnary(protocol, signingKey, \"catalog_schemas\", {\n params: CatalogSchemasParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const schemas = await cat.schemas(\n toUint8Array(params.attach_opaque_data),\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return wrapResult({\n items: schemas.map((s) => encodeSchemaInfo(s)),\n }, CatalogSchemasResultSchema);\n },\n });\n\n // catalog_copy_from_formats — catalog-level (not schema-scoped). Lists the\n // custom COPY ... FROM formats this catalog advertises; empty list when none.\n catalogUnary(protocol, signingKey, \"catalog_copy_from_formats\", {\n params: CatalogCopyFromFormatsParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const formats = await cat.copyFromFormats(\n toUint8Array(params.attach_opaque_data),\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined,\n );\n return wrapResult({\n items: formats.map((f) => encodeCopyFromFormatInfo(f)),\n }, CatalogCopyFromFormatsResultSchema);\n },\n });\n\n // catalog_schema_get\n catalogUnary(protocol, signingKey, \"catalog_schema_get\", {\n params: CatalogSchemaGetParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const info = await cat.schemaGet(\n toUint8Array(params.attach_opaque_data),\n params.path,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return wrapResult({\n items: info ? [encodeSchemaInfo(info)] : [],\n }, CatalogSchemaGetResultSchema);\n },\n });\n\n // catalog_schema_create\n catalogUnary(protocol, signingKey, \"catalog_schema_create\", {\n params: CatalogSchemaCreateParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.schemaCreate(\n toUint8Array(params.attach_opaque_data),\n params.path,\n params.comment,\n null, // tags\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_schema_drop\n catalogUnary(protocol, signingKey, \"catalog_schema_drop\", {\n params: CatalogSchemaDropParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.schemaDrop(\n toUint8Array(params.attach_opaque_data),\n params.path,\n params.ignore_not_found,\n params.cascade,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_schema_contents_tables\n catalogUnary(protocol, signingKey, \"catalog_schema_contents_tables\", {\n params: CatalogSchemaContentsTablesParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const tables = await cat.schemaContentsTables(\n toUint8Array(params.attach_opaque_data),\n params.path,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return wrapResult({\n items: tables.map((t) => encodeTableInfo(t)),\n }, CatalogSchemaContentsTablesResultSchema);\n },\n });\n\n // catalog_schema_contents_views\n catalogUnary(protocol, signingKey, \"catalog_schema_contents_views\", {\n params: CatalogSchemaContentsViewsParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const views = await cat.schemaContentsViews(\n toUint8Array(params.attach_opaque_data),\n params.path,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return wrapResult({\n items: views.map((v) => encodeViewInfo(v)),\n }, CatalogSchemaContentsViewsResultSchema);\n },\n });\n\n // catalog_schema_contents_functions\n catalogUnary(protocol, signingKey, \"catalog_schema_contents_functions\", {\n params: CatalogSchemaContentsFunctionsParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const funcs = await cat.schemaContentsFunctions(\n toUint8Array(params.attach_opaque_data),\n params.path,\n decodeDictValue(params.type),\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return wrapResult({\n items: funcs.map((f) => encodeFunctionInfo(f)),\n }, CatalogSchemaContentsFunctionsResultSchema);\n },\n });\n}\n",
|
|
59
|
+
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Catalog admin handlers: attach/detach/create/drop, version, transactions,\n// schemas (list, get, create, drop), schema contents listings.\n\nimport { type VgiSchema, schema, type VgiField, field, type VgiDataType, binary, utf8, bool } from \"../../../arrow/index.js\";\nimport { Protocol, type CallContext } from \"@query-farm/vgi-rpc\";\nimport { encodeSchemaInfo, encodeTableInfo, encodeViewInfo, encodeCatalogInfo } from \"../../../generated/vgi-client.js\";\nimport { encodeFunctionInfoOnce } from \"../../../catalog/item-encoding.js\";\nimport { encodeCopyFromFormatInfo } from \"../../../catalog/interface.js\";\nimport {\n CatalogAttachParamsSchema,\n CatalogAttachResultSchema,\n CatalogCatalogsParamsSchema,\n CatalogCatalogsResultSchema,\n CatalogCopyFromFormatsParamsSchema,\n CatalogCopyFromFormatsResultSchema,\n CatalogCreateParamsSchema,\n CatalogDetachParamsSchema,\n CatalogDropParamsSchema,\n CatalogSchemaContentsFunctionsParamsSchema,\n CatalogSchemaContentsFunctionsResultSchema,\n CatalogSchemaContentsTablesParamsSchema,\n CatalogSchemaContentsTablesResultSchema,\n CatalogSchemaContentsViewsParamsSchema,\n CatalogSchemaContentsViewsResultSchema,\n CatalogSchemaCreateParamsSchema,\n CatalogSchemaDropParamsSchema,\n CatalogSchemaGetParamsSchema,\n CatalogSchemaGetResultSchema,\n CatalogSchemasParamsSchema,\n CatalogSchemasResultSchema,\n CatalogTransactionBeginParamsSchema,\n CatalogTransactionBeginResultSchema,\n CatalogTransactionCommitParamsSchema,\n CatalogTransactionRollbackParamsSchema,\n CatalogVersionParamsSchema,\n CatalogVersionResultSchema,\n} from \"../../../generated/vgi-protocol-schemas.js\";\nimport { toUint8Array } from \"../../../util/bytes.js\";\nimport { decodeDictValue } from \"../../../util/arrow/index.js\";\nimport {\n REQUEST_PARAMS_SCHEMA,\n RESULT_BINARY_SCHEMA,\n unwrapRequest,\n wrapResult,\n} from \"../shared.js\";\nimport {\n type GetCatalog,\n decodeOptionsBatch,\n emptyResultSchema,\n catalogUnary,\n sealAttach,\n openAttach,\n sealTransaction,\n} from \"./shared.js\";\n\nexport function registerCatalogAdminMethods(protocol: Protocol, getCatalog: GetCatalog, signingKey?: Uint8Array): void {\n // catalog_catalogs\n catalogUnary(protocol, signingKey, \"catalog_catalogs\", {\n params: CatalogCatalogsParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async () => {\n const cat = getCatalog();\n // Each catalog advertised as an IPC-serialized CatalogInfo\n // {name, implementation_version?, data_version_spec?}. Versioned workers\n // override catalogsInfo() to supply real values; otherwise both version\n // fields default to null.\n const infos = cat.catalogsInfo\n ? await cat.catalogsInfo()\n : cat.catalogs().map((name) => ({\n name,\n implementation_version: null,\n data_version_spec: null,\n attach_option_specs: [],\n releases: [],\n }));\n const items = infos.map((info) => encodeCatalogInfo(info));\n return wrapResult({ items }, CatalogCatalogsResultSchema);\n },\n });\n\n // catalog_attach (params wrapped in request: Binary like bind/init)\n protocol.unary(\"catalog_attach\", {\n params: CatalogAttachParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params, ctx) => {\n const innerParams = unwrapRequest(params.request);\n const cat = getCatalog();\n // The extension sends user-supplied ATTACH options as an IPC-serialized\n // RecordBatch of typed columns — one column per option. Deserialize\n // once here so workers see an ergonomic {name: value} dict instead of\n // raw bytes. Nullable / absent → {}.\n const optionsDict = decodeOptionsBatch(innerParams.options);\n const result = await cat.attach(\n innerParams.name,\n optionsDict,\n innerParams.data_version_spec ?? null,\n innerParams.implementation_version ?? null,\n );\n // Seal the attach value into an AEAD envelope bound to the caller's\n // identity before it leaves the worker (HTTP transport; pass-through\n // when there is no signing key).\n const sealedAttach = await sealAttach(\n toUint8Array(result.attach_opaque_data),\n (ctx as CallContext | undefined)?.auth,\n signingKey,\n );\n return wrapResult({\n attach_opaque_data: sealedAttach,\n supports_transactions: result.supports_transactions,\n supports_time_travel: result.supports_time_travel,\n catalog_version_frozen: result.catalog_version_frozen,\n catalog_version: result.catalog_version,\n attach_opaque_data_required: result.attach_opaque_data_required ?? true,\n default_schema: result.default_schema ?? \"main\",\n settings: result.settings ?? [],\n secret_types: result.secret_types ?? [],\n attach_catalogs: result.attach_catalogs ?? [],\n comment: result.comment ?? null,\n tags: result.tags ?? {},\n // True so DuckDB will route catalog_table_column_statistics_get RPCs\n // to our handler for tables whose TableInfo.supports_column_statistics\n // is also true. Catalogs that never serve column stats can override\n // this in attach() via CatalogAttachResult.supports_column_statistics.\n supports_column_statistics: result.supports_column_statistics ?? true,\n // Protocol 1.3.0: functions the worker asks the client to publish into\n // its global namespace. Empty unless the catalog advertises them —\n // but the columns must still be present, since the extension pins the\n // full CatalogAttachResult field list on the response schema.\n global_functions: result.global_functions ?? [],\n global_function_prefix: result.global_function_prefix ?? \"\",\n resolved_data_version: result.resolved_data_version ?? null,\n resolved_implementation_version: result.resolved_implementation_version ?? null,\n }, CatalogAttachResultSchema);\n },\n });\n\n // catalog_detach\n catalogUnary(protocol, signingKey, \"catalog_detach\", {\n params: CatalogDetachParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.detach(toUint8Array(params.attach_opaque_data));\n return {};\n },\n });\n\n // catalog_create\n catalogUnary(protocol, signingKey, \"catalog_create\", {\n params: CatalogCreateParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.create(params.name, params.on_conflict, params.options);\n return {};\n },\n });\n\n // catalog_drop\n catalogUnary(protocol, signingKey, \"catalog_drop\", {\n params: CatalogDropParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.drop(params.name);\n return {};\n },\n });\n\n // catalog_version\n catalogUnary(protocol, signingKey, \"catalog_version\", {\n params: CatalogVersionParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const version = await cat.version(\n toUint8Array(params.attach_opaque_data),\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return wrapResult({ version }, CatalogVersionResultSchema);\n },\n });\n\n // catalog_transaction_begin — bespoke: it must keep the *sealed* attach\n // envelope to bind the transaction envelope's AAD, so it cannot route\n // through catalogUnary (which would replace it with plaintext).\n protocol.unary(\"catalog_transaction_begin\", {\n params: CatalogTransactionBeginParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params, ctx) => {\n const auth = (ctx as CallContext | undefined)?.auth;\n const sealedAttach =\n params.attach_opaque_data != null ? toUint8Array(params.attach_opaque_data) : new Uint8Array(0);\n const attachPlain = await openAttach(sealedAttach, auth, signingKey);\n const cat = getCatalog();\n const txPlain = await cat.transactionBegin(attachPlain);\n // Seal the transaction value, binding it to the caller's identity and\n // the parent attach envelope it was minted under. null → null.\n const transaction_opaque_data =\n txPlain != null ? await sealTransaction(toUint8Array(txPlain), sealedAttach, auth, signingKey) : null;\n return wrapResult({ transaction_opaque_data }, CatalogTransactionBeginResultSchema);\n },\n });\n\n // catalog_transaction_commit\n catalogUnary(protocol, signingKey, \"catalog_transaction_commit\", {\n params: CatalogTransactionCommitParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.transactionCommit(\n toUint8Array(params.attach_opaque_data),\n toUint8Array(params.transaction_opaque_data)\n );\n return {};\n },\n });\n\n // catalog_transaction_rollback\n catalogUnary(protocol, signingKey, \"catalog_transaction_rollback\", {\n params: CatalogTransactionRollbackParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.transactionRollback(\n toUint8Array(params.attach_opaque_data),\n toUint8Array(params.transaction_opaque_data)\n );\n return {};\n },\n });\n\n // catalog_schemas\n catalogUnary(protocol, signingKey, \"catalog_schemas\", {\n params: CatalogSchemasParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const schemas = await cat.schemas(\n toUint8Array(params.attach_opaque_data),\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return wrapResult({\n items: schemas.map((s) => encodeSchemaInfo(s)),\n }, CatalogSchemasResultSchema);\n },\n });\n\n // catalog_copy_from_formats — catalog-level (not schema-scoped). Lists the\n // custom COPY ... FROM formats this catalog advertises; empty list when none.\n catalogUnary(protocol, signingKey, \"catalog_copy_from_formats\", {\n params: CatalogCopyFromFormatsParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const formats = await cat.copyFromFormats(\n toUint8Array(params.attach_opaque_data),\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined,\n );\n return wrapResult({\n items: formats.map((f) => encodeCopyFromFormatInfo(f)),\n }, CatalogCopyFromFormatsResultSchema);\n },\n });\n\n // catalog_schema_get\n catalogUnary(protocol, signingKey, \"catalog_schema_get\", {\n params: CatalogSchemaGetParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const info = await cat.schemaGet(\n toUint8Array(params.attach_opaque_data),\n params.path,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return wrapResult({\n items: info ? [encodeSchemaInfo(info)] : [],\n }, CatalogSchemaGetResultSchema);\n },\n });\n\n // catalog_schema_create\n catalogUnary(protocol, signingKey, \"catalog_schema_create\", {\n params: CatalogSchemaCreateParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.schemaCreate(\n toUint8Array(params.attach_opaque_data),\n params.path,\n params.comment,\n null, // tags\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_schema_drop\n catalogUnary(protocol, signingKey, \"catalog_schema_drop\", {\n params: CatalogSchemaDropParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.schemaDrop(\n toUint8Array(params.attach_opaque_data),\n params.path,\n params.ignore_not_found,\n params.cascade,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_schema_contents_tables\n catalogUnary(protocol, signingKey, \"catalog_schema_contents_tables\", {\n params: CatalogSchemaContentsTablesParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const tables = await cat.schemaContentsTables(\n toUint8Array(params.attach_opaque_data),\n params.path,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return wrapResult({\n items: tables.map((t) => encodeTableInfo(t)),\n }, CatalogSchemaContentsTablesResultSchema);\n },\n });\n\n // catalog_schema_contents_views\n catalogUnary(protocol, signingKey, \"catalog_schema_contents_views\", {\n params: CatalogSchemaContentsViewsParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const views = await cat.schemaContentsViews(\n toUint8Array(params.attach_opaque_data),\n params.path,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return wrapResult({\n items: views.map((v) => encodeViewInfo(v)),\n }, CatalogSchemaContentsViewsResultSchema);\n },\n });\n\n // catalog_schema_contents_functions\n catalogUnary(protocol, signingKey, \"catalog_schema_contents_functions\", {\n params: CatalogSchemaContentsFunctionsParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const funcs = await cat.schemaContentsFunctions(\n toUint8Array(params.attach_opaque_data),\n params.path,\n decodeDictValue(params.type),\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n // A frozen item (a descriptor catalog's cached listing) is encoded once;\n // anything else is encoded per call, as before (see item-encoding.ts).\n return wrapResult({\n items: funcs.map((f) => encodeFunctionInfoOnce(f)),\n }, CatalogSchemaContentsFunctionsResultSchema);\n },\n });\n}\n",
|
|
56
60
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Catalog table handlers: table_get/create/drop, scan_function_get,\n// column_statistics_get, comment_set, rename, plus all column_* mutations.\n\nimport { type VgiSchema, schema, type VgiField, field, type VgiDataType, binary, utf8, bool, int32, list } from \"../../../arrow/index.js\";\nimport { Protocol } from \"@query-farm/vgi-rpc\";\nimport { encodeTableInfo } from \"../../../generated/vgi-client.js\";\nimport {\n CatalogTableColumnAddParamsSchema,\n CatalogTableColumnDefaultDropParamsSchema,\n CatalogTableColumnDefaultSetParamsSchema,\n CatalogTableColumnDropParamsSchema,\n CatalogTableColumnRenameParamsSchema,\n CatalogTableColumnStatisticsGetParamsSchema,\n CatalogTableColumnTypeChangeParamsSchema,\n CatalogTableCommentSetParamsSchema,\n CatalogTableCreateParamsSchema,\n CatalogTableDropParamsSchema,\n CatalogTableGetParamsSchema,\n CatalogTableGetResultSchema,\n CatalogTableNotNullDropParamsSchema,\n CatalogTableNotNullSetParamsSchema,\n CatalogTableRenameParamsSchema,\n CatalogTableScanBranchesGetParamsSchema,\n CatalogTableScanFunctionGetParamsSchema,\n ScanBranchesResultSchema,\n ScanFunctionResultSchema,\n} from \"../../../generated/vgi-protocol-schemas.js\";\nimport { toUint8Array } from \"../../../util/bytes.js\";\nimport {\n RESULT_BINARY_SCHEMA,\n RESULT_BINARY_NULLABLE_SCHEMA,\n wrapResult,\n} from \"../shared.js\";\nimport {\n type GetCatalog,\n emptyResultSchema,\n catalogUnary,\n} from \"./shared.js\";\n\nexport function registerCatalogTableMethods(protocol: Protocol, getCatalog: GetCatalog, signingKey?: Uint8Array): void {\n // catalog_table_get\n catalogUnary(protocol, signingKey, \"catalog_table_get\", {\n params: CatalogTableGetParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const info = await cat.tableGet(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.at_unit,\n params.at_value,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return wrapResult({\n items: info ? [encodeTableInfo(info)] : [],\n }, CatalogTableGetResultSchema);\n },\n });\n\n // catalog_table_create\n catalogUnary(protocol, signingKey, \"catalog_table_create\", {\n params: CatalogTableCreateParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.tableCreate(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n toUint8Array(params.columns),\n params.on_conflict,\n params.not_null_constraints ?? [],\n params.unique_constraints ?? [],\n params.check_constraints ?? [],\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_table_drop\n catalogUnary(protocol, signingKey, \"catalog_table_drop\", {\n params: CatalogTableDropParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.tableDrop(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.ignore_not_found,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_table_column_statistics_get\n catalogUnary(protocol, signingKey, \"catalog_table_column_statistics_get\", {\n params: CatalogTableColumnStatisticsGetParamsSchema,\n result: RESULT_BINARY_NULLABLE_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const stats = await cat.tableColumnStatisticsGet(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined,\n );\n return { result: stats?.bytes ?? null };\n },\n });\n\n // catalog_table_scan_function_get\n catalogUnary(protocol, signingKey, \"catalog_table_scan_function_get\", {\n params: CatalogTableScanFunctionGetParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const scanResult = await cat.tableScanFunctionGet(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.at_unit,\n params.at_value,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return wrapResult(scanResult, ScanFunctionResultSchema);\n },\n });\n\n // catalog_table_scan_branches_get — branches-aware variant of\n // scan_function_get. The branches-aware C++ extension calls this for every\n // table scan; single-source catalogs synthesise a one-branch result.\n catalogUnary(protocol, signingKey, \"catalog_table_scan_branches_get\", {\n params: CatalogTableScanBranchesGetParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const branchesResult = await cat.tableScanBranchesGet(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.at_unit,\n params.at_value,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return wrapResult(branchesResult, ScanBranchesResultSchema);\n },\n });\n\n // catalog_table_comment_set\n catalogUnary(protocol, signingKey, \"catalog_table_comment_set\", {\n params: CatalogTableCommentSetParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.tableCommentSet(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.comment,\n params.ignore_not_found,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_table_rename\n catalogUnary(protocol, signingKey, \"catalog_table_rename\", {\n params: CatalogTableRenameParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.tableRename(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.new_name,\n params.ignore_not_found,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_table_column_add\n catalogUnary(protocol, signingKey, \"catalog_table_column_add\", {\n params: CatalogTableColumnAddParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.tableColumnAdd(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.column_name,\n params.column_type,\n params.default_value,\n params.ignore_not_found,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_table_column_drop\n catalogUnary(protocol, signingKey, \"catalog_table_column_drop\", {\n params: CatalogTableColumnDropParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.tableColumnDrop(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.column_name,\n params.ignore_not_found,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_table_column_rename\n catalogUnary(protocol, signingKey, \"catalog_table_column_rename\", {\n params: CatalogTableColumnRenameParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.tableColumnRename(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.column_name,\n params.new_name,\n params.ignore_not_found,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_table_column_default_set\n catalogUnary(protocol, signingKey, \"catalog_table_column_default_set\", {\n params: CatalogTableColumnDefaultSetParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.tableColumnDefaultSet(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.column_name,\n params.default_value,\n params.ignore_not_found,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_table_column_default_drop\n catalogUnary(protocol, signingKey, \"catalog_table_column_default_drop\", {\n params: CatalogTableColumnDefaultDropParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.tableColumnDefaultDrop(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.column_name,\n params.ignore_not_found,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_table_column_type_change\n catalogUnary(protocol, signingKey, \"catalog_table_column_type_change\", {\n params: CatalogTableColumnTypeChangeParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.tableColumnTypeChange(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.column_name,\n params.new_type,\n params.ignore_not_found,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_table_not_null_set\n catalogUnary(protocol, signingKey, \"catalog_table_not_null_set\", {\n params: CatalogTableNotNullSetParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.tableNotNullSet(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.column_name,\n params.ignore_not_found,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_table_not_null_drop\n catalogUnary(protocol, signingKey, \"catalog_table_not_null_drop\", {\n params: CatalogTableNotNullDropParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.tableNotNullDrop(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.column_name,\n params.ignore_not_found,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n}\n",
|
|
57
61
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Catalog view handlers: view_get/create/drop/rename/comment_set.\n\nimport { type VgiSchema, schema, type VgiField, field, type VgiDataType, binary, utf8 } from \"../../../arrow/index.js\";\nimport { Protocol } from \"@query-farm/vgi-rpc\";\nimport { encodeViewInfo } from \"../../../generated/vgi-client.js\";\nimport {\n CatalogViewCommentSetParamsSchema,\n CatalogViewCreateParamsSchema,\n CatalogViewDropParamsSchema,\n CatalogViewGetParamsSchema,\n CatalogViewGetResultSchema,\n CatalogViewRenameParamsSchema,\n} from \"../../../generated/vgi-protocol-schemas.js\";\nimport { toUint8Array } from \"../../../util/bytes.js\";\nimport {\n RESULT_BINARY_SCHEMA,\n wrapResult,\n} from \"../shared.js\";\nimport {\n type GetCatalog,\n emptyResultSchema,\n catalogUnary,\n} from \"./shared.js\";\n\nexport function registerCatalogViewMethods(protocol: Protocol, getCatalog: GetCatalog, signingKey?: Uint8Array): void {\n // catalog_view_get\n catalogUnary(protocol, signingKey, \"catalog_view_get\", {\n params: CatalogViewGetParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const info = await cat.viewGet(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return wrapResult({\n items: info ? [encodeViewInfo(info)] : [],\n }, CatalogViewGetResultSchema);\n },\n });\n\n // catalog_view_create\n catalogUnary(protocol, signingKey, \"catalog_view_create\", {\n params: CatalogViewCreateParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.viewCreate(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.definition,\n params.on_conflict,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_view_drop\n catalogUnary(protocol, signingKey, \"catalog_view_drop\", {\n params: CatalogViewDropParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.viewDrop(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.ignore_not_found,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_view_rename\n catalogUnary(protocol, signingKey, \"catalog_view_rename\", {\n params: CatalogViewRenameParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.viewRename(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.new_name,\n params.ignore_not_found,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_view_comment_set\n catalogUnary(protocol, signingKey, \"catalog_view_comment_set\", {\n params: CatalogViewCommentSetParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.viewCommentSet(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.comment,\n params.ignore_not_found,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n}\n",
|
|
58
62
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// Catalog macro handlers: macro_get/create/drop, schema_contents_macros.\n\nimport { type VgiSchema, schema, type VgiField, field, type VgiDataType, binary, utf8, bool } from \"../../../arrow/index.js\";\nimport { Protocol } from \"@query-farm/vgi-rpc\";\nimport { encodeMacroInfo } from \"../../../generated/vgi-client.js\";\nimport {\n CatalogMacroCreateParamsSchema,\n CatalogMacroDropParamsSchema,\n CatalogMacroGetParamsSchema,\n CatalogMacroGetResultSchema,\n CatalogSchemaContentsMacrosParamsSchema,\n CatalogSchemaContentsMacrosResultSchema,\n} from \"../../../generated/vgi-protocol-schemas.js\";\nimport type { MacroType } from \"../../../catalog/interface.js\";\nimport { toUint8Array } from \"../../../util/bytes.js\";\nimport { decodeDictValue } from \"../../../util/arrow/index.js\";\nimport {\n REQUEST_PARAMS_SCHEMA,\n RESULT_BINARY_SCHEMA,\n unwrapRequest,\n wrapResult,\n} from \"../shared.js\";\nimport {\n type GetCatalog,\n emptyResultSchema,\n catalogUnary,\n} from \"./shared.js\";\n\nexport function registerCatalogMacroMethods(protocol: Protocol, getCatalog: GetCatalog, signingKey?: Uint8Array): void {\n // catalog_macro_get\n catalogUnary(protocol, signingKey, \"catalog_macro_get\", {\n params: CatalogMacroGetParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const info = await cat.macroGet(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return wrapResult({\n items: info ? [encodeMacroInfo(info)] : [],\n }, CatalogMacroGetResultSchema);\n },\n });\n\n // catalog_macro_create\n catalogUnary(protocol, signingKey, \"catalog_macro_create\", {\n params: CatalogMacroCreateParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n const innerParams = unwrapRequest(params.request);\n await cat.macroCreate(\n toUint8Array(innerParams.attach_opaque_data),\n innerParams.schema_path,\n innerParams.name,\n innerParams.macro_type as MacroType,\n innerParams.parameters ? (Array.isArray(innerParams.parameters) ? innerParams.parameters : [...innerParams.parameters]) : [],\n innerParams.definition,\n innerParams.on_conflict,\n innerParams.parameter_default_values ? toUint8Array(innerParams.parameter_default_values) : null,\n innerParams.arguments_schema ? toUint8Array(innerParams.arguments_schema) : null,\n innerParams.transaction_opaque_data ? toUint8Array(innerParams.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_macro_drop\n catalogUnary(protocol, signingKey, \"catalog_macro_drop\", {\n params: CatalogMacroDropParamsSchema,\n result: emptyResultSchema,\n handler: async (params) => {\n const cat = getCatalog();\n await cat.macroDrop(\n toUint8Array(params.attach_opaque_data),\n params.schema_path,\n params.name,\n params.ignore_not_found,\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return {};\n },\n });\n\n // catalog_schema_contents_macros\n catalogUnary(protocol, signingKey, \"catalog_schema_contents_macros\", {\n params: CatalogSchemaContentsMacrosParamsSchema,\n result: RESULT_BINARY_SCHEMA,\n handler: async (params) => {\n const cat = getCatalog();\n const macros = await cat.schemaContentsMacros(\n toUint8Array(params.attach_opaque_data),\n params.path,\n decodeDictValue(params.type),\n params.transaction_opaque_data ? toUint8Array(params.transaction_opaque_data) : undefined\n );\n return wrapResult({\n items: macros.map((m) => encodeMacroInfo(m)),\n }, CatalogSchemaContentsMacrosResultSchema);\n },\n });\n}\n",
|
|
@@ -62,7 +66,7 @@
|
|
|
62
66
|
"// © Copyright 2025-2026, Query.Farm LLC - https://query.farm\n// SPDX-License-Identifier: Apache-2.0\n//\n// VENDORED ASSET — DO NOT EDIT BY HAND.\n// Browser build of the @query-farm/vgi client, authored in\n// vgi-web-frontend (`bun run build:landing-client`). The shared landing\n// page imports it from {prefix}/vgi-client.js to read catalog metadata\n// over the VGI protocol. Base64-embedded so it survives single-file\n// bundling (bun build) unchanged and is served as raw bytes.\n// Regenerate with scripts/vendor-client-bundle.mjs.\n\nconst CLIENT_BUNDLE_B64 =\n \"dmFyIHpEPU9iamVjdC5kZWZpbmVQcm9wZXJ0eTt2YXIgakQ9KHQpPT50O2Z1bmN0aW9uICREKHQsZSl7dGhpc1t0XT1qRC5iaW5kKG51bGwsZSl9dmFyIFplPSh0LGUpPT57Zm9yKHZhciByIGluIGUpekQodCxyLHtnZXQ6ZVtyXSxlbnVtZXJhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMCxzZXQ6JEQuYmluZChlLHIpfSl9O3ZhciBtPSh0LGUscik9PigpPT57aWYodCl0cnl7ZT10KHQ9MCl9Y2F0Y2gobil7cj1bbl19aWYocil0aHJvdyByWzBdO3JldHVybiBlfTtmdW5jdGlvbiBTYih0LGUpe3ZhciByPXt9O2Zvcih2YXIgbiBpbiB0KWlmKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0LG4pJiZlLmluZGV4T2Yobik8MClyW25dPXRbbl07aWYodCE9bnVsbCYmdHlwZW9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHM9PT0iZnVuY3Rpb24iKXtmb3IodmFyIGk9MCxuPU9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHModCk7aTxuLmxlbmd0aDtpKyspaWYoZS5pbmRleE9mKG5baV0pPDAmJk9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbCh0LG5baV0pKXJbbltpXV09dFtuW2ldXX1yZXR1cm4gcn1mdW5jdGlvbiBFKHQsZSxyLG4pe2Z1bmN0aW9uIGkocyl7cmV0dXJuIHMgaW5zdGFuY2VvZiByP3M6bmV3IHIoZnVuY3Rpb24obyl7byhzKX0pfXJldHVybiBuZXcocnx8KHI9UHJvbWlzZSkpKGZ1bmN0aW9uKHMsbyl7ZnVuY3Rpb24gYShmKXt0cnl7dShuLm5leHQoZikpfWNhdGNoKHApe28ocCl9fWZ1bmN0aW9uIGwoZil7dHJ5e3Uobi50aHJvdyhmKSl9Y2F0Y2gocCl7byhwKX19ZnVuY3Rpb24gdShmKXtmLmRvbmU/cyhmLnZhbHVlKTppKGYudmFsdWUpLnRoZW4oYSxsKX11KChuPW4uYXBwbHkodCxlfHxbXSkpLm5leHQoKSl9KX1mdW5jdGlvbiBCYih0KXt2YXIgZT10eXBlb2YgU3ltYm9sPT09ImZ1bmN0aW9uIiYmU3ltYm9sLml0ZXJhdG9yLHI9ZSYmdFtlXSxuPTA7aWYocilyZXR1cm4gci5jYWxsKHQpO2lmKHQmJnR5cGVvZiB0Lmxlbmd0aD09PSJudW1iZXIiKXJldHVybntuZXh0OmZ1bmN0aW9uKCl7aWYodCYmbj49dC5sZW5ndGgpdD12b2lkIDA7cmV0dXJue3ZhbHVlOnQmJnRbbisrXSxkb25lOiF0fX19O3Rocm93IFR5cGVFcnJvcihlPyJPYmplY3QgaXMgbm90IGl0ZXJhYmxlLiI6IlN5bWJvbC5pdGVyYXRvciBpcyBub3QgZGVmaW5lZC4iKX1mdW5jdGlvbiB5dCh0KXtyZXR1cm4gdGhpcyBpbnN0YW5jZW9mIHl0Pyh0aGlzLnY9dCx0aGlzKTpuZXcgeXQodCl9ZnVuY3Rpb24gaG4odCxlLHIpe2lmKCFTeW1ib2wuYXN5bmNJdGVyYXRvcil0aHJvdyBUeXBlRXJyb3IoIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLiIpO3ZhciBuPXIuYXBwbHkodCxlfHxbXSksaSxzPVtdO3JldHVybiBpPU9iamVjdC5jcmVhdGUoKHR5cGVvZiBBc3luY0l0ZXJhdG9yPT09ImZ1bmN0aW9uIj9Bc3luY0l0ZXJhdG9yOk9iamVjdCkucHJvdG90eXBlKSxhKCJuZXh0IiksYSgidGhyb3ciKSxhKCJyZXR1cm4iLG8pLGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXN9LGk7ZnVuY3Rpb24gbyh2KXtyZXR1cm4gZnVuY3Rpb24oSSl7cmV0dXJuIFByb21pc2UucmVzb2x2ZShJKS50aGVuKHYscCl9fWZ1bmN0aW9uIGEodixJKXtpZihuW3ZdKXtpZihpW3ZdPWZ1bmN0aW9uKEQpe3JldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihaLG10KXtzLnB1c2goW3YsRCxaLG10XSk+MXx8bCh2LEQpfSl9LEkpaVt2XT1JKGlbdl0pfX1mdW5jdGlvbiBsKHYsSSl7dHJ5e3Uoblt2XShJKSl9Y2F0Y2goRCl7ZyhzWzBdWzNdLEQpfX1mdW5jdGlvbiB1KHYpe3YudmFsdWUgaW5zdGFuY2VvZiB5dD9Qcm9taXNlLnJlc29sdmUodi52YWx1ZS52KS50aGVuKGYscCk6ZyhzWzBdWzJdLHYpfWZ1bmN0aW9uIGYodil7bCgibmV4dCIsdil9ZnVuY3Rpb24gcCh2KXtsKCJ0aHJvdyIsdil9ZnVuY3Rpb24gZyh2LEkpe2lmKHYoSSkscy5zaGlmdCgpLHMubGVuZ3RoKWwoc1swXVswXSxzWzBdWzFdKX19ZnVuY3Rpb24gaWModCl7dmFyIGUscjtyZXR1cm4gZT17fSxuKCJuZXh0IiksbigidGhyb3ciLGZ1bmN0aW9uKGkpe3Rocm93IGl9KSxuKCJyZXR1cm4iKSxlW1N5bWJvbC5pdGVyYXRvcl09ZnVuY3Rpb24oKXtyZXR1cm4gdGhpc30sZTtmdW5jdGlvbiBuKGkscyl7ZVtpXT10W2ldP2Z1bmN0aW9uKG8pe3JldHVybihyPSFyKT97dmFsdWU6eXQodFtpXShvKSksZG9uZTohMX06cz9zKG8pOm99OnN9fWZ1bmN0aW9uIGdpKHQpe2lmKCFTeW1ib2wuYXN5bmNJdGVyYXRvcil0aHJvdyBUeXBlRXJyb3IoIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLiIpO3ZhciBlPXRbU3ltYm9sLmFzeW5jSXRlcmF0b3JdLHI7cmV0dXJuIGU/ZS5jYWxsKHQpOih0PXR5cGVvZiBCYj09PSJmdW5jdGlvbiI/QmIodCk6dFtTeW1ib2wuaXRlcmF0b3JdKCkscj17fSxuKCJuZXh0IiksbigidGhyb3ciKSxuKCJyZXR1cm4iKSxyW1N5bWJvbC5hc3luY0l0ZXJhdG9yXT1mdW5jdGlvbigpe3JldHVybiB0aGlzfSxyKTtmdW5jdGlvbiBuKHMpe3Jbc109dFtzXSYmZnVuY3Rpb24obyl7cmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKGEsbCl7bz10W3NdKG8pLGkoYSxsLG8uZG9uZSxvLnZhbHVlKX0pfX1mdW5jdGlvbiBpKHMsbyxhLGwpe1Byb21pc2UucmVzb2x2ZShsKS50aGVuKGZ1bmN0aW9uKHUpe3Moe3ZhbHVlOnUsZG9uZTphfSl9LG8pfX12YXIgcG49KCk9Pnt9O3ZhciBBYixzYyxxRCxtbj0odCk9PnFELmVuY29kZSh0KTt2YXIgdnM9bSgoKT0+e0FiPW5ldyBUZXh0RGVjb2RlcigidXRmLTgiKSxzYz1BYi5kZWNvZGUuYmluZChBYikscUQ9bmV3IFRleHRFbmNvZGVyfSk7dmFyIFdEPSh0KT0+dHlwZW9mIHQ9PT0ibnVtYmVyIixEYj0odCk9PnR5cGVvZiB0PT09ImJvb2xlYW4iLHplPSh0KT0+dHlwZW9mIHQ9PT0iZnVuY3Rpb24iLEZyPSh0KT0+dCE9bnVsbCYmT2JqZWN0KHQpPT09dCxiaT0odCk9PkZyKHQpJiZ6ZSh0LnRoZW4pLHdpPSh0KT0+RnIodCkmJnplKHRbU3ltYm9sLml0ZXJhdG9yXSksVm49KHQpPT5Gcih0KSYmemUodFtTeW1ib2wuYXN5bmNJdGVyYXRvcl0pLG5mPSh0KT0+RnIodCkmJkZyKHQuc2NoZW1hKSxzZj0odCk9PkZyKHQpJiYoImRvbmUiaW4gdCkmJigidmFsdWUiaW4gdCksb2Y9KHQpPT5Gcih0KSYmemUodC5zdGF0KSYmV0QodC5mZCksYWY9KHQpPT5Gcih0KSYmQmwodC5ib2R5KSxjZj0odCk9PigiX2dldERPTVN0cmVhbSJpbiB0KSYmKCJfZ2V0Tm9kZVN0cmVhbSJpbiB0KSx4Yj0odCk9PkZyKHQpJiZ6ZSh0LmFib3J0KSYmemUodC5nZXRXcml0ZXIpJiYhY2YodCksQmw9KHQpPT5Gcih0KSYmemUodC5jYW5jZWwpJiZ6ZSh0LmdldFJlYWRlcikmJiFjZih0KSxUYj0odCk9PkZyKHQpJiZ6ZSh0LmVuZCkmJnplKHQud3JpdGUpJiZEYih0LndyaXRhYmxlKSYmIWNmKHQpLGxmPSh0KT0+RnIodCkmJnplKHQucmVhZCkmJnplKHQucGlwZSkmJkRiKHQucmVhZGFibGUpJiYhY2YodCksRWI9KHQpPT5Gcih0KSYmemUodC5jbGVhcikmJnplKHQuYnl0ZXMpJiZ6ZSh0LnBvc2l0aW9uKSYmemUodC5zZXRQb3NpdGlvbikmJnplKHQuY2FwYWNpdHkpJiZ6ZSh0LmdldEJ1ZmZlcklkZW50aWZpZXIpJiZ6ZSh0LmNyZWF0ZUxvbmcpO3ZhciBLcD17fTtaZShLcCx7Y29tcGFyZUFycmF5TGlrZTooKT0+WXAsam9pblVpbnQ4QXJyYXlzOigpPT55bixtZW1jcHk6KCk9PlNsLHJlYmFzZVZhbHVlT2Zmc2V0czooKT0+ZmYsdG9BcnJheUJ1ZmZlclZpZXc6KCk9Pnd0LHRvQXJyYXlCdWZmZXJWaWV3QXN5bmNJdGVyYXRvcjooKT0+dmksdG9BcnJheUJ1ZmZlclZpZXdJdGVyYXRvcjooKT0+bnMsdG9CaWdJbnQ2NEFycmF5OigpPT51Zix0b0JpZ1VpbnQ2NEFycmF5OigpPT5YRCx0b0Zsb2F0MzJBcnJheTooKT0+WkQsdG9GbG9hdDMyQXJyYXlBc3luY0l0ZXJhdG9yOigpPT5weCx0b0Zsb2F0MzJBcnJheUl0ZXJhdG9yOigpPT5veCx0b0Zsb2F0NjRBcnJheTooKT0+UUQsdG9GbG9hdDY0QXJyYXlBc3luY0l0ZXJhdG9yOigpPT5teCx0b0Zsb2F0NjRBcnJheUl0ZXJhdG9yOigpPT5heCx0b0ludDE2QXJyYXk6KCk9PktELHRvSW50MTZBcnJheUFzeW5jSXRlcmF0b3I6KCk9PnV4LHRvSW50MTZBcnJheUl0ZXJhdG9yOigpPT5yeCx0b0ludDMyQXJyYXk6KCk9Pm9hLHRvSW50MzJBcnJheUFzeW5jSXRlcmF0b3I6KCk9PmZ4LHRvSW50MzJBcnJheUl0ZXJhdG9yOigpPT5ueCx0b0ludDhBcnJheTooKT0+WUQsdG9JbnQ4QXJyYXlBc3luY0l0ZXJhdG9yOigpPT5seCx0b0ludDhBcnJheUl0ZXJhdG9yOigpPT5leCx0b1VpbnQxNkFycmF5OigpPT5HRCx0b1VpbnQxNkFycmF5QXN5bmNJdGVyYXRvcjooKT0+ZHgsdG9VaW50MTZBcnJheUl0ZXJhdG9yOigpPT5peCx0b1VpbnQzMkFycmF5OigpPT5KRCx0b1VpbnQzMkFycmF5QXN5bmNJdGVyYXRvcjooKT0+aHgsdG9VaW50MzJBcnJheUl0ZXJhdG9yOigpPT5zeCx0b1VpbnQ4QXJyYXk6KCk9PkMsdG9VaW50OEFycmF5QXN5bmNJdGVyYXRvcjooKT0+SHAsdG9VaW50OEFycmF5SXRlcmF0b3I6KCk9PldwLHRvVWludDhDbGFtcGVkQXJyYXk6KCk9PnR4LHRvVWludDhDbGFtcGVkQXJyYXlBc3luY0l0ZXJhdG9yOigpPT55eCx0b1VpbnQ4Q2xhbXBlZEFycmF5SXRlcmF0b3I6KCk9PmN4fSk7ZnVuY3Rpb24gSEQodCl7bGV0IGU9dFswXT9bdFswXV06W10scixuLGkscztmb3IobGV0IG8sYSxsPTAsdT0wLGY9dC5sZW5ndGg7KytsPGY7KXtpZihvPWVbdV0sYT10W2xdLCFvfHwhYXx8by5idWZmZXIhPT1hLmJ1ZmZlcnx8YS5ieXRlT2Zmc2V0PG8uYnl0ZU9mZnNldCl7YSYmKGVbKyt1XT1hKTtjb250aW51ZX1pZih7Ynl0ZU9mZnNldDpyLGJ5dGVMZW5ndGg6aX09byx7Ynl0ZU9mZnNldDpuLGJ5dGVMZW5ndGg6c309YSxyK2k8bnx8bitzPHIpe2EmJihlWysrdV09YSk7Y29udGludWV9ZVt1XT1uZXcgVWludDhBcnJheShvLmJ1ZmZlcixyLG4tcitzKX1yZXR1cm4gZX1mdW5jdGlvbiBTbCh0LGUscj0wLG49ZS5ieXRlTGVuZ3RoKXtsZXQgaT10LmJ5dGVMZW5ndGgscz1uZXcgVWludDhBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQsaSksbz1uZXcgVWludDhBcnJheShlLmJ1ZmZlcixlLmJ5dGVPZmZzZXQsTWF0aC5taW4obixpKSk7cmV0dXJuIHMuc2V0KG8sciksdH1mdW5jdGlvbiB5bih0LGUpe2xldCByPUhEKHQpLG49ci5yZWR1Y2UoKGYscCk9PmYrcC5ieXRlTGVuZ3RoLDApLGkscyxvLGE9MCxsPS0xLHU9TWF0aC5taW4oZXx8TnVtYmVyLlBPU0lUSVZFX0lORklOSVRZLG4pO2ZvcihsZXQgZj1yLmxlbmd0aDsrK2w8Zjspe2lmKGk9cltsXSxzPWkuc3ViYXJyYXkoMCxNYXRoLm1pbihpLmxlbmd0aCx1LWEpKSx1PD1hK3MubGVuZ3RoKXtpZihzLmxlbmd0aDxpLmxlbmd0aClyW2xdPWkuc3ViYXJyYXkocy5sZW5ndGgpO2Vsc2UgaWYocy5sZW5ndGg9PT1pLmxlbmd0aClsKys7bz9TbChvLHMsYSk6bz1zO2JyZWFrfVNsKG98fChvPW5ldyBVaW50OEFycmF5KHUpKSxzLGEpLGErPXMubGVuZ3RofXJldHVybltvfHxuZXcgVWludDhBcnJheSgwKSxyLnNsaWNlKGwpLG4tKG8/by5ieXRlTGVuZ3RoOjApXX1mdW5jdGlvbiB3dCh0LGUpe2xldCByPXNmKGUpP2UudmFsdWU6ZTtpZihyIGluc3RhbmNlb2YgdCl7aWYodD09PVVpbnQ4QXJyYXkpcmV0dXJuIG5ldyB0KHIuYnVmZmVyLHIuYnl0ZU9mZnNldCxyLmJ5dGVMZW5ndGgpO3JldHVybiByfWlmKCFyKXJldHVybiBuZXcgdCgwKTtpZih0eXBlb2Ygcj09PSJzdHJpbmciKXI9bW4ocik7aWYociBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKXJldHVybiBuZXcgdChyKTtpZihyIGluc3RhbmNlb2YgcXApcmV0dXJuIG5ldyB0KHIpO2lmKEViKHIpKXJldHVybiB3dCh0LHIuYnl0ZXMoKSk7cmV0dXJuIUFycmF5QnVmZmVyLmlzVmlldyhyKT90LmZyb20ocik6ci5ieXRlTGVuZ3RoPD0wP25ldyB0KDApOm5ldyB0KHIuYnVmZmVyLHIuYnl0ZU9mZnNldCxyLmJ5dGVMZW5ndGgvdC5CWVRFU19QRVJfRUxFTUVOVCl9ZnVuY3Rpb24qbnModCxlKXtsZXQgcj1mdW5jdGlvbiooaSl7eWllbGQgaX0sbj10eXBlb2YgZT09PSJzdHJpbmciP3IoZSk6QXJyYXlCdWZmZXIuaXNWaWV3KGUpP3IoZSk6ZSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyP3IoZSk6ZSBpbnN0YW5jZW9mIHFwP3IoZSk6IXdpKGUpP3IoZSk6ZTtyZXR1cm4geWllbGQqJHAoZnVuY3Rpb24qKGkpe2xldCBzPW51bGw7ZG8gcz1pLm5leHQoeWllbGQgd3QodCxzKSk7d2hpbGUoIXMuZG9uZSl9KG5bU3ltYm9sLml0ZXJhdG9yXSgpKSksbmV3IHR9ZnVuY3Rpb24gdmkodCxlKXtyZXR1cm4gaG4odGhpcyxhcmd1bWVudHMsZnVuY3Rpb24qKCl7aWYoYmkoZSkpcmV0dXJuIHlpZWxkIHl0KHlpZWxkIHl0KHlpZWxkKmljKGdpKHZpKHQseWllbGQgeXQoZSkpKSkpKTtsZXQgbj1mdW5jdGlvbihvKXtyZXR1cm4gaG4odGhpcyxhcmd1bWVudHMsZnVuY3Rpb24qKCl7eWllbGQgeWllbGQgeXQoeWllbGQgeXQobykpfSl9LGk9ZnVuY3Rpb24obyl7cmV0dXJuIGhuKHRoaXMsYXJndW1lbnRzLGZ1bmN0aW9uKigpe3lpZWxkIHl0KHlpZWxkKmljKGdpKCRwKGZ1bmN0aW9uKihhKXtsZXQgbD1udWxsO2RvIGw9YS5uZXh0KHlpZWxkIGw9PT1udWxsfHxsPT09dm9pZCAwP3ZvaWQgMDpsLnZhbHVlKTt3aGlsZSghbC5kb25lKX0ob1tTeW1ib2wuaXRlcmF0b3JdKCkpKSkpKX0pfSxzPXR5cGVvZiBlPT09InN0cmluZyI/bihlKTpBcnJheUJ1ZmZlci5pc1ZpZXcoZSk/bihlKTplIGluc3RhbmNlb2YgQXJyYXlCdWZmZXI/bihlKTplIGluc3RhbmNlb2YgcXA/bihlKTp3aShlKT9pKGUpOiFWbihlKT9uKGUpOmU7cmV0dXJuIHlpZWxkIHl0KHlpZWxkKmljKGdpKCRwKGZ1bmN0aW9uKG8pe3JldHVybiBobih0aGlzLGFyZ3VtZW50cyxmdW5jdGlvbiooKXtsZXQgYT1udWxsO2RvIGE9eWllbGQgeXQoby5uZXh0KHlpZWxkIHlpZWxkIHl0KHd0KHQsYSkpKSk7d2hpbGUoIWEuZG9uZSl9KX0oc1tTeW1ib2wuYXN5bmNJdGVyYXRvcl0oKSkpKSkpLHlpZWxkIHl0KG5ldyB0KX0pfWZ1bmN0aW9uIGZmKHQsZSxyKXtpZih0IT09MCl7cj1yLnNsaWNlKDAsZSk7Zm9yKGxldCBuPS0xLGk9ci5sZW5ndGg7KytuPGk7KXJbbl0rPXR9cmV0dXJuIHIuc3ViYXJyYXkoMCxlKX1mdW5jdGlvbiBZcCh0LGUpe2xldCByPTAsbj10Lmxlbmd0aDtpZihuIT09ZS5sZW5ndGgpcmV0dXJuITE7aWYobj4wKWRvIGlmKHRbcl0hPT1lW3JdKXJldHVybiExO3doaWxlKCsrcjxuKTtyZXR1cm4hMH12YXIgcXAsWUQ9KHQpPT53dChJbnQ4QXJyYXksdCksS0Q9KHQpPT53dChJbnQxNkFycmF5LHQpLG9hPSh0KT0+d3QoSW50MzJBcnJheSx0KSx1Zj0odCk9Pnd0KEJpZ0ludDY0QXJyYXksdCksQz0odCk9Pnd0KFVpbnQ4QXJyYXksdCksR0Q9KHQpPT53dChVaW50MTZBcnJheSx0KSxKRD0odCk9Pnd0KFVpbnQzMkFycmF5LHQpLFhEPSh0KT0+d3QoQmlnVWludDY0QXJyYXksdCksWkQ9KHQpPT53dChGbG9hdDMyQXJyYXksdCksUUQ9KHQpPT53dChGbG9hdDY0QXJyYXksdCksdHg9KHQpPT53dChVaW50OENsYW1wZWRBcnJheSx0KSwkcD0odCk9Pih0Lm5leHQoKSx0KSxleD0odCk9Pm5zKEludDhBcnJheSx0KSxyeD0odCk9Pm5zKEludDE2QXJyYXksdCksbng9KHQpPT5ucyhJbnQzMkFycmF5LHQpLFdwPSh0KT0+bnMoVWludDhBcnJheSx0KSxpeD0odCk9Pm5zKFVpbnQxNkFycmF5LHQpLHN4PSh0KT0+bnMoVWludDMyQXJyYXksdCksb3g9KHQpPT5ucyhGbG9hdDMyQXJyYXksdCksYXg9KHQpPT5ucyhGbG9hdDY0QXJyYXksdCksY3g9KHQpPT5ucyhVaW50OENsYW1wZWRBcnJheSx0KSxseD0odCk9PnZpKEludDhBcnJheSx0KSx1eD0odCk9PnZpKEludDE2QXJyYXksdCksZng9KHQpPT52aShJbnQzMkFycmF5LHQpLEhwPSh0KT0+dmkoVWludDhBcnJheSx0KSxkeD0odCk9PnZpKFVpbnQxNkFycmF5LHQpLGh4PSh0KT0+dmkoVWludDMyQXJyYXksdCkscHg9KHQpPT52aShGbG9hdDMyQXJyYXksdCksbXg9KHQpPT52aShGbG9hdDY0QXJyYXksdCkseXg9KHQpPT52aShVaW50OENsYW1wZWRBcnJheSx0KTt2YXIgamU9bSgoKT0+e3BuKCk7dnMoKTtxcD10eXBlb2YgU2hhcmVkQXJyYXlCdWZmZXI8InUiP1NoYXJlZEFycmF5QnVmZmVyOkFycmF5QnVmZmVyfSk7ZnVuY3Rpb24qX3godCl7bGV0IGUscj0hMSxuPVtdLGkscyxvLGE9MDtmdW5jdGlvbiBsKCl7aWYocz09PSJwZWVrIilyZXR1cm4geW4obixvKVswXTtyZXR1cm5baSxuLGFdPXluKG4sbyksaX0oe2NtZDpzLHNpemU6b309KHlpZWxkKCgpPT5udWxsKSgpKXx8e2NtZDoicmVhZCIsc2l6ZTowfSk7bGV0IHU9V3AodClbU3ltYm9sLml0ZXJhdG9yXSgpO3RyeXtkb3tpZih7ZG9uZTplLHZhbHVlOml9PU51bWJlci5pc05hTihvLWEpP3UubmV4dCgpOnUubmV4dChvLWEpLCFlJiZpLmJ5dGVMZW5ndGg+MCluLnB1c2goaSksYSs9aS5ieXRlTGVuZ3RoO2lmKGV8fG88PWEpZG8oe2NtZDpzLHNpemU6b309eWllbGQgbCgpKTt3aGlsZShvPGEpfXdoaWxlKCFlKX1jYXRjaChmKXtyPSEwLHR5cGVvZiB1LnRocm93PT09ImZ1bmN0aW9uIiYmdS50aHJvdyhmKX1maW5hbGx5e3I9PT0hMSYmdHlwZW9mIHUucmV0dXJuPT09ImZ1bmN0aW9uIiYmdS5yZXR1cm4obnVsbCl9cmV0dXJuIG51bGx9ZnVuY3Rpb24gZ3godCl7cmV0dXJuIGhuKHRoaXMsYXJndW1lbnRzLGZ1bmN0aW9uKigpe2xldCByLG49ITEsaT1bXSxzLG8sYSxsPTA7ZnVuY3Rpb24gdSgpe2lmKG89PT0icGVlayIpcmV0dXJuIHluKGksYSlbMF07cmV0dXJuW3MsaSxsXT15bihpLGEpLHN9KHtjbWQ6byxzaXplOmF9PSh5aWVsZCB5aWVsZCB5dCgoKCk9Pm51bGwpKCkpKXx8e2NtZDoicmVhZCIsc2l6ZTowfSk7bGV0IGY9SHAodClbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCk7dHJ5e2Rve2lmKHtkb25lOnIsdmFsdWU6c309TnVtYmVyLmlzTmFOKGEtbCk/eWllbGQgeXQoZi5uZXh0KCkpOnlpZWxkIHl0KGYubmV4dChhLWwpKSwhciYmcy5ieXRlTGVuZ3RoPjApaS5wdXNoKHMpLGwrPXMuYnl0ZUxlbmd0aDtpZihyfHxhPD1sKWRvKHtjbWQ6byxzaXplOmF9PXlpZWxkIHlpZWxkIHl0KHUoKSkpO3doaWxlKGE8bCl9d2hpbGUoIXIpfWNhdGNoKHApe249ITAsdHlwZW9mIGYudGhyb3c9PT0iZnVuY3Rpb24iJiYoeWllbGQgeXQoZi50aHJvdyhwKSkpfWZpbmFsbHl7bj09PSExJiZ0eXBlb2YgZi5yZXR1cm49PT0iZnVuY3Rpb24iJiYoeWllbGQgeXQoZi5yZXR1cm4obmV3IFVpbnQ4QXJyYXkoMCkpKSl9cmV0dXJuIHlpZWxkIHl0KG51bGwpfSl9ZnVuY3Rpb24gYngodCl7cmV0dXJuIGhuKHRoaXMsYXJndW1lbnRzLGZ1bmN0aW9uKigpe2xldCByPSExLG49ITEsaT1bXSxzLG8sYSxsPTA7ZnVuY3Rpb24gdSgpe2lmKG89PT0icGVlayIpcmV0dXJuIHluKGksYSlbMF07cmV0dXJuW3MsaSxsXT15bihpLGEpLHN9KHtjbWQ6byxzaXplOmF9PSh5aWVsZCB5aWVsZCB5dCgoKCk9Pm51bGwpKCkpKXx8e2NtZDoicmVhZCIsc2l6ZTowfSk7bGV0IGY9bmV3IE9iKHQpO3RyeXtkb3tpZih7ZG9uZTpyLHZhbHVlOnN9PU51bWJlci5pc05hTihhLWwpP3lpZWxkIHl0KGYucmVhZCgpKTp5aWVsZCB5dChmLnJlYWQoYS1sKSksIXImJnMuYnl0ZUxlbmd0aD4wKWkucHVzaChDKHMpKSxsKz1zLmJ5dGVMZW5ndGg7aWYocnx8YTw9bClkbyh7Y21kOm8sc2l6ZTphfT15aWVsZCB5aWVsZCB5dCh1KCkpKTt3aGlsZShhPGwpfXdoaWxlKCFyKX1jYXRjaChwKXtuPSEwLHlpZWxkIHl0KGYuY2FuY2VsKHApKX1maW5hbGx5e249PT0hMT95aWVsZCB5dChmLmNhbmNlbCgpKTp0LmxvY2tlZCYmZi5yZWxlYXNlTG9jaygpfXJldHVybiB5aWVsZCB5dChudWxsKX0pfWNsYXNzIE9ie2NvbnN0cnVjdG9yKHQpe3RoaXMuc291cmNlPXQsdGhpcy5yZWFkZXI9bnVsbCx0aGlzLnJlYWRlcj10aGlzLnNvdXJjZS5nZXRSZWFkZXIoKSx0aGlzLnJlYWRlci5jbG9zZWQuY2F0Y2goKCk9Pnt9KX1nZXQgY2xvc2VkKCl7cmV0dXJuIHRoaXMucmVhZGVyP3RoaXMucmVhZGVyLmNsb3NlZC5jYXRjaCgoKT0+e30pOlByb21pc2UucmVzb2x2ZSgpfXJlbGVhc2VMb2NrKCl7aWYodGhpcy5yZWFkZXIpdGhpcy5yZWFkZXIucmVsZWFzZUxvY2soKTt0aGlzLnJlYWRlcj1udWxsfWNhbmNlbCh0KXtyZXR1cm4gRSh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7bGV0e3JlYWRlcjplLHNvdXJjZTpyfT10aGlzO2UmJih5aWVsZCBlLmNhbmNlbCh0KS5jYXRjaCgoKT0+e30pKSxyJiYoci5sb2NrZWQmJnRoaXMucmVsZWFzZUxvY2soKSl9KX1yZWFkKHQpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtpZih0PT09MClyZXR1cm57ZG9uZTp0aGlzLnJlYWRlcj09bnVsbCx2YWx1ZTpuZXcgVWludDhBcnJheSgwKX07bGV0IGU9eWllbGQgdGhpcy5yZWFkZXIucmVhZCgpO3JldHVybiFlLmRvbmUmJihlLnZhbHVlPUMoZSkpLGV9KX19ZnVuY3Rpb24gd3godCl7cmV0dXJuIGhuKHRoaXMsYXJndW1lbnRzLGZ1bmN0aW9uKigpe2xldCByPVtdLG49ImVycm9yIixpPSExLHM9bnVsbCxvLGEsbD0wLHU9W10sZjtmdW5jdGlvbiBwKCl7aWYobz09PSJwZWVrIilyZXR1cm4geW4odSxhKVswXTtyZXR1cm5bZix1LGxdPXluKHUsYSksZn1pZih7Y21kOm8sc2l6ZTphfT0oeWllbGQgeWllbGQgeXQoKCgpPT5udWxsKSgpKSl8fHtjbWQ6InJlYWQiLHNpemU6MH0sdC5pc1RUWSlyZXR1cm4geWllbGQgeWllbGQgeXQobmV3IFVpbnQ4QXJyYXkoMCkpLHlpZWxkIHl0KG51bGwpO3RyeXtyWzBdPUdwKHQsImVuZCIpLHJbMV09R3AodCwiZXJyb3IiKTtkb3tpZihyWzJdPUdwKHQsInJlYWRhYmxlIiksW24sc109eWllbGQgeXQoUHJvbWlzZS5yYWNlKHIubWFwKCh2KT0+dlsyXSkpKSxuPT09ImVycm9yIilicmVhaztpZighKGk9bj09PSJlbmQiKSl7aWYoIU51bWJlci5pc0Zpbml0ZShhLWwpKWY9Qyh0LnJlYWQoKSk7ZWxzZSBpZihmPUModC5yZWFkKGEtbCkpLGYuYnl0ZUxlbmd0aDxhLWwpZj1DKHQucmVhZCgpKTtpZihmLmJ5dGVMZW5ndGg+MCl1LnB1c2goZiksbCs9Zi5ieXRlTGVuZ3RofWlmKGl8fGE8PWwpZG8oe2NtZDpvLHNpemU6YX09eWllbGQgeWllbGQgeXQocCgpKSk7d2hpbGUoYTxsKX13aGlsZSghaSl9ZmluYWxseXt5aWVsZCB5dChnKHIsbj09PSJlcnJvciI/czpudWxsKSl9cmV0dXJuIHlpZWxkIHl0KG51bGwpO2Z1bmN0aW9uIGcodixJKXtyZXR1cm4gZj11PW51bGwsbmV3IFByb21pc2UoKEQsWik9Pntmb3IobGV0W210LHBlXW9mIHYpdC5vZmYobXQscGUpO3RyeXtsZXQgbXQ9dC5kZXN0cm95O210JiZtdC5jYWxsKHQsSSksST12b2lkIDB9Y2F0Y2gobXQpe0k9bXR8fEl9ZmluYWxseXtJIT1udWxsP1ooSSk6RCgpfX0pfX0pfXZhciBjcixkZj0odCk9Pih0Lm5leHQoKSx0KSxHcD0odCxlKT0+e2xldCByPShpKT0+bihbZSxpXSksbjtyZXR1cm5bZSxyLG5ldyBQcm9taXNlKChpKT0+KG49aSkmJnQub25jZShlLHIpKV19O3ZhciBBbD1tKCgpPT57cG4oKTtqZSgpO2NyPXtmcm9tSXRlcmFibGUodCl7cmV0dXJuIGRmKF94KHQpKX0sZnJvbUFzeW5jSXRlcmFibGUodCl7cmV0dXJuIGRmKGd4KHQpKX0sZnJvbURPTVN0cmVhbSh0KXtyZXR1cm4gZGYoYngodCkpfSxmcm9tTm9kZVN0cmVhbSh0KXtyZXR1cm4gZGYod3godCkpfSx0b0RPTVN0cmVhbSh0LGUpe3Rocm93IEVycm9yKCcidG9ET01TdHJlYW0iIG5vdCBhdmFpbGFibGUgaW4gdGhpcyBlbnZpcm9ubWVudCcpfSx0b05vZGVTdHJlYW0odCxlKXt0aHJvdyBFcnJvcignInRvTm9kZVN0cmVhbSIgbm90IGF2YWlsYWJsZSBpbiB0aGlzIGVudmlyb25tZW50Jyl9fX0pO3ZhciAkdDt2YXIgaGY9bSgoKT0+eyhmdW5jdGlvbih0KXt0W3QuVjE9MF09IlYxIix0W3QuVjI9MV09IlYyIix0W3QuVjM9Ml09IlYzIix0W3QuVjQ9M109IlY0Iix0W3QuVjU9NF09IlY1In0pKCR0fHwoJHQ9e30pKX0pO3ZhciBMdDt2YXIgSnA9bSgoKT0+eyhmdW5jdGlvbih0KXt0W3QuU3BhcnNlPTBdPSJTcGFyc2UiLHRbdC5EZW5zZT0xXT0iRGVuc2UifSkoTHR8fChMdD17fSkpfSk7dmFyIFp0O3ZhciBYcD1tKCgpPT57KGZ1bmN0aW9uKHQpe3RbdC5IQUxGPTBdPSJIQUxGIix0W3QuU0lOR0xFPTFdPSJTSU5HTEUiLHRbdC5ET1VCTEU9Ml09IkRPVUJMRSJ9KShadHx8KFp0PXt9KSl9KTt2YXIgcXQ7dmFyIFpwPW0oKCk9PnsoZnVuY3Rpb24odCl7dFt0LkRBWT0wXT0iREFZIix0W3QuTUlMTElTRUNPTkQ9MV09Ik1JTExJU0VDT05EIn0pKHF0fHwocXQ9e30pKX0pO3ZhciBUO3ZhciBEbD1tKCgpPT57KGZ1bmN0aW9uKHQpe3RbdC5TRUNPTkQ9MF09IlNFQ09ORCIsdFt0Lk1JTExJU0VDT05EPTFdPSJNSUxMSVNFQ09ORCIsdFt0Lk1JQ1JPU0VDT05EPTJdPSJNSUNST1NFQ09ORCIsdFt0Lk5BTk9TRUNPTkQ9M109Ik5BTk9TRUNPTkQifSkoVHx8KFQ9e30pKX0pO3ZhciBqdDt2YXIgUXA9bSgoKT0+eyhmdW5jdGlvbih0KXt0W3QuWUVBUl9NT05USD0wXT0iWUVBUl9NT05USCIsdFt0LkRBWV9USU1FPTFdPSJEQVlfVElNRSIsdFt0Lk1PTlRIX0RBWV9OQU5PPTJdPSJNT05USF9EQVlfTkFOTyJ9KShqdHx8KGp0PXt9KSl9KTt2YXIgeGw9Mixfbj00LHpuPTQsTT00O3ZhciBpcyxwZixtZixvYzt2YXIgdG09bSgoKT0+e2lzPW5ldyBJbnQzMkFycmF5KDIpLHBmPW5ldyBGbG9hdDMyQXJyYXkoaXMuYnVmZmVyKSxtZj1uZXcgRmxvYXQ2NEFycmF5KGlzLmJ1ZmZlciksb2M9bmV3IFVpbnQxNkFycmF5KG5ldyBVaW50OEFycmF5KFsxLDBdKS5idWZmZXIpWzBdPT09MX0pO3ZhciBUbDt2YXIgZW09bSgoKT0+eyhmdW5jdGlvbih0KXt0W3QuVVRGOF9CWVRFUz0xXT0iVVRGOF9CWVRFUyIsdFt0LlVURjE2X1NUUklORz0yXT0iVVRGMTZfU1RSSU5HIn0pKFRsfHwoVGw9e30pKX0pO2NsYXNzIGxye2NvbnN0cnVjdG9yKHQpe3RoaXMuYnl0ZXNfPXQsdGhpcy5wb3NpdGlvbl89MCx0aGlzLnRleHRfZGVjb2Rlcl89bmV3IFRleHREZWNvZGVyfXN0YXRpYyBhbGxvY2F0ZSh0KXtyZXR1cm4gbmV3IGxyKG5ldyBVaW50OEFycmF5KHQpKX1jbGVhcigpe3RoaXMucG9zaXRpb25fPTB9Ynl0ZXMoKXtyZXR1cm4gdGhpcy5ieXRlc199cG9zaXRpb24oKXtyZXR1cm4gdGhpcy5wb3NpdGlvbl99c2V0UG9zaXRpb24odCl7dGhpcy5wb3NpdGlvbl89dH1jYXBhY2l0eSgpe3JldHVybiB0aGlzLmJ5dGVzXy5sZW5ndGh9cmVhZEludDgodCl7cmV0dXJuIHRoaXMucmVhZFVpbnQ4KHQpPDwyND4+MjR9cmVhZFVpbnQ4KHQpe3JldHVybiB0aGlzLmJ5dGVzX1t0XX1yZWFkSW50MTYodCl7cmV0dXJuIHRoaXMucmVhZFVpbnQxNih0KTw8MTY+PjE2fXJlYWRVaW50MTYodCl7cmV0dXJuIHRoaXMuYnl0ZXNfW3RdfHRoaXMuYnl0ZXNfW3QrMV08PDh9cmVhZEludDMyKHQpe3JldHVybiB0aGlzLmJ5dGVzX1t0XXx0aGlzLmJ5dGVzX1t0KzFdPDw4fHRoaXMuYnl0ZXNfW3QrMl08PDE2fHRoaXMuYnl0ZXNfW3QrM108PDI0fXJlYWRVaW50MzIodCl7cmV0dXJuIHRoaXMucmVhZEludDMyKHQpPj4+MH1yZWFkSW50NjQodCl7cmV0dXJuIEJpZ0ludC5hc0ludE4oNjQsQmlnSW50KHRoaXMucmVhZFVpbnQzMih0KSkrKEJpZ0ludCh0aGlzLnJlYWRVaW50MzIodCs0KSk8PEJpZ0ludCgzMikpKX1yZWFkVWludDY0KHQpe3JldHVybiBCaWdJbnQuYXNVaW50Tig2NCxCaWdJbnQodGhpcy5yZWFkVWludDMyKHQpKSsoQmlnSW50KHRoaXMucmVhZFVpbnQzMih0KzQpKTw8QmlnSW50KDMyKSkpfXJlYWRGbG9hdDMyKHQpe3JldHVybiBpc1swXT10aGlzLnJlYWRJbnQzMih0KSxwZlswXX1yZWFkRmxvYXQ2NCh0KXtyZXR1cm4gaXNbb2M/MDoxXT10aGlzLnJlYWRJbnQzMih0KSxpc1tvYz8xOjBdPXRoaXMucmVhZEludDMyKHQrNCksbWZbMF19d3JpdGVJbnQ4KHQsZSl7dGhpcy5ieXRlc19bdF09ZX13cml0ZVVpbnQ4KHQsZSl7dGhpcy5ieXRlc19bdF09ZX13cml0ZUludDE2KHQsZSl7dGhpcy5ieXRlc19bdF09ZSx0aGlzLmJ5dGVzX1t0KzFdPWU+Pjh9d3JpdGVVaW50MTYodCxlKXt0aGlzLmJ5dGVzX1t0XT1lLHRoaXMuYnl0ZXNfW3QrMV09ZT4+OH13cml0ZUludDMyKHQsZSl7dGhpcy5ieXRlc19bdF09ZSx0aGlzLmJ5dGVzX1t0KzFdPWU+PjgsdGhpcy5ieXRlc19bdCsyXT1lPj4xNix0aGlzLmJ5dGVzX1t0KzNdPWU+PjI0fXdyaXRlVWludDMyKHQsZSl7dGhpcy5ieXRlc19bdF09ZSx0aGlzLmJ5dGVzX1t0KzFdPWU+PjgsdGhpcy5ieXRlc19bdCsyXT1lPj4xNix0aGlzLmJ5dGVzX1t0KzNdPWU+PjI0fXdyaXRlSW50NjQodCxlKXt0aGlzLndyaXRlSW50MzIodCxOdW1iZXIoQmlnSW50LmFzSW50TigzMixlKSkpLHRoaXMud3JpdGVJbnQzMih0KzQsTnVtYmVyKEJpZ0ludC5hc0ludE4oMzIsZT4+QmlnSW50KDMyKSkpKX13cml0ZVVpbnQ2NCh0LGUpe3RoaXMud3JpdGVVaW50MzIodCxOdW1iZXIoQmlnSW50LmFzVWludE4oMzIsZSkpKSx0aGlzLndyaXRlVWludDMyKHQrNCxOdW1iZXIoQmlnSW50LmFzVWludE4oMzIsZT4+QmlnSW50KDMyKSkpKX13cml0ZUZsb2F0MzIodCxlKXtwZlswXT1lLHRoaXMud3JpdGVJbnQzMih0LGlzWzBdKX13cml0ZUZsb2F0NjQodCxlKXttZlswXT1lLHRoaXMud3JpdGVJbnQzMih0LGlzW29jPzA6MV0pLHRoaXMud3JpdGVJbnQzMih0KzQsaXNbb2M/MTowXSl9Z2V0QnVmZmVySWRlbnRpZmllcigpe2lmKHRoaXMuYnl0ZXNfLmxlbmd0aDx0aGlzLnBvc2l0aW9uXytfbit6bil0aHJvdyBFcnJvcigiRmxhdEJ1ZmZlcnM6IEJ5dGVCdWZmZXIgaXMgdG9vIHNob3J0IHRvIGNvbnRhaW4gYW4gaWRlbnRpZmllci4iKTtsZXQgdD0iIjtmb3IobGV0IGU9MDtlPHpuO2UrKyl0Kz1TdHJpbmcuZnJvbUNoYXJDb2RlKHRoaXMucmVhZEludDgodGhpcy5wb3NpdGlvbl8rX24rZSkpO3JldHVybiB0fV9fb2Zmc2V0KHQsZSl7bGV0IHI9dC10aGlzLnJlYWRJbnQzMih0KTtyZXR1cm4gZTx0aGlzLnJlYWRJbnQxNihyKT90aGlzLnJlYWRJbnQxNihyK2UpOjB9X191bmlvbih0LGUpe3JldHVybiB0LmJiX3Bvcz1lK3RoaXMucmVhZEludDMyKGUpLHQuYmI9dGhpcyx0fV9fc3RyaW5nKHQsZSl7dCs9dGhpcy5yZWFkSW50MzIodCk7bGV0IHI9dGhpcy5yZWFkSW50MzIodCk7dCs9X247bGV0IG49dGhpcy5ieXRlc18uc3ViYXJyYXkodCx0K3IpO2lmKGU9PT1UbC5VVEY4X0JZVEVTKXJldHVybiBuO2Vsc2UgcmV0dXJuIHRoaXMudGV4dF9kZWNvZGVyXy5kZWNvZGUobil9X191bmlvbl93aXRoX3N0cmluZyh0LGUpe2lmKHR5cGVvZiB0PT09InN0cmluZyIpcmV0dXJuIHRoaXMuX19zdHJpbmcoZSk7cmV0dXJuIHRoaXMuX191bmlvbih0LGUpfV9faW5kaXJlY3QodCl7cmV0dXJuIHQrdGhpcy5yZWFkSW50MzIodCl9X192ZWN0b3IodCl7cmV0dXJuIHQrdGhpcy5yZWFkSW50MzIodCkrX259X192ZWN0b3JfbGVuKHQpe3JldHVybiB0aGlzLnJlYWRJbnQzMih0K3RoaXMucmVhZEludDMyKHQpKX1fX2hhc19pZGVudGlmaWVyKHQpe2lmKHQubGVuZ3RoIT16bil0aHJvdyBFcnJvcigiRmxhdEJ1ZmZlcnM6IGZpbGUgaWRlbnRpZmllciBtdXN0IGJlIGxlbmd0aCAiK3puKTtmb3IobGV0IGU9MDtlPHpuO2UrKylpZih0LmNoYXJDb2RlQXQoZSkhPXRoaXMucmVhZEludDgodGhpcy5wb3NpdGlvbigpK19uK2UpKXJldHVybiExO3JldHVybiEwfWNyZWF0ZVNjYWxhckxpc3QodCxlKXtsZXQgcj1bXTtmb3IobGV0IG49MDtuPGU7KytuKXtsZXQgaT10KG4pO2lmKGkhPT1udWxsKXIucHVzaChpKX1yZXR1cm4gcn1jcmVhdGVPYmpMaXN0KHQsZSl7bGV0IHI9W107Zm9yKGxldCBuPTA7bjxlOysrbil7bGV0IGk9dChuKTtpZihpIT09bnVsbClyLnB1c2goaS51bnBhY2soKSl9cmV0dXJuIHJ9fXZhciBybT1tKCgpPT57ZW0oKTt0bSgpfSk7Y2xhc3MgYWF7Y29uc3RydWN0b3IodCl7dGhpcy5taW5hbGlnbj0xLHRoaXMudnRhYmxlPW51bGwsdGhpcy52dGFibGVfaW5fdXNlPTAsdGhpcy5pc05lc3RlZD0hMSx0aGlzLm9iamVjdF9zdGFydD0wLHRoaXMudnRhYmxlcz1bXSx0aGlzLnZlY3Rvcl9udW1fZWxlbXM9MCx0aGlzLmZvcmNlX2RlZmF1bHRzPSExLHRoaXMuc3RyaW5nX21hcHM9bnVsbCx0aGlzLnRleHRfZW5jb2Rlcj1uZXcgVGV4dEVuY29kZXI7bGV0IGU7aWYoIXQpZT0xMDI0O2Vsc2UgZT10O3RoaXMuYmI9bHIuYWxsb2NhdGUoZSksdGhpcy5zcGFjZT1lfWNsZWFyKCl7dGhpcy5iYi5jbGVhcigpLHRoaXMuc3BhY2U9dGhpcy5iYi5jYXBhY2l0eSgpLHRoaXMubWluYWxpZ249MSx0aGlzLnZ0YWJsZT1udWxsLHRoaXMudnRhYmxlX2luX3VzZT0wLHRoaXMuaXNOZXN0ZWQ9ITEsdGhpcy5vYmplY3Rfc3RhcnQ9MCx0aGlzLnZ0YWJsZXM9W10sdGhpcy52ZWN0b3JfbnVtX2VsZW1zPTAsdGhpcy5mb3JjZV9kZWZhdWx0cz0hMSx0aGlzLnN0cmluZ19tYXBzPW51bGx9Zm9yY2VEZWZhdWx0cyh0KXt0aGlzLmZvcmNlX2RlZmF1bHRzPXR9ZGF0YUJ1ZmZlcigpe3JldHVybiB0aGlzLmJifWFzVWludDhBcnJheSgpe3JldHVybiB0aGlzLmJiLmJ5dGVzKCkuc3ViYXJyYXkodGhpcy5iYi5wb3NpdGlvbigpLHRoaXMuYmIucG9zaXRpb24oKSt0aGlzLm9mZnNldCgpKX1wcmVwKHQsZSl7aWYodD50aGlzLm1pbmFsaWduKXRoaXMubWluYWxpZ249dDtsZXQgcj1+KHRoaXMuYmIuY2FwYWNpdHkoKS10aGlzLnNwYWNlK2UpKzEmdC0xO3doaWxlKHRoaXMuc3BhY2U8cit0K2Upe2xldCBuPXRoaXMuYmIuY2FwYWNpdHkoKTt0aGlzLmJiPWFhLmdyb3dCeXRlQnVmZmVyKHRoaXMuYmIpLHRoaXMuc3BhY2UrPXRoaXMuYmIuY2FwYWNpdHkoKS1ufXRoaXMucGFkKHIpfXBhZCh0KXtmb3IobGV0IGU9MDtlPHQ7ZSsrKXRoaXMuYmIud3JpdGVJbnQ4KC0tdGhpcy5zcGFjZSwwKX13cml0ZUludDgodCl7dGhpcy5iYi53cml0ZUludDgodGhpcy5zcGFjZS09MSx0KX13cml0ZUludDE2KHQpe3RoaXMuYmIud3JpdGVJbnQxNih0aGlzLnNwYWNlLT0yLHQpfXdyaXRlSW50MzIodCl7dGhpcy5iYi53cml0ZUludDMyKHRoaXMuc3BhY2UtPTQsdCl9d3JpdGVJbnQ2NCh0KXt0aGlzLmJiLndyaXRlSW50NjQodGhpcy5zcGFjZS09OCx0KX13cml0ZUZsb2F0MzIodCl7dGhpcy5iYi53cml0ZUZsb2F0MzIodGhpcy5zcGFjZS09NCx0KX13cml0ZUZsb2F0NjQodCl7dGhpcy5iYi53cml0ZUZsb2F0NjQodGhpcy5zcGFjZS09OCx0KX1hZGRJbnQ4KHQpe3RoaXMucHJlcCgxLDApLHRoaXMud3JpdGVJbnQ4KHQpfWFkZEludDE2KHQpe3RoaXMucHJlcCgyLDApLHRoaXMud3JpdGVJbnQxNih0KX1hZGRJbnQzMih0KXt0aGlzLnByZXAoNCwwKSx0aGlzLndyaXRlSW50MzIodCl9YWRkSW50NjQodCl7dGhpcy5wcmVwKDgsMCksdGhpcy53cml0ZUludDY0KHQpfWFkZEZsb2F0MzIodCl7dGhpcy5wcmVwKDQsMCksdGhpcy53cml0ZUZsb2F0MzIodCl9YWRkRmxvYXQ2NCh0KXt0aGlzLnByZXAoOCwwKSx0aGlzLndyaXRlRmxvYXQ2NCh0KX1hZGRGaWVsZEludDgodCxlLHIpe2lmKHRoaXMuZm9yY2VfZGVmYXVsdHN8fGUhPXIpdGhpcy5hZGRJbnQ4KGUpLHRoaXMuc2xvdCh0KX1hZGRGaWVsZEludDE2KHQsZSxyKXtpZih0aGlzLmZvcmNlX2RlZmF1bHRzfHxlIT1yKXRoaXMuYWRkSW50MTYoZSksdGhpcy5zbG90KHQpfWFkZEZpZWxkSW50MzIodCxlLHIpe2lmKHRoaXMuZm9yY2VfZGVmYXVsdHN8fGUhPXIpdGhpcy5hZGRJbnQzMihlKSx0aGlzLnNsb3QodCl9YWRkRmllbGRJbnQ2NCh0LGUscil7aWYodGhpcy5mb3JjZV9kZWZhdWx0c3x8ZSE9PXIpdGhpcy5hZGRJbnQ2NChlKSx0aGlzLnNsb3QodCl9YWRkRmllbGRGbG9hdDMyKHQsZSxyKXtpZih0aGlzLmZvcmNlX2RlZmF1bHRzfHxlIT1yKXRoaXMuYWRkRmxvYXQzMihlKSx0aGlzLnNsb3QodCl9YWRkRmllbGRGbG9hdDY0KHQsZSxyKXtpZih0aGlzLmZvcmNlX2RlZmF1bHRzfHxlIT1yKXRoaXMuYWRkRmxvYXQ2NChlKSx0aGlzLnNsb3QodCl9YWRkRmllbGRPZmZzZXQodCxlLHIpe2lmKHRoaXMuZm9yY2VfZGVmYXVsdHN8fGUhPXIpdGhpcy5hZGRPZmZzZXQoZSksdGhpcy5zbG90KHQpfWFkZEZpZWxkU3RydWN0KHQsZSxyKXtpZihlIT1yKXRoaXMubmVzdGVkKGUpLHRoaXMuc2xvdCh0KX1uZXN0ZWQodCl7aWYodCE9dGhpcy5vZmZzZXQoKSl0aHJvdyBUeXBlRXJyb3IoIkZsYXRCdWZmZXJzOiBzdHJ1Y3QgbXVzdCBiZSBzZXJpYWxpemVkIGlubGluZS4iKX1ub3ROZXN0ZWQoKXtpZih0aGlzLmlzTmVzdGVkKXRocm93IFR5cGVFcnJvcigiRmxhdEJ1ZmZlcnM6IG9iamVjdCBzZXJpYWxpemF0aW9uIG11c3Qgbm90IGJlIG5lc3RlZC4iKX1zbG90KHQpe2lmKHRoaXMudnRhYmxlIT09bnVsbCl0aGlzLnZ0YWJsZVt0XT10aGlzLm9mZnNldCgpfW9mZnNldCgpe3JldHVybiB0aGlzLmJiLmNhcGFjaXR5KCktdGhpcy5zcGFjZX1zdGF0aWMgZ3Jvd0J5dGVCdWZmZXIodCl7bGV0IGU9dC5jYXBhY2l0eSgpO2lmKGUmMzIyMTIyNTQ3Mil0aHJvdyBFcnJvcigiRmxhdEJ1ZmZlcnM6IGNhbm5vdCBncm93IGJ1ZmZlciBiZXlvbmQgMiBnaWdhYnl0ZXMuIik7bGV0IHI9ZTw8MSxuPWxyLmFsbG9jYXRlKHIpO3JldHVybiBuLnNldFBvc2l0aW9uKHItZSksbi5ieXRlcygpLnNldCh0LmJ5dGVzKCksci1lKSxufWFkZE9mZnNldCh0KXt0aGlzLnByZXAoX24sMCksdGhpcy53cml0ZUludDMyKHRoaXMub2Zmc2V0KCktdCtfbil9c3RhcnRPYmplY3QodCl7aWYodGhpcy5ub3ROZXN0ZWQoKSx0aGlzLnZ0YWJsZT09bnVsbCl0aGlzLnZ0YWJsZT1bXTt0aGlzLnZ0YWJsZV9pbl91c2U9dDtmb3IobGV0IGU9MDtlPHQ7ZSsrKXRoaXMudnRhYmxlW2VdPTA7dGhpcy5pc05lc3RlZD0hMCx0aGlzLm9iamVjdF9zdGFydD10aGlzLm9mZnNldCgpfWVuZE9iamVjdCgpe2lmKHRoaXMudnRhYmxlPT1udWxsfHwhdGhpcy5pc05lc3RlZCl0aHJvdyBFcnJvcigiRmxhdEJ1ZmZlcnM6IGVuZE9iamVjdCBjYWxsZWQgd2l0aG91dCBzdGFydE9iamVjdCIpO3RoaXMuYWRkSW50MzIoMCk7bGV0IHQ9dGhpcy5vZmZzZXQoKSxlPXRoaXMudnRhYmxlX2luX3VzZS0xO2Zvcig7ZT49MCYmdGhpcy52dGFibGVbZV09PTA7ZS0tKTtsZXQgcj1lKzE7Zm9yKDtlPj0wO2UtLSl0aGlzLmFkZEludDE2KHRoaXMudnRhYmxlW2VdIT0wP3QtdGhpcy52dGFibGVbZV06MCk7bGV0IG49Mjt0aGlzLmFkZEludDE2KHQtdGhpcy5vYmplY3Rfc3RhcnQpO2xldCBpPShyK24pKnhsO3RoaXMuYWRkSW50MTYoaSk7bGV0IHM9MCxvPXRoaXMuc3BhY2U7dDpmb3IoZT0wO2U8dGhpcy52dGFibGVzLmxlbmd0aDtlKyspe2xldCBhPXRoaXMuYmIuY2FwYWNpdHkoKS10aGlzLnZ0YWJsZXNbZV07aWYoaT09dGhpcy5iYi5yZWFkSW50MTYoYSkpe2ZvcihsZXQgbD14bDtsPGk7bCs9eGwpaWYodGhpcy5iYi5yZWFkSW50MTYobytsKSE9dGhpcy5iYi5yZWFkSW50MTYoYStsKSljb250aW51ZSB0O3M9dGhpcy52dGFibGVzW2VdO2JyZWFrfX1pZihzKXRoaXMuc3BhY2U9dGhpcy5iYi5jYXBhY2l0eSgpLXQsdGhpcy5iYi53cml0ZUludDMyKHRoaXMuc3BhY2Uscy10KTtlbHNlIHRoaXMudnRhYmxlcy5wdXNoKHRoaXMub2Zmc2V0KCkpLHRoaXMuYmIud3JpdGVJbnQzMih0aGlzLmJiLmNhcGFjaXR5KCktdCx0aGlzLm9mZnNldCgpLXQpO3JldHVybiB0aGlzLmlzTmVzdGVkPSExLHR9ZmluaXNoKHQsZSxyKXtsZXQgbj1yP006MDtpZihlKXtsZXQgaT1lO2lmKHRoaXMucHJlcCh0aGlzLm1pbmFsaWduLF9uK3puK24pLGkubGVuZ3RoIT16bil0aHJvdyBUeXBlRXJyb3IoIkZsYXRCdWZmZXJzOiBmaWxlIGlkZW50aWZpZXIgbXVzdCBiZSBsZW5ndGggIit6bik7Zm9yKGxldCBzPXpuLTE7cz49MDtzLS0pdGhpcy53cml0ZUludDgoaS5jaGFyQ29kZUF0KHMpKX1pZih0aGlzLnByZXAodGhpcy5taW5hbGlnbixfbituKSx0aGlzLmFkZE9mZnNldCh0KSxuKXRoaXMuYWRkSW50MzIodGhpcy5iYi5jYXBhY2l0eSgpLXRoaXMuc3BhY2UpO3RoaXMuYmIuc2V0UG9zaXRpb24odGhpcy5zcGFjZSl9ZmluaXNoU2l6ZVByZWZpeGVkKHQsZSl7dGhpcy5maW5pc2godCxlLCEwKX1yZXF1aXJlZEZpZWxkKHQsZSl7bGV0IHI9dGhpcy5iYi5jYXBhY2l0eSgpLXQsbj1yLXRoaXMuYmIucmVhZEludDMyKHIpO2lmKCEoZTx0aGlzLmJiLnJlYWRJbnQxNihuKSYmdGhpcy5iYi5yZWFkSW50MTYobitlKSE9MCkpdGhyb3cgVHlwZUVycm9yKCJGbGF0QnVmZmVyczogZmllbGQgIitlKyIgbXVzdCBiZSBzZXQiKX1zdGFydFZlY3Rvcih0LGUscil7dGhpcy5ub3ROZXN0ZWQoKSx0aGlzLnZlY3Rvcl9udW1fZWxlbXM9ZSx0aGlzLnByZXAoX24sdCplKSx0aGlzLnByZXAocix0KmUpfWVuZFZlY3Rvcigpe3JldHVybiB0aGlzLndyaXRlSW50MzIodGhpcy52ZWN0b3JfbnVtX2VsZW1zKSx0aGlzLm9mZnNldCgpfWNyZWF0ZVNoYXJlZFN0cmluZyh0KXtpZighdClyZXR1cm4gMDtpZighdGhpcy5zdHJpbmdfbWFwcyl0aGlzLnN0cmluZ19tYXBzPW5ldyBNYXA7aWYodGhpcy5zdHJpbmdfbWFwcy5oYXModCkpcmV0dXJuIHRoaXMuc3RyaW5nX21hcHMuZ2V0KHQpO2xldCBlPXRoaXMuY3JlYXRlU3RyaW5nKHQpO3JldHVybiB0aGlzLnN0cmluZ19tYXBzLnNldCh0LGUpLGV9Y3JlYXRlU3RyaW5nKHQpe2lmKHQ9PT1udWxsfHx0PT09dm9pZCAwKXJldHVybiAwO2xldCBlO2lmKHQgaW5zdGFuY2VvZiBVaW50OEFycmF5KWU9dDtlbHNlIGU9dGhpcy50ZXh0X2VuY29kZXIuZW5jb2RlKHQpO3JldHVybiB0aGlzLmFkZEludDgoMCksdGhpcy5zdGFydFZlY3RvcigxLGUubGVuZ3RoLDEpLHRoaXMuYmIuc2V0UG9zaXRpb24odGhpcy5zcGFjZS09ZS5sZW5ndGgpLHRoaXMuYmIuYnl0ZXMoKS5zZXQoZSx0aGlzLnNwYWNlKSx0aGlzLmVuZFZlY3RvcigpfWNyZWF0ZUJ5dGVWZWN0b3IodCl7aWYodD09PW51bGx8fHQ9PT12b2lkIDApcmV0dXJuIDA7cmV0dXJuIHRoaXMuc3RhcnRWZWN0b3IoMSx0Lmxlbmd0aCwxKSx0aGlzLmJiLnNldFBvc2l0aW9uKHRoaXMuc3BhY2UtPXQubGVuZ3RoKSx0aGlzLmJiLmJ5dGVzKCkuc2V0KHQsdGhpcy5zcGFjZSksdGhpcy5lbmRWZWN0b3IoKX1jcmVhdGVPYmplY3RPZmZzZXQodCl7aWYodD09PW51bGwpcmV0dXJuIDA7aWYodHlwZW9mIHQ9PT0ic3RyaW5nIilyZXR1cm4gdGhpcy5jcmVhdGVTdHJpbmcodCk7ZWxzZSByZXR1cm4gdC5wYWNrKHRoaXMpfWNyZWF0ZU9iamVjdE9mZnNldExpc3QodCl7bGV0IGU9W107Zm9yKGxldCByPTA7cjx0Lmxlbmd0aDsrK3Ipe2xldCBuPXRbcl07aWYobiE9PW51bGwpZS5wdXNoKHRoaXMuY3JlYXRlT2JqZWN0T2Zmc2V0KG4pKTtlbHNlIHRocm93IFR5cGVFcnJvcigiRmxhdEJ1ZmZlcnM6IEFyZ3VtZW50IGZvciBjcmVhdGVPYmplY3RPZmZzZXRMaXN0IGNhbm5vdCBjb250YWluIG51bGwuIil9cmV0dXJuIGV9Y3JlYXRlU3RydWN0T2Zmc2V0TGlzdCh0LGUpe3JldHVybiBlKHRoaXMsdC5sZW5ndGgpLHRoaXMuY3JlYXRlT2JqZWN0T2Zmc2V0TGlzdCh0LnNsaWNlKCkucmV2ZXJzZSgpKSx0aGlzLmVuZFZlY3RvcigpfX12YXIgTmI9bSgoKT0+e3JtKCl9KTt2YXIgTnQ9bSgoKT0+e3RtKCk7TmIoKTtybSgpO2VtKCl9KTt2YXIgY2E7dmFyIG5tPW0oKCk9PnsoZnVuY3Rpb24odCl7dFt0LkJVRkZFUj0wXT0iQlVGRkVSIn0pKGNhfHwoY2E9e30pKX0pO3ZhciBNcjt2YXIgRWw9bSgoKT0+eyhmdW5jdGlvbih0KXt0W3QuTFo0X0ZSQU1FPTBdPSJMWjRfRlJBTUUiLHRbdC5aU1REPTFdPSJaU1REIn0pKE1yfHwoTXI9e30pKX0pO2NsYXNzIEdye2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc0JvZHlDb21wcmVzc2lvbih0LGUpe3JldHVybihlfHxuZXcgR3IpLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzQm9keUNvbXByZXNzaW9uKHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK00pLChlfHxuZXcgR3IpLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1jb2RlYygpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50OCh0aGlzLmJiX3Bvcyt0KTpNci5MWjRfRlJBTUV9bWV0aG9kKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw2KTtyZXR1cm4gdD90aGlzLmJiLnJlYWRJbnQ4KHRoaXMuYmJfcG9zK3QpOmNhLkJVRkZFUn1zdGF0aWMgc3RhcnRCb2R5Q29tcHJlc3Npb24odCl7dC5zdGFydE9iamVjdCgyKX1zdGF0aWMgYWRkQ29kZWModCxlKXt0LmFkZEZpZWxkSW50OCgwLGUsTXIuTFo0X0ZSQU1FKX1zdGF0aWMgYWRkTWV0aG9kKHQsZSl7dC5hZGRGaWVsZEludDgoMSxlLGNhLkJVRkZFUil9c3RhdGljIGVuZEJvZHlDb21wcmVzc2lvbih0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgY3JlYXRlQm9keUNvbXByZXNzaW9uKHQsZSxyKXtyZXR1cm4gR3Iuc3RhcnRCb2R5Q29tcHJlc3Npb24odCksR3IuYWRkQ29kZWModCxlKSxHci5hZGRNZXRob2QodCxyKSxHci5lbmRCb2R5Q29tcHJlc3Npb24odCl9fXZhciBpbT1tKCgpPT57TnQoKTtubSgpO0VsKCl9KTtjbGFzcyBPbHtjb25zdHJ1Y3Rvcigpe3RoaXMuYmI9bnVsbCx0aGlzLmJiX3Bvcz0wfV9faW5pdCh0LGUpe3JldHVybiB0aGlzLmJiX3Bvcz10LHRoaXMuYmI9ZSx0aGlzfW9mZnNldCgpe3JldHVybiB0aGlzLmJiLnJlYWRJbnQ2NCh0aGlzLmJiX3Bvcyl9bGVuZ3RoKCl7cmV0dXJuIHRoaXMuYmIucmVhZEludDY0KHRoaXMuYmJfcG9zKzgpfXN0YXRpYyBzaXplT2YoKXtyZXR1cm4gMTZ9c3RhdGljIGNyZWF0ZUJ1ZmZlcih0LGUscil7cmV0dXJuIHQucHJlcCg4LDE2KSx0LndyaXRlSW50NjQoQmlnSW50KHIhPT1udWxsJiZyIT09dm9pZCAwP3I6MCkpLHQud3JpdGVJbnQ2NChCaWdJbnQoZSE9PW51bGwmJmUhPT12b2lkIDA/ZTowKSksdC5vZmZzZXQoKX19Y2xhc3MgTmx7Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31sZW5ndGgoKXtyZXR1cm4gdGhpcy5iYi5yZWFkSW50NjQodGhpcy5iYl9wb3MpfW51bGxDb3VudCgpe3JldHVybiB0aGlzLmJiLnJlYWRJbnQ2NCh0aGlzLmJiX3Bvcys4KX1zdGF0aWMgc2l6ZU9mKCl7cmV0dXJuIDE2fXN0YXRpYyBjcmVhdGVGaWVsZE5vZGUodCxlLHIpe3JldHVybiB0LnByZXAoOCwxNiksdC53cml0ZUludDY0KEJpZ0ludChyIT09bnVsbCYmciE9PXZvaWQgMD9yOjApKSx0LndyaXRlSW50NjQoQmlnSW50KGUhPT1udWxsJiZlIT09dm9pZCAwP2U6MCkpLHQub2Zmc2V0KCl9fWNsYXNzIHVye2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc1JlY29yZEJhdGNoKHQsZSl7cmV0dXJuKGV8fG5ldyB1cikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNSZWNvcmRCYXRjaCh0LGUpe3JldHVybiB0LnNldFBvc2l0aW9uKHQucG9zaXRpb24oKStNKSwoZXx8bmV3IHVyKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9bGVuZ3RoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw0KTtyZXR1cm4gdD90aGlzLmJiLnJlYWRJbnQ2NCh0aGlzLmJiX3Bvcyt0KTpCaWdJbnQoIjAiKX1ub2Rlcyh0LGUpe2xldCByPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNik7cmV0dXJuIHI/KGV8fG5ldyBObCkuX19pbml0KHRoaXMuYmIuX192ZWN0b3IodGhpcy5iYl9wb3MrcikrdCoxNix0aGlzLmJiKTpudWxsfW5vZGVzTGVuZ3RoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw2KTtyZXR1cm4gdD90aGlzLmJiLl9fdmVjdG9yX2xlbih0aGlzLmJiX3Bvcyt0KTowfWJ1ZmZlcnModCxlKXtsZXQgcj10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDgpO3JldHVybiByPyhlfHxuZXcgT2wpLl9faW5pdCh0aGlzLmJiLl9fdmVjdG9yKHRoaXMuYmJfcG9zK3IpK3QqMTYsdGhpcy5iYik6bnVsbH1idWZmZXJzTGVuZ3RoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw4KTtyZXR1cm4gdD90aGlzLmJiLl9fdmVjdG9yX2xlbih0aGlzLmJiX3Bvcyt0KTowfWNvbXByZXNzaW9uKHQpe2xldCBlPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsMTApO3JldHVybiBlPyh0fHxuZXcgR3IpLl9faW5pdCh0aGlzLmJiLl9faW5kaXJlY3QodGhpcy5iYl9wb3MrZSksdGhpcy5iYik6bnVsbH12YXJpYWRpY0J1ZmZlckNvdW50cyh0KXtsZXQgZT10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDEyKTtyZXR1cm4gZT90aGlzLmJiLnJlYWRJbnQ2NCh0aGlzLmJiLl9fdmVjdG9yKHRoaXMuYmJfcG9zK2UpK3QqOCk6QmlnSW50KDApfXZhcmlhZGljQnVmZmVyQ291bnRzTGVuZ3RoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3BvcywxMik7cmV0dXJuIHQ/dGhpcy5iYi5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MrdCk6MH1zdGF0aWMgc3RhcnRSZWNvcmRCYXRjaCh0KXt0LnN0YXJ0T2JqZWN0KDUpfXN0YXRpYyBhZGRMZW5ndGgodCxlKXt0LmFkZEZpZWxkSW50NjQoMCxlLEJpZ0ludCgiMCIpKX1zdGF0aWMgYWRkTm9kZXModCxlKXt0LmFkZEZpZWxkT2Zmc2V0KDEsZSwwKX1zdGF0aWMgc3RhcnROb2Rlc1ZlY3Rvcih0LGUpe3Quc3RhcnRWZWN0b3IoMTYsZSw4KX1zdGF0aWMgYWRkQnVmZmVycyh0LGUpe3QuYWRkRmllbGRPZmZzZXQoMixlLDApfXN0YXRpYyBzdGFydEJ1ZmZlcnNWZWN0b3IodCxlKXt0LnN0YXJ0VmVjdG9yKDE2LGUsOCl9c3RhdGljIGFkZENvbXByZXNzaW9uKHQsZSl7dC5hZGRGaWVsZE9mZnNldCgzLGUsMCl9c3RhdGljIGFkZFZhcmlhZGljQnVmZmVyQ291bnRzKHQsZSl7dC5hZGRGaWVsZE9mZnNldCg0LGUsMCl9c3RhdGljIGNyZWF0ZVZhcmlhZGljQnVmZmVyQ291bnRzVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig4LGUubGVuZ3RoLDgpO2ZvcihsZXQgcj1lLmxlbmd0aC0xO3I+PTA7ci0tKXQuYWRkSW50NjQoZVtyXSk7cmV0dXJuIHQuZW5kVmVjdG9yKCl9c3RhdGljIHN0YXJ0VmFyaWFkaWNCdWZmZXJDb3VudHNWZWN0b3IodCxlKXt0LnN0YXJ0VmVjdG9yKDgsZSw4KX1zdGF0aWMgZW5kUmVjb3JkQmF0Y2godCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9fXZhciBzbT1tKCgpPT57TnQoKTtpbSgpfSk7Y2xhc3Mgc3N7Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzRGljdGlvbmFyeUJhdGNoKHQsZSl7cmV0dXJuKGV8fG5ldyBzcykuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNEaWN0aW9uYXJ5QmF0Y2godCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTSksKGV8fG5ldyBzcykuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfWlkKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw0KTtyZXR1cm4gdD90aGlzLmJiLnJlYWRJbnQ2NCh0aGlzLmJiX3Bvcyt0KTpCaWdJbnQoIjAiKX1kYXRhKHQpe2xldCBlPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNik7cmV0dXJuIGU/KHR8fG5ldyB1cikuX19pbml0KHRoaXMuYmIuX19pbmRpcmVjdCh0aGlzLmJiX3BvcytlKSx0aGlzLmJiKTpudWxsfWlzRGVsdGEoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDgpO3JldHVybiB0PyEhdGhpcy5iYi5yZWFkSW50OCh0aGlzLmJiX3Bvcyt0KTohMX1zdGF0aWMgc3RhcnREaWN0aW9uYXJ5QmF0Y2godCl7dC5zdGFydE9iamVjdCgzKX1zdGF0aWMgYWRkSWQodCxlKXt0LmFkZEZpZWxkSW50NjQoMCxlLEJpZ0ludCgiMCIpKX1zdGF0aWMgYWRkRGF0YSh0LGUpe3QuYWRkRmllbGRPZmZzZXQoMSxlLDApfXN0YXRpYyBhZGRJc0RlbHRhKHQsZSl7dC5hZGRGaWVsZEludDgoMiwrZSwwKX1zdGF0aWMgZW5kRGljdGlvbmFyeUJhdGNoKHQpe3JldHVybiB0LmVuZE9iamVjdCgpfX12YXIgRmI9bSgoKT0+e050KCk7c20oKX0pO3ZhciBubzt2YXIgb209bSgoKT0+eyhmdW5jdGlvbih0KXt0W3QuTGl0dGxlPTBdPSJMaXR0bGUiLHRbdC5CaWc9MV09IkJpZyJ9KShub3x8KG5vPXt9KSl9KTt2YXIgRmw7dmFyIE1iPW0oKCk9PnsoZnVuY3Rpb24odCl7dFt0LkRlbnNlQXJyYXk9MF09IkRlbnNlQXJyYXkifSkoRmx8fChGbD17fSkpfSk7Y2xhc3MgYnJ7Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzSW50KHQsZSl7cmV0dXJuKGV8fG5ldyBicikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNJbnQodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTSksKGV8fG5ldyBicikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfWJpdFdpZHRoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw0KTtyZXR1cm4gdD90aGlzLmJiLnJlYWRJbnQzMih0aGlzLmJiX3Bvcyt0KTowfWlzU2lnbmVkKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw2KTtyZXR1cm4gdD8hIXRoaXMuYmIucmVhZEludDgodGhpcy5iYl9wb3MrdCk6ITF9c3RhdGljIHN0YXJ0SW50KHQpe3Quc3RhcnRPYmplY3QoMil9c3RhdGljIGFkZEJpdFdpZHRoKHQsZSl7dC5hZGRGaWVsZEludDMyKDAsZSwwKX1zdGF0aWMgYWRkSXNTaWduZWQodCxlKXt0LmFkZEZpZWxkSW50OCgxLCtlLDApfXN0YXRpYyBlbmRJbnQodCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9c3RhdGljIGNyZWF0ZUludCh0LGUscil7cmV0dXJuIGJyLnN0YXJ0SW50KHQpLGJyLmFkZEJpdFdpZHRoKHQsZSksYnIuYWRkSXNTaWduZWQodCxyKSxici5lbmRJbnQodCl9fXZhciB5Zj1tKCgpPT57TnQoKX0pO2NsYXNzIElpe2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc0RpY3Rpb25hcnlFbmNvZGluZyh0LGUpe3JldHVybihlfHxuZXcgSWkpLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzRGljdGlvbmFyeUVuY29kaW5nKHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK00pLChlfHxuZXcgSWkpLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1pZCgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50NjQodGhpcy5iYl9wb3MrdCk6QmlnSW50KCIwIil9aW5kZXhUeXBlKHQpe2xldCBlPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNik7cmV0dXJuIGU/KHR8fG5ldyBicikuX19pbml0KHRoaXMuYmIuX19pbmRpcmVjdCh0aGlzLmJiX3BvcytlKSx0aGlzLmJiKTpudWxsfWlzT3JkZXJlZCgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsOCk7cmV0dXJuIHQ/ISF0aGlzLmJiLnJlYWRJbnQ4KHRoaXMuYmJfcG9zK3QpOiExfWRpY3Rpb25hcnlLaW5kKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3BvcywxMCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50MTYodGhpcy5iYl9wb3MrdCk6RmwuRGVuc2VBcnJheX1zdGF0aWMgc3RhcnREaWN0aW9uYXJ5RW5jb2RpbmcodCl7dC5zdGFydE9iamVjdCg0KX1zdGF0aWMgYWRkSWQodCxlKXt0LmFkZEZpZWxkSW50NjQoMCxlLEJpZ0ludCgiMCIpKX1zdGF0aWMgYWRkSW5kZXhUeXBlKHQsZSl7dC5hZGRGaWVsZE9mZnNldCgxLGUsMCl9c3RhdGljIGFkZElzT3JkZXJlZCh0LGUpe3QuYWRkRmllbGRJbnQ4KDIsK2UsMCl9c3RhdGljIGFkZERpY3Rpb25hcnlLaW5kKHQsZSl7dC5hZGRGaWVsZEludDE2KDMsZSxGbC5EZW5zZUFycmF5KX1zdGF0aWMgZW5kRGljdGlvbmFyeUVuY29kaW5nKHQpe3JldHVybiB0LmVuZE9iamVjdCgpfX12YXIgYW09bSgoKT0+e050KCk7TWIoKTt5ZigpfSk7Y2xhc3MgbmV7Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzS2V5VmFsdWUodCxlKXtyZXR1cm4oZXx8bmV3IG5lKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0tleVZhbHVlKHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK00pLChlfHxuZXcgbmUpLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1rZXkodCl7bGV0IGU9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw0KTtyZXR1cm4gZT90aGlzLmJiLl9fc3RyaW5nKHRoaXMuYmJfcG9zK2UsdCk6bnVsbH12YWx1ZSh0KXtsZXQgZT10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDYpO3JldHVybiBlP3RoaXMuYmIuX19zdHJpbmcodGhpcy5iYl9wb3MrZSx0KTpudWxsfXN0YXRpYyBzdGFydEtleVZhbHVlKHQpe3Quc3RhcnRPYmplY3QoMil9c3RhdGljIGFkZEtleSh0LGUpe3QuYWRkRmllbGRPZmZzZXQoMCxlLDApfXN0YXRpYyBhZGRWYWx1ZSh0LGUpe3QuYWRkRmllbGRPZmZzZXQoMSxlLDApfXN0YXRpYyBlbmRLZXlWYWx1ZSh0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgY3JlYXRlS2V5VmFsdWUodCxlLHIpe3JldHVybiBuZS5zdGFydEtleVZhbHVlKHQpLG5lLmFkZEtleSh0LGUpLG5lLmFkZFZhbHVlKHQsciksbmUuZW5kS2V5VmFsdWUodCl9fXZhciBhYz1tKCgpPT57TnQoKX0pO2NsYXNzIGlve2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc0JpbmFyeSh0LGUpe3JldHVybihlfHxuZXcgaW8pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzQmluYXJ5KHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK00pLChlfHxuZXcgaW8pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgc3RhcnRCaW5hcnkodCl7dC5zdGFydE9iamVjdCgwKX1zdGF0aWMgZW5kQmluYXJ5KHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVCaW5hcnkodCl7cmV0dXJuIGlvLnN0YXJ0QmluYXJ5KHQpLGlvLmVuZEJpbmFyeSh0KX19dmFyIExiPW0oKCk9PntOdCgpfSk7Y2xhc3Mgc297Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzQmluYXJ5Vmlldyh0LGUpe3JldHVybihlfHxuZXcgc28pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzQmluYXJ5Vmlldyh0LGUpe3JldHVybiB0LnNldFBvc2l0aW9uKHQucG9zaXRpb24oKStNKSwoZXx8bmV3IHNvKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIHN0YXJ0QmluYXJ5Vmlldyh0KXt0LnN0YXJ0T2JqZWN0KDApfXN0YXRpYyBlbmRCaW5hcnlWaWV3KHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVCaW5hcnlWaWV3KHQpe3JldHVybiBzby5zdGFydEJpbmFyeVZpZXcodCksc28uZW5kQmluYXJ5Vmlldyh0KX19dmFyIFViPW0oKCk9PntOdCgpfSk7Y2xhc3Mgb297Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzQm9vbCh0LGUpe3JldHVybihlfHxuZXcgb28pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzQm9vbCh0LGUpe3JldHVybiB0LnNldFBvc2l0aW9uKHQucG9zaXRpb24oKStNKSwoZXx8bmV3IG9vKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIHN0YXJ0Qm9vbCh0KXt0LnN0YXJ0T2JqZWN0KDApfXN0YXRpYyBlbmRCb29sKHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVCb29sKHQpe3JldHVybiBvby5zdGFydEJvb2wodCksb28uZW5kQm9vbCh0KX19dmFyIFJiPW0oKCk9PntOdCgpfSk7Y2xhc3Mgam57Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzRGF0ZSh0LGUpe3JldHVybihlfHxuZXcgam4pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzRGF0ZSh0LGUpe3JldHVybiB0LnNldFBvc2l0aW9uKHQucG9zaXRpb24oKStNKSwoZXx8bmV3IGpuKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9dW5pdCgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50MTYodGhpcy5iYl9wb3MrdCk6cXQuTUlMTElTRUNPTkR9c3RhdGljIHN0YXJ0RGF0ZSh0KXt0LnN0YXJ0T2JqZWN0KDEpfXN0YXRpYyBhZGRVbml0KHQsZSl7dC5hZGRGaWVsZEludDE2KDAsZSxxdC5NSUxMSVNFQ09ORCl9c3RhdGljIGVuZERhdGUodCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9c3RhdGljIGNyZWF0ZURhdGUodCxlKXtyZXR1cm4gam4uc3RhcnREYXRlKHQpLGpuLmFkZFVuaXQodCxlKSxqbi5lbmREYXRlKHQpfX12YXIgY209bSgoKT0+e050KCk7WnAoKX0pO2NsYXNzIHdye2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc0RlY2ltYWwodCxlKXtyZXR1cm4oZXx8bmV3IHdyKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0RlY2ltYWwodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTSksKGV8fG5ldyB3cikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXByZWNpc2lvbigpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50MzIodGhpcy5iYl9wb3MrdCk6MH1zY2FsZSgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNik7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50MzIodGhpcy5iYl9wb3MrdCk6MH1iaXRXaWR0aCgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsOCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50MzIodGhpcy5iYl9wb3MrdCk6MTI4fXN0YXRpYyBzdGFydERlY2ltYWwodCl7dC5zdGFydE9iamVjdCgzKX1zdGF0aWMgYWRkUHJlY2lzaW9uKHQsZSl7dC5hZGRGaWVsZEludDMyKDAsZSwwKX1zdGF0aWMgYWRkU2NhbGUodCxlKXt0LmFkZEZpZWxkSW50MzIoMSxlLDApfXN0YXRpYyBhZGRCaXRXaWR0aCh0LGUpe3QuYWRkRmllbGRJbnQzMigyLGUsMTI4KX1zdGF0aWMgZW5kRGVjaW1hbCh0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgY3JlYXRlRGVjaW1hbCh0LGUscixuKXtyZXR1cm4gd3Iuc3RhcnREZWNpbWFsKHQpLHdyLmFkZFByZWNpc2lvbih0LGUpLHdyLmFkZFNjYWxlKHQsciksd3IuYWRkQml0V2lkdGgodCxuKSx3ci5lbmREZWNpbWFsKHQpfX12YXIgbG09bSgoKT0+e050KCl9KTtjbGFzcyAkbntjb25zdHJ1Y3Rvcigpe3RoaXMuYmI9bnVsbCx0aGlzLmJiX3Bvcz0wfV9faW5pdCh0LGUpe3JldHVybiB0aGlzLmJiX3Bvcz10LHRoaXMuYmI9ZSx0aGlzfXN0YXRpYyBnZXRSb290QXNEdXJhdGlvbih0LGUpe3JldHVybihlfHxuZXcgJG4pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzRHVyYXRpb24odCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTSksKGV8fG5ldyAkbikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXVuaXQoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDQpO3JldHVybiB0P3RoaXMuYmIucmVhZEludDE2KHRoaXMuYmJfcG9zK3QpOlQuTUlMTElTRUNPTkR9c3RhdGljIHN0YXJ0RHVyYXRpb24odCl7dC5zdGFydE9iamVjdCgxKX1zdGF0aWMgYWRkVW5pdCh0LGUpe3QuYWRkRmllbGRJbnQxNigwLGUsVC5NSUxMSVNFQ09ORCl9c3RhdGljIGVuZER1cmF0aW9uKHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVEdXJhdGlvbih0LGUpe3JldHVybiAkbi5zdGFydER1cmF0aW9uKHQpLCRuLmFkZFVuaXQodCxlKSwkbi5lbmREdXJhdGlvbih0KX19dmFyIHVtPW0oKCk9PntOdCgpO0RsKCl9KTtjbGFzcyBxbntjb25zdHJ1Y3Rvcigpe3RoaXMuYmI9bnVsbCx0aGlzLmJiX3Bvcz0wfV9faW5pdCh0LGUpe3JldHVybiB0aGlzLmJiX3Bvcz10LHRoaXMuYmI9ZSx0aGlzfXN0YXRpYyBnZXRSb290QXNGaXhlZFNpemVCaW5hcnkodCxlKXtyZXR1cm4oZXx8bmV3IHFuKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0ZpeGVkU2l6ZUJpbmFyeSh0LGUpe3JldHVybiB0LnNldFBvc2l0aW9uKHQucG9zaXRpb24oKStNKSwoZXx8bmV3IHFuKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9Ynl0ZVdpZHRoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw0KTtyZXR1cm4gdD90aGlzLmJiLnJlYWRJbnQzMih0aGlzLmJiX3Bvcyt0KTowfXN0YXRpYyBzdGFydEZpeGVkU2l6ZUJpbmFyeSh0KXt0LnN0YXJ0T2JqZWN0KDEpfXN0YXRpYyBhZGRCeXRlV2lkdGgodCxlKXt0LmFkZEZpZWxkSW50MzIoMCxlLDApfXN0YXRpYyBlbmRGaXhlZFNpemVCaW5hcnkodCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9c3RhdGljIGNyZWF0ZUZpeGVkU2l6ZUJpbmFyeSh0LGUpe3JldHVybiBxbi5zdGFydEZpeGVkU2l6ZUJpbmFyeSh0KSxxbi5hZGRCeXRlV2lkdGgodCxlKSxxbi5lbmRGaXhlZFNpemVCaW5hcnkodCl9fXZhciBmbT1tKCgpPT57TnQoKX0pO2NsYXNzIFdue2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc0ZpeGVkU2l6ZUxpc3QodCxlKXtyZXR1cm4oZXx8bmV3IFduKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0ZpeGVkU2l6ZUxpc3QodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTSksKGV8fG5ldyBXbikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfWxpc3RTaXplKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw0KTtyZXR1cm4gdD90aGlzLmJiLnJlYWRJbnQzMih0aGlzLmJiX3Bvcyt0KTowfXN0YXRpYyBzdGFydEZpeGVkU2l6ZUxpc3QodCl7dC5zdGFydE9iamVjdCgxKX1zdGF0aWMgYWRkTGlzdFNpemUodCxlKXt0LmFkZEZpZWxkSW50MzIoMCxlLDApfXN0YXRpYyBlbmRGaXhlZFNpemVMaXN0KHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVGaXhlZFNpemVMaXN0KHQsZSl7cmV0dXJuIFduLnN0YXJ0Rml4ZWRTaXplTGlzdCh0KSxXbi5hZGRMaXN0U2l6ZSh0LGUpLFduLmVuZEZpeGVkU2l6ZUxpc3QodCl9fXZhciBkbT1tKCgpPT57TnQoKX0pO2NsYXNzIEhue2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc0Zsb2F0aW5nUG9pbnQodCxlKXtyZXR1cm4oZXx8bmV3IEhuKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0Zsb2F0aW5nUG9pbnQodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTSksKGV8fG5ldyBIbikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXByZWNpc2lvbigpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50MTYodGhpcy5iYl9wb3MrdCk6WnQuSEFMRn1zdGF0aWMgc3RhcnRGbG9hdGluZ1BvaW50KHQpe3Quc3RhcnRPYmplY3QoMSl9c3RhdGljIGFkZFByZWNpc2lvbih0LGUpe3QuYWRkRmllbGRJbnQxNigwLGUsWnQuSEFMRil9c3RhdGljIGVuZEZsb2F0aW5nUG9pbnQodCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9c3RhdGljIGNyZWF0ZUZsb2F0aW5nUG9pbnQodCxlKXtyZXR1cm4gSG4uc3RhcnRGbG9hdGluZ1BvaW50KHQpLEhuLmFkZFByZWNpc2lvbih0LGUpLEhuLmVuZEZsb2F0aW5nUG9pbnQodCl9fXZhciBobT1tKCgpPT57TnQoKTtYcCgpfSk7Y2xhc3MgWW57Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzSW50ZXJ2YWwodCxlKXtyZXR1cm4oZXx8bmV3IFluKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0ludGVydmFsKHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK00pLChlfHxuZXcgWW4pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX11bml0KCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw0KTtyZXR1cm4gdD90aGlzLmJiLnJlYWRJbnQxNih0aGlzLmJiX3Bvcyt0KTpqdC5ZRUFSX01PTlRIfXN0YXRpYyBzdGFydEludGVydmFsKHQpe3Quc3RhcnRPYmplY3QoMSl9c3RhdGljIGFkZFVuaXQodCxlKXt0LmFkZEZpZWxkSW50MTYoMCxlLGp0LllFQVJfTU9OVEgpfXN0YXRpYyBlbmRJbnRlcnZhbCh0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgY3JlYXRlSW50ZXJ2YWwodCxlKXtyZXR1cm4gWW4uc3RhcnRJbnRlcnZhbCh0KSxZbi5hZGRVbml0KHQsZSksWW4uZW5kSW50ZXJ2YWwodCl9fXZhciBwbT1tKCgpPT57TnQoKTtRcCgpfSk7Y2xhc3MgYW97Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzTGFyZ2VCaW5hcnkodCxlKXtyZXR1cm4oZXx8bmV3IGFvKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0xhcmdlQmluYXJ5KHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK00pLChlfHxuZXcgYW8pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgc3RhcnRMYXJnZUJpbmFyeSh0KXt0LnN0YXJ0T2JqZWN0KDApfXN0YXRpYyBlbmRMYXJnZUJpbmFyeSh0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgY3JlYXRlTGFyZ2VCaW5hcnkodCl7cmV0dXJuIGFvLnN0YXJ0TGFyZ2VCaW5hcnkodCksYW8uZW5kTGFyZ2VCaW5hcnkodCl9fXZhciBDYj1tKCgpPT57TnQoKX0pO2NsYXNzIGNve2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc0xhcmdlVXRmOCh0LGUpe3JldHVybihlfHxuZXcgY28pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzTGFyZ2VVdGY4KHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK00pLChlfHxuZXcgY28pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgc3RhcnRMYXJnZVV0ZjgodCl7dC5zdGFydE9iamVjdCgwKX1zdGF0aWMgZW5kTGFyZ2VVdGY4KHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVMYXJnZVV0ZjgodCl7cmV0dXJuIGNvLnN0YXJ0TGFyZ2VVdGY4KHQpLGNvLmVuZExhcmdlVXRmOCh0KX19dmFyIFBiPW0oKCk9PntOdCgpfSk7Y2xhc3MgbG97Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzTGlzdCh0LGUpe3JldHVybihlfHxuZXcgbG8pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzTGlzdCh0LGUpe3JldHVybiB0LnNldFBvc2l0aW9uKHQucG9zaXRpb24oKStNKSwoZXx8bmV3IGxvKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIHN0YXJ0TGlzdCh0KXt0LnN0YXJ0T2JqZWN0KDApfXN0YXRpYyBlbmRMaXN0KHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVMaXN0KHQpe3JldHVybiBsby5zdGFydExpc3QodCksbG8uZW5kTGlzdCh0KX19dmFyIGtiPW0oKCk9PntOdCgpfSk7Y2xhc3MgS257Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzTWFwKHQsZSl7cmV0dXJuKGV8fG5ldyBLbikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNNYXAodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTSksKGV8fG5ldyBLbikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfWtleXNTb3J0ZWQoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDQpO3JldHVybiB0PyEhdGhpcy5iYi5yZWFkSW50OCh0aGlzLmJiX3Bvcyt0KTohMX1zdGF0aWMgc3RhcnRNYXAodCl7dC5zdGFydE9iamVjdCgxKX1zdGF0aWMgYWRkS2V5c1NvcnRlZCh0LGUpe3QuYWRkRmllbGRJbnQ4KDAsK2UsMCl9c3RhdGljIGVuZE1hcCh0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgY3JlYXRlTWFwKHQsZSl7cmV0dXJuIEtuLnN0YXJ0TWFwKHQpLEtuLmFkZEtleXNTb3J0ZWQodCxlKSxLbi5lbmRNYXAodCl9fXZhciBtbT1tKCgpPT57TnQoKX0pO2NsYXNzIHVve2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc051bGwodCxlKXtyZXR1cm4oZXx8bmV3IHVvKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc051bGwodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTSksKGV8fG5ldyB1bykuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBzdGFydE51bGwodCl7dC5zdGFydE9iamVjdCgwKX1zdGF0aWMgZW5kTnVsbCh0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgY3JlYXRlTnVsbCh0KXtyZXR1cm4gdW8uc3RhcnROdWxsKHQpLHVvLmVuZE51bGwodCl9fXZhciBWYj1tKCgpPT57TnQoKX0pO2NsYXNzIGZve2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc1N0cnVjdF8odCxlKXtyZXR1cm4oZXx8bmV3IGZvKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc1N0cnVjdF8odCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTSksKGV8fG5ldyBmbykuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBzdGFydFN0cnVjdF8odCl7dC5zdGFydE9iamVjdCgwKX1zdGF0aWMgZW5kU3RydWN0Xyh0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgY3JlYXRlU3RydWN0Xyh0KXtyZXR1cm4gZm8uc3RhcnRTdHJ1Y3RfKHQpLGZvLmVuZFN0cnVjdF8odCl9fXZhciB6Yj1tKCgpPT57TnQoKX0pO2NsYXNzIEpye2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc1RpbWUodCxlKXtyZXR1cm4oZXx8bmV3IEpyKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc1RpbWUodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTSksKGV8fG5ldyBKcikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXVuaXQoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDQpO3JldHVybiB0P3RoaXMuYmIucmVhZEludDE2KHRoaXMuYmJfcG9zK3QpOlQuTUlMTElTRUNPTkR9Yml0V2lkdGgoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDYpO3JldHVybiB0P3RoaXMuYmIucmVhZEludDMyKHRoaXMuYmJfcG9zK3QpOjMyfXN0YXRpYyBzdGFydFRpbWUodCl7dC5zdGFydE9iamVjdCgyKX1zdGF0aWMgYWRkVW5pdCh0LGUpe3QuYWRkRmllbGRJbnQxNigwLGUsVC5NSUxMSVNFQ09ORCl9c3RhdGljIGFkZEJpdFdpZHRoKHQsZSl7dC5hZGRGaWVsZEludDMyKDEsZSwzMil9c3RhdGljIGVuZFRpbWUodCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9c3RhdGljIGNyZWF0ZVRpbWUodCxlLHIpe3JldHVybiBKci5zdGFydFRpbWUodCksSnIuYWRkVW5pdCh0LGUpLEpyLmFkZEJpdFdpZHRoKHQsciksSnIuZW5kVGltZSh0KX19dmFyIHltPW0oKCk9PntOdCgpO0RsKCl9KTtjbGFzcyBYcntjb25zdHJ1Y3Rvcigpe3RoaXMuYmI9bnVsbCx0aGlzLmJiX3Bvcz0wfV9faW5pdCh0LGUpe3JldHVybiB0aGlzLmJiX3Bvcz10LHRoaXMuYmI9ZSx0aGlzfXN0YXRpYyBnZXRSb290QXNUaW1lc3RhbXAodCxlKXtyZXR1cm4oZXx8bmV3IFhyKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc1RpbWVzdGFtcCh0LGUpe3JldHVybiB0LnNldFBvc2l0aW9uKHQucG9zaXRpb24oKStNKSwoZXx8bmV3IFhyKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9dW5pdCgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50MTYodGhpcy5iYl9wb3MrdCk6VC5TRUNPTkR9dGltZXpvbmUodCl7bGV0IGU9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw2KTtyZXR1cm4gZT90aGlzLmJiLl9fc3RyaW5nKHRoaXMuYmJfcG9zK2UsdCk6bnVsbH1zdGF0aWMgc3RhcnRUaW1lc3RhbXAodCl7dC5zdGFydE9iamVjdCgyKX1zdGF0aWMgYWRkVW5pdCh0LGUpe3QuYWRkRmllbGRJbnQxNigwLGUsVC5TRUNPTkQpfXN0YXRpYyBhZGRUaW1lem9uZSh0LGUpe3QuYWRkRmllbGRPZmZzZXQoMSxlLDApfXN0YXRpYyBlbmRUaW1lc3RhbXAodCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9c3RhdGljIGNyZWF0ZVRpbWVzdGFtcCh0LGUscil7cmV0dXJuIFhyLnN0YXJ0VGltZXN0YW1wKHQpLFhyLmFkZFVuaXQodCxlKSxYci5hZGRUaW1lem9uZSh0LHIpLFhyLmVuZFRpbWVzdGFtcCh0KX19dmFyIF9tPW0oKCk9PntOdCgpO0RsKCl9KTtjbGFzcyB2cntjb25zdHJ1Y3Rvcigpe3RoaXMuYmI9bnVsbCx0aGlzLmJiX3Bvcz0wfV9faW5pdCh0LGUpe3JldHVybiB0aGlzLmJiX3Bvcz10LHRoaXMuYmI9ZSx0aGlzfXN0YXRpYyBnZXRSb290QXNVbmlvbih0LGUpe3JldHVybihlfHxuZXcgdnIpLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzVW5pb24odCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTSksKGV8fG5ldyB2cikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfW1vZGUoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDQpO3JldHVybiB0P3RoaXMuYmIucmVhZEludDE2KHRoaXMuYmJfcG9zK3QpOkx0LlNwYXJzZX10eXBlSWRzKHQpe2xldCBlPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNik7cmV0dXJuIGU/dGhpcy5iYi5yZWFkSW50MzIodGhpcy5iYi5fX3ZlY3Rvcih0aGlzLmJiX3BvcytlKSt0KjQpOjB9dHlwZUlkc0xlbmd0aCgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNik7cmV0dXJuIHQ/dGhpcy5iYi5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MrdCk6MH10eXBlSWRzQXJyYXkoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDYpO3JldHVybiB0P25ldyBJbnQzMkFycmF5KHRoaXMuYmIuYnl0ZXMoKS5idWZmZXIsdGhpcy5iYi5ieXRlcygpLmJ5dGVPZmZzZXQrdGhpcy5iYi5fX3ZlY3Rvcih0aGlzLmJiX3Bvcyt0KSx0aGlzLmJiLl9fdmVjdG9yX2xlbih0aGlzLmJiX3Bvcyt0KSk6bnVsbH1zdGF0aWMgc3RhcnRVbmlvbih0KXt0LnN0YXJ0T2JqZWN0KDIpfXN0YXRpYyBhZGRNb2RlKHQsZSl7dC5hZGRGaWVsZEludDE2KDAsZSxMdC5TcGFyc2UpfXN0YXRpYyBhZGRUeXBlSWRzKHQsZSl7dC5hZGRGaWVsZE9mZnNldCgxLGUsMCl9c3RhdGljIGNyZWF0ZVR5cGVJZHNWZWN0b3IodCxlKXt0LnN0YXJ0VmVjdG9yKDQsZS5sZW5ndGgsNCk7Zm9yKGxldCByPWUubGVuZ3RoLTE7cj49MDtyLS0pdC5hZGRJbnQzMihlW3JdKTtyZXR1cm4gdC5lbmRWZWN0b3IoKX1zdGF0aWMgc3RhcnRUeXBlSWRzVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig0LGUsNCl9c3RhdGljIGVuZFVuaW9uKHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVVbmlvbih0LGUscil7cmV0dXJuIHZyLnN0YXJ0VW5pb24odCksdnIuYWRkTW9kZSh0LGUpLHZyLmFkZFR5cGVJZHModCxyKSx2ci5lbmRVbmlvbih0KX19dmFyIGdtPW0oKCk9PntOdCgpO0pwKCl9KTtjbGFzcyBob3tjb25zdHJ1Y3Rvcigpe3RoaXMuYmI9bnVsbCx0aGlzLmJiX3Bvcz0wfV9faW5pdCh0LGUpe3JldHVybiB0aGlzLmJiX3Bvcz10LHRoaXMuYmI9ZSx0aGlzfXN0YXRpYyBnZXRSb290QXNVdGY4KHQsZSl7cmV0dXJuKGV8fG5ldyBobykuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNVdGY4KHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK00pLChlfHxuZXcgaG8pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgc3RhcnRVdGY4KHQpe3Quc3RhcnRPYmplY3QoMCl9c3RhdGljIGVuZFV0ZjgodCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9c3RhdGljIGNyZWF0ZVV0ZjgodCl7cmV0dXJuIGhvLnN0YXJ0VXRmOCh0KSxoby5lbmRVdGY4KHQpfX12YXIgamI9bSgoKT0+e050KCl9KTtjbGFzcyBwb3tjb25zdHJ1Y3Rvcigpe3RoaXMuYmI9bnVsbCx0aGlzLmJiX3Bvcz0wfV9faW5pdCh0LGUpe3JldHVybiB0aGlzLmJiX3Bvcz10LHRoaXMuYmI9ZSx0aGlzfXN0YXRpYyBnZXRSb290QXNVdGY4Vmlldyh0LGUpe3JldHVybihlfHxuZXcgcG8pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzVXRmOFZpZXcodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTSksKGV8fG5ldyBwbykuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBzdGFydFV0ZjhWaWV3KHQpe3Quc3RhcnRPYmplY3QoMCl9c3RhdGljIGVuZFV0ZjhWaWV3KHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVVdGY4Vmlldyh0KXtyZXR1cm4gcG8uc3RhcnRVdGY4Vmlldyh0KSxwby5lbmRVdGY4Vmlldyh0KX19dmFyICRiPW0oKCk9PntOdCgpfSk7dmFyIFl0O3ZhciBibT1tKCgpPT57KGZ1bmN0aW9uKHQpe3RbdC5OT05FPTBdPSJOT05FIix0W3QuTnVsbD0xXT0iTnVsbCIsdFt0LkludD0yXT0iSW50Iix0W3QuRmxvYXRpbmdQb2ludD0zXT0iRmxvYXRpbmdQb2ludCIsdFt0LkJpbmFyeT00XT0iQmluYXJ5Iix0W3QuVXRmOD01XT0iVXRmOCIsdFt0LkJvb2w9Nl09IkJvb2wiLHRbdC5EZWNpbWFsPTddPSJEZWNpbWFsIix0W3QuRGF0ZT04XT0iRGF0ZSIsdFt0LlRpbWU9OV09IlRpbWUiLHRbdC5UaW1lc3RhbXA9MTBdPSJUaW1lc3RhbXAiLHRbdC5JbnRlcnZhbD0xMV09IkludGVydmFsIix0W3QuTGlzdD0xMl09Ikxpc3QiLHRbdC5TdHJ1Y3RfPTEzXT0iU3RydWN0XyIsdFt0LlVuaW9uPTE0XT0iVW5pb24iLHRbdC5GaXhlZFNpemVCaW5hcnk9MTVdPSJGaXhlZFNpemVCaW5hcnkiLHRbdC5GaXhlZFNpemVMaXN0PTE2XT0iRml4ZWRTaXplTGlzdCIsdFt0Lk1hcD0xN109Ik1hcCIsdFt0LkR1cmF0aW9uPTE4XT0iRHVyYXRpb24iLHRbdC5MYXJnZUJpbmFyeT0xOV09IkxhcmdlQmluYXJ5Iix0W3QuTGFyZ2VVdGY4PTIwXT0iTGFyZ2VVdGY4Iix0W3QuTGFyZ2VMaXN0PTIxXT0iTGFyZ2VMaXN0Iix0W3QuUnVuRW5kRW5jb2RlZD0yMl09IlJ1bkVuZEVuY29kZWQiLHRbdC5CaW5hcnlWaWV3PTIzXT0iQmluYXJ5VmlldyIsdFt0LlV0ZjhWaWV3PTI0XT0iVXRmOFZpZXciLHRbdC5MaXN0Vmlldz0yNV09Ikxpc3RWaWV3Iix0W3QuTGFyZ2VMaXN0Vmlldz0yNl09IkxhcmdlTGlzdFZpZXcifSkoWXR8fChZdD17fSkpfSk7Y2xhc3MgUWV7Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzRmllbGQodCxlKXtyZXR1cm4oZXx8bmV3IFFlKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0ZpZWxkKHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK00pLChlfHxuZXcgUWUpLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1uYW1lKHQpe2xldCBlPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNCk7cmV0dXJuIGU/dGhpcy5iYi5fX3N0cmluZyh0aGlzLmJiX3BvcytlLHQpOm51bGx9bnVsbGFibGUoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDYpO3JldHVybiB0PyEhdGhpcy5iYi5yZWFkSW50OCh0aGlzLmJiX3Bvcyt0KTohMX10eXBlVHlwZSgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsOCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkVWludDgodGhpcy5iYl9wb3MrdCk6WXQuTk9ORX10eXBlKHQpe2xldCBlPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsMTApO3JldHVybiBlP3RoaXMuYmIuX191bmlvbih0LHRoaXMuYmJfcG9zK2UpOm51bGx9ZGljdGlvbmFyeSh0KXtsZXQgZT10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDEyKTtyZXR1cm4gZT8odHx8bmV3IElpKS5fX2luaXQodGhpcy5iYi5fX2luZGlyZWN0KHRoaXMuYmJfcG9zK2UpLHRoaXMuYmIpOm51bGx9Y2hpbGRyZW4odCxlKXtsZXQgcj10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDE0KTtyZXR1cm4gcj8oZXx8bmV3IFFlKS5fX2luaXQodGhpcy5iYi5fX2luZGlyZWN0KHRoaXMuYmIuX192ZWN0b3IodGhpcy5iYl9wb3MrcikrdCo0KSx0aGlzLmJiKTpudWxsfWNoaWxkcmVuTGVuZ3RoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3BvcywxNCk7cmV0dXJuIHQ/dGhpcy5iYi5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MrdCk6MH1jdXN0b21NZXRhZGF0YSh0LGUpe2xldCByPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsMTYpO3JldHVybiByPyhlfHxuZXcgbmUpLl9faW5pdCh0aGlzLmJiLl9faW5kaXJlY3QodGhpcy5iYi5fX3ZlY3Rvcih0aGlzLmJiX3BvcytyKSt0KjQpLHRoaXMuYmIpOm51bGx9Y3VzdG9tTWV0YWRhdGFMZW5ndGgoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDE2KTtyZXR1cm4gdD90aGlzLmJiLl9fdmVjdG9yX2xlbih0aGlzLmJiX3Bvcyt0KTowfXN0YXRpYyBzdGFydEZpZWxkKHQpe3Quc3RhcnRPYmplY3QoNyl9c3RhdGljIGFkZE5hbWUodCxlKXt0LmFkZEZpZWxkT2Zmc2V0KDAsZSwwKX1zdGF0aWMgYWRkTnVsbGFibGUodCxlKXt0LmFkZEZpZWxkSW50OCgxLCtlLDApfXN0YXRpYyBhZGRUeXBlVHlwZSh0LGUpe3QuYWRkRmllbGRJbnQ4KDIsZSxZdC5OT05FKX1zdGF0aWMgYWRkVHlwZSh0LGUpe3QuYWRkRmllbGRPZmZzZXQoMyxlLDApfXN0YXRpYyBhZGREaWN0aW9uYXJ5KHQsZSl7dC5hZGRGaWVsZE9mZnNldCg0LGUsMCl9c3RhdGljIGFkZENoaWxkcmVuKHQsZSl7dC5hZGRGaWVsZE9mZnNldCg1LGUsMCl9c3RhdGljIGNyZWF0ZUNoaWxkcmVuVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig0LGUubGVuZ3RoLDQpO2ZvcihsZXQgcj1lLmxlbmd0aC0xO3I+PTA7ci0tKXQuYWRkT2Zmc2V0KGVbcl0pO3JldHVybiB0LmVuZFZlY3RvcigpfXN0YXRpYyBzdGFydENoaWxkcmVuVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig0LGUsNCl9c3RhdGljIGFkZEN1c3RvbU1ldGFkYXRhKHQsZSl7dC5hZGRGaWVsZE9mZnNldCg2LGUsMCl9c3RhdGljIGNyZWF0ZUN1c3RvbU1ldGFkYXRhVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig0LGUubGVuZ3RoLDQpO2ZvcihsZXQgcj1lLmxlbmd0aC0xO3I+PTA7ci0tKXQuYWRkT2Zmc2V0KGVbcl0pO3JldHVybiB0LmVuZFZlY3RvcigpfXN0YXRpYyBzdGFydEN1c3RvbU1ldGFkYXRhVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig0LGUsNCl9c3RhdGljIGVuZEZpZWxkKHQpe3JldHVybiB0LmVuZE9iamVjdCgpfX12YXIgd209bSgoKT0+e050KCk7YW0oKTthYygpO2JtKCl9KTtjbGFzcyBBZXtjb25zdHJ1Y3Rvcigpe3RoaXMuYmI9bnVsbCx0aGlzLmJiX3Bvcz0wfV9faW5pdCh0LGUpe3JldHVybiB0aGlzLmJiX3Bvcz10LHRoaXMuYmI9ZSx0aGlzfXN0YXRpYyBnZXRSb290QXNTY2hlbWEodCxlKXtyZXR1cm4oZXx8bmV3IEFlKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc1NjaGVtYSh0LGUpe3JldHVybiB0LnNldFBvc2l0aW9uKHQucG9zaXRpb24oKStNKSwoZXx8bmV3IEFlKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9ZW5kaWFubmVzcygpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50MTYodGhpcy5iYl9wb3MrdCk6bm8uTGl0dGxlfWZpZWxkcyh0LGUpe2xldCByPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNik7cmV0dXJuIHI/KGV8fG5ldyBRZSkuX19pbml0KHRoaXMuYmIuX19pbmRpcmVjdCh0aGlzLmJiLl9fdmVjdG9yKHRoaXMuYmJfcG9zK3IpK3QqNCksdGhpcy5iYik6bnVsbH1maWVsZHNMZW5ndGgoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDYpO3JldHVybiB0P3RoaXMuYmIuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zK3QpOjB9Y3VzdG9tTWV0YWRhdGEodCxlKXtsZXQgcj10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDgpO3JldHVybiByPyhlfHxuZXcgbmUpLl9faW5pdCh0aGlzLmJiLl9faW5kaXJlY3QodGhpcy5iYi5fX3ZlY3Rvcih0aGlzLmJiX3BvcytyKSt0KjQpLHRoaXMuYmIpOm51bGx9Y3VzdG9tTWV0YWRhdGFMZW5ndGgoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDgpO3JldHVybiB0P3RoaXMuYmIuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zK3QpOjB9ZmVhdHVyZXModCl7bGV0IGU9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3BvcywxMCk7cmV0dXJuIGU/dGhpcy5iYi5yZWFkSW50NjQodGhpcy5iYi5fX3ZlY3Rvcih0aGlzLmJiX3BvcytlKSt0KjgpOkJpZ0ludCgwKX1mZWF0dXJlc0xlbmd0aCgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsMTApO3JldHVybiB0P3RoaXMuYmIuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zK3QpOjB9c3RhdGljIHN0YXJ0U2NoZW1hKHQpe3Quc3RhcnRPYmplY3QoNCl9c3RhdGljIGFkZEVuZGlhbm5lc3ModCxlKXt0LmFkZEZpZWxkSW50MTYoMCxlLG5vLkxpdHRsZSl9c3RhdGljIGFkZEZpZWxkcyh0LGUpe3QuYWRkRmllbGRPZmZzZXQoMSxlLDApfXN0YXRpYyBjcmVhdGVGaWVsZHNWZWN0b3IodCxlKXt0LnN0YXJ0VmVjdG9yKDQsZS5sZW5ndGgsNCk7Zm9yKGxldCByPWUubGVuZ3RoLTE7cj49MDtyLS0pdC5hZGRPZmZzZXQoZVtyXSk7cmV0dXJuIHQuZW5kVmVjdG9yKCl9c3RhdGljIHN0YXJ0RmllbGRzVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig0LGUsNCl9c3RhdGljIGFkZEN1c3RvbU1ldGFkYXRhKHQsZSl7dC5hZGRGaWVsZE9mZnNldCgyLGUsMCl9c3RhdGljIGNyZWF0ZUN1c3RvbU1ldGFkYXRhVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig0LGUubGVuZ3RoLDQpO2ZvcihsZXQgcj1lLmxlbmd0aC0xO3I+PTA7ci0tKXQuYWRkT2Zmc2V0KGVbcl0pO3JldHVybiB0LmVuZFZlY3RvcigpfXN0YXRpYyBzdGFydEN1c3RvbU1ldGFkYXRhVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig0LGUsNCl9c3RhdGljIGFkZEZlYXR1cmVzKHQsZSl7dC5hZGRGaWVsZE9mZnNldCgzLGUsMCl9c3RhdGljIGNyZWF0ZUZlYXR1cmVzVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig4LGUubGVuZ3RoLDgpO2ZvcihsZXQgcj1lLmxlbmd0aC0xO3I+PTA7ci0tKXQuYWRkSW50NjQoZVtyXSk7cmV0dXJuIHQuZW5kVmVjdG9yKCl9c3RhdGljIHN0YXJ0RmVhdHVyZXNWZWN0b3IodCxlKXt0LnN0YXJ0VmVjdG9yKDgsZSw4KX1zdGF0aWMgZW5kU2NoZW1hKHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVTY2hlbWEodCxlLHIsbixpKXtyZXR1cm4gQWUuc3RhcnRTY2hlbWEodCksQWUuYWRkRW5kaWFubmVzcyh0LGUpLEFlLmFkZEZpZWxkcyh0LHIpLEFlLmFkZEN1c3RvbU1ldGFkYXRhKHQsbiksQWUuYWRkRmVhdHVyZXModCxpKSxBZS5lbmRTY2hlbWEodCl9fXZhciB2bT1tKCgpPT57TnQoKTtvbSgpO3dtKCk7YWMoKX0pO3ZhciB4dDt2YXIgSW09bSgoKT0+eyhmdW5jdGlvbih0KXt0W3QuTk9ORT0wXT0iTk9ORSIsdFt0LlNjaGVtYT0xXT0iU2NoZW1hIix0W3QuRGljdGlvbmFyeUJhdGNoPTJdPSJEaWN0aW9uYXJ5QmF0Y2giLHRbdC5SZWNvcmRCYXRjaD0zXT0iUmVjb3JkQmF0Y2giLHRbdC5UZW5zb3I9NF09IlRlbnNvciIsdFt0LlNwYXJzZVRlbnNvcj01XT0iU3BhcnNlVGVuc29yIn0pKHh0fHwoeHQ9e30pKX0pO3ZhciBfLFpyO3ZhciBMZT1tKCgpPT57aGYoKTtKcCgpO1hwKCk7WnAoKTtEbCgpO1FwKCk7SW0oKTsoZnVuY3Rpb24odCl7dFt0Lk5PTkU9MF09Ik5PTkUiLHRbdC5OdWxsPTFdPSJOdWxsIix0W3QuSW50PTJdPSJJbnQiLHRbdC5GbG9hdD0zXT0iRmxvYXQiLHRbdC5CaW5hcnk9NF09IkJpbmFyeSIsdFt0LlV0Zjg9NV09IlV0ZjgiLHRbdC5Cb29sPTZdPSJCb29sIix0W3QuRGVjaW1hbD03XT0iRGVjaW1hbCIsdFt0LkRhdGU9OF09IkRhdGUiLHRbdC5UaW1lPTldPSJUaW1lIix0W3QuVGltZXN0YW1wPTEwXT0iVGltZXN0YW1wIix0W3QuSW50ZXJ2YWw9MTFdPSJJbnRlcnZhbCIsdFt0Lkxpc3Q9MTJdPSJMaXN0Iix0W3QuU3RydWN0PTEzXT0iU3RydWN0Iix0W3QuVW5pb249MTRdPSJVbmlvbiIsdFt0LkZpeGVkU2l6ZUJpbmFyeT0xNV09IkZpeGVkU2l6ZUJpbmFyeSIsdFt0LkZpeGVkU2l6ZUxpc3Q9MTZdPSJGaXhlZFNpemVMaXN0Iix0W3QuTWFwPTE3XT0iTWFwIix0W3QuRHVyYXRpb249MThdPSJEdXJhdGlvbiIsdFt0LkxhcmdlQmluYXJ5PTE5XT0iTGFyZ2VCaW5hcnkiLHRbdC5MYXJnZVV0Zjg9MjBdPSJMYXJnZVV0ZjgiLHRbdC5CaW5hcnlWaWV3PTIzXT0iQmluYXJ5VmlldyIsdFt0LlV0ZjhWaWV3PTI0XT0iVXRmOFZpZXciLHRbdC5EaWN0aW9uYXJ5PS0xXT0iRGljdGlvbmFyeSIsdFt0LkludDg9LTJdPSJJbnQ4Iix0W3QuSW50MTY9LTNdPSJJbnQxNiIsdFt0LkludDMyPS00XT0iSW50MzIiLHRbdC5JbnQ2ND0tNV09IkludDY0Iix0W3QuVWludDg9LTZdPSJVaW50OCIsdFt0LlVpbnQxNj0tN109IlVpbnQxNiIsdFt0LlVpbnQzMj0tOF09IlVpbnQzMiIsdFt0LlVpbnQ2ND0tOV09IlVpbnQ2NCIsdFt0LkZsb2F0MTY9LTEwXT0iRmxvYXQxNiIsdFt0LkZsb2F0MzI9LTExXT0iRmxvYXQzMiIsdFt0LkZsb2F0NjQ9LTEyXT0iRmxvYXQ2NCIsdFt0LkRhdGVEYXk9LTEzXT0iRGF0ZURheSIsdFt0LkRhdGVNaWxsaXNlY29uZD0tMTRdPSJEYXRlTWlsbGlzZWNvbmQiLHRbdC5UaW1lc3RhbXBTZWNvbmQ9LTE1XT0iVGltZXN0YW1wU2Vjb25kIix0W3QuVGltZXN0YW1wTWlsbGlzZWNvbmQ9LTE2XT0iVGltZXN0YW1wTWlsbGlzZWNvbmQiLHRbdC5UaW1lc3RhbXBNaWNyb3NlY29uZD0tMTddPSJUaW1lc3RhbXBNaWNyb3NlY29uZCIsdFt0LlRpbWVzdGFtcE5hbm9zZWNvbmQ9LTE4XT0iVGltZXN0YW1wTmFub3NlY29uZCIsdFt0LlRpbWVTZWNvbmQ9LTE5XT0iVGltZVNlY29uZCIsdFt0LlRpbWVNaWxsaXNlY29uZD0tMjBdPSJUaW1lTWlsbGlzZWNvbmQiLHRbdC5UaW1lTWljcm9zZWNvbmQ9LTIxXT0iVGltZU1pY3Jvc2Vjb25kIix0W3QuVGltZU5hbm9zZWNvbmQ9LTIyXT0iVGltZU5hbm9zZWNvbmQiLHRbdC5EZW5zZVVuaW9uPS0yM109IkRlbnNlVW5pb24iLHRbdC5TcGFyc2VVbmlvbj0tMjRdPSJTcGFyc2VVbmlvbiIsdFt0LkludGVydmFsRGF5VGltZT0tMjVdPSJJbnRlcnZhbERheVRpbWUiLHRbdC5JbnRlcnZhbFllYXJNb250aD0tMjZdPSJJbnRlcnZhbFllYXJNb250aCIsdFt0LkR1cmF0aW9uU2Vjb25kPS0yN109IkR1cmF0aW9uU2Vjb25kIix0W3QuRHVyYXRpb25NaWxsaXNlY29uZD0tMjhdPSJEdXJhdGlvbk1pbGxpc2Vjb25kIix0W3QuRHVyYXRpb25NaWNyb3NlY29uZD0tMjldPSJEdXJhdGlvbk1pY3Jvc2Vjb25kIix0W3QuRHVyYXRpb25OYW5vc2Vjb25kPS0zMF09IkR1cmF0aW9uTmFub3NlY29uZCIsdFt0LkludGVydmFsTW9udGhEYXlOYW5vPS0zMV09IkludGVydmFsTW9udGhEYXlOYW5vIn0pKF98fChfPXt9KSk7KGZ1bmN0aW9uKHQpe3RbdC5PRkZTRVQ9MF09Ik9GRlNFVCIsdFt0LkRBVEE9MV09IkRBVEEiLHRbdC5WQUxJRElUWT0yXT0iVkFMSURJVFkiLHRbdC5UWVBFPTNdPSJUWVBFIn0pKFpyfHwoWnI9e30pKX0pO3ZhciBCbT17fTtaZShCbSx7dmFsdWVUb1N0cmluZzooKT0+Qml9KTtmdW5jdGlvbiBCaSh0KXtpZih0PT09bnVsbClyZXR1cm4ibnVsbCI7aWYodD09PXZvaWQgMClyZXR1cm4idW5kZWZpbmVkIjtzd2l0Y2godHlwZW9mIHQpe2Nhc2UibnVtYmVyIjpyZXR1cm5gJHt0fWA7Y2FzZSJiaWdpbnQiOnJldHVybmAke3R9YDtjYXNlInN0cmluZyI6cmV0dXJuYCIke3R9ImB9aWYodHlwZW9mIHRbU3ltYm9sLnRvUHJpbWl0aXZlXT09PSJmdW5jdGlvbiIpcmV0dXJuIHRbU3ltYm9sLnRvUHJpbWl0aXZlXSgic3RyaW5nIik7aWYoQXJyYXlCdWZmZXIuaXNWaWV3KHQpKXtpZih0IGluc3RhbmNlb2YgQmlnSW50NjRBcnJheXx8dCBpbnN0YW5jZW9mIEJpZ1VpbnQ2NEFycmF5KXJldHVybmBbJHtbLi4udF0ubWFwKChlKT0+QmkoZSkpfV1gO3JldHVybmBbJHt0fV1gfXJldHVybiBBcnJheUJ1ZmZlci5pc1ZpZXcodCk/YFske3R9XWA6SlNPTi5zdHJpbmdpZnkodCwoZSxyKT0+dHlwZW9mIHI9PT0iYmlnaW50Ij9gJHtyfWA6cil9ZnVuY3Rpb24gUHQodCl7aWYodHlwZW9mIHQ9PT0iYmlnaW50IiYmKHQ8TnVtYmVyLk1JTl9TQUZFX0lOVEVHRVJ8fHQ+TnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIpKXRocm93IFR5cGVFcnJvcihgJHt0fSBpcyBub3Qgc2FmZSB0byBjb252ZXJ0IHRvIGEgbnVtYmVyLmApO3JldHVybiBOdW1iZXIodCl9ZnVuY3Rpb24gU20odCxlKXtyZXR1cm4gUHQodC9lKStQdCh0JWUpL1B0KGUpfXZhciB4bT17fTtaZSh4bSx7Qk46KCk9PkxsLGJpZ051bVRvQmlnSW50OigpPT5XYixiaWdOdW1Ub051bWJlcjooKT0+RG0sYmlnTnVtVG9TdHJpbmc6KCk9PnVjLGlzQXJyb3dCaWdOdW1TeW1ib2w6KCk9PnFifSk7ZnVuY3Rpb24gU2kodCwuLi5lKXtpZihlLmxlbmd0aD09PTApcmV0dXJuIE9iamVjdC5zZXRQcm90b3R5cGVPZih3dCh0aGlzLlR5cGVkQXJyYXksdCksdGhpcy5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpO3JldHVybiBPYmplY3Quc2V0UHJvdG90eXBlT2YobmV3IHRoaXMuVHlwZWRBcnJheSh0LC4uLmUpLHRoaXMuY29uc3RydWN0b3IucHJvdG90eXBlKX1mdW5jdGlvbiBjYyguLi50KXtyZXR1cm4gU2kuYXBwbHkodGhpcyx0KX1mdW5jdGlvbiBsYyguLi50KXtyZXR1cm4gU2kuYXBwbHkodGhpcyx0KX1mdW5jdGlvbiBNbCguLi50KXtyZXR1cm4gU2kuYXBwbHkodGhpcyx0KX1mdW5jdGlvbiBEbSh0LGUpe2xldHtidWZmZXI6cixieXRlT2Zmc2V0Om4sYnl0ZUxlbmd0aDppLHNpZ25lZDpzfT10LG89bmV3IEJpZ1VpbnQ2NEFycmF5KHIsbixpLzgpLGE9cyYmby5hdCgtMSkmQmlnSW50KDEpPDxCaWdJbnQoNjMpLGw9QmlnSW50KDApLHU9MDtpZihhKXtmb3IobGV0IGYgb2YgbylsfD0oZl5JeCkqKEJpZ0ludCgxKTw8QmlnSW50KDY0KnUrKykpO2wqPUJpZ0ludCgtMSksbC09QmlnSW50KDEpfWVsc2UgZm9yKGxldCBmIG9mIG8pbHw9ZiooQmlnSW50KDEpPDxCaWdJbnQoNjQqdSsrKSk7aWYodHlwZW9mIGU9PT0ibnVtYmVyIiYmZT4wKXtsZXQgZj1CaWdJbnQoIjEiLnBhZEVuZChlKzEsIjAiKSkscD1sL2YsZz1hPy0obCVmKTpsJWYsdj1QdChwKSxJPWAke2d9YC5wYWRTdGFydChlLCIwIik7cmV0dXJuK2Ake2EmJnY9PT0wPyItIjoiIn0ke3Z9LiR7SX1gfXJldHVybiBQdChsKX1mdW5jdGlvbiB1Yyh0KXtpZih0LmJ5dGVMZW5ndGg9PT04KXJldHVybmAke25ldyB0LkJpZ0ludEFycmF5KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCwxKVswXX1gO2lmKCF0LnNpZ25lZClyZXR1cm4gQW0odCk7bGV0IGU9bmV3IFVpbnQxNkFycmF5KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCx0LmJ5dGVMZW5ndGgvMik7aWYobmV3IEludDE2QXJyYXkoW2UuYXQoLTEpXSlbMF0+PTApcmV0dXJuIEFtKHQpO2U9ZS5zbGljZSgpO2xldCBuPTE7Zm9yKGxldCBzPTA7czxlLmxlbmd0aDtzKyspe2xldCBvPWVbc10sYT1+bytuO2Vbc109YSxuJj1vPT09MD8xOjB9cmV0dXJuYC0ke0FtKGUpfWB9ZnVuY3Rpb24gV2IodCl7aWYodC5ieXRlTGVuZ3RoPT09OClyZXR1cm4gbmV3IHQuQmlnSW50QXJyYXkodC5idWZmZXIsdC5ieXRlT2Zmc2V0LDEpWzBdO2Vsc2UgcmV0dXJuIHVjKHQpfWZ1bmN0aW9uIEFtKHQpe2xldCBlPSIiLHI9bmV3IFVpbnQzMkFycmF5KDIpLG49bmV3IFVpbnQxNkFycmF5KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCx0LmJ5dGVMZW5ndGgvMiksaT1uZXcgVWludDMyQXJyYXkoKG49bmV3IFVpbnQxNkFycmF5KG4pLnJldmVyc2UoKSkuYnVmZmVyKSxzPS0xLG89bi5sZW5ndGgtMTtkb3tmb3IoclswXT1uW3M9MF07czxvOyluW3MrK109clsxXT1yWzBdLzEwLHJbMF09KHJbMF0tclsxXSoxMDw8MTYpK25bc107bltzXT1yWzFdPXJbMF0vMTAsclswXT1yWzBdLXJbMV0qMTAsZT1gJHtyWzBdfSR7ZX1gfXdoaWxlKGlbMF18fGlbMV18fGlbMl18fGlbM10pO3JldHVybiBlIT09bnVsbCYmZSE9PXZvaWQgMD9lOiIwIn1jbGFzcyBMbHtzdGF0aWMgbmV3KHQsZSl7c3dpdGNoKGUpe2Nhc2UhMDpyZXR1cm4gbmV3IGNjKHQpO2Nhc2UhMTpyZXR1cm4gbmV3IGxjKHQpfXN3aXRjaCh0LmNvbnN0cnVjdG9yKXtjYXNlIEludDhBcnJheTpjYXNlIEludDE2QXJyYXk6Y2FzZSBJbnQzMkFycmF5OmNhc2UgQmlnSW50NjRBcnJheTpyZXR1cm4gbmV3IGNjKHQpfWlmKHQuYnl0ZUxlbmd0aD09PTE2KXJldHVybiBuZXcgTWwodCk7cmV0dXJuIG5ldyBsYyh0KX1zdGF0aWMgc2lnbmVkKHQpe3JldHVybiBuZXcgY2ModCl9c3RhdGljIHVuc2lnbmVkKHQpe3JldHVybiBuZXcgbGModCl9c3RhdGljIGRlY2ltYWwodCl7cmV0dXJuIG5ldyBNbCh0KX1jb25zdHJ1Y3Rvcih0LGUpe3JldHVybiBMbC5uZXcodCxlKX19dmFyIHFiLHZ4LEl4O3ZhciBUbT1tKCgpPT57amUoKTtxYj1TeW1ib2wuZm9yKCJpc0Fycm93QmlnTnVtIik7U2kucHJvdG90eXBlW3FiXT0hMDtTaS5wcm90b3R5cGUudG9KU09OPWZ1bmN0aW9uKCl7cmV0dXJuYCIke3VjKHRoaXMpfSJgfTtTaS5wcm90b3R5cGUudmFsdWVPZj1mdW5jdGlvbih0KXtyZXR1cm4gRG0odGhpcyx0KX07U2kucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuIHVjKHRoaXMpfTtTaS5wcm90b3R5cGVbU3ltYm9sLnRvUHJpbWl0aXZlXT1mdW5jdGlvbih0PSJkZWZhdWx0Iil7c3dpdGNoKHQpe2Nhc2UibnVtYmVyIjpyZXR1cm4gRG0odGhpcyk7Y2FzZSJzdHJpbmciOnJldHVybiB1Yyh0aGlzKTtjYXNlImRlZmF1bHQiOnJldHVybiBXYih0aGlzKX1yZXR1cm4gdWModGhpcyl9O09iamVjdC5zZXRQcm90b3R5cGVPZihjYy5wcm90b3R5cGUsT2JqZWN0LmNyZWF0ZShJbnQzMkFycmF5LnByb3RvdHlwZSkpO09iamVjdC5zZXRQcm90b3R5cGVPZihsYy5wcm90b3R5cGUsT2JqZWN0LmNyZWF0ZShVaW50MzJBcnJheS5wcm90b3R5cGUpKTtPYmplY3Quc2V0UHJvdG90eXBlT2YoTWwucHJvdG90eXBlLE9iamVjdC5jcmVhdGUoVWludDMyQXJyYXkucHJvdG90eXBlKSk7T2JqZWN0LmFzc2lnbihjYy5wcm90b3R5cGUsU2kucHJvdG90eXBlLHtjb25zdHJ1Y3RvcjpjYyxzaWduZWQ6ITAsVHlwZWRBcnJheTpJbnQzMkFycmF5LEJpZ0ludEFycmF5OkJpZ0ludDY0QXJyYXl9KTtPYmplY3QuYXNzaWduKGxjLnByb3RvdHlwZSxTaS5wcm90b3R5cGUse2NvbnN0cnVjdG9yOmxjLHNpZ25lZDohMSxUeXBlZEFycmF5OlVpbnQzMkFycmF5LEJpZ0ludEFycmF5OkJpZ1VpbnQ2NEFycmF5fSk7T2JqZWN0LmFzc2lnbihNbC5wcm90b3R5cGUsU2kucHJvdG90eXBlLHtjb25zdHJ1Y3RvcjpNbCxzaWduZWQ6ITAsVHlwZWRBcnJheTpVaW50MzJBcnJheSxCaWdJbnRBcnJheTpCaWdVaW50NjRBcnJheX0pO3Z4PUJpZ0ludCg0Mjk0OTY3Mjk2KSpCaWdJbnQoNDI5NDk2NzI5NiksSXg9dngtQmlnSW50KDEpfSk7Y2xhc3MgQntzdGF0aWMgaXNEYXRhVHlwZSh0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnRbeXddKT09PSEwfXN0YXRpYyBpc051bGwodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT1fLk51bGx9c3RhdGljIGlzSW50KHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC50eXBlSWQpPT09Xy5JbnR9c3RhdGljIGlzRmxvYXQodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT1fLkZsb2F0fXN0YXRpYyBpc0JpbmFyeSh0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnQudHlwZUlkKT09PV8uQmluYXJ5fXN0YXRpYyBpc0JpbmFyeVZpZXcodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT1fLkJpbmFyeVZpZXd9c3RhdGljIGlzTGFyZ2VCaW5hcnkodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT1fLkxhcmdlQmluYXJ5fXN0YXRpYyBpc1V0ZjgodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT1fLlV0Zjh9c3RhdGljIGlzVXRmOFZpZXcodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT1fLlV0ZjhWaWV3fXN0YXRpYyBpc0xhcmdlVXRmOCh0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnQudHlwZUlkKT09PV8uTGFyZ2VVdGY4fXN0YXRpYyBpc0Jvb2wodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT1fLkJvb2x9c3RhdGljIGlzRGVjaW1hbCh0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnQudHlwZUlkKT09PV8uRGVjaW1hbH1zdGF0aWMgaXNEYXRlKHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC50eXBlSWQpPT09Xy5EYXRlfXN0YXRpYyBpc1RpbWUodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT1fLlRpbWV9c3RhdGljIGlzVGltZXN0YW1wKHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC50eXBlSWQpPT09Xy5UaW1lc3RhbXB9c3RhdGljIGlzSW50ZXJ2YWwodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT1fLkludGVydmFsfXN0YXRpYyBpc0R1cmF0aW9uKHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC50eXBlSWQpPT09Xy5EdXJhdGlvbn1zdGF0aWMgaXNMaXN0KHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC50eXBlSWQpPT09Xy5MaXN0fXN0YXRpYyBpc1N0cnVjdCh0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnQudHlwZUlkKT09PV8uU3RydWN0fXN0YXRpYyBpc1VuaW9uKHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC50eXBlSWQpPT09Xy5Vbmlvbn1zdGF0aWMgaXNGaXhlZFNpemVCaW5hcnkodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT1fLkZpeGVkU2l6ZUJpbmFyeX1zdGF0aWMgaXNGaXhlZFNpemVMaXN0KHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC50eXBlSWQpPT09Xy5GaXhlZFNpemVMaXN0fXN0YXRpYyBpc01hcCh0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnQudHlwZUlkKT09PV8uTWFwfXN0YXRpYyBpc0RpY3Rpb25hcnkodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT1fLkRpY3Rpb25hcnl9c3RhdGljIGlzRGVuc2VVbmlvbih0KXtyZXR1cm4gQi5pc1VuaW9uKHQpJiZ0Lm1vZGU9PT1MdC5EZW5zZX1zdGF0aWMgaXNTcGFyc2VVbmlvbih0KXtyZXR1cm4gQi5pc1VuaW9uKHQpJiZ0Lm1vZGU9PT1MdC5TcGFyc2V9Y29uc3RydWN0b3IodCl7dGhpcy50eXBlSWQ9dH19ZnVuY3Rpb24gQm4odCl7bGV0IGU9dDtzd2l0Y2godC50eXBlSWQpe2Nhc2UgXy5EZWNpbWFsOnJldHVybiB0LmJpdFdpZHRoLzMyO2Nhc2UgXy5JbnRlcnZhbDp7aWYoZS51bml0PT09anQuTU9OVEhfREFZX05BTk8pcmV0dXJuIDQ7cmV0dXJuIDErZS51bml0fWNhc2UgXy5CaW5hcnlWaWV3OmNhc2UgXy5VdGY4VmlldzpyZXR1cm4gMTY7Y2FzZSBfLkZpeGVkU2l6ZUxpc3Q6cmV0dXJuIGUubGlzdFNpemU7Y2FzZSBfLkZpeGVkU2l6ZUJpbmFyeTpyZXR1cm4gZS5ieXRlV2lkdGg7ZGVmYXVsdDpyZXR1cm4gMX19dmFyIEhiLFliLEtiLEdiLEpiLFhiLFpiLFFiLHR3LGV3LHJ3LG53LGl3LHN3LG93LGF3LGN3LGx3LHV3LGZ3LGR3LGh3LHB3LG13LHl3LHdlLCRlLG1vLHlvLEJyLEluLF9vLGdvLGJvLExpLEduLGZjLHdvLG9zLEFpLF90LERpLElyLGduLHhpLFVlLFRpLEVpLE9pLEpuLFVsLE5pLEZpLExyLEV0LGJuLFJsLHZvLE1pLHduLHZuLEJ4LGZyO3ZhciBpZT1tKCgpPT57TGUoKTt5dz1TeW1ib2wuZm9yKCJhcGFjaGUtYXJyb3cvRGF0YVR5cGUiKTtIYj1TeW1ib2wudG9TdHJpbmdUYWc7QltIYl09KCh0KT0+KHQuY2hpbGRyZW49bnVsbCx0LkFycmF5VHlwZT1BcnJheSx0Lk9mZnNldEFycmF5VHlwZT1JbnQzMkFycmF5LHRbeXddPSEwLHRbU3ltYm9sLnRvU3RyaW5nVGFnXT0iRGF0YVR5cGUiKSkoQi5wcm90b3R5cGUpO3dlPWNsYXNzIHdlIGV4dGVuZHMgQntjb25zdHJ1Y3Rvcigpe3N1cGVyKF8uTnVsbCl9dG9TdHJpbmcoKXtyZXR1cm4iTnVsbCJ9fTtZYj1TeW1ib2wudG9TdHJpbmdUYWc7d2VbWWJdPSgodCk9PnRbU3ltYm9sLnRvU3RyaW5nVGFnXT0iTnVsbCIpKHdlLnByb3RvdHlwZSk7JGU9Y2xhc3MgJGUgZXh0ZW5kcyBCe2NvbnN0cnVjdG9yKHQsZSl7c3VwZXIoXy5JbnQpO3RoaXMuaXNTaWduZWQ9dCx0aGlzLmJpdFdpZHRoPWV9Z2V0IEFycmF5VHlwZSgpe3N3aXRjaCh0aGlzLmJpdFdpZHRoKXtjYXNlIDg6cmV0dXJuIHRoaXMuaXNTaWduZWQ/SW50OEFycmF5OlVpbnQ4QXJyYXk7Y2FzZSAxNjpyZXR1cm4gdGhpcy5pc1NpZ25lZD9JbnQxNkFycmF5OlVpbnQxNkFycmF5O2Nhc2UgMzI6cmV0dXJuIHRoaXMuaXNTaWduZWQ/SW50MzJBcnJheTpVaW50MzJBcnJheTtjYXNlIDY0OnJldHVybiB0aGlzLmlzU2lnbmVkP0JpZ0ludDY0QXJyYXk6QmlnVWludDY0QXJyYXl9dGhyb3cgRXJyb3IoYFVucmVjb2duaXplZCAke3RoaXNbU3ltYm9sLnRvU3RyaW5nVGFnXX0gdHlwZWApfXRvU3RyaW5nKCl7cmV0dXJuYCR7dGhpcy5pc1NpZ25lZD8iSSI6IlVpIn1udCR7dGhpcy5iaXRXaWR0aH1gfX07S2I9U3ltYm9sLnRvU3RyaW5nVGFnOyRlW0tiXT0oKHQpPT4odC5pc1NpZ25lZD1udWxsLHQuYml0V2lkdGg9bnVsbCx0W1N5bWJvbC50b1N0cmluZ1RhZ109IkludCIpKSgkZS5wcm90b3R5cGUpO21vPWNsYXNzIG1vIGV4dGVuZHMgJGV7Y29uc3RydWN0b3IoKXtzdXBlcighMCw4KX1nZXQgQXJyYXlUeXBlKCl7cmV0dXJuIEludDhBcnJheX19O3lvPWNsYXNzIHlvIGV4dGVuZHMgJGV7Y29uc3RydWN0b3IoKXtzdXBlcighMCwxNil9Z2V0IEFycmF5VHlwZSgpe3JldHVybiBJbnQxNkFycmF5fX07QnI9Y2xhc3MgQnIgZXh0ZW5kcyAkZXtjb25zdHJ1Y3Rvcigpe3N1cGVyKCEwLDMyKX1nZXQgQXJyYXlUeXBlKCl7cmV0dXJuIEludDMyQXJyYXl9fTtJbj1jbGFzcyBJbiBleHRlbmRzICRle2NvbnN0cnVjdG9yKCl7c3VwZXIoITAsNjQpfWdldCBBcnJheVR5cGUoKXtyZXR1cm4gQmlnSW50NjRBcnJheX19O19vPWNsYXNzIF9vIGV4dGVuZHMgJGV7Y29uc3RydWN0b3IoKXtzdXBlcighMSw4KX1nZXQgQXJyYXlUeXBlKCl7cmV0dXJuIFVpbnQ4QXJyYXl9fTtnbz1jbGFzcyBnbyBleHRlbmRzICRle2NvbnN0cnVjdG9yKCl7c3VwZXIoITEsMTYpfWdldCBBcnJheVR5cGUoKXtyZXR1cm4gVWludDE2QXJyYXl9fTtibz1jbGFzcyBibyBleHRlbmRzICRle2NvbnN0cnVjdG9yKCl7c3VwZXIoITEsMzIpfWdldCBBcnJheVR5cGUoKXtyZXR1cm4gVWludDMyQXJyYXl9fTtMaT1jbGFzcyBMaSBleHRlbmRzICRle2NvbnN0cnVjdG9yKCl7c3VwZXIoITEsNjQpfWdldCBBcnJheVR5cGUoKXtyZXR1cm4gQmlnVWludDY0QXJyYXl9fTtPYmplY3QuZGVmaW5lUHJvcGVydHkobW8ucHJvdG90eXBlLCJBcnJheVR5cGUiLHt2YWx1ZTpJbnQ4QXJyYXl9KTtPYmplY3QuZGVmaW5lUHJvcGVydHkoeW8ucHJvdG90eXBlLCJBcnJheVR5cGUiLHt2YWx1ZTpJbnQxNkFycmF5fSk7T2JqZWN0LmRlZmluZVByb3BlcnR5KEJyLnByb3RvdHlwZSwiQXJyYXlUeXBlIix7dmFsdWU6SW50MzJBcnJheX0pO09iamVjdC5kZWZpbmVQcm9wZXJ0eShJbi5wcm90b3R5cGUsIkFycmF5VHlwZSIse3ZhbHVlOkJpZ0ludDY0QXJyYXl9KTtPYmplY3QuZGVmaW5lUHJvcGVydHkoX28ucHJvdG90eXBlLCJBcnJheVR5cGUiLHt2YWx1ZTpVaW50OEFycmF5fSk7T2JqZWN0LmRlZmluZVByb3BlcnR5KGdvLnByb3RvdHlwZSwiQXJyYXlUeXBlIix7dmFsdWU6VWludDE2QXJyYXl9KTtPYmplY3QuZGVmaW5lUHJvcGVydHkoYm8ucHJvdG90eXBlLCJBcnJheVR5cGUiLHt2YWx1ZTpVaW50MzJBcnJheX0pO09iamVjdC5kZWZpbmVQcm9wZXJ0eShMaS5wcm90b3R5cGUsIkFycmF5VHlwZSIse3ZhbHVlOkJpZ1VpbnQ2NEFycmF5fSk7R249Y2xhc3MgR24gZXh0ZW5kcyBCe2NvbnN0cnVjdG9yKHQpe3N1cGVyKF8uRmxvYXQpO3RoaXMucHJlY2lzaW9uPXR9Z2V0IEFycmF5VHlwZSgpe3N3aXRjaCh0aGlzLnByZWNpc2lvbil7Y2FzZSBadC5IQUxGOnJldHVybiBVaW50MTZBcnJheTtjYXNlIFp0LlNJTkdMRTpyZXR1cm4gRmxvYXQzMkFycmF5O2Nhc2UgWnQuRE9VQkxFOnJldHVybiBGbG9hdDY0QXJyYXl9dGhyb3cgRXJyb3IoYFVucmVjb2duaXplZCAke3RoaXNbU3ltYm9sLnRvU3RyaW5nVGFnXX0gdHlwZWApfXRvU3RyaW5nKCl7cmV0dXJuYEZsb2F0JHt0aGlzLnByZWNpc2lvbjw8NXx8MTZ9YH19O0diPVN5bWJvbC50b1N0cmluZ1RhZztHbltHYl09KCh0KT0+KHQucHJlY2lzaW9uPW51bGwsdFtTeW1ib2wudG9TdHJpbmdUYWddPSJGbG9hdCIpKShHbi5wcm90b3R5cGUpO2ZjPWNsYXNzIGZjIGV4dGVuZHMgR257Y29uc3RydWN0b3IoKXtzdXBlcihadC5IQUxGKX19O3dvPWNsYXNzIHdvIGV4dGVuZHMgR257Y29uc3RydWN0b3IoKXtzdXBlcihadC5TSU5HTEUpfX07b3M9Y2xhc3Mgb3MgZXh0ZW5kcyBHbntjb25zdHJ1Y3Rvcigpe3N1cGVyKFp0LkRPVUJMRSl9fTtPYmplY3QuZGVmaW5lUHJvcGVydHkoZmMucHJvdG90eXBlLCJBcnJheVR5cGUiLHt2YWx1ZTpVaW50MTZBcnJheX0pO09iamVjdC5kZWZpbmVQcm9wZXJ0eSh3by5wcm90b3R5cGUsIkFycmF5VHlwZSIse3ZhbHVlOkZsb2F0MzJBcnJheX0pO09iamVjdC5kZWZpbmVQcm9wZXJ0eShvcy5wcm90b3R5cGUsIkFycmF5VHlwZSIse3ZhbHVlOkZsb2F0NjRBcnJheX0pO0FpPWNsYXNzIEFpIGV4dGVuZHMgQntjb25zdHJ1Y3Rvcigpe3N1cGVyKF8uQmluYXJ5KX10b1N0cmluZygpe3JldHVybiJCaW5hcnkifX07SmI9U3ltYm9sLnRvU3RyaW5nVGFnO0FpW0piXT0oKHQpPT4odC5BcnJheVR5cGU9VWludDhBcnJheSx0W1N5bWJvbC50b1N0cmluZ1RhZ109IkJpbmFyeSIpKShBaS5wcm90b3R5cGUpO190PWNsYXNzIF90IGV4dGVuZHMgQntjb25zdHJ1Y3Rvcigpe3N1cGVyKF8uQmluYXJ5Vmlldyl9dG9TdHJpbmcoKXtyZXR1cm4iQmluYXJ5VmlldyJ9fTtYYj1TeW1ib2wudG9TdHJpbmdUYWc7X3QuRUxFTUVOVF9XSURUSD0xNjtfdC5JTkxJTkVfQ0FQQUNJVFk9MTI7X3QuTEVOR1RIX09GRlNFVD0wO190LklOTElORV9PRkZTRVQ9NDtfdC5CVUZGRVJfSU5ERVhfT0ZGU0VUPTg7X3QuQlVGRkVSX09GRlNFVF9PRkZTRVQ9MTI7X3RbWGJdPSgodCk9Pih0LkFycmF5VHlwZT1VaW50OEFycmF5LHRbU3ltYm9sLnRvU3RyaW5nVGFnXT0iQmluYXJ5VmlldyIpKShfdC5wcm90b3R5cGUpO0RpPWNsYXNzIERpIGV4dGVuZHMgQntjb25zdHJ1Y3Rvcigpe3N1cGVyKF8uTGFyZ2VCaW5hcnkpfXRvU3RyaW5nKCl7cmV0dXJuIkxhcmdlQmluYXJ5In19O1piPVN5bWJvbC50b1N0cmluZ1RhZztEaVtaYl09KCh0KT0+KHQuQXJyYXlUeXBlPVVpbnQ4QXJyYXksdC5PZmZzZXRBcnJheVR5cGU9QmlnSW50NjRBcnJheSx0W1N5bWJvbC50b1N0cmluZ1RhZ109IkxhcmdlQmluYXJ5IikpKERpLnByb3RvdHlwZSk7SXI9Y2xhc3MgSXIgZXh0ZW5kcyBCe2NvbnN0cnVjdG9yKCl7c3VwZXIoXy5VdGY4KX10b1N0cmluZygpe3JldHVybiJVdGY4In19O1FiPVN5bWJvbC50b1N0cmluZ1RhZztJcltRYl09KCh0KT0+KHQuQXJyYXlUeXBlPVVpbnQ4QXJyYXksdFtTeW1ib2wudG9TdHJpbmdUYWddPSJVdGY4IikpKElyLnByb3RvdHlwZSk7Z249Y2xhc3MgZ24gZXh0ZW5kcyBCe2NvbnN0cnVjdG9yKCl7c3VwZXIoXy5VdGY4Vmlldyl9dG9TdHJpbmcoKXtyZXR1cm4iVXRmOFZpZXcifX07dHc9U3ltYm9sLnRvU3RyaW5nVGFnO2duLkVMRU1FTlRfV0lEVEg9X3QuRUxFTUVOVF9XSURUSDtnbi5JTkxJTkVfQ0FQQUNJVFk9X3QuSU5MSU5FX0NBUEFDSVRZO2duW3R3XT0oKHQpPT4odC5BcnJheVR5cGU9VWludDhBcnJheSx0W1N5bWJvbC50b1N0cmluZ1RhZ109IlV0ZjhWaWV3IikpKGduLnByb3RvdHlwZSk7eGk9Y2xhc3MgeGkgZXh0ZW5kcyBCe2NvbnN0cnVjdG9yKCl7c3VwZXIoXy5MYXJnZVV0ZjgpfXRvU3RyaW5nKCl7cmV0dXJuIkxhcmdlVXRmOCJ9fTtldz1TeW1ib2wudG9TdHJpbmdUYWc7eGlbZXddPSgodCk9Pih0LkFycmF5VHlwZT1VaW50OEFycmF5LHQuT2Zmc2V0QXJyYXlUeXBlPUJpZ0ludDY0QXJyYXksdFtTeW1ib2wudG9TdHJpbmdUYWddPSJMYXJnZVV0ZjgiKSkoeGkucHJvdG90eXBlKTtVZT1jbGFzcyBVZSBleHRlbmRzIEJ7Y29uc3RydWN0b3IoKXtzdXBlcihfLkJvb2wpfXRvU3RyaW5nKCl7cmV0dXJuIkJvb2wifX07cnc9U3ltYm9sLnRvU3RyaW5nVGFnO1VlW3J3XT0oKHQpPT4odC5BcnJheVR5cGU9VWludDhBcnJheSx0W1N5bWJvbC50b1N0cmluZ1RhZ109IkJvb2wiKSkoVWUucHJvdG90eXBlKTtUaT1jbGFzcyBUaSBleHRlbmRzIEJ7Y29uc3RydWN0b3IodCxlLHI9MTI4KXtzdXBlcihfLkRlY2ltYWwpO3RoaXMuc2NhbGU9dCx0aGlzLnByZWNpc2lvbj1lLHRoaXMuYml0V2lkdGg9cn10b1N0cmluZygpe3JldHVybmBEZWNpbWFsWyR7dGhpcy5wcmVjaXNpb259ZSR7dGhpcy5zY2FsZT4wPyIrIjoiIn0ke3RoaXMuc2NhbGV9XWB9fTtudz1TeW1ib2wudG9TdHJpbmdUYWc7VGlbbnddPSgodCk9Pih0LnNjYWxlPW51bGwsdC5wcmVjaXNpb249bnVsbCx0LkFycmF5VHlwZT1VaW50MzJBcnJheSx0W1N5bWJvbC50b1N0cmluZ1RhZ109IkRlY2ltYWwiKSkoVGkucHJvdG90eXBlKTtFaT1jbGFzcyBFaSBleHRlbmRzIEJ7Y29uc3RydWN0b3IodCl7c3VwZXIoXy5EYXRlKTt0aGlzLnVuaXQ9dH10b1N0cmluZygpe3JldHVybmBEYXRlJHsodGhpcy51bml0KzEpKjMyfTwke3F0W3RoaXMudW5pdF19PmB9Z2V0IEFycmF5VHlwZSgpe3JldHVybiB0aGlzLnVuaXQ9PT1xdC5EQVk/SW50MzJBcnJheTpCaWdJbnQ2NEFycmF5fX07aXc9U3ltYm9sLnRvU3RyaW5nVGFnO0VpW2l3XT0oKHQpPT4odC51bml0PW51bGwsdFtTeW1ib2wudG9TdHJpbmdUYWddPSJEYXRlIikpKEVpLnByb3RvdHlwZSk7T2k9Y2xhc3MgT2kgZXh0ZW5kcyBCe2NvbnN0cnVjdG9yKHQsZSl7c3VwZXIoXy5UaW1lKTt0aGlzLnVuaXQ9dCx0aGlzLmJpdFdpZHRoPWV9dG9TdHJpbmcoKXtyZXR1cm5gVGltZSR7dGhpcy5iaXRXaWR0aH08JHtUW3RoaXMudW5pdF19PmB9Z2V0IEFycmF5VHlwZSgpe3N3aXRjaCh0aGlzLmJpdFdpZHRoKXtjYXNlIDMyOnJldHVybiBJbnQzMkFycmF5O2Nhc2UgNjQ6cmV0dXJuIEJpZ0ludDY0QXJyYXl9dGhyb3cgRXJyb3IoYFVucmVjb2duaXplZCAke3RoaXNbU3ltYm9sLnRvU3RyaW5nVGFnXX0gdHlwZWApfX07c3c9U3ltYm9sLnRvU3RyaW5nVGFnO09pW3N3XT0oKHQpPT4odC51bml0PW51bGwsdC5iaXRXaWR0aD1udWxsLHRbU3ltYm9sLnRvU3RyaW5nVGFnXT0iVGltZSIpKShPaS5wcm90b3R5cGUpO0puPWNsYXNzIEpuIGV4dGVuZHMgQntjb25zdHJ1Y3Rvcih0LGUpe3N1cGVyKF8uVGltZXN0YW1wKTt0aGlzLnVuaXQ9dCx0aGlzLnRpbWV6b25lPWV9dG9TdHJpbmcoKXtyZXR1cm5gVGltZXN0YW1wPCR7VFt0aGlzLnVuaXRdfSR7dGhpcy50aW1lem9uZT9gLCAke3RoaXMudGltZXpvbmV9YDoiIn0+YH19O293PVN5bWJvbC50b1N0cmluZ1RhZztKbltvd109KCh0KT0+KHQudW5pdD1udWxsLHQudGltZXpvbmU9bnVsbCx0LkFycmF5VHlwZT1CaWdJbnQ2NEFycmF5LHRbU3ltYm9sLnRvU3RyaW5nVGFnXT0iVGltZXN0YW1wIikpKEpuLnByb3RvdHlwZSk7VWw9Y2xhc3MgVWwgZXh0ZW5kcyBKbntjb25zdHJ1Y3Rvcih0KXtzdXBlcihULk1JTExJU0VDT05ELHQpfX07Tmk9Y2xhc3MgTmkgZXh0ZW5kcyBCe2NvbnN0cnVjdG9yKHQpe3N1cGVyKF8uSW50ZXJ2YWwpO3RoaXMudW5pdD10fXRvU3RyaW5nKCl7cmV0dXJuYEludGVydmFsPCR7anRbdGhpcy51bml0XX0+YH19O2F3PVN5bWJvbC50b1N0cmluZ1RhZztOaVthd109KCh0KT0+KHQudW5pdD1udWxsLHQuQXJyYXlUeXBlPUludDMyQXJyYXksdFtTeW1ib2wudG9TdHJpbmdUYWddPSJJbnRlcnZhbCIpKShOaS5wcm90b3R5cGUpO0ZpPWNsYXNzIEZpIGV4dGVuZHMgQntjb25zdHJ1Y3Rvcih0KXtzdXBlcihfLkR1cmF0aW9uKTt0aGlzLnVuaXQ9dH10b1N0cmluZygpe3JldHVybmBEdXJhdGlvbjwke1RbdGhpcy51bml0XX0+YH19O2N3PVN5bWJvbC50b1N0cmluZ1RhZztGaVtjd109KCh0KT0+KHQudW5pdD1udWxsLHQuQXJyYXlUeXBlPUJpZ0ludDY0QXJyYXksdFtTeW1ib2wudG9TdHJpbmdUYWddPSJEdXJhdGlvbiIpKShGaS5wcm90b3R5cGUpO0xyPWNsYXNzIExyIGV4dGVuZHMgQntjb25zdHJ1Y3Rvcih0KXtzdXBlcihfLkxpc3QpO3RoaXMuY2hpbGRyZW49W3RdfXRvU3RyaW5nKCl7cmV0dXJuYExpc3Q8JHt0aGlzLnZhbHVlVHlwZX0+YH1nZXQgdmFsdWVUeXBlKCl7cmV0dXJuIHRoaXMuY2hpbGRyZW5bMF0udHlwZX1nZXQgdmFsdWVGaWVsZCgpe3JldHVybiB0aGlzLmNoaWxkcmVuWzBdfWdldCBBcnJheVR5cGUoKXtyZXR1cm4gdGhpcy52YWx1ZVR5cGUuQXJyYXlUeXBlfX07bHc9U3ltYm9sLnRvU3RyaW5nVGFnO0xyW2x3XT0oKHQpPT4odC5jaGlsZHJlbj1udWxsLHRbU3ltYm9sLnRvU3RyaW5nVGFnXT0iTGlzdCIpKShMci5wcm90b3R5cGUpO0V0PWNsYXNzIEV0IGV4dGVuZHMgQntjb25zdHJ1Y3Rvcih0KXtzdXBlcihfLlN0cnVjdCk7dGhpcy5jaGlsZHJlbj10fXRvU3RyaW5nKCl7cmV0dXJuYFN0cnVjdDx7JHt0aGlzLmNoaWxkcmVuLm1hcCgodCk9PmAke3QubmFtZX06JHt0LnR5cGV9YCkuam9pbigiLCAiKX19PmB9fTt1dz1TeW1ib2wudG9TdHJpbmdUYWc7RXRbdXddPSgodCk9Pih0LmNoaWxkcmVuPW51bGwsdFtTeW1ib2wudG9TdHJpbmdUYWddPSJTdHJ1Y3QiKSkoRXQucHJvdG90eXBlKTtibj1jbGFzcyBibiBleHRlbmRzIEJ7Y29uc3RydWN0b3IodCxlLHIpe3N1cGVyKF8uVW5pb24pO3RoaXMubW9kZT10LHRoaXMuY2hpbGRyZW49cix0aGlzLnR5cGVJZHM9ZT1JbnQzMkFycmF5LmZyb20oZSksdGhpcy50eXBlSWRUb0NoaWxkSW5kZXg9ZS5yZWR1Y2UoKG4saSxzKT0+KG5baV09cykmJm58fG4sT2JqZWN0LmNyZWF0ZShudWxsKSl9dG9TdHJpbmcoKXtyZXR1cm5gJHt0aGlzW1N5bWJvbC50b1N0cmluZ1RhZ119PCR7dGhpcy5jaGlsZHJlbi5tYXAoKHQpPT5gJHt0LnR5cGV9YCkuam9pbigiIHwgIil9PmB9fTtmdz1TeW1ib2wudG9TdHJpbmdUYWc7Ym5bZnddPSgodCk9Pih0Lm1vZGU9bnVsbCx0LnR5cGVJZHM9bnVsbCx0LmNoaWxkcmVuPW51bGwsdC50eXBlSWRUb0NoaWxkSW5kZXg9bnVsbCx0LkFycmF5VHlwZT1JbnQ4QXJyYXksdFtTeW1ib2wudG9TdHJpbmdUYWddPSJVbmlvbiIpKShibi5wcm90b3R5cGUpO1JsPWNsYXNzIFJsIGV4dGVuZHMgYm57Y29uc3RydWN0b3IodCxlKXtzdXBlcihMdC5EZW5zZSx0LGUpfX07dm89Y2xhc3Mgdm8gZXh0ZW5kcyBibntjb25zdHJ1Y3Rvcih0LGUpe3N1cGVyKEx0LlNwYXJzZSx0LGUpfX07TWk9Y2xhc3MgTWkgZXh0ZW5kcyBCe2NvbnN0cnVjdG9yKHQpe3N1cGVyKF8uRml4ZWRTaXplQmluYXJ5KTt0aGlzLmJ5dGVXaWR0aD10fXRvU3RyaW5nKCl7cmV0dXJuYEZpeGVkU2l6ZUJpbmFyeVske3RoaXMuYnl0ZVdpZHRofV1gfX07ZHc9U3ltYm9sLnRvU3RyaW5nVGFnO01pW2R3XT0oKHQpPT4odC5ieXRlV2lkdGg9bnVsbCx0LkFycmF5VHlwZT1VaW50OEFycmF5LHRbU3ltYm9sLnRvU3RyaW5nVGFnXT0iRml4ZWRTaXplQmluYXJ5IikpKE1pLnByb3RvdHlwZSk7d249Y2xhc3Mgd24gZXh0ZW5kcyBCe2NvbnN0cnVjdG9yKHQsZSl7c3VwZXIoXy5GaXhlZFNpemVMaXN0KTt0aGlzLmxpc3RTaXplPXQsdGhpcy5jaGlsZHJlbj1bZV19Z2V0IHZhbHVlVHlwZSgpe3JldHVybiB0aGlzLmNoaWxkcmVuWzBdLnR5cGV9Z2V0IHZhbHVlRmllbGQoKXtyZXR1cm4gdGhpcy5jaGlsZHJlblswXX1nZXQgQXJyYXlUeXBlKCl7cmV0dXJuIHRoaXMudmFsdWVUeXBlLkFycmF5VHlwZX10b1N0cmluZygpe3JldHVybmBGaXhlZFNpemVMaXN0WyR7dGhpcy5saXN0U2l6ZX1dPCR7dGhpcy52YWx1ZVR5cGV9PmB9fTtodz1TeW1ib2wudG9TdHJpbmdUYWc7d25baHddPSgodCk9Pih0LmNoaWxkcmVuPW51bGwsdC5saXN0U2l6ZT1udWxsLHRbU3ltYm9sLnRvU3RyaW5nVGFnXT0iRml4ZWRTaXplTGlzdCIpKSh3bi5wcm90b3R5cGUpO3ZuPWNsYXNzIHZuIGV4dGVuZHMgQntjb25zdHJ1Y3Rvcih0LGU9ITEpe3ZhciByLG4saTtzdXBlcihfLk1hcCk7aWYodGhpcy5jaGlsZHJlbj1bdF0sdGhpcy5rZXlzU29ydGVkPWUsdCl7aWYodC5uYW1lPSJlbnRyaWVzIiwocj10PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC50eXBlKT09PW51bGx8fHI9PT12b2lkIDA/dm9pZCAwOnIuY2hpbGRyZW4pe2xldCBzPShuPXQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGUpPT09bnVsbHx8bj09PXZvaWQgMD92b2lkIDA6bi5jaGlsZHJlblswXTtpZihzKXMubmFtZT0ia2V5IjtsZXQgbz0oaT10PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC50eXBlKT09PW51bGx8fGk9PT12b2lkIDA/dm9pZCAwOmkuY2hpbGRyZW5bMV07aWYobylvLm5hbWU9InZhbHVlIn19fWdldCBrZXlUeXBlKCl7cmV0dXJuIHRoaXMuY2hpbGRyZW5bMF0udHlwZS5jaGlsZHJlblswXS50eXBlfWdldCB2YWx1ZVR5cGUoKXtyZXR1cm4gdGhpcy5jaGlsZHJlblswXS50eXBlLmNoaWxkcmVuWzFdLnR5cGV9Z2V0IGNoaWxkVHlwZSgpe3JldHVybiB0aGlzLmNoaWxkcmVuWzBdLnR5cGV9dG9TdHJpbmcoKXtyZXR1cm5gTWFwPHske3RoaXMuY2hpbGRyZW5bMF0udHlwZS5jaGlsZHJlbi5tYXAoKHQpPT5gJHt0Lm5hbWV9OiR7dC50eXBlfWApLmpvaW4oIiwgIil9fT5gfX07cHc9U3ltYm9sLnRvU3RyaW5nVGFnO3ZuW3B3XT0oKHQpPT4odC5jaGlsZHJlbj1udWxsLHQua2V5c1NvcnRlZD1udWxsLHRbU3ltYm9sLnRvU3RyaW5nVGFnXT0iTWFwXyIpKSh2bi5wcm90b3R5cGUpO0J4PSgodCk9PigpPT4rK3QpKC0xKTtmcj1jbGFzcyBmciBleHRlbmRzIEJ7Y29uc3RydWN0b3IodCxlLHIsbil7c3VwZXIoXy5EaWN0aW9uYXJ5KTt0aGlzLmluZGljZXM9ZSx0aGlzLmRpY3Rpb25hcnk9dCx0aGlzLmlzT3JkZXJlZD1ufHwhMSx0aGlzLmlkPXI9PW51bGw/QngoKTpQdChyKX1nZXQgY2hpbGRyZW4oKXtyZXR1cm4gdGhpcy5kaWN0aW9uYXJ5LmNoaWxkcmVufWdldCB2YWx1ZVR5cGUoKXtyZXR1cm4gdGhpcy5kaWN0aW9uYXJ5fWdldCBBcnJheVR5cGUoKXtyZXR1cm4gdGhpcy5kaWN0aW9uYXJ5LkFycmF5VHlwZX10b1N0cmluZygpe3JldHVybmBEaWN0aW9uYXJ5PCR7dGhpcy5pbmRpY2VzfSwgJHt0aGlzLmRpY3Rpb25hcnl9PmB9fTttdz1TeW1ib2wudG9TdHJpbmdUYWc7ZnJbbXddPSgodCk9Pih0LmlkPW51bGwsdC5pbmRpY2VzPW51bGwsdC5pc09yZGVyZWQ9bnVsbCx0LmRpY3Rpb25hcnk9bnVsbCx0W1N5bWJvbC50b1N0cmluZ1RhZ109IkRpY3Rpb25hcnkiKSkoZnIucHJvdG90eXBlKX0pO2NsYXNzIGV0e3Zpc2l0TWFueSh0LC4uLmUpe3JldHVybiB0Lm1hcCgocixuKT0+dGhpcy52aXNpdChyLC4uLmUubWFwKChpKT0+aVtuXSkpKX12aXNpdCguLi50KXtyZXR1cm4gdGhpcy5nZXRWaXNpdEZuKHRbMF0sITEpLmFwcGx5KHRoaXMsdCl9Z2V0VmlzaXRGbih0LGU9ITApe3JldHVybiBTeCh0aGlzLHQsZSl9Z2V0VmlzaXRGbkJ5VHlwZUlkKHQsZT0hMCl7cmV0dXJuIGRjKHRoaXMsdCxlKX12aXNpdE51bGwodCwuLi5lKXtyZXR1cm4gbnVsbH12aXNpdEJvb2wodCwuLi5lKXtyZXR1cm4gbnVsbH12aXNpdEludCh0LC4uLmUpe3JldHVybiBudWxsfXZpc2l0RmxvYXQodCwuLi5lKXtyZXR1cm4gbnVsbH12aXNpdFV0ZjgodCwuLi5lKXtyZXR1cm4gbnVsbH12aXNpdExhcmdlVXRmOCh0LC4uLmUpe3JldHVybiBudWxsfXZpc2l0VXRmOFZpZXcodCwuLi5lKXtyZXR1cm4gbnVsbH12aXNpdEJpbmFyeSh0LC4uLmUpe3JldHVybiBudWxsfXZpc2l0TGFyZ2VCaW5hcnkodCwuLi5lKXtyZXR1cm4gbnVsbH12aXNpdEJpbmFyeVZpZXcodCwuLi5lKXtyZXR1cm4gbnVsbH12aXNpdEZpeGVkU2l6ZUJpbmFyeSh0LC4uLmUpe3JldHVybiBudWxsfXZpc2l0RGF0ZSh0LC4uLmUpe3JldHVybiBudWxsfXZpc2l0VGltZXN0YW1wKHQsLi4uZSl7cmV0dXJuIG51bGx9dmlzaXRUaW1lKHQsLi4uZSl7cmV0dXJuIG51bGx9dmlzaXREZWNpbWFsKHQsLi4uZSl7cmV0dXJuIG51bGx9dmlzaXRMaXN0KHQsLi4uZSl7cmV0dXJuIG51bGx9dmlzaXRTdHJ1Y3QodCwuLi5lKXtyZXR1cm4gbnVsbH12aXNpdFVuaW9uKHQsLi4uZSl7cmV0dXJuIG51bGx9dmlzaXREaWN0aW9uYXJ5KHQsLi4uZSl7cmV0dXJuIG51bGx9dmlzaXRJbnRlcnZhbCh0LC4uLmUpe3JldHVybiBudWxsfXZpc2l0RHVyYXRpb24odCwuLi5lKXtyZXR1cm4gbnVsbH12aXNpdEZpeGVkU2l6ZUxpc3QodCwuLi5lKXtyZXR1cm4gbnVsbH12aXNpdE1hcCh0LC4uLmUpe3JldHVybiBudWxsfX1mdW5jdGlvbiBTeCh0LGUscj0hMCl7aWYodHlwZW9mIGU9PT0ibnVtYmVyIilyZXR1cm4gZGModCxlLHIpO2lmKHR5cGVvZiBlPT09InN0cmluZyImJmUgaW4gXylyZXR1cm4gZGModCxfW2VdLHIpO2lmKGUmJmUgaW5zdGFuY2VvZiBCKXJldHVybiBkYyh0LGd3KGUpLHIpO2lmKChlPT09bnVsbHx8ZT09PXZvaWQgMD92b2lkIDA6ZS50eXBlKSYmZS50eXBlIGluc3RhbmNlb2YgQilyZXR1cm4gZGModCxndyhlLnR5cGUpLHIpO3JldHVybiBkYyh0LF8uTk9ORSxyKX1mdW5jdGlvbiBkYyh0LGUscj0hMCl7bGV0IG49bnVsbDtzd2l0Y2goZSl7Y2FzZSBfLk51bGw6bj10LnZpc2l0TnVsbDticmVhaztjYXNlIF8uQm9vbDpuPXQudmlzaXRCb29sO2JyZWFrO2Nhc2UgXy5JbnQ6bj10LnZpc2l0SW50O2JyZWFrO2Nhc2UgXy5JbnQ4Om49dC52aXNpdEludDh8fHQudmlzaXRJbnQ7YnJlYWs7Y2FzZSBfLkludDE2Om49dC52aXNpdEludDE2fHx0LnZpc2l0SW50O2JyZWFrO2Nhc2UgXy5JbnQzMjpuPXQudmlzaXRJbnQzMnx8dC52aXNpdEludDticmVhaztjYXNlIF8uSW50NjQ6bj10LnZpc2l0SW50NjR8fHQudmlzaXRJbnQ7YnJlYWs7Y2FzZSBfLlVpbnQ4Om49dC52aXNpdFVpbnQ4fHx0LnZpc2l0SW50O2JyZWFrO2Nhc2UgXy5VaW50MTY6bj10LnZpc2l0VWludDE2fHx0LnZpc2l0SW50O2JyZWFrO2Nhc2UgXy5VaW50MzI6bj10LnZpc2l0VWludDMyfHx0LnZpc2l0SW50O2JyZWFrO2Nhc2UgXy5VaW50NjQ6bj10LnZpc2l0VWludDY0fHx0LnZpc2l0SW50O2JyZWFrO2Nhc2UgXy5GbG9hdDpuPXQudmlzaXRGbG9hdDticmVhaztjYXNlIF8uRmxvYXQxNjpuPXQudmlzaXRGbG9hdDE2fHx0LnZpc2l0RmxvYXQ7YnJlYWs7Y2FzZSBfLkZsb2F0MzI6bj10LnZpc2l0RmxvYXQzMnx8dC52aXNpdEZsb2F0O2JyZWFrO2Nhc2UgXy5GbG9hdDY0Om49dC52aXNpdEZsb2F0NjR8fHQudmlzaXRGbG9hdDticmVhaztjYXNlIF8uVXRmODpuPXQudmlzaXRVdGY4O2JyZWFrO2Nhc2UgXy5MYXJnZVV0Zjg6bj10LnZpc2l0TGFyZ2VVdGY4O2JyZWFrO2Nhc2UgXy5VdGY4VmlldzpuPXQudmlzaXRVdGY4Vmlld3x8dC52aXNpdFV0Zjg7YnJlYWs7Y2FzZSBfLkJpbmFyeTpuPXQudmlzaXRCaW5hcnk7YnJlYWs7Y2FzZSBfLkxhcmdlQmluYXJ5Om49dC52aXNpdExhcmdlQmluYXJ5O2JyZWFrO2Nhc2UgXy5CaW5hcnlWaWV3Om49dC52aXNpdEJpbmFyeVZpZXd8fHQudmlzaXRCaW5hcnk7YnJlYWs7Y2FzZSBfLkZpeGVkU2l6ZUJpbmFyeTpuPXQudmlzaXRGaXhlZFNpemVCaW5hcnk7YnJlYWs7Y2FzZSBfLkRhdGU6bj10LnZpc2l0RGF0ZTticmVhaztjYXNlIF8uRGF0ZURheTpuPXQudmlzaXREYXRlRGF5fHx0LnZpc2l0RGF0ZTticmVhaztjYXNlIF8uRGF0ZU1pbGxpc2Vjb25kOm49dC52aXNpdERhdGVNaWxsaXNlY29uZHx8dC52aXNpdERhdGU7YnJlYWs7Y2FzZSBfLlRpbWVzdGFtcDpuPXQudmlzaXRUaW1lc3RhbXA7YnJlYWs7Y2FzZSBfLlRpbWVzdGFtcFNlY29uZDpuPXQudmlzaXRUaW1lc3RhbXBTZWNvbmR8fHQudmlzaXRUaW1lc3RhbXA7YnJlYWs7Y2FzZSBfLlRpbWVzdGFtcE1pbGxpc2Vjb25kOm49dC52aXNpdFRpbWVzdGFtcE1pbGxpc2Vjb25kfHx0LnZpc2l0VGltZXN0YW1wO2JyZWFrO2Nhc2UgXy5UaW1lc3RhbXBNaWNyb3NlY29uZDpuPXQudmlzaXRUaW1lc3RhbXBNaWNyb3NlY29uZHx8dC52aXNpdFRpbWVzdGFtcDticmVhaztjYXNlIF8uVGltZXN0YW1wTmFub3NlY29uZDpuPXQudmlzaXRUaW1lc3RhbXBOYW5vc2Vjb25kfHx0LnZpc2l0VGltZXN0YW1wO2JyZWFrO2Nhc2UgXy5UaW1lOm49dC52aXNpdFRpbWU7YnJlYWs7Y2FzZSBfLlRpbWVTZWNvbmQ6bj10LnZpc2l0VGltZVNlY29uZHx8dC52aXNpdFRpbWU7YnJlYWs7Y2FzZSBfLlRpbWVNaWxsaXNlY29uZDpuPXQudmlzaXRUaW1lTWlsbGlzZWNvbmR8fHQudmlzaXRUaW1lO2JyZWFrO2Nhc2UgXy5UaW1lTWljcm9zZWNvbmQ6bj10LnZpc2l0VGltZU1pY3Jvc2Vjb25kfHx0LnZpc2l0VGltZTticmVhaztjYXNlIF8uVGltZU5hbm9zZWNvbmQ6bj10LnZpc2l0VGltZU5hbm9zZWNvbmR8fHQudmlzaXRUaW1lO2JyZWFrO2Nhc2UgXy5EZWNpbWFsOm49dC52aXNpdERlY2ltYWw7YnJlYWs7Y2FzZSBfLkxpc3Q6bj10LnZpc2l0TGlzdDticmVhaztjYXNlIF8uU3RydWN0Om49dC52aXNpdFN0cnVjdDticmVhaztjYXNlIF8uVW5pb246bj10LnZpc2l0VW5pb247YnJlYWs7Y2FzZSBfLkRlbnNlVW5pb246bj10LnZpc2l0RGVuc2VVbmlvbnx8dC52aXNpdFVuaW9uO2JyZWFrO2Nhc2UgXy5TcGFyc2VVbmlvbjpuPXQudmlzaXRTcGFyc2VVbmlvbnx8dC52aXNpdFVuaW9uO2JyZWFrO2Nhc2UgXy5EaWN0aW9uYXJ5Om49dC52aXNpdERpY3Rpb25hcnk7YnJlYWs7Y2FzZSBfLkludGVydmFsOm49dC52aXNpdEludGVydmFsO2JyZWFrO2Nhc2UgXy5JbnRlcnZhbERheVRpbWU6bj10LnZpc2l0SW50ZXJ2YWxEYXlUaW1lfHx0LnZpc2l0SW50ZXJ2YWw7YnJlYWs7Y2FzZSBfLkludGVydmFsWWVhck1vbnRoOm49dC52aXNpdEludGVydmFsWWVhck1vbnRofHx0LnZpc2l0SW50ZXJ2YWw7YnJlYWs7Y2FzZSBfLkludGVydmFsTW9udGhEYXlOYW5vOm49dC52aXNpdEludGVydmFsTW9udGhEYXlOYW5vfHx0LnZpc2l0SW50ZXJ2YWw7YnJlYWs7Y2FzZSBfLkR1cmF0aW9uOm49dC52aXNpdER1cmF0aW9uO2JyZWFrO2Nhc2UgXy5EdXJhdGlvblNlY29uZDpuPXQudmlzaXREdXJhdGlvblNlY29uZHx8dC52aXNpdER1cmF0aW9uO2JyZWFrO2Nhc2UgXy5EdXJhdGlvbk1pbGxpc2Vjb25kOm49dC52aXNpdER1cmF0aW9uTWlsbGlzZWNvbmR8fHQudmlzaXREdXJhdGlvbjticmVhaztjYXNlIF8uRHVyYXRpb25NaWNyb3NlY29uZDpuPXQudmlzaXREdXJhdGlvbk1pY3Jvc2Vjb25kfHx0LnZpc2l0RHVyYXRpb247YnJlYWs7Y2FzZSBfLkR1cmF0aW9uTmFub3NlY29uZDpuPXQudmlzaXREdXJhdGlvbk5hbm9zZWNvbmR8fHQudmlzaXREdXJhdGlvbjticmVhaztjYXNlIF8uRml4ZWRTaXplTGlzdDpuPXQudmlzaXRGaXhlZFNpemVMaXN0O2JyZWFrO2Nhc2UgXy5NYXA6bj10LnZpc2l0TWFwO2JyZWFrfWlmKHR5cGVvZiBuPT09ImZ1bmN0aW9uIilyZXR1cm4gbjtpZighcilyZXR1cm4oKT0+bnVsbDt0aHJvdyBFcnJvcihgVW5yZWNvZ25pemVkIHR5cGUgJyR7X1tlXX0nYCl9ZnVuY3Rpb24gZ3codCl7c3dpdGNoKHQudHlwZUlkKXtjYXNlIF8uTnVsbDpyZXR1cm4gXy5OdWxsO2Nhc2UgXy5JbnQ6e2xldHtiaXRXaWR0aDplLGlzU2lnbmVkOnJ9PXQ7c3dpdGNoKGUpe2Nhc2UgODpyZXR1cm4gcj9fLkludDg6Xy5VaW50ODtjYXNlIDE2OnJldHVybiByP18uSW50MTY6Xy5VaW50MTY7Y2FzZSAzMjpyZXR1cm4gcj9fLkludDMyOl8uVWludDMyO2Nhc2UgNjQ6cmV0dXJuIHI/Xy5JbnQ2NDpfLlVpbnQ2NH1yZXR1cm4gXy5JbnR9Y2FzZSBfLkZsb2F0OnN3aXRjaCh0LnByZWNpc2lvbil7Y2FzZSBadC5IQUxGOnJldHVybiBfLkZsb2F0MTY7Y2FzZSBadC5TSU5HTEU6cmV0dXJuIF8uRmxvYXQzMjtjYXNlIFp0LkRPVUJMRTpyZXR1cm4gXy5GbG9hdDY0fXJldHVybiBfLkZsb2F0O2Nhc2UgXy5CaW5hcnk6cmV0dXJuIF8uQmluYXJ5O2Nhc2UgXy5MYXJnZUJpbmFyeTpyZXR1cm4gXy5MYXJnZUJpbmFyeTtjYXNlIF8uQmluYXJ5VmlldzpyZXR1cm4gXy5CaW5hcnlWaWV3O2Nhc2UgXy5VdGY4OnJldHVybiBfLlV0Zjg7Y2FzZSBfLkxhcmdlVXRmODpyZXR1cm4gXy5MYXJnZVV0Zjg7Y2FzZSBfLlV0ZjhWaWV3OnJldHVybiBfLlV0ZjhWaWV3O2Nhc2UgXy5Cb29sOnJldHVybiBfLkJvb2w7Y2FzZSBfLkRlY2ltYWw6cmV0dXJuIF8uRGVjaW1hbDtjYXNlIF8uVGltZTpzd2l0Y2godC51bml0KXtjYXNlIFQuU0VDT05EOnJldHVybiBfLlRpbWVTZWNvbmQ7Y2FzZSBULk1JTExJU0VDT05EOnJldHVybiBfLlRpbWVNaWxsaXNlY29uZDtjYXNlIFQuTUlDUk9TRUNPTkQ6cmV0dXJuIF8uVGltZU1pY3Jvc2Vjb25kO2Nhc2UgVC5OQU5PU0VDT05EOnJldHVybiBfLlRpbWVOYW5vc2Vjb25kfXJldHVybiBfLlRpbWU7Y2FzZSBfLlRpbWVzdGFtcDpzd2l0Y2godC51bml0KXtjYXNlIFQuU0VDT05EOnJldHVybiBfLlRpbWVzdGFtcFNlY29uZDtjYXNlIFQuTUlMTElTRUNPTkQ6cmV0dXJuIF8uVGltZXN0YW1wTWlsbGlzZWNvbmQ7Y2FzZSBULk1JQ1JPU0VDT05EOnJldHVybiBfLlRpbWVzdGFtcE1pY3Jvc2Vjb25kO2Nhc2UgVC5OQU5PU0VDT05EOnJldHVybiBfLlRpbWVzdGFtcE5hbm9zZWNvbmR9cmV0dXJuIF8uVGltZXN0YW1wO2Nhc2UgXy5EYXRlOnN3aXRjaCh0LnVuaXQpe2Nhc2UgcXQuREFZOnJldHVybiBfLkRhdGVEYXk7Y2FzZSBxdC5NSUxMSVNFQ09ORDpyZXR1cm4gXy5EYXRlTWlsbGlzZWNvbmR9cmV0dXJuIF8uRGF0ZTtjYXNlIF8uSW50ZXJ2YWw6c3dpdGNoKHQudW5pdCl7Y2FzZSBqdC5EQVlfVElNRTpyZXR1cm4gXy5JbnRlcnZhbERheVRpbWU7Y2FzZSBqdC5ZRUFSX01PTlRIOnJldHVybiBfLkludGVydmFsWWVhck1vbnRoO2Nhc2UganQuTU9OVEhfREFZX05BTk86cmV0dXJuIF8uSW50ZXJ2YWxNb250aERheU5hbm99cmV0dXJuIF8uSW50ZXJ2YWw7Y2FzZSBfLkR1cmF0aW9uOnN3aXRjaCh0LnVuaXQpe2Nhc2UgVC5TRUNPTkQ6cmV0dXJuIF8uRHVyYXRpb25TZWNvbmQ7Y2FzZSBULk1JTExJU0VDT05EOnJldHVybiBfLkR1cmF0aW9uTWlsbGlzZWNvbmQ7Y2FzZSBULk1JQ1JPU0VDT05EOnJldHVybiBfLkR1cmF0aW9uTWljcm9zZWNvbmQ7Y2FzZSBULk5BTk9TRUNPTkQ6cmV0dXJuIF8uRHVyYXRpb25OYW5vc2Vjb25kfXJldHVybiBfLkR1cmF0aW9uO2Nhc2UgXy5NYXA6cmV0dXJuIF8uTWFwO2Nhc2UgXy5MaXN0OnJldHVybiBfLkxpc3Q7Y2FzZSBfLlN0cnVjdDpyZXR1cm4gXy5TdHJ1Y3Q7Y2FzZSBfLlVuaW9uOnN3aXRjaCh0Lm1vZGUpe2Nhc2UgTHQuRGVuc2U6cmV0dXJuIF8uRGVuc2VVbmlvbjtjYXNlIEx0LlNwYXJzZTpyZXR1cm4gXy5TcGFyc2VVbmlvbn1yZXR1cm4gXy5VbmlvbjtjYXNlIF8uRml4ZWRTaXplQmluYXJ5OnJldHVybiBfLkZpeGVkU2l6ZUJpbmFyeTtjYXNlIF8uRml4ZWRTaXplTGlzdDpyZXR1cm4gXy5GaXhlZFNpemVMaXN0O2Nhc2UgXy5EaWN0aW9uYXJ5OnJldHVybiBfLkRpY3Rpb25hcnl9dGhyb3cgRXJyb3IoYFVucmVjb2duaXplZCB0eXBlICcke19bdC50eXBlSWRdfSdgKX12YXIgVWk9bSgoKT0+e0xlKCk7aWUoKTtldC5wcm90b3R5cGUudmlzaXRJbnQ4PW51bGw7ZXQucHJvdG90eXBlLnZpc2l0SW50MTY9bnVsbDtldC5wcm90b3R5cGUudmlzaXRJbnQzMj1udWxsO2V0LnByb3RvdHlwZS52aXNpdEludDY0PW51bGw7ZXQucHJvdG90eXBlLnZpc2l0VWludDg9bnVsbDtldC5wcm90b3R5cGUudmlzaXRVaW50MTY9bnVsbDtldC5wcm90b3R5cGUudmlzaXRVaW50MzI9bnVsbDtldC5wcm90b3R5cGUudmlzaXRVaW50NjQ9bnVsbDtldC5wcm90b3R5cGUudmlzaXRGbG9hdDE2PW51bGw7ZXQucHJvdG90eXBlLnZpc2l0RmxvYXQzMj1udWxsO2V0LnByb3RvdHlwZS52aXNpdEZsb2F0NjQ9bnVsbDtldC5wcm90b3R5cGUudmlzaXREYXRlRGF5PW51bGw7ZXQucHJvdG90eXBlLnZpc2l0RGF0ZU1pbGxpc2Vjb25kPW51bGw7ZXQucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wU2Vjb25kPW51bGw7ZXQucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wTWlsbGlzZWNvbmQ9bnVsbDtldC5wcm90b3R5cGUudmlzaXRUaW1lc3RhbXBNaWNyb3NlY29uZD1udWxsO2V0LnByb3RvdHlwZS52aXNpdFRpbWVzdGFtcE5hbm9zZWNvbmQ9bnVsbDtldC5wcm90b3R5cGUudmlzaXRUaW1lU2Vjb25kPW51bGw7ZXQucHJvdG90eXBlLnZpc2l0VGltZU1pbGxpc2Vjb25kPW51bGw7ZXQucHJvdG90eXBlLnZpc2l0VGltZU1pY3Jvc2Vjb25kPW51bGw7ZXQucHJvdG90eXBlLnZpc2l0VGltZU5hbm9zZWNvbmQ9bnVsbDtldC5wcm90b3R5cGUudmlzaXREZW5zZVVuaW9uPW51bGw7ZXQucHJvdG90eXBlLnZpc2l0U3BhcnNlVW5pb249bnVsbDtldC5wcm90b3R5cGUudmlzaXRJbnRlcnZhbERheVRpbWU9bnVsbDtldC5wcm90b3R5cGUudmlzaXRJbnRlcnZhbFllYXJNb250aD1udWxsO2V0LnByb3RvdHlwZS52aXNpdEludGVydmFsTW9udGhEYXlOYW5vPW51bGw7ZXQucHJvdG90eXBlLnZpc2l0RHVyYXRpb249bnVsbDtldC5wcm90b3R5cGUudmlzaXREdXJhdGlvblNlY29uZD1udWxsO2V0LnByb3RvdHlwZS52aXNpdER1cmF0aW9uTWlsbGlzZWNvbmQ9bnVsbDtldC5wcm90b3R5cGUudmlzaXREdXJhdGlvbk1pY3Jvc2Vjb25kPW51bGw7ZXQucHJvdG90eXBlLnZpc2l0RHVyYXRpb25OYW5vc2Vjb25kPW51bGx9KTt2YXIgRW09e307WmUoRW0se2Zsb2F0NjRUb1VpbnQxNjooKT0+Q2wsdWludDE2VG9GbG9hdDY0OigpPT5fZn0pO2Z1bmN0aW9uIF9mKHQpe2xldCBlPSh0JjMxNzQ0KT4+MTAscj0odCYxMDIzKS8xMDI0LG49TWF0aC5wb3coLTEsKHQmMzI3NjgpPj4xNSk7c3dpdGNoKGUpe2Nhc2UgMzE6cmV0dXJuIG4qKHI/TnVtYmVyLk5hTjoxLzApO2Nhc2UgMDpyZXR1cm4gbioocj8wLjAwMDA2MTAzNTE1NjI1KnI6MCl9cmV0dXJuIG4qTWF0aC5wb3coMixlLTE1KSooMStyKX1mdW5jdGlvbiBDbCh0KXtpZih0IT09dClyZXR1cm4gMzIyNTY7YndbMF09dDtsZXQgZT0oaGNbMV0mMjE0NzQ4MzY0OCk+PjE2JjY1NTM1LHI9aGNbMV0mMjE0NjQzNTA3MixuPTA7aWYocj49MTA4OTQ3MDQ2NClpZihoY1swXT4wKXI9MzE3NDQ7ZWxzZSByPShyJjIwODAzNzQ3ODQpPj4xNixuPShoY1sxXSYxMDQ4NTc1KT4+MTA7ZWxzZSBpZihyPD0xMDU2OTY0NjA4KW49MTA0ODU3NisoaGNbMV0mMTA0ODU3NSksbj0xMDQ4NTc2KyhuPDwocj4+MjApLTk5OCk+PjIxLHI9MDtlbHNlIHI9ci0xMDU2OTY0NjA4Pj4xMCxuPShoY1sxXSYxMDQ4NTc1KSs1MTI+PjEwO3JldHVybiBlfHJ8biY2NTUzNX12YXIgYncsaGM7dmFyIFBsPW0oKCk9Pntidz1uZXcgRmxvYXQ2NEFycmF5KDEpLGhjPW5ldyBVaW50MzJBcnJheShidy5idWZmZXIpfSk7ZnVuY3Rpb24gY3QodCl7cmV0dXJuKGUscixuKT0+e2lmKGUuc2V0VmFsaWQocixuIT1udWxsKSlyZXR1cm4gdChlLHIsbil9fXZhciBRLEF4PSh0LGUscik9Pnt0W2VdPU1hdGguZmxvb3Ioci84NjQwMDAwMCl9LHd3PSh0LGUscixuKT0+e2lmKHIrMTxlLmxlbmd0aCl7bGV0IGk9UHQoZVtyXSkscz1QdChlW3IrMV0pO3Quc2V0KG4uc3ViYXJyYXkoMCxzLWkpLGkpfX0sRHg9KHtvZmZzZXQ6dCx2YWx1ZXM6ZX0scixuKT0+e2xldCBpPXQrcjtuP2VbaT4+M118PTE8PGklODplW2k+PjNdJj1+KDE8PGklOCl9LElzPSh7dmFsdWVzOnR9LGUscik9Pnt0W2VdPXJ9LE9tPSh7dmFsdWVzOnR9LGUscik9Pnt0W2VdPXJ9LHZ3PSh7dmFsdWVzOnR9LGUscik9Pnt0W2VdPUNsKHIpfSx4eD0odCxlLHIpPT57c3dpdGNoKHQudHlwZS5wcmVjaXNpb24pe2Nhc2UgWnQuSEFMRjpyZXR1cm4gdncodCxlLHIpO2Nhc2UgWnQuU0lOR0xFOmNhc2UgWnQuRE9VQkxFOnJldHVybiBPbSh0LGUscil9fSxnZj0oe3ZhbHVlczp0fSxlLHIpPT57QXgodCxlLHIudmFsdWVPZigpKX0sYmY9KHt2YWx1ZXM6dH0sZSxyKT0+e3RbZV09QmlnSW50KHIpfSxObT0oe3N0cmlkZTp0LHZhbHVlczplfSxyLG4pPT57ZS5zZXQobi5zdWJhcnJheSgwLHQpLHQqcil9LEl3PSh7dmFsdWVzOnQsdmFsdWVPZmZzZXRzOmV9LHIsbik9Pnd3KHQsZSxyLG4pLFR4PSh0KT0+e2xldCBlPXQudmFyaWFkaWNCdWZmZXJzO2lmKCFBcnJheS5pc0FycmF5KGUpfHxPYmplY3QuaXNGcm96ZW4oZSkpZT1BcnJheS5mcm9tKGUpLHQudmFyaWFkaWNCdWZmZXJzPWU7cmV0dXJuIGV9LEJ3PSh0LGUscik9Pnt2YXIgbixpLHMsbztsZXQgYT10LnZhbHVlcztpZighYSl0aHJvdyBFcnJvcigiQmluYXJ5VmlldyBkYXRhIGlzIG1pc3NpbmcgdmlldyBidWZmZXIiKTtsZXQgbD1fdC5FTEVNRU5UX1dJRFRILHU9ZSpsLGY9dStsO2lmKHU8MHx8Zj5hLmxlbmd0aCl0aHJvdyBSYW5nZUVycm9yKGBCaW5hcnlWaWV3IGluZGV4ICR7ZX0gb3V0IG9mIGJvdW5kc2ApO2EuZmlsbCgwLHUsZik7bGV0IHA9bmV3IERhdGFWaWV3KGEuYnVmZmVyLGEuYnl0ZU9mZnNldCt1LGwpLGc9ci5sZW5ndGg7aWYocC5zZXRJbnQzMihfdC5MRU5HVEhfT0ZGU0VULGcsITApLGc8PV90LklOTElORV9DQVBBQ0lUWSl7YS5zZXQocix1K190LklOTElORV9PRkZTRVQpO3JldHVybn1sZXQgdj0oKG49clswXSkhPT1udWxsJiZuIT09dm9pZCAwP246MCl8KChpPXJbMV0pIT09bnVsbCYmaSE9PXZvaWQgMD9pOjApPDw4fCgocz1yWzJdKSE9PW51bGwmJnMhPT12b2lkIDA/czowKTw8MTZ8KChvPXJbM10pIT09bnVsbCYmbyE9PXZvaWQgMD9vOjApPDwyNDtwLnNldFVpbnQzMihfdC5JTkxJTkVfT0ZGU0VULHY+Pj4wLCEwKTtsZXQgST1UeCh0KSxEPXIuc2xpY2UoKSxaPUkucHVzaChEKS0xO3Auc2V0SW50MzIoX3QuQlVGRkVSX0lOREVYX09GRlNFVCxaLCEwKSxwLnNldEludDMyKF90LkJVRkZFUl9PRkZTRVRfT0ZGU0VULDAsITApfSxFeD0odCxlLHIpPT57bGV0IG49ciBpbnN0YW5jZW9mIFVpbnQ4QXJyYXk/cjpuZXcgVWludDhBcnJheShyKTtCdyh0LGUsbil9LFN3PSh7dmFsdWVzOnQsdmFsdWVPZmZzZXRzOmV9LHIsbik9Pnd3KHQsZSxyLG1uKG4pKSxPeD0odCxlLHIpPT57bGV0IG49bW4ocik7QncodCxlLG4pfSxGbT0odCxlLHIpPT57dC50eXBlLnVuaXQ9PT1xdC5EQVk/Z2YodCxlLHIpOmJmKHQsZSxyKX0sd2Y9KHt2YWx1ZXM6dH0sZSxyKT0+e3RbZV09QmlnSW50KHIvMTAwMCl9LHZmPSh7dmFsdWVzOnR9LGUscik9Pnt0W2VdPUJpZ0ludChyKX0sSWY9KHt2YWx1ZXM6dH0sZSxyKT0+e3RbZV09QmlnSW50KHIqMTAwMCl9LEJmPSh7dmFsdWVzOnR9LGUscik9Pnt0W2VdPUJpZ0ludChyKjFlNil9LE1tPSh0LGUscik9Pntzd2l0Y2godC50eXBlLnVuaXQpe2Nhc2UgVC5TRUNPTkQ6cmV0dXJuIHdmKHQsZSxyKTtjYXNlIFQuTUlMTElTRUNPTkQ6cmV0dXJuIHZmKHQsZSxyKTtjYXNlIFQuTUlDUk9TRUNPTkQ6cmV0dXJuIElmKHQsZSxyKTtjYXNlIFQuTkFOT1NFQ09ORDpyZXR1cm4gQmYodCxlLHIpfX0sU2Y9KHt2YWx1ZXM6dH0sZSxyKT0+e3RbZV09cn0sQWY9KHt2YWx1ZXM6dH0sZSxyKT0+e3RbZV09cn0sRGY9KHt2YWx1ZXM6dH0sZSxyKT0+e3RbZV09cn0seGY9KHt2YWx1ZXM6dH0sZSxyKT0+e3RbZV09cn0sTG09KHQsZSxyKT0+e3N3aXRjaCh0LnR5cGUudW5pdCl7Y2FzZSBULlNFQ09ORDpyZXR1cm4gU2YodCxlLHIpO2Nhc2UgVC5NSUxMSVNFQ09ORDpyZXR1cm4gQWYodCxlLHIpO2Nhc2UgVC5NSUNST1NFQ09ORDpyZXR1cm4gRGYodCxlLHIpO2Nhc2UgVC5OQU5PU0VDT05EOnJldHVybiB4Zih0LGUscil9fSxVbT0oe3ZhbHVlczp0LHN0cmlkZTplfSxyLG4pPT57dC5zZXQobi5zdWJhcnJheSgwLGUpLGUqcil9LE54PSh0LGUscik9PntsZXQgbj10LmNoaWxkcmVuWzBdLGk9dC52YWx1ZU9mZnNldHMscz1kci5nZXRWaXNpdEZuKG4pO2lmKEFycmF5LmlzQXJyYXkocikpZm9yKGxldCBvPS0xLGE9aVtlXSxsPWlbZSsxXTthPGw7KXMobixhKyssclsrK29dKTtlbHNlIGZvcihsZXQgbz0tMSxhPWlbZV0sbD1pW2UrMV07YTxsOylzKG4sYSsrLHIuZ2V0KCsrbykpfSxGeD0odCxlLHIpPT57bGV0IG49dC5jaGlsZHJlblswXSx7dmFsdWVPZmZzZXRzOml9PXQscz1kci5nZXRWaXNpdEZuKG4pLHtbZV06byxbZSsxXTphfT1pLGw9ciBpbnN0YW5jZW9mIE1hcD9yLmVudHJpZXMoKTpPYmplY3QuZW50cmllcyhyKTtmb3IobGV0IHUgb2YgbClpZihzKG4sbyx1KSwrK28+PWEpYnJlYWt9LE14PSh0LGUpPT4ocixuLGkscyk9Pm4mJnIobix0LGVbc10pLEx4PSh0LGUpPT4ocixuLGkscyk9Pm4mJnIobix0LGUuZ2V0KHMpKSxVeD0odCxlKT0+KHIsbixpLHMpPT5uJiZyKG4sdCxlLmdldChpLm5hbWUpKSxSeD0odCxlKT0+KHIsbixpLHMpPT5uJiZyKG4sdCxlW2kubmFtZV0pLEN4PSh0LGUscik9PntsZXQgbj10LnR5cGUuY2hpbGRyZW4ubWFwKChzKT0+ZHIuZ2V0VmlzaXRGbihzLnR5cGUpKSxpPXIgaW5zdGFuY2VvZiBNYXA/VXgoZSxyKTpyIGluc3RhbmNlb2YgTj9MeChlLHIpOkFycmF5LmlzQXJyYXkocik/TXgoZSxyKTpSeChlLHIpO3QudHlwZS5jaGlsZHJlbi5mb3JFYWNoKChzLG8pPT5pKG5bb10sdC5jaGlsZHJlbltvXSxzLG8pKX0sUHg9KHQsZSxyKT0+e3QudHlwZS5tb2RlPT09THQuRGVuc2U/QXcodCxlLHIpOkR3KHQsZSxyKX0sQXc9KHQsZSxyKT0+e2xldCBuPXQudHlwZS50eXBlSWRUb0NoaWxkSW5kZXhbdC50eXBlSWRzW2VdXSxpPXQuY2hpbGRyZW5bbl07ZHIudmlzaXQoaSx0LnZhbHVlT2Zmc2V0c1tlXSxyKX0sRHc9KHQsZSxyKT0+e2xldCBuPXQudHlwZS50eXBlSWRUb0NoaWxkSW5kZXhbdC50eXBlSWRzW2VdXSxpPXQuY2hpbGRyZW5bbl07ZHIudmlzaXQoaSxlLHIpfSxreD0odCxlLHIpPT57dmFyIG47KG49dC5kaWN0aW9uYXJ5KT09PW51bGx8fG49PT12b2lkIDB8fG4uc2V0KHQudmFsdWVzW2VdLHIpfSxSbT0odCxlLHIpPT57c3dpdGNoKHQudHlwZS51bml0KXtjYXNlIGp0LllFQVJfTU9OVEg6cmV0dXJuIEVmKHQsZSxyKTtjYXNlIGp0LkRBWV9USU1FOnJldHVybiBUZih0LGUscik7Y2FzZSBqdC5NT05USF9EQVlfTkFOTzpyZXR1cm4gT2YodCxlLHIpfX0sVGY9KHt2YWx1ZXM6dH0sZSxyKT0+e3Quc2V0KHIuc3ViYXJyYXkoMCwyKSwyKmUpfSxFZj0oe3ZhbHVlczp0fSxlLHIpPT57dFtlXT1yWzBdKjEyK3JbMV0lMTJ9LE9mPSh7dmFsdWVzOnQsc3RyaWRlOmV9LHIsbik9Pnt0LnNldChuLnN1YmFycmF5KDAsZSksZSpyKX0sTmY9KHt2YWx1ZXM6dH0sZSxyKT0+e3RbZV09cn0sRmY9KHt2YWx1ZXM6dH0sZSxyKT0+e3RbZV09cn0sTWY9KHt2YWx1ZXM6dH0sZSxyKT0+e3RbZV09cn0sTGY9KHt2YWx1ZXM6dH0sZSxyKT0+e3RbZV09cn0sQ209KHQsZSxyKT0+e3N3aXRjaCh0LnR5cGUudW5pdCl7Y2FzZSBULlNFQ09ORDpyZXR1cm4gTmYodCxlLHIpO2Nhc2UgVC5NSUxMSVNFQ09ORDpyZXR1cm4gRmYodCxlLHIpO2Nhc2UgVC5NSUNST1NFQ09ORDpyZXR1cm4gTWYodCxlLHIpO2Nhc2UgVC5OQU5PU0VDT05EOnJldHVybiBMZih0LGUscil9fSxWeD0odCxlLHIpPT57bGV0e3N0cmlkZTpufT10LGk9dC5jaGlsZHJlblswXSxzPWRyLmdldFZpc2l0Rm4oaSk7aWYoQXJyYXkuaXNBcnJheShyKSlmb3IobGV0IG89LTEsYT1lKm47KytvPG47KXMoaSxhK28scltvXSk7ZWxzZSBmb3IobGV0IG89LTEsYT1lKm47KytvPG47KXMoaSxhK28sci5nZXQobykpfSxkcjt2YXIgU249bSgoKT0+e1FyKCk7VWkoKTt2cygpO1BsKCk7TGUoKTtpZSgpO1E9Y2xhc3MgUSBleHRlbmRzIGV0e307US5wcm90b3R5cGUudmlzaXRCb29sPWN0KER4KTtRLnByb3RvdHlwZS52aXNpdEludD1jdChJcyk7US5wcm90b3R5cGUudmlzaXRJbnQ4PWN0KElzKTtRLnByb3RvdHlwZS52aXNpdEludDE2PWN0KElzKTtRLnByb3RvdHlwZS52aXNpdEludDMyPWN0KElzKTtRLnByb3RvdHlwZS52aXNpdEludDY0PWN0KElzKTtRLnByb3RvdHlwZS52aXNpdFVpbnQ4PWN0KElzKTtRLnByb3RvdHlwZS52aXNpdFVpbnQxNj1jdChJcyk7US5wcm90b3R5cGUudmlzaXRVaW50MzI9Y3QoSXMpO1EucHJvdG90eXBlLnZpc2l0VWludDY0PWN0KElzKTtRLnByb3RvdHlwZS52aXNpdEZsb2F0PWN0KHh4KTtRLnByb3RvdHlwZS52aXNpdEZsb2F0MTY9Y3QodncpO1EucHJvdG90eXBlLnZpc2l0RmxvYXQzMj1jdChPbSk7US5wcm90b3R5cGUudmlzaXRGbG9hdDY0PWN0KE9tKTtRLnByb3RvdHlwZS52aXNpdFV0Zjg9Y3QoU3cpO1EucHJvdG90eXBlLnZpc2l0TGFyZ2VVdGY4PWN0KFN3KTtRLnByb3RvdHlwZS52aXNpdFV0ZjhWaWV3PWN0KE94KTtRLnByb3RvdHlwZS52aXNpdEJpbmFyeT1jdChJdyk7US5wcm90b3R5cGUudmlzaXRMYXJnZUJpbmFyeT1jdChJdyk7US5wcm90b3R5cGUudmlzaXRCaW5hcnlWaWV3PWN0KEV4KTtRLnByb3RvdHlwZS52aXNpdEZpeGVkU2l6ZUJpbmFyeT1jdChObSk7US5wcm90b3R5cGUudmlzaXREYXRlPWN0KEZtKTtRLnByb3RvdHlwZS52aXNpdERhdGVEYXk9Y3QoZ2YpO1EucHJvdG90eXBlLnZpc2l0RGF0ZU1pbGxpc2Vjb25kPWN0KGJmKTtRLnByb3RvdHlwZS52aXNpdFRpbWVzdGFtcD1jdChNbSk7US5wcm90b3R5cGUudmlzaXRUaW1lc3RhbXBTZWNvbmQ9Y3Qod2YpO1EucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wTWlsbGlzZWNvbmQ9Y3QodmYpO1EucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wTWljcm9zZWNvbmQ9Y3QoSWYpO1EucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wTmFub3NlY29uZD1jdChCZik7US5wcm90b3R5cGUudmlzaXRUaW1lPWN0KExtKTtRLnByb3RvdHlwZS52aXNpdFRpbWVTZWNvbmQ9Y3QoU2YpO1EucHJvdG90eXBlLnZpc2l0VGltZU1pbGxpc2Vjb25kPWN0KEFmKTtRLnByb3RvdHlwZS52aXNpdFRpbWVNaWNyb3NlY29uZD1jdChEZik7US5wcm90b3R5cGUudmlzaXRUaW1lTmFub3NlY29uZD1jdCh4Zik7US5wcm90b3R5cGUudmlzaXREZWNpbWFsPWN0KFVtKTtRLnByb3RvdHlwZS52aXNpdExpc3Q9Y3QoTngpO1EucHJvdG90eXBlLnZpc2l0U3RydWN0PWN0KEN4KTtRLnByb3RvdHlwZS52aXNpdFVuaW9uPWN0KFB4KTtRLnByb3RvdHlwZS52aXNpdERlbnNlVW5pb249Y3QoQXcpO1EucHJvdG90eXBlLnZpc2l0U3BhcnNlVW5pb249Y3QoRHcpO1EucHJvdG90eXBlLnZpc2l0RGljdGlvbmFyeT1jdChreCk7US5wcm90b3R5cGUudmlzaXRJbnRlcnZhbD1jdChSbSk7US5wcm90b3R5cGUudmlzaXRJbnRlcnZhbERheVRpbWU9Y3QoVGYpO1EucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWxZZWFyTW9udGg9Y3QoRWYpO1EucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWxNb250aERheU5hbm89Y3QoT2YpO1EucHJvdG90eXBlLnZpc2l0RHVyYXRpb249Y3QoQ20pO1EucHJvdG90eXBlLnZpc2l0RHVyYXRpb25TZWNvbmQ9Y3QoTmYpO1EucHJvdG90eXBlLnZpc2l0RHVyYXRpb25NaWxsaXNlY29uZD1jdChGZik7US5wcm90b3R5cGUudmlzaXREdXJhdGlvbk1pY3Jvc2Vjb25kPWN0KE1mKTtRLnByb3RvdHlwZS52aXNpdER1cmF0aW9uTmFub3NlY29uZD1jdChMZik7US5wcm90b3R5cGUudmlzaXRGaXhlZFNpemVMaXN0PWN0KFZ4KTtRLnByb3RvdHlwZS52aXNpdE1hcD1jdChGeCk7ZHI9bmV3IFF9KTtjbGFzcyBUd3tpc0V4dGVuc2libGUoKXtyZXR1cm4hMX1kZWxldGVQcm9wZXJ0eSgpe3JldHVybiExfXByZXZlbnRFeHRlbnNpb25zKCl7cmV0dXJuITB9b3duS2V5cyh0KXtyZXR1cm4gdFtSaV0udHlwZS5jaGlsZHJlbi5tYXAoKGUpPT5lLm5hbWUpfWhhcyh0LGUpe3JldHVybiB0W1JpXS50eXBlLmNoaWxkcmVuLnNvbWUoKHIpPT5yLm5hbWU9PT1lKX1nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodCxlKXtpZih0W1JpXS50eXBlLmNoaWxkcmVuLnNvbWUoKHIpPT5yLm5hbWU9PT1lKSlyZXR1cm57d3JpdGFibGU6ITAsZW51bWVyYWJsZTohMCxjb25maWd1cmFibGU6ITB9O3JldHVybn1nZXQodCxlKXtpZihSZWZsZWN0Lmhhcyh0LGUpKXJldHVybiB0W2VdO2xldCByPXRbUmldLnR5cGUuY2hpbGRyZW4uZmluZEluZGV4KChuKT0+bi5uYW1lPT09ZSk7aWYociE9PS0xKXtsZXQgbj1SZS52aXNpdCh0W1JpXS5jaGlsZHJlbltyXSx0W3BjXSk7cmV0dXJuIFJlZmxlY3Quc2V0KHQsZSxuKSxufX1zZXQodCxlLHIpe2xldCBuPXRbUmldLnR5cGUuY2hpbGRyZW4uZmluZEluZGV4KChpKT0+aS5uYW1lPT09ZSk7aWYobiE9PS0xKXJldHVybiBkci52aXNpdCh0W1JpXS5jaGlsZHJlbltuXSx0W3BjXSxyKSxSZWZsZWN0LnNldCh0LGUscik7ZWxzZSBpZihSZWZsZWN0Lmhhcyh0LGUpfHx0eXBlb2YgZT09PSJzeW1ib2wiKXJldHVybiBSZWZsZWN0LnNldCh0LGUscik7cmV0dXJuITF9fXZhciBSaSxwYyxsYSx4dyx6eDt2YXIgUG09bSgoKT0+e3VhKCk7U24oKTtSaT1TeW1ib2wuZm9yKCJwYXJlbnQiKSxwYz1TeW1ib2wuZm9yKCJyb3dJbmRleCIpO2xhPWNsYXNzIGxhe2NvbnN0cnVjdG9yKHQsZSl7cmV0dXJuIHRoaXNbUmldPXQsdGhpc1twY109ZSxuZXcgUHJveHkodGhpcyx6eCl9dG9BcnJheSgpe3JldHVybiBPYmplY3QudmFsdWVzKHRoaXMudG9KU09OKCkpfXRvSlNPTigpe2xldCB0PXRoaXNbcGNdLGU9dGhpc1tSaV0scj1lLnR5cGUuY2hpbGRyZW4sbj17fTtmb3IobGV0IGk9LTEscz1yLmxlbmd0aDsrK2k8czspbltyW2ldLm5hbWVdPVJlLnZpc2l0KGUuY2hpbGRyZW5baV0sdCk7cmV0dXJuIG59dG9TdHJpbmcoKXtyZXR1cm5geyR7Wy4uLnRoaXNdLm1hcCgoW3QsZV0pPT5gJHtCaSh0KX06ICR7QmkoZSl9YCkuam9pbigiLCAiKX19YH1bU3ltYm9sLmZvcigibm9kZWpzLnV0aWwuaW5zcGVjdC5jdXN0b20iKV0oKXtyZXR1cm4gdGhpcy50b1N0cmluZygpfVtTeW1ib2wuaXRlcmF0b3JdKCl7cmV0dXJuIG5ldyB4dyh0aGlzW1JpXSx0aGlzW3BjXSl9fTt4dz1jbGFzcyB4d3tjb25zdHJ1Y3Rvcih0LGUpe3RoaXMuY2hpbGRJbmRleD0wLHRoaXMuY2hpbGRyZW49dC5jaGlsZHJlbix0aGlzLnJvd0luZGV4PWUsdGhpcy5jaGlsZEZpZWxkcz10LnR5cGUuY2hpbGRyZW4sdGhpcy5udW1DaGlsZHJlbj10aGlzLmNoaWxkRmllbGRzLmxlbmd0aH1bU3ltYm9sLml0ZXJhdG9yXSgpe3JldHVybiB0aGlzfW5leHQoKXtsZXQgdD10aGlzLmNoaWxkSW5kZXg7aWYodDx0aGlzLm51bUNoaWxkcmVuKXJldHVybiB0aGlzLmNoaWxkSW5kZXg9dCsxLHtkb25lOiExLHZhbHVlOlt0aGlzLmNoaWxkRmllbGRzW3RdLm5hbWUsUmUudmlzaXQodGhpcy5jaGlsZHJlblt0XSx0aGlzLnJvd0luZGV4KV19O3JldHVybntkb25lOiEwLHZhbHVlOm51bGx9fX07T2JqZWN0LmRlZmluZVByb3BlcnRpZXMobGEucHJvdG90eXBlLHtbU3ltYm9sLnRvU3RyaW5nVGFnXTp7ZW51bWVyYWJsZTohMSxjb25maWd1cmFibGU6ITEsdmFsdWU6IlJvdyJ9LFtSaV06e3dyaXRhYmxlOiEwLGVudW1lcmFibGU6ITEsY29uZmlndXJhYmxlOiExLHZhbHVlOm51bGx9LFtwY106e3dyaXRhYmxlOiEwLGVudW1lcmFibGU6ITEsY29uZmlndXJhYmxlOiExLHZhbHVlOi0xfX0pO3p4PW5ldyBUd30pO2Z1bmN0aW9uIHJ0KHQpe3JldHVybihlLHIpPT5lLmdldFZhbGlkKHIpP3QoZSxyKTpudWxsfXZhciBxLGp4PSh0LGUpPT44NjQwMDAwMCp0W2VdLG1jPTE2LCR4PTEyLHF4PSh0LGUpPT5udWxsLEV3PSh0LGUscik9PntpZihyKzE+PWUubGVuZ3RoKXJldHVybiBudWxsO2xldCBuPVB0KGVbcl0pLGk9UHQoZVtyKzFdKTtyZXR1cm4gdC5zdWJhcnJheShuLGkpfSxXeD0oe29mZnNldDp0LHZhbHVlczplfSxyKT0+e2xldCBuPXQrcjtyZXR1cm4oZVtuPj4zXSYxPDxuJTgpIT09MH0sT3c9KHt2YWx1ZXM6dH0sZSk9Pmp4KHQsZSksTnc9KHt2YWx1ZXM6dH0sZSk9PlB0KHRbZV0pLElvPSh7c3RyaWRlOnQsdmFsdWVzOmV9LHIpPT5lW3Qqcl0sSHg9KHtzdHJpZGU6dCx2YWx1ZXM6ZX0scik9Pl9mKGVbdCpyXSksRnc9KHt2YWx1ZXM6dH0sZSk9PnRbZV0sWXg9KHtzdHJpZGU6dCx2YWx1ZXM6ZX0scik9PmUuc3ViYXJyYXkodCpyLHQqKHIrMSkpLE13PSh7dmFsdWVzOnQsdmFsdWVPZmZzZXRzOmV9LHIpPT5Fdyh0LGUsciksTHc9KHQsZSk9Pnt2YXIgcjtsZXQgbj10LnZhbHVlcztpZighbil0aHJvdyBFcnJvcigiQmluYXJ5VmlldyBkYXRhIGlzIG1pc3NpbmcgdmlldyBidWZmZXIiKTtsZXQgaT1lKm1jLHM9aSttYztpZihpPDB8fHM+bi5sZW5ndGgpdGhyb3cgRXJyb3IoYEJpbmFyeVZpZXcgZGF0YSBidWZmZXIgaXMgdG9vIHNob3J0OiBleHBlY3RlZCAke21jfSBieXRlcywgZ290ICR7TWF0aC5tYXgoMCxuLmxlbmd0aC1pKX1gKTtsZXQgbz1uLnN1YmFycmF5KGkscyk7aWYoby5sZW5ndGg8bWMpdGhyb3cgRXJyb3IoYEJpbmFyeVZpZXcgZGF0YSBidWZmZXIgaXMgdG9vIHNob3J0OiBleHBlY3RlZCAke21jfSBieXRlcywgZ290ICR7by5sZW5ndGh9YCk7bGV0IGE9bmV3IERhdGFWaWV3KG4uYnVmZmVyLG8uYnl0ZU9mZnNldCxtYyksbD1hLmdldEludDMyKDAsITApO2lmKGw8PTApcmV0dXJuIG5ldyBVaW50OEFycmF5KDApO2lmKGw8PSR4KXJldHVybiBvLnN1YmFycmF5KDQsNCtsKTtsZXQgdT1hLmdldEludDMyKDgsITApLGY9YS5nZXRJbnQzMigxMiwhMCkscD0ocj10LnZhcmlhZGljQnVmZmVycyk9PT1udWxsfHxyPT09dm9pZCAwP3ZvaWQgMDpyW3VdO2lmKCFwKXRocm93IEVycm9yKGBCaW5hcnlWaWV3IHZhcmlhZGljIGJ1ZmZlciAke3V9IGlzIG1pc3NpbmdgKTtyZXR1cm4gcC5zdWJhcnJheShmLGYrbCl9LEt4PSh0LGUpPT5Mdyh0LGUpLFV3PSh7dmFsdWVzOnQsdmFsdWVPZmZzZXRzOmV9LHIpPT57bGV0IG49RXcodCxlLHIpO3JldHVybiBuIT09bnVsbD9zYyhuKTpudWxsfSxHeD0odCxlKT0+e2xldCByPUx3KHQsZSk7cmV0dXJuIHNjKHIpfSxKeD0oe3ZhbHVlczp0fSxlKT0+dFtlXSxYeD0oe3R5cGU6dCx2YWx1ZXM6ZX0scik9PnQucHJlY2lzaW9uIT09WnQuSEFMRj9lW3JdOl9mKGVbcl0pLFp4PSh0LGUpPT50LnR5cGUudW5pdD09PXF0LkRBWT9Pdyh0LGUpOk53KHQsZSksUnc9KHt2YWx1ZXM6dH0sZSk9PjEwMDAqUHQodFtlXSksQ3c9KHt2YWx1ZXM6dH0sZSk9PlB0KHRbZV0pLFB3PSh7dmFsdWVzOnR9LGUpPT5TbSh0W2VdLEJpZ0ludCgxMDAwKSksa3c9KHt2YWx1ZXM6dH0sZSk9PlNtKHRbZV0sQmlnSW50KDFlNikpLFF4PSh0LGUpPT57c3dpdGNoKHQudHlwZS51bml0KXtjYXNlIFQuU0VDT05EOnJldHVybiBSdyh0LGUpO2Nhc2UgVC5NSUxMSVNFQ09ORDpyZXR1cm4gQ3codCxlKTtjYXNlIFQuTUlDUk9TRUNPTkQ6cmV0dXJuIFB3KHQsZSk7Y2FzZSBULk5BTk9TRUNPTkQ6cmV0dXJuIGt3KHQsZSl9fSxWdz0oe3ZhbHVlczp0fSxlKT0+dFtlXSx6dz0oe3ZhbHVlczp0fSxlKT0+dFtlXSxqdz0oe3ZhbHVlczp0fSxlKT0+dFtlXSwkdz0oe3ZhbHVlczp0fSxlKT0+dFtlXSx0VD0odCxlKT0+e3N3aXRjaCh0LnR5cGUudW5pdCl7Y2FzZSBULlNFQ09ORDpyZXR1cm4gVncodCxlKTtjYXNlIFQuTUlMTElTRUNPTkQ6cmV0dXJuIHp3KHQsZSk7Y2FzZSBULk1JQ1JPU0VDT05EOnJldHVybiBqdyh0LGUpO2Nhc2UgVC5OQU5PU0VDT05EOnJldHVybiAkdyh0LGUpfX0sZVQ9KHt2YWx1ZXM6dCxzdHJpZGU6ZX0scik9PkxsLmRlY2ltYWwodC5zdWJhcnJheShlKnIsZSoocisxKSkpLHJUPSh0LGUpPT57bGV0e3ZhbHVlT2Zmc2V0czpyLHN0cmlkZTpuLGNoaWxkcmVuOml9PXQse1tlKm5dOnMsW2UqbisxXTpvfT1yLGw9aVswXS5zbGljZShzLG8tcyk7cmV0dXJuIG5ldyBOKFtsXSl9LG5UPSh0LGUpPT57bGV0e3ZhbHVlT2Zmc2V0czpyLGNoaWxkcmVuOm59PXQse1tlXTppLFtlKzFdOnN9PXIsbz1uWzBdO3JldHVybiBuZXcgQnMoby5zbGljZShpLHMtaSkpfSxpVD0odCxlKT0+bmV3IGxhKHQsZSksc1Q9KHQsZSk9PnQudHlwZS5tb2RlPT09THQuRGVuc2U/cXcodCxlKTpXdyh0LGUpLHF3PSh0LGUpPT57bGV0IHI9dC50eXBlLnR5cGVJZFRvQ2hpbGRJbmRleFt0LnR5cGVJZHNbZV1dLG49dC5jaGlsZHJlbltyXTtyZXR1cm4gUmUudmlzaXQobix0LnZhbHVlT2Zmc2V0c1tlXSl9LFd3PSh0LGUpPT57bGV0IHI9dC50eXBlLnR5cGVJZFRvQ2hpbGRJbmRleFt0LnR5cGVJZHNbZV1dLG49dC5jaGlsZHJlbltyXTtyZXR1cm4gUmUudmlzaXQobixlKX0sb1Q9KHQsZSk9Pnt2YXIgcjtyZXR1cm4ocj10LmRpY3Rpb25hcnkpPT09bnVsbHx8cj09PXZvaWQgMD92b2lkIDA6ci5nZXQodC52YWx1ZXNbZV0pfSxhVD0odCxlKT0+dC50eXBlLnVuaXQ9PT1qdC5NT05USF9EQVlfTkFOTz9Ldyh0LGUpOnQudHlwZS51bml0PT09anQuREFZX1RJTUU/SHcodCxlKTpZdyh0LGUpLEh3PSh7dmFsdWVzOnR9LGUpPT50LnN1YmFycmF5KDIqZSwyKihlKzEpKSxZdz0oe3ZhbHVlczp0fSxlKT0+e2xldCByPXRbZV0sbj1uZXcgSW50MzJBcnJheSgyKTtyZXR1cm4gblswXT1NYXRoLnRydW5jKHIvMTIpLG5bMV09TWF0aC50cnVuYyhyJTEyKSxufSxLdz0oe3ZhbHVlczp0fSxlKT0+dC5zdWJhcnJheSg0KmUsNCooZSsxKSksR3c9KHt2YWx1ZXM6dH0sZSk9PnRbZV0sSnc9KHt2YWx1ZXM6dH0sZSk9PnRbZV0sWHc9KHt2YWx1ZXM6dH0sZSk9PnRbZV0sWnc9KHt2YWx1ZXM6dH0sZSk9PnRbZV0sY1Q9KHQsZSk9Pntzd2l0Y2godC50eXBlLnVuaXQpe2Nhc2UgVC5TRUNPTkQ6cmV0dXJuIEd3KHQsZSk7Y2FzZSBULk1JTExJU0VDT05EOnJldHVybiBKdyh0LGUpO2Nhc2UgVC5NSUNST1NFQ09ORDpyZXR1cm4gWHcodCxlKTtjYXNlIFQuTkFOT1NFQ09ORDpyZXR1cm4gWncodCxlKX19LGxUPSh0LGUpPT57bGV0e3N0cmlkZTpyLGNoaWxkcmVuOm59PXQscz1uWzBdLnNsaWNlKGUqcixyKTtyZXR1cm4gbmV3IE4oW3NdKX0sUmU7dmFyIHVhPW0oKCk9PntUbSgpO1FyKCk7VWkoKTtVZigpO1BtKCk7dnMoKTtQbCgpO0xlKCk7cT1jbGFzcyBxIGV4dGVuZHMgZXR7fTtxLnByb3RvdHlwZS52aXNpdE51bGw9cnQocXgpO3EucHJvdG90eXBlLnZpc2l0Qm9vbD1ydChXeCk7cS5wcm90b3R5cGUudmlzaXRJbnQ9cnQoSngpO3EucHJvdG90eXBlLnZpc2l0SW50OD1ydChJbyk7cS5wcm90b3R5cGUudmlzaXRJbnQxNj1ydChJbyk7cS5wcm90b3R5cGUudmlzaXRJbnQzMj1ydChJbyk7cS5wcm90b3R5cGUudmlzaXRJbnQ2ND1ydChGdyk7cS5wcm90b3R5cGUudmlzaXRVaW50OD1ydChJbyk7cS5wcm90b3R5cGUudmlzaXRVaW50MTY9cnQoSW8pO3EucHJvdG90eXBlLnZpc2l0VWludDMyPXJ0KElvKTtxLnByb3RvdHlwZS52aXNpdFVpbnQ2ND1ydChGdyk7cS5wcm90b3R5cGUudmlzaXRGbG9hdD1ydChYeCk7cS5wcm90b3R5cGUudmlzaXRGbG9hdDE2PXJ0KEh4KTtxLnByb3RvdHlwZS52aXNpdEZsb2F0MzI9cnQoSW8pO3EucHJvdG90eXBlLnZpc2l0RmxvYXQ2ND1ydChJbyk7cS5wcm90b3R5cGUudmlzaXRVdGY4PXJ0KFV3KTtxLnByb3RvdHlwZS52aXNpdExhcmdlVXRmOD1ydChVdyk7cS5wcm90b3R5cGUudmlzaXRVdGY4Vmlldz1ydChHeCk7cS5wcm90b3R5cGUudmlzaXRCaW5hcnk9cnQoTXcpO3EucHJvdG90eXBlLnZpc2l0TGFyZ2VCaW5hcnk9cnQoTXcpO3EucHJvdG90eXBlLnZpc2l0QmluYXJ5Vmlldz1ydChLeCk7cS5wcm90b3R5cGUudmlzaXRGaXhlZFNpemVCaW5hcnk9cnQoWXgpO3EucHJvdG90eXBlLnZpc2l0RGF0ZT1ydChaeCk7cS5wcm90b3R5cGUudmlzaXREYXRlRGF5PXJ0KE93KTtxLnByb3RvdHlwZS52aXNpdERhdGVNaWxsaXNlY29uZD1ydChOdyk7cS5wcm90b3R5cGUudmlzaXRUaW1lc3RhbXA9cnQoUXgpO3EucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wU2Vjb25kPXJ0KFJ3KTtxLnByb3RvdHlwZS52aXNpdFRpbWVzdGFtcE1pbGxpc2Vjb25kPXJ0KEN3KTtxLnByb3RvdHlwZS52aXNpdFRpbWVzdGFtcE1pY3Jvc2Vjb25kPXJ0KFB3KTtxLnByb3RvdHlwZS52aXNpdFRpbWVzdGFtcE5hbm9zZWNvbmQ9cnQoa3cpO3EucHJvdG90eXBlLnZpc2l0VGltZT1ydCh0VCk7cS5wcm90b3R5cGUudmlzaXRUaW1lU2Vjb25kPXJ0KFZ3KTtxLnByb3RvdHlwZS52aXNpdFRpbWVNaWxsaXNlY29uZD1ydCh6dyk7cS5wcm90b3R5cGUudmlzaXRUaW1lTWljcm9zZWNvbmQ9cnQoancpO3EucHJvdG90eXBlLnZpc2l0VGltZU5hbm9zZWNvbmQ9cnQoJHcpO3EucHJvdG90eXBlLnZpc2l0RGVjaW1hbD1ydChlVCk7cS5wcm90b3R5cGUudmlzaXRMaXN0PXJ0KHJUKTtxLnByb3RvdHlwZS52aXNpdFN0cnVjdD1ydChpVCk7cS5wcm90b3R5cGUudmlzaXRVbmlvbj1ydChzVCk7cS5wcm90b3R5cGUudmlzaXREZW5zZVVuaW9uPXJ0KHF3KTtxLnByb3RvdHlwZS52aXNpdFNwYXJzZVVuaW9uPXJ0KFd3KTtxLnByb3RvdHlwZS52aXNpdERpY3Rpb25hcnk9cnQob1QpO3EucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWw9cnQoYVQpO3EucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWxEYXlUaW1lPXJ0KEh3KTtxLnByb3RvdHlwZS52aXNpdEludGVydmFsWWVhck1vbnRoPXJ0KFl3KTtxLnByb3RvdHlwZS52aXNpdEludGVydmFsTW9udGhEYXlOYW5vPXJ0KEt3KTtxLnByb3RvdHlwZS52aXNpdER1cmF0aW9uPXJ0KGNUKTtxLnByb3RvdHlwZS52aXNpdER1cmF0aW9uU2Vjb25kPXJ0KEd3KTtxLnByb3RvdHlwZS52aXNpdER1cmF0aW9uTWlsbGlzZWNvbmQ9cnQoSncpO3EucHJvdG90eXBlLnZpc2l0RHVyYXRpb25NaWNyb3NlY29uZD1ydChYdyk7cS5wcm90b3R5cGUudmlzaXREdXJhdGlvbk5hbm9zZWNvbmQ9cnQoWncpO3EucHJvdG90eXBlLnZpc2l0Rml4ZWRTaXplTGlzdD1ydChsVCk7cS5wcm90b3R5cGUudmlzaXRNYXA9cnQoblQpO1JlPW5ldyBxfSk7Y2xhc3MgdHZ7aXNFeHRlbnNpYmxlKCl7cmV0dXJuITF9ZGVsZXRlUHJvcGVydHkoKXtyZXR1cm4hMX1wcmV2ZW50RXh0ZW5zaW9ucygpe3JldHVybiEwfW93bktleXModCl7cmV0dXJuIHRbeWNdfWhhcyh0LGUpe3JldHVybiB0W3ljXS5pbmNsdWRlcyhlKX1nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodCxlKXtpZih0W3ljXS5pbmRleE9mKGUpIT09LTEpcmV0dXJue3dyaXRhYmxlOiEwLGVudW1lcmFibGU6ITAsY29uZmlndXJhYmxlOiEwfTtyZXR1cm59Z2V0KHQsZSl7aWYoUmVmbGVjdC5oYXModCxlKSlyZXR1cm4gdFtlXTtsZXQgcj10W3ljXS5pbmRleE9mKGUpO2lmKHIhPT0tMSl7bGV0IG49UmUudmlzaXQoUmVmbGVjdC5nZXQodCxfYykscik7cmV0dXJuIFJlZmxlY3Quc2V0KHQsZSxuKSxufX1zZXQodCxlLHIpe2xldCBuPXRbeWNdLmluZGV4T2YoZSk7aWYobiE9PS0xKXJldHVybiBkci52aXNpdChSZWZsZWN0LmdldCh0LF9jKSxuLHIpLFJlZmxlY3Quc2V0KHQsZSxyKTtlbHNlIGlmKFJlZmxlY3QuaGFzKHQsZSkpcmV0dXJuIFJlZmxlY3Quc2V0KHQsZSxyKTtyZXR1cm4hMX19dmFyIEJvLF9jLHljLGttLEJzLFF3O3ZhciBVZj1tKCgpPT57UXIoKTt1YSgpO1NuKCk7Qm89U3ltYm9sLmZvcigia2V5cyIpLF9jPVN5bWJvbC5mb3IoInZhbHMiKSx5Yz1TeW1ib2wuZm9yKCJrS2V5c0FzU3RyaW5ncyIpLGttPVN5bWJvbC5mb3IoIl9rS2V5c0FzU3RyaW5ncyIpO0JzPWNsYXNzIEJze2NvbnN0cnVjdG9yKHQpe3JldHVybiB0aGlzW0JvXT1uZXcgTihbdC5jaGlsZHJlblswXV0pLm1lbW9pemUoKSx0aGlzW19jXT10LmNoaWxkcmVuWzFdLG5ldyBQcm94eSh0aGlzLG5ldyB0dil9Z2V0W3ljXSgpe3JldHVybiB0aGlzW2ttXXx8KHRoaXNba21dPUFycmF5LmZyb20odGhpc1tCb10udG9BcnJheSgpLFN0cmluZykpfVtTeW1ib2wuaXRlcmF0b3JdKCl7cmV0dXJuIG5ldyBRdyh0aGlzW0JvXSx0aGlzW19jXSl9Z2V0IHNpemUoKXtyZXR1cm4gdGhpc1tCb10ubGVuZ3RofXRvQXJyYXkoKXtyZXR1cm4gT2JqZWN0LnZhbHVlcyh0aGlzLnRvSlNPTigpKX10b0pTT04oKXtsZXQgdD10aGlzW0JvXSxlPXRoaXNbX2NdLHI9e307Zm9yKGxldCBuPS0xLGk9dC5sZW5ndGg7KytuPGk7KXJbdC5nZXQobildPVJlLnZpc2l0KGUsbik7cmV0dXJuIHJ9dG9TdHJpbmcoKXtyZXR1cm5geyR7Wy4uLnRoaXNdLm1hcCgoW3QsZV0pPT5gJHtCaSh0KX06ICR7QmkoZSl9YCkuam9pbigiLCAiKX19YH1bU3ltYm9sLmZvcigibm9kZWpzLnV0aWwuaW5zcGVjdC5jdXN0b20iKV0oKXtyZXR1cm4gdGhpcy50b1N0cmluZygpfX07UXc9Y2xhc3MgUXd7Y29uc3RydWN0b3IodCxlKXt0aGlzLmtleXM9dCx0aGlzLnZhbHM9ZSx0aGlzLmtleUluZGV4PTAsdGhpcy5udW1LZXlzPXQubGVuZ3RofVtTeW1ib2wuaXRlcmF0b3JdKCl7cmV0dXJuIHRoaXN9bmV4dCgpe2xldCB0PXRoaXMua2V5SW5kZXg7aWYodD09PXRoaXMubnVtS2V5cylyZXR1cm57ZG9uZTohMCx2YWx1ZTpudWxsfTtyZXR1cm4gdGhpcy5rZXlJbmRleCsrLHtkb25lOiExLHZhbHVlOlt0aGlzLmtleXMuZ2V0KHQpLFJlLnZpc2l0KHRoaXMudmFscyx0KV19fX07T2JqZWN0LmRlZmluZVByb3BlcnRpZXMoQnMucHJvdG90eXBlLHtbU3ltYm9sLnRvU3RyaW5nVGFnXTp7ZW51bWVyYWJsZTohMSxjb25maWd1cmFibGU6ITEsdmFsdWU6IlJvdyJ9LFtCb106e3dyaXRhYmxlOiEwLGVudW1lcmFibGU6ITEsY29uZmlndXJhYmxlOiExLHZhbHVlOm51bGx9LFtfY106e3dyaXRhYmxlOiEwLGVudW1lcmFibGU6ITEsY29uZmlndXJhYmxlOiExLHZhbHVlOm51bGx9LFtrbV06e3dyaXRhYmxlOiEwLGVudW1lcmFibGU6ITEsY29uZmlndXJhYmxlOiExLHZhbHVlOm51bGx9fSl9KTt2YXIgVm09e307WmUoVm0se2NsYW1wUmFuZ2U6KCk9PmtsLGNyZWF0ZUVsZW1lbnRDb21wYXJhdG9yOigpPT5Tbyx3cmFwSW5kZXg6KCk9PmZhfSk7ZnVuY3Rpb24ga2wodCxlLHIsbil7bGV0e2xlbmd0aDppPTB9PXQscz10eXBlb2YgZSE9PSJudW1iZXIiPzA6ZSxvPXR5cGVvZiByIT09Im51bWJlciI/aTpyO3JldHVybiBzPDAmJihzPShzJWkraSklaSksbzwwJiYobz0obyVpK2kpJWkpLG88cyYmKGV2PXMscz1vLG89ZXYpLG8+aSYmKG89aSksbj9uKHQscyxvKTpbcyxvXX1mdW5jdGlvbiBTbyh0KXtpZih0eXBlb2YgdCE9PSJvYmplY3QifHx0PT09bnVsbCl7aWYocnYodCkpcmV0dXJuIHJ2O3JldHVybihyKT0+cj09PXR9aWYodCBpbnN0YW5jZW9mIERhdGUpe2xldCByPXQudmFsdWVPZigpO3JldHVybihuKT0+biBpbnN0YW5jZW9mIERhdGU/bi52YWx1ZU9mKCk9PT1yOiExfWlmKEFycmF5QnVmZmVyLmlzVmlldyh0KSlyZXR1cm4ocik9PnI/WXAodCxyKTohMTtpZih0IGluc3RhbmNlb2YgTWFwKXJldHVybiBmVCh0KTtpZihBcnJheS5pc0FycmF5KHQpKXJldHVybiB1VCh0KTtpZih0IGluc3RhbmNlb2YgTilyZXR1cm4gZFQodCk7cmV0dXJuIGhUKHQsITApfWZ1bmN0aW9uIHVUKHQpe2xldCBlPVtdO2ZvcihsZXQgcj0tMSxuPXQubGVuZ3RoOysrcjxuOyllW3JdPVNvKHRbcl0pO3JldHVybiBSZihlKX1mdW5jdGlvbiBmVCh0KXtsZXQgZT0tMSxyPVtdO2ZvcihsZXQgbiBvZiB0LnZhbHVlcygpKXJbKytlXT1TbyhuKTtyZXR1cm4gUmYocil9ZnVuY3Rpb24gZFQodCl7bGV0IGU9W107Zm9yKGxldCByPS0xLG49dC5sZW5ndGg7KytyPG47KWVbcl09U28odC5nZXQocikpO3JldHVybiBSZihlKX1mdW5jdGlvbiBoVCh0LGU9ITEpe2xldCByPU9iamVjdC5rZXlzKHQpO2lmKCFlJiZyLmxlbmd0aD09PTApcmV0dXJuKCk9PiExO2xldCBuPVtdO2ZvcihsZXQgaT0tMSxzPXIubGVuZ3RoOysraTxzOyluW2ldPVNvKHRbcltpXV0pO3JldHVybiBSZihuLHIpfWZ1bmN0aW9uIFJmKHQsZSl7cmV0dXJuKHIpPT57aWYoIXJ8fHR5cGVvZiByIT09Im9iamVjdCIpcmV0dXJuITE7c3dpdGNoKHIuY29uc3RydWN0b3Ipe2Nhc2UgQXJyYXk6cmV0dXJuIHBUKHQscik7Y2FzZSBNYXA6cmV0dXJuIG52KHQscixyLmtleXMoKSk7Y2FzZSBCczpjYXNlIGxhOmNhc2UgT2JqZWN0OmNhc2Ugdm9pZCAwOnJldHVybiBudih0LHIsZXx8T2JqZWN0LmtleXMocikpfXJldHVybiByIGluc3RhbmNlb2YgTj9tVCh0LHIpOiExfX1mdW5jdGlvbiBwVCh0LGUpe2xldCByPXQubGVuZ3RoO2lmKGUubGVuZ3RoIT09cilyZXR1cm4hMTtmb3IobGV0IG49LTE7KytuPHI7KWlmKCF0W25dKGVbbl0pKXJldHVybiExO3JldHVybiEwfWZ1bmN0aW9uIG1UKHQsZSl7bGV0IHI9dC5sZW5ndGg7aWYoZS5sZW5ndGghPT1yKXJldHVybiExO2ZvcihsZXQgbj0tMTsrK248cjspaWYoIXRbbl0oZS5nZXQobikpKXJldHVybiExO3JldHVybiEwfWZ1bmN0aW9uIG52KHQsZSxyKXtsZXQgbj1yW1N5bWJvbC5pdGVyYXRvcl0oKSxpPWUgaW5zdGFuY2VvZiBNYXA/ZS5rZXlzKCk6T2JqZWN0LmtleXMoZSlbU3ltYm9sLml0ZXJhdG9yXSgpLHM9ZSBpbnN0YW5jZW9mIE1hcD9lLnZhbHVlcygpOk9iamVjdC52YWx1ZXMoZSlbU3ltYm9sLml0ZXJhdG9yXSgpLG89MCxhPXQubGVuZ3RoLGw9cy5uZXh0KCksdT1uLm5leHQoKSxmPWkubmV4dCgpO2Zvcig7bzxhJiYhdS5kb25lJiYhZi5kb25lJiYhbC5kb25lOysrbyx1PW4ubmV4dCgpLGY9aS5uZXh0KCksbD1zLm5leHQoKSlpZih1LnZhbHVlIT09Zi52YWx1ZXx8IXRbb10obC52YWx1ZSkpYnJlYWs7aWYobz09PWEmJnUuZG9uZSYmZi5kb25lJiZsLmRvbmUpcmV0dXJuITA7cmV0dXJuIG4ucmV0dXJuJiZuLnJldHVybigpLGkucmV0dXJuJiZpLnJldHVybigpLHMucmV0dXJuJiZzLnJldHVybigpLCExfXZhciBldixmYT0odCxlKT0+dDwwP2UrdDp0LHJ2PSh0KT0+dCE9PXQ7dmFyIGdjPW0oKCk9PntRcigpO1VmKCk7UG0oKTtqZSgpfSk7dmFyIHptPXt9O1plKHptLHtCaXRJdGVyYXRvcjooKT0+YmMsZ2V0Qml0OigpPT5pdixnZXRCb29sOigpPT5QZixwYWNrQm9vbHM6KCk9PmhhLHBvcGNudF9hcnJheTooKT0+c3YscG9wY250X2JpdF9yYW5nZTooKT0+VmwscG9wY250X3VpbnQzMjooKT0+Q2Ysc2V0Qm9vbDooKT0+eVQsdHJ1bmNhdGVCaXRtYXA6KCk9PmRhfSk7ZnVuY3Rpb24gUGYodCxlLHIsbil7cmV0dXJuKHImMTw8bikhPT0wfWZ1bmN0aW9uIGl2KHQsZSxyLG4pe3JldHVybihyJjE8PG4pPj5ufWZ1bmN0aW9uIHlUKHQsZSxyKXtyZXR1cm4gcj8hISh0W2U+PjNdfD0xPDxlJTgpfHwhMDohKHRbZT4+M10mPX4oMTw8ZSU4KSkmJiExfWZ1bmN0aW9uIGRhKHQsZSxyKXtsZXQgbj1yLmJ5dGVMZW5ndGgrNyYtODtpZih0PjB8fHIuYnl0ZUxlbmd0aDxuKXtsZXQgaT1uZXcgVWludDhBcnJheShuKTtyZXR1cm4gaS5zZXQodCU4PT09MD9yLnN1YmFycmF5KHQ+PjMpOmhhKG5ldyBiYyhyLHQsZSxudWxsLFBmKSkuc3ViYXJyYXkoMCxuKSksaX1yZXR1cm4gcn1mdW5jdGlvbiBoYSh0KXtsZXQgZT1bXSxyPTAsbj0wLGk9MDtmb3IobGV0IG8gb2YgdClpZihvJiYoaXw9MTw8biksKytuPT09OCllW3IrK109aSxpPW49MDtpZihyPT09MHx8bj4wKWVbcisrXT1pO2xldCBzPW5ldyBVaW50OEFycmF5KGUubGVuZ3RoKzcmLTgpO3JldHVybiBzLnNldChlKSxzfWZ1bmN0aW9uIFZsKHQsZSxyKXtpZihyLWU8PTApcmV0dXJuIDA7aWYoci1lPDgpe2xldCBzPTA7Zm9yKGxldCBvIG9mIG5ldyBiYyh0LGUsci1lLHQsaXYpKXMrPW87cmV0dXJuIHN9bGV0IG49cj4+Mzw8MyxpPWUrKGUlOD09PTA/MDo4LWUlOCk7cmV0dXJuIFZsKHQsZSxpKStWbCh0LG4scikrc3YodCxpPj4zLG4taT4+Myl9ZnVuY3Rpb24gc3YodCxlLHIpe2xldCBuPTAsaT1NYXRoLnRydW5jKGUpLHM9bmV3IERhdGFWaWV3KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCx0LmJ5dGVMZW5ndGgpLG89cj09PXZvaWQgMD90LmJ5dGVMZW5ndGg6aStyO3doaWxlKG8taT49NCluKz1DZihzLmdldFVpbnQzMihpKSksaSs9NDt3aGlsZShvLWk+PTIpbis9Q2Yocy5nZXRVaW50MTYoaSkpLGkrPTI7d2hpbGUoby1pPj0xKW4rPUNmKHMuZ2V0VWludDgoaSkpLGkrPTE7cmV0dXJuIG59ZnVuY3Rpb24gQ2YodCl7bGV0IGU9TWF0aC50cnVuYyh0KTtyZXR1cm4gZT1lLShlPj4+MSYxNDMxNjU1NzY1KSxlPShlJjg1ODk5MzQ1OSkrKGU+Pj4yJjg1ODk5MzQ1OSksKGUrKGU+Pj40KSYyNTI2NDUxMzUpKjE2ODQzMDA5Pj4+MjR9dmFyIGJjO3ZhciB3Yz1tKCgpPT57YmM9Y2xhc3MgYmN7Y29uc3RydWN0b3IodCxlLHIsbixpKXt0aGlzLmJ5dGVzPXQsdGhpcy5sZW5ndGg9cix0aGlzLmNvbnRleHQ9bix0aGlzLmdldD1pLHRoaXMuYml0PWUlOCx0aGlzLmJ5dGVJbmRleD1lPj4zLHRoaXMuYnl0ZT10W3RoaXMuYnl0ZUluZGV4KytdLHRoaXMuaW5kZXg9MH1uZXh0KCl7aWYodGhpcy5pbmRleDx0aGlzLmxlbmd0aCl7aWYodGhpcy5iaXQ9PT04KXRoaXMuYml0PTAsdGhpcy5ieXRlPXRoaXMuYnl0ZXNbdGhpcy5ieXRlSW5kZXgrK107cmV0dXJue3ZhbHVlOnRoaXMuZ2V0KHRoaXMuY29udGV4dCx0aGlzLmluZGV4KyssdGhpcy5ieXRlLHRoaXMuYml0KyspfX1yZXR1cm57ZG9uZTohMCx2YWx1ZTpudWxsfX1bU3ltYm9sLml0ZXJhdG9yXSgpe3JldHVybiB0aGlzfX19KTtjbGFzcyBwdHtzdGF0aWMgaXNEYXRhKHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dFtvdl0pPT09ITB9Z2V0IHR5cGVJZCgpe3JldHVybiB0aGlzLnR5cGUudHlwZUlkfWdldCBBcnJheVR5cGUoKXtyZXR1cm4gdGhpcy50eXBlLkFycmF5VHlwZX1nZXQgYnVmZmVycygpe3JldHVyblt0aGlzLnZhbHVlT2Zmc2V0cyx0aGlzLnZhbHVlcyx0aGlzLm51bGxCaXRtYXAsdGhpcy50eXBlSWRzXX1nZXQgbnVsbGFibGUoKXtpZih0aGlzLl9udWxsQ291bnQhPT0wKXtsZXR7dHlwZTp0fT10aGlzO2lmKEIuaXNTcGFyc2VVbmlvbih0KSlyZXR1cm4gdGhpcy5jaGlsZHJlbi5zb21lKChlKT0+ZS5udWxsYWJsZSk7ZWxzZSBpZihCLmlzRGVuc2VVbmlvbih0KSlyZXR1cm4gdGhpcy5jaGlsZHJlbi5zb21lKChlKT0+ZS5udWxsYWJsZSk7cmV0dXJuIHRoaXMubnVsbEJpdG1hcCYmdGhpcy5udWxsQml0bWFwLmJ5dGVMZW5ndGg+MH1yZXR1cm4hMH1nZXQgYnl0ZUxlbmd0aCgpe2xldCB0PTAse3ZhbHVlT2Zmc2V0czplLHZhbHVlczpyLG51bGxCaXRtYXA6bix0eXBlSWRzOml9PXRoaXM7cmV0dXJuIGUmJih0Kz1lLmJ5dGVMZW5ndGgpLHImJih0Kz1yLmJ5dGVMZW5ndGgpLG4mJih0Kz1uLmJ5dGVMZW5ndGgpLGkmJih0Kz1pLmJ5dGVMZW5ndGgpLHQrPXRoaXMudmFyaWFkaWNCdWZmZXJzLnJlZHVjZSgocyxvKT0+e3ZhciBhO3JldHVybiBzKygoYT1vPT09bnVsbHx8bz09PXZvaWQgMD92b2lkIDA6by5ieXRlTGVuZ3RoKSE9PW51bGwmJmEhPT12b2lkIDA/YTowKX0sMCksdGhpcy5jaGlsZHJlbi5yZWR1Y2UoKHMsbyk9PnMrby5ieXRlTGVuZ3RoLHQpfWdldCBudWxsQ291bnQoKXtpZihCLmlzVW5pb24odGhpcy50eXBlKSlyZXR1cm4gdGhpcy5jaGlsZHJlbi5yZWR1Y2UoKHIsbik9PnIrbi5udWxsQ291bnQsMCk7bGV0IHQ9dGhpcy5fbnVsbENvdW50LGU7aWYodDw9X1QmJihlPXRoaXMubnVsbEJpdG1hcCkpdGhpcy5fbnVsbENvdW50PXQ9ZS5sZW5ndGg9PT0wPzA6dGhpcy5sZW5ndGgtVmwoZSx0aGlzLm9mZnNldCx0aGlzLm9mZnNldCt0aGlzLmxlbmd0aCk7cmV0dXJuIHR9Y29uc3RydWN0b3IodCxlLHIsbixpLHM9W10sbyxhPVtdKXt2YXIgbDt0aGlzLnR5cGU9dCx0aGlzLmNoaWxkcmVuPXMsdGhpcy5kaWN0aW9uYXJ5PW8sdGhpcy5vZmZzZXQ9TWF0aC5mbG9vcihNYXRoLm1heChlfHwwLDApKSx0aGlzLmxlbmd0aD1NYXRoLmZsb29yKE1hdGgubWF4KHJ8fDAsMCkpLHRoaXMuX251bGxDb3VudD1NYXRoLmZsb29yKE1hdGgubWF4KG58fDAsLTEpKTtsZXQgdTtpZihpIGluc3RhbmNlb2YgcHQpdGhpcy5zdHJpZGU9aS5zdHJpZGUsdGhpcy52YWx1ZXM9aS52YWx1ZXMsdGhpcy50eXBlSWRzPWkudHlwZUlkcyx0aGlzLm51bGxCaXRtYXA9aS5udWxsQml0bWFwLHRoaXMudmFsdWVPZmZzZXRzPWkudmFsdWVPZmZzZXRzLHRoaXMudmFyaWFkaWNCdWZmZXJzPWkudmFyaWFkaWNCdWZmZXJzO2Vsc2V7aWYodGhpcy5zdHJpZGU9Qm4odCksaSkodT1pWzBdKSYmKHRoaXMudmFsdWVPZmZzZXRzPXUpLCh1PWlbMV0pJiYodGhpcy52YWx1ZXM9dSksKHU9aVsyXSkmJih0aGlzLm51bGxCaXRtYXA9dSksKHU9aVszXSkmJih0aGlzLnR5cGVJZHM9dSk7dGhpcy52YXJpYWRpY0J1ZmZlcnM9YX0obD10aGlzLnZhcmlhZGljQnVmZmVycykhPT1udWxsJiZsIT09dm9pZCAwfHwodGhpcy52YXJpYWRpY0J1ZmZlcnM9W10pfWdldFZhbGlkKHQpe2xldHt0eXBlOmV9PXRoaXM7aWYoQi5pc1VuaW9uKGUpKXtsZXQgcj1lLG49dGhpcy50eXBlSWRzW3RdLGk9ci50eXBlSWRUb0NoaWxkSW5kZXhbbl0scz10aGlzLmNoaWxkcmVuW2ldLG89dGhpcy52YWx1ZU9mZnNldHMsYT1yLm1vZGU9PT1MdC5EZW5zZSYmbz9OdW1iZXIob1t0XSk6dDtyZXR1cm4gcy5nZXRWYWxpZChhKX1pZih0aGlzLm51bGxhYmxlJiZ0aGlzLm51bGxDb3VudD4wKXtsZXQgcj10aGlzLm9mZnNldCt0O3JldHVybih0aGlzLm51bGxCaXRtYXBbcj4+M10mMTw8ciU4KSE9PTB9cmV0dXJuITB9c2V0VmFsaWQodCxlKXtsZXQgcix7dHlwZTpufT10aGlzO2lmKEIuaXNVbmlvbihuKSl7bGV0IGk9bixzPXRoaXMudHlwZUlkc1t0XSxvPWkudHlwZUlkVG9DaGlsZEluZGV4W3NdLGE9dGhpcy5jaGlsZHJlbltvXSxsPXRoaXMudmFsdWVPZmZzZXRzLHU9aS5tb2RlPT09THQuRGVuc2UmJmw/TnVtYmVyKGxbdF0pOnQ7cj1hLmdldFZhbGlkKHUpLGEuc2V0VmFsaWQodSxlKX1lbHNle2xldHtudWxsQml0bWFwOml9PXRoaXMse29mZnNldDpzLGxlbmd0aDpvfT10aGlzLGE9cyt0LGw9MTw8YSU4LHU9YT4+MztpZighaXx8aS5ieXRlTGVuZ3RoPD11KWlmKGk9bmV3IFVpbnQ4QXJyYXkoKHMrbys2MyYtNjQpPj4zKS5maWxsKDI1NSksdGhpcy5udWxsQ291bnQ+MClpLnNldChkYShzLG8sdGhpcy5udWxsQml0bWFwKSwwKSxPYmplY3QuYXNzaWduKHRoaXMse251bGxCaXRtYXA6aX0pO2Vsc2UgT2JqZWN0LmFzc2lnbih0aGlzLHtudWxsQml0bWFwOmksX251bGxDb3VudDowfSk7bGV0IGY9aVt1XTtyPShmJmwpIT09MCxpW3VdPWU/ZnxsOmYmfmx9aWYociE9PSEhZSl0aGlzLl9udWxsQ291bnQ9dGhpcy5udWxsQ291bnQrKGU/LTE6MSk7cmV0dXJuIGV9Y2xvbmUodD10aGlzLnR5cGUsZT10aGlzLm9mZnNldCxyPXRoaXMubGVuZ3RoLG49dGhpcy5fbnVsbENvdW50LGk9dGhpcyxzPXRoaXMuY2hpbGRyZW4sbz10aGlzLnZhcmlhZGljQnVmZmVycyl7cmV0dXJuIG5ldyBwdCh0LGUscixuLGkscyx0aGlzLmRpY3Rpb25hcnksbyl9c2xpY2UodCxlKXtsZXR7c3RyaWRlOnIsdHlwZUlkOm4sY2hpbGRyZW46aX09dGhpcyxzPSsodGhpcy5fbnVsbENvdW50PT09MCktMSxvPW49PT0xNj9yOjEsYT10aGlzLl9zbGljZUJ1ZmZlcnModCxlLHIsbik7cmV0dXJuIHRoaXMuY2xvbmUodGhpcy50eXBlLHRoaXMub2Zmc2V0K3QsZSxzLGEsaS5sZW5ndGg9PT0wfHx0aGlzLnZhbHVlT2Zmc2V0cz9pOnRoaXMuX3NsaWNlQ2hpbGRyZW4oaSxvKnQsbyplKSx0aGlzLnZhcmlhZGljQnVmZmVycyl9X2NoYW5nZUxlbmd0aEFuZEJhY2tmaWxsTnVsbEJpdG1hcCh0KXtpZih0aGlzLnR5cGVJZD09PV8uTnVsbClyZXR1cm4gdGhpcy5jbG9uZSh0aGlzLnR5cGUsMCx0LDAsdGhpcy5idWZmZXJzLHRoaXMuY2hpbGRyZW4sdGhpcy52YXJpYWRpY0J1ZmZlcnMpO2xldHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcyxuPW5ldyBVaW50OEFycmF5KCh0KzYzJi02NCk+PjMpLmZpbGwoMjU1LDAsZT4+Myk7aWYobltlPj4zXT0oMTw8ZS0oZSYtOCkpLTEscj4wKW4uc2V0KGRhKHRoaXMub2Zmc2V0LGUsdGhpcy5udWxsQml0bWFwKSwwKTtsZXQgaT10aGlzLmJ1ZmZlcnM7cmV0dXJuIGlbWnIuVkFMSURJVFldPW4sdGhpcy5jbG9uZSh0aGlzLnR5cGUsMCx0LHIrKHQtZSksaSx0aGlzLmNoaWxkcmVuLHRoaXMudmFyaWFkaWNCdWZmZXJzKX1fc2xpY2VCdWZmZXJzKHQsZSxyLG4pe2xldCBpLHtidWZmZXJzOnN9PXRoaXM7aWYoKGk9c1taci5UWVBFXSkmJihzW1pyLlRZUEVdPWkuc3ViYXJyYXkodCx0K2UpKSxCLmlzQmluYXJ5Vmlldyh0aGlzLnR5cGUpfHxCLmlzVXRmOFZpZXcodGhpcy50eXBlKSl7bGV0IG89X3QuRUxFTUVOVF9XSURUSDsoaT1zW1pyLkRBVEFdKSYmKHNbWnIuREFUQV09aS5zdWJhcnJheSh0Km8sKHQrZSkqbykpfWVsc2UoaT1zW1pyLk9GRlNFVF0pJiYoc1taci5PRkZTRVRdPWkuc3ViYXJyYXkodCx0K2UrMSkpfHwoaT1zW1pyLkRBVEFdKSYmKHNbWnIuREFUQV09bj09PTY/aTppLnN1YmFycmF5KHIqdCxyKih0K2UpKSk7cmV0dXJuIHN9X3NsaWNlQ2hpbGRyZW4odCxlLHIpe3JldHVybiB0Lm1hcCgobik9Pm4uc2xpY2UoZSxyKSl9fWZ1bmN0aW9uIFModCl7cmV0dXJuIGdULnZpc2l0KHQpfXZhciBfVD0tMSxvdix6bCxnVDt2YXIgWG49bSgoKT0+e1FyKCk7TGUoKTtpZSgpO3djKCk7aWUoKTtVaSgpO2plKCk7b3Y9U3ltYm9sLmZvcigiYXBhY2hlLWFycm93L0RhdGEiKTtwdC5wcm90b3R5cGUuY2hpbGRyZW49T2JqZWN0LmZyZWV6ZShbXSk7cHQucHJvdG90eXBlW292XT0hMDtPYmplY3QuZGVmaW5lUHJvcGVydHkocHQsU3ltYm9sLmhhc0luc3RhbmNlLHt2YWx1ZTpmdW5jdGlvbihlKXtyZXR1cm4gRnVuY3Rpb24ucHJvdG90eXBlW1N5bWJvbC5oYXNJbnN0YW5jZV0uY2FsbCh0aGlzLGUpfHx0aGlzPT09cHQmJnB0LmlzRGF0YShlKX19KTt6bD1jbGFzcyB6bCBleHRlbmRzIGV0e3Zpc2l0KHQpe3JldHVybiB0aGlzLmdldFZpc2l0Rm4odC50eXBlKS5jYWxsKHRoaXMsdCl9dmlzaXROdWxsKHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wLFsibGVuZ3RoIl06bj0wfT10O3JldHVybiBuZXcgcHQoZSxyLG4sbil9dmlzaXRCb29sKHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wfT10LG49Qyh0Lm51bGxCaXRtYXApLGk9d3QoZS5BcnJheVR5cGUsdC5kYXRhKSx7WyJsZW5ndGgiXTpzPWkubGVuZ3RoPj4zLFsibnVsbENvdW50Il06bz10Lm51bGxCaXRtYXA/LTE6MH09dDtyZXR1cm4gbmV3IHB0KGUscixzLG8sW3ZvaWQgMCxpLG5dKX12aXNpdEludCh0KXtsZXR7WyJ0eXBlIl06ZSxbIm9mZnNldCJdOnI9MH09dCxuPUModC5udWxsQml0bWFwKSxpPXd0KGUuQXJyYXlUeXBlLHQuZGF0YSkse1sibGVuZ3RoIl06cz1pLmxlbmd0aCxbIm51bGxDb3VudCJdOm89dC5udWxsQml0bWFwPy0xOjB9PXQ7cmV0dXJuIG5ldyBwdChlLHIscyxvLFt2b2lkIDAsaSxuXSl9dmlzaXRGbG9hdCh0KXtsZXR7WyJ0eXBlIl06ZSxbIm9mZnNldCJdOnI9MH09dCxuPUModC5udWxsQml0bWFwKSxpPXd0KGUuQXJyYXlUeXBlLHQuZGF0YSkse1sibGVuZ3RoIl06cz1pLmxlbmd0aCxbIm51bGxDb3VudCJdOm89dC5udWxsQml0bWFwPy0xOjB9PXQ7cmV0dXJuIG5ldyBwdChlLHIscyxvLFt2b2lkIDAsaSxuXSl9dmlzaXRVdGY4KHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wfT10LG49Qyh0LmRhdGEpLGk9Qyh0Lm51bGxCaXRtYXApLHM9b2EodC52YWx1ZU9mZnNldHMpLHtbImxlbmd0aCJdOm89cy5sZW5ndGgtMSxbIm51bGxDb3VudCJdOmE9dC5udWxsQml0bWFwPy0xOjB9PXQ7cmV0dXJuIG5ldyBwdChlLHIsbyxhLFtzLG4saV0pfXZpc2l0VXRmOFZpZXcodCl7dmFyIGU7bGV0e1sidHlwZSJdOnIsWyJvZmZzZXQiXTpuPTB9PXQsaT13dChyLkFycmF5VHlwZSx0LnZpZXdzKSxzPUModC5udWxsQml0bWFwKSxvPSh0LnZhcmlhZGljQnVmZmVyc3x8W10pLm1hcCgodSk9PkModSkpLGE9KGU9dC5sZW5ndGgpIT09bnVsbCYmZSE9PXZvaWQgMD9lOk1hdGgudHJ1bmMoaS5sZW5ndGgvZ24uRUxFTUVOVF9XSURUSCksbD10Lm51bGxCaXRtYXA/LTE6MDtyZXR1cm4gbmV3IHB0KHIsbixhLGwsW3ZvaWQgMCxpLHNdLFtdLHZvaWQgMCxvKX12aXNpdExhcmdlVXRmOCh0KXtsZXR7WyJ0eXBlIl06ZSxbIm9mZnNldCJdOnI9MH09dCxuPUModC5kYXRhKSxpPUModC5udWxsQml0bWFwKSxzPXVmKHQudmFsdWVPZmZzZXRzKSx7WyJsZW5ndGgiXTpvPXMubGVuZ3RoLTEsWyJudWxsQ291bnQiXTphPXQubnVsbEJpdG1hcD8tMTowfT10O3JldHVybiBuZXcgcHQoZSxyLG8sYSxbcyxuLGldKX12aXNpdEJpbmFyeSh0KXtsZXR7WyJ0eXBlIl06ZSxbIm9mZnNldCJdOnI9MH09dCxuPUModC5kYXRhKSxpPUModC5udWxsQml0bWFwKSxzPW9hKHQudmFsdWVPZmZzZXRzKSx7WyJsZW5ndGgiXTpvPXMubGVuZ3RoLTEsWyJudWxsQ291bnQiXTphPXQubnVsbEJpdG1hcD8tMTowfT10O3JldHVybiBuZXcgcHQoZSxyLG8sYSxbcyxuLGldKX12aXNpdEJpbmFyeVZpZXcodCl7dmFyIGU7bGV0e1sidHlwZSJdOnIsWyJvZmZzZXQiXTpuPTB9PXQsaT13dChyLkFycmF5VHlwZSx0LnZpZXdzKSxzPUModC5udWxsQml0bWFwKSxvPSh0LnZhcmlhZGljQnVmZmVyc3x8W10pLm1hcCgodSk9PkModSkpLGE9KGU9dC5sZW5ndGgpIT09bnVsbCYmZSE9PXZvaWQgMD9lOk1hdGgudHJ1bmMoaS5sZW5ndGgvX3QuRUxFTUVOVF9XSURUSCksbD10Lm51bGxCaXRtYXA/LTE6MDtyZXR1cm4gbmV3IHB0KHIsbixhLGwsW3ZvaWQgMCxpLHNdLFtdLHZvaWQgMCxvKX12aXNpdExhcmdlQmluYXJ5KHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wfT10LG49Qyh0LmRhdGEpLGk9Qyh0Lm51bGxCaXRtYXApLHM9dWYodC52YWx1ZU9mZnNldHMpLHtbImxlbmd0aCJdOm89cy5sZW5ndGgtMSxbIm51bGxDb3VudCJdOmE9dC5udWxsQml0bWFwPy0xOjB9PXQ7cmV0dXJuIG5ldyBwdChlLHIsbyxhLFtzLG4saV0pfXZpc2l0Rml4ZWRTaXplQmluYXJ5KHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wfT10LG49Qyh0Lm51bGxCaXRtYXApLGk9d3QoZS5BcnJheVR5cGUsdC5kYXRhKSx7WyJsZW5ndGgiXTpzPWkubGVuZ3RoL0JuKGUpLFsibnVsbENvdW50Il06bz10Lm51bGxCaXRtYXA/LTE6MH09dDtyZXR1cm4gbmV3IHB0KGUscixzLG8sW3ZvaWQgMCxpLG5dKX12aXNpdERhdGUodCl7bGV0e1sidHlwZSJdOmUsWyJvZmZzZXQiXTpyPTB9PXQsbj1DKHQubnVsbEJpdG1hcCksaT13dChlLkFycmF5VHlwZSx0LmRhdGEpLHtbImxlbmd0aCJdOnM9aS5sZW5ndGgvQm4oZSksWyJudWxsQ291bnQiXTpvPXQubnVsbEJpdG1hcD8tMTowfT10O3JldHVybiBuZXcgcHQoZSxyLHMsbyxbdm9pZCAwLGksbl0pfXZpc2l0VGltZXN0YW1wKHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wfT10LG49Qyh0Lm51bGxCaXRtYXApLGk9d3QoZS5BcnJheVR5cGUsdC5kYXRhKSx7WyJsZW5ndGgiXTpzPWkubGVuZ3RoL0JuKGUpLFsibnVsbENvdW50Il06bz10Lm51bGxCaXRtYXA/LTE6MH09dDtyZXR1cm4gbmV3IHB0KGUscixzLG8sW3ZvaWQgMCxpLG5dKX12aXNpdFRpbWUodCl7bGV0e1sidHlwZSJdOmUsWyJvZmZzZXQiXTpyPTB9PXQsbj1DKHQubnVsbEJpdG1hcCksaT13dChlLkFycmF5VHlwZSx0LmRhdGEpLHtbImxlbmd0aCJdOnM9aS5sZW5ndGgvQm4oZSksWyJudWxsQ291bnQiXTpvPXQubnVsbEJpdG1hcD8tMTowfT10O3JldHVybiBuZXcgcHQoZSxyLHMsbyxbdm9pZCAwLGksbl0pfXZpc2l0RGVjaW1hbCh0KXtsZXR7WyJ0eXBlIl06ZSxbIm9mZnNldCJdOnI9MH09dCxuPUModC5udWxsQml0bWFwKSxpPXd0KGUuQXJyYXlUeXBlLHQuZGF0YSkse1sibGVuZ3RoIl06cz1pLmxlbmd0aC9CbihlKSxbIm51bGxDb3VudCJdOm89dC5udWxsQml0bWFwPy0xOjB9PXQ7cmV0dXJuIG5ldyBwdChlLHIscyxvLFt2b2lkIDAsaSxuXSl9dmlzaXRMaXN0KHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wLFsiY2hpbGQiXTpufT10LGk9Qyh0Lm51bGxCaXRtYXApLHM9b2EodC52YWx1ZU9mZnNldHMpLHtbImxlbmd0aCJdOm89cy5sZW5ndGgtMSxbIm51bGxDb3VudCJdOmE9dC5udWxsQml0bWFwPy0xOjB9PXQ7cmV0dXJuIG5ldyBwdChlLHIsbyxhLFtzLHZvaWQgMCxpXSxbbl0pfXZpc2l0U3RydWN0KHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wLFsiY2hpbGRyZW4iXTpuPVtdfT10LGk9Qyh0Lm51bGxCaXRtYXApLHtsZW5ndGg6cz1uLnJlZHVjZSgoYSx7bGVuZ3RoOmx9KT0+TWF0aC5tYXgoYSxsKSwwKSxudWxsQ291bnQ6bz10Lm51bGxCaXRtYXA/LTE6MH09dDtyZXR1cm4gbmV3IHB0KGUscixzLG8sW3ZvaWQgMCx2b2lkIDAsaV0sbil9dmlzaXRVbmlvbih0KXtsZXR7WyJ0eXBlIl06ZSxbIm9mZnNldCJdOnI9MCxbImNoaWxkcmVuIl06bj1bXX09dCxpPXd0KGUuQXJyYXlUeXBlLHQudHlwZUlkcykse1sibGVuZ3RoIl06cz1pLmxlbmd0aCxbIm51bGxDb3VudCJdOm89LTF9PXQ7aWYoQi5pc1NwYXJzZVVuaW9uKGUpKXJldHVybiBuZXcgcHQoZSxyLHMsbyxbdm9pZCAwLHZvaWQgMCx2b2lkIDAsaV0sbik7bGV0IGE9b2EodC52YWx1ZU9mZnNldHMpO3JldHVybiBuZXcgcHQoZSxyLHMsbyxbYSx2b2lkIDAsdm9pZCAwLGldLG4pfXZpc2l0RGljdGlvbmFyeSh0KXtsZXR7WyJ0eXBlIl06ZSxbIm9mZnNldCJdOnI9MH09dCxuPUModC5udWxsQml0bWFwKSxpPXd0KGUuaW5kaWNlcy5BcnJheVR5cGUsdC5kYXRhKSx7WyJkaWN0aW9uYXJ5Il06cz1uZXcgTihbbmV3IHpsKCkudmlzaXQoe3R5cGU6ZS5kaWN0aW9uYXJ5fSldKX09dCx7WyJsZW5ndGgiXTpvPWkubGVuZ3RoLFsibnVsbENvdW50Il06YT10Lm51bGxCaXRtYXA/LTE6MH09dDtyZXR1cm4gbmV3IHB0KGUscixvLGEsW3ZvaWQgMCxpLG5dLFtdLHMpfXZpc2l0SW50ZXJ2YWwodCl7bGV0e1sidHlwZSJdOmUsWyJvZmZzZXQiXTpyPTB9PXQsbj1DKHQubnVsbEJpdG1hcCksaT13dChlLkFycmF5VHlwZSx0LmRhdGEpLHtbImxlbmd0aCJdOnM9aS5sZW5ndGgvQm4oZSksWyJudWxsQ291bnQiXTpvPXQubnVsbEJpdG1hcD8tMTowfT10O3JldHVybiBuZXcgcHQoZSxyLHMsbyxbdm9pZCAwLGksbl0pfXZpc2l0RHVyYXRpb24odCl7bGV0e1sidHlwZSJdOmUsWyJvZmZzZXQiXTpyPTB9PXQsbj1DKHQubnVsbEJpdG1hcCksaT13dChlLkFycmF5VHlwZSx0LmRhdGEpLHtbImxlbmd0aCJdOnM9aS5sZW5ndGgsWyJudWxsQ291bnQiXTpvPXQubnVsbEJpdG1hcD8tMTowfT10O3JldHVybiBuZXcgcHQoZSxyLHMsbyxbdm9pZCAwLGksbl0pfXZpc2l0Rml4ZWRTaXplTGlzdCh0KXtsZXR7WyJ0eXBlIl06ZSxbIm9mZnNldCJdOnI9MCxbImNoaWxkIl06bj1uZXcgemwoKS52aXNpdCh7dHlwZTplLnZhbHVlVHlwZX0pfT10LGk9Qyh0Lm51bGxCaXRtYXApLHtbImxlbmd0aCJdOnM9bi5sZW5ndGgvQm4oZSksWyJudWxsQ291bnQiXTpvPXQubnVsbEJpdG1hcD8tMTowfT10O3JldHVybiBuZXcgcHQoZSxyLHMsbyxbdm9pZCAwLHZvaWQgMCxpXSxbbl0pfXZpc2l0TWFwKHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wLFsiY2hpbGQiXTpuPW5ldyB6bCgpLnZpc2l0KHt0eXBlOmUuY2hpbGRUeXBlfSl9PXQsaT1DKHQubnVsbEJpdG1hcCkscz1vYSh0LnZhbHVlT2Zmc2V0cykse1sibGVuZ3RoIl06bz1zLmxlbmd0aC0xLFsibnVsbENvdW50Il06YT10Lm51bGxCaXRtYXA/LTE6MH09dDtyZXR1cm4gbmV3IHB0KGUscixvLGEsW3Msdm9pZCAwLGldLFtuXSl9fTtnVD1uZXcgemx9KTtmdW5jdGlvbiBhdih0KXtyZXR1cm4gdC5zb21lKChlKT0+ZS5udWxsYWJsZSl9ZnVuY3Rpb24gVmYodCl7cmV0dXJuIHQucmVkdWNlKChlLHIpPT5lK3IubnVsbENvdW50LDApfWZ1bmN0aW9uIHpmKHQpe3JldHVybiB0LnJlZHVjZSgoZSxyLG4pPT4oZVtuKzFdPWVbbl0rci5sZW5ndGgsZSksbmV3IFVpbnQzMkFycmF5KHQubGVuZ3RoKzEpKX1mdW5jdGlvbiBqZih0LGUscixuKXtsZXQgaT1bXTtmb3IobGV0IHM9LTEsbz10Lmxlbmd0aDsrK3M8bzspe2xldCBhPXRbc10sbD1lW3NdLHtsZW5ndGg6dX09YTtpZihsPj1uKWJyZWFrO2lmKHI+PWwrdSljb250aW51ZTtpZihsPj1yJiZsK3U8PW4pe2kucHVzaChhKTtjb250aW51ZX1sZXQgZj1NYXRoLm1heCgwLHItbCkscD1NYXRoLm1pbihuLWwsdSk7aS5wdXNoKGEuc2xpY2UoZixwLWYpKX1pZihpLmxlbmd0aD09PTApaS5wdXNoKHRbMF0uc2xpY2UoMCwwKSk7cmV0dXJuIGl9ZnVuY3Rpb24gam0odCxlLHIsbil7bGV0IGk9MCxzPTAsbz1lLmxlbmd0aC0xO2Rve2lmKGk+PW8tMSlyZXR1cm4gcjxlW29dP24odCxpLHItZVtpXSk6bnVsbDtzPWkrTWF0aC50cnVuYygoby1pKSowLjUpLHI8ZVtzXT9vPXM6aT1zfXdoaWxlKGk8byl9ZnVuY3Rpb24gamwodCxlKXtyZXR1cm4gdC5nZXRWYWxpZChlKX1mdW5jdGlvbiB2Yyh0KXtmdW5jdGlvbiBlKHIsbixpKXtyZXR1cm4gdChyW25dLGkpfXJldHVybiBmdW5jdGlvbihyKXtsZXQgbj10aGlzLmRhdGE7cmV0dXJuIGptKG4sdGhpcy5fb2Zmc2V0cyxyLGUpfX1mdW5jdGlvbiAkZih0KXtsZXQgZTtmdW5jdGlvbiByKG4saSxzKXtyZXR1cm4gdChuW2ldLHMsZSl9cmV0dXJuIGZ1bmN0aW9uKG4saSl7bGV0IHM9dGhpcy5kYXRhO2U9aTtsZXQgbz1qbShzLHRoaXMuX29mZnNldHMsbixyKTtyZXR1cm4gZT12b2lkIDAsb319ZnVuY3Rpb24gcWYodCl7bGV0IGU7ZnVuY3Rpb24gcihuLGkscyl7bGV0IG89cyxhPTAsbD0wO2ZvcihsZXQgdT1pLTEsZj1uLmxlbmd0aDsrK3U8Zjspe2xldCBwPW5bdV07aWYofihhPXQocCxlLG8pKSlyZXR1cm4gbCthO289MCxsKz1wLmxlbmd0aH1yZXR1cm4tMX1yZXR1cm4gZnVuY3Rpb24obixpKXtlPW47bGV0IHM9dGhpcy5kYXRhLG89dHlwZW9mIGkhPT0ibnVtYmVyIj9yKHMsMCwwKTpqbShzLHRoaXMuX29mZnNldHMsaSxyKTtyZXR1cm4gZT12b2lkIDAsb319dmFyIGtmO3ZhciBXZj1tKCgpPT57a2Y9Y2xhc3Mga2Z7Y29uc3RydWN0b3IodD0wLGUpe3RoaXMubnVtQ2h1bmtzPXQsdGhpcy5nZXRDaHVua0l0ZXJhdG9yPWUsdGhpcy5jaHVua0luZGV4PTAsdGhpcy5jaHVua0l0ZXJhdG9yPXRoaXMuZ2V0Q2h1bmtJdGVyYXRvcigwKX1uZXh0KCl7d2hpbGUodGhpcy5jaHVua0luZGV4PHRoaXMubnVtQ2h1bmtzKXtsZXQgdD10aGlzLmNodW5rSXRlcmF0b3IubmV4dCgpO2lmKCF0LmRvbmUpcmV0dXJuIHQ7aWYoKyt0aGlzLmNodW5rSW5kZXg8dGhpcy5udW1DaHVua3MpdGhpcy5jaHVua0l0ZXJhdG9yPXRoaXMuZ2V0Q2h1bmtJdGVyYXRvcih0aGlzLmNodW5rSW5kZXgpfXJldHVybntkb25lOiEwLHZhbHVlOm51bGx9fVtTeW1ib2wuaXRlcmF0b3JdKCl7cmV0dXJuIHRoaXN9fX0pO2Z1bmN0aW9uIGJUKHQsZSl7cmV0dXJuIGU9PT1udWxsJiZ0Lmxlbmd0aD4wPzA6LTF9ZnVuY3Rpb24gd1QodCxlKXtsZXR7bnVsbEJpdG1hcDpyfT10O2lmKCFyfHx0Lm51bGxDb3VudDw9MClyZXR1cm4tMTtsZXQgbj0wO2ZvcihsZXQgaSBvZiBuZXcgYmMocix0Lm9mZnNldCsoZXx8MCksdC5sZW5ndGgscixQZikpe2lmKCFpKXJldHVybiBuOysrbn1yZXR1cm4tMX1mdW5jdGlvbiBmdCh0LGUscil7aWYoZT09PXZvaWQgMClyZXR1cm4tMTtpZihlPT09bnVsbClzd2l0Y2godC50eXBlSWQpe2Nhc2UgXy5VbmlvbjpicmVhaztjYXNlIF8uRGljdGlvbmFyeTpicmVhaztkZWZhdWx0OnJldHVybiB3VCh0LHIpfWxldCBuPVJlLmdldFZpc2l0Rm4odCksaT1TbyhlKTtmb3IobGV0IHM9KHJ8fDApLTEsbz10Lmxlbmd0aDsrK3M8bzspaWYoaShuKHQscykpKXJldHVybiBzO3JldHVybi0xfWZ1bmN0aW9uIGN2KHQsZSxyKXtsZXQgbj1SZS5nZXRWaXNpdEZuKHQpLGk9U28oZSk7Zm9yKGxldCBzPShyfHwwKS0xLG89dC5sZW5ndGg7KytzPG87KWlmKGkobih0LHMpKSlyZXR1cm4gcztyZXR1cm4tMX12YXIgVyxwYTt2YXIgSGY9bSgoKT0+e0xlKCk7VWkoKTt1YSgpO3djKCk7Z2MoKTtXPWNsYXNzIFcgZXh0ZW5kcyBldHt9O1cucHJvdG90eXBlLnZpc2l0TnVsbD1iVDtXLnByb3RvdHlwZS52aXNpdEJvb2w9ZnQ7Vy5wcm90b3R5cGUudmlzaXRJbnQ9ZnQ7Vy5wcm90b3R5cGUudmlzaXRJbnQ4PWZ0O1cucHJvdG90eXBlLnZpc2l0SW50MTY9ZnQ7Vy5wcm90b3R5cGUudmlzaXRJbnQzMj1mdDtXLnByb3RvdHlwZS52aXNpdEludDY0PWZ0O1cucHJvdG90eXBlLnZpc2l0VWludDg9ZnQ7Vy5wcm90b3R5cGUudmlzaXRVaW50MTY9ZnQ7Vy5wcm90b3R5cGUudmlzaXRVaW50MzI9ZnQ7Vy5wcm90b3R5cGUudmlzaXRVaW50NjQ9ZnQ7Vy5wcm90b3R5cGUudmlzaXRGbG9hdD1mdDtXLnByb3RvdHlwZS52aXNpdEZsb2F0MTY9ZnQ7Vy5wcm90b3R5cGUudmlzaXRGbG9hdDMyPWZ0O1cucHJvdG90eXBlLnZpc2l0RmxvYXQ2ND1mdDtXLnByb3RvdHlwZS52aXNpdFV0Zjg9ZnQ7Vy5wcm90b3R5cGUudmlzaXRMYXJnZVV0Zjg9ZnQ7Vy5wcm90b3R5cGUudmlzaXRVdGY4Vmlldz1mdDtXLnByb3RvdHlwZS52aXNpdEJpbmFyeT1mdDtXLnByb3RvdHlwZS52aXNpdExhcmdlQmluYXJ5PWZ0O1cucHJvdG90eXBlLnZpc2l0QmluYXJ5Vmlldz1mdDtXLnByb3RvdHlwZS52aXNpdEZpeGVkU2l6ZUJpbmFyeT1mdDtXLnByb3RvdHlwZS52aXNpdERhdGU9ZnQ7Vy5wcm90b3R5cGUudmlzaXREYXRlRGF5PWZ0O1cucHJvdG90eXBlLnZpc2l0RGF0ZU1pbGxpc2Vjb25kPWZ0O1cucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wPWZ0O1cucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wU2Vjb25kPWZ0O1cucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wTWlsbGlzZWNvbmQ9ZnQ7Vy5wcm90b3R5cGUudmlzaXRUaW1lc3RhbXBNaWNyb3NlY29uZD1mdDtXLnByb3RvdHlwZS52aXNpdFRpbWVzdGFtcE5hbm9zZWNvbmQ9ZnQ7Vy5wcm90b3R5cGUudmlzaXRUaW1lPWZ0O1cucHJvdG90eXBlLnZpc2l0VGltZVNlY29uZD1mdDtXLnByb3RvdHlwZS52aXNpdFRpbWVNaWxsaXNlY29uZD1mdDtXLnByb3RvdHlwZS52aXNpdFRpbWVNaWNyb3NlY29uZD1mdDtXLnByb3RvdHlwZS52aXNpdFRpbWVOYW5vc2Vjb25kPWZ0O1cucHJvdG90eXBlLnZpc2l0RGVjaW1hbD1mdDtXLnByb3RvdHlwZS52aXNpdExpc3Q9ZnQ7Vy5wcm90b3R5cGUudmlzaXRTdHJ1Y3Q9ZnQ7Vy5wcm90b3R5cGUudmlzaXRVbmlvbj1mdDtXLnByb3RvdHlwZS52aXNpdERlbnNlVW5pb249Y3Y7Vy5wcm90b3R5cGUudmlzaXRTcGFyc2VVbmlvbj1jdjtXLnByb3RvdHlwZS52aXNpdERpY3Rpb25hcnk9ZnQ7Vy5wcm90b3R5cGUudmlzaXRJbnRlcnZhbD1mdDtXLnByb3RvdHlwZS52aXNpdEludGVydmFsRGF5VGltZT1mdDtXLnByb3RvdHlwZS52aXNpdEludGVydmFsWWVhck1vbnRoPWZ0O1cucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWxNb250aERheU5hbm89ZnQ7Vy5wcm90b3R5cGUudmlzaXREdXJhdGlvbj1mdDtXLnByb3RvdHlwZS52aXNpdER1cmF0aW9uU2Vjb25kPWZ0O1cucHJvdG90eXBlLnZpc2l0RHVyYXRpb25NaWxsaXNlY29uZD1mdDtXLnByb3RvdHlwZS52aXNpdER1cmF0aW9uTWljcm9zZWNvbmQ9ZnQ7Vy5wcm90b3R5cGUudmlzaXREdXJhdGlvbk5hbm9zZWNvbmQ9ZnQ7Vy5wcm90b3R5cGUudmlzaXRGaXhlZFNpemVMaXN0PWZ0O1cucHJvdG90eXBlLnZpc2l0TWFwPWZ0O3BhPW5ldyBXfSk7ZnVuY3Rpb24gbnQodCl7bGV0e3R5cGU6ZX09dDtpZih0Lm51bGxDb3VudD09PTAmJnQuc3RyaWRlPT09MSYmKEIuaXNJbnQoZSkmJmUuYml0V2lkdGghPT02NHx8Qi5pc1RpbWUoZSkmJmUuYml0V2lkdGghPT02NHx8Qi5pc0Zsb2F0KGUpJiZlLnByZWNpc2lvbiE9PVp0LkhBTEYpKXJldHVybiBuZXcga2YodC5kYXRhLmxlbmd0aCwobik9PntsZXQgaT10LmRhdGFbbl07cmV0dXJuIGkudmFsdWVzLnN1YmFycmF5KDAsaS5sZW5ndGgpW1N5bWJvbC5pdGVyYXRvcl0oKX0pO2xldCByPTA7cmV0dXJuIG5ldyBrZih0LmRhdGEubGVuZ3RoLChuKT0+e2xldCBzPXQuZGF0YVtuXS5sZW5ndGgsbz10LnNsaWNlKHIscitzKTtyZXR1cm4gcis9cyxuZXcgbHYobyl9KX12YXIgSCxsdixJYzt2YXIgWWY9bSgoKT0+e1VpKCk7TGUoKTtpZSgpO1dmKCk7SD1jbGFzcyBIIGV4dGVuZHMgZXR7fTtsdj1jbGFzcyBsdntjb25zdHJ1Y3Rvcih0KXt0aGlzLnZlY3Rvcj10LHRoaXMuaW5kZXg9MH1uZXh0KCl7aWYodGhpcy5pbmRleDx0aGlzLnZlY3Rvci5sZW5ndGgpcmV0dXJue3ZhbHVlOnRoaXMudmVjdG9yLmdldCh0aGlzLmluZGV4KyspfTtyZXR1cm57ZG9uZTohMCx2YWx1ZTpudWxsfX1bU3ltYm9sLml0ZXJhdG9yXSgpe3JldHVybiB0aGlzfX07SC5wcm90b3R5cGUudmlzaXROdWxsPW50O0gucHJvdG90eXBlLnZpc2l0Qm9vbD1udDtILnByb3RvdHlwZS52aXNpdEludD1udDtILnByb3RvdHlwZS52aXNpdEludDg9bnQ7SC5wcm90b3R5cGUudmlzaXRJbnQxNj1udDtILnByb3RvdHlwZS52aXNpdEludDMyPW50O0gucHJvdG90eXBlLnZpc2l0SW50NjQ9bnQ7SC5wcm90b3R5cGUudmlzaXRVaW50OD1udDtILnByb3RvdHlwZS52aXNpdFVpbnQxNj1udDtILnByb3RvdHlwZS52aXNpdFVpbnQzMj1udDtILnByb3RvdHlwZS52aXNpdFVpbnQ2ND1udDtILnByb3RvdHlwZS52aXNpdEZsb2F0PW50O0gucHJvdG90eXBlLnZpc2l0RmxvYXQxNj1udDtILnByb3RvdHlwZS52aXNpdEZsb2F0MzI9bnQ7SC5wcm90b3R5cGUudmlzaXRGbG9hdDY0PW50O0gucHJvdG90eXBlLnZpc2l0VXRmOD1udDtILnByb3RvdHlwZS52aXNpdExhcmdlVXRmOD1udDtILnByb3RvdHlwZS52aXNpdFV0ZjhWaWV3PW50O0gucHJvdG90eXBlLnZpc2l0QmluYXJ5PW50O0gucHJvdG90eXBlLnZpc2l0TGFyZ2VCaW5hcnk9bnQ7SC5wcm90b3R5cGUudmlzaXRCaW5hcnlWaWV3PW50O0gucHJvdG90eXBlLnZpc2l0Rml4ZWRTaXplQmluYXJ5PW50O0gucHJvdG90eXBlLnZpc2l0RGF0ZT1udDtILnByb3RvdHlwZS52aXNpdERhdGVEYXk9bnQ7SC5wcm90b3R5cGUudmlzaXREYXRlTWlsbGlzZWNvbmQ9bnQ7SC5wcm90b3R5cGUudmlzaXRUaW1lc3RhbXA9bnQ7SC5wcm90b3R5cGUudmlzaXRUaW1lc3RhbXBTZWNvbmQ9bnQ7SC5wcm90b3R5cGUudmlzaXRUaW1lc3RhbXBNaWxsaXNlY29uZD1udDtILnByb3RvdHlwZS52aXNpdFRpbWVzdGFtcE1pY3Jvc2Vjb25kPW50O0gucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wTmFub3NlY29uZD1udDtILnByb3RvdHlwZS52aXNpdFRpbWU9bnQ7SC5wcm90b3R5cGUudmlzaXRUaW1lU2Vjb25kPW50O0gucHJvdG90eXBlLnZpc2l0VGltZU1pbGxpc2Vjb25kPW50O0gucHJvdG90eXBlLnZpc2l0VGltZU1pY3Jvc2Vjb25kPW50O0gucHJvdG90eXBlLnZpc2l0VGltZU5hbm9zZWNvbmQ9bnQ7SC5wcm90b3R5cGUudmlzaXREZWNpbWFsPW50O0gucHJvdG90eXBlLnZpc2l0TGlzdD1udDtILnByb3RvdHlwZS52aXNpdFN0cnVjdD1udDtILnByb3RvdHlwZS52aXNpdFVuaW9uPW50O0gucHJvdG90eXBlLnZpc2l0RGVuc2VVbmlvbj1udDtILnByb3RvdHlwZS52aXNpdFNwYXJzZVVuaW9uPW50O0gucHJvdG90eXBlLnZpc2l0RGljdGlvbmFyeT1udDtILnByb3RvdHlwZS52aXNpdEludGVydmFsPW50O0gucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWxEYXlUaW1lPW50O0gucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWxZZWFyTW9udGg9bnQ7SC5wcm90b3R5cGUudmlzaXRJbnRlcnZhbE1vbnRoRGF5TmFubz1udDtILnByb3RvdHlwZS52aXNpdER1cmF0aW9uPW50O0gucHJvdG90eXBlLnZpc2l0RHVyYXRpb25TZWNvbmQ9bnQ7SC5wcm90b3R5cGUudmlzaXREdXJhdGlvbk1pbGxpc2Vjb25kPW50O0gucHJvdG90eXBlLnZpc2l0RHVyYXRpb25NaWNyb3NlY29uZD1udDtILnByb3RvdHlwZS52aXNpdER1cmF0aW9uTmFub3NlY29uZD1udDtILnByb3RvdHlwZS52aXNpdEZpeGVkU2l6ZUxpc3Q9bnQ7SC5wcm90b3R5cGUudmlzaXRNYXA9bnQ7SWM9bmV3IEh9KTtmdW5jdGlvbiBtYSh0KXtpZih0KXtpZih0IGluc3RhbmNlb2YgcHQpcmV0dXJuIG5ldyBOKFt0XSk7aWYodCBpbnN0YW5jZW9mIE4pcmV0dXJuIG5ldyBOKHQuZGF0YSk7aWYodC50eXBlIGluc3RhbmNlb2YgQilyZXR1cm4gbmV3IE4oW1ModCldKTtpZihBcnJheS5pc0FycmF5KHQpKXJldHVybiBuZXcgTih0LmZsYXRNYXAoKGUpPT52VChlKSkpO2lmKEFycmF5QnVmZmVyLmlzVmlldyh0KSl7aWYodCBpbnN0YW5jZW9mIERhdGFWaWV3KXQ9bmV3IFVpbnQ4QXJyYXkodC5idWZmZXIpO2xldCBlPXtvZmZzZXQ6MCxsZW5ndGg6dC5sZW5ndGgsbnVsbENvdW50Oi0xLGRhdGE6dH07aWYodCBpbnN0YW5jZW9mIEludDhBcnJheSlyZXR1cm4gbmV3IE4oW1MoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LGUpLHt0eXBlOm5ldyBtb30pKV0pO2lmKHQgaW5zdGFuY2VvZiBJbnQxNkFycmF5KXJldHVybiBuZXcgTihbUyhPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sZSkse3R5cGU6bmV3IHlvfSkpXSk7aWYodCBpbnN0YW5jZW9mIEludDMyQXJyYXkpcmV0dXJuIG5ldyBOKFtTKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSxlKSx7dHlwZTpuZXcgQnJ9KSldKTtpZih0IGluc3RhbmNlb2YgQmlnSW50NjRBcnJheSlyZXR1cm4gbmV3IE4oW1MoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LGUpLHt0eXBlOm5ldyBJbn0pKV0pO2lmKHQgaW5zdGFuY2VvZiBVaW50OEFycmF5fHx0IGluc3RhbmNlb2YgVWludDhDbGFtcGVkQXJyYXkpcmV0dXJuIG5ldyBOKFtTKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSxlKSx7dHlwZTpuZXcgX299KSldKTtpZih0IGluc3RhbmNlb2YgVWludDE2QXJyYXkpcmV0dXJuIG5ldyBOKFtTKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSxlKSx7dHlwZTpuZXcgZ299KSldKTtpZih0IGluc3RhbmNlb2YgVWludDMyQXJyYXkpcmV0dXJuIG5ldyBOKFtTKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSxlKSx7dHlwZTpuZXcgYm99KSldKTtpZih0IGluc3RhbmNlb2YgQmlnVWludDY0QXJyYXkpcmV0dXJuIG5ldyBOKFtTKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSxlKSx7dHlwZTpuZXcgTGl9KSldKTtpZih0IGluc3RhbmNlb2YgRmxvYXQzMkFycmF5KXJldHVybiBuZXcgTihbUyhPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sZSkse3R5cGU6bmV3IHdvfSkpXSk7aWYodCBpbnN0YW5jZW9mIEZsb2F0NjRBcnJheSlyZXR1cm4gbmV3IE4oW1MoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LGUpLHt0eXBlOm5ldyBvc30pKV0pO3Rocm93IEVycm9yKCJVbnJlY29nbml6ZWQgaW5wdXQiKX19dGhyb3cgRXJyb3IoIlVucmVjb2duaXplZCBpbnB1dCIpfWZ1bmN0aW9uIHZUKHQpe3JldHVybiB0IGluc3RhbmNlb2YgcHQ/W3RdOnQgaW5zdGFuY2VvZiBOP3QuZGF0YTptYSh0KS5kYXRhfXZhciB1dixmdixkdixodixOLEtmO3ZhciBRcj1tKCgpPT57TGUoKTtnYygpO2llKCk7WG4oKTtXZigpO3VhKCk7U24oKTtIZigpO1lmKCk7aWUoKTtmdj1TeW1ib2wuZm9yKCJhcGFjaGUtYXJyb3cvVmVjdG9yIiksZHY9e30saHY9e307Tj1jbGFzcyBOe3N0YXRpYyBpc1ZlY3Rvcih0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnRbZnZdKT09PSEwfWNvbnN0cnVjdG9yKHQpe3ZhciBlLHIsbjtsZXQgaT10WzBdaW5zdGFuY2VvZiBOP3QuZmxhdE1hcCgobyk9Pm8uZGF0YSk6dDtpZihpLmxlbmd0aD09PTB8fGkuc29tZSgobyk9PiEobyBpbnN0YW5jZW9mIHB0KSkpdGhyb3cgVHlwZUVycm9yKCJWZWN0b3IgY29uc3RydWN0b3IgZXhwZWN0cyBhbiBBcnJheSBvZiBEYXRhIGluc3RhbmNlcy4iKTtsZXQgcz0oZT1pWzBdKT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUudHlwZTtzd2l0Y2goaS5sZW5ndGgpe2Nhc2UgMDp0aGlzLl9vZmZzZXRzPVswXTticmVhaztjYXNlIDE6e2xldHtnZXQ6byxzZXQ6YSxpbmRleE9mOmx9PWR2W3MudHlwZUlkXSx1PWlbMF07dGhpcy5pc1ZhbGlkPShmKT0+amwodSxmKSx0aGlzLmdldD0oZik9Pm8odSxmKSx0aGlzLnNldD0oZixwKT0+YSh1LGYscCksdGhpcy5pbmRleE9mPShmKT0+bCh1LGYpLHRoaXMuX29mZnNldHM9WzAsdS5sZW5ndGhdO2JyZWFrfWRlZmF1bHQ6T2JqZWN0LnNldFByb3RvdHlwZU9mKHRoaXMsaHZbcy50eXBlSWRdKSx0aGlzLl9vZmZzZXRzPXpmKGkpO2JyZWFrfXRoaXMuZGF0YT1pLHRoaXMudHlwZT1zLHRoaXMuc3RyaWRlPUJuKHMpLHRoaXMubnVtQ2hpbGRyZW49KG49KHI9cy5jaGlsZHJlbik9PT1udWxsfHxyPT09dm9pZCAwP3ZvaWQgMDpyLmxlbmd0aCkhPT1udWxsJiZuIT09dm9pZCAwP246MCx0aGlzLmxlbmd0aD10aGlzLl9vZmZzZXRzLmF0KC0xKX1nZXQgYnl0ZUxlbmd0aCgpe3JldHVybiB0aGlzLmRhdGEucmVkdWNlKCh0LGUpPT50K2UuYnl0ZUxlbmd0aCwwKX1nZXQgbnVsbGFibGUoKXtyZXR1cm4gYXYodGhpcy5kYXRhKX1nZXQgbnVsbENvdW50KCl7cmV0dXJuIFZmKHRoaXMuZGF0YSl9Z2V0IEFycmF5VHlwZSgpe3JldHVybiB0aGlzLnR5cGUuQXJyYXlUeXBlfWdldFtTeW1ib2wudG9TdHJpbmdUYWddKCl7cmV0dXJuYCR7dGhpcy5WZWN0b3JOYW1lfTwke3RoaXMudHlwZVtTeW1ib2wudG9TdHJpbmdUYWddfT5gfWdldCBWZWN0b3JOYW1lKCl7cmV0dXJuYCR7X1t0aGlzLnR5cGUudHlwZUlkXX1WZWN0b3JgfWlzVmFsaWQodCl7cmV0dXJuITF9Z2V0KHQpe3JldHVybiBudWxsfWF0KHQpe3JldHVybiB0aGlzLmdldChmYSh0LHRoaXMubGVuZ3RoKSl9c2V0KHQsZSl7cmV0dXJufWluZGV4T2YodCxlKXtyZXR1cm4tMX1pbmNsdWRlcyh0LGUpe3JldHVybiB0aGlzLmluZGV4T2YodCxlKT4tMX1bU3ltYm9sLml0ZXJhdG9yXSgpe3JldHVybiBJYy52aXNpdCh0aGlzKX1jb25jYXQoLi4udCl7cmV0dXJuIG5ldyBOKHRoaXMuZGF0YS5jb25jYXQodC5mbGF0TWFwKChlKT0+ZS5kYXRhKS5mbGF0KE51bWJlci5QT1NJVElWRV9JTkZJTklUWSkpKX1zbGljZSh0LGUpe3JldHVybiBuZXcgTihrbCh0aGlzLHQsZSwoe2RhdGE6cixfb2Zmc2V0czpufSxpLHMpPT5qZihyLG4saSxzKSkpfXRvSlNPTigpe3JldHVyblsuLi50aGlzXX10b0FycmF5KCl7bGV0e3R5cGU6dCxkYXRhOmUsbGVuZ3RoOnIsc3RyaWRlOm4sQXJyYXlUeXBlOml9PXRoaXM7c3dpdGNoKHQudHlwZUlkKXtjYXNlIF8uSW50OmNhc2UgXy5GbG9hdDpjYXNlIF8uRGVjaW1hbDpjYXNlIF8uVGltZTpjYXNlIF8uVGltZXN0YW1wOnN3aXRjaChlLmxlbmd0aCl7Y2FzZSAwOnJldHVybiBuZXcgaTtjYXNlIDE6cmV0dXJuIGVbMF0udmFsdWVzLnN1YmFycmF5KDAscipuKTtkZWZhdWx0OnJldHVybiBlLnJlZHVjZSgocyx7dmFsdWVzOm8sbGVuZ3RoOmF9KT0+KHMuYXJyYXkuc2V0KG8uc3ViYXJyYXkoMCxhKm4pLHMub2Zmc2V0KSxzLm9mZnNldCs9YSpuLHMpLHthcnJheTpuZXcgaShyKm4pLG9mZnNldDowfSkuYXJyYXl9fXJldHVyblsuLi50aGlzXX10b1N0cmluZygpe3JldHVybmBbJHtbLi4udGhpc10uam9pbigiLCIpfV1gfWdldENoaWxkKHQpe3ZhciBlO3JldHVybiB0aGlzLmdldENoaWxkQXQoKGU9dGhpcy50eXBlLmNoaWxkcmVuKT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUuZmluZEluZGV4KChyKT0+ci5uYW1lPT09dCkpfWdldENoaWxkQXQodCl7aWYodD4tMSYmdDx0aGlzLm51bUNoaWxkcmVuKXJldHVybiBuZXcgTih0aGlzLmRhdGEubWFwKCh7Y2hpbGRyZW46ZX0pPT5lW3RdKSk7cmV0dXJuIG51bGx9Z2V0IGlzTWVtb2l6ZWQoKXtpZihCLmlzRGljdGlvbmFyeSh0aGlzLnR5cGUpKXJldHVybiB0aGlzLmRhdGFbMF0uZGljdGlvbmFyeS5pc01lbW9pemVkO3JldHVybiExfW1lbW9pemUoKXtpZihCLmlzRGljdGlvbmFyeSh0aGlzLnR5cGUpKXtsZXQgdD1uZXcgS2YodGhpcy5kYXRhWzBdLmRpY3Rpb25hcnkpLGU9dGhpcy5kYXRhLm1hcCgocik9PntsZXQgbj1yLmNsb25lKCk7cmV0dXJuIG4uZGljdGlvbmFyeT10LG59KTtyZXR1cm4gbmV3IE4oZSl9cmV0dXJuIG5ldyBLZih0aGlzKX11bm1lbW9pemUoKXtpZihCLmlzRGljdGlvbmFyeSh0aGlzLnR5cGUpJiZ0aGlzLmlzTWVtb2l6ZWQpe2xldCB0PXRoaXMuZGF0YVswXS5kaWN0aW9uYXJ5LnVubWVtb2l6ZSgpLGU9dGhpcy5kYXRhLm1hcCgocik9PntsZXQgbj1yLmNsb25lKCk7cmV0dXJuIG4uZGljdGlvbmFyeT10LG59KTtyZXR1cm4gbmV3IE4oZSl9cmV0dXJuIHRoaXN9fTt1dj1TeW1ib2wudG9TdHJpbmdUYWc7Tlt1dl09KCh0KT0+e3QudHlwZT1CLnByb3RvdHlwZSx0LmRhdGE9W10sdC5sZW5ndGg9MCx0LnN0cmlkZT0xLHQubnVtQ2hpbGRyZW49MCx0Ll9vZmZzZXRzPW5ldyBVaW50MzJBcnJheShbMF0pLHRbU3ltYm9sLmlzQ29uY2F0U3ByZWFkYWJsZV09ITAsdFtmdl09ITA7bGV0IGU9T2JqZWN0LmtleXMoXykubWFwKChyKT0+X1tyXSkuZmlsdGVyKChyKT0+dHlwZW9mIHI9PT0ibnVtYmVyIiYmciE9PV8uTk9ORSk7Zm9yKGxldCByIG9mIGUpe2xldCBuPVJlLmdldFZpc2l0Rm5CeVR5cGVJZChyKSxpPWRyLmdldFZpc2l0Rm5CeVR5cGVJZChyKSxzPXBhLmdldFZpc2l0Rm5CeVR5cGVJZChyKTtkdltyXT17Z2V0Om4sc2V0OmksaW5kZXhPZjpzfSxodltyXT1PYmplY3QuY3JlYXRlKHQse1siaXNWYWxpZCJdOnt2YWx1ZTp2YyhqbCl9LFsiZ2V0Il06e3ZhbHVlOnZjKFJlLmdldFZpc2l0Rm5CeVR5cGVJZChyKSl9LFsic2V0Il06e3ZhbHVlOiRmKGRyLmdldFZpc2l0Rm5CeVR5cGVJZChyKSl9LFsiaW5kZXhPZiJdOnt2YWx1ZTpxZihwYS5nZXRWaXNpdEZuQnlUeXBlSWQocikpfX0pfXJldHVybiJWZWN0b3IifSkoTi5wcm90b3R5cGUpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShOLFN5bWJvbC5oYXNJbnN0YW5jZSx7dmFsdWU6ZnVuY3Rpb24oZSl7cmV0dXJuIEZ1bmN0aW9uLnByb3RvdHlwZVtTeW1ib2wuaGFzSW5zdGFuY2VdLmNhbGwodGhpcyxlKXx8dGhpcz09PU4mJk4uaXNWZWN0b3IoZSl9fSk7S2Y9Y2xhc3MgS2YgZXh0ZW5kcyBOe2NvbnN0cnVjdG9yKHQpe3N1cGVyKHQuZGF0YSk7bGV0IGU9dGhpcy5nZXQscj10aGlzLnNldCxuPXRoaXMuc2xpY2UsaT1BcnJheSh0aGlzLmxlbmd0aCk7T2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsImdldCIse3ZhbHVlKHMpe2xldCBvPWlbc107aWYobyE9PXZvaWQgMClyZXR1cm4gbztsZXQgYT1lLmNhbGwodGhpcyxzKTtyZXR1cm4gaVtzXT1hLGF9fSksT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsInNldCIse3ZhbHVlKHMsbyl7ci5jYWxsKHRoaXMscyxvKSxpW3NdPW99fSksT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsInNsaWNlIix7dmFsdWU6KHMsbyk9Pm5ldyBLZihuLmNhbGwodGhpcyxzLG8pKX0pLE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCJpc01lbW9pemVkIix7dmFsdWU6ITB9KSxPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywidW5tZW1vaXplIix7dmFsdWU6KCk9Pm5ldyBOKHRoaXMuZGF0YSl9KSxPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywibWVtb2l6ZSIse3ZhbHVlOigpPT50aGlzfSl9fX0pO2Z1bmN0aW9uIHB2KHQpe2lmKCF0fHx0Lmxlbmd0aDw9MClyZXR1cm4gZnVuY3Rpb24oaSl7cmV0dXJuITB9O2xldCBlPSIiLHI9dC5maWx0ZXIoKG4pPT5uPT09bik7aWYoci5sZW5ndGg+MCllPWAKICAgIHN3aXRjaCAoeCkgeyR7ci5tYXAoKG4pPT5gCiAgICAgICAgY2FzZSAke0lUKG4pfTpgKS5qb2luKCIiKX0KICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgfWA7aWYodC5sZW5ndGghPT1yLmxlbmd0aCllPWBpZiAoeCAhPT0geCkgcmV0dXJuIGZhbHNlOwoke2V9YDtyZXR1cm4gRnVuY3Rpb24oIngiLGAke2V9CnJldHVybiB0cnVlO2ApfWZ1bmN0aW9uIElUKHQpe2lmKHR5cGVvZiB0IT09ImJpZ2ludCIpcmV0dXJuIEJpKHQpO3JldHVybmAke0JpKHQpfW5gfXZhciBtdj0oKT0+e307ZnVuY3Rpb24gJG0odCxlKXtsZXQgcj1NYXRoLmNlaWwodCkqZS0xO3JldHVybihyLXIlNjQrNjR8fDY0KS9lfWZ1bmN0aW9uIHl2KHQsZT0wKXtyZXR1cm4gdC5sZW5ndGg+PWU/dC5zdWJhcnJheSgwLGUpOlNsKG5ldyB0LmNvbnN0cnVjdG9yKGUpLHQsMCl9Y2xhc3MgQW57Y29uc3RydWN0b3IodCxlPTAscj0xKXt0aGlzLmxlbmd0aD1NYXRoLmNlaWwoZS9yKSx0aGlzLmJ1ZmZlcj1uZXcgdCh0aGlzLmxlbmd0aCksdGhpcy5zdHJpZGU9cix0aGlzLkJZVEVTX1BFUl9FTEVNRU5UPXQuQllURVNfUEVSX0VMRU1FTlQsdGhpcy5BcnJheVR5cGU9dH1nZXQgYnl0ZUxlbmd0aCgpe3JldHVybiBNYXRoLmNlaWwodGhpcy5sZW5ndGgqdGhpcy5zdHJpZGUpKnRoaXMuQllURVNfUEVSX0VMRU1FTlR9Z2V0IHJlc2VydmVkTGVuZ3RoKCl7cmV0dXJuIHRoaXMuYnVmZmVyLmxlbmd0aC90aGlzLnN0cmlkZX1nZXQgcmVzZXJ2ZWRCeXRlTGVuZ3RoKCl7cmV0dXJuIHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGh9c2V0KHQsZSl7cmV0dXJuIHRoaXN9YXBwZW5kKHQpe3JldHVybiB0aGlzLnNldCh0aGlzLmxlbmd0aCx0KX1yZXNlcnZlKHQpe2lmKHQ+MCl7dGhpcy5sZW5ndGgrPXQ7bGV0IGU9dGhpcy5zdHJpZGUscj10aGlzLmxlbmd0aCplLG49dGhpcy5idWZmZXIubGVuZ3RoO2lmKHI+PW4pdGhpcy5fcmVzaXplKG49PT0wPyRtKHIqMSx0aGlzLkJZVEVTX1BFUl9FTEVNRU5UKTokbShyKjIsdGhpcy5CWVRFU19QRVJfRUxFTUVOVCkpfXJldHVybiB0aGlzfWZsdXNoKHQ9dGhpcy5sZW5ndGgpe3Q9JG0odCp0aGlzLnN0cmlkZSx0aGlzLkJZVEVTX1BFUl9FTEVNRU5UKTtsZXQgZT15dih0aGlzLmJ1ZmZlcix0KTtyZXR1cm4gdGhpcy5jbGVhcigpLGV9Y2xlYXIoKXtyZXR1cm4gdGhpcy5sZW5ndGg9MCx0aGlzLmJ1ZmZlcj1uZXcgdGhpcy5BcnJheVR5cGUsdGhpc31fcmVzaXplKHQpe3JldHVybiB0aGlzLmJ1ZmZlcj15dih0aGlzLmJ1ZmZlcix0KX19dmFyIEFvLCRsLHFsO3ZhciBhcz1tKCgpPT57amUoKTtBbz1jbGFzcyBBbyBleHRlbmRzIEFue2xhc3QoKXtyZXR1cm4gdGhpcy5nZXQodGhpcy5sZW5ndGgtMSl9Z2V0KHQpe3JldHVybiB0aGlzLmJ1ZmZlclt0XX1zZXQodCxlKXtyZXR1cm4gdGhpcy5yZXNlcnZlKHQtdGhpcy5sZW5ndGgrMSksdGhpcy5idWZmZXJbdCp0aGlzLnN0cmlkZV09ZSx0aGlzfX07JGw9Y2xhc3MgJGwgZXh0ZW5kcyBBb3tjb25zdHJ1Y3Rvcigpe3N1cGVyKFVpbnQ4QXJyYXksMCwwLjEyNSk7dGhpcy5udW1WYWxpZD0wfWdldCBudW1JbnZhbGlkKCl7cmV0dXJuIHRoaXMubGVuZ3RoLXRoaXMubnVtVmFsaWR9Z2V0KHQpe3JldHVybiB0aGlzLmJ1ZmZlclt0Pj4zXT4+dCU4JjF9c2V0KHQsZSl7bGV0e2J1ZmZlcjpyfT10aGlzLnJlc2VydmUodC10aGlzLmxlbmd0aCsxKSxuPXQ+PjMsaT10JTgscz1yW25dPj5pJjE7cmV0dXJuIGU/cz09PTAmJihyW25dfD0xPDxpLCsrdGhpcy5udW1WYWxpZCk6cz09PTEmJihyW25dJj1+KDE8PGkpLC0tdGhpcy5udW1WYWxpZCksdGhpc31jbGVhcigpe3JldHVybiB0aGlzLm51bVZhbGlkPTAsc3VwZXIuY2xlYXIoKX19O3FsPWNsYXNzIHFsIGV4dGVuZHMgQW97Y29uc3RydWN0b3IodCl7c3VwZXIodC5PZmZzZXRBcnJheVR5cGUsMSwxKX1hcHBlbmQodCl7cmV0dXJuIHRoaXMuc2V0KHRoaXMubGVuZ3RoLTEsdCl9c2V0KHQsZSl7bGV0IHI9dGhpcy5sZW5ndGgtMSxuPXRoaXMucmVzZXJ2ZSh0LXIrMSkuYnVmZmVyO2lmKHI8dCsrJiZyPj0wKW4uZmlsbChuW3JdLHIsdCk7cmV0dXJuIG5bdF09blt0LTFdK2UsdGhpc31mbHVzaCh0PXRoaXMubGVuZ3RoLTEpe2lmKHQ+dGhpcy5sZW5ndGgpdGhpcy5zZXQodC0xLHRoaXMuQllURVNfUEVSX0VMRU1FTlQ+ND9CaWdJbnQoMCk6MCk7cmV0dXJuIHN1cGVyLmZsdXNoKHQrMSl9fX0pO2NsYXNzIHVle3N0YXRpYyB0aHJvdWdoTm9kZSh0KXt0aHJvdyBFcnJvcignInRocm91Z2hOb2RlIiBub3QgYXZhaWxhYmxlIGluIHRoaXMgZW52aXJvbm1lbnQnKX1zdGF0aWMgdGhyb3VnaERPTSh0KXt0aHJvdyBFcnJvcignInRocm91Z2hET00iIG5vdCBhdmFpbGFibGUgaW4gdGhpcyBlbnZpcm9ubWVudCcpfWNvbnN0cnVjdG9yKHt0eXBlOnQsbnVsbFZhbHVlczplfSl7aWYodGhpcy5sZW5ndGg9MCx0aGlzLmZpbmlzaGVkPSExLHRoaXMudHlwZT10LHRoaXMuY2hpbGRyZW49W10sdGhpcy5udWxsVmFsdWVzPWUsdGhpcy5zdHJpZGU9Qm4odCksdGhpcy5fbnVsbHM9bmV3ICRsLGUmJmUubGVuZ3RoPjApdGhpcy5faXNWYWxpZD1wdihlKX10b1ZlY3Rvcigpe3JldHVybiBuZXcgTihbdGhpcy5mbHVzaCgpXSl9Z2V0IEFycmF5VHlwZSgpe3JldHVybiB0aGlzLnR5cGUuQXJyYXlUeXBlfWdldCBudWxsQ291bnQoKXtyZXR1cm4gdGhpcy5fbnVsbHMubnVtSW52YWxpZH1nZXQgbnVtQ2hpbGRyZW4oKXtyZXR1cm4gdGhpcy5jaGlsZHJlbi5sZW5ndGh9Z2V0IGJ5dGVMZW5ndGgoKXtsZXQgdD0wLHtfb2Zmc2V0czplLF92YWx1ZXM6cixfbnVsbHM6bixfdHlwZUlkczppLGNoaWxkcmVuOnN9PXRoaXM7cmV0dXJuIGUmJih0Kz1lLmJ5dGVMZW5ndGgpLHImJih0Kz1yLmJ5dGVMZW5ndGgpLG4mJih0Kz1uLmJ5dGVMZW5ndGgpLGkmJih0Kz1pLmJ5dGVMZW5ndGgpLHMucmVkdWNlKChvLGEpPT5vK2EuYnl0ZUxlbmd0aCx0KX1nZXQgcmVzZXJ2ZWRMZW5ndGgoKXtyZXR1cm4gdGhpcy5fbnVsbHMucmVzZXJ2ZWRMZW5ndGh9Z2V0IHJlc2VydmVkQnl0ZUxlbmd0aCgpe2xldCB0PTA7cmV0dXJuIHRoaXMuX29mZnNldHMmJih0Kz10aGlzLl9vZmZzZXRzLnJlc2VydmVkQnl0ZUxlbmd0aCksdGhpcy5fdmFsdWVzJiYodCs9dGhpcy5fdmFsdWVzLnJlc2VydmVkQnl0ZUxlbmd0aCksdGhpcy5fbnVsbHMmJih0Kz10aGlzLl9udWxscy5yZXNlcnZlZEJ5dGVMZW5ndGgpLHRoaXMuX3R5cGVJZHMmJih0Kz10aGlzLl90eXBlSWRzLnJlc2VydmVkQnl0ZUxlbmd0aCksdGhpcy5jaGlsZHJlbi5yZWR1Y2UoKGUscik9PmUrci5yZXNlcnZlZEJ5dGVMZW5ndGgsdCl9Z2V0IHZhbHVlT2Zmc2V0cygpe3JldHVybiB0aGlzLl9vZmZzZXRzP3RoaXMuX29mZnNldHMuYnVmZmVyOm51bGx9Z2V0IHZhbHVlcygpe3JldHVybiB0aGlzLl92YWx1ZXM/dGhpcy5fdmFsdWVzLmJ1ZmZlcjpudWxsfWdldCBudWxsQml0bWFwKCl7cmV0dXJuIHRoaXMuX251bGxzP3RoaXMuX251bGxzLmJ1ZmZlcjpudWxsfWdldCB0eXBlSWRzKCl7cmV0dXJuIHRoaXMuX3R5cGVJZHM/dGhpcy5fdHlwZUlkcy5idWZmZXI6bnVsbH1hcHBlbmQodCl7cmV0dXJuIHRoaXMuc2V0KHRoaXMubGVuZ3RoLHQpfWlzVmFsaWQodCl7cmV0dXJuIHRoaXMuX2lzVmFsaWQodCl9c2V0KHQsZSl7aWYodGhpcy5zZXRWYWxpZCh0LHRoaXMuaXNWYWxpZChlKSkpdGhpcy5zZXRWYWx1ZSh0LGUpO3JldHVybiB0aGlzfXNldFZhbHVlKHQsZSl7dGhpcy5fc2V0VmFsdWUodGhpcyx0LGUpfXNldFZhbGlkKHQsZSl7cmV0dXJuIHRoaXMubGVuZ3RoPXRoaXMuX251bGxzLnNldCh0LCtlKS5sZW5ndGgsZX1hZGRDaGlsZCh0LGU9YCR7dGhpcy5udW1DaGlsZHJlbn1gKXt0aHJvdyBFcnJvcihgQ2Fubm90IGFwcGVuZCBjaGlsZHJlbiB0byBub24tbmVzdGVkIHR5cGUgIiR7dGhpcy50eXBlfSJgKX1nZXRDaGlsZEF0KHQpe3JldHVybiB0aGlzLmNoaWxkcmVuW3RdfHxudWxsfWZsdXNoKCl7bGV0IHQsZSxyLG4se3R5cGU6aSxsZW5ndGg6cyxudWxsQ291bnQ6byxfdHlwZUlkczphLF9vZmZzZXRzOmwsX3ZhbHVlczp1LF9udWxsczpmfT10aGlzO2lmKGU9YT09PW51bGx8fGE9PT12b2lkIDA/dm9pZCAwOmEuZmx1c2gocykpbj1sPT09bnVsbHx8bD09PXZvaWQgMD92b2lkIDA6bC5mbHVzaChzKTtlbHNlIGlmKG49bD09PW51bGx8fGw9PT12b2lkIDA/dm9pZCAwOmwuZmx1c2gocykpdD11PT09bnVsbHx8dT09PXZvaWQgMD92b2lkIDA6dS5mbHVzaChsLmxhc3QoKSk7ZWxzZSB0PXU9PT1udWxsfHx1PT09dm9pZCAwP3ZvaWQgMDp1LmZsdXNoKHMpO2lmKG8+MClyPWY9PT1udWxsfHxmPT09dm9pZCAwP3ZvaWQgMDpmLmZsdXNoKHMpO2xldCBwPXRoaXMuY2hpbGRyZW4ubWFwKChnKT0+Zy5mbHVzaCgpKTtyZXR1cm4gdGhpcy5jbGVhcigpLFMoe3R5cGU6aSxsZW5ndGg6cyxudWxsQ291bnQ6byxjaGlsZHJlbjpwLGNoaWxkOnBbMF0sZGF0YTp0LHR5cGVJZHM6ZSxudWxsQml0bWFwOnIsdmFsdWVPZmZzZXRzOm59KX1maW5pc2goKXt0aGlzLmZpbmlzaGVkPSEwO2ZvcihsZXQgdCBvZiB0aGlzLmNoaWxkcmVuKXQuZmluaXNoKCk7cmV0dXJuIHRoaXN9Y2xlYXIoKXt2YXIgdCxlLHIsbjt0aGlzLmxlbmd0aD0wLCh0PXRoaXMuX251bGxzKT09PW51bGx8fHQ9PT12b2lkIDB8fHQuY2xlYXIoKSwoZT10aGlzLl92YWx1ZXMpPT09bnVsbHx8ZT09PXZvaWQgMHx8ZS5jbGVhcigpLChyPXRoaXMuX29mZnNldHMpPT09bnVsbHx8cj09PXZvaWQgMHx8ci5jbGVhcigpLChuPXRoaXMuX3R5cGVJZHMpPT09bnVsbHx8bj09PXZvaWQgMHx8bi5jbGVhcigpO2ZvcihsZXQgaSBvZiB0aGlzLmNoaWxkcmVuKWkuY2xlYXIoKTtyZXR1cm4gdGhpc319dmFyIHFlLERuO3ZhciBfZT1tKCgpPT57UXIoKTtYbigpO1VmKCk7aWUoKTttdigpO2FzKCk7dWUucHJvdG90eXBlLmxlbmd0aD0xO3VlLnByb3RvdHlwZS5zdHJpZGU9MTt1ZS5wcm90b3R5cGUuY2hpbGRyZW49bnVsbDt1ZS5wcm90b3R5cGUuZmluaXNoZWQ9ITE7dWUucHJvdG90eXBlLm51bGxWYWx1ZXM9bnVsbDt1ZS5wcm90b3R5cGUuX2lzVmFsaWQ9KCk9PiEwO3FlPWNsYXNzIHFlIGV4dGVuZHMgdWV7Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5fdmFsdWVzPW5ldyBBbyh0aGlzLkFycmF5VHlwZSwwLHRoaXMuc3RyaWRlKX1zZXRWYWx1ZSh0LGUpe2xldCByPXRoaXMuX3ZhbHVlcztyZXR1cm4gci5yZXNlcnZlKHQtci5sZW5ndGgrMSksc3VwZXIuc2V0VmFsdWUodCxlKX19O0RuPWNsYXNzIERuIGV4dGVuZHMgdWV7Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5fcGVuZGluZ0xlbmd0aD0wLHRoaXMuX29mZnNldHM9bmV3IHFsKHQudHlwZSl9c2V0VmFsdWUodCxlKXtsZXQgcj10aGlzLl9wZW5kaW5nfHwodGhpcy5fcGVuZGluZz1uZXcgTWFwKSxuPXIuZ2V0KHQpO24mJih0aGlzLl9wZW5kaW5nTGVuZ3RoLT1uLmxlbmd0aCksdGhpcy5fcGVuZGluZ0xlbmd0aCs9ZSBpbnN0YW5jZW9mIEJzP2VbQm9dLmxlbmd0aDplLmxlbmd0aCxyLnNldCh0LGUpfXNldFZhbGlkKHQsZSl7aWYoIXN1cGVyLnNldFZhbGlkKHQsZSkpcmV0dXJuKHRoaXMuX3BlbmRpbmd8fCh0aGlzLl9wZW5kaW5nPW5ldyBNYXApKS5zZXQodCx2b2lkIDApLCExO3JldHVybiEwfWNsZWFyKCl7cmV0dXJuIHRoaXMuX3BlbmRpbmdMZW5ndGg9MCx0aGlzLl9wZW5kaW5nPXZvaWQgMCxzdXBlci5jbGVhcigpfWZsdXNoKCl7cmV0dXJuIHRoaXMuX2ZsdXNoKCksc3VwZXIuZmx1c2goKX1maW5pc2goKXtyZXR1cm4gdGhpcy5fZmx1c2goKSxzdXBlci5maW5pc2goKX1fZmx1c2goKXtsZXQgdD10aGlzLl9wZW5kaW5nLGU9dGhpcy5fcGVuZGluZ0xlbmd0aDtpZih0aGlzLl9wZW5kaW5nTGVuZ3RoPTAsdGhpcy5fcGVuZGluZz12b2lkIDAsdCYmdC5zaXplPjApdGhpcy5fZmx1c2hQZW5kaW5nKHQsZSk7cmV0dXJuIHRoaXN9fX0pO2NsYXNzIEJje2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9b2Zmc2V0KCl7cmV0dXJuIHRoaXMuYmIucmVhZEludDY0KHRoaXMuYmJfcG9zKX1tZXRhRGF0YUxlbmd0aCgpe3JldHVybiB0aGlzLmJiLnJlYWRJbnQzMih0aGlzLmJiX3Bvcys4KX1ib2R5TGVuZ3RoKCl7cmV0dXJuIHRoaXMuYmIucmVhZEludDY0KHRoaXMuYmJfcG9zKzE2KX1zdGF0aWMgc2l6ZU9mKCl7cmV0dXJuIDI0fXN0YXRpYyBjcmVhdGVCbG9jayh0LGUscixuKXtyZXR1cm4gdC5wcmVwKDgsMjQpLHQud3JpdGVJbnQ2NChCaWdJbnQobiE9PW51bGwmJm4hPT12b2lkIDA/bjowKSksdC5wYWQoNCksdC53cml0ZUludDMyKHIpLHQud3JpdGVJbnQ2NChCaWdJbnQoZSE9PW51bGwmJmUhPT12b2lkIDA/ZTowKSksdC5vZmZzZXQoKX19Y2xhc3MgdG57Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzRm9vdGVyKHQsZSl7cmV0dXJuKGV8fG5ldyB0bikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNGb290ZXIodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTSksKGV8fG5ldyB0bikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXZlcnNpb24oKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDQpO3JldHVybiB0P3RoaXMuYmIucmVhZEludDE2KHRoaXMuYmJfcG9zK3QpOiR0LlYxfXNjaGVtYSh0KXtsZXQgZT10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDYpO3JldHVybiBlPyh0fHxuZXcgQWUpLl9faW5pdCh0aGlzLmJiLl9faW5kaXJlY3QodGhpcy5iYl9wb3MrZSksdGhpcy5iYik6bnVsbH1kaWN0aW9uYXJpZXModCxlKXtsZXQgcj10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDgpO3JldHVybiByPyhlfHxuZXcgQmMpLl9faW5pdCh0aGlzLmJiLl9fdmVjdG9yKHRoaXMuYmJfcG9zK3IpK3QqMjQsdGhpcy5iYik6bnVsbH1kaWN0aW9uYXJpZXNMZW5ndGgoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDgpO3JldHVybiB0P3RoaXMuYmIuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zK3QpOjB9cmVjb3JkQmF0Y2hlcyh0LGUpe2xldCByPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsMTApO3JldHVybiByPyhlfHxuZXcgQmMpLl9faW5pdCh0aGlzLmJiLl9fdmVjdG9yKHRoaXMuYmJfcG9zK3IpK3QqMjQsdGhpcy5iYik6bnVsbH1yZWNvcmRCYXRjaGVzTGVuZ3RoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3BvcywxMCk7cmV0dXJuIHQ/dGhpcy5iYi5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MrdCk6MH1jdXN0b21NZXRhZGF0YSh0LGUpe2xldCByPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsMTIpO3JldHVybiByPyhlfHxuZXcgbmUpLl9faW5pdCh0aGlzLmJiLl9faW5kaXJlY3QodGhpcy5iYi5fX3ZlY3Rvcih0aGlzLmJiX3BvcytyKSt0KjQpLHRoaXMuYmIpOm51bGx9Y3VzdG9tTWV0YWRhdGFMZW5ndGgoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDEyKTtyZXR1cm4gdD90aGlzLmJiLl9fdmVjdG9yX2xlbih0aGlzLmJiX3Bvcyt0KTowfXN0YXRpYyBzdGFydEZvb3Rlcih0KXt0LnN0YXJ0T2JqZWN0KDUpfXN0YXRpYyBhZGRWZXJzaW9uKHQsZSl7dC5hZGRGaWVsZEludDE2KDAsZSwkdC5WMSl9c3RhdGljIGFkZFNjaGVtYSh0LGUpe3QuYWRkRmllbGRPZmZzZXQoMSxlLDApfXN0YXRpYyBhZGREaWN0aW9uYXJpZXModCxlKXt0LmFkZEZpZWxkT2Zmc2V0KDIsZSwwKX1zdGF0aWMgc3RhcnREaWN0aW9uYXJpZXNWZWN0b3IodCxlKXt0LnN0YXJ0VmVjdG9yKDI0LGUsOCl9c3RhdGljIGFkZFJlY29yZEJhdGNoZXModCxlKXt0LmFkZEZpZWxkT2Zmc2V0KDMsZSwwKX1zdGF0aWMgc3RhcnRSZWNvcmRCYXRjaGVzVmVjdG9yKHQsZSl7dC5zdGFydFZlY3RvcigyNCxlLDgpfXN0YXRpYyBhZGRDdXN0b21NZXRhZGF0YSh0LGUpe3QuYWRkRmllbGRPZmZzZXQoNCxlLDApfXN0YXRpYyBjcmVhdGVDdXN0b21NZXRhZGF0YVZlY3Rvcih0LGUpe3Quc3RhcnRWZWN0b3IoNCxlLmxlbmd0aCw0KTtmb3IobGV0IHI9ZS5sZW5ndGgtMTtyPj0wO3ItLSl0LmFkZE9mZnNldChlW3JdKTtyZXR1cm4gdC5lbmRWZWN0b3IoKX1zdGF0aWMgc3RhcnRDdXN0b21NZXRhZGF0YVZlY3Rvcih0LGUpe3Quc3RhcnRWZWN0b3IoNCxlLDQpfXN0YXRpYyBlbmRGb290ZXIodCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9c3RhdGljIGZpbmlzaEZvb3RlckJ1ZmZlcih0LGUpe3QuZmluaXNoKGUpfXN0YXRpYyBmaW5pc2hTaXplUHJlZml4ZWRGb290ZXJCdWZmZXIodCxlKXt0LmZpbmlzaChlLHZvaWQgMCwhMCl9fXZhciBfdj1tKCgpPT57TnQoKTthYygpO2hmKCk7dm0oKX0pO2Z1bmN0aW9uIEdmKHQsZSl7cmV0dXJuIG5ldyBNYXAoWy4uLnR8fG5ldyBNYXAsLi4uZXx8bmV3IE1hcF0pfWZ1bmN0aW9uIHFtKHQsZT1uZXcgTWFwKXtmb3IobGV0IHI9LTEsbj10Lmxlbmd0aDsrK3I8bjspe2xldCBzPXRbcl0udHlwZTtpZihCLmlzRGljdGlvbmFyeShzKSl7aWYoIWUuaGFzKHMuaWQpKWUuc2V0KHMuaWQscy5kaWN0aW9uYXJ5KTtlbHNlIGlmKGUuZ2V0KHMuaWQpIT09cy5kaWN0aW9uYXJ5KXRocm93IEVycm9yKCJDYW5ub3QgY3JlYXRlIFNjaGVtYSBjb250YWluaW5nIHR3byBkaWZmZXJlbnQgZGljdGlvbmFyaWVzIHdpdGggdGhlIHNhbWUgSWQiKX1pZihzLmNoaWxkcmVuJiZzLmNoaWxkcmVuLmxlbmd0aD4wKXFtKHMuY2hpbGRyZW4sZSl9cmV0dXJuIGV9dmFyIGd2LGJ2LGx0LFU7dmFyIFVyPW0oKCk9PntMZSgpO2llKCk7Z3Y9U3ltYm9sLmZvcigiYXBhY2hlLWFycm93L1NjaGVtYSIpLGJ2PVN5bWJvbC5mb3IoImFwYWNoZS1hcnJvdy9GaWVsZCIpO2x0PWNsYXNzIGx0e3N0YXRpYyBpc1NjaGVtYSh0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnRbZ3ZdKT09PSEwfWNvbnN0cnVjdG9yKHQ9W10sZSxyLG49JHQuVjUpe2lmKHRoaXMuZmllbGRzPXR8fFtdLHRoaXMubWV0YWRhdGE9ZXx8bmV3IE1hcCwhcilyPXFtKHRoaXMuZmllbGRzKTt0aGlzLmRpY3Rpb25hcmllcz1yLHRoaXMubWV0YWRhdGFWZXJzaW9uPW59Z2V0W1N5bWJvbC50b1N0cmluZ1RhZ10oKXtyZXR1cm4iU2NoZW1hIn1nZXQgbmFtZXMoKXtyZXR1cm4gdGhpcy5maWVsZHMubWFwKCh0KT0+dC5uYW1lKX10b1N0cmluZygpe3JldHVybmBTY2hlbWE8eyAke3RoaXMuZmllbGRzLm1hcCgodCxlKT0+YCR7ZX06ICR7dH1gKS5qb2luKCIsICIpfSB9PmB9c2VsZWN0KHQpe2xldCBlPW5ldyBTZXQodCkscj10aGlzLmZpZWxkcy5maWx0ZXIoKG4pPT5lLmhhcyhuLm5hbWUpKTtyZXR1cm4gbmV3IGx0KHIsdGhpcy5tZXRhZGF0YSl9c2VsZWN0QXQodCl7bGV0IGU9dC5tYXAoKHIpPT50aGlzLmZpZWxkc1tyXSkuZmlsdGVyKEJvb2xlYW4pO3JldHVybiBuZXcgbHQoZSx0aGlzLm1ldGFkYXRhKX1hc3NpZ24oLi4udCl7bGV0IGU9dFswXWluc3RhbmNlb2YgbHQ/dFswXTpBcnJheS5pc0FycmF5KHRbMF0pP25ldyBsdCh0WzBdKTpuZXcgbHQodCkscj1bLi4udGhpcy5maWVsZHNdLG49R2YoR2YobmV3IE1hcCx0aGlzLm1ldGFkYXRhKSxlLm1ldGFkYXRhKSxpPWUuZmllbGRzLmZpbHRlcigobyk9PntsZXQgYT1yLmZpbmRJbmRleCgobCk9PmwubmFtZT09PW8ubmFtZSk7cmV0dXJufmE/KHJbYV09by5jbG9uZSh7bWV0YWRhdGE6R2YoR2YobmV3IE1hcCxyW2FdLm1ldGFkYXRhKSxvLm1ldGFkYXRhKX0pKSYmITE6ITB9KSxzPXFtKGksbmV3IE1hcCk7cmV0dXJuIG5ldyBsdChbLi4uciwuLi5pXSxuLG5ldyBNYXAoWy4uLnRoaXMuZGljdGlvbmFyaWVzLC4uLnNdKSl9fTtsdC5wcm90b3R5cGUuZmllbGRzPW51bGw7bHQucHJvdG90eXBlLm1ldGFkYXRhPW51bGw7bHQucHJvdG90eXBlLmRpY3Rpb25hcmllcz1udWxsO2x0LnByb3RvdHlwZVtndl09ITA7T2JqZWN0LmRlZmluZVByb3BlcnR5KGx0LFN5bWJvbC5oYXNJbnN0YW5jZSx7dmFsdWU6ZnVuY3Rpb24oZSl7cmV0dXJuIEZ1bmN0aW9uLnByb3RvdHlwZVtTeW1ib2wuaGFzSW5zdGFuY2VdLmNhbGwodGhpcyxlKXx8dGhpcz09PWx0JiZsdC5pc1NjaGVtYShlKX19KTtVPWNsYXNzIFV7c3RhdGljIGlzRmllbGQodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0W2J2XSk9PT0hMH1zdGF0aWMgbmV3KC4uLnQpe2xldFtlLHIsbixpXT10O2lmKHRbMF0mJnR5cGVvZiB0WzBdPT09Im9iamVjdCIpKHtuYW1lOmV9PXRbMF0pLHI9PT12b2lkIDAmJihyPXRbMF0udHlwZSksbj09PXZvaWQgMCYmKG49dFswXS5udWxsYWJsZSksaT09PXZvaWQgMCYmKGk9dFswXS5tZXRhZGF0YSk7cmV0dXJuIG5ldyBVKGAke2V9YCxyLG4saSl9Y29uc3RydWN0b3IodCxlLHI9ITEsbil7dGhpcy5uYW1lPXQsdGhpcy50eXBlPWUsdGhpcy5udWxsYWJsZT1yLHRoaXMubWV0YWRhdGE9bnx8bmV3IE1hcH1nZXQgdHlwZUlkKCl7cmV0dXJuIHRoaXMudHlwZS50eXBlSWR9Z2V0W1N5bWJvbC50b1N0cmluZ1RhZ10oKXtyZXR1cm4iRmllbGQifXRvU3RyaW5nKCl7cmV0dXJuYCR7dGhpcy5uYW1lfTogJHt0aGlzLnR5cGV9YH1jbG9uZSguLi50KXtsZXRbZSxyLG4saV09dDtyZXR1cm4hdFswXXx8dHlwZW9mIHRbMF0hPT0ib2JqZWN0Ij9bZT10aGlzLm5hbWUscj10aGlzLnR5cGUsbj10aGlzLm51bGxhYmxlLGk9dGhpcy5tZXRhZGF0YV09dDp7bmFtZTplPXRoaXMubmFtZSx0eXBlOnI9dGhpcy50eXBlLG51bGxhYmxlOm49dGhpcy5udWxsYWJsZSxtZXRhZGF0YTppPXRoaXMubWV0YWRhdGF9PXRbMF0sVS5uZXcoZSxyLG4saSl9fTtVLnByb3RvdHlwZS50eXBlPW51bGw7VS5wcm90b3R5cGUubmFtZT1udWxsO1UucHJvdG90eXBlLm51bGxhYmxlPW51bGw7VS5wcm90b3R5cGUubWV0YWRhdGE9bnVsbDtVLnByb3RvdHlwZVtidl09ITA7T2JqZWN0LmRlZmluZVByb3BlcnR5KFUsU3ltYm9sLmhhc0luc3RhbmNlLHt2YWx1ZTpmdW5jdGlvbihlKXtyZXR1cm4gRnVuY3Rpb24ucHJvdG90eXBlW1N5bWJvbC5oYXNJbnN0YW5jZV0uY2FsbCh0aGlzLGUpfHx0aGlzPT09VSYmVS5pc0ZpZWxkKGUpfX0pfSk7Y2xhc3MgRG97c3RhdGljIGRlY29kZSh0KXt0PW5ldyBTVChDKHQpKTtsZXQgZT10bi5nZXRSb290QXNGb290ZXIodCkscj1sdC5kZWNvZGUoZS5zY2hlbWEoKSxuZXcgTWFwLGUudmVyc2lvbigpKTtyZXR1cm4gbmV3IHd2KHIsZSl9c3RhdGljIGVuY29kZSh0KXtsZXQgZT1uZXcgQlQscj1sdC5lbmNvZGUoZSx0LnNjaGVtYSk7dG4uc3RhcnRSZWNvcmRCYXRjaGVzVmVjdG9yKGUsdC5udW1SZWNvcmRCYXRjaGVzKTtmb3IobGV0IHMgb2ZbLi4udC5yZWNvcmRCYXRjaGVzKCldLnNsaWNlKCkucmV2ZXJzZSgpKVNzLmVuY29kZShlLHMpO2xldCBuPWUuZW5kVmVjdG9yKCk7dG4uc3RhcnREaWN0aW9uYXJpZXNWZWN0b3IoZSx0Lm51bURpY3Rpb25hcmllcyk7Zm9yKGxldCBzIG9mWy4uLnQuZGljdGlvbmFyeUJhdGNoZXMoKV0uc2xpY2UoKS5yZXZlcnNlKCkpU3MuZW5jb2RlKGUscyk7bGV0IGk9ZS5lbmRWZWN0b3IoKTtyZXR1cm4gdG4uc3RhcnRGb290ZXIoZSksdG4uYWRkU2NoZW1hKGUsciksdG4uYWRkVmVyc2lvbihlLCR0LlY1KSx0bi5hZGRSZWNvcmRCYXRjaGVzKGUsbiksdG4uYWRkRGljdGlvbmFyaWVzKGUsaSksdG4uZmluaXNoRm9vdGVyQnVmZmVyKGUsdG4uZW5kRm9vdGVyKGUpKSxlLmFzVWludDhBcnJheSgpfWdldCBudW1SZWNvcmRCYXRjaGVzKCl7cmV0dXJuIHRoaXMuX3JlY29yZEJhdGNoZXMubGVuZ3RofWdldCBudW1EaWN0aW9uYXJpZXMoKXtyZXR1cm4gdGhpcy5fZGljdGlvbmFyeUJhdGNoZXMubGVuZ3RofWNvbnN0cnVjdG9yKHQsZT0kdC5WNSxyLG4pe3RoaXMuc2NoZW1hPXQsdGhpcy52ZXJzaW9uPWUsciYmKHRoaXMuX3JlY29yZEJhdGNoZXM9ciksbiYmKHRoaXMuX2RpY3Rpb25hcnlCYXRjaGVzPW4pfSpyZWNvcmRCYXRjaGVzKCl7Zm9yKGxldCB0LGU9LTEscj10aGlzLm51bVJlY29yZEJhdGNoZXM7KytlPHI7KWlmKHQ9dGhpcy5nZXRSZWNvcmRCYXRjaChlKSl5aWVsZCB0fSpkaWN0aW9uYXJ5QmF0Y2hlcygpe2ZvcihsZXQgdCxlPS0xLHI9dGhpcy5udW1EaWN0aW9uYXJpZXM7KytlPHI7KWlmKHQ9dGhpcy5nZXREaWN0aW9uYXJ5QmF0Y2goZSkpeWllbGQgdH1nZXRSZWNvcmRCYXRjaCh0KXtyZXR1cm4gdD49MCYmdDx0aGlzLm51bVJlY29yZEJhdGNoZXMmJnRoaXMuX3JlY29yZEJhdGNoZXNbdF18fG51bGx9Z2V0RGljdGlvbmFyeUJhdGNoKHQpe3JldHVybiB0Pj0wJiZ0PHRoaXMubnVtRGljdGlvbmFyaWVzJiZ0aGlzLl9kaWN0aW9uYXJ5QmF0Y2hlc1t0XXx8bnVsbH19Y2xhc3MgU3N7c3RhdGljIGRlY29kZSh0KXtyZXR1cm4gbmV3IFNzKHQubWV0YURhdGFMZW5ndGgoKSx0LmJvZHlMZW5ndGgoKSx0Lm9mZnNldCgpKX1zdGF0aWMgZW5jb2RlKHQsZSl7bGV0e21ldGFEYXRhTGVuZ3RoOnJ9PWUsbj1CaWdJbnQoZS5vZmZzZXQpLGk9QmlnSW50KGUuYm9keUxlbmd0aCk7cmV0dXJuIEJjLmNyZWF0ZUJsb2NrKHQsbixyLGkpfWNvbnN0cnVjdG9yKHQsZSxyKXt0aGlzLm1ldGFEYXRhTGVuZ3RoPXQsdGhpcy5vZmZzZXQ9UHQociksdGhpcy5ib2R5TGVuZ3RoPVB0KGUpfX12YXIgQlQsU1Qsd3Y7dmFyIFdtPW0oKCk9PntfdigpO050KCk7VXIoKTtMZSgpO2plKCk7QlQ9YWEsU1Q9bHI7d3Y9Y2xhc3Mgd3YgZXh0ZW5kcyBEb3tnZXQgbnVtUmVjb3JkQmF0Y2hlcygpe3JldHVybiB0aGlzLl9mb290ZXIucmVjb3JkQmF0Y2hlc0xlbmd0aCgpfWdldCBudW1EaWN0aW9uYXJpZXMoKXtyZXR1cm4gdGhpcy5fZm9vdGVyLmRpY3Rpb25hcmllc0xlbmd0aCgpfWNvbnN0cnVjdG9yKHQsZSl7c3VwZXIodCxlLnZlcnNpb24oKSk7dGhpcy5fZm9vdGVyPWV9Z2V0UmVjb3JkQmF0Y2godCl7aWYodD49MCYmdDx0aGlzLm51bVJlY29yZEJhdGNoZXMpe2xldCBlPXRoaXMuX2Zvb3Rlci5yZWNvcmRCYXRjaGVzKHQpO2lmKGUpcmV0dXJuIFNzLmRlY29kZShlKX1yZXR1cm4gbnVsbH1nZXREaWN0aW9uYXJ5QmF0Y2godCl7aWYodD49MCYmdDx0aGlzLm51bURpY3Rpb25hcmllcyl7bGV0IGU9dGhpcy5fZm9vdGVyLmRpY3Rpb25hcmllcyh0KTtpZihlKXJldHVybiBTcy5kZWNvZGUoZSl9cmV0dXJuIG51bGx9fX0pO2NsYXNzIERle2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc01lc3NhZ2UodCxlKXtyZXR1cm4oZXx8bmV3IERlKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc01lc3NhZ2UodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTSksKGV8fG5ldyBEZSkuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXZlcnNpb24oKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDQpO3JldHVybiB0P3RoaXMuYmIucmVhZEludDE2KHRoaXMuYmJfcG9zK3QpOiR0LlYxfWhlYWRlclR5cGUoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDYpO3JldHVybiB0P3RoaXMuYmIucmVhZFVpbnQ4KHRoaXMuYmJfcG9zK3QpOnh0Lk5PTkV9aGVhZGVyKHQpe2xldCBlPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsOCk7cmV0dXJuIGU/dGhpcy5iYi5fX3VuaW9uKHQsdGhpcy5iYl9wb3MrZSk6bnVsbH1ib2R5TGVuZ3RoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3BvcywxMCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50NjQodGhpcy5iYl9wb3MrdCk6QmlnSW50KCIwIil9Y3VzdG9tTWV0YWRhdGEodCxlKXtsZXQgcj10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDEyKTtyZXR1cm4gcj8oZXx8bmV3IG5lKS5fX2luaXQodGhpcy5iYi5fX2luZGlyZWN0KHRoaXMuYmIuX192ZWN0b3IodGhpcy5iYl9wb3MrcikrdCo0KSx0aGlzLmJiKTpudWxsfWN1c3RvbU1ldGFkYXRhTGVuZ3RoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3BvcywxMik7cmV0dXJuIHQ/dGhpcy5iYi5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MrdCk6MH1zdGF0aWMgc3RhcnRNZXNzYWdlKHQpe3Quc3RhcnRPYmplY3QoNSl9c3RhdGljIGFkZFZlcnNpb24odCxlKXt0LmFkZEZpZWxkSW50MTYoMCxlLCR0LlYxKX1zdGF0aWMgYWRkSGVhZGVyVHlwZSh0LGUpe3QuYWRkRmllbGRJbnQ4KDEsZSx4dC5OT05FKX1zdGF0aWMgYWRkSGVhZGVyKHQsZSl7dC5hZGRGaWVsZE9mZnNldCgyLGUsMCl9c3RhdGljIGFkZEJvZHlMZW5ndGgodCxlKXt0LmFkZEZpZWxkSW50NjQoMyxlLEJpZ0ludCgiMCIpKX1zdGF0aWMgYWRkQ3VzdG9tTWV0YWRhdGEodCxlKXt0LmFkZEZpZWxkT2Zmc2V0KDQsZSwwKX1zdGF0aWMgY3JlYXRlQ3VzdG9tTWV0YWRhdGFWZWN0b3IodCxlKXt0LnN0YXJ0VmVjdG9yKDQsZS5sZW5ndGgsNCk7Zm9yKGxldCByPWUubGVuZ3RoLTE7cj49MDtyLS0pdC5hZGRPZmZzZXQoZVtyXSk7cmV0dXJuIHQuZW5kVmVjdG9yKCl9c3RhdGljIHN0YXJ0Q3VzdG9tTWV0YWRhdGFWZWN0b3IodCxlKXt0LnN0YXJ0VmVjdG9yKDQsZSw0KX1zdGF0aWMgZW5kTWVzc2FnZSh0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgZmluaXNoTWVzc2FnZUJ1ZmZlcih0LGUpe3QuZmluaXNoKGUpfXN0YXRpYyBmaW5pc2hTaXplUHJlZml4ZWRNZXNzYWdlQnVmZmVyKHQsZSl7dC5maW5pc2goZSx2b2lkIDAsITApfXN0YXRpYyBjcmVhdGVNZXNzYWdlKHQsZSxyLG4saSxzKXtyZXR1cm4gRGUuc3RhcnRNZXNzYWdlKHQpLERlLmFkZFZlcnNpb24odCxlKSxEZS5hZGRIZWFkZXJUeXBlKHQsciksRGUuYWRkSGVhZGVyKHQsbiksRGUuYWRkQm9keUxlbmd0aCh0LGkpLERlLmFkZEN1c3RvbU1ldGFkYXRhKHQscyksRGUuZW5kTWVzc2FnZSh0KX19dmFyIHZ2PW0oKCk9PntOdCgpO2FjKCk7SW0oKTtoZigpfSk7dmFyIEl2LEpmO3ZhciBCdj1tKCgpPT57VWkoKTtWYigpO3lmKCk7aG0oKTtMYigpO1ViKCk7Q2IoKTtSYigpO2piKCk7JGIoKTtQYigpO2xtKCk7Y20oKTt5bSgpO19tKCk7cG0oKTt1bSgpO2tiKCk7emIoKTtnbSgpO2FtKCk7Zm0oKTtkbSgpO21tKCk7SXY9Y2xhc3MgSXYgZXh0ZW5kcyBldHt2aXNpdCh0LGUpe3JldHVybiB0PT1udWxsfHxlPT1udWxsP3ZvaWQgMDpzdXBlci52aXNpdCh0LGUpfXZpc2l0TnVsbCh0LGUpe3JldHVybiB1by5zdGFydE51bGwoZSksdW8uZW5kTnVsbChlKX12aXNpdEludCh0LGUpe3JldHVybiBici5zdGFydEludChlKSxici5hZGRCaXRXaWR0aChlLHQuYml0V2lkdGgpLGJyLmFkZElzU2lnbmVkKGUsdC5pc1NpZ25lZCksYnIuZW5kSW50KGUpfXZpc2l0RmxvYXQodCxlKXtyZXR1cm4gSG4uc3RhcnRGbG9hdGluZ1BvaW50KGUpLEhuLmFkZFByZWNpc2lvbihlLHQucHJlY2lzaW9uKSxIbi5lbmRGbG9hdGluZ1BvaW50KGUpfXZpc2l0QmluYXJ5KHQsZSl7cmV0dXJuIGlvLnN0YXJ0QmluYXJ5KGUpLGlvLmVuZEJpbmFyeShlKX12aXNpdEJpbmFyeVZpZXcodCxlKXtyZXR1cm4gc28uc3RhcnRCaW5hcnlWaWV3KGUpLHNvLmVuZEJpbmFyeVZpZXcoZSl9dmlzaXRMYXJnZUJpbmFyeSh0LGUpe3JldHVybiBhby5zdGFydExhcmdlQmluYXJ5KGUpLGFvLmVuZExhcmdlQmluYXJ5KGUpfXZpc2l0Qm9vbCh0LGUpe3JldHVybiBvby5zdGFydEJvb2woZSksb28uZW5kQm9vbChlKX12aXNpdFV0ZjgodCxlKXtyZXR1cm4gaG8uc3RhcnRVdGY4KGUpLGhvLmVuZFV0ZjgoZSl9dmlzaXRVdGY4Vmlldyh0LGUpe3JldHVybiBwby5zdGFydFV0ZjhWaWV3KGUpLHBvLmVuZFV0ZjhWaWV3KGUpfXZpc2l0TGFyZ2VVdGY4KHQsZSl7cmV0dXJuIGNvLnN0YXJ0TGFyZ2VVdGY4KGUpLGNvLmVuZExhcmdlVXRmOChlKX12aXNpdERlY2ltYWwodCxlKXtyZXR1cm4gd3Iuc3RhcnREZWNpbWFsKGUpLHdyLmFkZFNjYWxlKGUsdC5zY2FsZSksd3IuYWRkUHJlY2lzaW9uKGUsdC5wcmVjaXNpb24pLHdyLmFkZEJpdFdpZHRoKGUsdC5iaXRXaWR0aCksd3IuZW5kRGVjaW1hbChlKX12aXNpdERhdGUodCxlKXtyZXR1cm4gam4uc3RhcnREYXRlKGUpLGpuLmFkZFVuaXQoZSx0LnVuaXQpLGpuLmVuZERhdGUoZSl9dmlzaXRUaW1lKHQsZSl7cmV0dXJuIEpyLnN0YXJ0VGltZShlKSxKci5hZGRVbml0KGUsdC51bml0KSxKci5hZGRCaXRXaWR0aChlLHQuYml0V2lkdGgpLEpyLmVuZFRpbWUoZSl9dmlzaXRUaW1lc3RhbXAodCxlKXtsZXQgcj10LnRpbWV6b25lJiZlLmNyZWF0ZVN0cmluZyh0LnRpbWV6b25lKXx8dm9pZCAwO2lmKFhyLnN0YXJ0VGltZXN0YW1wKGUpLFhyLmFkZFVuaXQoZSx0LnVuaXQpLHIhPT12b2lkIDApWHIuYWRkVGltZXpvbmUoZSxyKTtyZXR1cm4gWHIuZW5kVGltZXN0YW1wKGUpfXZpc2l0SW50ZXJ2YWwodCxlKXtyZXR1cm4gWW4uc3RhcnRJbnRlcnZhbChlKSxZbi5hZGRVbml0KGUsdC51bml0KSxZbi5lbmRJbnRlcnZhbChlKX12aXNpdER1cmF0aW9uKHQsZSl7cmV0dXJuICRuLnN0YXJ0RHVyYXRpb24oZSksJG4uYWRkVW5pdChlLHQudW5pdCksJG4uZW5kRHVyYXRpb24oZSl9dmlzaXRMaXN0KHQsZSl7cmV0dXJuIGxvLnN0YXJ0TGlzdChlKSxsby5lbmRMaXN0KGUpfXZpc2l0U3RydWN0KHQsZSl7cmV0dXJuIGZvLnN0YXJ0U3RydWN0XyhlKSxmby5lbmRTdHJ1Y3RfKGUpfXZpc2l0VW5pb24odCxlKXt2ci5zdGFydFR5cGVJZHNWZWN0b3IoZSx0LnR5cGVJZHMubGVuZ3RoKTtsZXQgcj12ci5jcmVhdGVUeXBlSWRzVmVjdG9yKGUsdC50eXBlSWRzKTtyZXR1cm4gdnIuc3RhcnRVbmlvbihlKSx2ci5hZGRNb2RlKGUsdC5tb2RlKSx2ci5hZGRUeXBlSWRzKGUsciksdnIuZW5kVW5pb24oZSl9dmlzaXREaWN0aW9uYXJ5KHQsZSl7bGV0IHI9dGhpcy52aXNpdCh0LmluZGljZXMsZSk7aWYoSWkuc3RhcnREaWN0aW9uYXJ5RW5jb2RpbmcoZSksSWkuYWRkSWQoZSxCaWdJbnQodC5pZCkpLElpLmFkZElzT3JkZXJlZChlLHQuaXNPcmRlcmVkKSxyIT09dm9pZCAwKUlpLmFkZEluZGV4VHlwZShlLHIpO3JldHVybiBJaS5lbmREaWN0aW9uYXJ5RW5jb2RpbmcoZSl9dmlzaXRGaXhlZFNpemVCaW5hcnkodCxlKXtyZXR1cm4gcW4uc3RhcnRGaXhlZFNpemVCaW5hcnkoZSkscW4uYWRkQnl0ZVdpZHRoKGUsdC5ieXRlV2lkdGgpLHFuLmVuZEZpeGVkU2l6ZUJpbmFyeShlKX12aXNpdEZpeGVkU2l6ZUxpc3QodCxlKXtyZXR1cm4gV24uc3RhcnRGaXhlZFNpemVMaXN0KGUpLFduLmFkZExpc3RTaXplKGUsdC5saXN0U2l6ZSksV24uZW5kRml4ZWRTaXplTGlzdChlKX12aXNpdE1hcCh0LGUpe3JldHVybiBLbi5zdGFydE1hcChlKSxLbi5hZGRLZXlzU29ydGVkKGUsdC5rZXlzU29ydGVkKSxLbi5lbmRNYXAoZSl9fTtKZj1uZXcgSXZ9KTtmdW5jdGlvbiB4dih0LGU9bmV3IE1hcCl7cmV0dXJuIG5ldyBsdChBVCh0LGUpLFhmKHQubWV0YWRhdGEpLGUpfWZ1bmN0aW9uIEhtKHQpe3JldHVybiBuZXcgV2UodC5jb3VudCxFdih0LmNvbHVtbnMpLE92KHQuY29sdW1ucyksbnVsbCxOdih0LmNvbHVtbnMpKX1mdW5jdGlvbiBUdih0KXtyZXR1cm4gbmV3IFJyKEhtKHQuZGF0YSksdC5pZCx0LmlzRGVsdGEpfWZ1bmN0aW9uIEFUKHQsZSl7cmV0dXJuKHQuZmllbGRzfHxbXSkuZmlsdGVyKEJvb2xlYW4pLm1hcCgocik9PlUuZnJvbUpTT04ocixlKSl9ZnVuY3Rpb24gU3YodCxlKXtyZXR1cm4odC5jaGlsZHJlbnx8W10pLmZpbHRlcihCb29sZWFuKS5tYXAoKHIpPT5VLmZyb21KU09OKHIsZSkpfWZ1bmN0aW9uIEV2KHQpe3JldHVybih0fHxbXSkucmVkdWNlKChlLHIpPT5bLi4uZSxuZXcgQ2koci5jb3VudCxEVChyLlZBTElESVRZKSksLi4uRXYoci5jaGlsZHJlbildLFtdKX1mdW5jdGlvbiBPdih0LGU9W10pe2ZvcihsZXQgcj0tMSxuPSh0fHxbXSkubGVuZ3RoOysrcjxuOyl7bGV0IGk9dFtyXTtpZihpLlZBTElESVRZJiZlLnB1c2gobmV3IHhlKGUubGVuZ3RoLGkuVkFMSURJVFkubGVuZ3RoKSksaS5UWVBFX0lEJiZlLnB1c2gobmV3IHhlKGUubGVuZ3RoLGkuVFlQRV9JRC5sZW5ndGgpKSxpLk9GRlNFVCYmZS5wdXNoKG5ldyB4ZShlLmxlbmd0aCxpLk9GRlNFVC5sZW5ndGgpKSxpLkRBVEEmJmUucHVzaChuZXcgeGUoZS5sZW5ndGgsaS5EQVRBLmxlbmd0aCkpLGkuVklFV1MmJmUucHVzaChuZXcgeGUoZS5sZW5ndGgsaS5WSUVXUy5sZW5ndGgpKSxpLlZBUklBRElDX0RBVEFfQlVGRkVSUylmb3IobGV0IHMgb2YgaS5WQVJJQURJQ19EQVRBX0JVRkZFUlMpZS5wdXNoKG5ldyB4ZShlLmxlbmd0aCxzLmxlbmd0aCkpO2U9T3YoaS5jaGlsZHJlbixlKX1yZXR1cm4gZX1mdW5jdGlvbiBEVCh0KXtyZXR1cm4odHx8W10pLnJlZHVjZSgoZSxyKT0+ZSsgKyhyPT09MCksMCl9ZnVuY3Rpb24gTnYodCl7cmV0dXJuKHR8fFtdKS5yZWR1Y2UoKGUscik9PlsuLi5lLC4uLnIuVkFSSUFESUNfREFUQV9CVUZGRVJTP1tyLlZBUklBRElDX0RBVEFfQlVGRkVSUy5sZW5ndGhdOltdLC4uLk52KHIuY2hpbGRyZW4pXSxbXSl9ZnVuY3Rpb24gRnYodCxlKXtsZXQgcixuLGkscyxvLGE7aWYoIWV8fCEocz10LmRpY3Rpb25hcnkpKW89RHYodCxTdih0LGUpKSxpPW5ldyBVKHQubmFtZSxvLHQubnVsbGFibGUsWGYodC5tZXRhZGF0YSkpO2Vsc2UgaWYoIWUuaGFzKHI9cy5pZCkpbj0obj1zLmluZGV4VHlwZSk/QXYobik6bmV3IEJyLGUuc2V0KHIsbz1Edih0LFN2KHQsZSkpKSxhPW5ldyBmcihvLG4scixzLmlzT3JkZXJlZCksaT1uZXcgVSh0Lm5hbWUsYSx0Lm51bGxhYmxlLFhmKHQubWV0YWRhdGEpKTtlbHNlIG49KG49cy5pbmRleFR5cGUpP0F2KG4pOm5ldyBCcixhPW5ldyBmcihlLmdldChyKSxuLHIscy5pc09yZGVyZWQpLGk9bmV3IFUodC5uYW1lLGEsdC5udWxsYWJsZSxYZih0Lm1ldGFkYXRhKSk7cmV0dXJuIGl8fG51bGx9ZnVuY3Rpb24gWGYodD1bXSl7cmV0dXJuIG5ldyBNYXAodC5tYXAoKHtrZXk6ZSx2YWx1ZTpyfSk9PltlLHJdKSl9ZnVuY3Rpb24gQXYodCl7cmV0dXJuIG5ldyAkZSh0LmlzU2lnbmVkLHQuYml0V2lkdGgpfWZ1bmN0aW9uIER2KHQsZSl7bGV0IHI9dC50eXBlLm5hbWU7c3dpdGNoKHIpe2Nhc2UiTk9ORSI6cmV0dXJuIG5ldyB3ZTtjYXNlIm51bGwiOnJldHVybiBuZXcgd2U7Y2FzZSJiaW5hcnkiOnJldHVybiBuZXcgQWk7Y2FzZSJsYXJnZWJpbmFyeSI6cmV0dXJuIG5ldyBEaTtjYXNlImJpbmFyeXZpZXciOnJldHVybiBuZXcgX3Q7Y2FzZSJ1dGY4IjpyZXR1cm4gbmV3IElyO2Nhc2UibGFyZ2V1dGY4IjpyZXR1cm4gbmV3IHhpO2Nhc2UidXRmOHZpZXciOnJldHVybiBuZXcgZ247Y2FzZSJib29sIjpyZXR1cm4gbmV3IFVlO2Nhc2UibGlzdCI6cmV0dXJuIG5ldyBMcigoZXx8W10pWzBdKTtjYXNlInN0cnVjdCI6cmV0dXJuIG5ldyBFdChlfHxbXSk7Y2FzZSJzdHJ1Y3RfIjpyZXR1cm4gbmV3IEV0KGV8fFtdKX1zd2l0Y2gocil7Y2FzZSJpbnQiOntsZXQgbj10LnR5cGU7cmV0dXJuIG5ldyAkZShuLmlzU2lnbmVkLG4uYml0V2lkdGgpfWNhc2UiZmxvYXRpbmdwb2ludCI6e2xldCBuPXQudHlwZTtyZXR1cm4gbmV3IEduKFp0W24ucHJlY2lzaW9uXSl9Y2FzZSJkZWNpbWFsIjp7bGV0IG49dC50eXBlO3JldHVybiBuZXcgVGkobi5zY2FsZSxuLnByZWNpc2lvbixuLmJpdFdpZHRoKX1jYXNlImRhdGUiOntsZXQgbj10LnR5cGU7cmV0dXJuIG5ldyBFaShxdFtuLnVuaXRdKX1jYXNlInRpbWUiOntsZXQgbj10LnR5cGU7cmV0dXJuIG5ldyBPaShUW24udW5pdF0sbi5iaXRXaWR0aCl9Y2FzZSJ0aW1lc3RhbXAiOntsZXQgbj10LnR5cGU7cmV0dXJuIG5ldyBKbihUW24udW5pdF0sbi50aW1lem9uZSl9Y2FzZSJpbnRlcnZhbCI6e2xldCBuPXQudHlwZTtyZXR1cm4gbmV3IE5pKGp0W24udW5pdF0pfWNhc2UiZHVyYXRpb24iOntsZXQgbj10LnR5cGU7cmV0dXJuIG5ldyBGaShUW24udW5pdF0pfWNhc2UidW5pb24iOntsZXQgbj10LnR5cGUsW2ksLi4uc109KG4ubW9kZSsiIikudG9Mb3dlckNhc2UoKSxvPWkudG9VcHBlckNhc2UoKStzLmpvaW4oIiIpO3JldHVybiBuZXcgYm4oTHRbb10sbi50eXBlSWRzfHxbXSxlfHxbXSl9Y2FzZSJmaXhlZHNpemViaW5hcnkiOntsZXQgbj10LnR5cGU7cmV0dXJuIG5ldyBNaShuLmJ5dGVXaWR0aCl9Y2FzZSJmaXhlZHNpemVsaXN0Ijp7bGV0IG49dC50eXBlO3JldHVybiBuZXcgd24obi5saXN0U2l6ZSwoZXx8W10pWzBdKX1jYXNlIm1hcCI6e2xldCBuPXQudHlwZTtyZXR1cm4gbmV3IHZuKChlfHxbXSlbMF0sbi5rZXlzU29ydGVkKX19dGhyb3cgRXJyb3IoYFVucmVjb2duaXplZCB0eXBlOiAiJHtyfSJgKX12YXIgTXY9bSgoKT0+e1VyKCk7aWUoKTt5YSgpO0xlKCl9KTtjbGFzcyB0cntzdGF0aWMgZnJvbUpTT04odCxlKXtsZXQgcj1uZXcgdHIoMCwkdC5WNSxlKTtyZXR1cm4gci5fY3JlYXRlSGVhZGVyPUVUKHQsZSkscn1zdGF0aWMgZGVjb2RlKHQpe3Q9bmV3IFRUKEModCkpO2xldCBlPURlLmdldFJvb3RBc01lc3NhZ2UodCkscj1lLmJvZHlMZW5ndGgoKSxuPWUudmVyc2lvbigpLGk9ZS5oZWFkZXJUeXBlKCkscz16VChlKSxvPW5ldyB0cihyLG4saSx2b2lkIDAscyk7cmV0dXJuIG8uX2NyZWF0ZUhlYWRlcj1PVChlLGkpLG99c3RhdGljIGVuY29kZSh0KXtsZXQgZT1uZXcgeFQscj0tMTtpZih0LmlzU2NoZW1hKCkpcj1sdC5lbmNvZGUoZSx0LmhlYWRlcigpKTtlbHNlIGlmKHQuaXNSZWNvcmRCYXRjaCgpKXI9V2UuZW5jb2RlKGUsdC5oZWFkZXIoKSk7ZWxzZSBpZih0LmlzRGljdGlvbmFyeUJhdGNoKCkpcj1Sci5lbmNvZGUoZSx0LmhlYWRlcigpKTtsZXQgbj0hKHQubWV0YWRhdGEmJnQubWV0YWRhdGEuc2l6ZT4wKT8tMTpEZS5jcmVhdGVDdXN0b21NZXRhZGF0YVZlY3RvcihlLFsuLi50Lm1ldGFkYXRhXS5tYXAoKFtpLHNdKT0+e2xldCBvPWUuY3JlYXRlU3RyaW5nKGAke2l9YCksYT1lLmNyZWF0ZVN0cmluZyhgJHtzfWApO3JldHVybiBuZS5zdGFydEtleVZhbHVlKGUpLG5lLmFkZEtleShlLG8pLG5lLmFkZFZhbHVlKGUsYSksbmUuZW5kS2V5VmFsdWUoZSl9KSk7aWYoRGUuc3RhcnRNZXNzYWdlKGUpLERlLmFkZFZlcnNpb24oZSwkdC5WNSksRGUuYWRkSGVhZGVyKGUsciksRGUuYWRkSGVhZGVyVHlwZShlLHQuaGVhZGVyVHlwZSksRGUuYWRkQm9keUxlbmd0aChlLEJpZ0ludCh0LmJvZHlMZW5ndGgpKSxuIT09LTEpRGUuYWRkQ3VzdG9tTWV0YWRhdGEoZSxuKTtyZXR1cm4gRGUuZmluaXNoTWVzc2FnZUJ1ZmZlcihlLERlLmVuZE1lc3NhZ2UoZSkpLGUuYXNVaW50OEFycmF5KCl9c3RhdGljIGZyb20odCxlPTApe2lmKHQgaW5zdGFuY2VvZiBsdClyZXR1cm4gbmV3IHRyKDAsJHQuVjUseHQuU2NoZW1hLHQpO2lmKHQgaW5zdGFuY2VvZiBXZSlyZXR1cm4gbmV3IHRyKGUsJHQuVjUseHQuUmVjb3JkQmF0Y2gsdCx0Lm1ldGFkYXRhKTtpZih0IGluc3RhbmNlb2YgUnIpcmV0dXJuIG5ldyB0cihlLCR0LlY1LHh0LkRpY3Rpb25hcnlCYXRjaCx0KTt0aHJvdyBFcnJvcihgVW5yZWNvZ25pemVkIE1lc3NhZ2UgaGVhZGVyOiAke3R9YCl9Z2V0IHR5cGUoKXtyZXR1cm4gdGhpcy5oZWFkZXJUeXBlfWdldCB2ZXJzaW9uKCl7cmV0dXJuIHRoaXMuX3ZlcnNpb259Z2V0IGhlYWRlclR5cGUoKXtyZXR1cm4gdGhpcy5faGVhZGVyVHlwZX1nZXQgY29tcHJlc3Npb24oKXtyZXR1cm4gdGhpcy5fY29tcHJlc3Npb259Z2V0IGJvZHlMZW5ndGgoKXtyZXR1cm4gdGhpcy5fYm9keUxlbmd0aH1nZXQgbWV0YWRhdGEoKXtyZXR1cm4gdGhpcy5fbWV0YWRhdGF9aGVhZGVyKCl7cmV0dXJuIHRoaXMuX2NyZWF0ZUhlYWRlcigpfWlzU2NoZW1hKCl7cmV0dXJuIHRoaXMuaGVhZGVyVHlwZT09PXh0LlNjaGVtYX1pc1JlY29yZEJhdGNoKCl7cmV0dXJuIHRoaXMuaGVhZGVyVHlwZT09PXh0LlJlY29yZEJhdGNofWlzRGljdGlvbmFyeUJhdGNoKCl7cmV0dXJuIHRoaXMuaGVhZGVyVHlwZT09PXh0LkRpY3Rpb25hcnlCYXRjaH1jb25zdHJ1Y3Rvcih0LGUscixuLGkpe3RoaXMuX3ZlcnNpb249ZSx0aGlzLl9oZWFkZXJUeXBlPXIsdGhpcy5ib2R5PW5ldyBVaW50OEFycmF5KDApLHRoaXMuX2NvbXByZXNzaW9uPW49PT1udWxsfHxuPT09dm9pZCAwP3ZvaWQgMDpuLmNvbXByZXNzaW9uLG4mJih0aGlzLl9jcmVhdGVIZWFkZXI9KCk9Pm4pLHRoaXMuX2JvZHlMZW5ndGg9UHQodCksdGhpcy5fbWV0YWRhdGE9aXx8bmV3IE1hcH19Y2xhc3MgV2V7Z2V0IG5vZGVzKCl7cmV0dXJuIHRoaXMuX25vZGVzfWdldCBsZW5ndGgoKXtyZXR1cm4gdGhpcy5fbGVuZ3RofWdldCBidWZmZXJzKCl7cmV0dXJuIHRoaXMuX2J1ZmZlcnN9Z2V0IGNvbXByZXNzaW9uKCl7cmV0dXJuIHRoaXMuX2NvbXByZXNzaW9ufWdldCB2YXJpYWRpY0J1ZmZlckNvdW50cygpe3JldHVybiB0aGlzLl92YXJpYWRpY0J1ZmZlckNvdW50c31nZXQgbWV0YWRhdGEoKXtyZXR1cm4gdGhpcy5fbWV0YWRhdGF9Y29uc3RydWN0b3IodCxlLHIsbixpPVtdLHMpe3RoaXMuX25vZGVzPWUsdGhpcy5fYnVmZmVycz1yLHRoaXMuX2xlbmd0aD1QdCh0KSx0aGlzLl9jb21wcmVzc2lvbj1uLHRoaXMuX3ZhcmlhZGljQnVmZmVyQ291bnRzPWksdGhpcy5fbWV0YWRhdGE9c3x8bmV3IE1hcH19Y2xhc3MgUnJ7Z2V0IGlkKCl7cmV0dXJuIHRoaXMuX2lkfWdldCBkYXRhKCl7cmV0dXJuIHRoaXMuX2RhdGF9Z2V0IGlzRGVsdGEoKXtyZXR1cm4gdGhpcy5faXNEZWx0YX1nZXQgbGVuZ3RoKCl7cmV0dXJuIHRoaXMuZGF0YS5sZW5ndGh9Z2V0IG5vZGVzKCl7cmV0dXJuIHRoaXMuZGF0YS5ub2Rlc31nZXQgYnVmZmVycygpe3JldHVybiB0aGlzLmRhdGEuYnVmZmVyc31jb25zdHJ1Y3Rvcih0LGUscj0hMSl7dGhpcy5fZGF0YT10LHRoaXMuX2lzRGVsdGE9cix0aGlzLl9pZD1QdChlKX19Y2xhc3MgeGV7Y29uc3RydWN0b3IodCxlKXt0aGlzLm9mZnNldD1QdCh0KSx0aGlzLmxlbmd0aD1QdChlKX19Y2xhc3MgQ2l7Y29uc3RydWN0b3IodCxlKXt0aGlzLmxlbmd0aD1QdCh0KSx0aGlzLm51bGxDb3VudD1QdChlKX19Y2xhc3MgU2N7Y29uc3RydWN0b3IodCxlPWNhLkJVRkZFUil7dGhpcy50eXBlPXQsdGhpcy5tZXRob2Q9ZX19ZnVuY3Rpb24gRVQodCxlKXtyZXR1cm4oKT0+e3N3aXRjaChlKXtjYXNlIHh0LlNjaGVtYTpyZXR1cm4gbHQuZnJvbUpTT04odCk7Y2FzZSB4dC5SZWNvcmRCYXRjaDpyZXR1cm4gV2UuZnJvbUpTT04odCk7Y2FzZSB4dC5EaWN0aW9uYXJ5QmF0Y2g6cmV0dXJuIFJyLmZyb21KU09OKHQpfXRocm93IEVycm9yKGBVbnJlY29nbml6ZWQgTWVzc2FnZSB0eXBlOiB7IG5hbWU6ICR7eHRbZV19LCB0eXBlOiAke2V9IH1gKX19ZnVuY3Rpb24gT1QodCxlKXtyZXR1cm4oKT0+e3N3aXRjaChlKXtjYXNlIHh0LlNjaGVtYTpyZXR1cm4gbHQuZGVjb2RlKHQuaGVhZGVyKG5ldyBBZSksbmV3IE1hcCx0LnZlcnNpb24oKSk7Y2FzZSB4dC5SZWNvcmRCYXRjaDpyZXR1cm4gV2UuZGVjb2RlKHQuaGVhZGVyKG5ldyB1ciksdC52ZXJzaW9uKCkpO2Nhc2UgeHQuRGljdGlvbmFyeUJhdGNoOnJldHVybiBSci5kZWNvZGUodC5oZWFkZXIobmV3IHNzKSx0LnZlcnNpb24oKSl9dGhyb3cgRXJyb3IoYFVucmVjb2duaXplZCBNZXNzYWdlIHR5cGU6IHsgbmFtZTogJHt4dFtlXX0sIHR5cGU6ICR7ZX0gfWApfX1mdW5jdGlvbiBOVCh0LGU9bmV3IE1hcCxyPSR0LlY1KXtsZXQgbj1rVCh0LGUpO3JldHVybiBuZXcgbHQobixaZih0KSxlLHIpfWZ1bmN0aW9uIEZUKHQsZT0kdC5WNSl7cmV0dXJuIG5ldyBXZSh0Lmxlbmd0aCgpLFJUKHQpLENUKHQsZSksQ3YodC5jb21wcmVzc2lvbigpKSxQVCh0KSl9ZnVuY3Rpb24gTVQodCxlPSR0LlY1KXtyZXR1cm4gbmV3IFJyKFdlLmRlY29kZSh0LmRhdGEoKSxlKSx0LmlkKCksdC5pc0RlbHRhKCkpfWZ1bmN0aW9uIExUKHQpe3JldHVybiBuZXcgeGUodC5vZmZzZXQoKSx0Lmxlbmd0aCgpKX1mdW5jdGlvbiBVVCh0KXtyZXR1cm4gbmV3IENpKHQubGVuZ3RoKCksdC5udWxsQ291bnQoKSl9ZnVuY3Rpb24gUlQodCl7bGV0IGU9W107Zm9yKGxldCByLG49LTEsaT0tMSxzPXQubm9kZXNMZW5ndGgoKTsrK248czspaWYocj10Lm5vZGVzKG4pKWVbKytpXT1DaS5kZWNvZGUocik7cmV0dXJuIGV9ZnVuY3Rpb24gQ1QodCxlKXtsZXQgcj1bXTtmb3IobGV0IG4saT0tMSxzPS0xLG89dC5idWZmZXJzTGVuZ3RoKCk7KytpPG87KWlmKG49dC5idWZmZXJzKGkpKXtpZihlPCR0LlY0KW4uYmJfcG9zKz04KihpKzEpO3JbKytzXT14ZS5kZWNvZGUobil9cmV0dXJuIHJ9ZnVuY3Rpb24gUFQodCl7bGV0IGU9W10scj1NYXRoLnRydW5jKHQudmFyaWFkaWNCdWZmZXJDb3VudHNMZW5ndGgoKSk7Zm9yKGxldCBuPTA7bjxyOysrbillLnB1c2goUHQodC52YXJpYWRpY0J1ZmZlckNvdW50cyhuKSkpO3JldHVybiBlfWZ1bmN0aW9uIGtUKHQsZSl7bGV0IHI9W107Zm9yKGxldCBuLGk9LTEscz0tMSxvPXQuZmllbGRzTGVuZ3RoKCk7KytpPG87KWlmKG49dC5maWVsZHMoaSkpclsrK3NdPVUuZGVjb2RlKG4sZSk7cmV0dXJuIHJ9ZnVuY3Rpb24gTHYodCxlKXtsZXQgcj1bXTtmb3IobGV0IG4saT0tMSxzPS0xLG89dC5jaGlsZHJlbkxlbmd0aCgpOysraTxvOylpZihuPXQuY2hpbGRyZW4oaSkpclsrK3NdPVUuZGVjb2RlKG4sZSk7cmV0dXJuIHJ9ZnVuY3Rpb24gVlQodCxlKXtsZXQgcixuLGkscyxvLGE7aWYoIWV8fCEoYT10LmRpY3Rpb25hcnkoKSkpaT1Sdih0LEx2KHQsZSkpLG49bmV3IFUodC5uYW1lKCksaSx0Lm51bGxhYmxlKCksWmYodCkpO2Vsc2UgaWYoIWUuaGFzKHI9UHQoYS5pZCgpKSkpcz0ocz1hLmluZGV4VHlwZSgpKT9VdihzKTpuZXcgQnIsZS5zZXQocixpPVJ2KHQsTHYodCxlKSkpLG89bmV3IGZyKGkscyxyLGEuaXNPcmRlcmVkKCkpLG49bmV3IFUodC5uYW1lKCksbyx0Lm51bGxhYmxlKCksWmYodCkpO2Vsc2Ugcz0ocz1hLmluZGV4VHlwZSgpKT9VdihzKTpuZXcgQnIsbz1uZXcgZnIoZS5nZXQocikscyxyLGEuaXNPcmRlcmVkKCkpLG49bmV3IFUodC5uYW1lKCksbyx0Lm51bGxhYmxlKCksWmYodCkpO3JldHVybiBufHxudWxsfWZ1bmN0aW9uIFpmKHQpe2xldCBlPW5ldyBNYXA7aWYodCl7Zm9yKGxldCByLG4saT0tMSxzPU1hdGgudHJ1bmModC5jdXN0b21NZXRhZGF0YUxlbmd0aCgpKTsrK2k8czspaWYoKHI9dC5jdXN0b21NZXRhZGF0YShpKSkmJihuPXIua2V5KCkpIT1udWxsKWUuc2V0KG4sci52YWx1ZSgpKX1yZXR1cm4gZX1mdW5jdGlvbiB6VCh0KXtsZXQgZT1uZXcgTWFwO2ZvcihsZXQgcixuLGk9LTEscz1NYXRoLnRydW5jKHQuY3VzdG9tTWV0YWRhdGFMZW5ndGgoKSk7KytpPHM7KWlmKChyPXQuY3VzdG9tTWV0YWRhdGEoaSkpJiYobj1yLmtleSgpKSE9bnVsbCllLnNldChuLHIudmFsdWUoKSk7cmV0dXJuIGV9ZnVuY3Rpb24gVXYodCl7cmV0dXJuIG5ldyAkZSh0LmlzU2lnbmVkKCksdC5iaXRXaWR0aCgpKX1mdW5jdGlvbiBSdih0LGUpe2xldCByPXQudHlwZVR5cGUoKTtzd2l0Y2gocil7Y2FzZSBZdC5OT05FOnJldHVybiBuZXcgd2U7Y2FzZSBZdC5OdWxsOnJldHVybiBuZXcgd2U7Y2FzZSBZdC5CaW5hcnk6cmV0dXJuIG5ldyBBaTtjYXNlIFl0LkxhcmdlQmluYXJ5OnJldHVybiBuZXcgRGk7Y2FzZSBZdC5CaW5hcnlWaWV3OnJldHVybiBuZXcgX3Q7Y2FzZSBZdC5VdGY4OnJldHVybiBuZXcgSXI7Y2FzZSBZdC5MYXJnZVV0Zjg6cmV0dXJuIG5ldyB4aTtjYXNlIFl0LlV0ZjhWaWV3OnJldHVybiBuZXcgZ247Y2FzZSBZdC5Cb29sOnJldHVybiBuZXcgVWU7Y2FzZSBZdC5MaXN0OnJldHVybiBuZXcgTHIoKGV8fFtdKVswXSk7Y2FzZSBZdC5TdHJ1Y3RfOnJldHVybiBuZXcgRXQoZXx8W10pfXN3aXRjaChyKXtjYXNlIFl0LkludDp7bGV0IG49dC50eXBlKG5ldyBicik7cmV0dXJuIG5ldyAkZShuLmlzU2lnbmVkKCksbi5iaXRXaWR0aCgpKX1jYXNlIFl0LkZsb2F0aW5nUG9pbnQ6e2xldCBuPXQudHlwZShuZXcgSG4pO3JldHVybiBuZXcgR24obi5wcmVjaXNpb24oKSl9Y2FzZSBZdC5EZWNpbWFsOntsZXQgbj10LnR5cGUobmV3IHdyKTtyZXR1cm4gbmV3IFRpKG4uc2NhbGUoKSxuLnByZWNpc2lvbigpLG4uYml0V2lkdGgoKSl9Y2FzZSBZdC5EYXRlOntsZXQgbj10LnR5cGUobmV3IGpuKTtyZXR1cm4gbmV3IEVpKG4udW5pdCgpKX1jYXNlIFl0LlRpbWU6e2xldCBuPXQudHlwZShuZXcgSnIpO3JldHVybiBuZXcgT2kobi51bml0KCksbi5iaXRXaWR0aCgpKX1jYXNlIFl0LlRpbWVzdGFtcDp7bGV0IG49dC50eXBlKG5ldyBYcik7cmV0dXJuIG5ldyBKbihuLnVuaXQoKSxuLnRpbWV6b25lKCkpfWNhc2UgWXQuSW50ZXJ2YWw6e2xldCBuPXQudHlwZShuZXcgWW4pO3JldHVybiBuZXcgTmkobi51bml0KCkpfWNhc2UgWXQuRHVyYXRpb246e2xldCBuPXQudHlwZShuZXcgJG4pO3JldHVybiBuZXcgRmkobi51bml0KCkpfWNhc2UgWXQuVW5pb246e2xldCBuPXQudHlwZShuZXcgdnIpO3JldHVybiBuZXcgYm4obi5tb2RlKCksbi50eXBlSWRzQXJyYXkoKXx8W10sZXx8W10pfWNhc2UgWXQuRml4ZWRTaXplQmluYXJ5OntsZXQgbj10LnR5cGUobmV3IHFuKTtyZXR1cm4gbmV3IE1pKG4uYnl0ZVdpZHRoKCkpfWNhc2UgWXQuRml4ZWRTaXplTGlzdDp7bGV0IG49dC50eXBlKG5ldyBXbik7cmV0dXJuIG5ldyB3bihuLmxpc3RTaXplKCksKGV8fFtdKVswXSl9Y2FzZSBZdC5NYXA6e2xldCBuPXQudHlwZShuZXcgS24pO3JldHVybiBuZXcgdm4oKGV8fFtdKVswXSxuLmtleXNTb3J0ZWQoKSl9fXRocm93IEVycm9yKGBVbnJlY29nbml6ZWQgdHlwZTogIiR7WXRbcl19IiAoJHtyfSlgKX1mdW5jdGlvbiBDdih0KXtyZXR1cm4gdD9uZXcgU2ModC5jb2RlYygpLHQubWV0aG9kKCkpOm51bGx9ZnVuY3Rpb24galQodCxlKXtsZXQgcj1lLmZpZWxkcy5tYXAoKHMpPT5VLmVuY29kZSh0LHMpKTtBZS5zdGFydEZpZWxkc1ZlY3Rvcih0LHIubGVuZ3RoKTtsZXQgbj1BZS5jcmVhdGVGaWVsZHNWZWN0b3IodCxyKSxpPSEoZS5tZXRhZGF0YSYmZS5tZXRhZGF0YS5zaXplPjApPy0xOkFlLmNyZWF0ZUN1c3RvbU1ldGFkYXRhVmVjdG9yKHQsWy4uLmUubWV0YWRhdGFdLm1hcCgoW3Msb10pPT57bGV0IGE9dC5jcmVhdGVTdHJpbmcoYCR7c31gKSxsPXQuY3JlYXRlU3RyaW5nKGAke299YCk7cmV0dXJuIG5lLnN0YXJ0S2V5VmFsdWUodCksbmUuYWRkS2V5KHQsYSksbmUuYWRkVmFsdWUodCxsKSxuZS5lbmRLZXlWYWx1ZSh0KX0pKTtpZihBZS5zdGFydFNjaGVtYSh0KSxBZS5hZGRGaWVsZHModCxuKSxBZS5hZGRFbmRpYW5uZXNzKHQsS1Q/bm8uTGl0dGxlOm5vLkJpZyksaSE9PS0xKUFlLmFkZEN1c3RvbU1ldGFkYXRhKHQsaSk7cmV0dXJuIEFlLmVuZFNjaGVtYSh0KX1mdW5jdGlvbiAkVCh0LGUpe2xldCByPS0xLG49LTEsaT0tMSx7dHlwZTpzLHR5cGVJZDpvfT1lO2lmKCFCLmlzRGljdGlvbmFyeShzKSluPUpmLnZpc2l0KHMsdCk7ZWxzZSBvPXMuZGljdGlvbmFyeS50eXBlSWQsaT1KZi52aXNpdChzLHQpLG49SmYudmlzaXQocy5kaWN0aW9uYXJ5LHQpO2xldCBhPShzLmNoaWxkcmVufHxbXSkubWFwKChmKT0+VS5lbmNvZGUodCxmKSksbD1RZS5jcmVhdGVDaGlsZHJlblZlY3Rvcih0LGEpLHU9IShlLm1ldGFkYXRhJiZlLm1ldGFkYXRhLnNpemU+MCk/LTE6UWUuY3JlYXRlQ3VzdG9tTWV0YWRhdGFWZWN0b3IodCxbLi4uZS5tZXRhZGF0YV0ubWFwKChbZixwXSk9PntsZXQgZz10LmNyZWF0ZVN0cmluZyhgJHtmfWApLHY9dC5jcmVhdGVTdHJpbmcoYCR7cH1gKTtyZXR1cm4gbmUuc3RhcnRLZXlWYWx1ZSh0KSxuZS5hZGRLZXkodCxnKSxuZS5hZGRWYWx1ZSh0LHYpLG5lLmVuZEtleVZhbHVlKHQpfSkpO2lmKGUubmFtZSlyPXQuY3JlYXRlU3RyaW5nKGUubmFtZSk7aWYoUWUuc3RhcnRGaWVsZCh0KSxRZS5hZGRUeXBlKHQsbiksUWUuYWRkVHlwZVR5cGUodCxvKSxRZS5hZGRDaGlsZHJlbih0LGwpLFFlLmFkZE51bGxhYmxlKHQsISFlLm51bGxhYmxlKSxyIT09LTEpUWUuYWRkTmFtZSh0LHIpO2lmKGkhPT0tMSlRZS5hZGREaWN0aW9uYXJ5KHQsaSk7aWYodSE9PS0xKVFlLmFkZEN1c3RvbU1ldGFkYXRhKHQsdSk7cmV0dXJuIFFlLmVuZEZpZWxkKHQpfWZ1bmN0aW9uIHFUKHQsZSl7bGV0IHI9ZS5ub2Rlc3x8W10sbj1lLmJ1ZmZlcnN8fFtdLGk9ZS52YXJpYWRpY0J1ZmZlckNvdW50c3x8W107dXIuc3RhcnROb2Rlc1ZlY3Rvcih0LHIubGVuZ3RoKTtmb3IobGV0IHUgb2Ygci5zbGljZSgpLnJldmVyc2UoKSlDaS5lbmNvZGUodCx1KTtsZXQgcz10LmVuZFZlY3RvcigpO3VyLnN0YXJ0QnVmZmVyc1ZlY3Rvcih0LG4ubGVuZ3RoKTtmb3IobGV0IHUgb2Ygbi5zbGljZSgpLnJldmVyc2UoKSl4ZS5lbmNvZGUodCx1KTtsZXQgbz10LmVuZFZlY3RvcigpLGE9bnVsbDtpZihlLmNvbXByZXNzaW9uIT09bnVsbClhPVB2KHQsZS5jb21wcmVzc2lvbik7bGV0IGw9LTE7aWYoaS5sZW5ndGg+MClsPXVyLmNyZWF0ZVZhcmlhZGljQnVmZmVyQ291bnRzVmVjdG9yKHQsaS5tYXAoQmlnSW50KSk7aWYodXIuc3RhcnRSZWNvcmRCYXRjaCh0KSx1ci5hZGRMZW5ndGgodCxCaWdJbnQoZS5sZW5ndGgpKSx1ci5hZGROb2Rlcyh0LHMpLHVyLmFkZEJ1ZmZlcnModCxvKSxlLmNvbXByZXNzaW9uIT09bnVsbCYmYSl1ci5hZGRDb21wcmVzc2lvbih0LGEpO2lmKGwhPT0tMSl1ci5hZGRWYXJpYWRpY0J1ZmZlckNvdW50cyh0LGwpO3JldHVybiB1ci5lbmRSZWNvcmRCYXRjaCh0KX1mdW5jdGlvbiBQdih0LGUpe3JldHVybiBHci5zdGFydEJvZHlDb21wcmVzc2lvbih0KSxHci5hZGRDb2RlYyh0LGUudHlwZSksR3IuYWRkTWV0aG9kKHQsZS5tZXRob2QpLEdyLmVuZEJvZHlDb21wcmVzc2lvbih0KX1mdW5jdGlvbiBXVCh0LGUpe2xldCByPVdlLmVuY29kZSh0LGUuZGF0YSk7cmV0dXJuIHNzLnN0YXJ0RGljdGlvbmFyeUJhdGNoKHQpLHNzLmFkZElkKHQsQmlnSW50KGUuaWQpKSxzcy5hZGRJc0RlbHRhKHQsZS5pc0RlbHRhKSxzcy5hZGREYXRhKHQsciksc3MuZW5kRGljdGlvbmFyeUJhdGNoKHQpfWZ1bmN0aW9uIEhUKHQsZSl7cmV0dXJuIE5sLmNyZWF0ZUZpZWxkTm9kZSh0LEJpZ0ludChlLmxlbmd0aCksQmlnSW50KGUubnVsbENvdW50KSl9ZnVuY3Rpb24gWVQodCxlKXtyZXR1cm4gT2wuY3JlYXRlQnVmZmVyKHQsQmlnSW50KGUub2Zmc2V0KSxCaWdJbnQoZS5sZW5ndGgpKX12YXIgeFQsVFQsS1Q7dmFyIHlhPW0oKCk9PntOdCgpO3ZtKCk7eWYoKTtzbSgpO0ZiKCk7d20oKTtibSgpO2FjKCk7b20oKTtobSgpO2xtKCk7Y20oKTt5bSgpO19tKCk7cG0oKTt1bSgpO2dtKCk7Zm0oKTtkbSgpO21tKCk7dnYoKTtpbSgpO25tKCk7VXIoKTtqZSgpO0xlKCk7QnYoKTtNdigpO2llKCk7eFQ9YWEsVFQ9bHI7VS5lbmNvZGU9JFQ7VS5kZWNvZGU9VlQ7VS5mcm9tSlNPTj1GdjtsdC5lbmNvZGU9alQ7bHQuZGVjb2RlPU5UO2x0LmZyb21KU09OPXh2O1dlLmVuY29kZT1xVDtXZS5kZWNvZGU9RlQ7V2UuZnJvbUpTT049SG07UnIuZW5jb2RlPVdUO1JyLmRlY29kZT1NVDtSci5mcm9tSlNPTj1UdjtDaS5lbmNvZGU9SFQ7Q2kuZGVjb2RlPVVUO3hlLmVuY29kZT1ZVDt4ZS5kZWNvZGU9TFQ7U2MuZW5jb2RlPVB2O1NjLmRlY29kZT1DdjtLVD0oKCk9PntsZXQgdD1uZXcgQXJyYXlCdWZmZXIoMik7cmV0dXJuIG5ldyBEYXRhVmlldyh0KS5zZXRJbnQxNigwLDI1NiwhMCksbmV3IEludDE2QXJyYXkodClbMF09PT0yNTZ9KSgpfSk7Y2xhc3MgUWZ7Y29uc3RydWN0b3IodCl7dGhpcy5fanNvbj10fWdldCBzY2hlbWEoKXtyZXR1cm4gdGhpcy5fanNvbi5zY2hlbWF9Z2V0IGJhdGNoZXMoKXtyZXR1cm4gdGhpcy5fanNvbi5iYXRjaGVzfHxbXX1nZXQgZGljdGlvbmFyaWVzKCl7cmV0dXJuIHRoaXMuX2pzb24uZGljdGlvbmFyaWVzfHxbXX19Y2xhc3MgQWN7dGVlKCl7cmV0dXJuIHRoaXMuX2dldERPTVN0cmVhbSgpLnRlZSgpfXBpcGUodCxlKXtyZXR1cm4gdGhpcy5fZ2V0Tm9kZVN0cmVhbSgpLnBpcGUodCxlKX1waXBlVG8odCxlKXtyZXR1cm4gdGhpcy5fZ2V0RE9NU3RyZWFtKCkucGlwZVRvKHQsZSl9cGlwZVRocm91Z2godCxlKXtyZXR1cm4gdGhpcy5fZ2V0RE9NU3RyZWFtKCkucGlwZVRocm91Z2godCxlKX1fZ2V0RE9NU3RyZWFtKCl7cmV0dXJuIHRoaXMuX0RPTVN0cmVhbXx8KHRoaXMuX0RPTVN0cmVhbT10aGlzLnRvRE9NU3RyZWFtKCkpfV9nZXROb2RlU3RyZWFtKCl7cmV0dXJuIHRoaXMuX25vZGVTdHJlYW18fCh0aGlzLl9ub2RlU3RyZWFtPXRoaXMudG9Ob2RlU3RyZWFtKCkpfX12YXIgZmUsWW07dmFyIFdsPW0oKCk9PntwbigpO0FsKCk7ZmU9T2JqZWN0LmZyZWV6ZSh7ZG9uZTohMCx2YWx1ZTp2b2lkIDB9KTtZbT1jbGFzcyBZbSBleHRlbmRzIEFje2NvbnN0cnVjdG9yKCl7c3VwZXIoKTt0aGlzLl92YWx1ZXM9W10sdGhpcy5yZXNvbHZlcnM9W10sdGhpcy5fY2xvc2VkUHJvbWlzZT1uZXcgUHJvbWlzZSgodCk9PnRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlPXQpfWdldCBjbG9zZWQoKXtyZXR1cm4gdGhpcy5fY2xvc2VkUHJvbWlzZX1jYW5jZWwodCl7cmV0dXJuIEUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3lpZWxkIHRoaXMucmV0dXJuKHQpfSl9d3JpdGUodCl7aWYodGhpcy5fZW5zdXJlT3BlbigpKXRoaXMucmVzb2x2ZXJzLmxlbmd0aDw9MD90aGlzLl92YWx1ZXMucHVzaCh0KTp0aGlzLnJlc29sdmVycy5zaGlmdCgpLnJlc29sdmUoe2RvbmU6ITEsdmFsdWU6dH0pfWFib3J0KHQpe2lmKHRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlKXRoaXMucmVzb2x2ZXJzLmxlbmd0aDw9MD90aGlzLl9lcnJvcj17ZXJyb3I6dH06dGhpcy5yZXNvbHZlcnMuc2hpZnQoKS5yZWplY3Qoe2RvbmU6ITAsdmFsdWU6dH0pfWNsb3NlKCl7aWYodGhpcy5fY2xvc2VkUHJvbWlzZVJlc29sdmUpe2xldHtyZXNvbHZlcnM6dH09dGhpczt3aGlsZSh0Lmxlbmd0aD4wKXQuc2hpZnQoKS5yZXNvbHZlKGZlKTt0aGlzLl9jbG9zZWRQcm9taXNlUmVzb2x2ZSgpLHRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlPXZvaWQgMH19W1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpe3JldHVybiB0aGlzfXRvRE9NU3RyZWFtKHQpe3JldHVybiBjci50b0RPTVN0cmVhbSh0aGlzLl9jbG9zZWRQcm9taXNlUmVzb2x2ZXx8dGhpcy5fZXJyb3I/dGhpczp0aGlzLl92YWx1ZXMsdCl9dG9Ob2RlU3RyZWFtKHQpe3JldHVybiBjci50b05vZGVTdHJlYW0odGhpcy5fY2xvc2VkUHJvbWlzZVJlc29sdmV8fHRoaXMuX2Vycm9yP3RoaXM6dGhpcy5fdmFsdWVzLHQpfXRocm93KHQpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtyZXR1cm4geWllbGQgdGhpcy5hYm9ydCh0KSxmZX0pfXJldHVybih0KXtyZXR1cm4gRSh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7cmV0dXJuIHlpZWxkIHRoaXMuY2xvc2UoKSxmZX0pfXJlYWQodCl7cmV0dXJuIEUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3JldHVybih5aWVsZCB0aGlzLm5leHQodCwicmVhZCIpKS52YWx1ZX0pfXBlZWsodCl7cmV0dXJuIEUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3JldHVybih5aWVsZCB0aGlzLm5leHQodCwicGVlayIpKS52YWx1ZX0pfW5leHQoLi4udCl7aWYodGhpcy5fdmFsdWVzLmxlbmd0aD4wKXJldHVybiBQcm9taXNlLnJlc29sdmUoe2RvbmU6ITEsdmFsdWU6dGhpcy5fdmFsdWVzLnNoaWZ0KCl9KTtlbHNlIGlmKHRoaXMuX2Vycm9yKXJldHVybiBQcm9taXNlLnJlamVjdCh7ZG9uZTohMCx2YWx1ZTp0aGlzLl9lcnJvci5lcnJvcn0pO2Vsc2UgaWYoIXRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlKXJldHVybiBQcm9taXNlLnJlc29sdmUoZmUpO2Vsc2UgcmV0dXJuIG5ldyBQcm9taXNlKChlLHIpPT57dGhpcy5yZXNvbHZlcnMucHVzaCh7cmVzb2x2ZTplLHJlamVjdDpyfSl9KX1fZW5zdXJlT3Blbigpe2lmKHRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlKXJldHVybiEwO3Rocm93IEVycm9yKCJBc3luY1F1ZXVlIGlzIGNsb3NlZCIpfX19KTtjbGFzcyBWdntjb25zdHJ1Y3Rvcih0KXt0aGlzLnNvdXJjZT10fWNhbmNlbCh0KXt0aGlzLnJldHVybih0KX1wZWVrKHQpe3JldHVybiB0aGlzLm5leHQodCwicGVlayIpLnZhbHVlfXJlYWQodCl7cmV0dXJuIHRoaXMubmV4dCh0LCJyZWFkIikudmFsdWV9bmV4dCh0LGU9InJlYWQiKXtyZXR1cm4gdGhpcy5zb3VyY2UubmV4dCh7Y21kOmUsc2l6ZTp0fSl9dGhyb3codCl7cmV0dXJuIE9iamVjdC5jcmVhdGUodGhpcy5zb3VyY2UudGhyb3cmJnRoaXMuc291cmNlLnRocm93KHQpfHxmZSl9cmV0dXJuKHQpe3JldHVybiBPYmplY3QuY3JlYXRlKHRoaXMuc291cmNlLnJldHVybiYmdGhpcy5zb3VyY2UucmV0dXJuKHQpfHxmZSl9fWNsYXNzIHhve2NvbnN0cnVjdG9yKHQpe3RoaXMuc291cmNlPXQsdGhpcy5fY2xvc2VkUHJvbWlzZT1uZXcgUHJvbWlzZSgoZSk9PnRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlPWUpfWNhbmNlbCh0KXtyZXR1cm4gRSh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7eWllbGQgdGhpcy5yZXR1cm4odCl9KX1nZXQgY2xvc2VkKCl7cmV0dXJuIHRoaXMuX2Nsb3NlZFByb21pc2V9cmVhZCh0KXtyZXR1cm4gRSh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7cmV0dXJuKHlpZWxkIHRoaXMubmV4dCh0LCJyZWFkIikpLnZhbHVlfSl9cGVlayh0KXtyZXR1cm4gRSh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7cmV0dXJuKHlpZWxkIHRoaXMubmV4dCh0LCJwZWVrIikpLnZhbHVlfSl9bmV4dCh0KXtyZXR1cm4gRSh0aGlzLGFyZ3VtZW50cyx2b2lkIDAsZnVuY3Rpb24qKGUscj0icmVhZCIpe3JldHVybiB5aWVsZCB0aGlzLnNvdXJjZS5uZXh0KHtjbWQ6cixzaXplOmV9KX0pfXRocm93KHQpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXQgZT10aGlzLnNvdXJjZS50aHJvdyYmKHlpZWxkIHRoaXMuc291cmNlLnRocm93KHQpKXx8ZmU7cmV0dXJuIHRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlJiZ0aGlzLl9jbG9zZWRQcm9taXNlUmVzb2x2ZSgpLHRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlPXZvaWQgMCxPYmplY3QuY3JlYXRlKGUpfSl9cmV0dXJuKHQpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXQgZT10aGlzLnNvdXJjZS5yZXR1cm4mJih5aWVsZCB0aGlzLnNvdXJjZS5yZXR1cm4odCkpfHxmZTtyZXR1cm4gdGhpcy5fY2xvc2VkUHJvbWlzZVJlc29sdmUmJnRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlKCksdGhpcy5fY2xvc2VkUHJvbWlzZVJlc29sdmU9dm9pZCAwLE9iamVjdC5jcmVhdGUoZSl9KX19dmFyIEFzLERzLFpuO3ZhciBfYT1tKCgpPT57cG4oKTtBbCgpO3ZzKCk7V2woKTtqZSgpO0FzPWNsYXNzIEFzIGV4dGVuZHMgWW17d3JpdGUodCl7aWYoKHQ9Qyh0KSkuYnl0ZUxlbmd0aD4wKXJldHVybiBzdXBlci53cml0ZSh0KX10b1N0cmluZyh0PSExKXtyZXR1cm4gdD9zYyh0aGlzLnRvVWludDhBcnJheSghMCkpOnRoaXMudG9VaW50OEFycmF5KCExKS50aGVuKHNjKX10b1VpbnQ4QXJyYXkodD0hMSl7cmV0dXJuIHQ/eW4odGhpcy5fdmFsdWVzKVswXTooKCk9PkUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3ZhciBlLHIsbixpO2xldCBzPVtdLG89MDt0cnl7Zm9yKHZhciBhPSEwLGw9Z2kodGhpcyksdTt1PXlpZWxkIGwubmV4dCgpLGU9dS5kb25lLCFlO2E9ITApe2k9dS52YWx1ZSxhPSExO2xldCBmPWk7cy5wdXNoKGYpLG8rPWYuYnl0ZUxlbmd0aH19Y2F0Y2goZil7cj17ZXJyb3I6Zn19ZmluYWxseXt0cnl7aWYoIWEmJiFlJiYobj1sLnJldHVybikpeWllbGQgbi5jYWxsKGwpfWZpbmFsbHl7aWYocil0aHJvdyByLmVycm9yfX1yZXR1cm4geW4ocyxvKVswXX0pKSgpfX07RHM9Y2xhc3MgRHN7Y29uc3RydWN0b3IodCl7aWYodCl0aGlzLnNvdXJjZT1uZXcgVnYoY3IuZnJvbUl0ZXJhYmxlKHQpKX1bU3ltYm9sLml0ZXJhdG9yXSgpe3JldHVybiB0aGlzfW5leHQodCl7cmV0dXJuIHRoaXMuc291cmNlLm5leHQodCl9dGhyb3codCl7cmV0dXJuIHRoaXMuc291cmNlLnRocm93KHQpfXJldHVybih0KXtyZXR1cm4gdGhpcy5zb3VyY2UucmV0dXJuKHQpfXBlZWsodCl7cmV0dXJuIHRoaXMuc291cmNlLnBlZWsodCl9cmVhZCh0KXtyZXR1cm4gdGhpcy5zb3VyY2UucmVhZCh0KX19O1puPWNsYXNzIFpue2NvbnN0cnVjdG9yKHQpe2lmKHQgaW5zdGFuY2VvZiBabil0aGlzLnNvdXJjZT10LnNvdXJjZTtlbHNlIGlmKHQgaW5zdGFuY2VvZiBBcyl0aGlzLnNvdXJjZT1uZXcgeG8oY3IuZnJvbUFzeW5jSXRlcmFibGUodCkpO2Vsc2UgaWYobGYodCkpdGhpcy5zb3VyY2U9bmV3IHhvKGNyLmZyb21Ob2RlU3RyZWFtKHQpKTtlbHNlIGlmKEJsKHQpKXRoaXMuc291cmNlPW5ldyB4byhjci5mcm9tRE9NU3RyZWFtKHQpKTtlbHNlIGlmKGFmKHQpKXRoaXMuc291cmNlPW5ldyB4byhjci5mcm9tRE9NU3RyZWFtKHQuYm9keSkpO2Vsc2UgaWYod2kodCkpdGhpcy5zb3VyY2U9bmV3IHhvKGNyLmZyb21JdGVyYWJsZSh0KSk7ZWxzZSBpZihiaSh0KSl0aGlzLnNvdXJjZT1uZXcgeG8oY3IuZnJvbUFzeW5jSXRlcmFibGUodCkpO2Vsc2UgaWYoVm4odCkpdGhpcy5zb3VyY2U9bmV3IHhvKGNyLmZyb21Bc3luY0l0ZXJhYmxlKHQpKX1bU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCl7cmV0dXJuIHRoaXN9bmV4dCh0KXtyZXR1cm4gdGhpcy5zb3VyY2UubmV4dCh0KX10aHJvdyh0KXtyZXR1cm4gdGhpcy5zb3VyY2UudGhyb3codCl9cmV0dXJuKHQpe3JldHVybiB0aGlzLnNvdXJjZS5yZXR1cm4odCl9Z2V0IGNsb3NlZCgpe3JldHVybiB0aGlzLnNvdXJjZS5jbG9zZWR9Y2FuY2VsKHQpe3JldHVybiB0aGlzLnNvdXJjZS5jYW5jZWwodCl9cGVlayh0KXtyZXR1cm4gdGhpcy5zb3VyY2UucGVlayh0KX1yZWFkKHQpe3JldHVybiB0aGlzLnNvdXJjZS5yZWFkKHQpfX19KTt2YXIgdGQsZ2E7dmFyIEttPW0oKCk9PntwbigpO19hKCk7amUoKTt0ZD1jbGFzcyB0ZCBleHRlbmRzIERze2NvbnN0cnVjdG9yKHQsZSl7c3VwZXIoKTt0aGlzLnBvc2l0aW9uPTAsdGhpcy5idWZmZXI9Qyh0KSx0aGlzLnNpemU9ZT09PXZvaWQgMD90aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoOmV9cmVhZEludDMyKHQpe2xldHtidWZmZXI6ZSxieXRlT2Zmc2V0OnJ9PXRoaXMucmVhZEF0KHQsNCk7cmV0dXJuIG5ldyBEYXRhVmlldyhlLHIpLmdldEludDMyKDAsITApfXNlZWsodCl7cmV0dXJuIHRoaXMucG9zaXRpb249TWF0aC5taW4odCx0aGlzLnNpemUpLHQ8dGhpcy5zaXplfXJlYWQodCl7bGV0e2J1ZmZlcjplLHNpemU6cixwb3NpdGlvbjpufT10aGlzO2lmKGUmJm48cil7aWYodHlwZW9mIHQhPT0ibnVtYmVyIil0PU51bWJlci5QT1NJVElWRV9JTkZJTklUWTtyZXR1cm4gdGhpcy5wb3NpdGlvbj1NYXRoLm1pbihyLG4rTWF0aC5taW4oci1uLHQpKSxlLnN1YmFycmF5KG4sdGhpcy5wb3NpdGlvbil9cmV0dXJuIG51bGx9cmVhZEF0KHQsZSl7bGV0IHI9dGhpcy5idWZmZXIsbj1NYXRoLm1pbih0aGlzLnNpemUsdCtlKTtyZXR1cm4gcj9yLnN1YmFycmF5KHQsbik6bmV3IFVpbnQ4QXJyYXkoZSl9Y2xvc2UoKXt0aGlzLmJ1ZmZlciYmKHRoaXMuYnVmZmVyPW51bGwpfXRocm93KHQpe3JldHVybiB0aGlzLmNsb3NlKCkse2RvbmU6ITAsdmFsdWU6dH19cmV0dXJuKHQpe3JldHVybiB0aGlzLmNsb3NlKCkse2RvbmU6ITAsdmFsdWU6dH19fTtnYT1jbGFzcyBnYSBleHRlbmRzIFpue2NvbnN0cnVjdG9yKHQsZSl7c3VwZXIoKTtpZih0aGlzLnBvc2l0aW9uPTAsdGhpcy5faGFuZGxlPXQsdHlwZW9mIGU9PT0ibnVtYmVyIil0aGlzLnNpemU9ZTtlbHNlIHRoaXMuX3BlbmRpbmc9KCgpPT5FKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXt0aGlzLnNpemU9KHlpZWxkIHQuc3RhdCgpKS5zaXplLGRlbGV0ZSB0aGlzLl9wZW5kaW5nfSkpKCl9cmVhZEludDMyKHQpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXR7YnVmZmVyOmUsYnl0ZU9mZnNldDpyfT15aWVsZCB0aGlzLnJlYWRBdCh0LDQpO3JldHVybiBuZXcgRGF0YVZpZXcoZSxyKS5nZXRJbnQzMigwLCEwKX0pfXNlZWsodCl7cmV0dXJuIEUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3JldHVybiB0aGlzLl9wZW5kaW5nJiYoeWllbGQgdGhpcy5fcGVuZGluZyksdGhpcy5wb3NpdGlvbj1NYXRoLm1pbih0LHRoaXMuc2l6ZSksdDx0aGlzLnNpemV9KX1yZWFkKHQpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXt0aGlzLl9wZW5kaW5nJiYoeWllbGQgdGhpcy5fcGVuZGluZyk7bGV0e19oYW5kbGU6ZSxzaXplOnIscG9zaXRpb246bn09dGhpcztpZihlJiZuPHIpe2lmKHR5cGVvZiB0IT09Im51bWJlciIpdD1OdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7bGV0IGk9bixzPTAsbz0wLGE9TWF0aC5taW4ocixpK01hdGgubWluKHItaSx0KSksbD1uZXcgVWludDhBcnJheShNYXRoLm1heCgwLCh0aGlzLnBvc2l0aW9uPWEpLWkpKTt3aGlsZSgoaSs9byk8YSYmKHMrPW8pPGwuYnl0ZUxlbmd0aCkoe2J5dGVzUmVhZDpvfT15aWVsZCBlLnJlYWQobCxzLGwuYnl0ZUxlbmd0aC1zLGkpKTtyZXR1cm4gbH1yZXR1cm4gbnVsbH0pfXJlYWRBdCh0LGUpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXt0aGlzLl9wZW5kaW5nJiYoeWllbGQgdGhpcy5fcGVuZGluZyk7bGV0e19oYW5kbGU6cixzaXplOm59PXRoaXM7aWYociYmdCtlPG4pe2xldCBpPU1hdGgubWluKG4sdCtlKSxzPW5ldyBVaW50OEFycmF5KGktdCk7cmV0dXJuKHlpZWxkIHIucmVhZChzLDAsZSx0KSkuYnVmZmVyfXJldHVybiBuZXcgVWludDhBcnJheShlKX0pfWNsb3NlKCl7cmV0dXJuIEUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe2xldCB0PXRoaXMuX2hhbmRsZTt0aGlzLl9oYW5kbGU9bnVsbCx0JiYoeWllbGQgdC5jbG9zZSgpKX0pfXRocm93KHQpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtyZXR1cm4geWllbGQgdGhpcy5jbG9zZSgpLHtkb25lOiEwLHZhbHVlOnR9fSl9cmV0dXJuKHQpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtyZXR1cm4geWllbGQgdGhpcy5jbG9zZSgpLHtkb25lOiEwLHZhbHVlOnR9fSl9fX0pO3ZhciBKbT17fTtaZShKbSx7QmFzZUludDY0OigpPT5lZCxJbnQxMjg6KCk9PlFuLEludDY0OigpPT5TcixVaW50NjQ6KCk9Pkt0fSk7ZnVuY3Rpb24gRGModCl7aWYodDwwKXQ9NDI5NDk2NzI5NSt0KzE7cmV0dXJuYDB4JHt0LnRvU3RyaW5nKDE2KX1gfWNsYXNzIGVke2NvbnN0cnVjdG9yKHQpe3RoaXMuYnVmZmVyPXR9aGlnaCgpe3JldHVybiB0aGlzLmJ1ZmZlclsxXX1sb3coKXtyZXR1cm4gdGhpcy5idWZmZXJbMF19X3RpbWVzKHQpe2xldCBlPW5ldyBVaW50MzJBcnJheShbdGhpcy5idWZmZXJbMV0+Pj4xNix0aGlzLmJ1ZmZlclsxXSY2NTUzNSx0aGlzLmJ1ZmZlclswXT4+PjE2LHRoaXMuYnVmZmVyWzBdJjY1NTM1XSkscj1uZXcgVWludDMyQXJyYXkoW3QuYnVmZmVyWzFdPj4+MTYsdC5idWZmZXJbMV0mNjU1MzUsdC5idWZmZXJbMF0+Pj4xNix0LmJ1ZmZlclswXSY2NTUzNV0pLG49ZVszXSpyWzNdO3RoaXMuYnVmZmVyWzBdPW4mNjU1MzU7bGV0IGk9bj4+PjE2O3JldHVybiBuPWVbMl0qclszXSxpKz1uLG49ZVszXSpyWzJdPj4+MCxpKz1uLHRoaXMuYnVmZmVyWzBdKz1pPDwxNix0aGlzLmJ1ZmZlclsxXT1pPj4+MDxuPzY1NTM2OjAsdGhpcy5idWZmZXJbMV0rPWk+Pj4xNix0aGlzLmJ1ZmZlclsxXSs9ZVsxXSpyWzNdK2VbMl0qclsyXStlWzNdKnJbMV0sdGhpcy5idWZmZXJbMV0rPWVbMF0qclszXStlWzFdKnJbMl0rZVsyXSpyWzFdK2VbM10qclswXTw8MTYsdGhpc31fcGx1cyh0KXtsZXQgZT10aGlzLmJ1ZmZlclswXSt0LmJ1ZmZlclswXT4+PjA7aWYodGhpcy5idWZmZXJbMV0rPXQuYnVmZmVyWzFdLGU8dGhpcy5idWZmZXJbMF0+Pj4wKSsrdGhpcy5idWZmZXJbMV07dGhpcy5idWZmZXJbMF09ZX1sZXNzVGhhbih0KXtyZXR1cm4gdGhpcy5idWZmZXJbMV08dC5idWZmZXJbMV18fHRoaXMuYnVmZmVyWzFdPT09dC5idWZmZXJbMV0mJnRoaXMuYnVmZmVyWzBdPHQuYnVmZmVyWzBdfWVxdWFscyh0KXtyZXR1cm4gdGhpcy5idWZmZXJbMV09PT10LmJ1ZmZlclsxXSYmdGhpcy5idWZmZXJbMF09PXQuYnVmZmVyWzBdfWdyZWF0ZXJUaGFuKHQpe3JldHVybiB0Lmxlc3NUaGFuKHRoaXMpfWhleCgpe3JldHVybmAke0RjKHRoaXMuYnVmZmVyWzFdKX0gJHtEYyh0aGlzLmJ1ZmZlclswXSl9YH19Y2xhc3MgUW57Y29uc3RydWN0b3IodCl7dGhpcy5idWZmZXI9dH1oaWdoKCl7cmV0dXJuIG5ldyBTcihuZXcgVWludDMyQXJyYXkodGhpcy5idWZmZXIuYnVmZmVyLHRoaXMuYnVmZmVyLmJ5dGVPZmZzZXQrOCwyKSl9bG93KCl7cmV0dXJuIG5ldyBTcihuZXcgVWludDMyQXJyYXkodGhpcy5idWZmZXIuYnVmZmVyLHRoaXMuYnVmZmVyLmJ5dGVPZmZzZXQsMikpfW5lZ2F0ZSgpe2lmKHRoaXMuYnVmZmVyWzBdPX50aGlzLmJ1ZmZlclswXSsxLHRoaXMuYnVmZmVyWzFdPX50aGlzLmJ1ZmZlclsxXSx0aGlzLmJ1ZmZlclsyXT1+dGhpcy5idWZmZXJbMl0sdGhpcy5idWZmZXJbM109fnRoaXMuYnVmZmVyWzNdLHRoaXMuYnVmZmVyWzBdPT0wKSsrdGhpcy5idWZmZXJbMV07aWYodGhpcy5idWZmZXJbMV09PTApKyt0aGlzLmJ1ZmZlclsyXTtpZih0aGlzLmJ1ZmZlclsyXT09MCkrK3RoaXMuYnVmZmVyWzNdO3JldHVybiB0aGlzfXRpbWVzKHQpe2xldCBlPW5ldyBLdChuZXcgVWludDMyQXJyYXkoW3RoaXMuYnVmZmVyWzNdLDBdKSkscj1uZXcgS3QobmV3IFVpbnQzMkFycmF5KFt0aGlzLmJ1ZmZlclsyXSwwXSkpLG49bmV3IEt0KG5ldyBVaW50MzJBcnJheShbdGhpcy5idWZmZXJbMV0sMF0pKSxpPW5ldyBLdChuZXcgVWludDMyQXJyYXkoW3RoaXMuYnVmZmVyWzBdLDBdKSkscz1uZXcgS3QobmV3IFVpbnQzMkFycmF5KFt0LmJ1ZmZlclszXSwwXSkpLG89bmV3IEt0KG5ldyBVaW50MzJBcnJheShbdC5idWZmZXJbMl0sMF0pKSxhPW5ldyBLdChuZXcgVWludDMyQXJyYXkoW3QuYnVmZmVyWzFdLDBdKSksbD1uZXcgS3QobmV3IFVpbnQzMkFycmF5KFt0LmJ1ZmZlclswXSwwXSkpLHU9S3QubXVsdGlwbHkoaSxsKTt0aGlzLmJ1ZmZlclswXT11LmxvdygpO2xldCBmPW5ldyBLdChuZXcgVWludDMyQXJyYXkoW3UuaGlnaCgpLDBdKSk7cmV0dXJuIHU9S3QubXVsdGlwbHkobixsKSxmLnBsdXModSksdT1LdC5tdWx0aXBseShpLGEpLGYucGx1cyh1KSx0aGlzLmJ1ZmZlclsxXT1mLmxvdygpLHRoaXMuYnVmZmVyWzNdPWYubGVzc1RoYW4odSk/MTowLHRoaXMuYnVmZmVyWzJdPWYuaGlnaCgpLG5ldyBLdChuZXcgVWludDMyQXJyYXkodGhpcy5idWZmZXIuYnVmZmVyLHRoaXMuYnVmZmVyLmJ5dGVPZmZzZXQrOCwyKSkucGx1cyhLdC5tdWx0aXBseShyLGwpKS5wbHVzKEt0Lm11bHRpcGx5KG4sYSkpLnBsdXMoS3QubXVsdGlwbHkoaSxvKSksdGhpcy5idWZmZXJbM10rPUt0Lm11bHRpcGx5KGUsbCkucGx1cyhLdC5tdWx0aXBseShyLGEpKS5wbHVzKEt0Lm11bHRpcGx5KG4sbykpLnBsdXMoS3QubXVsdGlwbHkoaSxzKSkubG93KCksdGhpc31wbHVzKHQpe2xldCBlPW5ldyBVaW50MzJBcnJheSg0KTtpZihlWzNdPXRoaXMuYnVmZmVyWzNdK3QuYnVmZmVyWzNdPj4+MCxlWzJdPXRoaXMuYnVmZmVyWzJdK3QuYnVmZmVyWzJdPj4+MCxlWzFdPXRoaXMuYnVmZmVyWzFdK3QuYnVmZmVyWzFdPj4+MCxlWzBdPXRoaXMuYnVmZmVyWzBdK3QuYnVmZmVyWzBdPj4+MCxlWzBdPHRoaXMuYnVmZmVyWzBdPj4+MCkrK2VbMV07aWYoZVsxXTx0aGlzLmJ1ZmZlclsxXT4+PjApKytlWzJdO2lmKGVbMl08dGhpcy5idWZmZXJbMl0+Pj4wKSsrZVszXTtyZXR1cm4gdGhpcy5idWZmZXJbM109ZVszXSx0aGlzLmJ1ZmZlclsyXT1lWzJdLHRoaXMuYnVmZmVyWzFdPWVbMV0sdGhpcy5idWZmZXJbMF09ZVswXSx0aGlzfWhleCgpe3JldHVybmAke0RjKHRoaXMuYnVmZmVyWzNdKX0gJHtEYyh0aGlzLmJ1ZmZlclsyXSl9ICR7RGModGhpcy5idWZmZXJbMV0pfSAke0RjKHRoaXMuYnVmZmVyWzBdKX1gfXN0YXRpYyBtdWx0aXBseSh0LGUpe3JldHVybiBuZXcgUW4obmV3IFVpbnQzMkFycmF5KHQuYnVmZmVyKSkudGltZXMoZSl9c3RhdGljIGFkZCh0LGUpe3JldHVybiBuZXcgUW4obmV3IFVpbnQzMkFycmF5KHQuYnVmZmVyKSkucGx1cyhlKX1zdGF0aWMgZnJvbSh0LGU9bmV3IFVpbnQzMkFycmF5KDQpKXtyZXR1cm4gUW4uZnJvbVN0cmluZyh0eXBlb2YgdD09PSJzdHJpbmciP3Q6dC50b1N0cmluZygpLGUpfXN0YXRpYyBmcm9tTnVtYmVyKHQsZT1uZXcgVWludDMyQXJyYXkoNCkpe3JldHVybiBRbi5mcm9tU3RyaW5nKHQudG9TdHJpbmcoKSxlKX1zdGF0aWMgZnJvbVN0cmluZyh0LGU9bmV3IFVpbnQzMkFycmF5KDQpKXtsZXQgcj10LnN0YXJ0c1dpdGgoIi0iKSxuPXQubGVuZ3RoLGk9bmV3IFFuKGUpO2ZvcihsZXQgcz1yPzE6MDtzPG47KXtsZXQgbz14YzxuLXM/eGM6bi1zLGE9bmV3IFFuKG5ldyBVaW50MzJBcnJheShbTnVtYmVyLnBhcnNlSW50KHQuc2xpY2UocyxzK28pLDEwKSwwLDAsMF0pKSxsPW5ldyBRbihuZXcgVWludDMyQXJyYXkoW0dtW29dLDAsMCwwXSkpO2kudGltZXMobCksaS5wbHVzKGEpLHMrPW99cmV0dXJuIHI/aS5uZWdhdGUoKTppfXN0YXRpYyBjb252ZXJ0QXJyYXkodCl7bGV0IGU9bmV3IFVpbnQzMkFycmF5KHQubGVuZ3RoKjQpO2ZvcihsZXQgcj0tMSxuPXQubGVuZ3RoOysrcjxuOylRbi5mcm9tKHRbcl0sbmV3IFVpbnQzMkFycmF5KGUuYnVmZmVyLGUuYnl0ZU9mZnNldCsxNipyLDQpKTtyZXR1cm4gZX19dmFyIHhjPTgsR20sS3QsU3I7dmFyIFhtPW0oKCk9PntHbT1bMSwxMCwxMDAsMTAwMCwxZTQsMWU1LDFlNiwxZTcsMWU4XTtLdD1jbGFzcyBLdCBleHRlbmRzIGVke3RpbWVzKHQpe3JldHVybiB0aGlzLl90aW1lcyh0KSx0aGlzfXBsdXModCl7cmV0dXJuIHRoaXMuX3BsdXModCksdGhpc31zdGF0aWMgZnJvbSh0LGU9bmV3IFVpbnQzMkFycmF5KDIpKXtyZXR1cm4gS3QuZnJvbVN0cmluZyh0eXBlb2YgdD09PSJzdHJpbmciP3Q6dC50b1N0cmluZygpLGUpfXN0YXRpYyBmcm9tTnVtYmVyKHQsZT1uZXcgVWludDMyQXJyYXkoMikpe3JldHVybiBLdC5mcm9tU3RyaW5nKHQudG9TdHJpbmcoKSxlKX1zdGF0aWMgZnJvbVN0cmluZyh0LGU9bmV3IFVpbnQzMkFycmF5KDIpKXtsZXQgcj10Lmxlbmd0aCxuPW5ldyBLdChlKTtmb3IobGV0IGk9MDtpPHI7KXtsZXQgcz14YzxyLWk/eGM6ci1pLG89bmV3IEt0KG5ldyBVaW50MzJBcnJheShbTnVtYmVyLnBhcnNlSW50KHQuc2xpY2UoaSxpK3MpLDEwKSwwXSkpLGE9bmV3IEt0KG5ldyBVaW50MzJBcnJheShbR21bc10sMF0pKTtuLnRpbWVzKGEpLG4ucGx1cyhvKSxpKz1zfXJldHVybiBufXN0YXRpYyBjb252ZXJ0QXJyYXkodCl7bGV0IGU9bmV3IFVpbnQzMkFycmF5KHQubGVuZ3RoKjIpO2ZvcihsZXQgcj0tMSxuPXQubGVuZ3RoOysrcjxuOylLdC5mcm9tKHRbcl0sbmV3IFVpbnQzMkFycmF5KGUuYnVmZmVyLGUuYnl0ZU9mZnNldCsyKnIqNCwyKSk7cmV0dXJuIGV9c3RhdGljIG11bHRpcGx5KHQsZSl7cmV0dXJuIG5ldyBLdChuZXcgVWludDMyQXJyYXkodC5idWZmZXIpKS50aW1lcyhlKX1zdGF0aWMgYWRkKHQsZSl7cmV0dXJuIG5ldyBLdChuZXcgVWludDMyQXJyYXkodC5idWZmZXIpKS5wbHVzKGUpfX07U3I9Y2xhc3MgU3IgZXh0ZW5kcyBlZHtuZWdhdGUoKXtpZih0aGlzLmJ1ZmZlclswXT1+dGhpcy5idWZmZXJbMF0rMSx0aGlzLmJ1ZmZlclsxXT1+dGhpcy5idWZmZXJbMV0sdGhpcy5idWZmZXJbMF09PTApKyt0aGlzLmJ1ZmZlclsxXTtyZXR1cm4gdGhpc310aW1lcyh0KXtyZXR1cm4gdGhpcy5fdGltZXModCksdGhpc31wbHVzKHQpe3JldHVybiB0aGlzLl9wbHVzKHQpLHRoaXN9bGVzc1RoYW4odCl7bGV0IGU9dGhpcy5idWZmZXJbMV08PDAscj10LmJ1ZmZlclsxXTw8MDtyZXR1cm4gZTxyfHxlPT09ciYmdGhpcy5idWZmZXJbMF08dC5idWZmZXJbMF19c3RhdGljIGZyb20odCxlPW5ldyBVaW50MzJBcnJheSgyKSl7cmV0dXJuIFNyLmZyb21TdHJpbmcodHlwZW9mIHQ9PT0ic3RyaW5nIj90OnQudG9TdHJpbmcoKSxlKX1zdGF0aWMgZnJvbU51bWJlcih0LGU9bmV3IFVpbnQzMkFycmF5KDIpKXtyZXR1cm4gU3IuZnJvbVN0cmluZyh0LnRvU3RyaW5nKCksZSl9c3RhdGljIGZyb21TdHJpbmcodCxlPW5ldyBVaW50MzJBcnJheSgyKSl7bGV0IHI9dC5zdGFydHNXaXRoKCItIiksbj10Lmxlbmd0aCxpPW5ldyBTcihlKTtmb3IobGV0IHM9cj8xOjA7czxuOyl7bGV0IG89eGM8bi1zP3hjOm4tcyxhPW5ldyBTcihuZXcgVWludDMyQXJyYXkoW051bWJlci5wYXJzZUludCh0LnNsaWNlKHMscytvKSwxMCksMF0pKSxsPW5ldyBTcihuZXcgVWludDMyQXJyYXkoW0dtW29dLDBdKSk7aS50aW1lcyhsKSxpLnBsdXMoYSkscys9b31yZXR1cm4gcj9pLm5lZ2F0ZSgpOml9c3RhdGljIGNvbnZlcnRBcnJheSh0KXtsZXQgZT1uZXcgVWludDMyQXJyYXkodC5sZW5ndGgqMik7Zm9yKGxldCByPS0xLG49dC5sZW5ndGg7KytyPG47KVNyLmZyb20odFtyXSxuZXcgVWludDMyQXJyYXkoZS5idWZmZXIsZS5ieXRlT2Zmc2V0KzIqcio0LDIpKTtyZXR1cm4gZX1zdGF0aWMgbXVsdGlwbHkodCxlKXtyZXR1cm4gbmV3IFNyKG5ldyBVaW50MzJBcnJheSh0LmJ1ZmZlcikpLnRpbWVzKGUpfXN0YXRpYyBhZGQodCxlKXtyZXR1cm4gbmV3IFNyKG5ldyBVaW50MzJBcnJheSh0LmJ1ZmZlcikpLnBsdXMoZSl9fX0pO3ZhciB0eT17fTtaZSh0eSx7dG9JbnRlcnZhbERheVRpbWVJbnQzMkFycmF5OigpPT5abSx0b0ludGVydmFsRGF5VGltZU9iamVjdHM6KCk9PkdULHRvSW50ZXJ2YWxNb250aERheU5hbm9JbnQzMkFycmF5OigpPT5RbSx0b0ludGVydmFsTW9udGhEYXlOYW5vT2JqZWN0czooKT0+SlR9KTtmdW5jdGlvbiBabSh0KXt2YXIgZSxyO2xldCBuPXQubGVuZ3RoLGk9bmV3IEludDMyQXJyYXkobioyKTtmb3IobGV0IHM9MCxvPTA7czxuO3MrKyl7bGV0IGE9dFtzXTtpW28rK109KGU9YS5kYXlzKSE9PW51bGwmJmUhPT12b2lkIDA/ZTowLGlbbysrXT0ocj1hLm1pbGxpc2Vjb25kcykhPT1udWxsJiZyIT09dm9pZCAwP3I6MH1yZXR1cm4gaX1mdW5jdGlvbiBRbSh0KXt2YXIgZSxyO2xldCBuPXQubGVuZ3RoLGk9bmV3IEludDMyQXJyYXkobio0KTtmb3IobGV0IHM9MCxvPTA7czxuO3MrKyl7bGV0IGE9dFtzXTtpW28rK109KGU9YS5tb250aHMpIT09bnVsbCYmZSE9PXZvaWQgMD9lOjAsaVtvKytdPShyPWEuZGF5cykhPT1udWxsJiZyIT09dm9pZCAwP3I6MDtsZXQgbD1hLm5hbm9zZWNvbmRzO2lmKGwpe2xldCB1PUJpZ0ludChsKTtpW28rK109TnVtYmVyKHUmQmlnSW50KDQyOTQ5NjcyOTUpKT4+PjAsaVtvKytdPU51bWJlcih1Pj5CaWdJbnQoMzIpKT4+PjB9ZWxzZSBvKz0yfXJldHVybiBpfWZ1bmN0aW9uIEdUKHQpe2xldCBlPXQubGVuZ3RoLHI9QXJyYXkoZS8yKTtmb3IobGV0IG49MCxpPTA7bjxlO24rPTIpcltpKytdPXtkYXlzOnRbbl0sbWlsbGlzZWNvbmRzOnRbbisxXX07cmV0dXJuIHJ9ZnVuY3Rpb24gSlQodCxlKXtsZXQgcj10Lmxlbmd0aCxuPUFycmF5KHIvNCk7Zm9yKGxldCBpPTAscz0wO2k8cjtpKz00KXtsZXQgbz1CaWdJbnQodFtpKzNdKTw8QmlnSW50KDMyKXxCaWdJbnQodFtpKzJdPj4+MCk7bltzKytdPXttb250aHM6dFtpXSxkYXlzOnRbaSsxXSxuYW5vc2Vjb25kczplP2Ake299YDpvfX1yZXR1cm4gbn1mdW5jdGlvbiB6dih0KXtsZXQgZT1uZXcgVWludDhBcnJheSh0Lmxlbmd0aC8yKTtmb3IobGV0IHI9MDtyPHQubGVuZ3RoO3IrPTIpZVtyPj4xXT1OdW1iZXIucGFyc2VJbnQodC5zbGljZShyLHIrMiksMTYpO3JldHVybiBlfWZ1bmN0aW9uIFhUKHQpe3JldHVybiB6dih0LmpvaW4oIiIpKX1mdW5jdGlvbiBqdih0LGUpe2xldCByPW5ldyBVaW50OEFycmF5KHQubGVuZ3RoKjE2KSxuPW5ldyBEYXRhVmlldyhyLmJ1ZmZlcik7Zm9yKGxldFtpLHNdb2YgdC5lbnRyaWVzKCkpe2xldCBvPWkqMTYsYT1zLlNJWkU7aWYobi5zZXRJbnQzMihvLGEsITApLHMuSU5MSU5FRCE9PXZvaWQgMCl7bGV0IGw9ZShzLklOTElORUQpO2ZvcihsZXQgdT0wO3U8bC5sZW5ndGgmJnU8MTI7dSsrKXJbbys0K3VdPWxbdV19ZWxzZXtsZXQgbD1zLlBSRUZJWF9IRVg7Zm9yKGxldCB1PTA7dTw4JiZ1PGwubGVuZ3RoO3UrPTIpcltvKzQrKHU+PjEpXT1OdW1iZXIucGFyc2VJbnQobC5zbGljZSh1LHUrMiksMTYpO24uc2V0SW50MzIobys4LHMuQlVGRkVSX0lOREVYLCEwKSxuLnNldEludDMyKG8rMTIscy5PRkZTRVQsITApfX1yZXR1cm4gcn1mdW5jdGlvbiBaVCh0KXtyZXR1cm4ganYodCwoZSk9PntsZXQgcj1uZXcgVWludDhBcnJheShlLmxlbmd0aC8yKTtmb3IobGV0IG49MDtuPGUubGVuZ3RoO24rPTIpcltuPj4xXT1OdW1iZXIucGFyc2VJbnQoZS5zbGljZShuLG4rMiksMTYpO3JldHVybiByfSl9ZnVuY3Rpb24gUVQodCl7cmV0dXJuIGp2KHQsKGUpPT5uZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoZSkpfXZhciBIbCxleSxyeTt2YXIgJHY9bSgoKT0+e1huKCk7VXIoKTtpZSgpO1VpKCk7d2MoKTt2cygpO1htKCk7TGUoKTtqZSgpO0hsPWNsYXNzIEhsIGV4dGVuZHMgZXR7Y29uc3RydWN0b3IodCxlLHIsbixpPSR0LlY1LHM9W10pe3N1cGVyKCk7dGhpcy5ub2Rlc0luZGV4PS0xLHRoaXMuYnVmZmVyc0luZGV4PS0xLHRoaXMudmFyaWFkaWNCdWZmZXJJbmRleD0tMSx0aGlzLmJ5dGVzPXQsdGhpcy5ub2Rlcz1lLHRoaXMuYnVmZmVycz1yLHRoaXMuZGljdGlvbmFyaWVzPW4sdGhpcy5tZXRhZGF0YVZlcnNpb249aSx0aGlzLnZhcmlhZGljQnVmZmVyQ291bnRzPXN9dmlzaXQodCl7cmV0dXJuIHN1cGVyLnZpc2l0KHQgaW5zdGFuY2VvZiBVP3QudHlwZTp0KX12aXNpdE51bGwodCx7bGVuZ3RoOmV9PXRoaXMubmV4dEZpZWxkTm9kZSgpKXtyZXR1cm4gUyh7dHlwZTp0LGxlbmd0aDplfSl9dmlzaXRCb29sKHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7cmV0dXJuIFMoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cixudWxsQml0bWFwOnRoaXMucmVhZE51bGxCaXRtYXAodCxyKSxkYXRhOnRoaXMucmVhZERhdGEodCl9KX12aXNpdEludCh0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe3JldHVybiBTKHt0eXBlOnQsbGVuZ3RoOmUsbnVsbENvdW50OnIsbnVsbEJpdG1hcDp0aGlzLnJlYWROdWxsQml0bWFwKHQsciksZGF0YTp0aGlzLnJlYWREYXRhKHQpfSl9dmlzaXRGbG9hdCh0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe3JldHVybiBTKHt0eXBlOnQsbGVuZ3RoOmUsbnVsbENvdW50OnIsbnVsbEJpdG1hcDp0aGlzLnJlYWROdWxsQml0bWFwKHQsciksZGF0YTp0aGlzLnJlYWREYXRhKHQpfSl9dmlzaXRVdGY4KHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7cmV0dXJuIFMoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cixudWxsQml0bWFwOnRoaXMucmVhZE51bGxCaXRtYXAodCxyKSx2YWx1ZU9mZnNldHM6dGhpcy5yZWFkT2Zmc2V0cyh0KSxkYXRhOnRoaXMucmVhZERhdGEodCl9KX12aXNpdExhcmdlVXRmOCh0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe3JldHVybiBTKHt0eXBlOnQsbGVuZ3RoOmUsbnVsbENvdW50OnIsbnVsbEJpdG1hcDp0aGlzLnJlYWROdWxsQml0bWFwKHQsciksdmFsdWVPZmZzZXRzOnRoaXMucmVhZE9mZnNldHModCksZGF0YTp0aGlzLnJlYWREYXRhKHQpfSl9dmlzaXRVdGY4Vmlldyh0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe2xldCBuPXRoaXMucmVhZE51bGxCaXRtYXAodCxyKSxpPXRoaXMucmVhZERhdGEodCkscz10aGlzLnJlYWRWYXJpYWRpY0J1ZmZlcnModGhpcy5uZXh0VmFyaWFkaWNCdWZmZXJDb3VudCgpKTtyZXR1cm4gUyh7dHlwZTp0LGxlbmd0aDplLG51bGxDb3VudDpyLG51bGxCaXRtYXA6bixbInZpZXdzIl06aSxbInZhcmlhZGljQnVmZmVycyJdOnN9KX12aXNpdEJpbmFyeSh0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe3JldHVybiBTKHt0eXBlOnQsbGVuZ3RoOmUsbnVsbENvdW50OnIsbnVsbEJpdG1hcDp0aGlzLnJlYWROdWxsQml0bWFwKHQsciksdmFsdWVPZmZzZXRzOnRoaXMucmVhZE9mZnNldHModCksZGF0YTp0aGlzLnJlYWREYXRhKHQpfSl9dmlzaXRMYXJnZUJpbmFyeSh0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe3JldHVybiBTKHt0eXBlOnQsbGVuZ3RoOmUsbnVsbENvdW50OnIsbnVsbEJpdG1hcDp0aGlzLnJlYWROdWxsQml0bWFwKHQsciksdmFsdWVPZmZzZXRzOnRoaXMucmVhZE9mZnNldHModCksZGF0YTp0aGlzLnJlYWREYXRhKHQpfSl9dmlzaXRCaW5hcnlWaWV3KHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7bGV0IG49dGhpcy5yZWFkTnVsbEJpdG1hcCh0LHIpLGk9dGhpcy5yZWFkRGF0YSh0KSxzPXRoaXMucmVhZFZhcmlhZGljQnVmZmVycyh0aGlzLm5leHRWYXJpYWRpY0J1ZmZlckNvdW50KCkpO3JldHVybiBTKHt0eXBlOnQsbGVuZ3RoOmUsbnVsbENvdW50OnIsbnVsbEJpdG1hcDpuLFsidmlld3MiXTppLFsidmFyaWFkaWNCdWZmZXJzIl06c30pfXZpc2l0Rml4ZWRTaXplQmluYXJ5KHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7cmV0dXJuIFMoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cixudWxsQml0bWFwOnRoaXMucmVhZE51bGxCaXRtYXAodCxyKSxkYXRhOnRoaXMucmVhZERhdGEodCl9KX12aXNpdERhdGUodCx7bGVuZ3RoOmUsbnVsbENvdW50OnJ9PXRoaXMubmV4dEZpZWxkTm9kZSgpKXtyZXR1cm4gUyh7dHlwZTp0LGxlbmd0aDplLG51bGxDb3VudDpyLG51bGxCaXRtYXA6dGhpcy5yZWFkTnVsbEJpdG1hcCh0LHIpLGRhdGE6dGhpcy5yZWFkRGF0YSh0KX0pfXZpc2l0VGltZXN0YW1wKHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7cmV0dXJuIFMoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cixudWxsQml0bWFwOnRoaXMucmVhZE51bGxCaXRtYXAodCxyKSxkYXRhOnRoaXMucmVhZERhdGEodCl9KX12aXNpdFRpbWUodCx7bGVuZ3RoOmUsbnVsbENvdW50OnJ9PXRoaXMubmV4dEZpZWxkTm9kZSgpKXtyZXR1cm4gUyh7dHlwZTp0LGxlbmd0aDplLG51bGxDb3VudDpyLG51bGxCaXRtYXA6dGhpcy5yZWFkTnVsbEJpdG1hcCh0LHIpLGRhdGE6dGhpcy5yZWFkRGF0YSh0KX0pfXZpc2l0RGVjaW1hbCh0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe3JldHVybiBTKHt0eXBlOnQsbGVuZ3RoOmUsbnVsbENvdW50OnIsbnVsbEJpdG1hcDp0aGlzLnJlYWROdWxsQml0bWFwKHQsciksZGF0YTp0aGlzLnJlYWREYXRhKHQpfSl9dmlzaXRMaXN0KHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7cmV0dXJuIFMoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cixudWxsQml0bWFwOnRoaXMucmVhZE51bGxCaXRtYXAodCxyKSx2YWx1ZU9mZnNldHM6dGhpcy5yZWFkT2Zmc2V0cyh0KSxjaGlsZDp0aGlzLnZpc2l0KHQuY2hpbGRyZW5bMF0pfSl9dmlzaXRTdHJ1Y3QodCx7bGVuZ3RoOmUsbnVsbENvdW50OnJ9PXRoaXMubmV4dEZpZWxkTm9kZSgpKXtyZXR1cm4gUyh7dHlwZTp0LGxlbmd0aDplLG51bGxDb3VudDpyLG51bGxCaXRtYXA6dGhpcy5yZWFkTnVsbEJpdG1hcCh0LHIpLGNoaWxkcmVuOnRoaXMudmlzaXRNYW55KHQuY2hpbGRyZW4pfSl9dmlzaXRVbmlvbih0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe2lmKHRoaXMubWV0YWRhdGFWZXJzaW9uPCR0LlY1KXRoaXMucmVhZE51bGxCaXRtYXAodCxyKTtyZXR1cm4gdC5tb2RlPT09THQuU3BhcnNlP3RoaXMudmlzaXRTcGFyc2VVbmlvbih0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn0pOnRoaXMudmlzaXREZW5zZVVuaW9uKHQse2xlbmd0aDplLG51bGxDb3VudDpyfSl9dmlzaXREZW5zZVVuaW9uKHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7cmV0dXJuIFMoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cix0eXBlSWRzOnRoaXMucmVhZFR5cGVJZHModCksdmFsdWVPZmZzZXRzOnRoaXMucmVhZE9mZnNldHModCksY2hpbGRyZW46dGhpcy52aXNpdE1hbnkodC5jaGlsZHJlbil9KX12aXNpdFNwYXJzZVVuaW9uKHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7cmV0dXJuIFMoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cix0eXBlSWRzOnRoaXMucmVhZFR5cGVJZHModCksY2hpbGRyZW46dGhpcy52aXNpdE1hbnkodC5jaGlsZHJlbil9KX12aXNpdERpY3Rpb25hcnkodCx7bGVuZ3RoOmUsbnVsbENvdW50OnJ9PXRoaXMubmV4dEZpZWxkTm9kZSgpKXtyZXR1cm4gUyh7dHlwZTp0LGxlbmd0aDplLG51bGxDb3VudDpyLG51bGxCaXRtYXA6dGhpcy5yZWFkTnVsbEJpdG1hcCh0LHIpLGRhdGE6dGhpcy5yZWFkRGF0YSh0LmluZGljZXMpLGRpY3Rpb25hcnk6dGhpcy5yZWFkRGljdGlvbmFyeSh0KX0pfXZpc2l0SW50ZXJ2YWwodCx7bGVuZ3RoOmUsbnVsbENvdW50OnJ9PXRoaXMubmV4dEZpZWxkTm9kZSgpKXtyZXR1cm4gUyh7dHlwZTp0LGxlbmd0aDplLG51bGxDb3VudDpyLG51bGxCaXRtYXA6dGhpcy5yZWFkTnVsbEJpdG1hcCh0LHIpLGRhdGE6dGhpcy5yZWFkRGF0YSh0KX0pfXZpc2l0RHVyYXRpb24odCx7bGVuZ3RoOmUsbnVsbENvdW50OnJ9PXRoaXMubmV4dEZpZWxkTm9kZSgpKXtyZXR1cm4gUyh7dHlwZTp0LGxlbmd0aDplLG51bGxDb3VudDpyLG51bGxCaXRtYXA6dGhpcy5yZWFkTnVsbEJpdG1hcCh0LHIpLGRhdGE6dGhpcy5yZWFkRGF0YSh0KX0pfXZpc2l0Rml4ZWRTaXplTGlzdCh0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe3JldHVybiBTKHt0eXBlOnQsbGVuZ3RoOmUsbnVsbENvdW50OnIsbnVsbEJpdG1hcDp0aGlzLnJlYWROdWxsQml0bWFwKHQsciksY2hpbGQ6dGhpcy52aXNpdCh0LmNoaWxkcmVuWzBdKX0pfXZpc2l0TWFwKHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7cmV0dXJuIFMoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cixudWxsQml0bWFwOnRoaXMucmVhZE51bGxCaXRtYXAodCxyKSx2YWx1ZU9mZnNldHM6dGhpcy5yZWFkT2Zmc2V0cyh0KSxjaGlsZDp0aGlzLnZpc2l0KHQuY2hpbGRyZW5bMF0pfSl9bmV4dEZpZWxkTm9kZSgpe3JldHVybiB0aGlzLm5vZGVzWysrdGhpcy5ub2Rlc0luZGV4XX1uZXh0QnVmZmVyUmFuZ2UoKXtyZXR1cm4gdGhpcy5idWZmZXJzWysrdGhpcy5idWZmZXJzSW5kZXhdfXJlYWROdWxsQml0bWFwKHQsZSxyPXRoaXMubmV4dEJ1ZmZlclJhbmdlKCkpe3JldHVybiBlPjAmJnRoaXMucmVhZERhdGEodCxyKXx8bmV3IFVpbnQ4QXJyYXkoMCl9cmVhZE9mZnNldHModCxlKXtyZXR1cm4gdGhpcy5yZWFkRGF0YSh0LGUpfXJlYWRUeXBlSWRzKHQsZSl7cmV0dXJuIHRoaXMucmVhZERhdGEodCxlKX1yZWFkRGF0YSh0LHtsZW5ndGg6ZSxvZmZzZXQ6cn09dGhpcy5uZXh0QnVmZmVyUmFuZ2UoKSl7cmV0dXJuIHRoaXMuYnl0ZXMuc3ViYXJyYXkocixyK2UpfXJlYWRWYXJpYWRpY0J1ZmZlcnModCl7cmV0dXJuIEFycmF5LmZyb20oe2xlbmd0aDp0fSwoKT0+dGhpcy5yZWFkRGF0YShudWxsKSl9bmV4dFZhcmlhZGljQnVmZmVyQ291bnQoKXt2YXIgdDtyZXR1cm4odD10aGlzLnZhcmlhZGljQnVmZmVyQ291bnRzWysrdGhpcy52YXJpYWRpY0J1ZmZlckluZGV4XSkhPT1udWxsJiZ0IT09dm9pZCAwP3Q6MH1yZWFkRGljdGlvbmFyeSh0KXtyZXR1cm4gdGhpcy5kaWN0aW9uYXJpZXMuZ2V0KHQuaWQpfX07ZXk9Y2xhc3MgZXkgZXh0ZW5kcyBIbHtjb25zdHJ1Y3Rvcih0LGUscixuLGkscz1bXSl7c3VwZXIobmV3IFVpbnQ4QXJyYXkoMCksZSxyLG4saSxzKTt0aGlzLnNvdXJjZXM9dH1yZWFkTnVsbEJpdG1hcCh0LGUse29mZnNldDpyfT10aGlzLm5leHRCdWZmZXJSYW5nZSgpKXtyZXR1cm4gZTw9MD9uZXcgVWludDhBcnJheSgwKTpoYSh0aGlzLnNvdXJjZXNbcl0pfXJlYWRPZmZzZXRzKHQse29mZnNldDplfT10aGlzLm5leHRCdWZmZXJSYW5nZSgpKXtyZXR1cm4gd3QoVWludDhBcnJheSx3dCh0Lk9mZnNldEFycmF5VHlwZSx0aGlzLnNvdXJjZXNbZV0pKX1yZWFkVHlwZUlkcyh0LHtvZmZzZXQ6ZX09dGhpcy5uZXh0QnVmZmVyUmFuZ2UoKSl7cmV0dXJuIHd0KFVpbnQ4QXJyYXksd3QodC5BcnJheVR5cGUsdGhpcy5zb3VyY2VzW2VdKSl9cmVhZERhdGEodCx7b2Zmc2V0OmV9PXRoaXMubmV4dEJ1ZmZlclJhbmdlKCkpe2xldHtzb3VyY2VzOnJ9PXRoaXM7aWYoQi5pc1RpbWVzdGFtcCh0KSlyZXR1cm4gd3QoVWludDhBcnJheSxTci5jb252ZXJ0QXJyYXkocltlXSkpO2Vsc2UgaWYoKEIuaXNJbnQodCl8fEIuaXNUaW1lKHQpKSYmdC5iaXRXaWR0aD09PTY0fHxCLmlzRHVyYXRpb24odCkpcmV0dXJuIHd0KFVpbnQ4QXJyYXksU3IuY29udmVydEFycmF5KHJbZV0pKTtlbHNlIGlmKEIuaXNEYXRlKHQpJiZ0LnVuaXQ9PT1xdC5NSUxMSVNFQ09ORClyZXR1cm4gd3QoVWludDhBcnJheSxTci5jb252ZXJ0QXJyYXkocltlXSkpO2Vsc2UgaWYoQi5pc0RlY2ltYWwodCkpcmV0dXJuIHd0KFVpbnQ4QXJyYXksUW4uY29udmVydEFycmF5KHJbZV0pKTtlbHNlIGlmKEIuaXNCaW5hcnkodCl8fEIuaXNMYXJnZUJpbmFyeSh0KXx8Qi5pc0ZpeGVkU2l6ZUJpbmFyeSh0KSlyZXR1cm4gWFQocltlXSk7ZWxzZSBpZihCLmlzQmluYXJ5Vmlldyh0KSlyZXR1cm4gWlQocltlXSk7ZWxzZSBpZihCLmlzVXRmOFZpZXcodCkpcmV0dXJuIFFUKHJbZV0pO2Vsc2UgaWYoQi5pc0Jvb2wodCkpcmV0dXJuIGhhKHJbZV0pO2Vsc2UgaWYoQi5pc1V0ZjgodCl8fEIuaXNMYXJnZVV0ZjgodCkpcmV0dXJuIG1uKHJbZV0uam9pbigiIikpO2Vsc2UgaWYoQi5pc0ludGVydmFsKHQpKXN3aXRjaCh0LnVuaXQpe2Nhc2UganQuREFZX1RJTUU6cmV0dXJuIFptKHJbZV0pO2Nhc2UganQuTU9OVEhfREFZX05BTk86cmV0dXJuIFFtKHJbZV0pO2RlZmF1bHQ6YnJlYWt9cmV0dXJuIHd0KFVpbnQ4QXJyYXksd3QodC5BcnJheVR5cGUscltlXS5tYXAoKG4pPT4rbikpKX1yZWFkVmFyaWFkaWNCdWZmZXJzKHQpe2xldCBlPVtdO2ZvcihsZXQgcj0wO3I8dDtyKyspe2xldHtvZmZzZXQ6bn09dGhpcy5uZXh0QnVmZmVyUmFuZ2UoKSxpPXRoaXMuc291cmNlc1tuXTtlLnB1c2goenYoaSkpfXJldHVybiBlfX07cnk9Y2xhc3MgcnkgZXh0ZW5kcyBIbHtjb25zdHJ1Y3Rvcih0LGUscixuLGkscz1bXSl7c3VwZXIobmV3IFVpbnQ4QXJyYXkoMCksZSxyLG4saSxzKTt0aGlzLmJvZHlDaHVua3M9dH1yZWFkRGF0YSh0LGU9dGhpcy5uZXh0QnVmZmVyUmFuZ2UoKSl7cmV0dXJuIHRoaXMuYm9keUNodW5rc1t0aGlzLmJ1ZmZlcnNJbmRleF19fX0pO3ZhciBZbDt2YXIgbnk9bSgoKT0+e2FzKCk7X2UoKTtqZSgpO1lsPWNsYXNzIFlsIGV4dGVuZHMgRG57Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5fdmFsdWVzPW5ldyBBbihVaW50OEFycmF5KX1nZXQgYnl0ZUxlbmd0aCgpe2xldCB0PXRoaXMuX3BlbmRpbmdMZW5ndGgrdGhpcy5sZW5ndGgqNDtyZXR1cm4gdGhpcy5fb2Zmc2V0cyYmKHQrPXRoaXMuX29mZnNldHMuYnl0ZUxlbmd0aCksdGhpcy5fdmFsdWVzJiYodCs9dGhpcy5fdmFsdWVzLmJ5dGVMZW5ndGgpLHRoaXMuX251bGxzJiYodCs9dGhpcy5fbnVsbHMuYnl0ZUxlbmd0aCksdH1zZXRWYWx1ZSh0LGUpe3JldHVybiBzdXBlci5zZXRWYWx1ZSh0LEMoZSkpfV9mbHVzaFBlbmRpbmcodCxlKXtsZXQgcj10aGlzLl9vZmZzZXRzLG49dGhpcy5fdmFsdWVzLnJlc2VydmUoZSkuYnVmZmVyLGk9MDtmb3IobGV0W3Msb11vZiB0KWlmKG89PT12b2lkIDApci5zZXQocywwKTtlbHNle2xldCBhPW8ubGVuZ3RoO24uc2V0KG8saSksci5zZXQocyxhKSxpKz1hfX19fSk7dmFyIEtsO3ZhciBpeT1tKCgpPT57amUoKTthcygpO19lKCk7S2w9Y2xhc3MgS2wgZXh0ZW5kcyBEbntjb25zdHJ1Y3Rvcih0KXtzdXBlcih0KTt0aGlzLl92YWx1ZXM9bmV3IEFuKFVpbnQ4QXJyYXkpfWdldCBieXRlTGVuZ3RoKCl7bGV0IHQ9dGhpcy5fcGVuZGluZ0xlbmd0aCt0aGlzLmxlbmd0aCo0O3JldHVybiB0aGlzLl9vZmZzZXRzJiYodCs9dGhpcy5fb2Zmc2V0cy5ieXRlTGVuZ3RoKSx0aGlzLl92YWx1ZXMmJih0Kz10aGlzLl92YWx1ZXMuYnl0ZUxlbmd0aCksdGhpcy5fbnVsbHMmJih0Kz10aGlzLl9udWxscy5ieXRlTGVuZ3RoKSx0fXNldFZhbHVlKHQsZSl7cmV0dXJuIHN1cGVyLnNldFZhbHVlKHQsQyhlKSl9X2ZsdXNoUGVuZGluZyh0LGUpe2xldCByPXRoaXMuX29mZnNldHMsbj10aGlzLl92YWx1ZXMucmVzZXJ2ZShlKS5idWZmZXIsaT0wO2ZvcihsZXRbcyxvXW9mIHQpaWYobz09PXZvaWQgMClyLnNldChzLEJpZ0ludCgwKSk7ZWxzZXtsZXQgYT1vLmxlbmd0aDtuLnNldChvLGkpLHIuc2V0KHMsQmlnSW50KGEpKSxpKz1hfX19fSk7dmFyIHN5O3ZhciBxdj1tKCgpPT57YXMoKTtfZSgpO3N5PWNsYXNzIHN5IGV4dGVuZHMgdWV7Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5fdmFsdWVzPW5ldyAkbH1zZXRWYWx1ZSh0LGUpe3RoaXMuX3ZhbHVlcy5zZXQodCwrZSl9fX0pO3ZhciBUYyxyZCxuZDt2YXIgV3Y9bSgoKT0+e19lKCk7U24oKTtUYz1jbGFzcyBUYyBleHRlbmRzIHFle307VGMucHJvdG90eXBlLl9zZXRWYWx1ZT1GbTtyZD1jbGFzcyByZCBleHRlbmRzIFRje307cmQucHJvdG90eXBlLl9zZXRWYWx1ZT1nZjtuZD1jbGFzcyBuZCBleHRlbmRzIFRje307bmQucHJvdG90eXBlLl9zZXRWYWx1ZT1iZn0pO3ZhciBpZDt2YXIgSHY9bSgoKT0+e19lKCk7U24oKTtpZD1jbGFzcyBpZCBleHRlbmRzIHFle307aWQucHJvdG90eXBlLl9zZXRWYWx1ZT1VbX0pO3ZhciBveTt2YXIgWXY9bSgoKT0+e2llKCk7X2UoKTtzZCgpO295PWNsYXNzIG95IGV4dGVuZHMgdWV7Y29uc3RydWN0b3Ioe3R5cGU6dCxudWxsVmFsdWVzOmUsZGljdGlvbmFyeUhhc2hGdW5jdGlvbjpyfSl7c3VwZXIoe3R5cGU6bmV3IGZyKHQuZGljdGlvbmFyeSx0LmluZGljZXMsdC5pZCx0LmlzT3JkZXJlZCl9KTtpZih0aGlzLl9udWxscz1udWxsLHRoaXMuX2RpY3Rpb25hcnlPZmZzZXQ9MCx0aGlzLl9rZXlzVG9JbmRpY2VzPU9iamVjdC5jcmVhdGUobnVsbCksdGhpcy5pbmRpY2VzPXhzKHt0eXBlOnRoaXMudHlwZS5pbmRpY2VzLG51bGxWYWx1ZXM6ZX0pLHRoaXMuZGljdGlvbmFyeT14cyh7dHlwZTp0aGlzLnR5cGUuZGljdGlvbmFyeSxudWxsVmFsdWVzOm51bGx9KSx0eXBlb2Ygcj09PSJmdW5jdGlvbiIpdGhpcy52YWx1ZVRvS2V5PXJ9Z2V0IHZhbHVlcygpe3JldHVybiB0aGlzLmluZGljZXMudmFsdWVzfWdldCBudWxsQ291bnQoKXtyZXR1cm4gdGhpcy5pbmRpY2VzLm51bGxDb3VudH1nZXQgbnVsbEJpdG1hcCgpe3JldHVybiB0aGlzLmluZGljZXMubnVsbEJpdG1hcH1nZXQgYnl0ZUxlbmd0aCgpe3JldHVybiB0aGlzLmluZGljZXMuYnl0ZUxlbmd0aCt0aGlzLmRpY3Rpb25hcnkuYnl0ZUxlbmd0aH1nZXQgcmVzZXJ2ZWRMZW5ndGgoKXtyZXR1cm4gdGhpcy5pbmRpY2VzLnJlc2VydmVkTGVuZ3RoK3RoaXMuZGljdGlvbmFyeS5yZXNlcnZlZExlbmd0aH1nZXQgcmVzZXJ2ZWRCeXRlTGVuZ3RoKCl7cmV0dXJuIHRoaXMuaW5kaWNlcy5yZXNlcnZlZEJ5dGVMZW5ndGgrdGhpcy5kaWN0aW9uYXJ5LnJlc2VydmVkQnl0ZUxlbmd0aH1pc1ZhbGlkKHQpe3JldHVybiB0aGlzLmluZGljZXMuaXNWYWxpZCh0KX1zZXRWYWxpZCh0LGUpe2xldCByPXRoaXMuaW5kaWNlcztyZXR1cm4gZT1yLnNldFZhbGlkKHQsZSksdGhpcy5sZW5ndGg9ci5sZW5ndGgsZX1zZXRWYWx1ZSh0LGUpe2xldCByPXRoaXMuX2tleXNUb0luZGljZXMsbj10aGlzLnZhbHVlVG9LZXkoZSksaT1yW25dO2lmKGk9PT12b2lkIDApcltuXT1pPXRoaXMuX2RpY3Rpb25hcnlPZmZzZXQrdGhpcy5kaWN0aW9uYXJ5LmFwcGVuZChlKS5sZW5ndGgtMTtyZXR1cm4gdGhpcy5pbmRpY2VzLnNldFZhbHVlKHQsaSl9Zmx1c2goKXtsZXQgdD10aGlzLnR5cGUsZT10aGlzLl9kaWN0aW9uYXJ5LHI9dGhpcy5kaWN0aW9uYXJ5LnRvVmVjdG9yKCksbj10aGlzLmluZGljZXMuZmx1c2goKS5jbG9uZSh0KTtyZXR1cm4gbi5kaWN0aW9uYXJ5PWU/ZS5jb25jYXQocik6cix0aGlzLmZpbmlzaGVkfHwodGhpcy5fZGljdGlvbmFyeU9mZnNldCs9ci5sZW5ndGgpLHRoaXMuX2RpY3Rpb25hcnk9bi5kaWN0aW9uYXJ5LHRoaXMuY2xlYXIoKSxufWZpbmlzaCgpe3JldHVybiB0aGlzLmluZGljZXMuZmluaXNoKCksdGhpcy5kaWN0aW9uYXJ5LmZpbmlzaCgpLHRoaXMuX2RpY3Rpb25hcnlPZmZzZXQ9MCx0aGlzLl9rZXlzVG9JbmRpY2VzPU9iamVjdC5jcmVhdGUobnVsbCksc3VwZXIuZmluaXNoKCl9Y2xlYXIoKXtyZXR1cm4gdGhpcy5pbmRpY2VzLmNsZWFyKCksdGhpcy5kaWN0aW9uYXJ5LmNsZWFyKCksc3VwZXIuY2xlYXIoKX12YWx1ZVRvS2V5KHQpe3JldHVybiB0eXBlb2YgdD09PSJzdHJpbmciP3Q6YCR7dH1gfX19KTt2YXIgb2Q7dmFyIEt2PW0oKCk9PntfZSgpO1NuKCk7b2Q9Y2xhc3Mgb2QgZXh0ZW5kcyBxZXt9O29kLnByb3RvdHlwZS5fc2V0VmFsdWU9Tm19KTt2YXIgYXk7dmFyIEd2PW0oKCk9PntVcigpO19lKCk7aWUoKTtheT1jbGFzcyBheSBleHRlbmRzIHVle3NldFZhbHVlKHQsZSl7bGV0W3JdPXRoaXMuY2hpbGRyZW4sbj10KnRoaXMuc3RyaWRlO2ZvcihsZXQgaT0tMSxzPXRoaXMuc3RyaWRlOysraTxzOylyLnNldChuK2ksZVtpXSl9c2V0VmFsaWQodCxlKXtpZighc3VwZXIuc2V0VmFsaWQodCxlKSl0aGlzLmNoaWxkcmVuWzBdLnNldFZhbGlkKCh0KzEpKnRoaXMuc3RyaWRlLTEsITEpO3JldHVybiBlfWFkZENoaWxkKHQsZT0iMCIpe2lmKHRoaXMubnVtQ2hpbGRyZW4+MCl0aHJvdyBFcnJvcigiRml4ZWRTaXplTGlzdEJ1aWxkZXIgY2FuIG9ubHkgaGF2ZSBvbmUgY2hpbGQuIik7bGV0IHI9dGhpcy5jaGlsZHJlbi5wdXNoKHQpO3JldHVybiB0aGlzLnR5cGU9bmV3IHduKHRoaXMudHlwZS5saXN0U2l6ZSxuZXcgVShlLHQudHlwZSwhMCkpLHJ9fX0pO3ZhciBFYyxjeSxseSx1eTt2YXIgSnY9bSgoKT0+e1BsKCk7X2UoKTtFYz1jbGFzcyBFYyBleHRlbmRzIHFle3NldFZhbHVlKHQsZSl7dGhpcy5fdmFsdWVzLnNldCh0LGUpfX07Y3k9Y2xhc3MgY3kgZXh0ZW5kcyBFY3tzZXRWYWx1ZSh0LGUpe3N1cGVyLnNldFZhbHVlKHQsQ2woZSkpfX07bHk9Y2xhc3MgbHkgZXh0ZW5kcyBFY3t9O3V5PWNsYXNzIHV5IGV4dGVuZHMgRWN7fX0pO3ZhciBiYSxhZCxjZCxsZDt2YXIgWHY9bSgoKT0+e19lKCk7U24oKTtiYT1jbGFzcyBiYSBleHRlbmRzIHFle307YmEucHJvdG90eXBlLl9zZXRWYWx1ZT1SbTthZD1jbGFzcyBhZCBleHRlbmRzIGJhe307YWQucHJvdG90eXBlLl9zZXRWYWx1ZT1UZjtjZD1jbGFzcyBjZCBleHRlbmRzIGJhe307Y2QucHJvdG90eXBlLl9zZXRWYWx1ZT1FZjtsZD1jbGFzcyBsZCBleHRlbmRzIGJhe307bGQucHJvdG90eXBlLl9zZXRWYWx1ZT1PZn0pO3ZhciBUbyx1ZCxmZCxkZCxoZDt2YXIgWnY9bSgoKT0+e19lKCk7U24oKTtUbz1jbGFzcyBUbyBleHRlbmRzIHFle307VG8ucHJvdG90eXBlLl9zZXRWYWx1ZT1DbTt1ZD1jbGFzcyB1ZCBleHRlbmRzIFRve307dWQucHJvdG90eXBlLl9zZXRWYWx1ZT1OZjtmZD1jbGFzcyBmZCBleHRlbmRzIFRve307ZmQucHJvdG90eXBlLl9zZXRWYWx1ZT1GZjtkZD1jbGFzcyBkZCBleHRlbmRzIFRve307ZGQucHJvdG90eXBlLl9zZXRWYWx1ZT1NZjtoZD1jbGFzcyBoZCBleHRlbmRzIFRve307aGQucHJvdG90eXBlLl9zZXRWYWx1ZT1MZn0pO3ZhciBQaSxmeSxkeSxoeSxweSxteSx5eSxfeSxneTt2YXIgUXY9bSgoKT0+e19lKCk7UGk9Y2xhc3MgUGkgZXh0ZW5kcyBxZXtzZXRWYWx1ZSh0LGUpe3RoaXMuX3ZhbHVlcy5zZXQodCxlKX19O2Z5PWNsYXNzIGZ5IGV4dGVuZHMgUGl7fTtkeT1jbGFzcyBkeSBleHRlbmRzIFBpe307aHk9Y2xhc3MgaHkgZXh0ZW5kcyBQaXt9O3B5PWNsYXNzIHB5IGV4dGVuZHMgUGl7fTtteT1jbGFzcyBteSBleHRlbmRzIFBpe307eXk9Y2xhc3MgeXkgZXh0ZW5kcyBQaXt9O195PWNsYXNzIF95IGV4dGVuZHMgUGl7fTtneT1jbGFzcyBneSBleHRlbmRzIFBpe319KTt2YXIgYnk7dmFyIHQwPW0oKCk9PntVcigpO2llKCk7YXMoKTtfZSgpO2J5PWNsYXNzIGJ5IGV4dGVuZHMgRG57Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5fb2Zmc2V0cz1uZXcgcWwodC50eXBlKX1hZGRDaGlsZCh0LGU9IjAiKXtpZih0aGlzLm51bUNoaWxkcmVuPjApdGhyb3cgRXJyb3IoIkxpc3RCdWlsZGVyIGNhbiBvbmx5IGhhdmUgb25lIGNoaWxkLiIpO3JldHVybiB0aGlzLmNoaWxkcmVuW3RoaXMubnVtQ2hpbGRyZW5dPXQsdGhpcy50eXBlPW5ldyBMcihuZXcgVShlLHQudHlwZSwhMCkpLHRoaXMubnVtQ2hpbGRyZW4tMX1fZmx1c2hQZW5kaW5nKHQpe2xldCBlPXRoaXMuX29mZnNldHMsW3JdPXRoaXMuY2hpbGRyZW47Zm9yKGxldFtuLGldb2YgdClpZih0eXBlb2YgaT4idSIpZS5zZXQobiwwKTtlbHNle2xldCBzPWksbz1zLmxlbmd0aCxhPWUuc2V0KG4sbykuYnVmZmVyW25dO2ZvcihsZXQgbD0tMTsrK2w8bzspci5zZXQoYStsLHNbbF0pfX19fSk7dmFyIHd5O3ZhciBlMD1tKCgpPT57VXIoKTtpZSgpO19lKCk7d3k9Y2xhc3Mgd3kgZXh0ZW5kcyBEbntzZXQodCxlKXtyZXR1cm4gc3VwZXIuc2V0KHQsZSl9c2V0VmFsdWUodCxlKXtsZXQgcj1lIGluc3RhbmNlb2YgTWFwP2U6bmV3IE1hcChPYmplY3QuZW50cmllcyhlKSksbj10aGlzLl9wZW5kaW5nfHwodGhpcy5fcGVuZGluZz1uZXcgTWFwKSxpPW4uZ2V0KHQpO2kmJih0aGlzLl9wZW5kaW5nTGVuZ3RoLT1pLnNpemUpLHRoaXMuX3BlbmRpbmdMZW5ndGgrPXIuc2l6ZSxuLnNldCh0LHIpfWFkZENoaWxkKHQsZT1gJHt0aGlzLm51bUNoaWxkcmVufWApe2lmKHRoaXMubnVtQ2hpbGRyZW4+MCl0aHJvdyBFcnJvcigiTGlzdEJ1aWxkZXIgY2FuIG9ubHkgaGF2ZSBvbmUgY2hpbGQuIik7cmV0dXJuIHRoaXMuY2hpbGRyZW5bdGhpcy5udW1DaGlsZHJlbl09dCx0aGlzLnR5cGU9bmV3IHZuKG5ldyBVKGUsdC50eXBlLCEwKSx0aGlzLnR5cGUua2V5c1NvcnRlZCksdGhpcy5udW1DaGlsZHJlbi0xfV9mbHVzaFBlbmRpbmcodCl7bGV0IGU9dGhpcy5fb2Zmc2V0cyxbcl09dGhpcy5jaGlsZHJlbjtmb3IobGV0W24saV1vZiB0KWlmKGk9PT12b2lkIDApZS5zZXQobiwwKTtlbHNle2xldHtbbl06cyxbbisxXTpvfT1lLnNldChuLGkuc2l6ZSkuYnVmZmVyO2ZvcihsZXQgYSBvZiBpLmVudHJpZXMoKSlpZihyLnNldChzLGEpLCsrcz49bylicmVha319fX0pO3ZhciB2eTt2YXIgcjA9bSgoKT0+e19lKCk7dnk9Y2xhc3MgdnkgZXh0ZW5kcyB1ZXtzZXRWYWx1ZSh0LGUpe31zZXRWYWxpZCh0LGUpe3JldHVybiB0aGlzLmxlbmd0aD1NYXRoLm1heCh0KzEsdGhpcy5sZW5ndGgpLGV9fX0pO3ZhciBJeTt2YXIgbjA9bSgoKT0+e1VyKCk7X2UoKTtpZSgpO0l5PWNsYXNzIEl5IGV4dGVuZHMgdWV7c2V0VmFsdWUodCxlKXtsZXR7Y2hpbGRyZW46cix0eXBlOm59PXRoaXM7c3dpdGNoKEFycmF5LmlzQXJyYXkoZSl8fGUuY29uc3RydWN0b3Ipe2Nhc2UhMDpyZXR1cm4gbi5jaGlsZHJlbi5mb3JFYWNoKChpLHMpPT5yW3NdLnNldCh0LGVbc10pKTtjYXNlIE1hcDpyZXR1cm4gbi5jaGlsZHJlbi5mb3JFYWNoKChpLHMpPT5yW3NdLnNldCh0LGUuZ2V0KGkubmFtZSkpKTtkZWZhdWx0OnJldHVybiBuLmNoaWxkcmVuLmZvckVhY2goKGkscyk9PnJbc10uc2V0KHQsZVtpLm5hbWVdKSl9fXNldFZhbGlkKHQsZSl7aWYoIXN1cGVyLnNldFZhbGlkKHQsZSkpdGhpcy5jaGlsZHJlbi5mb3JFYWNoKChyKT0+ci5zZXRWYWxpZCh0LGUpKTtyZXR1cm4gZX1hZGRDaGlsZCh0LGU9YCR7dGhpcy5udW1DaGlsZHJlbn1gKXtsZXQgcj10aGlzLmNoaWxkcmVuLnB1c2godCk7cmV0dXJuIHRoaXMudHlwZT1uZXcgRXQoWy4uLnRoaXMudHlwZS5jaGlsZHJlbixuZXcgVShlLHQudHlwZSwhMCldKSxyfX19KTt2YXIgRW8scGQsbWQseWQsX2Q7dmFyIGkwPW0oKCk9PntfZSgpO1NuKCk7RW89Y2xhc3MgRW8gZXh0ZW5kcyBxZXt9O0VvLnByb3RvdHlwZS5fc2V0VmFsdWU9TW07cGQ9Y2xhc3MgcGQgZXh0ZW5kcyBFb3t9O3BkLnByb3RvdHlwZS5fc2V0VmFsdWU9d2Y7bWQ9Y2xhc3MgbWQgZXh0ZW5kcyBFb3t9O21kLnByb3RvdHlwZS5fc2V0VmFsdWU9dmY7eWQ9Y2xhc3MgeWQgZXh0ZW5kcyBFb3t9O3lkLnByb3RvdHlwZS5fc2V0VmFsdWU9SWY7X2Q9Y2xhc3MgX2QgZXh0ZW5kcyBFb3t9O19kLnByb3RvdHlwZS5fc2V0VmFsdWU9QmZ9KTt2YXIgT28sZ2QsYmQsd2QsdmQ7dmFyIHMwPW0oKCk9PntfZSgpO1NuKCk7T289Y2xhc3MgT28gZXh0ZW5kcyBxZXt9O09vLnByb3RvdHlwZS5fc2V0VmFsdWU9TG07Z2Q9Y2xhc3MgZ2QgZXh0ZW5kcyBPb3t9O2dkLnByb3RvdHlwZS5fc2V0VmFsdWU9U2Y7YmQ9Y2xhc3MgYmQgZXh0ZW5kcyBPb3t9O2JkLnByb3RvdHlwZS5fc2V0VmFsdWU9QWY7d2Q9Y2xhc3Mgd2QgZXh0ZW5kcyBPb3t9O3dkLnByb3RvdHlwZS5fc2V0VmFsdWU9RGY7dmQ9Y2xhc3MgdmQgZXh0ZW5kcyBPb3t9O3ZkLnByb3RvdHlwZS5fc2V0VmFsdWU9eGZ9KTt2YXIgR2wsQnksU3k7dmFyIG8wPW0oKCk9PntVcigpO2FzKCk7X2UoKTtpZSgpO0dsPWNsYXNzIEdsIGV4dGVuZHMgdWV7Y29uc3RydWN0b3IodCl7c3VwZXIodCk7aWYodGhpcy5fdHlwZUlkcz1uZXcgQW8oSW50OEFycmF5LDAsMSksdHlwZW9mIHQudmFsdWVUb0NoaWxkVHlwZUlkPT09ImZ1bmN0aW9uIil0aGlzLl92YWx1ZVRvQ2hpbGRUeXBlSWQ9dC52YWx1ZVRvQ2hpbGRUeXBlSWR9Z2V0IHR5cGVJZFRvQ2hpbGRJbmRleCgpe3JldHVybiB0aGlzLnR5cGUudHlwZUlkVG9DaGlsZEluZGV4fWFwcGVuZCh0LGUpe3JldHVybiB0aGlzLnNldCh0aGlzLmxlbmd0aCx0LGUpfXNldCh0LGUscil7aWYocj09PXZvaWQgMClyPXRoaXMuX3ZhbHVlVG9DaGlsZFR5cGVJZCh0aGlzLGUsdCk7cmV0dXJuIHRoaXMuc2V0VmFsdWUodCxlLHIpLHRoaXN9c2V0VmFsdWUodCxlLHIpe3RoaXMuX3R5cGVJZHMuc2V0KHQscik7bGV0IG49dGhpcy50eXBlLnR5cGVJZFRvQ2hpbGRJbmRleFtyXSxpPXRoaXMuY2hpbGRyZW5bbl07aT09PW51bGx8fGk9PT12b2lkIDB8fGkuc2V0KHQsZSksdGhpcy5sZW5ndGg9TWF0aC5tYXgodCsxLHRoaXMubGVuZ3RoKX1hZGRDaGlsZCh0LGU9YCR7dGhpcy5jaGlsZHJlbi5sZW5ndGh9YCl7bGV0IHI9dGhpcy5jaGlsZHJlbi5wdXNoKHQpLHt0eXBlOntjaGlsZHJlbjpuLG1vZGU6aSx0eXBlSWRzOnN9fT10aGlzLG89Wy4uLm4sbmV3IFUoZSx0LnR5cGUpXTtyZXR1cm4gdGhpcy50eXBlPW5ldyBibihpLFsuLi5zLHJdLG8pLHJ9X3ZhbHVlVG9DaGlsZFR5cGVJZCh0LGUscil7dGhyb3cgRXJyb3IoIkNhbm5vdCBtYXAgVW5pb25CdWlsZGVyIHZhbHVlIHRvIGNoaWxkIHR5cGVJZC4gUGFzcyB0aGUgYGNoaWxkVHlwZUlkYCBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50IHRvIHVuaW9uQnVpbGRlci5hcHBlbmQoKSwgb3Igc3VwcGx5IGEgYHZhbHVlVG9DaGlsZFR5cGVJZGAgZnVuY3Rpb24gYXMgcGFydCBvZiB0aGUgVW5pb25CdWlsZGVyIGNvbnN0cnVjdG9yIG9wdGlvbnMuIil9fTtCeT1jbGFzcyBCeSBleHRlbmRzIEdse307U3k9Y2xhc3MgU3kgZXh0ZW5kcyBHbHtjb25zdHJ1Y3Rvcih0KXtzdXBlcih0KTt0aGlzLl9vZmZzZXRzPW5ldyBBbyhJbnQzMkFycmF5KX1zZXRWYWx1ZSh0LGUscil7bGV0IG49dGhpcy5fdHlwZUlkcy5zZXQodCxyKS5idWZmZXJbdF0saT10aGlzLmdldENoaWxkQXQodGhpcy50eXBlLnR5cGVJZFRvQ2hpbGRJbmRleFtuXSkscz10aGlzLl9vZmZzZXRzLnNldCh0LGkubGVuZ3RoKS5idWZmZXJbdF07aT09PW51bGx8fGk9PT12b2lkIDB8fGkuc2V0KHMsZSksdGhpcy5sZW5ndGg9TWF0aC5tYXgodCsxLHRoaXMubGVuZ3RoKX19fSk7dmFyIElkO3ZhciBhMD1tKCgpPT57dnMoKTtueSgpO2FzKCk7X2UoKTtJZD1jbGFzcyBJZCBleHRlbmRzIERue2NvbnN0cnVjdG9yKHQpe3N1cGVyKHQpO3RoaXMuX3ZhbHVlcz1uZXcgQW4oVWludDhBcnJheSl9Z2V0IGJ5dGVMZW5ndGgoKXtsZXQgdD10aGlzLl9wZW5kaW5nTGVuZ3RoK3RoaXMubGVuZ3RoKjQ7cmV0dXJuIHRoaXMuX29mZnNldHMmJih0Kz10aGlzLl9vZmZzZXRzLmJ5dGVMZW5ndGgpLHRoaXMuX3ZhbHVlcyYmKHQrPXRoaXMuX3ZhbHVlcy5ieXRlTGVuZ3RoKSx0aGlzLl9udWxscyYmKHQrPXRoaXMuX251bGxzLmJ5dGVMZW5ndGgpLHR9c2V0VmFsdWUodCxlKXtyZXR1cm4gc3VwZXIuc2V0VmFsdWUodCxtbihlKSl9X2ZsdXNoUGVuZGluZyh0LGUpe319O0lkLnByb3RvdHlwZS5fZmx1c2hQZW5kaW5nPVlsLnByb3RvdHlwZS5fZmx1c2hQZW5kaW5nfSk7dmFyIEJkO3ZhciBjMD1tKCgpPT57dnMoKTthcygpO19lKCk7aXkoKTtCZD1jbGFzcyBCZCBleHRlbmRzIERue2NvbnN0cnVjdG9yKHQpe3N1cGVyKHQpO3RoaXMuX3ZhbHVlcz1uZXcgQW4oVWludDhBcnJheSl9Z2V0IGJ5dGVMZW5ndGgoKXtsZXQgdD10aGlzLl9wZW5kaW5nTGVuZ3RoK3RoaXMubGVuZ3RoKjQ7cmV0dXJuIHRoaXMuX29mZnNldHMmJih0Kz10aGlzLl9vZmZzZXRzLmJ5dGVMZW5ndGgpLHRoaXMuX3ZhbHVlcyYmKHQrPXRoaXMuX3ZhbHVlcy5ieXRlTGVuZ3RoKSx0aGlzLl9udWxscyYmKHQrPXRoaXMuX251bGxzLmJ5dGVMZW5ndGgpLHR9c2V0VmFsdWUodCxlKXtyZXR1cm4gc3VwZXIuc2V0VmFsdWUodCxtbihlKSl9X2ZsdXNoUGVuZGluZyh0LGUpe319O0JkLnByb3RvdHlwZS5fZmx1c2hQZW5kaW5nPUtsLnByb3RvdHlwZS5fZmx1c2hQZW5kaW5nfSk7dmFyIEpsO3ZhciBBeT1tKCgpPT57aWUoKTtfZSgpO2FzKCk7amUoKTtYbigpO0psPWNsYXNzIEpsIGV4dGVuZHMgdWV7Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5fdmFyaWFkaWNCdWZmZXJzPVtdLHRoaXMuX2N1cnJlbnRCdWZmZXI9bnVsbCx0aGlzLl9jdXJyZW50QnVmZmVySW5kZXg9MCx0aGlzLl9jdXJyZW50QnVmZmVyT2Zmc2V0PTAsdGhpcy5fYnVmZmVyU2l6ZT0zMzU1NDQzMix0aGlzLl92aWV3cz1uZXcgQW4oVWludDhBcnJheSl9Z2V0IGJ5dGVMZW5ndGgoKXtsZXQgdD0wO3RoaXMuX3ZpZXdzJiYodCs9dGhpcy5fdmlld3MuYnl0ZUxlbmd0aCksdGhpcy5fbnVsbHMmJih0Kz10aGlzLl9udWxscy5ieXRlTGVuZ3RoKTtmb3IobGV0IGUgb2YgdGhpcy5fdmFyaWFkaWNCdWZmZXJzKXQrPWUuYnl0ZUxlbmd0aDtyZXR1cm4gdGhpcy5fY3VycmVudEJ1ZmZlciYmKHQrPXRoaXMuX2N1cnJlbnRCdWZmZXIuYnl0ZUxlbmd0aCksdH1zZXRWYWx1ZSh0LGUpe3JldHVybiB0aGlzLndyaXRlQmluYXJ5VmFsdWUodCx0aGlzLmVuY29kZVZhbHVlKGUpKX13cml0ZUJpbmFyeVZhbHVlKHQsZSl7bGV0IHI9ZS5sZW5ndGgsbj0odCsxKSpfdC5FTEVNRU5UX1dJRFRILGk9dGhpcy5fdmlld3MubGVuZ3RoO2lmKG4+aSl0aGlzLl92aWV3cy5yZXNlcnZlKG4taSk7bGV0IHM9dGhpcy5fdmlld3MuYnVmZmVyLG89dCpfdC5FTEVNRU5UX1dJRFRILGE9bmV3IERhdGFWaWV3KHMuYnVmZmVyLHMuYnl0ZU9mZnNldCtvLF90LkVMRU1FTlRfV0lEVEgpO2lmKGEuc2V0SW50MzIoX3QuTEVOR1RIX09GRlNFVCxyLCEwKSxyPD1fdC5JTkxJTkVfQ0FQQUNJVFkpe3Muc2V0KGUsbytfdC5JTkxJTkVfT0ZGU0VUKTtmb3IobGV0IGw9cjtsPF90LklOTElORV9DQVBBQ0lUWTtsKyspc1tvK190LklOTElORV9PRkZTRVQrbF09MH1lbHNle2xldCBsPW5ldyBEYXRhVmlldyhlLmJ1ZmZlcixlLmJ5dGVPZmZzZXQsTWF0aC5taW4oNCxyKSk7aWYoYS5zZXRVaW50MzIoX3QuSU5MSU5FX09GRlNFVCxsLmdldFVpbnQzMigwLCEwKSwhMCksIXRoaXMuX2N1cnJlbnRCdWZmZXJ8fHRoaXMuX2N1cnJlbnRCdWZmZXJPZmZzZXQrcj50aGlzLl9idWZmZXJTaXplKXtpZih0aGlzLl9jdXJyZW50QnVmZmVyKXRoaXMuX3ZhcmlhZGljQnVmZmVycy5wdXNoKHRoaXMuX2N1cnJlbnRCdWZmZXIuYnVmZmVyLnNsaWNlKDAsdGhpcy5fY3VycmVudEJ1ZmZlck9mZnNldCkpO3RoaXMuX2N1cnJlbnRCdWZmZXI9bmV3IEFuKFVpbnQ4QXJyYXkpLHRoaXMuX2N1cnJlbnRCdWZmZXJJbmRleD10aGlzLl92YXJpYWRpY0J1ZmZlcnMubGVuZ3RoLHRoaXMuX2N1cnJlbnRCdWZmZXJPZmZzZXQ9MH10aGlzLl9jdXJyZW50QnVmZmVyLnJlc2VydmUocikuYnVmZmVyLnNldChlLHRoaXMuX2N1cnJlbnRCdWZmZXJPZmZzZXQpLGEuc2V0SW50MzIoX3QuQlVGRkVSX0lOREVYX09GRlNFVCx0aGlzLl9jdXJyZW50QnVmZmVySW5kZXgsITApLGEuc2V0SW50MzIoX3QuQlVGRkVSX09GRlNFVF9PRkZTRVQsdGhpcy5fY3VycmVudEJ1ZmZlck9mZnNldCwhMCksdGhpcy5fY3VycmVudEJ1ZmZlck9mZnNldCs9cn1yZXR1cm4gdGhpc31lbmNvZGVWYWx1ZSh0KXtyZXR1cm4gQyh0KX1zZXRWYWxpZCh0LGUpe2xldCByPSh0KzEpKl90LkVMRU1FTlRfV0lEVEgsbj10aGlzLl92aWV3cy5sZW5ndGg7aWYocj5uKXRoaXMuX3ZpZXdzLnJlc2VydmUoci1uKTtsZXQgaT1zdXBlci5zZXRWYWxpZCh0LGUpO2lmKCFpKXtsZXQgcz10aGlzLl92aWV3cy5idWZmZXIsbz10Kl90LkVMRU1FTlRfV0lEVEg7Zm9yKGxldCBhPTA7YTxfdC5FTEVNRU5UX1dJRFRIO2ErKylzW28rYV09MH1yZXR1cm4gaX1jbGVhcigpe3JldHVybiB0aGlzLl92YXJpYWRpY0J1ZmZlcnM9W10sdGhpcy5fY3VycmVudEJ1ZmZlcj1udWxsLHRoaXMuX2N1cnJlbnRCdWZmZXJJbmRleD0wLHRoaXMuX2N1cnJlbnRCdWZmZXJPZmZzZXQ9MCx0aGlzLl92aWV3cy5jbGVhcigpLHN1cGVyLmNsZWFyKCl9Zmx1c2goKXtsZXR7dHlwZTp0LGxlbmd0aDplLG51bGxDb3VudDpyLF92aWV3czpuLF9udWxsczppfT10aGlzO2lmKHRoaXMuX2N1cnJlbnRCdWZmZXImJnRoaXMuX2N1cnJlbnRCdWZmZXJPZmZzZXQ+MCl0aGlzLl92YXJpYWRpY0J1ZmZlcnMucHVzaCh0aGlzLl9jdXJyZW50QnVmZmVyLmJ1ZmZlci5zbGljZSgwLHRoaXMuX2N1cnJlbnRCdWZmZXJPZmZzZXQpKSx0aGlzLl9jdXJyZW50QnVmZmVyPW51bGwsdGhpcy5fY3VycmVudEJ1ZmZlck9mZnNldD0wO2xldCBzPW4uZmx1c2goZSpfdC5FTEVNRU5UX1dJRFRIKSxvPXI+MD9pLmZsdXNoKGUpOnZvaWQgMCxhPXRoaXMuX3ZhcmlhZGljQnVmZmVycy5zbGljZSgpO3JldHVybiB0aGlzLl92YXJpYWRpY0J1ZmZlcnM9W10sdGhpcy5fY3VycmVudEJ1ZmZlckluZGV4PTAsdGhpcy5jbGVhcigpLFMoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cixudWxsQml0bWFwOm8sWyJ2aWV3cyJdOnMsWyJ2YXJpYWRpY0J1ZmZlcnMiXTphfSl9ZmluaXNoKCl7cmV0dXJuIHRoaXMuZmluaXNoZWQ9ITAsdGhpc319fSk7dmFyIER5O3ZhciBsMD1tKCgpPT57QXkoKTt2cygpO0R5PWNsYXNzIER5IGV4dGVuZHMgSmx7Y29uc3RydWN0b3IodCl7c3VwZXIodCl9c2V0VmFsdWUodCxlKXtyZXR1cm4gdGhpcy53cml0ZUJpbmFyeVZhbHVlKHQsbW4oZSkpfX19KTt2YXIgdTAsZjA7dmFyIGQwPW0oKCk9PntVaSgpO255KCk7aXkoKTtxdigpO1d2KCk7SHYoKTtZdigpO0t2KCk7R3YoKTtKdigpO1h2KCk7WnYoKTtRdigpO3QwKCk7ZTAoKTtyMCgpO24wKCk7aTAoKTtzMCgpO28wKCk7YTAoKTtjMCgpO0F5KCk7bDAoKTt1MD1jbGFzcyB1MCBleHRlbmRzIGV0e3Zpc2l0TnVsbCgpe3JldHVybiB2eX12aXNpdEJvb2woKXtyZXR1cm4gc3l9dmlzaXRJbnQoKXtyZXR1cm4gUGl9dmlzaXRJbnQ4KCl7cmV0dXJuIGZ5fXZpc2l0SW50MTYoKXtyZXR1cm4gZHl9dmlzaXRJbnQzMigpe3JldHVybiBoeX12aXNpdEludDY0KCl7cmV0dXJuIHB5fXZpc2l0VWludDgoKXtyZXR1cm4gbXl9dmlzaXRVaW50MTYoKXtyZXR1cm4geXl9dmlzaXRVaW50MzIoKXtyZXR1cm4gX3l9dmlzaXRVaW50NjQoKXtyZXR1cm4gZ3l9dmlzaXRGbG9hdCgpe3JldHVybiBFY312aXNpdEZsb2F0MTYoKXtyZXR1cm4gY3l9dmlzaXRGbG9hdDMyKCl7cmV0dXJuIGx5fXZpc2l0RmxvYXQ2NCgpe3JldHVybiB1eX12aXNpdFV0ZjgoKXtyZXR1cm4gSWR9dmlzaXRMYXJnZVV0ZjgoKXtyZXR1cm4gQmR9dmlzaXRCaW5hcnkoKXtyZXR1cm4gWWx9dmlzaXRMYXJnZUJpbmFyeSgpe3JldHVybiBLbH12aXNpdEZpeGVkU2l6ZUJpbmFyeSgpe3JldHVybiBvZH12aXNpdERhdGUoKXtyZXR1cm4gVGN9dmlzaXREYXRlRGF5KCl7cmV0dXJuIHJkfXZpc2l0RGF0ZU1pbGxpc2Vjb25kKCl7cmV0dXJuIG5kfXZpc2l0VGltZXN0YW1wKCl7cmV0dXJuIEVvfXZpc2l0VGltZXN0YW1wU2Vjb25kKCl7cmV0dXJuIHBkfXZpc2l0VGltZXN0YW1wTWlsbGlzZWNvbmQoKXtyZXR1cm4gbWR9dmlzaXRUaW1lc3RhbXBNaWNyb3NlY29uZCgpe3JldHVybiB5ZH12aXNpdFRpbWVzdGFtcE5hbm9zZWNvbmQoKXtyZXR1cm4gX2R9dmlzaXRUaW1lKCl7cmV0dXJuIE9vfXZpc2l0VGltZVNlY29uZCgpe3JldHVybiBnZH12aXNpdFRpbWVNaWxsaXNlY29uZCgpe3JldHVybiBiZH12aXNpdFRpbWVNaWNyb3NlY29uZCgpe3JldHVybiB3ZH12aXNpdFRpbWVOYW5vc2Vjb25kKCl7cmV0dXJuIHZkfXZpc2l0RGVjaW1hbCgpe3JldHVybiBpZH12aXNpdExpc3QoKXtyZXR1cm4gYnl9dmlzaXRTdHJ1Y3QoKXtyZXR1cm4gSXl9dmlzaXRVbmlvbigpe3JldHVybiBHbH12aXNpdERlbnNlVW5pb24oKXtyZXR1cm4gU3l9dmlzaXRTcGFyc2VVbmlvbigpe3JldHVybiBCeX12aXNpdERpY3Rpb25hcnkoKXtyZXR1cm4gb3l9dmlzaXRJbnRlcnZhbCgpe3JldHVybiBiYX12aXNpdEludGVydmFsRGF5VGltZSgpe3JldHVybiBhZH12aXNpdEludGVydmFsWWVhck1vbnRoKCl7cmV0dXJuIGNkfXZpc2l0SW50ZXJ2YWxNb250aERheU5hbm8oKXtyZXR1cm4gbGR9dmlzaXREdXJhdGlvbigpe3JldHVybiBUb312aXNpdER1cmF0aW9uU2Vjb25kKCl7cmV0dXJuIHVkfXZpc2l0RHVyYXRpb25NaWxsaXNlY29uZCgpe3JldHVybiBmZH12aXNpdER1cmF0aW9uTWljcm9zZWNvbmQoKXtyZXR1cm4gZGR9dmlzaXREdXJhdGlvbk5hbm9zZWNvbmQoKXtyZXR1cm4gaGR9dmlzaXRGaXhlZFNpemVMaXN0KCl7cmV0dXJuIGF5fXZpc2l0TWFwKCl7cmV0dXJuIHd5fXZpc2l0QmluYXJ5Vmlldygpe3JldHVybiBKbH12aXNpdFV0ZjhWaWV3KCl7cmV0dXJuIER5fX07ZjA9bmV3IHUwfSk7ZnVuY3Rpb24gQ3IodCxlKXtyZXR1cm4gZSBpbnN0YW5jZW9mIHQuY29uc3RydWN0b3J9ZnVuY3Rpb24gVHModCxlKXtyZXR1cm4gdD09PWV8fENyKHQsZSl9ZnVuY3Rpb24gRXModCxlKXtyZXR1cm4gdD09PWV8fENyKHQsZSkmJnQuYml0V2lkdGg9PT1lLmJpdFdpZHRoJiZ0LmlzU2lnbmVkPT09ZS5pc1NpZ25lZH1mdW5jdGlvbiBTZCh0LGUpe3JldHVybiB0PT09ZXx8Q3IodCxlKSYmdC5wcmVjaXNpb249PT1lLnByZWNpc2lvbn1mdW5jdGlvbiB0RSh0LGUpe3JldHVybiB0PT09ZXx8Q3IodCxlKSYmdC5ieXRlV2lkdGg9PT1lLmJ5dGVXaWR0aH1mdW5jdGlvbiB4eSh0LGUpe3JldHVybiB0PT09ZXx8Q3IodCxlKSYmdC51bml0PT09ZS51bml0fWZ1bmN0aW9uIFhsKHQsZSl7cmV0dXJuIHQ9PT1lfHxDcih0LGUpJiZ0LnVuaXQ9PT1lLnVuaXQmJnQudGltZXpvbmU9PT1lLnRpbWV6b25lfWZ1bmN0aW9uIFpsKHQsZSl7cmV0dXJuIHQ9PT1lfHxDcih0LGUpJiZ0LnVuaXQ9PT1lLnVuaXQmJnQuYml0V2lkdGg9PT1lLmJpdFdpZHRofWZ1bmN0aW9uIGVFKHQsZSl7cmV0dXJuIHQ9PT1lfHxDcih0LGUpJiZ0LmNoaWxkcmVuLmxlbmd0aD09PWUuY2hpbGRyZW4ubGVuZ3RoJiZjcy5jb21wYXJlTWFueUZpZWxkcyh0LmNoaWxkcmVuLGUuY2hpbGRyZW4pfWZ1bmN0aW9uIHJFKHQsZSl7cmV0dXJuIHQ9PT1lfHxDcih0LGUpJiZ0LmNoaWxkcmVuLmxlbmd0aD09PWUuY2hpbGRyZW4ubGVuZ3RoJiZjcy5jb21wYXJlTWFueUZpZWxkcyh0LmNoaWxkcmVuLGUuY2hpbGRyZW4pfWZ1bmN0aW9uIFR5KHQsZSl7cmV0dXJuIHQ9PT1lfHxDcih0LGUpJiZ0Lm1vZGU9PT1lLm1vZGUmJnQudHlwZUlkcy5ldmVyeSgocixuKT0+cj09PWUudHlwZUlkc1tuXSkmJmNzLmNvbXBhcmVNYW55RmllbGRzKHQuY2hpbGRyZW4sZS5jaGlsZHJlbil9ZnVuY3Rpb24gbkUodCxlKXtyZXR1cm4gdD09PWV8fENyKHQsZSkmJnQuaWQ9PT1lLmlkJiZ0LmlzT3JkZXJlZD09PWUuaXNPcmRlcmVkJiZjcy52aXNpdCh0LmluZGljZXMsZS5pbmRpY2VzKSYmY3MudmlzaXQodC5kaWN0aW9uYXJ5LGUuZGljdGlvbmFyeSl9ZnVuY3Rpb24gQWQodCxlKXtyZXR1cm4gdD09PWV8fENyKHQsZSkmJnQudW5pdD09PWUudW5pdH1mdW5jdGlvbiBRbCh0LGUpe3JldHVybiB0PT09ZXx8Q3IodCxlKSYmdC51bml0PT09ZS51bml0fWZ1bmN0aW9uIGlFKHQsZSl7cmV0dXJuIHQ9PT1lfHxDcih0LGUpJiZ0Lmxpc3RTaXplPT09ZS5saXN0U2l6ZSYmdC5jaGlsZHJlbi5sZW5ndGg9PT1lLmNoaWxkcmVuLmxlbmd0aCYmY3MuY29tcGFyZU1hbnlGaWVsZHModC5jaGlsZHJlbixlLmNoaWxkcmVuKX1mdW5jdGlvbiBzRSh0LGUpe3JldHVybiB0PT09ZXx8Q3IodCxlKSYmdC5rZXlzU29ydGVkPT09ZS5rZXlzU29ydGVkJiZ0LmNoaWxkcmVuLmxlbmd0aD09PWUuY2hpbGRyZW4ubGVuZ3RoJiZjcy5jb21wYXJlTWFueUZpZWxkcyh0LmNoaWxkcmVuLGUuY2hpbGRyZW4pfWZ1bmN0aW9uIHdhKHQsZSl7cmV0dXJuIGNzLmNvbXBhcmVTY2hlbWFzKHQsZSl9ZnVuY3Rpb24gaDAodCxlKXtyZXR1cm4gY3MuY29tcGFyZUZpZWxkcyh0LGUpfWZ1bmN0aW9uIERkKHQsZSl7cmV0dXJuIGNzLnZpc2l0KHQsZSl9dmFyIFksY3M7dmFyIHR1PW0oKCk9PntVaSgpO1k9Y2xhc3MgWSBleHRlbmRzIGV0e2NvbXBhcmVTY2hlbWFzKHQsZSl7cmV0dXJuIHQ9PT1lfHxlIGluc3RhbmNlb2YgdC5jb25zdHJ1Y3RvciYmdGhpcy5jb21wYXJlTWFueUZpZWxkcyh0LmZpZWxkcyxlLmZpZWxkcyl9Y29tcGFyZU1hbnlGaWVsZHModCxlKXtyZXR1cm4gdD09PWV8fEFycmF5LmlzQXJyYXkodCkmJkFycmF5LmlzQXJyYXkoZSkmJnQubGVuZ3RoPT09ZS5sZW5ndGgmJnQuZXZlcnkoKHIsbik9PnRoaXMuY29tcGFyZUZpZWxkcyhyLGVbbl0pKX1jb21wYXJlRmllbGRzKHQsZSl7cmV0dXJuIHQ9PT1lfHxlIGluc3RhbmNlb2YgdC5jb25zdHJ1Y3RvciYmdC5uYW1lPT09ZS5uYW1lJiZ0Lm51bGxhYmxlPT09ZS5udWxsYWJsZSYmdGhpcy52aXNpdCh0LnR5cGUsZS50eXBlKX19O1kucHJvdG90eXBlLnZpc2l0TnVsbD1UcztZLnByb3RvdHlwZS52aXNpdEJvb2w9VHM7WS5wcm90b3R5cGUudmlzaXRJbnQ9RXM7WS5wcm90b3R5cGUudmlzaXRJbnQ4PUVzO1kucHJvdG90eXBlLnZpc2l0SW50MTY9RXM7WS5wcm90b3R5cGUudmlzaXRJbnQzMj1FcztZLnByb3RvdHlwZS52aXNpdEludDY0PUVzO1kucHJvdG90eXBlLnZpc2l0VWludDg9RXM7WS5wcm90b3R5cGUudmlzaXRVaW50MTY9RXM7WS5wcm90b3R5cGUudmlzaXRVaW50MzI9RXM7WS5wcm90b3R5cGUudmlzaXRVaW50NjQ9RXM7WS5wcm90b3R5cGUudmlzaXRGbG9hdD1TZDtZLnByb3RvdHlwZS52aXNpdEZsb2F0MTY9U2Q7WS5wcm90b3R5cGUudmlzaXRGbG9hdDMyPVNkO1kucHJvdG90eXBlLnZpc2l0RmxvYXQ2ND1TZDtZLnByb3RvdHlwZS52aXNpdFV0Zjg9VHM7WS5wcm90b3R5cGUudmlzaXRMYXJnZVV0Zjg9VHM7WS5wcm90b3R5cGUudmlzaXRVdGY4Vmlldz1UcztZLnByb3RvdHlwZS52aXNpdEJpbmFyeT1UcztZLnByb3RvdHlwZS52aXNpdExhcmdlQmluYXJ5PVRzO1kucHJvdG90eXBlLnZpc2l0QmluYXJ5Vmlldz1UcztZLnByb3RvdHlwZS52aXNpdEZpeGVkU2l6ZUJpbmFyeT10RTtZLnByb3RvdHlwZS52aXNpdERhdGU9eHk7WS5wcm90b3R5cGUudmlzaXREYXRlRGF5PXh5O1kucHJvdG90eXBlLnZpc2l0RGF0ZU1pbGxpc2Vjb25kPXh5O1kucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wPVhsO1kucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wU2Vjb25kPVhsO1kucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wTWlsbGlzZWNvbmQ9WGw7WS5wcm90b3R5cGUudmlzaXRUaW1lc3RhbXBNaWNyb3NlY29uZD1YbDtZLnByb3RvdHlwZS52aXNpdFRpbWVzdGFtcE5hbm9zZWNvbmQ9WGw7WS5wcm90b3R5cGUudmlzaXRUaW1lPVpsO1kucHJvdG90eXBlLnZpc2l0VGltZVNlY29uZD1abDtZLnByb3RvdHlwZS52aXNpdFRpbWVNaWxsaXNlY29uZD1abDtZLnByb3RvdHlwZS52aXNpdFRpbWVNaWNyb3NlY29uZD1abDtZLnByb3RvdHlwZS52aXNpdFRpbWVOYW5vc2Vjb25kPVpsO1kucHJvdG90eXBlLnZpc2l0RGVjaW1hbD1UcztZLnByb3RvdHlwZS52aXNpdExpc3Q9ZUU7WS5wcm90b3R5cGUudmlzaXRTdHJ1Y3Q9ckU7WS5wcm90b3R5cGUudmlzaXRVbmlvbj1UeTtZLnByb3RvdHlwZS52aXNpdERlbnNlVW5pb249VHk7WS5wcm90b3R5cGUudmlzaXRTcGFyc2VVbmlvbj1UeTtZLnByb3RvdHlwZS52aXNpdERpY3Rpb25hcnk9bkU7WS5wcm90b3R5cGUudmlzaXRJbnRlcnZhbD1BZDtZLnByb3RvdHlwZS52aXNpdEludGVydmFsRGF5VGltZT1BZDtZLnByb3RvdHlwZS52aXNpdEludGVydmFsWWVhck1vbnRoPUFkO1kucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWxNb250aERheU5hbm89QWQ7WS5wcm90b3R5cGUudmlzaXREdXJhdGlvbj1RbDtZLnByb3RvdHlwZS52aXNpdER1cmF0aW9uU2Vjb25kPVFsO1kucHJvdG90eXBlLnZpc2l0RHVyYXRpb25NaWxsaXNlY29uZD1RbDtZLnByb3RvdHlwZS52aXNpdER1cmF0aW9uTWljcm9zZWNvbmQ9UWw7WS5wcm90b3R5cGUudmlzaXREdXJhdGlvbk5hbm9zZWNvbmQ9UWw7WS5wcm90b3R5cGUudmlzaXRGaXhlZFNpemVMaXN0PWlFO1kucHJvdG90eXBlLnZpc2l0TWFwPXNFO2NzPW5ldyBZfSk7ZnVuY3Rpb24geHModCl7bGV0IGU9dC50eXBlLHI9bmV3KGYwLmdldFZpc2l0Rm4oZSkoKSkodCk7aWYoZS5jaGlsZHJlbiYmZS5jaGlsZHJlbi5sZW5ndGg+MCl7bGV0IG49dC5jaGlsZHJlbnx8W10saT17bnVsbFZhbHVlczp0Lm51bGxWYWx1ZXN9LHM9QXJyYXkuaXNBcnJheShuKT8obyxhKT0+blthXXx8aTooe25hbWU6b30pPT5uW29dfHxpO2ZvcihsZXRbbyxhXW9mIGUuY2hpbGRyZW4uZW50cmllcygpKXtsZXR7dHlwZTpsfT1hLHU9cyhhLG8pO3IuY2hpbGRyZW4ucHVzaCh4cyhPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sdSkse3R5cGU6bH0pKSl9fXJldHVybiByfWZ1bmN0aW9uIE9jKHQsZSl7aWYodCBpbnN0YW5jZW9mIHB0fHx0IGluc3RhbmNlb2YgTnx8dC50eXBlIGluc3RhbmNlb2YgQilyZXR1cm4gbWEodCk7aWYoQXJyYXlCdWZmZXIuaXNWaWV3KHQpJiYhZSlyZXR1cm4gbWEodCk7aWYoQXJyYXlCdWZmZXIuaXNWaWV3KHQpJiZlKXtsZXQgcz10IGluc3RhbmNlb2YgQmlnSW50NjRBcnJheXx8dCBpbnN0YW5jZW9mIEJpZ1VpbnQ2NEFycmF5LG89ZS5BcnJheVR5cGU9PT1CaWdJbnQ2NEFycmF5fHxlLkFycmF5VHlwZT09PUJpZ1VpbnQ2NEFycmF5O2lmKHMmJiFvKXRocm93IFR5cGVFcnJvcihgQ2Fubm90IGNvbnZlcnQgQmlnSW50IGlucHV0IHRvICR7ZX0uIEJpZ0ludCBhcnJheXMgY2FuIG9ubHkgdGFyZ2V0IEJpZ0ludC1iYXNlZCB0eXBlcyAoZS5nLiBJbnQ2NCwgVWludDY0KS5gKTtpZighcyYmbyl0aHJvdyBUeXBlRXJyb3IoYENhbm5vdCBjb252ZXJ0IG5vbi1CaWdJbnQgaW5wdXQgdG8gJHtlfS4gJHtlfSByZXF1aXJlcyBCaWdJbnQgdmFsdWVzLmApO2lmKEIuaXNJbnQoZSl8fEIuaXNGbG9hdChlKSl7bGV0IGE9dC5jb25zdHJ1Y3Rvcj09PWUuQXJyYXlUeXBlP3Q6bmV3IGUuQXJyYXlUeXBlKHQpO3JldHVybiBtYSh7dHlwZTplLGRhdGE6YSxvZmZzZXQ6MCxsZW5ndGg6YS5sZW5ndGgsbnVsbENvdW50OjB9KX19bGV0IHI9e3R5cGU6ZSE9PW51bGwmJmUhPT12b2lkIDA/ZTp4ZCh0KSxudWxsVmFsdWVzOltudWxsXX0sbj1bLi4uRXkocikodCldLGk9bi5sZW5ndGg9PT0xP25bMF06bi5yZWR1Y2UoKHMsbyk9PnMuY29uY2F0KG8pKTtpZihCLmlzRGljdGlvbmFyeShpLnR5cGUpKXJldHVybiBpLm1lbW9pemUoKTtyZXR1cm4gaX1mdW5jdGlvbiB4ZCh0KXtpZih0Lmxlbmd0aD09PTApcmV0dXJuIG5ldyB3ZTtsZXQgZT0wLHI9MCxuPTAsaT0wLHM9MCxvPTAsYT0wLGw9MDtmb3IobGV0IHUgb2YgdCl7aWYodT09bnVsbCl7KytlO2NvbnRpbnVlfXN3aXRjaCh0eXBlb2YgdSl7Y2FzZSJiaWdpbnQiOisrbztjb250aW51ZTtjYXNlImJvb2xlYW4iOisrYTtjb250aW51ZTtjYXNlIm51bWJlciI6KytpO2NvbnRpbnVlO2Nhc2Uic3RyaW5nIjorK3M7Y29udGludWU7Y2FzZSJvYmplY3QiOmlmKEFycmF5LmlzQXJyYXkodSkpKytyO2Vsc2UgaWYoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHUpPT09IltvYmplY3QgRGF0ZV0iKSsrbDtlbHNlKytuO2NvbnRpbnVlfXRocm93IFR5cGVFcnJvcigiVW5hYmxlIHRvIGluZmVyIFZlY3RvciB0eXBlIGZyb20gaW5wdXQgdmFsdWVzLCBleHBsaWNpdCB0eXBlIGRlY2xhcmF0aW9uIGV4cGVjdGVkLiIpfWlmKGkrZT09PXQubGVuZ3RoKXJldHVybiBuZXcgb3M7ZWxzZSBpZihzK2U9PT10Lmxlbmd0aClyZXR1cm4gbmV3IGZyKG5ldyBJcixuZXcgQnIpO2Vsc2UgaWYobytlPT09dC5sZW5ndGgpcmV0dXJuIG5ldyBJbjtlbHNlIGlmKGErZT09PXQubGVuZ3RoKXJldHVybiBuZXcgVWU7ZWxzZSBpZihsK2U9PT10Lmxlbmd0aClyZXR1cm4gbmV3IFVsO2Vsc2UgaWYocitlPT09dC5sZW5ndGgpe2xldCB1PXQsZj14ZCh1W3UuZmluZEluZGV4KChwKT0+cCE9bnVsbCldKTtpZih1LmV2ZXJ5KChwKT0+cD09bnVsbHx8RGQoZix4ZChwKSkpKXJldHVybiBuZXcgTHIobmV3IFUoIiIsZiwhMCkpfWVsc2UgaWYobitlPT09dC5sZW5ndGgpe2xldCB1PW5ldyBNYXA7Zm9yKGxldCBmIG9mIHQpZm9yKGxldCBwIG9mIE9iamVjdC5rZXlzKGYpKWlmKCF1LmhhcyhwKSYmZltwXSE9bnVsbCl1LnNldChwLG5ldyBVKHAseGQoW2ZbcF1dKSwhMCkpO3JldHVybiBuZXcgRXQoWy4uLnUudmFsdWVzKCldKX10aHJvdyBUeXBlRXJyb3IoIlVuYWJsZSB0byBpbmZlciBWZWN0b3IgdHlwZSBmcm9tIGlucHV0IHZhbHVlcywgZXhwbGljaXQgdHlwZSBkZWNsYXJhdGlvbiBleHBlY3RlZC4iKX1mdW5jdGlvbiBFeSh0KXtsZXR7WyJxdWV1ZWluZ1N0cmF0ZWd5Il06ZT0iY291bnQifT10LHtbImhpZ2hXYXRlck1hcmsiXTpyPWUhPT0iYnl0ZXMiP051bWJlci5QT1NJVElWRV9JTkZJTklUWTpNYXRoLnBvdygyLDE0KX09dCxuPWUhPT0iYnl0ZXMiPyJsZW5ndGgiOiJieXRlTGVuZ3RoIjtyZXR1cm4gZnVuY3Rpb24qKGkpe2xldCBzPTAsbz14cyh0KTtmb3IobGV0IGEgb2YgaSlpZihvLmFwcGVuZChhKVtuXT49cikrK3MmJih5aWVsZCBvLnRvVmVjdG9yKCkpO2lmKG8uZmluaXNoKCkubGVuZ3RoPjB8fHM9PT0wKXlpZWxkIG8udG9WZWN0b3IoKX19dmFyIHNkPW0oKCk9PntVcigpO2llKCk7WG4oKTtRcigpO2QwKCk7dHUoKX0pO2Z1bmN0aW9uIFRkKHQsZSl7cmV0dXJuIG9FKHQsZS5tYXAoKHIpPT5yLmRhdGEuY29uY2F0KCkpKX1mdW5jdGlvbiBvRSh0LGUpe2xldCByPVsuLi50LmZpZWxkc10sbj1bXSxpPXtudW1CYXRjaGVzOmUucmVkdWNlKChwLGcpPT5NYXRoLm1heChwLGcubGVuZ3RoKSwwKX0scz0wLG89MCxhPS0xLGw9ZS5sZW5ndGgsdSxmPVtdO3doaWxlKGkubnVtQmF0Y2hlcy0tID4wKXtmb3Iobz1OdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFksYT0tMTsrK2E8bDspZlthXT11PWVbYV0uc2hpZnQoKSxvPU1hdGgubWluKG8sdT91Lmxlbmd0aDpvKTtpZihOdW1iZXIuaXNGaW5pdGUobykpe2lmKGY9YUUocixvLGYsZSxpKSxvPjApbltzKytdPVMoe3R5cGU6bmV3IEV0KHIpLGxlbmd0aDpvLG51bGxDb3VudDowLGNoaWxkcmVuOmYuc2xpY2UoKX0pfX1yZXR1cm5bdD10LmFzc2lnbihyKSxuLm1hcCgocCk9Pm5ldyBBdCh0LHApKV19ZnVuY3Rpb24gYUUodCxlLHIsbixpKXt2YXIgcztsZXQgbz0oZSs2MyYtNjQpPj4zO2ZvcihsZXQgYT0tMSxsPW4ubGVuZ3RoOysrYTxsOyl7bGV0IHU9clthXSxmPXU9PT1udWxsfHx1PT09dm9pZCAwP3ZvaWQgMDp1Lmxlbmd0aDtpZihmPj1lKWlmKGY9PT1lKXJbYV09dTtlbHNlIHJbYV09dS5zbGljZSgwLGUpLGkubnVtQmF0Y2hlcz1NYXRoLm1heChpLm51bUJhdGNoZXMsblthXS51bnNoaWZ0KHUuc2xpY2UoZSxmLWUpKSk7ZWxzZXtsZXQgcD10W2FdO3RbYV09cC5jbG9uZSh7bnVsbGFibGU6ITB9KSxyW2FdPShzPXU9PT1udWxsfHx1PT09dm9pZCAwP3ZvaWQgMDp1Ll9jaGFuZ2VMZW5ndGhBbmRCYWNrZmlsbE51bGxCaXRtYXAoZSkpIT09bnVsbCYmcyE9PXZvaWQgMD9zOlMoe3R5cGU6cC50eXBlLGxlbmd0aDplLG51bGxDb3VudDplLG51bGxCaXRtYXA6bmV3IFVpbnQ4QXJyYXkobyl9KX19cmV0dXJuIHJ9dmFyIHAwPW0oKCk9PntYbigpO2llKCk7Tm8oKX0pO3ZhciBtMCx5MCxUZTt2YXIgRWQ9bSgoKT0+e0xlKCk7WG4oKTtRcigpO1VyKCk7aWUoKTt0dSgpO3AwKCk7V2YoKTt1YSgpO1NuKCk7SGYoKTtZZigpO2djKCk7Tm8oKTt5MD1TeW1ib2wuZm9yKCJhcGFjaGUtYXJyb3cvVGFibGUiKTtUZT1jbGFzcyBUZXtzdGF0aWMgaXNUYWJsZSh0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnRbeTBdKT09PSEwfWNvbnN0cnVjdG9yKC4uLnQpe3ZhciBlLHI7aWYodC5sZW5ndGg9PT0wKXJldHVybiB0aGlzLmJhdGNoZXM9W10sdGhpcy5zY2hlbWE9bmV3IGx0KFtdKSx0aGlzLl9vZmZzZXRzPVswXSx0aGlzO2xldCBuLGk7aWYodFswXWluc3RhbmNlb2YgbHQpbj10LnNoaWZ0KCk7aWYodC5hdCgtMSlpbnN0YW5jZW9mIFVpbnQzMkFycmF5KWk9dC5wb3AoKTtsZXQgcz0oYSk9PntpZihhKXtpZihhIGluc3RhbmNlb2YgQXQpcmV0dXJuW2FdO2Vsc2UgaWYoYSBpbnN0YW5jZW9mIFRlKXJldHVybiBhLmJhdGNoZXM7ZWxzZSBpZihhIGluc3RhbmNlb2YgcHQpe2lmKGEudHlwZSBpbnN0YW5jZW9mIEV0KXJldHVybltuZXcgQXQobmV3IGx0KGEudHlwZS5jaGlsZHJlbiksYSldfWVsc2UgaWYoQXJyYXkuaXNBcnJheShhKSlyZXR1cm4gYS5mbGF0TWFwKChsKT0+cyhsKSk7ZWxzZSBpZih0eXBlb2YgYVtTeW1ib2wuaXRlcmF0b3JdPT09ImZ1bmN0aW9uIilyZXR1cm5bLi4uYV0uZmxhdE1hcCgobCk9PnMobCkpO2Vsc2UgaWYodHlwZW9mIGE9PT0ib2JqZWN0Iil7bGV0IGw9T2JqZWN0LmtleXMoYSksdT1sLm1hcCgoZyk9Pm5ldyBOKFthW2ddXSkpLGY9biE9PW51bGwmJm4hPT12b2lkIDA/bjpuZXcgbHQobC5tYXAoKGcsdik9Pm5ldyBVKFN0cmluZyhnKSx1W3ZdLnR5cGUsdVt2XS5udWxsYWJsZSkpKSxbLHBdPVRkKGYsdSk7cmV0dXJuIHAubGVuZ3RoPT09MD9bbmV3IEF0KGEpXTpwfX1yZXR1cm5bXX0sbz10LmZsYXRNYXAoKGEpPT5zKGEpKTtpZihuPShyPW4hPT1udWxsJiZuIT09dm9pZCAwP246KGU9b1swXSk9PT1udWxsfHxlPT09dm9pZCAwP3ZvaWQgMDplLnNjaGVtYSkhPT1udWxsJiZyIT09dm9pZCAwP3I6bmV3IGx0KFtdKSwhKG4gaW5zdGFuY2VvZiBsdCkpdGhyb3cgVHlwZUVycm9yKCJUYWJsZSBjb25zdHJ1Y3RvciBleHBlY3RzIGEgW1NjaGVtYSwgUmVjb3JkQmF0Y2hbXV0gcGFpci4iKTtmb3IobGV0IGEgb2Ygbyl7aWYoIShhIGluc3RhbmNlb2YgQXQpKXRocm93IFR5cGVFcnJvcigiVGFibGUgY29uc3RydWN0b3IgZXhwZWN0cyBhIFtTY2hlbWEsIFJlY29yZEJhdGNoW11dIHBhaXIuIik7aWYoIXdhKG4sYS5zY2hlbWEpKXRocm93IFR5cGVFcnJvcigiVGFibGUgYW5kIGlubmVyIFJlY29yZEJhdGNoIHNjaGVtYXMgbXVzdCBiZSBlcXVpdmFsZW50LiIpfXRoaXMuc2NoZW1hPW4sdGhpcy5iYXRjaGVzPW8sdGhpcy5fb2Zmc2V0cz1pIT09bnVsbCYmaSE9PXZvaWQgMD9pOnpmKHRoaXMuZGF0YSl9Z2V0IGRhdGEoKXtyZXR1cm4gdGhpcy5iYXRjaGVzLm1hcCgoe2RhdGE6dH0pPT50KX1nZXQgbnVtQ29scygpe3JldHVybiB0aGlzLnNjaGVtYS5maWVsZHMubGVuZ3RofWdldCBudW1Sb3dzKCl7cmV0dXJuIHRoaXMuZGF0YS5yZWR1Y2UoKHQsZSk9PnQrZS5sZW5ndGgsMCl9Z2V0IG51bGxDb3VudCgpe2lmKHRoaXMuX251bGxDb3VudD09PS0xKXRoaXMuX251bGxDb3VudD1WZih0aGlzLmRhdGEpO3JldHVybiB0aGlzLl9udWxsQ291bnR9aXNWYWxpZCh0KXtyZXR1cm4hMX1nZXQodCl7cmV0dXJuIG51bGx9YXQodCl7cmV0dXJuIHRoaXMuZ2V0KGZhKHQsdGhpcy5udW1Sb3dzKSl9c2V0KHQsZSl7cmV0dXJufWluZGV4T2YodCxlKXtyZXR1cm4tMX1bU3ltYm9sLml0ZXJhdG9yXSgpe2lmKHRoaXMuYmF0Y2hlcy5sZW5ndGg+MClyZXR1cm4gSWMudmlzaXQobmV3IE4odGhpcy5kYXRhKSk7cmV0dXJuW11bU3ltYm9sLml0ZXJhdG9yXSgpfXRvQXJyYXkoKXtyZXR1cm5bLi4udGhpc119dG9TdHJpbmcoKXtyZXR1cm5gWwogICR7dGhpcy50b0FycmF5KCkuam9pbihgLAogIGApfQpdYH1jb25jYXQoLi4udCl7bGV0IGU9dGhpcy5zY2hlbWEscj10aGlzLmRhdGEuY29uY2F0KHQuZmxhdE1hcCgoe2RhdGE6bn0pPT5uKSk7cmV0dXJuIG5ldyBUZShlLHIubWFwKChuKT0+bmV3IEF0KGUsbikpKX1zbGljZSh0LGUpe2xldCByPXRoaXMuc2NoZW1hO1t0LGVdPWtsKHtsZW5ndGg6dGhpcy5udW1Sb3dzfSx0LGUpO2xldCBuPWpmKHRoaXMuZGF0YSx0aGlzLl9vZmZzZXRzLHQsZSk7cmV0dXJuIG5ldyBUZShyLG4ubWFwKChpKT0+bmV3IEF0KHIsaSkpKX1nZXRDaGlsZCh0KXtyZXR1cm4gdGhpcy5nZXRDaGlsZEF0KHRoaXMuc2NoZW1hLmZpZWxkcy5maW5kSW5kZXgoKGUpPT5lLm5hbWU9PT10KSl9Z2V0Q2hpbGRBdCh0KXtpZih0Pi0xJiZ0PHRoaXMuc2NoZW1hLmZpZWxkcy5sZW5ndGgpe2xldCBlPXRoaXMuZGF0YS5tYXAoKHIpPT5yLmNoaWxkcmVuW3RdKTtpZihlLmxlbmd0aD09PTApe2xldHt0eXBlOnJ9PXRoaXMuc2NoZW1hLmZpZWxkc1t0XSxuPVMoe3R5cGU6cixsZW5ndGg6MCxudWxsQ291bnQ6MH0pO2UucHVzaChuLl9jaGFuZ2VMZW5ndGhBbmRCYWNrZmlsbE51bGxCaXRtYXAodGhpcy5udW1Sb3dzKSl9cmV0dXJuIG5ldyBOKGUpfXJldHVybiBudWxsfXNldENoaWxkKHQsZSl7dmFyIHI7cmV0dXJuIHRoaXMuc2V0Q2hpbGRBdCgocj10aGlzLnNjaGVtYS5maWVsZHMpPT09bnVsbHx8cj09PXZvaWQgMD92b2lkIDA6ci5maW5kSW5kZXgoKG4pPT5uLm5hbWU9PT10KSxlKX1zZXRDaGlsZEF0KHQsZSl7bGV0IHI9dGhpcy5zY2hlbWEsbj1bLi4udGhpcy5iYXRjaGVzXTtpZih0Pi0xJiZ0PHRoaXMubnVtQ29scyl7aWYoIWUpZT1uZXcgTihbUyh7dHlwZTpuZXcgd2UsbGVuZ3RoOnRoaXMubnVtUm93c30pXSk7bGV0IGk9ci5maWVsZHMuc2xpY2UoKSxzPWlbdF0uY2xvbmUoe3R5cGU6ZS50eXBlfSksbz10aGlzLnNjaGVtYS5maWVsZHMubWFwKChhLGwpPT50aGlzLmdldENoaWxkQXQobCkpO1tpW3RdLG9bdF1dPVtzLGVdLFtyLG5dPVRkKHIsbyl9cmV0dXJuIG5ldyBUZShyLG4pfXNlbGVjdCh0KXtsZXQgZT10aGlzLnNjaGVtYS5maWVsZHMucmVkdWNlKChyLG4saSk9PnIuc2V0KG4ubmFtZSxpKSxuZXcgTWFwKTtyZXR1cm4gdGhpcy5zZWxlY3RBdCh0Lm1hcCgocik9PmUuZ2V0KHIpKS5maWx0ZXIoKHIpPT5yPi0xKSl9c2VsZWN0QXQodCl7bGV0IGU9dGhpcy5zY2hlbWEuc2VsZWN0QXQodCkscj10aGlzLmJhdGNoZXMubWFwKChuKT0+bi5zZWxlY3RBdCh0KSk7cmV0dXJuIG5ldyBUZShlLHIpfWFzc2lnbih0KXtsZXQgZT10aGlzLnNjaGVtYS5maWVsZHMsW3Isbl09dC5zY2hlbWEuZmllbGRzLnJlZHVjZSgobyxhLGwpPT57bGV0W3UsZl09byxwPWUuZmluZEluZGV4KChnKT0+Zy5uYW1lPT09YS5uYW1lKTtyZXR1cm5+cD9mW3BdPWw6dS5wdXNoKGwpLG99LFtbXSxbXV0pLGk9dGhpcy5zY2hlbWEuYXNzaWduKHQuc2NoZW1hKSxzPVsuLi5lLm1hcCgobyxhKT0+W2EsblthXV0pLm1hcCgoW28sYV0pPT5hPT09dm9pZCAwP3RoaXMuZ2V0Q2hpbGRBdChvKTp0LmdldENoaWxkQXQoYSkpLC4uLnIubWFwKChvKT0+dC5nZXRDaGlsZEF0KG8pKV0uZmlsdGVyKEJvb2xlYW4pO3JldHVybiBuZXcgVGUoLi4uVGQoaSxzKSl9fTttMD1TeW1ib2wudG9TdHJpbmdUYWc7VGVbbTBdPSgodCk9Pih0LnNjaGVtYT1udWxsLHQuYmF0Y2hlcz1bXSx0Ll9vZmZzZXRzPW5ldyBVaW50MzJBcnJheShbMF0pLHQuX251bGxDb3VudD0tMSx0W1N5bWJvbC5pc0NvbmNhdFNwcmVhZGFibGVdPSEwLHRbeTBdPSEwLHQuaXNWYWxpZD12YyhqbCksdC5nZXQ9dmMoUmUuZ2V0VmlzaXRGbihfLlN0cnVjdCkpLHQuc2V0PSRmKGRyLmdldFZpc2l0Rm4oXy5TdHJ1Y3QpKSx0LmluZGV4T2Y9cWYocGEuZ2V0VmlzaXRGbihfLlN0cnVjdCkpLCJUYWJsZSIpKShUZS5wcm90b3R5cGUpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShUZSxTeW1ib2wuaGFzSW5zdGFuY2Use3ZhbHVlOmZ1bmN0aW9uKGUpe3JldHVybiBGdW5jdGlvbi5wcm90b3R5cGVbU3ltYm9sLmhhc0luc3RhbmNlXS5jYWxsKHRoaXMsZSl8fHRoaXM9PT1UZSYmVGUuaXNUYWJsZShlKX19KX0pO2Z1bmN0aW9uIF8wKHQsZSxyPWUucmVkdWNlKChuLGkpPT5NYXRoLm1heChuLGkubGVuZ3RoKSwwKSl7dmFyIG47bGV0IGk9Wy4uLnQuZmllbGRzXSxzPVsuLi5lXSxvPShyKzYzJi02NCk+PjM7Zm9yKGxldFthLGxdb2YgdC5maWVsZHMuZW50cmllcygpKXtsZXQgdT1lW2FdO2lmKCF1fHx1Lmxlbmd0aCE9PXIpaVthXT1sLmNsb25lKHtudWxsYWJsZTohMH0pLHNbYV09KG49dT09PW51bGx8fHU9PT12b2lkIDA/dm9pZCAwOnUuX2NoYW5nZUxlbmd0aEFuZEJhY2tmaWxsTnVsbEJpdG1hcChyKSkhPT1udWxsJiZuIT09dm9pZCAwP246Uyh7dHlwZTpsLnR5cGUsbGVuZ3RoOnIsbnVsbENvdW50OnIsbnVsbEJpdG1hcDpuZXcgVWludDhBcnJheShvKX0pfXJldHVyblt0LmFzc2lnbihpKSxTKHt0eXBlOm5ldyBFdChpKSxsZW5ndGg6cixjaGlsZHJlbjpzfSldfWZ1bmN0aW9uIHcwKHQsZSxyPW5ldyBNYXApe3ZhciBuLGk7aWYoKChuPXQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0Lmxlbmd0aCkhPT1udWxsJiZuIT09dm9pZCAwP246MCk+MCYmKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0Lmxlbmd0aCk9PT0oZT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUubGVuZ3RoKSlmb3IobGV0IHM9LTEsbz10Lmxlbmd0aDsrK3M8bzspe2xldHt0eXBlOmF9PXRbc10sbD1lW3NdO2ZvcihsZXQgdSBvZltsLC4uLigoaT1sPT09bnVsbHx8bD09PXZvaWQgMD92b2lkIDA6bC5kaWN0aW9uYXJ5KT09PW51bGx8fGk9PT12b2lkIDA/dm9pZCAwOmkuZGF0YSl8fFtdXSl3MChhLmNoaWxkcmVuLHU9PT1udWxsfHx1PT09dm9pZCAwP3ZvaWQgMDp1LmNoaWxkcmVuLHIpO2lmKEIuaXNEaWN0aW9uYXJ5KGEpKXtsZXR7aWQ6dX09YTtpZighci5oYXModSkpe2lmKGw9PT1udWxsfHxsPT09dm9pZCAwP3ZvaWQgMDpsLmRpY3Rpb25hcnkpci5zZXQodSxsLmRpY3Rpb25hcnkpfWVsc2UgaWYoci5nZXQodSkhPT1sLmRpY3Rpb25hcnkpdGhyb3cgRXJyb3IoIkNhbm5vdCBjcmVhdGUgU2NoZW1hIGNvbnRhaW5pbmcgdHdvIGRpZmZlcmVudCBkaWN0aW9uYXJpZXMgd2l0aCB0aGUgc2FtZSBJZCIpfX1yZXR1cm4gcn12YXIgZzAsYjAsQXQsTmM7dmFyIE5vPW0oKCk9PntYbigpO0VkKCk7UXIoKTtVcigpO2llKCk7Z2MoKTt1YSgpO1NuKCk7SGYoKTtZZigpO2IwPVN5bWJvbC5mb3IoImFwYWNoZS1hcnJvdy9SZWNvcmRCYXRjaCIpO0F0PWNsYXNzIEF0e3N0YXRpYyBpc1JlY29yZEJhdGNoKHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dFtiMF0pPT09ITB9Y29uc3RydWN0b3IoLi4udCl7c3dpdGNoKHQubGVuZ3RoKXtjYXNlIDM6Y2FzZSAyOntpZihbdGhpcy5zY2hlbWFdPXQsISh0aGlzLnNjaGVtYSBpbnN0YW5jZW9mIGx0KSl0aHJvdyBUeXBlRXJyb3IoIlJlY29yZEJhdGNoIGNvbnN0cnVjdG9yIGV4cGVjdHMgYSBbU2NoZW1hLCBEYXRhXSBwYWlyLiIpO2lmKFssdGhpcy5kYXRhPVMoe251bGxDb3VudDowLHR5cGU6bmV3IEV0KHRoaXMuc2NoZW1hLmZpZWxkcyksY2hpbGRyZW46dGhpcy5zY2hlbWEuZmllbGRzLm1hcCgoZSk9PlMoe3R5cGU6ZS50eXBlLG51bGxDb3VudDowfSkpfSksdGhpcy5fbWV0YWRhdGE9bmV3IE1hcF09dCwhKHRoaXMuZGF0YSBpbnN0YW5jZW9mIHB0KSl0aHJvdyBUeXBlRXJyb3IoIlJlY29yZEJhdGNoIGNvbnN0cnVjdG9yIGV4cGVjdHMgYSBbU2NoZW1hLCBEYXRhXSBwYWlyLiIpO1t0aGlzLnNjaGVtYSx0aGlzLmRhdGFdPV8wKHRoaXMuc2NoZW1hLHRoaXMuZGF0YS5jaGlsZHJlbix0aGlzLmRhdGEubGVuZ3RoKTticmVha31jYXNlIDE6e2xldFtlXT10LHtmaWVsZHM6cixjaGlsZHJlbjpuLGxlbmd0aDppfT1PYmplY3Qua2V5cyhlKS5yZWR1Y2UoKGEsbCx1KT0+KGEuY2hpbGRyZW5bdV09ZVtsXSxhLmxlbmd0aD1NYXRoLm1heChhLmxlbmd0aCxlW2xdLmxlbmd0aCksYS5maWVsZHNbdV09VS5uZXcoe25hbWU6bCx0eXBlOmVbbF0udHlwZSxudWxsYWJsZTohMH0pLGEpLHtsZW5ndGg6MCxmaWVsZHM6W10sY2hpbGRyZW46W119KSxzPW5ldyBsdChyKSxvPVMoe3R5cGU6bmV3IEV0KHIpLGxlbmd0aDppLGNoaWxkcmVuOm4sbnVsbENvdW50OjB9KTtbdGhpcy5zY2hlbWEsdGhpcy5kYXRhXT1fMChzLG8uY2hpbGRyZW4saSksdGhpcy5fbWV0YWRhdGE9bmV3IE1hcDticmVha31kZWZhdWx0OnRocm93IFR5cGVFcnJvcigiUmVjb3JkQmF0Y2ggY29uc3RydWN0b3IgZXhwZWN0cyBhbiBPYmplY3QgbWFwcGluZyBuYW1lcyB0byBjaGlsZCBEYXRhLCBvciBhIFtTY2hlbWEsIERhdGFdIHBhaXIuIil9fWdldCBtZXRhZGF0YSgpe3JldHVybiB0aGlzLl9tZXRhZGF0YX1nZXQgZGljdGlvbmFyaWVzKCl7cmV0dXJuIHRoaXMuX2RpY3Rpb25hcmllc3x8KHRoaXMuX2RpY3Rpb25hcmllcz13MCh0aGlzLnNjaGVtYS5maWVsZHMsdGhpcy5kYXRhLmNoaWxkcmVuKSl9Z2V0IG51bUNvbHMoKXtyZXR1cm4gdGhpcy5zY2hlbWEuZmllbGRzLmxlbmd0aH1nZXQgbnVtUm93cygpe3JldHVybiB0aGlzLmRhdGEubGVuZ3RofWdldCBudWxsQ291bnQoKXtyZXR1cm4gdGhpcy5kYXRhLm51bGxDb3VudH1pc1ZhbGlkKHQpe3JldHVybiB0aGlzLmRhdGEuZ2V0VmFsaWQodCl9Z2V0KHQpe3JldHVybiBSZS52aXNpdCh0aGlzLmRhdGEsdCl9YXQodCl7cmV0dXJuIHRoaXMuZ2V0KGZhKHQsdGhpcy5udW1Sb3dzKSl9c2V0KHQsZSl7cmV0dXJuIGRyLnZpc2l0KHRoaXMuZGF0YSx0LGUpfWluZGV4T2YodCxlKXtyZXR1cm4gcGEudmlzaXQodGhpcy5kYXRhLHQsZSl9W1N5bWJvbC5pdGVyYXRvcl0oKXtyZXR1cm4gSWMudmlzaXQobmV3IE4oW3RoaXMuZGF0YV0pKX10b0FycmF5KCl7cmV0dXJuWy4uLnRoaXNdfWNvbmNhdCguLi50KXtyZXR1cm4gbmV3IFRlKHRoaXMuc2NoZW1hLFt0aGlzLC4uLnRdKX1zbGljZSh0LGUpe2xldFtyXT1uZXcgTihbdGhpcy5kYXRhXSkuc2xpY2UodCxlKS5kYXRhO3JldHVybiBuZXcgQXQodGhpcy5zY2hlbWEscix0aGlzLl9tZXRhZGF0YSl9Z2V0Q2hpbGQodCl7dmFyIGU7cmV0dXJuIHRoaXMuZ2V0Q2hpbGRBdCgoZT10aGlzLnNjaGVtYS5maWVsZHMpPT09bnVsbHx8ZT09PXZvaWQgMD92b2lkIDA6ZS5maW5kSW5kZXgoKHIpPT5yLm5hbWU9PT10KSl9Z2V0Q2hpbGRBdCh0KXtpZih0Pi0xJiZ0PHRoaXMuc2NoZW1hLmZpZWxkcy5sZW5ndGgpcmV0dXJuIG5ldyBOKFt0aGlzLmRhdGEuY2hpbGRyZW5bdF1dKTtyZXR1cm4gbnVsbH1zZXRDaGlsZCh0LGUpe3ZhciByO3JldHVybiB0aGlzLnNldENoaWxkQXQoKHI9dGhpcy5zY2hlbWEuZmllbGRzKT09PW51bGx8fHI9PT12b2lkIDA/dm9pZCAwOnIuZmluZEluZGV4KChuKT0+bi5uYW1lPT09dCksZSl9c2V0Q2hpbGRBdCh0LGUpe2xldCByPXRoaXMuc2NoZW1hLG49dGhpcy5kYXRhO2lmKHQ+LTEmJnQ8dGhpcy5udW1Db2xzKXtpZighZSllPW5ldyBOKFtTKHt0eXBlOm5ldyB3ZSxsZW5ndGg6dGhpcy5udW1Sb3dzfSldKTtsZXQgaT1yLmZpZWxkcy5zbGljZSgpLHM9bi5jaGlsZHJlbi5zbGljZSgpLG89aVt0XS5jbG9uZSh7dHlwZTplLnR5cGV9KTtbaVt0XSxzW3RdXT1bbyxlLmRhdGFbMF1dLHI9bmV3IGx0KGksbmV3IE1hcCh0aGlzLnNjaGVtYS5tZXRhZGF0YSkpLG49Uyh7dHlwZTpuZXcgRXQoaSksbGVuZ3RoOm4ubGVuZ3RoLGNoaWxkcmVuOnN9KX1yZXR1cm4gbmV3IEF0KHIsbix0aGlzLl9tZXRhZGF0YSl9c2VsZWN0KHQpe2xldCBlPXRoaXMuc2NoZW1hLnNlbGVjdCh0KSxyPW5ldyBFdChlLmZpZWxkcyksbj1bXTtmb3IobGV0IGkgb2YgdCl7bGV0IHM9dGhpcy5zY2hlbWEuZmllbGRzLmZpbmRJbmRleCgobyk9Pm8ubmFtZT09PWkpO2lmKH5zKW5bc109dGhpcy5kYXRhLmNoaWxkcmVuW3NdfXJldHVybiBuZXcgQXQoZSxTKHt0eXBlOnIsbGVuZ3RoOnRoaXMubnVtUm93cyxjaGlsZHJlbjpufSksdGhpcy5fbWV0YWRhdGEpfXNlbGVjdEF0KHQpe2xldCBlPXRoaXMuc2NoZW1hLnNlbGVjdEF0KHQpLHI9dC5tYXAoKGkpPT50aGlzLmRhdGEuY2hpbGRyZW5baV0pLmZpbHRlcihCb29sZWFuKSxuPVMoe3R5cGU6bmV3IEV0KGUuZmllbGRzKSxsZW5ndGg6dGhpcy5udW1Sb3dzLGNoaWxkcmVuOnJ9KTtyZXR1cm4gbmV3IEF0KGUsbix0aGlzLl9tZXRhZGF0YSl9fTtnMD1TeW1ib2wudG9TdHJpbmdUYWc7QXRbZzBdPSgodCk9Pih0Ll9udWxsQ291bnQ9LTEsdFtTeW1ib2wuaXNDb25jYXRTcHJlYWRhYmxlXT0hMCx0W2IwXT0hMCwiUmVjb3JkQmF0Y2giKSkoQXQucHJvdG90eXBlKTtPYmplY3QuZGVmaW5lUHJvcGVydHkoQXQsU3ltYm9sLmhhc0luc3RhbmNlLHt2YWx1ZTpmdW5jdGlvbihlKXtyZXR1cm4gRnVuY3Rpb24ucHJvdG90eXBlW1N5bWJvbC5oYXNJbnN0YW5jZV0uY2FsbCh0aGlzLGUpfHx0aGlzPT09QXQmJkF0LmlzUmVjb3JkQmF0Y2goZSl9fSk7TmM9Y2xhc3MgTmMgZXh0ZW5kcyBBdHtjb25zdHJ1Y3Rvcih0LGUpe2xldCByPXQuZmllbGRzLm1hcCgoaSk9PlMoe3R5cGU6aS50eXBlfSkpLG49Uyh7dHlwZTpuZXcgRXQodC5maWVsZHMpLGxlbmd0aDowLG51bGxDb3VudDowLGNoaWxkcmVuOnJ9KTtzdXBlcih0LG4sZXx8bmV3IE1hcCl9fX0pO2Z1bmN0aW9uIE1kKHQsZT0wKXtmb3IobGV0IHI9LTEsbj1GYy5sZW5ndGg7KytyPG47KWlmKEZjW3JdIT09dFtlK3JdKXJldHVybiExO3JldHVybiEwfXZhciBOeT0odCk9PmBFeHBlY3RlZCAke3h0W3RdfSBNZXNzYWdlIGluIHN0cmVhbSwgYnV0IHdhcyBudWxsIG9yIGxlbmd0aCAwLmAsRnk9KHQpPT5gSGVhZGVyIHBvaW50ZXIgb2YgZmxhdGJ1ZmZlci1lbmNvZGVkICR7eHRbdF19IE1lc3NhZ2UgaXMgbnVsbCBvciBsZW5ndGggMC5gLHYwPSh0LGUpPT5gRXhwZWN0ZWQgdG8gcmVhZCAke3R9IG1ldGFkYXRhIGJ5dGVzLCBidXQgb25seSByZWFkICR7ZX0uYCxJMD0odCxlKT0+YEV4cGVjdGVkIHRvIHJlYWQgJHt0fSBieXRlcyBmb3IgbWVzc2FnZSBib2R5LCBidXQgb25seSByZWFkICR7ZX0uYCxldSxPZCxOZCxGZD00LE95PSJBUlJPVzEiLEZjLE1jLE15LEIwO3ZhciBMeT1tKCgpPT57cG4oKTtMZSgpO050KCk7eWEoKTtLbSgpO2plKCk7X2EoKTtXbCgpO2V1PWNsYXNzIGV1e2NvbnN0cnVjdG9yKHQpe3RoaXMuc291cmNlPXQgaW5zdGFuY2VvZiBEcz90Om5ldyBEcyh0KX1bU3ltYm9sLml0ZXJhdG9yXSgpe3JldHVybiB0aGlzfW5leHQoKXtsZXQgdDtpZigodD10aGlzLnJlYWRNZXRhZGF0YUxlbmd0aCgpKS5kb25lKXJldHVybiBmZTtpZih0LnZhbHVlPT09LTEmJih0PXRoaXMucmVhZE1ldGFkYXRhTGVuZ3RoKCkpLmRvbmUpcmV0dXJuIGZlO2lmKCh0PXRoaXMucmVhZE1ldGFkYXRhKHQudmFsdWUpKS5kb25lKXJldHVybiBmZTtyZXR1cm4gdH10aHJvdyh0KXtyZXR1cm4gdGhpcy5zb3VyY2UudGhyb3codCl9cmV0dXJuKHQpe3JldHVybiB0aGlzLnNvdXJjZS5yZXR1cm4odCl9cmVhZE1lc3NhZ2UodCl7bGV0IGU7aWYoKGU9dGhpcy5uZXh0KCkpLmRvbmUpcmV0dXJuIG51bGw7aWYodCE9bnVsbCYmZS52YWx1ZS5oZWFkZXJUeXBlIT09dCl0aHJvdyBFcnJvcihOeSh0KSk7cmV0dXJuIGUudmFsdWV9cmVhZE1lc3NhZ2VCb2R5KHQpe2lmKHQ8PTApcmV0dXJuIG5ldyBVaW50OEFycmF5KDApO2xldCBlPUModGhpcy5zb3VyY2UucmVhZCh0KSk7aWYoZS5ieXRlTGVuZ3RoPHQpdGhyb3cgRXJyb3IoSTAodCxlLmJ5dGVMZW5ndGgpKTtyZXR1cm4gZS5ieXRlT2Zmc2V0JTg9PT0wJiZlLmJ5dGVPZmZzZXQrZS5ieXRlTGVuZ3RoPD1lLmJ1ZmZlci5ieXRlTGVuZ3RoP2U6ZS5zbGljZSgpfXJlYWRTY2hlbWEodD0hMSl7bGV0IGU9eHQuU2NoZW1hLHI9dGhpcy5yZWFkTWVzc2FnZShlKSxuPXI9PT1udWxsfHxyPT09dm9pZCAwP3ZvaWQgMDpyLmhlYWRlcigpO2lmKHQmJiFuKXRocm93IEVycm9yKEZ5KGUpKTtyZXR1cm4gbn1yZWFkTWV0YWRhdGFMZW5ndGgoKXtsZXQgdD10aGlzLnNvdXJjZS5yZWFkKEZkKSxlPXQmJm5ldyBscih0KSxyPShlPT09bnVsbHx8ZT09PXZvaWQgMD92b2lkIDA6ZS5yZWFkSW50MzIoMCkpfHwwO3JldHVybntkb25lOnI9PT0wLHZhbHVlOnJ9fXJlYWRNZXRhZGF0YSh0KXtsZXQgZT10aGlzLnNvdXJjZS5yZWFkKHQpO2lmKCFlKXJldHVybiBmZTtpZihlLmJ5dGVMZW5ndGg8dCl0aHJvdyBFcnJvcih2MCh0LGUuYnl0ZUxlbmd0aCkpO3JldHVybntkb25lOiExLHZhbHVlOnRyLmRlY29kZShlKX19fTtPZD1jbGFzcyBPZHtjb25zdHJ1Y3Rvcih0LGUpe3RoaXMuc291cmNlPXQgaW5zdGFuY2VvZiBabj90Om9mKHQpP25ldyBnYSh0LGUpOm5ldyBabih0KX1bU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCl7cmV0dXJuIHRoaXN9bmV4dCgpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXQgdDtpZigodD15aWVsZCB0aGlzLnJlYWRNZXRhZGF0YUxlbmd0aCgpKS5kb25lKXJldHVybiBmZTtpZih0LnZhbHVlPT09LTEmJih0PXlpZWxkIHRoaXMucmVhZE1ldGFkYXRhTGVuZ3RoKCkpLmRvbmUpcmV0dXJuIGZlO2lmKCh0PXlpZWxkIHRoaXMucmVhZE1ldGFkYXRhKHQudmFsdWUpKS5kb25lKXJldHVybiBmZTtyZXR1cm4gdH0pfXRocm93KHQpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtyZXR1cm4geWllbGQgdGhpcy5zb3VyY2UudGhyb3codCl9KX1yZXR1cm4odCl7cmV0dXJuIEUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3JldHVybiB5aWVsZCB0aGlzLnNvdXJjZS5yZXR1cm4odCl9KX1yZWFkTWVzc2FnZSh0KXtyZXR1cm4gRSh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7bGV0IGU7aWYoKGU9eWllbGQgdGhpcy5uZXh0KCkpLmRvbmUpcmV0dXJuIG51bGw7aWYodCE9bnVsbCYmZS52YWx1ZS5oZWFkZXJUeXBlIT09dCl0aHJvdyBFcnJvcihOeSh0KSk7cmV0dXJuIGUudmFsdWV9KX1yZWFkTWVzc2FnZUJvZHkodCl7cmV0dXJuIEUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe2lmKHQ8PTApcmV0dXJuIG5ldyBVaW50OEFycmF5KDApO2xldCBlPUMoeWllbGQgdGhpcy5zb3VyY2UucmVhZCh0KSk7aWYoZS5ieXRlTGVuZ3RoPHQpdGhyb3cgRXJyb3IoSTAodCxlLmJ5dGVMZW5ndGgpKTtyZXR1cm4gZS5ieXRlT2Zmc2V0JTg9PT0wJiZlLmJ5dGVPZmZzZXQrZS5ieXRlTGVuZ3RoPD1lLmJ1ZmZlci5ieXRlTGVuZ3RoP2U6ZS5zbGljZSgpfSl9cmVhZFNjaGVtYSgpe3JldHVybiBFKHRoaXMsYXJndW1lbnRzLHZvaWQgMCxmdW5jdGlvbioodD0hMSl7bGV0IGU9eHQuU2NoZW1hLHI9eWllbGQgdGhpcy5yZWFkTWVzc2FnZShlKSxuPXI9PT1udWxsfHxyPT09dm9pZCAwP3ZvaWQgMDpyLmhlYWRlcigpO2lmKHQmJiFuKXRocm93IEVycm9yKEZ5KGUpKTtyZXR1cm4gbn0pfXJlYWRNZXRhZGF0YUxlbmd0aCgpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXQgdD15aWVsZCB0aGlzLnNvdXJjZS5yZWFkKEZkKSxlPXQmJm5ldyBscih0KSxyPShlPT09bnVsbHx8ZT09PXZvaWQgMD92b2lkIDA6ZS5yZWFkSW50MzIoMCkpfHwwO3JldHVybntkb25lOnI9PT0wLHZhbHVlOnJ9fSl9cmVhZE1ldGFkYXRhKHQpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXQgZT15aWVsZCB0aGlzLnNvdXJjZS5yZWFkKHQpO2lmKCFlKXJldHVybiBmZTtpZihlLmJ5dGVMZW5ndGg8dCl0aHJvdyBFcnJvcih2MCh0LGUuYnl0ZUxlbmd0aCkpO3JldHVybntkb25lOiExLHZhbHVlOnRyLmRlY29kZShlKX19KX19O05kPWNsYXNzIE5kIGV4dGVuZHMgZXV7Y29uc3RydWN0b3IodCl7c3VwZXIobmV3IFVpbnQ4QXJyYXkoMCkpO3RoaXMuX3NjaGVtYT0hMSx0aGlzLl9ib2R5PVtdLHRoaXMuX2JhdGNoSW5kZXg9MCx0aGlzLl9kaWN0aW9uYXJ5SW5kZXg9MCx0aGlzLl9qc29uPXQgaW5zdGFuY2VvZiBRZj90Om5ldyBRZih0KX1uZXh0KCl7bGV0e19qc29uOnR9PXRoaXM7aWYoIXRoaXMuX3NjaGVtYSlyZXR1cm4gdGhpcy5fc2NoZW1hPSEwLHtkb25lOiExLHZhbHVlOnRyLmZyb21KU09OKHQuc2NoZW1hLHh0LlNjaGVtYSl9O2lmKHRoaXMuX2RpY3Rpb25hcnlJbmRleDx0LmRpY3Rpb25hcmllcy5sZW5ndGgpe2xldCBlPXQuZGljdGlvbmFyaWVzW3RoaXMuX2RpY3Rpb25hcnlJbmRleCsrXTtyZXR1cm4gdGhpcy5fYm9keT1lLmRhdGEuY29sdW1ucyx7ZG9uZTohMSx2YWx1ZTp0ci5mcm9tSlNPTihlLHh0LkRpY3Rpb25hcnlCYXRjaCl9fWlmKHRoaXMuX2JhdGNoSW5kZXg8dC5iYXRjaGVzLmxlbmd0aCl7bGV0IGU9dC5iYXRjaGVzW3RoaXMuX2JhdGNoSW5kZXgrK107cmV0dXJuIHRoaXMuX2JvZHk9ZS5jb2x1bW5zLHtkb25lOiExLHZhbHVlOnRyLmZyb21KU09OKGUseHQuUmVjb3JkQmF0Y2gpfX1yZXR1cm4gdGhpcy5fYm9keT1bXSxmZX1yZWFkTWVzc2FnZUJvZHkodCl7cmV0dXJuIGUodGhpcy5fYm9keSk7ZnVuY3Rpb24gZShyKXtyZXR1cm4ocnx8W10pLnJlZHVjZSgobixpKT0+Wy4uLm4sLi4uaS5WQUxJRElUWSYmW2kuVkFMSURJVFldfHxbXSwuLi5pLlRZUEVfSUQmJltpLlRZUEVfSURdfHxbXSwuLi5pLk9GRlNFVCYmW2kuT0ZGU0VUXXx8W10sLi4uaS5EQVRBJiZbaS5EQVRBXXx8W10sLi4uaS5WSUVXUyYmW2kuVklFV1NdfHxbXSwuLi5pLlZBUklBRElDX0RBVEFfQlVGRkVSU3x8W10sLi4uZShpLmNoaWxkcmVuKV0sW10pfX1yZWFkTWVzc2FnZSh0KXtsZXQgZTtpZigoZT10aGlzLm5leHQoKSkuZG9uZSlyZXR1cm4gbnVsbDtpZih0IT1udWxsJiZlLnZhbHVlLmhlYWRlclR5cGUhPT10KXRocm93IEVycm9yKE55KHQpKTtyZXR1cm4gZS52YWx1ZX1yZWFkU2NoZW1hKCl7bGV0IHQ9eHQuU2NoZW1hLGU9dGhpcy5yZWFkTWVzc2FnZSh0KSxyPWU9PT1udWxsfHxlPT09dm9pZCAwP3ZvaWQgMDplLmhlYWRlcigpO2lmKCFlfHwhcil0aHJvdyBFcnJvcihGeSh0KSk7cmV0dXJuIHJ9fTtGYz1uZXcgVWludDhBcnJheShPeS5sZW5ndGgpO2ZvcihsZXQgdD0wO3Q8T3kubGVuZ3RoO3QrPTEpRmNbdF09T3kuY29kZVBvaW50QXQodCk7TWM9RmMubGVuZ3RoLE15PU1jK0ZkLEIwPU1jKjIrRmR9KTtjbGFzcyBTMHtjb25zdHJ1Y3Rvcigpe3RoaXMuTFo0X0ZSQU1FX01BR0lDPW5ldyBVaW50OEFycmF5KFs0LDM0LDc3LDI0XSksdGhpcy5NSU5fSEVBREVSX0xFTkdUSD03fWlzVmFsaWRDb2RlY0VuY29kZSh0KXtsZXQgZT1uZXcgVWludDhBcnJheShbMSwyLDMsNCw1LDYsNyw4XSkscj10LmVuY29kZShlKTtyZXR1cm4gdGhpcy5faXNWYWxpZENvbXByZXNzZWQocil9X2lzVmFsaWRDb21wcmVzc2VkKHQpe3JldHVybiB0aGlzLl9oYXNNaW5pbXVtTGVuZ3RoKHQpJiZ0aGlzLl9oYXNWYWxpZE1hZ2ljTnVtYmVyKHQpJiZ0aGlzLl9oYXNWYWxpZFZlcnNpb24odCl9X2hhc01pbmltdW1MZW5ndGgodCl7cmV0dXJuIHQubGVuZ3RoPj10aGlzLk1JTl9IRUFERVJfTEVOR1RIfV9oYXNWYWxpZE1hZ2ljTnVtYmVyKHQpe3JldHVybiB0aGlzLkxaNF9GUkFNRV9NQUdJQy5ldmVyeSgoZSxyKT0+dFtyXT09PWUpfV9oYXNWYWxpZFZlcnNpb24odCl7cmV0dXJuKHRbNF0mMTkyKT4+Nj09PTF9fWNsYXNzIEEwe2NvbnN0cnVjdG9yKCl7dGhpcy5aU1REX01BR0lDPW5ldyBVaW50OEFycmF5KFs0MCwxODEsNDcsMjUzXSksdGhpcy5NSU5fSEVBREVSX0xFTkdUSD02fWlzVmFsaWRDb2RlY0VuY29kZSh0KXtsZXQgZT1uZXcgVWludDhBcnJheShbMSwyLDMsNCw1LDYsNyw4XSkscj10LmVuY29kZShlKTtyZXR1cm4gdGhpcy5faXNWYWxpZENvbXByZXNzZWQocil9X2lzVmFsaWRDb21wcmVzc2VkKHQpe3JldHVybiB0aGlzLl9oYXNNaW5pbXVtTGVuZ3RoKHQpJiZ0aGlzLl9oYXNWYWxpZE1hZ2ljTnVtYmVyKHQpfV9oYXNNaW5pbXVtTGVuZ3RoKHQpe3JldHVybiB0Lmxlbmd0aD49dGhpcy5NSU5fSEVBREVSX0xFTkdUSH1faGFzVmFsaWRNYWdpY051bWJlcih0KXtyZXR1cm4gdGhpcy5aU1REX01BR0lDLmV2ZXJ5KChlLHIpPT50W3JdPT09ZSl9fXZhciBEMDt2YXIgeDA9bSgoKT0+e0VsKCk7RDA9e1tNci5MWjRfRlJBTUVdOm5ldyBTMCxbTXIuWlNURF06bmV3IEEwfX0pO2NsYXNzIFQwe2NvbnN0cnVjdG9yKCl7dGhpcy5yZWdpc3RyeT17fX1zZXQodCxlKXtpZigoZT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUuZW5jb2RlKSYmdHlwZW9mIGUuZW5jb2RlPT09ImZ1bmN0aW9uIiYmIUQwW3RdLmlzVmFsaWRDb2RlY0VuY29kZShlKSl0aHJvdyBFcnJvcihgRW5jb2RlciBmb3IgJHtNclt0XX0gaXMgbm90IHZhbGlkLmApO3RoaXMucmVnaXN0cnlbdF09ZX1nZXQodCl7dmFyIGU7cmV0dXJuKChlPXRoaXMucmVnaXN0cnkpPT09bnVsbHx8ZT09PXZvaWQgMD92b2lkIDA6ZVt0XSl8fG51bGx9fXZhciBMYzt2YXIgVXk9bSgoKT0+e0VsKCk7eDAoKTtMYz1uZXcgVDB9KTt2YXIgTGQ9LTEscnU9ODtjbGFzcyBSeXtnZXQgbnVtRGljdGlvbmFyaWVzKCl7cmV0dXJuIHRoaXMuX2RpY3Rpb25hcnlJbmRleH1nZXQgbnVtUmVjb3JkQmF0Y2hlcygpe3JldHVybiB0aGlzLl9yZWNvcmRCYXRjaEluZGV4fWNvbnN0cnVjdG9yKHQ9bmV3IE1hcCl7dGhpcy5jbG9zZWQ9ITEsdGhpcy5hdXRvRGVzdHJveT0hMCx0aGlzLl9kaWN0aW9uYXJ5SW5kZXg9MCx0aGlzLl9yZWNvcmRCYXRjaEluZGV4PTAsdGhpcy5kaWN0aW9uYXJpZXM9dH1pc1N5bmMoKXtyZXR1cm4hMX1pc0FzeW5jKCl7cmV0dXJuITF9aXNGaWxlKCl7cmV0dXJuITF9aXNTdHJlYW0oKXtyZXR1cm4hMX1yZXNldCh0KXtyZXR1cm4gdGhpcy5fZGljdGlvbmFyeUluZGV4PTAsdGhpcy5fcmVjb3JkQmF0Y2hJbmRleD0wLHRoaXMuc2NoZW1hPXQsdGhpcy5kaWN0aW9uYXJpZXM9bmV3IE1hcCx0aGlzfV9sb2FkUmVjb3JkQmF0Y2godCxlLHIpe2xldCBuO2lmKHQuY29tcHJlc3Npb24hPW51bGwpe2xldCBzPUxjLmdldCh0LmNvbXByZXNzaW9uLnR5cGUpO2lmKChzPT09bnVsbHx8cz09PXZvaWQgMD92b2lkIDA6cy5kZWNvZGUpJiZ0eXBlb2Ygcy5kZWNvZGU9PT0iZnVuY3Rpb24iKXtsZXR7ZGVjb21tcHJlc3NlZEJvZHk6byxidWZmZXJzOmF9PXRoaXMuX2RlY29tcHJlc3NCdWZmZXJzKHQsZSxzKTtuPXRoaXMuX2xvYWRDb21wcmVzc2VkVmVjdG9ycyh0LG8sdGhpcy5zY2hlbWEuZmllbGRzKSx0PW5ldyBXZSh0Lmxlbmd0aCx0Lm5vZGVzLGEsbnVsbCl9ZWxzZSB0aHJvdyBFcnJvcigiUmVjb3JkIGJhdGNoIGlzIGNvbXByZXNzZWQgYnV0IGNvZGVjIG5vdCBmb3VuZCIpfWVsc2Ugbj10aGlzLl9sb2FkVmVjdG9ycyh0LGUsdGhpcy5zY2hlbWEuZmllbGRzKTtsZXQgaT1TKHt0eXBlOm5ldyBFdCh0aGlzLnNjaGVtYS5maWVsZHMpLGxlbmd0aDp0Lmxlbmd0aCxjaGlsZHJlbjpufSk7cmV0dXJuIG5ldyBBdCh0aGlzLnNjaGVtYSxpLHIpfV9sb2FkRGljdGlvbmFyeUJhdGNoKHQsZSl7bGV0e2lkOnIsaXNEZWx0YTpufT10LHtkaWN0aW9uYXJpZXM6aSxzY2hlbWE6c309dGhpcyxvPWkuZ2V0KHIpLGE9cy5kaWN0aW9uYXJpZXMuZ2V0KHIpLGw7aWYodC5kYXRhLmNvbXByZXNzaW9uIT1udWxsKXtsZXQgdT1MYy5nZXQodC5kYXRhLmNvbXByZXNzaW9uLnR5cGUpO2lmKCh1PT09bnVsbHx8dT09PXZvaWQgMD92b2lkIDA6dS5kZWNvZGUpJiZ0eXBlb2YgdS5kZWNvZGU9PT0iZnVuY3Rpb24iKXtsZXR7ZGVjb21tcHJlc3NlZEJvZHk6ZixidWZmZXJzOnB9PXRoaXMuX2RlY29tcHJlc3NCdWZmZXJzKHQuZGF0YSxlLHUpO2w9dGhpcy5fbG9hZENvbXByZXNzZWRWZWN0b3JzKHQuZGF0YSxmLFthXSksdD1uZXcgUnIobmV3IFdlKHQuZGF0YS5sZW5ndGgsdC5kYXRhLm5vZGVzLHAsbnVsbCx0LmRhdGEudmFyaWFkaWNCdWZmZXJDb3VudHMpLHIsbil9ZWxzZSB0aHJvdyBFcnJvcigiRGljdGlvbmFyeSBiYXRjaCBpcyBjb21wcmVzc2VkIGJ1dCBjb2RlYyBub3QgZm91bmQiKX1lbHNlIGw9dGhpcy5fbG9hZFZlY3RvcnModC5kYXRhLGUsW2FdKTtyZXR1cm4obyYmbj9vLmNvbmNhdChuZXcgTihsKSk6bmV3IE4obCkpLm1lbW9pemUoKX1fbG9hZFZlY3RvcnModCxlLHIpe3JldHVybiBuZXcgSGwoZSx0Lm5vZGVzLHQuYnVmZmVycyx0aGlzLmRpY3Rpb25hcmllcyx0aGlzLnNjaGVtYS5tZXRhZGF0YVZlcnNpb24sdC52YXJpYWRpY0J1ZmZlckNvdW50cykudmlzaXRNYW55KHIpfV9sb2FkQ29tcHJlc3NlZFZlY3RvcnModCxlLHIpe3JldHVybiBuZXcgcnkoZSx0Lm5vZGVzLHQuYnVmZmVycyx0aGlzLmRpY3Rpb25hcmllcyx0aGlzLnNjaGVtYS5tZXRhZGF0YVZlcnNpb24sdC52YXJpYWRpY0J1ZmZlckNvdW50cykudmlzaXRNYW55KHIpfV9kZWNvbXByZXNzQnVmZmVycyh0LGUscil7bGV0IG49W10saT1bXSxzPTA7Zm9yKGxldHtvZmZzZXQ6byxsZW5ndGg6YX1vZiB0LmJ1ZmZlcnMpe2lmKGE9PT0wKXtuLnB1c2gobmV3IFVpbnQ4QXJyYXkoMCkpLGkucHVzaChuZXcgeGUocywwKSk7Y29udGludWV9bGV0IGw9bmV3IGxyKGUuc3ViYXJyYXkobyxvK2EpKSx1PVB0KGwucmVhZEludDY0KDApKSxmPWwuYnl0ZXMoKS5zdWJhcnJheShydSkscD11PT09TGQ/ZjpyLmRlY29kZShmKTtuLnB1c2gocCk7bGV0IGc9KHMrNyYtOCktcztzKz1nLGkucHVzaChuZXcgeGUocyxwLmxlbmd0aCkpLHMrPXAubGVuZ3RofXJldHVybntkZWNvbW1wcmVzc2VkQm9keTpuLGJ1ZmZlcnM6aX19fWZ1bmN0aW9uIE0wKHQsZSl7cmV0dXJuIGUmJnR5cGVvZiBlLmF1dG9EZXN0cm95PT09ImJvb2xlYW4iP2UuYXV0b0Rlc3Ryb3k6dC5hdXRvRGVzdHJveX1mdW5jdGlvbipFMCh0KXtsZXQgZT1oci5mcm9tKHQpO3RyeXtpZighZS5vcGVuKHthdXRvRGVzdHJveTohMX0pLmNsb3NlZClkbyB5aWVsZCBlO3doaWxlKCFlLnJlc2V0KCkub3BlbigpLmNsb3NlZCl9ZmluYWxseXtlLmNhbmNlbCgpfX1mdW5jdGlvbiBPMCh0KXtyZXR1cm4gaG4odGhpcyxhcmd1bWVudHMsZnVuY3Rpb24qKCl7bGV0IHI9eWllbGQgeXQoaHIuZnJvbSh0KSk7dHJ5e2lmKCEoeWllbGQgeXQoci5vcGVuKHthdXRvRGVzdHJveTohMX0pKSkuY2xvc2VkKWRvIHlpZWxkIHlpZWxkIHl0KHIpO3doaWxlKCEoeWllbGQgeXQoci5yZXNldCgpLm9wZW4oKSkpLmNsb3NlZCl9ZmluYWxseXt5aWVsZCB5dChyLmNhbmNlbCgpKX19KX1mdW5jdGlvbiBjRSh0KXtyZXR1cm4gbmV3IE9zKG5ldyBGMCh0KSl9ZnVuY3Rpb24gbEUodCl7bGV0IGU9dC5wZWVrKE1jKzcmLTgpO3JldHVybiBlJiZlLmJ5dGVMZW5ndGg+PTQ/IU1kKGUpP25ldyBPcyhuZXcgbnUodCkpOm5ldyBJYShuZXcgQ3kodC5yZWFkKCkpKTpuZXcgT3MobmV3IG51KGZ1bmN0aW9uKigpe30oKSkpfWZ1bmN0aW9uIHVFKHQpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXQgZT15aWVsZCB0LnBlZWsoTWMrNyYtOCk7cmV0dXJuIGUmJmUuYnl0ZUxlbmd0aD49ND8hTWQoZSk/bmV3IHZhKG5ldyBpdSh0KSk6bmV3IElhKG5ldyBDeSh5aWVsZCB0LnJlYWQoKSkpOm5ldyB2YShuZXcgaXUoZnVuY3Rpb24oKXtyZXR1cm4gaG4odGhpcyxhcmd1bWVudHMsZnVuY3Rpb24qKCl7fSl9KCkpKX0pfWZ1bmN0aW9uIGZFKHQpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXR7c2l6ZTplfT15aWVsZCB0LnN0YXQoKSxyPW5ldyBnYSh0LGUpO2lmKGU+PUIwJiZNZCh5aWVsZCByLnJlYWRBdCgwLE1jKzcmLTgpKSlyZXR1cm4gbmV3IFVkKG5ldyBOMChyKSk7cmV0dXJuIG5ldyB2YShuZXcgaXUocikpfSl9dmFyIGhyLE9zLHZhLElhLFVkLG51LGl1LEN5LE4wLEYwO3ZhciBSZD1tKCgpPT57cG4oKTtYbigpO1FyKCk7aWUoKTtMZSgpO1dtKCk7QWwoKTt5YSgpO19hKCk7S20oKTskdigpO05vKCk7V2woKTtMeSgpO1V5KCk7TnQoKTtocj1jbGFzcyBociBleHRlbmRzIEFje2NvbnN0cnVjdG9yKHQpe3N1cGVyKCk7dGhpcy5faW1wbD10fWdldCBjbG9zZWQoKXtyZXR1cm4gdGhpcy5faW1wbC5jbG9zZWR9Z2V0IHNjaGVtYSgpe3JldHVybiB0aGlzLl9pbXBsLnNjaGVtYX1nZXQgYXV0b0Rlc3Ryb3koKXtyZXR1cm4gdGhpcy5faW1wbC5hdXRvRGVzdHJveX1nZXQgZGljdGlvbmFyaWVzKCl7cmV0dXJuIHRoaXMuX2ltcGwuZGljdGlvbmFyaWVzfWdldCBudW1EaWN0aW9uYXJpZXMoKXtyZXR1cm4gdGhpcy5faW1wbC5udW1EaWN0aW9uYXJpZXN9Z2V0IG51bVJlY29yZEJhdGNoZXMoKXtyZXR1cm4gdGhpcy5faW1wbC5udW1SZWNvcmRCYXRjaGVzfWdldCBmb290ZXIoKXtyZXR1cm4gdGhpcy5faW1wbC5pc0ZpbGUoKT90aGlzLl9pbXBsLmZvb3RlcjpudWxsfWlzU3luYygpe3JldHVybiB0aGlzLl9pbXBsLmlzU3luYygpfWlzQXN5bmMoKXtyZXR1cm4gdGhpcy5faW1wbC5pc0FzeW5jKCl9aXNGaWxlKCl7cmV0dXJuIHRoaXMuX2ltcGwuaXNGaWxlKCl9aXNTdHJlYW0oKXtyZXR1cm4gdGhpcy5faW1wbC5pc1N0cmVhbSgpfW5leHQoKXtyZXR1cm4gdGhpcy5faW1wbC5uZXh0KCl9dGhyb3codCl7cmV0dXJuIHRoaXMuX2ltcGwudGhyb3codCl9cmV0dXJuKHQpe3JldHVybiB0aGlzLl9pbXBsLnJldHVybih0KX1jYW5jZWwoKXtyZXR1cm4gdGhpcy5faW1wbC5jYW5jZWwoKX1yZXNldCh0KXtyZXR1cm4gdGhpcy5faW1wbC5yZXNldCh0KSx0aGlzLl9ET01TdHJlYW09dm9pZCAwLHRoaXMuX25vZGVTdHJlYW09dm9pZCAwLHRoaXN9b3Blbih0KXtsZXQgZT10aGlzLl9pbXBsLm9wZW4odCk7cmV0dXJuIGJpKGUpP2UudGhlbigoKT0+dGhpcyk6dGhpc31yZWFkUmVjb3JkQmF0Y2godCl7cmV0dXJuIHRoaXMuX2ltcGwuaXNGaWxlKCk/dGhpcy5faW1wbC5yZWFkUmVjb3JkQmF0Y2godCk6bnVsbH1bU3ltYm9sLml0ZXJhdG9yXSgpe3JldHVybiB0aGlzLl9pbXBsW1N5bWJvbC5pdGVyYXRvcl0oKX1bU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCl7cmV0dXJuIHRoaXMuX2ltcGxbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCl9dG9ET01TdHJlYW0oKXtyZXR1cm4gY3IudG9ET01TdHJlYW0odGhpcy5pc1N5bmMoKT97W1N5bWJvbC5pdGVyYXRvcl06KCk9PnRoaXN9OntbU3ltYm9sLmFzeW5jSXRlcmF0b3JdOigpPT50aGlzfSl9dG9Ob2RlU3RyZWFtKCl7cmV0dXJuIGNyLnRvTm9kZVN0cmVhbSh0aGlzLmlzU3luYygpP3tbU3ltYm9sLml0ZXJhdG9yXTooKT0+dGhpc306e1tTeW1ib2wuYXN5bmNJdGVyYXRvcl06KCk9PnRoaXN9LHtvYmplY3RNb2RlOiEwfSl9c3RhdGljIHRocm91Z2hOb2RlKHQpe3Rocm93IEVycm9yKCcidGhyb3VnaE5vZGUiIG5vdCBhdmFpbGFibGUgaW4gdGhpcyBlbnZpcm9ubWVudCcpfXN0YXRpYyB0aHJvdWdoRE9NKHQsZSl7dGhyb3cgRXJyb3IoJyJ0aHJvdWdoRE9NIiBub3QgYXZhaWxhYmxlIGluIHRoaXMgZW52aXJvbm1lbnQnKX1zdGF0aWMgZnJvbSh0KXtpZih0IGluc3RhbmNlb2YgaHIpcmV0dXJuIHQ7ZWxzZSBpZihuZih0KSlyZXR1cm4gY0UodCk7ZWxzZSBpZihvZih0KSlyZXR1cm4gZkUodCk7ZWxzZSBpZihiaSh0KSlyZXR1cm4oKCk9PkUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3JldHVybiB5aWVsZCBoci5mcm9tKHlpZWxkIHQpfSkpKCk7ZWxzZSBpZihhZih0KXx8QmwodCl8fGxmKHQpfHxWbih0KSlyZXR1cm4gdUUobmV3IFpuKHQpKTtyZXR1cm4gbEUobmV3IERzKHQpKX1zdGF0aWMgcmVhZEFsbCh0KXtpZih0IGluc3RhbmNlb2YgaHIpcmV0dXJuIHQuaXNTeW5jKCk/RTAodCk6TzAodCk7ZWxzZSBpZihuZih0KXx8QXJyYXlCdWZmZXIuaXNWaWV3KHQpfHx3aSh0KXx8c2YodCkpcmV0dXJuIEUwKHQpO3JldHVybiBPMCh0KX19O09zPWNsYXNzIE9zIGV4dGVuZHMgaHJ7Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5faW1wbD10fXJlYWRBbGwoKXtyZXR1cm5bLi4udGhpc119W1N5bWJvbC5pdGVyYXRvcl0oKXtyZXR1cm4gdGhpcy5faW1wbFtTeW1ib2wuaXRlcmF0b3JdKCl9W1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpe3JldHVybiBobih0aGlzLGFyZ3VtZW50cyxmdW5jdGlvbiooKXt5aWVsZCB5dCh5aWVsZCppYyhnaSh0aGlzW1N5bWJvbC5pdGVyYXRvcl0oKSkpKX0pfX07dmE9Y2xhc3MgdmEgZXh0ZW5kcyBocntjb25zdHJ1Y3Rvcih0KXtzdXBlcih0KTt0aGlzLl9pbXBsPXR9cmVhZEFsbCgpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXt2YXIgdCxlLHIsbjtsZXQgaT1bXTt0cnl7Zm9yKHZhciBzPSEwLG89Z2kodGhpcyksYTthPXlpZWxkIG8ubmV4dCgpLHQ9YS5kb25lLCF0O3M9ITApe249YS52YWx1ZSxzPSExO2xldCBsPW47aS5wdXNoKGwpfX1jYXRjaChsKXtlPXtlcnJvcjpsfX1maW5hbGx5e3RyeXtpZighcyYmIXQmJihyPW8ucmV0dXJuKSl5aWVsZCByLmNhbGwobyl9ZmluYWxseXtpZihlKXRocm93IGUuZXJyb3J9fXJldHVybiBpfSl9W1N5bWJvbC5pdGVyYXRvcl0oKXt0aHJvdyBFcnJvcigiQXN5bmNSZWNvcmRCYXRjaFN0cmVhbVJlYWRlciBpcyBub3QgSXRlcmFibGUiKX1bU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCl7cmV0dXJuIHRoaXMuX2ltcGxbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCl9fTtJYT1jbGFzcyBJYSBleHRlbmRzIE9ze2NvbnN0cnVjdG9yKHQpe3N1cGVyKHQpO3RoaXMuX2ltcGw9dH19O1VkPWNsYXNzIFVkIGV4dGVuZHMgdmF7Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5faW1wbD10fX07bnU9Y2xhc3MgbnUgZXh0ZW5kcyBSeXtjb25zdHJ1Y3Rvcih0LGUpe3N1cGVyKGUpO3RoaXMuX3JlYWRlcj0hbmYodCk/bmV3IGV1KHRoaXMuX2hhbmRsZT10KTpuZXcgTmQodGhpcy5faGFuZGxlPXQpfWlzU3luYygpe3JldHVybiEwfWlzU3RyZWFtKCl7cmV0dXJuITB9W1N5bWJvbC5pdGVyYXRvcl0oKXtyZXR1cm4gdGhpc31jYW5jZWwoKXtpZighdGhpcy5jbG9zZWQmJih0aGlzLmNsb3NlZD0hMCkpdGhpcy5yZXNldCgpLl9yZWFkZXIucmV0dXJuKCksdGhpcy5fcmVhZGVyPW51bGwsdGhpcy5kaWN0aW9uYXJpZXM9bnVsbH1vcGVuKHQpe2lmKCF0aGlzLmNsb3NlZCl7aWYodGhpcy5hdXRvRGVzdHJveT1NMCh0aGlzLHQpLCEodGhpcy5zY2hlbWF8fCh0aGlzLnNjaGVtYT10aGlzLl9yZWFkZXIucmVhZFNjaGVtYSgpKSkpdGhpcy5jYW5jZWwoKX1yZXR1cm4gdGhpc310aHJvdyh0KXtpZighdGhpcy5jbG9zZWQmJnRoaXMuYXV0b0Rlc3Ryb3kmJih0aGlzLmNsb3NlZD0hMCkpcmV0dXJuIHRoaXMucmVzZXQoKS5fcmVhZGVyLnRocm93KHQpO3JldHVybiBmZX1yZXR1cm4odCl7aWYoIXRoaXMuY2xvc2VkJiZ0aGlzLmF1dG9EZXN0cm95JiYodGhpcy5jbG9zZWQ9ITApKXJldHVybiB0aGlzLnJlc2V0KCkuX3JlYWRlci5yZXR1cm4odCk7cmV0dXJuIGZlfW5leHQoKXtpZih0aGlzLmNsb3NlZClyZXR1cm4gZmU7bGV0IHQse19yZWFkZXI6ZX09dGhpczt3aGlsZSh0PXRoaXMuX3JlYWROZXh0TWVzc2FnZUFuZFZhbGlkYXRlKCkpaWYodC5pc1NjaGVtYSgpKXRoaXMucmVzZXQodC5oZWFkZXIoKSk7ZWxzZSBpZih0LmlzUmVjb3JkQmF0Y2goKSl7dGhpcy5fcmVjb3JkQmF0Y2hJbmRleCsrO2xldCByPXQuaGVhZGVyKCksbj1lLnJlYWRNZXNzYWdlQm9keSh0LmJvZHlMZW5ndGgpO3JldHVybntkb25lOiExLHZhbHVlOnRoaXMuX2xvYWRSZWNvcmRCYXRjaChyLG4sdC5tZXRhZGF0YSl9fWVsc2UgaWYodC5pc0RpY3Rpb25hcnlCYXRjaCgpKXt0aGlzLl9kaWN0aW9uYXJ5SW5kZXgrKztsZXQgcj10LmhlYWRlcigpLG49ZS5yZWFkTWVzc2FnZUJvZHkodC5ib2R5TGVuZ3RoKSxpPXRoaXMuX2xvYWREaWN0aW9uYXJ5QmF0Y2gocixuKTt0aGlzLmRpY3Rpb25hcmllcy5zZXQoci5pZCxpKX1pZih0aGlzLnNjaGVtYSYmdGhpcy5fcmVjb3JkQmF0Y2hJbmRleD09PTApcmV0dXJuIHRoaXMuX3JlY29yZEJhdGNoSW5kZXgrKyx7ZG9uZTohMSx2YWx1ZTpuZXcgTmModGhpcy5zY2hlbWEpfTtyZXR1cm4gdGhpcy5yZXR1cm4oKX1fcmVhZE5leHRNZXNzYWdlQW5kVmFsaWRhdGUodCl7cmV0dXJuIHRoaXMuX3JlYWRlci5yZWFkTWVzc2FnZSh0KX19O2l1PWNsYXNzIGl1IGV4dGVuZHMgUnl7Y29uc3RydWN0b3IodCxlKXtzdXBlcihlKTt0aGlzLl9yZWFkZXI9bmV3IE9kKHRoaXMuX2hhbmRsZT10KX1pc0FzeW5jKCl7cmV0dXJuITB9aXNTdHJlYW0oKXtyZXR1cm4hMH1bU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCl7cmV0dXJuIHRoaXN9Y2FuY2VsKCl7cmV0dXJuIEUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe2lmKCF0aGlzLmNsb3NlZCYmKHRoaXMuY2xvc2VkPSEwKSl5aWVsZCB0aGlzLnJlc2V0KCkuX3JlYWRlci5yZXR1cm4oKSx0aGlzLl9yZWFkZXI9bnVsbCx0aGlzLmRpY3Rpb25hcmllcz1udWxsfSl9b3Blbih0KXtyZXR1cm4gRSh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7aWYoIXRoaXMuY2xvc2VkKXtpZih0aGlzLmF1dG9EZXN0cm95PU0wKHRoaXMsdCksISh0aGlzLnNjaGVtYXx8KHRoaXMuc2NoZW1hPXlpZWxkIHRoaXMuX3JlYWRlci5yZWFkU2NoZW1hKCkpKSl5aWVsZCB0aGlzLmNhbmNlbCgpfXJldHVybiB0aGlzfSl9dGhyb3codCl7cmV0dXJuIEUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe2lmKCF0aGlzLmNsb3NlZCYmdGhpcy5hdXRvRGVzdHJveSYmKHRoaXMuY2xvc2VkPSEwKSlyZXR1cm4geWllbGQgdGhpcy5yZXNldCgpLl9yZWFkZXIudGhyb3codCk7cmV0dXJuIGZlfSl9cmV0dXJuKHQpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtpZighdGhpcy5jbG9zZWQmJnRoaXMuYXV0b0Rlc3Ryb3kmJih0aGlzLmNsb3NlZD0hMCkpcmV0dXJuIHlpZWxkIHRoaXMucmVzZXQoKS5fcmVhZGVyLnJldHVybih0KTtyZXR1cm4gZmV9KX1uZXh0KCl7cmV0dXJuIEUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe2lmKHRoaXMuY2xvc2VkKXJldHVybiBmZTtsZXQgdCx7X3JlYWRlcjplfT10aGlzO3doaWxlKHQ9eWllbGQgdGhpcy5fcmVhZE5leHRNZXNzYWdlQW5kVmFsaWRhdGUoKSlpZih0LmlzU2NoZW1hKCkpeWllbGQgdGhpcy5yZXNldCh0LmhlYWRlcigpKTtlbHNlIGlmKHQuaXNSZWNvcmRCYXRjaCgpKXt0aGlzLl9yZWNvcmRCYXRjaEluZGV4Kys7bGV0IHI9dC5oZWFkZXIoKSxuPXlpZWxkIGUucmVhZE1lc3NhZ2VCb2R5KHQuYm9keUxlbmd0aCk7cmV0dXJue2RvbmU6ITEsdmFsdWU6dGhpcy5fbG9hZFJlY29yZEJhdGNoKHIsbix0Lm1ldGFkYXRhKX19ZWxzZSBpZih0LmlzRGljdGlvbmFyeUJhdGNoKCkpe3RoaXMuX2RpY3Rpb25hcnlJbmRleCsrO2xldCByPXQuaGVhZGVyKCksbj15aWVsZCBlLnJlYWRNZXNzYWdlQm9keSh0LmJvZHlMZW5ndGgpLGk9dGhpcy5fbG9hZERpY3Rpb25hcnlCYXRjaChyLG4pO3RoaXMuZGljdGlvbmFyaWVzLnNldChyLmlkLGkpfWlmKHRoaXMuc2NoZW1hJiZ0aGlzLl9yZWNvcmRCYXRjaEluZGV4PT09MClyZXR1cm4gdGhpcy5fcmVjb3JkQmF0Y2hJbmRleCsrLHtkb25lOiExLHZhbHVlOm5ldyBOYyh0aGlzLnNjaGVtYSl9O3JldHVybiB5aWVsZCB0aGlzLnJldHVybigpfSl9X3JlYWROZXh0TWVzc2FnZUFuZFZhbGlkYXRlKHQpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtyZXR1cm4geWllbGQgdGhpcy5fcmVhZGVyLnJlYWRNZXNzYWdlKHQpfSl9fTtDeT1jbGFzcyBDeSBleHRlbmRzIG51e2dldCBmb290ZXIoKXtyZXR1cm4gdGhpcy5fZm9vdGVyfWdldCBudW1EaWN0aW9uYXJpZXMoKXtyZXR1cm4gdGhpcy5fZm9vdGVyP3RoaXMuX2Zvb3Rlci5udW1EaWN0aW9uYXJpZXM6MH1nZXQgbnVtUmVjb3JkQmF0Y2hlcygpe3JldHVybiB0aGlzLl9mb290ZXI/dGhpcy5fZm9vdGVyLm51bVJlY29yZEJhdGNoZXM6MH1jb25zdHJ1Y3Rvcih0LGUpe3N1cGVyKHQgaW5zdGFuY2VvZiB0ZD90Om5ldyB0ZCh0KSxlKX1pc1N5bmMoKXtyZXR1cm4hMH1pc0ZpbGUoKXtyZXR1cm4hMH1vcGVuKHQpe2lmKCF0aGlzLmNsb3NlZCYmIXRoaXMuX2Zvb3Rlcil7dGhpcy5zY2hlbWE9KHRoaXMuX2Zvb3Rlcj10aGlzLl9yZWFkRm9vdGVyKCkpLnNjaGVtYTtmb3IobGV0IGUgb2YgdGhpcy5fZm9vdGVyLmRpY3Rpb25hcnlCYXRjaGVzKCkpZSYmdGhpcy5fcmVhZERpY3Rpb25hcnlCYXRjaCh0aGlzLl9kaWN0aW9uYXJ5SW5kZXgrKyl9cmV0dXJuIHN1cGVyLm9wZW4odCl9cmVhZFJlY29yZEJhdGNoKHQpe3ZhciBlO2lmKHRoaXMuY2xvc2VkKXJldHVybiBudWxsO2lmKCF0aGlzLl9mb290ZXIpdGhpcy5vcGVuKCk7bGV0IHI9KGU9dGhpcy5fZm9vdGVyKT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUuZ2V0UmVjb3JkQmF0Y2godCk7aWYociYmdGhpcy5faGFuZGxlLnNlZWsoci5vZmZzZXQpKXtsZXQgbj10aGlzLl9yZWFkZXIucmVhZE1lc3NhZ2UoeHQuUmVjb3JkQmF0Y2gpO2lmKG49PT1udWxsfHxuPT09dm9pZCAwP3ZvaWQgMDpuLmlzUmVjb3JkQmF0Y2goKSl7bGV0IGk9bi5oZWFkZXIoKSxzPXRoaXMuX3JlYWRlci5yZWFkTWVzc2FnZUJvZHkobi5ib2R5TGVuZ3RoKTtyZXR1cm4gdGhpcy5fbG9hZFJlY29yZEJhdGNoKGkscyxuLm1ldGFkYXRhKX19cmV0dXJuIG51bGx9X3JlYWREaWN0aW9uYXJ5QmF0Y2godCl7dmFyIGU7bGV0IHI9KGU9dGhpcy5fZm9vdGVyKT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUuZ2V0RGljdGlvbmFyeUJhdGNoKHQpO2lmKHImJnRoaXMuX2hhbmRsZS5zZWVrKHIub2Zmc2V0KSl7bGV0IG49dGhpcy5fcmVhZGVyLnJlYWRNZXNzYWdlKHh0LkRpY3Rpb25hcnlCYXRjaCk7aWYobj09PW51bGx8fG49PT12b2lkIDA/dm9pZCAwOm4uaXNEaWN0aW9uYXJ5QmF0Y2goKSl7bGV0IGk9bi5oZWFkZXIoKSxzPXRoaXMuX3JlYWRlci5yZWFkTWVzc2FnZUJvZHkobi5ib2R5TGVuZ3RoKSxvPXRoaXMuX2xvYWREaWN0aW9uYXJ5QmF0Y2goaSxzKTt0aGlzLmRpY3Rpb25hcmllcy5zZXQoaS5pZCxvKX19fV9yZWFkRm9vdGVyKCl7bGV0e19oYW5kbGU6dH09dGhpcyxlPXQuc2l6ZS1NeSxyPXQucmVhZEludDMyKGUpLG49dC5yZWFkQXQoZS1yLHIpO3JldHVybiBEby5kZWNvZGUobil9X3JlYWROZXh0TWVzc2FnZUFuZFZhbGlkYXRlKHQpe3ZhciBlO2lmKCF0aGlzLl9mb290ZXIpdGhpcy5vcGVuKCk7aWYodGhpcy5fZm9vdGVyJiZ0aGlzLl9yZWNvcmRCYXRjaEluZGV4PHRoaXMubnVtUmVjb3JkQmF0Y2hlcyl7bGV0IHI9KGU9dGhpcy5fZm9vdGVyKT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUuZ2V0UmVjb3JkQmF0Y2godGhpcy5fcmVjb3JkQmF0Y2hJbmRleCk7aWYociYmdGhpcy5faGFuZGxlLnNlZWsoci5vZmZzZXQpKXJldHVybiB0aGlzLl9yZWFkZXIucmVhZE1lc3NhZ2UodCl9cmV0dXJuIG51bGx9fTtOMD1jbGFzcyBOMCBleHRlbmRzIGl1e2dldCBmb290ZXIoKXtyZXR1cm4gdGhpcy5fZm9vdGVyfWdldCBudW1EaWN0aW9uYXJpZXMoKXtyZXR1cm4gdGhpcy5fZm9vdGVyP3RoaXMuX2Zvb3Rlci5udW1EaWN0aW9uYXJpZXM6MH1nZXQgbnVtUmVjb3JkQmF0Y2hlcygpe3JldHVybiB0aGlzLl9mb290ZXI/dGhpcy5fZm9vdGVyLm51bVJlY29yZEJhdGNoZXM6MH1jb25zdHJ1Y3Rvcih0LC4uLmUpe2xldCByPXR5cGVvZiBlWzBdIT09Im51bWJlciI/ZS5zaGlmdCgpOnZvaWQgMCxuPWVbMF1pbnN0YW5jZW9mIE1hcD9lLnNoaWZ0KCk6dm9pZCAwO3N1cGVyKHQgaW5zdGFuY2VvZiBnYT90Om5ldyBnYSh0LHIpLG4pfWlzRmlsZSgpe3JldHVybiEwfWlzQXN5bmMoKXtyZXR1cm4hMH1vcGVuKHQpe2xldCBlPU9iamVjdC5jcmVhdGUobnVsbCx7b3Blbjp7Z2V0OigpPT5zdXBlci5vcGVufX0pO3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtpZighdGhpcy5jbG9zZWQmJiF0aGlzLl9mb290ZXIpe3RoaXMuc2NoZW1hPSh0aGlzLl9mb290ZXI9eWllbGQgdGhpcy5fcmVhZEZvb3RlcigpKS5zY2hlbWE7Zm9yKGxldCByIG9mIHRoaXMuX2Zvb3Rlci5kaWN0aW9uYXJ5QmF0Y2hlcygpKXImJih5aWVsZCB0aGlzLl9yZWFkRGljdGlvbmFyeUJhdGNoKHRoaXMuX2RpY3Rpb25hcnlJbmRleCsrKSl9cmV0dXJuIHlpZWxkIGUub3Blbi5jYWxsKHRoaXMsdCl9KX1yZWFkUmVjb3JkQmF0Y2godCl7cmV0dXJuIEUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3ZhciBlO2lmKHRoaXMuY2xvc2VkKXJldHVybiBudWxsO2lmKCF0aGlzLl9mb290ZXIpeWllbGQgdGhpcy5vcGVuKCk7bGV0IHI9KGU9dGhpcy5fZm9vdGVyKT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUuZ2V0UmVjb3JkQmF0Y2godCk7aWYociYmKHlpZWxkIHRoaXMuX2hhbmRsZS5zZWVrKHIub2Zmc2V0KSkpe2xldCBuPXlpZWxkIHRoaXMuX3JlYWRlci5yZWFkTWVzc2FnZSh4dC5SZWNvcmRCYXRjaCk7aWYobj09PW51bGx8fG49PT12b2lkIDA/dm9pZCAwOm4uaXNSZWNvcmRCYXRjaCgpKXtsZXQgaT1uLmhlYWRlcigpLHM9eWllbGQgdGhpcy5fcmVhZGVyLnJlYWRNZXNzYWdlQm9keShuLmJvZHlMZW5ndGgpO3JldHVybiB0aGlzLl9sb2FkUmVjb3JkQmF0Y2goaSxzLG4ubWV0YWRhdGEpfX1yZXR1cm4gbnVsbH0pfV9yZWFkRGljdGlvbmFyeUJhdGNoKHQpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXt2YXIgZTtsZXQgcj0oZT10aGlzLl9mb290ZXIpPT09bnVsbHx8ZT09PXZvaWQgMD92b2lkIDA6ZS5nZXREaWN0aW9uYXJ5QmF0Y2godCk7aWYociYmKHlpZWxkIHRoaXMuX2hhbmRsZS5zZWVrKHIub2Zmc2V0KSkpe2xldCBuPXlpZWxkIHRoaXMuX3JlYWRlci5yZWFkTWVzc2FnZSh4dC5EaWN0aW9uYXJ5QmF0Y2gpO2lmKG49PT1udWxsfHxuPT09dm9pZCAwP3ZvaWQgMDpuLmlzRGljdGlvbmFyeUJhdGNoKCkpe2xldCBpPW4uaGVhZGVyKCkscz15aWVsZCB0aGlzLl9yZWFkZXIucmVhZE1lc3NhZ2VCb2R5KG4uYm9keUxlbmd0aCksbz10aGlzLl9sb2FkRGljdGlvbmFyeUJhdGNoKGkscyk7dGhpcy5kaWN0aW9uYXJpZXMuc2V0KGkuaWQsbyl9fX0pfV9yZWFkRm9vdGVyKCl7cmV0dXJuIEUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe2xldHtfaGFuZGxlOnR9PXRoaXM7dC5fcGVuZGluZyYmKHlpZWxkIHQuX3BlbmRpbmcpO2xldCBlPXQuc2l6ZS1NeSxyPXlpZWxkIHQucmVhZEludDMyKGUpLG49eWllbGQgdC5yZWFkQXQoZS1yLHIpO3JldHVybiBEby5kZWNvZGUobil9KX1fcmVhZE5leHRNZXNzYWdlQW5kVmFsaWRhdGUodCl7cmV0dXJuIEUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe2lmKCF0aGlzLl9mb290ZXIpeWllbGQgdGhpcy5vcGVuKCk7aWYodGhpcy5fZm9vdGVyJiZ0aGlzLl9yZWNvcmRCYXRjaEluZGV4PHRoaXMubnVtUmVjb3JkQmF0Y2hlcyl7bGV0IGU9dGhpcy5fZm9vdGVyLmdldFJlY29yZEJhdGNoKHRoaXMuX3JlY29yZEJhdGNoSW5kZXgpO2lmKGUmJih5aWVsZCB0aGlzLl9oYW5kbGUuc2VlayhlLm9mZnNldCkpKXJldHVybiB5aWVsZCB0aGlzLl9yZWFkZXIucmVhZE1lc3NhZ2UodCl9cmV0dXJuIG51bGx9KX19O0YwPWNsYXNzIEYwIGV4dGVuZHMgbnV7Y29uc3RydWN0b3IodCxlKXtzdXBlcih0LGUpfV9sb2FkVmVjdG9ycyh0LGUscil7cmV0dXJuIG5ldyBleShlLHQubm9kZXMsdC5idWZmZXJzLHRoaXMuZGljdGlvbmFyaWVzLHRoaXMuc2NoZW1hLm1ldGFkYXRhVmVyc2lvbix0LnZhcmlhZGljQnVmZmVyQ291bnRzKS52aXNpdE1hbnkocil9fX0pO2Z1bmN0aW9uIHhuKHQpe2xldCBlPXQuYnl0ZUxlbmd0aCs3Ji04O3JldHVybiB0aGlzLmJ1ZmZlcnMucHVzaCh0KSx0aGlzLmJ1ZmZlclJlZ2lvbnMucHVzaChuZXcgeGUodGhpcy5fYnl0ZUxlbmd0aCxlKSksdGhpcy5fYnl0ZUxlbmd0aCs9ZSx0aGlzfWZ1bmN0aW9uIGRFKHQpe3ZhciBlO2xldHt0eXBlOnIsbGVuZ3RoOm4sdHlwZUlkczppLHZhbHVlT2Zmc2V0czpzfT10O2lmKHhuLmNhbGwodGhpcyxpKSxyLm1vZGU9PT1MdC5TcGFyc2UpcmV0dXJuIFB5LmNhbGwodGhpcyx0KTtlbHNlIGlmKHIubW9kZT09PUx0LkRlbnNlKWlmKHQub2Zmc2V0PD0wKXJldHVybiB4bi5jYWxsKHRoaXMscyksUHkuY2FsbCh0aGlzLHQpO2Vsc2V7bGV0IG89bmV3IEludDMyQXJyYXkobiksYT1PYmplY3QuY3JlYXRlKG51bGwpLGw9T2JqZWN0LmNyZWF0ZShudWxsKTtmb3IobGV0IHUsZixwPS0xOysrcDxuOyl7aWYoKHU9aVtwXSk9PT12b2lkIDApY29udGludWU7aWYoKGY9YVt1XSk9PT12b2lkIDApZj1hW3VdPXNbcF07b1twXT1zW3BdLWYsbFt1XT0oKGU9bFt1XSkhPT1udWxsJiZlIT09dm9pZCAwP2U6MCkrMX14bi5jYWxsKHRoaXMsbyksdGhpcy52aXNpdE1hbnkodC5jaGlsZHJlbi5tYXAoKHUsZik9PntsZXQgcD1yLnR5cGVJZHNbZl0sZz1hW3BdLHY9bFtwXTtyZXR1cm4gdS5zbGljZShnLE1hdGgubWluKG4sdikpfSkpfXJldHVybiB0aGlzfWZ1bmN0aW9uIGhFKHQpe2xldCBlO2lmKHQubnVsbENvdW50Pj10Lmxlbmd0aClyZXR1cm4geG4uY2FsbCh0aGlzLG5ldyBVaW50OEFycmF5KHQubGVuZ3RoKzc+PjMpKTtlbHNlIGlmKChlPXQudmFsdWVzKWluc3RhbmNlb2YgVWludDhBcnJheSlyZXR1cm4geG4uY2FsbCh0aGlzLGRhKHQub2Zmc2V0LHQubGVuZ3RoLGUpKTtyZXR1cm4geG4uY2FsbCh0aGlzLGhhKHQudmFsdWVzKSl9ZnVuY3Rpb24gTnModCl7cmV0dXJuIHhuLmNhbGwodGhpcyx0LnZhbHVlcy5zdWJhcnJheSgwLHQubGVuZ3RoKnQuc3RyaWRlKSl9ZnVuY3Rpb24gQ2QodCl7bGV0e2xlbmd0aDplLHZhbHVlczpyLHZhbHVlT2Zmc2V0czpufT10LGk9UHQoblswXSkscz1QdChuW2VdKSxvPU1hdGgubWluKHMtaSxyLmJ5dGVMZW5ndGgtaSk7cmV0dXJuIHhuLmNhbGwodGhpcyxmZigtaSxlKzEsbikpLHhuLmNhbGwodGhpcyxyLnN1YmFycmF5KGksaStvKSksdGhpc31mdW5jdGlvbiBMMCh0KXtsZXR7b2Zmc2V0OmUsbGVuZ3RoOnIsc3RyaWRlOm4sdmFsdWVzOmksdmFyaWFkaWNCdWZmZXJzOnM9W119PXQ7aWYoIWkpdGhyb3cgRXJyb3IoIkJpbmFyeVZpZXcgZGF0YSBpcyBtaXNzaW5nIHZpZXcgYnVmZmVyIik7bGV0IG89ZSpuLGE9bytyKm47eG4uY2FsbCh0aGlzLGkuc3ViYXJyYXkobyxhKSk7Zm9yKGxldCBsIG9mIHMpeG4uY2FsbCh0aGlzLGwpO3JldHVybiB0aGlzLl92YXJpYWRpY0J1ZmZlckNvdW50cy5wdXNoKHMubGVuZ3RoKSx0aGlzfWZ1bmN0aW9uIGt5KHQpe2xldHtsZW5ndGg6ZSx2YWx1ZU9mZnNldHM6cn09dDtpZihyKXtsZXR7WzBdOm4sW2VdOml9PXI7cmV0dXJuIHhuLmNhbGwodGhpcyxmZigtbixlKzEscikpLHRoaXMudmlzaXQodC5jaGlsZHJlblswXS5zbGljZShuLGktbikpfXJldHVybiB0aGlzLnZpc2l0KHQuY2hpbGRyZW5bMF0pfWZ1bmN0aW9uIFB5KHQpe3JldHVybiB0aGlzLnZpc2l0TWFueSh0LnR5cGUuY2hpbGRyZW4ubWFwKChlLHIpPT50LmNoaWxkcmVuW3JdKS5maWx0ZXIoQm9vbGVhbikpWzBdfXZhciBtZTt2YXIgVTA9bSgoKT0+e1FyKCk7VWkoKTtMZSgpO05vKCk7amUoKTt3YygpO3lhKCk7aWUoKTttZT1jbGFzcyBtZSBleHRlbmRzIGV0e3N0YXRpYyBhc3NlbWJsZSguLi50KXtsZXQgZT0obik9Pm4uZmxhdE1hcCgoaSk9PkFycmF5LmlzQXJyYXkoaSk/ZShpKTppIGluc3RhbmNlb2YgQXQ/aS5kYXRhLmNoaWxkcmVuOmkuZGF0YSkscj1uZXcgbWU7cmV0dXJuIHIudmlzaXRNYW55KGUodCkpLHJ9Y29uc3RydWN0b3IoKXtzdXBlcigpO3RoaXMuX2J5dGVMZW5ndGg9MCx0aGlzLl9ub2Rlcz1bXSx0aGlzLl9idWZmZXJzPVtdLHRoaXMuX2J1ZmZlclJlZ2lvbnM9W10sdGhpcy5fdmFyaWFkaWNCdWZmZXJDb3VudHM9W119dmlzaXQodCl7aWYodCBpbnN0YW5jZW9mIE4pcmV0dXJuIHRoaXMudmlzaXRNYW55KHQuZGF0YSksdGhpcztsZXR7dHlwZTplfT10O2lmKCFCLmlzRGljdGlvbmFyeShlKSl7bGV0e2xlbmd0aDpyfT10O2lmKHI+MjE0NzQ4MzY0Nyl0aHJvdyBSYW5nZUVycm9yKCJDYW5ub3Qgd3JpdGUgYXJyYXlzIGxhcmdlciB0aGFuIDJeMzEgLSAxIGluIGxlbmd0aCIpO2lmKEIuaXNVbmlvbihlKSl0aGlzLm5vZGVzLnB1c2gobmV3IENpKHIsMCkpO2Vsc2V7bGV0e251bGxDb3VudDpufT10O2lmKCFCLmlzTnVsbChlKSl4bi5jYWxsKHRoaXMsbjw9MD9uZXcgVWludDhBcnJheSgwKTpkYSh0Lm9mZnNldCxyLHQubnVsbEJpdG1hcCkpO3RoaXMubm9kZXMucHVzaChuZXcgQ2kocixuKSl9fXJldHVybiBzdXBlci52aXNpdCh0KX12aXNpdE51bGwodCl7cmV0dXJuIHRoaXN9dmlzaXREaWN0aW9uYXJ5KHQpe3JldHVybiB0aGlzLnZpc2l0KHQuY2xvbmUodC50eXBlLmluZGljZXMpKX1nZXQgbm9kZXMoKXtyZXR1cm4gdGhpcy5fbm9kZXN9Z2V0IGJ1ZmZlcnMoKXtyZXR1cm4gdGhpcy5fYnVmZmVyc31nZXQgYnl0ZUxlbmd0aCgpe3JldHVybiB0aGlzLl9ieXRlTGVuZ3RofWdldCBidWZmZXJSZWdpb25zKCl7cmV0dXJuIHRoaXMuX2J1ZmZlclJlZ2lvbnN9Z2V0IHZhcmlhZGljQnVmZmVyQ291bnRzKCl7cmV0dXJuIHRoaXMuX3ZhcmlhZGljQnVmZmVyQ291bnRzfX07bWUucHJvdG90eXBlLnZpc2l0Qm9vbD1oRTttZS5wcm90b3R5cGUudmlzaXRJbnQ9TnM7bWUucHJvdG90eXBlLnZpc2l0RmxvYXQ9TnM7bWUucHJvdG90eXBlLnZpc2l0VXRmOD1DZDttZS5wcm90b3R5cGUudmlzaXRMYXJnZVV0Zjg9Q2Q7bWUucHJvdG90eXBlLnZpc2l0VXRmOFZpZXc9TDA7bWUucHJvdG90eXBlLnZpc2l0QmluYXJ5PUNkO21lLnByb3RvdHlwZS52aXNpdExhcmdlQmluYXJ5PUNkO21lLnByb3RvdHlwZS52aXNpdEJpbmFyeVZpZXc9TDA7bWUucHJvdG90eXBlLnZpc2l0Rml4ZWRTaXplQmluYXJ5PU5zO21lLnByb3RvdHlwZS52aXNpdERhdGU9TnM7bWUucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wPU5zO21lLnByb3RvdHlwZS52aXNpdFRpbWU9TnM7bWUucHJvdG90eXBlLnZpc2l0RGVjaW1hbD1OczttZS5wcm90b3R5cGUudmlzaXRMaXN0PWt5O21lLnByb3RvdHlwZS52aXNpdFN0cnVjdD1QeTttZS5wcm90b3R5cGUudmlzaXRVbmlvbj1kRTttZS5wcm90b3R5cGUudmlzaXRJbnRlcnZhbD1OczttZS5wcm90b3R5cGUudmlzaXREdXJhdGlvbj1OczttZS5wcm90b3R5cGUudmlzaXRGaXhlZFNpemVMaXN0PWt5O21lLnByb3RvdHlwZS52aXNpdE1hcD1reX0pO2Z1bmN0aW9uIFZ5KHQsZSl7bGV0IHI9ZTtpZihlIGluc3RhbmNlb2YgVGUpcj1lLmJhdGNoZXMsdC5yZXNldCh2b2lkIDAsZS5zY2hlbWEpO2ZvcihsZXQgbiBvZiByKXQud3JpdGUobik7cmV0dXJuIHQuZmluaXNoKCl9ZnVuY3Rpb24genkodCxlKXtyZXR1cm4gRSh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7dmFyIHIsbixpLHMsbyxhLGw7dHJ5e2ZvcihyPSEwLG49Z2koZSk7aT15aWVsZCBuLm5leHQoKSxzPWkuZG9uZSwhcztyPSEwKXtsPWkudmFsdWUscj0hMTtsZXQgdT1sO3Qud3JpdGUodSl9fWNhdGNoKHUpe289e2Vycm9yOnV9fWZpbmFsbHl7dHJ5e2lmKCFyJiYhcyYmKGE9bi5yZXR1cm4pKXlpZWxkIGEuY2FsbChuKX1maW5hbGx5e2lmKG8pdGhyb3cgby5lcnJvcn19cmV0dXJuIHQuZmluaXNoKCl9KX12YXIgQmEsRnMsVWM7dmFyIGp5PW0oKCk9PntwbigpO0VkKCk7THkoKTtRcigpO3lhKCk7eWEoKTtXbSgpO0xlKCk7dHUoKTtfYSgpO1UwKCk7amUoKTtObygpO1dsKCk7RWwoKTtVeSgpO050KCk7QmE9Y2xhc3MgQmEgZXh0ZW5kcyBBY3tzdGF0aWMgdGhyb3VnaE5vZGUodCl7dGhyb3cgRXJyb3IoJyJ0aHJvdWdoTm9kZSIgbm90IGF2YWlsYWJsZSBpbiB0aGlzIGVudmlyb25tZW50Jyl9c3RhdGljIHRocm91Z2hET00odCxlKXt0aHJvdyBFcnJvcignInRocm91Z2hET00iIG5vdCBhdmFpbGFibGUgaW4gdGhpcyBlbnZpcm9ubWVudCcpfWNvbnN0cnVjdG9yKHQpe3N1cGVyKCk7aWYodGhpcy5fcG9zaXRpb249MCx0aGlzLl9zdGFydGVkPSExLHRoaXMuX2NvbXByZXNzaW9uPW51bGwsdGhpcy5fc2luaz1uZXcgQXMsdGhpcy5fc2NoZW1hPW51bGwsdGhpcy5fZGljdGlvbmFyeUJsb2Nrcz1bXSx0aGlzLl9yZWNvcmRCYXRjaEJsb2Nrcz1bXSx0aGlzLl9zZWVuRGljdGlvbmFyaWVzPW5ldyBNYXAsdGhpcy5fZGljdGlvbmFyeURlbHRhT2Zmc2V0cz1uZXcgTWFwLEZyKHQpfHwodD17YXV0b0Rlc3Ryb3k6ITAsd3JpdGVMZWdhY3lJcGNGb3JtYXQ6ITEsY29tcHJlc3Npb25UeXBlOm51bGx9KSx0aGlzLl9hdXRvRGVzdHJveT10eXBlb2YgdC5hdXRvRGVzdHJveT09PSJib29sZWFuIj90LmF1dG9EZXN0cm95OiEwLHRoaXMuX3dyaXRlTGVnYWN5SXBjRm9ybWF0PXR5cGVvZiB0LndyaXRlTGVnYWN5SXBjRm9ybWF0PT09ImJvb2xlYW4iP3Qud3JpdGVMZWdhY3lJcGNGb3JtYXQ6ITEsdC5jb21wcmVzc2lvblR5cGUhPW51bGwpe2lmKHRoaXMuX3dyaXRlTGVnYWN5SXBjRm9ybWF0KXRocm93IEVycm9yKCJMZWdhY3kgSVBDIGZvcm1hdCBkb2VzIG5vdCBzdXBwb3J0IGNvbHVtbmFyIGNvbXByZXNzaW9uLiBVc2UgbW9kZXJuIElQQyBmb3JtYXQgKHdyaXRlTGVnYWN5SXBjRm9ybWF0PWZhbHNlKS4iKTtpZihPYmplY3QudmFsdWVzKE1yKS5pbmNsdWRlcyh0LmNvbXByZXNzaW9uVHlwZSkpdGhpcy5fY29tcHJlc3Npb249bmV3IFNjKHQuY29tcHJlc3Npb25UeXBlKTtlbHNle2xldCBlPU9iamVjdC52YWx1ZXMoTXIpLmZpbHRlcigocik9PnR5cGVvZiByPT09InN0cmluZyIpO3Rocm93IEVycm9yKGBVbnN1cHBvcnRlZCBjb21wcmVzc2lvblR5cGU6ICR7dC5jb21wcmVzc2lvblR5cGV9IEF2YWlsYWJsZSB0eXBlczogJHtlLmpvaW4oIiwgIil9YCl9fWVsc2UgdGhpcy5fY29tcHJlc3Npb249bnVsbH10b1N0cmluZyh0PSExKXtyZXR1cm4gdGhpcy5fc2luay50b1N0cmluZyh0KX10b1VpbnQ4QXJyYXkodD0hMSl7cmV0dXJuIHRoaXMuX3NpbmsudG9VaW50OEFycmF5KHQpfXdyaXRlQWxsKHQpe2lmKGJpKHQpKXJldHVybiB0LnRoZW4oKGUpPT50aGlzLndyaXRlQWxsKGUpKTtlbHNlIGlmKFZuKHQpKXJldHVybiB6eSh0aGlzLHQpO3JldHVybiBWeSh0aGlzLHQpfWdldCBjbG9zZWQoKXtyZXR1cm4gdGhpcy5fc2luay5jbG9zZWR9W1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpe3JldHVybiB0aGlzLl9zaW5rW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpfXRvRE9NU3RyZWFtKHQpe3JldHVybiB0aGlzLl9zaW5rLnRvRE9NU3RyZWFtKHQpfXRvTm9kZVN0cmVhbSh0KXtyZXR1cm4gdGhpcy5fc2luay50b05vZGVTdHJlYW0odCl9Y2xvc2UoKXtyZXR1cm4gdGhpcy5yZXNldCgpLl9zaW5rLmNsb3NlKCl9YWJvcnQodCl7cmV0dXJuIHRoaXMucmVzZXQoKS5fc2luay5hYm9ydCh0KX1maW5pc2goKXtyZXR1cm4gdGhpcy5fYXV0b0Rlc3Ryb3k/dGhpcy5jbG9zZSgpOnRoaXMucmVzZXQodGhpcy5fc2luayx0aGlzLl9zY2hlbWEpLHRoaXN9cmVzZXQodD10aGlzLl9zaW5rLGU9bnVsbCl7aWYodD09PXRoaXMuX3Npbmt8fHQgaW5zdGFuY2VvZiBBcyl0aGlzLl9zaW5rPXQ7ZWxzZSBpZih0aGlzLl9zaW5rPW5ldyBBcyx0JiZ4Yih0KSl0aGlzLnRvRE9NU3RyZWFtKHt0eXBlOiJieXRlcyJ9KS5waXBlVG8odCk7ZWxzZSBpZih0JiZUYih0KSl0aGlzLnRvTm9kZVN0cmVhbSh7b2JqZWN0TW9kZTohMX0pLnBpcGUodCk7aWYodGhpcy5fc3RhcnRlZCYmdGhpcy5fc2NoZW1hKXRoaXMuX3dyaXRlRm9vdGVyKHRoaXMuX3NjaGVtYSk7aWYodGhpcy5fc3RhcnRlZD0hMSx0aGlzLl9kaWN0aW9uYXJ5QmxvY2tzPVtdLHRoaXMuX3JlY29yZEJhdGNoQmxvY2tzPVtdLHRoaXMuX3NlZW5EaWN0aW9uYXJpZXM9bmV3IE1hcCx0aGlzLl9kaWN0aW9uYXJ5RGVsdGFPZmZzZXRzPW5ldyBNYXAsIWV8fCF3YShlLHRoaXMuX3NjaGVtYSkpaWYoZT09bnVsbCl0aGlzLl9wb3NpdGlvbj0wLHRoaXMuX3NjaGVtYT1udWxsO2Vsc2UgdGhpcy5fc3RhcnRlZD0hMCx0aGlzLl9zY2hlbWE9ZSx0aGlzLl93cml0ZVNjaGVtYShlKTtyZXR1cm4gdGhpc313cml0ZSh0KXtsZXQgZT1udWxsO2lmKCF0aGlzLl9zaW5rKXRocm93IEVycm9yKCJSZWNvcmRCYXRjaFdyaXRlciBpcyBjbG9zZWQiKTtlbHNlIGlmKHQ9PW51bGwpcmV0dXJuIHRoaXMuZmluaXNoKCkmJnZvaWQgMDtlbHNlIGlmKHQgaW5zdGFuY2VvZiBUZSYmIShlPXQuc2NoZW1hKSlyZXR1cm4gdGhpcy5maW5pc2goKSYmdm9pZCAwO2Vsc2UgaWYodCBpbnN0YW5jZW9mIEF0JiYhKGU9dC5zY2hlbWEpKXJldHVybiB0aGlzLmZpbmlzaCgpJiZ2b2lkIDA7aWYoZSYmIXdhKGUsdGhpcy5fc2NoZW1hKSl7aWYodGhpcy5fc3RhcnRlZCYmdGhpcy5fYXV0b0Rlc3Ryb3kpcmV0dXJuIHRoaXMuY2xvc2UoKTt0aGlzLnJlc2V0KHRoaXMuX3NpbmssZSl9aWYodCBpbnN0YW5jZW9mIEF0KXtpZighKHQgaW5zdGFuY2VvZiBOYykpdGhpcy5fd3JpdGVSZWNvcmRCYXRjaCh0KX1lbHNlIGlmKHQgaW5zdGFuY2VvZiBUZSl0aGlzLndyaXRlQWxsKHQuYmF0Y2hlcyk7ZWxzZSBpZih3aSh0KSl0aGlzLndyaXRlQWxsKHQpfV93cml0ZU1lc3NhZ2UodCxlPTgpe2xldCByPWUtMSxuPXRyLmVuY29kZSh0KSxpPW4uYnl0ZUxlbmd0aCxzPSF0aGlzLl93cml0ZUxlZ2FjeUlwY0Zvcm1hdD84OjQsbz1pK3MrciZ+cixhPW8taS1zO2lmKHQuaGVhZGVyVHlwZT09PXh0LlJlY29yZEJhdGNoKXRoaXMuX3JlY29yZEJhdGNoQmxvY2tzLnB1c2gobmV3IFNzKG8sdC5ib2R5TGVuZ3RoLHRoaXMuX3Bvc2l0aW9uKSk7ZWxzZSBpZih0LmhlYWRlclR5cGU9PT14dC5EaWN0aW9uYXJ5QmF0Y2gpdGhpcy5fZGljdGlvbmFyeUJsb2Nrcy5wdXNoKG5ldyBTcyhvLHQuYm9keUxlbmd0aCx0aGlzLl9wb3NpdGlvbikpO2lmKCF0aGlzLl93cml0ZUxlZ2FjeUlwY0Zvcm1hdCl0aGlzLl93cml0ZShJbnQzMkFycmF5Lm9mKC0xKSk7aWYodGhpcy5fd3JpdGUoSW50MzJBcnJheS5vZihvLXMpKSxpPjApdGhpcy5fd3JpdGUobik7cmV0dXJuIHRoaXMuX3dyaXRlUGFkZGluZyhhKX1fd3JpdGUodCl7aWYodGhpcy5fc3RhcnRlZCl7bGV0IGU9Qyh0KTtpZihlJiZlLmJ5dGVMZW5ndGg+MCl0aGlzLl9zaW5rLndyaXRlKGUpLHRoaXMuX3Bvc2l0aW9uKz1lLmJ5dGVMZW5ndGh9cmV0dXJuIHRoaXN9X3dyaXRlU2NoZW1hKHQpe3JldHVybiB0aGlzLl93cml0ZU1lc3NhZ2UodHIuZnJvbSh0KSl9X3dyaXRlRm9vdGVyKHQpe3JldHVybiB0aGlzLl93cml0ZUxlZ2FjeUlwY0Zvcm1hdD90aGlzLl93cml0ZShJbnQzMkFycmF5Lm9mKDApKTp0aGlzLl93cml0ZShJbnQzMkFycmF5Lm9mKC0xLDApKX1fd3JpdGVNYWdpYygpe3JldHVybiB0aGlzLl93cml0ZShGYyl9X3dyaXRlUGFkZGluZyh0KXtyZXR1cm4gdD4wP3RoaXMuX3dyaXRlKG5ldyBVaW50OEFycmF5KHQpKTp0aGlzfV93cml0ZVJlY29yZEJhdGNoKHQpe2xldHtieXRlTGVuZ3RoOmUsbm9kZXM6cixidWZmZXJSZWdpb25zOm4sYnVmZmVyczppLHZhcmlhZGljQnVmZmVyQ291bnRzOnN9PXRoaXMuX2Fzc2VtYmxlUmVjb3JkQmF0Y2godCksbz1uZXcgV2UodC5udW1Sb3dzLHIsbix0aGlzLl9jb21wcmVzc2lvbixzLHQubWV0YWRhdGEpLGE9dHIuZnJvbShvLGUpO3JldHVybiB0aGlzLl93cml0ZURpY3Rpb25hcmllcyh0KS5fd3JpdGVNZXNzYWdlKGEpLl93cml0ZUJvZHlCdWZmZXJzKGkpfV9hc3NlbWJsZVJlY29yZEJhdGNoKHQpe2xldHtieXRlTGVuZ3RoOmUsbm9kZXM6cixidWZmZXJSZWdpb25zOm4sYnVmZmVyczppLHZhcmlhZGljQnVmZmVyQ291bnRzOnN9PW1lLmFzc2VtYmxlKHQpO2lmKHRoaXMuX2NvbXByZXNzaW9uIT1udWxsKSh7Ynl0ZUxlbmd0aDplLGJ1ZmZlclJlZ2lvbnM6bixidWZmZXJzOml9PXRoaXMuX2NvbXByZXNzQm9keUJ1ZmZlcnMoaSkpO3JldHVybntieXRlTGVuZ3RoOmUsbm9kZXM6cixidWZmZXJSZWdpb25zOm4sYnVmZmVyczppLHZhcmlhZGljQnVmZmVyQ291bnRzOnN9fV9jb21wcmVzc0JvZHlCdWZmZXJzKHQpe2xldCBlPUxjLmdldCh0aGlzLl9jb21wcmVzc2lvbi50eXBlKTtpZighKGU9PT1udWxsfHxlPT09dm9pZCAwP3ZvaWQgMDplLmVuY29kZSl8fHR5cGVvZiBlLmVuY29kZSE9PSJmdW5jdGlvbiIpdGhyb3cgRXJyb3IoYENvZGVjIGZvciBjb21wcmVzc2lvbiB0eXBlICIke01yW3RoaXMuX2NvbXByZXNzaW9uLnR5cGVdfSIgaGFzIGludmFsaWQgZW5jb2RlIG1ldGhvZGApO2xldCByPTAsbj1bXSxpPVtdO2ZvcihsZXQgbyBvZiB0KXtsZXQgYT1DKG8pO2lmKGEubGVuZ3RoPT09MCl7bi5wdXNoKG5ldyBVaW50OEFycmF5KDApLG5ldyBVaW50OEFycmF5KDApKSxpLnB1c2gobmV3IHhlKHIsMCkpO2NvbnRpbnVlfWxldCBsPWUuZW5jb2RlKGEpLHU9bC5sZW5ndGg8YS5sZW5ndGgsZj11P2w6YSxwPXU/Zi5sZW5ndGg6TGQsZz1uZXcgbHIobmV3IFVpbnQ4QXJyYXkocnUpKTtnLndyaXRlSW50NjQoMCxCaWdJbnQocCkpLG4ucHVzaChnLmJ5dGVzKCksbmV3IFVpbnQ4QXJyYXkoZikpO2xldCB2PShyKzcmLTgpLXI7cis9djtsZXQgST1ydStmLmxlbmd0aDtpLnB1c2gobmV3IHhlKHIsSSkpLHIrPUl9bGV0IHM9KHIrNyYtOCktcjtyZXR1cm4gcis9cyx7Ynl0ZUxlbmd0aDpyLGJ1ZmZlclJlZ2lvbnM6aSxidWZmZXJzOm59fV93cml0ZURpY3Rpb25hcnlCYXRjaCh0LGUscj0hMSl7bGV0e2J5dGVMZW5ndGg6bixub2RlczppLGJ1ZmZlclJlZ2lvbnM6cyxidWZmZXJzOm8sdmFyaWFkaWNCdWZmZXJDb3VudHM6YX09dGhpcy5fYXNzZW1ibGVSZWNvcmRCYXRjaChuZXcgTihbdF0pKSxsPW5ldyBXZSh0Lmxlbmd0aCxpLHMsdGhpcy5fY29tcHJlc3Npb24sYSksdT1uZXcgUnIobCxlLHIpLGY9dHIuZnJvbSh1LG4pO3JldHVybiB0aGlzLl93cml0ZU1lc3NhZ2UoZikuX3dyaXRlQm9keUJ1ZmZlcnMobyl9X3dyaXRlQm9keUJ1ZmZlcnModCl7bGV0IGU9dGhpcy5fY29tcHJlc3Npb24hPW51bGw/MjoxLHI9QXJyYXkoZSk7Zm9yKGxldCBuPTA7bjx0Lmxlbmd0aDtuKz1lKXtsZXQgaT0wO2ZvcihsZXQgbz0tMTsrK288ZTspcltvXT10W24rb10saSs9cltvXS5ieXRlTGVuZ3RoO2lmKGk9PT0wKWNvbnRpbnVlO2ZvcihsZXQgbyBvZiByKXRoaXMuX3dyaXRlKG8pO2xldCBzPShpKzcmLTgpLWk7aWYocz4wKXRoaXMuX3dyaXRlUGFkZGluZyhzKX1yZXR1cm4gdGhpc31fd3JpdGVEaWN0aW9uYXJpZXModCl7dmFyIGUscjtmb3IobGV0W24saV1vZiB0LmRpY3Rpb25hcmllcyl7bGV0IHM9KGU9aT09PW51bGx8fGk9PT12b2lkIDA/dm9pZCAwOmkuZGF0YSkhPT1udWxsJiZlIT09dm9pZCAwP2U6W10sbz10aGlzLl9zZWVuRGljdGlvbmFyaWVzLmdldChuKSxhPShyPXRoaXMuX2RpY3Rpb25hcnlEZWx0YU9mZnNldHMuZ2V0KG4pKSE9PW51bGwmJnIhPT12b2lkIDA/cjowO2lmKCFvfHxvLmRhdGFbMF0hPT1zWzBdKWZvcihsZXRbbCx1XW9mIHMuZW50cmllcygpKXRoaXMuX3dyaXRlRGljdGlvbmFyeUJhdGNoKHUsbixsPjApO2Vsc2UgaWYoYTxzLmxlbmd0aClmb3IobGV0IGwgb2Ygcy5zbGljZShhKSl0aGlzLl93cml0ZURpY3Rpb25hcnlCYXRjaChsLG4sITApO3RoaXMuX3NlZW5EaWN0aW9uYXJpZXMuc2V0KG4saSksdGhpcy5fZGljdGlvbmFyeURlbHRhT2Zmc2V0cy5zZXQobixzLmxlbmd0aCl9cmV0dXJuIHRoaXN9fTtGcz1jbGFzcyBGcyBleHRlbmRzIEJhe3N0YXRpYyB3cml0ZUFsbCh0LGUpe2xldCByPW5ldyBGcyhlKTtpZihiaSh0KSlyZXR1cm4gdC50aGVuKChuKT0+ci53cml0ZUFsbChuKSk7ZWxzZSBpZihWbih0KSlyZXR1cm4genkocix0KTtyZXR1cm4gVnkocix0KX19O1VjPWNsYXNzIFVjIGV4dGVuZHMgQmF7c3RhdGljIHdyaXRlQWxsKHQsZSl7bGV0IHI9bmV3IFVjKGUpO2lmKGJpKHQpKXJldHVybiB0LnRoZW4oKG4pPT5yLndyaXRlQWxsKG4pKTtlbHNlIGlmKFZuKHQpKXJldHVybiB6eShyLHQpO3JldHVybiBWeShyLHQpfWNvbnN0cnVjdG9yKHQpe3N1cGVyKHQpO3RoaXMuX2F1dG9EZXN0cm95PSEwLHRoaXMuX3dyaXRlTGVnYWN5SXBjRm9ybWF0PSExfV93cml0ZVNjaGVtYSh0KXtyZXR1cm4gdGhpcy5fd3JpdGVNYWdpYygpLl93cml0ZVBhZGRpbmcoMil9X3dyaXRlRGljdGlvbmFyeUJhdGNoKHQsZSxyPSExKXtpZighciYmdGhpcy5fc2VlbkRpY3Rpb25hcmllcy5oYXMoZSkpdGhyb3cgRXJyb3IoIlRoZSBBcnJvdyBGaWxlIGZvcm1hdCBkb2VzIG5vdCBzdXBwb3J0IHJlcGxhY2VtZW50IGRpY3Rpb25hcmllcy4gIik7cmV0dXJuIHN1cGVyLl93cml0ZURpY3Rpb25hcnlCYXRjaCh0LGUscil9X3dyaXRlRm9vdGVyKHQpe2xldCBlPURvLmVuY29kZShuZXcgRG8odCwkdC5WNSx0aGlzLl9yZWNvcmRCYXRjaEJsb2Nrcyx0aGlzLl9kaWN0aW9uYXJ5QmxvY2tzKSk7cmV0dXJuIHN1cGVyLl93cml0ZUZvb3Rlcih0KS5fd3JpdGUoZSkuX3dyaXRlKEludDMyQXJyYXkub2YoZS5ieXRlTGVuZ3RoKSkuX3dyaXRlTWFnaWMoKX19fSk7ZnVuY3Rpb24gUjAodCxlKXtpZihWbih0KSlyZXR1cm4gbUUodCxlKTtpZih3aSh0KSlyZXR1cm4gcEUodCxlKTt0aHJvdyBFcnJvcigidG9ET01TdHJlYW0oKSBtdXN0IGJlIGNhbGxlZCB3aXRoIGFuIEl0ZXJhYmxlIG9yIEFzeW5jSXRlcmFibGUiKX1mdW5jdGlvbiBwRSh0LGUpe2xldCByPW51bGwsbj0oZT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUudHlwZSk9PT0iYnl0ZXMifHwhMSxpPShlPT09bnVsbHx8ZT09PXZvaWQgMD92b2lkIDA6ZS5oaWdoV2F0ZXJNYXJrKXx8TWF0aC5wb3coMiwyNCk7cmV0dXJuIG5ldyBSZWFkYWJsZVN0cmVhbShPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sZSkse3N0YXJ0KG8pe3MobyxyfHwocj10W1N5bWJvbC5pdGVyYXRvcl0oKSkpfSxwdWxsKG8pe3I/cyhvLHIpOm8uY2xvc2UoKX0sY2FuY2VsKCl7KHI9PT1udWxsfHxyPT09dm9pZCAwP3ZvaWQgMDpyLnJldHVybikmJnIucmV0dXJuKCkscj1udWxsfX0pLE9iamVjdC5hc3NpZ24oe2hpZ2hXYXRlck1hcms6bj9pOnZvaWQgMH0sZSkpO2Z1bmN0aW9uIHMobyxhKXtsZXQgbCx1PW51bGwsZj1vLmRlc2lyZWRTaXplfHxudWxsO3doaWxlKCEodT1hLm5leHQobj9mOm51bGwpKS5kb25lKXtpZihBcnJheUJ1ZmZlci5pc1ZpZXcodS52YWx1ZSkmJihsPUModS52YWx1ZSkpKWYhPW51bGwmJm4mJihmPWYtbC5ieXRlTGVuZ3RoKzEpLHUudmFsdWU9bDtpZihvLmVucXVldWUodS52YWx1ZSksZiE9bnVsbCYmLS1mPD0wKXJldHVybn1vLmNsb3NlKCl9fWZ1bmN0aW9uIG1FKHQsZSl7bGV0IHI9bnVsbCxuPShlPT09bnVsbHx8ZT09PXZvaWQgMD92b2lkIDA6ZS50eXBlKT09PSJieXRlcyJ8fCExLGk9KGU9PT1udWxsfHxlPT09dm9pZCAwP3ZvaWQgMDplLmhpZ2hXYXRlck1hcmspfHxNYXRoLnBvdygyLDI0KTtyZXR1cm4gbmV3IFJlYWRhYmxlU3RyZWFtKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSxlKSx7c3RhcnQobyl7cmV0dXJuIEUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3lpZWxkIHMobyxyfHwocj10W1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpKSl9KX0scHVsbChvKXtyZXR1cm4gRSh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7cj95aWVsZCBzKG8scik6by5jbG9zZSgpfSl9LGNhbmNlbCgpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXsocj09PW51bGx8fHI9PT12b2lkIDA/dm9pZCAwOnIucmV0dXJuKSYmKHlpZWxkIHIucmV0dXJuKCkpLHI9bnVsbH0pfX0pLE9iamVjdC5hc3NpZ24oe2hpZ2hXYXRlck1hcms6bj9pOnZvaWQgMH0sZSkpO2Z1bmN0aW9uIHMobyxhKXtyZXR1cm4gRSh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7bGV0IGwsdT1udWxsLGY9by5kZXNpcmVkU2l6ZXx8bnVsbDt3aGlsZSghKHU9eWllbGQgYS5uZXh0KG4/ZjpudWxsKSkuZG9uZSl7aWYoQXJyYXlCdWZmZXIuaXNWaWV3KHUudmFsdWUpJiYobD1DKHUudmFsdWUpKSlmIT1udWxsJiZuJiYoZj1mLWwuYnl0ZUxlbmd0aCsxKSx1LnZhbHVlPWw7aWYoby5lbnF1ZXVlKHUudmFsdWUpLGYhPW51bGwmJi0tZjw9MClyZXR1cm59by5jbG9zZSgpfSl9fXZhciBDMD1tKCgpPT57cG4oKTtqZSgpfSk7ZnVuY3Rpb24gVjAodCl7cmV0dXJuIG5ldyB6MCh0KX1jbGFzcyB6MHtjb25zdHJ1Y3Rvcih0KXt0aGlzLl9udW1DaHVua3M9MCx0aGlzLl9maW5pc2hlZD0hMSx0aGlzLl9idWZmZXJlZFNpemU9MDtsZXR7WyJyZWFkYWJsZVN0cmF0ZWd5Il06ZSxbIndyaXRhYmxlU3RyYXRlZ3kiXTpyLFsicXVldWVpbmdTdHJhdGVneSJdOm49ImNvdW50In09dCxpPVNiKHQsWyJyZWFkYWJsZVN0cmF0ZWd5Iiwid3JpdGFibGVTdHJhdGVneSIsInF1ZXVlaW5nU3RyYXRlZ3kiXSk7dGhpcy5fY29udHJvbGxlcj1udWxsLHRoaXMuX2J1aWxkZXI9eHMoaSksdGhpcy5fZ2V0U2l6ZT1uIT09ImJ5dGVzIj9QMDprMDtsZXR7WyJoaWdoV2F0ZXJNYXJrIl06cz1uPT09ImJ5dGVzIj9NYXRoLnBvdygyLDE0KToxMDAwfT1PYmplY3QuYXNzaWduKHt9LGUpLHtbImhpZ2hXYXRlck1hcmsiXTpvPW49PT0iYnl0ZXMiP01hdGgucG93KDIsMTQpOjEwMDB9PU9iamVjdC5hc3NpZ24oe30scik7dGhpcy5yZWFkYWJsZT1uZXcgUmVhZGFibGVTdHJlYW0oe1siY2FuY2VsIl06KCk9Pnt0aGlzLl9idWlsZGVyLmNsZWFyKCl9LFsicHVsbCJdOihhKT0+e3RoaXMuX21heWJlRmx1c2godGhpcy5fYnVpbGRlcix0aGlzLl9jb250cm9sbGVyPWEpfSxbInN0YXJ0Il06KGEpPT57dGhpcy5fbWF5YmVGbHVzaCh0aGlzLl9idWlsZGVyLHRoaXMuX2NvbnRyb2xsZXI9YSl9fSx7aGlnaFdhdGVyTWFyazpzLHNpemU6biE9PSJieXRlcyI/UDA6azB9KSx0aGlzLndyaXRhYmxlPW5ldyBXcml0YWJsZVN0cmVhbSh7WyJhYm9ydCJdOigpPT57dGhpcy5fYnVpbGRlci5jbGVhcigpfSxbIndyaXRlIl06KCk9Pnt0aGlzLl9tYXliZUZsdXNoKHRoaXMuX2J1aWxkZXIsdGhpcy5fY29udHJvbGxlcil9LFsiY2xvc2UiXTooKT0+e3RoaXMuX21heWJlRmx1c2godGhpcy5fYnVpbGRlci5maW5pc2goKSx0aGlzLl9jb250cm9sbGVyKX19LHtoaWdoV2F0ZXJNYXJrOm8sc2l6ZTooYSk9PnRoaXMuX3dyaXRlVmFsdWVBbmRSZXR1cm5DaHVua1NpemUoYSl9KX1fd3JpdGVWYWx1ZUFuZFJldHVybkNodW5rU2l6ZSh0KXtsZXQgZT10aGlzLl9idWZmZXJlZFNpemU7cmV0dXJuIHRoaXMuX2J1ZmZlcmVkU2l6ZT10aGlzLl9nZXRTaXplKHRoaXMuX2J1aWxkZXIuYXBwZW5kKHQpKSx0aGlzLl9idWZmZXJlZFNpemUtZX1fbWF5YmVGbHVzaCh0LGUpe2lmKGU9PW51bGwpcmV0dXJuO2lmKHRoaXMuX2J1ZmZlcmVkU2l6ZT49ZS5kZXNpcmVkU2l6ZSkrK3RoaXMuX251bUNodW5rcyYmdGhpcy5fZW5xdWV1ZShlLHQudG9WZWN0b3IoKSk7aWYodC5maW5pc2hlZCl7aWYodC5sZW5ndGg+MHx8dGhpcy5fbnVtQ2h1bmtzPT09MCkrK3RoaXMuX251bUNodW5rcyYmdGhpcy5fZW5xdWV1ZShlLHQudG9WZWN0b3IoKSk7aWYoIXRoaXMuX2ZpbmlzaGVkJiYodGhpcy5fZmluaXNoZWQ9ITApKXRoaXMuX2VucXVldWUoZSxudWxsKX19X2VucXVldWUodCxlKXt0aGlzLl9idWZmZXJlZFNpemU9MCx0aGlzLl9jb250cm9sbGVyPW51bGwsZT09bnVsbD90LmNsb3NlKCk6dC5lbnF1ZXVlKGUpfX12YXIgUDA9KHQpPT57dmFyIGU7cmV0dXJuKGU9dD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnQubGVuZ3RoKSE9PW51bGwmJmUhPT12b2lkIDA/ZTowfSxrMD0odCk9Pnt2YXIgZTtyZXR1cm4oZT10PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC5ieXRlTGVuZ3RoKSE9PW51bGwmJmUhPT12b2lkIDA/ZTowfTt2YXIgajA9bSgoKT0+e3BuKCk7c2QoKX0pO2Z1bmN0aW9uIFBkKHQsZSl7bGV0IHI9bmV3IEFzLG49bnVsbCxpPW5ldyBSZWFkYWJsZVN0cmVhbSh7Y2FuY2VsKCl7cmV0dXJuIEUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3lpZWxkIHIuY2xvc2UoKX0pfSxzdGFydChhKXtyZXR1cm4gRSh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7eWllbGQgbyhhLG58fChuPXlpZWxkIHMoKSkpfSl9LHB1bGwoYSl7cmV0dXJuIEUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe24/eWllbGQgbyhhLG4pOmEuY2xvc2UoKX0pfX0pO3JldHVybnt3cml0YWJsZTpuZXcgV3JpdGFibGVTdHJlYW0ocixPYmplY3QuYXNzaWduKHtoaWdoV2F0ZXJNYXJrOk1hdGgucG93KDIsMTQpfSx0KSkscmVhZGFibGU6aX07ZnVuY3Rpb24gcygpe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtyZXR1cm4geWllbGQoeWllbGQgaHIuZnJvbShyKSkub3BlbihlKX0pfWZ1bmN0aW9uIG8oYSxsKXtyZXR1cm4gRSh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7bGV0IHU9YS5kZXNpcmVkU2l6ZSxmPW51bGw7d2hpbGUoIShmPXlpZWxkIGwubmV4dCgpKS5kb25lKWlmKGEuZW5xdWV1ZShmLnZhbHVlKSx1IT1udWxsJiYtLXU8PTApcmV0dXJuO2EuY2xvc2UoKX0pfX12YXIgJDA9bSgoKT0+e3BuKCk7X2EoKTtSZCgpfSk7ZnVuY3Rpb24ga2QodCxlKXtsZXQgcj1uZXcgdGhpcyh0KSxuPW5ldyBabihyKSxpPW5ldyBSZWFkYWJsZVN0cmVhbSh7Y2FuY2VsKCl7cmV0dXJuIEUodGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3lpZWxkIG4uY2FuY2VsKCl9KX0scHVsbChvKXtyZXR1cm4gRSh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7eWllbGQgcyhvKX0pfSxzdGFydChvKXtyZXR1cm4gRSh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7eWllbGQgcyhvKX0pfX0sT2JqZWN0LmFzc2lnbih7aGlnaFdhdGVyTWFyazpNYXRoLnBvdygyLDE0KX0sZSkpO3JldHVybnt3cml0YWJsZTpuZXcgV3JpdGFibGVTdHJlYW0ocix0KSxyZWFkYWJsZTppfTtmdW5jdGlvbiBzKG8pe3JldHVybiBFKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXQgYT1udWxsLGw9by5kZXNpcmVkU2l6ZTt3aGlsZShhPXlpZWxkIG4ucmVhZChsfHxudWxsKSlpZihvLmVucXVldWUoYSksbCE9bnVsbCYmKGwtPWEuYnl0ZUxlbmd0aCk8PTApcmV0dXJuO28uY2xvc2UoKX0pfX12YXIgcTA9bSgoKT0+e3BuKCk7X2EoKX0pO3ZhciAkeT17fTtaZSgkeSx7aXNBcnJvd0RhdGE6KCk9PkswLGlzQXJyb3dEYXRhVHlwZTooKT0+WTAsaXNBcnJvd0ZpZWxkOigpPT5IMCxpc0Fycm93UmVjb3JkQmF0Y2g6KCk9PkowLGlzQXJyb3dTY2hlbWE6KCk9PlcwLGlzQXJyb3dUYWJsZTooKT0+WDAsaXNBcnJvd1ZlY3RvcjooKT0+RzB9KTtmdW5jdGlvbiBXMCh0KXtyZXR1cm4gbHQuaXNTY2hlbWEodCl9ZnVuY3Rpb24gSDAodCl7cmV0dXJuIFUuaXNGaWVsZCh0KX1mdW5jdGlvbiBZMCh0KXtyZXR1cm4gQi5pc0RhdGFUeXBlKHQpfWZ1bmN0aW9uIEswKHQpe3JldHVybiBwdC5pc0RhdGEodCl9ZnVuY3Rpb24gRzAodCl7cmV0dXJuIE4uaXNWZWN0b3IodCl9ZnVuY3Rpb24gSjAodCl7cmV0dXJuIEF0LmlzUmVjb3JkQmF0Y2godCl9ZnVuY3Rpb24gWDAodCl7cmV0dXJuIFRlLmlzVGFibGUodCl9dmFyIFowPW0oKCk9PntVcigpO2llKCk7WG4oKTtRcigpO05vKCk7RWQoKX0pO3ZhciBSRTt2YXIgUTA9bSgoKT0+e0xlKCk7WG4oKTtpZSgpO1VyKCk7c2QoKTtSZCgpO2p5KCk7Tm8oKTtUbSgpO1htKCk7d2MoKTtQbCgpO2plKCk7Z2MoKTtaMCgpO3R1KCk7UkU9T2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSx4bSksSm0pLHptKSxFbSksS3ApLFZtKSxCbSksdHkpLCR5KSx7Y29tcGFyZVNjaGVtYXM6d2EsY29tcGFyZUZpZWxkczpoMCxjb21wYXJlVHlwZXM6RGR9KX0pO3ZhciBNcz1tKCgpPT57QWwoKTtfZSgpO1JkKCk7ankoKTtDMCgpO2owKCk7JDAoKTtxMCgpO1EwKCk7Y3IudG9ET01TdHJlYW09UjA7dWUudGhyb3VnaERPTT1WMDtoci50aHJvdWdoRE9NPVBkO0lhLnRocm91Z2hET009UGQ7T3MudGhyb3VnaERPTT1QZDtCYS50aHJvdWdoRE9NPWtkO1VjLnRocm91Z2hET009a2Q7RnMudGhyb3VnaERPTT1rZH0pO3ZhciBzdTt2YXIgdEk9bSgoKT0+e3N1PWNsYXNzIHN1IGV4dGVuZHMgRXJyb3J7ZXJyb3JUeXBlO2Vycm9yTWVzc2FnZTtyZW1vdGVUcmFjZWJhY2s7Y29uc3RydWN0b3IodCxlLHIpe3N1cGVyKGAke3R9OiAke2V9YCk7dGhpcy5lcnJvclR5cGU9dCx0aGlzLmVycm9yTWVzc2FnZT1lLHRoaXMucmVtb3RlVHJhY2ViYWNrPXIsdGhpcy5uYW1lPSJScGNFcnJvciJ9fX0pO3ZhciBlST0oKT0+e307dmFyIHJJPW0oKCk9Pnt0SSgpO2VJKCl9KTt2YXIgcXk9bSgoKT0+e3JJKCl9KTtmdW5jdGlvbiB6SSh0LGUpe3ZhciByPXt9O2Zvcih2YXIgbiBpbiB0KWlmKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0LG4pJiZlLmluZGV4T2Yobik8MClyW25dPXRbbl07aWYodCE9bnVsbCYmdHlwZW9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHM9PT0iZnVuY3Rpb24iKXtmb3IodmFyIGk9MCxuPU9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHModCk7aTxuLmxlbmd0aDtpKyspaWYoZS5pbmRleE9mKG5baV0pPDAmJk9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbCh0LG5baV0pKXJbbltpXV09dFtuW2ldXX1yZXR1cm4gcn1mdW5jdGlvbiBPKHQsZSxyLG4pe2Z1bmN0aW9uIGkocyl7cmV0dXJuIHMgaW5zdGFuY2VvZiByP3M6bmV3IHIoZnVuY3Rpb24obyl7byhzKX0pfXJldHVybiBuZXcocnx8KHI9UHJvbWlzZSkpKGZ1bmN0aW9uKHMsbyl7ZnVuY3Rpb24gYShmKXt0cnl7dShuLm5leHQoZikpfWNhdGNoKHApe28ocCl9fWZ1bmN0aW9uIGwoZil7dHJ5e3Uobi50aHJvdyhmKSl9Y2F0Y2gocCl7byhwKX19ZnVuY3Rpb24gdShmKXtmLmRvbmU/cyhmLnZhbHVlKTppKGYudmFsdWUpLnRoZW4oYSxsKX11KChuPW4uYXBwbHkodCxlfHxbXSkpLm5leHQoKSl9KX1mdW5jdGlvbiBWSSh0KXt2YXIgZT10eXBlb2YgU3ltYm9sPT09ImZ1bmN0aW9uIiYmU3ltYm9sLml0ZXJhdG9yLHI9ZSYmdFtlXSxuPTA7aWYocilyZXR1cm4gci5jYWxsKHQpO2lmKHQmJnR5cGVvZiB0Lmxlbmd0aD09PSJudW1iZXIiKXJldHVybntuZXh0OmZ1bmN0aW9uKCl7aWYodCYmbj49dC5sZW5ndGgpdD12b2lkIDA7cmV0dXJue3ZhbHVlOnQmJnRbbisrXSxkb25lOiF0fX19O3Rocm93IFR5cGVFcnJvcihlPyJPYmplY3QgaXMgbm90IGl0ZXJhYmxlLiI6IlN5bWJvbC5pdGVyYXRvciBpcyBub3QgZGVmaW5lZC4iKX1mdW5jdGlvbiBndCh0KXtyZXR1cm4gdGhpcyBpbnN0YW5jZW9mIGd0Pyh0aGlzLnY9dCx0aGlzKTpuZXcgZ3QodCl9ZnVuY3Rpb24gRW4odCxlLHIpe2lmKCFTeW1ib2wuYXN5bmNJdGVyYXRvcil0aHJvdyBUeXBlRXJyb3IoIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLiIpO3ZhciBuPXIuYXBwbHkodCxlfHxbXSksaSxzPVtdO3JldHVybiBpPU9iamVjdC5jcmVhdGUoKHR5cGVvZiBBc3luY0l0ZXJhdG9yPT09ImZ1bmN0aW9uIj9Bc3luY0l0ZXJhdG9yOk9iamVjdCkucHJvdG90eXBlKSxhKCJuZXh0IiksYSgidGhyb3ciKSxhKCJyZXR1cm4iLG8pLGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXN9LGk7ZnVuY3Rpb24gbyh2KXtyZXR1cm4gZnVuY3Rpb24oSSl7cmV0dXJuIFByb21pc2UucmVzb2x2ZShJKS50aGVuKHYscCl9fWZ1bmN0aW9uIGEodixJKXtpZihuW3ZdKXtpZihpW3ZdPWZ1bmN0aW9uKEQpe3JldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihaLG10KXtzLnB1c2goW3YsRCxaLG10XSk+MXx8bCh2LEQpfSl9LEkpaVt2XT1JKGlbdl0pfX1mdW5jdGlvbiBsKHYsSSl7dHJ5e3Uoblt2XShJKSl9Y2F0Y2goRCl7ZyhzWzBdWzNdLEQpfX1mdW5jdGlvbiB1KHYpe3YudmFsdWUgaW5zdGFuY2VvZiBndD9Qcm9taXNlLnJlc29sdmUodi52YWx1ZS52KS50aGVuKGYscCk6ZyhzWzBdWzJdLHYpfWZ1bmN0aW9uIGYodil7bCgibmV4dCIsdil9ZnVuY3Rpb24gcCh2KXtsKCJ0aHJvdyIsdil9ZnVuY3Rpb24gZyh2LEkpe2lmKHYoSSkscy5zaGlmdCgpLHMubGVuZ3RoKWwoc1swXVswXSxzWzBdWzFdKX19ZnVuY3Rpb24gVmModCl7dmFyIGUscjtyZXR1cm4gZT17fSxuKCJuZXh0IiksbigidGhyb3ciLGZ1bmN0aW9uKGkpe3Rocm93IGl9KSxuKCJyZXR1cm4iKSxlW1N5bWJvbC5pdGVyYXRvcl09ZnVuY3Rpb24oKXtyZXR1cm4gdGhpc30sZTtmdW5jdGlvbiBuKGkscyl7ZVtpXT10W2ldP2Z1bmN0aW9uKG8pe3JldHVybihyPSFyKT97dmFsdWU6Z3QodFtpXShvKSksZG9uZTohMX06cz9zKG8pOm99OnN9fWZ1bmN0aW9uICRpKHQpe2lmKCFTeW1ib2wuYXN5bmNJdGVyYXRvcil0aHJvdyBUeXBlRXJyb3IoIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLiIpO3ZhciBlPXRbU3ltYm9sLmFzeW5jSXRlcmF0b3JdLHI7cmV0dXJuIGU/ZS5jYWxsKHQpOih0PXR5cGVvZiBWST09PSJmdW5jdGlvbiI/VkkodCk6dFtTeW1ib2wuaXRlcmF0b3JdKCkscj17fSxuKCJuZXh0IiksbigidGhyb3ciKSxuKCJyZXR1cm4iKSxyW1N5bWJvbC5hc3luY0l0ZXJhdG9yXT1mdW5jdGlvbigpe3JldHVybiB0aGlzfSxyKTtmdW5jdGlvbiBuKHMpe3Jbc109dFtzXSYmZnVuY3Rpb24obyl7cmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKGEsbCl7bz10W3NdKG8pLGkoYSxsLG8uZG9uZSxvLnZhbHVlKX0pfX1mdW5jdGlvbiBpKHMsbyxhLGwpe1Byb21pc2UucmVzb2x2ZShsKS50aGVuKGZ1bmN0aW9uKHUpe3Moe3ZhbHVlOnUsZG9uZTphfSl9LG8pfX12YXIgT249KCk9Pnt9O3ZhciBqSSx6YyxkRixObj0odCk9PmRGLmVuY29kZSh0KTt2YXIgVXM9bSgoKT0+e2pJPW5ldyBUZXh0RGVjb2RlcigidXRmLTgiKSx6Yz1qSS5kZWNvZGUuYmluZChqSSksZEY9bmV3IFRleHRFbmNvZGVyfSk7dmFyIGhGPSh0KT0+dHlwZW9mIHQ9PT0ibnVtYmVyIiwkST0odCk9PnR5cGVvZiB0PT09ImJvb2xlYW4iLEhlPSh0KT0+dHlwZW9mIHQ9PT0iZnVuY3Rpb24iLFZyPSh0KT0+dCE9bnVsbCYmT2JqZWN0KHQpPT09dCxxaT0odCk9PlZyKHQpJiZIZSh0LnRoZW4pLFdpPSh0KT0+VnIodCkmJkhlKHRbU3ltYm9sLml0ZXJhdG9yXSksZWk9KHQpPT5Wcih0KSYmSGUodFtTeW1ib2wuYXN5bmNJdGVyYXRvcl0pLEdkPSh0KT0+VnIodCkmJlZyKHQuc2NoZW1hKSxKZD0odCk9PlZyKHQpJiYoImRvbmUiaW4gdCkmJigidmFsdWUiaW4gdCksWGQ9KHQpPT5Wcih0KSYmSGUodC5zdGF0KSYmaEYodC5mZCksWmQ9KHQpPT5Wcih0KSYmZHUodC5ib2R5KSxRZD0odCk9PigiX2dldERPTVN0cmVhbSJpbiB0KSYmKCJfZ2V0Tm9kZVN0cmVhbSJpbiB0KSxxST0odCk9PlZyKHQpJiZIZSh0LmFib3J0KSYmSGUodC5nZXRXcml0ZXIpJiYhUWQodCksZHU9KHQpPT5Wcih0KSYmSGUodC5jYW5jZWwpJiZIZSh0LmdldFJlYWRlcikmJiFRZCh0KSxXST0odCk9PlZyKHQpJiZIZSh0LmVuZCkmJkhlKHQud3JpdGUpJiYkSSh0LndyaXRhYmxlKSYmIVFkKHQpLHRoPSh0KT0+VnIodCkmJkhlKHQucmVhZCkmJkhlKHQucGlwZSkmJiRJKHQucmVhZGFibGUpJiYhUWQodCksSEk9KHQpPT5Wcih0KSYmSGUodC5jbGVhcikmJkhlKHQuYnl0ZXMpJiZIZSh0LnBvc2l0aW9uKSYmSGUodC5zZXRQb3NpdGlvbikmJkhlKHQuY2FwYWNpdHkpJiZIZSh0LmdldEJ1ZmZlcklkZW50aWZpZXIpJiZIZSh0LmNyZWF0ZUxvbmcpO3ZhciBhXz17fTtaZShhXyx7Y29tcGFyZUFycmF5TGlrZTooKT0+b18sam9pblVpbnQ4QXJyYXlzOigpPT5GbixtZW1jcHk6KCk9Pmh1LHJlYmFzZVZhbHVlT2Zmc2V0czooKT0+cmgsdG9BcnJheUJ1ZmZlclZpZXc6KCk9PnZ0LHRvQXJyYXlCdWZmZXJWaWV3QXN5bmNJdGVyYXRvcjooKT0+SGksdG9BcnJheUJ1ZmZlclZpZXdJdGVyYXRvcjooKT0+ZnMsdG9CaWdJbnQ2NEFycmF5OigpPT5laCx0b0JpZ1VpbnQ2NEFycmF5OigpPT5iRix0b0Zsb2F0MzJBcnJheTooKT0+d0YsdG9GbG9hdDMyQXJyYXlBc3luY0l0ZXJhdG9yOigpPT5SRix0b0Zsb2F0MzJBcnJheUl0ZXJhdG9yOigpPT5URix0b0Zsb2F0NjRBcnJheTooKT0+dkYsdG9GbG9hdDY0QXJyYXlBc3luY0l0ZXJhdG9yOigpPT5DRix0b0Zsb2F0NjRBcnJheUl0ZXJhdG9yOigpPT5FRix0b0ludDE2QXJyYXk6KCk9PnlGLHRvSW50MTZBcnJheUFzeW5jSXRlcmF0b3I6KCk9PkZGLHRvSW50MTZBcnJheUl0ZXJhdG9yOigpPT5TRix0b0ludDMyQXJyYXk6KCk9PnhhLHRvSW50MzJBcnJheUFzeW5jSXRlcmF0b3I6KCk9Pk1GLHRvSW50MzJBcnJheUl0ZXJhdG9yOigpPT5BRix0b0ludDhBcnJheTooKT0+bUYsdG9JbnQ4QXJyYXlBc3luY0l0ZXJhdG9yOigpPT5ORix0b0ludDhBcnJheUl0ZXJhdG9yOigpPT5CRix0b1VpbnQxNkFycmF5OigpPT5fRix0b1VpbnQxNkFycmF5QXN5bmNJdGVyYXRvcjooKT0+TEYsdG9VaW50MTZBcnJheUl0ZXJhdG9yOigpPT5ERix0b1VpbnQzMkFycmF5OigpPT5nRix0b1VpbnQzMkFycmF5QXN5bmNJdGVyYXRvcjooKT0+VUYsdG9VaW50MzJBcnJheUl0ZXJhdG9yOigpPT54Rix0b1VpbnQ4QXJyYXk6KCk9PmssdG9VaW50OEFycmF5QXN5bmNJdGVyYXRvcjooKT0+c18sdG9VaW50OEFycmF5SXRlcmF0b3I6KCk9PmlfLHRvVWludDhDbGFtcGVkQXJyYXk6KCk9PklGLHRvVWludDhDbGFtcGVkQXJyYXlBc3luY0l0ZXJhdG9yOigpPT5QRix0b1VpbnQ4Q2xhbXBlZEFycmF5SXRlcmF0b3I6KCk9Pk9GfSk7ZnVuY3Rpb24gcEYodCl7bGV0IGU9dFswXT9bdFswXV06W10scixuLGkscztmb3IobGV0IG8sYSxsPTAsdT0wLGY9dC5sZW5ndGg7KytsPGY7KXtpZihvPWVbdV0sYT10W2xdLCFvfHwhYXx8by5idWZmZXIhPT1hLmJ1ZmZlcnx8YS5ieXRlT2Zmc2V0PG8uYnl0ZU9mZnNldCl7YSYmKGVbKyt1XT1hKTtjb250aW51ZX1pZih7Ynl0ZU9mZnNldDpyLGJ5dGVMZW5ndGg6aX09byx7Ynl0ZU9mZnNldDpuLGJ5dGVMZW5ndGg6c309YSxyK2k8bnx8bitzPHIpe2EmJihlWysrdV09YSk7Y29udGludWV9ZVt1XT1uZXcgVWludDhBcnJheShvLmJ1ZmZlcixyLG4tcitzKX1yZXR1cm4gZX1mdW5jdGlvbiBodSh0LGUscj0wLG49ZS5ieXRlTGVuZ3RoKXtsZXQgaT10LmJ5dGVMZW5ndGgscz1uZXcgVWludDhBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQsaSksbz1uZXcgVWludDhBcnJheShlLmJ1ZmZlcixlLmJ5dGVPZmZzZXQsTWF0aC5taW4obixpKSk7cmV0dXJuIHMuc2V0KG8sciksdH1mdW5jdGlvbiBGbih0LGUpe2xldCByPXBGKHQpLG49ci5yZWR1Y2UoKGYscCk9PmYrcC5ieXRlTGVuZ3RoLDApLGkscyxvLGE9MCxsPS0xLHU9TWF0aC5taW4oZXx8TnVtYmVyLlBPU0lUSVZFX0lORklOSVRZLG4pO2ZvcihsZXQgZj1yLmxlbmd0aDsrK2w8Zjspe2lmKGk9cltsXSxzPWkuc3ViYXJyYXkoMCxNYXRoLm1pbihpLmxlbmd0aCx1LWEpKSx1PD1hK3MubGVuZ3RoKXtpZihzLmxlbmd0aDxpLmxlbmd0aClyW2xdPWkuc3ViYXJyYXkocy5sZW5ndGgpO2Vsc2UgaWYocy5sZW5ndGg9PT1pLmxlbmd0aClsKys7bz9odShvLHMsYSk6bz1zO2JyZWFrfWh1KG98fChvPW5ldyBVaW50OEFycmF5KHUpKSxzLGEpLGErPXMubGVuZ3RofXJldHVybltvfHxuZXcgVWludDhBcnJheSgwKSxyLnNsaWNlKGwpLG4tKG8/by5ieXRlTGVuZ3RoOjApXX1mdW5jdGlvbiB2dCh0LGUpe2xldCByPUpkKGUpP2UudmFsdWU6ZTtpZihyIGluc3RhbmNlb2YgdCl7aWYodD09PVVpbnQ4QXJyYXkpcmV0dXJuIG5ldyB0KHIuYnVmZmVyLHIuYnl0ZU9mZnNldCxyLmJ5dGVMZW5ndGgpO3JldHVybiByfWlmKCFyKXJldHVybiBuZXcgdCgwKTtpZih0eXBlb2Ygcj09PSJzdHJpbmciKXI9Tm4ocik7aWYociBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKXJldHVybiBuZXcgdChyKTtpZihyIGluc3RhbmNlb2Ygbl8pcmV0dXJuIG5ldyB0KHIpO2lmKEhJKHIpKXJldHVybiB2dCh0LHIuYnl0ZXMoKSk7cmV0dXJuIUFycmF5QnVmZmVyLmlzVmlldyhyKT90LmZyb20ocik6ci5ieXRlTGVuZ3RoPD0wP25ldyB0KDApOm5ldyB0KHIuYnVmZmVyLHIuYnl0ZU9mZnNldCxyLmJ5dGVMZW5ndGgvdC5CWVRFU19QRVJfRUxFTUVOVCl9ZnVuY3Rpb24qZnModCxlKXtsZXQgcj1mdW5jdGlvbiooaSl7eWllbGQgaX0sbj10eXBlb2YgZT09PSJzdHJpbmciP3IoZSk6QXJyYXlCdWZmZXIuaXNWaWV3KGUpP3IoZSk6ZSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyP3IoZSk6ZSBpbnN0YW5jZW9mIG5fP3IoZSk6IVdpKGUpP3IoZSk6ZTtyZXR1cm4geWllbGQqcl8oZnVuY3Rpb24qKGkpe2xldCBzPW51bGw7ZG8gcz1pLm5leHQoeWllbGQgdnQodCxzKSk7d2hpbGUoIXMuZG9uZSl9KG5bU3ltYm9sLml0ZXJhdG9yXSgpKSksbmV3IHR9ZnVuY3Rpb24gSGkodCxlKXtyZXR1cm4gRW4odGhpcyxhcmd1bWVudHMsZnVuY3Rpb24qKCl7aWYocWkoZSkpcmV0dXJuIHlpZWxkIGd0KHlpZWxkIGd0KHlpZWxkKlZjKCRpKEhpKHQseWllbGQgZ3QoZSkpKSkpKTtsZXQgbj1mdW5jdGlvbihvKXtyZXR1cm4gRW4odGhpcyxhcmd1bWVudHMsZnVuY3Rpb24qKCl7eWllbGQgeWllbGQgZ3QoeWllbGQgZ3QobykpfSl9LGk9ZnVuY3Rpb24obyl7cmV0dXJuIEVuKHRoaXMsYXJndW1lbnRzLGZ1bmN0aW9uKigpe3lpZWxkIGd0KHlpZWxkKlZjKCRpKHJfKGZ1bmN0aW9uKihhKXtsZXQgbD1udWxsO2RvIGw9YS5uZXh0KHlpZWxkIGw9PT1udWxsfHxsPT09dm9pZCAwP3ZvaWQgMDpsLnZhbHVlKTt3aGlsZSghbC5kb25lKX0ob1tTeW1ib2wuaXRlcmF0b3JdKCkpKSkpKX0pfSxzPXR5cGVvZiBlPT09InN0cmluZyI/bihlKTpBcnJheUJ1ZmZlci5pc1ZpZXcoZSk/bihlKTplIGluc3RhbmNlb2YgQXJyYXlCdWZmZXI/bihlKTplIGluc3RhbmNlb2Ygbl8/bihlKTpXaShlKT9pKGUpOiFlaShlKT9uKGUpOmU7cmV0dXJuIHlpZWxkIGd0KHlpZWxkKlZjKCRpKHJfKGZ1bmN0aW9uKG8pe3JldHVybiBFbih0aGlzLGFyZ3VtZW50cyxmdW5jdGlvbiooKXtsZXQgYT1udWxsO2RvIGE9eWllbGQgZ3Qoby5uZXh0KHlpZWxkIHlpZWxkIGd0KHZ0KHQsYSkpKSk7d2hpbGUoIWEuZG9uZSl9KX0oc1tTeW1ib2wuYXN5bmNJdGVyYXRvcl0oKSkpKSkpLHlpZWxkIGd0KG5ldyB0KX0pfWZ1bmN0aW9uIHJoKHQsZSxyKXtpZih0IT09MCl7cj1yLnNsaWNlKDAsZSk7Zm9yKGxldCBuPS0xLGk9ci5sZW5ndGg7KytuPGk7KXJbbl0rPXR9cmV0dXJuIHIuc3ViYXJyYXkoMCxlKX1mdW5jdGlvbiBvXyh0LGUpe2xldCByPTAsbj10Lmxlbmd0aDtpZihuIT09ZS5sZW5ndGgpcmV0dXJuITE7aWYobj4wKWRvIGlmKHRbcl0hPT1lW3JdKXJldHVybiExO3doaWxlKCsrcjxuKTtyZXR1cm4hMH12YXIgbl8sbUY9KHQpPT52dChJbnQ4QXJyYXksdCkseUY9KHQpPT52dChJbnQxNkFycmF5LHQpLHhhPSh0KT0+dnQoSW50MzJBcnJheSx0KSxlaD0odCk9PnZ0KEJpZ0ludDY0QXJyYXksdCksaz0odCk9PnZ0KFVpbnQ4QXJyYXksdCksX0Y9KHQpPT52dChVaW50MTZBcnJheSx0KSxnRj0odCk9PnZ0KFVpbnQzMkFycmF5LHQpLGJGPSh0KT0+dnQoQmlnVWludDY0QXJyYXksdCksd0Y9KHQpPT52dChGbG9hdDMyQXJyYXksdCksdkY9KHQpPT52dChGbG9hdDY0QXJyYXksdCksSUY9KHQpPT52dChVaW50OENsYW1wZWRBcnJheSx0KSxyXz0odCk9Pih0Lm5leHQoKSx0KSxCRj0odCk9PmZzKEludDhBcnJheSx0KSxTRj0odCk9PmZzKEludDE2QXJyYXksdCksQUY9KHQpPT5mcyhJbnQzMkFycmF5LHQpLGlfPSh0KT0+ZnMoVWludDhBcnJheSx0KSxERj0odCk9PmZzKFVpbnQxNkFycmF5LHQpLHhGPSh0KT0+ZnMoVWludDMyQXJyYXksdCksVEY9KHQpPT5mcyhGbG9hdDMyQXJyYXksdCksRUY9KHQpPT5mcyhGbG9hdDY0QXJyYXksdCksT0Y9KHQpPT5mcyhVaW50OENsYW1wZWRBcnJheSx0KSxORj0odCk9PkhpKEludDhBcnJheSx0KSxGRj0odCk9PkhpKEludDE2QXJyYXksdCksTUY9KHQpPT5IaShJbnQzMkFycmF5LHQpLHNfPSh0KT0+SGkoVWludDhBcnJheSx0KSxMRj0odCk9PkhpKFVpbnQxNkFycmF5LHQpLFVGPSh0KT0+SGkoVWludDMyQXJyYXksdCksUkY9KHQpPT5IaShGbG9hdDMyQXJyYXksdCksQ0Y9KHQpPT5IaShGbG9hdDY0QXJyYXksdCksUEY9KHQpPT5IaShVaW50OENsYW1wZWRBcnJheSx0KTt2YXIgWWU9bSgoKT0+e09uKCk7VXMoKTtuXz10eXBlb2YgU2hhcmVkQXJyYXlCdWZmZXI8InUiP1NoYXJlZEFycmF5QnVmZmVyOkFycmF5QnVmZmVyfSk7ZnVuY3Rpb24qa0YodCl7bGV0IGUscj0hMSxuPVtdLGkscyxvLGE9MDtmdW5jdGlvbiBsKCl7aWYocz09PSJwZWVrIilyZXR1cm4gRm4obixvKVswXTtyZXR1cm5baSxuLGFdPUZuKG4sbyksaX0oe2NtZDpzLHNpemU6b309KHlpZWxkKCgpPT5udWxsKSgpKXx8e2NtZDoicmVhZCIsc2l6ZTowfSk7bGV0IHU9aV8odClbU3ltYm9sLml0ZXJhdG9yXSgpO3RyeXtkb3tpZih7ZG9uZTplLHZhbHVlOml9PU51bWJlci5pc05hTihvLWEpP3UubmV4dCgpOnUubmV4dChvLWEpLCFlJiZpLmJ5dGVMZW5ndGg+MCluLnB1c2goaSksYSs9aS5ieXRlTGVuZ3RoO2lmKGV8fG88PWEpZG8oe2NtZDpzLHNpemU6b309eWllbGQgbCgpKTt3aGlsZShvPGEpfXdoaWxlKCFlKX1jYXRjaChmKXtyPSEwLHR5cGVvZiB1LnRocm93PT09ImZ1bmN0aW9uIiYmdS50aHJvdyhmKX1maW5hbGx5e3I9PT0hMSYmdHlwZW9mIHUucmV0dXJuPT09ImZ1bmN0aW9uIiYmdS5yZXR1cm4obnVsbCl9cmV0dXJuIG51bGx9ZnVuY3Rpb24gVkYodCl7cmV0dXJuIEVuKHRoaXMsYXJndW1lbnRzLGZ1bmN0aW9uKigpe2xldCByLG49ITEsaT1bXSxzLG8sYSxsPTA7ZnVuY3Rpb24gdSgpe2lmKG89PT0icGVlayIpcmV0dXJuIEZuKGksYSlbMF07cmV0dXJuW3MsaSxsXT1GbihpLGEpLHN9KHtjbWQ6byxzaXplOmF9PSh5aWVsZCB5aWVsZCBndCgoKCk9Pm51bGwpKCkpKXx8e2NtZDoicmVhZCIsc2l6ZTowfSk7bGV0IGY9c18odClbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCk7dHJ5e2Rve2lmKHtkb25lOnIsdmFsdWU6c309TnVtYmVyLmlzTmFOKGEtbCk/eWllbGQgZ3QoZi5uZXh0KCkpOnlpZWxkIGd0KGYubmV4dChhLWwpKSwhciYmcy5ieXRlTGVuZ3RoPjApaS5wdXNoKHMpLGwrPXMuYnl0ZUxlbmd0aDtpZihyfHxhPD1sKWRvKHtjbWQ6byxzaXplOmF9PXlpZWxkIHlpZWxkIGd0KHUoKSkpO3doaWxlKGE8bCl9d2hpbGUoIXIpfWNhdGNoKHApe249ITAsdHlwZW9mIGYudGhyb3c9PT0iZnVuY3Rpb24iJiYoeWllbGQgZ3QoZi50aHJvdyhwKSkpfWZpbmFsbHl7bj09PSExJiZ0eXBlb2YgZi5yZXR1cm49PT0iZnVuY3Rpb24iJiYoeWllbGQgZ3QoZi5yZXR1cm4obmV3IFVpbnQ4QXJyYXkoMCkpKSl9cmV0dXJuIHlpZWxkIGd0KG51bGwpfSl9ZnVuY3Rpb24gekYodCl7cmV0dXJuIEVuKHRoaXMsYXJndW1lbnRzLGZ1bmN0aW9uKigpe2xldCByPSExLG49ITEsaT1bXSxzLG8sYSxsPTA7ZnVuY3Rpb24gdSgpe2lmKG89PT0icGVlayIpcmV0dXJuIEZuKGksYSlbMF07cmV0dXJuW3MsaSxsXT1GbihpLGEpLHN9KHtjbWQ6byxzaXplOmF9PSh5aWVsZCB5aWVsZCBndCgoKCk9Pm51bGwpKCkpKXx8e2NtZDoicmVhZCIsc2l6ZTowfSk7bGV0IGY9bmV3IFlJKHQpO3RyeXtkb3tpZih7ZG9uZTpyLHZhbHVlOnN9PU51bWJlci5pc05hTihhLWwpP3lpZWxkIGd0KGYucmVhZCgpKTp5aWVsZCBndChmLnJlYWQoYS1sKSksIXImJnMuYnl0ZUxlbmd0aD4wKWkucHVzaChrKHMpKSxsKz1zLmJ5dGVMZW5ndGg7aWYocnx8YTw9bClkbyh7Y21kOm8sc2l6ZTphfT15aWVsZCB5aWVsZCBndCh1KCkpKTt3aGlsZShhPGwpfXdoaWxlKCFyKX1jYXRjaChwKXtuPSEwLHlpZWxkIGd0KGYuY2FuY2VsKHApKX1maW5hbGx5e249PT0hMT95aWVsZCBndChmLmNhbmNlbCgpKTp0LmxvY2tlZCYmZi5yZWxlYXNlTG9jaygpfXJldHVybiB5aWVsZCBndChudWxsKX0pfWNsYXNzIFlJe2NvbnN0cnVjdG9yKHQpe3RoaXMuc291cmNlPXQsdGhpcy5yZWFkZXI9bnVsbCx0aGlzLnJlYWRlcj10aGlzLnNvdXJjZS5nZXRSZWFkZXIoKSx0aGlzLnJlYWRlci5jbG9zZWQuY2F0Y2goKCk9Pnt9KX1nZXQgY2xvc2VkKCl7cmV0dXJuIHRoaXMucmVhZGVyP3RoaXMucmVhZGVyLmNsb3NlZC5jYXRjaCgoKT0+e30pOlByb21pc2UucmVzb2x2ZSgpfXJlbGVhc2VMb2NrKCl7aWYodGhpcy5yZWFkZXIpdGhpcy5yZWFkZXIucmVsZWFzZUxvY2soKTt0aGlzLnJlYWRlcj1udWxsfWNhbmNlbCh0KXtyZXR1cm4gTyh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7bGV0e3JlYWRlcjplLHNvdXJjZTpyfT10aGlzO2UmJih5aWVsZCBlLmNhbmNlbCh0KS5jYXRjaCgoKT0+e30pKSxyJiYoci5sb2NrZWQmJnRoaXMucmVsZWFzZUxvY2soKSl9KX1yZWFkKHQpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtpZih0PT09MClyZXR1cm57ZG9uZTp0aGlzLnJlYWRlcj09bnVsbCx2YWx1ZTpuZXcgVWludDhBcnJheSgwKX07bGV0IGU9eWllbGQgdGhpcy5yZWFkZXIucmVhZCgpO3JldHVybiFlLmRvbmUmJihlLnZhbHVlPWsoZSkpLGV9KX19ZnVuY3Rpb24gakYodCl7cmV0dXJuIEVuKHRoaXMsYXJndW1lbnRzLGZ1bmN0aW9uKigpe2xldCByPVtdLG49ImVycm9yIixpPSExLHM9bnVsbCxvLGEsbD0wLHU9W10sZjtmdW5jdGlvbiBwKCl7aWYobz09PSJwZWVrIilyZXR1cm4gRm4odSxhKVswXTtyZXR1cm5bZix1LGxdPUZuKHUsYSksZn1pZih7Y21kOm8sc2l6ZTphfT0oeWllbGQgeWllbGQgZ3QoKCgpPT5udWxsKSgpKSl8fHtjbWQ6InJlYWQiLHNpemU6MH0sdC5pc1RUWSlyZXR1cm4geWllbGQgeWllbGQgZ3QobmV3IFVpbnQ4QXJyYXkoMCkpLHlpZWxkIGd0KG51bGwpO3RyeXtyWzBdPWNfKHQsImVuZCIpLHJbMV09Y18odCwiZXJyb3IiKTtkb3tpZihyWzJdPWNfKHQsInJlYWRhYmxlIiksW24sc109eWllbGQgZ3QoUHJvbWlzZS5yYWNlKHIubWFwKCh2KT0+dlsyXSkpKSxuPT09ImVycm9yIilicmVhaztpZighKGk9bj09PSJlbmQiKSl7aWYoIU51bWJlci5pc0Zpbml0ZShhLWwpKWY9ayh0LnJlYWQoKSk7ZWxzZSBpZihmPWsodC5yZWFkKGEtbCkpLGYuYnl0ZUxlbmd0aDxhLWwpZj1rKHQucmVhZCgpKTtpZihmLmJ5dGVMZW5ndGg+MCl1LnB1c2goZiksbCs9Zi5ieXRlTGVuZ3RofWlmKGl8fGE8PWwpZG8oe2NtZDpvLHNpemU6YX09eWllbGQgeWllbGQgZ3QocCgpKSk7d2hpbGUoYTxsKX13aGlsZSghaSl9ZmluYWxseXt5aWVsZCBndChnKHIsbj09PSJlcnJvciI/czpudWxsKSl9cmV0dXJuIHlpZWxkIGd0KG51bGwpO2Z1bmN0aW9uIGcodixJKXtyZXR1cm4gZj11PW51bGwsbmV3IFByb21pc2UoKEQsWik9Pntmb3IobGV0W210LHBlXW9mIHYpdC5vZmYobXQscGUpO3RyeXtsZXQgbXQ9dC5kZXN0cm95O210JiZtdC5jYWxsKHQsSSksST12b2lkIDB9Y2F0Y2gobXQpe0k9bXR8fEl9ZmluYWxseXtJIT1udWxsP1ooSSk6RCgpfX0pfX0pfXZhciBwcixuaD0odCk9Pih0Lm5leHQoKSx0KSxjXz0odCxlKT0+e2xldCByPShpKT0+bihbZSxpXSksbjtyZXR1cm5bZSxyLG5ldyBQcm9taXNlKChpKT0+KG49aSkmJnQub25jZShlLHIpKV19O3ZhciBwdT1tKCgpPT57T24oKTtZZSgpO3ByPXtmcm9tSXRlcmFibGUodCl7cmV0dXJuIG5oKGtGKHQpKX0sZnJvbUFzeW5jSXRlcmFibGUodCl7cmV0dXJuIG5oKFZGKHQpKX0sZnJvbURPTVN0cmVhbSh0KXtyZXR1cm4gbmgoekYodCkpfSxmcm9tTm9kZVN0cmVhbSh0KXtyZXR1cm4gbmgoakYodCkpfSx0b0RPTVN0cmVhbSh0LGUpe3Rocm93IEVycm9yKCcidG9ET01TdHJlYW0iIG5vdCBhdmFpbGFibGUgaW4gdGhpcyBlbnZpcm9ubWVudCcpfSx0b05vZGVTdHJlYW0odCxlKXt0aHJvdyBFcnJvcignInRvTm9kZVN0cmVhbSIgbm90IGF2YWlsYWJsZSBpbiB0aGlzIGVudmlyb25tZW50Jyl9fX0pO3ZhciBIdDt2YXIgaWg9bSgoKT0+eyhmdW5jdGlvbih0KXt0W3QuVjE9MF09IlYxIix0W3QuVjI9MV09IlYyIix0W3QuVjM9Ml09IlYzIix0W3QuVjQ9M109IlY0Iix0W3QuVjU9NF09IlY1In0pKEh0fHwoSHQ9e30pKX0pO3ZhciBzZTt2YXIgbF89bSgoKT0+eyhmdW5jdGlvbih0KXt0W3QuU3BhcnNlPTBdPSJTcGFyc2UiLHRbdC5EZW5zZT0xXT0iRGVuc2UifSkoc2V8fChzZT17fSkpfSk7dmFyIHJlO3ZhciB1Xz1tKCgpPT57KGZ1bmN0aW9uKHQpe3RbdC5IQUxGPTBdPSJIQUxGIix0W3QuU0lOR0xFPTFdPSJTSU5HTEUiLHRbdC5ET1VCTEU9Ml09IkRPVUJMRSJ9KShyZXx8KHJlPXt9KSl9KTt2YXIgSWU7dmFyIGZfPW0oKCk9PnsoZnVuY3Rpb24odCl7dFt0LkRBWT0wXT0iREFZIix0W3QuTUlMTElTRUNPTkQ9MV09Ik1JTExJU0VDT05EIn0pKEllfHwoSWU9e30pKX0pO3ZhciBSO3ZhciBtdT1tKCgpPT57KGZ1bmN0aW9uKHQpe3RbdC5TRUNPTkQ9MF09IlNFQ09ORCIsdFt0Lk1JTExJU0VDT05EPTFdPSJNSUxMSVNFQ09ORCIsdFt0Lk1JQ1JPU0VDT05EPTJdPSJNSUNST1NFQ09ORCIsdFt0Lk5BTk9TRUNPTkQ9M109Ik5BTk9TRUNPTkQifSkoUnx8KFI9e30pKX0pO3ZhciBjZTt2YXIgZF89bSgoKT0+eyhmdW5jdGlvbih0KXt0W3QuWUVBUl9NT05USD0wXT0iWUVBUl9NT05USCIsdFt0LkRBWV9USU1FPTFdPSJEQVlfVElNRSIsdFt0Lk1PTlRIX0RBWV9OQU5PPTJdPSJNT05USF9EQVlfTkFOTyJ9KShjZXx8KGNlPXt9KSl9KTt2YXIgeXU9MixNbj00LHJpPTQsTD00O3ZhciBkcyxzaCxvaCxqYzt2YXIgaF89bSgoKT0+e2RzPW5ldyBJbnQzMkFycmF5KDIpLHNoPW5ldyBGbG9hdDMyQXJyYXkoZHMuYnVmZmVyKSxvaD1uZXcgRmxvYXQ2NEFycmF5KGRzLmJ1ZmZlciksamM9bmV3IFVpbnQxNkFycmF5KG5ldyBVaW50OEFycmF5KFsxLDBdKS5idWZmZXIpWzBdPT09MX0pO3ZhciBfdTt2YXIgcF89bSgoKT0+eyhmdW5jdGlvbih0KXt0W3QuVVRGOF9CWVRFUz0xXT0iVVRGOF9CWVRFUyIsdFt0LlVURjE2X1NUUklORz0yXT0iVVRGMTZfU1RSSU5HIn0pKF91fHwoX3U9e30pKX0pO2NsYXNzIG1ye2NvbnN0cnVjdG9yKHQpe3RoaXMuYnl0ZXNfPXQsdGhpcy5wb3NpdGlvbl89MCx0aGlzLnRleHRfZGVjb2Rlcl89bmV3IFRleHREZWNvZGVyfXN0YXRpYyBhbGxvY2F0ZSh0KXtyZXR1cm4gbmV3IG1yKG5ldyBVaW50OEFycmF5KHQpKX1jbGVhcigpe3RoaXMucG9zaXRpb25fPTB9Ynl0ZXMoKXtyZXR1cm4gdGhpcy5ieXRlc199cG9zaXRpb24oKXtyZXR1cm4gdGhpcy5wb3NpdGlvbl99c2V0UG9zaXRpb24odCl7dGhpcy5wb3NpdGlvbl89dH1jYXBhY2l0eSgpe3JldHVybiB0aGlzLmJ5dGVzXy5sZW5ndGh9cmVhZEludDgodCl7cmV0dXJuIHRoaXMucmVhZFVpbnQ4KHQpPDwyND4+MjR9cmVhZFVpbnQ4KHQpe3JldHVybiB0aGlzLmJ5dGVzX1t0XX1yZWFkSW50MTYodCl7cmV0dXJuIHRoaXMucmVhZFVpbnQxNih0KTw8MTY+PjE2fXJlYWRVaW50MTYodCl7cmV0dXJuIHRoaXMuYnl0ZXNfW3RdfHRoaXMuYnl0ZXNfW3QrMV08PDh9cmVhZEludDMyKHQpe3JldHVybiB0aGlzLmJ5dGVzX1t0XXx0aGlzLmJ5dGVzX1t0KzFdPDw4fHRoaXMuYnl0ZXNfW3QrMl08PDE2fHRoaXMuYnl0ZXNfW3QrM108PDI0fXJlYWRVaW50MzIodCl7cmV0dXJuIHRoaXMucmVhZEludDMyKHQpPj4+MH1yZWFkSW50NjQodCl7cmV0dXJuIEJpZ0ludC5hc0ludE4oNjQsQmlnSW50KHRoaXMucmVhZFVpbnQzMih0KSkrKEJpZ0ludCh0aGlzLnJlYWRVaW50MzIodCs0KSk8PEJpZ0ludCgzMikpKX1yZWFkVWludDY0KHQpe3JldHVybiBCaWdJbnQuYXNVaW50Tig2NCxCaWdJbnQodGhpcy5yZWFkVWludDMyKHQpKSsoQmlnSW50KHRoaXMucmVhZFVpbnQzMih0KzQpKTw8QmlnSW50KDMyKSkpfXJlYWRGbG9hdDMyKHQpe3JldHVybiBkc1swXT10aGlzLnJlYWRJbnQzMih0KSxzaFswXX1yZWFkRmxvYXQ2NCh0KXtyZXR1cm4gZHNbamM/MDoxXT10aGlzLnJlYWRJbnQzMih0KSxkc1tqYz8xOjBdPXRoaXMucmVhZEludDMyKHQrNCksb2hbMF19d3JpdGVJbnQ4KHQsZSl7dGhpcy5ieXRlc19bdF09ZX13cml0ZVVpbnQ4KHQsZSl7dGhpcy5ieXRlc19bdF09ZX13cml0ZUludDE2KHQsZSl7dGhpcy5ieXRlc19bdF09ZSx0aGlzLmJ5dGVzX1t0KzFdPWU+Pjh9d3JpdGVVaW50MTYodCxlKXt0aGlzLmJ5dGVzX1t0XT1lLHRoaXMuYnl0ZXNfW3QrMV09ZT4+OH13cml0ZUludDMyKHQsZSl7dGhpcy5ieXRlc19bdF09ZSx0aGlzLmJ5dGVzX1t0KzFdPWU+PjgsdGhpcy5ieXRlc19bdCsyXT1lPj4xNix0aGlzLmJ5dGVzX1t0KzNdPWU+PjI0fXdyaXRlVWludDMyKHQsZSl7dGhpcy5ieXRlc19bdF09ZSx0aGlzLmJ5dGVzX1t0KzFdPWU+PjgsdGhpcy5ieXRlc19bdCsyXT1lPj4xNix0aGlzLmJ5dGVzX1t0KzNdPWU+PjI0fXdyaXRlSW50NjQodCxlKXt0aGlzLndyaXRlSW50MzIodCxOdW1iZXIoQmlnSW50LmFzSW50TigzMixlKSkpLHRoaXMud3JpdGVJbnQzMih0KzQsTnVtYmVyKEJpZ0ludC5hc0ludE4oMzIsZT4+QmlnSW50KDMyKSkpKX13cml0ZVVpbnQ2NCh0LGUpe3RoaXMud3JpdGVVaW50MzIodCxOdW1iZXIoQmlnSW50LmFzVWludE4oMzIsZSkpKSx0aGlzLndyaXRlVWludDMyKHQrNCxOdW1iZXIoQmlnSW50LmFzVWludE4oMzIsZT4+QmlnSW50KDMyKSkpKX13cml0ZUZsb2F0MzIodCxlKXtzaFswXT1lLHRoaXMud3JpdGVJbnQzMih0LGRzWzBdKX13cml0ZUZsb2F0NjQodCxlKXtvaFswXT1lLHRoaXMud3JpdGVJbnQzMih0LGRzW2pjPzA6MV0pLHRoaXMud3JpdGVJbnQzMih0KzQsZHNbamM/MTowXSl9Z2V0QnVmZmVySWRlbnRpZmllcigpe2lmKHRoaXMuYnl0ZXNfLmxlbmd0aDx0aGlzLnBvc2l0aW9uXytNbityaSl0aHJvdyBFcnJvcigiRmxhdEJ1ZmZlcnM6IEJ5dGVCdWZmZXIgaXMgdG9vIHNob3J0IHRvIGNvbnRhaW4gYW4gaWRlbnRpZmllci4iKTtsZXQgdD0iIjtmb3IobGV0IGU9MDtlPHJpO2UrKyl0Kz1TdHJpbmcuZnJvbUNoYXJDb2RlKHRoaXMucmVhZEludDgodGhpcy5wb3NpdGlvbl8rTW4rZSkpO3JldHVybiB0fV9fb2Zmc2V0KHQsZSl7bGV0IHI9dC10aGlzLnJlYWRJbnQzMih0KTtyZXR1cm4gZTx0aGlzLnJlYWRJbnQxNihyKT90aGlzLnJlYWRJbnQxNihyK2UpOjB9X191bmlvbih0LGUpe3JldHVybiB0LmJiX3Bvcz1lK3RoaXMucmVhZEludDMyKGUpLHQuYmI9dGhpcyx0fV9fc3RyaW5nKHQsZSl7dCs9dGhpcy5yZWFkSW50MzIodCk7bGV0IHI9dGhpcy5yZWFkSW50MzIodCk7dCs9TW47bGV0IG49dGhpcy5ieXRlc18uc3ViYXJyYXkodCx0K3IpO2lmKGU9PT1fdS5VVEY4X0JZVEVTKXJldHVybiBuO2Vsc2UgcmV0dXJuIHRoaXMudGV4dF9kZWNvZGVyXy5kZWNvZGUobil9X191bmlvbl93aXRoX3N0cmluZyh0LGUpe2lmKHR5cGVvZiB0PT09InN0cmluZyIpcmV0dXJuIHRoaXMuX19zdHJpbmcoZSk7cmV0dXJuIHRoaXMuX191bmlvbih0LGUpfV9faW5kaXJlY3QodCl7cmV0dXJuIHQrdGhpcy5yZWFkSW50MzIodCl9X192ZWN0b3IodCl7cmV0dXJuIHQrdGhpcy5yZWFkSW50MzIodCkrTW59X192ZWN0b3JfbGVuKHQpe3JldHVybiB0aGlzLnJlYWRJbnQzMih0K3RoaXMucmVhZEludDMyKHQpKX1fX2hhc19pZGVudGlmaWVyKHQpe2lmKHQubGVuZ3RoIT1yaSl0aHJvdyBFcnJvcigiRmxhdEJ1ZmZlcnM6IGZpbGUgaWRlbnRpZmllciBtdXN0IGJlIGxlbmd0aCAiK3JpKTtmb3IobGV0IGU9MDtlPHJpO2UrKylpZih0LmNoYXJDb2RlQXQoZSkhPXRoaXMucmVhZEludDgodGhpcy5wb3NpdGlvbigpK01uK2UpKXJldHVybiExO3JldHVybiEwfWNyZWF0ZVNjYWxhckxpc3QodCxlKXtsZXQgcj1bXTtmb3IobGV0IG49MDtuPGU7KytuKXtsZXQgaT10KG4pO2lmKGkhPT1udWxsKXIucHVzaChpKX1yZXR1cm4gcn1jcmVhdGVPYmpMaXN0KHQsZSl7bGV0IHI9W107Zm9yKGxldCBuPTA7bjxlOysrbil7bGV0IGk9dChuKTtpZihpIT09bnVsbClyLnB1c2goaS51bnBhY2soKSl9cmV0dXJuIHJ9fXZhciBtXz1tKCgpPT57cF8oKTtoXygpfSk7Y2xhc3MgVGF7Y29uc3RydWN0b3IodCl7dGhpcy5taW5hbGlnbj0xLHRoaXMudnRhYmxlPW51bGwsdGhpcy52dGFibGVfaW5fdXNlPTAsdGhpcy5pc05lc3RlZD0hMSx0aGlzLm9iamVjdF9zdGFydD0wLHRoaXMudnRhYmxlcz1bXSx0aGlzLnZlY3Rvcl9udW1fZWxlbXM9MCx0aGlzLmZvcmNlX2RlZmF1bHRzPSExLHRoaXMuc3RyaW5nX21hcHM9bnVsbCx0aGlzLnRleHRfZW5jb2Rlcj1uZXcgVGV4dEVuY29kZXI7bGV0IGU7aWYoIXQpZT0xMDI0O2Vsc2UgZT10O3RoaXMuYmI9bXIuYWxsb2NhdGUoZSksdGhpcy5zcGFjZT1lfWNsZWFyKCl7dGhpcy5iYi5jbGVhcigpLHRoaXMuc3BhY2U9dGhpcy5iYi5jYXBhY2l0eSgpLHRoaXMubWluYWxpZ249MSx0aGlzLnZ0YWJsZT1udWxsLHRoaXMudnRhYmxlX2luX3VzZT0wLHRoaXMuaXNOZXN0ZWQ9ITEsdGhpcy5vYmplY3Rfc3RhcnQ9MCx0aGlzLnZ0YWJsZXM9W10sdGhpcy52ZWN0b3JfbnVtX2VsZW1zPTAsdGhpcy5mb3JjZV9kZWZhdWx0cz0hMSx0aGlzLnN0cmluZ19tYXBzPW51bGx9Zm9yY2VEZWZhdWx0cyh0KXt0aGlzLmZvcmNlX2RlZmF1bHRzPXR9ZGF0YUJ1ZmZlcigpe3JldHVybiB0aGlzLmJifWFzVWludDhBcnJheSgpe3JldHVybiB0aGlzLmJiLmJ5dGVzKCkuc3ViYXJyYXkodGhpcy5iYi5wb3NpdGlvbigpLHRoaXMuYmIucG9zaXRpb24oKSt0aGlzLm9mZnNldCgpKX1wcmVwKHQsZSl7aWYodD50aGlzLm1pbmFsaWduKXRoaXMubWluYWxpZ249dDtsZXQgcj1+KHRoaXMuYmIuY2FwYWNpdHkoKS10aGlzLnNwYWNlK2UpKzEmdC0xO3doaWxlKHRoaXMuc3BhY2U8cit0K2Upe2xldCBuPXRoaXMuYmIuY2FwYWNpdHkoKTt0aGlzLmJiPVRhLmdyb3dCeXRlQnVmZmVyKHRoaXMuYmIpLHRoaXMuc3BhY2UrPXRoaXMuYmIuY2FwYWNpdHkoKS1ufXRoaXMucGFkKHIpfXBhZCh0KXtmb3IobGV0IGU9MDtlPHQ7ZSsrKXRoaXMuYmIud3JpdGVJbnQ4KC0tdGhpcy5zcGFjZSwwKX13cml0ZUludDgodCl7dGhpcy5iYi53cml0ZUludDgodGhpcy5zcGFjZS09MSx0KX13cml0ZUludDE2KHQpe3RoaXMuYmIud3JpdGVJbnQxNih0aGlzLnNwYWNlLT0yLHQpfXdyaXRlSW50MzIodCl7dGhpcy5iYi53cml0ZUludDMyKHRoaXMuc3BhY2UtPTQsdCl9d3JpdGVJbnQ2NCh0KXt0aGlzLmJiLndyaXRlSW50NjQodGhpcy5zcGFjZS09OCx0KX13cml0ZUZsb2F0MzIodCl7dGhpcy5iYi53cml0ZUZsb2F0MzIodGhpcy5zcGFjZS09NCx0KX13cml0ZUZsb2F0NjQodCl7dGhpcy5iYi53cml0ZUZsb2F0NjQodGhpcy5zcGFjZS09OCx0KX1hZGRJbnQ4KHQpe3RoaXMucHJlcCgxLDApLHRoaXMud3JpdGVJbnQ4KHQpfWFkZEludDE2KHQpe3RoaXMucHJlcCgyLDApLHRoaXMud3JpdGVJbnQxNih0KX1hZGRJbnQzMih0KXt0aGlzLnByZXAoNCwwKSx0aGlzLndyaXRlSW50MzIodCl9YWRkSW50NjQodCl7dGhpcy5wcmVwKDgsMCksdGhpcy53cml0ZUludDY0KHQpfWFkZEZsb2F0MzIodCl7dGhpcy5wcmVwKDQsMCksdGhpcy53cml0ZUZsb2F0MzIodCl9YWRkRmxvYXQ2NCh0KXt0aGlzLnByZXAoOCwwKSx0aGlzLndyaXRlRmxvYXQ2NCh0KX1hZGRGaWVsZEludDgodCxlLHIpe2lmKHRoaXMuZm9yY2VfZGVmYXVsdHN8fGUhPXIpdGhpcy5hZGRJbnQ4KGUpLHRoaXMuc2xvdCh0KX1hZGRGaWVsZEludDE2KHQsZSxyKXtpZih0aGlzLmZvcmNlX2RlZmF1bHRzfHxlIT1yKXRoaXMuYWRkSW50MTYoZSksdGhpcy5zbG90KHQpfWFkZEZpZWxkSW50MzIodCxlLHIpe2lmKHRoaXMuZm9yY2VfZGVmYXVsdHN8fGUhPXIpdGhpcy5hZGRJbnQzMihlKSx0aGlzLnNsb3QodCl9YWRkRmllbGRJbnQ2NCh0LGUscil7aWYodGhpcy5mb3JjZV9kZWZhdWx0c3x8ZSE9PXIpdGhpcy5hZGRJbnQ2NChlKSx0aGlzLnNsb3QodCl9YWRkRmllbGRGbG9hdDMyKHQsZSxyKXtpZih0aGlzLmZvcmNlX2RlZmF1bHRzfHxlIT1yKXRoaXMuYWRkRmxvYXQzMihlKSx0aGlzLnNsb3QodCl9YWRkRmllbGRGbG9hdDY0KHQsZSxyKXtpZih0aGlzLmZvcmNlX2RlZmF1bHRzfHxlIT1yKXRoaXMuYWRkRmxvYXQ2NChlKSx0aGlzLnNsb3QodCl9YWRkRmllbGRPZmZzZXQodCxlLHIpe2lmKHRoaXMuZm9yY2VfZGVmYXVsdHN8fGUhPXIpdGhpcy5hZGRPZmZzZXQoZSksdGhpcy5zbG90KHQpfWFkZEZpZWxkU3RydWN0KHQsZSxyKXtpZihlIT1yKXRoaXMubmVzdGVkKGUpLHRoaXMuc2xvdCh0KX1uZXN0ZWQodCl7aWYodCE9dGhpcy5vZmZzZXQoKSl0aHJvdyBUeXBlRXJyb3IoIkZsYXRCdWZmZXJzOiBzdHJ1Y3QgbXVzdCBiZSBzZXJpYWxpemVkIGlubGluZS4iKX1ub3ROZXN0ZWQoKXtpZih0aGlzLmlzTmVzdGVkKXRocm93IFR5cGVFcnJvcigiRmxhdEJ1ZmZlcnM6IG9iamVjdCBzZXJpYWxpemF0aW9uIG11c3Qgbm90IGJlIG5lc3RlZC4iKX1zbG90KHQpe2lmKHRoaXMudnRhYmxlIT09bnVsbCl0aGlzLnZ0YWJsZVt0XT10aGlzLm9mZnNldCgpfW9mZnNldCgpe3JldHVybiB0aGlzLmJiLmNhcGFjaXR5KCktdGhpcy5zcGFjZX1zdGF0aWMgZ3Jvd0J5dGVCdWZmZXIodCl7bGV0IGU9dC5jYXBhY2l0eSgpO2lmKGUmMzIyMTIyNTQ3Mil0aHJvdyBFcnJvcigiRmxhdEJ1ZmZlcnM6IGNhbm5vdCBncm93IGJ1ZmZlciBiZXlvbmQgMiBnaWdhYnl0ZXMuIik7bGV0IHI9ZTw8MSxuPW1yLmFsbG9jYXRlKHIpO3JldHVybiBuLnNldFBvc2l0aW9uKHItZSksbi5ieXRlcygpLnNldCh0LmJ5dGVzKCksci1lKSxufWFkZE9mZnNldCh0KXt0aGlzLnByZXAoTW4sMCksdGhpcy53cml0ZUludDMyKHRoaXMub2Zmc2V0KCktdCtNbil9c3RhcnRPYmplY3QodCl7aWYodGhpcy5ub3ROZXN0ZWQoKSx0aGlzLnZ0YWJsZT09bnVsbCl0aGlzLnZ0YWJsZT1bXTt0aGlzLnZ0YWJsZV9pbl91c2U9dDtmb3IobGV0IGU9MDtlPHQ7ZSsrKXRoaXMudnRhYmxlW2VdPTA7dGhpcy5pc05lc3RlZD0hMCx0aGlzLm9iamVjdF9zdGFydD10aGlzLm9mZnNldCgpfWVuZE9iamVjdCgpe2lmKHRoaXMudnRhYmxlPT1udWxsfHwhdGhpcy5pc05lc3RlZCl0aHJvdyBFcnJvcigiRmxhdEJ1ZmZlcnM6IGVuZE9iamVjdCBjYWxsZWQgd2l0aG91dCBzdGFydE9iamVjdCIpO3RoaXMuYWRkSW50MzIoMCk7bGV0IHQ9dGhpcy5vZmZzZXQoKSxlPXRoaXMudnRhYmxlX2luX3VzZS0xO2Zvcig7ZT49MCYmdGhpcy52dGFibGVbZV09PTA7ZS0tKTtsZXQgcj1lKzE7Zm9yKDtlPj0wO2UtLSl0aGlzLmFkZEludDE2KHRoaXMudnRhYmxlW2VdIT0wP3QtdGhpcy52dGFibGVbZV06MCk7bGV0IG49Mjt0aGlzLmFkZEludDE2KHQtdGhpcy5vYmplY3Rfc3RhcnQpO2xldCBpPShyK24pKnl1O3RoaXMuYWRkSW50MTYoaSk7bGV0IHM9MCxvPXRoaXMuc3BhY2U7dDpmb3IoZT0wO2U8dGhpcy52dGFibGVzLmxlbmd0aDtlKyspe2xldCBhPXRoaXMuYmIuY2FwYWNpdHkoKS10aGlzLnZ0YWJsZXNbZV07aWYoaT09dGhpcy5iYi5yZWFkSW50MTYoYSkpe2ZvcihsZXQgbD15dTtsPGk7bCs9eXUpaWYodGhpcy5iYi5yZWFkSW50MTYobytsKSE9dGhpcy5iYi5yZWFkSW50MTYoYStsKSljb250aW51ZSB0O3M9dGhpcy52dGFibGVzW2VdO2JyZWFrfX1pZihzKXRoaXMuc3BhY2U9dGhpcy5iYi5jYXBhY2l0eSgpLXQsdGhpcy5iYi53cml0ZUludDMyKHRoaXMuc3BhY2Uscy10KTtlbHNlIHRoaXMudnRhYmxlcy5wdXNoKHRoaXMub2Zmc2V0KCkpLHRoaXMuYmIud3JpdGVJbnQzMih0aGlzLmJiLmNhcGFjaXR5KCktdCx0aGlzLm9mZnNldCgpLXQpO3JldHVybiB0aGlzLmlzTmVzdGVkPSExLHR9ZmluaXNoKHQsZSxyKXtsZXQgbj1yP0w6MDtpZihlKXtsZXQgaT1lO2lmKHRoaXMucHJlcCh0aGlzLm1pbmFsaWduLE1uK3JpK24pLGkubGVuZ3RoIT1yaSl0aHJvdyBUeXBlRXJyb3IoIkZsYXRCdWZmZXJzOiBmaWxlIGlkZW50aWZpZXIgbXVzdCBiZSBsZW5ndGggIityaSk7Zm9yKGxldCBzPXJpLTE7cz49MDtzLS0pdGhpcy53cml0ZUludDgoaS5jaGFyQ29kZUF0KHMpKX1pZih0aGlzLnByZXAodGhpcy5taW5hbGlnbixNbituKSx0aGlzLmFkZE9mZnNldCh0KSxuKXRoaXMuYWRkSW50MzIodGhpcy5iYi5jYXBhY2l0eSgpLXRoaXMuc3BhY2UpO3RoaXMuYmIuc2V0UG9zaXRpb24odGhpcy5zcGFjZSl9ZmluaXNoU2l6ZVByZWZpeGVkKHQsZSl7dGhpcy5maW5pc2godCxlLCEwKX1yZXF1aXJlZEZpZWxkKHQsZSl7bGV0IHI9dGhpcy5iYi5jYXBhY2l0eSgpLXQsbj1yLXRoaXMuYmIucmVhZEludDMyKHIpO2lmKCEoZTx0aGlzLmJiLnJlYWRJbnQxNihuKSYmdGhpcy5iYi5yZWFkSW50MTYobitlKSE9MCkpdGhyb3cgVHlwZUVycm9yKCJGbGF0QnVmZmVyczogZmllbGQgIitlKyIgbXVzdCBiZSBzZXQiKX1zdGFydFZlY3Rvcih0LGUscil7dGhpcy5ub3ROZXN0ZWQoKSx0aGlzLnZlY3Rvcl9udW1fZWxlbXM9ZSx0aGlzLnByZXAoTW4sdCplKSx0aGlzLnByZXAocix0KmUpfWVuZFZlY3Rvcigpe3JldHVybiB0aGlzLndyaXRlSW50MzIodGhpcy52ZWN0b3JfbnVtX2VsZW1zKSx0aGlzLm9mZnNldCgpfWNyZWF0ZVNoYXJlZFN0cmluZyh0KXtpZighdClyZXR1cm4gMDtpZighdGhpcy5zdHJpbmdfbWFwcyl0aGlzLnN0cmluZ19tYXBzPW5ldyBNYXA7aWYodGhpcy5zdHJpbmdfbWFwcy5oYXModCkpcmV0dXJuIHRoaXMuc3RyaW5nX21hcHMuZ2V0KHQpO2xldCBlPXRoaXMuY3JlYXRlU3RyaW5nKHQpO3JldHVybiB0aGlzLnN0cmluZ19tYXBzLnNldCh0LGUpLGV9Y3JlYXRlU3RyaW5nKHQpe2lmKHQ9PT1udWxsfHx0PT09dm9pZCAwKXJldHVybiAwO2xldCBlO2lmKHQgaW5zdGFuY2VvZiBVaW50OEFycmF5KWU9dDtlbHNlIGU9dGhpcy50ZXh0X2VuY29kZXIuZW5jb2RlKHQpO3JldHVybiB0aGlzLmFkZEludDgoMCksdGhpcy5zdGFydFZlY3RvcigxLGUubGVuZ3RoLDEpLHRoaXMuYmIuc2V0UG9zaXRpb24odGhpcy5zcGFjZS09ZS5sZW5ndGgpLHRoaXMuYmIuYnl0ZXMoKS5zZXQoZSx0aGlzLnNwYWNlKSx0aGlzLmVuZFZlY3RvcigpfWNyZWF0ZUJ5dGVWZWN0b3IodCl7aWYodD09PW51bGx8fHQ9PT12b2lkIDApcmV0dXJuIDA7cmV0dXJuIHRoaXMuc3RhcnRWZWN0b3IoMSx0Lmxlbmd0aCwxKSx0aGlzLmJiLnNldFBvc2l0aW9uKHRoaXMuc3BhY2UtPXQubGVuZ3RoKSx0aGlzLmJiLmJ5dGVzKCkuc2V0KHQsdGhpcy5zcGFjZSksdGhpcy5lbmRWZWN0b3IoKX1jcmVhdGVPYmplY3RPZmZzZXQodCl7aWYodD09PW51bGwpcmV0dXJuIDA7aWYodHlwZW9mIHQ9PT0ic3RyaW5nIilyZXR1cm4gdGhpcy5jcmVhdGVTdHJpbmcodCk7ZWxzZSByZXR1cm4gdC5wYWNrKHRoaXMpfWNyZWF0ZU9iamVjdE9mZnNldExpc3QodCl7bGV0IGU9W107Zm9yKGxldCByPTA7cjx0Lmxlbmd0aDsrK3Ipe2xldCBuPXRbcl07aWYobiE9PW51bGwpZS5wdXNoKHRoaXMuY3JlYXRlT2JqZWN0T2Zmc2V0KG4pKTtlbHNlIHRocm93IFR5cGVFcnJvcigiRmxhdEJ1ZmZlcnM6IEFyZ3VtZW50IGZvciBjcmVhdGVPYmplY3RPZmZzZXRMaXN0IGNhbm5vdCBjb250YWluIG51bGwuIil9cmV0dXJuIGV9Y3JlYXRlU3RydWN0T2Zmc2V0TGlzdCh0LGUpe3JldHVybiBlKHRoaXMsdC5sZW5ndGgpLHRoaXMuY3JlYXRlT2JqZWN0T2Zmc2V0TGlzdCh0LnNsaWNlKCkucmV2ZXJzZSgpKSx0aGlzLmVuZFZlY3RvcigpfX12YXIgS0k9bSgoKT0+e21fKCl9KTt2YXIgRnQ9bSgoKT0+e2hfKCk7S0koKTttXygpO3BfKCl9KTt2YXIgRWE7dmFyIHlfPW0oKCk9PnsoZnVuY3Rpb24odCl7dFt0LkJVRkZFUj0wXT0iQlVGRkVSIn0pKEVhfHwoRWE9e30pKX0pO3ZhciB6cjt2YXIgZ3U9bSgoKT0+eyhmdW5jdGlvbih0KXt0W3QuTFo0X0ZSQU1FPTBdPSJMWjRfRlJBTUUiLHRbdC5aU1REPTFdPSJaU1REIn0pKHpyfHwoenI9e30pKX0pO2NsYXNzIGVue2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc0JvZHlDb21wcmVzc2lvbih0LGUpe3JldHVybihlfHxuZXcgZW4pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzQm9keUNvbXByZXNzaW9uKHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK0wpLChlfHxuZXcgZW4pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1jb2RlYygpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50OCh0aGlzLmJiX3Bvcyt0KTp6ci5MWjRfRlJBTUV9bWV0aG9kKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw2KTtyZXR1cm4gdD90aGlzLmJiLnJlYWRJbnQ4KHRoaXMuYmJfcG9zK3QpOkVhLkJVRkZFUn1zdGF0aWMgc3RhcnRCb2R5Q29tcHJlc3Npb24odCl7dC5zdGFydE9iamVjdCgyKX1zdGF0aWMgYWRkQ29kZWModCxlKXt0LmFkZEZpZWxkSW50OCgwLGUsenIuTFo0X0ZSQU1FKX1zdGF0aWMgYWRkTWV0aG9kKHQsZSl7dC5hZGRGaWVsZEludDgoMSxlLEVhLkJVRkZFUil9c3RhdGljIGVuZEJvZHlDb21wcmVzc2lvbih0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgY3JlYXRlQm9keUNvbXByZXNzaW9uKHQsZSxyKXtyZXR1cm4gZW4uc3RhcnRCb2R5Q29tcHJlc3Npb24odCksZW4uYWRkQ29kZWModCxlKSxlbi5hZGRNZXRob2QodCxyKSxlbi5lbmRCb2R5Q29tcHJlc3Npb24odCl9fXZhciBfXz1tKCgpPT57RnQoKTt5XygpO2d1KCl9KTtjbGFzcyBidXtjb25zdHJ1Y3Rvcigpe3RoaXMuYmI9bnVsbCx0aGlzLmJiX3Bvcz0wfV9faW5pdCh0LGUpe3JldHVybiB0aGlzLmJiX3Bvcz10LHRoaXMuYmI9ZSx0aGlzfW9mZnNldCgpe3JldHVybiB0aGlzLmJiLnJlYWRJbnQ2NCh0aGlzLmJiX3Bvcyl9bGVuZ3RoKCl7cmV0dXJuIHRoaXMuYmIucmVhZEludDY0KHRoaXMuYmJfcG9zKzgpfXN0YXRpYyBzaXplT2YoKXtyZXR1cm4gMTZ9c3RhdGljIGNyZWF0ZUJ1ZmZlcih0LGUscil7cmV0dXJuIHQucHJlcCg4LDE2KSx0LndyaXRlSW50NjQoQmlnSW50KHIhPT1udWxsJiZyIT09dm9pZCAwP3I6MCkpLHQud3JpdGVJbnQ2NChCaWdJbnQoZSE9PW51bGwmJmUhPT12b2lkIDA/ZTowKSksdC5vZmZzZXQoKX19Y2xhc3Mgd3V7Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31sZW5ndGgoKXtyZXR1cm4gdGhpcy5iYi5yZWFkSW50NjQodGhpcy5iYl9wb3MpfW51bGxDb3VudCgpe3JldHVybiB0aGlzLmJiLnJlYWRJbnQ2NCh0aGlzLmJiX3Bvcys4KX1zdGF0aWMgc2l6ZU9mKCl7cmV0dXJuIDE2fXN0YXRpYyBjcmVhdGVGaWVsZE5vZGUodCxlLHIpe3JldHVybiB0LnByZXAoOCwxNiksdC53cml0ZUludDY0KEJpZ0ludChyIT09bnVsbCYmciE9PXZvaWQgMD9yOjApKSx0LndyaXRlSW50NjQoQmlnSW50KGUhPT1udWxsJiZlIT09dm9pZCAwP2U6MCkpLHQub2Zmc2V0KCl9fWNsYXNzIHlye2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc1JlY29yZEJhdGNoKHQsZSl7cmV0dXJuKGV8fG5ldyB5cikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNSZWNvcmRCYXRjaCh0LGUpe3JldHVybiB0LnNldFBvc2l0aW9uKHQucG9zaXRpb24oKStMKSwoZXx8bmV3IHlyKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9bGVuZ3RoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw0KTtyZXR1cm4gdD90aGlzLmJiLnJlYWRJbnQ2NCh0aGlzLmJiX3Bvcyt0KTpCaWdJbnQoIjAiKX1ub2Rlcyh0LGUpe2xldCByPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNik7cmV0dXJuIHI/KGV8fG5ldyB3dSkuX19pbml0KHRoaXMuYmIuX192ZWN0b3IodGhpcy5iYl9wb3MrcikrdCoxNix0aGlzLmJiKTpudWxsfW5vZGVzTGVuZ3RoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw2KTtyZXR1cm4gdD90aGlzLmJiLl9fdmVjdG9yX2xlbih0aGlzLmJiX3Bvcyt0KTowfWJ1ZmZlcnModCxlKXtsZXQgcj10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDgpO3JldHVybiByPyhlfHxuZXcgYnUpLl9faW5pdCh0aGlzLmJiLl9fdmVjdG9yKHRoaXMuYmJfcG9zK3IpK3QqMTYsdGhpcy5iYik6bnVsbH1idWZmZXJzTGVuZ3RoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw4KTtyZXR1cm4gdD90aGlzLmJiLl9fdmVjdG9yX2xlbih0aGlzLmJiX3Bvcyt0KTowfWNvbXByZXNzaW9uKHQpe2xldCBlPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsMTApO3JldHVybiBlPyh0fHxuZXcgZW4pLl9faW5pdCh0aGlzLmJiLl9faW5kaXJlY3QodGhpcy5iYl9wb3MrZSksdGhpcy5iYik6bnVsbH12YXJpYWRpY0J1ZmZlckNvdW50cyh0KXtsZXQgZT10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDEyKTtyZXR1cm4gZT90aGlzLmJiLnJlYWRJbnQ2NCh0aGlzLmJiLl9fdmVjdG9yKHRoaXMuYmJfcG9zK2UpK3QqOCk6QmlnSW50KDApfXZhcmlhZGljQnVmZmVyQ291bnRzTGVuZ3RoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3BvcywxMik7cmV0dXJuIHQ/dGhpcy5iYi5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MrdCk6MH1zdGF0aWMgc3RhcnRSZWNvcmRCYXRjaCh0KXt0LnN0YXJ0T2JqZWN0KDUpfXN0YXRpYyBhZGRMZW5ndGgodCxlKXt0LmFkZEZpZWxkSW50NjQoMCxlLEJpZ0ludCgiMCIpKX1zdGF0aWMgYWRkTm9kZXModCxlKXt0LmFkZEZpZWxkT2Zmc2V0KDEsZSwwKX1zdGF0aWMgc3RhcnROb2Rlc1ZlY3Rvcih0LGUpe3Quc3RhcnRWZWN0b3IoMTYsZSw4KX1zdGF0aWMgYWRkQnVmZmVycyh0LGUpe3QuYWRkRmllbGRPZmZzZXQoMixlLDApfXN0YXRpYyBzdGFydEJ1ZmZlcnNWZWN0b3IodCxlKXt0LnN0YXJ0VmVjdG9yKDE2LGUsOCl9c3RhdGljIGFkZENvbXByZXNzaW9uKHQsZSl7dC5hZGRGaWVsZE9mZnNldCgzLGUsMCl9c3RhdGljIGFkZFZhcmlhZGljQnVmZmVyQ291bnRzKHQsZSl7dC5hZGRGaWVsZE9mZnNldCg0LGUsMCl9c3RhdGljIGNyZWF0ZVZhcmlhZGljQnVmZmVyQ291bnRzVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig4LGUubGVuZ3RoLDgpO2ZvcihsZXQgcj1lLmxlbmd0aC0xO3I+PTA7ci0tKXQuYWRkSW50NjQoZVtyXSk7cmV0dXJuIHQuZW5kVmVjdG9yKCl9c3RhdGljIHN0YXJ0VmFyaWFkaWNCdWZmZXJDb3VudHNWZWN0b3IodCxlKXt0LnN0YXJ0VmVjdG9yKDgsZSw4KX1zdGF0aWMgZW5kUmVjb3JkQmF0Y2godCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9fXZhciBnXz1tKCgpPT57RnQoKTtfXygpfSk7Y2xhc3MgaHN7Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzRGljdGlvbmFyeUJhdGNoKHQsZSl7cmV0dXJuKGV8fG5ldyBocykuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNEaWN0aW9uYXJ5QmF0Y2godCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTCksKGV8fG5ldyBocykuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfWlkKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw0KTtyZXR1cm4gdD90aGlzLmJiLnJlYWRJbnQ2NCh0aGlzLmJiX3Bvcyt0KTpCaWdJbnQoIjAiKX1kYXRhKHQpe2xldCBlPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNik7cmV0dXJuIGU/KHR8fG5ldyB5cikuX19pbml0KHRoaXMuYmIuX19pbmRpcmVjdCh0aGlzLmJiX3BvcytlKSx0aGlzLmJiKTpudWxsfWlzRGVsdGEoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDgpO3JldHVybiB0PyEhdGhpcy5iYi5yZWFkSW50OCh0aGlzLmJiX3Bvcyt0KTohMX1zdGF0aWMgc3RhcnREaWN0aW9uYXJ5QmF0Y2godCl7dC5zdGFydE9iamVjdCgzKX1zdGF0aWMgYWRkSWQodCxlKXt0LmFkZEZpZWxkSW50NjQoMCxlLEJpZ0ludCgiMCIpKX1zdGF0aWMgYWRkRGF0YSh0LGUpe3QuYWRkRmllbGRPZmZzZXQoMSxlLDApfXN0YXRpYyBhZGRJc0RlbHRhKHQsZSl7dC5hZGRGaWVsZEludDgoMiwrZSwwKX1zdGF0aWMgZW5kRGljdGlvbmFyeUJhdGNoKHQpe3JldHVybiB0LmVuZE9iamVjdCgpfX12YXIgR0k9bSgoKT0+e0Z0KCk7Z18oKX0pO3ZhciBSbzt2YXIgYl89bSgoKT0+eyhmdW5jdGlvbih0KXt0W3QuTGl0dGxlPTBdPSJMaXR0bGUiLHRbdC5CaWc9MV09IkJpZyJ9KShSb3x8KFJvPXt9KSl9KTt2YXIgdnU7dmFyIEpJPW0oKCk9PnsoZnVuY3Rpb24odCl7dFt0LkRlbnNlQXJyYXk9MF09IkRlbnNlQXJyYXkifSkodnV8fCh2dT17fSkpfSk7Y2xhc3MgQXJ7Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzSW50KHQsZSl7cmV0dXJuKGV8fG5ldyBBcikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNJbnQodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTCksKGV8fG5ldyBBcikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfWJpdFdpZHRoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw0KTtyZXR1cm4gdD90aGlzLmJiLnJlYWRJbnQzMih0aGlzLmJiX3Bvcyt0KTowfWlzU2lnbmVkKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw2KTtyZXR1cm4gdD8hIXRoaXMuYmIucmVhZEludDgodGhpcy5iYl9wb3MrdCk6ITF9c3RhdGljIHN0YXJ0SW50KHQpe3Quc3RhcnRPYmplY3QoMil9c3RhdGljIGFkZEJpdFdpZHRoKHQsZSl7dC5hZGRGaWVsZEludDMyKDAsZSwwKX1zdGF0aWMgYWRkSXNTaWduZWQodCxlKXt0LmFkZEZpZWxkSW50OCgxLCtlLDApfXN0YXRpYyBlbmRJbnQodCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9c3RhdGljIGNyZWF0ZUludCh0LGUscil7cmV0dXJuIEFyLnN0YXJ0SW50KHQpLEFyLmFkZEJpdFdpZHRoKHQsZSksQXIuYWRkSXNTaWduZWQodCxyKSxBci5lbmRJbnQodCl9fXZhciBhaD1tKCgpPT57RnQoKX0pO2NsYXNzIFlpe2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc0RpY3Rpb25hcnlFbmNvZGluZyh0LGUpe3JldHVybihlfHxuZXcgWWkpLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzRGljdGlvbmFyeUVuY29kaW5nKHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK0wpLChlfHxuZXcgWWkpLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1pZCgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50NjQodGhpcy5iYl9wb3MrdCk6QmlnSW50KCIwIil9aW5kZXhUeXBlKHQpe2xldCBlPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNik7cmV0dXJuIGU/KHR8fG5ldyBBcikuX19pbml0KHRoaXMuYmIuX19pbmRpcmVjdCh0aGlzLmJiX3BvcytlKSx0aGlzLmJiKTpudWxsfWlzT3JkZXJlZCgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsOCk7cmV0dXJuIHQ/ISF0aGlzLmJiLnJlYWRJbnQ4KHRoaXMuYmJfcG9zK3QpOiExfWRpY3Rpb25hcnlLaW5kKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3BvcywxMCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50MTYodGhpcy5iYl9wb3MrdCk6dnUuRGVuc2VBcnJheX1zdGF0aWMgc3RhcnREaWN0aW9uYXJ5RW5jb2RpbmcodCl7dC5zdGFydE9iamVjdCg0KX1zdGF0aWMgYWRkSWQodCxlKXt0LmFkZEZpZWxkSW50NjQoMCxlLEJpZ0ludCgiMCIpKX1zdGF0aWMgYWRkSW5kZXhUeXBlKHQsZSl7dC5hZGRGaWVsZE9mZnNldCgxLGUsMCl9c3RhdGljIGFkZElzT3JkZXJlZCh0LGUpe3QuYWRkRmllbGRJbnQ4KDIsK2UsMCl9c3RhdGljIGFkZERpY3Rpb25hcnlLaW5kKHQsZSl7dC5hZGRGaWVsZEludDE2KDMsZSx2dS5EZW5zZUFycmF5KX1zdGF0aWMgZW5kRGljdGlvbmFyeUVuY29kaW5nKHQpe3JldHVybiB0LmVuZE9iamVjdCgpfX12YXIgd189bSgoKT0+e0Z0KCk7SkkoKTthaCgpfSk7Y2xhc3Mgb2V7Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzS2V5VmFsdWUodCxlKXtyZXR1cm4oZXx8bmV3IG9lKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0tleVZhbHVlKHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK0wpLChlfHxuZXcgb2UpLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1rZXkodCl7bGV0IGU9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw0KTtyZXR1cm4gZT90aGlzLmJiLl9fc3RyaW5nKHRoaXMuYmJfcG9zK2UsdCk6bnVsbH12YWx1ZSh0KXtsZXQgZT10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDYpO3JldHVybiBlP3RoaXMuYmIuX19zdHJpbmcodGhpcy5iYl9wb3MrZSx0KTpudWxsfXN0YXRpYyBzdGFydEtleVZhbHVlKHQpe3Quc3RhcnRPYmplY3QoMil9c3RhdGljIGFkZEtleSh0LGUpe3QuYWRkRmllbGRPZmZzZXQoMCxlLDApfXN0YXRpYyBhZGRWYWx1ZSh0LGUpe3QuYWRkRmllbGRPZmZzZXQoMSxlLDApfXN0YXRpYyBlbmRLZXlWYWx1ZSh0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgY3JlYXRlS2V5VmFsdWUodCxlLHIpe3JldHVybiBvZS5zdGFydEtleVZhbHVlKHQpLG9lLmFkZEtleSh0LGUpLG9lLmFkZFZhbHVlKHQsciksb2UuZW5kS2V5VmFsdWUodCl9fXZhciAkYz1tKCgpPT57RnQoKX0pO2NsYXNzIENve2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc0JpbmFyeSh0LGUpe3JldHVybihlfHxuZXcgQ28pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzQmluYXJ5KHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK0wpLChlfHxuZXcgQ28pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgc3RhcnRCaW5hcnkodCl7dC5zdGFydE9iamVjdCgwKX1zdGF0aWMgZW5kQmluYXJ5KHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVCaW5hcnkodCl7cmV0dXJuIENvLnN0YXJ0QmluYXJ5KHQpLENvLmVuZEJpbmFyeSh0KX19dmFyIFhJPW0oKCk9PntGdCgpfSk7Y2xhc3MgUG97Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzQmluYXJ5Vmlldyh0LGUpe3JldHVybihlfHxuZXcgUG8pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzQmluYXJ5Vmlldyh0LGUpe3JldHVybiB0LnNldFBvc2l0aW9uKHQucG9zaXRpb24oKStMKSwoZXx8bmV3IFBvKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIHN0YXJ0QmluYXJ5Vmlldyh0KXt0LnN0YXJ0T2JqZWN0KDApfXN0YXRpYyBlbmRCaW5hcnlWaWV3KHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVCaW5hcnlWaWV3KHQpe3JldHVybiBQby5zdGFydEJpbmFyeVZpZXcodCksUG8uZW5kQmluYXJ5Vmlldyh0KX19dmFyIFpJPW0oKCk9PntGdCgpfSk7Y2xhc3Mga297Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzQm9vbCh0LGUpe3JldHVybihlfHxuZXcga28pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzQm9vbCh0LGUpe3JldHVybiB0LnNldFBvc2l0aW9uKHQucG9zaXRpb24oKStMKSwoZXx8bmV3IGtvKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIHN0YXJ0Qm9vbCh0KXt0LnN0YXJ0T2JqZWN0KDApfXN0YXRpYyBlbmRCb29sKHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVCb29sKHQpe3JldHVybiBrby5zdGFydEJvb2wodCksa28uZW5kQm9vbCh0KX19dmFyIFFJPW0oKCk9PntGdCgpfSk7Y2xhc3Mgbml7Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzRGF0ZSh0LGUpe3JldHVybihlfHxuZXcgbmkpLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzRGF0ZSh0LGUpe3JldHVybiB0LnNldFBvc2l0aW9uKHQucG9zaXRpb24oKStMKSwoZXx8bmV3IG5pKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9dW5pdCgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50MTYodGhpcy5iYl9wb3MrdCk6SWUuTUlMTElTRUNPTkR9c3RhdGljIHN0YXJ0RGF0ZSh0KXt0LnN0YXJ0T2JqZWN0KDEpfXN0YXRpYyBhZGRVbml0KHQsZSl7dC5hZGRGaWVsZEludDE2KDAsZSxJZS5NSUxMSVNFQ09ORCl9c3RhdGljIGVuZERhdGUodCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9c3RhdGljIGNyZWF0ZURhdGUodCxlKXtyZXR1cm4gbmkuc3RhcnREYXRlKHQpLG5pLmFkZFVuaXQodCxlKSxuaS5lbmREYXRlKHQpfX12YXIgdl89bSgoKT0+e0Z0KCk7Zl8oKX0pO2NsYXNzIERye2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc0RlY2ltYWwodCxlKXtyZXR1cm4oZXx8bmV3IERyKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0RlY2ltYWwodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTCksKGV8fG5ldyBEcikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXByZWNpc2lvbigpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50MzIodGhpcy5iYl9wb3MrdCk6MH1zY2FsZSgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNik7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50MzIodGhpcy5iYl9wb3MrdCk6MH1iaXRXaWR0aCgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsOCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50MzIodGhpcy5iYl9wb3MrdCk6MTI4fXN0YXRpYyBzdGFydERlY2ltYWwodCl7dC5zdGFydE9iamVjdCgzKX1zdGF0aWMgYWRkUHJlY2lzaW9uKHQsZSl7dC5hZGRGaWVsZEludDMyKDAsZSwwKX1zdGF0aWMgYWRkU2NhbGUodCxlKXt0LmFkZEZpZWxkSW50MzIoMSxlLDApfXN0YXRpYyBhZGRCaXRXaWR0aCh0LGUpe3QuYWRkRmllbGRJbnQzMigyLGUsMTI4KX1zdGF0aWMgZW5kRGVjaW1hbCh0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgY3JlYXRlRGVjaW1hbCh0LGUscixuKXtyZXR1cm4gRHIuc3RhcnREZWNpbWFsKHQpLERyLmFkZFByZWNpc2lvbih0LGUpLERyLmFkZFNjYWxlKHQsciksRHIuYWRkQml0V2lkdGgodCxuKSxEci5lbmREZWNpbWFsKHQpfX12YXIgSV89bSgoKT0+e0Z0KCl9KTtjbGFzcyBpaXtjb25zdHJ1Y3Rvcigpe3RoaXMuYmI9bnVsbCx0aGlzLmJiX3Bvcz0wfV9faW5pdCh0LGUpe3JldHVybiB0aGlzLmJiX3Bvcz10LHRoaXMuYmI9ZSx0aGlzfXN0YXRpYyBnZXRSb290QXNEdXJhdGlvbih0LGUpe3JldHVybihlfHxuZXcgaWkpLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzRHVyYXRpb24odCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTCksKGV8fG5ldyBpaSkuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXVuaXQoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDQpO3JldHVybiB0P3RoaXMuYmIucmVhZEludDE2KHRoaXMuYmJfcG9zK3QpOlIuTUlMTElTRUNPTkR9c3RhdGljIHN0YXJ0RHVyYXRpb24odCl7dC5zdGFydE9iamVjdCgxKX1zdGF0aWMgYWRkVW5pdCh0LGUpe3QuYWRkRmllbGRJbnQxNigwLGUsUi5NSUxMSVNFQ09ORCl9c3RhdGljIGVuZER1cmF0aW9uKHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVEdXJhdGlvbih0LGUpe3JldHVybiBpaS5zdGFydER1cmF0aW9uKHQpLGlpLmFkZFVuaXQodCxlKSxpaS5lbmREdXJhdGlvbih0KX19dmFyIEJfPW0oKCk9PntGdCgpO211KCl9KTtjbGFzcyBzaXtjb25zdHJ1Y3Rvcigpe3RoaXMuYmI9bnVsbCx0aGlzLmJiX3Bvcz0wfV9faW5pdCh0LGUpe3JldHVybiB0aGlzLmJiX3Bvcz10LHRoaXMuYmI9ZSx0aGlzfXN0YXRpYyBnZXRSb290QXNGaXhlZFNpemVCaW5hcnkodCxlKXtyZXR1cm4oZXx8bmV3IHNpKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0ZpeGVkU2l6ZUJpbmFyeSh0LGUpe3JldHVybiB0LnNldFBvc2l0aW9uKHQucG9zaXRpb24oKStMKSwoZXx8bmV3IHNpKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9Ynl0ZVdpZHRoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw0KTtyZXR1cm4gdD90aGlzLmJiLnJlYWRJbnQzMih0aGlzLmJiX3Bvcyt0KTowfXN0YXRpYyBzdGFydEZpeGVkU2l6ZUJpbmFyeSh0KXt0LnN0YXJ0T2JqZWN0KDEpfXN0YXRpYyBhZGRCeXRlV2lkdGgodCxlKXt0LmFkZEZpZWxkSW50MzIoMCxlLDApfXN0YXRpYyBlbmRGaXhlZFNpemVCaW5hcnkodCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9c3RhdGljIGNyZWF0ZUZpeGVkU2l6ZUJpbmFyeSh0LGUpe3JldHVybiBzaS5zdGFydEZpeGVkU2l6ZUJpbmFyeSh0KSxzaS5hZGRCeXRlV2lkdGgodCxlKSxzaS5lbmRGaXhlZFNpemVCaW5hcnkodCl9fXZhciBTXz1tKCgpPT57RnQoKX0pO2NsYXNzIG9pe2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc0ZpeGVkU2l6ZUxpc3QodCxlKXtyZXR1cm4oZXx8bmV3IG9pKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0ZpeGVkU2l6ZUxpc3QodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTCksKGV8fG5ldyBvaSkuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfWxpc3RTaXplKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw0KTtyZXR1cm4gdD90aGlzLmJiLnJlYWRJbnQzMih0aGlzLmJiX3Bvcyt0KTowfXN0YXRpYyBzdGFydEZpeGVkU2l6ZUxpc3QodCl7dC5zdGFydE9iamVjdCgxKX1zdGF0aWMgYWRkTGlzdFNpemUodCxlKXt0LmFkZEZpZWxkSW50MzIoMCxlLDApfXN0YXRpYyBlbmRGaXhlZFNpemVMaXN0KHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVGaXhlZFNpemVMaXN0KHQsZSl7cmV0dXJuIG9pLnN0YXJ0Rml4ZWRTaXplTGlzdCh0KSxvaS5hZGRMaXN0U2l6ZSh0LGUpLG9pLmVuZEZpeGVkU2l6ZUxpc3QodCl9fXZhciBBXz1tKCgpPT57RnQoKX0pO2NsYXNzIGFpe2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc0Zsb2F0aW5nUG9pbnQodCxlKXtyZXR1cm4oZXx8bmV3IGFpKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0Zsb2F0aW5nUG9pbnQodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTCksKGV8fG5ldyBhaSkuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXByZWNpc2lvbigpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50MTYodGhpcy5iYl9wb3MrdCk6cmUuSEFMRn1zdGF0aWMgc3RhcnRGbG9hdGluZ1BvaW50KHQpe3Quc3RhcnRPYmplY3QoMSl9c3RhdGljIGFkZFByZWNpc2lvbih0LGUpe3QuYWRkRmllbGRJbnQxNigwLGUscmUuSEFMRil9c3RhdGljIGVuZEZsb2F0aW5nUG9pbnQodCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9c3RhdGljIGNyZWF0ZUZsb2F0aW5nUG9pbnQodCxlKXtyZXR1cm4gYWkuc3RhcnRGbG9hdGluZ1BvaW50KHQpLGFpLmFkZFByZWNpc2lvbih0LGUpLGFpLmVuZEZsb2F0aW5nUG9pbnQodCl9fXZhciBEXz1tKCgpPT57RnQoKTt1XygpfSk7Y2xhc3MgY2l7Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzSW50ZXJ2YWwodCxlKXtyZXR1cm4oZXx8bmV3IGNpKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0ludGVydmFsKHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK0wpLChlfHxuZXcgY2kpLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX11bml0KCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw0KTtyZXR1cm4gdD90aGlzLmJiLnJlYWRJbnQxNih0aGlzLmJiX3Bvcyt0KTpjZS5ZRUFSX01PTlRIfXN0YXRpYyBzdGFydEludGVydmFsKHQpe3Quc3RhcnRPYmplY3QoMSl9c3RhdGljIGFkZFVuaXQodCxlKXt0LmFkZEZpZWxkSW50MTYoMCxlLGNlLllFQVJfTU9OVEgpfXN0YXRpYyBlbmRJbnRlcnZhbCh0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgY3JlYXRlSW50ZXJ2YWwodCxlKXtyZXR1cm4gY2kuc3RhcnRJbnRlcnZhbCh0KSxjaS5hZGRVbml0KHQsZSksY2kuZW5kSW50ZXJ2YWwodCl9fXZhciB4Xz1tKCgpPT57RnQoKTtkXygpfSk7Y2xhc3MgVm97Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzTGFyZ2VCaW5hcnkodCxlKXtyZXR1cm4oZXx8bmV3IFZvKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0xhcmdlQmluYXJ5KHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK0wpLChlfHxuZXcgVm8pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgc3RhcnRMYXJnZUJpbmFyeSh0KXt0LnN0YXJ0T2JqZWN0KDApfXN0YXRpYyBlbmRMYXJnZUJpbmFyeSh0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgY3JlYXRlTGFyZ2VCaW5hcnkodCl7cmV0dXJuIFZvLnN0YXJ0TGFyZ2VCaW5hcnkodCksVm8uZW5kTGFyZ2VCaW5hcnkodCl9fXZhciB0Qj1tKCgpPT57RnQoKX0pO2NsYXNzIHpve2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc0xhcmdlVXRmOCh0LGUpe3JldHVybihlfHxuZXcgem8pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzTGFyZ2VVdGY4KHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK0wpLChlfHxuZXcgem8pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgc3RhcnRMYXJnZVV0ZjgodCl7dC5zdGFydE9iamVjdCgwKX1zdGF0aWMgZW5kTGFyZ2VVdGY4KHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVMYXJnZVV0ZjgodCl7cmV0dXJuIHpvLnN0YXJ0TGFyZ2VVdGY4KHQpLHpvLmVuZExhcmdlVXRmOCh0KX19dmFyIGVCPW0oKCk9PntGdCgpfSk7Y2xhc3Mgam97Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzTGlzdCh0LGUpe3JldHVybihlfHxuZXcgam8pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzTGlzdCh0LGUpe3JldHVybiB0LnNldFBvc2l0aW9uKHQucG9zaXRpb24oKStMKSwoZXx8bmV3IGpvKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIHN0YXJ0TGlzdCh0KXt0LnN0YXJ0T2JqZWN0KDApfXN0YXRpYyBlbmRMaXN0KHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVMaXN0KHQpe3JldHVybiBqby5zdGFydExpc3QodCksam8uZW5kTGlzdCh0KX19dmFyIHJCPW0oKCk9PntGdCgpfSk7Y2xhc3MgbGl7Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzTWFwKHQsZSl7cmV0dXJuKGV8fG5ldyBsaSkuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNNYXAodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTCksKGV8fG5ldyBsaSkuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfWtleXNTb3J0ZWQoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDQpO3JldHVybiB0PyEhdGhpcy5iYi5yZWFkSW50OCh0aGlzLmJiX3Bvcyt0KTohMX1zdGF0aWMgc3RhcnRNYXAodCl7dC5zdGFydE9iamVjdCgxKX1zdGF0aWMgYWRkS2V5c1NvcnRlZCh0LGUpe3QuYWRkRmllbGRJbnQ4KDAsK2UsMCl9c3RhdGljIGVuZE1hcCh0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgY3JlYXRlTWFwKHQsZSl7cmV0dXJuIGxpLnN0YXJ0TWFwKHQpLGxpLmFkZEtleXNTb3J0ZWQodCxlKSxsaS5lbmRNYXAodCl9fXZhciBUXz1tKCgpPT57RnQoKX0pO2NsYXNzICRve2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc051bGwodCxlKXtyZXR1cm4oZXx8bmV3ICRvKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc051bGwodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTCksKGV8fG5ldyAkbykuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBzdGFydE51bGwodCl7dC5zdGFydE9iamVjdCgwKX1zdGF0aWMgZW5kTnVsbCh0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgY3JlYXRlTnVsbCh0KXtyZXR1cm4gJG8uc3RhcnROdWxsKHQpLCRvLmVuZE51bGwodCl9fXZhciBuQj1tKCgpPT57RnQoKX0pO2NsYXNzIHFve2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc1N0cnVjdF8odCxlKXtyZXR1cm4oZXx8bmV3IHFvKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc1N0cnVjdF8odCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTCksKGV8fG5ldyBxbykuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBzdGFydFN0cnVjdF8odCl7dC5zdGFydE9iamVjdCgwKX1zdGF0aWMgZW5kU3RydWN0Xyh0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgY3JlYXRlU3RydWN0Xyh0KXtyZXR1cm4gcW8uc3RhcnRTdHJ1Y3RfKHQpLHFvLmVuZFN0cnVjdF8odCl9fXZhciBpQj1tKCgpPT57RnQoKX0pO2NsYXNzIHJue2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc1RpbWUodCxlKXtyZXR1cm4oZXx8bmV3IHJuKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc1RpbWUodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTCksKGV8fG5ldyBybikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXVuaXQoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDQpO3JldHVybiB0P3RoaXMuYmIucmVhZEludDE2KHRoaXMuYmJfcG9zK3QpOlIuTUlMTElTRUNPTkR9Yml0V2lkdGgoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDYpO3JldHVybiB0P3RoaXMuYmIucmVhZEludDMyKHRoaXMuYmJfcG9zK3QpOjMyfXN0YXRpYyBzdGFydFRpbWUodCl7dC5zdGFydE9iamVjdCgyKX1zdGF0aWMgYWRkVW5pdCh0LGUpe3QuYWRkRmllbGRJbnQxNigwLGUsUi5NSUxMSVNFQ09ORCl9c3RhdGljIGFkZEJpdFdpZHRoKHQsZSl7dC5hZGRGaWVsZEludDMyKDEsZSwzMil9c3RhdGljIGVuZFRpbWUodCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9c3RhdGljIGNyZWF0ZVRpbWUodCxlLHIpe3JldHVybiBybi5zdGFydFRpbWUodCkscm4uYWRkVW5pdCh0LGUpLHJuLmFkZEJpdFdpZHRoKHQscikscm4uZW5kVGltZSh0KX19dmFyIEVfPW0oKCk9PntGdCgpO211KCl9KTtjbGFzcyBubntjb25zdHJ1Y3Rvcigpe3RoaXMuYmI9bnVsbCx0aGlzLmJiX3Bvcz0wfV9faW5pdCh0LGUpe3JldHVybiB0aGlzLmJiX3Bvcz10LHRoaXMuYmI9ZSx0aGlzfXN0YXRpYyBnZXRSb290QXNUaW1lc3RhbXAodCxlKXtyZXR1cm4oZXx8bmV3IG5uKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc1RpbWVzdGFtcCh0LGUpe3JldHVybiB0LnNldFBvc2l0aW9uKHQucG9zaXRpb24oKStMKSwoZXx8bmV3IG5uKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9dW5pdCgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50MTYodGhpcy5iYl9wb3MrdCk6Ui5TRUNPTkR9dGltZXpvbmUodCl7bGV0IGU9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3Bvcyw2KTtyZXR1cm4gZT90aGlzLmJiLl9fc3RyaW5nKHRoaXMuYmJfcG9zK2UsdCk6bnVsbH1zdGF0aWMgc3RhcnRUaW1lc3RhbXAodCl7dC5zdGFydE9iamVjdCgyKX1zdGF0aWMgYWRkVW5pdCh0LGUpe3QuYWRkRmllbGRJbnQxNigwLGUsUi5TRUNPTkQpfXN0YXRpYyBhZGRUaW1lem9uZSh0LGUpe3QuYWRkRmllbGRPZmZzZXQoMSxlLDApfXN0YXRpYyBlbmRUaW1lc3RhbXAodCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9c3RhdGljIGNyZWF0ZVRpbWVzdGFtcCh0LGUscil7cmV0dXJuIG5uLnN0YXJ0VGltZXN0YW1wKHQpLG5uLmFkZFVuaXQodCxlKSxubi5hZGRUaW1lem9uZSh0LHIpLG5uLmVuZFRpbWVzdGFtcCh0KX19dmFyIE9fPW0oKCk9PntGdCgpO211KCl9KTtjbGFzcyB4cntjb25zdHJ1Y3Rvcigpe3RoaXMuYmI9bnVsbCx0aGlzLmJiX3Bvcz0wfV9faW5pdCh0LGUpe3JldHVybiB0aGlzLmJiX3Bvcz10LHRoaXMuYmI9ZSx0aGlzfXN0YXRpYyBnZXRSb290QXNVbmlvbih0LGUpe3JldHVybihlfHxuZXcgeHIpLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzVW5pb24odCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTCksKGV8fG5ldyB4cikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfW1vZGUoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDQpO3JldHVybiB0P3RoaXMuYmIucmVhZEludDE2KHRoaXMuYmJfcG9zK3QpOnNlLlNwYXJzZX10eXBlSWRzKHQpe2xldCBlPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNik7cmV0dXJuIGU/dGhpcy5iYi5yZWFkSW50MzIodGhpcy5iYi5fX3ZlY3Rvcih0aGlzLmJiX3BvcytlKSt0KjQpOjB9dHlwZUlkc0xlbmd0aCgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNik7cmV0dXJuIHQ/dGhpcy5iYi5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MrdCk6MH10eXBlSWRzQXJyYXkoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDYpO3JldHVybiB0P25ldyBJbnQzMkFycmF5KHRoaXMuYmIuYnl0ZXMoKS5idWZmZXIsdGhpcy5iYi5ieXRlcygpLmJ5dGVPZmZzZXQrdGhpcy5iYi5fX3ZlY3Rvcih0aGlzLmJiX3Bvcyt0KSx0aGlzLmJiLl9fdmVjdG9yX2xlbih0aGlzLmJiX3Bvcyt0KSk6bnVsbH1zdGF0aWMgc3RhcnRVbmlvbih0KXt0LnN0YXJ0T2JqZWN0KDIpfXN0YXRpYyBhZGRNb2RlKHQsZSl7dC5hZGRGaWVsZEludDE2KDAsZSxzZS5TcGFyc2UpfXN0YXRpYyBhZGRUeXBlSWRzKHQsZSl7dC5hZGRGaWVsZE9mZnNldCgxLGUsMCl9c3RhdGljIGNyZWF0ZVR5cGVJZHNWZWN0b3IodCxlKXt0LnN0YXJ0VmVjdG9yKDQsZS5sZW5ndGgsNCk7Zm9yKGxldCByPWUubGVuZ3RoLTE7cj49MDtyLS0pdC5hZGRJbnQzMihlW3JdKTtyZXR1cm4gdC5lbmRWZWN0b3IoKX1zdGF0aWMgc3RhcnRUeXBlSWRzVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig0LGUsNCl9c3RhdGljIGVuZFVuaW9uKHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVVbmlvbih0LGUscil7cmV0dXJuIHhyLnN0YXJ0VW5pb24odCkseHIuYWRkTW9kZSh0LGUpLHhyLmFkZFR5cGVJZHModCxyKSx4ci5lbmRVbmlvbih0KX19dmFyIE5fPW0oKCk9PntGdCgpO2xfKCl9KTtjbGFzcyBXb3tjb25zdHJ1Y3Rvcigpe3RoaXMuYmI9bnVsbCx0aGlzLmJiX3Bvcz0wfV9faW5pdCh0LGUpe3JldHVybiB0aGlzLmJiX3Bvcz10LHRoaXMuYmI9ZSx0aGlzfXN0YXRpYyBnZXRSb290QXNVdGY4KHQsZSl7cmV0dXJuKGV8fG5ldyBXbykuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNVdGY4KHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK0wpLChlfHxuZXcgV28pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgc3RhcnRVdGY4KHQpe3Quc3RhcnRPYmplY3QoMCl9c3RhdGljIGVuZFV0ZjgodCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9c3RhdGljIGNyZWF0ZVV0ZjgodCl7cmV0dXJuIFdvLnN0YXJ0VXRmOCh0KSxXby5lbmRVdGY4KHQpfX12YXIgc0I9bSgoKT0+e0Z0KCl9KTtjbGFzcyBIb3tjb25zdHJ1Y3Rvcigpe3RoaXMuYmI9bnVsbCx0aGlzLmJiX3Bvcz0wfV9faW5pdCh0LGUpe3JldHVybiB0aGlzLmJiX3Bvcz10LHRoaXMuYmI9ZSx0aGlzfXN0YXRpYyBnZXRSb290QXNVdGY4Vmlldyh0LGUpe3JldHVybihlfHxuZXcgSG8pLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1zdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzVXRmOFZpZXcodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTCksKGV8fG5ldyBIbykuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBzdGFydFV0ZjhWaWV3KHQpe3Quc3RhcnRPYmplY3QoMCl9c3RhdGljIGVuZFV0ZjhWaWV3KHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVVdGY4Vmlldyh0KXtyZXR1cm4gSG8uc3RhcnRVdGY4Vmlldyh0KSxIby5lbmRVdGY4Vmlldyh0KX19dmFyIG9CPW0oKCk9PntGdCgpfSk7dmFyIEp0O3ZhciBGXz1tKCgpPT57KGZ1bmN0aW9uKHQpe3RbdC5OT05FPTBdPSJOT05FIix0W3QuTnVsbD0xXT0iTnVsbCIsdFt0LkludD0yXT0iSW50Iix0W3QuRmxvYXRpbmdQb2ludD0zXT0iRmxvYXRpbmdQb2ludCIsdFt0LkJpbmFyeT00XT0iQmluYXJ5Iix0W3QuVXRmOD01XT0iVXRmOCIsdFt0LkJvb2w9Nl09IkJvb2wiLHRbdC5EZWNpbWFsPTddPSJEZWNpbWFsIix0W3QuRGF0ZT04XT0iRGF0ZSIsdFt0LlRpbWU9OV09IlRpbWUiLHRbdC5UaW1lc3RhbXA9MTBdPSJUaW1lc3RhbXAiLHRbdC5JbnRlcnZhbD0xMV09IkludGVydmFsIix0W3QuTGlzdD0xMl09Ikxpc3QiLHRbdC5TdHJ1Y3RfPTEzXT0iU3RydWN0XyIsdFt0LlVuaW9uPTE0XT0iVW5pb24iLHRbdC5GaXhlZFNpemVCaW5hcnk9MTVdPSJGaXhlZFNpemVCaW5hcnkiLHRbdC5GaXhlZFNpemVMaXN0PTE2XT0iRml4ZWRTaXplTGlzdCIsdFt0Lk1hcD0xN109Ik1hcCIsdFt0LkR1cmF0aW9uPTE4XT0iRHVyYXRpb24iLHRbdC5MYXJnZUJpbmFyeT0xOV09IkxhcmdlQmluYXJ5Iix0W3QuTGFyZ2VVdGY4PTIwXT0iTGFyZ2VVdGY4Iix0W3QuTGFyZ2VMaXN0PTIxXT0iTGFyZ2VMaXN0Iix0W3QuUnVuRW5kRW5jb2RlZD0yMl09IlJ1bkVuZEVuY29kZWQiLHRbdC5CaW5hcnlWaWV3PTIzXT0iQmluYXJ5VmlldyIsdFt0LlV0ZjhWaWV3PTI0XT0iVXRmOFZpZXciLHRbdC5MaXN0Vmlldz0yNV09Ikxpc3RWaWV3Iix0W3QuTGFyZ2VMaXN0Vmlldz0yNl09IkxhcmdlTGlzdFZpZXcifSkoSnR8fChKdD17fSkpfSk7Y2xhc3MgcnJ7Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzRmllbGQodCxlKXtyZXR1cm4oZXx8bmV3IHJyKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0ZpZWxkKHQsZSl7cmV0dXJuIHQuc2V0UG9zaXRpb24odC5wb3NpdGlvbigpK0wpLChlfHxuZXcgcnIpLl9faW5pdCh0LnJlYWRJbnQzMih0LnBvc2l0aW9uKCkpK3QucG9zaXRpb24oKSx0KX1uYW1lKHQpe2xldCBlPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNCk7cmV0dXJuIGU/dGhpcy5iYi5fX3N0cmluZyh0aGlzLmJiX3BvcytlLHQpOm51bGx9bnVsbGFibGUoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDYpO3JldHVybiB0PyEhdGhpcy5iYi5yZWFkSW50OCh0aGlzLmJiX3Bvcyt0KTohMX10eXBlVHlwZSgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsOCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkVWludDgodGhpcy5iYl9wb3MrdCk6SnQuTk9ORX10eXBlKHQpe2xldCBlPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsMTApO3JldHVybiBlP3RoaXMuYmIuX191bmlvbih0LHRoaXMuYmJfcG9zK2UpOm51bGx9ZGljdGlvbmFyeSh0KXtsZXQgZT10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDEyKTtyZXR1cm4gZT8odHx8bmV3IFlpKS5fX2luaXQodGhpcy5iYi5fX2luZGlyZWN0KHRoaXMuYmJfcG9zK2UpLHRoaXMuYmIpOm51bGx9Y2hpbGRyZW4odCxlKXtsZXQgcj10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDE0KTtyZXR1cm4gcj8oZXx8bmV3IHJyKS5fX2luaXQodGhpcy5iYi5fX2luZGlyZWN0KHRoaXMuYmIuX192ZWN0b3IodGhpcy5iYl9wb3MrcikrdCo0KSx0aGlzLmJiKTpudWxsfWNoaWxkcmVuTGVuZ3RoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3BvcywxNCk7cmV0dXJuIHQ/dGhpcy5iYi5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MrdCk6MH1jdXN0b21NZXRhZGF0YSh0LGUpe2xldCByPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsMTYpO3JldHVybiByPyhlfHxuZXcgb2UpLl9faW5pdCh0aGlzLmJiLl9faW5kaXJlY3QodGhpcy5iYi5fX3ZlY3Rvcih0aGlzLmJiX3BvcytyKSt0KjQpLHRoaXMuYmIpOm51bGx9Y3VzdG9tTWV0YWRhdGFMZW5ndGgoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDE2KTtyZXR1cm4gdD90aGlzLmJiLl9fdmVjdG9yX2xlbih0aGlzLmJiX3Bvcyt0KTowfXN0YXRpYyBzdGFydEZpZWxkKHQpe3Quc3RhcnRPYmplY3QoNyl9c3RhdGljIGFkZE5hbWUodCxlKXt0LmFkZEZpZWxkT2Zmc2V0KDAsZSwwKX1zdGF0aWMgYWRkTnVsbGFibGUodCxlKXt0LmFkZEZpZWxkSW50OCgxLCtlLDApfXN0YXRpYyBhZGRUeXBlVHlwZSh0LGUpe3QuYWRkRmllbGRJbnQ4KDIsZSxKdC5OT05FKX1zdGF0aWMgYWRkVHlwZSh0LGUpe3QuYWRkRmllbGRPZmZzZXQoMyxlLDApfXN0YXRpYyBhZGREaWN0aW9uYXJ5KHQsZSl7dC5hZGRGaWVsZE9mZnNldCg0LGUsMCl9c3RhdGljIGFkZENoaWxkcmVuKHQsZSl7dC5hZGRGaWVsZE9mZnNldCg1LGUsMCl9c3RhdGljIGNyZWF0ZUNoaWxkcmVuVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig0LGUubGVuZ3RoLDQpO2ZvcihsZXQgcj1lLmxlbmd0aC0xO3I+PTA7ci0tKXQuYWRkT2Zmc2V0KGVbcl0pO3JldHVybiB0LmVuZFZlY3RvcigpfXN0YXRpYyBzdGFydENoaWxkcmVuVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig0LGUsNCl9c3RhdGljIGFkZEN1c3RvbU1ldGFkYXRhKHQsZSl7dC5hZGRGaWVsZE9mZnNldCg2LGUsMCl9c3RhdGljIGNyZWF0ZUN1c3RvbU1ldGFkYXRhVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig0LGUubGVuZ3RoLDQpO2ZvcihsZXQgcj1lLmxlbmd0aC0xO3I+PTA7ci0tKXQuYWRkT2Zmc2V0KGVbcl0pO3JldHVybiB0LmVuZFZlY3RvcigpfXN0YXRpYyBzdGFydEN1c3RvbU1ldGFkYXRhVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig0LGUsNCl9c3RhdGljIGVuZEZpZWxkKHQpe3JldHVybiB0LmVuZE9iamVjdCgpfX12YXIgTV89bSgoKT0+e0Z0KCk7d18oKTskYygpO0ZfKCl9KTtjbGFzcyBFZXtjb25zdHJ1Y3Rvcigpe3RoaXMuYmI9bnVsbCx0aGlzLmJiX3Bvcz0wfV9faW5pdCh0LGUpe3JldHVybiB0aGlzLmJiX3Bvcz10LHRoaXMuYmI9ZSx0aGlzfXN0YXRpYyBnZXRSb290QXNTY2hlbWEodCxlKXtyZXR1cm4oZXx8bmV3IEVlKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc1NjaGVtYSh0LGUpe3JldHVybiB0LnNldFBvc2l0aW9uKHQucG9zaXRpb24oKStMKSwoZXx8bmV3IEVlKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9ZW5kaWFubmVzcygpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50MTYodGhpcy5iYl9wb3MrdCk6Um8uTGl0dGxlfWZpZWxkcyh0LGUpe2xldCByPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsNik7cmV0dXJuIHI/KGV8fG5ldyBycikuX19pbml0KHRoaXMuYmIuX19pbmRpcmVjdCh0aGlzLmJiLl9fdmVjdG9yKHRoaXMuYmJfcG9zK3IpK3QqNCksdGhpcy5iYik6bnVsbH1maWVsZHNMZW5ndGgoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDYpO3JldHVybiB0P3RoaXMuYmIuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zK3QpOjB9Y3VzdG9tTWV0YWRhdGEodCxlKXtsZXQgcj10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDgpO3JldHVybiByPyhlfHxuZXcgb2UpLl9faW5pdCh0aGlzLmJiLl9faW5kaXJlY3QodGhpcy5iYi5fX3ZlY3Rvcih0aGlzLmJiX3BvcytyKSt0KjQpLHRoaXMuYmIpOm51bGx9Y3VzdG9tTWV0YWRhdGFMZW5ndGgoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDgpO3JldHVybiB0P3RoaXMuYmIuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zK3QpOjB9ZmVhdHVyZXModCl7bGV0IGU9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3BvcywxMCk7cmV0dXJuIGU/dGhpcy5iYi5yZWFkSW50NjQodGhpcy5iYi5fX3ZlY3Rvcih0aGlzLmJiX3BvcytlKSt0KjgpOkJpZ0ludCgwKX1mZWF0dXJlc0xlbmd0aCgpe2xldCB0PXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsMTApO3JldHVybiB0P3RoaXMuYmIuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zK3QpOjB9c3RhdGljIHN0YXJ0U2NoZW1hKHQpe3Quc3RhcnRPYmplY3QoNCl9c3RhdGljIGFkZEVuZGlhbm5lc3ModCxlKXt0LmFkZEZpZWxkSW50MTYoMCxlLFJvLkxpdHRsZSl9c3RhdGljIGFkZEZpZWxkcyh0LGUpe3QuYWRkRmllbGRPZmZzZXQoMSxlLDApfXN0YXRpYyBjcmVhdGVGaWVsZHNWZWN0b3IodCxlKXt0LnN0YXJ0VmVjdG9yKDQsZS5sZW5ndGgsNCk7Zm9yKGxldCByPWUubGVuZ3RoLTE7cj49MDtyLS0pdC5hZGRPZmZzZXQoZVtyXSk7cmV0dXJuIHQuZW5kVmVjdG9yKCl9c3RhdGljIHN0YXJ0RmllbGRzVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig0LGUsNCl9c3RhdGljIGFkZEN1c3RvbU1ldGFkYXRhKHQsZSl7dC5hZGRGaWVsZE9mZnNldCgyLGUsMCl9c3RhdGljIGNyZWF0ZUN1c3RvbU1ldGFkYXRhVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig0LGUubGVuZ3RoLDQpO2ZvcihsZXQgcj1lLmxlbmd0aC0xO3I+PTA7ci0tKXQuYWRkT2Zmc2V0KGVbcl0pO3JldHVybiB0LmVuZFZlY3RvcigpfXN0YXRpYyBzdGFydEN1c3RvbU1ldGFkYXRhVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig0LGUsNCl9c3RhdGljIGFkZEZlYXR1cmVzKHQsZSl7dC5hZGRGaWVsZE9mZnNldCgzLGUsMCl9c3RhdGljIGNyZWF0ZUZlYXR1cmVzVmVjdG9yKHQsZSl7dC5zdGFydFZlY3Rvcig4LGUubGVuZ3RoLDgpO2ZvcihsZXQgcj1lLmxlbmd0aC0xO3I+PTA7ci0tKXQuYWRkSW50NjQoZVtyXSk7cmV0dXJuIHQuZW5kVmVjdG9yKCl9c3RhdGljIHN0YXJ0RmVhdHVyZXNWZWN0b3IodCxlKXt0LnN0YXJ0VmVjdG9yKDgsZSw4KX1zdGF0aWMgZW5kU2NoZW1hKHQpe3JldHVybiB0LmVuZE9iamVjdCgpfXN0YXRpYyBjcmVhdGVTY2hlbWEodCxlLHIsbixpKXtyZXR1cm4gRWUuc3RhcnRTY2hlbWEodCksRWUuYWRkRW5kaWFubmVzcyh0LGUpLEVlLmFkZEZpZWxkcyh0LHIpLEVlLmFkZEN1c3RvbU1ldGFkYXRhKHQsbiksRWUuYWRkRmVhdHVyZXModCxpKSxFZS5lbmRTY2hlbWEodCl9fXZhciBMXz1tKCgpPT57RnQoKTtiXygpO01fKCk7JGMoKX0pO3ZhciBUdDt2YXIgVV89bSgoKT0+eyhmdW5jdGlvbih0KXt0W3QuTk9ORT0wXT0iTk9ORSIsdFt0LlNjaGVtYT0xXT0iU2NoZW1hIix0W3QuRGljdGlvbmFyeUJhdGNoPTJdPSJEaWN0aW9uYXJ5QmF0Y2giLHRbdC5SZWNvcmRCYXRjaD0zXT0iUmVjb3JkQmF0Y2giLHRbdC5UZW5zb3I9NF09IlRlbnNvciIsdFt0LlNwYXJzZVRlbnNvcj01XT0iU3BhcnNlVGVuc29yIn0pKFR0fHwoVHQ9e30pKX0pO3ZhciB5LHNuO3ZhciBDZT1tKCgpPT57aWgoKTtsXygpO3VfKCk7Zl8oKTttdSgpO2RfKCk7VV8oKTsoZnVuY3Rpb24odCl7dFt0Lk5PTkU9MF09Ik5PTkUiLHRbdC5OdWxsPTFdPSJOdWxsIix0W3QuSW50PTJdPSJJbnQiLHRbdC5GbG9hdD0zXT0iRmxvYXQiLHRbdC5CaW5hcnk9NF09IkJpbmFyeSIsdFt0LlV0Zjg9NV09IlV0ZjgiLHRbdC5Cb29sPTZdPSJCb29sIix0W3QuRGVjaW1hbD03XT0iRGVjaW1hbCIsdFt0LkRhdGU9OF09IkRhdGUiLHRbdC5UaW1lPTldPSJUaW1lIix0W3QuVGltZXN0YW1wPTEwXT0iVGltZXN0YW1wIix0W3QuSW50ZXJ2YWw9MTFdPSJJbnRlcnZhbCIsdFt0Lkxpc3Q9MTJdPSJMaXN0Iix0W3QuU3RydWN0PTEzXT0iU3RydWN0Iix0W3QuVW5pb249MTRdPSJVbmlvbiIsdFt0LkZpeGVkU2l6ZUJpbmFyeT0xNV09IkZpeGVkU2l6ZUJpbmFyeSIsdFt0LkZpeGVkU2l6ZUxpc3Q9MTZdPSJGaXhlZFNpemVMaXN0Iix0W3QuTWFwPTE3XT0iTWFwIix0W3QuRHVyYXRpb249MThdPSJEdXJhdGlvbiIsdFt0LkxhcmdlQmluYXJ5PTE5XT0iTGFyZ2VCaW5hcnkiLHRbdC5MYXJnZVV0Zjg9MjBdPSJMYXJnZVV0ZjgiLHRbdC5CaW5hcnlWaWV3PTIzXT0iQmluYXJ5VmlldyIsdFt0LlV0ZjhWaWV3PTI0XT0iVXRmOFZpZXciLHRbdC5EaWN0aW9uYXJ5PS0xXT0iRGljdGlvbmFyeSIsdFt0LkludDg9LTJdPSJJbnQ4Iix0W3QuSW50MTY9LTNdPSJJbnQxNiIsdFt0LkludDMyPS00XT0iSW50MzIiLHRbdC5JbnQ2ND0tNV09IkludDY0Iix0W3QuVWludDg9LTZdPSJVaW50OCIsdFt0LlVpbnQxNj0tN109IlVpbnQxNiIsdFt0LlVpbnQzMj0tOF09IlVpbnQzMiIsdFt0LlVpbnQ2ND0tOV09IlVpbnQ2NCIsdFt0LkZsb2F0MTY9LTEwXT0iRmxvYXQxNiIsdFt0LkZsb2F0MzI9LTExXT0iRmxvYXQzMiIsdFt0LkZsb2F0NjQ9LTEyXT0iRmxvYXQ2NCIsdFt0LkRhdGVEYXk9LTEzXT0iRGF0ZURheSIsdFt0LkRhdGVNaWxsaXNlY29uZD0tMTRdPSJEYXRlTWlsbGlzZWNvbmQiLHRbdC5UaW1lc3RhbXBTZWNvbmQ9LTE1XT0iVGltZXN0YW1wU2Vjb25kIix0W3QuVGltZXN0YW1wTWlsbGlzZWNvbmQ9LTE2XT0iVGltZXN0YW1wTWlsbGlzZWNvbmQiLHRbdC5UaW1lc3RhbXBNaWNyb3NlY29uZD0tMTddPSJUaW1lc3RhbXBNaWNyb3NlY29uZCIsdFt0LlRpbWVzdGFtcE5hbm9zZWNvbmQ9LTE4XT0iVGltZXN0YW1wTmFub3NlY29uZCIsdFt0LlRpbWVTZWNvbmQ9LTE5XT0iVGltZVNlY29uZCIsdFt0LlRpbWVNaWxsaXNlY29uZD0tMjBdPSJUaW1lTWlsbGlzZWNvbmQiLHRbdC5UaW1lTWljcm9zZWNvbmQ9LTIxXT0iVGltZU1pY3Jvc2Vjb25kIix0W3QuVGltZU5hbm9zZWNvbmQ9LTIyXT0iVGltZU5hbm9zZWNvbmQiLHRbdC5EZW5zZVVuaW9uPS0yM109IkRlbnNlVW5pb24iLHRbdC5TcGFyc2VVbmlvbj0tMjRdPSJTcGFyc2VVbmlvbiIsdFt0LkludGVydmFsRGF5VGltZT0tMjVdPSJJbnRlcnZhbERheVRpbWUiLHRbdC5JbnRlcnZhbFllYXJNb250aD0tMjZdPSJJbnRlcnZhbFllYXJNb250aCIsdFt0LkR1cmF0aW9uU2Vjb25kPS0yN109IkR1cmF0aW9uU2Vjb25kIix0W3QuRHVyYXRpb25NaWxsaXNlY29uZD0tMjhdPSJEdXJhdGlvbk1pbGxpc2Vjb25kIix0W3QuRHVyYXRpb25NaWNyb3NlY29uZD0tMjldPSJEdXJhdGlvbk1pY3Jvc2Vjb25kIix0W3QuRHVyYXRpb25OYW5vc2Vjb25kPS0zMF09IkR1cmF0aW9uTmFub3NlY29uZCIsdFt0LkludGVydmFsTW9udGhEYXlOYW5vPS0zMV09IkludGVydmFsTW9udGhEYXlOYW5vIn0pKHl8fCh5PXt9KSk7KGZ1bmN0aW9uKHQpe3RbdC5PRkZTRVQ9MF09Ik9GRlNFVCIsdFt0LkRBVEE9MV09IkRBVEEiLHRbdC5WQUxJRElUWT0yXT0iVkFMSURJVFkiLHRbdC5UWVBFPTNdPSJUWVBFIn0pKHNufHwoc249e30pKX0pO3ZhciBSXz17fTtaZShSXyx7dmFsdWVUb1N0cmluZzooKT0+S2l9KTtmdW5jdGlvbiBLaSh0KXtpZih0PT09bnVsbClyZXR1cm4ibnVsbCI7aWYodD09PXZvaWQgMClyZXR1cm4idW5kZWZpbmVkIjtzd2l0Y2godHlwZW9mIHQpe2Nhc2UibnVtYmVyIjpyZXR1cm5gJHt0fWA7Y2FzZSJiaWdpbnQiOnJldHVybmAke3R9YDtjYXNlInN0cmluZyI6cmV0dXJuYCIke3R9ImB9aWYodHlwZW9mIHRbU3ltYm9sLnRvUHJpbWl0aXZlXT09PSJmdW5jdGlvbiIpcmV0dXJuIHRbU3ltYm9sLnRvUHJpbWl0aXZlXSgic3RyaW5nIik7aWYoQXJyYXlCdWZmZXIuaXNWaWV3KHQpKXtpZih0IGluc3RhbmNlb2YgQmlnSW50NjRBcnJheXx8dCBpbnN0YW5jZW9mIEJpZ1VpbnQ2NEFycmF5KXJldHVybmBbJHtbLi4udF0ubWFwKChlKT0+S2koZSkpfV1gO3JldHVybmBbJHt0fV1gfXJldHVybiBBcnJheUJ1ZmZlci5pc1ZpZXcodCk/YFske3R9XWA6SlNPTi5zdHJpbmdpZnkodCwoZSxyKT0+dHlwZW9mIHI9PT0iYmlnaW50Ij9gJHtyfWA6cil9ZnVuY3Rpb24gVnQodCl7aWYodHlwZW9mIHQ9PT0iYmlnaW50IiYmKHQ8TnVtYmVyLk1JTl9TQUZFX0lOVEVHRVJ8fHQ+TnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIpKXRocm93IFR5cGVFcnJvcihgJHt0fSBpcyBub3Qgc2FmZSB0byBjb252ZXJ0IHRvIGEgbnVtYmVyLmApO3JldHVybiBOdW1iZXIodCl9ZnVuY3Rpb24gQ18odCxlKXtyZXR1cm4gVnQodC9lKStWdCh0JWUpL1Z0KGUpfXZhciBWXz17fTtaZShWXyx7Qk46KCk9PkJ1LGJpZ051bVRvQmlnSW50OigpPT5jQixiaWdOdW1Ub051bWJlcjooKT0+a18sYmlnTnVtVG9TdHJpbmc6KCk9PkhjLGlzQXJyb3dCaWdOdW1TeW1ib2w6KCk9PmFCfSk7ZnVuY3Rpb24gR2kodCwuLi5lKXtpZihlLmxlbmd0aD09PTApcmV0dXJuIE9iamVjdC5zZXRQcm90b3R5cGVPZih2dCh0aGlzLlR5cGVkQXJyYXksdCksdGhpcy5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpO3JldHVybiBPYmplY3Quc2V0UHJvdG90eXBlT2YobmV3IHRoaXMuVHlwZWRBcnJheSh0LC4uLmUpLHRoaXMuY29uc3RydWN0b3IucHJvdG90eXBlKX1mdW5jdGlvbiBxYyguLi50KXtyZXR1cm4gR2kuYXBwbHkodGhpcyx0KX1mdW5jdGlvbiBXYyguLi50KXtyZXR1cm4gR2kuYXBwbHkodGhpcyx0KX1mdW5jdGlvbiBJdSguLi50KXtyZXR1cm4gR2kuYXBwbHkodGhpcyx0KX1mdW5jdGlvbiBrXyh0LGUpe2xldHtidWZmZXI6cixieXRlT2Zmc2V0Om4sYnl0ZUxlbmd0aDppLHNpZ25lZDpzfT10LG89bmV3IEJpZ1VpbnQ2NEFycmF5KHIsbixpLzgpLGE9cyYmby5hdCgtMSkmQmlnSW50KDEpPDxCaWdJbnQoNjMpLGw9QmlnSW50KDApLHU9MDtpZihhKXtmb3IobGV0IGYgb2YgbylsfD0oZl5xRikqKEJpZ0ludCgxKTw8QmlnSW50KDY0KnUrKykpO2wqPUJpZ0ludCgtMSksbC09QmlnSW50KDEpfWVsc2UgZm9yKGxldCBmIG9mIG8pbHw9ZiooQmlnSW50KDEpPDxCaWdJbnQoNjQqdSsrKSk7aWYodHlwZW9mIGU9PT0ibnVtYmVyIiYmZT4wKXtsZXQgZj1CaWdJbnQoIjEiLnBhZEVuZChlKzEsIjAiKSkscD1sL2YsZz1hPy0obCVmKTpsJWYsdj1WdChwKSxJPWAke2d9YC5wYWRTdGFydChlLCIwIik7cmV0dXJuK2Ake2EmJnY9PT0wPyItIjoiIn0ke3Z9LiR7SX1gfXJldHVybiBWdChsKX1mdW5jdGlvbiBIYyh0KXtpZih0LmJ5dGVMZW5ndGg9PT04KXJldHVybmAke25ldyB0LkJpZ0ludEFycmF5KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCwxKVswXX1gO2lmKCF0LnNpZ25lZClyZXR1cm4gUF8odCk7bGV0IGU9bmV3IFVpbnQxNkFycmF5KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCx0LmJ5dGVMZW5ndGgvMik7aWYobmV3IEludDE2QXJyYXkoW2UuYXQoLTEpXSlbMF0+PTApcmV0dXJuIFBfKHQpO2U9ZS5zbGljZSgpO2xldCBuPTE7Zm9yKGxldCBzPTA7czxlLmxlbmd0aDtzKyspe2xldCBvPWVbc10sYT1+bytuO2Vbc109YSxuJj1vPT09MD8xOjB9cmV0dXJuYC0ke1BfKGUpfWB9ZnVuY3Rpb24gY0IodCl7aWYodC5ieXRlTGVuZ3RoPT09OClyZXR1cm4gbmV3IHQuQmlnSW50QXJyYXkodC5idWZmZXIsdC5ieXRlT2Zmc2V0LDEpWzBdO2Vsc2UgcmV0dXJuIEhjKHQpfWZ1bmN0aW9uIFBfKHQpe2xldCBlPSIiLHI9bmV3IFVpbnQzMkFycmF5KDIpLG49bmV3IFVpbnQxNkFycmF5KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCx0LmJ5dGVMZW5ndGgvMiksaT1uZXcgVWludDMyQXJyYXkoKG49bmV3IFVpbnQxNkFycmF5KG4pLnJldmVyc2UoKSkuYnVmZmVyKSxzPS0xLG89bi5sZW5ndGgtMTtkb3tmb3IoclswXT1uW3M9MF07czxvOyluW3MrK109clsxXT1yWzBdLzEwLHJbMF09KHJbMF0tclsxXSoxMDw8MTYpK25bc107bltzXT1yWzFdPXJbMF0vMTAsclswXT1yWzBdLXJbMV0qMTAsZT1gJHtyWzBdfSR7ZX1gfXdoaWxlKGlbMF18fGlbMV18fGlbMl18fGlbM10pO3JldHVybiBlIT09bnVsbCYmZSE9PXZvaWQgMD9lOiIwIn1jbGFzcyBCdXtzdGF0aWMgbmV3KHQsZSl7c3dpdGNoKGUpe2Nhc2UhMDpyZXR1cm4gbmV3IHFjKHQpO2Nhc2UhMTpyZXR1cm4gbmV3IFdjKHQpfXN3aXRjaCh0LmNvbnN0cnVjdG9yKXtjYXNlIEludDhBcnJheTpjYXNlIEludDE2QXJyYXk6Y2FzZSBJbnQzMkFycmF5OmNhc2UgQmlnSW50NjRBcnJheTpyZXR1cm4gbmV3IHFjKHQpfWlmKHQuYnl0ZUxlbmd0aD09PTE2KXJldHVybiBuZXcgSXUodCk7cmV0dXJuIG5ldyBXYyh0KX1zdGF0aWMgc2lnbmVkKHQpe3JldHVybiBuZXcgcWModCl9c3RhdGljIHVuc2lnbmVkKHQpe3JldHVybiBuZXcgV2ModCl9c3RhdGljIGRlY2ltYWwodCl7cmV0dXJuIG5ldyBJdSh0KX1jb25zdHJ1Y3Rvcih0LGUpe3JldHVybiBCdS5uZXcodCxlKX19dmFyIGFCLCRGLHFGO3ZhciB6Xz1tKCgpPT57WWUoKTthQj1TeW1ib2wuZm9yKCJpc0Fycm93QmlnTnVtIik7R2kucHJvdG90eXBlW2FCXT0hMDtHaS5wcm90b3R5cGUudG9KU09OPWZ1bmN0aW9uKCl7cmV0dXJuYCIke0hjKHRoaXMpfSJgfTtHaS5wcm90b3R5cGUudmFsdWVPZj1mdW5jdGlvbih0KXtyZXR1cm4ga18odGhpcyx0KX07R2kucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuIEhjKHRoaXMpfTtHaS5wcm90b3R5cGVbU3ltYm9sLnRvUHJpbWl0aXZlXT1mdW5jdGlvbih0PSJkZWZhdWx0Iil7c3dpdGNoKHQpe2Nhc2UibnVtYmVyIjpyZXR1cm4ga18odGhpcyk7Y2FzZSJzdHJpbmciOnJldHVybiBIYyh0aGlzKTtjYXNlImRlZmF1bHQiOnJldHVybiBjQih0aGlzKX1yZXR1cm4gSGModGhpcyl9O09iamVjdC5zZXRQcm90b3R5cGVPZihxYy5wcm90b3R5cGUsT2JqZWN0LmNyZWF0ZShJbnQzMkFycmF5LnByb3RvdHlwZSkpO09iamVjdC5zZXRQcm90b3R5cGVPZihXYy5wcm90b3R5cGUsT2JqZWN0LmNyZWF0ZShVaW50MzJBcnJheS5wcm90b3R5cGUpKTtPYmplY3Quc2V0UHJvdG90eXBlT2YoSXUucHJvdG90eXBlLE9iamVjdC5jcmVhdGUoVWludDMyQXJyYXkucHJvdG90eXBlKSk7T2JqZWN0LmFzc2lnbihxYy5wcm90b3R5cGUsR2kucHJvdG90eXBlLHtjb25zdHJ1Y3RvcjpxYyxzaWduZWQ6ITAsVHlwZWRBcnJheTpJbnQzMkFycmF5LEJpZ0ludEFycmF5OkJpZ0ludDY0QXJyYXl9KTtPYmplY3QuYXNzaWduKFdjLnByb3RvdHlwZSxHaS5wcm90b3R5cGUse2NvbnN0cnVjdG9yOldjLHNpZ25lZDohMSxUeXBlZEFycmF5OlVpbnQzMkFycmF5LEJpZ0ludEFycmF5OkJpZ1VpbnQ2NEFycmF5fSk7T2JqZWN0LmFzc2lnbihJdS5wcm90b3R5cGUsR2kucHJvdG90eXBlLHtjb25zdHJ1Y3RvcjpJdSxzaWduZWQ6ITAsVHlwZWRBcnJheTpVaW50MzJBcnJheSxCaWdJbnRBcnJheTpCaWdVaW50NjRBcnJheX0pOyRGPUJpZ0ludCg0Mjk0OTY3Mjk2KSpCaWdJbnQoNDI5NDk2NzI5NikscUY9JEYtQmlnSW50KDEpfSk7Y2xhc3MgQXtzdGF0aWMgaXNEYXRhVHlwZSh0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnRbTUJdKT09PSEwfXN0YXRpYyBpc051bGwodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT15Lk51bGx9c3RhdGljIGlzSW50KHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC50eXBlSWQpPT09eS5JbnR9c3RhdGljIGlzRmxvYXQodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT15LkZsb2F0fXN0YXRpYyBpc0JpbmFyeSh0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnQudHlwZUlkKT09PXkuQmluYXJ5fXN0YXRpYyBpc0JpbmFyeVZpZXcodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT15LkJpbmFyeVZpZXd9c3RhdGljIGlzTGFyZ2VCaW5hcnkodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT15LkxhcmdlQmluYXJ5fXN0YXRpYyBpc1V0ZjgodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT15LlV0Zjh9c3RhdGljIGlzVXRmOFZpZXcodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT15LlV0ZjhWaWV3fXN0YXRpYyBpc0xhcmdlVXRmOCh0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnQudHlwZUlkKT09PXkuTGFyZ2VVdGY4fXN0YXRpYyBpc0Jvb2wodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT15LkJvb2x9c3RhdGljIGlzRGVjaW1hbCh0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnQudHlwZUlkKT09PXkuRGVjaW1hbH1zdGF0aWMgaXNEYXRlKHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC50eXBlSWQpPT09eS5EYXRlfXN0YXRpYyBpc1RpbWUodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT15LlRpbWV9c3RhdGljIGlzVGltZXN0YW1wKHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC50eXBlSWQpPT09eS5UaW1lc3RhbXB9c3RhdGljIGlzSW50ZXJ2YWwodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT15LkludGVydmFsfXN0YXRpYyBpc0R1cmF0aW9uKHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC50eXBlSWQpPT09eS5EdXJhdGlvbn1zdGF0aWMgaXNMaXN0KHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC50eXBlSWQpPT09eS5MaXN0fXN0YXRpYyBpc1N0cnVjdCh0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnQudHlwZUlkKT09PXkuU3RydWN0fXN0YXRpYyBpc1VuaW9uKHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC50eXBlSWQpPT09eS5Vbmlvbn1zdGF0aWMgaXNGaXhlZFNpemVCaW5hcnkodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT15LkZpeGVkU2l6ZUJpbmFyeX1zdGF0aWMgaXNGaXhlZFNpemVMaXN0KHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC50eXBlSWQpPT09eS5GaXhlZFNpemVMaXN0fXN0YXRpYyBpc01hcCh0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnQudHlwZUlkKT09PXkuTWFwfXN0YXRpYyBpc0RpY3Rpb25hcnkodCl7cmV0dXJuKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0LnR5cGVJZCk9PT15LkRpY3Rpb25hcnl9c3RhdGljIGlzRGVuc2VVbmlvbih0KXtyZXR1cm4gQS5pc1VuaW9uKHQpJiZ0Lm1vZGU9PT1zZS5EZW5zZX1zdGF0aWMgaXNTcGFyc2VVbmlvbih0KXtyZXR1cm4gQS5pc1VuaW9uKHQpJiZ0Lm1vZGU9PT1zZS5TcGFyc2V9Y29uc3RydWN0b3IodCl7dGhpcy50eXBlSWQ9dH19ZnVuY3Rpb24gVW4odCl7bGV0IGU9dDtzd2l0Y2godC50eXBlSWQpe2Nhc2UgeS5EZWNpbWFsOnJldHVybiB0LmJpdFdpZHRoLzMyO2Nhc2UgeS5JbnRlcnZhbDp7aWYoZS51bml0PT09Y2UuTU9OVEhfREFZX05BTk8pcmV0dXJuIDQ7cmV0dXJuIDErZS51bml0fWNhc2UgeS5CaW5hcnlWaWV3OmNhc2UgeS5VdGY4VmlldzpyZXR1cm4gMTY7Y2FzZSB5LkZpeGVkU2l6ZUxpc3Q6cmV0dXJuIGUubGlzdFNpemU7Y2FzZSB5LkZpeGVkU2l6ZUJpbmFyeTpyZXR1cm4gZS5ieXRlV2lkdGg7ZGVmYXVsdDpyZXR1cm4gMX19dmFyIGxCLHVCLGZCLGRCLGhCLHBCLG1CLHlCLF9CLGdCLGJCLHdCLHZCLElCLEJCLFNCLEFCLERCLHhCLFRCLEVCLE9CLE5CLEZCLE1CLG5yLEtlLE9hLE5hLGpyLGNuLEZhLE1hLExhLFVhLHVpLGNoLFJhLFppLGZpLGJ0LHBzLFRyLExuLG1zLG9uLHlzLFJzLENzLGRpLFN1LFBzLGtzLGFuLE90LEppLF9zLFhpLGhpLFdGLEVyO3ZhciBhZT1tKCgpPT57Q2UoKTtNQj1TeW1ib2wuZm9yKCJhcGFjaGUtYXJyb3cvRGF0YVR5cGUiKTtsQj1TeW1ib2wudG9TdHJpbmdUYWc7QVtsQl09KCh0KT0+KHQuY2hpbGRyZW49bnVsbCx0LkFycmF5VHlwZT1BcnJheSx0Lk9mZnNldEFycmF5VHlwZT1JbnQzMkFycmF5LHRbTUJdPSEwLHRbU3ltYm9sLnRvU3RyaW5nVGFnXT0iRGF0YVR5cGUiKSkoQS5wcm90b3R5cGUpO25yPWNsYXNzIG5yIGV4dGVuZHMgQXtjb25zdHJ1Y3Rvcigpe3N1cGVyKHkuTnVsbCl9dG9TdHJpbmcoKXtyZXR1cm4iTnVsbCJ9fTt1Qj1TeW1ib2wudG9TdHJpbmdUYWc7bnJbdUJdPSgodCk9PnRbU3ltYm9sLnRvU3RyaW5nVGFnXT0iTnVsbCIpKG5yLnByb3RvdHlwZSk7S2U9Y2xhc3MgS2UgZXh0ZW5kcyBBe2NvbnN0cnVjdG9yKHQsZSl7c3VwZXIoeS5JbnQpO3RoaXMuaXNTaWduZWQ9dCx0aGlzLmJpdFdpZHRoPWV9Z2V0IEFycmF5VHlwZSgpe3N3aXRjaCh0aGlzLmJpdFdpZHRoKXtjYXNlIDg6cmV0dXJuIHRoaXMuaXNTaWduZWQ/SW50OEFycmF5OlVpbnQ4QXJyYXk7Y2FzZSAxNjpyZXR1cm4gdGhpcy5pc1NpZ25lZD9JbnQxNkFycmF5OlVpbnQxNkFycmF5O2Nhc2UgMzI6cmV0dXJuIHRoaXMuaXNTaWduZWQ/SW50MzJBcnJheTpVaW50MzJBcnJheTtjYXNlIDY0OnJldHVybiB0aGlzLmlzU2lnbmVkP0JpZ0ludDY0QXJyYXk6QmlnVWludDY0QXJyYXl9dGhyb3cgRXJyb3IoYFVucmVjb2duaXplZCAke3RoaXNbU3ltYm9sLnRvU3RyaW5nVGFnXX0gdHlwZWApfXRvU3RyaW5nKCl7cmV0dXJuYCR7dGhpcy5pc1NpZ25lZD8iSSI6IlVpIn1udCR7dGhpcy5iaXRXaWR0aH1gfX07ZkI9U3ltYm9sLnRvU3RyaW5nVGFnO0tlW2ZCXT0oKHQpPT4odC5pc1NpZ25lZD1udWxsLHQuYml0V2lkdGg9bnVsbCx0W1N5bWJvbC50b1N0cmluZ1RhZ109IkludCIpKShLZS5wcm90b3R5cGUpO09hPWNsYXNzIE9hIGV4dGVuZHMgS2V7Y29uc3RydWN0b3IoKXtzdXBlcighMCw4KX1nZXQgQXJyYXlUeXBlKCl7cmV0dXJuIEludDhBcnJheX19O05hPWNsYXNzIE5hIGV4dGVuZHMgS2V7Y29uc3RydWN0b3IoKXtzdXBlcighMCwxNil9Z2V0IEFycmF5VHlwZSgpe3JldHVybiBJbnQxNkFycmF5fX07anI9Y2xhc3MganIgZXh0ZW5kcyBLZXtjb25zdHJ1Y3Rvcigpe3N1cGVyKCEwLDMyKX1nZXQgQXJyYXlUeXBlKCl7cmV0dXJuIEludDMyQXJyYXl9fTtjbj1jbGFzcyBjbiBleHRlbmRzIEtle2NvbnN0cnVjdG9yKCl7c3VwZXIoITAsNjQpfWdldCBBcnJheVR5cGUoKXtyZXR1cm4gQmlnSW50NjRBcnJheX19O0ZhPWNsYXNzIEZhIGV4dGVuZHMgS2V7Y29uc3RydWN0b3IoKXtzdXBlcighMSw4KX1nZXQgQXJyYXlUeXBlKCl7cmV0dXJuIFVpbnQ4QXJyYXl9fTtNYT1jbGFzcyBNYSBleHRlbmRzIEtle2NvbnN0cnVjdG9yKCl7c3VwZXIoITEsMTYpfWdldCBBcnJheVR5cGUoKXtyZXR1cm4gVWludDE2QXJyYXl9fTtMYT1jbGFzcyBMYSBleHRlbmRzIEtle2NvbnN0cnVjdG9yKCl7c3VwZXIoITEsMzIpfWdldCBBcnJheVR5cGUoKXtyZXR1cm4gVWludDMyQXJyYXl9fTtVYT1jbGFzcyBVYSBleHRlbmRzIEtle2NvbnN0cnVjdG9yKCl7c3VwZXIoITEsNjQpfWdldCBBcnJheVR5cGUoKXtyZXR1cm4gQmlnVWludDY0QXJyYXl9fTtPYmplY3QuZGVmaW5lUHJvcGVydHkoT2EucHJvdG90eXBlLCJBcnJheVR5cGUiLHt2YWx1ZTpJbnQ4QXJyYXl9KTtPYmplY3QuZGVmaW5lUHJvcGVydHkoTmEucHJvdG90eXBlLCJBcnJheVR5cGUiLHt2YWx1ZTpJbnQxNkFycmF5fSk7T2JqZWN0LmRlZmluZVByb3BlcnR5KGpyLnByb3RvdHlwZSwiQXJyYXlUeXBlIix7dmFsdWU6SW50MzJBcnJheX0pO09iamVjdC5kZWZpbmVQcm9wZXJ0eShjbi5wcm90b3R5cGUsIkFycmF5VHlwZSIse3ZhbHVlOkJpZ0ludDY0QXJyYXl9KTtPYmplY3QuZGVmaW5lUHJvcGVydHkoRmEucHJvdG90eXBlLCJBcnJheVR5cGUiLHt2YWx1ZTpVaW50OEFycmF5fSk7T2JqZWN0LmRlZmluZVByb3BlcnR5KE1hLnByb3RvdHlwZSwiQXJyYXlUeXBlIix7dmFsdWU6VWludDE2QXJyYXl9KTtPYmplY3QuZGVmaW5lUHJvcGVydHkoTGEucHJvdG90eXBlLCJBcnJheVR5cGUiLHt2YWx1ZTpVaW50MzJBcnJheX0pO09iamVjdC5kZWZpbmVQcm9wZXJ0eShVYS5wcm90b3R5cGUsIkFycmF5VHlwZSIse3ZhbHVlOkJpZ1VpbnQ2NEFycmF5fSk7dWk9Y2xhc3MgdWkgZXh0ZW5kcyBBe2NvbnN0cnVjdG9yKHQpe3N1cGVyKHkuRmxvYXQpO3RoaXMucHJlY2lzaW9uPXR9Z2V0IEFycmF5VHlwZSgpe3N3aXRjaCh0aGlzLnByZWNpc2lvbil7Y2FzZSByZS5IQUxGOnJldHVybiBVaW50MTZBcnJheTtjYXNlIHJlLlNJTkdMRTpyZXR1cm4gRmxvYXQzMkFycmF5O2Nhc2UgcmUuRE9VQkxFOnJldHVybiBGbG9hdDY0QXJyYXl9dGhyb3cgRXJyb3IoYFVucmVjb2duaXplZCAke3RoaXNbU3ltYm9sLnRvU3RyaW5nVGFnXX0gdHlwZWApfXRvU3RyaW5nKCl7cmV0dXJuYEZsb2F0JHt0aGlzLnByZWNpc2lvbjw8NXx8MTZ9YH19O2RCPVN5bWJvbC50b1N0cmluZ1RhZzt1aVtkQl09KCh0KT0+KHQucHJlY2lzaW9uPW51bGwsdFtTeW1ib2wudG9TdHJpbmdUYWddPSJGbG9hdCIpKSh1aS5wcm90b3R5cGUpO2NoPWNsYXNzIGNoIGV4dGVuZHMgdWl7Y29uc3RydWN0b3IoKXtzdXBlcihyZS5IQUxGKX19O1JhPWNsYXNzIFJhIGV4dGVuZHMgdWl7Y29uc3RydWN0b3IoKXtzdXBlcihyZS5TSU5HTEUpfX07Wmk9Y2xhc3MgWmkgZXh0ZW5kcyB1aXtjb25zdHJ1Y3Rvcigpe3N1cGVyKHJlLkRPVUJMRSl9fTtPYmplY3QuZGVmaW5lUHJvcGVydHkoY2gucHJvdG90eXBlLCJBcnJheVR5cGUiLHt2YWx1ZTpVaW50MTZBcnJheX0pO09iamVjdC5kZWZpbmVQcm9wZXJ0eShSYS5wcm90b3R5cGUsIkFycmF5VHlwZSIse3ZhbHVlOkZsb2F0MzJBcnJheX0pO09iamVjdC5kZWZpbmVQcm9wZXJ0eShaaS5wcm90b3R5cGUsIkFycmF5VHlwZSIse3ZhbHVlOkZsb2F0NjRBcnJheX0pO2ZpPWNsYXNzIGZpIGV4dGVuZHMgQXtjb25zdHJ1Y3Rvcigpe3N1cGVyKHkuQmluYXJ5KX10b1N0cmluZygpe3JldHVybiJCaW5hcnkifX07aEI9U3ltYm9sLnRvU3RyaW5nVGFnO2ZpW2hCXT0oKHQpPT4odC5BcnJheVR5cGU9VWludDhBcnJheSx0W1N5bWJvbC50b1N0cmluZ1RhZ109IkJpbmFyeSIpKShmaS5wcm90b3R5cGUpO2J0PWNsYXNzIGJ0IGV4dGVuZHMgQXtjb25zdHJ1Y3Rvcigpe3N1cGVyKHkuQmluYXJ5Vmlldyl9dG9TdHJpbmcoKXtyZXR1cm4iQmluYXJ5VmlldyJ9fTtwQj1TeW1ib2wudG9TdHJpbmdUYWc7YnQuRUxFTUVOVF9XSURUSD0xNjtidC5JTkxJTkVfQ0FQQUNJVFk9MTI7YnQuTEVOR1RIX09GRlNFVD0wO2J0LklOTElORV9PRkZTRVQ9NDtidC5CVUZGRVJfSU5ERVhfT0ZGU0VUPTg7YnQuQlVGRkVSX09GRlNFVF9PRkZTRVQ9MTI7YnRbcEJdPSgodCk9Pih0LkFycmF5VHlwZT1VaW50OEFycmF5LHRbU3ltYm9sLnRvU3RyaW5nVGFnXT0iQmluYXJ5VmlldyIpKShidC5wcm90b3R5cGUpO3BzPWNsYXNzIHBzIGV4dGVuZHMgQXtjb25zdHJ1Y3Rvcigpe3N1cGVyKHkuTGFyZ2VCaW5hcnkpfXRvU3RyaW5nKCl7cmV0dXJuIkxhcmdlQmluYXJ5In19O21CPVN5bWJvbC50b1N0cmluZ1RhZztwc1ttQl09KCh0KT0+KHQuQXJyYXlUeXBlPVVpbnQ4QXJyYXksdC5PZmZzZXRBcnJheVR5cGU9QmlnSW50NjRBcnJheSx0W1N5bWJvbC50b1N0cmluZ1RhZ109IkxhcmdlQmluYXJ5IikpKHBzLnByb3RvdHlwZSk7VHI9Y2xhc3MgVHIgZXh0ZW5kcyBBe2NvbnN0cnVjdG9yKCl7c3VwZXIoeS5VdGY4KX10b1N0cmluZygpe3JldHVybiJVdGY4In19O3lCPVN5bWJvbC50b1N0cmluZ1RhZztUclt5Ql09KCh0KT0+KHQuQXJyYXlUeXBlPVVpbnQ4QXJyYXksdFtTeW1ib2wudG9TdHJpbmdUYWddPSJVdGY4IikpKFRyLnByb3RvdHlwZSk7TG49Y2xhc3MgTG4gZXh0ZW5kcyBBe2NvbnN0cnVjdG9yKCl7c3VwZXIoeS5VdGY4Vmlldyl9dG9TdHJpbmcoKXtyZXR1cm4iVXRmOFZpZXcifX07X0I9U3ltYm9sLnRvU3RyaW5nVGFnO0xuLkVMRU1FTlRfV0lEVEg9YnQuRUxFTUVOVF9XSURUSDtMbi5JTkxJTkVfQ0FQQUNJVFk9YnQuSU5MSU5FX0NBUEFDSVRZO0xuW19CXT0oKHQpPT4odC5BcnJheVR5cGU9VWludDhBcnJheSx0W1N5bWJvbC50b1N0cmluZ1RhZ109IlV0ZjhWaWV3IikpKExuLnByb3RvdHlwZSk7bXM9Y2xhc3MgbXMgZXh0ZW5kcyBBe2NvbnN0cnVjdG9yKCl7c3VwZXIoeS5MYXJnZVV0ZjgpfXRvU3RyaW5nKCl7cmV0dXJuIkxhcmdlVXRmOCJ9fTtnQj1TeW1ib2wudG9TdHJpbmdUYWc7bXNbZ0JdPSgodCk9Pih0LkFycmF5VHlwZT1VaW50OEFycmF5LHQuT2Zmc2V0QXJyYXlUeXBlPUJpZ0ludDY0QXJyYXksdFtTeW1ib2wudG9TdHJpbmdUYWddPSJMYXJnZVV0ZjgiKSkobXMucHJvdG90eXBlKTtvbj1jbGFzcyBvbiBleHRlbmRzIEF7Y29uc3RydWN0b3IoKXtzdXBlcih5LkJvb2wpfXRvU3RyaW5nKCl7cmV0dXJuIkJvb2wifX07YkI9U3ltYm9sLnRvU3RyaW5nVGFnO29uW2JCXT0oKHQpPT4odC5BcnJheVR5cGU9VWludDhBcnJheSx0W1N5bWJvbC50b1N0cmluZ1RhZ109IkJvb2wiKSkob24ucHJvdG90eXBlKTt5cz1jbGFzcyB5cyBleHRlbmRzIEF7Y29uc3RydWN0b3IodCxlLHI9MTI4KXtzdXBlcih5LkRlY2ltYWwpO3RoaXMuc2NhbGU9dCx0aGlzLnByZWNpc2lvbj1lLHRoaXMuYml0V2lkdGg9cn10b1N0cmluZygpe3JldHVybmBEZWNpbWFsWyR7dGhpcy5wcmVjaXNpb259ZSR7dGhpcy5zY2FsZT4wPyIrIjoiIn0ke3RoaXMuc2NhbGV9XWB9fTt3Qj1TeW1ib2wudG9TdHJpbmdUYWc7eXNbd0JdPSgodCk9Pih0LnNjYWxlPW51bGwsdC5wcmVjaXNpb249bnVsbCx0LkFycmF5VHlwZT1VaW50MzJBcnJheSx0W1N5bWJvbC50b1N0cmluZ1RhZ109IkRlY2ltYWwiKSkoeXMucHJvdG90eXBlKTtScz1jbGFzcyBScyBleHRlbmRzIEF7Y29uc3RydWN0b3IodCl7c3VwZXIoeS5EYXRlKTt0aGlzLnVuaXQ9dH10b1N0cmluZygpe3JldHVybmBEYXRlJHsodGhpcy51bml0KzEpKjMyfTwke0llW3RoaXMudW5pdF19PmB9Z2V0IEFycmF5VHlwZSgpe3JldHVybiB0aGlzLnVuaXQ9PT1JZS5EQVk/SW50MzJBcnJheTpCaWdJbnQ2NEFycmF5fX07dkI9U3ltYm9sLnRvU3RyaW5nVGFnO1JzW3ZCXT0oKHQpPT4odC51bml0PW51bGwsdFtTeW1ib2wudG9TdHJpbmdUYWddPSJEYXRlIikpKFJzLnByb3RvdHlwZSk7Q3M9Y2xhc3MgQ3MgZXh0ZW5kcyBBe2NvbnN0cnVjdG9yKHQsZSl7c3VwZXIoeS5UaW1lKTt0aGlzLnVuaXQ9dCx0aGlzLmJpdFdpZHRoPWV9dG9TdHJpbmcoKXtyZXR1cm5gVGltZSR7dGhpcy5iaXRXaWR0aH08JHtSW3RoaXMudW5pdF19PmB9Z2V0IEFycmF5VHlwZSgpe3N3aXRjaCh0aGlzLmJpdFdpZHRoKXtjYXNlIDMyOnJldHVybiBJbnQzMkFycmF5O2Nhc2UgNjQ6cmV0dXJuIEJpZ0ludDY0QXJyYXl9dGhyb3cgRXJyb3IoYFVucmVjb2duaXplZCAke3RoaXNbU3ltYm9sLnRvU3RyaW5nVGFnXX0gdHlwZWApfX07SUI9U3ltYm9sLnRvU3RyaW5nVGFnO0NzW0lCXT0oKHQpPT4odC51bml0PW51bGwsdC5iaXRXaWR0aD1udWxsLHRbU3ltYm9sLnRvU3RyaW5nVGFnXT0iVGltZSIpKShDcy5wcm90b3R5cGUpO2RpPWNsYXNzIGRpIGV4dGVuZHMgQXtjb25zdHJ1Y3Rvcih0LGUpe3N1cGVyKHkuVGltZXN0YW1wKTt0aGlzLnVuaXQ9dCx0aGlzLnRpbWV6b25lPWV9dG9TdHJpbmcoKXtyZXR1cm5gVGltZXN0YW1wPCR7Ult0aGlzLnVuaXRdfSR7dGhpcy50aW1lem9uZT9gLCAke3RoaXMudGltZXpvbmV9YDoiIn0+YH19O0JCPVN5bWJvbC50b1N0cmluZ1RhZztkaVtCQl09KCh0KT0+KHQudW5pdD1udWxsLHQudGltZXpvbmU9bnVsbCx0LkFycmF5VHlwZT1CaWdJbnQ2NEFycmF5LHRbU3ltYm9sLnRvU3RyaW5nVGFnXT0iVGltZXN0YW1wIikpKGRpLnByb3RvdHlwZSk7U3U9Y2xhc3MgU3UgZXh0ZW5kcyBkaXtjb25zdHJ1Y3Rvcih0KXtzdXBlcihSLk1JTExJU0VDT05ELHQpfX07UHM9Y2xhc3MgUHMgZXh0ZW5kcyBBe2NvbnN0cnVjdG9yKHQpe3N1cGVyKHkuSW50ZXJ2YWwpO3RoaXMudW5pdD10fXRvU3RyaW5nKCl7cmV0dXJuYEludGVydmFsPCR7Y2VbdGhpcy51bml0XX0+YH19O1NCPVN5bWJvbC50b1N0cmluZ1RhZztQc1tTQl09KCh0KT0+KHQudW5pdD1udWxsLHQuQXJyYXlUeXBlPUludDMyQXJyYXksdFtTeW1ib2wudG9TdHJpbmdUYWddPSJJbnRlcnZhbCIpKShQcy5wcm90b3R5cGUpO2tzPWNsYXNzIGtzIGV4dGVuZHMgQXtjb25zdHJ1Y3Rvcih0KXtzdXBlcih5LkR1cmF0aW9uKTt0aGlzLnVuaXQ9dH10b1N0cmluZygpe3JldHVybmBEdXJhdGlvbjwke1JbdGhpcy51bml0XX0+YH19O0FCPVN5bWJvbC50b1N0cmluZ1RhZztrc1tBQl09KCh0KT0+KHQudW5pdD1udWxsLHQuQXJyYXlUeXBlPUJpZ0ludDY0QXJyYXksdFtTeW1ib2wudG9TdHJpbmdUYWddPSJEdXJhdGlvbiIpKShrcy5wcm90b3R5cGUpO2FuPWNsYXNzIGFuIGV4dGVuZHMgQXtjb25zdHJ1Y3Rvcih0KXtzdXBlcih5Lkxpc3QpO3RoaXMuY2hpbGRyZW49W3RdfXRvU3RyaW5nKCl7cmV0dXJuYExpc3Q8JHt0aGlzLnZhbHVlVHlwZX0+YH1nZXQgdmFsdWVUeXBlKCl7cmV0dXJuIHRoaXMuY2hpbGRyZW5bMF0udHlwZX1nZXQgdmFsdWVGaWVsZCgpe3JldHVybiB0aGlzLmNoaWxkcmVuWzBdfWdldCBBcnJheVR5cGUoKXtyZXR1cm4gdGhpcy52YWx1ZVR5cGUuQXJyYXlUeXBlfX07REI9U3ltYm9sLnRvU3RyaW5nVGFnO2FuW0RCXT0oKHQpPT4odC5jaGlsZHJlbj1udWxsLHRbU3ltYm9sLnRvU3RyaW5nVGFnXT0iTGlzdCIpKShhbi5wcm90b3R5cGUpO090PWNsYXNzIE90IGV4dGVuZHMgQXtjb25zdHJ1Y3Rvcih0KXtzdXBlcih5LlN0cnVjdCk7dGhpcy5jaGlsZHJlbj10fXRvU3RyaW5nKCl7cmV0dXJuYFN0cnVjdDx7JHt0aGlzLmNoaWxkcmVuLm1hcCgodCk9PmAke3QubmFtZX06JHt0LnR5cGV9YCkuam9pbigiLCAiKX19PmB9fTt4Qj1TeW1ib2wudG9TdHJpbmdUYWc7T3RbeEJdPSgodCk9Pih0LmNoaWxkcmVuPW51bGwsdFtTeW1ib2wudG9TdHJpbmdUYWddPSJTdHJ1Y3QiKSkoT3QucHJvdG90eXBlKTtKaT1jbGFzcyBKaSBleHRlbmRzIEF7Y29uc3RydWN0b3IodCxlLHIpe3N1cGVyKHkuVW5pb24pO3RoaXMubW9kZT10LHRoaXMuY2hpbGRyZW49cix0aGlzLnR5cGVJZHM9ZT1JbnQzMkFycmF5LmZyb20oZSksdGhpcy50eXBlSWRUb0NoaWxkSW5kZXg9ZS5yZWR1Y2UoKG4saSxzKT0+KG5baV09cykmJm58fG4sT2JqZWN0LmNyZWF0ZShudWxsKSl9dG9TdHJpbmcoKXtyZXR1cm5gJHt0aGlzW1N5bWJvbC50b1N0cmluZ1RhZ119PCR7dGhpcy5jaGlsZHJlbi5tYXAoKHQpPT5gJHt0LnR5cGV9YCkuam9pbigiIHwgIil9PmB9fTtUQj1TeW1ib2wudG9TdHJpbmdUYWc7SmlbVEJdPSgodCk9Pih0Lm1vZGU9bnVsbCx0LnR5cGVJZHM9bnVsbCx0LmNoaWxkcmVuPW51bGwsdC50eXBlSWRUb0NoaWxkSW5kZXg9bnVsbCx0LkFycmF5VHlwZT1JbnQ4QXJyYXksdFtTeW1ib2wudG9TdHJpbmdUYWddPSJVbmlvbiIpKShKaS5wcm90b3R5cGUpO19zPWNsYXNzIF9zIGV4dGVuZHMgQXtjb25zdHJ1Y3Rvcih0KXtzdXBlcih5LkZpeGVkU2l6ZUJpbmFyeSk7dGhpcy5ieXRlV2lkdGg9dH10b1N0cmluZygpe3JldHVybmBGaXhlZFNpemVCaW5hcnlbJHt0aGlzLmJ5dGVXaWR0aH1dYH19O0VCPVN5bWJvbC50b1N0cmluZ1RhZztfc1tFQl09KCh0KT0+KHQuYnl0ZVdpZHRoPW51bGwsdC5BcnJheVR5cGU9VWludDhBcnJheSx0W1N5bWJvbC50b1N0cmluZ1RhZ109IkZpeGVkU2l6ZUJpbmFyeSIpKShfcy5wcm90b3R5cGUpO1hpPWNsYXNzIFhpIGV4dGVuZHMgQXtjb25zdHJ1Y3Rvcih0LGUpe3N1cGVyKHkuRml4ZWRTaXplTGlzdCk7dGhpcy5saXN0U2l6ZT10LHRoaXMuY2hpbGRyZW49W2VdfWdldCB2YWx1ZVR5cGUoKXtyZXR1cm4gdGhpcy5jaGlsZHJlblswXS50eXBlfWdldCB2YWx1ZUZpZWxkKCl7cmV0dXJuIHRoaXMuY2hpbGRyZW5bMF19Z2V0IEFycmF5VHlwZSgpe3JldHVybiB0aGlzLnZhbHVlVHlwZS5BcnJheVR5cGV9dG9TdHJpbmcoKXtyZXR1cm5gRml4ZWRTaXplTGlzdFske3RoaXMubGlzdFNpemV9XTwke3RoaXMudmFsdWVUeXBlfT5gfX07T0I9U3ltYm9sLnRvU3RyaW5nVGFnO1hpW09CXT0oKHQpPT4odC5jaGlsZHJlbj1udWxsLHQubGlzdFNpemU9bnVsbCx0W1N5bWJvbC50b1N0cmluZ1RhZ109IkZpeGVkU2l6ZUxpc3QiKSkoWGkucHJvdG90eXBlKTtoaT1jbGFzcyBoaSBleHRlbmRzIEF7Y29uc3RydWN0b3IodCxlPSExKXt2YXIgcixuLGk7c3VwZXIoeS5NYXApO2lmKHRoaXMuY2hpbGRyZW49W3RdLHRoaXMua2V5c1NvcnRlZD1lLHQpe2lmKHQubmFtZT0iZW50cmllcyIsKHI9dD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnQudHlwZSk9PT1udWxsfHxyPT09dm9pZCAwP3ZvaWQgMDpyLmNoaWxkcmVuKXtsZXQgcz0obj10PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC50eXBlKT09PW51bGx8fG49PT12b2lkIDA/dm9pZCAwOm4uY2hpbGRyZW5bMF07aWYocylzLm5hbWU9ImtleSI7bGV0IG89KGk9dD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnQudHlwZSk9PT1udWxsfHxpPT09dm9pZCAwP3ZvaWQgMDppLmNoaWxkcmVuWzFdO2lmKG8pby5uYW1lPSJ2YWx1ZSJ9fX1nZXQga2V5VHlwZSgpe3JldHVybiB0aGlzLmNoaWxkcmVuWzBdLnR5cGUuY2hpbGRyZW5bMF0udHlwZX1nZXQgdmFsdWVUeXBlKCl7cmV0dXJuIHRoaXMuY2hpbGRyZW5bMF0udHlwZS5jaGlsZHJlblsxXS50eXBlfWdldCBjaGlsZFR5cGUoKXtyZXR1cm4gdGhpcy5jaGlsZHJlblswXS50eXBlfXRvU3RyaW5nKCl7cmV0dXJuYE1hcDx7JHt0aGlzLmNoaWxkcmVuWzBdLnR5cGUuY2hpbGRyZW4ubWFwKCh0KT0+YCR7dC5uYW1lfToke3QudHlwZX1gKS5qb2luKCIsICIpfX0+YH19O05CPVN5bWJvbC50b1N0cmluZ1RhZztoaVtOQl09KCh0KT0+KHQuY2hpbGRyZW49bnVsbCx0LmtleXNTb3J0ZWQ9bnVsbCx0W1N5bWJvbC50b1N0cmluZ1RhZ109Ik1hcF8iKSkoaGkucHJvdG90eXBlKTtXRj0oKHQpPT4oKT0+Kyt0KSgtMSk7RXI9Y2xhc3MgRXIgZXh0ZW5kcyBBe2NvbnN0cnVjdG9yKHQsZSxyLG4pe3N1cGVyKHkuRGljdGlvbmFyeSk7dGhpcy5pbmRpY2VzPWUsdGhpcy5kaWN0aW9uYXJ5PXQsdGhpcy5pc09yZGVyZWQ9bnx8ITEsdGhpcy5pZD1yPT1udWxsP1dGKCk6VnQocil9Z2V0IGNoaWxkcmVuKCl7cmV0dXJuIHRoaXMuZGljdGlvbmFyeS5jaGlsZHJlbn1nZXQgdmFsdWVUeXBlKCl7cmV0dXJuIHRoaXMuZGljdGlvbmFyeX1nZXQgQXJyYXlUeXBlKCl7cmV0dXJuIHRoaXMuZGljdGlvbmFyeS5BcnJheVR5cGV9dG9TdHJpbmcoKXtyZXR1cm5gRGljdGlvbmFyeTwke3RoaXMuaW5kaWNlc30sICR7dGhpcy5kaWN0aW9uYXJ5fT5gfX07RkI9U3ltYm9sLnRvU3RyaW5nVGFnO0VyW0ZCXT0oKHQpPT4odC5pZD1udWxsLHQuaW5kaWNlcz1udWxsLHQuaXNPcmRlcmVkPW51bGwsdC5kaWN0aW9uYXJ5PW51bGwsdFtTeW1ib2wudG9TdHJpbmdUYWddPSJEaWN0aW9uYXJ5IikpKEVyLnByb3RvdHlwZSl9KTtjbGFzcyBzdHt2aXNpdE1hbnkodCwuLi5lKXtyZXR1cm4gdC5tYXAoKHIsbik9PnRoaXMudmlzaXQociwuLi5lLm1hcCgoaSk9Pmlbbl0pKSl9dmlzaXQoLi4udCl7cmV0dXJuIHRoaXMuZ2V0VmlzaXRGbih0WzBdLCExKS5hcHBseSh0aGlzLHQpfWdldFZpc2l0Rm4odCxlPSEwKXtyZXR1cm4gSEYodGhpcyx0LGUpfWdldFZpc2l0Rm5CeVR5cGVJZCh0LGU9ITApe3JldHVybiBZYyh0aGlzLHQsZSl9dmlzaXROdWxsKHQsLi4uZSl7cmV0dXJuIG51bGx9dmlzaXRCb29sKHQsLi4uZSl7cmV0dXJuIG51bGx9dmlzaXRJbnQodCwuLi5lKXtyZXR1cm4gbnVsbH12aXNpdEZsb2F0KHQsLi4uZSl7cmV0dXJuIG51bGx9dmlzaXRVdGY4KHQsLi4uZSl7cmV0dXJuIG51bGx9dmlzaXRMYXJnZVV0ZjgodCwuLi5lKXtyZXR1cm4gbnVsbH12aXNpdFV0ZjhWaWV3KHQsLi4uZSl7cmV0dXJuIG51bGx9dmlzaXRCaW5hcnkodCwuLi5lKXtyZXR1cm4gbnVsbH12aXNpdExhcmdlQmluYXJ5KHQsLi4uZSl7cmV0dXJuIG51bGx9dmlzaXRCaW5hcnlWaWV3KHQsLi4uZSl7cmV0dXJuIG51bGx9dmlzaXRGaXhlZFNpemVCaW5hcnkodCwuLi5lKXtyZXR1cm4gbnVsbH12aXNpdERhdGUodCwuLi5lKXtyZXR1cm4gbnVsbH12aXNpdFRpbWVzdGFtcCh0LC4uLmUpe3JldHVybiBudWxsfXZpc2l0VGltZSh0LC4uLmUpe3JldHVybiBudWxsfXZpc2l0RGVjaW1hbCh0LC4uLmUpe3JldHVybiBudWxsfXZpc2l0TGlzdCh0LC4uLmUpe3JldHVybiBudWxsfXZpc2l0U3RydWN0KHQsLi4uZSl7cmV0dXJuIG51bGx9dmlzaXRVbmlvbih0LC4uLmUpe3JldHVybiBudWxsfXZpc2l0RGljdGlvbmFyeSh0LC4uLmUpe3JldHVybiBudWxsfXZpc2l0SW50ZXJ2YWwodCwuLi5lKXtyZXR1cm4gbnVsbH12aXNpdER1cmF0aW9uKHQsLi4uZSl7cmV0dXJuIG51bGx9dmlzaXRGaXhlZFNpemVMaXN0KHQsLi4uZSl7cmV0dXJuIG51bGx9dmlzaXRNYXAodCwuLi5lKXtyZXR1cm4gbnVsbH19ZnVuY3Rpb24gSEYodCxlLHI9ITApe2lmKHR5cGVvZiBlPT09Im51bWJlciIpcmV0dXJuIFljKHQsZSxyKTtpZih0eXBlb2YgZT09PSJzdHJpbmciJiZlIGluIHkpcmV0dXJuIFljKHQseVtlXSxyKTtpZihlJiZlIGluc3RhbmNlb2YgQSlyZXR1cm4gWWModCxVQihlKSxyKTtpZigoZT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUudHlwZSkmJmUudHlwZSBpbnN0YW5jZW9mIEEpcmV0dXJuIFljKHQsVUIoZS50eXBlKSxyKTtyZXR1cm4gWWModCx5Lk5PTkUscil9ZnVuY3Rpb24gWWModCxlLHI9ITApe2xldCBuPW51bGw7c3dpdGNoKGUpe2Nhc2UgeS5OdWxsOm49dC52aXNpdE51bGw7YnJlYWs7Y2FzZSB5LkJvb2w6bj10LnZpc2l0Qm9vbDticmVhaztjYXNlIHkuSW50Om49dC52aXNpdEludDticmVhaztjYXNlIHkuSW50ODpuPXQudmlzaXRJbnQ4fHx0LnZpc2l0SW50O2JyZWFrO2Nhc2UgeS5JbnQxNjpuPXQudmlzaXRJbnQxNnx8dC52aXNpdEludDticmVhaztjYXNlIHkuSW50MzI6bj10LnZpc2l0SW50MzJ8fHQudmlzaXRJbnQ7YnJlYWs7Y2FzZSB5LkludDY0Om49dC52aXNpdEludDY0fHx0LnZpc2l0SW50O2JyZWFrO2Nhc2UgeS5VaW50ODpuPXQudmlzaXRVaW50OHx8dC52aXNpdEludDticmVhaztjYXNlIHkuVWludDE2Om49dC52aXNpdFVpbnQxNnx8dC52aXNpdEludDticmVhaztjYXNlIHkuVWludDMyOm49dC52aXNpdFVpbnQzMnx8dC52aXNpdEludDticmVhaztjYXNlIHkuVWludDY0Om49dC52aXNpdFVpbnQ2NHx8dC52aXNpdEludDticmVhaztjYXNlIHkuRmxvYXQ6bj10LnZpc2l0RmxvYXQ7YnJlYWs7Y2FzZSB5LkZsb2F0MTY6bj10LnZpc2l0RmxvYXQxNnx8dC52aXNpdEZsb2F0O2JyZWFrO2Nhc2UgeS5GbG9hdDMyOm49dC52aXNpdEZsb2F0MzJ8fHQudmlzaXRGbG9hdDticmVhaztjYXNlIHkuRmxvYXQ2NDpuPXQudmlzaXRGbG9hdDY0fHx0LnZpc2l0RmxvYXQ7YnJlYWs7Y2FzZSB5LlV0Zjg6bj10LnZpc2l0VXRmODticmVhaztjYXNlIHkuTGFyZ2VVdGY4Om49dC52aXNpdExhcmdlVXRmODticmVhaztjYXNlIHkuVXRmOFZpZXc6bj10LnZpc2l0VXRmOFZpZXd8fHQudmlzaXRVdGY4O2JyZWFrO2Nhc2UgeS5CaW5hcnk6bj10LnZpc2l0QmluYXJ5O2JyZWFrO2Nhc2UgeS5MYXJnZUJpbmFyeTpuPXQudmlzaXRMYXJnZUJpbmFyeTticmVhaztjYXNlIHkuQmluYXJ5VmlldzpuPXQudmlzaXRCaW5hcnlWaWV3fHx0LnZpc2l0QmluYXJ5O2JyZWFrO2Nhc2UgeS5GaXhlZFNpemVCaW5hcnk6bj10LnZpc2l0Rml4ZWRTaXplQmluYXJ5O2JyZWFrO2Nhc2UgeS5EYXRlOm49dC52aXNpdERhdGU7YnJlYWs7Y2FzZSB5LkRhdGVEYXk6bj10LnZpc2l0RGF0ZURheXx8dC52aXNpdERhdGU7YnJlYWs7Y2FzZSB5LkRhdGVNaWxsaXNlY29uZDpuPXQudmlzaXREYXRlTWlsbGlzZWNvbmR8fHQudmlzaXREYXRlO2JyZWFrO2Nhc2UgeS5UaW1lc3RhbXA6bj10LnZpc2l0VGltZXN0YW1wO2JyZWFrO2Nhc2UgeS5UaW1lc3RhbXBTZWNvbmQ6bj10LnZpc2l0VGltZXN0YW1wU2Vjb25kfHx0LnZpc2l0VGltZXN0YW1wO2JyZWFrO2Nhc2UgeS5UaW1lc3RhbXBNaWxsaXNlY29uZDpuPXQudmlzaXRUaW1lc3RhbXBNaWxsaXNlY29uZHx8dC52aXNpdFRpbWVzdGFtcDticmVhaztjYXNlIHkuVGltZXN0YW1wTWljcm9zZWNvbmQ6bj10LnZpc2l0VGltZXN0YW1wTWljcm9zZWNvbmR8fHQudmlzaXRUaW1lc3RhbXA7YnJlYWs7Y2FzZSB5LlRpbWVzdGFtcE5hbm9zZWNvbmQ6bj10LnZpc2l0VGltZXN0YW1wTmFub3NlY29uZHx8dC52aXNpdFRpbWVzdGFtcDticmVhaztjYXNlIHkuVGltZTpuPXQudmlzaXRUaW1lO2JyZWFrO2Nhc2UgeS5UaW1lU2Vjb25kOm49dC52aXNpdFRpbWVTZWNvbmR8fHQudmlzaXRUaW1lO2JyZWFrO2Nhc2UgeS5UaW1lTWlsbGlzZWNvbmQ6bj10LnZpc2l0VGltZU1pbGxpc2Vjb25kfHx0LnZpc2l0VGltZTticmVhaztjYXNlIHkuVGltZU1pY3Jvc2Vjb25kOm49dC52aXNpdFRpbWVNaWNyb3NlY29uZHx8dC52aXNpdFRpbWU7YnJlYWs7Y2FzZSB5LlRpbWVOYW5vc2Vjb25kOm49dC52aXNpdFRpbWVOYW5vc2Vjb25kfHx0LnZpc2l0VGltZTticmVhaztjYXNlIHkuRGVjaW1hbDpuPXQudmlzaXREZWNpbWFsO2JyZWFrO2Nhc2UgeS5MaXN0Om49dC52aXNpdExpc3Q7YnJlYWs7Y2FzZSB5LlN0cnVjdDpuPXQudmlzaXRTdHJ1Y3Q7YnJlYWs7Y2FzZSB5LlVuaW9uOm49dC52aXNpdFVuaW9uO2JyZWFrO2Nhc2UgeS5EZW5zZVVuaW9uOm49dC52aXNpdERlbnNlVW5pb258fHQudmlzaXRVbmlvbjticmVhaztjYXNlIHkuU3BhcnNlVW5pb246bj10LnZpc2l0U3BhcnNlVW5pb258fHQudmlzaXRVbmlvbjticmVhaztjYXNlIHkuRGljdGlvbmFyeTpuPXQudmlzaXREaWN0aW9uYXJ5O2JyZWFrO2Nhc2UgeS5JbnRlcnZhbDpuPXQudmlzaXRJbnRlcnZhbDticmVhaztjYXNlIHkuSW50ZXJ2YWxEYXlUaW1lOm49dC52aXNpdEludGVydmFsRGF5VGltZXx8dC52aXNpdEludGVydmFsO2JyZWFrO2Nhc2UgeS5JbnRlcnZhbFllYXJNb250aDpuPXQudmlzaXRJbnRlcnZhbFllYXJNb250aHx8dC52aXNpdEludGVydmFsO2JyZWFrO2Nhc2UgeS5JbnRlcnZhbE1vbnRoRGF5TmFubzpuPXQudmlzaXRJbnRlcnZhbE1vbnRoRGF5TmFub3x8dC52aXNpdEludGVydmFsO2JyZWFrO2Nhc2UgeS5EdXJhdGlvbjpuPXQudmlzaXREdXJhdGlvbjticmVhaztjYXNlIHkuRHVyYXRpb25TZWNvbmQ6bj10LnZpc2l0RHVyYXRpb25TZWNvbmR8fHQudmlzaXREdXJhdGlvbjticmVhaztjYXNlIHkuRHVyYXRpb25NaWxsaXNlY29uZDpuPXQudmlzaXREdXJhdGlvbk1pbGxpc2Vjb25kfHx0LnZpc2l0RHVyYXRpb247YnJlYWs7Y2FzZSB5LkR1cmF0aW9uTWljcm9zZWNvbmQ6bj10LnZpc2l0RHVyYXRpb25NaWNyb3NlY29uZHx8dC52aXNpdER1cmF0aW9uO2JyZWFrO2Nhc2UgeS5EdXJhdGlvbk5hbm9zZWNvbmQ6bj10LnZpc2l0RHVyYXRpb25OYW5vc2Vjb25kfHx0LnZpc2l0RHVyYXRpb247YnJlYWs7Y2FzZSB5LkZpeGVkU2l6ZUxpc3Q6bj10LnZpc2l0Rml4ZWRTaXplTGlzdDticmVhaztjYXNlIHkuTWFwOm49dC52aXNpdE1hcDticmVha31pZih0eXBlb2Ygbj09PSJmdW5jdGlvbiIpcmV0dXJuIG47aWYoIXIpcmV0dXJuKCk9Pm51bGw7dGhyb3cgRXJyb3IoYFVucmVjb2duaXplZCB0eXBlICcke3lbZV19J2ApfWZ1bmN0aW9uIFVCKHQpe3N3aXRjaCh0LnR5cGVJZCl7Y2FzZSB5Lk51bGw6cmV0dXJuIHkuTnVsbDtjYXNlIHkuSW50OntsZXR7Yml0V2lkdGg6ZSxpc1NpZ25lZDpyfT10O3N3aXRjaChlKXtjYXNlIDg6cmV0dXJuIHI/eS5JbnQ4OnkuVWludDg7Y2FzZSAxNjpyZXR1cm4gcj95LkludDE2OnkuVWludDE2O2Nhc2UgMzI6cmV0dXJuIHI/eS5JbnQzMjp5LlVpbnQzMjtjYXNlIDY0OnJldHVybiByP3kuSW50NjQ6eS5VaW50NjR9cmV0dXJuIHkuSW50fWNhc2UgeS5GbG9hdDpzd2l0Y2godC5wcmVjaXNpb24pe2Nhc2UgcmUuSEFMRjpyZXR1cm4geS5GbG9hdDE2O2Nhc2UgcmUuU0lOR0xFOnJldHVybiB5LkZsb2F0MzI7Y2FzZSByZS5ET1VCTEU6cmV0dXJuIHkuRmxvYXQ2NH1yZXR1cm4geS5GbG9hdDtjYXNlIHkuQmluYXJ5OnJldHVybiB5LkJpbmFyeTtjYXNlIHkuTGFyZ2VCaW5hcnk6cmV0dXJuIHkuTGFyZ2VCaW5hcnk7Y2FzZSB5LkJpbmFyeVZpZXc6cmV0dXJuIHkuQmluYXJ5VmlldztjYXNlIHkuVXRmODpyZXR1cm4geS5VdGY4O2Nhc2UgeS5MYXJnZVV0Zjg6cmV0dXJuIHkuTGFyZ2VVdGY4O2Nhc2UgeS5VdGY4VmlldzpyZXR1cm4geS5VdGY4VmlldztjYXNlIHkuQm9vbDpyZXR1cm4geS5Cb29sO2Nhc2UgeS5EZWNpbWFsOnJldHVybiB5LkRlY2ltYWw7Y2FzZSB5LlRpbWU6c3dpdGNoKHQudW5pdCl7Y2FzZSBSLlNFQ09ORDpyZXR1cm4geS5UaW1lU2Vjb25kO2Nhc2UgUi5NSUxMSVNFQ09ORDpyZXR1cm4geS5UaW1lTWlsbGlzZWNvbmQ7Y2FzZSBSLk1JQ1JPU0VDT05EOnJldHVybiB5LlRpbWVNaWNyb3NlY29uZDtjYXNlIFIuTkFOT1NFQ09ORDpyZXR1cm4geS5UaW1lTmFub3NlY29uZH1yZXR1cm4geS5UaW1lO2Nhc2UgeS5UaW1lc3RhbXA6c3dpdGNoKHQudW5pdCl7Y2FzZSBSLlNFQ09ORDpyZXR1cm4geS5UaW1lc3RhbXBTZWNvbmQ7Y2FzZSBSLk1JTExJU0VDT05EOnJldHVybiB5LlRpbWVzdGFtcE1pbGxpc2Vjb25kO2Nhc2UgUi5NSUNST1NFQ09ORDpyZXR1cm4geS5UaW1lc3RhbXBNaWNyb3NlY29uZDtjYXNlIFIuTkFOT1NFQ09ORDpyZXR1cm4geS5UaW1lc3RhbXBOYW5vc2Vjb25kfXJldHVybiB5LlRpbWVzdGFtcDtjYXNlIHkuRGF0ZTpzd2l0Y2godC51bml0KXtjYXNlIEllLkRBWTpyZXR1cm4geS5EYXRlRGF5O2Nhc2UgSWUuTUlMTElTRUNPTkQ6cmV0dXJuIHkuRGF0ZU1pbGxpc2Vjb25kfXJldHVybiB5LkRhdGU7Y2FzZSB5LkludGVydmFsOnN3aXRjaCh0LnVuaXQpe2Nhc2UgY2UuREFZX1RJTUU6cmV0dXJuIHkuSW50ZXJ2YWxEYXlUaW1lO2Nhc2UgY2UuWUVBUl9NT05USDpyZXR1cm4geS5JbnRlcnZhbFllYXJNb250aDtjYXNlIGNlLk1PTlRIX0RBWV9OQU5POnJldHVybiB5LkludGVydmFsTW9udGhEYXlOYW5vfXJldHVybiB5LkludGVydmFsO2Nhc2UgeS5EdXJhdGlvbjpzd2l0Y2godC51bml0KXtjYXNlIFIuU0VDT05EOnJldHVybiB5LkR1cmF0aW9uU2Vjb25kO2Nhc2UgUi5NSUxMSVNFQ09ORDpyZXR1cm4geS5EdXJhdGlvbk1pbGxpc2Vjb25kO2Nhc2UgUi5NSUNST1NFQ09ORDpyZXR1cm4geS5EdXJhdGlvbk1pY3Jvc2Vjb25kO2Nhc2UgUi5OQU5PU0VDT05EOnJldHVybiB5LkR1cmF0aW9uTmFub3NlY29uZH1yZXR1cm4geS5EdXJhdGlvbjtjYXNlIHkuTWFwOnJldHVybiB5Lk1hcDtjYXNlIHkuTGlzdDpyZXR1cm4geS5MaXN0O2Nhc2UgeS5TdHJ1Y3Q6cmV0dXJuIHkuU3RydWN0O2Nhc2UgeS5Vbmlvbjpzd2l0Y2godC5tb2RlKXtjYXNlIHNlLkRlbnNlOnJldHVybiB5LkRlbnNlVW5pb247Y2FzZSBzZS5TcGFyc2U6cmV0dXJuIHkuU3BhcnNlVW5pb259cmV0dXJuIHkuVW5pb247Y2FzZSB5LkZpeGVkU2l6ZUJpbmFyeTpyZXR1cm4geS5GaXhlZFNpemVCaW5hcnk7Y2FzZSB5LkZpeGVkU2l6ZUxpc3Q6cmV0dXJuIHkuRml4ZWRTaXplTGlzdDtjYXNlIHkuRGljdGlvbmFyeTpyZXR1cm4geS5EaWN0aW9uYXJ5fXRocm93IEVycm9yKGBVbnJlY29nbml6ZWQgdHlwZSAnJHt5W3QudHlwZUlkXX0nYCl9dmFyIFFpPW0oKCk9PntDZSgpO2FlKCk7c3QucHJvdG90eXBlLnZpc2l0SW50OD1udWxsO3N0LnByb3RvdHlwZS52aXNpdEludDE2PW51bGw7c3QucHJvdG90eXBlLnZpc2l0SW50MzI9bnVsbDtzdC5wcm90b3R5cGUudmlzaXRJbnQ2ND1udWxsO3N0LnByb3RvdHlwZS52aXNpdFVpbnQ4PW51bGw7c3QucHJvdG90eXBlLnZpc2l0VWludDE2PW51bGw7c3QucHJvdG90eXBlLnZpc2l0VWludDMyPW51bGw7c3QucHJvdG90eXBlLnZpc2l0VWludDY0PW51bGw7c3QucHJvdG90eXBlLnZpc2l0RmxvYXQxNj1udWxsO3N0LnByb3RvdHlwZS52aXNpdEZsb2F0MzI9bnVsbDtzdC5wcm90b3R5cGUudmlzaXRGbG9hdDY0PW51bGw7c3QucHJvdG90eXBlLnZpc2l0RGF0ZURheT1udWxsO3N0LnByb3RvdHlwZS52aXNpdERhdGVNaWxsaXNlY29uZD1udWxsO3N0LnByb3RvdHlwZS52aXNpdFRpbWVzdGFtcFNlY29uZD1udWxsO3N0LnByb3RvdHlwZS52aXNpdFRpbWVzdGFtcE1pbGxpc2Vjb25kPW51bGw7c3QucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wTWljcm9zZWNvbmQ9bnVsbDtzdC5wcm90b3R5cGUudmlzaXRUaW1lc3RhbXBOYW5vc2Vjb25kPW51bGw7c3QucHJvdG90eXBlLnZpc2l0VGltZVNlY29uZD1udWxsO3N0LnByb3RvdHlwZS52aXNpdFRpbWVNaWxsaXNlY29uZD1udWxsO3N0LnByb3RvdHlwZS52aXNpdFRpbWVNaWNyb3NlY29uZD1udWxsO3N0LnByb3RvdHlwZS52aXNpdFRpbWVOYW5vc2Vjb25kPW51bGw7c3QucHJvdG90eXBlLnZpc2l0RGVuc2VVbmlvbj1udWxsO3N0LnByb3RvdHlwZS52aXNpdFNwYXJzZVVuaW9uPW51bGw7c3QucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWxEYXlUaW1lPW51bGw7c3QucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWxZZWFyTW9udGg9bnVsbDtzdC5wcm90b3R5cGUudmlzaXRJbnRlcnZhbE1vbnRoRGF5TmFubz1udWxsO3N0LnByb3RvdHlwZS52aXNpdER1cmF0aW9uPW51bGw7c3QucHJvdG90eXBlLnZpc2l0RHVyYXRpb25TZWNvbmQ9bnVsbDtzdC5wcm90b3R5cGUudmlzaXREdXJhdGlvbk1pbGxpc2Vjb25kPW51bGw7c3QucHJvdG90eXBlLnZpc2l0RHVyYXRpb25NaWNyb3NlY29uZD1udWxsO3N0LnByb3RvdHlwZS52aXNpdER1cmF0aW9uTmFub3NlY29uZD1udWxsfSk7dmFyIGpfPXt9O1plKGpfLHtmbG9hdDY0VG9VaW50MTY6KCk9PkF1LHVpbnQxNlRvRmxvYXQ2NDooKT0+bGh9KTtmdW5jdGlvbiBsaCh0KXtsZXQgZT0odCYzMTc0NCk+PjEwLHI9KHQmMTAyMykvMTAyNCxuPU1hdGgucG93KC0xLCh0JjMyNzY4KT4+MTUpO3N3aXRjaChlKXtjYXNlIDMxOnJldHVybiBuKihyP051bWJlci5OYU46MS8wKTtjYXNlIDA6cmV0dXJuIG4qKHI/MC4wMDAwNjEwMzUxNTYyNSpyOjApfXJldHVybiBuKk1hdGgucG93KDIsZS0xNSkqKDErcil9ZnVuY3Rpb24gQXUodCl7aWYodCE9PXQpcmV0dXJuIDMyMjU2O1JCWzBdPXQ7bGV0IGU9KEtjWzFdJjIxNDc0ODM2NDgpPj4xNiY2NTUzNSxyPUtjWzFdJjIxNDY0MzUwNzIsbj0wO2lmKHI+PTEwODk0NzA0NjQpaWYoS2NbMF0+MClyPTMxNzQ0O2Vsc2Ugcj0ociYyMDgwMzc0Nzg0KT4+MTYsbj0oS2NbMV0mMTA0ODU3NSk+PjEwO2Vsc2UgaWYocjw9MTA1Njk2NDYwOCluPTEwNDg1NzYrKEtjWzFdJjEwNDg1NzUpLG49MTA0ODU3Nisobjw8KHI+PjIwKS05OTgpPj4yMSxyPTA7ZWxzZSByPXItMTA1Njk2NDYwOD4+MTAsbj0oS2NbMV0mMTA0ODU3NSkrNTEyPj4xMDtyZXR1cm4gZXxyfG4mNjU1MzV9dmFyIFJCLEtjO3ZhciBEdT1tKCgpPT57UkI9bmV3IEZsb2F0NjRBcnJheSgxKSxLYz1uZXcgVWludDMyQXJyYXkoUkIuYnVmZmVyKX0pO2Z1bmN0aW9uIHV0KHQpe3JldHVybihlLHIsbik9PntpZihlLnNldFZhbGlkKHIsbiE9bnVsbCkpcmV0dXJuIHQoZSxyLG4pfX12YXIgdHQsWUY9KHQsZSxyKT0+e3RbZV09TWF0aC5mbG9vcihyLzg2NDAwMDAwKX0sQ0I9KHQsZSxyLG4pPT57aWYocisxPGUubGVuZ3RoKXtsZXQgaT1WdChlW3JdKSxzPVZ0KGVbcisxXSk7dC5zZXQobi5zdWJhcnJheSgwLHMtaSksaSl9fSxLRj0oe29mZnNldDp0LHZhbHVlczplfSxyLG4pPT57bGV0IGk9dCtyO24/ZVtpPj4zXXw9MTw8aSU4OmVbaT4+M10mPX4oMTw8aSU4KX0sVnM9KHt2YWx1ZXM6dH0sZSxyKT0+e3RbZV09cn0sJF89KHt2YWx1ZXM6dH0sZSxyKT0+e3RbZV09cn0sUEI9KHt2YWx1ZXM6dH0sZSxyKT0+e3RbZV09QXUocil9LEdGPSh0LGUscik9Pntzd2l0Y2godC50eXBlLnByZWNpc2lvbil7Y2FzZSByZS5IQUxGOnJldHVybiBQQih0LGUscik7Y2FzZSByZS5TSU5HTEU6Y2FzZSByZS5ET1VCTEU6cmV0dXJuICRfKHQsZSxyKX19LHVoPSh7dmFsdWVzOnR9LGUscik9PntZRih0LGUsci52YWx1ZU9mKCkpfSxmaD0oe3ZhbHVlczp0fSxlLHIpPT57dFtlXT1CaWdJbnQocil9LHFfPSh7c3RyaWRlOnQsdmFsdWVzOmV9LHIsbik9PntlLnNldChuLnN1YmFycmF5KDAsdCksdCpyKX0sa0I9KHt2YWx1ZXM6dCx2YWx1ZU9mZnNldHM6ZX0scixuKT0+Q0IodCxlLHIsbiksSkY9KHQpPT57bGV0IGU9dC52YXJpYWRpY0J1ZmZlcnM7aWYoIUFycmF5LmlzQXJyYXkoZSl8fE9iamVjdC5pc0Zyb3plbihlKSllPUFycmF5LmZyb20oZSksdC52YXJpYWRpY0J1ZmZlcnM9ZTtyZXR1cm4gZX0sVkI9KHQsZSxyKT0+e3ZhciBuLGkscyxvO2xldCBhPXQudmFsdWVzO2lmKCFhKXRocm93IEVycm9yKCJCaW5hcnlWaWV3IGRhdGEgaXMgbWlzc2luZyB2aWV3IGJ1ZmZlciIpO2xldCBsPWJ0LkVMRU1FTlRfV0lEVEgsdT1lKmwsZj11K2w7aWYodTwwfHxmPmEubGVuZ3RoKXRocm93IFJhbmdlRXJyb3IoYEJpbmFyeVZpZXcgaW5kZXggJHtlfSBvdXQgb2YgYm91bmRzYCk7YS5maWxsKDAsdSxmKTtsZXQgcD1uZXcgRGF0YVZpZXcoYS5idWZmZXIsYS5ieXRlT2Zmc2V0K3UsbCksZz1yLmxlbmd0aDtpZihwLnNldEludDMyKGJ0LkxFTkdUSF9PRkZTRVQsZywhMCksZzw9YnQuSU5MSU5FX0NBUEFDSVRZKXthLnNldChyLHUrYnQuSU5MSU5FX09GRlNFVCk7cmV0dXJufWxldCB2PSgobj1yWzBdKSE9PW51bGwmJm4hPT12b2lkIDA/bjowKXwoKGk9clsxXSkhPT1udWxsJiZpIT09dm9pZCAwP2k6MCk8PDh8KChzPXJbMl0pIT09bnVsbCYmcyE9PXZvaWQgMD9zOjApPDwxNnwoKG89clszXSkhPT1udWxsJiZvIT09dm9pZCAwP286MCk8PDI0O3Auc2V0VWludDMyKGJ0LklOTElORV9PRkZTRVQsdj4+PjAsITApO2xldCBJPUpGKHQpLEQ9ci5zbGljZSgpLFo9SS5wdXNoKEQpLTE7cC5zZXRJbnQzMihidC5CVUZGRVJfSU5ERVhfT0ZGU0VULFosITApLHAuc2V0SW50MzIoYnQuQlVGRkVSX09GRlNFVF9PRkZTRVQsMCwhMCl9LFhGPSh0LGUscik9PntsZXQgbj1yIGluc3RhbmNlb2YgVWludDhBcnJheT9yOm5ldyBVaW50OEFycmF5KHIpO1ZCKHQsZSxuKX0sekI9KHt2YWx1ZXM6dCx2YWx1ZU9mZnNldHM6ZX0scixuKT0+Q0IodCxlLHIsTm4obikpLFpGPSh0LGUscik9PntsZXQgbj1ObihyKTtWQih0LGUsbil9LFdfPSh0LGUscik9Pnt0LnR5cGUudW5pdD09PUllLkRBWT91aCh0LGUscik6ZmgodCxlLHIpfSxkaD0oe3ZhbHVlczp0fSxlLHIpPT57dFtlXT1CaWdJbnQoci8xMDAwKX0saGg9KHt2YWx1ZXM6dH0sZSxyKT0+e3RbZV09QmlnSW50KHIpfSxwaD0oe3ZhbHVlczp0fSxlLHIpPT57dFtlXT1CaWdJbnQocioxMDAwKX0sbWg9KHt2YWx1ZXM6dH0sZSxyKT0+e3RbZV09QmlnSW50KHIqMWU2KX0sSF89KHQsZSxyKT0+e3N3aXRjaCh0LnR5cGUudW5pdCl7Y2FzZSBSLlNFQ09ORDpyZXR1cm4gZGgodCxlLHIpO2Nhc2UgUi5NSUxMSVNFQ09ORDpyZXR1cm4gaGgodCxlLHIpO2Nhc2UgUi5NSUNST1NFQ09ORDpyZXR1cm4gcGgodCxlLHIpO2Nhc2UgUi5OQU5PU0VDT05EOnJldHVybiBtaCh0LGUscil9fSx5aD0oe3ZhbHVlczp0fSxlLHIpPT57dFtlXT1yfSxfaD0oe3ZhbHVlczp0fSxlLHIpPT57dFtlXT1yfSxnaD0oe3ZhbHVlczp0fSxlLHIpPT57dFtlXT1yfSxiaD0oe3ZhbHVlczp0fSxlLHIpPT57dFtlXT1yfSxZXz0odCxlLHIpPT57c3dpdGNoKHQudHlwZS51bml0KXtjYXNlIFIuU0VDT05EOnJldHVybiB5aCh0LGUscik7Y2FzZSBSLk1JTExJU0VDT05EOnJldHVybiBfaCh0LGUscik7Y2FzZSBSLk1JQ1JPU0VDT05EOnJldHVybiBnaCh0LGUscik7Y2FzZSBSLk5BTk9TRUNPTkQ6cmV0dXJuIGJoKHQsZSxyKX19LEtfPSh7dmFsdWVzOnQsc3RyaWRlOmV9LHIsbik9Pnt0LnNldChuLnN1YmFycmF5KDAsZSksZSpyKX0sUUY9KHQsZSxyKT0+e2xldCBuPXQuY2hpbGRyZW5bMF0saT10LnZhbHVlT2Zmc2V0cyxzPV9yLmdldFZpc2l0Rm4obik7aWYoQXJyYXkuaXNBcnJheShyKSlmb3IobGV0IG89LTEsYT1pW2VdLGw9aVtlKzFdO2E8bDspcyhuLGErKyxyWysrb10pO2Vsc2UgZm9yKGxldCBvPS0xLGE9aVtlXSxsPWlbZSsxXTthPGw7KXMobixhKyssci5nZXQoKytvKSl9LHQxPSh0LGUscik9PntsZXQgbj10LmNoaWxkcmVuWzBdLHt2YWx1ZU9mZnNldHM6aX09dCxzPV9yLmdldFZpc2l0Rm4obikse1tlXTpvLFtlKzFdOmF9PWksbD1yIGluc3RhbmNlb2YgTWFwP3IuZW50cmllcygpOk9iamVjdC5lbnRyaWVzKHIpO2ZvcihsZXQgdSBvZiBsKWlmKHMobixvLHUpLCsrbz49YSlicmVha30sZTE9KHQsZSk9PihyLG4saSxzKT0+biYmcihuLHQsZVtzXSkscjE9KHQsZSk9PihyLG4saSxzKT0+biYmcihuLHQsZS5nZXQocykpLG4xPSh0LGUpPT4ocixuLGkscyk9Pm4mJnIobix0LGUuZ2V0KGkubmFtZSkpLGkxPSh0LGUpPT4ocixuLGkscyk9Pm4mJnIobix0LGVbaS5uYW1lXSksczE9KHQsZSxyKT0+e2xldCBuPXQudHlwZS5jaGlsZHJlbi5tYXAoKHMpPT5fci5nZXRWaXNpdEZuKHMudHlwZSkpLGk9ciBpbnN0YW5jZW9mIE1hcD9uMShlLHIpOnIgaW5zdGFuY2VvZiBGP3IxKGUscik6QXJyYXkuaXNBcnJheShyKT9lMShlLHIpOmkxKGUscik7dC50eXBlLmNoaWxkcmVuLmZvckVhY2goKHMsbyk9PmkobltvXSx0LmNoaWxkcmVuW29dLHMsbykpfSxvMT0odCxlLHIpPT57dC50eXBlLm1vZGU9PT1zZS5EZW5zZT9qQih0LGUscik6JEIodCxlLHIpfSxqQj0odCxlLHIpPT57bGV0IG49dC50eXBlLnR5cGVJZFRvQ2hpbGRJbmRleFt0LnR5cGVJZHNbZV1dLGk9dC5jaGlsZHJlbltuXTtfci52aXNpdChpLHQudmFsdWVPZmZzZXRzW2VdLHIpfSwkQj0odCxlLHIpPT57bGV0IG49dC50eXBlLnR5cGVJZFRvQ2hpbGRJbmRleFt0LnR5cGVJZHNbZV1dLGk9dC5jaGlsZHJlbltuXTtfci52aXNpdChpLGUscil9LGExPSh0LGUscik9Pnt2YXIgbjsobj10LmRpY3Rpb25hcnkpPT09bnVsbHx8bj09PXZvaWQgMHx8bi5zZXQodC52YWx1ZXNbZV0scil9LEdfPSh0LGUscik9Pntzd2l0Y2godC50eXBlLnVuaXQpe2Nhc2UgY2UuWUVBUl9NT05USDpyZXR1cm4gdmgodCxlLHIpO2Nhc2UgY2UuREFZX1RJTUU6cmV0dXJuIHdoKHQsZSxyKTtjYXNlIGNlLk1PTlRIX0RBWV9OQU5POnJldHVybiBJaCh0LGUscil9fSx3aD0oe3ZhbHVlczp0fSxlLHIpPT57dC5zZXQoci5zdWJhcnJheSgwLDIpLDIqZSl9LHZoPSh7dmFsdWVzOnR9LGUscik9Pnt0W2VdPXJbMF0qMTIrclsxXSUxMn0sSWg9KHt2YWx1ZXM6dCxzdHJpZGU6ZX0scixuKT0+e3Quc2V0KG4uc3ViYXJyYXkoMCxlKSxlKnIpfSxCaD0oe3ZhbHVlczp0fSxlLHIpPT57dFtlXT1yfSxTaD0oe3ZhbHVlczp0fSxlLHIpPT57dFtlXT1yfSxBaD0oe3ZhbHVlczp0fSxlLHIpPT57dFtlXT1yfSxEaD0oe3ZhbHVlczp0fSxlLHIpPT57dFtlXT1yfSxKXz0odCxlLHIpPT57c3dpdGNoKHQudHlwZS51bml0KXtjYXNlIFIuU0VDT05EOnJldHVybiBCaCh0LGUscik7Y2FzZSBSLk1JTExJU0VDT05EOnJldHVybiBTaCh0LGUscik7Y2FzZSBSLk1JQ1JPU0VDT05EOnJldHVybiBBaCh0LGUscik7Y2FzZSBSLk5BTk9TRUNPTkQ6cmV0dXJuIERoKHQsZSxyKX19LGMxPSh0LGUscik9PntsZXR7c3RyaWRlOm59PXQsaT10LmNoaWxkcmVuWzBdLHM9X3IuZ2V0VmlzaXRGbihpKTtpZihBcnJheS5pc0FycmF5KHIpKWZvcihsZXQgbz0tMSxhPWUqbjsrK288bjspcyhpLGErbyxyW29dKTtlbHNlIGZvcihsZXQgbz0tMSxhPWUqbjsrK288bjspcyhpLGErbyxyLmdldChvKSl9LF9yO3ZhciBSbj1tKCgpPT57bG4oKTtRaSgpO1VzKCk7RHUoKTtDZSgpO2FlKCk7dHQ9Y2xhc3MgdHQgZXh0ZW5kcyBzdHt9O3R0LnByb3RvdHlwZS52aXNpdEJvb2w9dXQoS0YpO3R0LnByb3RvdHlwZS52aXNpdEludD11dChWcyk7dHQucHJvdG90eXBlLnZpc2l0SW50OD11dChWcyk7dHQucHJvdG90eXBlLnZpc2l0SW50MTY9dXQoVnMpO3R0LnByb3RvdHlwZS52aXNpdEludDMyPXV0KFZzKTt0dC5wcm90b3R5cGUudmlzaXRJbnQ2ND11dChWcyk7dHQucHJvdG90eXBlLnZpc2l0VWludDg9dXQoVnMpO3R0LnByb3RvdHlwZS52aXNpdFVpbnQxNj11dChWcyk7dHQucHJvdG90eXBlLnZpc2l0VWludDMyPXV0KFZzKTt0dC5wcm90b3R5cGUudmlzaXRVaW50NjQ9dXQoVnMpO3R0LnByb3RvdHlwZS52aXNpdEZsb2F0PXV0KEdGKTt0dC5wcm90b3R5cGUudmlzaXRGbG9hdDE2PXV0KFBCKTt0dC5wcm90b3R5cGUudmlzaXRGbG9hdDMyPXV0KCRfKTt0dC5wcm90b3R5cGUudmlzaXRGbG9hdDY0PXV0KCRfKTt0dC5wcm90b3R5cGUudmlzaXRVdGY4PXV0KHpCKTt0dC5wcm90b3R5cGUudmlzaXRMYXJnZVV0Zjg9dXQoekIpO3R0LnByb3RvdHlwZS52aXNpdFV0ZjhWaWV3PXV0KFpGKTt0dC5wcm90b3R5cGUudmlzaXRCaW5hcnk9dXQoa0IpO3R0LnByb3RvdHlwZS52aXNpdExhcmdlQmluYXJ5PXV0KGtCKTt0dC5wcm90b3R5cGUudmlzaXRCaW5hcnlWaWV3PXV0KFhGKTt0dC5wcm90b3R5cGUudmlzaXRGaXhlZFNpemVCaW5hcnk9dXQocV8pO3R0LnByb3RvdHlwZS52aXNpdERhdGU9dXQoV18pO3R0LnByb3RvdHlwZS52aXNpdERhdGVEYXk9dXQodWgpO3R0LnByb3RvdHlwZS52aXNpdERhdGVNaWxsaXNlY29uZD11dChmaCk7dHQucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wPXV0KEhfKTt0dC5wcm90b3R5cGUudmlzaXRUaW1lc3RhbXBTZWNvbmQ9dXQoZGgpO3R0LnByb3RvdHlwZS52aXNpdFRpbWVzdGFtcE1pbGxpc2Vjb25kPXV0KGhoKTt0dC5wcm90b3R5cGUudmlzaXRUaW1lc3RhbXBNaWNyb3NlY29uZD11dChwaCk7dHQucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wTmFub3NlY29uZD11dChtaCk7dHQucHJvdG90eXBlLnZpc2l0VGltZT11dChZXyk7dHQucHJvdG90eXBlLnZpc2l0VGltZVNlY29uZD11dCh5aCk7dHQucHJvdG90eXBlLnZpc2l0VGltZU1pbGxpc2Vjb25kPXV0KF9oKTt0dC5wcm90b3R5cGUudmlzaXRUaW1lTWljcm9zZWNvbmQ9dXQoZ2gpO3R0LnByb3RvdHlwZS52aXNpdFRpbWVOYW5vc2Vjb25kPXV0KGJoKTt0dC5wcm90b3R5cGUudmlzaXREZWNpbWFsPXV0KEtfKTt0dC5wcm90b3R5cGUudmlzaXRMaXN0PXV0KFFGKTt0dC5wcm90b3R5cGUudmlzaXRTdHJ1Y3Q9dXQoczEpO3R0LnByb3RvdHlwZS52aXNpdFVuaW9uPXV0KG8xKTt0dC5wcm90b3R5cGUudmlzaXREZW5zZVVuaW9uPXV0KGpCKTt0dC5wcm90b3R5cGUudmlzaXRTcGFyc2VVbmlvbj11dCgkQik7dHQucHJvdG90eXBlLnZpc2l0RGljdGlvbmFyeT11dChhMSk7dHQucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWw9dXQoR18pO3R0LnByb3RvdHlwZS52aXNpdEludGVydmFsRGF5VGltZT11dCh3aCk7dHQucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWxZZWFyTW9udGg9dXQodmgpO3R0LnByb3RvdHlwZS52aXNpdEludGVydmFsTW9udGhEYXlOYW5vPXV0KEloKTt0dC5wcm90b3R5cGUudmlzaXREdXJhdGlvbj11dChKXyk7dHQucHJvdG90eXBlLnZpc2l0RHVyYXRpb25TZWNvbmQ9dXQoQmgpO3R0LnByb3RvdHlwZS52aXNpdER1cmF0aW9uTWlsbGlzZWNvbmQ9dXQoU2gpO3R0LnByb3RvdHlwZS52aXNpdER1cmF0aW9uTWljcm9zZWNvbmQ9dXQoQWgpO3R0LnByb3RvdHlwZS52aXNpdER1cmF0aW9uTmFub3NlY29uZD11dChEaCk7dHQucHJvdG90eXBlLnZpc2l0Rml4ZWRTaXplTGlzdD11dChjMSk7dHQucHJvdG90eXBlLnZpc2l0TWFwPXV0KHQxKTtfcj1uZXcgdHR9KTtjbGFzcyBXQntpc0V4dGVuc2libGUoKXtyZXR1cm4hMX1kZWxldGVQcm9wZXJ0eSgpe3JldHVybiExfXByZXZlbnRFeHRlbnNpb25zKCl7cmV0dXJuITB9b3duS2V5cyh0KXtyZXR1cm4gdFt0c10udHlwZS5jaGlsZHJlbi5tYXAoKGUpPT5lLm5hbWUpfWhhcyh0LGUpe3JldHVybiB0W3RzXS50eXBlLmNoaWxkcmVuLnNvbWUoKHIpPT5yLm5hbWU9PT1lKX1nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodCxlKXtpZih0W3RzXS50eXBlLmNoaWxkcmVuLnNvbWUoKHIpPT5yLm5hbWU9PT1lKSlyZXR1cm57d3JpdGFibGU6ITAsZW51bWVyYWJsZTohMCxjb25maWd1cmFibGU6ITB9O3JldHVybn1nZXQodCxlKXtpZihSZWZsZWN0Lmhhcyh0LGUpKXJldHVybiB0W2VdO2xldCByPXRbdHNdLnR5cGUuY2hpbGRyZW4uZmluZEluZGV4KChuKT0+bi5uYW1lPT09ZSk7aWYociE9PS0xKXtsZXQgbj1QZS52aXNpdCh0W3RzXS5jaGlsZHJlbltyXSx0W0djXSk7cmV0dXJuIFJlZmxlY3Quc2V0KHQsZSxuKSxufX1zZXQodCxlLHIpe2xldCBuPXRbdHNdLnR5cGUuY2hpbGRyZW4uZmluZEluZGV4KChpKT0+aS5uYW1lPT09ZSk7aWYobiE9PS0xKXJldHVybiBfci52aXNpdCh0W3RzXS5jaGlsZHJlbltuXSx0W0djXSxyKSxSZWZsZWN0LnNldCh0LGUscik7ZWxzZSBpZihSZWZsZWN0Lmhhcyh0LGUpfHx0eXBlb2YgZT09PSJzeW1ib2wiKXJldHVybiBSZWZsZWN0LnNldCh0LGUscik7cmV0dXJuITF9fXZhciB0cyxHYyxDYSxxQixsMTt2YXIgWF89bSgoKT0+e1BhKCk7Um4oKTt0cz1TeW1ib2wuZm9yKCJwYXJlbnQiKSxHYz1TeW1ib2wuZm9yKCJyb3dJbmRleCIpO0NhPWNsYXNzIENhe2NvbnN0cnVjdG9yKHQsZSl7cmV0dXJuIHRoaXNbdHNdPXQsdGhpc1tHY109ZSxuZXcgUHJveHkodGhpcyxsMSl9dG9BcnJheSgpe3JldHVybiBPYmplY3QudmFsdWVzKHRoaXMudG9KU09OKCkpfXRvSlNPTigpe2xldCB0PXRoaXNbR2NdLGU9dGhpc1t0c10scj1lLnR5cGUuY2hpbGRyZW4sbj17fTtmb3IobGV0IGk9LTEscz1yLmxlbmd0aDsrK2k8czspbltyW2ldLm5hbWVdPVBlLnZpc2l0KGUuY2hpbGRyZW5baV0sdCk7cmV0dXJuIG59dG9TdHJpbmcoKXtyZXR1cm5geyR7Wy4uLnRoaXNdLm1hcCgoW3QsZV0pPT5gJHtLaSh0KX06ICR7S2koZSl9YCkuam9pbigiLCAiKX19YH1bU3ltYm9sLmZvcigibm9kZWpzLnV0aWwuaW5zcGVjdC5jdXN0b20iKV0oKXtyZXR1cm4gdGhpcy50b1N0cmluZygpfVtTeW1ib2wuaXRlcmF0b3JdKCl7cmV0dXJuIG5ldyBxQih0aGlzW3RzXSx0aGlzW0djXSl9fTtxQj1jbGFzcyBxQntjb25zdHJ1Y3Rvcih0LGUpe3RoaXMuY2hpbGRJbmRleD0wLHRoaXMuY2hpbGRyZW49dC5jaGlsZHJlbix0aGlzLnJvd0luZGV4PWUsdGhpcy5jaGlsZEZpZWxkcz10LnR5cGUuY2hpbGRyZW4sdGhpcy5udW1DaGlsZHJlbj10aGlzLmNoaWxkRmllbGRzLmxlbmd0aH1bU3ltYm9sLml0ZXJhdG9yXSgpe3JldHVybiB0aGlzfW5leHQoKXtsZXQgdD10aGlzLmNoaWxkSW5kZXg7aWYodDx0aGlzLm51bUNoaWxkcmVuKXJldHVybiB0aGlzLmNoaWxkSW5kZXg9dCsxLHtkb25lOiExLHZhbHVlOlt0aGlzLmNoaWxkRmllbGRzW3RdLm5hbWUsUGUudmlzaXQodGhpcy5jaGlsZHJlblt0XSx0aGlzLnJvd0luZGV4KV19O3JldHVybntkb25lOiEwLHZhbHVlOm51bGx9fX07T2JqZWN0LmRlZmluZVByb3BlcnRpZXMoQ2EucHJvdG90eXBlLHtbU3ltYm9sLnRvU3RyaW5nVGFnXTp7ZW51bWVyYWJsZTohMSxjb25maWd1cmFibGU6ITEsdmFsdWU6IlJvdyJ9LFt0c106e3dyaXRhYmxlOiEwLGVudW1lcmFibGU6ITEsY29uZmlndXJhYmxlOiExLHZhbHVlOm51bGx9LFtHY106e3dyaXRhYmxlOiEwLGVudW1lcmFibGU6ITEsY29uZmlndXJhYmxlOiExLHZhbHVlOi0xfX0pO2wxPW5ldyBXQn0pO2Z1bmN0aW9uIG90KHQpe3JldHVybihlLHIpPT5lLmdldFZhbGlkKHIpP3QoZSxyKTpudWxsfXZhciBLLHUxPSh0LGUpPT44NjQwMDAwMCp0W2VdLEpjPTE2LGYxPTEyLGQxPSh0LGUpPT5udWxsLEhCPSh0LGUscik9PntpZihyKzE+PWUubGVuZ3RoKXJldHVybiBudWxsO2xldCBuPVZ0KGVbcl0pLGk9VnQoZVtyKzFdKTtyZXR1cm4gdC5zdWJhcnJheShuLGkpfSxoMT0oe29mZnNldDp0LHZhbHVlczplfSxyKT0+e2xldCBuPXQrcjtyZXR1cm4oZVtuPj4zXSYxPDxuJTgpIT09MH0sWUI9KHt2YWx1ZXM6dH0sZSk9PnUxKHQsZSksS0I9KHt2YWx1ZXM6dH0sZSk9PlZ0KHRbZV0pLFlvPSh7c3RyaWRlOnQsdmFsdWVzOmV9LHIpPT5lW3Qqcl0scDE9KHtzdHJpZGU6dCx2YWx1ZXM6ZX0scik9PmxoKGVbdCpyXSksR0I9KHt2YWx1ZXM6dH0sZSk9PnRbZV0sbTE9KHtzdHJpZGU6dCx2YWx1ZXM6ZX0scik9PmUuc3ViYXJyYXkodCpyLHQqKHIrMSkpLEpCPSh7dmFsdWVzOnQsdmFsdWVPZmZzZXRzOmV9LHIpPT5IQih0LGUsciksWEI9KHQsZSk9Pnt2YXIgcjtsZXQgbj10LnZhbHVlcztpZighbil0aHJvdyBFcnJvcigiQmluYXJ5VmlldyBkYXRhIGlzIG1pc3NpbmcgdmlldyBidWZmZXIiKTtsZXQgaT1lKkpjLHM9aStKYztpZihpPDB8fHM+bi5sZW5ndGgpdGhyb3cgRXJyb3IoYEJpbmFyeVZpZXcgZGF0YSBidWZmZXIgaXMgdG9vIHNob3J0OiBleHBlY3RlZCAke0pjfSBieXRlcywgZ290ICR7TWF0aC5tYXgoMCxuLmxlbmd0aC1pKX1gKTtsZXQgbz1uLnN1YmFycmF5KGkscyk7aWYoby5sZW5ndGg8SmMpdGhyb3cgRXJyb3IoYEJpbmFyeVZpZXcgZGF0YSBidWZmZXIgaXMgdG9vIHNob3J0OiBleHBlY3RlZCAke0pjfSBieXRlcywgZ290ICR7by5sZW5ndGh9YCk7bGV0IGE9bmV3IERhdGFWaWV3KG4uYnVmZmVyLG8uYnl0ZU9mZnNldCxKYyksbD1hLmdldEludDMyKDAsITApO2lmKGw8PTApcmV0dXJuIG5ldyBVaW50OEFycmF5KDApO2lmKGw8PWYxKXJldHVybiBvLnN1YmFycmF5KDQsNCtsKTtsZXQgdT1hLmdldEludDMyKDgsITApLGY9YS5nZXRJbnQzMigxMiwhMCkscD0ocj10LnZhcmlhZGljQnVmZmVycyk9PT1udWxsfHxyPT09dm9pZCAwP3ZvaWQgMDpyW3VdO2lmKCFwKXRocm93IEVycm9yKGBCaW5hcnlWaWV3IHZhcmlhZGljIGJ1ZmZlciAke3V9IGlzIG1pc3NpbmdgKTtyZXR1cm4gcC5zdWJhcnJheShmLGYrbCl9LHkxPSh0LGUpPT5YQih0LGUpLFpCPSh7dmFsdWVzOnQsdmFsdWVPZmZzZXRzOmV9LHIpPT57bGV0IG49SEIodCxlLHIpO3JldHVybiBuIT09bnVsbD96YyhuKTpudWxsfSxfMT0odCxlKT0+e2xldCByPVhCKHQsZSk7cmV0dXJuIHpjKHIpfSxnMT0oe3ZhbHVlczp0fSxlKT0+dFtlXSxiMT0oe3R5cGU6dCx2YWx1ZXM6ZX0scik9PnQucHJlY2lzaW9uIT09cmUuSEFMRj9lW3JdOmxoKGVbcl0pLHcxPSh0LGUpPT50LnR5cGUudW5pdD09PUllLkRBWT9ZQih0LGUpOktCKHQsZSksUUI9KHt2YWx1ZXM6dH0sZSk9PjEwMDAqVnQodFtlXSksdFM9KHt2YWx1ZXM6dH0sZSk9PlZ0KHRbZV0pLGVTPSh7dmFsdWVzOnR9LGUpPT5DXyh0W2VdLEJpZ0ludCgxMDAwKSksclM9KHt2YWx1ZXM6dH0sZSk9PkNfKHRbZV0sQmlnSW50KDFlNikpLHYxPSh0LGUpPT57c3dpdGNoKHQudHlwZS51bml0KXtjYXNlIFIuU0VDT05EOnJldHVybiBRQih0LGUpO2Nhc2UgUi5NSUxMSVNFQ09ORDpyZXR1cm4gdFModCxlKTtjYXNlIFIuTUlDUk9TRUNPTkQ6cmV0dXJuIGVTKHQsZSk7Y2FzZSBSLk5BTk9TRUNPTkQ6cmV0dXJuIHJTKHQsZSl9fSxuUz0oe3ZhbHVlczp0fSxlKT0+dFtlXSxpUz0oe3ZhbHVlczp0fSxlKT0+dFtlXSxzUz0oe3ZhbHVlczp0fSxlKT0+dFtlXSxvUz0oe3ZhbHVlczp0fSxlKT0+dFtlXSxJMT0odCxlKT0+e3N3aXRjaCh0LnR5cGUudW5pdCl7Y2FzZSBSLlNFQ09ORDpyZXR1cm4gblModCxlKTtjYXNlIFIuTUlMTElTRUNPTkQ6cmV0dXJuIGlTKHQsZSk7Y2FzZSBSLk1JQ1JPU0VDT05EOnJldHVybiBzUyh0LGUpO2Nhc2UgUi5OQU5PU0VDT05EOnJldHVybiBvUyh0LGUpfX0sQjE9KHt2YWx1ZXM6dCxzdHJpZGU6ZX0scik9PkJ1LmRlY2ltYWwodC5zdWJhcnJheShlKnIsZSoocisxKSkpLFMxPSh0LGUpPT57bGV0e3ZhbHVlT2Zmc2V0czpyLHN0cmlkZTpuLGNoaWxkcmVuOml9PXQse1tlKm5dOnMsW2UqbisxXTpvfT1yLGw9aVswXS5zbGljZShzLG8tcyk7cmV0dXJuIG5ldyBGKFtsXSl9LEExPSh0LGUpPT57bGV0e3ZhbHVlT2Zmc2V0czpyLGNoaWxkcmVuOm59PXQse1tlXTppLFtlKzFdOnN9PXIsbz1uWzBdO3JldHVybiBuZXcgenMoby5zbGljZShpLHMtaSkpfSxEMT0odCxlKT0+bmV3IENhKHQsZSkseDE9KHQsZSk9PnQudHlwZS5tb2RlPT09c2UuRGVuc2U/YVModCxlKTpjUyh0LGUpLGFTPSh0LGUpPT57bGV0IHI9dC50eXBlLnR5cGVJZFRvQ2hpbGRJbmRleFt0LnR5cGVJZHNbZV1dLG49dC5jaGlsZHJlbltyXTtyZXR1cm4gUGUudmlzaXQobix0LnZhbHVlT2Zmc2V0c1tlXSl9LGNTPSh0LGUpPT57bGV0IHI9dC50eXBlLnR5cGVJZFRvQ2hpbGRJbmRleFt0LnR5cGVJZHNbZV1dLG49dC5jaGlsZHJlbltyXTtyZXR1cm4gUGUudmlzaXQobixlKX0sVDE9KHQsZSk9Pnt2YXIgcjtyZXR1cm4ocj10LmRpY3Rpb25hcnkpPT09bnVsbHx8cj09PXZvaWQgMD92b2lkIDA6ci5nZXQodC52YWx1ZXNbZV0pfSxFMT0odCxlKT0+dC50eXBlLnVuaXQ9PT1jZS5NT05USF9EQVlfTkFOTz9mUyh0LGUpOnQudHlwZS51bml0PT09Y2UuREFZX1RJTUU/bFModCxlKTp1Uyh0LGUpLGxTPSh7dmFsdWVzOnR9LGUpPT50LnN1YmFycmF5KDIqZSwyKihlKzEpKSx1Uz0oe3ZhbHVlczp0fSxlKT0+e2xldCByPXRbZV0sbj1uZXcgSW50MzJBcnJheSgyKTtyZXR1cm4gblswXT1NYXRoLnRydW5jKHIvMTIpLG5bMV09TWF0aC50cnVuYyhyJTEyKSxufSxmUz0oe3ZhbHVlczp0fSxlKT0+dC5zdWJhcnJheSg0KmUsNCooZSsxKSksZFM9KHt2YWx1ZXM6dH0sZSk9PnRbZV0saFM9KHt2YWx1ZXM6dH0sZSk9PnRbZV0scFM9KHt2YWx1ZXM6dH0sZSk9PnRbZV0sbVM9KHt2YWx1ZXM6dH0sZSk9PnRbZV0sTzE9KHQsZSk9Pntzd2l0Y2godC50eXBlLnVuaXQpe2Nhc2UgUi5TRUNPTkQ6cmV0dXJuIGRTKHQsZSk7Y2FzZSBSLk1JTExJU0VDT05EOnJldHVybiBoUyh0LGUpO2Nhc2UgUi5NSUNST1NFQ09ORDpyZXR1cm4gcFModCxlKTtjYXNlIFIuTkFOT1NFQ09ORDpyZXR1cm4gbVModCxlKX19LE4xPSh0LGUpPT57bGV0e3N0cmlkZTpyLGNoaWxkcmVuOm59PXQscz1uWzBdLnNsaWNlKGUqcixyKTtyZXR1cm4gbmV3IEYoW3NdKX0sUGU7dmFyIFBhPW0oKCk9Pnt6XygpO2xuKCk7UWkoKTt4aCgpO1hfKCk7VXMoKTtEdSgpO0NlKCk7Sz1jbGFzcyBLIGV4dGVuZHMgc3R7fTtLLnByb3RvdHlwZS52aXNpdE51bGw9b3QoZDEpO0sucHJvdG90eXBlLnZpc2l0Qm9vbD1vdChoMSk7Sy5wcm90b3R5cGUudmlzaXRJbnQ9b3QoZzEpO0sucHJvdG90eXBlLnZpc2l0SW50OD1vdChZbyk7Sy5wcm90b3R5cGUudmlzaXRJbnQxNj1vdChZbyk7Sy5wcm90b3R5cGUudmlzaXRJbnQzMj1vdChZbyk7Sy5wcm90b3R5cGUudmlzaXRJbnQ2ND1vdChHQik7Sy5wcm90b3R5cGUudmlzaXRVaW50OD1vdChZbyk7Sy5wcm90b3R5cGUudmlzaXRVaW50MTY9b3QoWW8pO0sucHJvdG90eXBlLnZpc2l0VWludDMyPW90KFlvKTtLLnByb3RvdHlwZS52aXNpdFVpbnQ2ND1vdChHQik7Sy5wcm90b3R5cGUudmlzaXRGbG9hdD1vdChiMSk7Sy5wcm90b3R5cGUudmlzaXRGbG9hdDE2PW90KHAxKTtLLnByb3RvdHlwZS52aXNpdEZsb2F0MzI9b3QoWW8pO0sucHJvdG90eXBlLnZpc2l0RmxvYXQ2ND1vdChZbyk7Sy5wcm90b3R5cGUudmlzaXRVdGY4PW90KFpCKTtLLnByb3RvdHlwZS52aXNpdExhcmdlVXRmOD1vdChaQik7Sy5wcm90b3R5cGUudmlzaXRVdGY4Vmlldz1vdChfMSk7Sy5wcm90b3R5cGUudmlzaXRCaW5hcnk9b3QoSkIpO0sucHJvdG90eXBlLnZpc2l0TGFyZ2VCaW5hcnk9b3QoSkIpO0sucHJvdG90eXBlLnZpc2l0QmluYXJ5Vmlldz1vdCh5MSk7Sy5wcm90b3R5cGUudmlzaXRGaXhlZFNpemVCaW5hcnk9b3QobTEpO0sucHJvdG90eXBlLnZpc2l0RGF0ZT1vdCh3MSk7Sy5wcm90b3R5cGUudmlzaXREYXRlRGF5PW90KFlCKTtLLnByb3RvdHlwZS52aXNpdERhdGVNaWxsaXNlY29uZD1vdChLQik7Sy5wcm90b3R5cGUudmlzaXRUaW1lc3RhbXA9b3QodjEpO0sucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wU2Vjb25kPW90KFFCKTtLLnByb3RvdHlwZS52aXNpdFRpbWVzdGFtcE1pbGxpc2Vjb25kPW90KHRTKTtLLnByb3RvdHlwZS52aXNpdFRpbWVzdGFtcE1pY3Jvc2Vjb25kPW90KGVTKTtLLnByb3RvdHlwZS52aXNpdFRpbWVzdGFtcE5hbm9zZWNvbmQ9b3QoclMpO0sucHJvdG90eXBlLnZpc2l0VGltZT1vdChJMSk7Sy5wcm90b3R5cGUudmlzaXRUaW1lU2Vjb25kPW90KG5TKTtLLnByb3RvdHlwZS52aXNpdFRpbWVNaWxsaXNlY29uZD1vdChpUyk7Sy5wcm90b3R5cGUudmlzaXRUaW1lTWljcm9zZWNvbmQ9b3Qoc1MpO0sucHJvdG90eXBlLnZpc2l0VGltZU5hbm9zZWNvbmQ9b3Qob1MpO0sucHJvdG90eXBlLnZpc2l0RGVjaW1hbD1vdChCMSk7Sy5wcm90b3R5cGUudmlzaXRMaXN0PW90KFMxKTtLLnByb3RvdHlwZS52aXNpdFN0cnVjdD1vdChEMSk7Sy5wcm90b3R5cGUudmlzaXRVbmlvbj1vdCh4MSk7Sy5wcm90b3R5cGUudmlzaXREZW5zZVVuaW9uPW90KGFTKTtLLnByb3RvdHlwZS52aXNpdFNwYXJzZVVuaW9uPW90KGNTKTtLLnByb3RvdHlwZS52aXNpdERpY3Rpb25hcnk9b3QoVDEpO0sucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWw9b3QoRTEpO0sucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWxEYXlUaW1lPW90KGxTKTtLLnByb3RvdHlwZS52aXNpdEludGVydmFsWWVhck1vbnRoPW90KHVTKTtLLnByb3RvdHlwZS52aXNpdEludGVydmFsTW9udGhEYXlOYW5vPW90KGZTKTtLLnByb3RvdHlwZS52aXNpdER1cmF0aW9uPW90KE8xKTtLLnByb3RvdHlwZS52aXNpdER1cmF0aW9uU2Vjb25kPW90KGRTKTtLLnByb3RvdHlwZS52aXNpdER1cmF0aW9uTWlsbGlzZWNvbmQ9b3QoaFMpO0sucHJvdG90eXBlLnZpc2l0RHVyYXRpb25NaWNyb3NlY29uZD1vdChwUyk7Sy5wcm90b3R5cGUudmlzaXREdXJhdGlvbk5hbm9zZWNvbmQ9b3QobVMpO0sucHJvdG90eXBlLnZpc2l0Rml4ZWRTaXplTGlzdD1vdChOMSk7Sy5wcm90b3R5cGUudmlzaXRNYXA9b3QoQTEpO1BlPW5ldyBLfSk7Y2xhc3MgX1N7aXNFeHRlbnNpYmxlKCl7cmV0dXJuITF9ZGVsZXRlUHJvcGVydHkoKXtyZXR1cm4hMX1wcmV2ZW50RXh0ZW5zaW9ucygpe3JldHVybiEwfW93bktleXModCl7cmV0dXJuIHRbWGNdfWhhcyh0LGUpe3JldHVybiB0W1hjXS5pbmNsdWRlcyhlKX1nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodCxlKXtpZih0W1hjXS5pbmRleE9mKGUpIT09LTEpcmV0dXJue3dyaXRhYmxlOiEwLGVudW1lcmFibGU6ITAsY29uZmlndXJhYmxlOiEwfTtyZXR1cm59Z2V0KHQsZSl7aWYoUmVmbGVjdC5oYXModCxlKSlyZXR1cm4gdFtlXTtsZXQgcj10W1hjXS5pbmRleE9mKGUpO2lmKHIhPT0tMSl7bGV0IG49UGUudmlzaXQoUmVmbGVjdC5nZXQodCxaYykscik7cmV0dXJuIFJlZmxlY3Quc2V0KHQsZSxuKSxufX1zZXQodCxlLHIpe2xldCBuPXRbWGNdLmluZGV4T2YoZSk7aWYobiE9PS0xKXJldHVybiBfci52aXNpdChSZWZsZWN0LmdldCh0LFpjKSxuLHIpLFJlZmxlY3Quc2V0KHQsZSxyKTtlbHNlIGlmKFJlZmxlY3QuaGFzKHQsZSkpcmV0dXJuIFJlZmxlY3Quc2V0KHQsZSxyKTtyZXR1cm4hMX19dmFyIEtvLFpjLFhjLFpfLHpzLHlTO3ZhciB4aD1tKCgpPT57bG4oKTtQYSgpO1JuKCk7S289U3ltYm9sLmZvcigia2V5cyIpLFpjPVN5bWJvbC5mb3IoInZhbHMiKSxYYz1TeW1ib2wuZm9yKCJrS2V5c0FzU3RyaW5ncyIpLFpfPVN5bWJvbC5mb3IoIl9rS2V5c0FzU3RyaW5ncyIpO3pzPWNsYXNzIHpze2NvbnN0cnVjdG9yKHQpe3JldHVybiB0aGlzW0tvXT1uZXcgRihbdC5jaGlsZHJlblswXV0pLm1lbW9pemUoKSx0aGlzW1pjXT10LmNoaWxkcmVuWzFdLG5ldyBQcm94eSh0aGlzLG5ldyBfUyl9Z2V0W1hjXSgpe3JldHVybiB0aGlzW1pfXXx8KHRoaXNbWl9dPUFycmF5LmZyb20odGhpc1tLb10udG9BcnJheSgpLFN0cmluZykpfVtTeW1ib2wuaXRlcmF0b3JdKCl7cmV0dXJuIG5ldyB5Uyh0aGlzW0tvXSx0aGlzW1pjXSl9Z2V0IHNpemUoKXtyZXR1cm4gdGhpc1tLb10ubGVuZ3RofXRvQXJyYXkoKXtyZXR1cm4gT2JqZWN0LnZhbHVlcyh0aGlzLnRvSlNPTigpKX10b0pTT04oKXtsZXQgdD10aGlzW0tvXSxlPXRoaXNbWmNdLHI9e307Zm9yKGxldCBuPS0xLGk9dC5sZW5ndGg7KytuPGk7KXJbdC5nZXQobildPVBlLnZpc2l0KGUsbik7cmV0dXJuIHJ9dG9TdHJpbmcoKXtyZXR1cm5geyR7Wy4uLnRoaXNdLm1hcCgoW3QsZV0pPT5gJHtLaSh0KX06ICR7S2koZSl9YCkuam9pbigiLCAiKX19YH1bU3ltYm9sLmZvcigibm9kZWpzLnV0aWwuaW5zcGVjdC5jdXN0b20iKV0oKXtyZXR1cm4gdGhpcy50b1N0cmluZygpfX07eVM9Y2xhc3MgeVN7Y29uc3RydWN0b3IodCxlKXt0aGlzLmtleXM9dCx0aGlzLnZhbHM9ZSx0aGlzLmtleUluZGV4PTAsdGhpcy5udW1LZXlzPXQubGVuZ3RofVtTeW1ib2wuaXRlcmF0b3JdKCl7cmV0dXJuIHRoaXN9bmV4dCgpe2xldCB0PXRoaXMua2V5SW5kZXg7aWYodD09PXRoaXMubnVtS2V5cylyZXR1cm57ZG9uZTohMCx2YWx1ZTpudWxsfTtyZXR1cm4gdGhpcy5rZXlJbmRleCsrLHtkb25lOiExLHZhbHVlOlt0aGlzLmtleXMuZ2V0KHQpLFBlLnZpc2l0KHRoaXMudmFscyx0KV19fX07T2JqZWN0LmRlZmluZVByb3BlcnRpZXMoenMucHJvdG90eXBlLHtbU3ltYm9sLnRvU3RyaW5nVGFnXTp7ZW51bWVyYWJsZTohMSxjb25maWd1cmFibGU6ITEsdmFsdWU6IlJvdyJ9LFtLb106e3dyaXRhYmxlOiEwLGVudW1lcmFibGU6ITEsY29uZmlndXJhYmxlOiExLHZhbHVlOm51bGx9LFtaY106e3dyaXRhYmxlOiEwLGVudW1lcmFibGU6ITEsY29uZmlndXJhYmxlOiExLHZhbHVlOm51bGx9LFtaX106e3dyaXRhYmxlOiEwLGVudW1lcmFibGU6ITEsY29uZmlndXJhYmxlOiExLHZhbHVlOm51bGx9fSl9KTt2YXIgUV89e307WmUoUV8se2NsYW1wUmFuZ2U6KCk9Pnh1LGNyZWF0ZUVsZW1lbnRDb21wYXJhdG9yOigpPT5Hbyx3cmFwSW5kZXg6KCk9PmthfSk7ZnVuY3Rpb24geHUodCxlLHIsbil7bGV0e2xlbmd0aDppPTB9PXQscz10eXBlb2YgZSE9PSJudW1iZXIiPzA6ZSxvPXR5cGVvZiByIT09Im51bWJlciI/aTpyO3JldHVybiBzPDAmJihzPShzJWkraSklaSksbzwwJiYobz0obyVpK2kpJWkpLG88cyYmKGdTPXMscz1vLG89Z1MpLG8+aSYmKG89aSksbj9uKHQscyxvKTpbcyxvXX1mdW5jdGlvbiBHbyh0KXtpZih0eXBlb2YgdCE9PSJvYmplY3QifHx0PT09bnVsbCl7aWYoYlModCkpcmV0dXJuIGJTO3JldHVybihyKT0+cj09PXR9aWYodCBpbnN0YW5jZW9mIERhdGUpe2xldCByPXQudmFsdWVPZigpO3JldHVybihuKT0+biBpbnN0YW5jZW9mIERhdGU/bi52YWx1ZU9mKCk9PT1yOiExfWlmKEFycmF5QnVmZmVyLmlzVmlldyh0KSlyZXR1cm4ocik9PnI/b18odCxyKTohMTtpZih0IGluc3RhbmNlb2YgTWFwKXJldHVybiBNMSh0KTtpZihBcnJheS5pc0FycmF5KHQpKXJldHVybiBGMSh0KTtpZih0IGluc3RhbmNlb2YgRilyZXR1cm4gTDEodCk7cmV0dXJuIFUxKHQsITApfWZ1bmN0aW9uIEYxKHQpe2xldCBlPVtdO2ZvcihsZXQgcj0tMSxuPXQubGVuZ3RoOysrcjxuOyllW3JdPUdvKHRbcl0pO3JldHVybiBUaChlKX1mdW5jdGlvbiBNMSh0KXtsZXQgZT0tMSxyPVtdO2ZvcihsZXQgbiBvZiB0LnZhbHVlcygpKXJbKytlXT1HbyhuKTtyZXR1cm4gVGgocil9ZnVuY3Rpb24gTDEodCl7bGV0IGU9W107Zm9yKGxldCByPS0xLG49dC5sZW5ndGg7KytyPG47KWVbcl09R28odC5nZXQocikpO3JldHVybiBUaChlKX1mdW5jdGlvbiBVMSh0LGU9ITEpe2xldCByPU9iamVjdC5rZXlzKHQpO2lmKCFlJiZyLmxlbmd0aD09PTApcmV0dXJuKCk9PiExO2xldCBuPVtdO2ZvcihsZXQgaT0tMSxzPXIubGVuZ3RoOysraTxzOyluW2ldPUdvKHRbcltpXV0pO3JldHVybiBUaChuLHIpfWZ1bmN0aW9uIFRoKHQsZSl7cmV0dXJuKHIpPT57aWYoIXJ8fHR5cGVvZiByIT09Im9iamVjdCIpcmV0dXJuITE7c3dpdGNoKHIuY29uc3RydWN0b3Ipe2Nhc2UgQXJyYXk6cmV0dXJuIFIxKHQscik7Y2FzZSBNYXA6cmV0dXJuIHdTKHQscixyLmtleXMoKSk7Y2FzZSB6czpjYXNlIENhOmNhc2UgT2JqZWN0OmNhc2Ugdm9pZCAwOnJldHVybiB3Uyh0LHIsZXx8T2JqZWN0LmtleXMocikpfXJldHVybiByIGluc3RhbmNlb2YgRj9DMSh0LHIpOiExfX1mdW5jdGlvbiBSMSh0LGUpe2xldCByPXQubGVuZ3RoO2lmKGUubGVuZ3RoIT09cilyZXR1cm4hMTtmb3IobGV0IG49LTE7KytuPHI7KWlmKCF0W25dKGVbbl0pKXJldHVybiExO3JldHVybiEwfWZ1bmN0aW9uIEMxKHQsZSl7bGV0IHI9dC5sZW5ndGg7aWYoZS5sZW5ndGghPT1yKXJldHVybiExO2ZvcihsZXQgbj0tMTsrK248cjspaWYoIXRbbl0oZS5nZXQobikpKXJldHVybiExO3JldHVybiEwfWZ1bmN0aW9uIHdTKHQsZSxyKXtsZXQgbj1yW1N5bWJvbC5pdGVyYXRvcl0oKSxpPWUgaW5zdGFuY2VvZiBNYXA/ZS5rZXlzKCk6T2JqZWN0LmtleXMoZSlbU3ltYm9sLml0ZXJhdG9yXSgpLHM9ZSBpbnN0YW5jZW9mIE1hcD9lLnZhbHVlcygpOk9iamVjdC52YWx1ZXMoZSlbU3ltYm9sLml0ZXJhdG9yXSgpLG89MCxhPXQubGVuZ3RoLGw9cy5uZXh0KCksdT1uLm5leHQoKSxmPWkubmV4dCgpO2Zvcig7bzxhJiYhdS5kb25lJiYhZi5kb25lJiYhbC5kb25lOysrbyx1PW4ubmV4dCgpLGY9aS5uZXh0KCksbD1zLm5leHQoKSlpZih1LnZhbHVlIT09Zi52YWx1ZXx8IXRbb10obC52YWx1ZSkpYnJlYWs7aWYobz09PWEmJnUuZG9uZSYmZi5kb25lJiZsLmRvbmUpcmV0dXJuITA7cmV0dXJuIG4ucmV0dXJuJiZuLnJldHVybigpLGkucmV0dXJuJiZpLnJldHVybigpLHMucmV0dXJuJiZzLnJldHVybigpLCExfXZhciBnUyxrYT0odCxlKT0+dDwwP2UrdDp0LGJTPSh0KT0+dCE9PXQ7dmFyIFFjPW0oKCk9PntsbigpO3hoKCk7WF8oKTtZZSgpfSk7dmFyIHRnPXt9O1plKHRnLHtCaXRJdGVyYXRvcjooKT0+dGwsZ2V0Qml0OigpPT52UyxnZXRCb29sOigpPT5PaCxwYWNrQm9vbHM6KCk9PnphLHBvcGNudF9hcnJheTooKT0+SVMscG9wY250X2JpdF9yYW5nZTooKT0+VHUscG9wY250X3VpbnQzMjooKT0+RWgsc2V0Qm9vbDooKT0+UDEsdHJ1bmNhdGVCaXRtYXA6KCk9PlZhfSk7ZnVuY3Rpb24gT2godCxlLHIsbil7cmV0dXJuKHImMTw8bikhPT0wfWZ1bmN0aW9uIHZTKHQsZSxyLG4pe3JldHVybihyJjE8PG4pPj5ufWZ1bmN0aW9uIFAxKHQsZSxyKXtyZXR1cm4gcj8hISh0W2U+PjNdfD0xPDxlJTgpfHwhMDohKHRbZT4+M10mPX4oMTw8ZSU4KSkmJiExfWZ1bmN0aW9uIFZhKHQsZSxyKXtsZXQgbj1yLmJ5dGVMZW5ndGgrNyYtODtpZih0PjB8fHIuYnl0ZUxlbmd0aDxuKXtsZXQgaT1uZXcgVWludDhBcnJheShuKTtyZXR1cm4gaS5zZXQodCU4PT09MD9yLnN1YmFycmF5KHQ+PjMpOnphKG5ldyB0bChyLHQsZSxudWxsLE9oKSkuc3ViYXJyYXkoMCxuKSksaX1yZXR1cm4gcn1mdW5jdGlvbiB6YSh0KXtsZXQgZT1bXSxyPTAsbj0wLGk9MDtmb3IobGV0IG8gb2YgdClpZihvJiYoaXw9MTw8biksKytuPT09OCllW3IrK109aSxpPW49MDtpZihyPT09MHx8bj4wKWVbcisrXT1pO2xldCBzPW5ldyBVaW50OEFycmF5KGUubGVuZ3RoKzcmLTgpO3JldHVybiBzLnNldChlKSxzfWZ1bmN0aW9uIFR1KHQsZSxyKXtpZihyLWU8PTApcmV0dXJuIDA7aWYoci1lPDgpe2xldCBzPTA7Zm9yKGxldCBvIG9mIG5ldyB0bCh0LGUsci1lLHQsdlMpKXMrPW87cmV0dXJuIHN9bGV0IG49cj4+Mzw8MyxpPWUrKGUlOD09PTA/MDo4LWUlOCk7cmV0dXJuIFR1KHQsZSxpKStUdSh0LG4scikrSVModCxpPj4zLG4taT4+Myl9ZnVuY3Rpb24gSVModCxlLHIpe2xldCBuPTAsaT1NYXRoLnRydW5jKGUpLHM9bmV3IERhdGFWaWV3KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCx0LmJ5dGVMZW5ndGgpLG89cj09PXZvaWQgMD90LmJ5dGVMZW5ndGg6aStyO3doaWxlKG8taT49NCluKz1FaChzLmdldFVpbnQzMihpKSksaSs9NDt3aGlsZShvLWk+PTIpbis9RWgocy5nZXRVaW50MTYoaSkpLGkrPTI7d2hpbGUoby1pPj0xKW4rPUVoKHMuZ2V0VWludDgoaSkpLGkrPTE7cmV0dXJuIG59ZnVuY3Rpb24gRWgodCl7bGV0IGU9TWF0aC50cnVuYyh0KTtyZXR1cm4gZT1lLShlPj4+MSYxNDMxNjU1NzY1KSxlPShlJjg1ODk5MzQ1OSkrKGU+Pj4yJjg1ODk5MzQ1OSksKGUrKGU+Pj40KSYyNTI2NDUxMzUpKjE2ODQzMDA5Pj4+MjR9dmFyIHRsO3ZhciBlbD1tKCgpPT57dGw9Y2xhc3MgdGx7Y29uc3RydWN0b3IodCxlLHIsbixpKXt0aGlzLmJ5dGVzPXQsdGhpcy5sZW5ndGg9cix0aGlzLmNvbnRleHQ9bix0aGlzLmdldD1pLHRoaXMuYml0PWUlOCx0aGlzLmJ5dGVJbmRleD1lPj4zLHRoaXMuYnl0ZT10W3RoaXMuYnl0ZUluZGV4KytdLHRoaXMuaW5kZXg9MH1uZXh0KCl7aWYodGhpcy5pbmRleDx0aGlzLmxlbmd0aCl7aWYodGhpcy5iaXQ9PT04KXRoaXMuYml0PTAsdGhpcy5ieXRlPXRoaXMuYnl0ZXNbdGhpcy5ieXRlSW5kZXgrK107cmV0dXJue3ZhbHVlOnRoaXMuZ2V0KHRoaXMuY29udGV4dCx0aGlzLmluZGV4KyssdGhpcy5ieXRlLHRoaXMuYml0KyspfX1yZXR1cm57ZG9uZTohMCx2YWx1ZTpudWxsfX1bU3ltYm9sLml0ZXJhdG9yXSgpe3JldHVybiB0aGlzfX19KTtjbGFzcyBodHtzdGF0aWMgaXNEYXRhKHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dFtCU10pPT09ITB9Z2V0IHR5cGVJZCgpe3JldHVybiB0aGlzLnR5cGUudHlwZUlkfWdldCBBcnJheVR5cGUoKXtyZXR1cm4gdGhpcy50eXBlLkFycmF5VHlwZX1nZXQgYnVmZmVycygpe3JldHVyblt0aGlzLnZhbHVlT2Zmc2V0cyx0aGlzLnZhbHVlcyx0aGlzLm51bGxCaXRtYXAsdGhpcy50eXBlSWRzXX1nZXQgbnVsbGFibGUoKXtpZih0aGlzLl9udWxsQ291bnQhPT0wKXtsZXR7dHlwZTp0fT10aGlzO2lmKEEuaXNTcGFyc2VVbmlvbih0KSlyZXR1cm4gdGhpcy5jaGlsZHJlbi5zb21lKChlKT0+ZS5udWxsYWJsZSk7ZWxzZSBpZihBLmlzRGVuc2VVbmlvbih0KSlyZXR1cm4gdGhpcy5jaGlsZHJlbi5zb21lKChlKT0+ZS5udWxsYWJsZSk7cmV0dXJuIHRoaXMubnVsbEJpdG1hcCYmdGhpcy5udWxsQml0bWFwLmJ5dGVMZW5ndGg+MH1yZXR1cm4hMH1nZXQgYnl0ZUxlbmd0aCgpe2xldCB0PTAse3ZhbHVlT2Zmc2V0czplLHZhbHVlczpyLG51bGxCaXRtYXA6bix0eXBlSWRzOml9PXRoaXM7cmV0dXJuIGUmJih0Kz1lLmJ5dGVMZW5ndGgpLHImJih0Kz1yLmJ5dGVMZW5ndGgpLG4mJih0Kz1uLmJ5dGVMZW5ndGgpLGkmJih0Kz1pLmJ5dGVMZW5ndGgpLHQrPXRoaXMudmFyaWFkaWNCdWZmZXJzLnJlZHVjZSgocyxvKT0+e3ZhciBhO3JldHVybiBzKygoYT1vPT09bnVsbHx8bz09PXZvaWQgMD92b2lkIDA6by5ieXRlTGVuZ3RoKSE9PW51bGwmJmEhPT12b2lkIDA/YTowKX0sMCksdGhpcy5jaGlsZHJlbi5yZWR1Y2UoKHMsbyk9PnMrby5ieXRlTGVuZ3RoLHQpfWdldCBudWxsQ291bnQoKXtpZihBLmlzVW5pb24odGhpcy50eXBlKSlyZXR1cm4gdGhpcy5jaGlsZHJlbi5yZWR1Y2UoKHIsbik9PnIrbi5udWxsQ291bnQsMCk7bGV0IHQ9dGhpcy5fbnVsbENvdW50LGU7aWYodDw9azEmJihlPXRoaXMubnVsbEJpdG1hcCkpdGhpcy5fbnVsbENvdW50PXQ9ZS5sZW5ndGg9PT0wPzA6dGhpcy5sZW5ndGgtVHUoZSx0aGlzLm9mZnNldCx0aGlzLm9mZnNldCt0aGlzLmxlbmd0aCk7cmV0dXJuIHR9Y29uc3RydWN0b3IodCxlLHIsbixpLHM9W10sbyxhPVtdKXt2YXIgbDt0aGlzLnR5cGU9dCx0aGlzLmNoaWxkcmVuPXMsdGhpcy5kaWN0aW9uYXJ5PW8sdGhpcy5vZmZzZXQ9TWF0aC5mbG9vcihNYXRoLm1heChlfHwwLDApKSx0aGlzLmxlbmd0aD1NYXRoLmZsb29yKE1hdGgubWF4KHJ8fDAsMCkpLHRoaXMuX251bGxDb3VudD1NYXRoLmZsb29yKE1hdGgubWF4KG58fDAsLTEpKTtsZXQgdTtpZihpIGluc3RhbmNlb2YgaHQpdGhpcy5zdHJpZGU9aS5zdHJpZGUsdGhpcy52YWx1ZXM9aS52YWx1ZXMsdGhpcy50eXBlSWRzPWkudHlwZUlkcyx0aGlzLm51bGxCaXRtYXA9aS5udWxsQml0bWFwLHRoaXMudmFsdWVPZmZzZXRzPWkudmFsdWVPZmZzZXRzLHRoaXMudmFyaWFkaWNCdWZmZXJzPWkudmFyaWFkaWNCdWZmZXJzO2Vsc2V7aWYodGhpcy5zdHJpZGU9VW4odCksaSkodT1pWzBdKSYmKHRoaXMudmFsdWVPZmZzZXRzPXUpLCh1PWlbMV0pJiYodGhpcy52YWx1ZXM9dSksKHU9aVsyXSkmJih0aGlzLm51bGxCaXRtYXA9dSksKHU9aVszXSkmJih0aGlzLnR5cGVJZHM9dSk7dGhpcy52YXJpYWRpY0J1ZmZlcnM9YX0obD10aGlzLnZhcmlhZGljQnVmZmVycykhPT1udWxsJiZsIT09dm9pZCAwfHwodGhpcy52YXJpYWRpY0J1ZmZlcnM9W10pfWdldFZhbGlkKHQpe2xldHt0eXBlOmV9PXRoaXM7aWYoQS5pc1VuaW9uKGUpKXtsZXQgcj1lLG49dGhpcy50eXBlSWRzW3RdLGk9ci50eXBlSWRUb0NoaWxkSW5kZXhbbl0scz10aGlzLmNoaWxkcmVuW2ldLG89dGhpcy52YWx1ZU9mZnNldHMsYT1yLm1vZGU9PT1zZS5EZW5zZSYmbz9OdW1iZXIob1t0XSk6dDtyZXR1cm4gcy5nZXRWYWxpZChhKX1pZih0aGlzLm51bGxhYmxlJiZ0aGlzLm51bGxDb3VudD4wKXtsZXQgcj10aGlzLm9mZnNldCt0O3JldHVybih0aGlzLm51bGxCaXRtYXBbcj4+M10mMTw8ciU4KSE9PTB9cmV0dXJuITB9c2V0VmFsaWQodCxlKXtsZXQgcix7dHlwZTpufT10aGlzO2lmKEEuaXNVbmlvbihuKSl7bGV0IGk9bixzPXRoaXMudHlwZUlkc1t0XSxvPWkudHlwZUlkVG9DaGlsZEluZGV4W3NdLGE9dGhpcy5jaGlsZHJlbltvXSxsPXRoaXMudmFsdWVPZmZzZXRzLHU9aS5tb2RlPT09c2UuRGVuc2UmJmw/TnVtYmVyKGxbdF0pOnQ7cj1hLmdldFZhbGlkKHUpLGEuc2V0VmFsaWQodSxlKX1lbHNle2xldHtudWxsQml0bWFwOml9PXRoaXMse29mZnNldDpzLGxlbmd0aDpvfT10aGlzLGE9cyt0LGw9MTw8YSU4LHU9YT4+MztpZighaXx8aS5ieXRlTGVuZ3RoPD11KWlmKGk9bmV3IFVpbnQ4QXJyYXkoKHMrbys2MyYtNjQpPj4zKS5maWxsKDI1NSksdGhpcy5udWxsQ291bnQ+MClpLnNldChWYShzLG8sdGhpcy5udWxsQml0bWFwKSwwKSxPYmplY3QuYXNzaWduKHRoaXMse251bGxCaXRtYXA6aX0pO2Vsc2UgT2JqZWN0LmFzc2lnbih0aGlzLHtudWxsQml0bWFwOmksX251bGxDb3VudDowfSk7bGV0IGY9aVt1XTtyPShmJmwpIT09MCxpW3VdPWU/ZnxsOmYmfmx9aWYociE9PSEhZSl0aGlzLl9udWxsQ291bnQ9dGhpcy5udWxsQ291bnQrKGU/LTE6MSk7cmV0dXJuIGV9Y2xvbmUodD10aGlzLnR5cGUsZT10aGlzLm9mZnNldCxyPXRoaXMubGVuZ3RoLG49dGhpcy5fbnVsbENvdW50LGk9dGhpcyxzPXRoaXMuY2hpbGRyZW4sbz10aGlzLnZhcmlhZGljQnVmZmVycyl7cmV0dXJuIG5ldyBodCh0LGUscixuLGkscyx0aGlzLmRpY3Rpb25hcnksbyl9c2xpY2UodCxlKXtsZXR7c3RyaWRlOnIsdHlwZUlkOm4sY2hpbGRyZW46aX09dGhpcyxzPSsodGhpcy5fbnVsbENvdW50PT09MCktMSxvPW49PT0xNj9yOjEsYT10aGlzLl9zbGljZUJ1ZmZlcnModCxlLHIsbik7cmV0dXJuIHRoaXMuY2xvbmUodGhpcy50eXBlLHRoaXMub2Zmc2V0K3QsZSxzLGEsaS5sZW5ndGg9PT0wfHx0aGlzLnZhbHVlT2Zmc2V0cz9pOnRoaXMuX3NsaWNlQ2hpbGRyZW4oaSxvKnQsbyplKSx0aGlzLnZhcmlhZGljQnVmZmVycyl9X2NoYW5nZUxlbmd0aEFuZEJhY2tmaWxsTnVsbEJpdG1hcCh0KXtpZih0aGlzLnR5cGVJZD09PXkuTnVsbClyZXR1cm4gdGhpcy5jbG9uZSh0aGlzLnR5cGUsMCx0LDAsdGhpcy5idWZmZXJzLHRoaXMuY2hpbGRyZW4sdGhpcy52YXJpYWRpY0J1ZmZlcnMpO2xldHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcyxuPW5ldyBVaW50OEFycmF5KCh0KzYzJi02NCk+PjMpLmZpbGwoMjU1LDAsZT4+Myk7aWYobltlPj4zXT0oMTw8ZS0oZSYtOCkpLTEscj4wKW4uc2V0KFZhKHRoaXMub2Zmc2V0LGUsdGhpcy5udWxsQml0bWFwKSwwKTtsZXQgaT10aGlzLmJ1ZmZlcnM7cmV0dXJuIGlbc24uVkFMSURJVFldPW4sdGhpcy5jbG9uZSh0aGlzLnR5cGUsMCx0LHIrKHQtZSksaSx0aGlzLmNoaWxkcmVuLHRoaXMudmFyaWFkaWNCdWZmZXJzKX1fc2xpY2VCdWZmZXJzKHQsZSxyLG4pe2xldCBpLHtidWZmZXJzOnN9PXRoaXM7aWYoKGk9c1tzbi5UWVBFXSkmJihzW3NuLlRZUEVdPWkuc3ViYXJyYXkodCx0K2UpKSxBLmlzQmluYXJ5Vmlldyh0aGlzLnR5cGUpfHxBLmlzVXRmOFZpZXcodGhpcy50eXBlKSl7bGV0IG89YnQuRUxFTUVOVF9XSURUSDsoaT1zW3NuLkRBVEFdKSYmKHNbc24uREFUQV09aS5zdWJhcnJheSh0Km8sKHQrZSkqbykpfWVsc2UoaT1zW3NuLk9GRlNFVF0pJiYoc1tzbi5PRkZTRVRdPWkuc3ViYXJyYXkodCx0K2UrMSkpfHwoaT1zW3NuLkRBVEFdKSYmKHNbc24uREFUQV09bj09PTY/aTppLnN1YmFycmF5KHIqdCxyKih0K2UpKSk7cmV0dXJuIHN9X3NsaWNlQ2hpbGRyZW4odCxlLHIpe3JldHVybiB0Lm1hcCgobik9Pm4uc2xpY2UoZSxyKSl9fWZ1bmN0aW9uIHgodCl7cmV0dXJuIFYxLnZpc2l0KHQpfXZhciBrMT0tMSxCUyxFdSxWMTt2YXIgcGk9bSgoKT0+e2xuKCk7Q2UoKTthZSgpO2VsKCk7YWUoKTtRaSgpO1llKCk7QlM9U3ltYm9sLmZvcigiYXBhY2hlLWFycm93L0RhdGEiKTtodC5wcm90b3R5cGUuY2hpbGRyZW49T2JqZWN0LmZyZWV6ZShbXSk7aHQucHJvdG90eXBlW0JTXT0hMDtPYmplY3QuZGVmaW5lUHJvcGVydHkoaHQsU3ltYm9sLmhhc0luc3RhbmNlLHt2YWx1ZTpmdW5jdGlvbihlKXtyZXR1cm4gRnVuY3Rpb24ucHJvdG90eXBlW1N5bWJvbC5oYXNJbnN0YW5jZV0uY2FsbCh0aGlzLGUpfHx0aGlzPT09aHQmJmh0LmlzRGF0YShlKX19KTtFdT1jbGFzcyBFdSBleHRlbmRzIHN0e3Zpc2l0KHQpe3JldHVybiB0aGlzLmdldFZpc2l0Rm4odC50eXBlKS5jYWxsKHRoaXMsdCl9dmlzaXROdWxsKHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wLFsibGVuZ3RoIl06bj0wfT10O3JldHVybiBuZXcgaHQoZSxyLG4sbil9dmlzaXRCb29sKHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wfT10LG49ayh0Lm51bGxCaXRtYXApLGk9dnQoZS5BcnJheVR5cGUsdC5kYXRhKSx7WyJsZW5ndGgiXTpzPWkubGVuZ3RoPj4zLFsibnVsbENvdW50Il06bz10Lm51bGxCaXRtYXA/LTE6MH09dDtyZXR1cm4gbmV3IGh0KGUscixzLG8sW3ZvaWQgMCxpLG5dKX12aXNpdEludCh0KXtsZXR7WyJ0eXBlIl06ZSxbIm9mZnNldCJdOnI9MH09dCxuPWsodC5udWxsQml0bWFwKSxpPXZ0KGUuQXJyYXlUeXBlLHQuZGF0YSkse1sibGVuZ3RoIl06cz1pLmxlbmd0aCxbIm51bGxDb3VudCJdOm89dC5udWxsQml0bWFwPy0xOjB9PXQ7cmV0dXJuIG5ldyBodChlLHIscyxvLFt2b2lkIDAsaSxuXSl9dmlzaXRGbG9hdCh0KXtsZXR7WyJ0eXBlIl06ZSxbIm9mZnNldCJdOnI9MH09dCxuPWsodC5udWxsQml0bWFwKSxpPXZ0KGUuQXJyYXlUeXBlLHQuZGF0YSkse1sibGVuZ3RoIl06cz1pLmxlbmd0aCxbIm51bGxDb3VudCJdOm89dC5udWxsQml0bWFwPy0xOjB9PXQ7cmV0dXJuIG5ldyBodChlLHIscyxvLFt2b2lkIDAsaSxuXSl9dmlzaXRVdGY4KHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wfT10LG49ayh0LmRhdGEpLGk9ayh0Lm51bGxCaXRtYXApLHM9eGEodC52YWx1ZU9mZnNldHMpLHtbImxlbmd0aCJdOm89cy5sZW5ndGgtMSxbIm51bGxDb3VudCJdOmE9dC5udWxsQml0bWFwPy0xOjB9PXQ7cmV0dXJuIG5ldyBodChlLHIsbyxhLFtzLG4saV0pfXZpc2l0VXRmOFZpZXcodCl7dmFyIGU7bGV0e1sidHlwZSJdOnIsWyJvZmZzZXQiXTpuPTB9PXQsaT12dChyLkFycmF5VHlwZSx0LnZpZXdzKSxzPWsodC5udWxsQml0bWFwKSxvPSh0LnZhcmlhZGljQnVmZmVyc3x8W10pLm1hcCgodSk9PmsodSkpLGE9KGU9dC5sZW5ndGgpIT09bnVsbCYmZSE9PXZvaWQgMD9lOk1hdGgudHJ1bmMoaS5sZW5ndGgvTG4uRUxFTUVOVF9XSURUSCksbD10Lm51bGxCaXRtYXA/LTE6MDtyZXR1cm4gbmV3IGh0KHIsbixhLGwsW3ZvaWQgMCxpLHNdLFtdLHZvaWQgMCxvKX12aXNpdExhcmdlVXRmOCh0KXtsZXR7WyJ0eXBlIl06ZSxbIm9mZnNldCJdOnI9MH09dCxuPWsodC5kYXRhKSxpPWsodC5udWxsQml0bWFwKSxzPWVoKHQudmFsdWVPZmZzZXRzKSx7WyJsZW5ndGgiXTpvPXMubGVuZ3RoLTEsWyJudWxsQ291bnQiXTphPXQubnVsbEJpdG1hcD8tMTowfT10O3JldHVybiBuZXcgaHQoZSxyLG8sYSxbcyxuLGldKX12aXNpdEJpbmFyeSh0KXtsZXR7WyJ0eXBlIl06ZSxbIm9mZnNldCJdOnI9MH09dCxuPWsodC5kYXRhKSxpPWsodC5udWxsQml0bWFwKSxzPXhhKHQudmFsdWVPZmZzZXRzKSx7WyJsZW5ndGgiXTpvPXMubGVuZ3RoLTEsWyJudWxsQ291bnQiXTphPXQubnVsbEJpdG1hcD8tMTowfT10O3JldHVybiBuZXcgaHQoZSxyLG8sYSxbcyxuLGldKX12aXNpdEJpbmFyeVZpZXcodCl7dmFyIGU7bGV0e1sidHlwZSJdOnIsWyJvZmZzZXQiXTpuPTB9PXQsaT12dChyLkFycmF5VHlwZSx0LnZpZXdzKSxzPWsodC5udWxsQml0bWFwKSxvPSh0LnZhcmlhZGljQnVmZmVyc3x8W10pLm1hcCgodSk9PmsodSkpLGE9KGU9dC5sZW5ndGgpIT09bnVsbCYmZSE9PXZvaWQgMD9lOk1hdGgudHJ1bmMoaS5sZW5ndGgvYnQuRUxFTUVOVF9XSURUSCksbD10Lm51bGxCaXRtYXA/LTE6MDtyZXR1cm4gbmV3IGh0KHIsbixhLGwsW3ZvaWQgMCxpLHNdLFtdLHZvaWQgMCxvKX12aXNpdExhcmdlQmluYXJ5KHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wfT10LG49ayh0LmRhdGEpLGk9ayh0Lm51bGxCaXRtYXApLHM9ZWgodC52YWx1ZU9mZnNldHMpLHtbImxlbmd0aCJdOm89cy5sZW5ndGgtMSxbIm51bGxDb3VudCJdOmE9dC5udWxsQml0bWFwPy0xOjB9PXQ7cmV0dXJuIG5ldyBodChlLHIsbyxhLFtzLG4saV0pfXZpc2l0Rml4ZWRTaXplQmluYXJ5KHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wfT10LG49ayh0Lm51bGxCaXRtYXApLGk9dnQoZS5BcnJheVR5cGUsdC5kYXRhKSx7WyJsZW5ndGgiXTpzPWkubGVuZ3RoL1VuKGUpLFsibnVsbENvdW50Il06bz10Lm51bGxCaXRtYXA/LTE6MH09dDtyZXR1cm4gbmV3IGh0KGUscixzLG8sW3ZvaWQgMCxpLG5dKX12aXNpdERhdGUodCl7bGV0e1sidHlwZSJdOmUsWyJvZmZzZXQiXTpyPTB9PXQsbj1rKHQubnVsbEJpdG1hcCksaT12dChlLkFycmF5VHlwZSx0LmRhdGEpLHtbImxlbmd0aCJdOnM9aS5sZW5ndGgvVW4oZSksWyJudWxsQ291bnQiXTpvPXQubnVsbEJpdG1hcD8tMTowfT10O3JldHVybiBuZXcgaHQoZSxyLHMsbyxbdm9pZCAwLGksbl0pfXZpc2l0VGltZXN0YW1wKHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wfT10LG49ayh0Lm51bGxCaXRtYXApLGk9dnQoZS5BcnJheVR5cGUsdC5kYXRhKSx7WyJsZW5ndGgiXTpzPWkubGVuZ3RoL1VuKGUpLFsibnVsbENvdW50Il06bz10Lm51bGxCaXRtYXA/LTE6MH09dDtyZXR1cm4gbmV3IGh0KGUscixzLG8sW3ZvaWQgMCxpLG5dKX12aXNpdFRpbWUodCl7bGV0e1sidHlwZSJdOmUsWyJvZmZzZXQiXTpyPTB9PXQsbj1rKHQubnVsbEJpdG1hcCksaT12dChlLkFycmF5VHlwZSx0LmRhdGEpLHtbImxlbmd0aCJdOnM9aS5sZW5ndGgvVW4oZSksWyJudWxsQ291bnQiXTpvPXQubnVsbEJpdG1hcD8tMTowfT10O3JldHVybiBuZXcgaHQoZSxyLHMsbyxbdm9pZCAwLGksbl0pfXZpc2l0RGVjaW1hbCh0KXtsZXR7WyJ0eXBlIl06ZSxbIm9mZnNldCJdOnI9MH09dCxuPWsodC5udWxsQml0bWFwKSxpPXZ0KGUuQXJyYXlUeXBlLHQuZGF0YSkse1sibGVuZ3RoIl06cz1pLmxlbmd0aC9VbihlKSxbIm51bGxDb3VudCJdOm89dC5udWxsQml0bWFwPy0xOjB9PXQ7cmV0dXJuIG5ldyBodChlLHIscyxvLFt2b2lkIDAsaSxuXSl9dmlzaXRMaXN0KHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wLFsiY2hpbGQiXTpufT10LGk9ayh0Lm51bGxCaXRtYXApLHM9eGEodC52YWx1ZU9mZnNldHMpLHtbImxlbmd0aCJdOm89cy5sZW5ndGgtMSxbIm51bGxDb3VudCJdOmE9dC5udWxsQml0bWFwPy0xOjB9PXQ7cmV0dXJuIG5ldyBodChlLHIsbyxhLFtzLHZvaWQgMCxpXSxbbl0pfXZpc2l0U3RydWN0KHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wLFsiY2hpbGRyZW4iXTpuPVtdfT10LGk9ayh0Lm51bGxCaXRtYXApLHtsZW5ndGg6cz1uLnJlZHVjZSgoYSx7bGVuZ3RoOmx9KT0+TWF0aC5tYXgoYSxsKSwwKSxudWxsQ291bnQ6bz10Lm51bGxCaXRtYXA/LTE6MH09dDtyZXR1cm4gbmV3IGh0KGUscixzLG8sW3ZvaWQgMCx2b2lkIDAsaV0sbil9dmlzaXRVbmlvbih0KXtsZXR7WyJ0eXBlIl06ZSxbIm9mZnNldCJdOnI9MCxbImNoaWxkcmVuIl06bj1bXX09dCxpPXZ0KGUuQXJyYXlUeXBlLHQudHlwZUlkcykse1sibGVuZ3RoIl06cz1pLmxlbmd0aCxbIm51bGxDb3VudCJdOm89LTF9PXQ7aWYoQS5pc1NwYXJzZVVuaW9uKGUpKXJldHVybiBuZXcgaHQoZSxyLHMsbyxbdm9pZCAwLHZvaWQgMCx2b2lkIDAsaV0sbik7bGV0IGE9eGEodC52YWx1ZU9mZnNldHMpO3JldHVybiBuZXcgaHQoZSxyLHMsbyxbYSx2b2lkIDAsdm9pZCAwLGldLG4pfXZpc2l0RGljdGlvbmFyeSh0KXtsZXR7WyJ0eXBlIl06ZSxbIm9mZnNldCJdOnI9MH09dCxuPWsodC5udWxsQml0bWFwKSxpPXZ0KGUuaW5kaWNlcy5BcnJheVR5cGUsdC5kYXRhKSx7WyJkaWN0aW9uYXJ5Il06cz1uZXcgRihbbmV3IEV1KCkudmlzaXQoe3R5cGU6ZS5kaWN0aW9uYXJ5fSldKX09dCx7WyJsZW5ndGgiXTpvPWkubGVuZ3RoLFsibnVsbENvdW50Il06YT10Lm51bGxCaXRtYXA/LTE6MH09dDtyZXR1cm4gbmV3IGh0KGUscixvLGEsW3ZvaWQgMCxpLG5dLFtdLHMpfXZpc2l0SW50ZXJ2YWwodCl7bGV0e1sidHlwZSJdOmUsWyJvZmZzZXQiXTpyPTB9PXQsbj1rKHQubnVsbEJpdG1hcCksaT12dChlLkFycmF5VHlwZSx0LmRhdGEpLHtbImxlbmd0aCJdOnM9aS5sZW5ndGgvVW4oZSksWyJudWxsQ291bnQiXTpvPXQubnVsbEJpdG1hcD8tMTowfT10O3JldHVybiBuZXcgaHQoZSxyLHMsbyxbdm9pZCAwLGksbl0pfXZpc2l0RHVyYXRpb24odCl7bGV0e1sidHlwZSJdOmUsWyJvZmZzZXQiXTpyPTB9PXQsbj1rKHQubnVsbEJpdG1hcCksaT12dChlLkFycmF5VHlwZSx0LmRhdGEpLHtbImxlbmd0aCJdOnM9aS5sZW5ndGgsWyJudWxsQ291bnQiXTpvPXQubnVsbEJpdG1hcD8tMTowfT10O3JldHVybiBuZXcgaHQoZSxyLHMsbyxbdm9pZCAwLGksbl0pfXZpc2l0Rml4ZWRTaXplTGlzdCh0KXtsZXR7WyJ0eXBlIl06ZSxbIm9mZnNldCJdOnI9MCxbImNoaWxkIl06bj1uZXcgRXUoKS52aXNpdCh7dHlwZTplLnZhbHVlVHlwZX0pfT10LGk9ayh0Lm51bGxCaXRtYXApLHtbImxlbmd0aCJdOnM9bi5sZW5ndGgvVW4oZSksWyJudWxsQ291bnQiXTpvPXQubnVsbEJpdG1hcD8tMTowfT10O3JldHVybiBuZXcgaHQoZSxyLHMsbyxbdm9pZCAwLHZvaWQgMCxpXSxbbl0pfXZpc2l0TWFwKHQpe2xldHtbInR5cGUiXTplLFsib2Zmc2V0Il06cj0wLFsiY2hpbGQiXTpuPW5ldyBFdSgpLnZpc2l0KHt0eXBlOmUuY2hpbGRUeXBlfSl9PXQsaT1rKHQubnVsbEJpdG1hcCkscz14YSh0LnZhbHVlT2Zmc2V0cykse1sibGVuZ3RoIl06bz1zLmxlbmd0aC0xLFsibnVsbENvdW50Il06YT10Lm51bGxCaXRtYXA/LTE6MH09dDtyZXR1cm4gbmV3IGh0KGUscixvLGEsW3Msdm9pZCAwLGldLFtuXSl9fTtWMT1uZXcgRXV9KTtmdW5jdGlvbiBTUyh0KXtyZXR1cm4gdC5zb21lKChlKT0+ZS5udWxsYWJsZSl9ZnVuY3Rpb24gRmgodCl7cmV0dXJuIHQucmVkdWNlKChlLHIpPT5lK3IubnVsbENvdW50LDApfWZ1bmN0aW9uIE1oKHQpe3JldHVybiB0LnJlZHVjZSgoZSxyLG4pPT4oZVtuKzFdPWVbbl0rci5sZW5ndGgsZSksbmV3IFVpbnQzMkFycmF5KHQubGVuZ3RoKzEpKX1mdW5jdGlvbiBMaCh0LGUscixuKXtsZXQgaT1bXTtmb3IobGV0IHM9LTEsbz10Lmxlbmd0aDsrK3M8bzspe2xldCBhPXRbc10sbD1lW3NdLHtsZW5ndGg6dX09YTtpZihsPj1uKWJyZWFrO2lmKHI+PWwrdSljb250aW51ZTtpZihsPj1yJiZsK3U8PW4pe2kucHVzaChhKTtjb250aW51ZX1sZXQgZj1NYXRoLm1heCgwLHItbCkscD1NYXRoLm1pbihuLWwsdSk7aS5wdXNoKGEuc2xpY2UoZixwLWYpKX1pZihpLmxlbmd0aD09PTApaS5wdXNoKHRbMF0uc2xpY2UoMCwwKSk7cmV0dXJuIGl9ZnVuY3Rpb24gZWcodCxlLHIsbil7bGV0IGk9MCxzPTAsbz1lLmxlbmd0aC0xO2Rve2lmKGk+PW8tMSlyZXR1cm4gcjxlW29dP24odCxpLHItZVtpXSk6bnVsbDtzPWkrTWF0aC50cnVuYygoby1pKSowLjUpLHI8ZVtzXT9vPXM6aT1zfXdoaWxlKGk8byl9ZnVuY3Rpb24gT3UodCxlKXtyZXR1cm4gdC5nZXRWYWxpZChlKX1mdW5jdGlvbiBybCh0KXtmdW5jdGlvbiBlKHIsbixpKXtyZXR1cm4gdChyW25dLGkpfXJldHVybiBmdW5jdGlvbihyKXtsZXQgbj10aGlzLmRhdGE7cmV0dXJuIGVnKG4sdGhpcy5fb2Zmc2V0cyxyLGUpfX1mdW5jdGlvbiBVaCh0KXtsZXQgZTtmdW5jdGlvbiByKG4saSxzKXtyZXR1cm4gdChuW2ldLHMsZSl9cmV0dXJuIGZ1bmN0aW9uKG4saSl7bGV0IHM9dGhpcy5kYXRhO2U9aTtsZXQgbz1lZyhzLHRoaXMuX29mZnNldHMsbixyKTtyZXR1cm4gZT12b2lkIDAsb319ZnVuY3Rpb24gUmgodCl7bGV0IGU7ZnVuY3Rpb24gcihuLGkscyl7bGV0IG89cyxhPTAsbD0wO2ZvcihsZXQgdT1pLTEsZj1uLmxlbmd0aDsrK3U8Zjspe2xldCBwPW5bdV07aWYofihhPXQocCxlLG8pKSlyZXR1cm4gbCthO289MCxsKz1wLmxlbmd0aH1yZXR1cm4tMX1yZXR1cm4gZnVuY3Rpb24obixpKXtlPW47bGV0IHM9dGhpcy5kYXRhLG89dHlwZW9mIGkhPT0ibnVtYmVyIj9yKHMsMCwwKTplZyhzLHRoaXMuX29mZnNldHMsaSxyKTtyZXR1cm4gZT12b2lkIDAsb319dmFyIE5oO3ZhciBDaD1tKCgpPT57Tmg9Y2xhc3MgTmh7Y29uc3RydWN0b3IodD0wLGUpe3RoaXMubnVtQ2h1bmtzPXQsdGhpcy5nZXRDaHVua0l0ZXJhdG9yPWUsdGhpcy5jaHVua0luZGV4PTAsdGhpcy5jaHVua0l0ZXJhdG9yPXRoaXMuZ2V0Q2h1bmtJdGVyYXRvcigwKX1uZXh0KCl7d2hpbGUodGhpcy5jaHVua0luZGV4PHRoaXMubnVtQ2h1bmtzKXtsZXQgdD10aGlzLmNodW5rSXRlcmF0b3IubmV4dCgpO2lmKCF0LmRvbmUpcmV0dXJuIHQ7aWYoKyt0aGlzLmNodW5rSW5kZXg8dGhpcy5udW1DaHVua3MpdGhpcy5jaHVua0l0ZXJhdG9yPXRoaXMuZ2V0Q2h1bmtJdGVyYXRvcih0aGlzLmNodW5rSW5kZXgpfXJldHVybntkb25lOiEwLHZhbHVlOm51bGx9fVtTeW1ib2wuaXRlcmF0b3JdKCl7cmV0dXJuIHRoaXN9fX0pO2Z1bmN0aW9uIHoxKHQsZSl7cmV0dXJuIGU9PT1udWxsJiZ0Lmxlbmd0aD4wPzA6LTF9ZnVuY3Rpb24gajEodCxlKXtsZXR7bnVsbEJpdG1hcDpyfT10O2lmKCFyfHx0Lm51bGxDb3VudDw9MClyZXR1cm4tMTtsZXQgbj0wO2ZvcihsZXQgaSBvZiBuZXcgdGwocix0Lm9mZnNldCsoZXx8MCksdC5sZW5ndGgscixPaCkpe2lmKCFpKXJldHVybiBuOysrbn1yZXR1cm4tMX1mdW5jdGlvbiBkdCh0LGUscil7aWYoZT09PXZvaWQgMClyZXR1cm4tMTtpZihlPT09bnVsbClzd2l0Y2godC50eXBlSWQpe2Nhc2UgeS5VbmlvbjpicmVhaztjYXNlIHkuRGljdGlvbmFyeTpicmVhaztkZWZhdWx0OnJldHVybiBqMSh0LHIpfWxldCBuPVBlLmdldFZpc2l0Rm4odCksaT1HbyhlKTtmb3IobGV0IHM9KHJ8fDApLTEsbz10Lmxlbmd0aDsrK3M8bzspaWYoaShuKHQscykpKXJldHVybiBzO3JldHVybi0xfWZ1bmN0aW9uIEFTKHQsZSxyKXtsZXQgbj1QZS5nZXRWaXNpdEZuKHQpLGk9R28oZSk7Zm9yKGxldCBzPShyfHwwKS0xLG89dC5sZW5ndGg7KytzPG87KWlmKGkobih0LHMpKSlyZXR1cm4gcztyZXR1cm4tMX12YXIgRyxqYTt2YXIgUGg9bSgoKT0+e0NlKCk7UWkoKTtQYSgpO2VsKCk7UWMoKTtHPWNsYXNzIEcgZXh0ZW5kcyBzdHt9O0cucHJvdG90eXBlLnZpc2l0TnVsbD16MTtHLnByb3RvdHlwZS52aXNpdEJvb2w9ZHQ7Ry5wcm90b3R5cGUudmlzaXRJbnQ9ZHQ7Ry5wcm90b3R5cGUudmlzaXRJbnQ4PWR0O0cucHJvdG90eXBlLnZpc2l0SW50MTY9ZHQ7Ry5wcm90b3R5cGUudmlzaXRJbnQzMj1kdDtHLnByb3RvdHlwZS52aXNpdEludDY0PWR0O0cucHJvdG90eXBlLnZpc2l0VWludDg9ZHQ7Ry5wcm90b3R5cGUudmlzaXRVaW50MTY9ZHQ7Ry5wcm90b3R5cGUudmlzaXRVaW50MzI9ZHQ7Ry5wcm90b3R5cGUudmlzaXRVaW50NjQ9ZHQ7Ry5wcm90b3R5cGUudmlzaXRGbG9hdD1kdDtHLnByb3RvdHlwZS52aXNpdEZsb2F0MTY9ZHQ7Ry5wcm90b3R5cGUudmlzaXRGbG9hdDMyPWR0O0cucHJvdG90eXBlLnZpc2l0RmxvYXQ2ND1kdDtHLnByb3RvdHlwZS52aXNpdFV0Zjg9ZHQ7Ry5wcm90b3R5cGUudmlzaXRMYXJnZVV0Zjg9ZHQ7Ry5wcm90b3R5cGUudmlzaXRVdGY4Vmlldz1kdDtHLnByb3RvdHlwZS52aXNpdEJpbmFyeT1kdDtHLnByb3RvdHlwZS52aXNpdExhcmdlQmluYXJ5PWR0O0cucHJvdG90eXBlLnZpc2l0QmluYXJ5Vmlldz1kdDtHLnByb3RvdHlwZS52aXNpdEZpeGVkU2l6ZUJpbmFyeT1kdDtHLnByb3RvdHlwZS52aXNpdERhdGU9ZHQ7Ry5wcm90b3R5cGUudmlzaXREYXRlRGF5PWR0O0cucHJvdG90eXBlLnZpc2l0RGF0ZU1pbGxpc2Vjb25kPWR0O0cucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wPWR0O0cucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wU2Vjb25kPWR0O0cucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wTWlsbGlzZWNvbmQ9ZHQ7Ry5wcm90b3R5cGUudmlzaXRUaW1lc3RhbXBNaWNyb3NlY29uZD1kdDtHLnByb3RvdHlwZS52aXNpdFRpbWVzdGFtcE5hbm9zZWNvbmQ9ZHQ7Ry5wcm90b3R5cGUudmlzaXRUaW1lPWR0O0cucHJvdG90eXBlLnZpc2l0VGltZVNlY29uZD1kdDtHLnByb3RvdHlwZS52aXNpdFRpbWVNaWxsaXNlY29uZD1kdDtHLnByb3RvdHlwZS52aXNpdFRpbWVNaWNyb3NlY29uZD1kdDtHLnByb3RvdHlwZS52aXNpdFRpbWVOYW5vc2Vjb25kPWR0O0cucHJvdG90eXBlLnZpc2l0RGVjaW1hbD1kdDtHLnByb3RvdHlwZS52aXNpdExpc3Q9ZHQ7Ry5wcm90b3R5cGUudmlzaXRTdHJ1Y3Q9ZHQ7Ry5wcm90b3R5cGUudmlzaXRVbmlvbj1kdDtHLnByb3RvdHlwZS52aXNpdERlbnNlVW5pb249QVM7Ry5wcm90b3R5cGUudmlzaXRTcGFyc2VVbmlvbj1BUztHLnByb3RvdHlwZS52aXNpdERpY3Rpb25hcnk9ZHQ7Ry5wcm90b3R5cGUudmlzaXRJbnRlcnZhbD1kdDtHLnByb3RvdHlwZS52aXNpdEludGVydmFsRGF5VGltZT1kdDtHLnByb3RvdHlwZS52aXNpdEludGVydmFsWWVhck1vbnRoPWR0O0cucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWxNb250aERheU5hbm89ZHQ7Ry5wcm90b3R5cGUudmlzaXREdXJhdGlvbj1kdDtHLnByb3RvdHlwZS52aXNpdER1cmF0aW9uU2Vjb25kPWR0O0cucHJvdG90eXBlLnZpc2l0RHVyYXRpb25NaWxsaXNlY29uZD1kdDtHLnByb3RvdHlwZS52aXNpdER1cmF0aW9uTWljcm9zZWNvbmQ9ZHQ7Ry5wcm90b3R5cGUudmlzaXREdXJhdGlvbk5hbm9zZWNvbmQ9ZHQ7Ry5wcm90b3R5cGUudmlzaXRGaXhlZFNpemVMaXN0PWR0O0cucHJvdG90eXBlLnZpc2l0TWFwPWR0O2phPW5ldyBHfSk7ZnVuY3Rpb24gYXQodCl7bGV0e3R5cGU6ZX09dDtpZih0Lm51bGxDb3VudD09PTAmJnQuc3RyaWRlPT09MSYmKEEuaXNJbnQoZSkmJmUuYml0V2lkdGghPT02NHx8QS5pc1RpbWUoZSkmJmUuYml0V2lkdGghPT02NHx8QS5pc0Zsb2F0KGUpJiZlLnByZWNpc2lvbiE9PXJlLkhBTEYpKXJldHVybiBuZXcgTmgodC5kYXRhLmxlbmd0aCwobik9PntsZXQgaT10LmRhdGFbbl07cmV0dXJuIGkudmFsdWVzLnN1YmFycmF5KDAsaS5sZW5ndGgpW1N5bWJvbC5pdGVyYXRvcl0oKX0pO2xldCByPTA7cmV0dXJuIG5ldyBOaCh0LmRhdGEubGVuZ3RoLChuKT0+e2xldCBzPXQuZGF0YVtuXS5sZW5ndGgsbz10LnNsaWNlKHIscitzKTtyZXR1cm4gcis9cyxuZXcgRFMobyl9KX12YXIgSixEUyxubDt2YXIga2g9bSgoKT0+e1FpKCk7Q2UoKTthZSgpO0NoKCk7Sj1jbGFzcyBKIGV4dGVuZHMgc3R7fTtEUz1jbGFzcyBEU3tjb25zdHJ1Y3Rvcih0KXt0aGlzLnZlY3Rvcj10LHRoaXMuaW5kZXg9MH1uZXh0KCl7aWYodGhpcy5pbmRleDx0aGlzLnZlY3Rvci5sZW5ndGgpcmV0dXJue3ZhbHVlOnRoaXMudmVjdG9yLmdldCh0aGlzLmluZGV4KyspfTtyZXR1cm57ZG9uZTohMCx2YWx1ZTpudWxsfX1bU3ltYm9sLml0ZXJhdG9yXSgpe3JldHVybiB0aGlzfX07Si5wcm90b3R5cGUudmlzaXROdWxsPWF0O0oucHJvdG90eXBlLnZpc2l0Qm9vbD1hdDtKLnByb3RvdHlwZS52aXNpdEludD1hdDtKLnByb3RvdHlwZS52aXNpdEludDg9YXQ7Si5wcm90b3R5cGUudmlzaXRJbnQxNj1hdDtKLnByb3RvdHlwZS52aXNpdEludDMyPWF0O0oucHJvdG90eXBlLnZpc2l0SW50NjQ9YXQ7Si5wcm90b3R5cGUudmlzaXRVaW50OD1hdDtKLnByb3RvdHlwZS52aXNpdFVpbnQxNj1hdDtKLnByb3RvdHlwZS52aXNpdFVpbnQzMj1hdDtKLnByb3RvdHlwZS52aXNpdFVpbnQ2ND1hdDtKLnByb3RvdHlwZS52aXNpdEZsb2F0PWF0O0oucHJvdG90eXBlLnZpc2l0RmxvYXQxNj1hdDtKLnByb3RvdHlwZS52aXNpdEZsb2F0MzI9YXQ7Si5wcm90b3R5cGUudmlzaXRGbG9hdDY0PWF0O0oucHJvdG90eXBlLnZpc2l0VXRmOD1hdDtKLnByb3RvdHlwZS52aXNpdExhcmdlVXRmOD1hdDtKLnByb3RvdHlwZS52aXNpdFV0ZjhWaWV3PWF0O0oucHJvdG90eXBlLnZpc2l0QmluYXJ5PWF0O0oucHJvdG90eXBlLnZpc2l0TGFyZ2VCaW5hcnk9YXQ7Si5wcm90b3R5cGUudmlzaXRCaW5hcnlWaWV3PWF0O0oucHJvdG90eXBlLnZpc2l0Rml4ZWRTaXplQmluYXJ5PWF0O0oucHJvdG90eXBlLnZpc2l0RGF0ZT1hdDtKLnByb3RvdHlwZS52aXNpdERhdGVEYXk9YXQ7Si5wcm90b3R5cGUudmlzaXREYXRlTWlsbGlzZWNvbmQ9YXQ7Si5wcm90b3R5cGUudmlzaXRUaW1lc3RhbXA9YXQ7Si5wcm90b3R5cGUudmlzaXRUaW1lc3RhbXBTZWNvbmQ9YXQ7Si5wcm90b3R5cGUudmlzaXRUaW1lc3RhbXBNaWxsaXNlY29uZD1hdDtKLnByb3RvdHlwZS52aXNpdFRpbWVzdGFtcE1pY3Jvc2Vjb25kPWF0O0oucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wTmFub3NlY29uZD1hdDtKLnByb3RvdHlwZS52aXNpdFRpbWU9YXQ7Si5wcm90b3R5cGUudmlzaXRUaW1lU2Vjb25kPWF0O0oucHJvdG90eXBlLnZpc2l0VGltZU1pbGxpc2Vjb25kPWF0O0oucHJvdG90eXBlLnZpc2l0VGltZU1pY3Jvc2Vjb25kPWF0O0oucHJvdG90eXBlLnZpc2l0VGltZU5hbm9zZWNvbmQ9YXQ7Si5wcm90b3R5cGUudmlzaXREZWNpbWFsPWF0O0oucHJvdG90eXBlLnZpc2l0TGlzdD1hdDtKLnByb3RvdHlwZS52aXNpdFN0cnVjdD1hdDtKLnByb3RvdHlwZS52aXNpdFVuaW9uPWF0O0oucHJvdG90eXBlLnZpc2l0RGVuc2VVbmlvbj1hdDtKLnByb3RvdHlwZS52aXNpdFNwYXJzZVVuaW9uPWF0O0oucHJvdG90eXBlLnZpc2l0RGljdGlvbmFyeT1hdDtKLnByb3RvdHlwZS52aXNpdEludGVydmFsPWF0O0oucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWxEYXlUaW1lPWF0O0oucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWxZZWFyTW9udGg9YXQ7Si5wcm90b3R5cGUudmlzaXRJbnRlcnZhbE1vbnRoRGF5TmFubz1hdDtKLnByb3RvdHlwZS52aXNpdER1cmF0aW9uPWF0O0oucHJvdG90eXBlLnZpc2l0RHVyYXRpb25TZWNvbmQ9YXQ7Si5wcm90b3R5cGUudmlzaXREdXJhdGlvbk1pbGxpc2Vjb25kPWF0O0oucHJvdG90eXBlLnZpc2l0RHVyYXRpb25NaWNyb3NlY29uZD1hdDtKLnByb3RvdHlwZS52aXNpdER1cmF0aW9uTmFub3NlY29uZD1hdDtKLnByb3RvdHlwZS52aXNpdEZpeGVkU2l6ZUxpc3Q9YXQ7Si5wcm90b3R5cGUudmlzaXRNYXA9YXQ7bmw9bmV3IEp9KTtmdW5jdGlvbiAkYSh0KXtpZih0KXtpZih0IGluc3RhbmNlb2YgaHQpcmV0dXJuIG5ldyBGKFt0XSk7aWYodCBpbnN0YW5jZW9mIEYpcmV0dXJuIG5ldyBGKHQuZGF0YSk7aWYodC50eXBlIGluc3RhbmNlb2YgQSlyZXR1cm4gbmV3IEYoW3godCldKTtpZihBcnJheS5pc0FycmF5KHQpKXJldHVybiBuZXcgRih0LmZsYXRNYXAoKGUpPT4kMShlKSkpO2lmKEFycmF5QnVmZmVyLmlzVmlldyh0KSl7aWYodCBpbnN0YW5jZW9mIERhdGFWaWV3KXQ9bmV3IFVpbnQ4QXJyYXkodC5idWZmZXIpO2xldCBlPXtvZmZzZXQ6MCxsZW5ndGg6dC5sZW5ndGgsbnVsbENvdW50Oi0xLGRhdGE6dH07aWYodCBpbnN0YW5jZW9mIEludDhBcnJheSlyZXR1cm4gbmV3IEYoW3goT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LGUpLHt0eXBlOm5ldyBPYX0pKV0pO2lmKHQgaW5zdGFuY2VvZiBJbnQxNkFycmF5KXJldHVybiBuZXcgRihbeChPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sZSkse3R5cGU6bmV3IE5hfSkpXSk7aWYodCBpbnN0YW5jZW9mIEludDMyQXJyYXkpcmV0dXJuIG5ldyBGKFt4KE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSxlKSx7dHlwZTpuZXcganJ9KSldKTtpZih0IGluc3RhbmNlb2YgQmlnSW50NjRBcnJheSlyZXR1cm4gbmV3IEYoW3goT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LGUpLHt0eXBlOm5ldyBjbn0pKV0pO2lmKHQgaW5zdGFuY2VvZiBVaW50OEFycmF5fHx0IGluc3RhbmNlb2YgVWludDhDbGFtcGVkQXJyYXkpcmV0dXJuIG5ldyBGKFt4KE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSxlKSx7dHlwZTpuZXcgRmF9KSldKTtpZih0IGluc3RhbmNlb2YgVWludDE2QXJyYXkpcmV0dXJuIG5ldyBGKFt4KE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSxlKSx7dHlwZTpuZXcgTWF9KSldKTtpZih0IGluc3RhbmNlb2YgVWludDMyQXJyYXkpcmV0dXJuIG5ldyBGKFt4KE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSxlKSx7dHlwZTpuZXcgTGF9KSldKTtpZih0IGluc3RhbmNlb2YgQmlnVWludDY0QXJyYXkpcmV0dXJuIG5ldyBGKFt4KE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSxlKSx7dHlwZTpuZXcgVWF9KSldKTtpZih0IGluc3RhbmNlb2YgRmxvYXQzMkFycmF5KXJldHVybiBuZXcgRihbeChPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sZSkse3R5cGU6bmV3IFJhfSkpXSk7aWYodCBpbnN0YW5jZW9mIEZsb2F0NjRBcnJheSlyZXR1cm4gbmV3IEYoW3goT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LGUpLHt0eXBlOm5ldyBaaX0pKV0pO3Rocm93IEVycm9yKCJVbnJlY29nbml6ZWQgaW5wdXQiKX19dGhyb3cgRXJyb3IoIlVucmVjb2duaXplZCBpbnB1dCIpfWZ1bmN0aW9uICQxKHQpe3JldHVybiB0IGluc3RhbmNlb2YgaHQ/W3RdOnQgaW5zdGFuY2VvZiBGP3QuZGF0YTokYSh0KS5kYXRhfXZhciB4UyxUUyxFUyxPUyxGLFZoO3ZhciBsbj1tKCgpPT57Q2UoKTtRYygpO2FlKCk7cGkoKTtDaCgpO1BhKCk7Um4oKTtQaCgpO2toKCk7YWUoKTtUUz1TeW1ib2wuZm9yKCJhcGFjaGUtYXJyb3cvVmVjdG9yIiksRVM9e30sT1M9e307Rj1jbGFzcyBGe3N0YXRpYyBpc1ZlY3Rvcih0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnRbVFNdKT09PSEwfWNvbnN0cnVjdG9yKHQpe3ZhciBlLHIsbjtsZXQgaT10WzBdaW5zdGFuY2VvZiBGP3QuZmxhdE1hcCgobyk9Pm8uZGF0YSk6dDtpZihpLmxlbmd0aD09PTB8fGkuc29tZSgobyk9PiEobyBpbnN0YW5jZW9mIGh0KSkpdGhyb3cgVHlwZUVycm9yKCJWZWN0b3IgY29uc3RydWN0b3IgZXhwZWN0cyBhbiBBcnJheSBvZiBEYXRhIGluc3RhbmNlcy4iKTtsZXQgcz0oZT1pWzBdKT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUudHlwZTtzd2l0Y2goaS5sZW5ndGgpe2Nhc2UgMDp0aGlzLl9vZmZzZXRzPVswXTticmVhaztjYXNlIDE6e2xldHtnZXQ6byxzZXQ6YSxpbmRleE9mOmx9PUVTW3MudHlwZUlkXSx1PWlbMF07dGhpcy5pc1ZhbGlkPShmKT0+T3UodSxmKSx0aGlzLmdldD0oZik9Pm8odSxmKSx0aGlzLnNldD0oZixwKT0+YSh1LGYscCksdGhpcy5pbmRleE9mPShmKT0+bCh1LGYpLHRoaXMuX29mZnNldHM9WzAsdS5sZW5ndGhdO2JyZWFrfWRlZmF1bHQ6T2JqZWN0LnNldFByb3RvdHlwZU9mKHRoaXMsT1Nbcy50eXBlSWRdKSx0aGlzLl9vZmZzZXRzPU1oKGkpO2JyZWFrfXRoaXMuZGF0YT1pLHRoaXMudHlwZT1zLHRoaXMuc3RyaWRlPVVuKHMpLHRoaXMubnVtQ2hpbGRyZW49KG49KHI9cy5jaGlsZHJlbik9PT1udWxsfHxyPT09dm9pZCAwP3ZvaWQgMDpyLmxlbmd0aCkhPT1udWxsJiZuIT09dm9pZCAwP246MCx0aGlzLmxlbmd0aD10aGlzLl9vZmZzZXRzLmF0KC0xKX1nZXQgYnl0ZUxlbmd0aCgpe3JldHVybiB0aGlzLmRhdGEucmVkdWNlKCh0LGUpPT50K2UuYnl0ZUxlbmd0aCwwKX1nZXQgbnVsbGFibGUoKXtyZXR1cm4gU1ModGhpcy5kYXRhKX1nZXQgbnVsbENvdW50KCl7cmV0dXJuIEZoKHRoaXMuZGF0YSl9Z2V0IEFycmF5VHlwZSgpe3JldHVybiB0aGlzLnR5cGUuQXJyYXlUeXBlfWdldFtTeW1ib2wudG9TdHJpbmdUYWddKCl7cmV0dXJuYCR7dGhpcy5WZWN0b3JOYW1lfTwke3RoaXMudHlwZVtTeW1ib2wudG9TdHJpbmdUYWddfT5gfWdldCBWZWN0b3JOYW1lKCl7cmV0dXJuYCR7eVt0aGlzLnR5cGUudHlwZUlkXX1WZWN0b3JgfWlzVmFsaWQodCl7cmV0dXJuITF9Z2V0KHQpe3JldHVybiBudWxsfWF0KHQpe3JldHVybiB0aGlzLmdldChrYSh0LHRoaXMubGVuZ3RoKSl9c2V0KHQsZSl7cmV0dXJufWluZGV4T2YodCxlKXtyZXR1cm4tMX1pbmNsdWRlcyh0LGUpe3JldHVybiB0aGlzLmluZGV4T2YodCxlKT4tMX1bU3ltYm9sLml0ZXJhdG9yXSgpe3JldHVybiBubC52aXNpdCh0aGlzKX1jb25jYXQoLi4udCl7cmV0dXJuIG5ldyBGKHRoaXMuZGF0YS5jb25jYXQodC5mbGF0TWFwKChlKT0+ZS5kYXRhKS5mbGF0KE51bWJlci5QT1NJVElWRV9JTkZJTklUWSkpKX1zbGljZSh0LGUpe3JldHVybiBuZXcgRih4dSh0aGlzLHQsZSwoe2RhdGE6cixfb2Zmc2V0czpufSxpLHMpPT5MaChyLG4saSxzKSkpfXRvSlNPTigpe3JldHVyblsuLi50aGlzXX10b0FycmF5KCl7bGV0e3R5cGU6dCxkYXRhOmUsbGVuZ3RoOnIsc3RyaWRlOm4sQXJyYXlUeXBlOml9PXRoaXM7c3dpdGNoKHQudHlwZUlkKXtjYXNlIHkuSW50OmNhc2UgeS5GbG9hdDpjYXNlIHkuRGVjaW1hbDpjYXNlIHkuVGltZTpjYXNlIHkuVGltZXN0YW1wOnN3aXRjaChlLmxlbmd0aCl7Y2FzZSAwOnJldHVybiBuZXcgaTtjYXNlIDE6cmV0dXJuIGVbMF0udmFsdWVzLnN1YmFycmF5KDAscipuKTtkZWZhdWx0OnJldHVybiBlLnJlZHVjZSgocyx7dmFsdWVzOm8sbGVuZ3RoOmF9KT0+KHMuYXJyYXkuc2V0KG8uc3ViYXJyYXkoMCxhKm4pLHMub2Zmc2V0KSxzLm9mZnNldCs9YSpuLHMpLHthcnJheTpuZXcgaShyKm4pLG9mZnNldDowfSkuYXJyYXl9fXJldHVyblsuLi50aGlzXX10b1N0cmluZygpe3JldHVybmBbJHtbLi4udGhpc10uam9pbigiLCIpfV1gfWdldENoaWxkKHQpe3ZhciBlO3JldHVybiB0aGlzLmdldENoaWxkQXQoKGU9dGhpcy50eXBlLmNoaWxkcmVuKT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUuZmluZEluZGV4KChyKT0+ci5uYW1lPT09dCkpfWdldENoaWxkQXQodCl7aWYodD4tMSYmdDx0aGlzLm51bUNoaWxkcmVuKXJldHVybiBuZXcgRih0aGlzLmRhdGEubWFwKCh7Y2hpbGRyZW46ZX0pPT5lW3RdKSk7cmV0dXJuIG51bGx9Z2V0IGlzTWVtb2l6ZWQoKXtpZihBLmlzRGljdGlvbmFyeSh0aGlzLnR5cGUpKXJldHVybiB0aGlzLmRhdGFbMF0uZGljdGlvbmFyeS5pc01lbW9pemVkO3JldHVybiExfW1lbW9pemUoKXtpZihBLmlzRGljdGlvbmFyeSh0aGlzLnR5cGUpKXtsZXQgdD1uZXcgVmgodGhpcy5kYXRhWzBdLmRpY3Rpb25hcnkpLGU9dGhpcy5kYXRhLm1hcCgocik9PntsZXQgbj1yLmNsb25lKCk7cmV0dXJuIG4uZGljdGlvbmFyeT10LG59KTtyZXR1cm4gbmV3IEYoZSl9cmV0dXJuIG5ldyBWaCh0aGlzKX11bm1lbW9pemUoKXtpZihBLmlzRGljdGlvbmFyeSh0aGlzLnR5cGUpJiZ0aGlzLmlzTWVtb2l6ZWQpe2xldCB0PXRoaXMuZGF0YVswXS5kaWN0aW9uYXJ5LnVubWVtb2l6ZSgpLGU9dGhpcy5kYXRhLm1hcCgocik9PntsZXQgbj1yLmNsb25lKCk7cmV0dXJuIG4uZGljdGlvbmFyeT10LG59KTtyZXR1cm4gbmV3IEYoZSl9cmV0dXJuIHRoaXN9fTt4Uz1TeW1ib2wudG9TdHJpbmdUYWc7Rlt4U109KCh0KT0+e3QudHlwZT1BLnByb3RvdHlwZSx0LmRhdGE9W10sdC5sZW5ndGg9MCx0LnN0cmlkZT0xLHQubnVtQ2hpbGRyZW49MCx0Ll9vZmZzZXRzPW5ldyBVaW50MzJBcnJheShbMF0pLHRbU3ltYm9sLmlzQ29uY2F0U3ByZWFkYWJsZV09ITAsdFtUU109ITA7bGV0IGU9T2JqZWN0LmtleXMoeSkubWFwKChyKT0+eVtyXSkuZmlsdGVyKChyKT0+dHlwZW9mIHI9PT0ibnVtYmVyIiYmciE9PXkuTk9ORSk7Zm9yKGxldCByIG9mIGUpe2xldCBuPVBlLmdldFZpc2l0Rm5CeVR5cGVJZChyKSxpPV9yLmdldFZpc2l0Rm5CeVR5cGVJZChyKSxzPWphLmdldFZpc2l0Rm5CeVR5cGVJZChyKTtFU1tyXT17Z2V0Om4sc2V0OmksaW5kZXhPZjpzfSxPU1tyXT1PYmplY3QuY3JlYXRlKHQse1siaXNWYWxpZCJdOnt2YWx1ZTpybChPdSl9LFsiZ2V0Il06e3ZhbHVlOnJsKFBlLmdldFZpc2l0Rm5CeVR5cGVJZChyKSl9LFsic2V0Il06e3ZhbHVlOlVoKF9yLmdldFZpc2l0Rm5CeVR5cGVJZChyKSl9LFsiaW5kZXhPZiJdOnt2YWx1ZTpSaChqYS5nZXRWaXNpdEZuQnlUeXBlSWQocikpfX0pfXJldHVybiJWZWN0b3IifSkoRi5wcm90b3R5cGUpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShGLFN5bWJvbC5oYXNJbnN0YW5jZSx7dmFsdWU6ZnVuY3Rpb24oZSl7cmV0dXJuIEZ1bmN0aW9uLnByb3RvdHlwZVtTeW1ib2wuaGFzSW5zdGFuY2VdLmNhbGwodGhpcyxlKXx8dGhpcz09PUYmJkYuaXNWZWN0b3IoZSl9fSk7Vmg9Y2xhc3MgVmggZXh0ZW5kcyBGe2NvbnN0cnVjdG9yKHQpe3N1cGVyKHQuZGF0YSk7bGV0IGU9dGhpcy5nZXQscj10aGlzLnNldCxuPXRoaXMuc2xpY2UsaT1BcnJheSh0aGlzLmxlbmd0aCk7T2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsImdldCIse3ZhbHVlKHMpe2xldCBvPWlbc107aWYobyE9PXZvaWQgMClyZXR1cm4gbztsZXQgYT1lLmNhbGwodGhpcyxzKTtyZXR1cm4gaVtzXT1hLGF9fSksT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsInNldCIse3ZhbHVlKHMsbyl7ci5jYWxsKHRoaXMscyxvKSxpW3NdPW99fSksT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsInNsaWNlIix7dmFsdWU6KHMsbyk9Pm5ldyBWaChuLmNhbGwodGhpcyxzLG8pKX0pLE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCJpc01lbW9pemVkIix7dmFsdWU6ITB9KSxPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywidW5tZW1vaXplIix7dmFsdWU6KCk9Pm5ldyBGKHRoaXMuZGF0YSl9KSxPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywibWVtb2l6ZSIse3ZhbHVlOigpPT50aGlzfSl9fX0pO2Z1bmN0aW9uIE5TKHQpe2lmKCF0fHx0Lmxlbmd0aDw9MClyZXR1cm4gZnVuY3Rpb24oaSl7cmV0dXJuITB9O2xldCBlPSIiLHI9dC5maWx0ZXIoKG4pPT5uPT09bik7aWYoci5sZW5ndGg+MCllPWAKICAgIHN3aXRjaCAoeCkgeyR7ci5tYXAoKG4pPT5gCiAgICAgICAgY2FzZSAke3ExKG4pfTpgKS5qb2luKCIiKX0KICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgfWA7aWYodC5sZW5ndGghPT1yLmxlbmd0aCllPWBpZiAoeCAhPT0geCkgcmV0dXJuIGZhbHNlOwoke2V9YDtyZXR1cm4gRnVuY3Rpb24oIngiLGAke2V9CnJldHVybiB0cnVlO2ApfWZ1bmN0aW9uIHExKHQpe2lmKHR5cGVvZiB0IT09ImJpZ2ludCIpcmV0dXJuIEtpKHQpO3JldHVybmAke0tpKHQpfW5gfXZhciBGUz0oKT0+e307ZnVuY3Rpb24gcmcodCxlKXtsZXQgcj1NYXRoLmNlaWwodCkqZS0xO3JldHVybihyLXIlNjQrNjR8fDY0KS9lfWZ1bmN0aW9uIE1TKHQsZT0wKXtyZXR1cm4gdC5sZW5ndGg+PWU/dC5zdWJhcnJheSgwLGUpOmh1KG5ldyB0LmNvbnN0cnVjdG9yKGUpLHQsMCl9Y2xhc3MgQ257Y29uc3RydWN0b3IodCxlPTAscj0xKXt0aGlzLmxlbmd0aD1NYXRoLmNlaWwoZS9yKSx0aGlzLmJ1ZmZlcj1uZXcgdCh0aGlzLmxlbmd0aCksdGhpcy5zdHJpZGU9cix0aGlzLkJZVEVTX1BFUl9FTEVNRU5UPXQuQllURVNfUEVSX0VMRU1FTlQsdGhpcy5BcnJheVR5cGU9dH1nZXQgYnl0ZUxlbmd0aCgpe3JldHVybiBNYXRoLmNlaWwodGhpcy5sZW5ndGgqdGhpcy5zdHJpZGUpKnRoaXMuQllURVNfUEVSX0VMRU1FTlR9Z2V0IHJlc2VydmVkTGVuZ3RoKCl7cmV0dXJuIHRoaXMuYnVmZmVyLmxlbmd0aC90aGlzLnN0cmlkZX1nZXQgcmVzZXJ2ZWRCeXRlTGVuZ3RoKCl7cmV0dXJuIHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGh9c2V0KHQsZSl7cmV0dXJuIHRoaXN9YXBwZW5kKHQpe3JldHVybiB0aGlzLnNldCh0aGlzLmxlbmd0aCx0KX1yZXNlcnZlKHQpe2lmKHQ+MCl7dGhpcy5sZW5ndGgrPXQ7bGV0IGU9dGhpcy5zdHJpZGUscj10aGlzLmxlbmd0aCplLG49dGhpcy5idWZmZXIubGVuZ3RoO2lmKHI+PW4pdGhpcy5fcmVzaXplKG49PT0wP3JnKHIqMSx0aGlzLkJZVEVTX1BFUl9FTEVNRU5UKTpyZyhyKjIsdGhpcy5CWVRFU19QRVJfRUxFTUVOVCkpfXJldHVybiB0aGlzfWZsdXNoKHQ9dGhpcy5sZW5ndGgpe3Q9cmcodCp0aGlzLnN0cmlkZSx0aGlzLkJZVEVTX1BFUl9FTEVNRU5UKTtsZXQgZT1NUyh0aGlzLmJ1ZmZlcix0KTtyZXR1cm4gdGhpcy5jbGVhcigpLGV9Y2xlYXIoKXtyZXR1cm4gdGhpcy5sZW5ndGg9MCx0aGlzLmJ1ZmZlcj1uZXcgdGhpcy5BcnJheVR5cGUsdGhpc31fcmVzaXplKHQpe3JldHVybiB0aGlzLmJ1ZmZlcj1NUyh0aGlzLmJ1ZmZlcix0KX19dmFyIEpvLE51LEZ1O3ZhciBncz1tKCgpPT57WWUoKTtKbz1jbGFzcyBKbyBleHRlbmRzIENue2xhc3QoKXtyZXR1cm4gdGhpcy5nZXQodGhpcy5sZW5ndGgtMSl9Z2V0KHQpe3JldHVybiB0aGlzLmJ1ZmZlclt0XX1zZXQodCxlKXtyZXR1cm4gdGhpcy5yZXNlcnZlKHQtdGhpcy5sZW5ndGgrMSksdGhpcy5idWZmZXJbdCp0aGlzLnN0cmlkZV09ZSx0aGlzfX07TnU9Y2xhc3MgTnUgZXh0ZW5kcyBKb3tjb25zdHJ1Y3Rvcigpe3N1cGVyKFVpbnQ4QXJyYXksMCwwLjEyNSk7dGhpcy5udW1WYWxpZD0wfWdldCBudW1JbnZhbGlkKCl7cmV0dXJuIHRoaXMubGVuZ3RoLXRoaXMubnVtVmFsaWR9Z2V0KHQpe3JldHVybiB0aGlzLmJ1ZmZlclt0Pj4zXT4+dCU4JjF9c2V0KHQsZSl7bGV0e2J1ZmZlcjpyfT10aGlzLnJlc2VydmUodC10aGlzLmxlbmd0aCsxKSxuPXQ+PjMsaT10JTgscz1yW25dPj5pJjE7cmV0dXJuIGU/cz09PTAmJihyW25dfD0xPDxpLCsrdGhpcy5udW1WYWxpZCk6cz09PTEmJihyW25dJj1+KDE8PGkpLC0tdGhpcy5udW1WYWxpZCksdGhpc31jbGVhcigpe3JldHVybiB0aGlzLm51bVZhbGlkPTAsc3VwZXIuY2xlYXIoKX19O0Z1PWNsYXNzIEZ1IGV4dGVuZHMgSm97Y29uc3RydWN0b3IodCl7c3VwZXIodC5PZmZzZXRBcnJheVR5cGUsMSwxKX1hcHBlbmQodCl7cmV0dXJuIHRoaXMuc2V0KHRoaXMubGVuZ3RoLTEsdCl9c2V0KHQsZSl7bGV0IHI9dGhpcy5sZW5ndGgtMSxuPXRoaXMucmVzZXJ2ZSh0LXIrMSkuYnVmZmVyO2lmKHI8dCsrJiZyPj0wKW4uZmlsbChuW3JdLHIsdCk7cmV0dXJuIG5bdF09blt0LTFdK2UsdGhpc31mbHVzaCh0PXRoaXMubGVuZ3RoLTEpe2lmKHQ+dGhpcy5sZW5ndGgpdGhpcy5zZXQodC0xLHRoaXMuQllURVNfUEVSX0VMRU1FTlQ+ND9CaWdJbnQoMCk6MCk7cmV0dXJuIHN1cGVyLmZsdXNoKHQrMSl9fX0pO2NsYXNzIGRle3N0YXRpYyB0aHJvdWdoTm9kZSh0KXt0aHJvdyBFcnJvcignInRocm91Z2hOb2RlIiBub3QgYXZhaWxhYmxlIGluIHRoaXMgZW52aXJvbm1lbnQnKX1zdGF0aWMgdGhyb3VnaERPTSh0KXt0aHJvdyBFcnJvcignInRocm91Z2hET00iIG5vdCBhdmFpbGFibGUgaW4gdGhpcyBlbnZpcm9ubWVudCcpfWNvbnN0cnVjdG9yKHt0eXBlOnQsbnVsbFZhbHVlczplfSl7aWYodGhpcy5sZW5ndGg9MCx0aGlzLmZpbmlzaGVkPSExLHRoaXMudHlwZT10LHRoaXMuY2hpbGRyZW49W10sdGhpcy5udWxsVmFsdWVzPWUsdGhpcy5zdHJpZGU9VW4odCksdGhpcy5fbnVsbHM9bmV3IE51LGUmJmUubGVuZ3RoPjApdGhpcy5faXNWYWxpZD1OUyhlKX10b1ZlY3Rvcigpe3JldHVybiBuZXcgRihbdGhpcy5mbHVzaCgpXSl9Z2V0IEFycmF5VHlwZSgpe3JldHVybiB0aGlzLnR5cGUuQXJyYXlUeXBlfWdldCBudWxsQ291bnQoKXtyZXR1cm4gdGhpcy5fbnVsbHMubnVtSW52YWxpZH1nZXQgbnVtQ2hpbGRyZW4oKXtyZXR1cm4gdGhpcy5jaGlsZHJlbi5sZW5ndGh9Z2V0IGJ5dGVMZW5ndGgoKXtsZXQgdD0wLHtfb2Zmc2V0czplLF92YWx1ZXM6cixfbnVsbHM6bixfdHlwZUlkczppLGNoaWxkcmVuOnN9PXRoaXM7cmV0dXJuIGUmJih0Kz1lLmJ5dGVMZW5ndGgpLHImJih0Kz1yLmJ5dGVMZW5ndGgpLG4mJih0Kz1uLmJ5dGVMZW5ndGgpLGkmJih0Kz1pLmJ5dGVMZW5ndGgpLHMucmVkdWNlKChvLGEpPT5vK2EuYnl0ZUxlbmd0aCx0KX1nZXQgcmVzZXJ2ZWRMZW5ndGgoKXtyZXR1cm4gdGhpcy5fbnVsbHMucmVzZXJ2ZWRMZW5ndGh9Z2V0IHJlc2VydmVkQnl0ZUxlbmd0aCgpe2xldCB0PTA7cmV0dXJuIHRoaXMuX29mZnNldHMmJih0Kz10aGlzLl9vZmZzZXRzLnJlc2VydmVkQnl0ZUxlbmd0aCksdGhpcy5fdmFsdWVzJiYodCs9dGhpcy5fdmFsdWVzLnJlc2VydmVkQnl0ZUxlbmd0aCksdGhpcy5fbnVsbHMmJih0Kz10aGlzLl9udWxscy5yZXNlcnZlZEJ5dGVMZW5ndGgpLHRoaXMuX3R5cGVJZHMmJih0Kz10aGlzLl90eXBlSWRzLnJlc2VydmVkQnl0ZUxlbmd0aCksdGhpcy5jaGlsZHJlbi5yZWR1Y2UoKGUscik9PmUrci5yZXNlcnZlZEJ5dGVMZW5ndGgsdCl9Z2V0IHZhbHVlT2Zmc2V0cygpe3JldHVybiB0aGlzLl9vZmZzZXRzP3RoaXMuX29mZnNldHMuYnVmZmVyOm51bGx9Z2V0IHZhbHVlcygpe3JldHVybiB0aGlzLl92YWx1ZXM/dGhpcy5fdmFsdWVzLmJ1ZmZlcjpudWxsfWdldCBudWxsQml0bWFwKCl7cmV0dXJuIHRoaXMuX251bGxzP3RoaXMuX251bGxzLmJ1ZmZlcjpudWxsfWdldCB0eXBlSWRzKCl7cmV0dXJuIHRoaXMuX3R5cGVJZHM/dGhpcy5fdHlwZUlkcy5idWZmZXI6bnVsbH1hcHBlbmQodCl7cmV0dXJuIHRoaXMuc2V0KHRoaXMubGVuZ3RoLHQpfWlzVmFsaWQodCl7cmV0dXJuIHRoaXMuX2lzVmFsaWQodCl9c2V0KHQsZSl7aWYodGhpcy5zZXRWYWxpZCh0LHRoaXMuaXNWYWxpZChlKSkpdGhpcy5zZXRWYWx1ZSh0LGUpO3JldHVybiB0aGlzfXNldFZhbHVlKHQsZSl7dGhpcy5fc2V0VmFsdWUodGhpcyx0LGUpfXNldFZhbGlkKHQsZSl7cmV0dXJuIHRoaXMubGVuZ3RoPXRoaXMuX251bGxzLnNldCh0LCtlKS5sZW5ndGgsZX1hZGRDaGlsZCh0LGU9YCR7dGhpcy5udW1DaGlsZHJlbn1gKXt0aHJvdyBFcnJvcihgQ2Fubm90IGFwcGVuZCBjaGlsZHJlbiB0byBub24tbmVzdGVkIHR5cGUgIiR7dGhpcy50eXBlfSJgKX1nZXRDaGlsZEF0KHQpe3JldHVybiB0aGlzLmNoaWxkcmVuW3RdfHxudWxsfWZsdXNoKCl7bGV0IHQsZSxyLG4se3R5cGU6aSxsZW5ndGg6cyxudWxsQ291bnQ6byxfdHlwZUlkczphLF9vZmZzZXRzOmwsX3ZhbHVlczp1LF9udWxsczpmfT10aGlzO2lmKGU9YT09PW51bGx8fGE9PT12b2lkIDA/dm9pZCAwOmEuZmx1c2gocykpbj1sPT09bnVsbHx8bD09PXZvaWQgMD92b2lkIDA6bC5mbHVzaChzKTtlbHNlIGlmKG49bD09PW51bGx8fGw9PT12b2lkIDA/dm9pZCAwOmwuZmx1c2gocykpdD11PT09bnVsbHx8dT09PXZvaWQgMD92b2lkIDA6dS5mbHVzaChsLmxhc3QoKSk7ZWxzZSB0PXU9PT1udWxsfHx1PT09dm9pZCAwP3ZvaWQgMDp1LmZsdXNoKHMpO2lmKG8+MClyPWY9PT1udWxsfHxmPT09dm9pZCAwP3ZvaWQgMDpmLmZsdXNoKHMpO2xldCBwPXRoaXMuY2hpbGRyZW4ubWFwKChnKT0+Zy5mbHVzaCgpKTtyZXR1cm4gdGhpcy5jbGVhcigpLHgoe3R5cGU6aSxsZW5ndGg6cyxudWxsQ291bnQ6byxjaGlsZHJlbjpwLGNoaWxkOnBbMF0sZGF0YTp0LHR5cGVJZHM6ZSxudWxsQml0bWFwOnIsdmFsdWVPZmZzZXRzOm59KX1maW5pc2goKXt0aGlzLmZpbmlzaGVkPSEwO2ZvcihsZXQgdCBvZiB0aGlzLmNoaWxkcmVuKXQuZmluaXNoKCk7cmV0dXJuIHRoaXN9Y2xlYXIoKXt2YXIgdCxlLHIsbjt0aGlzLmxlbmd0aD0wLCh0PXRoaXMuX251bGxzKT09PW51bGx8fHQ9PT12b2lkIDB8fHQuY2xlYXIoKSwoZT10aGlzLl92YWx1ZXMpPT09bnVsbHx8ZT09PXZvaWQgMHx8ZS5jbGVhcigpLChyPXRoaXMuX29mZnNldHMpPT09bnVsbHx8cj09PXZvaWQgMHx8ci5jbGVhcigpLChuPXRoaXMuX3R5cGVJZHMpPT09bnVsbHx8bj09PXZvaWQgMHx8bi5jbGVhcigpO2ZvcihsZXQgaSBvZiB0aGlzLmNoaWxkcmVuKWkuY2xlYXIoKTtyZXR1cm4gdGhpc319dmFyIEdlLFBuO3ZhciBnZT1tKCgpPT57bG4oKTtwaSgpO3hoKCk7YWUoKTtGUygpO2dzKCk7ZGUucHJvdG90eXBlLmxlbmd0aD0xO2RlLnByb3RvdHlwZS5zdHJpZGU9MTtkZS5wcm90b3R5cGUuY2hpbGRyZW49bnVsbDtkZS5wcm90b3R5cGUuZmluaXNoZWQ9ITE7ZGUucHJvdG90eXBlLm51bGxWYWx1ZXM9bnVsbDtkZS5wcm90b3R5cGUuX2lzVmFsaWQ9KCk9PiEwO0dlPWNsYXNzIEdlIGV4dGVuZHMgZGV7Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5fdmFsdWVzPW5ldyBKbyh0aGlzLkFycmF5VHlwZSwwLHRoaXMuc3RyaWRlKX1zZXRWYWx1ZSh0LGUpe2xldCByPXRoaXMuX3ZhbHVlcztyZXR1cm4gci5yZXNlcnZlKHQtci5sZW5ndGgrMSksc3VwZXIuc2V0VmFsdWUodCxlKX19O1BuPWNsYXNzIFBuIGV4dGVuZHMgZGV7Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5fcGVuZGluZ0xlbmd0aD0wLHRoaXMuX29mZnNldHM9bmV3IEZ1KHQudHlwZSl9c2V0VmFsdWUodCxlKXtsZXQgcj10aGlzLl9wZW5kaW5nfHwodGhpcy5fcGVuZGluZz1uZXcgTWFwKSxuPXIuZ2V0KHQpO24mJih0aGlzLl9wZW5kaW5nTGVuZ3RoLT1uLmxlbmd0aCksdGhpcy5fcGVuZGluZ0xlbmd0aCs9ZSBpbnN0YW5jZW9mIHpzP2VbS29dLmxlbmd0aDplLmxlbmd0aCxyLnNldCh0LGUpfXNldFZhbGlkKHQsZSl7aWYoIXN1cGVyLnNldFZhbGlkKHQsZSkpcmV0dXJuKHRoaXMuX3BlbmRpbmd8fCh0aGlzLl9wZW5kaW5nPW5ldyBNYXApKS5zZXQodCx2b2lkIDApLCExO3JldHVybiEwfWNsZWFyKCl7cmV0dXJuIHRoaXMuX3BlbmRpbmdMZW5ndGg9MCx0aGlzLl9wZW5kaW5nPXZvaWQgMCxzdXBlci5jbGVhcigpfWZsdXNoKCl7cmV0dXJuIHRoaXMuX2ZsdXNoKCksc3VwZXIuZmx1c2goKX1maW5pc2goKXtyZXR1cm4gdGhpcy5fZmx1c2goKSxzdXBlci5maW5pc2goKX1fZmx1c2goKXtsZXQgdD10aGlzLl9wZW5kaW5nLGU9dGhpcy5fcGVuZGluZ0xlbmd0aDtpZih0aGlzLl9wZW5kaW5nTGVuZ3RoPTAsdGhpcy5fcGVuZGluZz12b2lkIDAsdCYmdC5zaXplPjApdGhpcy5fZmx1c2hQZW5kaW5nKHQsZSk7cmV0dXJuIHRoaXN9fX0pO2NsYXNzIGlse2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9b2Zmc2V0KCl7cmV0dXJuIHRoaXMuYmIucmVhZEludDY0KHRoaXMuYmJfcG9zKX1tZXRhRGF0YUxlbmd0aCgpe3JldHVybiB0aGlzLmJiLnJlYWRJbnQzMih0aGlzLmJiX3Bvcys4KX1ib2R5TGVuZ3RoKCl7cmV0dXJuIHRoaXMuYmIucmVhZEludDY0KHRoaXMuYmJfcG9zKzE2KX1zdGF0aWMgc2l6ZU9mKCl7cmV0dXJuIDI0fXN0YXRpYyBjcmVhdGVCbG9jayh0LGUscixuKXtyZXR1cm4gdC5wcmVwKDgsMjQpLHQud3JpdGVJbnQ2NChCaWdJbnQobiE9PW51bGwmJm4hPT12b2lkIDA/bjowKSksdC5wYWQoNCksdC53cml0ZUludDMyKHIpLHQud3JpdGVJbnQ2NChCaWdJbnQoZSE9PW51bGwmJmUhPT12b2lkIDA/ZTowKSksdC5vZmZzZXQoKX19Y2xhc3MgdW57Y29uc3RydWN0b3IoKXt0aGlzLmJiPW51bGwsdGhpcy5iYl9wb3M9MH1fX2luaXQodCxlKXtyZXR1cm4gdGhpcy5iYl9wb3M9dCx0aGlzLmJiPWUsdGhpc31zdGF0aWMgZ2V0Um9vdEFzRm9vdGVyKHQsZSl7cmV0dXJuKGV8fG5ldyB1bikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNGb290ZXIodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTCksKGV8fG5ldyB1bikuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXZlcnNpb24oKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDQpO3JldHVybiB0P3RoaXMuYmIucmVhZEludDE2KHRoaXMuYmJfcG9zK3QpOkh0LlYxfXNjaGVtYSh0KXtsZXQgZT10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDYpO3JldHVybiBlPyh0fHxuZXcgRWUpLl9faW5pdCh0aGlzLmJiLl9faW5kaXJlY3QodGhpcy5iYl9wb3MrZSksdGhpcy5iYik6bnVsbH1kaWN0aW9uYXJpZXModCxlKXtsZXQgcj10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDgpO3JldHVybiByPyhlfHxuZXcgaWwpLl9faW5pdCh0aGlzLmJiLl9fdmVjdG9yKHRoaXMuYmJfcG9zK3IpK3QqMjQsdGhpcy5iYik6bnVsbH1kaWN0aW9uYXJpZXNMZW5ndGgoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDgpO3JldHVybiB0P3RoaXMuYmIuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zK3QpOjB9cmVjb3JkQmF0Y2hlcyh0LGUpe2xldCByPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsMTApO3JldHVybiByPyhlfHxuZXcgaWwpLl9faW5pdCh0aGlzLmJiLl9fdmVjdG9yKHRoaXMuYmJfcG9zK3IpK3QqMjQsdGhpcy5iYik6bnVsbH1yZWNvcmRCYXRjaGVzTGVuZ3RoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3BvcywxMCk7cmV0dXJuIHQ/dGhpcy5iYi5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MrdCk6MH1jdXN0b21NZXRhZGF0YSh0LGUpe2xldCByPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsMTIpO3JldHVybiByPyhlfHxuZXcgb2UpLl9faW5pdCh0aGlzLmJiLl9faW5kaXJlY3QodGhpcy5iYi5fX3ZlY3Rvcih0aGlzLmJiX3BvcytyKSt0KjQpLHRoaXMuYmIpOm51bGx9Y3VzdG9tTWV0YWRhdGFMZW5ndGgoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDEyKTtyZXR1cm4gdD90aGlzLmJiLl9fdmVjdG9yX2xlbih0aGlzLmJiX3Bvcyt0KTowfXN0YXRpYyBzdGFydEZvb3Rlcih0KXt0LnN0YXJ0T2JqZWN0KDUpfXN0YXRpYyBhZGRWZXJzaW9uKHQsZSl7dC5hZGRGaWVsZEludDE2KDAsZSxIdC5WMSl9c3RhdGljIGFkZFNjaGVtYSh0LGUpe3QuYWRkRmllbGRPZmZzZXQoMSxlLDApfXN0YXRpYyBhZGREaWN0aW9uYXJpZXModCxlKXt0LmFkZEZpZWxkT2Zmc2V0KDIsZSwwKX1zdGF0aWMgc3RhcnREaWN0aW9uYXJpZXNWZWN0b3IodCxlKXt0LnN0YXJ0VmVjdG9yKDI0LGUsOCl9c3RhdGljIGFkZFJlY29yZEJhdGNoZXModCxlKXt0LmFkZEZpZWxkT2Zmc2V0KDMsZSwwKX1zdGF0aWMgc3RhcnRSZWNvcmRCYXRjaGVzVmVjdG9yKHQsZSl7dC5zdGFydFZlY3RvcigyNCxlLDgpfXN0YXRpYyBhZGRDdXN0b21NZXRhZGF0YSh0LGUpe3QuYWRkRmllbGRPZmZzZXQoNCxlLDApfXN0YXRpYyBjcmVhdGVDdXN0b21NZXRhZGF0YVZlY3Rvcih0LGUpe3Quc3RhcnRWZWN0b3IoNCxlLmxlbmd0aCw0KTtmb3IobGV0IHI9ZS5sZW5ndGgtMTtyPj0wO3ItLSl0LmFkZE9mZnNldChlW3JdKTtyZXR1cm4gdC5lbmRWZWN0b3IoKX1zdGF0aWMgc3RhcnRDdXN0b21NZXRhZGF0YVZlY3Rvcih0LGUpe3Quc3RhcnRWZWN0b3IoNCxlLDQpfXN0YXRpYyBlbmRGb290ZXIodCl7cmV0dXJuIHQuZW5kT2JqZWN0KCl9c3RhdGljIGZpbmlzaEZvb3RlckJ1ZmZlcih0LGUpe3QuZmluaXNoKGUpfXN0YXRpYyBmaW5pc2hTaXplUHJlZml4ZWRGb290ZXJCdWZmZXIodCxlKXt0LmZpbmlzaChlLHZvaWQgMCwhMCl9fXZhciBMUz1tKCgpPT57RnQoKTskYygpO2loKCk7TF8oKX0pO2Z1bmN0aW9uIHpoKHQsZSl7cmV0dXJuIG5ldyBNYXAoWy4uLnR8fG5ldyBNYXAsLi4uZXx8bmV3IE1hcF0pfWZ1bmN0aW9uIG5nKHQsZT1uZXcgTWFwKXtmb3IobGV0IHI9LTEsbj10Lmxlbmd0aDsrK3I8bjspe2xldCBzPXRbcl0udHlwZTtpZihBLmlzRGljdGlvbmFyeShzKSl7aWYoIWUuaGFzKHMuaWQpKWUuc2V0KHMuaWQscy5kaWN0aW9uYXJ5KTtlbHNlIGlmKGUuZ2V0KHMuaWQpIT09cy5kaWN0aW9uYXJ5KXRocm93IEVycm9yKCJDYW5ub3QgY3JlYXRlIFNjaGVtYSBjb250YWluaW5nIHR3byBkaWZmZXJlbnQgZGljdGlvbmFyaWVzIHdpdGggdGhlIHNhbWUgSWQiKX1pZihzLmNoaWxkcmVuJiZzLmNoaWxkcmVuLmxlbmd0aD4wKW5nKHMuY2hpbGRyZW4sZSl9cmV0dXJuIGV9dmFyIFVTLFJTLGosVjt2YXIgJHI9bSgoKT0+e0NlKCk7YWUoKTtVUz1TeW1ib2wuZm9yKCJhcGFjaGUtYXJyb3cvU2NoZW1hIiksUlM9U3ltYm9sLmZvcigiYXBhY2hlLWFycm93L0ZpZWxkIik7aj1jbGFzcyBqe3N0YXRpYyBpc1NjaGVtYSh0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnRbVVNdKT09PSEwfWNvbnN0cnVjdG9yKHQ9W10sZSxyLG49SHQuVjUpe2lmKHRoaXMuZmllbGRzPXR8fFtdLHRoaXMubWV0YWRhdGE9ZXx8bmV3IE1hcCwhcilyPW5nKHRoaXMuZmllbGRzKTt0aGlzLmRpY3Rpb25hcmllcz1yLHRoaXMubWV0YWRhdGFWZXJzaW9uPW59Z2V0W1N5bWJvbC50b1N0cmluZ1RhZ10oKXtyZXR1cm4iU2NoZW1hIn1nZXQgbmFtZXMoKXtyZXR1cm4gdGhpcy5maWVsZHMubWFwKCh0KT0+dC5uYW1lKX10b1N0cmluZygpe3JldHVybmBTY2hlbWE8eyAke3RoaXMuZmllbGRzLm1hcCgodCxlKT0+YCR7ZX06ICR7dH1gKS5qb2luKCIsICIpfSB9PmB9c2VsZWN0KHQpe2xldCBlPW5ldyBTZXQodCkscj10aGlzLmZpZWxkcy5maWx0ZXIoKG4pPT5lLmhhcyhuLm5hbWUpKTtyZXR1cm4gbmV3IGoocix0aGlzLm1ldGFkYXRhKX1zZWxlY3RBdCh0KXtsZXQgZT10Lm1hcCgocik9PnRoaXMuZmllbGRzW3JdKS5maWx0ZXIoQm9vbGVhbik7cmV0dXJuIG5ldyBqKGUsdGhpcy5tZXRhZGF0YSl9YXNzaWduKC4uLnQpe2xldCBlPXRbMF1pbnN0YW5jZW9mIGo/dFswXTpBcnJheS5pc0FycmF5KHRbMF0pP25ldyBqKHRbMF0pOm5ldyBqKHQpLHI9Wy4uLnRoaXMuZmllbGRzXSxuPXpoKHpoKG5ldyBNYXAsdGhpcy5tZXRhZGF0YSksZS5tZXRhZGF0YSksaT1lLmZpZWxkcy5maWx0ZXIoKG8pPT57bGV0IGE9ci5maW5kSW5kZXgoKGwpPT5sLm5hbWU9PT1vLm5hbWUpO3JldHVybn5hPyhyW2FdPW8uY2xvbmUoe21ldGFkYXRhOnpoKHpoKG5ldyBNYXAsclthXS5tZXRhZGF0YSksby5tZXRhZGF0YSl9KSkmJiExOiEwfSkscz1uZyhpLG5ldyBNYXApO3JldHVybiBuZXcgaihbLi4uciwuLi5pXSxuLG5ldyBNYXAoWy4uLnRoaXMuZGljdGlvbmFyaWVzLC4uLnNdKSl9fTtqLnByb3RvdHlwZS5maWVsZHM9bnVsbDtqLnByb3RvdHlwZS5tZXRhZGF0YT1udWxsO2oucHJvdG90eXBlLmRpY3Rpb25hcmllcz1udWxsO2oucHJvdG90eXBlW1VTXT0hMDtPYmplY3QuZGVmaW5lUHJvcGVydHkoaixTeW1ib2wuaGFzSW5zdGFuY2Use3ZhbHVlOmZ1bmN0aW9uKGUpe3JldHVybiBGdW5jdGlvbi5wcm90b3R5cGVbU3ltYm9sLmhhc0luc3RhbmNlXS5jYWxsKHRoaXMsZSl8fHRoaXM9PT1qJiZqLmlzU2NoZW1hKGUpfX0pO1Y9Y2xhc3MgVntzdGF0aWMgaXNGaWVsZCh0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnRbUlNdKT09PSEwfXN0YXRpYyBuZXcoLi4udCl7bGV0W2UscixuLGldPXQ7aWYodFswXSYmdHlwZW9mIHRbMF09PT0ib2JqZWN0Iikoe25hbWU6ZX09dFswXSkscj09PXZvaWQgMCYmKHI9dFswXS50eXBlKSxuPT09dm9pZCAwJiYobj10WzBdLm51bGxhYmxlKSxpPT09dm9pZCAwJiYoaT10WzBdLm1ldGFkYXRhKTtyZXR1cm4gbmV3IFYoYCR7ZX1gLHIsbixpKX1jb25zdHJ1Y3Rvcih0LGUscj0hMSxuKXt0aGlzLm5hbWU9dCx0aGlzLnR5cGU9ZSx0aGlzLm51bGxhYmxlPXIsdGhpcy5tZXRhZGF0YT1ufHxuZXcgTWFwfWdldCB0eXBlSWQoKXtyZXR1cm4gdGhpcy50eXBlLnR5cGVJZH1nZXRbU3ltYm9sLnRvU3RyaW5nVGFnXSgpe3JldHVybiJGaWVsZCJ9dG9TdHJpbmcoKXtyZXR1cm5gJHt0aGlzLm5hbWV9OiAke3RoaXMudHlwZX1gfWNsb25lKC4uLnQpe2xldFtlLHIsbixpXT10O3JldHVybiF0WzBdfHx0eXBlb2YgdFswXSE9PSJvYmplY3QiP1tlPXRoaXMubmFtZSxyPXRoaXMudHlwZSxuPXRoaXMubnVsbGFibGUsaT10aGlzLm1ldGFkYXRhXT10OntuYW1lOmU9dGhpcy5uYW1lLHR5cGU6cj10aGlzLnR5cGUsbnVsbGFibGU6bj10aGlzLm51bGxhYmxlLG1ldGFkYXRhOmk9dGhpcy5tZXRhZGF0YX09dFswXSxWLm5ldyhlLHIsbixpKX19O1YucHJvdG90eXBlLnR5cGU9bnVsbDtWLnByb3RvdHlwZS5uYW1lPW51bGw7Vi5wcm90b3R5cGUubnVsbGFibGU9bnVsbDtWLnByb3RvdHlwZS5tZXRhZGF0YT1udWxsO1YucHJvdG90eXBlW1JTXT0hMDtPYmplY3QuZGVmaW5lUHJvcGVydHkoVixTeW1ib2wuaGFzSW5zdGFuY2Use3ZhbHVlOmZ1bmN0aW9uKGUpe3JldHVybiBGdW5jdGlvbi5wcm90b3R5cGVbU3ltYm9sLmhhc0luc3RhbmNlXS5jYWxsKHRoaXMsZSl8fHRoaXM9PT1WJiZWLmlzRmllbGQoZSl9fSl9KTtjbGFzcyBYb3tzdGF0aWMgZGVjb2RlKHQpe3Q9bmV3IEgxKGsodCkpO2xldCBlPXVuLmdldFJvb3RBc0Zvb3Rlcih0KSxyPWouZGVjb2RlKGUuc2NoZW1hKCksbmV3IE1hcCxlLnZlcnNpb24oKSk7cmV0dXJuIG5ldyBDUyhyLGUpfXN0YXRpYyBlbmNvZGUodCl7bGV0IGU9bmV3IFcxLHI9ai5lbmNvZGUoZSx0LnNjaGVtYSk7dW4uc3RhcnRSZWNvcmRCYXRjaGVzVmVjdG9yKGUsdC5udW1SZWNvcmRCYXRjaGVzKTtmb3IobGV0IHMgb2ZbLi4udC5yZWNvcmRCYXRjaGVzKCldLnNsaWNlKCkucmV2ZXJzZSgpKWpzLmVuY29kZShlLHMpO2xldCBuPWUuZW5kVmVjdG9yKCk7dW4uc3RhcnREaWN0aW9uYXJpZXNWZWN0b3IoZSx0Lm51bURpY3Rpb25hcmllcyk7Zm9yKGxldCBzIG9mWy4uLnQuZGljdGlvbmFyeUJhdGNoZXMoKV0uc2xpY2UoKS5yZXZlcnNlKCkpanMuZW5jb2RlKGUscyk7bGV0IGk9ZS5lbmRWZWN0b3IoKTtyZXR1cm4gdW4uc3RhcnRGb290ZXIoZSksdW4uYWRkU2NoZW1hKGUsciksdW4uYWRkVmVyc2lvbihlLEh0LlY1KSx1bi5hZGRSZWNvcmRCYXRjaGVzKGUsbiksdW4uYWRkRGljdGlvbmFyaWVzKGUsaSksdW4uZmluaXNoRm9vdGVyQnVmZmVyKGUsdW4uZW5kRm9vdGVyKGUpKSxlLmFzVWludDhBcnJheSgpfWdldCBudW1SZWNvcmRCYXRjaGVzKCl7cmV0dXJuIHRoaXMuX3JlY29yZEJhdGNoZXMubGVuZ3RofWdldCBudW1EaWN0aW9uYXJpZXMoKXtyZXR1cm4gdGhpcy5fZGljdGlvbmFyeUJhdGNoZXMubGVuZ3RofWNvbnN0cnVjdG9yKHQsZT1IdC5WNSxyLG4pe3RoaXMuc2NoZW1hPXQsdGhpcy52ZXJzaW9uPWUsciYmKHRoaXMuX3JlY29yZEJhdGNoZXM9ciksbiYmKHRoaXMuX2RpY3Rpb25hcnlCYXRjaGVzPW4pfSpyZWNvcmRCYXRjaGVzKCl7Zm9yKGxldCB0LGU9LTEscj10aGlzLm51bVJlY29yZEJhdGNoZXM7KytlPHI7KWlmKHQ9dGhpcy5nZXRSZWNvcmRCYXRjaChlKSl5aWVsZCB0fSpkaWN0aW9uYXJ5QmF0Y2hlcygpe2ZvcihsZXQgdCxlPS0xLHI9dGhpcy5udW1EaWN0aW9uYXJpZXM7KytlPHI7KWlmKHQ9dGhpcy5nZXREaWN0aW9uYXJ5QmF0Y2goZSkpeWllbGQgdH1nZXRSZWNvcmRCYXRjaCh0KXtyZXR1cm4gdD49MCYmdDx0aGlzLm51bVJlY29yZEJhdGNoZXMmJnRoaXMuX3JlY29yZEJhdGNoZXNbdF18fG51bGx9Z2V0RGljdGlvbmFyeUJhdGNoKHQpe3JldHVybiB0Pj0wJiZ0PHRoaXMubnVtRGljdGlvbmFyaWVzJiZ0aGlzLl9kaWN0aW9uYXJ5QmF0Y2hlc1t0XXx8bnVsbH19Y2xhc3MganN7c3RhdGljIGRlY29kZSh0KXtyZXR1cm4gbmV3IGpzKHQubWV0YURhdGFMZW5ndGgoKSx0LmJvZHlMZW5ndGgoKSx0Lm9mZnNldCgpKX1zdGF0aWMgZW5jb2RlKHQsZSl7bGV0e21ldGFEYXRhTGVuZ3RoOnJ9PWUsbj1CaWdJbnQoZS5vZmZzZXQpLGk9QmlnSW50KGUuYm9keUxlbmd0aCk7cmV0dXJuIGlsLmNyZWF0ZUJsb2NrKHQsbixyLGkpfWNvbnN0cnVjdG9yKHQsZSxyKXt0aGlzLm1ldGFEYXRhTGVuZ3RoPXQsdGhpcy5vZmZzZXQ9VnQociksdGhpcy5ib2R5TGVuZ3RoPVZ0KGUpfX12YXIgVzEsSDEsQ1M7dmFyIGlnPW0oKCk9PntMUygpO0Z0KCk7JHIoKTtDZSgpO1llKCk7VzE9VGEsSDE9bXI7Q1M9Y2xhc3MgQ1MgZXh0ZW5kcyBYb3tnZXQgbnVtUmVjb3JkQmF0Y2hlcygpe3JldHVybiB0aGlzLl9mb290ZXIucmVjb3JkQmF0Y2hlc0xlbmd0aCgpfWdldCBudW1EaWN0aW9uYXJpZXMoKXtyZXR1cm4gdGhpcy5fZm9vdGVyLmRpY3Rpb25hcmllc0xlbmd0aCgpfWNvbnN0cnVjdG9yKHQsZSl7c3VwZXIodCxlLnZlcnNpb24oKSk7dGhpcy5fZm9vdGVyPWV9Z2V0UmVjb3JkQmF0Y2godCl7aWYodD49MCYmdDx0aGlzLm51bVJlY29yZEJhdGNoZXMpe2xldCBlPXRoaXMuX2Zvb3Rlci5yZWNvcmRCYXRjaGVzKHQpO2lmKGUpcmV0dXJuIGpzLmRlY29kZShlKX1yZXR1cm4gbnVsbH1nZXREaWN0aW9uYXJ5QmF0Y2godCl7aWYodD49MCYmdDx0aGlzLm51bURpY3Rpb25hcmllcyl7bGV0IGU9dGhpcy5fZm9vdGVyLmRpY3Rpb25hcmllcyh0KTtpZihlKXJldHVybiBqcy5kZWNvZGUoZSl9cmV0dXJuIG51bGx9fX0pO2NsYXNzIE9le2NvbnN0cnVjdG9yKCl7dGhpcy5iYj1udWxsLHRoaXMuYmJfcG9zPTB9X19pbml0KHQsZSl7cmV0dXJuIHRoaXMuYmJfcG9zPXQsdGhpcy5iYj1lLHRoaXN9c3RhdGljIGdldFJvb3RBc01lc3NhZ2UodCxlKXtyZXR1cm4oZXx8bmV3IE9lKS5fX2luaXQodC5yZWFkSW50MzIodC5wb3NpdGlvbigpKSt0LnBvc2l0aW9uKCksdCl9c3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc01lc3NhZ2UodCxlKXtyZXR1cm4gdC5zZXRQb3NpdGlvbih0LnBvc2l0aW9uKCkrTCksKGV8fG5ldyBPZSkuX19pbml0KHQucmVhZEludDMyKHQucG9zaXRpb24oKSkrdC5wb3NpdGlvbigpLHQpfXZlcnNpb24oKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDQpO3JldHVybiB0P3RoaXMuYmIucmVhZEludDE2KHRoaXMuYmJfcG9zK3QpOkh0LlYxfWhlYWRlclR5cGUoKXtsZXQgdD10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDYpO3JldHVybiB0P3RoaXMuYmIucmVhZFVpbnQ4KHRoaXMuYmJfcG9zK3QpOlR0Lk5PTkV9aGVhZGVyKHQpe2xldCBlPXRoaXMuYmIuX19vZmZzZXQodGhpcy5iYl9wb3MsOCk7cmV0dXJuIGU/dGhpcy5iYi5fX3VuaW9uKHQsdGhpcy5iYl9wb3MrZSk6bnVsbH1ib2R5TGVuZ3RoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3BvcywxMCk7cmV0dXJuIHQ/dGhpcy5iYi5yZWFkSW50NjQodGhpcy5iYl9wb3MrdCk6QmlnSW50KCIwIil9Y3VzdG9tTWV0YWRhdGEodCxlKXtsZXQgcj10aGlzLmJiLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLDEyKTtyZXR1cm4gcj8oZXx8bmV3IG9lKS5fX2luaXQodGhpcy5iYi5fX2luZGlyZWN0KHRoaXMuYmIuX192ZWN0b3IodGhpcy5iYl9wb3MrcikrdCo0KSx0aGlzLmJiKTpudWxsfWN1c3RvbU1ldGFkYXRhTGVuZ3RoKCl7bGV0IHQ9dGhpcy5iYi5fX29mZnNldCh0aGlzLmJiX3BvcywxMik7cmV0dXJuIHQ/dGhpcy5iYi5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MrdCk6MH1zdGF0aWMgc3RhcnRNZXNzYWdlKHQpe3Quc3RhcnRPYmplY3QoNSl9c3RhdGljIGFkZFZlcnNpb24odCxlKXt0LmFkZEZpZWxkSW50MTYoMCxlLEh0LlYxKX1zdGF0aWMgYWRkSGVhZGVyVHlwZSh0LGUpe3QuYWRkRmllbGRJbnQ4KDEsZSxUdC5OT05FKX1zdGF0aWMgYWRkSGVhZGVyKHQsZSl7dC5hZGRGaWVsZE9mZnNldCgyLGUsMCl9c3RhdGljIGFkZEJvZHlMZW5ndGgodCxlKXt0LmFkZEZpZWxkSW50NjQoMyxlLEJpZ0ludCgiMCIpKX1zdGF0aWMgYWRkQ3VzdG9tTWV0YWRhdGEodCxlKXt0LmFkZEZpZWxkT2Zmc2V0KDQsZSwwKX1zdGF0aWMgY3JlYXRlQ3VzdG9tTWV0YWRhdGFWZWN0b3IodCxlKXt0LnN0YXJ0VmVjdG9yKDQsZS5sZW5ndGgsNCk7Zm9yKGxldCByPWUubGVuZ3RoLTE7cj49MDtyLS0pdC5hZGRPZmZzZXQoZVtyXSk7cmV0dXJuIHQuZW5kVmVjdG9yKCl9c3RhdGljIHN0YXJ0Q3VzdG9tTWV0YWRhdGFWZWN0b3IodCxlKXt0LnN0YXJ0VmVjdG9yKDQsZSw0KX1zdGF0aWMgZW5kTWVzc2FnZSh0KXtyZXR1cm4gdC5lbmRPYmplY3QoKX1zdGF0aWMgZmluaXNoTWVzc2FnZUJ1ZmZlcih0LGUpe3QuZmluaXNoKGUpfXN0YXRpYyBmaW5pc2hTaXplUHJlZml4ZWRNZXNzYWdlQnVmZmVyKHQsZSl7dC5maW5pc2goZSx2b2lkIDAsITApfXN0YXRpYyBjcmVhdGVNZXNzYWdlKHQsZSxyLG4saSxzKXtyZXR1cm4gT2Uuc3RhcnRNZXNzYWdlKHQpLE9lLmFkZFZlcnNpb24odCxlKSxPZS5hZGRIZWFkZXJUeXBlKHQsciksT2UuYWRkSGVhZGVyKHQsbiksT2UuYWRkQm9keUxlbmd0aCh0LGkpLE9lLmFkZEN1c3RvbU1ldGFkYXRhKHQscyksT2UuZW5kTWVzc2FnZSh0KX19dmFyIFBTPW0oKCk9PntGdCgpOyRjKCk7VV8oKTtpaCgpfSk7dmFyIGtTLGpoO3ZhciBWUz1tKCgpPT57UWkoKTtuQigpO2FoKCk7RF8oKTtYSSgpO1pJKCk7dEIoKTtRSSgpO3NCKCk7b0IoKTtlQigpO0lfKCk7dl8oKTtFXygpO09fKCk7eF8oKTtCXygpO3JCKCk7aUIoKTtOXygpO3dfKCk7U18oKTtBXygpO1RfKCk7a1M9Y2xhc3Mga1MgZXh0ZW5kcyBzdHt2aXNpdCh0LGUpe3JldHVybiB0PT1udWxsfHxlPT1udWxsP3ZvaWQgMDpzdXBlci52aXNpdCh0LGUpfXZpc2l0TnVsbCh0LGUpe3JldHVybiAkby5zdGFydE51bGwoZSksJG8uZW5kTnVsbChlKX12aXNpdEludCh0LGUpe3JldHVybiBBci5zdGFydEludChlKSxBci5hZGRCaXRXaWR0aChlLHQuYml0V2lkdGgpLEFyLmFkZElzU2lnbmVkKGUsdC5pc1NpZ25lZCksQXIuZW5kSW50KGUpfXZpc2l0RmxvYXQodCxlKXtyZXR1cm4gYWkuc3RhcnRGbG9hdGluZ1BvaW50KGUpLGFpLmFkZFByZWNpc2lvbihlLHQucHJlY2lzaW9uKSxhaS5lbmRGbG9hdGluZ1BvaW50KGUpfXZpc2l0QmluYXJ5KHQsZSl7cmV0dXJuIENvLnN0YXJ0QmluYXJ5KGUpLENvLmVuZEJpbmFyeShlKX12aXNpdEJpbmFyeVZpZXcodCxlKXtyZXR1cm4gUG8uc3RhcnRCaW5hcnlWaWV3KGUpLFBvLmVuZEJpbmFyeVZpZXcoZSl9dmlzaXRMYXJnZUJpbmFyeSh0LGUpe3JldHVybiBWby5zdGFydExhcmdlQmluYXJ5KGUpLFZvLmVuZExhcmdlQmluYXJ5KGUpfXZpc2l0Qm9vbCh0LGUpe3JldHVybiBrby5zdGFydEJvb2woZSksa28uZW5kQm9vbChlKX12aXNpdFV0ZjgodCxlKXtyZXR1cm4gV28uc3RhcnRVdGY4KGUpLFdvLmVuZFV0ZjgoZSl9dmlzaXRVdGY4Vmlldyh0LGUpe3JldHVybiBIby5zdGFydFV0ZjhWaWV3KGUpLEhvLmVuZFV0ZjhWaWV3KGUpfXZpc2l0TGFyZ2VVdGY4KHQsZSl7cmV0dXJuIHpvLnN0YXJ0TGFyZ2VVdGY4KGUpLHpvLmVuZExhcmdlVXRmOChlKX12aXNpdERlY2ltYWwodCxlKXtyZXR1cm4gRHIuc3RhcnREZWNpbWFsKGUpLERyLmFkZFNjYWxlKGUsdC5zY2FsZSksRHIuYWRkUHJlY2lzaW9uKGUsdC5wcmVjaXNpb24pLERyLmFkZEJpdFdpZHRoKGUsdC5iaXRXaWR0aCksRHIuZW5kRGVjaW1hbChlKX12aXNpdERhdGUodCxlKXtyZXR1cm4gbmkuc3RhcnREYXRlKGUpLG5pLmFkZFVuaXQoZSx0LnVuaXQpLG5pLmVuZERhdGUoZSl9dmlzaXRUaW1lKHQsZSl7cmV0dXJuIHJuLnN0YXJ0VGltZShlKSxybi5hZGRVbml0KGUsdC51bml0KSxybi5hZGRCaXRXaWR0aChlLHQuYml0V2lkdGgpLHJuLmVuZFRpbWUoZSl9dmlzaXRUaW1lc3RhbXAodCxlKXtsZXQgcj10LnRpbWV6b25lJiZlLmNyZWF0ZVN0cmluZyh0LnRpbWV6b25lKXx8dm9pZCAwO2lmKG5uLnN0YXJ0VGltZXN0YW1wKGUpLG5uLmFkZFVuaXQoZSx0LnVuaXQpLHIhPT12b2lkIDApbm4uYWRkVGltZXpvbmUoZSxyKTtyZXR1cm4gbm4uZW5kVGltZXN0YW1wKGUpfXZpc2l0SW50ZXJ2YWwodCxlKXtyZXR1cm4gY2kuc3RhcnRJbnRlcnZhbChlKSxjaS5hZGRVbml0KGUsdC51bml0KSxjaS5lbmRJbnRlcnZhbChlKX12aXNpdER1cmF0aW9uKHQsZSl7cmV0dXJuIGlpLnN0YXJ0RHVyYXRpb24oZSksaWkuYWRkVW5pdChlLHQudW5pdCksaWkuZW5kRHVyYXRpb24oZSl9dmlzaXRMaXN0KHQsZSl7cmV0dXJuIGpvLnN0YXJ0TGlzdChlKSxqby5lbmRMaXN0KGUpfXZpc2l0U3RydWN0KHQsZSl7cmV0dXJuIHFvLnN0YXJ0U3RydWN0XyhlKSxxby5lbmRTdHJ1Y3RfKGUpfXZpc2l0VW5pb24odCxlKXt4ci5zdGFydFR5cGVJZHNWZWN0b3IoZSx0LnR5cGVJZHMubGVuZ3RoKTtsZXQgcj14ci5jcmVhdGVUeXBlSWRzVmVjdG9yKGUsdC50eXBlSWRzKTtyZXR1cm4geHIuc3RhcnRVbmlvbihlKSx4ci5hZGRNb2RlKGUsdC5tb2RlKSx4ci5hZGRUeXBlSWRzKGUscikseHIuZW5kVW5pb24oZSl9dmlzaXREaWN0aW9uYXJ5KHQsZSl7bGV0IHI9dGhpcy52aXNpdCh0LmluZGljZXMsZSk7aWYoWWkuc3RhcnREaWN0aW9uYXJ5RW5jb2RpbmcoZSksWWkuYWRkSWQoZSxCaWdJbnQodC5pZCkpLFlpLmFkZElzT3JkZXJlZChlLHQuaXNPcmRlcmVkKSxyIT09dm9pZCAwKVlpLmFkZEluZGV4VHlwZShlLHIpO3JldHVybiBZaS5lbmREaWN0aW9uYXJ5RW5jb2RpbmcoZSl9dmlzaXRGaXhlZFNpemVCaW5hcnkodCxlKXtyZXR1cm4gc2kuc3RhcnRGaXhlZFNpemVCaW5hcnkoZSksc2kuYWRkQnl0ZVdpZHRoKGUsdC5ieXRlV2lkdGgpLHNpLmVuZEZpeGVkU2l6ZUJpbmFyeShlKX12aXNpdEZpeGVkU2l6ZUxpc3QodCxlKXtyZXR1cm4gb2kuc3RhcnRGaXhlZFNpemVMaXN0KGUpLG9pLmFkZExpc3RTaXplKGUsdC5saXN0U2l6ZSksb2kuZW5kRml4ZWRTaXplTGlzdChlKX12aXNpdE1hcCh0LGUpe3JldHVybiBsaS5zdGFydE1hcChlKSxsaS5hZGRLZXlzU29ydGVkKGUsdC5rZXlzU29ydGVkKSxsaS5lbmRNYXAoZSl9fTtqaD1uZXcga1N9KTtmdW5jdGlvbiBxUyh0LGU9bmV3IE1hcCl7cmV0dXJuIG5ldyBqKFkxKHQsZSksJGgodC5tZXRhZGF0YSksZSl9ZnVuY3Rpb24gc2codCl7cmV0dXJuIG5ldyBKZSh0LmNvdW50LEhTKHQuY29sdW1ucyksWVModC5jb2x1bW5zKSxudWxsLEtTKHQuY29sdW1ucykpfWZ1bmN0aW9uIFdTKHQpe3JldHVybiBuZXcgcXIoc2codC5kYXRhKSx0LmlkLHQuaXNEZWx0YSl9ZnVuY3Rpb24gWTEodCxlKXtyZXR1cm4odC5maWVsZHN8fFtdKS5maWx0ZXIoQm9vbGVhbikubWFwKChyKT0+Vi5mcm9tSlNPTihyLGUpKX1mdW5jdGlvbiB6Uyh0LGUpe3JldHVybih0LmNoaWxkcmVufHxbXSkuZmlsdGVyKEJvb2xlYW4pLm1hcCgocik9PlYuZnJvbUpTT04ocixlKSl9ZnVuY3Rpb24gSFModCl7cmV0dXJuKHR8fFtdKS5yZWR1Y2UoKGUscik9PlsuLi5lLG5ldyBlcyhyLmNvdW50LEsxKHIuVkFMSURJVFkpKSwuLi5IUyhyLmNoaWxkcmVuKV0sW10pfWZ1bmN0aW9uIFlTKHQsZT1bXSl7Zm9yKGxldCByPS0xLG49KHR8fFtdKS5sZW5ndGg7KytyPG47KXtsZXQgaT10W3JdO2lmKGkuVkFMSURJVFkmJmUucHVzaChuZXcgTmUoZS5sZW5ndGgsaS5WQUxJRElUWS5sZW5ndGgpKSxpLlRZUEVfSUQmJmUucHVzaChuZXcgTmUoZS5sZW5ndGgsaS5UWVBFX0lELmxlbmd0aCkpLGkuT0ZGU0VUJiZlLnB1c2gobmV3IE5lKGUubGVuZ3RoLGkuT0ZGU0VULmxlbmd0aCkpLGkuREFUQSYmZS5wdXNoKG5ldyBOZShlLmxlbmd0aCxpLkRBVEEubGVuZ3RoKSksaS5WSUVXUyYmZS5wdXNoKG5ldyBOZShlLmxlbmd0aCxpLlZJRVdTLmxlbmd0aCkpLGkuVkFSSUFESUNfREFUQV9CVUZGRVJTKWZvcihsZXQgcyBvZiBpLlZBUklBRElDX0RBVEFfQlVGRkVSUyllLnB1c2gobmV3IE5lKGUubGVuZ3RoLHMubGVuZ3RoKSk7ZT1ZUyhpLmNoaWxkcmVuLGUpfXJldHVybiBlfWZ1bmN0aW9uIEsxKHQpe3JldHVybih0fHxbXSkucmVkdWNlKChlLHIpPT5lKyArKHI9PT0wKSwwKX1mdW5jdGlvbiBLUyh0KXtyZXR1cm4odHx8W10pLnJlZHVjZSgoZSxyKT0+Wy4uLmUsLi4uci5WQVJJQURJQ19EQVRBX0JVRkZFUlM/W3IuVkFSSUFESUNfREFUQV9CVUZGRVJTLmxlbmd0aF06W10sLi4uS1Moci5jaGlsZHJlbildLFtdKX1mdW5jdGlvbiBHUyh0LGUpe2xldCByLG4saSxzLG8sYTtpZighZXx8IShzPXQuZGljdGlvbmFyeSkpbz0kUyh0LHpTKHQsZSkpLGk9bmV3IFYodC5uYW1lLG8sdC5udWxsYWJsZSwkaCh0Lm1ldGFkYXRhKSk7ZWxzZSBpZighZS5oYXMocj1zLmlkKSluPShuPXMuaW5kZXhUeXBlKT9qUyhuKTpuZXcganIsZS5zZXQocixvPSRTKHQselModCxlKSkpLGE9bmV3IEVyKG8sbixyLHMuaXNPcmRlcmVkKSxpPW5ldyBWKHQubmFtZSxhLHQubnVsbGFibGUsJGgodC5tZXRhZGF0YSkpO2Vsc2Ugbj0obj1zLmluZGV4VHlwZSk/alMobik6bmV3IGpyLGE9bmV3IEVyKGUuZ2V0KHIpLG4scixzLmlzT3JkZXJlZCksaT1uZXcgVih0Lm5hbWUsYSx0Lm51bGxhYmxlLCRoKHQubWV0YWRhdGEpKTtyZXR1cm4gaXx8bnVsbH1mdW5jdGlvbiAkaCh0PVtdKXtyZXR1cm4gbmV3IE1hcCh0Lm1hcCgoe2tleTplLHZhbHVlOnJ9KT0+W2Uscl0pKX1mdW5jdGlvbiBqUyh0KXtyZXR1cm4gbmV3IEtlKHQuaXNTaWduZWQsdC5iaXRXaWR0aCl9ZnVuY3Rpb24gJFModCxlKXtsZXQgcj10LnR5cGUubmFtZTtzd2l0Y2gocil7Y2FzZSJOT05FIjpyZXR1cm4gbmV3IG5yO2Nhc2UibnVsbCI6cmV0dXJuIG5ldyBucjtjYXNlImJpbmFyeSI6cmV0dXJuIG5ldyBmaTtjYXNlImxhcmdlYmluYXJ5IjpyZXR1cm4gbmV3IHBzO2Nhc2UiYmluYXJ5dmlldyI6cmV0dXJuIG5ldyBidDtjYXNlInV0ZjgiOnJldHVybiBuZXcgVHI7Y2FzZSJsYXJnZXV0ZjgiOnJldHVybiBuZXcgbXM7Y2FzZSJ1dGY4dmlldyI6cmV0dXJuIG5ldyBMbjtjYXNlImJvb2wiOnJldHVybiBuZXcgb247Y2FzZSJsaXN0IjpyZXR1cm4gbmV3IGFuKChlfHxbXSlbMF0pO2Nhc2Uic3RydWN0IjpyZXR1cm4gbmV3IE90KGV8fFtdKTtjYXNlInN0cnVjdF8iOnJldHVybiBuZXcgT3QoZXx8W10pfXN3aXRjaChyKXtjYXNlImludCI6e2xldCBuPXQudHlwZTtyZXR1cm4gbmV3IEtlKG4uaXNTaWduZWQsbi5iaXRXaWR0aCl9Y2FzZSJmbG9hdGluZ3BvaW50Ijp7bGV0IG49dC50eXBlO3JldHVybiBuZXcgdWkocmVbbi5wcmVjaXNpb25dKX1jYXNlImRlY2ltYWwiOntsZXQgbj10LnR5cGU7cmV0dXJuIG5ldyB5cyhuLnNjYWxlLG4ucHJlY2lzaW9uLG4uYml0V2lkdGgpfWNhc2UiZGF0ZSI6e2xldCBuPXQudHlwZTtyZXR1cm4gbmV3IFJzKEllW24udW5pdF0pfWNhc2UidGltZSI6e2xldCBuPXQudHlwZTtyZXR1cm4gbmV3IENzKFJbbi51bml0XSxuLmJpdFdpZHRoKX1jYXNlInRpbWVzdGFtcCI6e2xldCBuPXQudHlwZTtyZXR1cm4gbmV3IGRpKFJbbi51bml0XSxuLnRpbWV6b25lKX1jYXNlImludGVydmFsIjp7bGV0IG49dC50eXBlO3JldHVybiBuZXcgUHMoY2Vbbi51bml0XSl9Y2FzZSJkdXJhdGlvbiI6e2xldCBuPXQudHlwZTtyZXR1cm4gbmV3IGtzKFJbbi51bml0XSl9Y2FzZSJ1bmlvbiI6e2xldCBuPXQudHlwZSxbaSwuLi5zXT0obi5tb2RlKyIiKS50b0xvd2VyQ2FzZSgpLG89aS50b1VwcGVyQ2FzZSgpK3Muam9pbigiIik7cmV0dXJuIG5ldyBKaShzZVtvXSxuLnR5cGVJZHN8fFtdLGV8fFtdKX1jYXNlImZpeGVkc2l6ZWJpbmFyeSI6e2xldCBuPXQudHlwZTtyZXR1cm4gbmV3IF9zKG4uYnl0ZVdpZHRoKX1jYXNlImZpeGVkc2l6ZWxpc3QiOntsZXQgbj10LnR5cGU7cmV0dXJuIG5ldyBYaShuLmxpc3RTaXplLChlfHxbXSlbMF0pfWNhc2UibWFwIjp7bGV0IG49dC50eXBlO3JldHVybiBuZXcgaGkoKGV8fFtdKVswXSxuLmtleXNTb3J0ZWQpfX10aHJvdyBFcnJvcihgVW5yZWNvZ25pemVkIHR5cGU6ICIke3J9ImApfXZhciBKUz1tKCgpPT57JHIoKTthZSgpO3FhKCk7Q2UoKX0pO2NsYXNzIGlye3N0YXRpYyBmcm9tSlNPTih0LGUpe2xldCByPW5ldyBpcigwLEh0LlY1LGUpO3JldHVybiByLl9jcmVhdGVIZWFkZXI9WDEodCxlKSxyfXN0YXRpYyBkZWNvZGUodCl7dD1uZXcgSjEoayh0KSk7bGV0IGU9T2UuZ2V0Um9vdEFzTWVzc2FnZSh0KSxyPWUuYm9keUxlbmd0aCgpLG49ZS52ZXJzaW9uKCksaT1lLmhlYWRlclR5cGUoKSxzPWxNKGUpLG89bmV3IGlyKHIsbixpLHZvaWQgMCxzKTtyZXR1cm4gby5fY3JlYXRlSGVhZGVyPVoxKGUsaSksb31zdGF0aWMgZW5jb2RlKHQpe2xldCBlPW5ldyBHMSxyPS0xO2lmKHQuaXNTY2hlbWEoKSlyPWouZW5jb2RlKGUsdC5oZWFkZXIoKSk7ZWxzZSBpZih0LmlzUmVjb3JkQmF0Y2goKSlyPUplLmVuY29kZShlLHQuaGVhZGVyKCkpO2Vsc2UgaWYodC5pc0RpY3Rpb25hcnlCYXRjaCgpKXI9cXIuZW5jb2RlKGUsdC5oZWFkZXIoKSk7bGV0IG49ISh0Lm1ldGFkYXRhJiZ0Lm1ldGFkYXRhLnNpemU+MCk/LTE6T2UuY3JlYXRlQ3VzdG9tTWV0YWRhdGFWZWN0b3IoZSxbLi4udC5tZXRhZGF0YV0ubWFwKChbaSxzXSk9PntsZXQgbz1lLmNyZWF0ZVN0cmluZyhgJHtpfWApLGE9ZS5jcmVhdGVTdHJpbmcoYCR7c31gKTtyZXR1cm4gb2Uuc3RhcnRLZXlWYWx1ZShlKSxvZS5hZGRLZXkoZSxvKSxvZS5hZGRWYWx1ZShlLGEpLG9lLmVuZEtleVZhbHVlKGUpfSkpO2lmKE9lLnN0YXJ0TWVzc2FnZShlKSxPZS5hZGRWZXJzaW9uKGUsSHQuVjUpLE9lLmFkZEhlYWRlcihlLHIpLE9lLmFkZEhlYWRlclR5cGUoZSx0LmhlYWRlclR5cGUpLE9lLmFkZEJvZHlMZW5ndGgoZSxCaWdJbnQodC5ib2R5TGVuZ3RoKSksbiE9PS0xKU9lLmFkZEN1c3RvbU1ldGFkYXRhKGUsbik7cmV0dXJuIE9lLmZpbmlzaE1lc3NhZ2VCdWZmZXIoZSxPZS5lbmRNZXNzYWdlKGUpKSxlLmFzVWludDhBcnJheSgpfXN0YXRpYyBmcm9tKHQsZT0wKXtpZih0IGluc3RhbmNlb2YgailyZXR1cm4gbmV3IGlyKDAsSHQuVjUsVHQuU2NoZW1hLHQpO2lmKHQgaW5zdGFuY2VvZiBKZSlyZXR1cm4gbmV3IGlyKGUsSHQuVjUsVHQuUmVjb3JkQmF0Y2gsdCx0Lm1ldGFkYXRhKTtpZih0IGluc3RhbmNlb2YgcXIpcmV0dXJuIG5ldyBpcihlLEh0LlY1LFR0LkRpY3Rpb25hcnlCYXRjaCx0KTt0aHJvdyBFcnJvcihgVW5yZWNvZ25pemVkIE1lc3NhZ2UgaGVhZGVyOiAke3R9YCl9Z2V0IHR5cGUoKXtyZXR1cm4gdGhpcy5oZWFkZXJUeXBlfWdldCB2ZXJzaW9uKCl7cmV0dXJuIHRoaXMuX3ZlcnNpb259Z2V0IGhlYWRlclR5cGUoKXtyZXR1cm4gdGhpcy5faGVhZGVyVHlwZX1nZXQgY29tcHJlc3Npb24oKXtyZXR1cm4gdGhpcy5fY29tcHJlc3Npb259Z2V0IGJvZHlMZW5ndGgoKXtyZXR1cm4gdGhpcy5fYm9keUxlbmd0aH1nZXQgbWV0YWRhdGEoKXtyZXR1cm4gdGhpcy5fbWV0YWRhdGF9aGVhZGVyKCl7cmV0dXJuIHRoaXMuX2NyZWF0ZUhlYWRlcigpfWlzU2NoZW1hKCl7cmV0dXJuIHRoaXMuaGVhZGVyVHlwZT09PVR0LlNjaGVtYX1pc1JlY29yZEJhdGNoKCl7cmV0dXJuIHRoaXMuaGVhZGVyVHlwZT09PVR0LlJlY29yZEJhdGNofWlzRGljdGlvbmFyeUJhdGNoKCl7cmV0dXJuIHRoaXMuaGVhZGVyVHlwZT09PVR0LkRpY3Rpb25hcnlCYXRjaH1jb25zdHJ1Y3Rvcih0LGUscixuLGkpe3RoaXMuX3ZlcnNpb249ZSx0aGlzLl9oZWFkZXJUeXBlPXIsdGhpcy5ib2R5PW5ldyBVaW50OEFycmF5KDApLHRoaXMuX2NvbXByZXNzaW9uPW49PT1udWxsfHxuPT09dm9pZCAwP3ZvaWQgMDpuLmNvbXByZXNzaW9uLG4mJih0aGlzLl9jcmVhdGVIZWFkZXI9KCk9Pm4pLHRoaXMuX2JvZHlMZW5ndGg9VnQodCksdGhpcy5fbWV0YWRhdGE9aXx8bmV3IE1hcH19Y2xhc3MgSmV7Z2V0IG5vZGVzKCl7cmV0dXJuIHRoaXMuX25vZGVzfWdldCBsZW5ndGgoKXtyZXR1cm4gdGhpcy5fbGVuZ3RofWdldCBidWZmZXJzKCl7cmV0dXJuIHRoaXMuX2J1ZmZlcnN9Z2V0IGNvbXByZXNzaW9uKCl7cmV0dXJuIHRoaXMuX2NvbXByZXNzaW9ufWdldCB2YXJpYWRpY0J1ZmZlckNvdW50cygpe3JldHVybiB0aGlzLl92YXJpYWRpY0J1ZmZlckNvdW50c31nZXQgbWV0YWRhdGEoKXtyZXR1cm4gdGhpcy5fbWV0YWRhdGF9Y29uc3RydWN0b3IodCxlLHIsbixpPVtdLHMpe3RoaXMuX25vZGVzPWUsdGhpcy5fYnVmZmVycz1yLHRoaXMuX2xlbmd0aD1WdCh0KSx0aGlzLl9jb21wcmVzc2lvbj1uLHRoaXMuX3ZhcmlhZGljQnVmZmVyQ291bnRzPWksdGhpcy5fbWV0YWRhdGE9c3x8bmV3IE1hcH19Y2xhc3MgcXJ7Z2V0IGlkKCl7cmV0dXJuIHRoaXMuX2lkfWdldCBkYXRhKCl7cmV0dXJuIHRoaXMuX2RhdGF9Z2V0IGlzRGVsdGEoKXtyZXR1cm4gdGhpcy5faXNEZWx0YX1nZXQgbGVuZ3RoKCl7cmV0dXJuIHRoaXMuZGF0YS5sZW5ndGh9Z2V0IG5vZGVzKCl7cmV0dXJuIHRoaXMuZGF0YS5ub2Rlc31nZXQgYnVmZmVycygpe3JldHVybiB0aGlzLmRhdGEuYnVmZmVyc31jb25zdHJ1Y3Rvcih0LGUscj0hMSl7dGhpcy5fZGF0YT10LHRoaXMuX2lzRGVsdGE9cix0aGlzLl9pZD1WdChlKX19Y2xhc3MgTmV7Y29uc3RydWN0b3IodCxlKXt0aGlzLm9mZnNldD1WdCh0KSx0aGlzLmxlbmd0aD1WdChlKX19Y2xhc3MgZXN7Y29uc3RydWN0b3IodCxlKXt0aGlzLmxlbmd0aD1WdCh0KSx0aGlzLm51bGxDb3VudD1WdChlKX19Y2xhc3Mgc2x7Y29uc3RydWN0b3IodCxlPUVhLkJVRkZFUil7dGhpcy50eXBlPXQsdGhpcy5tZXRob2Q9ZX19ZnVuY3Rpb24gWDEodCxlKXtyZXR1cm4oKT0+e3N3aXRjaChlKXtjYXNlIFR0LlNjaGVtYTpyZXR1cm4gai5mcm9tSlNPTih0KTtjYXNlIFR0LlJlY29yZEJhdGNoOnJldHVybiBKZS5mcm9tSlNPTih0KTtjYXNlIFR0LkRpY3Rpb25hcnlCYXRjaDpyZXR1cm4gcXIuZnJvbUpTT04odCl9dGhyb3cgRXJyb3IoYFVucmVjb2duaXplZCBNZXNzYWdlIHR5cGU6IHsgbmFtZTogJHtUdFtlXX0sIHR5cGU6ICR7ZX0gfWApfX1mdW5jdGlvbiBaMSh0LGUpe3JldHVybigpPT57c3dpdGNoKGUpe2Nhc2UgVHQuU2NoZW1hOnJldHVybiBqLmRlY29kZSh0LmhlYWRlcihuZXcgRWUpLG5ldyBNYXAsdC52ZXJzaW9uKCkpO2Nhc2UgVHQuUmVjb3JkQmF0Y2g6cmV0dXJuIEplLmRlY29kZSh0LmhlYWRlcihuZXcgeXIpLHQudmVyc2lvbigpKTtjYXNlIFR0LkRpY3Rpb25hcnlCYXRjaDpyZXR1cm4gcXIuZGVjb2RlKHQuaGVhZGVyKG5ldyBocyksdC52ZXJzaW9uKCkpfXRocm93IEVycm9yKGBVbnJlY29nbml6ZWQgTWVzc2FnZSB0eXBlOiB7IG5hbWU6ICR7VHRbZV19LCB0eXBlOiAke2V9IH1gKX19ZnVuY3Rpb24gUTEodCxlPW5ldyBNYXAscj1IdC5WNSl7bGV0IG49YU0odCxlKTtyZXR1cm4gbmV3IGoobixxaCh0KSxlLHIpfWZ1bmN0aW9uIHRNKHQsZT1IdC5WNSl7cmV0dXJuIG5ldyBKZSh0Lmxlbmd0aCgpLGlNKHQpLHNNKHQsZSksdEEodC5jb21wcmVzc2lvbigpKSxvTSh0KSl9ZnVuY3Rpb24gZU0odCxlPUh0LlY1KXtyZXR1cm4gbmV3IHFyKEplLmRlY29kZSh0LmRhdGEoKSxlKSx0LmlkKCksdC5pc0RlbHRhKCkpfWZ1bmN0aW9uIHJNKHQpe3JldHVybiBuZXcgTmUodC5vZmZzZXQoKSx0Lmxlbmd0aCgpKX1mdW5jdGlvbiBuTSh0KXtyZXR1cm4gbmV3IGVzKHQubGVuZ3RoKCksdC5udWxsQ291bnQoKSl9ZnVuY3Rpb24gaU0odCl7bGV0IGU9W107Zm9yKGxldCByLG49LTEsaT0tMSxzPXQubm9kZXNMZW5ndGgoKTsrK248czspaWYocj10Lm5vZGVzKG4pKWVbKytpXT1lcy5kZWNvZGUocik7cmV0dXJuIGV9ZnVuY3Rpb24gc00odCxlKXtsZXQgcj1bXTtmb3IobGV0IG4saT0tMSxzPS0xLG89dC5idWZmZXJzTGVuZ3RoKCk7KytpPG87KWlmKG49dC5idWZmZXJzKGkpKXtpZihlPEh0LlY0KW4uYmJfcG9zKz04KihpKzEpO3JbKytzXT1OZS5kZWNvZGUobil9cmV0dXJuIHJ9ZnVuY3Rpb24gb00odCl7bGV0IGU9W10scj1NYXRoLnRydW5jKHQudmFyaWFkaWNCdWZmZXJDb3VudHNMZW5ndGgoKSk7Zm9yKGxldCBuPTA7bjxyOysrbillLnB1c2goVnQodC52YXJpYWRpY0J1ZmZlckNvdW50cyhuKSkpO3JldHVybiBlfWZ1bmN0aW9uIGFNKHQsZSl7bGV0IHI9W107Zm9yKGxldCBuLGk9LTEscz0tMSxvPXQuZmllbGRzTGVuZ3RoKCk7KytpPG87KWlmKG49dC5maWVsZHMoaSkpclsrK3NdPVYuZGVjb2RlKG4sZSk7cmV0dXJuIHJ9ZnVuY3Rpb24gWFModCxlKXtsZXQgcj1bXTtmb3IobGV0IG4saT0tMSxzPS0xLG89dC5jaGlsZHJlbkxlbmd0aCgpOysraTxvOylpZihuPXQuY2hpbGRyZW4oaSkpclsrK3NdPVYuZGVjb2RlKG4sZSk7cmV0dXJuIHJ9ZnVuY3Rpb24gY00odCxlKXtsZXQgcixuLGkscyxvLGE7aWYoIWV8fCEoYT10LmRpY3Rpb25hcnkoKSkpaT1RUyh0LFhTKHQsZSkpLG49bmV3IFYodC5uYW1lKCksaSx0Lm51bGxhYmxlKCkscWgodCkpO2Vsc2UgaWYoIWUuaGFzKHI9VnQoYS5pZCgpKSkpcz0ocz1hLmluZGV4VHlwZSgpKT9aUyhzKTpuZXcganIsZS5zZXQocixpPVFTKHQsWFModCxlKSkpLG89bmV3IEVyKGkscyxyLGEuaXNPcmRlcmVkKCkpLG49bmV3IFYodC5uYW1lKCksbyx0Lm51bGxhYmxlKCkscWgodCkpO2Vsc2Ugcz0ocz1hLmluZGV4VHlwZSgpKT9aUyhzKTpuZXcganIsbz1uZXcgRXIoZS5nZXQocikscyxyLGEuaXNPcmRlcmVkKCkpLG49bmV3IFYodC5uYW1lKCksbyx0Lm51bGxhYmxlKCkscWgodCkpO3JldHVybiBufHxudWxsfWZ1bmN0aW9uIHFoKHQpe2xldCBlPW5ldyBNYXA7aWYodCl7Zm9yKGxldCByLG4saT0tMSxzPU1hdGgudHJ1bmModC5jdXN0b21NZXRhZGF0YUxlbmd0aCgpKTsrK2k8czspaWYoKHI9dC5jdXN0b21NZXRhZGF0YShpKSkmJihuPXIua2V5KCkpIT1udWxsKWUuc2V0KG4sci52YWx1ZSgpKX1yZXR1cm4gZX1mdW5jdGlvbiBsTSh0KXtsZXQgZT1uZXcgTWFwO2ZvcihsZXQgcixuLGk9LTEscz1NYXRoLnRydW5jKHQuY3VzdG9tTWV0YWRhdGFMZW5ndGgoKSk7KytpPHM7KWlmKChyPXQuY3VzdG9tTWV0YWRhdGEoaSkpJiYobj1yLmtleSgpKSE9bnVsbCllLnNldChuLHIudmFsdWUoKSk7cmV0dXJuIGV9ZnVuY3Rpb24gWlModCl7cmV0dXJuIG5ldyBLZSh0LmlzU2lnbmVkKCksdC5iaXRXaWR0aCgpKX1mdW5jdGlvbiBRUyh0LGUpe2xldCByPXQudHlwZVR5cGUoKTtzd2l0Y2gocil7Y2FzZSBKdC5OT05FOnJldHVybiBuZXcgbnI7Y2FzZSBKdC5OdWxsOnJldHVybiBuZXcgbnI7Y2FzZSBKdC5CaW5hcnk6cmV0dXJuIG5ldyBmaTtjYXNlIEp0LkxhcmdlQmluYXJ5OnJldHVybiBuZXcgcHM7Y2FzZSBKdC5CaW5hcnlWaWV3OnJldHVybiBuZXcgYnQ7Y2FzZSBKdC5VdGY4OnJldHVybiBuZXcgVHI7Y2FzZSBKdC5MYXJnZVV0Zjg6cmV0dXJuIG5ldyBtcztjYXNlIEp0LlV0ZjhWaWV3OnJldHVybiBuZXcgTG47Y2FzZSBKdC5Cb29sOnJldHVybiBuZXcgb247Y2FzZSBKdC5MaXN0OnJldHVybiBuZXcgYW4oKGV8fFtdKVswXSk7Y2FzZSBKdC5TdHJ1Y3RfOnJldHVybiBuZXcgT3QoZXx8W10pfXN3aXRjaChyKXtjYXNlIEp0LkludDp7bGV0IG49dC50eXBlKG5ldyBBcik7cmV0dXJuIG5ldyBLZShuLmlzU2lnbmVkKCksbi5iaXRXaWR0aCgpKX1jYXNlIEp0LkZsb2F0aW5nUG9pbnQ6e2xldCBuPXQudHlwZShuZXcgYWkpO3JldHVybiBuZXcgdWkobi5wcmVjaXNpb24oKSl9Y2FzZSBKdC5EZWNpbWFsOntsZXQgbj10LnR5cGUobmV3IERyKTtyZXR1cm4gbmV3IHlzKG4uc2NhbGUoKSxuLnByZWNpc2lvbigpLG4uYml0V2lkdGgoKSl9Y2FzZSBKdC5EYXRlOntsZXQgbj10LnR5cGUobmV3IG5pKTtyZXR1cm4gbmV3IFJzKG4udW5pdCgpKX1jYXNlIEp0LlRpbWU6e2xldCBuPXQudHlwZShuZXcgcm4pO3JldHVybiBuZXcgQ3Mobi51bml0KCksbi5iaXRXaWR0aCgpKX1jYXNlIEp0LlRpbWVzdGFtcDp7bGV0IG49dC50eXBlKG5ldyBubik7cmV0dXJuIG5ldyBkaShuLnVuaXQoKSxuLnRpbWV6b25lKCkpfWNhc2UgSnQuSW50ZXJ2YWw6e2xldCBuPXQudHlwZShuZXcgY2kpO3JldHVybiBuZXcgUHMobi51bml0KCkpfWNhc2UgSnQuRHVyYXRpb246e2xldCBuPXQudHlwZShuZXcgaWkpO3JldHVybiBuZXcga3Mobi51bml0KCkpfWNhc2UgSnQuVW5pb246e2xldCBuPXQudHlwZShuZXcgeHIpO3JldHVybiBuZXcgSmkobi5tb2RlKCksbi50eXBlSWRzQXJyYXkoKXx8W10sZXx8W10pfWNhc2UgSnQuRml4ZWRTaXplQmluYXJ5OntsZXQgbj10LnR5cGUobmV3IHNpKTtyZXR1cm4gbmV3IF9zKG4uYnl0ZVdpZHRoKCkpfWNhc2UgSnQuRml4ZWRTaXplTGlzdDp7bGV0IG49dC50eXBlKG5ldyBvaSk7cmV0dXJuIG5ldyBYaShuLmxpc3RTaXplKCksKGV8fFtdKVswXSl9Y2FzZSBKdC5NYXA6e2xldCBuPXQudHlwZShuZXcgbGkpO3JldHVybiBuZXcgaGkoKGV8fFtdKVswXSxuLmtleXNTb3J0ZWQoKSl9fXRocm93IEVycm9yKGBVbnJlY29nbml6ZWQgdHlwZTogIiR7SnRbcl19IiAoJHtyfSlgKX1mdW5jdGlvbiB0QSh0KXtyZXR1cm4gdD9uZXcgc2wodC5jb2RlYygpLHQubWV0aG9kKCkpOm51bGx9ZnVuY3Rpb24gdU0odCxlKXtsZXQgcj1lLmZpZWxkcy5tYXAoKHMpPT5WLmVuY29kZSh0LHMpKTtFZS5zdGFydEZpZWxkc1ZlY3Rvcih0LHIubGVuZ3RoKTtsZXQgbj1FZS5jcmVhdGVGaWVsZHNWZWN0b3IodCxyKSxpPSEoZS5tZXRhZGF0YSYmZS5tZXRhZGF0YS5zaXplPjApPy0xOkVlLmNyZWF0ZUN1c3RvbU1ldGFkYXRhVmVjdG9yKHQsWy4uLmUubWV0YWRhdGFdLm1hcCgoW3Msb10pPT57bGV0IGE9dC5jcmVhdGVTdHJpbmcoYCR7c31gKSxsPXQuY3JlYXRlU3RyaW5nKGAke299YCk7cmV0dXJuIG9lLnN0YXJ0S2V5VmFsdWUodCksb2UuYWRkS2V5KHQsYSksb2UuYWRkVmFsdWUodCxsKSxvZS5lbmRLZXlWYWx1ZSh0KX0pKTtpZihFZS5zdGFydFNjaGVtYSh0KSxFZS5hZGRGaWVsZHModCxuKSxFZS5hZGRFbmRpYW5uZXNzKHQseU0/Um8uTGl0dGxlOlJvLkJpZyksaSE9PS0xKUVlLmFkZEN1c3RvbU1ldGFkYXRhKHQsaSk7cmV0dXJuIEVlLmVuZFNjaGVtYSh0KX1mdW5jdGlvbiBmTSh0LGUpe2xldCByPS0xLG49LTEsaT0tMSx7dHlwZTpzLHR5cGVJZDpvfT1lO2lmKCFBLmlzRGljdGlvbmFyeShzKSluPWpoLnZpc2l0KHMsdCk7ZWxzZSBvPXMuZGljdGlvbmFyeS50eXBlSWQsaT1qaC52aXNpdChzLHQpLG49amgudmlzaXQocy5kaWN0aW9uYXJ5LHQpO2xldCBhPShzLmNoaWxkcmVufHxbXSkubWFwKChmKT0+Vi5lbmNvZGUodCxmKSksbD1yci5jcmVhdGVDaGlsZHJlblZlY3Rvcih0LGEpLHU9IShlLm1ldGFkYXRhJiZlLm1ldGFkYXRhLnNpemU+MCk/LTE6cnIuY3JlYXRlQ3VzdG9tTWV0YWRhdGFWZWN0b3IodCxbLi4uZS5tZXRhZGF0YV0ubWFwKChbZixwXSk9PntsZXQgZz10LmNyZWF0ZVN0cmluZyhgJHtmfWApLHY9dC5jcmVhdGVTdHJpbmcoYCR7cH1gKTtyZXR1cm4gb2Uuc3RhcnRLZXlWYWx1ZSh0KSxvZS5hZGRLZXkodCxnKSxvZS5hZGRWYWx1ZSh0LHYpLG9lLmVuZEtleVZhbHVlKHQpfSkpO2lmKGUubmFtZSlyPXQuY3JlYXRlU3RyaW5nKGUubmFtZSk7aWYocnIuc3RhcnRGaWVsZCh0KSxyci5hZGRUeXBlKHQsbikscnIuYWRkVHlwZVR5cGUodCxvKSxyci5hZGRDaGlsZHJlbih0LGwpLHJyLmFkZE51bGxhYmxlKHQsISFlLm51bGxhYmxlKSxyIT09LTEpcnIuYWRkTmFtZSh0LHIpO2lmKGkhPT0tMSlyci5hZGREaWN0aW9uYXJ5KHQsaSk7aWYodSE9PS0xKXJyLmFkZEN1c3RvbU1ldGFkYXRhKHQsdSk7cmV0dXJuIHJyLmVuZEZpZWxkKHQpfWZ1bmN0aW9uIGRNKHQsZSl7bGV0IHI9ZS5ub2Rlc3x8W10sbj1lLmJ1ZmZlcnN8fFtdLGk9ZS52YXJpYWRpY0J1ZmZlckNvdW50c3x8W107eXIuc3RhcnROb2Rlc1ZlY3Rvcih0LHIubGVuZ3RoKTtmb3IobGV0IHUgb2Ygci5zbGljZSgpLnJldmVyc2UoKSllcy5lbmNvZGUodCx1KTtsZXQgcz10LmVuZFZlY3RvcigpO3lyLnN0YXJ0QnVmZmVyc1ZlY3Rvcih0LG4ubGVuZ3RoKTtmb3IobGV0IHUgb2Ygbi5zbGljZSgpLnJldmVyc2UoKSlOZS5lbmNvZGUodCx1KTtsZXQgbz10LmVuZFZlY3RvcigpLGE9bnVsbDtpZihlLmNvbXByZXNzaW9uIT09bnVsbClhPWVBKHQsZS5jb21wcmVzc2lvbik7bGV0IGw9LTE7aWYoaS5sZW5ndGg+MClsPXlyLmNyZWF0ZVZhcmlhZGljQnVmZmVyQ291bnRzVmVjdG9yKHQsaS5tYXAoQmlnSW50KSk7aWYoeXIuc3RhcnRSZWNvcmRCYXRjaCh0KSx5ci5hZGRMZW5ndGgodCxCaWdJbnQoZS5sZW5ndGgpKSx5ci5hZGROb2Rlcyh0LHMpLHlyLmFkZEJ1ZmZlcnModCxvKSxlLmNvbXByZXNzaW9uIT09bnVsbCYmYSl5ci5hZGRDb21wcmVzc2lvbih0LGEpO2lmKGwhPT0tMSl5ci5hZGRWYXJpYWRpY0J1ZmZlckNvdW50cyh0LGwpO3JldHVybiB5ci5lbmRSZWNvcmRCYXRjaCh0KX1mdW5jdGlvbiBlQSh0LGUpe3JldHVybiBlbi5zdGFydEJvZHlDb21wcmVzc2lvbih0KSxlbi5hZGRDb2RlYyh0LGUudHlwZSksZW4uYWRkTWV0aG9kKHQsZS5tZXRob2QpLGVuLmVuZEJvZHlDb21wcmVzc2lvbih0KX1mdW5jdGlvbiBoTSh0LGUpe2xldCByPUplLmVuY29kZSh0LGUuZGF0YSk7cmV0dXJuIGhzLnN0YXJ0RGljdGlvbmFyeUJhdGNoKHQpLGhzLmFkZElkKHQsQmlnSW50KGUuaWQpKSxocy5hZGRJc0RlbHRhKHQsZS5pc0RlbHRhKSxocy5hZGREYXRhKHQsciksaHMuZW5kRGljdGlvbmFyeUJhdGNoKHQpfWZ1bmN0aW9uIHBNKHQsZSl7cmV0dXJuIHd1LmNyZWF0ZUZpZWxkTm9kZSh0LEJpZ0ludChlLmxlbmd0aCksQmlnSW50KGUubnVsbENvdW50KSl9ZnVuY3Rpb24gbU0odCxlKXtyZXR1cm4gYnUuY3JlYXRlQnVmZmVyKHQsQmlnSW50KGUub2Zmc2V0KSxCaWdJbnQoZS5sZW5ndGgpKX12YXIgRzEsSjEseU07dmFyIHFhPW0oKCk9PntGdCgpO0xfKCk7YWgoKTtnXygpO0dJKCk7TV8oKTtGXygpOyRjKCk7Yl8oKTtEXygpO0lfKCk7dl8oKTtFXygpO09fKCk7eF8oKTtCXygpO05fKCk7U18oKTtBXygpO1RfKCk7UFMoKTtfXygpO3lfKCk7JHIoKTtZZSgpO0NlKCk7VlMoKTtKUygpO2FlKCk7RzE9VGEsSjE9bXI7Vi5lbmNvZGU9Zk07Vi5kZWNvZGU9Y007Vi5mcm9tSlNPTj1HUztqLmVuY29kZT11TTtqLmRlY29kZT1RMTtqLmZyb21KU09OPXFTO0plLmVuY29kZT1kTTtKZS5kZWNvZGU9dE07SmUuZnJvbUpTT049c2c7cXIuZW5jb2RlPWhNO3FyLmRlY29kZT1lTTtxci5mcm9tSlNPTj1XUztlcy5lbmNvZGU9cE07ZXMuZGVjb2RlPW5NO05lLmVuY29kZT1tTTtOZS5kZWNvZGU9ck07c2wuZW5jb2RlPWVBO3NsLmRlY29kZT10QTt5TT0oKCk9PntsZXQgdD1uZXcgQXJyYXlCdWZmZXIoMik7cmV0dXJuIG5ldyBEYXRhVmlldyh0KS5zZXRJbnQxNigwLDI1NiwhMCksbmV3IEludDE2QXJyYXkodClbMF09PT0yNTZ9KSgpfSk7Y2xhc3MgV2h7Y29uc3RydWN0b3IodCl7dGhpcy5fanNvbj10fWdldCBzY2hlbWEoKXtyZXR1cm4gdGhpcy5fanNvbi5zY2hlbWF9Z2V0IGJhdGNoZXMoKXtyZXR1cm4gdGhpcy5fanNvbi5iYXRjaGVzfHxbXX1nZXQgZGljdGlvbmFyaWVzKCl7cmV0dXJuIHRoaXMuX2pzb24uZGljdGlvbmFyaWVzfHxbXX19Y2xhc3Mgb2x7dGVlKCl7cmV0dXJuIHRoaXMuX2dldERPTVN0cmVhbSgpLnRlZSgpfXBpcGUodCxlKXtyZXR1cm4gdGhpcy5fZ2V0Tm9kZVN0cmVhbSgpLnBpcGUodCxlKX1waXBlVG8odCxlKXtyZXR1cm4gdGhpcy5fZ2V0RE9NU3RyZWFtKCkucGlwZVRvKHQsZSl9cGlwZVRocm91Z2godCxlKXtyZXR1cm4gdGhpcy5fZ2V0RE9NU3RyZWFtKCkucGlwZVRocm91Z2godCxlKX1fZ2V0RE9NU3RyZWFtKCl7cmV0dXJuIHRoaXMuX0RPTVN0cmVhbXx8KHRoaXMuX0RPTVN0cmVhbT10aGlzLnRvRE9NU3RyZWFtKCkpfV9nZXROb2RlU3RyZWFtKCl7cmV0dXJuIHRoaXMuX25vZGVTdHJlYW18fCh0aGlzLl9ub2RlU3RyZWFtPXRoaXMudG9Ob2RlU3RyZWFtKCkpfX12YXIgaGUsb2c7dmFyIE11PW0oKCk9PntPbigpO3B1KCk7aGU9T2JqZWN0LmZyZWV6ZSh7ZG9uZTohMCx2YWx1ZTp2b2lkIDB9KTtvZz1jbGFzcyBvZyBleHRlbmRzIG9se2NvbnN0cnVjdG9yKCl7c3VwZXIoKTt0aGlzLl92YWx1ZXM9W10sdGhpcy5yZXNvbHZlcnM9W10sdGhpcy5fY2xvc2VkUHJvbWlzZT1uZXcgUHJvbWlzZSgodCk9PnRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlPXQpfWdldCBjbG9zZWQoKXtyZXR1cm4gdGhpcy5fY2xvc2VkUHJvbWlzZX1jYW5jZWwodCl7cmV0dXJuIE8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3lpZWxkIHRoaXMucmV0dXJuKHQpfSl9d3JpdGUodCl7aWYodGhpcy5fZW5zdXJlT3BlbigpKXRoaXMucmVzb2x2ZXJzLmxlbmd0aDw9MD90aGlzLl92YWx1ZXMucHVzaCh0KTp0aGlzLnJlc29sdmVycy5zaGlmdCgpLnJlc29sdmUoe2RvbmU6ITEsdmFsdWU6dH0pfWFib3J0KHQpe2lmKHRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlKXRoaXMucmVzb2x2ZXJzLmxlbmd0aDw9MD90aGlzLl9lcnJvcj17ZXJyb3I6dH06dGhpcy5yZXNvbHZlcnMuc2hpZnQoKS5yZWplY3Qoe2RvbmU6ITAsdmFsdWU6dH0pfWNsb3NlKCl7aWYodGhpcy5fY2xvc2VkUHJvbWlzZVJlc29sdmUpe2xldHtyZXNvbHZlcnM6dH09dGhpczt3aGlsZSh0Lmxlbmd0aD4wKXQuc2hpZnQoKS5yZXNvbHZlKGhlKTt0aGlzLl9jbG9zZWRQcm9taXNlUmVzb2x2ZSgpLHRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlPXZvaWQgMH19W1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpe3JldHVybiB0aGlzfXRvRE9NU3RyZWFtKHQpe3JldHVybiBwci50b0RPTVN0cmVhbSh0aGlzLl9jbG9zZWRQcm9taXNlUmVzb2x2ZXx8dGhpcy5fZXJyb3I/dGhpczp0aGlzLl92YWx1ZXMsdCl9dG9Ob2RlU3RyZWFtKHQpe3JldHVybiBwci50b05vZGVTdHJlYW0odGhpcy5fY2xvc2VkUHJvbWlzZVJlc29sdmV8fHRoaXMuX2Vycm9yP3RoaXM6dGhpcy5fdmFsdWVzLHQpfXRocm93KHQpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtyZXR1cm4geWllbGQgdGhpcy5hYm9ydCh0KSxoZX0pfXJldHVybih0KXtyZXR1cm4gTyh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7cmV0dXJuIHlpZWxkIHRoaXMuY2xvc2UoKSxoZX0pfXJlYWQodCl7cmV0dXJuIE8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3JldHVybih5aWVsZCB0aGlzLm5leHQodCwicmVhZCIpKS52YWx1ZX0pfXBlZWsodCl7cmV0dXJuIE8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3JldHVybih5aWVsZCB0aGlzLm5leHQodCwicGVlayIpKS52YWx1ZX0pfW5leHQoLi4udCl7aWYodGhpcy5fdmFsdWVzLmxlbmd0aD4wKXJldHVybiBQcm9taXNlLnJlc29sdmUoe2RvbmU6ITEsdmFsdWU6dGhpcy5fdmFsdWVzLnNoaWZ0KCl9KTtlbHNlIGlmKHRoaXMuX2Vycm9yKXJldHVybiBQcm9taXNlLnJlamVjdCh7ZG9uZTohMCx2YWx1ZTp0aGlzLl9lcnJvci5lcnJvcn0pO2Vsc2UgaWYoIXRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlKXJldHVybiBQcm9taXNlLnJlc29sdmUoaGUpO2Vsc2UgcmV0dXJuIG5ldyBQcm9taXNlKChlLHIpPT57dGhpcy5yZXNvbHZlcnMucHVzaCh7cmVzb2x2ZTplLHJlamVjdDpyfSl9KX1fZW5zdXJlT3Blbigpe2lmKHRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlKXJldHVybiEwO3Rocm93IEVycm9yKCJBc3luY1F1ZXVlIGlzIGNsb3NlZCIpfX19KTtjbGFzcyBuQXtjb25zdHJ1Y3Rvcih0KXt0aGlzLnNvdXJjZT10fWNhbmNlbCh0KXt0aGlzLnJldHVybih0KX1wZWVrKHQpe3JldHVybiB0aGlzLm5leHQodCwicGVlayIpLnZhbHVlfXJlYWQodCl7cmV0dXJuIHRoaXMubmV4dCh0LCJyZWFkIikudmFsdWV9bmV4dCh0LGU9InJlYWQiKXtyZXR1cm4gdGhpcy5zb3VyY2UubmV4dCh7Y21kOmUsc2l6ZTp0fSl9dGhyb3codCl7cmV0dXJuIE9iamVjdC5jcmVhdGUodGhpcy5zb3VyY2UudGhyb3cmJnRoaXMuc291cmNlLnRocm93KHQpfHxoZSl9cmV0dXJuKHQpe3JldHVybiBPYmplY3QuY3JlYXRlKHRoaXMuc291cmNlLnJldHVybiYmdGhpcy5zb3VyY2UucmV0dXJuKHQpfHxoZSl9fWNsYXNzIFpve2NvbnN0cnVjdG9yKHQpe3RoaXMuc291cmNlPXQsdGhpcy5fY2xvc2VkUHJvbWlzZT1uZXcgUHJvbWlzZSgoZSk9PnRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlPWUpfWNhbmNlbCh0KXtyZXR1cm4gTyh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7eWllbGQgdGhpcy5yZXR1cm4odCl9KX1nZXQgY2xvc2VkKCl7cmV0dXJuIHRoaXMuX2Nsb3NlZFByb21pc2V9cmVhZCh0KXtyZXR1cm4gTyh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7cmV0dXJuKHlpZWxkIHRoaXMubmV4dCh0LCJyZWFkIikpLnZhbHVlfSl9cGVlayh0KXtyZXR1cm4gTyh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7cmV0dXJuKHlpZWxkIHRoaXMubmV4dCh0LCJwZWVrIikpLnZhbHVlfSl9bmV4dCh0KXtyZXR1cm4gTyh0aGlzLGFyZ3VtZW50cyx2b2lkIDAsZnVuY3Rpb24qKGUscj0icmVhZCIpe3JldHVybiB5aWVsZCB0aGlzLnNvdXJjZS5uZXh0KHtjbWQ6cixzaXplOmV9KX0pfXRocm93KHQpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXQgZT10aGlzLnNvdXJjZS50aHJvdyYmKHlpZWxkIHRoaXMuc291cmNlLnRocm93KHQpKXx8aGU7cmV0dXJuIHRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlJiZ0aGlzLl9jbG9zZWRQcm9taXNlUmVzb2x2ZSgpLHRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlPXZvaWQgMCxPYmplY3QuY3JlYXRlKGUpfSl9cmV0dXJuKHQpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXQgZT10aGlzLnNvdXJjZS5yZXR1cm4mJih5aWVsZCB0aGlzLnNvdXJjZS5yZXR1cm4odCkpfHxoZTtyZXR1cm4gdGhpcy5fY2xvc2VkUHJvbWlzZVJlc29sdmUmJnRoaXMuX2Nsb3NlZFByb21pc2VSZXNvbHZlKCksdGhpcy5fY2xvc2VkUHJvbWlzZVJlc29sdmU9dm9pZCAwLE9iamVjdC5jcmVhdGUoZSl9KX19dmFyICRzLHFzLG1pO3ZhciBXYT1tKCgpPT57T24oKTtwdSgpO1VzKCk7TXUoKTtZZSgpOyRzPWNsYXNzICRzIGV4dGVuZHMgb2d7d3JpdGUodCl7aWYoKHQ9ayh0KSkuYnl0ZUxlbmd0aD4wKXJldHVybiBzdXBlci53cml0ZSh0KX10b1N0cmluZyh0PSExKXtyZXR1cm4gdD96Yyh0aGlzLnRvVWludDhBcnJheSghMCkpOnRoaXMudG9VaW50OEFycmF5KCExKS50aGVuKHpjKX10b1VpbnQ4QXJyYXkodD0hMSl7cmV0dXJuIHQ/Rm4odGhpcy5fdmFsdWVzKVswXTooKCk9Pk8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3ZhciBlLHIsbixpO2xldCBzPVtdLG89MDt0cnl7Zm9yKHZhciBhPSEwLGw9JGkodGhpcyksdTt1PXlpZWxkIGwubmV4dCgpLGU9dS5kb25lLCFlO2E9ITApe2k9dS52YWx1ZSxhPSExO2xldCBmPWk7cy5wdXNoKGYpLG8rPWYuYnl0ZUxlbmd0aH19Y2F0Y2goZil7cj17ZXJyb3I6Zn19ZmluYWxseXt0cnl7aWYoIWEmJiFlJiYobj1sLnJldHVybikpeWllbGQgbi5jYWxsKGwpfWZpbmFsbHl7aWYocil0aHJvdyByLmVycm9yfX1yZXR1cm4gRm4ocyxvKVswXX0pKSgpfX07cXM9Y2xhc3MgcXN7Y29uc3RydWN0b3IodCl7aWYodCl0aGlzLnNvdXJjZT1uZXcgbkEocHIuZnJvbUl0ZXJhYmxlKHQpKX1bU3ltYm9sLml0ZXJhdG9yXSgpe3JldHVybiB0aGlzfW5leHQodCl7cmV0dXJuIHRoaXMuc291cmNlLm5leHQodCl9dGhyb3codCl7cmV0dXJuIHRoaXMuc291cmNlLnRocm93KHQpfXJldHVybih0KXtyZXR1cm4gdGhpcy5zb3VyY2UucmV0dXJuKHQpfXBlZWsodCl7cmV0dXJuIHRoaXMuc291cmNlLnBlZWsodCl9cmVhZCh0KXtyZXR1cm4gdGhpcy5zb3VyY2UucmVhZCh0KX19O21pPWNsYXNzIG1pe2NvbnN0cnVjdG9yKHQpe2lmKHQgaW5zdGFuY2VvZiBtaSl0aGlzLnNvdXJjZT10LnNvdXJjZTtlbHNlIGlmKHQgaW5zdGFuY2VvZiAkcyl0aGlzLnNvdXJjZT1uZXcgWm8ocHIuZnJvbUFzeW5jSXRlcmFibGUodCkpO2Vsc2UgaWYodGgodCkpdGhpcy5zb3VyY2U9bmV3IFpvKHByLmZyb21Ob2RlU3RyZWFtKHQpKTtlbHNlIGlmKGR1KHQpKXRoaXMuc291cmNlPW5ldyBabyhwci5mcm9tRE9NU3RyZWFtKHQpKTtlbHNlIGlmKFpkKHQpKXRoaXMuc291cmNlPW5ldyBabyhwci5mcm9tRE9NU3RyZWFtKHQuYm9keSkpO2Vsc2UgaWYoV2kodCkpdGhpcy5zb3VyY2U9bmV3IFpvKHByLmZyb21JdGVyYWJsZSh0KSk7ZWxzZSBpZihxaSh0KSl0aGlzLnNvdXJjZT1uZXcgWm8ocHIuZnJvbUFzeW5jSXRlcmFibGUodCkpO2Vsc2UgaWYoZWkodCkpdGhpcy5zb3VyY2U9bmV3IFpvKHByLmZyb21Bc3luY0l0ZXJhYmxlKHQpKX1bU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCl7cmV0dXJuIHRoaXN9bmV4dCh0KXtyZXR1cm4gdGhpcy5zb3VyY2UubmV4dCh0KX10aHJvdyh0KXtyZXR1cm4gdGhpcy5zb3VyY2UudGhyb3codCl9cmV0dXJuKHQpe3JldHVybiB0aGlzLnNvdXJjZS5yZXR1cm4odCl9Z2V0IGNsb3NlZCgpe3JldHVybiB0aGlzLnNvdXJjZS5jbG9zZWR9Y2FuY2VsKHQpe3JldHVybiB0aGlzLnNvdXJjZS5jYW5jZWwodCl9cGVlayh0KXtyZXR1cm4gdGhpcy5zb3VyY2UucGVlayh0KX1yZWFkKHQpe3JldHVybiB0aGlzLnNvdXJjZS5yZWFkKHQpfX19KTt2YXIgSGgsSGE7dmFyIGFnPW0oKCk9PntPbigpO1dhKCk7WWUoKTtIaD1jbGFzcyBIaCBleHRlbmRzIHFze2NvbnN0cnVjdG9yKHQsZSl7c3VwZXIoKTt0aGlzLnBvc2l0aW9uPTAsdGhpcy5idWZmZXI9ayh0KSx0aGlzLnNpemU9ZT09PXZvaWQgMD90aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoOmV9cmVhZEludDMyKHQpe2xldHtidWZmZXI6ZSxieXRlT2Zmc2V0OnJ9PXRoaXMucmVhZEF0KHQsNCk7cmV0dXJuIG5ldyBEYXRhVmlldyhlLHIpLmdldEludDMyKDAsITApfXNlZWsodCl7cmV0dXJuIHRoaXMucG9zaXRpb249TWF0aC5taW4odCx0aGlzLnNpemUpLHQ8dGhpcy5zaXplfXJlYWQodCl7bGV0e2J1ZmZlcjplLHNpemU6cixwb3NpdGlvbjpufT10aGlzO2lmKGUmJm48cil7aWYodHlwZW9mIHQhPT0ibnVtYmVyIil0PU51bWJlci5QT1NJVElWRV9JTkZJTklUWTtyZXR1cm4gdGhpcy5wb3NpdGlvbj1NYXRoLm1pbihyLG4rTWF0aC5taW4oci1uLHQpKSxlLnN1YmFycmF5KG4sdGhpcy5wb3NpdGlvbil9cmV0dXJuIG51bGx9cmVhZEF0KHQsZSl7bGV0IHI9dGhpcy5idWZmZXIsbj1NYXRoLm1pbih0aGlzLnNpemUsdCtlKTtyZXR1cm4gcj9yLnN1YmFycmF5KHQsbik6bmV3IFVpbnQ4QXJyYXkoZSl9Y2xvc2UoKXt0aGlzLmJ1ZmZlciYmKHRoaXMuYnVmZmVyPW51bGwpfXRocm93KHQpe3JldHVybiB0aGlzLmNsb3NlKCkse2RvbmU6ITAsdmFsdWU6dH19cmV0dXJuKHQpe3JldHVybiB0aGlzLmNsb3NlKCkse2RvbmU6ITAsdmFsdWU6dH19fTtIYT1jbGFzcyBIYSBleHRlbmRzIG1pe2NvbnN0cnVjdG9yKHQsZSl7c3VwZXIoKTtpZih0aGlzLnBvc2l0aW9uPTAsdGhpcy5faGFuZGxlPXQsdHlwZW9mIGU9PT0ibnVtYmVyIil0aGlzLnNpemU9ZTtlbHNlIHRoaXMuX3BlbmRpbmc9KCgpPT5PKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXt0aGlzLnNpemU9KHlpZWxkIHQuc3RhdCgpKS5zaXplLGRlbGV0ZSB0aGlzLl9wZW5kaW5nfSkpKCl9cmVhZEludDMyKHQpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXR7YnVmZmVyOmUsYnl0ZU9mZnNldDpyfT15aWVsZCB0aGlzLnJlYWRBdCh0LDQpO3JldHVybiBuZXcgRGF0YVZpZXcoZSxyKS5nZXRJbnQzMigwLCEwKX0pfXNlZWsodCl7cmV0dXJuIE8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3JldHVybiB0aGlzLl9wZW5kaW5nJiYoeWllbGQgdGhpcy5fcGVuZGluZyksdGhpcy5wb3NpdGlvbj1NYXRoLm1pbih0LHRoaXMuc2l6ZSksdDx0aGlzLnNpemV9KX1yZWFkKHQpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXt0aGlzLl9wZW5kaW5nJiYoeWllbGQgdGhpcy5fcGVuZGluZyk7bGV0e19oYW5kbGU6ZSxzaXplOnIscG9zaXRpb246bn09dGhpcztpZihlJiZuPHIpe2lmKHR5cGVvZiB0IT09Im51bWJlciIpdD1OdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7bGV0IGk9bixzPTAsbz0wLGE9TWF0aC5taW4ocixpK01hdGgubWluKHItaSx0KSksbD1uZXcgVWludDhBcnJheShNYXRoLm1heCgwLCh0aGlzLnBvc2l0aW9uPWEpLWkpKTt3aGlsZSgoaSs9byk8YSYmKHMrPW8pPGwuYnl0ZUxlbmd0aCkoe2J5dGVzUmVhZDpvfT15aWVsZCBlLnJlYWQobCxzLGwuYnl0ZUxlbmd0aC1zLGkpKTtyZXR1cm4gbH1yZXR1cm4gbnVsbH0pfXJlYWRBdCh0LGUpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXt0aGlzLl9wZW5kaW5nJiYoeWllbGQgdGhpcy5fcGVuZGluZyk7bGV0e19oYW5kbGU6cixzaXplOm59PXRoaXM7aWYociYmdCtlPG4pe2xldCBpPU1hdGgubWluKG4sdCtlKSxzPW5ldyBVaW50OEFycmF5KGktdCk7cmV0dXJuKHlpZWxkIHIucmVhZChzLDAsZSx0KSkuYnVmZmVyfXJldHVybiBuZXcgVWludDhBcnJheShlKX0pfWNsb3NlKCl7cmV0dXJuIE8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe2xldCB0PXRoaXMuX2hhbmRsZTt0aGlzLl9oYW5kbGU9bnVsbCx0JiYoeWllbGQgdC5jbG9zZSgpKX0pfXRocm93KHQpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtyZXR1cm4geWllbGQgdGhpcy5jbG9zZSgpLHtkb25lOiEwLHZhbHVlOnR9fSl9cmV0dXJuKHQpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtyZXR1cm4geWllbGQgdGhpcy5jbG9zZSgpLHtkb25lOiEwLHZhbHVlOnR9fSl9fX0pO3ZhciBsZz17fTtaZShsZyx7QmFzZUludDY0OigpPT5ZaCxJbnQxMjg6KCk9PnlpLEludDY0OigpPT5PcixVaW50NjQ6KCk9Plh0fSk7ZnVuY3Rpb24gYWwodCl7aWYodDwwKXQ9NDI5NDk2NzI5NSt0KzE7cmV0dXJuYDB4JHt0LnRvU3RyaW5nKDE2KX1gfWNsYXNzIFloe2NvbnN0cnVjdG9yKHQpe3RoaXMuYnVmZmVyPXR9aGlnaCgpe3JldHVybiB0aGlzLmJ1ZmZlclsxXX1sb3coKXtyZXR1cm4gdGhpcy5idWZmZXJbMF19X3RpbWVzKHQpe2xldCBlPW5ldyBVaW50MzJBcnJheShbdGhpcy5idWZmZXJbMV0+Pj4xNix0aGlzLmJ1ZmZlclsxXSY2NTUzNSx0aGlzLmJ1ZmZlclswXT4+PjE2LHRoaXMuYnVmZmVyWzBdJjY1NTM1XSkscj1uZXcgVWludDMyQXJyYXkoW3QuYnVmZmVyWzFdPj4+MTYsdC5idWZmZXJbMV0mNjU1MzUsdC5idWZmZXJbMF0+Pj4xNix0LmJ1ZmZlclswXSY2NTUzNV0pLG49ZVszXSpyWzNdO3RoaXMuYnVmZmVyWzBdPW4mNjU1MzU7bGV0IGk9bj4+PjE2O3JldHVybiBuPWVbMl0qclszXSxpKz1uLG49ZVszXSpyWzJdPj4+MCxpKz1uLHRoaXMuYnVmZmVyWzBdKz1pPDwxNix0aGlzLmJ1ZmZlclsxXT1pPj4+MDxuPzY1NTM2OjAsdGhpcy5idWZmZXJbMV0rPWk+Pj4xNix0aGlzLmJ1ZmZlclsxXSs9ZVsxXSpyWzNdK2VbMl0qclsyXStlWzNdKnJbMV0sdGhpcy5idWZmZXJbMV0rPWVbMF0qclszXStlWzFdKnJbMl0rZVsyXSpyWzFdK2VbM10qclswXTw8MTYsdGhpc31fcGx1cyh0KXtsZXQgZT10aGlzLmJ1ZmZlclswXSt0LmJ1ZmZlclswXT4+PjA7aWYodGhpcy5idWZmZXJbMV0rPXQuYnVmZmVyWzFdLGU8dGhpcy5idWZmZXJbMF0+Pj4wKSsrdGhpcy5idWZmZXJbMV07dGhpcy5idWZmZXJbMF09ZX1sZXNzVGhhbih0KXtyZXR1cm4gdGhpcy5idWZmZXJbMV08dC5idWZmZXJbMV18fHRoaXMuYnVmZmVyWzFdPT09dC5idWZmZXJbMV0mJnRoaXMuYnVmZmVyWzBdPHQuYnVmZmVyWzBdfWVxdWFscyh0KXtyZXR1cm4gdGhpcy5idWZmZXJbMV09PT10LmJ1ZmZlclsxXSYmdGhpcy5idWZmZXJbMF09PXQuYnVmZmVyWzBdfWdyZWF0ZXJUaGFuKHQpe3JldHVybiB0Lmxlc3NUaGFuKHRoaXMpfWhleCgpe3JldHVybmAke2FsKHRoaXMuYnVmZmVyWzFdKX0gJHthbCh0aGlzLmJ1ZmZlclswXSl9YH19Y2xhc3MgeWl7Y29uc3RydWN0b3IodCl7dGhpcy5idWZmZXI9dH1oaWdoKCl7cmV0dXJuIG5ldyBPcihuZXcgVWludDMyQXJyYXkodGhpcy5idWZmZXIuYnVmZmVyLHRoaXMuYnVmZmVyLmJ5dGVPZmZzZXQrOCwyKSl9bG93KCl7cmV0dXJuIG5ldyBPcihuZXcgVWludDMyQXJyYXkodGhpcy5idWZmZXIuYnVmZmVyLHRoaXMuYnVmZmVyLmJ5dGVPZmZzZXQsMikpfW5lZ2F0ZSgpe2lmKHRoaXMuYnVmZmVyWzBdPX50aGlzLmJ1ZmZlclswXSsxLHRoaXMuYnVmZmVyWzFdPX50aGlzLmJ1ZmZlclsxXSx0aGlzLmJ1ZmZlclsyXT1+dGhpcy5idWZmZXJbMl0sdGhpcy5idWZmZXJbM109fnRoaXMuYnVmZmVyWzNdLHRoaXMuYnVmZmVyWzBdPT0wKSsrdGhpcy5idWZmZXJbMV07aWYodGhpcy5idWZmZXJbMV09PTApKyt0aGlzLmJ1ZmZlclsyXTtpZih0aGlzLmJ1ZmZlclsyXT09MCkrK3RoaXMuYnVmZmVyWzNdO3JldHVybiB0aGlzfXRpbWVzKHQpe2xldCBlPW5ldyBYdChuZXcgVWludDMyQXJyYXkoW3RoaXMuYnVmZmVyWzNdLDBdKSkscj1uZXcgWHQobmV3IFVpbnQzMkFycmF5KFt0aGlzLmJ1ZmZlclsyXSwwXSkpLG49bmV3IFh0KG5ldyBVaW50MzJBcnJheShbdGhpcy5idWZmZXJbMV0sMF0pKSxpPW5ldyBYdChuZXcgVWludDMyQXJyYXkoW3RoaXMuYnVmZmVyWzBdLDBdKSkscz1uZXcgWHQobmV3IFVpbnQzMkFycmF5KFt0LmJ1ZmZlclszXSwwXSkpLG89bmV3IFh0KG5ldyBVaW50MzJBcnJheShbdC5idWZmZXJbMl0sMF0pKSxhPW5ldyBYdChuZXcgVWludDMyQXJyYXkoW3QuYnVmZmVyWzFdLDBdKSksbD1uZXcgWHQobmV3IFVpbnQzMkFycmF5KFt0LmJ1ZmZlclswXSwwXSkpLHU9WHQubXVsdGlwbHkoaSxsKTt0aGlzLmJ1ZmZlclswXT11LmxvdygpO2xldCBmPW5ldyBYdChuZXcgVWludDMyQXJyYXkoW3UuaGlnaCgpLDBdKSk7cmV0dXJuIHU9WHQubXVsdGlwbHkobixsKSxmLnBsdXModSksdT1YdC5tdWx0aXBseShpLGEpLGYucGx1cyh1KSx0aGlzLmJ1ZmZlclsxXT1mLmxvdygpLHRoaXMuYnVmZmVyWzNdPWYubGVzc1RoYW4odSk/MTowLHRoaXMuYnVmZmVyWzJdPWYuaGlnaCgpLG5ldyBYdChuZXcgVWludDMyQXJyYXkodGhpcy5idWZmZXIuYnVmZmVyLHRoaXMuYnVmZmVyLmJ5dGVPZmZzZXQrOCwyKSkucGx1cyhYdC5tdWx0aXBseShyLGwpKS5wbHVzKFh0Lm11bHRpcGx5KG4sYSkpLnBsdXMoWHQubXVsdGlwbHkoaSxvKSksdGhpcy5idWZmZXJbM10rPVh0Lm11bHRpcGx5KGUsbCkucGx1cyhYdC5tdWx0aXBseShyLGEpKS5wbHVzKFh0Lm11bHRpcGx5KG4sbykpLnBsdXMoWHQubXVsdGlwbHkoaSxzKSkubG93KCksdGhpc31wbHVzKHQpe2xldCBlPW5ldyBVaW50MzJBcnJheSg0KTtpZihlWzNdPXRoaXMuYnVmZmVyWzNdK3QuYnVmZmVyWzNdPj4+MCxlWzJdPXRoaXMuYnVmZmVyWzJdK3QuYnVmZmVyWzJdPj4+MCxlWzFdPXRoaXMuYnVmZmVyWzFdK3QuYnVmZmVyWzFdPj4+MCxlWzBdPXRoaXMuYnVmZmVyWzBdK3QuYnVmZmVyWzBdPj4+MCxlWzBdPHRoaXMuYnVmZmVyWzBdPj4+MCkrK2VbMV07aWYoZVsxXTx0aGlzLmJ1ZmZlclsxXT4+PjApKytlWzJdO2lmKGVbMl08dGhpcy5idWZmZXJbMl0+Pj4wKSsrZVszXTtyZXR1cm4gdGhpcy5idWZmZXJbM109ZVszXSx0aGlzLmJ1ZmZlclsyXT1lWzJdLHRoaXMuYnVmZmVyWzFdPWVbMV0sdGhpcy5idWZmZXJbMF09ZVswXSx0aGlzfWhleCgpe3JldHVybmAke2FsKHRoaXMuYnVmZmVyWzNdKX0gJHthbCh0aGlzLmJ1ZmZlclsyXSl9ICR7YWwodGhpcy5idWZmZXJbMV0pfSAke2FsKHRoaXMuYnVmZmVyWzBdKX1gfXN0YXRpYyBtdWx0aXBseSh0LGUpe3JldHVybiBuZXcgeWkobmV3IFVpbnQzMkFycmF5KHQuYnVmZmVyKSkudGltZXMoZSl9c3RhdGljIGFkZCh0LGUpe3JldHVybiBuZXcgeWkobmV3IFVpbnQzMkFycmF5KHQuYnVmZmVyKSkucGx1cyhlKX1zdGF0aWMgZnJvbSh0LGU9bmV3IFVpbnQzMkFycmF5KDQpKXtyZXR1cm4geWkuZnJvbVN0cmluZyh0eXBlb2YgdD09PSJzdHJpbmciP3Q6dC50b1N0cmluZygpLGUpfXN0YXRpYyBmcm9tTnVtYmVyKHQsZT1uZXcgVWludDMyQXJyYXkoNCkpe3JldHVybiB5aS5mcm9tU3RyaW5nKHQudG9TdHJpbmcoKSxlKX1zdGF0aWMgZnJvbVN0cmluZyh0LGU9bmV3IFVpbnQzMkFycmF5KDQpKXtsZXQgcj10LnN0YXJ0c1dpdGgoIi0iKSxuPXQubGVuZ3RoLGk9bmV3IHlpKGUpO2ZvcihsZXQgcz1yPzE6MDtzPG47KXtsZXQgbz1jbDxuLXM/Y2w6bi1zLGE9bmV3IHlpKG5ldyBVaW50MzJBcnJheShbTnVtYmVyLnBhcnNlSW50KHQuc2xpY2UocyxzK28pLDEwKSwwLDAsMF0pKSxsPW5ldyB5aShuZXcgVWludDMyQXJyYXkoW2NnW29dLDAsMCwwXSkpO2kudGltZXMobCksaS5wbHVzKGEpLHMrPW99cmV0dXJuIHI/aS5uZWdhdGUoKTppfXN0YXRpYyBjb252ZXJ0QXJyYXkodCl7bGV0IGU9bmV3IFVpbnQzMkFycmF5KHQubGVuZ3RoKjQpO2ZvcihsZXQgcj0tMSxuPXQubGVuZ3RoOysrcjxuOyl5aS5mcm9tKHRbcl0sbmV3IFVpbnQzMkFycmF5KGUuYnVmZmVyLGUuYnl0ZU9mZnNldCsxNipyLDQpKTtyZXR1cm4gZX19dmFyIGNsPTgsY2csWHQsT3I7dmFyIHVnPW0oKCk9PntjZz1bMSwxMCwxMDAsMTAwMCwxZTQsMWU1LDFlNiwxZTcsMWU4XTtYdD1jbGFzcyBYdCBleHRlbmRzIFloe3RpbWVzKHQpe3JldHVybiB0aGlzLl90aW1lcyh0KSx0aGlzfXBsdXModCl7cmV0dXJuIHRoaXMuX3BsdXModCksdGhpc31zdGF0aWMgZnJvbSh0LGU9bmV3IFVpbnQzMkFycmF5KDIpKXtyZXR1cm4gWHQuZnJvbVN0cmluZyh0eXBlb2YgdD09PSJzdHJpbmciP3Q6dC50b1N0cmluZygpLGUpfXN0YXRpYyBmcm9tTnVtYmVyKHQsZT1uZXcgVWludDMyQXJyYXkoMikpe3JldHVybiBYdC5mcm9tU3RyaW5nKHQudG9TdHJpbmcoKSxlKX1zdGF0aWMgZnJvbVN0cmluZyh0LGU9bmV3IFVpbnQzMkFycmF5KDIpKXtsZXQgcj10Lmxlbmd0aCxuPW5ldyBYdChlKTtmb3IobGV0IGk9MDtpPHI7KXtsZXQgcz1jbDxyLWk/Y2w6ci1pLG89bmV3IFh0KG5ldyBVaW50MzJBcnJheShbTnVtYmVyLnBhcnNlSW50KHQuc2xpY2UoaSxpK3MpLDEwKSwwXSkpLGE9bmV3IFh0KG5ldyBVaW50MzJBcnJheShbY2dbc10sMF0pKTtuLnRpbWVzKGEpLG4ucGx1cyhvKSxpKz1zfXJldHVybiBufXN0YXRpYyBjb252ZXJ0QXJyYXkodCl7bGV0IGU9bmV3IFVpbnQzMkFycmF5KHQubGVuZ3RoKjIpO2ZvcihsZXQgcj0tMSxuPXQubGVuZ3RoOysrcjxuOylYdC5mcm9tKHRbcl0sbmV3IFVpbnQzMkFycmF5KGUuYnVmZmVyLGUuYnl0ZU9mZnNldCsyKnIqNCwyKSk7cmV0dXJuIGV9c3RhdGljIG11bHRpcGx5KHQsZSl7cmV0dXJuIG5ldyBYdChuZXcgVWludDMyQXJyYXkodC5idWZmZXIpKS50aW1lcyhlKX1zdGF0aWMgYWRkKHQsZSl7cmV0dXJuIG5ldyBYdChuZXcgVWludDMyQXJyYXkodC5idWZmZXIpKS5wbHVzKGUpfX07T3I9Y2xhc3MgT3IgZXh0ZW5kcyBZaHtuZWdhdGUoKXtpZih0aGlzLmJ1ZmZlclswXT1+dGhpcy5idWZmZXJbMF0rMSx0aGlzLmJ1ZmZlclsxXT1+dGhpcy5idWZmZXJbMV0sdGhpcy5idWZmZXJbMF09PTApKyt0aGlzLmJ1ZmZlclsxXTtyZXR1cm4gdGhpc310aW1lcyh0KXtyZXR1cm4gdGhpcy5fdGltZXModCksdGhpc31wbHVzKHQpe3JldHVybiB0aGlzLl9wbHVzKHQpLHRoaXN9bGVzc1RoYW4odCl7bGV0IGU9dGhpcy5idWZmZXJbMV08PDAscj10LmJ1ZmZlclsxXTw8MDtyZXR1cm4gZTxyfHxlPT09ciYmdGhpcy5idWZmZXJbMF08dC5idWZmZXJbMF19c3RhdGljIGZyb20odCxlPW5ldyBVaW50MzJBcnJheSgyKSl7cmV0dXJuIE9yLmZyb21TdHJpbmcodHlwZW9mIHQ9PT0ic3RyaW5nIj90OnQudG9TdHJpbmcoKSxlKX1zdGF0aWMgZnJvbU51bWJlcih0LGU9bmV3IFVpbnQzMkFycmF5KDIpKXtyZXR1cm4gT3IuZnJvbVN0cmluZyh0LnRvU3RyaW5nKCksZSl9c3RhdGljIGZyb21TdHJpbmcodCxlPW5ldyBVaW50MzJBcnJheSgyKSl7bGV0IHI9dC5zdGFydHNXaXRoKCItIiksbj10Lmxlbmd0aCxpPW5ldyBPcihlKTtmb3IobGV0IHM9cj8xOjA7czxuOyl7bGV0IG89Y2w8bi1zP2NsOm4tcyxhPW5ldyBPcihuZXcgVWludDMyQXJyYXkoW051bWJlci5wYXJzZUludCh0LnNsaWNlKHMscytvKSwxMCksMF0pKSxsPW5ldyBPcihuZXcgVWludDMyQXJyYXkoW2NnW29dLDBdKSk7aS50aW1lcyhsKSxpLnBsdXMoYSkscys9b31yZXR1cm4gcj9pLm5lZ2F0ZSgpOml9c3RhdGljIGNvbnZlcnRBcnJheSh0KXtsZXQgZT1uZXcgVWludDMyQXJyYXkodC5sZW5ndGgqMik7Zm9yKGxldCByPS0xLG49dC5sZW5ndGg7KytyPG47KU9yLmZyb20odFtyXSxuZXcgVWludDMyQXJyYXkoZS5idWZmZXIsZS5ieXRlT2Zmc2V0KzIqcio0LDIpKTtyZXR1cm4gZX1zdGF0aWMgbXVsdGlwbHkodCxlKXtyZXR1cm4gbmV3IE9yKG5ldyBVaW50MzJBcnJheSh0LmJ1ZmZlcikpLnRpbWVzKGUpfXN0YXRpYyBhZGQodCxlKXtyZXR1cm4gbmV3IE9yKG5ldyBVaW50MzJBcnJheSh0LmJ1ZmZlcikpLnBsdXMoZSl9fX0pO3ZhciBoZz17fTtaZShoZyx7dG9JbnRlcnZhbERheVRpbWVJbnQzMkFycmF5OigpPT5mZyx0b0ludGVydmFsRGF5VGltZU9iamVjdHM6KCk9Pl9NLHRvSW50ZXJ2YWxNb250aERheU5hbm9JbnQzMkFycmF5OigpPT5kZyx0b0ludGVydmFsTW9udGhEYXlOYW5vT2JqZWN0czooKT0+Z019KTtmdW5jdGlvbiBmZyh0KXt2YXIgZSxyO2xldCBuPXQubGVuZ3RoLGk9bmV3IEludDMyQXJyYXkobioyKTtmb3IobGV0IHM9MCxvPTA7czxuO3MrKyl7bGV0IGE9dFtzXTtpW28rK109KGU9YS5kYXlzKSE9PW51bGwmJmUhPT12b2lkIDA/ZTowLGlbbysrXT0ocj1hLm1pbGxpc2Vjb25kcykhPT1udWxsJiZyIT09dm9pZCAwP3I6MH1yZXR1cm4gaX1mdW5jdGlvbiBkZyh0KXt2YXIgZSxyO2xldCBuPXQubGVuZ3RoLGk9bmV3IEludDMyQXJyYXkobio0KTtmb3IobGV0IHM9MCxvPTA7czxuO3MrKyl7bGV0IGE9dFtzXTtpW28rK109KGU9YS5tb250aHMpIT09bnVsbCYmZSE9PXZvaWQgMD9lOjAsaVtvKytdPShyPWEuZGF5cykhPT1udWxsJiZyIT09dm9pZCAwP3I6MDtsZXQgbD1hLm5hbm9zZWNvbmRzO2lmKGwpe2xldCB1PUJpZ0ludChsKTtpW28rK109TnVtYmVyKHUmQmlnSW50KDQyOTQ5NjcyOTUpKT4+PjAsaVtvKytdPU51bWJlcih1Pj5CaWdJbnQoMzIpKT4+PjB9ZWxzZSBvKz0yfXJldHVybiBpfWZ1bmN0aW9uIF9NKHQpe2xldCBlPXQubGVuZ3RoLHI9QXJyYXkoZS8yKTtmb3IobGV0IG49MCxpPTA7bjxlO24rPTIpcltpKytdPXtkYXlzOnRbbl0sbWlsbGlzZWNvbmRzOnRbbisxXX07cmV0dXJuIHJ9ZnVuY3Rpb24gZ00odCxlKXtsZXQgcj10Lmxlbmd0aCxuPUFycmF5KHIvNCk7Zm9yKGxldCBpPTAscz0wO2k8cjtpKz00KXtsZXQgbz1CaWdJbnQodFtpKzNdKTw8QmlnSW50KDMyKXxCaWdJbnQodFtpKzJdPj4+MCk7bltzKytdPXttb250aHM6dFtpXSxkYXlzOnRbaSsxXSxuYW5vc2Vjb25kczplP2Ake299YDpvfX1yZXR1cm4gbn1mdW5jdGlvbiBpQSh0KXtsZXQgZT1uZXcgVWludDhBcnJheSh0Lmxlbmd0aC8yKTtmb3IobGV0IHI9MDtyPHQubGVuZ3RoO3IrPTIpZVtyPj4xXT1OdW1iZXIucGFyc2VJbnQodC5zbGljZShyLHIrMiksMTYpO3JldHVybiBlfWZ1bmN0aW9uIGJNKHQpe3JldHVybiBpQSh0LmpvaW4oIiIpKX1mdW5jdGlvbiBzQSh0LGUpe2xldCByPW5ldyBVaW50OEFycmF5KHQubGVuZ3RoKjE2KSxuPW5ldyBEYXRhVmlldyhyLmJ1ZmZlcik7Zm9yKGxldFtpLHNdb2YgdC5lbnRyaWVzKCkpe2xldCBvPWkqMTYsYT1zLlNJWkU7aWYobi5zZXRJbnQzMihvLGEsITApLHMuSU5MSU5FRCE9PXZvaWQgMCl7bGV0IGw9ZShzLklOTElORUQpO2ZvcihsZXQgdT0wO3U8bC5sZW5ndGgmJnU8MTI7dSsrKXJbbys0K3VdPWxbdV19ZWxzZXtsZXQgbD1zLlBSRUZJWF9IRVg7Zm9yKGxldCB1PTA7dTw4JiZ1PGwubGVuZ3RoO3UrPTIpcltvKzQrKHU+PjEpXT1OdW1iZXIucGFyc2VJbnQobC5zbGljZSh1LHUrMiksMTYpO24uc2V0SW50MzIobys4LHMuQlVGRkVSX0lOREVYLCEwKSxuLnNldEludDMyKG8rMTIscy5PRkZTRVQsITApfX1yZXR1cm4gcn1mdW5jdGlvbiB3TSh0KXtyZXR1cm4gc0EodCwoZSk9PntsZXQgcj1uZXcgVWludDhBcnJheShlLmxlbmd0aC8yKTtmb3IobGV0IG49MDtuPGUubGVuZ3RoO24rPTIpcltuPj4xXT1OdW1iZXIucGFyc2VJbnQoZS5zbGljZShuLG4rMiksMTYpO3JldHVybiByfSl9ZnVuY3Rpb24gdk0odCl7cmV0dXJuIHNBKHQsKGUpPT5uZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoZSkpfXZhciBMdSxwZyxtZzt2YXIgb0E9bSgoKT0+e3BpKCk7JHIoKTthZSgpO1FpKCk7ZWwoKTtVcygpO3VnKCk7Q2UoKTtZZSgpO0x1PWNsYXNzIEx1IGV4dGVuZHMgc3R7Y29uc3RydWN0b3IodCxlLHIsbixpPUh0LlY1LHM9W10pe3N1cGVyKCk7dGhpcy5ub2Rlc0luZGV4PS0xLHRoaXMuYnVmZmVyc0luZGV4PS0xLHRoaXMudmFyaWFkaWNCdWZmZXJJbmRleD0tMSx0aGlzLmJ5dGVzPXQsdGhpcy5ub2Rlcz1lLHRoaXMuYnVmZmVycz1yLHRoaXMuZGljdGlvbmFyaWVzPW4sdGhpcy5tZXRhZGF0YVZlcnNpb249aSx0aGlzLnZhcmlhZGljQnVmZmVyQ291bnRzPXN9dmlzaXQodCl7cmV0dXJuIHN1cGVyLnZpc2l0KHQgaW5zdGFuY2VvZiBWP3QudHlwZTp0KX12aXNpdE51bGwodCx7bGVuZ3RoOmV9PXRoaXMubmV4dEZpZWxkTm9kZSgpKXtyZXR1cm4geCh7dHlwZTp0LGxlbmd0aDplfSl9dmlzaXRCb29sKHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7cmV0dXJuIHgoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cixudWxsQml0bWFwOnRoaXMucmVhZE51bGxCaXRtYXAodCxyKSxkYXRhOnRoaXMucmVhZERhdGEodCl9KX12aXNpdEludCh0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe3JldHVybiB4KHt0eXBlOnQsbGVuZ3RoOmUsbnVsbENvdW50OnIsbnVsbEJpdG1hcDp0aGlzLnJlYWROdWxsQml0bWFwKHQsciksZGF0YTp0aGlzLnJlYWREYXRhKHQpfSl9dmlzaXRGbG9hdCh0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe3JldHVybiB4KHt0eXBlOnQsbGVuZ3RoOmUsbnVsbENvdW50OnIsbnVsbEJpdG1hcDp0aGlzLnJlYWROdWxsQml0bWFwKHQsciksZGF0YTp0aGlzLnJlYWREYXRhKHQpfSl9dmlzaXRVdGY4KHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7cmV0dXJuIHgoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cixudWxsQml0bWFwOnRoaXMucmVhZE51bGxCaXRtYXAodCxyKSx2YWx1ZU9mZnNldHM6dGhpcy5yZWFkT2Zmc2V0cyh0KSxkYXRhOnRoaXMucmVhZERhdGEodCl9KX12aXNpdExhcmdlVXRmOCh0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe3JldHVybiB4KHt0eXBlOnQsbGVuZ3RoOmUsbnVsbENvdW50OnIsbnVsbEJpdG1hcDp0aGlzLnJlYWROdWxsQml0bWFwKHQsciksdmFsdWVPZmZzZXRzOnRoaXMucmVhZE9mZnNldHModCksZGF0YTp0aGlzLnJlYWREYXRhKHQpfSl9dmlzaXRVdGY4Vmlldyh0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe2xldCBuPXRoaXMucmVhZE51bGxCaXRtYXAodCxyKSxpPXRoaXMucmVhZERhdGEodCkscz10aGlzLnJlYWRWYXJpYWRpY0J1ZmZlcnModGhpcy5uZXh0VmFyaWFkaWNCdWZmZXJDb3VudCgpKTtyZXR1cm4geCh7dHlwZTp0LGxlbmd0aDplLG51bGxDb3VudDpyLG51bGxCaXRtYXA6bixbInZpZXdzIl06aSxbInZhcmlhZGljQnVmZmVycyJdOnN9KX12aXNpdEJpbmFyeSh0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe3JldHVybiB4KHt0eXBlOnQsbGVuZ3RoOmUsbnVsbENvdW50OnIsbnVsbEJpdG1hcDp0aGlzLnJlYWROdWxsQml0bWFwKHQsciksdmFsdWVPZmZzZXRzOnRoaXMucmVhZE9mZnNldHModCksZGF0YTp0aGlzLnJlYWREYXRhKHQpfSl9dmlzaXRMYXJnZUJpbmFyeSh0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe3JldHVybiB4KHt0eXBlOnQsbGVuZ3RoOmUsbnVsbENvdW50OnIsbnVsbEJpdG1hcDp0aGlzLnJlYWROdWxsQml0bWFwKHQsciksdmFsdWVPZmZzZXRzOnRoaXMucmVhZE9mZnNldHModCksZGF0YTp0aGlzLnJlYWREYXRhKHQpfSl9dmlzaXRCaW5hcnlWaWV3KHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7bGV0IG49dGhpcy5yZWFkTnVsbEJpdG1hcCh0LHIpLGk9dGhpcy5yZWFkRGF0YSh0KSxzPXRoaXMucmVhZFZhcmlhZGljQnVmZmVycyh0aGlzLm5leHRWYXJpYWRpY0J1ZmZlckNvdW50KCkpO3JldHVybiB4KHt0eXBlOnQsbGVuZ3RoOmUsbnVsbENvdW50OnIsbnVsbEJpdG1hcDpuLFsidmlld3MiXTppLFsidmFyaWFkaWNCdWZmZXJzIl06c30pfXZpc2l0Rml4ZWRTaXplQmluYXJ5KHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7cmV0dXJuIHgoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cixudWxsQml0bWFwOnRoaXMucmVhZE51bGxCaXRtYXAodCxyKSxkYXRhOnRoaXMucmVhZERhdGEodCl9KX12aXNpdERhdGUodCx7bGVuZ3RoOmUsbnVsbENvdW50OnJ9PXRoaXMubmV4dEZpZWxkTm9kZSgpKXtyZXR1cm4geCh7dHlwZTp0LGxlbmd0aDplLG51bGxDb3VudDpyLG51bGxCaXRtYXA6dGhpcy5yZWFkTnVsbEJpdG1hcCh0LHIpLGRhdGE6dGhpcy5yZWFkRGF0YSh0KX0pfXZpc2l0VGltZXN0YW1wKHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7cmV0dXJuIHgoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cixudWxsQml0bWFwOnRoaXMucmVhZE51bGxCaXRtYXAodCxyKSxkYXRhOnRoaXMucmVhZERhdGEodCl9KX12aXNpdFRpbWUodCx7bGVuZ3RoOmUsbnVsbENvdW50OnJ9PXRoaXMubmV4dEZpZWxkTm9kZSgpKXtyZXR1cm4geCh7dHlwZTp0LGxlbmd0aDplLG51bGxDb3VudDpyLG51bGxCaXRtYXA6dGhpcy5yZWFkTnVsbEJpdG1hcCh0LHIpLGRhdGE6dGhpcy5yZWFkRGF0YSh0KX0pfXZpc2l0RGVjaW1hbCh0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe3JldHVybiB4KHt0eXBlOnQsbGVuZ3RoOmUsbnVsbENvdW50OnIsbnVsbEJpdG1hcDp0aGlzLnJlYWROdWxsQml0bWFwKHQsciksZGF0YTp0aGlzLnJlYWREYXRhKHQpfSl9dmlzaXRMaXN0KHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7cmV0dXJuIHgoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cixudWxsQml0bWFwOnRoaXMucmVhZE51bGxCaXRtYXAodCxyKSx2YWx1ZU9mZnNldHM6dGhpcy5yZWFkT2Zmc2V0cyh0KSxjaGlsZDp0aGlzLnZpc2l0KHQuY2hpbGRyZW5bMF0pfSl9dmlzaXRTdHJ1Y3QodCx7bGVuZ3RoOmUsbnVsbENvdW50OnJ9PXRoaXMubmV4dEZpZWxkTm9kZSgpKXtyZXR1cm4geCh7dHlwZTp0LGxlbmd0aDplLG51bGxDb3VudDpyLG51bGxCaXRtYXA6dGhpcy5yZWFkTnVsbEJpdG1hcCh0LHIpLGNoaWxkcmVuOnRoaXMudmlzaXRNYW55KHQuY2hpbGRyZW4pfSl9dmlzaXRVbmlvbih0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe2lmKHRoaXMubWV0YWRhdGFWZXJzaW9uPEh0LlY1KXRoaXMucmVhZE51bGxCaXRtYXAodCxyKTtyZXR1cm4gdC5tb2RlPT09c2UuU3BhcnNlP3RoaXMudmlzaXRTcGFyc2VVbmlvbih0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn0pOnRoaXMudmlzaXREZW5zZVVuaW9uKHQse2xlbmd0aDplLG51bGxDb3VudDpyfSl9dmlzaXREZW5zZVVuaW9uKHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7cmV0dXJuIHgoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cix0eXBlSWRzOnRoaXMucmVhZFR5cGVJZHModCksdmFsdWVPZmZzZXRzOnRoaXMucmVhZE9mZnNldHModCksY2hpbGRyZW46dGhpcy52aXNpdE1hbnkodC5jaGlsZHJlbil9KX12aXNpdFNwYXJzZVVuaW9uKHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7cmV0dXJuIHgoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cix0eXBlSWRzOnRoaXMucmVhZFR5cGVJZHModCksY2hpbGRyZW46dGhpcy52aXNpdE1hbnkodC5jaGlsZHJlbil9KX12aXNpdERpY3Rpb25hcnkodCx7bGVuZ3RoOmUsbnVsbENvdW50OnJ9PXRoaXMubmV4dEZpZWxkTm9kZSgpKXtyZXR1cm4geCh7dHlwZTp0LGxlbmd0aDplLG51bGxDb3VudDpyLG51bGxCaXRtYXA6dGhpcy5yZWFkTnVsbEJpdG1hcCh0LHIpLGRhdGE6dGhpcy5yZWFkRGF0YSh0LmluZGljZXMpLGRpY3Rpb25hcnk6dGhpcy5yZWFkRGljdGlvbmFyeSh0KX0pfXZpc2l0SW50ZXJ2YWwodCx7bGVuZ3RoOmUsbnVsbENvdW50OnJ9PXRoaXMubmV4dEZpZWxkTm9kZSgpKXtyZXR1cm4geCh7dHlwZTp0LGxlbmd0aDplLG51bGxDb3VudDpyLG51bGxCaXRtYXA6dGhpcy5yZWFkTnVsbEJpdG1hcCh0LHIpLGRhdGE6dGhpcy5yZWFkRGF0YSh0KX0pfXZpc2l0RHVyYXRpb24odCx7bGVuZ3RoOmUsbnVsbENvdW50OnJ9PXRoaXMubmV4dEZpZWxkTm9kZSgpKXtyZXR1cm4geCh7dHlwZTp0LGxlbmd0aDplLG51bGxDb3VudDpyLG51bGxCaXRtYXA6dGhpcy5yZWFkTnVsbEJpdG1hcCh0LHIpLGRhdGE6dGhpcy5yZWFkRGF0YSh0KX0pfXZpc2l0Rml4ZWRTaXplTGlzdCh0LHtsZW5ndGg6ZSxudWxsQ291bnQ6cn09dGhpcy5uZXh0RmllbGROb2RlKCkpe3JldHVybiB4KHt0eXBlOnQsbGVuZ3RoOmUsbnVsbENvdW50OnIsbnVsbEJpdG1hcDp0aGlzLnJlYWROdWxsQml0bWFwKHQsciksY2hpbGQ6dGhpcy52aXNpdCh0LmNoaWxkcmVuWzBdKX0pfXZpc2l0TWFwKHQse2xlbmd0aDplLG51bGxDb3VudDpyfT10aGlzLm5leHRGaWVsZE5vZGUoKSl7cmV0dXJuIHgoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cixudWxsQml0bWFwOnRoaXMucmVhZE51bGxCaXRtYXAodCxyKSx2YWx1ZU9mZnNldHM6dGhpcy5yZWFkT2Zmc2V0cyh0KSxjaGlsZDp0aGlzLnZpc2l0KHQuY2hpbGRyZW5bMF0pfSl9bmV4dEZpZWxkTm9kZSgpe3JldHVybiB0aGlzLm5vZGVzWysrdGhpcy5ub2Rlc0luZGV4XX1uZXh0QnVmZmVyUmFuZ2UoKXtyZXR1cm4gdGhpcy5idWZmZXJzWysrdGhpcy5idWZmZXJzSW5kZXhdfXJlYWROdWxsQml0bWFwKHQsZSxyPXRoaXMubmV4dEJ1ZmZlclJhbmdlKCkpe3JldHVybiBlPjAmJnRoaXMucmVhZERhdGEodCxyKXx8bmV3IFVpbnQ4QXJyYXkoMCl9cmVhZE9mZnNldHModCxlKXtyZXR1cm4gdGhpcy5yZWFkRGF0YSh0LGUpfXJlYWRUeXBlSWRzKHQsZSl7cmV0dXJuIHRoaXMucmVhZERhdGEodCxlKX1yZWFkRGF0YSh0LHtsZW5ndGg6ZSxvZmZzZXQ6cn09dGhpcy5uZXh0QnVmZmVyUmFuZ2UoKSl7cmV0dXJuIHRoaXMuYnl0ZXMuc3ViYXJyYXkocixyK2UpfXJlYWRWYXJpYWRpY0J1ZmZlcnModCl7cmV0dXJuIEFycmF5LmZyb20oe2xlbmd0aDp0fSwoKT0+dGhpcy5yZWFkRGF0YShudWxsKSl9bmV4dFZhcmlhZGljQnVmZmVyQ291bnQoKXt2YXIgdDtyZXR1cm4odD10aGlzLnZhcmlhZGljQnVmZmVyQ291bnRzWysrdGhpcy52YXJpYWRpY0J1ZmZlckluZGV4XSkhPT1udWxsJiZ0IT09dm9pZCAwP3Q6MH1yZWFkRGljdGlvbmFyeSh0KXtyZXR1cm4gdGhpcy5kaWN0aW9uYXJpZXMuZ2V0KHQuaWQpfX07cGc9Y2xhc3MgcGcgZXh0ZW5kcyBMdXtjb25zdHJ1Y3Rvcih0LGUscixuLGkscz1bXSl7c3VwZXIobmV3IFVpbnQ4QXJyYXkoMCksZSxyLG4saSxzKTt0aGlzLnNvdXJjZXM9dH1yZWFkTnVsbEJpdG1hcCh0LGUse29mZnNldDpyfT10aGlzLm5leHRCdWZmZXJSYW5nZSgpKXtyZXR1cm4gZTw9MD9uZXcgVWludDhBcnJheSgwKTp6YSh0aGlzLnNvdXJjZXNbcl0pfXJlYWRPZmZzZXRzKHQse29mZnNldDplfT10aGlzLm5leHRCdWZmZXJSYW5nZSgpKXtyZXR1cm4gdnQoVWludDhBcnJheSx2dCh0Lk9mZnNldEFycmF5VHlwZSx0aGlzLnNvdXJjZXNbZV0pKX1yZWFkVHlwZUlkcyh0LHtvZmZzZXQ6ZX09dGhpcy5uZXh0QnVmZmVyUmFuZ2UoKSl7cmV0dXJuIHZ0KFVpbnQ4QXJyYXksdnQodC5BcnJheVR5cGUsdGhpcy5zb3VyY2VzW2VdKSl9cmVhZERhdGEodCx7b2Zmc2V0OmV9PXRoaXMubmV4dEJ1ZmZlclJhbmdlKCkpe2xldHtzb3VyY2VzOnJ9PXRoaXM7aWYoQS5pc1RpbWVzdGFtcCh0KSlyZXR1cm4gdnQoVWludDhBcnJheSxPci5jb252ZXJ0QXJyYXkocltlXSkpO2Vsc2UgaWYoKEEuaXNJbnQodCl8fEEuaXNUaW1lKHQpKSYmdC5iaXRXaWR0aD09PTY0fHxBLmlzRHVyYXRpb24odCkpcmV0dXJuIHZ0KFVpbnQ4QXJyYXksT3IuY29udmVydEFycmF5KHJbZV0pKTtlbHNlIGlmKEEuaXNEYXRlKHQpJiZ0LnVuaXQ9PT1JZS5NSUxMSVNFQ09ORClyZXR1cm4gdnQoVWludDhBcnJheSxPci5jb252ZXJ0QXJyYXkocltlXSkpO2Vsc2UgaWYoQS5pc0RlY2ltYWwodCkpcmV0dXJuIHZ0KFVpbnQ4QXJyYXkseWkuY29udmVydEFycmF5KHJbZV0pKTtlbHNlIGlmKEEuaXNCaW5hcnkodCl8fEEuaXNMYXJnZUJpbmFyeSh0KXx8QS5pc0ZpeGVkU2l6ZUJpbmFyeSh0KSlyZXR1cm4gYk0ocltlXSk7ZWxzZSBpZihBLmlzQmluYXJ5Vmlldyh0KSlyZXR1cm4gd00ocltlXSk7ZWxzZSBpZihBLmlzVXRmOFZpZXcodCkpcmV0dXJuIHZNKHJbZV0pO2Vsc2UgaWYoQS5pc0Jvb2wodCkpcmV0dXJuIHphKHJbZV0pO2Vsc2UgaWYoQS5pc1V0ZjgodCl8fEEuaXNMYXJnZVV0ZjgodCkpcmV0dXJuIE5uKHJbZV0uam9pbigiIikpO2Vsc2UgaWYoQS5pc0ludGVydmFsKHQpKXN3aXRjaCh0LnVuaXQpe2Nhc2UgY2UuREFZX1RJTUU6cmV0dXJuIGZnKHJbZV0pO2Nhc2UgY2UuTU9OVEhfREFZX05BTk86cmV0dXJuIGRnKHJbZV0pO2RlZmF1bHQ6YnJlYWt9cmV0dXJuIHZ0KFVpbnQ4QXJyYXksdnQodC5BcnJheVR5cGUscltlXS5tYXAoKG4pPT4rbikpKX1yZWFkVmFyaWFkaWNCdWZmZXJzKHQpe2xldCBlPVtdO2ZvcihsZXQgcj0wO3I8dDtyKyspe2xldHtvZmZzZXQ6bn09dGhpcy5uZXh0QnVmZmVyUmFuZ2UoKSxpPXRoaXMuc291cmNlc1tuXTtlLnB1c2goaUEoaSkpfXJldHVybiBlfX07bWc9Y2xhc3MgbWcgZXh0ZW5kcyBMdXtjb25zdHJ1Y3Rvcih0LGUscixuLGkscz1bXSl7c3VwZXIobmV3IFVpbnQ4QXJyYXkoMCksZSxyLG4saSxzKTt0aGlzLmJvZHlDaHVua3M9dH1yZWFkRGF0YSh0LGU9dGhpcy5uZXh0QnVmZmVyUmFuZ2UoKSl7cmV0dXJuIHRoaXMuYm9keUNodW5rc1t0aGlzLmJ1ZmZlcnNJbmRleF19fX0pO3ZhciBVdTt2YXIgeWc9bSgoKT0+e2dzKCk7Z2UoKTtZZSgpO1V1PWNsYXNzIFV1IGV4dGVuZHMgUG57Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5fdmFsdWVzPW5ldyBDbihVaW50OEFycmF5KX1nZXQgYnl0ZUxlbmd0aCgpe2xldCB0PXRoaXMuX3BlbmRpbmdMZW5ndGgrdGhpcy5sZW5ndGgqNDtyZXR1cm4gdGhpcy5fb2Zmc2V0cyYmKHQrPXRoaXMuX29mZnNldHMuYnl0ZUxlbmd0aCksdGhpcy5fdmFsdWVzJiYodCs9dGhpcy5fdmFsdWVzLmJ5dGVMZW5ndGgpLHRoaXMuX251bGxzJiYodCs9dGhpcy5fbnVsbHMuYnl0ZUxlbmd0aCksdH1zZXRWYWx1ZSh0LGUpe3JldHVybiBzdXBlci5zZXRWYWx1ZSh0LGsoZSkpfV9mbHVzaFBlbmRpbmcodCxlKXtsZXQgcj10aGlzLl9vZmZzZXRzLG49dGhpcy5fdmFsdWVzLnJlc2VydmUoZSkuYnVmZmVyLGk9MDtmb3IobGV0W3Msb11vZiB0KWlmKG89PT12b2lkIDApci5zZXQocywwKTtlbHNle2xldCBhPW8ubGVuZ3RoO24uc2V0KG8saSksci5zZXQocyxhKSxpKz1hfX19fSk7dmFyIFJ1O3ZhciBfZz1tKCgpPT57WWUoKTtncygpO2dlKCk7UnU9Y2xhc3MgUnUgZXh0ZW5kcyBQbntjb25zdHJ1Y3Rvcih0KXtzdXBlcih0KTt0aGlzLl92YWx1ZXM9bmV3IENuKFVpbnQ4QXJyYXkpfWdldCBieXRlTGVuZ3RoKCl7bGV0IHQ9dGhpcy5fcGVuZGluZ0xlbmd0aCt0aGlzLmxlbmd0aCo0O3JldHVybiB0aGlzLl9vZmZzZXRzJiYodCs9dGhpcy5fb2Zmc2V0cy5ieXRlTGVuZ3RoKSx0aGlzLl92YWx1ZXMmJih0Kz10aGlzLl92YWx1ZXMuYnl0ZUxlbmd0aCksdGhpcy5fbnVsbHMmJih0Kz10aGlzLl9udWxscy5ieXRlTGVuZ3RoKSx0fXNldFZhbHVlKHQsZSl7cmV0dXJuIHN1cGVyLnNldFZhbHVlKHQsayhlKSl9X2ZsdXNoUGVuZGluZyh0LGUpe2xldCByPXRoaXMuX29mZnNldHMsbj10aGlzLl92YWx1ZXMucmVzZXJ2ZShlKS5idWZmZXIsaT0wO2ZvcihsZXRbcyxvXW9mIHQpaWYobz09PXZvaWQgMClyLnNldChzLEJpZ0ludCgwKSk7ZWxzZXtsZXQgYT1vLmxlbmd0aDtuLnNldChvLGkpLHIuc2V0KHMsQmlnSW50KGEpKSxpKz1hfX19fSk7dmFyIGdnO3ZhciBhQT1tKCgpPT57Z3MoKTtnZSgpO2dnPWNsYXNzIGdnIGV4dGVuZHMgZGV7Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5fdmFsdWVzPW5ldyBOdX1zZXRWYWx1ZSh0LGUpe3RoaXMuX3ZhbHVlcy5zZXQodCwrZSl9fX0pO3ZhciBsbCxLaCxHaDt2YXIgY0E9bSgoKT0+e2dlKCk7Um4oKTtsbD1jbGFzcyBsbCBleHRlbmRzIEdle307bGwucHJvdG90eXBlLl9zZXRWYWx1ZT1XXztLaD1jbGFzcyBLaCBleHRlbmRzIGxse307S2gucHJvdG90eXBlLl9zZXRWYWx1ZT11aDtHaD1jbGFzcyBHaCBleHRlbmRzIGxse307R2gucHJvdG90eXBlLl9zZXRWYWx1ZT1maH0pO3ZhciBKaDt2YXIgbEE9bSgoKT0+e2dlKCk7Um4oKTtKaD1jbGFzcyBKaCBleHRlbmRzIEdle307SmgucHJvdG90eXBlLl9zZXRWYWx1ZT1LX30pO3ZhciBiZzt2YXIgdUE9bSgoKT0+e2FlKCk7Z2UoKTtYaCgpO2JnPWNsYXNzIGJnIGV4dGVuZHMgZGV7Y29uc3RydWN0b3Ioe3R5cGU6dCxudWxsVmFsdWVzOmUsZGljdGlvbmFyeUhhc2hGdW5jdGlvbjpyfSl7c3VwZXIoe3R5cGU6bmV3IEVyKHQuZGljdGlvbmFyeSx0LmluZGljZXMsdC5pZCx0LmlzT3JkZXJlZCl9KTtpZih0aGlzLl9udWxscz1udWxsLHRoaXMuX2RpY3Rpb25hcnlPZmZzZXQ9MCx0aGlzLl9rZXlzVG9JbmRpY2VzPU9iamVjdC5jcmVhdGUobnVsbCksdGhpcy5pbmRpY2VzPVdzKHt0eXBlOnRoaXMudHlwZS5pbmRpY2VzLG51bGxWYWx1ZXM6ZX0pLHRoaXMuZGljdGlvbmFyeT1Xcyh7dHlwZTp0aGlzLnR5cGUuZGljdGlvbmFyeSxudWxsVmFsdWVzOm51bGx9KSx0eXBlb2Ygcj09PSJmdW5jdGlvbiIpdGhpcy52YWx1ZVRvS2V5PXJ9Z2V0IHZhbHVlcygpe3JldHVybiB0aGlzLmluZGljZXMudmFsdWVzfWdldCBudWxsQ291bnQoKXtyZXR1cm4gdGhpcy5pbmRpY2VzLm51bGxDb3VudH1nZXQgbnVsbEJpdG1hcCgpe3JldHVybiB0aGlzLmluZGljZXMubnVsbEJpdG1hcH1nZXQgYnl0ZUxlbmd0aCgpe3JldHVybiB0aGlzLmluZGljZXMuYnl0ZUxlbmd0aCt0aGlzLmRpY3Rpb25hcnkuYnl0ZUxlbmd0aH1nZXQgcmVzZXJ2ZWRMZW5ndGgoKXtyZXR1cm4gdGhpcy5pbmRpY2VzLnJlc2VydmVkTGVuZ3RoK3RoaXMuZGljdGlvbmFyeS5yZXNlcnZlZExlbmd0aH1nZXQgcmVzZXJ2ZWRCeXRlTGVuZ3RoKCl7cmV0dXJuIHRoaXMuaW5kaWNlcy5yZXNlcnZlZEJ5dGVMZW5ndGgrdGhpcy5kaWN0aW9uYXJ5LnJlc2VydmVkQnl0ZUxlbmd0aH1pc1ZhbGlkKHQpe3JldHVybiB0aGlzLmluZGljZXMuaXNWYWxpZCh0KX1zZXRWYWxpZCh0LGUpe2xldCByPXRoaXMuaW5kaWNlcztyZXR1cm4gZT1yLnNldFZhbGlkKHQsZSksdGhpcy5sZW5ndGg9ci5sZW5ndGgsZX1zZXRWYWx1ZSh0LGUpe2xldCByPXRoaXMuX2tleXNUb0luZGljZXMsbj10aGlzLnZhbHVlVG9LZXkoZSksaT1yW25dO2lmKGk9PT12b2lkIDApcltuXT1pPXRoaXMuX2RpY3Rpb25hcnlPZmZzZXQrdGhpcy5kaWN0aW9uYXJ5LmFwcGVuZChlKS5sZW5ndGgtMTtyZXR1cm4gdGhpcy5pbmRpY2VzLnNldFZhbHVlKHQsaSl9Zmx1c2goKXtsZXQgdD10aGlzLnR5cGUsZT10aGlzLl9kaWN0aW9uYXJ5LHI9dGhpcy5kaWN0aW9uYXJ5LnRvVmVjdG9yKCksbj10aGlzLmluZGljZXMuZmx1c2goKS5jbG9uZSh0KTtyZXR1cm4gbi5kaWN0aW9uYXJ5PWU/ZS5jb25jYXQocik6cix0aGlzLmZpbmlzaGVkfHwodGhpcy5fZGljdGlvbmFyeU9mZnNldCs9ci5sZW5ndGgpLHRoaXMuX2RpY3Rpb25hcnk9bi5kaWN0aW9uYXJ5LHRoaXMuY2xlYXIoKSxufWZpbmlzaCgpe3JldHVybiB0aGlzLmluZGljZXMuZmluaXNoKCksdGhpcy5kaWN0aW9uYXJ5LmZpbmlzaCgpLHRoaXMuX2RpY3Rpb25hcnlPZmZzZXQ9MCx0aGlzLl9rZXlzVG9JbmRpY2VzPU9iamVjdC5jcmVhdGUobnVsbCksc3VwZXIuZmluaXNoKCl9Y2xlYXIoKXtyZXR1cm4gdGhpcy5pbmRpY2VzLmNsZWFyKCksdGhpcy5kaWN0aW9uYXJ5LmNsZWFyKCksc3VwZXIuY2xlYXIoKX12YWx1ZVRvS2V5KHQpe3JldHVybiB0eXBlb2YgdD09PSJzdHJpbmciP3Q6YCR7dH1gfX19KTt2YXIgWmg7dmFyIGZBPW0oKCk9PntnZSgpO1JuKCk7Wmg9Y2xhc3MgWmggZXh0ZW5kcyBHZXt9O1poLnByb3RvdHlwZS5fc2V0VmFsdWU9cV99KTt2YXIgd2c7dmFyIGRBPW0oKCk9PnskcigpO2dlKCk7YWUoKTt3Zz1jbGFzcyB3ZyBleHRlbmRzIGRle3NldFZhbHVlKHQsZSl7bGV0W3JdPXRoaXMuY2hpbGRyZW4sbj10KnRoaXMuc3RyaWRlO2ZvcihsZXQgaT0tMSxzPXRoaXMuc3RyaWRlOysraTxzOylyLnNldChuK2ksZVtpXSl9c2V0VmFsaWQodCxlKXtpZighc3VwZXIuc2V0VmFsaWQodCxlKSl0aGlzLmNoaWxkcmVuWzBdLnNldFZhbGlkKCh0KzEpKnRoaXMuc3RyaWRlLTEsITEpO3JldHVybiBlfWFkZENoaWxkKHQsZT0iMCIpe2lmKHRoaXMubnVtQ2hpbGRyZW4+MCl0aHJvdyBFcnJvcigiRml4ZWRTaXplTGlzdEJ1aWxkZXIgY2FuIG9ubHkgaGF2ZSBvbmUgY2hpbGQuIik7bGV0IHI9dGhpcy5jaGlsZHJlbi5wdXNoKHQpO3JldHVybiB0aGlzLnR5cGU9bmV3IFhpKHRoaXMudHlwZS5saXN0U2l6ZSxuZXcgVihlLHQudHlwZSwhMCkpLHJ9fX0pO3ZhciB1bCx2ZyxJZyxCZzt2YXIgaEE9bSgoKT0+e0R1KCk7Z2UoKTt1bD1jbGFzcyB1bCBleHRlbmRzIEdle3NldFZhbHVlKHQsZSl7dGhpcy5fdmFsdWVzLnNldCh0LGUpfX07dmc9Y2xhc3MgdmcgZXh0ZW5kcyB1bHtzZXRWYWx1ZSh0LGUpe3N1cGVyLnNldFZhbHVlKHQsQXUoZSkpfX07SWc9Y2xhc3MgSWcgZXh0ZW5kcyB1bHt9O0JnPWNsYXNzIEJnIGV4dGVuZHMgdWx7fX0pO3ZhciBZYSxRaCx0cCxlcDt2YXIgcEE9bSgoKT0+e2dlKCk7Um4oKTtZYT1jbGFzcyBZYSBleHRlbmRzIEdle307WWEucHJvdG90eXBlLl9zZXRWYWx1ZT1HXztRaD1jbGFzcyBRaCBleHRlbmRzIFlhe307UWgucHJvdG90eXBlLl9zZXRWYWx1ZT13aDt0cD1jbGFzcyB0cCBleHRlbmRzIFlhe307dHAucHJvdG90eXBlLl9zZXRWYWx1ZT12aDtlcD1jbGFzcyBlcCBleHRlbmRzIFlhe307ZXAucHJvdG90eXBlLl9zZXRWYWx1ZT1JaH0pO3ZhciBRbyxycCxucCxpcCxzcDt2YXIgbUE9bSgoKT0+e2dlKCk7Um4oKTtRbz1jbGFzcyBRbyBleHRlbmRzIEdle307UW8ucHJvdG90eXBlLl9zZXRWYWx1ZT1KXztycD1jbGFzcyBycCBleHRlbmRzIFFve307cnAucHJvdG90eXBlLl9zZXRWYWx1ZT1CaDtucD1jbGFzcyBucCBleHRlbmRzIFFve307bnAucHJvdG90eXBlLl9zZXRWYWx1ZT1TaDtpcD1jbGFzcyBpcCBleHRlbmRzIFFve307aXAucHJvdG90eXBlLl9zZXRWYWx1ZT1BaDtzcD1jbGFzcyBzcCBleHRlbmRzIFFve307c3AucHJvdG90eXBlLl9zZXRWYWx1ZT1EaH0pO3ZhciBycyxTZyxBZyxEZyx4ZyxUZyxFZyxPZyxOZzt2YXIgeUE9bSgoKT0+e2dlKCk7cnM9Y2xhc3MgcnMgZXh0ZW5kcyBHZXtzZXRWYWx1ZSh0LGUpe3RoaXMuX3ZhbHVlcy5zZXQodCxlKX19O1NnPWNsYXNzIFNnIGV4dGVuZHMgcnN7fTtBZz1jbGFzcyBBZyBleHRlbmRzIHJze307RGc9Y2xhc3MgRGcgZXh0ZW5kcyByc3t9O3hnPWNsYXNzIHhnIGV4dGVuZHMgcnN7fTtUZz1jbGFzcyBUZyBleHRlbmRzIHJze307RWc9Y2xhc3MgRWcgZXh0ZW5kcyByc3t9O09nPWNsYXNzIE9nIGV4dGVuZHMgcnN7fTtOZz1jbGFzcyBOZyBleHRlbmRzIHJze319KTt2YXIgRmc7dmFyIF9BPW0oKCk9PnskcigpO2FlKCk7Z3MoKTtnZSgpO0ZnPWNsYXNzIEZnIGV4dGVuZHMgUG57Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5fb2Zmc2V0cz1uZXcgRnUodC50eXBlKX1hZGRDaGlsZCh0LGU9IjAiKXtpZih0aGlzLm51bUNoaWxkcmVuPjApdGhyb3cgRXJyb3IoIkxpc3RCdWlsZGVyIGNhbiBvbmx5IGhhdmUgb25lIGNoaWxkLiIpO3JldHVybiB0aGlzLmNoaWxkcmVuW3RoaXMubnVtQ2hpbGRyZW5dPXQsdGhpcy50eXBlPW5ldyBhbihuZXcgVihlLHQudHlwZSwhMCkpLHRoaXMubnVtQ2hpbGRyZW4tMX1fZmx1c2hQZW5kaW5nKHQpe2xldCBlPXRoaXMuX29mZnNldHMsW3JdPXRoaXMuY2hpbGRyZW47Zm9yKGxldFtuLGldb2YgdClpZih0eXBlb2YgaT4idSIpZS5zZXQobiwwKTtlbHNle2xldCBzPWksbz1zLmxlbmd0aCxhPWUuc2V0KG4sbykuYnVmZmVyW25dO2ZvcihsZXQgbD0tMTsrK2w8bzspci5zZXQoYStsLHNbbF0pfX19fSk7dmFyIE1nO3ZhciBnQT1tKCgpPT57JHIoKTthZSgpO2dlKCk7TWc9Y2xhc3MgTWcgZXh0ZW5kcyBQbntzZXQodCxlKXtyZXR1cm4gc3VwZXIuc2V0KHQsZSl9c2V0VmFsdWUodCxlKXtsZXQgcj1lIGluc3RhbmNlb2YgTWFwP2U6bmV3IE1hcChPYmplY3QuZW50cmllcyhlKSksbj10aGlzLl9wZW5kaW5nfHwodGhpcy5fcGVuZGluZz1uZXcgTWFwKSxpPW4uZ2V0KHQpO2kmJih0aGlzLl9wZW5kaW5nTGVuZ3RoLT1pLnNpemUpLHRoaXMuX3BlbmRpbmdMZW5ndGgrPXIuc2l6ZSxuLnNldCh0LHIpfWFkZENoaWxkKHQsZT1gJHt0aGlzLm51bUNoaWxkcmVufWApe2lmKHRoaXMubnVtQ2hpbGRyZW4+MCl0aHJvdyBFcnJvcigiTGlzdEJ1aWxkZXIgY2FuIG9ubHkgaGF2ZSBvbmUgY2hpbGQuIik7cmV0dXJuIHRoaXMuY2hpbGRyZW5bdGhpcy5udW1DaGlsZHJlbl09dCx0aGlzLnR5cGU9bmV3IGhpKG5ldyBWKGUsdC50eXBlLCEwKSx0aGlzLnR5cGUua2V5c1NvcnRlZCksdGhpcy5udW1DaGlsZHJlbi0xfV9mbHVzaFBlbmRpbmcodCl7bGV0IGU9dGhpcy5fb2Zmc2V0cyxbcl09dGhpcy5jaGlsZHJlbjtmb3IobGV0W24saV1vZiB0KWlmKGk9PT12b2lkIDApZS5zZXQobiwwKTtlbHNle2xldHtbbl06cyxbbisxXTpvfT1lLnNldChuLGkuc2l6ZSkuYnVmZmVyO2ZvcihsZXQgYSBvZiBpLmVudHJpZXMoKSlpZihyLnNldChzLGEpLCsrcz49bylicmVha319fX0pO3ZhciBMZzt2YXIgYkE9bSgoKT0+e2dlKCk7TGc9Y2xhc3MgTGcgZXh0ZW5kcyBkZXtzZXRWYWx1ZSh0LGUpe31zZXRWYWxpZCh0LGUpe3JldHVybiB0aGlzLmxlbmd0aD1NYXRoLm1heCh0KzEsdGhpcy5sZW5ndGgpLGV9fX0pO3ZhciBVZzt2YXIgd0E9bSgoKT0+eyRyKCk7Z2UoKTthZSgpO1VnPWNsYXNzIFVnIGV4dGVuZHMgZGV7c2V0VmFsdWUodCxlKXtsZXR7Y2hpbGRyZW46cix0eXBlOm59PXRoaXM7c3dpdGNoKEFycmF5LmlzQXJyYXkoZSl8fGUuY29uc3RydWN0b3Ipe2Nhc2UhMDpyZXR1cm4gbi5jaGlsZHJlbi5mb3JFYWNoKChpLHMpPT5yW3NdLnNldCh0LGVbc10pKTtjYXNlIE1hcDpyZXR1cm4gbi5jaGlsZHJlbi5mb3JFYWNoKChpLHMpPT5yW3NdLnNldCh0LGUuZ2V0KGkubmFtZSkpKTtkZWZhdWx0OnJldHVybiBuLmNoaWxkcmVuLmZvckVhY2goKGkscyk9PnJbc10uc2V0KHQsZVtpLm5hbWVdKSl9fXNldFZhbGlkKHQsZSl7aWYoIXN1cGVyLnNldFZhbGlkKHQsZSkpdGhpcy5jaGlsZHJlbi5mb3JFYWNoKChyKT0+ci5zZXRWYWxpZCh0LGUpKTtyZXR1cm4gZX1hZGRDaGlsZCh0LGU9YCR7dGhpcy5udW1DaGlsZHJlbn1gKXtsZXQgcj10aGlzLmNoaWxkcmVuLnB1c2godCk7cmV0dXJuIHRoaXMudHlwZT1uZXcgT3QoWy4uLnRoaXMudHlwZS5jaGlsZHJlbixuZXcgVihlLHQudHlwZSwhMCldKSxyfX19KTt2YXIgdGEsb3AsYXAsY3AsbHA7dmFyIHZBPW0oKCk9PntnZSgpO1JuKCk7dGE9Y2xhc3MgdGEgZXh0ZW5kcyBHZXt9O3RhLnByb3RvdHlwZS5fc2V0VmFsdWU9SF87b3A9Y2xhc3Mgb3AgZXh0ZW5kcyB0YXt9O29wLnByb3RvdHlwZS5fc2V0VmFsdWU9ZGg7YXA9Y2xhc3MgYXAgZXh0ZW5kcyB0YXt9O2FwLnByb3RvdHlwZS5fc2V0VmFsdWU9aGg7Y3A9Y2xhc3MgY3AgZXh0ZW5kcyB0YXt9O2NwLnByb3RvdHlwZS5fc2V0VmFsdWU9cGg7bHA9Y2xhc3MgbHAgZXh0ZW5kcyB0YXt9O2xwLnByb3RvdHlwZS5fc2V0VmFsdWU9bWh9KTt2YXIgZWEsdXAsZnAsZHAsaHA7dmFyIElBPW0oKCk9PntnZSgpO1JuKCk7ZWE9Y2xhc3MgZWEgZXh0ZW5kcyBHZXt9O2VhLnByb3RvdHlwZS5fc2V0VmFsdWU9WV87dXA9Y2xhc3MgdXAgZXh0ZW5kcyBlYXt9O3VwLnByb3RvdHlwZS5fc2V0VmFsdWU9eWg7ZnA9Y2xhc3MgZnAgZXh0ZW5kcyBlYXt9O2ZwLnByb3RvdHlwZS5fc2V0VmFsdWU9X2g7ZHA9Y2xhc3MgZHAgZXh0ZW5kcyBlYXt9O2RwLnByb3RvdHlwZS5fc2V0VmFsdWU9Z2g7aHA9Y2xhc3MgaHAgZXh0ZW5kcyBlYXt9O2hwLnByb3RvdHlwZS5fc2V0VmFsdWU9Ymh9KTt2YXIgQ3UsUmcsQ2c7dmFyIEJBPW0oKCk9PnskcigpO2dzKCk7Z2UoKTthZSgpO0N1PWNsYXNzIEN1IGV4dGVuZHMgZGV7Y29uc3RydWN0b3IodCl7c3VwZXIodCk7aWYodGhpcy5fdHlwZUlkcz1uZXcgSm8oSW50OEFycmF5LDAsMSksdHlwZW9mIHQudmFsdWVUb0NoaWxkVHlwZUlkPT09ImZ1bmN0aW9uIil0aGlzLl92YWx1ZVRvQ2hpbGRUeXBlSWQ9dC52YWx1ZVRvQ2hpbGRUeXBlSWR9Z2V0IHR5cGVJZFRvQ2hpbGRJbmRleCgpe3JldHVybiB0aGlzLnR5cGUudHlwZUlkVG9DaGlsZEluZGV4fWFwcGVuZCh0LGUpe3JldHVybiB0aGlzLnNldCh0aGlzLmxlbmd0aCx0LGUpfXNldCh0LGUscil7aWYocj09PXZvaWQgMClyPXRoaXMuX3ZhbHVlVG9DaGlsZFR5cGVJZCh0aGlzLGUsdCk7cmV0dXJuIHRoaXMuc2V0VmFsdWUodCxlLHIpLHRoaXN9c2V0VmFsdWUodCxlLHIpe3RoaXMuX3R5cGVJZHMuc2V0KHQscik7bGV0IG49dGhpcy50eXBlLnR5cGVJZFRvQ2hpbGRJbmRleFtyXSxpPXRoaXMuY2hpbGRyZW5bbl07aT09PW51bGx8fGk9PT12b2lkIDB8fGkuc2V0KHQsZSksdGhpcy5sZW5ndGg9TWF0aC5tYXgodCsxLHRoaXMubGVuZ3RoKX1hZGRDaGlsZCh0LGU9YCR7dGhpcy5jaGlsZHJlbi5sZW5ndGh9YCl7bGV0IHI9dGhpcy5jaGlsZHJlbi5wdXNoKHQpLHt0eXBlOntjaGlsZHJlbjpuLG1vZGU6aSx0eXBlSWRzOnN9fT10aGlzLG89Wy4uLm4sbmV3IFYoZSx0LnR5cGUpXTtyZXR1cm4gdGhpcy50eXBlPW5ldyBKaShpLFsuLi5zLHJdLG8pLHJ9X3ZhbHVlVG9DaGlsZFR5cGVJZCh0LGUscil7dGhyb3cgRXJyb3IoIkNhbm5vdCBtYXAgVW5pb25CdWlsZGVyIHZhbHVlIHRvIGNoaWxkIHR5cGVJZC4gUGFzcyB0aGUgYGNoaWxkVHlwZUlkYCBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50IHRvIHVuaW9uQnVpbGRlci5hcHBlbmQoKSwgb3Igc3VwcGx5IGEgYHZhbHVlVG9DaGlsZFR5cGVJZGAgZnVuY3Rpb24gYXMgcGFydCBvZiB0aGUgVW5pb25CdWlsZGVyIGNvbnN0cnVjdG9yIG9wdGlvbnMuIil9fTtSZz1jbGFzcyBSZyBleHRlbmRzIEN1e307Q2c9Y2xhc3MgQ2cgZXh0ZW5kcyBDdXtjb25zdHJ1Y3Rvcih0KXtzdXBlcih0KTt0aGlzLl9vZmZzZXRzPW5ldyBKbyhJbnQzMkFycmF5KX1zZXRWYWx1ZSh0LGUscil7bGV0IG49dGhpcy5fdHlwZUlkcy5zZXQodCxyKS5idWZmZXJbdF0saT10aGlzLmdldENoaWxkQXQodGhpcy50eXBlLnR5cGVJZFRvQ2hpbGRJbmRleFtuXSkscz10aGlzLl9vZmZzZXRzLnNldCh0LGkubGVuZ3RoKS5idWZmZXJbdF07aT09PW51bGx8fGk9PT12b2lkIDB8fGkuc2V0KHMsZSksdGhpcy5sZW5ndGg9TWF0aC5tYXgodCsxLHRoaXMubGVuZ3RoKX19fSk7dmFyIHBwO3ZhciBTQT1tKCgpPT57VXMoKTt5ZygpO2dzKCk7Z2UoKTtwcD1jbGFzcyBwcCBleHRlbmRzIFBue2NvbnN0cnVjdG9yKHQpe3N1cGVyKHQpO3RoaXMuX3ZhbHVlcz1uZXcgQ24oVWludDhBcnJheSl9Z2V0IGJ5dGVMZW5ndGgoKXtsZXQgdD10aGlzLl9wZW5kaW5nTGVuZ3RoK3RoaXMubGVuZ3RoKjQ7cmV0dXJuIHRoaXMuX29mZnNldHMmJih0Kz10aGlzLl9vZmZzZXRzLmJ5dGVMZW5ndGgpLHRoaXMuX3ZhbHVlcyYmKHQrPXRoaXMuX3ZhbHVlcy5ieXRlTGVuZ3RoKSx0aGlzLl9udWxscyYmKHQrPXRoaXMuX251bGxzLmJ5dGVMZW5ndGgpLHR9c2V0VmFsdWUodCxlKXtyZXR1cm4gc3VwZXIuc2V0VmFsdWUodCxObihlKSl9X2ZsdXNoUGVuZGluZyh0LGUpe319O3BwLnByb3RvdHlwZS5fZmx1c2hQZW5kaW5nPVV1LnByb3RvdHlwZS5fZmx1c2hQZW5kaW5nfSk7dmFyIG1wO3ZhciBBQT1tKCgpPT57VXMoKTtncygpO2dlKCk7X2coKTttcD1jbGFzcyBtcCBleHRlbmRzIFBue2NvbnN0cnVjdG9yKHQpe3N1cGVyKHQpO3RoaXMuX3ZhbHVlcz1uZXcgQ24oVWludDhBcnJheSl9Z2V0IGJ5dGVMZW5ndGgoKXtsZXQgdD10aGlzLl9wZW5kaW5nTGVuZ3RoK3RoaXMubGVuZ3RoKjQ7cmV0dXJuIHRoaXMuX29mZnNldHMmJih0Kz10aGlzLl9vZmZzZXRzLmJ5dGVMZW5ndGgpLHRoaXMuX3ZhbHVlcyYmKHQrPXRoaXMuX3ZhbHVlcy5ieXRlTGVuZ3RoKSx0aGlzLl9udWxscyYmKHQrPXRoaXMuX251bGxzLmJ5dGVMZW5ndGgpLHR9c2V0VmFsdWUodCxlKXtyZXR1cm4gc3VwZXIuc2V0VmFsdWUodCxObihlKSl9X2ZsdXNoUGVuZGluZyh0LGUpe319O21wLnByb3RvdHlwZS5fZmx1c2hQZW5kaW5nPVJ1LnByb3RvdHlwZS5fZmx1c2hQZW5kaW5nfSk7dmFyIFB1O3ZhciBQZz1tKCgpPT57YWUoKTtnZSgpO2dzKCk7WWUoKTtwaSgpO1B1PWNsYXNzIFB1IGV4dGVuZHMgZGV7Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5fdmFyaWFkaWNCdWZmZXJzPVtdLHRoaXMuX2N1cnJlbnRCdWZmZXI9bnVsbCx0aGlzLl9jdXJyZW50QnVmZmVySW5kZXg9MCx0aGlzLl9jdXJyZW50QnVmZmVyT2Zmc2V0PTAsdGhpcy5fYnVmZmVyU2l6ZT0zMzU1NDQzMix0aGlzLl92aWV3cz1uZXcgQ24oVWludDhBcnJheSl9Z2V0IGJ5dGVMZW5ndGgoKXtsZXQgdD0wO3RoaXMuX3ZpZXdzJiYodCs9dGhpcy5fdmlld3MuYnl0ZUxlbmd0aCksdGhpcy5fbnVsbHMmJih0Kz10aGlzLl9udWxscy5ieXRlTGVuZ3RoKTtmb3IobGV0IGUgb2YgdGhpcy5fdmFyaWFkaWNCdWZmZXJzKXQrPWUuYnl0ZUxlbmd0aDtyZXR1cm4gdGhpcy5fY3VycmVudEJ1ZmZlciYmKHQrPXRoaXMuX2N1cnJlbnRCdWZmZXIuYnl0ZUxlbmd0aCksdH1zZXRWYWx1ZSh0LGUpe3JldHVybiB0aGlzLndyaXRlQmluYXJ5VmFsdWUodCx0aGlzLmVuY29kZVZhbHVlKGUpKX13cml0ZUJpbmFyeVZhbHVlKHQsZSl7bGV0IHI9ZS5sZW5ndGgsbj0odCsxKSpidC5FTEVNRU5UX1dJRFRILGk9dGhpcy5fdmlld3MubGVuZ3RoO2lmKG4+aSl0aGlzLl92aWV3cy5yZXNlcnZlKG4taSk7bGV0IHM9dGhpcy5fdmlld3MuYnVmZmVyLG89dCpidC5FTEVNRU5UX1dJRFRILGE9bmV3IERhdGFWaWV3KHMuYnVmZmVyLHMuYnl0ZU9mZnNldCtvLGJ0LkVMRU1FTlRfV0lEVEgpO2lmKGEuc2V0SW50MzIoYnQuTEVOR1RIX09GRlNFVCxyLCEwKSxyPD1idC5JTkxJTkVfQ0FQQUNJVFkpe3Muc2V0KGUsbytidC5JTkxJTkVfT0ZGU0VUKTtmb3IobGV0IGw9cjtsPGJ0LklOTElORV9DQVBBQ0lUWTtsKyspc1tvK2J0LklOTElORV9PRkZTRVQrbF09MH1lbHNle2xldCBsPW5ldyBEYXRhVmlldyhlLmJ1ZmZlcixlLmJ5dGVPZmZzZXQsTWF0aC5taW4oNCxyKSk7aWYoYS5zZXRVaW50MzIoYnQuSU5MSU5FX09GRlNFVCxsLmdldFVpbnQzMigwLCEwKSwhMCksIXRoaXMuX2N1cnJlbnRCdWZmZXJ8fHRoaXMuX2N1cnJlbnRCdWZmZXJPZmZzZXQrcj50aGlzLl9idWZmZXJTaXplKXtpZih0aGlzLl9jdXJyZW50QnVmZmVyKXRoaXMuX3ZhcmlhZGljQnVmZmVycy5wdXNoKHRoaXMuX2N1cnJlbnRCdWZmZXIuYnVmZmVyLnNsaWNlKDAsdGhpcy5fY3VycmVudEJ1ZmZlck9mZnNldCkpO3RoaXMuX2N1cnJlbnRCdWZmZXI9bmV3IENuKFVpbnQ4QXJyYXkpLHRoaXMuX2N1cnJlbnRCdWZmZXJJbmRleD10aGlzLl92YXJpYWRpY0J1ZmZlcnMubGVuZ3RoLHRoaXMuX2N1cnJlbnRCdWZmZXJPZmZzZXQ9MH10aGlzLl9jdXJyZW50QnVmZmVyLnJlc2VydmUocikuYnVmZmVyLnNldChlLHRoaXMuX2N1cnJlbnRCdWZmZXJPZmZzZXQpLGEuc2V0SW50MzIoYnQuQlVGRkVSX0lOREVYX09GRlNFVCx0aGlzLl9jdXJyZW50QnVmZmVySW5kZXgsITApLGEuc2V0SW50MzIoYnQuQlVGRkVSX09GRlNFVF9PRkZTRVQsdGhpcy5fY3VycmVudEJ1ZmZlck9mZnNldCwhMCksdGhpcy5fY3VycmVudEJ1ZmZlck9mZnNldCs9cn1yZXR1cm4gdGhpc31lbmNvZGVWYWx1ZSh0KXtyZXR1cm4gayh0KX1zZXRWYWxpZCh0LGUpe2xldCByPSh0KzEpKmJ0LkVMRU1FTlRfV0lEVEgsbj10aGlzLl92aWV3cy5sZW5ndGg7aWYocj5uKXRoaXMuX3ZpZXdzLnJlc2VydmUoci1uKTtsZXQgaT1zdXBlci5zZXRWYWxpZCh0LGUpO2lmKCFpKXtsZXQgcz10aGlzLl92aWV3cy5idWZmZXIsbz10KmJ0LkVMRU1FTlRfV0lEVEg7Zm9yKGxldCBhPTA7YTxidC5FTEVNRU5UX1dJRFRIO2ErKylzW28rYV09MH1yZXR1cm4gaX1jbGVhcigpe3JldHVybiB0aGlzLl92YXJpYWRpY0J1ZmZlcnM9W10sdGhpcy5fY3VycmVudEJ1ZmZlcj1udWxsLHRoaXMuX2N1cnJlbnRCdWZmZXJJbmRleD0wLHRoaXMuX2N1cnJlbnRCdWZmZXJPZmZzZXQ9MCx0aGlzLl92aWV3cy5jbGVhcigpLHN1cGVyLmNsZWFyKCl9Zmx1c2goKXtsZXR7dHlwZTp0LGxlbmd0aDplLG51bGxDb3VudDpyLF92aWV3czpuLF9udWxsczppfT10aGlzO2lmKHRoaXMuX2N1cnJlbnRCdWZmZXImJnRoaXMuX2N1cnJlbnRCdWZmZXJPZmZzZXQ+MCl0aGlzLl92YXJpYWRpY0J1ZmZlcnMucHVzaCh0aGlzLl9jdXJyZW50QnVmZmVyLmJ1ZmZlci5zbGljZSgwLHRoaXMuX2N1cnJlbnRCdWZmZXJPZmZzZXQpKSx0aGlzLl9jdXJyZW50QnVmZmVyPW51bGwsdGhpcy5fY3VycmVudEJ1ZmZlck9mZnNldD0wO2xldCBzPW4uZmx1c2goZSpidC5FTEVNRU5UX1dJRFRIKSxvPXI+MD9pLmZsdXNoKGUpOnZvaWQgMCxhPXRoaXMuX3ZhcmlhZGljQnVmZmVycy5zbGljZSgpO3JldHVybiB0aGlzLl92YXJpYWRpY0J1ZmZlcnM9W10sdGhpcy5fY3VycmVudEJ1ZmZlckluZGV4PTAsdGhpcy5jbGVhcigpLHgoe3R5cGU6dCxsZW5ndGg6ZSxudWxsQ291bnQ6cixudWxsQml0bWFwOm8sWyJ2aWV3cyJdOnMsWyJ2YXJpYWRpY0J1ZmZlcnMiXTphfSl9ZmluaXNoKCl7cmV0dXJuIHRoaXMuZmluaXNoZWQ9ITAsdGhpc319fSk7dmFyIGtnO3ZhciBEQT1tKCgpPT57UGcoKTtVcygpO2tnPWNsYXNzIGtnIGV4dGVuZHMgUHV7Y29uc3RydWN0b3IodCl7c3VwZXIodCl9c2V0VmFsdWUodCxlKXtyZXR1cm4gdGhpcy53cml0ZUJpbmFyeVZhbHVlKHQsTm4oZSkpfX19KTt2YXIgeEEsVEE7dmFyIEVBPW0oKCk9PntRaSgpO3lnKCk7X2coKTthQSgpO2NBKCk7bEEoKTt1QSgpO2ZBKCk7ZEEoKTtoQSgpO3BBKCk7bUEoKTt5QSgpO19BKCk7Z0EoKTtiQSgpO3dBKCk7dkEoKTtJQSgpO0JBKCk7U0EoKTtBQSgpO1BnKCk7REEoKTt4QT1jbGFzcyB4QSBleHRlbmRzIHN0e3Zpc2l0TnVsbCgpe3JldHVybiBMZ312aXNpdEJvb2woKXtyZXR1cm4gZ2d9dmlzaXRJbnQoKXtyZXR1cm4gcnN9dmlzaXRJbnQ4KCl7cmV0dXJuIFNnfXZpc2l0SW50MTYoKXtyZXR1cm4gQWd9dmlzaXRJbnQzMigpe3JldHVybiBEZ312aXNpdEludDY0KCl7cmV0dXJuIHhnfXZpc2l0VWludDgoKXtyZXR1cm4gVGd9dmlzaXRVaW50MTYoKXtyZXR1cm4gRWd9dmlzaXRVaW50MzIoKXtyZXR1cm4gT2d9dmlzaXRVaW50NjQoKXtyZXR1cm4gTmd9dmlzaXRGbG9hdCgpe3JldHVybiB1bH12aXNpdEZsb2F0MTYoKXtyZXR1cm4gdmd9dmlzaXRGbG9hdDMyKCl7cmV0dXJuIElnfXZpc2l0RmxvYXQ2NCgpe3JldHVybiBCZ312aXNpdFV0ZjgoKXtyZXR1cm4gcHB9dmlzaXRMYXJnZVV0ZjgoKXtyZXR1cm4gbXB9dmlzaXRCaW5hcnkoKXtyZXR1cm4gVXV9dmlzaXRMYXJnZUJpbmFyeSgpe3JldHVybiBSdX12aXNpdEZpeGVkU2l6ZUJpbmFyeSgpe3JldHVybiBaaH12aXNpdERhdGUoKXtyZXR1cm4gbGx9dmlzaXREYXRlRGF5KCl7cmV0dXJuIEtofXZpc2l0RGF0ZU1pbGxpc2Vjb25kKCl7cmV0dXJuIEdofXZpc2l0VGltZXN0YW1wKCl7cmV0dXJuIHRhfXZpc2l0VGltZXN0YW1wU2Vjb25kKCl7cmV0dXJuIG9wfXZpc2l0VGltZXN0YW1wTWlsbGlzZWNvbmQoKXtyZXR1cm4gYXB9dmlzaXRUaW1lc3RhbXBNaWNyb3NlY29uZCgpe3JldHVybiBjcH12aXNpdFRpbWVzdGFtcE5hbm9zZWNvbmQoKXtyZXR1cm4gbHB9dmlzaXRUaW1lKCl7cmV0dXJuIGVhfXZpc2l0VGltZVNlY29uZCgpe3JldHVybiB1cH12aXNpdFRpbWVNaWxsaXNlY29uZCgpe3JldHVybiBmcH12aXNpdFRpbWVNaWNyb3NlY29uZCgpe3JldHVybiBkcH12aXNpdFRpbWVOYW5vc2Vjb25kKCl7cmV0dXJuIGhwfXZpc2l0RGVjaW1hbCgpe3JldHVybiBKaH12aXNpdExpc3QoKXtyZXR1cm4gRmd9dmlzaXRTdHJ1Y3QoKXtyZXR1cm4gVWd9dmlzaXRVbmlvbigpe3JldHVybiBDdX12aXNpdERlbnNlVW5pb24oKXtyZXR1cm4gQ2d9dmlzaXRTcGFyc2VVbmlvbigpe3JldHVybiBSZ312aXNpdERpY3Rpb25hcnkoKXtyZXR1cm4gYmd9dmlzaXRJbnRlcnZhbCgpe3JldHVybiBZYX12aXNpdEludGVydmFsRGF5VGltZSgpe3JldHVybiBRaH12aXNpdEludGVydmFsWWVhck1vbnRoKCl7cmV0dXJuIHRwfXZpc2l0SW50ZXJ2YWxNb250aERheU5hbm8oKXtyZXR1cm4gZXB9dmlzaXREdXJhdGlvbigpe3JldHVybiBRb312aXNpdER1cmF0aW9uU2Vjb25kKCl7cmV0dXJuIHJwfXZpc2l0RHVyYXRpb25NaWxsaXNlY29uZCgpe3JldHVybiBucH12aXNpdER1cmF0aW9uTWljcm9zZWNvbmQoKXtyZXR1cm4gaXB9dmlzaXREdXJhdGlvbk5hbm9zZWNvbmQoKXtyZXR1cm4gc3B9dmlzaXRGaXhlZFNpemVMaXN0KCl7cmV0dXJuIHdnfXZpc2l0TWFwKCl7cmV0dXJuIE1nfXZpc2l0QmluYXJ5Vmlldygpe3JldHVybiBQdX12aXNpdFV0ZjhWaWV3KCl7cmV0dXJuIGtnfX07VEE9bmV3IHhBfSk7ZnVuY3Rpb24gV3IodCxlKXtyZXR1cm4gZSBpbnN0YW5jZW9mIHQuY29uc3RydWN0b3J9ZnVuY3Rpb24gSHModCxlKXtyZXR1cm4gdD09PWV8fFdyKHQsZSl9ZnVuY3Rpb24gWXModCxlKXtyZXR1cm4gdD09PWV8fFdyKHQsZSkmJnQuYml0V2lkdGg9PT1lLmJpdFdpZHRoJiZ0LmlzU2lnbmVkPT09ZS5pc1NpZ25lZH1mdW5jdGlvbiB5cCh0LGUpe3JldHVybiB0PT09ZXx8V3IodCxlKSYmdC5wcmVjaXNpb249PT1lLnByZWNpc2lvbn1mdW5jdGlvbiBJTSh0LGUpe3JldHVybiB0PT09ZXx8V3IodCxlKSYmdC5ieXRlV2lkdGg9PT1lLmJ5dGVXaWR0aH1mdW5jdGlvbiBWZyh0LGUpe3JldHVybiB0PT09ZXx8V3IodCxlKSYmdC51bml0PT09ZS51bml0fWZ1bmN0aW9uIGt1KHQsZSl7cmV0dXJuIHQ9PT1lfHxXcih0LGUpJiZ0LnVuaXQ9PT1lLnVuaXQmJnQudGltZXpvbmU9PT1lLnRpbWV6b25lfWZ1bmN0aW9uIFZ1KHQsZSl7cmV0dXJuIHQ9PT1lfHxXcih0LGUpJiZ0LnVuaXQ9PT1lLnVuaXQmJnQuYml0V2lkdGg9PT1lLmJpdFdpZHRofWZ1bmN0aW9uIEJNKHQsZSl7cmV0dXJuIHQ9PT1lfHxXcih0LGUpJiZ0LmNoaWxkcmVuLmxlbmd0aD09PWUuY2hpbGRyZW4ubGVuZ3RoJiZicy5jb21wYXJlTWFueUZpZWxkcyh0LmNoaWxkcmVuLGUuY2hpbGRyZW4pfWZ1bmN0aW9uIFNNKHQsZSl7cmV0dXJuIHQ9PT1lfHxXcih0LGUpJiZ0LmNoaWxkcmVuLmxlbmd0aD09PWUuY2hpbGRyZW4ubGVuZ3RoJiZicy5jb21wYXJlTWFueUZpZWxkcyh0LmNoaWxkcmVuLGUuY2hpbGRyZW4pfWZ1bmN0aW9uIHpnKHQsZSl7cmV0dXJuIHQ9PT1lfHxXcih0LGUpJiZ0Lm1vZGU9PT1lLm1vZGUmJnQudHlwZUlkcy5ldmVyeSgocixuKT0+cj09PWUudHlwZUlkc1tuXSkmJmJzLmNvbXBhcmVNYW55RmllbGRzKHQuY2hpbGRyZW4sZS5jaGlsZHJlbil9ZnVuY3Rpb24gQU0odCxlKXtyZXR1cm4gdD09PWV8fFdyKHQsZSkmJnQuaWQ9PT1lLmlkJiZ0LmlzT3JkZXJlZD09PWUuaXNPcmRlcmVkJiZicy52aXNpdCh0LmluZGljZXMsZS5pbmRpY2VzKSYmYnMudmlzaXQodC5kaWN0aW9uYXJ5LGUuZGljdGlvbmFyeSl9ZnVuY3Rpb24gX3AodCxlKXtyZXR1cm4gdD09PWV8fFdyKHQsZSkmJnQudW5pdD09PWUudW5pdH1mdW5jdGlvbiB6dSh0LGUpe3JldHVybiB0PT09ZXx8V3IodCxlKSYmdC51bml0PT09ZS51bml0fWZ1bmN0aW9uIERNKHQsZSl7cmV0dXJuIHQ9PT1lfHxXcih0LGUpJiZ0Lmxpc3RTaXplPT09ZS5saXN0U2l6ZSYmdC5jaGlsZHJlbi5sZW5ndGg9PT1lLmNoaWxkcmVuLmxlbmd0aCYmYnMuY29tcGFyZU1hbnlGaWVsZHModC5jaGlsZHJlbixlLmNoaWxkcmVuKX1mdW5jdGlvbiB4TSh0LGUpe3JldHVybiB0PT09ZXx8V3IodCxlKSYmdC5rZXlzU29ydGVkPT09ZS5rZXlzU29ydGVkJiZ0LmNoaWxkcmVuLmxlbmd0aD09PWUuY2hpbGRyZW4ubGVuZ3RoJiZicy5jb21wYXJlTWFueUZpZWxkcyh0LmNoaWxkcmVuLGUuY2hpbGRyZW4pfWZ1bmN0aW9uIEthKHQsZSl7cmV0dXJuIGJzLmNvbXBhcmVTY2hlbWFzKHQsZSl9ZnVuY3Rpb24gT0EodCxlKXtyZXR1cm4gYnMuY29tcGFyZUZpZWxkcyh0LGUpfWZ1bmN0aW9uIGdwKHQsZSl7cmV0dXJuIGJzLnZpc2l0KHQsZSl9dmFyIFgsYnM7dmFyIGp1PW0oKCk9PntRaSgpO1g9Y2xhc3MgWCBleHRlbmRzIHN0e2NvbXBhcmVTY2hlbWFzKHQsZSl7cmV0dXJuIHQ9PT1lfHxlIGluc3RhbmNlb2YgdC5jb25zdHJ1Y3RvciYmdGhpcy5jb21wYXJlTWFueUZpZWxkcyh0LmZpZWxkcyxlLmZpZWxkcyl9Y29tcGFyZU1hbnlGaWVsZHModCxlKXtyZXR1cm4gdD09PWV8fEFycmF5LmlzQXJyYXkodCkmJkFycmF5LmlzQXJyYXkoZSkmJnQubGVuZ3RoPT09ZS5sZW5ndGgmJnQuZXZlcnkoKHIsbik9PnRoaXMuY29tcGFyZUZpZWxkcyhyLGVbbl0pKX1jb21wYXJlRmllbGRzKHQsZSl7cmV0dXJuIHQ9PT1lfHxlIGluc3RhbmNlb2YgdC5jb25zdHJ1Y3RvciYmdC5uYW1lPT09ZS5uYW1lJiZ0Lm51bGxhYmxlPT09ZS5udWxsYWJsZSYmdGhpcy52aXNpdCh0LnR5cGUsZS50eXBlKX19O1gucHJvdG90eXBlLnZpc2l0TnVsbD1IcztYLnByb3RvdHlwZS52aXNpdEJvb2w9SHM7WC5wcm90b3R5cGUudmlzaXRJbnQ9WXM7WC5wcm90b3R5cGUudmlzaXRJbnQ4PVlzO1gucHJvdG90eXBlLnZpc2l0SW50MTY9WXM7WC5wcm90b3R5cGUudmlzaXRJbnQzMj1ZcztYLnByb3RvdHlwZS52aXNpdEludDY0PVlzO1gucHJvdG90eXBlLnZpc2l0VWludDg9WXM7WC5wcm90b3R5cGUudmlzaXRVaW50MTY9WXM7WC5wcm90b3R5cGUudmlzaXRVaW50MzI9WXM7WC5wcm90b3R5cGUudmlzaXRVaW50NjQ9WXM7WC5wcm90b3R5cGUudmlzaXRGbG9hdD15cDtYLnByb3RvdHlwZS52aXNpdEZsb2F0MTY9eXA7WC5wcm90b3R5cGUudmlzaXRGbG9hdDMyPXlwO1gucHJvdG90eXBlLnZpc2l0RmxvYXQ2ND15cDtYLnByb3RvdHlwZS52aXNpdFV0Zjg9SHM7WC5wcm90b3R5cGUudmlzaXRMYXJnZVV0Zjg9SHM7WC5wcm90b3R5cGUudmlzaXRVdGY4Vmlldz1IcztYLnByb3RvdHlwZS52aXNpdEJpbmFyeT1IcztYLnByb3RvdHlwZS52aXNpdExhcmdlQmluYXJ5PUhzO1gucHJvdG90eXBlLnZpc2l0QmluYXJ5Vmlldz1IcztYLnByb3RvdHlwZS52aXNpdEZpeGVkU2l6ZUJpbmFyeT1JTTtYLnByb3RvdHlwZS52aXNpdERhdGU9Vmc7WC5wcm90b3R5cGUudmlzaXREYXRlRGF5PVZnO1gucHJvdG90eXBlLnZpc2l0RGF0ZU1pbGxpc2Vjb25kPVZnO1gucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wPWt1O1gucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wU2Vjb25kPWt1O1gucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wTWlsbGlzZWNvbmQ9a3U7WC5wcm90b3R5cGUudmlzaXRUaW1lc3RhbXBNaWNyb3NlY29uZD1rdTtYLnByb3RvdHlwZS52aXNpdFRpbWVzdGFtcE5hbm9zZWNvbmQ9a3U7WC5wcm90b3R5cGUudmlzaXRUaW1lPVZ1O1gucHJvdG90eXBlLnZpc2l0VGltZVNlY29uZD1WdTtYLnByb3RvdHlwZS52aXNpdFRpbWVNaWxsaXNlY29uZD1WdTtYLnByb3RvdHlwZS52aXNpdFRpbWVNaWNyb3NlY29uZD1WdTtYLnByb3RvdHlwZS52aXNpdFRpbWVOYW5vc2Vjb25kPVZ1O1gucHJvdG90eXBlLnZpc2l0RGVjaW1hbD1IcztYLnByb3RvdHlwZS52aXNpdExpc3Q9Qk07WC5wcm90b3R5cGUudmlzaXRTdHJ1Y3Q9U007WC5wcm90b3R5cGUudmlzaXRVbmlvbj16ZztYLnByb3RvdHlwZS52aXNpdERlbnNlVW5pb249emc7WC5wcm90b3R5cGUudmlzaXRTcGFyc2VVbmlvbj16ZztYLnByb3RvdHlwZS52aXNpdERpY3Rpb25hcnk9QU07WC5wcm90b3R5cGUudmlzaXRJbnRlcnZhbD1fcDtYLnByb3RvdHlwZS52aXNpdEludGVydmFsRGF5VGltZT1fcDtYLnByb3RvdHlwZS52aXNpdEludGVydmFsWWVhck1vbnRoPV9wO1gucHJvdG90eXBlLnZpc2l0SW50ZXJ2YWxNb250aERheU5hbm89X3A7WC5wcm90b3R5cGUudmlzaXREdXJhdGlvbj16dTtYLnByb3RvdHlwZS52aXNpdER1cmF0aW9uU2Vjb25kPXp1O1gucHJvdG90eXBlLnZpc2l0RHVyYXRpb25NaWxsaXNlY29uZD16dTtYLnByb3RvdHlwZS52aXNpdER1cmF0aW9uTWljcm9zZWNvbmQ9enU7WC5wcm90b3R5cGUudmlzaXREdXJhdGlvbk5hbm9zZWNvbmQ9enU7WC5wcm90b3R5cGUudmlzaXRGaXhlZFNpemVMaXN0PURNO1gucHJvdG90eXBlLnZpc2l0TWFwPXhNO2JzPW5ldyBYfSk7ZnVuY3Rpb24gV3ModCl7bGV0IGU9dC50eXBlLHI9bmV3KFRBLmdldFZpc2l0Rm4oZSkoKSkodCk7aWYoZS5jaGlsZHJlbiYmZS5jaGlsZHJlbi5sZW5ndGg+MCl7bGV0IG49dC5jaGlsZHJlbnx8W10saT17bnVsbFZhbHVlczp0Lm51bGxWYWx1ZXN9LHM9QXJyYXkuaXNBcnJheShuKT8obyxhKT0+blthXXx8aTooe25hbWU6b30pPT5uW29dfHxpO2ZvcihsZXRbbyxhXW9mIGUuY2hpbGRyZW4uZW50cmllcygpKXtsZXR7dHlwZTpsfT1hLHU9cyhhLG8pO3IuY2hpbGRyZW4ucHVzaChXcyhPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sdSkse3R5cGU6bH0pKSl9fXJldHVybiByfWZ1bmN0aW9uIEdhKHQsZSl7aWYodCBpbnN0YW5jZW9mIGh0fHx0IGluc3RhbmNlb2YgRnx8dC50eXBlIGluc3RhbmNlb2YgQSlyZXR1cm4gJGEodCk7aWYoQXJyYXlCdWZmZXIuaXNWaWV3KHQpJiYhZSlyZXR1cm4gJGEodCk7aWYoQXJyYXlCdWZmZXIuaXNWaWV3KHQpJiZlKXtsZXQgcz10IGluc3RhbmNlb2YgQmlnSW50NjRBcnJheXx8dCBpbnN0YW5jZW9mIEJpZ1VpbnQ2NEFycmF5LG89ZS5BcnJheVR5cGU9PT1CaWdJbnQ2NEFycmF5fHxlLkFycmF5VHlwZT09PUJpZ1VpbnQ2NEFycmF5O2lmKHMmJiFvKXRocm93IFR5cGVFcnJvcihgQ2Fubm90IGNvbnZlcnQgQmlnSW50IGlucHV0IHRvICR7ZX0uIEJpZ0ludCBhcnJheXMgY2FuIG9ubHkgdGFyZ2V0IEJpZ0ludC1iYXNlZCB0eXBlcyAoZS5nLiBJbnQ2NCwgVWludDY0KS5gKTtpZighcyYmbyl0aHJvdyBUeXBlRXJyb3IoYENhbm5vdCBjb252ZXJ0IG5vbi1CaWdJbnQgaW5wdXQgdG8gJHtlfS4gJHtlfSByZXF1aXJlcyBCaWdJbnQgdmFsdWVzLmApO2lmKEEuaXNJbnQoZSl8fEEuaXNGbG9hdChlKSl7bGV0IGE9dC5jb25zdHJ1Y3Rvcj09PWUuQXJyYXlUeXBlP3Q6bmV3IGUuQXJyYXlUeXBlKHQpO3JldHVybiAkYSh7dHlwZTplLGRhdGE6YSxvZmZzZXQ6MCxsZW5ndGg6YS5sZW5ndGgsbnVsbENvdW50OjB9KX19bGV0IHI9e3R5cGU6ZSE9PW51bGwmJmUhPT12b2lkIDA/ZTpicCh0KSxudWxsVmFsdWVzOltudWxsXX0sbj1bLi4uamcocikodCldLGk9bi5sZW5ndGg9PT0xP25bMF06bi5yZWR1Y2UoKHMsbyk9PnMuY29uY2F0KG8pKTtpZihBLmlzRGljdGlvbmFyeShpLnR5cGUpKXJldHVybiBpLm1lbW9pemUoKTtyZXR1cm4gaX1mdW5jdGlvbiBicCh0KXtpZih0Lmxlbmd0aD09PTApcmV0dXJuIG5ldyBucjtsZXQgZT0wLHI9MCxuPTAsaT0wLHM9MCxvPTAsYT0wLGw9MDtmb3IobGV0IHUgb2YgdCl7aWYodT09bnVsbCl7KytlO2NvbnRpbnVlfXN3aXRjaCh0eXBlb2YgdSl7Y2FzZSJiaWdpbnQiOisrbztjb250aW51ZTtjYXNlImJvb2xlYW4iOisrYTtjb250aW51ZTtjYXNlIm51bWJlciI6KytpO2NvbnRpbnVlO2Nhc2Uic3RyaW5nIjorK3M7Y29udGludWU7Y2FzZSJvYmplY3QiOmlmKEFycmF5LmlzQXJyYXkodSkpKytyO2Vsc2UgaWYoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHUpPT09IltvYmplY3QgRGF0ZV0iKSsrbDtlbHNlKytuO2NvbnRpbnVlfXRocm93IFR5cGVFcnJvcigiVW5hYmxlIHRvIGluZmVyIFZlY3RvciB0eXBlIGZyb20gaW5wdXQgdmFsdWVzLCBleHBsaWNpdCB0eXBlIGRlY2xhcmF0aW9uIGV4cGVjdGVkLiIpfWlmKGkrZT09PXQubGVuZ3RoKXJldHVybiBuZXcgWmk7ZWxzZSBpZihzK2U9PT10Lmxlbmd0aClyZXR1cm4gbmV3IEVyKG5ldyBUcixuZXcganIpO2Vsc2UgaWYobytlPT09dC5sZW5ndGgpcmV0dXJuIG5ldyBjbjtlbHNlIGlmKGErZT09PXQubGVuZ3RoKXJldHVybiBuZXcgb247ZWxzZSBpZihsK2U9PT10Lmxlbmd0aClyZXR1cm4gbmV3IFN1O2Vsc2UgaWYocitlPT09dC5sZW5ndGgpe2xldCB1PXQsZj1icCh1W3UuZmluZEluZGV4KChwKT0+cCE9bnVsbCldKTtpZih1LmV2ZXJ5KChwKT0+cD09bnVsbHx8Z3AoZixicChwKSkpKXJldHVybiBuZXcgYW4obmV3IFYoIiIsZiwhMCkpfWVsc2UgaWYobitlPT09dC5sZW5ndGgpe2xldCB1PW5ldyBNYXA7Zm9yKGxldCBmIG9mIHQpZm9yKGxldCBwIG9mIE9iamVjdC5rZXlzKGYpKWlmKCF1LmhhcyhwKSYmZltwXSE9bnVsbCl1LnNldChwLG5ldyBWKHAsYnAoW2ZbcF1dKSwhMCkpO3JldHVybiBuZXcgT3QoWy4uLnUudmFsdWVzKCldKX10aHJvdyBUeXBlRXJyb3IoIlVuYWJsZSB0byBpbmZlciBWZWN0b3IgdHlwZSBmcm9tIGlucHV0IHZhbHVlcywgZXhwbGljaXQgdHlwZSBkZWNsYXJhdGlvbiBleHBlY3RlZC4iKX1mdW5jdGlvbiBqZyh0KXtsZXR7WyJxdWV1ZWluZ1N0cmF0ZWd5Il06ZT0iY291bnQifT10LHtbImhpZ2hXYXRlck1hcmsiXTpyPWUhPT0iYnl0ZXMiP051bWJlci5QT1NJVElWRV9JTkZJTklUWTpNYXRoLnBvdygyLDE0KX09dCxuPWUhPT0iYnl0ZXMiPyJsZW5ndGgiOiJieXRlTGVuZ3RoIjtyZXR1cm4gZnVuY3Rpb24qKGkpe2xldCBzPTAsbz1Xcyh0KTtmb3IobGV0IGEgb2YgaSlpZihvLmFwcGVuZChhKVtuXT49cikrK3MmJih5aWVsZCBvLnRvVmVjdG9yKCkpO2lmKG8uZmluaXNoKCkubGVuZ3RoPjB8fHM9PT0wKXlpZWxkIG8udG9WZWN0b3IoKX19dmFyIFhoPW0oKCk9PnskcigpO2FlKCk7cGkoKTtsbigpO0VBKCk7anUoKX0pO2Z1bmN0aW9uIHdwKHQsZSl7cmV0dXJuIFRNKHQsZS5tYXAoKHIpPT5yLmRhdGEuY29uY2F0KCkpKX1mdW5jdGlvbiBUTSh0LGUpe2xldCByPVsuLi50LmZpZWxkc10sbj1bXSxpPXtudW1CYXRjaGVzOmUucmVkdWNlKChwLGcpPT5NYXRoLm1heChwLGcubGVuZ3RoKSwwKX0scz0wLG89MCxhPS0xLGw9ZS5sZW5ndGgsdSxmPVtdO3doaWxlKGkubnVtQmF0Y2hlcy0tID4wKXtmb3Iobz1OdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFksYT0tMTsrK2E8bDspZlthXT11PWVbYV0uc2hpZnQoKSxvPU1hdGgubWluKG8sdT91Lmxlbmd0aDpvKTtpZihOdW1iZXIuaXNGaW5pdGUobykpe2lmKGY9RU0ocixvLGYsZSxpKSxvPjApbltzKytdPXgoe3R5cGU6bmV3IE90KHIpLGxlbmd0aDpvLG51bGxDb3VudDowLGNoaWxkcmVuOmYuc2xpY2UoKX0pfX1yZXR1cm5bdD10LmFzc2lnbihyKSxuLm1hcCgocCk9Pm5ldyBJdCh0LHApKV19ZnVuY3Rpb24gRU0odCxlLHIsbixpKXt2YXIgcztsZXQgbz0oZSs2MyYtNjQpPj4zO2ZvcihsZXQgYT0tMSxsPW4ubGVuZ3RoOysrYTxsOyl7bGV0IHU9clthXSxmPXU9PT1udWxsfHx1PT09dm9pZCAwP3ZvaWQgMDp1Lmxlbmd0aDtpZihmPj1lKWlmKGY9PT1lKXJbYV09dTtlbHNlIHJbYV09dS5zbGljZSgwLGUpLGkubnVtQmF0Y2hlcz1NYXRoLm1heChpLm51bUJhdGNoZXMsblthXS51bnNoaWZ0KHUuc2xpY2UoZSxmLWUpKSk7ZWxzZXtsZXQgcD10W2FdO3RbYV09cC5jbG9uZSh7bnVsbGFibGU6ITB9KSxyW2FdPShzPXU9PT1udWxsfHx1PT09dm9pZCAwP3ZvaWQgMDp1Ll9jaGFuZ2VMZW5ndGhBbmRCYWNrZmlsbE51bGxCaXRtYXAoZSkpIT09bnVsbCYmcyE9PXZvaWQgMD9zOngoe3R5cGU6cC50eXBlLGxlbmd0aDplLG51bGxDb3VudDplLG51bGxCaXRtYXA6bmV3IFVpbnQ4QXJyYXkobyl9KX19cmV0dXJuIHJ9dmFyIE5BPW0oKCk9PntwaSgpO2FlKCk7cmEoKX0pO3ZhciBGQSxNQSxGZTt2YXIgdnA9bSgoKT0+e0NlKCk7cGkoKTtsbigpOyRyKCk7YWUoKTtqdSgpO05BKCk7Q2goKTtQYSgpO1JuKCk7UGgoKTtraCgpO1FjKCk7cmEoKTtNQT1TeW1ib2wuZm9yKCJhcGFjaGUtYXJyb3cvVGFibGUiKTtGZT1jbGFzcyBGZXtzdGF0aWMgaXNUYWJsZSh0KXtyZXR1cm4odD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnRbTUFdKT09PSEwfWNvbnN0cnVjdG9yKC4uLnQpe3ZhciBlLHI7aWYodC5sZW5ndGg9PT0wKXJldHVybiB0aGlzLmJhdGNoZXM9W10sdGhpcy5zY2hlbWE9bmV3IGooW10pLHRoaXMuX29mZnNldHM9WzBdLHRoaXM7bGV0IG4saTtpZih0WzBdaW5zdGFuY2VvZiBqKW49dC5zaGlmdCgpO2lmKHQuYXQoLTEpaW5zdGFuY2VvZiBVaW50MzJBcnJheSlpPXQucG9wKCk7bGV0IHM9KGEpPT57aWYoYSl7aWYoYSBpbnN0YW5jZW9mIEl0KXJldHVyblthXTtlbHNlIGlmKGEgaW5zdGFuY2VvZiBGZSlyZXR1cm4gYS5iYXRjaGVzO2Vsc2UgaWYoYSBpbnN0YW5jZW9mIGh0KXtpZihhLnR5cGUgaW5zdGFuY2VvZiBPdClyZXR1cm5bbmV3IEl0KG5ldyBqKGEudHlwZS5jaGlsZHJlbiksYSldfWVsc2UgaWYoQXJyYXkuaXNBcnJheShhKSlyZXR1cm4gYS5mbGF0TWFwKChsKT0+cyhsKSk7ZWxzZSBpZih0eXBlb2YgYVtTeW1ib2wuaXRlcmF0b3JdPT09ImZ1bmN0aW9uIilyZXR1cm5bLi4uYV0uZmxhdE1hcCgobCk9PnMobCkpO2Vsc2UgaWYodHlwZW9mIGE9PT0ib2JqZWN0Iil7bGV0IGw9T2JqZWN0LmtleXMoYSksdT1sLm1hcCgoZyk9Pm5ldyBGKFthW2ddXSkpLGY9biE9PW51bGwmJm4hPT12b2lkIDA/bjpuZXcgaihsLm1hcCgoZyx2KT0+bmV3IFYoU3RyaW5nKGcpLHVbdl0udHlwZSx1W3ZdLm51bGxhYmxlKSkpLFsscF09d3AoZix1KTtyZXR1cm4gcC5sZW5ndGg9PT0wP1tuZXcgSXQoYSldOnB9fXJldHVybltdfSxvPXQuZmxhdE1hcCgoYSk9PnMoYSkpO2lmKG49KHI9biE9PW51bGwmJm4hPT12b2lkIDA/bjooZT1vWzBdKT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUuc2NoZW1hKSE9PW51bGwmJnIhPT12b2lkIDA/cjpuZXcgaihbXSksIShuIGluc3RhbmNlb2YgaikpdGhyb3cgVHlwZUVycm9yKCJUYWJsZSBjb25zdHJ1Y3RvciBleHBlY3RzIGEgW1NjaGVtYSwgUmVjb3JkQmF0Y2hbXV0gcGFpci4iKTtmb3IobGV0IGEgb2Ygbyl7aWYoIShhIGluc3RhbmNlb2YgSXQpKXRocm93IFR5cGVFcnJvcigiVGFibGUgY29uc3RydWN0b3IgZXhwZWN0cyBhIFtTY2hlbWEsIFJlY29yZEJhdGNoW11dIHBhaXIuIik7aWYoIUthKG4sYS5zY2hlbWEpKXRocm93IFR5cGVFcnJvcigiVGFibGUgYW5kIGlubmVyIFJlY29yZEJhdGNoIHNjaGVtYXMgbXVzdCBiZSBlcXVpdmFsZW50LiIpfXRoaXMuc2NoZW1hPW4sdGhpcy5iYXRjaGVzPW8sdGhpcy5fb2Zmc2V0cz1pIT09bnVsbCYmaSE9PXZvaWQgMD9pOk1oKHRoaXMuZGF0YSl9Z2V0IGRhdGEoKXtyZXR1cm4gdGhpcy5iYXRjaGVzLm1hcCgoe2RhdGE6dH0pPT50KX1nZXQgbnVtQ29scygpe3JldHVybiB0aGlzLnNjaGVtYS5maWVsZHMubGVuZ3RofWdldCBudW1Sb3dzKCl7cmV0dXJuIHRoaXMuZGF0YS5yZWR1Y2UoKHQsZSk9PnQrZS5sZW5ndGgsMCl9Z2V0IG51bGxDb3VudCgpe2lmKHRoaXMuX251bGxDb3VudD09PS0xKXRoaXMuX251bGxDb3VudD1GaCh0aGlzLmRhdGEpO3JldHVybiB0aGlzLl9udWxsQ291bnR9aXNWYWxpZCh0KXtyZXR1cm4hMX1nZXQodCl7cmV0dXJuIG51bGx9YXQodCl7cmV0dXJuIHRoaXMuZ2V0KGthKHQsdGhpcy5udW1Sb3dzKSl9c2V0KHQsZSl7cmV0dXJufWluZGV4T2YodCxlKXtyZXR1cm4tMX1bU3ltYm9sLml0ZXJhdG9yXSgpe2lmKHRoaXMuYmF0Y2hlcy5sZW5ndGg+MClyZXR1cm4gbmwudmlzaXQobmV3IEYodGhpcy5kYXRhKSk7cmV0dXJuW11bU3ltYm9sLml0ZXJhdG9yXSgpfXRvQXJyYXkoKXtyZXR1cm5bLi4udGhpc119dG9TdHJpbmcoKXtyZXR1cm5gWwogICR7dGhpcy50b0FycmF5KCkuam9pbihgLAogIGApfQpdYH1jb25jYXQoLi4udCl7bGV0IGU9dGhpcy5zY2hlbWEscj10aGlzLmRhdGEuY29uY2F0KHQuZmxhdE1hcCgoe2RhdGE6bn0pPT5uKSk7cmV0dXJuIG5ldyBGZShlLHIubWFwKChuKT0+bmV3IEl0KGUsbikpKX1zbGljZSh0LGUpe2xldCByPXRoaXMuc2NoZW1hO1t0LGVdPXh1KHtsZW5ndGg6dGhpcy5udW1Sb3dzfSx0LGUpO2xldCBuPUxoKHRoaXMuZGF0YSx0aGlzLl9vZmZzZXRzLHQsZSk7cmV0dXJuIG5ldyBGZShyLG4ubWFwKChpKT0+bmV3IEl0KHIsaSkpKX1nZXRDaGlsZCh0KXtyZXR1cm4gdGhpcy5nZXRDaGlsZEF0KHRoaXMuc2NoZW1hLmZpZWxkcy5maW5kSW5kZXgoKGUpPT5lLm5hbWU9PT10KSl9Z2V0Q2hpbGRBdCh0KXtpZih0Pi0xJiZ0PHRoaXMuc2NoZW1hLmZpZWxkcy5sZW5ndGgpe2xldCBlPXRoaXMuZGF0YS5tYXAoKHIpPT5yLmNoaWxkcmVuW3RdKTtpZihlLmxlbmd0aD09PTApe2xldHt0eXBlOnJ9PXRoaXMuc2NoZW1hLmZpZWxkc1t0XSxuPXgoe3R5cGU6cixsZW5ndGg6MCxudWxsQ291bnQ6MH0pO2UucHVzaChuLl9jaGFuZ2VMZW5ndGhBbmRCYWNrZmlsbE51bGxCaXRtYXAodGhpcy5udW1Sb3dzKSl9cmV0dXJuIG5ldyBGKGUpfXJldHVybiBudWxsfXNldENoaWxkKHQsZSl7dmFyIHI7cmV0dXJuIHRoaXMuc2V0Q2hpbGRBdCgocj10aGlzLnNjaGVtYS5maWVsZHMpPT09bnVsbHx8cj09PXZvaWQgMD92b2lkIDA6ci5maW5kSW5kZXgoKG4pPT5uLm5hbWU9PT10KSxlKX1zZXRDaGlsZEF0KHQsZSl7bGV0IHI9dGhpcy5zY2hlbWEsbj1bLi4udGhpcy5iYXRjaGVzXTtpZih0Pi0xJiZ0PHRoaXMubnVtQ29scyl7aWYoIWUpZT1uZXcgRihbeCh7dHlwZTpuZXcgbnIsbGVuZ3RoOnRoaXMubnVtUm93c30pXSk7bGV0IGk9ci5maWVsZHMuc2xpY2UoKSxzPWlbdF0uY2xvbmUoe3R5cGU6ZS50eXBlfSksbz10aGlzLnNjaGVtYS5maWVsZHMubWFwKChhLGwpPT50aGlzLmdldENoaWxkQXQobCkpO1tpW3RdLG9bdF1dPVtzLGVdLFtyLG5dPXdwKHIsbyl9cmV0dXJuIG5ldyBGZShyLG4pfXNlbGVjdCh0KXtsZXQgZT10aGlzLnNjaGVtYS5maWVsZHMucmVkdWNlKChyLG4saSk9PnIuc2V0KG4ubmFtZSxpKSxuZXcgTWFwKTtyZXR1cm4gdGhpcy5zZWxlY3RBdCh0Lm1hcCgocik9PmUuZ2V0KHIpKS5maWx0ZXIoKHIpPT5yPi0xKSl9c2VsZWN0QXQodCl7bGV0IGU9dGhpcy5zY2hlbWEuc2VsZWN0QXQodCkscj10aGlzLmJhdGNoZXMubWFwKChuKT0+bi5zZWxlY3RBdCh0KSk7cmV0dXJuIG5ldyBGZShlLHIpfWFzc2lnbih0KXtsZXQgZT10aGlzLnNjaGVtYS5maWVsZHMsW3Isbl09dC5zY2hlbWEuZmllbGRzLnJlZHVjZSgobyxhLGwpPT57bGV0W3UsZl09byxwPWUuZmluZEluZGV4KChnKT0+Zy5uYW1lPT09YS5uYW1lKTtyZXR1cm5+cD9mW3BdPWw6dS5wdXNoKGwpLG99LFtbXSxbXV0pLGk9dGhpcy5zY2hlbWEuYXNzaWduKHQuc2NoZW1hKSxzPVsuLi5lLm1hcCgobyxhKT0+W2EsblthXV0pLm1hcCgoW28sYV0pPT5hPT09dm9pZCAwP3RoaXMuZ2V0Q2hpbGRBdChvKTp0LmdldENoaWxkQXQoYSkpLC4uLnIubWFwKChvKT0+dC5nZXRDaGlsZEF0KG8pKV0uZmlsdGVyKEJvb2xlYW4pO3JldHVybiBuZXcgRmUoLi4ud3AoaSxzKSl9fTtGQT1TeW1ib2wudG9TdHJpbmdUYWc7RmVbRkFdPSgodCk9Pih0LnNjaGVtYT1udWxsLHQuYmF0Y2hlcz1bXSx0Ll9vZmZzZXRzPW5ldyBVaW50MzJBcnJheShbMF0pLHQuX251bGxDb3VudD0tMSx0W1N5bWJvbC5pc0NvbmNhdFNwcmVhZGFibGVdPSEwLHRbTUFdPSEwLHQuaXNWYWxpZD1ybChPdSksdC5nZXQ9cmwoUGUuZ2V0VmlzaXRGbih5LlN0cnVjdCkpLHQuc2V0PVVoKF9yLmdldFZpc2l0Rm4oeS5TdHJ1Y3QpKSx0LmluZGV4T2Y9UmgoamEuZ2V0VmlzaXRGbih5LlN0cnVjdCkpLCJUYWJsZSIpKShGZS5wcm90b3R5cGUpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShGZSxTeW1ib2wuaGFzSW5zdGFuY2Use3ZhbHVlOmZ1bmN0aW9uKGUpe3JldHVybiBGdW5jdGlvbi5wcm90b3R5cGVbU3ltYm9sLmhhc0luc3RhbmNlXS5jYWxsKHRoaXMsZSl8fHRoaXM9PT1GZSYmRmUuaXNUYWJsZShlKX19KX0pO2Z1bmN0aW9uIExBKHQsZSxyPWUucmVkdWNlKChuLGkpPT5NYXRoLm1heChuLGkubGVuZ3RoKSwwKSl7dmFyIG47bGV0IGk9Wy4uLnQuZmllbGRzXSxzPVsuLi5lXSxvPShyKzYzJi02NCk+PjM7Zm9yKGxldFthLGxdb2YgdC5maWVsZHMuZW50cmllcygpKXtsZXQgdT1lW2FdO2lmKCF1fHx1Lmxlbmd0aCE9PXIpaVthXT1sLmNsb25lKHtudWxsYWJsZTohMH0pLHNbYV09KG49dT09PW51bGx8fHU9PT12b2lkIDA/dm9pZCAwOnUuX2NoYW5nZUxlbmd0aEFuZEJhY2tmaWxsTnVsbEJpdG1hcChyKSkhPT1udWxsJiZuIT09dm9pZCAwP246eCh7dHlwZTpsLnR5cGUsbGVuZ3RoOnIsbnVsbENvdW50OnIsbnVsbEJpdG1hcDpuZXcgVWludDhBcnJheShvKX0pfXJldHVyblt0LmFzc2lnbihpKSx4KHt0eXBlOm5ldyBPdChpKSxsZW5ndGg6cixjaGlsZHJlbjpzfSldfWZ1bmN0aW9uIENBKHQsZSxyPW5ldyBNYXApe3ZhciBuLGk7aWYoKChuPXQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0Lmxlbmd0aCkhPT1udWxsJiZuIT09dm9pZCAwP246MCk+MCYmKHQ9PT1udWxsfHx0PT09dm9pZCAwP3ZvaWQgMDp0Lmxlbmd0aCk9PT0oZT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUubGVuZ3RoKSlmb3IobGV0IHM9LTEsbz10Lmxlbmd0aDsrK3M8bzspe2xldHt0eXBlOmF9PXRbc10sbD1lW3NdO2ZvcihsZXQgdSBvZltsLC4uLigoaT1sPT09bnVsbHx8bD09PXZvaWQgMD92b2lkIDA6bC5kaWN0aW9uYXJ5KT09PW51bGx8fGk9PT12b2lkIDA/dm9pZCAwOmkuZGF0YSl8fFtdXSlDQShhLmNoaWxkcmVuLHU9PT1udWxsfHx1PT09dm9pZCAwP3ZvaWQgMDp1LmNoaWxkcmVuLHIpO2lmKEEuaXNEaWN0aW9uYXJ5KGEpKXtsZXR7aWQ6dX09YTtpZighci5oYXModSkpe2lmKGw9PT1udWxsfHxsPT09dm9pZCAwP3ZvaWQgMDpsLmRpY3Rpb25hcnkpci5zZXQodSxsLmRpY3Rpb25hcnkpfWVsc2UgaWYoci5nZXQodSkhPT1sLmRpY3Rpb25hcnkpdGhyb3cgRXJyb3IoIkNhbm5vdCBjcmVhdGUgU2NoZW1hIGNvbnRhaW5pbmcgdHdvIGRpZmZlcmVudCBkaWN0aW9uYXJpZXMgd2l0aCB0aGUgc2FtZSBJZCIpfX1yZXR1cm4gcn12YXIgVUEsUkEsSXQsZmw7dmFyIHJhPW0oKCk9PntwaSgpO3ZwKCk7bG4oKTskcigpO2FlKCk7UWMoKTtQYSgpO1JuKCk7UGgoKTtraCgpO1JBPVN5bWJvbC5mb3IoImFwYWNoZS1hcnJvdy9SZWNvcmRCYXRjaCIpO0l0PWNsYXNzIEl0e3N0YXRpYyBpc1JlY29yZEJhdGNoKHQpe3JldHVybih0PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dFtSQV0pPT09ITB9Y29uc3RydWN0b3IoLi4udCl7c3dpdGNoKHQubGVuZ3RoKXtjYXNlIDM6Y2FzZSAyOntpZihbdGhpcy5zY2hlbWFdPXQsISh0aGlzLnNjaGVtYSBpbnN0YW5jZW9mIGopKXRocm93IFR5cGVFcnJvcigiUmVjb3JkQmF0Y2ggY29uc3RydWN0b3IgZXhwZWN0cyBhIFtTY2hlbWEsIERhdGFdIHBhaXIuIik7aWYoWyx0aGlzLmRhdGE9eCh7bnVsbENvdW50OjAsdHlwZTpuZXcgT3QodGhpcy5zY2hlbWEuZmllbGRzKSxjaGlsZHJlbjp0aGlzLnNjaGVtYS5maWVsZHMubWFwKChlKT0+eCh7dHlwZTplLnR5cGUsbnVsbENvdW50OjB9KSl9KSx0aGlzLl9tZXRhZGF0YT1uZXcgTWFwXT10LCEodGhpcy5kYXRhIGluc3RhbmNlb2YgaHQpKXRocm93IFR5cGVFcnJvcigiUmVjb3JkQmF0Y2ggY29uc3RydWN0b3IgZXhwZWN0cyBhIFtTY2hlbWEsIERhdGFdIHBhaXIuIik7W3RoaXMuc2NoZW1hLHRoaXMuZGF0YV09TEEodGhpcy5zY2hlbWEsdGhpcy5kYXRhLmNoaWxkcmVuLHRoaXMuZGF0YS5sZW5ndGgpO2JyZWFrfWNhc2UgMTp7bGV0W2VdPXQse2ZpZWxkczpyLGNoaWxkcmVuOm4sbGVuZ3RoOml9PU9iamVjdC5rZXlzKGUpLnJlZHVjZSgoYSxsLHUpPT4oYS5jaGlsZHJlblt1XT1lW2xdLGEubGVuZ3RoPU1hdGgubWF4KGEubGVuZ3RoLGVbbF0ubGVuZ3RoKSxhLmZpZWxkc1t1XT1WLm5ldyh7bmFtZTpsLHR5cGU6ZVtsXS50eXBlLG51bGxhYmxlOiEwfSksYSkse2xlbmd0aDowLGZpZWxkczpbXSxjaGlsZHJlbjpbXX0pLHM9bmV3IGoociksbz14KHt0eXBlOm5ldyBPdChyKSxsZW5ndGg6aSxjaGlsZHJlbjpuLG51bGxDb3VudDowfSk7W3RoaXMuc2NoZW1hLHRoaXMuZGF0YV09TEEocyxvLmNoaWxkcmVuLGkpLHRoaXMuX21ldGFkYXRhPW5ldyBNYXA7YnJlYWt9ZGVmYXVsdDp0aHJvdyBUeXBlRXJyb3IoIlJlY29yZEJhdGNoIGNvbnN0cnVjdG9yIGV4cGVjdHMgYW4gT2JqZWN0IG1hcHBpbmcgbmFtZXMgdG8gY2hpbGQgRGF0YSwgb3IgYSBbU2NoZW1hLCBEYXRhXSBwYWlyLiIpfX1nZXQgbWV0YWRhdGEoKXtyZXR1cm4gdGhpcy5fbWV0YWRhdGF9Z2V0IGRpY3Rpb25hcmllcygpe3JldHVybiB0aGlzLl9kaWN0aW9uYXJpZXN8fCh0aGlzLl9kaWN0aW9uYXJpZXM9Q0EodGhpcy5zY2hlbWEuZmllbGRzLHRoaXMuZGF0YS5jaGlsZHJlbikpfWdldCBudW1Db2xzKCl7cmV0dXJuIHRoaXMuc2NoZW1hLmZpZWxkcy5sZW5ndGh9Z2V0IG51bVJvd3MoKXtyZXR1cm4gdGhpcy5kYXRhLmxlbmd0aH1nZXQgbnVsbENvdW50KCl7cmV0dXJuIHRoaXMuZGF0YS5udWxsQ291bnR9aXNWYWxpZCh0KXtyZXR1cm4gdGhpcy5kYXRhLmdldFZhbGlkKHQpfWdldCh0KXtyZXR1cm4gUGUudmlzaXQodGhpcy5kYXRhLHQpfWF0KHQpe3JldHVybiB0aGlzLmdldChrYSh0LHRoaXMubnVtUm93cykpfXNldCh0LGUpe3JldHVybiBfci52aXNpdCh0aGlzLmRhdGEsdCxlKX1pbmRleE9mKHQsZSl7cmV0dXJuIGphLnZpc2l0KHRoaXMuZGF0YSx0LGUpfVtTeW1ib2wuaXRlcmF0b3JdKCl7cmV0dXJuIG5sLnZpc2l0KG5ldyBGKFt0aGlzLmRhdGFdKSl9dG9BcnJheSgpe3JldHVyblsuLi50aGlzXX1jb25jYXQoLi4udCl7cmV0dXJuIG5ldyBGZSh0aGlzLnNjaGVtYSxbdGhpcywuLi50XSl9c2xpY2UodCxlKXtsZXRbcl09bmV3IEYoW3RoaXMuZGF0YV0pLnNsaWNlKHQsZSkuZGF0YTtyZXR1cm4gbmV3IEl0KHRoaXMuc2NoZW1hLHIsdGhpcy5fbWV0YWRhdGEpfWdldENoaWxkKHQpe3ZhciBlO3JldHVybiB0aGlzLmdldENoaWxkQXQoKGU9dGhpcy5zY2hlbWEuZmllbGRzKT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUuZmluZEluZGV4KChyKT0+ci5uYW1lPT09dCkpfWdldENoaWxkQXQodCl7aWYodD4tMSYmdDx0aGlzLnNjaGVtYS5maWVsZHMubGVuZ3RoKXJldHVybiBuZXcgRihbdGhpcy5kYXRhLmNoaWxkcmVuW3RdXSk7cmV0dXJuIG51bGx9c2V0Q2hpbGQodCxlKXt2YXIgcjtyZXR1cm4gdGhpcy5zZXRDaGlsZEF0KChyPXRoaXMuc2NoZW1hLmZpZWxkcyk9PT1udWxsfHxyPT09dm9pZCAwP3ZvaWQgMDpyLmZpbmRJbmRleCgobik9Pm4ubmFtZT09PXQpLGUpfXNldENoaWxkQXQodCxlKXtsZXQgcj10aGlzLnNjaGVtYSxuPXRoaXMuZGF0YTtpZih0Pi0xJiZ0PHRoaXMubnVtQ29scyl7aWYoIWUpZT1uZXcgRihbeCh7dHlwZTpuZXcgbnIsbGVuZ3RoOnRoaXMubnVtUm93c30pXSk7bGV0IGk9ci5maWVsZHMuc2xpY2UoKSxzPW4uY2hpbGRyZW4uc2xpY2UoKSxvPWlbdF0uY2xvbmUoe3R5cGU6ZS50eXBlfSk7W2lbdF0sc1t0XV09W28sZS5kYXRhWzBdXSxyPW5ldyBqKGksbmV3IE1hcCh0aGlzLnNjaGVtYS5tZXRhZGF0YSkpLG49eCh7dHlwZTpuZXcgT3QoaSksbGVuZ3RoOm4ubGVuZ3RoLGNoaWxkcmVuOnN9KX1yZXR1cm4gbmV3IEl0KHIsbix0aGlzLl9tZXRhZGF0YSl9c2VsZWN0KHQpe2xldCBlPXRoaXMuc2NoZW1hLnNlbGVjdCh0KSxyPW5ldyBPdChlLmZpZWxkcyksbj1bXTtmb3IobGV0IGkgb2YgdCl7bGV0IHM9dGhpcy5zY2hlbWEuZmllbGRzLmZpbmRJbmRleCgobyk9Pm8ubmFtZT09PWkpO2lmKH5zKW5bc109dGhpcy5kYXRhLmNoaWxkcmVuW3NdfXJldHVybiBuZXcgSXQoZSx4KHt0eXBlOnIsbGVuZ3RoOnRoaXMubnVtUm93cyxjaGlsZHJlbjpufSksdGhpcy5fbWV0YWRhdGEpfXNlbGVjdEF0KHQpe2xldCBlPXRoaXMuc2NoZW1hLnNlbGVjdEF0KHQpLHI9dC5tYXAoKGkpPT50aGlzLmRhdGEuY2hpbGRyZW5baV0pLmZpbHRlcihCb29sZWFuKSxuPXgoe3R5cGU6bmV3IE90KGUuZmllbGRzKSxsZW5ndGg6dGhpcy5udW1Sb3dzLGNoaWxkcmVuOnJ9KTtyZXR1cm4gbmV3IEl0KGUsbix0aGlzLl9tZXRhZGF0YSl9fTtVQT1TeW1ib2wudG9TdHJpbmdUYWc7SXRbVUFdPSgodCk9Pih0Ll9udWxsQ291bnQ9LTEsdFtTeW1ib2wuaXNDb25jYXRTcHJlYWRhYmxlXT0hMCx0W1JBXT0hMCwiUmVjb3JkQmF0Y2giKSkoSXQucHJvdG90eXBlKTtPYmplY3QuZGVmaW5lUHJvcGVydHkoSXQsU3ltYm9sLmhhc0luc3RhbmNlLHt2YWx1ZTpmdW5jdGlvbihlKXtyZXR1cm4gRnVuY3Rpb24ucHJvdG90eXBlW1N5bWJvbC5oYXNJbnN0YW5jZV0uY2FsbCh0aGlzLGUpfHx0aGlzPT09SXQmJkl0LmlzUmVjb3JkQmF0Y2goZSl9fSk7Zmw9Y2xhc3MgZmwgZXh0ZW5kcyBJdHtjb25zdHJ1Y3Rvcih0LGUpe2xldCByPXQuZmllbGRzLm1hcCgoaSk9Pngoe3R5cGU6aS50eXBlfSkpLG49eCh7dHlwZTpuZXcgT3QodC5maWVsZHMpLGxlbmd0aDowLG51bGxDb3VudDowLGNoaWxkcmVuOnJ9KTtzdXBlcih0LG4sZXx8bmV3IE1hcCl9fX0pO2Z1bmN0aW9uIEFwKHQsZT0wKXtmb3IobGV0IHI9LTEsbj1kbC5sZW5ndGg7KytyPG47KWlmKGRsW3JdIT09dFtlK3JdKXJldHVybiExO3JldHVybiEwfXZhciBxZz0odCk9PmBFeHBlY3RlZCAke1R0W3RdfSBNZXNzYWdlIGluIHN0cmVhbSwgYnV0IHdhcyBudWxsIG9yIGxlbmd0aCAwLmAsV2c9KHQpPT5gSGVhZGVyIHBvaW50ZXIgb2YgZmxhdGJ1ZmZlci1lbmNvZGVkICR7VHRbdF19IE1lc3NhZ2UgaXMgbnVsbCBvciBsZW5ndGggMC5gLFBBPSh0LGUpPT5gRXhwZWN0ZWQgdG8gcmVhZCAke3R9IG1ldGFkYXRhIGJ5dGVzLCBidXQgb25seSByZWFkICR7ZX0uYCxrQT0odCxlKT0+YEV4cGVjdGVkIHRvIHJlYWQgJHt0fSBieXRlcyBmb3IgbWVzc2FnZSBib2R5LCBidXQgb25seSByZWFkICR7ZX0uYCwkdSxJcCxCcCxTcD00LCRnPSJBUlJPVzEiLGRsLGhsLEhnLFZBO3ZhciBZZz1tKCgpPT57T24oKTtDZSgpO0Z0KCk7cWEoKTthZygpO1llKCk7V2EoKTtNdSgpOyR1PWNsYXNzICR1e2NvbnN0cnVjdG9yKHQpe3RoaXMuc291cmNlPXQgaW5zdGFuY2VvZiBxcz90Om5ldyBxcyh0KX1bU3ltYm9sLml0ZXJhdG9yXSgpe3JldHVybiB0aGlzfW5leHQoKXtsZXQgdDtpZigodD10aGlzLnJlYWRNZXRhZGF0YUxlbmd0aCgpKS5kb25lKXJldHVybiBoZTtpZih0LnZhbHVlPT09LTEmJih0PXRoaXMucmVhZE1ldGFkYXRhTGVuZ3RoKCkpLmRvbmUpcmV0dXJuIGhlO2lmKCh0PXRoaXMucmVhZE1ldGFkYXRhKHQudmFsdWUpKS5kb25lKXJldHVybiBoZTtyZXR1cm4gdH10aHJvdyh0KXtyZXR1cm4gdGhpcy5zb3VyY2UudGhyb3codCl9cmV0dXJuKHQpe3JldHVybiB0aGlzLnNvdXJjZS5yZXR1cm4odCl9cmVhZE1lc3NhZ2UodCl7bGV0IGU7aWYoKGU9dGhpcy5uZXh0KCkpLmRvbmUpcmV0dXJuIG51bGw7aWYodCE9bnVsbCYmZS52YWx1ZS5oZWFkZXJUeXBlIT09dCl0aHJvdyBFcnJvcihxZyh0KSk7cmV0dXJuIGUudmFsdWV9cmVhZE1lc3NhZ2VCb2R5KHQpe2lmKHQ8PTApcmV0dXJuIG5ldyBVaW50OEFycmF5KDApO2xldCBlPWsodGhpcy5zb3VyY2UucmVhZCh0KSk7aWYoZS5ieXRlTGVuZ3RoPHQpdGhyb3cgRXJyb3Ioa0EodCxlLmJ5dGVMZW5ndGgpKTtyZXR1cm4gZS5ieXRlT2Zmc2V0JTg9PT0wJiZlLmJ5dGVPZmZzZXQrZS5ieXRlTGVuZ3RoPD1lLmJ1ZmZlci5ieXRlTGVuZ3RoP2U6ZS5zbGljZSgpfXJlYWRTY2hlbWEodD0hMSl7bGV0IGU9VHQuU2NoZW1hLHI9dGhpcy5yZWFkTWVzc2FnZShlKSxuPXI9PT1udWxsfHxyPT09dm9pZCAwP3ZvaWQgMDpyLmhlYWRlcigpO2lmKHQmJiFuKXRocm93IEVycm9yKFdnKGUpKTtyZXR1cm4gbn1yZWFkTWV0YWRhdGFMZW5ndGgoKXtsZXQgdD10aGlzLnNvdXJjZS5yZWFkKFNwKSxlPXQmJm5ldyBtcih0KSxyPShlPT09bnVsbHx8ZT09PXZvaWQgMD92b2lkIDA6ZS5yZWFkSW50MzIoMCkpfHwwO3JldHVybntkb25lOnI9PT0wLHZhbHVlOnJ9fXJlYWRNZXRhZGF0YSh0KXtsZXQgZT10aGlzLnNvdXJjZS5yZWFkKHQpO2lmKCFlKXJldHVybiBoZTtpZihlLmJ5dGVMZW5ndGg8dCl0aHJvdyBFcnJvcihQQSh0LGUuYnl0ZUxlbmd0aCkpO3JldHVybntkb25lOiExLHZhbHVlOmlyLmRlY29kZShlKX19fTtJcD1jbGFzcyBJcHtjb25zdHJ1Y3Rvcih0LGUpe3RoaXMuc291cmNlPXQgaW5zdGFuY2VvZiBtaT90OlhkKHQpP25ldyBIYSh0LGUpOm5ldyBtaSh0KX1bU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCl7cmV0dXJuIHRoaXN9bmV4dCgpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXQgdDtpZigodD15aWVsZCB0aGlzLnJlYWRNZXRhZGF0YUxlbmd0aCgpKS5kb25lKXJldHVybiBoZTtpZih0LnZhbHVlPT09LTEmJih0PXlpZWxkIHRoaXMucmVhZE1ldGFkYXRhTGVuZ3RoKCkpLmRvbmUpcmV0dXJuIGhlO2lmKCh0PXlpZWxkIHRoaXMucmVhZE1ldGFkYXRhKHQudmFsdWUpKS5kb25lKXJldHVybiBoZTtyZXR1cm4gdH0pfXRocm93KHQpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtyZXR1cm4geWllbGQgdGhpcy5zb3VyY2UudGhyb3codCl9KX1yZXR1cm4odCl7cmV0dXJuIE8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3JldHVybiB5aWVsZCB0aGlzLnNvdXJjZS5yZXR1cm4odCl9KX1yZWFkTWVzc2FnZSh0KXtyZXR1cm4gTyh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7bGV0IGU7aWYoKGU9eWllbGQgdGhpcy5uZXh0KCkpLmRvbmUpcmV0dXJuIG51bGw7aWYodCE9bnVsbCYmZS52YWx1ZS5oZWFkZXJUeXBlIT09dCl0aHJvdyBFcnJvcihxZyh0KSk7cmV0dXJuIGUudmFsdWV9KX1yZWFkTWVzc2FnZUJvZHkodCl7cmV0dXJuIE8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe2lmKHQ8PTApcmV0dXJuIG5ldyBVaW50OEFycmF5KDApO2xldCBlPWsoeWllbGQgdGhpcy5zb3VyY2UucmVhZCh0KSk7aWYoZS5ieXRlTGVuZ3RoPHQpdGhyb3cgRXJyb3Ioa0EodCxlLmJ5dGVMZW5ndGgpKTtyZXR1cm4gZS5ieXRlT2Zmc2V0JTg9PT0wJiZlLmJ5dGVPZmZzZXQrZS5ieXRlTGVuZ3RoPD1lLmJ1ZmZlci5ieXRlTGVuZ3RoP2U6ZS5zbGljZSgpfSl9cmVhZFNjaGVtYSgpe3JldHVybiBPKHRoaXMsYXJndW1lbnRzLHZvaWQgMCxmdW5jdGlvbioodD0hMSl7bGV0IGU9VHQuU2NoZW1hLHI9eWllbGQgdGhpcy5yZWFkTWVzc2FnZShlKSxuPXI9PT1udWxsfHxyPT09dm9pZCAwP3ZvaWQgMDpyLmhlYWRlcigpO2lmKHQmJiFuKXRocm93IEVycm9yKFdnKGUpKTtyZXR1cm4gbn0pfXJlYWRNZXRhZGF0YUxlbmd0aCgpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXQgdD15aWVsZCB0aGlzLnNvdXJjZS5yZWFkKFNwKSxlPXQmJm5ldyBtcih0KSxyPShlPT09bnVsbHx8ZT09PXZvaWQgMD92b2lkIDA6ZS5yZWFkSW50MzIoMCkpfHwwO3JldHVybntkb25lOnI9PT0wLHZhbHVlOnJ9fSl9cmVhZE1ldGFkYXRhKHQpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXQgZT15aWVsZCB0aGlzLnNvdXJjZS5yZWFkKHQpO2lmKCFlKXJldHVybiBoZTtpZihlLmJ5dGVMZW5ndGg8dCl0aHJvdyBFcnJvcihQQSh0LGUuYnl0ZUxlbmd0aCkpO3JldHVybntkb25lOiExLHZhbHVlOmlyLmRlY29kZShlKX19KX19O0JwPWNsYXNzIEJwIGV4dGVuZHMgJHV7Y29uc3RydWN0b3IodCl7c3VwZXIobmV3IFVpbnQ4QXJyYXkoMCkpO3RoaXMuX3NjaGVtYT0hMSx0aGlzLl9ib2R5PVtdLHRoaXMuX2JhdGNoSW5kZXg9MCx0aGlzLl9kaWN0aW9uYXJ5SW5kZXg9MCx0aGlzLl9qc29uPXQgaW5zdGFuY2VvZiBXaD90Om5ldyBXaCh0KX1uZXh0KCl7bGV0e19qc29uOnR9PXRoaXM7aWYoIXRoaXMuX3NjaGVtYSlyZXR1cm4gdGhpcy5fc2NoZW1hPSEwLHtkb25lOiExLHZhbHVlOmlyLmZyb21KU09OKHQuc2NoZW1hLFR0LlNjaGVtYSl9O2lmKHRoaXMuX2RpY3Rpb25hcnlJbmRleDx0LmRpY3Rpb25hcmllcy5sZW5ndGgpe2xldCBlPXQuZGljdGlvbmFyaWVzW3RoaXMuX2RpY3Rpb25hcnlJbmRleCsrXTtyZXR1cm4gdGhpcy5fYm9keT1lLmRhdGEuY29sdW1ucyx7ZG9uZTohMSx2YWx1ZTppci5mcm9tSlNPTihlLFR0LkRpY3Rpb25hcnlCYXRjaCl9fWlmKHRoaXMuX2JhdGNoSW5kZXg8dC5iYXRjaGVzLmxlbmd0aCl7bGV0IGU9dC5iYXRjaGVzW3RoaXMuX2JhdGNoSW5kZXgrK107cmV0dXJuIHRoaXMuX2JvZHk9ZS5jb2x1bW5zLHtkb25lOiExLHZhbHVlOmlyLmZyb21KU09OKGUsVHQuUmVjb3JkQmF0Y2gpfX1yZXR1cm4gdGhpcy5fYm9keT1bXSxoZX1yZWFkTWVzc2FnZUJvZHkodCl7cmV0dXJuIGUodGhpcy5fYm9keSk7ZnVuY3Rpb24gZShyKXtyZXR1cm4ocnx8W10pLnJlZHVjZSgobixpKT0+Wy4uLm4sLi4uaS5WQUxJRElUWSYmW2kuVkFMSURJVFldfHxbXSwuLi5pLlRZUEVfSUQmJltpLlRZUEVfSURdfHxbXSwuLi5pLk9GRlNFVCYmW2kuT0ZGU0VUXXx8W10sLi4uaS5EQVRBJiZbaS5EQVRBXXx8W10sLi4uaS5WSUVXUyYmW2kuVklFV1NdfHxbXSwuLi5pLlZBUklBRElDX0RBVEFfQlVGRkVSU3x8W10sLi4uZShpLmNoaWxkcmVuKV0sW10pfX1yZWFkTWVzc2FnZSh0KXtsZXQgZTtpZigoZT10aGlzLm5leHQoKSkuZG9uZSlyZXR1cm4gbnVsbDtpZih0IT1udWxsJiZlLnZhbHVlLmhlYWRlclR5cGUhPT10KXRocm93IEVycm9yKHFnKHQpKTtyZXR1cm4gZS52YWx1ZX1yZWFkU2NoZW1hKCl7bGV0IHQ9VHQuU2NoZW1hLGU9dGhpcy5yZWFkTWVzc2FnZSh0KSxyPWU9PT1udWxsfHxlPT09dm9pZCAwP3ZvaWQgMDplLmhlYWRlcigpO2lmKCFlfHwhcil0aHJvdyBFcnJvcihXZyh0KSk7cmV0dXJuIHJ9fTtkbD1uZXcgVWludDhBcnJheSgkZy5sZW5ndGgpO2ZvcihsZXQgdD0wO3Q8JGcubGVuZ3RoO3QrPTEpZGxbdF09JGcuY29kZVBvaW50QXQodCk7aGw9ZGwubGVuZ3RoLEhnPWhsK1NwLFZBPWhsKjIrU3B9KTtjbGFzcyB6QXtjb25zdHJ1Y3Rvcigpe3RoaXMuTFo0X0ZSQU1FX01BR0lDPW5ldyBVaW50OEFycmF5KFs0LDM0LDc3LDI0XSksdGhpcy5NSU5fSEVBREVSX0xFTkdUSD03fWlzVmFsaWRDb2RlY0VuY29kZSh0KXtsZXQgZT1uZXcgVWludDhBcnJheShbMSwyLDMsNCw1LDYsNyw4XSkscj10LmVuY29kZShlKTtyZXR1cm4gdGhpcy5faXNWYWxpZENvbXByZXNzZWQocil9X2lzVmFsaWRDb21wcmVzc2VkKHQpe3JldHVybiB0aGlzLl9oYXNNaW5pbXVtTGVuZ3RoKHQpJiZ0aGlzLl9oYXNWYWxpZE1hZ2ljTnVtYmVyKHQpJiZ0aGlzLl9oYXNWYWxpZFZlcnNpb24odCl9X2hhc01pbmltdW1MZW5ndGgodCl7cmV0dXJuIHQubGVuZ3RoPj10aGlzLk1JTl9IRUFERVJfTEVOR1RIfV9oYXNWYWxpZE1hZ2ljTnVtYmVyKHQpe3JldHVybiB0aGlzLkxaNF9GUkFNRV9NQUdJQy5ldmVyeSgoZSxyKT0+dFtyXT09PWUpfV9oYXNWYWxpZFZlcnNpb24odCl7cmV0dXJuKHRbNF0mMTkyKT4+Nj09PTF9fWNsYXNzIGpBe2NvbnN0cnVjdG9yKCl7dGhpcy5aU1REX01BR0lDPW5ldyBVaW50OEFycmF5KFs0MCwxODEsNDcsMjUzXSksdGhpcy5NSU5fSEVBREVSX0xFTkdUSD02fWlzVmFsaWRDb2RlY0VuY29kZSh0KXtsZXQgZT1uZXcgVWludDhBcnJheShbMSwyLDMsNCw1LDYsNyw4XSkscj10LmVuY29kZShlKTtyZXR1cm4gdGhpcy5faXNWYWxpZENvbXByZXNzZWQocil9X2lzVmFsaWRDb21wcmVzc2VkKHQpe3JldHVybiB0aGlzLl9oYXNNaW5pbXVtTGVuZ3RoKHQpJiZ0aGlzLl9oYXNWYWxpZE1hZ2ljTnVtYmVyKHQpfV9oYXNNaW5pbXVtTGVuZ3RoKHQpe3JldHVybiB0Lmxlbmd0aD49dGhpcy5NSU5fSEVBREVSX0xFTkdUSH1faGFzVmFsaWRNYWdpY051bWJlcih0KXtyZXR1cm4gdGhpcy5aU1REX01BR0lDLmV2ZXJ5KChlLHIpPT50W3JdPT09ZSl9fXZhciAkQTt2YXIgcUE9bSgoKT0+e2d1KCk7JEE9e1t6ci5MWjRfRlJBTUVdOm5ldyB6QSxbenIuWlNURF06bmV3IGpBfX0pO2NsYXNzIFdBe2NvbnN0cnVjdG9yKCl7dGhpcy5yZWdpc3RyeT17fX1zZXQodCxlKXtpZigoZT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUuZW5jb2RlKSYmdHlwZW9mIGUuZW5jb2RlPT09ImZ1bmN0aW9uIiYmISRBW3RdLmlzVmFsaWRDb2RlY0VuY29kZShlKSl0aHJvdyBFcnJvcihgRW5jb2RlciBmb3IgJHt6clt0XX0gaXMgbm90IHZhbGlkLmApO3RoaXMucmVnaXN0cnlbdF09ZX1nZXQodCl7dmFyIGU7cmV0dXJuKChlPXRoaXMucmVnaXN0cnkpPT09bnVsbHx8ZT09PXZvaWQgMD92b2lkIDA6ZVt0XSl8fG51bGx9fXZhciBwbDt2YXIgS2c9bSgoKT0+e2d1KCk7cUEoKTtwbD1uZXcgV0F9KTt2YXIgRHA9LTEscXU9ODtjbGFzcyBHZ3tnZXQgbnVtRGljdGlvbmFyaWVzKCl7cmV0dXJuIHRoaXMuX2RpY3Rpb25hcnlJbmRleH1nZXQgbnVtUmVjb3JkQmF0Y2hlcygpe3JldHVybiB0aGlzLl9yZWNvcmRCYXRjaEluZGV4fWNvbnN0cnVjdG9yKHQ9bmV3IE1hcCl7dGhpcy5jbG9zZWQ9ITEsdGhpcy5hdXRvRGVzdHJveT0hMCx0aGlzLl9kaWN0aW9uYXJ5SW5kZXg9MCx0aGlzLl9yZWNvcmRCYXRjaEluZGV4PTAsdGhpcy5kaWN0aW9uYXJpZXM9dH1pc1N5bmMoKXtyZXR1cm4hMX1pc0FzeW5jKCl7cmV0dXJuITF9aXNGaWxlKCl7cmV0dXJuITF9aXNTdHJlYW0oKXtyZXR1cm4hMX1yZXNldCh0KXtyZXR1cm4gdGhpcy5fZGljdGlvbmFyeUluZGV4PTAsdGhpcy5fcmVjb3JkQmF0Y2hJbmRleD0wLHRoaXMuc2NoZW1hPXQsdGhpcy5kaWN0aW9uYXJpZXM9bmV3IE1hcCx0aGlzfV9sb2FkUmVjb3JkQmF0Y2godCxlLHIpe2xldCBuO2lmKHQuY29tcHJlc3Npb24hPW51bGwpe2xldCBzPXBsLmdldCh0LmNvbXByZXNzaW9uLnR5cGUpO2lmKChzPT09bnVsbHx8cz09PXZvaWQgMD92b2lkIDA6cy5kZWNvZGUpJiZ0eXBlb2Ygcy5kZWNvZGU9PT0iZnVuY3Rpb24iKXtsZXR7ZGVjb21tcHJlc3NlZEJvZHk6byxidWZmZXJzOmF9PXRoaXMuX2RlY29tcHJlc3NCdWZmZXJzKHQsZSxzKTtuPXRoaXMuX2xvYWRDb21wcmVzc2VkVmVjdG9ycyh0LG8sdGhpcy5zY2hlbWEuZmllbGRzKSx0PW5ldyBKZSh0Lmxlbmd0aCx0Lm5vZGVzLGEsbnVsbCl9ZWxzZSB0aHJvdyBFcnJvcigiUmVjb3JkIGJhdGNoIGlzIGNvbXByZXNzZWQgYnV0IGNvZGVjIG5vdCBmb3VuZCIpfWVsc2Ugbj10aGlzLl9sb2FkVmVjdG9ycyh0LGUsdGhpcy5zY2hlbWEuZmllbGRzKTtsZXQgaT14KHt0eXBlOm5ldyBPdCh0aGlzLnNjaGVtYS5maWVsZHMpLGxlbmd0aDp0Lmxlbmd0aCxjaGlsZHJlbjpufSk7cmV0dXJuIG5ldyBJdCh0aGlzLnNjaGVtYSxpLHIpfV9sb2FkRGljdGlvbmFyeUJhdGNoKHQsZSl7bGV0e2lkOnIsaXNEZWx0YTpufT10LHtkaWN0aW9uYXJpZXM6aSxzY2hlbWE6c309dGhpcyxvPWkuZ2V0KHIpLGE9cy5kaWN0aW9uYXJpZXMuZ2V0KHIpLGw7aWYodC5kYXRhLmNvbXByZXNzaW9uIT1udWxsKXtsZXQgdT1wbC5nZXQodC5kYXRhLmNvbXByZXNzaW9uLnR5cGUpO2lmKCh1PT09bnVsbHx8dT09PXZvaWQgMD92b2lkIDA6dS5kZWNvZGUpJiZ0eXBlb2YgdS5kZWNvZGU9PT0iZnVuY3Rpb24iKXtsZXR7ZGVjb21tcHJlc3NlZEJvZHk6ZixidWZmZXJzOnB9PXRoaXMuX2RlY29tcHJlc3NCdWZmZXJzKHQuZGF0YSxlLHUpO2w9dGhpcy5fbG9hZENvbXByZXNzZWRWZWN0b3JzKHQuZGF0YSxmLFthXSksdD1uZXcgcXIobmV3IEplKHQuZGF0YS5sZW5ndGgsdC5kYXRhLm5vZGVzLHAsbnVsbCx0LmRhdGEudmFyaWFkaWNCdWZmZXJDb3VudHMpLHIsbil9ZWxzZSB0aHJvdyBFcnJvcigiRGljdGlvbmFyeSBiYXRjaCBpcyBjb21wcmVzc2VkIGJ1dCBjb2RlYyBub3QgZm91bmQiKX1lbHNlIGw9dGhpcy5fbG9hZFZlY3RvcnModC5kYXRhLGUsW2FdKTtyZXR1cm4obyYmbj9vLmNvbmNhdChuZXcgRihsKSk6bmV3IEYobCkpLm1lbW9pemUoKX1fbG9hZFZlY3RvcnModCxlLHIpe3JldHVybiBuZXcgTHUoZSx0Lm5vZGVzLHQuYnVmZmVycyx0aGlzLmRpY3Rpb25hcmllcyx0aGlzLnNjaGVtYS5tZXRhZGF0YVZlcnNpb24sdC52YXJpYWRpY0J1ZmZlckNvdW50cykudmlzaXRNYW55KHIpfV9sb2FkQ29tcHJlc3NlZFZlY3RvcnModCxlLHIpe3JldHVybiBuZXcgbWcoZSx0Lm5vZGVzLHQuYnVmZmVycyx0aGlzLmRpY3Rpb25hcmllcyx0aGlzLnNjaGVtYS5tZXRhZGF0YVZlcnNpb24sdC52YXJpYWRpY0J1ZmZlckNvdW50cykudmlzaXRNYW55KHIpfV9kZWNvbXByZXNzQnVmZmVycyh0LGUscil7bGV0IG49W10saT1bXSxzPTA7Zm9yKGxldHtvZmZzZXQ6byxsZW5ndGg6YX1vZiB0LmJ1ZmZlcnMpe2lmKGE9PT0wKXtuLnB1c2gobmV3IFVpbnQ4QXJyYXkoMCkpLGkucHVzaChuZXcgTmUocywwKSk7Y29udGludWV9bGV0IGw9bmV3IG1yKGUuc3ViYXJyYXkobyxvK2EpKSx1PVZ0KGwucmVhZEludDY0KDApKSxmPWwuYnl0ZXMoKS5zdWJhcnJheShxdSkscD11PT09RHA/ZjpyLmRlY29kZShmKTtuLnB1c2gocCk7bGV0IGc9KHMrNyYtOCktcztzKz1nLGkucHVzaChuZXcgTmUocyxwLmxlbmd0aCkpLHMrPXAubGVuZ3RofXJldHVybntkZWNvbW1wcmVzc2VkQm9keTpuLGJ1ZmZlcnM6aX19fWZ1bmN0aW9uIEpBKHQsZSl7cmV0dXJuIGUmJnR5cGVvZiBlLmF1dG9EZXN0cm95PT09ImJvb2xlYW4iP2UuYXV0b0Rlc3Ryb3k6dC5hdXRvRGVzdHJveX1mdW5jdGlvbipIQSh0KXtsZXQgZT1iZS5mcm9tKHQpO3RyeXtpZighZS5vcGVuKHthdXRvRGVzdHJveTohMX0pLmNsb3NlZClkbyB5aWVsZCBlO3doaWxlKCFlLnJlc2V0KCkub3BlbigpLmNsb3NlZCl9ZmluYWxseXtlLmNhbmNlbCgpfX1mdW5jdGlvbiBZQSh0KXtyZXR1cm4gRW4odGhpcyxhcmd1bWVudHMsZnVuY3Rpb24qKCl7bGV0IHI9eWllbGQgZ3QoYmUuZnJvbSh0KSk7dHJ5e2lmKCEoeWllbGQgZ3Qoci5vcGVuKHthdXRvRGVzdHJveTohMX0pKSkuY2xvc2VkKWRvIHlpZWxkIHlpZWxkIGd0KHIpO3doaWxlKCEoeWllbGQgZ3Qoci5yZXNldCgpLm9wZW4oKSkpLmNsb3NlZCl9ZmluYWxseXt5aWVsZCBndChyLmNhbmNlbCgpKX19KX1mdW5jdGlvbiBPTSh0KXtyZXR1cm4gbmV3IEtzKG5ldyBHQSh0KSl9ZnVuY3Rpb24gTk0odCl7bGV0IGU9dC5wZWVrKGhsKzcmLTgpO3JldHVybiBlJiZlLmJ5dGVMZW5ndGg+PTQ/IUFwKGUpP25ldyBLcyhuZXcgV3UodCkpOm5ldyBYYShuZXcgSmcodC5yZWFkKCkpKTpuZXcgS3MobmV3IFd1KGZ1bmN0aW9uKigpe30oKSkpfWZ1bmN0aW9uIEZNKHQpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXQgZT15aWVsZCB0LnBlZWsoaGwrNyYtOCk7cmV0dXJuIGUmJmUuYnl0ZUxlbmd0aD49ND8hQXAoZSk/bmV3IEphKG5ldyBIdSh0KSk6bmV3IFhhKG5ldyBKZyh5aWVsZCB0LnJlYWQoKSkpOm5ldyBKYShuZXcgSHUoZnVuY3Rpb24oKXtyZXR1cm4gRW4odGhpcyxhcmd1bWVudHMsZnVuY3Rpb24qKCl7fSl9KCkpKX0pfWZ1bmN0aW9uIE1NKHQpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXR7c2l6ZTplfT15aWVsZCB0LnN0YXQoKSxyPW5ldyBIYSh0LGUpO2lmKGU+PVZBJiZBcCh5aWVsZCByLnJlYWRBdCgwLGhsKzcmLTgpKSlyZXR1cm4gbmV3IHhwKG5ldyBLQShyKSk7cmV0dXJuIG5ldyBKYShuZXcgSHUocikpfSl9dmFyIGJlLEtzLEphLFhhLHhwLFd1LEh1LEpnLEtBLEdBO3ZhciBUcD1tKCgpPT57T24oKTtwaSgpO2xuKCk7YWUoKTtDZSgpO2lnKCk7cHUoKTtxYSgpO1dhKCk7YWcoKTtvQSgpO3JhKCk7TXUoKTtZZygpO0tnKCk7RnQoKTtiZT1jbGFzcyBiZSBleHRlbmRzIG9se2NvbnN0cnVjdG9yKHQpe3N1cGVyKCk7dGhpcy5faW1wbD10fWdldCBjbG9zZWQoKXtyZXR1cm4gdGhpcy5faW1wbC5jbG9zZWR9Z2V0IHNjaGVtYSgpe3JldHVybiB0aGlzLl9pbXBsLnNjaGVtYX1nZXQgYXV0b0Rlc3Ryb3koKXtyZXR1cm4gdGhpcy5faW1wbC5hdXRvRGVzdHJveX1nZXQgZGljdGlvbmFyaWVzKCl7cmV0dXJuIHRoaXMuX2ltcGwuZGljdGlvbmFyaWVzfWdldCBudW1EaWN0aW9uYXJpZXMoKXtyZXR1cm4gdGhpcy5faW1wbC5udW1EaWN0aW9uYXJpZXN9Z2V0IG51bVJlY29yZEJhdGNoZXMoKXtyZXR1cm4gdGhpcy5faW1wbC5udW1SZWNvcmRCYXRjaGVzfWdldCBmb290ZXIoKXtyZXR1cm4gdGhpcy5faW1wbC5pc0ZpbGUoKT90aGlzLl9pbXBsLmZvb3RlcjpudWxsfWlzU3luYygpe3JldHVybiB0aGlzLl9pbXBsLmlzU3luYygpfWlzQXN5bmMoKXtyZXR1cm4gdGhpcy5faW1wbC5pc0FzeW5jKCl9aXNGaWxlKCl7cmV0dXJuIHRoaXMuX2ltcGwuaXNGaWxlKCl9aXNTdHJlYW0oKXtyZXR1cm4gdGhpcy5faW1wbC5pc1N0cmVhbSgpfW5leHQoKXtyZXR1cm4gdGhpcy5faW1wbC5uZXh0KCl9dGhyb3codCl7cmV0dXJuIHRoaXMuX2ltcGwudGhyb3codCl9cmV0dXJuKHQpe3JldHVybiB0aGlzLl9pbXBsLnJldHVybih0KX1jYW5jZWwoKXtyZXR1cm4gdGhpcy5faW1wbC5jYW5jZWwoKX1yZXNldCh0KXtyZXR1cm4gdGhpcy5faW1wbC5yZXNldCh0KSx0aGlzLl9ET01TdHJlYW09dm9pZCAwLHRoaXMuX25vZGVTdHJlYW09dm9pZCAwLHRoaXN9b3Blbih0KXtsZXQgZT10aGlzLl9pbXBsLm9wZW4odCk7cmV0dXJuIHFpKGUpP2UudGhlbigoKT0+dGhpcyk6dGhpc31yZWFkUmVjb3JkQmF0Y2godCl7cmV0dXJuIHRoaXMuX2ltcGwuaXNGaWxlKCk/dGhpcy5faW1wbC5yZWFkUmVjb3JkQmF0Y2godCk6bnVsbH1bU3ltYm9sLml0ZXJhdG9yXSgpe3JldHVybiB0aGlzLl9pbXBsW1N5bWJvbC5pdGVyYXRvcl0oKX1bU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCl7cmV0dXJuIHRoaXMuX2ltcGxbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCl9dG9ET01TdHJlYW0oKXtyZXR1cm4gcHIudG9ET01TdHJlYW0odGhpcy5pc1N5bmMoKT97W1N5bWJvbC5pdGVyYXRvcl06KCk9PnRoaXN9OntbU3ltYm9sLmFzeW5jSXRlcmF0b3JdOigpPT50aGlzfSl9dG9Ob2RlU3RyZWFtKCl7cmV0dXJuIHByLnRvTm9kZVN0cmVhbSh0aGlzLmlzU3luYygpP3tbU3ltYm9sLml0ZXJhdG9yXTooKT0+dGhpc306e1tTeW1ib2wuYXN5bmNJdGVyYXRvcl06KCk9PnRoaXN9LHtvYmplY3RNb2RlOiEwfSl9c3RhdGljIHRocm91Z2hOb2RlKHQpe3Rocm93IEVycm9yKCcidGhyb3VnaE5vZGUiIG5vdCBhdmFpbGFibGUgaW4gdGhpcyBlbnZpcm9ubWVudCcpfXN0YXRpYyB0aHJvdWdoRE9NKHQsZSl7dGhyb3cgRXJyb3IoJyJ0aHJvdWdoRE9NIiBub3QgYXZhaWxhYmxlIGluIHRoaXMgZW52aXJvbm1lbnQnKX1zdGF0aWMgZnJvbSh0KXtpZih0IGluc3RhbmNlb2YgYmUpcmV0dXJuIHQ7ZWxzZSBpZihHZCh0KSlyZXR1cm4gT00odCk7ZWxzZSBpZihYZCh0KSlyZXR1cm4gTU0odCk7ZWxzZSBpZihxaSh0KSlyZXR1cm4oKCk9Pk8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3JldHVybiB5aWVsZCBiZS5mcm9tKHlpZWxkIHQpfSkpKCk7ZWxzZSBpZihaZCh0KXx8ZHUodCl8fHRoKHQpfHxlaSh0KSlyZXR1cm4gRk0obmV3IG1pKHQpKTtyZXR1cm4gTk0obmV3IHFzKHQpKX1zdGF0aWMgcmVhZEFsbCh0KXtpZih0IGluc3RhbmNlb2YgYmUpcmV0dXJuIHQuaXNTeW5jKCk/SEEodCk6WUEodCk7ZWxzZSBpZihHZCh0KXx8QXJyYXlCdWZmZXIuaXNWaWV3KHQpfHxXaSh0KXx8SmQodCkpcmV0dXJuIEhBKHQpO3JldHVybiBZQSh0KX19O0tzPWNsYXNzIEtzIGV4dGVuZHMgYmV7Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5faW1wbD10fXJlYWRBbGwoKXtyZXR1cm5bLi4udGhpc119W1N5bWJvbC5pdGVyYXRvcl0oKXtyZXR1cm4gdGhpcy5faW1wbFtTeW1ib2wuaXRlcmF0b3JdKCl9W1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpe3JldHVybiBFbih0aGlzLGFyZ3VtZW50cyxmdW5jdGlvbiooKXt5aWVsZCBndCh5aWVsZCpWYygkaSh0aGlzW1N5bWJvbC5pdGVyYXRvcl0oKSkpKX0pfX07SmE9Y2xhc3MgSmEgZXh0ZW5kcyBiZXtjb25zdHJ1Y3Rvcih0KXtzdXBlcih0KTt0aGlzLl9pbXBsPXR9cmVhZEFsbCgpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXt2YXIgdCxlLHIsbjtsZXQgaT1bXTt0cnl7Zm9yKHZhciBzPSEwLG89JGkodGhpcyksYTthPXlpZWxkIG8ubmV4dCgpLHQ9YS5kb25lLCF0O3M9ITApe249YS52YWx1ZSxzPSExO2xldCBsPW47aS5wdXNoKGwpfX1jYXRjaChsKXtlPXtlcnJvcjpsfX1maW5hbGx5e3RyeXtpZighcyYmIXQmJihyPW8ucmV0dXJuKSl5aWVsZCByLmNhbGwobyl9ZmluYWxseXtpZihlKXRocm93IGUuZXJyb3J9fXJldHVybiBpfSl9W1N5bWJvbC5pdGVyYXRvcl0oKXt0aHJvdyBFcnJvcigiQXN5bmNSZWNvcmRCYXRjaFN0cmVhbVJlYWRlciBpcyBub3QgSXRlcmFibGUiKX1bU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCl7cmV0dXJuIHRoaXMuX2ltcGxbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCl9fTtYYT1jbGFzcyBYYSBleHRlbmRzIEtze2NvbnN0cnVjdG9yKHQpe3N1cGVyKHQpO3RoaXMuX2ltcGw9dH19O3hwPWNsYXNzIHhwIGV4dGVuZHMgSmF7Y29uc3RydWN0b3IodCl7c3VwZXIodCk7dGhpcy5faW1wbD10fX07V3U9Y2xhc3MgV3UgZXh0ZW5kcyBHZ3tjb25zdHJ1Y3Rvcih0LGUpe3N1cGVyKGUpO3RoaXMuX3JlYWRlcj0hR2QodCk/bmV3ICR1KHRoaXMuX2hhbmRsZT10KTpuZXcgQnAodGhpcy5faGFuZGxlPXQpfWlzU3luYygpe3JldHVybiEwfWlzU3RyZWFtKCl7cmV0dXJuITB9W1N5bWJvbC5pdGVyYXRvcl0oKXtyZXR1cm4gdGhpc31jYW5jZWwoKXtpZighdGhpcy5jbG9zZWQmJih0aGlzLmNsb3NlZD0hMCkpdGhpcy5yZXNldCgpLl9yZWFkZXIucmV0dXJuKCksdGhpcy5fcmVhZGVyPW51bGwsdGhpcy5kaWN0aW9uYXJpZXM9bnVsbH1vcGVuKHQpe2lmKCF0aGlzLmNsb3NlZCl7aWYodGhpcy5hdXRvRGVzdHJveT1KQSh0aGlzLHQpLCEodGhpcy5zY2hlbWF8fCh0aGlzLnNjaGVtYT10aGlzLl9yZWFkZXIucmVhZFNjaGVtYSgpKSkpdGhpcy5jYW5jZWwoKX1yZXR1cm4gdGhpc310aHJvdyh0KXtpZighdGhpcy5jbG9zZWQmJnRoaXMuYXV0b0Rlc3Ryb3kmJih0aGlzLmNsb3NlZD0hMCkpcmV0dXJuIHRoaXMucmVzZXQoKS5fcmVhZGVyLnRocm93KHQpO3JldHVybiBoZX1yZXR1cm4odCl7aWYoIXRoaXMuY2xvc2VkJiZ0aGlzLmF1dG9EZXN0cm95JiYodGhpcy5jbG9zZWQ9ITApKXJldHVybiB0aGlzLnJlc2V0KCkuX3JlYWRlci5yZXR1cm4odCk7cmV0dXJuIGhlfW5leHQoKXtpZih0aGlzLmNsb3NlZClyZXR1cm4gaGU7bGV0IHQse19yZWFkZXI6ZX09dGhpczt3aGlsZSh0PXRoaXMuX3JlYWROZXh0TWVzc2FnZUFuZFZhbGlkYXRlKCkpaWYodC5pc1NjaGVtYSgpKXRoaXMucmVzZXQodC5oZWFkZXIoKSk7ZWxzZSBpZih0LmlzUmVjb3JkQmF0Y2goKSl7dGhpcy5fcmVjb3JkQmF0Y2hJbmRleCsrO2xldCByPXQuaGVhZGVyKCksbj1lLnJlYWRNZXNzYWdlQm9keSh0LmJvZHlMZW5ndGgpO3JldHVybntkb25lOiExLHZhbHVlOnRoaXMuX2xvYWRSZWNvcmRCYXRjaChyLG4sdC5tZXRhZGF0YSl9fWVsc2UgaWYodC5pc0RpY3Rpb25hcnlCYXRjaCgpKXt0aGlzLl9kaWN0aW9uYXJ5SW5kZXgrKztsZXQgcj10LmhlYWRlcigpLG49ZS5yZWFkTWVzc2FnZUJvZHkodC5ib2R5TGVuZ3RoKSxpPXRoaXMuX2xvYWREaWN0aW9uYXJ5QmF0Y2gocixuKTt0aGlzLmRpY3Rpb25hcmllcy5zZXQoci5pZCxpKX1pZih0aGlzLnNjaGVtYSYmdGhpcy5fcmVjb3JkQmF0Y2hJbmRleD09PTApcmV0dXJuIHRoaXMuX3JlY29yZEJhdGNoSW5kZXgrKyx7ZG9uZTohMSx2YWx1ZTpuZXcgZmwodGhpcy5zY2hlbWEpfTtyZXR1cm4gdGhpcy5yZXR1cm4oKX1fcmVhZE5leHRNZXNzYWdlQW5kVmFsaWRhdGUodCl7cmV0dXJuIHRoaXMuX3JlYWRlci5yZWFkTWVzc2FnZSh0KX19O0h1PWNsYXNzIEh1IGV4dGVuZHMgR2d7Y29uc3RydWN0b3IodCxlKXtzdXBlcihlKTt0aGlzLl9yZWFkZXI9bmV3IElwKHRoaXMuX2hhbmRsZT10KX1pc0FzeW5jKCl7cmV0dXJuITB9aXNTdHJlYW0oKXtyZXR1cm4hMH1bU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCl7cmV0dXJuIHRoaXN9Y2FuY2VsKCl7cmV0dXJuIE8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe2lmKCF0aGlzLmNsb3NlZCYmKHRoaXMuY2xvc2VkPSEwKSl5aWVsZCB0aGlzLnJlc2V0KCkuX3JlYWRlci5yZXR1cm4oKSx0aGlzLl9yZWFkZXI9bnVsbCx0aGlzLmRpY3Rpb25hcmllcz1udWxsfSl9b3Blbih0KXtyZXR1cm4gTyh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7aWYoIXRoaXMuY2xvc2VkKXtpZih0aGlzLmF1dG9EZXN0cm95PUpBKHRoaXMsdCksISh0aGlzLnNjaGVtYXx8KHRoaXMuc2NoZW1hPXlpZWxkIHRoaXMuX3JlYWRlci5yZWFkU2NoZW1hKCkpKSl5aWVsZCB0aGlzLmNhbmNlbCgpfXJldHVybiB0aGlzfSl9dGhyb3codCl7cmV0dXJuIE8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe2lmKCF0aGlzLmNsb3NlZCYmdGhpcy5hdXRvRGVzdHJveSYmKHRoaXMuY2xvc2VkPSEwKSlyZXR1cm4geWllbGQgdGhpcy5yZXNldCgpLl9yZWFkZXIudGhyb3codCk7cmV0dXJuIGhlfSl9cmV0dXJuKHQpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtpZighdGhpcy5jbG9zZWQmJnRoaXMuYXV0b0Rlc3Ryb3kmJih0aGlzLmNsb3NlZD0hMCkpcmV0dXJuIHlpZWxkIHRoaXMucmVzZXQoKS5fcmVhZGVyLnJldHVybih0KTtyZXR1cm4gaGV9KX1uZXh0KCl7cmV0dXJuIE8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe2lmKHRoaXMuY2xvc2VkKXJldHVybiBoZTtsZXQgdCx7X3JlYWRlcjplfT10aGlzO3doaWxlKHQ9eWllbGQgdGhpcy5fcmVhZE5leHRNZXNzYWdlQW5kVmFsaWRhdGUoKSlpZih0LmlzU2NoZW1hKCkpeWllbGQgdGhpcy5yZXNldCh0LmhlYWRlcigpKTtlbHNlIGlmKHQuaXNSZWNvcmRCYXRjaCgpKXt0aGlzLl9yZWNvcmRCYXRjaEluZGV4Kys7bGV0IHI9dC5oZWFkZXIoKSxuPXlpZWxkIGUucmVhZE1lc3NhZ2VCb2R5KHQuYm9keUxlbmd0aCk7cmV0dXJue2RvbmU6ITEsdmFsdWU6dGhpcy5fbG9hZFJlY29yZEJhdGNoKHIsbix0Lm1ldGFkYXRhKX19ZWxzZSBpZih0LmlzRGljdGlvbmFyeUJhdGNoKCkpe3RoaXMuX2RpY3Rpb25hcnlJbmRleCsrO2xldCByPXQuaGVhZGVyKCksbj15aWVsZCBlLnJlYWRNZXNzYWdlQm9keSh0LmJvZHlMZW5ndGgpLGk9dGhpcy5fbG9hZERpY3Rpb25hcnlCYXRjaChyLG4pO3RoaXMuZGljdGlvbmFyaWVzLnNldChyLmlkLGkpfWlmKHRoaXMuc2NoZW1hJiZ0aGlzLl9yZWNvcmRCYXRjaEluZGV4PT09MClyZXR1cm4gdGhpcy5fcmVjb3JkQmF0Y2hJbmRleCsrLHtkb25lOiExLHZhbHVlOm5ldyBmbCh0aGlzLnNjaGVtYSl9O3JldHVybiB5aWVsZCB0aGlzLnJldHVybigpfSl9X3JlYWROZXh0TWVzc2FnZUFuZFZhbGlkYXRlKHQpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtyZXR1cm4geWllbGQgdGhpcy5fcmVhZGVyLnJlYWRNZXNzYWdlKHQpfSl9fTtKZz1jbGFzcyBKZyBleHRlbmRzIFd1e2dldCBmb290ZXIoKXtyZXR1cm4gdGhpcy5fZm9vdGVyfWdldCBudW1EaWN0aW9uYXJpZXMoKXtyZXR1cm4gdGhpcy5fZm9vdGVyP3RoaXMuX2Zvb3Rlci5udW1EaWN0aW9uYXJpZXM6MH1nZXQgbnVtUmVjb3JkQmF0Y2hlcygpe3JldHVybiB0aGlzLl9mb290ZXI/dGhpcy5fZm9vdGVyLm51bVJlY29yZEJhdGNoZXM6MH1jb25zdHJ1Y3Rvcih0LGUpe3N1cGVyKHQgaW5zdGFuY2VvZiBIaD90Om5ldyBIaCh0KSxlKX1pc1N5bmMoKXtyZXR1cm4hMH1pc0ZpbGUoKXtyZXR1cm4hMH1vcGVuKHQpe2lmKCF0aGlzLmNsb3NlZCYmIXRoaXMuX2Zvb3Rlcil7dGhpcy5zY2hlbWE9KHRoaXMuX2Zvb3Rlcj10aGlzLl9yZWFkRm9vdGVyKCkpLnNjaGVtYTtmb3IobGV0IGUgb2YgdGhpcy5fZm9vdGVyLmRpY3Rpb25hcnlCYXRjaGVzKCkpZSYmdGhpcy5fcmVhZERpY3Rpb25hcnlCYXRjaCh0aGlzLl9kaWN0aW9uYXJ5SW5kZXgrKyl9cmV0dXJuIHN1cGVyLm9wZW4odCl9cmVhZFJlY29yZEJhdGNoKHQpe3ZhciBlO2lmKHRoaXMuY2xvc2VkKXJldHVybiBudWxsO2lmKCF0aGlzLl9mb290ZXIpdGhpcy5vcGVuKCk7bGV0IHI9KGU9dGhpcy5fZm9vdGVyKT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUuZ2V0UmVjb3JkQmF0Y2godCk7aWYociYmdGhpcy5faGFuZGxlLnNlZWsoci5vZmZzZXQpKXtsZXQgbj10aGlzLl9yZWFkZXIucmVhZE1lc3NhZ2UoVHQuUmVjb3JkQmF0Y2gpO2lmKG49PT1udWxsfHxuPT09dm9pZCAwP3ZvaWQgMDpuLmlzUmVjb3JkQmF0Y2goKSl7bGV0IGk9bi5oZWFkZXIoKSxzPXRoaXMuX3JlYWRlci5yZWFkTWVzc2FnZUJvZHkobi5ib2R5TGVuZ3RoKTtyZXR1cm4gdGhpcy5fbG9hZFJlY29yZEJhdGNoKGkscyxuLm1ldGFkYXRhKX19cmV0dXJuIG51bGx9X3JlYWREaWN0aW9uYXJ5QmF0Y2godCl7dmFyIGU7bGV0IHI9KGU9dGhpcy5fZm9vdGVyKT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUuZ2V0RGljdGlvbmFyeUJhdGNoKHQpO2lmKHImJnRoaXMuX2hhbmRsZS5zZWVrKHIub2Zmc2V0KSl7bGV0IG49dGhpcy5fcmVhZGVyLnJlYWRNZXNzYWdlKFR0LkRpY3Rpb25hcnlCYXRjaCk7aWYobj09PW51bGx8fG49PT12b2lkIDA/dm9pZCAwOm4uaXNEaWN0aW9uYXJ5QmF0Y2goKSl7bGV0IGk9bi5oZWFkZXIoKSxzPXRoaXMuX3JlYWRlci5yZWFkTWVzc2FnZUJvZHkobi5ib2R5TGVuZ3RoKSxvPXRoaXMuX2xvYWREaWN0aW9uYXJ5QmF0Y2goaSxzKTt0aGlzLmRpY3Rpb25hcmllcy5zZXQoaS5pZCxvKX19fV9yZWFkRm9vdGVyKCl7bGV0e19oYW5kbGU6dH09dGhpcyxlPXQuc2l6ZS1IZyxyPXQucmVhZEludDMyKGUpLG49dC5yZWFkQXQoZS1yLHIpO3JldHVybiBYby5kZWNvZGUobil9X3JlYWROZXh0TWVzc2FnZUFuZFZhbGlkYXRlKHQpe3ZhciBlO2lmKCF0aGlzLl9mb290ZXIpdGhpcy5vcGVuKCk7aWYodGhpcy5fZm9vdGVyJiZ0aGlzLl9yZWNvcmRCYXRjaEluZGV4PHRoaXMubnVtUmVjb3JkQmF0Y2hlcyl7bGV0IHI9KGU9dGhpcy5fZm9vdGVyKT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUuZ2V0UmVjb3JkQmF0Y2godGhpcy5fcmVjb3JkQmF0Y2hJbmRleCk7aWYociYmdGhpcy5faGFuZGxlLnNlZWsoci5vZmZzZXQpKXJldHVybiB0aGlzLl9yZWFkZXIucmVhZE1lc3NhZ2UodCl9cmV0dXJuIG51bGx9fTtLQT1jbGFzcyBLQSBleHRlbmRzIEh1e2dldCBmb290ZXIoKXtyZXR1cm4gdGhpcy5fZm9vdGVyfWdldCBudW1EaWN0aW9uYXJpZXMoKXtyZXR1cm4gdGhpcy5fZm9vdGVyP3RoaXMuX2Zvb3Rlci5udW1EaWN0aW9uYXJpZXM6MH1nZXQgbnVtUmVjb3JkQmF0Y2hlcygpe3JldHVybiB0aGlzLl9mb290ZXI/dGhpcy5fZm9vdGVyLm51bVJlY29yZEJhdGNoZXM6MH1jb25zdHJ1Y3Rvcih0LC4uLmUpe2xldCByPXR5cGVvZiBlWzBdIT09Im51bWJlciI/ZS5zaGlmdCgpOnZvaWQgMCxuPWVbMF1pbnN0YW5jZW9mIE1hcD9lLnNoaWZ0KCk6dm9pZCAwO3N1cGVyKHQgaW5zdGFuY2VvZiBIYT90Om5ldyBIYSh0LHIpLG4pfWlzRmlsZSgpe3JldHVybiEwfWlzQXN5bmMoKXtyZXR1cm4hMH1vcGVuKHQpe2xldCBlPU9iamVjdC5jcmVhdGUobnVsbCx7b3Blbjp7Z2V0OigpPT5zdXBlci5vcGVufX0pO3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtpZighdGhpcy5jbG9zZWQmJiF0aGlzLl9mb290ZXIpe3RoaXMuc2NoZW1hPSh0aGlzLl9mb290ZXI9eWllbGQgdGhpcy5fcmVhZEZvb3RlcigpKS5zY2hlbWE7Zm9yKGxldCByIG9mIHRoaXMuX2Zvb3Rlci5kaWN0aW9uYXJ5QmF0Y2hlcygpKXImJih5aWVsZCB0aGlzLl9yZWFkRGljdGlvbmFyeUJhdGNoKHRoaXMuX2RpY3Rpb25hcnlJbmRleCsrKSl9cmV0dXJuIHlpZWxkIGUub3Blbi5jYWxsKHRoaXMsdCl9KX1yZWFkUmVjb3JkQmF0Y2godCl7cmV0dXJuIE8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3ZhciBlO2lmKHRoaXMuY2xvc2VkKXJldHVybiBudWxsO2lmKCF0aGlzLl9mb290ZXIpeWllbGQgdGhpcy5vcGVuKCk7bGV0IHI9KGU9dGhpcy5fZm9vdGVyKT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUuZ2V0UmVjb3JkQmF0Y2godCk7aWYociYmKHlpZWxkIHRoaXMuX2hhbmRsZS5zZWVrKHIub2Zmc2V0KSkpe2xldCBuPXlpZWxkIHRoaXMuX3JlYWRlci5yZWFkTWVzc2FnZShUdC5SZWNvcmRCYXRjaCk7aWYobj09PW51bGx8fG49PT12b2lkIDA/dm9pZCAwOm4uaXNSZWNvcmRCYXRjaCgpKXtsZXQgaT1uLmhlYWRlcigpLHM9eWllbGQgdGhpcy5fcmVhZGVyLnJlYWRNZXNzYWdlQm9keShuLmJvZHlMZW5ndGgpO3JldHVybiB0aGlzLl9sb2FkUmVjb3JkQmF0Y2goaSxzLG4ubWV0YWRhdGEpfX1yZXR1cm4gbnVsbH0pfV9yZWFkRGljdGlvbmFyeUJhdGNoKHQpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXt2YXIgZTtsZXQgcj0oZT10aGlzLl9mb290ZXIpPT09bnVsbHx8ZT09PXZvaWQgMD92b2lkIDA6ZS5nZXREaWN0aW9uYXJ5QmF0Y2godCk7aWYociYmKHlpZWxkIHRoaXMuX2hhbmRsZS5zZWVrKHIub2Zmc2V0KSkpe2xldCBuPXlpZWxkIHRoaXMuX3JlYWRlci5yZWFkTWVzc2FnZShUdC5EaWN0aW9uYXJ5QmF0Y2gpO2lmKG49PT1udWxsfHxuPT09dm9pZCAwP3ZvaWQgMDpuLmlzRGljdGlvbmFyeUJhdGNoKCkpe2xldCBpPW4uaGVhZGVyKCkscz15aWVsZCB0aGlzLl9yZWFkZXIucmVhZE1lc3NhZ2VCb2R5KG4uYm9keUxlbmd0aCksbz10aGlzLl9sb2FkRGljdGlvbmFyeUJhdGNoKGkscyk7dGhpcy5kaWN0aW9uYXJpZXMuc2V0KGkuaWQsbyl9fX0pfV9yZWFkRm9vdGVyKCl7cmV0dXJuIE8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe2xldHtfaGFuZGxlOnR9PXRoaXM7dC5fcGVuZGluZyYmKHlpZWxkIHQuX3BlbmRpbmcpO2xldCBlPXQuc2l6ZS1IZyxyPXlpZWxkIHQucmVhZEludDMyKGUpLG49eWllbGQgdC5yZWFkQXQoZS1yLHIpO3JldHVybiBYby5kZWNvZGUobil9KX1fcmVhZE5leHRNZXNzYWdlQW5kVmFsaWRhdGUodCl7cmV0dXJuIE8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe2lmKCF0aGlzLl9mb290ZXIpeWllbGQgdGhpcy5vcGVuKCk7aWYodGhpcy5fZm9vdGVyJiZ0aGlzLl9yZWNvcmRCYXRjaEluZGV4PHRoaXMubnVtUmVjb3JkQmF0Y2hlcyl7bGV0IGU9dGhpcy5fZm9vdGVyLmdldFJlY29yZEJhdGNoKHRoaXMuX3JlY29yZEJhdGNoSW5kZXgpO2lmKGUmJih5aWVsZCB0aGlzLl9oYW5kbGUuc2VlayhlLm9mZnNldCkpKXJldHVybiB5aWVsZCB0aGlzLl9yZWFkZXIucmVhZE1lc3NhZ2UodCl9cmV0dXJuIG51bGx9KX19O0dBPWNsYXNzIEdBIGV4dGVuZHMgV3V7Y29uc3RydWN0b3IodCxlKXtzdXBlcih0LGUpfV9sb2FkVmVjdG9ycyh0LGUscil7cmV0dXJuIG5ldyBwZyhlLHQubm9kZXMsdC5idWZmZXJzLHRoaXMuZGljdGlvbmFyaWVzLHRoaXMuc2NoZW1hLm1ldGFkYXRhVmVyc2lvbix0LnZhcmlhZGljQnVmZmVyQ291bnRzKS52aXNpdE1hbnkocil9fX0pO2Z1bmN0aW9uIGtuKHQpe2xldCBlPXQuYnl0ZUxlbmd0aCs3Ji04O3JldHVybiB0aGlzLmJ1ZmZlcnMucHVzaCh0KSx0aGlzLmJ1ZmZlclJlZ2lvbnMucHVzaChuZXcgTmUodGhpcy5fYnl0ZUxlbmd0aCxlKSksdGhpcy5fYnl0ZUxlbmd0aCs9ZSx0aGlzfWZ1bmN0aW9uIExNKHQpe3ZhciBlO2xldHt0eXBlOnIsbGVuZ3RoOm4sdHlwZUlkczppLHZhbHVlT2Zmc2V0czpzfT10O2lmKGtuLmNhbGwodGhpcyxpKSxyLm1vZGU9PT1zZS5TcGFyc2UpcmV0dXJuIFhnLmNhbGwodGhpcyx0KTtlbHNlIGlmKHIubW9kZT09PXNlLkRlbnNlKWlmKHQub2Zmc2V0PD0wKXJldHVybiBrbi5jYWxsKHRoaXMscyksWGcuY2FsbCh0aGlzLHQpO2Vsc2V7bGV0IG89bmV3IEludDMyQXJyYXkobiksYT1PYmplY3QuY3JlYXRlKG51bGwpLGw9T2JqZWN0LmNyZWF0ZShudWxsKTtmb3IobGV0IHUsZixwPS0xOysrcDxuOyl7aWYoKHU9aVtwXSk9PT12b2lkIDApY29udGludWU7aWYoKGY9YVt1XSk9PT12b2lkIDApZj1hW3VdPXNbcF07b1twXT1zW3BdLWYsbFt1XT0oKGU9bFt1XSkhPT1udWxsJiZlIT09dm9pZCAwP2U6MCkrMX1rbi5jYWxsKHRoaXMsbyksdGhpcy52aXNpdE1hbnkodC5jaGlsZHJlbi5tYXAoKHUsZik9PntsZXQgcD1yLnR5cGVJZHNbZl0sZz1hW3BdLHY9bFtwXTtyZXR1cm4gdS5zbGljZShnLE1hdGgubWluKG4sdikpfSkpfXJldHVybiB0aGlzfWZ1bmN0aW9uIFVNKHQpe2xldCBlO2lmKHQubnVsbENvdW50Pj10Lmxlbmd0aClyZXR1cm4ga24uY2FsbCh0aGlzLG5ldyBVaW50OEFycmF5KHQubGVuZ3RoKzc+PjMpKTtlbHNlIGlmKChlPXQudmFsdWVzKWluc3RhbmNlb2YgVWludDhBcnJheSlyZXR1cm4ga24uY2FsbCh0aGlzLFZhKHQub2Zmc2V0LHQubGVuZ3RoLGUpKTtyZXR1cm4ga24uY2FsbCh0aGlzLHphKHQudmFsdWVzKSl9ZnVuY3Rpb24gR3ModCl7cmV0dXJuIGtuLmNhbGwodGhpcyx0LnZhbHVlcy5zdWJhcnJheSgwLHQubGVuZ3RoKnQuc3RyaWRlKSl9ZnVuY3Rpb24gRXAodCl7bGV0e2xlbmd0aDplLHZhbHVlczpyLHZhbHVlT2Zmc2V0czpufT10LGk9VnQoblswXSkscz1WdChuW2VdKSxvPU1hdGgubWluKHMtaSxyLmJ5dGVMZW5ndGgtaSk7cmV0dXJuIGtuLmNhbGwodGhpcyxyaCgtaSxlKzEsbikpLGtuLmNhbGwodGhpcyxyLnN1YmFycmF5KGksaStvKSksdGhpc31mdW5jdGlvbiBYQSh0KXtsZXR7b2Zmc2V0OmUsbGVuZ3RoOnIsc3RyaWRlOm4sdmFsdWVzOmksdmFyaWFkaWNCdWZmZXJzOnM9W119PXQ7aWYoIWkpdGhyb3cgRXJyb3IoIkJpbmFyeVZpZXcgZGF0YSBpcyBtaXNzaW5nIHZpZXcgYnVmZmVyIik7bGV0IG89ZSpuLGE9bytyKm47a24uY2FsbCh0aGlzLGkuc3ViYXJyYXkobyxhKSk7Zm9yKGxldCBsIG9mIHMpa24uY2FsbCh0aGlzLGwpO3JldHVybiB0aGlzLl92YXJpYWRpY0J1ZmZlckNvdW50cy5wdXNoKHMubGVuZ3RoKSx0aGlzfWZ1bmN0aW9uIFpnKHQpe2xldHtsZW5ndGg6ZSx2YWx1ZU9mZnNldHM6cn09dDtpZihyKXtsZXR7WzBdOm4sW2VdOml9PXI7cmV0dXJuIGtuLmNhbGwodGhpcyxyaCgtbixlKzEscikpLHRoaXMudmlzaXQodC5jaGlsZHJlblswXS5zbGljZShuLGktbikpfXJldHVybiB0aGlzLnZpc2l0KHQuY2hpbGRyZW5bMF0pfWZ1bmN0aW9uIFhnKHQpe3JldHVybiB0aGlzLnZpc2l0TWFueSh0LnR5cGUuY2hpbGRyZW4ubWFwKChlLHIpPT50LmNoaWxkcmVuW3JdKS5maWx0ZXIoQm9vbGVhbikpWzBdfXZhciB5ZTt2YXIgWkE9bSgoKT0+e2xuKCk7UWkoKTtDZSgpO3JhKCk7WWUoKTtlbCgpO3FhKCk7YWUoKTt5ZT1jbGFzcyB5ZSBleHRlbmRzIHN0e3N0YXRpYyBhc3NlbWJsZSguLi50KXtsZXQgZT0obik9Pm4uZmxhdE1hcCgoaSk9PkFycmF5LmlzQXJyYXkoaSk/ZShpKTppIGluc3RhbmNlb2YgSXQ/aS5kYXRhLmNoaWxkcmVuOmkuZGF0YSkscj1uZXcgeWU7cmV0dXJuIHIudmlzaXRNYW55KGUodCkpLHJ9Y29uc3RydWN0b3IoKXtzdXBlcigpO3RoaXMuX2J5dGVMZW5ndGg9MCx0aGlzLl9ub2Rlcz1bXSx0aGlzLl9idWZmZXJzPVtdLHRoaXMuX2J1ZmZlclJlZ2lvbnM9W10sdGhpcy5fdmFyaWFkaWNCdWZmZXJDb3VudHM9W119dmlzaXQodCl7aWYodCBpbnN0YW5jZW9mIEYpcmV0dXJuIHRoaXMudmlzaXRNYW55KHQuZGF0YSksdGhpcztsZXR7dHlwZTplfT10O2lmKCFBLmlzRGljdGlvbmFyeShlKSl7bGV0e2xlbmd0aDpyfT10O2lmKHI+MjE0NzQ4MzY0Nyl0aHJvdyBSYW5nZUVycm9yKCJDYW5ub3Qgd3JpdGUgYXJyYXlzIGxhcmdlciB0aGFuIDJeMzEgLSAxIGluIGxlbmd0aCIpO2lmKEEuaXNVbmlvbihlKSl0aGlzLm5vZGVzLnB1c2gobmV3IGVzKHIsMCkpO2Vsc2V7bGV0e251bGxDb3VudDpufT10O2lmKCFBLmlzTnVsbChlKSlrbi5jYWxsKHRoaXMsbjw9MD9uZXcgVWludDhBcnJheSgwKTpWYSh0Lm9mZnNldCxyLHQubnVsbEJpdG1hcCkpO3RoaXMubm9kZXMucHVzaChuZXcgZXMocixuKSl9fXJldHVybiBzdXBlci52aXNpdCh0KX12aXNpdE51bGwodCl7cmV0dXJuIHRoaXN9dmlzaXREaWN0aW9uYXJ5KHQpe3JldHVybiB0aGlzLnZpc2l0KHQuY2xvbmUodC50eXBlLmluZGljZXMpKX1nZXQgbm9kZXMoKXtyZXR1cm4gdGhpcy5fbm9kZXN9Z2V0IGJ1ZmZlcnMoKXtyZXR1cm4gdGhpcy5fYnVmZmVyc31nZXQgYnl0ZUxlbmd0aCgpe3JldHVybiB0aGlzLl9ieXRlTGVuZ3RofWdldCBidWZmZXJSZWdpb25zKCl7cmV0dXJuIHRoaXMuX2J1ZmZlclJlZ2lvbnN9Z2V0IHZhcmlhZGljQnVmZmVyQ291bnRzKCl7cmV0dXJuIHRoaXMuX3ZhcmlhZGljQnVmZmVyQ291bnRzfX07eWUucHJvdG90eXBlLnZpc2l0Qm9vbD1VTTt5ZS5wcm90b3R5cGUudmlzaXRJbnQ9R3M7eWUucHJvdG90eXBlLnZpc2l0RmxvYXQ9R3M7eWUucHJvdG90eXBlLnZpc2l0VXRmOD1FcDt5ZS5wcm90b3R5cGUudmlzaXRMYXJnZVV0Zjg9RXA7eWUucHJvdG90eXBlLnZpc2l0VXRmOFZpZXc9WEE7eWUucHJvdG90eXBlLnZpc2l0QmluYXJ5PUVwO3llLnByb3RvdHlwZS52aXNpdExhcmdlQmluYXJ5PUVwO3llLnByb3RvdHlwZS52aXNpdEJpbmFyeVZpZXc9WEE7eWUucHJvdG90eXBlLnZpc2l0Rml4ZWRTaXplQmluYXJ5PUdzO3llLnByb3RvdHlwZS52aXNpdERhdGU9R3M7eWUucHJvdG90eXBlLnZpc2l0VGltZXN0YW1wPUdzO3llLnByb3RvdHlwZS52aXNpdFRpbWU9R3M7eWUucHJvdG90eXBlLnZpc2l0RGVjaW1hbD1Hczt5ZS5wcm90b3R5cGUudmlzaXRMaXN0PVpnO3llLnByb3RvdHlwZS52aXNpdFN0cnVjdD1YZzt5ZS5wcm90b3R5cGUudmlzaXRVbmlvbj1MTTt5ZS5wcm90b3R5cGUudmlzaXRJbnRlcnZhbD1Hczt5ZS5wcm90b3R5cGUudmlzaXREdXJhdGlvbj1Hczt5ZS5wcm90b3R5cGUudmlzaXRGaXhlZFNpemVMaXN0PVpnO3llLnByb3RvdHlwZS52aXNpdE1hcD1aZ30pO2Z1bmN0aW9uIFFnKHQsZSl7bGV0IHI9ZTtpZihlIGluc3RhbmNlb2YgRmUpcj1lLmJhdGNoZXMsdC5yZXNldCh2b2lkIDAsZS5zY2hlbWEpO2ZvcihsZXQgbiBvZiByKXQud3JpdGUobik7cmV0dXJuIHQuZmluaXNoKCl9ZnVuY3Rpb24gdGIodCxlKXtyZXR1cm4gTyh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7dmFyIHIsbixpLHMsbyxhLGw7dHJ5e2ZvcihyPSEwLG49JGkoZSk7aT15aWVsZCBuLm5leHQoKSxzPWkuZG9uZSwhcztyPSEwKXtsPWkudmFsdWUscj0hMTtsZXQgdT1sO3Qud3JpdGUodSl9fWNhdGNoKHUpe289e2Vycm9yOnV9fWZpbmFsbHl7dHJ5e2lmKCFyJiYhcyYmKGE9bi5yZXR1cm4pKXlpZWxkIGEuY2FsbChuKX1maW5hbGx5e2lmKG8pdGhyb3cgby5lcnJvcn19cmV0dXJuIHQuZmluaXNoKCl9KX12YXIgWmEsbmEsbWw7dmFyIGViPW0oKCk9PntPbigpO3ZwKCk7WWcoKTtsbigpO3FhKCk7cWEoKTtpZygpO0NlKCk7anUoKTtXYSgpO1pBKCk7WWUoKTtyYSgpO011KCk7Z3UoKTtLZygpO0Z0KCk7WmE9Y2xhc3MgWmEgZXh0ZW5kcyBvbHtzdGF0aWMgdGhyb3VnaE5vZGUodCl7dGhyb3cgRXJyb3IoJyJ0aHJvdWdoTm9kZSIgbm90IGF2YWlsYWJsZSBpbiB0aGlzIGVudmlyb25tZW50Jyl9c3RhdGljIHRocm91Z2hET00odCxlKXt0aHJvdyBFcnJvcignInRocm91Z2hET00iIG5vdCBhdmFpbGFibGUgaW4gdGhpcyBlbnZpcm9ubWVudCcpfWNvbnN0cnVjdG9yKHQpe3N1cGVyKCk7aWYodGhpcy5fcG9zaXRpb249MCx0aGlzLl9zdGFydGVkPSExLHRoaXMuX2NvbXByZXNzaW9uPW51bGwsdGhpcy5fc2luaz1uZXcgJHMsdGhpcy5fc2NoZW1hPW51bGwsdGhpcy5fZGljdGlvbmFyeUJsb2Nrcz1bXSx0aGlzLl9yZWNvcmRCYXRjaEJsb2Nrcz1bXSx0aGlzLl9zZWVuRGljdGlvbmFyaWVzPW5ldyBNYXAsdGhpcy5fZGljdGlvbmFyeURlbHRhT2Zmc2V0cz1uZXcgTWFwLFZyKHQpfHwodD17YXV0b0Rlc3Ryb3k6ITAsd3JpdGVMZWdhY3lJcGNGb3JtYXQ6ITEsY29tcHJlc3Npb25UeXBlOm51bGx9KSx0aGlzLl9hdXRvRGVzdHJveT10eXBlb2YgdC5hdXRvRGVzdHJveT09PSJib29sZWFuIj90LmF1dG9EZXN0cm95OiEwLHRoaXMuX3dyaXRlTGVnYWN5SXBjRm9ybWF0PXR5cGVvZiB0LndyaXRlTGVnYWN5SXBjRm9ybWF0PT09ImJvb2xlYW4iP3Qud3JpdGVMZWdhY3lJcGNGb3JtYXQ6ITEsdC5jb21wcmVzc2lvblR5cGUhPW51bGwpe2lmKHRoaXMuX3dyaXRlTGVnYWN5SXBjRm9ybWF0KXRocm93IEVycm9yKCJMZWdhY3kgSVBDIGZvcm1hdCBkb2VzIG5vdCBzdXBwb3J0IGNvbHVtbmFyIGNvbXByZXNzaW9uLiBVc2UgbW9kZXJuIElQQyBmb3JtYXQgKHdyaXRlTGVnYWN5SXBjRm9ybWF0PWZhbHNlKS4iKTtpZihPYmplY3QudmFsdWVzKHpyKS5pbmNsdWRlcyh0LmNvbXByZXNzaW9uVHlwZSkpdGhpcy5fY29tcHJlc3Npb249bmV3IHNsKHQuY29tcHJlc3Npb25UeXBlKTtlbHNle2xldCBlPU9iamVjdC52YWx1ZXMoenIpLmZpbHRlcigocik9PnR5cGVvZiByPT09InN0cmluZyIpO3Rocm93IEVycm9yKGBVbnN1cHBvcnRlZCBjb21wcmVzc2lvblR5cGU6ICR7dC5jb21wcmVzc2lvblR5cGV9IEF2YWlsYWJsZSB0eXBlczogJHtlLmpvaW4oIiwgIil9YCl9fWVsc2UgdGhpcy5fY29tcHJlc3Npb249bnVsbH10b1N0cmluZyh0PSExKXtyZXR1cm4gdGhpcy5fc2luay50b1N0cmluZyh0KX10b1VpbnQ4QXJyYXkodD0hMSl7cmV0dXJuIHRoaXMuX3NpbmsudG9VaW50OEFycmF5KHQpfXdyaXRlQWxsKHQpe2lmKHFpKHQpKXJldHVybiB0LnRoZW4oKGUpPT50aGlzLndyaXRlQWxsKGUpKTtlbHNlIGlmKGVpKHQpKXJldHVybiB0Yih0aGlzLHQpO3JldHVybiBRZyh0aGlzLHQpfWdldCBjbG9zZWQoKXtyZXR1cm4gdGhpcy5fc2luay5jbG9zZWR9W1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpe3JldHVybiB0aGlzLl9zaW5rW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpfXRvRE9NU3RyZWFtKHQpe3JldHVybiB0aGlzLl9zaW5rLnRvRE9NU3RyZWFtKHQpfXRvTm9kZVN0cmVhbSh0KXtyZXR1cm4gdGhpcy5fc2luay50b05vZGVTdHJlYW0odCl9Y2xvc2UoKXtyZXR1cm4gdGhpcy5yZXNldCgpLl9zaW5rLmNsb3NlKCl9YWJvcnQodCl7cmV0dXJuIHRoaXMucmVzZXQoKS5fc2luay5hYm9ydCh0KX1maW5pc2goKXtyZXR1cm4gdGhpcy5fYXV0b0Rlc3Ryb3k/dGhpcy5jbG9zZSgpOnRoaXMucmVzZXQodGhpcy5fc2luayx0aGlzLl9zY2hlbWEpLHRoaXN9cmVzZXQodD10aGlzLl9zaW5rLGU9bnVsbCl7aWYodD09PXRoaXMuX3Npbmt8fHQgaW5zdGFuY2VvZiAkcyl0aGlzLl9zaW5rPXQ7ZWxzZSBpZih0aGlzLl9zaW5rPW5ldyAkcyx0JiZxSSh0KSl0aGlzLnRvRE9NU3RyZWFtKHt0eXBlOiJieXRlcyJ9KS5waXBlVG8odCk7ZWxzZSBpZih0JiZXSSh0KSl0aGlzLnRvTm9kZVN0cmVhbSh7b2JqZWN0TW9kZTohMX0pLnBpcGUodCk7aWYodGhpcy5fc3RhcnRlZCYmdGhpcy5fc2NoZW1hKXRoaXMuX3dyaXRlRm9vdGVyKHRoaXMuX3NjaGVtYSk7aWYodGhpcy5fc3RhcnRlZD0hMSx0aGlzLl9kaWN0aW9uYXJ5QmxvY2tzPVtdLHRoaXMuX3JlY29yZEJhdGNoQmxvY2tzPVtdLHRoaXMuX3NlZW5EaWN0aW9uYXJpZXM9bmV3IE1hcCx0aGlzLl9kaWN0aW9uYXJ5RGVsdGFPZmZzZXRzPW5ldyBNYXAsIWV8fCFLYShlLHRoaXMuX3NjaGVtYSkpaWYoZT09bnVsbCl0aGlzLl9wb3NpdGlvbj0wLHRoaXMuX3NjaGVtYT1udWxsO2Vsc2UgdGhpcy5fc3RhcnRlZD0hMCx0aGlzLl9zY2hlbWE9ZSx0aGlzLl93cml0ZVNjaGVtYShlKTtyZXR1cm4gdGhpc313cml0ZSh0KXtsZXQgZT1udWxsO2lmKCF0aGlzLl9zaW5rKXRocm93IEVycm9yKCJSZWNvcmRCYXRjaFdyaXRlciBpcyBjbG9zZWQiKTtlbHNlIGlmKHQ9PW51bGwpcmV0dXJuIHRoaXMuZmluaXNoKCkmJnZvaWQgMDtlbHNlIGlmKHQgaW5zdGFuY2VvZiBGZSYmIShlPXQuc2NoZW1hKSlyZXR1cm4gdGhpcy5maW5pc2goKSYmdm9pZCAwO2Vsc2UgaWYodCBpbnN0YW5jZW9mIEl0JiYhKGU9dC5zY2hlbWEpKXJldHVybiB0aGlzLmZpbmlzaCgpJiZ2b2lkIDA7aWYoZSYmIUthKGUsdGhpcy5fc2NoZW1hKSl7aWYodGhpcy5fc3RhcnRlZCYmdGhpcy5fYXV0b0Rlc3Ryb3kpcmV0dXJuIHRoaXMuY2xvc2UoKTt0aGlzLnJlc2V0KHRoaXMuX3NpbmssZSl9aWYodCBpbnN0YW5jZW9mIEl0KXtpZighKHQgaW5zdGFuY2VvZiBmbCkpdGhpcy5fd3JpdGVSZWNvcmRCYXRjaCh0KX1lbHNlIGlmKHQgaW5zdGFuY2VvZiBGZSl0aGlzLndyaXRlQWxsKHQuYmF0Y2hlcyk7ZWxzZSBpZihXaSh0KSl0aGlzLndyaXRlQWxsKHQpfV93cml0ZU1lc3NhZ2UodCxlPTgpe2xldCByPWUtMSxuPWlyLmVuY29kZSh0KSxpPW4uYnl0ZUxlbmd0aCxzPSF0aGlzLl93cml0ZUxlZ2FjeUlwY0Zvcm1hdD84OjQsbz1pK3MrciZ+cixhPW8taS1zO2lmKHQuaGVhZGVyVHlwZT09PVR0LlJlY29yZEJhdGNoKXRoaXMuX3JlY29yZEJhdGNoQmxvY2tzLnB1c2gobmV3IGpzKG8sdC5ib2R5TGVuZ3RoLHRoaXMuX3Bvc2l0aW9uKSk7ZWxzZSBpZih0LmhlYWRlclR5cGU9PT1UdC5EaWN0aW9uYXJ5QmF0Y2gpdGhpcy5fZGljdGlvbmFyeUJsb2Nrcy5wdXNoKG5ldyBqcyhvLHQuYm9keUxlbmd0aCx0aGlzLl9wb3NpdGlvbikpO2lmKCF0aGlzLl93cml0ZUxlZ2FjeUlwY0Zvcm1hdCl0aGlzLl93cml0ZShJbnQzMkFycmF5Lm9mKC0xKSk7aWYodGhpcy5fd3JpdGUoSW50MzJBcnJheS5vZihvLXMpKSxpPjApdGhpcy5fd3JpdGUobik7cmV0dXJuIHRoaXMuX3dyaXRlUGFkZGluZyhhKX1fd3JpdGUodCl7aWYodGhpcy5fc3RhcnRlZCl7bGV0IGU9ayh0KTtpZihlJiZlLmJ5dGVMZW5ndGg+MCl0aGlzLl9zaW5rLndyaXRlKGUpLHRoaXMuX3Bvc2l0aW9uKz1lLmJ5dGVMZW5ndGh9cmV0dXJuIHRoaXN9X3dyaXRlU2NoZW1hKHQpe3JldHVybiB0aGlzLl93cml0ZU1lc3NhZ2UoaXIuZnJvbSh0KSl9X3dyaXRlRm9vdGVyKHQpe3JldHVybiB0aGlzLl93cml0ZUxlZ2FjeUlwY0Zvcm1hdD90aGlzLl93cml0ZShJbnQzMkFycmF5Lm9mKDApKTp0aGlzLl93cml0ZShJbnQzMkFycmF5Lm9mKC0xLDApKX1fd3JpdGVNYWdpYygpe3JldHVybiB0aGlzLl93cml0ZShkbCl9X3dyaXRlUGFkZGluZyh0KXtyZXR1cm4gdD4wP3RoaXMuX3dyaXRlKG5ldyBVaW50OEFycmF5KHQpKTp0aGlzfV93cml0ZVJlY29yZEJhdGNoKHQpe2xldHtieXRlTGVuZ3RoOmUsbm9kZXM6cixidWZmZXJSZWdpb25zOm4sYnVmZmVyczppLHZhcmlhZGljQnVmZmVyQ291bnRzOnN9PXRoaXMuX2Fzc2VtYmxlUmVjb3JkQmF0Y2godCksbz1uZXcgSmUodC5udW1Sb3dzLHIsbix0aGlzLl9jb21wcmVzc2lvbixzLHQubWV0YWRhdGEpLGE9aXIuZnJvbShvLGUpO3JldHVybiB0aGlzLl93cml0ZURpY3Rpb25hcmllcyh0KS5fd3JpdGVNZXNzYWdlKGEpLl93cml0ZUJvZHlCdWZmZXJzKGkpfV9hc3NlbWJsZVJlY29yZEJhdGNoKHQpe2xldHtieXRlTGVuZ3RoOmUsbm9kZXM6cixidWZmZXJSZWdpb25zOm4sYnVmZmVyczppLHZhcmlhZGljQnVmZmVyQ291bnRzOnN9PXllLmFzc2VtYmxlKHQpO2lmKHRoaXMuX2NvbXByZXNzaW9uIT1udWxsKSh7Ynl0ZUxlbmd0aDplLGJ1ZmZlclJlZ2lvbnM6bixidWZmZXJzOml9PXRoaXMuX2NvbXByZXNzQm9keUJ1ZmZlcnMoaSkpO3JldHVybntieXRlTGVuZ3RoOmUsbm9kZXM6cixidWZmZXJSZWdpb25zOm4sYnVmZmVyczppLHZhcmlhZGljQnVmZmVyQ291bnRzOnN9fV9jb21wcmVzc0JvZHlCdWZmZXJzKHQpe2xldCBlPXBsLmdldCh0aGlzLl9jb21wcmVzc2lvbi50eXBlKTtpZighKGU9PT1udWxsfHxlPT09dm9pZCAwP3ZvaWQgMDplLmVuY29kZSl8fHR5cGVvZiBlLmVuY29kZSE9PSJmdW5jdGlvbiIpdGhyb3cgRXJyb3IoYENvZGVjIGZvciBjb21wcmVzc2lvbiB0eXBlICIke3pyW3RoaXMuX2NvbXByZXNzaW9uLnR5cGVdfSIgaGFzIGludmFsaWQgZW5jb2RlIG1ldGhvZGApO2xldCByPTAsbj1bXSxpPVtdO2ZvcihsZXQgbyBvZiB0KXtsZXQgYT1rKG8pO2lmKGEubGVuZ3RoPT09MCl7bi5wdXNoKG5ldyBVaW50OEFycmF5KDApLG5ldyBVaW50OEFycmF5KDApKSxpLnB1c2gobmV3IE5lKHIsMCkpO2NvbnRpbnVlfWxldCBsPWUuZW5jb2RlKGEpLHU9bC5sZW5ndGg8YS5sZW5ndGgsZj11P2w6YSxwPXU/Zi5sZW5ndGg6RHAsZz1uZXcgbXIobmV3IFVpbnQ4QXJyYXkocXUpKTtnLndyaXRlSW50NjQoMCxCaWdJbnQocCkpLG4ucHVzaChnLmJ5dGVzKCksbmV3IFVpbnQ4QXJyYXkoZikpO2xldCB2PShyKzcmLTgpLXI7cis9djtsZXQgST1xdStmLmxlbmd0aDtpLnB1c2gobmV3IE5lKHIsSSkpLHIrPUl9bGV0IHM9KHIrNyYtOCktcjtyZXR1cm4gcis9cyx7Ynl0ZUxlbmd0aDpyLGJ1ZmZlclJlZ2lvbnM6aSxidWZmZXJzOm59fV93cml0ZURpY3Rpb25hcnlCYXRjaCh0LGUscj0hMSl7bGV0e2J5dGVMZW5ndGg6bixub2RlczppLGJ1ZmZlclJlZ2lvbnM6cyxidWZmZXJzOm8sdmFyaWFkaWNCdWZmZXJDb3VudHM6YX09dGhpcy5fYXNzZW1ibGVSZWNvcmRCYXRjaChuZXcgRihbdF0pKSxsPW5ldyBKZSh0Lmxlbmd0aCxpLHMsdGhpcy5fY29tcHJlc3Npb24sYSksdT1uZXcgcXIobCxlLHIpLGY9aXIuZnJvbSh1LG4pO3JldHVybiB0aGlzLl93cml0ZU1lc3NhZ2UoZikuX3dyaXRlQm9keUJ1ZmZlcnMobyl9X3dyaXRlQm9keUJ1ZmZlcnModCl7bGV0IGU9dGhpcy5fY29tcHJlc3Npb24hPW51bGw/MjoxLHI9QXJyYXkoZSk7Zm9yKGxldCBuPTA7bjx0Lmxlbmd0aDtuKz1lKXtsZXQgaT0wO2ZvcihsZXQgbz0tMTsrK288ZTspcltvXT10W24rb10saSs9cltvXS5ieXRlTGVuZ3RoO2lmKGk9PT0wKWNvbnRpbnVlO2ZvcihsZXQgbyBvZiByKXRoaXMuX3dyaXRlKG8pO2xldCBzPShpKzcmLTgpLWk7aWYocz4wKXRoaXMuX3dyaXRlUGFkZGluZyhzKX1yZXR1cm4gdGhpc31fd3JpdGVEaWN0aW9uYXJpZXModCl7dmFyIGUscjtmb3IobGV0W24saV1vZiB0LmRpY3Rpb25hcmllcyl7bGV0IHM9KGU9aT09PW51bGx8fGk9PT12b2lkIDA/dm9pZCAwOmkuZGF0YSkhPT1udWxsJiZlIT09dm9pZCAwP2U6W10sbz10aGlzLl9zZWVuRGljdGlvbmFyaWVzLmdldChuKSxhPShyPXRoaXMuX2RpY3Rpb25hcnlEZWx0YU9mZnNldHMuZ2V0KG4pKSE9PW51bGwmJnIhPT12b2lkIDA/cjowO2lmKCFvfHxvLmRhdGFbMF0hPT1zWzBdKWZvcihsZXRbbCx1XW9mIHMuZW50cmllcygpKXRoaXMuX3dyaXRlRGljdGlvbmFyeUJhdGNoKHUsbixsPjApO2Vsc2UgaWYoYTxzLmxlbmd0aClmb3IobGV0IGwgb2Ygcy5zbGljZShhKSl0aGlzLl93cml0ZURpY3Rpb25hcnlCYXRjaChsLG4sITApO3RoaXMuX3NlZW5EaWN0aW9uYXJpZXMuc2V0KG4saSksdGhpcy5fZGljdGlvbmFyeURlbHRhT2Zmc2V0cy5zZXQobixzLmxlbmd0aCl9cmV0dXJuIHRoaXN9fTtuYT1jbGFzcyBuYSBleHRlbmRzIFphe3N0YXRpYyB3cml0ZUFsbCh0LGUpe2xldCByPW5ldyBuYShlKTtpZihxaSh0KSlyZXR1cm4gdC50aGVuKChuKT0+ci53cml0ZUFsbChuKSk7ZWxzZSBpZihlaSh0KSlyZXR1cm4gdGIocix0KTtyZXR1cm4gUWcocix0KX19O21sPWNsYXNzIG1sIGV4dGVuZHMgWmF7c3RhdGljIHdyaXRlQWxsKHQsZSl7bGV0IHI9bmV3IG1sKGUpO2lmKHFpKHQpKXJldHVybiB0LnRoZW4oKG4pPT5yLndyaXRlQWxsKG4pKTtlbHNlIGlmKGVpKHQpKXJldHVybiB0YihyLHQpO3JldHVybiBRZyhyLHQpfWNvbnN0cnVjdG9yKHQpe3N1cGVyKHQpO3RoaXMuX2F1dG9EZXN0cm95PSEwLHRoaXMuX3dyaXRlTGVnYWN5SXBjRm9ybWF0PSExfV93cml0ZVNjaGVtYSh0KXtyZXR1cm4gdGhpcy5fd3JpdGVNYWdpYygpLl93cml0ZVBhZGRpbmcoMil9X3dyaXRlRGljdGlvbmFyeUJhdGNoKHQsZSxyPSExKXtpZighciYmdGhpcy5fc2VlbkRpY3Rpb25hcmllcy5oYXMoZSkpdGhyb3cgRXJyb3IoIlRoZSBBcnJvdyBGaWxlIGZvcm1hdCBkb2VzIG5vdCBzdXBwb3J0IHJlcGxhY2VtZW50IGRpY3Rpb25hcmllcy4gIik7cmV0dXJuIHN1cGVyLl93cml0ZURpY3Rpb25hcnlCYXRjaCh0LGUscil9X3dyaXRlRm9vdGVyKHQpe2xldCBlPVhvLmVuY29kZShuZXcgWG8odCxIdC5WNSx0aGlzLl9yZWNvcmRCYXRjaEJsb2Nrcyx0aGlzLl9kaWN0aW9uYXJ5QmxvY2tzKSk7cmV0dXJuIHN1cGVyLl93cml0ZUZvb3Rlcih0KS5fd3JpdGUoZSkuX3dyaXRlKEludDMyQXJyYXkub2YoZS5ieXRlTGVuZ3RoKSkuX3dyaXRlTWFnaWMoKX19fSk7ZnVuY3Rpb24gUUEodCxlKXtpZihlaSh0KSlyZXR1cm4gQ00odCxlKTtpZihXaSh0KSlyZXR1cm4gUk0odCxlKTt0aHJvdyBFcnJvcigidG9ET01TdHJlYW0oKSBtdXN0IGJlIGNhbGxlZCB3aXRoIGFuIEl0ZXJhYmxlIG9yIEFzeW5jSXRlcmFibGUiKX1mdW5jdGlvbiBSTSh0LGUpe2xldCByPW51bGwsbj0oZT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUudHlwZSk9PT0iYnl0ZXMifHwhMSxpPShlPT09bnVsbHx8ZT09PXZvaWQgMD92b2lkIDA6ZS5oaWdoV2F0ZXJNYXJrKXx8TWF0aC5wb3coMiwyNCk7cmV0dXJuIG5ldyBSZWFkYWJsZVN0cmVhbShPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sZSkse3N0YXJ0KG8pe3MobyxyfHwocj10W1N5bWJvbC5pdGVyYXRvcl0oKSkpfSxwdWxsKG8pe3I/cyhvLHIpOm8uY2xvc2UoKX0sY2FuY2VsKCl7KHI9PT1udWxsfHxyPT09dm9pZCAwP3ZvaWQgMDpyLnJldHVybikmJnIucmV0dXJuKCkscj1udWxsfX0pLE9iamVjdC5hc3NpZ24oe2hpZ2hXYXRlck1hcms6bj9pOnZvaWQgMH0sZSkpO2Z1bmN0aW9uIHMobyxhKXtsZXQgbCx1PW51bGwsZj1vLmRlc2lyZWRTaXplfHxudWxsO3doaWxlKCEodT1hLm5leHQobj9mOm51bGwpKS5kb25lKXtpZihBcnJheUJ1ZmZlci5pc1ZpZXcodS52YWx1ZSkmJihsPWsodS52YWx1ZSkpKWYhPW51bGwmJm4mJihmPWYtbC5ieXRlTGVuZ3RoKzEpLHUudmFsdWU9bDtpZihvLmVucXVldWUodS52YWx1ZSksZiE9bnVsbCYmLS1mPD0wKXJldHVybn1vLmNsb3NlKCl9fWZ1bmN0aW9uIENNKHQsZSl7bGV0IHI9bnVsbCxuPShlPT09bnVsbHx8ZT09PXZvaWQgMD92b2lkIDA6ZS50eXBlKT09PSJieXRlcyJ8fCExLGk9KGU9PT1udWxsfHxlPT09dm9pZCAwP3ZvaWQgMDplLmhpZ2hXYXRlck1hcmspfHxNYXRoLnBvdygyLDI0KTtyZXR1cm4gbmV3IFJlYWRhYmxlU3RyZWFtKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSxlKSx7c3RhcnQobyl7cmV0dXJuIE8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3lpZWxkIHMobyxyfHwocj10W1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpKSl9KX0scHVsbChvKXtyZXR1cm4gTyh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7cj95aWVsZCBzKG8scik6by5jbG9zZSgpfSl9LGNhbmNlbCgpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXsocj09PW51bGx8fHI9PT12b2lkIDA/dm9pZCAwOnIucmV0dXJuKSYmKHlpZWxkIHIucmV0dXJuKCkpLHI9bnVsbH0pfX0pLE9iamVjdC5hc3NpZ24oe2hpZ2hXYXRlck1hcms6bj9pOnZvaWQgMH0sZSkpO2Z1bmN0aW9uIHMobyxhKXtyZXR1cm4gTyh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7bGV0IGwsdT1udWxsLGY9by5kZXNpcmVkU2l6ZXx8bnVsbDt3aGlsZSghKHU9eWllbGQgYS5uZXh0KG4/ZjpudWxsKSkuZG9uZSl7aWYoQXJyYXlCdWZmZXIuaXNWaWV3KHUudmFsdWUpJiYobD1rKHUudmFsdWUpKSlmIT1udWxsJiZuJiYoZj1mLWwuYnl0ZUxlbmd0aCsxKSx1LnZhbHVlPWw7aWYoby5lbnF1ZXVlKHUudmFsdWUpLGYhPW51bGwmJi0tZjw9MClyZXR1cm59by5jbG9zZSgpfSl9fXZhciB0RD1tKCgpPT57T24oKTtZZSgpfSk7ZnVuY3Rpb24gbkQodCl7cmV0dXJuIG5ldyBpRCh0KX1jbGFzcyBpRHtjb25zdHJ1Y3Rvcih0KXt0aGlzLl9udW1DaHVua3M9MCx0aGlzLl9maW5pc2hlZD0hMSx0aGlzLl9idWZmZXJlZFNpemU9MDtsZXR7WyJyZWFkYWJsZVN0cmF0ZWd5Il06ZSxbIndyaXRhYmxlU3RyYXRlZ3kiXTpyLFsicXVldWVpbmdTdHJhdGVneSJdOm49ImNvdW50In09dCxpPXpJKHQsWyJyZWFkYWJsZVN0cmF0ZWd5Iiwid3JpdGFibGVTdHJhdGVneSIsInF1ZXVlaW5nU3RyYXRlZ3kiXSk7dGhpcy5fY29udHJvbGxlcj1udWxsLHRoaXMuX2J1aWxkZXI9V3MoaSksdGhpcy5fZ2V0U2l6ZT1uIT09ImJ5dGVzIj9lRDpyRDtsZXR7WyJoaWdoV2F0ZXJNYXJrIl06cz1uPT09ImJ5dGVzIj9NYXRoLnBvdygyLDE0KToxMDAwfT1PYmplY3QuYXNzaWduKHt9LGUpLHtbImhpZ2hXYXRlck1hcmsiXTpvPW49PT0iYnl0ZXMiP01hdGgucG93KDIsMTQpOjEwMDB9PU9iamVjdC5hc3NpZ24oe30scik7dGhpcy5yZWFkYWJsZT1uZXcgUmVhZGFibGVTdHJlYW0oe1siY2FuY2VsIl06KCk9Pnt0aGlzLl9idWlsZGVyLmNsZWFyKCl9LFsicHVsbCJdOihhKT0+e3RoaXMuX21heWJlRmx1c2godGhpcy5fYnVpbGRlcix0aGlzLl9jb250cm9sbGVyPWEpfSxbInN0YXJ0Il06KGEpPT57dGhpcy5fbWF5YmVGbHVzaCh0aGlzLl9idWlsZGVyLHRoaXMuX2NvbnRyb2xsZXI9YSl9fSx7aGlnaFdhdGVyTWFyazpzLHNpemU6biE9PSJieXRlcyI/ZUQ6ckR9KSx0aGlzLndyaXRhYmxlPW5ldyBXcml0YWJsZVN0cmVhbSh7WyJhYm9ydCJdOigpPT57dGhpcy5fYnVpbGRlci5jbGVhcigpfSxbIndyaXRlIl06KCk9Pnt0aGlzLl9tYXliZUZsdXNoKHRoaXMuX2J1aWxkZXIsdGhpcy5fY29udHJvbGxlcil9LFsiY2xvc2UiXTooKT0+e3RoaXMuX21heWJlRmx1c2godGhpcy5fYnVpbGRlci5maW5pc2goKSx0aGlzLl9jb250cm9sbGVyKX19LHtoaWdoV2F0ZXJNYXJrOm8sc2l6ZTooYSk9PnRoaXMuX3dyaXRlVmFsdWVBbmRSZXR1cm5DaHVua1NpemUoYSl9KX1fd3JpdGVWYWx1ZUFuZFJldHVybkNodW5rU2l6ZSh0KXtsZXQgZT10aGlzLl9idWZmZXJlZFNpemU7cmV0dXJuIHRoaXMuX2J1ZmZlcmVkU2l6ZT10aGlzLl9nZXRTaXplKHRoaXMuX2J1aWxkZXIuYXBwZW5kKHQpKSx0aGlzLl9idWZmZXJlZFNpemUtZX1fbWF5YmVGbHVzaCh0LGUpe2lmKGU9PW51bGwpcmV0dXJuO2lmKHRoaXMuX2J1ZmZlcmVkU2l6ZT49ZS5kZXNpcmVkU2l6ZSkrK3RoaXMuX251bUNodW5rcyYmdGhpcy5fZW5xdWV1ZShlLHQudG9WZWN0b3IoKSk7aWYodC5maW5pc2hlZCl7aWYodC5sZW5ndGg+MHx8dGhpcy5fbnVtQ2h1bmtzPT09MCkrK3RoaXMuX251bUNodW5rcyYmdGhpcy5fZW5xdWV1ZShlLHQudG9WZWN0b3IoKSk7aWYoIXRoaXMuX2ZpbmlzaGVkJiYodGhpcy5fZmluaXNoZWQ9ITApKXRoaXMuX2VucXVldWUoZSxudWxsKX19X2VucXVldWUodCxlKXt0aGlzLl9idWZmZXJlZFNpemU9MCx0aGlzLl9jb250cm9sbGVyPW51bGwsZT09bnVsbD90LmNsb3NlKCk6dC5lbnF1ZXVlKGUpfX12YXIgZUQ9KHQpPT57dmFyIGU7cmV0dXJuKGU9dD09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnQubGVuZ3RoKSE9PW51bGwmJmUhPT12b2lkIDA/ZTowfSxyRD0odCk9Pnt2YXIgZTtyZXR1cm4oZT10PT09bnVsbHx8dD09PXZvaWQgMD92b2lkIDA6dC5ieXRlTGVuZ3RoKSE9PW51bGwmJmUhPT12b2lkIDA/ZTowfTt2YXIgc0Q9bSgoKT0+e09uKCk7WGgoKX0pO2Z1bmN0aW9uIE9wKHQsZSl7bGV0IHI9bmV3ICRzLG49bnVsbCxpPW5ldyBSZWFkYWJsZVN0cmVhbSh7Y2FuY2VsKCl7cmV0dXJuIE8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3lpZWxkIHIuY2xvc2UoKX0pfSxzdGFydChhKXtyZXR1cm4gTyh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7eWllbGQgbyhhLG58fChuPXlpZWxkIHMoKSkpfSl9LHB1bGwoYSl7cmV0dXJuIE8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe24/eWllbGQgbyhhLG4pOmEuY2xvc2UoKX0pfX0pO3JldHVybnt3cml0YWJsZTpuZXcgV3JpdGFibGVTdHJlYW0ocixPYmplY3QuYXNzaWduKHtoaWdoV2F0ZXJNYXJrOk1hdGgucG93KDIsMTQpfSx0KSkscmVhZGFibGU6aX07ZnVuY3Rpb24gcygpe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtyZXR1cm4geWllbGQoeWllbGQgYmUuZnJvbShyKSkub3BlbihlKX0pfWZ1bmN0aW9uIG8oYSxsKXtyZXR1cm4gTyh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7bGV0IHU9YS5kZXNpcmVkU2l6ZSxmPW51bGw7d2hpbGUoIShmPXlpZWxkIGwubmV4dCgpKS5kb25lKWlmKGEuZW5xdWV1ZShmLnZhbHVlKSx1IT1udWxsJiYtLXU8PTApcmV0dXJuO2EuY2xvc2UoKX0pfX12YXIgb0Q9bSgoKT0+e09uKCk7V2EoKTtUcCgpfSk7ZnVuY3Rpb24gTnAodCxlKXtsZXQgcj1uZXcgdGhpcyh0KSxuPW5ldyBtaShyKSxpPW5ldyBSZWFkYWJsZVN0cmVhbSh7Y2FuY2VsKCl7cmV0dXJuIE8odGhpcyx2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKigpe3lpZWxkIG4uY2FuY2VsKCl9KX0scHVsbChvKXtyZXR1cm4gTyh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7eWllbGQgcyhvKX0pfSxzdGFydChvKXtyZXR1cm4gTyh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24qKCl7eWllbGQgcyhvKX0pfX0sT2JqZWN0LmFzc2lnbih7aGlnaFdhdGVyTWFyazpNYXRoLnBvdygyLDE0KX0sZSkpO3JldHVybnt3cml0YWJsZTpuZXcgV3JpdGFibGVTdHJlYW0ocix0KSxyZWFkYWJsZTppfTtmdW5jdGlvbiBzKG8pe3JldHVybiBPKHRoaXMsdm9pZCAwLHZvaWQgMCxmdW5jdGlvbiooKXtsZXQgYT1udWxsLGw9by5kZXNpcmVkU2l6ZTt3aGlsZShhPXlpZWxkIG4ucmVhZChsfHxudWxsKSlpZihvLmVucXVldWUoYSksbCE9bnVsbCYmKGwtPWEuYnl0ZUxlbmd0aCk8PTApcmV0dXJuO28uY2xvc2UoKX0pfX12YXIgYUQ9bSgoKT0+e09uKCk7V2EoKX0pO3ZhciByYj17fTtaZShyYix7aXNBcnJvd0RhdGE6KCk9PmZELGlzQXJyb3dEYXRhVHlwZTooKT0+dUQsaXNBcnJvd0ZpZWxkOigpPT5sRCxpc0Fycm93UmVjb3JkQmF0Y2g6KCk9PmhELGlzQXJyb3dTY2hlbWE6KCk9PmNELGlzQXJyb3dUYWJsZTooKT0+cEQsaXNBcnJvd1ZlY3RvcjooKT0+ZER9KTtmdW5jdGlvbiBjRCh0KXtyZXR1cm4gai5pc1NjaGVtYSh0KX1mdW5jdGlvbiBsRCh0KXtyZXR1cm4gVi5pc0ZpZWxkKHQpfWZ1bmN0aW9uIHVEKHQpe3JldHVybiBBLmlzRGF0YVR5cGUodCl9ZnVuY3Rpb24gZkQodCl7cmV0dXJuIGh0LmlzRGF0YSh0KX1mdW5jdGlvbiBkRCh0KXtyZXR1cm4gRi5pc1ZlY3Rvcih0KX1mdW5jdGlvbiBoRCh0KXtyZXR1cm4gSXQuaXNSZWNvcmRCYXRjaCh0KX1mdW5jdGlvbiBwRCh0KXtyZXR1cm4gRmUuaXNUYWJsZSh0KX12YXIgbUQ9bSgoKT0+eyRyKCk7YWUoKTtwaSgpO2xuKCk7cmEoKTt2cCgpfSk7dmFyIG5MO3ZhciBiRD1tKCgpPT57Q2UoKTtwaSgpO2FlKCk7JHIoKTtYaCgpO1RwKCk7ZWIoKTtyYSgpO3pfKCk7dWcoKTtlbCgpO0R1KCk7WWUoKTtRYygpO21EKCk7anUoKTtuTD1PYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LFZfKSxsZyksdGcpLGpfKSxhXyksUV8pLFJfKSxoZykscmIpLHtjb21wYXJlU2NoZW1hczpLYSxjb21wYXJlRmllbGRzOk9BLGNvbXBhcmVUeXBlczpncH0pfSk7dmFyIEpzPW0oKCk9PntwdSgpO2dlKCk7VHAoKTtlYigpO3REKCk7c0QoKTtvRCgpO2FEKCk7YkQoKTtwci50b0RPTVN0cmVhbT1RQTtkZS50aHJvdWdoRE9NPW5EO2JlLnRocm91Z2hET009T3A7WGEudGhyb3VnaERPTT1PcDtLcy50aHJvdWdoRE9NPU9wO1phLnRocm91Z2hET009TnA7bWwudGhyb3VnaERPTT1OcDtuYS50aHJvdWdoRE9NPU5wfSk7ZnVuY3Rpb24gREQodCxlKXt2YXIgcj1bXSxuPSshZSxpPTAscz0wO2Zvcig7dC5sZW5ndGg7KXt2YXIgbz1kTCh0LG58fGUpO2lmKHR5cGVvZiBvPT0ib2JqZWN0Iil7aWYobil7aWYoZT1udWxsLG8udy5sZW5ndGg9PW8udSlyLnB1c2goZT1vLncpLHMrPW8udX1lbHNlIHIucHVzaChlKSxvLmU9MDtmb3IoOyFvLmw7KXt2YXIgYT13TCh0LG8sZSk7aWYoIWEpa2UoNSk7aWYoZSlvLmU9by55O2Vsc2Ugci5wdXNoKGEpLHMrPWEubGVuZ3RoLGxMKG8udywwLGEubGVuZ3RoKSxvLncuc2V0KGEsby53Lmxlbmd0aC1hLmxlbmd0aCl9aT1vLmIrby5jKjR9ZWxzZSBpPW87dD10LnN1YmFycmF5KGkpfXJldHVybiB2TChyLHMpfXZhciBhTCxNZSxrcCxjTCxWcCxmYj1mdW5jdGlvbih0LGUscil7aWYoTWUucHJvdG90eXBlLnNsaWNlKXJldHVybiBNZS5wcm90b3R5cGUuc2xpY2UuY2FsbCh0LGUscik7aWYoZT09bnVsbHx8ZTwwKWU9MDtpZihyPT1udWxsfHxyPnQubGVuZ3RoKXI9dC5sZW5ndGg7dmFyIG49bmV3IE1lKHItZSk7cmV0dXJuIG4uc2V0KHQuc3ViYXJyYXkoZSxyKSksbn0sWnU9ZnVuY3Rpb24odCxlLHIsbil7aWYoTWUucHJvdG90eXBlLmZpbGwpcmV0dXJuIE1lLnByb3RvdHlwZS5maWxsLmNhbGwodCxlLHIsbik7aWYocj09bnVsbHx8cjwwKXI9MDtpZihuPT1udWxsfHxuPnQubGVuZ3RoKW49dC5sZW5ndGg7Zm9yKDtyPG47KytyKXRbcl09ZTtyZXR1cm4gdH0sbEw9ZnVuY3Rpb24odCxlLHIsbil7aWYoTWUucHJvdG90eXBlLmNvcHlXaXRoaW4pcmV0dXJuIE1lLnByb3RvdHlwZS5jb3B5V2l0aGluLmNhbGwodCxlLHIsbik7aWYocj09bnVsbHx8cjwwKXI9MDtpZihuPT1udWxsfHxuPnQubGVuZ3RoKW49dC5sZW5ndGg7d2hpbGUocjxuKXRbZSsrXT10W3IrK119LHVMLGtlPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbj1FcnJvcihlfHx1TFt0XSk7aWYobi5jb2RlPXQsRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UpRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UobixrZSk7aWYoIXIpdGhyb3cgbjtyZXR1cm4gbn0sU0Q9ZnVuY3Rpb24odCxlLHIpe3ZhciBuPTAsaT0wO2Zvcig7bjxyOysrbilpfD10W2UrK108PChuPDwzKTtyZXR1cm4gaX0sZkw9ZnVuY3Rpb24odCxlKXtyZXR1cm4odFtlXXx0W2UrMV08PDh8dFtlKzJdPDwxNnx0W2UrM108PDI0KT4+PjB9LGRMPWZ1bmN0aW9uKHQsZSl7dmFyIHI9dFswXXx0WzFdPDw4fHRbMl08PDE2O2lmKHI9PTMxMjY1NjgmJnRbM109PTI1Myl7dmFyIG49dFs0XSxpPW4+PjUmMSxzPW4+PjImMSxvPW4mMyxhPW4+PjY7aWYobiY4KWtlKDApO3ZhciBsPTYtaSx1PW89PTM/NDpvLGY9U0QodCxsLHUpO2wrPXU7dmFyIHA9YT8xPDxhOmksZz1TRCh0LGwscCkrKGE9PTEmJjI1Niksdj1nO2lmKCFpKXt2YXIgST0xPDwxMCsodFs1XT4+Myk7dj1JKyhJPj4zKSoodFs1XSY3KX1pZih2PjIxNDUzODY0OTYpa2UoMSk7dmFyIEQ9bmV3IE1lKChlPT0xP2d8fHY6ZT8wOnYpKzEyKTtyZXR1cm4gRFswXT0xLERbNF09NCxEWzhdPTgse2I6bCtwLHk6MCxsOjAsZDpmLHc6ZSYmZSE9MT9lOkQuc3ViYXJyYXkoMTIpLGU6dixvOm5ldyBWcChELmJ1ZmZlciwwLDMpLHU6ZyxjOnMsbTpNYXRoLm1pbigxMzEwNzIsdil9fWVsc2UgaWYoKHI+PjR8dFszXTw8MjApPT0yNTQ4MTg5MylyZXR1cm4gZkwodCw0KSs4O2tlKDApfSx0Yz1mdW5jdGlvbih0KXt2YXIgZT0wO2Zvcig7MTw8ZTw9dDsrK2UpO3JldHVybiBlLTF9LFF1PWZ1bmN0aW9uKHQsZSxyKXt2YXIgbj0oZTw8MykrNCxpPSh0W2VdJjE1KSs1O2lmKGk+cilrZSgzKTt2YXIgcz0xPDxpLG89cyxhPS0xLGw9LTEsdT0tMSxmPXMscD1uZXcgYUwoNTEyKyhzPDwyKSksZz1uZXcgY0wocCwwLDI1Niksdj1uZXcga3AocCwwLDI1NiksST1uZXcga3AocCw1MTIscyksRD01MTIrKHM8PDEpLFo9bmV3IE1lKHAsRCxzKSxtdD1uZXcgTWUocCxEK3MpO3doaWxlKGE8MjU1JiZvPjApe3ZhciBwZT10YyhvKzEpLEJlPW4+PjMsX2k9KDE8PHBlKzEpLTEsU2U9KHRbQmVdfHRbQmUrMV08PDh8dFtCZSsyXTw8MTYpPj4obiY3KSZfaSxCdD0oMTw8cGUpLTEsej1faS1vLTEsTXQ9U2UmQnQ7aWYoTXQ8eiluKz1wZSxTZT1NdDtlbHNlIGlmKG4rPXBlKzEsU2U+QnQpU2UtPXo7aWYoZ1srK2FdPS0tU2UsU2U9PS0xKW8rPVNlLFpbLS1mXT1hO2Vsc2Ugby09U2U7aWYoIVNlKWRve3ZhciBncj1uPj4zO2w9KHRbZ3JdfHRbZ3IrMV08PDgpPj4obiY3KSYzLG4rPTIsYSs9bH13aGlsZShsPT0zKX1pZihhPjI1NXx8bylrZSgwKTt2YXIgVXQ9MCxYZT0ocz4+MSkrKHM+PjMpKzMsWXI9cy0xO2Zvcih2YXIgc3I9MDtzcjw9YTsrK3NyKXt2YXIgenQ9Z1tzcl07aWYoenQ8MSl7dltzcl09LXp0O2NvbnRpbnVlfWZvcih1PTA7dTx6dDsrK3Upe1pbVXRdPXNyO2RvIFV0PVV0K1hlJllyO3doaWxlKFV0Pj1mKX19aWYoVXQpa2UoMCk7Zm9yKHU9MDt1PHM7Kyt1KXt2YXIgU3Q9dltaW3VdXSsrLGxlPW10W3VdPWktdGMoU3QpO0lbdV09KFN0PDxsZSktc31yZXR1cm5bbis3Pj4zLHtiOmksczpaLG46bXQsdDpJfV19LGhMPWZ1bmN0aW9uKHQsZSl7dmFyIHI9MCxuPS0xLGk9bmV3IE1lKDI5Mikscz10W2VdLG89aS5zdWJhcnJheSgwLDI1NiksYT1pLnN1YmFycmF5KDI1NiwyNjgpLGw9bmV3IGtwKGkuYnVmZmVyLDI2OCk7aWYoczwxMjgpe3ZhciB1PVF1KHQsZSsxLDYpLGY9dVswXSxwPXVbMV07ZSs9czt2YXIgZz1mPDwzLHY9dFtlXTtpZighdilrZSgwKTt2YXIgST0wLEQ9MCxaPXAuYixtdD1aLHBlPSgrK2U8PDMpLTgrdGModik7Zm9yKDs7KXtpZihwZS09WixwZTxnKWJyZWFrO3ZhciBCZT1wZT4+MztpZihJKz0odFtCZV18dFtCZSsxXTw8OCk+PihwZSY3KSYoMTw8WiktMSxvWysrbl09cC5zW0ldLHBlLT1tdCxwZTxnKWJyZWFrO0JlPXBlPj4zLEQrPSh0W0JlXXx0W0JlKzFdPDw4KT4+KHBlJjcpJigxPDxtdCktMSxvWysrbl09cC5zW0RdLFo9cC5uW0ldLEk9cC50W0ldLG10PXAubltEXSxEPXAudFtEXX1pZigrK24+MjU1KWtlKDApfWVsc2V7bj1zLTEyNztmb3IoO3I8bjtyKz0yKXt2YXIgX2k9dFsrK2VdO29bcl09X2k+PjQsb1tyKzFdPV9pJjE1fSsrZX12YXIgU2U9MDtmb3Iocj0wO3I8bjsrK3Ipe3ZhciBCdD1vW3JdO2lmKEJ0PjExKWtlKDApO1NlKz1CdCYmMTw8QnQtMX12YXIgej10YyhTZSkrMSxNdD0xPDx6LGdyPU10LVNlO2lmKGdyJmdyLTEpa2UoMCk7b1tuKytdPXRjKGdyKSsxO2ZvcihyPTA7cjxuOysrcil7dmFyIEJ0PW9bcl07KythW29bcl09QnQmJnorMS1CdF19dmFyIFV0PW5ldyBNZShNdDw8MSksWGU9VXQuc3ViYXJyYXkoMCxNdCksWXI9VXQuc3ViYXJyYXkoTXQpO2xbel09MDtmb3Iocj16O3I+MDstLXIpe3ZhciBzcj1sW3JdO1p1KFlyLHIsc3IsbFtyLTFdPXNyK2Fbcl0qKDE8PHotcikpfWlmKGxbMF0hPU10KWtlKDApO2ZvcihyPTA7cjxuOysrcil7dmFyIHp0PW9bcl07aWYoenQpe3ZhciBTdD1sW3p0XTtadShYZSxyLFN0LGxbenRdPVN0KygxPDx6LXp0KSl9fXJldHVybltlLHtuOllyLGI6eixzOlhlfV19LHBMLG1MLHlMLEFEPWZ1bmN0aW9uKHQsZSl7dmFyIHI9dC5sZW5ndGgsbj1uZXcgVnAocik7Zm9yKHZhciBpPTA7aTxyOysraSluW2ldPWUsZSs9MTw8dFtpXTtyZXR1cm4gbn0sZGIsX0wsaGIsZ0wsWHU9ZnVuY3Rpb24odCxlLHIpe3ZhciBuPXQubGVuZ3RoLGk9ZS5sZW5ndGgscz10W24tMV0sbz0oMTw8ci5iKS0xLGE9LXIuYjtpZighcylrZSgwKTt2YXIgbD0wLHU9ci5iLGY9KG48PDMpLTgrdGMocyktdSxwPS0xO2Zvcig7Zj5hJiZwPGk7KXt2YXIgZz1mPj4zLHY9KHRbZ118dFtnKzFdPDw4fHRbZysyXTw8MTYpPj4oZiY3KTtsPShsPDx1fHYpJm8sZVsrK3BdPXIuc1tsXSxmLT11PXIubltsXX1pZihmIT1hfHxwKzEhPWkpa2UoMCl9LGJMPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbj02LGk9ZS5sZW5ndGgscz1pKzM+PjIsbz1zPDwxLGE9cytvO1h1KHQuc3ViYXJyYXkobixuKz10WzBdfHRbMV08PDgpLGUuc3ViYXJyYXkoMCxzKSxyKSxYdSh0LnN1YmFycmF5KG4sbis9dFsyXXx0WzNdPDw4KSxlLnN1YmFycmF5KHMsbyksciksWHUodC5zdWJhcnJheShuLG4rPXRbNF18dFs1XTw8OCksZS5zdWJhcnJheShvLGEpLHIpLFh1KHQuc3ViYXJyYXkobiksZS5zdWJhcnJheShhKSxyKX0sd0w9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLGk9ZS5iLHM9dFtpXSxvPXM+PjEmMztlLmw9cyYxO3ZhciBhPXM+PjN8dFtpKzFdPDw1fHRbaSsyXTw8MTMsbD0oaSs9MykrYTtpZihvPT0xKXtpZihpPj10Lmxlbmd0aClyZXR1cm47aWYoZS5iPWkrMSxyKXJldHVybiBadShyLHRbaV0sZS55LGUueSs9YSkscjtyZXR1cm4gWnUobmV3IE1lKGEpLHRbaV0pfWlmKGw+dC5sZW5ndGgpcmV0dXJuO2lmKG89PTApe2lmKGUuYj1sLHIpcmV0dXJuIHIuc2V0KHQuc3ViYXJyYXkoaSxsKSxlLnkpLGUueSs9YSxyO3JldHVybiBmYih0LGksbCl9aWYobz09Mil7dmFyIHU9dFtpXSxmPXUmMyxwPXU+PjImMyxnPXU+PjQsdj0wLEk9MDtpZihmPDIpaWYocCYxKWd8PXRbKytpXTw8NHwocCYyJiZ0WysraV08PDEyKTtlbHNlIGc9dT4+MztlbHNlIGlmKEk9cCxwPDIpZ3w9KHRbKytpXSY2Myk8PDQsdj10W2ldPj42fHRbKytpXTw8MjtlbHNlIGlmKHA9PTIpZ3w9dFsrK2ldPDw0fCh0WysraV0mMyk8PDEyLHY9dFtpXT4+Mnx0WysraV08PDY7ZWxzZSBnfD10WysraV08PDR8KHRbKytpXSY2Myk8PDEyLHY9dFtpXT4+Nnx0WysraV08PDJ8dFsrK2ldPDwxMDsrK2k7dmFyIEQ9cj9yLnN1YmFycmF5KGUueSxlLnkrZS5tKTpuZXcgTWUoZS5tKSxaPUQubGVuZ3RoLWc7aWYoZj09MClELnNldCh0LnN1YmFycmF5KGksaSs9ZyksWik7ZWxzZSBpZihmPT0xKVp1KEQsdFtpKytdLFopO2Vsc2V7dmFyIG10PWUuaDtpZihmPT0yKXt2YXIgcGU9aEwodCxpKTt2Kz1pLShpPXBlWzBdKSxlLmg9bXQ9cGVbMV19ZWxzZSBpZighbXQpa2UoMCk7KEk/Ykw6WHUpKHQuc3ViYXJyYXkoaSxpKz12KSxELnN1YmFycmF5KFopLG10KX12YXIgQmU9dFtpKytdO2lmKEJlKXtpZihCZT09MjU1KUJlPSh0W2krK118dFtpKytdPDw4KSszMjUxMjtlbHNlIGlmKEJlPjEyNylCZT1CZS0xMjg8PDh8dFtpKytdO3ZhciBfaT10W2krK107aWYoX2kmMylrZSgwKTt2YXIgU2U9W21MLHlMLHBMXTtmb3IodmFyIEJ0PTI7QnQ+LTE7LS1CdCl7dmFyIHo9X2k+PihCdDw8MSkrMiYzO2lmKHo9PTEpe3ZhciBNdD1uZXcgTWUoWzAsMCx0W2krK11dKTtTZVtCdF09e3M6TXQuc3ViYXJyYXkoMiwzKSxuOk10LnN1YmFycmF5KDAsMSksdDpuZXcga3AoTXQuYnVmZmVyLDAsMSksYjowfX1lbHNlIGlmKHo9PTIpbj1RdSh0LGksOS0oQnQmMSkpLGk9blswXSxTZVtCdF09blsxXTtlbHNlIGlmKHo9PTMpe2lmKCFlLnQpa2UoMCk7U2VbQnRdPWUudFtCdF19fXZhciBncj1lLnQ9U2UsVXQ9Z3JbMF0sWGU9Z3JbMV0sWXI9Z3JbMl0sc3I9dFtsLTFdO2lmKCFzcilrZSgwKTt2YXIgenQ9KGw8PDMpLTgrdGMoc3IpLVlyLmIsU3Q9enQ+PjMsbGU9MCxmbj0odFtTdF18dFtTdCsxXTw8OCk+Pih6dCY3KSYoMTw8WXIuYiktMTtTdD0oenQtPVhlLmIpPj4zO3ZhciBvcj0odFtTdF18dFtTdCsxXTw8OCk+Pih6dCY3KSYoMTw8WGUuYiktMTtTdD0oenQtPVV0LmIpPj4zO3ZhciBOcj0odFtTdF18dFtTdCsxXTw8OCk+Pih6dCY3KSYoMTw8VXQuYiktMTtmb3IoKytCZTstLUJlOyl7dmFyIHdzPVlyLnNbZm5dLHRmPVlyLm5bZm5dLHJvPVV0LnNbTnJdLHNhPVV0Lm5bTnJdLGRuPVhlLnNbb3JdLGFyPVhlLm5bb3JdO1N0PSh6dC09ZG4pPj4zO3ZhciBWZT0xPDxkbixLcj1WZSsoKHRbU3RdfHRbU3QrMV08PDh8dFtTdCsyXTw8MTZ8dFtTdCszXTw8MjQpPj4+KHp0JjcpJlZlLTEpO1N0PSh6dC09aGJbcm9dKT4+Mzt2YXIgbmM9Z0xbcm9dKygodFtTdF18dFtTdCsxXTw8OHx0W1N0KzJdPDwxNik+Pih6dCY3KSYoMTw8aGJbcm9dKS0xKTtTdD0oenQtPWRiW3dzXSk+PjM7dmFyIGVmPV9MW3dzXSsoKHRbU3RdfHRbU3QrMV08PDh8dFtTdCsyXTw8MTYpPj4oenQmNykmKDE8PGRiW3dzXSktMSk7aWYoU3Q9KHp0LT10Zik+PjMsZm49WXIudFtmbl0rKCh0W1N0XXx0W1N0KzFdPDw4KT4+KHp0JjcpJigxPDx0ZiktMSksU3Q9KHp0LT1zYSk+PjMsTnI9VXQudFtOcl0rKCh0W1N0XXx0W1N0KzFdPDw4KT4+KHp0JjcpJigxPDxzYSktMSksU3Q9KHp0LT1hcik+PjMsb3I9WGUudFtvcl0rKCh0W1N0XXx0W1N0KzFdPDw4KT4+KHp0JjcpJigxPDxhciktMSksS3I+MyllLm9bMl09ZS5vWzFdLGUub1sxXT1lLm9bMF0sZS5vWzBdPUtyLT0zO2Vsc2V7dmFyIHJmPUtyLShlZiE9MCk7aWYocmYpe2lmKEtyPXJmPT0zP2Uub1swXS0xOmUub1tyZl0scmY+MSllLm9bMl09ZS5vWzFdO2Uub1sxXT1lLm9bMF0sZS5vWzBdPUtyfWVsc2UgS3I9ZS5vWzBdfWZvcih2YXIgQnQ9MDtCdDxlZjsrK0J0KURbbGUrQnRdPURbWitCdF07bGUrPWVmLForPWVmO3ZhciB2bD1sZS1LcjtpZih2bDwwKXt2YXIgSWw9LXZsLFZEPWUuZSt2bDtpZihJbD5uYylJbD1uYztmb3IodmFyIEJ0PTA7QnQ8SWw7KytCdClEW2xlK0J0XT1lLndbVkQrQnRdO2xlKz1JbCxuYy09SWwsdmw9MH1mb3IodmFyIEJ0PTA7QnQ8bmM7KytCdClEW2xlK0J0XT1EW3ZsK0J0XTtsZSs9bmN9aWYobGUhPVopd2hpbGUoWjxELmxlbmd0aClEW2xlKytdPURbWisrXTtlbHNlIGxlPUQubGVuZ3RoO2lmKHIpZS55Kz1sZTtlbHNlIEQ9ZmIoRCwwLGxlKX1lbHNlIGlmKHIpe2lmKGUueSs9ZyxaKWZvcih2YXIgQnQ9MDtCdDxnOysrQnQpRFtCdF09RFtaK0J0XX1lbHNlIGlmKFopRD1mYihELFopO3JldHVybiBlLmI9bCxEfWtlKDIpfSx2TD1mdW5jdGlvbih0LGUpe2lmKHQubGVuZ3RoPT0xKXJldHVybiB0WzBdO3ZhciByPW5ldyBNZShlKTtmb3IodmFyIG49MCxpPTA7bjx0Lmxlbmd0aDsrK24pe3ZhciBzPXRbbl07ci5zZXQocyxpKSxpKz1zLmxlbmd0aH1yZXR1cm4gcn07dmFyIHhEPW0oKCk9PnthTD1BcnJheUJ1ZmZlcixNZT1VaW50OEFycmF5LGtwPVVpbnQxNkFycmF5LGNMPUludDE2QXJyYXksVnA9SW50MzJBcnJheSx1TD1bImludmFsaWQgenN0ZCBkYXRhIiwid2luZG93IHNpemUgdG9vIGxhcmdlICg+MjA0Nk1CKSIsImludmFsaWQgYmxvY2sgdHlwZSIsIkZTRSBhY2N1cmFjeSB0b28gaGlnaCIsIm1hdGNoIGRpc3RhbmNlIHRvbyBmYXIgYmFjayIsInVuZXhwZWN0ZWQgRU9GIl0scEw9UXUobmV3IE1lKFs4MSwxNiw5OSwxNDAsNDksMTk4LDI0LDk5LDEyLDMzLDE5NiwyNCw5OSwxMDIsMTAyLDEzNCw3MCwxNDYsNF0pLDAsNilbMV0sbUw9UXUobmV3IE1lKFszMywyMCwxOTYsMjQsOTksMTQwLDMzLDEzMiwxNiw2Niw4LDMzLDEzMiwxNiw2Niw4LDMzLDY4LDY4LDY4LDY4LDY4LDY4LDY4LDY4LDM2LDldKSwwLDYpWzFdLHlMPVF1KG5ldyBNZShbMzIsMTMyLDE2LDY2LDEwMiw3MCw2OCw2OCw2OCw2OCwzNiw3MywyXSksMCw1KVsxXSxkYj1uZXcgTWUobmV3IFZwKFswLDAsMCwwLDE2ODQzMDA5LDUwNTI4NzcwLDEzNDY3ODAyMCwyMDIwNTAwNTcsMjY5NDIyMDkzXSkuYnVmZmVyLDAsMzYpLF9MPUFEKGRiLDApLGhiPW5ldyBNZShuZXcgVnAoWzAsMCwwLDAsMCwwLDAsMCwxNjg0MzAwOSw1MDUyODc3MCwxMTc3NjkyMjAsMTg1MjA3MDQ4LDI1MjU3OTA4NCwxNl0pLmJ1ZmZlciwwLDUzKSxnTD1BRChoYiwzKX0pO2Z1bmN0aW9uIEVEKCl7bGV0IHQ9aW1wb3J0Lm1ldGEucmVxdWlyZT8/Z2xvYmFsVGhpcy5yZXF1aXJlPz9udWxsO2lmKCF0KXJldHVybiBudWxsO3RyeXtyZXR1cm4gdChJTCl9Y2F0Y2h7cmV0dXJuIG51bGx9fWFzeW5jIGZ1bmN0aW9uIE9EKHQsZSl7aWYoVEQpcmV0dXJuIG5ldyBVaW50OEFycmF5KEJ1bi56c3RkQ29tcHJlc3NTeW5jKHQse2xldmVsOmV9KSk7bGV0IHI9RUQoKSxuPXI/LnpzdGRDb21wcmVzc1N5bmM7aWYodHlwZW9mIG4hPT0iZnVuY3Rpb24iKXRocm93IEVycm9yKCJ6c3RkIGNvbXByZXNzaW9uIGlzIG5vdCBhdmFpbGFibGUgaW4gdGhpcyBydW50aW1lLiBSZXF1aXJlcyBCdW4gb3IgTm9kZS5qcyA+PSAyMi4xNSAvIERlbm8gPj0gMi42LjkuICh3b3JrZXJkIGhhcyBubyBuYXRpdmUgenN0ZCBlbmNvZGVyOyBmenN0ZCBpcyBkZWNvbXByZXNzLW9ubHkuKSIpO3JldHVybiBuZXcgVWludDhBcnJheShuKHQse3BhcmFtczp7W3IuY29uc3RhbnRzLlpTVERfY19jb21wcmVzc2lvbkxldmVsXTplfX0pKX1hc3luYyBmdW5jdGlvbiBwYih0LGUpe2lmKGUhPW51bGwpe2xldCBuPUJMKHQpO2lmKG4hPT1udWxsJiZuPmUpdGhyb3cgRXJyb3IoYHpzdGQgZGVjb21wcmVzc2VkIHNpemUgKCR7bn0pIHdvdWxkIGV4Y2VlZCBjYXAgKCR7ZX0pYCl9bGV0IHI7aWYoVEQpcj1uZXcgVWludDhBcnJheShCdW4uenN0ZERlY29tcHJlc3NTeW5jKHQpKTtlbHNle2xldCBpPUVEKCk/LnpzdGREZWNvbXByZXNzU3luYztpZih0eXBlb2YgaT09PSJmdW5jdGlvbiIpcj1uZXcgVWludDhBcnJheShpKHQpKTtlbHNle2xldCBzPUREKHQpO3I9bmV3IFVpbnQ4QXJyYXkocy5ieXRlTGVuZ3RoKSxyLnNldChzKX19aWYoZSE9bnVsbCYmci5ieXRlTGVuZ3RoPmUpdGhyb3cgRXJyb3IoYHpzdGQgZGVjb21wcmVzc2VkIHNpemUgKCR7ci5ieXRlTGVuZ3RofSkgZXhjZWVkcyBjYXAgKCR7ZX0pYCk7cmV0dXJuIHJ9ZnVuY3Rpb24gQkwodCl7aWYodC5sZW5ndGg8NilyZXR1cm4gbnVsbDtpZih0WzBdIT09NDB8fHRbMV0hPT0xODF8fHRbMl0hPT00N3x8dFszXSE9PTI1MylyZXR1cm4gbnVsbDtsZXQgZT10WzRdLHI9ZT4+NiYzLG49KGU+PjUmMSk9PT0xLGk9ZSYzLHM9cj09PTA/bj8xOjA6cj09PTE/MjpyPT09Mj80Ojg7aWYocz09PTApcmV0dXJuIG51bGw7bGV0IG89bj8wOjEsYT1pPT09MD8wOmk9PT0xPzE6aT09PTI/Mjo0LGw9NStvK2E7aWYodC5sZW5ndGg8bCtzKXJldHVybiBudWxsO2xldCB1PTBuO2ZvcihsZXQgZj0wO2Y8cztmKyspdXw9QmlnSW50KHRbbCtmXSk8PEJpZ0ludChmKjgpO2lmKHM9PT0yKXUrPTI1Nm47aWYodT5CaWdJbnQoTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIpKXJldHVybiBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUjtyZXR1cm4gTnVtYmVyKHUpfXZhciBJTD0ibm9kZTp6bGliIixURDt2YXIgbWI9bSgoKT0+e3hEKCk7VEQ9dHlwZW9mIGdsb2JhbFRoaXMuQnVuPCJ1In0pO01zKCk7TXMoKTtNcygpO01zKCk7TXMoKTtNcygpO01zKCk7TXMoKTtxeSgpO3ZhciBDRT1PYmplY3QuZGVmaW5lUHJvcGVydHksUEU9KHQpPT50O2Z1bmN0aW9uIGtFKHQsZSl7dGhpc1t0XT1QRS5iaW5kKG51bGwsZSl9dmFyIFZFPSh0LGUpPT57Zm9yKHZhciByIGluIGUpQ0UodCxyLHtnZXQ6ZVtyXSxlbnVtZXJhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMCxzZXQ6a0UuYmluZChlLHIpfSl9LEd0PXtOdWxsOjEsSW50OjIsRmxvYXQ6MyxCaW5hcnk6NCxVdGY4OjUsQm9vbDo2LERlY2ltYWw6NyxEYXRlOjgsVGltZTo5LFRpbWVzdGFtcDoxMCxJbnRlcnZhbDoxMSxMaXN0OjEyLFN0cnVjdDoxMyxVbmlvbjoxNCxGaXhlZFNpemVCaW5hcnk6MTUsRml4ZWRTaXplTGlzdDoxNixNYXA6MTcsRHVyYXRpb246MTgsTGFyZ2VCaW5hcnk6MTksTGFyZ2VVdGY4OjIwLERpY3Rpb25hcnk6LTF9O2Z1bmN0aW9uIFl5KHQpe3JldHVybiB0LnR5cGVJZD09PUd0LkludH1mdW5jdGlvbiB6RSh0KXtyZXR1cm4gdC50eXBlSWQ9PT1HdC5CaW5hcnl8fHQudHlwZUlkPT09R3QuTGFyZ2VCaW5hcnl9ZnVuY3Rpb24gakUodCl7cmV0dXJuIHQudHlwZUlkPT09R3QuQm9vbH1mdW5jdGlvbiAkRSh0KXtyZXR1cm4gdC50eXBlSWQ9PT1HdC5MaXN0fWZ1bmN0aW9uIHFFKHQpe3JldHVybiB0LnR5cGVJZD09PUd0LlN0cnVjdH1mdW5jdGlvbiBXRSh0KXtyZXR1cm4gdC50eXBlSWQ9PT1HdC5NYXB9ZnVuY3Rpb24gSEUodCl7cmV0dXJuIHQudHlwZUlkPT09R3QuRGljdGlvbmFyeX12YXIgcEk9e307VkUocEkse0RhdGVVbml0OigpPT5ZRSxJbnRlcnZhbFVuaXQ6KCk9PktFLFRpbWVVbml0OigpPT5hdSxVbmlvbk1vZGU6KCk9PkdFLGFkb3B0QXJyb3dKc1NoYXBlOigpPT5tTixiYWNrZW5kOigpPT5wTixiYXRjaEZyb21Db2x1bW5zOigpPT5VbyxiYXRjaEZyb21Sb3dzOigpPT5GbyxiYXRjaFRvU2NhbGFyRGljdDooKT0+RkksYmF0Y2hUb1NlY3JldERpY3Q6KCk9Pm9OLGJpbmFyeTooKT0+QkksYm9vbDooKT0+eUksYnVpbGRTdGF0aXN0aWNzQmF0Y2g6KCk9PmhOLGNvbHVtbkZyb21BcnJheTooKT0+aU4sZGF0ZTooKT0+WnksZGF0ZURheTooKT0+aU8sZGF0ZU1pbGxpc2Vjb25kOigpPT5zTyxkZWNpbWFsOigpPT5YeSxkZWNpbWFsMTI4OigpPT5yTyxkZWNpbWFsMjU2OigpPT5uTyxkZWNvZGVEaWN0VmFsdWU6KCk9PnNOLGRlbnNlVW5pb246KCk9PnBPLGRlc2VyaWFsaXplQmF0Y2g6KCk9PkNjLGRlc2VyaWFsaXplU2NoZW1hOigpPT5ZZCxkaWN0aW9uYXJ5OigpPT5USSxkdXJhdGlvbjooKT0+dU8sZW1wdHlCYXRjaDooKT0+SGQsZmllbGQ6KCk9PkxvLGZpbHRlckJhdGNoOigpPT5sTixmaXhlZFNpemVCaW5hcnk6KCk9PmVPLGZpeGVkU2l6ZUxpc3Q6KCk9PmRPLGZsb2F0MTY6KCk9PlpFLGZsb2F0MzI6KCk9PlFFLGZsb2F0NjQ6KCk9PnZJLGludDooKT0+WEUsaW50MTY6KCk9PldkLGludDMyOigpPT5LeSxpbnQ2NDooKT0+R3ksaW50ODooKT0+X0ksaW50ZXJ2YWw6KCk9PmZPLGl0ZXJSb3dzOigpPT5raSxsYXJnZUJpbmFyeTooKT0+U0ksbGFyZ2VVdGY4OigpPT50TyxsaXN0OigpPT5ESSxtYXA6KCk9PnhJLG51bGxUeXBlOigpPT5tSSxwcm9qZWN0QmF0Y2g6KCk9PnVOLHByb2plY3RTY2hlbWE6KCk9PlVJLHJlYWRDYW5vbmljYWxWYWx1ZTooKT0+amksc2FmZU51bWJlcjooKT0+Y04sc2NoZW1hOigpPT5KRSxzZXJpYWxpemVCYXRjaDooKT0+dXMsc2VyaWFsaXplU2NoZW1hOigpPT4kZCxzcGFyc2VVbmlvbjooKT0+aE8sc3RydWN0OigpPT5ReSx0aW1lOigpPT5mdSx0aW1lTWljcm9zZWNvbmQ6KCk9PmNPLHRpbWVNaWxsaXNlY29uZDooKT0+YU8sdGltZU5hbm9zZWNvbmQ6KCk9PmxPLHRpbWVTZWNvbmQ6KCk9Pm9PLHRpbWVzdGFtcDooKT0+QUksdWludDE2OigpPT5iSSx1aW50MzI6KCk9PndJLHVpbnQ2NDooKT0+SnksdWludDg6KCk9PmdJLHVuaW9uOigpPT50Xyx1dGY4OigpPT5JSSx3aXRoQmF0Y2hNZXRhZGF0YTooKT0+Zk59KTt2YXIgYXU9e1NFQ09ORDpULlNFQ09ORCxNSUxMSVNFQ09ORDpULk1JTExJU0VDT05ELE1JQ1JPU0VDT05EOlQuTUlDUk9TRUNPTkQsTkFOT1NFQ09ORDpULk5BTk9TRUNPTkR9LFlFPXtEQVk6cXQuREFZLE1JTExJU0VDT05EOnF0Lk1JTExJU0VDT05EfSxLRT17WUVBUl9NT05USDpqdC5ZRUFSX01PTlRILERBWV9USU1FOmp0LkRBWV9USU1FLE1PTlRIX0RBWV9OQU5POmp0Lk1PTlRIX0RBWV9OQU5PfSxHRT17U3BhcnNlOkx0LlNwYXJzZSxEZW5zZTpMdC5EZW5zZX07ZnVuY3Rpb24gSkUodCxlKXtyZXR1cm4gbmV3IGx0KHQsZT8/bmV3IE1hcCl9ZnVuY3Rpb24gTG8odCxlLHI9ITAsbil7cmV0dXJuIG5ldyBVKHQsZSxyLG4/P25ldyBNYXApfXZhciBtST0oKT0+bmV3IHdlLHlJPSgpPT5uZXcgVWUsX0k9KCk9Pm5ldyBtbyxXZD0oKT0+bmV3IHlvLEt5PSgpPT5uZXcgQnIsR3k9KCk9Pm5ldyBJbixnST0oKT0+bmV3IF9vLGJJPSgpPT5uZXcgZ28sd0k9KCk9Pm5ldyBibyxKeT0oKT0+bmV3IExpO2Z1bmN0aW9uIFhFKHQ9MzIsZT0hMCl7aWYoZSlzd2l0Y2godCl7Y2FzZSA4OnJldHVybiBfSSgpO2Nhc2UgMTY6cmV0dXJuIFdkKCk7Y2FzZSAzMjpyZXR1cm4gS3koKTtjYXNlIDY0OnJldHVybiBHeSgpfWVsc2Ugc3dpdGNoKHQpe2Nhc2UgODpyZXR1cm4gZ0koKTtjYXNlIDE2OnJldHVybiBiSSgpO2Nhc2UgMzI6cmV0dXJuIHdJKCk7Y2FzZSA2NDpyZXR1cm4gSnkoKX10aHJvdyBFcnJvcihgaW50OiB1bnN1cHBvcnRlZCBiaXRXaWR0aCAke3R9YCl9dmFyIFpFPSgpPT5uZXcgZmMsUUU9KCk9Pm5ldyB3byx2ST0oKT0+bmV3IG9zLElJPSgpPT5uZXcgSXIsdE89KCk9Pm5ldyB4aSxCST0oKT0+bmV3IEFpLFNJPSgpPT5uZXcgRGksZU89KHQpPT5uZXcgTWkodCk7ZnVuY3Rpb24gWHkodCxlLHI9MTI4KXtyZXR1cm4gbmV3IFRpKGUsdCxyKX12YXIgck89KHQsZSk9Plh5KHQsZSwxMjgpLG5PPSh0LGUpPT5YeSh0LGUsMjU2KSxaeT0odD1xdC5NSUxMSVNFQ09ORCk9Pm5ldyBFaSh0KSxpTz0oKT0+WnkocXQuREFZKSxzTz0oKT0+WnkocXQuTUlMTElTRUNPTkQpO2Z1bmN0aW9uIGZ1KHQ9VC5NSUxMSVNFQ09ORCxlKXtsZXQgcj1lPz8odDw9VC5NSUxMSVNFQ09ORD8zMjo2NCk7cmV0dXJuIG5ldyBPaSh0LHIpfXZhciBvTz0oKT0+ZnUoVC5TRUNPTkQsMzIpLGFPPSgpPT5mdShULk1JTExJU0VDT05ELDMyKSxjTz0oKT0+ZnUoVC5NSUNST1NFQ09ORCw2NCksbE89KCk9PmZ1KFQuTkFOT1NFQ09ORCw2NCksQUk9KHQ9VC5NSUxMSVNFQ09ORCxlPW51bGwpPT5uZXcgSm4odCxlKSx1Tz0odD1ULk1JTExJU0VDT05EKT0+bmV3IEZpKHQpLGZPPSh0PWp0Lk1PTlRIX0RBWV9OQU5PKT0+bmV3IE5pKHQpO2Z1bmN0aW9uIERJKHQpe2xldCBlPWx1KHQpP3Q6TG8oIml0ZW0iLHQsITApO3JldHVybiBuZXcgTHIoZSl9ZnVuY3Rpb24gZE8odCxlKXtsZXQgcj1sdSh0KT90OkxvKCJpdGVtIix0LCEwKTtyZXR1cm4gbmV3IHduKGUscil9ZnVuY3Rpb24gUXkodCl7cmV0dXJuIG5ldyBFdCh0KX1mdW5jdGlvbiB4SSh0LGUscj0hMSl7bGV0IG49bHUodCk/dDpMbygia2V5Iix0LCExKSxpPWx1KGUpP2U6TG8oInZhbHVlIixlLCEwKSxzPUxvKCJlbnRyaWVzIixReShbbixpXSksITEpO3JldHVybiBuZXcgdm4ocyxyKX1mdW5jdGlvbiBUSSh0LGU9V2QoKSxyPSExLG4pe3JldHVybiBuZXcgZnIodCxlLG4scil9ZnVuY3Rpb24gdF8odCxlLHIpe2xldCBuPWUubWFwKChvLGEpPT5sdShvKT9vOkxvKFN0cmluZyhhKSxvLCEwKSksaT1yPz9uLm1hcCgobyxhKT0+YSk7cmV0dXJuIG5ldyh0PT09THQuRGVuc2U/Umw6dm8pKGksbil9dmFyIGhPPSh0LGUpPT50XyhMdC5TcGFyc2UsdCxlKSxwTz0odCxlKT0+dF8oTHQuRGVuc2UsdCxlKTtmdW5jdGlvbiBsdSh0KXtyZXR1cm4gdHlwZW9mIHQubmFtZT09PSJzdHJpbmciJiZ0LnR5cGUhPW51bGx9ZnVuY3Rpb24gamQodCl7bGV0IGU9dC50eXBlO2lmKEIuaXNMaXN0KGUpKXtsZXQgcj1lLmNoaWxkcmVuWzBdO3JldHVybiBTKHt0eXBlOmUsbGVuZ3RoOjAsbnVsbENvdW50OjAsY2hpbGQ6amQociksdmFsdWVPZmZzZXRzOm5ldyBJbnQzMkFycmF5KFswXSl9KX1pZihCLmlzTWFwKGUpKXtsZXQgcj1lLmNoaWxkcmVuWzBdO3JldHVybiBTKHt0eXBlOmUsbGVuZ3RoOjAsbnVsbENvdW50OjAsY2hpbGQ6amQociksdmFsdWVPZmZzZXRzOm5ldyBJbnQzMkFycmF5KFswXSl9KX1pZihCLmlzU3RydWN0KGUpKXtsZXQgcj1lLmNoaWxkcmVuLm1hcCgobik9PmpkKG4pKTtyZXR1cm4gUyh7dHlwZTplLGxlbmd0aDowLG51bGxDb3VudDowLGNoaWxkcmVuOnJ9KX1yZXR1cm4gUyh7dHlwZTplLGxlbmd0aDowLG51bGxDb3VudDowfSl9ZnVuY3Rpb24gSGQodCl7bGV0IGU9dCxyPWUuZmllbGRzLm1hcCgocyk9PmpkKHMpKSxuPW5ldyBFdChlLmZpZWxkcyksaT1TKHt0eXBlOm4sbGVuZ3RoOjAsY2hpbGRyZW46cixudWxsQ291bnQ6MH0pO3JldHVybiBuZXcgQXQoZSxpKX12YXIgb3U9ODY0MDAwMDA7ZnVuY3Rpb24gV3QodCl7cmV0dXJuIHQ9PT1udWxsfHx0PT09dm9pZCAwfWZ1bmN0aW9uIER0KHQsZSxyKXtsZXQgbjt0cnl7bj10eXBlb2Ygcj09PSJiaWdpbnQiP2Ake3J9bmA6dHlwZW9mIHI9PT0ib2JqZWN0Ij9PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwocik6U3RyaW5nKHIpfWNhdGNoe249Ijx1bnByaW50YWJsZT4ifXRocm93IFR5cGVFcnJvcihgY29kZWNbJHt0fV06ICR7ZX0gKGdvdCAke3R5cGVvZiByfTogJHtufSlgKX1mdW5jdGlvbiBUbih0LGUpe2xldCByPShuKT0+e2lmKFd0KG4pKXJldHVybiBudWxsO3JldHVybiBlKG4pLG59O3JldHVybntsYWJlbDp0LHJpY2hUb0Nhbm9uaWNhbDpyLGNhbm9uaWNhbFRvUmljaDpyLHJhd1RvQ2Fub25pY2FsOnIsY2Fub25pY2FsVG9SYXc6cn19ZnVuY3Rpb24gbU8odCl7cmV0dXJuKGUpPT57aWYodHlwZW9mIGUhPT0iYm9vbGVhbiIpRHQodCwiZXhwZWN0ZWQgYm9vbGVhbiIsZSl9fWZ1bmN0aW9uIFBjKHQsZSxyKXtyZXR1cm4obik9PntsZXQgaTtpZih0eXBlb2Ygbj09PSJudW1iZXIiKWk9bjtlbHNlIGlmKHR5cGVvZiBuPT09ImJpZ2ludCIpe2lmKG48QmlnSW50KGUpfHxuPkJpZ0ludChyKSlEdCh0LGBiaWdpbnQgb3V0IG9mICR7dH0gcmFuZ2VgLG4pO3JldHVybn1lbHNlIHJldHVybiBEdCh0LCJleHBlY3RlZCBudW1iZXIiLG4pO2lmKCFOdW1iZXIuaXNJbnRlZ2VyKGkpKUR0KHQsImV4cGVjdGVkIGFuIGludGVnZXIiLG4pO2lmKGk8ZXx8aT5yKUR0KHQsYHZhbHVlIG91dCBvZiAke3R9IHJhbmdlIFske2V9LCAke3J9XWAsbil9fWZ1bmN0aW9uIHlPKHQpe3JldHVybihlKT0+e2lmKHR5cGVvZiBlPT09Im51bWJlciIpcmV0dXJuO2lmKHR5cGVvZiBlPT09ImJpZ2ludCIpcmV0dXJuO0R0KHQsImV4cGVjdGVkIG51bWJlciIsZSl9fWZ1bmN0aW9uIEVJKHQsZSxyKXtsZXQgbj1yPygxbjw8QmlnSW50KGUtMSkpLTFuOigxbjw8QmlnSW50KGUpKS0xbixpPXI/LSgxbjw8QmlnSW50KGUtMSkpOjBuO3JldHVybihzKT0+e2xldCBvO2lmKHR5cGVvZiBzPT09ImJpZ2ludCIpbz1zO2Vsc2UgaWYodHlwZW9mIHM9PT0ibnVtYmVyIil7aWYoIU51bWJlci5pc0ludGVnZXIocykpRHQodCwiZXhwZWN0ZWQgYW4gaW50ZWdlciIscyk7bz1CaWdJbnQocyl9ZWxzZSByZXR1cm4gRHQodCwiZXhwZWN0ZWQgYmlnaW50IixzKTtpZihvPGl8fG8+bilEdCh0LGB2YWx1ZSBvdXQgb2YgJHt0fSByYW5nZWAscyl9fWZ1bmN0aW9uIG5JKHQpe3JldHVybihlKT0+e2lmKHR5cGVvZiBlIT09InN0cmluZyIpRHQodCwiZXhwZWN0ZWQgc3RyaW5nIixlKX19ZnVuY3Rpb24gY3UodCxlKXtpZih0eXBlb2YgZT09PSJiaWdpbnQiKXJldHVybiBlO2lmKHR5cGVvZiBlPT09Im51bWJlciIpe2lmKCFOdW1iZXIuaXNJbnRlZ2VyKGUpKUR0KHQsImV4cGVjdGVkIGFuIGludGVnZXIgdmFsdWUiLGUpO3JldHVybiBCaWdJbnQoZSl9cmV0dXJuIER0KHQsImV4cGVjdGVkIG51bWJlciBvciBiaWdpbnQiLGUpfWZ1bmN0aW9uIEFhKHQsZSl7aWYoZTwtOTAwNzE5OTI1NDc0MDk5MW58fGU+OTAwNzE5OTI1NDc0MDk5MW4pRHQodCwiYmlnaW50IG92ZXJmbG93cyB0aGUgc2FmZS1pbnRlZ2VyIHJhbmdlIHdoZW4gbmFycm93aW5nIHRvIG51bWJlciIsZSk7cmV0dXJuIE51bWJlcihlKX1mdW5jdGlvbiBfTygpe3JldHVybntsYWJlbDoiZGF0ZTMyIixyaWNoVG9DYW5vbmljYWwoZSl7aWYoV3QoZSkpcmV0dXJuIG51bGw7aWYoZSBpbnN0YW5jZW9mIERhdGUpe2xldCByPWUuZ2V0VGltZSgpO2lmKE51bWJlci5pc05hTihyKSlEdCgiZGF0ZTMyIiwiaW52YWxpZCBEYXRlIixlKTtpZihyJW91IT09MClyZXR1cm4gTWF0aC5mbG9vcihyL291KTtyZXR1cm4gci9vdX1pZih0eXBlb2YgZT09PSJudW1iZXIiKXtpZighTnVtYmVyLmlzSW50ZWdlcihlKSlEdCgiZGF0ZTMyIiwiZGF5LW51bWJlciBtdXN0IGJlIGFuIGludGVnZXIiLGUpO3JldHVybiBlfWlmKHR5cGVvZiBlPT09ImJpZ2ludCIpcmV0dXJuIEFhKCJkYXRlMzIiLGUpO3JldHVybiBEdCgiZGF0ZTMyIiwiZXhwZWN0ZWQgRGF0ZSwgbnVtYmVyIChkYXlzKSwgb3IgYmlnaW50IixlKX0sY2Fub25pY2FsVG9SaWNoKGUpe2lmKFd0KGUpKXJldHVybiBudWxsO2xldCByO2lmKHR5cGVvZiBlPT09Im51bWJlciIpe2lmKCFOdW1iZXIuaXNJbnRlZ2VyKGUpKUR0KCJkYXRlMzIiLCJjYW5vbmljYWwgZGF5LW51bWJlciBtdXN0IGJlIGFuIGludGVnZXIiLGUpO3I9ZX1lbHNlIGlmKHR5cGVvZiBlPT09ImJpZ2ludCIpcj1BYSgiZGF0ZTMyIixlKTtlbHNlIGlmKGUgaW5zdGFuY2VvZiBEYXRlKXJldHVybiBlO2Vsc2UgcmV0dXJuIER0KCJkYXRlMzIiLCJleHBlY3RlZCBudW1iZXIgKGRheXMpIGNhbm9uaWNhbCIsZSk7bGV0IG49cipvdSxpPW5ldyBEYXRlKG4pO2lmKE51bWJlci5pc05hTihpLmdldFRpbWUoKSkpRHQoImRhdGUzMiIsImRheS1udW1iZXIgcHJvZHVjZXMgYW4gaW52YWxpZCBEYXRlIixlKTtyZXR1cm4gaX0scmF3VG9DYW5vbmljYWwoZSl7aWYoV3QoZSkpcmV0dXJuIG51bGw7aWYodHlwZW9mIGU9PT0ibnVtYmVyIil7aWYoIU51bWJlci5pc0ludGVnZXIoZSkpRHQoImRhdGUzMiIsInJhdyBkYXktbnVtYmVyIG11c3QgYmUgYW4gaW50ZWdlciIsZSk7cmV0dXJuIGV9aWYodHlwZW9mIGU9PT0iYmlnaW50IilyZXR1cm4gQWEoImRhdGUzMiIsZSk7cmV0dXJuIER0KCJkYXRlMzIiLCJleHBlY3RlZCBicmFuZGVkIERhdGUzMiAoZGF5LW51bWJlcikiLGUpfSxjYW5vbmljYWxUb1JhdyhlKXtpZihXdChlKSlyZXR1cm4gbnVsbDtpZih0eXBlb2YgZT09PSJudW1iZXIiKXtpZighTnVtYmVyLmlzSW50ZWdlcihlKSlEdCgiZGF0ZTMyIiwiY2Fub25pY2FsIGRheS1udW1iZXIgbXVzdCBiZSBhbiBpbnRlZ2VyIixlKTtyZXR1cm4gZX1pZih0eXBlb2YgZT09PSJiaWdpbnQiKXJldHVybiBBYSgiZGF0ZTMyIixlKTtpZihlIGluc3RhbmNlb2YgRGF0ZSl7bGV0IHI9ZS5nZXRUaW1lKCk7aWYoTnVtYmVyLmlzTmFOKHIpKUR0KCJkYXRlMzIiLCJpbnZhbGlkIERhdGUiLGUpO3JldHVybiBNYXRoLmZsb29yKHIvb3UpfXJldHVybiBEdCgiZGF0ZTMyIiwiZXhwZWN0ZWQgbnVtYmVyIChkYXlzKSBjYW5vbmljYWwiLGUpfX19ZnVuY3Rpb24gZ08oKXtyZXR1cm57bGFiZWw6ImRhdGU2NCIscmljaFRvQ2Fub25pY2FsKGUpe2lmKFd0KGUpKXJldHVybiBudWxsO2lmKGUgaW5zdGFuY2VvZiBEYXRlKXtsZXQgcj1lLmdldFRpbWUoKTtpZihOdW1iZXIuaXNOYU4ocikpRHQoImRhdGU2NCIsImludmFsaWQgRGF0ZSIsZSk7cmV0dXJuIEJpZ0ludChyKX1pZih0eXBlb2YgZT09PSJiaWdpbnQiKXJldHVybiBlO2lmKHR5cGVvZiBlPT09Im51bWJlciIpe2lmKCFOdW1iZXIuaXNJbnRlZ2VyKGUpKUR0KCJkYXRlNjQiLCJtcyB2YWx1ZSBtdXN0IGJlIGFuIGludGVnZXIiLGUpO3JldHVybiBCaWdJbnQoZSl9cmV0dXJuIER0KCJkYXRlNjQiLCJleHBlY3RlZCBEYXRlLCBiaWdpbnQgKG1zKSwgb3IgbnVtYmVyIixlKX0sY2Fub25pY2FsVG9SaWNoKGUpe2lmKFd0KGUpKXJldHVybiBudWxsO2lmKGUgaW5zdGFuY2VvZiBEYXRlKXJldHVybiBlO2xldCByPWN1KCJkYXRlNjQiLGUpLG49QWEoImRhdGU2NCIsciksaT1uZXcgRGF0ZShuKTtpZihOdW1iZXIuaXNOYU4oaS5nZXRUaW1lKCkpKUR0KCJkYXRlNjQiLCJtcyB2YWx1ZSBwcm9kdWNlcyBhbiBpbnZhbGlkIERhdGUiLGUpO3JldHVybiBpfSxyYXdUb0Nhbm9uaWNhbChlKXtpZihXdChlKSlyZXR1cm4gbnVsbDtpZihlIGluc3RhbmNlb2YgRGF0ZSlyZXR1cm4gRHQoImRhdGU2NCIsInJhdyBEYXRlNjRNcyBtdXN0IGJlIGEgYmlnaW50IChtcyksIG5vdCBhIERhdGUiLGUpO3JldHVybiBjdSgiZGF0ZTY0IixlKX0sY2Fub25pY2FsVG9SYXcoZSl7aWYoV3QoZSkpcmV0dXJuIG51bGw7aWYoZSBpbnN0YW5jZW9mIERhdGUpcmV0dXJuIEJpZ0ludChlLmdldFRpbWUoKSk7cmV0dXJuIGN1KCJkYXRlNjQiLGUpfX19ZnVuY3Rpb24gYk8oKXtsZXQgZT0obik9PntpZihXdChuKSlyZXR1cm4gbnVsbDtpZih0eXBlb2Ygbj09PSJudW1iZXIiKXtpZighTnVtYmVyLmlzSW50ZWdlcihuKSlEdCgidGltZTMyIiwidGltZTMyIHZhbHVlIG11c3QgYmUgYW4gaW50ZWdlciIsbik7cmV0dXJuIG59aWYodHlwZW9mIG49PT0iYmlnaW50IilyZXR1cm4gQWEoInRpbWUzMiIsbik7cmV0dXJuIER0KCJ0aW1lMzIiLCJleHBlY3RlZCBudW1iZXIgKHJhdyB0aW1lIHVuaXQpIixuKX0scj0obik9PntpZihXdChuKSlyZXR1cm4gbnVsbDtpZih0eXBlb2Ygbj09PSJudW1iZXIiKXJldHVybiBuO2lmKHR5cGVvZiBuPT09ImJpZ2ludCIpcmV0dXJuIEFhKCJ0aW1lMzIiLG4pO3JldHVybiBEdCgidGltZTMyIiwiZXhwZWN0ZWQgbnVtYmVyIGNhbm9uaWNhbCIsbil9O3JldHVybntsYWJlbDoidGltZTMyIixyaWNoVG9DYW5vbmljYWw6ZSxjYW5vbmljYWxUb1JpY2g6cixyYXdUb0Nhbm9uaWNhbDplLGNhbm9uaWNhbFRvUmF3OnJ9fWZ1bmN0aW9uIFd5KHQpe2xldCBlPShyKT0+e2lmKFd0KHIpKXJldHVybiBudWxsO3JldHVybiBjdSh0LHIpfTtyZXR1cm57bGFiZWw6dCxyaWNoVG9DYW5vbmljYWw6ZSxjYW5vbmljYWxUb1JpY2g6ZSxyYXdUb0Nhbm9uaWNhbDplLGNhbm9uaWNhbFRvUmF3OmV9fWZ1bmN0aW9uIHdPKHQpe2xldCBlPW5ldyBVaW50OEFycmF5KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCx0LmJ5dGVMZW5ndGgpLHI9MG47Zm9yKGxldCBuPWUubGVuZ3RoLTE7bj49MDtuLS0pcj1yPDw4bnxCaWdJbnQoZVtuXSk7aWYoZS5sZW5ndGg+MCYmZVtlLmxlbmd0aC0xXSYxMjgpci09MW48PEJpZ0ludChlLmxlbmd0aCo4KTtyZXR1cm4gcn1mdW5jdGlvbiB2Tygpe2xldCBlPShuKT0+e2lmKFd0KG4pKXJldHVybiBudWxsO2lmKHR5cGVvZiBuPT09ImJpZ2ludCIpcmV0dXJuIG47aWYodHlwZW9mIG49PT0ibnVtYmVyIilyZXR1cm4gY3UoImRlY2ltYWwiLG4pO2lmKEFycmF5QnVmZmVyLmlzVmlldyhuKSlyZXR1cm4gd08obik7cmV0dXJuIER0KCJkZWNpbWFsIiwiZXhwZWN0ZWQgYmlnaW50LCBudW1iZXIsIG9yIGRlY2ltYWwgYnl0ZSB2aWV3IixuKX0scj0obik9PntpZihXdChuKSlyZXR1cm4gbnVsbDtyZXR1cm4gZShuKX07cmV0dXJue2xhYmVsOiJkZWNpbWFsIixyaWNoVG9DYW5vbmljYWw6ZSxjYW5vbmljYWxUb1JpY2g6cixyYXdUb0Nhbm9uaWNhbDplLGNhbm9uaWNhbFRvUmF3OnJ9fWZ1bmN0aW9uIElPKHQpe2xldCByPXQuY2hpbGRyZW4ubWFwKChpKT0+KHtuYW1lOmkubmFtZSxjb2RlYzp6aShpLnR5cGUpfSkpLG49InN0cnVjdCI7cmV0dXJue2xhYmVsOiJzdHJ1Y3QiLHJpY2hUb0Nhbm9uaWNhbChpKXtpZihXdChpKSlyZXR1cm4gbnVsbDtpZih0eXBlb2YgaSE9PSJvYmplY3QiKUR0KCJzdHJ1Y3QiLCJleHBlY3RlZCBhbiBvYmplY3QiLGkpO2xldCBzPWksbz17fTtmb3IobGV0e25hbWU6YSxjb2RlYzpsfW9mIHIpb1thXT1sLnJpY2hUb0Nhbm9uaWNhbChzW2FdPz9udWxsKTtyZXR1cm4gb30sY2Fub25pY2FsVG9SaWNoKGkpe2lmKFd0KGkpKXJldHVybiBudWxsO2lmKHR5cGVvZiBpIT09Im9iamVjdCIpRHQoInN0cnVjdCIsImV4cGVjdGVkIGFuIG9iamVjdCIsaSk7bGV0IHM9aSxvPXt9O2ZvcihsZXR7bmFtZTphLGNvZGVjOmx9b2YgcilvW2FdPWwuY2Fub25pY2FsVG9SaWNoKHNbYV0/P251bGwpO3JldHVybiBvfSxyYXdUb0Nhbm9uaWNhbChpKXtpZihXdChpKSlyZXR1cm4gbnVsbDtpZih0eXBlb2YgaSE9PSJvYmplY3QiKUR0KCJzdHJ1Y3QiLCJleHBlY3RlZCBhbiBvYmplY3QiLGkpO2xldCBzPWksbz17fTtmb3IobGV0e25hbWU6YSxjb2RlYzpsfW9mIHIpb1thXT1sLnJhd1RvQ2Fub25pY2FsKHNbYV0/P251bGwpO3JldHVybiBvfSxjYW5vbmljYWxUb1JhdyhpKXtpZihXdChpKSlyZXR1cm4gbnVsbDtpZih0eXBlb2YgaSE9PSJvYmplY3QiKUR0KCJzdHJ1Y3QiLCJleHBlY3RlZCBhbiBvYmplY3QiLGkpO2xldCBzPWksbz17fTtmb3IobGV0e25hbWU6YSxjb2RlYzpsfW9mIHIpb1thXT1sLmNhbm9uaWNhbFRvUmF3KHNbYV0/P251bGwpO3JldHVybiBvfX19ZnVuY3Rpb24gQk8odCl7bGV0IGU9dC5jaGlsZHJlbj8uWzBdO2lmKCFlKXRocm93IEVycm9yKCJjb2RlY1tsaXN0XTogbGlzdCB0eXBlIGhhcyBubyBjaGlsZCBmaWVsZCIpO2xldCByPXppKGUudHlwZSksbj0ibGlzdCIsaT0ocyk9PntpZihBcnJheS5pc0FycmF5KHMpKXJldHVybiBzO2lmKHMhPW51bGwmJnR5cGVvZiBzW1N5bWJvbC5pdGVyYXRvcl09PT0iZnVuY3Rpb24iKXJldHVybiBBcnJheS5mcm9tKHMpO3JldHVybiBEdChuLCJleHBlY3RlZCBhbiBhcnJheSBvciBpdGVyYWJsZSIscyl9O3JldHVybntsYWJlbDpuLHJpY2hUb0Nhbm9uaWNhbChzKXtpZihXdChzKSlyZXR1cm4gbnVsbDtyZXR1cm4gaShzKS5tYXAoKG8pPT5yLnJpY2hUb0Nhbm9uaWNhbChvKSl9LGNhbm9uaWNhbFRvUmljaChzKXtpZihXdChzKSlyZXR1cm4gbnVsbDtyZXR1cm4gaShzKS5tYXAoKG8pPT5yLmNhbm9uaWNhbFRvUmljaChvKSl9LHJhd1RvQ2Fub25pY2FsKHMpe2lmKFd0KHMpKXJldHVybiBudWxsO3JldHVybiBpKHMpLm1hcCgobyk9PnIucmF3VG9DYW5vbmljYWwobykpfSxjYW5vbmljYWxUb1JhdyhzKXtpZihXdChzKSlyZXR1cm4gbnVsbDtyZXR1cm4gaShzKS5tYXAoKG8pPT5yLmNhbm9uaWNhbFRvUmF3KG8pKX19fWZ1bmN0aW9uIFNPKHQpe2xldCByPXQuY2hpbGRyZW4/LlswXT8udHlwZT8uY2hpbGRyZW47aWYoIXJ8fHIubGVuZ3RoPDIpdGhyb3cgRXJyb3IoImNvZGVjW21hcF06IG1hcCB0eXBlIGhhcyBubyBrZXkvdmFsdWUgZW50cnkgZmllbGRzIik7bGV0IG49emkoclswXS50eXBlKSxpPXppKHJbMV0udHlwZSkscz0ibWFwIixvPShhKT0+e2lmKEFycmF5LmlzQXJyYXkoYSkpcmV0dXJuIGE7aWYoYSBpbnN0YW5jZW9mIE1hcClyZXR1cm4gQXJyYXkuZnJvbShhLmVudHJpZXMoKSk7aWYoYSE9bnVsbCYmdHlwZW9mIGFbU3ltYm9sLml0ZXJhdG9yXT09PSJmdW5jdGlvbiIpcmV0dXJuIEFycmF5LmZyb20oYSk7aWYoYSE9bnVsbCYmdHlwZW9mIGE9PT0ib2JqZWN0IilyZXR1cm4gT2JqZWN0LmVudHJpZXMoYSk7cmV0dXJuIER0KHMsImV4cGVjdGVkIE1hcCwgYXJyYXkgb2YgcGFpcnMsIG9yIG9iamVjdCIsYSl9O3JldHVybntsYWJlbDpzLHJpY2hUb0Nhbm9uaWNhbChhKXtpZihXdChhKSlyZXR1cm4gbnVsbDtyZXR1cm4gbyhhKS5tYXAoKFtsLHVdKT0+W24ucmljaFRvQ2Fub25pY2FsKGwpLGkucmljaFRvQ2Fub25pY2FsKHUpXSl9LGNhbm9uaWNhbFRvUmljaChhKXtpZihXdChhKSlyZXR1cm4gbnVsbDtyZXR1cm4gbyhhKS5tYXAoKFtsLHVdKT0+W24uY2Fub25pY2FsVG9SaWNoKGwpLGkuY2Fub25pY2FsVG9SaWNoKHUpXSl9LHJhd1RvQ2Fub25pY2FsKGEpe2lmKFd0KGEpKXJldHVybiBudWxsO3JldHVybiBvKGEpLm1hcCgoW2wsdV0pPT5bbi5yYXdUb0Nhbm9uaWNhbChsKSxpLnJhd1RvQ2Fub25pY2FsKHUpXSl9LGNhbm9uaWNhbFRvUmF3KGEpe2lmKFd0KGEpKXJldHVybiBudWxsO3JldHVybiBvKGEpLm1hcCgoW2wsdV0pPT5bbi5jYW5vbmljYWxUb1JhdyhsKSxpLmNhbm9uaWNhbFRvUmF3KHUpXSl9fX1mdW5jdGlvbiBBTyh0KXtsZXQgZT10LmRpY3Rpb25hcnk7aWYoIWUpdGhyb3cgRXJyb3IoImNvZGVjW2RpY3Rpb25hcnldOiBtaXNzaW5nIGRpY3Rpb25hcnkgdmFsdWUgdHlwZSIpO2xldCByPXppKGUpO3JldHVybntsYWJlbDpgZGljdGlvbmFyeTwke3IubGFiZWx9PmAscmljaFRvQ2Fub25pY2FsOihuKT0+ci5yaWNoVG9DYW5vbmljYWwobiksY2Fub25pY2FsVG9SaWNoOihuKT0+ci5jYW5vbmljYWxUb1JpY2gobikscmF3VG9DYW5vbmljYWw6KG4pPT5yLnJhd1RvQ2Fub25pY2FsKG4pLGNhbm9uaWNhbFRvUmF3OihuKT0+ci5jYW5vbmljYWxUb1JhdyhuKX19dmFyIERPPVRuKCJpbnQ4IixQYygiaW50OCIsLTEyOCwxMjcpKSx4Tz1UbigiaW50MTYiLFBjKCJpbnQxNiIsLTMyNzY4LDMyNzY3KSksVE89VG4oImludDMyIixQYygiaW50MzIiLC0yMTQ3NDgzNjQ4LDIxNDc0ODM2NDcpKSxFTz1UbigidWludDgiLFBjKCJ1aW50OCIsMCwyNTUpKSxPTz1UbigidWludDE2IixQYygidWludDE2IiwwLDY1NTM1KSksTk89VG4oInVpbnQzMiIsUGMoInVpbnQzMiIsMCw0Mjk0OTY3Mjk1KSksRk89VG4oImludDY0IixFSSgiaW50NjQiLDY0LCEwKSksTU89VG4oInVpbnQ2NCIsRUkoInVpbnQ2NCIsNjQsITEpKSxMTz1UbigiZmxvYXQiLHlPKCJmbG9hdCIpKSxVTz1UbigiYm9vbCIsbU8oImJvb2wiKSksUk89e2xhYmVsOiJ1dGY4IixyaWNoVG9DYW5vbmljYWwodCl7aWYoV3QodCkpcmV0dXJuIG51bGw7cmV0dXJuIHR5cGVvZiB0PT09InN0cmluZyI/dDpTdHJpbmcodCl9LGNhbm9uaWNhbFRvUmljaCh0KXtpZihXdCh0KSlyZXR1cm4gbnVsbDtyZXR1cm4gbkkoInV0ZjgiKSh0KSx0fSxyYXdUb0Nhbm9uaWNhbCh0KXtpZihXdCh0KSlyZXR1cm4gbnVsbDtyZXR1cm4gdHlwZW9mIHQ9PT0ic3RyaW5nIj90OlN0cmluZyh0KX0sY2Fub25pY2FsVG9SYXcodCl7aWYoV3QodCkpcmV0dXJuIG51bGw7cmV0dXJuIG5JKCJ1dGY4IikodCksdH19O2Z1bmN0aW9uIENPKHQsZSl7cmV0dXJuKHIpPT57aWYoV3QocikpcmV0dXJuIG51bGw7bGV0IG47aWYociBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpbj1yO2Vsc2UgaWYoQXJyYXlCdWZmZXIuaXNWaWV3KHIpKXtsZXQgaT1yO249bmV3IFVpbnQ4QXJyYXkoaS5idWZmZXIsaS5ieXRlT2Zmc2V0LGkuYnl0ZUxlbmd0aCl9ZWxzZSByZXR1cm4gRHQodCwiZXhwZWN0ZWQgVWludDhBcnJheSIscik7aWYoZSE9bnVsbCYmbi5sZW5ndGghPT1lKUR0KHQsYGV4cGVjdGVkIGV4YWN0bHkgJHtlfSBieXRlc2Ascik7cmV0dXJuIG59fWZ1bmN0aW9uIE9JKHQsZSl7bGV0IHI9Q08odCxlKTtyZXR1cm57bGFiZWw6dCxyaWNoVG9DYW5vbmljYWw6cixjYW5vbmljYWxUb1JpY2g6cixyYXdUb0Nhbm9uaWNhbDpyLGNhbm9uaWNhbFRvUmF3OnJ9fXZhciBQTz1PSSgiYmluYXJ5Iiksa089e2xhYmVsOiJudWxsIixyaWNoVG9DYW5vbmljYWw6KCk9Pm51bGwsY2Fub25pY2FsVG9SaWNoOigpPT5udWxsLHJhd1RvQ2Fub25pY2FsOigpPT5udWxsLGNhbm9uaWNhbFRvUmF3OigpPT5udWxsfTtmdW5jdGlvbiB6aSh0KXtzd2l0Y2godC50eXBlSWQpe2Nhc2UgR3QuTnVsbDpyZXR1cm4ga087Y2FzZSBHdC5Cb29sOnJldHVybiBVTztjYXNlIEd0LkludDp7bGV0IGU9dC5iaXRXaWR0aD8/MzIscj10LmlzU2lnbmVkPz90LnNpZ25lZD8/ITA7aWYoZT09PTY0KXJldHVybiByP0ZPOk1PO2lmKHIpe2lmKGU9PT04KXJldHVybiBETztpZihlPT09MTYpcmV0dXJuIHhPO3JldHVybiBUT31pZihlPT09OClyZXR1cm4gRU87aWYoZT09PTE2KXJldHVybiBPTztyZXR1cm4gTk99Y2FzZSBHdC5GbG9hdDpyZXR1cm4gTE87Y2FzZSBHdC5VdGY4OmNhc2UgR3QuTGFyZ2VVdGY4OnJldHVybiBSTztjYXNlIEd0LkJpbmFyeTpjYXNlIEd0LkxhcmdlQmluYXJ5OnJldHVybiBQTztjYXNlIEd0LkZpeGVkU2l6ZUJpbmFyeTpyZXR1cm4gT0koImZpeGVkU2l6ZUJpbmFyeSIsdC5ieXRlV2lkdGg/P3Quc3RyaWRlKTtjYXNlIEd0LkRlY2ltYWw6cmV0dXJuIHZPKCk7Y2FzZSBHdC5EYXRlOnJldHVybiB0LnVuaXQ9PT0wP19PKCk6Z08oKTtjYXNlIEd0LlRpbWU6cmV0dXJuKHQuYml0V2lkdGg/PzMyKT09PTY0P1d5KCJ0aW1lNjQiKTpiTygpO2Nhc2UgR3QuVGltZXN0YW1wOnJldHVybiBXeSgidGltZXN0YW1wIik7Y2FzZSBHdC5EdXJhdGlvbjpyZXR1cm4gV3koImR1cmF0aW9uIik7Y2FzZSBHdC5TdHJ1Y3Q6cmV0dXJuIElPKHQpO2Nhc2UgR3QuVW5pb246cmV0dXJuIFRuKCJ1bmlvbiIsKCk9Pnt9KTtjYXNlIEd0Lkxpc3Q6Y2FzZSBHdC5GaXhlZFNpemVMaXN0OnJldHVybiBCTyh0KTtjYXNlIEd0Lk1hcDpyZXR1cm4gU08odCk7Y2FzZSBHdC5EaWN0aW9uYXJ5OnJldHVybiBBTyh0KTtjYXNlIEd0LkludGVydmFsOnJldHVybiBUbigiaW50ZXJ2YWwiLCgpPT57fSk7ZGVmYXVsdDpyZXR1cm4gVG4oYHR5cGUjJHt0LnR5cGVJZH1gLCgpPT57fSl9fWZ1bmN0aW9uIE5JKHQsZSl7cmV0dXJuIHV1KGUsdCl9ZnVuY3Rpb24gdXUodCxlKXtpZihCLmlzTGlzdChlKSlyZXR1cm4gV08odCxlKTtpZihCLmlzTWFwKGUpKXJldHVybiBITyh0LGUpO2lmKEIuaXNTdHJ1Y3QoZSkpcmV0dXJuIFlPKHQsZSk7aWYoQi5pc0RlY2ltYWwoZSkpcmV0dXJuIGpPKHQsZSk7aWYoQi5pc0RhdGUoZSl8fEIuaXNUaW1lKGUpfHxCLmlzVGltZXN0YW1wKGUpfHxCLmlzRHVyYXRpb24oZSkpe2lmKFZPKGUpPT09NjQpcmV0dXJuIGlJKHQsZSk7cmV0dXJuIHpPKHQsZSl9aWYoQi5pc0ludChlKSYmZS5iaXRXaWR0aD09PTY0KXJldHVybiBpSSh0LGUpO3JldHVybiBPYyh0LGUpLmRhdGFbMF19ZnVuY3Rpb24gVk8odCl7aWYoQi5pc0RhdGUodCkpcmV0dXJuIHQudW5pdD09PXF0LkRBWT8zMjo2NDtpZihCLmlzVGltZSh0KSlyZXR1cm4gdC5iaXRXaWR0aD8/MzI7cmV0dXJuIDY0fWZ1bmN0aW9uIHpPKHQsZSl7bGV0IHI9dC5sZW5ndGgsbj1uZXcgSW50MzJBcnJheShyKSxpPW5ldyBVaW50OEFycmF5KE1hdGguY2VpbChyLzgpKSxzPTA7Zm9yKGxldCBvPTA7bzxyO28rKyl7bGV0IGE9dFtvXTtpZihhPT09bnVsbHx8YT09PXZvaWQgMCl7cysrO2NvbnRpbnVlfWlbbz4+M118PTE8PChvJjcpLG5bb109dHlwZW9mIGE9PT0iYmlnaW50Ij9OdW1iZXIoYSk6YX1yZXR1cm4gUyh7dHlwZTplLGxlbmd0aDpyLG51bGxCaXRtYXA6cz4wP2k6dm9pZCAwLGRhdGE6bixudWxsQ291bnQ6c30pfWZ1bmN0aW9uIGlJKHQsZSl7bGV0IHI9dC5sZW5ndGgsbj1uZXcgQmlnSW50NjRBcnJheShyKSxpPW5ldyBVaW50OEFycmF5KE1hdGguY2VpbChyLzgpKSxzPTA7Zm9yKGxldCBhPTA7YTxyO2ErKyl7bGV0IGw9dFthXTtpZihsPT09bnVsbHx8bD09PXZvaWQgMCl7cysrO2NvbnRpbnVlfWlbYT4+M118PTE8PChhJjcpLG5bYV09dHlwZW9mIGw9PT0iYmlnaW50Ij9sOkJpZ0ludChsKX1sZXQgbz1uZXcgSW50MzJBcnJheShuLmJ1ZmZlcik7cmV0dXJuIFMoe3R5cGU6ZSxsZW5ndGg6cixudWxsQml0bWFwOnM+MD9pOnZvaWQgMCxkYXRhOm8sbnVsbENvdW50OnN9KX1mdW5jdGlvbiBqTyh0LGUpe2xldCByPWUuYnl0ZVdpZHRoPz8oZS5iaXRXaWR0aD9lLmJpdFdpZHRoLzg6MTYpLG49dC5sZW5ndGgsaT1uZXcgVWludDhBcnJheShuKnIpLHM9bmV3IFVpbnQ4QXJyYXkoTWF0aC5jZWlsKG4vOCkpLG89MDtmb3IobGV0IGE9MDthPG47YSsrKXtsZXQgbD10W2FdO2lmKGw9PT1udWxsfHxsPT09dm9pZCAwKXtvKys7Y29udGludWV9c1thPj4zXXw9MTw8KGEmNyk7bGV0IHU7aWYobCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpdT1sO2Vsc2UgaWYoQXJyYXlCdWZmZXIuaXNWaWV3KGwpKXtsZXQgZj1sO3U9bmV3IFVpbnQ4QXJyYXkoZi5idWZmZXIsZi5ieXRlT2Zmc2V0LGYuYnl0ZUxlbmd0aCl9ZWxzZSB1PXFPKCRPKGwpLHIpO2kuc2V0KHUuc3ViYXJyYXkoMCxyKSxhKnIpfXJldHVybiBTKHt0eXBlOmUsbGVuZ3RoOm4sbnVsbEJpdG1hcDpvPjA/czp2b2lkIDAsZGF0YTpuZXcgVWludDMyQXJyYXkoaS5idWZmZXIsaS5ieXRlT2Zmc2V0LGkuYnl0ZUxlbmd0aC80KSxudWxsQ291bnQ6b30pfWZ1bmN0aW9uICRPKHQpe3JldHVybiB0eXBlb2YgdD09PSJiaWdpbnQiP3Q6QmlnSW50KE1hdGgudHJ1bmMoTnVtYmVyKHQpKSl9ZnVuY3Rpb24gcU8odCxlKXtsZXQgcj1uZXcgVWludDhBcnJheShlKSxuPXQ7aWYobjwwbiluPSgxbjw8QmlnSW50KGUqOCkpK247Zm9yKGxldCBpPTA7aTxlO2krKylyW2ldPU51bWJlcihuJjB4ZmZuKSxuPj49OG47cmV0dXJuIHJ9ZnVuY3Rpb24gV08odCxlKXtsZXQgcj1lLmNoaWxkcmVuWzBdLG49dC5sZW5ndGgsaT1uZXcgSW50MzJBcnJheShuKzEpLHM9W10sbz1uZXcgVWludDhBcnJheShNYXRoLmNlaWwobi84KSksYT0wO2ZvcihsZXQgdT0wO3U8bjt1Kyspe2lbdV09cy5sZW5ndGg7bGV0IGY9dFt1XTtpZihmPT1udWxsKWErKztlbHNle29bdT4+M118PTE8PCh1JjcpO2xldCBwPUFycmF5LmlzQXJyYXkoZik/Zjp0eXBlb2YgZltTeW1ib2wuaXRlcmF0b3JdPT09ImZ1bmN0aW9uIj9BcnJheS5mcm9tKGYpOm51bGw7aWYocClmb3IobGV0IGcgb2YgcClzLnB1c2goZyl9fWlbbl09cy5sZW5ndGg7bGV0IGw9cy5sZW5ndGg+MD91dShzLHIudHlwZSk6UmMoci50eXBlKTtyZXR1cm4gUyh7dHlwZTplLGxlbmd0aDpuLG51bGxDb3VudDphLG51bGxCaXRtYXA6YT4wP286dm9pZCAwLGNoaWxkOmwsb2Zmc2V0OjAsdmFsdWVPZmZzZXRzOml9KX1mdW5jdGlvbiBITyh0LGUpe2xldCByPXQubGVuZ3RoLG49ZS5jaGlsZHJlblswXSxpPW4udHlwZS5jaGlsZHJlblswXSxzPW4udHlwZS5jaGlsZHJlblsxXSxvPW5ldyBJbnQzMkFycmF5KHIrMSksYT1bXSxsPVtdLHU9bmV3IFVpbnQ4QXJyYXkoTWF0aC5jZWlsKHIvOCkpLGY9MDtmb3IobGV0IEk9MDtJPHI7SSsrKXtvW0ldPWEubGVuZ3RoO2xldCBEPXRbSV07aWYoRD09bnVsbClmKys7ZWxzZXt1W0k+PjNdfD0xPDwoSSY3KTtsZXQgWj1BcnJheS5pc0FycmF5KEQpP0Q6RCBpbnN0YW5jZW9mIE1hcD9BcnJheS5mcm9tKEQuZW50cmllcygpKTp0eXBlb2YgRFtTeW1ib2wuaXRlcmF0b3JdPT09ImZ1bmN0aW9uIj9BcnJheS5mcm9tKEQpOnR5cGVvZiBEPT09Im9iamVjdCI/T2JqZWN0LmVudHJpZXMoRCk6W107Zm9yKGxldFttdCxwZV1vZiBaKWEucHVzaChtdCksbC5wdXNoKHBlKX19b1tyXT1hLmxlbmd0aDtsZXQgcD1hLmxlbmd0aD4wP3V1KGEsaS50eXBlKTpSYyhpLnR5cGUpLGc9bC5sZW5ndGg+MD91dShsLHMudHlwZSk6UmMocy50eXBlKSx2PVMoe3R5cGU6bi50eXBlLGxlbmd0aDphLmxlbmd0aCxjaGlsZHJlbjpbcCxnXSxudWxsQ291bnQ6MH0pO3JldHVybiBTKHt0eXBlOmUsbGVuZ3RoOnIsbnVsbENvdW50OmYsbnVsbEJpdG1hcDpmPjA/dTp2b2lkIDAsY2hpbGQ6dixvZmZzZXQ6MCx2YWx1ZU9mZnNldHM6b30pfWZ1bmN0aW9uIFlPKHQsZSl7bGV0IHI9ZS5jaGlsZHJlbixuPXQubGVuZ3RoLGk9bmV3IFVpbnQ4QXJyYXkoTWF0aC5jZWlsKG4vOCkpLHM9MCxvPXIubWFwKCgpPT5bXSk7Zm9yKGxldCBsPTA7bDxuO2wrKyl7bGV0IHU9dFtsXTtpZih1PT1udWxsKXtzKys7Zm9yKGxldCBmPTA7ZjxyLmxlbmd0aDtmKyspb1tmXS5wdXNoKG51bGwpfWVsc2V7aVtsPj4zXXw9MTw8KGwmNyk7Zm9yKGxldCBmPTA7ZjxyLmxlbmd0aDtmKyspe2xldCBwPXJbZl0ubmFtZTtvW2ZdLnB1c2godVtwXT8/dVtmXT8/bnVsbCl9fX1sZXQgYT1yLm1hcCgobCx1KT0+dXUob1t1XSxsLnR5cGUpKTtyZXR1cm4gUyh7dHlwZTplLGxlbmd0aDpuLG51bGxDb3VudDpzLG51bGxCaXRtYXA6cz4wP2k6dm9pZCAwLGNoaWxkcmVuOmF9KX1mdW5jdGlvbiBSYyh0KXtpZihCLmlzTGlzdCh0KSlyZXR1cm4gUyh7dHlwZTp0LGxlbmd0aDowLG51bGxDb3VudDowLGNoaWxkOlJjKHQuY2hpbGRyZW5bMF0udHlwZSksdmFsdWVPZmZzZXRzOm5ldyBJbnQzMkFycmF5KFswXSl9KTtpZihCLmlzTWFwKHQpKXJldHVybiBTKHt0eXBlOnQsbGVuZ3RoOjAsbnVsbENvdW50OjAsY2hpbGQ6UmModC5jaGlsZHJlblswXS50eXBlKSx2YWx1ZU9mZnNldHM6bmV3IEludDMyQXJyYXkoWzBdKX0pO2lmKEIuaXNTdHJ1Y3QodCkpe2xldCBlPXQuY2hpbGRyZW4ubWFwKChyKT0+UmMoci50eXBlKSk7cmV0dXJuIFMoe3R5cGU6dCxsZW5ndGg6MCxudWxsQ291bnQ6MCxjaGlsZHJlbjplfSl9cmV0dXJuIFMoe3R5cGU6dCxsZW5ndGg6MCxudWxsQ291bnQ6MH0pfWZ1bmN0aW9uIGppKHQsZSxyKXtsZXQgbj1lLGk9bj8uZGF0YT8uWzBdO3JldHVybiBHTyh0LG4saSxyKX1mdW5jdGlvbiBLTyh0LGUscil7aWYodHlwZW9mIHQ/LmlzVmFsaWQ9PT0iZnVuY3Rpb24iKXJldHVybiB0LmlzVmFsaWQocik7bGV0IG49ZT8ubnVsbEJpdG1hcDtpZihuJiZuLmxlbmd0aD4wKXJldHVybihuW3I+PjNdPj4ociY3KSYxKT09PTE7cmV0dXJuITB9ZnVuY3Rpb24gR08odCxlLHIsbil7aWYoIUtPKGUscixuKSlyZXR1cm4gbnVsbDtzd2l0Y2godC50eXBlSWQpe2Nhc2UgMTpyZXR1cm4gbnVsbDtjYXNlIDY6cmV0dXJuIGUuZ2V0KG4pO2Nhc2UgMjp7bGV0IHM9dC5iaXRXaWR0aD8/MzIsbz1yPy52YWx1ZXM/LltuXTtpZihzPT09NjQpcmV0dXJuIHR5cGVvZiBvPT09ImJpZ2ludCI/bzpCaWdJbnQobyk7cmV0dXJuIE51bWJlcihvKX1jYXNlIDM6cmV0dXJuIE51bWJlcihyPy52YWx1ZXM/LltuXSk7Y2FzZSA1OmNhc2UgMjA6cmV0dXJuIFN0cmluZyhlLmdldChuKSk7Y2FzZSA0OmNhc2UgMTk6Y2FzZSAxNTpyZXR1cm4gSk8oZS5nZXQobikpO2Nhc2UgNzpyZXR1cm4gWE8odCxyLG4pO2Nhc2UgODp7bGV0IHM9cj8udmFsdWVzPy5bbl07aWYodC51bml0PT09cXQuREFZKXJldHVybiBOdW1iZXIocyk7cmV0dXJuIHR5cGVvZiBzPT09ImJpZ2ludCI/czpCaWdJbnQocyl9Y2FzZSA5OntsZXQgcz1yPy52YWx1ZXM/LltuXTtpZigodC5iaXRXaWR0aD8/MzIpPT09NjQpcmV0dXJuIHR5cGVvZiBzPT09ImJpZ2ludCI/czpCaWdJbnQocyk7cmV0dXJuIE51bWJlcihzKX1jYXNlIDEwOmNhc2UgMTg6e2xldCBzPXI/LnZhbHVlcz8uW25dO3JldHVybiB0eXBlb2Ygcz09PSJiaWdpbnQiP3M6QmlnSW50KHMpfWNhc2UgMTM6cmV0dXJuIFFPKHQsZSxuKTtjYXNlIDE0OnJldHVybiB0Tih0LGUscixuKTtjYXNlIDEyOmNhc2UgMTY6cmV0dXJuIGVOKHQsZSxyLG4pO2Nhc2UgMTc6cmV0dXJuIHJOKHQsZSxyLG4pO2Nhc2UtMTpyZXR1cm4gbk4odCxlLHIsbik7ZGVmYXVsdDpyZXR1cm4gZS5nZXQobil9fWZ1bmN0aW9uIEpPKHQpe2lmKHQ9PW51bGwpcmV0dXJuIG51bGw7aWYodCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpcmV0dXJuIHQ7aWYoQXJyYXlCdWZmZXIuaXNWaWV3KHQpKXtsZXQgZT10O3JldHVybiBuZXcgVWludDhBcnJheShlLmJ1ZmZlcixlLmJ5dGVPZmZzZXQsZS5ieXRlTGVuZ3RoKX1yZXR1cm4gdH1mdW5jdGlvbiBYTyh0LGUscil7bGV0IG49dC5ieXRlV2lkdGg/Pyh0LmJpdFdpZHRoP3QuYml0V2lkdGgvODoxNiksaT1lLnZhbHVlcyxzPW4vNCxvPXIqcyxhPW5ldyBVaW50OEFycmF5KG4pO2ZvcihsZXQgbD0wO2w8cztsKyspe2xldCB1PWlbbytsXT4+PjA7YVtsKjRdPXUmMjU1LGFbbCo0KzFdPXU+Pj44JjI1NSxhW2wqNCsyXT11Pj4+MTYmMjU1LGFbbCo0KzNdPXU+Pj4yNCYyNTV9cmV0dXJuIFpPKGEpfWZ1bmN0aW9uIFpPKHQpe2xldCBlPTBuO2ZvcihsZXQgcj10Lmxlbmd0aC0xO3I+PTA7ci0tKWU9ZTw8OG58QmlnSW50KHRbcl0pO2lmKHRbdC5sZW5ndGgtMV0mMTI4KWUtPTFuPDxCaWdJbnQodC5sZW5ndGgqOCk7cmV0dXJuIGV9ZnVuY3Rpb24gUU8odCxlLHIpe2xldCBuPXQuY2hpbGRyZW4saT17fTtmb3IobGV0IHM9MDtzPG4ubGVuZ3RoO3MrKyl7bGV0IG89bltzXSxhPXR5cGVvZiBlLmdldENoaWxkQXQ9PT0iZnVuY3Rpb24iP2UuZ2V0Q2hpbGRBdChzKTplLmNoaWxkcmVuPy5bc107aWYoIWEpe2lbby5uYW1lXT1udWxsO2NvbnRpbnVlfWlbby5uYW1lXT1qaShvLnR5cGUsYSxyKX1yZXR1cm4gaX1mdW5jdGlvbiB0Tih0LGUscixuKXtsZXQgaT10LmNoaWxkcmVuLHM9cj8udHlwZUlkcyxvPXM/c1tuXTppLmxlbmd0aD4wPzA6LTEsYT10LnR5cGVJZFRvQ2hpbGRJbmRleCxsPWEmJmFbb10hPT12b2lkIDA/YVtvXTpvLHU9aVtsXTtpZighdSlyZXR1cm57dGFnOm51bGwsdmFsdWU6bnVsbH07bGV0IGY9cj8udmFsdWVPZmZzZXRzLHA9Zj9mW25dOm4sZz10eXBlb2YgZS5nZXRDaGlsZEF0PT09ImZ1bmN0aW9uIj9lLmdldENoaWxkQXQobCk6ZS5jaGlsZHJlbj8uW2xdLHY9Zz9qaSh1LnR5cGUsZyxwKTpudWxsO3JldHVybnt0YWc6dS5uYW1lLHZhbHVlOnZ9fWZ1bmN0aW9uIGVOKHQsZSxyLG4pe2xldCBpPXQuY2hpbGRyZW5bMF0scz10eXBlb2YgZS5nZXRDaGlsZEF0PT09ImZ1bmN0aW9uIj9lLmdldENoaWxkQXQoMCk6ZS5jaGlsZHJlbj8uWzBdLG89cj8udmFsdWVPZmZzZXRzLGEsbDtpZihvKWE9b1tuXSxsPW9bbisxXTtlbHNle2xldCBmPXQubGlzdFNpemU/PzA7YT1uKmYsbD1hK2Z9bGV0IHU9W107Zm9yKGxldCBmPWE7ZjxsO2YrKyl1LnB1c2goamkoaS50eXBlLHMsZikpO3JldHVybiB1fWZ1bmN0aW9uIHJOKHQsZSxyLG4pe2xldCBpPXQuY2hpbGRyZW5bMF0scz1pLnR5cGUuY2hpbGRyZW5bMF0sbz1pLnR5cGUuY2hpbGRyZW5bMV0sYT1yPy52YWx1ZU9mZnNldHMsbD10eXBlb2YgZS5nZXRDaGlsZEF0PT09ImZ1bmN0aW9uIj9lLmdldENoaWxkQXQoMCk6ZS5jaGlsZHJlbj8uWzBdLHU9bCYmKHR5cGVvZiBsLmdldENoaWxkQXQ9PT0iZnVuY3Rpb24iP2wuZ2V0Q2hpbGRBdCgwKTpsLmNoaWxkcmVuPy5bMF0pLGY9bCYmKHR5cGVvZiBsLmdldENoaWxkQXQ9PT0iZnVuY3Rpb24iP2wuZ2V0Q2hpbGRBdCgxKTpsLmNoaWxkcmVuPy5bMV0pLHA9YT9hW25dOjAsZz1hP2FbbisxXTowLHY9W107Zm9yKGxldCBJPXA7STxnO0krKyl2LnB1c2goW2ppKHMudHlwZSx1LEkpLGppKG8udHlwZSxmLEkpXSk7cmV0dXJuIHZ9ZnVuY3Rpb24gbk4odCxlLHIsbil7bGV0IGk9dC5kaWN0aW9uYXJ5O2lmKHImJnIuZGljdGlvbmFyeSYmci52YWx1ZXMpe2xldCBzPU51bWJlcihyLnZhbHVlc1tuXSksbz1yLmRpY3Rpb25hcnk7cmV0dXJuIGppKGksbyxzKX1yZXR1cm4gZS5nZXQobil9ZnVuY3Rpb24gaU4odCxlKXtyZXR1cm4gT2ModCxlKS5kYXRhWzBdfWZ1bmN0aW9uIEZvKHQsZSl7bGV0IHI9ZTtpZih0Lmxlbmd0aD09PTApcmV0dXJuIEhkKHIpO2xldCBuPXt9O2ZvcihsZXQgaSBvZiByLmZpZWxkcyluW2kubmFtZV09dC5tYXAoKHMpPT5zW2kubmFtZV0/P251bGwpO3JldHVybiBVbyhuLHIpfWZ1bmN0aW9uIFVvKHQsZSxyPSJyaWNoIil7bGV0IG49ZSxpPW4uZmllbGRzLmxlbmd0aD4wP3Rbbi5maWVsZHNbMF0ubmFtZV0/Lmxlbmd0aD8/MDowLHM9bi5maWVsZHMubWFwKChsKT0+e2xldCB1PXRbbC5uYW1lXTtpZighdSlyZXR1cm4gUyh7dHlwZTpsLnR5cGUsbGVuZ3RoOmksbnVsbENvdW50Oml9KTtsZXQgZj16aShsLnR5cGUpLHA9cj09PSJyYXciP2YucmF3VG9DYW5vbmljYWw6Zi5yaWNoVG9DYW5vbmljYWwsZz11Lm1hcCgodik9PnAuY2FsbChmLHYpKTtyZXR1cm4gTkkobC50eXBlLGcpfSksbz1uZXcgRXQobi5maWVsZHMpLGE9Uyh7dHlwZTpvLGxlbmd0aDppLGNoaWxkcmVuOnMsbnVsbENvdW50OjB9KTtyZXR1cm4gbmV3IEF0KG4sYSl9ZnVuY3Rpb24qa2kodCxlPSJyaWNoIil7bGV0IHI9dCxuPXIuc2NoZW1hLmZpZWxkcy5tYXAoKGkpPT56aShpLnR5cGUpKTtmb3IobGV0IGk9MDtpPHIubnVtUm93cztpKyspe2xldCBzPXt9O2ZvcihsZXQgbz0wO288ci5zY2hlbWEuZmllbGRzLmxlbmd0aDtvKyspe2xldCBhPXIuc2NoZW1hLmZpZWxkc1tvXSxsPXIuZ2V0Q2hpbGQoYS5uYW1lKTtpZighbCl7c1thLm5hbWVdPW51bGw7Y29udGludWV9bGV0IHU9amkoYS50eXBlLGwsaSksZj1uW29dO3NbYS5uYW1lXT1lPT09InJhdyI/Zi5jYW5vbmljYWxUb1Jhdyh1KTpmLmNhbm9uaWNhbFRvUmljaCh1KX15aWVsZCBzfX1mdW5jdGlvbiBGSSh0KXtpZighdClyZXR1cm57fTtsZXQgZT10O2lmKGUubnVtUm93cz09PTApcmV0dXJue307bGV0IHI9e307Zm9yKGxldCBuIG9mIGUuc2NoZW1hLmZpZWxkcyl7bGV0IGk9ZS5nZXRDaGlsZChuLm5hbWUpO2lmKGkpe2xldCBzPW4udHlwZSxvPWppKHMsaSwwKTtyW24ubmFtZV09emkocykuY2Fub25pY2FsVG9SaWNoKG8pfX1yZXR1cm4gcn1mdW5jdGlvbiBzTih0LGU9MCl7aWYodCYmdHlwZW9mIHQ9PT0ib2JqZWN0IiYmImRpY3Rpb25hcnkiaW4gdCYmInZhbHVlcyJpbiB0JiZ0eXBlb2YgdC5kaWN0aW9uYXJ5Py5nZXQ9PT0iZnVuY3Rpb24iKXtsZXQgcj10LG49ci5udWxsQml0bWFwO2lmKG4mJm4ubGVuZ3RoPjApe2lmKChuW2U+PjNdPj4oZSY3KSYxKT09PTApcmV0dXJuIG51bGx9bGV0IGk9TnVtYmVyKHIudmFsdWVzW2VdKTtyZXR1cm4gdC5kaWN0aW9uYXJ5LmdldChpKX1yZXR1cm4gdH1mdW5jdGlvbiBvTih0KXtpZighdClyZXR1cm57fTtsZXQgZT10O2lmKGUubnVtUm93cz09PTApcmV0dXJue307bGV0IHI9e307Zm9yKGxldCBuIG9mIGUuc2NoZW1hLmZpZWxkcyl7bGV0IGk9ZS5nZXRDaGlsZChuLm5hbWUpO2lmKGkpe2xldCBzPW4udHlwZSxvPXppKHMpLmNhbm9uaWNhbFRvUmljaChqaShzLGksMCkpLGE9bi5uYW1lLGw7aWYobi5uYW1lLnN0YXJ0c1dpdGgoInNlY3JldF8iKSl7bGV0IHU9bi5tZXRhZGF0YT8uZ2V0Py4oInNlY3JldF90eXBlIik7aWYodSlhPXUsbD1uLm1ldGFkYXRhPy5nZXQ/Ligic2NvcGUiKT8/dm9pZCAwfWlmKG8mJnR5cGVvZiBvPT09Im9iamVjdCImJiFBcnJheUJ1ZmZlci5pc1ZpZXcobykpe2xldCB1PXsuLi5vfTtpZihhIGluIHIpdGhyb3cgRXJyb3IoYGJhdGNoVG9TZWNyZXREaWN0OiBkdXBsaWNhdGUgc2VjcmV0X3R5cGUgJyR7YX0nIChzY29wZT0ke2w/PyJub25lIn0pLiBVc2Ugc2NvcGVkIHNlY3JldHMgd2l0aCBkaXN0aW5jdCBzY29wZXMgdG8gYXZvaWQgY29sbGlzaW9ucy5gKTtpZihyW2FdPXUsbClyW2Ake2F9OiR7bH1gXT11fWVsc2UgaWYobz09PW51bGx8fG89PT12b2lkIDApO2Vsc2UgclthXT17fX19cmV0dXJuIHJ9dmFyIE1JPUJpZ0ludChOdW1iZXIuTUFYX1NBRkVfSU5URUdFUiksYU49LU1JO2Z1bmN0aW9uIGNOKHQpe2lmKHR5cGVvZiB0PT09ImJpZ2ludCIpe2lmKHQ+TUl8fHQ8YU4pdGhyb3cgUmFuZ2VFcnJvcihgJHt0fSBjYW5ub3QgYmUgcmVwcmVzZW50ZWQgZXhhY3RseSBhcyBhIEpTIG51bWJlciAofHZhbHVlfCA+IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSKS4gS2VlcCBpdCBhcyBhIGJpZ2ludC5gKTtyZXR1cm4gTnVtYmVyKHQpfXJldHVybiB0fWZ1bmN0aW9uIGxOKHQsZSl7bGV0IHI9dCxuPXIubnVtUm93cyxpPTA7Zm9yKGxldCBhPTA7YTxuO2ErKylpZihlW2FdKWkrKztpZihpPT09bilyZXR1cm4gcjtpZihpPT09MClyZXR1cm4gSGQoci5zY2hlbWEpO2xldCBzPVtdO2ZvcihsZXQgYT0wO2E8bjthKyspaWYoZVthXSlzLnB1c2goYSk7bGV0IG89e307Zm9yKGxldCBhIG9mIHIuc2NoZW1hLmZpZWxkcyl7bGV0IGw9ci5nZXRDaGlsZChhLm5hbWUpLHU9YS50eXBlLGY9emkodSk7b1thLm5hbWVdPXMubWFwKChwKT0+Zi5jYW5vbmljYWxUb1JpY2goamkodSxsLHApKSl9cmV0dXJuIFVvKG8sci5zY2hlbWEpfWZ1bmN0aW9uIExJKHQsZSxyKXtmb3IobGV0IG4gb2YgZSl7aWYobjwtMSl0aHJvdyBFcnJvcihgJHt0fTogdW5leHBlY3RlZCBuZWdhdGl2ZSBwcm9qZWN0aW9uIElEICR7bn0gKG9ubHkgLTEgZm9yIHJvd19pZCBpcyBhbGxvd2VkKWApO2lmKG4+PXIpY29uc29sZS53YXJuKGAke3R9OiBwcm9qZWN0aW9uIElEICR7bn0gaXMgb3V0IG9mIGJvdW5kcyAoc2NoZW1hIGhhcyAke3J9IGZpZWxkcyksIGlnbm9yaW5nYCl9cmV0dXJuIGUuZmlsdGVyKChuKT0+bj49MCYmbjxyKX1mdW5jdGlvbiBVSSh0LGUpe2xldCByPWU7aWYoIXQpcmV0dXJuIHI7bGV0IG49TEkoInByb2plY3RTY2hlbWEiLHQsci5maWVsZHMubGVuZ3RoKTtpZihuLmxlbmd0aD09PTApcmV0dXJuIHI7cmV0dXJuIG5ldyBsdChuLm1hcCgoaSk9PnIuZmllbGRzW2ldKSl9ZnVuY3Rpb24gdU4odCxlKXtsZXQgcj1lO2lmKCF0KXJldHVybiByO2xldCBuPUxJKCJwcm9qZWN0QmF0Y2giLHQsci5zY2hlbWEuZmllbGRzLmxlbmd0aCk7aWYobi5sZW5ndGg9PT0wKXJldHVybiByO2xldCBpPVVJKHQsci5zY2hlbWEpLHM9bi5tYXAoKGwpPT5yLmdldENoaWxkQXQobCkuZGF0YVswXSksbz1uZXcgRXQoaS5maWVsZHMpLGE9Uyh7dHlwZTpvLGxlbmd0aDpyLm51bVJvd3MsY2hpbGRyZW46cyxudWxsQ291bnQ6MH0pO3JldHVybiBuZXcgQXQoaSxhKX1mdW5jdGlvbiBmTih0LGUpe2xldCByPXQ7cmV0dXJuIG5ldyBBdChyLnNjaGVtYSxyLmRhdGEsZSl9ZnVuY3Rpb24gJGQodCl7bGV0IGU9bmV3IEZzO3JldHVybiBlLnJlc2V0KHZvaWQgMCx0KSxlLmNsb3NlKCksZS50b1VpbnQ4QXJyYXkoITApfWZ1bmN0aW9uIFlkKHQpe2xldCBlPWhyLmZyb20odCkscj1bLi4uZV07aWYoci5sZW5ndGg+MClyZXR1cm4gclswXS5zY2hlbWE7aWYoZS5zY2hlbWEpcmV0dXJuIGUuc2NoZW1hO3Rocm93IEVycm9yKCJDYW5ub3QgZGVzZXJpYWxpemUgc2NoZW1hIGZyb20gZW1wdHkgSVBDIHN0cmVhbSIpfWZ1bmN0aW9uIHVzKHQpe2xldCBlPXQscj1uZXcgRnM7cmV0dXJuIHIucmVzZXQodm9pZCAwLGUuc2NoZW1hKSxyLl93cml0ZVJlY29yZEJhdGNoKGUpLHIuY2xvc2UoKSxyLnRvVWludDhBcnJheSghMCl9ZnVuY3Rpb24gQ2ModCl7bGV0IGU9aHIuZnJvbSh0KSxyPVsuLi5lXTtpZihyLmxlbmd0aD09PTApe2xldCBuPWUuc2NoZW1hPz9uZXcgbHQoW10pO3JldHVybiBIZChuKX1yZXR1cm4gclswXX1mdW5jdGlvbiBkTih0KXtsZXQgZT10O3JldHVyblt0LnR5cGVJZCxlLnVuaXQ/PyIiLGUuYml0V2lkdGg/PyIiLGUucHJlY2lzaW9uPz8iIixlLnNjYWxlPz8iIixlLmJ5dGVXaWR0aD8/IiJdLmpvaW4oIjoiKX1mdW5jdGlvbiBNbyh0LGUpe2xldCByPWU7aWYoci50eXBlSWQ9PT0xKXJldHVybiBTKHt0eXBlOnIsbGVuZ3RoOnQubGVuZ3RoLG51bGxDb3VudDp0Lmxlbmd0aH0pO2xldCBuPXppKGUpLGk9dC5tYXAoKHMpPT5uLnJpY2hUb0Nhbm9uaWNhbChzKSk7cmV0dXJuIE5JKGUsaSl9ZnVuY3Rpb24gaE4odCl7aWYodC5sZW5ndGg9PT0wKXtsZXQgZz1uZXcgVSgiMCIsbmV3IHdlLCEwKSx2PW5ldyB2byhbMF0sW2ddKSxJPVMoe3R5cGU6dixsZW5ndGg6MCx0eXBlSWRzOm5ldyBJbnQ4QXJyYXkoMCksY2hpbGRyZW46W1Moe3R5cGU6bmV3IHdlLGxlbmd0aDowLG51bGxDb3VudDowfSldfSksRD1TKHt0eXBlOnYsbGVuZ3RoOjAsdHlwZUlkczpuZXcgSW50OEFycmF5KDApLGNoaWxkcmVuOltTKHt0eXBlOm5ldyB3ZSxsZW5ndGg6MCxudWxsQ291bnQ6MH0pXX0pO3JldHVybiBzSShbXSxJLEQsW10sW10sW10sW10sW10sdil9bGV0IGU9W10scj1uZXcgTWFwLG49W107Zm9yKGxldCBnIG9mIHQpe2xldCB2PWROKGcuYXJyb3dUeXBlKSxJPXIuZ2V0KHYpO2lmKEk9PT12b2lkIDApST1lLmxlbmd0aCxyLnNldCh2LEkpLGUucHVzaChnLmFycm93VHlwZSk7bi5wdXNoKEkpfWxldCBpPVtdLHM9W10sbz1bXSxhPVtdO2ZvcihsZXRbZyx2XW9mIGUuZW50cmllcygpKXtpLnB1c2gobmV3IFUoU3RyaW5nKGcpLHYsITApKSxhLnB1c2goZyk7bGV0IEk9dC5tYXAoKFosbXQpPT5uW210XT09PWc/Wi5taW46bnVsbCksRD10Lm1hcCgoWixtdCk9Pm5bbXRdPT09Zz9aLm1heDpudWxsKTtzLnB1c2goTW8oSSx2KSksby5wdXNoKE1vKEQsdikpfWxldCBsPW5ldyB2byhhLGkpLHU9SW50OEFycmF5LmZyb20obiksZj1TKHt0eXBlOmwsbGVuZ3RoOnQubGVuZ3RoLHR5cGVJZHM6dSxjaGlsZHJlbjpzfSkscD1TKHt0eXBlOmwsbGVuZ3RoOnQubGVuZ3RoLHR5cGVJZHM6dSxjaGlsZHJlbjpvfSk7cmV0dXJuIHNJKHQubWFwKChnKT0+Zy5jb2x1bW5OYW1lKSxmLHAsdC5tYXAoKGcpPT5nLmhhc051bGwpLHQubWFwKChnKT0+Zy5oYXNOb3ROdWxsKSx0Lm1hcCgoZyk9PmcuZGlzdGluY3RDb3VudD09bnVsbD9udWxsOkJpZ0ludChnLmRpc3RpbmN0Q291bnQpKSx0Lm1hcCgoZyk9PmcuY29udGFpbnNVbmljb2RlKSx0Lm1hcCgoZyk9PmcubWF4U3RyaW5nTGVuZ3RoPT1udWxsP251bGw6QmlnSW50KGcubWF4U3RyaW5nTGVuZ3RoKSksbCl9ZnVuY3Rpb24gc0kodCxlLHIsbixpLHMsbyxhLGwpe2xldCB1PW5ldyBsdChbbmV3IFUoImNvbHVtbl9uYW1lIixuZXcgSXIsITEpLG5ldyBVKCJtaW4iLGwsITApLG5ldyBVKCJtYXgiLGwsITApLG5ldyBVKCJoYXNfbnVsbCIsbmV3IFVlLCExKSxuZXcgVSgiaGFzX25vdF9udWxsIixuZXcgVWUsITEpLG5ldyBVKCJkaXN0aW5jdF9jb3VudCIsbmV3IEluLCEwKSxuZXcgVSgiY29udGFpbnNfdW5pY29kZSIsbmV3IFVlLCEwKSxuZXcgVSgibWF4X3N0cmluZ19sZW5ndGgiLG5ldyBMaSwhMCldKSxmPXQubGVuZ3RoLHA9W01vKHQsbmV3IElyKSxlLHIsTW8obixuZXcgVWUpLE1vKGksbmV3IFVlKSxNbyhzLG5ldyBJbiksTW8obyxuZXcgVWUpLE1vKGEsbmV3IExpKV0sZz1uZXcgRXQodS5maWVsZHMpLHY9Uyh7dHlwZTpnLGxlbmd0aDpmLGNoaWxkcmVuOnAsbnVsbENvdW50OjB9KTtyZXR1cm4gbmV3IEF0KHUsdil9dmFyIHBOPXtuYW1lOiJhcnJvdy1qcyJ9O2Z1bmN0aW9uIG1OKHQpe3JldHVybiB0fXZhcntUaW1lVW5pdDp5TixEYXRlVW5pdDpyeixJbnRlcnZhbFVuaXQ6bnosVW5pb25Nb2RlOml6LHNjaGVtYTpifT1wSTtmdW5jdGlvbiBjKHQsZSxyLG4pe3JldHVybiBMbyh0LGUscixuKX12YXIgUkk9KCk9Pm1JKCksUD0oKT0+eUkoKSx0ZT0oKT0+V2QoKSxEYT0oKT0+S3koKSxpdD0oKT0+R3koKSxvST0oKT0+SnkoKSxLZD0oKT0+dkkoKSxkPSgpPT5JSSgpLGg9KCk9PkJJKCksTHM9KCk9PlNJKCksc3o9e1thdS5TRUNPTkRdOiJzIixbYXUuTUlMTElTRUNPTkRdOiJtcyIsW2F1Lk1JQ1JPU0VDT05EXToidXMiLFthdS5OQU5PU0VDT05EXToibnMifTtmdW5jdGlvbiBfTih0LGUpe3JldHVybiBBSSh0LGU/P251bGwpfWZ1bmN0aW9uIHcodCl7cmV0dXJuIERJKHQpfWZ1bmN0aW9uIFZpKHQpe3JldHVybiBReSh0KX1mdW5jdGlvbiBrcih0LGUscil7cmV0dXJuIHhJKHQsZSxyKX1mdW5jdGlvbiBlZSh0LGUscixuKXtyZXR1cm4gVEkodCxlLHIsbil9Y2xhc3MgU2F7cG9zaXRpb25hbDtuYW1lZDthcmd1bWVudHNTY2hlbWE7Y29uc3RydWN0b3IodD1bXSxlPW5ldyBNYXAscj1udWxsKXt0aGlzLnBvc2l0aW9uYWw9dCx0aGlzLm5hbWVkPWUsdGhpcy5hcmd1bWVudHNTY2hlbWE9cn1nZXQodCxlKXtpZih0eXBlb2YgdD09PSJudW1iZXIiKXtpZih0PHRoaXMucG9zaXRpb25hbC5sZW5ndGgpe2xldCByPXRoaXMucG9zaXRpb25hbFt0XTtpZihyPT09bnVsbHx8cj09PXZvaWQgMClyZXR1cm4gZSE9PXZvaWQgMD9lOm51bGw7cmV0dXJuIGFJKHIpfWlmKGUhPT12b2lkIDApcmV0dXJuIGU7dGhyb3cgRXJyb3IoYFBvc2l0aW9uYWwgYXJndW1lbnQgJHt0fSBub3QgZm91bmRgKX1pZih0aGlzLm5hbWVkLmhhcyh0KSl7bGV0IHI9dGhpcy5uYW1lZC5nZXQodCk7aWYocj09PW51bGx8fHI9PT12b2lkIDApcmV0dXJuIGUhPT12b2lkIDA/ZTpudWxsO3JldHVybiBhSShyKX1pZihlIT09dm9pZCAwKXJldHVybiBlO3Rocm93IEVycm9yKGBOYW1lZCBhcmd1bWVudCAnJHt0fScgbm90IGZvdW5kYCl9Z2V0IGxlbmd0aCgpe3JldHVybiB0aGlzLnBvc2l0aW9uYWwubGVuZ3RofX1mdW5jdGlvbiBhSSh0KXtpZih0PT09bnVsbHx8dD09PXZvaWQgMClyZXR1cm4gbnVsbDtpZih0eXBlb2YgdCE9PSJvYmplY3QiKXJldHVybiB0O2lmKHR5cGVvZiB0LnZhbHVlT2Y9PT0iZnVuY3Rpb24iKXtsZXQgZTt0cnl7ZT10LnZhbHVlT2YoKX1jYXRjaHtyZXR1cm4gdH1pZih0eXBlb2YgZT09PSJiaWdpbnQiKXtpZihlPj1OdW1iZXIuTUlOX1NBRkVfSU5URUdFUiYmZTw9TnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIpcmV0dXJuIE51bWJlcihlKTtyZXR1cm4gZX1yZXR1cm4gZX1yZXR1cm4gdH1mdW5jdGlvbiBnTih0KXtsZXQgZT1bXSxyPXt9O2ZvcihsZXQgYT0wO2E8dC5wb3NpdGlvbmFsLmxlbmd0aDthKyspe2xldCBsPXQucG9zaXRpb25hbFthXSx1PWBwb3NpdGlvbmFsXyR7YX1gO2UucHVzaChjKHUsY0kobCksITApKSxyW3VdPWx9Zm9yKGxldFthLGxdb2YgdC5uYW1lZCl7bGV0IHU9YG5hbWVkXyR7YX1gO2UucHVzaChjKHUsY0kobCksITApKSxyW3VdPWx9bGV0IG49VmkoZSksaT1iKFtjKCJhcmdzIixuLCEwKV0pLHM9e307Zm9yKGxldCBhIG9mIGUpe2xldCBsPXJbYS5uYW1lXTtpZihZeShhLnR5cGUpJiZhLnR5cGUuYml0V2lkdGg9PT02NCYmdHlwZW9mIGw9PT0ibnVtYmVyIilsPUJpZ0ludChsKTtzW2EubmFtZV09bH1sZXQgbz1Vbyh7YXJnczpbc119LGkpO3JldHVybiB1cyhvKX1mdW5jdGlvbiBjSSh0KXtpZih0PT09bnVsbHx8dD09PXZvaWQgMClyZXR1cm4gUkkoKTtpZih0eXBlb2YgdD09PSJzdHJpbmciKXJldHVybiBkKCk7aWYodHlwZW9mIHQ9PT0iYm9vbGVhbiIpcmV0dXJuIFAoKTtpZih0eXBlb2YgdD09PSJudW1iZXIiKXJldHVybiBpdCgpO2lmKHR5cGVvZiB0PT09ImJpZ2ludCIpcmV0dXJuIGl0KCk7aWYodCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXl8fHQgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcilyZXR1cm4gaCgpO3JldHVybiBkKCl9dmFyIENJOygodCk9Pnt0LlNDQUxBUj0ic2NhbGFyIix0LlRBQkxFPSJ0YWJsZSIsdC5UQUJMRV9CVUZGRVJJTkc9InRhYmxlX2J1ZmZlcmluZyIsdC5BR0dSRUdBVEU9ImFnZ3JlZ2F0ZSJ9KShDSXx8PXt9KTt2YXIgYk47KCh0KT0+e3QuQ09OU0lTVEVOVD0iQ09OU0lTVEVOVCIsdC5WT0xBVElMRT0iVk9MQVRJTEUiLHQuQ09OU0lTVEVOVF9XSVRISU5fUVVFUlk9IkNPTlNJU1RFTlRfV0lUSElOX1FVRVJZIn0pKGJOfHw9e30pO3ZhciB3TjsoKHQpPT57dC5ERUZBVUxUPSJERUZBVUxUIix0LlNQRUNJQUw9IlNQRUNJQUwifSkod058fD17fSk7dmFyIHZOOygodCk9Pnt0LlVOS05PV049IlVOS05PV04iLHQuQ09OU1RBTlQ9IkNPTlNUQU5UIix0Lk5PTl9ERUNSRUFTSU5HPSJOT05fREVDUkVBU0lORyIsdC5TVFJJQ1RMWV9JTkNSRUFTSU5HPSJTVFJJQ1RMWV9JTkNSRUFTSU5HIix0Lk5PTl9JTkNSRUFTSU5HPSJOT05fSU5DUkVBU0lORyIsdC5TVFJJQ1RMWV9ERUNSRUFTSU5HPSJTVFJJQ1RMWV9ERUNSRUFTSU5HIn0pKHZOfHw9e30pO3ZhciBJTjsoKHQpPT57dC5QUkVTRVJWRVNfT1JERVI9IlBSRVNFUlZFU19PUkRFUiIsdC5OT19PUkRFUl9HVUFSQU5URUU9Ik5PX09SREVSX0dVQVJBTlRFRSIsdC5GSVhFRF9PUkRFUj0iRklYRURfT1JERVIifSkoSU58fD17fSk7dmFyIEJOOygodCk9Pnt0Lk9SREVSX0RFUEVOREVOVD0iT1JERVJfREVQRU5ERU5UIix0Lk5PVF9PUkRFUl9ERVBFTkRFTlQ9Ik5PVF9PUkRFUl9ERVBFTkRFTlQifSkoQk58fD17fSk7dmFyIFNOOygodCk9Pnt0LkRJU1RJTkNUX0RFUEVOREVOVD0iRElTVElOQ1RfREVQRU5ERU5UIix0Lk5PVF9ESVNUSU5DVF9ERVBFTkRFTlQ9Ik5PVF9ESVNUSU5DVF9ERVBFTkRFTlQifSkoU058fD17fSk7dmFyIEFOOygodCk9Pnt0LklOUFVUPSJJTlBVVCIsdC5GSU5BTElaRT0iRklOQUxJWkUiLHQuVEFCTEVfQlVGRkVSSU5HPSJUQUJMRV9CVUZGRVJJTkciLHQuVEFCTEVfQlVGRkVSSU5HX0ZJTkFMSVpFPSJUQUJMRV9CVUZGRVJJTkdfRklOQUxJWkUifSkoQU58fD17fSk7dmFyIEROPSJ2Z2lfYXJnIix4Tj0ibmFtZWQiLFROPSJ2Z2lfdHlwZSIsRU49InRhYmxlIixPTj0iYW55IixOTj0idmdpX3ZhcmFyZ3MiLEZOPSJ0cnVlIixNTj0idmdpX2NvbnN0IixMTj0idHJ1ZSIsVU49InZnaV9kb2MiLFJOPSJ2Z2lfZGVmYXVsdCIsQ049InZnaV9jaG9pY2VzIixQTj0idmdpX3JhbmdlIixrTj0idmdpX3BhdHRlcm4iO2Z1bmN0aW9uIHRpKHQpe2lmKHQgaW5zdGFuY2VvZiBVaW50OEFycmF5KXJldHVybiB0O2lmKHQgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcilyZXR1cm4gbmV3IFVpbnQ4QXJyYXkodCk7aWYodHlwZW9mIEJ1ZmZlcjwidSImJkJ1ZmZlci5pc0J1ZmZlcih0KSlyZXR1cm4gbmV3IFVpbnQ4QXJyYXkodCk7aWYodCYmdC5idWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcilyZXR1cm4gbmV3IFVpbnQ4QXJyYXkodC5idWZmZXIsdC5ieXRlT2Zmc2V0LHQuYnl0ZUxlbmd0aCk7cmV0dXJuIG5ldyBVaW50OEFycmF5KDApfWZ1bmN0aW9uIHFkKHQpe2lmKHR5cGVvZiB0PT09InN0cmluZyIpcmV0dXJuIG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZSh0KTtsZXQgZT10aSh0KTtpZihlLmxlbmd0aD09PTAmJnQhPW51bGwpdGhyb3cgRXJyb3IoYENhbm5vdCBjb252ZXJ0ICR7dHlwZW9mIHR9IHRvIFVpbnQ4QXJyYXlgKTtyZXR1cm4gZX1mdW5jdGlvbiBQSSh0LGUpe2xldCByPXt9O2ZvcihsZXQgbiBvZiB0LmZpZWxkcyl7bGV0IGk9ZVtuLm5hbWVdO2lmKFl5KG4udHlwZSkmJm4udHlwZS5iaXRXaWR0aD09PTY0JiZ0eXBlb2YgaT09PSJudW1iZXIiKWk9QmlnSW50KGkpO3Jbbi5uYW1lXT1baV19cmV0dXJuIFVvKHIsdCl9dmFyIFZOPVZpKFtjKCJmb3JtYXQiLGQoKSwhMSksYygiZmlsZV9wYXRoIixkKCksITEpLGMoImV4cGVjdGVkX3NjaGVtYSIsaCgpLCExKV0pLHpOPVZpKFtjKCJmb3JtYXQiLGQoKSwhMSksYygiZmlsZV9wYXRoIixkKCksITEpXSksak49YihbYygiZnVuY3Rpb25fbmFtZSIsZCgpLCExKSxjKCJhcmd1bWVudHMiLGgoKSwhMSksYygiZnVuY3Rpb25fdHlwZSIsZWUoZCgpLHRlKCkpLCExKSxjKCJpbnB1dF9zY2hlbWEiLGgoKSwhMCksYygic2V0dGluZ3MiLGgoKSwhMCksYygic2VjcmV0cyIsaCgpLCEwKSxjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMCksYygidHJhbnNhY3Rpb25fb3BhcXVlX2RhdGEiLGgoKSwhMCksYygicmVzb2x2ZWRfc2VjcmV0c19wcm92aWRlZCIsUCgpLCExKSxjKCJhdF91bml0IixkKCksITApLGMoImF0X3ZhbHVlIixkKCksITApLGMoImNvcHlfZnJvbSIsVk4sITApLGMoImNvcHlfdG8iLHpOLCEwKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMCksYygiYXJndW1lbnRfbmFtZXMiLHcoYygiaXRlbSIsZCgpLCEwKSksITApXSk7ZnVuY3Rpb24ga0kodCl7cmV0dXJuIFBJKGpOLHtmdW5jdGlvbl9uYW1lOnQuZnVuY3Rpb25fbmFtZSxhcmd1bWVudHM6Z04odC5hcmd1bWVudHMpLGZ1bmN0aW9uX3R5cGU6dC5mdW5jdGlvbl90eXBlLGlucHV0X3NjaGVtYTp0LmlucHV0X3NjaGVtYT8kZCh0LmlucHV0X3NjaGVtYSk6bnVsbCxzZXR0aW5nczp0LnNldHRpbmdzP3VzKHQuc2V0dGluZ3MpOm51bGwsc2VjcmV0czp0LnNlY3JldHM/dXModC5zZWNyZXRzKTpudWxsLGF0dGFjaF9vcGFxdWVfZGF0YTp0LmF0dGFjaF9vcGFxdWVfZGF0YT8/bnVsbCx0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YTp0LnRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhPz9udWxsLHJlc29sdmVkX3NlY3JldHNfcHJvdmlkZWQ6dC5yZXNvbHZlZF9zZWNyZXRzX3Byb3ZpZGVkPz8hMSxhdF91bml0OnQuYXRfdW5pdD8/bnVsbCxhdF92YWx1ZTp0LmF0X3ZhbHVlPz9udWxsLGNvcHlfZnJvbTp0LmNvcHlfZnJvbT97Zm9ybWF0OnQuY29weV9mcm9tLmZvcm1hdCxmaWxlX3BhdGg6dC5jb3B5X2Zyb20uZmlsZV9wYXRoLGV4cGVjdGVkX3NjaGVtYTokZCh0LmNvcHlfZnJvbS5leHBlY3RlZF9zY2hlbWEpfTpudWxsLGNvcHlfdG86dC5jb3B5X3RvP3tmb3JtYXQ6dC5jb3B5X3RvLmZvcm1hdCxmaWxlX3BhdGg6dC5jb3B5X3RvLmZpbGVfcGF0aH06bnVsbCxzY2hlbWFfcGF0aDp0LnNjaGVtYV9wYXRoPz9udWxsLGFyZ3VtZW50X25hbWVzOnQuYXJndW1lbnRfbmFtZXM/P251bGx9KX1mdW5jdGlvbiAkTih0KXtsZXQgZT0ocik9PntpZighcilyZXR1cm5bXTtyZXR1cm4oQXJyYXkuaXNBcnJheShyKT9yOlsuLi5yXSkuZmlsdGVyKChpKT0+aSE9bnVsbCkubWFwKFN0cmluZyl9O3JldHVybntvdXRwdXRfc2NoZW1hOllkKHFkKHQub3V0cHV0X3NjaGVtYSkpLG9wYXF1ZV9kYXRhOnQub3BhcXVlX2RhdGE/cWQodC5vcGFxdWVfZGF0YSk6bnVsbCxsb29rdXBfc2VjcmV0X3R5cGVzOmUodC5sb29rdXBfc2VjcmV0X3R5cGVzKSxsb29rdXBfc2NvcGVzOmUodC5sb29rdXBfc2NvcGVzKSxsb29rdXBfbmFtZXM6ZSh0Lmxvb2t1cF9uYW1lcyl9fXZhciBxTj1iKFtjKCJiaW5kX2NhbGwiLGgoKSwhMSksYygib3V0cHV0X3NjaGVtYSIsaCgpLCExKSxjKCJiaW5kX29wYXF1ZV9kYXRhIixoKCksITApLGMoInByb2plY3Rpb25faWRzIix3KGMoIml0ZW0iLGl0KCksITApKSwhMCksYygicHVzaGRvd25fZmlsdGVycyIsTHMoKSwhMCksYygiam9pbl9rZXlzIix3KGMoIml0ZW0iLExzKCksITApKSwhMCksYygic3BsaXRfdG9rZW5zIix3KGMoIml0ZW0iLExzKCksITApKSwhMCksYygicm93X2xpbWl0IixpdCgpLCEwKSxjKCJwaGFzZSIsZWUoZCgpLHRlKCkpLCEwKSxjKCJmaW5hbGl6ZV9zdGF0ZV9pZCIsaCgpLCEwKSxjKCJleGVjdXRpb25faWQiLGgoKSwhMCksYygiaW5pdF9vcGFxdWVfZGF0YSIsaCgpLCEwKSxjKCJzdWJzdHJlYW1faWQiLGgoKSwhMCksYygib3JkZXJfYnlfY29sdW1uX25hbWUiLGQoKSwhMCksYygib3JkZXJfYnlfZGlyZWN0aW9uIixlZShkKCksdGUoKSksITApLGMoIm9yZGVyX2J5X251bGxfb3JkZXIiLGVlKGQoKSx0ZSgpKSwhMCksYygib3JkZXJfYnlfbGltaXQiLGl0KCksITApLGMoInRhYmxlc2FtcGxlX3BlcmNlbnRhZ2UiLEtkKCksITApLGMoInRhYmxlc2FtcGxlX3NlZWQiLGl0KCksITApXSksb3o9YihbYygiZXhlY3V0aW9uX2lkIixoKCksITEpLGMoIm9wYXF1ZV9kYXRhIixoKCksITApLGMoIm1heF93b3JrZXJzIixpdCgpLCExKV0pO2Z1bmN0aW9uIFdOKHQpe2xldCBlPWtJKHQuYmluZF9jYWxsKSxuPXtiaW5kX2NhbGw6dXMoZSksb3V0cHV0X3NjaGVtYTokZCh0Lm91dHB1dF9zY2hlbWEpLGJpbmRfb3BhcXVlX2RhdGE6dC5iaW5kX29wYXF1ZV9kYXRhPz9udWxsLHByb2plY3Rpb25faWRzOnQucHJvamVjdGlvbl9pZHM/Lm1hcCgoaSk9PkJpZ0ludChpKSk/P251bGwscHVzaGRvd25fZmlsdGVyczp0LnB1c2hkb3duX2ZpbHRlcnM/dXModC5wdXNoZG93bl9maWx0ZXJzKTpudWxsLGpvaW5fa2V5czoodC5qb2luX2tleXM/P1tdKS5tYXAoKGkpPT51cyhpKSksc3BsaXRfdG9rZW5zOnQuc3BsaXRfdG9rZW5zPz9udWxsLHJvd19saW1pdDp0LnJvd19saW1pdD8/bnVsbCxwaGFzZTp0LnBoYXNlPz9udWxsLGZpbmFsaXplX3N0YXRlX2lkOnQuZmluYWxpemVfc3RhdGVfaWQ/P251bGwsZXhlY3V0aW9uX2lkOnQuZXhlY3V0aW9uX2lkPz9udWxsLGluaXRfb3BhcXVlX2RhdGE6dC5pbml0X29wYXF1ZV9kYXRhPz9udWxsLHN1YnN0cmVhbV9pZDp0LnN1YnN0cmVhbV9pZD8/bnVsbCxvcmRlcl9ieV9jb2x1bW5fbmFtZTp0Lm9yZGVyX2J5X2NvbHVtbl9uYW1lPz9udWxsLG9yZGVyX2J5X2RpcmVjdGlvbjp0Lm9yZGVyX2J5X2RpcmVjdGlvbj8/bnVsbCxvcmRlcl9ieV9udWxsX29yZGVyOnQub3JkZXJfYnlfbnVsbF9vcmRlcj8/bnVsbCxvcmRlcl9ieV9saW1pdDp0Lm9yZGVyX2J5X2xpbWl0Pz9udWxsLHRhYmxlc2FtcGxlX3BlcmNlbnRhZ2U6dC50YWJsZXNhbXBsZV9wZXJjZW50YWdlPz9udWxsLHRhYmxlc2FtcGxlX3NlZWQ6dC50YWJsZXNhbXBsZV9zZWVkPz9udWxsfTtyZXR1cm4gUEkocU4sbil9ZnVuY3Rpb24gSE4odCl7cmV0dXJue2V4ZWN1dGlvbl9pZDpxZCh0LmV4ZWN1dGlvbl9pZCksb3BhcXVlX2RhdGE6dC5vcGFxdWVfZGF0YT9xZCh0Lm9wYXF1ZV9kYXRhKTpudWxsLG1heF93b3JrZXJzOk51bWJlcih0Lm1heF93b3JrZXJzKX19ZnVuY3Rpb24gUXQodCl7cmV0dXJuIHR5cGVvZiB0PT09InN0cmluZyI/W3RdOkFycmF5LmZyb20odCxTdHJpbmcpfWZ1bmN0aW9uIFlOKHQsZSl7cmV0dXJuIHVzKEZvKFtlXSx0KSl9ZnVuY3Rpb24ga2ModCxlKXtsZXQgcj1DYyhlKTtpZihyLm51bVJvd3M9PT0wKXtsZXQgaT10LmZpZWxkcy5tYXAoKHMpPT5zLm5hbWUpLmpvaW4oIiwiKTt0aHJvdyBFcnJvcihgZGVjb2RlQVNEOiBlbXB0eSBiYXRjaCAoZXhwZWN0ZWQgMSByb3cgZm9yICR7aX0pYCl9bGV0IG49e307Zm9yKGxldCBpIG9mIHQuZmllbGRzKXtsZXQgcz1yLmdldENoaWxkKGkubmFtZSksbz1zP3MuZ2V0KDApOm51bGw7bltpLm5hbWVdPUh5KG8saS50eXBlKX1yZXR1cm4gbn1mdW5jdGlvbiBIeSh0LGUpe2lmKHQ9PW51bGwpcmV0dXJuIG51bGw7aWYoJEUoZSkpe2xldCByPWUuY2hpbGRyZW5bMF0udHlwZSxuPVtdO2ZvcihsZXQgaSBvZiB0KW4ucHVzaChIeShpLHIpKTtyZXR1cm4gbn1pZihXRShlKSl7bGV0IHI9e307aWYodFtTeW1ib2wuaXRlcmF0b3JdKXtmb3IobGV0IG4gb2YgdClpZihBcnJheS5pc0FycmF5KG4pKXJbU3RyaW5nKG5bMF0pXT1TdHJpbmcoblsxXT8/IiIpO2Vsc2UgaWYobiYmdHlwZW9mIG49PT0ib2JqZWN0Iil7bGV0IGk9bi5rZXk/P25bMF0scz1uLnZhbHVlPz9uWzFdO3JbU3RyaW5nKGkpXT1zPT1udWxsPyIiOlN0cmluZyhzKX19ZWxzZSBpZih0eXBlb2YgdD09PSJvYmplY3QiKWZvcihsZXRbbixpXW9mIE9iamVjdC5lbnRyaWVzKHQpKXJbU3RyaW5nKG4pXT1pPT1udWxsPyIiOlN0cmluZyhpKTtyZXR1cm4gcn1pZihxRShlKSl7bGV0IHI9ZS5jaGlsZHJlbixuPXt9O2ZvcihsZXQgaSBvZiByKW5baS5uYW1lXT1IeSh0W2kubmFtZV0saS50eXBlKTtyZXR1cm4gbn1pZihIRShlKSlyZXR1cm4gdD09bnVsbD9udWxsOlN0cmluZyh0KTtpZih6RShlKSlyZXR1cm4gS04odCk7aWYoWXkoZSkmJmUuYml0V2lkdGg9PT02NCl7aWYodHlwZW9mIHQ9PT0iYmlnaW50Iil7aWYodD49QmlnSW50KE51bWJlci5NSU5fU0FGRV9JTlRFR0VSKSYmdDw9QmlnSW50KE51bWJlci5NQVhfU0FGRV9JTlRFR0VSKSlyZXR1cm4gTnVtYmVyKHQpO3JldHVybiB0fXJldHVybiB0fWlmKGpFKGUpKXJldHVybiBCb29sZWFuKHQpO3JldHVybiB0fWZ1bmN0aW9uIEtOKHQpe2lmKHQgaW5zdGFuY2VvZiBVaW50OEFycmF5KXJldHVybiB0O2lmKHQgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcilyZXR1cm4gbmV3IFVpbnQ4QXJyYXkodCk7aWYodCYmdC5idWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcilyZXR1cm4gbmV3IFVpbnQ4QXJyYXkodC5idWZmZXIsdC5ieXRlT2Zmc2V0LHQuYnl0ZUxlbmd0aCk7cmV0dXJuIG5ldyBVaW50OEFycmF5KDApfXZhciBHTj1iKFtjKCJuYW1lIixkKCksITEpLGMoImltcGxlbWVudGF0aW9uX3ZlcnNpb24iLGQoKSwhMCksYygiZGF0YV92ZXJzaW9uX3NwZWMiLGQoKSwhMCksYygiYXR0YWNoX29wdGlvbl9zcGVjcyIsdyhjKCJpdGVtIixoKCksITApKSwhMSksYygicmVsZWFzZXMiLHcoYygiaXRlbSIsVmkoW2MoInZlcnNpb24iLGQoKSwhMSksYygicmVsZWFzZWRfYXQiLF9OKHlOLk1JQ1JPU0VDT05ELCJVVEMiKSwhMCksYygic3VtbWFyeSIsZCgpLCExKSxjKCJub3Rlc191cmwiLGQoKSwhMCldKSwhMCkpLCExKSxjKCJzb3VyY2VfdXJsIixkKCksITApXSksSk49YihbYygiY29tbWVudCIsZCgpLCEwKSxjKCJ0YWdzIixrcihjKCJrZXkiLGQoKSwhMSksYygidmFsdWUiLGQoKSwhMCksITEpLCExKSxjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMSksYygicGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMSksYygiZXN0aW1hdGVkX29iamVjdF9jb3VudCIsa3IoYygia2V5IixkKCksITEpLGMoInZhbHVlIixpdCgpLCEwKSwhMSksITApXSksWE49YihbYygiY29tbWVudCIsZCgpLCEwKSxjKCJ0YWdzIixrcihjKCJrZXkiLGQoKSwhMSksYygidmFsdWUiLGQoKSwhMCksITEpLCExKSxjKCJuYW1lIixkKCksITEpLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJjb2x1bW5zIixoKCksITEpLGMoIm5vdF9udWxsX2NvbnN0cmFpbnRzIix3KGMoIml0ZW0iLERhKCksITApKSwhMSksYygidW5pcXVlX2NvbnN0cmFpbnRzIix3KGMoIml0ZW0iLHcoYygiaXRlbSIsRGEoKSwhMCkpLCEwKSksITEpLGMoImNoZWNrX2NvbnN0cmFpbnRzIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJwcmltYXJ5X2tleV9jb25zdHJhaW50cyIsdyhjKCJpdGVtIix3KGMoIml0ZW0iLERhKCksITApKSwhMCkpLCExKSxjKCJmb3JlaWduX2tleV9jb25zdHJhaW50cyIsdyhjKCJpdGVtIixoKCksITApKSwhMSksYygid3JpdGVfcmVzdWx0X21vZGVzIixrcihjKCJrZXkiLGQoKSwhMSksYygidmFsdWUiLGQoKSwhMCksITEpLCExKSxjKCJzdXBwb3J0c19jb2x1bW5fc3RhdGlzdGljcyIsUCgpLCExKSxjKCJzY2FuX2Z1bmN0aW9uIixoKCksITApLGMoImluc2VydF9mdW5jdGlvbiIsaCgpLCEwKSxjKCJ1cGRhdGVfZnVuY3Rpb24iLGgoKSwhMCksYygiZGVsZXRlX2Z1bmN0aW9uIixoKCksITApLGMoImNhcmRpbmFsaXR5X2VzdGltYXRlIixpdCgpLCEwKSxjKCJjYXJkaW5hbGl0eV9tYXgiLGl0KCksITApLGMoImNvbHVtbl9zdGF0aXN0aWNzIixoKCksITApLGMoImJpbmRfcmVzdWx0IixoKCksITApLGMoInJlcXVpcmVkX2ZpbHRlcnMiLHcoYygiaXRlbSIsdyhjKCJpdGVtIixkKCksITApKSwhMCkpLCExKV0pLFpOPWIoW2MoImNvbW1lbnQiLGQoKSwhMCksYygidGFncyIsa3IoYygia2V5IixkKCksITEpLGMoInZhbHVlIixkKCksITApLCExKSwhMSksYygibmFtZSIsZCgpLCExKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMSksYygiZGVmaW5pdGlvbiIsZCgpLCExKSxjKCJjb2x1bW5fY29tbWVudHMiLGtyKGMoImtleSIsZCgpLCExKSxjKCJ2YWx1ZSIsZCgpLCEwKSwhMSksITEpXSksUU49YihbYygiY29tbWVudCIsZCgpLCEwKSxjKCJ0YWdzIixrcihjKCJrZXkiLGQoKSwhMSksYygidmFsdWUiLGQoKSwhMCksITEpLCExKSxjKCJuYW1lIixkKCksITEpLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJmdW5jdGlvbl90eXBlIixlZShkKCksdGUoKSksITEpLGMoImFyZ3VtZW50cyIsaCgpLCExKSxjKCJvdXRwdXRfc2NoZW1hIixoKCksITEpLGMoInBhcmFtZXRlcl9kZWZhdWx0X3ZhbHVlcyIsaCgpLCEwKSxjKCJzdGFiaWxpdHkiLGVlKGQoKSx0ZSgpKSwhMCksYygibnVsbF9oYW5kbGluZyIsZWUoZCgpLHRlKCkpLCEwKSxjKCJhcmd1bWVudF9tb25vdG9uaWNpdHkiLHcoYygiaXRlbSIsZCgpLCEwKSksITApLGMoImRlc2NyaXB0aW9uIixkKCksITEpLGMoImV4YW1wbGVzIix3KGMoIml0ZW0iLFZpKFtjKCJzcWwiLGQoKSwhMSksYygiZGVzY3JpcHRpb24iLGQoKSwhMSksYygiZXhwZWN0ZWRfb3V0cHV0IixkKCksITApXSksITApKSwhMSksYygiY2F0ZWdvcmllcyIsdyhjKCJpdGVtIixkKCksITApKSwhMSksYygicHJvamVjdGlvbl9wdXNoZG93biIsUCgpLCEwKSxjKCJmaWx0ZXJfcHVzaGRvd24iLFAoKSwhMCksYygic2FtcGxpbmdfcHVzaGRvd24iLFAoKSwhMCksYygibGF0ZV9tYXRlcmlhbGl6YXRpb24iLFAoKSwhMCksYygiZmlsdGVyX3NlbWFudGljX3Byb2ZpbGVzIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJhZGRpdGlvbmFsX2ZpbHRlcl9mdW5jdGlvbnMiLHcoYygiaXRlbSIsVmkoW2MoIm5hbWVzcGFjZSIsZCgpLCExKSxjKCJuYW1lIixkKCksITEpLGMoInZlcnNpb24iLG9JKCksITEpXSksITApKSwhMSksYygicnVudGltZV9maWx0ZXJfYWxnb3JpdGhtcyIsdyhjKCJpdGVtIixWaShbYygibmFtZXNwYWNlIixkKCksITEpLGMoIm5hbWUiLGQoKSwhMSksYygidmVyc2lvbiIsb0koKSwhMSldKSwhMCkpLCExKSxjKCJmaWx0ZXJfZXZhbHVhdGlvbl9jb250ZXh0cyIsdyhjKCJpdGVtIixWaShbYygicHJvZmlsZSIsZCgpLCExKSxjKCJwcm92aWRlcl9maW5nZXJwcmludCIsZCgpLCEwKV0pLCEwKSksITEpLGMoIm9yZGVyX3ByZXNlcnZhdGlvbiIsZWUoZCgpLHRlKCkpLCEwKSxjKCJtYXhfd29ya2VycyIsRGEoKSwhMCksYygic3VwcG9ydHNfYmF0Y2hfaW5kZXgiLFAoKSwhMSksYygic3VwcG9ydHNfc3BsaXRzIixQKCksITEpLGMoImZpbHRlcnNfZXhhY3RseV9hcHBsaWVkIixQKCksITEpLGMoInN1cHBvcnRzX3Bvc2l0aW9ucyIsUCgpLCExKSxjKCJzcGxpdF90b2tlbl90dGxfc2Vjb25kcyIsaXQoKSwhMCksYygicGFydGl0aW9uX2tpbmQiLGVlKGQoKSx0ZSgpKSwhMSksYygib3JkZXJfZGVwZW5kZW50IixlZShkKCksdGUoKSksITEpLGMoImRpc3RpbmN0X2RlcGVuZGVudCIsZWUoZCgpLHRlKCkpLCExKSxjKCJzdXBwb3J0c193aW5kb3ciLFAoKSwhMSksYygic3RyZWFtaW5nX3BhcnRpdGlvbmVkIixQKCksITEpLGMoImhhc19maW5hbGl6ZSIsUCgpLCExKSxjKCJzb3VyY2Vfb3JkZXJfZGVwZW5kZW50IixQKCksITEpLGMoInNpbmtfb3JkZXJfZGVwZW5kZW50IixQKCksITEpLGMoInJlcXVpcmVzX2lucHV0X2JhdGNoX2luZGV4IixQKCksITEpLGMoImlucHV0X2Zyb21fYXJncyIsUCgpLCExKSxjKCJyZXF1aXJlZF9zZXR0aW5ncyIsdyhjKCJpdGVtIixkKCksITApKSwhMSksYygicmVxdWlyZWRfc2VjcmV0cyIsdyhjKCJpdGVtIixWaShbYygic2VjcmV0X3R5cGUiLGQoKSwhMSksYygic2NvcGUiLGQoKSwhMCksYygic2VjcmV0X25hbWUiLGQoKSwhMCldKSwhMCkpLCExKV0pLHRGPWIoW2MoImNvbW1lbnQiLGQoKSwhMCksYygidGFncyIsa3IoYygia2V5IixkKCksITEpLGMoInZhbHVlIixkKCksITApLCExKSwhMSksYygibmFtZSIsZCgpLCExKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMSksYygibWFjcm9fdHlwZSIsZWUoZCgpLHRlKCkpLCExKSxjKCJwYXJhbWV0ZXJzIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJwYXJhbWV0ZXJfZGVmYXVsdF92YWx1ZXMiLGgoKSwhMCksYygiZGVmaW5pdGlvbiIsZCgpLCExKSxjKCJhcmd1bWVudHNfc2NoZW1hIixoKCksITApXSksYXo9YihbYygiY29tbWVudCIsZCgpLCEwKSxjKCJ0YWdzIixrcihjKCJrZXkiLGQoKSwhMSksYygidmFsdWUiLGQoKSwhMCksITEpLCExKSxjKCJuYW1lIixkKCksITEpLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJ0YWJsZV9uYW1lIixkKCksITEpLGMoImluZGV4X3R5cGUiLGQoKSwhMSksYygiY29uc3RyYWludF90eXBlIixlZShkKCksdGUoKSksITEpLGMoImV4cHJlc3Npb25zIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJvcHRpb25zIixrcihjKCJrZXkiLGQoKSwhMSksYygidmFsdWUiLGQoKSwhMCksITEpLCExKV0pLGN6PWIoW2MoImNvbW1lbnQiLGQoKSwhMCksYygidGFncyIsa3IoYygia2V5IixkKCksITEpLGMoInZhbHVlIixkKCksITApLCExKSwhMSksYygiZm9ybWF0X25hbWUiLGQoKSwhMSksYygiaGFuZGxlciIsZCgpLCExKSxjKCJvcHRpb25zIixoKCksITEpLGMoImRpcmVjdGlvbiIsZCgpLCExKSxjKCJkZXNjcmlwdGlvbiIsZCgpLCExKSxjKCJvcmRlcmVkIixQKCksITEpXSksbHo9YihbYygiZnVuY3Rpb25fbmFtZSIsZCgpLCExKSxjKCJhcmd1bWVudHMiLGgoKSwhMSksYygicmVxdWlyZWRfZXh0ZW5zaW9ucyIsdyhjKCJpdGVtIixkKCksITApKSwhMSksYygic2NoZW1hX3BhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITApXSksdXo9YihbYygiYnJhbmNoZXMiLHcoYygiaXRlbSIsaCgpLCEwKSksITEpLGMoInJlcXVpcmVkX2V4dGVuc2lvbnMiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpXSksZno9YihbYygiZnVuY3Rpb25fbmFtZSIsZCgpLCExKSxjKCJhcmd1bWVudHMiLGgoKSwhMSksYygiYnJhbmNoX2ZpbHRlciIsZCgpLCEwKSxjKCJ3cml0YWJsZSIsUCgpLCExKSxjKCJzb3VyY2VfY2F0YWxvZyIsZCgpLCEwKSxjKCJzb3VyY2Vfc2NoZW1hX3BhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITApLGMoInNvdXJjZV90YWJsZSIsZCgpLCEwKSxjKCJmb3JtYXRfbmFtZSIsZCgpLCEwKSxjKCJmb3JtYXRfbG9jYXRpb25zIix3KGMoIml0ZW0iLGQoKSwhMCkpLCEwKSxjKCJmb3JtYXRfb3B0aW9ucyIsaCgpLCEwKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMCldKSxkej1iKFtjKCJwYXlsb2FkIixoKCksITEpLGMoInRva2VuIixoKCksITEpLGMoImVzdGltYXRlZF9yb3dzIixpdCgpLCEwKSxjKCJyb3dzX2V4YWN0IixQKCksITEpLGMoImVzdGltYXRlZF9ieXRlcyIsaXQoKSwhMCksYygicGFydGl0aW9uX2JvdW5kcyIsaCgpLCEwKSxjKCJjb2x1bW5fc3RhdGlzdGljcyIsaCgpLCEwKSxjKCJsb2NhdGlvbl9pZHMiLHcoYygiaXRlbSIsaXQoKSwhMCkpLCEwKSxjKCJzdGFydF9wb3NpdGlvbiIsaCgpLCEwKSxjKCJlbmRfcG9zaXRpb24iLGgoKSwhMCldKSxoej1iKFtjKCJhbGlhcyIsZCgpLCExKSxjKCJ0YXJnZXQiLGQoKSwhMSksYygiZGJfdHlwZSIsZCgpLCExKSxjKCJvcHRpb25zIixrcihjKCJrZXkiLGQoKSwhMSksYygidmFsdWUiLGQoKSwhMCksITEpLCExKSxjKCJoaWRkZW4iLFAoKSwhMSksYygicmVxdWlyZWQiLFAoKSwhMSksYygic2VjcmV0X3JlZiIsZCgpLCExKV0pLHB6PWIoW2MoImZrX2NvbHVtbnMiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoInBrX2NvbHVtbnMiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoInJlZmVyZW5jZWRfdGFibGUiLGQoKSwhMSksYygicmVmZXJlbmNlZF9zY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMSldKSxtej1iKFtjKCJmdW5jdGlvbl9uYW1lIixkKCksITEpLGMoImFyZ3VtZW50cyIsaCgpLCExKSxjKCJpbnB1dF9zY2hlbWEiLGgoKSwhMCksYygic2V0dGluZ3MiLGgoKSwhMCksYygic2VjcmV0cyIsaCgpLCEwKSxjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMCksYygic2NoZW1hX3BhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITApLGMoImFyZ3VtZW50X25hbWVzIix3KGMoIml0ZW0iLGQoKSwhMCkpLCEwKV0pLHl6PWIoW2MoImZ1bmN0aW9uX25hbWUiLGQoKSwhMSksYygiZXhlY3V0aW9uX2lkIixoKCksITEpLGMoIm1lcmdlX2JhdGNoIixoKCksITEpLGMoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCEwKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMCldKSxfej1iKFtjKCJmdW5jdGlvbl9uYW1lIixkKCksITEpLGMoImV4ZWN1dGlvbl9pZCIsaCgpLCExKSxjKCJncm91cF9pZHNfYmF0Y2giLGgoKSwhMSksYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITApLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCEwKV0pLGd6PWIoW2MoImZ1bmN0aW9uX25hbWUiLGQoKSwhMSksYygiZXhlY3V0aW9uX2lkIixoKCksITEpLGMoImdyb3VwX2lkc19iYXRjaCIsaCgpLCExKSxjKCJvdXRwdXRfc2NoZW1hIixoKCksITEpLGMoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCEwKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMCldKSxiej1iKFtjKCJmdW5jdGlvbl9uYW1lIixkKCksITEpLGMoImV4ZWN1dGlvbl9pZCIsaCgpLCExKSxjKCJpbnB1dF9iYXRjaCIsaCgpLCExKSxjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMCksYygic2NoZW1hX3BhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITApXSksd3o9YihbYygiZnVuY3Rpb25fbmFtZSIsZCgpLCExKSxjKCJleGVjdXRpb25faWQiLGgoKSwhMSksYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITApLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCEwKV0pLHZ6PWIoW2MoImZ1bmN0aW9uX25hbWUiLGQoKSwhMSksYygiYXJndW1lbnRzIixoKCksITEpLGMoImlucHV0X3NjaGVtYSIsaCgpLCExKSxjKCJwYXJ0aXRpb25fa2V5X2NvdW50IixpdCgpLCExKSxjKCJvcmRlcl9rZXlfY291bnQiLGl0KCksITEpLGMoIm91dHB1dF9zY2hlbWEiLGgoKSwhMSksYygic2V0dGluZ3MiLGgoKSwhMCksYygic2VjcmV0cyIsaCgpLCEwKSxjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMCksYygic2NoZW1hX3BhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITApXSksSXo9YihbYygiZnVuY3Rpb25fbmFtZSIsZCgpLCExKSxjKCJleGVjdXRpb25faWQiLGgoKSwhMSksYygiaW5wdXRfYmF0Y2giLGgoKSwhMSksYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITApLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCEwKV0pLEJ6PWIoW2MoImZ1bmN0aW9uX25hbWUiLGQoKSwhMSksYygiZXhlY3V0aW9uX2lkIixoKCksITEpLGMoInBhcnRpdGlvbl9pZCIsaXQoKSwhMSksYygicm93X2lkeCIsaXQoKSwhMSksYygiY291bnQiLGl0KCksITEpLGMoImZyYW1lc19wZXJfcm93Iix3KGMoIml0ZW0iLGl0KCksITApKSwhMSksYygiZnJhbWVfc3RhcnRzIix3KGMoIml0ZW0iLGl0KCksITApKSwhMSksYygiZnJhbWVfZW5kcyIsdyhjKCJpdGVtIixpdCgpLCEwKSksITEpLGMoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCEwKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMCldKSxTej1iKFtjKCJmdW5jdGlvbl9uYW1lIixkKCksITEpLGMoImV4ZWN1dGlvbl9pZCIsaCgpLCExKSxjKCJwYXJ0aXRpb25faWQiLGl0KCksITEpLGMoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCEwKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMCldKSxBej1iKFtjKCJmdW5jdGlvbl9uYW1lIixkKCksITEpLGMoImV4ZWN1dGlvbl9pZCIsaCgpLCExKSxjKCJwYXJ0aXRpb25faWQiLGl0KCksITEpLGMoInJvd19jb3VudCIsaXQoKSwhMSksYygicGFydGl0aW9uX2JhdGNoIixoKCksITEpLGMoIm91dHB1dF9zY2hlbWEiLGgoKSwhMSksYygiZmlsdGVyX21hc2siLGgoKSwhMSksYygiZnJhbWVfc3RhdHMiLGgoKSwhMSksYygiYWxsX3ZhbGlkIixoKCksITEpLGMoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCEwKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMCldKSxEej1iKFtjKCJmdW5jdGlvbl9uYW1lIixkKCksITEpLGMoImV4ZWN1dGlvbl9pZCIsaCgpLCExKSxjKCJwYXJ0aXRpb25faWQiLGl0KCksITEpLGMoInJpZCIsaXQoKSwhMSksYygiZnJhbWVfc3RhcnRzIix3KGMoIml0ZW0iLGl0KCksITApKSwhMSksYygiZnJhbWVfZW5kcyIsdyhjKCJpdGVtIixpdCgpLCEwKSksITEpLGMoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCEwKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMCldKSx4ej1iKFtjKCJmdW5jdGlvbl9uYW1lIixkKCksITEpLGMoImFyZ3VtZW50cyIsaCgpLCExKSxjKCJmdW5jdGlvbl90eXBlIixlZShkKCksdGUoKSksITEpLGMoImlucHV0X3NjaGVtYSIsaCgpLCEwKSxjKCJzZXR0aW5ncyIsaCgpLCEwKSxjKCJzZWNyZXRzIixoKCksITApLGMoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCEwKSxjKCJ0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YSIsaCgpLCEwKSxjKCJyZXNvbHZlZF9zZWNyZXRzX3Byb3ZpZGVkIixQKCksITEpLGMoImF0X3VuaXQiLGQoKSwhMCksYygiYXRfdmFsdWUiLGQoKSwhMCksYygiY29weV9mcm9tIixWaShbYygiZm9ybWF0IixkKCksITEpLGMoImZpbGVfcGF0aCIsZCgpLCExKSxjKCJleHBlY3RlZF9zY2hlbWEiLGgoKSwhMSldKSwhMCksYygiY29weV90byIsVmkoW2MoImZvcm1hdCIsZCgpLCExKSxjKCJmaWxlX3BhdGgiLGQoKSwhMSldKSwhMCksYygic2NoZW1hX3BhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITApLGMoImFyZ3VtZW50X25hbWVzIix3KGMoIml0ZW0iLGQoKSwhMCkpLCEwKV0pLFR6PWIoW2MoIm5hbWUiLGQoKSwhMSksYygib3B0aW9ucyIsaCgpLCEwKSxjKCJkYXRhX3ZlcnNpb25fc3BlYyIsZCgpLCEwKSxjKCJpbXBsZW1lbnRhdGlvbl92ZXJzaW9uIixkKCksITApLGMoImNsaWVudF9jYXBhYmlsaXRpZXMiLGgoKSwhMCldKSxFej1iKFtjKCJuYW1lIixkKCksITEpLGMoIm9uX2NvbmZsaWN0IixlZShkKCksdGUoKSksITEpLGMoIm9wdGlvbnMiLGgoKSwhMCldKSxlRj1iKFtjKCJlbmdpbmUiLGQoKSwhMSksYygibmF0aXZlX2Zvcm1hdHMiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoImNhdGFsb2dzIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJjYW5fc3RyZWFtIixQKCksITEpLGMoImZpbHRlcl9lbmNvZGluZ3MiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpXSksT3o9YihbYygiZm9ybWF0IixkKCksITEpLGMoImZpbGVfcGF0aCIsZCgpLCExKSxjKCJleHBlY3RlZF9zY2hlbWEiLGgoKSwhMSldKSxOej1iKFtjKCJmb3JtYXQiLGQoKSwhMSksYygiZmlsZV9wYXRoIixkKCksITEpXSksRno9YihbYygiZXhlY3V0aW9uX2lkIixoKCksITEpLGMoIm9wYXF1ZV9kYXRhIixoKCksITApLGMoIm1heF93b3JrZXJzIixpdCgpLCExKV0pLE16PWIoW2MoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCExKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMSksYygibmFtZSIsZCgpLCExKSxjKCJ0YWJsZV9uYW1lIixkKCksITEpLGMoImluZGV4X3R5cGUiLGQoKSwhMSksYygiY29uc3RyYWludF90eXBlIixlZShkKCksdGUoKSksITEpLGMoImV4cHJlc3Npb25zIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJvbl9jb25mbGljdCIsZWUoZCgpLHRlKCkpLCExKSxjKCJvcHRpb25zIixrcihjKCJrZXkiLGQoKSwhMSksYygidmFsdWUiLGQoKSwhMCksITEpLCExKSxjKCJ0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YSIsaCgpLCEwKV0pLEx6PWIoW2MoImJpbmRfY2FsbCIsaCgpLCExKSxjKCJvdXRwdXRfc2NoZW1hIixoKCksITEpLGMoImJpbmRfb3BhcXVlX2RhdGEiLGgoKSwhMCksYygicHJvamVjdGlvbl9pZHMiLHcoYygiaXRlbSIsaXQoKSwhMCkpLCEwKSxjKCJwdXNoZG93bl9maWx0ZXJzIixMcygpLCEwKSxjKCJqb2luX2tleXMiLHcoYygiaXRlbSIsTHMoKSwhMCkpLCEwKSxjKCJzcGxpdF90b2tlbnMiLHcoYygiaXRlbSIsTHMoKSwhMCkpLCEwKSxjKCJyb3dfbGltaXQiLGl0KCksITApLGMoInBoYXNlIixlZShkKCksdGUoKSksITApLGMoImZpbmFsaXplX3N0YXRlX2lkIixoKCksITApLGMoImV4ZWN1dGlvbl9pZCIsaCgpLCEwKSxjKCJpbml0X29wYXF1ZV9kYXRhIixoKCksITApLGMoInN1YnN0cmVhbV9pZCIsaCgpLCEwKSxjKCJvcmRlcl9ieV9jb2x1bW5fbmFtZSIsZCgpLCEwKSxjKCJvcmRlcl9ieV9kaXJlY3Rpb24iLGVlKGQoKSx0ZSgpKSwhMCksYygib3JkZXJfYnlfbnVsbF9vcmRlciIsZWUoZCgpLHRlKCkpLCEwKSxjKCJvcmRlcl9ieV9saW1pdCIsaXQoKSwhMCksYygidGFibGVzYW1wbGVfcGVyY2VudGFnZSIsS2QoKSwhMCksYygidGFibGVzYW1wbGVfc2VlZCIsaXQoKSwhMCldKSxyRj1iKFtjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMSksYygic2NoZW1hX3BhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoIm5hbWUiLGQoKSwhMSksYygibWFjcm9fdHlwZSIsZWUoZCgpLHRlKCkpLCExKSxjKCJwYXJhbWV0ZXJzIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJkZWZpbml0aW9uIixkKCksITEpLGMoIm9uX2NvbmZsaWN0IixlZShkKCksdGUoKSksITEpLGMoInBhcmFtZXRlcl9kZWZhdWx0X3ZhbHVlcyIsaCgpLCEwKSxjKCJhcmd1bWVudHNfc2NoZW1hIixoKCksITApLGMoInRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhIixoKCksITApXSksVXo9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJuYW1lIixkKCksITEpLGMoImNvbHVtbnMiLGgoKSwhMSksYygib25fY29uZmxpY3QiLGVlKGQoKSx0ZSgpKSwhMSksYygibm90X251bGxfY29uc3RyYWludHMiLHcoYygiaXRlbSIsRGEoKSwhMCkpLCExKSxjKCJ1bmlxdWVfY29uc3RyYWludHMiLHcoYygiaXRlbSIsdyhjKCJpdGVtIixEYSgpLCEwKSksITApKSwhMSksYygiY2hlY2tfY29uc3RyYWludHMiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoInByaW1hcnlfa2V5X2NvbnN0cmFpbnRzIix3KGMoIml0ZW0iLHcoYygiaXRlbSIsRGEoKSwhMCkpLCEwKSksITEpLGMoImZvcmVpZ25fa2V5X2NvbnN0cmFpbnRzIix3KGMoIml0ZW0iLGgoKSwhMCkpLCExKSxjKCJ0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YSIsaCgpLCEwKV0pLFJ6PWIoW2MoImZ1bmN0aW9uX25hbWUiLGQoKSwhMSksYygiZXhlY3V0aW9uX2lkIixoKCksITEpLGMoInN0YXRlX2lkcyIsdyhjKCJpdGVtIixoKCksITApKSwhMSksYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITApLGMoInRyYW5zYWN0aW9uX2lkIixoKCksITApLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCEwKV0pLEN6PWIoW2MoImZ1bmN0aW9uX25hbWUiLGQoKSwhMSksYygiZXhlY3V0aW9uX2lkIixoKCksITEpLGMoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCEwKSxjKCJ0cmFuc2FjdGlvbl9pZCIsaCgpLCEwKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMCldKSxQej1iKFtjKCJmdW5jdGlvbl9uYW1lIixkKCksITEpLGMoImV4ZWN1dGlvbl9pZCIsaCgpLCExKSxjKCJpbnB1dF9iYXRjaCIsaCgpLCExKSxjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMCksYygidHJhbnNhY3Rpb25faWQiLGgoKSwhMCksYygiYmF0Y2hfaW5kZXgiLGl0KCksITApLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCEwKV0pLGt6PWIoW2MoImJpbmRfY2FsbCIsaCgpLCExKSxjKCJiaW5kX29wYXF1ZV9kYXRhIixoKCksITApXSksVno9YihbYygiYmluZF9jYWxsIixoKCksITEpLGMoImJpbmRfb3BhcXVlX2RhdGEiLGgoKSwhMCksYygiZ2xvYmFsX2V4ZWN1dGlvbl9pZCIsaCgpLCExKV0pLHp6PWIoW2MoImJpbmRfY2FsbCIsaCgpLCExKSxjKCJiaW5kX29wYXF1ZV9kYXRhIixoKCksITApLGMoInByb2plY3Rpb25faWRzIix3KGMoIml0ZW0iLGl0KCksITApKSwhMCksYygicHVzaGRvd25fZmlsdGVycyIsTHMoKSwhMCksYygiam9pbl9rZXlzIix3KGMoIml0ZW0iLExzKCksITApKSwhMCksYygicm93X2xpbWl0IixpdCgpLCEwKSxjKCJ0YXJnZXRfc3BsaXRfYnl0ZXMiLGl0KCksITApLGMoIm1pbl9zcGxpdHMiLGl0KCksITApLGMoIm1heF9zcGxpdHNfcGVyX3Jlc3BvbnNlIixpdCgpLCEwKSxjKCJjdXJzb3IiLGgoKSwhMCksYygicmVmaW5lZF9maWx0ZXJzIixMcygpLCEwKSxjKCJmaWx0ZXJzX2NvbXBsZXRlIixQKCksITEpLGMoInN0YXJ0X3Bvc2l0aW9uIixoKCksITApLGMoImVuZF9wb3NpdGlvbiIsaCgpLCEwKSxjKCJvcmRlcl9ieV9jb2x1bW5fbmFtZSIsZCgpLCEwKSxjKCJvcmRlcl9ieV9kaXJlY3Rpb24iLGVlKGQoKSx0ZSgpKSwhMCksYygib3JkZXJfYnlfbnVsbF9vcmRlciIsZWUoZCgpLHRlKCkpLCEwKSxjKCJvcmRlcl9ieV9saW1pdCIsaXQoKSwhMCksYygidGFibGVzYW1wbGVfcGVyY2VudGFnZSIsS2QoKSwhMCksYygidGFibGVzYW1wbGVfc2VlZCIsaXQoKSwhMCldKSxqej1iKFtjKCJiaW5kX2NhbGwiLGgoKSwhMSksYygiYmluZF9vcGFxdWVfZGF0YSIsaCgpLCEwKV0pLCR6PWIoW2MoIm91dHB1dF9zY2hlbWEiLGgoKSwhMSksYygiZXhlY3V0aW9uX2lkIixoKCksITEpXSkscXo9YihbXSksV3o9YihbXSksSHo9YihbYygicmVzdWx0X2JhdGNoIixoKCksITEpXSksWXo9YihbYygicmVzdWx0X2JhdGNoIixoKCksITEpXSksS3o9YihbXSksR3o9YihbYygiZXhlY3V0aW9uX2lkIixoKCksITEpXSksSno9YihbXSksWHo9YihbYygicmVzdWx0X2JhdGNoIixoKCksITEpXSksWno9YihbYygicmVzdWx0X2JhdGNoIixoKCksITEpXSksUXo9YihbXSksdGo9YihbXSksZWo9YihbYygib3V0cHV0X3NjaGVtYSIsaCgpLCExKSxjKCJvcGFxdWVfZGF0YSIsaCgpLCEwKSxjKCJsb29rdXBfc2VjcmV0X3R5cGVzIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJsb29rdXBfc2NvcGVzIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJsb29rdXBfbmFtZXMiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpXSkscmo9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInN1cHBvcnRzX3RyYW5zYWN0aW9ucyIsUCgpLCExKSxjKCJzdXBwb3J0c190aW1lX3RyYXZlbCIsUCgpLCExKSxjKCJjYXRhbG9nX3ZlcnNpb25fZnJvemVuIixQKCksITEpLGMoImNhdGFsb2dfdmVyc2lvbiIsaXQoKSwhMSksYygiYXR0YWNoX29wYXF1ZV9kYXRhX3JlcXVpcmVkIixQKCksITEpLGMoImRlZmF1bHRfc2NoZW1hIixkKCksITEpLGMoInNldHRpbmdzIix3KGMoIml0ZW0iLGgoKSwhMCkpLCExKSxjKCJzZWNyZXRfdHlwZXMiLHcoYygiaXRlbSIsaCgpLCEwKSksITEpLGMoImF0dGFjaF9jYXRhbG9ncyIsdyhjKCJpdGVtIixoKCksITApKSwhMSksYygiY29tbWVudCIsZCgpLCEwKSxjKCJ0YWdzIixrcihjKCJrZXkiLGQoKSwhMSksYygidmFsdWUiLGQoKSwhMCksITEpLCExKSxjKCJzdXBwb3J0c19jb2x1bW5fc3RhdGlzdGljcyIsUCgpLCExKSxjKCJnbG9iYWxfZnVuY3Rpb25zIix3KGMoIml0ZW0iLGgoKSwhMCkpLCExKSxjKCJnbG9iYWxfZnVuY3Rpb25fcHJlZml4IixkKCksITEpLGMoInJlc29sdmVkX2RhdGFfdmVyc2lvbiIsZCgpLCEwKSxjKCJyZXNvbHZlZF9pbXBsZW1lbnRhdGlvbl92ZXJzaW9uIixkKCksITApXSksbmo9YihbYygiaXRlbXMiLHcoYygiaXRlbSIsaCgpLCEwKSksITEpXSksaWo9YihbYygiaXRlbXMiLHcoYygiaXRlbSIsaCgpLCEwKSksITEpXSksc2o9YihbYygiaXRlbXMiLHcoYygiaXRlbSIsaCgpLCEwKSksITEpXSksb2o9YihbYygiaXRlbXMiLHcoYygiaXRlbSIsaCgpLCEwKSksITEpXSksYWo9YihbYygiaXRlbXMiLHcoYygiaXRlbSIsaCgpLCEwKSksITEpXSksY2o9YihbYygiaXRlbXMiLHcoYygiaXRlbSIsaCgpLCEwKSksITEpXSksbGo9YihbYygiaXRlbXMiLHcoYygiaXRlbSIsaCgpLCEwKSksITEpXSksdWo9YihbYygiaXRlbXMiLHcoYygiaXRlbSIsaCgpLCEwKSksITEpXSksZmo9YihbYygiaXRlbXMiLHcoYygiaXRlbSIsaCgpLCEwKSksITEpXSksZGo9YihbYygiaXRlbXMiLHcoYygiaXRlbSIsaCgpLCEwKSksITEpXSksaGo9YihbYygiaXRlbXMiLHcoYygiaXRlbSIsaCgpLCEwKSksITEpXSkscGo9YihbYygiaXRlbXMiLHcoYygiaXRlbSIsaCgpLCEwKSksITEpXSksbWo9YihbYygidHJhbnNhY3Rpb25fb3BhcXVlX2RhdGEiLGgoKSwhMCldKSx5aj1iKFtjKCJ2ZXJzaW9uIixpdCgpLCExKV0pLF9qPWIoW2MoIml0ZW1zIix3KGMoIml0ZW0iLGgoKSwhMCkpLCExKV0pLGdqPWIoW2MoImZpbmFsaXplX3N0YXRlX2lkcyIsdyhjKCJpdGVtIixoKCksITApKSwhMSldKSxiaj1iKFtdKSx3aj1iKFtjKCJzdGF0ZV9pZCIsaCgpLCExKV0pLHZqPWIoW2MoImVzdGltYXRlIixpdCgpLCEwKSxjKCJtYXgiLGl0KCksITApXSksSWo9YihbYygia2V5cyIsdyhjKCJpdGVtIixkKCksITApKSwhMSksYygidmFsdWVzIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKV0pLEJqPWIoW2MoInNwbGl0cyIsdyhjKCJpdGVtIixoKCksITApKSwhMSksYygibmV4dF9jdXJzb3JzIix3KGMoIml0ZW0iLGgoKSwhMCkpLCEwKSxjKCJleGVjdXRpb25faWQiLGgoKSwhMCksYygiaW5pdF9vcGFxdWVfZGF0YSIsaCgpLCEwKSxjKCJtYXhfd29ya2VycyIsaXQoKSwhMCksYygiZXN0aW1hdGVkX3RvdGFsX3NwbGl0cyIsaXQoKSwhMCksYygiZXN0aW1hdGVkX3RvdGFsX3Jvd3MiLGl0KCksITApLGMoImVzdGltYXRlZF90b3RhbF9ieXRlcyIsaXQoKSwhMCksYygiY2F0YWxvZ192ZXJzaW9uIixpdCgpLCEwKSxjKCJzY29wZSIsZCgpLCExKSxjKCJsb2NhdGlvbnMiLHcoYygiaXRlbSIsZCgpLCEwKSksITApLGMoInBhcnRpdGlvbmluZyIsdyhjKCJpdGVtIixoKCksITApKSwhMCksYygic29ydF9vcmRlciIsdyhjKCJpdGVtIixoKCksITApKSwhMCksYygiY2FjaGVfbWF4X2FnZV9zZWNvbmRzIixpdCgpLCEwKSxjKCJzdGFydF9wb3NpdGlvbiIsaCgpLCEwKSxjKCJlbmRfcG9zaXRpb24iLGgoKSwhMCldKSxTaj1iKFtjKCJyZXF1ZXN0IixoKCksITEpXSksQWo9YihbYygicmVxdWVzdCIsaCgpLCExKV0pLERqPWIoW2MoInJlcXVlc3QiLGgoKSwhMSldKSx4aj1iKFtjKCJyZXF1ZXN0IixoKCksITEpXSksVGo9YihbYygicmVxdWVzdCIsaCgpLCExKV0pLEVqPWIoW2MoInJlcXVlc3QiLGgoKSwhMSldKSxPaj1iKFtjKCJyZXF1ZXN0IixoKCksITEpXSksTmo9YihbYygicmVxdWVzdCIsaCgpLCExKV0pLEZqPWIoW2MoInJlcXVlc3QiLGgoKSwhMSldKSxNaj1iKFtjKCJyZXF1ZXN0IixoKCksITEpXSksTGo9YihbYygicmVxdWVzdCIsaCgpLCExKV0pLFVqPWIoW2MoInJlcXVlc3QiLGgoKSwhMSldKSxSaj1iKFtjKCJyZXF1ZXN0IixoKCksITEpXSksQ2o9YihbYygicmVxdWVzdCIsaCgpLCExKV0pLFBqPWIoW10pLGtqPWIoW2MoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCExKSxjKCJ0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YSIsaCgpLCEwKV0pLFZqPWIoW2MoInJlcXVlc3QiLGgoKSwhMSldKSx6aj1iKFtjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMSldKSxqaj1iKFtjKCJuYW1lIixkKCksITEpXSksJGo9YihbYygicmVxdWVzdCIsaCgpLCExKV0pLHFqPWIoW2MoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCExKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMSksYygibmFtZSIsZCgpLCExKSxjKCJpZ25vcmVfbm90X2ZvdW5kIixQKCksITEpLGMoImNhc2NhZGUiLFAoKSwhMSksYygidHJhbnNhY3Rpb25fb3BhcXVlX2RhdGEiLGgoKSwhMCldKSxXaj1iKFtjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMSksYygic2NoZW1hX3BhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoIm5hbWUiLGQoKSwhMSksYygidHJhbnNhY3Rpb25fb3BhcXVlX2RhdGEiLGgoKSwhMCldKSxIaj1iKFtjKCJyZXF1ZXN0IixoKCksITEpXSksWWo9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJuYW1lIixkKCksITEpLGMoImlnbm9yZV9ub3RfZm91bmQiLFAoKSwhMSksYygidHJhbnNhY3Rpb25fb3BhcXVlX2RhdGEiLGgoKSwhMCldKSxLaj1iKFtjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMSksYygic2NoZW1hX3BhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoIm5hbWUiLGQoKSwhMSksYygidHJhbnNhY3Rpb25fb3BhcXVlX2RhdGEiLGgoKSwhMCldKSxHaj1iKFtjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMSksYygicGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMSksYygidHlwZSIsZWUoZCgpLHRlKCkpLCExKSxjKCJ0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YSIsaCgpLCEwKV0pLEpqPWIoW2MoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCExKSxjKCJwYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJ0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YSIsaCgpLCEwKV0pLFhqPWIoW2MoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCExKSxjKCJwYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJ0eXBlIixlZShkKCksdGUoKSksITEpLGMoInRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhIixoKCksITApXSksWmo9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInBhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoInRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhIixoKCksITApXSksUWo9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInBhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoInRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhIixoKCksITApXSksdCQ9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInBhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoIm9uX2NvbmZsaWN0IixlZShkKCksdGUoKSksITEpLGMoImNvbW1lbnQiLGQoKSwhMCksYygidGFncyIsa3IoYygia2V5IixkKCksITEpLGMoInZhbHVlIixkKCksITApLCExKSwhMCksYygidHJhbnNhY3Rpb25fb3BhcXVlX2RhdGEiLGgoKSwhMCldKSxlJD1iKFtjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMSksYygicGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMSksYygiaWdub3JlX25vdF9mb3VuZCIsUCgpLCExKSxjKCJjYXNjYWRlIixQKCksITEpLGMoInRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhIixoKCksITApXSksciQ9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInBhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoInRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhIixoKCksITApXSksbiQ9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhIixoKCksITApXSksaSQ9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJuYW1lIixkKCksITEpLGMoImNvbHVtbl9kZWZpbml0aW9uIixoKCksITEpLGMoImlnbm9yZV9ub3RfZm91bmQiLFAoKSwhMSksYygiaWZfY29sdW1uX25vdF9leGlzdHMiLFAoKSwhMSksYygidHJhbnNhY3Rpb25fb3BhcXVlX2RhdGEiLGgoKSwhMCldKSxzJD1iKFtjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMSksYygic2NoZW1hX3BhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoIm5hbWUiLGQoKSwhMSksYygiY29sdW1uX25hbWUiLGQoKSwhMSksYygiY29tbWVudCIsZCgpLCEwKSxjKCJpZ25vcmVfbm90X2ZvdW5kIixQKCksITEpLGMoInRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhIixoKCksITApXSksbyQ9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJuYW1lIixkKCksITEpLGMoImNvbHVtbl9uYW1lIixkKCksITEpLGMoImlnbm9yZV9ub3RfZm91bmQiLFAoKSwhMSksYygidHJhbnNhY3Rpb25fb3BhcXVlX2RhdGEiLGgoKSwhMCldKSxhJD1iKFtjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMSksYygic2NoZW1hX3BhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoIm5hbWUiLGQoKSwhMSksYygiY29sdW1uX25hbWUiLGQoKSwhMSksYygiZXhwcmVzc2lvbiIsZCgpLCExKSxjKCJpZ25vcmVfbm90X2ZvdW5kIixQKCksITEpLGMoInRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhIixoKCksITApXSksYyQ9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJuYW1lIixkKCksITEpLGMoImNvbHVtbl9uYW1lIixkKCksITEpLGMoImlnbm9yZV9ub3RfZm91bmQiLFAoKSwhMSksYygiaWZfY29sdW1uX2V4aXN0cyIsUCgpLCExKSxjKCJjYXNjYWRlIixQKCksITEpLGMoInRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhIixoKCksITApXSksbCQ9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJuYW1lIixkKCksITEpLGMoImNvbHVtbl9uYW1lIixkKCksITEpLGMoIm5ld19jb2x1bW5fbmFtZSIsZCgpLCExKSxjKCJpZ25vcmVfbm90X2ZvdW5kIixQKCksITEpLGMoInRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhIixoKCksITApXSksdSQ9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJuYW1lIixkKCksITEpLGMoInRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhIixoKCksITApXSksZiQ9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJuYW1lIixkKCksITEpLGMoImNvbHVtbl9kZWZpbml0aW9uIixoKCksITEpLGMoImV4cHJlc3Npb24iLGQoKSwhMCksYygiaWdub3JlX25vdF9mb3VuZCIsUCgpLCExKSxjKCJ0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YSIsaCgpLCEwKV0pLGQkPWIoW2MoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCExKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMSksYygibmFtZSIsZCgpLCExKSxjKCJjb21tZW50IixkKCksITApLGMoImlnbm9yZV9ub3RfZm91bmQiLFAoKSwhMSksYygidHJhbnNhY3Rpb25fb3BhcXVlX2RhdGEiLGgoKSwhMCldKSxoJD1iKFtjKCJyZXF1ZXN0IixoKCksITEpXSkscCQ9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJuYW1lIixkKCksITEpLGMoInRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhIixoKCksITApXSksbSQ9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJuYW1lIixkKCksITEpLGMoImlnbm9yZV9ub3RfZm91bmQiLFAoKSwhMSksYygiY2FzY2FkZSIsUCgpLCExKSxjKCJ0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YSIsaCgpLCEwKV0pLHkkPWIoW2MoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCExKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMSksYygibmFtZSIsZCgpLCExKSxjKCJhdF91bml0IixkKCksITApLGMoImF0X3ZhbHVlIixkKCksITApLGMoInRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhIixoKCksITApXSksXyQ9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJuYW1lIixkKCksITEpLGMoInRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhIixoKCksITApLGMoIndyaXRhYmxlX2JyYW5jaF9mdW5jdGlvbl9uYW1lIixkKCksITApXSksZyQ9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJuYW1lIixkKCksITEpLGMoImNvbHVtbl9uYW1lIixkKCksITEpLGMoImlnbm9yZV9ub3RfZm91bmQiLFAoKSwhMSksYygidHJhbnNhY3Rpb25fb3BhcXVlX2RhdGEiLGgoKSwhMCldKSxiJD1iKFtjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMSksYygic2NoZW1hX3BhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoIm5hbWUiLGQoKSwhMSksYygiY29sdW1uX25hbWUiLGQoKSwhMSksYygiaWdub3JlX25vdF9mb3VuZCIsUCgpLCExKSxjKCJ0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YSIsaCgpLCEwKV0pLHckPWIoW2MoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCExKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMSksYygibmFtZSIsZCgpLCExKSxjKCJuZXdfbmFtZSIsZCgpLCExKSxjKCJpZ25vcmVfbm90X2ZvdW5kIixQKCksITEpLGMoInRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhIixoKCksITApXSksdiQ9YihbYygiYXR0YWNoX29wYXF1ZV9kYXRhIixoKCksITEpLGMoInNjaGVtYV9wYXRoIix3KGMoIml0ZW0iLGQoKSwhMCkpLCExKSxjKCJuYW1lIixkKCksITEpLGMoImF0X3VuaXQiLGQoKSwhMCksYygiYXRfdmFsdWUiLGQoKSwhMCksYygidHJhbnNhY3Rpb25fb3BhcXVlX2RhdGEiLGgoKSwhMCldKSxJJD1iKFtjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMSksYygic2NoZW1hX3BhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoIm5hbWUiLGQoKSwhMSksYygiYXRfdW5pdCIsZCgpLCEwKSxjKCJhdF92YWx1ZSIsZCgpLCEwKSxjKCJ0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YSIsaCgpLCEwKV0pLEIkPWIoW2MoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCExKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMSksYygibmFtZSIsZCgpLCExKSxjKCJ0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YSIsaCgpLCEwKV0pLFMkPWIoW2MoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCExKV0pLEEkPWIoW2MoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCExKSxjKCJ0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YSIsaCgpLCExKV0pLEQkPWIoW2MoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCExKSxjKCJ0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YSIsaCgpLCExKV0pLHgkPWIoW2MoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCExKSxjKCJ0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YSIsaCgpLCEwKV0pLFQkPWIoW2MoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCExKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMSksYygibmFtZSIsZCgpLCExKSxjKCJjb21tZW50IixkKCksITApLGMoImlnbm9yZV9ub3RfZm91bmQiLFAoKSwhMSksYygidHJhbnNhY3Rpb25fb3BhcXVlX2RhdGEiLGgoKSwhMCldKSxFJD1iKFtjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMSksYygic2NoZW1hX3BhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoIm5hbWUiLGQoKSwhMSksYygiZGVmaW5pdGlvbiIsZCgpLCExKSxjKCJvbl9jb25mbGljdCIsZWUoZCgpLHRlKCkpLCExKSxjKCJ0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YSIsaCgpLCEwKV0pLE8kPWIoW2MoImF0dGFjaF9vcGFxdWVfZGF0YSIsaCgpLCExKSxjKCJzY2hlbWFfcGF0aCIsdyhjKCJpdGVtIixkKCksITApKSwhMSksYygibmFtZSIsZCgpLCExKSxjKCJpZ25vcmVfbm90X2ZvdW5kIixQKCksITEpLGMoImNhc2NhZGUiLFAoKSwhMSksYygidHJhbnNhY3Rpb25fb3BhcXVlX2RhdGEiLGgoKSwhMCldKSxOJD1iKFtjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMSksYygic2NoZW1hX3BhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoIm5hbWUiLGQoKSwhMSksYygidHJhbnNhY3Rpb25fb3BhcXVlX2RhdGEiLGgoKSwhMCldKSxGJD1iKFtjKCJhdHRhY2hfb3BhcXVlX2RhdGEiLGgoKSwhMSksYygic2NoZW1hX3BhdGgiLHcoYygiaXRlbSIsZCgpLCEwKSksITEpLGMoIm5hbWUiLGQoKSwhMSksYygibmV3X25hbWUiLGQoKSwhMSksYygiaWdub3JlX25vdF9mb3VuZCIsUCgpLCExKSxjKCJ0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YSIsaCgpLCEwKV0pLE0kPWIoW2MoInJlcXVlc3QiLGgoKSwhMSldKSxMJD1iKFtjKCJyZXF1ZXN0IixoKCksITEpXSksVSQ9YihbYygicmVxdWVzdCIsaCgpLCExKV0pLFIkPWIoW2MoInJlcXVlc3QiLGgoKSwhMSldKSxDJD1iKFtjKCJyZXF1ZXN0IixoKCksITEpXSksUCQ9YihbYygicmVxdWVzdCIsaCgpLCExKV0pLGskPWIoW2MoInJlcXVlc3QiLGgoKSwhMSldKSxWJD1iKFtjKCJyZXF1ZXN0IixoKCksITEpXSksbkY9KHQpPT5rYyhHTix0KTt2YXIgaUY9KHQpPT5rYyhRTix0KTt2YXIgbEk9KHQpPT5rYyh0Rix0KTt2YXIgdUk9KHQpPT5rYyhKTix0KTt2YXIgZkk9KHQpPT5rYyhYTix0KTt2YXIgZEk9KHQpPT5rYyhaTix0KTtmdW5jdGlvbiBzRih0KXtsZXQgZT10LmFyZ3VtZW50cyxyPVtdLG49e307aWYoZSE9bnVsbCl7bGV0IG89Q2ModGkoZSkpO2ZvcihsZXQgYSBvZiBvLnNjaGVtYS5maWVsZHMpe2xldCBsPW8uZ2V0Q2hpbGQoYS5uYW1lKSx1PWw/bC5nZXQoMCk6bnVsbDtpZihhLm5hbWUuc3RhcnRzV2l0aCgiYXJnXyIpKXtsZXQgZj1wYXJzZUludChhLm5hbWUuc2xpY2UoNCksMTApO3doaWxlKHIubGVuZ3RoPD1mKXIucHVzaChudWxsKTtyW2ZdPXV9ZWxzZSBuW2EubmFtZV09dX19bGV0IGk9dC5yZXF1aXJlZF9leHRlbnNpb25zLHM9aT09bnVsbD9bXTooQXJyYXkuaXNBcnJheShpKT9pOlsuLi5pXSkuZmlsdGVyKChvKT0+byE9bnVsbCkubWFwKFN0cmluZyk7cmV0dXJue2Z1bmN0aW9uTmFtZTpTdHJpbmcodC5mdW5jdGlvbl9uYW1lPz8iIikscG9zaXRpb25hbEFyZ3VtZW50czpyLG5hbWVkQXJndW1lbnRzOm4scmVxdWlyZWRFeHRlbnNpb25zOnMsc2NoZW1hUGF0aDp0LnNjaGVtYV9wYXRoPT1udWxsP251bGw6KEFycmF5LmlzQXJyYXkodC5zY2hlbWFfcGF0aCk/dC5zY2hlbWFfcGF0aDpbLi4udC5zY2hlbWFfcGF0aF0pLmZpbHRlcigobyk9Pm8hPW51bGwpLm1hcChTdHJpbmcpfX1mdW5jdGlvbiBWZCh0KXtyZXR1cm57cmVxdWVzdDp1cyh0KX19ZnVuY3Rpb24gUHIodCl7bGV0IGU9dGkodC5yZXN1bHQpLHI9Q2MoZSk7cmV0dXJuIEZJKHIpfWZ1bmN0aW9uIG9GKHQpe2lmKHQ9PT1udWxsKXJldHVybiBSSSgpO2lmKHR5cGVvZiB0PT09InN0cmluZyIpcmV0dXJuIGQoKTtpZih0eXBlb2YgdD09PSJiaWdpbnQiKXJldHVybiBpdCgpO2lmKHR5cGVvZiB0PT09Im51bWJlciIpe2lmKCFOdW1iZXIuaXNGaW5pdGUodCkpdGhyb3cgVHlwZUVycm9yKGBBdHRhY2ggb3B0aW9uIG51bWJlciB2YWx1ZXMgbXVzdCBiZSBmaW5pdGUgKGdvdCAke3R9KS4gVXNlIGEgYmlnaW50IGZvciBpbnRlZ2VycyBvciBhIGZpbml0ZSBudW1iZXIgZm9yIGZsb2F0cy5gKTtyZXR1cm4gS2QoKX1pZih0eXBlb2YgdD09PSJib29sZWFuIilyZXR1cm4gUCgpO2lmKHQgaW5zdGFuY2VvZiBVaW50OEFycmF5KXJldHVybiBoKCk7dGhyb3cgVHlwZUVycm9yKGBVbnN1cHBvcnRlZCBhdHRhY2ggb3B0aW9uIHZhbHVlIHR5cGU6ICR7dHlwZW9mIHR9LiBTdXBwb3J0ZWQ6IHN0cmluZywgbnVtYmVyLCBiaWdpbnQsIGJvb2xlYW4sIG51bGwsIFVpbnQ4QXJyYXkuYCl9ZnVuY3Rpb24gaEkodCl7aWYoIXQpcmV0dXJuIG51bGw7bGV0IGU9T2JqZWN0LmVudHJpZXModCk7aWYoZS5sZW5ndGg9PT0wKXJldHVybiBudWxsO2xldCByPVtdLG49e307Zm9yKGxldFtvLGFdb2YgZSl7bGV0IGw9b0YoYSk7ci5wdXNoKGMobyxsLCEwKSksbltvXT1bYV19bGV0IGk9YihyKSxzPVVvKG4saSk7cmV0dXJuIHVzKHMpfWNsYXNzIGVyIGV4dGVuZHMgRXJyb3J7cmVtb3RlVHJhY2ViYWNrO2Vycm9yVHlwZTtjb25zdHJ1Y3Rvcih0LGUpe3N1cGVyKHQsZT8uY2F1c2UhPW51bGw/e2NhdXNlOmUuY2F1c2V9OnZvaWQgMCk7aWYodGhpcy5uYW1lPSJWZ2lDbGllbnRFcnJvciIsZT8ucmVtb3RlVHJhY2ViYWNrKXRoaXMucmVtb3RlVHJhY2ViYWNrPWUucmVtb3RlVHJhY2ViYWNrO2lmKGU/LmVycm9yVHlwZSl0aGlzLmVycm9yVHlwZT1lLmVycm9yVHlwZX1zdGF0aWMgZnJvbVJwY0Vycm9yKHQpe2xldCBlPWAke3QuZXJyb3JUeXBlfTogJHt0LmVycm9yTWVzc2FnZX1gLHI9dC5yZW1vdGVUcmFjZWJhY2s/YCR7ZX0KClJlbW90ZSB0cmFjZWJhY2s6CiR7dC5yZW1vdGVUcmFjZWJhY2t9YDplO3JldHVybiBuZXcgZXIocix7cmVtb3RlVHJhY2ViYWNrOnQucmVtb3RlVHJhY2ViYWNrfHx2b2lkIDAsZXJyb3JUeXBlOnQuZXJyb3JUeXBlLGNhdXNlOnR9KX19ZnVuY3Rpb24gYUYodCl7cmV0dXJue2FzeW5jIGNhbGwoZSxyKXt0cnl7cmV0dXJuIGF3YWl0IHQuY2FsbChlLHIpfWNhdGNoKG4pe2lmKG4gaW5zdGFuY2VvZiBzdSl0aHJvdyBlci5mcm9tUnBjRXJyb3Iobik7dGhyb3cgbn19LGFzeW5jIHN0cmVhbShlLHIpe3RyeXtyZXR1cm4gYXdhaXQgdC5zdHJlYW0oZSxyKX1jYXRjaChuKXtpZihuIGluc3RhbmNlb2Ygc3UpdGhyb3cgZXIuZnJvbVJwY0Vycm9yKG4pO3Rocm93IG59fSxkZXNjcmliZTooKT0+dC5kZXNjcmliZSgpLGNsb3NlOigpPT50LmNsb3NlKCl9fWZ1bmN0aW9uIGxzKHQsZSl7aWYoIXQpcmV0dXJuW107cmV0dXJuKEFycmF5LmlzQXJyYXkodCk/dDpbLi4udF0pLmZpbHRlcigobik9Pm4hPW51bGwpLm1hcCgobik9PmUodGkobikpKX1mdW5jdGlvbiBjRih0KXtsZXQgZT17fTtpZighdClyZXR1cm4gZTtsZXQgcj10O2lmKHR5cGVvZiByW1N5bWJvbC5pdGVyYXRvcl0hPT0iZnVuY3Rpb24iKXJldHVybiBlO2ZvcihsZXQgbiBvZiByKWlmKEFycmF5LmlzQXJyYXkobikpZVtTdHJpbmcoblswXSldPVN0cmluZyhuWzFdKTtlbHNlIGlmKG4mJnR5cGVvZiBuPT09Im9iamVjdCIpe2xldCBpPW47ZVtTdHJpbmcoaS5rZXk/P2lbMF0/PyIiKV09U3RyaW5nKGkudmFsdWU/P2lbMV0/PyIiKX1yZXR1cm4gZX1mdW5jdGlvbiB6ZCh0KXtpZihTeW1ib2wuYXN5bmNJdGVyYXRvciBpbiB0KXJldHVybiB0W1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpO2xldCBlPXRbU3ltYm9sLml0ZXJhdG9yXSgpO3JldHVybnthc3luYyBuZXh0KCl7cmV0dXJuIGUubmV4dCgpfX19Y2xhc3MgZV97cnBjO2RlZmF1bHRBdHRhY2hPcGFxdWVEYXRhO2NvbnN0cnVjdG9yKHQsZSl7dGhpcy5ycGM9YUYodCksdGhpcy5kZWZhdWx0QXR0YWNoT3BhcXVlRGF0YT1lPy5hdHRhY2hPcGFxdWVEYXRhPz9udWxsfXN0YXRpYyBhc3luYyBmcm9tSXJvaCh0LGU9e30scixuKXtpZighL14oaXJvaHxodHRwaSk6XC9cLy8udGVzdCh0KSl0aHJvdyBUeXBlRXJyb3IoIlZnaUNsaWVudC5mcm9tSXJvaCByZXF1aXJlcyBhbiBpcm9oOi8vIG9yIGh0dHBpOi8vIGVuZHBvaW50Iik7bGV0IGk9bjtpZighaSl7bGV0IHM9YXdhaXQgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiAocXkoKSx7fSkpO2k9dC5zdGFydHNXaXRoKCJpcm9oOi8vIik/dm9pZCAwOnZvaWQgMH1pZighaSl0aHJvdyBUeXBlRXJyb3IoIm5vIElyb2ggY29ubmVjdG9yIGlzIGF2YWlsYWJsZSBpbiB0aGlzIHJ1bnRpbWUiKTtyZXR1cm4gbmV3IGVfKGF3YWl0IGkodCxlKSxyKX1hc3luYyBfZG9CaW5kKHQsZSxyLG4saSxzLG8sYT1udWxsLGwpe2xldCB1PXtmdW5jdGlvbl9uYW1lOnQsYXJndW1lbnRzOnIsZnVuY3Rpb25fdHlwZTplLGlucHV0X3NjaGVtYTpuLHNldHRpbmdzOmk/P251bGwsc2VjcmV0czpzPz9udWxsLGF0dGFjaF9vcGFxdWVfZGF0YTphPz90aGlzLmRlZmF1bHRBdHRhY2hPcGFxdWVEYXRhLHRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhOm8/P251bGwscmVzb2x2ZWRfc2VjcmV0c19wcm92aWRlZDohMX0sZj1rSSh1KSxwPWF3YWl0IHRoaXMucnBjLmNhbGwoImJpbmQiLFZkKGYpKTtpZighcCl0aHJvdyBuZXcgZXIoImJpbmQgcmV0dXJuZWQgbnVsbCIpO2xldCBnPVByKHApLHY9JE4oZyk7aWYobClsKHYpO3JldHVybntyZXF1ZXN0OnUscmVzcG9uc2U6dn19YXN5bmMgX2RvSW5pdCh0LGUscil7bGV0IG49cj8ub3JkZXJCeT8/bnVsbCxpPXI/LnRhYmxlc2FtcGxlPz9udWxsLHM9e2JpbmRfY2FsbDp0LG91dHB1dF9zY2hlbWE6ZS5vdXRwdXRfc2NoZW1hLGJpbmRfb3BhcXVlX2RhdGE6ZS5vcGFxdWVfZGF0YSxzcGxpdF90b2tlbnM6bnVsbCxyb3dfbGltaXQ6bnVsbCxwcm9qZWN0aW9uX2lkczpyPy5wcm9qZWN0aW9uSWRzPz9udWxsLHB1c2hkb3duX2ZpbHRlcnM6cj8ucHVzaGRvd25GaWx0ZXJzPz9udWxsLGpvaW5fa2V5czpyPy5qb2luS2V5cz8/W10scGhhc2U6cj8ucGhhc2U/P251bGwsZmluYWxpemVfc3RhdGVfaWQ6bnVsbCxvcmRlcl9ieV9jb2x1bW5fbmFtZTpuPy5jb2x1bW5OYW1lPz9udWxsLG9yZGVyX2J5X2RpcmVjdGlvbjpuPy5kaXJlY3Rpb24/P251bGwsb3JkZXJfYnlfbnVsbF9vcmRlcjpuPy5udWxsT3JkZXI/P251bGwsb3JkZXJfYnlfbGltaXQ6bj8ubGltaXQ9PW51bGw/bnVsbDpCaWdJbnQobi5saW1pdCksdGFibGVzYW1wbGVfcGVyY2VudGFnZTppPy5wZXJjZW50YWdlPz9udWxsLHRhYmxlc2FtcGxlX3NlZWQ6aT8uc2VlZD09bnVsbD9udWxsOkJpZ0ludChpLnNlZWQpLGV4ZWN1dGlvbl9pZDpyPy5leGVjdXRpb25JZD8/bnVsbCxpbml0X29wYXF1ZV9kYXRhOm51bGwsc3Vic3RyZWFtX2lkOm51bGx9LG89V04ocyksYT1hd2FpdCB0aGlzLnJwYy5zdHJlYW0oImluaXQiLFZkKG8pKSxsPWEuaGVhZGVyO2lmKCFsKXRocm93IG5ldyBlcigiaW5pdCBkaWQgbm90IHJldHVybiBhIGhlYWRlciIpO2xldCB1PUhOKGwpO3JldHVybntzZXNzaW9uOmEsaW5pdFJlc3BvbnNlOnV9fWFzeW5jKnRhYmxlRnVuY3Rpb24odCl7bGV0IGU9dC5hcmd1bWVudHM/P25ldyBTYSx7cmVxdWVzdDpyLHJlc3BvbnNlOm59PWF3YWl0IHRoaXMuX2RvQmluZCh0LmZ1bmN0aW9uTmFtZSwidGFibGUiLGUsbnVsbCx0LnNldHRpbmdzPz9udWxsLG51bGwsdC50cmFuc2FjdGlvbk9wYXF1ZURhdGE/P251bGwsdC5hdHRhY2hPcGFxdWVEYXRhPz9udWxsLHQub25CaW5kPz9udWxsKSx7c2Vzc2lvbjppfT1hd2FpdCB0aGlzLl9kb0luaXQocixuLHtwcm9qZWN0aW9uSWRzOnQucHJvamVjdGlvbklkcyxwdXNoZG93bkZpbHRlcnM6dC5wdXNoZG93bkZpbHRlcnMsb3JkZXJCeTp0Lm9yZGVyQnksdGFibGVzYW1wbGU6dC50YWJsZXNhbXBsZSxqb2luS2V5czp0LmpvaW5LZXlzfSkscz1uLm91dHB1dF9zY2hlbWE7dHJ5e2ZvciBhd2FpdChsZXQgbyBvZiBpKWlmKG8ubGVuZ3RoPjApeWllbGQgRm8obyxzKX1maW5hbGx5e2kuY2xvc2UoKX19YXN5bmMqc2NhbGFyRnVuY3Rpb25Sb3dzKHQpe2xldCBlPXpkKHQuaW5wdXQpLHI9YXdhaXQgZS5uZXh0KCk7aWYoci5kb25lKXRocm93IG5ldyBlcihgc2NhbGFyRnVuY3Rpb24oJHt0LmZ1bmN0aW9uTmFtZX0pOiBpbnB1dCBpdGVyYXRvciB5aWVsZGVkIG5vIGJhdGNoZXM7IGF0IGxlYXN0IG9uZSBiYXRjaCBpcyByZXF1aXJlZCB0byBkZXRlcm1pbmUgdGhlIGlucHV0IHNjaGVtYWApO2xldCBuPXIudmFsdWUsaT1uLnNjaGVtYSxzPXQuYXJndW1lbnRzPz9uZXcgU2Ese3JlcXVlc3Q6byxyZXNwb25zZTphfT1hd2FpdCB0aGlzLl9kb0JpbmQodC5mdW5jdGlvbk5hbWUsInNjYWxhciIscyxpLHQuc2V0dGluZ3M/P251bGwsdC5zZWNyZXRzPz9udWxsLHQudHJhbnNhY3Rpb25PcGFxdWVEYXRhPz9udWxsLHQuYXR0YWNoT3BhcXVlRGF0YT8/bnVsbCx0Lm9uQmluZD8/bnVsbCkse3Nlc3Npb246bH09YXdhaXQgdGhpcy5fZG9Jbml0KG8sYSk7dHJ5e2xldCB1PWF3YWl0IGwuZXhjaGFuZ2UoWy4uLmtpKG4pXSk7aWYodS5sZW5ndGg+MCl5aWVsZCB1O2ZvciBhd2FpdChsZXQgZiBvZntbU3ltYm9sLmFzeW5jSXRlcmF0b3JdOigpPT5lfSl7bGV0IHA9YXdhaXQgbC5leGNoYW5nZShbLi4ua2koZildKTtpZihwLmxlbmd0aD4wKXlpZWxkIHB9fWZpbmFsbHl7bC5jbG9zZSgpfX1hc3luYypzY2FsYXJGdW5jdGlvbih0KXtsZXQgZT16ZCh0LmlucHV0KSxyPWF3YWl0IGUubmV4dCgpO2lmKHIuZG9uZSl0aHJvdyBuZXcgZXIoYHNjYWxhckZ1bmN0aW9uKCR7dC5mdW5jdGlvbk5hbWV9KTogaW5wdXQgaXRlcmF0b3IgeWllbGRlZCBubyBiYXRjaGVzOyBhdCBsZWFzdCBvbmUgYmF0Y2ggaXMgcmVxdWlyZWQgdG8gZGV0ZXJtaW5lIHRoZSBpbnB1dCBzY2hlbWFgKTtsZXQgbj1yLnZhbHVlLGk9bi5zY2hlbWEscz10LmFyZ3VtZW50cz8/bmV3IFNhLHtyZXF1ZXN0Om8scmVzcG9uc2U6YX09YXdhaXQgdGhpcy5fZG9CaW5kKHQuZnVuY3Rpb25OYW1lLCJzY2FsYXIiLHMsaSx0LnNldHRpbmdzPz9udWxsLHQuc2VjcmV0cz8/bnVsbCx0LnRyYW5zYWN0aW9uT3BhcXVlRGF0YT8/bnVsbCx0LmF0dGFjaE9wYXF1ZURhdGE/P251bGwsdC5vbkJpbmQ/P251bGwpLHtzZXNzaW9uOmx9PWF3YWl0IHRoaXMuX2RvSW5pdChvLGEpLHU9YS5vdXRwdXRfc2NoZW1hO3RyeXtsZXQgZj1hd2FpdCBsLmV4Y2hhbmdlKFsuLi5raShuKV0pO2lmKGYubGVuZ3RoPjApeWllbGQgRm8oZix1KTtmb3IgYXdhaXQobGV0IHAgb2Z7W1N5bWJvbC5hc3luY0l0ZXJhdG9yXTooKT0+ZX0pe2xldCBnPWF3YWl0IGwuZXhjaGFuZ2UoWy4uLmtpKHApXSk7aWYoZy5sZW5ndGg+MCl5aWVsZCBGbyhnLHUpfX1maW5hbGx5e2wuY2xvc2UoKX19YXN5bmMqdGFibGVJbk91dEZ1bmN0aW9uUm93cyh0KXtsZXQgZT16ZCh0LmlucHV0KSxyPWF3YWl0IGUubmV4dCgpO2lmKHIuZG9uZSl0aHJvdyBuZXcgZXIoYHRhYmxlSW5PdXRGdW5jdGlvbigke3QuZnVuY3Rpb25OYW1lfSk6IGlucHV0IGl0ZXJhdG9yIHlpZWxkZWQgbm8gYmF0Y2hlczsgYXQgbGVhc3Qgb25lIGJhdGNoIGlzIHJlcXVpcmVkIHRvIGRldGVybWluZSB0aGUgaW5wdXQgc2NoZW1hYCk7bGV0IG49ci52YWx1ZSxpPW4uc2NoZW1hLHM9dC5hcmd1bWVudHM/P25ldyBTYSx7cmVxdWVzdDpvLHJlc3BvbnNlOmF9PWF3YWl0IHRoaXMuX2RvQmluZCh0LmZ1bmN0aW9uTmFtZSwidGFibGUiLHMsaSx0LnNldHRpbmdzPz9udWxsLG51bGwsdC50cmFuc2FjdGlvbk9wYXF1ZURhdGE/P251bGwsdC5hdHRhY2hPcGFxdWVEYXRhPz9udWxsLHQub25CaW5kPz9udWxsKSx7c2Vzc2lvbjpsLGluaXRSZXNwb25zZTp1fT1hd2FpdCB0aGlzLl9kb0luaXQobyxhLHtwcm9qZWN0aW9uSWRzOnQucHJvamVjdGlvbklkcyxwdXNoZG93bkZpbHRlcnM6dC5wdXNoZG93bkZpbHRlcnMscGhhc2U6IklOUFVUIixvcmRlckJ5OnQub3JkZXJCeSx0YWJsZXNhbXBsZTp0LnRhYmxlc2FtcGxlLGpvaW5LZXlzOnQuam9pbktleXN9KTt0cnl7bGV0IHA9YXdhaXQgbC5leGNoYW5nZShbLi4ua2kobildKTtpZihwLmxlbmd0aD4wKXlpZWxkIHA7Zm9yIGF3YWl0KGxldCBnIG9me1tTeW1ib2wuYXN5bmNJdGVyYXRvcl06KCk9PmV9KXtsZXQgdj1hd2FpdCBsLmV4Y2hhbmdlKFsuLi5raShnKV0pO2lmKHYubGVuZ3RoPjApeWllbGQgdn19ZmluYWxseXtsLmNsb3NlKCl9bGV0e3Nlc3Npb246Zn09YXdhaXQgdGhpcy5fZG9Jbml0KG8sYSx7cHJvamVjdGlvbklkczp0LnByb2plY3Rpb25JZHMscHVzaGRvd25GaWx0ZXJzOnQucHVzaGRvd25GaWx0ZXJzLHBoYXNlOiJGSU5BTElaRSIsZXhlY3V0aW9uSWQ6dS5leGVjdXRpb25faWQsb3JkZXJCeTp0Lm9yZGVyQnksdGFibGVzYW1wbGU6dC50YWJsZXNhbXBsZSxqb2luS2V5czp0LmpvaW5LZXlzfSk7dHJ5e2ZvciBhd2FpdChsZXQgcCBvZiBmKWlmKHAubGVuZ3RoPjApeWllbGQgcH1maW5hbGx5e2YuY2xvc2UoKX19YXN5bmMqdGFibGVJbk91dEZ1bmN0aW9uKHQpe2xldCBlPXpkKHQuaW5wdXQpLHI9YXdhaXQgZS5uZXh0KCk7aWYoci5kb25lKXRocm93IG5ldyBlcihgdGFibGVJbk91dEZ1bmN0aW9uKCR7dC5mdW5jdGlvbk5hbWV9KTogaW5wdXQgaXRlcmF0b3IgeWllbGRlZCBubyBiYXRjaGVzOyBhdCBsZWFzdCBvbmUgYmF0Y2ggaXMgcmVxdWlyZWQgdG8gZGV0ZXJtaW5lIHRoZSBpbnB1dCBzY2hlbWFgKTtsZXQgbj1yLnZhbHVlLGk9bi5zY2hlbWEscz10LmFyZ3VtZW50cz8/bmV3IFNhLHtyZXF1ZXN0Om8scmVzcG9uc2U6YX09YXdhaXQgdGhpcy5fZG9CaW5kKHQuZnVuY3Rpb25OYW1lLCJ0YWJsZSIscyxpLHQuc2V0dGluZ3M/P251bGwsbnVsbCx0LnRyYW5zYWN0aW9uT3BhcXVlRGF0YT8/bnVsbCx0LmF0dGFjaE9wYXF1ZURhdGE/P251bGwsdC5vbkJpbmQ/P251bGwpLHtzZXNzaW9uOmwsaW5pdFJlc3BvbnNlOnV9PWF3YWl0IHRoaXMuX2RvSW5pdChvLGEse3Byb2plY3Rpb25JZHM6dC5wcm9qZWN0aW9uSWRzLHB1c2hkb3duRmlsdGVyczp0LnB1c2hkb3duRmlsdGVycyxwaGFzZToiSU5QVVQiLG9yZGVyQnk6dC5vcmRlckJ5LHRhYmxlc2FtcGxlOnQudGFibGVzYW1wbGUsam9pbktleXM6dC5qb2luS2V5c30pLGY9YS5vdXRwdXRfc2NoZW1hO3RyeXtsZXQgZz1hd2FpdCBsLmV4Y2hhbmdlKFsuLi5raShuKV0pO2lmKGcubGVuZ3RoPjApeWllbGQgRm8oZyxmKTtmb3IgYXdhaXQobGV0IHYgb2Z7W1N5bWJvbC5hc3luY0l0ZXJhdG9yXTooKT0+ZX0pe2xldCBJPWF3YWl0IGwuZXhjaGFuZ2UoWy4uLmtpKHYpXSk7aWYoSS5sZW5ndGg+MCl5aWVsZCBGbyhJLGYpfX1maW5hbGx5e2wuY2xvc2UoKX1sZXR7c2Vzc2lvbjpwfT1hd2FpdCB0aGlzLl9kb0luaXQobyxhLHtwcm9qZWN0aW9uSWRzOnQucHJvamVjdGlvbklkcyxwdXNoZG93bkZpbHRlcnM6dC5wdXNoZG93bkZpbHRlcnMscGhhc2U6IkZJTkFMSVpFIixleGVjdXRpb25JZDp1LmV4ZWN1dGlvbl9pZCxvcmRlckJ5OnQub3JkZXJCeSx0YWJsZXNhbXBsZTp0LnRhYmxlc2FtcGxlLGpvaW5LZXlzOnQuam9pbktleXN9KTt0cnl7Zm9yIGF3YWl0KGxldCBnIG9mIHApaWYoZy5sZW5ndGg+MCl5aWVsZCBGbyhnLGYpfWZpbmFsbHl7cC5jbG9zZSgpfX1hc3luYyp0YWJsZUZ1bmN0aW9uUm93cyh0KXtsZXQgZT10LmFyZ3VtZW50cz8/bmV3IFNhLHtyZXF1ZXN0OnIscmVzcG9uc2U6bn09YXdhaXQgdGhpcy5fZG9CaW5kKHQuZnVuY3Rpb25OYW1lLCJ0YWJsZSIsZSxudWxsLHQuc2V0dGluZ3M/P251bGwsbnVsbCx0LnRyYW5zYWN0aW9uT3BhcXVlRGF0YT8/bnVsbCx0LmF0dGFjaE9wYXF1ZURhdGE/P251bGwsdC5vbkJpbmQ/P251bGwpLHtzZXNzaW9uOml9PWF3YWl0IHRoaXMuX2RvSW5pdChyLG4se3Byb2plY3Rpb25JZHM6dC5wcm9qZWN0aW9uSWRzLHB1c2hkb3duRmlsdGVyczp0LnB1c2hkb3duRmlsdGVycyxvcmRlckJ5OnQub3JkZXJCeSx0YWJsZXNhbXBsZTp0LnRhYmxlc2FtcGxlLGpvaW5LZXlzOnQuam9pbktleXN9KTt0cnl7Zm9yIGF3YWl0KGxldCBzIG9mIGkpaWYocy5sZW5ndGg+MCl5aWVsZCBzfWZpbmFsbHl7aS5jbG9zZSgpfX1hc3luYyBjYXRhbG9nc0luZm8oKXtsZXQgdD1hd2FpdCB0aGlzLnJwYy5jYWxsKCJjYXRhbG9nX2NhdGFsb2dzIix7fSk7aWYoIXQpcmV0dXJuW107bGV0IGU9UHIodCk7cmV0dXJuIGxzKGUuaXRlbXMsbkYpfWFzeW5jIGNhdGFsb2dzKCl7cmV0dXJuKGF3YWl0IHRoaXMuY2F0YWxvZ3NJbmZvKCkpLm1hcCgoZSk9PmUubmFtZSl9YXN5bmMgY2F0YWxvZ0F0dGFjaCh0LGUpe2lmKGU/Lm9wdGlvbnMhPW51bGwmJmU/Lm9wdGlvbnNCeXRlcyE9bnVsbCl0aHJvdyBuZXcgZXIoImNhdGFsb2dBdHRhY2g6IGNhbm5vdCBzcGVjaWZ5IGJvdGggYG9wdGlvbnNgIGFuZCBgb3B0aW9uc0J5dGVzYCIpO2xldCByO2lmKGU/Lm9wdGlvbnNCeXRlcyE9bnVsbClyPWUub3B0aW9uc0J5dGVzLmJ5dGVMZW5ndGg9PT0wP251bGw6ZS5vcHRpb25zQnl0ZXM7ZWxzZSByPWhJKGU/Lm9wdGlvbnMpO2xldCBuPWIoW2MoIm5hbWUiLGQoKSwhMSksYygib3B0aW9ucyIsaCgpLCEwKSxjKCJkYXRhX3ZlcnNpb25fc3BlYyIsZCgpLCEwKSxjKCJpbXBsZW1lbnRhdGlvbl92ZXJzaW9uIixkKCksITApLGMoImNsaWVudF9jYXBhYmlsaXRpZXMiLGgoKSwhMCldKSxpPVVvKHtuYW1lOlt0XSxvcHRpb25zOltyXSxkYXRhX3ZlcnNpb25fc3BlYzpbZT8uZGF0YVZlcnNpb25TcGVjPz9udWxsXSxpbXBsZW1lbnRhdGlvbl92ZXJzaW9uOltlPy5pbXBsZW1lbnRhdGlvblZlcnNpb24/P251bGxdLGNsaWVudF9jYXBhYmlsaXRpZXM6W2U/LmNsaWVudENhcGFiaWxpdGllcz9ZTihlRixlLmNsaWVudENhcGFiaWxpdGllcyk6bnVsbF19LG4pLHM9YXdhaXQgdGhpcy5ycGMuY2FsbCgiY2F0YWxvZ19hdHRhY2giLFZkKGkpKTtpZighcyl0aHJvdyBuZXcgZXIoImNhdGFsb2dfYXR0YWNoIHJldHVybmVkIG51bGwiKTtsZXQgbz1QcihzKTtyZXR1cm57YXR0YWNoX29wYXF1ZV9kYXRhOnRpKG8uYXR0YWNoX29wYXF1ZV9kYXRhKSxzdXBwb3J0c190cmFuc2FjdGlvbnM6by5zdXBwb3J0c190cmFuc2FjdGlvbnM/PyExLHN1cHBvcnRzX3RpbWVfdHJhdmVsOm8uc3VwcG9ydHNfdGltZV90cmF2ZWw/PyExLGNhdGFsb2dfdmVyc2lvbl9mcm96ZW46by5jYXRhbG9nX3ZlcnNpb25fZnJvemVuPz8hMSxjYXRhbG9nX3ZlcnNpb246TnVtYmVyKG8uY2F0YWxvZ192ZXJzaW9uPz8wKSxhdHRhY2hfb3BhcXVlX2RhdGFfcmVxdWlyZWQ6by5hdHRhY2hfb3BhcXVlX2RhdGFfcmVxdWlyZWQ/PyEwLGRlZmF1bHRfc2NoZW1hOm8uZGVmYXVsdF9zY2hlbWE/PyJtYWluIixzZXR0aW5nczpvLnNldHRpbmdzPyhBcnJheS5pc0FycmF5KG8uc2V0dGluZ3MpP28uc2V0dGluZ3M6Wy4uLm8uc2V0dGluZ3NdKS5tYXAodGkpOltdLHNlY3JldF90eXBlczpvLnNlY3JldF90eXBlcz8oQXJyYXkuaXNBcnJheShvLnNlY3JldF90eXBlcyk/by5zZWNyZXRfdHlwZXM6Wy4uLm8uc2VjcmV0X3R5cGVzXSkubWFwKHRpKTpbXSxhdHRhY2hfY2F0YWxvZ3M6by5hdHRhY2hfY2F0YWxvZ3M/KEFycmF5LmlzQXJyYXkoby5hdHRhY2hfY2F0YWxvZ3MpP28uYXR0YWNoX2NhdGFsb2dzOlsuLi5vLmF0dGFjaF9jYXRhbG9nc10pLm1hcCh0aSk6W10sY29tbWVudDpvLmNvbW1lbnQ/P251bGwsdGFnczpjRihvLnRhZ3MpLHN1cHBvcnRzX2NvbHVtbl9zdGF0aXN0aWNzOm8uc3VwcG9ydHNfY29sdW1uX3N0YXRpc3RpY3M/PyExLGdsb2JhbF9mdW5jdGlvbnM6by5nbG9iYWxfZnVuY3Rpb25zPyhBcnJheS5pc0FycmF5KG8uZ2xvYmFsX2Z1bmN0aW9ucyk/by5nbG9iYWxfZnVuY3Rpb25zOlsuLi5vLmdsb2JhbF9mdW5jdGlvbnNdKS5tYXAodGkpOltdLGdsb2JhbF9mdW5jdGlvbl9wcmVmaXg6by5nbG9iYWxfZnVuY3Rpb25fcHJlZml4Pz8iIixyZXNvbHZlZF9kYXRhX3ZlcnNpb246by5yZXNvbHZlZF9kYXRhX3ZlcnNpb24/P251bGwscmVzb2x2ZWRfaW1wbGVtZW50YXRpb25fdmVyc2lvbjpvLnJlc29sdmVkX2ltcGxlbWVudGF0aW9uX3ZlcnNpb24/P251bGx9fWFzeW5jIGNhdGFsb2dEZXRhY2godCl7YXdhaXQgdGhpcy5ycGMuY2FsbCgiY2F0YWxvZ19kZXRhY2giLHthdHRhY2hfb3BhcXVlX2RhdGE6dH0pfWFzeW5jIGNhdGFsb2dDcmVhdGUodCxlLHIpe2xldCBuO2lmKHI9PW51bGwpbj1udWxsO2Vsc2UgaWYociBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpbj1yLmJ5dGVMZW5ndGg9PT0wP251bGw6cjtlbHNle2lmKHIub3B0aW9ucyE9bnVsbCYmci5vcHRpb25zQnl0ZXMhPW51bGwpdGhyb3cgbmV3IGVyKCJjYXRhbG9nQ3JlYXRlOiBjYW5ub3Qgc3BlY2lmeSBib3RoIGBvcHRpb25zYCBhbmQgYG9wdGlvbnNCeXRlc2AiKTtpZihyLm9wdGlvbnNCeXRlcyE9bnVsbCluPXIub3B0aW9uc0J5dGVzLmJ5dGVMZW5ndGg9PT0wP251bGw6ci5vcHRpb25zQnl0ZXM7ZWxzZSBuPWhJKHIub3B0aW9ucyl9YXdhaXQgdGhpcy5ycGMuY2FsbCgiY2F0YWxvZ19jcmVhdGUiLHtuYW1lOnQsb25fY29uZmxpY3Q6ZSxvcHRpb25zOm59KX1hc3luYyBjYXRhbG9nRHJvcCh0KXthd2FpdCB0aGlzLnJwYy5jYWxsKCJjYXRhbG9nX2Ryb3AiLHtuYW1lOnR9KX1hc3luYyBjYXRhbG9nVmVyc2lvbih0LGUpe2xldCByPWF3YWl0IHRoaXMucnBjLmNhbGwoImNhdGFsb2dfdmVyc2lvbiIse2F0dGFjaF9vcGFxdWVfZGF0YTp0LHRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhOmU/P251bGx9KTtpZighcil0aHJvdyBuZXcgZXIoImNhdGFsb2dfdmVyc2lvbiByZXR1cm5lZCBudWxsIik7bGV0IG49UHIocik7cmV0dXJuIE51bWJlcihuLnZlcnNpb24/PzApfWFzeW5jIHRyYW5zYWN0aW9uQmVnaW4odCl7bGV0IGU9YXdhaXQgdGhpcy5ycGMuY2FsbCgiY2F0YWxvZ190cmFuc2FjdGlvbl9iZWdpbiIse2F0dGFjaF9vcGFxdWVfZGF0YTp0fSk7aWYoIWUpdGhyb3cgbmV3IGVyKCJ0cmFuc2FjdGlvbl9iZWdpbiByZXR1cm5lZCBudWxsIik7bGV0IHI9UHIoZSk7aWYoIXIudHJhbnNhY3Rpb25fb3BhcXVlX2RhdGEpdGhyb3cgbmV3IGVyKCJ0cmFuc2FjdGlvbl9iZWdpbiByZXR1cm5lZCBubyB0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YSIpO3JldHVybiB0aShyLnRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhKX1hc3luYyB0cmFuc2FjdGlvbkNvbW1pdCh0LGUpe2F3YWl0IHRoaXMucnBjLmNhbGwoImNhdGFsb2dfdHJhbnNhY3Rpb25fY29tbWl0Iix7YXR0YWNoX29wYXF1ZV9kYXRhOnQsdHJhbnNhY3Rpb25fb3BhcXVlX2RhdGE6ZX0pfWFzeW5jIHRyYW5zYWN0aW9uUm9sbGJhY2sodCxlKXthd2FpdCB0aGlzLnJwYy5jYWxsKCJjYXRhbG9nX3RyYW5zYWN0aW9uX3JvbGxiYWNrIix7YXR0YWNoX29wYXF1ZV9kYXRhOnQsdHJhbnNhY3Rpb25fb3BhcXVlX2RhdGE6ZX0pfWFzeW5jIHNjaGVtYXModCxlKXtsZXQgcj1hd2FpdCB0aGlzLnJwYy5jYWxsKCJjYXRhbG9nX3NjaGVtYXMiLHthdHRhY2hfb3BhcXVlX2RhdGE6dCx0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YTplPz9udWxsfSk7aWYoIXIpcmV0dXJuW107bGV0IG49UHIocik7cmV0dXJuIGxzKG4uaXRlbXMsdUkpfWFzeW5jIHNjaGVtYUdldCh0LGUscil7bGV0IG49YXdhaXQgdGhpcy5ycGMuY2FsbCgiY2F0YWxvZ19zY2hlbWFfZ2V0Iix7YXR0YWNoX29wYXF1ZV9kYXRhOnQscGF0aDpRdChlKSx0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YTpyPz9udWxsfSk7aWYoIW4pcmV0dXJuIG51bGw7bGV0IGk9UHIobikscz1scyhpLml0ZW1zLHVJKTtyZXR1cm4gcy5sZW5ndGg+MD9zWzBdOm51bGx9YXN5bmMgc2NoZW1hQ3JlYXRlKHQsZSxyKXtsZXQgbj1yPy50YWdzP25ldyBNYXAoT2JqZWN0LmVudHJpZXMoci50YWdzKSk6bnVsbDthd2FpdCB0aGlzLnJwYy5jYWxsKCJjYXRhbG9nX3NjaGVtYV9jcmVhdGUiLHthdHRhY2hfb3BhcXVlX2RhdGE6dCxwYXRoOlF0KGUpLG9uX2NvbmZsaWN0OnI/Lm9uQ29uZmxpY3Q/PyJlcnJvciIsY29tbWVudDpyPy5jb21tZW50Pz9udWxsLHRhZ3M6bix0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YTpyPy50cmFuc2FjdGlvbk9wYXF1ZURhdGE/P251bGx9KX1hc3luYyBzY2hlbWFEcm9wKHQsZSxyLG4saSl7YXdhaXQgdGhpcy5ycGMuY2FsbCgiY2F0YWxvZ19zY2hlbWFfZHJvcCIse2F0dGFjaF9vcGFxdWVfZGF0YTp0LHBhdGg6UXQoZSksaWdub3JlX25vdF9mb3VuZDpyPz8hMSxjYXNjYWRlOm4/PyExLHRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhOmk/P251bGx9KX1hc3luYyBzY2hlbWFDb250ZW50c1RhYmxlcyh0LGUscil7bGV0IG49YXdhaXQgdGhpcy5ycGMuY2FsbCgiY2F0YWxvZ19zY2hlbWFfY29udGVudHNfdGFibGVzIix7YXR0YWNoX29wYXF1ZV9kYXRhOnQscGF0aDpRdChlKSx0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YTpyPz9udWxsfSk7aWYoIW4pcmV0dXJuW107bGV0IGk9UHIobik7cmV0dXJuIGxzKGkuaXRlbXMsZkkpfWFzeW5jIHNjaGVtYUNvbnRlbnRzVmlld3ModCxlLHIpe2xldCBuPWF3YWl0IHRoaXMucnBjLmNhbGwoImNhdGFsb2dfc2NoZW1hX2NvbnRlbnRzX3ZpZXdzIix7YXR0YWNoX29wYXF1ZV9kYXRhOnQscGF0aDpRdChlKSx0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YTpyPz9udWxsfSk7aWYoIW4pcmV0dXJuW107bGV0IGk9UHIobik7cmV0dXJuIGxzKGkuaXRlbXMsZEkpfWFzeW5jIHNjaGVtYUNvbnRlbnRzRnVuY3Rpb25zKHQsZSxyLG4pe2xldCBpPWF3YWl0IHRoaXMucnBjLmNhbGwoImNhdGFsb2dfc2NoZW1hX2NvbnRlbnRzX2Z1bmN0aW9ucyIse2F0dGFjaF9vcGFxdWVfZGF0YTp0LHBhdGg6UXQoZSksdHlwZTpyLHRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhOm4/P251bGx9KTtpZighaSlyZXR1cm5bXTtsZXQgcz1QcihpKTtyZXR1cm4gbHMocy5pdGVtcyxpRil9YXN5bmMgdGFibGVHZXQodCxlLHIsbil7bGV0IGk9YXdhaXQgdGhpcy5ycGMuY2FsbCgiY2F0YWxvZ190YWJsZV9nZXQiLHthdHRhY2hfb3BhcXVlX2RhdGE6dCxzY2hlbWFfcGF0aDpRdChlKSxuYW1lOnIsdHJhbnNhY3Rpb25fb3BhcXVlX2RhdGE6bj8/bnVsbH0pO2lmKCFpKXJldHVybiBudWxsO2xldCBzPVByKGkpLG89bHMocy5pdGVtcyxmSSk7cmV0dXJuIG8ubGVuZ3RoPjA/b1swXTpudWxsfWFzeW5jIHRhYmxlQ3JlYXRlKHQsZSxyLG4saSxzLG8sYSxsKXthd2FpdCB0aGlzLnJwYy5jYWxsKCJjYXRhbG9nX3RhYmxlX2NyZWF0ZSIse2F0dGFjaF9vcGFxdWVfZGF0YTp0LHNjaGVtYV9wYXRoOlF0KGUpLG5hbWU6cixjb2x1bW5zOm4sb25fY29uZmxpY3Q6aSxub3RfbnVsbF9jb25zdHJhaW50czpzPz9udWxsLHVuaXF1ZV9jb25zdHJhaW50czpvPz9udWxsLGNoZWNrX2NvbnN0cmFpbnRzOmE/P251bGwsdHJhbnNhY3Rpb25fb3BhcXVlX2RhdGE6bD8/bnVsbH0pfWFzeW5jIHRhYmxlRHJvcCh0LGUscixuLGkscyl7YXdhaXQgdGhpcy5ycGMuY2FsbCgiY2F0YWxvZ190YWJsZV9kcm9wIix7YXR0YWNoX29wYXF1ZV9kYXRhOnQsc2NoZW1hX3BhdGg6UXQoZSksbmFtZTpyLGlnbm9yZV9ub3RfZm91bmQ6bj8/ITEsY2FzY2FkZTppPz8hMSx0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YTpzPz9udWxsfSl9YXN5bmMgdGFibGVTY2FuRnVuY3Rpb25HZXQodCxlLHIsbixpLHMpe2xldCBvPWF3YWl0IHRoaXMucnBjLmNhbGwoImNhdGFsb2dfdGFibGVfc2Nhbl9mdW5jdGlvbl9nZXQiLHthdHRhY2hfb3BhcXVlX2RhdGE6dCxzY2hlbWFfcGF0aDpRdChlKSxuYW1lOnIsYXRfdW5pdDpuPz9udWxsLGF0X3ZhbHVlOmk/P251bGwsdHJhbnNhY3Rpb25fb3BhcXVlX2RhdGE6cz8/bnVsbH0pO2lmKCFvKXRocm93IG5ldyBlcigidGFibGVfc2Nhbl9mdW5jdGlvbl9nZXQgcmV0dXJuZWQgbnVsbCIpO3JldHVybiBzRihQcihvKSl9YXN5bmMgdGFibGVDb21tZW50U2V0KHQsZSxyLG4saSxzKXthd2FpdCB0aGlzLnJwYy5jYWxsKCJjYXRhbG9nX3RhYmxlX2NvbW1lbnRfc2V0Iix7YXR0YWNoX29wYXF1ZV9kYXRhOnQsc2NoZW1hX3BhdGg6UXQoZSksbmFtZTpyLGNvbW1lbnQ6bj8/bnVsbCxpZ25vcmVfbm90X2ZvdW5kOmk/P251bGwsdHJhbnNhY3Rpb25fb3BhcXVlX2RhdGE6cz8/bnVsbH0pfWFzeW5jIHRhYmxlUmVuYW1lKHQsZSxyLG4saSxzKXthd2FpdCB0aGlzLnJwYy5jYWxsKCJjYXRhbG9nX3RhYmxlX3JlbmFtZSIse2F0dGFjaF9vcGFxdWVfZGF0YTp0LHNjaGVtYV9wYXRoOlF0KGUpLG5hbWU6cixuZXdfbmFtZTpuLGlnbm9yZV9ub3RfZm91bmQ6aT8/bnVsbCx0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YTpzPz9udWxsfSl9YXN5bmMgdGFibGVDb2x1bW5BZGQodCxlLHIsbixpLHMsbyxhKXthd2FpdCB0aGlzLnJwYy5jYWxsKCJjYXRhbG9nX3RhYmxlX2NvbHVtbl9hZGQiLHthdHRhY2hfb3BhcXVlX2RhdGE6dCxzY2hlbWFfcGF0aDpRdChlKSxuYW1lOnIsY29sdW1uX25hbWU6bixjb2x1bW5fdHlwZTppLGRlZmF1bHRfdmFsdWU6cz8/bnVsbCxpZ25vcmVfbm90X2ZvdW5kOm8/P251bGwsdHJhbnNhY3Rpb25fb3BhcXVlX2RhdGE6YT8/bnVsbH0pfWFzeW5jIHRhYmxlQ29sdW1uRHJvcCh0LGUscixuLGkscyl7YXdhaXQgdGhpcy5ycGMuY2FsbCgiY2F0YWxvZ190YWJsZV9jb2x1bW5fZHJvcCIse2F0dGFjaF9vcGFxdWVfZGF0YTp0LHNjaGVtYV9wYXRoOlF0KGUpLG5hbWU6cixjb2x1bW5fbmFtZTpuLGlnbm9yZV9ub3RfZm91bmQ6aT8/bnVsbCx0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YTpzPz9udWxsfSl9YXN5bmMgdGFibGVDb2x1bW5SZW5hbWUodCxlLHIsbixpLHMsbyl7YXdhaXQgdGhpcy5ycGMuY2FsbCgiY2F0YWxvZ190YWJsZV9jb2x1bW5fcmVuYW1lIix7YXR0YWNoX29wYXF1ZV9kYXRhOnQsc2NoZW1hX3BhdGg6UXQoZSksbmFtZTpyLGNvbHVtbl9uYW1lOm4sbmV3X25hbWU6aSxpZ25vcmVfbm90X2ZvdW5kOnM/P251bGwsdHJhbnNhY3Rpb25fb3BhcXVlX2RhdGE6bz8/bnVsbH0pfWFzeW5jIHRhYmxlQ29sdW1uRGVmYXVsdFNldCh0LGUscixuLGkscyxvKXthd2FpdCB0aGlzLnJwYy5jYWxsKCJjYXRhbG9nX3RhYmxlX2NvbHVtbl9kZWZhdWx0X3NldCIse2F0dGFjaF9vcGFxdWVfZGF0YTp0LHNjaGVtYV9wYXRoOlF0KGUpLG5hbWU6cixjb2x1bW5fbmFtZTpuLGRlZmF1bHRfdmFsdWU6aSxpZ25vcmVfbm90X2ZvdW5kOnM/P251bGwsdHJhbnNhY3Rpb25fb3BhcXVlX2RhdGE6bz8/bnVsbH0pfWFzeW5jIHRhYmxlQ29sdW1uRGVmYXVsdERyb3AodCxlLHIsbixpLHMpe2F3YWl0IHRoaXMucnBjLmNhbGwoImNhdGFsb2dfdGFibGVfY29sdW1uX2RlZmF1bHRfZHJvcCIse2F0dGFjaF9vcGFxdWVfZGF0YTp0LHNjaGVtYV9wYXRoOlF0KGUpLG5hbWU6cixjb2x1bW5fbmFtZTpuLGlnbm9yZV9ub3RfZm91bmQ6aT8/bnVsbCx0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YTpzPz9udWxsfSl9YXN5bmMgdGFibGVDb2x1bW5UeXBlQ2hhbmdlKHQsZSxyLG4saSxzLG8pe2F3YWl0IHRoaXMucnBjLmNhbGwoImNhdGFsb2dfdGFibGVfY29sdW1uX3R5cGVfY2hhbmdlIix7YXR0YWNoX29wYXF1ZV9kYXRhOnQsc2NoZW1hX3BhdGg6UXQoZSksbmFtZTpyLGNvbHVtbl9kZWZpbml0aW9uOm4sZXhwcmVzc2lvbjppPz9udWxsLGlnbm9yZV9ub3RfZm91bmQ6cz8/ITEsdHJhbnNhY3Rpb25fb3BhcXVlX2RhdGE6bz8/bnVsbH0pfWFzeW5jIHRhYmxlTm90TnVsbFNldCh0LGUscixuLGkscyl7YXdhaXQgdGhpcy5ycGMuY2FsbCgiY2F0YWxvZ190YWJsZV9ub3RfbnVsbF9zZXQiLHthdHRhY2hfb3BhcXVlX2RhdGE6dCxzY2hlbWFfcGF0aDpRdChlKSxuYW1lOnIsY29sdW1uX25hbWU6bixpZ25vcmVfbm90X2ZvdW5kOmk/P251bGwsdHJhbnNhY3Rpb25fb3BhcXVlX2RhdGE6cz8/bnVsbH0pfWFzeW5jIHRhYmxlTm90TnVsbERyb3AodCxlLHIsbixpLHMpe2F3YWl0IHRoaXMucnBjLmNhbGwoImNhdGFsb2dfdGFibGVfbm90X251bGxfZHJvcCIse2F0dGFjaF9vcGFxdWVfZGF0YTp0LHNjaGVtYV9wYXRoOlF0KGUpLG5hbWU6cixjb2x1bW5fbmFtZTpuLGlnbm9yZV9ub3RfZm91bmQ6aT8/bnVsbCx0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YTpzPz9udWxsfSl9YXN5bmMgdmlld0dldCh0LGUscixuKXtsZXQgaT1hd2FpdCB0aGlzLnJwYy5jYWxsKCJjYXRhbG9nX3ZpZXdfZ2V0Iix7YXR0YWNoX29wYXF1ZV9kYXRhOnQsc2NoZW1hX3BhdGg6UXQoZSksbmFtZTpyLHRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhOm4/P251bGx9KTtpZighaSlyZXR1cm4gbnVsbDtsZXQgcz1QcihpKSxvPWxzKHMuaXRlbXMsZEkpO3JldHVybiBvLmxlbmd0aD4wP29bMF06bnVsbH1hc3luYyB2aWV3Q3JlYXRlKHQsZSxyLG4saSxzKXthd2FpdCB0aGlzLnJwYy5jYWxsKCJjYXRhbG9nX3ZpZXdfY3JlYXRlIix7YXR0YWNoX29wYXF1ZV9kYXRhOnQsc2NoZW1hX3BhdGg6UXQoZSksbmFtZTpyLGRlZmluaXRpb246bixvbl9jb25mbGljdDppLHRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhOnM/P251bGx9KX1hc3luYyB2aWV3RHJvcCh0LGUscixuLGkscyl7YXdhaXQgdGhpcy5ycGMuY2FsbCgiY2F0YWxvZ192aWV3X2Ryb3AiLHthdHRhY2hfb3BhcXVlX2RhdGE6dCxzY2hlbWFfcGF0aDpRdChlKSxuYW1lOnIsaWdub3JlX25vdF9mb3VuZDpuPz8hMSxjYXNjYWRlOmk/PyExLHRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhOnM/P251bGx9KX1hc3luYyB2aWV3UmVuYW1lKHQsZSxyLG4saSxzKXthd2FpdCB0aGlzLnJwYy5jYWxsKCJjYXRhbG9nX3ZpZXdfcmVuYW1lIix7YXR0YWNoX29wYXF1ZV9kYXRhOnQsc2NoZW1hX3BhdGg6UXQoZSksbmFtZTpyLG5ld19uYW1lOm4saWdub3JlX25vdF9mb3VuZDppPz9udWxsLHRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhOnM/P251bGx9KX1hc3luYyB2aWV3Q29tbWVudFNldCh0LGUscixuLGkscyl7YXdhaXQgdGhpcy5ycGMuY2FsbCgiY2F0YWxvZ192aWV3X2NvbW1lbnRfc2V0Iix7YXR0YWNoX29wYXF1ZV9kYXRhOnQsc2NoZW1hX3BhdGg6UXQoZSksbmFtZTpyLGNvbW1lbnQ6bj8/bnVsbCxpZ25vcmVfbm90X2ZvdW5kOmk/P251bGwsdHJhbnNhY3Rpb25fb3BhcXVlX2RhdGE6cz8/bnVsbH0pfWFzeW5jIG1hY3JvR2V0KHQsZSxyLG4pe2xldCBpPWF3YWl0IHRoaXMucnBjLmNhbGwoImNhdGFsb2dfbWFjcm9fZ2V0Iix7YXR0YWNoX29wYXF1ZV9kYXRhOnQsc2NoZW1hX3BhdGg6UXQoZSksbmFtZTpyLHRyYW5zYWN0aW9uX29wYXF1ZV9kYXRhOm4/P251bGx9KTtpZighaSlyZXR1cm4gbnVsbDtsZXQgcz1QcihpKSxvPWxzKHMuaXRlbXMsbEkpO3JldHVybiBvLmxlbmd0aD4wP29bMF06bnVsbH1hc3luYyBzY2hlbWFDb250ZW50c01hY3Jvcyh0LGUscixuKXtsZXQgaT1hd2FpdCB0aGlzLnJwYy5jYWxsKCJjYXRhbG9nX3NjaGVtYV9jb250ZW50c19tYWNyb3MiLHthdHRhY2hfb3BhcXVlX2RhdGE6dCxwYXRoOlF0KGUpLHR5cGU6cix0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YTpuPz9udWxsfSk7aWYoIWkpcmV0dXJuW107bGV0IHM9UHIoaSk7cmV0dXJuIGxzKHMuaXRlbXMsbEkpfWFzeW5jIG1hY3JvQ3JlYXRlKHQsZSxyLG4saSxzLG8sYSxsLHUpe2xldCBmPVVvKHthdHRhY2hfb3BhcXVlX2RhdGE6W3RdLHNjaGVtYV9wYXRoOltRdChlKV0sbmFtZTpbcl0sbWFjcm9fdHlwZTpbbl0scGFyYW1ldGVyczpbaV0sZGVmaW5pdGlvbjpbc10sb25fY29uZmxpY3Q6W29dLHBhcmFtZXRlcl9kZWZhdWx0X3ZhbHVlczpbYT8/bnVsbF0sYXJndW1lbnRzX3NjaGVtYTpbbD8/bnVsbF0sdHJhbnNhY3Rpb25fb3BhcXVlX2RhdGE6W3U/P251bGxdfSxyRik7YXdhaXQgdGhpcy5ycGMuY2FsbCgiY2F0YWxvZ19tYWNyb19jcmVhdGUiLFZkKGYpKX1hc3luYyBtYWNyb0Ryb3AodCxlLHIsbixpKXthd2FpdCB0aGlzLnJwYy5jYWxsKCJjYXRhbG9nX21hY3JvX2Ryb3AiLHthdHRhY2hfb3BhcXVlX2RhdGE6dCxzY2hlbWFfcGF0aDpRdChlKSxuYW1lOnIsaWdub3JlX25vdF9mb3VuZDpuPz8hMSx0cmFuc2FjdGlvbl9vcGFxdWVfZGF0YTppPz9udWxsfSl9Y2xvc2UoKXt0aGlzLnJwYy5jbG9zZSgpfX1mdW5jdGlvbiBsRih0KXtsZXQgZT1bXSxyPTA7Zm9yKGxldCBuIG9mIHQuZmllbGRzKXtsZXQgaT1uLm1ldGFkYXRhLG89aS5nZXQoRE4pPT09eE4/bi5uYW1lOnIrKyxhPWkuZ2V0KFROKSxsPWE9PT1FTix1PWE9PT1PTixmPWkuZ2V0KE5OKT09PUZOLHA9aS5nZXQoTU4pPT09TE4sZz1pLmdldChVTik/PyIiLHY9aS5nZXQoUk4pLEk9aS5nZXQoQ04pLEQ9aS5nZXQoUE4pLFo9aS5nZXQoa04pO2UucHVzaCh7bmFtZTpuLm5hbWUscG9zaXRpb246byxhcnJvd1R5cGU6bi50eXBlLGlzVGFibGVJbnB1dDpsLGlzQW55VHlwZTp1LGlzVmFyYXJnczpmLGlzQ29uc3Q6cCxkb2M6ZyxkZWZhdWx0SnNvbjp2LGNob2ljZXNKc29uOkkscmFuZ2VOb3RhdGlvbjpELHBhdHRlcm46Wn0pfXJldHVybiBlfXZhciBqJD1iKFtjKCJuYW1lIixkKCksITEpLGMoImRlc2NyaXB0aW9uIixkKCksITEpLGMoInR5cGUiLGgoKSwhMSksYygiZGVmYXVsdF92YWx1ZSIsaCgpLCEwKSxjKCJyZXF1aXJlZCIsUCgpLCEwKV0pO2Z1bmN0aW9uIHVGKHQpe2xldCBlPVsuLi5raShDYyh0KSldWzBdO2lmKGU9PT12b2lkIDApdGhyb3cgRXJyb3IoIkNhbm5vdCBkZXNlcmlhbGl6ZSBBdHRhY2hPcHRpb25TcGVjIGZyb20gYW4gZW1wdHkgYmF0Y2giKTtsZXQgbj1ZZCh0aShlLnR5cGUpKS5maWVsZHNbMF0udHlwZSxpLHM9ZS5kZWZhdWx0X3ZhbHVlO2lmKHMhPW51bGwpe2xldCBvPXRpKHMpO2lmKG8ubGVuZ3RoPjApaT1bLi4ua2koQ2MobykpXVswXT8udmFsdWV9cmV0dXJue25hbWU6U3RyaW5nKGUubmFtZSksZGVzY3JpcHRpb246U3RyaW5nKGUuZGVzY3JpcHRpb24/PyIiKSx0eXBlOm4sLi4uaT09PXZvaWQgMHx8aT09PW51bGw/e306e2RlZmF1bHQ6aX0scmVxdWlyZWQ6ZS5yZXF1aXJlZD09PSEwfX1mdW5jdGlvbiBmRih0KXtyZXR1cm4gQXJyYXkuZnJvbSh0LHVGKX1KcygpO3ZhciBZdT0idmdpX3JwYy5tZXRob2QiLFFhPSJ2Z2lfcnBjLmxvZ19sZXZlbCIsd0Q9InZnaV9ycGMubG9nX21lc3NhZ2UiLG5iPSJ2Z2lfcnBjLmxvZ19leHRyYSIsS3U9InZnaV9ycGMucmVxdWVzdF92ZXJzaW9uIixGcD0iMSI7dmFyIHZEPSJ2Z2lfcnBjLnByb3RvY29sX25hbWUiO3ZhciBNcD0idmdpX3JwYy5wcm90b2NvbF92ZXJzaW9uIixpYj0iX19kZXNjcmliZV9fIixYcz0idmdpX3JwYy5zdHJlYW1fc3RhdGUjYjY0IixHdT0idmdpX3JwYy5jYWxsX3N0YXRlI2I2NCI7dmFyIExwPSJ2Z2lfcnBjLmxvY2F0aW9uIixzYj0idmdpX3JwYy5sb2NhdGlvbi5zaGEyNTYiO2NsYXNzIHZlIGV4dGVuZHMgRXJyb3J7ZXJyb3JUeXBlO2Vycm9yTWVzc2FnZTtyZW1vdGVUcmFjZWJhY2s7Y29uc3RydWN0b3IodCxlLHIpe3N1cGVyKGAke3R9OiAke2V9YCk7dGhpcy5lcnJvclR5cGU9dCx0aGlzLmVycm9yTWVzc2FnZT1lLHRoaXMucmVtb3RlVHJhY2ViYWNrPXIsdGhpcy5uYW1lPSJScGNFcnJvciJ9fUpzKCk7ZnVuY3Rpb24gaUwodCl7cmV0dXJuIHR5cGVvZiB0PT09Im9iamVjdCImJnQhPT1udWxsJiZ0eXBlb2YgdC5idWZmZXJzPT09Im9iamVjdCJ9ZnVuY3Rpb24gSUQodCxlKXtsZXQgcj0tMTtpZihBcnJheUJ1ZmZlci5pc1ZpZXcodCkpcj10LmJ5dGVMZW5ndGg7ZWxzZSBpZih0IGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpcj10LmJ5dGVMZW5ndGg7ZWxzZSBpZihpTCh0KSlmb3IobGV0IG4gb2YgT2JqZWN0LnZhbHVlcyh0LmJ1ZmZlcnMpKXtsZXQgaT1uPy5ieXRlTGVuZ3RoO2lmKHR5cGVvZiBpPT09Im51bWJlciImJmk+cilyPWl9ZWxzZSBpZih0eXBlb2YgdD09PSJzdHJpbmciKXI9dC5sZW5ndGg7aWYocj4yMTQ3NDgzNjQwKXRocm93IFJhbmdlRXJyb3IoYCR7ZX0gaXMgJHtyfSBieXRlczsgdGhpcyBUeXBlU2NyaXB0IHdvcmtlciBjYW4gZW5jb2RlIGF0IG1vc3QgMjE0NzQ4MzY0MCAoMiBHaUIgLSA4KS4gQm90aCBBcnJvdyBiYWNrZW5kcyBhbGlnbiBidWZmZXJzIHdpdGggKGJ5dGVMZW5ndGggKyA3KSAmIH43LCBhbmQgdGhlIGJpdHdpc2UgJiB0cnVuY2F0ZXMgdG8gaW50MzIsIHNvIGEgbGFyZ2VyIHZhbHVlIHdvdWxkIGJlIHNlbnQgYXMgYSBuZWdhdGl2ZSBib2R5TGVuZ3RoLiBUaGUgd2lyZSBhbmQgdGhlIGArInByb3RvY29sIGNhcnJ5IGl0IGZpbmUg4oCUIHRoZSBsaW1pdCBpcyB0aGUgSmF2YVNjcmlwdCBBcnJvdyBlbmNvZGVycycsIG5vdCB2Z2ktcnBjJ3MuIil9dmFyIG9iPSgpPT5uZXcgY247dmFyIFVwPSgpPT5uZXcgVHI7dmFyIGFiPSh0PW51bGwpPT5uZXcgZGkoUi5NSUNST1NFQ09ORCx0KTtmdW5jdGlvbiBfbCh0LGUscj0hMCxuKXtyZXR1cm4gbmV3IFYodCxlLHIsbj8/bmV3IE1hcCl9ZnVuY3Rpb24gUnAodCxlKXtyZXR1cm4gbmV3IGoodCxlPz9uZXcgTWFwKX1mdW5jdGlvbiBjYih0KXtsZXQgZT1iZS5mcm9tKHQpLHI9Wy4uLmVdO2lmKHIubGVuZ3RoPjApcmV0dXJuIHJbMF0uc2NoZW1hO2lmKGUuc2NoZW1hKXJldHVybiBlLnNjaGVtYTt0aHJvdyBFcnJvcigiQ2Fubm90IGRlc2VyaWFsaXplIHNjaGVtYSBmcm9tIGVtcHR5IElQQyBzdHJlYW0iKX1mdW5jdGlvbiBDcCh0KXtsZXQgZT1iZS5mcm9tKHQpLHI9Wy4uLmVdO2lmKHIubGVuZ3RoPT09MCl7bGV0IG49ZS5zY2hlbWE/P25ldyBqKFtdKSxpPW5ldyBPdChuLmZpZWxkcykscz14KHt0eXBlOmksbGVuZ3RoOjAsY2hpbGRyZW46W10sbnVsbENvdW50OjB9KTtyZXR1cm4gbmV3IEl0KG4scyl9cmV0dXJuIHJbMF19ZnVuY3Rpb24gSnUodCxlKXtsZXQgcj10LG49ci5maWVsZHMubWFwKChvKT0+eWwoby50eXBlKSksaT1uZXcgT3Qoci5maWVsZHMpLHM9eCh7dHlwZTppLGxlbmd0aDowLGNoaWxkcmVuOm4sbnVsbENvdW50OjB9KTtyZXR1cm4gbmV3IEl0KHIscyxlKX1mdW5jdGlvbiB5bCh0KXtsZXQgZT17RGF0YVR5cGU6QSxEYXRhOmh0fTtpZihlLkRhdGFUeXBlLmlzU3RydWN0KHQpKXtsZXQgcj10LmNoaWxkcmVuLm1hcCgobik9PnlsKG4udHlwZSkpO3JldHVybiB4KHt0eXBlOnQsbGVuZ3RoOjAsY2hpbGRyZW46cixudWxsQ291bnQ6MH0pfWlmKGUuRGF0YVR5cGUuaXNMaXN0KHQpKXtsZXQgcj15bCh0LmNoaWxkcmVuWzBdLnR5cGUpO3JldHVybiB4KHt0eXBlOnQsbGVuZ3RoOjAsY2hpbGQ6cixudWxsQ291bnQ6MCx2YWx1ZU9mZnNldHM6bmV3IEludDMyQXJyYXkoWzBdKX0pfWlmKGUuRGF0YVR5cGUuaXNGaXhlZFNpemVMaXN0KHQpKXtsZXQgcj15bCh0LmNoaWxkcmVuWzBdLnR5cGUpO3JldHVybiB4KHt0eXBlOnQsbGVuZ3RoOjAsY2hpbGQ6cixudWxsQ291bnQ6MH0pfWlmKGUuRGF0YVR5cGUuaXNNYXAodCkpe2xldCByPXQuY2hpbGRyZW5bMF0/LnR5cGUsbj1yP3lsKHIpOngoe3R5cGU6bmV3IE90KFtdKSxsZW5ndGg6MCxjaGlsZHJlbjpbXSxudWxsQ291bnQ6MH0pO3JldHVybiB4KHt0eXBlOnQsbGVuZ3RoOjAsY2hpbGQ6bixudWxsQ291bnQ6MCx2YWx1ZU9mZnNldHM6bmV3IEludDMyQXJyYXkoWzBdKX0pfWlmKGUuRGF0YVR5cGUuaXNVbmlvbih0KSl7bGV0IHI9dC5jaGlsZHJlbi5tYXAoKG4pPT55bChuLnR5cGUpKTtpZihlLkRhdGFUeXBlLmlzRGVuc2VVbmlvbih0KSlyZXR1cm4geCh7dHlwZTp0LGxlbmd0aDowLHR5cGVJZHM6bmV3IEludDhBcnJheSgwKSx2YWx1ZU9mZnNldHM6bmV3IEludDMyQXJyYXkoMCksY2hpbGRyZW46cixudWxsQ291bnQ6MH0pO3JldHVybiB4KHt0eXBlOnQsbGVuZ3RoOjAsdHlwZUlkczpuZXcgSW50OEFycmF5KDApLGNoaWxkcmVuOnIsbnVsbENvdW50OjB9KX1yZXR1cm4geCh7dHlwZTp0LGxlbmd0aDowLG51bGxDb3VudDowfSl9ZnVuY3Rpb24gUHAodCxlLHIpe2xldCBuPXQsaT17RGF0YVR5cGU6QSxEYXRhOmh0fSxzPW4uZmllbGRzLm1hcCgobCk9PntsZXQgdT1lW2wubmFtZV07aWYoSUQodSxsLm5hbWUpLHUgaW5zdGFuY2VvZiBpLkRhdGEpcmV0dXJuIHU7cmV0dXJuIEdhKFt1XSxsLnR5cGUpLmRhdGFbMF19KSxvPW5ldyBPdChuLmZpZWxkcyksYT14KHt0eXBlOm8sbGVuZ3RoOjEsY2hpbGRyZW46cyxudWxsQ291bnQ6MH0pO3JldHVybiBuZXcgSXQobixhLHIpfWZ1bmN0aW9uIGxiKHQsZSl7bGV0IHI9bmV3IG5hO3IucmVzZXQodm9pZCAwLHQpO2ZvcihsZXQgbiBvZiBlKXIuX3dyaXRlUmVjb3JkQmF0Y2gobik7cmV0dXJuIHIuY2xvc2UoKSxyLnRvVWludDhBcnJheSghMCl9dmFyIHNMPSh0LGUpPT57aWYodC50eXBlSWQ9PT1lLnR5cGVJZClyZXR1cm4hMTtpZih0LmNvbnN0cnVjdG9yPT09ZS5jb25zdHJ1Y3RvcilyZXR1cm4hMTtyZXR1cm4hMH0sQkQ9KHQpPT50LnR5cGVJZD09PXkuSW50fHx0LnR5cGVJZD09PXkuRmxvYXQ7ZnVuY3Rpb24gdWIodCxlKXtsZXQgcj10O2lmKHIubnVtUm93cz09PTApcmV0dXJuIHQ7bGV0IG49ZTtpZihyLnNjaGVtYS5maWVsZHMubGVuZ3RoIT09bi5maWVsZHMubGVuZ3RoKXRocm93IFR5cGVFcnJvcihgRmllbGQgY291bnQgbWlzbWF0Y2g6IGV4cGVjdGVkICR7bi5maWVsZHMubGVuZ3RofSwgZ290ICR7ci5zY2hlbWEuZmllbGRzLmxlbmd0aH1gKTtmb3IobGV0IGw9MDtsPG4uZmllbGRzLmxlbmd0aDtsKyspaWYoci5zY2hlbWEuZmllbGRzW2xdLm5hbWUhPT1uLmZpZWxkc1tsXS5uYW1lKXRocm93IFR5cGVFcnJvcihgRmllbGQgbmFtZSBtaXNtYXRjaCBhdCBpbmRleCAke2x9OiBleHBlY3RlZCAnJHtuLmZpZWxkc1tsXS5uYW1lfScsIGdvdCAnJHtyLnNjaGVtYS5maWVsZHNbbF0ubmFtZX0nYCk7bGV0IGk9ITEscz1uLmZpZWxkcy5tYXAoKGwsdSk9PntsZXQgZj1yLmRhdGEuY2hpbGRyZW5bdV0scD1mLnR5cGUsZz1sLnR5cGU7aWYocD09PWcpcmV0dXJuIGY7aWYoIXNMKHAsZykpcmV0dXJuIGk9ITAsZi5jbG9uZShnKTtpZihCRChwKSYmQkQoZykpe2k9ITA7bGV0IHY9ci5nZXRDaGlsZEF0KHUpLEk9W107Zm9yKGxldCBEPTA7RDxyLm51bVJvd3M7RCsrKXtsZXQgWj12LmdldChEKTtJLnB1c2godHlwZW9mIFo9PT0iYmlnaW50Ij9OdW1iZXIoWik6Wil9cmV0dXJuIEdhKEksZykuZGF0YVswXX1yZXR1cm4gaT0hMCxmLmNsb25lKGcpfSk7aWYoIWkpcmV0dXJuIHQ7bGV0IG89bmV3IE90KG4uZmllbGRzKSxhPXgoe3R5cGU6byxsZW5ndGg6ci5udW1Sb3dzLGNoaWxkcmVuOnMsbnVsbENvdW50OnIuZGF0YS5udWxsQ291bnQsbnVsbEJpdG1hcDpyLmRhdGEubnVsbEJpdG1hcH0pO3JldHVybiBuZXcgSXQobixhLHIubWV0YWRhdGEpfW1iKCk7ZnVuY3Rpb24gTkQodCxlKXtyZXR1cm4gSnUodCxlKX1mdW5jdGlvbiBTTCh0KXtsZXQgZT1uZXcgVVJMKHQpO2lmKGUucHJvdG9jb2whPT0iaHR0cHM6Iil0aHJvdyBFcnJvcihgRXh0ZXJuYWwgbG9jYXRpb24gVVJMIG11c3QgdXNlIEhUVFBTLCBnb3QgIiR7ZS5wcm90b2NvbH0iYCl9YXN5bmMgZnVuY3Rpb24gQUwodCl7bGV0IGU9bmV3IEFycmF5QnVmZmVyKHQuYnl0ZUxlbmd0aCk7bmV3IFVpbnQ4QXJyYXkoZSkuc2V0KHQpO2xldCByPWF3YWl0IGNyeXB0by5zdWJ0bGUuZGlnZXN0KCJTSEEtMjU2IixlKTtyZXR1cm4gQXJyYXkuZnJvbShuZXcgVWludDhBcnJheShyKSkubWFwKChuKT0+bi50b1N0cmluZygxNikucGFkU3RhcnQoMiwiMCIpKS5qb2luKCIiKX1mdW5jdGlvbiBacyh0KXtpZih0Lm51bVJvd3MhPT0wKXJldHVybiExO2xldCBlPXQubWV0YWRhdGE7aWYoIWUpcmV0dXJuITE7cmV0dXJuIGUuaGFzKExwKSYmIWUuaGFzKFFhKX1mdW5jdGlvbiBGRCh0LGUscil7bGV0IG49bmV3IE1hcDtpZihuLnNldChMcCxlKSxyKW4uc2V0KHNiLHIpO3JldHVybiBORCh0LG4pfWFzeW5jIGZ1bmN0aW9uIGVjKHQsZSl7aWYoIWUpcmV0dXJuIHQ7aWYoIVpzKHQpKXJldHVybiB0O2xldCByPXQubWV0YWRhdGE/LmdldChMcCk7aWYoIXIpcmV0dXJuIHQ7bGV0IG49ZS51cmxWYWxpZGF0b3I9PT1udWxsP3ZvaWQgMDplLnVybFZhbGlkYXRvcj8/U0w7aWYobiluKHIpO2xldCBpPWF3YWl0IGZldGNoKHIpO2lmKCFpLm9rKXRocm93IEVycm9yKGBFeHRlcm5hbCBsb2NhdGlvbiBmZXRjaCBmYWlsZWQ6ICR7aS5zdGF0dXN9ICR7aS5zdGF0dXNUZXh0fSBbdXJsOiAke3J9XWApO2xldCBzPW5ldyBVaW50OEFycmF5KGF3YWl0IGkuYXJyYXlCdWZmZXIoKSk7aWYoaS5oZWFkZXJzLmdldCgiQ29udGVudC1FbmNvZGluZyIpPT09InpzdGQiKXtsZXQgdT1zLmJ5dGVMZW5ndGgqMTY7cz1uZXcgVWludDhBcnJheShhd2FpdCBwYihzLHUpKX1sZXQgYT10Lm1ldGFkYXRhPy5nZXQoc2IpO2lmKGEpe2xldCB1PWF3YWl0IEFMKHMpO2lmKHUhPT1hKXRocm93IEVycm9yKGBTSEEtMjU2IGNoZWNrc3VtIG1pc21hdGNoIGZvciAke3J9OiBleHBlY3RlZCAke2F9LCBnb3QgJHt1fWApfWxldCBsPUNwKHMpO2lmKGwubnVtUm93cz09PTAmJmwuc2NoZW1hLmZpZWxkcy5sZW5ndGg9PT0wKXRocm93IEVycm9yKGBObyBkYXRhIGJhdGNoIGZvdW5kIGluIGV4dGVybmFsIElQQyBzdHJlYW0gZnJvbSAke3J9YCk7cmV0dXJuIGx9dmFyIERMPVsienN0ZCIsImd6aXAiXTt2YXIgQzk9Wy4uLkRMLCJpZGVudGl0eSJdO3ZhciB5Yj0iQ29udGVudC1FbmNvZGluZyIsX2I9IlgtVkdJLUNvbnRlbnQtRW5jb2RpbmciLGdsPSJYLVZHSS1BY2NlcHQtRW5jb2RpbmciO2Z1bmN0aW9uIGJsKHQpe3JldHVybiB0PyJ6c3RkLCBnemlwIjoiZ3ppcCJ9YXN5bmMgZnVuY3Rpb24geEwodCxlLHIpe2xldCBuPWUud3JpdGFibGUuZ2V0V3JpdGVyKCksaT1lLnJlYWRhYmxlLmdldFJlYWRlcigpLHM9bmV3IFVpbnQ4QXJyYXkodC5ieXRlTGVuZ3RoKTtzLnNldCh0KTtsZXQgbz0oYXN5bmMoKT0+e2F3YWl0IG4ud3JpdGUocyksYXdhaXQgbi5jbG9zZSgpfSkoKSxhPVtdLGw9MDt3aGlsZSghMCl7bGV0e3ZhbHVlOnAsZG9uZTpnfT1hd2FpdCBpLnJlYWQoKTtpZihnKWJyZWFrO2xldCB2PXA7aWYobCs9di5ieXRlTGVuZ3RoLHIhPW51bGwmJmw+cil0aHJvdyBFcnJvcihgZ3ppcCBkZWNvbXByZXNzZWQgc2l6ZSAoJHtsfSkgZXhjZWVkcyBjYXAgKCR7cn0pYCk7YS5wdXNoKHYpfWF3YWl0IG87bGV0IHU9bmV3IFVpbnQ4QXJyYXkobCksZj0wO2ZvcihsZXQgcCBvZiBhKXUuc2V0KHAsZiksZis9cC5ieXRlTGVuZ3RoO3JldHVybiB1fWFzeW5jIGZ1bmN0aW9uIE1EKHQsZSl7cmV0dXJuIHhMKHQsbmV3IERlY29tcHJlc3Npb25TdHJlYW0oImd6aXAiKSxlKX12YXIgUXM9ImFwcGxpY2F0aW9uL3ZuZC5hcGFjaGUuYXJyb3cuc3RyZWFtIjt2YXIgejk9UnAoW19sKCJjb3VudCIsb2IoKSwhMCldKSxqOT1ScChbX2woInVwbG9hZF91cmwiLFVwKCksITEpLF9sKCJkb3dubG9hZF91cmwiLFVwKCksITEpLF9sKCJleHBpcmVzX2F0IixhYigiVVRDIiksITEpXSk7ZnVuY3Rpb24gaWEodCxlKXtsZXQgcj1lLm1hcCgobik9PnViKG4sdCkpO3JldHVybiBsYih0LHIpfWZ1bmN0aW9uIExEKHQsZSl7bGV0IHI9dC5nZXQoZSk/P3QuZ2V0KGUudG9Mb3dlckNhc2UoKSk7aWYocj09bnVsbClyZXR1cm4gbnVsbDtsZXQgbj1OdW1iZXIucGFyc2VJbnQociwxMCk7cmV0dXJuIE51bWJlci5pc0Zpbml0ZShuKT9uOm51bGx9ZnVuY3Rpb24gVUQodCl7bGV0IHI9KHQuZ2V0KCJWR0ktVXBsb2FkLVVSTC1TdXBwb3J0Iik/P3QuZ2V0KCJWR0ktVXBsb2FkLVVSTC1TdXBwb3J0Ii50b0xvd2VyQ2FzZSgpKSk9PT0idHJ1ZSIsbj1udWxsLGk9dC5nZXQoIkNhY2hlLUNvbnRyb2wiKT8/dC5nZXQoImNhY2hlLWNvbnRyb2wiKTtpZihpKWZvcihsZXQgcyBvZiBpLnNwbGl0KCIsIikpe2xldCBvPXMudHJpbSgpLnRvTG93ZXJDYXNlKCk7aWYoby5zdGFydHNXaXRoKCJtYXgtYWdlPSIpKXtsZXQgYT1OdW1iZXIucGFyc2VGbG9hdChvLnNsaWNlKDgpKTtpZihOdW1iZXIuaXNGaW5pdGUoYSkpbj1EYXRlLm5vdygpK2EqMTAwMDticmVha319cmV0dXJue21heFJlcXVlc3RCeXRlczpMRCh0LCJWR0ktTWF4LVJlcXVlc3QtQnl0ZXMiKSx1cGxvYWRVcmxTdXBwb3J0OnIsbWF4VXBsb2FkQnl0ZXM6TEQodCwiVkdJLU1heC1VcGxvYWQtQnl0ZXMiKSxjYWNoZUV4cGlyZXNBdDpufX1mdW5jdGlvbiBSRCh0KXtpZighdClyZXR1cm4hMTtpZih0LmNhY2hlRXhwaXJlc0F0PT1udWxsKXJldHVybiEwO3JldHVybiBEYXRlLm5vdygpPHQuY2FjaGVFeHBpcmVzQXR9ZnVuY3Rpb24gVEwodCl7bGV0IGU9dC5nZXQoX2IpPy50cmltKCkudG9Mb3dlckNhc2UoKTtpZihlJiZlIT09ImlkZW50aXR5IilyZXR1cm57Y29kZWM6ZSxjdXN0b206ITB9O2lmKHQuZ2V0KHliKT8udHJpbSgpLnRvTG93ZXJDYXNlKCk9PT0ienN0ZCIpcmV0dXJue2NvZGVjOiJ6c3RkIixjdXN0b206ITF9O3JldHVybntjb2RlYzpudWxsLGN1c3RvbTohMX19YXN5bmMgZnVuY3Rpb24gd2wodCxlLHIpe2xldHtjb2RlYzpuLGN1c3RvbTppfT1UTCh0KTtpZighbilyZXR1cm4gZTtpZihuPT09Imd6aXAiKXJldHVybiBuZXcgVWludDhBcnJheShhd2FpdCBNRChlKSk7aWYobj09PSJ6c3RkIil7aWYoIXIpdGhyb3cgbmV3IHZlKCJQcm90b2NvbEVycm9yIiwiU2VydmVyIHNlbnQgYSB6c3RkLWVuY29kZWQgcmVzcG9uc2UgYnV0IHRoaXMgY2xpZW50IGhhcyBubyB6c3RkIGRlY29kZXIuIEluc3RhbGwgdGhlIG9wdGlvbmFsIHpzdGQgZGVwZW5kZW5jeSwgb3IgY29uZmlndXJlIHRoZSBzZXJ2ZXIgbm90IHRvIG5lZ290aWF0ZSB6c3RkLiIsIiIpO3JldHVybiBuZXcgVWludDhBcnJheShhd2FpdCByKGUpKX10aHJvdyBuZXcgdmUoIlByb3RvY29sRXJyb3IiLGBVbnN1cHBvcnRlZCByZXNwb25zZSBlbmNvZGluZyAnJHtufScke2k/YCAoJHtfYn0pYDpgICgke3lifSlgfS5gLCIiKX1KcygpO0pzKCk7SnMoKTt2YXIgRUw9NjcxMDg4NjQ7ZnVuY3Rpb24gT0wodCl7bGV0IGU9dDtyZXR1cm4gdHlwZW9mIGU/LnJlYWQ9PT0iZnVuY3Rpb24iJiZ0eXBlb2YgZT8ucGlwZT09PSJmdW5jdGlvbiJ9ZnVuY3Rpb24gTkwodCl7cmV0dXJuIG5ldyBQcm94eSh0LHtnZXQoZSxyKXtpZihyPT09InJlYWQiKXJldHVybihpKT0+ZS5yZWFkKHR5cGVvZiBpPT09Im51bWJlciI/TWF0aC5taW4oaSxFTCk6aSk7bGV0IG49UmVmbGVjdC5nZXQoZSxyLGUpO3JldHVybiB0eXBlb2Ygbj09PSJmdW5jdGlvbiI/bi5iaW5kKGUpOm59fSl9Y2xhc3MgenB7cmVhZGVyO2luaXRpYWxpemVkPSExO3N0cmVhbUVuZGVkPSExO2NvbnN0cnVjdG9yKHQpe3RoaXMucmVhZGVyPXR9c3RhdGljIGFzeW5jIGNyZWF0ZSh0KXtsZXQgZT1PTCh0KT9OTCh0KTp0LHI9YXdhaXQgYmUuZnJvbShlKTtpZihhd2FpdCByLm9wZW4oe2F1dG9EZXN0cm95OiExfSksci5jbG9zZWQpdGhyb3cgRXJyb3IoIklucHV0IHN0cmVhbSBjbG9zZWQgYmVmb3JlIGZpcnN0IElQQyBtZXNzYWdlIik7cmV0dXJuIG5ldyB6cChyKX1hc3luYyByZWFkU3RyZWFtKCl7aWYodGhpcy5pbml0aWFsaXplZCl7aWYoYXdhaXQgdGhpcy5yZWFkZXIucmVzZXQoKS5vcGVuKCksdGhpcy5yZWFkZXIuY2xvc2VkKXJldHVybiBudWxsfXRoaXMuaW5pdGlhbGl6ZWQ9ITA7bGV0IHQ9dGhpcy5yZWFkZXIuc2NoZW1hO2lmKCF0KXJldHVybiBudWxsO2xldCBlPVtdO3doaWxlKCEwKXtsZXQgcj1hd2FpdCB0aGlzLnJlYWRlci5uZXh0KCk7aWYoci5kb25lKWJyZWFrO2lmKHIudmFsdWUuY29uc3RydWN0b3IubmFtZT09PSJfSW50ZXJuYWxFbXB0eVBsYWNlaG9sZGVyUmVjb3JkQmF0Y2giKWJyZWFrO2UucHVzaChyLnZhbHVlKX1yZXR1cm57c2NoZW1hOnQsYmF0Y2hlczplfX1hc3luYyBvcGVuTmV4dFN0cmVhbSgpe2lmKHRoaXMuaW5pdGlhbGl6ZWQpe2lmKGF3YWl0IHRoaXMucmVhZGVyLnJlc2V0KCkub3BlbigpLHRoaXMucmVhZGVyLmNsb3NlZClyZXR1cm4gbnVsbH1yZXR1cm4gdGhpcy5pbml0aWFsaXplZD0hMCx0aGlzLnN0cmVhbUVuZGVkPSExLHRoaXMucmVhZGVyLnNjaGVtYT8/bnVsbH1hc3luYyByZWFkTmV4dEJhdGNoKCl7aWYodGhpcy5zdHJlYW1FbmRlZClyZXR1cm4gbnVsbDtsZXQgdD1hd2FpdCB0aGlzLnJlYWRlci5uZXh0KCk7aWYodC5kb25lKXJldHVybiB0aGlzLnN0cmVhbUVuZGVkPSEwLG51bGw7aWYodC52YWx1ZS5jb25zdHJ1Y3Rvci5uYW1lPT09Il9JbnRlcm5hbEVtcHR5UGxhY2Vob2xkZXJSZWNvcmRCYXRjaCIpcmV0dXJuIHRoaXMuc3RyZWFtRW5kZWQ9ITAsbnVsbDtyZXR1cm4gdC52YWx1ZX1hc3luYyBjYW5jZWwoKXthd2FpdCB0aGlzLnJlYWRlci5jYW5jZWwoKX19ZnVuY3Rpb24gQ0QodCl7aWYodHlwZW9mIHQ9PT0ic3RyaW5nIilyZXR1cm4gbmV3IFRyO2lmKHR5cGVvZiB0PT09ImJvb2xlYW4iKXJldHVybiBuZXcgb247aWYodHlwZW9mIHQ9PT0iYmlnaW50IilyZXR1cm4gbmV3IGNuO2lmKHR5cGVvZiB0PT09Im51bWJlciIpcmV0dXJuIG5ldyBaaTtpZih0IGluc3RhbmNlb2YgVWludDhBcnJheSlyZXR1cm4gbmV3IGZpO3JldHVybiBuZXcgVHJ9ZnVuY3Rpb24gZ2IodCxlKXtpZihlPT1udWxsKXJldHVybiBlO2lmKEEuaXNJbnQodCkmJnQuYml0V2lkdGg9PT02NCl7aWYodHlwZW9mIGU9PT0ibnVtYmVyIilyZXR1cm4gQmlnSW50KGUpO3JldHVybiBlfWlmKEEuaXNNYXAodCkpe2lmKGUgaW5zdGFuY2VvZiBNYXApe2xldCBuPXQuY2hpbGRyZW5bMF0udHlwZS5jaGlsZHJlblsxXS50eXBlLGk9bmV3IE1hcDtmb3IobGV0W3Msb11vZiBlKWkuc2V0KHMsZ2IobixvKSk7cmV0dXJuIGl9cmV0dXJuIGV9aWYoQS5pc0xpc3QodCkpe2lmKEFycmF5LmlzQXJyYXkoZSkpe2xldCByPXQuY2hpbGRyZW5bMF0udHlwZTtyZXR1cm4gZS5tYXAoKG4pPT5nYihyLG4pKX1yZXR1cm4gZX1yZXR1cm4gZX1mdW5jdGlvbiByYyh0LGUscixuKXtsZXQgaT1uZXcgTWFwO2lmKGkuc2V0KFl1LHIpLGkuc2V0KEt1LEZwKSxuPy5wcm90b2NvbFZlcnNpb24paS5zZXQoTXAsbi5wcm90b2NvbFZlcnNpb24pO2lmKHQuZmllbGRzLmxlbmd0aD09PTApe2xldCBhPUp1KHQsaSk7cmV0dXJuIGlhKHQsW2FdKX1sZXQgcz17fTtmb3IobGV0IGEgb2YgdC5maWVsZHMpe2xldCBsPWVbYS5uYW1lXTtzW2EubmFtZV09bD09PXZvaWQgMD9udWxsOmdiKGEudHlwZSxsKX1sZXQgbz1QcCh0LHMsaSk7cmV0dXJuIGlhKHQsW29dKX1hc3luYyBmdW5jdGlvbiB0byh0KXtsZXQgZT1hd2FpdCBiZS5mcm9tKHQpO2F3YWl0IGUub3BlbigpO2xldCByPWUuc2NoZW1hO2lmKCFyKXRocm93IG5ldyB2ZSgiUHJvdG9jb2xFcnJvciIsIkVtcHR5IElQQyBzdHJlYW06IG5vIHNjaGVtYSIsIiIpO2xldCBuPWUucmVhZEFsbCgpO3JldHVybntzY2hlbWE6cixiYXRjaGVzOm59fWZ1bmN0aW9uIEhyKHQsZSl7bGV0IHI9dC5tZXRhZGF0YTtpZighcilyZXR1cm4hMTtsZXQgbj1yLmdldChRYSk7aWYoIW4pcmV0dXJuITE7bGV0IGk9ci5nZXQod0QpPz8iIjtpZihuPT09IkVYQ0VQVElPTiIpe2xldCBzPXIuZ2V0KG5iKSxvPSJScGNFcnJvciIsYT1pLGw9IiI7aWYocyl0cnl7bGV0IHU9SlNPTi5wYXJzZShzKTtvPXUuZXhjZXB0aW9uX3R5cGU/PyJScGNFcnJvciIsYT11LmV4Y2VwdGlvbl9tZXNzYWdlPz9pLGw9dS50cmFjZWJhY2s/PyIifWNhdGNoe310aHJvdyBuZXcgdmUobyxhLGwpfWlmKGUpe2xldCBzPXIuZ2V0KG5iKSxvO2lmKHMpdHJ5e289SlNPTi5wYXJzZShzKX1jYXRjaHt9ZSh7bGV2ZWw6bixtZXNzYWdlOmksZXh0cmE6b30pfXJldHVybiEwfWZ1bmN0aW9uIGVvKHQpe2xldCBlPVtdO2ZvcihsZXQgcj0wO3I8dC5udW1Sb3dzO3IrKyl7bGV0IG49e307Zm9yKGxldCBpPTA7aTx0LnNjaGVtYS5maWVsZHMubGVuZ3RoO2krKyl7bGV0IHM9dC5zY2hlbWEuZmllbGRzW2ldLG89dC5nZXRDaGlsZEF0KGkpPy5nZXQocik7aWYodHlwZW9mIG89PT0iYmlnaW50Iil7aWYobz49QmlnSW50KE51bWJlci5NSU5fU0FGRV9JTlRFR0VSKSYmbzw9QmlnSW50KE51bWJlci5NQVhfU0FGRV9JTlRFR0VSKSlvPU51bWJlcihvKX1uW3MubmFtZV09b31lLnB1c2gobil9cmV0dXJuIGV9YXN5bmMgZnVuY3Rpb24gUEQodCl7bGV0IGU9bmV3IFJlYWRhYmxlU3RyZWFtKHtzdGFydChyKXtyLmVucXVldWUodCksci5jbG9zZSgpfX0pO3JldHVybiB6cC5jcmVhdGUoZSl9ZnVuY3Rpb24gYmIodCl7cmV0dXJuIGNiKHQpfWFzeW5jIGZ1bmN0aW9uIEZMKHQsZSl7bGV0IHI9bnVsbDtmb3IobGV0IGEgb2YgdCl7aWYoYS5udW1Sb3dzPT09MCl7SHIoYSxlKTtjb250aW51ZX1yPWF9aWYoIXIpdGhyb3cgRXJyb3IoIkVtcHR5IF9fZGVzY3JpYmVfXyByZXNwb25zZSIpO2xldCBuPXIubWV0YWRhdGEsaT1uPy5nZXQodkQpPz8iIixzPW4/LmdldChNcCk/PyIiLG89W107Zm9yKGxldCBhPTA7YTxyLm51bVJvd3M7YSsrKXtsZXQgbD1yLmdldENoaWxkQXQoMCkuZ2V0KGEpLHU9ci5nZXRDaGlsZEF0KDEpLmdldChhKSxmPXIuZ2V0Q2hpbGRBdCgyKS5nZXQoYSkscD1yLmdldENoaWxkQXQoMykuZ2V0KGEpLGc9ci5nZXRDaGlsZEF0KDQpLmdldChhKSx2PXIuZ2V0Q2hpbGRBdCg1KS5nZXQoYSksST1yLmdldENoaWxkQXQoNik/LmdldChhKSxEPWF3YWl0IGJiKHApLFo9YXdhaXQgYmIoZyksbXQ9e25hbWU6bCx0eXBlOnUscGFyYW1zU2NoZW1hOkQscmVzdWx0U2NoZW1hOlp9O2lmKHU9PT0ic3RyZWFtIiltdC5vdXRwdXRTY2hlbWE9WjtpZih2JiZJKW10LmhlYWRlclNjaGVtYT1hd2FpdCBiYihJKTtvLnB1c2gobXQpfXJldHVybntwcm90b2NvbE5hbWU6aSxwcm90b2NvbFZlcnNpb246cyxtZXRob2RzOm99fWFzeW5jIGZ1bmN0aW9uIHdiKHQsZSl7bGV0IHI9dC5yZXBsYWNlKC9cLyskLywiIiksbj1lPy5wcmVmaXg/PyIiLGk9bmV3IGooW10pLHM9cmMoaSx7fSxpYiksbz17IkNvbnRlbnQtVHlwZSI6UXN9O2lmKGU/LmF1dGhvcml6YXRpb24pby5BdXRob3JpemF0aW9uPWUuYXV0aG9yaXphdGlvbjtsZXQgYT1lPy5jb21wcmVzc2lvbkxldmVsLGw9ZT8uY29tcHJlc3NGbix1PWU/LmRlY29tcHJlc3NGbixmPXM7aWYoYSE9bnVsbCYmbClvWyJDb250ZW50LUVuY29kaW5nIl09InpzdGQiLGY9YXdhaXQgbChzLGEpO2lmKGEhPW51bGwmJnUpb1siQWNjZXB0LUVuY29kaW5nIl09InpzdGQiO29bZ2xdPWJsKHUhPW51bGwpO2xldCBwPWF3YWl0IGZldGNoKGAke3J9JHtufS8ke2lifWAse21ldGhvZDoiUE9TVCIsaGVhZGVyczpvLGJvZHk6Zn0pO2lmKHAuc3RhdHVzPT09NDAxKXRocm93IG5ldyB2ZSgiQXV0aGVudGljYXRpb25FcnJvciIsIkF1dGhlbnRpY2F0aW9uIHJlcXVpcmVkIiwiIik7bGV0IGc9bmV3IFVpbnQ4QXJyYXkoYXdhaXQgcC5hcnJheUJ1ZmZlcigpKSx2PW5ldyBVaW50OEFycmF5KGF3YWl0IHdsKHAuaGVhZGVycyxnLHUpKSx7YmF0Y2hlczpJfT1hd2FpdCB0byh2KTtyZXR1cm4gRkwoSSl9SnMoKTtmdW5jdGlvbiBNTCh0LGUpe3JldHVybiBlPT09bnVsbD90OmAke3QubGVuZ3RofToke3R9JHtlfWB9ZnVuY3Rpb24gdmIodCl7bGV0IGU9dC5pbmRleE9mKCI6Iik7aWYoZTwwKXJldHVybntjdXJzb3I6dCxjYWxsVG9rZW46bnVsbH07bGV0IHI9TnVtYmVyKHQuc2xpY2UoMCxlKSk7aWYoIU51bWJlci5pc0ludGVnZXIocil8fHI8MClyZXR1cm57Y3Vyc29yOnQsY2FsbFRva2VuOm51bGx9O2xldCBuPXQuc2xpY2UoZSsxKTtpZihyPm4ubGVuZ3RoKXJldHVybntjdXJzb3I6dCxjYWxsVG9rZW46bnVsbH07bGV0IGk9bi5zbGljZShyKTtyZXR1cm57Y3Vyc29yOm4uc2xpY2UoMCxyKSxjYWxsVG9rZW46aT09PSIiP251bGw6aX19Y2xhc3MganB7X2Jhc2VVcmw7X3ByZWZpeDtfbWV0aG9kO19zdGF0ZVRva2VuO19jYWxsU3RhdGVUb2tlbjtfb3V0cHV0U2NoZW1hO19pbnB1dFNjaGVtYTtfb25Mb2c7X3BlbmRpbmdCYXRjaGVzO19maW5pc2hlZDtfaGVhZGVyO19jb21wcmVzc2lvbkxldmVsO19jb21wcmVzc0ZuO19kZWNvbXByZXNzRm47X2F1dGhvcml6YXRpb247X2V4dGVybmFsQ29uZmlnO19wb3N0Rm47Y29uc3RydWN0b3IodCl7dGhpcy5fYmFzZVVybD10LmJhc2VVcmwsdGhpcy5fcHJlZml4PXQucHJlZml4LHRoaXMuX21ldGhvZD10Lm1ldGhvZCx0aGlzLl9zdGF0ZVRva2VuPXQuc3RhdGVUb2tlbix0aGlzLl9jYWxsU3RhdGVUb2tlbj10LmNhbGxTdGF0ZVRva2VuPz9udWxsLHRoaXMuX291dHB1dFNjaGVtYT10Lm91dHB1dFNjaGVtYSx0aGlzLl9pbnB1dFNjaGVtYT10LmlucHV0U2NoZW1hLHRoaXMuX29uTG9nPXQub25Mb2csdGhpcy5fcGVuZGluZ0JhdGNoZXM9dC5wZW5kaW5nQmF0Y2hlcyx0aGlzLl9maW5pc2hlZD10LmZpbmlzaGVkLHRoaXMuX2hlYWRlcj10LmhlYWRlcix0aGlzLl9jb21wcmVzc2lvbkxldmVsPXQuY29tcHJlc3Npb25MZXZlbCx0aGlzLl9jb21wcmVzc0ZuPXQuY29tcHJlc3NGbix0aGlzLl9kZWNvbXByZXNzRm49dC5kZWNvbXByZXNzRm4sdGhpcy5fYXV0aG9yaXphdGlvbj10LmF1dGhvcml6YXRpb24sdGhpcy5fZXh0ZXJuYWxDb25maWc9dC5leHRlcm5hbENvbmZpZyx0aGlzLl9wb3N0Rm49dC5wb3N0Rm59YXN5bmMgX3Bvc3QodCxlKXtpZih0aGlzLl9wb3N0Rm4pcmV0dXJuIHRoaXMuX3Bvc3RGbih0LGUpO3JldHVybiBmZXRjaCh0LHttZXRob2Q6IlBPU1QiLGhlYWRlcnM6dGhpcy5fYnVpbGRIZWFkZXJzKCksYm9keTphd2FpdCB0aGlzLl9wcmVwYXJlQm9keShlKX0pfWdldCBoZWFkZXIoKXtyZXR1cm4gdGhpcy5faGVhZGVyfV90b2tlbk1ldGFkYXRhKHQpe2xldCBlPW5ldyBNYXA7aWYoZS5zZXQoWHMsdCksdGhpcy5fY2FsbFN0YXRlVG9rZW4hPT1udWxsKWUuc2V0KEd1LHRoaXMuX2NhbGxTdGF0ZVRva2VuKTtyZXR1cm4gZX1fcmVzdW1lVG9rZW4oKXtyZXR1cm4gdGhpcy5fc3RhdGVUb2tlbj09PW51bGw/bnVsbDpNTCh0aGlzLl9zdGF0ZVRva2VuLHRoaXMuX2NhbGxTdGF0ZVRva2VuKX1fYnVpbGRIZWFkZXJzKCl7bGV0IHQ9eyJDb250ZW50LVR5cGUiOlFzfTtpZih0aGlzLl9jb21wcmVzc2lvbkxldmVsIT1udWxsJiZ0aGlzLl9jb21wcmVzc0ZuKXRbIkNvbnRlbnQtRW5jb2RpbmciXT0ienN0ZCI7aWYodGhpcy5fY29tcHJlc3Npb25MZXZlbCE9bnVsbCYmdGhpcy5fZGVjb21wcmVzc0ZuKXRbIkFjY2VwdC1FbmNvZGluZyJdPSJ6c3RkIjtpZih0W2dsXT1ibCh0aGlzLl9kZWNvbXByZXNzRm4hPW51bGwpLHRoaXMuX2F1dGhvcml6YXRpb24pdC5BdXRob3JpemF0aW9uPXRoaXMuX2F1dGhvcml6YXRpb247cmV0dXJuIHR9YXN5bmMgX3ByZXBhcmVCb2R5KHQpe2lmKHRoaXMuX2NvbXByZXNzaW9uTGV2ZWwhPW51bGwmJnRoaXMuX2NvbXByZXNzRm4pcmV0dXJuIGF3YWl0IHRoaXMuX2NvbXByZXNzRm4odCx0aGlzLl9jb21wcmVzc2lvbkxldmVsKTtyZXR1cm4gdH1hc3luYyBfcmVhZFJlc3BvbnNlKHQpe2xldCBlPW5ldyBVaW50OEFycmF5KGF3YWl0IHQuYXJyYXlCdWZmZXIoKSk7cmV0dXJuIG5ldyBVaW50OEFycmF5KGF3YWl0IHdsKHQuaGVhZGVycyxlLHRoaXMuX2RlY29tcHJlc3NGbikpfWFzeW5jIGV4Y2hhbmdlKHQpe2lmKHRoaXMuX3N0YXRlVG9rZW49PT1udWxsKXRocm93IG5ldyB2ZSgiUHJvdG9jb2xFcnJvciIsIlN0cmVhbSBoYXMgZmluaXNoZWQg4oCUIG5vIHN0YXRlIHRva2VuIGF2YWlsYWJsZSIsIiIpO2lmKHQubGVuZ3RoPT09MCl7bGV0IGw9dGhpcy5faW5wdXRTY2hlbWE/P3RoaXMuX291dHB1dFNjaGVtYSx1PXRoaXMuX2J1aWxkRW1wdHlCYXRjaChsKSxmPW5ldyBJdChsLHUuZGF0YSx0aGlzLl90b2tlbk1ldGFkYXRhKHRoaXMuX3N0YXRlVG9rZW4pKTtyZXR1cm4gdGhpcy5fZG9FeGNoYW5nZShsLFtmXSl9bGV0IHI9T2JqZWN0LmtleXModFswXSkubWFwKChsKT0+e2xldCB1O2ZvcihsZXQgZyBvZiB0KWlmKGdbbF0hPW51bGwpe3U9Z1tsXTticmVha31sZXQgZj1DRCh1KSxwPXQuc29tZSgoZyk9PmdbbF09PW51bGwpO3JldHVybiBuZXcgVihsLGYscCl9KSxuPW5ldyBqKHIpLGk9bi5maWVsZHMubWFwKChsKT0+e2xldCB1PXQubWFwKChmKT0+ZltsLm5hbWVdKTtyZXR1cm4gR2EodSxsLnR5cGUpLmRhdGFbMF19KSxzPW5ldyBPdChuLmZpZWxkcyksbz14KHt0eXBlOnMsbGVuZ3RoOnQubGVuZ3RoLGNoaWxkcmVuOmksbnVsbENvdW50OjB9KSxhPW5ldyBJdChuLG8sdGhpcy5fdG9rZW5NZXRhZGF0YSh0aGlzLl9zdGF0ZVRva2VuKSk7cmV0dXJuIHRoaXMuX2RvRXhjaGFuZ2UobixbYV0pfWFzeW5jIF9kb0V4Y2hhbmdlKHQsZSl7bGV0IHI9aWEodCxlKSxuPWF3YWl0IHRoaXMuX3Bvc3QoYCR7dGhpcy5fYmFzZVVybH0ke3RoaXMuX3ByZWZpeH0vJHt0aGlzLl9tZXRob2R9L2V4Y2hhbmdlYCxyKTtpZihuLnN0YXR1cz09PTQwMSl0aHJvdyBuZXcgdmUoIkF1dGhlbnRpY2F0aW9uRXJyb3IiLCJBdXRoZW50aWNhdGlvbiByZXF1aXJlZCIsIiIpO2xldCBpPWF3YWl0IHRoaXMuX3JlYWRSZXNwb25zZShuKSx7YmF0Y2hlczpzfT1hd2FpdCB0byhpKSxvPVtdO2ZvcihsZXQgYSBvZiBzKXtpZihhLm51bVJvd3M9PT0wKXtIcihhLHRoaXMuX29uTG9nKTtsZXQgdT1hLm1ldGFkYXRhPy5nZXQoWHMpO2lmKHUpdGhpcy5fc3RhdGVUb2tlbj11O2NvbnRpbnVlfWxldCBsPWEubWV0YWRhdGE/LmdldChYcyk7aWYobCl0aGlzLl9zdGF0ZVRva2VuPWw7bz1lbyhhKX1yZXR1cm4gb31fYnVpbGRFbXB0eUJhdGNoKHQpe2xldCBlPXQuZmllbGRzLm1hcCgoaSk9Pngoe3R5cGU6aS50eXBlLGxlbmd0aDowLG51bGxDb3VudDowfSkpLHI9bmV3IE90KHQuZmllbGRzKSxuPXgoe3R5cGU6cixsZW5ndGg6MCxjaGlsZHJlbjplLG51bGxDb3VudDowfSk7cmV0dXJuIG5ldyBJdCh0LG4pfWFzeW5jKltTeW1ib2wuYXN5bmNJdGVyYXRvcl0oKXtmb3IobGV0IHQgb2YgdGhpcy5fcGVuZGluZ0JhdGNoZXMpe2lmKHQubnVtUm93cz09PTApaWYoWnModCkpdD1hd2FpdCBlYyh0LHRoaXMuX2V4dGVybmFsQ29uZmlnKTtlbHNle0hyKHQsdGhpcy5fb25Mb2cpO2NvbnRpbnVlfXlpZWxkIGVvKHQpfWlmKHRoaXMuX3BlbmRpbmdCYXRjaGVzPVtdLHRoaXMuX2ZpbmlzaGVkKXJldHVybjtpZih0aGlzLl9zdGF0ZVRva2VuPT09bnVsbClyZXR1cm47d2hpbGUoITApe2xldCB0PXRoaXMuX3N0YXRlVG9rZW47aWYodD09PW51bGwpcmV0dXJuO2xldCBlPWF3YWl0IHRoaXMuX3NlbmRDb250aW51YXRpb24odCkse2JhdGNoZXM6cn09YXdhaXQgdG8oZSksbj0hMTtmb3IobGV0IGkgb2Ygcil7aWYoaS5udW1Sb3dzPT09MCl7bGV0IHM9aS5tZXRhZGF0YT8uZ2V0KFhzKTtpZihzKXt0aGlzLl9zdGF0ZVRva2VuPXMsbj0hMDtjb250aW51ZX1pZihacyhpKSlpPWF3YWl0IGVjKGksdGhpcy5fZXh0ZXJuYWxDb25maWcpO2Vsc2V7SHIoaSx0aGlzLl9vbkxvZyk7Y29udGludWV9fXlpZWxkIGVvKGkpfWlmKCFuKWJyZWFrfX1hc3luYyBuZXh0V2l0aFRva2VuKCl7bGV0IHQ9Im5leHRXaXRoVG9rZW4gcmVxdWlyZXMgb25lIGRhdGEgYmF0Y2ggcGVyIHJlc3BvbnNlOyB0aGUgdXBzdHJlYW0gd29ya2VyIGJ1ZmZlcmVkIG11bHRpcGxlIChjb25maWd1cmVkIG1heF9yZXNwb25zZV9ieXRlcz8pIjt3aGlsZSh0aGlzLl9wZW5kaW5nQmF0Y2hlcy5sZW5ndGg+MCl7bGV0IHM9dGhpcy5fcGVuZGluZ0JhdGNoZXMuc2hpZnQoKTtpZihzLm51bVJvd3M9PT0wKWlmKFpzKHMpKXM9YXdhaXQgZWMocyx0aGlzLl9leHRlcm5hbENvbmZpZyk7ZWxzZXtIcihzLHRoaXMuX29uTG9nKTtjb250aW51ZX1pZih0aGlzLl9wZW5kaW5nQmF0Y2hlcy5zb21lKChvKT0+by5udW1Sb3dzPjB8fFpzKG8pKSl0aHJvdyBFcnJvcih0KTtyZXR1cm57cm93czplbyhzKSx0b2tlbjp0aGlzLl9yZXN1bWVUb2tlbigpfX1pZih0aGlzLl9maW5pc2hlZHx8dGhpcy5fc3RhdGVUb2tlbj09PW51bGwpcmV0dXJuIHRoaXMuX2ZpbmlzaGVkPSEwLG51bGw7bGV0IGU9YXdhaXQgdGhpcy5fc2VuZENvbnRpbnVhdGlvbih0aGlzLl9zdGF0ZVRva2VuKSx7YmF0Y2hlczpyfT1hd2FpdCB0byhlKSxuPW51bGwsaT1udWxsO2ZvcihsZXQgcyBvZiByKXtpZihzLm51bVJvd3M9PT0wKXtsZXQgbz1zLm1ldGFkYXRhPy5nZXQoWHMpO2lmKG8pe2k9bztjb250aW51ZX1pZihacyhzKSlzPWF3YWl0IGVjKHMsdGhpcy5fZXh0ZXJuYWxDb25maWcpO2Vsc2V7SHIocyx0aGlzLl9vbkxvZyk7Y29udGludWV9fWlmKG4hPT1udWxsKXRocm93IEVycm9yKHQpO249ZW8ocyl9aWYodGhpcy5fc3RhdGVUb2tlbj1pLG49PT1udWxsKXJldHVybiB0aGlzLl9maW5pc2hlZD0hMCxudWxsO3JldHVybntyb3dzOm4sdG9rZW46dGhpcy5fcmVzdW1lVG9rZW4oKX19c2Vla1RvVG9rZW4odCl7bGV0e2N1cnNvcjplLGNhbGxUb2tlbjpyfT12Yih0KTt0aGlzLl9wZW5kaW5nQmF0Y2hlcz1bXSx0aGlzLl9zdGF0ZVRva2VuPWUsdGhpcy5fY2FsbFN0YXRlVG9rZW49cix0aGlzLl9maW5pc2hlZD0hMX1hc3luYyBfc2VuZENvbnRpbnVhdGlvbih0KXtsZXQgZT1uZXcgaihbXSkscj10aGlzLl90b2tlbk1ldGFkYXRhKHQpLG49bmV3IE90KGUuZmllbGRzKSxpPXgoe3R5cGU6bixsZW5ndGg6MSxjaGlsZHJlbjpbXSxudWxsQ291bnQ6MH0pLHM9bmV3IEl0KGUsaSxyKSxvPWlhKGUsW3NdKSxhPWF3YWl0IHRoaXMuX3Bvc3QoYCR7dGhpcy5fYmFzZVVybH0ke3RoaXMuX3ByZWZpeH0vJHt0aGlzLl9tZXRob2R9L2V4Y2hhbmdlYCxvKTtpZihhLnN0YXR1cz09PTQwMSl0aHJvdyBuZXcgdmUoIkF1dGhlbnRpY2F0aW9uRXJyb3IiLCJBdXRoZW50aWNhdGlvbiByZXF1aXJlZCIsIiIpO3JldHVybiB0aGlzLl9yZWFkUmVzcG9uc2UoYSl9Y2xvc2UoKXt9fUpzKCk7dmFyIGtEPSJfX3VwbG9hZF91cmxfXyIsTEw9bmV3IGooW25ldyBWKCJjb3VudCIsbmV3IGNuLCExKV0pO2FzeW5jIGZ1bmN0aW9uIFVMKHQsZSxyLG4pe2xldCBpPXJjKExMLHtjb3VudDpCaWdJbnQocil9LGtEKSxzPXsiQ29udGVudC1UeXBlIjpRc307aWYobilzLkF1dGhvcml6YXRpb249bjtsZXQgbz1hd2FpdCBmZXRjaChgJHt0fSR7ZX0vJHtrRH0vaW5pdGAse21ldGhvZDoiUE9TVCIsaGVhZGVyczpzLGJvZHk6aX0pO2lmKG8uc3RhdHVzPT09NDA0KXRocm93IG5ldyB2ZSgiTm90U3VwcG9ydGVkIiwiU2VydmVyIGRvZXMgbm90IHN1cHBvcnQgdXBsb2FkIFVSTHMiLCIiKTtpZihvLnN0YXR1cz09PTQwMSl0aHJvdyBuZXcgdmUoIkF1dGhlbnRpY2F0aW9uRXJyb3IiLCJBdXRoZW50aWNhdGlvbiByZXF1aXJlZCIsIiIpO2lmKCFvLm9rKXRocm93IG5ldyB2ZSgiSHR0cEVycm9yIixgX191cGxvYWRfdXJsX18vaW5pdCBmYWlsZWQ6IEhUVFAgJHtvLnN0YXR1c31gLCIiKTtsZXQgYT1uZXcgVWludDhBcnJheShhd2FpdCBvLmFycmF5QnVmZmVyKCkpLGw9YXdhaXQgYmUuZnJvbShhKTthd2FpdCBsLm9wZW4oKTtsZXQgdT1bXTtmb3IobGV0IGYgb2YgbC5yZWFkQWxsKCkpe2lmKGYubnVtUm93cz09PTApY29udGludWU7Zm9yKGxldCBwPTA7cDxmLm51bVJvd3M7cCsrKXtsZXQgZz1mLmdldENoaWxkQXQoMCk/LmdldChwKSx2PWYuZ2V0Q2hpbGRBdCgxKT8uZ2V0KHApLEk9Zi5nZXRDaGlsZEF0KDIpPy5nZXQocCksRDtpZihJIGluc3RhbmNlb2YgRGF0ZSlEPUk7ZWxzZSBpZih0eXBlb2YgST09PSJiaWdpbnQiKUQ9bmV3IERhdGUoTnVtYmVyKEkvMTAwMG4pKTtlbHNlIGlmKHR5cGVvZiBJPT09Im51bWJlciIpRD1uZXcgRGF0ZShJKTtlbHNlIEQ9bmV3IERhdGU7dS5wdXNoKHt1cGxvYWRVcmw6Zyxkb3dubG9hZFVybDp2LGV4cGlyZXNBdDpEfSl9fWlmKHUubGVuZ3RoPT09MCl0aHJvdyBuZXcgdmUoIlByb3RvY29sRXJyb3IiLCJTZXJ2ZXIgcmV0dXJuZWQgbm8gdXBsb2FkIFVSTHMiLCIiKTtyZXR1cm4gdX1hc3luYyBmdW5jdGlvbiBSTCh0LGUpe2xldCByPWF3YWl0IGJlLmZyb20odCk7YXdhaXQgci5vcGVuKCk7bGV0IG49ci5zY2hlbWE7aWYoIW4pdGhyb3cgbmV3IHZlKCJQcm90b2NvbEVycm9yIiwiT3JpZ2luYWwgcmVxdWVzdCBib2R5IGhhcyBubyBzY2hlbWEiLCIiKTtsZXQgaT1yLnJlYWRBbGwoKTtpZihpLmxlbmd0aD09PTApdGhyb3cgbmV3IHZlKCJQcm90b2NvbEVycm9yIiwiT3JpZ2luYWwgcmVxdWVzdCBib2R5IGhhcyBubyBiYXRjaGVzIiwiIik7bGV0IG89aVswXS5tZXRhZGF0YT8/bmV3IE1hcCxhPUZEKG4sZSksbD1uZXcgTWFwKGEubWV0YWRhdGE/P25ldyBNYXApLHU9by5nZXQoWXUpLGY9by5nZXQoS3UpPz9GcDtpZih1KWwuc2V0KFl1LHUpO2wuc2V0KEt1LGYpO2ZvcihsZXRbdixJXW9mIG8paWYoIWwuaGFzKHYpKWwuc2V0KHYsSSk7YXdhaXQgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBKcygpKTtsZXQgZz1uZXcgSXQobixhLmRhdGEsbCk7cmV0dXJuIGlhKG4sW2ddKX1hc3luYyBmdW5jdGlvbiBJYih0LGUpe2xldCBuPShhd2FpdCBVTChlLmJhc2VVcmwsZS5wcmVmaXgsMSxlLmF1dGhvcml6YXRpb24pKVswXTtpZihlLnVybFZhbGlkYXRvcillLnVybFZhbGlkYXRvcihuLnVwbG9hZFVybCksZS51cmxWYWxpZGF0b3Iobi5kb3dubG9hZFVybCk7bGV0IGk9YXdhaXQgZmV0Y2gobi51cGxvYWRVcmwse21ldGhvZDoiUFVUIixoZWFkZXJzOnsiQ29udGVudC1UeXBlIjpRc30sYm9keTp0fSk7aWYoIWkub2spdGhyb3cgbmV3IHZlKCJFeHRlcm5hbFVwbG9hZEZhaWxlZCIsYFBVVCB0byB1cGxvYWQgVVJMIGZhaWxlZDogSFRUUCAke2kuc3RhdHVzfWAsIiIpO3JldHVybiBSTCh0LG4uZG93bmxvYWRVcmwpfWZ1bmN0aW9uIENMKHQsZSl7bGV0IHI9dC5yZXBsYWNlKC9cLyskLywiIiksbj0oZT8ucHJlZml4Pz8iIikucmVwbGFjZSgvXC8rJC8sIiIpLGk9ZT8ub25Mb2cscz1lPy5jb21wcmVzc2lvbkxldmVsLG89ZT8uYXV0aG9yaXphdGlvbixhPWU/LmV4dGVybmFsTG9jYXRpb24sbD1udWxsLHU9IiIsZixwLGc9ITEsdj1udWxsO2Z1bmN0aW9uIEkoeil7bGV0IE10PVVEKHouaGVhZGVycyk7aWYoTXQubWF4UmVxdWVzdEJ5dGVzIT1udWxsfHxNdC51cGxvYWRVcmxTdXBwb3J0KXY9TXR9YXN5bmMgZnVuY3Rpb24gRCh6KXtsZXQgTXQ9UkQodik/djpudWxsO2lmKCFNdClyZXR1cm4gejtpZighTXQudXBsb2FkVXJsU3VwcG9ydClyZXR1cm4gejtpZihNdC5tYXhSZXF1ZXN0Qnl0ZXM9PW51bGx8fHouYnl0ZUxlbmd0aDw9TXQubWF4UmVxdWVzdEJ5dGVzKXJldHVybiB6O3JldHVybiBJYih6LHtiYXNlVXJsOnIscHJlZml4Om4sYXV0aG9yaXphdGlvbjpvLHVybFZhbGlkYXRvcjphPy51cmxWYWxpZGF0b3I/P251bGx9KX1hc3luYyBmdW5jdGlvbiBaKHosTXQpe2xldCBncj1hd2FpdCBEKE10KSxVdD1hd2FpdCBmZXRjaCh6LHttZXRob2Q6IlBPU1QiLGhlYWRlcnM6cGUoKSxib2R5OmF3YWl0IEJlKGdyKX0pO2lmKEkoVXQpLFV0LnN0YXR1cz09PTQxMyYmdj8udXBsb2FkVXJsU3VwcG9ydCYmTXQuYnl0ZUxlbmd0aD4wKXtsZXQgWGU9YXdhaXQgSWIoTXQse2Jhc2VVcmw6cixwcmVmaXg6bixhdXRob3JpemF0aW9uOm8sdXJsVmFsaWRhdG9yOmE/LnVybFZhbGlkYXRvcj8/bnVsbH0pO1V0PWF3YWl0IGZldGNoKHose21ldGhvZDoiUE9TVCIsaGVhZGVyczpwZSgpLGJvZHk6YXdhaXQgQmUoWGUpfSksSShVdCl9cmV0dXJuIFV0fWFzeW5jIGZ1bmN0aW9uIG10KCl7aWYoZ3x8cz09bnVsbClyZXR1cm47dHJ5e2xldCB6PWF3YWl0IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKG1iKCkse30pKTtmPU9ELHA9cGJ9Y2F0Y2h7fWc9ITB9ZnVuY3Rpb24gcGUoKXtsZXQgej17IkNvbnRlbnQtVHlwZSI6UXN9O2lmKHMhPW51bGwmJmYpelsiQ29udGVudC1FbmNvZGluZyJdPSJ6c3RkIjtpZihzIT1udWxsJiZwKXpbIkFjY2VwdC1FbmNvZGluZyJdPSJ6c3RkIjtpZih6W2dsXT1ibChwIT1udWxsKSxvKXouQXV0aG9yaXphdGlvbj1vO3JldHVybiB6fWFzeW5jIGZ1bmN0aW9uIEJlKHope2lmKHMhPW51bGwmJmYpcmV0dXJuIGF3YWl0IGYoeixzKTtyZXR1cm4gen1mdW5jdGlvbiBfaSh6KXtpZih6LnN0YXR1cz09PTQwMSl0aHJvdyBuZXcgdmUoIkF1dGhlbnRpY2F0aW9uRXJyb3IiLCJBdXRoZW50aWNhdGlvbiByZXF1aXJlZCIsIiIpfWFzeW5jIGZ1bmN0aW9uIFNlKHope2xldCBNdD1uZXcgVWludDhBcnJheShhd2FpdCB6LmFycmF5QnVmZmVyKCkpO3JldHVybiBuZXcgVWludDhBcnJheShhd2FpdCB3bCh6LmhlYWRlcnMsTXQscCkpfWFzeW5jIGZ1bmN0aW9uIEJ0KCl7aWYobClyZXR1cm4gbDthd2FpdCBtdCgpO2xldCB6PWF3YWl0IHdiKHIse3ByZWZpeDpuLGF1dGhvcml6YXRpb246byxjb21wcmVzc2lvbkxldmVsOnMsY29tcHJlc3NGbjpmLGRlY29tcHJlc3NGbjpwfSk7cmV0dXJuIGw9bmV3IE1hcCh6Lm1ldGhvZHMubWFwKChNdCk9PltNdC5uYW1lLE10XSkpLHU9ei5wcm90b2NvbFZlcnNpb24sbH1yZXR1cm57YXN5bmMgY2FsbCh6LE10KXthd2FpdCBtdCgpO2xldCBVdD0oYXdhaXQgQnQoKSkuZ2V0KHopO2lmKCFVdCl0aHJvdyBFcnJvcihgVW5rbm93biBtZXRob2Q6ICcke3p9J2ApO2xldCBYZT17Li4uVXQuZGVmYXVsdHM/P3t9LC4uLk10Pz97fX0sWXI9cmMoVXQucGFyYW1zU2NoZW1hLFhlLHose3Byb3RvY29sVmVyc2lvbjp1fSksc3I9YXdhaXQgWihgJHtyfSR7bn0vJHt6fWAsWXIpO19pKHNyKTtsZXQgenQ9YXdhaXQgU2Uoc3IpLHtiYXRjaGVzOlN0fT1hd2FpdCB0byh6dCksbGU9bnVsbDtmb3IobGV0IE5yIG9mIFN0KXtpZihOci5udW1Sb3dzPT09MClpZihacyhOcikpTnI9YXdhaXQgZWMoTnIsYSk7ZWxzZXtIcihOcixpKTtjb250aW51ZX1sZT1Ocn1pZighbGUpcmV0dXJuIG51bGw7bGV0IGZuPWVvKGxlKTtpZihmbi5sZW5ndGg9PT0wKXJldHVybiBudWxsO2xldCBvcj1mblswXTtpZihVdC5yZXN1bHRTY2hlbWEuZmllbGRzLmxlbmd0aD09PTApcmV0dXJuIG51bGw7cmV0dXJuIG9yfSxhc3luYyBzdHJlYW0oeixNdCl7YXdhaXQgbXQoKTtsZXQgVXQ9KGF3YWl0IEJ0KCkpLmdldCh6KTtpZighVXQpdGhyb3cgRXJyb3IoYFVua25vd24gbWV0aG9kOiAnJHt6fSdgKTtsZXQgWGU9ey4uLlV0LmRlZmF1bHRzPz97fSwuLi5NdD8/e319LFlyPXJjKFV0LnBhcmFtc1NjaGVtYSxYZSx6LHtwcm90b2NvbFZlcnNpb246dX0pLHNyPWF3YWl0IFooYCR7cn0ke259LyR7en0vaW5pdGAsWXIpO19pKHNyKTtsZXQgenQ9YXdhaXQgU2Uoc3IpLFN0PW51bGwsbGU9bnVsbCxmbj1udWxsLG9yPVtdLE5yPSExLHdzPW51bGw7aWYoVXQuaGVhZGVyU2NoZW1hKXtsZXQgcm89YXdhaXQgUEQoenQpLHNhPWF3YWl0IHJvLnJlYWRTdHJlYW0oKTtpZihzYSlmb3IobGV0IFZlIG9mIHNhLmJhdGNoZXMpe2lmKFZlLm51bVJvd3M9PT0wKXtIcihWZSxpKTtjb250aW51ZX1sZXQgS3I9ZW8oVmUpO2lmKEtyLmxlbmd0aD4wKVN0PUtyWzBdfWxldCBkbj1hd2FpdCByby5yZWFkU3RyZWFtKCk7aWYoZG4pd3M9ZG4uc2NoZW1hO2xldCBhcj1bXTtpZihkbilmb3IobGV0IFZlIG9mIGRuLmJhdGNoZXMpe2lmKFZlLm51bVJvd3M9PT0wKXtsZXQgS3I9VmUubWV0YWRhdGE/LmdldChYcyk7aWYoS3Ipe2xlPUtyLGZuPVZlLm1ldGFkYXRhPy5nZXQoR3UpPz9mbjtjb250aW51ZX1pZihWZS5tZXRhZGF0YT8uZ2V0KFFhKT09PSJFWENFUFRJT04iKXthci5wdXNoKFZlKTtjb250aW51ZX1IcihWZSxpKTtjb250aW51ZX1vci5wdXNoKFZlKX1pZihhci5sZW5ndGg+MClpZihvci5sZW5ndGg+MHx8bGUhPT1udWxsKW9yLnB1c2goLi4uYXIpO2Vsc2UgZm9yKGxldCBWZSBvZiBhcilIcihWZSxpKTtpZighZG4mJiFsZSlOcj0hMH1lbHNle2xldHtzY2hlbWE6cm8sYmF0Y2hlczpzYX09YXdhaXQgdG8oenQpO3dzPXJvO2xldCBkbj1bXTtmb3IobGV0IGFyIG9mIHNhKXtpZihhci5udW1Sb3dzPT09MCl7bGV0IFZlPWFyLm1ldGFkYXRhPy5nZXQoWHMpO2lmKFZlKXtsZT1WZSxmbj1hci5tZXRhZGF0YT8uZ2V0KEd1KT8/Zm47Y29udGludWV9aWYoYXIubWV0YWRhdGE/LmdldChRYSk9PT0iRVhDRVBUSU9OIil7ZG4ucHVzaChhcik7Y29udGludWV9SHIoYXIsaSk7Y29udGludWV9b3IucHVzaChhcil9aWYoZG4ubGVuZ3RoPjApaWYob3IubGVuZ3RoPjB8fGxlIT09bnVsbClvci5wdXNoKC4uLmRuKTtlbHNlIGZvcihsZXQgYXIgb2YgZG4pSHIoYXIsaSl9aWYob3IubGVuZ3RoPT09MCYmbGU9PT1udWxsKU5yPSEwO2xldCB0Zj0od3MmJndzLmZpZWxkcy5sZW5ndGg+MD93czpudWxsKT8/KG9yLmxlbmd0aD4wP29yWzBdLnNjaGVtYTpudWxsKT8/VXQub3V0cHV0U2NoZW1hPz9VdC5yZXN1bHRTY2hlbWE7cmV0dXJuIG5ldyBqcCh7YmFzZVVybDpyLHByZWZpeDpuLG1ldGhvZDp6LHN0YXRlVG9rZW46bGUsY2FsbFN0YXRlVG9rZW46Zm4sb3V0cHV0U2NoZW1hOnRmLGlucHV0U2NoZW1hOlV0LmlucHV0U2NoZW1hLG9uTG9nOmkscGVuZGluZ0JhdGNoZXM6b3IsZmluaXNoZWQ6TnIsaGVhZGVyOlN0LGNvbXByZXNzaW9uTGV2ZWw6cyxjb21wcmVzc0ZuOmYsZGVjb21wcmVzc0ZuOnAsYXV0aG9yaXphdGlvbjpvLGV4dGVybmFsQ29uZmlnOmEscG9zdEZuOlp9KX0sYXN5bmMgcmVzdW1lU3RyZWFtKHosTXQsZ3Ipe2F3YWl0IG10KCk7bGV0e2N1cnNvcjpVdCxjYWxsVG9rZW46WGV9PXZiKE10KTtyZXR1cm4gbmV3IGpwKHtiYXNlVXJsOnIscHJlZml4Om4sbWV0aG9kOnosc3RhdGVUb2tlbjpVdCxjYWxsU3RhdGVUb2tlbjpYZSxvdXRwdXRTY2hlbWE6Z3I/P25ldyBqKFtdKSxvbkxvZzppLHBlbmRpbmdCYXRjaGVzOltdLGZpbmlzaGVkOiExLGhlYWRlcjpudWxsLGNvbXByZXNzaW9uTGV2ZWw6cyxjb21wcmVzc0ZuOmYsZGVjb21wcmVzc0ZuOnAsYXV0aG9yaXphdGlvbjpvLGV4dGVybmFsQ29uZmlnOmEscG9zdEZuOlp9KX0sYXN5bmMgZGVzY3JpYmUoKXtyZXR1cm4gYXdhaXQgbXQoKSx3YihyLHtwcmVmaXg6bixhdXRob3JpemF0aW9uOm8sY29tcHJlc3Npb25MZXZlbDpzLGNvbXByZXNzRm46ZixkZWNvbXByZXNzRm46cH0pfSxjbG9zZSgpe319fWV4cG9ydHtDSSBhcyBGdW5jdGlvblR5cGUsR3QgYXMgVHlwZUlkLGVfIGFzIFZnaUNsaWVudCxlciBhcyBWZ2lDbGllbnRFcnJvcixmRiBhcyBkZXNlcmlhbGl6ZUF0dGFjaE9wdGlvblNwZWNzLFlkIGFzIGRlc2VyaWFsaXplU2NoZW1hLENMIGFzIGh0dHBDb25uZWN0LGxGIGFzIHNjaGVtYVRvQXJndW1lbnRTcGVjc307Cg==\";\n\nfunction decodeBase64(b64: string): Uint8Array {\n // atob is available on Node >=16, Bun, Deno, and workerd.\n const bin = atob(b64);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\n/** The vendored VGI browser client bundle, decoded to its raw bytes. */\nexport const CLIENT_BUNDLE_BYTES: Uint8Array = decodeBase64(CLIENT_BUNDLE_B64);\n",
|
|
63
67
|
"// Copyright 2025, 2026 Query Farm LLC - https://query.farm\n// SPDX-License-Identifier: LicenseRef-QueryFarm-Source-Available-1.0\n\n// The standardized VGI landing surface.\n//\n// This lives here, not in `@query-farm/vgi-rpc`, because everything it serves\n// is VGI vocabulary: a page that renders catalogs, schemas, tables, functions\n// and macros, and the browser build of *this package's* client that reads them\n// over the protocol. vgi-rpc is generic RPC over Arrow and depends on nothing\n// here — yet it used to vendor both assets, which put a compiled artifact of\n// the higher layer inside the lower one and added ~900 KB to every consumer of\n// vgi-rpc, whether or not they served a VGI page. vgi-python already drew the\n// line this way: its landing surface is in `vgi/http/`, and `vgi_rpc/http/` has\n// neither asset.\n//\n// It reaches the request through vgi-rpc's `extraRoutes` hook rather than by\n// wrapping the returned fetch handler, because ordering matters. Contributed\n// routes run at the same pipeline position the surface occupied when it lived\n// inside vgi-rpc — after the OAuth browser-redirect branch, and before the\n// generic landing page and the 404. Wrapping from outside would answer ahead of\n// that redirect, so a worker with OAuth configured would show this page to a\n// browser that should have been sent to its identity provider first.\n//\n// That redirect is the only thing guarding these two routes, and only for\n// browsers: vgi-rpc gates GET pages on `authenticate && pkceConfig`, and a\n// non-browser caller that fails auth falls through to normal page serving. So\n// on a worker with no PKCE configured, the page and the client bundle are\n// public — as the generic landing page always was. Worth knowing before\n// treating anything on this surface as private; vgi-rpc-python is stricter and\n// answers 401 here.\n\nimport type { ExtraRouteContext, ExtraRouteHandler } from \"@query-farm/vgi-rpc\";\nimport { LANDING_HTML_BYTES } from \"./landing-html.js\";\nimport { CLIENT_BUNDLE_BYTES } from \"./client-bundle.js\";\n\n/**\n * Worker identity for the standardized VGI landing surface.\n *\n * The shared `landing.html` reads catalog metadata by speaking the VGI protocol\n * through the client bundle the worker serves beside it, so nothing about the\n * catalog belongs here. What the protocol has no method for — which worker this\n * is, what it is called, what version it runs — rides on the JSON status\n * document at `GET {prefix}/?format=json`.\n */\nexport interface LandingInfo {\n /** Worker name shown as the page heading, e.g. \"ishares\". */\n name: string;\n /** One-line description shown under the heading. */\n doc?: string;\n /** Worker version string shown in the footer. */\n version?: string;\n /** Override the Cupola base URL the \"Explore\" links point at. */\n cupolaBase?: string;\n}\n\n/** Default Cupola deployment the page's \"Explore\" links point at. */\nexport const DEFAULT_CUPOLA_BASE = \"https://cupola.query-farm.services\";\n\n// Caching. Both assets are immutable for a given build but live at URLs that\n// never change, which is the combination that goes wrong quietly: the page used\n// to be served with no Cache-Control and no validator at all, so browsers\n// applied heuristic caching with nothing to revalidate against and could hold a\n// stale page indefinitely — every landing-page fix needed a shift-reload to\n// see. The bundle was worse in a different way: `max-age=3600` with no\n// validator meant a full hour where a client could not learn that a release had\n// happened, which is how a bundle that could not decode workerd's compressed\n// responses stayed live in a browser long after it was fixed.\n//\n// `no-cache` does not mean \"do not store\" — it means \"store, but revalidate\n// before reuse\". With a strong ETag a repeat visit is a conditional GET that\n// answers 304 with no body, so the bandwidth is the same as a long TTL and the\n// staleness window closes to zero. `public` is kept so shared caches (the\n// Cloudflare edge in front of a Workers deployment) can hold and revalidate it\n// too, rather than each viewer paying the full transfer.\nconst REVALIDATE = \"public, no-cache\";\n\n/**\n * FNV-1a over the asset bytes, as a strong ETag.\n *\n * Computed lazily and memoised rather than at module load: most requests to a\n * worker are RPC and never touch these routes, and hashing ~700 KB on every\n * isolate start would tax cold starts for a page nobody may open. Once per\n * isolate on first use is the right trade.\n */\nfunction etagFor(bytes: Uint8Array): string {\n let hash = 0x811c9dc5;\n for (let i = 0; i < bytes.length; i++) {\n hash ^= bytes[i]!;\n hash = Math.imul(hash, 0x01000193) >>> 0;\n }\n // Length is folded in so two builds that collide on the hash still differ.\n return `\"${hash.toString(16)}-${bytes.length.toString(16)}\"`;\n}\n\nlet landingEtag: string | null = null;\nlet bundleEtag: string | null = null;\n\n/** 304 when the client already holds this exact body, else null. */\nfunction notModified(request: Request, etag: string, extra?: HeadersInit): Response | null {\n const ifNoneMatch = request.headers.get(\"If-None-Match\");\n if (!ifNoneMatch) return null;\n // A conditional GET may list several validators, and a cache is allowed to\n // weaken ours to `W/\"…\"` on the way back.\n const matches = ifNoneMatch\n .split(\",\")\n .map((c) => c.trim().replace(/^W\\//, \"\"))\n .includes(etag);\n if (!matches) return null;\n const headers = new Headers(extra);\n headers.set(\"ETag\", etag);\n headers.set(\"Cache-Control\", REVALIDATE);\n return new Response(null, { status: 304, headers });\n}\n\n/**\n * Build the VGI landing surface as a route contributed to vgi-rpc's HTTP\n * handler.\n *\n * Serves two paths, both relative to the handler's mount prefix:\n *\n * - `GET {prefix}/` — the shared `landing.html` for browsers, or a JSON status\n * document for health checks, `?format=json`, and the page's own identity\n * read. Content negotiation matches vgi-python's `LandingPageResource`.\n * - `GET {prefix}/vgi-client.js` — the browser build the page imports.\n *\n * Anything else returns `null`, which lets normal routing continue.\n */\nexport function createLandingRoutes(info: LandingInfo): ExtraRouteHandler {\n return (request: Request, ctx: ExtraRouteContext): Response | null => {\n const path = ctx.url.pathname;\n const { prefix } = ctx;\n\n if (path === prefix || path === `${prefix}/`) {\n const accept = request.headers.get(\"Accept\") ?? \"\";\n const wantJson =\n ctx.url.searchParams.get(\"format\") === \"json\" ||\n (accept.includes(\"application/json\") && !accept.includes(\"text/html\"));\n if (wantJson) {\n // Rebuilt per request rather than cached: `oauthActive` and `serverId`\n // come from the handler, so this cannot be pre-rendered at construction\n // time the way it was when it lived inside vgi-rpc.\n const body = JSON.stringify({\n status: \"ok\",\n server_id: ctx.serverId,\n protocol: \"vgi\",\n worker: info.name,\n doc: info.doc ?? \"\",\n version: info.version ?? \"\",\n lang: \"typescript\",\n oauth: ctx.oauthActive,\n cupola_base: info.cupolaBase ?? DEFAULT_CUPOLA_BASE,\n });\n const headers = new Headers({ \"Content-Type\": \"application/json\" });\n ctx.addCorsHeaders(headers);\n return new Response(body, { status: 200, headers });\n }\n landingEtag ??= etagFor(LANDING_HTML_BYTES);\n const conditional = notModified(request, landingEtag);\n if (conditional) {\n ctx.addCorsHeaders(conditional.headers);\n return conditional;\n }\n const headers = new Headers({\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": REVALIDATE,\n ETag: landingEtag,\n });\n ctx.addCorsHeaders(headers);\n return new Response(LANDING_HTML_BYTES as unknown as BodyInit, { status: 200, headers });\n }\n\n // Served by the worker rather than from a CDN: this page is same-origin\n // with an authenticated worker and carries its session cookie, so\n // third-party script here would run with full access to that origin — and a\n // CDN dependency would break air-gapped deployments that today need nothing\n // but the worker.\n if (path === `${prefix}/vgi-client.js`) {\n bundleEtag ??= etagFor(CLIENT_BUNDLE_BYTES);\n const conditional = notModified(request, bundleEtag);\n if (conditional) {\n ctx.addCorsHeaders(conditional.headers);\n return conditional;\n }\n const headers = new Headers({\n \"Content-Type\": \"text/javascript; charset=utf-8\",\n \"Cache-Control\": REVALIDATE,\n ETag: bundleEtag,\n });\n ctx.addCorsHeaders(headers);\n return new Response(CLIENT_BUNDLE_BYTES as unknown as BodyInit, { status: 200, headers });\n }\n\n return null;\n };\n}\n"
|
|
64
68
|
],
|
|
65
|
-
"mappings": "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",
|
|
66
|
-
"debugId": "
|
|
69
|
+
"mappings": "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B,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACvB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACxB,MAAO,MAAM,MAAO;AAAA,IACpB,MAAM,KAAK,MAAM,KAAK,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",
|
|
70
|
+
"debugId": "CEC41B08D9AF368564756E2164756E21",
|
|
67
71
|
"names": []
|
|
68
72
|
}
|