projen
Version:
CDK for software projects
578 lines • 104 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CodeArtifactAuthProvider = exports.Publisher = void 0;
exports.isAwsCodeArtifactRegistry = isAwsCodeArtifactRegistry;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const component_1 = require("../component");
const constants_1 = require("../github/constants");
const workflows_model_1 = require("../github/workflows-model");
const node_package_1 = require("../javascript/node-package");
const runner_options_1 = require("../runner-options");
const version_1 = require("../version");
const PUBLIB_VERSION = "latest";
const GITHUB_PACKAGES_REGISTRY = "npm.pkg.github.com";
const ARTIFACTS_DOWNLOAD_DIR = "dist";
const GITHUB_PACKAGES_MAVEN_REPOSITORY = "https://maven.pkg.github.com";
const GITHUB_PACKAGES_NUGET_REPOSITORY = "https://nuget.pkg.github.com";
const AWS_CODEARTIFACT_REGISTRY_REGEX = /.codeartifact.*.amazonaws.com/;
const PUBLIB_TOOLCHAIN = {
js: {},
java: { java: { version: "11" } },
python: { python: { version: "3.x" } },
go: { go: { version: "^1.18.0" } },
dotnet: { dotnet: { version: "6.x" } },
};
const PUBLISH_JOB_PREFIX = "release_";
/**
* Implements GitHub jobs for publishing modules to package managers.
*
* Under the hood, it uses https://github.com/aws/publib
*/
class Publisher extends component_1.Component {
constructor(project, options) {
super(project);
// functions that create jobs associated with a specific branch
this._jobFactories = [];
this._gitHubPrePublishing = [];
this._gitHubPostPublishing = [];
// List of publish jobs added to the publisher
// Maps between the basename and the jobname
this.publishJobs = {};
this.buildJobId = options.buildJobId;
this.artifactName = options.artifactName;
this.publibVersion =
options.publibVersion ?? options.jsiiReleaseVersion ?? PUBLIB_VERSION;
this.jsiiReleaseVersion = this.publibVersion;
this.condition = options.condition;
this.dryRun = options.dryRun ?? false;
this.workflowNodeVersion = options.workflowNodeVersion ?? "lts/*";
this.workflowContainerImage = options.workflowContainerImage;
this.failureIssue = options.failureIssue ?? false;
this.failureIssueLabel = options.failureIssueLabel ?? "failed-release";
this.publishTasks = options.publishTasks ?? false;
this.runsOn = options.workflowRunsOn;
this.runsOnGroup = options.workflowRunsOnGroup;
}
/**
* Called by `Release` to add the publishing jobs to a release workflow
* associated with a specific branch.
* @param branch The branch name
* @param options Branch options
*
* @internal
*/
_renderJobsForBranch(branch, options) {
let jobs = {};
for (const factory of this._jobFactories) {
jobs = {
...jobs,
...factory(branch, options),
};
}
return jobs;
}
/**
* Adds pre publishing steps for the GitHub release job.
*
* @param steps The steps.
*/
addGitHubPrePublishingSteps(...steps) {
this._gitHubPrePublishing.push(...steps);
}
/**
* Adds post publishing steps for the GitHub release job.
*
* @param steps The steps.
*/
addGitHubPostPublishingSteps(...steps) {
this._gitHubPostPublishing.push(...steps);
}
/**
* Publish to git.
*
* This includes generating a project-level changelog and release tags.
*
* @param options Options
*/
publishToGit(options) {
const releaseTagFile = options.releaseTagFile;
const versionFile = options.versionFile;
const changelog = options.changelogFile;
const projectChangelogFile = options.projectChangelogFile;
const gitBranch = options.gitBranch ?? "main";
const taskName = gitBranch === "main" || gitBranch === "master"
? Publisher.PUBLISH_GIT_TASK_NAME
: `${Publisher.PUBLISH_GIT_TASK_NAME}:${gitBranch}`;
const publishTask = this.project.addTask(taskName, {
description: "Prepends the release changelog onto the project changelog, creates a release commit, and tags the release",
env: {
CHANGELOG: changelog,
RELEASE_TAG_FILE: releaseTagFile,
PROJECT_CHANGELOG_FILE: projectChangelogFile ?? "",
VERSION_FILE: versionFile,
},
condition: version_1.CHANGES_SINCE_LAST_RELEASE,
});
if (projectChangelogFile) {
publishTask.builtin("release/update-changelog");
}
publishTask.builtin("release/tag-version");
if (options.gitPushCommand !== "") {
const gitPushCommand = options.gitPushCommand || `git push --follow-tags origin ${gitBranch}`;
publishTask.exec(gitPushCommand);
}
return publishTask;
}
/**
* Creates a GitHub Release.
* @param options Options
*/
publishToGitHubReleases(options) {
const jobName = "github";
this.addPublishJob(jobName, (_branch, branchOptions) => {
return {
registryName: "GitHub Releases",
prePublishSteps: options.prePublishSteps ?? this._gitHubPrePublishing,
postPublishSteps: options.postPublishSteps ?? this._gitHubPostPublishing,
publishTools: options.publishTools,
permissions: {
contents: workflows_model_1.JobPermission.WRITE,
},
needs: Object.entries(this.publishJobs)
.filter(([name, _]) => name != jobName)
.map(([_, job]) => job),
workflowEnv: {
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}",
},
run: this.githubReleaseCommand(options, branchOptions),
};
});
}
/**
* Publishes artifacts from `js/**` to npm.
* @param options Options
*/
publishToNpm(options = {}) {
const isGitHubPackages = options.registry?.startsWith(GITHUB_PACKAGES_REGISTRY);
const isAwsCodeArtifact = isAwsCodeArtifactRegistry(options.registry);
const isAwsCodeArtifactWithOidc = isAwsCodeArtifact &&
options.codeArtifactOptions?.authProvider ===
CodeArtifactAuthProvider.GITHUB_OIDC;
const npmToken = (0, node_package_1.defaultNpmToken)(options.npmTokenSecret, options.registry);
if (options.distTag) {
this.project.logger.warn("The `distTag` option is deprecated. Use the npmDistTag option instead.");
}
const prePublishSteps = options.prePublishSteps ?? [];
if (isAwsCodeArtifactWithOidc) {
if (options.codeArtifactOptions?.accessKeyIdSecret ||
options.codeArtifactOptions?.secretAccessKeySecret) {
throw new Error("access and secret key pair should not be provided when using GITHUB_OIDC auth provider for AWS CodeArtifact");
}
else if (!options.codeArtifactOptions?.roleToAssume) {
throw new Error('"roleToAssume" property is required when using GITHUB_OIDC for AWS CodeArtifact options');
}
const regionCaptureRegex = /codeartifact\.(.+)\.amazonaws\.com/;
const region = options.registry?.match(regionCaptureRegex)?.[1];
prePublishSteps.push({
name: "Configure AWS Credentials via GitHub OIDC Provider",
uses: "aws-actions/configure-aws-credentials@v4",
with: {
"role-to-assume": options.codeArtifactOptions.roleToAssume,
"aws-region": region,
},
});
}
this.addPublishJob("npm", (_branch, branchOptions) => {
if (branchOptions.npmDistTag && options.distTag) {
throw new Error("cannot set branch-level npmDistTag and npmDistTag in publishToNpm()");
}
const npmProvenance = options.npmProvenance ? "true" : undefined;
const needsIdTokenWrite = isAwsCodeArtifactWithOidc || npmProvenance;
return {
publishTools: PUBLIB_TOOLCHAIN.js,
prePublishSteps,
postPublishSteps: options.postPublishSteps ?? [],
run: this.publibCommand("publib-npm"),
registryName: "npm",
env: {
NPM_DIST_TAG: branchOptions.npmDistTag ?? options.distTag ?? "latest",
NPM_REGISTRY: options.registry,
NPM_CONFIG_PROVENANCE: npmProvenance,
},
permissions: {
idToken: needsIdTokenWrite ? workflows_model_1.JobPermission.WRITE : undefined,
contents: workflows_model_1.JobPermission.READ,
packages: isGitHubPackages ? workflows_model_1.JobPermission.WRITE : undefined,
},
workflowEnv: {
NPM_TOKEN: npmToken ? secret(npmToken) : undefined,
// if we are publishing to AWS CodeArtifact, pass AWS access keys that will be used to generate NPM_TOKEN using AWS CLI.
AWS_ACCESS_KEY_ID: isAwsCodeArtifact && !isAwsCodeArtifactWithOidc
? secret(options.codeArtifactOptions?.accessKeyIdSecret ??
"AWS_ACCESS_KEY_ID")
: undefined,
AWS_SECRET_ACCESS_KEY: isAwsCodeArtifact && !isAwsCodeArtifactWithOidc
? secret(options.codeArtifactOptions?.secretAccessKeySecret ??
"AWS_SECRET_ACCESS_KEY")
: undefined,
AWS_ROLE_TO_ASSUME: isAwsCodeArtifact && !isAwsCodeArtifactWithOidc
? options.codeArtifactOptions?.roleToAssume
: undefined,
},
};
});
}
/**
* Publishes artifacts from `dotnet/**` to NuGet Gallery.
* @param options Options
*/
publishToNuget(options = {}) {
const isGitHubPackages = options.nugetServer?.startsWith(GITHUB_PACKAGES_NUGET_REPOSITORY);
this.addPublishJob("nuget", (_branch, _branchOptions) => ({
publishTools: PUBLIB_TOOLCHAIN.dotnet,
prePublishSteps: options.prePublishSteps ?? [],
postPublishSteps: options.postPublishSteps ?? [],
run: this.publibCommand("publib-nuget"),
registryName: "NuGet Gallery",
permissions: {
contents: workflows_model_1.JobPermission.READ,
packages: isGitHubPackages ? workflows_model_1.JobPermission.WRITE : undefined,
},
workflowEnv: {
NUGET_API_KEY: secret(isGitHubPackages
? "GITHUB_TOKEN"
: options.nugetApiKeySecret ?? "NUGET_API_KEY"),
NUGET_SERVER: options.nugetServer ?? undefined,
},
}));
}
/**
* Publishes artifacts from `java/**` to Maven.
* @param options Options
*/
publishToMaven(options = {}) {
const isGitHubPackages = options.mavenRepositoryUrl?.startsWith(GITHUB_PACKAGES_MAVEN_REPOSITORY);
const isGitHubActor = isGitHubPackages && options.mavenUsername == undefined;
const mavenServerId = options.mavenServerId ?? (isGitHubPackages ? "github" : undefined);
if (isGitHubPackages && mavenServerId != "github") {
throw new Error('publishing to GitHub Packages requires the "mavenServerId" to be "github"');
}
if (mavenServerId === "central-ossrh" && options.mavenEndpoint != null) {
throw new Error('Custom endpoints are not supported when publishing to Maven Central (mavenServerId: "central-ossrh"). Please remove "mavenEndpoint" from the options.');
}
this.addPublishJob("maven", (_branch, _branchOptions) => ({
registryName: "Maven Central",
publishTools: PUBLIB_TOOLCHAIN.java,
prePublishSteps: options.prePublishSteps ?? [],
postPublishSteps: options.postPublishSteps ?? [],
run: this.publibCommand("publib-maven"),
env: {
MAVEN_ENDPOINT: options.mavenEndpoint,
MAVEN_SERVER_ID: mavenServerId,
MAVEN_REPOSITORY_URL: options.mavenRepositoryUrl,
},
workflowEnv: {
MAVEN_GPG_PRIVATE_KEY: isGitHubPackages
? undefined
: secret(options.mavenGpgPrivateKeySecret ?? "MAVEN_GPG_PRIVATE_KEY"),
MAVEN_GPG_PRIVATE_KEY_PASSPHRASE: isGitHubPackages
? undefined
: secret(options.mavenGpgPrivateKeyPassphrase ??
"MAVEN_GPG_PRIVATE_KEY_PASSPHRASE"),
MAVEN_PASSWORD: secret(options.mavenPassword ??
(isGitHubPackages ? "GITHUB_TOKEN" : "MAVEN_PASSWORD")),
MAVEN_USERNAME: isGitHubActor
? "${{ github.actor }}"
: secret(options.mavenUsername ?? "MAVEN_USERNAME"),
MAVEN_STAGING_PROFILE_ID: isGitHubPackages
? undefined
: secret(options.mavenStagingProfileId ?? "MAVEN_STAGING_PROFILE_ID"),
},
permissions: {
contents: workflows_model_1.JobPermission.READ,
packages: isGitHubPackages ? workflows_model_1.JobPermission.WRITE : undefined,
},
}));
}
/**
* Publishes wheel artifacts from `python` to PyPI.
* @param options Options
*/
publishToPyPi(options = {}) {
let permissions = { contents: workflows_model_1.JobPermission.READ };
const prePublishSteps = options.prePublishSteps ?? [];
let workflowEnv = {};
const isAwsCodeArtifact = isAwsCodeArtifactRegistry(options.twineRegistryUrl);
if (isAwsCodeArtifact) {
const { domain, account, region } = awsCodeArtifactInfoFromUrl(options.twineRegistryUrl);
const { authProvider, roleToAssume, accessKeyIdSecret, secretAccessKeySecret, } = options.codeArtifactOptions ?? {};
const useOidcAuth = authProvider === CodeArtifactAuthProvider.GITHUB_OIDC;
if (useOidcAuth) {
if (!roleToAssume) {
throw new Error('"roleToAssume" property is required when using GITHUB_OIDC for AWS CodeArtifact options');
}
permissions = { ...permissions, idToken: workflows_model_1.JobPermission.WRITE };
prePublishSteps.push({
name: "Configure AWS Credentials via GitHub OIDC Provider",
uses: "aws-actions/configure-aws-credentials@v4",
with: {
"role-to-assume": roleToAssume,
"aws-region": region,
},
});
}
prePublishSteps.push({
name: "Generate CodeArtifact Token",
run: `echo "TWINE_PASSWORD=$(aws codeartifact get-authorization-token --domain ${domain} --domain-owner ${account} --region ${region} --query authorizationToken --output text)" >> $GITHUB_ENV`,
env: useOidcAuth
? undefined
: {
AWS_ACCESS_KEY_ID: secret(accessKeyIdSecret ?? "AWS_ACCESS_KEY_ID"),
AWS_SECRET_ACCESS_KEY: secret(secretAccessKeySecret ?? "AWS_SECRET_ACCESS_KEY"),
},
});
workflowEnv = { TWINE_USERNAME: "aws" };
}
else {
workflowEnv = {
TWINE_USERNAME: secret(options.twineUsernameSecret ?? "TWINE_USERNAME"),
TWINE_PASSWORD: secret(options.twinePasswordSecret ?? "TWINE_PASSWORD"),
};
}
this.addPublishJob("pypi", (_branch, _branchOptions) => ({
registryName: "PyPI",
publishTools: PUBLIB_TOOLCHAIN.python,
permissions,
prePublishSteps,
postPublishSteps: options.postPublishSteps ?? [],
run: this.publibCommand("publib-pypi"),
env: {
TWINE_REPOSITORY_URL: options.twineRegistryUrl,
},
workflowEnv,
}));
}
/**
* Adds a go publishing job.
* @param options Options
*/
publishToGo(options = {}) {
const prePublishSteps = options.prePublishSteps ?? [];
const workflowEnv = {};
if (options.githubUseSsh) {
workflowEnv.GITHUB_USE_SSH = "true";
workflowEnv.SSH_AUTH_SOCK = "/tmp/ssh_agent.sock";
prePublishSteps.push({
name: "Setup GitHub deploy key",
run: 'ssh-agent -a ${SSH_AUTH_SOCK} && ssh-add - <<< "${GITHUB_DEPLOY_KEY}"',
env: {
GITHUB_DEPLOY_KEY: secret(options.githubDeployKeySecret ?? "GO_GITHUB_DEPLOY_KEY"),
SSH_AUTH_SOCK: workflowEnv.SSH_AUTH_SOCK,
},
});
}
else {
workflowEnv.GITHUB_TOKEN = secret(options.githubTokenSecret ?? "GO_GITHUB_TOKEN");
}
this.addPublishJob("golang", (_branch, _branchOptions) => ({
publishTools: PUBLIB_TOOLCHAIN.go,
prePublishSteps: prePublishSteps,
postPublishSteps: options.postPublishSteps ?? [],
run: this.publibCommand("publib-golang"),
registryName: "GitHub Go Module Repository",
env: {
GIT_BRANCH: options.gitBranch,
GIT_USER_NAME: options.gitUserName ?? constants_1.DEFAULT_GITHUB_ACTIONS_USER.name,
GIT_USER_EMAIL: options.gitUserEmail ?? constants_1.DEFAULT_GITHUB_ACTIONS_USER.email,
GIT_COMMIT_MESSAGE: options.gitCommitMessage,
},
workflowEnv: workflowEnv,
}));
}
addPublishJob(
/**
* The basename of the publish job (should be lowercase).
* Will be extended with a prefix.
*/
basename, factory) {
const jobname = `${PUBLISH_JOB_PREFIX}${basename}`;
this.publishJobs[basename] = jobname;
this._jobFactories.push((branch, branchOptions) => {
const opts = factory(branch, branchOptions);
if (jobname in this._jobFactories) {
throw new Error(`Duplicate job with name "${jobname}"`);
}
const commandToRun = this.dryRun
? `echo "DRY RUN: ${opts.run}"`
: opts.run;
const requiredEnv = new Array();
// jobEnv is the env we pass to the github job (task environment + secrets/expressions).
const jobEnv = { ...opts.env };
const workflowEnvEntries = Object.entries(opts.workflowEnv ?? {}).filter(([_, value]) => value != undefined);
for (const [env, expression] of workflowEnvEntries) {
requiredEnv.push(env);
jobEnv[env] = expression;
}
if (this.publishTasks) {
const branchSuffix = branch === "main" || branch === "master" ? "" : `:${branch}`;
// define a task which can be used through `projen publish:xxx`.
const task = this.project.addTask(`publish:${basename.toLocaleLowerCase()}${branchSuffix}`, {
description: `Publish this package to ${opts.registryName}`,
env: opts.env,
requiredEnv: requiredEnv,
});
// first verify that we are on the correct branch
task.exec(`test "$(git branch --show-current)" = "${branch}"`);
// run commands
task.exec(commandToRun);
}
const steps = [
{
name: "Download build artifacts",
uses: "actions/download-artifact@v4",
with: {
name: constants_1.BUILD_ARTIFACT_NAME,
path: ARTIFACTS_DOWNLOAD_DIR, // this must be "dist" for publib
},
},
{
name: "Restore build artifact permissions",
continueOnError: true,
run: [
`cd ${ARTIFACTS_DOWNLOAD_DIR} && setfacl --restore=${constants_1.PERMISSION_BACKUP_FILE}`,
].join("\n"),
},
...opts.prePublishSteps,
{
name: "Release",
// it would have been nice if we could just run "projen publish:xxx" here but that is not possible because this job does not checkout sources
run: commandToRun,
env: jobEnv,
},
...opts.postPublishSteps,
];
const perms = opts.permissions ?? { contents: workflows_model_1.JobPermission.READ };
const container = this.workflowContainerImage
? {
image: this.workflowContainerImage,
}
: undefined;
if (this.failureIssue) {
steps.push(...[
{
name: "Extract Version",
if: "${{ failure() }}",
id: "extract-version",
shell: "bash",
run: 'echo "VERSION=$(cat dist/version.txt)" >> $GITHUB_OUTPUT',
},
{
name: "Create Issue",
if: "${{ failure() }}",
uses: "imjohnbo/issue-bot@v3",
with: {
labels: this.failureIssueLabel,
title: `Publishing v\${{ steps.extract-version.outputs.VERSION }} to ${opts.registryName} failed`,
body: "See https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
},
env: {
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}",
},
},
]);
Object.assign(perms, { issues: workflows_model_1.JobPermission.WRITE });
}
return {
[jobname]: {
tools: {
node: { version: this.workflowNodeVersion },
...opts.publishTools,
},
name: `Publish to ${opts.registryName}`,
permissions: perms,
if: this.condition,
needs: [this.buildJobId, ...(opts.needs ?? [])],
...(0, runner_options_1.filteredRunsOnOptions)(this.runsOn, this.runsOnGroup),
container,
steps,
},
};
});
}
publibCommand(command) {
return `npx -p publib@${this.publibVersion} ${command}`;
}
githubReleaseCommand(options, branchOptions) {
const changelogFile = options.changelogFile;
const releaseTagFile = options.releaseTagFile;
// create a github release
const releaseTag = `$(cat ${releaseTagFile})`;
const ghReleaseCommand = [
`gh release create ${releaseTag}`,
"-R $GITHUB_REPOSITORY",
`-F ${changelogFile}`,
`-t ${releaseTag}`,
"--target $GITHUB_SHA",
];
if (branchOptions.prerelease) {
ghReleaseCommand.push("-p");
}
const ghRelease = ghReleaseCommand.join(" ");
// release script that does not error when re-releasing a given version
const idempotentRelease = [
"errout=$(mktemp);",
`${ghRelease} 2> $errout && true;`,
"exitcode=$?;",
'if [ $exitcode -ne 0 ] && ! grep -q "Release.tag_name already exists" $errout; then',
"cat $errout;",
"exit $exitcode;",
"fi",
].join(" ");
return idempotentRelease;
}
}
exports.Publisher = Publisher;
_a = JSII_RTTI_SYMBOL_1;
Publisher[_a] = { fqn: "projen.release.Publisher", version: "0.95.1" };
Publisher.PUBLISH_GIT_TASK_NAME = "publish:git";
function secret(secretName) {
return `\${{ secrets.${secretName} }}`;
}
/**
* Options for authorizing requests to a AWS CodeArtifact npm repository.
*/
var CodeArtifactAuthProvider;
(function (CodeArtifactAuthProvider) {
/**
* Fixed credentials provided via Github secrets.
*/
CodeArtifactAuthProvider["ACCESS_AND_SECRET_KEY_PAIR"] = "ACCESS_AND_SECRET_KEY_PAIR";
/**
* Ephemeral credentials provided via Github's OIDC integration with an IAM role.
* See:
* https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html
* https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services
*/
CodeArtifactAuthProvider["GITHUB_OIDC"] = "GITHUB_OIDC";
})(CodeArtifactAuthProvider || (exports.CodeArtifactAuthProvider = CodeArtifactAuthProvider = {}));
/**
* Evaluates if the `registryUrl` is a AWS CodeArtifact registry.
* @param registryUrl url of registry
* @returns true for AWS CodeArtifact
*/
function isAwsCodeArtifactRegistry(registryUrl) {
return registryUrl && AWS_CODEARTIFACT_REGISTRY_REGEX.test(registryUrl);
}
/**
* Parses info about code artifact domain from given AWS code artifact url
* @param url Of code artifact domain
* @returns domain, account, and region of code artifact domain
*/
function awsCodeArtifactInfoFromUrl(url) {
const captureRegex = /([a-z0-9-]+)-(.+)\.d\.codeartifact\.(.+)\.amazonaws\.com/;
const matches = url?.match(captureRegex) ?? [];
const [_, domain, account, region] = matches;
return { domain, account, region };
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGlzaGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JlbGVhc2UvcHVibGlzaGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUEwdUNBLDhEQUVDOztBQTN1Q0QsNENBQXlDO0FBQ3pDLG1EQUk2QjtBQUM3QiwrREFNbUM7QUFDbkMsNkRBQTZEO0FBRTdELHNEQUE4RTtBQUM5RSx3Q0FBd0Q7QUFFeEQsTUFBTSxjQUFjLEdBQUcsUUFBUSxDQUFDO0FBQ2hDLE1BQU0sd0JBQXdCLEdBQUcsb0JBQW9CLENBQUM7QUFDdEQsTUFBTSxzQkFBc0IsR0FBRyxNQUFNLENBQUM7QUFDdEMsTUFBTSxnQ0FBZ0MsR0FBRyw4QkFBOEIsQ0FBQztBQUN4RSxNQUFNLGdDQUFnQyxHQUFHLDhCQUE4QixDQUFDO0FBQ3hFLE1BQU0sK0JBQStCLEdBQUcsK0JBQStCLENBQUM7QUFDeEUsTUFBTSxnQkFBZ0IsR0FBRztJQUN2QixFQUFFLEVBQUUsRUFBRTtJQUNOLElBQUksRUFBRSxFQUFFLElBQUksRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsRUFBRTtJQUNqQyxNQUFNLEVBQUUsRUFBRSxNQUFNLEVBQUUsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLEVBQUU7SUFDdEMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxFQUFFO0lBQ2xDLE1BQU0sRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsRUFBRTtDQUN2QyxDQUFDO0FBQ0YsTUFBTSxrQkFBa0IsR0FBRyxVQUFVLENBQUM7QUF5R3RDOzs7O0dBSUc7QUFDSCxNQUFhLFNBQVUsU0FBUSxxQkFBUztJQWdDdEMsWUFBWSxPQUFnQixFQUFFLE9BQXlCO1FBQ3JELEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQWhCakIsK0RBQStEO1FBQzlDLGtCQUFhLEdBQXdCLEVBQUUsQ0FBQztRQUV4Qyx5QkFBb0IsR0FBYyxFQUFFLENBQUM7UUFDckMsMEJBQXFCLEdBQWMsRUFBRSxDQUFDO1FBT3ZELDhDQUE4QztRQUM5Qyw0Q0FBNEM7UUFDM0IsZ0JBQVcsR0FBMkIsRUFBRSxDQUFDO1FBS3hELElBQUksQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQztRQUNyQyxJQUFJLENBQUMsWUFBWSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUM7UUFDekMsSUFBSSxDQUFDLGFBQWE7WUFDaEIsT0FBTyxDQUFDLGFBQWEsSUFBSSxPQUFPLENBQUMsa0JBQWtCLElBQUksY0FBYyxDQUFDO1FBQ3hFLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDO1FBQzdDLElBQUksQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQztRQUNuQyxJQUFJLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLElBQUksS0FBSyxDQUFDO1FBQ3RDLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxPQUFPLENBQUMsbUJBQW1CLElBQUksT0FBTyxDQUFDO1FBQ2xFLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxPQUFPLENBQUMsc0JBQXNCLENBQUM7UUFFN0QsSUFBSSxDQUFDLFlBQVksR0FBRyxPQUFPLENBQUMsWUFBWSxJQUFJLEtBQUssQ0FBQztRQUNsRCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsT0FBTyxDQUFDLGlCQUFpQixJQUFJLGdCQUFnQixDQUFDO1FBQ3ZFLElBQUksQ0FBQyxZQUFZLEdBQUcsT0FBTyxDQUFDLFlBQVksSUFBSSxLQUFLLENBQUM7UUFDbEQsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDO0lBQ2pELENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0ksb0JBQW9CLENBQ3pCLE1BQWMsRUFDZCxPQUErQjtRQUUvQixJQUFJLElBQUksR0FBd0IsRUFBRSxDQUFDO1FBRW5DLEtBQUssTUFBTSxPQUFPLElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ3pDLElBQUksR0FBRztnQkFDTCxHQUFHLElBQUk7Z0JBQ1AsR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQzthQUM1QixDQUFDO1FBQ0osQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSwyQkFBMkIsQ0FBQyxHQUFHLEtBQWdCO1FBQ3BELElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLDRCQUE0QixDQUFDLEdBQUcsS0FBZ0I7UUFDckQsSUFBSSxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSSxZQUFZLENBQUMsT0FBMEI7UUFDNUMsTUFBTSxjQUFjLEdBQUcsT0FBTyxDQUFDLGNBQWMsQ0FBQztRQUM5QyxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDO1FBQ3hDLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUM7UUFDeEMsTUFBTSxvQkFBb0IsR0FBRyxPQUFPLENBQUMsb0JBQW9CLENBQUM7UUFDMUQsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLFNBQVMsSUFBSSxNQUFNLENBQUM7UUFFOUMsTUFBTSxRQUFRLEdBQ1osU0FBUyxLQUFLLE1BQU0sSUFBSSxTQUFTLEtBQUssUUFBUTtZQUM1QyxDQUFDLENBQUMsU0FBUyxDQUFDLHFCQUFxQjtZQUNqQyxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMscUJBQXFCLElBQUksU0FBUyxFQUFFLENBQUM7UUFFeEQsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFO1lBQ2pELFdBQVcsRUFDVCwyR0FBMkc7WUFDN0csR0FBRyxFQUFFO2dCQUNILFNBQVMsRUFBRSxTQUFTO2dCQUNwQixnQkFBZ0IsRUFBRSxjQUFjO2dCQUNoQyxzQkFBc0IsRUFBRSxvQkFBb0IsSUFBSSxFQUFFO2dCQUNsRCxZQUFZLEVBQUUsV0FBVzthQUMxQjtZQUNELFNBQVMsRUFBRSxvQ0FBMEI7U0FDdEMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxvQkFBb0IsRUFBRSxDQUFDO1lBQ3pCLFdBQVcsQ0FBQyxPQUFPLENBQUMsMEJBQTBCLENBQUMsQ0FBQztRQUNsRCxDQUFDO1FBQ0QsV0FBVyxDQUFDLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1FBRTNDLElBQUksT0FBTyxDQUFDLGNBQWMsS0FBSyxFQUFFLEVBQUUsQ0FBQztZQUNsQyxNQUFNLGNBQWMsR0FDbEIsT0FBTyxDQUFDLGNBQWMsSUFBSSxpQ0FBaUMsU0FBUyxFQUFFLENBQUM7WUFDekUsV0FBVyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNuQyxDQUFDO1FBRUQsT0FBTyxXQUFXLENBQUM7SUFDckIsQ0FBQztJQUVEOzs7T0FHRztJQUNJLHVCQUF1QixDQUFDLE9BQXFDO1FBQ2xFLE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQztRQUN6QixJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sRUFBRSxDQUFDLE9BQU8sRUFBRSxhQUFhLEVBQXFCLEVBQUU7WUFDeEUsT0FBTztnQkFDTCxZQUFZLEVBQUUsaUJBQWlCO2dCQUMvQixlQUFlLEVBQUUsT0FBTyxDQUFDLGVBQWUsSUFBSSxJQUFJLENBQUMsb0JBQW9CO2dCQUNyRSxnQkFBZ0IsRUFDZCxPQUFPLENBQUMsZ0JBQWdCLElBQUksSUFBSSxDQUFDLHFCQUFxQjtnQkFDeEQsWUFBWSxFQUFFLE9BQU8sQ0FBQyxZQUFZO2dCQUNsQyxXQUFXLEVBQUU7b0JBQ1gsUUFBUSxFQUFFLCtCQUFhLENBQUMsS0FBSztpQkFDOUI7Z0JBQ0QsS0FBSyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQztxQkFDcEMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksSUFBSSxPQUFPLENBQUM7cUJBQ3RDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUM7Z0JBQ3pCLFdBQVcsRUFBRTtvQkFDWCxZQUFZLEVBQUUsNkJBQTZCO2lCQUM1QztnQkFDRCxHQUFHLEVBQUUsSUFBSSxDQUFDLG9CQUFvQixDQUFDLE9BQU8sRUFBRSxhQUFhLENBQUM7YUFDdkQsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7T0FHRztJQUNJLFlBQVksQ0FBQyxVQUE2QixFQUFFO1FBQ2pELE1BQU0sZ0JBQWdCLEdBQUcsT0FBTyxDQUFDLFFBQVEsRUFBRSxVQUFVLENBQ25ELHdCQUF3QixDQUN6QixDQUFDO1FBQ0YsTUFBTSxpQkFBaUIsR0FBRyx5QkFBeUIsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdEUsTUFBTSx5QkFBeUIsR0FDN0IsaUJBQWlCO1lBQ2pCLE9BQU8sQ0FBQyxtQkFBbUIsRUFBRSxZQUFZO2dCQUN2Qyx3QkFBd0IsQ0FBQyxXQUFXLENBQUM7UUFDekMsTUFBTSxRQUFRLEdBQUcsSUFBQSw4QkFBZSxFQUFDLE9BQU8sQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRTNFLElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3BCLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FDdEIsd0VBQXdFLENBQ3pFLENBQUM7UUFDSixDQUFDO1FBRUQsTUFBTSxlQUFlLEdBQWMsT0FBTyxDQUFDLGVBQWUsSUFBSSxFQUFFLENBQUM7UUFFakUsSUFBSSx5QkFBeUIsRUFBRSxDQUFDO1lBQzlCLElBQ0UsT0FBTyxDQUFDLG1CQUFtQixFQUFFLGlCQUFpQjtnQkFDOUMsT0FBTyxDQUFDLG1CQUFtQixFQUFFLHFCQUFxQixFQUNsRCxDQUFDO2dCQUNELE1BQU0sSUFBSSxLQUFLLENBQ2IsNkdBQTZHLENBQzlHLENBQUM7WUFDSixDQUFDO2lCQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsbUJBQW1CLEVBQUUsWUFBWSxFQUFFLENBQUM7Z0JBQ3RELE1BQU0sSUFBSSxLQUFLLENBQ2IseUZBQXlGLENBQzFGLENBQUM7WUFDSixDQUFDO1lBQ0QsTUFBTSxrQkFBa0IsR0FBRyxvQ0FBb0MsQ0FBQztZQUNoRSxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDaEUsZUFBZSxDQUFDLElBQUksQ0FBQztnQkFDbkIsSUFBSSxFQUFFLG9EQUFvRDtnQkFDMUQsSUFBSSxFQUFFLDBDQUEwQztnQkFDaEQsSUFBSSxFQUFFO29CQUNKLGdCQUFnQixFQUFFLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZO29CQUMxRCxZQUFZLEVBQUUsTUFBTTtpQkFDckI7YUFDRixDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxPQUFPLEVBQUUsYUFBYSxFQUFxQixFQUFFO1lBQ3RFLElBQUksYUFBYSxDQUFDLFVBQVUsSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ2hELE1BQU0sSUFBSSxLQUFLLENBQ2IscUVBQXFFLENBQ3RFLENBQUM7WUFDSixDQUFDO1lBRUQsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7WUFDakUsTUFBTSxpQkFBaUIsR0FBRyx5QkFBeUIsSUFBSSxhQUFhLENBQUM7WUFDckUsT0FBTztnQkFDTCxZQUFZLEVBQUUsZ0JBQWdCLENBQUMsRUFBRTtnQkFDakMsZUFBZTtnQkFDZixnQkFBZ0IsRUFBRSxPQUFPLENBQUMsZ0JBQWdCLElBQUksRUFBRTtnQkFDaEQsR0FBRyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDO2dCQUNyQyxZQUFZLEVBQUUsS0FBSztnQkFDbkIsR0FBRyxFQUFFO29CQUNILFlBQVksRUFBRSxhQUFhLENBQUMsVUFBVSxJQUFJLE9BQU8sQ0FBQyxPQUFPLElBQUksUUFBUTtvQkFDckUsWUFBWSxFQUFFLE9BQU8sQ0FBQyxRQUFRO29CQUM5QixxQkFBcUIsRUFBRSxhQUFhO2lCQUNyQztnQkFDRCxXQUFXLEVBQUU7b0JBQ1gsT0FBTyxFQUFFLGlCQUFpQixDQUFDLENBQUMsQ0FBQywrQkFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUztvQkFDNUQsUUFBUSxFQUFFLCtCQUFhLENBQUMsSUFBSTtvQkFDNUIsUUFBUSxFQUFFLGdCQUFnQixDQUFDLENBQUMsQ0FBQywrQkFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUztpQkFDN0Q7Z0JBQ0QsV0FBVyxFQUFFO29CQUNYLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUztvQkFDbEQsd0hBQXdIO29CQUN4SCxpQkFBaUIsRUFDZixpQkFBaUIsSUFBSSxDQUFDLHlCQUF5Qjt3QkFDN0MsQ0FBQyxDQUFDLE1BQU0sQ0FDSixPQUFPLENBQUMsbUJBQW1CLEVBQUUsaUJBQWlCOzRCQUM1QyxtQkFBbUIsQ0FDdEI7d0JBQ0gsQ0FBQyxDQUFDLFNBQVM7b0JBQ2YscUJBQXFCLEVBQ25CLGlCQUFpQixJQUFJLENBQUMseUJBQXlCO3dCQUM3QyxDQUFDLENBQUMsTUFBTSxDQUNKLE9BQU8sQ0FBQyxtQkFBbUIsRUFBRSxxQkFBcUI7NEJBQ2hELHVCQUF1QixDQUMxQjt3QkFDSCxDQUFDLENBQUMsU0FBUztvQkFDZixrQkFBa0IsRUFDaEIsaUJBQWlCLElBQUksQ0FBQyx5QkFBeUI7d0JBQzdDLENBQUMsQ0FBQyxPQUFPLENBQUMsbUJBQW1CLEVBQUUsWUFBWTt3QkFDM0MsQ0FBQyxDQUFDLFNBQVM7aUJBQ2hCO2FBQ0YsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7T0FHRztJQUNJLGNBQWMsQ0FBQyxVQUErQixFQUFFO1FBQ3JELE1BQU0sZ0JBQWdCLEdBQUcsT0FBTyxDQUFDLFdBQVcsRUFBRSxVQUFVLENBQ3RELGdDQUFnQyxDQUNqQyxDQUFDO1FBRUYsSUFBSSxDQUFDLGFBQWEsQ0FDaEIsT0FBTyxFQUNQLENBQUMsT0FBTyxFQUFFLGNBQWMsRUFBcUIsRUFBRSxDQUFDLENBQUM7WUFDL0MsWUFBWSxFQUFFLGdCQUFnQixDQUFDLE1BQU07WUFDckMsZUFBZSxFQUFFLE9BQU8sQ0FBQyxlQUFlLElBQUksRUFBRTtZQUM5QyxnQkFBZ0IsRUFBRSxPQUFPLENBQUMsZ0JBQWdCLElBQUksRUFBRTtZQUNoRCxHQUFHLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxjQUFjLENBQUM7WUFDdkMsWUFBWSxFQUFFLGVBQWU7WUFDN0IsV0FBVyxFQUFFO2dCQUNYLFFBQVEsRUFBRSwrQkFBYSxDQUFDLElBQUk7Z0JBQzVCLFFBQVEsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsK0JBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFNBQVM7YUFDN0Q7WUFDRCxXQUFXLEVBQUU7Z0JBQ1gsYUFBYSxFQUFFLE1BQU0sQ0FDbkIsZ0JBQWdCO29CQUNkLENBQUMsQ0FBQyxjQUFjO29CQUNoQixDQUFDLENBQUMsT0FBTyxDQUFDLGlCQUFpQixJQUFJLGVBQWUsQ0FDakQ7Z0JBQ0QsWUFBWSxFQUFFLE9BQU8sQ0FBQyxXQUFXLElBQUksU0FBUzthQUMvQztTQUNGLENBQUMsQ0FDSCxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7T0FHRztJQUNJLGNBQWMsQ0FBQyxVQUErQixFQUFFO1FBQ3JELE1BQU0sZ0JBQWdCLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixFQUFFLFVBQVUsQ0FDN0QsZ0NBQWdDLENBQ2pDLENBQUM7UUFDRixNQUFNLGFBQWEsR0FDakIsZ0JBQWdCLElBQUksT0FBTyxDQUFDLGFBQWEsSUFBSSxTQUFTLENBQUM7UUFDekQsTUFBTSxhQUFhLEdBQ2pCLE9BQU8sQ0FBQyxhQUFhLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUVyRSxJQUFJLGdCQUFnQixJQUFJLGFBQWEsSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUNsRCxNQUFNLElBQUksS0FBSyxDQUNiLDJFQUEyRSxDQUM1RSxDQUFDO1FBQ0osQ0FBQztRQUVELElBQUksYUFBYSxLQUFLLGVBQWUsSUFBSSxPQUFPLENBQUMsYUFBYSxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ3ZFLE1BQU0sSUFBSSxLQUFLLENBQ2IsdUpBQXVKLENBQ3hKLENBQUM7UUFDSixDQUFDO1FBRUQsSUFBSSxDQUFDLGFBQWEsQ0FDaEIsT0FBTyxFQUNQLENBQUMsT0FBTyxFQUFFLGNBQWMsRUFBcUIsRUFBRSxDQUFDLENBQUM7WUFDL0MsWUFBWSxFQUFFLGVBQWU7WUFDN0IsWUFBWSxFQUFFLGdCQUFnQixDQUFDLElBQUk7WUFDbkMsZUFBZSxFQUFFLE9BQU8sQ0FBQyxlQUFlLElBQUksRUFBRTtZQUM5QyxnQkFBZ0IsRUFBRSxPQUFPLENBQUMsZ0JBQWdCLElBQUksRUFBRTtZQUNoRCxHQUFHLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxjQUFjLENBQUM7WUFDdkMsR0FBRyxFQUFFO2dCQUNILGNBQWMsRUFBRSxPQUFPLENBQUMsYUFBYTtnQkFDckMsZUFBZSxFQUFFLGFBQWE7Z0JBQzlCLG9CQUFvQixFQUFFLE9BQU8sQ0FBQyxrQkFBa0I7YUFDakQ7WUFDRCxXQUFXLEVBQUU7Z0JBQ1gscUJBQXFCLEVBQUUsZ0JBQWdCO29CQUNyQyxDQUFDLENBQUMsU0FBUztvQkFDWCxDQUFDLENBQUMsTUFBTSxDQUNKLE9BQU8sQ0FBQyx3QkFBd0IsSUFBSSx1QkFBdUIsQ0FDNUQ7Z0JBQ0wsZ0NBQWdDLEVBQUUsZ0JBQWdCO29CQUNoRCxDQUFDLENBQUMsU0FBUztvQkFDWCxDQUFDLENBQUMsTUFBTSxDQUNKLE9BQU8sQ0FBQyw0QkFBNEI7d0JBQ2xDLGtDQUFrQyxDQUNyQztnQkFDTCxjQUFjLEVBQUUsTUFBTSxDQUNwQixPQUFPLENBQUMsYUFBYTtvQkFDbkIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUN6RDtnQkFDRCxjQUFjLEVBQUUsYUFBYTtvQkFDM0IsQ0FBQyxDQUFDLHFCQUFxQjtvQkFDdkIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsYUFBYSxJQUFJLGdCQUFnQixDQUFDO2dCQUNyRCx3QkFBd0IsRUFBRSxnQkFBZ0I7b0JBQ3hDLENBQUMsQ0FBQyxTQUFTO29CQUNYLENBQUMsQ0FBQyxNQUFNLENBQ0osT0FBTyxDQUFDLHFCQUFxQixJQUFJLDBCQUEwQixDQUM1RDthQUNOO1lBQ0QsV0FBVyxFQUFFO2dCQUNYLFFBQVEsRUFBRSwrQkFBYSxDQUFDLElBQUk7Z0JBQzVCLFFBQVEsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsK0JBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFNBQVM7YUFDN0Q7U0FDRixDQUFDLENBQ0gsQ0FBQztJQUNKLENBQUM7SUFFRDs7O09BR0c7SUFDSSxhQUFhLENBQUMsVUFBOEIsRUFBRTtRQUNuRCxJQUFJLFdBQVcsR0FBbUIsRUFBRSxRQUFRLEVBQUUsK0JBQWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNuRSxNQUFNLGVBQWUsR0FBRyxPQUFPLENBQUMsZUFBZSxJQUFJLEVBQUUsQ0FBQztRQUN0RCxJQUFJLFdBQVcsR0FBdUMsRUFBRSxDQUFDO1FBQ3pELE1BQU0saUJBQWlCLEdBQUcseUJBQXlCLENBQ2pELE9BQU8sQ0FBQyxnQkFBZ0IsQ0FDekIsQ0FBQztRQUNGLElBQUksaUJBQWlCLEVBQUUsQ0FBQztZQUN0QixNQUFNLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsR0FBRywwQkFBMEIsQ0FDNUQsT0FBTyxDQUFDLGdCQUFnQixDQUN6QixDQUFDO1lBQ0YsTUFBTSxFQUNKLFlBQVksRUFDWixZQUFZLEVBQ1osaUJBQWlCLEVBQ2pCLHFCQUFxQixHQUN0QixHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsSUFBSSxFQUFFLENBQUM7WUFDdEMsTUFBTSxXQUFXLEdBQUcsWUFBWSxLQUFLLHdCQUF3QixDQUFDLFdBQVcsQ0FBQztZQUMxRSxJQUFJLFdBQVcsRUFBRSxDQUFDO2dCQUNoQixJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7b0JBQ2xCLE1BQU0sSUFBSSxLQUFLLENBQ2IseUZBQXlGLENBQzFGLENBQUM7Z0JBQ0osQ0FBQztnQkFDRCxXQUFXLEdBQUcsRUFBRSxHQUFHLFdBQVcsRUFBRSxPQUFPLEVBQUUsK0JBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDL0QsZUFBZSxDQUFDLElBQUksQ0FBQztvQkFDbkIsSUFBSSxFQUFFLG9EQUFvRDtvQkFDMUQsSUFBSSxFQUFFLDBDQUEwQztvQkFDaEQsSUFBSSxFQUFFO3dCQUNKLGdCQUFnQixFQUFFLFlBQVk7d0JBQzlCLFlBQVksRUFBRSxNQUFNO3FCQUNyQjtpQkFDRixDQUFDLENBQUM7WUFDTCxDQUFDO1lBQ0QsZUFBZSxDQUFDLElBQUksQ0FBQztnQkFDbkIsSUFBSSxFQUFFLDZCQUE2QjtnQkFDbkMsR0FBRyxFQUFFLDRFQUE0RSxNQUFNLG1CQUFtQixPQUFPLGFBQWEsTUFBTSw0REFBNEQ7Z0JBQ2hNLEdBQUcsRUFBRSxXQUFXO29CQUNkLENBQUMsQ0FBQyxTQUFTO29CQUNYLENBQUMsQ0FBQzt3QkFDRSxpQkFBaUIsRUFBRSxNQUFNLENBQ3ZCLGlCQUFpQixJQUFJLG1CQUFtQixDQUN6Qzt3QkFDRCxxQkFBcUIsRUFBRSxNQUFNLENBQzNCLHFCQUFxQixJQUFJLHVCQUF1QixDQUNqRDtxQkFDRjthQUNOLENBQUMsQ0FBQztZQUNILFdBQVcsR0FBRyxFQUFFLGNBQWMsRUFBRSxLQUFLLEVBQUUsQ0FBQztRQUMxQyxDQUFDO2FBQU0sQ0FBQztZQUNOLFdBQVcsR0FBRztnQkFDWixjQUFjLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsSUFBSSxnQkFBZ0IsQ0FBQztnQkFDdkUsY0FBYyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsbUJBQW1CLElBQUksZ0JBQWdCLENBQUM7YUFDeEUsQ0FBQztRQUNKLENBQUM7UUFFRCxJQUFJLENBQUMsYUFBYSxDQUNoQixNQUFNLEVBQ04sQ0FBQyxPQUFPLEVBQUUsY0FBYyxFQUFxQixFQUFFLENBQUMsQ0FBQztZQUMvQyxZQUFZLEVBQUUsTUFBTTtZQUNwQixZQUFZLEVBQUUsZ0JBQWdCLENBQUMsTUFBTTtZQUNyQyxXQUFXO1lBQ1gsZUFBZTtZQUNmLGdCQUFnQixFQUFFLE9BQU8sQ0FBQyxnQkFBZ0IsSUFBSSxFQUFFO1lBQ2hELEdBQUcsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQztZQUN0QyxHQUFHLEVBQUU7Z0JBQ0gsb0JBQW9CLEVBQUUsT0FBTyxDQUFDLGdCQUFnQjthQUMvQztZQUNELFdBQVc7U0FDWixDQUFDLENBQ0gsQ0FBQztJQUNKLENBQUM7SUFFRDs7O09BR0c7SUFDSSxXQUFXLENBQUMsVUFBNEIsRUFBRTtRQUMvQyxNQUFNLGVBQWUsR0FBRyxPQUFPLENBQUMsZUFBZSxJQUFJLEVBQUUsQ0FBQztRQUN0RCxNQUFNLFdBQVcsR0FBMkMsRUFBRSxDQUFDO1FBQy9ELElBQUksT0FBTyxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3pCLFdBQVcsQ0FBQyxjQUFjLEdBQUcsTUFBTSxDQUFDO1lBQ3BDLFdBQVcsQ0FBQyxhQUFhLEdBQUcscUJBQXFCLENBQUM7WUFDbEQsZUFBZSxDQUFDLElBQUksQ0FBQztnQkFDbkIsSUFBSSxFQUFFLHlCQUF5QjtnQkFDL0IsR0FBRyxFQUFFLHVFQUF1RTtnQkFDNUUsR0FBRyxFQUFFO29CQUNILGlCQUFpQixFQUFFLE1BQU0sQ0FDdkIsT0FBTyxDQUFDLHFCQUFxQixJQUFJLHNCQUFzQixDQUN4RDtvQkFDRCxhQUFhLEVBQUUsV0FBVyxDQUFDLGFBQWE7aUJBQ3pDO2FBQ0YsQ0FBQyxDQUFDO1FBQ0wsQ0FBQzthQUFNLENBQUM7WUFDTixXQUFXLENBQUMsWUFBWSxHQUFHLE1BQU0sQ0FDL0IsT0FBTyxDQUFDLGlCQUFpQixJQUFJLGlCQUFpQixDQUMvQyxDQUFDO1FBQ0osQ0FBQztRQUVELElBQUksQ0FBQyxhQUFhLENBQ2hCLFFBQVEsRUFDUixDQUFDLE9BQU8sRUFBRSxjQUFjLEVBQXFCLEVBQUUsQ0FBQyxDQUFDO1lBQy9DLFlBQVksRUFBRSxnQkFBZ0IsQ0FBQyxFQUFFO1lBQ2pDLGVBQWUsRUFBRSxlQUFlO1lBQ2hDLGdCQUFnQixFQUFFLE9BQU8sQ0FBQyxnQkFBZ0IsSUFBSSxFQUFFO1lBQ2hELEdBQUcsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQztZQUN4QyxZQUFZLEVBQUUsNkJBQTZCO1lBQzNDLEdBQUcsRUFBRTtnQkFDSCxVQUFVLEVBQUUsT0FBTyxDQUFDLFNBQVM7Z0JBQzdCLGFBQWEsRUFDWCxPQUFPLENBQUMsV0FBVyxJQUFJLHVDQUEyQixDQUFDLElBQUk7Z0JBQ3pELGNBQWMsRUFDWixPQUFPLENBQUMsWUFBWSxJQUFJLHVDQUEyQixDQUFDLEtBQUs7Z0JBQzNELGtCQUFrQixFQUFFLE9BQU8sQ0FBQyxnQkFBZ0I7YUFDN0M7WUFDRCxXQUFXLEVBQUUsV0FBVztTQUN6QixDQUFDLENBQ0gsQ0FBQztJQUNKLENBQUM7SUFFTyxhQUFhO0lBQ25COzs7T0FHRztJQUNILFFBQWdCLEVBQ2hCLE9BR3NCO1FBRXRCLE1BQU0sT0FBTyxHQUFHLEdBQUcsa0JBQWtCLEdBQUcsUUFBUSxFQUFFLENBQUM7UUFDbkQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsR0FBRyxPQUFPLENBQUM7UUFFckMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsYUFBYSxFQUFFLEVBQUU7WUFDaEQsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRSxhQUFhLENBQUMsQ0FBQztZQUM1QyxJQUFJLE9BQU8sSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7Z0JBQ2xDLE1BQU0sSUFBSSxLQUFLLENBQUMsNEJBQTRCLE9BQU8sR0FBRyxDQUFDLENBQUM7WUFDMUQsQ0FBQztZQUVELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxNQUFNO2dCQUM5QixDQUFDLENBQUMsa0JBQWtCLElBQUksQ0FBQyxHQUFHLEdBQUc7Z0JBQy9CLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO1lBQ2IsTUFBTSxXQUFXLEdBQUcsSUFBSSxLQUFLLEVBQVUsQ0FBQztZQUV4Qyx3RkFBd0Y7WUFDeEYsTUFBTSxNQUFNLEdBQTJCLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDdkQsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLElBQUksRUFBRSxDQUFDLENBQUMsTUFBTSxDQUN0RSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxLQUFLLElBQUksU0FBUyxDQUNyQixDQUFDO1lBQ2hCLEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxVQUFVLENBQUMsSUFBSSxrQkFBa0IsRUFBRSxDQUFDO2dCQUNuRCxXQUFXLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUN0QixNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsVUFBVSxDQUFDO1lBQzNCLENBQUM7WUFFRCxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDdEIsTUFBTSxZQUFZLEdBQ2hCLE1BQU0sS0FBSyxNQUFNLElBQUksTUFBTSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLE1BQU0sRUFBRSxDQUFDO2dCQUUvRCxnRUFBZ0U7Z0JBQ2hFLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUMvQixXQUFXLFFBQVEsQ0FBQyxpQkFBaUIsRUFBRSxHQUFHLFlBQVksRUFBRSxFQUN4RDtvQkFDRSxXQUFXLEVBQUUsMkJBQTJCLElBQUksQ0FBQyxZQUFZLEVBQUU7b0JBQzNELEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRztvQkFDYixXQUFXLEVBQUUsV0FBVztpQkFDekIsQ0FDRixDQUFDO2dCQUVGLGlEQUFpRDtnQkFDakQsSUFBSSxDQUFDLElBQUksQ0FBQywwQ0FBMEMsTUFBTSxHQUFHLENBQUMsQ0FBQztnQkFFL0QsZUFBZTtnQkFDZixJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQzFCLENBQUM7WUFFRCxNQUFNLEtBQUssR0FBYztnQkFDdkI7b0JBQ0UsSUFBSSxFQUFFLDBCQUEwQjtvQkFDaEMsSUFBSSxFQUFFLDhCQUE4QjtvQkFDcEMsSUFBSSxFQUFFO3dCQUNKLElBQUksRUFBRSwrQkFBbUI7d0JBQ3pCLElBQUksRUFBRSxzQkFBc0IsRUFBRSxpQ0FBaUM7cUJBQ2hFO2lCQUNGO2dCQUNEO29CQUNFLElBQUksRUFBRSxvQ0FBb0M7b0JBQzFDLGVBQWUsRUFBRSxJQUFJO29CQUNyQixHQUFHLEVBQUU7d0JBQ0gsTUFBTSxzQkFBc0IseUJBQXlCLGtDQUFzQixFQUFFO3FCQUM5RSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7aUJBQ2I7Z0JBQ0QsR0FBRyxJQUFJLENBQUMsZUFBZTtnQkFDdkI7b0JBQ0UsSUFBSSxFQUFFLFNBQVM7b0JBQ2YsNklBQTZJO29CQUM3SSxHQUFHLEVBQUUsWUFBWTtvQkFDakIsR0FBRyxFQUFFLE1BQU07aUJBQ1o7Z0JBQ0QsR0FBRyxJQUFJLENBQUMsZ0JBQWdCO2FBQ3pCLENBQUM7WUFFRixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxJQUFJLEVBQUUsUUFBUSxFQUFFLCtCQUFhLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbkUsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLHNCQUFzQjtnQkFDM0MsQ0FBQyxDQUFDO29CQUNFLEtBQUssRUFBRSxJQUFJLENBQUMsc0JBQXNCO2lCQUNuQztnQkFDSCxDQUFDLENBQUMsU0FBUyxDQUFDO1lBRWQsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ3RCLEtBQUssQ0FBQyxJQUFJLENBQ1IsR0FBRztvQkFDRDt3QkFDRSxJQUFJLEVBQUUsaUJBQWlCO3dCQUN2QixFQUFFLEVBQUUsa0JBQWtCO3dCQUN0QixFQUFFLEVBQUUsaUJBQWlCO3dCQUNyQixLQUFLLEVBQUUsTUFBTTt3QkFDYixHQUFHLEVBQUUsMERBQTBEO3FCQUNoRTtvQkFDRDt3QkFDRSxJQUFJLEVBQUUsY0FBYzt3QkFDcEIsRUFBRSxFQUFFLGtCQUFrQjt3QkFDdEIsSUFBSSxFQUFFLHVCQUF1Qjt3QkFDN0IsSUFBSSxFQUFFOzRCQUNKLE1BQU0sRUFBRSxJQUFJLENBQUMsaUJBQWlCOzRCQUM5QixLQUFLLEVBQUUsZ0VBQWdFLElBQUksQ0FBQyxZQUFZLFNBQVM7NEJBQ2pHLElBQUksRUFBRSxtRkFBbUY7eUJBQzFGO3dCQUNELEdBQUcsRUFBRTs0QkFDSCxZQUFZLEVBQUUsNkJBQTZCO3lCQUM1QztxQkFDRjtpQkFDRixDQUNGLENBQUM7Z0JBQ0YsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsRUFBRSxNQUFNLEVBQUUsK0JBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO1lBQ3hELENBQUM7WUFFRCxPQUFPO2dCQUNMLENBQUMsT0FBTyxDQUFDLEVBQUU7b0JBQ1QsS0FBSyxFQUFFO3dCQUNMLElBQUksRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsbUJBQW1CLEVBQUU7d0JBQzNDLEdBQUcsSUFBSSxDQUFDLFlBQVk7cUJBQ3JCO29CQUNELElBQUksRUFBRSxjQUFjLElBQUksQ0FBQyxZQUFZLEVBQUU7b0JBQ3ZDLFdBQVcsRUFBRSxLQUFLO29CQUNsQixFQUFFLEVBQUUsSUFBSSxDQUFDLFNBQVM7b0JBQ2xCLEtBQUssRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDLENBQUM7b0JBQy9DLEdBQUcsSUFBQSxzQ0FBcUIsRUFBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUM7b0JBQ3ZELFNBQVM7b0JBQ1QsS0FBSztpQkFDTjthQUNGLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxhQUFhLENBQUMsT0FBZTtRQUNuQyxPQUFPLGlCQUFpQixJQUFJLENBQUMsYUFBYSxJQUFJLE9BQU8sRUFBRSxDQUFDO0lBQzFELENBQUM7SUFFTyxvQkFBb0IsQ0FDMUIsT0FBcUMsRUFDckMsYUFBcUM7UUFFckMsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLGFBQWEsQ0FBQztRQUM1QyxNQUFNLGNBQWMsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDO1FBRTlDLDBCQUEwQjtRQUMxQixNQUFNLFVBQVUsR0FBRyxTQUFTLGNBQWMsR0FBRyxDQUFDO1FBQzlDLE1BQU0sZ0JBQWdCLEdBQUc7WUFDdkIscUJBQXFCLFVBQVUsRUFBRTtZQUNqQyx1QkFBdUI7WUFDdkIsTUFBTSxhQUFhLEVBQUU7WUFDckIsTUFBTSxVQUFVLEVBQUU7WUFDbEIsc0JBQXNCO1NBQ3ZCLENBQUM7UUFFRixJQUFJLGFBQWEsQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUM3QixnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDOUIsQ0FBQztRQUVELE1BQU0sU0FBUyxHQUFHLGdCQUFnQixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUU3Qyx1RUFBdUU7UUFDdkUsTUFBTSxpQkFBaUIsR0FBRztZQUN4QixtQkFBbUI7WUFDbkIsR0FBRyxTQUFTLHNCQUFzQjtZQUNsQyxjQUFjO1lBQ2QscUZBQXFGO1lBQ3JGLGNBQWM7WUFDZCxpQkFBaUI7WUFDakIsSUFBSTtTQUNMLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ1osT0FBTyxpQkFBaUIsQ0FBQztJQUMzQixDQUFDOztBQXpwQkgsOEJBMHBCQzs7O0FBenBCd0IsK0JBQXFCLEdBQUcsYUFBYSxBQUFoQixDQUFpQjtBQTJwQi9ELFNBQVMsTUFBTSxDQUFDLFVBQWtCO0lBQ2hDLE9BQU8sZ0JBQWdCLFVBQVUsS0FBSyxDQUFDO0FBQ3pDLENBQUM7QUFvSkQ7O0dBRUc7QUFDSCxJQUFZLHdCQWFYO0FBYkQsV0FBWSx3QkFBd0I7SUFDbEM7O09BRUc7SUFDSCxxRkFBeUQsQ0FBQTtJQUV6RDs7Ozs7T0FLRztJQUNILHVEQUEyQixDQUFBO0FBQzdCLENBQUMsRUFiVyx3QkFBd0Isd0NBQXhCLHdCQUF3QixRQWFuQztBQXFSRDs7OztHQUlHO0FBQ0gsU0FBZ0IseUJBQXlCLENBQUMsV0FBK0I7SUFDdkUsT0FBTyxXQUFXLElBQUksK0JBQStCLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0FBQzFFLENBQUM7QUFXRDs7OztHQUlHO0FBQ0gsU0FBUywwQkFBMEIsQ0FBQyxHQUFZO0lBQzlDLE1BQU0sWUFBWSxHQUNoQiwwREFBMEQsQ0FBQztJQUM3RCxNQUFNLE9BQU8sR0FBRyxHQUFHLEVBQUUsS0FBSyxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUMvQyxNQUFNLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLEdBQUcsT0FBTyxDQUFDO0lBQzdDLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxDQUFDO0FBQ3JDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCcmFuY2hPcHRpb25zIH0gZnJvbSBcIi4vcmVsZWFzZVwiO1xuaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSBcIi4uL2NvbXBvbmVudFwiO1xuaW1wb3J0IHtcbiAgQlVJTERfQVJUSUZBQ1RfTkFNRSxcbiAgREVGQVVMVF9HSVRIVUJfQUNUSU9OU19VU0VSLFxuICBQRVJNSVNTSU9OX0JBQ0tVUF9GSUxFLFxufSBmcm9tIFwiLi4vZ2l0aHViL2NvbnN0YW50c1wiO1xuaW1wb3J0IHtcbiAgSm9iLFxuICBKb2JQZXJtaXNzaW9uLFxuICBKb2JQZXJtaXNzaW9ucyxcbiAgSm9iU3RlcCxcbiAgVG9vbHMsXG59IGZyb20gXCIuLi9naXRodWIvd29ya2Zsb3dzLW1vZGVsXCI7XG5pbXBvcnQgeyBkZWZhdWx0TnBtVG9rZW4gfSBmcm9tIFwiLi4vamF2YXNjcmlwdC9ub2RlLXBhY2thZ2VcIjtcbmltcG9ydCB7IFByb2plY3QgfSBmcm9tIFwiLi4vcHJvamVjdFwiO1xuaW1wb3J0IHsgR3JvdXBSdW5uZXJPcHRpb25zLCBmaWx0ZXJlZFJ1bnNPbk9wdGlvbnMgfSBmcm9tIFwiLi4vcnVubmVyLW9wdGlvbnNcIjtcbmltcG9ydCB7IENIQU5HRVNfU0lOQ0VfTEFTVF9SRUxFQVNFIH0gZnJvbSBcIi4uL3ZlcnNpb25cIjtcblxuY29uc3QgUFVCTElCX1ZFUlNJT04gPSBcImxhdGVzdFwiO1xuY29uc3QgR0lUSFVCX1BBQ0tBR0VTX1JFR0lTVFJZID0gXCJucG0ucGtnLmdpdGh1Yi5jb21cIjtcbmNvbnN0IEFSVElGQUNUU19ET1dOTE9BRF9ESVIgPSBcImRpc3RcIjtcbmNvbnN0IEdJVEhVQl9QQUNLQUdFU19NQVZFTl9SRVBPU0lUT1JZID0gXCJodHRwczovL21hdmVuLnBrZy5naXRodWIuY29tXCI7XG5jb25zdCBHSVRIVUJfUEFDS0FHRVNfTlVHRVRfUkVQT1NJVE9SWSA9IFwiaHR0cHM6Ly9udWdldC5wa2cuZ2l0aHViLmNvbVwiO1xuY29uc3QgQVdTX0NPREVBUlRJRkFDVF9SRUdJU1RSWV9SRUdFWCA9IC8uY29kZWFydGlmYWN0LiouYW1hem9uYXdzLmNvbS87XG5jb25zdCBQVUJMSUJfVE9PTENIQUlOID0ge1xuICBqczoge30sXG4gIGphdmE6IHsgamF2YTogeyB2ZXJzaW9uOiBcIjExXCIgfSB9LFxuICBweXRob246IHsgcHl0aG9uOiB7IHZlcnNpb246IFwiMy54XCIgfSB9LFxuICBnbzogeyBnbzogeyB2ZXJzaW9uOiBcIl4xLjE4LjBcIiB9IH0sXG4gIGRvdG5ldDogeyBkb3RuZXQ6IHsgdmVyc2lvbjogXCI2LnhcIiB9IH0sXG59O1xuY29uc3QgUFVCTElTSF9KT0JfUFJFRklYID0gXCJyZWxlYXNlX1wiO1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGBQdWJsaXNoZXJgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFB1Ymxpc2hlck9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIGpvYiBJRCB0aGF0IHByb2R1Y2VzIHRoZSBidWlsZCBhcnRpZmFjdHMuIEFsbCBwdWJsaXNoIGpvYnMgd2lsbCB0YWtlIGEgZGVwZW5kZW5jeSBvbiB0aGlzIGpvYi5cbiAgICovXG4gIHJlYWRvbmx5IGJ1aWxkSm9iSWQ6IHN0cmluZztcblxuICAvKipcbiAgICogQSBHaXRIdWIgd29ya2Zsb3cgZXhwcmVzc2lvbiB1c2VkIGFzIGEgY29uZGl0aW9uIGZvciBwdWJsaXNoZXJzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGNvbmRpdGlvblxuICAgKi9cbiAgcmVhZG9ubHkgY29uZGl0aW9uPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgYXJ0aWZhY3QgdG8gZG93bmxvYWQgKGUuZy4gYGRpc3RgKS5cbiAgICpcbiAgICogVGhlIGFydGlmYWN0IGlzIGV4cGVjdGVkIHRvIGluY2x1ZGUgYSBzdWJkaXJlY3RvcnkgZm9yIGVhY2ggcmVsZWFzZSB0YXJnZXQ6XG4gICAqIGBnb2AgKEdpdEh1YiksIGBkb3RuZXRgIChOdUdldCksIGBqYXZhYCAoTWF2ZW4pLCBganNgIChucG0pLCBgcHl0aG9uYFxuICAgKi