From b5a8f8a6ab48531dc1aab20dc779db8e334529e5 Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Tue, 3 Jun 2025 15:02:54 +0200 Subject: [PATCH 01/16] Add PR upgrade tests from merge base to PR HEAD --- .../pipelines/pull-request/pr-upgrade.yml | 6 +++ .buildkite/scripts/run-pr-upgrade-tests.sh | 45 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 .buildkite/pipelines/pull-request/pr-upgrade.yml create mode 100644 .buildkite/scripts/run-pr-upgrade-tests.sh diff --git a/.buildkite/pipelines/pull-request/pr-upgrade.yml b/.buildkite/pipelines/pull-request/pr-upgrade.yml new file mode 100644 index 0000000000000..429a75a3f2a95 --- /dev/null +++ b/.buildkite/pipelines/pull-request/pr-upgrade.yml @@ -0,0 +1,6 @@ +steps: + - label: pr-upgrade + command: ".buildkite/scripts/run-pr-upgrade-tests.sh" + agents: + image: "docker.elastic.co/ci-agent-images/eck-region/buildkite-agent:1.5" + memory: "4G" diff --git a/.buildkite/scripts/run-pr-upgrade-tests.sh b/.buildkite/scripts/run-pr-upgrade-tests.sh new file mode 100644 index 0000000000000..1c5e9a345f323 --- /dev/null +++ b/.buildkite/scripts/run-pr-upgrade-tests.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# +# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +# or more contributor license agreements. Licensed under the "Elastic License +# 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side +# Public License v 1"; you may not use this file except in compliance with, at +# your election, the "Elastic License 2.0", the "GNU Affero General Public +# License v3.0 only", or the "Server Side Public License, v 1". +# + +set -euo pipefail + +if [[ -z "$BUILDKITE_PULL_REQUEST_BASE_BRANCH" ]]; then + echo "Not a pull request, skipping PR upgrade tests." + exit 0 +fi + +# Identify the merge base of the current commit (branch) and the base branch of the pull request. +# PR upgrade tests are run from the merge base to the current commit. +BASE_COMMIT=$(git merge-base $BUILDKITE_PULL_REQUEST_BASE_BRANCH $BUILDKITE_COMMIT) + +VERSION=$(sed -n 's/^elasticsearch[[:space:]]*=[[:space:]]*\(.*\)/\1/p' build-tools-internal/version.properties) + +echo "Running PR upgrade tests from $BUILDKITE_PULL_REQUEST_BASE_BRANCH [$BASE_COMMIT] to $BUILDKITE_BRANCH [$BUILDKITE_COMMIT]." + +cat < $BUILDKITE_BRANCH + command: .ci/scripts/run-gradle.sh -Dbwc.checkout.align=true -Dorg.elasticsearch.build.cache.push=true -Dignore.tests.seed -Dscan.capture-file-fingerprints -Dtests.bwc.main.version=${VERSION}-SNAPSHOT -Dtests.bwc.refspec.main=${BASE_COMMIT} bcUpgradeTest -Dtests.jvm.argline="-Des.serverless_transport=true" + timeout_in_minutes: 300 + agents: + provider: gcp + image: family/elasticsearch-ubuntu-2004 + machineType: n1-standard-32 + buildDirectory: /dev/shm/bk + preemptible: true + retry: + automatic: + - exit_status: "-1" + limit: 3 + signal_reason: none + - signal_reason: agent_stop + limit: 3 +EOF From 7888006dafd5fc2c46d0285648947525ffb12dc4 Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Thu, 5 Jun 2025 14:45:55 +0200 Subject: [PATCH 02/16] Expand bcUpgradeTask to run more test suites. Relates to ES-11904 --- modules/ingest-geoip/qa/full-cluster-restart/build.gradle | 8 ++++++++ qa/full-cluster-restart/build.gradle | 7 +++++++ qa/rolling-upgrade/build.gradle | 5 ----- x-pack/plugin/downsample/qa/mixed-cluster/build.gradle | 8 ++++++++ .../ent-search/qa/full-cluster-restart/build.gradle | 8 ++++++++ x-pack/plugin/esql/qa/server/mixed-cluster/build.gradle | 7 +++++++ x-pack/plugin/inference/qa/mixed-cluster/build.gradle | 6 ++++++ x-pack/plugin/inference/qa/rolling-upgrade/build.gradle | 7 +++++++ x-pack/plugin/security/qa/multi-cluster/build.gradle | 8 ++++++++ .../plugin/shutdown/qa/full-cluster-restart/build.gradle | 8 ++++++++ x-pack/qa/full-cluster-restart/build.gradle | 8 ++++++++ 11 files changed, 75 insertions(+), 5 deletions(-) diff --git a/modules/ingest-geoip/qa/full-cluster-restart/build.gradle b/modules/ingest-geoip/qa/full-cluster-restart/build.gradle index b6613b51ac8fc..0739ab78fa6e1 100644 --- a/modules/ingest-geoip/qa/full-cluster-restart/build.gradle +++ b/modules/ingest-geoip/qa/full-cluster-restart/build.gradle @@ -7,6 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ +import org.elasticsearch.gradle.Version import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask apply plugin: 'elasticsearch.internal-java-rest-test' @@ -24,3 +25,10 @@ buildParams.bwcVersions.withWireCompatible { bwcVersion, baseName -> systemProperty("tests.old_cluster_version", bwcVersion) } } + +tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { + // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property + usesBwcDistribution(Version.fromString("0.0.0")) + systemProperty("tests.old_cluster_version", "0.0.0") + onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } +} diff --git a/qa/full-cluster-restart/build.gradle b/qa/full-cluster-restart/build.gradle index d23267bb352fc..09c0dbb53a36b 100644 --- a/qa/full-cluster-restart/build.gradle +++ b/qa/full-cluster-restart/build.gradle @@ -28,6 +28,13 @@ tasks.register("luceneBwcTest", StandaloneRestIntegTestTask) { onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } } +tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { + // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property + usesBwcDistribution(Version.fromString("0.0.0")) + systemProperty("tests.old_cluster_version", "0.0.0") + onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } +} + tasks.withType(Test).configureEach { // CI doesn't like it when there's multiple clusters running at once maxParallelForks = 1 diff --git a/qa/rolling-upgrade/build.gradle b/qa/rolling-upgrade/build.gradle index 9a2fb22da5e39..d0eacd8689ec4 100644 --- a/qa/rolling-upgrade/build.gradle +++ b/qa/rolling-upgrade/build.gradle @@ -31,11 +31,6 @@ tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { usesBwcDistribution(Version.fromString("0.0.0")) systemProperty("tests.old_cluster_version", "0.0.0") onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } - filter { - // filter tests initially for quicker iterations - // TODO remove once expanding the test set to other modules - includeTestsMatching("org.elasticsearch.upgrades.IndexingIT") - } } tasks.withType(Test).configureEach { diff --git a/x-pack/plugin/downsample/qa/mixed-cluster/build.gradle b/x-pack/plugin/downsample/qa/mixed-cluster/build.gradle index 2cf2f602cff46..63d5096389a9c 100644 --- a/x-pack/plugin/downsample/qa/mixed-cluster/build.gradle +++ b/x-pack/plugin/downsample/qa/mixed-cluster/build.gradle @@ -5,6 +5,7 @@ * 2.0. */ +import org.elasticsearch.gradle.Version import org.elasticsearch.gradle.VersionProperties import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask @@ -43,6 +44,13 @@ buildParams.bwcVersions.withWireCompatible(supportedVersion) { bwcVersion, baseN } } +tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { + // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property + usesBwcDistribution(Version.fromString("0.0.0")) + systemProperty("tests.old_cluster_version", "0.0.0") + onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } +} + tasks.named("yamlRestTest") { enabled = false } diff --git a/x-pack/plugin/ent-search/qa/full-cluster-restart/build.gradle b/x-pack/plugin/ent-search/qa/full-cluster-restart/build.gradle index 1e1973a118074..0befb8ec5df22 100644 --- a/x-pack/plugin/ent-search/qa/full-cluster-restart/build.gradle +++ b/x-pack/plugin/ent-search/qa/full-cluster-restart/build.gradle @@ -5,6 +5,7 @@ * 2.0. */ +import org.elasticsearch.gradle.Version import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask apply plugin: 'elasticsearch.internal-java-rest-test' @@ -22,3 +23,10 @@ buildParams.bwcVersions.withWireCompatible(v -> v.after("8.8.0")) { bwcVersion, systemProperty("tests.old_cluster_version", bwcVersion) } } + +tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { + // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property + usesBwcDistribution(Version.fromString("0.0.0")) + systemProperty("tests.old_cluster_version", "0.0.0") + onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } +} diff --git a/x-pack/plugin/esql/qa/server/mixed-cluster/build.gradle b/x-pack/plugin/esql/qa/server/mixed-cluster/build.gradle index 321488c8c6c17..0c8767c4ac295 100644 --- a/x-pack/plugin/esql/qa/server/mixed-cluster/build.gradle +++ b/x-pack/plugin/esql/qa/server/mixed-cluster/build.gradle @@ -62,6 +62,13 @@ buildParams.bwcVersions.withWireCompatible(supportedVersion) { bwcVersion, baseN } } +tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { + // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property + usesBwcDistribution(Version.fromString("0.0.0")) + systemProperty("tests.old_cluster_version", "0.0.0") + onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } +} + tasks.named("yamlRestTest") { enabled = false } diff --git a/x-pack/plugin/inference/qa/mixed-cluster/build.gradle b/x-pack/plugin/inference/qa/mixed-cluster/build.gradle index 0f8c732154e85..3c5f5fbdb5b9d 100644 --- a/x-pack/plugin/inference/qa/mixed-cluster/build.gradle +++ b/x-pack/plugin/inference/qa/mixed-cluster/build.gradle @@ -38,3 +38,9 @@ buildParams.bwcVersions.withWireCompatible(supportedVersion) { bwcVersion, baseN } } +tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { + // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property + usesBwcDistribution(Version.fromString("0.0.0")) + systemProperty("tests.old_cluster_version", "0.0.0") + onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } +} diff --git a/x-pack/plugin/inference/qa/rolling-upgrade/build.gradle b/x-pack/plugin/inference/qa/rolling-upgrade/build.gradle index 214d775b46236..e656d3b9fd233 100644 --- a/x-pack/plugin/inference/qa/rolling-upgrade/build.gradle +++ b/x-pack/plugin/inference/qa/rolling-upgrade/build.gradle @@ -5,6 +5,7 @@ * 2.0. */ +import org.elasticsearch.gradle.Version import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask apply plugin: 'elasticsearch.internal-java-rest-test' @@ -27,3 +28,9 @@ buildParams.bwcVersions.withWireCompatible(v -> v.after("8.11.0")) { bwcVersion, } } +tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { + // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property + usesBwcDistribution(Version.fromString("0.0.0")) + systemProperty("tests.old_cluster_version", "0.0.0") + onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } +} diff --git a/x-pack/plugin/security/qa/multi-cluster/build.gradle b/x-pack/plugin/security/qa/multi-cluster/build.gradle index f4eee4ef46c02..a2f10f956098f 100644 --- a/x-pack/plugin/security/qa/multi-cluster/build.gradle +++ b/x-pack/plugin/security/qa/multi-cluster/build.gradle @@ -5,6 +5,7 @@ * 2.0. */ +import org.elasticsearch.gradle.Version import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask apply plugin: 'elasticsearch.internal-java-rest-test' @@ -43,3 +44,10 @@ buildParams.bwcVersions.withWireCompatible() { bwcVersion, baseName -> include '**/RemoteClusterSecurityBWCToRCS2ClusterRestIT.class' } } + +tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { + // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property + usesBwcDistribution(Version.fromString("0.0.0")) + systemProperty("tests.old_cluster_version", "0.0.0") + onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } +} diff --git a/x-pack/plugin/shutdown/qa/full-cluster-restart/build.gradle b/x-pack/plugin/shutdown/qa/full-cluster-restart/build.gradle index 60b0b372ba14c..306266742d721 100644 --- a/x-pack/plugin/shutdown/qa/full-cluster-restart/build.gradle +++ b/x-pack/plugin/shutdown/qa/full-cluster-restart/build.gradle @@ -5,6 +5,7 @@ * 2.0. */ +import org.elasticsearch.gradle.Version import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask apply plugin: 'elasticsearch.internal-java-rest-test' @@ -25,3 +26,10 @@ buildParams.bwcVersions.withIndexCompatible { bwcVersion, baseName -> systemProperty("tests.old_cluster_version", bwcVersion) } } + +tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { + // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property + usesBwcDistribution(Version.fromString("0.0.0")) + systemProperty("tests.old_cluster_version", "0.0.0") + onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } +} diff --git a/x-pack/qa/full-cluster-restart/build.gradle b/x-pack/qa/full-cluster-restart/build.gradle index ee0955c6db082..eeeaa8a370c09 100644 --- a/x-pack/qa/full-cluster-restart/build.gradle +++ b/x-pack/qa/full-cluster-restart/build.gradle @@ -5,6 +5,7 @@ * 2.0. */ +import org.elasticsearch.gradle.Version import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask apply plugin: 'elasticsearch.internal-java-rest-test' @@ -28,3 +29,10 @@ buildParams.bwcVersions.withIndexCompatible { bwcVersion, baseName -> maxParallelForks = 1 } } + +tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { + // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property + usesBwcDistribution(Version.fromString("0.0.0")) + systemProperty("tests.old_cluster_version", "0.0.0") + onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } +} From 43011688c4efee098b4749d5afbdd7c69b392f4a Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Thu, 5 Jun 2025 16:06:59 +0200 Subject: [PATCH 03/16] remove from downsample, only contains yaml rest tests --- x-pack/plugin/downsample/qa/mixed-cluster/build.gradle | 8 -------- 1 file changed, 8 deletions(-) diff --git a/x-pack/plugin/downsample/qa/mixed-cluster/build.gradle b/x-pack/plugin/downsample/qa/mixed-cluster/build.gradle index 63d5096389a9c..2cf2f602cff46 100644 --- a/x-pack/plugin/downsample/qa/mixed-cluster/build.gradle +++ b/x-pack/plugin/downsample/qa/mixed-cluster/build.gradle @@ -5,7 +5,6 @@ * 2.0. */ -import org.elasticsearch.gradle.Version import org.elasticsearch.gradle.VersionProperties import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask @@ -44,13 +43,6 @@ buildParams.bwcVersions.withWireCompatible(supportedVersion) { bwcVersion, baseN } } -tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { - // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property - usesBwcDistribution(Version.fromString("0.0.0")) - systemProperty("tests.old_cluster_version", "0.0.0") - onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } -} - tasks.named("yamlRestTest") { enabled = false } From dc4c9695c9e326fddbe6bdbfb0a7a4dae8ccabc1 Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Fri, 6 Jun 2025 12:28:32 +0200 Subject: [PATCH 04/16] support security for BC upgrade testing which use the magic version number 0.0.0 --- .../elasticsearch/test/cluster/local/LocalClusterSpec.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpec.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpec.java index cccf2a95234c9..633381cefbbbb 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpec.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpec.java @@ -212,7 +212,12 @@ public Path getConfigDir() { } public boolean isSecurityEnabled() { - return Boolean.parseBoolean(getSetting("xpack.security.enabled", getVersion().onOrAfter("8.0.0") ? "true" : "false")); + return Boolean.parseBoolean( + getSetting( + "xpack.security.enabled", + getVersion().equals(Version.fromString("0.0.0")) || getVersion().onOrAfter("8.0.0") ? "true" : "false" + ) + ); } public boolean isRemoteClusterServerEnabled() { From e49ca270fca6cc9824709edb76502be26bfa7849 Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Fri, 6 Jun 2025 12:45:26 +0200 Subject: [PATCH 05/16] support security for BC upgrade testing which use the magic version number 0.0.0 --- .../elasticsearch/test/cluster/local/LocalClusterSpec.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpec.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpec.java index cccf2a95234c9..633381cefbbbb 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpec.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/LocalClusterSpec.java @@ -212,7 +212,12 @@ public Path getConfigDir() { } public boolean isSecurityEnabled() { - return Boolean.parseBoolean(getSetting("xpack.security.enabled", getVersion().onOrAfter("8.0.0") ? "true" : "false")); + return Boolean.parseBoolean( + getSetting( + "xpack.security.enabled", + getVersion().equals(Version.fromString("0.0.0")) || getVersion().onOrAfter("8.0.0") ? "true" : "false" + ) + ); } public boolean isRemoteClusterServerEnabled() { From c97a8190d183e449169dce0a58966c1fe86c6213 Mon Sep 17 00:00:00 2001 From: Moritz Mack Date: Fri, 6 Jun 2025 16:14:55 +0200 Subject: [PATCH 06/16] exclude some likely incompatible tests --- qa/rolling-upgrade/build.gradle | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/qa/rolling-upgrade/build.gradle b/qa/rolling-upgrade/build.gradle index d0eacd8689ec4..f253d9a056920 100644 --- a/qa/rolling-upgrade/build.gradle +++ b/qa/rolling-upgrade/build.gradle @@ -31,6 +31,13 @@ tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { usesBwcDistribution(Version.fromString("0.0.0")) systemProperty("tests.old_cluster_version", "0.0.0") onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } + + filter { + // TODO (ES-12010) investigate these test failures + excludeTestsMatching("org.elasticsearch.upgrades.FeatureUpgradeIT") + excludeTestsMatching("org.elasticsearch.upgrades.LogsUsageRollingUpgradeIT") + excludeTestsMatching("org.elasticsearch.upgrades.SnapshotBasedRecoveryIT") + } } tasks.withType(Test).configureEach { From 489fcef403ffe4b402d62531717f8147c67b381c Mon Sep 17 00:00:00 2001 From: Lorenzo Dematte Date: Tue, 10 Jun 2025 12:06:36 +0200 Subject: [PATCH 07/16] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit e6b8a642102dae6f381c2f42e1d7ad950da2910c Author: Lorenzo Dematte Date: Tue Jun 10 12:02:16 2025 +0200 PR comments commit ad0902e8e8c00d723e771f68513ead6609a3866e Author: Moritz Mack Date: Fri Jun 6 13:33:37 2025 +0200 Update ReproduceInfoPrinter to correctly print a reproduction for lucene / BC upgrade tests. Relates to ES-12005 commit 78b4168801f780fc0e0b069bd71bf92b80e7abe6 Author: Alexander Spies Date: Fri Jun 6 11:37:53 2025 +0200 ESQL: Throw ISE instead of IAE for illegal block in page (#128960) IAE gets reported as a 400 status code, but that's inappropriate when inconsistent pages are always bugs, and should be reported with a 500. Throw ISE instead. commit 29e68bd9a99af216583b271b0c53624514272d9e Author: Aurélien FOUCRET Date: Fri Jun 6 11:24:23 2025 +0200 [ES|QL] Fix test releases for telemetry. (#128971) commit 1a76bc2dc80dec3b9115efc5dc5a14271461477a Author: Bogdan Pintea Date: Fri Jun 6 11:01:49 2025 +0200 ESQL: Workaround for RLike handling of empty lang pattern (#128895) Lucene's `org.apache.lucene.util.automaton.Operations#getSingleton` fails with an Automaton for a `REGEXP_EMPTY` `RegExp`. This adds a workaround for that, to check the type of automaton before calling into that failing method. Closes #128813 commit e24fd32c355bb98cb24e479d104d2dcf97a509ea Author: Aurélien FOUCRET Date: Fri Jun 6 10:25:28 2025 +0200 [ES|QL] Enable the completion command as a tech preview feature (#128948) commit 3f037751b42c16825ee48eff159c1f919d4422f0 Author: Niels Bauman <33722607+nielsbauman@users.noreply.github.com> Date: Fri Jun 6 09:00:24 2025 +0200 Remove non-test usages of `Metadata.Builder#putCustom` (#128801) This removes all non-test usages of ``` Metadata.Builder.putCustom(String type, ProjectCustom custom) ``` And replaces it with appropriate calls to the equivalent method on `ProjectMetadata.Builder`. In most cases this _does not_ make the code project aware, but does reduce the number of deprecated methods in use. commit 330d1275cfb2538d04a4c05f894d108b78407696 Author: Niels Bauman <33722607+nielsbauman@users.noreply.github.com> Date: Fri Jun 6 08:07:59 2025 +0200 Make utility methods in `IndexLifecycleTransition` project-aware (#128930) Modifies the methods to work with a project scope rather than a cluster scope. This is part of an iterative process to make ILM project-aware. commit 1b5720d5e2aca0a2da0f1cfaa975449bfbcca251 Author: Aurélien FOUCRET Date: Fri Jun 6 07:50:52 2025 +0200 [ES|QL] Fix test releases for LookupJoinTypesIT. (#128985) commit 40cf2d3560fbc41df208211c1492cda610e8fca2 Author: Tim Vernum Date: Fri Jun 6 13:09:31 2025 +1000 Add "extension" attribute validation to IdP SPs (#128805) This extends the change from #128176 to validate the "custom attributes" on a per Service Provider basis. Each Service Provider (whether registered or wildcard based) has a field "attributes.extensions" which is a list of attribute names that may be provided by the caller of "/_idp/saml/init". Service Providers that have not be configured with extension attributes will reject any custom attributes in SAML init. This necessitates a new field in the service provider index (but only if the new `extensions` attribute is set). The template has been updated, but there is no data migration because the `saml-service-provider` index does not exist in any of the environments into which we wish to deploy this change. commit 496fb2d5a4fc07a2763be06f880f2216adca7aeb Author: Jordan Powers Date: Thu Jun 5 19:50:09 2025 -0700 Skip UTF8 to UTF16 conversion during document indexing (#126492) When parsing documents, we receive the document as UTF-8 encoded data which we then parse and convert the fields to java-native UTF-16 encoded Strings. We then convert these strings back to UTF-8 for storage in lucene. This patch skips the redundant conversion, instead passing lucene a direct reference to the received UTF-8 bytes when possible. commit c34f8b6d3e61ec9c84df49bf2c34f716f29402de Author: Tim Vernum Date: Fri Jun 6 12:03:25 2025 +1000 Improve cache invalidation in IdP SP cache (#128890) The Identity Provider's Service Provider cache had two issues: 1. It checked for identity based on sequence numbers, but didn't include the `seq_no_primary_term` parameter on searches, which means the sequence would always by `-2` 2. It didn't track whether the index was deleted, which means it could be caching values from an old version of the index This commit fixes both of these issues. In practice neither issue was a problem because there are no deployments that use index-based service providers, however the 2nd issue did cause some challenges for testing. commit 923f029745cc0231494e195c1ba766c9091583f8 Author: Nhat Nguyen Date: Thu Jun 5 18:09:58 2025 -0700 Fix block loader with missing ignored source (#129006) We miss appending null when ignored_source is not available. Our randomized tests already cover this case, but we do not check it when loading fields. I labelled this non-issue for an unreleased bug. Closes #128959 Relates #119546 commit 0f8178a2a39018884b375f19c559659377e7fc91 Author: Bogdan Pintea Date: Fri Jun 6 02:02:24 2025 +0200 ESQL: Forward port 8.19 RegexMatch serialization change version (#128979) Fwd port ESQL_REGEX_MATCH_WITH_CASE_INSENSITIVITY_8_19. Related: #128919. commit ee716f11b9f94abf97affb638836c489e6ea76c8 Author: Simon Chase Date: Thu Jun 5 15:20:08 2025 -0700 transport: edit TransportConnectionListener for close exceptions (#129015) The TransportConnectionListener interface has previously included the Transport.Connection being closed and unregistered in its onNodeDisconnected callback. This is not in use, and can be removed as it is also available in the onConnectionClosed callback. It is being replaced with a Nullable exception that caused the close. This is being used in pending work (ES-11448) to differentiate network issues from node restarts. Closes ES-12007 commit aceaf23130e12621103042448374106182870c72 Merge: f18f4ee9d0d 159c57f0de3 Author: elasticsearchmachine Date: Thu Jun 5 19:27:54 2025 +0000 Merge patch/serverless-fix into main commit 159c57f0de3b0fa618bd79c9ecd00dca71a8e2bb Author: Rene Groeschke Date: Tue Jun 3 11:56:27 2025 +0200 Prepare serverless patch including #128784 #128740 (#128807) * Change default for vector.rescoring.directio to false (#128784) On serverless (and potentially elsewhere), direct IO is not available, which can cause BBQ shards to fail to read with org.apache.lucene.CorruptIndexException when this setting is true. * Optimize sparse vector stats collection (#128740) This change improves the performance of sparse vector statistics gathering by using the document count of terms directly, rather than relying on the field name field to compute stats. By avoiding per-term disk/network reads and instead leveraging statistics already loaded into leaf readers at index opening, we expect to significantly reduce overhead. Relates to #128583 --------- Co-authored-by: Dave Pifke Co-authored-by: Jim Ferenczi --- .../xcontent/OptimizedTextBenchmark.java | 108 + docs/changelog/128805.yaml | 5 + docs/changelog/128890.yaml | 5 + docs/changelog/128895.yaml | 6 + docs/changelog/128948.yaml | 6 + docs/changelog/128960.yaml | 5 + .../xcontent/provider/json/ESJsonFactory.java | 74 + .../provider/json/ESJsonFactoryBuilder.java | 20 + .../provider/json/ESUTF8StreamJsonParser.java | 118 ++ .../provider/json/JsonXContentImpl.java | 3 +- .../provider/json/JsonXContentParser.java | 16 + .../provider/json/ESJsonFactoryTests.java | 70 + .../json/ESUTF8StreamJsonParserTests.java | 161 ++ .../xcontent/FilterXContentParser.java | 8 + .../xcontent/XContentParser.java | 4 + .../xcontent/XContentString.java | 3 +- .../support/AbstractXContentParser.java | 15 + .../org/elasticsearch/xcontent/TextTests.java | 4 +- ...portDeleteDatabaseConfigurationAction.java | 12 +- ...ansportPutDatabaseConfigurationAction.java | 10 +- .../org/elasticsearch/TransportVersions.java | 3 +- .../coordination/FollowersChecker.java | 4 +- .../cluster/coordination/LeaderChecker.java | 3 +- .../cluster/metadata/Metadata.java | 1 + .../index/mapper/CompletionFieldMapper.java | 10 + .../mapper/DotExpandingXContentParser.java | 9 + .../FallbackSyntheticSourceBlockLoader.java | 1 + .../index/mapper/GeoPointFieldMapper.java | 7 + .../index/mapper/KeywordFieldMapper.java | 32 +- .../blobstore/BlobStoreRepository.java | 15 +- .../elasticsearch/script/ScriptService.java | 17 +- .../snapshots/RestoreService.java | 8 +- .../snapshots/SnapshotsService.java | 13 +- .../transport/ClusterConnectionManager.java | 25 +- .../transport/ConnectionManager.java | 4 +- .../transport/RemoteConnectionManager.java | 2 +- .../transport/RemoteConnectionStrategy.java | 3 +- .../TransportConnectionListener.java | 3 +- .../search/TransportSearchActionTests.java | 5 +- .../cluster/NodeConnectionsServiceTests.java | 3 +- .../common/xcontent/BaseXContentTestCase.java | 16 + .../ClusterConnectionManagerTests.java | 7 +- .../index/mapper/BlockLoaderTestRunner.java | 14 +- .../blobstore/BlobStoreTestUtil.java | 17 +- .../junit/listeners/ReproduceInfoPrinter.java | 8 +- .../AbstractSimpleTransportTestCase.java | 6 +- .../ParameterizableYamlXContentParser.java | 11 + .../ccr/action/AutoFollowCoordinator.java | 15 +- ...nsportActivateAutoFollowPatternAction.java | 8 +- .../TransportPutAutoFollowPatternAction.java | 8 +- .../core/ilm/OperationModeUpdateTask.java | 24 +- .../idp/saml-service-provider-template.json | 3 + .../regex/AbstractStringPattern.java | 6 +- .../predicate/regex/StringPatternTests.java | 22 +- .../xpack/esql/core/util/TestUtils.java | 4 +- .../org/elasticsearch/compute/data/Page.java | 2 +- .../xpack/esql/qa/rest/RestEsqlTestCase.java | 40 + .../src/main/resources/where-like.csv-spec | 10 + .../xpack/esql/action/LookupJoinTypesIT.java | 8 + .../esql/src/main/antlr/EsqlBaseLexer.tokens | 35 +- .../esql/src/main/antlr/EsqlBaseParser.g4 | 4 +- .../esql/src/main/antlr/EsqlBaseParser.tokens | 35 +- .../esql/src/main/antlr/lexer/Expression.g4 | 2 +- .../xpack/esql/action/EsqlCapabilities.java | 7 +- .../scalar/string/regex/RegexMatch.java | 29 +- .../xpack/esql/parser/EsqlBaseLexer.interp | 8 +- .../xpack/esql/parser/EsqlBaseLexer.java | 1777 ++++++++--------- .../xpack/esql/parser/EsqlBaseParser.interp | 6 +- .../xpack/esql/parser/EsqlBaseParser.java | 1751 ++++++++-------- .../xpack/esql/analysis/AnalyzerTests.java | 18 - .../GrammarInDevelopmentParsingTests.java | 4 - .../esql/parser/StatementParserTests.java | 12 - .../idp/IdentityProviderAuthenticationIT.java | 50 +- .../xpack/idp/IdentityProviderPlugin.java | 2 + ...lAuthenticationResponseMessageBuilder.java | 29 +- .../idp/saml/sp/SamlServiceProvider.java | 8 +- .../saml/sp/SamlServiceProviderDocument.java | 28 +- .../saml/sp/SamlServiceProviderFactory.java | 3 +- .../idp/saml/sp/SamlServiceProviderIndex.java | 46 +- .../saml/sp/SamlServiceProviderResolver.java | 20 +- ...rtSamlInitiateSingleSignOnActionTests.java | 3 +- ...enticationResponseMessageBuilderTests.java | 44 +- .../sp/SamlServiceProviderResolverTests.java | 35 + .../WildcardServiceProviderResolverTests.java | 11 +- .../xpack/ilm/ExecuteStepsUpdateTask.java | 11 +- .../xpack/ilm/IndexLifecycleRunner.java | 5 +- .../xpack/ilm/IndexLifecycleService.java | 8 +- .../xpack/ilm/IndexLifecycleTransition.java | 71 +- .../xpack/ilm/MoveToErrorStepUpdateTask.java | 7 +- .../xpack/ilm/SetStepInfoUpdateTask.java | 7 +- ...sportRemoveIndexLifecyclePolicyAction.java | 4 +- .../ilm/action/TransportRetryAction.java | 4 +- .../elasticsearch/xpack/ilm/package-info.java | 2 +- .../xpack/ilm/IndexLifecycleRunnerTests.java | 34 - .../ilm/IndexLifecycleTransitionTests.java | 225 +-- .../task/MigrationResultsUpdateTask.java | 8 +- .../TransportDeleteTrainedModelAction.java | 8 +- ...ransportDeleteTrainedModelAliasAction.java | 8 +- .../TransportPutTrainedModelAliasAction.java | 6 +- .../action/TransportSetUpgradeModeAction.java | 7 +- .../TrainedModelAssignmentClusterService.java | 12 +- .../TrainedModelCacheMetadataService.java | 7 +- .../xpack/slm/SnapshotLifecycleTask.java | 20 +- .../slm/UpdateSnapshotLifecycleStatsTask.java | 7 +- ...ransportDeleteSnapshotLifecycleAction.java | 23 +- .../TransportPutSnapshotLifecycleAction.java | 17 +- .../rest-api-spec/test/esql/60_usage.yml | 2 +- ...ransportSetTransformUpgradeModeAction.java | 6 +- .../TransportWatcherServiceAction.java | 8 +- 109 files changed, 3231 insertions(+), 2303 deletions(-) create mode 100644 benchmarks/src/main/java/org/elasticsearch/benchmark/xcontent/OptimizedTextBenchmark.java create mode 100644 docs/changelog/128805.yaml create mode 100644 docs/changelog/128890.yaml create mode 100644 docs/changelog/128895.yaml create mode 100644 docs/changelog/128948.yaml create mode 100644 docs/changelog/128960.yaml create mode 100644 libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/ESJsonFactory.java create mode 100644 libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/ESJsonFactoryBuilder.java create mode 100644 libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/ESUTF8StreamJsonParser.java create mode 100644 libs/x-content/impl/src/test/java/org/elasticsearch/xcontent/provider/json/ESJsonFactoryTests.java create mode 100644 libs/x-content/impl/src/test/java/org/elasticsearch/xcontent/provider/json/ESUTF8StreamJsonParserTests.java diff --git a/benchmarks/src/main/java/org/elasticsearch/benchmark/xcontent/OptimizedTextBenchmark.java b/benchmarks/src/main/java/org/elasticsearch/benchmark/xcontent/OptimizedTextBenchmark.java new file mode 100644 index 0000000000000..9984205445fcc --- /dev/null +++ b/benchmarks/src/main/java/org/elasticsearch/benchmark/xcontent/OptimizedTextBenchmark.java @@ -0,0 +1,108 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.benchmark.xcontent; + +import org.elasticsearch.benchmark.index.mapper.MapperServiceFactory; +import org.elasticsearch.common.UUIDs; +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.logging.LogConfigurator; +import org.elasticsearch.index.mapper.MapperService; +import org.elasticsearch.index.mapper.SourceToParse; +import org.elasticsearch.xcontent.XContentBuilder; +import org.elasticsearch.xcontent.XContentFactory; +import org.elasticsearch.xcontent.XContentType; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Threads; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +import java.io.IOException; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** + * Benchmark to measure indexing performance of keyword fields. Used to measure performance impact of skipping + * UTF-8 to UTF-16 conversion during document parsing. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +@Fork(1) +@Threads(1) +@Warmup(iterations = 1) +@Measurement(iterations = 5) +public class OptimizedTextBenchmark { + static { + // For Elasticsearch900Lucene101Codec: + LogConfigurator.loadLog4jPlugins(); + LogConfigurator.configureESLogging(); + LogConfigurator.setNodeName("test"); + } + + /** + * Total number of documents to index. + */ + @Param("1048576") + private int nDocs; + + private MapperService mapperService; + private SourceToParse[] sources; + + private String randomValue(int length) { + final String CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + Random random = new Random(); + StringBuilder builder = new StringBuilder(length); + for (int i = 0; i < length; i++) { + builder.append(CHARS.charAt(random.nextInt(CHARS.length()))); + } + return builder.toString(); + } + + @Setup(Level.Trial) + public void setup() throws IOException { + mapperService = MapperServiceFactory.create(""" + { + "_doc": { + "dynamic": false, + "properties": { + "field": { + "type": "keyword" + } + } + } + } + """); + + sources = new SourceToParse[nDocs]; + for (int i = 0; i < nDocs; i++) { + XContentBuilder b = XContentFactory.jsonBuilder(); + b.startObject().field("field", randomValue(8)).endObject(); + sources[i] = new SourceToParse(UUIDs.randomBase64UUID(), BytesReference.bytes(b), XContentType.JSON); + } + } + + @Benchmark + public void indexDocuments(final Blackhole bh) { + final var mapper = mapperService.documentMapper(); + for (int i = 0; i < nDocs; i++) { + bh.consume(mapper.parse(sources[i])); + } + } +} diff --git a/docs/changelog/128805.yaml b/docs/changelog/128805.yaml new file mode 100644 index 0000000000000..6236649e17aa8 --- /dev/null +++ b/docs/changelog/128805.yaml @@ -0,0 +1,5 @@ +pr: 128805 +summary: Add "extension" attribute validation to IdP SPs +area: IdentityProvider +type: enhancement +issues: [] diff --git a/docs/changelog/128890.yaml b/docs/changelog/128890.yaml new file mode 100644 index 0000000000000..79fa83c3e55e4 --- /dev/null +++ b/docs/changelog/128890.yaml @@ -0,0 +1,5 @@ +pr: 128890 +summary: Improve cache invalidation in IdP SP cache +area: IdentityProvider +type: bug +issues: [] diff --git a/docs/changelog/128895.yaml b/docs/changelog/128895.yaml new file mode 100644 index 0000000000000..a1487e47ebd36 --- /dev/null +++ b/docs/changelog/128895.yaml @@ -0,0 +1,6 @@ +pr: 128895 +summary: Workaround for RLike handling of empty lang pattern +area: ES|QL +type: bug +issues: + - 128813 diff --git a/docs/changelog/128948.yaml b/docs/changelog/128948.yaml new file mode 100644 index 0000000000000..a922104757083 --- /dev/null +++ b/docs/changelog/128948.yaml @@ -0,0 +1,6 @@ +pr: 128948 +summary: ES|QL - Add COMPLETION command as a tech preview feature +area: ES|QL +type: feature +issues: +- 124405 diff --git a/docs/changelog/128960.yaml b/docs/changelog/128960.yaml new file mode 100644 index 0000000000000..3721b34894548 --- /dev/null +++ b/docs/changelog/128960.yaml @@ -0,0 +1,5 @@ +pr: 128960 +summary: Throw ISE instead of IAE for illegal block in page +area: ES|QL +type: bug +issues: [] diff --git a/libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/ESJsonFactory.java b/libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/ESJsonFactory.java new file mode 100644 index 0000000000000..1ad4941dab51e --- /dev/null +++ b/libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/ESJsonFactory.java @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.xcontent.provider.json; + +import com.fasterxml.jackson.core.JsonEncoding; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonFactoryBuilder; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.io.IOContext; +import com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper; +import com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer; + +import java.io.IOException; + +public class ESJsonFactory extends JsonFactory { + ESJsonFactory(JsonFactoryBuilder b) { + super(b); + } + + @Override + protected JsonParser _createParser(byte[] data, int offset, int len, IOContext ctxt) throws IOException { + if (len > 0 + && Feature.CHARSET_DETECTION.enabledIn(_factoryFeatures) + && Feature.CANONICALIZE_FIELD_NAMES.enabledIn(_factoryFeatures)) { + var bootstrap = new ByteSourceJsonBootstrapper(ctxt, data, offset, len); + var encoding = bootstrap.detectEncoding(); + if (encoding == JsonEncoding.UTF8) { + boolean invalidBom = false; + int ptr = offset; + // Skip over the BOM if present + if ((data[ptr] & 0xFF) == 0xEF) { + if (len < 3) { + invalidBom = true; + } else if ((data[ptr + 1] & 0xFF) != 0xBB) { + invalidBom = true; + } else if ((data[ptr + 2] & 0xFF) != 0xBF) { + invalidBom = true; + } else { + ptr += 3; + } + } + if (invalidBom == false) { + ByteQuadsCanonicalizer can = _byteSymbolCanonicalizer.makeChild(_factoryFeatures); + return new ESUTF8StreamJsonParser( + ctxt, + _parserFeatures, + null, + _objectCodec, + can, + data, + ptr, + offset + len, + ptr - offset, + false + ); + } + } + } + return new ByteSourceJsonBootstrapper(ctxt, data, offset, len).constructParser( + _parserFeatures, + _objectCodec, + _byteSymbolCanonicalizer, + _rootCharSymbols, + _factoryFeatures + ); + } +} diff --git a/libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/ESJsonFactoryBuilder.java b/libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/ESJsonFactoryBuilder.java new file mode 100644 index 0000000000000..2bb6905fe19d9 --- /dev/null +++ b/libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/ESJsonFactoryBuilder.java @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.xcontent.provider.json; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonFactoryBuilder; + +public class ESJsonFactoryBuilder extends JsonFactoryBuilder { + @Override + public JsonFactory build() { + return new ESJsonFactory(this); + } +} diff --git a/libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/ESUTF8StreamJsonParser.java b/libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/ESUTF8StreamJsonParser.java new file mode 100644 index 0000000000000..5f91036dee96e --- /dev/null +++ b/libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/ESUTF8StreamJsonParser.java @@ -0,0 +1,118 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.xcontent.provider.json; + +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.ObjectCodec; +import com.fasterxml.jackson.core.SerializableString; +import com.fasterxml.jackson.core.io.IOContext; +import com.fasterxml.jackson.core.json.UTF8StreamJsonParser; +import com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer; + +import org.elasticsearch.xcontent.Text; +import org.elasticsearch.xcontent.XContentString; + +import java.io.IOException; +import java.io.InputStream; + +public class ESUTF8StreamJsonParser extends UTF8StreamJsonParser { + protected int stringEnd = -1; + + public ESUTF8StreamJsonParser( + IOContext ctxt, + int features, + InputStream in, + ObjectCodec codec, + ByteQuadsCanonicalizer sym, + byte[] inputBuffer, + int start, + int end, + int bytesPreProcessed, + boolean bufferRecyclable + ) { + super(ctxt, features, in, codec, sym, inputBuffer, start, end, bytesPreProcessed, bufferRecyclable); + } + + /** + * Method that will try to get underlying UTF-8 encoded bytes of the current string token. + * This is only a best-effort attempt; if there is some reason the bytes cannot be retrieved, this method will return null. + * Currently, this is only implemented for ascii-only strings that do not contain escaped characters. + */ + public Text getValueAsText() throws IOException { + if (_currToken == JsonToken.VALUE_STRING && _tokenIncomplete) { + if (stringEnd > 0) { + final int len = stringEnd - 1 - _inputPtr; + // For now, we can use `len` for `stringLength` because we only support ascii-encoded unescaped strings, + // which means each character uses exactly 1 byte. + return new Text(new XContentString.UTF8Bytes(_inputBuffer, _inputPtr, len), len); + } + return _finishAndReturnText(); + } + return null; + } + + protected Text _finishAndReturnText() throws IOException { + int ptr = _inputPtr; + if (ptr >= _inputEnd) { + _loadMoreGuaranteed(); + ptr = _inputPtr; + } + + int startPtr = ptr; + final int[] codes = INPUT_CODES_UTF8; + final int max = _inputEnd; + final byte[] inputBuffer = _inputBuffer; + while (ptr < max) { + int c = inputBuffer[ptr] & 0xFF; + if (codes[c] != 0) { + if (c == INT_QUOTE) { + stringEnd = ptr + 1; + final int len = ptr - startPtr; + // For now, we can use `len` for `stringLength` because we only support ascii-encoded unescaped strings, + // which means each character uses exactly 1 byte. + return new Text(new XContentString.UTF8Bytes(inputBuffer, startPtr, len), len); + } + return null; + } + ++ptr; + } + return null; + } + + @Override + public JsonToken nextToken() throws IOException { + if (_currToken == JsonToken.VALUE_STRING && _tokenIncomplete && stringEnd > 0) { + _inputPtr = stringEnd; + _tokenIncomplete = false; + } + stringEnd = -1; + return super.nextToken(); + } + + @Override + public boolean nextFieldName(SerializableString str) throws IOException { + if (_currToken == JsonToken.VALUE_STRING && _tokenIncomplete && stringEnd > 0) { + _inputPtr = stringEnd; + _tokenIncomplete = false; + } + stringEnd = -1; + return super.nextFieldName(str); + } + + @Override + public String nextFieldName() throws IOException { + if (_currToken == JsonToken.VALUE_STRING && _tokenIncomplete && stringEnd > 0) { + _inputPtr = stringEnd; + _tokenIncomplete = false; + } + stringEnd = -1; + return super.nextFieldName(); + } +} diff --git a/libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/JsonXContentImpl.java b/libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/JsonXContentImpl.java index 7f52467caf49b..067985b404f3e 100644 --- a/libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/JsonXContentImpl.java +++ b/libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/JsonXContentImpl.java @@ -11,7 +11,6 @@ import com.fasterxml.jackson.core.JsonEncoding; import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonFactoryBuilder; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; @@ -47,7 +46,7 @@ public static final XContent jsonXContent() { } static { - jsonFactory = XContentImplUtils.configure(new JsonFactoryBuilder()); + jsonFactory = XContentImplUtils.configure(new ESJsonFactoryBuilder()); jsonFactory.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, true); jsonFactory.configure(JsonParser.Feature.ALLOW_COMMENTS, true); jsonFactory.configure(JsonFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW, false); // this trips on many mappings now... diff --git a/libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/JsonXContentParser.java b/libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/JsonXContentParser.java index 38ef8bc2e4ef0..3471fd362f88e 100644 --- a/libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/JsonXContentParser.java +++ b/libs/x-content/impl/src/main/java/org/elasticsearch/xcontent/provider/json/JsonXContentParser.java @@ -18,10 +18,12 @@ import com.fasterxml.jackson.core.io.JsonEOFException; import org.elasticsearch.core.IOUtils; +import org.elasticsearch.xcontent.Text; import org.elasticsearch.xcontent.XContentEOFException; import org.elasticsearch.xcontent.XContentLocation; import org.elasticsearch.xcontent.XContentParseException; import org.elasticsearch.xcontent.XContentParserConfiguration; +import org.elasticsearch.xcontent.XContentString; import org.elasticsearch.xcontent.XContentType; import org.elasticsearch.xcontent.provider.XContentParserConfigurationImpl; import org.elasticsearch.xcontent.support.AbstractXContentParser; @@ -115,6 +117,20 @@ public String text() throws IOException { } } + @Override + public XContentString optimizedText() throws IOException { + if (currentToken().isValue() == false) { + throwOnNoText(); + } + if (parser instanceof ESUTF8StreamJsonParser esParser) { + var bytesRef = esParser.getValueAsText(); + if (bytesRef != null) { + return bytesRef; + } + } + return new Text(text()); + } + private void throwOnNoText() { throw new IllegalArgumentException("Expected text at " + getTokenLocation() + " but found " + currentToken()); } diff --git a/libs/x-content/impl/src/test/java/org/elasticsearch/xcontent/provider/json/ESJsonFactoryTests.java b/libs/x-content/impl/src/test/java/org/elasticsearch/xcontent/provider/json/ESJsonFactoryTests.java new file mode 100644 index 0000000000000..78f9d83cf94aa --- /dev/null +++ b/libs/x-content/impl/src/test/java/org/elasticsearch/xcontent/provider/json/ESJsonFactoryTests.java @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.xcontent.provider.json; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.json.ReaderBasedJsonParser; +import com.fasterxml.jackson.core.json.UTF8StreamJsonParser; + +import org.elasticsearch.test.ESTestCase; +import org.hamcrest.Matchers; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +public class ESJsonFactoryTests extends ESTestCase { + + public void testCreateParser() throws IOException { + JsonFactory factory = new ESJsonFactoryBuilder().build(); + assertThat(factory, Matchers.instanceOf(ESJsonFactory.class)); + + // \ufeff is the BOM + String[] inputs = { "{\"foo\": \"bar\"}", "\ufeff{\"foo\": \"bar\"}" }; + Charset[] charsets = { StandardCharsets.UTF_8, StandardCharsets.UTF_16LE, StandardCharsets.UTF_16BE }; + Class[] expectedParsers = { ESUTF8StreamJsonParser.class, ReaderBasedJsonParser.class, ReaderBasedJsonParser.class }; + + for (String input : inputs) { + for (int i = 0; i < charsets.length; i++) { + ByteBuffer encoded = charsets[i].encode(input); + JsonParser parser = factory.createParser(encoded.array()); + assertThat(parser, Matchers.instanceOf(expectedParsers[i])); + assertThat(parser.nextToken(), Matchers.equalTo(JsonToken.START_OBJECT)); + assertThat(parser.nextFieldName(), Matchers.equalTo("foo")); + assertThat(parser.nextValue(), Matchers.equalTo(JsonToken.VALUE_STRING)); + assertThat(parser.getValueAsString(), Matchers.equalTo("bar")); + } + } + + // Valid BOM + { + JsonParser parser = factory.createParser(new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF, '{', '}' }); + assertThat(parser, Matchers.instanceOf(ESUTF8StreamJsonParser.class)); + assertThat(parser.nextToken(), Matchers.equalTo(JsonToken.START_OBJECT)); + } + + // Invalid BOMs + { + JsonParser parser = factory.createParser(new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBB, '{', '}' }); + assertThat(parser, Matchers.instanceOf(UTF8StreamJsonParser.class)); + assertThrows("Invalid UTF-8 start byte 0xbb", JsonParseException.class, parser::nextToken); + } + + { + JsonParser parser = factory.createParser(new byte[] { (byte) 0xEF, '{', '}' }); + assertThat(parser, Matchers.instanceOf(UTF8StreamJsonParser.class)); + assertThrows("Invalid UTF-8 start byte 0x7b", JsonParseException.class, parser::nextToken); + } + } +} diff --git a/libs/x-content/impl/src/test/java/org/elasticsearch/xcontent/provider/json/ESUTF8StreamJsonParserTests.java b/libs/x-content/impl/src/test/java/org/elasticsearch/xcontent/provider/json/ESUTF8StreamJsonParserTests.java new file mode 100644 index 0000000000000..411f77be8b1e6 --- /dev/null +++ b/libs/x-content/impl/src/test/java/org/elasticsearch/xcontent/provider/json/ESUTF8StreamJsonParserTests.java @@ -0,0 +1,161 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.xcontent.provider.json; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; + +import org.elasticsearch.common.Strings; +import org.elasticsearch.core.CheckedConsumer; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xcontent.XContentBuilder; +import org.elasticsearch.xcontent.XContentString; +import org.elasticsearch.xcontent.json.JsonXContent; +import org.hamcrest.Matchers; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +public class ESUTF8StreamJsonParserTests extends ESTestCase { + + private void testParseJson(String input, CheckedConsumer test) throws IOException { + JsonFactory factory = new ESJsonFactoryBuilder().build(); + assertThat(factory, Matchers.instanceOf(ESJsonFactory.class)); + + JsonParser parser = factory.createParser(StandardCharsets.UTF_8.encode(input).array()); + assertThat(parser, Matchers.instanceOf(ESUTF8StreamJsonParser.class)); + test.accept((ESUTF8StreamJsonParser) parser); + } + + private void assertTextRef(XContentString.UTF8Bytes textRef, String expectedValue) { + assertThat(textRef, Matchers.equalTo(new XContentString.UTF8Bytes(expectedValue.getBytes(StandardCharsets.UTF_8)))); + } + + public void testGetValueAsText() throws IOException { + testParseJson("{\"foo\": \"bar\"}", parser -> { + assertThat(parser.nextToken(), Matchers.equalTo(JsonToken.START_OBJECT)); + assertThat(parser.nextFieldName(), Matchers.equalTo("foo")); + assertThat(parser.nextValue(), Matchers.equalTo(JsonToken.VALUE_STRING)); + + var textRef = parser.getValueAsText().bytes(); + assertThat(textRef, Matchers.notNullValue()); + assertThat(textRef.offset(), Matchers.equalTo(9)); + assertThat(textRef.offset() + textRef.length(), Matchers.equalTo(12)); + assertTextRef(textRef, "bar"); + + assertThat(parser.getValueAsString(), Matchers.equalTo("bar")); + assertThat(parser.getValueAsText(), Matchers.nullValue()); + + assertThat(parser.nextToken(), Matchers.equalTo(JsonToken.END_OBJECT)); + }); + + testParseJson("{\"foo\": \"bar\\\"baz\\\"\"}", parser -> { + assertThat(parser.nextToken(), Matchers.equalTo(JsonToken.START_OBJECT)); + assertThat(parser.nextFieldName(), Matchers.equalTo("foo")); + assertThat(parser.nextValue(), Matchers.equalTo(JsonToken.VALUE_STRING)); + + assertThat(parser.getValueAsText(), Matchers.nullValue()); + assertThat(parser.getValueAsString(), Matchers.equalTo("bar\"baz\"")); + }); + + testParseJson("{\"foo\": \"bår\"}", parser -> { + assertThat(parser.nextToken(), Matchers.equalTo(JsonToken.START_OBJECT)); + assertThat(parser.nextFieldName(), Matchers.equalTo("foo")); + assertThat(parser.nextValue(), Matchers.equalTo(JsonToken.VALUE_STRING)); + + assertThat(parser.getValueAsText(), Matchers.nullValue()); + assertThat(parser.getValueAsString(), Matchers.equalTo("bår")); + }); + + testParseJson("{\"foo\": [\"lorem\", \"ipsum\", \"dolor\"]}", parser -> { + assertThat(parser.nextToken(), Matchers.equalTo(JsonToken.START_OBJECT)); + assertThat(parser.nextFieldName(), Matchers.equalTo("foo")); + assertThat(parser.nextValue(), Matchers.equalTo(JsonToken.START_ARRAY)); + + assertThat(parser.nextValue(), Matchers.equalTo(JsonToken.VALUE_STRING)); + { + var textRef = parser.getValueAsText().bytes(); + assertThat(textRef, Matchers.notNullValue()); + assertThat(textRef.offset(), Matchers.equalTo(10)); + assertThat(textRef.offset() + textRef.length(), Matchers.equalTo(15)); + assertTextRef(textRef, "lorem"); + } + + assertThat(parser.nextValue(), Matchers.equalTo(JsonToken.VALUE_STRING)); + { + var textRef = parser.getValueAsText().bytes(); + assertThat(textRef, Matchers.notNullValue()); + assertThat(textRef.offset(), Matchers.equalTo(19)); + assertThat(textRef.offset() + textRef.length(), Matchers.equalTo(24)); + assertTextRef(textRef, "ipsum"); + } + + assertThat(parser.nextValue(), Matchers.equalTo(JsonToken.VALUE_STRING)); + { + var textRef = parser.getValueAsText().bytes(); + assertThat(textRef, Matchers.notNullValue()); + assertThat(textRef.offset(), Matchers.equalTo(28)); + assertThat(textRef.offset() + textRef.length(), Matchers.equalTo(33)); + assertTextRef(textRef, "dolor"); + } + + assertThat(parser.nextToken(), Matchers.equalTo(JsonToken.END_ARRAY)); + assertThat(parser.nextToken(), Matchers.equalTo(JsonToken.END_OBJECT)); + }); + } + + private boolean validForTextRef(String value) { + for (char c : value.toCharArray()) { + if (c == '"') { + return false; + } + if (c == '\\') { + return false; + } + if ((int) c < 32 || (int) c >= 128) { + return false; + } + } + return true; + } + + public void testGetValueRandomized() throws IOException { + XContentBuilder jsonBuilder = JsonXContent.contentBuilder().startObject(); + final int numKeys = 128; + String[] keys = new String[numKeys]; + String[] values = new String[numKeys]; + for (int i = 0; i < numKeys; i++) { + String currKey = randomAlphanumericOfLength(6); + String currVal = randomUnicodeOfLengthBetween(0, 512); + jsonBuilder.field(currKey, currVal); + keys[i] = currKey; + values[i] = currVal; + } + + jsonBuilder.endObject(); + testParseJson(Strings.toString(jsonBuilder), parser -> { + assertThat(parser.nextToken(), Matchers.equalTo(JsonToken.START_OBJECT)); + for (int i = 0; i < numKeys; i++) { + assertThat(parser.nextFieldName(), Matchers.equalTo(keys[i])); + assertThat(parser.nextValue(), Matchers.equalTo(JsonToken.VALUE_STRING)); + + String currVal = values[i]; + if (validForTextRef(currVal)) { + assertTextRef(parser.getValueAsText().bytes(), currVal); + } else { + assertThat(parser.getValueAsText(), Matchers.nullValue()); + assertThat(parser.getValueAsString(), Matchers.equalTo(currVal)); + } + } + }); + } + +} diff --git a/libs/x-content/src/main/java/org/elasticsearch/xcontent/FilterXContentParser.java b/libs/x-content/src/main/java/org/elasticsearch/xcontent/FilterXContentParser.java index a9616a6702aa0..4ff1185dc560c 100644 --- a/libs/x-content/src/main/java/org/elasticsearch/xcontent/FilterXContentParser.java +++ b/libs/x-content/src/main/java/org/elasticsearch/xcontent/FilterXContentParser.java @@ -100,6 +100,14 @@ public String textOrNull() throws IOException { return delegate().textOrNull(); } + public XContentString optimizedText() throws IOException { + return delegate().optimizedText(); + } + + public XContentString optimizedTextOrNull() throws IOException { + return delegate().optimizedTextOrNull(); + } + @Override public CharBuffer charBufferOrNull() throws IOException { return delegate().charBufferOrNull(); diff --git a/libs/x-content/src/main/java/org/elasticsearch/xcontent/XContentParser.java b/libs/x-content/src/main/java/org/elasticsearch/xcontent/XContentParser.java index 554043c2547cb..baee8922fd35b 100644 --- a/libs/x-content/src/main/java/org/elasticsearch/xcontent/XContentParser.java +++ b/libs/x-content/src/main/java/org/elasticsearch/xcontent/XContentParser.java @@ -109,6 +109,10 @@ Map map(Supplier> mapFactory, CheckedFunction { @@ -23,7 +24,7 @@ public int compareTo(UTF8Bytes o) { return 0; } - return ByteBuffer.wrap(bytes, offset, length).compareTo(ByteBuffer.wrap(o.bytes, o.offset, o.length)); + return Arrays.compareUnsigned(bytes, offset, offset + length, o.bytes, o.offset, o.offset + o.length); } @Override diff --git a/libs/x-content/src/main/java/org/elasticsearch/xcontent/support/AbstractXContentParser.java b/libs/x-content/src/main/java/org/elasticsearch/xcontent/support/AbstractXContentParser.java index 909cf808d1f34..351bfdc4b7d49 100644 --- a/libs/x-content/src/main/java/org/elasticsearch/xcontent/support/AbstractXContentParser.java +++ b/libs/x-content/src/main/java/org/elasticsearch/xcontent/support/AbstractXContentParser.java @@ -15,8 +15,10 @@ import org.elasticsearch.core.RestApiVersion; import org.elasticsearch.xcontent.DeprecationHandler; import org.elasticsearch.xcontent.NamedXContentRegistry; +import org.elasticsearch.xcontent.Text; import org.elasticsearch.xcontent.XContentParseException; import org.elasticsearch.xcontent.XContentParser; +import org.elasticsearch.xcontent.XContentString; import java.io.IOException; import java.math.BigDecimal; @@ -258,6 +260,19 @@ public final String textOrNull() throws IOException { return text(); } + @Override + public XContentString optimizedText() throws IOException { + return new Text(text()); + } + + @Override + public final XContentString optimizedTextOrNull() throws IOException { + if (currentToken() == Token.VALUE_NULL) { + return null; + } + return optimizedText(); + } + @Override public CharBuffer charBufferOrNull() throws IOException { if (currentToken() == Token.VALUE_NULL) { diff --git a/libs/x-content/src/test/java/org/elasticsearch/xcontent/TextTests.java b/libs/x-content/src/test/java/org/elasticsearch/xcontent/TextTests.java index 150fe1627c42c..4e637ff0248f5 100644 --- a/libs/x-content/src/test/java/org/elasticsearch/xcontent/TextTests.java +++ b/libs/x-content/src/test/java/org/elasticsearch/xcontent/TextTests.java @@ -12,6 +12,7 @@ import org.elasticsearch.test.ESTestCase; import java.nio.charset.StandardCharsets; +import java.util.Arrays; public class TextTests extends ESTestCase { public void testConvertToBytes() { @@ -136,7 +137,8 @@ public void testCompareTo() { byte[] encodedArr2 = value2.getBytes(StandardCharsets.UTF_8); var encoded2 = new XContentString.UTF8Bytes(encodedArr2); - int compSign = (int) Math.signum(encoded1.compareTo(encoded2)); + // String.compareTo() wasn't handling surrogate pairs very well, so here we compare the full 32-bit codepoints + int compSign = (int) Math.signum(Arrays.compare(value1.codePoints().toArray(), value2.codePoints().toArray())); { var text1 = new Text(value1); diff --git a/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/direct/TransportDeleteDatabaseConfigurationAction.java b/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/direct/TransportDeleteDatabaseConfigurationAction.java index 078aa142bba5a..5b1be42b1dcfa 100644 --- a/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/direct/TransportDeleteDatabaseConfigurationAction.java +++ b/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/direct/TransportDeleteDatabaseConfigurationAction.java @@ -21,7 +21,7 @@ import org.elasticsearch.cluster.SimpleBatchedExecutor; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; -import org.elasticsearch.cluster.metadata.Metadata; +import org.elasticsearch.cluster.metadata.ProjectMetadata; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.MasterServiceTaskQueue; import org.elasticsearch.common.Priority; @@ -103,17 +103,17 @@ private record DeleteDatabaseConfigurationTask(ActionListener databases = new HashMap<>(geoIpMeta.getDatabases()); databases.remove(databaseId); - Metadata currentMeta = currentState.metadata(); return ClusterState.builder(currentState) - .metadata(Metadata.builder(currentMeta).putCustom(IngestGeoIpMetadata.TYPE, new IngestGeoIpMetadata(databases))) + .putProjectMetadata( + ProjectMetadata.builder(project).putCustom(IngestGeoIpMetadata.TYPE, new IngestGeoIpMetadata(databases)) + ) .build(); } diff --git a/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/direct/TransportPutDatabaseConfigurationAction.java b/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/direct/TransportPutDatabaseConfigurationAction.java index 3096a60da1e18..f7a9c2aff305f 100644 --- a/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/direct/TransportPutDatabaseConfigurationAction.java +++ b/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/direct/TransportPutDatabaseConfigurationAction.java @@ -20,7 +20,7 @@ import org.elasticsearch.cluster.SimpleBatchedExecutor; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; -import org.elasticsearch.cluster.metadata.Metadata; +import org.elasticsearch.cluster.metadata.ProjectMetadata; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.MasterServiceTaskQueue; import org.elasticsearch.common.Priority; @@ -130,9 +130,8 @@ private record UpdateDatabaseConfigurationTask(ActionListener(String fieldName, Reader reade public void read(int docId, StoredFields storedFields, Builder builder) throws IOException { var ignoredSource = storedFields.storedFields().get(IgnoredSourceFieldMapper.NAME); if (ignoredSource == null) { + builder.appendNull(); return; } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java index 764f0c4cc5031..be5c4b82bf1f2 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java @@ -54,9 +54,11 @@ import org.elasticsearch.search.runtime.GeoPointScriptFieldDistanceFeatureQuery; import org.elasticsearch.xcontent.CopyingXContentParser; import org.elasticsearch.xcontent.FilterXContentParserWrapper; +import org.elasticsearch.xcontent.Text; import org.elasticsearch.xcontent.ToXContent; import org.elasticsearch.xcontent.XContentBuilder; import org.elasticsearch.xcontent.XContentParser; +import org.elasticsearch.xcontent.XContentString; import java.io.IOException; import java.io.UncheckedIOException; @@ -327,6 +329,11 @@ static class GeoHashMultiFieldParser extends FilterXContentParserWrapper { this.value = value; } + @Override + public XContentString optimizedTextOrNull() throws IOException { + return new Text(value); + } + @Override public String textOrNull() throws IOException { return value; diff --git a/server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java index 840f4a3726109..f8af7043b13dd 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java @@ -66,8 +66,10 @@ import org.elasticsearch.search.runtime.StringScriptFieldRegexpQuery; import org.elasticsearch.search.runtime.StringScriptFieldTermQuery; import org.elasticsearch.search.runtime.StringScriptFieldWildcardQuery; +import org.elasticsearch.xcontent.Text; import org.elasticsearch.xcontent.XContentBuilder; import org.elasticsearch.xcontent.XContentParser; +import org.elasticsearch.xcontent.XContentString; import java.io.IOException; import java.io.UncheckedIOException; @@ -1106,15 +1108,16 @@ public String getOffsetFieldName() { } protected void parseCreateField(DocumentParserContext context) throws IOException { - String value = context.parser().textOrNull(); - if (value == null) { - value = fieldType().nullValue; + var value = context.parser().optimizedTextOrNull(); + + if (value == null && fieldType().nullValue != null) { + value = new Text(fieldType().nullValue); } boolean indexed = indexValue(context, value); if (offsetsFieldName != null && context.isImmediateParentAnArray() && context.canAddIgnoredField()) { if (indexed) { - context.getOffSetContext().recordOffset(offsetsFieldName, value); + context.getOffSetContext().recordOffset(offsetsFieldName, value.bytes()); } else if (value == null) { context.getOffSetContext().recordNull(offsetsFieldName); } @@ -1132,28 +1135,37 @@ protected void indexScriptValues( } private boolean indexValue(DocumentParserContext context, String value) { + return indexValue(context, new Text(value)); + } + + private boolean indexValue(DocumentParserContext context, XContentString value) { if (value == null) { return false; } + // if field is disabled, skip indexing if ((fieldType.indexOptions() == IndexOptions.NONE) && (fieldType.stored() == false) && (fieldType().hasDocValues() == false)) { return false; } - if (value.length() > fieldType().ignoreAbove()) { + if (value.stringLength() > fieldType().ignoreAbove()) { context.addIgnoredField(fullPath()); if (isSyntheticSource) { // Save a copy of the field so synthetic source can load it - context.doc().add(new StoredField(originalName(), new BytesRef(value))); + var utfBytes = value.bytes(); + var bytesRef = new BytesRef(utfBytes.bytes(), utfBytes.offset(), utfBytes.length()); + context.doc().add(new StoredField(originalName(), bytesRef)); } return false; } - value = normalizeValue(fieldType().normalizer(), fullPath(), value); - - // convert to utf8 only once before feeding postings/dv/stored fields - final BytesRef binaryValue = new BytesRef(value); + if (fieldType().normalizer() != Lucene.KEYWORD_ANALYZER) { + String normalizedString = normalizeValue(fieldType().normalizer(), fullPath(), value.string()); + value = new Text(normalizedString); + } + var utfBytes = value.bytes(); + var binaryValue = new BytesRef(utfBytes.bytes(), utfBytes.offset(), utfBytes.length()); if (fieldType().isDimension()) { context.getRoutingFields().addString(fieldType().name(), binaryValue); } diff --git a/server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java b/server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java index 2e9e60dec08a4..9611f42437765 100644 --- a/server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java +++ b/server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java @@ -2593,7 +2593,8 @@ private void markRepoCorrupted(long corruptedGeneration, Exception originalExcep new ClusterStateUpdateTask() { @Override public ClusterState execute(ClusterState currentState) { - final RepositoriesMetadata state = RepositoriesMetadata.get(currentState); + final var project = currentState.metadata().getDefaultProject(); + final RepositoriesMetadata state = RepositoriesMetadata.get(project); final RepositoryMetadata repoState = state.repository(metadata.name()); if (repoState.generation() != corruptedGeneration) { throw new IllegalStateException( @@ -2605,8 +2606,8 @@ public ClusterState execute(ClusterState currentState) { ); } return ClusterState.builder(currentState) - .metadata( - Metadata.builder(currentState.metadata()) + .putProjectMetadata( + ProjectMetadata.builder(project) .putCustom( RepositoriesMetadata.TYPE, state.withUpdatedGeneration( @@ -2615,7 +2616,6 @@ public ClusterState execute(ClusterState currentState) { repoState.pendingGeneration() ) ) - .build() ) .build(); } @@ -2787,12 +2787,13 @@ public ClusterState execute(ClusterState currentState) { + "] must be larger than latest known generation [" + latestKnownRepoGen.get() + "]"; + final var project = currentState.metadata().getDefaultProject(); return ClusterState.builder(currentState) - .metadata( - Metadata.builder(currentState.getMetadata()) + .putProjectMetadata( + ProjectMetadata.builder(project) .putCustom( RepositoriesMetadata.TYPE, - RepositoriesMetadata.get(currentState).withUpdatedGeneration(repoName, safeGeneration, newGen) + RepositoriesMetadata.get(project).withUpdatedGeneration(repoName, safeGeneration, newGen) ) .build() ) diff --git a/server/src/main/java/org/elasticsearch/script/ScriptService.java b/server/src/main/java/org/elasticsearch/script/ScriptService.java index f84f1eb834bfd..c44bf1ffc2731 100644 --- a/server/src/main/java/org/elasticsearch/script/ScriptService.java +++ b/server/src/main/java/org/elasticsearch/script/ScriptService.java @@ -22,7 +22,6 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateApplier; import org.elasticsearch.cluster.ClusterStateUpdateTask; -import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Strings; import org.elasticsearch.common.logging.DeprecationCategory; @@ -733,11 +732,11 @@ public void putStoredScript( submitUnbatchedTask(clusterService, "put-script-" + request.id(), new AckedClusterStateUpdateTask(request, listener) { @Override public ClusterState execute(ClusterState currentState) { - ScriptMetadata smd = currentState.metadata().getProject().custom(ScriptMetadata.TYPE); - smd = ScriptMetadata.putStoredScript(smd, request.id(), source); - Metadata.Builder mdb = Metadata.builder(currentState.getMetadata()).putCustom(ScriptMetadata.TYPE, smd); + final var project = currentState.metadata().getProject(); + final ScriptMetadata originalSmd = project.custom(ScriptMetadata.TYPE); + final ScriptMetadata updatedSmd = ScriptMetadata.putStoredScript(originalSmd, request.id(), source); - return ClusterState.builder(currentState).metadata(mdb).build(); + return currentState.copyAndUpdateProject(project.id(), builder -> builder.putCustom(ScriptMetadata.TYPE, updatedSmd)); } }); } @@ -750,11 +749,11 @@ public static void deleteStoredScript( submitUnbatchedTask(clusterService, "delete-script-" + request.id(), new AckedClusterStateUpdateTask(request, listener) { @Override public ClusterState execute(ClusterState currentState) { - ScriptMetadata smd = currentState.metadata().getProject().custom(ScriptMetadata.TYPE); - smd = ScriptMetadata.deleteStoredScript(smd, request.id()); - Metadata.Builder mdb = Metadata.builder(currentState.getMetadata()).putCustom(ScriptMetadata.TYPE, smd); + final var project = currentState.metadata().getProject(); + final ScriptMetadata originalSmd = project.custom(ScriptMetadata.TYPE); + final ScriptMetadata updatedSmd = ScriptMetadata.deleteStoredScript(originalSmd, request.id()); - return ClusterState.builder(currentState).metadata(mdb).build(); + return currentState.copyAndUpdateProject(project.id(), builder -> builder.putCustom(ScriptMetadata.TYPE, updatedSmd)); } }); } diff --git a/server/src/main/java/org/elasticsearch/snapshots/RestoreService.java b/server/src/main/java/org/elasticsearch/snapshots/RestoreService.java index 99df2ac920f0c..bf6b078571bfc 100644 --- a/server/src/main/java/org/elasticsearch/snapshots/RestoreService.java +++ b/server/src/main/java/org/elasticsearch/snapshots/RestoreService.java @@ -1583,6 +1583,8 @@ private void ensureSnapshotNotDeleted(ClusterState currentState) { } private void applyGlobalStateRestore(ClusterState currentState, Metadata.Builder mdBuilder) { + @FixForMultiProject + final var projectBuilder = mdBuilder.getProject(ProjectId.DEFAULT); if (metadata.persistentSettings() != null) { Settings settings = metadata.persistentSettings(); if (request.skipOperatorOnlyState()) { @@ -1607,13 +1609,13 @@ private void applyGlobalStateRestore(ClusterState currentState, Metadata.Builder if (metadata.getProject().templates() != null) { // TODO: Should all existing templates be deleted first? for (IndexTemplateMetadata cursor : metadata.getProject().templates().values()) { - mdBuilder.put(cursor); + projectBuilder.put(cursor); } } // override existing restorable customs (as there might be nothing in snapshot to override them) mdBuilder.removeCustomIf((key, value) -> value.isRestorable()); - mdBuilder.removeProjectCustomIf((key, value) -> value.isRestorable()); + projectBuilder.removeCustomIf((key, value) -> value.isRestorable()); // restore customs from the snapshot if (metadata.customs() != null) { @@ -1630,7 +1632,7 @@ private void applyGlobalStateRestore(ClusterState currentState, Metadata.Builder for (var entry : metadata.getProject().customs().entrySet()) { if (entry.getValue().isRestorable()) { // Also, don't restore data streams here, we already added them to the metadata builder above - mdBuilder.putCustom(entry.getKey(), entry.getValue()); + projectBuilder.putCustom(entry.getKey(), entry.getValue()); } } } diff --git a/server/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java b/server/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java index 8496faf7bc0e6..4865e8cb5f690 100644 --- a/server/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java +++ b/server/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java @@ -4090,10 +4090,11 @@ public ClusterState execute(BatchExecutionContext batchExecutionCo // Handle the tasks to apply the shard snapshot updates (ShardSnapshotUpdate tasks). SnapshotsInProgress snapshotsInProgress = shardsUpdateContext.computeUpdatedState(); - final RegisteredPolicySnapshots.Builder registeredPolicySnapshots = state.metadata() - .getProject() - .custom(RegisteredPolicySnapshots.TYPE, RegisteredPolicySnapshots.EMPTY) - .builder(); + final var project = state.metadata().getProject(); + final RegisteredPolicySnapshots.Builder registeredPolicySnapshots = project.custom( + RegisteredPolicySnapshots.TYPE, + RegisteredPolicySnapshots.EMPTY + ).builder(); // Handle the tasks to create new snapshots (CreateSnapshotTask tasks). for (final var taskContext : batchExecutionContext.taskContexts()) { if (taskContext.getTask() instanceof CreateSnapshotTask task) { @@ -4135,7 +4136,9 @@ public ClusterState execute(BatchExecutionContext batchExecutionCo return ClusterState.builder(state) .putCustom(SnapshotsInProgress.TYPE, snapshotsInProgress) - .metadata(Metadata.builder(state.metadata()).putCustom(RegisteredPolicySnapshots.TYPE, registeredPolicySnapshots.build())) + .putProjectMetadata( + ProjectMetadata.builder(project).putCustom(RegisteredPolicySnapshots.TYPE, registeredPolicySnapshots.build()) + ) .build(); } diff --git a/server/src/main/java/org/elasticsearch/transport/ClusterConnectionManager.java b/server/src/main/java/org/elasticsearch/transport/ClusterConnectionManager.java index 5d13b10f5a6a4..e70a8abacb026 100644 --- a/server/src/main/java/org/elasticsearch/transport/ClusterConnectionManager.java +++ b/server/src/main/java/org/elasticsearch/transport/ClusterConnectionManager.java @@ -229,11 +229,26 @@ private void connectToNodeOrRetry( try { connectionListener.onNodeConnected(node, conn); } finally { - conn.addCloseListener(ActionListener.running(() -> { - connectedNodes.remove(node, conn); - connectionListener.onNodeDisconnected(node, conn); - managerRefs.decRef(); - })); + conn.addCloseListener(new ActionListener() { + @Override + public void onResponse(Void ignored) { + handleClose(null); + } + + @Override + public void onFailure(Exception e) { + handleClose(e); + } + + void handleClose(@Nullable Exception e) { + connectedNodes.remove(node, conn); + try { + connectionListener.onNodeDisconnected(node, e); + } finally { + managerRefs.decRef(); + } + } + }); conn.addCloseListener(ActionListener.running(() -> { if (connectingRefCounter.hasReferences() == false) { diff --git a/server/src/main/java/org/elasticsearch/transport/ConnectionManager.java b/server/src/main/java/org/elasticsearch/transport/ConnectionManager.java index daccac3fbe2cb..bc11ca0e8699f 100644 --- a/server/src/main/java/org/elasticsearch/transport/ConnectionManager.java +++ b/server/src/main/java/org/elasticsearch/transport/ConnectionManager.java @@ -60,9 +60,9 @@ final class DelegatingNodeConnectionListener implements TransportConnectionListe private final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList<>(); @Override - public void onNodeDisconnected(DiscoveryNode key, Transport.Connection connection) { + public void onNodeDisconnected(DiscoveryNode key, @Nullable Exception closeException) { for (TransportConnectionListener listener : listeners) { - listener.onNodeDisconnected(key, connection); + listener.onNodeDisconnected(key, closeException); } } diff --git a/server/src/main/java/org/elasticsearch/transport/RemoteConnectionManager.java b/server/src/main/java/org/elasticsearch/transport/RemoteConnectionManager.java index 8bc5771485f6d..c27d9cf69a905 100644 --- a/server/src/main/java/org/elasticsearch/transport/RemoteConnectionManager.java +++ b/server/src/main/java/org/elasticsearch/transport/RemoteConnectionManager.java @@ -61,7 +61,7 @@ public void onNodeConnected(DiscoveryNode node, Transport.Connection connection) } @Override - public void onNodeDisconnected(DiscoveryNode node, Transport.Connection connection) { + public void onNodeDisconnected(DiscoveryNode node, @Nullable Exception closeException) { removeConnectedNode(node); } }); diff --git a/server/src/main/java/org/elasticsearch/transport/RemoteConnectionStrategy.java b/server/src/main/java/org/elasticsearch/transport/RemoteConnectionStrategy.java index 248ca4313cefb..a715797b97977 100644 --- a/server/src/main/java/org/elasticsearch/transport/RemoteConnectionStrategy.java +++ b/server/src/main/java/org/elasticsearch/transport/RemoteConnectionStrategy.java @@ -21,6 +21,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.AbstractRunnable; import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException; +import org.elasticsearch.core.Nullable; import org.elasticsearch.core.TimeValue; import org.elasticsearch.threadpool.ThreadPool; @@ -339,7 +340,7 @@ boolean shouldRebuildConnection(Settings newSettings) { protected abstract ConnectionStrategy strategyType(); @Override - public void onNodeDisconnected(DiscoveryNode node, Transport.Connection connection) { + public void onNodeDisconnected(DiscoveryNode node, @Nullable Exception closeException) { if (shouldOpenMoreConnections()) { // try to reconnect and fill up the slot of the disconnected node connect( diff --git a/server/src/main/java/org/elasticsearch/transport/TransportConnectionListener.java b/server/src/main/java/org/elasticsearch/transport/TransportConnectionListener.java index 92796f826fc3a..470014eb7a676 100644 --- a/server/src/main/java/org/elasticsearch/transport/TransportConnectionListener.java +++ b/server/src/main/java/org/elasticsearch/transport/TransportConnectionListener.java @@ -10,6 +10,7 @@ package org.elasticsearch.transport; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.core.Nullable; /** * A listener interface that allows to react on transport events. All methods may be @@ -38,5 +39,5 @@ default void onNodeConnected(DiscoveryNode node, Transport.Connection connection /** * Called once a node connection is closed and unregistered. */ - default void onNodeDisconnected(DiscoveryNode node, Transport.Connection connection) {} + default void onNodeDisconnected(DiscoveryNode node, @Nullable Exception closeException) {} } diff --git a/server/src/test/java/org/elasticsearch/action/search/TransportSearchActionTests.java b/server/src/test/java/org/elasticsearch/action/search/TransportSearchActionTests.java index 7ab9b8611b8c4..3c5dc6b39292c 100644 --- a/server/src/test/java/org/elasticsearch/action/search/TransportSearchActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/search/TransportSearchActionTests.java @@ -52,6 +52,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.common.util.set.Sets; +import org.elasticsearch.core.Nullable; import org.elasticsearch.core.TimeValue; import org.elasticsearch.core.Tuple; import org.elasticsearch.index.Index; @@ -831,7 +832,7 @@ public void testCCSRemoteReduceWithDisconnectedRemoteClusters() throws Exception CountDownLatch disconnectedLatch = new CountDownLatch(numDisconnectedClusters); RemoteClusterServiceTests.addConnectionListener(remoteClusterService, new TransportConnectionListener() { @Override - public void onNodeDisconnected(DiscoveryNode node, Transport.Connection connection) { + public void onNodeDisconnected(DiscoveryNode node, @Nullable Exception closeException) { if (disconnectedNodes.remove(node)) { disconnectedLatch.countDown(); } @@ -1134,7 +1135,7 @@ public void testCollectSearchShards() throws Exception { CountDownLatch disconnectedLatch = new CountDownLatch(numDisconnectedClusters); RemoteClusterServiceTests.addConnectionListener(remoteClusterService, new TransportConnectionListener() { @Override - public void onNodeDisconnected(DiscoveryNode node, Transport.Connection connection) { + public void onNodeDisconnected(DiscoveryNode node, @Nullable Exception closeException) { if (disconnectedNodes.remove(node)) { disconnectedLatch.countDown(); } diff --git a/server/src/test/java/org/elasticsearch/cluster/NodeConnectionsServiceTests.java b/server/src/test/java/org/elasticsearch/cluster/NodeConnectionsServiceTests.java index 8963bb10d6573..f0edd4aeba126 100644 --- a/server/src/test/java/org/elasticsearch/cluster/NodeConnectionsServiceTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/NodeConnectionsServiceTests.java @@ -30,6 +30,7 @@ import org.elasticsearch.common.util.concurrent.DeterministicTaskQueue; import org.elasticsearch.core.AbstractRefCounted; import org.elasticsearch.core.CheckedRunnable; +import org.elasticsearch.core.Nullable; import org.elasticsearch.core.RefCounted; import org.elasticsearch.core.TimeValue; import org.elasticsearch.test.ESTestCase; @@ -251,7 +252,7 @@ public void testOnlyBlocksOnConnectionsToNewNodes() throws Exception { final AtomicReference> disconnectListenerRef = new AtomicReference<>(); transportService.addConnectionListener(new TransportConnectionListener() { @Override - public void onNodeDisconnected(DiscoveryNode node, Transport.Connection connection) { + public void onNodeDisconnected(DiscoveryNode node, @Nullable Exception closeException) { final ActionListener disconnectListener = disconnectListenerRef.getAndSet(null); if (disconnectListener != null) { disconnectListener.onResponse(node); diff --git a/server/src/test/java/org/elasticsearch/common/xcontent/BaseXContentTestCase.java b/server/src/test/java/org/elasticsearch/common/xcontent/BaseXContentTestCase.java index 979224ba8f9b7..0392f2a730cd2 100644 --- a/server/src/test/java/org/elasticsearch/common/xcontent/BaseXContentTestCase.java +++ b/server/src/test/java/org/elasticsearch/common/xcontent/BaseXContentTestCase.java @@ -395,6 +395,22 @@ public void testText() throws Exception { } } + public void testOptimizedText() throws Exception { + final var random = new XContentString.UTF8Bytes(randomBytes()); + XContentBuilder builder = builder().startObject().field("text", new Text(random)).endObject(); + + try (XContentParser parser = createParser(xcontentType().xContent(), BytesReference.bytes(builder))) { + assertSame(Token.START_OBJECT, parser.nextToken()); + assertSame(Token.FIELD_NAME, parser.nextToken()); + assertEquals("text", parser.currentName()); + assertTrue(parser.nextToken().isValue()); + var valueRef = parser.optimizedText().bytes(); + assertThat(valueRef, equalTo(random)); + assertSame(Token.END_OBJECT, parser.nextToken()); + assertNull(parser.nextToken()); + } + } + public void testDate() throws Exception { assertResult("{'date':null}", () -> builder().startObject().timestampField("date", (Date) null).endObject()); assertResult("{'date':null}", () -> builder().startObject().field("date").timestampValue((Date) null).endObject()); diff --git a/server/src/test/java/org/elasticsearch/transport/ClusterConnectionManagerTests.java b/server/src/test/java/org/elasticsearch/transport/ClusterConnectionManagerTests.java index 0a446e999c3c3..1e735de2651a5 100644 --- a/server/src/test/java/org/elasticsearch/transport/ClusterConnectionManagerTests.java +++ b/server/src/test/java/org/elasticsearch/transport/ClusterConnectionManagerTests.java @@ -23,6 +23,7 @@ import org.elasticsearch.common.util.concurrent.RunOnce; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.core.AbstractRefCounted; +import org.elasticsearch.core.Nullable; import org.elasticsearch.core.Releasable; import org.elasticsearch.core.Releasables; import org.elasticsearch.core.TimeValue; @@ -101,7 +102,7 @@ public void onNodeConnected(DiscoveryNode node, Transport.Connection connection) } @Override - public void onNodeDisconnected(DiscoveryNode node, Transport.Connection connection) { + public void onNodeDisconnected(DiscoveryNode node, @Nullable Exception closeException) { nodeDisconnectedCount.incrementAndGet(); } }); @@ -658,7 +659,7 @@ public void onNodeConnected(DiscoveryNode node, Transport.Connection connection) } @Override - public void onNodeDisconnected(DiscoveryNode node, Transport.Connection connection) { + public void onNodeDisconnected(DiscoveryNode node, @Nullable Exception closeException) { nodeDisconnectedCount.incrementAndGet(); } }); @@ -698,7 +699,7 @@ public void onNodeConnected(DiscoveryNode node, Transport.Connection connection) } @Override - public void onNodeDisconnected(DiscoveryNode node, Transport.Connection connection) { + public void onNodeDisconnected(DiscoveryNode node, @Nullable Exception closeException) { nodeDisconnectedCount.incrementAndGet(); } }); diff --git a/test/framework/src/main/java/org/elasticsearch/index/mapper/BlockLoaderTestRunner.java b/test/framework/src/main/java/org/elasticsearch/index/mapper/BlockLoaderTestRunner.java index c558cd9ddfa08..eb5bbea9e6bba 100644 --- a/test/framework/src/main/java/org/elasticsearch/index/mapper/BlockLoaderTestRunner.java +++ b/test/framework/src/main/java/org/elasticsearch/index/mapper/BlockLoaderTestRunner.java @@ -29,6 +29,8 @@ import static org.apache.lucene.tests.util.LuceneTestCase.newDirectory; import static org.apache.lucene.tests.util.LuceneTestCase.random; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; public class BlockLoaderTestRunner { private final BlockLoaderTestCase.Params params; @@ -74,10 +76,9 @@ private Object load(BlockLoader blockLoader, LeafReaderContext context, MapperSe // `columnAtATimeReader` is tried first, we mimic `ValuesSourceReaderOperator` var columnAtATimeReader = blockLoader.columnAtATimeReader(context); if (columnAtATimeReader != null) { - var block = (TestBlock) columnAtATimeReader.read(TestBlock.factory(context.reader().numDocs()), TestBlock.docs(0)); - if (block.size() == 0) { - return null; - } + BlockLoader.Docs docs = TestBlock.docs(0); + var block = (TestBlock) columnAtATimeReader.read(TestBlock.factory(context.reader().numDocs()), docs); + assertThat(block.size(), equalTo(1)); return block.get(0); } @@ -99,9 +100,8 @@ private Object load(BlockLoader blockLoader, LeafReaderContext context, MapperSe BlockLoader.Builder builder = blockLoader.builder(TestBlock.factory(context.reader().numDocs()), 1); blockLoader.rowStrideReader(context).read(0, storedFieldsLoader, builder); var block = (TestBlock) builder.build(); - if (block.size() == 0) { - return null; - } + assertThat(block.size(), equalTo(1)); + return block.get(0); } diff --git a/test/framework/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreTestUtil.java b/test/framework/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreTestUtil.java index 349f1ae5d1921..e9a50c12eae0a 100644 --- a/test/framework/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreTestUtil.java +++ b/test/framework/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreTestUtil.java @@ -18,6 +18,8 @@ import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.metadata.IndexMetadata; import org.elasticsearch.cluster.metadata.Metadata; +import org.elasticsearch.cluster.metadata.ProjectId; +import org.elasticsearch.cluster.metadata.ProjectMetadata; import org.elasticsearch.cluster.metadata.RepositoriesMetadata; import org.elasticsearch.cluster.metadata.RepositoryMetadata; import org.elasticsearch.cluster.node.DiscoveryNode; @@ -391,18 +393,25 @@ public static ClusterService mockClusterService() { /** * Creates a mocked {@link ClusterService} for use in {@link BlobStoreRepository} related tests that mocks out all the necessary * functionality to make {@link BlobStoreRepository} work. Initializes the cluster state with a {@link RepositoriesMetadata} instance - * that contains the given {@code metadata}. + * that contains the given {@code repositoryMetadata}. * - * @param metadata RepositoryMetadata to initialize the cluster state with + * @param repositoryMetadata RepositoryMetadata to initialize the cluster state with * @return Mock ClusterService */ - public static ClusterService mockClusterService(RepositoryMetadata metadata) { + public static ClusterService mockClusterService(RepositoryMetadata repositoryMetadata) { return mockClusterService( ClusterState.builder(ClusterState.EMPTY_STATE) .metadata( Metadata.builder() .clusterUUID(UUIDs.randomBase64UUID(random())) - .putCustom(RepositoriesMetadata.TYPE, new RepositoriesMetadata(Collections.singletonList(metadata))) + .put( + ProjectMetadata.builder(ProjectId.DEFAULT) + .putCustom( + RepositoriesMetadata.TYPE, + new RepositoriesMetadata(Collections.singletonList(repositoryMetadata)) + ) + .build() + ) .build() ) .build() diff --git a/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java b/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java index b627a8803bf21..c187c9b822a86 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java +++ b/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java @@ -65,7 +65,9 @@ public void testFailure(Failure failure) throws Exception { final String gradlew = Constants.WINDOWS ? "gradlew" : "./gradlew"; final StringBuilder b = new StringBuilder("REPRODUCE WITH: " + gradlew + " "); String task = System.getProperty("tests.task"); - boolean isBwcTest = Boolean.parseBoolean(System.getProperty("tests.bwc", "false")); + boolean isBwcTest = Boolean.parseBoolean(System.getProperty("tests.bwc", "false")) + || System.getProperty("tests.bwc.main.version") != null + || System.getProperty("tests.bwc.refspec.main") != null; // append Gradle test runner test filter string b.append("\"" + task + "\""); @@ -174,7 +176,9 @@ private ReproduceErrorMessageBuilder appendESProperties() { "tests.bwc", "tests.bwc.version", "build.snapshot", - "tests.configure_test_clusters_with_one_processor" + "tests.configure_test_clusters_with_one_processor", + "tests.bwc.main.version", + "tests.bwc.refspec.main" ); if (System.getProperty("tests.jvm.argline") != null && System.getProperty("tests.jvm.argline").isEmpty() == false) { appendOpt("tests.jvm.argline", "\"" + System.getProperty("tests.jvm.argline") + "\""); diff --git a/test/framework/src/main/java/org/elasticsearch/transport/AbstractSimpleTransportTestCase.java b/test/framework/src/main/java/org/elasticsearch/transport/AbstractSimpleTransportTestCase.java index f37a139e4583f..b54e9fca82069 100644 --- a/test/framework/src/main/java/org/elasticsearch/transport/AbstractSimpleTransportTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/transport/AbstractSimpleTransportTestCase.java @@ -202,7 +202,7 @@ public void onNodeConnected(DiscoveryNode node, Transport.Connection connection) } @Override - public void onNodeDisconnected(DiscoveryNode node, Transport.Connection connection) { + public void onNodeDisconnected(DiscoveryNode node, @Nullable Exception closeException) { fail("disconnect should not be called " + node); } }; @@ -924,7 +924,7 @@ public void onNodeConnected(DiscoveryNode node, Transport.Connection connection) } @Override - public void onNodeDisconnected(DiscoveryNode node, Transport.Connection connection) { + public void onNodeDisconnected(DiscoveryNode node, @Nullable Exception closeException) { latch.countDown(); } }; @@ -2118,7 +2118,7 @@ public void onNodeConnected(DiscoveryNode node, Transport.Connection connection) } @Override - public void onNodeDisconnected(DiscoveryNode node, Transport.Connection connection) { + public void onNodeDisconnected(DiscoveryNode node, @Nullable Exception closeException) { fail("disconnect should not be called " + node); } }; diff --git a/test/yaml-rest-runner/src/main/java/org/elasticsearch/test/rest/yaml/ParameterizableYamlXContentParser.java b/test/yaml-rest-runner/src/main/java/org/elasticsearch/test/rest/yaml/ParameterizableYamlXContentParser.java index c50115d53e629..786953b505f9e 100644 --- a/test/yaml-rest-runner/src/main/java/org/elasticsearch/test/rest/yaml/ParameterizableYamlXContentParser.java +++ b/test/yaml-rest-runner/src/main/java/org/elasticsearch/test/rest/yaml/ParameterizableYamlXContentParser.java @@ -16,6 +16,7 @@ import org.elasticsearch.xcontent.NamedXContentRegistry; import org.elasticsearch.xcontent.XContentLocation; import org.elasticsearch.xcontent.XContentParser; +import org.elasticsearch.xcontent.XContentString; import org.elasticsearch.xcontent.XContentType; import java.io.IOException; @@ -143,6 +144,16 @@ public String textOrNull() throws IOException { return delegate.textOrNull(); } + @Override + public XContentString optimizedText() throws IOException { + return delegate.optimizedText(); + } + + @Override + public XContentString optimizedTextOrNull() throws IOException { + return delegate.optimizedTextOrNull(); + } + @Override public CharBuffer charBufferOrNull() throws IOException { return delegate.charBufferOrNull(); diff --git a/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/AutoFollowCoordinator.java b/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/AutoFollowCoordinator.java index 9a0d46f4bc507..4590b38f09f46 100644 --- a/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/AutoFollowCoordinator.java +++ b/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/AutoFollowCoordinator.java @@ -23,6 +23,7 @@ import org.elasticsearch.cluster.metadata.IndexAbstraction; import org.elasticsearch.cluster.metadata.IndexMetadata; import org.elasticsearch.cluster.metadata.Metadata; +import org.elasticsearch.cluster.metadata.ProjectMetadata; import org.elasticsearch.cluster.routing.IndexRoutingTable; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.component.AbstractLifecycleComponent; @@ -879,7 +880,8 @@ static String getFollowerIndexName(AutoFollowPattern autoFollowPattern, String l static Function recordLeaderIndexAsFollowFunction(String name, Index indexToFollow) { return currentState -> { - AutoFollowMetadata currentAutoFollowMetadata = currentState.metadata().getProject().custom(AutoFollowMetadata.TYPE); + final var project = currentState.metadata().getProject(); + AutoFollowMetadata currentAutoFollowMetadata = project.custom(AutoFollowMetadata.TYPE); Map> newFollowedIndexUUIDS = new HashMap<>(currentAutoFollowMetadata.getFollowedLeaderIndexUUIDs()); if (newFollowedIndexUUIDS.containsKey(name) == false) { // A delete auto follow pattern request can have removed the auto follow pattern while we want to update @@ -900,9 +902,7 @@ static Function recordLeaderIndexAsFollowFunction(St currentAutoFollowMetadata.getHeaders() ); return ClusterState.builder(currentState) - .metadata( - Metadata.builder(currentState.getMetadata()).putCustom(AutoFollowMetadata.TYPE, newAutoFollowMetadata).build() - ) + .putProjectMetadata(ProjectMetadata.builder(project).putCustom(AutoFollowMetadata.TYPE, newAutoFollowMetadata).build()) .build(); }; } @@ -920,7 +920,8 @@ static Function cleanFollowedRemoteIndices( final List autoFollowPatternNames ) { return currentState -> { - AutoFollowMetadata currentAutoFollowMetadata = currentState.metadata().getProject().custom(AutoFollowMetadata.TYPE); + final var currentProject = currentState.metadata().getProject(); + AutoFollowMetadata currentAutoFollowMetadata = currentProject.custom(AutoFollowMetadata.TYPE); Map> autoFollowPatternNameToFollowedIndexUUIDs = new HashMap<>( currentAutoFollowMetadata.getFollowedLeaderIndexUUIDs() ); @@ -958,8 +959,8 @@ static Function cleanFollowedRemoteIndices( currentAutoFollowMetadata.getHeaders() ); return ClusterState.builder(currentState) - .metadata( - Metadata.builder(currentState.getMetadata()).putCustom(AutoFollowMetadata.TYPE, newAutoFollowMetadata).build() + .putProjectMetadata( + ProjectMetadata.builder(currentProject).putCustom(AutoFollowMetadata.TYPE, newAutoFollowMetadata).build() ) .build(); } else { diff --git a/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/TransportActivateAutoFollowPatternAction.java b/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/TransportActivateAutoFollowPatternAction.java index ef7d79af2b47c..d07ee76fd9792 100644 --- a/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/TransportActivateAutoFollowPatternAction.java +++ b/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/TransportActivateAutoFollowPatternAction.java @@ -76,7 +76,8 @@ private void submitUnbatchedTask(@SuppressWarnings("SameParameterValue") String } static ClusterState innerActivate(final Request request, ClusterState currentState) { - final AutoFollowMetadata autoFollowMetadata = currentState.metadata().getProject().custom(AutoFollowMetadata.TYPE); + final var project = currentState.metadata().getProject(); + final AutoFollowMetadata autoFollowMetadata = project.custom(AutoFollowMetadata.TYPE); if (autoFollowMetadata == null) { throw new ResourceNotFoundException("auto-follow pattern [{}] is missing", request.getName()); } @@ -114,8 +115,9 @@ static ClusterState innerActivate(final Request request, ClusterState currentSta ) ); - return currentState.copyAndUpdateMetadata( - metadata -> metadata.putCustom( + return currentState.copyAndUpdateProject( + project.id(), + builder -> builder.putCustom( AutoFollowMetadata.TYPE, new AutoFollowMetadata(newPatterns, autoFollowMetadata.getFollowedLeaderIndexUUIDs(), autoFollowMetadata.getHeaders()) ) diff --git a/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/TransportPutAutoFollowPatternAction.java b/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/TransportPutAutoFollowPatternAction.java index 2d1292899be0c..9002c14b73b48 100644 --- a/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/TransportPutAutoFollowPatternAction.java +++ b/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/TransportPutAutoFollowPatternAction.java @@ -151,7 +151,8 @@ static ClusterState innerPut( // auto patterns are always overwritten // only already followed index uuids are updated - AutoFollowMetadata currentAutoFollowMetadata = localState.metadata().getProject().custom(AutoFollowMetadata.TYPE); + final var localProject = localState.metadata().getProject(); + AutoFollowMetadata currentAutoFollowMetadata = localProject.custom(AutoFollowMetadata.TYPE); Map> followedLeaderIndices; Map patterns; Map> headers; @@ -215,8 +216,9 @@ static ClusterState innerPut( ); patterns.put(request.getName(), autoFollowPattern); - return localState.copyAndUpdateMetadata( - metadata -> metadata.putCustom(AutoFollowMetadata.TYPE, new AutoFollowMetadata(patterns, followedLeaderIndices, headers)) + return localState.copyAndUpdateProject( + localProject.id(), + builder -> builder.putCustom(AutoFollowMetadata.TYPE, new AutoFollowMetadata(patterns, followedLeaderIndices, headers)) ); } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ilm/OperationModeUpdateTask.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ilm/OperationModeUpdateTask.java index bdfa4c7303a4c..5a708dbf95fb2 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ilm/OperationModeUpdateTask.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ilm/OperationModeUpdateTask.java @@ -14,7 +14,6 @@ import org.elasticsearch.cluster.AckedClusterStateUpdateTask; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateUpdateTask; -import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.common.Priority; import org.elasticsearch.core.Nullable; import org.elasticsearch.core.Strings; @@ -91,7 +90,8 @@ private ClusterState updateILMState(final ClusterState currentState) { return currentState; } - final OperationMode currentMode = currentILMMode(currentState.metadata().getProject()); + final var project = currentState.metadata().getProject(); + final OperationMode currentMode = currentILMMode(project); if (currentMode.equals(ilmMode)) { // No need for a new state return currentState; @@ -106,12 +106,8 @@ private ClusterState updateILMState(final ClusterState currentState) { } logger.info("updating ILM operation mode to {}", newMode); - return ClusterState.builder(currentState) - .metadata( - Metadata.builder(currentState.metadata()) - .putCustom(LifecycleOperationMetadata.TYPE, new LifecycleOperationMetadata(newMode, currentSLMMode(currentState))) - ) - .build(); + final var updatedMetadata = new LifecycleOperationMetadata(newMode, currentSLMMode(currentState)); + return currentState.copyAndUpdateProject(project.id(), b -> b.putCustom(LifecycleOperationMetadata.TYPE, updatedMetadata)); } private ClusterState updateSLMState(final ClusterState currentState) { @@ -119,6 +115,7 @@ private ClusterState updateSLMState(final ClusterState currentState) { return currentState; } + final var project = currentState.metadata().getProject(); final OperationMode currentMode = currentSLMMode(currentState); if (currentMode.equals(slmMode)) { // No need for a new state @@ -134,15 +131,8 @@ private ClusterState updateSLMState(final ClusterState currentState) { } logger.info("updating SLM operation mode to {}", newMode); - return ClusterState.builder(currentState) - .metadata( - Metadata.builder(currentState.metadata()) - .putCustom( - LifecycleOperationMetadata.TYPE, - new LifecycleOperationMetadata(currentILMMode(currentState.metadata().getProject()), newMode) - ) - ) - .build(); + final var updatedMetadata = new LifecycleOperationMetadata(currentILMMode(project), newMode); + return currentState.copyAndUpdateProject(project.id(), b -> b.putCustom(LifecycleOperationMetadata.TYPE, updatedMetadata)); } @Override diff --git a/x-pack/plugin/core/template-resources/src/main/resources/idp/saml-service-provider-template.json b/x-pack/plugin/core/template-resources/src/main/resources/idp/saml-service-provider-template.json index 4d307949c18db..e51ee1912bc13 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/idp/saml-service-provider-template.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/idp/saml-service-provider-template.json @@ -75,6 +75,9 @@ }, "roles": { "type": "keyword" + }, + "extensions": { + "type": "keyword" } } }, diff --git a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/predicate/regex/AbstractStringPattern.java b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/predicate/regex/AbstractStringPattern.java index 1de62f750346d..cd8f0b75839c8 100644 --- a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/predicate/regex/AbstractStringPattern.java +++ b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/predicate/regex/AbstractStringPattern.java @@ -32,7 +32,11 @@ public boolean matchesAll() { @Override public String exactMatch() { - IntsRef singleton = Operations.getSingleton(automaton()); + Automaton a = automaton(); + if (a.getNumStates() == 0) { // workaround for https://github.com/elastic/elasticsearch/pull/128887 + return null; // Empty automaton has no matches + } + IntsRef singleton = Operations.getSingleton(a); return singleton != null ? UnicodeUtil.newString(singleton.ints, singleton.offset, singleton.length) : null; } } diff --git a/x-pack/plugin/esql-core/src/test/java/org/elasticsearch/xpack/esql/core/expression/predicate/regex/StringPatternTests.java b/x-pack/plugin/esql-core/src/test/java/org/elasticsearch/xpack/esql/core/expression/predicate/regex/StringPatternTests.java index c361b7e3726ed..f0abdb3ecbcf0 100644 --- a/x-pack/plugin/esql-core/src/test/java/org/elasticsearch/xpack/esql/core/expression/predicate/regex/StringPatternTests.java +++ b/x-pack/plugin/esql-core/src/test/java/org/elasticsearch/xpack/esql/core/expression/predicate/regex/StringPatternTests.java @@ -33,8 +33,12 @@ private boolean rlikeMatchesAll(String pattern) { return rlike(pattern).matchesAll(); } + private String exactMatchRLike(String pattern) { + return rlike(pattern).exactMatch(); + } + private boolean rlikeExactMatch(String pattern) { - return pattern.equals(rlike(pattern).exactMatch()); + return pattern.equals(exactMatchRLike(pattern)); } public void testWildcardMatchAll() { @@ -86,4 +90,20 @@ public void testRegexExactMatch() { assertTrue(rlikeExactMatch("abc")); assertTrue(rlikeExactMatch("12345")); } + + public void testRegexExactMatchWithEmptyMatch() { + // As soon as there's one no conditional `#` in the pattern, it'll match nothing + assertNull(exactMatchRLike("#")); + assertNull(exactMatchRLike("##")); + assertNull(exactMatchRLike("#foo")); + assertNull(exactMatchRLike("#foo#")); + assertNull(exactMatchRLike("f#oo")); + assertNull(exactMatchRLike("foo#")); + assertNull(exactMatchRLike("#[A-Z]*")); + assertNull(exactMatchRLike("foo(#)")); + + assertNotNull(exactMatchRLike("foo#?")); + assertNotNull(exactMatchRLike("#|foo")); + assertNotNull(exactMatchRLike("foo|#")); + } } diff --git a/x-pack/plugin/esql-core/src/test/java/org/elasticsearch/xpack/esql/core/util/TestUtils.java b/x-pack/plugin/esql-core/src/test/java/org/elasticsearch/xpack/esql/core/util/TestUtils.java index 08426d84c898a..27b2b9fb620a2 100644 --- a/x-pack/plugin/esql-core/src/test/java/org/elasticsearch/xpack/esql/core/util/TestUtils.java +++ b/x-pack/plugin/esql-core/src/test/java/org/elasticsearch/xpack/esql/core/util/TestUtils.java @@ -66,8 +66,8 @@ public static String stripThrough(String input) { /** Returns the input string, but with parts of it having the letter casing changed. */ public static String randomCasing(String input) { StringBuilder sb = new StringBuilder(input.length()); - for (int i = 0, inputLen = input.length(), step = (int) Math.sqrt(inputLen), chunkEnd; i < inputLen; i += step) { - chunkEnd = Math.min(i + step, inputLen); + for (int i = 0, inputLen = input.length(), step = (int) Math.sqrt(inputLen); i < inputLen; i += step) { + var chunkEnd = Math.min(i + step, inputLen); var chunk = input.substring(i, chunkEnd); sb.append(randomBoolean() ? chunk.toLowerCase(Locale.ROOT) : chunk.toUpperCase(Locale.ROOT)); } diff --git a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/Page.java b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/Page.java index 4a08d9cf5dadd..1b59d4d9b9979 100644 --- a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/Page.java +++ b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/Page.java @@ -84,7 +84,7 @@ private Page(boolean copyBlocks, int positionCount, Block[] blocks) { private Page(Page prev, Block[] toAdd) { for (Block block : toAdd) { if (prev.positionCount != block.getPositionCount()) { - throw new IllegalArgumentException( + throw new IllegalStateException( "Block [" + block + "] does not have same position count: " + block.getPositionCount() + " != " + prev.positionCount ); } diff --git a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestEsqlTestCase.java b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestEsqlTestCase.java index 02324f02577e6..ce13a655966cd 100644 --- a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestEsqlTestCase.java +++ b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestEsqlTestCase.java @@ -1440,6 +1440,46 @@ public void testReplaceStringCasingWithInsensitiveWildcardMatch() throws IOExcep assertThat(answer.get("values"), equalTo(List.of(List.of("_\"_$_(_)_+_._[_]_^_{_|_}___", "_#_&_<_>___")))); } + public void testRLikeHandlingOfEmptyLanguagePattern() throws IOException { + createIndex(testIndexName(), Settings.EMPTY, """ + { + "properties": { + "field": { + "type": "keyword" + } + } + } + """); + for (var val : List.of("#", "foo#bar")) { + Request doc = new Request("POST", testIndexName() + "/_doc?refresh=true"); + doc.setJsonEntity(""" + { + "field": "%s" + } + """.formatted(val)); + client().performRequest(doc); + } + // pushed down, matches nothing + var query = "FROM " + testIndexName() + " | WHERE TO_LOWER(field) RLIKE \"#\""; + var answer = runEsql(requestObjectBuilder().query(query)); + assertThat(answer.get("values"), equalTo(List.of())); + + // matches nothing + query = "FROM " + testIndexName() + " | WHERE field RLIKE \"#\""; + answer = runEsql(requestObjectBuilder().query(query)); + assertThat(answer.get("values"), equalTo(List.of())); + + // matches one doc + query = "FROM " + testIndexName() + " | WHERE field RLIKE \"\\\\#\""; + answer = runEsql(requestObjectBuilder().query(query)); + assertThat(answer.get("values"), equalTo(List.of(List.of("#")))); + + // matches both docs + query = "FROM " + testIndexName() + " | WHERE field RLIKE \".*\\\\#.*\" | SORT field"; + answer = runEsql(requestObjectBuilder().query(query)); + assertThat(answer.get("values"), equalTo(List.of(List.of("#"), List.of("foo#bar")))); + } + protected static Request prepareRequestWithOptions(RequestObjectBuilder requestObject, Mode mode) throws IOException { requestObject.build(); Request request = prepareRequest(mode); diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/where-like.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/where-like.csv-spec index aa04878ea12d0..55ce333a60542 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/where-like.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/where-like.csv-spec @@ -423,3 +423,13 @@ emp_no:integer |first_name:keyword 10001 |Georgi 10055 |Georgy ; + +# test for https://github.com/elastic/elasticsearch/issues/128813 +rlikeWithEmptyLanguagePattern +required_capability: rlike_with_empty_language_pattern +ROW x = "abc" | EVAL bool = x RLIKE "#" +; + +x:keyword | bool:boolean +abc | false +; diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/LookupJoinTypesIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/LookupJoinTypesIT.java index 4070e11120ab9..fdf82bc73349d 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/LookupJoinTypesIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/LookupJoinTypesIT.java @@ -54,6 +54,7 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.SHORT; import static org.elasticsearch.xpack.esql.core.type.DataType.TEXT; import static org.elasticsearch.xpack.esql.core.type.DataType.TSID_DATA_TYPE; +import static org.elasticsearch.xpack.esql.core.type.DataType.UNDER_CONSTRUCTION; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; @@ -318,6 +319,9 @@ private void testLookupJoinTypes(String group) { initIndexes(group); initData(group); for (TestConfig config : testConfigurations.get(group).configs.values()) { + if ((isValidDataType(config.mainType()) && isValidDataType(config.lookupType())) == false) { + continue; + } String query = String.format( Locale.ROOT, "FROM index | LOOKUP JOIN %s ON %s | KEEP other", @@ -572,4 +576,8 @@ public void testQuery(String query) { assertion().accept(e); } } + + private boolean isValidDataType(DataType dataType) { + return UNDER_CONSTRUCTION.get(dataType) == null || UNDER_CONSTRUCTION.get(dataType).isEnabled(); + } } diff --git a/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.tokens b/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.tokens index 0915a8497975a..72217c4cb3062 100644 --- a/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.tokens +++ b/x-pack/plugin/esql/src/main/antlr/EsqlBaseLexer.tokens @@ -4,15 +4,15 @@ WS=3 CHANGE_POINT=4 ENRICH=5 EXPLAIN=6 -DISSECT=7 -EVAL=8 -GROK=9 -LIMIT=10 -ROW=11 -SORT=12 -STATS=13 -WHERE=14 -DEV_COMPLETION=15 +COMPLETION=7 +DISSECT=8 +EVAL=9 +GROK=10 +LIMIT=11 +ROW=12 +SORT=13 +STATS=14 +WHERE=15 DEV_INLINESTATS=16 DEV_RERANK=17 DEV_SAMPLE=18 @@ -140,14 +140,15 @@ SHOW_WS=139 'change_point'=4 'enrich'=5 'explain'=6 -'dissect'=7 -'eval'=8 -'grok'=9 -'limit'=10 -'row'=11 -'sort'=12 -'stats'=13 -'where'=14 +'completion'=7 +'dissect'=8 +'eval'=9 +'grok'=10 +'limit'=11 +'row'=12 +'sort'=13 +'stats'=14 +'where'=15 'from'=19 'lookup'=22 'mv_expand'=27 diff --git a/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.g4 b/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.g4 index 74142be3e2c06..3d48c50e95da0 100644 --- a/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.g4 +++ b/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.g4 @@ -56,10 +56,10 @@ processingCommand | mvExpandCommand | joinCommand | changePointCommand + | completionCommand // in development | {this.isDevVersion()}? inlinestatsCommand | {this.isDevVersion()}? lookupCommand - | {this.isDevVersion()}? completionCommand | {this.isDevVersion()}? insistCommand | {this.isDevVersion()}? forkCommand | {this.isDevVersion()}? rerankCommand @@ -308,7 +308,7 @@ rerankCommand ; completionCommand - : DEV_COMPLETION prompt=primaryExpression WITH inferenceId=identifierOrParameter (AS targetField=qualifiedName)? + : COMPLETION prompt=primaryExpression WITH inferenceId=identifierOrParameter (AS targetField=qualifiedName)? ; sampleCommand diff --git a/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.tokens b/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.tokens index 0915a8497975a..72217c4cb3062 100644 --- a/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.tokens +++ b/x-pack/plugin/esql/src/main/antlr/EsqlBaseParser.tokens @@ -4,15 +4,15 @@ WS=3 CHANGE_POINT=4 ENRICH=5 EXPLAIN=6 -DISSECT=7 -EVAL=8 -GROK=9 -LIMIT=10 -ROW=11 -SORT=12 -STATS=13 -WHERE=14 -DEV_COMPLETION=15 +COMPLETION=7 +DISSECT=8 +EVAL=9 +GROK=10 +LIMIT=11 +ROW=12 +SORT=13 +STATS=14 +WHERE=15 DEV_INLINESTATS=16 DEV_RERANK=17 DEV_SAMPLE=18 @@ -140,14 +140,15 @@ SHOW_WS=139 'change_point'=4 'enrich'=5 'explain'=6 -'dissect'=7 -'eval'=8 -'grok'=9 -'limit'=10 -'row'=11 -'sort'=12 -'stats'=13 -'where'=14 +'completion'=7 +'dissect'=8 +'eval'=9 +'grok'=10 +'limit'=11 +'row'=12 +'sort'=13 +'stats'=14 +'where'=15 'from'=19 'lookup'=22 'mv_expand'=27 diff --git a/x-pack/plugin/esql/src/main/antlr/lexer/Expression.g4 b/x-pack/plugin/esql/src/main/antlr/lexer/Expression.g4 index e5dc131943593..fe233ca949795 100644 --- a/x-pack/plugin/esql/src/main/antlr/lexer/Expression.g4 +++ b/x-pack/plugin/esql/src/main/antlr/lexer/Expression.g4 @@ -9,6 +9,7 @@ lexer grammar Expression; // // Expression - used by many commands // +COMPLETION : 'completion' -> pushMode(EXPRESSION_MODE); DISSECT : 'dissect' -> pushMode(EXPRESSION_MODE); EVAL : 'eval' -> pushMode(EXPRESSION_MODE); GROK : 'grok' -> pushMode(EXPRESSION_MODE); @@ -18,7 +19,6 @@ SORT : 'sort' -> pushMode(EXPRESSION_MODE); STATS : 'stats' -> pushMode(EXPRESSION_MODE); WHERE : 'where' -> pushMode(EXPRESSION_MODE); -DEV_COMPLETION : {this.isDevVersion()}? 'completion' -> pushMode(EXPRESSION_MODE); DEV_INLINESTATS : {this.isDevVersion()}? 'inlinestats' -> pushMode(EXPRESSION_MODE); DEV_RERANK : {this.isDevVersion()}? 'rerank' -> pushMode(EXPRESSION_MODE); DEV_SAMPLE : {this.isDevVersion()}? 'sample' -> pushMode(EXPRESSION_MODE); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java index a4953e8de07f9..2b86b1726d051 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java @@ -925,7 +925,7 @@ public enum Cap { /** * Support for COMPLETION command */ - COMPLETION(Build.current().isSnapshot()), + COMPLETION, /** * Allow mixed numeric types in conditional functions - case, greatest and least @@ -1177,6 +1177,11 @@ public enum Cap { */ ENABLE_LOOKUP_JOIN_ON_ALIASES, + /** + * Allows RLIKE to correctly handle the "empty language" flag, `#`. + */ + RLIKE_WITH_EMPTY_LANGUAGE_PATTERN, + /** * MATCH PHRASE function */ diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/regex/RegexMatch.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/regex/RegexMatch.java index eb5e06a686320..140bbd697ce9e 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/regex/RegexMatch.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/regex/RegexMatch.java @@ -72,22 +72,25 @@ public String nodeString() { } void serializeCaseInsensitivity(StreamOutput out) throws IOException { - if (out.getTransportVersion().before(TransportVersions.ESQL_REGEX_MATCH_WITH_CASE_INSENSITIVITY)) { - if (caseInsensitive()) { - // The plan has been optimized to run a case-insensitive match, which the remote peer cannot be notified of. Simply avoiding - // the serialization of the boolean would result in wrong results. - throw new EsqlIllegalArgumentException( - name() + " with case insensitivity is not supported in peer node's version [{}]. Upgrade to version [{}] or newer.", - out.getTransportVersion(), - TransportVersions.ESQL_REGEX_MATCH_WITH_CASE_INSENSITIVITY - ); - } // else: write nothing, the remote peer can execute the case-sensitive query - } else { + var transportVersion = out.getTransportVersion(); + if (transportVersion.onOrAfter(TransportVersions.ESQL_REGEX_MATCH_WITH_CASE_INSENSITIVITY) + || transportVersion.isPatchFrom(TransportVersions.ESQL_REGEX_MATCH_WITH_CASE_INSENSITIVITY_8_19)) { out.writeBoolean(caseInsensitive()); - } + } else if (caseInsensitive()) { + // The plan has been optimized to run a case-insensitive match, which the remote peer cannot be notified of. Simply avoiding + // the serialization of the boolean would result in wrong results. + throw new EsqlIllegalArgumentException( + name() + " with case insensitivity is not supported in peer node's version [{}]. Upgrade to version [{}, {}] or newer.", + transportVersion, + TransportVersions.ESQL_REGEX_MATCH_WITH_CASE_INSENSITIVITY_8_19, + TransportVersions.ESQL_REGEX_MATCH_WITH_CASE_INSENSITIVITY + ); + } // else: write nothing, the remote peer can execute the case-sensitive query } static boolean deserializeCaseInsensitivity(StreamInput in) throws IOException { - return in.getTransportVersion().onOrAfter(TransportVersions.ESQL_REGEX_MATCH_WITH_CASE_INSENSITIVITY) && in.readBoolean(); + var transportVersion = in.getTransportVersion(); + return (transportVersion.onOrAfter(TransportVersions.ESQL_REGEX_MATCH_WITH_CASE_INSENSITIVITY) + || transportVersion.isPatchFrom(TransportVersions.ESQL_REGEX_MATCH_WITH_CASE_INSENSITIVITY_8_19)) && in.readBoolean(); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.interp b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.interp index 4d36c154625a3..9eb7c41164a0f 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.interp +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.interp @@ -6,6 +6,7 @@ null 'change_point' 'enrich' 'explain' +'completion' 'dissect' 'eval' 'grok' @@ -17,7 +18,6 @@ null null null null -null 'from' null null @@ -148,6 +148,7 @@ WS CHANGE_POINT ENRICH EXPLAIN +COMPLETION DISSECT EVAL GROK @@ -156,7 +157,6 @@ ROW SORT STATS WHERE -DEV_COMPLETION DEV_INLINESTATS DEV_RERANK DEV_SAMPLE @@ -289,6 +289,7 @@ WS CHANGE_POINT ENRICH EXPLAIN +COMPLETION DISSECT EVAL GROK @@ -297,7 +298,6 @@ ROW SORT STATS WHERE -DEV_COMPLETION DEV_INLINESTATS DEV_RERANK DEV_SAMPLE @@ -545,4 +545,4 @@ RENAME_MODE SHOW_MODE atn: -[4, 0, 139, 1783, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, 2, 136, 7, 136, 2, 137, 7, 137, 2, 138, 7, 138, 2, 139, 7, 139, 2, 140, 7, 140, 2, 141, 7, 141, 2, 142, 7, 142, 2, 143, 7, 143, 2, 144, 7, 144, 2, 145, 7, 145, 2, 146, 7, 146, 2, 147, 7, 147, 2, 148, 7, 148, 2, 149, 7, 149, 2, 150, 7, 150, 2, 151, 7, 151, 2, 152, 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, 2, 155, 7, 155, 2, 156, 7, 156, 2, 157, 7, 157, 2, 158, 7, 158, 2, 159, 7, 159, 2, 160, 7, 160, 2, 161, 7, 161, 2, 162, 7, 162, 2, 163, 7, 163, 2, 164, 7, 164, 2, 165, 7, 165, 2, 166, 7, 166, 2, 167, 7, 167, 2, 168, 7, 168, 2, 169, 7, 169, 2, 170, 7, 170, 2, 171, 7, 171, 2, 172, 7, 172, 2, 173, 7, 173, 2, 174, 7, 174, 2, 175, 7, 175, 2, 176, 7, 176, 2, 177, 7, 177, 2, 178, 7, 178, 2, 179, 7, 179, 2, 180, 7, 180, 2, 181, 7, 181, 2, 182, 7, 182, 2, 183, 7, 183, 2, 184, 7, 184, 2, 185, 7, 185, 2, 186, 7, 186, 2, 187, 7, 187, 2, 188, 7, 188, 2, 189, 7, 189, 2, 190, 7, 190, 2, 191, 7, 191, 2, 192, 7, 192, 2, 193, 7, 193, 2, 194, 7, 194, 2, 195, 7, 195, 2, 196, 7, 196, 2, 197, 7, 197, 2, 198, 7, 198, 2, 199, 7, 199, 2, 200, 7, 200, 2, 201, 7, 201, 2, 202, 7, 202, 2, 203, 7, 203, 2, 204, 7, 204, 2, 205, 7, 205, 2, 206, 7, 206, 2, 207, 7, 207, 2, 208, 7, 208, 2, 209, 7, 209, 2, 210, 7, 210, 2, 211, 7, 211, 2, 212, 7, 212, 2, 213, 7, 213, 2, 214, 7, 214, 2, 215, 7, 215, 2, 216, 7, 216, 2, 217, 7, 217, 2, 218, 7, 218, 2, 219, 7, 219, 2, 220, 7, 220, 2, 221, 7, 221, 2, 222, 7, 222, 2, 223, 7, 223, 2, 224, 7, 224, 2, 225, 7, 225, 2, 226, 7, 226, 2, 227, 7, 227, 2, 228, 7, 228, 2, 229, 7, 229, 2, 230, 7, 230, 2, 231, 7, 231, 2, 232, 7, 232, 2, 233, 7, 233, 2, 234, 7, 234, 2, 235, 7, 235, 2, 236, 7, 236, 2, 237, 7, 237, 1, 0, 1, 0, 1, 0, 1, 0, 5, 0, 497, 8, 0, 10, 0, 12, 0, 500, 9, 0, 1, 0, 3, 0, 503, 8, 0, 1, 0, 3, 0, 506, 8, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 515, 8, 1, 10, 1, 12, 1, 518, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 2, 526, 8, 2, 11, 2, 12, 2, 527, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 33, 4, 33, 805, 8, 33, 11, 33, 12, 33, 806, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 49, 4, 49, 875, 8, 49, 11, 49, 12, 49, 876, 1, 49, 1, 49, 3, 49, 881, 8, 49, 1, 49, 4, 49, 884, 8, 49, 11, 49, 12, 49, 885, 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 4, 70, 976, 8, 70, 11, 70, 12, 70, 977, 1, 71, 1, 71, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 73, 1, 73, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 80, 1, 80, 1, 81, 1, 81, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 84, 1, 84, 3, 84, 1029, 8, 84, 1, 84, 4, 84, 1032, 8, 84, 11, 84, 12, 84, 1033, 1, 85, 1, 85, 1, 86, 1, 86, 1, 87, 1, 87, 1, 87, 3, 87, 1043, 8, 87, 1, 88, 1, 88, 1, 89, 1, 89, 1, 89, 3, 89, 1050, 8, 89, 1, 90, 1, 90, 1, 90, 5, 90, 1055, 8, 90, 10, 90, 12, 90, 1058, 9, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 5, 90, 1066, 8, 90, 10, 90, 12, 90, 1069, 9, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 3, 90, 1076, 8, 90, 1, 90, 3, 90, 1079, 8, 90, 3, 90, 1081, 8, 90, 1, 91, 4, 91, 1084, 8, 91, 11, 91, 12, 91, 1085, 1, 92, 4, 92, 1089, 8, 92, 11, 92, 12, 92, 1090, 1, 92, 1, 92, 5, 92, 1095, 8, 92, 10, 92, 12, 92, 1098, 9, 92, 1, 92, 1, 92, 4, 92, 1102, 8, 92, 11, 92, 12, 92, 1103, 1, 92, 4, 92, 1107, 8, 92, 11, 92, 12, 92, 1108, 1, 92, 1, 92, 5, 92, 1113, 8, 92, 10, 92, 12, 92, 1116, 9, 92, 3, 92, 1118, 8, 92, 1, 92, 1, 92, 1, 92, 1, 92, 4, 92, 1124, 8, 92, 11, 92, 12, 92, 1125, 1, 92, 1, 92, 3, 92, 1130, 8, 92, 1, 93, 1, 93, 1, 93, 1, 93, 1, 94, 1, 94, 1, 94, 1, 95, 1, 95, 1, 95, 1, 95, 1, 96, 1, 96, 1, 97, 1, 97, 1, 97, 1, 98, 1, 98, 1, 98, 1, 99, 1, 99, 1, 100, 1, 100, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 102, 1, 102, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 105, 1, 105, 1, 105, 1, 106, 1, 106, 1, 106, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 109, 1, 109, 1, 109, 1, 109, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 112, 1, 112, 1, 112, 1, 113, 1, 113, 1, 113, 1, 114, 1, 114, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 116, 1, 116, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 118, 1, 118, 1, 118, 1, 119, 1, 119, 1, 119, 1, 120, 1, 120, 1, 120, 1, 121, 1, 121, 1, 122, 1, 122, 1, 122, 1, 123, 1, 123, 1, 124, 1, 124, 1, 124, 1, 125, 1, 125, 1, 126, 1, 126, 1, 127, 1, 127, 1, 128, 1, 128, 1, 129, 1, 129, 1, 130, 1, 130, 1, 131, 1, 131, 1, 132, 1, 132, 1, 132, 1, 133, 1, 133, 1, 133, 1, 133, 1, 134, 1, 134, 1, 134, 3, 134, 1272, 8, 134, 1, 134, 5, 134, 1275, 8, 134, 10, 134, 12, 134, 1278, 9, 134, 1, 134, 1, 134, 4, 134, 1282, 8, 134, 11, 134, 12, 134, 1283, 3, 134, 1286, 8, 134, 1, 135, 1, 135, 1, 135, 3, 135, 1291, 8, 135, 1, 135, 5, 135, 1294, 8, 135, 10, 135, 12, 135, 1297, 9, 135, 1, 135, 1, 135, 4, 135, 1301, 8, 135, 11, 135, 12, 135, 1302, 3, 135, 1305, 8, 135, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 140, 1, 140, 5, 140, 1329, 8, 140, 10, 140, 12, 140, 1332, 9, 140, 1, 140, 1, 140, 3, 140, 1336, 8, 140, 1, 140, 4, 140, 1339, 8, 140, 11, 140, 12, 140, 1340, 3, 140, 1343, 8, 140, 1, 141, 1, 141, 4, 141, 1347, 8, 141, 11, 141, 12, 141, 1348, 1, 141, 1, 141, 1, 142, 1, 142, 1, 143, 1, 143, 1, 143, 1, 143, 1, 144, 1, 144, 1, 144, 1, 144, 1, 145, 1, 145, 1, 145, 1, 145, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 1, 147, 1, 147, 1, 147, 1, 147, 1, 148, 1, 148, 1, 148, 1, 148, 1, 149, 1, 149, 1, 149, 1, 149, 1, 150, 1, 150, 1, 150, 1, 150, 1, 151, 1, 151, 1, 151, 1, 151, 1, 152, 1, 152, 1, 152, 1, 152, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 154, 1, 154, 1, 154, 3, 154, 1408, 8, 154, 1, 155, 4, 155, 1411, 8, 155, 11, 155, 12, 155, 1412, 1, 156, 1, 156, 1, 156, 1, 156, 1, 157, 1, 157, 1, 157, 1, 157, 1, 158, 1, 158, 1, 158, 1, 158, 1, 159, 1, 159, 1, 159, 1, 159, 1, 160, 1, 160, 1, 160, 1, 160, 1, 161, 1, 161, 1, 161, 1, 161, 1, 161, 1, 162, 1, 162, 1, 162, 1, 162, 1, 162, 1, 163, 1, 163, 1, 163, 1, 163, 1, 164, 1, 164, 1, 164, 1, 164, 1, 165, 1, 165, 1, 165, 1, 165, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 168, 1, 168, 1, 168, 1, 168, 1, 169, 1, 169, 1, 169, 1, 169, 1, 169, 1, 169, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 171, 1, 171, 1, 171, 1, 171, 1, 172, 1, 172, 1, 172, 1, 172, 1, 173, 1, 173, 1, 173, 1, 173, 1, 174, 1, 174, 1, 174, 1, 174, 1, 175, 1, 175, 1, 175, 1, 175, 1, 176, 1, 176, 1, 176, 1, 176, 1, 177, 1, 177, 1, 177, 1, 177, 1, 178, 1, 178, 1, 178, 1, 178, 1, 179, 1, 179, 1, 179, 1, 179, 1, 179, 1, 180, 1, 180, 1, 180, 1, 180, 1, 181, 1, 181, 1, 181, 1, 181, 1, 182, 1, 182, 1, 182, 1, 182, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 184, 1, 184, 1, 184, 1, 184, 1, 185, 1, 185, 1, 185, 1, 185, 1, 186, 1, 186, 1, 186, 1, 186, 1, 187, 1, 187, 1, 187, 1, 187, 1, 188, 1, 188, 1, 188, 1, 188, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 190, 1, 190, 1, 190, 1, 190, 1, 191, 1, 191, 1, 191, 1, 191, 1, 192, 1, 192, 1, 192, 1, 192, 1, 193, 1, 193, 1, 193, 1, 193, 1, 194, 1, 194, 1, 194, 1, 194, 1, 195, 1, 195, 1, 195, 1, 195, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 197, 1, 197, 1, 197, 1, 197, 1, 198, 1, 198, 1, 198, 1, 198, 1, 199, 1, 199, 1, 199, 1, 199, 1, 200, 1, 200, 1, 200, 1, 200, 1, 201, 1, 201, 1, 201, 1, 201, 1, 202, 1, 202, 1, 202, 1, 202, 1, 203, 1, 203, 1, 203, 1, 203, 1, 204, 1, 204, 1, 204, 1, 204, 1, 205, 1, 205, 1, 205, 1, 205, 1, 206, 1, 206, 1, 206, 1, 206, 1, 207, 1, 207, 1, 207, 1, 207, 1, 207, 1, 208, 1, 208, 1, 208, 1, 208, 1, 209, 1, 209, 1, 209, 1, 209, 1, 210, 1, 210, 1, 210, 1, 210, 1, 211, 1, 211, 1, 211, 1, 211, 1, 212, 1, 212, 1, 212, 1, 212, 1, 213, 1, 213, 1, 213, 1, 213, 1, 214, 1, 214, 1, 214, 1, 214, 3, 214, 1668, 8, 214, 1, 215, 1, 215, 3, 215, 1672, 8, 215, 1, 215, 5, 215, 1675, 8, 215, 10, 215, 12, 215, 1678, 9, 215, 1, 215, 1, 215, 3, 215, 1682, 8, 215, 1, 215, 4, 215, 1685, 8, 215, 11, 215, 12, 215, 1686, 3, 215, 1689, 8, 215, 1, 216, 1, 216, 4, 216, 1693, 8, 216, 11, 216, 12, 216, 1694, 1, 217, 1, 217, 1, 217, 1, 217, 1, 218, 1, 218, 1, 218, 1, 218, 1, 219, 1, 219, 1, 219, 1, 219, 1, 220, 1, 220, 1, 220, 1, 220, 1, 220, 1, 221, 1, 221, 1, 221, 1, 221, 1, 222, 1, 222, 1, 222, 1, 222, 1, 223, 1, 223, 1, 223, 1, 223, 1, 224, 1, 224, 1, 224, 1, 224, 1, 225, 1, 225, 1, 225, 1, 225, 1, 226, 1, 226, 1, 226, 1, 226, 1, 227, 1, 227, 1, 227, 1, 227, 1, 228, 1, 228, 1, 228, 1, 228, 1, 229, 1, 229, 1, 229, 1, 229, 1, 230, 1, 230, 1, 230, 1, 230, 1, 231, 1, 231, 1, 231, 1, 231, 1, 232, 1, 232, 1, 232, 1, 232, 1, 233, 1, 233, 1, 233, 1, 233, 1, 233, 1, 234, 1, 234, 1, 234, 1, 234, 1, 234, 1, 235, 1, 235, 1, 235, 1, 235, 1, 236, 1, 236, 1, 236, 1, 236, 1, 237, 1, 237, 1, 237, 1, 237, 2, 516, 1067, 0, 238, 16, 1, 18, 2, 20, 3, 22, 4, 24, 5, 26, 6, 28, 7, 30, 8, 32, 9, 34, 10, 36, 11, 38, 12, 40, 13, 42, 14, 44, 15, 46, 16, 48, 17, 50, 18, 52, 19, 54, 20, 56, 21, 58, 22, 60, 23, 62, 24, 64, 25, 66, 26, 68, 27, 70, 28, 72, 29, 74, 30, 76, 31, 78, 32, 80, 33, 82, 34, 84, 0, 86, 0, 88, 0, 90, 0, 92, 0, 94, 0, 96, 0, 98, 35, 100, 36, 102, 37, 104, 0, 106, 0, 108, 0, 110, 0, 112, 0, 114, 38, 116, 0, 118, 39, 120, 40, 122, 41, 124, 0, 126, 0, 128, 0, 130, 0, 132, 0, 134, 0, 136, 0, 138, 0, 140, 0, 142, 0, 144, 0, 146, 42, 148, 43, 150, 44, 152, 0, 154, 0, 156, 45, 158, 46, 160, 47, 162, 48, 164, 0, 166, 0, 168, 49, 170, 50, 172, 51, 174, 52, 176, 0, 178, 0, 180, 0, 182, 0, 184, 0, 186, 0, 188, 0, 190, 0, 192, 0, 194, 0, 196, 53, 198, 54, 200, 55, 202, 56, 204, 57, 206, 58, 208, 59, 210, 60, 212, 61, 214, 62, 216, 63, 218, 64, 220, 65, 222, 66, 224, 67, 226, 68, 228, 69, 230, 70, 232, 71, 234, 72, 236, 73, 238, 74, 240, 75, 242, 76, 244, 77, 246, 78, 248, 79, 250, 80, 252, 81, 254, 82, 256, 83, 258, 84, 260, 85, 262, 86, 264, 87, 266, 88, 268, 89, 270, 90, 272, 91, 274, 92, 276, 93, 278, 94, 280, 95, 282, 0, 284, 96, 286, 97, 288, 98, 290, 99, 292, 100, 294, 101, 296, 102, 298, 0, 300, 103, 302, 104, 304, 105, 306, 106, 308, 0, 310, 0, 312, 0, 314, 0, 316, 0, 318, 0, 320, 0, 322, 107, 324, 0, 326, 108, 328, 0, 330, 0, 332, 109, 334, 110, 336, 111, 338, 0, 340, 0, 342, 112, 344, 113, 346, 114, 348, 0, 350, 115, 352, 0, 354, 0, 356, 116, 358, 0, 360, 0, 362, 0, 364, 0, 366, 0, 368, 117, 370, 118, 372, 119, 374, 0, 376, 0, 378, 0, 380, 0, 382, 0, 384, 0, 386, 0, 388, 120, 390, 121, 392, 122, 394, 0, 396, 0, 398, 0, 400, 0, 402, 123, 404, 124, 406, 125, 408, 0, 410, 0, 412, 0, 414, 0, 416, 0, 418, 0, 420, 0, 422, 0, 424, 126, 426, 127, 428, 128, 430, 0, 432, 0, 434, 0, 436, 0, 438, 0, 440, 0, 442, 0, 444, 0, 446, 0, 448, 129, 450, 130, 452, 131, 454, 132, 456, 0, 458, 0, 460, 0, 462, 0, 464, 0, 466, 0, 468, 0, 470, 0, 472, 0, 474, 0, 476, 133, 478, 134, 480, 135, 482, 0, 484, 136, 486, 137, 488, 138, 490, 139, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 36, 2, 0, 10, 10, 13, 13, 3, 0, 9, 10, 13, 13, 32, 32, 2, 0, 67, 67, 99, 99, 2, 0, 72, 72, 104, 104, 2, 0, 65, 65, 97, 97, 2, 0, 78, 78, 110, 110, 2, 0, 71, 71, 103, 103, 2, 0, 69, 69, 101, 101, 2, 0, 80, 80, 112, 112, 2, 0, 79, 79, 111, 111, 2, 0, 73, 73, 105, 105, 2, 0, 84, 84, 116, 116, 2, 0, 82, 82, 114, 114, 2, 0, 88, 88, 120, 120, 2, 0, 76, 76, 108, 108, 2, 0, 68, 68, 100, 100, 2, 0, 83, 83, 115, 115, 2, 0, 86, 86, 118, 118, 2, 0, 75, 75, 107, 107, 2, 0, 77, 77, 109, 109, 2, 0, 87, 87, 119, 119, 2, 0, 70, 70, 102, 102, 2, 0, 85, 85, 117, 117, 6, 0, 9, 10, 13, 13, 32, 32, 47, 47, 91, 91, 93, 93, 11, 0, 9, 10, 13, 13, 32, 32, 34, 35, 44, 44, 47, 47, 58, 58, 60, 60, 62, 63, 92, 92, 124, 124, 1, 0, 48, 57, 2, 0, 65, 90, 97, 122, 8, 0, 34, 34, 78, 78, 82, 82, 84, 84, 92, 92, 110, 110, 114, 114, 116, 116, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 2, 0, 43, 43, 45, 45, 1, 0, 96, 96, 2, 0, 66, 66, 98, 98, 2, 0, 89, 89, 121, 121, 11, 0, 9, 10, 13, 13, 32, 32, 34, 34, 44, 44, 47, 47, 58, 58, 61, 61, 91, 91, 93, 93, 124, 124, 2, 0, 42, 42, 47, 47, 2, 0, 74, 74, 106, 106, 1814, 0, 16, 1, 0, 0, 0, 0, 18, 1, 0, 0, 0, 0, 20, 1, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 24, 1, 0, 0, 0, 0, 26, 1, 0, 0, 0, 0, 28, 1, 0, 0, 0, 0, 30, 1, 0, 0, 0, 0, 32, 1, 0, 0, 0, 0, 34, 1, 0, 0, 0, 0, 36, 1, 0, 0, 0, 0, 38, 1, 0, 0, 0, 0, 40, 1, 0, 0, 0, 0, 42, 1, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 46, 1, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 50, 1, 0, 0, 0, 0, 52, 1, 0, 0, 0, 0, 54, 1, 0, 0, 0, 0, 56, 1, 0, 0, 0, 0, 58, 1, 0, 0, 0, 0, 60, 1, 0, 0, 0, 0, 62, 1, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0, 66, 1, 0, 0, 0, 0, 68, 1, 0, 0, 0, 0, 70, 1, 0, 0, 0, 0, 72, 1, 0, 0, 0, 0, 74, 1, 0, 0, 0, 0, 76, 1, 0, 0, 0, 0, 78, 1, 0, 0, 0, 0, 80, 1, 0, 0, 0, 0, 82, 1, 0, 0, 0, 1, 84, 1, 0, 0, 0, 1, 86, 1, 0, 0, 0, 1, 88, 1, 0, 0, 0, 1, 90, 1, 0, 0, 0, 1, 92, 1, 0, 0, 0, 1, 94, 1, 0, 0, 0, 1, 96, 1, 0, 0, 0, 1, 98, 1, 0, 0, 0, 1, 100, 1, 0, 0, 0, 1, 102, 1, 0, 0, 0, 2, 104, 1, 0, 0, 0, 2, 106, 1, 0, 0, 0, 2, 108, 1, 0, 0, 0, 2, 110, 1, 0, 0, 0, 2, 114, 1, 0, 0, 0, 2, 116, 1, 0, 0, 0, 2, 118, 1, 0, 0, 0, 2, 120, 1, 0, 0, 0, 2, 122, 1, 0, 0, 0, 3, 124, 1, 0, 0, 0, 3, 126, 1, 0, 0, 0, 3, 128, 1, 0, 0, 0, 3, 130, 1, 0, 0, 0, 3, 132, 1, 0, 0, 0, 3, 134, 1, 0, 0, 0, 3, 136, 1, 0, 0, 0, 3, 138, 1, 0, 0, 0, 3, 140, 1, 0, 0, 0, 3, 142, 1, 0, 0, 0, 3, 144, 1, 0, 0, 0, 3, 146, 1, 0, 0, 0, 3, 148, 1, 0, 0, 0, 3, 150, 1, 0, 0, 0, 4, 152, 1, 0, 0, 0, 4, 154, 1, 0, 0, 0, 4, 156, 1, 0, 0, 0, 4, 158, 1, 0, 0, 0, 4, 160, 1, 0, 0, 0, 4, 162, 1, 0, 0, 0, 5, 164, 1, 0, 0, 0, 5, 166, 1, 0, 0, 0, 5, 168, 1, 0, 0, 0, 5, 170, 1, 0, 0, 0, 5, 172, 1, 0, 0, 0, 6, 174, 1, 0, 0, 0, 6, 196, 1, 0, 0, 0, 6, 198, 1, 0, 0, 0, 6, 200, 1, 0, 0, 0, 6, 202, 1, 0, 0, 0, 6, 204, 1, 0, 0, 0, 6, 206, 1, 0, 0, 0, 6, 208, 1, 0, 0, 0, 6, 210, 1, 0, 0, 0, 6, 212, 1, 0, 0, 0, 6, 214, 1, 0, 0, 0, 6, 216, 1, 0, 0, 0, 6, 218, 1, 0, 0, 0, 6, 220, 1, 0, 0, 0, 6, 222, 1, 0, 0, 0, 6, 224, 1, 0, 0, 0, 6, 226, 1, 0, 0, 0, 6, 228, 1, 0, 0, 0, 6, 230, 1, 0, 0, 0, 6, 232, 1, 0, 0, 0, 6, 234, 1, 0, 0, 0, 6, 236, 1, 0, 0, 0, 6, 238, 1, 0, 0, 0, 6, 240, 1, 0, 0, 0, 6, 242, 1, 0, 0, 0, 6, 244, 1, 0, 0, 0, 6, 246, 1, 0, 0, 0, 6, 248, 1, 0, 0, 0, 6, 250, 1, 0, 0, 0, 6, 252, 1, 0, 0, 0, 6, 254, 1, 0, 0, 0, 6, 256, 1, 0, 0, 0, 6, 258, 1, 0, 0, 0, 6, 260, 1, 0, 0, 0, 6, 262, 1, 0, 0, 0, 6, 264, 1, 0, 0, 0, 6, 266, 1, 0, 0, 0, 6, 268, 1, 0, 0, 0, 6, 270, 1, 0, 0, 0, 6, 272, 1, 0, 0, 0, 6, 274, 1, 0, 0, 0, 6, 276, 1, 0, 0, 0, 6, 278, 1, 0, 0, 0, 6, 280, 1, 0, 0, 0, 6, 282, 1, 0, 0, 0, 6, 284, 1, 0, 0, 0, 6, 286, 1, 0, 0, 0, 6, 288, 1, 0, 0, 0, 6, 290, 1, 0, 0, 0, 6, 292, 1, 0, 0, 0, 6, 294, 1, 0, 0, 0, 6, 296, 1, 0, 0, 0, 6, 300, 1, 0, 0, 0, 6, 302, 1, 0, 0, 0, 6, 304, 1, 0, 0, 0, 6, 306, 1, 0, 0, 0, 7, 308, 1, 0, 0, 0, 7, 310, 1, 0, 0, 0, 7, 312, 1, 0, 0, 0, 7, 314, 1, 0, 0, 0, 7, 316, 1, 0, 0, 0, 7, 318, 1, 0, 0, 0, 7, 320, 1, 0, 0, 0, 7, 322, 1, 0, 0, 0, 7, 326, 1, 0, 0, 0, 7, 328, 1, 0, 0, 0, 7, 330, 1, 0, 0, 0, 7, 332, 1, 0, 0, 0, 7, 334, 1, 0, 0, 0, 7, 336, 1, 0, 0, 0, 8, 338, 1, 0, 0, 0, 8, 340, 1, 0, 0, 0, 8, 342, 1, 0, 0, 0, 8, 344, 1, 0, 0, 0, 8, 346, 1, 0, 0, 0, 9, 348, 1, 0, 0, 0, 9, 350, 1, 0, 0, 0, 9, 352, 1, 0, 0, 0, 9, 354, 1, 0, 0, 0, 9, 356, 1, 0, 0, 0, 9, 358, 1, 0, 0, 0, 9, 360, 1, 0, 0, 0, 9, 362, 1, 0, 0, 0, 9, 364, 1, 0, 0, 0, 9, 366, 1, 0, 0, 0, 9, 368, 1, 0, 0, 0, 9, 370, 1, 0, 0, 0, 9, 372, 1, 0, 0, 0, 10, 374, 1, 0, 0, 0, 10, 376, 1, 0, 0, 0, 10, 378, 1, 0, 0, 0, 10, 380, 1, 0, 0, 0, 10, 382, 1, 0, 0, 0, 10, 384, 1, 0, 0, 0, 10, 386, 1, 0, 0, 0, 10, 388, 1, 0, 0, 0, 10, 390, 1, 0, 0, 0, 10, 392, 1, 0, 0, 0, 11, 394, 1, 0, 0, 0, 11, 396, 1, 0, 0, 0, 11, 398, 1, 0, 0, 0, 11, 400, 1, 0, 0, 0, 11, 402, 1, 0, 0, 0, 11, 404, 1, 0, 0, 0, 11, 406, 1, 0, 0, 0, 12, 408, 1, 0, 0, 0, 12, 410, 1, 0, 0, 0, 12, 412, 1, 0, 0, 0, 12, 414, 1, 0, 0, 0, 12, 416, 1, 0, 0, 0, 12, 418, 1, 0, 0, 0, 12, 420, 1, 0, 0, 0, 12, 422, 1, 0, 0, 0, 12, 424, 1, 0, 0, 0, 12, 426, 1, 0, 0, 0, 12, 428, 1, 0, 0, 0, 13, 430, 1, 0, 0, 0, 13, 432, 1, 0, 0, 0, 13, 434, 1, 0, 0, 0, 13, 436, 1, 0, 0, 0, 13, 438, 1, 0, 0, 0, 13, 440, 1, 0, 0, 0, 13, 442, 1, 0, 0, 0, 13, 448, 1, 0, 0, 0, 13, 450, 1, 0, 0, 0, 13, 452, 1, 0, 0, 0, 13, 454, 1, 0, 0, 0, 14, 456, 1, 0, 0, 0, 14, 458, 1, 0, 0, 0, 14, 460, 1, 0, 0, 0, 14, 462, 1, 0, 0, 0, 14, 464, 1, 0, 0, 0, 14, 466, 1, 0, 0, 0, 14, 468, 1, 0, 0, 0, 14, 470, 1, 0, 0, 0, 14, 472, 1, 0, 0, 0, 14, 474, 1, 0, 0, 0, 14, 476, 1, 0, 0, 0, 14, 478, 1, 0, 0, 0, 14, 480, 1, 0, 0, 0, 15, 482, 1, 0, 0, 0, 15, 484, 1, 0, 0, 0, 15, 486, 1, 0, 0, 0, 15, 488, 1, 0, 0, 0, 15, 490, 1, 0, 0, 0, 16, 492, 1, 0, 0, 0, 18, 509, 1, 0, 0, 0, 20, 525, 1, 0, 0, 0, 22, 531, 1, 0, 0, 0, 24, 546, 1, 0, 0, 0, 26, 555, 1, 0, 0, 0, 28, 565, 1, 0, 0, 0, 30, 575, 1, 0, 0, 0, 32, 582, 1, 0, 0, 0, 34, 589, 1, 0, 0, 0, 36, 597, 1, 0, 0, 0, 38, 603, 1, 0, 0, 0, 40, 610, 1, 0, 0, 0, 42, 618, 1, 0, 0, 0, 44, 626, 1, 0, 0, 0, 46, 640, 1, 0, 0, 0, 48, 655, 1, 0, 0, 0, 50, 665, 1, 0, 0, 0, 52, 675, 1, 0, 0, 0, 54, 682, 1, 0, 0, 0, 56, 688, 1, 0, 0, 0, 58, 696, 1, 0, 0, 0, 60, 705, 1, 0, 0, 0, 62, 713, 1, 0, 0, 0, 64, 721, 1, 0, 0, 0, 66, 730, 1, 0, 0, 0, 68, 742, 1, 0, 0, 0, 70, 754, 1, 0, 0, 0, 72, 761, 1, 0, 0, 0, 74, 768, 1, 0, 0, 0, 76, 780, 1, 0, 0, 0, 78, 787, 1, 0, 0, 0, 80, 796, 1, 0, 0, 0, 82, 804, 1, 0, 0, 0, 84, 810, 1, 0, 0, 0, 86, 815, 1, 0, 0, 0, 88, 819, 1, 0, 0, 0, 90, 823, 1, 0, 0, 0, 92, 827, 1, 0, 0, 0, 94, 831, 1, 0, 0, 0, 96, 835, 1, 0, 0, 0, 98, 839, 1, 0, 0, 0, 100, 843, 1, 0, 0, 0, 102, 847, 1, 0, 0, 0, 104, 851, 1, 0, 0, 0, 106, 856, 1, 0, 0, 0, 108, 861, 1, 0, 0, 0, 110, 866, 1, 0, 0, 0, 112, 871, 1, 0, 0, 0, 114, 880, 1, 0, 0, 0, 116, 887, 1, 0, 0, 0, 118, 891, 1, 0, 0, 0, 120, 895, 1, 0, 0, 0, 122, 899, 1, 0, 0, 0, 124, 903, 1, 0, 0, 0, 126, 909, 1, 0, 0, 0, 128, 913, 1, 0, 0, 0, 130, 917, 1, 0, 0, 0, 132, 921, 1, 0, 0, 0, 134, 925, 1, 0, 0, 0, 136, 929, 1, 0, 0, 0, 138, 933, 1, 0, 0, 0, 140, 937, 1, 0, 0, 0, 142, 941, 1, 0, 0, 0, 144, 945, 1, 0, 0, 0, 146, 949, 1, 0, 0, 0, 148, 953, 1, 0, 0, 0, 150, 957, 1, 0, 0, 0, 152, 961, 1, 0, 0, 0, 154, 966, 1, 0, 0, 0, 156, 975, 1, 0, 0, 0, 158, 979, 1, 0, 0, 0, 160, 983, 1, 0, 0, 0, 162, 987, 1, 0, 0, 0, 164, 991, 1, 0, 0, 0, 166, 996, 1, 0, 0, 0, 168, 1001, 1, 0, 0, 0, 170, 1005, 1, 0, 0, 0, 172, 1009, 1, 0, 0, 0, 174, 1013, 1, 0, 0, 0, 176, 1017, 1, 0, 0, 0, 178, 1019, 1, 0, 0, 0, 180, 1021, 1, 0, 0, 0, 182, 1024, 1, 0, 0, 0, 184, 1026, 1, 0, 0, 0, 186, 1035, 1, 0, 0, 0, 188, 1037, 1, 0, 0, 0, 190, 1042, 1, 0, 0, 0, 192, 1044, 1, 0, 0, 0, 194, 1049, 1, 0, 0, 0, 196, 1080, 1, 0, 0, 0, 198, 1083, 1, 0, 0, 0, 200, 1129, 1, 0, 0, 0, 202, 1131, 1, 0, 0, 0, 204, 1135, 1, 0, 0, 0, 206, 1138, 1, 0, 0, 0, 208, 1142, 1, 0, 0, 0, 210, 1144, 1, 0, 0, 0, 212, 1147, 1, 0, 0, 0, 214, 1150, 1, 0, 0, 0, 216, 1152, 1, 0, 0, 0, 218, 1154, 1, 0, 0, 0, 220, 1159, 1, 0, 0, 0, 222, 1161, 1, 0, 0, 0, 224, 1167, 1, 0, 0, 0, 226, 1173, 1, 0, 0, 0, 228, 1176, 1, 0, 0, 0, 230, 1179, 1, 0, 0, 0, 232, 1184, 1, 0, 0, 0, 234, 1189, 1, 0, 0, 0, 236, 1193, 1, 0, 0, 0, 238, 1198, 1, 0, 0, 0, 240, 1204, 1, 0, 0, 0, 242, 1207, 1, 0, 0, 0, 244, 1210, 1, 0, 0, 0, 246, 1212, 1, 0, 0, 0, 248, 1218, 1, 0, 0, 0, 250, 1223, 1, 0, 0, 0, 252, 1228, 1, 0, 0, 0, 254, 1231, 1, 0, 0, 0, 256, 1234, 1, 0, 0, 0, 258, 1237, 1, 0, 0, 0, 260, 1239, 1, 0, 0, 0, 262, 1242, 1, 0, 0, 0, 264, 1244, 1, 0, 0, 0, 266, 1247, 1, 0, 0, 0, 268, 1249, 1, 0, 0, 0, 270, 1251, 1, 0, 0, 0, 272, 1253, 1, 0, 0, 0, 274, 1255, 1, 0, 0, 0, 276, 1257, 1, 0, 0, 0, 278, 1259, 1, 0, 0, 0, 280, 1261, 1, 0, 0, 0, 282, 1264, 1, 0, 0, 0, 284, 1285, 1, 0, 0, 0, 286, 1304, 1, 0, 0, 0, 288, 1306, 1, 0, 0, 0, 290, 1311, 1, 0, 0, 0, 292, 1316, 1, 0, 0, 0, 294, 1321, 1, 0, 0, 0, 296, 1342, 1, 0, 0, 0, 298, 1344, 1, 0, 0, 0, 300, 1352, 1, 0, 0, 0, 302, 1354, 1, 0, 0, 0, 304, 1358, 1, 0, 0, 0, 306, 1362, 1, 0, 0, 0, 308, 1366, 1, 0, 0, 0, 310, 1371, 1, 0, 0, 0, 312, 1375, 1, 0, 0, 0, 314, 1379, 1, 0, 0, 0, 316, 1383, 1, 0, 0, 0, 318, 1387, 1, 0, 0, 0, 320, 1391, 1, 0, 0, 0, 322, 1395, 1, 0, 0, 0, 324, 1407, 1, 0, 0, 0, 326, 1410, 1, 0, 0, 0, 328, 1414, 1, 0, 0, 0, 330, 1418, 1, 0, 0, 0, 332, 1422, 1, 0, 0, 0, 334, 1426, 1, 0, 0, 0, 336, 1430, 1, 0, 0, 0, 338, 1434, 1, 0, 0, 0, 340, 1439, 1, 0, 0, 0, 342, 1444, 1, 0, 0, 0, 344, 1448, 1, 0, 0, 0, 346, 1452, 1, 0, 0, 0, 348, 1456, 1, 0, 0, 0, 350, 1461, 1, 0, 0, 0, 352, 1466, 1, 0, 0, 0, 354, 1470, 1, 0, 0, 0, 356, 1476, 1, 0, 0, 0, 358, 1485, 1, 0, 0, 0, 360, 1489, 1, 0, 0, 0, 362, 1493, 1, 0, 0, 0, 364, 1497, 1, 0, 0, 0, 366, 1501, 1, 0, 0, 0, 368, 1505, 1, 0, 0, 0, 370, 1509, 1, 0, 0, 0, 372, 1513, 1, 0, 0, 0, 374, 1517, 1, 0, 0, 0, 376, 1522, 1, 0, 0, 0, 378, 1526, 1, 0, 0, 0, 380, 1530, 1, 0, 0, 0, 382, 1534, 1, 0, 0, 0, 384, 1539, 1, 0, 0, 0, 386, 1543, 1, 0, 0, 0, 388, 1547, 1, 0, 0, 0, 390, 1551, 1, 0, 0, 0, 392, 1555, 1, 0, 0, 0, 394, 1559, 1, 0, 0, 0, 396, 1565, 1, 0, 0, 0, 398, 1569, 1, 0, 0, 0, 400, 1573, 1, 0, 0, 0, 402, 1577, 1, 0, 0, 0, 404, 1581, 1, 0, 0, 0, 406, 1585, 1, 0, 0, 0, 408, 1589, 1, 0, 0, 0, 410, 1594, 1, 0, 0, 0, 412, 1598, 1, 0, 0, 0, 414, 1602, 1, 0, 0, 0, 416, 1606, 1, 0, 0, 0, 418, 1610, 1, 0, 0, 0, 420, 1614, 1, 0, 0, 0, 422, 1618, 1, 0, 0, 0, 424, 1622, 1, 0, 0, 0, 426, 1626, 1, 0, 0, 0, 428, 1630, 1, 0, 0, 0, 430, 1634, 1, 0, 0, 0, 432, 1639, 1, 0, 0, 0, 434, 1643, 1, 0, 0, 0, 436, 1647, 1, 0, 0, 0, 438, 1651, 1, 0, 0, 0, 440, 1655, 1, 0, 0, 0, 442, 1659, 1, 0, 0, 0, 444, 1667, 1, 0, 0, 0, 446, 1688, 1, 0, 0, 0, 448, 1692, 1, 0, 0, 0, 450, 1696, 1, 0, 0, 0, 452, 1700, 1, 0, 0, 0, 454, 1704, 1, 0, 0, 0, 456, 1708, 1, 0, 0, 0, 458, 1713, 1, 0, 0, 0, 460, 1717, 1, 0, 0, 0, 462, 1721, 1, 0, 0, 0, 464, 1725, 1, 0, 0, 0, 466, 1729, 1, 0, 0, 0, 468, 1733, 1, 0, 0, 0, 470, 1737, 1, 0, 0, 0, 472, 1741, 1, 0, 0, 0, 474, 1745, 1, 0, 0, 0, 476, 1749, 1, 0, 0, 0, 478, 1753, 1, 0, 0, 0, 480, 1757, 1, 0, 0, 0, 482, 1761, 1, 0, 0, 0, 484, 1766, 1, 0, 0, 0, 486, 1771, 1, 0, 0, 0, 488, 1775, 1, 0, 0, 0, 490, 1779, 1, 0, 0, 0, 492, 493, 5, 47, 0, 0, 493, 494, 5, 47, 0, 0, 494, 498, 1, 0, 0, 0, 495, 497, 8, 0, 0, 0, 496, 495, 1, 0, 0, 0, 497, 500, 1, 0, 0, 0, 498, 496, 1, 0, 0, 0, 498, 499, 1, 0, 0, 0, 499, 502, 1, 0, 0, 0, 500, 498, 1, 0, 0, 0, 501, 503, 5, 13, 0, 0, 502, 501, 1, 0, 0, 0, 502, 503, 1, 0, 0, 0, 503, 505, 1, 0, 0, 0, 504, 506, 5, 10, 0, 0, 505, 504, 1, 0, 0, 0, 505, 506, 1, 0, 0, 0, 506, 507, 1, 0, 0, 0, 507, 508, 6, 0, 0, 0, 508, 17, 1, 0, 0, 0, 509, 510, 5, 47, 0, 0, 510, 511, 5, 42, 0, 0, 511, 516, 1, 0, 0, 0, 512, 515, 3, 18, 1, 0, 513, 515, 9, 0, 0, 0, 514, 512, 1, 0, 0, 0, 514, 513, 1, 0, 0, 0, 515, 518, 1, 0, 0, 0, 516, 517, 1, 0, 0, 0, 516, 514, 1, 0, 0, 0, 517, 519, 1, 0, 0, 0, 518, 516, 1, 0, 0, 0, 519, 520, 5, 42, 0, 0, 520, 521, 5, 47, 0, 0, 521, 522, 1, 0, 0, 0, 522, 523, 6, 1, 0, 0, 523, 19, 1, 0, 0, 0, 524, 526, 7, 1, 0, 0, 525, 524, 1, 0, 0, 0, 526, 527, 1, 0, 0, 0, 527, 525, 1, 0, 0, 0, 527, 528, 1, 0, 0, 0, 528, 529, 1, 0, 0, 0, 529, 530, 6, 2, 0, 0, 530, 21, 1, 0, 0, 0, 531, 532, 7, 2, 0, 0, 532, 533, 7, 3, 0, 0, 533, 534, 7, 4, 0, 0, 534, 535, 7, 5, 0, 0, 535, 536, 7, 6, 0, 0, 536, 537, 7, 7, 0, 0, 537, 538, 5, 95, 0, 0, 538, 539, 7, 8, 0, 0, 539, 540, 7, 9, 0, 0, 540, 541, 7, 10, 0, 0, 541, 542, 7, 5, 0, 0, 542, 543, 7, 11, 0, 0, 543, 544, 1, 0, 0, 0, 544, 545, 6, 3, 1, 0, 545, 23, 1, 0, 0, 0, 546, 547, 7, 7, 0, 0, 547, 548, 7, 5, 0, 0, 548, 549, 7, 12, 0, 0, 549, 550, 7, 10, 0, 0, 550, 551, 7, 2, 0, 0, 551, 552, 7, 3, 0, 0, 552, 553, 1, 0, 0, 0, 553, 554, 6, 4, 2, 0, 554, 25, 1, 0, 0, 0, 555, 556, 7, 7, 0, 0, 556, 557, 7, 13, 0, 0, 557, 558, 7, 8, 0, 0, 558, 559, 7, 14, 0, 0, 559, 560, 7, 4, 0, 0, 560, 561, 7, 10, 0, 0, 561, 562, 7, 5, 0, 0, 562, 563, 1, 0, 0, 0, 563, 564, 6, 5, 3, 0, 564, 27, 1, 0, 0, 0, 565, 566, 7, 15, 0, 0, 566, 567, 7, 10, 0, 0, 567, 568, 7, 16, 0, 0, 568, 569, 7, 16, 0, 0, 569, 570, 7, 7, 0, 0, 570, 571, 7, 2, 0, 0, 571, 572, 7, 11, 0, 0, 572, 573, 1, 0, 0, 0, 573, 574, 6, 6, 4, 0, 574, 29, 1, 0, 0, 0, 575, 576, 7, 7, 0, 0, 576, 577, 7, 17, 0, 0, 577, 578, 7, 4, 0, 0, 578, 579, 7, 14, 0, 0, 579, 580, 1, 0, 0, 0, 580, 581, 6, 7, 4, 0, 581, 31, 1, 0, 0, 0, 582, 583, 7, 6, 0, 0, 583, 584, 7, 12, 0, 0, 584, 585, 7, 9, 0, 0, 585, 586, 7, 18, 0, 0, 586, 587, 1, 0, 0, 0, 587, 588, 6, 8, 4, 0, 588, 33, 1, 0, 0, 0, 589, 590, 7, 14, 0, 0, 590, 591, 7, 10, 0, 0, 591, 592, 7, 19, 0, 0, 592, 593, 7, 10, 0, 0, 593, 594, 7, 11, 0, 0, 594, 595, 1, 0, 0, 0, 595, 596, 6, 9, 4, 0, 596, 35, 1, 0, 0, 0, 597, 598, 7, 12, 0, 0, 598, 599, 7, 9, 0, 0, 599, 600, 7, 20, 0, 0, 600, 601, 1, 0, 0, 0, 601, 602, 6, 10, 4, 0, 602, 37, 1, 0, 0, 0, 603, 604, 7, 16, 0, 0, 604, 605, 7, 9, 0, 0, 605, 606, 7, 12, 0, 0, 606, 607, 7, 11, 0, 0, 607, 608, 1, 0, 0, 0, 608, 609, 6, 11, 4, 0, 609, 39, 1, 0, 0, 0, 610, 611, 7, 16, 0, 0, 611, 612, 7, 11, 0, 0, 612, 613, 7, 4, 0, 0, 613, 614, 7, 11, 0, 0, 614, 615, 7, 16, 0, 0, 615, 616, 1, 0, 0, 0, 616, 617, 6, 12, 4, 0, 617, 41, 1, 0, 0, 0, 618, 619, 7, 20, 0, 0, 619, 620, 7, 3, 0, 0, 620, 621, 7, 7, 0, 0, 621, 622, 7, 12, 0, 0, 622, 623, 7, 7, 0, 0, 623, 624, 1, 0, 0, 0, 624, 625, 6, 13, 4, 0, 625, 43, 1, 0, 0, 0, 626, 627, 4, 14, 0, 0, 627, 628, 7, 2, 0, 0, 628, 629, 7, 9, 0, 0, 629, 630, 7, 19, 0, 0, 630, 631, 7, 8, 0, 0, 631, 632, 7, 14, 0, 0, 632, 633, 7, 7, 0, 0, 633, 634, 7, 11, 0, 0, 634, 635, 7, 10, 0, 0, 635, 636, 7, 9, 0, 0, 636, 637, 7, 5, 0, 0, 637, 638, 1, 0, 0, 0, 638, 639, 6, 14, 4, 0, 639, 45, 1, 0, 0, 0, 640, 641, 4, 15, 1, 0, 641, 642, 7, 10, 0, 0, 642, 643, 7, 5, 0, 0, 643, 644, 7, 14, 0, 0, 644, 645, 7, 10, 0, 0, 645, 646, 7, 5, 0, 0, 646, 647, 7, 7, 0, 0, 647, 648, 7, 16, 0, 0, 648, 649, 7, 11, 0, 0, 649, 650, 7, 4, 0, 0, 650, 651, 7, 11, 0, 0, 651, 652, 7, 16, 0, 0, 652, 653, 1, 0, 0, 0, 653, 654, 6, 15, 4, 0, 654, 47, 1, 0, 0, 0, 655, 656, 4, 16, 2, 0, 656, 657, 7, 12, 0, 0, 657, 658, 7, 7, 0, 0, 658, 659, 7, 12, 0, 0, 659, 660, 7, 4, 0, 0, 660, 661, 7, 5, 0, 0, 661, 662, 7, 18, 0, 0, 662, 663, 1, 0, 0, 0, 663, 664, 6, 16, 4, 0, 664, 49, 1, 0, 0, 0, 665, 666, 4, 17, 3, 0, 666, 667, 7, 16, 0, 0, 667, 668, 7, 4, 0, 0, 668, 669, 7, 19, 0, 0, 669, 670, 7, 8, 0, 0, 670, 671, 7, 14, 0, 0, 671, 672, 7, 7, 0, 0, 672, 673, 1, 0, 0, 0, 673, 674, 6, 17, 4, 0, 674, 51, 1, 0, 0, 0, 675, 676, 7, 21, 0, 0, 676, 677, 7, 12, 0, 0, 677, 678, 7, 9, 0, 0, 678, 679, 7, 19, 0, 0, 679, 680, 1, 0, 0, 0, 680, 681, 6, 18, 5, 0, 681, 53, 1, 0, 0, 0, 682, 683, 4, 19, 4, 0, 683, 684, 7, 11, 0, 0, 684, 685, 7, 16, 0, 0, 685, 686, 1, 0, 0, 0, 686, 687, 6, 19, 5, 0, 687, 55, 1, 0, 0, 0, 688, 689, 4, 20, 5, 0, 689, 690, 7, 21, 0, 0, 690, 691, 7, 9, 0, 0, 691, 692, 7, 12, 0, 0, 692, 693, 7, 18, 0, 0, 693, 694, 1, 0, 0, 0, 694, 695, 6, 20, 6, 0, 695, 57, 1, 0, 0, 0, 696, 697, 7, 14, 0, 0, 697, 698, 7, 9, 0, 0, 698, 699, 7, 9, 0, 0, 699, 700, 7, 18, 0, 0, 700, 701, 7, 22, 0, 0, 701, 702, 7, 8, 0, 0, 702, 703, 1, 0, 0, 0, 703, 704, 6, 21, 7, 0, 704, 59, 1, 0, 0, 0, 705, 706, 4, 22, 6, 0, 706, 707, 7, 21, 0, 0, 707, 708, 7, 22, 0, 0, 708, 709, 7, 14, 0, 0, 709, 710, 7, 14, 0, 0, 710, 711, 1, 0, 0, 0, 711, 712, 6, 22, 7, 0, 712, 61, 1, 0, 0, 0, 713, 714, 4, 23, 7, 0, 714, 715, 7, 14, 0, 0, 715, 716, 7, 7, 0, 0, 716, 717, 7, 21, 0, 0, 717, 718, 7, 11, 0, 0, 718, 719, 1, 0, 0, 0, 719, 720, 6, 23, 7, 0, 720, 63, 1, 0, 0, 0, 721, 722, 4, 24, 8, 0, 722, 723, 7, 12, 0, 0, 723, 724, 7, 10, 0, 0, 724, 725, 7, 6, 0, 0, 725, 726, 7, 3, 0, 0, 726, 727, 7, 11, 0, 0, 727, 728, 1, 0, 0, 0, 728, 729, 6, 24, 7, 0, 729, 65, 1, 0, 0, 0, 730, 731, 4, 25, 9, 0, 731, 732, 7, 14, 0, 0, 732, 733, 7, 9, 0, 0, 733, 734, 7, 9, 0, 0, 734, 735, 7, 18, 0, 0, 735, 736, 7, 22, 0, 0, 736, 737, 7, 8, 0, 0, 737, 738, 5, 95, 0, 0, 738, 739, 5, 128020, 0, 0, 739, 740, 1, 0, 0, 0, 740, 741, 6, 25, 8, 0, 741, 67, 1, 0, 0, 0, 742, 743, 7, 19, 0, 0, 743, 744, 7, 17, 0, 0, 744, 745, 5, 95, 0, 0, 745, 746, 7, 7, 0, 0, 746, 747, 7, 13, 0, 0, 747, 748, 7, 8, 0, 0, 748, 749, 7, 4, 0, 0, 749, 750, 7, 5, 0, 0, 750, 751, 7, 15, 0, 0, 751, 752, 1, 0, 0, 0, 752, 753, 6, 26, 9, 0, 753, 69, 1, 0, 0, 0, 754, 755, 7, 15, 0, 0, 755, 756, 7, 12, 0, 0, 756, 757, 7, 9, 0, 0, 757, 758, 7, 8, 0, 0, 758, 759, 1, 0, 0, 0, 759, 760, 6, 27, 10, 0, 760, 71, 1, 0, 0, 0, 761, 762, 7, 18, 0, 0, 762, 763, 7, 7, 0, 0, 763, 764, 7, 7, 0, 0, 764, 765, 7, 8, 0, 0, 765, 766, 1, 0, 0, 0, 766, 767, 6, 28, 10, 0, 767, 73, 1, 0, 0, 0, 768, 769, 4, 29, 10, 0, 769, 770, 7, 10, 0, 0, 770, 771, 7, 5, 0, 0, 771, 772, 7, 16, 0, 0, 772, 773, 7, 10, 0, 0, 773, 774, 7, 16, 0, 0, 774, 775, 7, 11, 0, 0, 775, 776, 5, 95, 0, 0, 776, 777, 5, 128020, 0, 0, 777, 778, 1, 0, 0, 0, 778, 779, 6, 29, 10, 0, 779, 75, 1, 0, 0, 0, 780, 781, 4, 30, 11, 0, 781, 782, 7, 12, 0, 0, 782, 783, 7, 12, 0, 0, 783, 784, 7, 21, 0, 0, 784, 785, 1, 0, 0, 0, 785, 786, 6, 30, 4, 0, 786, 77, 1, 0, 0, 0, 787, 788, 7, 12, 0, 0, 788, 789, 7, 7, 0, 0, 789, 790, 7, 5, 0, 0, 790, 791, 7, 4, 0, 0, 791, 792, 7, 19, 0, 0, 792, 793, 7, 7, 0, 0, 793, 794, 1, 0, 0, 0, 794, 795, 6, 31, 11, 0, 795, 79, 1, 0, 0, 0, 796, 797, 7, 16, 0, 0, 797, 798, 7, 3, 0, 0, 798, 799, 7, 9, 0, 0, 799, 800, 7, 20, 0, 0, 800, 801, 1, 0, 0, 0, 801, 802, 6, 32, 12, 0, 802, 81, 1, 0, 0, 0, 803, 805, 8, 23, 0, 0, 804, 803, 1, 0, 0, 0, 805, 806, 1, 0, 0, 0, 806, 804, 1, 0, 0, 0, 806, 807, 1, 0, 0, 0, 807, 808, 1, 0, 0, 0, 808, 809, 6, 33, 4, 0, 809, 83, 1, 0, 0, 0, 810, 811, 3, 174, 79, 0, 811, 812, 1, 0, 0, 0, 812, 813, 6, 34, 13, 0, 813, 814, 6, 34, 14, 0, 814, 85, 1, 0, 0, 0, 815, 816, 3, 240, 112, 0, 816, 817, 1, 0, 0, 0, 817, 818, 6, 35, 15, 0, 818, 87, 1, 0, 0, 0, 819, 820, 3, 204, 94, 0, 820, 821, 1, 0, 0, 0, 821, 822, 6, 36, 16, 0, 822, 89, 1, 0, 0, 0, 823, 824, 3, 220, 102, 0, 824, 825, 1, 0, 0, 0, 825, 826, 6, 37, 17, 0, 826, 91, 1, 0, 0, 0, 827, 828, 3, 216, 100, 0, 828, 829, 1, 0, 0, 0, 829, 830, 6, 38, 18, 0, 830, 93, 1, 0, 0, 0, 831, 832, 3, 300, 142, 0, 832, 833, 1, 0, 0, 0, 833, 834, 6, 39, 19, 0, 834, 95, 1, 0, 0, 0, 835, 836, 3, 296, 140, 0, 836, 837, 1, 0, 0, 0, 837, 838, 6, 40, 20, 0, 838, 97, 1, 0, 0, 0, 839, 840, 3, 16, 0, 0, 840, 841, 1, 0, 0, 0, 841, 842, 6, 41, 0, 0, 842, 99, 1, 0, 0, 0, 843, 844, 3, 18, 1, 0, 844, 845, 1, 0, 0, 0, 845, 846, 6, 42, 0, 0, 846, 101, 1, 0, 0, 0, 847, 848, 3, 20, 2, 0, 848, 849, 1, 0, 0, 0, 849, 850, 6, 43, 0, 0, 850, 103, 1, 0, 0, 0, 851, 852, 3, 174, 79, 0, 852, 853, 1, 0, 0, 0, 853, 854, 6, 44, 13, 0, 854, 855, 6, 44, 14, 0, 855, 105, 1, 0, 0, 0, 856, 857, 3, 288, 136, 0, 857, 858, 1, 0, 0, 0, 858, 859, 6, 45, 21, 0, 859, 860, 6, 45, 22, 0, 860, 107, 1, 0, 0, 0, 861, 862, 3, 240, 112, 0, 862, 863, 1, 0, 0, 0, 863, 864, 6, 46, 15, 0, 864, 865, 6, 46, 23, 0, 865, 109, 1, 0, 0, 0, 866, 867, 3, 250, 117, 0, 867, 868, 1, 0, 0, 0, 868, 869, 6, 47, 24, 0, 869, 870, 6, 47, 23, 0, 870, 111, 1, 0, 0, 0, 871, 872, 8, 24, 0, 0, 872, 113, 1, 0, 0, 0, 873, 875, 3, 112, 48, 0, 874, 873, 1, 0, 0, 0, 875, 876, 1, 0, 0, 0, 876, 874, 1, 0, 0, 0, 876, 877, 1, 0, 0, 0, 877, 878, 1, 0, 0, 0, 878, 879, 3, 214, 99, 0, 879, 881, 1, 0, 0, 0, 880, 874, 1, 0, 0, 0, 880, 881, 1, 0, 0, 0, 881, 883, 1, 0, 0, 0, 882, 884, 3, 112, 48, 0, 883, 882, 1, 0, 0, 0, 884, 885, 1, 0, 0, 0, 885, 883, 1, 0, 0, 0, 885, 886, 1, 0, 0, 0, 886, 115, 1, 0, 0, 0, 887, 888, 3, 114, 49, 0, 888, 889, 1, 0, 0, 0, 889, 890, 6, 50, 25, 0, 890, 117, 1, 0, 0, 0, 891, 892, 3, 16, 0, 0, 892, 893, 1, 0, 0, 0, 893, 894, 6, 51, 0, 0, 894, 119, 1, 0, 0, 0, 895, 896, 3, 18, 1, 0, 896, 897, 1, 0, 0, 0, 897, 898, 6, 52, 0, 0, 898, 121, 1, 0, 0, 0, 899, 900, 3, 20, 2, 0, 900, 901, 1, 0, 0, 0, 901, 902, 6, 53, 0, 0, 902, 123, 1, 0, 0, 0, 903, 904, 3, 174, 79, 0, 904, 905, 1, 0, 0, 0, 905, 906, 6, 54, 13, 0, 906, 907, 6, 54, 14, 0, 907, 908, 6, 54, 14, 0, 908, 125, 1, 0, 0, 0, 909, 910, 3, 208, 96, 0, 910, 911, 1, 0, 0, 0, 911, 912, 6, 55, 26, 0, 912, 127, 1, 0, 0, 0, 913, 914, 3, 216, 100, 0, 914, 915, 1, 0, 0, 0, 915, 916, 6, 56, 18, 0, 916, 129, 1, 0, 0, 0, 917, 918, 3, 220, 102, 0, 918, 919, 1, 0, 0, 0, 919, 920, 6, 57, 17, 0, 920, 131, 1, 0, 0, 0, 921, 922, 3, 250, 117, 0, 922, 923, 1, 0, 0, 0, 923, 924, 6, 58, 24, 0, 924, 133, 1, 0, 0, 0, 925, 926, 3, 448, 216, 0, 926, 927, 1, 0, 0, 0, 927, 928, 6, 59, 27, 0, 928, 135, 1, 0, 0, 0, 929, 930, 3, 300, 142, 0, 930, 931, 1, 0, 0, 0, 931, 932, 6, 60, 19, 0, 932, 137, 1, 0, 0, 0, 933, 934, 3, 244, 114, 0, 934, 935, 1, 0, 0, 0, 935, 936, 6, 61, 28, 0, 936, 139, 1, 0, 0, 0, 937, 938, 3, 284, 134, 0, 938, 939, 1, 0, 0, 0, 939, 940, 6, 62, 29, 0, 940, 141, 1, 0, 0, 0, 941, 942, 3, 280, 132, 0, 942, 943, 1, 0, 0, 0, 943, 944, 6, 63, 30, 0, 944, 143, 1, 0, 0, 0, 945, 946, 3, 286, 135, 0, 946, 947, 1, 0, 0, 0, 947, 948, 6, 64, 31, 0, 948, 145, 1, 0, 0, 0, 949, 950, 3, 16, 0, 0, 950, 951, 1, 0, 0, 0, 951, 952, 6, 65, 0, 0, 952, 147, 1, 0, 0, 0, 953, 954, 3, 18, 1, 0, 954, 955, 1, 0, 0, 0, 955, 956, 6, 66, 0, 0, 956, 149, 1, 0, 0, 0, 957, 958, 3, 20, 2, 0, 958, 959, 1, 0, 0, 0, 959, 960, 6, 67, 0, 0, 960, 151, 1, 0, 0, 0, 961, 962, 3, 290, 137, 0, 962, 963, 1, 0, 0, 0, 963, 964, 6, 68, 32, 0, 964, 965, 6, 68, 14, 0, 965, 153, 1, 0, 0, 0, 966, 967, 3, 214, 99, 0, 967, 968, 1, 0, 0, 0, 968, 969, 6, 69, 33, 0, 969, 155, 1, 0, 0, 0, 970, 976, 3, 186, 85, 0, 971, 976, 3, 176, 80, 0, 972, 976, 3, 220, 102, 0, 973, 976, 3, 178, 81, 0, 974, 976, 3, 192, 88, 0, 975, 970, 1, 0, 0, 0, 975, 971, 1, 0, 0, 0, 975, 972, 1, 0, 0, 0, 975, 973, 1, 0, 0, 0, 975, 974, 1, 0, 0, 0, 976, 977, 1, 0, 0, 0, 977, 975, 1, 0, 0, 0, 977, 978, 1, 0, 0, 0, 978, 157, 1, 0, 0, 0, 979, 980, 3, 16, 0, 0, 980, 981, 1, 0, 0, 0, 981, 982, 6, 71, 0, 0, 982, 159, 1, 0, 0, 0, 983, 984, 3, 18, 1, 0, 984, 985, 1, 0, 0, 0, 985, 986, 6, 72, 0, 0, 986, 161, 1, 0, 0, 0, 987, 988, 3, 20, 2, 0, 988, 989, 1, 0, 0, 0, 989, 990, 6, 73, 0, 0, 990, 163, 1, 0, 0, 0, 991, 992, 3, 288, 136, 0, 992, 993, 1, 0, 0, 0, 993, 994, 6, 74, 21, 0, 994, 995, 6, 74, 34, 0, 995, 165, 1, 0, 0, 0, 996, 997, 3, 174, 79, 0, 997, 998, 1, 0, 0, 0, 998, 999, 6, 75, 13, 0, 999, 1000, 6, 75, 14, 0, 1000, 167, 1, 0, 0, 0, 1001, 1002, 3, 20, 2, 0, 1002, 1003, 1, 0, 0, 0, 1003, 1004, 6, 76, 0, 0, 1004, 169, 1, 0, 0, 0, 1005, 1006, 3, 16, 0, 0, 1006, 1007, 1, 0, 0, 0, 1007, 1008, 6, 77, 0, 0, 1008, 171, 1, 0, 0, 0, 1009, 1010, 3, 18, 1, 0, 1010, 1011, 1, 0, 0, 0, 1011, 1012, 6, 78, 0, 0, 1012, 173, 1, 0, 0, 0, 1013, 1014, 5, 124, 0, 0, 1014, 1015, 1, 0, 0, 0, 1015, 1016, 6, 79, 14, 0, 1016, 175, 1, 0, 0, 0, 1017, 1018, 7, 25, 0, 0, 1018, 177, 1, 0, 0, 0, 1019, 1020, 7, 26, 0, 0, 1020, 179, 1, 0, 0, 0, 1021, 1022, 5, 92, 0, 0, 1022, 1023, 7, 27, 0, 0, 1023, 181, 1, 0, 0, 0, 1024, 1025, 8, 28, 0, 0, 1025, 183, 1, 0, 0, 0, 1026, 1028, 7, 7, 0, 0, 1027, 1029, 7, 29, 0, 0, 1028, 1027, 1, 0, 0, 0, 1028, 1029, 1, 0, 0, 0, 1029, 1031, 1, 0, 0, 0, 1030, 1032, 3, 176, 80, 0, 1031, 1030, 1, 0, 0, 0, 1032, 1033, 1, 0, 0, 0, 1033, 1031, 1, 0, 0, 0, 1033, 1034, 1, 0, 0, 0, 1034, 185, 1, 0, 0, 0, 1035, 1036, 5, 64, 0, 0, 1036, 187, 1, 0, 0, 0, 1037, 1038, 5, 96, 0, 0, 1038, 189, 1, 0, 0, 0, 1039, 1043, 8, 30, 0, 0, 1040, 1041, 5, 96, 0, 0, 1041, 1043, 5, 96, 0, 0, 1042, 1039, 1, 0, 0, 0, 1042, 1040, 1, 0, 0, 0, 1043, 191, 1, 0, 0, 0, 1044, 1045, 5, 95, 0, 0, 1045, 193, 1, 0, 0, 0, 1046, 1050, 3, 178, 81, 0, 1047, 1050, 3, 176, 80, 0, 1048, 1050, 3, 192, 88, 0, 1049, 1046, 1, 0, 0, 0, 1049, 1047, 1, 0, 0, 0, 1049, 1048, 1, 0, 0, 0, 1050, 195, 1, 0, 0, 0, 1051, 1056, 5, 34, 0, 0, 1052, 1055, 3, 180, 82, 0, 1053, 1055, 3, 182, 83, 0, 1054, 1052, 1, 0, 0, 0, 1054, 1053, 1, 0, 0, 0, 1055, 1058, 1, 0, 0, 0, 1056, 1054, 1, 0, 0, 0, 1056, 1057, 1, 0, 0, 0, 1057, 1059, 1, 0, 0, 0, 1058, 1056, 1, 0, 0, 0, 1059, 1081, 5, 34, 0, 0, 1060, 1061, 5, 34, 0, 0, 1061, 1062, 5, 34, 0, 0, 1062, 1063, 5, 34, 0, 0, 1063, 1067, 1, 0, 0, 0, 1064, 1066, 8, 0, 0, 0, 1065, 1064, 1, 0, 0, 0, 1066, 1069, 1, 0, 0, 0, 1067, 1068, 1, 0, 0, 0, 1067, 1065, 1, 0, 0, 0, 1068, 1070, 1, 0, 0, 0, 1069, 1067, 1, 0, 0, 0, 1070, 1071, 5, 34, 0, 0, 1071, 1072, 5, 34, 0, 0, 1072, 1073, 5, 34, 0, 0, 1073, 1075, 1, 0, 0, 0, 1074, 1076, 5, 34, 0, 0, 1075, 1074, 1, 0, 0, 0, 1075, 1076, 1, 0, 0, 0, 1076, 1078, 1, 0, 0, 0, 1077, 1079, 5, 34, 0, 0, 1078, 1077, 1, 0, 0, 0, 1078, 1079, 1, 0, 0, 0, 1079, 1081, 1, 0, 0, 0, 1080, 1051, 1, 0, 0, 0, 1080, 1060, 1, 0, 0, 0, 1081, 197, 1, 0, 0, 0, 1082, 1084, 3, 176, 80, 0, 1083, 1082, 1, 0, 0, 0, 1084, 1085, 1, 0, 0, 0, 1085, 1083, 1, 0, 0, 0, 1085, 1086, 1, 0, 0, 0, 1086, 199, 1, 0, 0, 0, 1087, 1089, 3, 176, 80, 0, 1088, 1087, 1, 0, 0, 0, 1089, 1090, 1, 0, 0, 0, 1090, 1088, 1, 0, 0, 0, 1090, 1091, 1, 0, 0, 0, 1091, 1092, 1, 0, 0, 0, 1092, 1096, 3, 220, 102, 0, 1093, 1095, 3, 176, 80, 0, 1094, 1093, 1, 0, 0, 0, 1095, 1098, 1, 0, 0, 0, 1096, 1094, 1, 0, 0, 0, 1096, 1097, 1, 0, 0, 0, 1097, 1130, 1, 0, 0, 0, 1098, 1096, 1, 0, 0, 0, 1099, 1101, 3, 220, 102, 0, 1100, 1102, 3, 176, 80, 0, 1101, 1100, 1, 0, 0, 0, 1102, 1103, 1, 0, 0, 0, 1103, 1101, 1, 0, 0, 0, 1103, 1104, 1, 0, 0, 0, 1104, 1130, 1, 0, 0, 0, 1105, 1107, 3, 176, 80, 0, 1106, 1105, 1, 0, 0, 0, 1107, 1108, 1, 0, 0, 0, 1108, 1106, 1, 0, 0, 0, 1108, 1109, 1, 0, 0, 0, 1109, 1117, 1, 0, 0, 0, 1110, 1114, 3, 220, 102, 0, 1111, 1113, 3, 176, 80, 0, 1112, 1111, 1, 0, 0, 0, 1113, 1116, 1, 0, 0, 0, 1114, 1112, 1, 0, 0, 0, 1114, 1115, 1, 0, 0, 0, 1115, 1118, 1, 0, 0, 0, 1116, 1114, 1, 0, 0, 0, 1117, 1110, 1, 0, 0, 0, 1117, 1118, 1, 0, 0, 0, 1118, 1119, 1, 0, 0, 0, 1119, 1120, 3, 184, 84, 0, 1120, 1130, 1, 0, 0, 0, 1121, 1123, 3, 220, 102, 0, 1122, 1124, 3, 176, 80, 0, 1123, 1122, 1, 0, 0, 0, 1124, 1125, 1, 0, 0, 0, 1125, 1123, 1, 0, 0, 0, 1125, 1126, 1, 0, 0, 0, 1126, 1127, 1, 0, 0, 0, 1127, 1128, 3, 184, 84, 0, 1128, 1130, 1, 0, 0, 0, 1129, 1088, 1, 0, 0, 0, 1129, 1099, 1, 0, 0, 0, 1129, 1106, 1, 0, 0, 0, 1129, 1121, 1, 0, 0, 0, 1130, 201, 1, 0, 0, 0, 1131, 1132, 7, 4, 0, 0, 1132, 1133, 7, 5, 0, 0, 1133, 1134, 7, 15, 0, 0, 1134, 203, 1, 0, 0, 0, 1135, 1136, 7, 4, 0, 0, 1136, 1137, 7, 16, 0, 0, 1137, 205, 1, 0, 0, 0, 1138, 1139, 7, 4, 0, 0, 1139, 1140, 7, 16, 0, 0, 1140, 1141, 7, 2, 0, 0, 1141, 207, 1, 0, 0, 0, 1142, 1143, 5, 61, 0, 0, 1143, 209, 1, 0, 0, 0, 1144, 1145, 7, 31, 0, 0, 1145, 1146, 7, 32, 0, 0, 1146, 211, 1, 0, 0, 0, 1147, 1148, 5, 58, 0, 0, 1148, 1149, 5, 58, 0, 0, 1149, 213, 1, 0, 0, 0, 1150, 1151, 5, 58, 0, 0, 1151, 215, 1, 0, 0, 0, 1152, 1153, 5, 44, 0, 0, 1153, 217, 1, 0, 0, 0, 1154, 1155, 7, 15, 0, 0, 1155, 1156, 7, 7, 0, 0, 1156, 1157, 7, 16, 0, 0, 1157, 1158, 7, 2, 0, 0, 1158, 219, 1, 0, 0, 0, 1159, 1160, 5, 46, 0, 0, 1160, 221, 1, 0, 0, 0, 1161, 1162, 7, 21, 0, 0, 1162, 1163, 7, 4, 0, 0, 1163, 1164, 7, 14, 0, 0, 1164, 1165, 7, 16, 0, 0, 1165, 1166, 7, 7, 0, 0, 1166, 223, 1, 0, 0, 0, 1167, 1168, 7, 21, 0, 0, 1168, 1169, 7, 10, 0, 0, 1169, 1170, 7, 12, 0, 0, 1170, 1171, 7, 16, 0, 0, 1171, 1172, 7, 11, 0, 0, 1172, 225, 1, 0, 0, 0, 1173, 1174, 7, 10, 0, 0, 1174, 1175, 7, 5, 0, 0, 1175, 227, 1, 0, 0, 0, 1176, 1177, 7, 10, 0, 0, 1177, 1178, 7, 16, 0, 0, 1178, 229, 1, 0, 0, 0, 1179, 1180, 7, 14, 0, 0, 1180, 1181, 7, 4, 0, 0, 1181, 1182, 7, 16, 0, 0, 1182, 1183, 7, 11, 0, 0, 1183, 231, 1, 0, 0, 0, 1184, 1185, 7, 14, 0, 0, 1185, 1186, 7, 10, 0, 0, 1186, 1187, 7, 18, 0, 0, 1187, 1188, 7, 7, 0, 0, 1188, 233, 1, 0, 0, 0, 1189, 1190, 7, 5, 0, 0, 1190, 1191, 7, 9, 0, 0, 1191, 1192, 7, 11, 0, 0, 1192, 235, 1, 0, 0, 0, 1193, 1194, 7, 5, 0, 0, 1194, 1195, 7, 22, 0, 0, 1195, 1196, 7, 14, 0, 0, 1196, 1197, 7, 14, 0, 0, 1197, 237, 1, 0, 0, 0, 1198, 1199, 7, 5, 0, 0, 1199, 1200, 7, 22, 0, 0, 1200, 1201, 7, 14, 0, 0, 1201, 1202, 7, 14, 0, 0, 1202, 1203, 7, 16, 0, 0, 1203, 239, 1, 0, 0, 0, 1204, 1205, 7, 9, 0, 0, 1205, 1206, 7, 5, 0, 0, 1206, 241, 1, 0, 0, 0, 1207, 1208, 7, 9, 0, 0, 1208, 1209, 7, 12, 0, 0, 1209, 243, 1, 0, 0, 0, 1210, 1211, 5, 63, 0, 0, 1211, 245, 1, 0, 0, 0, 1212, 1213, 7, 12, 0, 0, 1213, 1214, 7, 14, 0, 0, 1214, 1215, 7, 10, 0, 0, 1215, 1216, 7, 18, 0, 0, 1216, 1217, 7, 7, 0, 0, 1217, 247, 1, 0, 0, 0, 1218, 1219, 7, 11, 0, 0, 1219, 1220, 7, 12, 0, 0, 1220, 1221, 7, 22, 0, 0, 1221, 1222, 7, 7, 0, 0, 1222, 249, 1, 0, 0, 0, 1223, 1224, 7, 20, 0, 0, 1224, 1225, 7, 10, 0, 0, 1225, 1226, 7, 11, 0, 0, 1226, 1227, 7, 3, 0, 0, 1227, 251, 1, 0, 0, 0, 1228, 1229, 5, 61, 0, 0, 1229, 1230, 5, 61, 0, 0, 1230, 253, 1, 0, 0, 0, 1231, 1232, 5, 61, 0, 0, 1232, 1233, 5, 126, 0, 0, 1233, 255, 1, 0, 0, 0, 1234, 1235, 5, 33, 0, 0, 1235, 1236, 5, 61, 0, 0, 1236, 257, 1, 0, 0, 0, 1237, 1238, 5, 60, 0, 0, 1238, 259, 1, 0, 0, 0, 1239, 1240, 5, 60, 0, 0, 1240, 1241, 5, 61, 0, 0, 1241, 261, 1, 0, 0, 0, 1242, 1243, 5, 62, 0, 0, 1243, 263, 1, 0, 0, 0, 1244, 1245, 5, 62, 0, 0, 1245, 1246, 5, 61, 0, 0, 1246, 265, 1, 0, 0, 0, 1247, 1248, 5, 43, 0, 0, 1248, 267, 1, 0, 0, 0, 1249, 1250, 5, 45, 0, 0, 1250, 269, 1, 0, 0, 0, 1251, 1252, 5, 42, 0, 0, 1252, 271, 1, 0, 0, 0, 1253, 1254, 5, 47, 0, 0, 1254, 273, 1, 0, 0, 0, 1255, 1256, 5, 37, 0, 0, 1256, 275, 1, 0, 0, 0, 1257, 1258, 5, 123, 0, 0, 1258, 277, 1, 0, 0, 0, 1259, 1260, 5, 125, 0, 0, 1260, 279, 1, 0, 0, 0, 1261, 1262, 5, 63, 0, 0, 1262, 1263, 5, 63, 0, 0, 1263, 281, 1, 0, 0, 0, 1264, 1265, 3, 42, 13, 0, 1265, 1266, 1, 0, 0, 0, 1266, 1267, 6, 133, 35, 0, 1267, 283, 1, 0, 0, 0, 1268, 1271, 3, 244, 114, 0, 1269, 1272, 3, 178, 81, 0, 1270, 1272, 3, 192, 88, 0, 1271, 1269, 1, 0, 0, 0, 1271, 1270, 1, 0, 0, 0, 1272, 1276, 1, 0, 0, 0, 1273, 1275, 3, 194, 89, 0, 1274, 1273, 1, 0, 0, 0, 1275, 1278, 1, 0, 0, 0, 1276, 1274, 1, 0, 0, 0, 1276, 1277, 1, 0, 0, 0, 1277, 1286, 1, 0, 0, 0, 1278, 1276, 1, 0, 0, 0, 1279, 1281, 3, 244, 114, 0, 1280, 1282, 3, 176, 80, 0, 1281, 1280, 1, 0, 0, 0, 1282, 1283, 1, 0, 0, 0, 1283, 1281, 1, 0, 0, 0, 1283, 1284, 1, 0, 0, 0, 1284, 1286, 1, 0, 0, 0, 1285, 1268, 1, 0, 0, 0, 1285, 1279, 1, 0, 0, 0, 1286, 285, 1, 0, 0, 0, 1287, 1290, 3, 280, 132, 0, 1288, 1291, 3, 178, 81, 0, 1289, 1291, 3, 192, 88, 0, 1290, 1288, 1, 0, 0, 0, 1290, 1289, 1, 0, 0, 0, 1291, 1295, 1, 0, 0, 0, 1292, 1294, 3, 194, 89, 0, 1293, 1292, 1, 0, 0, 0, 1294, 1297, 1, 0, 0, 0, 1295, 1293, 1, 0, 0, 0, 1295, 1296, 1, 0, 0, 0, 1296, 1305, 1, 0, 0, 0, 1297, 1295, 1, 0, 0, 0, 1298, 1300, 3, 280, 132, 0, 1299, 1301, 3, 176, 80, 0, 1300, 1299, 1, 0, 0, 0, 1301, 1302, 1, 0, 0, 0, 1302, 1300, 1, 0, 0, 0, 1302, 1303, 1, 0, 0, 0, 1303, 1305, 1, 0, 0, 0, 1304, 1287, 1, 0, 0, 0, 1304, 1298, 1, 0, 0, 0, 1305, 287, 1, 0, 0, 0, 1306, 1307, 5, 91, 0, 0, 1307, 1308, 1, 0, 0, 0, 1308, 1309, 6, 136, 4, 0, 1309, 1310, 6, 136, 4, 0, 1310, 289, 1, 0, 0, 0, 1311, 1312, 5, 93, 0, 0, 1312, 1313, 1, 0, 0, 0, 1313, 1314, 6, 137, 14, 0, 1314, 1315, 6, 137, 14, 0, 1315, 291, 1, 0, 0, 0, 1316, 1317, 5, 40, 0, 0, 1317, 1318, 1, 0, 0, 0, 1318, 1319, 6, 138, 4, 0, 1319, 1320, 6, 138, 4, 0, 1320, 293, 1, 0, 0, 0, 1321, 1322, 5, 41, 0, 0, 1322, 1323, 1, 0, 0, 0, 1323, 1324, 6, 139, 14, 0, 1324, 1325, 6, 139, 14, 0, 1325, 295, 1, 0, 0, 0, 1326, 1330, 3, 178, 81, 0, 1327, 1329, 3, 194, 89, 0, 1328, 1327, 1, 0, 0, 0, 1329, 1332, 1, 0, 0, 0, 1330, 1328, 1, 0, 0, 0, 1330, 1331, 1, 0, 0, 0, 1331, 1343, 1, 0, 0, 0, 1332, 1330, 1, 0, 0, 0, 1333, 1336, 3, 192, 88, 0, 1334, 1336, 3, 186, 85, 0, 1335, 1333, 1, 0, 0, 0, 1335, 1334, 1, 0, 0, 0, 1336, 1338, 1, 0, 0, 0, 1337, 1339, 3, 194, 89, 0, 1338, 1337, 1, 0, 0, 0, 1339, 1340, 1, 0, 0, 0, 1340, 1338, 1, 0, 0, 0, 1340, 1341, 1, 0, 0, 0, 1341, 1343, 1, 0, 0, 0, 1342, 1326, 1, 0, 0, 0, 1342, 1335, 1, 0, 0, 0, 1343, 297, 1, 0, 0, 0, 1344, 1346, 3, 188, 86, 0, 1345, 1347, 3, 190, 87, 0, 1346, 1345, 1, 0, 0, 0, 1347, 1348, 1, 0, 0, 0, 1348, 1346, 1, 0, 0, 0, 1348, 1349, 1, 0, 0, 0, 1349, 1350, 1, 0, 0, 0, 1350, 1351, 3, 188, 86, 0, 1351, 299, 1, 0, 0, 0, 1352, 1353, 3, 298, 141, 0, 1353, 301, 1, 0, 0, 0, 1354, 1355, 3, 16, 0, 0, 1355, 1356, 1, 0, 0, 0, 1356, 1357, 6, 143, 0, 0, 1357, 303, 1, 0, 0, 0, 1358, 1359, 3, 18, 1, 0, 1359, 1360, 1, 0, 0, 0, 1360, 1361, 6, 144, 0, 0, 1361, 305, 1, 0, 0, 0, 1362, 1363, 3, 20, 2, 0, 1363, 1364, 1, 0, 0, 0, 1364, 1365, 6, 145, 0, 0, 1365, 307, 1, 0, 0, 0, 1366, 1367, 3, 174, 79, 0, 1367, 1368, 1, 0, 0, 0, 1368, 1369, 6, 146, 13, 0, 1369, 1370, 6, 146, 14, 0, 1370, 309, 1, 0, 0, 0, 1371, 1372, 3, 288, 136, 0, 1372, 1373, 1, 0, 0, 0, 1373, 1374, 6, 147, 21, 0, 1374, 311, 1, 0, 0, 0, 1375, 1376, 3, 290, 137, 0, 1376, 1377, 1, 0, 0, 0, 1377, 1378, 6, 148, 32, 0, 1378, 313, 1, 0, 0, 0, 1379, 1380, 3, 214, 99, 0, 1380, 1381, 1, 0, 0, 0, 1381, 1382, 6, 149, 33, 0, 1382, 315, 1, 0, 0, 0, 1383, 1384, 3, 212, 98, 0, 1384, 1385, 1, 0, 0, 0, 1385, 1386, 6, 150, 36, 0, 1386, 317, 1, 0, 0, 0, 1387, 1388, 3, 216, 100, 0, 1388, 1389, 1, 0, 0, 0, 1389, 1390, 6, 151, 18, 0, 1390, 319, 1, 0, 0, 0, 1391, 1392, 3, 208, 96, 0, 1392, 1393, 1, 0, 0, 0, 1393, 1394, 6, 152, 26, 0, 1394, 321, 1, 0, 0, 0, 1395, 1396, 7, 19, 0, 0, 1396, 1397, 7, 7, 0, 0, 1397, 1398, 7, 11, 0, 0, 1398, 1399, 7, 4, 0, 0, 1399, 1400, 7, 15, 0, 0, 1400, 1401, 7, 4, 0, 0, 1401, 1402, 7, 11, 0, 0, 1402, 1403, 7, 4, 0, 0, 1403, 323, 1, 0, 0, 0, 1404, 1408, 8, 33, 0, 0, 1405, 1406, 5, 47, 0, 0, 1406, 1408, 8, 34, 0, 0, 1407, 1404, 1, 0, 0, 0, 1407, 1405, 1, 0, 0, 0, 1408, 325, 1, 0, 0, 0, 1409, 1411, 3, 324, 154, 0, 1410, 1409, 1, 0, 0, 0, 1411, 1412, 1, 0, 0, 0, 1412, 1410, 1, 0, 0, 0, 1412, 1413, 1, 0, 0, 0, 1413, 327, 1, 0, 0, 0, 1414, 1415, 3, 326, 155, 0, 1415, 1416, 1, 0, 0, 0, 1416, 1417, 6, 156, 37, 0, 1417, 329, 1, 0, 0, 0, 1418, 1419, 3, 196, 90, 0, 1419, 1420, 1, 0, 0, 0, 1420, 1421, 6, 157, 38, 0, 1421, 331, 1, 0, 0, 0, 1422, 1423, 3, 16, 0, 0, 1423, 1424, 1, 0, 0, 0, 1424, 1425, 6, 158, 0, 0, 1425, 333, 1, 0, 0, 0, 1426, 1427, 3, 18, 1, 0, 1427, 1428, 1, 0, 0, 0, 1428, 1429, 6, 159, 0, 0, 1429, 335, 1, 0, 0, 0, 1430, 1431, 3, 20, 2, 0, 1431, 1432, 1, 0, 0, 0, 1432, 1433, 6, 160, 0, 0, 1433, 337, 1, 0, 0, 0, 1434, 1435, 3, 292, 138, 0, 1435, 1436, 1, 0, 0, 0, 1436, 1437, 6, 161, 39, 0, 1437, 1438, 6, 161, 34, 0, 1438, 339, 1, 0, 0, 0, 1439, 1440, 3, 174, 79, 0, 1440, 1441, 1, 0, 0, 0, 1441, 1442, 6, 162, 13, 0, 1442, 1443, 6, 162, 14, 0, 1443, 341, 1, 0, 0, 0, 1444, 1445, 3, 20, 2, 0, 1445, 1446, 1, 0, 0, 0, 1446, 1447, 6, 163, 0, 0, 1447, 343, 1, 0, 0, 0, 1448, 1449, 3, 16, 0, 0, 1449, 1450, 1, 0, 0, 0, 1450, 1451, 6, 164, 0, 0, 1451, 345, 1, 0, 0, 0, 1452, 1453, 3, 18, 1, 0, 1453, 1454, 1, 0, 0, 0, 1454, 1455, 6, 165, 0, 0, 1455, 347, 1, 0, 0, 0, 1456, 1457, 3, 174, 79, 0, 1457, 1458, 1, 0, 0, 0, 1458, 1459, 6, 166, 13, 0, 1459, 1460, 6, 166, 14, 0, 1460, 349, 1, 0, 0, 0, 1461, 1462, 7, 35, 0, 0, 1462, 1463, 7, 9, 0, 0, 1463, 1464, 7, 10, 0, 0, 1464, 1465, 7, 5, 0, 0, 1465, 351, 1, 0, 0, 0, 1466, 1467, 3, 204, 94, 0, 1467, 1468, 1, 0, 0, 0, 1468, 1469, 6, 168, 16, 0, 1469, 353, 1, 0, 0, 0, 1470, 1471, 3, 240, 112, 0, 1471, 1472, 1, 0, 0, 0, 1472, 1473, 6, 169, 15, 0, 1473, 1474, 6, 169, 14, 0, 1474, 1475, 6, 169, 4, 0, 1475, 355, 1, 0, 0, 0, 1476, 1477, 7, 22, 0, 0, 1477, 1478, 7, 16, 0, 0, 1478, 1479, 7, 10, 0, 0, 1479, 1480, 7, 5, 0, 0, 1480, 1481, 7, 6, 0, 0, 1481, 1482, 1, 0, 0, 0, 1482, 1483, 6, 170, 14, 0, 1483, 1484, 6, 170, 4, 0, 1484, 357, 1, 0, 0, 0, 1485, 1486, 3, 326, 155, 0, 1486, 1487, 1, 0, 0, 0, 1487, 1488, 6, 171, 37, 0, 1488, 359, 1, 0, 0, 0, 1489, 1490, 3, 196, 90, 0, 1490, 1491, 1, 0, 0, 0, 1491, 1492, 6, 172, 38, 0, 1492, 361, 1, 0, 0, 0, 1493, 1494, 3, 214, 99, 0, 1494, 1495, 1, 0, 0, 0, 1495, 1496, 6, 173, 33, 0, 1496, 363, 1, 0, 0, 0, 1497, 1498, 3, 296, 140, 0, 1498, 1499, 1, 0, 0, 0, 1499, 1500, 6, 174, 20, 0, 1500, 365, 1, 0, 0, 0, 1501, 1502, 3, 300, 142, 0, 1502, 1503, 1, 0, 0, 0, 1503, 1504, 6, 175, 19, 0, 1504, 367, 1, 0, 0, 0, 1505, 1506, 3, 16, 0, 0, 1506, 1507, 1, 0, 0, 0, 1507, 1508, 6, 176, 0, 0, 1508, 369, 1, 0, 0, 0, 1509, 1510, 3, 18, 1, 0, 1510, 1511, 1, 0, 0, 0, 1511, 1512, 6, 177, 0, 0, 1512, 371, 1, 0, 0, 0, 1513, 1514, 3, 20, 2, 0, 1514, 1515, 1, 0, 0, 0, 1515, 1516, 6, 178, 0, 0, 1516, 373, 1, 0, 0, 0, 1517, 1518, 3, 174, 79, 0, 1518, 1519, 1, 0, 0, 0, 1519, 1520, 6, 179, 13, 0, 1520, 1521, 6, 179, 14, 0, 1521, 375, 1, 0, 0, 0, 1522, 1523, 3, 214, 99, 0, 1523, 1524, 1, 0, 0, 0, 1524, 1525, 6, 180, 33, 0, 1525, 377, 1, 0, 0, 0, 1526, 1527, 3, 216, 100, 0, 1527, 1528, 1, 0, 0, 0, 1528, 1529, 6, 181, 18, 0, 1529, 379, 1, 0, 0, 0, 1530, 1531, 3, 220, 102, 0, 1531, 1532, 1, 0, 0, 0, 1532, 1533, 6, 182, 17, 0, 1533, 381, 1, 0, 0, 0, 1534, 1535, 3, 240, 112, 0, 1535, 1536, 1, 0, 0, 0, 1536, 1537, 6, 183, 15, 0, 1537, 1538, 6, 183, 40, 0, 1538, 383, 1, 0, 0, 0, 1539, 1540, 3, 326, 155, 0, 1540, 1541, 1, 0, 0, 0, 1541, 1542, 6, 184, 37, 0, 1542, 385, 1, 0, 0, 0, 1543, 1544, 3, 196, 90, 0, 1544, 1545, 1, 0, 0, 0, 1545, 1546, 6, 185, 38, 0, 1546, 387, 1, 0, 0, 0, 1547, 1548, 3, 16, 0, 0, 1548, 1549, 1, 0, 0, 0, 1549, 1550, 6, 186, 0, 0, 1550, 389, 1, 0, 0, 0, 1551, 1552, 3, 18, 1, 0, 1552, 1553, 1, 0, 0, 0, 1553, 1554, 6, 187, 0, 0, 1554, 391, 1, 0, 0, 0, 1555, 1556, 3, 20, 2, 0, 1556, 1557, 1, 0, 0, 0, 1557, 1558, 6, 188, 0, 0, 1558, 393, 1, 0, 0, 0, 1559, 1560, 3, 174, 79, 0, 1560, 1561, 1, 0, 0, 0, 1561, 1562, 6, 189, 13, 0, 1562, 1563, 6, 189, 14, 0, 1563, 1564, 6, 189, 14, 0, 1564, 395, 1, 0, 0, 0, 1565, 1566, 3, 216, 100, 0, 1566, 1567, 1, 0, 0, 0, 1567, 1568, 6, 190, 18, 0, 1568, 397, 1, 0, 0, 0, 1569, 1570, 3, 220, 102, 0, 1570, 1571, 1, 0, 0, 0, 1571, 1572, 6, 191, 17, 0, 1572, 399, 1, 0, 0, 0, 1573, 1574, 3, 448, 216, 0, 1574, 1575, 1, 0, 0, 0, 1575, 1576, 6, 192, 27, 0, 1576, 401, 1, 0, 0, 0, 1577, 1578, 3, 16, 0, 0, 1578, 1579, 1, 0, 0, 0, 1579, 1580, 6, 193, 0, 0, 1580, 403, 1, 0, 0, 0, 1581, 1582, 3, 18, 1, 0, 1582, 1583, 1, 0, 0, 0, 1583, 1584, 6, 194, 0, 0, 1584, 405, 1, 0, 0, 0, 1585, 1586, 3, 20, 2, 0, 1586, 1587, 1, 0, 0, 0, 1587, 1588, 6, 195, 0, 0, 1588, 407, 1, 0, 0, 0, 1589, 1590, 3, 174, 79, 0, 1590, 1591, 1, 0, 0, 0, 1591, 1592, 6, 196, 13, 0, 1592, 1593, 6, 196, 14, 0, 1593, 409, 1, 0, 0, 0, 1594, 1595, 3, 220, 102, 0, 1595, 1596, 1, 0, 0, 0, 1596, 1597, 6, 197, 17, 0, 1597, 411, 1, 0, 0, 0, 1598, 1599, 3, 244, 114, 0, 1599, 1600, 1, 0, 0, 0, 1600, 1601, 6, 198, 28, 0, 1601, 413, 1, 0, 0, 0, 1602, 1603, 3, 284, 134, 0, 1603, 1604, 1, 0, 0, 0, 1604, 1605, 6, 199, 29, 0, 1605, 415, 1, 0, 0, 0, 1606, 1607, 3, 280, 132, 0, 1607, 1608, 1, 0, 0, 0, 1608, 1609, 6, 200, 30, 0, 1609, 417, 1, 0, 0, 0, 1610, 1611, 3, 286, 135, 0, 1611, 1612, 1, 0, 0, 0, 1612, 1613, 6, 201, 31, 0, 1613, 419, 1, 0, 0, 0, 1614, 1615, 3, 300, 142, 0, 1615, 1616, 1, 0, 0, 0, 1616, 1617, 6, 202, 19, 0, 1617, 421, 1, 0, 0, 0, 1618, 1619, 3, 296, 140, 0, 1619, 1620, 1, 0, 0, 0, 1620, 1621, 6, 203, 20, 0, 1621, 423, 1, 0, 0, 0, 1622, 1623, 3, 16, 0, 0, 1623, 1624, 1, 0, 0, 0, 1624, 1625, 6, 204, 0, 0, 1625, 425, 1, 0, 0, 0, 1626, 1627, 3, 18, 1, 0, 1627, 1628, 1, 0, 0, 0, 1628, 1629, 6, 205, 0, 0, 1629, 427, 1, 0, 0, 0, 1630, 1631, 3, 20, 2, 0, 1631, 1632, 1, 0, 0, 0, 1632, 1633, 6, 206, 0, 0, 1633, 429, 1, 0, 0, 0, 1634, 1635, 3, 174, 79, 0, 1635, 1636, 1, 0, 0, 0, 1636, 1637, 6, 207, 13, 0, 1637, 1638, 6, 207, 14, 0, 1638, 431, 1, 0, 0, 0, 1639, 1640, 3, 220, 102, 0, 1640, 1641, 1, 0, 0, 0, 1641, 1642, 6, 208, 17, 0, 1642, 433, 1, 0, 0, 0, 1643, 1644, 3, 216, 100, 0, 1644, 1645, 1, 0, 0, 0, 1645, 1646, 6, 209, 18, 0, 1646, 435, 1, 0, 0, 0, 1647, 1648, 3, 244, 114, 0, 1648, 1649, 1, 0, 0, 0, 1649, 1650, 6, 210, 28, 0, 1650, 437, 1, 0, 0, 0, 1651, 1652, 3, 284, 134, 0, 1652, 1653, 1, 0, 0, 0, 1653, 1654, 6, 211, 29, 0, 1654, 439, 1, 0, 0, 0, 1655, 1656, 3, 280, 132, 0, 1656, 1657, 1, 0, 0, 0, 1657, 1658, 6, 212, 30, 0, 1658, 441, 1, 0, 0, 0, 1659, 1660, 3, 286, 135, 0, 1660, 1661, 1, 0, 0, 0, 1661, 1662, 6, 213, 31, 0, 1662, 443, 1, 0, 0, 0, 1663, 1668, 3, 178, 81, 0, 1664, 1668, 3, 176, 80, 0, 1665, 1668, 3, 192, 88, 0, 1666, 1668, 3, 270, 127, 0, 1667, 1663, 1, 0, 0, 0, 1667, 1664, 1, 0, 0, 0, 1667, 1665, 1, 0, 0, 0, 1667, 1666, 1, 0, 0, 0, 1668, 445, 1, 0, 0, 0, 1669, 1672, 3, 178, 81, 0, 1670, 1672, 3, 270, 127, 0, 1671, 1669, 1, 0, 0, 0, 1671, 1670, 1, 0, 0, 0, 1672, 1676, 1, 0, 0, 0, 1673, 1675, 3, 444, 214, 0, 1674, 1673, 1, 0, 0, 0, 1675, 1678, 1, 0, 0, 0, 1676, 1674, 1, 0, 0, 0, 1676, 1677, 1, 0, 0, 0, 1677, 1689, 1, 0, 0, 0, 1678, 1676, 1, 0, 0, 0, 1679, 1682, 3, 192, 88, 0, 1680, 1682, 3, 186, 85, 0, 1681, 1679, 1, 0, 0, 0, 1681, 1680, 1, 0, 0, 0, 1682, 1684, 1, 0, 0, 0, 1683, 1685, 3, 444, 214, 0, 1684, 1683, 1, 0, 0, 0, 1685, 1686, 1, 0, 0, 0, 1686, 1684, 1, 0, 0, 0, 1686, 1687, 1, 0, 0, 0, 1687, 1689, 1, 0, 0, 0, 1688, 1671, 1, 0, 0, 0, 1688, 1681, 1, 0, 0, 0, 1689, 447, 1, 0, 0, 0, 1690, 1693, 3, 446, 215, 0, 1691, 1693, 3, 298, 141, 0, 1692, 1690, 1, 0, 0, 0, 1692, 1691, 1, 0, 0, 0, 1693, 1694, 1, 0, 0, 0, 1694, 1692, 1, 0, 0, 0, 1694, 1695, 1, 0, 0, 0, 1695, 449, 1, 0, 0, 0, 1696, 1697, 3, 16, 0, 0, 1697, 1698, 1, 0, 0, 0, 1698, 1699, 6, 217, 0, 0, 1699, 451, 1, 0, 0, 0, 1700, 1701, 3, 18, 1, 0, 1701, 1702, 1, 0, 0, 0, 1702, 1703, 6, 218, 0, 0, 1703, 453, 1, 0, 0, 0, 1704, 1705, 3, 20, 2, 0, 1705, 1706, 1, 0, 0, 0, 1706, 1707, 6, 219, 0, 0, 1707, 455, 1, 0, 0, 0, 1708, 1709, 3, 174, 79, 0, 1709, 1710, 1, 0, 0, 0, 1710, 1711, 6, 220, 13, 0, 1711, 1712, 6, 220, 14, 0, 1712, 457, 1, 0, 0, 0, 1713, 1714, 3, 208, 96, 0, 1714, 1715, 1, 0, 0, 0, 1715, 1716, 6, 221, 26, 0, 1716, 459, 1, 0, 0, 0, 1717, 1718, 3, 216, 100, 0, 1718, 1719, 1, 0, 0, 0, 1719, 1720, 6, 222, 18, 0, 1720, 461, 1, 0, 0, 0, 1721, 1722, 3, 220, 102, 0, 1722, 1723, 1, 0, 0, 0, 1723, 1724, 6, 223, 17, 0, 1724, 463, 1, 0, 0, 0, 1725, 1726, 3, 244, 114, 0, 1726, 1727, 1, 0, 0, 0, 1727, 1728, 6, 224, 28, 0, 1728, 465, 1, 0, 0, 0, 1729, 1730, 3, 284, 134, 0, 1730, 1731, 1, 0, 0, 0, 1731, 1732, 6, 225, 29, 0, 1732, 467, 1, 0, 0, 0, 1733, 1734, 3, 280, 132, 0, 1734, 1735, 1, 0, 0, 0, 1735, 1736, 6, 226, 30, 0, 1736, 469, 1, 0, 0, 0, 1737, 1738, 3, 286, 135, 0, 1738, 1739, 1, 0, 0, 0, 1739, 1740, 6, 227, 31, 0, 1740, 471, 1, 0, 0, 0, 1741, 1742, 3, 204, 94, 0, 1742, 1743, 1, 0, 0, 0, 1743, 1744, 6, 228, 16, 0, 1744, 473, 1, 0, 0, 0, 1745, 1746, 3, 448, 216, 0, 1746, 1747, 1, 0, 0, 0, 1747, 1748, 6, 229, 27, 0, 1748, 475, 1, 0, 0, 0, 1749, 1750, 3, 16, 0, 0, 1750, 1751, 1, 0, 0, 0, 1751, 1752, 6, 230, 0, 0, 1752, 477, 1, 0, 0, 0, 1753, 1754, 3, 18, 1, 0, 1754, 1755, 1, 0, 0, 0, 1755, 1756, 6, 231, 0, 0, 1756, 479, 1, 0, 0, 0, 1757, 1758, 3, 20, 2, 0, 1758, 1759, 1, 0, 0, 0, 1759, 1760, 6, 232, 0, 0, 1760, 481, 1, 0, 0, 0, 1761, 1762, 3, 174, 79, 0, 1762, 1763, 1, 0, 0, 0, 1763, 1764, 6, 233, 13, 0, 1764, 1765, 6, 233, 14, 0, 1765, 483, 1, 0, 0, 0, 1766, 1767, 7, 10, 0, 0, 1767, 1768, 7, 5, 0, 0, 1768, 1769, 7, 21, 0, 0, 1769, 1770, 7, 9, 0, 0, 1770, 485, 1, 0, 0, 0, 1771, 1772, 3, 16, 0, 0, 1772, 1773, 1, 0, 0, 0, 1773, 1774, 6, 235, 0, 0, 1774, 487, 1, 0, 0, 0, 1775, 1776, 3, 18, 1, 0, 1776, 1777, 1, 0, 0, 0, 1777, 1778, 6, 236, 0, 0, 1778, 489, 1, 0, 0, 0, 1779, 1780, 3, 20, 2, 0, 1780, 1781, 1, 0, 0, 0, 1781, 1782, 6, 237, 0, 0, 1782, 491, 1, 0, 0, 0, 70, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 498, 502, 505, 514, 516, 527, 806, 876, 880, 885, 975, 977, 1028, 1033, 1042, 1049, 1054, 1056, 1067, 1075, 1078, 1080, 1085, 1090, 1096, 1103, 1108, 1114, 1117, 1125, 1129, 1271, 1276, 1283, 1285, 1290, 1295, 1302, 1304, 1330, 1335, 1340, 1342, 1348, 1407, 1412, 1667, 1671, 1676, 1681, 1686, 1688, 1692, 1694, 41, 0, 1, 0, 5, 1, 0, 5, 2, 0, 5, 5, 0, 5, 6, 0, 5, 7, 0, 5, 8, 0, 5, 9, 0, 5, 10, 0, 5, 12, 0, 5, 13, 0, 5, 14, 0, 5, 15, 0, 7, 52, 0, 4, 0, 0, 7, 75, 0, 7, 57, 0, 7, 65, 0, 7, 63, 0, 7, 103, 0, 7, 102, 0, 7, 98, 0, 5, 4, 0, 5, 3, 0, 7, 80, 0, 7, 38, 0, 7, 59, 0, 7, 129, 0, 7, 77, 0, 7, 96, 0, 7, 95, 0, 7, 97, 0, 7, 99, 0, 7, 62, 0, 5, 0, 0, 7, 14, 0, 7, 61, 0, 7, 108, 0, 7, 53, 0, 7, 100, 0, 5, 11, 0] \ No newline at end of file +[4, 0, 139, 1782, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, 2, 136, 7, 136, 2, 137, 7, 137, 2, 138, 7, 138, 2, 139, 7, 139, 2, 140, 7, 140, 2, 141, 7, 141, 2, 142, 7, 142, 2, 143, 7, 143, 2, 144, 7, 144, 2, 145, 7, 145, 2, 146, 7, 146, 2, 147, 7, 147, 2, 148, 7, 148, 2, 149, 7, 149, 2, 150, 7, 150, 2, 151, 7, 151, 2, 152, 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, 2, 155, 7, 155, 2, 156, 7, 156, 2, 157, 7, 157, 2, 158, 7, 158, 2, 159, 7, 159, 2, 160, 7, 160, 2, 161, 7, 161, 2, 162, 7, 162, 2, 163, 7, 163, 2, 164, 7, 164, 2, 165, 7, 165, 2, 166, 7, 166, 2, 167, 7, 167, 2, 168, 7, 168, 2, 169, 7, 169, 2, 170, 7, 170, 2, 171, 7, 171, 2, 172, 7, 172, 2, 173, 7, 173, 2, 174, 7, 174, 2, 175, 7, 175, 2, 176, 7, 176, 2, 177, 7, 177, 2, 178, 7, 178, 2, 179, 7, 179, 2, 180, 7, 180, 2, 181, 7, 181, 2, 182, 7, 182, 2, 183, 7, 183, 2, 184, 7, 184, 2, 185, 7, 185, 2, 186, 7, 186, 2, 187, 7, 187, 2, 188, 7, 188, 2, 189, 7, 189, 2, 190, 7, 190, 2, 191, 7, 191, 2, 192, 7, 192, 2, 193, 7, 193, 2, 194, 7, 194, 2, 195, 7, 195, 2, 196, 7, 196, 2, 197, 7, 197, 2, 198, 7, 198, 2, 199, 7, 199, 2, 200, 7, 200, 2, 201, 7, 201, 2, 202, 7, 202, 2, 203, 7, 203, 2, 204, 7, 204, 2, 205, 7, 205, 2, 206, 7, 206, 2, 207, 7, 207, 2, 208, 7, 208, 2, 209, 7, 209, 2, 210, 7, 210, 2, 211, 7, 211, 2, 212, 7, 212, 2, 213, 7, 213, 2, 214, 7, 214, 2, 215, 7, 215, 2, 216, 7, 216, 2, 217, 7, 217, 2, 218, 7, 218, 2, 219, 7, 219, 2, 220, 7, 220, 2, 221, 7, 221, 2, 222, 7, 222, 2, 223, 7, 223, 2, 224, 7, 224, 2, 225, 7, 225, 2, 226, 7, 226, 2, 227, 7, 227, 2, 228, 7, 228, 2, 229, 7, 229, 2, 230, 7, 230, 2, 231, 7, 231, 2, 232, 7, 232, 2, 233, 7, 233, 2, 234, 7, 234, 2, 235, 7, 235, 2, 236, 7, 236, 2, 237, 7, 237, 1, 0, 1, 0, 1, 0, 1, 0, 5, 0, 497, 8, 0, 10, 0, 12, 0, 500, 9, 0, 1, 0, 3, 0, 503, 8, 0, 1, 0, 3, 0, 506, 8, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 515, 8, 1, 10, 1, 12, 1, 518, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 2, 526, 8, 2, 11, 2, 12, 2, 527, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 33, 4, 33, 804, 8, 33, 11, 33, 12, 33, 805, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 49, 4, 49, 874, 8, 49, 11, 49, 12, 49, 875, 1, 49, 1, 49, 3, 49, 880, 8, 49, 1, 49, 4, 49, 883, 8, 49, 11, 49, 12, 49, 884, 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 4, 70, 975, 8, 70, 11, 70, 12, 70, 976, 1, 71, 1, 71, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 73, 1, 73, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 80, 1, 80, 1, 81, 1, 81, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 84, 1, 84, 3, 84, 1028, 8, 84, 1, 84, 4, 84, 1031, 8, 84, 11, 84, 12, 84, 1032, 1, 85, 1, 85, 1, 86, 1, 86, 1, 87, 1, 87, 1, 87, 3, 87, 1042, 8, 87, 1, 88, 1, 88, 1, 89, 1, 89, 1, 89, 3, 89, 1049, 8, 89, 1, 90, 1, 90, 1, 90, 5, 90, 1054, 8, 90, 10, 90, 12, 90, 1057, 9, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 5, 90, 1065, 8, 90, 10, 90, 12, 90, 1068, 9, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 3, 90, 1075, 8, 90, 1, 90, 3, 90, 1078, 8, 90, 3, 90, 1080, 8, 90, 1, 91, 4, 91, 1083, 8, 91, 11, 91, 12, 91, 1084, 1, 92, 4, 92, 1088, 8, 92, 11, 92, 12, 92, 1089, 1, 92, 1, 92, 5, 92, 1094, 8, 92, 10, 92, 12, 92, 1097, 9, 92, 1, 92, 1, 92, 4, 92, 1101, 8, 92, 11, 92, 12, 92, 1102, 1, 92, 4, 92, 1106, 8, 92, 11, 92, 12, 92, 1107, 1, 92, 1, 92, 5, 92, 1112, 8, 92, 10, 92, 12, 92, 1115, 9, 92, 3, 92, 1117, 8, 92, 1, 92, 1, 92, 1, 92, 1, 92, 4, 92, 1123, 8, 92, 11, 92, 12, 92, 1124, 1, 92, 1, 92, 3, 92, 1129, 8, 92, 1, 93, 1, 93, 1, 93, 1, 93, 1, 94, 1, 94, 1, 94, 1, 95, 1, 95, 1, 95, 1, 95, 1, 96, 1, 96, 1, 97, 1, 97, 1, 97, 1, 98, 1, 98, 1, 98, 1, 99, 1, 99, 1, 100, 1, 100, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 102, 1, 102, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 105, 1, 105, 1, 105, 1, 106, 1, 106, 1, 106, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 109, 1, 109, 1, 109, 1, 109, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 112, 1, 112, 1, 112, 1, 113, 1, 113, 1, 113, 1, 114, 1, 114, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 116, 1, 116, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 118, 1, 118, 1, 118, 1, 119, 1, 119, 1, 119, 1, 120, 1, 120, 1, 120, 1, 121, 1, 121, 1, 122, 1, 122, 1, 122, 1, 123, 1, 123, 1, 124, 1, 124, 1, 124, 1, 125, 1, 125, 1, 126, 1, 126, 1, 127, 1, 127, 1, 128, 1, 128, 1, 129, 1, 129, 1, 130, 1, 130, 1, 131, 1, 131, 1, 132, 1, 132, 1, 132, 1, 133, 1, 133, 1, 133, 1, 133, 1, 134, 1, 134, 1, 134, 3, 134, 1271, 8, 134, 1, 134, 5, 134, 1274, 8, 134, 10, 134, 12, 134, 1277, 9, 134, 1, 134, 1, 134, 4, 134, 1281, 8, 134, 11, 134, 12, 134, 1282, 3, 134, 1285, 8, 134, 1, 135, 1, 135, 1, 135, 3, 135, 1290, 8, 135, 1, 135, 5, 135, 1293, 8, 135, 10, 135, 12, 135, 1296, 9, 135, 1, 135, 1, 135, 4, 135, 1300, 8, 135, 11, 135, 12, 135, 1301, 3, 135, 1304, 8, 135, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 140, 1, 140, 5, 140, 1328, 8, 140, 10, 140, 12, 140, 1331, 9, 140, 1, 140, 1, 140, 3, 140, 1335, 8, 140, 1, 140, 4, 140, 1338, 8, 140, 11, 140, 12, 140, 1339, 3, 140, 1342, 8, 140, 1, 141, 1, 141, 4, 141, 1346, 8, 141, 11, 141, 12, 141, 1347, 1, 141, 1, 141, 1, 142, 1, 142, 1, 143, 1, 143, 1, 143, 1, 143, 1, 144, 1, 144, 1, 144, 1, 144, 1, 145, 1, 145, 1, 145, 1, 145, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 1, 147, 1, 147, 1, 147, 1, 147, 1, 148, 1, 148, 1, 148, 1, 148, 1, 149, 1, 149, 1, 149, 1, 149, 1, 150, 1, 150, 1, 150, 1, 150, 1, 151, 1, 151, 1, 151, 1, 151, 1, 152, 1, 152, 1, 152, 1, 152, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 154, 1, 154, 1, 154, 3, 154, 1407, 8, 154, 1, 155, 4, 155, 1410, 8, 155, 11, 155, 12, 155, 1411, 1, 156, 1, 156, 1, 156, 1, 156, 1, 157, 1, 157, 1, 157, 1, 157, 1, 158, 1, 158, 1, 158, 1, 158, 1, 159, 1, 159, 1, 159, 1, 159, 1, 160, 1, 160, 1, 160, 1, 160, 1, 161, 1, 161, 1, 161, 1, 161, 1, 161, 1, 162, 1, 162, 1, 162, 1, 162, 1, 162, 1, 163, 1, 163, 1, 163, 1, 163, 1, 164, 1, 164, 1, 164, 1, 164, 1, 165, 1, 165, 1, 165, 1, 165, 1, 166, 1, 166, 1, 166, 1, 166, 1, 166, 1, 167, 1, 167, 1, 167, 1, 167, 1, 167, 1, 168, 1, 168, 1, 168, 1, 168, 1, 169, 1, 169, 1, 169, 1, 169, 1, 169, 1, 169, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 171, 1, 171, 1, 171, 1, 171, 1, 172, 1, 172, 1, 172, 1, 172, 1, 173, 1, 173, 1, 173, 1, 173, 1, 174, 1, 174, 1, 174, 1, 174, 1, 175, 1, 175, 1, 175, 1, 175, 1, 176, 1, 176, 1, 176, 1, 176, 1, 177, 1, 177, 1, 177, 1, 177, 1, 178, 1, 178, 1, 178, 1, 178, 1, 179, 1, 179, 1, 179, 1, 179, 1, 179, 1, 180, 1, 180, 1, 180, 1, 180, 1, 181, 1, 181, 1, 181, 1, 181, 1, 182, 1, 182, 1, 182, 1, 182, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 184, 1, 184, 1, 184, 1, 184, 1, 185, 1, 185, 1, 185, 1, 185, 1, 186, 1, 186, 1, 186, 1, 186, 1, 187, 1, 187, 1, 187, 1, 187, 1, 188, 1, 188, 1, 188, 1, 188, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 190, 1, 190, 1, 190, 1, 190, 1, 191, 1, 191, 1, 191, 1, 191, 1, 192, 1, 192, 1, 192, 1, 192, 1, 193, 1, 193, 1, 193, 1, 193, 1, 194, 1, 194, 1, 194, 1, 194, 1, 195, 1, 195, 1, 195, 1, 195, 1, 196, 1, 196, 1, 196, 1, 196, 1, 196, 1, 197, 1, 197, 1, 197, 1, 197, 1, 198, 1, 198, 1, 198, 1, 198, 1, 199, 1, 199, 1, 199, 1, 199, 1, 200, 1, 200, 1, 200, 1, 200, 1, 201, 1, 201, 1, 201, 1, 201, 1, 202, 1, 202, 1, 202, 1, 202, 1, 203, 1, 203, 1, 203, 1, 203, 1, 204, 1, 204, 1, 204, 1, 204, 1, 205, 1, 205, 1, 205, 1, 205, 1, 206, 1, 206, 1, 206, 1, 206, 1, 207, 1, 207, 1, 207, 1, 207, 1, 207, 1, 208, 1, 208, 1, 208, 1, 208, 1, 209, 1, 209, 1, 209, 1, 209, 1, 210, 1, 210, 1, 210, 1, 210, 1, 211, 1, 211, 1, 211, 1, 211, 1, 212, 1, 212, 1, 212, 1, 212, 1, 213, 1, 213, 1, 213, 1, 213, 1, 214, 1, 214, 1, 214, 1, 214, 3, 214, 1667, 8, 214, 1, 215, 1, 215, 3, 215, 1671, 8, 215, 1, 215, 5, 215, 1674, 8, 215, 10, 215, 12, 215, 1677, 9, 215, 1, 215, 1, 215, 3, 215, 1681, 8, 215, 1, 215, 4, 215, 1684, 8, 215, 11, 215, 12, 215, 1685, 3, 215, 1688, 8, 215, 1, 216, 1, 216, 4, 216, 1692, 8, 216, 11, 216, 12, 216, 1693, 1, 217, 1, 217, 1, 217, 1, 217, 1, 218, 1, 218, 1, 218, 1, 218, 1, 219, 1, 219, 1, 219, 1, 219, 1, 220, 1, 220, 1, 220, 1, 220, 1, 220, 1, 221, 1, 221, 1, 221, 1, 221, 1, 222, 1, 222, 1, 222, 1, 222, 1, 223, 1, 223, 1, 223, 1, 223, 1, 224, 1, 224, 1, 224, 1, 224, 1, 225, 1, 225, 1, 225, 1, 225, 1, 226, 1, 226, 1, 226, 1, 226, 1, 227, 1, 227, 1, 227, 1, 227, 1, 228, 1, 228, 1, 228, 1, 228, 1, 229, 1, 229, 1, 229, 1, 229, 1, 230, 1, 230, 1, 230, 1, 230, 1, 231, 1, 231, 1, 231, 1, 231, 1, 232, 1, 232, 1, 232, 1, 232, 1, 233, 1, 233, 1, 233, 1, 233, 1, 233, 1, 234, 1, 234, 1, 234, 1, 234, 1, 234, 1, 235, 1, 235, 1, 235, 1, 235, 1, 236, 1, 236, 1, 236, 1, 236, 1, 237, 1, 237, 1, 237, 1, 237, 2, 516, 1066, 0, 238, 16, 1, 18, 2, 20, 3, 22, 4, 24, 5, 26, 6, 28, 7, 30, 8, 32, 9, 34, 10, 36, 11, 38, 12, 40, 13, 42, 14, 44, 15, 46, 16, 48, 17, 50, 18, 52, 19, 54, 20, 56, 21, 58, 22, 60, 23, 62, 24, 64, 25, 66, 26, 68, 27, 70, 28, 72, 29, 74, 30, 76, 31, 78, 32, 80, 33, 82, 34, 84, 0, 86, 0, 88, 0, 90, 0, 92, 0, 94, 0, 96, 0, 98, 35, 100, 36, 102, 37, 104, 0, 106, 0, 108, 0, 110, 0, 112, 0, 114, 38, 116, 0, 118, 39, 120, 40, 122, 41, 124, 0, 126, 0, 128, 0, 130, 0, 132, 0, 134, 0, 136, 0, 138, 0, 140, 0, 142, 0, 144, 0, 146, 42, 148, 43, 150, 44, 152, 0, 154, 0, 156, 45, 158, 46, 160, 47, 162, 48, 164, 0, 166, 0, 168, 49, 170, 50, 172, 51, 174, 52, 176, 0, 178, 0, 180, 0, 182, 0, 184, 0, 186, 0, 188, 0, 190, 0, 192, 0, 194, 0, 196, 53, 198, 54, 200, 55, 202, 56, 204, 57, 206, 58, 208, 59, 210, 60, 212, 61, 214, 62, 216, 63, 218, 64, 220, 65, 222, 66, 224, 67, 226, 68, 228, 69, 230, 70, 232, 71, 234, 72, 236, 73, 238, 74, 240, 75, 242, 76, 244, 77, 246, 78, 248, 79, 250, 80, 252, 81, 254, 82, 256, 83, 258, 84, 260, 85, 262, 86, 264, 87, 266, 88, 268, 89, 270, 90, 272, 91, 274, 92, 276, 93, 278, 94, 280, 95, 282, 0, 284, 96, 286, 97, 288, 98, 290, 99, 292, 100, 294, 101, 296, 102, 298, 0, 300, 103, 302, 104, 304, 105, 306, 106, 308, 0, 310, 0, 312, 0, 314, 0, 316, 0, 318, 0, 320, 0, 322, 107, 324, 0, 326, 108, 328, 0, 330, 0, 332, 109, 334, 110, 336, 111, 338, 0, 340, 0, 342, 112, 344, 113, 346, 114, 348, 0, 350, 115, 352, 0, 354, 0, 356, 116, 358, 0, 360, 0, 362, 0, 364, 0, 366, 0, 368, 117, 370, 118, 372, 119, 374, 0, 376, 0, 378, 0, 380, 0, 382, 0, 384, 0, 386, 0, 388, 120, 390, 121, 392, 122, 394, 0, 396, 0, 398, 0, 400, 0, 402, 123, 404, 124, 406, 125, 408, 0, 410, 0, 412, 0, 414, 0, 416, 0, 418, 0, 420, 0, 422, 0, 424, 126, 426, 127, 428, 128, 430, 0, 432, 0, 434, 0, 436, 0, 438, 0, 440, 0, 442, 0, 444, 0, 446, 0, 448, 129, 450, 130, 452, 131, 454, 132, 456, 0, 458, 0, 460, 0, 462, 0, 464, 0, 466, 0, 468, 0, 470, 0, 472, 0, 474, 0, 476, 133, 478, 134, 480, 135, 482, 0, 484, 136, 486, 137, 488, 138, 490, 139, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 36, 2, 0, 10, 10, 13, 13, 3, 0, 9, 10, 13, 13, 32, 32, 2, 0, 67, 67, 99, 99, 2, 0, 72, 72, 104, 104, 2, 0, 65, 65, 97, 97, 2, 0, 78, 78, 110, 110, 2, 0, 71, 71, 103, 103, 2, 0, 69, 69, 101, 101, 2, 0, 80, 80, 112, 112, 2, 0, 79, 79, 111, 111, 2, 0, 73, 73, 105, 105, 2, 0, 84, 84, 116, 116, 2, 0, 82, 82, 114, 114, 2, 0, 88, 88, 120, 120, 2, 0, 76, 76, 108, 108, 2, 0, 77, 77, 109, 109, 2, 0, 68, 68, 100, 100, 2, 0, 83, 83, 115, 115, 2, 0, 86, 86, 118, 118, 2, 0, 75, 75, 107, 107, 2, 0, 87, 87, 119, 119, 2, 0, 70, 70, 102, 102, 2, 0, 85, 85, 117, 117, 6, 0, 9, 10, 13, 13, 32, 32, 47, 47, 91, 91, 93, 93, 11, 0, 9, 10, 13, 13, 32, 32, 34, 35, 44, 44, 47, 47, 58, 58, 60, 60, 62, 63, 92, 92, 124, 124, 1, 0, 48, 57, 2, 0, 65, 90, 97, 122, 8, 0, 34, 34, 78, 78, 82, 82, 84, 84, 92, 92, 110, 110, 114, 114, 116, 116, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 2, 0, 43, 43, 45, 45, 1, 0, 96, 96, 2, 0, 66, 66, 98, 98, 2, 0, 89, 89, 121, 121, 11, 0, 9, 10, 13, 13, 32, 32, 34, 34, 44, 44, 47, 47, 58, 58, 61, 61, 91, 91, 93, 93, 124, 124, 2, 0, 42, 42, 47, 47, 2, 0, 74, 74, 106, 106, 1813, 0, 16, 1, 0, 0, 0, 0, 18, 1, 0, 0, 0, 0, 20, 1, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 24, 1, 0, 0, 0, 0, 26, 1, 0, 0, 0, 0, 28, 1, 0, 0, 0, 0, 30, 1, 0, 0, 0, 0, 32, 1, 0, 0, 0, 0, 34, 1, 0, 0, 0, 0, 36, 1, 0, 0, 0, 0, 38, 1, 0, 0, 0, 0, 40, 1, 0, 0, 0, 0, 42, 1, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 46, 1, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 50, 1, 0, 0, 0, 0, 52, 1, 0, 0, 0, 0, 54, 1, 0, 0, 0, 0, 56, 1, 0, 0, 0, 0, 58, 1, 0, 0, 0, 0, 60, 1, 0, 0, 0, 0, 62, 1, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0, 66, 1, 0, 0, 0, 0, 68, 1, 0, 0, 0, 0, 70, 1, 0, 0, 0, 0, 72, 1, 0, 0, 0, 0, 74, 1, 0, 0, 0, 0, 76, 1, 0, 0, 0, 0, 78, 1, 0, 0, 0, 0, 80, 1, 0, 0, 0, 0, 82, 1, 0, 0, 0, 1, 84, 1, 0, 0, 0, 1, 86, 1, 0, 0, 0, 1, 88, 1, 0, 0, 0, 1, 90, 1, 0, 0, 0, 1, 92, 1, 0, 0, 0, 1, 94, 1, 0, 0, 0, 1, 96, 1, 0, 0, 0, 1, 98, 1, 0, 0, 0, 1, 100, 1, 0, 0, 0, 1, 102, 1, 0, 0, 0, 2, 104, 1, 0, 0, 0, 2, 106, 1, 0, 0, 0, 2, 108, 1, 0, 0, 0, 2, 110, 1, 0, 0, 0, 2, 114, 1, 0, 0, 0, 2, 116, 1, 0, 0, 0, 2, 118, 1, 0, 0, 0, 2, 120, 1, 0, 0, 0, 2, 122, 1, 0, 0, 0, 3, 124, 1, 0, 0, 0, 3, 126, 1, 0, 0, 0, 3, 128, 1, 0, 0, 0, 3, 130, 1, 0, 0, 0, 3, 132, 1, 0, 0, 0, 3, 134, 1, 0, 0, 0, 3, 136, 1, 0, 0, 0, 3, 138, 1, 0, 0, 0, 3, 140, 1, 0, 0, 0, 3, 142, 1, 0, 0, 0, 3, 144, 1, 0, 0, 0, 3, 146, 1, 0, 0, 0, 3, 148, 1, 0, 0, 0, 3, 150, 1, 0, 0, 0, 4, 152, 1, 0, 0, 0, 4, 154, 1, 0, 0, 0, 4, 156, 1, 0, 0, 0, 4, 158, 1, 0, 0, 0, 4, 160, 1, 0, 0, 0, 4, 162, 1, 0, 0, 0, 5, 164, 1, 0, 0, 0, 5, 166, 1, 0, 0, 0, 5, 168, 1, 0, 0, 0, 5, 170, 1, 0, 0, 0, 5, 172, 1, 0, 0, 0, 6, 174, 1, 0, 0, 0, 6, 196, 1, 0, 0, 0, 6, 198, 1, 0, 0, 0, 6, 200, 1, 0, 0, 0, 6, 202, 1, 0, 0, 0, 6, 204, 1, 0, 0, 0, 6, 206, 1, 0, 0, 0, 6, 208, 1, 0, 0, 0, 6, 210, 1, 0, 0, 0, 6, 212, 1, 0, 0, 0, 6, 214, 1, 0, 0, 0, 6, 216, 1, 0, 0, 0, 6, 218, 1, 0, 0, 0, 6, 220, 1, 0, 0, 0, 6, 222, 1, 0, 0, 0, 6, 224, 1, 0, 0, 0, 6, 226, 1, 0, 0, 0, 6, 228, 1, 0, 0, 0, 6, 230, 1, 0, 0, 0, 6, 232, 1, 0, 0, 0, 6, 234, 1, 0, 0, 0, 6, 236, 1, 0, 0, 0, 6, 238, 1, 0, 0, 0, 6, 240, 1, 0, 0, 0, 6, 242, 1, 0, 0, 0, 6, 244, 1, 0, 0, 0, 6, 246, 1, 0, 0, 0, 6, 248, 1, 0, 0, 0, 6, 250, 1, 0, 0, 0, 6, 252, 1, 0, 0, 0, 6, 254, 1, 0, 0, 0, 6, 256, 1, 0, 0, 0, 6, 258, 1, 0, 0, 0, 6, 260, 1, 0, 0, 0, 6, 262, 1, 0, 0, 0, 6, 264, 1, 0, 0, 0, 6, 266, 1, 0, 0, 0, 6, 268, 1, 0, 0, 0, 6, 270, 1, 0, 0, 0, 6, 272, 1, 0, 0, 0, 6, 274, 1, 0, 0, 0, 6, 276, 1, 0, 0, 0, 6, 278, 1, 0, 0, 0, 6, 280, 1, 0, 0, 0, 6, 282, 1, 0, 0, 0, 6, 284, 1, 0, 0, 0, 6, 286, 1, 0, 0, 0, 6, 288, 1, 0, 0, 0, 6, 290, 1, 0, 0, 0, 6, 292, 1, 0, 0, 0, 6, 294, 1, 0, 0, 0, 6, 296, 1, 0, 0, 0, 6, 300, 1, 0, 0, 0, 6, 302, 1, 0, 0, 0, 6, 304, 1, 0, 0, 0, 6, 306, 1, 0, 0, 0, 7, 308, 1, 0, 0, 0, 7, 310, 1, 0, 0, 0, 7, 312, 1, 0, 0, 0, 7, 314, 1, 0, 0, 0, 7, 316, 1, 0, 0, 0, 7, 318, 1, 0, 0, 0, 7, 320, 1, 0, 0, 0, 7, 322, 1, 0, 0, 0, 7, 326, 1, 0, 0, 0, 7, 328, 1, 0, 0, 0, 7, 330, 1, 0, 0, 0, 7, 332, 1, 0, 0, 0, 7, 334, 1, 0, 0, 0, 7, 336, 1, 0, 0, 0, 8, 338, 1, 0, 0, 0, 8, 340, 1, 0, 0, 0, 8, 342, 1, 0, 0, 0, 8, 344, 1, 0, 0, 0, 8, 346, 1, 0, 0, 0, 9, 348, 1, 0, 0, 0, 9, 350, 1, 0, 0, 0, 9, 352, 1, 0, 0, 0, 9, 354, 1, 0, 0, 0, 9, 356, 1, 0, 0, 0, 9, 358, 1, 0, 0, 0, 9, 360, 1, 0, 0, 0, 9, 362, 1, 0, 0, 0, 9, 364, 1, 0, 0, 0, 9, 366, 1, 0, 0, 0, 9, 368, 1, 0, 0, 0, 9, 370, 1, 0, 0, 0, 9, 372, 1, 0, 0, 0, 10, 374, 1, 0, 0, 0, 10, 376, 1, 0, 0, 0, 10, 378, 1, 0, 0, 0, 10, 380, 1, 0, 0, 0, 10, 382, 1, 0, 0, 0, 10, 384, 1, 0, 0, 0, 10, 386, 1, 0, 0, 0, 10, 388, 1, 0, 0, 0, 10, 390, 1, 0, 0, 0, 10, 392, 1, 0, 0, 0, 11, 394, 1, 0, 0, 0, 11, 396, 1, 0, 0, 0, 11, 398, 1, 0, 0, 0, 11, 400, 1, 0, 0, 0, 11, 402, 1, 0, 0, 0, 11, 404, 1, 0, 0, 0, 11, 406, 1, 0, 0, 0, 12, 408, 1, 0, 0, 0, 12, 410, 1, 0, 0, 0, 12, 412, 1, 0, 0, 0, 12, 414, 1, 0, 0, 0, 12, 416, 1, 0, 0, 0, 12, 418, 1, 0, 0, 0, 12, 420, 1, 0, 0, 0, 12, 422, 1, 0, 0, 0, 12, 424, 1, 0, 0, 0, 12, 426, 1, 0, 0, 0, 12, 428, 1, 0, 0, 0, 13, 430, 1, 0, 0, 0, 13, 432, 1, 0, 0, 0, 13, 434, 1, 0, 0, 0, 13, 436, 1, 0, 0, 0, 13, 438, 1, 0, 0, 0, 13, 440, 1, 0, 0, 0, 13, 442, 1, 0, 0, 0, 13, 448, 1, 0, 0, 0, 13, 450, 1, 0, 0, 0, 13, 452, 1, 0, 0, 0, 13, 454, 1, 0, 0, 0, 14, 456, 1, 0, 0, 0, 14, 458, 1, 0, 0, 0, 14, 460, 1, 0, 0, 0, 14, 462, 1, 0, 0, 0, 14, 464, 1, 0, 0, 0, 14, 466, 1, 0, 0, 0, 14, 468, 1, 0, 0, 0, 14, 470, 1, 0, 0, 0, 14, 472, 1, 0, 0, 0, 14, 474, 1, 0, 0, 0, 14, 476, 1, 0, 0, 0, 14, 478, 1, 0, 0, 0, 14, 480, 1, 0, 0, 0, 15, 482, 1, 0, 0, 0, 15, 484, 1, 0, 0, 0, 15, 486, 1, 0, 0, 0, 15, 488, 1, 0, 0, 0, 15, 490, 1, 0, 0, 0, 16, 492, 1, 0, 0, 0, 18, 509, 1, 0, 0, 0, 20, 525, 1, 0, 0, 0, 22, 531, 1, 0, 0, 0, 24, 546, 1, 0, 0, 0, 26, 555, 1, 0, 0, 0, 28, 565, 1, 0, 0, 0, 30, 578, 1, 0, 0, 0, 32, 588, 1, 0, 0, 0, 34, 595, 1, 0, 0, 0, 36, 602, 1, 0, 0, 0, 38, 610, 1, 0, 0, 0, 40, 616, 1, 0, 0, 0, 42, 623, 1, 0, 0, 0, 44, 631, 1, 0, 0, 0, 46, 639, 1, 0, 0, 0, 48, 654, 1, 0, 0, 0, 50, 664, 1, 0, 0, 0, 52, 674, 1, 0, 0, 0, 54, 681, 1, 0, 0, 0, 56, 687, 1, 0, 0, 0, 58, 695, 1, 0, 0, 0, 60, 704, 1, 0, 0, 0, 62, 712, 1, 0, 0, 0, 64, 720, 1, 0, 0, 0, 66, 729, 1, 0, 0, 0, 68, 741, 1, 0, 0, 0, 70, 753, 1, 0, 0, 0, 72, 760, 1, 0, 0, 0, 74, 767, 1, 0, 0, 0, 76, 779, 1, 0, 0, 0, 78, 786, 1, 0, 0, 0, 80, 795, 1, 0, 0, 0, 82, 803, 1, 0, 0, 0, 84, 809, 1, 0, 0, 0, 86, 814, 1, 0, 0, 0, 88, 818, 1, 0, 0, 0, 90, 822, 1, 0, 0, 0, 92, 826, 1, 0, 0, 0, 94, 830, 1, 0, 0, 0, 96, 834, 1, 0, 0, 0, 98, 838, 1, 0, 0, 0, 100, 842, 1, 0, 0, 0, 102, 846, 1, 0, 0, 0, 104, 850, 1, 0, 0, 0, 106, 855, 1, 0, 0, 0, 108, 860, 1, 0, 0, 0, 110, 865, 1, 0, 0, 0, 112, 870, 1, 0, 0, 0, 114, 879, 1, 0, 0, 0, 116, 886, 1, 0, 0, 0, 118, 890, 1, 0, 0, 0, 120, 894, 1, 0, 0, 0, 122, 898, 1, 0, 0, 0, 124, 902, 1, 0, 0, 0, 126, 908, 1, 0, 0, 0, 128, 912, 1, 0, 0, 0, 130, 916, 1, 0, 0, 0, 132, 920, 1, 0, 0, 0, 134, 924, 1, 0, 0, 0, 136, 928, 1, 0, 0, 0, 138, 932, 1, 0, 0, 0, 140, 936, 1, 0, 0, 0, 142, 940, 1, 0, 0, 0, 144, 944, 1, 0, 0, 0, 146, 948, 1, 0, 0, 0, 148, 952, 1, 0, 0, 0, 150, 956, 1, 0, 0, 0, 152, 960, 1, 0, 0, 0, 154, 965, 1, 0, 0, 0, 156, 974, 1, 0, 0, 0, 158, 978, 1, 0, 0, 0, 160, 982, 1, 0, 0, 0, 162, 986, 1, 0, 0, 0, 164, 990, 1, 0, 0, 0, 166, 995, 1, 0, 0, 0, 168, 1000, 1, 0, 0, 0, 170, 1004, 1, 0, 0, 0, 172, 1008, 1, 0, 0, 0, 174, 1012, 1, 0, 0, 0, 176, 1016, 1, 0, 0, 0, 178, 1018, 1, 0, 0, 0, 180, 1020, 1, 0, 0, 0, 182, 1023, 1, 0, 0, 0, 184, 1025, 1, 0, 0, 0, 186, 1034, 1, 0, 0, 0, 188, 1036, 1, 0, 0, 0, 190, 1041, 1, 0, 0, 0, 192, 1043, 1, 0, 0, 0, 194, 1048, 1, 0, 0, 0, 196, 1079, 1, 0, 0, 0, 198, 1082, 1, 0, 0, 0, 200, 1128, 1, 0, 0, 0, 202, 1130, 1, 0, 0, 0, 204, 1134, 1, 0, 0, 0, 206, 1137, 1, 0, 0, 0, 208, 1141, 1, 0, 0, 0, 210, 1143, 1, 0, 0, 0, 212, 1146, 1, 0, 0, 0, 214, 1149, 1, 0, 0, 0, 216, 1151, 1, 0, 0, 0, 218, 1153, 1, 0, 0, 0, 220, 1158, 1, 0, 0, 0, 222, 1160, 1, 0, 0, 0, 224, 1166, 1, 0, 0, 0, 226, 1172, 1, 0, 0, 0, 228, 1175, 1, 0, 0, 0, 230, 1178, 1, 0, 0, 0, 232, 1183, 1, 0, 0, 0, 234, 1188, 1, 0, 0, 0, 236, 1192, 1, 0, 0, 0, 238, 1197, 1, 0, 0, 0, 240, 1203, 1, 0, 0, 0, 242, 1206, 1, 0, 0, 0, 244, 1209, 1, 0, 0, 0, 246, 1211, 1, 0, 0, 0, 248, 1217, 1, 0, 0, 0, 250, 1222, 1, 0, 0, 0, 252, 1227, 1, 0, 0, 0, 254, 1230, 1, 0, 0, 0, 256, 1233, 1, 0, 0, 0, 258, 1236, 1, 0, 0, 0, 260, 1238, 1, 0, 0, 0, 262, 1241, 1, 0, 0, 0, 264, 1243, 1, 0, 0, 0, 266, 1246, 1, 0, 0, 0, 268, 1248, 1, 0, 0, 0, 270, 1250, 1, 0, 0, 0, 272, 1252, 1, 0, 0, 0, 274, 1254, 1, 0, 0, 0, 276, 1256, 1, 0, 0, 0, 278, 1258, 1, 0, 0, 0, 280, 1260, 1, 0, 0, 0, 282, 1263, 1, 0, 0, 0, 284, 1284, 1, 0, 0, 0, 286, 1303, 1, 0, 0, 0, 288, 1305, 1, 0, 0, 0, 290, 1310, 1, 0, 0, 0, 292, 1315, 1, 0, 0, 0, 294, 1320, 1, 0, 0, 0, 296, 1341, 1, 0, 0, 0, 298, 1343, 1, 0, 0, 0, 300, 1351, 1, 0, 0, 0, 302, 1353, 1, 0, 0, 0, 304, 1357, 1, 0, 0, 0, 306, 1361, 1, 0, 0, 0, 308, 1365, 1, 0, 0, 0, 310, 1370, 1, 0, 0, 0, 312, 1374, 1, 0, 0, 0, 314, 1378, 1, 0, 0, 0, 316, 1382, 1, 0, 0, 0, 318, 1386, 1, 0, 0, 0, 320, 1390, 1, 0, 0, 0, 322, 1394, 1, 0, 0, 0, 324, 1406, 1, 0, 0, 0, 326, 1409, 1, 0, 0, 0, 328, 1413, 1, 0, 0, 0, 330, 1417, 1, 0, 0, 0, 332, 1421, 1, 0, 0, 0, 334, 1425, 1, 0, 0, 0, 336, 1429, 1, 0, 0, 0, 338, 1433, 1, 0, 0, 0, 340, 1438, 1, 0, 0, 0, 342, 1443, 1, 0, 0, 0, 344, 1447, 1, 0, 0, 0, 346, 1451, 1, 0, 0, 0, 348, 1455, 1, 0, 0, 0, 350, 1460, 1, 0, 0, 0, 352, 1465, 1, 0, 0, 0, 354, 1469, 1, 0, 0, 0, 356, 1475, 1, 0, 0, 0, 358, 1484, 1, 0, 0, 0, 360, 1488, 1, 0, 0, 0, 362, 1492, 1, 0, 0, 0, 364, 1496, 1, 0, 0, 0, 366, 1500, 1, 0, 0, 0, 368, 1504, 1, 0, 0, 0, 370, 1508, 1, 0, 0, 0, 372, 1512, 1, 0, 0, 0, 374, 1516, 1, 0, 0, 0, 376, 1521, 1, 0, 0, 0, 378, 1525, 1, 0, 0, 0, 380, 1529, 1, 0, 0, 0, 382, 1533, 1, 0, 0, 0, 384, 1538, 1, 0, 0, 0, 386, 1542, 1, 0, 0, 0, 388, 1546, 1, 0, 0, 0, 390, 1550, 1, 0, 0, 0, 392, 1554, 1, 0, 0, 0, 394, 1558, 1, 0, 0, 0, 396, 1564, 1, 0, 0, 0, 398, 1568, 1, 0, 0, 0, 400, 1572, 1, 0, 0, 0, 402, 1576, 1, 0, 0, 0, 404, 1580, 1, 0, 0, 0, 406, 1584, 1, 0, 0, 0, 408, 1588, 1, 0, 0, 0, 410, 1593, 1, 0, 0, 0, 412, 1597, 1, 0, 0, 0, 414, 1601, 1, 0, 0, 0, 416, 1605, 1, 0, 0, 0, 418, 1609, 1, 0, 0, 0, 420, 1613, 1, 0, 0, 0, 422, 1617, 1, 0, 0, 0, 424, 1621, 1, 0, 0, 0, 426, 1625, 1, 0, 0, 0, 428, 1629, 1, 0, 0, 0, 430, 1633, 1, 0, 0, 0, 432, 1638, 1, 0, 0, 0, 434, 1642, 1, 0, 0, 0, 436, 1646, 1, 0, 0, 0, 438, 1650, 1, 0, 0, 0, 440, 1654, 1, 0, 0, 0, 442, 1658, 1, 0, 0, 0, 444, 1666, 1, 0, 0, 0, 446, 1687, 1, 0, 0, 0, 448, 1691, 1, 0, 0, 0, 450, 1695, 1, 0, 0, 0, 452, 1699, 1, 0, 0, 0, 454, 1703, 1, 0, 0, 0, 456, 1707, 1, 0, 0, 0, 458, 1712, 1, 0, 0, 0, 460, 1716, 1, 0, 0, 0, 462, 1720, 1, 0, 0, 0, 464, 1724, 1, 0, 0, 0, 466, 1728, 1, 0, 0, 0, 468, 1732, 1, 0, 0, 0, 470, 1736, 1, 0, 0, 0, 472, 1740, 1, 0, 0, 0, 474, 1744, 1, 0, 0, 0, 476, 1748, 1, 0, 0, 0, 478, 1752, 1, 0, 0, 0, 480, 1756, 1, 0, 0, 0, 482, 1760, 1, 0, 0, 0, 484, 1765, 1, 0, 0, 0, 486, 1770, 1, 0, 0, 0, 488, 1774, 1, 0, 0, 0, 490, 1778, 1, 0, 0, 0, 492, 493, 5, 47, 0, 0, 493, 494, 5, 47, 0, 0, 494, 498, 1, 0, 0, 0, 495, 497, 8, 0, 0, 0, 496, 495, 1, 0, 0, 0, 497, 500, 1, 0, 0, 0, 498, 496, 1, 0, 0, 0, 498, 499, 1, 0, 0, 0, 499, 502, 1, 0, 0, 0, 500, 498, 1, 0, 0, 0, 501, 503, 5, 13, 0, 0, 502, 501, 1, 0, 0, 0, 502, 503, 1, 0, 0, 0, 503, 505, 1, 0, 0, 0, 504, 506, 5, 10, 0, 0, 505, 504, 1, 0, 0, 0, 505, 506, 1, 0, 0, 0, 506, 507, 1, 0, 0, 0, 507, 508, 6, 0, 0, 0, 508, 17, 1, 0, 0, 0, 509, 510, 5, 47, 0, 0, 510, 511, 5, 42, 0, 0, 511, 516, 1, 0, 0, 0, 512, 515, 3, 18, 1, 0, 513, 515, 9, 0, 0, 0, 514, 512, 1, 0, 0, 0, 514, 513, 1, 0, 0, 0, 515, 518, 1, 0, 0, 0, 516, 517, 1, 0, 0, 0, 516, 514, 1, 0, 0, 0, 517, 519, 1, 0, 0, 0, 518, 516, 1, 0, 0, 0, 519, 520, 5, 42, 0, 0, 520, 521, 5, 47, 0, 0, 521, 522, 1, 0, 0, 0, 522, 523, 6, 1, 0, 0, 523, 19, 1, 0, 0, 0, 524, 526, 7, 1, 0, 0, 525, 524, 1, 0, 0, 0, 526, 527, 1, 0, 0, 0, 527, 525, 1, 0, 0, 0, 527, 528, 1, 0, 0, 0, 528, 529, 1, 0, 0, 0, 529, 530, 6, 2, 0, 0, 530, 21, 1, 0, 0, 0, 531, 532, 7, 2, 0, 0, 532, 533, 7, 3, 0, 0, 533, 534, 7, 4, 0, 0, 534, 535, 7, 5, 0, 0, 535, 536, 7, 6, 0, 0, 536, 537, 7, 7, 0, 0, 537, 538, 5, 95, 0, 0, 538, 539, 7, 8, 0, 0, 539, 540, 7, 9, 0, 0, 540, 541, 7, 10, 0, 0, 541, 542, 7, 5, 0, 0, 542, 543, 7, 11, 0, 0, 543, 544, 1, 0, 0, 0, 544, 545, 6, 3, 1, 0, 545, 23, 1, 0, 0, 0, 546, 547, 7, 7, 0, 0, 547, 548, 7, 5, 0, 0, 548, 549, 7, 12, 0, 0, 549, 550, 7, 10, 0, 0, 550, 551, 7, 2, 0, 0, 551, 552, 7, 3, 0, 0, 552, 553, 1, 0, 0, 0, 553, 554, 6, 4, 2, 0, 554, 25, 1, 0, 0, 0, 555, 556, 7, 7, 0, 0, 556, 557, 7, 13, 0, 0, 557, 558, 7, 8, 0, 0, 558, 559, 7, 14, 0, 0, 559, 560, 7, 4, 0, 0, 560, 561, 7, 10, 0, 0, 561, 562, 7, 5, 0, 0, 562, 563, 1, 0, 0, 0, 563, 564, 6, 5, 3, 0, 564, 27, 1, 0, 0, 0, 565, 566, 7, 2, 0, 0, 566, 567, 7, 9, 0, 0, 567, 568, 7, 15, 0, 0, 568, 569, 7, 8, 0, 0, 569, 570, 7, 14, 0, 0, 570, 571, 7, 7, 0, 0, 571, 572, 7, 11, 0, 0, 572, 573, 7, 10, 0, 0, 573, 574, 7, 9, 0, 0, 574, 575, 7, 5, 0, 0, 575, 576, 1, 0, 0, 0, 576, 577, 6, 6, 4, 0, 577, 29, 1, 0, 0, 0, 578, 579, 7, 16, 0, 0, 579, 580, 7, 10, 0, 0, 580, 581, 7, 17, 0, 0, 581, 582, 7, 17, 0, 0, 582, 583, 7, 7, 0, 0, 583, 584, 7, 2, 0, 0, 584, 585, 7, 11, 0, 0, 585, 586, 1, 0, 0, 0, 586, 587, 6, 7, 4, 0, 587, 31, 1, 0, 0, 0, 588, 589, 7, 7, 0, 0, 589, 590, 7, 18, 0, 0, 590, 591, 7, 4, 0, 0, 591, 592, 7, 14, 0, 0, 592, 593, 1, 0, 0, 0, 593, 594, 6, 8, 4, 0, 594, 33, 1, 0, 0, 0, 595, 596, 7, 6, 0, 0, 596, 597, 7, 12, 0, 0, 597, 598, 7, 9, 0, 0, 598, 599, 7, 19, 0, 0, 599, 600, 1, 0, 0, 0, 600, 601, 6, 9, 4, 0, 601, 35, 1, 0, 0, 0, 602, 603, 7, 14, 0, 0, 603, 604, 7, 10, 0, 0, 604, 605, 7, 15, 0, 0, 605, 606, 7, 10, 0, 0, 606, 607, 7, 11, 0, 0, 607, 608, 1, 0, 0, 0, 608, 609, 6, 10, 4, 0, 609, 37, 1, 0, 0, 0, 610, 611, 7, 12, 0, 0, 611, 612, 7, 9, 0, 0, 612, 613, 7, 20, 0, 0, 613, 614, 1, 0, 0, 0, 614, 615, 6, 11, 4, 0, 615, 39, 1, 0, 0, 0, 616, 617, 7, 17, 0, 0, 617, 618, 7, 9, 0, 0, 618, 619, 7, 12, 0, 0, 619, 620, 7, 11, 0, 0, 620, 621, 1, 0, 0, 0, 621, 622, 6, 12, 4, 0, 622, 41, 1, 0, 0, 0, 623, 624, 7, 17, 0, 0, 624, 625, 7, 11, 0, 0, 625, 626, 7, 4, 0, 0, 626, 627, 7, 11, 0, 0, 627, 628, 7, 17, 0, 0, 628, 629, 1, 0, 0, 0, 629, 630, 6, 13, 4, 0, 630, 43, 1, 0, 0, 0, 631, 632, 7, 20, 0, 0, 632, 633, 7, 3, 0, 0, 633, 634, 7, 7, 0, 0, 634, 635, 7, 12, 0, 0, 635, 636, 7, 7, 0, 0, 636, 637, 1, 0, 0, 0, 637, 638, 6, 14, 4, 0, 638, 45, 1, 0, 0, 0, 639, 640, 4, 15, 0, 0, 640, 641, 7, 10, 0, 0, 641, 642, 7, 5, 0, 0, 642, 643, 7, 14, 0, 0, 643, 644, 7, 10, 0, 0, 644, 645, 7, 5, 0, 0, 645, 646, 7, 7, 0, 0, 646, 647, 7, 17, 0, 0, 647, 648, 7, 11, 0, 0, 648, 649, 7, 4, 0, 0, 649, 650, 7, 11, 0, 0, 650, 651, 7, 17, 0, 0, 651, 652, 1, 0, 0, 0, 652, 653, 6, 15, 4, 0, 653, 47, 1, 0, 0, 0, 654, 655, 4, 16, 1, 0, 655, 656, 7, 12, 0, 0, 656, 657, 7, 7, 0, 0, 657, 658, 7, 12, 0, 0, 658, 659, 7, 4, 0, 0, 659, 660, 7, 5, 0, 0, 660, 661, 7, 19, 0, 0, 661, 662, 1, 0, 0, 0, 662, 663, 6, 16, 4, 0, 663, 49, 1, 0, 0, 0, 664, 665, 4, 17, 2, 0, 665, 666, 7, 17, 0, 0, 666, 667, 7, 4, 0, 0, 667, 668, 7, 15, 0, 0, 668, 669, 7, 8, 0, 0, 669, 670, 7, 14, 0, 0, 670, 671, 7, 7, 0, 0, 671, 672, 1, 0, 0, 0, 672, 673, 6, 17, 4, 0, 673, 51, 1, 0, 0, 0, 674, 675, 7, 21, 0, 0, 675, 676, 7, 12, 0, 0, 676, 677, 7, 9, 0, 0, 677, 678, 7, 15, 0, 0, 678, 679, 1, 0, 0, 0, 679, 680, 6, 18, 5, 0, 680, 53, 1, 0, 0, 0, 681, 682, 4, 19, 3, 0, 682, 683, 7, 11, 0, 0, 683, 684, 7, 17, 0, 0, 684, 685, 1, 0, 0, 0, 685, 686, 6, 19, 5, 0, 686, 55, 1, 0, 0, 0, 687, 688, 4, 20, 4, 0, 688, 689, 7, 21, 0, 0, 689, 690, 7, 9, 0, 0, 690, 691, 7, 12, 0, 0, 691, 692, 7, 19, 0, 0, 692, 693, 1, 0, 0, 0, 693, 694, 6, 20, 6, 0, 694, 57, 1, 0, 0, 0, 695, 696, 7, 14, 0, 0, 696, 697, 7, 9, 0, 0, 697, 698, 7, 9, 0, 0, 698, 699, 7, 19, 0, 0, 699, 700, 7, 22, 0, 0, 700, 701, 7, 8, 0, 0, 701, 702, 1, 0, 0, 0, 702, 703, 6, 21, 7, 0, 703, 59, 1, 0, 0, 0, 704, 705, 4, 22, 5, 0, 705, 706, 7, 21, 0, 0, 706, 707, 7, 22, 0, 0, 707, 708, 7, 14, 0, 0, 708, 709, 7, 14, 0, 0, 709, 710, 1, 0, 0, 0, 710, 711, 6, 22, 7, 0, 711, 61, 1, 0, 0, 0, 712, 713, 4, 23, 6, 0, 713, 714, 7, 14, 0, 0, 714, 715, 7, 7, 0, 0, 715, 716, 7, 21, 0, 0, 716, 717, 7, 11, 0, 0, 717, 718, 1, 0, 0, 0, 718, 719, 6, 23, 7, 0, 719, 63, 1, 0, 0, 0, 720, 721, 4, 24, 7, 0, 721, 722, 7, 12, 0, 0, 722, 723, 7, 10, 0, 0, 723, 724, 7, 6, 0, 0, 724, 725, 7, 3, 0, 0, 725, 726, 7, 11, 0, 0, 726, 727, 1, 0, 0, 0, 727, 728, 6, 24, 7, 0, 728, 65, 1, 0, 0, 0, 729, 730, 4, 25, 8, 0, 730, 731, 7, 14, 0, 0, 731, 732, 7, 9, 0, 0, 732, 733, 7, 9, 0, 0, 733, 734, 7, 19, 0, 0, 734, 735, 7, 22, 0, 0, 735, 736, 7, 8, 0, 0, 736, 737, 5, 95, 0, 0, 737, 738, 5, 128020, 0, 0, 738, 739, 1, 0, 0, 0, 739, 740, 6, 25, 8, 0, 740, 67, 1, 0, 0, 0, 741, 742, 7, 15, 0, 0, 742, 743, 7, 18, 0, 0, 743, 744, 5, 95, 0, 0, 744, 745, 7, 7, 0, 0, 745, 746, 7, 13, 0, 0, 746, 747, 7, 8, 0, 0, 747, 748, 7, 4, 0, 0, 748, 749, 7, 5, 0, 0, 749, 750, 7, 16, 0, 0, 750, 751, 1, 0, 0, 0, 751, 752, 6, 26, 9, 0, 752, 69, 1, 0, 0, 0, 753, 754, 7, 16, 0, 0, 754, 755, 7, 12, 0, 0, 755, 756, 7, 9, 0, 0, 756, 757, 7, 8, 0, 0, 757, 758, 1, 0, 0, 0, 758, 759, 6, 27, 10, 0, 759, 71, 1, 0, 0, 0, 760, 761, 7, 19, 0, 0, 761, 762, 7, 7, 0, 0, 762, 763, 7, 7, 0, 0, 763, 764, 7, 8, 0, 0, 764, 765, 1, 0, 0, 0, 765, 766, 6, 28, 10, 0, 766, 73, 1, 0, 0, 0, 767, 768, 4, 29, 9, 0, 768, 769, 7, 10, 0, 0, 769, 770, 7, 5, 0, 0, 770, 771, 7, 17, 0, 0, 771, 772, 7, 10, 0, 0, 772, 773, 7, 17, 0, 0, 773, 774, 7, 11, 0, 0, 774, 775, 5, 95, 0, 0, 775, 776, 5, 128020, 0, 0, 776, 777, 1, 0, 0, 0, 777, 778, 6, 29, 10, 0, 778, 75, 1, 0, 0, 0, 779, 780, 4, 30, 10, 0, 780, 781, 7, 12, 0, 0, 781, 782, 7, 12, 0, 0, 782, 783, 7, 21, 0, 0, 783, 784, 1, 0, 0, 0, 784, 785, 6, 30, 4, 0, 785, 77, 1, 0, 0, 0, 786, 787, 7, 12, 0, 0, 787, 788, 7, 7, 0, 0, 788, 789, 7, 5, 0, 0, 789, 790, 7, 4, 0, 0, 790, 791, 7, 15, 0, 0, 791, 792, 7, 7, 0, 0, 792, 793, 1, 0, 0, 0, 793, 794, 6, 31, 11, 0, 794, 79, 1, 0, 0, 0, 795, 796, 7, 17, 0, 0, 796, 797, 7, 3, 0, 0, 797, 798, 7, 9, 0, 0, 798, 799, 7, 20, 0, 0, 799, 800, 1, 0, 0, 0, 800, 801, 6, 32, 12, 0, 801, 81, 1, 0, 0, 0, 802, 804, 8, 23, 0, 0, 803, 802, 1, 0, 0, 0, 804, 805, 1, 0, 0, 0, 805, 803, 1, 0, 0, 0, 805, 806, 1, 0, 0, 0, 806, 807, 1, 0, 0, 0, 807, 808, 6, 33, 4, 0, 808, 83, 1, 0, 0, 0, 809, 810, 3, 174, 79, 0, 810, 811, 1, 0, 0, 0, 811, 812, 6, 34, 13, 0, 812, 813, 6, 34, 14, 0, 813, 85, 1, 0, 0, 0, 814, 815, 3, 240, 112, 0, 815, 816, 1, 0, 0, 0, 816, 817, 6, 35, 15, 0, 817, 87, 1, 0, 0, 0, 818, 819, 3, 204, 94, 0, 819, 820, 1, 0, 0, 0, 820, 821, 6, 36, 16, 0, 821, 89, 1, 0, 0, 0, 822, 823, 3, 220, 102, 0, 823, 824, 1, 0, 0, 0, 824, 825, 6, 37, 17, 0, 825, 91, 1, 0, 0, 0, 826, 827, 3, 216, 100, 0, 827, 828, 1, 0, 0, 0, 828, 829, 6, 38, 18, 0, 829, 93, 1, 0, 0, 0, 830, 831, 3, 300, 142, 0, 831, 832, 1, 0, 0, 0, 832, 833, 6, 39, 19, 0, 833, 95, 1, 0, 0, 0, 834, 835, 3, 296, 140, 0, 835, 836, 1, 0, 0, 0, 836, 837, 6, 40, 20, 0, 837, 97, 1, 0, 0, 0, 838, 839, 3, 16, 0, 0, 839, 840, 1, 0, 0, 0, 840, 841, 6, 41, 0, 0, 841, 99, 1, 0, 0, 0, 842, 843, 3, 18, 1, 0, 843, 844, 1, 0, 0, 0, 844, 845, 6, 42, 0, 0, 845, 101, 1, 0, 0, 0, 846, 847, 3, 20, 2, 0, 847, 848, 1, 0, 0, 0, 848, 849, 6, 43, 0, 0, 849, 103, 1, 0, 0, 0, 850, 851, 3, 174, 79, 0, 851, 852, 1, 0, 0, 0, 852, 853, 6, 44, 13, 0, 853, 854, 6, 44, 14, 0, 854, 105, 1, 0, 0, 0, 855, 856, 3, 288, 136, 0, 856, 857, 1, 0, 0, 0, 857, 858, 6, 45, 21, 0, 858, 859, 6, 45, 22, 0, 859, 107, 1, 0, 0, 0, 860, 861, 3, 240, 112, 0, 861, 862, 1, 0, 0, 0, 862, 863, 6, 46, 15, 0, 863, 864, 6, 46, 23, 0, 864, 109, 1, 0, 0, 0, 865, 866, 3, 250, 117, 0, 866, 867, 1, 0, 0, 0, 867, 868, 6, 47, 24, 0, 868, 869, 6, 47, 23, 0, 869, 111, 1, 0, 0, 0, 870, 871, 8, 24, 0, 0, 871, 113, 1, 0, 0, 0, 872, 874, 3, 112, 48, 0, 873, 872, 1, 0, 0, 0, 874, 875, 1, 0, 0, 0, 875, 873, 1, 0, 0, 0, 875, 876, 1, 0, 0, 0, 876, 877, 1, 0, 0, 0, 877, 878, 3, 214, 99, 0, 878, 880, 1, 0, 0, 0, 879, 873, 1, 0, 0, 0, 879, 880, 1, 0, 0, 0, 880, 882, 1, 0, 0, 0, 881, 883, 3, 112, 48, 0, 882, 881, 1, 0, 0, 0, 883, 884, 1, 0, 0, 0, 884, 882, 1, 0, 0, 0, 884, 885, 1, 0, 0, 0, 885, 115, 1, 0, 0, 0, 886, 887, 3, 114, 49, 0, 887, 888, 1, 0, 0, 0, 888, 889, 6, 50, 25, 0, 889, 117, 1, 0, 0, 0, 890, 891, 3, 16, 0, 0, 891, 892, 1, 0, 0, 0, 892, 893, 6, 51, 0, 0, 893, 119, 1, 0, 0, 0, 894, 895, 3, 18, 1, 0, 895, 896, 1, 0, 0, 0, 896, 897, 6, 52, 0, 0, 897, 121, 1, 0, 0, 0, 898, 899, 3, 20, 2, 0, 899, 900, 1, 0, 0, 0, 900, 901, 6, 53, 0, 0, 901, 123, 1, 0, 0, 0, 902, 903, 3, 174, 79, 0, 903, 904, 1, 0, 0, 0, 904, 905, 6, 54, 13, 0, 905, 906, 6, 54, 14, 0, 906, 907, 6, 54, 14, 0, 907, 125, 1, 0, 0, 0, 908, 909, 3, 208, 96, 0, 909, 910, 1, 0, 0, 0, 910, 911, 6, 55, 26, 0, 911, 127, 1, 0, 0, 0, 912, 913, 3, 216, 100, 0, 913, 914, 1, 0, 0, 0, 914, 915, 6, 56, 18, 0, 915, 129, 1, 0, 0, 0, 916, 917, 3, 220, 102, 0, 917, 918, 1, 0, 0, 0, 918, 919, 6, 57, 17, 0, 919, 131, 1, 0, 0, 0, 920, 921, 3, 250, 117, 0, 921, 922, 1, 0, 0, 0, 922, 923, 6, 58, 24, 0, 923, 133, 1, 0, 0, 0, 924, 925, 3, 448, 216, 0, 925, 926, 1, 0, 0, 0, 926, 927, 6, 59, 27, 0, 927, 135, 1, 0, 0, 0, 928, 929, 3, 300, 142, 0, 929, 930, 1, 0, 0, 0, 930, 931, 6, 60, 19, 0, 931, 137, 1, 0, 0, 0, 932, 933, 3, 244, 114, 0, 933, 934, 1, 0, 0, 0, 934, 935, 6, 61, 28, 0, 935, 139, 1, 0, 0, 0, 936, 937, 3, 284, 134, 0, 937, 938, 1, 0, 0, 0, 938, 939, 6, 62, 29, 0, 939, 141, 1, 0, 0, 0, 940, 941, 3, 280, 132, 0, 941, 942, 1, 0, 0, 0, 942, 943, 6, 63, 30, 0, 943, 143, 1, 0, 0, 0, 944, 945, 3, 286, 135, 0, 945, 946, 1, 0, 0, 0, 946, 947, 6, 64, 31, 0, 947, 145, 1, 0, 0, 0, 948, 949, 3, 16, 0, 0, 949, 950, 1, 0, 0, 0, 950, 951, 6, 65, 0, 0, 951, 147, 1, 0, 0, 0, 952, 953, 3, 18, 1, 0, 953, 954, 1, 0, 0, 0, 954, 955, 6, 66, 0, 0, 955, 149, 1, 0, 0, 0, 956, 957, 3, 20, 2, 0, 957, 958, 1, 0, 0, 0, 958, 959, 6, 67, 0, 0, 959, 151, 1, 0, 0, 0, 960, 961, 3, 290, 137, 0, 961, 962, 1, 0, 0, 0, 962, 963, 6, 68, 32, 0, 963, 964, 6, 68, 14, 0, 964, 153, 1, 0, 0, 0, 965, 966, 3, 214, 99, 0, 966, 967, 1, 0, 0, 0, 967, 968, 6, 69, 33, 0, 968, 155, 1, 0, 0, 0, 969, 975, 3, 186, 85, 0, 970, 975, 3, 176, 80, 0, 971, 975, 3, 220, 102, 0, 972, 975, 3, 178, 81, 0, 973, 975, 3, 192, 88, 0, 974, 969, 1, 0, 0, 0, 974, 970, 1, 0, 0, 0, 974, 971, 1, 0, 0, 0, 974, 972, 1, 0, 0, 0, 974, 973, 1, 0, 0, 0, 975, 976, 1, 0, 0, 0, 976, 974, 1, 0, 0, 0, 976, 977, 1, 0, 0, 0, 977, 157, 1, 0, 0, 0, 978, 979, 3, 16, 0, 0, 979, 980, 1, 0, 0, 0, 980, 981, 6, 71, 0, 0, 981, 159, 1, 0, 0, 0, 982, 983, 3, 18, 1, 0, 983, 984, 1, 0, 0, 0, 984, 985, 6, 72, 0, 0, 985, 161, 1, 0, 0, 0, 986, 987, 3, 20, 2, 0, 987, 988, 1, 0, 0, 0, 988, 989, 6, 73, 0, 0, 989, 163, 1, 0, 0, 0, 990, 991, 3, 288, 136, 0, 991, 992, 1, 0, 0, 0, 992, 993, 6, 74, 21, 0, 993, 994, 6, 74, 34, 0, 994, 165, 1, 0, 0, 0, 995, 996, 3, 174, 79, 0, 996, 997, 1, 0, 0, 0, 997, 998, 6, 75, 13, 0, 998, 999, 6, 75, 14, 0, 999, 167, 1, 0, 0, 0, 1000, 1001, 3, 20, 2, 0, 1001, 1002, 1, 0, 0, 0, 1002, 1003, 6, 76, 0, 0, 1003, 169, 1, 0, 0, 0, 1004, 1005, 3, 16, 0, 0, 1005, 1006, 1, 0, 0, 0, 1006, 1007, 6, 77, 0, 0, 1007, 171, 1, 0, 0, 0, 1008, 1009, 3, 18, 1, 0, 1009, 1010, 1, 0, 0, 0, 1010, 1011, 6, 78, 0, 0, 1011, 173, 1, 0, 0, 0, 1012, 1013, 5, 124, 0, 0, 1013, 1014, 1, 0, 0, 0, 1014, 1015, 6, 79, 14, 0, 1015, 175, 1, 0, 0, 0, 1016, 1017, 7, 25, 0, 0, 1017, 177, 1, 0, 0, 0, 1018, 1019, 7, 26, 0, 0, 1019, 179, 1, 0, 0, 0, 1020, 1021, 5, 92, 0, 0, 1021, 1022, 7, 27, 0, 0, 1022, 181, 1, 0, 0, 0, 1023, 1024, 8, 28, 0, 0, 1024, 183, 1, 0, 0, 0, 1025, 1027, 7, 7, 0, 0, 1026, 1028, 7, 29, 0, 0, 1027, 1026, 1, 0, 0, 0, 1027, 1028, 1, 0, 0, 0, 1028, 1030, 1, 0, 0, 0, 1029, 1031, 3, 176, 80, 0, 1030, 1029, 1, 0, 0, 0, 1031, 1032, 1, 0, 0, 0, 1032, 1030, 1, 0, 0, 0, 1032, 1033, 1, 0, 0, 0, 1033, 185, 1, 0, 0, 0, 1034, 1035, 5, 64, 0, 0, 1035, 187, 1, 0, 0, 0, 1036, 1037, 5, 96, 0, 0, 1037, 189, 1, 0, 0, 0, 1038, 1042, 8, 30, 0, 0, 1039, 1040, 5, 96, 0, 0, 1040, 1042, 5, 96, 0, 0, 1041, 1038, 1, 0, 0, 0, 1041, 1039, 1, 0, 0, 0, 1042, 191, 1, 0, 0, 0, 1043, 1044, 5, 95, 0, 0, 1044, 193, 1, 0, 0, 0, 1045, 1049, 3, 178, 81, 0, 1046, 1049, 3, 176, 80, 0, 1047, 1049, 3, 192, 88, 0, 1048, 1045, 1, 0, 0, 0, 1048, 1046, 1, 0, 0, 0, 1048, 1047, 1, 0, 0, 0, 1049, 195, 1, 0, 0, 0, 1050, 1055, 5, 34, 0, 0, 1051, 1054, 3, 180, 82, 0, 1052, 1054, 3, 182, 83, 0, 1053, 1051, 1, 0, 0, 0, 1053, 1052, 1, 0, 0, 0, 1054, 1057, 1, 0, 0, 0, 1055, 1053, 1, 0, 0, 0, 1055, 1056, 1, 0, 0, 0, 1056, 1058, 1, 0, 0, 0, 1057, 1055, 1, 0, 0, 0, 1058, 1080, 5, 34, 0, 0, 1059, 1060, 5, 34, 0, 0, 1060, 1061, 5, 34, 0, 0, 1061, 1062, 5, 34, 0, 0, 1062, 1066, 1, 0, 0, 0, 1063, 1065, 8, 0, 0, 0, 1064, 1063, 1, 0, 0, 0, 1065, 1068, 1, 0, 0, 0, 1066, 1067, 1, 0, 0, 0, 1066, 1064, 1, 0, 0, 0, 1067, 1069, 1, 0, 0, 0, 1068, 1066, 1, 0, 0, 0, 1069, 1070, 5, 34, 0, 0, 1070, 1071, 5, 34, 0, 0, 1071, 1072, 5, 34, 0, 0, 1072, 1074, 1, 0, 0, 0, 1073, 1075, 5, 34, 0, 0, 1074, 1073, 1, 0, 0, 0, 1074, 1075, 1, 0, 0, 0, 1075, 1077, 1, 0, 0, 0, 1076, 1078, 5, 34, 0, 0, 1077, 1076, 1, 0, 0, 0, 1077, 1078, 1, 0, 0, 0, 1078, 1080, 1, 0, 0, 0, 1079, 1050, 1, 0, 0, 0, 1079, 1059, 1, 0, 0, 0, 1080, 197, 1, 0, 0, 0, 1081, 1083, 3, 176, 80, 0, 1082, 1081, 1, 0, 0, 0, 1083, 1084, 1, 0, 0, 0, 1084, 1082, 1, 0, 0, 0, 1084, 1085, 1, 0, 0, 0, 1085, 199, 1, 0, 0, 0, 1086, 1088, 3, 176, 80, 0, 1087, 1086, 1, 0, 0, 0, 1088, 1089, 1, 0, 0, 0, 1089, 1087, 1, 0, 0, 0, 1089, 1090, 1, 0, 0, 0, 1090, 1091, 1, 0, 0, 0, 1091, 1095, 3, 220, 102, 0, 1092, 1094, 3, 176, 80, 0, 1093, 1092, 1, 0, 0, 0, 1094, 1097, 1, 0, 0, 0, 1095, 1093, 1, 0, 0, 0, 1095, 1096, 1, 0, 0, 0, 1096, 1129, 1, 0, 0, 0, 1097, 1095, 1, 0, 0, 0, 1098, 1100, 3, 220, 102, 0, 1099, 1101, 3, 176, 80, 0, 1100, 1099, 1, 0, 0, 0, 1101, 1102, 1, 0, 0, 0, 1102, 1100, 1, 0, 0, 0, 1102, 1103, 1, 0, 0, 0, 1103, 1129, 1, 0, 0, 0, 1104, 1106, 3, 176, 80, 0, 1105, 1104, 1, 0, 0, 0, 1106, 1107, 1, 0, 0, 0, 1107, 1105, 1, 0, 0, 0, 1107, 1108, 1, 0, 0, 0, 1108, 1116, 1, 0, 0, 0, 1109, 1113, 3, 220, 102, 0, 1110, 1112, 3, 176, 80, 0, 1111, 1110, 1, 0, 0, 0, 1112, 1115, 1, 0, 0, 0, 1113, 1111, 1, 0, 0, 0, 1113, 1114, 1, 0, 0, 0, 1114, 1117, 1, 0, 0, 0, 1115, 1113, 1, 0, 0, 0, 1116, 1109, 1, 0, 0, 0, 1116, 1117, 1, 0, 0, 0, 1117, 1118, 1, 0, 0, 0, 1118, 1119, 3, 184, 84, 0, 1119, 1129, 1, 0, 0, 0, 1120, 1122, 3, 220, 102, 0, 1121, 1123, 3, 176, 80, 0, 1122, 1121, 1, 0, 0, 0, 1123, 1124, 1, 0, 0, 0, 1124, 1122, 1, 0, 0, 0, 1124, 1125, 1, 0, 0, 0, 1125, 1126, 1, 0, 0, 0, 1126, 1127, 3, 184, 84, 0, 1127, 1129, 1, 0, 0, 0, 1128, 1087, 1, 0, 0, 0, 1128, 1098, 1, 0, 0, 0, 1128, 1105, 1, 0, 0, 0, 1128, 1120, 1, 0, 0, 0, 1129, 201, 1, 0, 0, 0, 1130, 1131, 7, 4, 0, 0, 1131, 1132, 7, 5, 0, 0, 1132, 1133, 7, 16, 0, 0, 1133, 203, 1, 0, 0, 0, 1134, 1135, 7, 4, 0, 0, 1135, 1136, 7, 17, 0, 0, 1136, 205, 1, 0, 0, 0, 1137, 1138, 7, 4, 0, 0, 1138, 1139, 7, 17, 0, 0, 1139, 1140, 7, 2, 0, 0, 1140, 207, 1, 0, 0, 0, 1141, 1142, 5, 61, 0, 0, 1142, 209, 1, 0, 0, 0, 1143, 1144, 7, 31, 0, 0, 1144, 1145, 7, 32, 0, 0, 1145, 211, 1, 0, 0, 0, 1146, 1147, 5, 58, 0, 0, 1147, 1148, 5, 58, 0, 0, 1148, 213, 1, 0, 0, 0, 1149, 1150, 5, 58, 0, 0, 1150, 215, 1, 0, 0, 0, 1151, 1152, 5, 44, 0, 0, 1152, 217, 1, 0, 0, 0, 1153, 1154, 7, 16, 0, 0, 1154, 1155, 7, 7, 0, 0, 1155, 1156, 7, 17, 0, 0, 1156, 1157, 7, 2, 0, 0, 1157, 219, 1, 0, 0, 0, 1158, 1159, 5, 46, 0, 0, 1159, 221, 1, 0, 0, 0, 1160, 1161, 7, 21, 0, 0, 1161, 1162, 7, 4, 0, 0, 1162, 1163, 7, 14, 0, 0, 1163, 1164, 7, 17, 0, 0, 1164, 1165, 7, 7, 0, 0, 1165, 223, 1, 0, 0, 0, 1166, 1167, 7, 21, 0, 0, 1167, 1168, 7, 10, 0, 0, 1168, 1169, 7, 12, 0, 0, 1169, 1170, 7, 17, 0, 0, 1170, 1171, 7, 11, 0, 0, 1171, 225, 1, 0, 0, 0, 1172, 1173, 7, 10, 0, 0, 1173, 1174, 7, 5, 0, 0, 1174, 227, 1, 0, 0, 0, 1175, 1176, 7, 10, 0, 0, 1176, 1177, 7, 17, 0, 0, 1177, 229, 1, 0, 0, 0, 1178, 1179, 7, 14, 0, 0, 1179, 1180, 7, 4, 0, 0, 1180, 1181, 7, 17, 0, 0, 1181, 1182, 7, 11, 0, 0, 1182, 231, 1, 0, 0, 0, 1183, 1184, 7, 14, 0, 0, 1184, 1185, 7, 10, 0, 0, 1185, 1186, 7, 19, 0, 0, 1186, 1187, 7, 7, 0, 0, 1187, 233, 1, 0, 0, 0, 1188, 1189, 7, 5, 0, 0, 1189, 1190, 7, 9, 0, 0, 1190, 1191, 7, 11, 0, 0, 1191, 235, 1, 0, 0, 0, 1192, 1193, 7, 5, 0, 0, 1193, 1194, 7, 22, 0, 0, 1194, 1195, 7, 14, 0, 0, 1195, 1196, 7, 14, 0, 0, 1196, 237, 1, 0, 0, 0, 1197, 1198, 7, 5, 0, 0, 1198, 1199, 7, 22, 0, 0, 1199, 1200, 7, 14, 0, 0, 1200, 1201, 7, 14, 0, 0, 1201, 1202, 7, 17, 0, 0, 1202, 239, 1, 0, 0, 0, 1203, 1204, 7, 9, 0, 0, 1204, 1205, 7, 5, 0, 0, 1205, 241, 1, 0, 0, 0, 1206, 1207, 7, 9, 0, 0, 1207, 1208, 7, 12, 0, 0, 1208, 243, 1, 0, 0, 0, 1209, 1210, 5, 63, 0, 0, 1210, 245, 1, 0, 0, 0, 1211, 1212, 7, 12, 0, 0, 1212, 1213, 7, 14, 0, 0, 1213, 1214, 7, 10, 0, 0, 1214, 1215, 7, 19, 0, 0, 1215, 1216, 7, 7, 0, 0, 1216, 247, 1, 0, 0, 0, 1217, 1218, 7, 11, 0, 0, 1218, 1219, 7, 12, 0, 0, 1219, 1220, 7, 22, 0, 0, 1220, 1221, 7, 7, 0, 0, 1221, 249, 1, 0, 0, 0, 1222, 1223, 7, 20, 0, 0, 1223, 1224, 7, 10, 0, 0, 1224, 1225, 7, 11, 0, 0, 1225, 1226, 7, 3, 0, 0, 1226, 251, 1, 0, 0, 0, 1227, 1228, 5, 61, 0, 0, 1228, 1229, 5, 61, 0, 0, 1229, 253, 1, 0, 0, 0, 1230, 1231, 5, 61, 0, 0, 1231, 1232, 5, 126, 0, 0, 1232, 255, 1, 0, 0, 0, 1233, 1234, 5, 33, 0, 0, 1234, 1235, 5, 61, 0, 0, 1235, 257, 1, 0, 0, 0, 1236, 1237, 5, 60, 0, 0, 1237, 259, 1, 0, 0, 0, 1238, 1239, 5, 60, 0, 0, 1239, 1240, 5, 61, 0, 0, 1240, 261, 1, 0, 0, 0, 1241, 1242, 5, 62, 0, 0, 1242, 263, 1, 0, 0, 0, 1243, 1244, 5, 62, 0, 0, 1244, 1245, 5, 61, 0, 0, 1245, 265, 1, 0, 0, 0, 1246, 1247, 5, 43, 0, 0, 1247, 267, 1, 0, 0, 0, 1248, 1249, 5, 45, 0, 0, 1249, 269, 1, 0, 0, 0, 1250, 1251, 5, 42, 0, 0, 1251, 271, 1, 0, 0, 0, 1252, 1253, 5, 47, 0, 0, 1253, 273, 1, 0, 0, 0, 1254, 1255, 5, 37, 0, 0, 1255, 275, 1, 0, 0, 0, 1256, 1257, 5, 123, 0, 0, 1257, 277, 1, 0, 0, 0, 1258, 1259, 5, 125, 0, 0, 1259, 279, 1, 0, 0, 0, 1260, 1261, 5, 63, 0, 0, 1261, 1262, 5, 63, 0, 0, 1262, 281, 1, 0, 0, 0, 1263, 1264, 3, 44, 14, 0, 1264, 1265, 1, 0, 0, 0, 1265, 1266, 6, 133, 35, 0, 1266, 283, 1, 0, 0, 0, 1267, 1270, 3, 244, 114, 0, 1268, 1271, 3, 178, 81, 0, 1269, 1271, 3, 192, 88, 0, 1270, 1268, 1, 0, 0, 0, 1270, 1269, 1, 0, 0, 0, 1271, 1275, 1, 0, 0, 0, 1272, 1274, 3, 194, 89, 0, 1273, 1272, 1, 0, 0, 0, 1274, 1277, 1, 0, 0, 0, 1275, 1273, 1, 0, 0, 0, 1275, 1276, 1, 0, 0, 0, 1276, 1285, 1, 0, 0, 0, 1277, 1275, 1, 0, 0, 0, 1278, 1280, 3, 244, 114, 0, 1279, 1281, 3, 176, 80, 0, 1280, 1279, 1, 0, 0, 0, 1281, 1282, 1, 0, 0, 0, 1282, 1280, 1, 0, 0, 0, 1282, 1283, 1, 0, 0, 0, 1283, 1285, 1, 0, 0, 0, 1284, 1267, 1, 0, 0, 0, 1284, 1278, 1, 0, 0, 0, 1285, 285, 1, 0, 0, 0, 1286, 1289, 3, 280, 132, 0, 1287, 1290, 3, 178, 81, 0, 1288, 1290, 3, 192, 88, 0, 1289, 1287, 1, 0, 0, 0, 1289, 1288, 1, 0, 0, 0, 1290, 1294, 1, 0, 0, 0, 1291, 1293, 3, 194, 89, 0, 1292, 1291, 1, 0, 0, 0, 1293, 1296, 1, 0, 0, 0, 1294, 1292, 1, 0, 0, 0, 1294, 1295, 1, 0, 0, 0, 1295, 1304, 1, 0, 0, 0, 1296, 1294, 1, 0, 0, 0, 1297, 1299, 3, 280, 132, 0, 1298, 1300, 3, 176, 80, 0, 1299, 1298, 1, 0, 0, 0, 1300, 1301, 1, 0, 0, 0, 1301, 1299, 1, 0, 0, 0, 1301, 1302, 1, 0, 0, 0, 1302, 1304, 1, 0, 0, 0, 1303, 1286, 1, 0, 0, 0, 1303, 1297, 1, 0, 0, 0, 1304, 287, 1, 0, 0, 0, 1305, 1306, 5, 91, 0, 0, 1306, 1307, 1, 0, 0, 0, 1307, 1308, 6, 136, 4, 0, 1308, 1309, 6, 136, 4, 0, 1309, 289, 1, 0, 0, 0, 1310, 1311, 5, 93, 0, 0, 1311, 1312, 1, 0, 0, 0, 1312, 1313, 6, 137, 14, 0, 1313, 1314, 6, 137, 14, 0, 1314, 291, 1, 0, 0, 0, 1315, 1316, 5, 40, 0, 0, 1316, 1317, 1, 0, 0, 0, 1317, 1318, 6, 138, 4, 0, 1318, 1319, 6, 138, 4, 0, 1319, 293, 1, 0, 0, 0, 1320, 1321, 5, 41, 0, 0, 1321, 1322, 1, 0, 0, 0, 1322, 1323, 6, 139, 14, 0, 1323, 1324, 6, 139, 14, 0, 1324, 295, 1, 0, 0, 0, 1325, 1329, 3, 178, 81, 0, 1326, 1328, 3, 194, 89, 0, 1327, 1326, 1, 0, 0, 0, 1328, 1331, 1, 0, 0, 0, 1329, 1327, 1, 0, 0, 0, 1329, 1330, 1, 0, 0, 0, 1330, 1342, 1, 0, 0, 0, 1331, 1329, 1, 0, 0, 0, 1332, 1335, 3, 192, 88, 0, 1333, 1335, 3, 186, 85, 0, 1334, 1332, 1, 0, 0, 0, 1334, 1333, 1, 0, 0, 0, 1335, 1337, 1, 0, 0, 0, 1336, 1338, 3, 194, 89, 0, 1337, 1336, 1, 0, 0, 0, 1338, 1339, 1, 0, 0, 0, 1339, 1337, 1, 0, 0, 0, 1339, 1340, 1, 0, 0, 0, 1340, 1342, 1, 0, 0, 0, 1341, 1325, 1, 0, 0, 0, 1341, 1334, 1, 0, 0, 0, 1342, 297, 1, 0, 0, 0, 1343, 1345, 3, 188, 86, 0, 1344, 1346, 3, 190, 87, 0, 1345, 1344, 1, 0, 0, 0, 1346, 1347, 1, 0, 0, 0, 1347, 1345, 1, 0, 0, 0, 1347, 1348, 1, 0, 0, 0, 1348, 1349, 1, 0, 0, 0, 1349, 1350, 3, 188, 86, 0, 1350, 299, 1, 0, 0, 0, 1351, 1352, 3, 298, 141, 0, 1352, 301, 1, 0, 0, 0, 1353, 1354, 3, 16, 0, 0, 1354, 1355, 1, 0, 0, 0, 1355, 1356, 6, 143, 0, 0, 1356, 303, 1, 0, 0, 0, 1357, 1358, 3, 18, 1, 0, 1358, 1359, 1, 0, 0, 0, 1359, 1360, 6, 144, 0, 0, 1360, 305, 1, 0, 0, 0, 1361, 1362, 3, 20, 2, 0, 1362, 1363, 1, 0, 0, 0, 1363, 1364, 6, 145, 0, 0, 1364, 307, 1, 0, 0, 0, 1365, 1366, 3, 174, 79, 0, 1366, 1367, 1, 0, 0, 0, 1367, 1368, 6, 146, 13, 0, 1368, 1369, 6, 146, 14, 0, 1369, 309, 1, 0, 0, 0, 1370, 1371, 3, 288, 136, 0, 1371, 1372, 1, 0, 0, 0, 1372, 1373, 6, 147, 21, 0, 1373, 311, 1, 0, 0, 0, 1374, 1375, 3, 290, 137, 0, 1375, 1376, 1, 0, 0, 0, 1376, 1377, 6, 148, 32, 0, 1377, 313, 1, 0, 0, 0, 1378, 1379, 3, 214, 99, 0, 1379, 1380, 1, 0, 0, 0, 1380, 1381, 6, 149, 33, 0, 1381, 315, 1, 0, 0, 0, 1382, 1383, 3, 212, 98, 0, 1383, 1384, 1, 0, 0, 0, 1384, 1385, 6, 150, 36, 0, 1385, 317, 1, 0, 0, 0, 1386, 1387, 3, 216, 100, 0, 1387, 1388, 1, 0, 0, 0, 1388, 1389, 6, 151, 18, 0, 1389, 319, 1, 0, 0, 0, 1390, 1391, 3, 208, 96, 0, 1391, 1392, 1, 0, 0, 0, 1392, 1393, 6, 152, 26, 0, 1393, 321, 1, 0, 0, 0, 1394, 1395, 7, 15, 0, 0, 1395, 1396, 7, 7, 0, 0, 1396, 1397, 7, 11, 0, 0, 1397, 1398, 7, 4, 0, 0, 1398, 1399, 7, 16, 0, 0, 1399, 1400, 7, 4, 0, 0, 1400, 1401, 7, 11, 0, 0, 1401, 1402, 7, 4, 0, 0, 1402, 323, 1, 0, 0, 0, 1403, 1407, 8, 33, 0, 0, 1404, 1405, 5, 47, 0, 0, 1405, 1407, 8, 34, 0, 0, 1406, 1403, 1, 0, 0, 0, 1406, 1404, 1, 0, 0, 0, 1407, 325, 1, 0, 0, 0, 1408, 1410, 3, 324, 154, 0, 1409, 1408, 1, 0, 0, 0, 1410, 1411, 1, 0, 0, 0, 1411, 1409, 1, 0, 0, 0, 1411, 1412, 1, 0, 0, 0, 1412, 327, 1, 0, 0, 0, 1413, 1414, 3, 326, 155, 0, 1414, 1415, 1, 0, 0, 0, 1415, 1416, 6, 156, 37, 0, 1416, 329, 1, 0, 0, 0, 1417, 1418, 3, 196, 90, 0, 1418, 1419, 1, 0, 0, 0, 1419, 1420, 6, 157, 38, 0, 1420, 331, 1, 0, 0, 0, 1421, 1422, 3, 16, 0, 0, 1422, 1423, 1, 0, 0, 0, 1423, 1424, 6, 158, 0, 0, 1424, 333, 1, 0, 0, 0, 1425, 1426, 3, 18, 1, 0, 1426, 1427, 1, 0, 0, 0, 1427, 1428, 6, 159, 0, 0, 1428, 335, 1, 0, 0, 0, 1429, 1430, 3, 20, 2, 0, 1430, 1431, 1, 0, 0, 0, 1431, 1432, 6, 160, 0, 0, 1432, 337, 1, 0, 0, 0, 1433, 1434, 3, 292, 138, 0, 1434, 1435, 1, 0, 0, 0, 1435, 1436, 6, 161, 39, 0, 1436, 1437, 6, 161, 34, 0, 1437, 339, 1, 0, 0, 0, 1438, 1439, 3, 174, 79, 0, 1439, 1440, 1, 0, 0, 0, 1440, 1441, 6, 162, 13, 0, 1441, 1442, 6, 162, 14, 0, 1442, 341, 1, 0, 0, 0, 1443, 1444, 3, 20, 2, 0, 1444, 1445, 1, 0, 0, 0, 1445, 1446, 6, 163, 0, 0, 1446, 343, 1, 0, 0, 0, 1447, 1448, 3, 16, 0, 0, 1448, 1449, 1, 0, 0, 0, 1449, 1450, 6, 164, 0, 0, 1450, 345, 1, 0, 0, 0, 1451, 1452, 3, 18, 1, 0, 1452, 1453, 1, 0, 0, 0, 1453, 1454, 6, 165, 0, 0, 1454, 347, 1, 0, 0, 0, 1455, 1456, 3, 174, 79, 0, 1456, 1457, 1, 0, 0, 0, 1457, 1458, 6, 166, 13, 0, 1458, 1459, 6, 166, 14, 0, 1459, 349, 1, 0, 0, 0, 1460, 1461, 7, 35, 0, 0, 1461, 1462, 7, 9, 0, 0, 1462, 1463, 7, 10, 0, 0, 1463, 1464, 7, 5, 0, 0, 1464, 351, 1, 0, 0, 0, 1465, 1466, 3, 204, 94, 0, 1466, 1467, 1, 0, 0, 0, 1467, 1468, 6, 168, 16, 0, 1468, 353, 1, 0, 0, 0, 1469, 1470, 3, 240, 112, 0, 1470, 1471, 1, 0, 0, 0, 1471, 1472, 6, 169, 15, 0, 1472, 1473, 6, 169, 14, 0, 1473, 1474, 6, 169, 4, 0, 1474, 355, 1, 0, 0, 0, 1475, 1476, 7, 22, 0, 0, 1476, 1477, 7, 17, 0, 0, 1477, 1478, 7, 10, 0, 0, 1478, 1479, 7, 5, 0, 0, 1479, 1480, 7, 6, 0, 0, 1480, 1481, 1, 0, 0, 0, 1481, 1482, 6, 170, 14, 0, 1482, 1483, 6, 170, 4, 0, 1483, 357, 1, 0, 0, 0, 1484, 1485, 3, 326, 155, 0, 1485, 1486, 1, 0, 0, 0, 1486, 1487, 6, 171, 37, 0, 1487, 359, 1, 0, 0, 0, 1488, 1489, 3, 196, 90, 0, 1489, 1490, 1, 0, 0, 0, 1490, 1491, 6, 172, 38, 0, 1491, 361, 1, 0, 0, 0, 1492, 1493, 3, 214, 99, 0, 1493, 1494, 1, 0, 0, 0, 1494, 1495, 6, 173, 33, 0, 1495, 363, 1, 0, 0, 0, 1496, 1497, 3, 296, 140, 0, 1497, 1498, 1, 0, 0, 0, 1498, 1499, 6, 174, 20, 0, 1499, 365, 1, 0, 0, 0, 1500, 1501, 3, 300, 142, 0, 1501, 1502, 1, 0, 0, 0, 1502, 1503, 6, 175, 19, 0, 1503, 367, 1, 0, 0, 0, 1504, 1505, 3, 16, 0, 0, 1505, 1506, 1, 0, 0, 0, 1506, 1507, 6, 176, 0, 0, 1507, 369, 1, 0, 0, 0, 1508, 1509, 3, 18, 1, 0, 1509, 1510, 1, 0, 0, 0, 1510, 1511, 6, 177, 0, 0, 1511, 371, 1, 0, 0, 0, 1512, 1513, 3, 20, 2, 0, 1513, 1514, 1, 0, 0, 0, 1514, 1515, 6, 178, 0, 0, 1515, 373, 1, 0, 0, 0, 1516, 1517, 3, 174, 79, 0, 1517, 1518, 1, 0, 0, 0, 1518, 1519, 6, 179, 13, 0, 1519, 1520, 6, 179, 14, 0, 1520, 375, 1, 0, 0, 0, 1521, 1522, 3, 214, 99, 0, 1522, 1523, 1, 0, 0, 0, 1523, 1524, 6, 180, 33, 0, 1524, 377, 1, 0, 0, 0, 1525, 1526, 3, 216, 100, 0, 1526, 1527, 1, 0, 0, 0, 1527, 1528, 6, 181, 18, 0, 1528, 379, 1, 0, 0, 0, 1529, 1530, 3, 220, 102, 0, 1530, 1531, 1, 0, 0, 0, 1531, 1532, 6, 182, 17, 0, 1532, 381, 1, 0, 0, 0, 1533, 1534, 3, 240, 112, 0, 1534, 1535, 1, 0, 0, 0, 1535, 1536, 6, 183, 15, 0, 1536, 1537, 6, 183, 40, 0, 1537, 383, 1, 0, 0, 0, 1538, 1539, 3, 326, 155, 0, 1539, 1540, 1, 0, 0, 0, 1540, 1541, 6, 184, 37, 0, 1541, 385, 1, 0, 0, 0, 1542, 1543, 3, 196, 90, 0, 1543, 1544, 1, 0, 0, 0, 1544, 1545, 6, 185, 38, 0, 1545, 387, 1, 0, 0, 0, 1546, 1547, 3, 16, 0, 0, 1547, 1548, 1, 0, 0, 0, 1548, 1549, 6, 186, 0, 0, 1549, 389, 1, 0, 0, 0, 1550, 1551, 3, 18, 1, 0, 1551, 1552, 1, 0, 0, 0, 1552, 1553, 6, 187, 0, 0, 1553, 391, 1, 0, 0, 0, 1554, 1555, 3, 20, 2, 0, 1555, 1556, 1, 0, 0, 0, 1556, 1557, 6, 188, 0, 0, 1557, 393, 1, 0, 0, 0, 1558, 1559, 3, 174, 79, 0, 1559, 1560, 1, 0, 0, 0, 1560, 1561, 6, 189, 13, 0, 1561, 1562, 6, 189, 14, 0, 1562, 1563, 6, 189, 14, 0, 1563, 395, 1, 0, 0, 0, 1564, 1565, 3, 216, 100, 0, 1565, 1566, 1, 0, 0, 0, 1566, 1567, 6, 190, 18, 0, 1567, 397, 1, 0, 0, 0, 1568, 1569, 3, 220, 102, 0, 1569, 1570, 1, 0, 0, 0, 1570, 1571, 6, 191, 17, 0, 1571, 399, 1, 0, 0, 0, 1572, 1573, 3, 448, 216, 0, 1573, 1574, 1, 0, 0, 0, 1574, 1575, 6, 192, 27, 0, 1575, 401, 1, 0, 0, 0, 1576, 1577, 3, 16, 0, 0, 1577, 1578, 1, 0, 0, 0, 1578, 1579, 6, 193, 0, 0, 1579, 403, 1, 0, 0, 0, 1580, 1581, 3, 18, 1, 0, 1581, 1582, 1, 0, 0, 0, 1582, 1583, 6, 194, 0, 0, 1583, 405, 1, 0, 0, 0, 1584, 1585, 3, 20, 2, 0, 1585, 1586, 1, 0, 0, 0, 1586, 1587, 6, 195, 0, 0, 1587, 407, 1, 0, 0, 0, 1588, 1589, 3, 174, 79, 0, 1589, 1590, 1, 0, 0, 0, 1590, 1591, 6, 196, 13, 0, 1591, 1592, 6, 196, 14, 0, 1592, 409, 1, 0, 0, 0, 1593, 1594, 3, 220, 102, 0, 1594, 1595, 1, 0, 0, 0, 1595, 1596, 6, 197, 17, 0, 1596, 411, 1, 0, 0, 0, 1597, 1598, 3, 244, 114, 0, 1598, 1599, 1, 0, 0, 0, 1599, 1600, 6, 198, 28, 0, 1600, 413, 1, 0, 0, 0, 1601, 1602, 3, 284, 134, 0, 1602, 1603, 1, 0, 0, 0, 1603, 1604, 6, 199, 29, 0, 1604, 415, 1, 0, 0, 0, 1605, 1606, 3, 280, 132, 0, 1606, 1607, 1, 0, 0, 0, 1607, 1608, 6, 200, 30, 0, 1608, 417, 1, 0, 0, 0, 1609, 1610, 3, 286, 135, 0, 1610, 1611, 1, 0, 0, 0, 1611, 1612, 6, 201, 31, 0, 1612, 419, 1, 0, 0, 0, 1613, 1614, 3, 300, 142, 0, 1614, 1615, 1, 0, 0, 0, 1615, 1616, 6, 202, 19, 0, 1616, 421, 1, 0, 0, 0, 1617, 1618, 3, 296, 140, 0, 1618, 1619, 1, 0, 0, 0, 1619, 1620, 6, 203, 20, 0, 1620, 423, 1, 0, 0, 0, 1621, 1622, 3, 16, 0, 0, 1622, 1623, 1, 0, 0, 0, 1623, 1624, 6, 204, 0, 0, 1624, 425, 1, 0, 0, 0, 1625, 1626, 3, 18, 1, 0, 1626, 1627, 1, 0, 0, 0, 1627, 1628, 6, 205, 0, 0, 1628, 427, 1, 0, 0, 0, 1629, 1630, 3, 20, 2, 0, 1630, 1631, 1, 0, 0, 0, 1631, 1632, 6, 206, 0, 0, 1632, 429, 1, 0, 0, 0, 1633, 1634, 3, 174, 79, 0, 1634, 1635, 1, 0, 0, 0, 1635, 1636, 6, 207, 13, 0, 1636, 1637, 6, 207, 14, 0, 1637, 431, 1, 0, 0, 0, 1638, 1639, 3, 220, 102, 0, 1639, 1640, 1, 0, 0, 0, 1640, 1641, 6, 208, 17, 0, 1641, 433, 1, 0, 0, 0, 1642, 1643, 3, 216, 100, 0, 1643, 1644, 1, 0, 0, 0, 1644, 1645, 6, 209, 18, 0, 1645, 435, 1, 0, 0, 0, 1646, 1647, 3, 244, 114, 0, 1647, 1648, 1, 0, 0, 0, 1648, 1649, 6, 210, 28, 0, 1649, 437, 1, 0, 0, 0, 1650, 1651, 3, 284, 134, 0, 1651, 1652, 1, 0, 0, 0, 1652, 1653, 6, 211, 29, 0, 1653, 439, 1, 0, 0, 0, 1654, 1655, 3, 280, 132, 0, 1655, 1656, 1, 0, 0, 0, 1656, 1657, 6, 212, 30, 0, 1657, 441, 1, 0, 0, 0, 1658, 1659, 3, 286, 135, 0, 1659, 1660, 1, 0, 0, 0, 1660, 1661, 6, 213, 31, 0, 1661, 443, 1, 0, 0, 0, 1662, 1667, 3, 178, 81, 0, 1663, 1667, 3, 176, 80, 0, 1664, 1667, 3, 192, 88, 0, 1665, 1667, 3, 270, 127, 0, 1666, 1662, 1, 0, 0, 0, 1666, 1663, 1, 0, 0, 0, 1666, 1664, 1, 0, 0, 0, 1666, 1665, 1, 0, 0, 0, 1667, 445, 1, 0, 0, 0, 1668, 1671, 3, 178, 81, 0, 1669, 1671, 3, 270, 127, 0, 1670, 1668, 1, 0, 0, 0, 1670, 1669, 1, 0, 0, 0, 1671, 1675, 1, 0, 0, 0, 1672, 1674, 3, 444, 214, 0, 1673, 1672, 1, 0, 0, 0, 1674, 1677, 1, 0, 0, 0, 1675, 1673, 1, 0, 0, 0, 1675, 1676, 1, 0, 0, 0, 1676, 1688, 1, 0, 0, 0, 1677, 1675, 1, 0, 0, 0, 1678, 1681, 3, 192, 88, 0, 1679, 1681, 3, 186, 85, 0, 1680, 1678, 1, 0, 0, 0, 1680, 1679, 1, 0, 0, 0, 1681, 1683, 1, 0, 0, 0, 1682, 1684, 3, 444, 214, 0, 1683, 1682, 1, 0, 0, 0, 1684, 1685, 1, 0, 0, 0, 1685, 1683, 1, 0, 0, 0, 1685, 1686, 1, 0, 0, 0, 1686, 1688, 1, 0, 0, 0, 1687, 1670, 1, 0, 0, 0, 1687, 1680, 1, 0, 0, 0, 1688, 447, 1, 0, 0, 0, 1689, 1692, 3, 446, 215, 0, 1690, 1692, 3, 298, 141, 0, 1691, 1689, 1, 0, 0, 0, 1691, 1690, 1, 0, 0, 0, 1692, 1693, 1, 0, 0, 0, 1693, 1691, 1, 0, 0, 0, 1693, 1694, 1, 0, 0, 0, 1694, 449, 1, 0, 0, 0, 1695, 1696, 3, 16, 0, 0, 1696, 1697, 1, 0, 0, 0, 1697, 1698, 6, 217, 0, 0, 1698, 451, 1, 0, 0, 0, 1699, 1700, 3, 18, 1, 0, 1700, 1701, 1, 0, 0, 0, 1701, 1702, 6, 218, 0, 0, 1702, 453, 1, 0, 0, 0, 1703, 1704, 3, 20, 2, 0, 1704, 1705, 1, 0, 0, 0, 1705, 1706, 6, 219, 0, 0, 1706, 455, 1, 0, 0, 0, 1707, 1708, 3, 174, 79, 0, 1708, 1709, 1, 0, 0, 0, 1709, 1710, 6, 220, 13, 0, 1710, 1711, 6, 220, 14, 0, 1711, 457, 1, 0, 0, 0, 1712, 1713, 3, 208, 96, 0, 1713, 1714, 1, 0, 0, 0, 1714, 1715, 6, 221, 26, 0, 1715, 459, 1, 0, 0, 0, 1716, 1717, 3, 216, 100, 0, 1717, 1718, 1, 0, 0, 0, 1718, 1719, 6, 222, 18, 0, 1719, 461, 1, 0, 0, 0, 1720, 1721, 3, 220, 102, 0, 1721, 1722, 1, 0, 0, 0, 1722, 1723, 6, 223, 17, 0, 1723, 463, 1, 0, 0, 0, 1724, 1725, 3, 244, 114, 0, 1725, 1726, 1, 0, 0, 0, 1726, 1727, 6, 224, 28, 0, 1727, 465, 1, 0, 0, 0, 1728, 1729, 3, 284, 134, 0, 1729, 1730, 1, 0, 0, 0, 1730, 1731, 6, 225, 29, 0, 1731, 467, 1, 0, 0, 0, 1732, 1733, 3, 280, 132, 0, 1733, 1734, 1, 0, 0, 0, 1734, 1735, 6, 226, 30, 0, 1735, 469, 1, 0, 0, 0, 1736, 1737, 3, 286, 135, 0, 1737, 1738, 1, 0, 0, 0, 1738, 1739, 6, 227, 31, 0, 1739, 471, 1, 0, 0, 0, 1740, 1741, 3, 204, 94, 0, 1741, 1742, 1, 0, 0, 0, 1742, 1743, 6, 228, 16, 0, 1743, 473, 1, 0, 0, 0, 1744, 1745, 3, 448, 216, 0, 1745, 1746, 1, 0, 0, 0, 1746, 1747, 6, 229, 27, 0, 1747, 475, 1, 0, 0, 0, 1748, 1749, 3, 16, 0, 0, 1749, 1750, 1, 0, 0, 0, 1750, 1751, 6, 230, 0, 0, 1751, 477, 1, 0, 0, 0, 1752, 1753, 3, 18, 1, 0, 1753, 1754, 1, 0, 0, 0, 1754, 1755, 6, 231, 0, 0, 1755, 479, 1, 0, 0, 0, 1756, 1757, 3, 20, 2, 0, 1757, 1758, 1, 0, 0, 0, 1758, 1759, 6, 232, 0, 0, 1759, 481, 1, 0, 0, 0, 1760, 1761, 3, 174, 79, 0, 1761, 1762, 1, 0, 0, 0, 1762, 1763, 6, 233, 13, 0, 1763, 1764, 6, 233, 14, 0, 1764, 483, 1, 0, 0, 0, 1765, 1766, 7, 10, 0, 0, 1766, 1767, 7, 5, 0, 0, 1767, 1768, 7, 21, 0, 0, 1768, 1769, 7, 9, 0, 0, 1769, 485, 1, 0, 0, 0, 1770, 1771, 3, 16, 0, 0, 1771, 1772, 1, 0, 0, 0, 1772, 1773, 6, 235, 0, 0, 1773, 487, 1, 0, 0, 0, 1774, 1775, 3, 18, 1, 0, 1775, 1776, 1, 0, 0, 0, 1776, 1777, 6, 236, 0, 0, 1777, 489, 1, 0, 0, 0, 1778, 1779, 3, 20, 2, 0, 1779, 1780, 1, 0, 0, 0, 1780, 1781, 6, 237, 0, 0, 1781, 491, 1, 0, 0, 0, 70, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 498, 502, 505, 514, 516, 527, 805, 875, 879, 884, 974, 976, 1027, 1032, 1041, 1048, 1053, 1055, 1066, 1074, 1077, 1079, 1084, 1089, 1095, 1102, 1107, 1113, 1116, 1124, 1128, 1270, 1275, 1282, 1284, 1289, 1294, 1301, 1303, 1329, 1334, 1339, 1341, 1347, 1406, 1411, 1666, 1670, 1675, 1680, 1685, 1687, 1691, 1693, 41, 0, 1, 0, 5, 1, 0, 5, 2, 0, 5, 5, 0, 5, 6, 0, 5, 7, 0, 5, 8, 0, 5, 9, 0, 5, 10, 0, 5, 12, 0, 5, 13, 0, 5, 14, 0, 5, 15, 0, 7, 52, 0, 4, 0, 0, 7, 75, 0, 7, 57, 0, 7, 65, 0, 7, 63, 0, 7, 103, 0, 7, 102, 0, 7, 98, 0, 5, 4, 0, 5, 3, 0, 7, 80, 0, 7, 38, 0, 7, 59, 0, 7, 129, 0, 7, 77, 0, 7, 96, 0, 7, 95, 0, 7, 97, 0, 7, 99, 0, 7, 62, 0, 5, 0, 0, 7, 15, 0, 7, 61, 0, 7, 108, 0, 7, 53, 0, 7, 100, 0, 5, 11, 0] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.java index 3c38aea898c45..302332bb649f5 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseLexer.java @@ -26,31 +26,31 @@ public class EsqlBaseLexer extends LexerConfig { new PredictionContextCache(); public static final int LINE_COMMENT=1, MULTILINE_COMMENT=2, WS=3, CHANGE_POINT=4, ENRICH=5, EXPLAIN=6, - DISSECT=7, EVAL=8, GROK=9, LIMIT=10, ROW=11, SORT=12, STATS=13, WHERE=14, - DEV_COMPLETION=15, DEV_INLINESTATS=16, DEV_RERANK=17, DEV_SAMPLE=18, FROM=19, - DEV_TIME_SERIES=20, DEV_FORK=21, JOIN_LOOKUP=22, DEV_JOIN_FULL=23, DEV_JOIN_LEFT=24, - DEV_JOIN_RIGHT=25, DEV_LOOKUP=26, MV_EXPAND=27, DROP=28, KEEP=29, DEV_INSIST=30, - DEV_RRF=31, RENAME=32, SHOW=33, UNKNOWN_CMD=34, CHANGE_POINT_LINE_COMMENT=35, - CHANGE_POINT_MULTILINE_COMMENT=36, CHANGE_POINT_WS=37, ENRICH_POLICY_NAME=38, - ENRICH_LINE_COMMENT=39, ENRICH_MULTILINE_COMMENT=40, ENRICH_WS=41, ENRICH_FIELD_LINE_COMMENT=42, - ENRICH_FIELD_MULTILINE_COMMENT=43, ENRICH_FIELD_WS=44, SETTING=45, SETTING_LINE_COMMENT=46, - SETTTING_MULTILINE_COMMENT=47, SETTING_WS=48, EXPLAIN_WS=49, EXPLAIN_LINE_COMMENT=50, - EXPLAIN_MULTILINE_COMMENT=51, PIPE=52, QUOTED_STRING=53, INTEGER_LITERAL=54, - DECIMAL_LITERAL=55, AND=56, AS=57, ASC=58, ASSIGN=59, BY=60, CAST_OP=61, - COLON=62, COMMA=63, DESC=64, DOT=65, FALSE=66, FIRST=67, IN=68, IS=69, - LAST=70, LIKE=71, NOT=72, NULL=73, NULLS=74, ON=75, OR=76, PARAM=77, RLIKE=78, - TRUE=79, WITH=80, EQ=81, CIEQ=82, NEQ=83, LT=84, LTE=85, GT=86, GTE=87, - PLUS=88, MINUS=89, ASTERISK=90, SLASH=91, PERCENT=92, LEFT_BRACES=93, - RIGHT_BRACES=94, DOUBLE_PARAMS=95, NAMED_OR_POSITIONAL_PARAM=96, NAMED_OR_POSITIONAL_DOUBLE_PARAMS=97, - OPENING_BRACKET=98, CLOSING_BRACKET=99, LP=100, RP=101, UNQUOTED_IDENTIFIER=102, - QUOTED_IDENTIFIER=103, EXPR_LINE_COMMENT=104, EXPR_MULTILINE_COMMENT=105, - EXPR_WS=106, METADATA=107, UNQUOTED_SOURCE=108, FROM_LINE_COMMENT=109, - FROM_MULTILINE_COMMENT=110, FROM_WS=111, FORK_WS=112, FORK_LINE_COMMENT=113, - FORK_MULTILINE_COMMENT=114, JOIN=115, USING=116, JOIN_LINE_COMMENT=117, - JOIN_MULTILINE_COMMENT=118, JOIN_WS=119, LOOKUP_LINE_COMMENT=120, LOOKUP_MULTILINE_COMMENT=121, - LOOKUP_WS=122, LOOKUP_FIELD_LINE_COMMENT=123, LOOKUP_FIELD_MULTILINE_COMMENT=124, - LOOKUP_FIELD_WS=125, MVEXPAND_LINE_COMMENT=126, MVEXPAND_MULTILINE_COMMENT=127, - MVEXPAND_WS=128, ID_PATTERN=129, PROJECT_LINE_COMMENT=130, PROJECT_MULTILINE_COMMENT=131, + COMPLETION=7, DISSECT=8, EVAL=9, GROK=10, LIMIT=11, ROW=12, SORT=13, STATS=14, + WHERE=15, DEV_INLINESTATS=16, DEV_RERANK=17, DEV_SAMPLE=18, FROM=19, DEV_TIME_SERIES=20, + DEV_FORK=21, JOIN_LOOKUP=22, DEV_JOIN_FULL=23, DEV_JOIN_LEFT=24, DEV_JOIN_RIGHT=25, + DEV_LOOKUP=26, MV_EXPAND=27, DROP=28, KEEP=29, DEV_INSIST=30, DEV_RRF=31, + RENAME=32, SHOW=33, UNKNOWN_CMD=34, CHANGE_POINT_LINE_COMMENT=35, CHANGE_POINT_MULTILINE_COMMENT=36, + CHANGE_POINT_WS=37, ENRICH_POLICY_NAME=38, ENRICH_LINE_COMMENT=39, ENRICH_MULTILINE_COMMENT=40, + ENRICH_WS=41, ENRICH_FIELD_LINE_COMMENT=42, ENRICH_FIELD_MULTILINE_COMMENT=43, + ENRICH_FIELD_WS=44, SETTING=45, SETTING_LINE_COMMENT=46, SETTTING_MULTILINE_COMMENT=47, + SETTING_WS=48, EXPLAIN_WS=49, EXPLAIN_LINE_COMMENT=50, EXPLAIN_MULTILINE_COMMENT=51, + PIPE=52, QUOTED_STRING=53, INTEGER_LITERAL=54, DECIMAL_LITERAL=55, AND=56, + AS=57, ASC=58, ASSIGN=59, BY=60, CAST_OP=61, COLON=62, COMMA=63, DESC=64, + DOT=65, FALSE=66, FIRST=67, IN=68, IS=69, LAST=70, LIKE=71, NOT=72, NULL=73, + NULLS=74, ON=75, OR=76, PARAM=77, RLIKE=78, TRUE=79, WITH=80, EQ=81, CIEQ=82, + NEQ=83, LT=84, LTE=85, GT=86, GTE=87, PLUS=88, MINUS=89, ASTERISK=90, + SLASH=91, PERCENT=92, LEFT_BRACES=93, RIGHT_BRACES=94, DOUBLE_PARAMS=95, + NAMED_OR_POSITIONAL_PARAM=96, NAMED_OR_POSITIONAL_DOUBLE_PARAMS=97, OPENING_BRACKET=98, + CLOSING_BRACKET=99, LP=100, RP=101, UNQUOTED_IDENTIFIER=102, QUOTED_IDENTIFIER=103, + EXPR_LINE_COMMENT=104, EXPR_MULTILINE_COMMENT=105, EXPR_WS=106, METADATA=107, + UNQUOTED_SOURCE=108, FROM_LINE_COMMENT=109, FROM_MULTILINE_COMMENT=110, + FROM_WS=111, FORK_WS=112, FORK_LINE_COMMENT=113, FORK_MULTILINE_COMMENT=114, + JOIN=115, USING=116, JOIN_LINE_COMMENT=117, JOIN_MULTILINE_COMMENT=118, + JOIN_WS=119, LOOKUP_LINE_COMMENT=120, LOOKUP_MULTILINE_COMMENT=121, LOOKUP_WS=122, + LOOKUP_FIELD_LINE_COMMENT=123, LOOKUP_FIELD_MULTILINE_COMMENT=124, LOOKUP_FIELD_WS=125, + MVEXPAND_LINE_COMMENT=126, MVEXPAND_MULTILINE_COMMENT=127, MVEXPAND_WS=128, + ID_PATTERN=129, PROJECT_LINE_COMMENT=130, PROJECT_MULTILINE_COMMENT=131, PROJECT_WS=132, RENAME_LINE_COMMENT=133, RENAME_MULTILINE_COMMENT=134, RENAME_WS=135, INFO=136, SHOW_LINE_COMMENT=137, SHOW_MULTILINE_COMMENT=138, SHOW_WS=139; @@ -73,16 +73,15 @@ public class EsqlBaseLexer extends LexerConfig { private static String[] makeRuleNames() { return new String[] { "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "CHANGE_POINT", "ENRICH", - "EXPLAIN", "DISSECT", "EVAL", "GROK", "LIMIT", "ROW", "SORT", "STATS", - "WHERE", "DEV_COMPLETION", "DEV_INLINESTATS", "DEV_RERANK", "DEV_SAMPLE", - "FROM", "DEV_TIME_SERIES", "DEV_FORK", "JOIN_LOOKUP", "DEV_JOIN_FULL", - "DEV_JOIN_LEFT", "DEV_JOIN_RIGHT", "DEV_LOOKUP", "MV_EXPAND", "DROP", - "KEEP", "DEV_INSIST", "DEV_RRF", "RENAME", "SHOW", "UNKNOWN_CMD", "CHANGE_POINT_PIPE", - "CHANGE_POINT_ON", "CHANGE_POINT_AS", "CHANGE_POINT_DOT", "CHANGE_POINT_COMMA", - "CHANGE_POINT_QUOTED_IDENTIFIER", "CHANGE_POINT_UNQUOTED_IDENTIFIER", - "CHANGE_POINT_LINE_COMMENT", "CHANGE_POINT_MULTILINE_COMMENT", "CHANGE_POINT_WS", - "ENRICH_PIPE", "ENRICH_OPENING_BRACKET", "ENRICH_ON", "ENRICH_WITH", - "ENRICH_POLICY_NAME_BODY", "ENRICH_POLICY_NAME", "ENRICH_MODE_UNQUOTED_VALUE", + "EXPLAIN", "COMPLETION", "DISSECT", "EVAL", "GROK", "LIMIT", "ROW", "SORT", + "STATS", "WHERE", "DEV_INLINESTATS", "DEV_RERANK", "DEV_SAMPLE", "FROM", + "DEV_TIME_SERIES", "DEV_FORK", "JOIN_LOOKUP", "DEV_JOIN_FULL", "DEV_JOIN_LEFT", + "DEV_JOIN_RIGHT", "DEV_LOOKUP", "MV_EXPAND", "DROP", "KEEP", "DEV_INSIST", + "DEV_RRF", "RENAME", "SHOW", "UNKNOWN_CMD", "CHANGE_POINT_PIPE", "CHANGE_POINT_ON", + "CHANGE_POINT_AS", "CHANGE_POINT_DOT", "CHANGE_POINT_COMMA", "CHANGE_POINT_QUOTED_IDENTIFIER", + "CHANGE_POINT_UNQUOTED_IDENTIFIER", "CHANGE_POINT_LINE_COMMENT", "CHANGE_POINT_MULTILINE_COMMENT", + "CHANGE_POINT_WS", "ENRICH_PIPE", "ENRICH_OPENING_BRACKET", "ENRICH_ON", + "ENRICH_WITH", "ENRICH_POLICY_NAME_BODY", "ENRICH_POLICY_NAME", "ENRICH_MODE_UNQUOTED_VALUE", "ENRICH_LINE_COMMENT", "ENRICH_MULTILINE_COMMENT", "ENRICH_WS", "ENRICH_FIELD_PIPE", "ENRICH_FIELD_ASSIGN", "ENRICH_FIELD_COMMA", "ENRICH_FIELD_DOT", "ENRICH_FIELD_WITH", "ENRICH_FIELD_ID_PATTERN", "ENRICH_FIELD_QUOTED_IDENTIFIER", "ENRICH_FIELD_PARAM", @@ -133,10 +132,10 @@ private static String[] makeRuleNames() { private static String[] makeLiteralNames() { return new String[] { - null, null, null, null, "'change_point'", "'enrich'", "'explain'", "'dissect'", - "'eval'", "'grok'", "'limit'", "'row'", "'sort'", "'stats'", "'where'", - null, null, null, null, "'from'", null, null, "'lookup'", null, null, - null, null, "'mv_expand'", "'drop'", "'keep'", null, null, "'rename'", + null, null, null, null, "'change_point'", "'enrich'", "'explain'", "'completion'", + "'dissect'", "'eval'", "'grok'", "'limit'", "'row'", "'sort'", "'stats'", + "'where'", null, null, null, "'from'", null, null, "'lookup'", null, + null, null, null, "'mv_expand'", "'drop'", "'keep'", null, null, "'rename'", "'show'", null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "'|'", null, null, null, "'and'", "'as'", "'asc'", "'='", "'by'", "'::'", "':'", "','", "'desc'", @@ -154,11 +153,11 @@ private static String[] makeLiteralNames() { private static String[] makeSymbolicNames() { return new String[] { null, "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "CHANGE_POINT", "ENRICH", - "EXPLAIN", "DISSECT", "EVAL", "GROK", "LIMIT", "ROW", "SORT", "STATS", - "WHERE", "DEV_COMPLETION", "DEV_INLINESTATS", "DEV_RERANK", "DEV_SAMPLE", - "FROM", "DEV_TIME_SERIES", "DEV_FORK", "JOIN_LOOKUP", "DEV_JOIN_FULL", - "DEV_JOIN_LEFT", "DEV_JOIN_RIGHT", "DEV_LOOKUP", "MV_EXPAND", "DROP", - "KEEP", "DEV_INSIST", "DEV_RRF", "RENAME", "SHOW", "UNKNOWN_CMD", "CHANGE_POINT_LINE_COMMENT", + "EXPLAIN", "COMPLETION", "DISSECT", "EVAL", "GROK", "LIMIT", "ROW", "SORT", + "STATS", "WHERE", "DEV_INLINESTATS", "DEV_RERANK", "DEV_SAMPLE", "FROM", + "DEV_TIME_SERIES", "DEV_FORK", "JOIN_LOOKUP", "DEV_JOIN_FULL", "DEV_JOIN_LEFT", + "DEV_JOIN_RIGHT", "DEV_LOOKUP", "MV_EXPAND", "DROP", "KEEP", "DEV_INSIST", + "DEV_RRF", "RENAME", "SHOW", "UNKNOWN_CMD", "CHANGE_POINT_LINE_COMMENT", "CHANGE_POINT_MULTILINE_COMMENT", "CHANGE_POINT_WS", "ENRICH_POLICY_NAME", "ENRICH_LINE_COMMENT", "ENRICH_MULTILINE_COMMENT", "ENRICH_WS", "ENRICH_FIELD_LINE_COMMENT", "ENRICH_FIELD_MULTILINE_COMMENT", "ENRICH_FIELD_WS", "SETTING", "SETTING_LINE_COMMENT", @@ -244,8 +243,6 @@ public EsqlBaseLexer(CharStream input) { @Override public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) { switch (ruleIndex) { - case 14: - return DEV_COMPLETION_sempred((RuleContext)_localctx, predIndex); case 15: return DEV_INLINESTATS_sempred((RuleContext)_localctx, predIndex); case 16: @@ -271,93 +268,86 @@ public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) { } return true; } - private boolean DEV_COMPLETION_sempred(RuleContext _localctx, int predIndex) { - switch (predIndex) { - case 0: - return this.isDevVersion(); - } - return true; - } private boolean DEV_INLINESTATS_sempred(RuleContext _localctx, int predIndex) { switch (predIndex) { - case 1: + case 0: return this.isDevVersion(); } return true; } private boolean DEV_RERANK_sempred(RuleContext _localctx, int predIndex) { switch (predIndex) { - case 2: + case 1: return this.isDevVersion(); } return true; } private boolean DEV_SAMPLE_sempred(RuleContext _localctx, int predIndex) { switch (predIndex) { - case 3: + case 2: return this.isDevVersion(); } return true; } private boolean DEV_TIME_SERIES_sempred(RuleContext _localctx, int predIndex) { switch (predIndex) { - case 4: + case 3: return this.isDevVersion(); } return true; } private boolean DEV_FORK_sempred(RuleContext _localctx, int predIndex) { switch (predIndex) { - case 5: + case 4: return this.isDevVersion(); } return true; } private boolean DEV_JOIN_FULL_sempred(RuleContext _localctx, int predIndex) { switch (predIndex) { - case 6: + case 5: return this.isDevVersion(); } return true; } private boolean DEV_JOIN_LEFT_sempred(RuleContext _localctx, int predIndex) { switch (predIndex) { - case 7: + case 6: return this.isDevVersion(); } return true; } private boolean DEV_JOIN_RIGHT_sempred(RuleContext _localctx, int predIndex) { switch (predIndex) { - case 8: + case 7: return this.isDevVersion(); } return true; } private boolean DEV_LOOKUP_sempred(RuleContext _localctx, int predIndex) { switch (predIndex) { - case 9: + case 8: return this.isDevVersion(); } return true; } private boolean DEV_INSIST_sempred(RuleContext _localctx, int predIndex) { switch (predIndex) { - case 10: + case 9: return this.isDevVersion(); } return true; } private boolean DEV_RRF_sempred(RuleContext _localctx, int predIndex) { switch (predIndex) { - case 11: + case 10: return this.isDevVersion(); } return true; } public static final String _serializedATN = - "\u0004\u0000\u008b\u06f7\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff"+ + "\u0004\u0000\u008b\u06f6\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff"+ "\uffff\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff"+ "\uffff\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff"+ "\uffff\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff"+ @@ -441,76 +431,76 @@ private boolean DEV_RRF_sempred(RuleContext _localctx, int predIndex) { "\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001"+ "\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0006\u0001\u0006\u0001"+ "\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001"+ - "\u0006\u0001\u0006\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001"+ + "\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0007\u0001"+ + "\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001"+ "\u0007\u0001\u0007\u0001\u0007\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b"+ "\u0001\b\u0001\b\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001"+ - "\t\u0001\t\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\u000b"+ - "\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b"+ - "\u0001\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001"+ - "\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\u000e"+ - "\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e"+ - "\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e"+ - "\u0001\u000e\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f"+ - "\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f"+ - "\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010"+ - "\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010"+ - "\u0001\u0010\u0001\u0010\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0011"+ - "\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0011"+ - "\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012"+ - "\u0001\u0012\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013"+ - "\u0001\u0013\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0014"+ - "\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0015\u0001\u0015\u0001\u0015"+ - "\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015"+ - "\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016"+ - "\u0001\u0016\u0001\u0016\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017"+ - "\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0018\u0001\u0018"+ - "\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018"+ - "\u0001\u0018\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019"+ - "\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019"+ - "\u0001\u0019\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a"+ - "\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a"+ - "\u0001\u001a\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001b"+ - "\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0001\u001c\u0001\u001c"+ - "\u0001\u001c\u0001\u001c\u0001\u001c\u0001\u001d\u0001\u001d\u0001\u001d"+ - "\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d"+ - "\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001e\u0001\u001e\u0001\u001e"+ - "\u0001\u001e\u0001\u001e\u0001\u001e\u0001\u001e\u0001\u001f\u0001\u001f"+ - "\u0001\u001f\u0001\u001f\u0001\u001f\u0001\u001f\u0001\u001f\u0001\u001f"+ - "\u0001\u001f\u0001 \u0001 \u0001 \u0001 \u0001 \u0001 \u0001 \u0001!\u0004"+ - "!\u0325\b!\u000b!\f!\u0326\u0001!\u0001!\u0001\"\u0001\"\u0001\"\u0001"+ - "\"\u0001\"\u0001#\u0001#\u0001#\u0001#\u0001$\u0001$\u0001$\u0001$\u0001"+ - "%\u0001%\u0001%\u0001%\u0001&\u0001&\u0001&\u0001&\u0001\'\u0001\'\u0001"+ - "\'\u0001\'\u0001(\u0001(\u0001(\u0001(\u0001)\u0001)\u0001)\u0001)\u0001"+ - "*\u0001*\u0001*\u0001*\u0001+\u0001+\u0001+\u0001+\u0001,\u0001,\u0001"+ - ",\u0001,\u0001,\u0001-\u0001-\u0001-\u0001-\u0001-\u0001.\u0001.\u0001"+ - ".\u0001.\u0001.\u0001/\u0001/\u0001/\u0001/\u0001/\u00010\u00010\u0001"+ - "1\u00041\u036b\b1\u000b1\f1\u036c\u00011\u00011\u00031\u0371\b1\u0001"+ - "1\u00041\u0374\b1\u000b1\f1\u0375\u00012\u00012\u00012\u00012\u00013\u0001"+ - "3\u00013\u00013\u00014\u00014\u00014\u00014\u00015\u00015\u00015\u0001"+ - "5\u00016\u00016\u00016\u00016\u00016\u00016\u00017\u00017\u00017\u0001"+ - "7\u00018\u00018\u00018\u00018\u00019\u00019\u00019\u00019\u0001:\u0001"+ - ":\u0001:\u0001:\u0001;\u0001;\u0001;\u0001;\u0001<\u0001<\u0001<\u0001"+ - "<\u0001=\u0001=\u0001=\u0001=\u0001>\u0001>\u0001>\u0001>\u0001?\u0001"+ - "?\u0001?\u0001?\u0001@\u0001@\u0001@\u0001@\u0001A\u0001A\u0001A\u0001"+ - "A\u0001B\u0001B\u0001B\u0001B\u0001C\u0001C\u0001C\u0001C\u0001D\u0001"+ - "D\u0001D\u0001D\u0001D\u0001E\u0001E\u0001E\u0001E\u0001F\u0001F\u0001"+ - "F\u0001F\u0001F\u0004F\u03d0\bF\u000bF\fF\u03d1\u0001G\u0001G\u0001G\u0001"+ - "G\u0001H\u0001H\u0001H\u0001H\u0001I\u0001I\u0001I\u0001I\u0001J\u0001"+ - "J\u0001J\u0001J\u0001J\u0001K\u0001K\u0001K\u0001K\u0001K\u0001L\u0001"+ - "L\u0001L\u0001L\u0001M\u0001M\u0001M\u0001M\u0001N\u0001N\u0001N\u0001"+ - "N\u0001O\u0001O\u0001O\u0001O\u0001P\u0001P\u0001Q\u0001Q\u0001R\u0001"+ - "R\u0001R\u0001S\u0001S\u0001T\u0001T\u0003T\u0405\bT\u0001T\u0004T\u0408"+ - "\bT\u000bT\fT\u0409\u0001U\u0001U\u0001V\u0001V\u0001W\u0001W\u0001W\u0003"+ - "W\u0413\bW\u0001X\u0001X\u0001Y\u0001Y\u0001Y\u0003Y\u041a\bY\u0001Z\u0001"+ - "Z\u0001Z\u0005Z\u041f\bZ\nZ\fZ\u0422\tZ\u0001Z\u0001Z\u0001Z\u0001Z\u0001"+ - "Z\u0001Z\u0005Z\u042a\bZ\nZ\fZ\u042d\tZ\u0001Z\u0001Z\u0001Z\u0001Z\u0001"+ - "Z\u0003Z\u0434\bZ\u0001Z\u0003Z\u0437\bZ\u0003Z\u0439\bZ\u0001[\u0004"+ - "[\u043c\b[\u000b[\f[\u043d\u0001\\\u0004\\\u0441\b\\\u000b\\\f\\\u0442"+ - "\u0001\\\u0001\\\u0005\\\u0447\b\\\n\\\f\\\u044a\t\\\u0001\\\u0001\\\u0004"+ - "\\\u044e\b\\\u000b\\\f\\\u044f\u0001\\\u0004\\\u0453\b\\\u000b\\\f\\\u0454"+ - "\u0001\\\u0001\\\u0005\\\u0459\b\\\n\\\f\\\u045c\t\\\u0003\\\u045e\b\\"+ - "\u0001\\\u0001\\\u0001\\\u0001\\\u0004\\\u0464\b\\\u000b\\\f\\\u0465\u0001"+ - "\\\u0001\\\u0003\\\u046a\b\\\u0001]\u0001]\u0001]\u0001]\u0001^\u0001"+ + "\t\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001"+ + "\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001"+ + "\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001\f\u0001\r\u0001\r\u0001"+ + "\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\u000e\u0001\u000e\u0001"+ + "\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001"+ + "\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001"+ + "\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001"+ + "\u000f\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010\u0001\u0010\u0001"+ + "\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001"+ + "\u0010\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0011\u0001"+ + "\u0011\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0011\u0001\u0012\u0001"+ + "\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001"+ + "\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001"+ + "\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001"+ + "\u0014\u0001\u0014\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0001"+ + "\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0016\u0001"+ + "\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001"+ + "\u0016\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0001"+ + "\u0017\u0001\u0017\u0001\u0017\u0001\u0018\u0001\u0018\u0001\u0018\u0001"+ + "\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001"+ + "\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001"+ + "\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001"+ + "\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001"+ + "\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001"+ + "\u001b\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001b\u0001"+ + "\u001b\u0001\u001c\u0001\u001c\u0001\u001c\u0001\u001c\u0001\u001c\u0001"+ + "\u001c\u0001\u001c\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0001"+ + "\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0001\u001d\u0001"+ + "\u001d\u0001\u001d\u0001\u001e\u0001\u001e\u0001\u001e\u0001\u001e\u0001"+ + "\u001e\u0001\u001e\u0001\u001e\u0001\u001f\u0001\u001f\u0001\u001f\u0001"+ + "\u001f\u0001\u001f\u0001\u001f\u0001\u001f\u0001\u001f\u0001\u001f\u0001"+ + " \u0001 \u0001 \u0001 \u0001 \u0001 \u0001 \u0001!\u0004!\u0324\b!\u000b"+ + "!\f!\u0325\u0001!\u0001!\u0001\"\u0001\"\u0001\"\u0001\"\u0001\"\u0001"+ + "#\u0001#\u0001#\u0001#\u0001$\u0001$\u0001$\u0001$\u0001%\u0001%\u0001"+ + "%\u0001%\u0001&\u0001&\u0001&\u0001&\u0001\'\u0001\'\u0001\'\u0001\'\u0001"+ + "(\u0001(\u0001(\u0001(\u0001)\u0001)\u0001)\u0001)\u0001*\u0001*\u0001"+ + "*\u0001*\u0001+\u0001+\u0001+\u0001+\u0001,\u0001,\u0001,\u0001,\u0001"+ + ",\u0001-\u0001-\u0001-\u0001-\u0001-\u0001.\u0001.\u0001.\u0001.\u0001"+ + ".\u0001/\u0001/\u0001/\u0001/\u0001/\u00010\u00010\u00011\u00041\u036a"+ + "\b1\u000b1\f1\u036b\u00011\u00011\u00031\u0370\b1\u00011\u00041\u0373"+ + "\b1\u000b1\f1\u0374\u00012\u00012\u00012\u00012\u00013\u00013\u00013\u0001"+ + "3\u00014\u00014\u00014\u00014\u00015\u00015\u00015\u00015\u00016\u0001"+ + "6\u00016\u00016\u00016\u00016\u00017\u00017\u00017\u00017\u00018\u0001"+ + "8\u00018\u00018\u00019\u00019\u00019\u00019\u0001:\u0001:\u0001:\u0001"+ + ":\u0001;\u0001;\u0001;\u0001;\u0001<\u0001<\u0001<\u0001<\u0001=\u0001"+ + "=\u0001=\u0001=\u0001>\u0001>\u0001>\u0001>\u0001?\u0001?\u0001?\u0001"+ + "?\u0001@\u0001@\u0001@\u0001@\u0001A\u0001A\u0001A\u0001A\u0001B\u0001"+ + "B\u0001B\u0001B\u0001C\u0001C\u0001C\u0001C\u0001D\u0001D\u0001D\u0001"+ + "D\u0001D\u0001E\u0001E\u0001E\u0001E\u0001F\u0001F\u0001F\u0001F\u0001"+ + "F\u0004F\u03cf\bF\u000bF\fF\u03d0\u0001G\u0001G\u0001G\u0001G\u0001H\u0001"+ + "H\u0001H\u0001H\u0001I\u0001I\u0001I\u0001I\u0001J\u0001J\u0001J\u0001"+ + "J\u0001J\u0001K\u0001K\u0001K\u0001K\u0001K\u0001L\u0001L\u0001L\u0001"+ + "L\u0001M\u0001M\u0001M\u0001M\u0001N\u0001N\u0001N\u0001N\u0001O\u0001"+ + "O\u0001O\u0001O\u0001P\u0001P\u0001Q\u0001Q\u0001R\u0001R\u0001R\u0001"+ + "S\u0001S\u0001T\u0001T\u0003T\u0404\bT\u0001T\u0004T\u0407\bT\u000bT\f"+ + "T\u0408\u0001U\u0001U\u0001V\u0001V\u0001W\u0001W\u0001W\u0003W\u0412"+ + "\bW\u0001X\u0001X\u0001Y\u0001Y\u0001Y\u0003Y\u0419\bY\u0001Z\u0001Z\u0001"+ + "Z\u0005Z\u041e\bZ\nZ\fZ\u0421\tZ\u0001Z\u0001Z\u0001Z\u0001Z\u0001Z\u0001"+ + "Z\u0005Z\u0429\bZ\nZ\fZ\u042c\tZ\u0001Z\u0001Z\u0001Z\u0001Z\u0001Z\u0003"+ + "Z\u0433\bZ\u0001Z\u0003Z\u0436\bZ\u0003Z\u0438\bZ\u0001[\u0004[\u043b"+ + "\b[\u000b[\f[\u043c\u0001\\\u0004\\\u0440\b\\\u000b\\\f\\\u0441\u0001"+ + "\\\u0001\\\u0005\\\u0446\b\\\n\\\f\\\u0449\t\\\u0001\\\u0001\\\u0004\\"+ + "\u044d\b\\\u000b\\\f\\\u044e\u0001\\\u0004\\\u0452\b\\\u000b\\\f\\\u0453"+ + "\u0001\\\u0001\\\u0005\\\u0458\b\\\n\\\f\\\u045b\t\\\u0003\\\u045d\b\\"+ + "\u0001\\\u0001\\\u0001\\\u0001\\\u0004\\\u0463\b\\\u000b\\\f\\\u0464\u0001"+ + "\\\u0001\\\u0003\\\u0469\b\\\u0001]\u0001]\u0001]\u0001]\u0001^\u0001"+ "^\u0001^\u0001_\u0001_\u0001_\u0001_\u0001`\u0001`\u0001a\u0001a\u0001"+ "a\u0001b\u0001b\u0001b\u0001c\u0001c\u0001d\u0001d\u0001e\u0001e\u0001"+ "e\u0001e\u0001e\u0001f\u0001f\u0001g\u0001g\u0001g\u0001g\u0001g\u0001"+ @@ -525,21 +515,21 @@ private boolean DEV_RRF_sempred(RuleContext _localctx, int predIndex) { "|\u0001}\u0001}\u0001~\u0001~\u0001\u007f\u0001\u007f\u0001\u0080\u0001"+ "\u0080\u0001\u0081\u0001\u0081\u0001\u0082\u0001\u0082\u0001\u0083\u0001"+ "\u0083\u0001\u0084\u0001\u0084\u0001\u0084\u0001\u0085\u0001\u0085\u0001"+ - "\u0085\u0001\u0085\u0001\u0086\u0001\u0086\u0001\u0086\u0003\u0086\u04f8"+ - "\b\u0086\u0001\u0086\u0005\u0086\u04fb\b\u0086\n\u0086\f\u0086\u04fe\t"+ - "\u0086\u0001\u0086\u0001\u0086\u0004\u0086\u0502\b\u0086\u000b\u0086\f"+ - "\u0086\u0503\u0003\u0086\u0506\b\u0086\u0001\u0087\u0001\u0087\u0001\u0087"+ - "\u0003\u0087\u050b\b\u0087\u0001\u0087\u0005\u0087\u050e\b\u0087\n\u0087"+ - "\f\u0087\u0511\t\u0087\u0001\u0087\u0001\u0087\u0004\u0087\u0515\b\u0087"+ - "\u000b\u0087\f\u0087\u0516\u0003\u0087\u0519\b\u0087\u0001\u0088\u0001"+ + "\u0085\u0001\u0085\u0001\u0086\u0001\u0086\u0001\u0086\u0003\u0086\u04f7"+ + "\b\u0086\u0001\u0086\u0005\u0086\u04fa\b\u0086\n\u0086\f\u0086\u04fd\t"+ + "\u0086\u0001\u0086\u0001\u0086\u0004\u0086\u0501\b\u0086\u000b\u0086\f"+ + "\u0086\u0502\u0003\u0086\u0505\b\u0086\u0001\u0087\u0001\u0087\u0001\u0087"+ + "\u0003\u0087\u050a\b\u0087\u0001\u0087\u0005\u0087\u050d\b\u0087\n\u0087"+ + "\f\u0087\u0510\t\u0087\u0001\u0087\u0001\u0087\u0004\u0087\u0514\b\u0087"+ + "\u000b\u0087\f\u0087\u0515\u0003\u0087\u0518\b\u0087\u0001\u0088\u0001"+ "\u0088\u0001\u0088\u0001\u0088\u0001\u0088\u0001\u0089\u0001\u0089\u0001"+ "\u0089\u0001\u0089\u0001\u0089\u0001\u008a\u0001\u008a\u0001\u008a\u0001"+ "\u008a\u0001\u008a\u0001\u008b\u0001\u008b\u0001\u008b\u0001\u008b\u0001"+ - "\u008b\u0001\u008c\u0001\u008c\u0005\u008c\u0531\b\u008c\n\u008c\f\u008c"+ - "\u0534\t\u008c\u0001\u008c\u0001\u008c\u0003\u008c\u0538\b\u008c\u0001"+ - "\u008c\u0004\u008c\u053b\b\u008c\u000b\u008c\f\u008c\u053c\u0003\u008c"+ - "\u053f\b\u008c\u0001\u008d\u0001\u008d\u0004\u008d\u0543\b\u008d\u000b"+ - "\u008d\f\u008d\u0544\u0001\u008d\u0001\u008d\u0001\u008e\u0001\u008e\u0001"+ + "\u008b\u0001\u008c\u0001\u008c\u0005\u008c\u0530\b\u008c\n\u008c\f\u008c"+ + "\u0533\t\u008c\u0001\u008c\u0001\u008c\u0003\u008c\u0537\b\u008c\u0001"+ + "\u008c\u0004\u008c\u053a\b\u008c\u000b\u008c\f\u008c\u053b\u0003\u008c"+ + "\u053e\b\u008c\u0001\u008d\u0001\u008d\u0004\u008d\u0542\b\u008d\u000b"+ + "\u008d\f\u008d\u0543\u0001\u008d\u0001\u008d\u0001\u008e\u0001\u008e\u0001"+ "\u008f\u0001\u008f\u0001\u008f\u0001\u008f\u0001\u0090\u0001\u0090\u0001"+ "\u0090\u0001\u0090\u0001\u0091\u0001\u0091\u0001\u0091\u0001\u0091\u0001"+ "\u0092\u0001\u0092\u0001\u0092\u0001\u0092\u0001\u0092\u0001\u0093\u0001"+ @@ -548,8 +538,8 @@ private boolean DEV_RRF_sempred(RuleContext _localctx, int predIndex) { "\u0096\u0001\u0096\u0001\u0096\u0001\u0097\u0001\u0097\u0001\u0097\u0001"+ "\u0097\u0001\u0098\u0001\u0098\u0001\u0098\u0001\u0098\u0001\u0099\u0001"+ "\u0099\u0001\u0099\u0001\u0099\u0001\u0099\u0001\u0099\u0001\u0099\u0001"+ - "\u0099\u0001\u0099\u0001\u009a\u0001\u009a\u0001\u009a\u0003\u009a\u0580"+ - "\b\u009a\u0001\u009b\u0004\u009b\u0583\b\u009b\u000b\u009b\f\u009b\u0584"+ + "\u0099\u0001\u0099\u0001\u009a\u0001\u009a\u0001\u009a\u0003\u009a\u057f"+ + "\b\u009a\u0001\u009b\u0004\u009b\u0582\b\u009b\u000b\u009b\f\u009b\u0583"+ "\u0001\u009c\u0001\u009c\u0001\u009c\u0001\u009c\u0001\u009d\u0001\u009d"+ "\u0001\u009d\u0001\u009d\u0001\u009e\u0001\u009e\u0001\u009e\u0001\u009e"+ "\u0001\u009f\u0001\u009f\u0001\u009f\u0001\u009f\u0001\u00a0\u0001\u00a0"+ @@ -592,12 +582,12 @@ private boolean DEV_RRF_sempred(RuleContext _localctx, int predIndex) { "\u0001\u00d2\u0001\u00d2\u0001\u00d2\u0001\u00d3\u0001\u00d3\u0001\u00d3"+ "\u0001\u00d3\u0001\u00d4\u0001\u00d4\u0001\u00d4\u0001\u00d4\u0001\u00d5"+ "\u0001\u00d5\u0001\u00d5\u0001\u00d5\u0001\u00d6\u0001\u00d6\u0001\u00d6"+ - "\u0001\u00d6\u0003\u00d6\u0684\b\u00d6\u0001\u00d7\u0001\u00d7\u0003\u00d7"+ - "\u0688\b\u00d7\u0001\u00d7\u0005\u00d7\u068b\b\u00d7\n\u00d7\f\u00d7\u068e"+ - "\t\u00d7\u0001\u00d7\u0001\u00d7\u0003\u00d7\u0692\b\u00d7\u0001\u00d7"+ - "\u0004\u00d7\u0695\b\u00d7\u000b\u00d7\f\u00d7\u0696\u0003\u00d7\u0699"+ - "\b\u00d7\u0001\u00d8\u0001\u00d8\u0004\u00d8\u069d\b\u00d8\u000b\u00d8"+ - "\f\u00d8\u069e\u0001\u00d9\u0001\u00d9\u0001\u00d9\u0001\u00d9\u0001\u00da"+ + "\u0001\u00d6\u0003\u00d6\u0683\b\u00d6\u0001\u00d7\u0001\u00d7\u0003\u00d7"+ + "\u0687\b\u00d7\u0001\u00d7\u0005\u00d7\u068a\b\u00d7\n\u00d7\f\u00d7\u068d"+ + "\t\u00d7\u0001\u00d7\u0001\u00d7\u0003\u00d7\u0691\b\u00d7\u0001\u00d7"+ + "\u0004\u00d7\u0694\b\u00d7\u000b\u00d7\f\u00d7\u0695\u0003\u00d7\u0698"+ + "\b\u00d7\u0001\u00d8\u0001\u00d8\u0004\u00d8\u069c\b\u00d8\u000b\u00d8"+ + "\f\u00d8\u069d\u0001\u00d9\u0001\u00d9\u0001\u00d9\u0001\u00d9\u0001\u00da"+ "\u0001\u00da\u0001\u00da\u0001\u00da\u0001\u00db\u0001\u00db\u0001\u00db"+ "\u0001\u00db\u0001\u00dc\u0001\u00dc\u0001\u00dc\u0001\u00dc\u0001\u00dc"+ "\u0001\u00dd\u0001\u00dd\u0001\u00dd\u0001\u00dd\u0001\u00de\u0001\u00de"+ @@ -611,7 +601,7 @@ private boolean DEV_RRF_sempred(RuleContext _localctx, int predIndex) { "\u0001\u00e9\u0001\u00e9\u0001\u00e9\u0001\u00e9\u0001\u00e9\u0001\u00ea"+ "\u0001\u00ea\u0001\u00ea\u0001\u00ea\u0001\u00ea\u0001\u00eb\u0001\u00eb"+ "\u0001\u00eb\u0001\u00eb\u0001\u00ec\u0001\u00ec\u0001\u00ec\u0001\u00ec"+ - "\u0001\u00ed\u0001\u00ed\u0001\u00ed\u0001\u00ed\u0002\u0204\u042b\u0000"+ + "\u0001\u00ed\u0001\u00ed\u0001\u00ed\u0001\u00ed\u0002\u0204\u042a\u0000"+ "\u00ee\u0010\u0001\u0012\u0002\u0014\u0003\u0016\u0004\u0018\u0005\u001a"+ "\u0006\u001c\u0007\u001e\b \t\"\n$\u000b&\f(\r*\u000e,\u000f.\u00100\u0011"+ "2\u00124\u00136\u00148\u0015:\u0016<\u0017>\u0018@\u0019B\u001aD\u001b"+ @@ -646,13 +636,13 @@ private boolean DEV_RRF_sempred(RuleContext _localctx, int predIndex) { "\u000f$\u0002\u0000\n\n\r\r\u0003\u0000\t\n\r\r \u0002\u0000CCcc\u0002"+ "\u0000HHhh\u0002\u0000AAaa\u0002\u0000NNnn\u0002\u0000GGgg\u0002\u0000"+ "EEee\u0002\u0000PPpp\u0002\u0000OOoo\u0002\u0000IIii\u0002\u0000TTtt\u0002"+ - "\u0000RRrr\u0002\u0000XXxx\u0002\u0000LLll\u0002\u0000DDdd\u0002\u0000"+ - "SSss\u0002\u0000VVvv\u0002\u0000KKkk\u0002\u0000MMmm\u0002\u0000WWww\u0002"+ + "\u0000RRrr\u0002\u0000XXxx\u0002\u0000LLll\u0002\u0000MMmm\u0002\u0000"+ + "DDdd\u0002\u0000SSss\u0002\u0000VVvv\u0002\u0000KKkk\u0002\u0000WWww\u0002"+ "\u0000FFff\u0002\u0000UUuu\u0006\u0000\t\n\r\r //[[]]\u000b\u0000\t\n"+ "\r\r \"#,,//::<<>?\\\\||\u0001\u000009\u0002\u0000AZaz\b\u0000\"\"NN"+ "RRTT\\\\nnrrtt\u0004\u0000\n\n\r\r\"\"\\\\\u0002\u0000++--\u0001\u0000"+ "``\u0002\u0000BBbb\u0002\u0000YYyy\u000b\u0000\t\n\r\r \"\",,//::==["+ - "[]]||\u0002\u0000**//\u0002\u0000JJjj\u0716\u0000\u0010\u0001\u0000\u0000"+ + "[]]||\u0002\u0000**//\u0002\u0000JJjj\u0715\u0000\u0010\u0001\u0000\u0000"+ "\u0000\u0000\u0012\u0001\u0000\u0000\u0000\u0000\u0014\u0001\u0000\u0000"+ "\u0000\u0000\u0016\u0001\u0000\u0000\u0000\u0000\u0018\u0001\u0000\u0000"+ "\u0000\u0000\u001a\u0001\u0000\u0000\u0000\u0000\u001c\u0001\u0000\u0000"+ @@ -762,118 +752,118 @@ private boolean DEV_RRF_sempred(RuleContext _localctx, int predIndex) { "\u0012\u01fd\u0001\u0000\u0000\u0000\u0014\u020d\u0001\u0000\u0000\u0000"+ "\u0016\u0213\u0001\u0000\u0000\u0000\u0018\u0222\u0001\u0000\u0000\u0000"+ "\u001a\u022b\u0001\u0000\u0000\u0000\u001c\u0235\u0001\u0000\u0000\u0000"+ - "\u001e\u023f\u0001\u0000\u0000\u0000 \u0246\u0001\u0000\u0000\u0000\""+ - "\u024d\u0001\u0000\u0000\u0000$\u0255\u0001\u0000\u0000\u0000&\u025b\u0001"+ - "\u0000\u0000\u0000(\u0262\u0001\u0000\u0000\u0000*\u026a\u0001\u0000\u0000"+ - "\u0000,\u0272\u0001\u0000\u0000\u0000.\u0280\u0001\u0000\u0000\u00000"+ - "\u028f\u0001\u0000\u0000\u00002\u0299\u0001\u0000\u0000\u00004\u02a3\u0001"+ - "\u0000\u0000\u00006\u02aa\u0001\u0000\u0000\u00008\u02b0\u0001\u0000\u0000"+ - "\u0000:\u02b8\u0001\u0000\u0000\u0000<\u02c1\u0001\u0000\u0000\u0000>"+ - "\u02c9\u0001\u0000\u0000\u0000@\u02d1\u0001\u0000\u0000\u0000B\u02da\u0001"+ - "\u0000\u0000\u0000D\u02e6\u0001\u0000\u0000\u0000F\u02f2\u0001\u0000\u0000"+ - "\u0000H\u02f9\u0001\u0000\u0000\u0000J\u0300\u0001\u0000\u0000\u0000L"+ - "\u030c\u0001\u0000\u0000\u0000N\u0313\u0001\u0000\u0000\u0000P\u031c\u0001"+ - "\u0000\u0000\u0000R\u0324\u0001\u0000\u0000\u0000T\u032a\u0001\u0000\u0000"+ - "\u0000V\u032f\u0001\u0000\u0000\u0000X\u0333\u0001\u0000\u0000\u0000Z"+ - "\u0337\u0001\u0000\u0000\u0000\\\u033b\u0001\u0000\u0000\u0000^\u033f"+ - "\u0001\u0000\u0000\u0000`\u0343\u0001\u0000\u0000\u0000b\u0347\u0001\u0000"+ - "\u0000\u0000d\u034b\u0001\u0000\u0000\u0000f\u034f\u0001\u0000\u0000\u0000"+ - "h\u0353\u0001\u0000\u0000\u0000j\u0358\u0001\u0000\u0000\u0000l\u035d"+ - "\u0001\u0000\u0000\u0000n\u0362\u0001\u0000\u0000\u0000p\u0367\u0001\u0000"+ - "\u0000\u0000r\u0370\u0001\u0000\u0000\u0000t\u0377\u0001\u0000\u0000\u0000"+ - "v\u037b\u0001\u0000\u0000\u0000x\u037f\u0001\u0000\u0000\u0000z\u0383"+ - "\u0001\u0000\u0000\u0000|\u0387\u0001\u0000\u0000\u0000~\u038d\u0001\u0000"+ - "\u0000\u0000\u0080\u0391\u0001\u0000\u0000\u0000\u0082\u0395\u0001\u0000"+ - "\u0000\u0000\u0084\u0399\u0001\u0000\u0000\u0000\u0086\u039d\u0001\u0000"+ - "\u0000\u0000\u0088\u03a1\u0001\u0000\u0000\u0000\u008a\u03a5\u0001\u0000"+ - "\u0000\u0000\u008c\u03a9\u0001\u0000\u0000\u0000\u008e\u03ad\u0001\u0000"+ - "\u0000\u0000\u0090\u03b1\u0001\u0000\u0000\u0000\u0092\u03b5\u0001\u0000"+ - "\u0000\u0000\u0094\u03b9\u0001\u0000\u0000\u0000\u0096\u03bd\u0001\u0000"+ - "\u0000\u0000\u0098\u03c1\u0001\u0000\u0000\u0000\u009a\u03c6\u0001\u0000"+ - "\u0000\u0000\u009c\u03cf\u0001\u0000\u0000\u0000\u009e\u03d3\u0001\u0000"+ - "\u0000\u0000\u00a0\u03d7\u0001\u0000\u0000\u0000\u00a2\u03db\u0001\u0000"+ - "\u0000\u0000\u00a4\u03df\u0001\u0000\u0000\u0000\u00a6\u03e4\u0001\u0000"+ - "\u0000\u0000\u00a8\u03e9\u0001\u0000\u0000\u0000\u00aa\u03ed\u0001\u0000"+ - "\u0000\u0000\u00ac\u03f1\u0001\u0000\u0000\u0000\u00ae\u03f5\u0001\u0000"+ - "\u0000\u0000\u00b0\u03f9\u0001\u0000\u0000\u0000\u00b2\u03fb\u0001\u0000"+ - "\u0000\u0000\u00b4\u03fd\u0001\u0000\u0000\u0000\u00b6\u0400\u0001\u0000"+ - "\u0000\u0000\u00b8\u0402\u0001\u0000\u0000\u0000\u00ba\u040b\u0001\u0000"+ - "\u0000\u0000\u00bc\u040d\u0001\u0000\u0000\u0000\u00be\u0412\u0001\u0000"+ - "\u0000\u0000\u00c0\u0414\u0001\u0000\u0000\u0000\u00c2\u0419\u0001\u0000"+ - "\u0000\u0000\u00c4\u0438\u0001\u0000\u0000\u0000\u00c6\u043b\u0001\u0000"+ - "\u0000\u0000\u00c8\u0469\u0001\u0000\u0000\u0000\u00ca\u046b\u0001\u0000"+ - "\u0000\u0000\u00cc\u046f\u0001\u0000\u0000\u0000\u00ce\u0472\u0001\u0000"+ - "\u0000\u0000\u00d0\u0476\u0001\u0000\u0000\u0000\u00d2\u0478\u0001\u0000"+ - "\u0000\u0000\u00d4\u047b\u0001\u0000\u0000\u0000\u00d6\u047e\u0001\u0000"+ - "\u0000\u0000\u00d8\u0480\u0001\u0000\u0000\u0000\u00da\u0482\u0001\u0000"+ - "\u0000\u0000\u00dc\u0487\u0001\u0000\u0000\u0000\u00de\u0489\u0001\u0000"+ - "\u0000\u0000\u00e0\u048f\u0001\u0000\u0000\u0000\u00e2\u0495\u0001\u0000"+ - "\u0000\u0000\u00e4\u0498\u0001\u0000\u0000\u0000\u00e6\u049b\u0001\u0000"+ - "\u0000\u0000\u00e8\u04a0\u0001\u0000\u0000\u0000\u00ea\u04a5\u0001\u0000"+ - "\u0000\u0000\u00ec\u04a9\u0001\u0000\u0000\u0000\u00ee\u04ae\u0001\u0000"+ - "\u0000\u0000\u00f0\u04b4\u0001\u0000\u0000\u0000\u00f2\u04b7\u0001\u0000"+ - "\u0000\u0000\u00f4\u04ba\u0001\u0000\u0000\u0000\u00f6\u04bc\u0001\u0000"+ - "\u0000\u0000\u00f8\u04c2\u0001\u0000\u0000\u0000\u00fa\u04c7\u0001\u0000"+ - "\u0000\u0000\u00fc\u04cc\u0001\u0000\u0000\u0000\u00fe\u04cf\u0001\u0000"+ - "\u0000\u0000\u0100\u04d2\u0001\u0000\u0000\u0000\u0102\u04d5\u0001\u0000"+ - "\u0000\u0000\u0104\u04d7\u0001\u0000\u0000\u0000\u0106\u04da\u0001\u0000"+ - "\u0000\u0000\u0108\u04dc\u0001\u0000\u0000\u0000\u010a\u04df\u0001\u0000"+ - "\u0000\u0000\u010c\u04e1\u0001\u0000\u0000\u0000\u010e\u04e3\u0001\u0000"+ - "\u0000\u0000\u0110\u04e5\u0001\u0000\u0000\u0000\u0112\u04e7\u0001\u0000"+ - "\u0000\u0000\u0114\u04e9\u0001\u0000\u0000\u0000\u0116\u04eb\u0001\u0000"+ - "\u0000\u0000\u0118\u04ed\u0001\u0000\u0000\u0000\u011a\u04f0\u0001\u0000"+ - "\u0000\u0000\u011c\u0505\u0001\u0000\u0000\u0000\u011e\u0518\u0001\u0000"+ - "\u0000\u0000\u0120\u051a\u0001\u0000\u0000\u0000\u0122\u051f\u0001\u0000"+ - "\u0000\u0000\u0124\u0524\u0001\u0000\u0000\u0000\u0126\u0529\u0001\u0000"+ - "\u0000\u0000\u0128\u053e\u0001\u0000\u0000\u0000\u012a\u0540\u0001\u0000"+ - "\u0000\u0000\u012c\u0548\u0001\u0000\u0000\u0000\u012e\u054a\u0001\u0000"+ - "\u0000\u0000\u0130\u054e\u0001\u0000\u0000\u0000\u0132\u0552\u0001\u0000"+ - "\u0000\u0000\u0134\u0556\u0001\u0000\u0000\u0000\u0136\u055b\u0001\u0000"+ - "\u0000\u0000\u0138\u055f\u0001\u0000\u0000\u0000\u013a\u0563\u0001\u0000"+ - "\u0000\u0000\u013c\u0567\u0001\u0000\u0000\u0000\u013e\u056b\u0001\u0000"+ - "\u0000\u0000\u0140\u056f\u0001\u0000\u0000\u0000\u0142\u0573\u0001\u0000"+ - "\u0000\u0000\u0144\u057f\u0001\u0000\u0000\u0000\u0146\u0582\u0001\u0000"+ - "\u0000\u0000\u0148\u0586\u0001\u0000\u0000\u0000\u014a\u058a\u0001\u0000"+ - "\u0000\u0000\u014c\u058e\u0001\u0000\u0000\u0000\u014e\u0592\u0001\u0000"+ - "\u0000\u0000\u0150\u0596\u0001\u0000\u0000\u0000\u0152\u059a\u0001\u0000"+ - "\u0000\u0000\u0154\u059f\u0001\u0000\u0000\u0000\u0156\u05a4\u0001\u0000"+ - "\u0000\u0000\u0158\u05a8\u0001\u0000\u0000\u0000\u015a\u05ac\u0001\u0000"+ - "\u0000\u0000\u015c\u05b0\u0001\u0000\u0000\u0000\u015e\u05b5\u0001\u0000"+ - "\u0000\u0000\u0160\u05ba\u0001\u0000\u0000\u0000\u0162\u05be\u0001\u0000"+ - "\u0000\u0000\u0164\u05c4\u0001\u0000\u0000\u0000\u0166\u05cd\u0001\u0000"+ - "\u0000\u0000\u0168\u05d1\u0001\u0000\u0000\u0000\u016a\u05d5\u0001\u0000"+ - "\u0000\u0000\u016c\u05d9\u0001\u0000\u0000\u0000\u016e\u05dd\u0001\u0000"+ - "\u0000\u0000\u0170\u05e1\u0001\u0000\u0000\u0000\u0172\u05e5\u0001\u0000"+ - "\u0000\u0000\u0174\u05e9\u0001\u0000\u0000\u0000\u0176\u05ed\u0001\u0000"+ - "\u0000\u0000\u0178\u05f2\u0001\u0000\u0000\u0000\u017a\u05f6\u0001\u0000"+ - "\u0000\u0000\u017c\u05fa\u0001\u0000\u0000\u0000\u017e\u05fe\u0001\u0000"+ - "\u0000\u0000\u0180\u0603\u0001\u0000\u0000\u0000\u0182\u0607\u0001\u0000"+ - "\u0000\u0000\u0184\u060b\u0001\u0000\u0000\u0000\u0186\u060f\u0001\u0000"+ - "\u0000\u0000\u0188\u0613\u0001\u0000\u0000\u0000\u018a\u0617\u0001\u0000"+ - "\u0000\u0000\u018c\u061d\u0001\u0000\u0000\u0000\u018e\u0621\u0001\u0000"+ - "\u0000\u0000\u0190\u0625\u0001\u0000\u0000\u0000\u0192\u0629\u0001\u0000"+ - "\u0000\u0000\u0194\u062d\u0001\u0000\u0000\u0000\u0196\u0631\u0001\u0000"+ - "\u0000\u0000\u0198\u0635\u0001\u0000\u0000\u0000\u019a\u063a\u0001\u0000"+ - "\u0000\u0000\u019c\u063e\u0001\u0000\u0000\u0000\u019e\u0642\u0001\u0000"+ - "\u0000\u0000\u01a0\u0646\u0001\u0000\u0000\u0000\u01a2\u064a\u0001\u0000"+ - "\u0000\u0000\u01a4\u064e\u0001\u0000\u0000\u0000\u01a6\u0652\u0001\u0000"+ - "\u0000\u0000\u01a8\u0656\u0001\u0000\u0000\u0000\u01aa\u065a\u0001\u0000"+ - "\u0000\u0000\u01ac\u065e\u0001\u0000\u0000\u0000\u01ae\u0662\u0001\u0000"+ - "\u0000\u0000\u01b0\u0667\u0001\u0000\u0000\u0000\u01b2\u066b\u0001\u0000"+ - "\u0000\u0000\u01b4\u066f\u0001\u0000\u0000\u0000\u01b6\u0673\u0001\u0000"+ - "\u0000\u0000\u01b8\u0677\u0001\u0000\u0000\u0000\u01ba\u067b\u0001\u0000"+ - "\u0000\u0000\u01bc\u0683\u0001\u0000\u0000\u0000\u01be\u0698\u0001\u0000"+ - "\u0000\u0000\u01c0\u069c\u0001\u0000\u0000\u0000\u01c2\u06a0\u0001\u0000"+ - "\u0000\u0000\u01c4\u06a4\u0001\u0000\u0000\u0000\u01c6\u06a8\u0001\u0000"+ - "\u0000\u0000\u01c8\u06ac\u0001\u0000\u0000\u0000\u01ca\u06b1\u0001\u0000"+ - "\u0000\u0000\u01cc\u06b5\u0001\u0000\u0000\u0000\u01ce\u06b9\u0001\u0000"+ - "\u0000\u0000\u01d0\u06bd\u0001\u0000\u0000\u0000\u01d2\u06c1\u0001\u0000"+ - "\u0000\u0000\u01d4\u06c5\u0001\u0000\u0000\u0000\u01d6\u06c9\u0001\u0000"+ - "\u0000\u0000\u01d8\u06cd\u0001\u0000\u0000\u0000\u01da\u06d1\u0001\u0000"+ - "\u0000\u0000\u01dc\u06d5\u0001\u0000\u0000\u0000\u01de\u06d9\u0001\u0000"+ - "\u0000\u0000\u01e0\u06dd\u0001\u0000\u0000\u0000\u01e2\u06e1\u0001\u0000"+ - "\u0000\u0000\u01e4\u06e6\u0001\u0000\u0000\u0000\u01e6\u06eb\u0001\u0000"+ - "\u0000\u0000\u01e8\u06ef\u0001\u0000\u0000\u0000\u01ea\u06f3\u0001\u0000"+ + "\u001e\u0242\u0001\u0000\u0000\u0000 \u024c\u0001\u0000\u0000\u0000\""+ + "\u0253\u0001\u0000\u0000\u0000$\u025a\u0001\u0000\u0000\u0000&\u0262\u0001"+ + "\u0000\u0000\u0000(\u0268\u0001\u0000\u0000\u0000*\u026f\u0001\u0000\u0000"+ + "\u0000,\u0277\u0001\u0000\u0000\u0000.\u027f\u0001\u0000\u0000\u00000"+ + "\u028e\u0001\u0000\u0000\u00002\u0298\u0001\u0000\u0000\u00004\u02a2\u0001"+ + "\u0000\u0000\u00006\u02a9\u0001\u0000\u0000\u00008\u02af\u0001\u0000\u0000"+ + "\u0000:\u02b7\u0001\u0000\u0000\u0000<\u02c0\u0001\u0000\u0000\u0000>"+ + "\u02c8\u0001\u0000\u0000\u0000@\u02d0\u0001\u0000\u0000\u0000B\u02d9\u0001"+ + "\u0000\u0000\u0000D\u02e5\u0001\u0000\u0000\u0000F\u02f1\u0001\u0000\u0000"+ + "\u0000H\u02f8\u0001\u0000\u0000\u0000J\u02ff\u0001\u0000\u0000\u0000L"+ + "\u030b\u0001\u0000\u0000\u0000N\u0312\u0001\u0000\u0000\u0000P\u031b\u0001"+ + "\u0000\u0000\u0000R\u0323\u0001\u0000\u0000\u0000T\u0329\u0001\u0000\u0000"+ + "\u0000V\u032e\u0001\u0000\u0000\u0000X\u0332\u0001\u0000\u0000\u0000Z"+ + "\u0336\u0001\u0000\u0000\u0000\\\u033a\u0001\u0000\u0000\u0000^\u033e"+ + "\u0001\u0000\u0000\u0000`\u0342\u0001\u0000\u0000\u0000b\u0346\u0001\u0000"+ + "\u0000\u0000d\u034a\u0001\u0000\u0000\u0000f\u034e\u0001\u0000\u0000\u0000"+ + "h\u0352\u0001\u0000\u0000\u0000j\u0357\u0001\u0000\u0000\u0000l\u035c"+ + "\u0001\u0000\u0000\u0000n\u0361\u0001\u0000\u0000\u0000p\u0366\u0001\u0000"+ + "\u0000\u0000r\u036f\u0001\u0000\u0000\u0000t\u0376\u0001\u0000\u0000\u0000"+ + "v\u037a\u0001\u0000\u0000\u0000x\u037e\u0001\u0000\u0000\u0000z\u0382"+ + "\u0001\u0000\u0000\u0000|\u0386\u0001\u0000\u0000\u0000~\u038c\u0001\u0000"+ + "\u0000\u0000\u0080\u0390\u0001\u0000\u0000\u0000\u0082\u0394\u0001\u0000"+ + "\u0000\u0000\u0084\u0398\u0001\u0000\u0000\u0000\u0086\u039c\u0001\u0000"+ + "\u0000\u0000\u0088\u03a0\u0001\u0000\u0000\u0000\u008a\u03a4\u0001\u0000"+ + "\u0000\u0000\u008c\u03a8\u0001\u0000\u0000\u0000\u008e\u03ac\u0001\u0000"+ + "\u0000\u0000\u0090\u03b0\u0001\u0000\u0000\u0000\u0092\u03b4\u0001\u0000"+ + "\u0000\u0000\u0094\u03b8\u0001\u0000\u0000\u0000\u0096\u03bc\u0001\u0000"+ + "\u0000\u0000\u0098\u03c0\u0001\u0000\u0000\u0000\u009a\u03c5\u0001\u0000"+ + "\u0000\u0000\u009c\u03ce\u0001\u0000\u0000\u0000\u009e\u03d2\u0001\u0000"+ + "\u0000\u0000\u00a0\u03d6\u0001\u0000\u0000\u0000\u00a2\u03da\u0001\u0000"+ + "\u0000\u0000\u00a4\u03de\u0001\u0000\u0000\u0000\u00a6\u03e3\u0001\u0000"+ + "\u0000\u0000\u00a8\u03e8\u0001\u0000\u0000\u0000\u00aa\u03ec\u0001\u0000"+ + "\u0000\u0000\u00ac\u03f0\u0001\u0000\u0000\u0000\u00ae\u03f4\u0001\u0000"+ + "\u0000\u0000\u00b0\u03f8\u0001\u0000\u0000\u0000\u00b2\u03fa\u0001\u0000"+ + "\u0000\u0000\u00b4\u03fc\u0001\u0000\u0000\u0000\u00b6\u03ff\u0001\u0000"+ + "\u0000\u0000\u00b8\u0401\u0001\u0000\u0000\u0000\u00ba\u040a\u0001\u0000"+ + "\u0000\u0000\u00bc\u040c\u0001\u0000\u0000\u0000\u00be\u0411\u0001\u0000"+ + "\u0000\u0000\u00c0\u0413\u0001\u0000\u0000\u0000\u00c2\u0418\u0001\u0000"+ + "\u0000\u0000\u00c4\u0437\u0001\u0000\u0000\u0000\u00c6\u043a\u0001\u0000"+ + "\u0000\u0000\u00c8\u0468\u0001\u0000\u0000\u0000\u00ca\u046a\u0001\u0000"+ + "\u0000\u0000\u00cc\u046e\u0001\u0000\u0000\u0000\u00ce\u0471\u0001\u0000"+ + "\u0000\u0000\u00d0\u0475\u0001\u0000\u0000\u0000\u00d2\u0477\u0001\u0000"+ + "\u0000\u0000\u00d4\u047a\u0001\u0000\u0000\u0000\u00d6\u047d\u0001\u0000"+ + "\u0000\u0000\u00d8\u047f\u0001\u0000\u0000\u0000\u00da\u0481\u0001\u0000"+ + "\u0000\u0000\u00dc\u0486\u0001\u0000\u0000\u0000\u00de\u0488\u0001\u0000"+ + "\u0000\u0000\u00e0\u048e\u0001\u0000\u0000\u0000\u00e2\u0494\u0001\u0000"+ + "\u0000\u0000\u00e4\u0497\u0001\u0000\u0000\u0000\u00e6\u049a\u0001\u0000"+ + "\u0000\u0000\u00e8\u049f\u0001\u0000\u0000\u0000\u00ea\u04a4\u0001\u0000"+ + "\u0000\u0000\u00ec\u04a8\u0001\u0000\u0000\u0000\u00ee\u04ad\u0001\u0000"+ + "\u0000\u0000\u00f0\u04b3\u0001\u0000\u0000\u0000\u00f2\u04b6\u0001\u0000"+ + "\u0000\u0000\u00f4\u04b9\u0001\u0000\u0000\u0000\u00f6\u04bb\u0001\u0000"+ + "\u0000\u0000\u00f8\u04c1\u0001\u0000\u0000\u0000\u00fa\u04c6\u0001\u0000"+ + "\u0000\u0000\u00fc\u04cb\u0001\u0000\u0000\u0000\u00fe\u04ce\u0001\u0000"+ + "\u0000\u0000\u0100\u04d1\u0001\u0000\u0000\u0000\u0102\u04d4\u0001\u0000"+ + "\u0000\u0000\u0104\u04d6\u0001\u0000\u0000\u0000\u0106\u04d9\u0001\u0000"+ + "\u0000\u0000\u0108\u04db\u0001\u0000\u0000\u0000\u010a\u04de\u0001\u0000"+ + "\u0000\u0000\u010c\u04e0\u0001\u0000\u0000\u0000\u010e\u04e2\u0001\u0000"+ + "\u0000\u0000\u0110\u04e4\u0001\u0000\u0000\u0000\u0112\u04e6\u0001\u0000"+ + "\u0000\u0000\u0114\u04e8\u0001\u0000\u0000\u0000\u0116\u04ea\u0001\u0000"+ + "\u0000\u0000\u0118\u04ec\u0001\u0000\u0000\u0000\u011a\u04ef\u0001\u0000"+ + "\u0000\u0000\u011c\u0504\u0001\u0000\u0000\u0000\u011e\u0517\u0001\u0000"+ + "\u0000\u0000\u0120\u0519\u0001\u0000\u0000\u0000\u0122\u051e\u0001\u0000"+ + "\u0000\u0000\u0124\u0523\u0001\u0000\u0000\u0000\u0126\u0528\u0001\u0000"+ + "\u0000\u0000\u0128\u053d\u0001\u0000\u0000\u0000\u012a\u053f\u0001\u0000"+ + "\u0000\u0000\u012c\u0547\u0001\u0000\u0000\u0000\u012e\u0549\u0001\u0000"+ + "\u0000\u0000\u0130\u054d\u0001\u0000\u0000\u0000\u0132\u0551\u0001\u0000"+ + "\u0000\u0000\u0134\u0555\u0001\u0000\u0000\u0000\u0136\u055a\u0001\u0000"+ + "\u0000\u0000\u0138\u055e\u0001\u0000\u0000\u0000\u013a\u0562\u0001\u0000"+ + "\u0000\u0000\u013c\u0566\u0001\u0000\u0000\u0000\u013e\u056a\u0001\u0000"+ + "\u0000\u0000\u0140\u056e\u0001\u0000\u0000\u0000\u0142\u0572\u0001\u0000"+ + "\u0000\u0000\u0144\u057e\u0001\u0000\u0000\u0000\u0146\u0581\u0001\u0000"+ + "\u0000\u0000\u0148\u0585\u0001\u0000\u0000\u0000\u014a\u0589\u0001\u0000"+ + "\u0000\u0000\u014c\u058d\u0001\u0000\u0000\u0000\u014e\u0591\u0001\u0000"+ + "\u0000\u0000\u0150\u0595\u0001\u0000\u0000\u0000\u0152\u0599\u0001\u0000"+ + "\u0000\u0000\u0154\u059e\u0001\u0000\u0000\u0000\u0156\u05a3\u0001\u0000"+ + "\u0000\u0000\u0158\u05a7\u0001\u0000\u0000\u0000\u015a\u05ab\u0001\u0000"+ + "\u0000\u0000\u015c\u05af\u0001\u0000\u0000\u0000\u015e\u05b4\u0001\u0000"+ + "\u0000\u0000\u0160\u05b9\u0001\u0000\u0000\u0000\u0162\u05bd\u0001\u0000"+ + "\u0000\u0000\u0164\u05c3\u0001\u0000\u0000\u0000\u0166\u05cc\u0001\u0000"+ + "\u0000\u0000\u0168\u05d0\u0001\u0000\u0000\u0000\u016a\u05d4\u0001\u0000"+ + "\u0000\u0000\u016c\u05d8\u0001\u0000\u0000\u0000\u016e\u05dc\u0001\u0000"+ + "\u0000\u0000\u0170\u05e0\u0001\u0000\u0000\u0000\u0172\u05e4\u0001\u0000"+ + "\u0000\u0000\u0174\u05e8\u0001\u0000\u0000\u0000\u0176\u05ec\u0001\u0000"+ + "\u0000\u0000\u0178\u05f1\u0001\u0000\u0000\u0000\u017a\u05f5\u0001\u0000"+ + "\u0000\u0000\u017c\u05f9\u0001\u0000\u0000\u0000\u017e\u05fd\u0001\u0000"+ + "\u0000\u0000\u0180\u0602\u0001\u0000\u0000\u0000\u0182\u0606\u0001\u0000"+ + "\u0000\u0000\u0184\u060a\u0001\u0000\u0000\u0000\u0186\u060e\u0001\u0000"+ + "\u0000\u0000\u0188\u0612\u0001\u0000\u0000\u0000\u018a\u0616\u0001\u0000"+ + "\u0000\u0000\u018c\u061c\u0001\u0000\u0000\u0000\u018e\u0620\u0001\u0000"+ + "\u0000\u0000\u0190\u0624\u0001\u0000\u0000\u0000\u0192\u0628\u0001\u0000"+ + "\u0000\u0000\u0194\u062c\u0001\u0000\u0000\u0000\u0196\u0630\u0001\u0000"+ + "\u0000\u0000\u0198\u0634\u0001\u0000\u0000\u0000\u019a\u0639\u0001\u0000"+ + "\u0000\u0000\u019c\u063d\u0001\u0000\u0000\u0000\u019e\u0641\u0001\u0000"+ + "\u0000\u0000\u01a0\u0645\u0001\u0000\u0000\u0000\u01a2\u0649\u0001\u0000"+ + "\u0000\u0000\u01a4\u064d\u0001\u0000\u0000\u0000\u01a6\u0651\u0001\u0000"+ + "\u0000\u0000\u01a8\u0655\u0001\u0000\u0000\u0000\u01aa\u0659\u0001\u0000"+ + "\u0000\u0000\u01ac\u065d\u0001\u0000\u0000\u0000\u01ae\u0661\u0001\u0000"+ + "\u0000\u0000\u01b0\u0666\u0001\u0000\u0000\u0000\u01b2\u066a\u0001\u0000"+ + "\u0000\u0000\u01b4\u066e\u0001\u0000\u0000\u0000\u01b6\u0672\u0001\u0000"+ + "\u0000\u0000\u01b8\u0676\u0001\u0000\u0000\u0000\u01ba\u067a\u0001\u0000"+ + "\u0000\u0000\u01bc\u0682\u0001\u0000\u0000\u0000\u01be\u0697\u0001\u0000"+ + "\u0000\u0000\u01c0\u069b\u0001\u0000\u0000\u0000\u01c2\u069f\u0001\u0000"+ + "\u0000\u0000\u01c4\u06a3\u0001\u0000\u0000\u0000\u01c6\u06a7\u0001\u0000"+ + "\u0000\u0000\u01c8\u06ab\u0001\u0000\u0000\u0000\u01ca\u06b0\u0001\u0000"+ + "\u0000\u0000\u01cc\u06b4\u0001\u0000\u0000\u0000\u01ce\u06b8\u0001\u0000"+ + "\u0000\u0000\u01d0\u06bc\u0001\u0000\u0000\u0000\u01d2\u06c0\u0001\u0000"+ + "\u0000\u0000\u01d4\u06c4\u0001\u0000\u0000\u0000\u01d6\u06c8\u0001\u0000"+ + "\u0000\u0000\u01d8\u06cc\u0001\u0000\u0000\u0000\u01da\u06d0\u0001\u0000"+ + "\u0000\u0000\u01dc\u06d4\u0001\u0000\u0000\u0000\u01de\u06d8\u0001\u0000"+ + "\u0000\u0000\u01e0\u06dc\u0001\u0000\u0000\u0000\u01e2\u06e0\u0001\u0000"+ + "\u0000\u0000\u01e4\u06e5\u0001\u0000\u0000\u0000\u01e6\u06ea\u0001\u0000"+ + "\u0000\u0000\u01e8\u06ee\u0001\u0000\u0000\u0000\u01ea\u06f2\u0001\u0000"+ "\u0000\u0000\u01ec\u01ed\u0005/\u0000\u0000\u01ed\u01ee\u0005/\u0000\u0000"+ "\u01ee\u01f2\u0001\u0000\u0000\u0000\u01ef\u01f1\b\u0000\u0000\u0000\u01f0"+ "\u01ef\u0001\u0000\u0000\u0000\u01f1\u01f4\u0001\u0000\u0000\u0000\u01f2"+ @@ -912,631 +902,630 @@ private boolean DEV_RRF_sempred(RuleContext _localctx, int predIndex) { "\u022e\u022f\u0007\u000e\u0000\u0000\u022f\u0230\u0007\u0004\u0000\u0000"+ "\u0230\u0231\u0007\n\u0000\u0000\u0231\u0232\u0007\u0005\u0000\u0000\u0232"+ "\u0233\u0001\u0000\u0000\u0000\u0233\u0234\u0006\u0005\u0003\u0000\u0234"+ - "\u001b\u0001\u0000\u0000\u0000\u0235\u0236\u0007\u000f\u0000\u0000\u0236"+ - "\u0237\u0007\n\u0000\u0000\u0237\u0238\u0007\u0010\u0000\u0000\u0238\u0239"+ - "\u0007\u0010\u0000\u0000\u0239\u023a\u0007\u0007\u0000\u0000\u023a\u023b"+ - "\u0007\u0002\u0000\u0000\u023b\u023c\u0007\u000b\u0000\u0000\u023c\u023d"+ - "\u0001\u0000\u0000\u0000\u023d\u023e\u0006\u0006\u0004\u0000\u023e\u001d"+ - "\u0001\u0000\u0000\u0000\u023f\u0240\u0007\u0007\u0000\u0000\u0240\u0241"+ - "\u0007\u0011\u0000\u0000\u0241\u0242\u0007\u0004\u0000\u0000\u0242\u0243"+ - "\u0007\u000e\u0000\u0000\u0243\u0244\u0001\u0000\u0000\u0000\u0244\u0245"+ - "\u0006\u0007\u0004\u0000\u0245\u001f\u0001\u0000\u0000\u0000\u0246\u0247"+ - "\u0007\u0006\u0000\u0000\u0247\u0248\u0007\f\u0000\u0000\u0248\u0249\u0007"+ - "\t\u0000\u0000\u0249\u024a\u0007\u0012\u0000\u0000\u024a\u024b\u0001\u0000"+ - "\u0000\u0000\u024b\u024c\u0006\b\u0004\u0000\u024c!\u0001\u0000\u0000"+ - "\u0000\u024d\u024e\u0007\u000e\u0000\u0000\u024e\u024f\u0007\n\u0000\u0000"+ - "\u024f\u0250\u0007\u0013\u0000\u0000\u0250\u0251\u0007\n\u0000\u0000\u0251"+ - "\u0252\u0007\u000b\u0000\u0000\u0252\u0253\u0001\u0000\u0000\u0000\u0253"+ - "\u0254\u0006\t\u0004\u0000\u0254#\u0001\u0000\u0000\u0000\u0255\u0256"+ - "\u0007\f\u0000\u0000\u0256\u0257\u0007\t\u0000\u0000\u0257\u0258\u0007"+ - "\u0014\u0000\u0000\u0258\u0259\u0001\u0000\u0000\u0000\u0259\u025a\u0006"+ - "\n\u0004\u0000\u025a%\u0001\u0000\u0000\u0000\u025b\u025c\u0007\u0010"+ - "\u0000\u0000\u025c\u025d\u0007\t\u0000\u0000\u025d\u025e\u0007\f\u0000"+ - "\u0000\u025e\u025f\u0007\u000b\u0000\u0000\u025f\u0260\u0001\u0000\u0000"+ - "\u0000\u0260\u0261\u0006\u000b\u0004\u0000\u0261\'\u0001\u0000\u0000\u0000"+ - "\u0262\u0263\u0007\u0010\u0000\u0000\u0263\u0264\u0007\u000b\u0000\u0000"+ - "\u0264\u0265\u0007\u0004\u0000\u0000\u0265\u0266\u0007\u000b\u0000\u0000"+ - "\u0266\u0267\u0007\u0010\u0000\u0000\u0267\u0268\u0001\u0000\u0000\u0000"+ - "\u0268\u0269\u0006\f\u0004\u0000\u0269)\u0001\u0000\u0000\u0000\u026a"+ - "\u026b\u0007\u0014\u0000\u0000\u026b\u026c\u0007\u0003\u0000\u0000\u026c"+ - "\u026d\u0007\u0007\u0000\u0000\u026d\u026e\u0007\f\u0000\u0000\u026e\u026f"+ - "\u0007\u0007\u0000\u0000\u026f\u0270\u0001\u0000\u0000\u0000\u0270\u0271"+ - "\u0006\r\u0004\u0000\u0271+\u0001\u0000\u0000\u0000\u0272\u0273\u0004"+ - "\u000e\u0000\u0000\u0273\u0274\u0007\u0002\u0000\u0000\u0274\u0275\u0007"+ - "\t\u0000\u0000\u0275\u0276\u0007\u0013\u0000\u0000\u0276\u0277\u0007\b"+ - "\u0000\u0000\u0277\u0278\u0007\u000e\u0000\u0000\u0278\u0279\u0007\u0007"+ - "\u0000\u0000\u0279\u027a\u0007\u000b\u0000\u0000\u027a\u027b\u0007\n\u0000"+ - "\u0000\u027b\u027c\u0007\t\u0000\u0000\u027c\u027d\u0007\u0005\u0000\u0000"+ - "\u027d\u027e\u0001\u0000\u0000\u0000\u027e\u027f\u0006\u000e\u0004\u0000"+ - "\u027f-\u0001\u0000\u0000\u0000\u0280\u0281\u0004\u000f\u0001\u0000\u0281"+ - "\u0282\u0007\n\u0000\u0000\u0282\u0283\u0007\u0005\u0000\u0000\u0283\u0284"+ - "\u0007\u000e\u0000\u0000\u0284\u0285\u0007\n\u0000\u0000\u0285\u0286\u0007"+ - "\u0005\u0000\u0000\u0286\u0287\u0007\u0007\u0000\u0000\u0287\u0288\u0007"+ - "\u0010\u0000\u0000\u0288\u0289\u0007\u000b\u0000\u0000\u0289\u028a\u0007"+ - "\u0004\u0000\u0000\u028a\u028b\u0007\u000b\u0000\u0000\u028b\u028c\u0007"+ - "\u0010\u0000\u0000\u028c\u028d\u0001\u0000\u0000\u0000\u028d\u028e\u0006"+ - "\u000f\u0004\u0000\u028e/\u0001\u0000\u0000\u0000\u028f\u0290\u0004\u0010"+ - "\u0002\u0000\u0290\u0291\u0007\f\u0000\u0000\u0291\u0292\u0007\u0007\u0000"+ - "\u0000\u0292\u0293\u0007\f\u0000\u0000\u0293\u0294\u0007\u0004\u0000\u0000"+ - "\u0294\u0295\u0007\u0005\u0000\u0000\u0295\u0296\u0007\u0012\u0000\u0000"+ - "\u0296\u0297\u0001\u0000\u0000\u0000\u0297\u0298\u0006\u0010\u0004\u0000"+ - "\u02981\u0001\u0000\u0000\u0000\u0299\u029a\u0004\u0011\u0003\u0000\u029a"+ - "\u029b\u0007\u0010\u0000\u0000\u029b\u029c\u0007\u0004\u0000\u0000\u029c"+ - "\u029d\u0007\u0013\u0000\u0000\u029d\u029e\u0007\b\u0000\u0000\u029e\u029f"+ - "\u0007\u000e\u0000\u0000\u029f\u02a0\u0007\u0007\u0000\u0000\u02a0\u02a1"+ - "\u0001\u0000\u0000\u0000\u02a1\u02a2\u0006\u0011\u0004\u0000\u02a23\u0001"+ - "\u0000\u0000\u0000\u02a3\u02a4\u0007\u0015\u0000\u0000\u02a4\u02a5\u0007"+ - "\f\u0000\u0000\u02a5\u02a6\u0007\t\u0000\u0000\u02a6\u02a7\u0007\u0013"+ - "\u0000\u0000\u02a7\u02a8\u0001\u0000\u0000\u0000\u02a8\u02a9\u0006\u0012"+ - "\u0005\u0000\u02a95\u0001\u0000\u0000\u0000\u02aa\u02ab\u0004\u0013\u0004"+ - "\u0000\u02ab\u02ac\u0007\u000b\u0000\u0000\u02ac\u02ad\u0007\u0010\u0000"+ - "\u0000\u02ad\u02ae\u0001\u0000\u0000\u0000\u02ae\u02af\u0006\u0013\u0005"+ - "\u0000\u02af7\u0001\u0000\u0000\u0000\u02b0\u02b1\u0004\u0014\u0005\u0000"+ - "\u02b1\u02b2\u0007\u0015\u0000\u0000\u02b2\u02b3\u0007\t\u0000\u0000\u02b3"+ - "\u02b4\u0007\f\u0000\u0000\u02b4\u02b5\u0007\u0012\u0000\u0000\u02b5\u02b6"+ - "\u0001\u0000\u0000\u0000\u02b6\u02b7\u0006\u0014\u0006\u0000\u02b79\u0001"+ - "\u0000\u0000\u0000\u02b8\u02b9\u0007\u000e\u0000\u0000\u02b9\u02ba\u0007"+ - "\t\u0000\u0000\u02ba\u02bb\u0007\t\u0000\u0000\u02bb\u02bc\u0007\u0012"+ - "\u0000\u0000\u02bc\u02bd\u0007\u0016\u0000\u0000\u02bd\u02be\u0007\b\u0000"+ - "\u0000\u02be\u02bf\u0001\u0000\u0000\u0000\u02bf\u02c0\u0006\u0015\u0007"+ - "\u0000\u02c0;\u0001\u0000\u0000\u0000\u02c1\u02c2\u0004\u0016\u0006\u0000"+ - "\u02c2\u02c3\u0007\u0015\u0000\u0000\u02c3\u02c4\u0007\u0016\u0000\u0000"+ - "\u02c4\u02c5\u0007\u000e\u0000\u0000\u02c5\u02c6\u0007\u000e\u0000\u0000"+ - "\u02c6\u02c7\u0001\u0000\u0000\u0000\u02c7\u02c8\u0006\u0016\u0007\u0000"+ - "\u02c8=\u0001\u0000\u0000\u0000\u02c9\u02ca\u0004\u0017\u0007\u0000\u02ca"+ - "\u02cb\u0007\u000e\u0000\u0000\u02cb\u02cc\u0007\u0007\u0000\u0000\u02cc"+ - "\u02cd\u0007\u0015\u0000\u0000\u02cd\u02ce\u0007\u000b\u0000\u0000\u02ce"+ - "\u02cf\u0001\u0000\u0000\u0000\u02cf\u02d0\u0006\u0017\u0007\u0000\u02d0"+ - "?\u0001\u0000\u0000\u0000\u02d1\u02d2\u0004\u0018\b\u0000\u02d2\u02d3"+ - "\u0007\f\u0000\u0000\u02d3\u02d4\u0007\n\u0000\u0000\u02d4\u02d5\u0007"+ - "\u0006\u0000\u0000\u02d5\u02d6\u0007\u0003\u0000\u0000\u02d6\u02d7\u0007"+ - "\u000b\u0000\u0000\u02d7\u02d8\u0001\u0000\u0000\u0000\u02d8\u02d9\u0006"+ - "\u0018\u0007\u0000\u02d9A\u0001\u0000\u0000\u0000\u02da\u02db\u0004\u0019"+ - "\t\u0000\u02db\u02dc\u0007\u000e\u0000\u0000\u02dc\u02dd\u0007\t\u0000"+ - "\u0000\u02dd\u02de\u0007\t\u0000\u0000\u02de\u02df\u0007\u0012\u0000\u0000"+ - "\u02df\u02e0\u0007\u0016\u0000\u0000\u02e0\u02e1\u0007\b\u0000\u0000\u02e1"+ - "\u02e2\u0005_\u0000\u0000\u02e2\u02e3\u0005\u8001\uf414\u0000\u0000\u02e3"+ - "\u02e4\u0001\u0000\u0000\u0000\u02e4\u02e5\u0006\u0019\b\u0000\u02e5C"+ - "\u0001\u0000\u0000\u0000\u02e6\u02e7\u0007\u0013\u0000\u0000\u02e7\u02e8"+ - "\u0007\u0011\u0000\u0000\u02e8\u02e9\u0005_\u0000\u0000\u02e9\u02ea\u0007"+ - "\u0007\u0000\u0000\u02ea\u02eb\u0007\r\u0000\u0000\u02eb\u02ec\u0007\b"+ - "\u0000\u0000\u02ec\u02ed\u0007\u0004\u0000\u0000\u02ed\u02ee\u0007\u0005"+ - "\u0000\u0000\u02ee\u02ef\u0007\u000f\u0000\u0000\u02ef\u02f0\u0001\u0000"+ - "\u0000\u0000\u02f0\u02f1\u0006\u001a\t\u0000\u02f1E\u0001\u0000\u0000"+ - "\u0000\u02f2\u02f3\u0007\u000f\u0000\u0000\u02f3\u02f4\u0007\f\u0000\u0000"+ - "\u02f4\u02f5\u0007\t\u0000\u0000\u02f5\u02f6\u0007\b\u0000\u0000\u02f6"+ - "\u02f7\u0001\u0000\u0000\u0000\u02f7\u02f8\u0006\u001b\n\u0000\u02f8G"+ - "\u0001\u0000\u0000\u0000\u02f9\u02fa\u0007\u0012\u0000\u0000\u02fa\u02fb"+ - "\u0007\u0007\u0000\u0000\u02fb\u02fc\u0007\u0007\u0000\u0000\u02fc\u02fd"+ - "\u0007\b\u0000\u0000\u02fd\u02fe\u0001\u0000\u0000\u0000\u02fe\u02ff\u0006"+ - "\u001c\n\u0000\u02ffI\u0001\u0000\u0000\u0000\u0300\u0301\u0004\u001d"+ - "\n\u0000\u0301\u0302\u0007\n\u0000\u0000\u0302\u0303\u0007\u0005\u0000"+ - "\u0000\u0303\u0304\u0007\u0010\u0000\u0000\u0304\u0305\u0007\n\u0000\u0000"+ - "\u0305\u0306\u0007\u0010\u0000\u0000\u0306\u0307\u0007\u000b\u0000\u0000"+ - "\u0307\u0308\u0005_\u0000\u0000\u0308\u0309\u0005\u8001\uf414\u0000\u0000"+ - "\u0309\u030a\u0001\u0000\u0000\u0000\u030a\u030b\u0006\u001d\n\u0000\u030b"+ - "K\u0001\u0000\u0000\u0000\u030c\u030d\u0004\u001e\u000b\u0000\u030d\u030e"+ - "\u0007\f\u0000\u0000\u030e\u030f\u0007\f\u0000\u0000\u030f\u0310\u0007"+ - "\u0015\u0000\u0000\u0310\u0311\u0001\u0000\u0000\u0000\u0311\u0312\u0006"+ - "\u001e\u0004\u0000\u0312M\u0001\u0000\u0000\u0000\u0313\u0314\u0007\f"+ - "\u0000\u0000\u0314\u0315\u0007\u0007\u0000\u0000\u0315\u0316\u0007\u0005"+ - "\u0000\u0000\u0316\u0317\u0007\u0004\u0000\u0000\u0317\u0318\u0007\u0013"+ - "\u0000\u0000\u0318\u0319\u0007\u0007\u0000\u0000\u0319\u031a\u0001\u0000"+ - "\u0000\u0000\u031a\u031b\u0006\u001f\u000b\u0000\u031bO\u0001\u0000\u0000"+ - "\u0000\u031c\u031d\u0007\u0010\u0000\u0000\u031d\u031e\u0007\u0003\u0000"+ - "\u0000\u031e\u031f\u0007\t\u0000\u0000\u031f\u0320\u0007\u0014\u0000\u0000"+ - "\u0320\u0321\u0001\u0000\u0000\u0000\u0321\u0322\u0006 \f\u0000\u0322"+ - "Q\u0001\u0000\u0000\u0000\u0323\u0325\b\u0017\u0000\u0000\u0324\u0323"+ - "\u0001\u0000\u0000\u0000\u0325\u0326\u0001\u0000\u0000\u0000\u0326\u0324"+ - "\u0001\u0000\u0000\u0000\u0326\u0327\u0001\u0000\u0000\u0000\u0327\u0328"+ - "\u0001\u0000\u0000\u0000\u0328\u0329\u0006!\u0004\u0000\u0329S\u0001\u0000"+ - "\u0000\u0000\u032a\u032b\u0003\u00aeO\u0000\u032b\u032c\u0001\u0000\u0000"+ - "\u0000\u032c\u032d\u0006\"\r\u0000\u032d\u032e\u0006\"\u000e\u0000\u032e"+ - "U\u0001\u0000\u0000\u0000\u032f\u0330\u0003\u00f0p\u0000\u0330\u0331\u0001"+ - "\u0000\u0000\u0000\u0331\u0332\u0006#\u000f\u0000\u0332W\u0001\u0000\u0000"+ - "\u0000\u0333\u0334\u0003\u00cc^\u0000\u0334\u0335\u0001\u0000\u0000\u0000"+ - "\u0335\u0336\u0006$\u0010\u0000\u0336Y\u0001\u0000\u0000\u0000\u0337\u0338"+ - "\u0003\u00dcf\u0000\u0338\u0339\u0001\u0000\u0000\u0000\u0339\u033a\u0006"+ - "%\u0011\u0000\u033a[\u0001\u0000\u0000\u0000\u033b\u033c\u0003\u00d8d"+ - "\u0000\u033c\u033d\u0001\u0000\u0000\u0000\u033d\u033e\u0006&\u0012\u0000"+ - "\u033e]\u0001\u0000\u0000\u0000\u033f\u0340\u0003\u012c\u008e\u0000\u0340"+ - "\u0341\u0001\u0000\u0000\u0000\u0341\u0342\u0006\'\u0013\u0000\u0342_"+ - "\u0001\u0000\u0000\u0000\u0343\u0344\u0003\u0128\u008c\u0000\u0344\u0345"+ - "\u0001\u0000\u0000\u0000\u0345\u0346\u0006(\u0014\u0000\u0346a\u0001\u0000"+ - "\u0000\u0000\u0347\u0348\u0003\u0010\u0000\u0000\u0348\u0349\u0001\u0000"+ - "\u0000\u0000\u0349\u034a\u0006)\u0000\u0000\u034ac\u0001\u0000\u0000\u0000"+ - "\u034b\u034c\u0003\u0012\u0001\u0000\u034c\u034d\u0001\u0000\u0000\u0000"+ - "\u034d\u034e\u0006*\u0000\u0000\u034ee\u0001\u0000\u0000\u0000\u034f\u0350"+ - "\u0003\u0014\u0002\u0000\u0350\u0351\u0001\u0000\u0000\u0000\u0351\u0352"+ - "\u0006+\u0000\u0000\u0352g\u0001\u0000\u0000\u0000\u0353\u0354\u0003\u00ae"+ - "O\u0000\u0354\u0355\u0001\u0000\u0000\u0000\u0355\u0356\u0006,\r\u0000"+ - "\u0356\u0357\u0006,\u000e\u0000\u0357i\u0001\u0000\u0000\u0000\u0358\u0359"+ - "\u0003\u0120\u0088\u0000\u0359\u035a\u0001\u0000\u0000\u0000\u035a\u035b"+ - "\u0006-\u0015\u0000\u035b\u035c\u0006-\u0016\u0000\u035ck\u0001\u0000"+ - "\u0000\u0000\u035d\u035e\u0003\u00f0p\u0000\u035e\u035f\u0001\u0000\u0000"+ - "\u0000\u035f\u0360\u0006.\u000f\u0000\u0360\u0361\u0006.\u0017\u0000\u0361"+ - "m\u0001\u0000\u0000\u0000\u0362\u0363\u0003\u00fau\u0000\u0363\u0364\u0001"+ - "\u0000\u0000\u0000\u0364\u0365\u0006/\u0018\u0000\u0365\u0366\u0006/\u0017"+ - "\u0000\u0366o\u0001\u0000\u0000\u0000\u0367\u0368\b\u0018\u0000\u0000"+ - "\u0368q\u0001\u0000\u0000\u0000\u0369\u036b\u0003p0\u0000\u036a\u0369"+ - "\u0001\u0000\u0000\u0000\u036b\u036c\u0001\u0000\u0000\u0000\u036c\u036a"+ - "\u0001\u0000\u0000\u0000\u036c\u036d\u0001\u0000\u0000\u0000\u036d\u036e"+ - "\u0001\u0000\u0000\u0000\u036e\u036f\u0003\u00d6c\u0000\u036f\u0371\u0001"+ - "\u0000\u0000\u0000\u0370\u036a\u0001\u0000\u0000\u0000\u0370\u0371\u0001"+ - "\u0000\u0000\u0000\u0371\u0373\u0001\u0000\u0000\u0000\u0372\u0374\u0003"+ - "p0\u0000\u0373\u0372\u0001\u0000\u0000\u0000\u0374\u0375\u0001\u0000\u0000"+ - "\u0000\u0375\u0373\u0001\u0000\u0000\u0000\u0375\u0376\u0001\u0000\u0000"+ - "\u0000\u0376s\u0001\u0000\u0000\u0000\u0377\u0378\u0003r1\u0000\u0378"+ - "\u0379\u0001\u0000\u0000\u0000\u0379\u037a\u00062\u0019\u0000\u037au\u0001"+ - "\u0000\u0000\u0000\u037b\u037c\u0003\u0010\u0000\u0000\u037c\u037d\u0001"+ - "\u0000\u0000\u0000\u037d\u037e\u00063\u0000\u0000\u037ew\u0001\u0000\u0000"+ - "\u0000\u037f\u0380\u0003\u0012\u0001\u0000\u0380\u0381\u0001\u0000\u0000"+ - "\u0000\u0381\u0382\u00064\u0000\u0000\u0382y\u0001\u0000\u0000\u0000\u0383"+ - "\u0384\u0003\u0014\u0002\u0000\u0384\u0385\u0001\u0000\u0000\u0000\u0385"+ - "\u0386\u00065\u0000\u0000\u0386{\u0001\u0000\u0000\u0000\u0387\u0388\u0003"+ - "\u00aeO\u0000\u0388\u0389\u0001\u0000\u0000\u0000\u0389\u038a\u00066\r"+ - "\u0000\u038a\u038b\u00066\u000e\u0000\u038b\u038c\u00066\u000e\u0000\u038c"+ - "}\u0001\u0000\u0000\u0000\u038d\u038e\u0003\u00d0`\u0000\u038e\u038f\u0001"+ - "\u0000\u0000\u0000\u038f\u0390\u00067\u001a\u0000\u0390\u007f\u0001\u0000"+ - "\u0000\u0000\u0391\u0392\u0003\u00d8d\u0000\u0392\u0393\u0001\u0000\u0000"+ - "\u0000\u0393\u0394\u00068\u0012\u0000\u0394\u0081\u0001\u0000\u0000\u0000"+ - "\u0395\u0396\u0003\u00dcf\u0000\u0396\u0397\u0001\u0000\u0000\u0000\u0397"+ - "\u0398\u00069\u0011\u0000\u0398\u0083\u0001\u0000\u0000\u0000\u0399\u039a"+ - "\u0003\u00fau\u0000\u039a\u039b\u0001\u0000\u0000\u0000\u039b\u039c\u0006"+ - ":\u0018\u0000\u039c\u0085\u0001\u0000\u0000\u0000\u039d\u039e\u0003\u01c0"+ - "\u00d8\u0000\u039e\u039f\u0001\u0000\u0000\u0000\u039f\u03a0\u0006;\u001b"+ - "\u0000\u03a0\u0087\u0001\u0000\u0000\u0000\u03a1\u03a2\u0003\u012c\u008e"+ - "\u0000\u03a2\u03a3\u0001\u0000\u0000\u0000\u03a3\u03a4\u0006<\u0013\u0000"+ - "\u03a4\u0089\u0001\u0000\u0000\u0000\u03a5\u03a6\u0003\u00f4r\u0000\u03a6"+ - "\u03a7\u0001\u0000\u0000\u0000\u03a7\u03a8\u0006=\u001c\u0000\u03a8\u008b"+ - "\u0001\u0000\u0000\u0000\u03a9\u03aa\u0003\u011c\u0086\u0000\u03aa\u03ab"+ - "\u0001\u0000\u0000\u0000\u03ab\u03ac\u0006>\u001d\u0000\u03ac\u008d\u0001"+ - "\u0000\u0000\u0000\u03ad\u03ae\u0003\u0118\u0084\u0000\u03ae\u03af\u0001"+ - "\u0000\u0000\u0000\u03af\u03b0\u0006?\u001e\u0000\u03b0\u008f\u0001\u0000"+ - "\u0000\u0000\u03b1\u03b2\u0003\u011e\u0087\u0000\u03b2\u03b3\u0001\u0000"+ - "\u0000\u0000\u03b3\u03b4\u0006@\u001f\u0000\u03b4\u0091\u0001\u0000\u0000"+ - "\u0000\u03b5\u03b6\u0003\u0010\u0000\u0000\u03b6\u03b7\u0001\u0000\u0000"+ - "\u0000\u03b7\u03b8\u0006A\u0000\u0000\u03b8\u0093\u0001\u0000\u0000\u0000"+ - "\u03b9\u03ba\u0003\u0012\u0001\u0000\u03ba\u03bb\u0001\u0000\u0000\u0000"+ - "\u03bb\u03bc\u0006B\u0000\u0000\u03bc\u0095\u0001\u0000\u0000\u0000\u03bd"+ - "\u03be\u0003\u0014\u0002\u0000\u03be\u03bf\u0001\u0000\u0000\u0000\u03bf"+ - "\u03c0\u0006C\u0000\u0000\u03c0\u0097\u0001\u0000\u0000\u0000\u03c1\u03c2"+ - "\u0003\u0122\u0089\u0000\u03c2\u03c3\u0001\u0000\u0000\u0000\u03c3\u03c4"+ - "\u0006D \u0000\u03c4\u03c5\u0006D\u000e\u0000\u03c5\u0099\u0001\u0000"+ - "\u0000\u0000\u03c6\u03c7\u0003\u00d6c\u0000\u03c7\u03c8\u0001\u0000\u0000"+ - "\u0000\u03c8\u03c9\u0006E!\u0000\u03c9\u009b\u0001\u0000\u0000\u0000\u03ca"+ - "\u03d0\u0003\u00baU\u0000\u03cb\u03d0\u0003\u00b0P\u0000\u03cc\u03d0\u0003"+ - "\u00dcf\u0000\u03cd\u03d0\u0003\u00b2Q\u0000\u03ce\u03d0\u0003\u00c0X"+ - "\u0000\u03cf\u03ca\u0001\u0000\u0000\u0000\u03cf\u03cb\u0001\u0000\u0000"+ - "\u0000\u03cf\u03cc\u0001\u0000\u0000\u0000\u03cf\u03cd\u0001\u0000\u0000"+ - "\u0000\u03cf\u03ce\u0001\u0000\u0000\u0000\u03d0\u03d1\u0001\u0000\u0000"+ - "\u0000\u03d1\u03cf\u0001\u0000\u0000\u0000\u03d1\u03d2\u0001\u0000\u0000"+ - "\u0000\u03d2\u009d\u0001\u0000\u0000\u0000\u03d3\u03d4\u0003\u0010\u0000"+ - "\u0000\u03d4\u03d5\u0001\u0000\u0000\u0000\u03d5\u03d6\u0006G\u0000\u0000"+ - "\u03d6\u009f\u0001\u0000\u0000\u0000\u03d7\u03d8\u0003\u0012\u0001\u0000"+ - "\u03d8\u03d9\u0001\u0000\u0000\u0000\u03d9\u03da\u0006H\u0000\u0000\u03da"+ - "\u00a1\u0001\u0000\u0000\u0000\u03db\u03dc\u0003\u0014\u0002\u0000\u03dc"+ - "\u03dd\u0001\u0000\u0000\u0000\u03dd\u03de\u0006I\u0000\u0000\u03de\u00a3"+ - "\u0001\u0000\u0000\u0000\u03df\u03e0\u0003\u0120\u0088\u0000\u03e0\u03e1"+ - "\u0001\u0000\u0000\u0000\u03e1\u03e2\u0006J\u0015\u0000\u03e2\u03e3\u0006"+ - "J\"\u0000\u03e3\u00a5\u0001\u0000\u0000\u0000\u03e4\u03e5\u0003\u00ae"+ - "O\u0000\u03e5\u03e6\u0001\u0000\u0000\u0000\u03e6\u03e7\u0006K\r\u0000"+ - "\u03e7\u03e8\u0006K\u000e\u0000\u03e8\u00a7\u0001\u0000\u0000\u0000\u03e9"+ - "\u03ea\u0003\u0014\u0002\u0000\u03ea\u03eb\u0001\u0000\u0000\u0000\u03eb"+ - "\u03ec\u0006L\u0000\u0000\u03ec\u00a9\u0001\u0000\u0000\u0000\u03ed\u03ee"+ - "\u0003\u0010\u0000\u0000\u03ee\u03ef\u0001\u0000\u0000\u0000\u03ef\u03f0"+ - "\u0006M\u0000\u0000\u03f0\u00ab\u0001\u0000\u0000\u0000\u03f1\u03f2\u0003"+ - "\u0012\u0001\u0000\u03f2\u03f3\u0001\u0000\u0000\u0000\u03f3\u03f4\u0006"+ - "N\u0000\u0000\u03f4\u00ad\u0001\u0000\u0000\u0000\u03f5\u03f6\u0005|\u0000"+ - "\u0000\u03f6\u03f7\u0001\u0000\u0000\u0000\u03f7\u03f8\u0006O\u000e\u0000"+ - "\u03f8\u00af\u0001\u0000\u0000\u0000\u03f9\u03fa\u0007\u0019\u0000\u0000"+ - "\u03fa\u00b1\u0001\u0000\u0000\u0000\u03fb\u03fc\u0007\u001a\u0000\u0000"+ - "\u03fc\u00b3\u0001\u0000\u0000\u0000\u03fd\u03fe\u0005\\\u0000\u0000\u03fe"+ - "\u03ff\u0007\u001b\u0000\u0000\u03ff\u00b5\u0001\u0000\u0000\u0000\u0400"+ - "\u0401\b\u001c\u0000\u0000\u0401\u00b7\u0001\u0000\u0000\u0000\u0402\u0404"+ - "\u0007\u0007\u0000\u0000\u0403\u0405\u0007\u001d\u0000\u0000\u0404\u0403"+ - "\u0001\u0000\u0000\u0000\u0404\u0405\u0001\u0000\u0000\u0000\u0405\u0407"+ - "\u0001\u0000\u0000\u0000\u0406\u0408\u0003\u00b0P\u0000\u0407\u0406\u0001"+ - "\u0000\u0000\u0000\u0408\u0409\u0001\u0000\u0000\u0000\u0409\u0407\u0001"+ - "\u0000\u0000\u0000\u0409\u040a\u0001\u0000\u0000\u0000\u040a\u00b9\u0001"+ - "\u0000\u0000\u0000\u040b\u040c\u0005@\u0000\u0000\u040c\u00bb\u0001\u0000"+ - "\u0000\u0000\u040d\u040e\u0005`\u0000\u0000\u040e\u00bd\u0001\u0000\u0000"+ - "\u0000\u040f\u0413\b\u001e\u0000\u0000\u0410\u0411\u0005`\u0000\u0000"+ - "\u0411\u0413\u0005`\u0000\u0000\u0412\u040f\u0001\u0000\u0000\u0000\u0412"+ - "\u0410\u0001\u0000\u0000\u0000\u0413\u00bf\u0001\u0000\u0000\u0000\u0414"+ - "\u0415\u0005_\u0000\u0000\u0415\u00c1\u0001\u0000\u0000\u0000\u0416\u041a"+ - "\u0003\u00b2Q\u0000\u0417\u041a\u0003\u00b0P\u0000\u0418\u041a\u0003\u00c0"+ - "X\u0000\u0419\u0416\u0001\u0000\u0000\u0000\u0419\u0417\u0001\u0000\u0000"+ - "\u0000\u0419\u0418\u0001\u0000\u0000\u0000\u041a\u00c3\u0001\u0000\u0000"+ - "\u0000\u041b\u0420\u0005\"\u0000\u0000\u041c\u041f\u0003\u00b4R\u0000"+ - "\u041d\u041f\u0003\u00b6S\u0000\u041e\u041c\u0001\u0000\u0000\u0000\u041e"+ - "\u041d\u0001\u0000\u0000\u0000\u041f\u0422\u0001\u0000\u0000\u0000\u0420"+ - "\u041e\u0001\u0000\u0000\u0000\u0420\u0421\u0001\u0000\u0000\u0000\u0421"+ - "\u0423\u0001\u0000\u0000\u0000\u0422\u0420\u0001\u0000\u0000\u0000\u0423"+ - "\u0439\u0005\"\u0000\u0000\u0424\u0425\u0005\"\u0000\u0000\u0425\u0426"+ - "\u0005\"\u0000\u0000\u0426\u0427\u0005\"\u0000\u0000\u0427\u042b\u0001"+ - "\u0000\u0000\u0000\u0428\u042a\b\u0000\u0000\u0000\u0429\u0428\u0001\u0000"+ - "\u0000\u0000\u042a\u042d\u0001\u0000\u0000\u0000\u042b\u042c\u0001\u0000"+ - "\u0000\u0000\u042b\u0429\u0001\u0000\u0000\u0000\u042c\u042e\u0001\u0000"+ - "\u0000\u0000\u042d\u042b\u0001\u0000\u0000\u0000\u042e\u042f\u0005\"\u0000"+ - "\u0000\u042f\u0430\u0005\"\u0000\u0000\u0430\u0431\u0005\"\u0000\u0000"+ - "\u0431\u0433\u0001\u0000\u0000\u0000\u0432\u0434\u0005\"\u0000\u0000\u0433"+ - "\u0432\u0001\u0000\u0000\u0000\u0433\u0434\u0001\u0000\u0000\u0000\u0434"+ - "\u0436\u0001\u0000\u0000\u0000\u0435\u0437\u0005\"\u0000\u0000\u0436\u0435"+ - "\u0001\u0000\u0000\u0000\u0436\u0437\u0001\u0000\u0000\u0000\u0437\u0439"+ - "\u0001\u0000\u0000\u0000\u0438\u041b\u0001\u0000\u0000\u0000\u0438\u0424"+ - "\u0001\u0000\u0000\u0000\u0439\u00c5\u0001\u0000\u0000\u0000\u043a\u043c"+ - "\u0003\u00b0P\u0000\u043b\u043a\u0001\u0000\u0000\u0000\u043c\u043d\u0001"+ - "\u0000\u0000\u0000\u043d\u043b\u0001\u0000\u0000\u0000\u043d\u043e\u0001"+ - "\u0000\u0000\u0000\u043e\u00c7\u0001\u0000\u0000\u0000\u043f\u0441\u0003"+ - "\u00b0P\u0000\u0440\u043f\u0001\u0000\u0000\u0000\u0441\u0442\u0001\u0000"+ - "\u0000\u0000\u0442\u0440\u0001\u0000\u0000\u0000\u0442\u0443\u0001\u0000"+ - "\u0000\u0000\u0443\u0444\u0001\u0000\u0000\u0000\u0444\u0448\u0003\u00dc"+ - "f\u0000\u0445\u0447\u0003\u00b0P\u0000\u0446\u0445\u0001\u0000\u0000\u0000"+ - "\u0447\u044a\u0001\u0000\u0000\u0000\u0448\u0446\u0001\u0000\u0000\u0000"+ - "\u0448\u0449\u0001\u0000\u0000\u0000\u0449\u046a\u0001\u0000\u0000\u0000"+ - "\u044a\u0448\u0001\u0000\u0000\u0000\u044b\u044d\u0003\u00dcf\u0000\u044c"+ - "\u044e\u0003\u00b0P\u0000\u044d\u044c\u0001\u0000\u0000\u0000\u044e\u044f"+ - "\u0001\u0000\u0000\u0000\u044f\u044d\u0001\u0000\u0000\u0000\u044f\u0450"+ - "\u0001\u0000\u0000\u0000\u0450\u046a\u0001\u0000\u0000\u0000\u0451\u0453"+ - "\u0003\u00b0P\u0000\u0452\u0451\u0001\u0000\u0000\u0000\u0453\u0454\u0001"+ - "\u0000\u0000\u0000\u0454\u0452\u0001\u0000\u0000\u0000\u0454\u0455\u0001"+ - "\u0000\u0000\u0000\u0455\u045d\u0001\u0000\u0000\u0000\u0456\u045a\u0003"+ - "\u00dcf\u0000\u0457\u0459\u0003\u00b0P\u0000\u0458\u0457\u0001\u0000\u0000"+ - "\u0000\u0459\u045c\u0001\u0000\u0000\u0000\u045a\u0458\u0001\u0000\u0000"+ - "\u0000\u045a\u045b\u0001\u0000\u0000\u0000\u045b\u045e\u0001\u0000\u0000"+ - "\u0000\u045c\u045a\u0001\u0000\u0000\u0000\u045d\u0456\u0001\u0000\u0000"+ - "\u0000\u045d\u045e\u0001\u0000\u0000\u0000\u045e\u045f\u0001\u0000\u0000"+ - "\u0000\u045f\u0460\u0003\u00b8T\u0000\u0460\u046a\u0001\u0000\u0000\u0000"+ - "\u0461\u0463\u0003\u00dcf\u0000\u0462\u0464\u0003\u00b0P\u0000\u0463\u0462"+ - "\u0001\u0000\u0000\u0000\u0464\u0465\u0001\u0000\u0000\u0000\u0465\u0463"+ - "\u0001\u0000\u0000\u0000\u0465\u0466\u0001\u0000\u0000\u0000\u0466\u0467"+ - "\u0001\u0000\u0000\u0000\u0467\u0468\u0003\u00b8T\u0000\u0468\u046a\u0001"+ - "\u0000\u0000\u0000\u0469\u0440\u0001\u0000\u0000\u0000\u0469\u044b\u0001"+ - "\u0000\u0000\u0000\u0469\u0452\u0001\u0000\u0000\u0000\u0469\u0461\u0001"+ - "\u0000\u0000\u0000\u046a\u00c9\u0001\u0000\u0000\u0000\u046b\u046c\u0007"+ - "\u0004\u0000\u0000\u046c\u046d\u0007\u0005\u0000\u0000\u046d\u046e\u0007"+ - "\u000f\u0000\u0000\u046e\u00cb\u0001\u0000\u0000\u0000\u046f\u0470\u0007"+ - "\u0004\u0000\u0000\u0470\u0471\u0007\u0010\u0000\u0000\u0471\u00cd\u0001"+ - "\u0000\u0000\u0000\u0472\u0473\u0007\u0004\u0000\u0000\u0473\u0474\u0007"+ - "\u0010\u0000\u0000\u0474\u0475\u0007\u0002\u0000\u0000\u0475\u00cf\u0001"+ - "\u0000\u0000\u0000\u0476\u0477\u0005=\u0000\u0000\u0477\u00d1\u0001\u0000"+ - "\u0000\u0000\u0478\u0479\u0007\u001f\u0000\u0000\u0479\u047a\u0007 \u0000"+ - "\u0000\u047a\u00d3\u0001\u0000\u0000\u0000\u047b\u047c\u0005:\u0000\u0000"+ - "\u047c\u047d\u0005:\u0000\u0000\u047d\u00d5\u0001\u0000\u0000\u0000\u047e"+ - "\u047f\u0005:\u0000\u0000\u047f\u00d7\u0001\u0000\u0000\u0000\u0480\u0481"+ - "\u0005,\u0000\u0000\u0481\u00d9\u0001\u0000\u0000\u0000\u0482\u0483\u0007"+ - "\u000f\u0000\u0000\u0483\u0484\u0007\u0007\u0000\u0000\u0484\u0485\u0007"+ - "\u0010\u0000\u0000\u0485\u0486\u0007\u0002\u0000\u0000\u0486\u00db\u0001"+ - "\u0000\u0000\u0000\u0487\u0488\u0005.\u0000\u0000\u0488\u00dd\u0001\u0000"+ - "\u0000\u0000\u0489\u048a\u0007\u0015\u0000\u0000\u048a\u048b\u0007\u0004"+ - "\u0000\u0000\u048b\u048c\u0007\u000e\u0000\u0000\u048c\u048d\u0007\u0010"+ - "\u0000\u0000\u048d\u048e\u0007\u0007\u0000\u0000\u048e\u00df\u0001\u0000"+ - "\u0000\u0000\u048f\u0490\u0007\u0015\u0000\u0000\u0490\u0491\u0007\n\u0000"+ - "\u0000\u0491\u0492\u0007\f\u0000\u0000\u0492\u0493\u0007\u0010\u0000\u0000"+ - "\u0493\u0494\u0007\u000b\u0000\u0000\u0494\u00e1\u0001\u0000\u0000\u0000"+ - "\u0495\u0496\u0007\n\u0000\u0000\u0496\u0497\u0007\u0005\u0000\u0000\u0497"+ - "\u00e3\u0001\u0000\u0000\u0000\u0498\u0499\u0007\n\u0000\u0000\u0499\u049a"+ - "\u0007\u0010\u0000\u0000\u049a\u00e5\u0001\u0000\u0000\u0000\u049b\u049c"+ - "\u0007\u000e\u0000\u0000\u049c\u049d\u0007\u0004\u0000\u0000\u049d\u049e"+ - "\u0007\u0010\u0000\u0000\u049e\u049f\u0007\u000b\u0000\u0000\u049f\u00e7"+ - "\u0001\u0000\u0000\u0000\u04a0\u04a1\u0007\u000e\u0000\u0000\u04a1\u04a2"+ - "\u0007\n\u0000\u0000\u04a2\u04a3\u0007\u0012\u0000\u0000\u04a3\u04a4\u0007"+ - "\u0007\u0000\u0000\u04a4\u00e9\u0001\u0000\u0000\u0000\u04a5\u04a6\u0007"+ - "\u0005\u0000\u0000\u04a6\u04a7\u0007\t\u0000\u0000\u04a7\u04a8\u0007\u000b"+ - "\u0000\u0000\u04a8\u00eb\u0001\u0000\u0000\u0000\u04a9\u04aa\u0007\u0005"+ - "\u0000\u0000\u04aa\u04ab\u0007\u0016\u0000\u0000\u04ab\u04ac\u0007\u000e"+ - "\u0000\u0000\u04ac\u04ad\u0007\u000e\u0000\u0000\u04ad\u00ed\u0001\u0000"+ - "\u0000\u0000\u04ae\u04af\u0007\u0005\u0000\u0000\u04af\u04b0\u0007\u0016"+ - "\u0000\u0000\u04b0\u04b1\u0007\u000e\u0000\u0000\u04b1\u04b2\u0007\u000e"+ - "\u0000\u0000\u04b2\u04b3\u0007\u0010\u0000\u0000\u04b3\u00ef\u0001\u0000"+ - "\u0000\u0000\u04b4\u04b5\u0007\t\u0000\u0000\u04b5\u04b6\u0007\u0005\u0000"+ - "\u0000\u04b6\u00f1\u0001\u0000\u0000\u0000\u04b7\u04b8\u0007\t\u0000\u0000"+ - "\u04b8\u04b9\u0007\f\u0000\u0000\u04b9\u00f3\u0001\u0000\u0000\u0000\u04ba"+ - "\u04bb\u0005?\u0000\u0000\u04bb\u00f5\u0001\u0000\u0000\u0000\u04bc\u04bd"+ - "\u0007\f\u0000\u0000\u04bd\u04be\u0007\u000e\u0000\u0000\u04be\u04bf\u0007"+ - "\n\u0000\u0000\u04bf\u04c0\u0007\u0012\u0000\u0000\u04c0\u04c1\u0007\u0007"+ - "\u0000\u0000\u04c1\u00f7\u0001\u0000\u0000\u0000\u04c2\u04c3\u0007\u000b"+ - "\u0000\u0000\u04c3\u04c4\u0007\f\u0000\u0000\u04c4\u04c5\u0007\u0016\u0000"+ - "\u0000\u04c5\u04c6\u0007\u0007\u0000\u0000\u04c6\u00f9\u0001\u0000\u0000"+ - "\u0000\u04c7\u04c8\u0007\u0014\u0000\u0000\u04c8\u04c9\u0007\n\u0000\u0000"+ - "\u04c9\u04ca\u0007\u000b\u0000\u0000\u04ca\u04cb\u0007\u0003\u0000\u0000"+ - "\u04cb\u00fb\u0001\u0000\u0000\u0000\u04cc\u04cd\u0005=\u0000\u0000\u04cd"+ - "\u04ce\u0005=\u0000\u0000\u04ce\u00fd\u0001\u0000\u0000\u0000\u04cf\u04d0"+ - "\u0005=\u0000\u0000\u04d0\u04d1\u0005~\u0000\u0000\u04d1\u00ff\u0001\u0000"+ - "\u0000\u0000\u04d2\u04d3\u0005!\u0000\u0000\u04d3\u04d4\u0005=\u0000\u0000"+ - "\u04d4\u0101\u0001\u0000\u0000\u0000\u04d5\u04d6\u0005<\u0000\u0000\u04d6"+ - "\u0103\u0001\u0000\u0000\u0000\u04d7\u04d8\u0005<\u0000\u0000\u04d8\u04d9"+ - "\u0005=\u0000\u0000\u04d9\u0105\u0001\u0000\u0000\u0000\u04da\u04db\u0005"+ - ">\u0000\u0000\u04db\u0107\u0001\u0000\u0000\u0000\u04dc\u04dd\u0005>\u0000"+ - "\u0000\u04dd\u04de\u0005=\u0000\u0000\u04de\u0109\u0001\u0000\u0000\u0000"+ - "\u04df\u04e0\u0005+\u0000\u0000\u04e0\u010b\u0001\u0000\u0000\u0000\u04e1"+ - "\u04e2\u0005-\u0000\u0000\u04e2\u010d\u0001\u0000\u0000\u0000\u04e3\u04e4"+ - "\u0005*\u0000\u0000\u04e4\u010f\u0001\u0000\u0000\u0000\u04e5\u04e6\u0005"+ - "/\u0000\u0000\u04e6\u0111\u0001\u0000\u0000\u0000\u04e7\u04e8\u0005%\u0000"+ - "\u0000\u04e8\u0113\u0001\u0000\u0000\u0000\u04e9\u04ea\u0005{\u0000\u0000"+ - "\u04ea\u0115\u0001\u0000\u0000\u0000\u04eb\u04ec\u0005}\u0000\u0000\u04ec"+ - "\u0117\u0001\u0000\u0000\u0000\u04ed\u04ee\u0005?\u0000\u0000\u04ee\u04ef"+ - "\u0005?\u0000\u0000\u04ef\u0119\u0001\u0000\u0000\u0000\u04f0\u04f1\u0003"+ - "*\r\u0000\u04f1\u04f2\u0001\u0000\u0000\u0000\u04f2\u04f3\u0006\u0085"+ - "#\u0000\u04f3\u011b\u0001\u0000\u0000\u0000\u04f4\u04f7\u0003\u00f4r\u0000"+ - "\u04f5\u04f8\u0003\u00b2Q\u0000\u04f6\u04f8\u0003\u00c0X\u0000\u04f7\u04f5"+ - "\u0001\u0000\u0000\u0000\u04f7\u04f6\u0001\u0000\u0000\u0000\u04f8\u04fc"+ - "\u0001\u0000\u0000\u0000\u04f9\u04fb\u0003\u00c2Y\u0000\u04fa\u04f9\u0001"+ - "\u0000\u0000\u0000\u04fb\u04fe\u0001\u0000\u0000\u0000\u04fc\u04fa\u0001"+ - "\u0000\u0000\u0000\u04fc\u04fd\u0001\u0000\u0000\u0000\u04fd\u0506\u0001"+ - "\u0000\u0000\u0000\u04fe\u04fc\u0001\u0000\u0000\u0000\u04ff\u0501\u0003"+ - "\u00f4r\u0000\u0500\u0502\u0003\u00b0P\u0000\u0501\u0500\u0001\u0000\u0000"+ - "\u0000\u0502\u0503\u0001\u0000\u0000\u0000\u0503\u0501\u0001\u0000\u0000"+ - "\u0000\u0503\u0504\u0001\u0000\u0000\u0000\u0504\u0506\u0001\u0000\u0000"+ - "\u0000\u0505\u04f4\u0001\u0000\u0000\u0000\u0505\u04ff\u0001\u0000\u0000"+ - "\u0000\u0506\u011d\u0001\u0000\u0000\u0000\u0507\u050a\u0003\u0118\u0084"+ - "\u0000\u0508\u050b\u0003\u00b2Q\u0000\u0509\u050b\u0003\u00c0X\u0000\u050a"+ - "\u0508\u0001\u0000\u0000\u0000\u050a\u0509\u0001\u0000\u0000\u0000\u050b"+ - "\u050f\u0001\u0000\u0000\u0000\u050c\u050e\u0003\u00c2Y\u0000\u050d\u050c"+ - "\u0001\u0000\u0000\u0000\u050e\u0511\u0001\u0000\u0000\u0000\u050f\u050d"+ - "\u0001\u0000\u0000\u0000\u050f\u0510\u0001\u0000\u0000\u0000\u0510\u0519"+ - "\u0001\u0000\u0000\u0000\u0511\u050f\u0001\u0000\u0000\u0000\u0512\u0514"+ - "\u0003\u0118\u0084\u0000\u0513\u0515\u0003\u00b0P\u0000\u0514\u0513\u0001"+ - "\u0000\u0000\u0000\u0515\u0516\u0001\u0000\u0000\u0000\u0516\u0514\u0001"+ - "\u0000\u0000\u0000\u0516\u0517\u0001\u0000\u0000\u0000\u0517\u0519\u0001"+ - "\u0000\u0000\u0000\u0518\u0507\u0001\u0000\u0000\u0000\u0518\u0512\u0001"+ - "\u0000\u0000\u0000\u0519\u011f\u0001\u0000\u0000\u0000\u051a\u051b\u0005"+ - "[\u0000\u0000\u051b\u051c\u0001\u0000\u0000\u0000\u051c\u051d\u0006\u0088"+ - "\u0004\u0000\u051d\u051e\u0006\u0088\u0004\u0000\u051e\u0121\u0001\u0000"+ - "\u0000\u0000\u051f\u0520\u0005]\u0000\u0000\u0520\u0521\u0001\u0000\u0000"+ - "\u0000\u0521\u0522\u0006\u0089\u000e\u0000\u0522\u0523\u0006\u0089\u000e"+ - "\u0000\u0523\u0123\u0001\u0000\u0000\u0000\u0524\u0525\u0005(\u0000\u0000"+ - "\u0525\u0526\u0001\u0000\u0000\u0000\u0526\u0527\u0006\u008a\u0004\u0000"+ - "\u0527\u0528\u0006\u008a\u0004\u0000\u0528\u0125\u0001\u0000\u0000\u0000"+ - "\u0529\u052a\u0005)\u0000\u0000\u052a\u052b\u0001\u0000\u0000\u0000\u052b"+ - "\u052c\u0006\u008b\u000e\u0000\u052c\u052d\u0006\u008b\u000e\u0000\u052d"+ - "\u0127\u0001\u0000\u0000\u0000\u052e\u0532\u0003\u00b2Q\u0000\u052f\u0531"+ - "\u0003\u00c2Y\u0000\u0530\u052f\u0001\u0000\u0000\u0000\u0531\u0534\u0001"+ - "\u0000\u0000\u0000\u0532\u0530\u0001\u0000\u0000\u0000\u0532\u0533\u0001"+ - "\u0000\u0000\u0000\u0533\u053f\u0001\u0000\u0000\u0000\u0534\u0532\u0001"+ - "\u0000\u0000\u0000\u0535\u0538\u0003\u00c0X\u0000\u0536\u0538\u0003\u00ba"+ - "U\u0000\u0537\u0535\u0001\u0000\u0000\u0000\u0537\u0536\u0001\u0000\u0000"+ - "\u0000\u0538\u053a\u0001\u0000\u0000\u0000\u0539\u053b\u0003\u00c2Y\u0000"+ - "\u053a\u0539\u0001\u0000\u0000\u0000\u053b\u053c\u0001\u0000\u0000\u0000"+ - "\u053c\u053a\u0001\u0000\u0000\u0000\u053c\u053d\u0001\u0000\u0000\u0000"+ - "\u053d\u053f\u0001\u0000\u0000\u0000\u053e\u052e\u0001\u0000\u0000\u0000"+ - "\u053e\u0537\u0001\u0000\u0000\u0000\u053f\u0129\u0001\u0000\u0000\u0000"+ - "\u0540\u0542\u0003\u00bcV\u0000\u0541\u0543\u0003\u00beW\u0000\u0542\u0541"+ - "\u0001\u0000\u0000\u0000\u0543\u0544\u0001\u0000\u0000\u0000\u0544\u0542"+ - "\u0001\u0000\u0000\u0000\u0544\u0545\u0001\u0000\u0000\u0000\u0545\u0546"+ - "\u0001\u0000\u0000\u0000\u0546\u0547\u0003\u00bcV\u0000\u0547\u012b\u0001"+ - "\u0000\u0000\u0000\u0548\u0549\u0003\u012a\u008d\u0000\u0549\u012d\u0001"+ - "\u0000\u0000\u0000\u054a\u054b\u0003\u0010\u0000\u0000\u054b\u054c\u0001"+ - "\u0000\u0000\u0000\u054c\u054d\u0006\u008f\u0000\u0000\u054d\u012f\u0001"+ - "\u0000\u0000\u0000\u054e\u054f\u0003\u0012\u0001\u0000\u054f\u0550\u0001"+ - "\u0000\u0000\u0000\u0550\u0551\u0006\u0090\u0000\u0000\u0551\u0131\u0001"+ - "\u0000\u0000\u0000\u0552\u0553\u0003\u0014\u0002\u0000\u0553\u0554\u0001"+ - "\u0000\u0000\u0000\u0554\u0555\u0006\u0091\u0000\u0000\u0555\u0133\u0001"+ - "\u0000\u0000\u0000\u0556\u0557\u0003\u00aeO\u0000\u0557\u0558\u0001\u0000"+ - "\u0000\u0000\u0558\u0559\u0006\u0092\r\u0000\u0559\u055a\u0006\u0092\u000e"+ - "\u0000\u055a\u0135\u0001\u0000\u0000\u0000\u055b\u055c\u0003\u0120\u0088"+ - "\u0000\u055c\u055d\u0001\u0000\u0000\u0000\u055d\u055e\u0006\u0093\u0015"+ - "\u0000\u055e\u0137\u0001\u0000\u0000\u0000\u055f\u0560\u0003\u0122\u0089"+ - "\u0000\u0560\u0561\u0001\u0000\u0000\u0000\u0561\u0562\u0006\u0094 \u0000"+ - "\u0562\u0139\u0001\u0000\u0000\u0000\u0563\u0564\u0003\u00d6c\u0000\u0564"+ - "\u0565\u0001\u0000\u0000\u0000\u0565\u0566\u0006\u0095!\u0000\u0566\u013b"+ - "\u0001\u0000\u0000\u0000\u0567\u0568\u0003\u00d4b\u0000\u0568\u0569\u0001"+ - "\u0000\u0000\u0000\u0569\u056a\u0006\u0096$\u0000\u056a\u013d\u0001\u0000"+ - "\u0000\u0000\u056b\u056c\u0003\u00d8d\u0000\u056c\u056d\u0001\u0000\u0000"+ - "\u0000\u056d\u056e\u0006\u0097\u0012\u0000\u056e\u013f\u0001\u0000\u0000"+ - "\u0000\u056f\u0570\u0003\u00d0`\u0000\u0570\u0571\u0001\u0000\u0000\u0000"+ - "\u0571\u0572\u0006\u0098\u001a\u0000\u0572\u0141\u0001\u0000\u0000\u0000"+ - "\u0573\u0574\u0007\u0013\u0000\u0000\u0574\u0575\u0007\u0007\u0000\u0000"+ - "\u0575\u0576\u0007\u000b\u0000\u0000\u0576\u0577\u0007\u0004\u0000\u0000"+ - "\u0577\u0578\u0007\u000f\u0000\u0000\u0578\u0579\u0007\u0004\u0000\u0000"+ - "\u0579\u057a\u0007\u000b\u0000\u0000\u057a\u057b\u0007\u0004\u0000\u0000"+ - "\u057b\u0143\u0001\u0000\u0000\u0000\u057c\u0580\b!\u0000\u0000\u057d"+ - "\u057e\u0005/\u0000\u0000\u057e\u0580\b\"\u0000\u0000\u057f\u057c\u0001"+ - "\u0000\u0000\u0000\u057f\u057d\u0001\u0000\u0000\u0000\u0580\u0145\u0001"+ - "\u0000\u0000\u0000\u0581\u0583\u0003\u0144\u009a\u0000\u0582\u0581\u0001"+ - "\u0000\u0000\u0000\u0583\u0584\u0001\u0000\u0000\u0000\u0584\u0582\u0001"+ - "\u0000\u0000\u0000\u0584\u0585\u0001\u0000\u0000\u0000\u0585\u0147\u0001"+ - "\u0000\u0000\u0000\u0586\u0587\u0003\u0146\u009b\u0000\u0587\u0588\u0001"+ - "\u0000\u0000\u0000\u0588\u0589\u0006\u009c%\u0000\u0589\u0149\u0001\u0000"+ - "\u0000\u0000\u058a\u058b\u0003\u00c4Z\u0000\u058b\u058c\u0001\u0000\u0000"+ - "\u0000\u058c\u058d\u0006\u009d&\u0000\u058d\u014b\u0001\u0000\u0000\u0000"+ - "\u058e\u058f\u0003\u0010\u0000\u0000\u058f\u0590\u0001\u0000\u0000\u0000"+ - "\u0590\u0591\u0006\u009e\u0000\u0000\u0591\u014d\u0001\u0000\u0000\u0000"+ - "\u0592\u0593\u0003\u0012\u0001\u0000\u0593\u0594\u0001\u0000\u0000\u0000"+ - "\u0594\u0595\u0006\u009f\u0000\u0000\u0595\u014f\u0001\u0000\u0000\u0000"+ - "\u0596\u0597\u0003\u0014\u0002\u0000\u0597\u0598\u0001\u0000\u0000\u0000"+ - "\u0598\u0599\u0006\u00a0\u0000\u0000\u0599\u0151\u0001\u0000\u0000\u0000"+ - "\u059a\u059b\u0003\u0124\u008a\u0000\u059b\u059c\u0001\u0000\u0000\u0000"+ - "\u059c\u059d\u0006\u00a1\'\u0000\u059d\u059e\u0006\u00a1\"\u0000\u059e"+ - "\u0153\u0001\u0000\u0000\u0000\u059f\u05a0\u0003\u00aeO\u0000\u05a0\u05a1"+ - "\u0001\u0000\u0000\u0000\u05a1\u05a2\u0006\u00a2\r\u0000\u05a2\u05a3\u0006"+ - "\u00a2\u000e\u0000\u05a3\u0155\u0001\u0000\u0000\u0000\u05a4\u05a5\u0003"+ - "\u0014\u0002\u0000\u05a5\u05a6\u0001\u0000\u0000\u0000\u05a6\u05a7\u0006"+ - "\u00a3\u0000\u0000\u05a7\u0157\u0001\u0000\u0000\u0000\u05a8\u05a9\u0003"+ - "\u0010\u0000\u0000\u05a9\u05aa\u0001\u0000\u0000\u0000\u05aa\u05ab\u0006"+ - "\u00a4\u0000\u0000\u05ab\u0159\u0001\u0000\u0000\u0000\u05ac\u05ad\u0003"+ - "\u0012\u0001\u0000\u05ad\u05ae\u0001\u0000\u0000\u0000\u05ae\u05af\u0006"+ - "\u00a5\u0000\u0000\u05af\u015b\u0001\u0000\u0000\u0000\u05b0\u05b1\u0003"+ - "\u00aeO\u0000\u05b1\u05b2\u0001\u0000\u0000\u0000\u05b2\u05b3\u0006\u00a6"+ - "\r\u0000\u05b3\u05b4\u0006\u00a6\u000e\u0000\u05b4\u015d\u0001\u0000\u0000"+ - "\u0000\u05b5\u05b6\u0007#\u0000\u0000\u05b6\u05b7\u0007\t\u0000\u0000"+ - "\u05b7\u05b8\u0007\n\u0000\u0000\u05b8\u05b9\u0007\u0005\u0000\u0000\u05b9"+ - "\u015f\u0001\u0000\u0000\u0000\u05ba\u05bb\u0003\u00cc^\u0000\u05bb\u05bc"+ - "\u0001\u0000\u0000\u0000\u05bc\u05bd\u0006\u00a8\u0010\u0000\u05bd\u0161"+ - "\u0001\u0000\u0000\u0000\u05be\u05bf\u0003\u00f0p\u0000\u05bf\u05c0\u0001"+ - "\u0000\u0000\u0000\u05c0\u05c1\u0006\u00a9\u000f\u0000\u05c1\u05c2\u0006"+ - "\u00a9\u000e\u0000\u05c2\u05c3\u0006\u00a9\u0004\u0000\u05c3\u0163\u0001"+ - "\u0000\u0000\u0000\u05c4\u05c5\u0007\u0016\u0000\u0000\u05c5\u05c6\u0007"+ - "\u0010\u0000\u0000\u05c6\u05c7\u0007\n\u0000\u0000\u05c7\u05c8\u0007\u0005"+ - "\u0000\u0000\u05c8\u05c9\u0007\u0006\u0000\u0000\u05c9\u05ca\u0001\u0000"+ - "\u0000\u0000\u05ca\u05cb\u0006\u00aa\u000e\u0000\u05cb\u05cc\u0006\u00aa"+ - "\u0004\u0000\u05cc\u0165\u0001\u0000\u0000\u0000\u05cd\u05ce\u0003\u0146"+ - "\u009b\u0000\u05ce\u05cf\u0001\u0000\u0000\u0000\u05cf\u05d0\u0006\u00ab"+ - "%\u0000\u05d0\u0167\u0001\u0000\u0000\u0000\u05d1\u05d2\u0003\u00c4Z\u0000"+ - "\u05d2\u05d3\u0001\u0000\u0000\u0000\u05d3\u05d4\u0006\u00ac&\u0000\u05d4"+ - "\u0169\u0001\u0000\u0000\u0000\u05d5\u05d6\u0003\u00d6c\u0000\u05d6\u05d7"+ - "\u0001\u0000\u0000\u0000\u05d7\u05d8\u0006\u00ad!\u0000\u05d8\u016b\u0001"+ - "\u0000\u0000\u0000\u05d9\u05da\u0003\u0128\u008c\u0000\u05da\u05db\u0001"+ - "\u0000\u0000\u0000\u05db\u05dc\u0006\u00ae\u0014\u0000\u05dc\u016d\u0001"+ - "\u0000\u0000\u0000\u05dd\u05de\u0003\u012c\u008e\u0000\u05de\u05df\u0001"+ - "\u0000\u0000\u0000\u05df\u05e0\u0006\u00af\u0013\u0000\u05e0\u016f\u0001"+ - "\u0000\u0000\u0000\u05e1\u05e2\u0003\u0010\u0000\u0000\u05e2\u05e3\u0001"+ - "\u0000\u0000\u0000\u05e3\u05e4\u0006\u00b0\u0000\u0000\u05e4\u0171\u0001"+ - "\u0000\u0000\u0000\u05e5\u05e6\u0003\u0012\u0001\u0000\u05e6\u05e7\u0001"+ - "\u0000\u0000\u0000\u05e7\u05e8\u0006\u00b1\u0000\u0000\u05e8\u0173\u0001"+ - "\u0000\u0000\u0000\u05e9\u05ea\u0003\u0014\u0002\u0000\u05ea\u05eb\u0001"+ - "\u0000\u0000\u0000\u05eb\u05ec\u0006\u00b2\u0000\u0000\u05ec\u0175\u0001"+ - "\u0000\u0000\u0000\u05ed\u05ee\u0003\u00aeO\u0000\u05ee\u05ef\u0001\u0000"+ - "\u0000\u0000\u05ef\u05f0\u0006\u00b3\r\u0000\u05f0\u05f1\u0006\u00b3\u000e"+ - "\u0000\u05f1\u0177\u0001\u0000\u0000\u0000\u05f2\u05f3\u0003\u00d6c\u0000"+ - "\u05f3\u05f4\u0001\u0000\u0000\u0000\u05f4\u05f5\u0006\u00b4!\u0000\u05f5"+ - "\u0179\u0001\u0000\u0000\u0000\u05f6\u05f7\u0003\u00d8d\u0000\u05f7\u05f8"+ - "\u0001\u0000\u0000\u0000\u05f8\u05f9\u0006\u00b5\u0012\u0000\u05f9\u017b"+ - "\u0001\u0000\u0000\u0000\u05fa\u05fb\u0003\u00dcf\u0000\u05fb\u05fc\u0001"+ - "\u0000\u0000\u0000\u05fc\u05fd\u0006\u00b6\u0011\u0000\u05fd\u017d\u0001"+ - "\u0000\u0000\u0000\u05fe\u05ff\u0003\u00f0p\u0000\u05ff\u0600\u0001\u0000"+ - "\u0000\u0000\u0600\u0601\u0006\u00b7\u000f\u0000\u0601\u0602\u0006\u00b7"+ - "(\u0000\u0602\u017f\u0001\u0000\u0000\u0000\u0603\u0604\u0003\u0146\u009b"+ - "\u0000\u0604\u0605\u0001\u0000\u0000\u0000\u0605\u0606\u0006\u00b8%\u0000"+ - "\u0606\u0181\u0001\u0000\u0000\u0000\u0607\u0608\u0003\u00c4Z\u0000\u0608"+ - "\u0609\u0001\u0000\u0000\u0000\u0609\u060a\u0006\u00b9&\u0000\u060a\u0183"+ - "\u0001\u0000\u0000\u0000\u060b\u060c\u0003\u0010\u0000\u0000\u060c\u060d"+ - "\u0001\u0000\u0000\u0000\u060d\u060e\u0006\u00ba\u0000\u0000\u060e\u0185"+ - "\u0001\u0000\u0000\u0000\u060f\u0610\u0003\u0012\u0001\u0000\u0610\u0611"+ - "\u0001\u0000\u0000\u0000\u0611\u0612\u0006\u00bb\u0000\u0000\u0612\u0187"+ - "\u0001\u0000\u0000\u0000\u0613\u0614\u0003\u0014\u0002\u0000\u0614\u0615"+ - "\u0001\u0000\u0000\u0000\u0615\u0616\u0006\u00bc\u0000\u0000\u0616\u0189"+ - "\u0001\u0000\u0000\u0000\u0617\u0618\u0003\u00aeO\u0000\u0618\u0619\u0001"+ - "\u0000\u0000\u0000\u0619\u061a\u0006\u00bd\r\u0000\u061a\u061b\u0006\u00bd"+ - "\u000e\u0000\u061b\u061c\u0006\u00bd\u000e\u0000\u061c\u018b\u0001\u0000"+ - "\u0000\u0000\u061d\u061e\u0003\u00d8d\u0000\u061e\u061f\u0001\u0000\u0000"+ - "\u0000\u061f\u0620\u0006\u00be\u0012\u0000\u0620\u018d\u0001\u0000\u0000"+ - "\u0000\u0621\u0622\u0003\u00dcf\u0000\u0622\u0623\u0001\u0000\u0000\u0000"+ - "\u0623\u0624\u0006\u00bf\u0011\u0000\u0624\u018f\u0001\u0000\u0000\u0000"+ - "\u0625\u0626\u0003\u01c0\u00d8\u0000\u0626\u0627\u0001\u0000\u0000\u0000"+ - "\u0627\u0628\u0006\u00c0\u001b\u0000\u0628\u0191\u0001\u0000\u0000\u0000"+ - "\u0629\u062a\u0003\u0010\u0000\u0000\u062a\u062b\u0001\u0000\u0000\u0000"+ - "\u062b\u062c\u0006\u00c1\u0000\u0000\u062c\u0193\u0001\u0000\u0000\u0000"+ - "\u062d\u062e\u0003\u0012\u0001\u0000\u062e\u062f\u0001\u0000\u0000\u0000"+ - "\u062f\u0630\u0006\u00c2\u0000\u0000\u0630\u0195\u0001\u0000\u0000\u0000"+ - "\u0631\u0632\u0003\u0014\u0002\u0000\u0632\u0633\u0001\u0000\u0000\u0000"+ - "\u0633\u0634\u0006\u00c3\u0000\u0000\u0634\u0197\u0001\u0000\u0000\u0000"+ - "\u0635\u0636\u0003\u00aeO\u0000\u0636\u0637\u0001\u0000\u0000\u0000\u0637"+ - "\u0638\u0006\u00c4\r\u0000\u0638\u0639\u0006\u00c4\u000e\u0000\u0639\u0199"+ - "\u0001\u0000\u0000\u0000\u063a\u063b\u0003\u00dcf\u0000\u063b\u063c\u0001"+ - "\u0000\u0000\u0000\u063c\u063d\u0006\u00c5\u0011\u0000\u063d\u019b\u0001"+ - "\u0000\u0000\u0000\u063e\u063f\u0003\u00f4r\u0000\u063f\u0640\u0001\u0000"+ - "\u0000\u0000\u0640\u0641\u0006\u00c6\u001c\u0000\u0641\u019d\u0001\u0000"+ - "\u0000\u0000\u0642\u0643\u0003\u011c\u0086\u0000\u0643\u0644\u0001\u0000"+ - "\u0000\u0000\u0644\u0645\u0006\u00c7\u001d\u0000\u0645\u019f\u0001\u0000"+ - "\u0000\u0000\u0646\u0647\u0003\u0118\u0084\u0000\u0647\u0648\u0001\u0000"+ - "\u0000\u0000\u0648\u0649\u0006\u00c8\u001e\u0000\u0649\u01a1\u0001\u0000"+ - "\u0000\u0000\u064a\u064b\u0003\u011e\u0087\u0000\u064b\u064c\u0001\u0000"+ - "\u0000\u0000\u064c\u064d\u0006\u00c9\u001f\u0000\u064d\u01a3\u0001\u0000"+ - "\u0000\u0000\u064e\u064f\u0003\u012c\u008e\u0000\u064f\u0650\u0001\u0000"+ - "\u0000\u0000\u0650\u0651\u0006\u00ca\u0013\u0000\u0651\u01a5\u0001\u0000"+ - "\u0000\u0000\u0652\u0653\u0003\u0128\u008c\u0000\u0653\u0654\u0001\u0000"+ - "\u0000\u0000\u0654\u0655\u0006\u00cb\u0014\u0000\u0655\u01a7\u0001\u0000"+ - "\u0000\u0000\u0656\u0657\u0003\u0010\u0000\u0000\u0657\u0658\u0001\u0000"+ - "\u0000\u0000\u0658\u0659\u0006\u00cc\u0000\u0000\u0659\u01a9\u0001\u0000"+ - "\u0000\u0000\u065a\u065b\u0003\u0012\u0001\u0000\u065b\u065c\u0001\u0000"+ - "\u0000\u0000\u065c\u065d\u0006\u00cd\u0000\u0000\u065d\u01ab\u0001\u0000"+ - "\u0000\u0000\u065e\u065f\u0003\u0014\u0002\u0000\u065f\u0660\u0001\u0000"+ - "\u0000\u0000\u0660\u0661\u0006\u00ce\u0000\u0000\u0661\u01ad\u0001\u0000"+ - "\u0000\u0000\u0662\u0663\u0003\u00aeO\u0000\u0663\u0664\u0001\u0000\u0000"+ - "\u0000\u0664\u0665\u0006\u00cf\r\u0000\u0665\u0666\u0006\u00cf\u000e\u0000"+ - "\u0666\u01af\u0001\u0000\u0000\u0000\u0667\u0668\u0003\u00dcf\u0000\u0668"+ - "\u0669\u0001\u0000\u0000\u0000\u0669\u066a\u0006\u00d0\u0011\u0000\u066a"+ - "\u01b1\u0001\u0000\u0000\u0000\u066b\u066c\u0003\u00d8d\u0000\u066c\u066d"+ - "\u0001\u0000\u0000\u0000\u066d\u066e\u0006\u00d1\u0012\u0000\u066e\u01b3"+ - "\u0001\u0000\u0000\u0000\u066f\u0670\u0003\u00f4r\u0000\u0670\u0671\u0001"+ - "\u0000\u0000\u0000\u0671\u0672\u0006\u00d2\u001c\u0000\u0672\u01b5\u0001"+ - "\u0000\u0000\u0000\u0673\u0674\u0003\u011c\u0086\u0000\u0674\u0675\u0001"+ - "\u0000\u0000\u0000\u0675\u0676\u0006\u00d3\u001d\u0000\u0676\u01b7\u0001"+ - "\u0000\u0000\u0000\u0677\u0678\u0003\u0118\u0084\u0000\u0678\u0679\u0001"+ - "\u0000\u0000\u0000\u0679\u067a\u0006\u00d4\u001e\u0000\u067a\u01b9\u0001"+ - "\u0000\u0000\u0000\u067b\u067c\u0003\u011e\u0087\u0000\u067c\u067d\u0001"+ - "\u0000\u0000\u0000\u067d\u067e\u0006\u00d5\u001f\u0000\u067e\u01bb\u0001"+ - "\u0000\u0000\u0000\u067f\u0684\u0003\u00b2Q\u0000\u0680\u0684\u0003\u00b0"+ - "P\u0000\u0681\u0684\u0003\u00c0X\u0000\u0682\u0684\u0003\u010e\u007f\u0000"+ - "\u0683\u067f\u0001\u0000\u0000\u0000\u0683\u0680\u0001\u0000\u0000\u0000"+ - "\u0683\u0681\u0001\u0000\u0000\u0000\u0683\u0682\u0001\u0000\u0000\u0000"+ - "\u0684\u01bd\u0001\u0000\u0000\u0000\u0685\u0688\u0003\u00b2Q\u0000\u0686"+ - "\u0688\u0003\u010e\u007f\u0000\u0687\u0685\u0001\u0000\u0000\u0000\u0687"+ - "\u0686\u0001\u0000\u0000\u0000\u0688\u068c\u0001\u0000\u0000\u0000\u0689"+ - "\u068b\u0003\u01bc\u00d6\u0000\u068a\u0689\u0001\u0000\u0000\u0000\u068b"+ - "\u068e\u0001\u0000\u0000\u0000\u068c\u068a\u0001\u0000\u0000\u0000\u068c"+ - "\u068d\u0001\u0000\u0000\u0000\u068d\u0699\u0001\u0000\u0000\u0000\u068e"+ - "\u068c\u0001\u0000\u0000\u0000\u068f\u0692\u0003\u00c0X\u0000\u0690\u0692"+ - "\u0003\u00baU\u0000\u0691\u068f\u0001\u0000\u0000\u0000\u0691\u0690\u0001"+ - "\u0000\u0000\u0000\u0692\u0694\u0001\u0000\u0000\u0000\u0693\u0695\u0003"+ - "\u01bc\u00d6\u0000\u0694\u0693\u0001\u0000\u0000\u0000\u0695\u0696\u0001"+ - "\u0000\u0000\u0000\u0696\u0694\u0001\u0000\u0000\u0000\u0696\u0697\u0001"+ - "\u0000\u0000\u0000\u0697\u0699\u0001\u0000\u0000\u0000\u0698\u0687\u0001"+ - "\u0000\u0000\u0000\u0698\u0691\u0001\u0000\u0000\u0000\u0699\u01bf\u0001"+ - "\u0000\u0000\u0000\u069a\u069d\u0003\u01be\u00d7\u0000\u069b\u069d\u0003"+ - "\u012a\u008d\u0000\u069c\u069a\u0001\u0000\u0000\u0000\u069c\u069b\u0001"+ - "\u0000\u0000\u0000\u069d\u069e\u0001\u0000\u0000\u0000\u069e\u069c\u0001"+ - "\u0000\u0000\u0000\u069e\u069f\u0001\u0000\u0000\u0000\u069f\u01c1\u0001"+ - "\u0000\u0000\u0000\u06a0\u06a1\u0003\u0010\u0000\u0000\u06a1\u06a2\u0001"+ - "\u0000\u0000\u0000\u06a2\u06a3\u0006\u00d9\u0000\u0000\u06a3\u01c3\u0001"+ - "\u0000\u0000\u0000\u06a4\u06a5\u0003\u0012\u0001\u0000\u06a5\u06a6\u0001"+ - "\u0000\u0000\u0000\u06a6\u06a7\u0006\u00da\u0000\u0000\u06a7\u01c5\u0001"+ - "\u0000\u0000\u0000\u06a8\u06a9\u0003\u0014\u0002\u0000\u06a9\u06aa\u0001"+ - "\u0000\u0000\u0000\u06aa\u06ab\u0006\u00db\u0000\u0000\u06ab\u01c7\u0001"+ - "\u0000\u0000\u0000\u06ac\u06ad\u0003\u00aeO\u0000\u06ad\u06ae\u0001\u0000"+ - "\u0000\u0000\u06ae\u06af\u0006\u00dc\r\u0000\u06af\u06b0\u0006\u00dc\u000e"+ - "\u0000\u06b0\u01c9\u0001\u0000\u0000\u0000\u06b1\u06b2\u0003\u00d0`\u0000"+ - "\u06b2\u06b3\u0001\u0000\u0000\u0000\u06b3\u06b4\u0006\u00dd\u001a\u0000"+ - "\u06b4\u01cb\u0001\u0000\u0000\u0000\u06b5\u06b6\u0003\u00d8d\u0000\u06b6"+ - "\u06b7\u0001\u0000\u0000\u0000\u06b7\u06b8\u0006\u00de\u0012\u0000\u06b8"+ - "\u01cd\u0001\u0000\u0000\u0000\u06b9\u06ba\u0003\u00dcf\u0000\u06ba\u06bb"+ - "\u0001\u0000\u0000\u0000\u06bb\u06bc\u0006\u00df\u0011\u0000\u06bc\u01cf"+ - "\u0001\u0000\u0000\u0000\u06bd\u06be\u0003\u00f4r\u0000\u06be\u06bf\u0001"+ - "\u0000\u0000\u0000\u06bf\u06c0\u0006\u00e0\u001c\u0000\u06c0\u01d1\u0001"+ - "\u0000\u0000\u0000\u06c1\u06c2\u0003\u011c\u0086\u0000\u06c2\u06c3\u0001"+ - "\u0000\u0000\u0000\u06c3\u06c4\u0006\u00e1\u001d\u0000\u06c4\u01d3\u0001"+ - "\u0000\u0000\u0000\u06c5\u06c6\u0003\u0118\u0084\u0000\u06c6\u06c7\u0001"+ - "\u0000\u0000\u0000\u06c7\u06c8\u0006\u00e2\u001e\u0000\u06c8\u01d5\u0001"+ - "\u0000\u0000\u0000\u06c9\u06ca\u0003\u011e\u0087\u0000\u06ca\u06cb\u0001"+ - "\u0000\u0000\u0000\u06cb\u06cc\u0006\u00e3\u001f\u0000\u06cc\u01d7\u0001"+ - "\u0000\u0000\u0000\u06cd\u06ce\u0003\u00cc^\u0000\u06ce\u06cf\u0001\u0000"+ - "\u0000\u0000\u06cf\u06d0\u0006\u00e4\u0010\u0000\u06d0\u01d9\u0001\u0000"+ - "\u0000\u0000\u06d1\u06d2\u0003\u01c0\u00d8\u0000\u06d2\u06d3\u0001\u0000"+ - "\u0000\u0000\u06d3\u06d4\u0006\u00e5\u001b\u0000\u06d4\u01db\u0001\u0000"+ - "\u0000\u0000\u06d5\u06d6\u0003\u0010\u0000\u0000\u06d6\u06d7\u0001\u0000"+ - "\u0000\u0000\u06d7\u06d8\u0006\u00e6\u0000\u0000\u06d8\u01dd\u0001\u0000"+ - "\u0000\u0000\u06d9\u06da\u0003\u0012\u0001\u0000\u06da\u06db\u0001\u0000"+ - "\u0000\u0000\u06db\u06dc\u0006\u00e7\u0000\u0000\u06dc\u01df\u0001\u0000"+ - "\u0000\u0000\u06dd\u06de\u0003\u0014\u0002\u0000\u06de\u06df\u0001\u0000"+ - "\u0000\u0000\u06df\u06e0\u0006\u00e8\u0000\u0000\u06e0\u01e1\u0001\u0000"+ - "\u0000\u0000\u06e1\u06e2\u0003\u00aeO\u0000\u06e2\u06e3\u0001\u0000\u0000"+ - "\u0000\u06e3\u06e4\u0006\u00e9\r\u0000\u06e4\u06e5\u0006\u00e9\u000e\u0000"+ - "\u06e5\u01e3\u0001\u0000\u0000\u0000\u06e6\u06e7\u0007\n\u0000\u0000\u06e7"+ - "\u06e8\u0007\u0005\u0000\u0000\u06e8\u06e9\u0007\u0015\u0000\u0000\u06e9"+ - "\u06ea\u0007\t\u0000\u0000\u06ea\u01e5\u0001\u0000\u0000\u0000\u06eb\u06ec"+ - "\u0003\u0010\u0000\u0000\u06ec\u06ed\u0001\u0000\u0000\u0000\u06ed\u06ee"+ - "\u0006\u00eb\u0000\u0000\u06ee\u01e7\u0001\u0000\u0000\u0000\u06ef\u06f0"+ - "\u0003\u0012\u0001\u0000\u06f0\u06f1\u0001\u0000\u0000\u0000\u06f1\u06f2"+ - "\u0006\u00ec\u0000\u0000\u06f2\u01e9\u0001\u0000\u0000\u0000\u06f3\u06f4"+ - "\u0003\u0014\u0002\u0000\u06f4\u06f5\u0001\u0000\u0000\u0000\u06f5\u06f6"+ - "\u0006\u00ed\u0000\u0000\u06f6\u01eb\u0001\u0000\u0000\u0000F\u0000\u0001"+ - "\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u01f2"+ - "\u01f6\u01f9\u0202\u0204\u020f\u0326\u036c\u0370\u0375\u03cf\u03d1\u0404"+ - "\u0409\u0412\u0419\u041e\u0420\u042b\u0433\u0436\u0438\u043d\u0442\u0448"+ - "\u044f\u0454\u045a\u045d\u0465\u0469\u04f7\u04fc\u0503\u0505\u050a\u050f"+ - "\u0516\u0518\u0532\u0537\u053c\u053e\u0544\u057f\u0584\u0683\u0687\u068c"+ - "\u0691\u0696\u0698\u069c\u069e)\u0000\u0001\u0000\u0005\u0001\u0000\u0005"+ - "\u0002\u0000\u0005\u0005\u0000\u0005\u0006\u0000\u0005\u0007\u0000\u0005"+ - "\b\u0000\u0005\t\u0000\u0005\n\u0000\u0005\f\u0000\u0005\r\u0000\u0005"+ - "\u000e\u0000\u0005\u000f\u0000\u00074\u0000\u0004\u0000\u0000\u0007K\u0000"+ - "\u00079\u0000\u0007A\u0000\u0007?\u0000\u0007g\u0000\u0007f\u0000\u0007"+ - "b\u0000\u0005\u0004\u0000\u0005\u0003\u0000\u0007P\u0000\u0007&\u0000"+ - "\u0007;\u0000\u0007\u0081\u0000\u0007M\u0000\u0007`\u0000\u0007_\u0000"+ - "\u0007a\u0000\u0007c\u0000\u0007>\u0000\u0005\u0000\u0000\u0007\u000e"+ - "\u0000\u0007=\u0000\u0007l\u0000\u00075\u0000\u0007d\u0000\u0005\u000b"+ - "\u0000"; + "\u001b\u0001\u0000\u0000\u0000\u0235\u0236\u0007\u0002\u0000\u0000\u0236"+ + "\u0237\u0007\t\u0000\u0000\u0237\u0238\u0007\u000f\u0000\u0000\u0238\u0239"+ + "\u0007\b\u0000\u0000\u0239\u023a\u0007\u000e\u0000\u0000\u023a\u023b\u0007"+ + "\u0007\u0000\u0000\u023b\u023c\u0007\u000b\u0000\u0000\u023c\u023d\u0007"+ + "\n\u0000\u0000\u023d\u023e\u0007\t\u0000\u0000\u023e\u023f\u0007\u0005"+ + "\u0000\u0000\u023f\u0240\u0001\u0000\u0000\u0000\u0240\u0241\u0006\u0006"+ + "\u0004\u0000\u0241\u001d\u0001\u0000\u0000\u0000\u0242\u0243\u0007\u0010"+ + "\u0000\u0000\u0243\u0244\u0007\n\u0000\u0000\u0244\u0245\u0007\u0011\u0000"+ + "\u0000\u0245\u0246\u0007\u0011\u0000\u0000\u0246\u0247\u0007\u0007\u0000"+ + "\u0000\u0247\u0248\u0007\u0002\u0000\u0000\u0248\u0249\u0007\u000b\u0000"+ + "\u0000\u0249\u024a\u0001\u0000\u0000\u0000\u024a\u024b\u0006\u0007\u0004"+ + "\u0000\u024b\u001f\u0001\u0000\u0000\u0000\u024c\u024d\u0007\u0007\u0000"+ + "\u0000\u024d\u024e\u0007\u0012\u0000\u0000\u024e\u024f\u0007\u0004\u0000"+ + "\u0000\u024f\u0250\u0007\u000e\u0000\u0000\u0250\u0251\u0001\u0000\u0000"+ + "\u0000\u0251\u0252\u0006\b\u0004\u0000\u0252!\u0001\u0000\u0000\u0000"+ + "\u0253\u0254\u0007\u0006\u0000\u0000\u0254\u0255\u0007\f\u0000\u0000\u0255"+ + "\u0256\u0007\t\u0000\u0000\u0256\u0257\u0007\u0013\u0000\u0000\u0257\u0258"+ + "\u0001\u0000\u0000\u0000\u0258\u0259\u0006\t\u0004\u0000\u0259#\u0001"+ + "\u0000\u0000\u0000\u025a\u025b\u0007\u000e\u0000\u0000\u025b\u025c\u0007"+ + "\n\u0000\u0000\u025c\u025d\u0007\u000f\u0000\u0000\u025d\u025e\u0007\n"+ + "\u0000\u0000\u025e\u025f\u0007\u000b\u0000\u0000\u025f\u0260\u0001\u0000"+ + "\u0000\u0000\u0260\u0261\u0006\n\u0004\u0000\u0261%\u0001\u0000\u0000"+ + "\u0000\u0262\u0263\u0007\f\u0000\u0000\u0263\u0264\u0007\t\u0000\u0000"+ + "\u0264\u0265\u0007\u0014\u0000\u0000\u0265\u0266\u0001\u0000\u0000\u0000"+ + "\u0266\u0267\u0006\u000b\u0004\u0000\u0267\'\u0001\u0000\u0000\u0000\u0268"+ + "\u0269\u0007\u0011\u0000\u0000\u0269\u026a\u0007\t\u0000\u0000\u026a\u026b"+ + "\u0007\f\u0000\u0000\u026b\u026c\u0007\u000b\u0000\u0000\u026c\u026d\u0001"+ + "\u0000\u0000\u0000\u026d\u026e\u0006\f\u0004\u0000\u026e)\u0001\u0000"+ + "\u0000\u0000\u026f\u0270\u0007\u0011\u0000\u0000\u0270\u0271\u0007\u000b"+ + "\u0000\u0000\u0271\u0272\u0007\u0004\u0000\u0000\u0272\u0273\u0007\u000b"+ + "\u0000\u0000\u0273\u0274\u0007\u0011\u0000\u0000\u0274\u0275\u0001\u0000"+ + "\u0000\u0000\u0275\u0276\u0006\r\u0004\u0000\u0276+\u0001\u0000\u0000"+ + "\u0000\u0277\u0278\u0007\u0014\u0000\u0000\u0278\u0279\u0007\u0003\u0000"+ + "\u0000\u0279\u027a\u0007\u0007\u0000\u0000\u027a\u027b\u0007\f\u0000\u0000"+ + "\u027b\u027c\u0007\u0007\u0000\u0000\u027c\u027d\u0001\u0000\u0000\u0000"+ + "\u027d\u027e\u0006\u000e\u0004\u0000\u027e-\u0001\u0000\u0000\u0000\u027f"+ + "\u0280\u0004\u000f\u0000\u0000\u0280\u0281\u0007\n\u0000\u0000\u0281\u0282"+ + "\u0007\u0005\u0000\u0000\u0282\u0283\u0007\u000e\u0000\u0000\u0283\u0284"+ + "\u0007\n\u0000\u0000\u0284\u0285\u0007\u0005\u0000\u0000\u0285\u0286\u0007"+ + "\u0007\u0000\u0000\u0286\u0287\u0007\u0011\u0000\u0000\u0287\u0288\u0007"+ + "\u000b\u0000\u0000\u0288\u0289\u0007\u0004\u0000\u0000\u0289\u028a\u0007"+ + "\u000b\u0000\u0000\u028a\u028b\u0007\u0011\u0000\u0000\u028b\u028c\u0001"+ + "\u0000\u0000\u0000\u028c\u028d\u0006\u000f\u0004\u0000\u028d/\u0001\u0000"+ + "\u0000\u0000\u028e\u028f\u0004\u0010\u0001\u0000\u028f\u0290\u0007\f\u0000"+ + "\u0000\u0290\u0291\u0007\u0007\u0000\u0000\u0291\u0292\u0007\f\u0000\u0000"+ + "\u0292\u0293\u0007\u0004\u0000\u0000\u0293\u0294\u0007\u0005\u0000\u0000"+ + "\u0294\u0295\u0007\u0013\u0000\u0000\u0295\u0296\u0001\u0000\u0000\u0000"+ + "\u0296\u0297\u0006\u0010\u0004\u0000\u02971\u0001\u0000\u0000\u0000\u0298"+ + "\u0299\u0004\u0011\u0002\u0000\u0299\u029a\u0007\u0011\u0000\u0000\u029a"+ + "\u029b\u0007\u0004\u0000\u0000\u029b\u029c\u0007\u000f\u0000\u0000\u029c"+ + "\u029d\u0007\b\u0000\u0000\u029d\u029e\u0007\u000e\u0000\u0000\u029e\u029f"+ + "\u0007\u0007\u0000\u0000\u029f\u02a0\u0001\u0000\u0000\u0000\u02a0\u02a1"+ + "\u0006\u0011\u0004\u0000\u02a13\u0001\u0000\u0000\u0000\u02a2\u02a3\u0007"+ + "\u0015\u0000\u0000\u02a3\u02a4\u0007\f\u0000\u0000\u02a4\u02a5\u0007\t"+ + "\u0000\u0000\u02a5\u02a6\u0007\u000f\u0000\u0000\u02a6\u02a7\u0001\u0000"+ + "\u0000\u0000\u02a7\u02a8\u0006\u0012\u0005\u0000\u02a85\u0001\u0000\u0000"+ + "\u0000\u02a9\u02aa\u0004\u0013\u0003\u0000\u02aa\u02ab\u0007\u000b\u0000"+ + "\u0000\u02ab\u02ac\u0007\u0011\u0000\u0000\u02ac\u02ad\u0001\u0000\u0000"+ + "\u0000\u02ad\u02ae\u0006\u0013\u0005\u0000\u02ae7\u0001\u0000\u0000\u0000"+ + "\u02af\u02b0\u0004\u0014\u0004\u0000\u02b0\u02b1\u0007\u0015\u0000\u0000"+ + "\u02b1\u02b2\u0007\t\u0000\u0000\u02b2\u02b3\u0007\f\u0000\u0000\u02b3"+ + "\u02b4\u0007\u0013\u0000\u0000\u02b4\u02b5\u0001\u0000\u0000\u0000\u02b5"+ + "\u02b6\u0006\u0014\u0006\u0000\u02b69\u0001\u0000\u0000\u0000\u02b7\u02b8"+ + "\u0007\u000e\u0000\u0000\u02b8\u02b9\u0007\t\u0000\u0000\u02b9\u02ba\u0007"+ + "\t\u0000\u0000\u02ba\u02bb\u0007\u0013\u0000\u0000\u02bb\u02bc\u0007\u0016"+ + "\u0000\u0000\u02bc\u02bd\u0007\b\u0000\u0000\u02bd\u02be\u0001\u0000\u0000"+ + "\u0000\u02be\u02bf\u0006\u0015\u0007\u0000\u02bf;\u0001\u0000\u0000\u0000"+ + "\u02c0\u02c1\u0004\u0016\u0005\u0000\u02c1\u02c2\u0007\u0015\u0000\u0000"+ + "\u02c2\u02c3\u0007\u0016\u0000\u0000\u02c3\u02c4\u0007\u000e\u0000\u0000"+ + "\u02c4\u02c5\u0007\u000e\u0000\u0000\u02c5\u02c6\u0001\u0000\u0000\u0000"+ + "\u02c6\u02c7\u0006\u0016\u0007\u0000\u02c7=\u0001\u0000\u0000\u0000\u02c8"+ + "\u02c9\u0004\u0017\u0006\u0000\u02c9\u02ca\u0007\u000e\u0000\u0000\u02ca"+ + "\u02cb\u0007\u0007\u0000\u0000\u02cb\u02cc\u0007\u0015\u0000\u0000\u02cc"+ + "\u02cd\u0007\u000b\u0000\u0000\u02cd\u02ce\u0001\u0000\u0000\u0000\u02ce"+ + "\u02cf\u0006\u0017\u0007\u0000\u02cf?\u0001\u0000\u0000\u0000\u02d0\u02d1"+ + "\u0004\u0018\u0007\u0000\u02d1\u02d2\u0007\f\u0000\u0000\u02d2\u02d3\u0007"+ + "\n\u0000\u0000\u02d3\u02d4\u0007\u0006\u0000\u0000\u02d4\u02d5\u0007\u0003"+ + "\u0000\u0000\u02d5\u02d6\u0007\u000b\u0000\u0000\u02d6\u02d7\u0001\u0000"+ + "\u0000\u0000\u02d7\u02d8\u0006\u0018\u0007\u0000\u02d8A\u0001\u0000\u0000"+ + "\u0000\u02d9\u02da\u0004\u0019\b\u0000\u02da\u02db\u0007\u000e\u0000\u0000"+ + "\u02db\u02dc\u0007\t\u0000\u0000\u02dc\u02dd\u0007\t\u0000\u0000\u02dd"+ + "\u02de\u0007\u0013\u0000\u0000\u02de\u02df\u0007\u0016\u0000\u0000\u02df"+ + "\u02e0\u0007\b\u0000\u0000\u02e0\u02e1\u0005_\u0000\u0000\u02e1\u02e2"+ + "\u0005\u8001\uf414\u0000\u0000\u02e2\u02e3\u0001\u0000\u0000\u0000\u02e3"+ + "\u02e4\u0006\u0019\b\u0000\u02e4C\u0001\u0000\u0000\u0000\u02e5\u02e6"+ + "\u0007\u000f\u0000\u0000\u02e6\u02e7\u0007\u0012\u0000\u0000\u02e7\u02e8"+ + "\u0005_\u0000\u0000\u02e8\u02e9\u0007\u0007\u0000\u0000\u02e9\u02ea\u0007"+ + "\r\u0000\u0000\u02ea\u02eb\u0007\b\u0000\u0000\u02eb\u02ec\u0007\u0004"+ + "\u0000\u0000\u02ec\u02ed\u0007\u0005\u0000\u0000\u02ed\u02ee\u0007\u0010"+ + "\u0000\u0000\u02ee\u02ef\u0001\u0000\u0000\u0000\u02ef\u02f0\u0006\u001a"+ + "\t\u0000\u02f0E\u0001\u0000\u0000\u0000\u02f1\u02f2\u0007\u0010\u0000"+ + "\u0000\u02f2\u02f3\u0007\f\u0000\u0000\u02f3\u02f4\u0007\t\u0000\u0000"+ + "\u02f4\u02f5\u0007\b\u0000\u0000\u02f5\u02f6\u0001\u0000\u0000\u0000\u02f6"+ + "\u02f7\u0006\u001b\n\u0000\u02f7G\u0001\u0000\u0000\u0000\u02f8\u02f9"+ + "\u0007\u0013\u0000\u0000\u02f9\u02fa\u0007\u0007\u0000\u0000\u02fa\u02fb"+ + "\u0007\u0007\u0000\u0000\u02fb\u02fc\u0007\b\u0000\u0000\u02fc\u02fd\u0001"+ + "\u0000\u0000\u0000\u02fd\u02fe\u0006\u001c\n\u0000\u02feI\u0001\u0000"+ + "\u0000\u0000\u02ff\u0300\u0004\u001d\t\u0000\u0300\u0301\u0007\n\u0000"+ + "\u0000\u0301\u0302\u0007\u0005\u0000\u0000\u0302\u0303\u0007\u0011\u0000"+ + "\u0000\u0303\u0304\u0007\n\u0000\u0000\u0304\u0305\u0007\u0011\u0000\u0000"+ + "\u0305\u0306\u0007\u000b\u0000\u0000\u0306\u0307\u0005_\u0000\u0000\u0307"+ + "\u0308\u0005\u8001\uf414\u0000\u0000\u0308\u0309\u0001\u0000\u0000\u0000"+ + "\u0309\u030a\u0006\u001d\n\u0000\u030aK\u0001\u0000\u0000\u0000\u030b"+ + "\u030c\u0004\u001e\n\u0000\u030c\u030d\u0007\f\u0000\u0000\u030d\u030e"+ + "\u0007\f\u0000\u0000\u030e\u030f\u0007\u0015\u0000\u0000\u030f\u0310\u0001"+ + "\u0000\u0000\u0000\u0310\u0311\u0006\u001e\u0004\u0000\u0311M\u0001\u0000"+ + "\u0000\u0000\u0312\u0313\u0007\f\u0000\u0000\u0313\u0314\u0007\u0007\u0000"+ + "\u0000\u0314\u0315\u0007\u0005\u0000\u0000\u0315\u0316\u0007\u0004\u0000"+ + "\u0000\u0316\u0317\u0007\u000f\u0000\u0000\u0317\u0318\u0007\u0007\u0000"+ + "\u0000\u0318\u0319\u0001\u0000\u0000\u0000\u0319\u031a\u0006\u001f\u000b"+ + "\u0000\u031aO\u0001\u0000\u0000\u0000\u031b\u031c\u0007\u0011\u0000\u0000"+ + "\u031c\u031d\u0007\u0003\u0000\u0000\u031d\u031e\u0007\t\u0000\u0000\u031e"+ + "\u031f\u0007\u0014\u0000\u0000\u031f\u0320\u0001\u0000\u0000\u0000\u0320"+ + "\u0321\u0006 \f\u0000\u0321Q\u0001\u0000\u0000\u0000\u0322\u0324\b\u0017"+ + "\u0000\u0000\u0323\u0322\u0001\u0000\u0000\u0000\u0324\u0325\u0001\u0000"+ + "\u0000\u0000\u0325\u0323\u0001\u0000\u0000\u0000\u0325\u0326\u0001\u0000"+ + "\u0000\u0000\u0326\u0327\u0001\u0000\u0000\u0000\u0327\u0328\u0006!\u0004"+ + "\u0000\u0328S\u0001\u0000\u0000\u0000\u0329\u032a\u0003\u00aeO\u0000\u032a"+ + "\u032b\u0001\u0000\u0000\u0000\u032b\u032c\u0006\"\r\u0000\u032c\u032d"+ + "\u0006\"\u000e\u0000\u032dU\u0001\u0000\u0000\u0000\u032e\u032f\u0003"+ + "\u00f0p\u0000\u032f\u0330\u0001\u0000\u0000\u0000\u0330\u0331\u0006#\u000f"+ + "\u0000\u0331W\u0001\u0000\u0000\u0000\u0332\u0333\u0003\u00cc^\u0000\u0333"+ + "\u0334\u0001\u0000\u0000\u0000\u0334\u0335\u0006$\u0010\u0000\u0335Y\u0001"+ + "\u0000\u0000\u0000\u0336\u0337\u0003\u00dcf\u0000\u0337\u0338\u0001\u0000"+ + "\u0000\u0000\u0338\u0339\u0006%\u0011\u0000\u0339[\u0001\u0000\u0000\u0000"+ + "\u033a\u033b\u0003\u00d8d\u0000\u033b\u033c\u0001\u0000\u0000\u0000\u033c"+ + "\u033d\u0006&\u0012\u0000\u033d]\u0001\u0000\u0000\u0000\u033e\u033f\u0003"+ + "\u012c\u008e\u0000\u033f\u0340\u0001\u0000\u0000\u0000\u0340\u0341\u0006"+ + "\'\u0013\u0000\u0341_\u0001\u0000\u0000\u0000\u0342\u0343\u0003\u0128"+ + "\u008c\u0000\u0343\u0344\u0001\u0000\u0000\u0000\u0344\u0345\u0006(\u0014"+ + "\u0000\u0345a\u0001\u0000\u0000\u0000\u0346\u0347\u0003\u0010\u0000\u0000"+ + "\u0347\u0348\u0001\u0000\u0000\u0000\u0348\u0349\u0006)\u0000\u0000\u0349"+ + "c\u0001\u0000\u0000\u0000\u034a\u034b\u0003\u0012\u0001\u0000\u034b\u034c"+ + "\u0001\u0000\u0000\u0000\u034c\u034d\u0006*\u0000\u0000\u034de\u0001\u0000"+ + "\u0000\u0000\u034e\u034f\u0003\u0014\u0002\u0000\u034f\u0350\u0001\u0000"+ + "\u0000\u0000\u0350\u0351\u0006+\u0000\u0000\u0351g\u0001\u0000\u0000\u0000"+ + "\u0352\u0353\u0003\u00aeO\u0000\u0353\u0354\u0001\u0000\u0000\u0000\u0354"+ + "\u0355\u0006,\r\u0000\u0355\u0356\u0006,\u000e\u0000\u0356i\u0001\u0000"+ + "\u0000\u0000\u0357\u0358\u0003\u0120\u0088\u0000\u0358\u0359\u0001\u0000"+ + "\u0000\u0000\u0359\u035a\u0006-\u0015\u0000\u035a\u035b\u0006-\u0016\u0000"+ + "\u035bk\u0001\u0000\u0000\u0000\u035c\u035d\u0003\u00f0p\u0000\u035d\u035e"+ + "\u0001\u0000\u0000\u0000\u035e\u035f\u0006.\u000f\u0000\u035f\u0360\u0006"+ + ".\u0017\u0000\u0360m\u0001\u0000\u0000\u0000\u0361\u0362\u0003\u00fau"+ + "\u0000\u0362\u0363\u0001\u0000\u0000\u0000\u0363\u0364\u0006/\u0018\u0000"+ + "\u0364\u0365\u0006/\u0017\u0000\u0365o\u0001\u0000\u0000\u0000\u0366\u0367"+ + "\b\u0018\u0000\u0000\u0367q\u0001\u0000\u0000\u0000\u0368\u036a\u0003"+ + "p0\u0000\u0369\u0368\u0001\u0000\u0000\u0000\u036a\u036b\u0001\u0000\u0000"+ + "\u0000\u036b\u0369\u0001\u0000\u0000\u0000\u036b\u036c\u0001\u0000\u0000"+ + "\u0000\u036c\u036d\u0001\u0000\u0000\u0000\u036d\u036e\u0003\u00d6c\u0000"+ + "\u036e\u0370\u0001\u0000\u0000\u0000\u036f\u0369\u0001\u0000\u0000\u0000"+ + "\u036f\u0370\u0001\u0000\u0000\u0000\u0370\u0372\u0001\u0000\u0000\u0000"+ + "\u0371\u0373\u0003p0\u0000\u0372\u0371\u0001\u0000\u0000\u0000\u0373\u0374"+ + "\u0001\u0000\u0000\u0000\u0374\u0372\u0001\u0000\u0000\u0000\u0374\u0375"+ + "\u0001\u0000\u0000\u0000\u0375s\u0001\u0000\u0000\u0000\u0376\u0377\u0003"+ + "r1\u0000\u0377\u0378\u0001\u0000\u0000\u0000\u0378\u0379\u00062\u0019"+ + "\u0000\u0379u\u0001\u0000\u0000\u0000\u037a\u037b\u0003\u0010\u0000\u0000"+ + "\u037b\u037c\u0001\u0000\u0000\u0000\u037c\u037d\u00063\u0000\u0000\u037d"+ + "w\u0001\u0000\u0000\u0000\u037e\u037f\u0003\u0012\u0001\u0000\u037f\u0380"+ + "\u0001\u0000\u0000\u0000\u0380\u0381\u00064\u0000\u0000\u0381y\u0001\u0000"+ + "\u0000\u0000\u0382\u0383\u0003\u0014\u0002\u0000\u0383\u0384\u0001\u0000"+ + "\u0000\u0000\u0384\u0385\u00065\u0000\u0000\u0385{\u0001\u0000\u0000\u0000"+ + "\u0386\u0387\u0003\u00aeO\u0000\u0387\u0388\u0001\u0000\u0000\u0000\u0388"+ + "\u0389\u00066\r\u0000\u0389\u038a\u00066\u000e\u0000\u038a\u038b\u0006"+ + "6\u000e\u0000\u038b}\u0001\u0000\u0000\u0000\u038c\u038d\u0003\u00d0`"+ + "\u0000\u038d\u038e\u0001\u0000\u0000\u0000\u038e\u038f\u00067\u001a\u0000"+ + "\u038f\u007f\u0001\u0000\u0000\u0000\u0390\u0391\u0003\u00d8d\u0000\u0391"+ + "\u0392\u0001\u0000\u0000\u0000\u0392\u0393\u00068\u0012\u0000\u0393\u0081"+ + "\u0001\u0000\u0000\u0000\u0394\u0395\u0003\u00dcf\u0000\u0395\u0396\u0001"+ + "\u0000\u0000\u0000\u0396\u0397\u00069\u0011\u0000\u0397\u0083\u0001\u0000"+ + "\u0000\u0000\u0398\u0399\u0003\u00fau\u0000\u0399\u039a\u0001\u0000\u0000"+ + "\u0000\u039a\u039b\u0006:\u0018\u0000\u039b\u0085\u0001\u0000\u0000\u0000"+ + "\u039c\u039d\u0003\u01c0\u00d8\u0000\u039d\u039e\u0001\u0000\u0000\u0000"+ + "\u039e\u039f\u0006;\u001b\u0000\u039f\u0087\u0001\u0000\u0000\u0000\u03a0"+ + "\u03a1\u0003\u012c\u008e\u0000\u03a1\u03a2\u0001\u0000\u0000\u0000\u03a2"+ + "\u03a3\u0006<\u0013\u0000\u03a3\u0089\u0001\u0000\u0000\u0000\u03a4\u03a5"+ + "\u0003\u00f4r\u0000\u03a5\u03a6\u0001\u0000\u0000\u0000\u03a6\u03a7\u0006"+ + "=\u001c\u0000\u03a7\u008b\u0001\u0000\u0000\u0000\u03a8\u03a9\u0003\u011c"+ + "\u0086\u0000\u03a9\u03aa\u0001\u0000\u0000\u0000\u03aa\u03ab\u0006>\u001d"+ + "\u0000\u03ab\u008d\u0001\u0000\u0000\u0000\u03ac\u03ad\u0003\u0118\u0084"+ + "\u0000\u03ad\u03ae\u0001\u0000\u0000\u0000\u03ae\u03af\u0006?\u001e\u0000"+ + "\u03af\u008f\u0001\u0000\u0000\u0000\u03b0\u03b1\u0003\u011e\u0087\u0000"+ + "\u03b1\u03b2\u0001\u0000\u0000\u0000\u03b2\u03b3\u0006@\u001f\u0000\u03b3"+ + "\u0091\u0001\u0000\u0000\u0000\u03b4\u03b5\u0003\u0010\u0000\u0000\u03b5"+ + "\u03b6\u0001\u0000\u0000\u0000\u03b6\u03b7\u0006A\u0000\u0000\u03b7\u0093"+ + "\u0001\u0000\u0000\u0000\u03b8\u03b9\u0003\u0012\u0001\u0000\u03b9\u03ba"+ + "\u0001\u0000\u0000\u0000\u03ba\u03bb\u0006B\u0000\u0000\u03bb\u0095\u0001"+ + "\u0000\u0000\u0000\u03bc\u03bd\u0003\u0014\u0002\u0000\u03bd\u03be\u0001"+ + "\u0000\u0000\u0000\u03be\u03bf\u0006C\u0000\u0000\u03bf\u0097\u0001\u0000"+ + "\u0000\u0000\u03c0\u03c1\u0003\u0122\u0089\u0000\u03c1\u03c2\u0001\u0000"+ + "\u0000\u0000\u03c2\u03c3\u0006D \u0000\u03c3\u03c4\u0006D\u000e\u0000"+ + "\u03c4\u0099\u0001\u0000\u0000\u0000\u03c5\u03c6\u0003\u00d6c\u0000\u03c6"+ + "\u03c7\u0001\u0000\u0000\u0000\u03c7\u03c8\u0006E!\u0000\u03c8\u009b\u0001"+ + "\u0000\u0000\u0000\u03c9\u03cf\u0003\u00baU\u0000\u03ca\u03cf\u0003\u00b0"+ + "P\u0000\u03cb\u03cf\u0003\u00dcf\u0000\u03cc\u03cf\u0003\u00b2Q\u0000"+ + "\u03cd\u03cf\u0003\u00c0X\u0000\u03ce\u03c9\u0001\u0000\u0000\u0000\u03ce"+ + "\u03ca\u0001\u0000\u0000\u0000\u03ce\u03cb\u0001\u0000\u0000\u0000\u03ce"+ + "\u03cc\u0001\u0000\u0000\u0000\u03ce\u03cd\u0001\u0000\u0000\u0000\u03cf"+ + "\u03d0\u0001\u0000\u0000\u0000\u03d0\u03ce\u0001\u0000\u0000\u0000\u03d0"+ + "\u03d1\u0001\u0000\u0000\u0000\u03d1\u009d\u0001\u0000\u0000\u0000\u03d2"+ + "\u03d3\u0003\u0010\u0000\u0000\u03d3\u03d4\u0001\u0000\u0000\u0000\u03d4"+ + "\u03d5\u0006G\u0000\u0000\u03d5\u009f\u0001\u0000\u0000\u0000\u03d6\u03d7"+ + "\u0003\u0012\u0001\u0000\u03d7\u03d8\u0001\u0000\u0000\u0000\u03d8\u03d9"+ + "\u0006H\u0000\u0000\u03d9\u00a1\u0001\u0000\u0000\u0000\u03da\u03db\u0003"+ + "\u0014\u0002\u0000\u03db\u03dc\u0001\u0000\u0000\u0000\u03dc\u03dd\u0006"+ + "I\u0000\u0000\u03dd\u00a3\u0001\u0000\u0000\u0000\u03de\u03df\u0003\u0120"+ + "\u0088\u0000\u03df\u03e0\u0001\u0000\u0000\u0000\u03e0\u03e1\u0006J\u0015"+ + "\u0000\u03e1\u03e2\u0006J\"\u0000\u03e2\u00a5\u0001\u0000\u0000\u0000"+ + "\u03e3\u03e4\u0003\u00aeO\u0000\u03e4\u03e5\u0001\u0000\u0000\u0000\u03e5"+ + "\u03e6\u0006K\r\u0000\u03e6\u03e7\u0006K\u000e\u0000\u03e7\u00a7\u0001"+ + "\u0000\u0000\u0000\u03e8\u03e9\u0003\u0014\u0002\u0000\u03e9\u03ea\u0001"+ + "\u0000\u0000\u0000\u03ea\u03eb\u0006L\u0000\u0000\u03eb\u00a9\u0001\u0000"+ + "\u0000\u0000\u03ec\u03ed\u0003\u0010\u0000\u0000\u03ed\u03ee\u0001\u0000"+ + "\u0000\u0000\u03ee\u03ef\u0006M\u0000\u0000\u03ef\u00ab\u0001\u0000\u0000"+ + "\u0000\u03f0\u03f1\u0003\u0012\u0001\u0000\u03f1\u03f2\u0001\u0000\u0000"+ + "\u0000\u03f2\u03f3\u0006N\u0000\u0000\u03f3\u00ad\u0001\u0000\u0000\u0000"+ + "\u03f4\u03f5\u0005|\u0000\u0000\u03f5\u03f6\u0001\u0000\u0000\u0000\u03f6"+ + "\u03f7\u0006O\u000e\u0000\u03f7\u00af\u0001\u0000\u0000\u0000\u03f8\u03f9"+ + "\u0007\u0019\u0000\u0000\u03f9\u00b1\u0001\u0000\u0000\u0000\u03fa\u03fb"+ + "\u0007\u001a\u0000\u0000\u03fb\u00b3\u0001\u0000\u0000\u0000\u03fc\u03fd"+ + "\u0005\\\u0000\u0000\u03fd\u03fe\u0007\u001b\u0000\u0000\u03fe\u00b5\u0001"+ + "\u0000\u0000\u0000\u03ff\u0400\b\u001c\u0000\u0000\u0400\u00b7\u0001\u0000"+ + "\u0000\u0000\u0401\u0403\u0007\u0007\u0000\u0000\u0402\u0404\u0007\u001d"+ + "\u0000\u0000\u0403\u0402\u0001\u0000\u0000\u0000\u0403\u0404\u0001\u0000"+ + "\u0000\u0000\u0404\u0406\u0001\u0000\u0000\u0000\u0405\u0407\u0003\u00b0"+ + "P\u0000\u0406\u0405\u0001\u0000\u0000\u0000\u0407\u0408\u0001\u0000\u0000"+ + "\u0000\u0408\u0406\u0001\u0000\u0000\u0000\u0408\u0409\u0001\u0000\u0000"+ + "\u0000\u0409\u00b9\u0001\u0000\u0000\u0000\u040a\u040b\u0005@\u0000\u0000"+ + "\u040b\u00bb\u0001\u0000\u0000\u0000\u040c\u040d\u0005`\u0000\u0000\u040d"+ + "\u00bd\u0001\u0000\u0000\u0000\u040e\u0412\b\u001e\u0000\u0000\u040f\u0410"+ + "\u0005`\u0000\u0000\u0410\u0412\u0005`\u0000\u0000\u0411\u040e\u0001\u0000"+ + "\u0000\u0000\u0411\u040f\u0001\u0000\u0000\u0000\u0412\u00bf\u0001\u0000"+ + "\u0000\u0000\u0413\u0414\u0005_\u0000\u0000\u0414\u00c1\u0001\u0000\u0000"+ + "\u0000\u0415\u0419\u0003\u00b2Q\u0000\u0416\u0419\u0003\u00b0P\u0000\u0417"+ + "\u0419\u0003\u00c0X\u0000\u0418\u0415\u0001\u0000\u0000\u0000\u0418\u0416"+ + "\u0001\u0000\u0000\u0000\u0418\u0417\u0001\u0000\u0000\u0000\u0419\u00c3"+ + "\u0001\u0000\u0000\u0000\u041a\u041f\u0005\"\u0000\u0000\u041b\u041e\u0003"+ + "\u00b4R\u0000\u041c\u041e\u0003\u00b6S\u0000\u041d\u041b\u0001\u0000\u0000"+ + "\u0000\u041d\u041c\u0001\u0000\u0000\u0000\u041e\u0421\u0001\u0000\u0000"+ + "\u0000\u041f\u041d\u0001\u0000\u0000\u0000\u041f\u0420\u0001\u0000\u0000"+ + "\u0000\u0420\u0422\u0001\u0000\u0000\u0000\u0421\u041f\u0001\u0000\u0000"+ + "\u0000\u0422\u0438\u0005\"\u0000\u0000\u0423\u0424\u0005\"\u0000\u0000"+ + "\u0424\u0425\u0005\"\u0000\u0000\u0425\u0426\u0005\"\u0000\u0000\u0426"+ + "\u042a\u0001\u0000\u0000\u0000\u0427\u0429\b\u0000\u0000\u0000\u0428\u0427"+ + "\u0001\u0000\u0000\u0000\u0429\u042c\u0001\u0000\u0000\u0000\u042a\u042b"+ + "\u0001\u0000\u0000\u0000\u042a\u0428\u0001\u0000\u0000\u0000\u042b\u042d"+ + "\u0001\u0000\u0000\u0000\u042c\u042a\u0001\u0000\u0000\u0000\u042d\u042e"+ + "\u0005\"\u0000\u0000\u042e\u042f\u0005\"\u0000\u0000\u042f\u0430\u0005"+ + "\"\u0000\u0000\u0430\u0432\u0001\u0000\u0000\u0000\u0431\u0433\u0005\""+ + "\u0000\u0000\u0432\u0431\u0001\u0000\u0000\u0000\u0432\u0433\u0001\u0000"+ + "\u0000\u0000\u0433\u0435\u0001\u0000\u0000\u0000\u0434\u0436\u0005\"\u0000"+ + "\u0000\u0435\u0434\u0001\u0000\u0000\u0000\u0435\u0436\u0001\u0000\u0000"+ + "\u0000\u0436\u0438\u0001\u0000\u0000\u0000\u0437\u041a\u0001\u0000\u0000"+ + "\u0000\u0437\u0423\u0001\u0000\u0000\u0000\u0438\u00c5\u0001\u0000\u0000"+ + "\u0000\u0439\u043b\u0003\u00b0P\u0000\u043a\u0439\u0001\u0000\u0000\u0000"+ + "\u043b\u043c\u0001\u0000\u0000\u0000\u043c\u043a\u0001\u0000\u0000\u0000"+ + "\u043c\u043d\u0001\u0000\u0000\u0000\u043d\u00c7\u0001\u0000\u0000\u0000"+ + "\u043e\u0440\u0003\u00b0P\u0000\u043f\u043e\u0001\u0000\u0000\u0000\u0440"+ + "\u0441\u0001\u0000\u0000\u0000\u0441\u043f\u0001\u0000\u0000\u0000\u0441"+ + "\u0442\u0001\u0000\u0000\u0000\u0442\u0443\u0001\u0000\u0000\u0000\u0443"+ + "\u0447\u0003\u00dcf\u0000\u0444\u0446\u0003\u00b0P\u0000\u0445\u0444\u0001"+ + "\u0000\u0000\u0000\u0446\u0449\u0001\u0000\u0000\u0000\u0447\u0445\u0001"+ + "\u0000\u0000\u0000\u0447\u0448\u0001\u0000\u0000\u0000\u0448\u0469\u0001"+ + "\u0000\u0000\u0000\u0449\u0447\u0001\u0000\u0000\u0000\u044a\u044c\u0003"+ + "\u00dcf\u0000\u044b\u044d\u0003\u00b0P\u0000\u044c\u044b\u0001\u0000\u0000"+ + "\u0000\u044d\u044e\u0001\u0000\u0000\u0000\u044e\u044c\u0001\u0000\u0000"+ + "\u0000\u044e\u044f\u0001\u0000\u0000\u0000\u044f\u0469\u0001\u0000\u0000"+ + "\u0000\u0450\u0452\u0003\u00b0P\u0000\u0451\u0450\u0001\u0000\u0000\u0000"+ + "\u0452\u0453\u0001\u0000\u0000\u0000\u0453\u0451\u0001\u0000\u0000\u0000"+ + "\u0453\u0454\u0001\u0000\u0000\u0000\u0454\u045c\u0001\u0000\u0000\u0000"+ + "\u0455\u0459\u0003\u00dcf\u0000\u0456\u0458\u0003\u00b0P\u0000\u0457\u0456"+ + "\u0001\u0000\u0000\u0000\u0458\u045b\u0001\u0000\u0000\u0000\u0459\u0457"+ + "\u0001\u0000\u0000\u0000\u0459\u045a\u0001\u0000\u0000\u0000\u045a\u045d"+ + "\u0001\u0000\u0000\u0000\u045b\u0459\u0001\u0000\u0000\u0000\u045c\u0455"+ + "\u0001\u0000\u0000\u0000\u045c\u045d\u0001\u0000\u0000\u0000\u045d\u045e"+ + "\u0001\u0000\u0000\u0000\u045e\u045f\u0003\u00b8T\u0000\u045f\u0469\u0001"+ + "\u0000\u0000\u0000\u0460\u0462\u0003\u00dcf\u0000\u0461\u0463\u0003\u00b0"+ + "P\u0000\u0462\u0461\u0001\u0000\u0000\u0000\u0463\u0464\u0001\u0000\u0000"+ + "\u0000\u0464\u0462\u0001\u0000\u0000\u0000\u0464\u0465\u0001\u0000\u0000"+ + "\u0000\u0465\u0466\u0001\u0000\u0000\u0000\u0466\u0467\u0003\u00b8T\u0000"+ + "\u0467\u0469\u0001\u0000\u0000\u0000\u0468\u043f\u0001\u0000\u0000\u0000"+ + "\u0468\u044a\u0001\u0000\u0000\u0000\u0468\u0451\u0001\u0000\u0000\u0000"+ + "\u0468\u0460\u0001\u0000\u0000\u0000\u0469\u00c9\u0001\u0000\u0000\u0000"+ + "\u046a\u046b\u0007\u0004\u0000\u0000\u046b\u046c\u0007\u0005\u0000\u0000"+ + "\u046c\u046d\u0007\u0010\u0000\u0000\u046d\u00cb\u0001\u0000\u0000\u0000"+ + "\u046e\u046f\u0007\u0004\u0000\u0000\u046f\u0470\u0007\u0011\u0000\u0000"+ + "\u0470\u00cd\u0001\u0000\u0000\u0000\u0471\u0472\u0007\u0004\u0000\u0000"+ + "\u0472\u0473\u0007\u0011\u0000\u0000\u0473\u0474\u0007\u0002\u0000\u0000"+ + "\u0474\u00cf\u0001\u0000\u0000\u0000\u0475\u0476\u0005=\u0000\u0000\u0476"+ + "\u00d1\u0001\u0000\u0000\u0000\u0477\u0478\u0007\u001f\u0000\u0000\u0478"+ + "\u0479\u0007 \u0000\u0000\u0479\u00d3\u0001\u0000\u0000\u0000\u047a\u047b"+ + "\u0005:\u0000\u0000\u047b\u047c\u0005:\u0000\u0000\u047c\u00d5\u0001\u0000"+ + "\u0000\u0000\u047d\u047e\u0005:\u0000\u0000\u047e\u00d7\u0001\u0000\u0000"+ + "\u0000\u047f\u0480\u0005,\u0000\u0000\u0480\u00d9\u0001\u0000\u0000\u0000"+ + "\u0481\u0482\u0007\u0010\u0000\u0000\u0482\u0483\u0007\u0007\u0000\u0000"+ + "\u0483\u0484\u0007\u0011\u0000\u0000\u0484\u0485\u0007\u0002\u0000\u0000"+ + "\u0485\u00db\u0001\u0000\u0000\u0000\u0486\u0487\u0005.\u0000\u0000\u0487"+ + "\u00dd\u0001\u0000\u0000\u0000\u0488\u0489\u0007\u0015\u0000\u0000\u0489"+ + "\u048a\u0007\u0004\u0000\u0000\u048a\u048b\u0007\u000e\u0000\u0000\u048b"+ + "\u048c\u0007\u0011\u0000\u0000\u048c\u048d\u0007\u0007\u0000\u0000\u048d"+ + "\u00df\u0001\u0000\u0000\u0000\u048e\u048f\u0007\u0015\u0000\u0000\u048f"+ + "\u0490\u0007\n\u0000\u0000\u0490\u0491\u0007\f\u0000\u0000\u0491\u0492"+ + "\u0007\u0011\u0000\u0000\u0492\u0493\u0007\u000b\u0000\u0000\u0493\u00e1"+ + "\u0001\u0000\u0000\u0000\u0494\u0495\u0007\n\u0000\u0000\u0495\u0496\u0007"+ + "\u0005\u0000\u0000\u0496\u00e3\u0001\u0000\u0000\u0000\u0497\u0498\u0007"+ + "\n\u0000\u0000\u0498\u0499\u0007\u0011\u0000\u0000\u0499\u00e5\u0001\u0000"+ + "\u0000\u0000\u049a\u049b\u0007\u000e\u0000\u0000\u049b\u049c\u0007\u0004"+ + "\u0000\u0000\u049c\u049d\u0007\u0011\u0000\u0000\u049d\u049e\u0007\u000b"+ + "\u0000\u0000\u049e\u00e7\u0001\u0000\u0000\u0000\u049f\u04a0\u0007\u000e"+ + "\u0000\u0000\u04a0\u04a1\u0007\n\u0000\u0000\u04a1\u04a2\u0007\u0013\u0000"+ + "\u0000\u04a2\u04a3\u0007\u0007\u0000\u0000\u04a3\u00e9\u0001\u0000\u0000"+ + "\u0000\u04a4\u04a5\u0007\u0005\u0000\u0000\u04a5\u04a6\u0007\t\u0000\u0000"+ + "\u04a6\u04a7\u0007\u000b\u0000\u0000\u04a7\u00eb\u0001\u0000\u0000\u0000"+ + "\u04a8\u04a9\u0007\u0005\u0000\u0000\u04a9\u04aa\u0007\u0016\u0000\u0000"+ + "\u04aa\u04ab\u0007\u000e\u0000\u0000\u04ab\u04ac\u0007\u000e\u0000\u0000"+ + "\u04ac\u00ed\u0001\u0000\u0000\u0000\u04ad\u04ae\u0007\u0005\u0000\u0000"+ + "\u04ae\u04af\u0007\u0016\u0000\u0000\u04af\u04b0\u0007\u000e\u0000\u0000"+ + "\u04b0\u04b1\u0007\u000e\u0000\u0000\u04b1\u04b2\u0007\u0011\u0000\u0000"+ + "\u04b2\u00ef\u0001\u0000\u0000\u0000\u04b3\u04b4\u0007\t\u0000\u0000\u04b4"+ + "\u04b5\u0007\u0005\u0000\u0000\u04b5\u00f1\u0001\u0000\u0000\u0000\u04b6"+ + "\u04b7\u0007\t\u0000\u0000\u04b7\u04b8\u0007\f\u0000\u0000\u04b8\u00f3"+ + "\u0001\u0000\u0000\u0000\u04b9\u04ba\u0005?\u0000\u0000\u04ba\u00f5\u0001"+ + "\u0000\u0000\u0000\u04bb\u04bc\u0007\f\u0000\u0000\u04bc\u04bd\u0007\u000e"+ + "\u0000\u0000\u04bd\u04be\u0007\n\u0000\u0000\u04be\u04bf\u0007\u0013\u0000"+ + "\u0000\u04bf\u04c0\u0007\u0007\u0000\u0000\u04c0\u00f7\u0001\u0000\u0000"+ + "\u0000\u04c1\u04c2\u0007\u000b\u0000\u0000\u04c2\u04c3\u0007\f\u0000\u0000"+ + "\u04c3\u04c4\u0007\u0016\u0000\u0000\u04c4\u04c5\u0007\u0007\u0000\u0000"+ + "\u04c5\u00f9\u0001\u0000\u0000\u0000\u04c6\u04c7\u0007\u0014\u0000\u0000"+ + "\u04c7\u04c8\u0007\n\u0000\u0000\u04c8\u04c9\u0007\u000b\u0000\u0000\u04c9"+ + "\u04ca\u0007\u0003\u0000\u0000\u04ca\u00fb\u0001\u0000\u0000\u0000\u04cb"+ + "\u04cc\u0005=\u0000\u0000\u04cc\u04cd\u0005=\u0000\u0000\u04cd\u00fd\u0001"+ + "\u0000\u0000\u0000\u04ce\u04cf\u0005=\u0000\u0000\u04cf\u04d0\u0005~\u0000"+ + "\u0000\u04d0\u00ff\u0001\u0000\u0000\u0000\u04d1\u04d2\u0005!\u0000\u0000"+ + "\u04d2\u04d3\u0005=\u0000\u0000\u04d3\u0101\u0001\u0000\u0000\u0000\u04d4"+ + "\u04d5\u0005<\u0000\u0000\u04d5\u0103\u0001\u0000\u0000\u0000\u04d6\u04d7"+ + "\u0005<\u0000\u0000\u04d7\u04d8\u0005=\u0000\u0000\u04d8\u0105\u0001\u0000"+ + "\u0000\u0000\u04d9\u04da\u0005>\u0000\u0000\u04da\u0107\u0001\u0000\u0000"+ + "\u0000\u04db\u04dc\u0005>\u0000\u0000\u04dc\u04dd\u0005=\u0000\u0000\u04dd"+ + "\u0109\u0001\u0000\u0000\u0000\u04de\u04df\u0005+\u0000\u0000\u04df\u010b"+ + "\u0001\u0000\u0000\u0000\u04e0\u04e1\u0005-\u0000\u0000\u04e1\u010d\u0001"+ + "\u0000\u0000\u0000\u04e2\u04e3\u0005*\u0000\u0000\u04e3\u010f\u0001\u0000"+ + "\u0000\u0000\u04e4\u04e5\u0005/\u0000\u0000\u04e5\u0111\u0001\u0000\u0000"+ + "\u0000\u04e6\u04e7\u0005%\u0000\u0000\u04e7\u0113\u0001\u0000\u0000\u0000"+ + "\u04e8\u04e9\u0005{\u0000\u0000\u04e9\u0115\u0001\u0000\u0000\u0000\u04ea"+ + "\u04eb\u0005}\u0000\u0000\u04eb\u0117\u0001\u0000\u0000\u0000\u04ec\u04ed"+ + "\u0005?\u0000\u0000\u04ed\u04ee\u0005?\u0000\u0000\u04ee\u0119\u0001\u0000"+ + "\u0000\u0000\u04ef\u04f0\u0003,\u000e\u0000\u04f0\u04f1\u0001\u0000\u0000"+ + "\u0000\u04f1\u04f2\u0006\u0085#\u0000\u04f2\u011b\u0001\u0000\u0000\u0000"+ + "\u04f3\u04f6\u0003\u00f4r\u0000\u04f4\u04f7\u0003\u00b2Q\u0000\u04f5\u04f7"+ + "\u0003\u00c0X\u0000\u04f6\u04f4\u0001\u0000\u0000\u0000\u04f6\u04f5\u0001"+ + "\u0000\u0000\u0000\u04f7\u04fb\u0001\u0000\u0000\u0000\u04f8\u04fa\u0003"+ + "\u00c2Y\u0000\u04f9\u04f8\u0001\u0000\u0000\u0000\u04fa\u04fd\u0001\u0000"+ + "\u0000\u0000\u04fb\u04f9\u0001\u0000\u0000\u0000\u04fb\u04fc\u0001\u0000"+ + "\u0000\u0000\u04fc\u0505\u0001\u0000\u0000\u0000\u04fd\u04fb\u0001\u0000"+ + "\u0000\u0000\u04fe\u0500\u0003\u00f4r\u0000\u04ff\u0501\u0003\u00b0P\u0000"+ + "\u0500\u04ff\u0001\u0000\u0000\u0000\u0501\u0502\u0001\u0000\u0000\u0000"+ + "\u0502\u0500\u0001\u0000\u0000\u0000\u0502\u0503\u0001\u0000\u0000\u0000"+ + "\u0503\u0505\u0001\u0000\u0000\u0000\u0504\u04f3\u0001\u0000\u0000\u0000"+ + "\u0504\u04fe\u0001\u0000\u0000\u0000\u0505\u011d\u0001\u0000\u0000\u0000"+ + "\u0506\u0509\u0003\u0118\u0084\u0000\u0507\u050a\u0003\u00b2Q\u0000\u0508"+ + "\u050a\u0003\u00c0X\u0000\u0509\u0507\u0001\u0000\u0000\u0000\u0509\u0508"+ + "\u0001\u0000\u0000\u0000\u050a\u050e\u0001\u0000\u0000\u0000\u050b\u050d"+ + "\u0003\u00c2Y\u0000\u050c\u050b\u0001\u0000\u0000\u0000\u050d\u0510\u0001"+ + "\u0000\u0000\u0000\u050e\u050c\u0001\u0000\u0000\u0000\u050e\u050f\u0001"+ + "\u0000\u0000\u0000\u050f\u0518\u0001\u0000\u0000\u0000\u0510\u050e\u0001"+ + "\u0000\u0000\u0000\u0511\u0513\u0003\u0118\u0084\u0000\u0512\u0514\u0003"+ + "\u00b0P\u0000\u0513\u0512\u0001\u0000\u0000\u0000\u0514\u0515\u0001\u0000"+ + "\u0000\u0000\u0515\u0513\u0001\u0000\u0000\u0000\u0515\u0516\u0001\u0000"+ + "\u0000\u0000\u0516\u0518\u0001\u0000\u0000\u0000\u0517\u0506\u0001\u0000"+ + "\u0000\u0000\u0517\u0511\u0001\u0000\u0000\u0000\u0518\u011f\u0001\u0000"+ + "\u0000\u0000\u0519\u051a\u0005[\u0000\u0000\u051a\u051b\u0001\u0000\u0000"+ + "\u0000\u051b\u051c\u0006\u0088\u0004\u0000\u051c\u051d\u0006\u0088\u0004"+ + "\u0000\u051d\u0121\u0001\u0000\u0000\u0000\u051e\u051f\u0005]\u0000\u0000"+ + "\u051f\u0520\u0001\u0000\u0000\u0000\u0520\u0521\u0006\u0089\u000e\u0000"+ + "\u0521\u0522\u0006\u0089\u000e\u0000\u0522\u0123\u0001\u0000\u0000\u0000"+ + "\u0523\u0524\u0005(\u0000\u0000\u0524\u0525\u0001\u0000\u0000\u0000\u0525"+ + "\u0526\u0006\u008a\u0004\u0000\u0526\u0527\u0006\u008a\u0004\u0000\u0527"+ + "\u0125\u0001\u0000\u0000\u0000\u0528\u0529\u0005)\u0000\u0000\u0529\u052a"+ + "\u0001\u0000\u0000\u0000\u052a\u052b\u0006\u008b\u000e\u0000\u052b\u052c"+ + "\u0006\u008b\u000e\u0000\u052c\u0127\u0001\u0000\u0000\u0000\u052d\u0531"+ + "\u0003\u00b2Q\u0000\u052e\u0530\u0003\u00c2Y\u0000\u052f\u052e\u0001\u0000"+ + "\u0000\u0000\u0530\u0533\u0001\u0000\u0000\u0000\u0531\u052f\u0001\u0000"+ + "\u0000\u0000\u0531\u0532\u0001\u0000\u0000\u0000\u0532\u053e\u0001\u0000"+ + "\u0000\u0000\u0533\u0531\u0001\u0000\u0000\u0000\u0534\u0537\u0003\u00c0"+ + "X\u0000\u0535\u0537\u0003\u00baU\u0000\u0536\u0534\u0001\u0000\u0000\u0000"+ + "\u0536\u0535\u0001\u0000\u0000\u0000\u0537\u0539\u0001\u0000\u0000\u0000"+ + "\u0538\u053a\u0003\u00c2Y\u0000\u0539\u0538\u0001\u0000\u0000\u0000\u053a"+ + "\u053b\u0001\u0000\u0000\u0000\u053b\u0539\u0001\u0000\u0000\u0000\u053b"+ + "\u053c\u0001\u0000\u0000\u0000\u053c\u053e\u0001\u0000\u0000\u0000\u053d"+ + "\u052d\u0001\u0000\u0000\u0000\u053d\u0536\u0001\u0000\u0000\u0000\u053e"+ + "\u0129\u0001\u0000\u0000\u0000\u053f\u0541\u0003\u00bcV\u0000\u0540\u0542"+ + "\u0003\u00beW\u0000\u0541\u0540\u0001\u0000\u0000\u0000\u0542\u0543\u0001"+ + "\u0000\u0000\u0000\u0543\u0541\u0001\u0000\u0000\u0000\u0543\u0544\u0001"+ + "\u0000\u0000\u0000\u0544\u0545\u0001\u0000\u0000\u0000\u0545\u0546\u0003"+ + "\u00bcV\u0000\u0546\u012b\u0001\u0000\u0000\u0000\u0547\u0548\u0003\u012a"+ + "\u008d\u0000\u0548\u012d\u0001\u0000\u0000\u0000\u0549\u054a\u0003\u0010"+ + "\u0000\u0000\u054a\u054b\u0001\u0000\u0000\u0000\u054b\u054c\u0006\u008f"+ + "\u0000\u0000\u054c\u012f\u0001\u0000\u0000\u0000\u054d\u054e\u0003\u0012"+ + "\u0001\u0000\u054e\u054f\u0001\u0000\u0000\u0000\u054f\u0550\u0006\u0090"+ + "\u0000\u0000\u0550\u0131\u0001\u0000\u0000\u0000\u0551\u0552\u0003\u0014"+ + "\u0002\u0000\u0552\u0553\u0001\u0000\u0000\u0000\u0553\u0554\u0006\u0091"+ + "\u0000\u0000\u0554\u0133\u0001\u0000\u0000\u0000\u0555\u0556\u0003\u00ae"+ + "O\u0000\u0556\u0557\u0001\u0000\u0000\u0000\u0557\u0558\u0006\u0092\r"+ + "\u0000\u0558\u0559\u0006\u0092\u000e\u0000\u0559\u0135\u0001\u0000\u0000"+ + "\u0000\u055a\u055b\u0003\u0120\u0088\u0000\u055b\u055c\u0001\u0000\u0000"+ + "\u0000\u055c\u055d\u0006\u0093\u0015\u0000\u055d\u0137\u0001\u0000\u0000"+ + "\u0000\u055e\u055f\u0003\u0122\u0089\u0000\u055f\u0560\u0001\u0000\u0000"+ + "\u0000\u0560\u0561\u0006\u0094 \u0000\u0561\u0139\u0001\u0000\u0000\u0000"+ + "\u0562\u0563\u0003\u00d6c\u0000\u0563\u0564\u0001\u0000\u0000\u0000\u0564"+ + "\u0565\u0006\u0095!\u0000\u0565\u013b\u0001\u0000\u0000\u0000\u0566\u0567"+ + "\u0003\u00d4b\u0000\u0567\u0568\u0001\u0000\u0000\u0000\u0568\u0569\u0006"+ + "\u0096$\u0000\u0569\u013d\u0001\u0000\u0000\u0000\u056a\u056b\u0003\u00d8"+ + "d\u0000\u056b\u056c\u0001\u0000\u0000\u0000\u056c\u056d\u0006\u0097\u0012"+ + "\u0000\u056d\u013f\u0001\u0000\u0000\u0000\u056e\u056f\u0003\u00d0`\u0000"+ + "\u056f\u0570\u0001\u0000\u0000\u0000\u0570\u0571\u0006\u0098\u001a\u0000"+ + "\u0571\u0141\u0001\u0000\u0000\u0000\u0572\u0573\u0007\u000f\u0000\u0000"+ + "\u0573\u0574\u0007\u0007\u0000\u0000\u0574\u0575\u0007\u000b\u0000\u0000"+ + "\u0575\u0576\u0007\u0004\u0000\u0000\u0576\u0577\u0007\u0010\u0000\u0000"+ + "\u0577\u0578\u0007\u0004\u0000\u0000\u0578\u0579\u0007\u000b\u0000\u0000"+ + "\u0579\u057a\u0007\u0004\u0000\u0000\u057a\u0143\u0001\u0000\u0000\u0000"+ + "\u057b\u057f\b!\u0000\u0000\u057c\u057d\u0005/\u0000\u0000\u057d\u057f"+ + "\b\"\u0000\u0000\u057e\u057b\u0001\u0000\u0000\u0000\u057e\u057c\u0001"+ + "\u0000\u0000\u0000\u057f\u0145\u0001\u0000\u0000\u0000\u0580\u0582\u0003"+ + "\u0144\u009a\u0000\u0581\u0580\u0001\u0000\u0000\u0000\u0582\u0583\u0001"+ + "\u0000\u0000\u0000\u0583\u0581\u0001\u0000\u0000\u0000\u0583\u0584\u0001"+ + "\u0000\u0000\u0000\u0584\u0147\u0001\u0000\u0000\u0000\u0585\u0586\u0003"+ + "\u0146\u009b\u0000\u0586\u0587\u0001\u0000\u0000\u0000\u0587\u0588\u0006"+ + "\u009c%\u0000\u0588\u0149\u0001\u0000\u0000\u0000\u0589\u058a\u0003\u00c4"+ + "Z\u0000\u058a\u058b\u0001\u0000\u0000\u0000\u058b\u058c\u0006\u009d&\u0000"+ + "\u058c\u014b\u0001\u0000\u0000\u0000\u058d\u058e\u0003\u0010\u0000\u0000"+ + "\u058e\u058f\u0001\u0000\u0000\u0000\u058f\u0590\u0006\u009e\u0000\u0000"+ + "\u0590\u014d\u0001\u0000\u0000\u0000\u0591\u0592\u0003\u0012\u0001\u0000"+ + "\u0592\u0593\u0001\u0000\u0000\u0000\u0593\u0594\u0006\u009f\u0000\u0000"+ + "\u0594\u014f\u0001\u0000\u0000\u0000\u0595\u0596\u0003\u0014\u0002\u0000"+ + "\u0596\u0597\u0001\u0000\u0000\u0000\u0597\u0598\u0006\u00a0\u0000\u0000"+ + "\u0598\u0151\u0001\u0000\u0000\u0000\u0599\u059a\u0003\u0124\u008a\u0000"+ + "\u059a\u059b\u0001\u0000\u0000\u0000\u059b\u059c\u0006\u00a1\'\u0000\u059c"+ + "\u059d\u0006\u00a1\"\u0000\u059d\u0153\u0001\u0000\u0000\u0000\u059e\u059f"+ + "\u0003\u00aeO\u0000\u059f\u05a0\u0001\u0000\u0000\u0000\u05a0\u05a1\u0006"+ + "\u00a2\r\u0000\u05a1\u05a2\u0006\u00a2\u000e\u0000\u05a2\u0155\u0001\u0000"+ + "\u0000\u0000\u05a3\u05a4\u0003\u0014\u0002\u0000\u05a4\u05a5\u0001\u0000"+ + "\u0000\u0000\u05a5\u05a6\u0006\u00a3\u0000\u0000\u05a6\u0157\u0001\u0000"+ + "\u0000\u0000\u05a7\u05a8\u0003\u0010\u0000\u0000\u05a8\u05a9\u0001\u0000"+ + "\u0000\u0000\u05a9\u05aa\u0006\u00a4\u0000\u0000\u05aa\u0159\u0001\u0000"+ + "\u0000\u0000\u05ab\u05ac\u0003\u0012\u0001\u0000\u05ac\u05ad\u0001\u0000"+ + "\u0000\u0000\u05ad\u05ae\u0006\u00a5\u0000\u0000\u05ae\u015b\u0001\u0000"+ + "\u0000\u0000\u05af\u05b0\u0003\u00aeO\u0000\u05b0\u05b1\u0001\u0000\u0000"+ + "\u0000\u05b1\u05b2\u0006\u00a6\r\u0000\u05b2\u05b3\u0006\u00a6\u000e\u0000"+ + "\u05b3\u015d\u0001\u0000\u0000\u0000\u05b4\u05b5\u0007#\u0000\u0000\u05b5"+ + "\u05b6\u0007\t\u0000\u0000\u05b6\u05b7\u0007\n\u0000\u0000\u05b7\u05b8"+ + "\u0007\u0005\u0000\u0000\u05b8\u015f\u0001\u0000\u0000\u0000\u05b9\u05ba"+ + "\u0003\u00cc^\u0000\u05ba\u05bb\u0001\u0000\u0000\u0000\u05bb\u05bc\u0006"+ + "\u00a8\u0010\u0000\u05bc\u0161\u0001\u0000\u0000\u0000\u05bd\u05be\u0003"+ + "\u00f0p\u0000\u05be\u05bf\u0001\u0000\u0000\u0000\u05bf\u05c0\u0006\u00a9"+ + "\u000f\u0000\u05c0\u05c1\u0006\u00a9\u000e\u0000\u05c1\u05c2\u0006\u00a9"+ + "\u0004\u0000\u05c2\u0163\u0001\u0000\u0000\u0000\u05c3\u05c4\u0007\u0016"+ + "\u0000\u0000\u05c4\u05c5\u0007\u0011\u0000\u0000\u05c5\u05c6\u0007\n\u0000"+ + "\u0000\u05c6\u05c7\u0007\u0005\u0000\u0000\u05c7\u05c8\u0007\u0006\u0000"+ + "\u0000\u05c8\u05c9\u0001\u0000\u0000\u0000\u05c9\u05ca\u0006\u00aa\u000e"+ + "\u0000\u05ca\u05cb\u0006\u00aa\u0004\u0000\u05cb\u0165\u0001\u0000\u0000"+ + "\u0000\u05cc\u05cd\u0003\u0146\u009b\u0000\u05cd\u05ce\u0001\u0000\u0000"+ + "\u0000\u05ce\u05cf\u0006\u00ab%\u0000\u05cf\u0167\u0001\u0000\u0000\u0000"+ + "\u05d0\u05d1\u0003\u00c4Z\u0000\u05d1\u05d2\u0001\u0000\u0000\u0000\u05d2"+ + "\u05d3\u0006\u00ac&\u0000\u05d3\u0169\u0001\u0000\u0000\u0000\u05d4\u05d5"+ + "\u0003\u00d6c\u0000\u05d5\u05d6\u0001\u0000\u0000\u0000\u05d6\u05d7\u0006"+ + "\u00ad!\u0000\u05d7\u016b\u0001\u0000\u0000\u0000\u05d8\u05d9\u0003\u0128"+ + "\u008c\u0000\u05d9\u05da\u0001\u0000\u0000\u0000\u05da\u05db\u0006\u00ae"+ + "\u0014\u0000\u05db\u016d\u0001\u0000\u0000\u0000\u05dc\u05dd\u0003\u012c"+ + "\u008e\u0000\u05dd\u05de\u0001\u0000\u0000\u0000\u05de\u05df\u0006\u00af"+ + "\u0013\u0000\u05df\u016f\u0001\u0000\u0000\u0000\u05e0\u05e1\u0003\u0010"+ + "\u0000\u0000\u05e1\u05e2\u0001\u0000\u0000\u0000\u05e2\u05e3\u0006\u00b0"+ + "\u0000\u0000\u05e3\u0171\u0001\u0000\u0000\u0000\u05e4\u05e5\u0003\u0012"+ + "\u0001\u0000\u05e5\u05e6\u0001\u0000\u0000\u0000\u05e6\u05e7\u0006\u00b1"+ + "\u0000\u0000\u05e7\u0173\u0001\u0000\u0000\u0000\u05e8\u05e9\u0003\u0014"+ + "\u0002\u0000\u05e9\u05ea\u0001\u0000\u0000\u0000\u05ea\u05eb\u0006\u00b2"+ + "\u0000\u0000\u05eb\u0175\u0001\u0000\u0000\u0000\u05ec\u05ed\u0003\u00ae"+ + "O\u0000\u05ed\u05ee\u0001\u0000\u0000\u0000\u05ee\u05ef\u0006\u00b3\r"+ + "\u0000\u05ef\u05f0\u0006\u00b3\u000e\u0000\u05f0\u0177\u0001\u0000\u0000"+ + "\u0000\u05f1\u05f2\u0003\u00d6c\u0000\u05f2\u05f3\u0001\u0000\u0000\u0000"+ + "\u05f3\u05f4\u0006\u00b4!\u0000\u05f4\u0179\u0001\u0000\u0000\u0000\u05f5"+ + "\u05f6\u0003\u00d8d\u0000\u05f6\u05f7\u0001\u0000\u0000\u0000\u05f7\u05f8"+ + "\u0006\u00b5\u0012\u0000\u05f8\u017b\u0001\u0000\u0000\u0000\u05f9\u05fa"+ + "\u0003\u00dcf\u0000\u05fa\u05fb\u0001\u0000\u0000\u0000\u05fb\u05fc\u0006"+ + "\u00b6\u0011\u0000\u05fc\u017d\u0001\u0000\u0000\u0000\u05fd\u05fe\u0003"+ + "\u00f0p\u0000\u05fe\u05ff\u0001\u0000\u0000\u0000\u05ff\u0600\u0006\u00b7"+ + "\u000f\u0000\u0600\u0601\u0006\u00b7(\u0000\u0601\u017f\u0001\u0000\u0000"+ + "\u0000\u0602\u0603\u0003\u0146\u009b\u0000\u0603\u0604\u0001\u0000\u0000"+ + "\u0000\u0604\u0605\u0006\u00b8%\u0000\u0605\u0181\u0001\u0000\u0000\u0000"+ + "\u0606\u0607\u0003\u00c4Z\u0000\u0607\u0608\u0001\u0000\u0000\u0000\u0608"+ + "\u0609\u0006\u00b9&\u0000\u0609\u0183\u0001\u0000\u0000\u0000\u060a\u060b"+ + "\u0003\u0010\u0000\u0000\u060b\u060c\u0001\u0000\u0000\u0000\u060c\u060d"+ + "\u0006\u00ba\u0000\u0000\u060d\u0185\u0001\u0000\u0000\u0000\u060e\u060f"+ + "\u0003\u0012\u0001\u0000\u060f\u0610\u0001\u0000\u0000\u0000\u0610\u0611"+ + "\u0006\u00bb\u0000\u0000\u0611\u0187\u0001\u0000\u0000\u0000\u0612\u0613"+ + "\u0003\u0014\u0002\u0000\u0613\u0614\u0001\u0000\u0000\u0000\u0614\u0615"+ + "\u0006\u00bc\u0000\u0000\u0615\u0189\u0001\u0000\u0000\u0000\u0616\u0617"+ + "\u0003\u00aeO\u0000\u0617\u0618\u0001\u0000\u0000\u0000\u0618\u0619\u0006"+ + "\u00bd\r\u0000\u0619\u061a\u0006\u00bd\u000e\u0000\u061a\u061b\u0006\u00bd"+ + "\u000e\u0000\u061b\u018b\u0001\u0000\u0000\u0000\u061c\u061d\u0003\u00d8"+ + "d\u0000\u061d\u061e\u0001\u0000\u0000\u0000\u061e\u061f\u0006\u00be\u0012"+ + "\u0000\u061f\u018d\u0001\u0000\u0000\u0000\u0620\u0621\u0003\u00dcf\u0000"+ + "\u0621\u0622\u0001\u0000\u0000\u0000\u0622\u0623\u0006\u00bf\u0011\u0000"+ + "\u0623\u018f\u0001\u0000\u0000\u0000\u0624\u0625\u0003\u01c0\u00d8\u0000"+ + "\u0625\u0626\u0001\u0000\u0000\u0000\u0626\u0627\u0006\u00c0\u001b\u0000"+ + "\u0627\u0191\u0001\u0000\u0000\u0000\u0628\u0629\u0003\u0010\u0000\u0000"+ + "\u0629\u062a\u0001\u0000\u0000\u0000\u062a\u062b\u0006\u00c1\u0000\u0000"+ + "\u062b\u0193\u0001\u0000\u0000\u0000\u062c\u062d\u0003\u0012\u0001\u0000"+ + "\u062d\u062e\u0001\u0000\u0000\u0000\u062e\u062f\u0006\u00c2\u0000\u0000"+ + "\u062f\u0195\u0001\u0000\u0000\u0000\u0630\u0631\u0003\u0014\u0002\u0000"+ + "\u0631\u0632\u0001\u0000\u0000\u0000\u0632\u0633\u0006\u00c3\u0000\u0000"+ + "\u0633\u0197\u0001\u0000\u0000\u0000\u0634\u0635\u0003\u00aeO\u0000\u0635"+ + "\u0636\u0001\u0000\u0000\u0000\u0636\u0637\u0006\u00c4\r\u0000\u0637\u0638"+ + "\u0006\u00c4\u000e\u0000\u0638\u0199\u0001\u0000\u0000\u0000\u0639\u063a"+ + "\u0003\u00dcf\u0000\u063a\u063b\u0001\u0000\u0000\u0000\u063b\u063c\u0006"+ + "\u00c5\u0011\u0000\u063c\u019b\u0001\u0000\u0000\u0000\u063d\u063e\u0003"+ + "\u00f4r\u0000\u063e\u063f\u0001\u0000\u0000\u0000\u063f\u0640\u0006\u00c6"+ + "\u001c\u0000\u0640\u019d\u0001\u0000\u0000\u0000\u0641\u0642\u0003\u011c"+ + "\u0086\u0000\u0642\u0643\u0001\u0000\u0000\u0000\u0643\u0644\u0006\u00c7"+ + "\u001d\u0000\u0644\u019f\u0001\u0000\u0000\u0000\u0645\u0646\u0003\u0118"+ + "\u0084\u0000\u0646\u0647\u0001\u0000\u0000\u0000\u0647\u0648\u0006\u00c8"+ + "\u001e\u0000\u0648\u01a1\u0001\u0000\u0000\u0000\u0649\u064a\u0003\u011e"+ + "\u0087\u0000\u064a\u064b\u0001\u0000\u0000\u0000\u064b\u064c\u0006\u00c9"+ + "\u001f\u0000\u064c\u01a3\u0001\u0000\u0000\u0000\u064d\u064e\u0003\u012c"+ + "\u008e\u0000\u064e\u064f\u0001\u0000\u0000\u0000\u064f\u0650\u0006\u00ca"+ + "\u0013\u0000\u0650\u01a5\u0001\u0000\u0000\u0000\u0651\u0652\u0003\u0128"+ + "\u008c\u0000\u0652\u0653\u0001\u0000\u0000\u0000\u0653\u0654\u0006\u00cb"+ + "\u0014\u0000\u0654\u01a7\u0001\u0000\u0000\u0000\u0655\u0656\u0003\u0010"+ + "\u0000\u0000\u0656\u0657\u0001\u0000\u0000\u0000\u0657\u0658\u0006\u00cc"+ + "\u0000\u0000\u0658\u01a9\u0001\u0000\u0000\u0000\u0659\u065a\u0003\u0012"+ + "\u0001\u0000\u065a\u065b\u0001\u0000\u0000\u0000\u065b\u065c\u0006\u00cd"+ + "\u0000\u0000\u065c\u01ab\u0001\u0000\u0000\u0000\u065d\u065e\u0003\u0014"+ + "\u0002\u0000\u065e\u065f\u0001\u0000\u0000\u0000\u065f\u0660\u0006\u00ce"+ + "\u0000\u0000\u0660\u01ad\u0001\u0000\u0000\u0000\u0661\u0662\u0003\u00ae"+ + "O\u0000\u0662\u0663\u0001\u0000\u0000\u0000\u0663\u0664\u0006\u00cf\r"+ + "\u0000\u0664\u0665\u0006\u00cf\u000e\u0000\u0665\u01af\u0001\u0000\u0000"+ + "\u0000\u0666\u0667\u0003\u00dcf\u0000\u0667\u0668\u0001\u0000\u0000\u0000"+ + "\u0668\u0669\u0006\u00d0\u0011\u0000\u0669\u01b1\u0001\u0000\u0000\u0000"+ + "\u066a\u066b\u0003\u00d8d\u0000\u066b\u066c\u0001\u0000\u0000\u0000\u066c"+ + "\u066d\u0006\u00d1\u0012\u0000\u066d\u01b3\u0001\u0000\u0000\u0000\u066e"+ + "\u066f\u0003\u00f4r\u0000\u066f\u0670\u0001\u0000\u0000\u0000\u0670\u0671"+ + "\u0006\u00d2\u001c\u0000\u0671\u01b5\u0001\u0000\u0000\u0000\u0672\u0673"+ + "\u0003\u011c\u0086\u0000\u0673\u0674\u0001\u0000\u0000\u0000\u0674\u0675"+ + "\u0006\u00d3\u001d\u0000\u0675\u01b7\u0001\u0000\u0000\u0000\u0676\u0677"+ + "\u0003\u0118\u0084\u0000\u0677\u0678\u0001\u0000\u0000\u0000\u0678\u0679"+ + "\u0006\u00d4\u001e\u0000\u0679\u01b9\u0001\u0000\u0000\u0000\u067a\u067b"+ + "\u0003\u011e\u0087\u0000\u067b\u067c\u0001\u0000\u0000\u0000\u067c\u067d"+ + "\u0006\u00d5\u001f\u0000\u067d\u01bb\u0001\u0000\u0000\u0000\u067e\u0683"+ + "\u0003\u00b2Q\u0000\u067f\u0683\u0003\u00b0P\u0000\u0680\u0683\u0003\u00c0"+ + "X\u0000\u0681\u0683\u0003\u010e\u007f\u0000\u0682\u067e\u0001\u0000\u0000"+ + "\u0000\u0682\u067f\u0001\u0000\u0000\u0000\u0682\u0680\u0001\u0000\u0000"+ + "\u0000\u0682\u0681\u0001\u0000\u0000\u0000\u0683\u01bd\u0001\u0000\u0000"+ + "\u0000\u0684\u0687\u0003\u00b2Q\u0000\u0685\u0687\u0003\u010e\u007f\u0000"+ + "\u0686\u0684\u0001\u0000\u0000\u0000\u0686\u0685\u0001\u0000\u0000\u0000"+ + "\u0687\u068b\u0001\u0000\u0000\u0000\u0688\u068a\u0003\u01bc\u00d6\u0000"+ + "\u0689\u0688\u0001\u0000\u0000\u0000\u068a\u068d\u0001\u0000\u0000\u0000"+ + "\u068b\u0689\u0001\u0000\u0000\u0000\u068b\u068c\u0001\u0000\u0000\u0000"+ + "\u068c\u0698\u0001\u0000\u0000\u0000\u068d\u068b\u0001\u0000\u0000\u0000"+ + "\u068e\u0691\u0003\u00c0X\u0000\u068f\u0691\u0003\u00baU\u0000\u0690\u068e"+ + "\u0001\u0000\u0000\u0000\u0690\u068f\u0001\u0000\u0000\u0000\u0691\u0693"+ + "\u0001\u0000\u0000\u0000\u0692\u0694\u0003\u01bc\u00d6\u0000\u0693\u0692"+ + "\u0001\u0000\u0000\u0000\u0694\u0695\u0001\u0000\u0000\u0000\u0695\u0693"+ + "\u0001\u0000\u0000\u0000\u0695\u0696\u0001\u0000\u0000\u0000\u0696\u0698"+ + "\u0001\u0000\u0000\u0000\u0697\u0686\u0001\u0000\u0000\u0000\u0697\u0690"+ + "\u0001\u0000\u0000\u0000\u0698\u01bf\u0001\u0000\u0000\u0000\u0699\u069c"+ + "\u0003\u01be\u00d7\u0000\u069a\u069c\u0003\u012a\u008d\u0000\u069b\u0699"+ + "\u0001\u0000\u0000\u0000\u069b\u069a\u0001\u0000\u0000\u0000\u069c\u069d"+ + "\u0001\u0000\u0000\u0000\u069d\u069b\u0001\u0000\u0000\u0000\u069d\u069e"+ + "\u0001\u0000\u0000\u0000\u069e\u01c1\u0001\u0000\u0000\u0000\u069f\u06a0"+ + "\u0003\u0010\u0000\u0000\u06a0\u06a1\u0001\u0000\u0000\u0000\u06a1\u06a2"+ + "\u0006\u00d9\u0000\u0000\u06a2\u01c3\u0001\u0000\u0000\u0000\u06a3\u06a4"+ + "\u0003\u0012\u0001\u0000\u06a4\u06a5\u0001\u0000\u0000\u0000\u06a5\u06a6"+ + "\u0006\u00da\u0000\u0000\u06a6\u01c5\u0001\u0000\u0000\u0000\u06a7\u06a8"+ + "\u0003\u0014\u0002\u0000\u06a8\u06a9\u0001\u0000\u0000\u0000\u06a9\u06aa"+ + "\u0006\u00db\u0000\u0000\u06aa\u01c7\u0001\u0000\u0000\u0000\u06ab\u06ac"+ + "\u0003\u00aeO\u0000\u06ac\u06ad\u0001\u0000\u0000\u0000\u06ad\u06ae\u0006"+ + "\u00dc\r\u0000\u06ae\u06af\u0006\u00dc\u000e\u0000\u06af\u01c9\u0001\u0000"+ + "\u0000\u0000\u06b0\u06b1\u0003\u00d0`\u0000\u06b1\u06b2\u0001\u0000\u0000"+ + "\u0000\u06b2\u06b3\u0006\u00dd\u001a\u0000\u06b3\u01cb\u0001\u0000\u0000"+ + "\u0000\u06b4\u06b5\u0003\u00d8d\u0000\u06b5\u06b6\u0001\u0000\u0000\u0000"+ + "\u06b6\u06b7\u0006\u00de\u0012\u0000\u06b7\u01cd\u0001\u0000\u0000\u0000"+ + "\u06b8\u06b9\u0003\u00dcf\u0000\u06b9\u06ba\u0001\u0000\u0000\u0000\u06ba"+ + "\u06bb\u0006\u00df\u0011\u0000\u06bb\u01cf\u0001\u0000\u0000\u0000\u06bc"+ + "\u06bd\u0003\u00f4r\u0000\u06bd\u06be\u0001\u0000\u0000\u0000\u06be\u06bf"+ + "\u0006\u00e0\u001c\u0000\u06bf\u01d1\u0001\u0000\u0000\u0000\u06c0\u06c1"+ + "\u0003\u011c\u0086\u0000\u06c1\u06c2\u0001\u0000\u0000\u0000\u06c2\u06c3"+ + "\u0006\u00e1\u001d\u0000\u06c3\u01d3\u0001\u0000\u0000\u0000\u06c4\u06c5"+ + "\u0003\u0118\u0084\u0000\u06c5\u06c6\u0001\u0000\u0000\u0000\u06c6\u06c7"+ + "\u0006\u00e2\u001e\u0000\u06c7\u01d5\u0001\u0000\u0000\u0000\u06c8\u06c9"+ + "\u0003\u011e\u0087\u0000\u06c9\u06ca\u0001\u0000\u0000\u0000\u06ca\u06cb"+ + "\u0006\u00e3\u001f\u0000\u06cb\u01d7\u0001\u0000\u0000\u0000\u06cc\u06cd"+ + "\u0003\u00cc^\u0000\u06cd\u06ce\u0001\u0000\u0000\u0000\u06ce\u06cf\u0006"+ + "\u00e4\u0010\u0000\u06cf\u01d9\u0001\u0000\u0000\u0000\u06d0\u06d1\u0003"+ + "\u01c0\u00d8\u0000\u06d1\u06d2\u0001\u0000\u0000\u0000\u06d2\u06d3\u0006"+ + "\u00e5\u001b\u0000\u06d3\u01db\u0001\u0000\u0000\u0000\u06d4\u06d5\u0003"+ + "\u0010\u0000\u0000\u06d5\u06d6\u0001\u0000\u0000\u0000\u06d6\u06d7\u0006"+ + "\u00e6\u0000\u0000\u06d7\u01dd\u0001\u0000\u0000\u0000\u06d8\u06d9\u0003"+ + "\u0012\u0001\u0000\u06d9\u06da\u0001\u0000\u0000\u0000\u06da\u06db\u0006"+ + "\u00e7\u0000\u0000\u06db\u01df\u0001\u0000\u0000\u0000\u06dc\u06dd\u0003"+ + "\u0014\u0002\u0000\u06dd\u06de\u0001\u0000\u0000\u0000\u06de\u06df\u0006"+ + "\u00e8\u0000\u0000\u06df\u01e1\u0001\u0000\u0000\u0000\u06e0\u06e1\u0003"+ + "\u00aeO\u0000\u06e1\u06e2\u0001\u0000\u0000\u0000\u06e2\u06e3\u0006\u00e9"+ + "\r\u0000\u06e3\u06e4\u0006\u00e9\u000e\u0000\u06e4\u01e3\u0001\u0000\u0000"+ + "\u0000\u06e5\u06e6\u0007\n\u0000\u0000\u06e6\u06e7\u0007\u0005\u0000\u0000"+ + "\u06e7\u06e8\u0007\u0015\u0000\u0000\u06e8\u06e9\u0007\t\u0000\u0000\u06e9"+ + "\u01e5\u0001\u0000\u0000\u0000\u06ea\u06eb\u0003\u0010\u0000\u0000\u06eb"+ + "\u06ec\u0001\u0000\u0000\u0000\u06ec\u06ed\u0006\u00eb\u0000\u0000\u06ed"+ + "\u01e7\u0001\u0000\u0000\u0000\u06ee\u06ef\u0003\u0012\u0001\u0000\u06ef"+ + "\u06f0\u0001\u0000\u0000\u0000\u06f0\u06f1\u0006\u00ec\u0000\u0000\u06f1"+ + "\u01e9\u0001\u0000\u0000\u0000\u06f2\u06f3\u0003\u0014\u0002\u0000\u06f3"+ + "\u06f4\u0001\u0000\u0000\u0000\u06f4\u06f5\u0006\u00ed\u0000\u0000\u06f5"+ + "\u01eb\u0001\u0000\u0000\u0000F\u0000\u0001\u0002\u0003\u0004\u0005\u0006"+ + "\u0007\b\t\n\u000b\f\r\u000e\u000f\u01f2\u01f6\u01f9\u0202\u0204\u020f"+ + "\u0325\u036b\u036f\u0374\u03ce\u03d0\u0403\u0408\u0411\u0418\u041d\u041f"+ + "\u042a\u0432\u0435\u0437\u043c\u0441\u0447\u044e\u0453\u0459\u045c\u0464"+ + "\u0468\u04f6\u04fb\u0502\u0504\u0509\u050e\u0515\u0517\u0531\u0536\u053b"+ + "\u053d\u0543\u057e\u0583\u0682\u0686\u068b\u0690\u0695\u0697\u069b\u069d"+ + ")\u0000\u0001\u0000\u0005\u0001\u0000\u0005\u0002\u0000\u0005\u0005\u0000"+ + "\u0005\u0006\u0000\u0005\u0007\u0000\u0005\b\u0000\u0005\t\u0000\u0005"+ + "\n\u0000\u0005\f\u0000\u0005\r\u0000\u0005\u000e\u0000\u0005\u000f\u0000"+ + "\u00074\u0000\u0004\u0000\u0000\u0007K\u0000\u00079\u0000\u0007A\u0000"+ + "\u0007?\u0000\u0007g\u0000\u0007f\u0000\u0007b\u0000\u0005\u0004\u0000"+ + "\u0005\u0003\u0000\u0007P\u0000\u0007&\u0000\u0007;\u0000\u0007\u0081"+ + "\u0000\u0007M\u0000\u0007`\u0000\u0007_\u0000\u0007a\u0000\u0007c\u0000"+ + "\u0007>\u0000\u0005\u0000\u0000\u0007\u000f\u0000\u0007=\u0000\u0007l"+ + "\u0000\u00075\u0000\u0007d\u0000\u0005\u000b\u0000"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp index e88c08f8368f6..3cc1109d65077 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp @@ -6,6 +6,7 @@ null 'change_point' 'enrich' 'explain' +'completion' 'dissect' 'eval' 'grok' @@ -17,7 +18,6 @@ null null null null -null 'from' null null @@ -148,6 +148,7 @@ WS CHANGE_POINT ENRICH EXPLAIN +COMPLETION DISSECT EVAL GROK @@ -156,7 +157,6 @@ ROW SORT STATS WHERE -DEV_COMPLETION DEV_INLINESTATS DEV_RERANK DEV_SAMPLE @@ -368,4 +368,4 @@ joinPredicate atn: -[4, 1, 139, 773, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 174, 8, 1, 10, 1, 12, 1, 177, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 185, 8, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 217, 8, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 5, 7, 230, 8, 7, 10, 7, 12, 7, 233, 9, 7, 1, 8, 1, 8, 1, 8, 3, 8, 238, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 5, 9, 245, 8, 9, 10, 9, 12, 9, 248, 9, 9, 1, 10, 1, 10, 1, 10, 3, 10, 253, 8, 10, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 5, 13, 264, 8, 13, 10, 13, 12, 13, 267, 9, 13, 1, 13, 3, 13, 270, 8, 13, 1, 14, 1, 14, 1, 14, 3, 14, 275, 8, 14, 1, 14, 1, 14, 1, 14, 1, 14, 3, 14, 281, 8, 14, 3, 14, 283, 8, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 295, 8, 18, 10, 18, 12, 18, 298, 9, 18, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 3, 20, 305, 8, 20, 1, 20, 1, 20, 3, 20, 309, 8, 20, 1, 21, 1, 21, 1, 21, 5, 21, 314, 8, 21, 10, 21, 12, 21, 317, 9, 21, 1, 22, 1, 22, 1, 22, 3, 22, 322, 8, 22, 1, 23, 1, 23, 1, 23, 5, 23, 327, 8, 23, 10, 23, 12, 23, 330, 9, 23, 1, 24, 1, 24, 1, 24, 5, 24, 335, 8, 24, 10, 24, 12, 24, 338, 9, 24, 1, 25, 1, 25, 1, 25, 5, 25, 343, 8, 25, 10, 25, 12, 25, 346, 9, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 3, 27, 353, 8, 27, 1, 28, 1, 28, 3, 28, 357, 8, 28, 1, 29, 1, 29, 3, 29, 361, 8, 29, 1, 30, 1, 30, 1, 30, 3, 30, 366, 8, 30, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 5, 32, 375, 8, 32, 10, 32, 12, 32, 378, 9, 32, 1, 33, 1, 33, 3, 33, 382, 8, 33, 1, 33, 1, 33, 3, 33, 386, 8, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 5, 36, 398, 8, 36, 10, 36, 12, 36, 401, 9, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 411, 8, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 5, 41, 423, 8, 41, 10, 41, 12, 41, 426, 9, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 3, 46, 446, 8, 46, 1, 46, 1, 46, 1, 46, 1, 46, 5, 46, 452, 8, 46, 10, 46, 12, 46, 455, 9, 46, 3, 46, 457, 8, 46, 1, 47, 1, 47, 1, 47, 3, 47, 462, 8, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 3, 49, 475, 8, 49, 1, 50, 1, 50, 1, 50, 1, 50, 3, 50, 481, 8, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 3, 50, 488, 8, 50, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 53, 4, 53, 497, 8, 53, 11, 53, 12, 53, 498, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 5, 55, 511, 8, 55, 10, 55, 12, 55, 514, 9, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 3, 56, 522, 8, 56, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 3, 58, 532, 8, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 3, 59, 540, 8, 59, 1, 60, 1, 60, 1, 60, 3, 60, 545, 8, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 3, 61, 554, 8, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 5, 61, 561, 8, 61, 10, 61, 12, 61, 564, 9, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 3, 61, 571, 8, 61, 1, 61, 1, 61, 1, 61, 3, 61, 576, 8, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 5, 61, 584, 8, 61, 10, 61, 12, 61, 587, 9, 61, 1, 62, 1, 62, 3, 62, 591, 8, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 3, 62, 598, 8, 62, 1, 62, 1, 62, 1, 62, 3, 62, 603, 8, 62, 1, 63, 1, 63, 1, 63, 3, 63, 608, 8, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 3, 64, 618, 8, 64, 1, 65, 1, 65, 1, 65, 1, 65, 3, 65, 624, 8, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 5, 65, 632, 8, 65, 10, 65, 12, 65, 635, 9, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 3, 66, 645, 8, 66, 1, 66, 1, 66, 1, 66, 5, 66, 650, 8, 66, 10, 66, 12, 66, 653, 9, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 5, 67, 661, 8, 67, 10, 67, 12, 67, 664, 9, 67, 1, 67, 1, 67, 3, 67, 668, 8, 67, 3, 67, 670, 8, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 5, 69, 680, 8, 69, 10, 69, 12, 69, 683, 9, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 704, 8, 71, 10, 71, 12, 71, 707, 9, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 715, 8, 71, 10, 71, 12, 71, 718, 9, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 726, 8, 71, 10, 71, 12, 71, 729, 9, 71, 1, 71, 1, 71, 3, 71, 733, 8, 71, 1, 72, 1, 72, 1, 73, 1, 73, 3, 73, 739, 8, 73, 1, 74, 3, 74, 742, 8, 74, 1, 74, 1, 74, 1, 75, 3, 75, 747, 8, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 5, 80, 766, 8, 80, 10, 80, 12, 80, 769, 9, 80, 1, 81, 1, 81, 1, 81, 0, 5, 2, 110, 122, 130, 132, 82, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 0, 9, 2, 0, 53, 53, 108, 108, 1, 0, 102, 103, 2, 0, 58, 58, 64, 64, 2, 0, 67, 67, 70, 70, 1, 0, 88, 89, 1, 0, 90, 92, 2, 0, 66, 66, 79, 79, 2, 0, 81, 81, 83, 87, 2, 0, 22, 22, 24, 25, 805, 0, 164, 1, 0, 0, 0, 2, 167, 1, 0, 0, 0, 4, 184, 1, 0, 0, 0, 6, 216, 1, 0, 0, 0, 8, 218, 1, 0, 0, 0, 10, 221, 1, 0, 0, 0, 12, 223, 1, 0, 0, 0, 14, 226, 1, 0, 0, 0, 16, 237, 1, 0, 0, 0, 18, 241, 1, 0, 0, 0, 20, 249, 1, 0, 0, 0, 22, 254, 1, 0, 0, 0, 24, 257, 1, 0, 0, 0, 26, 260, 1, 0, 0, 0, 28, 282, 1, 0, 0, 0, 30, 284, 1, 0, 0, 0, 32, 286, 1, 0, 0, 0, 34, 288, 1, 0, 0, 0, 36, 290, 1, 0, 0, 0, 38, 299, 1, 0, 0, 0, 40, 302, 1, 0, 0, 0, 42, 310, 1, 0, 0, 0, 44, 318, 1, 0, 0, 0, 46, 323, 1, 0, 0, 0, 48, 331, 1, 0, 0, 0, 50, 339, 1, 0, 0, 0, 52, 347, 1, 0, 0, 0, 54, 352, 1, 0, 0, 0, 56, 356, 1, 0, 0, 0, 58, 360, 1, 0, 0, 0, 60, 365, 1, 0, 0, 0, 62, 367, 1, 0, 0, 0, 64, 370, 1, 0, 0, 0, 66, 379, 1, 0, 0, 0, 68, 387, 1, 0, 0, 0, 70, 390, 1, 0, 0, 0, 72, 393, 1, 0, 0, 0, 74, 402, 1, 0, 0, 0, 76, 406, 1, 0, 0, 0, 78, 412, 1, 0, 0, 0, 80, 416, 1, 0, 0, 0, 82, 419, 1, 0, 0, 0, 84, 427, 1, 0, 0, 0, 86, 431, 1, 0, 0, 0, 88, 434, 1, 0, 0, 0, 90, 438, 1, 0, 0, 0, 92, 441, 1, 0, 0, 0, 94, 461, 1, 0, 0, 0, 96, 465, 1, 0, 0, 0, 98, 470, 1, 0, 0, 0, 100, 476, 1, 0, 0, 0, 102, 489, 1, 0, 0, 0, 104, 492, 1, 0, 0, 0, 106, 496, 1, 0, 0, 0, 108, 500, 1, 0, 0, 0, 110, 504, 1, 0, 0, 0, 112, 521, 1, 0, 0, 0, 114, 523, 1, 0, 0, 0, 116, 525, 1, 0, 0, 0, 118, 533, 1, 0, 0, 0, 120, 541, 1, 0, 0, 0, 122, 575, 1, 0, 0, 0, 124, 602, 1, 0, 0, 0, 126, 604, 1, 0, 0, 0, 128, 617, 1, 0, 0, 0, 130, 623, 1, 0, 0, 0, 132, 644, 1, 0, 0, 0, 134, 654, 1, 0, 0, 0, 136, 673, 1, 0, 0, 0, 138, 675, 1, 0, 0, 0, 140, 686, 1, 0, 0, 0, 142, 732, 1, 0, 0, 0, 144, 734, 1, 0, 0, 0, 146, 738, 1, 0, 0, 0, 148, 741, 1, 0, 0, 0, 150, 746, 1, 0, 0, 0, 152, 750, 1, 0, 0, 0, 154, 752, 1, 0, 0, 0, 156, 754, 1, 0, 0, 0, 158, 759, 1, 0, 0, 0, 160, 761, 1, 0, 0, 0, 162, 770, 1, 0, 0, 0, 164, 165, 3, 2, 1, 0, 165, 166, 5, 0, 0, 1, 166, 1, 1, 0, 0, 0, 167, 168, 6, 1, -1, 0, 168, 169, 3, 4, 2, 0, 169, 175, 1, 0, 0, 0, 170, 171, 10, 1, 0, 0, 171, 172, 5, 52, 0, 0, 172, 174, 3, 6, 3, 0, 173, 170, 1, 0, 0, 0, 174, 177, 1, 0, 0, 0, 175, 173, 1, 0, 0, 0, 175, 176, 1, 0, 0, 0, 176, 3, 1, 0, 0, 0, 177, 175, 1, 0, 0, 0, 178, 185, 3, 86, 43, 0, 179, 185, 3, 22, 11, 0, 180, 185, 3, 12, 6, 0, 181, 185, 3, 90, 45, 0, 182, 183, 4, 2, 1, 0, 183, 185, 3, 24, 12, 0, 184, 178, 1, 0, 0, 0, 184, 179, 1, 0, 0, 0, 184, 180, 1, 0, 0, 0, 184, 181, 1, 0, 0, 0, 184, 182, 1, 0, 0, 0, 185, 5, 1, 0, 0, 0, 186, 217, 3, 38, 19, 0, 187, 217, 3, 8, 4, 0, 188, 217, 3, 68, 34, 0, 189, 217, 3, 62, 31, 0, 190, 217, 3, 40, 20, 0, 191, 217, 3, 64, 32, 0, 192, 217, 3, 70, 35, 0, 193, 217, 3, 72, 36, 0, 194, 217, 3, 76, 38, 0, 195, 217, 3, 78, 39, 0, 196, 217, 3, 92, 46, 0, 197, 217, 3, 80, 40, 0, 198, 217, 3, 156, 78, 0, 199, 217, 3, 100, 50, 0, 200, 201, 4, 3, 2, 0, 201, 217, 3, 98, 49, 0, 202, 203, 4, 3, 3, 0, 203, 217, 3, 96, 48, 0, 204, 205, 4, 3, 4, 0, 205, 217, 3, 118, 59, 0, 206, 207, 4, 3, 5, 0, 207, 217, 3, 102, 51, 0, 208, 209, 4, 3, 6, 0, 209, 217, 3, 104, 52, 0, 210, 211, 4, 3, 7, 0, 211, 217, 3, 116, 58, 0, 212, 213, 4, 3, 8, 0, 213, 217, 3, 114, 57, 0, 214, 215, 4, 3, 9, 0, 215, 217, 3, 120, 60, 0, 216, 186, 1, 0, 0, 0, 216, 187, 1, 0, 0, 0, 216, 188, 1, 0, 0, 0, 216, 189, 1, 0, 0, 0, 216, 190, 1, 0, 0, 0, 216, 191, 1, 0, 0, 0, 216, 192, 1, 0, 0, 0, 216, 193, 1, 0, 0, 0, 216, 194, 1, 0, 0, 0, 216, 195, 1, 0, 0, 0, 216, 196, 1, 0, 0, 0, 216, 197, 1, 0, 0, 0, 216, 198, 1, 0, 0, 0, 216, 199, 1, 0, 0, 0, 216, 200, 1, 0, 0, 0, 216, 202, 1, 0, 0, 0, 216, 204, 1, 0, 0, 0, 216, 206, 1, 0, 0, 0, 216, 208, 1, 0, 0, 0, 216, 210, 1, 0, 0, 0, 216, 212, 1, 0, 0, 0, 216, 214, 1, 0, 0, 0, 217, 7, 1, 0, 0, 0, 218, 219, 5, 14, 0, 0, 219, 220, 3, 122, 61, 0, 220, 9, 1, 0, 0, 0, 221, 222, 3, 52, 26, 0, 222, 11, 1, 0, 0, 0, 223, 224, 5, 11, 0, 0, 224, 225, 3, 14, 7, 0, 225, 13, 1, 0, 0, 0, 226, 231, 3, 16, 8, 0, 227, 228, 5, 63, 0, 0, 228, 230, 3, 16, 8, 0, 229, 227, 1, 0, 0, 0, 230, 233, 1, 0, 0, 0, 231, 229, 1, 0, 0, 0, 231, 232, 1, 0, 0, 0, 232, 15, 1, 0, 0, 0, 233, 231, 1, 0, 0, 0, 234, 235, 3, 46, 23, 0, 235, 236, 5, 59, 0, 0, 236, 238, 1, 0, 0, 0, 237, 234, 1, 0, 0, 0, 237, 238, 1, 0, 0, 0, 238, 239, 1, 0, 0, 0, 239, 240, 3, 122, 61, 0, 240, 17, 1, 0, 0, 0, 241, 246, 3, 20, 10, 0, 242, 243, 5, 63, 0, 0, 243, 245, 3, 20, 10, 0, 244, 242, 1, 0, 0, 0, 245, 248, 1, 0, 0, 0, 246, 244, 1, 0, 0, 0, 246, 247, 1, 0, 0, 0, 247, 19, 1, 0, 0, 0, 248, 246, 1, 0, 0, 0, 249, 252, 3, 46, 23, 0, 250, 251, 5, 59, 0, 0, 251, 253, 3, 122, 61, 0, 252, 250, 1, 0, 0, 0, 252, 253, 1, 0, 0, 0, 253, 21, 1, 0, 0, 0, 254, 255, 5, 19, 0, 0, 255, 256, 3, 26, 13, 0, 256, 23, 1, 0, 0, 0, 257, 258, 5, 20, 0, 0, 258, 259, 3, 26, 13, 0, 259, 25, 1, 0, 0, 0, 260, 265, 3, 28, 14, 0, 261, 262, 5, 63, 0, 0, 262, 264, 3, 28, 14, 0, 263, 261, 1, 0, 0, 0, 264, 267, 1, 0, 0, 0, 265, 263, 1, 0, 0, 0, 265, 266, 1, 0, 0, 0, 266, 269, 1, 0, 0, 0, 267, 265, 1, 0, 0, 0, 268, 270, 3, 36, 18, 0, 269, 268, 1, 0, 0, 0, 269, 270, 1, 0, 0, 0, 270, 27, 1, 0, 0, 0, 271, 272, 3, 30, 15, 0, 272, 273, 5, 62, 0, 0, 273, 275, 1, 0, 0, 0, 274, 271, 1, 0, 0, 0, 274, 275, 1, 0, 0, 0, 275, 276, 1, 0, 0, 0, 276, 283, 3, 34, 17, 0, 277, 280, 3, 34, 17, 0, 278, 279, 5, 61, 0, 0, 279, 281, 3, 32, 16, 0, 280, 278, 1, 0, 0, 0, 280, 281, 1, 0, 0, 0, 281, 283, 1, 0, 0, 0, 282, 274, 1, 0, 0, 0, 282, 277, 1, 0, 0, 0, 283, 29, 1, 0, 0, 0, 284, 285, 7, 0, 0, 0, 285, 31, 1, 0, 0, 0, 286, 287, 7, 0, 0, 0, 287, 33, 1, 0, 0, 0, 288, 289, 7, 0, 0, 0, 289, 35, 1, 0, 0, 0, 290, 291, 5, 107, 0, 0, 291, 296, 5, 108, 0, 0, 292, 293, 5, 63, 0, 0, 293, 295, 5, 108, 0, 0, 294, 292, 1, 0, 0, 0, 295, 298, 1, 0, 0, 0, 296, 294, 1, 0, 0, 0, 296, 297, 1, 0, 0, 0, 297, 37, 1, 0, 0, 0, 298, 296, 1, 0, 0, 0, 299, 300, 5, 8, 0, 0, 300, 301, 3, 14, 7, 0, 301, 39, 1, 0, 0, 0, 302, 304, 5, 13, 0, 0, 303, 305, 3, 42, 21, 0, 304, 303, 1, 0, 0, 0, 304, 305, 1, 0, 0, 0, 305, 308, 1, 0, 0, 0, 306, 307, 5, 60, 0, 0, 307, 309, 3, 14, 7, 0, 308, 306, 1, 0, 0, 0, 308, 309, 1, 0, 0, 0, 309, 41, 1, 0, 0, 0, 310, 315, 3, 44, 22, 0, 311, 312, 5, 63, 0, 0, 312, 314, 3, 44, 22, 0, 313, 311, 1, 0, 0, 0, 314, 317, 1, 0, 0, 0, 315, 313, 1, 0, 0, 0, 315, 316, 1, 0, 0, 0, 316, 43, 1, 0, 0, 0, 317, 315, 1, 0, 0, 0, 318, 321, 3, 16, 8, 0, 319, 320, 5, 14, 0, 0, 320, 322, 3, 122, 61, 0, 321, 319, 1, 0, 0, 0, 321, 322, 1, 0, 0, 0, 322, 45, 1, 0, 0, 0, 323, 328, 3, 60, 30, 0, 324, 325, 5, 65, 0, 0, 325, 327, 3, 60, 30, 0, 326, 324, 1, 0, 0, 0, 327, 330, 1, 0, 0, 0, 328, 326, 1, 0, 0, 0, 328, 329, 1, 0, 0, 0, 329, 47, 1, 0, 0, 0, 330, 328, 1, 0, 0, 0, 331, 336, 3, 54, 27, 0, 332, 333, 5, 65, 0, 0, 333, 335, 3, 54, 27, 0, 334, 332, 1, 0, 0, 0, 335, 338, 1, 0, 0, 0, 336, 334, 1, 0, 0, 0, 336, 337, 1, 0, 0, 0, 337, 49, 1, 0, 0, 0, 338, 336, 1, 0, 0, 0, 339, 344, 3, 48, 24, 0, 340, 341, 5, 63, 0, 0, 341, 343, 3, 48, 24, 0, 342, 340, 1, 0, 0, 0, 343, 346, 1, 0, 0, 0, 344, 342, 1, 0, 0, 0, 344, 345, 1, 0, 0, 0, 345, 51, 1, 0, 0, 0, 346, 344, 1, 0, 0, 0, 347, 348, 7, 1, 0, 0, 348, 53, 1, 0, 0, 0, 349, 353, 5, 129, 0, 0, 350, 353, 3, 56, 28, 0, 351, 353, 3, 58, 29, 0, 352, 349, 1, 0, 0, 0, 352, 350, 1, 0, 0, 0, 352, 351, 1, 0, 0, 0, 353, 55, 1, 0, 0, 0, 354, 357, 5, 77, 0, 0, 355, 357, 5, 96, 0, 0, 356, 354, 1, 0, 0, 0, 356, 355, 1, 0, 0, 0, 357, 57, 1, 0, 0, 0, 358, 361, 5, 95, 0, 0, 359, 361, 5, 97, 0, 0, 360, 358, 1, 0, 0, 0, 360, 359, 1, 0, 0, 0, 361, 59, 1, 0, 0, 0, 362, 366, 3, 52, 26, 0, 363, 366, 3, 56, 28, 0, 364, 366, 3, 58, 29, 0, 365, 362, 1, 0, 0, 0, 365, 363, 1, 0, 0, 0, 365, 364, 1, 0, 0, 0, 366, 61, 1, 0, 0, 0, 367, 368, 5, 10, 0, 0, 368, 369, 3, 142, 71, 0, 369, 63, 1, 0, 0, 0, 370, 371, 5, 12, 0, 0, 371, 376, 3, 66, 33, 0, 372, 373, 5, 63, 0, 0, 373, 375, 3, 66, 33, 0, 374, 372, 1, 0, 0, 0, 375, 378, 1, 0, 0, 0, 376, 374, 1, 0, 0, 0, 376, 377, 1, 0, 0, 0, 377, 65, 1, 0, 0, 0, 378, 376, 1, 0, 0, 0, 379, 381, 3, 122, 61, 0, 380, 382, 7, 2, 0, 0, 381, 380, 1, 0, 0, 0, 381, 382, 1, 0, 0, 0, 382, 385, 1, 0, 0, 0, 383, 384, 5, 74, 0, 0, 384, 386, 7, 3, 0, 0, 385, 383, 1, 0, 0, 0, 385, 386, 1, 0, 0, 0, 386, 67, 1, 0, 0, 0, 387, 388, 5, 29, 0, 0, 388, 389, 3, 50, 25, 0, 389, 69, 1, 0, 0, 0, 390, 391, 5, 28, 0, 0, 391, 392, 3, 50, 25, 0, 392, 71, 1, 0, 0, 0, 393, 394, 5, 32, 0, 0, 394, 399, 3, 74, 37, 0, 395, 396, 5, 63, 0, 0, 396, 398, 3, 74, 37, 0, 397, 395, 1, 0, 0, 0, 398, 401, 1, 0, 0, 0, 399, 397, 1, 0, 0, 0, 399, 400, 1, 0, 0, 0, 400, 73, 1, 0, 0, 0, 401, 399, 1, 0, 0, 0, 402, 403, 3, 48, 24, 0, 403, 404, 5, 57, 0, 0, 404, 405, 3, 48, 24, 0, 405, 75, 1, 0, 0, 0, 406, 407, 5, 7, 0, 0, 407, 408, 3, 132, 66, 0, 408, 410, 3, 152, 76, 0, 409, 411, 3, 82, 41, 0, 410, 409, 1, 0, 0, 0, 410, 411, 1, 0, 0, 0, 411, 77, 1, 0, 0, 0, 412, 413, 5, 9, 0, 0, 413, 414, 3, 132, 66, 0, 414, 415, 3, 152, 76, 0, 415, 79, 1, 0, 0, 0, 416, 417, 5, 27, 0, 0, 417, 418, 3, 46, 23, 0, 418, 81, 1, 0, 0, 0, 419, 424, 3, 84, 42, 0, 420, 421, 5, 63, 0, 0, 421, 423, 3, 84, 42, 0, 422, 420, 1, 0, 0, 0, 423, 426, 1, 0, 0, 0, 424, 422, 1, 0, 0, 0, 424, 425, 1, 0, 0, 0, 425, 83, 1, 0, 0, 0, 426, 424, 1, 0, 0, 0, 427, 428, 3, 52, 26, 0, 428, 429, 5, 59, 0, 0, 429, 430, 3, 142, 71, 0, 430, 85, 1, 0, 0, 0, 431, 432, 5, 6, 0, 0, 432, 433, 3, 88, 44, 0, 433, 87, 1, 0, 0, 0, 434, 435, 5, 98, 0, 0, 435, 436, 3, 2, 1, 0, 436, 437, 5, 99, 0, 0, 437, 89, 1, 0, 0, 0, 438, 439, 5, 33, 0, 0, 439, 440, 5, 136, 0, 0, 440, 91, 1, 0, 0, 0, 441, 442, 5, 5, 0, 0, 442, 445, 5, 38, 0, 0, 443, 444, 5, 75, 0, 0, 444, 446, 3, 48, 24, 0, 445, 443, 1, 0, 0, 0, 445, 446, 1, 0, 0, 0, 446, 456, 1, 0, 0, 0, 447, 448, 5, 80, 0, 0, 448, 453, 3, 94, 47, 0, 449, 450, 5, 63, 0, 0, 450, 452, 3, 94, 47, 0, 451, 449, 1, 0, 0, 0, 452, 455, 1, 0, 0, 0, 453, 451, 1, 0, 0, 0, 453, 454, 1, 0, 0, 0, 454, 457, 1, 0, 0, 0, 455, 453, 1, 0, 0, 0, 456, 447, 1, 0, 0, 0, 456, 457, 1, 0, 0, 0, 457, 93, 1, 0, 0, 0, 458, 459, 3, 48, 24, 0, 459, 460, 5, 59, 0, 0, 460, 462, 1, 0, 0, 0, 461, 458, 1, 0, 0, 0, 461, 462, 1, 0, 0, 0, 462, 463, 1, 0, 0, 0, 463, 464, 3, 48, 24, 0, 464, 95, 1, 0, 0, 0, 465, 466, 5, 26, 0, 0, 466, 467, 3, 28, 14, 0, 467, 468, 5, 75, 0, 0, 468, 469, 3, 50, 25, 0, 469, 97, 1, 0, 0, 0, 470, 471, 5, 16, 0, 0, 471, 474, 3, 42, 21, 0, 472, 473, 5, 60, 0, 0, 473, 475, 3, 14, 7, 0, 474, 472, 1, 0, 0, 0, 474, 475, 1, 0, 0, 0, 475, 99, 1, 0, 0, 0, 476, 477, 5, 4, 0, 0, 477, 480, 3, 46, 23, 0, 478, 479, 5, 75, 0, 0, 479, 481, 3, 46, 23, 0, 480, 478, 1, 0, 0, 0, 480, 481, 1, 0, 0, 0, 481, 487, 1, 0, 0, 0, 482, 483, 5, 57, 0, 0, 483, 484, 3, 46, 23, 0, 484, 485, 5, 63, 0, 0, 485, 486, 3, 46, 23, 0, 486, 488, 1, 0, 0, 0, 487, 482, 1, 0, 0, 0, 487, 488, 1, 0, 0, 0, 488, 101, 1, 0, 0, 0, 489, 490, 5, 30, 0, 0, 490, 491, 3, 50, 25, 0, 491, 103, 1, 0, 0, 0, 492, 493, 5, 21, 0, 0, 493, 494, 3, 106, 53, 0, 494, 105, 1, 0, 0, 0, 495, 497, 3, 108, 54, 0, 496, 495, 1, 0, 0, 0, 497, 498, 1, 0, 0, 0, 498, 496, 1, 0, 0, 0, 498, 499, 1, 0, 0, 0, 499, 107, 1, 0, 0, 0, 500, 501, 5, 100, 0, 0, 501, 502, 3, 110, 55, 0, 502, 503, 5, 101, 0, 0, 503, 109, 1, 0, 0, 0, 504, 505, 6, 55, -1, 0, 505, 506, 3, 112, 56, 0, 506, 512, 1, 0, 0, 0, 507, 508, 10, 1, 0, 0, 508, 509, 5, 52, 0, 0, 509, 511, 3, 112, 56, 0, 510, 507, 1, 0, 0, 0, 511, 514, 1, 0, 0, 0, 512, 510, 1, 0, 0, 0, 512, 513, 1, 0, 0, 0, 513, 111, 1, 0, 0, 0, 514, 512, 1, 0, 0, 0, 515, 522, 3, 38, 19, 0, 516, 522, 3, 8, 4, 0, 517, 522, 3, 62, 31, 0, 518, 522, 3, 40, 20, 0, 519, 522, 3, 64, 32, 0, 520, 522, 3, 76, 38, 0, 521, 515, 1, 0, 0, 0, 521, 516, 1, 0, 0, 0, 521, 517, 1, 0, 0, 0, 521, 518, 1, 0, 0, 0, 521, 519, 1, 0, 0, 0, 521, 520, 1, 0, 0, 0, 522, 113, 1, 0, 0, 0, 523, 524, 5, 31, 0, 0, 524, 115, 1, 0, 0, 0, 525, 526, 5, 17, 0, 0, 526, 527, 3, 142, 71, 0, 527, 528, 5, 75, 0, 0, 528, 531, 3, 18, 9, 0, 529, 530, 5, 80, 0, 0, 530, 532, 3, 60, 30, 0, 531, 529, 1, 0, 0, 0, 531, 532, 1, 0, 0, 0, 532, 117, 1, 0, 0, 0, 533, 534, 5, 15, 0, 0, 534, 535, 3, 132, 66, 0, 535, 536, 5, 80, 0, 0, 536, 539, 3, 60, 30, 0, 537, 538, 5, 57, 0, 0, 538, 540, 3, 46, 23, 0, 539, 537, 1, 0, 0, 0, 539, 540, 1, 0, 0, 0, 540, 119, 1, 0, 0, 0, 541, 542, 5, 18, 0, 0, 542, 544, 3, 148, 74, 0, 543, 545, 3, 150, 75, 0, 544, 543, 1, 0, 0, 0, 544, 545, 1, 0, 0, 0, 545, 121, 1, 0, 0, 0, 546, 547, 6, 61, -1, 0, 547, 548, 5, 72, 0, 0, 548, 576, 3, 122, 61, 8, 549, 576, 3, 128, 64, 0, 550, 576, 3, 124, 62, 0, 551, 553, 3, 128, 64, 0, 552, 554, 5, 72, 0, 0, 553, 552, 1, 0, 0, 0, 553, 554, 1, 0, 0, 0, 554, 555, 1, 0, 0, 0, 555, 556, 5, 68, 0, 0, 556, 557, 5, 100, 0, 0, 557, 562, 3, 128, 64, 0, 558, 559, 5, 63, 0, 0, 559, 561, 3, 128, 64, 0, 560, 558, 1, 0, 0, 0, 561, 564, 1, 0, 0, 0, 562, 560, 1, 0, 0, 0, 562, 563, 1, 0, 0, 0, 563, 565, 1, 0, 0, 0, 564, 562, 1, 0, 0, 0, 565, 566, 5, 101, 0, 0, 566, 576, 1, 0, 0, 0, 567, 568, 3, 128, 64, 0, 568, 570, 5, 69, 0, 0, 569, 571, 5, 72, 0, 0, 570, 569, 1, 0, 0, 0, 570, 571, 1, 0, 0, 0, 571, 572, 1, 0, 0, 0, 572, 573, 5, 73, 0, 0, 573, 576, 1, 0, 0, 0, 574, 576, 3, 126, 63, 0, 575, 546, 1, 0, 0, 0, 575, 549, 1, 0, 0, 0, 575, 550, 1, 0, 0, 0, 575, 551, 1, 0, 0, 0, 575, 567, 1, 0, 0, 0, 575, 574, 1, 0, 0, 0, 576, 585, 1, 0, 0, 0, 577, 578, 10, 5, 0, 0, 578, 579, 5, 56, 0, 0, 579, 584, 3, 122, 61, 6, 580, 581, 10, 4, 0, 0, 581, 582, 5, 76, 0, 0, 582, 584, 3, 122, 61, 5, 583, 577, 1, 0, 0, 0, 583, 580, 1, 0, 0, 0, 584, 587, 1, 0, 0, 0, 585, 583, 1, 0, 0, 0, 585, 586, 1, 0, 0, 0, 586, 123, 1, 0, 0, 0, 587, 585, 1, 0, 0, 0, 588, 590, 3, 128, 64, 0, 589, 591, 5, 72, 0, 0, 590, 589, 1, 0, 0, 0, 590, 591, 1, 0, 0, 0, 591, 592, 1, 0, 0, 0, 592, 593, 5, 71, 0, 0, 593, 594, 3, 152, 76, 0, 594, 603, 1, 0, 0, 0, 595, 597, 3, 128, 64, 0, 596, 598, 5, 72, 0, 0, 597, 596, 1, 0, 0, 0, 597, 598, 1, 0, 0, 0, 598, 599, 1, 0, 0, 0, 599, 600, 5, 78, 0, 0, 600, 601, 3, 152, 76, 0, 601, 603, 1, 0, 0, 0, 602, 588, 1, 0, 0, 0, 602, 595, 1, 0, 0, 0, 603, 125, 1, 0, 0, 0, 604, 607, 3, 46, 23, 0, 605, 606, 5, 61, 0, 0, 606, 608, 3, 10, 5, 0, 607, 605, 1, 0, 0, 0, 607, 608, 1, 0, 0, 0, 608, 609, 1, 0, 0, 0, 609, 610, 5, 62, 0, 0, 610, 611, 3, 142, 71, 0, 611, 127, 1, 0, 0, 0, 612, 618, 3, 130, 65, 0, 613, 614, 3, 130, 65, 0, 614, 615, 3, 154, 77, 0, 615, 616, 3, 130, 65, 0, 616, 618, 1, 0, 0, 0, 617, 612, 1, 0, 0, 0, 617, 613, 1, 0, 0, 0, 618, 129, 1, 0, 0, 0, 619, 620, 6, 65, -1, 0, 620, 624, 3, 132, 66, 0, 621, 622, 7, 4, 0, 0, 622, 624, 3, 130, 65, 3, 623, 619, 1, 0, 0, 0, 623, 621, 1, 0, 0, 0, 624, 633, 1, 0, 0, 0, 625, 626, 10, 2, 0, 0, 626, 627, 7, 5, 0, 0, 627, 632, 3, 130, 65, 3, 628, 629, 10, 1, 0, 0, 629, 630, 7, 4, 0, 0, 630, 632, 3, 130, 65, 2, 631, 625, 1, 0, 0, 0, 631, 628, 1, 0, 0, 0, 632, 635, 1, 0, 0, 0, 633, 631, 1, 0, 0, 0, 633, 634, 1, 0, 0, 0, 634, 131, 1, 0, 0, 0, 635, 633, 1, 0, 0, 0, 636, 637, 6, 66, -1, 0, 637, 645, 3, 142, 71, 0, 638, 645, 3, 46, 23, 0, 639, 645, 3, 134, 67, 0, 640, 641, 5, 100, 0, 0, 641, 642, 3, 122, 61, 0, 642, 643, 5, 101, 0, 0, 643, 645, 1, 0, 0, 0, 644, 636, 1, 0, 0, 0, 644, 638, 1, 0, 0, 0, 644, 639, 1, 0, 0, 0, 644, 640, 1, 0, 0, 0, 645, 651, 1, 0, 0, 0, 646, 647, 10, 1, 0, 0, 647, 648, 5, 61, 0, 0, 648, 650, 3, 10, 5, 0, 649, 646, 1, 0, 0, 0, 650, 653, 1, 0, 0, 0, 651, 649, 1, 0, 0, 0, 651, 652, 1, 0, 0, 0, 652, 133, 1, 0, 0, 0, 653, 651, 1, 0, 0, 0, 654, 655, 3, 136, 68, 0, 655, 669, 5, 100, 0, 0, 656, 670, 5, 90, 0, 0, 657, 662, 3, 122, 61, 0, 658, 659, 5, 63, 0, 0, 659, 661, 3, 122, 61, 0, 660, 658, 1, 0, 0, 0, 661, 664, 1, 0, 0, 0, 662, 660, 1, 0, 0, 0, 662, 663, 1, 0, 0, 0, 663, 667, 1, 0, 0, 0, 664, 662, 1, 0, 0, 0, 665, 666, 5, 63, 0, 0, 666, 668, 3, 138, 69, 0, 667, 665, 1, 0, 0, 0, 667, 668, 1, 0, 0, 0, 668, 670, 1, 0, 0, 0, 669, 656, 1, 0, 0, 0, 669, 657, 1, 0, 0, 0, 669, 670, 1, 0, 0, 0, 670, 671, 1, 0, 0, 0, 671, 672, 5, 101, 0, 0, 672, 135, 1, 0, 0, 0, 673, 674, 3, 60, 30, 0, 674, 137, 1, 0, 0, 0, 675, 676, 5, 93, 0, 0, 676, 681, 3, 140, 70, 0, 677, 678, 5, 63, 0, 0, 678, 680, 3, 140, 70, 0, 679, 677, 1, 0, 0, 0, 680, 683, 1, 0, 0, 0, 681, 679, 1, 0, 0, 0, 681, 682, 1, 0, 0, 0, 682, 684, 1, 0, 0, 0, 683, 681, 1, 0, 0, 0, 684, 685, 5, 94, 0, 0, 685, 139, 1, 0, 0, 0, 686, 687, 3, 152, 76, 0, 687, 688, 5, 62, 0, 0, 688, 689, 3, 142, 71, 0, 689, 141, 1, 0, 0, 0, 690, 733, 5, 73, 0, 0, 691, 692, 3, 150, 75, 0, 692, 693, 5, 102, 0, 0, 693, 733, 1, 0, 0, 0, 694, 733, 3, 148, 74, 0, 695, 733, 3, 150, 75, 0, 696, 733, 3, 144, 72, 0, 697, 733, 3, 56, 28, 0, 698, 733, 3, 152, 76, 0, 699, 700, 5, 98, 0, 0, 700, 705, 3, 146, 73, 0, 701, 702, 5, 63, 0, 0, 702, 704, 3, 146, 73, 0, 703, 701, 1, 0, 0, 0, 704, 707, 1, 0, 0, 0, 705, 703, 1, 0, 0, 0, 705, 706, 1, 0, 0, 0, 706, 708, 1, 0, 0, 0, 707, 705, 1, 0, 0, 0, 708, 709, 5, 99, 0, 0, 709, 733, 1, 0, 0, 0, 710, 711, 5, 98, 0, 0, 711, 716, 3, 144, 72, 0, 712, 713, 5, 63, 0, 0, 713, 715, 3, 144, 72, 0, 714, 712, 1, 0, 0, 0, 715, 718, 1, 0, 0, 0, 716, 714, 1, 0, 0, 0, 716, 717, 1, 0, 0, 0, 717, 719, 1, 0, 0, 0, 718, 716, 1, 0, 0, 0, 719, 720, 5, 99, 0, 0, 720, 733, 1, 0, 0, 0, 721, 722, 5, 98, 0, 0, 722, 727, 3, 152, 76, 0, 723, 724, 5, 63, 0, 0, 724, 726, 3, 152, 76, 0, 725, 723, 1, 0, 0, 0, 726, 729, 1, 0, 0, 0, 727, 725, 1, 0, 0, 0, 727, 728, 1, 0, 0, 0, 728, 730, 1, 0, 0, 0, 729, 727, 1, 0, 0, 0, 730, 731, 5, 99, 0, 0, 731, 733, 1, 0, 0, 0, 732, 690, 1, 0, 0, 0, 732, 691, 1, 0, 0, 0, 732, 694, 1, 0, 0, 0, 732, 695, 1, 0, 0, 0, 732, 696, 1, 0, 0, 0, 732, 697, 1, 0, 0, 0, 732, 698, 1, 0, 0, 0, 732, 699, 1, 0, 0, 0, 732, 710, 1, 0, 0, 0, 732, 721, 1, 0, 0, 0, 733, 143, 1, 0, 0, 0, 734, 735, 7, 6, 0, 0, 735, 145, 1, 0, 0, 0, 736, 739, 3, 148, 74, 0, 737, 739, 3, 150, 75, 0, 738, 736, 1, 0, 0, 0, 738, 737, 1, 0, 0, 0, 739, 147, 1, 0, 0, 0, 740, 742, 7, 4, 0, 0, 741, 740, 1, 0, 0, 0, 741, 742, 1, 0, 0, 0, 742, 743, 1, 0, 0, 0, 743, 744, 5, 55, 0, 0, 744, 149, 1, 0, 0, 0, 745, 747, 7, 4, 0, 0, 746, 745, 1, 0, 0, 0, 746, 747, 1, 0, 0, 0, 747, 748, 1, 0, 0, 0, 748, 749, 5, 54, 0, 0, 749, 151, 1, 0, 0, 0, 750, 751, 5, 53, 0, 0, 751, 153, 1, 0, 0, 0, 752, 753, 7, 7, 0, 0, 753, 155, 1, 0, 0, 0, 754, 755, 7, 8, 0, 0, 755, 756, 5, 115, 0, 0, 756, 757, 3, 158, 79, 0, 757, 758, 3, 160, 80, 0, 758, 157, 1, 0, 0, 0, 759, 760, 3, 28, 14, 0, 760, 159, 1, 0, 0, 0, 761, 762, 5, 75, 0, 0, 762, 767, 3, 162, 81, 0, 763, 764, 5, 63, 0, 0, 764, 766, 3, 162, 81, 0, 765, 763, 1, 0, 0, 0, 766, 769, 1, 0, 0, 0, 767, 765, 1, 0, 0, 0, 767, 768, 1, 0, 0, 0, 768, 161, 1, 0, 0, 0, 769, 767, 1, 0, 0, 0, 770, 771, 3, 128, 64, 0, 771, 163, 1, 0, 0, 0, 71, 175, 184, 216, 231, 237, 246, 252, 265, 269, 274, 280, 282, 296, 304, 308, 315, 321, 328, 336, 344, 352, 356, 360, 365, 376, 381, 385, 399, 410, 424, 445, 453, 456, 461, 474, 480, 487, 498, 512, 521, 531, 539, 544, 553, 562, 570, 575, 583, 585, 590, 597, 602, 607, 617, 623, 631, 633, 644, 651, 662, 667, 669, 681, 705, 716, 727, 732, 738, 741, 746, 767] \ No newline at end of file +[4, 1, 139, 772, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 174, 8, 1, 10, 1, 12, 1, 177, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 185, 8, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 216, 8, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 5, 7, 229, 8, 7, 10, 7, 12, 7, 232, 9, 7, 1, 8, 1, 8, 1, 8, 3, 8, 237, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 5, 9, 244, 8, 9, 10, 9, 12, 9, 247, 9, 9, 1, 10, 1, 10, 1, 10, 3, 10, 252, 8, 10, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 5, 13, 263, 8, 13, 10, 13, 12, 13, 266, 9, 13, 1, 13, 3, 13, 269, 8, 13, 1, 14, 1, 14, 1, 14, 3, 14, 274, 8, 14, 1, 14, 1, 14, 1, 14, 1, 14, 3, 14, 280, 8, 14, 3, 14, 282, 8, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 294, 8, 18, 10, 18, 12, 18, 297, 9, 18, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 3, 20, 304, 8, 20, 1, 20, 1, 20, 3, 20, 308, 8, 20, 1, 21, 1, 21, 1, 21, 5, 21, 313, 8, 21, 10, 21, 12, 21, 316, 9, 21, 1, 22, 1, 22, 1, 22, 3, 22, 321, 8, 22, 1, 23, 1, 23, 1, 23, 5, 23, 326, 8, 23, 10, 23, 12, 23, 329, 9, 23, 1, 24, 1, 24, 1, 24, 5, 24, 334, 8, 24, 10, 24, 12, 24, 337, 9, 24, 1, 25, 1, 25, 1, 25, 5, 25, 342, 8, 25, 10, 25, 12, 25, 345, 9, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 3, 27, 352, 8, 27, 1, 28, 1, 28, 3, 28, 356, 8, 28, 1, 29, 1, 29, 3, 29, 360, 8, 29, 1, 30, 1, 30, 1, 30, 3, 30, 365, 8, 30, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 5, 32, 374, 8, 32, 10, 32, 12, 32, 377, 9, 32, 1, 33, 1, 33, 3, 33, 381, 8, 33, 1, 33, 1, 33, 3, 33, 385, 8, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 5, 36, 397, 8, 36, 10, 36, 12, 36, 400, 9, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 410, 8, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 5, 41, 422, 8, 41, 10, 41, 12, 41, 425, 9, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 3, 46, 445, 8, 46, 1, 46, 1, 46, 1, 46, 1, 46, 5, 46, 451, 8, 46, 10, 46, 12, 46, 454, 9, 46, 3, 46, 456, 8, 46, 1, 47, 1, 47, 1, 47, 3, 47, 461, 8, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 3, 49, 474, 8, 49, 1, 50, 1, 50, 1, 50, 1, 50, 3, 50, 480, 8, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 3, 50, 487, 8, 50, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 53, 4, 53, 496, 8, 53, 11, 53, 12, 53, 497, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 5, 55, 510, 8, 55, 10, 55, 12, 55, 513, 9, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 3, 56, 521, 8, 56, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 3, 58, 531, 8, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 3, 59, 539, 8, 59, 1, 60, 1, 60, 1, 60, 3, 60, 544, 8, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 3, 61, 553, 8, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 5, 61, 560, 8, 61, 10, 61, 12, 61, 563, 9, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 3, 61, 570, 8, 61, 1, 61, 1, 61, 1, 61, 3, 61, 575, 8, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 5, 61, 583, 8, 61, 10, 61, 12, 61, 586, 9, 61, 1, 62, 1, 62, 3, 62, 590, 8, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 3, 62, 597, 8, 62, 1, 62, 1, 62, 1, 62, 3, 62, 602, 8, 62, 1, 63, 1, 63, 1, 63, 3, 63, 607, 8, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 3, 64, 617, 8, 64, 1, 65, 1, 65, 1, 65, 1, 65, 3, 65, 623, 8, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 5, 65, 631, 8, 65, 10, 65, 12, 65, 634, 9, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 3, 66, 644, 8, 66, 1, 66, 1, 66, 1, 66, 5, 66, 649, 8, 66, 10, 66, 12, 66, 652, 9, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 5, 67, 660, 8, 67, 10, 67, 12, 67, 663, 9, 67, 1, 67, 1, 67, 3, 67, 667, 8, 67, 3, 67, 669, 8, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 5, 69, 679, 8, 69, 10, 69, 12, 69, 682, 9, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 703, 8, 71, 10, 71, 12, 71, 706, 9, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 714, 8, 71, 10, 71, 12, 71, 717, 9, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 725, 8, 71, 10, 71, 12, 71, 728, 9, 71, 1, 71, 1, 71, 3, 71, 732, 8, 71, 1, 72, 1, 72, 1, 73, 1, 73, 3, 73, 738, 8, 73, 1, 74, 3, 74, 741, 8, 74, 1, 74, 1, 74, 1, 75, 3, 75, 746, 8, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 5, 80, 765, 8, 80, 10, 80, 12, 80, 768, 9, 80, 1, 81, 1, 81, 1, 81, 0, 5, 2, 110, 122, 130, 132, 82, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 0, 9, 2, 0, 53, 53, 108, 108, 1, 0, 102, 103, 2, 0, 58, 58, 64, 64, 2, 0, 67, 67, 70, 70, 1, 0, 88, 89, 1, 0, 90, 92, 2, 0, 66, 66, 79, 79, 2, 0, 81, 81, 83, 87, 2, 0, 22, 22, 24, 25, 804, 0, 164, 1, 0, 0, 0, 2, 167, 1, 0, 0, 0, 4, 184, 1, 0, 0, 0, 6, 215, 1, 0, 0, 0, 8, 217, 1, 0, 0, 0, 10, 220, 1, 0, 0, 0, 12, 222, 1, 0, 0, 0, 14, 225, 1, 0, 0, 0, 16, 236, 1, 0, 0, 0, 18, 240, 1, 0, 0, 0, 20, 248, 1, 0, 0, 0, 22, 253, 1, 0, 0, 0, 24, 256, 1, 0, 0, 0, 26, 259, 1, 0, 0, 0, 28, 281, 1, 0, 0, 0, 30, 283, 1, 0, 0, 0, 32, 285, 1, 0, 0, 0, 34, 287, 1, 0, 0, 0, 36, 289, 1, 0, 0, 0, 38, 298, 1, 0, 0, 0, 40, 301, 1, 0, 0, 0, 42, 309, 1, 0, 0, 0, 44, 317, 1, 0, 0, 0, 46, 322, 1, 0, 0, 0, 48, 330, 1, 0, 0, 0, 50, 338, 1, 0, 0, 0, 52, 346, 1, 0, 0, 0, 54, 351, 1, 0, 0, 0, 56, 355, 1, 0, 0, 0, 58, 359, 1, 0, 0, 0, 60, 364, 1, 0, 0, 0, 62, 366, 1, 0, 0, 0, 64, 369, 1, 0, 0, 0, 66, 378, 1, 0, 0, 0, 68, 386, 1, 0, 0, 0, 70, 389, 1, 0, 0, 0, 72, 392, 1, 0, 0, 0, 74, 401, 1, 0, 0, 0, 76, 405, 1, 0, 0, 0, 78, 411, 1, 0, 0, 0, 80, 415, 1, 0, 0, 0, 82, 418, 1, 0, 0, 0, 84, 426, 1, 0, 0, 0, 86, 430, 1, 0, 0, 0, 88, 433, 1, 0, 0, 0, 90, 437, 1, 0, 0, 0, 92, 440, 1, 0, 0, 0, 94, 460, 1, 0, 0, 0, 96, 464, 1, 0, 0, 0, 98, 469, 1, 0, 0, 0, 100, 475, 1, 0, 0, 0, 102, 488, 1, 0, 0, 0, 104, 491, 1, 0, 0, 0, 106, 495, 1, 0, 0, 0, 108, 499, 1, 0, 0, 0, 110, 503, 1, 0, 0, 0, 112, 520, 1, 0, 0, 0, 114, 522, 1, 0, 0, 0, 116, 524, 1, 0, 0, 0, 118, 532, 1, 0, 0, 0, 120, 540, 1, 0, 0, 0, 122, 574, 1, 0, 0, 0, 124, 601, 1, 0, 0, 0, 126, 603, 1, 0, 0, 0, 128, 616, 1, 0, 0, 0, 130, 622, 1, 0, 0, 0, 132, 643, 1, 0, 0, 0, 134, 653, 1, 0, 0, 0, 136, 672, 1, 0, 0, 0, 138, 674, 1, 0, 0, 0, 140, 685, 1, 0, 0, 0, 142, 731, 1, 0, 0, 0, 144, 733, 1, 0, 0, 0, 146, 737, 1, 0, 0, 0, 148, 740, 1, 0, 0, 0, 150, 745, 1, 0, 0, 0, 152, 749, 1, 0, 0, 0, 154, 751, 1, 0, 0, 0, 156, 753, 1, 0, 0, 0, 158, 758, 1, 0, 0, 0, 160, 760, 1, 0, 0, 0, 162, 769, 1, 0, 0, 0, 164, 165, 3, 2, 1, 0, 165, 166, 5, 0, 0, 1, 166, 1, 1, 0, 0, 0, 167, 168, 6, 1, -1, 0, 168, 169, 3, 4, 2, 0, 169, 175, 1, 0, 0, 0, 170, 171, 10, 1, 0, 0, 171, 172, 5, 52, 0, 0, 172, 174, 3, 6, 3, 0, 173, 170, 1, 0, 0, 0, 174, 177, 1, 0, 0, 0, 175, 173, 1, 0, 0, 0, 175, 176, 1, 0, 0, 0, 176, 3, 1, 0, 0, 0, 177, 175, 1, 0, 0, 0, 178, 185, 3, 86, 43, 0, 179, 185, 3, 22, 11, 0, 180, 185, 3, 12, 6, 0, 181, 185, 3, 90, 45, 0, 182, 183, 4, 2, 1, 0, 183, 185, 3, 24, 12, 0, 184, 178, 1, 0, 0, 0, 184, 179, 1, 0, 0, 0, 184, 180, 1, 0, 0, 0, 184, 181, 1, 0, 0, 0, 184, 182, 1, 0, 0, 0, 185, 5, 1, 0, 0, 0, 186, 216, 3, 38, 19, 0, 187, 216, 3, 8, 4, 0, 188, 216, 3, 68, 34, 0, 189, 216, 3, 62, 31, 0, 190, 216, 3, 40, 20, 0, 191, 216, 3, 64, 32, 0, 192, 216, 3, 70, 35, 0, 193, 216, 3, 72, 36, 0, 194, 216, 3, 76, 38, 0, 195, 216, 3, 78, 39, 0, 196, 216, 3, 92, 46, 0, 197, 216, 3, 80, 40, 0, 198, 216, 3, 156, 78, 0, 199, 216, 3, 100, 50, 0, 200, 216, 3, 118, 59, 0, 201, 202, 4, 3, 2, 0, 202, 216, 3, 98, 49, 0, 203, 204, 4, 3, 3, 0, 204, 216, 3, 96, 48, 0, 205, 206, 4, 3, 4, 0, 206, 216, 3, 102, 51, 0, 207, 208, 4, 3, 5, 0, 208, 216, 3, 104, 52, 0, 209, 210, 4, 3, 6, 0, 210, 216, 3, 116, 58, 0, 211, 212, 4, 3, 7, 0, 212, 216, 3, 114, 57, 0, 213, 214, 4, 3, 8, 0, 214, 216, 3, 120, 60, 0, 215, 186, 1, 0, 0, 0, 215, 187, 1, 0, 0, 0, 215, 188, 1, 0, 0, 0, 215, 189, 1, 0, 0, 0, 215, 190, 1, 0, 0, 0, 215, 191, 1, 0, 0, 0, 215, 192, 1, 0, 0, 0, 215, 193, 1, 0, 0, 0, 215, 194, 1, 0, 0, 0, 215, 195, 1, 0, 0, 0, 215, 196, 1, 0, 0, 0, 215, 197, 1, 0, 0, 0, 215, 198, 1, 0, 0, 0, 215, 199, 1, 0, 0, 0, 215, 200, 1, 0, 0, 0, 215, 201, 1, 0, 0, 0, 215, 203, 1, 0, 0, 0, 215, 205, 1, 0, 0, 0, 215, 207, 1, 0, 0, 0, 215, 209, 1, 0, 0, 0, 215, 211, 1, 0, 0, 0, 215, 213, 1, 0, 0, 0, 216, 7, 1, 0, 0, 0, 217, 218, 5, 15, 0, 0, 218, 219, 3, 122, 61, 0, 219, 9, 1, 0, 0, 0, 220, 221, 3, 52, 26, 0, 221, 11, 1, 0, 0, 0, 222, 223, 5, 12, 0, 0, 223, 224, 3, 14, 7, 0, 224, 13, 1, 0, 0, 0, 225, 230, 3, 16, 8, 0, 226, 227, 5, 63, 0, 0, 227, 229, 3, 16, 8, 0, 228, 226, 1, 0, 0, 0, 229, 232, 1, 0, 0, 0, 230, 228, 1, 0, 0, 0, 230, 231, 1, 0, 0, 0, 231, 15, 1, 0, 0, 0, 232, 230, 1, 0, 0, 0, 233, 234, 3, 46, 23, 0, 234, 235, 5, 59, 0, 0, 235, 237, 1, 0, 0, 0, 236, 233, 1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 238, 1, 0, 0, 0, 238, 239, 3, 122, 61, 0, 239, 17, 1, 0, 0, 0, 240, 245, 3, 20, 10, 0, 241, 242, 5, 63, 0, 0, 242, 244, 3, 20, 10, 0, 243, 241, 1, 0, 0, 0, 244, 247, 1, 0, 0, 0, 245, 243, 1, 0, 0, 0, 245, 246, 1, 0, 0, 0, 246, 19, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 248, 251, 3, 46, 23, 0, 249, 250, 5, 59, 0, 0, 250, 252, 3, 122, 61, 0, 251, 249, 1, 0, 0, 0, 251, 252, 1, 0, 0, 0, 252, 21, 1, 0, 0, 0, 253, 254, 5, 19, 0, 0, 254, 255, 3, 26, 13, 0, 255, 23, 1, 0, 0, 0, 256, 257, 5, 20, 0, 0, 257, 258, 3, 26, 13, 0, 258, 25, 1, 0, 0, 0, 259, 264, 3, 28, 14, 0, 260, 261, 5, 63, 0, 0, 261, 263, 3, 28, 14, 0, 262, 260, 1, 0, 0, 0, 263, 266, 1, 0, 0, 0, 264, 262, 1, 0, 0, 0, 264, 265, 1, 0, 0, 0, 265, 268, 1, 0, 0, 0, 266, 264, 1, 0, 0, 0, 267, 269, 3, 36, 18, 0, 268, 267, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 27, 1, 0, 0, 0, 270, 271, 3, 30, 15, 0, 271, 272, 5, 62, 0, 0, 272, 274, 1, 0, 0, 0, 273, 270, 1, 0, 0, 0, 273, 274, 1, 0, 0, 0, 274, 275, 1, 0, 0, 0, 275, 282, 3, 34, 17, 0, 276, 279, 3, 34, 17, 0, 277, 278, 5, 61, 0, 0, 278, 280, 3, 32, 16, 0, 279, 277, 1, 0, 0, 0, 279, 280, 1, 0, 0, 0, 280, 282, 1, 0, 0, 0, 281, 273, 1, 0, 0, 0, 281, 276, 1, 0, 0, 0, 282, 29, 1, 0, 0, 0, 283, 284, 7, 0, 0, 0, 284, 31, 1, 0, 0, 0, 285, 286, 7, 0, 0, 0, 286, 33, 1, 0, 0, 0, 287, 288, 7, 0, 0, 0, 288, 35, 1, 0, 0, 0, 289, 290, 5, 107, 0, 0, 290, 295, 5, 108, 0, 0, 291, 292, 5, 63, 0, 0, 292, 294, 5, 108, 0, 0, 293, 291, 1, 0, 0, 0, 294, 297, 1, 0, 0, 0, 295, 293, 1, 0, 0, 0, 295, 296, 1, 0, 0, 0, 296, 37, 1, 0, 0, 0, 297, 295, 1, 0, 0, 0, 298, 299, 5, 9, 0, 0, 299, 300, 3, 14, 7, 0, 300, 39, 1, 0, 0, 0, 301, 303, 5, 14, 0, 0, 302, 304, 3, 42, 21, 0, 303, 302, 1, 0, 0, 0, 303, 304, 1, 0, 0, 0, 304, 307, 1, 0, 0, 0, 305, 306, 5, 60, 0, 0, 306, 308, 3, 14, 7, 0, 307, 305, 1, 0, 0, 0, 307, 308, 1, 0, 0, 0, 308, 41, 1, 0, 0, 0, 309, 314, 3, 44, 22, 0, 310, 311, 5, 63, 0, 0, 311, 313, 3, 44, 22, 0, 312, 310, 1, 0, 0, 0, 313, 316, 1, 0, 0, 0, 314, 312, 1, 0, 0, 0, 314, 315, 1, 0, 0, 0, 315, 43, 1, 0, 0, 0, 316, 314, 1, 0, 0, 0, 317, 320, 3, 16, 8, 0, 318, 319, 5, 15, 0, 0, 319, 321, 3, 122, 61, 0, 320, 318, 1, 0, 0, 0, 320, 321, 1, 0, 0, 0, 321, 45, 1, 0, 0, 0, 322, 327, 3, 60, 30, 0, 323, 324, 5, 65, 0, 0, 324, 326, 3, 60, 30, 0, 325, 323, 1, 0, 0, 0, 326, 329, 1, 0, 0, 0, 327, 325, 1, 0, 0, 0, 327, 328, 1, 0, 0, 0, 328, 47, 1, 0, 0, 0, 329, 327, 1, 0, 0, 0, 330, 335, 3, 54, 27, 0, 331, 332, 5, 65, 0, 0, 332, 334, 3, 54, 27, 0, 333, 331, 1, 0, 0, 0, 334, 337, 1, 0, 0, 0, 335, 333, 1, 0, 0, 0, 335, 336, 1, 0, 0, 0, 336, 49, 1, 0, 0, 0, 337, 335, 1, 0, 0, 0, 338, 343, 3, 48, 24, 0, 339, 340, 5, 63, 0, 0, 340, 342, 3, 48, 24, 0, 341, 339, 1, 0, 0, 0, 342, 345, 1, 0, 0, 0, 343, 341, 1, 0, 0, 0, 343, 344, 1, 0, 0, 0, 344, 51, 1, 0, 0, 0, 345, 343, 1, 0, 0, 0, 346, 347, 7, 1, 0, 0, 347, 53, 1, 0, 0, 0, 348, 352, 5, 129, 0, 0, 349, 352, 3, 56, 28, 0, 350, 352, 3, 58, 29, 0, 351, 348, 1, 0, 0, 0, 351, 349, 1, 0, 0, 0, 351, 350, 1, 0, 0, 0, 352, 55, 1, 0, 0, 0, 353, 356, 5, 77, 0, 0, 354, 356, 5, 96, 0, 0, 355, 353, 1, 0, 0, 0, 355, 354, 1, 0, 0, 0, 356, 57, 1, 0, 0, 0, 357, 360, 5, 95, 0, 0, 358, 360, 5, 97, 0, 0, 359, 357, 1, 0, 0, 0, 359, 358, 1, 0, 0, 0, 360, 59, 1, 0, 0, 0, 361, 365, 3, 52, 26, 0, 362, 365, 3, 56, 28, 0, 363, 365, 3, 58, 29, 0, 364, 361, 1, 0, 0, 0, 364, 362, 1, 0, 0, 0, 364, 363, 1, 0, 0, 0, 365, 61, 1, 0, 0, 0, 366, 367, 5, 11, 0, 0, 367, 368, 3, 142, 71, 0, 368, 63, 1, 0, 0, 0, 369, 370, 5, 13, 0, 0, 370, 375, 3, 66, 33, 0, 371, 372, 5, 63, 0, 0, 372, 374, 3, 66, 33, 0, 373, 371, 1, 0, 0, 0, 374, 377, 1, 0, 0, 0, 375, 373, 1, 0, 0, 0, 375, 376, 1, 0, 0, 0, 376, 65, 1, 0, 0, 0, 377, 375, 1, 0, 0, 0, 378, 380, 3, 122, 61, 0, 379, 381, 7, 2, 0, 0, 380, 379, 1, 0, 0, 0, 380, 381, 1, 0, 0, 0, 381, 384, 1, 0, 0, 0, 382, 383, 5, 74, 0, 0, 383, 385, 7, 3, 0, 0, 384, 382, 1, 0, 0, 0, 384, 385, 1, 0, 0, 0, 385, 67, 1, 0, 0, 0, 386, 387, 5, 29, 0, 0, 387, 388, 3, 50, 25, 0, 388, 69, 1, 0, 0, 0, 389, 390, 5, 28, 0, 0, 390, 391, 3, 50, 25, 0, 391, 71, 1, 0, 0, 0, 392, 393, 5, 32, 0, 0, 393, 398, 3, 74, 37, 0, 394, 395, 5, 63, 0, 0, 395, 397, 3, 74, 37, 0, 396, 394, 1, 0, 0, 0, 397, 400, 1, 0, 0, 0, 398, 396, 1, 0, 0, 0, 398, 399, 1, 0, 0, 0, 399, 73, 1, 0, 0, 0, 400, 398, 1, 0, 0, 0, 401, 402, 3, 48, 24, 0, 402, 403, 5, 57, 0, 0, 403, 404, 3, 48, 24, 0, 404, 75, 1, 0, 0, 0, 405, 406, 5, 8, 0, 0, 406, 407, 3, 132, 66, 0, 407, 409, 3, 152, 76, 0, 408, 410, 3, 82, 41, 0, 409, 408, 1, 0, 0, 0, 409, 410, 1, 0, 0, 0, 410, 77, 1, 0, 0, 0, 411, 412, 5, 10, 0, 0, 412, 413, 3, 132, 66, 0, 413, 414, 3, 152, 76, 0, 414, 79, 1, 0, 0, 0, 415, 416, 5, 27, 0, 0, 416, 417, 3, 46, 23, 0, 417, 81, 1, 0, 0, 0, 418, 423, 3, 84, 42, 0, 419, 420, 5, 63, 0, 0, 420, 422, 3, 84, 42, 0, 421, 419, 1, 0, 0, 0, 422, 425, 1, 0, 0, 0, 423, 421, 1, 0, 0, 0, 423, 424, 1, 0, 0, 0, 424, 83, 1, 0, 0, 0, 425, 423, 1, 0, 0, 0, 426, 427, 3, 52, 26, 0, 427, 428, 5, 59, 0, 0, 428, 429, 3, 142, 71, 0, 429, 85, 1, 0, 0, 0, 430, 431, 5, 6, 0, 0, 431, 432, 3, 88, 44, 0, 432, 87, 1, 0, 0, 0, 433, 434, 5, 98, 0, 0, 434, 435, 3, 2, 1, 0, 435, 436, 5, 99, 0, 0, 436, 89, 1, 0, 0, 0, 437, 438, 5, 33, 0, 0, 438, 439, 5, 136, 0, 0, 439, 91, 1, 0, 0, 0, 440, 441, 5, 5, 0, 0, 441, 444, 5, 38, 0, 0, 442, 443, 5, 75, 0, 0, 443, 445, 3, 48, 24, 0, 444, 442, 1, 0, 0, 0, 444, 445, 1, 0, 0, 0, 445, 455, 1, 0, 0, 0, 446, 447, 5, 80, 0, 0, 447, 452, 3, 94, 47, 0, 448, 449, 5, 63, 0, 0, 449, 451, 3, 94, 47, 0, 450, 448, 1, 0, 0, 0, 451, 454, 1, 0, 0, 0, 452, 450, 1, 0, 0, 0, 452, 453, 1, 0, 0, 0, 453, 456, 1, 0, 0, 0, 454, 452, 1, 0, 0, 0, 455, 446, 1, 0, 0, 0, 455, 456, 1, 0, 0, 0, 456, 93, 1, 0, 0, 0, 457, 458, 3, 48, 24, 0, 458, 459, 5, 59, 0, 0, 459, 461, 1, 0, 0, 0, 460, 457, 1, 0, 0, 0, 460, 461, 1, 0, 0, 0, 461, 462, 1, 0, 0, 0, 462, 463, 3, 48, 24, 0, 463, 95, 1, 0, 0, 0, 464, 465, 5, 26, 0, 0, 465, 466, 3, 28, 14, 0, 466, 467, 5, 75, 0, 0, 467, 468, 3, 50, 25, 0, 468, 97, 1, 0, 0, 0, 469, 470, 5, 16, 0, 0, 470, 473, 3, 42, 21, 0, 471, 472, 5, 60, 0, 0, 472, 474, 3, 14, 7, 0, 473, 471, 1, 0, 0, 0, 473, 474, 1, 0, 0, 0, 474, 99, 1, 0, 0, 0, 475, 476, 5, 4, 0, 0, 476, 479, 3, 46, 23, 0, 477, 478, 5, 75, 0, 0, 478, 480, 3, 46, 23, 0, 479, 477, 1, 0, 0, 0, 479, 480, 1, 0, 0, 0, 480, 486, 1, 0, 0, 0, 481, 482, 5, 57, 0, 0, 482, 483, 3, 46, 23, 0, 483, 484, 5, 63, 0, 0, 484, 485, 3, 46, 23, 0, 485, 487, 1, 0, 0, 0, 486, 481, 1, 0, 0, 0, 486, 487, 1, 0, 0, 0, 487, 101, 1, 0, 0, 0, 488, 489, 5, 30, 0, 0, 489, 490, 3, 50, 25, 0, 490, 103, 1, 0, 0, 0, 491, 492, 5, 21, 0, 0, 492, 493, 3, 106, 53, 0, 493, 105, 1, 0, 0, 0, 494, 496, 3, 108, 54, 0, 495, 494, 1, 0, 0, 0, 496, 497, 1, 0, 0, 0, 497, 495, 1, 0, 0, 0, 497, 498, 1, 0, 0, 0, 498, 107, 1, 0, 0, 0, 499, 500, 5, 100, 0, 0, 500, 501, 3, 110, 55, 0, 501, 502, 5, 101, 0, 0, 502, 109, 1, 0, 0, 0, 503, 504, 6, 55, -1, 0, 504, 505, 3, 112, 56, 0, 505, 511, 1, 0, 0, 0, 506, 507, 10, 1, 0, 0, 507, 508, 5, 52, 0, 0, 508, 510, 3, 112, 56, 0, 509, 506, 1, 0, 0, 0, 510, 513, 1, 0, 0, 0, 511, 509, 1, 0, 0, 0, 511, 512, 1, 0, 0, 0, 512, 111, 1, 0, 0, 0, 513, 511, 1, 0, 0, 0, 514, 521, 3, 38, 19, 0, 515, 521, 3, 8, 4, 0, 516, 521, 3, 62, 31, 0, 517, 521, 3, 40, 20, 0, 518, 521, 3, 64, 32, 0, 519, 521, 3, 76, 38, 0, 520, 514, 1, 0, 0, 0, 520, 515, 1, 0, 0, 0, 520, 516, 1, 0, 0, 0, 520, 517, 1, 0, 0, 0, 520, 518, 1, 0, 0, 0, 520, 519, 1, 0, 0, 0, 521, 113, 1, 0, 0, 0, 522, 523, 5, 31, 0, 0, 523, 115, 1, 0, 0, 0, 524, 525, 5, 17, 0, 0, 525, 526, 3, 142, 71, 0, 526, 527, 5, 75, 0, 0, 527, 530, 3, 18, 9, 0, 528, 529, 5, 80, 0, 0, 529, 531, 3, 60, 30, 0, 530, 528, 1, 0, 0, 0, 530, 531, 1, 0, 0, 0, 531, 117, 1, 0, 0, 0, 532, 533, 5, 7, 0, 0, 533, 534, 3, 132, 66, 0, 534, 535, 5, 80, 0, 0, 535, 538, 3, 60, 30, 0, 536, 537, 5, 57, 0, 0, 537, 539, 3, 46, 23, 0, 538, 536, 1, 0, 0, 0, 538, 539, 1, 0, 0, 0, 539, 119, 1, 0, 0, 0, 540, 541, 5, 18, 0, 0, 541, 543, 3, 148, 74, 0, 542, 544, 3, 150, 75, 0, 543, 542, 1, 0, 0, 0, 543, 544, 1, 0, 0, 0, 544, 121, 1, 0, 0, 0, 545, 546, 6, 61, -1, 0, 546, 547, 5, 72, 0, 0, 547, 575, 3, 122, 61, 8, 548, 575, 3, 128, 64, 0, 549, 575, 3, 124, 62, 0, 550, 552, 3, 128, 64, 0, 551, 553, 5, 72, 0, 0, 552, 551, 1, 0, 0, 0, 552, 553, 1, 0, 0, 0, 553, 554, 1, 0, 0, 0, 554, 555, 5, 68, 0, 0, 555, 556, 5, 100, 0, 0, 556, 561, 3, 128, 64, 0, 557, 558, 5, 63, 0, 0, 558, 560, 3, 128, 64, 0, 559, 557, 1, 0, 0, 0, 560, 563, 1, 0, 0, 0, 561, 559, 1, 0, 0, 0, 561, 562, 1, 0, 0, 0, 562, 564, 1, 0, 0, 0, 563, 561, 1, 0, 0, 0, 564, 565, 5, 101, 0, 0, 565, 575, 1, 0, 0, 0, 566, 567, 3, 128, 64, 0, 567, 569, 5, 69, 0, 0, 568, 570, 5, 72, 0, 0, 569, 568, 1, 0, 0, 0, 569, 570, 1, 0, 0, 0, 570, 571, 1, 0, 0, 0, 571, 572, 5, 73, 0, 0, 572, 575, 1, 0, 0, 0, 573, 575, 3, 126, 63, 0, 574, 545, 1, 0, 0, 0, 574, 548, 1, 0, 0, 0, 574, 549, 1, 0, 0, 0, 574, 550, 1, 0, 0, 0, 574, 566, 1, 0, 0, 0, 574, 573, 1, 0, 0, 0, 575, 584, 1, 0, 0, 0, 576, 577, 10, 5, 0, 0, 577, 578, 5, 56, 0, 0, 578, 583, 3, 122, 61, 6, 579, 580, 10, 4, 0, 0, 580, 581, 5, 76, 0, 0, 581, 583, 3, 122, 61, 5, 582, 576, 1, 0, 0, 0, 582, 579, 1, 0, 0, 0, 583, 586, 1, 0, 0, 0, 584, 582, 1, 0, 0, 0, 584, 585, 1, 0, 0, 0, 585, 123, 1, 0, 0, 0, 586, 584, 1, 0, 0, 0, 587, 589, 3, 128, 64, 0, 588, 590, 5, 72, 0, 0, 589, 588, 1, 0, 0, 0, 589, 590, 1, 0, 0, 0, 590, 591, 1, 0, 0, 0, 591, 592, 5, 71, 0, 0, 592, 593, 3, 152, 76, 0, 593, 602, 1, 0, 0, 0, 594, 596, 3, 128, 64, 0, 595, 597, 5, 72, 0, 0, 596, 595, 1, 0, 0, 0, 596, 597, 1, 0, 0, 0, 597, 598, 1, 0, 0, 0, 598, 599, 5, 78, 0, 0, 599, 600, 3, 152, 76, 0, 600, 602, 1, 0, 0, 0, 601, 587, 1, 0, 0, 0, 601, 594, 1, 0, 0, 0, 602, 125, 1, 0, 0, 0, 603, 606, 3, 46, 23, 0, 604, 605, 5, 61, 0, 0, 605, 607, 3, 10, 5, 0, 606, 604, 1, 0, 0, 0, 606, 607, 1, 0, 0, 0, 607, 608, 1, 0, 0, 0, 608, 609, 5, 62, 0, 0, 609, 610, 3, 142, 71, 0, 610, 127, 1, 0, 0, 0, 611, 617, 3, 130, 65, 0, 612, 613, 3, 130, 65, 0, 613, 614, 3, 154, 77, 0, 614, 615, 3, 130, 65, 0, 615, 617, 1, 0, 0, 0, 616, 611, 1, 0, 0, 0, 616, 612, 1, 0, 0, 0, 617, 129, 1, 0, 0, 0, 618, 619, 6, 65, -1, 0, 619, 623, 3, 132, 66, 0, 620, 621, 7, 4, 0, 0, 621, 623, 3, 130, 65, 3, 622, 618, 1, 0, 0, 0, 622, 620, 1, 0, 0, 0, 623, 632, 1, 0, 0, 0, 624, 625, 10, 2, 0, 0, 625, 626, 7, 5, 0, 0, 626, 631, 3, 130, 65, 3, 627, 628, 10, 1, 0, 0, 628, 629, 7, 4, 0, 0, 629, 631, 3, 130, 65, 2, 630, 624, 1, 0, 0, 0, 630, 627, 1, 0, 0, 0, 631, 634, 1, 0, 0, 0, 632, 630, 1, 0, 0, 0, 632, 633, 1, 0, 0, 0, 633, 131, 1, 0, 0, 0, 634, 632, 1, 0, 0, 0, 635, 636, 6, 66, -1, 0, 636, 644, 3, 142, 71, 0, 637, 644, 3, 46, 23, 0, 638, 644, 3, 134, 67, 0, 639, 640, 5, 100, 0, 0, 640, 641, 3, 122, 61, 0, 641, 642, 5, 101, 0, 0, 642, 644, 1, 0, 0, 0, 643, 635, 1, 0, 0, 0, 643, 637, 1, 0, 0, 0, 643, 638, 1, 0, 0, 0, 643, 639, 1, 0, 0, 0, 644, 650, 1, 0, 0, 0, 645, 646, 10, 1, 0, 0, 646, 647, 5, 61, 0, 0, 647, 649, 3, 10, 5, 0, 648, 645, 1, 0, 0, 0, 649, 652, 1, 0, 0, 0, 650, 648, 1, 0, 0, 0, 650, 651, 1, 0, 0, 0, 651, 133, 1, 0, 0, 0, 652, 650, 1, 0, 0, 0, 653, 654, 3, 136, 68, 0, 654, 668, 5, 100, 0, 0, 655, 669, 5, 90, 0, 0, 656, 661, 3, 122, 61, 0, 657, 658, 5, 63, 0, 0, 658, 660, 3, 122, 61, 0, 659, 657, 1, 0, 0, 0, 660, 663, 1, 0, 0, 0, 661, 659, 1, 0, 0, 0, 661, 662, 1, 0, 0, 0, 662, 666, 1, 0, 0, 0, 663, 661, 1, 0, 0, 0, 664, 665, 5, 63, 0, 0, 665, 667, 3, 138, 69, 0, 666, 664, 1, 0, 0, 0, 666, 667, 1, 0, 0, 0, 667, 669, 1, 0, 0, 0, 668, 655, 1, 0, 0, 0, 668, 656, 1, 0, 0, 0, 668, 669, 1, 0, 0, 0, 669, 670, 1, 0, 0, 0, 670, 671, 5, 101, 0, 0, 671, 135, 1, 0, 0, 0, 672, 673, 3, 60, 30, 0, 673, 137, 1, 0, 0, 0, 674, 675, 5, 93, 0, 0, 675, 680, 3, 140, 70, 0, 676, 677, 5, 63, 0, 0, 677, 679, 3, 140, 70, 0, 678, 676, 1, 0, 0, 0, 679, 682, 1, 0, 0, 0, 680, 678, 1, 0, 0, 0, 680, 681, 1, 0, 0, 0, 681, 683, 1, 0, 0, 0, 682, 680, 1, 0, 0, 0, 683, 684, 5, 94, 0, 0, 684, 139, 1, 0, 0, 0, 685, 686, 3, 152, 76, 0, 686, 687, 5, 62, 0, 0, 687, 688, 3, 142, 71, 0, 688, 141, 1, 0, 0, 0, 689, 732, 5, 73, 0, 0, 690, 691, 3, 150, 75, 0, 691, 692, 5, 102, 0, 0, 692, 732, 1, 0, 0, 0, 693, 732, 3, 148, 74, 0, 694, 732, 3, 150, 75, 0, 695, 732, 3, 144, 72, 0, 696, 732, 3, 56, 28, 0, 697, 732, 3, 152, 76, 0, 698, 699, 5, 98, 0, 0, 699, 704, 3, 146, 73, 0, 700, 701, 5, 63, 0, 0, 701, 703, 3, 146, 73, 0, 702, 700, 1, 0, 0, 0, 703, 706, 1, 0, 0, 0, 704, 702, 1, 0, 0, 0, 704, 705, 1, 0, 0, 0, 705, 707, 1, 0, 0, 0, 706, 704, 1, 0, 0, 0, 707, 708, 5, 99, 0, 0, 708, 732, 1, 0, 0, 0, 709, 710, 5, 98, 0, 0, 710, 715, 3, 144, 72, 0, 711, 712, 5, 63, 0, 0, 712, 714, 3, 144, 72, 0, 713, 711, 1, 0, 0, 0, 714, 717, 1, 0, 0, 0, 715, 713, 1, 0, 0, 0, 715, 716, 1, 0, 0, 0, 716, 718, 1, 0, 0, 0, 717, 715, 1, 0, 0, 0, 718, 719, 5, 99, 0, 0, 719, 732, 1, 0, 0, 0, 720, 721, 5, 98, 0, 0, 721, 726, 3, 152, 76, 0, 722, 723, 5, 63, 0, 0, 723, 725, 3, 152, 76, 0, 724, 722, 1, 0, 0, 0, 725, 728, 1, 0, 0, 0, 726, 724, 1, 0, 0, 0, 726, 727, 1, 0, 0, 0, 727, 729, 1, 0, 0, 0, 728, 726, 1, 0, 0, 0, 729, 730, 5, 99, 0, 0, 730, 732, 1, 0, 0, 0, 731, 689, 1, 0, 0, 0, 731, 690, 1, 0, 0, 0, 731, 693, 1, 0, 0, 0, 731, 694, 1, 0, 0, 0, 731, 695, 1, 0, 0, 0, 731, 696, 1, 0, 0, 0, 731, 697, 1, 0, 0, 0, 731, 698, 1, 0, 0, 0, 731, 709, 1, 0, 0, 0, 731, 720, 1, 0, 0, 0, 732, 143, 1, 0, 0, 0, 733, 734, 7, 6, 0, 0, 734, 145, 1, 0, 0, 0, 735, 738, 3, 148, 74, 0, 736, 738, 3, 150, 75, 0, 737, 735, 1, 0, 0, 0, 737, 736, 1, 0, 0, 0, 738, 147, 1, 0, 0, 0, 739, 741, 7, 4, 0, 0, 740, 739, 1, 0, 0, 0, 740, 741, 1, 0, 0, 0, 741, 742, 1, 0, 0, 0, 742, 743, 5, 55, 0, 0, 743, 149, 1, 0, 0, 0, 744, 746, 7, 4, 0, 0, 745, 744, 1, 0, 0, 0, 745, 746, 1, 0, 0, 0, 746, 747, 1, 0, 0, 0, 747, 748, 5, 54, 0, 0, 748, 151, 1, 0, 0, 0, 749, 750, 5, 53, 0, 0, 750, 153, 1, 0, 0, 0, 751, 752, 7, 7, 0, 0, 752, 155, 1, 0, 0, 0, 753, 754, 7, 8, 0, 0, 754, 755, 5, 115, 0, 0, 755, 756, 3, 158, 79, 0, 756, 757, 3, 160, 80, 0, 757, 157, 1, 0, 0, 0, 758, 759, 3, 28, 14, 0, 759, 159, 1, 0, 0, 0, 760, 761, 5, 75, 0, 0, 761, 766, 3, 162, 81, 0, 762, 763, 5, 63, 0, 0, 763, 765, 3, 162, 81, 0, 764, 762, 1, 0, 0, 0, 765, 768, 1, 0, 0, 0, 766, 764, 1, 0, 0, 0, 766, 767, 1, 0, 0, 0, 767, 161, 1, 0, 0, 0, 768, 766, 1, 0, 0, 0, 769, 770, 3, 128, 64, 0, 770, 163, 1, 0, 0, 0, 71, 175, 184, 215, 230, 236, 245, 251, 264, 268, 273, 279, 281, 295, 303, 307, 314, 320, 327, 335, 343, 351, 355, 359, 364, 375, 380, 384, 398, 409, 423, 444, 452, 455, 460, 473, 479, 486, 497, 511, 520, 530, 538, 543, 552, 561, 569, 574, 582, 584, 589, 596, 601, 606, 616, 622, 630, 632, 643, 650, 661, 666, 668, 680, 704, 715, 726, 731, 737, 740, 745, 766] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.java index efac82a9d91df..f87031c0a6da0 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.java @@ -26,31 +26,31 @@ public class EsqlBaseParser extends ParserConfig { new PredictionContextCache(); public static final int LINE_COMMENT=1, MULTILINE_COMMENT=2, WS=3, CHANGE_POINT=4, ENRICH=5, EXPLAIN=6, - DISSECT=7, EVAL=8, GROK=9, LIMIT=10, ROW=11, SORT=12, STATS=13, WHERE=14, - DEV_COMPLETION=15, DEV_INLINESTATS=16, DEV_RERANK=17, DEV_SAMPLE=18, FROM=19, - DEV_TIME_SERIES=20, DEV_FORK=21, JOIN_LOOKUP=22, DEV_JOIN_FULL=23, DEV_JOIN_LEFT=24, - DEV_JOIN_RIGHT=25, DEV_LOOKUP=26, MV_EXPAND=27, DROP=28, KEEP=29, DEV_INSIST=30, - DEV_RRF=31, RENAME=32, SHOW=33, UNKNOWN_CMD=34, CHANGE_POINT_LINE_COMMENT=35, - CHANGE_POINT_MULTILINE_COMMENT=36, CHANGE_POINT_WS=37, ENRICH_POLICY_NAME=38, - ENRICH_LINE_COMMENT=39, ENRICH_MULTILINE_COMMENT=40, ENRICH_WS=41, ENRICH_FIELD_LINE_COMMENT=42, - ENRICH_FIELD_MULTILINE_COMMENT=43, ENRICH_FIELD_WS=44, SETTING=45, SETTING_LINE_COMMENT=46, - SETTTING_MULTILINE_COMMENT=47, SETTING_WS=48, EXPLAIN_WS=49, EXPLAIN_LINE_COMMENT=50, - EXPLAIN_MULTILINE_COMMENT=51, PIPE=52, QUOTED_STRING=53, INTEGER_LITERAL=54, - DECIMAL_LITERAL=55, AND=56, AS=57, ASC=58, ASSIGN=59, BY=60, CAST_OP=61, - COLON=62, COMMA=63, DESC=64, DOT=65, FALSE=66, FIRST=67, IN=68, IS=69, - LAST=70, LIKE=71, NOT=72, NULL=73, NULLS=74, ON=75, OR=76, PARAM=77, RLIKE=78, - TRUE=79, WITH=80, EQ=81, CIEQ=82, NEQ=83, LT=84, LTE=85, GT=86, GTE=87, - PLUS=88, MINUS=89, ASTERISK=90, SLASH=91, PERCENT=92, LEFT_BRACES=93, - RIGHT_BRACES=94, DOUBLE_PARAMS=95, NAMED_OR_POSITIONAL_PARAM=96, NAMED_OR_POSITIONAL_DOUBLE_PARAMS=97, - OPENING_BRACKET=98, CLOSING_BRACKET=99, LP=100, RP=101, UNQUOTED_IDENTIFIER=102, - QUOTED_IDENTIFIER=103, EXPR_LINE_COMMENT=104, EXPR_MULTILINE_COMMENT=105, - EXPR_WS=106, METADATA=107, UNQUOTED_SOURCE=108, FROM_LINE_COMMENT=109, - FROM_MULTILINE_COMMENT=110, FROM_WS=111, FORK_WS=112, FORK_LINE_COMMENT=113, - FORK_MULTILINE_COMMENT=114, JOIN=115, USING=116, JOIN_LINE_COMMENT=117, - JOIN_MULTILINE_COMMENT=118, JOIN_WS=119, LOOKUP_LINE_COMMENT=120, LOOKUP_MULTILINE_COMMENT=121, - LOOKUP_WS=122, LOOKUP_FIELD_LINE_COMMENT=123, LOOKUP_FIELD_MULTILINE_COMMENT=124, - LOOKUP_FIELD_WS=125, MVEXPAND_LINE_COMMENT=126, MVEXPAND_MULTILINE_COMMENT=127, - MVEXPAND_WS=128, ID_PATTERN=129, PROJECT_LINE_COMMENT=130, PROJECT_MULTILINE_COMMENT=131, + COMPLETION=7, DISSECT=8, EVAL=9, GROK=10, LIMIT=11, ROW=12, SORT=13, STATS=14, + WHERE=15, DEV_INLINESTATS=16, DEV_RERANK=17, DEV_SAMPLE=18, FROM=19, DEV_TIME_SERIES=20, + DEV_FORK=21, JOIN_LOOKUP=22, DEV_JOIN_FULL=23, DEV_JOIN_LEFT=24, DEV_JOIN_RIGHT=25, + DEV_LOOKUP=26, MV_EXPAND=27, DROP=28, KEEP=29, DEV_INSIST=30, DEV_RRF=31, + RENAME=32, SHOW=33, UNKNOWN_CMD=34, CHANGE_POINT_LINE_COMMENT=35, CHANGE_POINT_MULTILINE_COMMENT=36, + CHANGE_POINT_WS=37, ENRICH_POLICY_NAME=38, ENRICH_LINE_COMMENT=39, ENRICH_MULTILINE_COMMENT=40, + ENRICH_WS=41, ENRICH_FIELD_LINE_COMMENT=42, ENRICH_FIELD_MULTILINE_COMMENT=43, + ENRICH_FIELD_WS=44, SETTING=45, SETTING_LINE_COMMENT=46, SETTTING_MULTILINE_COMMENT=47, + SETTING_WS=48, EXPLAIN_WS=49, EXPLAIN_LINE_COMMENT=50, EXPLAIN_MULTILINE_COMMENT=51, + PIPE=52, QUOTED_STRING=53, INTEGER_LITERAL=54, DECIMAL_LITERAL=55, AND=56, + AS=57, ASC=58, ASSIGN=59, BY=60, CAST_OP=61, COLON=62, COMMA=63, DESC=64, + DOT=65, FALSE=66, FIRST=67, IN=68, IS=69, LAST=70, LIKE=71, NOT=72, NULL=73, + NULLS=74, ON=75, OR=76, PARAM=77, RLIKE=78, TRUE=79, WITH=80, EQ=81, CIEQ=82, + NEQ=83, LT=84, LTE=85, GT=86, GTE=87, PLUS=88, MINUS=89, ASTERISK=90, + SLASH=91, PERCENT=92, LEFT_BRACES=93, RIGHT_BRACES=94, DOUBLE_PARAMS=95, + NAMED_OR_POSITIONAL_PARAM=96, NAMED_OR_POSITIONAL_DOUBLE_PARAMS=97, OPENING_BRACKET=98, + CLOSING_BRACKET=99, LP=100, RP=101, UNQUOTED_IDENTIFIER=102, QUOTED_IDENTIFIER=103, + EXPR_LINE_COMMENT=104, EXPR_MULTILINE_COMMENT=105, EXPR_WS=106, METADATA=107, + UNQUOTED_SOURCE=108, FROM_LINE_COMMENT=109, FROM_MULTILINE_COMMENT=110, + FROM_WS=111, FORK_WS=112, FORK_LINE_COMMENT=113, FORK_MULTILINE_COMMENT=114, + JOIN=115, USING=116, JOIN_LINE_COMMENT=117, JOIN_MULTILINE_COMMENT=118, + JOIN_WS=119, LOOKUP_LINE_COMMENT=120, LOOKUP_MULTILINE_COMMENT=121, LOOKUP_WS=122, + LOOKUP_FIELD_LINE_COMMENT=123, LOOKUP_FIELD_MULTILINE_COMMENT=124, LOOKUP_FIELD_WS=125, + MVEXPAND_LINE_COMMENT=126, MVEXPAND_MULTILINE_COMMENT=127, MVEXPAND_WS=128, + ID_PATTERN=129, PROJECT_LINE_COMMENT=130, PROJECT_MULTILINE_COMMENT=131, PROJECT_WS=132, RENAME_LINE_COMMENT=133, RENAME_MULTILINE_COMMENT=134, RENAME_WS=135, INFO=136, SHOW_LINE_COMMENT=137, SHOW_MULTILINE_COMMENT=138, SHOW_WS=139; @@ -109,10 +109,10 @@ private static String[] makeRuleNames() { private static String[] makeLiteralNames() { return new String[] { - null, null, null, null, "'change_point'", "'enrich'", "'explain'", "'dissect'", - "'eval'", "'grok'", "'limit'", "'row'", "'sort'", "'stats'", "'where'", - null, null, null, null, "'from'", null, null, "'lookup'", null, null, - null, null, "'mv_expand'", "'drop'", "'keep'", null, null, "'rename'", + null, null, null, null, "'change_point'", "'enrich'", "'explain'", "'completion'", + "'dissect'", "'eval'", "'grok'", "'limit'", "'row'", "'sort'", "'stats'", + "'where'", null, null, null, "'from'", null, null, "'lookup'", null, + null, null, null, "'mv_expand'", "'drop'", "'keep'", null, null, "'rename'", "'show'", null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "'|'", null, null, null, "'and'", "'as'", "'asc'", "'='", "'by'", "'::'", "':'", "','", "'desc'", @@ -130,11 +130,11 @@ private static String[] makeLiteralNames() { private static String[] makeSymbolicNames() { return new String[] { null, "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "CHANGE_POINT", "ENRICH", - "EXPLAIN", "DISSECT", "EVAL", "GROK", "LIMIT", "ROW", "SORT", "STATS", - "WHERE", "DEV_COMPLETION", "DEV_INLINESTATS", "DEV_RERANK", "DEV_SAMPLE", - "FROM", "DEV_TIME_SERIES", "DEV_FORK", "JOIN_LOOKUP", "DEV_JOIN_FULL", - "DEV_JOIN_LEFT", "DEV_JOIN_RIGHT", "DEV_LOOKUP", "MV_EXPAND", "DROP", - "KEEP", "DEV_INSIST", "DEV_RRF", "RENAME", "SHOW", "UNKNOWN_CMD", "CHANGE_POINT_LINE_COMMENT", + "EXPLAIN", "COMPLETION", "DISSECT", "EVAL", "GROK", "LIMIT", "ROW", "SORT", + "STATS", "WHERE", "DEV_INLINESTATS", "DEV_RERANK", "DEV_SAMPLE", "FROM", + "DEV_TIME_SERIES", "DEV_FORK", "JOIN_LOOKUP", "DEV_JOIN_FULL", "DEV_JOIN_LEFT", + "DEV_JOIN_RIGHT", "DEV_LOOKUP", "MV_EXPAND", "DROP", "KEEP", "DEV_INSIST", + "DEV_RRF", "RENAME", "SHOW", "UNKNOWN_CMD", "CHANGE_POINT_LINE_COMMENT", "CHANGE_POINT_MULTILINE_COMMENT", "CHANGE_POINT_WS", "ENRICH_POLICY_NAME", "ENRICH_LINE_COMMENT", "ENRICH_MULTILINE_COMMENT", "ENRICH_WS", "ENRICH_FIELD_LINE_COMMENT", "ENRICH_FIELD_MULTILINE_COMMENT", "ENRICH_FIELD_WS", "SETTING", "SETTING_LINE_COMMENT", @@ -519,15 +519,15 @@ public JoinCommandContext joinCommand() { public ChangePointCommandContext changePointCommand() { return getRuleContext(ChangePointCommandContext.class,0); } + public CompletionCommandContext completionCommand() { + return getRuleContext(CompletionCommandContext.class,0); + } public InlinestatsCommandContext inlinestatsCommand() { return getRuleContext(InlinestatsCommandContext.class,0); } public LookupCommandContext lookupCommand() { return getRuleContext(LookupCommandContext.class,0); } - public CompletionCommandContext completionCommand() { - return getRuleContext(CompletionCommandContext.class,0); - } public InsistCommandContext insistCommand() { return getRuleContext(InsistCommandContext.class,0); } @@ -567,7 +567,7 @@ public final ProcessingCommandContext processingCommand() throws RecognitionExce ProcessingCommandContext _localctx = new ProcessingCommandContext(_ctx, getState()); enterRule(_localctx, 6, RULE_processingCommand); try { - setState(216); + setState(215); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,2,_ctx) ) { case 1: @@ -672,71 +672,69 @@ public final ProcessingCommandContext processingCommand() throws RecognitionExce enterOuterAlt(_localctx, 15); { setState(200); - if (!(this.isDevVersion())) throw new FailedPredicateException(this, "this.isDevVersion()"); - setState(201); - inlinestatsCommand(); + completionCommand(); } break; case 16: enterOuterAlt(_localctx, 16); { - setState(202); + setState(201); if (!(this.isDevVersion())) throw new FailedPredicateException(this, "this.isDevVersion()"); - setState(203); - lookupCommand(); + setState(202); + inlinestatsCommand(); } break; case 17: enterOuterAlt(_localctx, 17); { - setState(204); + setState(203); if (!(this.isDevVersion())) throw new FailedPredicateException(this, "this.isDevVersion()"); - setState(205); - completionCommand(); + setState(204); + lookupCommand(); } break; case 18: enterOuterAlt(_localctx, 18); { - setState(206); + setState(205); if (!(this.isDevVersion())) throw new FailedPredicateException(this, "this.isDevVersion()"); - setState(207); + setState(206); insistCommand(); } break; case 19: enterOuterAlt(_localctx, 19); { - setState(208); + setState(207); if (!(this.isDevVersion())) throw new FailedPredicateException(this, "this.isDevVersion()"); - setState(209); + setState(208); forkCommand(); } break; case 20: enterOuterAlt(_localctx, 20); { - setState(210); + setState(209); if (!(this.isDevVersion())) throw new FailedPredicateException(this, "this.isDevVersion()"); - setState(211); + setState(210); rerankCommand(); } break; case 21: enterOuterAlt(_localctx, 21); { - setState(212); + setState(211); if (!(this.isDevVersion())) throw new FailedPredicateException(this, "this.isDevVersion()"); - setState(213); + setState(212); rrfCommand(); } break; case 22: enterOuterAlt(_localctx, 22); { - setState(214); + setState(213); if (!(this.isDevVersion())) throw new FailedPredicateException(this, "this.isDevVersion()"); - setState(215); + setState(214); sampleCommand(); } break; @@ -785,9 +783,9 @@ public final WhereCommandContext whereCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(218); + setState(217); match(WHERE); - setState(219); + setState(218); booleanExpression(0); } } @@ -845,7 +843,7 @@ public final DataTypeContext dataType() throws RecognitionException { _localctx = new ToDataTypeContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(221); + setState(220); identifier(); } } @@ -892,9 +890,9 @@ public final RowCommandContext rowCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(223); + setState(222); match(ROW); - setState(224); + setState(223); fields(); } } @@ -948,23 +946,23 @@ public final FieldsContext fields() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(226); + setState(225); field(); - setState(231); + setState(230); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,3,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(227); + setState(226); match(COMMA); - setState(228); + setState(227); field(); } } } - setState(233); + setState(232); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,3,_ctx); } @@ -1016,19 +1014,19 @@ public final FieldContext field() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(237); + setState(236); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,4,_ctx) ) { case 1: { - setState(234); + setState(233); qualifiedName(); - setState(235); + setState(234); match(ASSIGN); } break; } - setState(239); + setState(238); booleanExpression(0); } } @@ -1082,23 +1080,23 @@ public final RerankFieldsContext rerankFields() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(241); + setState(240); rerankField(); - setState(246); + setState(245); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,5,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(242); + setState(241); match(COMMA); - setState(243); + setState(242); rerankField(); } } } - setState(248); + setState(247); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,5,_ctx); } @@ -1150,16 +1148,16 @@ public final RerankFieldContext rerankField() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(249); + setState(248); qualifiedName(); - setState(252); + setState(251); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) { case 1: { - setState(250); + setState(249); match(ASSIGN); - setState(251); + setState(250); booleanExpression(0); } break; @@ -1209,9 +1207,9 @@ public final FromCommandContext fromCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(254); + setState(253); match(FROM); - setState(255); + setState(254); indexPatternAndMetadataFields(); } } @@ -1258,9 +1256,9 @@ public final TimeSeriesCommandContext timeSeriesCommand() throws RecognitionExce try { enterOuterAlt(_localctx, 1); { - setState(257); + setState(256); match(DEV_TIME_SERIES); - setState(258); + setState(257); indexPatternAndMetadataFields(); } } @@ -1317,32 +1315,32 @@ public final IndexPatternAndMetadataFieldsContext indexPatternAndMetadataFields( int _alt; enterOuterAlt(_localctx, 1); { - setState(260); + setState(259); indexPattern(); - setState(265); + setState(264); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,7,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(261); + setState(260); match(COMMA); - setState(262); + setState(261); indexPattern(); } } } - setState(267); + setState(266); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,7,_ctx); } - setState(269); + setState(268); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,8,_ctx) ) { case 1: { - setState(268); + setState(267); metadata(); } break; @@ -1397,41 +1395,41 @@ public final IndexPatternContext indexPattern() throws RecognitionException { IndexPatternContext _localctx = new IndexPatternContext(_ctx, getState()); enterRule(_localctx, 28, RULE_indexPattern); try { - setState(282); + setState(281); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,11,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(274); + setState(273); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,9,_ctx) ) { case 1: { - setState(271); + setState(270); clusterString(); - setState(272); + setState(271); match(COLON); } break; } - setState(276); + setState(275); indexString(); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(277); + setState(276); indexString(); - setState(280); + setState(279); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,10,_ctx) ) { case 1: { - setState(278); + setState(277); match(CAST_OP); - setState(279); + setState(278); selectorString(); } break; @@ -1482,7 +1480,7 @@ public final ClusterStringContext clusterString() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(284); + setState(283); _la = _input.LA(1); if ( !(_la==QUOTED_STRING || _la==UNQUOTED_SOURCE) ) { _errHandler.recoverInline(this); @@ -1536,7 +1534,7 @@ public final SelectorStringContext selectorString() throws RecognitionException try { enterOuterAlt(_localctx, 1); { - setState(286); + setState(285); _la = _input.LA(1); if ( !(_la==QUOTED_STRING || _la==UNQUOTED_SOURCE) ) { _errHandler.recoverInline(this); @@ -1590,7 +1588,7 @@ public final IndexStringContext indexString() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(288); + setState(287); _la = _input.LA(1); if ( !(_la==QUOTED_STRING || _la==UNQUOTED_SOURCE) ) { _errHandler.recoverInline(this); @@ -1651,25 +1649,25 @@ public final MetadataContext metadata() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(290); + setState(289); match(METADATA); - setState(291); + setState(290); match(UNQUOTED_SOURCE); - setState(296); + setState(295); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,12,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(292); + setState(291); match(COMMA); - setState(293); + setState(292); match(UNQUOTED_SOURCE); } } } - setState(298); + setState(297); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,12,_ctx); } @@ -1718,9 +1716,9 @@ public final EvalCommandContext evalCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(299); + setState(298); match(EVAL); - setState(300); + setState(299); fields(); } } @@ -1773,26 +1771,26 @@ public final StatsCommandContext statsCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(302); + setState(301); match(STATS); - setState(304); + setState(303); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,13,_ctx) ) { case 1: { - setState(303); + setState(302); ((StatsCommandContext)_localctx).stats = aggFields(); } break; } - setState(308); + setState(307); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,14,_ctx) ) { case 1: { - setState(306); + setState(305); match(BY); - setState(307); + setState(306); ((StatsCommandContext)_localctx).grouping = fields(); } break; @@ -1849,23 +1847,23 @@ public final AggFieldsContext aggFields() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(310); + setState(309); aggField(); - setState(315); + setState(314); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,15,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(311); + setState(310); match(COMMA); - setState(312); + setState(311); aggField(); } } } - setState(317); + setState(316); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,15,_ctx); } @@ -1917,16 +1915,16 @@ public final AggFieldContext aggField() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(318); + setState(317); field(); - setState(321); + setState(320); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,16,_ctx) ) { case 1: { - setState(319); + setState(318); match(WHERE); - setState(320); + setState(319); booleanExpression(0); } break; @@ -1983,23 +1981,23 @@ public final QualifiedNameContext qualifiedName() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(323); + setState(322); identifierOrParameter(); - setState(328); + setState(327); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,17,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(324); + setState(323); match(DOT); - setState(325); + setState(324); identifierOrParameter(); } } } - setState(330); + setState(329); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,17,_ctx); } @@ -2055,23 +2053,23 @@ public final QualifiedNamePatternContext qualifiedNamePattern() throws Recogniti int _alt; enterOuterAlt(_localctx, 1); { - setState(331); + setState(330); identifierPattern(); - setState(336); + setState(335); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,18,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(332); + setState(331); match(DOT); - setState(333); + setState(332); identifierPattern(); } } } - setState(338); + setState(337); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,18,_ctx); } @@ -2127,23 +2125,23 @@ public final QualifiedNamePatternsContext qualifiedNamePatterns() throws Recogni int _alt; enterOuterAlt(_localctx, 1); { - setState(339); + setState(338); qualifiedNamePattern(); - setState(344); + setState(343); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,19,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(340); + setState(339); match(COMMA); - setState(341); + setState(340); qualifiedNamePattern(); } } } - setState(346); + setState(345); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,19,_ctx); } @@ -2191,7 +2189,7 @@ public final IdentifierContext identifier() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(347); + setState(346); _la = _input.LA(1); if ( !(_la==UNQUOTED_IDENTIFIER || _la==QUOTED_IDENTIFIER) ) { _errHandler.recoverInline(this); @@ -2247,13 +2245,13 @@ public final IdentifierPatternContext identifierPattern() throws RecognitionExce IdentifierPatternContext _localctx = new IdentifierPatternContext(_ctx, getState()); enterRule(_localctx, 54, RULE_identifierPattern); try { - setState(352); + setState(351); _errHandler.sync(this); switch (_input.LA(1)) { case ID_PATTERN: enterOuterAlt(_localctx, 1); { - setState(349); + setState(348); match(ID_PATTERN); } break; @@ -2261,7 +2259,7 @@ public final IdentifierPatternContext identifierPattern() throws RecognitionExce case NAMED_OR_POSITIONAL_PARAM: enterOuterAlt(_localctx, 2); { - setState(350); + setState(349); parameter(); } break; @@ -2269,7 +2267,7 @@ public final IdentifierPatternContext identifierPattern() throws RecognitionExce case NAMED_OR_POSITIONAL_DOUBLE_PARAMS: enterOuterAlt(_localctx, 3); { - setState(351); + setState(350); doubleParameter(); } break; @@ -2345,14 +2343,14 @@ public final ParameterContext parameter() throws RecognitionException { ParameterContext _localctx = new ParameterContext(_ctx, getState()); enterRule(_localctx, 56, RULE_parameter); try { - setState(356); + setState(355); _errHandler.sync(this); switch (_input.LA(1)) { case PARAM: _localctx = new InputParamContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(354); + setState(353); match(PARAM); } break; @@ -2360,7 +2358,7 @@ public final ParameterContext parameter() throws RecognitionException { _localctx = new InputNamedOrPositionalParamContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(355); + setState(354); match(NAMED_OR_POSITIONAL_PARAM); } break; @@ -2436,14 +2434,14 @@ public final DoubleParameterContext doubleParameter() throws RecognitionExceptio DoubleParameterContext _localctx = new DoubleParameterContext(_ctx, getState()); enterRule(_localctx, 58, RULE_doubleParameter); try { - setState(360); + setState(359); _errHandler.sync(this); switch (_input.LA(1)) { case DOUBLE_PARAMS: _localctx = new InputDoubleParamsContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(358); + setState(357); match(DOUBLE_PARAMS); } break; @@ -2451,7 +2449,7 @@ public final DoubleParameterContext doubleParameter() throws RecognitionExceptio _localctx = new InputNamedOrPositionalDoubleParamsContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(359); + setState(358); match(NAMED_OR_POSITIONAL_DOUBLE_PARAMS); } break; @@ -2505,14 +2503,14 @@ public final IdentifierOrParameterContext identifierOrParameter() throws Recogni IdentifierOrParameterContext _localctx = new IdentifierOrParameterContext(_ctx, getState()); enterRule(_localctx, 60, RULE_identifierOrParameter); try { - setState(365); + setState(364); _errHandler.sync(this); switch (_input.LA(1)) { case UNQUOTED_IDENTIFIER: case QUOTED_IDENTIFIER: enterOuterAlt(_localctx, 1); { - setState(362); + setState(361); identifier(); } break; @@ -2520,7 +2518,7 @@ public final IdentifierOrParameterContext identifierOrParameter() throws Recogni case NAMED_OR_POSITIONAL_PARAM: enterOuterAlt(_localctx, 2); { - setState(363); + setState(362); parameter(); } break; @@ -2528,7 +2526,7 @@ public final IdentifierOrParameterContext identifierOrParameter() throws Recogni case NAMED_OR_POSITIONAL_DOUBLE_PARAMS: enterOuterAlt(_localctx, 3); { - setState(364); + setState(363); doubleParameter(); } break; @@ -2579,9 +2577,9 @@ public final LimitCommandContext limitCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(367); + setState(366); match(LIMIT); - setState(368); + setState(367); constant(); } } @@ -2636,25 +2634,25 @@ public final SortCommandContext sortCommand() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(370); + setState(369); match(SORT); - setState(371); + setState(370); orderExpression(); - setState(376); + setState(375); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,24,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(372); + setState(371); match(COMMA); - setState(373); + setState(372); orderExpression(); } } } - setState(378); + setState(377); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,24,_ctx); } @@ -2710,14 +2708,14 @@ public final OrderExpressionContext orderExpression() throws RecognitionExceptio try { enterOuterAlt(_localctx, 1); { - setState(379); + setState(378); booleanExpression(0); - setState(381); + setState(380); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,25,_ctx) ) { case 1: { - setState(380); + setState(379); ((OrderExpressionContext)_localctx).ordering = _input.LT(1); _la = _input.LA(1); if ( !(_la==ASC || _la==DESC) ) { @@ -2731,14 +2729,14 @@ public final OrderExpressionContext orderExpression() throws RecognitionExceptio } break; } - setState(385); + setState(384); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,26,_ctx) ) { case 1: { - setState(383); + setState(382); match(NULLS); - setState(384); + setState(383); ((OrderExpressionContext)_localctx).nullOrdering = _input.LT(1); _la = _input.LA(1); if ( !(_la==FIRST || _la==LAST) ) { @@ -2797,9 +2795,9 @@ public final KeepCommandContext keepCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(387); + setState(386); match(KEEP); - setState(388); + setState(387); qualifiedNamePatterns(); } } @@ -2846,9 +2844,9 @@ public final DropCommandContext dropCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(390); + setState(389); match(DROP); - setState(391); + setState(390); qualifiedNamePatterns(); } } @@ -2903,25 +2901,25 @@ public final RenameCommandContext renameCommand() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(393); + setState(392); match(RENAME); - setState(394); + setState(393); renameClause(); - setState(399); + setState(398); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,27,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(395); + setState(394); match(COMMA); - setState(396); + setState(395); renameClause(); } } } - setState(401); + setState(400); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,27,_ctx); } @@ -2975,11 +2973,11 @@ public final RenameClauseContext renameClause() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(402); + setState(401); ((RenameClauseContext)_localctx).oldName = qualifiedNamePattern(); - setState(403); + setState(402); match(AS); - setState(404); + setState(403); ((RenameClauseContext)_localctx).newName = qualifiedNamePattern(); } } @@ -3032,18 +3030,18 @@ public final DissectCommandContext dissectCommand() throws RecognitionException try { enterOuterAlt(_localctx, 1); { - setState(406); + setState(405); match(DISSECT); - setState(407); + setState(406); primaryExpression(0); - setState(408); + setState(407); string(); - setState(410); + setState(409); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,28,_ctx) ) { case 1: { - setState(409); + setState(408); commandOptions(); } break; @@ -3096,11 +3094,11 @@ public final GrokCommandContext grokCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(412); + setState(411); match(GROK); - setState(413); + setState(412); primaryExpression(0); - setState(414); + setState(413); string(); } } @@ -3147,9 +3145,9 @@ public final MvExpandCommandContext mvExpandCommand() throws RecognitionExceptio try { enterOuterAlt(_localctx, 1); { - setState(416); + setState(415); match(MV_EXPAND); - setState(417); + setState(416); qualifiedName(); } } @@ -3203,23 +3201,23 @@ public final CommandOptionsContext commandOptions() throws RecognitionException int _alt; enterOuterAlt(_localctx, 1); { - setState(419); + setState(418); commandOption(); - setState(424); + setState(423); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,29,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(420); + setState(419); match(COMMA); - setState(421); + setState(420); commandOption(); } } } - setState(426); + setState(425); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,29,_ctx); } @@ -3271,11 +3269,11 @@ public final CommandOptionContext commandOption() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(427); + setState(426); identifier(); - setState(428); + setState(427); match(ASSIGN); - setState(429); + setState(428); constant(); } } @@ -3322,9 +3320,9 @@ public final ExplainCommandContext explainCommand() throws RecognitionException try { enterOuterAlt(_localctx, 1); { - setState(431); + setState(430); match(EXPLAIN); - setState(432); + setState(431); subqueryExpression(); } } @@ -3372,11 +3370,11 @@ public final SubqueryExpressionContext subqueryExpression() throws RecognitionEx try { enterOuterAlt(_localctx, 1); { - setState(434); + setState(433); match(OPENING_BRACKET); - setState(435); + setState(434); query(0); - setState(436); + setState(435); match(CLOSING_BRACKET); } } @@ -3433,9 +3431,9 @@ public final ShowCommandContext showCommand() throws RecognitionException { _localctx = new ShowInfoContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(438); + setState(437); match(SHOW); - setState(439); + setState(438); match(INFO); } } @@ -3498,46 +3496,46 @@ public final EnrichCommandContext enrichCommand() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(441); + setState(440); match(ENRICH); - setState(442); + setState(441); ((EnrichCommandContext)_localctx).policyName = match(ENRICH_POLICY_NAME); - setState(445); + setState(444); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,30,_ctx) ) { case 1: { - setState(443); + setState(442); match(ON); - setState(444); + setState(443); ((EnrichCommandContext)_localctx).matchField = qualifiedNamePattern(); } break; } - setState(456); + setState(455); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,32,_ctx) ) { case 1: { - setState(447); + setState(446); match(WITH); - setState(448); + setState(447); enrichWithClause(); - setState(453); + setState(452); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,31,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(449); + setState(448); match(COMMA); - setState(450); + setState(449); enrichWithClause(); } } } - setState(455); + setState(454); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,31,_ctx); } @@ -3594,19 +3592,19 @@ public final EnrichWithClauseContext enrichWithClause() throws RecognitionExcept try { enterOuterAlt(_localctx, 1); { - setState(461); + setState(460); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,33,_ctx) ) { case 1: { - setState(458); + setState(457); ((EnrichWithClauseContext)_localctx).newName = qualifiedNamePattern(); - setState(459); + setState(458); match(ASSIGN); } break; } - setState(463); + setState(462); ((EnrichWithClauseContext)_localctx).enrichField = qualifiedNamePattern(); } } @@ -3659,13 +3657,13 @@ public final LookupCommandContext lookupCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(465); + setState(464); match(DEV_LOOKUP); - setState(466); + setState(465); ((LookupCommandContext)_localctx).tableName = indexPattern(); - setState(467); + setState(466); match(ON); - setState(468); + setState(467); ((LookupCommandContext)_localctx).matchFields = qualifiedNamePatterns(); } } @@ -3718,18 +3716,18 @@ public final InlinestatsCommandContext inlinestatsCommand() throws RecognitionEx try { enterOuterAlt(_localctx, 1); { - setState(470); + setState(469); match(DEV_INLINESTATS); - setState(471); + setState(470); ((InlinestatsCommandContext)_localctx).stats = aggFields(); - setState(474); + setState(473); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,34,_ctx) ) { case 1: { - setState(472); + setState(471); match(BY); - setState(473); + setState(472); ((InlinestatsCommandContext)_localctx).grouping = fields(); } break; @@ -3789,34 +3787,34 @@ public final ChangePointCommandContext changePointCommand() throws RecognitionEx try { enterOuterAlt(_localctx, 1); { - setState(476); + setState(475); match(CHANGE_POINT); - setState(477); + setState(476); ((ChangePointCommandContext)_localctx).value = qualifiedName(); - setState(480); + setState(479); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,35,_ctx) ) { case 1: { - setState(478); + setState(477); match(ON); - setState(479); + setState(478); ((ChangePointCommandContext)_localctx).key = qualifiedName(); } break; } - setState(487); + setState(486); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,36,_ctx) ) { case 1: { - setState(482); + setState(481); match(AS); - setState(483); + setState(482); ((ChangePointCommandContext)_localctx).targetType = qualifiedName(); - setState(484); + setState(483); match(COMMA); - setState(485); + setState(484); ((ChangePointCommandContext)_localctx).targetPvalue = qualifiedName(); } break; @@ -3866,9 +3864,9 @@ public final InsistCommandContext insistCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(489); + setState(488); match(DEV_INSIST); - setState(490); + setState(489); qualifiedNamePatterns(); } } @@ -3915,9 +3913,9 @@ public final ForkCommandContext forkCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(492); + setState(491); match(DEV_FORK); - setState(493); + setState(492); forkSubQueries(); } } @@ -3967,7 +3965,7 @@ public final ForkSubQueriesContext forkSubQueries() throws RecognitionException int _alt; enterOuterAlt(_localctx, 1); { - setState(496); + setState(495); _errHandler.sync(this); _alt = 1; do { @@ -3975,7 +3973,7 @@ public final ForkSubQueriesContext forkSubQueries() throws RecognitionException case 1: { { - setState(495); + setState(494); forkSubQuery(); } } @@ -3983,7 +3981,7 @@ public final ForkSubQueriesContext forkSubQueries() throws RecognitionException default: throw new NoViableAltException(this); } - setState(498); + setState(497); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,37,_ctx); } while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ); @@ -4033,11 +4031,11 @@ public final ForkSubQueryContext forkSubQuery() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(500); + setState(499); match(LP); - setState(501); + setState(500); forkSubQueryCommand(0); - setState(502); + setState(501); match(RP); } } @@ -4133,11 +4131,11 @@ private ForkSubQueryCommandContext forkSubQueryCommand(int _p) throws Recognitio _ctx = _localctx; _prevctx = _localctx; - setState(505); + setState(504); forkSubQueryProcessingCommand(); } _ctx.stop = _input.LT(-1); - setState(512); + setState(511); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,38,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -4148,16 +4146,16 @@ private ForkSubQueryCommandContext forkSubQueryCommand(int _p) throws Recognitio { _localctx = new CompositeForkSubQueryContext(new ForkSubQueryCommandContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_forkSubQueryCommand); - setState(507); + setState(506); if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(508); + setState(507); match(PIPE); - setState(509); + setState(508); forkSubQueryProcessingCommand(); } } } - setState(514); + setState(513); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,38,_ctx); } @@ -4218,48 +4216,48 @@ public final ForkSubQueryProcessingCommandContext forkSubQueryProcessingCommand( ForkSubQueryProcessingCommandContext _localctx = new ForkSubQueryProcessingCommandContext(_ctx, getState()); enterRule(_localctx, 112, RULE_forkSubQueryProcessingCommand); try { - setState(521); + setState(520); _errHandler.sync(this); switch (_input.LA(1)) { case EVAL: enterOuterAlt(_localctx, 1); { - setState(515); + setState(514); evalCommand(); } break; case WHERE: enterOuterAlt(_localctx, 2); { - setState(516); + setState(515); whereCommand(); } break; case LIMIT: enterOuterAlt(_localctx, 3); { - setState(517); + setState(516); limitCommand(); } break; case STATS: enterOuterAlt(_localctx, 4); { - setState(518); + setState(517); statsCommand(); } break; case SORT: enterOuterAlt(_localctx, 5); { - setState(519); + setState(518); sortCommand(); } break; case DISSECT: enterOuterAlt(_localctx, 6); { - setState(520); + setState(519); dissectCommand(); } break; @@ -4307,7 +4305,7 @@ public final RrfCommandContext rrfCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(523); + setState(522); match(DEV_RRF); } } @@ -4364,22 +4362,22 @@ public final RerankCommandContext rerankCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(525); + setState(524); match(DEV_RERANK); - setState(526); + setState(525); ((RerankCommandContext)_localctx).queryText = constant(); - setState(527); + setState(526); match(ON); - setState(528); + setState(527); rerankFields(); - setState(531); + setState(530); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,40,_ctx) ) { case 1: { - setState(529); + setState(528); match(WITH); - setState(530); + setState(529); ((RerankCommandContext)_localctx).inferenceId = identifierOrParameter(); } break; @@ -4402,7 +4400,7 @@ public static class CompletionCommandContext extends ParserRuleContext { public PrimaryExpressionContext prompt; public IdentifierOrParameterContext inferenceId; public QualifiedNameContext targetField; - public TerminalNode DEV_COMPLETION() { return getToken(EsqlBaseParser.DEV_COMPLETION, 0); } + public TerminalNode COMPLETION() { return getToken(EsqlBaseParser.COMPLETION, 0); } public TerminalNode WITH() { return getToken(EsqlBaseParser.WITH, 0); } public PrimaryExpressionContext primaryExpression() { return getRuleContext(PrimaryExpressionContext.class,0); @@ -4440,22 +4438,22 @@ public final CompletionCommandContext completionCommand() throws RecognitionExce try { enterOuterAlt(_localctx, 1); { + setState(532); + match(COMPLETION); setState(533); - match(DEV_COMPLETION); - setState(534); ((CompletionCommandContext)_localctx).prompt = primaryExpression(0); - setState(535); + setState(534); match(WITH); - setState(536); + setState(535); ((CompletionCommandContext)_localctx).inferenceId = identifierOrParameter(); - setState(539); + setState(538); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,41,_ctx) ) { case 1: { - setState(537); + setState(536); match(AS); - setState(538); + setState(537); ((CompletionCommandContext)_localctx).targetField = qualifiedName(); } break; @@ -4510,16 +4508,16 @@ public final SampleCommandContext sampleCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(541); + setState(540); match(DEV_SAMPLE); - setState(542); + setState(541); ((SampleCommandContext)_localctx).probability = decimalValue(); - setState(544); + setState(543); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,42,_ctx) ) { case 1: { - setState(543); + setState(542); ((SampleCommandContext)_localctx).seed = integerValue(); } break; @@ -4738,7 +4736,7 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc int _alt; enterOuterAlt(_localctx, 1); { - setState(575); + setState(574); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,46,_ctx) ) { case 1: @@ -4747,9 +4745,9 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _ctx = _localctx; _prevctx = _localctx; - setState(547); + setState(546); match(NOT); - setState(548); + setState(547); booleanExpression(8); } break; @@ -4758,7 +4756,7 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new BooleanDefaultContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(549); + setState(548); valueExpression(); } break; @@ -4767,7 +4765,7 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new RegexExpressionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(550); + setState(549); regexBooleanExpression(); } break; @@ -4776,41 +4774,41 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new LogicalInContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(551); + setState(550); valueExpression(); - setState(553); + setState(552); _errHandler.sync(this); _la = _input.LA(1); if (_la==NOT) { { - setState(552); + setState(551); match(NOT); } } - setState(555); + setState(554); match(IN); - setState(556); + setState(555); match(LP); - setState(557); + setState(556); valueExpression(); - setState(562); + setState(561); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(558); + setState(557); match(COMMA); - setState(559); + setState(558); valueExpression(); } } - setState(564); + setState(563); _errHandler.sync(this); _la = _input.LA(1); } - setState(565); + setState(564); match(RP); } break; @@ -4819,21 +4817,21 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new IsNullContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(567); + setState(566); valueExpression(); - setState(568); + setState(567); match(IS); - setState(570); + setState(569); _errHandler.sync(this); _la = _input.LA(1); if (_la==NOT) { { - setState(569); + setState(568); match(NOT); } } - setState(572); + setState(571); match(NULL); } break; @@ -4842,13 +4840,13 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new MatchExpressionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(574); + setState(573); matchBooleanExpression(); } break; } _ctx.stop = _input.LT(-1); - setState(585); + setState(584); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,48,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -4856,7 +4854,7 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(583); + setState(582); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,47,_ctx) ) { case 1: @@ -4864,11 +4862,11 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new LogicalBinaryContext(new BooleanExpressionContext(_parentctx, _parentState)); ((LogicalBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_booleanExpression); - setState(577); + setState(576); if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)"); - setState(578); + setState(577); ((LogicalBinaryContext)_localctx).operator = match(AND); - setState(579); + setState(578); ((LogicalBinaryContext)_localctx).right = booleanExpression(6); } break; @@ -4877,18 +4875,18 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new LogicalBinaryContext(new BooleanExpressionContext(_parentctx, _parentState)); ((LogicalBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_booleanExpression); - setState(580); + setState(579); if (!(precpred(_ctx, 4))) throw new FailedPredicateException(this, "precpred(_ctx, 4)"); - setState(581); + setState(580); ((LogicalBinaryContext)_localctx).operator = match(OR); - setState(582); + setState(581); ((LogicalBinaryContext)_localctx).right = booleanExpression(5); } break; } } } - setState(587); + setState(586); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,48,_ctx); } @@ -4943,48 +4941,48 @@ public final RegexBooleanExpressionContext regexBooleanExpression() throws Recog enterRule(_localctx, 124, RULE_regexBooleanExpression); int _la; try { - setState(602); + setState(601); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,51,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(588); + setState(587); valueExpression(); - setState(590); + setState(589); _errHandler.sync(this); _la = _input.LA(1); if (_la==NOT) { { - setState(589); + setState(588); match(NOT); } } - setState(592); + setState(591); ((RegexBooleanExpressionContext)_localctx).kind = match(LIKE); - setState(593); + setState(592); ((RegexBooleanExpressionContext)_localctx).pattern = string(); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(595); + setState(594); valueExpression(); - setState(597); + setState(596); _errHandler.sync(this); _la = _input.LA(1); if (_la==NOT) { { - setState(596); + setState(595); match(NOT); } } - setState(599); + setState(598); ((RegexBooleanExpressionContext)_localctx).kind = match(RLIKE); - setState(600); + setState(599); ((RegexBooleanExpressionContext)_localctx).pattern = string(); } break; @@ -5044,23 +5042,23 @@ public final MatchBooleanExpressionContext matchBooleanExpression() throws Recog try { enterOuterAlt(_localctx, 1); { - setState(604); + setState(603); ((MatchBooleanExpressionContext)_localctx).fieldExp = qualifiedName(); - setState(607); + setState(606); _errHandler.sync(this); _la = _input.LA(1); if (_la==CAST_OP) { { - setState(605); + setState(604); match(CAST_OP); - setState(606); + setState(605); ((MatchBooleanExpressionContext)_localctx).fieldType = dataType(); } } - setState(609); + setState(608); match(COLON); - setState(610); + setState(609); ((MatchBooleanExpressionContext)_localctx).matchQuery = constant(); } } @@ -5144,14 +5142,14 @@ public final ValueExpressionContext valueExpression() throws RecognitionExceptio ValueExpressionContext _localctx = new ValueExpressionContext(_ctx, getState()); enterRule(_localctx, 128, RULE_valueExpression); try { - setState(617); + setState(616); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,53,_ctx) ) { case 1: _localctx = new ValueExpressionDefaultContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(612); + setState(611); operatorExpression(0); } break; @@ -5159,11 +5157,11 @@ public final ValueExpressionContext valueExpression() throws RecognitionExceptio _localctx = new ComparisonContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(613); + setState(612); ((ComparisonContext)_localctx).left = operatorExpression(0); - setState(614); + setState(613); comparisonOperator(); - setState(615); + setState(614); ((ComparisonContext)_localctx).right = operatorExpression(0); } break; @@ -5288,7 +5286,7 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE int _alt; enterOuterAlt(_localctx, 1); { - setState(623); + setState(622); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,54,_ctx) ) { case 1: @@ -5297,7 +5295,7 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE _ctx = _localctx; _prevctx = _localctx; - setState(620); + setState(619); primaryExpression(0); } break; @@ -5306,7 +5304,7 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE _localctx = new ArithmeticUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(621); + setState(620); ((ArithmeticUnaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { @@ -5317,13 +5315,13 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE _errHandler.reportMatch(this); consume(); } - setState(622); + setState(621); operatorExpression(3); } break; } _ctx.stop = _input.LT(-1); - setState(633); + setState(632); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,56,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -5331,7 +5329,7 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(631); + setState(630); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,55,_ctx) ) { case 1: @@ -5339,9 +5337,9 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE _localctx = new ArithmeticBinaryContext(new OperatorExpressionContext(_parentctx, _parentState)); ((ArithmeticBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_operatorExpression); - setState(625); + setState(624); if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)"); - setState(626); + setState(625); ((ArithmeticBinaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !(((((_la - 90)) & ~0x3f) == 0 && ((1L << (_la - 90)) & 7L) != 0)) ) { @@ -5352,7 +5350,7 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE _errHandler.reportMatch(this); consume(); } - setState(627); + setState(626); ((ArithmeticBinaryContext)_localctx).right = operatorExpression(3); } break; @@ -5361,9 +5359,9 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE _localctx = new ArithmeticBinaryContext(new OperatorExpressionContext(_parentctx, _parentState)); ((ArithmeticBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_operatorExpression); - setState(628); + setState(627); if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(629); + setState(628); ((ArithmeticBinaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { @@ -5374,14 +5372,14 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE _errHandler.reportMatch(this); consume(); } - setState(630); + setState(629); ((ArithmeticBinaryContext)_localctx).right = operatorExpression(2); } break; } } } - setState(635); + setState(634); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,56,_ctx); } @@ -5539,7 +5537,7 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc int _alt; enterOuterAlt(_localctx, 1); { - setState(644); + setState(643); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,57,_ctx) ) { case 1: @@ -5548,7 +5546,7 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc _ctx = _localctx; _prevctx = _localctx; - setState(637); + setState(636); constant(); } break; @@ -5557,7 +5555,7 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc _localctx = new DereferenceContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(638); + setState(637); qualifiedName(); } break; @@ -5566,7 +5564,7 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc _localctx = new FunctionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(639); + setState(638); functionExpression(); } break; @@ -5575,17 +5573,17 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc _localctx = new ParenthesizedExpressionContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(640); + setState(639); match(LP); - setState(641); + setState(640); booleanExpression(0); - setState(642); + setState(641); match(RP); } break; } _ctx.stop = _input.LT(-1); - setState(651); + setState(650); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,58,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -5596,16 +5594,16 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc { _localctx = new InlineCastContext(new PrimaryExpressionContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_primaryExpression); - setState(646); + setState(645); if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(647); + setState(646); match(CAST_OP); - setState(648); + setState(647); dataType(); } } } - setState(653); + setState(652); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,58,_ctx); } @@ -5671,16 +5669,16 @@ public final FunctionExpressionContext functionExpression() throws RecognitionEx int _alt; enterOuterAlt(_localctx, 1); { - setState(654); + setState(653); functionName(); - setState(655); + setState(654); match(LP); - setState(669); + setState(668); _errHandler.sync(this); switch (_input.LA(1)) { case ASTERISK: { - setState(656); + setState(655); match(ASTERISK); } break; @@ -5703,34 +5701,34 @@ public final FunctionExpressionContext functionExpression() throws RecognitionEx case QUOTED_IDENTIFIER: { { - setState(657); + setState(656); booleanExpression(0); - setState(662); + setState(661); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,59,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(658); + setState(657); match(COMMA); - setState(659); + setState(658); booleanExpression(0); } } } - setState(664); + setState(663); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,59,_ctx); } - setState(667); + setState(666); _errHandler.sync(this); _la = _input.LA(1); if (_la==COMMA) { { - setState(665); + setState(664); match(COMMA); - setState(666); + setState(665); mapExpression(); } } @@ -5743,7 +5741,7 @@ public final FunctionExpressionContext functionExpression() throws RecognitionEx default: break; } - setState(671); + setState(670); match(RP); } } @@ -5789,7 +5787,7 @@ public final FunctionNameContext functionName() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(673); + setState(672); identifierOrParameter(); } } @@ -5845,27 +5843,27 @@ public final MapExpressionContext mapExpression() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(675); + setState(674); match(LEFT_BRACES); - setState(676); + setState(675); entryExpression(); - setState(681); + setState(680); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(677); + setState(676); match(COMMA); - setState(678); + setState(677); entryExpression(); } } - setState(683); + setState(682); _errHandler.sync(this); _la = _input.LA(1); } - setState(684); + setState(683); match(RIGHT_BRACES); } } @@ -5917,11 +5915,11 @@ public final EntryExpressionContext entryExpression() throws RecognitionExceptio try { enterOuterAlt(_localctx, 1); { - setState(686); + setState(685); ((EntryExpressionContext)_localctx).key = string(); - setState(687); + setState(686); match(COLON); - setState(688); + setState(687); ((EntryExpressionContext)_localctx).value = constant(); } } @@ -6192,14 +6190,14 @@ public final ConstantContext constant() throws RecognitionException { enterRule(_localctx, 142, RULE_constant); int _la; try { - setState(732); + setState(731); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,66,_ctx) ) { case 1: _localctx = new NullLiteralContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(690); + setState(689); match(NULL); } break; @@ -6207,9 +6205,9 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new QualifiedIntegerLiteralContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(691); + setState(690); integerValue(); - setState(692); + setState(691); match(UNQUOTED_IDENTIFIER); } break; @@ -6217,7 +6215,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new DecimalLiteralContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(694); + setState(693); decimalValue(); } break; @@ -6225,7 +6223,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new IntegerLiteralContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(695); + setState(694); integerValue(); } break; @@ -6233,7 +6231,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new BooleanLiteralContext(_localctx); enterOuterAlt(_localctx, 5); { - setState(696); + setState(695); booleanValue(); } break; @@ -6241,7 +6239,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new InputParameterContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(697); + setState(696); parameter(); } break; @@ -6249,7 +6247,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new StringLiteralContext(_localctx); enterOuterAlt(_localctx, 7); { - setState(698); + setState(697); string(); } break; @@ -6257,27 +6255,27 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new NumericArrayLiteralContext(_localctx); enterOuterAlt(_localctx, 8); { - setState(699); + setState(698); match(OPENING_BRACKET); - setState(700); + setState(699); numericValue(); - setState(705); + setState(704); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(701); + setState(700); match(COMMA); - setState(702); + setState(701); numericValue(); } } - setState(707); + setState(706); _errHandler.sync(this); _la = _input.LA(1); } - setState(708); + setState(707); match(CLOSING_BRACKET); } break; @@ -6285,27 +6283,27 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new BooleanArrayLiteralContext(_localctx); enterOuterAlt(_localctx, 9); { - setState(710); + setState(709); match(OPENING_BRACKET); - setState(711); + setState(710); booleanValue(); - setState(716); + setState(715); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(712); + setState(711); match(COMMA); - setState(713); + setState(712); booleanValue(); } } - setState(718); + setState(717); _errHandler.sync(this); _la = _input.LA(1); } - setState(719); + setState(718); match(CLOSING_BRACKET); } break; @@ -6313,27 +6311,27 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new StringArrayLiteralContext(_localctx); enterOuterAlt(_localctx, 10); { - setState(721); + setState(720); match(OPENING_BRACKET); - setState(722); + setState(721); string(); - setState(727); + setState(726); _errHandler.sync(this); _la = _input.LA(1); while (_la==COMMA) { { { - setState(723); + setState(722); match(COMMA); - setState(724); + setState(723); string(); } } - setState(729); + setState(728); _errHandler.sync(this); _la = _input.LA(1); } - setState(730); + setState(729); match(CLOSING_BRACKET); } break; @@ -6381,7 +6379,7 @@ public final BooleanValueContext booleanValue() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(734); + setState(733); _la = _input.LA(1); if ( !(_la==FALSE || _la==TRUE) ) { _errHandler.recoverInline(this); @@ -6436,20 +6434,20 @@ public final NumericValueContext numericValue() throws RecognitionException { NumericValueContext _localctx = new NumericValueContext(_ctx, getState()); enterRule(_localctx, 146, RULE_numericValue); try { - setState(738); + setState(737); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,67,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(736); + setState(735); decimalValue(); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(737); + setState(736); integerValue(); } break; @@ -6498,12 +6496,12 @@ public final DecimalValueContext decimalValue() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(741); + setState(740); _errHandler.sync(this); _la = _input.LA(1); if (_la==PLUS || _la==MINUS) { { - setState(740); + setState(739); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { _errHandler.recoverInline(this); @@ -6516,7 +6514,7 @@ public final DecimalValueContext decimalValue() throws RecognitionException { } } - setState(743); + setState(742); match(DECIMAL_LITERAL); } } @@ -6563,12 +6561,12 @@ public final IntegerValueContext integerValue() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(746); + setState(745); _errHandler.sync(this); _la = _input.LA(1); if (_la==PLUS || _la==MINUS) { { - setState(745); + setState(744); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { _errHandler.recoverInline(this); @@ -6581,7 +6579,7 @@ public final IntegerValueContext integerValue() throws RecognitionException { } } - setState(748); + setState(747); match(INTEGER_LITERAL); } } @@ -6625,7 +6623,7 @@ public final StringContext string() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(750); + setState(749); match(QUOTED_STRING); } } @@ -6675,7 +6673,7 @@ public final ComparisonOperatorContext comparisonOperator() throws RecognitionEx try { enterOuterAlt(_localctx, 1); { - setState(752); + setState(751); _la = _input.LA(1); if ( !(((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & 125L) != 0)) ) { _errHandler.recoverInline(this); @@ -6738,7 +6736,7 @@ public final JoinCommandContext joinCommand() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(754); + setState(753); ((JoinCommandContext)_localctx).type = _input.LT(1); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & 54525952L) != 0)) ) { @@ -6749,11 +6747,11 @@ public final JoinCommandContext joinCommand() throws RecognitionException { _errHandler.reportMatch(this); consume(); } - setState(755); + setState(754); match(JOIN); - setState(756); + setState(755); joinTarget(); - setState(757); + setState(756); joinCondition(); } } @@ -6800,7 +6798,7 @@ public final JoinTargetContext joinTarget() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(759); + setState(758); ((JoinTargetContext)_localctx).index = indexPattern(); } } @@ -6855,25 +6853,25 @@ public final JoinConditionContext joinCondition() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(761); + setState(760); match(ON); - setState(762); + setState(761); joinPredicate(); - setState(767); + setState(766); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,70,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(763); + setState(762); match(COMMA); - setState(764); + setState(763); joinPredicate(); } } } - setState(769); + setState(768); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,70,_ctx); } @@ -6921,7 +6919,7 @@ public final JoinPredicateContext joinPredicate() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(770); + setState(769); valueExpression(); } } @@ -6985,46 +6983,44 @@ private boolean processingCommand_sempred(ProcessingCommandContext _localctx, in return this.isDevVersion(); case 8: return this.isDevVersion(); - case 9: - return this.isDevVersion(); } return true; } private boolean forkSubQueryCommand_sempred(ForkSubQueryCommandContext _localctx, int predIndex) { switch (predIndex) { - case 10: + case 9: return precpred(_ctx, 1); } return true; } private boolean booleanExpression_sempred(BooleanExpressionContext _localctx, int predIndex) { switch (predIndex) { - case 11: + case 10: return precpred(_ctx, 5); - case 12: + case 11: return precpred(_ctx, 4); } return true; } private boolean operatorExpression_sempred(OperatorExpressionContext _localctx, int predIndex) { switch (predIndex) { - case 13: + case 12: return precpred(_ctx, 2); - case 14: + case 13: return precpred(_ctx, 1); } return true; } private boolean primaryExpression_sempred(PrimaryExpressionContext _localctx, int predIndex) { switch (predIndex) { - case 15: + case 14: return precpred(_ctx, 1); } return true; } public static final String _serializedATN = - "\u0004\u0001\u008b\u0305\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001"+ + "\u0004\u0001\u008b\u0304\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001"+ "\u0002\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004\u0007\u0004"+ "\u0002\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007\u0007\u0007"+ "\u0002\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002\u000b\u0007\u000b"+ @@ -7052,114 +7048,114 @@ private boolean primaryExpression_sempred(PrimaryExpressionContext _localctx, in "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+ "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+ "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+ - "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+ - "\u0003\u0003\u00d9\b\u0003\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0005"+ - "\u0001\u0005\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0007\u0001\u0007"+ - "\u0001\u0007\u0005\u0007\u00e6\b\u0007\n\u0007\f\u0007\u00e9\t\u0007\u0001"+ - "\b\u0001\b\u0001\b\u0003\b\u00ee\b\b\u0001\b\u0001\b\u0001\t\u0001\t\u0001"+ - "\t\u0005\t\u00f5\b\t\n\t\f\t\u00f8\t\t\u0001\n\u0001\n\u0001\n\u0003\n"+ - "\u00fd\b\n\u0001\u000b\u0001\u000b\u0001\u000b\u0001\f\u0001\f\u0001\f"+ - "\u0001\r\u0001\r\u0001\r\u0005\r\u0108\b\r\n\r\f\r\u010b\t\r\u0001\r\u0003"+ - "\r\u010e\b\r\u0001\u000e\u0001\u000e\u0001\u000e\u0003\u000e\u0113\b\u000e"+ - "\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0003\u000e\u0119\b\u000e"+ - "\u0003\u000e\u011b\b\u000e\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010"+ - "\u0001\u0011\u0001\u0011\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012"+ - "\u0005\u0012\u0127\b\u0012\n\u0012\f\u0012\u012a\t\u0012\u0001\u0013\u0001"+ - "\u0013\u0001\u0013\u0001\u0014\u0001\u0014\u0003\u0014\u0131\b\u0014\u0001"+ - "\u0014\u0001\u0014\u0003\u0014\u0135\b\u0014\u0001\u0015\u0001\u0015\u0001"+ - "\u0015\u0005\u0015\u013a\b\u0015\n\u0015\f\u0015\u013d\t\u0015\u0001\u0016"+ - "\u0001\u0016\u0001\u0016\u0003\u0016\u0142\b\u0016\u0001\u0017\u0001\u0017"+ - "\u0001\u0017\u0005\u0017\u0147\b\u0017\n\u0017\f\u0017\u014a\t\u0017\u0001"+ - "\u0018\u0001\u0018\u0001\u0018\u0005\u0018\u014f\b\u0018\n\u0018\f\u0018"+ - "\u0152\t\u0018\u0001\u0019\u0001\u0019\u0001\u0019\u0005\u0019\u0157\b"+ - "\u0019\n\u0019\f\u0019\u015a\t\u0019\u0001\u001a\u0001\u001a\u0001\u001b"+ - "\u0001\u001b\u0001\u001b\u0003\u001b\u0161\b\u001b\u0001\u001c\u0001\u001c"+ - "\u0003\u001c\u0165\b\u001c\u0001\u001d\u0001\u001d\u0003\u001d\u0169\b"+ - "\u001d\u0001\u001e\u0001\u001e\u0001\u001e\u0003\u001e\u016e\b\u001e\u0001"+ - "\u001f\u0001\u001f\u0001\u001f\u0001 \u0001 \u0001 \u0001 \u0005 \u0177"+ - "\b \n \f \u017a\t \u0001!\u0001!\u0003!\u017e\b!\u0001!\u0001!\u0003!"+ - "\u0182\b!\u0001\"\u0001\"\u0001\"\u0001#\u0001#\u0001#\u0001$\u0001$\u0001"+ - "$\u0001$\u0005$\u018e\b$\n$\f$\u0191\t$\u0001%\u0001%\u0001%\u0001%\u0001"+ - "&\u0001&\u0001&\u0001&\u0003&\u019b\b&\u0001\'\u0001\'\u0001\'\u0001\'"+ - "\u0001(\u0001(\u0001(\u0001)\u0001)\u0001)\u0005)\u01a7\b)\n)\f)\u01aa"+ + "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0003\u0003"+ + "\u00d8\b\u0003\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0005\u0001\u0005"+ + "\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0007\u0001\u0007\u0001\u0007"+ + "\u0005\u0007\u00e5\b\u0007\n\u0007\f\u0007\u00e8\t\u0007\u0001\b\u0001"+ + "\b\u0001\b\u0003\b\u00ed\b\b\u0001\b\u0001\b\u0001\t\u0001\t\u0001\t\u0005"+ + "\t\u00f4\b\t\n\t\f\t\u00f7\t\t\u0001\n\u0001\n\u0001\n\u0003\n\u00fc\b"+ + "\n\u0001\u000b\u0001\u000b\u0001\u000b\u0001\f\u0001\f\u0001\f\u0001\r"+ + "\u0001\r\u0001\r\u0005\r\u0107\b\r\n\r\f\r\u010a\t\r\u0001\r\u0003\r\u010d"+ + "\b\r\u0001\u000e\u0001\u000e\u0001\u000e\u0003\u000e\u0112\b\u000e\u0001"+ + "\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0003\u000e\u0118\b\u000e\u0003"+ + "\u000e\u011a\b\u000e\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010\u0001"+ + "\u0011\u0001\u0011\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0005"+ + "\u0012\u0126\b\u0012\n\u0012\f\u0012\u0129\t\u0012\u0001\u0013\u0001\u0013"+ + "\u0001\u0013\u0001\u0014\u0001\u0014\u0003\u0014\u0130\b\u0014\u0001\u0014"+ + "\u0001\u0014\u0003\u0014\u0134\b\u0014\u0001\u0015\u0001\u0015\u0001\u0015"+ + "\u0005\u0015\u0139\b\u0015\n\u0015\f\u0015\u013c\t\u0015\u0001\u0016\u0001"+ + "\u0016\u0001\u0016\u0003\u0016\u0141\b\u0016\u0001\u0017\u0001\u0017\u0001"+ + "\u0017\u0005\u0017\u0146\b\u0017\n\u0017\f\u0017\u0149\t\u0017\u0001\u0018"+ + "\u0001\u0018\u0001\u0018\u0005\u0018\u014e\b\u0018\n\u0018\f\u0018\u0151"+ + "\t\u0018\u0001\u0019\u0001\u0019\u0001\u0019\u0005\u0019\u0156\b\u0019"+ + "\n\u0019\f\u0019\u0159\t\u0019\u0001\u001a\u0001\u001a\u0001\u001b\u0001"+ + "\u001b\u0001\u001b\u0003\u001b\u0160\b\u001b\u0001\u001c\u0001\u001c\u0003"+ + "\u001c\u0164\b\u001c\u0001\u001d\u0001\u001d\u0003\u001d\u0168\b\u001d"+ + "\u0001\u001e\u0001\u001e\u0001\u001e\u0003\u001e\u016d\b\u001e\u0001\u001f"+ + "\u0001\u001f\u0001\u001f\u0001 \u0001 \u0001 \u0001 \u0005 \u0176\b \n"+ + " \f \u0179\t \u0001!\u0001!\u0003!\u017d\b!\u0001!\u0001!\u0003!\u0181"+ + "\b!\u0001\"\u0001\"\u0001\"\u0001#\u0001#\u0001#\u0001$\u0001$\u0001$"+ + "\u0001$\u0005$\u018d\b$\n$\f$\u0190\t$\u0001%\u0001%\u0001%\u0001%\u0001"+ + "&\u0001&\u0001&\u0001&\u0003&\u019a\b&\u0001\'\u0001\'\u0001\'\u0001\'"+ + "\u0001(\u0001(\u0001(\u0001)\u0001)\u0001)\u0005)\u01a6\b)\n)\f)\u01a9"+ "\t)\u0001*\u0001*\u0001*\u0001*\u0001+\u0001+\u0001+\u0001,\u0001,\u0001"+ - ",\u0001,\u0001-\u0001-\u0001-\u0001.\u0001.\u0001.\u0001.\u0003.\u01be"+ - "\b.\u0001.\u0001.\u0001.\u0001.\u0005.\u01c4\b.\n.\f.\u01c7\t.\u0003."+ - "\u01c9\b.\u0001/\u0001/\u0001/\u0003/\u01ce\b/\u0001/\u0001/\u00010\u0001"+ - "0\u00010\u00010\u00010\u00011\u00011\u00011\u00011\u00031\u01db\b1\u0001"+ - "2\u00012\u00012\u00012\u00032\u01e1\b2\u00012\u00012\u00012\u00012\u0001"+ - "2\u00032\u01e8\b2\u00013\u00013\u00013\u00014\u00014\u00014\u00015\u0004"+ - "5\u01f1\b5\u000b5\f5\u01f2\u00016\u00016\u00016\u00016\u00017\u00017\u0001"+ - "7\u00017\u00017\u00017\u00057\u01ff\b7\n7\f7\u0202\t7\u00018\u00018\u0001"+ - "8\u00018\u00018\u00018\u00038\u020a\b8\u00019\u00019\u0001:\u0001:\u0001"+ - ":\u0001:\u0001:\u0001:\u0003:\u0214\b:\u0001;\u0001;\u0001;\u0001;\u0001"+ - ";\u0001;\u0003;\u021c\b;\u0001<\u0001<\u0001<\u0003<\u0221\b<\u0001=\u0001"+ - "=\u0001=\u0001=\u0001=\u0001=\u0001=\u0003=\u022a\b=\u0001=\u0001=\u0001"+ - "=\u0001=\u0001=\u0005=\u0231\b=\n=\f=\u0234\t=\u0001=\u0001=\u0001=\u0001"+ - "=\u0001=\u0003=\u023b\b=\u0001=\u0001=\u0001=\u0003=\u0240\b=\u0001=\u0001"+ - "=\u0001=\u0001=\u0001=\u0001=\u0005=\u0248\b=\n=\f=\u024b\t=\u0001>\u0001"+ - ">\u0003>\u024f\b>\u0001>\u0001>\u0001>\u0001>\u0001>\u0003>\u0256\b>\u0001"+ - ">\u0001>\u0001>\u0003>\u025b\b>\u0001?\u0001?\u0001?\u0003?\u0260\b?\u0001"+ - "?\u0001?\u0001?\u0001@\u0001@\u0001@\u0001@\u0001@\u0003@\u026a\b@\u0001"+ - "A\u0001A\u0001A\u0001A\u0003A\u0270\bA\u0001A\u0001A\u0001A\u0001A\u0001"+ - "A\u0001A\u0005A\u0278\bA\nA\fA\u027b\tA\u0001B\u0001B\u0001B\u0001B\u0001"+ - "B\u0001B\u0001B\u0001B\u0003B\u0285\bB\u0001B\u0001B\u0001B\u0005B\u028a"+ - "\bB\nB\fB\u028d\tB\u0001C\u0001C\u0001C\u0001C\u0001C\u0001C\u0005C\u0295"+ - "\bC\nC\fC\u0298\tC\u0001C\u0001C\u0003C\u029c\bC\u0003C\u029e\bC\u0001"+ - "C\u0001C\u0001D\u0001D\u0001E\u0001E\u0001E\u0001E\u0005E\u02a8\bE\nE"+ - "\fE\u02ab\tE\u0001E\u0001E\u0001F\u0001F\u0001F\u0001F\u0001G\u0001G\u0001"+ + ",\u0001,\u0001-\u0001-\u0001-\u0001.\u0001.\u0001.\u0001.\u0003.\u01bd"+ + "\b.\u0001.\u0001.\u0001.\u0001.\u0005.\u01c3\b.\n.\f.\u01c6\t.\u0003."+ + "\u01c8\b.\u0001/\u0001/\u0001/\u0003/\u01cd\b/\u0001/\u0001/\u00010\u0001"+ + "0\u00010\u00010\u00010\u00011\u00011\u00011\u00011\u00031\u01da\b1\u0001"+ + "2\u00012\u00012\u00012\u00032\u01e0\b2\u00012\u00012\u00012\u00012\u0001"+ + "2\u00032\u01e7\b2\u00013\u00013\u00013\u00014\u00014\u00014\u00015\u0004"+ + "5\u01f0\b5\u000b5\f5\u01f1\u00016\u00016\u00016\u00016\u00017\u00017\u0001"+ + "7\u00017\u00017\u00017\u00057\u01fe\b7\n7\f7\u0201\t7\u00018\u00018\u0001"+ + "8\u00018\u00018\u00018\u00038\u0209\b8\u00019\u00019\u0001:\u0001:\u0001"+ + ":\u0001:\u0001:\u0001:\u0003:\u0213\b:\u0001;\u0001;\u0001;\u0001;\u0001"+ + ";\u0001;\u0003;\u021b\b;\u0001<\u0001<\u0001<\u0003<\u0220\b<\u0001=\u0001"+ + "=\u0001=\u0001=\u0001=\u0001=\u0001=\u0003=\u0229\b=\u0001=\u0001=\u0001"+ + "=\u0001=\u0001=\u0005=\u0230\b=\n=\f=\u0233\t=\u0001=\u0001=\u0001=\u0001"+ + "=\u0001=\u0003=\u023a\b=\u0001=\u0001=\u0001=\u0003=\u023f\b=\u0001=\u0001"+ + "=\u0001=\u0001=\u0001=\u0001=\u0005=\u0247\b=\n=\f=\u024a\t=\u0001>\u0001"+ + ">\u0003>\u024e\b>\u0001>\u0001>\u0001>\u0001>\u0001>\u0003>\u0255\b>\u0001"+ + ">\u0001>\u0001>\u0003>\u025a\b>\u0001?\u0001?\u0001?\u0003?\u025f\b?\u0001"+ + "?\u0001?\u0001?\u0001@\u0001@\u0001@\u0001@\u0001@\u0003@\u0269\b@\u0001"+ + "A\u0001A\u0001A\u0001A\u0003A\u026f\bA\u0001A\u0001A\u0001A\u0001A\u0001"+ + "A\u0001A\u0005A\u0277\bA\nA\fA\u027a\tA\u0001B\u0001B\u0001B\u0001B\u0001"+ + "B\u0001B\u0001B\u0001B\u0003B\u0284\bB\u0001B\u0001B\u0001B\u0005B\u0289"+ + "\bB\nB\fB\u028c\tB\u0001C\u0001C\u0001C\u0001C\u0001C\u0001C\u0005C\u0294"+ + "\bC\nC\fC\u0297\tC\u0001C\u0001C\u0003C\u029b\bC\u0003C\u029d\bC\u0001"+ + "C\u0001C\u0001D\u0001D\u0001E\u0001E\u0001E\u0001E\u0005E\u02a7\bE\nE"+ + "\fE\u02aa\tE\u0001E\u0001E\u0001F\u0001F\u0001F\u0001F\u0001G\u0001G\u0001"+ "G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001G\u0001"+ - "G\u0005G\u02c0\bG\nG\fG\u02c3\tG\u0001G\u0001G\u0001G\u0001G\u0001G\u0001"+ - "G\u0005G\u02cb\bG\nG\fG\u02ce\tG\u0001G\u0001G\u0001G\u0001G\u0001G\u0001"+ - "G\u0005G\u02d6\bG\nG\fG\u02d9\tG\u0001G\u0001G\u0003G\u02dd\bG\u0001H"+ - "\u0001H\u0001I\u0001I\u0003I\u02e3\bI\u0001J\u0003J\u02e6\bJ\u0001J\u0001"+ - "J\u0001K\u0003K\u02eb\bK\u0001K\u0001K\u0001L\u0001L\u0001M\u0001M\u0001"+ + "G\u0005G\u02bf\bG\nG\fG\u02c2\tG\u0001G\u0001G\u0001G\u0001G\u0001G\u0001"+ + "G\u0005G\u02ca\bG\nG\fG\u02cd\tG\u0001G\u0001G\u0001G\u0001G\u0001G\u0001"+ + "G\u0005G\u02d5\bG\nG\fG\u02d8\tG\u0001G\u0001G\u0003G\u02dc\bG\u0001H"+ + "\u0001H\u0001I\u0001I\u0003I\u02e2\bI\u0001J\u0003J\u02e5\bJ\u0001J\u0001"+ + "J\u0001K\u0003K\u02ea\bK\u0001K\u0001K\u0001L\u0001L\u0001M\u0001M\u0001"+ "N\u0001N\u0001N\u0001N\u0001N\u0001O\u0001O\u0001P\u0001P\u0001P\u0001"+ - "P\u0005P\u02fe\bP\nP\fP\u0301\tP\u0001Q\u0001Q\u0001Q\u0000\u0005\u0002"+ + "P\u0005P\u02fd\bP\nP\fP\u0300\tP\u0001Q\u0001Q\u0001Q\u0000\u0005\u0002"+ "nz\u0082\u0084R\u0000\u0002\u0004\u0006\b\n\f\u000e\u0010\u0012\u0014"+ "\u0016\u0018\u001a\u001c\u001e \"$&(*,.02468:<>@BDFHJLNPRTVXZ\\^`bdfh"+ "jlnprtvxz|~\u0080\u0082\u0084\u0086\u0088\u008a\u008c\u008e\u0090\u0092"+ "\u0094\u0096\u0098\u009a\u009c\u009e\u00a0\u00a2\u0000\t\u0002\u00005"+ "5ll\u0001\u0000fg\u0002\u0000::@@\u0002\u0000CCFF\u0001\u0000XY\u0001"+ "\u0000Z\\\u0002\u0000BBOO\u0002\u0000QQSW\u0002\u0000\u0016\u0016\u0018"+ - "\u0019\u0325\u0000\u00a4\u0001\u0000\u0000\u0000\u0002\u00a7\u0001\u0000"+ - "\u0000\u0000\u0004\u00b8\u0001\u0000\u0000\u0000\u0006\u00d8\u0001\u0000"+ - "\u0000\u0000\b\u00da\u0001\u0000\u0000\u0000\n\u00dd\u0001\u0000\u0000"+ - "\u0000\f\u00df\u0001\u0000\u0000\u0000\u000e\u00e2\u0001\u0000\u0000\u0000"+ - "\u0010\u00ed\u0001\u0000\u0000\u0000\u0012\u00f1\u0001\u0000\u0000\u0000"+ - "\u0014\u00f9\u0001\u0000\u0000\u0000\u0016\u00fe\u0001\u0000\u0000\u0000"+ - "\u0018\u0101\u0001\u0000\u0000\u0000\u001a\u0104\u0001\u0000\u0000\u0000"+ - "\u001c\u011a\u0001\u0000\u0000\u0000\u001e\u011c\u0001\u0000\u0000\u0000"+ - " \u011e\u0001\u0000\u0000\u0000\"\u0120\u0001\u0000\u0000\u0000$\u0122"+ - "\u0001\u0000\u0000\u0000&\u012b\u0001\u0000\u0000\u0000(\u012e\u0001\u0000"+ - "\u0000\u0000*\u0136\u0001\u0000\u0000\u0000,\u013e\u0001\u0000\u0000\u0000"+ - ".\u0143\u0001\u0000\u0000\u00000\u014b\u0001\u0000\u0000\u00002\u0153"+ - "\u0001\u0000\u0000\u00004\u015b\u0001\u0000\u0000\u00006\u0160\u0001\u0000"+ - "\u0000\u00008\u0164\u0001\u0000\u0000\u0000:\u0168\u0001\u0000\u0000\u0000"+ - "<\u016d\u0001\u0000\u0000\u0000>\u016f\u0001\u0000\u0000\u0000@\u0172"+ - "\u0001\u0000\u0000\u0000B\u017b\u0001\u0000\u0000\u0000D\u0183\u0001\u0000"+ - "\u0000\u0000F\u0186\u0001\u0000\u0000\u0000H\u0189\u0001\u0000\u0000\u0000"+ - "J\u0192\u0001\u0000\u0000\u0000L\u0196\u0001\u0000\u0000\u0000N\u019c"+ - "\u0001\u0000\u0000\u0000P\u01a0\u0001\u0000\u0000\u0000R\u01a3\u0001\u0000"+ - "\u0000\u0000T\u01ab\u0001\u0000\u0000\u0000V\u01af\u0001\u0000\u0000\u0000"+ - "X\u01b2\u0001\u0000\u0000\u0000Z\u01b6\u0001\u0000\u0000\u0000\\\u01b9"+ - "\u0001\u0000\u0000\u0000^\u01cd\u0001\u0000\u0000\u0000`\u01d1\u0001\u0000"+ - "\u0000\u0000b\u01d6\u0001\u0000\u0000\u0000d\u01dc\u0001\u0000\u0000\u0000"+ - "f\u01e9\u0001\u0000\u0000\u0000h\u01ec\u0001\u0000\u0000\u0000j\u01f0"+ - "\u0001\u0000\u0000\u0000l\u01f4\u0001\u0000\u0000\u0000n\u01f8\u0001\u0000"+ - "\u0000\u0000p\u0209\u0001\u0000\u0000\u0000r\u020b\u0001\u0000\u0000\u0000"+ - "t\u020d\u0001\u0000\u0000\u0000v\u0215\u0001\u0000\u0000\u0000x\u021d"+ - "\u0001\u0000\u0000\u0000z\u023f\u0001\u0000\u0000\u0000|\u025a\u0001\u0000"+ - "\u0000\u0000~\u025c\u0001\u0000\u0000\u0000\u0080\u0269\u0001\u0000\u0000"+ - "\u0000\u0082\u026f\u0001\u0000\u0000\u0000\u0084\u0284\u0001\u0000\u0000"+ - "\u0000\u0086\u028e\u0001\u0000\u0000\u0000\u0088\u02a1\u0001\u0000\u0000"+ - "\u0000\u008a\u02a3\u0001\u0000\u0000\u0000\u008c\u02ae\u0001\u0000\u0000"+ - "\u0000\u008e\u02dc\u0001\u0000\u0000\u0000\u0090\u02de\u0001\u0000\u0000"+ - "\u0000\u0092\u02e2\u0001\u0000\u0000\u0000\u0094\u02e5\u0001\u0000\u0000"+ - "\u0000\u0096\u02ea\u0001\u0000\u0000\u0000\u0098\u02ee\u0001\u0000\u0000"+ - "\u0000\u009a\u02f0\u0001\u0000\u0000\u0000\u009c\u02f2\u0001\u0000\u0000"+ - "\u0000\u009e\u02f7\u0001\u0000\u0000\u0000\u00a0\u02f9\u0001\u0000\u0000"+ - "\u0000\u00a2\u0302\u0001\u0000\u0000\u0000\u00a4\u00a5\u0003\u0002\u0001"+ + "\u0019\u0324\u0000\u00a4\u0001\u0000\u0000\u0000\u0002\u00a7\u0001\u0000"+ + "\u0000\u0000\u0004\u00b8\u0001\u0000\u0000\u0000\u0006\u00d7\u0001\u0000"+ + "\u0000\u0000\b\u00d9\u0001\u0000\u0000\u0000\n\u00dc\u0001\u0000\u0000"+ + "\u0000\f\u00de\u0001\u0000\u0000\u0000\u000e\u00e1\u0001\u0000\u0000\u0000"+ + "\u0010\u00ec\u0001\u0000\u0000\u0000\u0012\u00f0\u0001\u0000\u0000\u0000"+ + "\u0014\u00f8\u0001\u0000\u0000\u0000\u0016\u00fd\u0001\u0000\u0000\u0000"+ + "\u0018\u0100\u0001\u0000\u0000\u0000\u001a\u0103\u0001\u0000\u0000\u0000"+ + "\u001c\u0119\u0001\u0000\u0000\u0000\u001e\u011b\u0001\u0000\u0000\u0000"+ + " \u011d\u0001\u0000\u0000\u0000\"\u011f\u0001\u0000\u0000\u0000$\u0121"+ + "\u0001\u0000\u0000\u0000&\u012a\u0001\u0000\u0000\u0000(\u012d\u0001\u0000"+ + "\u0000\u0000*\u0135\u0001\u0000\u0000\u0000,\u013d\u0001\u0000\u0000\u0000"+ + ".\u0142\u0001\u0000\u0000\u00000\u014a\u0001\u0000\u0000\u00002\u0152"+ + "\u0001\u0000\u0000\u00004\u015a\u0001\u0000\u0000\u00006\u015f\u0001\u0000"+ + "\u0000\u00008\u0163\u0001\u0000\u0000\u0000:\u0167\u0001\u0000\u0000\u0000"+ + "<\u016c\u0001\u0000\u0000\u0000>\u016e\u0001\u0000\u0000\u0000@\u0171"+ + "\u0001\u0000\u0000\u0000B\u017a\u0001\u0000\u0000\u0000D\u0182\u0001\u0000"+ + "\u0000\u0000F\u0185\u0001\u0000\u0000\u0000H\u0188\u0001\u0000\u0000\u0000"+ + "J\u0191\u0001\u0000\u0000\u0000L\u0195\u0001\u0000\u0000\u0000N\u019b"+ + "\u0001\u0000\u0000\u0000P\u019f\u0001\u0000\u0000\u0000R\u01a2\u0001\u0000"+ + "\u0000\u0000T\u01aa\u0001\u0000\u0000\u0000V\u01ae\u0001\u0000\u0000\u0000"+ + "X\u01b1\u0001\u0000\u0000\u0000Z\u01b5\u0001\u0000\u0000\u0000\\\u01b8"+ + "\u0001\u0000\u0000\u0000^\u01cc\u0001\u0000\u0000\u0000`\u01d0\u0001\u0000"+ + "\u0000\u0000b\u01d5\u0001\u0000\u0000\u0000d\u01db\u0001\u0000\u0000\u0000"+ + "f\u01e8\u0001\u0000\u0000\u0000h\u01eb\u0001\u0000\u0000\u0000j\u01ef"+ + "\u0001\u0000\u0000\u0000l\u01f3\u0001\u0000\u0000\u0000n\u01f7\u0001\u0000"+ + "\u0000\u0000p\u0208\u0001\u0000\u0000\u0000r\u020a\u0001\u0000\u0000\u0000"+ + "t\u020c\u0001\u0000\u0000\u0000v\u0214\u0001\u0000\u0000\u0000x\u021c"+ + "\u0001\u0000\u0000\u0000z\u023e\u0001\u0000\u0000\u0000|\u0259\u0001\u0000"+ + "\u0000\u0000~\u025b\u0001\u0000\u0000\u0000\u0080\u0268\u0001\u0000\u0000"+ + "\u0000\u0082\u026e\u0001\u0000\u0000\u0000\u0084\u0283\u0001\u0000\u0000"+ + "\u0000\u0086\u028d\u0001\u0000\u0000\u0000\u0088\u02a0\u0001\u0000\u0000"+ + "\u0000\u008a\u02a2\u0001\u0000\u0000\u0000\u008c\u02ad\u0001\u0000\u0000"+ + "\u0000\u008e\u02db\u0001\u0000\u0000\u0000\u0090\u02dd\u0001\u0000\u0000"+ + "\u0000\u0092\u02e1\u0001\u0000\u0000\u0000\u0094\u02e4\u0001\u0000\u0000"+ + "\u0000\u0096\u02e9\u0001\u0000\u0000\u0000\u0098\u02ed\u0001\u0000\u0000"+ + "\u0000\u009a\u02ef\u0001\u0000\u0000\u0000\u009c\u02f1\u0001\u0000\u0000"+ + "\u0000\u009e\u02f6\u0001\u0000\u0000\u0000\u00a0\u02f8\u0001\u0000\u0000"+ + "\u0000\u00a2\u0301\u0001\u0000\u0000\u0000\u00a4\u00a5\u0003\u0002\u0001"+ "\u0000\u00a5\u00a6\u0005\u0000\u0000\u0001\u00a6\u0001\u0001\u0000\u0000"+ "\u0000\u00a7\u00a8\u0006\u0001\uffff\uffff\u0000\u00a8\u00a9\u0003\u0004"+ "\u0002\u0000\u00a9\u00af\u0001\u0000\u0000\u0000\u00aa\u00ab\n\u0001\u0000"+ @@ -7172,334 +7168,333 @@ private boolean primaryExpression_sempred(PrimaryExpressionContext _localctx, in "\u0001\u0000\u00b7\u00b9\u0003\u0018\f\u0000\u00b8\u00b2\u0001\u0000\u0000"+ "\u0000\u00b8\u00b3\u0001\u0000\u0000\u0000\u00b8\u00b4\u0001\u0000\u0000"+ "\u0000\u00b8\u00b5\u0001\u0000\u0000\u0000\u00b8\u00b6\u0001\u0000\u0000"+ - "\u0000\u00b9\u0005\u0001\u0000\u0000\u0000\u00ba\u00d9\u0003&\u0013\u0000"+ - "\u00bb\u00d9\u0003\b\u0004\u0000\u00bc\u00d9\u0003D\"\u0000\u00bd\u00d9"+ - "\u0003>\u001f\u0000\u00be\u00d9\u0003(\u0014\u0000\u00bf\u00d9\u0003@"+ - " \u0000\u00c0\u00d9\u0003F#\u0000\u00c1\u00d9\u0003H$\u0000\u00c2\u00d9"+ - "\u0003L&\u0000\u00c3\u00d9\u0003N\'\u0000\u00c4\u00d9\u0003\\.\u0000\u00c5"+ - "\u00d9\u0003P(\u0000\u00c6\u00d9\u0003\u009cN\u0000\u00c7\u00d9\u0003"+ - "d2\u0000\u00c8\u00c9\u0004\u0003\u0002\u0000\u00c9\u00d9\u0003b1\u0000"+ - "\u00ca\u00cb\u0004\u0003\u0003\u0000\u00cb\u00d9\u0003`0\u0000\u00cc\u00cd"+ - "\u0004\u0003\u0004\u0000\u00cd\u00d9\u0003v;\u0000\u00ce\u00cf\u0004\u0003"+ - "\u0005\u0000\u00cf\u00d9\u0003f3\u0000\u00d0\u00d1\u0004\u0003\u0006\u0000"+ - "\u00d1\u00d9\u0003h4\u0000\u00d2\u00d3\u0004\u0003\u0007\u0000\u00d3\u00d9"+ - "\u0003t:\u0000\u00d4\u00d5\u0004\u0003\b\u0000\u00d5\u00d9\u0003r9\u0000"+ - "\u00d6\u00d7\u0004\u0003\t\u0000\u00d7\u00d9\u0003x<\u0000\u00d8\u00ba"+ - "\u0001\u0000\u0000\u0000\u00d8\u00bb\u0001\u0000\u0000\u0000\u00d8\u00bc"+ - "\u0001\u0000\u0000\u0000\u00d8\u00bd\u0001\u0000\u0000\u0000\u00d8\u00be"+ - "\u0001\u0000\u0000\u0000\u00d8\u00bf\u0001\u0000\u0000\u0000\u00d8\u00c0"+ - "\u0001\u0000\u0000\u0000\u00d8\u00c1\u0001\u0000\u0000\u0000\u00d8\u00c2"+ - "\u0001\u0000\u0000\u0000\u00d8\u00c3\u0001\u0000\u0000\u0000\u00d8\u00c4"+ - "\u0001\u0000\u0000\u0000\u00d8\u00c5\u0001\u0000\u0000\u0000\u00d8\u00c6"+ - "\u0001\u0000\u0000\u0000\u00d8\u00c7\u0001\u0000\u0000\u0000\u00d8\u00c8"+ - "\u0001\u0000\u0000\u0000\u00d8\u00ca\u0001\u0000\u0000\u0000\u00d8\u00cc"+ - "\u0001\u0000\u0000\u0000\u00d8\u00ce\u0001\u0000\u0000\u0000\u00d8\u00d0"+ - "\u0001\u0000\u0000\u0000\u00d8\u00d2\u0001\u0000\u0000\u0000\u00d8\u00d4"+ - "\u0001\u0000\u0000\u0000\u00d8\u00d6\u0001\u0000\u0000\u0000\u00d9\u0007"+ - "\u0001\u0000\u0000\u0000\u00da\u00db\u0005\u000e\u0000\u0000\u00db\u00dc"+ - "\u0003z=\u0000\u00dc\t\u0001\u0000\u0000\u0000\u00dd\u00de\u00034\u001a"+ - "\u0000\u00de\u000b\u0001\u0000\u0000\u0000\u00df\u00e0\u0005\u000b\u0000"+ - "\u0000\u00e0\u00e1\u0003\u000e\u0007\u0000\u00e1\r\u0001\u0000\u0000\u0000"+ - "\u00e2\u00e7\u0003\u0010\b\u0000\u00e3\u00e4\u0005?\u0000\u0000\u00e4"+ - "\u00e6\u0003\u0010\b\u0000\u00e5\u00e3\u0001\u0000\u0000\u0000\u00e6\u00e9"+ - "\u0001\u0000\u0000\u0000\u00e7\u00e5\u0001\u0000\u0000\u0000\u00e7\u00e8"+ - "\u0001\u0000\u0000\u0000\u00e8\u000f\u0001\u0000\u0000\u0000\u00e9\u00e7"+ - "\u0001\u0000\u0000\u0000\u00ea\u00eb\u0003.\u0017\u0000\u00eb\u00ec\u0005"+ - ";\u0000\u0000\u00ec\u00ee\u0001\u0000\u0000\u0000\u00ed\u00ea\u0001\u0000"+ - "\u0000\u0000\u00ed\u00ee\u0001\u0000\u0000\u0000\u00ee\u00ef\u0001\u0000"+ - "\u0000\u0000\u00ef\u00f0\u0003z=\u0000\u00f0\u0011\u0001\u0000\u0000\u0000"+ - "\u00f1\u00f6\u0003\u0014\n\u0000\u00f2\u00f3\u0005?\u0000\u0000\u00f3"+ - "\u00f5\u0003\u0014\n\u0000\u00f4\u00f2\u0001\u0000\u0000\u0000\u00f5\u00f8"+ - "\u0001\u0000\u0000\u0000\u00f6\u00f4\u0001\u0000\u0000\u0000\u00f6\u00f7"+ - "\u0001\u0000\u0000\u0000\u00f7\u0013\u0001\u0000\u0000\u0000\u00f8\u00f6"+ - "\u0001\u0000\u0000\u0000\u00f9\u00fc\u0003.\u0017\u0000\u00fa\u00fb\u0005"+ - ";\u0000\u0000\u00fb\u00fd\u0003z=\u0000\u00fc\u00fa\u0001\u0000\u0000"+ - "\u0000\u00fc\u00fd\u0001\u0000\u0000\u0000\u00fd\u0015\u0001\u0000\u0000"+ - "\u0000\u00fe\u00ff\u0005\u0013\u0000\u0000\u00ff\u0100\u0003\u001a\r\u0000"+ - "\u0100\u0017\u0001\u0000\u0000\u0000\u0101\u0102\u0005\u0014\u0000\u0000"+ - "\u0102\u0103\u0003\u001a\r\u0000\u0103\u0019\u0001\u0000\u0000\u0000\u0104"+ - "\u0109\u0003\u001c\u000e\u0000\u0105\u0106\u0005?\u0000\u0000\u0106\u0108"+ - "\u0003\u001c\u000e\u0000\u0107\u0105\u0001\u0000\u0000\u0000\u0108\u010b"+ - "\u0001\u0000\u0000\u0000\u0109\u0107\u0001\u0000\u0000\u0000\u0109\u010a"+ - "\u0001\u0000\u0000\u0000\u010a\u010d\u0001\u0000\u0000\u0000\u010b\u0109"+ - "\u0001\u0000\u0000\u0000\u010c\u010e\u0003$\u0012\u0000\u010d\u010c\u0001"+ - "\u0000\u0000\u0000\u010d\u010e\u0001\u0000\u0000\u0000\u010e\u001b\u0001"+ - "\u0000\u0000\u0000\u010f\u0110\u0003\u001e\u000f\u0000\u0110\u0111\u0005"+ - ">\u0000\u0000\u0111\u0113\u0001\u0000\u0000\u0000\u0112\u010f\u0001\u0000"+ - "\u0000\u0000\u0112\u0113\u0001\u0000\u0000\u0000\u0113\u0114\u0001\u0000"+ - "\u0000\u0000\u0114\u011b\u0003\"\u0011\u0000\u0115\u0118\u0003\"\u0011"+ - "\u0000\u0116\u0117\u0005=\u0000\u0000\u0117\u0119\u0003 \u0010\u0000\u0118"+ - "\u0116\u0001\u0000\u0000\u0000\u0118\u0119\u0001\u0000\u0000\u0000\u0119"+ - "\u011b\u0001\u0000\u0000\u0000\u011a\u0112\u0001\u0000\u0000\u0000\u011a"+ - "\u0115\u0001\u0000\u0000\u0000\u011b\u001d\u0001\u0000\u0000\u0000\u011c"+ - "\u011d\u0007\u0000\u0000\u0000\u011d\u001f\u0001\u0000\u0000\u0000\u011e"+ - "\u011f\u0007\u0000\u0000\u0000\u011f!\u0001\u0000\u0000\u0000\u0120\u0121"+ - "\u0007\u0000\u0000\u0000\u0121#\u0001\u0000\u0000\u0000\u0122\u0123\u0005"+ - "k\u0000\u0000\u0123\u0128\u0005l\u0000\u0000\u0124\u0125\u0005?\u0000"+ - "\u0000\u0125\u0127\u0005l\u0000\u0000\u0126\u0124\u0001\u0000\u0000\u0000"+ - "\u0127\u012a\u0001\u0000\u0000\u0000\u0128\u0126\u0001\u0000\u0000\u0000"+ - "\u0128\u0129\u0001\u0000\u0000\u0000\u0129%\u0001\u0000\u0000\u0000\u012a"+ - "\u0128\u0001\u0000\u0000\u0000\u012b\u012c\u0005\b\u0000\u0000\u012c\u012d"+ - "\u0003\u000e\u0007\u0000\u012d\'\u0001\u0000\u0000\u0000\u012e\u0130\u0005"+ - "\r\u0000\u0000\u012f\u0131\u0003*\u0015\u0000\u0130\u012f\u0001\u0000"+ - "\u0000\u0000\u0130\u0131\u0001\u0000\u0000\u0000\u0131\u0134\u0001\u0000"+ - "\u0000\u0000\u0132\u0133\u0005<\u0000\u0000\u0133\u0135\u0003\u000e\u0007"+ - "\u0000\u0134\u0132\u0001\u0000\u0000\u0000\u0134\u0135\u0001\u0000\u0000"+ - "\u0000\u0135)\u0001\u0000\u0000\u0000\u0136\u013b\u0003,\u0016\u0000\u0137"+ - "\u0138\u0005?\u0000\u0000\u0138\u013a\u0003,\u0016\u0000\u0139\u0137\u0001"+ - "\u0000\u0000\u0000\u013a\u013d\u0001\u0000\u0000\u0000\u013b\u0139\u0001"+ - "\u0000\u0000\u0000\u013b\u013c\u0001\u0000\u0000\u0000\u013c+\u0001\u0000"+ - "\u0000\u0000\u013d\u013b\u0001\u0000\u0000\u0000\u013e\u0141\u0003\u0010"+ - "\b\u0000\u013f\u0140\u0005\u000e\u0000\u0000\u0140\u0142\u0003z=\u0000"+ - "\u0141\u013f\u0001\u0000\u0000\u0000\u0141\u0142\u0001\u0000\u0000\u0000"+ - "\u0142-\u0001\u0000\u0000\u0000\u0143\u0148\u0003<\u001e\u0000\u0144\u0145"+ - "\u0005A\u0000\u0000\u0145\u0147\u0003<\u001e\u0000\u0146\u0144\u0001\u0000"+ - "\u0000\u0000\u0147\u014a\u0001\u0000\u0000\u0000\u0148\u0146\u0001\u0000"+ - "\u0000\u0000\u0148\u0149\u0001\u0000\u0000\u0000\u0149/\u0001\u0000\u0000"+ - "\u0000\u014a\u0148\u0001\u0000\u0000\u0000\u014b\u0150\u00036\u001b\u0000"+ - "\u014c\u014d\u0005A\u0000\u0000\u014d\u014f\u00036\u001b\u0000\u014e\u014c"+ - "\u0001\u0000\u0000\u0000\u014f\u0152\u0001\u0000\u0000\u0000\u0150\u014e"+ - "\u0001\u0000\u0000\u0000\u0150\u0151\u0001\u0000\u0000\u0000\u01511\u0001"+ - "\u0000\u0000\u0000\u0152\u0150\u0001\u0000\u0000\u0000\u0153\u0158\u0003"+ - "0\u0018\u0000\u0154\u0155\u0005?\u0000\u0000\u0155\u0157\u00030\u0018"+ - "\u0000\u0156\u0154\u0001\u0000\u0000\u0000\u0157\u015a\u0001\u0000\u0000"+ - "\u0000\u0158\u0156\u0001\u0000\u0000\u0000\u0158\u0159\u0001\u0000\u0000"+ - "\u0000\u01593\u0001\u0000\u0000\u0000\u015a\u0158\u0001\u0000\u0000\u0000"+ - "\u015b\u015c\u0007\u0001\u0000\u0000\u015c5\u0001\u0000\u0000\u0000\u015d"+ - "\u0161\u0005\u0081\u0000\u0000\u015e\u0161\u00038\u001c\u0000\u015f\u0161"+ - "\u0003:\u001d\u0000\u0160\u015d\u0001\u0000\u0000\u0000\u0160\u015e\u0001"+ - "\u0000\u0000\u0000\u0160\u015f\u0001\u0000\u0000\u0000\u01617\u0001\u0000"+ - "\u0000\u0000\u0162\u0165\u0005M\u0000\u0000\u0163\u0165\u0005`\u0000\u0000"+ - "\u0164\u0162\u0001\u0000\u0000\u0000\u0164\u0163\u0001\u0000\u0000\u0000"+ - "\u01659\u0001\u0000\u0000\u0000\u0166\u0169\u0005_\u0000\u0000\u0167\u0169"+ - "\u0005a\u0000\u0000\u0168\u0166\u0001\u0000\u0000\u0000\u0168\u0167\u0001"+ - "\u0000\u0000\u0000\u0169;\u0001\u0000\u0000\u0000\u016a\u016e\u00034\u001a"+ - "\u0000\u016b\u016e\u00038\u001c\u0000\u016c\u016e\u0003:\u001d\u0000\u016d"+ - "\u016a\u0001\u0000\u0000\u0000\u016d\u016b\u0001\u0000\u0000\u0000\u016d"+ - "\u016c\u0001\u0000\u0000\u0000\u016e=\u0001\u0000\u0000\u0000\u016f\u0170"+ - "\u0005\n\u0000\u0000\u0170\u0171\u0003\u008eG\u0000\u0171?\u0001\u0000"+ - "\u0000\u0000\u0172\u0173\u0005\f\u0000\u0000\u0173\u0178\u0003B!\u0000"+ - "\u0174\u0175\u0005?\u0000\u0000\u0175\u0177\u0003B!\u0000\u0176\u0174"+ - "\u0001\u0000\u0000\u0000\u0177\u017a\u0001\u0000\u0000\u0000\u0178\u0176"+ - "\u0001\u0000\u0000\u0000\u0178\u0179\u0001\u0000\u0000\u0000\u0179A\u0001"+ - "\u0000\u0000\u0000\u017a\u0178\u0001\u0000\u0000\u0000\u017b\u017d\u0003"+ - "z=\u0000\u017c\u017e\u0007\u0002\u0000\u0000\u017d\u017c\u0001\u0000\u0000"+ - "\u0000\u017d\u017e\u0001\u0000\u0000\u0000\u017e\u0181\u0001\u0000\u0000"+ - "\u0000\u017f\u0180\u0005J\u0000\u0000\u0180\u0182\u0007\u0003\u0000\u0000"+ - "\u0181\u017f\u0001\u0000\u0000\u0000\u0181\u0182\u0001\u0000\u0000\u0000"+ - "\u0182C\u0001\u0000\u0000\u0000\u0183\u0184\u0005\u001d\u0000\u0000\u0184"+ - "\u0185\u00032\u0019\u0000\u0185E\u0001\u0000\u0000\u0000\u0186\u0187\u0005"+ - "\u001c\u0000\u0000\u0187\u0188\u00032\u0019\u0000\u0188G\u0001\u0000\u0000"+ - "\u0000\u0189\u018a\u0005 \u0000\u0000\u018a\u018f\u0003J%\u0000\u018b"+ - "\u018c\u0005?\u0000\u0000\u018c\u018e\u0003J%\u0000\u018d\u018b\u0001"+ - "\u0000\u0000\u0000\u018e\u0191\u0001\u0000\u0000\u0000\u018f\u018d\u0001"+ - "\u0000\u0000\u0000\u018f\u0190\u0001\u0000\u0000\u0000\u0190I\u0001\u0000"+ - "\u0000\u0000\u0191\u018f\u0001\u0000\u0000\u0000\u0192\u0193\u00030\u0018"+ - "\u0000\u0193\u0194\u00059\u0000\u0000\u0194\u0195\u00030\u0018\u0000\u0195"+ - "K\u0001\u0000\u0000\u0000\u0196\u0197\u0005\u0007\u0000\u0000\u0197\u0198"+ - "\u0003\u0084B\u0000\u0198\u019a\u0003\u0098L\u0000\u0199\u019b\u0003R"+ - ")\u0000\u019a\u0199\u0001\u0000\u0000\u0000\u019a\u019b\u0001\u0000\u0000"+ - "\u0000\u019bM\u0001\u0000\u0000\u0000\u019c\u019d\u0005\t\u0000\u0000"+ - "\u019d\u019e\u0003\u0084B\u0000\u019e\u019f\u0003\u0098L\u0000\u019fO"+ - "\u0001\u0000\u0000\u0000\u01a0\u01a1\u0005\u001b\u0000\u0000\u01a1\u01a2"+ - "\u0003.\u0017\u0000\u01a2Q\u0001\u0000\u0000\u0000\u01a3\u01a8\u0003T"+ - "*\u0000\u01a4\u01a5\u0005?\u0000\u0000\u01a5\u01a7\u0003T*\u0000\u01a6"+ - "\u01a4\u0001\u0000\u0000\u0000\u01a7\u01aa\u0001\u0000\u0000\u0000\u01a8"+ - "\u01a6\u0001\u0000\u0000\u0000\u01a8\u01a9\u0001\u0000\u0000\u0000\u01a9"+ - "S\u0001\u0000\u0000\u0000\u01aa\u01a8\u0001\u0000\u0000\u0000\u01ab\u01ac"+ - "\u00034\u001a\u0000\u01ac\u01ad\u0005;\u0000\u0000\u01ad\u01ae\u0003\u008e"+ - "G\u0000\u01aeU\u0001\u0000\u0000\u0000\u01af\u01b0\u0005\u0006\u0000\u0000"+ - "\u01b0\u01b1\u0003X,\u0000\u01b1W\u0001\u0000\u0000\u0000\u01b2\u01b3"+ - "\u0005b\u0000\u0000\u01b3\u01b4\u0003\u0002\u0001\u0000\u01b4\u01b5\u0005"+ - "c\u0000\u0000\u01b5Y\u0001\u0000\u0000\u0000\u01b6\u01b7\u0005!\u0000"+ - "\u0000\u01b7\u01b8\u0005\u0088\u0000\u0000\u01b8[\u0001\u0000\u0000\u0000"+ - "\u01b9\u01ba\u0005\u0005\u0000\u0000\u01ba\u01bd\u0005&\u0000\u0000\u01bb"+ - "\u01bc\u0005K\u0000\u0000\u01bc\u01be\u00030\u0018\u0000\u01bd\u01bb\u0001"+ - "\u0000\u0000\u0000\u01bd\u01be\u0001\u0000\u0000\u0000\u01be\u01c8\u0001"+ - "\u0000\u0000\u0000\u01bf\u01c0\u0005P\u0000\u0000\u01c0\u01c5\u0003^/"+ - "\u0000\u01c1\u01c2\u0005?\u0000\u0000\u01c2\u01c4\u0003^/\u0000\u01c3"+ - "\u01c1\u0001\u0000\u0000\u0000\u01c4\u01c7\u0001\u0000\u0000\u0000\u01c5"+ - "\u01c3\u0001\u0000\u0000\u0000\u01c5\u01c6\u0001\u0000\u0000\u0000\u01c6"+ - "\u01c9\u0001\u0000\u0000\u0000\u01c7\u01c5\u0001\u0000\u0000\u0000\u01c8"+ - "\u01bf\u0001\u0000\u0000\u0000\u01c8\u01c9\u0001\u0000\u0000\u0000\u01c9"+ - "]\u0001\u0000\u0000\u0000\u01ca\u01cb\u00030\u0018\u0000\u01cb\u01cc\u0005"+ - ";\u0000\u0000\u01cc\u01ce\u0001\u0000\u0000\u0000\u01cd\u01ca\u0001\u0000"+ - "\u0000\u0000\u01cd\u01ce\u0001\u0000\u0000\u0000\u01ce\u01cf\u0001\u0000"+ - "\u0000\u0000\u01cf\u01d0\u00030\u0018\u0000\u01d0_\u0001\u0000\u0000\u0000"+ - "\u01d1\u01d2\u0005\u001a\u0000\u0000\u01d2\u01d3\u0003\u001c\u000e\u0000"+ - "\u01d3\u01d4\u0005K\u0000\u0000\u01d4\u01d5\u00032\u0019\u0000\u01d5a"+ - "\u0001\u0000\u0000\u0000\u01d6\u01d7\u0005\u0010\u0000\u0000\u01d7\u01da"+ - "\u0003*\u0015\u0000\u01d8\u01d9\u0005<\u0000\u0000\u01d9\u01db\u0003\u000e"+ - "\u0007\u0000\u01da\u01d8\u0001\u0000\u0000\u0000\u01da\u01db\u0001\u0000"+ - "\u0000\u0000\u01dbc\u0001\u0000\u0000\u0000\u01dc\u01dd\u0005\u0004\u0000"+ - "\u0000\u01dd\u01e0\u0003.\u0017\u0000\u01de\u01df\u0005K\u0000\u0000\u01df"+ - "\u01e1\u0003.\u0017\u0000\u01e0\u01de\u0001\u0000\u0000\u0000\u01e0\u01e1"+ - "\u0001\u0000\u0000\u0000\u01e1\u01e7\u0001\u0000\u0000\u0000\u01e2\u01e3"+ - "\u00059\u0000\u0000\u01e3\u01e4\u0003.\u0017\u0000\u01e4\u01e5\u0005?"+ - "\u0000\u0000\u01e5\u01e6\u0003.\u0017\u0000\u01e6\u01e8\u0001\u0000\u0000"+ - "\u0000\u01e7\u01e2\u0001\u0000\u0000\u0000\u01e7\u01e8\u0001\u0000\u0000"+ - "\u0000\u01e8e\u0001\u0000\u0000\u0000\u01e9\u01ea\u0005\u001e\u0000\u0000"+ - "\u01ea\u01eb\u00032\u0019\u0000\u01ebg\u0001\u0000\u0000\u0000\u01ec\u01ed"+ - "\u0005\u0015\u0000\u0000\u01ed\u01ee\u0003j5\u0000\u01eei\u0001\u0000"+ - "\u0000\u0000\u01ef\u01f1\u0003l6\u0000\u01f0\u01ef\u0001\u0000\u0000\u0000"+ - "\u01f1\u01f2\u0001\u0000\u0000\u0000\u01f2\u01f0\u0001\u0000\u0000\u0000"+ - "\u01f2\u01f3\u0001\u0000\u0000\u0000\u01f3k\u0001\u0000\u0000\u0000\u01f4"+ - "\u01f5\u0005d\u0000\u0000\u01f5\u01f6\u0003n7\u0000\u01f6\u01f7\u0005"+ - "e\u0000\u0000\u01f7m\u0001\u0000\u0000\u0000\u01f8\u01f9\u00067\uffff"+ - "\uffff\u0000\u01f9\u01fa\u0003p8\u0000\u01fa\u0200\u0001\u0000\u0000\u0000"+ - "\u01fb\u01fc\n\u0001\u0000\u0000\u01fc\u01fd\u00054\u0000\u0000\u01fd"+ - "\u01ff\u0003p8\u0000\u01fe\u01fb\u0001\u0000\u0000\u0000\u01ff\u0202\u0001"+ - "\u0000\u0000\u0000\u0200\u01fe\u0001\u0000\u0000\u0000\u0200\u0201\u0001"+ - "\u0000\u0000\u0000\u0201o\u0001\u0000\u0000\u0000\u0202\u0200\u0001\u0000"+ - "\u0000\u0000\u0203\u020a\u0003&\u0013\u0000\u0204\u020a\u0003\b\u0004"+ - "\u0000\u0205\u020a\u0003>\u001f\u0000\u0206\u020a\u0003(\u0014\u0000\u0207"+ - "\u020a\u0003@ \u0000\u0208\u020a\u0003L&\u0000\u0209\u0203\u0001\u0000"+ - "\u0000\u0000\u0209\u0204\u0001\u0000\u0000\u0000\u0209\u0205\u0001\u0000"+ - "\u0000\u0000\u0209\u0206\u0001\u0000\u0000\u0000\u0209\u0207\u0001\u0000"+ - "\u0000\u0000\u0209\u0208\u0001\u0000\u0000\u0000\u020aq\u0001\u0000\u0000"+ - "\u0000\u020b\u020c\u0005\u001f\u0000\u0000\u020cs\u0001\u0000\u0000\u0000"+ - "\u020d\u020e\u0005\u0011\u0000\u0000\u020e\u020f\u0003\u008eG\u0000\u020f"+ - "\u0210\u0005K\u0000\u0000\u0210\u0213\u0003\u0012\t\u0000\u0211\u0212"+ - "\u0005P\u0000\u0000\u0212\u0214\u0003<\u001e\u0000\u0213\u0211\u0001\u0000"+ - "\u0000\u0000\u0213\u0214\u0001\u0000\u0000\u0000\u0214u\u0001\u0000\u0000"+ - "\u0000\u0215\u0216\u0005\u000f\u0000\u0000\u0216\u0217\u0003\u0084B\u0000"+ - "\u0217\u0218\u0005P\u0000\u0000\u0218\u021b\u0003<\u001e\u0000\u0219\u021a"+ - "\u00059\u0000\u0000\u021a\u021c\u0003.\u0017\u0000\u021b\u0219\u0001\u0000"+ - "\u0000\u0000\u021b\u021c\u0001\u0000\u0000\u0000\u021cw\u0001\u0000\u0000"+ - "\u0000\u021d\u021e\u0005\u0012\u0000\u0000\u021e\u0220\u0003\u0094J\u0000"+ - "\u021f\u0221\u0003\u0096K\u0000\u0220\u021f\u0001\u0000\u0000\u0000\u0220"+ - "\u0221\u0001\u0000\u0000\u0000\u0221y\u0001\u0000\u0000\u0000\u0222\u0223"+ - "\u0006=\uffff\uffff\u0000\u0223\u0224\u0005H\u0000\u0000\u0224\u0240\u0003"+ - "z=\b\u0225\u0240\u0003\u0080@\u0000\u0226\u0240\u0003|>\u0000\u0227\u0229"+ - "\u0003\u0080@\u0000\u0228\u022a\u0005H\u0000\u0000\u0229\u0228\u0001\u0000"+ - "\u0000\u0000\u0229\u022a\u0001\u0000\u0000\u0000\u022a\u022b\u0001\u0000"+ - "\u0000\u0000\u022b\u022c\u0005D\u0000\u0000\u022c\u022d\u0005d\u0000\u0000"+ - "\u022d\u0232\u0003\u0080@\u0000\u022e\u022f\u0005?\u0000\u0000\u022f\u0231"+ - "\u0003\u0080@\u0000\u0230\u022e\u0001\u0000\u0000\u0000\u0231\u0234\u0001"+ - "\u0000\u0000\u0000\u0232\u0230\u0001\u0000\u0000\u0000\u0232\u0233\u0001"+ - "\u0000\u0000\u0000\u0233\u0235\u0001\u0000\u0000\u0000\u0234\u0232\u0001"+ - "\u0000\u0000\u0000\u0235\u0236\u0005e\u0000\u0000\u0236\u0240\u0001\u0000"+ - "\u0000\u0000\u0237\u0238\u0003\u0080@\u0000\u0238\u023a\u0005E\u0000\u0000"+ - "\u0239\u023b\u0005H\u0000\u0000\u023a\u0239\u0001\u0000\u0000\u0000\u023a"+ - "\u023b\u0001\u0000\u0000\u0000\u023b\u023c\u0001\u0000\u0000\u0000\u023c"+ - "\u023d\u0005I\u0000\u0000\u023d\u0240\u0001\u0000\u0000\u0000\u023e\u0240"+ - "\u0003~?\u0000\u023f\u0222\u0001\u0000\u0000\u0000\u023f\u0225\u0001\u0000"+ - "\u0000\u0000\u023f\u0226\u0001\u0000\u0000\u0000\u023f\u0227\u0001\u0000"+ - "\u0000\u0000\u023f\u0237\u0001\u0000\u0000\u0000\u023f\u023e\u0001\u0000"+ - "\u0000\u0000\u0240\u0249\u0001\u0000\u0000\u0000\u0241\u0242\n\u0005\u0000"+ - "\u0000\u0242\u0243\u00058\u0000\u0000\u0243\u0248\u0003z=\u0006\u0244"+ - "\u0245\n\u0004\u0000\u0000\u0245\u0246\u0005L\u0000\u0000\u0246\u0248"+ - "\u0003z=\u0005\u0247\u0241\u0001\u0000\u0000\u0000\u0247\u0244\u0001\u0000"+ - "\u0000\u0000\u0248\u024b\u0001\u0000\u0000\u0000\u0249\u0247\u0001\u0000"+ - "\u0000\u0000\u0249\u024a\u0001\u0000\u0000\u0000\u024a{\u0001\u0000\u0000"+ - "\u0000\u024b\u0249\u0001\u0000\u0000\u0000\u024c\u024e\u0003\u0080@\u0000"+ - "\u024d\u024f\u0005H\u0000\u0000\u024e\u024d\u0001\u0000\u0000\u0000\u024e"+ - "\u024f\u0001\u0000\u0000\u0000\u024f\u0250\u0001\u0000\u0000\u0000\u0250"+ - "\u0251\u0005G\u0000\u0000\u0251\u0252\u0003\u0098L\u0000\u0252\u025b\u0001"+ - "\u0000\u0000\u0000\u0253\u0255\u0003\u0080@\u0000\u0254\u0256\u0005H\u0000"+ - "\u0000\u0255\u0254\u0001\u0000\u0000\u0000\u0255\u0256\u0001\u0000\u0000"+ - "\u0000\u0256\u0257\u0001\u0000\u0000\u0000\u0257\u0258\u0005N\u0000\u0000"+ - "\u0258\u0259\u0003\u0098L\u0000\u0259\u025b\u0001\u0000\u0000\u0000\u025a"+ - "\u024c\u0001\u0000\u0000\u0000\u025a\u0253\u0001\u0000\u0000\u0000\u025b"+ - "}\u0001\u0000\u0000\u0000\u025c\u025f\u0003.\u0017\u0000\u025d\u025e\u0005"+ - "=\u0000\u0000\u025e\u0260\u0003\n\u0005\u0000\u025f\u025d\u0001\u0000"+ - "\u0000\u0000\u025f\u0260\u0001\u0000\u0000\u0000\u0260\u0261\u0001\u0000"+ - "\u0000\u0000\u0261\u0262\u0005>\u0000\u0000\u0262\u0263\u0003\u008eG\u0000"+ - "\u0263\u007f\u0001\u0000\u0000\u0000\u0264\u026a\u0003\u0082A\u0000\u0265"+ - "\u0266\u0003\u0082A\u0000\u0266\u0267\u0003\u009aM\u0000\u0267\u0268\u0003"+ - "\u0082A\u0000\u0268\u026a\u0001\u0000\u0000\u0000\u0269\u0264\u0001\u0000"+ - "\u0000\u0000\u0269\u0265\u0001\u0000\u0000\u0000\u026a\u0081\u0001\u0000"+ - "\u0000\u0000\u026b\u026c\u0006A\uffff\uffff\u0000\u026c\u0270\u0003\u0084"+ - "B\u0000\u026d\u026e\u0007\u0004\u0000\u0000\u026e\u0270\u0003\u0082A\u0003"+ - "\u026f\u026b\u0001\u0000\u0000\u0000\u026f\u026d\u0001\u0000\u0000\u0000"+ - "\u0270\u0279\u0001\u0000\u0000\u0000\u0271\u0272\n\u0002\u0000\u0000\u0272"+ - "\u0273\u0007\u0005\u0000\u0000\u0273\u0278\u0003\u0082A\u0003\u0274\u0275"+ - "\n\u0001\u0000\u0000\u0275\u0276\u0007\u0004\u0000\u0000\u0276\u0278\u0003"+ - "\u0082A\u0002\u0277\u0271\u0001\u0000\u0000\u0000\u0277\u0274\u0001\u0000"+ - "\u0000\u0000\u0278\u027b\u0001\u0000\u0000\u0000\u0279\u0277\u0001\u0000"+ - "\u0000\u0000\u0279\u027a\u0001\u0000\u0000\u0000\u027a\u0083\u0001\u0000"+ - "\u0000\u0000\u027b\u0279\u0001\u0000\u0000\u0000\u027c\u027d\u0006B\uffff"+ - "\uffff\u0000\u027d\u0285\u0003\u008eG\u0000\u027e\u0285\u0003.\u0017\u0000"+ - "\u027f\u0285\u0003\u0086C\u0000\u0280\u0281\u0005d\u0000\u0000\u0281\u0282"+ - "\u0003z=\u0000\u0282\u0283\u0005e\u0000\u0000\u0283\u0285\u0001\u0000"+ - "\u0000\u0000\u0284\u027c\u0001\u0000\u0000\u0000\u0284\u027e\u0001\u0000"+ - "\u0000\u0000\u0284\u027f\u0001\u0000\u0000\u0000\u0284\u0280\u0001\u0000"+ - "\u0000\u0000\u0285\u028b\u0001\u0000\u0000\u0000\u0286\u0287\n\u0001\u0000"+ - "\u0000\u0287\u0288\u0005=\u0000\u0000\u0288\u028a\u0003\n\u0005\u0000"+ - "\u0289\u0286\u0001\u0000\u0000\u0000\u028a\u028d\u0001\u0000\u0000\u0000"+ - "\u028b\u0289\u0001\u0000\u0000\u0000\u028b\u028c\u0001\u0000\u0000\u0000"+ - "\u028c\u0085\u0001\u0000\u0000\u0000\u028d\u028b\u0001\u0000\u0000\u0000"+ - "\u028e\u028f\u0003\u0088D\u0000\u028f\u029d\u0005d\u0000\u0000\u0290\u029e"+ - "\u0005Z\u0000\u0000\u0291\u0296\u0003z=\u0000\u0292\u0293\u0005?\u0000"+ - "\u0000\u0293\u0295\u0003z=\u0000\u0294\u0292\u0001\u0000\u0000\u0000\u0295"+ - "\u0298\u0001\u0000\u0000\u0000\u0296\u0294\u0001\u0000\u0000\u0000\u0296"+ - "\u0297\u0001\u0000\u0000\u0000\u0297\u029b\u0001\u0000\u0000\u0000\u0298"+ - "\u0296\u0001\u0000\u0000\u0000\u0299\u029a\u0005?\u0000\u0000\u029a\u029c"+ - "\u0003\u008aE\u0000\u029b\u0299\u0001\u0000\u0000\u0000\u029b\u029c\u0001"+ - "\u0000\u0000\u0000\u029c\u029e\u0001\u0000\u0000\u0000\u029d\u0290\u0001"+ - "\u0000\u0000\u0000\u029d\u0291\u0001\u0000\u0000\u0000\u029d\u029e\u0001"+ - "\u0000\u0000\u0000\u029e\u029f\u0001\u0000\u0000\u0000\u029f\u02a0\u0005"+ - "e\u0000\u0000\u02a0\u0087\u0001\u0000\u0000\u0000\u02a1\u02a2\u0003<\u001e"+ - "\u0000\u02a2\u0089\u0001\u0000\u0000\u0000\u02a3\u02a4\u0005]\u0000\u0000"+ - "\u02a4\u02a9\u0003\u008cF\u0000\u02a5\u02a6\u0005?\u0000\u0000\u02a6\u02a8"+ - "\u0003\u008cF\u0000\u02a7\u02a5\u0001\u0000\u0000\u0000\u02a8\u02ab\u0001"+ - "\u0000\u0000\u0000\u02a9\u02a7\u0001\u0000\u0000\u0000\u02a9\u02aa\u0001"+ - "\u0000\u0000\u0000\u02aa\u02ac\u0001\u0000\u0000\u0000\u02ab\u02a9\u0001"+ - "\u0000\u0000\u0000\u02ac\u02ad\u0005^\u0000\u0000\u02ad\u008b\u0001\u0000"+ - "\u0000\u0000\u02ae\u02af\u0003\u0098L\u0000\u02af\u02b0\u0005>\u0000\u0000"+ - "\u02b0\u02b1\u0003\u008eG\u0000\u02b1\u008d\u0001\u0000\u0000\u0000\u02b2"+ - "\u02dd\u0005I\u0000\u0000\u02b3\u02b4\u0003\u0096K\u0000\u02b4\u02b5\u0005"+ - "f\u0000\u0000\u02b5\u02dd\u0001\u0000\u0000\u0000\u02b6\u02dd\u0003\u0094"+ - "J\u0000\u02b7\u02dd\u0003\u0096K\u0000\u02b8\u02dd\u0003\u0090H\u0000"+ - "\u02b9\u02dd\u00038\u001c\u0000\u02ba\u02dd\u0003\u0098L\u0000\u02bb\u02bc"+ - "\u0005b\u0000\u0000\u02bc\u02c1\u0003\u0092I\u0000\u02bd\u02be\u0005?"+ - "\u0000\u0000\u02be\u02c0\u0003\u0092I\u0000\u02bf\u02bd\u0001\u0000\u0000"+ - "\u0000\u02c0\u02c3\u0001\u0000\u0000\u0000\u02c1\u02bf\u0001\u0000\u0000"+ - "\u0000\u02c1\u02c2\u0001\u0000\u0000\u0000\u02c2\u02c4\u0001\u0000\u0000"+ - "\u0000\u02c3\u02c1\u0001\u0000\u0000\u0000\u02c4\u02c5\u0005c\u0000\u0000"+ - "\u02c5\u02dd\u0001\u0000\u0000\u0000\u02c6\u02c7\u0005b\u0000\u0000\u02c7"+ - "\u02cc\u0003\u0090H\u0000\u02c8\u02c9\u0005?\u0000\u0000\u02c9\u02cb\u0003"+ - "\u0090H\u0000\u02ca\u02c8\u0001\u0000\u0000\u0000\u02cb\u02ce\u0001\u0000"+ - "\u0000\u0000\u02cc\u02ca\u0001\u0000\u0000\u0000\u02cc\u02cd\u0001\u0000"+ - "\u0000\u0000\u02cd\u02cf\u0001\u0000\u0000\u0000\u02ce\u02cc\u0001\u0000"+ - "\u0000\u0000\u02cf\u02d0\u0005c\u0000\u0000\u02d0\u02dd\u0001\u0000\u0000"+ - "\u0000\u02d1\u02d2\u0005b\u0000\u0000\u02d2\u02d7\u0003\u0098L\u0000\u02d3"+ - "\u02d4\u0005?\u0000\u0000\u02d4\u02d6\u0003\u0098L\u0000\u02d5\u02d3\u0001"+ - "\u0000\u0000\u0000\u02d6\u02d9\u0001\u0000\u0000\u0000\u02d7\u02d5\u0001"+ - "\u0000\u0000\u0000\u02d7\u02d8\u0001\u0000\u0000\u0000\u02d8\u02da\u0001"+ - "\u0000\u0000\u0000\u02d9\u02d7\u0001\u0000\u0000\u0000\u02da\u02db\u0005"+ - "c\u0000\u0000\u02db\u02dd\u0001\u0000\u0000\u0000\u02dc\u02b2\u0001\u0000"+ - "\u0000\u0000\u02dc\u02b3\u0001\u0000\u0000\u0000\u02dc\u02b6\u0001\u0000"+ - "\u0000\u0000\u02dc\u02b7\u0001\u0000\u0000\u0000\u02dc\u02b8\u0001\u0000"+ - "\u0000\u0000\u02dc\u02b9\u0001\u0000\u0000\u0000\u02dc\u02ba\u0001\u0000"+ - "\u0000\u0000\u02dc\u02bb\u0001\u0000\u0000\u0000\u02dc\u02c6\u0001\u0000"+ - "\u0000\u0000\u02dc\u02d1\u0001\u0000\u0000\u0000\u02dd\u008f\u0001\u0000"+ - "\u0000\u0000\u02de\u02df\u0007\u0006\u0000\u0000\u02df\u0091\u0001\u0000"+ - "\u0000\u0000\u02e0\u02e3\u0003\u0094J\u0000\u02e1\u02e3\u0003\u0096K\u0000"+ - "\u02e2\u02e0\u0001\u0000\u0000\u0000\u02e2\u02e1\u0001\u0000\u0000\u0000"+ - "\u02e3\u0093\u0001\u0000\u0000\u0000\u02e4\u02e6\u0007\u0004\u0000\u0000"+ - "\u02e5\u02e4\u0001\u0000\u0000\u0000\u02e5\u02e6\u0001\u0000\u0000\u0000"+ - "\u02e6\u02e7\u0001\u0000\u0000\u0000\u02e7\u02e8\u00057\u0000\u0000\u02e8"+ - "\u0095\u0001\u0000\u0000\u0000\u02e9\u02eb\u0007\u0004\u0000\u0000\u02ea"+ - "\u02e9\u0001\u0000\u0000\u0000\u02ea\u02eb\u0001\u0000\u0000\u0000\u02eb"+ - "\u02ec\u0001\u0000\u0000\u0000\u02ec\u02ed\u00056\u0000\u0000\u02ed\u0097"+ - "\u0001\u0000\u0000\u0000\u02ee\u02ef\u00055\u0000\u0000\u02ef\u0099\u0001"+ - "\u0000\u0000\u0000\u02f0\u02f1\u0007\u0007\u0000\u0000\u02f1\u009b\u0001"+ - "\u0000\u0000\u0000\u02f2\u02f3\u0007\b\u0000\u0000\u02f3\u02f4\u0005s"+ - "\u0000\u0000\u02f4\u02f5\u0003\u009eO\u0000\u02f5\u02f6\u0003\u00a0P\u0000"+ - "\u02f6\u009d\u0001\u0000\u0000\u0000\u02f7\u02f8\u0003\u001c\u000e\u0000"+ - "\u02f8\u009f\u0001\u0000\u0000\u0000\u02f9\u02fa\u0005K\u0000\u0000\u02fa"+ - "\u02ff\u0003\u00a2Q\u0000\u02fb\u02fc\u0005?\u0000\u0000\u02fc\u02fe\u0003"+ - "\u00a2Q\u0000\u02fd\u02fb\u0001\u0000\u0000\u0000\u02fe\u0301\u0001\u0000"+ - "\u0000\u0000\u02ff\u02fd\u0001\u0000\u0000\u0000\u02ff\u0300\u0001\u0000"+ - "\u0000\u0000\u0300\u00a1\u0001\u0000\u0000\u0000\u0301\u02ff\u0001\u0000"+ - "\u0000\u0000\u0302\u0303\u0003\u0080@\u0000\u0303\u00a3\u0001\u0000\u0000"+ - "\u0000G\u00af\u00b8\u00d8\u00e7\u00ed\u00f6\u00fc\u0109\u010d\u0112\u0118"+ - "\u011a\u0128\u0130\u0134\u013b\u0141\u0148\u0150\u0158\u0160\u0164\u0168"+ - "\u016d\u0178\u017d\u0181\u018f\u019a\u01a8\u01bd\u01c5\u01c8\u01cd\u01da"+ - "\u01e0\u01e7\u01f2\u0200\u0209\u0213\u021b\u0220\u0229\u0232\u023a\u023f"+ - "\u0247\u0249\u024e\u0255\u025a\u025f\u0269\u026f\u0277\u0279\u0284\u028b"+ - "\u0296\u029b\u029d\u02a9\u02c1\u02cc\u02d7\u02dc\u02e2\u02e5\u02ea\u02ff"; + "\u0000\u00b9\u0005\u0001\u0000\u0000\u0000\u00ba\u00d8\u0003&\u0013\u0000"+ + "\u00bb\u00d8\u0003\b\u0004\u0000\u00bc\u00d8\u0003D\"\u0000\u00bd\u00d8"+ + "\u0003>\u001f\u0000\u00be\u00d8\u0003(\u0014\u0000\u00bf\u00d8\u0003@"+ + " \u0000\u00c0\u00d8\u0003F#\u0000\u00c1\u00d8\u0003H$\u0000\u00c2\u00d8"+ + "\u0003L&\u0000\u00c3\u00d8\u0003N\'\u0000\u00c4\u00d8\u0003\\.\u0000\u00c5"+ + "\u00d8\u0003P(\u0000\u00c6\u00d8\u0003\u009cN\u0000\u00c7\u00d8\u0003"+ + "d2\u0000\u00c8\u00d8\u0003v;\u0000\u00c9\u00ca\u0004\u0003\u0002\u0000"+ + "\u00ca\u00d8\u0003b1\u0000\u00cb\u00cc\u0004\u0003\u0003\u0000\u00cc\u00d8"+ + "\u0003`0\u0000\u00cd\u00ce\u0004\u0003\u0004\u0000\u00ce\u00d8\u0003f"+ + "3\u0000\u00cf\u00d0\u0004\u0003\u0005\u0000\u00d0\u00d8\u0003h4\u0000"+ + "\u00d1\u00d2\u0004\u0003\u0006\u0000\u00d2\u00d8\u0003t:\u0000\u00d3\u00d4"+ + "\u0004\u0003\u0007\u0000\u00d4\u00d8\u0003r9\u0000\u00d5\u00d6\u0004\u0003"+ + "\b\u0000\u00d6\u00d8\u0003x<\u0000\u00d7\u00ba\u0001\u0000\u0000\u0000"+ + "\u00d7\u00bb\u0001\u0000\u0000\u0000\u00d7\u00bc\u0001\u0000\u0000\u0000"+ + "\u00d7\u00bd\u0001\u0000\u0000\u0000\u00d7\u00be\u0001\u0000\u0000\u0000"+ + "\u00d7\u00bf\u0001\u0000\u0000\u0000\u00d7\u00c0\u0001\u0000\u0000\u0000"+ + "\u00d7\u00c1\u0001\u0000\u0000\u0000\u00d7\u00c2\u0001\u0000\u0000\u0000"+ + "\u00d7\u00c3\u0001\u0000\u0000\u0000\u00d7\u00c4\u0001\u0000\u0000\u0000"+ + "\u00d7\u00c5\u0001\u0000\u0000\u0000\u00d7\u00c6\u0001\u0000\u0000\u0000"+ + "\u00d7\u00c7\u0001\u0000\u0000\u0000\u00d7\u00c8\u0001\u0000\u0000\u0000"+ + "\u00d7\u00c9\u0001\u0000\u0000\u0000\u00d7\u00cb\u0001\u0000\u0000\u0000"+ + "\u00d7\u00cd\u0001\u0000\u0000\u0000\u00d7\u00cf\u0001\u0000\u0000\u0000"+ + "\u00d7\u00d1\u0001\u0000\u0000\u0000\u00d7\u00d3\u0001\u0000\u0000\u0000"+ + "\u00d7\u00d5\u0001\u0000\u0000\u0000\u00d8\u0007\u0001\u0000\u0000\u0000"+ + "\u00d9\u00da\u0005\u000f\u0000\u0000\u00da\u00db\u0003z=\u0000\u00db\t"+ + "\u0001\u0000\u0000\u0000\u00dc\u00dd\u00034\u001a\u0000\u00dd\u000b\u0001"+ + "\u0000\u0000\u0000\u00de\u00df\u0005\f\u0000\u0000\u00df\u00e0\u0003\u000e"+ + "\u0007\u0000\u00e0\r\u0001\u0000\u0000\u0000\u00e1\u00e6\u0003\u0010\b"+ + "\u0000\u00e2\u00e3\u0005?\u0000\u0000\u00e3\u00e5\u0003\u0010\b\u0000"+ + "\u00e4\u00e2\u0001\u0000\u0000\u0000\u00e5\u00e8\u0001\u0000\u0000\u0000"+ + "\u00e6\u00e4\u0001\u0000\u0000\u0000\u00e6\u00e7\u0001\u0000\u0000\u0000"+ + "\u00e7\u000f\u0001\u0000\u0000\u0000\u00e8\u00e6\u0001\u0000\u0000\u0000"+ + "\u00e9\u00ea\u0003.\u0017\u0000\u00ea\u00eb\u0005;\u0000\u0000\u00eb\u00ed"+ + "\u0001\u0000\u0000\u0000\u00ec\u00e9\u0001\u0000\u0000\u0000\u00ec\u00ed"+ + "\u0001\u0000\u0000\u0000\u00ed\u00ee\u0001\u0000\u0000\u0000\u00ee\u00ef"+ + "\u0003z=\u0000\u00ef\u0011\u0001\u0000\u0000\u0000\u00f0\u00f5\u0003\u0014"+ + "\n\u0000\u00f1\u00f2\u0005?\u0000\u0000\u00f2\u00f4\u0003\u0014\n\u0000"+ + "\u00f3\u00f1\u0001\u0000\u0000\u0000\u00f4\u00f7\u0001\u0000\u0000\u0000"+ + "\u00f5\u00f3\u0001\u0000\u0000\u0000\u00f5\u00f6\u0001\u0000\u0000\u0000"+ + "\u00f6\u0013\u0001\u0000\u0000\u0000\u00f7\u00f5\u0001\u0000\u0000\u0000"+ + "\u00f8\u00fb\u0003.\u0017\u0000\u00f9\u00fa\u0005;\u0000\u0000\u00fa\u00fc"+ + "\u0003z=\u0000\u00fb\u00f9\u0001\u0000\u0000\u0000\u00fb\u00fc\u0001\u0000"+ + "\u0000\u0000\u00fc\u0015\u0001\u0000\u0000\u0000\u00fd\u00fe\u0005\u0013"+ + "\u0000\u0000\u00fe\u00ff\u0003\u001a\r\u0000\u00ff\u0017\u0001\u0000\u0000"+ + "\u0000\u0100\u0101\u0005\u0014\u0000\u0000\u0101\u0102\u0003\u001a\r\u0000"+ + "\u0102\u0019\u0001\u0000\u0000\u0000\u0103\u0108\u0003\u001c\u000e\u0000"+ + "\u0104\u0105\u0005?\u0000\u0000\u0105\u0107\u0003\u001c\u000e\u0000\u0106"+ + "\u0104\u0001\u0000\u0000\u0000\u0107\u010a\u0001\u0000\u0000\u0000\u0108"+ + "\u0106\u0001\u0000\u0000\u0000\u0108\u0109\u0001\u0000\u0000\u0000\u0109"+ + "\u010c\u0001\u0000\u0000\u0000\u010a\u0108\u0001\u0000\u0000\u0000\u010b"+ + "\u010d\u0003$\u0012\u0000\u010c\u010b\u0001\u0000\u0000\u0000\u010c\u010d"+ + "\u0001\u0000\u0000\u0000\u010d\u001b\u0001\u0000\u0000\u0000\u010e\u010f"+ + "\u0003\u001e\u000f\u0000\u010f\u0110\u0005>\u0000\u0000\u0110\u0112\u0001"+ + "\u0000\u0000\u0000\u0111\u010e\u0001\u0000\u0000\u0000\u0111\u0112\u0001"+ + "\u0000\u0000\u0000\u0112\u0113\u0001\u0000\u0000\u0000\u0113\u011a\u0003"+ + "\"\u0011\u0000\u0114\u0117\u0003\"\u0011\u0000\u0115\u0116\u0005=\u0000"+ + "\u0000\u0116\u0118\u0003 \u0010\u0000\u0117\u0115\u0001\u0000\u0000\u0000"+ + "\u0117\u0118\u0001\u0000\u0000\u0000\u0118\u011a\u0001\u0000\u0000\u0000"+ + "\u0119\u0111\u0001\u0000\u0000\u0000\u0119\u0114\u0001\u0000\u0000\u0000"+ + "\u011a\u001d\u0001\u0000\u0000\u0000\u011b\u011c\u0007\u0000\u0000\u0000"+ + "\u011c\u001f\u0001\u0000\u0000\u0000\u011d\u011e\u0007\u0000\u0000\u0000"+ + "\u011e!\u0001\u0000\u0000\u0000\u011f\u0120\u0007\u0000\u0000\u0000\u0120"+ + "#\u0001\u0000\u0000\u0000\u0121\u0122\u0005k\u0000\u0000\u0122\u0127\u0005"+ + "l\u0000\u0000\u0123\u0124\u0005?\u0000\u0000\u0124\u0126\u0005l\u0000"+ + "\u0000\u0125\u0123\u0001\u0000\u0000\u0000\u0126\u0129\u0001\u0000\u0000"+ + "\u0000\u0127\u0125\u0001\u0000\u0000\u0000\u0127\u0128\u0001\u0000\u0000"+ + "\u0000\u0128%\u0001\u0000\u0000\u0000\u0129\u0127\u0001\u0000\u0000\u0000"+ + "\u012a\u012b\u0005\t\u0000\u0000\u012b\u012c\u0003\u000e\u0007\u0000\u012c"+ + "\'\u0001\u0000\u0000\u0000\u012d\u012f\u0005\u000e\u0000\u0000\u012e\u0130"+ + "\u0003*\u0015\u0000\u012f\u012e\u0001\u0000\u0000\u0000\u012f\u0130\u0001"+ + "\u0000\u0000\u0000\u0130\u0133\u0001\u0000\u0000\u0000\u0131\u0132\u0005"+ + "<\u0000\u0000\u0132\u0134\u0003\u000e\u0007\u0000\u0133\u0131\u0001\u0000"+ + "\u0000\u0000\u0133\u0134\u0001\u0000\u0000\u0000\u0134)\u0001\u0000\u0000"+ + "\u0000\u0135\u013a\u0003,\u0016\u0000\u0136\u0137\u0005?\u0000\u0000\u0137"+ + "\u0139\u0003,\u0016\u0000\u0138\u0136\u0001\u0000\u0000\u0000\u0139\u013c"+ + "\u0001\u0000\u0000\u0000\u013a\u0138\u0001\u0000\u0000\u0000\u013a\u013b"+ + "\u0001\u0000\u0000\u0000\u013b+\u0001\u0000\u0000\u0000\u013c\u013a\u0001"+ + "\u0000\u0000\u0000\u013d\u0140\u0003\u0010\b\u0000\u013e\u013f\u0005\u000f"+ + "\u0000\u0000\u013f\u0141\u0003z=\u0000\u0140\u013e\u0001\u0000\u0000\u0000"+ + "\u0140\u0141\u0001\u0000\u0000\u0000\u0141-\u0001\u0000\u0000\u0000\u0142"+ + "\u0147\u0003<\u001e\u0000\u0143\u0144\u0005A\u0000\u0000\u0144\u0146\u0003"+ + "<\u001e\u0000\u0145\u0143\u0001\u0000\u0000\u0000\u0146\u0149\u0001\u0000"+ + "\u0000\u0000\u0147\u0145\u0001\u0000\u0000\u0000\u0147\u0148\u0001\u0000"+ + "\u0000\u0000\u0148/\u0001\u0000\u0000\u0000\u0149\u0147\u0001\u0000\u0000"+ + "\u0000\u014a\u014f\u00036\u001b\u0000\u014b\u014c\u0005A\u0000\u0000\u014c"+ + "\u014e\u00036\u001b\u0000\u014d\u014b\u0001\u0000\u0000\u0000\u014e\u0151"+ + "\u0001\u0000\u0000\u0000\u014f\u014d\u0001\u0000\u0000\u0000\u014f\u0150"+ + "\u0001\u0000\u0000\u0000\u01501\u0001\u0000\u0000\u0000\u0151\u014f\u0001"+ + "\u0000\u0000\u0000\u0152\u0157\u00030\u0018\u0000\u0153\u0154\u0005?\u0000"+ + "\u0000\u0154\u0156\u00030\u0018\u0000\u0155\u0153\u0001\u0000\u0000\u0000"+ + "\u0156\u0159\u0001\u0000\u0000\u0000\u0157\u0155\u0001\u0000\u0000\u0000"+ + "\u0157\u0158\u0001\u0000\u0000\u0000\u01583\u0001\u0000\u0000\u0000\u0159"+ + "\u0157\u0001\u0000\u0000\u0000\u015a\u015b\u0007\u0001\u0000\u0000\u015b"+ + "5\u0001\u0000\u0000\u0000\u015c\u0160\u0005\u0081\u0000\u0000\u015d\u0160"+ + "\u00038\u001c\u0000\u015e\u0160\u0003:\u001d\u0000\u015f\u015c\u0001\u0000"+ + "\u0000\u0000\u015f\u015d\u0001\u0000\u0000\u0000\u015f\u015e\u0001\u0000"+ + "\u0000\u0000\u01607\u0001\u0000\u0000\u0000\u0161\u0164\u0005M\u0000\u0000"+ + "\u0162\u0164\u0005`\u0000\u0000\u0163\u0161\u0001\u0000\u0000\u0000\u0163"+ + "\u0162\u0001\u0000\u0000\u0000\u01649\u0001\u0000\u0000\u0000\u0165\u0168"+ + "\u0005_\u0000\u0000\u0166\u0168\u0005a\u0000\u0000\u0167\u0165\u0001\u0000"+ + "\u0000\u0000\u0167\u0166\u0001\u0000\u0000\u0000\u0168;\u0001\u0000\u0000"+ + "\u0000\u0169\u016d\u00034\u001a\u0000\u016a\u016d\u00038\u001c\u0000\u016b"+ + "\u016d\u0003:\u001d\u0000\u016c\u0169\u0001\u0000\u0000\u0000\u016c\u016a"+ + "\u0001\u0000\u0000\u0000\u016c\u016b\u0001\u0000\u0000\u0000\u016d=\u0001"+ + "\u0000\u0000\u0000\u016e\u016f\u0005\u000b\u0000\u0000\u016f\u0170\u0003"+ + "\u008eG\u0000\u0170?\u0001\u0000\u0000\u0000\u0171\u0172\u0005\r\u0000"+ + "\u0000\u0172\u0177\u0003B!\u0000\u0173\u0174\u0005?\u0000\u0000\u0174"+ + "\u0176\u0003B!\u0000\u0175\u0173\u0001\u0000\u0000\u0000\u0176\u0179\u0001"+ + "\u0000\u0000\u0000\u0177\u0175\u0001\u0000\u0000\u0000\u0177\u0178\u0001"+ + "\u0000\u0000\u0000\u0178A\u0001\u0000\u0000\u0000\u0179\u0177\u0001\u0000"+ + "\u0000\u0000\u017a\u017c\u0003z=\u0000\u017b\u017d\u0007\u0002\u0000\u0000"+ + "\u017c\u017b\u0001\u0000\u0000\u0000\u017c\u017d\u0001\u0000\u0000\u0000"+ + "\u017d\u0180\u0001\u0000\u0000\u0000\u017e\u017f\u0005J\u0000\u0000\u017f"+ + "\u0181\u0007\u0003\u0000\u0000\u0180\u017e\u0001\u0000\u0000\u0000\u0180"+ + "\u0181\u0001\u0000\u0000\u0000\u0181C\u0001\u0000\u0000\u0000\u0182\u0183"+ + "\u0005\u001d\u0000\u0000\u0183\u0184\u00032\u0019\u0000\u0184E\u0001\u0000"+ + "\u0000\u0000\u0185\u0186\u0005\u001c\u0000\u0000\u0186\u0187\u00032\u0019"+ + "\u0000\u0187G\u0001\u0000\u0000\u0000\u0188\u0189\u0005 \u0000\u0000\u0189"+ + "\u018e\u0003J%\u0000\u018a\u018b\u0005?\u0000\u0000\u018b\u018d\u0003"+ + "J%\u0000\u018c\u018a\u0001\u0000\u0000\u0000\u018d\u0190\u0001\u0000\u0000"+ + "\u0000\u018e\u018c\u0001\u0000\u0000\u0000\u018e\u018f\u0001\u0000\u0000"+ + "\u0000\u018fI\u0001\u0000\u0000\u0000\u0190\u018e\u0001\u0000\u0000\u0000"+ + "\u0191\u0192\u00030\u0018\u0000\u0192\u0193\u00059\u0000\u0000\u0193\u0194"+ + "\u00030\u0018\u0000\u0194K\u0001\u0000\u0000\u0000\u0195\u0196\u0005\b"+ + "\u0000\u0000\u0196\u0197\u0003\u0084B\u0000\u0197\u0199\u0003\u0098L\u0000"+ + "\u0198\u019a\u0003R)\u0000\u0199\u0198\u0001\u0000\u0000\u0000\u0199\u019a"+ + "\u0001\u0000\u0000\u0000\u019aM\u0001\u0000\u0000\u0000\u019b\u019c\u0005"+ + "\n\u0000\u0000\u019c\u019d\u0003\u0084B\u0000\u019d\u019e\u0003\u0098"+ + "L\u0000\u019eO\u0001\u0000\u0000\u0000\u019f\u01a0\u0005\u001b\u0000\u0000"+ + "\u01a0\u01a1\u0003.\u0017\u0000\u01a1Q\u0001\u0000\u0000\u0000\u01a2\u01a7"+ + "\u0003T*\u0000\u01a3\u01a4\u0005?\u0000\u0000\u01a4\u01a6\u0003T*\u0000"+ + "\u01a5\u01a3\u0001\u0000\u0000\u0000\u01a6\u01a9\u0001\u0000\u0000\u0000"+ + "\u01a7\u01a5\u0001\u0000\u0000\u0000\u01a7\u01a8\u0001\u0000\u0000\u0000"+ + "\u01a8S\u0001\u0000\u0000\u0000\u01a9\u01a7\u0001\u0000\u0000\u0000\u01aa"+ + "\u01ab\u00034\u001a\u0000\u01ab\u01ac\u0005;\u0000\u0000\u01ac\u01ad\u0003"+ + "\u008eG\u0000\u01adU\u0001\u0000\u0000\u0000\u01ae\u01af\u0005\u0006\u0000"+ + "\u0000\u01af\u01b0\u0003X,\u0000\u01b0W\u0001\u0000\u0000\u0000\u01b1"+ + "\u01b2\u0005b\u0000\u0000\u01b2\u01b3\u0003\u0002\u0001\u0000\u01b3\u01b4"+ + "\u0005c\u0000\u0000\u01b4Y\u0001\u0000\u0000\u0000\u01b5\u01b6\u0005!"+ + "\u0000\u0000\u01b6\u01b7\u0005\u0088\u0000\u0000\u01b7[\u0001\u0000\u0000"+ + "\u0000\u01b8\u01b9\u0005\u0005\u0000\u0000\u01b9\u01bc\u0005&\u0000\u0000"+ + "\u01ba\u01bb\u0005K\u0000\u0000\u01bb\u01bd\u00030\u0018\u0000\u01bc\u01ba"+ + "\u0001\u0000\u0000\u0000\u01bc\u01bd\u0001\u0000\u0000\u0000\u01bd\u01c7"+ + "\u0001\u0000\u0000\u0000\u01be\u01bf\u0005P\u0000\u0000\u01bf\u01c4\u0003"+ + "^/\u0000\u01c0\u01c1\u0005?\u0000\u0000\u01c1\u01c3\u0003^/\u0000\u01c2"+ + "\u01c0\u0001\u0000\u0000\u0000\u01c3\u01c6\u0001\u0000\u0000\u0000\u01c4"+ + "\u01c2\u0001\u0000\u0000\u0000\u01c4\u01c5\u0001\u0000\u0000\u0000\u01c5"+ + "\u01c8\u0001\u0000\u0000\u0000\u01c6\u01c4\u0001\u0000\u0000\u0000\u01c7"+ + "\u01be\u0001\u0000\u0000\u0000\u01c7\u01c8\u0001\u0000\u0000\u0000\u01c8"+ + "]\u0001\u0000\u0000\u0000\u01c9\u01ca\u00030\u0018\u0000\u01ca\u01cb\u0005"+ + ";\u0000\u0000\u01cb\u01cd\u0001\u0000\u0000\u0000\u01cc\u01c9\u0001\u0000"+ + "\u0000\u0000\u01cc\u01cd\u0001\u0000\u0000\u0000\u01cd\u01ce\u0001\u0000"+ + "\u0000\u0000\u01ce\u01cf\u00030\u0018\u0000\u01cf_\u0001\u0000\u0000\u0000"+ + "\u01d0\u01d1\u0005\u001a\u0000\u0000\u01d1\u01d2\u0003\u001c\u000e\u0000"+ + "\u01d2\u01d3\u0005K\u0000\u0000\u01d3\u01d4\u00032\u0019\u0000\u01d4a"+ + "\u0001\u0000\u0000\u0000\u01d5\u01d6\u0005\u0010\u0000\u0000\u01d6\u01d9"+ + "\u0003*\u0015\u0000\u01d7\u01d8\u0005<\u0000\u0000\u01d8\u01da\u0003\u000e"+ + "\u0007\u0000\u01d9\u01d7\u0001\u0000\u0000\u0000\u01d9\u01da\u0001\u0000"+ + "\u0000\u0000\u01dac\u0001\u0000\u0000\u0000\u01db\u01dc\u0005\u0004\u0000"+ + "\u0000\u01dc\u01df\u0003.\u0017\u0000\u01dd\u01de\u0005K\u0000\u0000\u01de"+ + "\u01e0\u0003.\u0017\u0000\u01df\u01dd\u0001\u0000\u0000\u0000\u01df\u01e0"+ + "\u0001\u0000\u0000\u0000\u01e0\u01e6\u0001\u0000\u0000\u0000\u01e1\u01e2"+ + "\u00059\u0000\u0000\u01e2\u01e3\u0003.\u0017\u0000\u01e3\u01e4\u0005?"+ + "\u0000\u0000\u01e4\u01e5\u0003.\u0017\u0000\u01e5\u01e7\u0001\u0000\u0000"+ + "\u0000\u01e6\u01e1\u0001\u0000\u0000\u0000\u01e6\u01e7\u0001\u0000\u0000"+ + "\u0000\u01e7e\u0001\u0000\u0000\u0000\u01e8\u01e9\u0005\u001e\u0000\u0000"+ + "\u01e9\u01ea\u00032\u0019\u0000\u01eag\u0001\u0000\u0000\u0000\u01eb\u01ec"+ + "\u0005\u0015\u0000\u0000\u01ec\u01ed\u0003j5\u0000\u01edi\u0001\u0000"+ + "\u0000\u0000\u01ee\u01f0\u0003l6\u0000\u01ef\u01ee\u0001\u0000\u0000\u0000"+ + "\u01f0\u01f1\u0001\u0000\u0000\u0000\u01f1\u01ef\u0001\u0000\u0000\u0000"+ + "\u01f1\u01f2\u0001\u0000\u0000\u0000\u01f2k\u0001\u0000\u0000\u0000\u01f3"+ + "\u01f4\u0005d\u0000\u0000\u01f4\u01f5\u0003n7\u0000\u01f5\u01f6\u0005"+ + "e\u0000\u0000\u01f6m\u0001\u0000\u0000\u0000\u01f7\u01f8\u00067\uffff"+ + "\uffff\u0000\u01f8\u01f9\u0003p8\u0000\u01f9\u01ff\u0001\u0000\u0000\u0000"+ + "\u01fa\u01fb\n\u0001\u0000\u0000\u01fb\u01fc\u00054\u0000\u0000\u01fc"+ + "\u01fe\u0003p8\u0000\u01fd\u01fa\u0001\u0000\u0000\u0000\u01fe\u0201\u0001"+ + "\u0000\u0000\u0000\u01ff\u01fd\u0001\u0000\u0000\u0000\u01ff\u0200\u0001"+ + "\u0000\u0000\u0000\u0200o\u0001\u0000\u0000\u0000\u0201\u01ff\u0001\u0000"+ + "\u0000\u0000\u0202\u0209\u0003&\u0013\u0000\u0203\u0209\u0003\b\u0004"+ + "\u0000\u0204\u0209\u0003>\u001f\u0000\u0205\u0209\u0003(\u0014\u0000\u0206"+ + "\u0209\u0003@ \u0000\u0207\u0209\u0003L&\u0000\u0208\u0202\u0001\u0000"+ + "\u0000\u0000\u0208\u0203\u0001\u0000\u0000\u0000\u0208\u0204\u0001\u0000"+ + "\u0000\u0000\u0208\u0205\u0001\u0000\u0000\u0000\u0208\u0206\u0001\u0000"+ + "\u0000\u0000\u0208\u0207\u0001\u0000\u0000\u0000\u0209q\u0001\u0000\u0000"+ + "\u0000\u020a\u020b\u0005\u001f\u0000\u0000\u020bs\u0001\u0000\u0000\u0000"+ + "\u020c\u020d\u0005\u0011\u0000\u0000\u020d\u020e\u0003\u008eG\u0000\u020e"+ + "\u020f\u0005K\u0000\u0000\u020f\u0212\u0003\u0012\t\u0000\u0210\u0211"+ + "\u0005P\u0000\u0000\u0211\u0213\u0003<\u001e\u0000\u0212\u0210\u0001\u0000"+ + "\u0000\u0000\u0212\u0213\u0001\u0000\u0000\u0000\u0213u\u0001\u0000\u0000"+ + "\u0000\u0214\u0215\u0005\u0007\u0000\u0000\u0215\u0216\u0003\u0084B\u0000"+ + "\u0216\u0217\u0005P\u0000\u0000\u0217\u021a\u0003<\u001e\u0000\u0218\u0219"+ + "\u00059\u0000\u0000\u0219\u021b\u0003.\u0017\u0000\u021a\u0218\u0001\u0000"+ + "\u0000\u0000\u021a\u021b\u0001\u0000\u0000\u0000\u021bw\u0001\u0000\u0000"+ + "\u0000\u021c\u021d\u0005\u0012\u0000\u0000\u021d\u021f\u0003\u0094J\u0000"+ + "\u021e\u0220\u0003\u0096K\u0000\u021f\u021e\u0001\u0000\u0000\u0000\u021f"+ + "\u0220\u0001\u0000\u0000\u0000\u0220y\u0001\u0000\u0000\u0000\u0221\u0222"+ + "\u0006=\uffff\uffff\u0000\u0222\u0223\u0005H\u0000\u0000\u0223\u023f\u0003"+ + "z=\b\u0224\u023f\u0003\u0080@\u0000\u0225\u023f\u0003|>\u0000\u0226\u0228"+ + "\u0003\u0080@\u0000\u0227\u0229\u0005H\u0000\u0000\u0228\u0227\u0001\u0000"+ + "\u0000\u0000\u0228\u0229\u0001\u0000\u0000\u0000\u0229\u022a\u0001\u0000"+ + "\u0000\u0000\u022a\u022b\u0005D\u0000\u0000\u022b\u022c\u0005d\u0000\u0000"+ + "\u022c\u0231\u0003\u0080@\u0000\u022d\u022e\u0005?\u0000\u0000\u022e\u0230"+ + "\u0003\u0080@\u0000\u022f\u022d\u0001\u0000\u0000\u0000\u0230\u0233\u0001"+ + "\u0000\u0000\u0000\u0231\u022f\u0001\u0000\u0000\u0000\u0231\u0232\u0001"+ + "\u0000\u0000\u0000\u0232\u0234\u0001\u0000\u0000\u0000\u0233\u0231\u0001"+ + "\u0000\u0000\u0000\u0234\u0235\u0005e\u0000\u0000\u0235\u023f\u0001\u0000"+ + "\u0000\u0000\u0236\u0237\u0003\u0080@\u0000\u0237\u0239\u0005E\u0000\u0000"+ + "\u0238\u023a\u0005H\u0000\u0000\u0239\u0238\u0001\u0000\u0000\u0000\u0239"+ + "\u023a\u0001\u0000\u0000\u0000\u023a\u023b\u0001\u0000\u0000\u0000\u023b"+ + "\u023c\u0005I\u0000\u0000\u023c\u023f\u0001\u0000\u0000\u0000\u023d\u023f"+ + "\u0003~?\u0000\u023e\u0221\u0001\u0000\u0000\u0000\u023e\u0224\u0001\u0000"+ + "\u0000\u0000\u023e\u0225\u0001\u0000\u0000\u0000\u023e\u0226\u0001\u0000"+ + "\u0000\u0000\u023e\u0236\u0001\u0000\u0000\u0000\u023e\u023d\u0001\u0000"+ + "\u0000\u0000\u023f\u0248\u0001\u0000\u0000\u0000\u0240\u0241\n\u0005\u0000"+ + "\u0000\u0241\u0242\u00058\u0000\u0000\u0242\u0247\u0003z=\u0006\u0243"+ + "\u0244\n\u0004\u0000\u0000\u0244\u0245\u0005L\u0000\u0000\u0245\u0247"+ + "\u0003z=\u0005\u0246\u0240\u0001\u0000\u0000\u0000\u0246\u0243\u0001\u0000"+ + "\u0000\u0000\u0247\u024a\u0001\u0000\u0000\u0000\u0248\u0246\u0001\u0000"+ + "\u0000\u0000\u0248\u0249\u0001\u0000\u0000\u0000\u0249{\u0001\u0000\u0000"+ + "\u0000\u024a\u0248\u0001\u0000\u0000\u0000\u024b\u024d\u0003\u0080@\u0000"+ + "\u024c\u024e\u0005H\u0000\u0000\u024d\u024c\u0001\u0000\u0000\u0000\u024d"+ + "\u024e\u0001\u0000\u0000\u0000\u024e\u024f\u0001\u0000\u0000\u0000\u024f"+ + "\u0250\u0005G\u0000\u0000\u0250\u0251\u0003\u0098L\u0000\u0251\u025a\u0001"+ + "\u0000\u0000\u0000\u0252\u0254\u0003\u0080@\u0000\u0253\u0255\u0005H\u0000"+ + "\u0000\u0254\u0253\u0001\u0000\u0000\u0000\u0254\u0255\u0001\u0000\u0000"+ + "\u0000\u0255\u0256\u0001\u0000\u0000\u0000\u0256\u0257\u0005N\u0000\u0000"+ + "\u0257\u0258\u0003\u0098L\u0000\u0258\u025a\u0001\u0000\u0000\u0000\u0259"+ + "\u024b\u0001\u0000\u0000\u0000\u0259\u0252\u0001\u0000\u0000\u0000\u025a"+ + "}\u0001\u0000\u0000\u0000\u025b\u025e\u0003.\u0017\u0000\u025c\u025d\u0005"+ + "=\u0000\u0000\u025d\u025f\u0003\n\u0005\u0000\u025e\u025c\u0001\u0000"+ + "\u0000\u0000\u025e\u025f\u0001\u0000\u0000\u0000\u025f\u0260\u0001\u0000"+ + "\u0000\u0000\u0260\u0261\u0005>\u0000\u0000\u0261\u0262\u0003\u008eG\u0000"+ + "\u0262\u007f\u0001\u0000\u0000\u0000\u0263\u0269\u0003\u0082A\u0000\u0264"+ + "\u0265\u0003\u0082A\u0000\u0265\u0266\u0003\u009aM\u0000\u0266\u0267\u0003"+ + "\u0082A\u0000\u0267\u0269\u0001\u0000\u0000\u0000\u0268\u0263\u0001\u0000"+ + "\u0000\u0000\u0268\u0264\u0001\u0000\u0000\u0000\u0269\u0081\u0001\u0000"+ + "\u0000\u0000\u026a\u026b\u0006A\uffff\uffff\u0000\u026b\u026f\u0003\u0084"+ + "B\u0000\u026c\u026d\u0007\u0004\u0000\u0000\u026d\u026f\u0003\u0082A\u0003"+ + "\u026e\u026a\u0001\u0000\u0000\u0000\u026e\u026c\u0001\u0000\u0000\u0000"+ + "\u026f\u0278\u0001\u0000\u0000\u0000\u0270\u0271\n\u0002\u0000\u0000\u0271"+ + "\u0272\u0007\u0005\u0000\u0000\u0272\u0277\u0003\u0082A\u0003\u0273\u0274"+ + "\n\u0001\u0000\u0000\u0274\u0275\u0007\u0004\u0000\u0000\u0275\u0277\u0003"+ + "\u0082A\u0002\u0276\u0270\u0001\u0000\u0000\u0000\u0276\u0273\u0001\u0000"+ + "\u0000\u0000\u0277\u027a\u0001\u0000\u0000\u0000\u0278\u0276\u0001\u0000"+ + "\u0000\u0000\u0278\u0279\u0001\u0000\u0000\u0000\u0279\u0083\u0001\u0000"+ + "\u0000\u0000\u027a\u0278\u0001\u0000\u0000\u0000\u027b\u027c\u0006B\uffff"+ + "\uffff\u0000\u027c\u0284\u0003\u008eG\u0000\u027d\u0284\u0003.\u0017\u0000"+ + "\u027e\u0284\u0003\u0086C\u0000\u027f\u0280\u0005d\u0000\u0000\u0280\u0281"+ + "\u0003z=\u0000\u0281\u0282\u0005e\u0000\u0000\u0282\u0284\u0001\u0000"+ + "\u0000\u0000\u0283\u027b\u0001\u0000\u0000\u0000\u0283\u027d\u0001\u0000"+ + "\u0000\u0000\u0283\u027e\u0001\u0000\u0000\u0000\u0283\u027f\u0001\u0000"+ + "\u0000\u0000\u0284\u028a\u0001\u0000\u0000\u0000\u0285\u0286\n\u0001\u0000"+ + "\u0000\u0286\u0287\u0005=\u0000\u0000\u0287\u0289\u0003\n\u0005\u0000"+ + "\u0288\u0285\u0001\u0000\u0000\u0000\u0289\u028c\u0001\u0000\u0000\u0000"+ + "\u028a\u0288\u0001\u0000\u0000\u0000\u028a\u028b\u0001\u0000\u0000\u0000"+ + "\u028b\u0085\u0001\u0000\u0000\u0000\u028c\u028a\u0001\u0000\u0000\u0000"+ + "\u028d\u028e\u0003\u0088D\u0000\u028e\u029c\u0005d\u0000\u0000\u028f\u029d"+ + "\u0005Z\u0000\u0000\u0290\u0295\u0003z=\u0000\u0291\u0292\u0005?\u0000"+ + "\u0000\u0292\u0294\u0003z=\u0000\u0293\u0291\u0001\u0000\u0000\u0000\u0294"+ + "\u0297\u0001\u0000\u0000\u0000\u0295\u0293\u0001\u0000\u0000\u0000\u0295"+ + "\u0296\u0001\u0000\u0000\u0000\u0296\u029a\u0001\u0000\u0000\u0000\u0297"+ + "\u0295\u0001\u0000\u0000\u0000\u0298\u0299\u0005?\u0000\u0000\u0299\u029b"+ + "\u0003\u008aE\u0000\u029a\u0298\u0001\u0000\u0000\u0000\u029a\u029b\u0001"+ + "\u0000\u0000\u0000\u029b\u029d\u0001\u0000\u0000\u0000\u029c\u028f\u0001"+ + "\u0000\u0000\u0000\u029c\u0290\u0001\u0000\u0000\u0000\u029c\u029d\u0001"+ + "\u0000\u0000\u0000\u029d\u029e\u0001\u0000\u0000\u0000\u029e\u029f\u0005"+ + "e\u0000\u0000\u029f\u0087\u0001\u0000\u0000\u0000\u02a0\u02a1\u0003<\u001e"+ + "\u0000\u02a1\u0089\u0001\u0000\u0000\u0000\u02a2\u02a3\u0005]\u0000\u0000"+ + "\u02a3\u02a8\u0003\u008cF\u0000\u02a4\u02a5\u0005?\u0000\u0000\u02a5\u02a7"+ + "\u0003\u008cF\u0000\u02a6\u02a4\u0001\u0000\u0000\u0000\u02a7\u02aa\u0001"+ + "\u0000\u0000\u0000\u02a8\u02a6\u0001\u0000\u0000\u0000\u02a8\u02a9\u0001"+ + "\u0000\u0000\u0000\u02a9\u02ab\u0001\u0000\u0000\u0000\u02aa\u02a8\u0001"+ + "\u0000\u0000\u0000\u02ab\u02ac\u0005^\u0000\u0000\u02ac\u008b\u0001\u0000"+ + "\u0000\u0000\u02ad\u02ae\u0003\u0098L\u0000\u02ae\u02af\u0005>\u0000\u0000"+ + "\u02af\u02b0\u0003\u008eG\u0000\u02b0\u008d\u0001\u0000\u0000\u0000\u02b1"+ + "\u02dc\u0005I\u0000\u0000\u02b2\u02b3\u0003\u0096K\u0000\u02b3\u02b4\u0005"+ + "f\u0000\u0000\u02b4\u02dc\u0001\u0000\u0000\u0000\u02b5\u02dc\u0003\u0094"+ + "J\u0000\u02b6\u02dc\u0003\u0096K\u0000\u02b7\u02dc\u0003\u0090H\u0000"+ + "\u02b8\u02dc\u00038\u001c\u0000\u02b9\u02dc\u0003\u0098L\u0000\u02ba\u02bb"+ + "\u0005b\u0000\u0000\u02bb\u02c0\u0003\u0092I\u0000\u02bc\u02bd\u0005?"+ + "\u0000\u0000\u02bd\u02bf\u0003\u0092I\u0000\u02be\u02bc\u0001\u0000\u0000"+ + "\u0000\u02bf\u02c2\u0001\u0000\u0000\u0000\u02c0\u02be\u0001\u0000\u0000"+ + "\u0000\u02c0\u02c1\u0001\u0000\u0000\u0000\u02c1\u02c3\u0001\u0000\u0000"+ + "\u0000\u02c2\u02c0\u0001\u0000\u0000\u0000\u02c3\u02c4\u0005c\u0000\u0000"+ + "\u02c4\u02dc\u0001\u0000\u0000\u0000\u02c5\u02c6\u0005b\u0000\u0000\u02c6"+ + "\u02cb\u0003\u0090H\u0000\u02c7\u02c8\u0005?\u0000\u0000\u02c8\u02ca\u0003"+ + "\u0090H\u0000\u02c9\u02c7\u0001\u0000\u0000\u0000\u02ca\u02cd\u0001\u0000"+ + "\u0000\u0000\u02cb\u02c9\u0001\u0000\u0000\u0000\u02cb\u02cc\u0001\u0000"+ + "\u0000\u0000\u02cc\u02ce\u0001\u0000\u0000\u0000\u02cd\u02cb\u0001\u0000"+ + "\u0000\u0000\u02ce\u02cf\u0005c\u0000\u0000\u02cf\u02dc\u0001\u0000\u0000"+ + "\u0000\u02d0\u02d1\u0005b\u0000\u0000\u02d1\u02d6\u0003\u0098L\u0000\u02d2"+ + "\u02d3\u0005?\u0000\u0000\u02d3\u02d5\u0003\u0098L\u0000\u02d4\u02d2\u0001"+ + "\u0000\u0000\u0000\u02d5\u02d8\u0001\u0000\u0000\u0000\u02d6\u02d4\u0001"+ + "\u0000\u0000\u0000\u02d6\u02d7\u0001\u0000\u0000\u0000\u02d7\u02d9\u0001"+ + "\u0000\u0000\u0000\u02d8\u02d6\u0001\u0000\u0000\u0000\u02d9\u02da\u0005"+ + "c\u0000\u0000\u02da\u02dc\u0001\u0000\u0000\u0000\u02db\u02b1\u0001\u0000"+ + "\u0000\u0000\u02db\u02b2\u0001\u0000\u0000\u0000\u02db\u02b5\u0001\u0000"+ + "\u0000\u0000\u02db\u02b6\u0001\u0000\u0000\u0000\u02db\u02b7\u0001\u0000"+ + "\u0000\u0000\u02db\u02b8\u0001\u0000\u0000\u0000\u02db\u02b9\u0001\u0000"+ + "\u0000\u0000\u02db\u02ba\u0001\u0000\u0000\u0000\u02db\u02c5\u0001\u0000"+ + "\u0000\u0000\u02db\u02d0\u0001\u0000\u0000\u0000\u02dc\u008f\u0001\u0000"+ + "\u0000\u0000\u02dd\u02de\u0007\u0006\u0000\u0000\u02de\u0091\u0001\u0000"+ + "\u0000\u0000\u02df\u02e2\u0003\u0094J\u0000\u02e0\u02e2\u0003\u0096K\u0000"+ + "\u02e1\u02df\u0001\u0000\u0000\u0000\u02e1\u02e0\u0001\u0000\u0000\u0000"+ + "\u02e2\u0093\u0001\u0000\u0000\u0000\u02e3\u02e5\u0007\u0004\u0000\u0000"+ + "\u02e4\u02e3\u0001\u0000\u0000\u0000\u02e4\u02e5\u0001\u0000\u0000\u0000"+ + "\u02e5\u02e6\u0001\u0000\u0000\u0000\u02e6\u02e7\u00057\u0000\u0000\u02e7"+ + "\u0095\u0001\u0000\u0000\u0000\u02e8\u02ea\u0007\u0004\u0000\u0000\u02e9"+ + "\u02e8\u0001\u0000\u0000\u0000\u02e9\u02ea\u0001\u0000\u0000\u0000\u02ea"+ + "\u02eb\u0001\u0000\u0000\u0000\u02eb\u02ec\u00056\u0000\u0000\u02ec\u0097"+ + "\u0001\u0000\u0000\u0000\u02ed\u02ee\u00055\u0000\u0000\u02ee\u0099\u0001"+ + "\u0000\u0000\u0000\u02ef\u02f0\u0007\u0007\u0000\u0000\u02f0\u009b\u0001"+ + "\u0000\u0000\u0000\u02f1\u02f2\u0007\b\u0000\u0000\u02f2\u02f3\u0005s"+ + "\u0000\u0000\u02f3\u02f4\u0003\u009eO\u0000\u02f4\u02f5\u0003\u00a0P\u0000"+ + "\u02f5\u009d\u0001\u0000\u0000\u0000\u02f6\u02f7\u0003\u001c\u000e\u0000"+ + "\u02f7\u009f\u0001\u0000\u0000\u0000\u02f8\u02f9\u0005K\u0000\u0000\u02f9"+ + "\u02fe\u0003\u00a2Q\u0000\u02fa\u02fb\u0005?\u0000\u0000\u02fb\u02fd\u0003"+ + "\u00a2Q\u0000\u02fc\u02fa\u0001\u0000\u0000\u0000\u02fd\u0300\u0001\u0000"+ + "\u0000\u0000\u02fe\u02fc\u0001\u0000\u0000\u0000\u02fe\u02ff\u0001\u0000"+ + "\u0000\u0000\u02ff\u00a1\u0001\u0000\u0000\u0000\u0300\u02fe\u0001\u0000"+ + "\u0000\u0000\u0301\u0302\u0003\u0080@\u0000\u0302\u00a3\u0001\u0000\u0000"+ + "\u0000G\u00af\u00b8\u00d7\u00e6\u00ec\u00f5\u00fb\u0108\u010c\u0111\u0117"+ + "\u0119\u0127\u012f\u0133\u013a\u0140\u0147\u014f\u0157\u015f\u0163\u0167"+ + "\u016c\u0177\u017c\u0180\u018e\u0199\u01a7\u01bc\u01c4\u01c7\u01cc\u01d9"+ + "\u01df\u01e6\u01f1\u01ff\u0208\u0212\u021a\u021f\u0228\u0231\u0239\u023e"+ + "\u0246\u0248\u024d\u0254\u0259\u025e\u0268\u026e\u0276\u0278\u0283\u028a"+ + "\u0295\u029a\u029c\u02a8\u02c0\u02cb\u02d6\u02db\u02e1\u02e4\u02e9\u02fe"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java index 5523d6eec643f..d53a392650f83 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java @@ -3721,8 +3721,6 @@ public void testResolveRerankScoreField() { } public void testResolveCompletionInferenceId() { - assumeTrue("Requires COMPLETION command", EsqlCapabilities.Cap.COMPLETION.isEnabled()); - LogicalPlan plan = analyze(""" FROM books METADATA _score | COMPLETION CONCAT("Translate the following text in French\\n", description) WITH `completion-inference-id` @@ -3732,8 +3730,6 @@ public void testResolveCompletionInferenceId() { } public void testResolveCompletionInferenceIdInvalidTaskType() { - assumeTrue("Requires COMPLETION command", EsqlCapabilities.Cap.COMPLETION.isEnabled()); - assertError( """ FROM books METADATA _score @@ -3747,8 +3743,6 @@ public void testResolveCompletionInferenceIdInvalidTaskType() { } public void testResolveCompletionInferenceMissingInferenceId() { - assumeTrue("Requires COMPLETION command", EsqlCapabilities.Cap.COMPLETION.isEnabled()); - assertError(""" FROM books METADATA _score | COMPLETION CONCAT("Translate the following text in French\\n", description) WITH `unknown-inference-id` @@ -3756,8 +3750,6 @@ public void testResolveCompletionInferenceMissingInferenceId() { } public void testResolveCompletionInferenceIdResolutionError() { - assumeTrue("Requires COMPLETION command", EsqlCapabilities.Cap.COMPLETION.isEnabled()); - assertError(""" FROM books METADATA _score | COMPLETION CONCAT("Translate the following text in French\\n", description) WITH `error-inference-id` @@ -3765,8 +3757,6 @@ public void testResolveCompletionInferenceIdResolutionError() { } public void testResolveCompletionTargetField() { - assumeTrue("Requires COMPLETION command", EsqlCapabilities.Cap.COMPLETION.isEnabled()); - LogicalPlan plan = analyze(""" FROM books METADATA _score | COMPLETION CONCAT("Translate the following text in French\\n", description) WITH `completion-inference-id` AS translation @@ -3777,8 +3767,6 @@ public void testResolveCompletionTargetField() { } public void testResolveCompletionDefaultTargetField() { - assumeTrue("Requires COMPLETION command", EsqlCapabilities.Cap.COMPLETION.isEnabled()); - LogicalPlan plan = analyze(""" FROM books METADATA _score | COMPLETION CONCAT("Translate the following text in French\\n", description) WITH `completion-inference-id` @@ -3789,8 +3777,6 @@ public void testResolveCompletionDefaultTargetField() { } public void testResolveCompletionPrompt() { - assumeTrue("Requires COMPLETION command", EsqlCapabilities.Cap.COMPLETION.isEnabled()); - LogicalPlan plan = analyze(""" FROM books METADATA _score | COMPLETION CONCAT("Translate the following text in French\\n", description) WITH `completion-inference-id` @@ -3806,8 +3792,6 @@ public void testResolveCompletionPrompt() { } public void testResolveCompletionPromptInvalidType() { - assumeTrue("Requires COMPLETION command", EsqlCapabilities.Cap.COMPLETION.isEnabled()); - assertError(""" FROM books METADATA _score | COMPLETION LENGTH(description) WITH `completion-inference-id` @@ -3815,8 +3799,6 @@ public void testResolveCompletionPromptInvalidType() { } public void testResolveCompletionOutputField() { - assumeTrue("Requires COMPLETION command", EsqlCapabilities.Cap.COMPLETION.isEnabled()); - LogicalPlan plan = analyze(""" FROM books METADATA _score | COMPLETION CONCAT("Translate the following text in French\\n", description) WITH `completion-inference-id` AS description diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/GrammarInDevelopmentParsingTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/GrammarInDevelopmentParsingTests.java index cc95fdcf17eb8..f31d9ee58c268 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/GrammarInDevelopmentParsingTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/GrammarInDevelopmentParsingTests.java @@ -34,10 +34,6 @@ public void testDevelopmentRerank() { parse("row a = 1 | rerank \"foo\" on title with reranker", "rerank"); } - public void testDevelopmentCompletion() { - parse("row a = 1 | completion concat(\"test\", \"a\") with inferenceId as fieldName", "completion"); - } - void parse(String query, String errorMessage) { ParsingException pe = expectThrows(ParsingException.class, () -> parser().createStatement(query)); assertThat(pe.getMessage(), containsString("mismatched input '" + errorMessage + "'")); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/StatementParserTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/StatementParserTests.java index 2b96ee5d3c381..3d50a109eded4 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/StatementParserTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/StatementParserTests.java @@ -3432,8 +3432,6 @@ public void testInvalidRerank() { } public void testCompletionUsingFieldAsPrompt() { - assumeTrue("COMPLETION requires corresponding capability", EsqlCapabilities.Cap.COMPLETION.isEnabled()); - var plan = as(processingCommand("COMPLETION prompt_field WITH inferenceID AS targetField"), Completion.class); assertThat(plan.prompt(), equalTo(attribute("prompt_field"))); @@ -3442,8 +3440,6 @@ public void testCompletionUsingFieldAsPrompt() { } public void testCompletionUsingFunctionAsPrompt() { - assumeTrue("COMPLETION requires corresponding capability", EsqlCapabilities.Cap.COMPLETION.isEnabled()); - var plan = as(processingCommand("COMPLETION CONCAT(fieldA, fieldB) WITH inferenceID AS targetField"), Completion.class); assertThat(plan.prompt(), equalTo(function("CONCAT", List.of(attribute("fieldA"), attribute("fieldB"))))); @@ -3452,8 +3448,6 @@ public void testCompletionUsingFunctionAsPrompt() { } public void testCompletionDefaultFieldName() { - assumeTrue("COMPLETION requires corresponding capability", EsqlCapabilities.Cap.COMPLETION.isEnabled()); - var plan = as(processingCommand("COMPLETION prompt_field WITH inferenceID"), Completion.class); assertThat(plan.prompt(), equalTo(attribute("prompt_field"))); @@ -3462,8 +3456,6 @@ public void testCompletionDefaultFieldName() { } public void testCompletionWithPositionalParameters() { - assumeTrue("COMPLETION requires corresponding capability", EsqlCapabilities.Cap.COMPLETION.isEnabled()); - var queryParams = new QueryParams(List.of(paramAsConstant(null, "inferenceId"))); var plan = as(parser.createStatement("row a = 1 | COMPLETION prompt_field WITH ?", queryParams), Completion.class); @@ -3473,8 +3465,6 @@ public void testCompletionWithPositionalParameters() { } public void testCompletionWithNamedParameters() { - assumeTrue("COMPLETION requires corresponding capability", EsqlCapabilities.Cap.COMPLETION.isEnabled()); - var queryParams = new QueryParams(List.of(paramAsConstant("inferenceId", "myInference"))); var plan = as(parser.createStatement("row a = 1 | COMPLETION prompt_field WITH ?inferenceId", queryParams), Completion.class); @@ -3484,8 +3474,6 @@ public void testCompletionWithNamedParameters() { } public void testInvalidCompletion() { - assumeTrue("COMPLETION requires corresponding capability", EsqlCapabilities.Cap.COMPLETION.isEnabled()); - expectError("FROM foo* | COMPLETION WITH inferenceId", "line 1:24: extraneous input 'WITH' expecting {"); expectError("FROM foo* | COMPLETION prompt WITH", "line 1:35: mismatched input '' expecting {"); diff --git a/x-pack/plugin/identity-provider/qa/idp-rest-tests/src/javaRestTest/java/org/elasticsearch/xpack/idp/IdentityProviderAuthenticationIT.java b/x-pack/plugin/identity-provider/qa/idp-rest-tests/src/javaRestTest/java/org/elasticsearch/xpack/idp/IdentityProviderAuthenticationIT.java index 7f3b39fb75d50..93771519aedc8 100644 --- a/x-pack/plugin/identity-provider/qa/idp-rest-tests/src/javaRestTest/java/org/elasticsearch/xpack/idp/IdentityProviderAuthenticationIT.java +++ b/x-pack/plugin/identity-provider/qa/idp-rest-tests/src/javaRestTest/java/org/elasticsearch/xpack/idp/IdentityProviderAuthenticationIT.java @@ -49,6 +49,7 @@ import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; public class IdentityProviderAuthenticationIT extends IdpRestTestCase { @@ -89,6 +90,52 @@ public void testRegistrationAndIdpInitiatedSso() throws Exception { authenticateWithSamlResponse(samlResponse, null); } + public void testUpdateExistingServiceProvider() throws Exception { + final Map request1 = Map.ofEntries( + Map.entry("name", "Test SP [v1]"), + Map.entry("acs", SP_ACS), + Map.entry("privileges", Map.ofEntries(Map.entry("resource", SP_ENTITY_ID), Map.entry("roles", List.of("sso:(\\w+)")))), + Map.entry( + "attributes", + Map.ofEntries( + Map.entry("principal", "https://idp.test.es.elasticsearch.org/attribute/principal"), + Map.entry("name", "https://idp.test.es.elasticsearch.org/attribute/name"), + Map.entry("email", "https://idp.test.es.elasticsearch.org/attribute/email"), + Map.entry("roles", "https://idp.test.es.elasticsearch.org/attribute/roles") + ) + ) + ); + final SamlServiceProviderIndex.DocumentVersion docVersion1 = createServiceProvider(SP_ENTITY_ID, request1); + checkIndexDoc(docVersion1); + ensureGreen(SamlServiceProviderIndex.INDEX_NAME); + + final String samlResponse1 = generateSamlResponse(SP_ENTITY_ID, SP_ACS, null); + assertThat(samlResponse1, containsString("https://idp.test.es.elasticsearch.org/attribute/principal")); + assertThat(samlResponse1, not(containsString("https://idp.test.es.elasticsearch.org/attribute/username"))); + + final Map request = Map.ofEntries( + Map.entry("name", "Test SP [v2]"), + Map.entry("acs", SP_ACS), + Map.entry("privileges", Map.ofEntries(Map.entry("resource", SP_ENTITY_ID), Map.entry("roles", List.of("sso:(\\w+)")))), + Map.entry( + "attributes", + Map.ofEntries( + Map.entry("principal", "https://idp.test.es.elasticsearch.org/attribute/username"), + Map.entry("name", "https://idp.test.es.elasticsearch.org/attribute/name"), + Map.entry("email", "https://idp.test.es.elasticsearch.org/attribute/email"), + Map.entry("roles", "https://idp.test.es.elasticsearch.org/attribute/roles") + ) + ) + ); + final SamlServiceProviderIndex.DocumentVersion docVersion2 = createServiceProvider(SP_ENTITY_ID, request); + checkIndexDoc(docVersion2); + ensureGreen(SamlServiceProviderIndex.INDEX_NAME); + + final String samlResponse2 = generateSamlResponse(SP_ENTITY_ID, SP_ACS, null); + assertThat(samlResponse2, containsString("https://idp.test.es.elasticsearch.org/attribute/username")); + assertThat(samlResponse2, not(containsString("https://idp.test.es.elasticsearch.org/attribute/principal"))); + } + public void testCustomAttributesInIdpInitiatedSso() throws Exception { final Map request = Map.ofEntries( Map.entry("name", "Test SP With Custom Attributes"), @@ -100,7 +147,8 @@ public void testCustomAttributesInIdpInitiatedSso() throws Exception { Map.entry("principal", "https://idp.test.es.elasticsearch.org/attribute/principal"), Map.entry("name", "https://idp.test.es.elasticsearch.org/attribute/name"), Map.entry("email", "https://idp.test.es.elasticsearch.org/attribute/email"), - Map.entry("roles", "https://idp.test.es.elasticsearch.org/attribute/roles") + Map.entry("roles", "https://idp.test.es.elasticsearch.org/attribute/roles"), + Map.entry("extensions", List.of("department", "region")) ) ) ); diff --git a/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/IdentityProviderPlugin.java b/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/IdentityProviderPlugin.java index 8f006fabc2d44..80b1bb8c01229 100644 --- a/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/IdentityProviderPlugin.java +++ b/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/IdentityProviderPlugin.java @@ -107,6 +107,8 @@ public Collection createComponents(PluginServices services) { index, serviceProviderFactory ); + services.clusterService().addListener(registeredServiceProviderResolver); + final WildcardServiceProviderResolver wildcardServiceProviderResolver = WildcardServiceProviderResolver.create( services.environment(), services.resourceWatcherService(), diff --git a/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/authn/SuccessfulAuthenticationResponseMessageBuilder.java b/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/authn/SuccessfulAuthenticationResponseMessageBuilder.java index 301ada3561299..ad0fecce623d1 100644 --- a/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/authn/SuccessfulAuthenticationResponseMessageBuilder.java +++ b/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/authn/SuccessfulAuthenticationResponseMessageBuilder.java @@ -48,6 +48,7 @@ import java.util.Map; import java.util.Set; +import static org.elasticsearch.common.Strings.collectionToCommaDelimitedString; import static org.opensaml.saml.saml2.core.NameIDType.TRANSIENT; /** @@ -214,28 +215,42 @@ private AttributeStatement buildAttributes( final SamlServiceProvider serviceProvider = user.getServiceProvider(); final AttributeStatement statement = samlFactory.object(AttributeStatement.class, AttributeStatement.DEFAULT_ELEMENT_NAME); final List attributes = new ArrayList<>(); - final Attribute roles = buildAttribute(serviceProvider.getAttributeNames().roles, "roles", user.getRoles()); + final SamlServiceProvider.AttributeNames attributeNames = serviceProvider.getAttributeNames(); + final Attribute roles = buildAttribute(attributeNames.roles, "roles", user.getRoles()); if (roles != null) { attributes.add(roles); } - final Attribute principal = buildAttribute(serviceProvider.getAttributeNames().principal, "principal", user.getPrincipal()); + final Attribute principal = buildAttribute(attributeNames.principal, "principal", user.getPrincipal()); if (principal != null) { attributes.add(principal); } - final Attribute email = buildAttribute(serviceProvider.getAttributeNames().email, "email", user.getEmail()); + final Attribute email = buildAttribute(attributeNames.email, "email", user.getEmail()); if (email != null) { attributes.add(email); } - final Attribute name = buildAttribute(serviceProvider.getAttributeNames().name, "name", user.getName()); + final Attribute name = buildAttribute(attributeNames.name, "name", user.getName()); if (name != null) { attributes.add(name); } // Add custom attributes if provided if (customAttributes != null && customAttributes.getAttributes().isEmpty() == false) { for (Map.Entry> entry : customAttributes.getAttributes().entrySet()) { - Attribute attribute = buildAttribute(entry.getKey(), null, entry.getValue()); - if (attribute != null) { - attributes.add(attribute); + final String attributeName = entry.getKey(); + if (attributeNames.isAllowedExtension(attributeName)) { + Attribute attribute = buildAttribute(attributeName, null, entry.getValue()); + if (attribute != null) { + attributes.add(attribute); + } + } else { + throw new IllegalArgumentException( + "the custom attribute [" + + attributeName + + "] is not permitted for the Service Provider [" + + serviceProvider.getName() + + "], allowed attribute names are [" + + collectionToCommaDelimitedString(attributeNames.allowedExtensions) + + "]" + ); } } } diff --git a/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProvider.java b/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProvider.java index 6d704ed759532..58d2c3dd73dae 100644 --- a/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProvider.java +++ b/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProvider.java @@ -36,12 +36,18 @@ class AttributeNames { public final String name; public final String email; public final String roles; + public final Set allowedExtensions; - public AttributeNames(String principal, String name, String email, String roles) { + public AttributeNames(String principal, String name, String email, String roles, Set allowedExtensions) { this.principal = principal; this.name = name; this.email = email; this.roles = roles; + this.allowedExtensions = allowedExtensions == null ? Set.of() : Set.copyOf(allowedExtensions); + } + + public boolean isAllowedExtension(String attributeName) { + return this.allowedExtensions.contains(attributeName); } } diff --git a/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderDocument.java b/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderDocument.java index ba2c971f0e0d9..40e0ca20fcf58 100644 --- a/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderDocument.java +++ b/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderDocument.java @@ -42,6 +42,8 @@ import java.util.TreeSet; import java.util.function.BiConsumer; +import static org.elasticsearch.TransportVersions.IDP_CUSTOM_SAML_ATTRIBUTES_ALLOW_LIST; + /** * This class models the storage of a {@link SamlServiceProvider} as an Elasticsearch document. */ @@ -87,6 +89,12 @@ public static class AttributeNames { @Nullable public String roles; + /** + * Extensions are attributes that are provided at runtime (by the trusted client that initiates + * the SAML SSO. They are sourced from the rest request rather than the user object itself. + */ + public Set extensions = Set.of(); + public void setPrincipal(String principal) { this.principal = principal; } @@ -103,6 +111,10 @@ public void setRoles(String roles) { this.roles = roles; } + public void setExtensions(Collection names) { + this.extensions = names == null ? Set.of() : Set.copyOf(names); + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -111,7 +123,8 @@ public boolean equals(Object o) { return Objects.equals(principal, that.principal) && Objects.equals(email, that.email) && Objects.equals(name, that.name) - && Objects.equals(roles, that.roles); + && Objects.equals(roles, that.roles) + && Objects.equals(extensions, that.extensions); } @Override @@ -263,6 +276,10 @@ public SamlServiceProviderDocument(StreamInput in) throws IOException { attributeNames.name = in.readOptionalString(); attributeNames.roles = in.readOptionalString(); + if (in.getTransportVersion().onOrAfter(IDP_CUSTOM_SAML_ATTRIBUTES_ALLOW_LIST)) { + attributeNames.extensions = in.readCollectionAsImmutableSet(StreamInput::readString); + } + certificates.serviceProviderSigning = in.readStringCollectionAsList(); certificates.identityProviderSigning = in.readStringCollectionAsList(); certificates.identityProviderMetadataSigning = in.readStringCollectionAsList(); @@ -288,6 +305,10 @@ public void writeTo(StreamOutput out) throws IOException { out.writeOptionalString(attributeNames.name); out.writeOptionalString(attributeNames.roles); + if (out.getTransportVersion().onOrAfter(IDP_CUSTOM_SAML_ATTRIBUTES_ALLOW_LIST)) { + out.writeStringCollection(attributeNames.extensions); + } + out.writeStringCollection(certificates.serviceProviderSigning); out.writeStringCollection(certificates.identityProviderSigning); out.writeStringCollection(certificates.identityProviderMetadataSigning); @@ -426,6 +447,7 @@ public int hashCode() { ATTRIBUTES_PARSER.declareStringOrNull(AttributeNames::setEmail, Fields.Attributes.EMAIL); ATTRIBUTES_PARSER.declareStringOrNull(AttributeNames::setName, Fields.Attributes.NAME); ATTRIBUTES_PARSER.declareStringOrNull(AttributeNames::setRoles, Fields.Attributes.ROLES); + ATTRIBUTES_PARSER.declareStringArray(AttributeNames::setExtensions, Fields.Attributes.EXTENSIONS); DOC_PARSER.declareObject(NULL_CONSUMER, (p, doc) -> CERTIFICATES_PARSER.parse(p, doc.certificates, null), Fields.CERTIFICATES); CERTIFICATES_PARSER.declareStringArray(Certificates::setServiceProviderSigning, Fields.Certificates.SP_SIGNING); @@ -516,6 +538,9 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws builder.field(Fields.Attributes.EMAIL.getPreferredName(), attributeNames.email); builder.field(Fields.Attributes.NAME.getPreferredName(), attributeNames.name); builder.field(Fields.Attributes.ROLES.getPreferredName(), attributeNames.roles); + if (attributeNames.extensions != null && attributeNames.extensions.isEmpty() == false) { + builder.field(Fields.Attributes.EXTENSIONS.getPreferredName(), attributeNames.extensions); + } builder.endObject(); builder.startObject(Fields.CERTIFICATES.getPreferredName()); @@ -553,6 +578,7 @@ interface Attributes { ParseField EMAIL = new ParseField("email"); ParseField NAME = new ParseField("name"); ParseField ROLES = new ParseField("roles"); + ParseField EXTENSIONS = new ParseField("extensions"); } interface Certificates { diff --git a/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderFactory.java b/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderFactory.java index 25a3ae59f17fd..815c1544ac1e3 100644 --- a/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderFactory.java +++ b/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderFactory.java @@ -38,7 +38,8 @@ SamlServiceProvider buildServiceProvider(SamlServiceProviderDocument document) { document.attributeNames.principal, document.attributeNames.name, document.attributeNames.email, - document.attributeNames.roles + document.attributeNames.roles, + document.attributeNames.extensions ); final Set credentials = document.certificates.getServiceProviderX509SigningCertificates() .stream() diff --git a/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderIndex.java b/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderIndex.java index 5b2d81f9e0e5e..ccb64dc6c55ad 100644 --- a/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderIndex.java +++ b/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderIndex.java @@ -26,6 +26,7 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateListener; import org.elasticsearch.cluster.metadata.IndexAbstraction; +import org.elasticsearch.cluster.metadata.ProjectMetadata; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Strings; import org.elasticsearch.common.ValidationException; @@ -33,6 +34,7 @@ import org.elasticsearch.common.util.CachedSupplier; import org.elasticsearch.common.xcontent.LoggingDeprecationHandler; import org.elasticsearch.common.xcontent.XContentHelper; +import org.elasticsearch.index.Index; import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.index.get.GetResult; import org.elasticsearch.index.query.QueryBuilder; @@ -51,6 +53,7 @@ import java.util.Arrays; import java.util.Objects; import java.util.Set; +import java.util.SortedMap; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -78,7 +81,26 @@ public class SamlServiceProviderIndex implements Closeable { static final String TEMPLATE_VERSION_STRING_DEPRECATED = "idp.template.version_deprecated"; static final String FINAL_TEMPLATE_VERSION_STRING_DEPRECATED = "8.14.0"; - static final int CURRENT_TEMPLATE_VERSION = 1; + /** + * The object in the index mapping metadata that contains a version field + */ + private static final String INDEX_META_FIELD = "_meta"; + /** + * The field in the {@link #INDEX_META_FIELD} metadata that contains the version number + */ + private static final String TEMPLATE_VERSION_META_FIELD = "idp-template-version"; + + /** + * The first version of this template (since it was moved to use {@link org.elasticsearch.xpack.core.template.IndexTemplateRegistry} + */ + private static final int VERSION_ORIGINAL = 1; + /** + * The version that added the {@code attributes.extensions} field to the SAML SP document + */ + private static final int VERSION_EXTENSION_ATTRIBUTES = 2; + static final int CURRENT_TEMPLATE_VERSION = VERSION_EXTENSION_ATTRIBUTES; + + private volatile boolean indexUpToDate = false; public static final class DocumentVersion { public final String id; @@ -152,6 +174,21 @@ private void checkForAliasStateChange(ClusterState state) { } } + Index getIndex(ClusterState state) { + final ProjectMetadata project = state.getMetadata().getProject(); + final SortedMap indicesLookup = project.getIndicesLookup(); + + IndexAbstraction indexAbstraction = indicesLookup.get(ALIAS_NAME); + if (indexAbstraction == null) { + indexAbstraction = indicesLookup.get(INDEX_NAME); + } + if (indexAbstraction == null) { + return null; + } else { + return indexAbstraction.getWriteIndex(); + } + } + @Override public void close() { logger.debug("Closing ... removing cluster state listener"); @@ -255,7 +292,12 @@ public void refresh(ActionListener listener) { private void findDocuments(QueryBuilder query, ActionListener> listener) { logger.trace("Searching [{}] for [{}]", ALIAS_NAME, query); - final SearchRequest request = client.prepareSearch(ALIAS_NAME).setQuery(query).setSize(1000).setFetchSource(true).request(); + final SearchRequest request = client.prepareSearch(ALIAS_NAME) + .setQuery(query) + .setSize(1000) + .setFetchSource(true) + .seqNoAndPrimaryTerm(true) + .request(); client.search(request, ActionListener.wrap(response -> { if (logger.isTraceEnabled()) { logger.trace("Search hits: [{}] [{}]", response.getHits().getTotalHits(), Arrays.toString(response.getHits().getHits())); diff --git a/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderResolver.java b/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderResolver.java index 4e3e76e539a95..621068c0db840 100644 --- a/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderResolver.java +++ b/x-pack/plugin/identity-provider/src/main/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderResolver.java @@ -7,16 +7,22 @@ package org.elasticsearch.xpack.idp.saml.sp; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.elasticsearch.action.ActionListener; +import org.elasticsearch.cluster.ClusterChangedEvent; +import org.elasticsearch.cluster.ClusterStateListener; import org.elasticsearch.common.cache.Cache; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.iterable.Iterables; +import org.elasticsearch.index.Index; import org.elasticsearch.xpack.idp.saml.sp.SamlServiceProviderIndex.DocumentSupplier; import org.elasticsearch.xpack.idp.saml.sp.SamlServiceProviderIndex.DocumentVersion; +import java.util.Objects; import java.util.stream.Collectors; -public class SamlServiceProviderResolver { +public class SamlServiceProviderResolver implements ClusterStateListener { private final Cache cache; private final SamlServiceProviderIndex index; @@ -32,6 +38,8 @@ public SamlServiceProviderResolver( this.serviceProviderFactory = serviceProviderFactory; } + private final Logger logger = LogManager.getLogger(getClass()); + /** * Find a {@link SamlServiceProvider} by entity-id. * @@ -75,6 +83,16 @@ private void populateCacheAndReturn(String entityId, DocumentSupplier doc, Actio listener.onResponse(serviceProvider); } + @Override + public void clusterChanged(ClusterChangedEvent event) { + final Index previousIndex = index.getIndex(event.previousState()); + final Index currentIndex = index.getIndex(event.state()); + if (Objects.equals(previousIndex, currentIndex) == false) { + logger.info("Index has changed [{}] => [{}], clearing cache", previousIndex, currentIndex); + this.cache.invalidateAll(); + } + } + private class CachedServiceProvider { private final String entityId; private final DocumentVersion documentVersion; diff --git a/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/action/TransportSamlInitiateSingleSignOnActionTests.java b/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/action/TransportSamlInitiateSingleSignOnActionTests.java index 3eb9096efce8d..865c77045bbf7 100644 --- a/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/action/TransportSamlInitiateSingleSignOnActionTests.java +++ b/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/action/TransportSamlInitiateSingleSignOnActionTests.java @@ -190,7 +190,8 @@ private TransportSamlInitiateSingleSignOnAction setupTransportAction(boolean wit "https://saml.elasticsearch.org/attributes/principal", "https://saml.elasticsearch.org/attributes/name", "https://saml.elasticsearch.org/attributes/email", - "https://saml.elasticsearch.org/attributes/roles" + "https://saml.elasticsearch.org/attributes/roles", + Set.of() ), null, false, diff --git a/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/saml/authn/SuccessfulAuthenticationResponseMessageBuilderTests.java b/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/saml/authn/SuccessfulAuthenticationResponseMessageBuilderTests.java index 0e58935c07e31..36eef5c54bf50 100644 --- a/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/saml/authn/SuccessfulAuthenticationResponseMessageBuilderTests.java +++ b/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/saml/authn/SuccessfulAuthenticationResponseMessageBuilderTests.java @@ -7,6 +7,7 @@ package org.elasticsearch.xpack.idp.saml.authn; +import org.elasticsearch.core.Nullable; import org.elasticsearch.xpack.idp.saml.idp.SamlIdentityProvider; import org.elasticsearch.xpack.idp.saml.sp.SamlServiceProvider; import org.elasticsearch.xpack.idp.saml.sp.ServiceProviderDefaults; @@ -103,7 +104,46 @@ public void testSignedResponseWithCustomAttributes() throws Exception { assertTrue("Custom attribute 'customAttr2' not found in SAML response", foundCustomAttr2); } - private Response buildResponse(SamlInitiateSingleSignOnAttributes customAttributes) throws Exception { + public void testRejectInvalidCustomAttributes() throws Exception { + final var customAttributes = new SamlInitiateSingleSignOnAttributes( + Map.of("https://idp.example.org/attribute/department", Collections.singletonList("engineering")) + ); + + // Build response with custom attributes + final IllegalArgumentException ex = expectThrows( + IllegalArgumentException.class, + () -> buildResponse( + new SamlServiceProvider.AttributeNames( + "https://idp.example.org/attribute/principal", + null, + null, + null, + Set.of("https://idp.example.org/attribute/avatar") + ), + customAttributes + ) + ); + assertThat(ex.getMessage(), containsString("custom attribute [https://idp.example.org/attribute/department]")); + assertThat(ex.getMessage(), containsString("allowed attribute names are [https://idp.example.org/attribute/avatar]")); + } + + private Response buildResponse(@Nullable SamlInitiateSingleSignOnAttributes customAttributes) throws Exception { + return buildResponse( + new SamlServiceProvider.AttributeNames( + "principal", + null, + null, + null, + customAttributes == null ? Set.of() : customAttributes.getAttributes().keySet() + ), + customAttributes + ); + } + + private Response buildResponse( + final SamlServiceProvider.AttributeNames attributes, + @Nullable SamlInitiateSingleSignOnAttributes customAttributes + ) throws Exception { final Clock clock = Clock.systemUTC(); final SamlServiceProvider sp = mock(SamlServiceProvider.class); @@ -112,7 +152,7 @@ private Response buildResponse(SamlInitiateSingleSignOnAttributes customAttribut when(sp.getEntityId()).thenReturn(baseServiceUrl); when(sp.getAssertionConsumerService()).thenReturn(URI.create(acs).toURL()); when(sp.getAuthnExpiry()).thenReturn(Duration.ofMinutes(10)); - when(sp.getAttributeNames()).thenReturn(new SamlServiceProvider.AttributeNames("principal", null, null, null)); + when(sp.getAttributeNames()).thenReturn(attributes); final UserServiceAuthentication user = mock(UserServiceAuthentication.class); when(user.getPrincipal()).thenReturn(randomAlphaOfLengthBetween(4, 12)); diff --git a/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderResolverTests.java b/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderResolverTests.java index 6b76deb08aad6..cc387703cd453 100644 --- a/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderResolverTests.java +++ b/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/saml/sp/SamlServiceProviderResolverTests.java @@ -9,7 +9,11 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.PlainActionFuture; +import org.elasticsearch.cluster.ClusterChangedEvent; +import org.elasticsearch.cluster.ClusterName; +import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.index.Index; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.idp.saml.idp.SamlIdentityProvider; import org.elasticsearch.xpack.idp.saml.sp.SamlServiceProviderIndex.DocumentVersion; @@ -135,6 +139,37 @@ public void testResolveIgnoresCacheWhenDocumentVersionChanges() throws Exception assertThat(serviceProvider2.getPrivileges().getResource(), equalTo(document2.privileges.resource)); } + public void testCacheIsClearedWhenIndexChanges() throws Exception { + final SamlServiceProviderDocument document1 = SamlServiceProviderTestUtils.randomDocument(1); + final SamlServiceProviderDocument document2 = SamlServiceProviderTestUtils.randomDocument(2); + document2.entityId = document1.entityId; + + final DocumentVersion docVersion = new DocumentVersion(randomAlphaOfLength(12), 1, 1); + + mockDocument(document1.entityId, docVersion, document1); + final SamlServiceProvider serviceProvider1a = resolveServiceProvider(document1.entityId); + final SamlServiceProvider serviceProvider1b = resolveServiceProvider(document1.entityId); + assertThat(serviceProvider1b, sameInstance(serviceProvider1a)); + + final ClusterState oldState = ClusterState.builder(ClusterName.DEFAULT).build(); + final ClusterState newState = ClusterState.builder(ClusterName.DEFAULT).build(); + when(index.getIndex(oldState)).thenReturn(new Index(SamlServiceProviderIndex.INDEX_NAME, randomUUID())); + when(index.getIndex(newState)).thenReturn(new Index(SamlServiceProviderIndex.INDEX_NAME, randomUUID())); + resolver.clusterChanged(new ClusterChangedEvent(getTestName(), newState, oldState)); + + mockDocument(document1.entityId, docVersion, document2); + final SamlServiceProvider serviceProvider2 = resolveServiceProvider(document1.entityId); + + assertThat(serviceProvider2, not(sameInstance(serviceProvider1a))); + assertThat(serviceProvider2.getEntityId(), equalTo(document2.entityId)); + assertThat(serviceProvider2.getAssertionConsumerService().toString(), equalTo(document2.acs)); + assertThat(serviceProvider2.getAttributeNames().principal, equalTo(document2.attributeNames.principal)); + assertThat(serviceProvider2.getAttributeNames().name, equalTo(document2.attributeNames.name)); + assertThat(serviceProvider2.getAttributeNames().email, equalTo(document2.attributeNames.email)); + assertThat(serviceProvider2.getAttributeNames().roles, equalTo(document2.attributeNames.roles)); + assertThat(serviceProvider2.getPrivileges().getResource(), equalTo(document2.privileges.resource)); + } + private SamlServiceProvider resolveServiceProvider(String entityId) { final PlainActionFuture future = new PlainActionFuture<>(); resolver.resolve(entityId, future); diff --git a/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/saml/sp/WildcardServiceProviderResolverTests.java b/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/saml/sp/WildcardServiceProviderResolverTests.java index 832a6e8163aca..3dfee84bbdedf 100644 --- a/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/saml/sp/WildcardServiceProviderResolverTests.java +++ b/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/saml/sp/WildcardServiceProviderResolverTests.java @@ -24,6 +24,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; @@ -82,7 +83,8 @@ public class WildcardServiceProviderResolverTests extends IdpSamlTestCase { "principal": "http://cloud.elastic.co/saml/principal", "name": "http://cloud.elastic.co/saml/name", "email": "http://cloud.elastic.co/saml/email", - "roles": "http://cloud.elastic.co/saml/roles" + "roles": "http://cloud.elastic.co/saml/roles", + "extensions": [ "http://cloud.elastic.co/saml/department", "http://cloud.elastic.co/saml/avatar" ] } } } @@ -154,6 +156,7 @@ public void testResolveServices() throws IOException { assertThat(sp1.getAssertionConsumerService().toString(), equalTo("https://abcdef.service.example.com/saml2/acs")); assertThat(sp1.getName(), equalTo("abcdef at example.com (A)")); assertThat(sp1.getPrivileges().getResource(), equalTo("service1:example:abcdef")); + assertThat(sp1.getAttributeNames().allowedExtensions, empty()); final SamlServiceProvider sp2 = resolver.resolve("https://qwerty.example.com/", "https://qwerty.service.example.com/saml2/acs"); assertThat(sp2, notNullValue()); @@ -161,6 +164,7 @@ public void testResolveServices() throws IOException { assertThat(sp2.getAssertionConsumerService().toString(), equalTo("https://qwerty.service.example.com/saml2/acs")); assertThat(sp2.getName(), equalTo("qwerty at example.com (A)")); assertThat(sp2.getPrivileges().getResource(), equalTo("service1:example:qwerty")); + assertThat(sp2.getAttributeNames().allowedExtensions, empty()); final SamlServiceProvider sp3 = resolver.resolve("https://xyzzy.example.com/", "https://services.example.com/xyzzy/saml2/acs"); assertThat(sp3, notNullValue()); @@ -168,6 +172,7 @@ public void testResolveServices() throws IOException { assertThat(sp3.getAssertionConsumerService().toString(), equalTo("https://services.example.com/xyzzy/saml2/acs")); assertThat(sp3.getName(), equalTo("xyzzy at example.com (B)")); assertThat(sp3.getPrivileges().getResource(), equalTo("service1:example:xyzzy")); + assertThat(sp3.getAttributeNames().allowedExtensions, empty()); final SamlServiceProvider sp4 = resolver.resolve("https://service-12345.example.net/", "https://saml.example.net/12345/acs"); assertThat(sp4, notNullValue()); @@ -175,6 +180,10 @@ public void testResolveServices() throws IOException { assertThat(sp4.getAssertionConsumerService().toString(), equalTo("https://saml.example.net/12345/acs")); assertThat(sp4.getName(), equalTo("12345 at example.net")); assertThat(sp4.getPrivileges().getResource(), equalTo("service2:example:12345")); + assertThat( + sp4.getAttributeNames().allowedExtensions, + containsInAnyOrder("http://cloud.elastic.co/saml/department", "http://cloud.elastic.co/saml/avatar") + ); expectThrows( IllegalArgumentException.class, diff --git a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/ExecuteStepsUpdateTask.java b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/ExecuteStepsUpdateTask.java index 0089d77cef0e6..29b808547b206 100644 --- a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/ExecuteStepsUpdateTask.java +++ b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/ExecuteStepsUpdateTask.java @@ -198,7 +198,9 @@ private ClusterState executeWaitStep(ClusterState state, Step currentStep) { if (stepInfo == null) { return state; } - return IndexLifecycleTransition.addStepInfoToClusterState(index, state, stepInfo); + return ClusterState.builder(state) + .putProjectMetadata(IndexLifecycleTransition.addStepInfoToProject(index, state.metadata().getProject(), stepInfo)) + .build(); } } @@ -286,7 +288,12 @@ private ClusterState moveToErrorStep(final ClusterState state, Step.StepKey curr ), cause ); - return IndexLifecycleTransition.moveClusterStateToErrorStep(index, state, cause, nowSupplier, policyStepsRegistry::getStep); + final var project = state.metadata().getProject(); + return ClusterState.builder(state) + .putProjectMetadata( + IndexLifecycleTransition.moveIndexToErrorStep(index, project, cause, nowSupplier, policyStepsRegistry::getStep) + ) + .build(); } @Override diff --git a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/IndexLifecycleRunner.java b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/IndexLifecycleRunner.java index 66d957c4a1a02..0721f1e1d5574 100644 --- a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/IndexLifecycleRunner.java +++ b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/IndexLifecycleRunner.java @@ -657,13 +657,14 @@ private final class MoveToRetryFailedStepUpdateTask extends IndexLifecycleCluste @Override protected ClusterState doExecute(ClusterState currentState) { - return IndexLifecycleTransition.moveClusterStateToPreviouslyFailedStep( - currentState, + final var updatedProject = IndexLifecycleTransition.moveIndexToPreviouslyFailedStep( + currentState.metadata().getProject(), index.getName(), nowSupplier, stepRegistry, true ); + return ClusterState.builder(currentState).putProjectMetadata(updatedProject).build(); } @Override diff --git a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/IndexLifecycleService.java b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/IndexLifecycleService.java index cd4fb585b33d4..3676bbf57afaf 100644 --- a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/IndexLifecycleService.java +++ b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/IndexLifecycleService.java @@ -170,12 +170,12 @@ public ProjectMetadata moveIndexToStep(ProjectMetadata project, Index index, Ste return IndexLifecycleTransition.moveIndexToStep(index, project, newStepKey, nowSupplier, policyRegistry, true); } - public ClusterState moveClusterStateToPreviouslyFailedStep(ClusterState currentState, String[] indices) { - ClusterState newState = currentState; + public ProjectMetadata moveIndicesToPreviouslyFailedStep(ProjectMetadata currentProject, String[] indices) { + ProjectMetadata newProject = currentProject; for (String index : indices) { - newState = IndexLifecycleTransition.moveClusterStateToPreviouslyFailedStep(newState, index, nowSupplier, policyRegistry, false); + newProject = IndexLifecycleTransition.moveIndexToPreviouslyFailedStep(newProject, index, nowSupplier, policyRegistry, false); } - return newState; + return newProject; } // package private for testing diff --git a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/IndexLifecycleTransition.java b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/IndexLifecycleTransition.java index 305e800677512..ff144f8428d73 100644 --- a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/IndexLifecycleTransition.java +++ b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/IndexLifecycleTransition.java @@ -12,13 +12,11 @@ import org.elasticsearch.ElasticsearchException; import org.elasticsearch.action.support.TransportAction; import org.elasticsearch.client.internal.Client; -import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexMetadata; import org.elasticsearch.cluster.metadata.LifecycleExecutionState; import org.elasticsearch.cluster.metadata.ProjectMetadata; import org.elasticsearch.common.Strings; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.core.Nullable; import org.elasticsearch.index.Index; import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.xcontent.ToXContentObject; @@ -26,7 +24,6 @@ import org.elasticsearch.xpack.core.ilm.IndexLifecycleMetadata; import org.elasticsearch.xpack.core.ilm.InitializePolicyContextStep; import org.elasticsearch.xpack.core.ilm.InitializePolicyException; -import org.elasticsearch.xpack.core.ilm.LifecycleExecutionStateUtils; import org.elasticsearch.xpack.core.ilm.LifecyclePolicy; import org.elasticsearch.xpack.core.ilm.LifecyclePolicyMetadata; import org.elasticsearch.xpack.core.ilm.LifecycleSettings; @@ -113,7 +110,7 @@ public static void validateTransition( * @param nowSupplier The current-time supplier for updating when steps changed * @param stepRegistry The steps registry to check a step-key's existence in the index's current policy * @param forcePhaseDefinitionRefresh Whether to force the phase JSON to be reread or not - * @return The updated cluster state where the index moved to newStepKey + * @return The updated project metadata where the index moved to newStepKey */ static ProjectMetadata moveIndexToStep( Index index, @@ -149,15 +146,15 @@ static ProjectMetadata moveIndexToStep( * Moves the given index into the ERROR step. The ERROR step will have the same phase and * action, but use the {@link ErrorStep#NAME} as the name in the lifecycle execution state. */ - static ClusterState moveClusterStateToErrorStep( + static ProjectMetadata moveIndexToErrorStep( Index index, - ClusterState clusterState, + ProjectMetadata project, Exception cause, LongSupplier nowSupplier, BiFunction stepLookupFunction ) { - IndexMetadata idxMeta = clusterState.getMetadata().getProject().index(index); - IndexLifecycleMetadata ilmMeta = clusterState.metadata().getProject().custom(IndexLifecycleMetadata.TYPE); + IndexMetadata idxMeta = project.index(index); + IndexLifecycleMetadata ilmMeta = project.custom(IndexLifecycleMetadata.TYPE); LifecyclePolicyMetadata policyMetadata = ilmMeta.getPolicyMetadatas().get(idxMeta.getLifecyclePolicyName()); LifecycleExecutionState currentState = idxMeta.getLifecycleExecutionState(); Step.StepKey currentStep; @@ -204,22 +201,21 @@ static ClusterState moveClusterStateToErrorStep( ); } - return LifecycleExecutionStateUtils.newClusterStateWithLifecycleState(clusterState, idxMeta.getIndex(), failedState.build()); + return project.withLifecycleState(idxMeta.getIndex(), failedState.build()); } /** * Move the given index's execution state back to a step that had previously failed. If this is * an automatic retry ({@code isAutomaticRetry}), the retry count is incremented. */ - static ClusterState moveClusterStateToPreviouslyFailedStep( - ClusterState currentState, + static ProjectMetadata moveIndexToPreviouslyFailedStep( + ProjectMetadata project, String index, LongSupplier nowSupplier, PolicyStepsRegistry stepRegistry, boolean isAutomaticRetry ) { - ClusterState newState; - IndexMetadata indexMetadata = currentState.metadata().getProject().index(index); + IndexMetadata indexMetadata = project.index(index); if (indexMetadata == null) { throw new IllegalArgumentException("index [" + index + "] does not exist"); } @@ -229,7 +225,7 @@ static ClusterState moveClusterStateToPreviouslyFailedStep( if (currentStepKey != null && ErrorStep.NAME.equals(currentStepKey.name()) && Strings.isNullOrEmpty(failedStep) == false) { Step.StepKey nextStepKey = new Step.StepKey(currentStepKey.phase(), currentStepKey.action(), failedStep); validateTransition(indexMetadata, currentStepKey, nextStepKey, stepRegistry); - IndexLifecycleMetadata ilmMeta = currentState.metadata().getProject().custom(IndexLifecycleMetadata.TYPE); + IndexLifecycleMetadata ilmMeta = project.custom(IndexLifecycleMetadata.TYPE); LifecyclePolicyMetadata policyMetadata = ilmMeta.getPolicyMetadatas().get(indexMetadata.getLifecyclePolicyName()); @@ -259,17 +255,12 @@ static ClusterState moveClusterStateToPreviouslyFailedStep( // manual retries don't update the retry count retryStepState.setFailedStepRetryCount(lifecycleState.failedStepRetryCount()); } - newState = LifecycleExecutionStateUtils.newClusterStateWithLifecycleState( - currentState, - indexMetadata.getIndex(), - retryStepState.build() - ); + return project.withLifecycleState(indexMetadata.getIndex(), retryStepState.build()); } else { throw new IllegalArgumentException( "cannot retry an action for an index [" + index + "] that has not encountered an error when running a Lifecycle Policy" ); } - return newState; } /** @@ -413,53 +404,31 @@ public static LifecycleExecutionState moveStateToNextActionAndUpdateCachedPhase( } /** - * Conditionally updates cluster state with new step info. The new cluster state is only - * built if the step info has changed, otherwise the same old clusterState is + * Conditionally updates project metadata with new step info. The new project metadata is only + * built if the step info has changed, otherwise the same old project is * returned - * - * @param index the index to modify - * @param clusterState the cluster state to modify - * @param stepInfo the new step info to update - * @return Updated cluster state with stepInfo if changed, otherwise the same cluster state - * if no changes to step info exist */ - static ClusterState addStepInfoToClusterState(Index index, ClusterState clusterState, ToXContentObject stepInfo) { - IndexMetadata indexMetadata = clusterState.getMetadata().getProject().index(index); + static ProjectMetadata addStepInfoToProject(Index index, ProjectMetadata project, ToXContentObject stepInfo) { + IndexMetadata indexMetadata = project.index(index); if (indexMetadata == null) { // This index doesn't exist anymore, we can't do anything - return clusterState; + return project; } LifecycleExecutionState lifecycleState = indexMetadata.getLifecycleExecutionState(); final String stepInfoString = Strings.toString(stepInfo); if (stepInfoString.equals(lifecycleState.stepInfo())) { - return clusterState; + return project; } LifecycleExecutionState.Builder newState = LifecycleExecutionState.builder(lifecycleState); newState.setStepInfo(stepInfoString); - return LifecycleExecutionStateUtils.newClusterStateWithLifecycleState(clusterState, indexMetadata.getIndex(), newState.build()); + return project.withLifecycleState(index, newState.build()); } /** * Remove the ILM policy from the given indices, this removes the lifecycle setting as well as * any lifecycle execution state that may be present in the index metadata */ - public static ClusterState removePolicyForIndexes(final Index[] indices, ClusterState currentState, List failedIndexes) { - final ProjectMetadata currentProject = currentState.metadata().getProject(); - final ProjectMetadata.Builder updatedProject = removePolicyForIndexes(indices, currentProject, failedIndexes); - - if (updatedProject == null) { - return currentState; - } else { - return ClusterState.builder(currentState).putProjectMetadata(updatedProject).build(); - } - } - - /** - * @return If one or more policies were removed, then a new builder representing the changed project state. - * Otherwise {@code null} (if no changes were made) - */ - @Nullable - private static ProjectMetadata.Builder removePolicyForIndexes( + public static ProjectMetadata removePolicyForIndexes( final Index[] indices, ProjectMetadata currentProject, List failedIndexes @@ -481,7 +450,7 @@ private static ProjectMetadata.Builder removePolicyForIndexes( } } - return newProject; + return newProject == null ? currentProject : newProject.build(); } /** diff --git a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/MoveToErrorStepUpdateTask.java b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/MoveToErrorStepUpdateTask.java index c2a39cf887d22..3a96252ab80fd 100644 --- a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/MoveToErrorStepUpdateTask.java +++ b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/MoveToErrorStepUpdateTask.java @@ -57,14 +57,17 @@ public MoveToErrorStepUpdateTask( @Override protected ClusterState doExecute(ClusterState currentState) throws Exception { - IndexMetadata idxMeta = currentState.getMetadata().getProject().index(index); + final var project = currentState.getMetadata().getProject(); + IndexMetadata idxMeta = project.index(index); if (idxMeta == null) { // Index must have been since deleted, ignore it return currentState; } LifecycleExecutionState lifecycleState = idxMeta.getLifecycleExecutionState(); if (policy.equals(idxMeta.getLifecyclePolicyName()) && currentStepKey.equals(Step.getCurrentStepKey(lifecycleState))) { - return IndexLifecycleTransition.moveClusterStateToErrorStep(index, currentState, cause, nowSupplier, stepLookupFunction); + return ClusterState.builder(currentState) + .putProjectMetadata(IndexLifecycleTransition.moveIndexToErrorStep(index, project, cause, nowSupplier, stepLookupFunction)) + .build(); } else { // either the policy has changed or the step is now // not the same as when we submitted the update task. In diff --git a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/SetStepInfoUpdateTask.java b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/SetStepInfoUpdateTask.java index 6a3fb9cec434c..0370169a73e41 100644 --- a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/SetStepInfoUpdateTask.java +++ b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/SetStepInfoUpdateTask.java @@ -46,14 +46,17 @@ ToXContentObject getStepInfo() { @Override protected ClusterState doExecute(ClusterState currentState) throws IOException { - IndexMetadata idxMeta = currentState.getMetadata().getProject().index(index); + final var project = currentState.metadata().getProject(); + IndexMetadata idxMeta = project.index(index); if (idxMeta == null) { // Index must have been since deleted, ignore it return currentState; } LifecycleExecutionState lifecycleState = idxMeta.getLifecycleExecutionState(); if (policy.equals(idxMeta.getLifecyclePolicyName()) && Objects.equals(currentStepKey, Step.getCurrentStepKey(lifecycleState))) { - return IndexLifecycleTransition.addStepInfoToClusterState(index, currentState, stepInfo); + return ClusterState.builder(currentState) + .putProjectMetadata(IndexLifecycleTransition.addStepInfoToProject(index, project, stepInfo)) + .build(); } else { // either the policy has changed or the step is now // not the same as when we submitted the update task. In diff --git a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/action/TransportRemoveIndexLifecyclePolicyAction.java b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/action/TransportRemoveIndexLifecyclePolicyAction.java index 64bc7fb3de021..4b1969820d113 100644 --- a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/action/TransportRemoveIndexLifecyclePolicyAction.java +++ b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/action/TransportRemoveIndexLifecyclePolicyAction.java @@ -70,7 +70,9 @@ protected void masterOperation(Task task, Request request, ClusterState state, A @Override public ClusterState execute(ClusterState currentState) throws Exception { - return IndexLifecycleTransition.removePolicyForIndexes(indices, currentState, failedIndexes); + final var project = currentState.metadata().getProject(); + final var updatedProject = IndexLifecycleTransition.removePolicyForIndexes(indices, project, failedIndexes); + return ClusterState.builder(currentState).putProjectMetadata(updatedProject).build(); } @Override diff --git a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/action/TransportRetryAction.java b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/action/TransportRetryAction.java index a00a50f061b42..c70aa94af8684 100644 --- a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/action/TransportRetryAction.java +++ b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/action/TransportRetryAction.java @@ -74,7 +74,9 @@ protected void masterOperation( submitUnbatchedTask("ilm-re-run", new AckedClusterStateUpdateTask(request, listener) { @Override public ClusterState execute(ClusterState currentState) { - return indexLifecycleService.moveClusterStateToPreviouslyFailedStep(currentState, request.indices()); + final var project = state.metadata().getProject(); + final var updatedProject = indexLifecycleService.moveIndicesToPreviouslyFailedStep(project, request.indices()); + return ClusterState.builder(currentState).putProjectMetadata(updatedProject).build(); } @Override diff --git a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/package-info.java b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/package-info.java index a5d8abeac7e8d..caad8a325c50c 100644 --- a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/package-info.java +++ b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/package-info.java @@ -90,7 +90,7 @@ * successfully (see {@link org.elasticsearch.xpack.ilm.IndexLifecycleRunner#onErrorMaybeRetryFailedStep}). In order to see all retryable * steps see {@link org.elasticsearch.xpack.core.ilm.Step#isRetryable()}. * For steps that are not retryable the failed step can manually be retried using - * {@link org.elasticsearch.xpack.ilm.IndexLifecycleService#moveClusterStateToPreviouslyFailedStep}. + * {@link org.elasticsearch.xpack.ilm.IndexLifecycleService#moveIndicesToPreviouslyFailedStep}. * */ package org.elasticsearch.xpack.ilm; diff --git a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/ilm/IndexLifecycleRunnerTests.java b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/ilm/IndexLifecycleRunnerTests.java index 6fd8f00e45a43..bd39932890c69 100644 --- a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/ilm/IndexLifecycleRunnerTests.java +++ b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/ilm/IndexLifecycleRunnerTests.java @@ -917,40 +917,6 @@ private static LifecyclePolicy createPolicy(String policyName, StepKey safeStep, return newTestLifecyclePolicy(policyName, phases); } - public static void assertClusterStateOnNextStep( - ClusterState oldClusterState, - Index index, - StepKey currentStep, - StepKey nextStep, - ClusterState newClusterState, - long now - ) { - assertNotSame(oldClusterState, newClusterState); - Metadata newMetadata = newClusterState.metadata(); - assertNotSame(oldClusterState.metadata(), newMetadata); - IndexMetadata newIndexMetadata = newMetadata.getProject().getIndexSafe(index); - assertNotSame(oldClusterState.metadata().getProject().index(index), newIndexMetadata); - LifecycleExecutionState newLifecycleState = newClusterState.metadata().getProject().index(index).getLifecycleExecutionState(); - LifecycleExecutionState oldLifecycleState = oldClusterState.metadata().getProject().index(index).getLifecycleExecutionState(); - assertNotSame(oldLifecycleState, newLifecycleState); - assertEquals(nextStep.phase(), newLifecycleState.phase()); - assertEquals(nextStep.action(), newLifecycleState.action()); - assertEquals(nextStep.name(), newLifecycleState.step()); - if (currentStep.phase().equals(nextStep.phase())) { - assertEquals(oldLifecycleState.phaseTime(), newLifecycleState.phaseTime()); - } else { - assertEquals(now, newLifecycleState.phaseTime().longValue()); - } - if (currentStep.action().equals(nextStep.action())) { - assertEquals(oldLifecycleState.actionTime(), newLifecycleState.actionTime()); - } else { - assertEquals(now, newLifecycleState.actionTime().longValue()); - } - assertEquals(now, newLifecycleState.stepTime().longValue()); - assertEquals(null, newLifecycleState.failedStep()); - assertEquals(null, newLifecycleState.stepInfo()); - } - private static IndexMetadata createIndex(String name) { return IndexMetadata.builder(name).settings(randomIndexSettings()).build(); } diff --git a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/ilm/IndexLifecycleTransitionTests.java b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/ilm/IndexLifecycleTransitionTests.java index e9cff0f2802f4..0ed528810dfca 100644 --- a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/ilm/IndexLifecycleTransitionTests.java +++ b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/ilm/IndexLifecycleTransitionTests.java @@ -8,17 +8,14 @@ package org.elasticsearch.xpack.ilm; import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexMetadata; import org.elasticsearch.cluster.metadata.LifecycleExecutionState; import org.elasticsearch.cluster.metadata.Metadata; -import org.elasticsearch.cluster.metadata.ProjectId; import org.elasticsearch.cluster.metadata.ProjectMetadata; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentHelper; -import org.elasticsearch.core.FixForMultiProject; import org.elasticsearch.core.TimeValue; import org.elasticsearch.index.Index; import org.elasticsearch.index.IndexVersion; @@ -288,7 +285,7 @@ public void testValidatedMoveClusterStateToNextStepInvalidNextStep() { for index [my_index] with policy [my_policy] does not exist""")); } - public void testMoveClusterStateToErrorStep() throws IOException { + public void testMoveIndexToErrorStep() throws IOException { String indexName = "my_index"; Step.StepKey currentStep = new Step.StepKey("current_phase", "current_action", "current_step"); Step.StepKey nextStepKey = new Step.StepKey("next_phase", "next_action", "next_step"); @@ -299,32 +296,32 @@ public void testMoveClusterStateToErrorStep() throws IOException { lifecycleState.setPhase(currentStep.phase()); lifecycleState.setAction(currentStep.action()); lifecycleState.setStep(currentStep.name()); - ClusterState clusterState = buildClusterState(indexName, Settings.builder(), lifecycleState.build(), List.of()); - Index index = clusterState.metadata().getProject().index(indexName).getIndex(); + ProjectMetadata project = buildProject(indexName, Settings.builder(), lifecycleState.build(), List.of()); + Index index = project.index(indexName).getIndex(); - ClusterState newClusterState = IndexLifecycleTransition.moveClusterStateToErrorStep( + ProjectMetadata newProject = IndexLifecycleTransition.moveIndexToErrorStep( index, - clusterState, + project, cause, () -> now, (idxMeta, stepKey) -> new MockStep(stepKey, nextStepKey) ); - assertClusterStateOnErrorStep(clusterState, index, currentStep, newClusterState, now, """ + assertProjectOnErrorStep(project, index, currentStep, newProject, now, """ {"type":"exception","reason":"THIS IS AN EXPECTED CAUSE\""""); cause = new IllegalArgumentException("non elasticsearch-exception"); - newClusterState = IndexLifecycleTransition.moveClusterStateToErrorStep( + newProject = IndexLifecycleTransition.moveIndexToErrorStep( index, - clusterState, + project, cause, () -> now, (idxMeta, stepKey) -> new MockStep(stepKey, nextStepKey) ); - assertClusterStateOnErrorStep(clusterState, index, currentStep, newClusterState, now, """ + assertProjectOnErrorStep(project, index, currentStep, newProject, now, """ {"type":"illegal_argument_exception","reason":"non elasticsearch-exception\""""); } - public void testAddStepInfoToClusterState() throws IOException { + public void testAddStepInfoToProject() throws IOException { String indexName = "my_index"; Step.StepKey currentStep = new Step.StepKey("current_phase", "current_action", "current_step"); RandomStepInfo stepInfo = new RandomStepInfo(() -> randomAlphaOfLength(10)); @@ -333,12 +330,12 @@ public void testAddStepInfoToClusterState() throws IOException { lifecycleState.setPhase(currentStep.phase()); lifecycleState.setAction(currentStep.action()); lifecycleState.setStep(currentStep.name()); - ClusterState clusterState = buildClusterState(indexName, Settings.builder(), lifecycleState.build(), List.of()); - Index index = clusterState.metadata().getProject().index(indexName).getIndex(); - ClusterState newClusterState = IndexLifecycleTransition.addStepInfoToClusterState(index, clusterState, stepInfo); - assertClusterStateStepInfo(clusterState, index, currentStep, newClusterState, stepInfo); - ClusterState runAgainClusterState = IndexLifecycleTransition.addStepInfoToClusterState(index, newClusterState, stepInfo); - assertSame(newClusterState, runAgainClusterState); + ProjectMetadata project = buildProject(indexName, Settings.builder(), lifecycleState.build(), List.of()); + Index index = project.index(indexName).getIndex(); + ProjectMetadata newProject = IndexLifecycleTransition.addStepInfoToProject(index, project, stepInfo); + assertProjectStepInfo(project, index, currentStep, newProject, stepInfo); + ProjectMetadata runAgainProject = IndexLifecycleTransition.addStepInfoToProject(index, newProject, stepInfo); + assertSame(newProject, runAgainProject); } public void testRemovePolicyForIndex() { @@ -353,34 +350,29 @@ public void testRemovePolicyForIndex() { lifecycleState.setStep(currentStep.name()); List policyMetadatas = new ArrayList<>(); policyMetadatas.add(new LifecyclePolicyMetadata(oldPolicy, Map.of(), randomNonNegativeLong(), randomNonNegativeLong())); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), policyMetadatas); - Index index = clusterState.metadata().getProject().index(indexName).getIndex(); + ProjectMetadata project = buildProject(indexName, indexSettingsBuilder, lifecycleState.build(), policyMetadatas); + Index index = project.index(indexName).getIndex(); Index[] indices = new Index[] { index }; List failedIndexes = new ArrayList<>(); - ClusterState newClusterState = IndexLifecycleTransition.removePolicyForIndexes(indices, clusterState, failedIndexes); + ProjectMetadata newProject = IndexLifecycleTransition.removePolicyForIndexes(indices, project, failedIndexes); assertTrue(failedIndexes.isEmpty()); - assertIndexNotManagedByILM(newClusterState, index); + assertIndexNotManagedByILM(newProject, index); } public void testRemovePolicyForIndexNoCurrentPolicy() { String indexName = randomAlphaOfLength(10); Settings.Builder indexSettingsBuilder = Settings.builder(); - ClusterState clusterState = buildClusterState( - indexName, - indexSettingsBuilder, - LifecycleExecutionState.builder().build(), - List.of() - ); - Index index = clusterState.metadata().getProject().index(indexName).getIndex(); + ProjectMetadata project = buildProject(indexName, indexSettingsBuilder, LifecycleExecutionState.builder().build(), List.of()); + Index index = project.index(indexName).getIndex(); Index[] indices = new Index[] { index }; List failedIndexes = new ArrayList<>(); - ClusterState newClusterState = IndexLifecycleTransition.removePolicyForIndexes(indices, clusterState, failedIndexes); + ProjectMetadata newProject = IndexLifecycleTransition.removePolicyForIndexes(indices, project, failedIndexes); assertTrue(failedIndexes.isEmpty()); - assertIndexNotManagedByILM(newClusterState, index); + assertIndexNotManagedByILM(newProject, index); } public void testRemovePolicyForIndexIndexDoesntExist() { @@ -395,16 +387,16 @@ public void testRemovePolicyForIndexIndexDoesntExist() { lifecycleState.setStep(currentStep.name()); List policyMetadatas = new ArrayList<>(); policyMetadatas.add(new LifecyclePolicyMetadata(oldPolicy, Map.of(), randomNonNegativeLong(), randomNonNegativeLong())); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), policyMetadatas); + ProjectMetadata project = buildProject(indexName, indexSettingsBuilder, lifecycleState.build(), policyMetadatas); Index index = new Index("doesnt_exist", "im_not_here"); Index[] indices = new Index[] { index }; List failedIndexes = new ArrayList<>(); - ClusterState newClusterState = IndexLifecycleTransition.removePolicyForIndexes(indices, clusterState, failedIndexes); + ProjectMetadata newProject = IndexLifecycleTransition.removePolicyForIndexes(indices, project, failedIndexes); assertEquals(1, failedIndexes.size()); assertEquals("doesnt_exist", failedIndexes.get(0)); - assertSame(clusterState, newClusterState); + assertSame(project, newProject); } public void testRemovePolicyForIndexIndexInUnsafe() { @@ -419,15 +411,15 @@ public void testRemovePolicyForIndexIndexInUnsafe() { lifecycleState.setStep(currentStep.name()); List policyMetadatas = new ArrayList<>(); policyMetadatas.add(new LifecyclePolicyMetadata(oldPolicy, Map.of(), randomNonNegativeLong(), randomNonNegativeLong())); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), policyMetadatas); - Index index = clusterState.metadata().getProject().index(indexName).getIndex(); + ProjectMetadata project = buildProject(indexName, indexSettingsBuilder, lifecycleState.build(), policyMetadatas); + Index index = project.index(indexName).getIndex(); Index[] indices = new Index[] { index }; List failedIndexes = new ArrayList<>(); - ClusterState newClusterState = IndexLifecycleTransition.removePolicyForIndexes(indices, clusterState, failedIndexes); + ProjectMetadata newProject = IndexLifecycleTransition.removePolicyForIndexes(indices, project, failedIndexes); assertTrue(failedIndexes.isEmpty()); - assertIndexNotManagedByILM(newClusterState, index); + assertIndexNotManagedByILM(newProject, index); } public void testRemovePolicyWithIndexingComplete() { @@ -444,15 +436,15 @@ public void testRemovePolicyWithIndexingComplete() { lifecycleState.setStep(currentStep.name()); List policyMetadatas = new ArrayList<>(); policyMetadatas.add(new LifecyclePolicyMetadata(oldPolicy, Map.of(), randomNonNegativeLong(), randomNonNegativeLong())); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), policyMetadatas); - Index index = clusterState.metadata().getProject().index(indexName).getIndex(); + ProjectMetadata project = buildProject(indexName, indexSettingsBuilder, lifecycleState.build(), policyMetadatas); + Index index = project.index(indexName).getIndex(); Index[] indices = new Index[] { index }; List failedIndexes = new ArrayList<>(); - ClusterState newClusterState = IndexLifecycleTransition.removePolicyForIndexes(indices, clusterState, failedIndexes); + ProjectMetadata newProject = IndexLifecycleTransition.removePolicyForIndexes(indices, project, failedIndexes); assertTrue(failedIndexes.isEmpty()); - assertIndexNotManagedByILM(newClusterState, index); + assertIndexNotManagedByILM(newProject, index); } public void testValidateTransitionThrowsExceptionForMissingIndexPolicy() { @@ -737,17 +729,17 @@ public void testMoveClusterStateToFailedStep() { lifecycleState.setStep(errorStepKey.name()); lifecycleState.setStepTime(now); lifecycleState.setFailedStep(failedStepKey.name()); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), List.of(policyMetadata)); - Index index = clusterState.metadata().getProject().index(indexName).getIndex(); - ClusterState nextClusterState = IndexLifecycleTransition.moveClusterStateToPreviouslyFailedStep( - clusterState, + ProjectMetadata project = buildProject(indexName, indexSettingsBuilder, lifecycleState.build(), List.of(policyMetadata)); + Index index = project.index(indexName).getIndex(); + ProjectMetadata newProject = IndexLifecycleTransition.moveIndexToPreviouslyFailedStep( + project, indexName, () -> now, policyRegistry, false ); - IndexLifecycleRunnerTests.assertClusterStateOnNextStep(clusterState, index, errorStepKey, failedStepKey, nextClusterState, now); - LifecycleExecutionState executionState = nextClusterState.metadata().getProject().index(indexName).getLifecycleExecutionState(); + assertClusterStateOnNextStep(project, index, errorStepKey, failedStepKey, newProject, now); + LifecycleExecutionState executionState = newProject.index(indexName).getLifecycleExecutionState(); assertThat("manual move to failed step should not count as a retry", executionState.failedStepRetryCount(), is(nullValue())); } @@ -778,10 +770,10 @@ public void testMoveClusterStateToFailedStepWithUnknownStep() { lifecycleState.setStep(errorStepKey.name()); lifecycleState.setStepTime(now); lifecycleState.setFailedStep(failedStepKey.name()); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), List.of(policyMetadata)); + ProjectMetadata project = buildProject(indexName, indexSettingsBuilder, lifecycleState.build(), List.of(policyMetadata)); IllegalArgumentException exception = expectThrows( IllegalArgumentException.class, - () -> IndexLifecycleTransition.moveClusterStateToPreviouslyFailedStep(clusterState, indexName, () -> now, policyRegistry, false) + () -> IndexLifecycleTransition.moveIndexToPreviouslyFailedStep(project, indexName, () -> now, policyRegistry, false) ); assertThat( exception.getMessage(), @@ -792,15 +784,10 @@ public void testMoveClusterStateToFailedStepWithUnknownStep() { public void testMoveClusterStateToFailedStepIndexNotFound() { String existingIndexName = "my_index"; String invalidIndexName = "does_not_exist"; - ClusterState clusterState = buildClusterState( - existingIndexName, - Settings.builder(), - LifecycleExecutionState.builder().build(), - List.of() - ); + ProjectMetadata project = buildProject(existingIndexName, Settings.builder(), LifecycleExecutionState.builder().build(), List.of()); IllegalArgumentException exception = expectThrows( IllegalArgumentException.class, - () -> IndexLifecycleTransition.moveClusterStateToPreviouslyFailedStep(clusterState, invalidIndexName, () -> 0L, null, false) + () -> IndexLifecycleTransition.moveIndexToPreviouslyFailedStep(project, invalidIndexName, () -> 0L, null, false) ); assertThat(exception.getMessage(), equalTo("index [" + invalidIndexName + "] does not exist")); } @@ -819,10 +806,10 @@ public void testMoveClusterStateToFailedStepInvalidPolicySetting() { lifecycleState.setAction(errorStepKey.action()); lifecycleState.setStep(errorStepKey.name()); lifecycleState.setFailedStep(failedStepKey.name()); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), List.of()); + ProjectMetadata project = buildProject(indexName, indexSettingsBuilder, lifecycleState.build(), List.of()); IllegalArgumentException exception = expectThrows( IllegalArgumentException.class, - () -> IndexLifecycleTransition.moveClusterStateToPreviouslyFailedStep(clusterState, indexName, () -> now, policyRegistry, false) + () -> IndexLifecycleTransition.moveIndexToPreviouslyFailedStep(project, indexName, () -> now, policyRegistry, false) ); assertThat(exception.getMessage(), equalTo("index [" + indexName + "] is not associated with an Index Lifecycle Policy")); } @@ -839,10 +826,10 @@ public void testMoveClusterStateToFailedNotOnError() { lifecycleState.setPhase(failedStepKey.phase()); lifecycleState.setAction(failedStepKey.action()); lifecycleState.setStep(failedStepKey.name()); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), List.of()); + ProjectMetadata project = buildProject(indexName, indexSettingsBuilder, lifecycleState.build(), List.of()); IllegalArgumentException exception = expectThrows( IllegalArgumentException.class, - () -> IndexLifecycleTransition.moveClusterStateToPreviouslyFailedStep(clusterState, indexName, () -> now, policyRegistry, false) + () -> IndexLifecycleTransition.moveIndexToPreviouslyFailedStep(project, indexName, () -> now, policyRegistry, false) ); assertThat( exception.getMessage(), @@ -852,7 +839,7 @@ public void testMoveClusterStateToFailedNotOnError() { ); } - public void testMoveClusterStateToPreviouslyFailedStepAsAutomaticRetryAndSetsPreviousStepInfo() { + public void testMoveIndexToPreviouslyFailedStepAsAutomaticRetryAndSetsPreviousStepInfo() { String indexName = "my_index"; String policyName = "my_policy"; long now = randomNonNegativeLong(); @@ -879,17 +866,17 @@ public void testMoveClusterStateToPreviouslyFailedStepAsAutomaticRetryAndSetsPre lifecycleState.setFailedStep(failedStepKey.name()); String initialStepInfo = randomAlphaOfLengthBetween(10, 50); lifecycleState.setStepInfo(initialStepInfo); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), List.of(policyMetadata)); - Index index = clusterState.metadata().getProject().index(indexName).getIndex(); - ClusterState nextClusterState = IndexLifecycleTransition.moveClusterStateToPreviouslyFailedStep( - clusterState, + ProjectMetadata project = buildProject(indexName, indexSettingsBuilder, lifecycleState.build(), List.of(policyMetadata)); + Index index = project.index(indexName).getIndex(); + ProjectMetadata newProject = IndexLifecycleTransition.moveIndexToPreviouslyFailedStep( + project, indexName, () -> now, policyRegistry, true ); - IndexLifecycleRunnerTests.assertClusterStateOnNextStep(clusterState, index, errorStepKey, failedStepKey, nextClusterState, now); - LifecycleExecutionState executionState = nextClusterState.metadata().getProject().index(indexName).getLifecycleExecutionState(); + assertClusterStateOnNextStep(project, index, errorStepKey, failedStepKey, newProject, now); + LifecycleExecutionState executionState = newProject.index(indexName).getLifecycleExecutionState(); assertThat(executionState.failedStepRetryCount(), is(1)); assertThat(executionState.previousStepInfo(), is(initialStepInfo)); } @@ -936,24 +923,21 @@ public void testMoveToFailedStepDoesntRefreshCachedPhaseWhenUnsafe() { Step.StepKey errorStepKey = new Step.StepKey("hot", RolloverAction.NAME, ErrorStep.NAME); PolicyStepsRegistry stepsRegistry = createOneStepPolicyStepRegistry("my-policy", new ErrorStep(errorStepKey)); - ClusterState clusterState = buildClusterState( + ProjectMetadata project = buildProject( indexName, Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, "my-policy"), currentExecutionState.build(), policyMetadatas ); - ClusterState newState = IndexLifecycleTransition.moveClusterStateToPreviouslyFailedStep( - clusterState, + ProjectMetadata newProject = IndexLifecycleTransition.moveIndexToPreviouslyFailedStep( + project, indexName, ESTestCase::randomNonNegativeLong, stepsRegistry, false ); - LifecycleExecutionState nextLifecycleExecutionState = newState.metadata() - .getProject() - .index(indexName) - .getLifecycleExecutionState(); + LifecycleExecutionState nextLifecycleExecutionState = newProject.index(indexName).getLifecycleExecutionState(); assertThat( "we musn't refresh the cache definition if the failed step is not part of the real policy anymore", nextLifecycleExecutionState.phaseDefinition(), @@ -1245,17 +1229,6 @@ private static LifecyclePolicy createPolicy(String policyName, Step.StepKey safe return newTestLifecyclePolicy(policyName, phases); } - private ClusterState buildClusterState( - String indexName, - Settings.Builder indexSettingsBuilder, - LifecycleExecutionState lifecycleState, - List lifecyclePolicyMetadatas - ) { - return ClusterState.builder(ClusterName.DEFAULT) - .putProjectMetadata(buildProject(indexName, indexSettingsBuilder, lifecycleState, lifecyclePolicyMetadatas)) - .build(); - } - private ProjectMetadata buildProject( String indexName, Settings.Builder indexSettingsBuilder, @@ -1275,19 +1248,14 @@ private ProjectMetadata buildProject( .collect(Collectors.toMap(LifecyclePolicyMetadata::getName, Function.identity())); IndexLifecycleMetadata indexLifecycleMetadata = new IndexLifecycleMetadata(lifecyclePolicyMetadatasMap, OperationMode.RUNNING); - @FixForMultiProject // Use non-default ID when the remainder of IndexLifecycleTransition is project-aware. - final var projectId = ProjectId.DEFAULT; - return ProjectMetadata.builder(projectId) + return ProjectMetadata.builder(randomProjectIdOrDefault()) .put(indexMetadata, true) .putCustom(IndexLifecycleMetadata.TYPE, indexLifecycleMetadata) .build(); } - public static void assertIndexNotManagedByILM(ClusterState clusterState, Index index) { - Metadata metadata = clusterState.metadata(); - assertNotNull(metadata); - - IndexMetadata indexMetadata = metadata.getProject().getIndexSafe(index); + public static void assertIndexNotManagedByILM(ProjectMetadata project, Index index) { + IndexMetadata indexMetadata = project.getIndexSafe(index); assertNotNull(indexMetadata); assertNull(indexMetadata.getLifecyclePolicyName()); @@ -1349,21 +1317,19 @@ private IndexMetadata buildIndexMetadata(String policy, LifecycleExecutionState. .build(); } - private void assertClusterStateOnErrorStep( - ClusterState oldClusterState, + private static void assertProjectOnErrorStep( + ProjectMetadata oldProject, Index index, Step.StepKey currentStep, - ClusterState newClusterState, + ProjectMetadata newProject, long now, String expectedCauseValue ) { - assertNotSame(oldClusterState, newClusterState); - Metadata newMetadata = newClusterState.metadata(); - assertNotSame(oldClusterState.metadata(), newMetadata); - IndexMetadata newIndexMetadata = newMetadata.getProject().getIndexSafe(index); - assertNotSame(oldClusterState.metadata().getProject().index(index), newIndexMetadata); - LifecycleExecutionState newLifecycleState = newClusterState.metadata().getProject().index(index).getLifecycleExecutionState(); - LifecycleExecutionState oldLifecycleState = oldClusterState.metadata().getProject().index(index).getLifecycleExecutionState(); + assertNotSame(oldProject, newProject); + IndexMetadata newIndexMetadata = newProject.getIndexSafe(index); + assertNotSame(oldProject.index(index), newIndexMetadata); + LifecycleExecutionState newLifecycleState = newProject.index(index).getLifecycleExecutionState(); + LifecycleExecutionState oldLifecycleState = oldProject.index(index).getLifecycleExecutionState(); assertNotSame(oldLifecycleState, newLifecycleState); assertEquals(currentStep.phase(), newLifecycleState.phase()); assertEquals(currentStep.action(), newLifecycleState.action()); @@ -1375,23 +1341,21 @@ private void assertClusterStateOnErrorStep( assertEquals(now, newLifecycleState.stepTime().longValue()); } - private void assertClusterStateStepInfo( - ClusterState oldClusterState, + private static void assertProjectStepInfo( + ProjectMetadata oldProject, Index index, Step.StepKey currentStep, - ClusterState newClusterState, + ProjectMetadata newProject, ToXContentObject stepInfo ) throws IOException { XContentBuilder stepInfoXContentBuilder = JsonXContent.contentBuilder(); stepInfo.toXContent(stepInfoXContentBuilder, ToXContent.EMPTY_PARAMS); String expectedstepInfoValue = BytesReference.bytes(stepInfoXContentBuilder).utf8ToString(); - assertNotSame(oldClusterState, newClusterState); - Metadata newMetadata = newClusterState.metadata(); - assertNotSame(oldClusterState.metadata(), newMetadata); - IndexMetadata newIndexMetadata = newMetadata.getProject().getIndexSafe(index); - assertNotSame(oldClusterState.metadata().getProject().index(index), newIndexMetadata); - LifecycleExecutionState newLifecycleState = newClusterState.metadata().getProject().index(index).getLifecycleExecutionState(); - LifecycleExecutionState oldLifecycleState = oldClusterState.metadata().getProject().index(index).getLifecycleExecutionState(); + assertNotSame(oldProject, newProject); + IndexMetadata newIndexMetadata = newProject.getIndexSafe(index); + assertNotSame(oldProject.index(index), newIndexMetadata); + LifecycleExecutionState newLifecycleState = newProject.index(index).getLifecycleExecutionState(); + LifecycleExecutionState oldLifecycleState = oldProject.index(index).getLifecycleExecutionState(); assertNotSame(oldLifecycleState, newLifecycleState); assertEquals(currentStep.phase(), newLifecycleState.phase()); assertEquals(currentStep.action(), newLifecycleState.action()); @@ -1401,4 +1365,35 @@ private void assertClusterStateStepInfo( assertEquals(oldLifecycleState.actionTime(), newLifecycleState.actionTime()); assertEquals(oldLifecycleState.stepTime(), newLifecycleState.stepTime()); } + + static void assertClusterStateOnNextStep( + ProjectMetadata oldProject, + Index index, + Step.StepKey currentStep, + Step.StepKey nextStep, + ProjectMetadata newProject, + long now + ) { + IndexMetadata newIndexMetadata = newProject.getIndexSafe(index); + assertNotSame(oldProject.index(index), newIndexMetadata); + LifecycleExecutionState newLifecycleState = newProject.index(index).getLifecycleExecutionState(); + LifecycleExecutionState oldLifecycleState = oldProject.index(index).getLifecycleExecutionState(); + assertNotSame(oldLifecycleState, newLifecycleState); + assertEquals(nextStep.phase(), newLifecycleState.phase()); + assertEquals(nextStep.action(), newLifecycleState.action()); + assertEquals(nextStep.name(), newLifecycleState.step()); + if (currentStep.phase().equals(nextStep.phase())) { + assertEquals(oldLifecycleState.phaseTime(), newLifecycleState.phaseTime()); + } else { + assertEquals(now, newLifecycleState.phaseTime().longValue()); + } + if (currentStep.action().equals(nextStep.action())) { + assertEquals(oldLifecycleState.actionTime(), newLifecycleState.actionTime()); + } else { + assertEquals(now, newLifecycleState.actionTime().longValue()); + } + assertEquals(now, newLifecycleState.stepTime().longValue()); + assertEquals(null, newLifecycleState.failedStep()); + assertEquals(null, newLifecycleState.stepInfo()); + } } diff --git a/x-pack/plugin/migrate/src/main/java/org/elasticsearch/system_indices/task/MigrationResultsUpdateTask.java b/x-pack/plugin/migrate/src/main/java/org/elasticsearch/system_indices/task/MigrationResultsUpdateTask.java index 43bbe2a5aa74b..80060ec4908f1 100644 --- a/x-pack/plugin/migrate/src/main/java/org/elasticsearch/system_indices/task/MigrationResultsUpdateTask.java +++ b/x-pack/plugin/migrate/src/main/java/org/elasticsearch/system_indices/task/MigrationResultsUpdateTask.java @@ -12,7 +12,6 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateUpdateTask; -import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.core.SuppressForbidden; @@ -70,14 +69,13 @@ private static void submitUnbatchedTask( @Override public ClusterState execute(ClusterState currentState) throws Exception { - FeatureMigrationResults currentResults = currentState.metadata().getProject().custom(FeatureMigrationResults.TYPE); + final var project = currentState.metadata().getProject(); + FeatureMigrationResults currentResults = project.custom(FeatureMigrationResults.TYPE); if (currentResults == null) { currentResults = new FeatureMigrationResults(new HashMap<>()); } FeatureMigrationResults newResults = currentResults.withResult(featureName, status); - final Metadata newMetadata = Metadata.builder(currentState.metadata()).putCustom(FeatureMigrationResults.TYPE, newResults).build(); - final ClusterState newState = ClusterState.builder(currentState).metadata(newMetadata).build(); - return newState; + return currentState.copyAndUpdateProject(project.id(), builder -> builder.putCustom(FeatureMigrationResults.TYPE, newResults)); } @Override diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteTrainedModelAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteTrainedModelAction.java index e5aedac14b08b..7ad733aa7443e 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteTrainedModelAction.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteTrainedModelAction.java @@ -22,7 +22,6 @@ import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; -import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.util.concurrent.EsExecutors; import org.elasticsearch.core.SuppressForbidden; @@ -228,7 +227,6 @@ private void deleteAliasesAndModel( submitUnbatchedTask("delete-trained-model-alias", new AckedClusterStateUpdateTask(request, nameDeletionListener) { @Override public ClusterState execute(final ClusterState currentState) { - final ClusterState.Builder builder = ClusterState.builder(currentState); final ModelAliasMetadata currentMetadata = ModelAliasMetadata.fromState(currentState); if (currentMetadata.modelAliases().isEmpty()) { return currentState; @@ -237,10 +235,8 @@ public ClusterState execute(final ClusterState currentState) { logger.info("[{}] delete model model_aliases {}", request.getId(), modelAliases); modelAliases.forEach(newMetadata::remove); final ModelAliasMetadata modelAliasMetadata = new ModelAliasMetadata(newMetadata); - builder.metadata( - Metadata.builder(currentState.getMetadata()).putCustom(ModelAliasMetadata.NAME, modelAliasMetadata).build() - ); - return builder.build(); + final var project = currentState.metadata().getProject(); + return currentState.copyAndUpdateProject(project.id(), b -> b.putCustom(ModelAliasMetadata.NAME, modelAliasMetadata)); } }); } diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteTrainedModelAliasAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteTrainedModelAliasAction.java index f2dbe43cd70e1..2b8baa9075ced 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteTrainedModelAliasAction.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportDeleteTrainedModelAliasAction.java @@ -19,7 +19,6 @@ import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; -import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.util.concurrent.EsExecutors; import org.elasticsearch.core.SuppressForbidden; @@ -108,7 +107,8 @@ static ClusterState deleteModelAlias( request.getModelId() ); } - IngestMetadata currentIngestMetadata = currentState.metadata().getProject().custom(IngestMetadata.TYPE); + final var project = currentState.metadata().getProject(); + IngestMetadata currentIngestMetadata = project.custom(IngestMetadata.TYPE); Set referencedModels = InferenceProcessorInfoExtractor.getModelIdsFromInferenceProcessors(currentIngestMetadata); if (referencedModels.contains(request.getModelAlias())) { throw new ElasticsearchStatusException( @@ -117,15 +117,13 @@ static ClusterState deleteModelAlias( request.getModelAlias() ); } - final ClusterState.Builder builder = ClusterState.builder(currentState); final Map newMetadata = new HashMap<>(currentMetadata.modelAliases()); logger.info("deleting model_alias [{}] that refers to model [{}]", request.getModelAlias(), request.getModelId()); inferenceAuditor.info(referencedModel, String.format(Locale.ROOT, "deleting model_alias [%s]", request.getModelAlias())); newMetadata.remove(request.getModelAlias()); final ModelAliasMetadata modelAliasMetadata = new ModelAliasMetadata(newMetadata); - builder.metadata(Metadata.builder(currentState.getMetadata()).putCustom(ModelAliasMetadata.NAME, modelAliasMetadata).build()); - return builder.build(); + return currentState.copyAndUpdateProject(project.id(), builder -> builder.putCustom(ModelAliasMetadata.NAME, modelAliasMetadata)); } @Override diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportPutTrainedModelAliasAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportPutTrainedModelAliasAction.java index f24c77f3d59a8..33b17ca46a240 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportPutTrainedModelAliasAction.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportPutTrainedModelAliasAction.java @@ -18,7 +18,6 @@ import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; -import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.logging.HeaderWarning; import org.elasticsearch.common.util.concurrent.EsExecutors; @@ -257,7 +256,6 @@ private void submitUnbatchedTask(@SuppressWarnings("SameParameterValue") String } static ClusterState updateModelAlias(final ClusterState currentState, final PutTrainedModelAliasAction.Request request) { - final ClusterState.Builder builder = ClusterState.builder(currentState); final ModelAliasMetadata currentMetadata = ModelAliasMetadata.fromState(currentState); String currentModelId = currentMetadata.getModelId(request.getModelAlias()); final Map newMetadata = new HashMap<>(currentMetadata.modelAliases()); @@ -273,8 +271,8 @@ static ClusterState updateModelAlias(final ClusterState currentState, final PutT } newMetadata.put(request.getModelAlias(), new ModelAliasMetadata.ModelAliasEntry(request.getModelId())); final ModelAliasMetadata modelAliasMetadata = new ModelAliasMetadata(newMetadata); - builder.metadata(Metadata.builder(currentState.getMetadata()).putCustom(ModelAliasMetadata.NAME, modelAliasMetadata).build()); - return builder.build(); + final var project = currentState.metadata().getProject(); + return currentState.copyAndUpdateProject(project.id(), builder -> builder.putCustom(ModelAliasMetadata.NAME, modelAliasMetadata)); } @Override diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportSetUpgradeModeAction.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportSetUpgradeModeAction.java index a937d310a47f1..b6defef18c8c3 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportSetUpgradeModeAction.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportSetUpgradeModeAction.java @@ -87,11 +87,10 @@ protected boolean upgradeMode(ClusterState state) { @Override protected ClusterState createUpdatedState(SetUpgradeModeActionRequest request, ClusterState currentState) { logger.trace("Executing cluster state update"); - MlMetadata.Builder builder = new MlMetadata.Builder(currentState.metadata().getProject().custom(MlMetadata.TYPE)); + final var project = currentState.metadata().getProject(); + MlMetadata.Builder builder = new MlMetadata.Builder(project.custom(MlMetadata.TYPE)); builder.isUpgradeMode(request.enabled()); - ClusterState.Builder newState = ClusterState.builder(currentState); - newState.metadata(Metadata.builder(currentState.getMetadata()).putCustom(MlMetadata.TYPE, builder.build()).build()); - return newState.build(); + return currentState.copyAndUpdateProject(project.id(), b -> b.putCustom(MlMetadata.TYPE, builder.build())); } protected void upgradeModeSuccessfullyChanged( diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/assignment/TrainedModelAssignmentClusterService.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/assignment/TrainedModelAssignmentClusterService.java index fd1557cd7310d..ae6a8934c3d62 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/assignment/TrainedModelAssignmentClusterService.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/assignment/TrainedModelAssignmentClusterService.java @@ -21,8 +21,8 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateListener; import org.elasticsearch.cluster.ClusterStateUpdateTask; -import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.cluster.metadata.NodesShutdownMetadata; +import org.elasticsearch.cluster.metadata.ProjectMetadata; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.service.ClusterService; @@ -523,14 +523,14 @@ private static ClusterState update(ClusterState currentState, TrainedModelAssign private static ClusterState forceUpdate(ClusterState currentState, TrainedModelAssignmentMetadata.Builder modelAssignments) { logger.debug(() -> format("updated assignments: %s", modelAssignments.build())); - Metadata.Builder metadata = Metadata.builder(currentState.metadata()); + ProjectMetadata.Builder builder = ProjectMetadata.builder(currentState.metadata().getProject()); if (currentState.getMinTransportVersion().onOrAfter(RENAME_ALLOCATION_TO_ASSIGNMENT_TRANSPORT_VERSION)) { - metadata.putCustom(TrainedModelAssignmentMetadata.NAME, modelAssignments.build()) - .removeProjectCustom(TrainedModelAssignmentMetadata.DEPRECATED_NAME); + builder.putCustom(TrainedModelAssignmentMetadata.NAME, modelAssignments.build()) + .removeCustom(TrainedModelAssignmentMetadata.DEPRECATED_NAME); } else { - metadata.putCustom(TrainedModelAssignmentMetadata.DEPRECATED_NAME, modelAssignments.buildOld()); + builder.putCustom(TrainedModelAssignmentMetadata.DEPRECATED_NAME, modelAssignments.buildOld()); } - return ClusterState.builder(currentState).metadata(metadata).build(); + return ClusterState.builder(currentState).putProjectMetadata(builder).build(); } ClusterState createModelAssignment(ClusterState currentState, CreateTrainedModelAssignmentAction.Request request) throws Exception { diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/persistence/TrainedModelCacheMetadataService.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/persistence/TrainedModelCacheMetadataService.java index bd7510a09a013..65420c6c15073 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/persistence/TrainedModelCacheMetadataService.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/persistence/TrainedModelCacheMetadataService.java @@ -17,7 +17,7 @@ import org.elasticsearch.cluster.ClusterStateTaskExecutor; import org.elasticsearch.cluster.ClusterStateTaskExecutor.TaskContext; import org.elasticsearch.cluster.ClusterStateTaskListener; -import org.elasticsearch.cluster.metadata.Metadata; +import org.elasticsearch.cluster.metadata.ProjectMetadata; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.MasterServiceTaskQueue; import org.elasticsearch.common.Priority; @@ -124,7 +124,10 @@ public ClusterState execute(BatchExecutionContext batch } return ClusterState.builder(initialState) - .metadata(Metadata.builder(initialState.metadata()).putCustom(TrainedModelCacheMetadata.NAME, currentCacheMetadata)) + .putProjectMetadata( + ProjectMetadata.builder(initialState.metadata().getProject()) + .putCustom(TrainedModelCacheMetadata.NAME, currentCacheMetadata) + ) .build(); } } diff --git a/x-pack/plugin/slm/src/main/java/org/elasticsearch/xpack/slm/SnapshotLifecycleTask.java b/x-pack/plugin/slm/src/main/java/org/elasticsearch/xpack/slm/SnapshotLifecycleTask.java index b2a68bc8603b2..eb7c9c1b8794e 100644 --- a/x-pack/plugin/slm/src/main/java/org/elasticsearch/xpack/slm/SnapshotLifecycleTask.java +++ b/x-pack/plugin/slm/src/main/java/org/elasticsearch/xpack/slm/SnapshotLifecycleTask.java @@ -17,7 +17,6 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.SnapshotsInProgress; -import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Strings; import org.elasticsearch.common.scheduler.SchedulerEngine; @@ -271,12 +270,9 @@ static WriteJobStatus failure(String policyId, SnapshotId snapshotId, long times @Override public ClusterState execute(ClusterState currentState) throws Exception { - SnapshotLifecycleMetadata snapMeta = currentState.metadata() - .getProject() - .custom(SnapshotLifecycleMetadata.TYPE, SnapshotLifecycleMetadata.EMPTY); - RegisteredPolicySnapshots registeredSnapshots = currentState.metadata() - .getProject() - .custom(RegisteredPolicySnapshots.TYPE, RegisteredPolicySnapshots.EMPTY); + final var project = currentState.metadata().getProject(); + SnapshotLifecycleMetadata snapMeta = project.custom(SnapshotLifecycleMetadata.TYPE, SnapshotLifecycleMetadata.EMPTY); + RegisteredPolicySnapshots registeredSnapshots = project.custom(RegisteredPolicySnapshots.TYPE, RegisteredPolicySnapshots.EMPTY); Map snapLifecycles = new HashMap<>(snapMeta.getSnapshotConfigurations()); SnapshotLifecyclePolicyMetadata policyMetadata = snapLifecycles.get(policyName); @@ -349,11 +345,11 @@ public ClusterState execute(ClusterState currentState) throws Exception { currentSLMMode(currentState), newStats ); - Metadata newMeta = Metadata.builder(currentState.metadata()) - .putCustom(SnapshotLifecycleMetadata.TYPE, lifecycleMetadata) - .putCustom(RegisteredPolicySnapshots.TYPE, new RegisteredPolicySnapshots(newRegistered)) - .build(); - return ClusterState.builder(currentState).metadata(newMeta).build(); + return currentState.copyAndUpdateProject( + project.id(), + builder -> builder.putCustom(SnapshotLifecycleMetadata.TYPE, lifecycleMetadata) + .putCustom(RegisteredPolicySnapshots.TYPE, new RegisteredPolicySnapshots(newRegistered)) + ); } @Override diff --git a/x-pack/plugin/slm/src/main/java/org/elasticsearch/xpack/slm/UpdateSnapshotLifecycleStatsTask.java b/x-pack/plugin/slm/src/main/java/org/elasticsearch/xpack/slm/UpdateSnapshotLifecycleStatsTask.java index ee341eed12c35..d23b0cdc0fe23 100644 --- a/x-pack/plugin/slm/src/main/java/org/elasticsearch/xpack/slm/UpdateSnapshotLifecycleStatsTask.java +++ b/x-pack/plugin/slm/src/main/java/org/elasticsearch/xpack/slm/UpdateSnapshotLifecycleStatsTask.java @@ -37,7 +37,8 @@ public class UpdateSnapshotLifecycleStatsTask extends ClusterStateUpdateTask { @Override public ClusterState execute(ClusterState currentState) { final Metadata currentMeta = currentState.metadata(); - final SnapshotLifecycleMetadata currentSlmMeta = currentMeta.getProject().custom(SnapshotLifecycleMetadata.TYPE); + final var project = currentMeta.getProject(); + final SnapshotLifecycleMetadata currentSlmMeta = project.custom(SnapshotLifecycleMetadata.TYPE); if (currentSlmMeta == null) { return currentState; @@ -50,9 +51,7 @@ public ClusterState execute(ClusterState currentState) { newMetrics ); - return ClusterState.builder(currentState) - .metadata(Metadata.builder(currentMeta).putCustom(SnapshotLifecycleMetadata.TYPE, newSlmMeta)) - .build(); + return currentState.copyAndUpdateProject(project.id(), builder -> builder.putCustom(SnapshotLifecycleMetadata.TYPE, newSlmMeta)); } @Override diff --git a/x-pack/plugin/slm/src/main/java/org/elasticsearch/xpack/slm/action/TransportDeleteSnapshotLifecycleAction.java b/x-pack/plugin/slm/src/main/java/org/elasticsearch/xpack/slm/action/TransportDeleteSnapshotLifecycleAction.java index ee2810d23eeb4..1462117c91123 100644 --- a/x-pack/plugin/slm/src/main/java/org/elasticsearch/xpack/slm/action/TransportDeleteSnapshotLifecycleAction.java +++ b/x-pack/plugin/slm/src/main/java/org/elasticsearch/xpack/slm/action/TransportDeleteSnapshotLifecycleAction.java @@ -17,7 +17,6 @@ import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; -import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.util.concurrent.EsExecutors; import org.elasticsearch.core.SuppressForbidden; @@ -82,7 +81,8 @@ public static class DeleteSnapshotPolicyTask extends AckedClusterStateUpdateTask @Override public ClusterState execute(ClusterState currentState) { - SnapshotLifecycleMetadata snapMeta = currentState.metadata().getProject().custom(SnapshotLifecycleMetadata.TYPE); + final var project = currentState.metadata().getProject(); + SnapshotLifecycleMetadata snapMeta = project.custom(SnapshotLifecycleMetadata.TYPE); if (snapMeta == null) { throw new ResourceNotFoundException("snapshot lifecycle policy not found: {}", request.getLifecycleId()); } @@ -101,20 +101,13 @@ public ClusterState execute(ClusterState currentState) { .filter(e -> e.getKey().equals(request.getLifecycleId()) == false) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - Metadata metadata = currentState.metadata(); - return ClusterState.builder(currentState) - .metadata( - Metadata.builder(metadata) - .putCustom( - SnapshotLifecycleMetadata.TYPE, - new SnapshotLifecycleMetadata( - newConfigs, - currentMode, - snapMeta.getStats().removePolicy(request.getLifecycleId()) - ) - ) + return currentState.copyAndUpdateProject( + project.id(), + builder -> builder.putCustom( + SnapshotLifecycleMetadata.TYPE, + new SnapshotLifecycleMetadata(newConfigs, currentMode, snapMeta.getStats().removePolicy(request.getLifecycleId())) ) - .build(); + ); } } diff --git a/x-pack/plugin/slm/src/main/java/org/elasticsearch/xpack/slm/action/TransportPutSnapshotLifecycleAction.java b/x-pack/plugin/slm/src/main/java/org/elasticsearch/xpack/slm/action/TransportPutSnapshotLifecycleAction.java index 3631a9c1efdde..a66373e6e9d6c 100644 --- a/x-pack/plugin/slm/src/main/java/org/elasticsearch/xpack/slm/action/TransportPutSnapshotLifecycleAction.java +++ b/x-pack/plugin/slm/src/main/java/org/elasticsearch/xpack/slm/action/TransportPutSnapshotLifecycleAction.java @@ -18,7 +18,6 @@ import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; -import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.util.concurrent.EsExecutors; import org.elasticsearch.core.Nullable; @@ -121,9 +120,8 @@ public static class UpdateSnapshotPolicyTask extends AckedClusterStateUpdateTask @Override public ClusterState execute(ClusterState currentState) { - SnapshotLifecycleMetadata snapMeta = currentState.metadata() - .getProject() - .custom(SnapshotLifecycleMetadata.TYPE, SnapshotLifecycleMetadata.EMPTY); + final var project = currentState.metadata().getProject(); + SnapshotLifecycleMetadata snapMeta = project.custom(SnapshotLifecycleMetadata.TYPE, SnapshotLifecycleMetadata.EMPTY); var currentMode = LifecycleOperationMetadata.currentSLMMode(currentState); final SnapshotLifecyclePolicyMetadata existingPolicyMetadata = snapMeta.getSnapshotConfigurations() .get(request.getLifecycleId()); @@ -149,15 +147,8 @@ public ClusterState execute(ClusterState currentState) { logger.info("updating existing snapshot lifecycle [{}]", newLifecycle.getId()); } - return ClusterState.builder(currentState) - .metadata( - Metadata.builder(currentState.metadata()) - .putCustom( - SnapshotLifecycleMetadata.TYPE, - new SnapshotLifecycleMetadata(snapLifecycles, currentMode, snapMeta.getStats()) - ) - ) - .build(); + final var updatedMetadata = new SnapshotLifecycleMetadata(snapLifecycles, currentMode, snapMeta.getStats()); + return currentState.copyAndUpdateProject(project.id(), b -> b.putCustom(SnapshotLifecycleMetadata.TYPE, updatedMetadata)); } } diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml index 4cb86e8e01a0e..3aa39f6983249 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml @@ -228,7 +228,7 @@ setup: - gt: {esql.functions.to_long: $functions_to_long} - match: {esql.functions.coalesce: $functions_coalesce} - gt: {esql.functions.categorize: $functions_categorize} - - length: {esql.functions: 144} # check the "sister" test above for a likely update to the same esql.functions length check + - length: {esql.functions: 145} # check the "sister" test above for a likely update to the same esql.functions length check --- took: diff --git a/x-pack/plugin/transform/src/main/java/org/elasticsearch/xpack/transform/action/TransportSetTransformUpgradeModeAction.java b/x-pack/plugin/transform/src/main/java/org/elasticsearch/xpack/transform/action/TransportSetTransformUpgradeModeAction.java index d5f30353f308e..98e5907bce3cf 100644 --- a/x-pack/plugin/transform/src/main/java/org/elasticsearch/xpack/transform/action/TransportSetTransformUpgradeModeAction.java +++ b/x-pack/plugin/transform/src/main/java/org/elasticsearch/xpack/transform/action/TransportSetTransformUpgradeModeAction.java @@ -77,8 +77,10 @@ protected boolean upgradeMode(ClusterState state) { @Override protected ClusterState createUpdatedState(SetUpgradeModeActionRequest request, ClusterState state) { var updatedTransformMetadata = TransformMetadata.getTransformMetadata(state).builder().upgradeMode(request.enabled()).build(); - var updatedClusterMetadata = state.metadata().copyAndUpdate(b -> b.putCustom(TransformMetadata.TYPE, updatedTransformMetadata)); - return state.copyAndUpdate(b -> b.metadata(updatedClusterMetadata)); + return state.copyAndUpdateProject( + state.metadata().getProject().id(), + b -> b.putCustom(TransformMetadata.TYPE, updatedTransformMetadata) + ); } @Override diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/transport/actions/TransportWatcherServiceAction.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/transport/actions/TransportWatcherServiceAction.java index 616821a8f3ddf..57eb0f9197ce5 100644 --- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/transport/actions/TransportWatcherServiceAction.java +++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/transport/actions/TransportWatcherServiceAction.java @@ -18,7 +18,6 @@ import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; -import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.core.SuppressForbidden; import org.elasticsearch.injection.guice.Inject; @@ -74,15 +73,14 @@ public ClusterState execute(ClusterState clusterState) { XPackPlugin.checkReadyForXPackCustomMetadata(clusterState); WatcherMetadata newWatcherMetadata = new WatcherMetadata(manuallyStopped); - WatcherMetadata currentMetadata = clusterState.metadata().getProject().custom(WatcherMetadata.TYPE); + final var project = clusterState.metadata().getProject(); + WatcherMetadata currentMetadata = project.custom(WatcherMetadata.TYPE); // adhere to the contract of returning the original state if nothing has changed if (newWatcherMetadata.equals(currentMetadata)) { return clusterState; } else { - ClusterState.Builder builder = new ClusterState.Builder(clusterState); - builder.metadata(Metadata.builder(clusterState.getMetadata()).putCustom(WatcherMetadata.TYPE, newWatcherMetadata)); - return builder.build(); + return clusterState.copyAndUpdateProject(project.id(), b -> b.putCustom(WatcherMetadata.TYPE, newWatcherMetadata)); } } From 71e94216044875d5e97da9cbcbb22e38b2ac710a Mon Sep 17 00:00:00 2001 From: Lorenzo Dematte Date: Tue, 10 Jun 2025 12:07:38 +0200 Subject: [PATCH 08/16] remove exclude --- qa/rolling-upgrade/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qa/rolling-upgrade/build.gradle b/qa/rolling-upgrade/build.gradle index f253d9a056920..9f5dd79298c2f 100644 --- a/qa/rolling-upgrade/build.gradle +++ b/qa/rolling-upgrade/build.gradle @@ -35,7 +35,7 @@ tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { filter { // TODO (ES-12010) investigate these test failures excludeTestsMatching("org.elasticsearch.upgrades.FeatureUpgradeIT") - excludeTestsMatching("org.elasticsearch.upgrades.LogsUsageRollingUpgradeIT") + //excludeTestsMatching("org.elasticsearch.upgrades.LogsUsageRollingUpgradeIT") excludeTestsMatching("org.elasticsearch.upgrades.SnapshotBasedRecoveryIT") } } From 148ceb2ad8ef72fd68514b1a70dc2d323e5364ff Mon Sep 17 00:00:00 2001 From: Lorenzo Dematte Date: Tue, 10 Jun 2025 14:57:33 +0200 Subject: [PATCH 09/16] fix tests to not try and parse versions (unsupported for BWC and serverless) --- ...rameterizedFullClusterRestartTestCase.java | 6 ++- .../AbstractRollingUpgradeTestCase.java | 5 +-- ...actRollingUpgradeWithSecurityTestCase.java | 5 +-- .../upgrades/DenseVectorMappingUpdateIT.java | 2 +- .../upgrades/FileSettingsUpgradeIT.java | 5 +-- .../upgrades/LogsUsageRollingUpgradeIT.java | 2 +- .../ParameterizedRollingUpgradeTestCase.java | 15 +++---- .../upgrades/SourceModeRollingUpgradeIT.java | 4 +- .../upgrades/VectorSearchIT.java | 43 +++++++------------ .../AzureOpenAiServiceUpgradeIT.java | 9 ++-- .../application/CohereServiceUpgradeIT.java | 19 ++++---- .../HuggingFaceServiceUpgradeIT.java | 18 ++++---- .../application/InferenceUpgradeTestCase.java | 4 +- .../application/OpenAiServiceUpgradeIT.java | 27 ++++++------ 14 files changed, 75 insertions(+), 89 deletions(-) diff --git a/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedFullClusterRestartTestCase.java b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedFullClusterRestartTestCase.java index 7518a799540b8..5c83fee97cdca 100644 --- a/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedFullClusterRestartTestCase.java +++ b/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedFullClusterRestartTestCase.java @@ -134,7 +134,11 @@ public boolean isRunningAgainstOldCluster() { return requestedUpgradeStatus == OLD; } - public static String getOldClusterVersion() { + /** + * The version of the "old" (initial) cluster. It is an opaque string, do not even think about parsing it for version + * comparison. Use (test) cluster features and {@link ParameterizedFullClusterRestartTestCase#oldClusterHasFeature} instead. + */ + protected static String getOldClusterVersion() { return System.getProperty("tests.bwc.main.version", OLD_CLUSTER_VERSION); } diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/AbstractRollingUpgradeTestCase.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/AbstractRollingUpgradeTestCase.java index 99db4c2677559..35b3819a76a18 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/AbstractRollingUpgradeTestCase.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/AbstractRollingUpgradeTestCase.java @@ -30,10 +30,9 @@ public abstract class AbstractRollingUpgradeTestCase extends ParameterizedRollin private static final ElasticsearchCluster cluster = buildCluster(); private static ElasticsearchCluster buildCluster() { - Version oldVersion = Version.fromString(OLD_CLUSTER_VERSION); var cluster = ElasticsearchCluster.local() .distribution(DistributionType.DEFAULT) - .version(getOldClusterTestVersion()) + .version(getOldClusterVersion()) .nodes(NODE_NUM) .setting("path.repo", new Supplier<>() { @Override @@ -47,7 +46,7 @@ public String get() { // Avoid triggering bogus assertion when serialized parsed mappings don't match with original mappings, because _source key is // inconsistent - if (oldVersion.before(Version.fromString("8.18.0"))) { + if (Version.fromString(getOldClusterVersion()).before(Version.fromString("8.18.0"))) { cluster.jvmArg("-da:org.elasticsearch.index.mapper.DocumentMapper"); cluster.jvmArg("-da:org.elasticsearch.index.mapper.MapperService"); } diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/AbstractRollingUpgradeWithSecurityTestCase.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/AbstractRollingUpgradeWithSecurityTestCase.java index 9f74573ca83fb..25d9b26ceb10f 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/AbstractRollingUpgradeWithSecurityTestCase.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/AbstractRollingUpgradeWithSecurityTestCase.java @@ -35,10 +35,9 @@ public abstract class AbstractRollingUpgradeWithSecurityTestCase extends Paramet private static final ElasticsearchCluster cluster = buildCluster(); private static ElasticsearchCluster buildCluster() { - Version oldVersion = Version.fromString(OLD_CLUSTER_VERSION); var cluster = ElasticsearchCluster.local() .distribution(DistributionType.DEFAULT) - .version(getOldClusterTestVersion()) + .version(getOldClusterVersion()) .nodes(NODE_NUM) .user(USER, PASS) .setting("xpack.security.autoconfiguration.enabled", "false") @@ -52,7 +51,7 @@ public String get() { // Avoid triggering bogus assertion when serialized parsed mappings don't match with original mappings, because _source key is // inconsistent - if (oldVersion.before(Version.fromString("8.18.0"))) { + if (Version.fromString(getOldClusterVersion()).before(Version.fromString("8.18.0"))) { cluster.jvmArg("-da:org.elasticsearch.index.mapper.DocumentMapper"); cluster.jvmArg("-da:org.elasticsearch.index.mapper.MapperService"); } diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/DenseVectorMappingUpdateIT.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/DenseVectorMappingUpdateIT.java index b8fc3b15636fb..dff0e94193054 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/DenseVectorMappingUpdateIT.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/DenseVectorMappingUpdateIT.java @@ -82,7 +82,7 @@ public DenseVectorMappingUpdateIT(@Name("upgradedNodes") int upgradedNodes) { } public void testDenseVectorMappingUpdateOnOldCluster() throws IOException { - if (getOldClusterTestVersion().after(Version.V_8_7_0.toString())) { + if (oldClusterHasFeature("gte_v8.7.1")) { String indexName = "test_index"; if (isOldCluster()) { Request createIndex = new Request("PUT", "/" + indexName); diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/FileSettingsUpgradeIT.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/FileSettingsUpgradeIT.java index 0f48fb65b41f3..eb03f58ae1900 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/FileSettingsUpgradeIT.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/FileSettingsUpgradeIT.java @@ -17,7 +17,6 @@ import org.elasticsearch.test.cluster.ElasticsearchCluster; import org.elasticsearch.test.cluster.FeatureFlag; import org.elasticsearch.test.cluster.local.distribution.DistributionType; -import org.elasticsearch.test.cluster.util.Version; import org.elasticsearch.test.cluster.util.resource.Resource; import org.elasticsearch.test.junit.RunnableTestRuleAdapter; import org.junit.ClassRule; @@ -34,7 +33,7 @@ public class FileSettingsUpgradeIT extends ParameterizedRollingUpgradeTestCase { private static final RunnableTestRuleAdapter versionLimit = new RunnableTestRuleAdapter( - () -> assumeTrue("Only valid when upgrading from pre-file settings", getOldClusterTestVersion().before(new Version(8, 4, 0))) + () -> assumeFalse("Only valid when upgrading from pre-file settings", oldClusterHasFeature("gte_v8.4.0")) ); private static final String settingsJSON = """ @@ -54,7 +53,7 @@ public class FileSettingsUpgradeIT extends ParameterizedRollingUpgradeTestCase { private static final ElasticsearchCluster cluster = ElasticsearchCluster.local() .distribution(DistributionType.DEFAULT) - .version(getOldClusterTestVersion()) + .version(getOldClusterVersion()) .nodes(NODE_NUM) .setting("path.repo", new Supplier<>() { @Override diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/LogsUsageRollingUpgradeIT.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/LogsUsageRollingUpgradeIT.java index b72060a34489e..6fea6917bebc0 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/LogsUsageRollingUpgradeIT.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/LogsUsageRollingUpgradeIT.java @@ -30,7 +30,7 @@ public LogsUsageRollingUpgradeIT(@Name("upgradedNodes") int upgradedNodes) { } public void testUsage() throws Exception { - assumeTrue("logsdb.prior_logs_usage only gets set in 8.x", getOldClusterTestVersion().before("9.0.0")); + assumeFalse("logsdb.prior_logs_usage only gets set in 8.x", oldClusterHasFeature("gte_v9.0.0")); String dataStreamName = "logs-mysql-error"; if (isOldCluster()) { bulkIndex(dataStreamName, 4, 256, Instant.now()); diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedRollingUpgradeTestCase.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedRollingUpgradeTestCase.java index 00adf18bba6e9..e6db9fb5da27f 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedRollingUpgradeTestCase.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedRollingUpgradeTestCase.java @@ -36,7 +36,7 @@ public abstract class ParameterizedRollingUpgradeTestCase extends ESRestTestCase { protected static final int NODE_NUM = 3; - protected static final String OLD_CLUSTER_VERSION = System.getProperty("tests.old_cluster_version"); + private static final String OLD_CLUSTER_VERSION = System.getProperty("tests.old_cluster_version"); private static final Set upgradedNodes = new HashSet<>(); private static TestFeatureService oldClusterTestFeatureService = null; private static boolean upgradeFailed = false; @@ -127,11 +127,6 @@ public static void resetNodes() { upgradeFailed = false; } - @Deprecated // Use the new testing framework and oldClusterHasFeature(feature) instead - protected static String getOldClusterVersion() { - return OLD_CLUSTER_VERSION; - } - protected static boolean oldClusterHasFeature(String featureId) { assert oldClusterTestFeatureService != null; return oldClusterTestFeatureService.clusterHasFeature(featureId); @@ -146,8 +141,12 @@ protected static IndexVersion getOldClusterIndexVersion() { return oldIndexVersion; } - protected static Version getOldClusterTestVersion() { - return Version.fromString(OLD_CLUSTER_VERSION); + /** + * The version of the "old" (initial) cluster. It is an opaque string, do not even think about parsing it for version + * comparison. Use (test) cluster features and {@link ParameterizedRollingUpgradeTestCase#oldClusterHasFeature} instead. + */ + protected static String getOldClusterVersion() { + return System.getProperty("tests.bwc.main.version", OLD_CLUSTER_VERSION); } protected static boolean isOldClusterVersion(String nodeVersion) { diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/SourceModeRollingUpgradeIT.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/SourceModeRollingUpgradeIT.java index 55a03da7c9e90..b512835b8201d 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/SourceModeRollingUpgradeIT.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/SourceModeRollingUpgradeIT.java @@ -27,7 +27,7 @@ public SourceModeRollingUpgradeIT(@Name("upgradedNodes") int upgradedNodes) { } public void testConfigureStoredSourceBeforeIndexCreationLegacy() throws IOException { - assumeTrue("testing deprecation warnings and deprecation migrations", getOldClusterTestVersion().before("9.0.0")); + assumeFalse("testing deprecation warnings and deprecation migrations", oldClusterHasFeature("gte_v9.0.0")); String templateName = "logs@custom"; if (isOldCluster()) { var storedSourceMapping = """ @@ -56,7 +56,7 @@ public void testConfigureStoredSourceBeforeIndexCreationLegacy() throws IOExcept } public void testConfigureStoredSourceWhenIndexIsCreatedLegacy() throws IOException { - assumeTrue("testing deprecation warnings and deprecation migrations", getOldClusterTestVersion().before("9.0.0")); + assumeFalse("testing deprecation warnings and deprecation migrations", oldClusterHasFeature("gte_v9.0.0")); String templateName = "logs@custom"; if (isOldCluster()) { var storedSourceMapping = """ diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/VectorSearchIT.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/VectorSearchIT.java index 07034618be4a6..53492e65412eb 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/VectorSearchIT.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/VectorSearchIT.java @@ -37,14 +37,16 @@ public VectorSearchIT(@Name("upgradedNodes") int upgradedNodes) { private static final String BBQ_INDEX_NAME = "bbq_vector_index"; private static final String FLAT_QUANTIZED_INDEX_NAME = "flat_quantized_vector_index"; private static final String FLAT_BBQ_INDEX_NAME = "flat_bbq_vector_index"; - private static final String FLOAT_VECTOR_SEARCH_VERSION = "8.4.0"; - private static final String BYTE_VECTOR_SEARCH_VERSION = "8.6.0"; - private static final String QUANTIZED_VECTOR_SEARCH_VERSION = "8.12.1"; - private static final String FLAT_QUANTIZED_VECTOR_SEARCH_VERSION = "8.13.0"; - private static final String BBQ_VECTOR_SEARCH_VERSION = "8.18.0"; + + // TODO: replace these with proper test features + private static final String FLOAT_VECTOR_SEARCH_TEST_FEATURE = "gte_v8.4.0"; + private static final String BYTE_VECTOR_SEARCH_TEST_FEATURE = "gte_v8.6.0"; + private static final String QUANTIZED_VECTOR_SEARCH_TEST_FEATURE = "gte_v8.12.1"; + private static final String FLAT_QUANTIZED_VECTOR_SEARCH_TEST_FEATURE = "gte_v8.13.0"; + private static final String BBQ_VECTOR_SEARCH_TEST_FEATURE = "gte_v.18.0"; public void testScriptByteVectorSearch() throws Exception { - assumeTrue("byte vector search is not supported on this version", getOldClusterTestVersion().onOrAfter(BYTE_VECTOR_SEARCH_VERSION)); + assumeTrue("byte vector search is not supported on this version", oldClusterHasFeature(BYTE_VECTOR_SEARCH_TEST_FEATURE)); if (isOldCluster()) { // create index and index 10 random floating point vectors String mapping = """ @@ -91,10 +93,7 @@ public void testScriptByteVectorSearch() throws Exception { } public void testScriptVectorSearch() throws Exception { - assumeTrue( - "Float vector search is not supported on this version", - getOldClusterTestVersion().onOrAfter(FLOAT_VECTOR_SEARCH_VERSION) - ); + assumeTrue("Float vector search is not supported on this version", oldClusterHasFeature(FLOAT_VECTOR_SEARCH_TEST_FEATURE)); if (isOldCluster()) { // create index and index 10 random floating point vectors String mapping = """ @@ -140,10 +139,7 @@ public void testScriptVectorSearch() throws Exception { } public void testFloatVectorSearch() throws Exception { - assumeTrue( - "Float vector search is not supported on this version", - getOldClusterTestVersion().onOrAfter(FLOAT_VECTOR_SEARCH_VERSION) - ); + assumeTrue("Float vector search is not supported on this version", oldClusterHasFeature(FLOAT_VECTOR_SEARCH_TEST_FEATURE)); if (isOldCluster()) { String mapping = """ { @@ -215,7 +211,7 @@ public void testFloatVectorSearch() throws Exception { } public void testByteVectorSearch() throws Exception { - assumeTrue("Byte vector search is not supported on this version", getOldClusterTestVersion().onOrAfter(BYTE_VECTOR_SEARCH_VERSION)); + assumeTrue("Byte vector search is not supported on this version", oldClusterHasFeature(BYTE_VECTOR_SEARCH_TEST_FEATURE)); if (isOldCluster()) { String mapping = """ { @@ -288,10 +284,7 @@ public void testByteVectorSearch() throws Exception { } public void testQuantizedVectorSearch() throws Exception { - assumeTrue( - "Quantized vector search is not supported on this version", - getOldClusterTestVersion().onOrAfter(QUANTIZED_VECTOR_SEARCH_VERSION) - ); + assumeTrue("Quantized vector search is not supported on this version", oldClusterHasFeature(QUANTIZED_VECTOR_SEARCH_TEST_FEATURE)); if (isOldCluster()) { String mapping = """ { @@ -364,7 +357,7 @@ public void testQuantizedVectorSearch() throws Exception { public void testFlatQuantizedVectorSearch() throws Exception { assumeTrue( "Quantized vector search is not supported on this version", - getOldClusterTestVersion().onOrAfter(FLAT_QUANTIZED_VECTOR_SEARCH_VERSION) + oldClusterHasFeature(FLAT_QUANTIZED_VECTOR_SEARCH_TEST_FEATURE) ); if (isOldCluster()) { String mapping = """ @@ -434,10 +427,7 @@ public void testFlatQuantizedVectorSearch() throws Exception { } public void testBBQVectorSearch() throws Exception { - assumeTrue( - "Quantized vector search is not supported on this version", - getOldClusterTestVersion().onOrAfter(BBQ_VECTOR_SEARCH_VERSION) - ); + assumeTrue("Quantized vector search is not supported on this version", oldClusterHasFeature(BBQ_VECTOR_SEARCH_TEST_FEATURE)); if (isOldCluster()) { String mapping = """ { @@ -518,10 +508,7 @@ public void testBBQVectorSearch() throws Exception { } public void testFlatBBQVectorSearch() throws Exception { - assumeTrue( - "Quantized vector search is not supported on this version", - getOldClusterTestVersion().onOrAfter(BBQ_VECTOR_SEARCH_VERSION) - ); + assumeTrue("Quantized vector search is not supported on this version", oldClusterHasFeature(BBQ_VECTOR_SEARCH_TEST_FEATURE)); if (isOldCluster()) { String mapping = """ { diff --git a/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/AzureOpenAiServiceUpgradeIT.java b/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/AzureOpenAiServiceUpgradeIT.java index f0196834b9175..82ebc755bdca5 100644 --- a/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/AzureOpenAiServiceUpgradeIT.java +++ b/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/AzureOpenAiServiceUpgradeIT.java @@ -26,7 +26,7 @@ public class AzureOpenAiServiceUpgradeIT extends InferenceUpgradeTestCase { - private static final String OPEN_AI_AZURE_EMBEDDINGS_ADDED = "8.14.0"; + private static final String OPEN_AI_AZURE_EMBEDDINGS_ADDED_FEATURE = "gte_v8.14.0"; private static MockWebServer openAiEmbeddingsServer; @@ -48,10 +48,9 @@ public static void shutdown() { @SuppressWarnings("unchecked") @AwaitsFix(bugUrl = "Cannot set the URL in the tests") public void testOpenAiEmbeddings() throws IOException { - var openAiEmbeddingsSupported = getOldClusterTestVersion().onOrAfter(OPEN_AI_AZURE_EMBEDDINGS_ADDED); - // `gte_v` indicates that the cluster version is Greater Than or Equal to MODELS_RENAMED_TO_ENDPOINTS - String oldClusterEndpointIdentifier = oldClusterHasFeature("gte_v" + MODELS_RENAMED_TO_ENDPOINTS) ? "endpoints" : "models"; - assumeTrue("Azure OpenAI embedding service added in " + OPEN_AI_AZURE_EMBEDDINGS_ADDED, openAiEmbeddingsSupported); + var openAiEmbeddingsSupported = oldClusterHasFeature(OPEN_AI_AZURE_EMBEDDINGS_ADDED_FEATURE); + String oldClusterEndpointIdentifier = oldClusterHasFeature(MODELS_RENAMED_TO_ENDPOINTS_FEATURE) ? "endpoints" : "models"; + assumeTrue("Azure OpenAI embedding service supported", openAiEmbeddingsSupported); final String oldClusterId = "old-cluster-embeddings"; final String upgradedClusterId = "upgraded-cluster-embeddings"; diff --git a/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/CohereServiceUpgradeIT.java b/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/CohereServiceUpgradeIT.java index 0acbc148515bd..7851a093a95cb 100644 --- a/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/CohereServiceUpgradeIT.java +++ b/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/CohereServiceUpgradeIT.java @@ -33,9 +33,9 @@ public class CohereServiceUpgradeIT extends InferenceUpgradeTestCase { - private static final String COHERE_EMBEDDINGS_ADDED = "8.13.0"; - private static final String COHERE_RERANK_ADDED = "8.14.0"; - private static final String BYTE_ALIAS_FOR_INT8_ADDED = "8.14.0"; + // TODO: replace with proper test features + private static final String COHERE_EMBEDDINGS_ADDED_TEST_FEATURE = "gte_v8.13.0"; + private static final String COHERE_RERANK_ADDED_TEST_FEATURE = "gte_v8.14.0"; private static MockWebServer cohereEmbeddingsServer; private static MockWebServer cohereRerankServer; @@ -61,10 +61,9 @@ public static void shutdown() { @SuppressWarnings("unchecked") public void testCohereEmbeddings() throws IOException { - var embeddingsSupported = getOldClusterTestVersion().onOrAfter(COHERE_EMBEDDINGS_ADDED); - // `gte_v` indicates that the cluster version is Greater Than or Equal to MODELS_RENAMED_TO_ENDPOINTS - String oldClusterEndpointIdentifier = oldClusterHasFeature("gte_v" + MODELS_RENAMED_TO_ENDPOINTS) ? "endpoints" : "models"; - assumeTrue("Cohere embedding service added in " + COHERE_EMBEDDINGS_ADDED, embeddingsSupported); + var embeddingsSupported = oldClusterHasFeature(COHERE_EMBEDDINGS_ADDED_TEST_FEATURE); + String oldClusterEndpointIdentifier = oldClusterHasFeature(MODELS_RENAMED_TO_ENDPOINTS_FEATURE) ? "endpoints" : "models"; + assumeTrue("Cohere embedding service supported", embeddingsSupported); final String oldClusterIdInt8 = "old-cluster-embeddings-int8"; final String oldClusterIdFloat = "old-cluster-embeddings-float"; @@ -191,9 +190,9 @@ void assertEmbeddingInference(String inferenceId, CohereEmbeddingType type) thro @SuppressWarnings("unchecked") public void testRerank() throws IOException { - var rerankSupported = getOldClusterTestVersion().onOrAfter(COHERE_RERANK_ADDED); - String old_cluster_endpoint_identifier = oldClusterHasFeature("gte_v" + MODELS_RENAMED_TO_ENDPOINTS) ? "endpoints" : "models"; - assumeTrue("Cohere rerank service added in " + COHERE_RERANK_ADDED, rerankSupported); + var rerankSupported = oldClusterHasFeature(COHERE_RERANK_ADDED_TEST_FEATURE); + String old_cluster_endpoint_identifier = oldClusterHasFeature(MODELS_RENAMED_TO_ENDPOINTS_FEATURE) ? "endpoints" : "models"; + assumeTrue("Cohere rerank service supported", rerankSupported); final String oldClusterId = "old-cluster-rerank"; final String upgradedClusterId = "upgraded-cluster-rerank"; diff --git a/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/HuggingFaceServiceUpgradeIT.java b/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/HuggingFaceServiceUpgradeIT.java index 61556e02e5cd2..41e67d7f39859 100644 --- a/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/HuggingFaceServiceUpgradeIT.java +++ b/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/HuggingFaceServiceUpgradeIT.java @@ -29,8 +29,9 @@ public class HuggingFaceServiceUpgradeIT extends InferenceUpgradeTestCase { - private static final String HF_EMBEDDINGS_ADDED = "8.12.0"; - private static final String HF_ELSER_ADDED = "8.12.0"; + // TODO: replace with proper test features + private static final String HF_EMBEDDINGS_TEST_FEATURE = "gte_v8.12.0"; + private static final String HF_ELSER_TEST_FEATURE = "gte_v8.12.0"; private static MockWebServer embeddingsServer; private static MockWebServer elserServer; @@ -56,10 +57,9 @@ public static void shutdown() { @SuppressWarnings("unchecked") public void testHFEmbeddings() throws IOException { - var embeddingsSupported = getOldClusterTestVersion().onOrAfter(HF_EMBEDDINGS_ADDED); - // `gte_v` indicates that the cluster version is Greater Than or Equal to MODELS_RENAMED_TO_ENDPOINTS - String oldClusterEndpointIdentifier = oldClusterHasFeature("gte_v" + MODELS_RENAMED_TO_ENDPOINTS) ? "endpoints" : "models"; - assumeTrue("Hugging Face embedding service added in " + HF_EMBEDDINGS_ADDED, embeddingsSupported); + var embeddingsSupported = oldClusterHasFeature(HF_EMBEDDINGS_TEST_FEATURE); + String oldClusterEndpointIdentifier = oldClusterHasFeature(MODELS_RENAMED_TO_ENDPOINTS_FEATURE) ? "endpoints" : "models"; + assumeTrue("Hugging Face embedding service supported", embeddingsSupported); final String oldClusterId = "old-cluster-embeddings"; final String upgradedClusterId = "upgraded-cluster-embeddings"; @@ -110,9 +110,9 @@ void assertEmbeddingInference(String inferenceId) throws IOException { @SuppressWarnings("unchecked") public void testElser() throws IOException { - var supported = getOldClusterTestVersion().onOrAfter(HF_ELSER_ADDED); - String old_cluster_endpoint_identifier = oldClusterHasFeature("gte_v" + MODELS_RENAMED_TO_ENDPOINTS) ? "endpoints" : "models"; - assumeTrue("HF elser service added in " + HF_ELSER_ADDED, supported); + var supported = oldClusterHasFeature(HF_ELSER_TEST_FEATURE); + String old_cluster_endpoint_identifier = oldClusterHasFeature(MODELS_RENAMED_TO_ENDPOINTS_FEATURE) ? "endpoints" : "models"; + assumeTrue("HF elser service supported", supported); final String oldClusterId = "old-cluster-elser"; final String upgradedClusterId = "upgraded-cluster-elser"; diff --git a/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/InferenceUpgradeTestCase.java b/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/InferenceUpgradeTestCase.java index bdbaedf532817..64b82eb936935 100644 --- a/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/InferenceUpgradeTestCase.java +++ b/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/InferenceUpgradeTestCase.java @@ -29,7 +29,7 @@ public class InferenceUpgradeTestCase extends ParameterizedRollingUpgradeTestCase { - static final String MODELS_RENAMED_TO_ENDPOINTS = "8.15.0"; + static final String MODELS_RENAMED_TO_ENDPOINTS_FEATURE = "gte_v8.15.0"; public InferenceUpgradeTestCase(@Name("upgradedNodes") int upgradedNodes) { super(upgradedNodes); @@ -38,7 +38,7 @@ public InferenceUpgradeTestCase(@Name("upgradedNodes") int upgradedNodes) { @ClassRule public static ElasticsearchCluster cluster = ElasticsearchCluster.local() .distribution(DistributionType.DEFAULT) - .version(getOldClusterTestVersion()) + .version(getOldClusterVersion()) .nodes(NODE_NUM) .setting("xpack.security.enabled", "false") .setting("xpack.license.self_generated.type", "trial") diff --git a/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/OpenAiServiceUpgradeIT.java b/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/OpenAiServiceUpgradeIT.java index b6dcfcb84a77f..0f6ac361dadf2 100644 --- a/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/OpenAiServiceUpgradeIT.java +++ b/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/OpenAiServiceUpgradeIT.java @@ -31,9 +31,10 @@ public class OpenAiServiceUpgradeIT extends InferenceUpgradeTestCase { - private static final String OPEN_AI_EMBEDDINGS_ADDED = "8.12.0"; - private static final String OPEN_AI_EMBEDDINGS_MODEL_SETTING_MOVED = "8.13.0"; - private static final String OPEN_AI_COMPLETIONS_ADDED = "8.14.0"; + // TODO: replace with proper test features + private static final String OPEN_AI_EMBEDDINGS_TEST_FEATURE = "gte_v8.12.0"; + private static final String OPEN_AI_EMBEDDINGS_MODEL_SETTING_MOVED_TEST_FEATURE = "gte_v8.13.0"; + private static final String OPEN_AI_COMPLETIONS_TEST_FEATURE = "gte_v8.14.0"; private static MockWebServer openAiEmbeddingsServer; private static MockWebServer openAiChatCompletionsServer; @@ -59,10 +60,9 @@ public static void shutdown() { @SuppressWarnings("unchecked") public void testOpenAiEmbeddings() throws IOException { - var openAiEmbeddingsSupported = getOldClusterTestVersion().onOrAfter(OPEN_AI_EMBEDDINGS_ADDED); - // `gte_v` indicates that the cluster version is Greater Than or Equal to MODELS_RENAMED_TO_ENDPOINTS - String oldClusterEndpointIdentifier = oldClusterHasFeature("gte_v" + MODELS_RENAMED_TO_ENDPOINTS) ? "endpoints" : "models"; - assumeTrue("OpenAI embedding service added in " + OPEN_AI_EMBEDDINGS_ADDED, openAiEmbeddingsSupported); + var openAiEmbeddingsSupported = oldClusterHasFeature(OPEN_AI_EMBEDDINGS_TEST_FEATURE); + String oldClusterEndpointIdentifier = oldClusterHasFeature(MODELS_RENAMED_TO_ENDPOINTS_FEATURE) ? "endpoints" : "models"; + assumeTrue("OpenAI embedding service supported", openAiEmbeddingsSupported); final String oldClusterId = "old-cluster-embeddings"; final String upgradedClusterId = "upgraded-cluster-embeddings"; @@ -86,7 +86,8 @@ public void testOpenAiEmbeddings() throws IOException { var serviceSettings = (Map) configs.get(0).get("service_settings"); var taskSettings = (Map) configs.get(0).get("task_settings"); var modelIdFound = serviceSettings.containsKey("model_id") - || (taskSettings.containsKey("model") && getOldClusterTestVersion().onOrBefore(OPEN_AI_EMBEDDINGS_MODEL_SETTING_MOVED)); + || (taskSettings.containsKey("model") + && (oldClusterHasFeature(OPEN_AI_EMBEDDINGS_MODEL_SETTING_MOVED_TEST_FEATURE) == false)); assertTrue("model_id not found in config: " + configs, modelIdFound); assertEmbeddingInference(oldClusterId); @@ -124,9 +125,9 @@ void assertEmbeddingInference(String inferenceId) throws IOException { @SuppressWarnings("unchecked") public void testOpenAiCompletions() throws IOException { - var openAiEmbeddingsSupported = getOldClusterTestVersion().onOrAfter(OPEN_AI_COMPLETIONS_ADDED); - String old_cluster_endpoint_identifier = oldClusterHasFeature("gte_v" + MODELS_RENAMED_TO_ENDPOINTS) ? "endpoints" : "models"; - assumeTrue("OpenAI completions service added in " + OPEN_AI_COMPLETIONS_ADDED, openAiEmbeddingsSupported); + var openAiEmbeddingsSupported = oldClusterHasFeature(OPEN_AI_COMPLETIONS_TEST_FEATURE); + String old_cluster_endpoint_identifier = oldClusterHasFeature(MODELS_RENAMED_TO_ENDPOINTS_FEATURE) ? "endpoints" : "models"; + assumeTrue("OpenAI completions service supported" + OPEN_AI_COMPLETIONS_TEST_FEATURE, openAiEmbeddingsSupported); final String oldClusterId = "old-cluster-completions"; final String upgradedClusterId = "upgraded-cluster-completions"; @@ -145,7 +146,7 @@ public void testOpenAiCompletions() throws IOException { List> configs = new LinkedList<>(); var request = get(testTaskType, oldClusterId); configs.addAll((Collection>) request.getOrDefault("endpoints", List.of())); - if (oldClusterHasFeature("gte_v" + MODELS_RENAMED_TO_ENDPOINTS) == false) { + if (oldClusterHasFeature(MODELS_RENAMED_TO_ENDPOINTS_FEATURE) == false) { configs.addAll((List>) request.getOrDefault(old_cluster_endpoint_identifier, List.of())); // in version 8.15, there was a breaking change where "models" was renamed to "endpoints" } @@ -186,7 +187,7 @@ void assertCompletionInference(String inferenceId) throws IOException { } private String oldClusterVersionCompatibleEmbeddingConfig() { - if (getOldClusterTestVersion().before(OPEN_AI_EMBEDDINGS_MODEL_SETTING_MOVED)) { + if (oldClusterHasFeature(OPEN_AI_EMBEDDINGS_MODEL_SETTING_MOVED_TEST_FEATURE) == false) { return embeddingConfigWithModelInTaskSettings(getUrl(openAiEmbeddingsServer)); } else { return embeddingConfigWithModelInServiceSettings(getUrl(openAiEmbeddingsServer)); From d15c8635d32e57c25216972c71bab29bb3bbe2e3 Mon Sep 17 00:00:00 2001 From: Lorenzo Dematte Date: Tue, 10 Jun 2025 14:58:14 +0200 Subject: [PATCH 10/16] do not filter re-worked tests --- qa/rolling-upgrade/build.gradle | 7 ------- 1 file changed, 7 deletions(-) diff --git a/qa/rolling-upgrade/build.gradle b/qa/rolling-upgrade/build.gradle index 9f5dd79298c2f..d0eacd8689ec4 100644 --- a/qa/rolling-upgrade/build.gradle +++ b/qa/rolling-upgrade/build.gradle @@ -31,13 +31,6 @@ tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { usesBwcDistribution(Version.fromString("0.0.0")) systemProperty("tests.old_cluster_version", "0.0.0") onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } - - filter { - // TODO (ES-12010) investigate these test failures - excludeTestsMatching("org.elasticsearch.upgrades.FeatureUpgradeIT") - //excludeTestsMatching("org.elasticsearch.upgrades.LogsUsageRollingUpgradeIT") - excludeTestsMatching("org.elasticsearch.upgrades.SnapshotBasedRecoveryIT") - } } tasks.withType(Test).configureEach { From bc017b533b44516c87c049d7b6bc7748c4686013 Mon Sep 17 00:00:00 2001 From: Lorenzo Dematte Date: Tue, 10 Jun 2025 15:46:40 +0200 Subject: [PATCH 11/16] revert FileSettingsUpgradeIT change --- .../org/elasticsearch/upgrades/FileSettingsUpgradeIT.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/FileSettingsUpgradeIT.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/FileSettingsUpgradeIT.java index eb03f58ae1900..9a01a8fb22340 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/FileSettingsUpgradeIT.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/FileSettingsUpgradeIT.java @@ -17,6 +17,7 @@ import org.elasticsearch.test.cluster.ElasticsearchCluster; import org.elasticsearch.test.cluster.FeatureFlag; import org.elasticsearch.test.cluster.local.distribution.DistributionType; +import org.elasticsearch.test.cluster.util.Version; import org.elasticsearch.test.cluster.util.resource.Resource; import org.elasticsearch.test.junit.RunnableTestRuleAdapter; import org.junit.ClassRule; @@ -33,7 +34,10 @@ public class FileSettingsUpgradeIT extends ParameterizedRollingUpgradeTestCase { private static final RunnableTestRuleAdapter versionLimit = new RunnableTestRuleAdapter( - () -> assumeFalse("Only valid when upgrading from pre-file settings", oldClusterHasFeature("gte_v8.4.0")) + () -> assumeTrue( + "Only valid when upgrading from pre-file settings", + Version.fromString(getOldClusterVersion()).before(new Version(8, 4, 0)) + ) ); private static final String settingsJSON = """ From 5233b61836116cefba762bd662665292399ae0b4 Mon Sep 17 00:00:00 2001 From: Lorenzo Dematte Date: Tue, 10 Jun 2025 15:47:43 +0200 Subject: [PATCH 12/16] revert FileSettingsUpgradeIT change --- .../java/org/elasticsearch/upgrades/FileSettingsUpgradeIT.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/FileSettingsUpgradeIT.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/FileSettingsUpgradeIT.java index 9a01a8fb22340..2ce800f544ad3 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/FileSettingsUpgradeIT.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/FileSettingsUpgradeIT.java @@ -14,6 +14,7 @@ import org.elasticsearch.client.Request; import org.elasticsearch.common.xcontent.support.XContentMapValues; import org.elasticsearch.core.SuppressForbidden; +import org.elasticsearch.core.UpdateForV10; import org.elasticsearch.test.cluster.ElasticsearchCluster; import org.elasticsearch.test.cluster.FeatureFlag; import org.elasticsearch.test.cluster.local.distribution.DistributionType; @@ -33,6 +34,7 @@ public class FileSettingsUpgradeIT extends ParameterizedRollingUpgradeTestCase { + @UpdateForV10(owner = UpdateForV10.Owner.CORE_INFRA) // Remove this rule entirely private static final RunnableTestRuleAdapter versionLimit = new RunnableTestRuleAdapter( () -> assumeTrue( "Only valid when upgrading from pre-file settings", From f2aab12a585654d2ab46b3ee27229ff74fd09a83 Mon Sep 17 00:00:00 2001 From: Lorenzo Dematte Date: Tue, 10 Jun 2025 16:10:05 +0200 Subject: [PATCH 13/16] extract bc upgrade test registration in script --- .../groovy/elasticsearch.bc-update-test.gradle | 18 ++++++++++++++++++ .../qa/full-cluster-restart/build.gradle | 9 +-------- qa/full-cluster-restart/build.gradle | 8 +------- qa/rolling-upgrade/build.gradle | 8 +------- .../qa/full-cluster-restart/build.gradle | 9 +-------- .../esql/qa/server/mixed-cluster/build.gradle | 8 +------- .../inference/qa/mixed-cluster/build.gradle | 8 +------- .../inference/qa/rolling-upgrade/build.gradle | 9 +-------- .../security/qa/multi-cluster/build.gradle | 8 +------- .../qa/full-cluster-restart/build.gradle | 8 +------- x-pack/qa/full-cluster-restart/build.gradle | 8 +------- 11 files changed, 28 insertions(+), 73 deletions(-) create mode 100644 build-tools-internal/src/main/groovy/elasticsearch.bc-update-test.gradle diff --git a/build-tools-internal/src/main/groovy/elasticsearch.bc-update-test.gradle b/build-tools-internal/src/main/groovy/elasticsearch.bc-update-test.gradle new file mode 100644 index 0000000000000..94702c840c745 --- /dev/null +++ b/build-tools-internal/src/main/groovy/elasticsearch.bc-update-test.gradle @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import org.elasticsearch.gradle.Version +import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask + +tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { + // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property + usesBwcDistribution(Version.fromString("0.0.0")) + systemProperty("tests.old_cluster_version", "0.0.0") + onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } +} diff --git a/modules/ingest-geoip/qa/full-cluster-restart/build.gradle b/modules/ingest-geoip/qa/full-cluster-restart/build.gradle index 0739ab78fa6e1..5f83271ed6242 100644 --- a/modules/ingest-geoip/qa/full-cluster-restart/build.gradle +++ b/modules/ingest-geoip/qa/full-cluster-restart/build.gradle @@ -12,7 +12,7 @@ import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.bwc-test' - +apply plugin: 'elasticsearch.bc-upgrade-test' dependencies { javaRestTestImplementation project(':test:fixtures:geoip-fixture') @@ -25,10 +25,3 @@ buildParams.bwcVersions.withWireCompatible { bwcVersion, baseName -> systemProperty("tests.old_cluster_version", bwcVersion) } } - -tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { - // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property - usesBwcDistribution(Version.fromString("0.0.0")) - systemProperty("tests.old_cluster_version", "0.0.0") - onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } -} diff --git a/qa/full-cluster-restart/build.gradle b/qa/full-cluster-restart/build.gradle index 09c0dbb53a36b..16f7abc183421 100644 --- a/qa/full-cluster-restart/build.gradle +++ b/qa/full-cluster-restart/build.gradle @@ -13,6 +13,7 @@ import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.internal-test-artifact' apply plugin: 'elasticsearch.bwc-test' +apply plugin: 'elasticsearch.bc-upgrade-test' buildParams.bwcVersions.withIndexCompatible { bwcVersion, baseName -> tasks.register(bwcTaskName(bwcVersion), StandaloneRestIntegTestTask) { @@ -28,13 +29,6 @@ tasks.register("luceneBwcTest", StandaloneRestIntegTestTask) { onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } } -tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { - // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property - usesBwcDistribution(Version.fromString("0.0.0")) - systemProperty("tests.old_cluster_version", "0.0.0") - onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } -} - tasks.withType(Test).configureEach { // CI doesn't like it when there's multiple clusters running at once maxParallelForks = 1 diff --git a/qa/rolling-upgrade/build.gradle b/qa/rolling-upgrade/build.gradle index d0eacd8689ec4..aef0ea6cdae0a 100644 --- a/qa/rolling-upgrade/build.gradle +++ b/qa/rolling-upgrade/build.gradle @@ -14,6 +14,7 @@ apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.internal-test-artifact-base' apply plugin: 'elasticsearch.bwc-test' apply plugin: 'elasticsearch.fwc-test' +apply plugin: 'elasticsearch.bc-upgrade-test' testArtifacts { registerTestArtifactFromSourceSet(sourceSets.javaRestTest) @@ -26,13 +27,6 @@ buildParams.bwcVersions.withWireCompatible { bwcVersion, baseName -> } } -tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { - // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property - usesBwcDistribution(Version.fromString("0.0.0")) - systemProperty("tests.old_cluster_version", "0.0.0") - onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } -} - tasks.withType(Test).configureEach { // CI doesn't like it when there's multiple clusters running at once maxParallelForks = 1 diff --git a/x-pack/plugin/ent-search/qa/full-cluster-restart/build.gradle b/x-pack/plugin/ent-search/qa/full-cluster-restart/build.gradle index 0befb8ec5df22..b5e0d2b67b615 100644 --- a/x-pack/plugin/ent-search/qa/full-cluster-restart/build.gradle +++ b/x-pack/plugin/ent-search/qa/full-cluster-restart/build.gradle @@ -10,7 +10,7 @@ import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.bwc-test' - +apply plugin: 'elasticsearch.bc-upgrade-test' dependencies { javaRestTestImplementation(testArtifact(project(xpackModule('core')))) @@ -23,10 +23,3 @@ buildParams.bwcVersions.withWireCompatible(v -> v.after("8.8.0")) { bwcVersion, systemProperty("tests.old_cluster_version", bwcVersion) } } - -tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { - // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property - usesBwcDistribution(Version.fromString("0.0.0")) - systemProperty("tests.old_cluster_version", "0.0.0") - onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } -} diff --git a/x-pack/plugin/esql/qa/server/mixed-cluster/build.gradle b/x-pack/plugin/esql/qa/server/mixed-cluster/build.gradle index 0c8767c4ac295..4f88d4303f108 100644 --- a/x-pack/plugin/esql/qa/server/mixed-cluster/build.gradle +++ b/x-pack/plugin/esql/qa/server/mixed-cluster/build.gradle @@ -14,6 +14,7 @@ apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.internal-yaml-rest-test' apply plugin: 'elasticsearch.internal-test-artifact' apply plugin: 'elasticsearch.bwc-test' +apply plugin: 'elasticsearch.bc-upgrade-test' apply plugin: org.elasticsearch.gradle.internal.precommit.CheckstylePrecommitPlugin apply plugin: org.elasticsearch.gradle.internal.precommit.ForbiddenApisPrecommitPlugin apply plugin: org.elasticsearch.gradle.internal.precommit.ForbiddenPatternsPrecommitPlugin @@ -62,13 +63,6 @@ buildParams.bwcVersions.withWireCompatible(supportedVersion) { bwcVersion, baseN } } -tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { - // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property - usesBwcDistribution(Version.fromString("0.0.0")) - systemProperty("tests.old_cluster_version", "0.0.0") - onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } -} - tasks.named("yamlRestTest") { enabled = false } diff --git a/x-pack/plugin/inference/qa/mixed-cluster/build.gradle b/x-pack/plugin/inference/qa/mixed-cluster/build.gradle index 3c5f5fbdb5b9d..eb775bb096b2e 100644 --- a/x-pack/plugin/inference/qa/mixed-cluster/build.gradle +++ b/x-pack/plugin/inference/qa/mixed-cluster/build.gradle @@ -12,6 +12,7 @@ import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.internal-test-artifact-base' apply plugin: 'elasticsearch.bwc-test' +apply plugin: 'elasticsearch.bc-upgrade-test' dependencies { javaRestTestImplementation(testArtifact(project(xpackModule('core')))) @@ -37,10 +38,3 @@ buildParams.bwcVersions.withWireCompatible(supportedVersion) { bwcVersion, baseN dependsOn javaRestTest } } - -tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { - // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property - usesBwcDistribution(Version.fromString("0.0.0")) - systemProperty("tests.old_cluster_version", "0.0.0") - onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } -} diff --git a/x-pack/plugin/inference/qa/rolling-upgrade/build.gradle b/x-pack/plugin/inference/qa/rolling-upgrade/build.gradle index e656d3b9fd233..9a159475ca6c5 100644 --- a/x-pack/plugin/inference/qa/rolling-upgrade/build.gradle +++ b/x-pack/plugin/inference/qa/rolling-upgrade/build.gradle @@ -11,7 +11,7 @@ import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.internal-test-artifact-base' apply plugin: 'elasticsearch.bwc-test' - +apply plugin: 'elasticsearch.bc-upgrade-test' dependencies { javaRestTestImplementation(testArtifact(project(xpackModule('core')))) @@ -27,10 +27,3 @@ buildParams.bwcVersions.withWireCompatible(v -> v.after("8.11.0")) { bwcVersion, maxParallelForks = 1 } } - -tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { - // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property - usesBwcDistribution(Version.fromString("0.0.0")) - systemProperty("tests.old_cluster_version", "0.0.0") - onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } -} diff --git a/x-pack/plugin/security/qa/multi-cluster/build.gradle b/x-pack/plugin/security/qa/multi-cluster/build.gradle index a2f10f956098f..6371333b7cbb9 100644 --- a/x-pack/plugin/security/qa/multi-cluster/build.gradle +++ b/x-pack/plugin/security/qa/multi-cluster/build.gradle @@ -11,6 +11,7 @@ import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.rest-resources' apply plugin: 'elasticsearch.bwc-test' +apply plugin: 'elasticsearch.bc-upgrade-test' dependencies { javaRestTestImplementation project(':x-pack:plugin:core') @@ -44,10 +45,3 @@ buildParams.bwcVersions.withWireCompatible() { bwcVersion, baseName -> include '**/RemoteClusterSecurityBWCToRCS2ClusterRestIT.class' } } - -tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { - // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property - usesBwcDistribution(Version.fromString("0.0.0")) - systemProperty("tests.old_cluster_version", "0.0.0") - onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } -} diff --git a/x-pack/plugin/shutdown/qa/full-cluster-restart/build.gradle b/x-pack/plugin/shutdown/qa/full-cluster-restart/build.gradle index 306266742d721..580802c8098f4 100644 --- a/x-pack/plugin/shutdown/qa/full-cluster-restart/build.gradle +++ b/x-pack/plugin/shutdown/qa/full-cluster-restart/build.gradle @@ -10,6 +10,7 @@ import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.bwc-test' +apply plugin: 'elasticsearch.bc-upgrade-test' dependencies { // TODO: Remove core dependency and change tests to not use builders that are part of xpack-core. @@ -26,10 +27,3 @@ buildParams.bwcVersions.withIndexCompatible { bwcVersion, baseName -> systemProperty("tests.old_cluster_version", bwcVersion) } } - -tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { - // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property - usesBwcDistribution(Version.fromString("0.0.0")) - systemProperty("tests.old_cluster_version", "0.0.0") - onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } -} diff --git a/x-pack/qa/full-cluster-restart/build.gradle b/x-pack/qa/full-cluster-restart/build.gradle index eeeaa8a370c09..0d186be50c909 100644 --- a/x-pack/qa/full-cluster-restart/build.gradle +++ b/x-pack/qa/full-cluster-restart/build.gradle @@ -10,6 +10,7 @@ import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask apply plugin: 'elasticsearch.internal-java-rest-test' apply plugin: 'elasticsearch.bwc-test' +apply plugin: 'elasticsearch.bc-upgrade-test' dependencies { // TODO: Remove core dependency and change tests to not use builders that are part of xpack-core. @@ -29,10 +30,3 @@ buildParams.bwcVersions.withIndexCompatible { bwcVersion, baseName -> maxParallelForks = 1 } } - -tasks.register("bcUpgradeTest", StandaloneRestIntegTestTask) { - // We use a phony version here as the real version is provided via `tests.bwc.main.version` system property - usesBwcDistribution(Version.fromString("0.0.0")) - systemProperty("tests.old_cluster_version", "0.0.0") - onlyIf("tests.bwc.main.version system property exists") { System.getProperty("tests.bwc.main.version") != null } -} From 39f95066340a7bed8fe11b187711415bd8d7ed23 Mon Sep 17 00:00:00 2001 From: Lorenzo Dematte Date: Tue, 10 Jun 2025 18:21:19 +0200 Subject: [PATCH 14/16] fixes --- ...est.gradle => elasticsearch.bc-upgrade-test.gradle} | 0 .../upgrades/ParameterizedRollingUpgradeTestCase.java | 10 +++++++++- .../upgrades/SnapshotBasedRecoveryIT.java | 3 ++- .../org/elasticsearch/upgrades/VectorSearchIT.java | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) rename build-tools-internal/src/main/groovy/{elasticsearch.bc-update-test.gradle => elasticsearch.bc-upgrade-test.gradle} (100%) diff --git a/build-tools-internal/src/main/groovy/elasticsearch.bc-update-test.gradle b/build-tools-internal/src/main/groovy/elasticsearch.bc-upgrade-test.gradle similarity index 100% rename from build-tools-internal/src/main/groovy/elasticsearch.bc-update-test.gradle rename to build-tools-internal/src/main/groovy/elasticsearch.bc-upgrade-test.gradle diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedRollingUpgradeTestCase.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedRollingUpgradeTestCase.java index e6db9fb5da27f..6704885099036 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedRollingUpgradeTestCase.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedRollingUpgradeTestCase.java @@ -28,6 +28,7 @@ import java.util.HashSet; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.stream.IntStream; @@ -150,7 +151,14 @@ protected static String getOldClusterVersion() { } protected static boolean isOldClusterVersion(String nodeVersion) { - return OLD_CLUSTER_VERSION.equals(nodeVersion); + return getOldClusterVersion().equals(nodeVersion); + } + + protected static boolean isOldClusterVersion(String nodeVersion, String buildHash) { + if (Objects.equals(System.getProperty("tests.bwc.refspec.main"), buildHash)) { + return true; + } + return isOldClusterVersion(nodeVersion); } protected static boolean isOldCluster() { diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/SnapshotBasedRecoveryIT.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/SnapshotBasedRecoveryIT.java index 485e1d4f28826..d3bf4bc946947 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/SnapshotBasedRecoveryIT.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/SnapshotBasedRecoveryIT.java @@ -137,7 +137,8 @@ private List getUpgradedNodeIds() throws IOException { List upgradedNodes = new ArrayList<>(); for (Map.Entry> nodeInfoEntry : nodes.entrySet()) { String nodeVersion = extractValue(nodeInfoEntry.getValue(), "version"); - if (isOldClusterVersion(nodeVersion) == false) { + String nodeBuildHash = extractValue(nodeInfoEntry.getValue(), "build_hash"); + if (isOldClusterVersion(nodeVersion, nodeBuildHash) == false) { upgradedNodes.add(nodeInfoEntry.getKey()); } } diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/VectorSearchIT.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/VectorSearchIT.java index 53492e65412eb..afee17cd82e2d 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/VectorSearchIT.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/VectorSearchIT.java @@ -43,7 +43,7 @@ public VectorSearchIT(@Name("upgradedNodes") int upgradedNodes) { private static final String BYTE_VECTOR_SEARCH_TEST_FEATURE = "gte_v8.6.0"; private static final String QUANTIZED_VECTOR_SEARCH_TEST_FEATURE = "gte_v8.12.1"; private static final String FLAT_QUANTIZED_VECTOR_SEARCH_TEST_FEATURE = "gte_v8.13.0"; - private static final String BBQ_VECTOR_SEARCH_TEST_FEATURE = "gte_v.18.0"; + private static final String BBQ_VECTOR_SEARCH_TEST_FEATURE = "gte_v8.18.0"; public void testScriptByteVectorSearch() throws Exception { assumeTrue("byte vector search is not supported on this version", oldClusterHasFeature(BYTE_VECTOR_SEARCH_TEST_FEATURE)); From 2de14330f4d202e85f6e18efd80681a237dfecb0 Mon Sep 17 00:00:00 2001 From: Lorenzo Dematte Date: Tue, 10 Jun 2025 18:55:33 +0200 Subject: [PATCH 15/16] more fixes --- .buildkite/scripts/run-pr-upgrade-tests.sh | 2 +- .../upgrades/AbstractRollingUpgradeTestCase.java | 2 +- ...stractRollingUpgradeWithSecurityTestCase.java | 4 +++- .../upgrades/FileSettingsUpgradeIT.java | 4 +++- .../ParameterizedRollingUpgradeTestCase.java | 14 +++++--------- .../upgrades/SnapshotBasedRecoveryIT.java | 16 +++++++++++----- .../application/InferenceUpgradeTestCase.java | 4 +++- 7 files changed, 27 insertions(+), 19 deletions(-) diff --git a/.buildkite/scripts/run-pr-upgrade-tests.sh b/.buildkite/scripts/run-pr-upgrade-tests.sh index 1c5e9a345f323..4729364a9a1f6 100644 --- a/.buildkite/scripts/run-pr-upgrade-tests.sh +++ b/.buildkite/scripts/run-pr-upgrade-tests.sh @@ -27,7 +27,7 @@ echo "Running PR upgrade tests from $BUILDKITE_PULL_REQUEST_BASE_BRANCH [$BASE_C cat < $BUILDKITE_BRANCH - command: .ci/scripts/run-gradle.sh -Dbwc.checkout.align=true -Dorg.elasticsearch.build.cache.push=true -Dignore.tests.seed -Dscan.capture-file-fingerprints -Dtests.bwc.main.version=${VERSION}-SNAPSHOT -Dtests.bwc.refspec.main=${BASE_COMMIT} bcUpgradeTest -Dtests.jvm.argline="-Des.serverless_transport=true" + command: .ci/scripts/run-gradle.sh -Dbwc.checkout.align=true -Dorg.elasticsearch.build.cache.push=true -Dignore.tests.seed -Dscan.capture-file-fingerprints -Dtests.bwc.main.version=${VERSION} -Dtests.bwc.refspec.main=${BASE_COMMIT} bcUpgradeTest -Dtests.jvm.argline="-Des.serverless_transport=true" timeout_in_minutes: 300 agents: provider: gcp diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/AbstractRollingUpgradeTestCase.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/AbstractRollingUpgradeTestCase.java index 35b3819a76a18..1b610422d5a2a 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/AbstractRollingUpgradeTestCase.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/AbstractRollingUpgradeTestCase.java @@ -32,7 +32,7 @@ public abstract class AbstractRollingUpgradeTestCase extends ParameterizedRollin private static ElasticsearchCluster buildCluster() { var cluster = ElasticsearchCluster.local() .distribution(DistributionType.DEFAULT) - .version(getOldClusterVersion()) + .version(OLD_CLUSTER_VERSION) .nodes(NODE_NUM) .setting("path.repo", new Supplier<>() { @Override diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/AbstractRollingUpgradeWithSecurityTestCase.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/AbstractRollingUpgradeWithSecurityTestCase.java index 25d9b26ceb10f..31be5bf90e801 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/AbstractRollingUpgradeWithSecurityTestCase.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/AbstractRollingUpgradeWithSecurityTestCase.java @@ -34,10 +34,12 @@ public abstract class AbstractRollingUpgradeWithSecurityTestCase extends Paramet private static final ElasticsearchCluster cluster = buildCluster(); + // Note we need to use OLD_CLUSTER_VERSION directly here, as it may contain special values (e.g. 0.0.0) the ElasticsearchCluster + // builder uses to lookup a particular distribution private static ElasticsearchCluster buildCluster() { var cluster = ElasticsearchCluster.local() .distribution(DistributionType.DEFAULT) - .version(getOldClusterVersion()) + .version(OLD_CLUSTER_VERSION) .nodes(NODE_NUM) .user(USER, PASS) .setting("xpack.security.autoconfiguration.enabled", "false") diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/FileSettingsUpgradeIT.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/FileSettingsUpgradeIT.java index 2ce800f544ad3..140ac67f806af 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/FileSettingsUpgradeIT.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/FileSettingsUpgradeIT.java @@ -57,9 +57,11 @@ public class FileSettingsUpgradeIT extends ParameterizedRollingUpgradeTestCase { private static final TemporaryFolder repoDirectory = new TemporaryFolder(); + // Note we need to use OLD_CLUSTER_VERSION directly here, as it may contain special values (e.g. 0.0.0) the ElasticsearchCluster + // builder uses to lookup a particular distribution private static final ElasticsearchCluster cluster = ElasticsearchCluster.local() .distribution(DistributionType.DEFAULT) - .version(getOldClusterVersion()) + .version(OLD_CLUSTER_VERSION) .nodes(NODE_NUM) .setting("path.repo", new Supplier<>() { @Override diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedRollingUpgradeTestCase.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedRollingUpgradeTestCase.java index 6704885099036..43a9081964483 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedRollingUpgradeTestCase.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedRollingUpgradeTestCase.java @@ -28,7 +28,6 @@ import java.util.HashSet; import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.stream.IntStream; @@ -37,7 +36,7 @@ public abstract class ParameterizedRollingUpgradeTestCase extends ESRestTestCase { protected static final int NODE_NUM = 3; - private static final String OLD_CLUSTER_VERSION = System.getProperty("tests.old_cluster_version"); + protected static final String OLD_CLUSTER_VERSION = System.getProperty("tests.old_cluster_version"); private static final Set upgradedNodes = new HashSet<>(); private static TestFeatureService oldClusterTestFeatureService = null; private static boolean upgradeFailed = false; @@ -150,15 +149,12 @@ protected static String getOldClusterVersion() { return System.getProperty("tests.bwc.main.version", OLD_CLUSTER_VERSION); } - protected static boolean isOldClusterVersion(String nodeVersion) { - return getOldClusterVersion().equals(nodeVersion); - } - protected static boolean isOldClusterVersion(String nodeVersion, String buildHash) { - if (Objects.equals(System.getProperty("tests.bwc.refspec.main"), buildHash)) { - return true; + String bwcRefSpec = System.getProperty("tests.bwc.refspec.main"); + if (bwcRefSpec != null) { + return bwcRefSpec.equals(buildHash); } - return isOldClusterVersion(nodeVersion); + return getOldClusterVersion().equals(nodeVersion); } protected static boolean isOldCluster() { diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/SnapshotBasedRecoveryIT.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/SnapshotBasedRecoveryIT.java index d3bf4bc946947..e6f3f9e67c05b 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/SnapshotBasedRecoveryIT.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/SnapshotBasedRecoveryIT.java @@ -20,6 +20,7 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.support.XContentMapValues; +import org.elasticsearch.core.Tuple; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.repositories.blobstore.BlobStoreRepository; @@ -88,7 +89,7 @@ public void testSnapshotBasedRecovery() throws Exception { } String primaryNodeId = getPrimaryNodeIdOfShard(indexName, 0); - String primaryNodeVersion = getNodeVersion(primaryNodeId); + var primaryNodeVersion = getNodeVersion(primaryNodeId); // Sometimes the primary shard ends on the upgraded node (i.e. after a rebalance) // This causes issues when removing and adding replicas, since then we cannot allocate to any of the old nodes. @@ -96,13 +97,14 @@ public void testSnapshotBasedRecovery() throws Exception { // In that case we exclude the upgraded node from the shard allocation and cancel the shard to force moving // the primary to a node in the old version, this allows adding replicas in the first mixed round. logger.info("--> Primary node in first mixed round {} / {}", primaryNodeId, primaryNodeVersion); - if (isOldClusterVersion(primaryNodeVersion) == false) { + if (isOldClusterVersion(primaryNodeVersion.v1(), primaryNodeVersion.v2()) == false) { logger.info("--> cancelling primary shard on node [{}]", primaryNodeId); cancelShard(indexName, 0, primaryNodeId); logger.info("--> done cancelling primary shard on node [{}]", primaryNodeId); String currentPrimaryNodeId = getPrimaryNodeIdOfShard(indexName, 0); - assertTrue(isOldClusterVersion(getNodeVersion(currentPrimaryNodeId))); + var currentPrimaryNodeVersion = getNodeVersion(currentPrimaryNodeId); + assertTrue(isOldClusterVersion(currentPrimaryNodeVersion.v1(), currentPrimaryNodeVersion.v2())); } } else { logger.info("--> not in first upgrade round, removing exclusions for [{}]", indexName); @@ -145,10 +147,14 @@ private List getUpgradedNodeIds() throws IOException { return upgradedNodes; } - private String getNodeVersion(String primaryNodeId) throws IOException { + private Tuple getNodeVersion(String primaryNodeId) throws IOException { Request request = new Request(HttpGet.METHOD_NAME, "_nodes/" + primaryNodeId); Response response = client().performRequest(request); - return extractValue(responseAsMap(response), "nodes." + primaryNodeId + ".version"); + Map responseAsMap = responseAsMap(response); + return Tuple.tuple( + extractValue(responseAsMap, "nodes." + primaryNodeId + ".version"), + extractValue(responseAsMap, "nodes." + primaryNodeId + ".build_hash") + ); } private String getPrimaryNodeIdOfShard(String indexName, int shard) throws Exception { diff --git a/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/InferenceUpgradeTestCase.java b/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/InferenceUpgradeTestCase.java index 64b82eb936935..7b28c562b13fc 100644 --- a/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/InferenceUpgradeTestCase.java +++ b/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/InferenceUpgradeTestCase.java @@ -35,10 +35,12 @@ public InferenceUpgradeTestCase(@Name("upgradedNodes") int upgradedNodes) { super(upgradedNodes); } + // Note we need to use OLD_CLUSTER_VERSION directly here, as it may contain special values (e.g. 0.0.0) the ElasticsearchCluster + // builder uses to lookup a particular distribution @ClassRule public static ElasticsearchCluster cluster = ElasticsearchCluster.local() .distribution(DistributionType.DEFAULT) - .version(getOldClusterVersion()) + .version(OLD_CLUSTER_VERSION) .nodes(NODE_NUM) .setting("xpack.security.enabled", "false") .setting("xpack.license.self_generated.type", "trial") From 274ff45a8ad7fd438f5bad2200ac43c7097ead00 Mon Sep 17 00:00:00 2001 From: Lorenzo Dematte Date: Thu, 12 Jun 2025 10:52:05 +0200 Subject: [PATCH 16/16] rename --- ...bc-update-test.gradle => elasticsearch.bc-upgrade-test.gradle} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename build-tools-internal/src/main/groovy/{elasticsearch.bc-update-test.gradle => elasticsearch.bc-upgrade-test.gradle} (100%) diff --git a/build-tools-internal/src/main/groovy/elasticsearch.bc-update-test.gradle b/build-tools-internal/src/main/groovy/elasticsearch.bc-upgrade-test.gradle similarity index 100% rename from build-tools-internal/src/main/groovy/elasticsearch.bc-update-test.gradle rename to build-tools-internal/src/main/groovy/elasticsearch.bc-upgrade-test.gradle