@sentry/node 8.53.0 → 9.0.0-alpha.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/build/cjs/cron/common.js +1 -1
- package/build/cjs/cron/cron.js +1 -1
- package/build/cjs/cron/index.js +1 -1
- package/build/cjs/cron/node-cron.js +10 -11
- package/build/cjs/cron/node-cron.js.map +1 -1
- package/build/cjs/cron/node-schedule.js +2 -6
- package/build/cjs/cron/node-schedule.js.map +1 -1
- package/build/cjs/debug-build.js +1 -1
- package/build/cjs/index.js +3 -15
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/integrations/anr/index.js +8 -13
- package/build/cjs/integrations/anr/index.js.map +1 -1
- package/build/cjs/integrations/childProcess.js +19 -24
- package/build/cjs/integrations/childProcess.js.map +1 -1
- package/build/cjs/integrations/console.js +1 -1
- package/build/cjs/integrations/context.js +16 -19
- package/build/cjs/integrations/context.js.map +1 -1
- package/build/cjs/integrations/contextlines.js +6 -10
- package/build/cjs/integrations/contextlines.js.map +1 -1
- package/build/cjs/integrations/fs.js +1 -1
- package/build/cjs/integrations/http/SentryHttpInstrumentation.js +99 -19
- package/build/cjs/integrations/http/SentryHttpInstrumentation.js.map +1 -1
- package/build/cjs/integrations/http/index.js +32 -46
- package/build/cjs/integrations/http/index.js.map +1 -1
- package/build/cjs/integrations/http/vendor/getRequestInfo.js +1 -1
- package/build/cjs/integrations/http/vendor/getRequestInfo.js.map +1 -1
- package/build/cjs/integrations/local-variables/common.js +1 -1
- package/build/cjs/integrations/local-variables/index.js +1 -1
- package/build/cjs/integrations/local-variables/local-variables-async.js +4 -8
- package/build/cjs/integrations/local-variables/local-variables-async.js.map +1 -1
- package/build/cjs/integrations/local-variables/local-variables-sync.js +18 -22
- package/build/cjs/integrations/local-variables/local-variables-sync.js.map +1 -1
- package/build/cjs/integrations/modules.js +2 -2
- package/build/cjs/integrations/modules.js.map +1 -1
- package/build/cjs/integrations/node-fetch.js +3 -7
- package/build/cjs/integrations/node-fetch.js.map +1 -1
- package/build/cjs/integrations/onuncaughtexception.js +1 -1
- package/build/cjs/integrations/onunhandledrejection.js +1 -1
- package/build/cjs/integrations/processSession.js +36 -0
- package/build/cjs/integrations/processSession.js.map +1 -0
- package/build/cjs/integrations/spotlight.js +2 -2
- package/build/cjs/integrations/spotlight.js.map +1 -1
- package/build/cjs/integrations/tracing/amqplib.js +1 -1
- package/build/cjs/integrations/tracing/connect.js +2 -2
- package/build/cjs/integrations/tracing/connect.js.map +1 -1
- package/build/cjs/integrations/tracing/dataloader.js +2 -6
- package/build/cjs/integrations/tracing/dataloader.js.map +1 -1
- package/build/cjs/integrations/tracing/express.js +4 -31
- package/build/cjs/integrations/tracing/express.js.map +1 -1
- package/build/cjs/integrations/tracing/fastify.js +3 -7
- package/build/cjs/integrations/tracing/fastify.js.map +1 -1
- package/build/cjs/integrations/tracing/genericPool.js +1 -1
- package/build/cjs/integrations/tracing/graphql.js +5 -5
- package/build/cjs/integrations/tracing/graphql.js.map +1 -1
- package/build/cjs/integrations/tracing/hapi/index.js +5 -9
- package/build/cjs/integrations/tracing/hapi/index.js.map +1 -1
- package/build/cjs/integrations/tracing/index.js +1 -6
- package/build/cjs/integrations/tracing/index.js.map +1 -1
- package/build/cjs/integrations/tracing/kafka.js +1 -1
- package/build/cjs/integrations/tracing/knex.js +2 -2
- package/build/cjs/integrations/tracing/knex.js.map +1 -1
- package/build/cjs/integrations/tracing/koa.js +4 -8
- package/build/cjs/integrations/tracing/koa.js.map +1 -1
- package/build/cjs/integrations/tracing/lrumemoizer.js +1 -1
- package/build/cjs/integrations/tracing/mongo.js +1 -1
- package/build/cjs/integrations/tracing/mongoose.js +1 -1
- package/build/cjs/integrations/tracing/mysql.js +1 -1
- package/build/cjs/integrations/tracing/mysql2.js +1 -1
- package/build/cjs/integrations/tracing/postgres.js +1 -1
- package/build/cjs/integrations/tracing/prisma.js +16 -21
- package/build/cjs/integrations/tracing/prisma.js.map +1 -1
- package/build/cjs/integrations/tracing/redis.js +4 -8
- package/build/cjs/integrations/tracing/redis.js.map +1 -1
- package/build/cjs/integrations/tracing/tedious.js +3 -7
- package/build/cjs/integrations/tracing/tedious.js.map +1 -1
- package/build/cjs/integrations/tracing/vercelai/index.js +14 -20
- package/build/cjs/integrations/tracing/vercelai/index.js.map +1 -1
- package/build/cjs/integrations/tracing/vercelai/instrumentation.js +1 -1
- package/build/cjs/nodeVersion.js +1 -1
- package/build/cjs/otel/contextManager.js +2 -2
- package/build/cjs/otel/contextManager.js.map +1 -1
- package/build/cjs/otel/instrument.js +1 -1
- package/build/cjs/proxy/base.js +30 -33
- package/build/cjs/proxy/base.js.map +1 -1
- package/build/cjs/proxy/index.js +3 -8
- package/build/cjs/proxy/index.js.map +1 -1
- package/build/cjs/proxy/parse-proxy-response.js +2 -2
- package/build/cjs/proxy/parse-proxy-response.js.map +1 -1
- package/build/cjs/sdk/api.js +2 -2
- package/build/cjs/sdk/api.js.map +1 -1
- package/build/cjs/sdk/client.js +3 -8
- package/build/cjs/sdk/client.js.map +1 -1
- package/build/cjs/sdk/index.js +5 -58
- package/build/cjs/sdk/index.js.map +1 -1
- package/build/cjs/sdk/initOtel.js +8 -22
- package/build/cjs/sdk/initOtel.js.map +1 -1
- package/build/cjs/transports/http.js +10 -16
- package/build/cjs/transports/http.js.map +1 -1
- package/build/cjs/utils/addOriginToSpan.js +1 -1
- package/build/cjs/utils/commonjs.js +1 -1
- package/build/cjs/utils/createMissingInstrumentationContext.js +1 -1
- package/build/cjs/utils/debug.js +1 -1
- package/build/cjs/utils/ensureIsWrapped.js +2 -6
- package/build/cjs/utils/ensureIsWrapped.js.map +1 -1
- package/build/cjs/utils/envToBool.js +2 -2
- package/build/cjs/utils/envToBool.js.map +1 -1
- package/build/cjs/utils/errorhandling.js +2 -3
- package/build/cjs/utils/errorhandling.js.map +1 -1
- package/build/cjs/utils/getRequestUrl.js +1 -1
- package/build/cjs/utils/module.js +1 -1
- package/build/cjs/utils/module.js.map +1 -1
- package/build/cjs/utils/redisCache.js +1 -4
- package/build/cjs/utils/redisCache.js.map +1 -1
- package/build/esm/cron/node-cron.js +9 -7
- package/build/esm/cron/node-cron.js.map +1 -1
- package/build/esm/cron/node-schedule.js +1 -2
- package/build/esm/cron/node-schedule.js.map +1 -1
- package/build/esm/index.js +3 -4
- package/build/esm/index.js.map +1 -1
- package/build/esm/integrations/anr/index.js +8 -9
- package/build/esm/integrations/anr/index.js.map +1 -1
- package/build/esm/integrations/anr/worker-script.js +2 -2
- package/build/esm/integrations/childProcess.js +20 -24
- package/build/esm/integrations/childProcess.js.map +1 -1
- package/build/esm/integrations/context.js +15 -15
- package/build/esm/integrations/context.js.map +1 -1
- package/build/esm/integrations/contextlines.js +5 -6
- package/build/esm/integrations/contextlines.js.map +1 -1
- package/build/esm/integrations/http/SentryHttpInstrumentation.js +99 -20
- package/build/esm/integrations/http/SentryHttpInstrumentation.js.map +1 -1
- package/build/esm/integrations/http/index.js +32 -43
- package/build/esm/integrations/http/index.js.map +1 -1
- package/build/esm/integrations/http/vendor/getRequestInfo.js.map +1 -1
- package/build/esm/integrations/local-variables/local-variables-async.js +3 -4
- package/build/esm/integrations/local-variables/local-variables-async.js.map +1 -1
- package/build/esm/integrations/local-variables/local-variables-sync.js +17 -18
- package/build/esm/integrations/local-variables/local-variables-sync.js.map +1 -1
- package/build/esm/integrations/local-variables/worker-script.js +2 -2
- package/build/esm/integrations/modules.js +1 -1
- package/build/esm/integrations/modules.js.map +1 -1
- package/build/esm/integrations/node-fetch.js +3 -4
- package/build/esm/integrations/node-fetch.js.map +1 -1
- package/build/esm/integrations/processSession.js +34 -0
- package/build/esm/integrations/processSession.js.map +1 -0
- package/build/esm/integrations/spotlight.js +1 -1
- package/build/esm/integrations/spotlight.js.map +1 -1
- package/build/esm/integrations/tracing/connect.js +1 -1
- package/build/esm/integrations/tracing/connect.js.map +1 -1
- package/build/esm/integrations/tracing/dataloader.js +1 -2
- package/build/esm/integrations/tracing/dataloader.js.map +1 -1
- package/build/esm/integrations/tracing/express.js +4 -28
- package/build/esm/integrations/tracing/express.js.map +1 -1
- package/build/esm/integrations/tracing/fastify.js +2 -3
- package/build/esm/integrations/tracing/fastify.js.map +1 -1
- package/build/esm/integrations/tracing/graphql.js +4 -4
- package/build/esm/integrations/tracing/graphql.js.map +1 -1
- package/build/esm/integrations/tracing/hapi/index.js +4 -5
- package/build/esm/integrations/tracing/hapi/index.js.map +1 -1
- package/build/esm/integrations/tracing/index.js +0 -5
- package/build/esm/integrations/tracing/index.js.map +1 -1
- package/build/esm/integrations/tracing/knex.js +1 -1
- package/build/esm/integrations/tracing/knex.js.map +1 -1
- package/build/esm/integrations/tracing/koa.js +3 -4
- package/build/esm/integrations/tracing/koa.js.map +1 -1
- package/build/esm/integrations/tracing/prisma.js +15 -17
- package/build/esm/integrations/tracing/prisma.js.map +1 -1
- package/build/esm/integrations/tracing/redis.js +4 -5
- package/build/esm/integrations/tracing/redis.js.map +1 -1
- package/build/esm/integrations/tracing/tedious.js +2 -3
- package/build/esm/integrations/tracing/tedious.js.map +1 -1
- package/build/esm/integrations/tracing/vercelai/index.js +13 -16
- package/build/esm/integrations/tracing/vercelai/index.js.map +1 -1
- package/build/esm/otel/contextManager.js +1 -1
- package/build/esm/otel/contextManager.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/proxy/base.js +29 -29
- package/build/esm/proxy/base.js.map +1 -1
- package/build/esm/proxy/index.js +2 -3
- package/build/esm/proxy/index.js.map +1 -1
- package/build/esm/proxy/parse-proxy-response.js +1 -1
- package/build/esm/proxy/parse-proxy-response.js.map +1 -1
- package/build/esm/sdk/api.js +1 -1
- package/build/esm/sdk/api.js.map +1 -1
- package/build/esm/sdk/client.js +2 -3
- package/build/esm/sdk/client.js.map +1 -1
- package/build/esm/sdk/index.js +5 -58
- package/build/esm/sdk/index.js.map +1 -1
- package/build/esm/sdk/initOtel.js +7 -18
- package/build/esm/sdk/initOtel.js.map +1 -1
- package/build/esm/transports/http.js +9 -12
- package/build/esm/transports/http.js.map +1 -1
- package/build/esm/utils/ensureIsWrapped.js +1 -2
- package/build/esm/utils/ensureIsWrapped.js.map +1 -1
- package/build/esm/utils/envToBool.js +1 -1
- package/build/esm/utils/envToBool.js.map +1 -1
- package/build/esm/utils/errorhandling.js +1 -2
- package/build/esm/utils/errorhandling.js.map +1 -1
- package/build/esm/utils/module.js.map +1 -1
- package/build/esm/utils/redisCache.js +0 -3
- package/build/esm/utils/redisCache.js.map +1 -1
- package/build/types/cron/node-cron.d.ts +1 -1
- package/build/types/cron/node-cron.d.ts.map +1 -1
- package/build/types/index.d.ts +4 -6
- package/build/types/index.d.ts.map +1 -1
- package/build/types/integrations/childProcess.d.ts +7 -7
- package/build/types/integrations/childProcess.d.ts.map +1 -1
- package/build/types/integrations/http/SentryHttpInstrumentation.d.ts +30 -0
- package/build/types/integrations/http/SentryHttpInstrumentation.d.ts.map +1 -1
- package/build/types/integrations/http/index.d.ts +11 -8
- package/build/types/integrations/http/index.d.ts.map +1 -1
- package/build/types/integrations/processSession.d.ts +5 -0
- package/build/types/integrations/processSession.d.ts.map +1 -0
- package/build/types/integrations/tracing/express.d.ts.map +1 -1
- package/build/types/integrations/tracing/hapi/types.d.ts +1 -0
- package/build/types/integrations/tracing/hapi/types.d.ts.map +1 -1
- package/build/types/integrations/tracing/index.d.ts.map +1 -1
- package/build/types/integrations/tracing/prisma.d.ts +11 -12
- package/build/types/integrations/tracing/prisma.d.ts.map +1 -1
- package/build/types/integrations/tracing/vercelai/index.d.ts.map +1 -1
- package/build/types/otel/contextManager.d.ts +1 -1
- package/build/types/proxy/helpers.d.ts +1 -0
- package/build/types/proxy/helpers.d.ts.map +1 -1
- package/build/types/proxy/parse-proxy-response.d.ts +1 -0
- package/build/types/proxy/parse-proxy-response.d.ts.map +1 -1
- package/build/types/sdk/index.d.ts.map +1 -1
- package/build/types/sdk/initOtel.d.ts +1 -3
- package/build/types/sdk/initOtel.d.ts.map +1 -1
- package/build/types/transports/http-module.d.ts +1 -0
- package/build/types/transports/http-module.d.ts.map +1 -1
- package/build/types/transports/http.d.ts +1 -0
- package/build/types/transports/http.d.ts.map +1 -1
- package/build/types/types.d.ts +2 -48
- package/build/types/types.d.ts.map +1 -1
- package/build/types/utils/errorhandling.d.ts.map +1 -1
- package/build/types-ts3.8/cron/node-cron.d.ts +1 -1
- package/build/types-ts3.8/index.d.ts +4 -6
- package/build/types-ts3.8/integrations/childProcess.d.ts +7 -7
- package/build/types-ts3.8/integrations/http/SentryHttpInstrumentation.d.ts +29 -0
- package/build/types-ts3.8/integrations/http/index.d.ts +11 -8
- package/build/types-ts3.8/integrations/processSession.d.ts +5 -0
- package/build/types-ts3.8/integrations/tracing/prisma.d.ts +11 -12
- package/build/types-ts3.8/otel/contextManager.d.ts +1 -1
- package/build/types-ts3.8/sdk/initOtel.d.ts +1 -3
- package/build/types-ts3.8/types.d.ts +2 -48
- package/package.json +36 -37
- package/build/cjs/integrations/tracing/nest/helpers.js +0 -100
- package/build/cjs/integrations/tracing/nest/helpers.js.map +0 -1
- package/build/cjs/integrations/tracing/nest/nest.js +0 -148
- package/build/cjs/integrations/tracing/nest/nest.js.map +0 -1
- package/build/cjs/integrations/tracing/nest/sentry-nest-event-instrumentation.js +0 -117
- package/build/cjs/integrations/tracing/nest/sentry-nest-event-instrumentation.js.map +0 -1
- package/build/cjs/integrations/tracing/nest/sentry-nest-instrumentation.js +0 -301
- package/build/cjs/integrations/tracing/nest/sentry-nest-instrumentation.js.map +0 -1
- package/build/esm/integrations/tracing/nest/helpers.js +0 -91
- package/build/esm/integrations/tracing/nest/helpers.js.map +0 -1
- package/build/esm/integrations/tracing/nest/nest.js +0 -141
- package/build/esm/integrations/tracing/nest/nest.js.map +0 -1
- package/build/esm/integrations/tracing/nest/sentry-nest-event-instrumentation.js +0 -115
- package/build/esm/integrations/tracing/nest/sentry-nest-event-instrumentation.js.map +0 -1
- package/build/esm/integrations/tracing/nest/sentry-nest-instrumentation.js +0 -295
- package/build/esm/integrations/tracing/nest/sentry-nest-instrumentation.js.map +0 -1
- package/build/types/integrations/tracing/nest/helpers.d.ts +0 -36
- package/build/types/integrations/tracing/nest/helpers.d.ts.map +0 -1
- package/build/types/integrations/tracing/nest/nest.d.ts +0 -19
- package/build/types/integrations/tracing/nest/nest.d.ts.map +0 -1
- package/build/types/integrations/tracing/nest/sentry-nest-event-instrumentation.d.ts +0 -27
- package/build/types/integrations/tracing/nest/sentry-nest-event-instrumentation.d.ts.map +0 -1
- package/build/types/integrations/tracing/nest/sentry-nest-instrumentation.d.ts +0 -37
- package/build/types/integrations/tracing/nest/sentry-nest-instrumentation.d.ts.map +0 -1
- package/build/types/integrations/tracing/nest/types.d.ts +0 -84
- package/build/types/integrations/tracing/nest/types.d.ts.map +0 -1
- package/build/types-ts3.8/integrations/tracing/nest/helpers.d.ts +0 -36
- package/build/types-ts3.8/integrations/tracing/nest/nest.d.ts +0 -19
- package/build/types-ts3.8/integrations/tracing/nest/sentry-nest-event-instrumentation.d.ts +0 -27
- package/build/types-ts3.8/integrations/tracing/nest/sentry-nest-instrumentation.d.ts +0 -37
- package/build/types-ts3.8/integrations/tracing/nest/types.d.ts +0 -84
package/build/cjs/cron/common.js
CHANGED
package/build/cjs/cron/cron.js
CHANGED
package/build/cjs/cron/index.js
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
_optionalChain
|
|
3
|
-
} = require('@sentry/core');
|
|
4
|
-
|
|
5
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
6
2
|
|
|
7
3
|
const core = require('@sentry/core');
|
|
8
4
|
const common = require('./common.js');
|
|
@@ -34,13 +30,16 @@ function instrumentNodeCron(lib) {
|
|
|
34
30
|
apply(target, thisArg, argArray) {
|
|
35
31
|
const [expression, callback, options] = argArray;
|
|
36
32
|
|
|
37
|
-
|
|
33
|
+
const name = options?.name;
|
|
34
|
+
const timezone = options?.timezone;
|
|
35
|
+
|
|
36
|
+
if (!name) {
|
|
38
37
|
throw new Error('Missing "name" for scheduled job. A name is required for Sentry check-in monitoring.');
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
async
|
|
40
|
+
const monitoredCallback = async () => {
|
|
42
41
|
return core.withMonitor(
|
|
43
|
-
|
|
42
|
+
name,
|
|
44
43
|
async () => {
|
|
45
44
|
// We have to manually catch here and capture the exception because node-cron swallows errors
|
|
46
45
|
// https://github.com/node-cron/node-cron/issues/399
|
|
@@ -53,16 +52,16 @@ function instrumentNodeCron(lib) {
|
|
|
53
52
|
},
|
|
54
53
|
{
|
|
55
54
|
schedule: { type: 'crontab', value: common.replaceCronNames(expression) },
|
|
56
|
-
timezone
|
|
55
|
+
timezone,
|
|
57
56
|
},
|
|
58
57
|
);
|
|
59
|
-
}
|
|
58
|
+
};
|
|
60
59
|
|
|
61
60
|
return target.apply(thisArg, [expression, monitoredCallback, options]);
|
|
62
61
|
},
|
|
63
62
|
});
|
|
64
63
|
} else {
|
|
65
|
-
return target[prop];
|
|
64
|
+
return target[prop ];
|
|
66
65
|
}
|
|
67
66
|
},
|
|
68
67
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-cron.js","sources":["../../../src/cron/node-cron.ts"],"sourcesContent":["import { captureException, withMonitor } from '@sentry/core';\nimport { replaceCronNames } from './common';\n\nexport interface NodeCronOptions {\n name: string;\n timezone?: string;\n}\n\nexport interface NodeCron {\n schedule: (cronExpression: string, callback: () => void, options: NodeCronOptions) => unknown;\n}\n\n/**\n * Wraps the `node-cron` library with check-in monitoring.\n *\n * ```ts\n * import * as Sentry from \"@sentry/node\";\n * import * as cron from \"node-cron\";\n *\n * const cronWithCheckIn = Sentry.cron.instrumentNodeCron(cron);\n *\n * cronWithCheckIn.schedule(\n * \"* * * * *\",\n * () => {\n * console.log(\"running a task every minute\");\n * },\n * { name: \"my-cron-job\" },\n * );\n * ```\n */\nexport function instrumentNodeCron<T>(lib: Partial<NodeCron> & T): T {\n return new Proxy(lib, {\n get(target, prop
|
|
1
|
+
{"version":3,"file":"node-cron.js","sources":["../../../src/cron/node-cron.ts"],"sourcesContent":["import { captureException, withMonitor } from '@sentry/core';\nimport { replaceCronNames } from './common';\n\nexport interface NodeCronOptions {\n name: string;\n timezone?: string;\n}\n\nexport interface NodeCron {\n schedule: (cronExpression: string, callback: () => void, options: NodeCronOptions | undefined) => unknown;\n}\n\n/**\n * Wraps the `node-cron` library with check-in monitoring.\n *\n * ```ts\n * import * as Sentry from \"@sentry/node\";\n * import * as cron from \"node-cron\";\n *\n * const cronWithCheckIn = Sentry.cron.instrumentNodeCron(cron);\n *\n * cronWithCheckIn.schedule(\n * \"* * * * *\",\n * () => {\n * console.log(\"running a task every minute\");\n * },\n * { name: \"my-cron-job\" },\n * );\n * ```\n */\nexport function instrumentNodeCron<T>(lib: Partial<NodeCron> & T): T {\n return new Proxy(lib, {\n get(target, prop) {\n if (prop === 'schedule' && target.schedule) {\n // When 'get' is called for schedule, return a proxied version of the schedule function\n return new Proxy(target.schedule, {\n apply(target, thisArg, argArray: Parameters<NodeCron['schedule']>) {\n const [expression, callback, options] = argArray;\n\n const name = options?.name;\n const timezone = options?.timezone;\n\n if (!name) {\n throw new Error('Missing \"name\" for scheduled job. A name is required for Sentry check-in monitoring.');\n }\n\n const monitoredCallback = async (): Promise<void> => {\n return withMonitor(\n name,\n async () => {\n // We have to manually catch here and capture the exception because node-cron swallows errors\n // https://github.com/node-cron/node-cron/issues/399\n try {\n return await callback();\n } catch (e) {\n captureException(e);\n throw e;\n }\n },\n {\n schedule: { type: 'crontab', value: replaceCronNames(expression) },\n timezone,\n },\n );\n };\n\n return target.apply(thisArg, [expression, monitoredCallback, options]);\n },\n });\n } else {\n return target[prop as keyof T];\n }\n },\n });\n}\n"],"names":["withMonitor","captureException","replaceCronNames"],"mappings":";;;;;AAYA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,kBAAkB,CAAI,GAAG,EAA4B;AACrE,EAAE,OAAO,IAAI,KAAK,CAAC,GAAG,EAAE;AACxB,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE;AACtB,MAAM,IAAI,IAAK,KAAI,cAAc,MAAM,CAAC,QAAQ,EAAE;AAClD;AACA,QAAQ,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE;AAC1C,UAAU,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAoC;AAC7E,YAAY,MAAM,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAE,GAAE,QAAQ;;AAE5D,YAAY,MAAM,IAAA,GAAO,OAAO,EAAE,IAAI;AACtC,YAAY,MAAM,QAAA,GAAW,OAAO,EAAE,QAAQ;;AAE9C,YAAY,IAAI,CAAC,IAAI,EAAE;AACvB,cAAc,MAAM,IAAI,KAAK,CAAC,sFAAsF,CAAC;AACrH;;AAEA,YAAY,MAAM,iBAAA,GAAoB,YAA2B;AACjE,cAAc,OAAOA,gBAAW;AAChC,gBAAgB,IAAI;AACpB,gBAAgB,YAAY;AAC5B;AACA;AACA,kBAAkB,IAAI;AACtB,oBAAoB,OAAO,MAAM,QAAQ,EAAE;AAC3C,mBAAoB,CAAA,OAAO,CAAC,EAAE;AAC9B,oBAAoBC,qBAAgB,CAAC,CAAC,CAAC;AACvC,oBAAoB,MAAM,CAAC;AAC3B;AACA,iBAAiB;AACjB,gBAAgB;AAChB,kBAAkB,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAEC,uBAAgB,CAAC,UAAU,GAAG;AACpF,kBAAkB,QAAQ;AAC1B,iBAAiB;AACjB,eAAe;AACf,aAAa;;AAEb,YAAY,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,iBAAiB,EAAE,OAAO,CAAC,CAAC;AAClF,WAAW;AACX,SAAS,CAAC;AACV,aAAa;AACb,QAAQ,OAAO,MAAM,CAAC,IAAA,EAAgB;AACtC;AACA,KAAK;AACL,GAAG,CAAC;AACJ;;;;"}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
_optionalChain
|
|
3
|
-
} = require('@sentry/core');
|
|
4
|
-
|
|
5
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
6
2
|
|
|
7
3
|
const core = require('@sentry/core');
|
|
8
4
|
const common = require('./common.js');
|
|
@@ -47,7 +43,7 @@ function instrumentNodeSchedule(lib) {
|
|
|
47
43
|
return core.withMonitor(
|
|
48
44
|
monitorSlug,
|
|
49
45
|
async () => {
|
|
50
|
-
await
|
|
46
|
+
await callback?.();
|
|
51
47
|
},
|
|
52
48
|
{
|
|
53
49
|
schedule: { type: 'crontab', value: common.replaceCronNames(expression) },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-schedule.js","sources":["../../../src/cron/node-schedule.ts"],"sourcesContent":["import { withMonitor } from '@sentry/core';\nimport { replaceCronNames } from './common';\n\nexport interface NodeSchedule {\n scheduleJob(\n nameOrExpression: string | Date | object,\n expressionOrCallback: string | Date | object | (() => void),\n callback?: () => void,\n ): unknown;\n}\n\n/**\n * Instruments the `node-schedule` library to send a check-in event to Sentry for each job execution.\n *\n * ```ts\n * import * as Sentry from '@sentry/node';\n * import * as schedule from 'node-schedule';\n *\n * const scheduleWithCheckIn = Sentry.cron.instrumentNodeSchedule(schedule);\n *\n * const job = scheduleWithCheckIn.scheduleJob('my-cron-job', '* * * * *', () => {\n * console.log('You will see this message every minute');\n * });\n * ```\n */\nexport function instrumentNodeSchedule<T>(lib: T & NodeSchedule): T {\n return new Proxy(lib, {\n get(target, prop: keyof NodeSchedule) {\n if (prop === 'scheduleJob') {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n return new Proxy(target.scheduleJob, {\n apply(target, thisArg, argArray: Parameters<NodeSchedule['scheduleJob']>) {\n const [nameOrExpression, expressionOrCallback, callback] = argArray;\n\n if (\n typeof nameOrExpression !== 'string' ||\n typeof expressionOrCallback !== 'string' ||\n typeof callback !== 'function'\n ) {\n throw new Error(\n \"Automatic instrumentation of 'node-schedule' requires the first parameter of 'scheduleJob' to be a job name string and the second parameter to be a crontab string\",\n );\n }\n\n const monitorSlug = nameOrExpression;\n const expression = expressionOrCallback;\n\n async function monitoredCallback(): Promise<void> {\n return withMonitor(\n monitorSlug,\n async () => {\n await callback?.();\n },\n {\n schedule: { type: 'crontab', value: replaceCronNames(expression) },\n },\n );\n }\n\n return target.apply(thisArg, [monitorSlug, expression, monitoredCallback]);\n },\n });\n }\n\n return target[prop];\n },\n });\n}\n"],"names":["withMonitor","replaceCronNames"],"mappings":"
|
|
1
|
+
{"version":3,"file":"node-schedule.js","sources":["../../../src/cron/node-schedule.ts"],"sourcesContent":["import { withMonitor } from '@sentry/core';\nimport { replaceCronNames } from './common';\n\nexport interface NodeSchedule {\n scheduleJob(\n nameOrExpression: string | Date | object,\n expressionOrCallback: string | Date | object | (() => void),\n callback?: () => void,\n ): unknown;\n}\n\n/**\n * Instruments the `node-schedule` library to send a check-in event to Sentry for each job execution.\n *\n * ```ts\n * import * as Sentry from '@sentry/node';\n * import * as schedule from 'node-schedule';\n *\n * const scheduleWithCheckIn = Sentry.cron.instrumentNodeSchedule(schedule);\n *\n * const job = scheduleWithCheckIn.scheduleJob('my-cron-job', '* * * * *', () => {\n * console.log('You will see this message every minute');\n * });\n * ```\n */\nexport function instrumentNodeSchedule<T>(lib: T & NodeSchedule): T {\n return new Proxy(lib, {\n get(target, prop: keyof NodeSchedule) {\n if (prop === 'scheduleJob') {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n return new Proxy(target.scheduleJob, {\n apply(target, thisArg, argArray: Parameters<NodeSchedule['scheduleJob']>) {\n const [nameOrExpression, expressionOrCallback, callback] = argArray;\n\n if (\n typeof nameOrExpression !== 'string' ||\n typeof expressionOrCallback !== 'string' ||\n typeof callback !== 'function'\n ) {\n throw new Error(\n \"Automatic instrumentation of 'node-schedule' requires the first parameter of 'scheduleJob' to be a job name string and the second parameter to be a crontab string\",\n );\n }\n\n const monitorSlug = nameOrExpression;\n const expression = expressionOrCallback;\n\n async function monitoredCallback(): Promise<void> {\n return withMonitor(\n monitorSlug,\n async () => {\n await callback?.();\n },\n {\n schedule: { type: 'crontab', value: replaceCronNames(expression) },\n },\n );\n }\n\n return target.apply(thisArg, [monitorSlug, expression, monitoredCallback]);\n },\n });\n }\n\n return target[prop];\n },\n });\n}\n"],"names":["withMonitor","replaceCronNames"],"mappings":";;;;;AAWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,sBAAsB,CAAI,GAAG,EAAuB;AACpE,EAAE,OAAO,IAAI,KAAK,CAAC,GAAG,EAAE;AACxB,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,EAAsB;AAC1C,MAAM,IAAI,IAAK,KAAI,aAAa,EAAE;AAClC;AACA,QAAQ,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE;AAC7C,UAAU,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAA2C;AACpF,YAAY,MAAM,CAAC,gBAAgB,EAAE,oBAAoB,EAAE,QAAQ,CAAE,GAAE,QAAQ;;AAE/E,YAAY;AACZ,cAAc,OAAO,gBAAiB,KAAI,QAAS;AACnD,cAAc,OAAO,oBAAqB,KAAI,QAAS;AACvD,cAAc,OAAO,aAAa;AAClC,cAAc;AACd,cAAc,MAAM,IAAI,KAAK;AAC7B,gBAAgB,oKAAoK;AACpL,eAAe;AACf;;AAEA,YAAY,MAAM,WAAY,GAAE,gBAAgB;AAChD,YAAY,MAAM,UAAW,GAAE,oBAAoB;;AAEnD,YAAY,eAAe,iBAAiB,GAAkB;AAC9D,cAAc,OAAOA,gBAAW;AAChC,gBAAgB,WAAW;AAC3B,gBAAgB,YAAY;AAC5B,kBAAkB,MAAM,QAAQ,IAAI;AACpC,iBAAiB;AACjB,gBAAgB;AAChB,kBAAkB,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAEC,uBAAgB,CAAC,UAAU,GAAG;AACpF,iBAAiB;AACjB,eAAe;AACf;;AAEA,YAAY,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,iBAAiB,CAAC,CAAC;AACtF,WAAW;AACX,SAAS,CAAC;AACV;;AAEA,MAAM,OAAO,MAAM,CAAC,IAAI,CAAC;AACzB,KAAK;AACL,GAAG,CAAC;AACJ;;;;"}
|
package/build/cjs/debug-build.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Object.defineProperty(exports,
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code.
|
package/build/cjs/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Object.defineProperty(exports,
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
const index = require('./integrations/http/index.js');
|
|
4
4
|
const nodeFetch = require('./integrations/node-fetch.js');
|
|
@@ -21,7 +21,6 @@ const mongoose = require('./integrations/tracing/mongoose.js');
|
|
|
21
21
|
const mysql = require('./integrations/tracing/mysql.js');
|
|
22
22
|
const mysql2 = require('./integrations/tracing/mysql2.js');
|
|
23
23
|
const redis = require('./integrations/tracing/redis.js');
|
|
24
|
-
const nest = require('./integrations/tracing/nest/nest.js');
|
|
25
24
|
const postgres = require('./integrations/tracing/postgres.js');
|
|
26
25
|
const prisma = require('./integrations/tracing/prisma.js');
|
|
27
26
|
const index$3 = require('./integrations/tracing/hapi/index.js');
|
|
@@ -44,8 +43,8 @@ const module$1 = require('./utils/module.js');
|
|
|
44
43
|
const http = require('./transports/http.js');
|
|
45
44
|
const client = require('./sdk/client.js');
|
|
46
45
|
const index$6 = require('./cron/index.js');
|
|
47
|
-
const core = require('@sentry/core');
|
|
48
46
|
const opentelemetry = require('@sentry/opentelemetry');
|
|
47
|
+
const core = require('@sentry/core');
|
|
49
48
|
|
|
50
49
|
|
|
51
50
|
|
|
@@ -74,8 +73,6 @@ exports.mongooseIntegration = mongoose.mongooseIntegration;
|
|
|
74
73
|
exports.mysqlIntegration = mysql.mysqlIntegration;
|
|
75
74
|
exports.mysql2Integration = mysql2.mysql2Integration;
|
|
76
75
|
exports.redisIntegration = redis.redisIntegration;
|
|
77
|
-
exports.nestIntegration = nest.nestIntegration;
|
|
78
|
-
exports.setupNestErrorHandler = nest.setupNestErrorHandler;
|
|
79
76
|
exports.postgresIntegration = postgres.postgresIntegration;
|
|
80
77
|
exports.prismaIntegration = prisma.prismaIntegration;
|
|
81
78
|
exports.hapiIntegration = index$3.hapiIntegration;
|
|
@@ -91,7 +88,6 @@ exports.genericPoolIntegration = genericPool.genericPoolIntegration;
|
|
|
91
88
|
exports.dataloaderIntegration = dataloader.dataloaderIntegration;
|
|
92
89
|
exports.amqplibIntegration = amqplib.amqplibIntegration;
|
|
93
90
|
exports.childProcessIntegration = childProcess.childProcessIntegration;
|
|
94
|
-
exports.processThreadBreadcrumbIntegration = childProcess.processThreadBreadcrumbIntegration;
|
|
95
91
|
exports.SentryContextManager = contextManager.SentryContextManager;
|
|
96
92
|
exports.generateInstrumentOnce = instrument.generateInstrumentOnce;
|
|
97
93
|
exports.getDefaultIntegrations = index$4.getDefaultIntegrations;
|
|
@@ -108,7 +104,7 @@ exports.createGetModuleFromFilename = module$1.createGetModuleFromFilename;
|
|
|
108
104
|
exports.makeNodeTransport = http.makeNodeTransport;
|
|
109
105
|
exports.NodeClient = client.NodeClient;
|
|
110
106
|
exports.cron = index$6.cron;
|
|
111
|
-
exports.
|
|
107
|
+
exports.setNodeAsyncContextStrategy = opentelemetry.setOpenTelemetryContextAsyncContextStrategy;
|
|
112
108
|
exports.SDK_VERSION = core.SDK_VERSION;
|
|
113
109
|
exports.SEMANTIC_ATTRIBUTE_SENTRY_OP = core.SEMANTIC_ATTRIBUTE_SENTRY_OP;
|
|
114
110
|
exports.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN = core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN;
|
|
@@ -118,7 +114,6 @@ exports.Scope = core.Scope;
|
|
|
118
114
|
exports.addBreadcrumb = core.addBreadcrumb;
|
|
119
115
|
exports.addEventProcessor = core.addEventProcessor;
|
|
120
116
|
exports.addIntegration = core.addIntegration;
|
|
121
|
-
exports.addRequestDataToEvent = core.addRequestDataToEvent;
|
|
122
117
|
exports.captureCheckIn = core.captureCheckIn;
|
|
123
118
|
exports.captureConsoleIntegration = core.captureConsoleIntegration;
|
|
124
119
|
exports.captureEvent = core.captureEvent;
|
|
@@ -129,16 +124,13 @@ exports.captureSession = core.captureSession;
|
|
|
129
124
|
exports.close = core.close;
|
|
130
125
|
exports.continueTrace = core.continueTrace;
|
|
131
126
|
exports.createTransport = core.createTransport;
|
|
132
|
-
exports.debugIntegration = core.debugIntegration;
|
|
133
127
|
exports.dedupeIntegration = core.dedupeIntegration;
|
|
134
128
|
exports.endSession = core.endSession;
|
|
135
129
|
exports.extraErrorDataIntegration = core.extraErrorDataIntegration;
|
|
136
|
-
exports.extractRequestData = core.extractRequestData;
|
|
137
130
|
exports.flush = core.flush;
|
|
138
131
|
exports.functionToStringIntegration = core.functionToStringIntegration;
|
|
139
132
|
exports.getActiveSpan = core.getActiveSpan;
|
|
140
133
|
exports.getClient = core.getClient;
|
|
141
|
-
exports.getCurrentHub = core.getCurrentHub;
|
|
142
134
|
exports.getCurrentScope = core.getCurrentScope;
|
|
143
135
|
exports.getGlobalScope = core.getGlobalScope;
|
|
144
136
|
exports.getIsolationScope = core.getIsolationScope;
|
|
@@ -151,12 +143,10 @@ exports.inboundFiltersIntegration = core.inboundFiltersIntegration;
|
|
|
151
143
|
exports.isInitialized = core.isInitialized;
|
|
152
144
|
exports.lastEventId = core.lastEventId;
|
|
153
145
|
exports.linkedErrorsIntegration = core.linkedErrorsIntegration;
|
|
154
|
-
exports.metrics = core.metricsDefault;
|
|
155
146
|
exports.parameterize = core.parameterize;
|
|
156
147
|
exports.profiler = core.profiler;
|
|
157
148
|
exports.requestDataIntegration = core.requestDataIntegration;
|
|
158
149
|
exports.rewriteFramesIntegration = core.rewriteFramesIntegration;
|
|
159
|
-
exports.sessionTimingIntegration = core.sessionTimingIntegration;
|
|
160
150
|
exports.setContext = core.setContext;
|
|
161
151
|
exports.setCurrentClient = core.setCurrentClient;
|
|
162
152
|
exports.setExtra = core.setExtra;
|
|
@@ -182,6 +172,4 @@ exports.withIsolationScope = core.withIsolationScope;
|
|
|
182
172
|
exports.withMonitor = core.withMonitor;
|
|
183
173
|
exports.withScope = core.withScope;
|
|
184
174
|
exports.zodErrorsIntegration = core.zodErrorsIntegration;
|
|
185
|
-
exports.addOpenTelemetryInstrumentation = opentelemetry.addOpenTelemetryInstrumentation;
|
|
186
|
-
exports.setNodeAsyncContextStrategy = opentelemetry.setOpenTelemetryContextAsyncContextStrategy;
|
|
187
175
|
//# sourceMappingURL=index.js.map
|
package/build/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
_optionalChain,
|
|
3
|
-
_optionalChainDelete
|
|
4
|
-
} = require('@sentry/core');
|
|
5
|
-
|
|
6
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
7
2
|
|
|
8
3
|
const util = require('node:util');
|
|
9
4
|
const node_worker_threads = require('node:worker_threads');
|
|
@@ -14,7 +9,7 @@ const debug = require('../../utils/debug.js');
|
|
|
14
9
|
const { isPromise } = util.types;
|
|
15
10
|
|
|
16
11
|
// This string is a placeholder that gets overwritten with the worker code.
|
|
17
|
-
const base64WorkerScript = 'LyohIEBzZW50cnkvbm9kZSA4LjUzLjAgKDNkOGIxMzIpIHwgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdCAqLwppbXBvcnR7U2Vzc2lvbiBhcyB0fWZyb20ibm9kZTppbnNwZWN0b3IiO2ltcG9ydHtwYXJlbnRQb3J0IGFzIG4sd29ya2VyRGF0YSBhcyBlfWZyb20ibm9kZTp3b3JrZXJfdGhyZWFkcyI7aW1wb3J0e3Bvc2l4IGFzIHIsc2VwIGFzIG99ZnJvbSJub2RlOnBhdGgiO2ltcG9ydCphcyBzIGZyb20ibm9kZTpodHRwIjtpbXBvcnQqYXMgaSBmcm9tIm5vZGU6aHR0cHMiO2ltcG9ydHtSZWFkYWJsZSBhcyBjfWZyb20ibm9kZTpzdHJlYW0iO2ltcG9ydHtjcmVhdGVHemlwIGFzIHV9ZnJvbSJub2RlOnpsaWIiO2ltcG9ydCphcyBhIGZyb20ibm9kZTpuZXQiO2ltcG9ydCphcyBmIGZyb20ibm9kZTp0bHMiO2NvbnN0IGg9InVuZGVmaW5lZCI9PXR5cGVvZiBfX1NFTlRSWV9ERUJVR19ffHxfX1NFTlRSWV9ERUJVR19fLHA9IjguNTMuMCIsbD1nbG9iYWxUaGlzO2Z1bmN0aW9uIGQodCxuLGUpe2NvbnN0IHI9bCxvPXIuX19TRU5UUllfXz1yLl9fU0VOVFJZX198fHt9LHM9b1twXT1vW3BdfHx7fTtyZXR1cm4gc1t0XXx8KHNbdF09bigpKX1jb25zdCBtPSJ1bmRlZmluZWQiPT10eXBlb2YgX19TRU5UUllfREVCVUdfX3x8X19TRU5UUllfREVCVUdfXyx5PVsiZGVidWciLCJpbmZvIiwid2FybiIsImVycm9yIiwibG9nIiwiYXNzZXJ0IiwidHJhY2UiXSxnPXt9O2Z1bmN0aW9uIGIodCl7aWYoISgiY29uc29sZSJpbiBsKSlyZXR1cm4gdCgpO2NvbnN0IG49bC5jb25zb2xlLGU9e30scj1PYmplY3Qua2V5cyhnKTtyLmZvckVhY2goKHQ9Pntjb25zdCByPWdbdF07ZVt0XT1uW3RdLG5bdF09cn0pKTt0cnl7cmV0dXJuIHQoKX1maW5hbGx5e3IuZm9yRWFjaCgodD0+e25bdF09ZVt0XX0pKX19Y29uc3QgXz1kKCJsb2dnZXIiLChmdW5jdGlvbigpe2xldCB0PSExO2NvbnN0IG49e2VuYWJsZTooKT0+e3Q9ITB9LGRpc2FibGU6KCk9Pnt0PSExfSxpc0VuYWJsZWQ6KCk9PnR9O3JldHVybiBtP3kuZm9yRWFjaCgoZT0+e25bZV09KC4uLm4pPT57dCYmYigoKCk9PntsLmNvbnNvbGVbZV0oYFNlbnRyeSBMb2dnZXIgWyR7ZX1dOmAsLi4ubil9KSl9fSkpOnkuZm9yRWFjaCgodD0+e25bdF09KCk9Pnt9fSkpLG59KSksdj01MCx3PSI/IixTPS9jYXB0dXJlTWVzc2FnZXxjYXB0dXJlRXhjZXB0aW9uLztmdW5jdGlvbiAkKHQpe3JldHVybiB0W3QubGVuZ3RoLTFdfHx7fX1jb25zdCBFPSI8YW5vbnltb3VzPiI7ZnVuY3Rpb24geCgpe3JldHVybiBOKGwpLGx9ZnVuY3Rpb24gTih0KXtjb25zdCBuPXQuX19TRU5UUllfXz10Ll9fU0VOVFJZX198fHt9O3JldHVybiBuLnZlcnNpb249bi52ZXJzaW9ufHxwLG5bcF09bltwXXx8e319Y29uc3QgVD1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO2Z1bmN0aW9uIEModCxuKXtyZXR1cm4gVC5jYWxsKHQpPT09YFtvYmplY3QgJHtufV1gfWZ1bmN0aW9uIGoodCl7cmV0dXJuIEModCwiU3RyaW5nIil9ZnVuY3Rpb24gayh0KXtyZXR1cm4gQyh0LCJPYmplY3QiKX1mdW5jdGlvbiBSKHQpe3JldHVybiBCb29sZWFuKHQmJnQudGhlbiYmImZ1bmN0aW9uIj09dHlwZW9mIHQudGhlbil9ZnVuY3Rpb24gTyh0LG4pe3RyeXtyZXR1cm4gdCBpbnN0YW5jZW9mIG59Y2F0Y2godCl7cmV0dXJuITF9fWNvbnN0IEQ9bCxBPTgwO2Z1bmN0aW9uIEkodCxuKXtjb25zdCBlPXQscj1bXTtpZighZXx8IWUudGFnTmFtZSlyZXR1cm4iIjtpZihELkhUTUxFbGVtZW50JiZlIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQmJmUuZGF0YXNldCl7aWYoZS5kYXRhc2V0LnNlbnRyeUNvbXBvbmVudClyZXR1cm4gZS5kYXRhc2V0LnNlbnRyeUNvbXBvbmVudDtpZihlLmRhdGFzZXQuc2VudHJ5RWxlbWVudClyZXR1cm4gZS5kYXRhc2V0LnNlbnRyeUVsZW1lbnR9ci5wdXNoKGUudGFnTmFtZS50b0xvd2VyQ2FzZSgpKTtjb25zdCBvPW4mJm4ubGVuZ3RoP24uZmlsdGVyKCh0PT5lLmdldEF0dHJpYnV0ZSh0KSkpLm1hcCgodD0+W3QsZS5nZXRBdHRyaWJ1dGUodCldKSk6bnVsbDtpZihvJiZvLmxlbmd0aClvLmZvckVhY2goKHQ9PntyLnB1c2goYFske3RbMF19PSIke3RbMV19Il1gKX0pKTtlbHNle2UuaWQmJnIucHVzaChgIyR7ZS5pZH1gKTtjb25zdCB0PWUuY2xhc3NOYW1lO2lmKHQmJmoodCkpe2NvbnN0IG49dC5zcGxpdCgvXHMrLyk7Zm9yKGNvbnN0IHQgb2YgbilyLnB1c2goYC4ke3R9YCl9fWNvbnN0IHM9WyJhcmlhLWxhYmVsIiwidHlwZSIsIm5hbWUiLCJ0aXRsZSIsImFsdCJdO2Zvcihjb25zdCB0IG9mIHMpe2NvbnN0IG49ZS5nZXRBdHRyaWJ1dGUodCk7biYmci5wdXNoKGBbJHt0fT0iJHtufSJdYCl9cmV0dXJuIHIuam9pbigiIil9ZnVuY3Rpb24gUCh0KXtpZihmdW5jdGlvbih0KXtzd2l0Y2goVC5jYWxsKHQpKXtjYXNlIltvYmplY3QgRXJyb3JdIjpjYXNlIltvYmplY3QgRXhjZXB0aW9uXSI6Y2FzZSJbb2JqZWN0IERPTUV4Y2VwdGlvbl0iOmNhc2UiW29iamVjdCBXZWJBc3NlbWJseS5FeGNlcHRpb25dIjpyZXR1cm4hMDtkZWZhdWx0OnJldHVybiBPKHQsRXJyb3IpfX0odCkpcmV0dXJue21lc3NhZ2U6dC5tZXNzYWdlLG5hbWU6dC5uYW1lLHN0YWNrOnQuc3RhY2ssLi4uTSh0KX07aWYobj10LCJ1bmRlZmluZWQiIT10eXBlb2YgRXZlbnQmJk8obixFdmVudCkpe2NvbnN0IG49e3R5cGU6dC50eXBlLHRhcmdldDpVKHQudGFyZ2V0KSxjdXJyZW50VGFyZ2V0OlUodC5jdXJyZW50VGFyZ2V0KSwuLi5NKHQpfTtyZXR1cm4idW5kZWZpbmVkIiE9dHlwZW9mIEN1c3RvbUV2ZW50JiZPKHQsQ3VzdG9tRXZlbnQpJiYobi5kZXRhaWw9dC5kZXRhaWwpLG59cmV0dXJuIHQ7dmFyIG59ZnVuY3Rpb24gVSh0KXt0cnl7cmV0dXJuIG49dCwidW5kZWZpbmVkIiE9dHlwZW9mIEVsZW1lbnQmJk8obixFbGVtZW50KT9mdW5jdGlvbih0LG49e30pe2lmKCF0KXJldHVybiI8dW5rbm93bj4iO3RyeXtsZXQgZT10O2NvbnN0IHI9NSxvPVtdO2xldCBzPTAsaT0wO2NvbnN0IGM9IiA+ICIsdT1jLmxlbmd0aDtsZXQgYTtjb25zdCBmPUFycmF5LmlzQXJyYXkobik/bjpuLmtleUF0dHJzLGg9IUFycmF5LmlzQXJyYXkobikmJm4ubWF4U3RyaW5nTGVuZ3RofHxBO2Zvcig7ZSYmcysrPHImJihhPUkoZSxmKSwhKCJodG1sIj09PWF8fHM+MSYmaStvLmxlbmd0aCp1K2EubGVuZ3RoPj1oKSk7KW8ucHVzaChhKSxpKz1hLmxlbmd0aCxlPWUucGFyZW50Tm9kZTtyZXR1cm4gby5yZXZlcnNlKCkuam9pbihjKX1jYXRjaCh0KXtyZXR1cm4iPHVua25vd24+In19KHQpOk9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh0KX1jYXRjaCh0KXtyZXR1cm4iPHVua25vd24+In12YXIgbn1mdW5jdGlvbiBNKHQpe2lmKCJvYmplY3QiPT10eXBlb2YgdCYmbnVsbCE9PXQpe2NvbnN0IG49e307Zm9yKGNvbnN0IGUgaW4gdClPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodCxlKSYmKG5bZV09dFtlXSk7cmV0dXJuIG59cmV0dXJue319ZnVuY3Rpb24gTCh0KXtyZXR1cm4gQih0LG5ldyBNYXApfWZ1bmN0aW9uIEIodCxuKXtpZihmdW5jdGlvbih0KXtpZighayh0KSlyZXR1cm4hMTt0cnl7Y29uc3Qgbj1PYmplY3QuZ2V0UHJvdG90eXBlT2YodCkuY29uc3RydWN0b3IubmFtZTtyZXR1cm4hbnx8Ik9iamVjdCI9PT1ufWNhdGNoKHQpe3JldHVybiEwfX0odCkpe2NvbnN0IGU9bi5nZXQodCk7aWYodm9pZCAwIT09ZSlyZXR1cm4gZTtjb25zdCByPXt9O24uc2V0KHQscik7Zm9yKGNvbnN0IGUgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModCkpdm9pZCAwIT09dFtlXSYmKHJbZV09Qih0W2VdLG4pKTtyZXR1cm4gcn1pZihBcnJheS5pc0FycmF5KHQpKXtjb25zdCBlPW4uZ2V0KHQpO2lmKHZvaWQgMCE9PWUpcmV0dXJuIGU7Y29uc3Qgcj1bXTtyZXR1cm4gbi5zZXQodCxyKSx0LmZvckVhY2goKHQ9PntyLnB1c2goQih0LG4pKX0pKSxyfXJldHVybiB0fWNvbnN0IEc9MWUzO2Z1bmN0aW9uIEooKXtyZXR1cm4gRGF0ZS5ub3coKS9HfWNvbnN0IFk9ZnVuY3Rpb24oKXtjb25zdHtwZXJmb3JtYW5jZTp0fT1sO2lmKCF0fHwhdC5ub3cpcmV0dXJuIEo7Y29uc3Qgbj1EYXRlLm5vdygpLXQubm93KCksZT1udWxsPT10LnRpbWVPcmlnaW4/bjp0LnRpbWVPcmlnaW47cmV0dXJuKCk9PihlK3Qubm93KCkpL0d9KCk7ZnVuY3Rpb24geigpe2NvbnN0IHQ9bCxuPXQuY3J5cHRvfHx0Lm1zQ3J5cHRvO2xldCBlPSgpPT4xNipNYXRoLnJhbmRvbSgpO3RyeXtpZihuJiZuLnJhbmRvbVVVSUQpcmV0dXJuIG4ucmFuZG9tVVVJRCgpLnJlcGxhY2UoLy0vZywiIik7biYmbi5nZXRSYW5kb21WYWx1ZXMmJihlPSgpPT57Y29uc3QgdD1uZXcgVWludDhBcnJheSgxKTtyZXR1cm4gbi5nZXRSYW5kb21WYWx1ZXModCksdFswXX0pfWNhdGNoKHQpe31yZXR1cm4oWzFlN10rMWUzKzRlMys4ZTMrMWUxMSkucmVwbGFjZSgvWzAxOF0vZywodD0+KHReKDE1JmUoKSk+PnQvNCkudG9TdHJpbmcoMTYpKSl9dmFyIEg7ZnVuY3Rpb24gVyh0KXtyZXR1cm4gbmV3IEYoKG49PntuKHQpfSkpfSgoKT0+e2NvbnN0e3BlcmZvcm1hbmNlOnR9PWw7aWYoIXR8fCF0Lm5vdylyZXR1cm47Y29uc3Qgbj0zNmU1LGU9dC5ub3coKSxyPURhdGUubm93KCksbz10LnRpbWVPcmlnaW4/TWF0aC5hYnModC50aW1lT3JpZ2luK2Utcik6bixzPW88bixpPXQudGltaW5nJiZ0LnRpbWluZy5uYXZpZ2F0aW9uU3RhcnQsYz0ibnVtYmVyIj09dHlwZW9mIGk/TWF0aC5hYnMoaStlLXIpOm47KHN8fGM8bikmJihvPD1jJiZ0LnRpbWVPcmlnaW4pfSkoKSxmdW5jdGlvbih0KXt0W3QuUEVORElORz0wXT0iUEVORElORyI7dFt0LlJFU09MVkVEPTFdPSJSRVNPTFZFRCI7dFt0LlJFSkVDVEVEPTJdPSJSRUpFQ1RFRCJ9KEh8fChIPXt9KSk7Y2xhc3MgRntjb25zdHJ1Y3Rvcih0KXtGLnByb3RvdHlwZS5fX2luaXQuY2FsbCh0aGlzKSxGLnByb3RvdHlwZS5fX2luaXQyLmNhbGwodGhpcyksRi5wcm90b3R5cGUuX19pbml0My5jYWxsKHRoaXMpLEYucHJvdG90eXBlLl9faW5pdDQuY2FsbCh0aGlzKSx0aGlzLnQ9SC5QRU5ESU5HLHRoaXMubz1bXTt0cnl7dCh0aGlzLmksdGhpcy51KX1jYXRjaCh0KXt0aGlzLnUodCl9fXRoZW4odCxuKXtyZXR1cm4gbmV3IEYoKChlLHIpPT57dGhpcy5vLnB1c2goWyExLG49PntpZih0KXRyeXtlKHQobikpfWNhdGNoKHQpe3IodCl9ZWxzZSBlKG4pfSx0PT57aWYobil0cnl7ZShuKHQpKX1jYXRjaCh0KXtyKHQpfWVsc2Ugcih0KX1dKSx0aGlzLmgoKX0pKX1jYXRjaCh0KXtyZXR1cm4gdGhpcy50aGVuKCh0PT50KSx0KX1maW5hbGx5KHQpe3JldHVybiBuZXcgRigoKG4sZSk9PntsZXQgcixvO3JldHVybiB0aGlzLnRoZW4oKG49PntvPSExLHI9bix0JiZ0KCl9KSwobj0+e289ITAscj1uLHQmJnQoKX0pKS50aGVuKCgoKT0+e28/ZShyKTpuKHIpfSkpfSkpfV9faW5pdCgpe3RoaXMuaT10PT57dGhpcy5wKEguUkVTT0xWRUQsdCl9fV9faW5pdDIoKXt0aGlzLnU9dD0+e3RoaXMucChILlJFSkVDVEVELHQpfX1fX2luaXQzKCl7dGhpcy5wPSh0LG4pPT57dGhpcy50PT09SC5QRU5ESU5HJiYoUihuKT9uLnRoZW4odGhpcy5pLHRoaXMudSk6KHRoaXMudD10LHRoaXMubD1uLHRoaXMuaCgpKSl9fV9faW5pdDQoKXt0aGlzLmg9KCk9PntpZih0aGlzLnQ9PT1ILlBFTkRJTkcpcmV0dXJuO2NvbnN0IHQ9dGhpcy5vLnNsaWNlKCk7dGhpcy5vPVtdLHQuZm9yRWFjaCgodD0+e3RbMF18fCh0aGlzLnQ9PT1ILlJFU09MVkVEJiZ0WzFdKHRoaXMubCksdGhpcy50PT09SC5SRUpFQ1RFRCYmdFsyXSh0aGlzLmwpLHRbMF09ITApfSkpfX19ZnVuY3Rpb24gSyh0KXtjb25zdCBuPVkoKSxlPXtzaWQ6eigpLGluaXQ6ITAsdGltZXN0YW1wOm4sc3RhcnRlZDpuLGR1cmF0aW9uOjAsc3RhdHVzOiJvayIsZXJyb3JzOjAsaWdub3JlRHVyYXRpb246ITEsdG9KU09OOigpPT5mdW5jdGlvbih0KXtyZXR1cm4gTCh7c2lkOmAke3Quc2lkfWAsaW5pdDp0LmluaXQsc3RhcnRlZDpuZXcgRGF0ZSgxZTMqdC5zdGFydGVkKS50b0lTT1N0cmluZygpLHRpbWVzdGFtcDpuZXcgRGF0ZSgxZTMqdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksc3RhdHVzOnQuc3RhdHVzLGVycm9yczp0LmVycm9ycyxkaWQ6Im51bWJlciI9PXR5cGVvZiB0LmRpZHx8InN0cmluZyI9PXR5cGVvZiB0LmRpZD9gJHt0LmRpZH1gOnZvaWQgMCxkdXJhdGlvbjp0LmR1cmF0aW9uLGFibm9ybWFsX21lY2hhbmlzbTp0LmFibm9ybWFsX21lY2hhbmlzbSxhdHRyczp7cmVsZWFzZTp0LnJlbGVhc2UsZW52aXJvbm1lbnQ6dC5lbnZpcm9ubWVudCxpcF9hZGRyZXNzOnQuaXBBZGRyZXNzLHVzZXJfYWdlbnQ6dC51c2VyQWdlbnR9fSl9KGUpfTtyZXR1cm4gdCYmVihlLHQpLGV9ZnVuY3Rpb24gVih0LG49e30pe2lmKG4udXNlciYmKCF0LmlwQWRkcmVzcyYmbi51c2VyLmlwX2FkZHJlc3MmJih0LmlwQWRkcmVzcz1uLnVzZXIuaXBfYWRkcmVzcyksdC5kaWR8fG4uZGlkfHwodC5kaWQ9bi51c2VyLmlkfHxuLnVzZXIuZW1haWx8fG4udXNlci51c2VybmFtZSkpLHQudGltZXN0YW1wPW4udGltZXN0YW1wfHxZKCksbi5hYm5vcm1hbF9tZWNoYW5pc20mJih0LmFibm9ybWFsX21lY2hhbmlzbT1uLmFibm9ybWFsX21lY2hhbmlzbSksbi5pZ25vcmVEdXJhdGlvbiYmKHQuaWdub3JlRHVyYXRpb249bi5pZ25vcmVEdXJhdGlvbiksbi5zaWQmJih0LnNpZD0zMj09PW4uc2lkLmxlbmd0aD9uLnNpZDp6KCkpLHZvaWQgMCE9PW4uaW5pdCYmKHQuaW5pdD1uLmluaXQpLCF0LmRpZCYmbi5kaWQmJih0LmRpZD1gJHtuLmRpZH1gKSwibnVtYmVyIj09dHlwZW9mIG4uc3RhcnRlZCYmKHQuc3RhcnRlZD1uLnN0YXJ0ZWQpLHQuaWdub3JlRHVyYXRpb24pdC5kdXJhdGlvbj12b2lkIDA7ZWxzZSBpZigibnVtYmVyIj09dHlwZW9mIG4uZHVyYXRpb24pdC5kdXJhdGlvbj1uLmR1cmF0aW9uO2Vsc2V7Y29uc3Qgbj10LnRpbWVzdGFtcC10LnN0YXJ0ZWQ7dC5kdXJhdGlvbj1uPj0wP246MH1uLnJlbGVhc2UmJih0LnJlbGVhc2U9bi5yZWxlYXNlKSxuLmVudmlyb25tZW50JiYodC5lbnZpcm9ubWVudD1uLmVudmlyb25tZW50KSwhdC5pcEFkZHJlc3MmJm4uaXBBZGRyZXNzJiYodC5pcEFkZHJlc3M9bi5pcEFkZHJlc3MpLCF0LnVzZXJBZ2VudCYmbi51c2VyQWdlbnQmJih0LnVzZXJBZ2VudD1uLnVzZXJBZ2VudCksIm51bWJlciI9PXR5cGVvZiBuLmVycm9ycyYmKHQuZXJyb3JzPW4uZXJyb3JzKSxuLnN0YXR1cyYmKHQuc3RhdHVzPW4uc3RhdHVzKX1mdW5jdGlvbiBaKCl7cmV0dXJuIHooKX1mdW5jdGlvbiBxKCl7cmV0dXJuIHooKS5zdWJzdHJpbmcoMTYpfWZ1bmN0aW9uIFEodCxuLGU9Mil7aWYoIW58fCJvYmplY3QiIT10eXBlb2Ygbnx8ZTw9MClyZXR1cm4gbjtpZih0JiZuJiYwPT09T2JqZWN0LmtleXMobikubGVuZ3RoKXJldHVybiB0O2NvbnN0IHI9ey4uLnR9O2Zvcihjb25zdCB0IGluIG4pT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG4sdCkmJihyW3RdPVEoclt0XSxuW3RdLGUtMSkpO3JldHVybiByfWNvbnN0IFg9Il9zZW50cnlTcGFuIjtmdW5jdGlvbiB0dCh0LG4pe24/ZnVuY3Rpb24odCxuLGUpe3RyeXtPYmplY3QuZGVmaW5lUHJvcGVydHkodCxuLHt2YWx1ZTplLHdyaXRhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMH0pfWNhdGNoKGUpe20mJl8ubG9nKGBGYWlsZWQgdG8gYWRkIG5vbi1lbnVtZXJhYmxlIHByb3BlcnR5ICIke259IiB0byBvYmplY3RgLHQpfX0odCxYLG4pOmRlbGV0ZSB0W1hdfWZ1bmN0aW9uIG50KHQpe3JldHVybiB0W1hdfWNsYXNzIGV0e2NvbnN0cnVjdG9yKCl7dGhpcy5tPSExLHRoaXMuXz1bXSx0aGlzLnY9W10sdGhpcy5TPVtdLHRoaXMuTj1bXSx0aGlzLlQ9e30sdGhpcy5DPXt9LHRoaXMuaj17fSx0aGlzLms9e30sdGhpcy5SPXt9LHRoaXMuTz17dHJhY2VJZDpaKCksc3BhbklkOnEoKX19Y2xvbmUoKXtjb25zdCB0PW5ldyBldDtyZXR1cm4gdC5TPVsuLi50aGlzLlNdLHQuQz17Li4udGhpcy5DfSx0Lmo9ey4uLnRoaXMuan0sdC5rPXsuLi50aGlzLmt9LHRoaXMuay5mbGFncyYmKHQuay5mbGFncz17dmFsdWVzOlsuLi50aGlzLmsuZmxhZ3MudmFsdWVzXX0pLHQuVD10aGlzLlQsdC5EPXRoaXMuRCx0LkE9dGhpcy5BLHQuST10aGlzLkksdC5QPXRoaXMuUCx0LnY9Wy4uLnRoaXMudl0sdC5VPXRoaXMuVSx0Lk49Wy4uLnRoaXMuTl0sdC5SPXsuLi50aGlzLlJ9LHQuTz17Li4udGhpcy5PfSx0Lk09dGhpcy5NLHQuTD10aGlzLkwsdHQodCxudCh0aGlzKSksdH1zZXRDbGllbnQodCl7dGhpcy5NPXR9c2V0TGFzdEV2ZW50SWQodCl7dGhpcy5MPXR9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuTX1sYXN0RXZlbnRJZCgpe3JldHVybiB0aGlzLkx9YWRkU2NvcGVMaXN0ZW5lcih0KXt0aGlzLl8ucHVzaCh0KX1hZGRFdmVudFByb2Nlc3Nvcih0KXtyZXR1cm4gdGhpcy52LnB1c2godCksdGhpc31zZXRVc2VyKHQpe3JldHVybiB0aGlzLlQ9dHx8e2VtYWlsOnZvaWQgMCxpZDp2b2lkIDAsaXBfYWRkcmVzczp2b2lkIDAsdXNlcm5hbWU6dm9pZCAwfSx0aGlzLkEmJlYodGhpcy5BLHt1c2VyOnR9KSx0aGlzLkIoKSx0aGlzfWdldFVzZXIoKXtyZXR1cm4gdGhpcy5UfWdldFJlcXVlc3RTZXNzaW9uKCl7cmV0dXJuIHRoaXMuVX1zZXRSZXF1ZXN0U2Vzc2lvbih0KXtyZXR1cm4gdGhpcy5VPXQsdGhpc31zZXRUYWdzKHQpe3JldHVybiB0aGlzLkM9ey4uLnRoaXMuQywuLi50fSx0aGlzLkIoKSx0aGlzfXNldFRhZyh0LG4pe3JldHVybiB0aGlzLkM9ey4uLnRoaXMuQyxbdF06bn0sdGhpcy5CKCksdGhpc31zZXRFeHRyYXModCl7cmV0dXJuIHRoaXMuaj17Li4udGhpcy5qLC4uLnR9LHRoaXMuQigpLHRoaXN9c2V0RXh0cmEodCxuKXtyZXR1cm4gdGhpcy5qPXsuLi50aGlzLmosW3RdOm59LHRoaXMuQigpLHRoaXN9c2V0RmluZ2VycHJpbnQodCl7cmV0dXJuIHRoaXMuUD10LHRoaXMuQigpLHRoaXN9c2V0TGV2ZWwodCl7cmV0dXJuIHRoaXMuRD10LHRoaXMuQigpLHRoaXN9c2V0VHJhbnNhY3Rpb25OYW1lKHQpe3JldHVybiB0aGlzLkk9dCx0aGlzLkIoKSx0aGlzfXNldENvbnRleHQodCxuKXtyZXR1cm4gbnVsbD09PW4/ZGVsZXRlIHRoaXMua1t0XTp0aGlzLmtbdF09bix0aGlzLkIoKSx0aGlzfXNldFNlc3Npb24odCl7cmV0dXJuIHQ/dGhpcy5BPXQ6ZGVsZXRlIHRoaXMuQSx0aGlzLkIoKSx0aGlzfWdldFNlc3Npb24oKXtyZXR1cm4gdGhpcy5BfXVwZGF0ZSh0KXtpZighdClyZXR1cm4gdGhpcztjb25zdCBuPSJmdW5jdGlvbiI9PXR5cGVvZiB0P3QodGhpcyk6dCxbZSxyXT1uIGluc3RhbmNlb2YgcnQ/W24uZ2V0U2NvcGVEYXRhKCksbi5nZXRSZXF1ZXN0U2Vzc2lvbigpXTprKG4pP1t0LHQucmVxdWVzdFNlc3Npb25dOltdLHt0YWdzOm8sZXh0cmE6cyx1c2VyOmksY29udGV4dHM6YyxsZXZlbDp1LGZpbmdlcnByaW50OmE9W10scHJvcGFnYXRpb25Db250ZXh0OmZ9PWV8fHt9O3JldHVybiB0aGlzLkM9ey4uLnRoaXMuQywuLi5vfSx0aGlzLmo9ey4uLnRoaXMuaiwuLi5zfSx0aGlzLms9ey4uLnRoaXMuaywuLi5jfSxpJiZPYmplY3Qua2V5cyhpKS5sZW5ndGgmJih0aGlzLlQ9aSksdSYmKHRoaXMuRD11KSxhLmxlbmd0aCYmKHRoaXMuUD1hKSxmJiYodGhpcy5PPWYpLHImJih0aGlzLlU9ciksdGhpc31jbGVhcigpe3JldHVybiB0aGlzLlM9W10sdGhpcy5DPXt9LHRoaXMuaj17fSx0aGlzLlQ9e30sdGhpcy5rPXt9LHRoaXMuRD12b2lkIDAsdGhpcy5JPXZvaWQgMCx0aGlzLlA9dm9pZCAwLHRoaXMuVT12b2lkIDAsdGhpcy5BPXZvaWQgMCx0dCh0aGlzLHZvaWQgMCksdGhpcy5OPVtdLHRoaXMuc2V0UHJvcGFnYXRpb25Db250ZXh0KHt0cmFjZUlkOlooKX0pLHRoaXMuQigpLHRoaXN9YWRkQnJlYWRjcnVtYih0LG4pe2NvbnN0IGU9Im51bWJlciI9PXR5cGVvZiBuP246MTAwO2lmKGU8PTApcmV0dXJuIHRoaXM7Y29uc3Qgcj17dGltZXN0YW1wOkooKSwuLi50fTtyZXR1cm4gdGhpcy5TLnB1c2gociksdGhpcy5TLmxlbmd0aD5lJiYodGhpcy5TPXRoaXMuUy5zbGljZSgtZSksdGhpcy5NJiZ0aGlzLk0ucmVjb3JkRHJvcHBlZEV2ZW50KCJidWZmZXJfb3ZlcmZsb3ciLCJsb2dfaXRlbSIpKSx0aGlzLkIoKSx0aGlzfWdldExhc3RCcmVhZGNydW1iKCl7cmV0dXJuIHRoaXMuU1t0aGlzLlMubGVuZ3RoLTFdfWNsZWFyQnJlYWRjcnVtYnMoKXtyZXR1cm4gdGhpcy5TPVtdLHRoaXMuQigpLHRoaXN9YWRkQXR0YWNobWVudCh0KXtyZXR1cm4gdGhpcy5OLnB1c2godCksdGhpc31jbGVhckF0dGFjaG1lbnRzKCl7cmV0dXJuIHRoaXMuTj1bXSx0aGlzfWdldFNjb3BlRGF0YSgpe3JldHVybnticmVhZGNydW1iczp0aGlzLlMsYXR0YWNobWVudHM6dGhpcy5OLGNvbnRleHRzOnRoaXMuayx0YWdzOnRoaXMuQyxleHRyYTp0aGlzLmosdXNlcjp0aGlzLlQsbGV2ZWw6dGhpcy5ELGZpbmdlcnByaW50OnRoaXMuUHx8W10sZXZlbnRQcm9jZXNzb3JzOnRoaXMudixwcm9wYWdhdGlvbkNvbnRleHQ6dGhpcy5PLHNka1Byb2Nlc3NpbmdNZXRhZGF0YTp0aGlzLlIsdHJhbnNhY3Rpb25OYW1lOnRoaXMuSSxzcGFuOm50KHRoaXMpfX1zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEodCl7cmV0dXJuIHRoaXMuUj1RKHRoaXMuUix0LDIpLHRoaXN9c2V0UHJvcGFnYXRpb25Db250ZXh0KHQpe3JldHVybiB0aGlzLk89e3NwYW5JZDpxKCksLi4udH0sdGhpc31nZXRQcm9wYWdhdGlvbkNvbnRleHQoKXtyZXR1cm4gdGhpcy5PfWNhcHR1cmVFeGNlcHRpb24odCxuKXtjb25zdCBlPW4mJm4uZXZlbnRfaWQ/bi5ldmVudF9pZDp6KCk7aWYoIXRoaXMuTSlyZXR1cm4gXy53YXJuKCJObyBjbGllbnQgY29uZmlndXJlZCBvbiBzY29wZSAtIHdpbGwgbm90IGNhcHR1cmUgZXhjZXB0aW9uISIpLGU7Y29uc3Qgcj1uZXcgRXJyb3IoIlNlbnRyeSBzeW50aGV0aWNFeGNlcHRpb24iKTtyZXR1cm4gdGhpcy5NLmNhcHR1cmVFeGNlcHRpb24odCx7b3JpZ2luYWxFeGNlcHRpb246dCxzeW50aGV0aWNFeGNlcHRpb246ciwuLi5uLGV2ZW50X2lkOmV9LHRoaXMpLGV9Y2FwdHVyZU1lc3NhZ2UodCxuLGUpe2NvbnN0IHI9ZSYmZS5ldmVudF9pZD9lLmV2ZW50X2lkOnooKTtpZighdGhpcy5NKXJldHVybiBfLndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBtZXNzYWdlISIpLHI7Y29uc3Qgbz1uZXcgRXJyb3IodCk7cmV0dXJuIHRoaXMuTS5jYXB0dXJlTWVzc2FnZSh0LG4se29yaWdpbmFsRXhjZXB0aW9uOnQsc3ludGhldGljRXhjZXB0aW9uOm8sLi4uZSxldmVudF9pZDpyfSx0aGlzKSxyfWNhcHR1cmVFdmVudCh0LG4pe2NvbnN0IGU9biYmbi5ldmVudF9pZD9uLmV2ZW50X2lkOnooKTtyZXR1cm4gdGhpcy5NPyh0aGlzLk0uY2FwdHVyZUV2ZW50KHQsey4uLm4sZXZlbnRfaWQ6ZX0sdGhpcyksZSk6KF8ud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIGV2ZW50ISIpLGUpfUIoKXt0aGlzLm18fCh0aGlzLm09ITAsdGhpcy5fLmZvckVhY2goKHQ9Pnt0KHRoaXMpfSkpLHRoaXMubT0hMSl9fWNvbnN0IHJ0PWV0O2NsYXNzIG90e2NvbnN0cnVjdG9yKHQsbil7bGV0IGUscjtlPXR8fG5ldyBydCxyPW58fG5ldyBydCx0aGlzLkc9W3tzY29wZTplfV0sdGhpcy5KPXJ9d2l0aFNjb3BlKHQpe2NvbnN0IG49dGhpcy5ZKCk7bGV0IGU7dHJ5e2U9dChuKX1jYXRjaCh0KXt0aHJvdyB0aGlzLkgoKSx0fXJldHVybiBSKGUpP2UudGhlbigodD0+KHRoaXMuSCgpLHQpKSwodD0+e3Rocm93IHRoaXMuSCgpLHR9KSk6KHRoaXMuSCgpLGUpfWdldENsaWVudCgpe3JldHVybiB0aGlzLmdldFN0YWNrVG9wKCkuY2xpZW50fWdldFNjb3BlKCl7cmV0dXJuIHRoaXMuZ2V0U3RhY2tUb3AoKS5zY29wZX1nZXRJc29sYXRpb25TY29wZSgpe3JldHVybiB0aGlzLkp9Z2V0U3RhY2tUb3AoKXtyZXR1cm4gdGhpcy5HW3RoaXMuRy5sZW5ndGgtMV19WSgpe2NvbnN0IHQ9dGhpcy5nZXRTY29wZSgpLmNsb25lKCk7cmV0dXJuIHRoaXMuRy5wdXNoKHtjbGllbnQ6dGhpcy5nZXRDbGllbnQoKSxzY29wZTp0fSksdH1IKCl7cmV0dXJuISh0aGlzLkcubGVuZ3RoPD0xKSYmISF0aGlzLkcucG9wKCl9fWZ1bmN0aW9uIHN0KCl7Y29uc3QgdD1OKHgoKSk7cmV0dXJuIHQuc3RhY2s9dC5zdGFja3x8bmV3IG90KGQoImRlZmF1bHRDdXJyZW50U2NvcGUiLCgoKT0+bmV3IHJ0KSksZCgiZGVmYXVsdElzb2xhdGlvblNjb3BlIiwoKCk9Pm5ldyBydCkpKX1mdW5jdGlvbiBpdCh0KXtyZXR1cm4gc3QoKS53aXRoU2NvcGUodCl9ZnVuY3Rpb24gY3QodCxuKXtjb25zdCBlPXN0KCk7cmV0dXJuIGUud2l0aFNjb3BlKCgoKT0+KGUuZ2V0U3RhY2tUb3AoKS5zY29wZT10LG4odCkpKSl9ZnVuY3Rpb24gdXQodCl7cmV0dXJuIHN0KCkud2l0aFNjb3BlKCgoKT0+dChzdCgpLmdldElzb2xhdGlvblNjb3BlKCkpKSl9ZnVuY3Rpb24gYXQodCl7Y29uc3Qgbj1OKHQpO3JldHVybiBuLmFjcz9uLmFjczp7d2l0aElzb2xhdGlvblNjb3BlOnV0LHdpdGhTY29wZTppdCx3aXRoU2V0U2NvcGU6Y3Qsd2l0aFNldElzb2xhdGlvblNjb3BlOih0LG4pPT51dChuKSxnZXRDdXJyZW50U2NvcGU6KCk9PnN0KCkuZ2V0U2NvcGUoKSxnZXRJc29sYXRpb25TY29wZTooKT0+c3QoKS5nZXRJc29sYXRpb25TY29wZSgpfX1mdW5jdGlvbiBmdCgpe3JldHVybiBhdCh4KCkpLmdldEN1cnJlbnRTY29wZSgpLmdldENsaWVudCgpfWNvbnN0IGh0PSJfc2VudHJ5TWV0cmljcyI7ZnVuY3Rpb24gcHQodCl7Y29uc3Qgbj10W2h0XTtpZighbilyZXR1cm47Y29uc3QgZT17fTtmb3IoY29uc3RbLFt0LHJdXW9mIG4peyhlW3RdfHwoZVt0XT1bXSkpLnB1c2goTChyKSl9cmV0dXJuIGV9Y29uc3QgbHQ9InNlbnRyeS5zb3VyY2UiLGR0PSJzZW50cnkuc2FtcGxlX3JhdGUiLG10PSJzZW50cnkub3AiLHl0PSJzZW50cnkub3JpZ2luIixndD0wLGJ0PTEsX3Q9InNlbnRyeS0iLHZ0PS9ec2VudHJ5LS87ZnVuY3Rpb24gd3QodCl7Y29uc3Qgbj1mdW5jdGlvbih0KXtpZighdHx8IWoodCkmJiFBcnJheS5pc0FycmF5KHQpKXJldHVybjtpZihBcnJheS5pc0FycmF5KHQpKXJldHVybiB0LnJlZHVjZSgoKHQsbik9Pntjb25zdCBlPVN0KG4pO3JldHVybiBPYmplY3QuZW50cmllcyhlKS5mb3JFYWNoKCgoW24sZV0pPT57dFtuXT1lfSkpLHR9KSx7fSk7cmV0dXJuIFN0KHQpfSh0KTtpZighbilyZXR1cm47Y29uc3QgZT1PYmplY3QuZW50cmllcyhuKS5yZWR1Y2UoKCh0LFtuLGVdKT0+e2lmKG4ubWF0Y2godnQpKXt0W24uc2xpY2UoX3QubGVuZ3RoKV09ZX1yZXR1cm4gdH0pLHt9KTtyZXR1cm4gT2JqZWN0LmtleXMoZSkubGVuZ3RoPjA/ZTp2b2lkIDB9ZnVuY3Rpb24gU3QodCl7cmV0dXJuIHQuc3BsaXQoIiwiKS5tYXAoKHQ9PnQuc3BsaXQoIj0iKS5tYXAoKHQ9PmRlY29kZVVSSUNvbXBvbmVudCh0LnRyaW0oKSkpKSkpLnJlZHVjZSgoKHQsW24sZV0pPT4obiYmZSYmKHRbbl09ZSksdCkpLHt9KX1jb25zdCAkdD0xO2Z1bmN0aW9uIEV0KHQpe2NvbnN0e3NwYW5JZDpuLHRyYWNlSWQ6ZSxpc1JlbW90ZTpyfT10LnNwYW5Db250ZXh0KCk7cmV0dXJuIEwoe3BhcmVudF9zcGFuX2lkOnI/bjpUdCh0KS5wYXJlbnRfc3Bhbl9pZCxzcGFuX2lkOnI/cSgpOm4sdHJhY2VfaWQ6ZX0pfWZ1bmN0aW9uIHh0KHQpe3JldHVybiJudW1iZXIiPT10eXBlb2YgdD9OdCh0KTpBcnJheS5pc0FycmF5KHQpP3RbMF0rdFsxXS8xZTk6dCBpbnN0YW5jZW9mIERhdGU/TnQodC5nZXRUaW1lKCkpOlkoKX1mdW5jdGlvbiBOdCh0KXtyZXR1cm4gdD45OTk5OTk5OTk5P3QvMWUzOnR9ZnVuY3Rpb24gVHQodCl7aWYoZnVuY3Rpb24odCl7cmV0dXJuImZ1bmN0aW9uIj09dHlwZW9mIHQuZ2V0U3BhbkpTT059KHQpKXJldHVybiB0LmdldFNwYW5KU09OKCk7dHJ5e2NvbnN0e3NwYW5JZDpuLHRyYWNlSWQ6ZX09dC5zcGFuQ29udGV4dCgpO2lmKGZ1bmN0aW9uKHQpe2NvbnN0IG49dDtyZXR1cm4hIShuLmF0dHJpYnV0ZXMmJm4uc3RhcnRUaW1lJiZuLm5hbWUmJm4uZW5kVGltZSYmbi5zdGF0dXMpfSh0KSl7Y29uc3R7YXR0cmlidXRlczpyLHN0YXJ0VGltZTpvLG5hbWU6cyxlbmRUaW1lOmkscGFyZW50U3BhbklkOmMsc3RhdHVzOnV9PXQ7cmV0dXJuIEwoe3NwYW5faWQ6bix0cmFjZV9pZDplLGRhdGE6cixkZXNjcmlwdGlvbjpzLHBhcmVudF9zcGFuX2lkOmMsc3RhcnRfdGltZXN0YW1wOnh0KG8pLHRpbWVzdGFtcDp4dChpKXx8dm9pZCAwLHN0YXR1czpDdCh1KSxvcDpyW210XSxvcmlnaW46clt5dF0sX21ldHJpY3Nfc3VtbWFyeTpwdCh0KX0pfXJldHVybntzcGFuX2lkOm4sdHJhY2VfaWQ6ZX19Y2F0Y2godCl7cmV0dXJue319fWZ1bmN0aW9uIEN0KHQpe2lmKHQmJnQuY29kZSE9PWd0KXJldHVybiB0LmNvZGU9PT1idD8ib2siOnQubWVzc2FnZXx8InVua25vd25fZXJyb3IifWNvbnN0IGp0PSJfc2VudHJ5Um9vdFNwYW4iO2Z1bmN0aW9uIGt0KHQpe3JldHVybiB0W2p0XXx8dH1jb25zdCBSdD0icHJvZHVjdGlvbiIsT3Q9Il9mcm96ZW5Ec2MiO2Z1bmN0aW9uIER0KHQpe2NvbnN0IG49ZnQoKTtpZighbilyZXR1cm57fTtjb25zdCBlPWt0KHQpLHI9ZVtPdF07aWYocilyZXR1cm4gcjtjb25zdCBvPWUuc3BhbkNvbnRleHQoKS50cmFjZVN0YXRlLHM9byYmby5nZXQoInNlbnRyeS5kc2MiKSxpPXMmJnd0KHMpO2lmKGkpcmV0dXJuIGk7Y29uc3QgYz1mdW5jdGlvbih0LG4pe2NvbnN0IGU9bi5nZXRPcHRpb25zKCkse3B1YmxpY0tleTpyfT1uLmdldERzbigpfHx7fSxvPUwoe2Vudmlyb25tZW50OmUuZW52aXJvbm1lbnR8fFJ0LHJlbGVhc2U6ZS5yZWxlYXNlLHB1YmxpY19rZXk6cix0cmFjZV9pZDp0fSk7cmV0dXJuIG4uZW1pdCgiY3JlYXRlRHNjIixvKSxvfSh0LnNwYW5Db250ZXh0KCkudHJhY2VJZCxuKSx1PVR0KGUpLGE9dS5kYXRhfHx7fSxmPWFbZHRdO251bGwhPWYmJihjLnNhbXBsZV9yYXRlPWAke2Z9YCk7Y29uc3QgaD1hW2x0XSxwPXUuZGVzY3JpcHRpb247cmV0dXJuInVybCIhPT1oJiZwJiYoYy50cmFuc2FjdGlvbj1wKSxmdW5jdGlvbih0KXtpZigiYm9vbGVhbiI9PXR5cGVvZiBfX1NFTlRSWV9UUkFDSU5HX18mJiFfX1NFTlRSWV9UUkFDSU5HX18pcmV0dXJuITE7Y29uc3Qgbj1mdCgpLGU9biYmbi5nZXRPcHRpb25zKCk7cmV0dXJuISFlJiYoZS5lbmFibGVUcmFjaW5nfHwidHJhY2VzU2FtcGxlUmF0ZSJpbiBlfHwidHJhY2VzU2FtcGxlciJpbiBlKX0oKSYmKGMuc2FtcGxlZD1TdHJpbmcoZnVuY3Rpb24odCl7Y29uc3R7dHJhY2VGbGFnczpufT10LnNwYW5Db250ZXh0KCk7cmV0dXJuIG49PT0kdH0oZSkpKSxuLmVtaXQoImNyZWF0ZURzYyIsYyxlKSxjfWZ1bmN0aW9uIEF0KHQsbj0hMSl7Y29uc3R7aG9zdDplLHBhdGg6cixwYXNzOm8scG9ydDpzLHByb2plY3RJZDppLHByb3RvY29sOmMscHVibGljS2V5OnV9PXQ7cmV0dXJuYCR7Y306Ly8ke3V9JHtuJiZvP2A6JHtvfWA6IiJ9QCR7ZX0ke3M/YDoke3N9YDoiIn0vJHtyP2Ake3J9L2A6cn0ke2l9YH1mdW5jdGlvbiBJdCh0LG49MTAwLGU9MS8wKXt0cnl7cmV0dXJuIFB0KCIiLHQsbixlKX1jYXRjaCh0KXtyZXR1cm57RVJST1I6YCoqbm9uLXNlcmlhbGl6YWJsZSoqICgke3R9KWB9fX1mdW5jdGlvbiBQdCh0LG4sZT0xLzAscj0xLzAsbz1mdW5jdGlvbigpe2NvbnN0IHQ9ImZ1bmN0aW9uIj09dHlwZW9mIFdlYWtTZXQsbj10P25ldyBXZWFrU2V0OltdO3JldHVybltmdW5jdGlvbihlKXtpZih0KXJldHVybiEhbi5oYXMoZSl8fChuLmFkZChlKSwhMSk7Zm9yKGxldCB0PTA7dDxuLmxlbmd0aDt0KyspaWYoblt0XT09PWUpcmV0dXJuITA7cmV0dXJuIG4ucHVzaChlKSwhMX0sZnVuY3Rpb24oZSl7aWYodCluLmRlbGV0ZShlKTtlbHNlIGZvcihsZXQgdD0wO3Q8bi5sZW5ndGg7dCsrKWlmKG5bdF09PT1lKXtuLnNwbGljZSh0LDEpO2JyZWFrfX1dfSgpKXtjb25zdFtzLGldPW87aWYobnVsbD09bnx8WyJib29sZWFuIiwic3RyaW5nIl0uaW5jbHVkZXModHlwZW9mIG4pfHwibnVtYmVyIj09dHlwZW9mIG4mJk51bWJlci5pc0Zpbml0ZShuKSlyZXR1cm4gbjtjb25zdCBjPWZ1bmN0aW9uKHQsbil7dHJ5e2lmKCJkb21haW4iPT09dCYmbiYmIm9iamVjdCI9PXR5cGVvZiBuJiZuLlcpcmV0dXJuIltEb21haW5dIjtpZigiZG9tYWluRW1pdHRlciI9PT10KXJldHVybiJbRG9tYWluRW1pdHRlcl0iO2lmKCJ1bmRlZmluZWQiIT10eXBlb2YgZ2xvYmFsJiZuPT09Z2xvYmFsKXJldHVybiJbR2xvYmFsXSI7aWYoInVuZGVmaW5lZCIhPXR5cGVvZiB3aW5kb3cmJm49PT13aW5kb3cpcmV0dXJuIltXaW5kb3ddIjtpZigidW5kZWZpbmVkIiE9dHlwZW9mIGRvY3VtZW50JiZuPT09ZG9jdW1lbnQpcmV0dXJuIltEb2N1bWVudF0iO2lmKCJvYmplY3QiPT10eXBlb2YoZT1uKSYmbnVsbCE9PWUmJihlLl9faXNWdWV8fGUuRikpcmV0dXJuIltWdWVWaWV3TW9kZWxdIjtpZihmdW5jdGlvbih0KXtyZXR1cm4gayh0KSYmIm5hdGl2ZUV2ZW50ImluIHQmJiJwcmV2ZW50RGVmYXVsdCJpbiB0JiYic3RvcFByb3BhZ2F0aW9uImluIHR9KG4pKXJldHVybiJbU3ludGhldGljRXZlbnRdIjtpZigibnVtYmVyIj09dHlwZW9mIG4mJiFOdW1iZXIuaXNGaW5pdGUobikpcmV0dXJuYFske259XWA7aWYoImZ1bmN0aW9uIj09dHlwZW9mIG4pcmV0dXJuYFtGdW5jdGlvbjogJHtmdW5jdGlvbih0KXt0cnl7cmV0dXJuIHQmJiJmdW5jdGlvbiI9PXR5cGVvZiB0JiZ0Lm5hbWV8fEV9Y2F0Y2godCl7cmV0dXJuIEV9fShuKX1dYDtpZigic3ltYm9sIj09dHlwZW9mIG4pcmV0dXJuYFske1N0cmluZyhuKX1dYDtpZigiYmlnaW50Ij09dHlwZW9mIG4pcmV0dXJuYFtCaWdJbnQ6ICR7U3RyaW5nKG4pfV1gO2NvbnN0IHI9ZnVuY3Rpb24odCl7Y29uc3Qgbj1PYmplY3QuZ2V0UHJvdG90eXBlT2YodCk7cmV0dXJuIG4/bi5jb25zdHJ1Y3Rvci5uYW1lOiJudWxsIHByb3RvdHlwZSJ9KG4pO3JldHVybi9eSFRNTChcdyopRWxlbWVudCQvLnRlc3Qocik/YFtIVE1MRWxlbWVudDogJHtyfV1gOmBbb2JqZWN0ICR7cn1dYH1jYXRjaCh0KXtyZXR1cm5gKipub24tc2VyaWFsaXphYmxlKiogKCR7dH0pYH12YXIgZX0odCxuKTtpZighYy5zdGFydHNXaXRoKCJbb2JqZWN0ICIpKXJldHVybiBjO2lmKG4uX19zZW50cnlfc2tpcF9ub3JtYWxpemF0aW9uX18pcmV0dXJuIG47Y29uc3QgdT0ibnVtYmVyIj09dHlwZW9mIG4uX19zZW50cnlfb3ZlcnJpZGVfbm9ybWFsaXphdGlvbl9kZXB0aF9fP24uX19zZW50cnlfb3ZlcnJpZGVfbm9ybWFsaXphdGlvbl9kZXB0aF9fOmU7aWYoMD09PXUpcmV0dXJuIGMucmVwbGFjZSgib2JqZWN0ICIsIiIpO2lmKHMobikpcmV0dXJuIltDaXJjdWxhciB+XSI7Y29uc3QgYT1uO2lmKGEmJiJmdW5jdGlvbiI9PXR5cGVvZiBhLnRvSlNPTil0cnl7cmV0dXJuIFB0KCIiLGEudG9KU09OKCksdS0xLHIsbyl9Y2F0Y2godCl7fWNvbnN0IGY9QXJyYXkuaXNBcnJheShuKT9bXTp7fTtsZXQgaD0wO2NvbnN0IHA9UChuKTtmb3IoY29uc3QgdCBpbiBwKXtpZighT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHAsdCkpY29udGludWU7aWYoaD49cil7Zlt0XT0iW01heFByb3BlcnRpZXMgfl0iO2JyZWFrfWNvbnN0IG49cFt0XTtmW3RdPVB0KHQsbix1LTEscixvKSxoKyt9cmV0dXJuIGkobiksZn1mdW5jdGlvbiBVdCh0LG4pe2NvbnN0IGU9bi5yZXBsYWNlKC9cXC9nLCIvIikucmVwbGFjZSgvW3xcXHt9KClbXF1eJCsqPy5dL2csIlxcJCYiKTtsZXQgcj10O3RyeXtyPWRlY29kZVVSSSh0KX1jYXRjaCh0KXt9cmV0dXJuIHIucmVwbGFjZSgvXFwvZywiLyIpLnJlcGxhY2UoL3dlYnBhY2s6XC8/L2csIiIpLnJlcGxhY2UobmV3IFJlZ0V4cChgKGZpbGU6Ly8pPy8qJHtlfS8qYCwiaWciKSwiYXBwOi8vLyIpfWZ1bmN0aW9uIE10KHQsbj1bXSl7cmV0dXJuW3Qsbl19ZnVuY3Rpb24gTHQodCxuKXtjb25zdCBlPXRbMV07Zm9yKGNvbnN0IHQgb2YgZSl7aWYobih0LHRbMF0udHlwZSkpcmV0dXJuITB9cmV0dXJuITF9ZnVuY3Rpb24gQnQodCl7cmV0dXJuIGwuX19TRU5UUllfXyYmbC5fX1NFTlRSWV9fLmVuY29kZVBvbHlmaWxsP2wuX19TRU5UUllfXy5lbmNvZGVQb2x5ZmlsbCh0KToobmV3IFRleHRFbmNvZGVyKS5lbmNvZGUodCl9ZnVuY3Rpb24gR3QodCl7Y29uc3RbbixlXT10O2xldCByPUpTT04uc3RyaW5naWZ5KG4pO2Z1bmN0aW9uIG8odCl7InN0cmluZyI9PXR5cGVvZiByP3I9InN0cmluZyI9PXR5cGVvZiB0P3IrdDpbQnQociksdF06ci5wdXNoKCJzdHJpbmciPT10eXBlb2YgdD9CdCh0KTp0KX1mb3IoY29uc3QgdCBvZiBlKXtjb25zdFtuLGVdPXQ7aWYobyhgXG4ke0pTT04uc3RyaW5naWZ5KG4pfVxuYCksInN0cmluZyI9PXR5cGVvZiBlfHxlIGluc3RhbmNlb2YgVWludDhBcnJheSlvKGUpO2Vsc2V7bGV0IHQ7dHJ5e3Q9SlNPTi5zdHJpbmdpZnkoZSl9Y2F0Y2gobil7dD1KU09OLnN0cmluZ2lmeShJdChlKSl9byh0KX19cmV0dXJuInN0cmluZyI9PXR5cGVvZiByP3I6ZnVuY3Rpb24odCl7Y29uc3Qgbj10LnJlZHVjZSgoKHQsbik9PnQrbi5sZW5ndGgpLDApLGU9bmV3IFVpbnQ4QXJyYXkobik7bGV0IHI9MDtmb3IoY29uc3QgbiBvZiB0KWUuc2V0KG4scikscis9bi5sZW5ndGg7cmV0dXJuIGV9KHIpfWNvbnN0IEp0PXtzZXNzaW9uOiJzZXNzaW9uIixzZXNzaW9uczoic2Vzc2lvbiIsYXR0YWNobWVudDoiYXR0YWNobWVudCIsdHJhbnNhY3Rpb246InRyYW5zYWN0aW9uIixldmVudDoiZXJyb3IiLGNsaWVudF9yZXBvcnQ6ImludGVybmFsIix1c2VyX3JlcG9ydDoiZGVmYXVsdCIscHJvZmlsZToicHJvZmlsZSIscHJvZmlsZV9jaHVuazoicHJvZmlsZSIscmVwbGF5X2V2ZW50OiJyZXBsYXkiLHJlcGxheV9yZWNvcmRpbmc6InJlcGxheSIsY2hlY2tfaW46Im1vbml0b3IiLGZlZWRiYWNrOiJmZWVkYmFjayIsc3Bhbjoic3BhbiIsc3RhdHNkOiJtZXRyaWNfYnVja2V0IixyYXdfc2VjdXJpdHk6InNlY3VyaXR5In07ZnVuY3Rpb24gWXQodCl7aWYoIXR8fCF0LnNkaylyZXR1cm47Y29uc3R7bmFtZTpuLHZlcnNpb246ZX09dC5zZGs7cmV0dXJue25hbWU6bix2ZXJzaW9uOmV9fWZ1bmN0aW9uIHp0KHQsbixlLHIpe2NvbnN0IG89WXQoZSkscz10LnR5cGUmJiJyZXBsYXlfZXZlbnQiIT09dC50eXBlP3QudHlwZToiZXZlbnQiOyFmdW5jdGlvbih0LG4pe24mJih0LnNkaz10LnNka3x8e30sdC5zZGsubmFtZT10LnNkay5uYW1lfHxuLm5hbWUsdC5zZGsudmVyc2lvbj10LnNkay52ZXJzaW9ufHxuLnZlcnNpb24sdC5zZGsuaW50ZWdyYXRpb25zPVsuLi50LnNkay5pbnRlZ3JhdGlvbnN8fFtdLC4uLm4uaW50ZWdyYXRpb25zfHxbXV0sdC5zZGsucGFja2FnZXM9Wy4uLnQuc2RrLnBhY2thZ2VzfHxbXSwuLi5uLnBhY2thZ2VzfHxbXV0pfSh0LGUmJmUuc2RrKTtjb25zdCBpPWZ1bmN0aW9uKHQsbixlLHIpe2NvbnN0IG89dC5zZGtQcm9jZXNzaW5nTWV0YWRhdGEmJnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhLmR5bmFtaWNTYW1wbGluZ0NvbnRleHQ7cmV0dXJue2V2ZW50X2lkOnQuZXZlbnRfaWQsc2VudF9hdDoobmV3IERhdGUpLnRvSVNPU3RyaW5nKCksLi4ubiYme3NkazpufSwuLi4hIWUmJnImJntkc246QXQocil9LC4uLm8mJnt0cmFjZTpMKHsuLi5vfSl9fX0odCxvLHIsbik7ZGVsZXRlIHQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhO3JldHVybiBNdChpLFtbe3R5cGU6c30sdF1dKX1jb25zdCBIdD0iX19TRU5UUllfU1VQUFJFU1NfVFJBQ0lOR19fIjtmdW5jdGlvbiBXdCh0KXtjb25zdCBuPWF0KHgoKSk7cmV0dXJuIG4uc3VwcHJlc3NUcmFjaW5nP24uc3VwcHJlc3NUcmFjaW5nKHQpOmZ1bmN0aW9uKC4uLnQpe2NvbnN0IG49YXQoeCgpKTtpZigyPT09dC5sZW5ndGgpe2NvbnN0W2Uscl09dDtyZXR1cm4gZT9uLndpdGhTZXRTY29wZShlLHIpOm4ud2l0aFNjb3BlKHIpfXJldHVybiBuLndpdGhTY29wZSh0WzBdKX0oKG49PihuLnNldFNES1Byb2Nlc3NpbmdNZXRhZGF0YSh7W0h0XTohMH0pLHQoKSkpKX1mdW5jdGlvbiBGdCh0LG4pe2NvbnN0e2ZpbmdlcnByaW50OmUsc3BhbjpyLGJyZWFkY3J1bWJzOm8sc2RrUHJvY2Vzc2luZ01ldGFkYXRhOnN9PW47IWZ1bmN0aW9uKHQsbil7Y29uc3R7ZXh0cmE6ZSx0YWdzOnIsdXNlcjpvLGNvbnRleHRzOnMsbGV2ZWw6aSx0cmFuc2FjdGlvbk5hbWU6Y309bix1PUwoZSk7dSYmT2JqZWN0LmtleXModSkubGVuZ3RoJiYodC5leHRyYT17Li4udSwuLi50LmV4dHJhfSk7Y29uc3QgYT1MKHIpO2EmJk9iamVjdC5rZXlzKGEpLmxlbmd0aCYmKHQudGFncz17Li4uYSwuLi50LnRhZ3N9KTtjb25zdCBmPUwobyk7ZiYmT2JqZWN0LmtleXMoZikubGVuZ3RoJiYodC51c2VyPXsuLi5mLC4uLnQudXNlcn0pO2NvbnN0IGg9TChzKTtoJiZPYmplY3Qua2V5cyhoKS5sZW5ndGgmJih0LmNvbnRleHRzPXsuLi5oLC4uLnQuY29udGV4dHN9KTtpJiYodC5sZXZlbD1pKTtjJiYidHJhbnNhY3Rpb24iIT09dC50eXBlJiYodC50cmFuc2FjdGlvbj1jKX0odCxuKSxyJiZmdW5jdGlvbih0LG4pe3QuY29udGV4dHM9e3RyYWNlOkV0KG4pLC4uLnQuY29udGV4dHN9LHQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhPXtkeW5hbWljU2FtcGxpbmdDb250ZXh0OkR0KG4pLC4uLnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhfTtjb25zdCBlPWt0KG4pLHI9VHQoZSkuZGVzY3JpcHRpb247ciYmIXQudHJhbnNhY3Rpb24mJiJ0cmFuc2FjdGlvbiI9PT10LnR5cGUmJih0LnRyYW5zYWN0aW9uPXIpfSh0LHIpLGZ1bmN0aW9uKHQsbil7dC5maW5nZXJwcmludD10LmZpbmdlcnByaW50P0FycmF5LmlzQXJyYXkodC5maW5nZXJwcmludCk/dC5maW5nZXJwcmludDpbdC5maW5nZXJwcmludF06W10sbiYmKHQuZmluZ2VycHJpbnQ9dC5maW5nZXJwcmludC5jb25jYXQobikpO3QuZmluZ2VycHJpbnQmJiF0LmZpbmdlcnByaW50Lmxlbmd0aCYmZGVsZXRlIHQuZmluZ2VycHJpbnR9KHQsZSksZnVuY3Rpb24odCxuKXtjb25zdCBlPVsuLi50LmJyZWFkY3J1bWJzfHxbXSwuLi5uXTt0LmJyZWFkY3J1bWJzPWUubGVuZ3RoP2U6dm9pZCAwfSh0LG8pLGZ1bmN0aW9uKHQsbil7dC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE9ey4uLnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhLC4uLm59fSh0LHMpfWNvbnN0IEt0PSI3IjtjbGFzcyBWdCBleHRlbmRzIEVycm9ye2NvbnN0cnVjdG9yKHQsbj0id2FybiIpe3N1cGVyKHQpLHRoaXMubWVzc2FnZT10LHRoaXMubG9nTGV2ZWw9bn19ZnVuY3Rpb24gWnQodCl7Y29uc3Qgbj1bXTtmdW5jdGlvbiBlKHQpe3JldHVybiBuLnNwbGljZShuLmluZGV4T2YodCksMSlbMF18fFByb21pc2UucmVzb2x2ZSh2b2lkIDApfXJldHVybnskOm4sYWRkOmZ1bmN0aW9uKHIpe2lmKCEodm9pZCAwPT09dHx8bi5sZW5ndGg8dCkpcmV0dXJuIG89bmV3IFZ0KCJOb3QgYWRkaW5nIFByb21pc2UgYmVjYXVzZSBidWZmZXIgbGltaXQgd2FzIHJlYWNoZWQuIiksbmV3IEYoKCh0LG4pPT57bihvKX0pKTt2YXIgbztjb25zdCBzPXIoKTtyZXR1cm4tMT09PW4uaW5kZXhPZihzKSYmbi5wdXNoKHMpLHMudGhlbigoKCk9PmUocykpKS50aGVuKG51bGwsKCgpPT5lKHMpLnRoZW4obnVsbCwoKCk9Pnt9KSkpKSxzfSxkcmFpbjpmdW5jdGlvbih0KXtyZXR1cm4gbmV3IEYoKChlLHIpPT57bGV0IG89bi5sZW5ndGg7aWYoIW8pcmV0dXJuIGUoITApO2NvbnN0IHM9c2V0VGltZW91dCgoKCk9Pnt0JiZ0PjAmJmUoITEpfSksdCk7bi5mb3JFYWNoKCh0PT57Vyh0KS50aGVuKCgoKT0+ey0tb3x8KGNsZWFyVGltZW91dChzKSxlKCEwKSl9KSxyKX0pKX0pKX19fWNvbnN0IHF0PTZlNDtmdW5jdGlvbiBRdCh0LHtzdGF0dXNDb2RlOm4saGVhZGVyczplfSxyPURhdGUubm93KCkpe2NvbnN0IG89ey4uLnR9LHM9ZSYmZVsieC1zZW50cnktcmF0ZS1saW1pdHMiXSxpPWUmJmVbInJldHJ5LWFmdGVyIl07aWYocylmb3IoY29uc3QgdCBvZiBzLnRyaW0oKS5zcGxpdCgiLCIpKXtjb25zdFtuLGUsLCxzXT10LnNwbGl0KCI6Iiw1KSxpPXBhcnNlSW50KG4sMTApLGM9MWUzKihpc05hTihpKT82MDppKTtpZihlKWZvcihjb25zdCB0IG9mIGUuc3BsaXQoIjsiKSkibWV0cmljX2J1Y2tldCI9PT10JiZzJiYhcy5zcGxpdCgiOyIpLmluY2x1ZGVzKCJjdXN0b20iKXx8KG9bdF09citjKTtlbHNlIG8uYWxsPXIrY31lbHNlIGk/by5hbGw9citmdW5jdGlvbih0LG49RGF0ZS5ub3coKSl7Y29uc3QgZT1wYXJzZUludChgJHt0fWAsMTApO2lmKCFpc05hTihlKSlyZXR1cm4gMWUzKmU7Y29uc3Qgcj1EYXRlLnBhcnNlKGAke3R9YCk7cmV0dXJuIGlzTmFOKHIpP3F0OnItbn0oaSxyKTo0Mjk9PT1uJiYoby5hbGw9cis2ZTQpO3JldHVybiBvfWNvbnN0IFh0PTY0O2Z1bmN0aW9uIHRuKHQsbixlPVp0KHQuYnVmZmVyU2l6ZXx8WHQpKXtsZXQgcj17fTtyZXR1cm57c2VuZDpmdW5jdGlvbih0KXtjb25zdCBvPVtdO2lmKEx0KHQsKCh0LG4pPT57Y29uc3QgZT1mdW5jdGlvbih0KXtyZXR1cm4gSnRbdF19KG4pOyhmdW5jdGlvbih0LG4sZT1EYXRlLm5vdygpKXtyZXR1cm4gZnVuY3Rpb24odCxuKXtyZXR1cm4gdFtuXXx8dC5hbGx8fDB9KHQsbik+ZX0pKHIsZSl8fG8ucHVzaCh0KX0pKSwwPT09by5sZW5ndGgpcmV0dXJuIFcoe30pO2NvbnN0IHM9TXQodFswXSxvKSxpPXQ9PntMdChzLCgodCxuKT0+e30pKX07cmV0dXJuIGUuYWRkKCgoKT0+bih7Ym9keTpHdChzKX0pLnRoZW4oKHQ9Pih2b2lkIDAhPT10LnN0YXR1c0NvZGUmJih0LnN0YXR1c0NvZGU8MjAwfHx0LnN0YXR1c0NvZGU+PTMwMCkmJmgmJl8ud2FybihgU2VudHJ5IHJlc3BvbmRlZCB3aXRoIHN0YXR1cyBjb2RlICR7dC5zdGF0dXNDb2RlfSB0byBzZW50IGV2ZW50LmApLHI9UXQocix0KSx0KSksKHQ9Pnt0aHJvdyBpKCksdH0pKSkpLnRoZW4oKHQ9PnQpLCh0PT57aWYodCBpbnN0YW5jZW9mIFZ0KXJldHVybiBoJiZfLmVycm9yKCJTa2lwcGVkIHNlbmRpbmcgZXZlbnQgYmVjYXVzZSBidWZmZXIgaXMgZnVsbC4iKSxpKCksVyh7fSk7dGhyb3cgdH0pKX0sZmx1c2g6dD0+ZS5kcmFpbih0KX19Y29uc3Qgbm49L14oXFMrOlxcfFwvPykoW1xzXFNdKj8pKCg/OlwuezEsMn18W14vXFxdKz98KShcLlteLi9cXF0qfCkpKD86Wy9cXF0qKSQvO2Z1bmN0aW9uIGVuKHQpe2NvbnN0IG49ZnVuY3Rpb24odCl7Y29uc3Qgbj10Lmxlbmd0aD4xMDI0P2A8dHJ1bmNhdGVkPiR7dC5zbGljZSgtMTAyNCl9YDp0LGU9bm4uZXhlYyhuKTtyZXR1cm4gZT9lLnNsaWNlKDEpOltdfSh0KSxlPW5bMF18fCIiO2xldCByPW5bMV07cmV0dXJuIGV8fHI/KHImJihyPXIuc2xpY2UoMCxyLmxlbmd0aC0xKSksZStyKToiLiJ9ZnVuY3Rpb24gcm4odCxuPSExKXtyZXR1cm4hKG58fHQmJiF0LnN0YXJ0c1dpdGgoIi8iKSYmIXQubWF0Y2goL15bQS1aXTovKSYmIXQuc3RhcnRzV2l0aCgiLiIpJiYhdC5tYXRjaCgvXlthLXpBLVpdKFthLXpBLVowLTkuXC0rXSkqOlwvXC8vKSkmJnZvaWQgMCE9PXQmJiF0LmluY2x1ZGVzKCJub2RlX21vZHVsZXMvIil9Y29uc3Qgb249U3ltYm9sKCJBZ2VudEJhc2VJbnRlcm5hbFN0YXRlIik7Y2xhc3Mgc24gZXh0ZW5kcyBzLkFnZW50e1tvbl07b3B0aW9ucztrZWVwQWxpdmU7Y29uc3RydWN0b3IodCl7c3VwZXIodCksdGhpc1tvbl09e319aXNTZWN1cmVFbmRwb2ludCh0KXtpZih0KXtpZigiYm9vbGVhbiI9PXR5cGVvZiB0LnNlY3VyZUVuZHBvaW50KXJldHVybiB0LnNlY3VyZUVuZHBvaW50O2lmKCJzdHJpbmciPT10eXBlb2YgdC5wcm90b2NvbClyZXR1cm4iaHR0cHM6Ij09PXQucHJvdG9jb2x9Y29uc3R7c3RhY2s6bn09bmV3IEVycm9yO3JldHVybiJzdHJpbmciPT10eXBlb2YgbiYmbi5zcGxpdCgiXG4iKS5zb21lKCh0PT4tMSE9PXQuaW5kZXhPZigiKGh0dHBzLmpzOiIpfHwtMSE9PXQuaW5kZXhPZigibm9kZTpodHRwczoiKSkpfWNyZWF0ZVNvY2tldCh0LG4sZSl7Y29uc3Qgcj17Li4ubixzZWN1cmVFbmRwb2ludDp0aGlzLmlzU2VjdXJlRW5kcG9pbnQobil9O1Byb21pc2UucmVzb2x2ZSgpLnRoZW4oKCgpPT50aGlzLmNvbm5lY3QodCxyKSkpLnRoZW4oKG89PntpZihvIGluc3RhbmNlb2Ygcy5BZ2VudClyZXR1cm4gby5hZGRSZXF1ZXN0KHQscik7dGhpc1tvbl0uY3VycmVudFNvY2tldD1vLHN1cGVyLmNyZWF0ZVNvY2tldCh0LG4sZSl9KSxlKX1jcmVhdGVDb25uZWN0aW9uKCl7Y29uc3QgdD10aGlzW29uXS5jdXJyZW50U29ja2V0O2lmKHRoaXNbb25dLmN1cnJlbnRTb2NrZXQ9dm9pZCAwLCF0KXRocm93IG5ldyBFcnJvcigiTm8gc29ja2V0IHdhcyByZXR1cm5lZCBpbiB0aGUgYGNvbm5lY3QoKWAgZnVuY3Rpb24iKTtyZXR1cm4gdH1nZXQgZGVmYXVsdFBvcnQoKXtyZXR1cm4gdGhpc1tvbl0uZGVmYXVsdFBvcnQ/PygiaHR0cHM6Ij09PXRoaXMucHJvdG9jb2w/NDQzOjgwKX1zZXQgZGVmYXVsdFBvcnQodCl7dGhpc1tvbl0mJih0aGlzW29uXS5kZWZhdWx0UG9ydD10KX1nZXQgcHJvdG9jb2woKXtyZXR1cm4gdGhpc1tvbl0ucHJvdG9jb2w/Pyh0aGlzLmlzU2VjdXJlRW5kcG9pbnQoKT8iaHR0cHM6IjoiaHR0cDoiKX1zZXQgcHJvdG9jb2wodCl7dGhpc1tvbl0mJih0aGlzW29uXS5wcm90b2NvbD10KX19ZnVuY3Rpb24gY24oLi4udCl7Xy5sb2coIltodHRwcy1wcm94eS1hZ2VudDpwYXJzZS1wcm94eS1yZXNwb25zZV0iLC4uLnQpfWZ1bmN0aW9uIHVuKHQpe3JldHVybiBuZXcgUHJvbWlzZSgoKG4sZSk9PntsZXQgcj0wO2NvbnN0IG89W107ZnVuY3Rpb24gcygpe2NvbnN0IGM9dC5yZWFkKCk7Yz9mdW5jdGlvbihjKXtvLnB1c2goYykscis9Yy5sZW5ndGg7Y29uc3QgdT1CdWZmZXIuY29uY2F0KG8sciksYT11LmluZGV4T2YoIlxyXG5cclxuIik7aWYoLTE9PT1hKXJldHVybiBjbigiaGF2ZSBub3QgcmVjZWl2ZWQgZW5kIG9mIEhUVFAgaGVhZGVycyB5ZXQuLi4iKSx2b2lkIHMoKTtjb25zdCBmPXUuc2xpY2UoMCxhKS50b1N0cmluZygiYXNjaWkiKS5zcGxpdCgiXHJcbiIpLGg9Zi5zaGlmdCgpO2lmKCFoKXJldHVybiB0LmRlc3Ryb3koKSxlKG5ldyBFcnJvcigiTm8gaGVhZGVyIHJlY2VpdmVkIGZyb20gcHJveHkgQ09OTkVDVCByZXNwb25zZSIpKTtjb25zdCBwPWguc3BsaXQoIiAiKSxsPSsocFsxXXx8MCksZD1wLnNsaWNlKDIpLmpvaW4oIiAiKSxtPXt9O2Zvcihjb25zdCBuIG9mIGYpe2lmKCFuKWNvbnRpbnVlO2NvbnN0IHI9bi5pbmRleE9mKCI6Iik7aWYoLTE9PT1yKXJldHVybiB0LmRlc3Ryb3koKSxlKG5ldyBFcnJvcihgSW52YWxpZCBoZWFkZXIgZnJvbSBwcm94eSBDT05ORUNUIHJlc3BvbnNlOiAiJHtufSJgKSk7Y29uc3Qgbz1uLnNsaWNlKDAscikudG9Mb3dlckNhc2UoKSxzPW4uc2xpY2UocisxKS50cmltU3RhcnQoKSxpPW1bb107InN0cmluZyI9PXR5cGVvZiBpP21bb109W2ksc106QXJyYXkuaXNBcnJheShpKT9pLnB1c2gocyk6bVtvXT1zfWNuKCJnb3QgcHJveHkgc2VydmVyIHJlc3BvbnNlOiAlbyAlbyIsaCxtKSxpKCksbih7Y29ubmVjdDp7c3RhdHVzQ29kZTpsLHN0YXR1c1RleHQ6ZCxoZWFkZXJzOm19LGJ1ZmZlcmVkOnV9KX0oYyk6dC5vbmNlKCJyZWFkYWJsZSIscyl9ZnVuY3Rpb24gaSgpe3QucmVtb3ZlTGlzdGVuZXIoImVuZCIsYyksdC5yZW1vdmVMaXN0ZW5lcigiZXJyb3IiLHUpLHQucmVtb3ZlTGlzdGVuZXIoInJlYWRhYmxlIixzKX1mdW5jdGlvbiBjKCl7aSgpLGNuKCJvbmVuZCIpLGUobmV3IEVycm9yKCJQcm94eSBjb25uZWN0aW9uIGVuZGVkIGJlZm9yZSByZWNlaXZpbmcgQ09OTkVDVCByZXNwb25zZSIpKX1mdW5jdGlvbiB1KHQpe2koKSxjbigib25lcnJvciAlbyIsdCksZSh0KX10Lm9uKCJlcnJvciIsdSksdC5vbigiZW5kIixjKSxzKCl9KSl9ZnVuY3Rpb24gYW4oLi4udCl7Xy5sb2coIltodHRwcy1wcm94eS1hZ2VudF0iLC4uLnQpfWNsYXNzIGZuIGV4dGVuZHMgc257c3RhdGljIHByb3RvY29scz1bImh0dHAiLCJodHRwcyJdO3Byb3h5O3Byb3h5SGVhZGVycztjb25uZWN0T3B0cztjb25zdHJ1Y3Rvcih0LG4pe3N1cGVyKG4pLHRoaXMub3B0aW9ucz17fSx0aGlzLnByb3h5PSJzdHJpbmciPT10eXBlb2YgdD9uZXcgVVJMKHQpOnQsdGhpcy5wcm94eUhlYWRlcnM9bj8uaGVhZGVycz8/e30sYW4oIkNyZWF0aW5nIG5ldyBIdHRwc1Byb3h5QWdlbnQgaW5zdGFuY2U6ICVvIix0aGlzLnByb3h5LmhyZWYpO2NvbnN0IGU9KHRoaXMucHJveHkuaG9zdG5hbWV8fHRoaXMucHJveHkuaG9zdCkucmVwbGFjZSgvXlxbfFxdJC9nLCIiKSxyPXRoaXMucHJveHkucG9ydD9wYXJzZUludCh0aGlzLnByb3h5LnBvcnQsMTApOiJodHRwczoiPT09dGhpcy5wcm94eS5wcm90b2NvbD80NDM6ODA7dGhpcy5jb25uZWN0T3B0cz17QUxQTlByb3RvY29sczpbImh0dHAvMS4xIl0sLi4ubj9wbihuLCJoZWFkZXJzIik6bnVsbCxob3N0OmUscG9ydDpyfX1hc3luYyBjb25uZWN0KHQsbil7Y29uc3R7cHJveHk6ZX09dGhpcztpZighbi5ob3N0KXRocm93IG5ldyBUeXBlRXJyb3IoJ05vICJob3N0IiBwcm92aWRlZCcpO2xldCByO2lmKCJodHRwczoiPT09ZS5wcm90b2NvbCl7YW4oIkNyZWF0aW5nIGB0bHMuU29ja2V0YDogJW8iLHRoaXMuY29ubmVjdE9wdHMpO2NvbnN0IHQ9dGhpcy5jb25uZWN0T3B0cy5zZXJ2ZXJuYW1lfHx0aGlzLmNvbm5lY3RPcHRzLmhvc3Q7cj1mLmNvbm5lY3Qoey4uLnRoaXMuY29ubmVjdE9wdHMsc2VydmVybmFtZTp0JiZhLmlzSVAodCk/dm9pZCAwOnR9KX1lbHNlIGFuKCJDcmVhdGluZyBgbmV0LlNvY2tldGA6ICVvIix0aGlzLmNvbm5lY3RPcHRzKSxyPWEuY29ubmVjdCh0aGlzLmNvbm5lY3RPcHRzKTtjb25zdCBvPSJmdW5jdGlvbiI9PXR5cGVvZiB0aGlzLnByb3h5SGVhZGVycz90aGlzLnByb3h5SGVhZGVycygpOnsuLi50aGlzLnByb3h5SGVhZGVyc30scz1hLmlzSVB2NihuLmhvc3QpP2BbJHtuLmhvc3R9XWA6bi5ob3N0O2xldCBpPWBDT05ORUNUICR7c306JHtuLnBvcnR9IEhUVFAvMS4xXHJcbmA7aWYoZS51c2VybmFtZXx8ZS5wYXNzd29yZCl7Y29uc3QgdD1gJHtkZWNvZGVVUklDb21wb25lbnQoZS51c2VybmFtZSl9OiR7ZGVjb2RlVVJJQ29tcG9uZW50KGUucGFzc3dvcmQpfWA7b1siUHJveHktQXV0aG9yaXphdGlvbiJdPWBCYXNpYyAke0J1ZmZlci5mcm9tKHQpLnRvU3RyaW5nKCJiYXNlNjQiKX1gfW8uSG9zdD1gJHtzfToke24ucG9ydH1gLG9bIlByb3h5LUNvbm5lY3Rpb24iXXx8KG9bIlByb3h5LUNvbm5lY3Rpb24iXT10aGlzLmtlZXBBbGl2ZT8iS2VlcC1BbGl2ZSI6ImNsb3NlIik7Zm9yKGNvbnN0IHQgb2YgT2JqZWN0LmtleXMobykpaSs9YCR7dH06ICR7b1t0XX1cclxuYDtjb25zdCBjPXVuKHIpO3Iud3JpdGUoYCR7aX1cclxuYCk7Y29uc3R7Y29ubmVjdDp1LGJ1ZmZlcmVkOmh9PWF3YWl0IGM7aWYodC5lbWl0KCJwcm94eUNvbm5lY3QiLHUpLHRoaXMuZW1pdCgicHJveHlDb25uZWN0Iix1LHQpLDIwMD09PXUuc3RhdHVzQ29kZSl7aWYodC5vbmNlKCJzb2NrZXQiLGhuKSxuLnNlY3VyZUVuZHBvaW50KXthbigiVXBncmFkaW5nIHNvY2tldCBjb25uZWN0aW9uIHRvIFRMUyIpO2NvbnN0IHQ9bi5zZXJ2ZXJuYW1lfHxuLmhvc3Q7cmV0dXJuIGYuY29ubmVjdCh7Li4ucG4obiwiaG9zdCIsInBhdGgiLCJwb3J0Iiksc29ja2V0OnIsc2VydmVybmFtZTphLmlzSVAodCk/dm9pZCAwOnR9KX1yZXR1cm4gcn1yLmRlc3Ryb3koKTtjb25zdCBwPW5ldyBhLlNvY2tldCh7d3JpdGFibGU6ITF9KTtyZXR1cm4gcC5yZWFkYWJsZT0hMCx0Lm9uY2UoInNvY2tldCIsKHQ9PnthbigiUmVwbGF5aW5nIHByb3h5IGJ1ZmZlciBmb3IgZmFpbGVkIHJlcXVlc3QiKSx0LnB1c2goaCksdC5wdXNoKG51bGwpfSkpLHB9fWZ1bmN0aW9uIGhuKHQpe3QucmVzdW1lKCl9ZnVuY3Rpb24gcG4odCwuLi5uKXtjb25zdCBlPXt9O2xldCByO2ZvcihyIGluIHQpbi5pbmNsdWRlcyhyKXx8KGVbcl09dFtyXSk7cmV0dXJuIGV9Y29uc3QgbG49MzI3Njg7ZnVuY3Rpb24gZG4odCl7cmV0dXJuIHQucmVwbGFjZSgvXltBLVpdOi8sIiIpLnJlcGxhY2UoL1xcL2csIi8iKX1jb25zdCBtbj1lO2xldCB5bixnbj0wLGJuPXt9O2Z1bmN0aW9uIF9uKHQpe21uLmRlYnVnJiZjb25zb2xlLmxvZyhgW0FOUiBXb3JrZXJdICR7dH1gKX12YXIgdm4sd24sU247Y29uc3QgJG49ZnVuY3Rpb24odCl7bGV0IG47dHJ5e249bmV3IFVSTCh0LnVybCl9Y2F0Y2gobil7cmV0dXJuIGIoKCgpPT57Y29uc29sZS53YXJuKCJbQHNlbnRyeS9ub2RlXTogSW52YWxpZCBkc24gb3IgdHVubmVsIG9wdGlvbiwgd2lsbCBub3Qgc2VuZCBhbnkgZXZlbnRzLiBUaGUgdHVubmVsIG9wdGlvbiBtdXN0IGJlIGEgZnVsbCBVUkwgd2hlbiB1c2VkLiIpfSkpLHRuKHQsKCgpPT5Qcm9taXNlLnJlc29sdmUoe30pKSl9Y29uc3QgZT0iaHR0cHM6Ij09PW4ucHJvdG9jb2wscj1mdW5jdGlvbih0LG4pe2NvbnN0e25vX3Byb3h5OmV9PXByb2Nlc3MuZW52O3JldHVybiBlJiZlLnNwbGl0KCIsIikuc29tZSgobj0+dC5ob3N0LmVuZHNXaXRoKG4pfHx0Lmhvc3RuYW1lLmVuZHNXaXRoKG4pKSk/dm9pZCAwOm59KG4sdC5wcm94eXx8KGU/cHJvY2Vzcy5lbnYuaHR0cHNfcHJveHk6dm9pZCAwKXx8cHJvY2Vzcy5lbnYuaHR0cF9wcm94eSksbz1lP2k6cyxhPXZvaWQgMCE9PXQua2VlcEFsaXZlJiZ0LmtlZXBBbGl2ZSxmPXI/bmV3IGZuKHIpOm5ldyBvLkFnZW50KHtrZWVwQWxpdmU6YSxtYXhTb2NrZXRzOjMwLHRpbWVvdXQ6MmUzfSksaD1mdW5jdGlvbih0LG4sZSl7Y29uc3R7aG9zdG5hbWU6cixwYXRobmFtZTpvLHBvcnQ6cyxwcm90b2NvbDppLHNlYXJjaDphfT1uZXcgVVJMKHQudXJsKTtyZXR1cm4gZnVuY3Rpb24oZil7cmV0dXJuIG5ldyBQcm9taXNlKCgoaCxwKT0+e1d0KCgoKT0+e2xldCBsPWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgYyh7cmVhZCgpe3RoaXMucHVzaCh0KSx0aGlzLnB1c2gobnVsbCl9fSl9KGYuYm9keSk7Y29uc3QgZD17Li4udC5oZWFkZXJzfTtmLmJvZHkubGVuZ3RoPmxuJiYoZFsiY29udGVudC1lbmNvZGluZyJdPSJnemlwIixsPWwucGlwZSh1KCkpKTtjb25zdCBtPW4ucmVxdWVzdCh7bWV0aG9kOiJQT1NUIixhZ2VudDplLGhlYWRlcnM6ZCxob3N0bmFtZTpyLHBhdGg6YCR7b30ke2F9YCxwb3J0OnMscHJvdG9jb2w6aSxjYTp0LmNhQ2VydHN9LCh0PT57dC5vbigiZGF0YSIsKCgpPT57fSkpLHQub24oImVuZCIsKCgpPT57fSkpLHQuc2V0RW5jb2RpbmcoInV0ZjgiKTtjb25zdCBuPXQuaGVhZGVyc1sicmV0cnktYWZ0ZXIiXT8/bnVsbCxlPXQuaGVhZGVyc1sieC1zZW50cnktcmF0ZS1saW1pdHMiXT8/bnVsbDtoKHtzdGF0dXNDb2RlOnQuc3RhdHVzQ29kZSxoZWFkZXJzOnsicmV0cnktYWZ0ZXIiOm4sIngtc2VudHJ5LXJhdGUtbGltaXRzIjpBcnJheS5pc0FycmF5KGUpP2VbMF18fG51bGw6ZX19KX0pKTttLm9uKCJlcnJvciIscCksbC5waXBlKG0pfSkpfSkpfX0odCx0Lmh0dHBNb2R1bGU/P28sZik7cmV0dXJuIHRuKHQsaCl9KHt1cmw6KHZuPW1uLmRzbix3bj1tbi50dW5uZWwsU249bW4uc2RrTWV0YWRhdGEuc2RrLHdufHxgJHtmdW5jdGlvbih0KXtyZXR1cm5gJHtmdW5jdGlvbih0KXtjb25zdCBuPXQucHJvdG9jb2w/YCR7dC5wcm90b2NvbH06YDoiIixlPXQucG9ydD9gOiR7dC5wb3J0fWA6IiI7cmV0dXJuYCR7bn0vLyR7dC5ob3N0fSR7ZX0ke3QucGF0aD9gLyR7dC5wYXRofWA6IiJ9L2FwaS9gfSh0KX0ke3QucHJvamVjdElkfS9lbnZlbG9wZS9gfSh2bil9PyR7ZnVuY3Rpb24odCxuKXtjb25zdCBlPXtzZW50cnlfdmVyc2lvbjpLdH07cmV0dXJuIHQucHVibGljS2V5JiYoZS5zZW50cnlfa2V5PXQucHVibGljS2V5KSxuJiYoZS5zZW50cnlfY2xpZW50PWAke24ubmFtZX0vJHtuLnZlcnNpb259YCksbmV3IFVSTFNlYXJjaFBhcmFtcyhlKS50b1N0cmluZygpfSh2bixTbil9YCkscmVjb3JkRHJvcHBlZEV2ZW50OigpPT57fX0pO2FzeW5jIGZ1bmN0aW9uIEVuKCl7aWYoeW4pe19uKCJTZW5kaW5nIGFibm9ybWFsIHNlc3Npb24iKSxWKHluLHtzdGF0dXM6ImFibm9ybWFsIixhYm5vcm1hbF9tZWNoYW5pc206ImFucl9mb3JlZ3JvdW5kIn0pO2NvbnN0IHQ9ZnVuY3Rpb24odCxuLGUscil7Y29uc3Qgbz1ZdChlKTtyZXR1cm4gTXQoe3NlbnRfYXQ6KG5ldyBEYXRlKS50b0lTT1N0cmluZygpLC4uLm8mJntzZGs6b30sLi4uISFyJiZuJiZ7ZHNuOkF0KG4pfX0sWyJhZ2dyZWdhdGVzImluIHQ/W3t0eXBlOiJzZXNzaW9ucyJ9LHRdOlt7dHlwZToic2Vzc2lvbiJ9LHQudG9KU09OKCldXSl9KHluLG1uLmRzbixtbi5zZGtNZXRhZGF0YSxtbi50dW5uZWwpO19uKEpTT04uc3RyaW5naWZ5KHQpKSxhd2FpdCAkbi5zZW5kKHQpO3RyeXtuPy5wb3N0TWVzc2FnZSgic2Vzc2lvbi1lbmRlZCIpfWNhdGNoKHQpe319fWZ1bmN0aW9uIHhuKHQpe2lmKCF0KXJldHVybjtjb25zdCBuPWZ1bmN0aW9uKHQpe2lmKCF0Lmxlbmd0aClyZXR1cm5bXTtjb25zdCBuPUFycmF5LmZyb20odCk7cmV0dXJuL3NlbnRyeVdyYXBwZWQvLnRlc3QoJChuKS5mdW5jdGlvbnx8IiIpJiZuLnBvcCgpLG4ucmV2ZXJzZSgpLFMudGVzdCgkKG4pLmZ1bmN0aW9ufHwiIikmJihuLnBvcCgpLFMudGVzdCgkKG4pLmZ1bmN0aW9ufHwiIikmJm4ucG9wKCkpLG4uc2xpY2UoMCx2KS5tYXAoKHQ9Pih7Li4udCxmaWxlbmFtZTp0LmZpbGVuYW1lfHwkKG4pLmZpbGVuYW1lLGZ1bmN0aW9uOnQuZnVuY3Rpb258fHd9KSkpfSh0KTtpZihtbi5hcHBSb290UGF0aClmb3IoY29uc3QgdCBvZiBuKXQuZmlsZW5hbWUmJih0LmZpbGVuYW1lPVV0KHQuZmlsZW5hbWUsbW4uYXBwUm9vdFBhdGgpKTtyZXR1cm4gbn1hc3luYyBmdW5jdGlvbiBObih0LG4pe2lmKGduPj1tbi5tYXhBbnJFdmVudHMpcmV0dXJuO2duKz0xLGF3YWl0IEVuKCksX24oIlNlbmRpbmcgZXZlbnQiKTtjb25zdCBlPXtldmVudF9pZDp6KCksY29udGV4dHM6bW4uY29udGV4dHMscmVsZWFzZTptbi5yZWxlYXNlLGVudmlyb25tZW50Om1uLmVudmlyb25tZW50LGRpc3Q6bW4uZGlzdCxwbGF0Zm9ybToibm9kZSIsbGV2ZWw6ImVycm9yIixleGNlcHRpb246e3ZhbHVlczpbe3R5cGU6IkFwcGxpY2F0aW9uTm90UmVzcG9uZGluZyIsdmFsdWU6YEFwcGxpY2F0aW9uIE5vdCBSZXNwb25kaW5nIGZvciBhdCBsZWFzdCAke21uLmFuclRocmVzaG9sZH0gbXNgLHN0YWNrdHJhY2U6e2ZyYW1lczp4bih0KX0sbWVjaGFuaXNtOnt0eXBlOiJBTlIifX1dfSx0YWdzOm1uLnN0YXRpY1RhZ3N9O24mJmZ1bmN0aW9uKHQsbil7aWYoRnQodCxuKSwhdC5jb250ZXh0cz8udHJhY2Upe2NvbnN0e3RyYWNlSWQ6ZSxzcGFuSWQ6cixwYXJlbnRTcGFuSWQ6b309bi5wcm9wYWdhdGlvbkNvbnRleHQ7dC5jb250ZXh0cz17dHJhY2U6e3RyYWNlX2lkOmUsc3Bhbl9pZDpyLHBhcmVudF9zcGFuX2lkOm99LC4uLnQuY29udGV4dHN9fX0oZSxuKSxmdW5jdGlvbih0KXtpZigwPT09T2JqZWN0LmtleXMoYm4pLmxlbmd0aClyZXR1cm47Y29uc3Qgbj1tbi5hcHBSb290UGF0aD97fTpibjtpZihtbi5hcHBSb290UGF0aClmb3IoY29uc3RbdCxlXW9mIE9iamVjdC5lbnRyaWVzKGJuKSluW1V0KHQsbW4uYXBwUm9vdFBhdGgpXT1lO2NvbnN0IGU9bmV3IE1hcDtmb3IoY29uc3QgciBvZiB0LmV4Y2VwdGlvbj8udmFsdWVzfHxbXSlmb3IoY29uc3QgdCBvZiByLnN0YWNrdHJhY2U/LmZyYW1lc3x8W10pe2NvbnN0IHI9dC5hYnNfcGF0aHx8dC5maWxlbmFtZTtyJiZuW3JdJiZlLnNldChyLG5bcl0pfWlmKGUuc2l6ZT4wKXtjb25zdCBuPVtdO2Zvcihjb25zdFt0LHJdb2YgZS5lbnRyaWVzKCkpbi5wdXNoKHt0eXBlOiJzb3VyY2VtYXAiLGNvZGVfZmlsZTp0LGRlYnVnX2lkOnJ9KTt0LmRlYnVnX21ldGE9e2ltYWdlczpufX19KGUpO2NvbnN0IHI9enQoZSxtbi5kc24sbW4uc2RrTWV0YWRhdGEsbW4udHVubmVsKTtfbihKU09OLnN0cmluZ2lmeShyKSksYXdhaXQgJG4uc2VuZChyKSxhd2FpdCAkbi5mbHVzaCgyZTMpLGduPj1tbi5tYXhBbnJFdmVudHMmJnNldFRpbWVvdXQoKCgpPT57cHJvY2Vzcy5leGl0KDApfSksNWUzKX1sZXQgVG47aWYoX24oIlN0YXJ0ZWQiKSxtbi5jYXB0dXJlU3RhY2tUcmFjZSl7X24oIkNvbm5lY3RpbmcgdG8gZGVidWdnZXIiKTtjb25zdCBuPW5ldyB0O24uY29ubmVjdFRvTWFpblRocmVhZCgpLF9uKCJDb25uZWN0ZWQgdG8gZGVidWdnZXIiKTtjb25zdCBlPW5ldyBNYXA7bi5vbigiRGVidWdnZXIuc2NyaXB0UGFyc2VkIiwodD0+e2Uuc2V0KHQucGFyYW1zLnNjcmlwdElkLHQucGFyYW1zLnVybCl9KSksbi5vbigiRGVidWdnZXIucGF1c2VkIiwodD0+e2lmKCJvdGhlciI9PT10LnBhcmFtcy5yZWFzb24pdHJ5e19uKCJEZWJ1Z2dlciBwYXVzZWQiKTtjb25zdCBzPVsuLi50LnBhcmFtcy5jYWxsRnJhbWVzXSxpPW1uLmFwcFJvb3RQYXRoP2Z1bmN0aW9uKHQ9KHByb2Nlc3MuYXJndlsxXT9lbihwcm9jZXNzLmFyZ3ZbMV0pOnByb2Nlc3MuY3dkKCkpLG49IlxcIj09PW8pe2NvbnN0IGU9bj9kbih0KTp0O3JldHVybiB0PT57aWYoIXQpcmV0dXJuO2NvbnN0IG89bj9kbih0KTp0O2xldHtkaXI6cyxiYXNlOmksZXh0OmN9PXIucGFyc2Uobyk7Ii5qcyIhPT1jJiYiLm1qcyIhPT1jJiYiLmNqcyIhPT1jfHwoaT1pLnNsaWNlKDAsLTEqYy5sZW5ndGgpKTtjb25zdCB1PWRlY29kZVVSSUNvbXBvbmVudChpKTtzfHwocz0iLiIpO2NvbnN0IGE9cy5sYXN0SW5kZXhPZigiL25vZGVfbW9kdWxlcyIpO2lmKGE+LTEpcmV0dXJuYCR7cy5zbGljZShhKzE0KS5yZXBsYWNlKC9cLy9nLCIuIil9OiR7dX1gO2lmKHMuc3RhcnRzV2l0aChlKSl7Y29uc3QgdD1zLnNsaWNlKGUubGVuZ3RoKzEpLnJlcGxhY2UoL1wvL2csIi4iKTtyZXR1cm4gdD9gJHt0fToke3V9YDp1fXJldHVybiB1fX0obW4uYXBwUm9vdFBhdGgpOigpPT57fSxjPXMubWFwKCh0PT5mdW5jdGlvbih0LG4sZSl7Y29uc3Qgcj1uP24ucmVwbGFjZSgvXmZpbGU6XC9cLy8sIiIpOnZvaWQgMCxvPXQubG9jYXRpb24uY29sdW1uTnVtYmVyP3QubG9jYXRpb24uY29sdW1uTnVtYmVyKzE6dm9pZCAwLHM9dC5sb2NhdGlvbi5saW5lTnVtYmVyP3QubG9jYXRpb24ubGluZU51bWJlcisxOnZvaWQgMDtyZXR1cm4gTCh7ZmlsZW5hbWU6cixtb2R1bGU6ZShyKSxmdW5jdGlvbjp0LmZ1bmN0aW9uTmFtZXx8dyxjb2xubzpvLGxpbmVubzpzLGluX2FwcDpyP3JuKHIpOnZvaWQgMH0pfSh0LGUuZ2V0KHQubG9jYXRpb24uc2NyaXB0SWQpLGkpKSksdT1zZXRUaW1lb3V0KCgoKT0+e05uKGMpLnRoZW4obnVsbCwoKCk9PntfbigiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkLiIpfSkpfSksNWUzKTtuLnBvc3QoIlJ1bnRpbWUuZXZhbHVhdGUiLHtleHByZXNzaW9uOiJnbG9iYWwuX19TRU5UUllfR0VUX1NDT1BFU19fKCk7IixzaWxlbnQ6ITAscmV0dXJuQnlWYWx1ZTohMH0sKCh0LGUpPT57dCYmX24oYEVycm9yIGV4ZWN1dGluZyBzY3JpcHQ6ICcke3QubWVzc2FnZX0nYCksY2xlYXJUaW1lb3V0KHUpO2NvbnN0IHI9ZSYmZS5yZXN1bHQ/ZS5yZXN1bHQudmFsdWU6dm9pZCAwO24ucG9zdCgiRGVidWdnZXIucmVzdW1lIiksbi5wb3N0KCJEZWJ1Z2dlci5kaXNhYmxlIiksTm4oYyxyKS50aGVuKG51bGwsKCgpPT57X24oIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZC4iKX0pKX0pKX1jYXRjaCh0KXt0aHJvdyBuLnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpLG4ucG9zdCgiRGVidWdnZXIuZGlzYWJsZSIpLHR9fSkpLFRuPSgpPT57dHJ5e24ucG9zdCgiRGVidWdnZXIuZW5hYmxlIiwoKCk9PntuLnBvc3QoIkRlYnVnZ2VyLnBhdXNlIil9KSl9Y2F0Y2godCl7fX19Y29uc3R7cG9sbDpDbn09ZnVuY3Rpb24odCxuLGUscil7Y29uc3Qgbz10KCk7bGV0IHM9ITEsaT0hMDtyZXR1cm4gc2V0SW50ZXJ2YWwoKCgpPT57Y29uc3QgdD1vLmdldFRpbWVNcygpOyExPT09cyYmdD5uK2UmJihzPSEwLGkmJnIoKSksdDxuK2UmJihzPSExKX0pLDIwKSx7cG9sbDooKT0+e28ucmVzZXQoKX0sZW5hYmxlZDp0PT57aT10fX19KChmdW5jdGlvbigpe2xldCB0PXByb2Nlc3MuaHJ0aW1lKCk7cmV0dXJue2dldFRpbWVNczooKT0+e2NvbnN0W24sZV09cHJvY2Vzcy5ocnRpbWUodCk7cmV0dXJuIE1hdGguZmxvb3IoMWUzKm4rZS8xZTYpfSxyZXNldDooKT0+e3Q9cHJvY2Vzcy5ocnRpbWUoKX19fSksbW4ucG9sbEludGVydmFsLG1uLmFuclRocmVzaG9sZCwoZnVuY3Rpb24oKXtfbigiV2F0Y2hkb2cgdGltZW91dCIpLFRuPyhfbigiUGF1c2luZyBkZWJ1Z2dlciB0byBjYXB0dXJlIHN0YWNrIHRyYWNlIiksVG4oKSk6KF9uKCJDYXB0dXJpbmcgZXZlbnQgd2l0aG91dCBhIHN0YWNrIHRyYWNlIiksTm4oKS50aGVuKG51bGwsKCgpPT57X24oIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZCBvbiB3YXRjaGRvZyB0aW1lb3V0LiIpfSkpKX0pKTtuPy5vbigibWVzc2FnZSIsKHQ9Pnt0LnNlc3Npb24mJih5bj1LKHQuc2Vzc2lvbikpLHQuZGVidWdJbWFnZXMmJihibj10LmRlYnVnSW1hZ2VzKSxDbigpfSkpOw==';
|
|
12
|
+
const base64WorkerScript = 'LyohIEBzZW50cnkvbm9kZSA5LjAuMC1hbHBoYS4wICgwMzUwMjJiKSB8IGh0dHBzOi8vZ2l0aHViLmNvbS9nZXRzZW50cnkvc2VudHJ5LWphdmFzY3JpcHQgKi8KaW1wb3J0e1Nlc3Npb24gYXMgdH1mcm9tIm5vZGU6aW5zcGVjdG9yIjtpbXBvcnR7cGFyZW50UG9ydCBhcyBuLHdvcmtlckRhdGEgYXMgZX1mcm9tIm5vZGU6d29ya2VyX3RocmVhZHMiO2ltcG9ydHtwb3NpeCBhcyByLHNlcCBhcyBvfWZyb20ibm9kZTpwYXRoIjtpbXBvcnQqYXMgcyBmcm9tIm5vZGU6aHR0cCI7aW1wb3J0KmFzIGkgZnJvbSJub2RlOmh0dHBzIjtpbXBvcnR7UmVhZGFibGUgYXMgY31mcm9tIm5vZGU6c3RyZWFtIjtpbXBvcnR7Y3JlYXRlR3ppcCBhcyB1fWZyb20ibm9kZTp6bGliIjtpbXBvcnQqYXMgYSBmcm9tIm5vZGU6bmV0IjtpbXBvcnQqYXMgZiBmcm9tIm5vZGU6dGxzIjtjb25zdCBoPSJ1bmRlZmluZWQiPT10eXBlb2YgX19TRU5UUllfREVCVUdfX3x8X19TRU5UUllfREVCVUdfXyxwPWdsb2JhbFRoaXMsZD0idW5kZWZpbmVkIj09dHlwZW9mIF9fU0VOVFJZX0RFQlVHX198fF9fU0VOVFJZX0RFQlVHX18sbD0iOS4wLjAtYWxwaGEuMCI7ZnVuY3Rpb24gbSgpe3JldHVybiBnKHApLHB9ZnVuY3Rpb24gZyh0KXtjb25zdCBuPXQuX19TRU5UUllfXz10Ll9fU0VOVFJZX198fHt9O3JldHVybiBuLnZlcnNpb249bi52ZXJzaW9ufHxsLG5bbF09bltsXXx8e319ZnVuY3Rpb24geSh0LG4sZT1wKXtjb25zdCByPWUuX19TRU5UUllfXz1lLl9fU0VOVFJZX198fHt9LG89cltsXT1yW2xdfHx7fTtyZXR1cm4gb1t0XXx8KG9bdF09bigpKX1jb25zdCBiPVsiZGVidWciLCJpbmZvIiwid2FybiIsImVycm9yIiwibG9nIiwiYXNzZXJ0IiwidHJhY2UiXSxfPXt9O2Z1bmN0aW9uIHYodCl7aWYoISgiY29uc29sZSJpbiBwKSlyZXR1cm4gdCgpO2NvbnN0IG49cC5jb25zb2xlLGU9e30scj1PYmplY3Qua2V5cyhfKTtyLmZvckVhY2goKHQ9Pntjb25zdCByPV9bdF07ZVt0XT1uW3RdLG5bdF09cn0pKTt0cnl7cmV0dXJuIHQoKX1maW5hbGx5e3IuZm9yRWFjaCgodD0+e25bdF09ZVt0XX0pKX19Y29uc3Qgdz15KCJsb2dnZXIiLChmdW5jdGlvbigpe2xldCB0PSExO2NvbnN0IG49e2VuYWJsZTooKT0+e3Q9ITB9LGRpc2FibGU6KCk9Pnt0PSExfSxpc0VuYWJsZWQ6KCk9PnR9O3JldHVybiBkP2IuZm9yRWFjaCgoZT0+e25bZV09KC4uLm4pPT57dCYmdigoKCk9PntwLmNvbnNvbGVbZV0oYFNlbnRyeSBMb2dnZXIgWyR7ZX1dOmAsLi4ubil9KSl9fSkpOmIuZm9yRWFjaCgodD0+e25bdF09KCk9Pnt9fSkpLG59KSksUz01MCwkPSI/IixFPS9jYXB0dXJlTWVzc2FnZXxjYXB0dXJlRXhjZXB0aW9uLztmdW5jdGlvbiB4KHQpe3JldHVybiB0W3QubGVuZ3RoLTFdfHx7fX1jb25zdCBOPSI8YW5vbnltb3VzPiI7Y29uc3QgVD1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO2Z1bmN0aW9uIGoodCxuKXtyZXR1cm4gVC5jYWxsKHQpPT09YFtvYmplY3QgJHtufV1gfWZ1bmN0aW9uIEModCl7cmV0dXJuIGoodCwiU3RyaW5nIil9ZnVuY3Rpb24gTyh0KXtyZXR1cm4gaih0LCJPYmplY3QiKX1mdW5jdGlvbiBSKHQpe3JldHVybiBCb29sZWFuKHQ/LnRoZW4mJiJmdW5jdGlvbiI9PXR5cGVvZiB0LnRoZW4pfWZ1bmN0aW9uIEQodCxuKXt0cnl7cmV0dXJuIHQgaW5zdGFuY2VvZiBufWNhdGNoKHQpe3JldHVybiExfX1jb25zdCBrPXAsQT04MDtmdW5jdGlvbiBJKHQsbil7Y29uc3QgZT10LHI9W107aWYoIWU/LnRhZ05hbWUpcmV0dXJuIiI7aWYoay5IVE1MRWxlbWVudCYmZSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50JiZlLmRhdGFzZXQpe2lmKGUuZGF0YXNldC5zZW50cnlDb21wb25lbnQpcmV0dXJuIGUuZGF0YXNldC5zZW50cnlDb21wb25lbnQ7aWYoZS5kYXRhc2V0LnNlbnRyeUVsZW1lbnQpcmV0dXJuIGUuZGF0YXNldC5zZW50cnlFbGVtZW50fXIucHVzaChlLnRhZ05hbWUudG9Mb3dlckNhc2UoKSk7Y29uc3Qgbz1uPy5sZW5ndGg/bi5maWx0ZXIoKHQ9PmUuZ2V0QXR0cmlidXRlKHQpKSkubWFwKCh0PT5bdCxlLmdldEF0dHJpYnV0ZSh0KV0pKTpudWxsO2lmKG8/Lmxlbmd0aClvLmZvckVhY2goKHQ9PntyLnB1c2goYFske3RbMF19PSIke3RbMV19Il1gKX0pKTtlbHNle2UuaWQmJnIucHVzaChgIyR7ZS5pZH1gKTtjb25zdCB0PWUuY2xhc3NOYW1lO2lmKHQmJkModCkpe2NvbnN0IG49dC5zcGxpdCgvXHMrLyk7Zm9yKGNvbnN0IHQgb2YgbilyLnB1c2goYC4ke3R9YCl9fWNvbnN0IHM9WyJhcmlhLWxhYmVsIiwidHlwZSIsIm5hbWUiLCJ0aXRsZSIsImFsdCJdO2Zvcihjb25zdCB0IG9mIHMpe2NvbnN0IG49ZS5nZXRBdHRyaWJ1dGUodCk7biYmci5wdXNoKGBbJHt0fT0iJHtufSJdYCl9cmV0dXJuIHIuam9pbigiIil9ZnVuY3Rpb24gUCh0KXtpZihmdW5jdGlvbih0KXtzd2l0Y2goVC5jYWxsKHQpKXtjYXNlIltvYmplY3QgRXJyb3JdIjpjYXNlIltvYmplY3QgRXhjZXB0aW9uXSI6Y2FzZSJbb2JqZWN0IERPTUV4Y2VwdGlvbl0iOmNhc2UiW29iamVjdCBXZWJBc3NlbWJseS5FeGNlcHRpb25dIjpyZXR1cm4hMDtkZWZhdWx0OnJldHVybiBEKHQsRXJyb3IpfX0odCkpcmV0dXJue21lc3NhZ2U6dC5tZXNzYWdlLG5hbWU6dC5uYW1lLHN0YWNrOnQuc3RhY2ssLi4uTSh0KX07aWYobj10LCJ1bmRlZmluZWQiIT10eXBlb2YgRXZlbnQmJkQobixFdmVudCkpe2NvbnN0IG49e3R5cGU6dC50eXBlLHRhcmdldDpVKHQudGFyZ2V0KSxjdXJyZW50VGFyZ2V0OlUodC5jdXJyZW50VGFyZ2V0KSwuLi5NKHQpfTtyZXR1cm4idW5kZWZpbmVkIiE9dHlwZW9mIEN1c3RvbUV2ZW50JiZEKHQsQ3VzdG9tRXZlbnQpJiYobi5kZXRhaWw9dC5kZXRhaWwpLG59cmV0dXJuIHQ7dmFyIG59ZnVuY3Rpb24gVSh0KXt0cnl7cmV0dXJuIG49dCwidW5kZWZpbmVkIiE9dHlwZW9mIEVsZW1lbnQmJkQobixFbGVtZW50KT9mdW5jdGlvbih0LG49e30pe2lmKCF0KXJldHVybiI8dW5rbm93bj4iO3RyeXtsZXQgZT10O2NvbnN0IHI9NSxvPVtdO2xldCBzPTAsaT0wO2NvbnN0IGM9IiA+ICIsdT1jLmxlbmd0aDtsZXQgYTtjb25zdCBmPUFycmF5LmlzQXJyYXkobik/bjpuLmtleUF0dHJzLGg9IUFycmF5LmlzQXJyYXkobikmJm4ubWF4U3RyaW5nTGVuZ3RofHxBO2Zvcig7ZSYmcysrPHImJihhPUkoZSxmKSwhKCJodG1sIj09PWF8fHM+MSYmaStvLmxlbmd0aCp1K2EubGVuZ3RoPj1oKSk7KW8ucHVzaChhKSxpKz1hLmxlbmd0aCxlPWUucGFyZW50Tm9kZTtyZXR1cm4gby5yZXZlcnNlKCkuam9pbihjKX1jYXRjaCh0KXtyZXR1cm4iPHVua25vd24+In19KHQpOk9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh0KX1jYXRjaCh0KXtyZXR1cm4iPHVua25vd24+In12YXIgbn1mdW5jdGlvbiBNKHQpe2lmKCJvYmplY3QiPT10eXBlb2YgdCYmbnVsbCE9PXQpe2NvbnN0IG49e307Zm9yKGNvbnN0IGUgaW4gdClPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodCxlKSYmKG5bZV09dFtlXSk7cmV0dXJuIG59cmV0dXJue319ZnVuY3Rpb24gTCh0KXtyZXR1cm4gQih0LG5ldyBNYXApfWZ1bmN0aW9uIEIodCxuKXtpZihmdW5jdGlvbih0KXtpZighTyh0KSlyZXR1cm4hMTt0cnl7Y29uc3Qgbj1PYmplY3QuZ2V0UHJvdG90eXBlT2YodCkuY29uc3RydWN0b3IubmFtZTtyZXR1cm4hbnx8Ik9iamVjdCI9PT1ufWNhdGNoe3JldHVybiEwfX0odCkpe2NvbnN0IGU9bi5nZXQodCk7aWYodm9pZCAwIT09ZSlyZXR1cm4gZTtjb25zdCByPXt9O24uc2V0KHQscik7Zm9yKGNvbnN0IGUgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModCkpdm9pZCAwIT09dFtlXSYmKHJbZV09Qih0W2VdLG4pKTtyZXR1cm4gcn1pZihBcnJheS5pc0FycmF5KHQpKXtjb25zdCBlPW4uZ2V0KHQpO2lmKHZvaWQgMCE9PWUpcmV0dXJuIGU7Y29uc3Qgcj1bXTtyZXR1cm4gbi5zZXQodCxyKSx0LmZvckVhY2goKHQ9PntyLnB1c2goQih0LG4pKX0pKSxyfXJldHVybiB0fWNvbnN0IEc9MWUzO2Z1bmN0aW9uIEooKXtyZXR1cm4gRGF0ZS5ub3coKS9HfWNvbnN0IFk9ZnVuY3Rpb24oKXtjb25zdHtwZXJmb3JtYW5jZTp0fT1wO2lmKCF0Py5ub3cpcmV0dXJuIEo7Y29uc3Qgbj1EYXRlLm5vdygpLXQubm93KCksZT1udWxsPT10LnRpbWVPcmlnaW4/bjp0LnRpbWVPcmlnaW47cmV0dXJuKCk9PihlK3Qubm93KCkpL0d9KCk7ZnVuY3Rpb24geigpe2NvbnN0IHQ9cCxuPXQuY3J5cHRvfHx0Lm1zQ3J5cHRvO2xldCBlPSgpPT4xNipNYXRoLnJhbmRvbSgpO3RyeXtpZihuPy5yYW5kb21VVUlEKXJldHVybiBuLnJhbmRvbVVVSUQoKS5yZXBsYWNlKC8tL2csIiIpO24/LmdldFJhbmRvbVZhbHVlcyYmKGU9KCk9Pntjb25zdCB0PW5ldyBVaW50OEFycmF5KDEpO3JldHVybiBuLmdldFJhbmRvbVZhbHVlcyh0KSx0WzBdfSl9Y2F0Y2godCl7fXJldHVybihbMWU3XSsxZTMrNGUzKzhlMysxZTExKS5yZXBsYWNlKC9bMDE4XS9nLCh0PT4odF4oMTUmZSgpKT4+dC80KS50b1N0cmluZygxNikpKX12YXIgSDtmdW5jdGlvbiBXKHQpe3JldHVybiBuZXcgRigobj0+e24odCl9KSl9IWZ1bmN0aW9uKHQpe3RbdC5QRU5ESU5HPTBdPSJQRU5ESU5HIjt0W3QuUkVTT0xWRUQ9MV09IlJFU09MVkVEIjt0W3QuUkVKRUNURUQ9Ml09IlJFSkVDVEVEIn0oSHx8KEg9e30pKTtjbGFzcyBGe2NvbnN0cnVjdG9yKHQpe3RoaXMudD1ILlBFTkRJTkcsdGhpcy5vPVtdLHRoaXMuaSh0KX10aGVuKHQsbil7cmV0dXJuIG5ldyBGKCgoZSxyKT0+e3RoaXMuby5wdXNoKFshMSxuPT57aWYodCl0cnl7ZSh0KG4pKX1jYXRjaCh0KXtyKHQpfWVsc2UgZShuKX0sdD0+e2lmKG4pdHJ5e2Uobih0KSl9Y2F0Y2godCl7cih0KX1lbHNlIHIodCl9XSksdGhpcy51KCl9KSl9Y2F0Y2godCl7cmV0dXJuIHRoaXMudGhlbigodD0+dCksdCl9ZmluYWxseSh0KXtyZXR1cm4gbmV3IEYoKChuLGUpPT57bGV0IHIsbztyZXR1cm4gdGhpcy50aGVuKChuPT57bz0hMSxyPW4sdCYmdCgpfSksKG49PntvPSEwLHI9bix0JiZ0KCl9KSkudGhlbigoKCk9PntvP2Uocik6bihyKX0pKX0pKX11KCl7aWYodGhpcy50PT09SC5QRU5ESU5HKXJldHVybjtjb25zdCB0PXRoaXMuby5zbGljZSgpO3RoaXMubz1bXSx0LmZvckVhY2goKHQ9Pnt0WzBdfHwodGhpcy50PT09SC5SRVNPTFZFRCYmdFsxXSh0aGlzLmgpLHRoaXMudD09PUguUkVKRUNURUQmJnRbMl0odGhpcy5oKSx0WzBdPSEwKX0pKX1pKHQpe2NvbnN0IG49KHQsbik9Pnt0aGlzLnQ9PT1ILlBFTkRJTkcmJihSKG4pP24udGhlbihlLHIpOih0aGlzLnQ9dCx0aGlzLmg9bix0aGlzLnUoKSkpfSxlPXQ9PntuKEguUkVTT0xWRUQsdCl9LHI9dD0+e24oSC5SRUpFQ1RFRCx0KX07dHJ5e3QoZSxyKX1jYXRjaCh0KXtyKHQpfX19ZnVuY3Rpb24gSyh0KXtjb25zdCBuPVkoKSxlPXtzaWQ6eigpLGluaXQ6ITAsdGltZXN0YW1wOm4sc3RhcnRlZDpuLGR1cmF0aW9uOjAsc3RhdHVzOiJvayIsZXJyb3JzOjAsaWdub3JlRHVyYXRpb246ITEsdG9KU09OOigpPT5mdW5jdGlvbih0KXtyZXR1cm4gTCh7c2lkOmAke3Quc2lkfWAsaW5pdDp0LmluaXQsc3RhcnRlZDpuZXcgRGF0ZSgxZTMqdC5zdGFydGVkKS50b0lTT1N0cmluZygpLHRpbWVzdGFtcDpuZXcgRGF0ZSgxZTMqdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksc3RhdHVzOnQuc3RhdHVzLGVycm9yczp0LmVycm9ycyxkaWQ6Im51bWJlciI9PXR5cGVvZiB0LmRpZHx8InN0cmluZyI9PXR5cGVvZiB0LmRpZD9gJHt0LmRpZH1gOnZvaWQgMCxkdXJhdGlvbjp0LmR1cmF0aW9uLGFibm9ybWFsX21lY2hhbmlzbTp0LmFibm9ybWFsX21lY2hhbmlzbSxhdHRyczp7cmVsZWFzZTp0LnJlbGVhc2UsZW52aXJvbm1lbnQ6dC5lbnZpcm9ubWVudCxpcF9hZGRyZXNzOnQuaXBBZGRyZXNzLHVzZXJfYWdlbnQ6dC51c2VyQWdlbnR9fSl9KGUpfTtyZXR1cm4gdCYmVihlLHQpLGV9ZnVuY3Rpb24gVih0LG49e30pe2lmKG4udXNlciYmKCF0LmlwQWRkcmVzcyYmbi51c2VyLmlwX2FkZHJlc3MmJih0LmlwQWRkcmVzcz1uLnVzZXIuaXBfYWRkcmVzcyksdC5kaWR8fG4uZGlkfHwodC5kaWQ9bi51c2VyLmlkfHxuLnVzZXIuZW1haWx8fG4udXNlci51c2VybmFtZSkpLHQudGltZXN0YW1wPW4udGltZXN0YW1wfHxZKCksbi5hYm5vcm1hbF9tZWNoYW5pc20mJih0LmFibm9ybWFsX21lY2hhbmlzbT1uLmFibm9ybWFsX21lY2hhbmlzbSksbi5pZ25vcmVEdXJhdGlvbiYmKHQuaWdub3JlRHVyYXRpb249bi5pZ25vcmVEdXJhdGlvbiksbi5zaWQmJih0LnNpZD0zMj09PW4uc2lkLmxlbmd0aD9uLnNpZDp6KCkpLHZvaWQgMCE9PW4uaW5pdCYmKHQuaW5pdD1uLmluaXQpLCF0LmRpZCYmbi5kaWQmJih0LmRpZD1gJHtuLmRpZH1gKSwibnVtYmVyIj09dHlwZW9mIG4uc3RhcnRlZCYmKHQuc3RhcnRlZD1uLnN0YXJ0ZWQpLHQuaWdub3JlRHVyYXRpb24pdC5kdXJhdGlvbj12b2lkIDA7ZWxzZSBpZigibnVtYmVyIj09dHlwZW9mIG4uZHVyYXRpb24pdC5kdXJhdGlvbj1uLmR1cmF0aW9uO2Vsc2V7Y29uc3Qgbj10LnRpbWVzdGFtcC10LnN0YXJ0ZWQ7dC5kdXJhdGlvbj1uPj0wP246MH1uLnJlbGVhc2UmJih0LnJlbGVhc2U9bi5yZWxlYXNlKSxuLmVudmlyb25tZW50JiYodC5lbnZpcm9ubWVudD1uLmVudmlyb25tZW50KSwhdC5pcEFkZHJlc3MmJm4uaXBBZGRyZXNzJiYodC5pcEFkZHJlc3M9bi5pcEFkZHJlc3MpLCF0LnVzZXJBZ2VudCYmbi51c2VyQWdlbnQmJih0LnVzZXJBZ2VudD1uLnVzZXJBZ2VudCksIm51bWJlciI9PXR5cGVvZiBuLmVycm9ycyYmKHQuZXJyb3JzPW4uZXJyb3JzKSxuLnN0YXR1cyYmKHQuc3RhdHVzPW4uc3RhdHVzKX1mdW5jdGlvbiBaKCl7cmV0dXJuIHooKX1mdW5jdGlvbiBxKCl7cmV0dXJuIHooKS5zdWJzdHJpbmcoMTYpfWZ1bmN0aW9uIFEodCxuLGU9Mil7aWYoIW58fCJvYmplY3QiIT10eXBlb2Ygbnx8ZTw9MClyZXR1cm4gbjtpZih0JiYwPT09T2JqZWN0LmtleXMobikubGVuZ3RoKXJldHVybiB0O2NvbnN0IHI9ey4uLnR9O2Zvcihjb25zdCB0IGluIG4pT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG4sdCkmJihyW3RdPVEoclt0XSxuW3RdLGUtMSkpO3JldHVybiByfWNvbnN0IFg9Il9zZW50cnlTcGFuIjtmdW5jdGlvbiB0dCh0LG4pe24/ZnVuY3Rpb24odCxuLGUpe3RyeXtPYmplY3QuZGVmaW5lUHJvcGVydHkodCxuLHt2YWx1ZTplLHdyaXRhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMH0pfWNhdGNoKGUpe2QmJncubG9nKGBGYWlsZWQgdG8gYWRkIG5vbi1lbnVtZXJhYmxlIHByb3BlcnR5ICIke259IiB0byBvYmplY3RgLHQpfX0odCxYLG4pOmRlbGV0ZSB0W1hdfWZ1bmN0aW9uIG50KHQpe3JldHVybiB0W1hdfWNsYXNzIGV0e2NvbnN0cnVjdG9yKCl7dGhpcy5wPSExLHRoaXMubD1bXSx0aGlzLm09W10sdGhpcy5fPVtdLHRoaXMudj1bXSx0aGlzLlM9e30sdGhpcy5OPXt9LHRoaXMuVD17fSx0aGlzLmo9e30sdGhpcy5DPXt9LHRoaXMuTz17dHJhY2VJZDpaKCksc2FtcGxlUmFuZDpNYXRoLnJhbmRvbSgpfX1jbG9uZSgpe2NvbnN0IHQ9bmV3IGV0O3JldHVybiB0Ll89Wy4uLnRoaXMuX10sdC5OPXsuLi50aGlzLk59LHQuVD17Li4udGhpcy5UfSx0Lmo9ey4uLnRoaXMuan0sdGhpcy5qLmZsYWdzJiYodC5qLmZsYWdzPXt2YWx1ZXM6Wy4uLnRoaXMuai5mbGFncy52YWx1ZXNdfSksdC5TPXRoaXMuUyx0LlI9dGhpcy5SLHQuRD10aGlzLkQsdC5rPXRoaXMuayx0LkE9dGhpcy5BLHQubT1bLi4udGhpcy5tXSx0LnY9Wy4uLnRoaXMudl0sdC5DPXsuLi50aGlzLkN9LHQuTz17Li4udGhpcy5PfSx0Lkk9dGhpcy5JLHQuUD10aGlzLlAsdHQodCxudCh0aGlzKSksdH1zZXRDbGllbnQodCl7dGhpcy5JPXR9c2V0TGFzdEV2ZW50SWQodCl7dGhpcy5QPXR9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuSX1sYXN0RXZlbnRJZCgpe3JldHVybiB0aGlzLlB9YWRkU2NvcGVMaXN0ZW5lcih0KXt0aGlzLmwucHVzaCh0KX1hZGRFdmVudFByb2Nlc3Nvcih0KXtyZXR1cm4gdGhpcy5tLnB1c2godCksdGhpc31zZXRVc2VyKHQpe3JldHVybiB0aGlzLlM9dHx8e2VtYWlsOnZvaWQgMCxpZDp2b2lkIDAsaXBfYWRkcmVzczp2b2lkIDAsdXNlcm5hbWU6dm9pZCAwfSx0aGlzLkQmJlYodGhpcy5ELHt1c2VyOnR9KSx0aGlzLlUoKSx0aGlzfWdldFVzZXIoKXtyZXR1cm4gdGhpcy5TfXNldFRhZ3ModCl7cmV0dXJuIHRoaXMuTj17Li4udGhpcy5OLC4uLnR9LHRoaXMuVSgpLHRoaXN9c2V0VGFnKHQsbil7cmV0dXJuIHRoaXMuTj17Li4udGhpcy5OLFt0XTpufSx0aGlzLlUoKSx0aGlzfXNldEV4dHJhcyh0KXtyZXR1cm4gdGhpcy5UPXsuLi50aGlzLlQsLi4udH0sdGhpcy5VKCksdGhpc31zZXRFeHRyYSh0LG4pe3JldHVybiB0aGlzLlQ9ey4uLnRoaXMuVCxbdF06bn0sdGhpcy5VKCksdGhpc31zZXRGaW5nZXJwcmludCh0KXtyZXR1cm4gdGhpcy5BPXQsdGhpcy5VKCksdGhpc31zZXRMZXZlbCh0KXtyZXR1cm4gdGhpcy5SPXQsdGhpcy5VKCksdGhpc31zZXRUcmFuc2FjdGlvbk5hbWUodCl7cmV0dXJuIHRoaXMuaz10LHRoaXMuVSgpLHRoaXN9c2V0Q29udGV4dCh0LG4pe3JldHVybiBudWxsPT09bj9kZWxldGUgdGhpcy5qW3RdOnRoaXMualt0XT1uLHRoaXMuVSgpLHRoaXN9c2V0U2Vzc2lvbih0KXtyZXR1cm4gdD90aGlzLkQ9dDpkZWxldGUgdGhpcy5ELHRoaXMuVSgpLHRoaXN9Z2V0U2Vzc2lvbigpe3JldHVybiB0aGlzLkR9dXBkYXRlKHQpe2lmKCF0KXJldHVybiB0aGlzO2NvbnN0IG49ImZ1bmN0aW9uIj09dHlwZW9mIHQ/dCh0aGlzKTp0LGU9biBpbnN0YW5jZW9mIGV0P24uZ2V0U2NvcGVEYXRhKCk6TyhuKT90OnZvaWQgMCx7dGFnczpyLGV4dHJhOm8sdXNlcjpzLGNvbnRleHRzOmksbGV2ZWw6YyxmaW5nZXJwcmludDp1PVtdLHByb3BhZ2F0aW9uQ29udGV4dDphfT1lfHx7fTtyZXR1cm4gdGhpcy5OPXsuLi50aGlzLk4sLi4ucn0sdGhpcy5UPXsuLi50aGlzLlQsLi4ub30sdGhpcy5qPXsuLi50aGlzLmosLi4uaX0scyYmT2JqZWN0LmtleXMocykubGVuZ3RoJiYodGhpcy5TPXMpLGMmJih0aGlzLlI9YyksdS5sZW5ndGgmJih0aGlzLkE9dSksYSYmKHRoaXMuTz1hKSx0aGlzfWNsZWFyKCl7cmV0dXJuIHRoaXMuXz1bXSx0aGlzLk49e30sdGhpcy5UPXt9LHRoaXMuUz17fSx0aGlzLmo9e30sdGhpcy5SPXZvaWQgMCx0aGlzLms9dm9pZCAwLHRoaXMuQT12b2lkIDAsdGhpcy5EPXZvaWQgMCx0dCh0aGlzLHZvaWQgMCksdGhpcy52PVtdLHRoaXMuc2V0UHJvcGFnYXRpb25Db250ZXh0KHt0cmFjZUlkOlooKSxzYW1wbGVSYW5kOk1hdGgucmFuZG9tKCl9KSx0aGlzLlUoKSx0aGlzfWFkZEJyZWFkY3J1bWIodCxuKXtjb25zdCBlPSJudW1iZXIiPT10eXBlb2Ygbj9uOjEwMDtpZihlPD0wKXJldHVybiB0aGlzO2NvbnN0IHI9e3RpbWVzdGFtcDpKKCksLi4udH0sbz10aGlzLl87cmV0dXJuIG8ucHVzaChyKSx0aGlzLl89by5sZW5ndGg+ZT9vLnNsaWNlKC1lKTpvLHRoaXMuVSgpLHRoaXN9Z2V0TGFzdEJyZWFkY3J1bWIoKXtyZXR1cm4gdGhpcy5fW3RoaXMuXy5sZW5ndGgtMV19Y2xlYXJCcmVhZGNydW1icygpe3JldHVybiB0aGlzLl89W10sdGhpcy5VKCksdGhpc31hZGRBdHRhY2htZW50KHQpe3JldHVybiB0aGlzLnYucHVzaCh0KSx0aGlzfWNsZWFyQXR0YWNobWVudHMoKXtyZXR1cm4gdGhpcy52PVtdLHRoaXN9Z2V0U2NvcGVEYXRhKCl7cmV0dXJue2JyZWFkY3J1bWJzOnRoaXMuXyxhdHRhY2htZW50czp0aGlzLnYsY29udGV4dHM6dGhpcy5qLHRhZ3M6dGhpcy5OLGV4dHJhOnRoaXMuVCx1c2VyOnRoaXMuUyxsZXZlbDp0aGlzLlIsZmluZ2VycHJpbnQ6dGhpcy5BfHxbXSxldmVudFByb2Nlc3NvcnM6dGhpcy5tLHByb3BhZ2F0aW9uQ29udGV4dDp0aGlzLk8sc2RrUHJvY2Vzc2luZ01ldGFkYXRhOnRoaXMuQyx0cmFuc2FjdGlvbk5hbWU6dGhpcy5rLHNwYW46bnQodGhpcyl9fXNldFNES1Byb2Nlc3NpbmdNZXRhZGF0YSh0KXtyZXR1cm4gdGhpcy5DPVEodGhpcy5DLHQsMiksdGhpc31zZXRQcm9wYWdhdGlvbkNvbnRleHQodCl7cmV0dXJuIHRoaXMuTz10LHRoaXN9Z2V0UHJvcGFnYXRpb25Db250ZXh0KCl7cmV0dXJuIHRoaXMuT31jYXB0dXJlRXhjZXB0aW9uKHQsbil7Y29uc3QgZT1uPy5ldmVudF9pZHx8eigpO2lmKCF0aGlzLkkpcmV0dXJuIHcud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIGV4Y2VwdGlvbiEiKSxlO2NvbnN0IHI9bmV3IEVycm9yKCJTZW50cnkgc3ludGhldGljRXhjZXB0aW9uIik7cmV0dXJuIHRoaXMuSS5jYXB0dXJlRXhjZXB0aW9uKHQse29yaWdpbmFsRXhjZXB0aW9uOnQsc3ludGhldGljRXhjZXB0aW9uOnIsLi4ubixldmVudF9pZDplfSx0aGlzKSxlfWNhcHR1cmVNZXNzYWdlKHQsbixlKXtjb25zdCByPWU/LmV2ZW50X2lkfHx6KCk7aWYoIXRoaXMuSSlyZXR1cm4gdy53YXJuKCJObyBjbGllbnQgY29uZmlndXJlZCBvbiBzY29wZSAtIHdpbGwgbm90IGNhcHR1cmUgbWVzc2FnZSEiKSxyO2NvbnN0IG89bmV3IEVycm9yKHQpO3JldHVybiB0aGlzLkkuY2FwdHVyZU1lc3NhZ2UodCxuLHtvcmlnaW5hbEV4Y2VwdGlvbjp0LHN5bnRoZXRpY0V4Y2VwdGlvbjpvLC4uLmUsZXZlbnRfaWQ6cn0sdGhpcykscn1jYXB0dXJlRXZlbnQodCxuKXtjb25zdCBlPW4/LmV2ZW50X2lkfHx6KCk7cmV0dXJuIHRoaXMuST8odGhpcy5JLmNhcHR1cmVFdmVudCh0LHsuLi5uLGV2ZW50X2lkOmV9LHRoaXMpLGUpOih3Lndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBldmVudCEiKSxlKX1VKCl7dGhpcy5wfHwodGhpcy5wPSEwLHRoaXMubC5mb3JFYWNoKCh0PT57dCh0aGlzKX0pKSx0aGlzLnA9ITEpfX1jbGFzcyBydHtjb25zdHJ1Y3Rvcih0LG4pe2xldCBlLHI7ZT10fHxuZXcgZXQscj1ufHxuZXcgZXQsdGhpcy5NPVt7c2NvcGU6ZX1dLHRoaXMuTD1yfXdpdGhTY29wZSh0KXtjb25zdCBuPXRoaXMuQigpO2xldCBlO3RyeXtlPXQobil9Y2F0Y2godCl7dGhyb3cgdGhpcy5HKCksdH1yZXR1cm4gUihlKT9lLnRoZW4oKHQ9Pih0aGlzLkcoKSx0KSksKHQ9Pnt0aHJvdyB0aGlzLkcoKSx0fSkpOih0aGlzLkcoKSxlKX1nZXRDbGllbnQoKXtyZXR1cm4gdGhpcy5nZXRTdGFja1RvcCgpLmNsaWVudH1nZXRTY29wZSgpe3JldHVybiB0aGlzLmdldFN0YWNrVG9wKCkuc2NvcGV9Z2V0SXNvbGF0aW9uU2NvcGUoKXtyZXR1cm4gdGhpcy5MfWdldFN0YWNrVG9wKCl7cmV0dXJuIHRoaXMuTVt0aGlzLk0ubGVuZ3RoLTFdfUIoKXtjb25zdCB0PXRoaXMuZ2V0U2NvcGUoKS5jbG9uZSgpO3JldHVybiB0aGlzLk0ucHVzaCh7Y2xpZW50OnRoaXMuZ2V0Q2xpZW50KCksc2NvcGU6dH0pLHR9Rygpe3JldHVybiEodGhpcy5NLmxlbmd0aDw9MSkmJiEhdGhpcy5NLnBvcCgpfX1mdW5jdGlvbiBvdCgpe2NvbnN0IHQ9ZyhtKCkpO3JldHVybiB0LnN0YWNrPXQuc3RhY2t8fG5ldyBydCh5KCJkZWZhdWx0Q3VycmVudFNjb3BlIiwoKCk9Pm5ldyBldCkpLHkoImRlZmF1bHRJc29sYXRpb25TY29wZSIsKCgpPT5uZXcgZXQpKSl9ZnVuY3Rpb24gc3QodCl7cmV0dXJuIG90KCkud2l0aFNjb3BlKHQpfWZ1bmN0aW9uIGl0KHQsbil7Y29uc3QgZT1vdCgpO3JldHVybiBlLndpdGhTY29wZSgoKCk9PihlLmdldFN0YWNrVG9wKCkuc2NvcGU9dCxuKHQpKSkpfWZ1bmN0aW9uIGN0KHQpe3JldHVybiBvdCgpLndpdGhTY29wZSgoKCk9PnQob3QoKS5nZXRJc29sYXRpb25TY29wZSgpKSkpfWZ1bmN0aW9uIHV0KHQpe2NvbnN0IG49Zyh0KTtyZXR1cm4gbi5hY3M/bi5hY3M6e3dpdGhJc29sYXRpb25TY29wZTpjdCx3aXRoU2NvcGU6c3Qsd2l0aFNldFNjb3BlOml0LHdpdGhTZXRJc29sYXRpb25TY29wZToodCxuKT0+Y3QobiksZ2V0Q3VycmVudFNjb3BlOigpPT5vdCgpLmdldFNjb3BlKCksZ2V0SXNvbGF0aW9uU2NvcGU6KCk9Pm90KCkuZ2V0SXNvbGF0aW9uU2NvcGUoKX19ZnVuY3Rpb24gYXQoKXtyZXR1cm4gdXQobSgpKS5nZXRDdXJyZW50U2NvcGUoKS5nZXRDbGllbnQoKX1jb25zdCBmdD0ic2VudHJ5LnNvdXJjZSIsaHQ9InNlbnRyeS5zYW1wbGVfcmF0ZSIscHQ9InNlbnRyeS5vcCIsZHQ9InNlbnRyeS5vcmlnaW4iLGx0PTAsbXQ9MSxndD0iX3NlbnRyeVNjb3BlIix5dD0iX3NlbnRyeUlzb2xhdGlvblNjb3BlIjtmdW5jdGlvbiBidCh0KXtyZXR1cm57c2NvcGU6dFtndF0saXNvbGF0aW9uU2NvcGU6dFt5dF19fWNvbnN0IF90PSJzZW50cnktIix2dD0vXnNlbnRyeS0vO2Z1bmN0aW9uIHd0KHQpe2NvbnN0IG49ZnVuY3Rpb24odCl7aWYoIXR8fCFDKHQpJiYhQXJyYXkuaXNBcnJheSh0KSlyZXR1cm47aWYoQXJyYXkuaXNBcnJheSh0KSlyZXR1cm4gdC5yZWR1Y2UoKCh0LG4pPT57Y29uc3QgZT1TdChuKTtyZXR1cm4gT2JqZWN0LmVudHJpZXMoZSkuZm9yRWFjaCgoKFtuLGVdKT0+e3Rbbl09ZX0pKSx0fSkse30pO3JldHVybiBTdCh0KX0odCk7aWYoIW4pcmV0dXJuO2NvbnN0IGU9T2JqZWN0LmVudHJpZXMobikucmVkdWNlKCgodCxbbixlXSk9PntpZihuLm1hdGNoKHZ0KSl7dFtuLnNsaWNlKF90Lmxlbmd0aCldPWV9cmV0dXJuIHR9KSx7fSk7cmV0dXJuIE9iamVjdC5rZXlzKGUpLmxlbmd0aD4wP2U6dm9pZCAwfWZ1bmN0aW9uIFN0KHQpe3JldHVybiB0LnNwbGl0KCIsIikubWFwKCh0PT50LnNwbGl0KCI9IikubWFwKCh0PT5kZWNvZGVVUklDb21wb25lbnQodC50cmltKCkpKSkpKS5yZWR1Y2UoKCh0LFtuLGVdKT0+KG4mJmUmJih0W25dPWUpLHQpKSx7fSl9Y29uc3QgJHQ9MTtmdW5jdGlvbiBFdCh0KXtjb25zdHtzcGFuSWQ6bix0cmFjZUlkOmUsaXNSZW1vdGU6cn09dC5zcGFuQ29udGV4dCgpLG89cj9uOlR0KHQpLnBhcmVudF9zcGFuX2lkLHM9YnQodCkuc2NvcGU7cmV0dXJuIEwoe3BhcmVudF9zcGFuX2lkOm8sc3Bhbl9pZDpyP3M/LmdldFByb3BhZ2F0aW9uQ29udGV4dCgpLnByb3BhZ2F0aW9uU3BhbklkfHxxKCk6bix0cmFjZV9pZDplfSl9ZnVuY3Rpb24geHQodCl7cmV0dXJuIm51bWJlciI9PXR5cGVvZiB0P050KHQpOkFycmF5LmlzQXJyYXkodCk/dFswXSt0WzFdLzFlOTp0IGluc3RhbmNlb2YgRGF0ZT9OdCh0LmdldFRpbWUoKSk6WSgpfWZ1bmN0aW9uIE50KHQpe3JldHVybiB0Pjk5OTk5OTk5OTk/dC8xZTM6dH1mdW5jdGlvbiBUdCh0KXtpZihmdW5jdGlvbih0KXtyZXR1cm4iZnVuY3Rpb24iPT10eXBlb2YgdC5nZXRTcGFuSlNPTn0odCkpcmV0dXJuIHQuZ2V0U3BhbkpTT04oKTtjb25zdHtzcGFuSWQ6bix0cmFjZUlkOmV9PXQuc3BhbkNvbnRleHQoKTtpZihmdW5jdGlvbih0KXtjb25zdCBuPXQ7cmV0dXJuISEobi5hdHRyaWJ1dGVzJiZuLnN0YXJ0VGltZSYmbi5uYW1lJiZuLmVuZFRpbWUmJm4uc3RhdHVzKX0odCkpe2NvbnN0e2F0dHJpYnV0ZXM6cixzdGFydFRpbWU6byxuYW1lOnMsZW5kVGltZTppLHBhcmVudFNwYW5JZDpjLHN0YXR1czp1fT10O3JldHVybiBMKHtzcGFuX2lkOm4sdHJhY2VfaWQ6ZSxkYXRhOnIsZGVzY3JpcHRpb246cyxwYXJlbnRfc3Bhbl9pZDpjLHN0YXJ0X3RpbWVzdGFtcDp4dChvKSx0aW1lc3RhbXA6eHQoaSl8fHZvaWQgMCxzdGF0dXM6anQodSksb3A6cltwdF0sb3JpZ2luOnJbZHRdfSl9cmV0dXJue3NwYW5faWQ6bix0cmFjZV9pZDplLHN0YXJ0X3RpbWVzdGFtcDowLGRhdGE6e319fWZ1bmN0aW9uIGp0KHQpe2lmKHQmJnQuY29kZSE9PWx0KXJldHVybiB0LmNvZGU9PT1tdD8ib2siOnQubWVzc2FnZXx8InVua25vd25fZXJyb3IifWNvbnN0IEN0PSJfc2VudHJ5Um9vdFNwYW4iO2Z1bmN0aW9uIE90KHQpe3JldHVybiB0W0N0XXx8dH1jb25zdCBSdD0icHJvZHVjdGlvbiIsRHQ9Il9mcm96ZW5Ec2MiO2Z1bmN0aW9uIGt0KHQpe2NvbnN0IG49YXQoKTtpZighbilyZXR1cm57fTtjb25zdCBlPU90KHQpLHI9VHQoZSksbz1yLmRhdGEscz1lLnNwYW5Db250ZXh0KCkudHJhY2VTdGF0ZSxpPXM/LmdldCgic2VudHJ5LnNhbXBsZV9yYXRlIik/P29baHRdO2Z1bmN0aW9uIGModCl7cmV0dXJuIm51bWJlciIhPXR5cGVvZiBpJiYic3RyaW5nIiE9dHlwZW9mIGl8fCh0LnNhbXBsZV9yYXRlPWAke2l9YCksdH1jb25zdCB1PWVbRHRdO2lmKHUpcmV0dXJuIGModSk7Y29uc3QgYT1zPy5nZXQoInNlbnRyeS5kc2MiKSxmPWEmJnd0KGEpO2lmKGYpcmV0dXJuIGMoZik7Y29uc3QgaD1mdW5jdGlvbih0LG4pe2NvbnN0IGU9bi5nZXRPcHRpb25zKCkse3B1YmxpY0tleTpyfT1uLmdldERzbigpfHx7fSxvPUwoe2Vudmlyb25tZW50OmUuZW52aXJvbm1lbnR8fFJ0LHJlbGVhc2U6ZS5yZWxlYXNlLHB1YmxpY19rZXk6cix0cmFjZV9pZDp0fSk7cmV0dXJuIG4uZW1pdCgiY3JlYXRlRHNjIixvKSxvfSh0LnNwYW5Db250ZXh0KCkudHJhY2VJZCxuKSxwPW9bZnRdLGQ9ci5kZXNjcmlwdGlvbjtyZXR1cm4idXJsIiE9PXAmJmQmJihoLnRyYW5zYWN0aW9uPWQpLGZ1bmN0aW9uKHQpe2lmKCJib29sZWFuIj09dHlwZW9mIF9fU0VOVFJZX1RSQUNJTkdfXyYmIV9fU0VOVFJZX1RSQUNJTkdfXylyZXR1cm4hMTtjb25zdCBuPWF0KCksZT1uPy5nZXRPcHRpb25zKCk7cmV0dXJuISghZXx8bnVsbD09ZS50cmFjZXNTYW1wbGVSYXRlJiYhZS50cmFjZXNTYW1wbGVyKX0oKSYmKGguc2FtcGxlZD1TdHJpbmcoZnVuY3Rpb24odCl7Y29uc3R7dHJhY2VGbGFnczpufT10LnNwYW5Db250ZXh0KCk7cmV0dXJuIG49PT0kdH0oZSkpLGguc2FtcGxlX3JhbmQ9cz8uZ2V0KCJzZW50cnkuc2FtcGxlX3JhbmQiKT8/YnQoZSkuc2NvcGU/LmdldFByb3BhZ2F0aW9uQ29udGV4dCgpLnNhbXBsZVJhbmQudG9TdHJpbmcoKSksYyhoKSxuLmVtaXQoImNyZWF0ZURzYyIsaCxlKSxofWZ1bmN0aW9uIEF0KHQsbj0hMSl7Y29uc3R7aG9zdDplLHBhdGg6cixwYXNzOm8scG9ydDpzLHByb2plY3RJZDppLHByb3RvY29sOmMscHVibGljS2V5OnV9PXQ7cmV0dXJuYCR7Y306Ly8ke3V9JHtuJiZvP2A6JHtvfWA6IiJ9QCR7ZX0ke3M/YDoke3N9YDoiIn0vJHtyP2Ake3J9L2A6cn0ke2l9YH1mdW5jdGlvbiBJdCh0LG49MTAwLGU9MS8wKXt0cnl7cmV0dXJuIFB0KCIiLHQsbixlKX1jYXRjaCh0KXtyZXR1cm57RVJST1I6YCoqbm9uLXNlcmlhbGl6YWJsZSoqICgke3R9KWB9fX1mdW5jdGlvbiBQdCh0LG4sZT0xLzAscj0xLzAsbz1mdW5jdGlvbigpe2NvbnN0IHQ9bmV3IFdlYWtTZXQ7ZnVuY3Rpb24gbihuKXtyZXR1cm4hIXQuaGFzKG4pfHwodC5hZGQobiksITEpfWZ1bmN0aW9uIGUobil7dC5kZWxldGUobil9cmV0dXJuW24sZV19KCkpe2NvbnN0W3MsaV09bztpZihudWxsPT1ufHxbImJvb2xlYW4iLCJzdHJpbmciXS5pbmNsdWRlcyh0eXBlb2Ygbil8fCJudW1iZXIiPT10eXBlb2YgbiYmTnVtYmVyLmlzRmluaXRlKG4pKXJldHVybiBuO2NvbnN0IGM9ZnVuY3Rpb24odCxuKXt0cnl7aWYoImRvbWFpbiI9PT10JiZuJiYib2JqZWN0Ij09dHlwZW9mIG4mJm4uSilyZXR1cm4iW0RvbWFpbl0iO2lmKCJkb21haW5FbWl0dGVyIj09PXQpcmV0dXJuIltEb21haW5FbWl0dGVyXSI7aWYoInVuZGVmaW5lZCIhPXR5cGVvZiBnbG9iYWwmJm49PT1nbG9iYWwpcmV0dXJuIltHbG9iYWxdIjtpZigidW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdyYmbj09PXdpbmRvdylyZXR1cm4iW1dpbmRvd10iO2lmKCJ1bmRlZmluZWQiIT10eXBlb2YgZG9jdW1lbnQmJm49PT1kb2N1bWVudClyZXR1cm4iW0RvY3VtZW50XSI7aWYoIm9iamVjdCI9PXR5cGVvZihlPW4pJiZudWxsIT09ZSYmKGUuX19pc1Z1ZXx8ZS5ZKSlyZXR1cm4iW1Z1ZVZpZXdNb2RlbF0iO2lmKGZ1bmN0aW9uKHQpe3JldHVybiBPKHQpJiYibmF0aXZlRXZlbnQiaW4gdCYmInByZXZlbnREZWZhdWx0ImluIHQmJiJzdG9wUHJvcGFnYXRpb24iaW4gdH0obikpcmV0dXJuIltTeW50aGV0aWNFdmVudF0iO2lmKCJudW1iZXIiPT10eXBlb2YgbiYmIU51bWJlci5pc0Zpbml0ZShuKSlyZXR1cm5gWyR7bn1dYDtpZigiZnVuY3Rpb24iPT10eXBlb2YgbilyZXR1cm5gW0Z1bmN0aW9uOiAke2Z1bmN0aW9uKHQpe3RyeXtyZXR1cm4gdCYmImZ1bmN0aW9uIj09dHlwZW9mIHQmJnQubmFtZXx8Tn1jYXRjaCh0KXtyZXR1cm4gTn19KG4pfV1gO2lmKCJzeW1ib2wiPT10eXBlb2YgbilyZXR1cm5gWyR7U3RyaW5nKG4pfV1gO2lmKCJiaWdpbnQiPT10eXBlb2YgbilyZXR1cm5gW0JpZ0ludDogJHtTdHJpbmcobil9XWA7Y29uc3Qgcj1mdW5jdGlvbih0KXtjb25zdCBuPU9iamVjdC5nZXRQcm90b3R5cGVPZih0KTtyZXR1cm4gbj9uLmNvbnN0cnVjdG9yLm5hbWU6Im51bGwgcHJvdG90eXBlIn0obik7cmV0dXJuL15IVE1MKFx3KilFbGVtZW50JC8udGVzdChyKT9gW0hUTUxFbGVtZW50OiAke3J9XWA6YFtvYmplY3QgJHtyfV1gfWNhdGNoKHQpe3JldHVybmAqKm5vbi1zZXJpYWxpemFibGUqKiAoJHt0fSlgfXZhciBlfSh0LG4pO2lmKCFjLnN0YXJ0c1dpdGgoIltvYmplY3QgIikpcmV0dXJuIGM7aWYobi5fX3NlbnRyeV9za2lwX25vcm1hbGl6YXRpb25fXylyZXR1cm4gbjtjb25zdCB1PSJudW1iZXIiPT10eXBlb2Ygbi5fX3NlbnRyeV9vdmVycmlkZV9ub3JtYWxpemF0aW9uX2RlcHRoX18/bi5fX3NlbnRyeV9vdmVycmlkZV9ub3JtYWxpemF0aW9uX2RlcHRoX186ZTtpZigwPT09dSlyZXR1cm4gYy5yZXBsYWNlKCJvYmplY3QgIiwiIik7aWYocyhuKSlyZXR1cm4iW0NpcmN1bGFyIH5dIjtjb25zdCBhPW47aWYoYSYmImZ1bmN0aW9uIj09dHlwZW9mIGEudG9KU09OKXRyeXtyZXR1cm4gUHQoIiIsYS50b0pTT04oKSx1LTEscixvKX1jYXRjaCh0KXt9Y29uc3QgZj1BcnJheS5pc0FycmF5KG4pP1tdOnt9O2xldCBoPTA7Y29uc3QgcD1QKG4pO2Zvcihjb25zdCB0IGluIHApe2lmKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocCx0KSljb250aW51ZTtpZihoPj1yKXtmW3RdPSJbTWF4UHJvcGVydGllcyB+XSI7YnJlYWt9Y29uc3Qgbj1wW3RdO2ZbdF09UHQodCxuLHUtMSxyLG8pLGgrK31yZXR1cm4gaShuKSxmfWZ1bmN0aW9uIFV0KHQsbil7Y29uc3QgZT1uLnJlcGxhY2UoL1xcL2csIi8iKS5yZXBsYWNlKC9bfFxce30oKVtcXV4kKyo/Ll0vZywiXFwkJiIpO2xldCByPXQ7dHJ5e3I9ZGVjb2RlVVJJKHQpfWNhdGNoKHQpe31yZXR1cm4gci5yZXBsYWNlKC9cXC9nLCIvIikucmVwbGFjZSgvd2VicGFjazpcLz8vZywiIikucmVwbGFjZShuZXcgUmVnRXhwKGAoZmlsZTovLyk/Lyoke2V9LypgLCJpZyIpLCJhcHA6Ly8vIil9ZnVuY3Rpb24gTXQodCxuPVtdKXtyZXR1cm5bdCxuXX1mdW5jdGlvbiBMdCh0LG4pe2NvbnN0IGU9dFsxXTtmb3IoY29uc3QgdCBvZiBlKXtpZihuKHQsdFswXS50eXBlKSlyZXR1cm4hMH1yZXR1cm4hMX1mdW5jdGlvbiBCdCh0KXtjb25zdCBuPWcocCk7cmV0dXJuIG4uZW5jb2RlUG9seWZpbGw/bi5lbmNvZGVQb2x5ZmlsbCh0KToobmV3IFRleHRFbmNvZGVyKS5lbmNvZGUodCl9ZnVuY3Rpb24gR3QodCl7Y29uc3RbbixlXT10O2xldCByPUpTT04uc3RyaW5naWZ5KG4pO2Z1bmN0aW9uIG8odCl7InN0cmluZyI9PXR5cGVvZiByP3I9InN0cmluZyI9PXR5cGVvZiB0P3IrdDpbQnQociksdF06ci5wdXNoKCJzdHJpbmciPT10eXBlb2YgdD9CdCh0KTp0KX1mb3IoY29uc3QgdCBvZiBlKXtjb25zdFtuLGVdPXQ7aWYobyhgXG4ke0pTT04uc3RyaW5naWZ5KG4pfVxuYCksInN0cmluZyI9PXR5cGVvZiBlfHxlIGluc3RhbmNlb2YgVWludDhBcnJheSlvKGUpO2Vsc2V7bGV0IHQ7dHJ5e3Q9SlNPTi5zdHJpbmdpZnkoZSl9Y2F0Y2gobil7dD1KU09OLnN0cmluZ2lmeShJdChlKSl9byh0KX19cmV0dXJuInN0cmluZyI9PXR5cGVvZiByP3I6ZnVuY3Rpb24odCl7Y29uc3Qgbj10LnJlZHVjZSgoKHQsbik9PnQrbi5sZW5ndGgpLDApLGU9bmV3IFVpbnQ4QXJyYXkobik7bGV0IHI9MDtmb3IoY29uc3QgbiBvZiB0KWUuc2V0KG4scikscis9bi5sZW5ndGg7cmV0dXJuIGV9KHIpfWNvbnN0IEp0PXtzZXNzaW9uOiJzZXNzaW9uIixzZXNzaW9uczoic2Vzc2lvbiIsYXR0YWNobWVudDoiYXR0YWNobWVudCIsdHJhbnNhY3Rpb246InRyYW5zYWN0aW9uIixldmVudDoiZXJyb3IiLGNsaWVudF9yZXBvcnQ6ImludGVybmFsIix1c2VyX3JlcG9ydDoiZGVmYXVsdCIscHJvZmlsZToicHJvZmlsZSIscHJvZmlsZV9jaHVuazoicHJvZmlsZSIscmVwbGF5X2V2ZW50OiJyZXBsYXkiLHJlcGxheV9yZWNvcmRpbmc6InJlcGxheSIsY2hlY2tfaW46Im1vbml0b3IiLGZlZWRiYWNrOiJmZWVkYmFjayIsc3Bhbjoic3BhbiIscmF3X3NlY3VyaXR5OiJzZWN1cml0eSJ9O2Z1bmN0aW9uIFl0KHQpe2lmKCF0Py5zZGspcmV0dXJuO2NvbnN0e25hbWU6bix2ZXJzaW9uOmV9PXQuc2RrO3JldHVybntuYW1lOm4sdmVyc2lvbjplfX1mdW5jdGlvbiB6dCh0LG4sZSxyKXtjb25zdCBvPVl0KGUpLHM9dC50eXBlJiYicmVwbGF5X2V2ZW50IiE9PXQudHlwZT90LnR5cGU6ImV2ZW50IjshZnVuY3Rpb24odCxuKXtuJiYodC5zZGs9dC5zZGt8fHt9LHQuc2RrLm5hbWU9dC5zZGsubmFtZXx8bi5uYW1lLHQuc2RrLnZlcnNpb249dC5zZGsudmVyc2lvbnx8bi52ZXJzaW9uLHQuc2RrLmludGVncmF0aW9ucz1bLi4udC5zZGsuaW50ZWdyYXRpb25zfHxbXSwuLi5uLmludGVncmF0aW9uc3x8W11dLHQuc2RrLnBhY2thZ2VzPVsuLi50LnNkay5wYWNrYWdlc3x8W10sLi4ubi5wYWNrYWdlc3x8W11dKX0odCxlPy5zZGspO2NvbnN0IGk9ZnVuY3Rpb24odCxuLGUscil7Y29uc3Qgbz10LnNka1Byb2Nlc3NpbmdNZXRhZGF0YT8uZHluYW1pY1NhbXBsaW5nQ29udGV4dDtyZXR1cm57ZXZlbnRfaWQ6dC5ldmVudF9pZCxzZW50X2F0OihuZXcgRGF0ZSkudG9JU09TdHJpbmcoKSwuLi5uJiZ7c2RrOm59LC4uLiEhZSYmciYme2RzbjpBdChyKX0sLi4ubyYme3RyYWNlOkwoey4uLm99KX19fSh0LG8scixuKTtkZWxldGUgdC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE7cmV0dXJuIE10KGksW1t7dHlwZTpzfSx0XV0pfWNvbnN0IEh0PSJfX1NFTlRSWV9TVVBQUkVTU19UUkFDSU5HX18iO2Z1bmN0aW9uIFd0KHQpe2NvbnN0IG49dXQobSgpKTtyZXR1cm4gbi5zdXBwcmVzc1RyYWNpbmc/bi5zdXBwcmVzc1RyYWNpbmcodCk6ZnVuY3Rpb24oLi4udCl7Y29uc3Qgbj11dChtKCkpO2lmKDI9PT10Lmxlbmd0aCl7Y29uc3RbZSxyXT10O3JldHVybiBlP24ud2l0aFNldFNjb3BlKGUscik6bi53aXRoU2NvcGUocil9cmV0dXJuIG4ud2l0aFNjb3BlKHRbMF0pfSgobj0+KG4uc2V0U0RLUHJvY2Vzc2luZ01ldGFkYXRhKHtbSHRdOiEwfSksdCgpKSkpfWZ1bmN0aW9uIEZ0KHQsbil7Y29uc3R7ZmluZ2VycHJpbnQ6ZSxzcGFuOnIsYnJlYWRjcnVtYnM6byxzZGtQcm9jZXNzaW5nTWV0YWRhdGE6c309bjshZnVuY3Rpb24odCxuKXtjb25zdHtleHRyYTplLHRhZ3M6cix1c2VyOm8sY29udGV4dHM6cyxsZXZlbDppLHRyYW5zYWN0aW9uTmFtZTpjfT1uLHU9TChlKTtPYmplY3Qua2V5cyh1KS5sZW5ndGgmJih0LmV4dHJhPXsuLi51LC4uLnQuZXh0cmF9KTtjb25zdCBhPUwocik7T2JqZWN0LmtleXMoYSkubGVuZ3RoJiYodC50YWdzPXsuLi5hLC4uLnQudGFnc30pO2NvbnN0IGY9TChvKTtPYmplY3Qua2V5cyhmKS5sZW5ndGgmJih0LnVzZXI9ey4uLmYsLi4udC51c2VyfSk7Y29uc3QgaD1MKHMpO09iamVjdC5rZXlzKGgpLmxlbmd0aCYmKHQuY29udGV4dHM9ey4uLmgsLi4udC5jb250ZXh0c30pO2kmJih0LmxldmVsPWkpO2MmJiJ0cmFuc2FjdGlvbiIhPT10LnR5cGUmJih0LnRyYW5zYWN0aW9uPWMpfSh0LG4pLHImJmZ1bmN0aW9uKHQsbil7dC5jb250ZXh0cz17dHJhY2U6RXQobiksLi4udC5jb250ZXh0c30sdC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE9e2R5bmFtaWNTYW1wbGluZ0NvbnRleHQ6a3QobiksLi4udC5zZGtQcm9jZXNzaW5nTWV0YWRhdGF9O2NvbnN0IGU9T3Qobikscj1UdChlKS5kZXNjcmlwdGlvbjtyJiYhdC50cmFuc2FjdGlvbiYmInRyYW5zYWN0aW9uIj09PXQudHlwZSYmKHQudHJhbnNhY3Rpb249cil9KHQsciksZnVuY3Rpb24odCxuKXt0LmZpbmdlcnByaW50PXQuZmluZ2VycHJpbnQ/QXJyYXkuaXNBcnJheSh0LmZpbmdlcnByaW50KT90LmZpbmdlcnByaW50Olt0LmZpbmdlcnByaW50XTpbXSxuJiYodC5maW5nZXJwcmludD10LmZpbmdlcnByaW50LmNvbmNhdChuKSk7dC5maW5nZXJwcmludC5sZW5ndGh8fGRlbGV0ZSB0LmZpbmdlcnByaW50fSh0LGUpLGZ1bmN0aW9uKHQsbil7Y29uc3QgZT1bLi4udC5icmVhZGNydW1ic3x8W10sLi4ubl07dC5icmVhZGNydW1icz1lLmxlbmd0aD9lOnZvaWQgMH0odCxvKSxmdW5jdGlvbih0LG4pe3Quc2RrUHJvY2Vzc2luZ01ldGFkYXRhPXsuLi50LnNka1Byb2Nlc3NpbmdNZXRhZGF0YSwuLi5ufX0odCxzKX1jb25zdCBLdD0iNyI7Y2xhc3MgVnQgZXh0ZW5kcyBFcnJvcntjb25zdHJ1Y3Rvcih0LG49Indhcm4iKXtzdXBlcih0KSx0aGlzLm1lc3NhZ2U9dCx0aGlzLm5hbWU9bmV3LnRhcmdldC5wcm90b3R5cGUuY29uc3RydWN0b3IubmFtZSxPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcyxuZXcudGFyZ2V0LnByb3RvdHlwZSksdGhpcy5sb2dMZXZlbD1ufX1mdW5jdGlvbiBadCh0KXtjb25zdCBuPVtdO2Z1bmN0aW9uIGUodCl7cmV0dXJuIG4uc3BsaWNlKG4uaW5kZXhPZih0KSwxKVswXXx8UHJvbWlzZS5yZXNvbHZlKHZvaWQgMCl9cmV0dXJueyQ6bixhZGQ6ZnVuY3Rpb24ocil7aWYoISh2b2lkIDA9PT10fHxuLmxlbmd0aDx0KSlyZXR1cm4gbz1uZXcgVnQoIk5vdCBhZGRpbmcgUHJvbWlzZSBiZWNhdXNlIGJ1ZmZlciBsaW1pdCB3YXMgcmVhY2hlZC4iKSxuZXcgRigoKHQsbik9PntuKG8pfSkpO3ZhciBvO2NvbnN0IHM9cigpO3JldHVybi0xPT09bi5pbmRleE9mKHMpJiZuLnB1c2gocykscy50aGVuKCgoKT0+ZShzKSkpLnRoZW4obnVsbCwoKCk9PmUocykudGhlbihudWxsLCgoKT0+e30pKSkpLHN9LGRyYWluOmZ1bmN0aW9uKHQpe3JldHVybiBuZXcgRigoKGUscik9PntsZXQgbz1uLmxlbmd0aDtpZighbylyZXR1cm4gZSghMCk7Y29uc3Qgcz1zZXRUaW1lb3V0KCgoKT0+e3QmJnQ+MCYmZSghMSl9KSx0KTtuLmZvckVhY2goKHQ9PntXKHQpLnRoZW4oKCgpPT57LS1vfHwoY2xlYXJUaW1lb3V0KHMpLGUoITApKX0pLHIpfSkpfSkpfX19Y29uc3QgcXQ9NmU0O2Z1bmN0aW9uIFF0KHQse3N0YXR1c0NvZGU6bixoZWFkZXJzOmV9LHI9RGF0ZS5ub3coKSl7Y29uc3Qgbz17Li4udH0scz1lPy5bIngtc2VudHJ5LXJhdGUtbGltaXRzIl0saT1lPy5bInJldHJ5LWFmdGVyIl07aWYocylmb3IoY29uc3QgdCBvZiBzLnRyaW0oKS5zcGxpdCgiLCIpKXtjb25zdFtuLGUsLCxzXT10LnNwbGl0KCI6Iiw1KSxpPXBhcnNlSW50KG4sMTApLGM9MWUzKihpc05hTihpKT82MDppKTtpZihlKWZvcihjb25zdCB0IG9mIGUuc3BsaXQoIjsiKSkibWV0cmljX2J1Y2tldCI9PT10JiZzJiYhcy5zcGxpdCgiOyIpLmluY2x1ZGVzKCJjdXN0b20iKXx8KG9bdF09citjKTtlbHNlIG8uYWxsPXIrY31lbHNlIGk/by5hbGw9citmdW5jdGlvbih0LG49RGF0ZS5ub3coKSl7Y29uc3QgZT1wYXJzZUludChgJHt0fWAsMTApO2lmKCFpc05hTihlKSlyZXR1cm4gMWUzKmU7Y29uc3Qgcj1EYXRlLnBhcnNlKGAke3R9YCk7cmV0dXJuIGlzTmFOKHIpP3F0OnItbn0oaSxyKTo0Mjk9PT1uJiYoby5hbGw9cis2ZTQpO3JldHVybiBvfWNvbnN0IFh0PTY0O2Z1bmN0aW9uIHRuKHQsbixlPVp0KHQuYnVmZmVyU2l6ZXx8WHQpKXtsZXQgcj17fTtyZXR1cm57c2VuZDpmdW5jdGlvbih0KXtjb25zdCBvPVtdO2lmKEx0KHQsKCh0LG4pPT57Y29uc3QgZT1mdW5jdGlvbih0KXtyZXR1cm4gSnRbdF19KG4pOyhmdW5jdGlvbih0LG4sZT1EYXRlLm5vdygpKXtyZXR1cm4gZnVuY3Rpb24odCxuKXtyZXR1cm4gdFtuXXx8dC5hbGx8fDB9KHQsbik+ZX0pKHIsZSl8fG8ucHVzaCh0KX0pKSwwPT09by5sZW5ndGgpcmV0dXJuIFcoe30pO2NvbnN0IHM9TXQodFswXSxvKSxpPXQ9PntMdChzLCgodCxuKT0+e30pKX07cmV0dXJuIGUuYWRkKCgoKT0+bih7Ym9keTpHdChzKX0pLnRoZW4oKHQ9Pih2b2lkIDAhPT10LnN0YXR1c0NvZGUmJih0LnN0YXR1c0NvZGU8MjAwfHx0LnN0YXR1c0NvZGU+PTMwMCkmJmgmJncud2FybihgU2VudHJ5IHJlc3BvbmRlZCB3aXRoIHN0YXR1cyBjb2RlICR7dC5zdGF0dXNDb2RlfSB0byBzZW50IGV2ZW50LmApLHI9UXQocix0KSx0KSksKHQ9Pnt0aHJvdyBpKCksdH0pKSkpLnRoZW4oKHQ9PnQpLCh0PT57aWYodCBpbnN0YW5jZW9mIFZ0KXJldHVybiBoJiZ3LmVycm9yKCJTa2lwcGVkIHNlbmRpbmcgZXZlbnQgYmVjYXVzZSBidWZmZXIgaXMgZnVsbC4iKSxpKCksVyh7fSk7dGhyb3cgdH0pKX0sZmx1c2g6dD0+ZS5kcmFpbih0KX19Y29uc3Qgbm49L14oXFMrOlxcfFwvPykoW1xzXFNdKj8pKCg/OlwuezEsMn18W14vXFxdKz98KShcLlteLi9cXF0qfCkpKD86Wy9cXF0qKSQvO2Z1bmN0aW9uIGVuKHQpe2NvbnN0IG49ZnVuY3Rpb24odCl7Y29uc3Qgbj10Lmxlbmd0aD4xMDI0P2A8dHJ1bmNhdGVkPiR7dC5zbGljZSgtMTAyNCl9YDp0LGU9bm4uZXhlYyhuKTtyZXR1cm4gZT9lLnNsaWNlKDEpOltdfSh0KSxlPW5bMF18fCIiO2xldCByPW5bMV07cmV0dXJuIGV8fHI/KHImJihyPXIuc2xpY2UoMCxyLmxlbmd0aC0xKSksZStyKToiLiJ9ZnVuY3Rpb24gcm4odCxuPSExKXtyZXR1cm4hKG58fHQmJiF0LnN0YXJ0c1dpdGgoIi8iKSYmIXQubWF0Y2goL15bQS1aXTovKSYmIXQuc3RhcnRzV2l0aCgiLiIpJiYhdC5tYXRjaCgvXlthLXpBLVpdKFthLXpBLVowLTkuXC0rXSkqOlwvXC8vKSkmJnZvaWQgMCE9PXQmJiF0LmluY2x1ZGVzKCJub2RlX21vZHVsZXMvIil9Y29uc3Qgb249U3ltYm9sKCJBZ2VudEJhc2VJbnRlcm5hbFN0YXRlIik7Y2xhc3Mgc24gZXh0ZW5kcyBzLkFnZW50e2NvbnN0cnVjdG9yKHQpe3N1cGVyKHQpLHRoaXNbb25dPXt9fWlzU2VjdXJlRW5kcG9pbnQodCl7aWYodCl7aWYoImJvb2xlYW4iPT10eXBlb2YgdC5zZWN1cmVFbmRwb2ludClyZXR1cm4gdC5zZWN1cmVFbmRwb2ludDtpZigic3RyaW5nIj09dHlwZW9mIHQucHJvdG9jb2wpcmV0dXJuImh0dHBzOiI9PT10LnByb3RvY29sfWNvbnN0e3N0YWNrOm59PW5ldyBFcnJvcjtyZXR1cm4ic3RyaW5nIj09dHlwZW9mIG4mJm4uc3BsaXQoIlxuIikuc29tZSgodD0+LTEhPT10LmluZGV4T2YoIihodHRwcy5qczoiKXx8LTEhPT10LmluZGV4T2YoIm5vZGU6aHR0cHM6IikpKX1jcmVhdGVTb2NrZXQodCxuLGUpe2NvbnN0IHI9ey4uLm4sc2VjdXJlRW5kcG9pbnQ6dGhpcy5pc1NlY3VyZUVuZHBvaW50KG4pfTtQcm9taXNlLnJlc29sdmUoKS50aGVuKCgoKT0+dGhpcy5jb25uZWN0KHQscikpKS50aGVuKChvPT57aWYobyBpbnN0YW5jZW9mIHMuQWdlbnQpcmV0dXJuIG8uYWRkUmVxdWVzdCh0LHIpO3RoaXNbb25dLmN1cnJlbnRTb2NrZXQ9byxzdXBlci5jcmVhdGVTb2NrZXQodCxuLGUpfSksZSl9Y3JlYXRlQ29ubmVjdGlvbigpe2NvbnN0IHQ9dGhpc1tvbl0uY3VycmVudFNvY2tldDtpZih0aGlzW29uXS5jdXJyZW50U29ja2V0PXZvaWQgMCwhdCl0aHJvdyBuZXcgRXJyb3IoIk5vIHNvY2tldCB3YXMgcmV0dXJuZWQgaW4gdGhlIGBjb25uZWN0KClgIGZ1bmN0aW9uIik7cmV0dXJuIHR9Z2V0IGRlZmF1bHRQb3J0KCl7cmV0dXJuIHRoaXNbb25dLmRlZmF1bHRQb3J0Pz8oImh0dHBzOiI9PT10aGlzLnByb3RvY29sPzQ0Mzo4MCl9c2V0IGRlZmF1bHRQb3J0KHQpe3RoaXNbb25dJiYodGhpc1tvbl0uZGVmYXVsdFBvcnQ9dCl9Z2V0IHByb3RvY29sKCl7cmV0dXJuIHRoaXNbb25dLnByb3RvY29sPz8odGhpcy5pc1NlY3VyZUVuZHBvaW50KCk/Imh0dHBzOiI6Imh0dHA6Iil9c2V0IHByb3RvY29sKHQpe3RoaXNbb25dJiYodGhpc1tvbl0ucHJvdG9jb2w9dCl9fWZ1bmN0aW9uIGNuKC4uLnQpe3cubG9nKCJbaHR0cHMtcHJveHktYWdlbnQ6cGFyc2UtcHJveHktcmVzcG9uc2VdIiwuLi50KX1mdW5jdGlvbiB1bih0KXtyZXR1cm4gbmV3IFByb21pc2UoKChuLGUpPT57bGV0IHI9MDtjb25zdCBvPVtdO2Z1bmN0aW9uIHMoKXtjb25zdCBjPXQucmVhZCgpO2M/ZnVuY3Rpb24oYyl7by5wdXNoKGMpLHIrPWMubGVuZ3RoO2NvbnN0IHU9QnVmZmVyLmNvbmNhdChvLHIpLGE9dS5pbmRleE9mKCJcclxuXHJcbiIpO2lmKC0xPT09YSlyZXR1cm4gY24oImhhdmUgbm90IHJlY2VpdmVkIGVuZCBvZiBIVFRQIGhlYWRlcnMgeWV0Li4uIiksdm9pZCBzKCk7Y29uc3QgZj11LnN1YmFycmF5KDAsYSkudG9TdHJpbmcoImFzY2lpIikuc3BsaXQoIlxyXG4iKSxoPWYuc2hpZnQoKTtpZighaClyZXR1cm4gdC5kZXN0cm95KCksZShuZXcgRXJyb3IoIk5vIGhlYWRlciByZWNlaXZlZCBmcm9tIHByb3h5IENPTk5FQ1QgcmVzcG9uc2UiKSk7Y29uc3QgcD1oLnNwbGl0KCIgIiksZD0rKHBbMV18fDApLGw9cC5zbGljZSgyKS5qb2luKCIgIiksbT17fTtmb3IoY29uc3QgbiBvZiBmKXtpZighbiljb250aW51ZTtjb25zdCByPW4uaW5kZXhPZigiOiIpO2lmKC0xPT09cilyZXR1cm4gdC5kZXN0cm95KCksZShuZXcgRXJyb3IoYEludmFsaWQgaGVhZGVyIGZyb20gcHJveHkgQ09OTkVDVCByZXNwb25zZTogIiR7bn0iYCkpO2NvbnN0IG89bi5zbGljZSgwLHIpLnRvTG93ZXJDYXNlKCkscz1uLnNsaWNlKHIrMSkudHJpbVN0YXJ0KCksaT1tW29dOyJzdHJpbmciPT10eXBlb2YgaT9tW29dPVtpLHNdOkFycmF5LmlzQXJyYXkoaSk/aS5wdXNoKHMpOm1bb109c31jbigiZ290IHByb3h5IHNlcnZlciByZXNwb25zZTogJW8gJW8iLGgsbSksaSgpLG4oe2Nvbm5lY3Q6e3N0YXR1c0NvZGU6ZCxzdGF0dXNUZXh0OmwsaGVhZGVyczptfSxidWZmZXJlZDp1fSl9KGMpOnQub25jZSgicmVhZGFibGUiLHMpfWZ1bmN0aW9uIGkoKXt0LnJlbW92ZUxpc3RlbmVyKCJlbmQiLGMpLHQucmVtb3ZlTGlzdGVuZXIoImVycm9yIix1KSx0LnJlbW92ZUxpc3RlbmVyKCJyZWFkYWJsZSIscyl9ZnVuY3Rpb24gYygpe2koKSxjbigib25lbmQiKSxlKG5ldyBFcnJvcigiUHJveHkgY29ubmVjdGlvbiBlbmRlZCBiZWZvcmUgcmVjZWl2aW5nIENPTk5FQ1QgcmVzcG9uc2UiKSl9ZnVuY3Rpb24gdSh0KXtpKCksY24oIm9uZXJyb3IgJW8iLHQpLGUodCl9dC5vbigiZXJyb3IiLHUpLHQub24oImVuZCIsYykscygpfSkpfWZ1bmN0aW9uIGFuKC4uLnQpe3cubG9nKCJbaHR0cHMtcHJveHktYWdlbnRdIiwuLi50KX1jbGFzcyBmbiBleHRlbmRzIHNue3N0YXRpYyBfX2luaXRTdGF0aWMoKXt0aGlzLnByb3RvY29scz1bImh0dHAiLCJodHRwcyJdfWNvbnN0cnVjdG9yKHQsbil7c3VwZXIobiksdGhpcy5vcHRpb25zPXt9LHRoaXMucHJveHk9InN0cmluZyI9PXR5cGVvZiB0P25ldyBVUkwodCk6dCx0aGlzLnByb3h5SGVhZGVycz1uPy5oZWFkZXJzPz97fSxhbigiQ3JlYXRpbmcgbmV3IEh0dHBzUHJveHlBZ2VudCBpbnN0YW5jZTogJW8iLHRoaXMucHJveHkuaHJlZik7Y29uc3QgZT0odGhpcy5wcm94eS5ob3N0bmFtZXx8dGhpcy5wcm94eS5ob3N0KS5yZXBsYWNlKC9eXFt8XF0kL2csIiIpLHI9dGhpcy5wcm94eS5wb3J0P3BhcnNlSW50KHRoaXMucHJveHkucG9ydCwxMCk6Imh0dHBzOiI9PT10aGlzLnByb3h5LnByb3RvY29sPzQ0Mzo4MDt0aGlzLmNvbm5lY3RPcHRzPXtBTFBOUHJvdG9jb2xzOlsiaHR0cC8xLjEiXSwuLi5uP3BuKG4sImhlYWRlcnMiKTpudWxsLGhvc3Q6ZSxwb3J0OnJ9fWFzeW5jIGNvbm5lY3QodCxuKXtjb25zdHtwcm94eTplfT10aGlzO2lmKCFuLmhvc3QpdGhyb3cgbmV3IFR5cGVFcnJvcignTm8gImhvc3QiIHByb3ZpZGVkJyk7bGV0IHI7aWYoImh0dHBzOiI9PT1lLnByb3RvY29sKXthbigiQ3JlYXRpbmcgYHRscy5Tb2NrZXRgOiAlbyIsdGhpcy5jb25uZWN0T3B0cyk7Y29uc3QgdD10aGlzLmNvbm5lY3RPcHRzLnNlcnZlcm5hbWV8fHRoaXMuY29ubmVjdE9wdHMuaG9zdDtyPWYuY29ubmVjdCh7Li4udGhpcy5jb25uZWN0T3B0cyxzZXJ2ZXJuYW1lOnQmJmEuaXNJUCh0KT92b2lkIDA6dH0pfWVsc2UgYW4oIkNyZWF0aW5nIGBuZXQuU29ja2V0YDogJW8iLHRoaXMuY29ubmVjdE9wdHMpLHI9YS5jb25uZWN0KHRoaXMuY29ubmVjdE9wdHMpO2NvbnN0IG89ImZ1bmN0aW9uIj09dHlwZW9mIHRoaXMucHJveHlIZWFkZXJzP3RoaXMucHJveHlIZWFkZXJzKCk6ey4uLnRoaXMucHJveHlIZWFkZXJzfSxzPWEuaXNJUHY2KG4uaG9zdCk/YFske24uaG9zdH1dYDpuLmhvc3Q7bGV0IGk9YENPTk5FQ1QgJHtzfToke24ucG9ydH0gSFRUUC8xLjFcclxuYDtpZihlLnVzZXJuYW1lfHxlLnBhc3N3b3JkKXtjb25zdCB0PWAke2RlY29kZVVSSUNvbXBvbmVudChlLnVzZXJuYW1lKX06JHtkZWNvZGVVUklDb21wb25lbnQoZS5wYXNzd29yZCl9YDtvWyJQcm94eS1BdXRob3JpemF0aW9uIl09YEJhc2ljICR7QnVmZmVyLmZyb20odCkudG9TdHJpbmcoImJhc2U2NCIpfWB9by5Ib3N0PWAke3N9OiR7bi5wb3J0fWAsb1siUHJveHktQ29ubmVjdGlvbiJdfHwob1siUHJveHktQ29ubmVjdGlvbiJdPXRoaXMua2VlcEFsaXZlPyJLZWVwLUFsaXZlIjoiY2xvc2UiKTtmb3IoY29uc3QgdCBvZiBPYmplY3Qua2V5cyhvKSlpKz1gJHt0fTogJHtvW3RdfVxyXG5gO2NvbnN0IGM9dW4ocik7ci53cml0ZShgJHtpfVxyXG5gKTtjb25zdHtjb25uZWN0OnUsYnVmZmVyZWQ6aH09YXdhaXQgYztpZih0LmVtaXQoInByb3h5Q29ubmVjdCIsdSksdGhpcy5lbWl0KCJwcm94eUNvbm5lY3QiLHUsdCksMjAwPT09dS5zdGF0dXNDb2RlKXtpZih0Lm9uY2UoInNvY2tldCIsaG4pLG4uc2VjdXJlRW5kcG9pbnQpe2FuKCJVcGdyYWRpbmcgc29ja2V0IGNvbm5lY3Rpb24gdG8gVExTIik7Y29uc3QgdD1uLnNlcnZlcm5hbWV8fG4uaG9zdDtyZXR1cm4gZi5jb25uZWN0KHsuLi5wbihuLCJob3N0IiwicGF0aCIsInBvcnQiKSxzb2NrZXQ6cixzZXJ2ZXJuYW1lOmEuaXNJUCh0KT92b2lkIDA6dH0pfXJldHVybiByfXIuZGVzdHJveSgpO2NvbnN0IHA9bmV3IGEuU29ja2V0KHt3cml0YWJsZTohMX0pO3JldHVybiBwLnJlYWRhYmxlPSEwLHQub25jZSgic29ja2V0IiwodD0+e2FuKCJSZXBsYXlpbmcgcHJveHkgYnVmZmVyIGZvciBmYWlsZWQgcmVxdWVzdCIpLHQucHVzaChoKSx0LnB1c2gobnVsbCl9KSkscH19ZnVuY3Rpb24gaG4odCl7dC5yZXN1bWUoKX1mdW5jdGlvbiBwbih0LC4uLm4pe2NvbnN0IGU9e307bGV0IHI7Zm9yKHIgaW4gdCluLmluY2x1ZGVzKHIpfHwoZVtyXT10W3JdKTtyZXR1cm4gZX1mbi5fX2luaXRTdGF0aWMoKTtjb25zdCBkbj0zMjc2ODtmdW5jdGlvbiBsbih0KXtyZXR1cm4gdC5yZXBsYWNlKC9eW0EtWl06LywiIikucmVwbGFjZSgvXFwvZywiLyIpfWNvbnN0IG1uPWU7bGV0IGduLHluPTAsYm49e307ZnVuY3Rpb24gX24odCl7bW4uZGVidWcmJmNvbnNvbGUubG9nKGBbQU5SIFdvcmtlcl0gJHt0fWApfXZhciB2bix3bixTbjtjb25zdCAkbj1mdW5jdGlvbih0KXtsZXQgbjt0cnl7bj1uZXcgVVJMKHQudXJsKX1jYXRjaChuKXtyZXR1cm4gdigoKCk9Pntjb25zb2xlLndhcm4oIltAc2VudHJ5L25vZGVdOiBJbnZhbGlkIGRzbiBvciB0dW5uZWwgb3B0aW9uLCB3aWxsIG5vdCBzZW5kIGFueSBldmVudHMuIFRoZSB0dW5uZWwgb3B0aW9uIG11c3QgYmUgYSBmdWxsIFVSTCB3aGVuIHVzZWQuIil9KSksdG4odCwoKCk9PlByb21pc2UucmVzb2x2ZSh7fSkpKX1jb25zdCBlPSJodHRwczoiPT09bi5wcm90b2NvbCxyPWZ1bmN0aW9uKHQsbil7Y29uc3R7bm9fcHJveHk6ZX09cHJvY2Vzcy5lbnYscj1lPy5zcGxpdCgiLCIpLnNvbWUoKG49PnQuaG9zdC5lbmRzV2l0aChuKXx8dC5ob3N0bmFtZS5lbmRzV2l0aChuKSkpO3JldHVybiByP3ZvaWQgMDpufShuLHQucHJveHl8fChlP3Byb2Nlc3MuZW52Lmh0dHBzX3Byb3h5OnZvaWQgMCl8fHByb2Nlc3MuZW52Lmh0dHBfcHJveHkpLG89ZT9pOnMsYT12b2lkIDAhPT10LmtlZXBBbGl2ZSYmdC5rZWVwQWxpdmUsZj1yP25ldyBmbihyKTpuZXcgby5BZ2VudCh7a2VlcEFsaXZlOmEsbWF4U29ja2V0czozMCx0aW1lb3V0OjJlM30pLGg9ZnVuY3Rpb24odCxuLGUpe2NvbnN0e2hvc3RuYW1lOnIscGF0aG5hbWU6byxwb3J0OnMscHJvdG9jb2w6aSxzZWFyY2g6YX09bmV3IFVSTCh0LnVybCk7cmV0dXJuIGZ1bmN0aW9uKGYpe3JldHVybiBuZXcgUHJvbWlzZSgoKGgscCk9PntXdCgoKCk9PntsZXQgZD1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IGMoe3JlYWQoKXt0aGlzLnB1c2godCksdGhpcy5wdXNoKG51bGwpfX0pfShmLmJvZHkpO2NvbnN0IGw9ey4uLnQuaGVhZGVyc307Zi5ib2R5Lmxlbmd0aD5kbiYmKGxbImNvbnRlbnQtZW5jb2RpbmciXT0iZ3ppcCIsZD1kLnBpcGUodSgpKSk7Y29uc3QgbT1uLnJlcXVlc3Qoe21ldGhvZDoiUE9TVCIsYWdlbnQ6ZSxoZWFkZXJzOmwsaG9zdG5hbWU6cixwYXRoOmAke299JHthfWAscG9ydDpzLHByb3RvY29sOmksY2E6dC5jYUNlcnRzfSwodD0+e3Qub24oImRhdGEiLCgoKT0+e30pKSx0Lm9uKCJlbmQiLCgoKT0+e30pKSx0LnNldEVuY29kaW5nKCJ1dGY4Iik7Y29uc3Qgbj10LmhlYWRlcnNbInJldHJ5LWFmdGVyIl0/P251bGwsZT10LmhlYWRlcnNbIngtc2VudHJ5LXJhdGUtbGltaXRzIl0/P251bGw7aCh7c3RhdHVzQ29kZTp0LnN0YXR1c0NvZGUsaGVhZGVyczp7InJldHJ5LWFmdGVyIjpuLCJ4LXNlbnRyeS1yYXRlLWxpbWl0cyI6QXJyYXkuaXNBcnJheShlKT9lWzBdfHxudWxsOmV9fSl9KSk7bS5vbigiZXJyb3IiLHApLGQucGlwZShtKX0pKX0pKX19KHQsdC5odHRwTW9kdWxlPz9vLGYpO3JldHVybiB0bih0LGgpfSh7dXJsOih2bj1tbi5kc24sd249bW4udHVubmVsLFNuPW1uLnNka01ldGFkYXRhLnNkayx3bnx8YCR7ZnVuY3Rpb24odCl7cmV0dXJuYCR7ZnVuY3Rpb24odCl7Y29uc3Qgbj10LnByb3RvY29sP2Ake3QucHJvdG9jb2x9OmA6IiIsZT10LnBvcnQ/YDoke3QucG9ydH1gOiIiO3JldHVybmAke259Ly8ke3QuaG9zdH0ke2V9JHt0LnBhdGg/YC8ke3QucGF0aH1gOiIifS9hcGkvYH0odCl9JHt0LnByb2plY3RJZH0vZW52ZWxvcGUvYH0odm4pfT8ke2Z1bmN0aW9uKHQsbil7Y29uc3QgZT17c2VudHJ5X3ZlcnNpb246S3R9O3JldHVybiB0LnB1YmxpY0tleSYmKGUuc2VudHJ5X2tleT10LnB1YmxpY0tleSksbiYmKGUuc2VudHJ5X2NsaWVudD1gJHtuLm5hbWV9LyR7bi52ZXJzaW9ufWApLG5ldyBVUkxTZWFyY2hQYXJhbXMoZSkudG9TdHJpbmcoKX0odm4sU24pfWApLHJlY29yZERyb3BwZWRFdmVudDooKT0+e319KTthc3luYyBmdW5jdGlvbiBFbigpe2lmKGduKXtfbigiU2VuZGluZyBhYm5vcm1hbCBzZXNzaW9uIiksVihnbix7c3RhdHVzOiJhYm5vcm1hbCIsYWJub3JtYWxfbWVjaGFuaXNtOiJhbnJfZm9yZWdyb3VuZCJ9KTtjb25zdCB0PWZ1bmN0aW9uKHQsbixlLHIpe2NvbnN0IG89WXQoZSk7cmV0dXJuIE10KHtzZW50X2F0OihuZXcgRGF0ZSkudG9JU09TdHJpbmcoKSwuLi5vJiZ7c2RrOm99LC4uLiEhciYmbiYme2RzbjpBdChuKX19LFsiYWdncmVnYXRlcyJpbiB0P1t7dHlwZToic2Vzc2lvbnMifSx0XTpbe3R5cGU6InNlc3Npb24ifSx0LnRvSlNPTigpXV0pfShnbixtbi5kc24sbW4uc2RrTWV0YWRhdGEsbW4udHVubmVsKTtfbihKU09OLnN0cmluZ2lmeSh0KSksYXdhaXQgJG4uc2VuZCh0KTt0cnl7bj8ucG9zdE1lc3NhZ2UoInNlc3Npb24tZW5kZWQiKX1jYXRjaCh0KXt9fX1mdW5jdGlvbiB4bih0KXtpZighdClyZXR1cm47Y29uc3Qgbj1mdW5jdGlvbih0KXtpZighdC5sZW5ndGgpcmV0dXJuW107Y29uc3Qgbj1BcnJheS5mcm9tKHQpO3JldHVybi9zZW50cnlXcmFwcGVkLy50ZXN0KHgobikuZnVuY3Rpb258fCIiKSYmbi5wb3AoKSxuLnJldmVyc2UoKSxFLnRlc3QoeChuKS5mdW5jdGlvbnx8IiIpJiYobi5wb3AoKSxFLnRlc3QoeChuKS5mdW5jdGlvbnx8IiIpJiZuLnBvcCgpKSxuLnNsaWNlKDAsUykubWFwKCh0PT4oey4uLnQsZmlsZW5hbWU6dC5maWxlbmFtZXx8eChuKS5maWxlbmFtZSxmdW5jdGlvbjp0LmZ1bmN0aW9ufHwkfSkpKX0odCk7aWYobW4uYXBwUm9vdFBhdGgpZm9yKGNvbnN0IHQgb2Ygbil0LmZpbGVuYW1lJiYodC5maWxlbmFtZT1VdCh0LmZpbGVuYW1lLG1uLmFwcFJvb3RQYXRoKSk7cmV0dXJuIG59YXN5bmMgZnVuY3Rpb24gTm4odCxuKXtpZih5bj49bW4ubWF4QW5yRXZlbnRzKXJldHVybjt5bis9MSxhd2FpdCBFbigpLF9uKCJTZW5kaW5nIGV2ZW50Iik7Y29uc3QgZT17ZXZlbnRfaWQ6eigpLGNvbnRleHRzOm1uLmNvbnRleHRzLHJlbGVhc2U6bW4ucmVsZWFzZSxlbnZpcm9ubWVudDptbi5lbnZpcm9ubWVudCxkaXN0Om1uLmRpc3QscGxhdGZvcm06Im5vZGUiLGxldmVsOiJlcnJvciIsZXhjZXB0aW9uOnt2YWx1ZXM6W3t0eXBlOiJBcHBsaWNhdGlvbk5vdFJlc3BvbmRpbmciLHZhbHVlOmBBcHBsaWNhdGlvbiBOb3QgUmVzcG9uZGluZyBmb3IgYXQgbGVhc3QgJHttbi5hbnJUaHJlc2hvbGR9IG1zYCxzdGFja3RyYWNlOntmcmFtZXM6eG4odCl9LG1lY2hhbmlzbTp7dHlwZToiQU5SIn19XX0sdGFnczptbi5zdGF0aWNUYWdzfTtuJiZmdW5jdGlvbih0LG4pe2lmKEZ0KHQsbiksIXQuY29udGV4dHM/LnRyYWNlKXtjb25zdHt0cmFjZUlkOmUscGFyZW50U3BhbklkOnIscHJvcGFnYXRpb25TcGFuSWQ6b309bi5wcm9wYWdhdGlvbkNvbnRleHQ7dC5jb250ZXh0cz17dHJhY2U6e3RyYWNlX2lkOmUsc3Bhbl9pZDpvfHxxKCkscGFyZW50X3NwYW5faWQ6cn0sLi4udC5jb250ZXh0c319fShlLG4pLGZ1bmN0aW9uKHQpe2lmKDA9PT1PYmplY3Qua2V5cyhibikubGVuZ3RoKXJldHVybjtjb25zdCBuPW1uLmFwcFJvb3RQYXRoP3t9OmJuO2lmKG1uLmFwcFJvb3RQYXRoKWZvcihjb25zdFt0LGVdb2YgT2JqZWN0LmVudHJpZXMoYm4pKW5bVXQodCxtbi5hcHBSb290UGF0aCldPWU7Y29uc3QgZT1uZXcgTWFwO2Zvcihjb25zdCByIG9mIHQuZXhjZXB0aW9uPy52YWx1ZXN8fFtdKWZvcihjb25zdCB0IG9mIHIuc3RhY2t0cmFjZT8uZnJhbWVzfHxbXSl7Y29uc3Qgcj10LmFic19wYXRofHx0LmZpbGVuYW1lO3ImJm5bcl0mJmUuc2V0KHIsbltyXSl9aWYoZS5zaXplPjApe2NvbnN0IG49W107Zm9yKGNvbnN0W3Qscl1vZiBlLmVudHJpZXMoKSluLnB1c2goe3R5cGU6InNvdXJjZW1hcCIsY29kZV9maWxlOnQsZGVidWdfaWQ6cn0pO3QuZGVidWdfbWV0YT17aW1hZ2VzOm59fX0oZSk7Y29uc3Qgcj16dChlLG1uLmRzbixtbi5zZGtNZXRhZGF0YSxtbi50dW5uZWwpO19uKEpTT04uc3RyaW5naWZ5KHIpKSxhd2FpdCAkbi5zZW5kKHIpLGF3YWl0ICRuLmZsdXNoKDJlMykseW4+PW1uLm1heEFuckV2ZW50cyYmc2V0VGltZW91dCgoKCk9Pntwcm9jZXNzLmV4aXQoMCl9KSw1ZTMpfWxldCBUbjtpZihfbigiU3RhcnRlZCIpLG1uLmNhcHR1cmVTdGFja1RyYWNlKXtfbigiQ29ubmVjdGluZyB0byBkZWJ1Z2dlciIpO2NvbnN0IG49bmV3IHQ7bi5jb25uZWN0VG9NYWluVGhyZWFkKCksX24oIkNvbm5lY3RlZCB0byBkZWJ1Z2dlciIpO2NvbnN0IGU9bmV3IE1hcDtuLm9uKCJEZWJ1Z2dlci5zY3JpcHRQYXJzZWQiLCh0PT57ZS5zZXQodC5wYXJhbXMuc2NyaXB0SWQsdC5wYXJhbXMudXJsKX0pKSxuLm9uKCJEZWJ1Z2dlci5wYXVzZWQiLCh0PT57aWYoIm90aGVyIj09PXQucGFyYW1zLnJlYXNvbil0cnl7X24oIkRlYnVnZ2VyIHBhdXNlZCIpO2NvbnN0IHM9Wy4uLnQucGFyYW1zLmNhbGxGcmFtZXNdLGk9bW4uYXBwUm9vdFBhdGg/ZnVuY3Rpb24odD0ocHJvY2Vzcy5hcmd2WzFdP2VuKHByb2Nlc3MuYXJndlsxXSk6cHJvY2Vzcy5jd2QoKSksbj0iXFwiPT09byl7Y29uc3QgZT1uP2xuKHQpOnQ7cmV0dXJuIHQ9PntpZighdClyZXR1cm47Y29uc3Qgbz1uP2xuKHQpOnQ7bGV0e2RpcjpzLGJhc2U6aSxleHQ6Y309ci5wYXJzZShvKTsiLmpzIiE9PWMmJiIubWpzIiE9PWMmJiIuY2pzIiE9PWN8fChpPWkuc2xpY2UoMCwtMSpjLmxlbmd0aCkpO2NvbnN0IHU9ZGVjb2RlVVJJQ29tcG9uZW50KGkpO3N8fChzPSIuIik7Y29uc3QgYT1zLmxhc3RJbmRleE9mKCIvbm9kZV9tb2R1bGVzIik7aWYoYT4tMSlyZXR1cm5gJHtzLnNsaWNlKGErMTQpLnJlcGxhY2UoL1wvL2csIi4iKX06JHt1fWA7aWYocy5zdGFydHNXaXRoKGUpKXtjb25zdCB0PXMuc2xpY2UoZS5sZW5ndGgrMSkucmVwbGFjZSgvXC8vZywiLiIpO3JldHVybiB0P2Ake3R9OiR7dX1gOnV9cmV0dXJuIHV9fShtbi5hcHBSb290UGF0aCk6KCk9Pnt9LGM9cy5tYXAoKHQ9PmZ1bmN0aW9uKHQsbixlKXtjb25zdCByPW4/bi5yZXBsYWNlKC9eZmlsZTpcL1wvLywiIik6dm9pZCAwLG89dC5sb2NhdGlvbi5jb2x1bW5OdW1iZXI/dC5sb2NhdGlvbi5jb2x1bW5OdW1iZXIrMTp2b2lkIDAscz10LmxvY2F0aW9uLmxpbmVOdW1iZXI/dC5sb2NhdGlvbi5saW5lTnVtYmVyKzE6dm9pZCAwO3JldHVybiBMKHtmaWxlbmFtZTpyLG1vZHVsZTplKHIpLGZ1bmN0aW9uOnQuZnVuY3Rpb25OYW1lfHwkLGNvbG5vOm8sbGluZW5vOnMsaW5fYXBwOnI/cm4ocik6dm9pZCAwfSl9KHQsZS5nZXQodC5sb2NhdGlvbi5zY3JpcHRJZCksaSkpKSx1PXNldFRpbWVvdXQoKCgpPT57Tm4oYykudGhlbihudWxsLCgoKT0+e19uKCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQuIil9KSl9KSw1ZTMpO24ucG9zdCgiUnVudGltZS5ldmFsdWF0ZSIse2V4cHJlc3Npb246Imdsb2JhbC5fX1NFTlRSWV9HRVRfU0NPUEVTX18oKTsiLHNpbGVudDohMCxyZXR1cm5CeVZhbHVlOiEwfSwoKHQsZSk9Pnt0JiZfbihgRXJyb3IgZXhlY3V0aW5nIHNjcmlwdDogJyR7dC5tZXNzYWdlfSdgKSxjbGVhclRpbWVvdXQodSk7Y29uc3Qgcj1lPy5yZXN1bHQ/ZS5yZXN1bHQudmFsdWU6dm9pZCAwO24ucG9zdCgiRGVidWdnZXIucmVzdW1lIiksbi5wb3N0KCJEZWJ1Z2dlci5kaXNhYmxlIiksTm4oYyxyKS50aGVuKG51bGwsKCgpPT57X24oIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZC4iKX0pKX0pKX1jYXRjaCh0KXt0aHJvdyBuLnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpLG4ucG9zdCgiRGVidWdnZXIuZGlzYWJsZSIpLHR9fSkpLFRuPSgpPT57dHJ5e24ucG9zdCgiRGVidWdnZXIuZW5hYmxlIiwoKCk9PntuLnBvc3QoIkRlYnVnZ2VyLnBhdXNlIil9KSl9Y2F0Y2godCl7fX19Y29uc3R7cG9sbDpqbn09ZnVuY3Rpb24odCxuLGUscil7Y29uc3Qgbz10KCk7bGV0IHM9ITEsaT0hMDtyZXR1cm4gc2V0SW50ZXJ2YWwoKCgpPT57Y29uc3QgdD1vLmdldFRpbWVNcygpOyExPT09cyYmdD5uK2UmJihzPSEwLGkmJnIoKSksdDxuK2UmJihzPSExKX0pLDIwKSx7cG9sbDooKT0+e28ucmVzZXQoKX0sZW5hYmxlZDp0PT57aT10fX19KChmdW5jdGlvbigpe2xldCB0PXByb2Nlc3MuaHJ0aW1lKCk7cmV0dXJue2dldFRpbWVNczooKT0+e2NvbnN0W24sZV09cHJvY2Vzcy5ocnRpbWUodCk7cmV0dXJuIE1hdGguZmxvb3IoMWUzKm4rZS8xZTYpfSxyZXNldDooKT0+e3Q9cHJvY2Vzcy5ocnRpbWUoKX19fSksbW4ucG9sbEludGVydmFsLG1uLmFuclRocmVzaG9sZCwoZnVuY3Rpb24oKXtfbigiV2F0Y2hkb2cgdGltZW91dCIpLFRuPyhfbigiUGF1c2luZyBkZWJ1Z2dlciB0byBjYXB0dXJlIHN0YWNrIHRyYWNlIiksVG4oKSk6KF9uKCJDYXB0dXJpbmcgZXZlbnQgd2l0aG91dCBhIHN0YWNrIHRyYWNlIiksTm4oKS50aGVuKG51bGwsKCgpPT57X24oIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZCBvbiB3YXRjaGRvZyB0aW1lb3V0LiIpfSkpKX0pKTtuPy5vbigibWVzc2FnZSIsKHQ9Pnt0LnNlc3Npb24mJihnbj1LKHQuc2Vzc2lvbikpLHQuZGVidWdJbWFnZXMmJihibj10LmRlYnVnSW1hZ2VzKSxqbigpfSkpOw==';
|
|
18
13
|
|
|
19
14
|
const DEFAULT_INTERVAL = 50;
|
|
20
15
|
const DEFAULT_HANG_THRESHOLD = 5000;
|
|
@@ -53,7 +48,7 @@ async function getContexts(client) {
|
|
|
53
48
|
event = await processor(event, eventHint);
|
|
54
49
|
}
|
|
55
50
|
|
|
56
|
-
return
|
|
51
|
+
return event?.contexts || {};
|
|
57
52
|
}
|
|
58
53
|
|
|
59
54
|
const INTEGRATION_NAME = 'Anr';
|
|
@@ -128,8 +123,8 @@ async function _startWorker(
|
|
|
128
123
|
const contexts = await getContexts(client);
|
|
129
124
|
|
|
130
125
|
// These will not be accurate if sent later from the worker thread
|
|
131
|
-
|
|
132
|
-
|
|
126
|
+
delete contexts.app?.app_memory;
|
|
127
|
+
delete contexts.device?.free_memory;
|
|
133
128
|
|
|
134
129
|
const initOptions = client.getOptions();
|
|
135
130
|
|
|
@@ -176,7 +171,7 @@ async function _startWorker(
|
|
|
176
171
|
|
|
177
172
|
const timer = setInterval(() => {
|
|
178
173
|
try {
|
|
179
|
-
const currentSession = core.
|
|
174
|
+
const currentSession = core.getIsolationScope().getSession();
|
|
180
175
|
// We need to copy the session object and remove the toJSON method so it can be sent to the worker
|
|
181
176
|
// serialized without making it a SerializedSession
|
|
182
177
|
const session = currentSession ? { ...currentSession, toJSON: undefined } : undefined;
|
|
@@ -192,7 +187,7 @@ async function _startWorker(
|
|
|
192
187
|
worker.on('message', (msg) => {
|
|
193
188
|
if (msg === 'session-ended') {
|
|
194
189
|
log('ANR event sent from ANR worker. Clearing session in this thread.');
|
|
195
|
-
core.
|
|
190
|
+
core.getIsolationScope().setSession(undefined);
|
|
196
191
|
}
|
|
197
192
|
});
|
|
198
193
|
|
|
@@ -220,7 +215,7 @@ async function _startWorker(
|
|
|
220
215
|
* Disables ANR detection for the duration of the callback
|
|
221
216
|
*/
|
|
222
217
|
function disableAnrDetectionForCallback(callback) {
|
|
223
|
-
const integration =
|
|
218
|
+
const integration = core.getClient()?.getIntegrationByName(INTEGRATION_NAME) ;
|
|
224
219
|
|
|
225
220
|
if (!integration) {
|
|
226
221
|
return callback();
|